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