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