Home | History | Annotate | Line # | Download | only in compiler
aslmethod.c revision 1.1.1.6
      1 /******************************************************************************
      2  *
      3  * Module Name: aslmethod.c - Control method analysis walk
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2016, 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 #include "aslcompiler.h"
     45 #include "aslcompiler.y.h"
     46 #include "acparser.h"
     47 #include "amlcode.h"
     48 
     49 
     50 #define _COMPONENT          ACPI_COMPILER
     51         ACPI_MODULE_NAME    ("aslmethod")
     52 
     53 
     54 /* Local prototypes */
     55 
     56 static void
     57 MtCheckNamedObjectInMethod (
     58     ACPI_PARSE_OBJECT       *Op,
     59     ASL_METHOD_INFO         *MethodInfo);
     60 
     61 
     62 /*******************************************************************************
     63  *
     64  * FUNCTION:    MtMethodAnalysisWalkBegin
     65  *
     66  * PARAMETERS:  ASL_WALK_CALLBACK
     67  *
     68  * RETURN:      Status
     69  *
     70  * DESCRIPTION: Descending callback for the analysis walk. Check methods for:
     71  *              1) Initialized local variables
     72  *              2) Valid arguments
     73  *              3) Return types
     74  *
     75  ******************************************************************************/
     76 
     77 ACPI_STATUS
     78 MtMethodAnalysisWalkBegin (
     79     ACPI_PARSE_OBJECT       *Op,
     80     UINT32                  Level,
     81     void                    *Context)
     82 {
     83     ASL_ANALYSIS_WALK_INFO  *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
     84     ASL_METHOD_INFO         *MethodInfo = WalkInfo->MethodStack;
     85     ACPI_PARSE_OBJECT       *Next;
     86     UINT32                  RegisterNumber;
     87     UINT32                  i;
     88     char                    LocalName[] = "Local0";
     89     char                    ArgName[] = "Arg0";
     90     ACPI_PARSE_OBJECT       *ArgNode;
     91     ACPI_PARSE_OBJECT       *NextType;
     92     ACPI_PARSE_OBJECT       *NextParamType;
     93     UINT8                   ActualArgs = 0;
     94 
     95 
     96     /* Build cross-reference output file if requested */
     97 
     98     if (Gbl_CrossReferenceOutput)
     99     {
    100         OtXrefWalkPart1 (Op, Level, MethodInfo);
    101     }
    102 
    103     switch (Op->Asl.ParseOpcode)
    104     {
    105     case PARSEOP_METHOD:
    106 
    107         TotalMethods++;
    108 
    109         /* Create and init method info */
    110 
    111         MethodInfo = UtLocalCalloc (sizeof (ASL_METHOD_INFO));
    112         MethodInfo->Next = WalkInfo->MethodStack;
    113         MethodInfo->Op = Op;
    114 
    115         WalkInfo->MethodStack = MethodInfo;
    116 
    117         /*
    118          * Special handling for _PSx methods. Dependency rules (same scope):
    119          *
    120          * 1) _PS0 - One of these must exist: _PS1, _PS2, _PS3
    121          * 2) _PS1/_PS2/_PS3: A _PS0 must exist
    122          */
    123         if (ACPI_COMPARE_NAME (METHOD_NAME__PS0, Op->Asl.NameSeg))
    124         {
    125             /* For _PS0, one of _PS1/_PS2/_PS3 must exist */
    126 
    127             if ((!ApFindNameInScope (METHOD_NAME__PS1, Op)) &&
    128                 (!ApFindNameInScope (METHOD_NAME__PS2, Op)) &&
    129                 (!ApFindNameInScope (METHOD_NAME__PS3, Op)))
    130             {
    131                 AslError (ASL_WARNING, ASL_MSG_MISSING_DEPENDENCY, Op,
    132                     "_PS0 requires one of _PS1/_PS2/_PS3 in same scope");
    133             }
    134         }
    135         else if (
    136             ACPI_COMPARE_NAME (METHOD_NAME__PS1, Op->Asl.NameSeg) ||
    137             ACPI_COMPARE_NAME (METHOD_NAME__PS2, Op->Asl.NameSeg) ||
    138             ACPI_COMPARE_NAME (METHOD_NAME__PS3, Op->Asl.NameSeg))
    139         {
    140             /* For _PS1/_PS2/_PS3, a _PS0 must exist */
    141 
    142             if (!ApFindNameInScope (METHOD_NAME__PS0, Op))
    143             {
    144                 sprintf (MsgBuffer,
    145                     "%4.4s requires _PS0 in same scope", Op->Asl.NameSeg);
    146 
    147                 AslError (ASL_WARNING, ASL_MSG_MISSING_DEPENDENCY, Op,
    148                     MsgBuffer);
    149             }
    150         }
    151 
    152         /* Get the name node */
    153 
    154         Next = Op->Asl.Child;
    155 
    156         /* Get the NumArguments node */
    157 
    158         Next = Next->Asl.Next;
    159         MethodInfo->NumArguments = (UINT8)
    160             (((UINT8) Next->Asl.Value.Integer) & 0x07);
    161 
    162         /* Get the SerializeRule and SyncLevel nodes, ignored here */
    163 
    164         Next = Next->Asl.Next;
    165         MethodInfo->ShouldBeSerialized = (UINT8) Next->Asl.Value.Integer;
    166 
    167         Next = Next->Asl.Next;
    168         ArgNode = Next;
    169 
    170         /* Get the ReturnType node */
    171 
    172         Next = Next->Asl.Next;
    173 
    174         NextType = Next->Asl.Child;
    175         while (NextType)
    176         {
    177             /* Get and map each of the ReturnTypes */
    178 
    179             MethodInfo->ValidReturnTypes |= AnMapObjTypeToBtype (NextType);
    180             NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    181             NextType = NextType->Asl.Next;
    182         }
    183 
    184         /* Get the ParameterType node */
    185 
    186         Next = Next->Asl.Next;
    187 
    188         NextType = Next->Asl.Child;
    189         while (NextType)
    190         {
    191             if (NextType->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
    192             {
    193                 NextParamType = NextType->Asl.Child;
    194                 while (NextParamType)
    195                 {
    196                     MethodInfo->ValidArgTypes[ActualArgs] |=
    197                         AnMapObjTypeToBtype (NextParamType);
    198 
    199                     NextParamType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    200                     NextParamType = NextParamType->Asl.Next;
    201                 }
    202             }
    203             else
    204             {
    205                 MethodInfo->ValidArgTypes[ActualArgs] =
    206                     AnMapObjTypeToBtype (NextType);
    207 
    208                 NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    209                 ActualArgs++;
    210             }
    211 
    212             NextType = NextType->Asl.Next;
    213         }
    214 
    215         if ((MethodInfo->NumArguments) &&
    216             (MethodInfo->NumArguments != ActualArgs))
    217         {
    218             /* error: Param list did not match number of args */
    219         }
    220 
    221         /* Allow numarguments == 0 for Function() */
    222 
    223         if ((!MethodInfo->NumArguments) && (ActualArgs))
    224         {
    225             MethodInfo->NumArguments = ActualArgs;
    226             ArgNode->Asl.Value.Integer |= ActualArgs;
    227         }
    228 
    229         /*
    230          * Actual arguments are initialized at method entry.
    231          * All other ArgX "registers" can be used as locals, so we
    232          * track their initialization.
    233          */
    234         for (i = 0; i < MethodInfo->NumArguments; i++)
    235         {
    236             MethodInfo->ArgInitialized[i] = TRUE;
    237         }
    238         break;
    239 
    240     case PARSEOP_METHODCALL:
    241 
    242         if (MethodInfo &&
    243            (Op->Asl.Node == MethodInfo->Op->Asl.Node))
    244         {
    245             AslError (ASL_REMARK, ASL_MSG_RECURSION, Op, Op->Asl.ExternalName);
    246         }
    247         break;
    248 
    249     case PARSEOP_LOCAL0:
    250     case PARSEOP_LOCAL1:
    251     case PARSEOP_LOCAL2:
    252     case PARSEOP_LOCAL3:
    253     case PARSEOP_LOCAL4:
    254     case PARSEOP_LOCAL5:
    255     case PARSEOP_LOCAL6:
    256     case PARSEOP_LOCAL7:
    257 
    258         if (!MethodInfo)
    259         {
    260             /*
    261              * Local was used outside a control method, or there was an error
    262              * in the method declaration.
    263              */
    264             AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD,
    265                 Op, Op->Asl.ExternalName);
    266             return (AE_ERROR);
    267         }
    268 
    269         RegisterNumber = (Op->Asl.AmlOpcode & 0x0007);
    270 
    271         /*
    272          * If the local is being used as a target, mark the local
    273          * initialized
    274          */
    275         if (Op->Asl.CompileFlags & NODE_IS_TARGET)
    276         {
    277             MethodInfo->LocalInitialized[RegisterNumber] = TRUE;
    278         }
    279 
    280         /*
    281          * Otherwise, this is a reference, check if the local
    282          * has been previously initialized.
    283          *
    284          * The only operator that accepts an uninitialized value is ObjectType()
    285          */
    286         else if ((!MethodInfo->LocalInitialized[RegisterNumber]) &&
    287                  (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
    288         {
    289             LocalName[strlen (LocalName) -1] = (char) (RegisterNumber + 0x30);
    290             AslError (ASL_ERROR, ASL_MSG_LOCAL_INIT, Op, LocalName);
    291         }
    292         break;
    293 
    294     case PARSEOP_ARG0:
    295     case PARSEOP_ARG1:
    296     case PARSEOP_ARG2:
    297     case PARSEOP_ARG3:
    298     case PARSEOP_ARG4:
    299     case PARSEOP_ARG5:
    300     case PARSEOP_ARG6:
    301 
    302         if (!MethodInfo)
    303         {
    304             /*
    305              * Arg was used outside a control method, or there was an error
    306              * in the method declaration.
    307              */
    308             AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD,
    309                 Op, Op->Asl.ExternalName);
    310             return (AE_ERROR);
    311         }
    312 
    313         RegisterNumber = (Op->Asl.AmlOpcode & 0x000F) - 8;
    314         ArgName[strlen (ArgName) -1] = (char) (RegisterNumber + 0x30);
    315 
    316         /*
    317          * If the Arg is being used as a target, mark the local
    318          * initialized
    319          */
    320         if (Op->Asl.CompileFlags & NODE_IS_TARGET)
    321         {
    322             MethodInfo->ArgInitialized[RegisterNumber] = TRUE;
    323         }
    324 
    325         /*
    326          * Otherwise, this is a reference, check if the Arg
    327          * has been previously initialized.
    328          *
    329          * The only operator that accepts an uninitialized value is ObjectType()
    330          */
    331         else if ((!MethodInfo->ArgInitialized[RegisterNumber]) &&
    332             (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
    333         {
    334             AslError (ASL_ERROR, ASL_MSG_ARG_INIT, Op, ArgName);
    335         }
    336 
    337         /* Flag this arg if it is not a "real" argument to the method */
    338 
    339         if (RegisterNumber >= MethodInfo->NumArguments)
    340         {
    341             AslError (ASL_REMARK, ASL_MSG_NOT_PARAMETER, Op, ArgName);
    342         }
    343         break;
    344 
    345     case PARSEOP_RETURN:
    346 
    347         if (!MethodInfo)
    348         {
    349             /*
    350              * Probably was an error in the method declaration,
    351              * no additional error here
    352              */
    353             ACPI_WARNING ((AE_INFO, "%p, No parent method", Op));
    354             return (AE_ERROR);
    355         }
    356 
    357         /*
    358          * A child indicates a possible return value. A simple Return or
    359          * Return() is marked with NODE_IS_NULL_RETURN by the parser so
    360          * that it is not counted as a "real" return-with-value, although
    361          * the AML code that is actually emitted is Return(0). The AML
    362          * definition of Return has a required parameter, so we are
    363          * forced to convert a null return to Return(0).
    364          */
    365         if ((Op->Asl.Child) &&
    366             (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
    367             (!(Op->Asl.Child->Asl.CompileFlags & NODE_IS_NULL_RETURN)))
    368         {
    369             MethodInfo->NumReturnWithValue++;
    370         }
    371         else
    372         {
    373             MethodInfo->NumReturnNoValue++;
    374         }
    375         break;
    376 
    377     case PARSEOP_BREAK:
    378     case PARSEOP_CONTINUE:
    379 
    380         Next = Op->Asl.Parent;
    381         while (Next)
    382         {
    383             if (Next->Asl.ParseOpcode == PARSEOP_WHILE)
    384             {
    385                 break;
    386             }
    387             Next = Next->Asl.Parent;
    388         }
    389 
    390         if (!Next)
    391         {
    392             AslError (ASL_ERROR, ASL_MSG_NO_WHILE, Op, NULL);
    393         }
    394         break;
    395 
    396     case PARSEOP_STALL:
    397 
    398         /* We can range check if the argument is an integer */
    399 
    400         if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
    401             (Op->Asl.Child->Asl.Value.Integer > ACPI_UINT8_MAX))
    402         {
    403             AslError (ASL_ERROR, ASL_MSG_INVALID_TIME, Op, NULL);
    404         }
    405         break;
    406 
    407     case PARSEOP_DEVICE:
    408 
    409         if (!ApFindNameInDeviceTree (METHOD_NAME__HID, Op) &&
    410             !ApFindNameInDeviceTree (METHOD_NAME__ADR, Op))
    411         {
    412             AslError (ASL_WARNING, ASL_MSG_MISSING_DEPENDENCY, Op,
    413                 "Device object requires a _HID or _ADR in same scope");
    414         }
    415         break;
    416 
    417     case PARSEOP_EVENT:
    418     case PARSEOP_MUTEX:
    419     case PARSEOP_OPERATIONREGION:
    420     case PARSEOP_POWERRESOURCE:
    421     case PARSEOP_PROCESSOR:
    422     case PARSEOP_THERMALZONE:
    423 
    424         /*
    425          * The first operand is a name to be created in the namespace.
    426          * Check against the reserved list.
    427          */
    428         i = ApCheckForPredefinedName (Op, Op->Asl.NameSeg);
    429         if (i < ACPI_VALID_RESERVED_NAME_MAX)
    430         {
    431             AslError (ASL_ERROR, ASL_MSG_RESERVED_USE,
    432                 Op, Op->Asl.ExternalName);
    433         }
    434         break;
    435 
    436     case PARSEOP_NAME:
    437 
    438         /* Typecheck any predefined names statically defined with Name() */
    439 
    440         ApCheckForPredefinedObject (Op, Op->Asl.NameSeg);
    441 
    442         /* Special typechecking for _HID */
    443 
    444         if (!strcmp (METHOD_NAME__HID, Op->Asl.NameSeg))
    445         {
    446             Next = Op->Asl.Child->Asl.Next;
    447             AnCheckId (Next, ASL_TYPE_HID);
    448         }
    449 
    450         /* Special typechecking for _CID */
    451 
    452         else if (!strcmp (METHOD_NAME__CID, Op->Asl.NameSeg))
    453         {
    454             Next = Op->Asl.Child->Asl.Next;
    455 
    456             if ((Next->Asl.ParseOpcode == PARSEOP_PACKAGE) ||
    457                 (Next->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE))
    458             {
    459                 Next = Next->Asl.Child;
    460                 while (Next)
    461                 {
    462                     AnCheckId (Next, ASL_TYPE_CID);
    463                     Next = Next->Asl.Next;
    464                 }
    465             }
    466             else
    467             {
    468                 AnCheckId (Next, ASL_TYPE_CID);
    469             }
    470         }
    471 
    472         break;
    473 
    474     default:
    475 
    476         break;
    477     }
    478 
    479     /* Check for named object creation within a non-serialized method */
    480 
    481     MtCheckNamedObjectInMethod (Op, MethodInfo);
    482     return (AE_OK);
    483 }
    484 
    485 
    486 /*******************************************************************************
    487  *
    488  * FUNCTION:    MtCheckNamedObjectInMethod
    489  *
    490  * PARAMETERS:  Op                  - Current parser op
    491  *              MethodInfo          - Info for method being parsed
    492  *
    493  * RETURN:      None
    494  *
    495  * DESCRIPTION: Detect if a non-serialized method is creating a named object,
    496  *              which could possibly cause problems if two threads execute
    497  *              the method concurrently. Emit a remark in this case.
    498  *
    499  ******************************************************************************/
    500 
    501 static void
    502 MtCheckNamedObjectInMethod (
    503     ACPI_PARSE_OBJECT       *Op,
    504     ASL_METHOD_INFO         *MethodInfo)
    505 {
    506     const ACPI_OPCODE_INFO  *OpInfo;
    507 
    508 
    509     /* We don't care about actual method declarations or scopes */
    510 
    511     if ((Op->Asl.AmlOpcode == AML_METHOD_OP) ||
    512         (Op->Asl.AmlOpcode == AML_SCOPE_OP))
    513     {
    514         return;
    515     }
    516 
    517     /* Determine if we are creating a named object */
    518 
    519     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
    520     if (OpInfo->Class == AML_CLASS_NAMED_OBJECT)
    521     {
    522         /*
    523          * If we have a named object created within a non-serialized method,
    524          * emit a remark that the method should be serialized.
    525          *
    526          * Reason: If a thread blocks within the method for any reason, and
    527          * another thread enters the method, the method will fail because an
    528          * attempt will be made to create the same object twice.
    529          */
    530         if (MethodInfo && !MethodInfo->ShouldBeSerialized)
    531         {
    532             AslError (ASL_REMARK, ASL_MSG_SERIALIZED_REQUIRED, MethodInfo->Op,
    533                 "due to creation of named objects within");
    534 
    535             /* Emit message only ONCE per method */
    536 
    537             MethodInfo->ShouldBeSerialized = TRUE;
    538         }
    539     }
    540 }
    541 
    542 
    543 /*******************************************************************************
    544  *
    545  * FUNCTION:    MtMethodAnalysisWalkEnd
    546  *
    547  * PARAMETERS:  ASL_WALK_CALLBACK
    548  *
    549  * RETURN:      Status
    550  *
    551  * DESCRIPTION: Ascending callback for analysis walk. Complete method
    552  *              return analysis.
    553  *
    554  ******************************************************************************/
    555 
    556 ACPI_STATUS
    557 MtMethodAnalysisWalkEnd (
    558     ACPI_PARSE_OBJECT       *Op,
    559     UINT32                  Level,
    560     void                    *Context)
    561 {
    562     ASL_ANALYSIS_WALK_INFO  *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
    563     ASL_METHOD_INFO         *MethodInfo = WalkInfo->MethodStack;
    564 
    565 
    566     switch (Op->Asl.ParseOpcode)
    567     {
    568     case PARSEOP_METHOD:
    569     case PARSEOP_RETURN:
    570 
    571         if (!MethodInfo)
    572         {
    573             printf ("No method info for method! [%s]\n", Op->Asl.Namepath);
    574             AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
    575                 "No method info for this method");
    576 
    577             CmCleanupAndExit ();
    578             return (AE_AML_INTERNAL);
    579         }
    580         break;
    581 
    582     default:
    583 
    584         break;
    585     }
    586 
    587     switch (Op->Asl.ParseOpcode)
    588     {
    589     case PARSEOP_METHOD:
    590 
    591         WalkInfo->MethodStack = MethodInfo->Next;
    592 
    593         /*
    594          * Check if there is no return statement at the end of the
    595          * method AND we can actually get there -- i.e., the execution
    596          * of the method can possibly terminate without a return statement.
    597          */
    598         if ((!AnLastStatementIsReturn (Op)) &&
    599             (!(Op->Asl.CompileFlags & NODE_HAS_NO_EXIT)))
    600         {
    601             /*
    602              * No return statement, and execution can possibly exit
    603              * via this path. This is equivalent to Return ()
    604              */
    605             MethodInfo->NumReturnNoValue++;
    606         }
    607 
    608         /*
    609          * Check for case where some return statements have a return value
    610          * and some do not. Exit without a return statement is a return with
    611          * no value
    612          */
    613         if (MethodInfo->NumReturnNoValue &&
    614             MethodInfo->NumReturnWithValue)
    615         {
    616             AslError (ASL_WARNING, ASL_MSG_RETURN_TYPES, Op,
    617                 Op->Asl.ExternalName);
    618         }
    619 
    620         /*
    621          * If there are any RETURN() statements with no value, or there is a
    622          * control path that allows the method to exit without a return value,
    623          * we mark the method as a method that does not return a value. This
    624          * knowledge can be used to check method invocations that expect a
    625          * returned value.
    626          */
    627         if (MethodInfo->NumReturnNoValue)
    628         {
    629             if (MethodInfo->NumReturnWithValue)
    630             {
    631                 Op->Asl.CompileFlags |= NODE_METHOD_SOME_NO_RETVAL;
    632             }
    633             else
    634             {
    635                 Op->Asl.CompileFlags |= NODE_METHOD_NO_RETVAL;
    636             }
    637         }
    638 
    639         /*
    640          * Check predefined method names for correct return behavior
    641          * and correct number of arguments. Also, some special checks
    642          * For GPE and _REG methods.
    643          */
    644         if (ApCheckForPredefinedMethod (Op, MethodInfo))
    645         {
    646             /* Special check for two names like _L01 and _E01 in same scope */
    647 
    648             ApCheckForGpeNameConflict (Op);
    649 
    650             /*
    651              * Special check for _REG: Must have an operation region definition
    652              * within the same scope!
    653              */
    654             ApCheckRegMethod (Op);
    655         }
    656 
    657         ACPI_FREE (MethodInfo);
    658         break;
    659 
    660     case PARSEOP_NAME:
    661 
    662          /* Special check for two names like _L01 and _E01 in same scope */
    663 
    664         ApCheckForGpeNameConflict (Op);
    665         break;
    666 
    667     case PARSEOP_RETURN:
    668 
    669         /*
    670          * If the parent is a predefined method name, attempt to typecheck
    671          * the return value. Only static types can be validated.
    672          */
    673         ApCheckPredefinedReturnValue (Op, MethodInfo);
    674 
    675         /*
    676          * The parent block does not "exit" and continue execution -- the
    677          * method is terminated here with the Return() statement.
    678          */
    679         Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
    680 
    681         /* Used in the "typing" pass later */
    682 
    683         Op->Asl.ParentMethod = MethodInfo->Op;
    684 
    685         /*
    686          * If there is a peer node after the return statement, then this
    687          * node is unreachable code -- i.e., it won't be executed because of
    688          * the preceding Return() statement.
    689          */
    690         if (Op->Asl.Next)
    691         {
    692             AslError (ASL_WARNING, ASL_MSG_UNREACHABLE_CODE,
    693                 Op->Asl.Next, NULL);
    694         }
    695         break;
    696 
    697     case PARSEOP_IF:
    698 
    699         if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
    700             (Op->Asl.Next) &&
    701             (Op->Asl.Next->Asl.ParseOpcode == PARSEOP_ELSE))
    702         {
    703             /*
    704              * This IF has a corresponding ELSE. The IF block has no exit,
    705              * (it contains an unconditional Return)
    706              * mark the ELSE block to remember this fact.
    707              */
    708             Op->Asl.Next->Asl.CompileFlags |= NODE_IF_HAS_NO_EXIT;
    709         }
    710         break;
    711 
    712     case PARSEOP_ELSE:
    713 
    714         if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
    715             (Op->Asl.CompileFlags & NODE_IF_HAS_NO_EXIT))
    716         {
    717             /*
    718              * This ELSE block has no exit and the corresponding IF block
    719              * has no exit either. Therefore, the parent node has no exit.
    720              */
    721             Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
    722         }
    723         break;
    724 
    725 
    726     default:
    727 
    728         if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
    729             (Op->Asl.Parent))
    730         {
    731             /* If this node has no exit, then the parent has no exit either */
    732 
    733             Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
    734         }
    735         break;
    736     }
    737 
    738     return (AE_OK);
    739 }
    740