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