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