Home | History | Annotate | Line # | Download | only in compiler
aslmethod.c revision 1.1.1.15
      1 /******************************************************************************
      2  *
      3  * Module Name: aslmethod.c - Control method analysis walk
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2020, 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 "acnamesp.h"
     47 #include "acparser.h"
     48 #include "amlcode.h"
     49 
     50 
     51 #define _COMPONENT          ACPI_COMPILER
     52         ACPI_MODULE_NAME    ("aslmethod")
     53 
     54 
     55 /* Local prototypes */
     56 
     57 static void
     58 MtCheckNamedObjectInMethod (
     59     ACPI_PARSE_OBJECT       *Op,
     60     ASL_METHOD_INFO         *MethodInfo);
     61 
     62 static void
     63 MtCheckStaticOperationRegionInMethod (
     64     ACPI_PARSE_OBJECT       *Op);
     65 
     66 
     67 /*******************************************************************************
     68  *
     69  * FUNCTION:    MtMethodAnalysisWalkBegin
     70  *
     71  * PARAMETERS:  ASL_WALK_CALLBACK
     72  *
     73  * RETURN:      Status
     74  *
     75  * DESCRIPTION: Descending callback for the analysis walk. Check methods for:
     76  *              1) Initialized local variables
     77  *              2) Valid arguments
     78  *              3) Return types
     79  *
     80  ******************************************************************************/
     81 
     82 ACPI_STATUS
     83 MtMethodAnalysisWalkBegin (
     84     ACPI_PARSE_OBJECT       *Op,
     85     UINT32                  Level,
     86     void                    *Context)
     87 {
     88     ASL_ANALYSIS_WALK_INFO  *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
     89     ASL_METHOD_INFO         *MethodInfo = WalkInfo->MethodStack;
     90     ACPI_PARSE_OBJECT       *Next;
     91     UINT32                  RegisterNumber;
     92     UINT32                  i;
     93     char                    LocalName[] = "Local0";
     94     char                    ArgName[] = "Arg0";
     95     ACPI_PARSE_OBJECT       *ArgNode;
     96     ACPI_PARSE_OBJECT       *NextType;
     97     UINT8                   ActualArgs = 0;
     98     BOOLEAN                 HidExists;
     99     BOOLEAN                 AdrExists;
    100 
    101 
    102     /* Build cross-reference output file if requested */
    103 
    104     if (AslGbl_CrossReferenceOutput)
    105     {
    106         OtXrefWalkPart1 (Op, Level, MethodInfo);
    107     }
    108 
    109     switch (Op->Asl.ParseOpcode)
    110     {
    111     case PARSEOP_METHOD:
    112 
    113         AslGbl_TotalMethods++;
    114 
    115         /* Create and init method info */
    116 
    117         MethodInfo = UtLocalCalloc (sizeof (ASL_METHOD_INFO));
    118         MethodInfo->Next = WalkInfo->MethodStack;
    119         MethodInfo->Op = Op;
    120 
    121         WalkInfo->MethodStack = MethodInfo;
    122 
    123         /*
    124          * Special handling for _PSx methods. Dependency rules (same scope):
    125          *
    126          * 1) _PS0 - One of these must exist: _PS1, _PS2, _PS3
    127          * 2) _PS1/_PS2/_PS3: A _PS0 must exist
    128          */
    129         if (ACPI_COMPARE_NAMESEG (METHOD_NAME__PS0, Op->Asl.NameSeg))
    130         {
    131             /* For _PS0, one of _PS1/_PS2/_PS3 must exist */
    132 
    133             if ((!ApFindNameInScope (METHOD_NAME__PS1, Op)) &&
    134                 (!ApFindNameInScope (METHOD_NAME__PS2, Op)) &&
    135                 (!ApFindNameInScope (METHOD_NAME__PS3, Op)))
    136             {
    137                 AslError (ASL_WARNING, ASL_MSG_MISSING_DEPENDENCY, Op,
    138                     "_PS0 requires one of _PS1/_PS2/_PS3 in same scope");
    139             }
    140         }
    141         else if (
    142             ACPI_COMPARE_NAMESEG (METHOD_NAME__PS1, Op->Asl.NameSeg) ||
    143             ACPI_COMPARE_NAMESEG (METHOD_NAME__PS2, Op->Asl.NameSeg) ||
    144             ACPI_COMPARE_NAMESEG (METHOD_NAME__PS3, Op->Asl.NameSeg))
    145         {
    146             /* For _PS1/_PS2/_PS3, a _PS0 must exist */
    147 
    148             if (!ApFindNameInScope (METHOD_NAME__PS0, Op))
    149             {
    150                 sprintf (AslGbl_MsgBuffer,
    151                     "%4.4s requires _PS0 in same scope", Op->Asl.NameSeg);
    152 
    153                 AslError (ASL_WARNING, ASL_MSG_MISSING_DEPENDENCY, Op,
    154                     AslGbl_MsgBuffer);
    155             }
    156         }
    157 
    158         /* Get the name node */
    159 
    160         Next = Op->Asl.Child;
    161 
    162         /* Get the NumArguments node */
    163 
    164         Next = Next->Asl.Next;
    165         MethodInfo->NumArguments = (UINT8)
    166             (((UINT8) Next->Asl.Value.Integer) & 0x07);
    167 
    168         /* Get the SerializeRule and SyncLevel nodes, ignored here */
    169 
    170         Next = Next->Asl.Next;
    171         MethodInfo->ShouldBeSerialized = (UINT8) Next->Asl.Value.Integer;
    172 
    173         Next = Next->Asl.Next;
    174         ArgNode = Next;
    175 
    176         /* Get the ReturnType node */
    177 
    178         Next = Next->Asl.Next;
    179 
    180         NextType = Next->Asl.Child;
    181 
    182         MethodInfo->ValidReturnTypes = MtProcessTypeOp (NextType);
    183 
    184         /* Get the ParameterType node */
    185 
    186         Next = Next->Asl.Next;
    187 
    188         NextType = Next->Asl.Child;
    189         if (!NextType)
    190         {
    191             /*
    192              * The optional parameter types list was omitted  at the source
    193              * level. Use the Argument count parameter instead.
    194              */
    195             ActualArgs = MethodInfo->NumArguments;
    196         }
    197         else
    198         {
    199             ActualArgs = MtProcessParameterTypeList (NextType,
    200                 MethodInfo->ValidArgTypes);
    201             MethodInfo->NumArguments = ActualArgs;
    202             ArgNode->Asl.Value.Integer |= ActualArgs;
    203         }
    204 
    205         if ((MethodInfo->NumArguments) &&
    206             (MethodInfo->NumArguments != ActualArgs))
    207         {
    208             sprintf (AslGbl_MsgBuffer,
    209                 "Length = %u", ActualArgs);
    210             AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_MISMATCH,
    211                 Op->Asl.Child->Asl.Next, AslGbl_MsgBuffer);
    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         /* Check for a recursive method call */
    236 
    237         if (MethodInfo &&
    238            (Op->Asl.Node == MethodInfo->Op->Asl.Node))
    239         {
    240             if (MethodInfo->CreatesNamedObjects)
    241             {
    242                 /*
    243                  * This is an error, as it will fail at runtime on all ACPI
    244                  * implementations. Any named object declarations will be
    245                  * executed twice, causing failure the second time. Note,
    246                  * this is independent of whether the method is declared
    247                  * Serialized, because the same thread is attempting to
    248                  * reenter the method, and this will always succeed.
    249                  */
    250                 AslDualParseOpError (ASL_ERROR, ASL_MSG_ILLEGAL_RECURSION, Op,
    251                     Op->Asl.Value.String, ASL_MSG_FOUND_HERE, MethodInfo->Op,
    252                     MethodInfo->Op->Asl.ExternalName);
    253             }
    254             else
    255             {
    256                 /* Method does not create objects, issue a remark */
    257 
    258                 AslError (ASL_REMARK, ASL_MSG_RECURSION, Op, Op->Asl.ExternalName);
    259             }
    260         }
    261         break;
    262 
    263     case PARSEOP_LOCAL0:
    264     case PARSEOP_LOCAL1:
    265     case PARSEOP_LOCAL2:
    266     case PARSEOP_LOCAL3:
    267     case PARSEOP_LOCAL4:
    268     case PARSEOP_LOCAL5:
    269     case PARSEOP_LOCAL6:
    270     case PARSEOP_LOCAL7:
    271 
    272         if (!MethodInfo)
    273         {
    274             /*
    275              * Local was used outside a control method, or there was an error
    276              * in the method declaration.
    277              */
    278             AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD,
    279                 Op, Op->Asl.ExternalName);
    280             return (AE_ERROR);
    281         }
    282 
    283         RegisterNumber = (Op->Asl.AmlOpcode & 0x0007);
    284 
    285         /*
    286          * If the local is being used as a target, mark the local
    287          * initialized
    288          */
    289         if (Op->Asl.CompileFlags & OP_IS_TARGET)
    290         {
    291             MethodInfo->LocalInitialized[RegisterNumber] = TRUE;
    292         }
    293 
    294         /*
    295          * Otherwise, this is a reference, check if the local
    296          * has been previously initialized.
    297          *
    298          * The only operator that accepts an uninitialized value is ObjectType()
    299          */
    300         else if ((!MethodInfo->LocalInitialized[RegisterNumber]) &&
    301                  (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
    302         {
    303             LocalName[strlen (LocalName) -1] = (char) (RegisterNumber + 0x30);
    304             AslError (ASL_ERROR, ASL_MSG_LOCAL_INIT, Op, LocalName);
    305         }
    306         break;
    307 
    308     case PARSEOP_ARG0:
    309     case PARSEOP_ARG1:
    310     case PARSEOP_ARG2:
    311     case PARSEOP_ARG3:
    312     case PARSEOP_ARG4:
    313     case PARSEOP_ARG5:
    314     case PARSEOP_ARG6:
    315 
    316         if (!MethodInfo)
    317         {
    318             /*
    319              * Arg was used outside a control method, or there was an error
    320              * in the method declaration.
    321              */
    322             AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD,
    323                 Op, Op->Asl.ExternalName);
    324             return (AE_ERROR);
    325         }
    326 
    327         RegisterNumber = (Op->Asl.AmlOpcode & 0x000F) - 8;
    328         ArgName[strlen (ArgName) -1] = (char) (RegisterNumber + 0x30);
    329 
    330         /*
    331          * If the Arg is being used as a target, mark the local
    332          * initialized
    333          */
    334         if (Op->Asl.CompileFlags & OP_IS_TARGET)
    335         {
    336             MethodInfo->ArgInitialized[RegisterNumber] = TRUE;
    337         }
    338 
    339         /*
    340          * Otherwise, this is a reference, check if the Arg
    341          * has been previously initialized.
    342          *
    343          * The only operator that accepts an uninitialized value is ObjectType()
    344          */
    345         else if ((!MethodInfo->ArgInitialized[RegisterNumber]) &&
    346             (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
    347         {
    348             AslError (ASL_ERROR, ASL_MSG_ARG_INIT, Op, ArgName);
    349         }
    350 
    351         /* Flag this arg if it is not a "real" argument to the method */
    352 
    353         if (RegisterNumber >= MethodInfo->NumArguments)
    354         {
    355             AslError (ASL_REMARK, ASL_MSG_NOT_PARAMETER, Op, ArgName);
    356         }
    357         break;
    358 
    359     case PARSEOP_RETURN:
    360 
    361         if (!MethodInfo)
    362         {
    363             /*
    364              * Probably was an error in the method declaration,
    365              * no additional error here
    366              */
    367             ACPI_WARNING ((AE_INFO, "%p, No parent method", Op));
    368             return (AE_ERROR);
    369         }
    370 
    371         /*
    372          * A child indicates a possible return value. A simple Return or
    373          * Return() is marked with OP_IS_NULL_RETURN by the parser so
    374          * that it is not counted as a "real" return-with-value, although
    375          * the AML code that is actually emitted is Return(0). The AML
    376          * definition of Return has a required parameter, so we are
    377          * forced to convert a null return to Return(0).
    378          */
    379         if ((Op->Asl.Child) &&
    380             (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
    381             (!(Op->Asl.Child->Asl.CompileFlags & OP_IS_NULL_RETURN)))
    382         {
    383             MethodInfo->NumReturnWithValue++;
    384         }
    385         else
    386         {
    387             MethodInfo->NumReturnNoValue++;
    388         }
    389         break;
    390 
    391     case PARSEOP_BREAK:
    392     case PARSEOP_CONTINUE:
    393 
    394         Next = Op->Asl.Parent;
    395         while (Next)
    396         {
    397             if (Next->Asl.ParseOpcode == PARSEOP_WHILE)
    398             {
    399                 break;
    400             }
    401             Next = Next->Asl.Parent;
    402         }
    403 
    404         if (!Next)
    405         {
    406             AslError (ASL_ERROR, ASL_MSG_NO_WHILE, Op, NULL);
    407         }
    408         break;
    409 
    410     case PARSEOP_STALL:
    411 
    412         /* We can range check if the argument is an integer */
    413 
    414         if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
    415             (Op->Asl.Child->Asl.Value.Integer > ACPI_UINT8_MAX))
    416         {
    417             AslError (ASL_ERROR, ASL_MSG_INVALID_TIME, Op, NULL);
    418         }
    419         break;
    420 
    421     case PARSEOP_DEVICE:
    422 
    423         /* Check usage of _HID and _ADR objects */
    424 
    425         HidExists = ApFindNameInDeviceTree (METHOD_NAME__HID, Op);
    426         AdrExists = ApFindNameInDeviceTree (METHOD_NAME__ADR, Op);
    427 
    428         if (!HidExists && !AdrExists)
    429         {
    430             AslError (ASL_WARNING, ASL_MSG_MISSING_DEPENDENCY, Op,
    431                 "Device object requires a _HID or _ADR in same scope");
    432         }
    433         else if (HidExists && AdrExists)
    434         {
    435             /*
    436              * According to the ACPI spec, "A device object must contain
    437              * either an _HID object or an _ADR object, but should not contain
    438              * both".
    439              */
    440             AslError (ASL_WARNING, ASL_MSG_MULTIPLE_TYPES, Op,
    441                 "Device object requires either a _HID or _ADR, but not both");
    442         }
    443         break;
    444 
    445     case PARSEOP_EVENT:
    446     case PARSEOP_MUTEX:
    447     case PARSEOP_OPERATIONREGION:
    448     case PARSEOP_POWERRESOURCE:
    449     case PARSEOP_PROCESSOR:
    450     case PARSEOP_THERMALZONE:
    451 
    452         /*
    453          * The first operand is a name to be created in the namespace.
    454          * Check against the reserved list.
    455          */
    456         i = ApCheckForPredefinedName (Op, Op->Asl.NameSeg);
    457         if (i < ACPI_VALID_RESERVED_NAME_MAX)
    458         {
    459             AslError (ASL_ERROR, ASL_MSG_RESERVED_USE,
    460                 Op, Op->Asl.ExternalName);
    461         }
    462 
    463         MtCheckStaticOperationRegionInMethod (Op);
    464         break;
    465 
    466     case PARSEOP_NAME:
    467 
    468         /* Typecheck any predefined names statically defined with Name() */
    469 
    470         ApCheckForPredefinedObject (Op, Op->Asl.NameSeg);
    471 
    472         /* Special typechecking for _HID */
    473 
    474         if (ACPI_COMPARE_NAMESEG (METHOD_NAME__HID, Op->Asl.NameSeg))
    475         {
    476             Next = Op->Asl.Child->Asl.Next;
    477             AnCheckId (Next, ASL_TYPE_HID);
    478         }
    479 
    480         /* Special typechecking for _CID */
    481 
    482         else if (ACPI_COMPARE_NAMESEG (METHOD_NAME__CID, Op->Asl.NameSeg))
    483         {
    484             Next = Op->Asl.Child->Asl.Next;
    485 
    486             if ((Next->Asl.ParseOpcode == PARSEOP_PACKAGE) ||
    487                 (Next->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE))
    488             {
    489                 Next = Next->Asl.Child;
    490                 while (Next)
    491                 {
    492                     AnCheckId (Next, ASL_TYPE_CID);
    493                     Next = Next->Asl.Next;
    494                 }
    495             }
    496             else
    497             {
    498                 AnCheckId (Next, ASL_TYPE_CID);
    499             }
    500         }
    501 
    502         break;
    503 
    504     default:
    505 
    506         break;
    507     }
    508 
    509     /* Check for named object creation within a non-serialized method */
    510 
    511     MtCheckNamedObjectInMethod (Op, MethodInfo);
    512     return (AE_OK);
    513 }
    514 
    515 
    516 /*******************************************************************************
    517  *
    518  * FUNCTION:    MtProcessTypeOp
    519  *
    520  * PARAMETERS:  Op                  - Op representing a btype
    521  *
    522  * RETURN:      Btype represented by Op
    523  *
    524  * DESCRIPTION: Process a parse object that represents single parameter type or
    525  *              a return type in method, function, and external declarations.
    526  *
    527  ******************************************************************************/
    528 
    529 UINT32
    530 MtProcessTypeOp (
    531     ACPI_PARSE_OBJECT       *TypeOp)
    532 {
    533     UINT32                  Btype = ACPI_BTYPE_ANY;
    534 
    535 
    536     while (TypeOp)
    537     {
    538         Btype |= AnMapObjTypeToBtype (TypeOp);
    539         TypeOp->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
    540         TypeOp = TypeOp->Asl.Next;
    541     }
    542 
    543     return (Btype);
    544 }
    545 
    546 
    547 /*******************************************************************************
    548  *
    549  * FUNCTION:    MtProcessParameterTypeList
    550  *
    551  * PARAMETERS:  Op                  - Op representing a btype
    552  *
    553  * RETURN:      Btype represented by Op
    554  *
    555  * DESCRIPTION: Process a parse object that represents a parameter type list in
    556  *              method, function, and external declarations.
    557  *
    558  ******************************************************************************/
    559 
    560 UINT8
    561 MtProcessParameterTypeList (
    562     ACPI_PARSE_OBJECT       *ParamTypeOp,
    563     UINT32                  *TypeList)
    564 {
    565     UINT8                   ParameterCount = 0;
    566 
    567 
    568     if (ParamTypeOp && ParamTypeOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
    569     {
    570         /* Special case for a single parameter without braces */
    571 
    572         TypeList[ParameterCount] =
    573             MtProcessTypeOp (ParamTypeOp);
    574 
    575         return (1);
    576     }
    577 
    578     while (ParamTypeOp)
    579     {
    580         TypeList[ParameterCount] =
    581             MtProcessTypeOp (ParamTypeOp->Asl.Child);
    582 
    583         ParameterCount++;
    584         ParamTypeOp = ParamTypeOp->Asl.Next;
    585     }
    586 
    587     return (ParameterCount);
    588 }
    589 
    590 
    591 /*******************************************************************************
    592  *
    593  * FUNCTION:    MtCheckNamedObjectInMethod
    594  *
    595  * PARAMETERS:  Op                  - Current parser op
    596  *              MethodInfo          - Info for method being parsed
    597  *
    598  * RETURN:      None
    599  *
    600  * DESCRIPTION: Detect if a non-serialized method is creating a named object,
    601  *              which could possibly cause problems if two threads execute
    602  *              the method concurrently. Emit a remark in this case.
    603  *
    604  ******************************************************************************/
    605 
    606 static void
    607 MtCheckNamedObjectInMethod (
    608     ACPI_PARSE_OBJECT       *Op,
    609     ASL_METHOD_INFO         *MethodInfo)
    610 {
    611     const ACPI_OPCODE_INFO  *OpInfo;
    612     char                    *ExternalPath;
    613 
    614 
    615     /* We don't care about actual method declarations or scopes */
    616 
    617     if ((Op->Asl.AmlOpcode == AML_METHOD_OP) ||
    618         (Op->Asl.AmlOpcode == AML_SCOPE_OP))
    619     {
    620         return;
    621     }
    622 
    623     /* Determine if we are creating a named object within a method */
    624 
    625     if (!MethodInfo)
    626     {
    627         return;
    628     }
    629 
    630     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
    631     if ((OpInfo->Class == AML_CLASS_NAMED_OBJECT) && (Op->Asl.AmlOpcode != AML_FIELD_OP))
    632     {
    633         /*
    634          * 1) Mark the method as a method that creates named objects.
    635          *
    636          * 2) Issue a remark indicating the inefficiency of creating named
    637          * objects within a method (Except for compiler-emitted temporary
    638          * variables).
    639          *
    640          * 3) If the method is non-serialized, emit a remark that the method
    641          * should be serialized.
    642          *
    643          * Reason: If a thread blocks within the method for any reason, and
    644          * another thread enters the method, the method will fail because
    645          * an attempt will be made to create the same object twice.
    646          *
    647          * Note: The Field opcode is disallowed here because Field() does not
    648          * create a new named object.
    649          */
    650         ExternalPath = AcpiNsGetNormalizedPathname (MethodInfo->Op->Asl.Node, TRUE);
    651 
    652         /* No error for compiler temp variables (name starts with "_T_") */
    653 
    654         if ((Op->Asl.NameSeg[0] != '_') &&
    655             (Op->Asl.NameSeg[1] != 'T') &&
    656             (Op->Asl.NameSeg[2] != '_'))
    657         {
    658             AslError (ASL_REMARK, ASL_MSG_NAMED_OBJECT_CREATION, Op,
    659                 ExternalPath);
    660         }
    661 
    662         MethodInfo->CreatesNamedObjects = TRUE;
    663         if (!MethodInfo->ShouldBeSerialized)
    664         {
    665             AslError (ASL_REMARK, ASL_MSG_SERIALIZED_REQUIRED, MethodInfo->Op,
    666                 ExternalPath);
    667 
    668             /* Emit message only ONCE per method */
    669 
    670             MethodInfo->ShouldBeSerialized = TRUE;
    671         }
    672 
    673         if (ExternalPath)
    674         {
    675             ACPI_FREE (ExternalPath);
    676         }
    677     }
    678 }
    679 
    680 
    681 /*******************************************************************************
    682  *
    683  * FUNCTION:    MtCheckStaticOperationRegionInMethod
    684  *
    685  * PARAMETERS:  Op                  - Current parser op
    686  *
    687  * RETURN:      None
    688  *
    689  * DESCRIPTION: Warns if an Operation Region with static address or length
    690  *              is declared inside a control method
    691  *
    692  ******************************************************************************/
    693 
    694 static void
    695 MtCheckStaticOperationRegionInMethod(
    696     ACPI_PARSE_OBJECT*       Op)
    697 {
    698     ACPI_PARSE_OBJECT*       AddressOp;
    699     ACPI_PARSE_OBJECT*       LengthOp;
    700 
    701 
    702     if (Op->Asl.ParseOpcode != PARSEOP_OPERATIONREGION)
    703     {
    704         return;
    705     }
    706 
    707     /*
    708      * OperationRegion should have 4 arguments defined. At this point, we
    709      * assume that the parse tree is well-formed.
    710      */
    711     AddressOp = Op->Asl.Child->Asl.Next->Asl.Next;
    712     LengthOp = Op->Asl.Child->Asl.Next->Asl.Next->Asl.Next;
    713 
    714     if (UtGetParentMethodOp (Op) &&
    715         AddressOp->Asl.ParseOpcode == PARSEOP_INTEGER &&
    716         LengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)
    717     {
    718         /*
    719          * At this point, a static operation region declared inside of a
    720          * control method has been found. Throw a warning because this is
    721          * highly inefficient.
    722          */
    723         AslError(ASL_WARNING, ASL_MSG_STATIC_OPREGION_IN_METHOD, Op, NULL);
    724     }
    725 
    726     return;
    727 }
    728 
    729 
    730 /*******************************************************************************
    731  *
    732  * FUNCTION:    MtMethodAnalysisWalkEnd
    733  *
    734  * PARAMETERS:  ASL_WALK_CALLBACK
    735  *
    736  * RETURN:      Status
    737  *
    738  * DESCRIPTION: Ascending callback for analysis walk. Complete method
    739  *              return analysis.
    740  *
    741  ******************************************************************************/
    742 
    743 ACPI_STATUS
    744 MtMethodAnalysisWalkEnd (
    745     ACPI_PARSE_OBJECT       *Op,
    746     UINT32                  Level,
    747     void                    *Context)
    748 {
    749     ASL_ANALYSIS_WALK_INFO  *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
    750     ASL_METHOD_INFO         *MethodInfo = WalkInfo->MethodStack;
    751     char                    *ExternalPath;
    752 
    753 
    754     switch (Op->Asl.ParseOpcode)
    755     {
    756     case PARSEOP_METHOD:
    757     case PARSEOP_RETURN:
    758 
    759         if (!MethodInfo)
    760         {
    761             printf ("No method info for method! [%s]\n", Op->Asl.Namepath);
    762             AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
    763                 "No method info for this method");
    764 
    765             CmCleanupAndExit ();
    766             return (AE_AML_INTERNAL);
    767         }
    768         break;
    769 
    770     default:
    771 
    772         break;
    773     }
    774 
    775     switch (Op->Asl.ParseOpcode)
    776     {
    777     case PARSEOP_METHOD:
    778 
    779         WalkInfo->MethodStack = MethodInfo->Next;
    780 
    781         /*
    782          * Check if there is no return statement at the end of the
    783          * method AND we can actually get there -- i.e., the execution
    784          * of the method can possibly terminate without a return statement.
    785          */
    786         if ((!AnLastStatementIsReturn (Op)) &&
    787             (!(Op->Asl.CompileFlags & OP_HAS_NO_EXIT)))
    788         {
    789             /*
    790              * No return statement, and execution can possibly exit
    791              * via this path. This is equivalent to Return ()
    792              */
    793             MethodInfo->NumReturnNoValue++;
    794         }
    795 
    796         /*
    797          * Check for case where some return statements have a return value
    798          * and some do not. Exit without a return statement is a return with
    799          * no value
    800          */
    801         if (MethodInfo->NumReturnNoValue &&
    802             MethodInfo->NumReturnWithValue)
    803         {
    804             ExternalPath = AcpiNsGetNormalizedPathname (Op->Asl.Node, TRUE);
    805 
    806             AslError (ASL_WARNING, ASL_MSG_RETURN_TYPES, Op,
    807                 ExternalPath);
    808 
    809             if (ExternalPath)
    810             {
    811                 ACPI_FREE (ExternalPath);
    812             }
    813         }
    814 
    815         /*
    816          * If there are any RETURN() statements with no value, or there is a
    817          * control path that allows the method to exit without a return value,
    818          * we mark the method as a method that does not return a value. This
    819          * knowledge can be used to check method invocations that expect a
    820          * returned value.
    821          */
    822         if (MethodInfo->NumReturnNoValue)
    823         {
    824             if (MethodInfo->NumReturnWithValue)
    825             {
    826                 Op->Asl.CompileFlags |= OP_METHOD_SOME_NO_RETVAL;
    827             }
    828             else
    829             {
    830                 Op->Asl.CompileFlags |= OP_METHOD_NO_RETVAL;
    831             }
    832         }
    833 
    834         /*
    835          * Check predefined method names for correct return behavior
    836          * and correct number of arguments. Also, some special checks
    837          * For GPE and _REG methods.
    838          */
    839         if (ApCheckForPredefinedMethod (Op, MethodInfo))
    840         {
    841             /* Special check for two names like _L01 and _E01 in same scope */
    842 
    843             ApCheckForGpeNameConflict (Op);
    844 
    845             /*
    846              * Special check for _REG: Must have an operation region definition
    847              * within the same scope!
    848              */
    849             ApCheckRegMethod (Op);
    850         }
    851 
    852         ACPI_FREE (MethodInfo);
    853         break;
    854 
    855     case PARSEOP_NAME:
    856 
    857          /* Special check for two names like _L01 and _E01 in same scope */
    858 
    859         ApCheckForGpeNameConflict (Op);
    860         break;
    861 
    862     case PARSEOP_RETURN:
    863 
    864         /*
    865          * If the parent is a predefined method name, attempt to typecheck
    866          * the return value. Only static types can be validated.
    867          */
    868         ApCheckPredefinedReturnValue (Op, MethodInfo);
    869 
    870         /*
    871          * The parent block does not "exit" and continue execution -- the
    872          * method is terminated here with the Return() statement.
    873          */
    874         Op->Asl.Parent->Asl.CompileFlags |= OP_HAS_NO_EXIT;
    875 
    876         /* Used in the "typing" pass later */
    877 
    878         Op->Asl.ParentMethod = MethodInfo->Op;
    879 
    880         /*
    881          * If there is a peer node after the return statement, then this
    882          * node is unreachable code -- i.e., it won't be executed because of
    883          * the preceding Return() statement.
    884          */
    885         if (Op->Asl.Next)
    886         {
    887             AslError (ASL_WARNING, ASL_MSG_UNREACHABLE_CODE,
    888                 Op->Asl.Next, NULL);
    889         }
    890         break;
    891 
    892     case PARSEOP_IF:
    893 
    894         if ((Op->Asl.CompileFlags & OP_HAS_NO_EXIT) &&
    895             (Op->Asl.Next) &&
    896             (Op->Asl.Next->Asl.ParseOpcode == PARSEOP_ELSE))
    897         {
    898             /*
    899              * This IF has a corresponding ELSE. The IF block has no exit,
    900              * (it contains an unconditional Return)
    901              * mark the ELSE block to remember this fact.
    902              */
    903             Op->Asl.Next->Asl.CompileFlags |= OP_IF_HAS_NO_EXIT;
    904         }
    905         break;
    906 
    907     case PARSEOP_ELSE:
    908 
    909         if ((Op->Asl.CompileFlags & OP_HAS_NO_EXIT) &&
    910             (Op->Asl.CompileFlags & OP_IF_HAS_NO_EXIT))
    911         {
    912             /*
    913              * This ELSE block has no exit and the corresponding IF block
    914              * has no exit either. Therefore, the parent node has no exit.
    915              */
    916             Op->Asl.Parent->Asl.CompileFlags |= OP_HAS_NO_EXIT;
    917         }
    918         break;
    919 
    920 
    921     default:
    922 
    923         if ((Op->Asl.CompileFlags & OP_HAS_NO_EXIT) &&
    924             (Op->Asl.Parent))
    925         {
    926             /* If this node has no exit, then the parent has no exit either */
    927 
    928             Op->Asl.Parent->Asl.CompileFlags |= OP_HAS_NO_EXIT;
    929         }
    930         break;
    931     }
    932 
    933     return (AE_OK);
    934 }
    935