aslwalks.c revision 220663
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
70ACPI_STATUS
71AnMethodAnalysisWalkBegin (
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        /*
306         * A child indicates a possible return value. A simple Return or
307         * Return() is marked with NODE_IS_NULL_RETURN by the parser so
308         * that it is not counted as a "real" return-with-value, although
309         * the AML code that is actually emitted is Return(0). The AML
310         * definition of Return has a required parameter, so we are
311         * forced to convert a null return to Return(0).
312         */
313        if ((Op->Asl.Child) &&
314            (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
315            (!(Op->Asl.Child->Asl.CompileFlags & NODE_IS_NULL_RETURN)))
316        {
317            MethodInfo->NumReturnWithValue++;
318        }
319        else
320        {
321            MethodInfo->NumReturnNoValue++;
322        }
323        break;
324
325
326    case PARSEOP_BREAK:
327    case PARSEOP_CONTINUE:
328
329        Next = Op->Asl.Parent;
330        while (Next)
331        {
332            if (Next->Asl.ParseOpcode == PARSEOP_WHILE)
333            {
334                break;
335            }
336            Next = Next->Asl.Parent;
337        }
338
339        if (!Next)
340        {
341            AslError (ASL_ERROR, ASL_MSG_NO_WHILE, Op, NULL);
342        }
343        break;
344
345
346    case PARSEOP_STALL:
347
348        /* We can range check if the argument is an integer */
349
350        if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
351            (Op->Asl.Child->Asl.Value.Integer > ACPI_UINT8_MAX))
352        {
353            AslError (ASL_ERROR, ASL_MSG_INVALID_TIME, Op, NULL);
354        }
355        break;
356
357
358    case PARSEOP_DEVICE:
359    case PARSEOP_EVENT:
360    case PARSEOP_MUTEX:
361    case PARSEOP_OPERATIONREGION:
362    case PARSEOP_POWERRESOURCE:
363    case PARSEOP_PROCESSOR:
364    case PARSEOP_THERMALZONE:
365
366        /*
367         * The first operand is a name to be created in the namespace.
368         * Check against the reserved list.
369         */
370        i = ApCheckForPredefinedName (Op, Op->Asl.NameSeg);
371        if (i < ACPI_VALID_RESERVED_NAME_MAX)
372        {
373            AslError (ASL_ERROR, ASL_MSG_RESERVED_USE, Op, Op->Asl.ExternalName);
374        }
375        break;
376
377
378    case PARSEOP_NAME:
379
380        /* Typecheck any predefined names statically defined with Name() */
381
382        ApCheckForPredefinedObject (Op, Op->Asl.NameSeg);
383
384        /* Special typechecking for _HID */
385
386        if (!ACPI_STRCMP (METHOD_NAME__HID, Op->Asl.NameSeg))
387        {
388            Next = Op->Asl.Child->Asl.Next;
389            AnCheckId (Next, ASL_TYPE_HID);
390        }
391
392        /* Special typechecking for _CID */
393
394        else if (!ACPI_STRCMP (METHOD_NAME__CID, Op->Asl.NameSeg))
395        {
396            Next = Op->Asl.Child->Asl.Next;
397
398            if ((Next->Asl.ParseOpcode == PARSEOP_PACKAGE) ||
399                (Next->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE))
400            {
401                Next = Next->Asl.Child;
402                while (Next)
403                {
404                    AnCheckId (Next, ASL_TYPE_CID);
405                    Next = Next->Asl.Next;
406                }
407            }
408            else
409            {
410                AnCheckId (Next, ASL_TYPE_CID);
411            }
412        }
413        break;
414
415
416    default:
417        break;
418    }
419
420    return (AE_OK);
421}
422
423
424/*******************************************************************************
425 *
426 * FUNCTION:    AnMethodAnalysisWalkEnd
427 *
428 * PARAMETERS:  ASL_WALK_CALLBACK
429 *
430 * RETURN:      Status
431 *
432 * DESCRIPTION: Ascending callback for analysis walk. Complete method
433 *              return analysis.
434 *
435 ******************************************************************************/
436
437ACPI_STATUS
438AnMethodAnalysisWalkEnd (
439    ACPI_PARSE_OBJECT       *Op,
440    UINT32                  Level,
441    void                    *Context)
442{
443    ASL_ANALYSIS_WALK_INFO  *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
444    ASL_METHOD_INFO         *MethodInfo = WalkInfo->MethodStack;
445
446
447    switch (Op->Asl.ParseOpcode)
448    {
449    case PARSEOP_METHOD:
450    case PARSEOP_RETURN:
451        if (!MethodInfo)
452        {
453            printf ("No method info for method! [%s]\n", Op->Asl.Namepath);
454            AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
455                "No method info for this method");
456
457            CmCleanupAndExit ();
458            return (AE_AML_INTERNAL);
459        }
460        break;
461
462    default:
463        break;
464    }
465
466    switch (Op->Asl.ParseOpcode)
467    {
468    case PARSEOP_METHOD:
469
470        WalkInfo->MethodStack = MethodInfo->Next;
471
472        /*
473         * Check if there is no return statement at the end of the
474         * method AND we can actually get there -- i.e., the execution
475         * of the method can possibly terminate without a return statement.
476         */
477        if ((!AnLastStatementIsReturn (Op)) &&
478            (!(Op->Asl.CompileFlags & NODE_HAS_NO_EXIT)))
479        {
480            /*
481             * No return statement, and execution can possibly exit
482             * via this path. This is equivalent to Return ()
483             */
484            MethodInfo->NumReturnNoValue++;
485        }
486
487        /*
488         * Check for case where some return statements have a return value
489         * and some do not. Exit without a return statement is a return with
490         * no value
491         */
492        if (MethodInfo->NumReturnNoValue &&
493            MethodInfo->NumReturnWithValue)
494        {
495            AslError (ASL_WARNING, ASL_MSG_RETURN_TYPES, Op,
496                Op->Asl.ExternalName);
497        }
498
499        /*
500         * If there are any RETURN() statements with no value, or there is a
501         * control path that allows the method to exit without a return value,
502         * we mark the method as a method that does not return a value. This
503         * knowledge can be used to check method invocations that expect a
504         * returned value.
505         */
506        if (MethodInfo->NumReturnNoValue)
507        {
508            if (MethodInfo->NumReturnWithValue)
509            {
510                Op->Asl.CompileFlags |= NODE_METHOD_SOME_NO_RETVAL;
511            }
512            else
513            {
514                Op->Asl.CompileFlags |= NODE_METHOD_NO_RETVAL;
515            }
516        }
517
518        /*
519         * Check predefined method names for correct return behavior
520         * and correct number of arguments. Also, some special checks
521         * For GPE and _REG methods.
522         */
523        if (ApCheckForPredefinedMethod (Op, MethodInfo))
524        {
525            /* Special check for two names like _L01 and _E01 in same scope */
526
527            ApCheckForGpeNameConflict (Op);
528
529            /*
530             * Special check for _REG: Must have an operation region definition
531             * within the same scope!
532             */
533            ApCheckRegMethod (Op);
534        }
535
536        ACPI_FREE (MethodInfo);
537        break;
538
539
540    case PARSEOP_NAME:
541
542         /* Special check for two names like _L01 and _E01 in same scope */
543
544        ApCheckForGpeNameConflict (Op);
545        break;
546
547
548    case PARSEOP_RETURN:
549
550        /*
551         * If the parent is a predefined method name, attempt to typecheck
552         * the return value. Only static types can be validated.
553         */
554        ApCheckPredefinedReturnValue (Op, MethodInfo);
555
556        /*
557         * The parent block does not "exit" and continue execution -- the
558         * method is terminated here with the Return() statement.
559         */
560        Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
561
562        /* Used in the "typing" pass later */
563
564        Op->Asl.ParentMethod = MethodInfo->Op;
565
566        /*
567         * If there is a peer node after the return statement, then this
568         * node is unreachable code -- i.e., it won't be executed because of
569         * the preceeding Return() statement.
570         */
571        if (Op->Asl.Next)
572        {
573            AslError (ASL_WARNING, ASL_MSG_UNREACHABLE_CODE, Op->Asl.Next, NULL);
574        }
575        break;
576
577
578    case PARSEOP_IF:
579
580        if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
581            (Op->Asl.Next) &&
582            (Op->Asl.Next->Asl.ParseOpcode == PARSEOP_ELSE))
583        {
584            /*
585             * This IF has a corresponding ELSE. The IF block has no exit,
586             * (it contains an unconditional Return)
587             * mark the ELSE block to remember this fact.
588             */
589            Op->Asl.Next->Asl.CompileFlags |= NODE_IF_HAS_NO_EXIT;
590        }
591        break;
592
593
594    case PARSEOP_ELSE:
595
596        if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
597            (Op->Asl.CompileFlags & NODE_IF_HAS_NO_EXIT))
598        {
599            /*
600             * This ELSE block has no exit and the corresponding IF block
601             * has no exit either. Therefore, the parent node has no exit.
602             */
603            Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
604        }
605        break;
606
607
608    default:
609
610        if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
611            (Op->Asl.Parent))
612        {
613            /* If this node has no exit, then the parent has no exit either */
614
615            Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
616        }
617        break;
618    }
619
620    return (AE_OK);
621}
622
623
624/*******************************************************************************
625 *
626 * FUNCTION:    AnMethodTypingWalkEnd
627 *
628 * PARAMETERS:  ASL_WALK_CALLBACK
629 *
630 * RETURN:      Status
631 *
632 * DESCRIPTION: Ascending callback for typing walk. Complete the method
633 *              return analysis. Check methods for:
634 *              1) Initialized local variables
635 *              2) Valid arguments
636 *              3) Return types
637 *
638 ******************************************************************************/
639
640ACPI_STATUS
641AnMethodTypingWalkEnd (
642    ACPI_PARSE_OBJECT       *Op,
643    UINT32                  Level,
644    void                    *Context)
645{
646    UINT32                  ThisNodeBtype;
647
648
649    switch (Op->Asl.ParseOpcode)
650    {
651    case PARSEOP_METHOD:
652
653        Op->Asl.CompileFlags |= NODE_METHOD_TYPED;
654        break;
655
656    case PARSEOP_RETURN:
657
658        if ((Op->Asl.Child) &&
659            (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
660        {
661            ThisNodeBtype = AnGetBtype (Op->Asl.Child);
662
663            if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_METHODCALL) &&
664                (ThisNodeBtype == (ACPI_UINT32_MAX -1)))
665            {
666                /*
667                 * The called method is untyped at this time (typically a
668                 * forward reference).
669                 *
670                 * Check for a recursive method call first.
671                 */
672                if (Op->Asl.ParentMethod != Op->Asl.Child->Asl.Node->Op)
673                {
674                    /* We must type the method here */
675
676                    TrWalkParseTree (Op->Asl.Child->Asl.Node->Op,
677                        ASL_WALK_VISIT_UPWARD, NULL,
678                        AnMethodTypingWalkEnd, NULL);
679
680                    ThisNodeBtype = AnGetBtype (Op->Asl.Child);
681                }
682            }
683
684            /* Returns a value, save the value type */
685
686            if (Op->Asl.ParentMethod)
687            {
688                Op->Asl.ParentMethod->Asl.AcpiBtype |= ThisNodeBtype;
689            }
690        }
691        break;
692
693    default:
694        break;
695    }
696
697    return (AE_OK);
698}
699
700
701/*******************************************************************************
702 *
703 * FUNCTION:    AnOperandTypecheckWalkEnd
704 *
705 * PARAMETERS:  ASL_WALK_CALLBACK
706 *
707 * RETURN:      Status
708 *
709 * DESCRIPTION: Ascending callback for analysis walk. Complete method
710 *              return analysis.
711 *
712 ******************************************************************************/
713
714ACPI_STATUS
715AnOperandTypecheckWalkEnd (
716    ACPI_PARSE_OBJECT       *Op,
717    UINT32                  Level,
718    void                    *Context)
719{
720    const ACPI_OPCODE_INFO  *OpInfo;
721    UINT32                  RuntimeArgTypes;
722    UINT32                  RuntimeArgTypes2;
723    UINT32                  RequiredBtypes;
724    UINT32                  ThisNodeBtype;
725    UINT32                  CommonBtypes;
726    UINT32                  OpcodeClass;
727    ACPI_PARSE_OBJECT       *ArgOp;
728    UINT32                  ArgType;
729
730
731    switch (Op->Asl.AmlOpcode)
732    {
733    case AML_RAW_DATA_BYTE:
734    case AML_RAW_DATA_WORD:
735    case AML_RAW_DATA_DWORD:
736    case AML_RAW_DATA_QWORD:
737    case AML_RAW_DATA_BUFFER:
738    case AML_RAW_DATA_CHAIN:
739    case AML_PACKAGE_LENGTH:
740    case AML_UNASSIGNED_OPCODE:
741    case AML_DEFAULT_ARG_OP:
742
743        /* Ignore the internal (compiler-only) AML opcodes */
744
745        return (AE_OK);
746
747    default:
748        break;
749    }
750
751    OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
752    if (!OpInfo)
753    {
754        return (AE_OK);
755    }
756
757    ArgOp           = Op->Asl.Child;
758    RuntimeArgTypes = OpInfo->RuntimeArgs;
759    OpcodeClass     = OpInfo->Class;
760
761#ifdef ASL_ERROR_NAMED_OBJECT_IN_WHILE
762    /*
763     * Update 11/2008: In practice, we can't perform this check. A simple
764     * analysis is not sufficient. Also, it can cause errors when compiling
765     * disassembled code because of the way Switch operators are implemented
766     * (a While(One) loop with a named temp variable created within.)
767     */
768
769    /*
770     * If we are creating a named object, check if we are within a while loop
771     * by checking if the parent is a WHILE op. This is a simple analysis, but
772     * probably sufficient for many cases.
773     *
774     * Allow Scope(), Buffer(), and Package().
775     */
776    if (((OpcodeClass == AML_CLASS_NAMED_OBJECT) && (Op->Asl.AmlOpcode != AML_SCOPE_OP)) ||
777        ((OpcodeClass == AML_CLASS_CREATE) && (OpInfo->Flags & AML_NSNODE)))
778    {
779        if (Op->Asl.Parent->Asl.AmlOpcode == AML_WHILE_OP)
780        {
781            AslError (ASL_ERROR, ASL_MSG_NAMED_OBJECT_IN_WHILE, Op, NULL);
782        }
783    }
784#endif
785
786    /*
787     * Special case for control opcodes IF/RETURN/WHILE since they
788     * have no runtime arg list (at this time)
789     */
790    switch (Op->Asl.AmlOpcode)
791    {
792    case AML_IF_OP:
793    case AML_WHILE_OP:
794    case AML_RETURN_OP:
795
796        if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
797        {
798            /* Check for an internal method */
799
800            if (AnIsInternalMethod (ArgOp))
801            {
802                return (AE_OK);
803            }
804
805            /* The lone arg is a method call, check it */
806
807            RequiredBtypes = AnMapArgTypeToBtype (ARGI_INTEGER);
808            if (Op->Asl.AmlOpcode == AML_RETURN_OP)
809            {
810                RequiredBtypes = 0xFFFFFFFF;
811            }
812
813            ThisNodeBtype = AnGetBtype (ArgOp);
814            if (ThisNodeBtype == ACPI_UINT32_MAX)
815            {
816                return (AE_OK);
817            }
818            AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
819                RequiredBtypes, ThisNodeBtype);
820        }
821        return (AE_OK);
822
823    default:
824        break;
825    }
826
827    /* Ignore the non-executable opcodes */
828
829    if (RuntimeArgTypes == ARGI_INVALID_OPCODE)
830    {
831        return (AE_OK);
832    }
833
834    switch (OpcodeClass)
835    {
836    case AML_CLASS_EXECUTE:
837    case AML_CLASS_CREATE:
838    case AML_CLASS_CONTROL:
839    case AML_CLASS_RETURN_VALUE:
840
841        /* TBD: Change class or fix typechecking for these */
842
843        if ((Op->Asl.AmlOpcode == AML_BUFFER_OP)        ||
844            (Op->Asl.AmlOpcode == AML_PACKAGE_OP)       ||
845            (Op->Asl.AmlOpcode == AML_VAR_PACKAGE_OP))
846        {
847            break;
848        }
849
850        /* Reverse the runtime argument list */
851
852        RuntimeArgTypes2 = 0;
853        while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes)))
854        {
855            RuntimeArgTypes2 <<= ARG_TYPE_WIDTH;
856            RuntimeArgTypes2 |= ArgType;
857            INCREMENT_ARG_LIST (RuntimeArgTypes);
858        }
859
860        while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2)))
861        {
862            RequiredBtypes = AnMapArgTypeToBtype (ArgType);
863
864            ThisNodeBtype = AnGetBtype (ArgOp);
865            if (ThisNodeBtype == ACPI_UINT32_MAX)
866            {
867                goto NextArgument;
868            }
869
870            /* Examine the arg based on the required type of the arg */
871
872            switch (ArgType)
873            {
874            case ARGI_TARGETREF:
875
876                if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO)
877                {
878                    /* ZERO is the placeholder for "don't store result" */
879
880                    ThisNodeBtype = RequiredBtypes;
881                    break;
882                }
883
884                if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER)
885                {
886                    /*
887                     * This is the case where an original reference to a resource
888                     * descriptor field has been replaced by an (Integer) offset.
889                     * These named fields are supported at compile-time only;
890                     * the names are not passed to the interpreter (via the AML).
891                     */
892                    if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
893                        (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
894                    {
895                        AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD, ArgOp, NULL);
896                    }
897                    else
898                    {
899                        AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, NULL);
900                    }
901                    break;
902                }
903
904                if ((ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) ||
905                    (ArgOp->Asl.ParseOpcode == PARSEOP_DEREFOF))
906                {
907                    break;
908                }
909
910                ThisNodeBtype = RequiredBtypes;
911                break;
912
913
914            case ARGI_REFERENCE:            /* References */
915            case ARGI_INTEGER_REF:
916            case ARGI_OBJECT_REF:
917            case ARGI_DEVICE_REF:
918
919                switch (ArgOp->Asl.ParseOpcode)
920                {
921                case PARSEOP_LOCAL0:
922                case PARSEOP_LOCAL1:
923                case PARSEOP_LOCAL2:
924                case PARSEOP_LOCAL3:
925                case PARSEOP_LOCAL4:
926                case PARSEOP_LOCAL5:
927                case PARSEOP_LOCAL6:
928                case PARSEOP_LOCAL7:
929
930                    /* TBD: implement analysis of current value (type) of the local */
931                    /* For now, just treat any local as a typematch */
932
933                    /*ThisNodeBtype = RequiredBtypes;*/
934                    break;
935
936                case PARSEOP_ARG0:
937                case PARSEOP_ARG1:
938                case PARSEOP_ARG2:
939                case PARSEOP_ARG3:
940                case PARSEOP_ARG4:
941                case PARSEOP_ARG5:
942                case PARSEOP_ARG6:
943
944                    /* Hard to analyze argument types, sow we won't */
945                    /* For now, just treat any arg as a typematch */
946
947                    /* ThisNodeBtype = RequiredBtypes; */
948                    break;
949
950                case PARSEOP_DEBUG:
951                    break;
952
953                case PARSEOP_REFOF:
954                case PARSEOP_INDEX:
955                default:
956                    break;
957
958                }
959                break;
960
961            case ARGI_INTEGER:
962            default:
963                break;
964            }
965
966
967            CommonBtypes = ThisNodeBtype & RequiredBtypes;
968
969            if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
970            {
971                if (AnIsInternalMethod (ArgOp))
972                {
973                    return (AE_OK);
974                }
975
976                /* Check a method call for a valid return value */
977
978                AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
979                    RequiredBtypes, ThisNodeBtype);
980            }
981
982            /*
983             * Now check if the actual type(s) match at least one
984             * bit to the required type
985             */
986            else if (!CommonBtypes)
987            {
988                /* No match -- this is a type mismatch error */
989
990                AnFormatBtype (StringBuffer, ThisNodeBtype);
991                AnFormatBtype (StringBuffer2, RequiredBtypes);
992
993                sprintf (MsgBuffer, "[%s] found, %s operator requires [%s]",
994                            StringBuffer, OpInfo->Name, StringBuffer2);
995
996                AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer);
997            }
998
999        NextArgument:
1000            ArgOp = ArgOp->Asl.Next;
1001            INCREMENT_ARG_LIST (RuntimeArgTypes2);
1002        }
1003        break;
1004
1005    default:
1006        break;
1007    }
1008
1009    return (AE_OK);
1010}
1011
1012
1013/*******************************************************************************
1014 *
1015 * FUNCTION:    AnOtherSemanticAnalysisWalkBegin
1016 *
1017 * PARAMETERS:  ASL_WALK_CALLBACK
1018 *
1019 * RETURN:      Status
1020 *
1021 * DESCRIPTION: Descending callback for the analysis walk. Checks for
1022 *              miscellaneous issues in the code.
1023 *
1024 ******************************************************************************/
1025
1026ACPI_STATUS
1027AnOtherSemanticAnalysisWalkBegin (
1028    ACPI_PARSE_OBJECT       *Op,
1029    UINT32                  Level,
1030    void                    *Context)
1031{
1032    ACPI_PARSE_OBJECT       *ArgNode;
1033    ACPI_PARSE_OBJECT       *PrevArgNode = NULL;
1034    const ACPI_OPCODE_INFO  *OpInfo;
1035
1036
1037    OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
1038
1039    /*
1040     * Determine if an execution class operator actually does something by
1041     * checking if it has a target and/or the function return value is used.
1042     * (Target is optional, so a standalone statement can actually do nothing.)
1043     */
1044    if ((OpInfo->Class == AML_CLASS_EXECUTE) &&
1045        (OpInfo->Flags & AML_HAS_RETVAL) &&
1046        (!AnIsResultUsed (Op)))
1047    {
1048        if (OpInfo->Flags & AML_HAS_TARGET)
1049        {
1050            /*
1051             * Find the target node, it is always the last child. If the traget
1052             * is not specified in the ASL, a default node of type Zero was
1053             * created by the parser.
1054             */
1055            ArgNode = Op->Asl.Child;
1056            while (ArgNode->Asl.Next)
1057            {
1058                PrevArgNode = ArgNode;
1059                ArgNode = ArgNode->Asl.Next;
1060            }
1061
1062            /* Divide() is the only weird case, it has two targets */
1063
1064            if (Op->Asl.AmlOpcode == AML_DIVIDE_OP)
1065            {
1066                if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) &&
1067                    (PrevArgNode) &&
1068                    (PrevArgNode->Asl.ParseOpcode == PARSEOP_ZERO))
1069                {
1070                    AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED,
1071                        Op, Op->Asl.ExternalName);
1072                }
1073            }
1074            else if (ArgNode->Asl.ParseOpcode == PARSEOP_ZERO)
1075            {
1076                AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED,
1077                    Op, Op->Asl.ExternalName);
1078            }
1079        }
1080        else
1081        {
1082            /*
1083             * Has no target and the result is not used. Only a couple opcodes
1084             * can have this combination.
1085             */
1086            switch (Op->Asl.ParseOpcode)
1087            {
1088            case PARSEOP_ACQUIRE:
1089            case PARSEOP_WAIT:
1090            case PARSEOP_LOADTABLE:
1091                break;
1092
1093            default:
1094                AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED,
1095                    Op, Op->Asl.ExternalName);
1096                break;
1097            }
1098        }
1099    }
1100
1101
1102    /*
1103     * Semantic checks for individual ASL operators
1104     */
1105    switch (Op->Asl.ParseOpcode)
1106    {
1107    case PARSEOP_ACQUIRE:
1108    case PARSEOP_WAIT:
1109        /*
1110         * Emit a warning if the timeout parameter for these operators is not
1111         * ACPI_WAIT_FOREVER, and the result value from the operator is not
1112         * checked, meaning that a timeout could happen, but the code
1113         * would not know about it.
1114         */
1115
1116        /* First child is the namepath, 2nd child is timeout */
1117
1118        ArgNode = Op->Asl.Child;
1119        ArgNode = ArgNode->Asl.Next;
1120
1121        /*
1122         * Check for the WAIT_FOREVER case - defined by the ACPI spec to be
1123         * 0xFFFF or greater
1124         */
1125        if (((ArgNode->Asl.ParseOpcode == PARSEOP_WORDCONST) ||
1126             (ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER))  &&
1127             (ArgNode->Asl.Value.Integer >= (UINT64) ACPI_WAIT_FOREVER))
1128        {
1129            break;
1130        }
1131
1132        /*
1133         * The operation could timeout. If the return value is not used
1134         * (indicates timeout occurred), issue a warning
1135         */
1136        if (!AnIsResultUsed (Op))
1137        {
1138            AslError (ASL_WARNING, ASL_MSG_TIMEOUT, ArgNode,
1139                Op->Asl.ExternalName);
1140        }
1141        break;
1142
1143    case PARSEOP_CREATEFIELD:
1144        /*
1145         * Check for a zero Length (NumBits) operand. NumBits is the 3rd operand
1146         */
1147        ArgNode = Op->Asl.Child;
1148        ArgNode = ArgNode->Asl.Next;
1149        ArgNode = ArgNode->Asl.Next;
1150
1151        if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) ||
1152           ((ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER) &&
1153            (ArgNode->Asl.Value.Integer == 0)))
1154        {
1155            AslError (ASL_ERROR, ASL_MSG_NON_ZERO, ArgNode, NULL);
1156        }
1157        break;
1158
1159    default:
1160        break;
1161    }
1162
1163    return (AE_OK);
1164}
1165