Initial import of binutils 2.22 on the new vendor branch
[dragonfly.git] / sys / contrib / dev / acpica-unix / compiler / aslwalks.c
1 /******************************************************************************
2  *
3  * Module Name: aslwalks.c - major analytical parse tree walks
4  *
5  *****************************************************************************/
6
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights.  You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code.  No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision.  In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change.  Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee.  Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution.  In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
86  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88  * PARTICULAR PURPOSE.
89  *
90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97  * LIMITED REMEDY.
98  *
99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
100  * software or system incorporating such software without first obtaining any
101  * required license or other approval from the U. S. Department of Commerce or
102  * any other agency or department of the United States Government.  In the
103  * event Licensee exports any such software from the United States or
104  * re-exports any such software from a foreign destination, Licensee shall
105  * ensure that the distribution and export/re-export of the software is in
106  * compliance with all laws, regulations, orders, or other restrictions of the
107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108  * any of its subsidiaries will export/re-export any technical data, process,
109  * software, or service, directly or indirectly, to any country for which the
110  * United States government or any agency thereof requires an export license,
111  * other governmental approval, or letter of assurance, without first obtaining
112  * such license, approval or letter.
113  *
114  *****************************************************************************/
115
116
117 #include "aslcompiler.h"
118 #include "aslcompiler.y.h"
119 #include "acparser.h"
120 #include "amlcode.h"
121
122
123 #define _COMPONENT          ACPI_COMPILER
124         ACPI_MODULE_NAME    ("aslwalks")
125
126
127 /*******************************************************************************
128  *
129  * FUNCTION:    AnMethodAnalysisWalkBegin
130  *
131  * PARAMETERS:  ASL_WALK_CALLBACK
132  *
133  * RETURN:      Status
134  *
135  * DESCRIPTION: Descending callback for the analysis walk. Check methods for:
136  *              1) Initialized local variables
137  *              2) Valid arguments
138  *              3) Return types
139  *
140  ******************************************************************************/
141
142 ACPI_STATUS
143 AnMethodAnalysisWalkBegin (
144     ACPI_PARSE_OBJECT       *Op,
145     UINT32                  Level,
146     void                    *Context)
147 {
148     ASL_ANALYSIS_WALK_INFO  *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
149     ASL_METHOD_INFO         *MethodInfo = WalkInfo->MethodStack;
150     ACPI_PARSE_OBJECT       *Next;
151     UINT32                  RegisterNumber;
152     UINT32                  i;
153     char                    LocalName[] = "Local0";
154     char                    ArgName[] = "Arg0";
155     ACPI_PARSE_OBJECT       *ArgNode;
156     ACPI_PARSE_OBJECT       *NextType;
157     ACPI_PARSE_OBJECT       *NextParamType;
158     UINT8                   ActualArgs = 0;
159
160
161     switch (Op->Asl.ParseOpcode)
162     {
163     case PARSEOP_METHOD:
164
165         TotalMethods++;
166
167         /* Create and init method info */
168
169         MethodInfo       = UtLocalCalloc (sizeof (ASL_METHOD_INFO));
170         MethodInfo->Next = WalkInfo->MethodStack;
171         MethodInfo->Op = Op;
172
173         WalkInfo->MethodStack = MethodInfo;
174
175         /* Get the name node, ignored here */
176
177         Next = Op->Asl.Child;
178
179         /* Get the NumArguments node */
180
181         Next = Next->Asl.Next;
182         MethodInfo->NumArguments = (UINT8)
183             (((UINT8) Next->Asl.Value.Integer) & 0x07);
184
185         /* Get the SerializeRule and SyncLevel nodes, ignored here */
186
187         Next = Next->Asl.Next;
188         Next = Next->Asl.Next;
189         ArgNode = Next;
190
191         /* Get the ReturnType node */
192
193         Next = Next->Asl.Next;
194
195         NextType = Next->Asl.Child;
196         while (NextType)
197         {
198             /* Get and map each of the ReturnTypes */
199
200             MethodInfo->ValidReturnTypes |= AnMapObjTypeToBtype (NextType);
201             NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
202             NextType = NextType->Asl.Next;
203         }
204
205         /* Get the ParameterType node */
206
207         Next = Next->Asl.Next;
208
209         NextType = Next->Asl.Child;
210         while (NextType)
211         {
212             if (NextType->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
213             {
214                 NextParamType = NextType->Asl.Child;
215                 while (NextParamType)
216                 {
217                     MethodInfo->ValidArgTypes[ActualArgs] |= AnMapObjTypeToBtype (NextParamType);
218                     NextParamType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
219                     NextParamType = NextParamType->Asl.Next;
220                 }
221             }
222             else
223             {
224                 MethodInfo->ValidArgTypes[ActualArgs] =
225                     AnMapObjTypeToBtype (NextType);
226                 NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
227                 ActualArgs++;
228             }
229
230             NextType = NextType->Asl.Next;
231         }
232
233         if ((MethodInfo->NumArguments) &&
234             (MethodInfo->NumArguments != ActualArgs))
235         {
236             /* error: Param list did not match number of args */
237         }
238
239         /* Allow numarguments == 0 for Function() */
240
241         if ((!MethodInfo->NumArguments) && (ActualArgs))
242         {
243             MethodInfo->NumArguments = ActualArgs;
244             ArgNode->Asl.Value.Integer |= ActualArgs;
245         }
246
247         /*
248          * Actual arguments are initialized at method entry.
249          * All other ArgX "registers" can be used as locals, so we
250          * track their initialization.
251          */
252         for (i = 0; i < MethodInfo->NumArguments; i++)
253         {
254             MethodInfo->ArgInitialized[i] = TRUE;
255         }
256         break;
257
258
259     case PARSEOP_METHODCALL:
260
261         if (MethodInfo &&
262            (Op->Asl.Node == MethodInfo->Op->Asl.Node))
263         {
264             AslError (ASL_REMARK, ASL_MSG_RECURSION, Op, Op->Asl.ExternalName);
265         }
266         break;
267
268
269     case PARSEOP_LOCAL0:
270     case PARSEOP_LOCAL1:
271     case PARSEOP_LOCAL2:
272     case PARSEOP_LOCAL3:
273     case PARSEOP_LOCAL4:
274     case PARSEOP_LOCAL5:
275     case PARSEOP_LOCAL6:
276     case PARSEOP_LOCAL7:
277
278         if (!MethodInfo)
279         {
280             /*
281              * Local was used outside a control method, or there was an error
282              * in the method declaration.
283              */
284             AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName);
285             return (AE_ERROR);
286         }
287
288         RegisterNumber = (Op->Asl.AmlOpcode & 0x000F);
289
290         /*
291          * If the local is being used as a target, mark the local
292          * initialized
293          */
294         if (Op->Asl.CompileFlags & NODE_IS_TARGET)
295         {
296             MethodInfo->LocalInitialized[RegisterNumber] = TRUE;
297         }
298
299         /*
300          * Otherwise, this is a reference, check if the local
301          * has been previously initialized.
302          *
303          * The only operator that accepts an uninitialized value is ObjectType()
304          */
305         else if ((!MethodInfo->LocalInitialized[RegisterNumber]) &&
306                  (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
307         {
308             LocalName[strlen (LocalName) -1] = (char) (RegisterNumber + 0x30);
309             AslError (ASL_ERROR, ASL_MSG_LOCAL_INIT, Op, LocalName);
310         }
311         break;
312
313
314     case PARSEOP_ARG0:
315     case PARSEOP_ARG1:
316     case PARSEOP_ARG2:
317     case PARSEOP_ARG3:
318     case PARSEOP_ARG4:
319     case PARSEOP_ARG5:
320     case PARSEOP_ARG6:
321
322         if (!MethodInfo)
323         {
324             /*
325              * Arg was used outside a control method, or there was an error
326              * in the method declaration.
327              */
328             AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName);
329             return (AE_ERROR);
330         }
331
332         RegisterNumber = (Op->Asl.AmlOpcode & 0x000F) - 8;
333         ArgName[strlen (ArgName) -1] = (char) (RegisterNumber + 0x30);
334
335         /*
336          * If the Arg is being used as a target, mark the local
337          * initialized
338          */
339         if (Op->Asl.CompileFlags & NODE_IS_TARGET)
340         {
341             MethodInfo->ArgInitialized[RegisterNumber] = TRUE;
342         }
343
344         /*
345          * Otherwise, this is a reference, check if the Arg
346          * has been previously initialized.
347          *
348          * The only operator that accepts an uninitialized value is ObjectType()
349          */
350         else if ((!MethodInfo->ArgInitialized[RegisterNumber]) &&
351                  (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
352         {
353             AslError (ASL_ERROR, ASL_MSG_ARG_INIT, Op, ArgName);
354         }
355
356         /* Flag this arg if it is not a "real" argument to the method */
357
358         if (RegisterNumber >= MethodInfo->NumArguments)
359         {
360             AslError (ASL_REMARK, ASL_MSG_NOT_PARAMETER, Op, ArgName);
361         }
362         break;
363
364
365     case PARSEOP_RETURN:
366
367         if (!MethodInfo)
368         {
369             /*
370              * Probably was an error in the method declaration,
371              * no additional error here
372              */
373             ACPI_WARNING ((AE_INFO, "%p, No parent method", Op));
374             return (AE_ERROR);
375         }
376
377         /* Child indicates a return value */
378
379         if ((Op->Asl.Child) &&
380             (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
381         {
382             MethodInfo->NumReturnWithValue++;
383         }
384         else
385         {
386             MethodInfo->NumReturnNoValue++;
387         }
388         break;
389
390
391     case PARSEOP_BREAK:
392     case PARSEOP_CONTINUE:
393
394         Next = Op->Asl.Parent;
395         while (Next)
396         {
397             if (Next->Asl.ParseOpcode == PARSEOP_WHILE)
398             {
399                 break;
400             }
401             Next = Next->Asl.Parent;
402         }
403
404         if (!Next)
405         {
406             AslError (ASL_ERROR, ASL_MSG_NO_WHILE, Op, NULL);
407         }
408         break;
409
410
411     case PARSEOP_STALL:
412
413         /* We can range check if the argument is an integer */
414
415         if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
416             (Op->Asl.Child->Asl.Value.Integer > ACPI_UINT8_MAX))
417         {
418             AslError (ASL_ERROR, ASL_MSG_INVALID_TIME, Op, NULL);
419         }
420         break;
421
422
423     case PARSEOP_DEVICE:
424     case PARSEOP_EVENT:
425     case PARSEOP_MUTEX:
426     case PARSEOP_OPERATIONREGION:
427     case PARSEOP_POWERRESOURCE:
428     case PARSEOP_PROCESSOR:
429     case PARSEOP_THERMALZONE:
430
431         /*
432          * The first operand is a name to be created in the namespace.
433          * Check against the reserved list.
434          */
435         i = ApCheckForPredefinedName (Op, Op->Asl.NameSeg);
436         if (i < ACPI_VALID_RESERVED_NAME_MAX)
437         {
438             AslError (ASL_ERROR, ASL_MSG_RESERVED_USE, Op, Op->Asl.ExternalName);
439         }
440         break;
441
442
443     case PARSEOP_NAME:
444
445         /* Typecheck any predefined names statically defined with Name() */
446
447         ApCheckForPredefinedObject (Op, Op->Asl.NameSeg);
448
449         /* Special typechecking for _HID */
450
451         if (!ACPI_STRCMP (METHOD_NAME__HID, Op->Asl.NameSeg))
452         {
453             Next = Op->Asl.Child->Asl.Next;
454             AnCheckId (Next, ASL_TYPE_HID);
455         }
456
457         /* Special typechecking for _CID */
458
459         else if (!ACPI_STRCMP (METHOD_NAME__CID, Op->Asl.NameSeg))
460         {
461             Next = Op->Asl.Child->Asl.Next;
462
463             if ((Next->Asl.ParseOpcode == PARSEOP_PACKAGE) ||
464                 (Next->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE))
465             {
466                 Next = Next->Asl.Child;
467                 while (Next)
468                 {
469                     AnCheckId (Next, ASL_TYPE_CID);
470                     Next = Next->Asl.Next;
471                 }
472             }
473             else
474             {
475                 AnCheckId (Next, ASL_TYPE_CID);
476             }
477         }
478         break;
479
480
481     default:
482         break;
483     }
484
485     return (AE_OK);
486 }
487
488
489 /*******************************************************************************
490  *
491  * FUNCTION:    AnMethodAnalysisWalkEnd
492  *
493  * PARAMETERS:  ASL_WALK_CALLBACK
494  *
495  * RETURN:      Status
496  *
497  * DESCRIPTION: Ascending callback for analysis walk. Complete method
498  *              return analysis.
499  *
500  ******************************************************************************/
501
502 ACPI_STATUS
503 AnMethodAnalysisWalkEnd (
504     ACPI_PARSE_OBJECT       *Op,
505     UINT32                  Level,
506     void                    *Context)
507 {
508     ASL_ANALYSIS_WALK_INFO  *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
509     ASL_METHOD_INFO         *MethodInfo = WalkInfo->MethodStack;
510
511
512     switch (Op->Asl.ParseOpcode)
513     {
514     case PARSEOP_METHOD:
515     case PARSEOP_RETURN:
516         if (!MethodInfo)
517         {
518             printf ("No method info for method! [%s]\n", Op->Asl.Namepath);
519             AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
520                 "No method info for this method");
521
522             CmCleanupAndExit ();
523             return (AE_AML_INTERNAL);
524         }
525         break;
526
527     default:
528         break;
529     }
530
531     switch (Op->Asl.ParseOpcode)
532     {
533     case PARSEOP_METHOD:
534
535         WalkInfo->MethodStack = MethodInfo->Next;
536
537         /*
538          * Check if there is no return statement at the end of the
539          * method AND we can actually get there -- i.e., the execution
540          * of the method can possibly terminate without a return statement.
541          */
542         if ((!AnLastStatementIsReturn (Op)) &&
543             (!(Op->Asl.CompileFlags & NODE_HAS_NO_EXIT)))
544         {
545             /*
546              * No return statement, and execution can possibly exit
547              * via this path. This is equivalent to Return ()
548              */
549             MethodInfo->NumReturnNoValue++;
550         }
551
552         /*
553          * Check for case where some return statements have a return value
554          * and some do not. Exit without a return statement is a return with
555          * no value
556          */
557         if (MethodInfo->NumReturnNoValue &&
558             MethodInfo->NumReturnWithValue)
559         {
560             AslError (ASL_WARNING, ASL_MSG_RETURN_TYPES, Op,
561                 Op->Asl.ExternalName);
562         }
563
564         /*
565          * If there are any RETURN() statements with no value, or there is a
566          * control path that allows the method to exit without a return value,
567          * we mark the method as a method that does not return a value. This
568          * knowledge can be used to check method invocations that expect a
569          * returned value.
570          */
571         if (MethodInfo->NumReturnNoValue)
572         {
573             if (MethodInfo->NumReturnWithValue)
574             {
575                 Op->Asl.CompileFlags |= NODE_METHOD_SOME_NO_RETVAL;
576             }
577             else
578             {
579                 Op->Asl.CompileFlags |= NODE_METHOD_NO_RETVAL;
580             }
581         }
582
583         /*
584          * Check predefined method names for correct return behavior
585          * and correct number of arguments
586          */
587         ApCheckForPredefinedMethod (Op, MethodInfo);
588
589         /* Special check for two names like _L01 and _E01 in same scope */
590
591         ApCheckForGpeNameConflict (Op);
592         ACPI_FREE (MethodInfo);
593         break;
594
595
596     case PARSEOP_NAME:
597
598          /* Special check for two names like _L01 and _E01 in same scope */
599
600         ApCheckForGpeNameConflict (Op);
601         break;
602
603
604     case PARSEOP_RETURN:
605
606         /*
607          * If the parent is a predefined method name, attempt to typecheck
608          * the return value. Only static types can be validated.
609          */
610         ApCheckPredefinedReturnValue (Op, MethodInfo);
611
612         /*
613          * The parent block does not "exit" and continue execution -- the
614          * method is terminated here with the Return() statement.
615          */
616         Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
617
618         /* Used in the "typing" pass later */
619
620         Op->Asl.ParentMethod = MethodInfo->Op;
621
622         /*
623          * If there is a peer node after the return statement, then this
624          * node is unreachable code -- i.e., it won't be executed because of
625          * the preceeding Return() statement.
626          */
627         if (Op->Asl.Next)
628         {
629             AslError (ASL_WARNING, ASL_MSG_UNREACHABLE_CODE, Op->Asl.Next, NULL);
630         }
631         break;
632
633
634     case PARSEOP_IF:
635
636         if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
637             (Op->Asl.Next) &&
638             (Op->Asl.Next->Asl.ParseOpcode == PARSEOP_ELSE))
639         {
640             /*
641              * This IF has a corresponding ELSE. The IF block has no exit,
642              * (it contains an unconditional Return)
643              * mark the ELSE block to remember this fact.
644              */
645             Op->Asl.Next->Asl.CompileFlags |= NODE_IF_HAS_NO_EXIT;
646         }
647         break;
648
649
650     case PARSEOP_ELSE:
651
652         if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
653             (Op->Asl.CompileFlags & NODE_IF_HAS_NO_EXIT))
654         {
655             /*
656              * This ELSE block has no exit and the corresponding IF block
657              * has no exit either. Therefore, the parent node has no exit.
658              */
659             Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
660         }
661         break;
662
663
664     default:
665
666         if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
667             (Op->Asl.Parent))
668         {
669             /* If this node has no exit, then the parent has no exit either */
670
671             Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
672         }
673         break;
674     }
675
676     return (AE_OK);
677 }
678
679
680 /*******************************************************************************
681  *
682  * FUNCTION:    AnMethodTypingWalkEnd
683  *
684  * PARAMETERS:  ASL_WALK_CALLBACK
685  *
686  * RETURN:      Status
687  *
688  * DESCRIPTION: Ascending callback for typing walk. Complete the method
689  *              return analysis. Check methods for:
690  *              1) Initialized local variables
691  *              2) Valid arguments
692  *              3) Return types
693  *
694  ******************************************************************************/
695
696 ACPI_STATUS
697 AnMethodTypingWalkEnd (
698     ACPI_PARSE_OBJECT       *Op,
699     UINT32                  Level,
700     void                    *Context)
701 {
702     UINT32                  ThisNodeBtype;
703
704
705     switch (Op->Asl.ParseOpcode)
706     {
707     case PARSEOP_METHOD:
708
709         Op->Asl.CompileFlags |= NODE_METHOD_TYPED;
710         break;
711
712     case PARSEOP_RETURN:
713
714         if ((Op->Asl.Child) &&
715             (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
716         {
717             ThisNodeBtype = AnGetBtype (Op->Asl.Child);
718
719             if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_METHODCALL) &&
720                 (ThisNodeBtype == (ACPI_UINT32_MAX -1)))
721             {
722                 /*
723                  * The called method is untyped at this time (typically a
724                  * forward reference).
725                  *
726                  * Check for a recursive method call first.
727                  */
728                 if (Op->Asl.ParentMethod != Op->Asl.Child->Asl.Node->Op)
729                 {
730                     /* We must type the method here */
731
732                     TrWalkParseTree (Op->Asl.Child->Asl.Node->Op,
733                         ASL_WALK_VISIT_UPWARD, NULL,
734                         AnMethodTypingWalkEnd, NULL);
735
736                     ThisNodeBtype = AnGetBtype (Op->Asl.Child);
737                 }
738             }
739
740             /* Returns a value, save the value type */
741
742             if (Op->Asl.ParentMethod)
743             {
744                 Op->Asl.ParentMethod->Asl.AcpiBtype |= ThisNodeBtype;
745             }
746         }
747         break;
748
749     default:
750         break;
751     }
752
753     return (AE_OK);
754 }
755
756
757 /*******************************************************************************
758  *
759  * FUNCTION:    AnOperandTypecheckWalkEnd
760  *
761  * PARAMETERS:  ASL_WALK_CALLBACK
762  *
763  * RETURN:      Status
764  *
765  * DESCRIPTION: Ascending callback for analysis walk. Complete method
766  *              return analysis.
767  *
768  ******************************************************************************/
769
770 ACPI_STATUS
771 AnOperandTypecheckWalkEnd (
772     ACPI_PARSE_OBJECT       *Op,
773     UINT32                  Level,
774     void                    *Context)
775 {
776     const ACPI_OPCODE_INFO  *OpInfo;
777     UINT32                  RuntimeArgTypes;
778     UINT32                  RuntimeArgTypes2;
779     UINT32                  RequiredBtypes;
780     UINT32                  ThisNodeBtype;
781     UINT32                  CommonBtypes;
782     UINT32                  OpcodeClass;
783     ACPI_PARSE_OBJECT       *ArgOp;
784     UINT32                  ArgType;
785
786
787     switch (Op->Asl.AmlOpcode)
788     {
789     case AML_RAW_DATA_BYTE:
790     case AML_RAW_DATA_WORD:
791     case AML_RAW_DATA_DWORD:
792     case AML_RAW_DATA_QWORD:
793     case AML_RAW_DATA_BUFFER:
794     case AML_RAW_DATA_CHAIN:
795     case AML_PACKAGE_LENGTH:
796     case AML_UNASSIGNED_OPCODE:
797     case AML_DEFAULT_ARG_OP:
798
799         /* Ignore the internal (compiler-only) AML opcodes */
800
801         return (AE_OK);
802
803     default:
804         break;
805     }
806
807     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
808     if (!OpInfo)
809     {
810         return (AE_OK);
811     }
812
813     ArgOp           = Op->Asl.Child;
814     RuntimeArgTypes = OpInfo->RuntimeArgs;
815     OpcodeClass     = OpInfo->Class;
816
817 #ifdef ASL_ERROR_NAMED_OBJECT_IN_WHILE
818     /*
819      * Update 11/2008: In practice, we can't perform this check. A simple
820      * analysis is not sufficient. Also, it can cause errors when compiling
821      * disassembled code because of the way Switch operators are implemented
822      * (a While(One) loop with a named temp variable created within.)
823      */
824
825     /*
826      * If we are creating a named object, check if we are within a while loop
827      * by checking if the parent is a WHILE op. This is a simple analysis, but
828      * probably sufficient for many cases.
829      *
830      * Allow Scope(), Buffer(), and Package().
831      */
832     if (((OpcodeClass == AML_CLASS_NAMED_OBJECT) && (Op->Asl.AmlOpcode != AML_SCOPE_OP)) ||
833         ((OpcodeClass == AML_CLASS_CREATE) && (OpInfo->Flags & AML_NSNODE)))
834     {
835         if (Op->Asl.Parent->Asl.AmlOpcode == AML_WHILE_OP)
836         {
837             AslError (ASL_ERROR, ASL_MSG_NAMED_OBJECT_IN_WHILE, Op, NULL);
838         }
839     }
840 #endif
841
842     /*
843      * Special case for control opcodes IF/RETURN/WHILE since they
844      * have no runtime arg list (at this time)
845      */
846     switch (Op->Asl.AmlOpcode)
847     {
848     case AML_IF_OP:
849     case AML_WHILE_OP:
850     case AML_RETURN_OP:
851
852         if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
853         {
854             /* Check for an internal method */
855
856             if (AnIsInternalMethod (ArgOp))
857             {
858                 return (AE_OK);
859             }
860
861             /* The lone arg is a method call, check it */
862
863             RequiredBtypes = AnMapArgTypeToBtype (ARGI_INTEGER);
864             if (Op->Asl.AmlOpcode == AML_RETURN_OP)
865             {
866                 RequiredBtypes = 0xFFFFFFFF;
867             }
868
869             ThisNodeBtype = AnGetBtype (ArgOp);
870             if (ThisNodeBtype == ACPI_UINT32_MAX)
871             {
872                 return (AE_OK);
873             }
874             AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
875                 RequiredBtypes, ThisNodeBtype);
876         }
877         return (AE_OK);
878
879     default:
880         break;
881     }
882
883     /* Ignore the non-executable opcodes */
884
885     if (RuntimeArgTypes == ARGI_INVALID_OPCODE)
886     {
887         return (AE_OK);
888     }
889
890     switch (OpcodeClass)
891     {
892     case AML_CLASS_EXECUTE:
893     case AML_CLASS_CREATE:
894     case AML_CLASS_CONTROL:
895     case AML_CLASS_RETURN_VALUE:
896
897         /* TBD: Change class or fix typechecking for these */
898
899         if ((Op->Asl.AmlOpcode == AML_BUFFER_OP)        ||
900             (Op->Asl.AmlOpcode == AML_PACKAGE_OP)       ||
901             (Op->Asl.AmlOpcode == AML_VAR_PACKAGE_OP))
902         {
903             break;
904         }
905
906         /* Reverse the runtime argument list */
907
908         RuntimeArgTypes2 = 0;
909         while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes)))
910         {
911             RuntimeArgTypes2 <<= ARG_TYPE_WIDTH;
912             RuntimeArgTypes2 |= ArgType;
913             INCREMENT_ARG_LIST (RuntimeArgTypes);
914         }
915
916         while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2)))
917         {
918             RequiredBtypes = AnMapArgTypeToBtype (ArgType);
919
920             ThisNodeBtype = AnGetBtype (ArgOp);
921             if (ThisNodeBtype == ACPI_UINT32_MAX)
922             {
923                 goto NextArgument;
924             }
925
926             /* Examine the arg based on the required type of the arg */
927
928             switch (ArgType)
929             {
930             case ARGI_TARGETREF:
931
932                 if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO)
933                 {
934                     /* ZERO is the placeholder for "don't store result" */
935
936                     ThisNodeBtype = RequiredBtypes;
937                     break;
938                 }
939
940                 if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER)
941                 {
942                     /*
943                      * This is the case where an original reference to a resource
944                      * descriptor field has been replaced by an (Integer) offset.
945                      * These named fields are supported at compile-time only;
946                      * the names are not passed to the interpreter (via the AML).
947                      */
948                     if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
949                         (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
950                     {
951                         AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD, ArgOp, NULL);
952                     }
953                     else
954                     {
955                         AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, NULL);
956                     }
957                     break;
958                 }
959
960                 if ((ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) ||
961                     (ArgOp->Asl.ParseOpcode == PARSEOP_DEREFOF))
962                 {
963                     break;
964                 }
965
966                 ThisNodeBtype = RequiredBtypes;
967                 break;
968
969
970             case ARGI_REFERENCE:            /* References */
971             case ARGI_INTEGER_REF:
972             case ARGI_OBJECT_REF:
973             case ARGI_DEVICE_REF:
974
975                 switch (ArgOp->Asl.ParseOpcode)
976                 {
977                 case PARSEOP_LOCAL0:
978                 case PARSEOP_LOCAL1:
979                 case PARSEOP_LOCAL2:
980                 case PARSEOP_LOCAL3:
981                 case PARSEOP_LOCAL4:
982                 case PARSEOP_LOCAL5:
983                 case PARSEOP_LOCAL6:
984                 case PARSEOP_LOCAL7:
985
986                     /* TBD: implement analysis of current value (type) of the local */
987                     /* For now, just treat any local as a typematch */
988
989                     /*ThisNodeBtype = RequiredBtypes;*/
990                     break;
991
992                 case PARSEOP_ARG0:
993                 case PARSEOP_ARG1:
994                 case PARSEOP_ARG2:
995                 case PARSEOP_ARG3:
996                 case PARSEOP_ARG4:
997                 case PARSEOP_ARG5:
998                 case PARSEOP_ARG6:
999
1000                     /* Hard to analyze argument types, sow we won't */
1001                     /* For now, just treat any arg as a typematch */
1002
1003                     /* ThisNodeBtype = RequiredBtypes; */
1004                     break;
1005
1006                 case PARSEOP_DEBUG:
1007                     break;
1008
1009                 case PARSEOP_REFOF:
1010                 case PARSEOP_INDEX:
1011                 default:
1012                     break;
1013
1014                 }
1015                 break;
1016
1017             case ARGI_INTEGER:
1018             default:
1019                 break;
1020             }
1021
1022
1023             CommonBtypes = ThisNodeBtype & RequiredBtypes;
1024
1025             if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
1026             {
1027                 if (AnIsInternalMethod (ArgOp))
1028                 {
1029                     return (AE_OK);
1030                 }
1031
1032                 /* Check a method call for a valid return value */
1033
1034                 AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
1035                     RequiredBtypes, ThisNodeBtype);
1036             }
1037
1038             /*
1039              * Now check if the actual type(s) match at least one
1040              * bit to the required type
1041              */
1042             else if (!CommonBtypes)
1043             {
1044                 /* No match -- this is a type mismatch error */
1045
1046                 AnFormatBtype (StringBuffer, ThisNodeBtype);
1047                 AnFormatBtype (StringBuffer2, RequiredBtypes);
1048
1049                 sprintf (MsgBuffer, "[%s] found, %s operator requires [%s]",
1050                             StringBuffer, OpInfo->Name, StringBuffer2);
1051
1052                 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer);
1053             }
1054
1055         NextArgument:
1056             ArgOp = ArgOp->Asl.Next;
1057             INCREMENT_ARG_LIST (RuntimeArgTypes2);
1058         }
1059         break;
1060
1061     default:
1062         break;
1063     }
1064
1065     return (AE_OK);
1066 }
1067
1068
1069 /*******************************************************************************
1070  *
1071  * FUNCTION:    AnOtherSemanticAnalysisWalkBegin
1072  *
1073  * PARAMETERS:  ASL_WALK_CALLBACK
1074  *
1075  * RETURN:      Status
1076  *
1077  * DESCRIPTION: Descending callback for the analysis walk. Checks for
1078  *              miscellaneous issues in the code.
1079  *
1080  ******************************************************************************/
1081
1082 ACPI_STATUS
1083 AnOtherSemanticAnalysisWalkBegin (
1084     ACPI_PARSE_OBJECT       *Op,
1085     UINT32                  Level,
1086     void                    *Context)
1087 {
1088     ACPI_PARSE_OBJECT       *ArgNode;
1089     ACPI_PARSE_OBJECT       *PrevArgNode = NULL;
1090     const ACPI_OPCODE_INFO  *OpInfo;
1091
1092
1093     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
1094
1095     /*
1096      * Determine if an execution class operator actually does something by
1097      * checking if it has a target and/or the function return value is used.
1098      * (Target is optional, so a standalone statement can actually do nothing.)
1099      */
1100     if ((OpInfo->Class == AML_CLASS_EXECUTE) &&
1101         (OpInfo->Flags & AML_HAS_RETVAL) &&
1102         (!AnIsResultUsed (Op)))
1103     {
1104         if (OpInfo->Flags & AML_HAS_TARGET)
1105         {
1106             /*
1107              * Find the target node, it is always the last child. If the traget
1108              * is not specified in the ASL, a default node of type Zero was
1109              * created by the parser.
1110              */
1111             ArgNode = Op->Asl.Child;
1112             while (ArgNode->Asl.Next)
1113             {
1114                 PrevArgNode = ArgNode;
1115                 ArgNode = ArgNode->Asl.Next;
1116             }
1117
1118             /* Divide() is the only weird case, it has two targets */
1119
1120             if (Op->Asl.AmlOpcode == AML_DIVIDE_OP)
1121             {
1122                 if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) &&
1123                     (PrevArgNode) &&
1124                     (PrevArgNode->Asl.ParseOpcode == PARSEOP_ZERO))
1125                 {
1126                     AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED,
1127                         Op, Op->Asl.ExternalName);
1128                 }
1129             }
1130             else if (ArgNode->Asl.ParseOpcode == PARSEOP_ZERO)
1131             {
1132                 AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED,
1133                     Op, Op->Asl.ExternalName);
1134             }
1135         }
1136         else
1137         {
1138             /*
1139              * Has no target and the result is not used. Only a couple opcodes
1140              * can have this combination.
1141              */
1142             switch (Op->Asl.ParseOpcode)
1143             {
1144             case PARSEOP_ACQUIRE:
1145             case PARSEOP_WAIT:
1146             case PARSEOP_LOADTABLE:
1147                 break;
1148
1149             default:
1150                 AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED,
1151                     Op, Op->Asl.ExternalName);
1152                 break;
1153             }
1154         }
1155     }
1156
1157
1158     /*
1159      * Semantic checks for individual ASL operators
1160      */
1161     switch (Op->Asl.ParseOpcode)
1162     {
1163     case PARSEOP_ACQUIRE:
1164     case PARSEOP_WAIT:
1165         /*
1166          * Emit a warning if the timeout parameter for these operators is not
1167          * ACPI_WAIT_FOREVER, and the result value from the operator is not
1168          * checked, meaning that a timeout could happen, but the code
1169          * would not know about it.
1170          */
1171
1172         /* First child is the namepath, 2nd child is timeout */
1173
1174         ArgNode = Op->Asl.Child;
1175         ArgNode = ArgNode->Asl.Next;
1176
1177         /*
1178          * Check for the WAIT_FOREVER case - defined by the ACPI spec to be
1179          * 0xFFFF or greater
1180          */
1181         if (((ArgNode->Asl.ParseOpcode == PARSEOP_WORDCONST) ||
1182              (ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER))  &&
1183              (ArgNode->Asl.Value.Integer >= (UINT64) ACPI_WAIT_FOREVER))
1184         {
1185             break;
1186         }
1187
1188         /*
1189          * The operation could timeout. If the return value is not used
1190          * (indicates timeout occurred), issue a warning
1191          */
1192         if (!AnIsResultUsed (Op))
1193         {
1194             AslError (ASL_WARNING, ASL_MSG_TIMEOUT, ArgNode,
1195                 Op->Asl.ExternalName);
1196         }
1197         break;
1198
1199     case PARSEOP_CREATEFIELD:
1200         /*
1201          * Check for a zero Length (NumBits) operand. NumBits is the 3rd operand
1202          */
1203         ArgNode = Op->Asl.Child;
1204         ArgNode = ArgNode->Asl.Next;
1205         ArgNode = ArgNode->Asl.Next;
1206
1207         if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) ||
1208            ((ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER) &&
1209             (ArgNode->Asl.Value.Integer == 0)))
1210         {
1211             AslError (ASL_ERROR, ASL_MSG_NON_ZERO, ArgNode, NULL);
1212         }
1213         break;
1214
1215     default:
1216         break;
1217     }
1218
1219     return (AE_OK);
1220 }