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