Home | History | Annotate | Line # | Download | only in compiler
aslwalks.c revision 1.1.1.7
      1 /******************************************************************************
      2  *
      3  * Module Name: aslwalks.c - Miscellaneous analytical parse tree walks
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2016, Intel Corp.
      9  * All rights reserved.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions, and the following disclaimer,
     16  *    without modification.
     17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
     18  *    substantially similar to the "NO WARRANTY" disclaimer below
     19  *    ("Disclaimer") and any redistribution must be conditioned upon
     20  *    including a substantially similar Disclaimer requirement for further
     21  *    binary redistribution.
     22  * 3. Neither the names of the above-listed copyright holders nor the names
     23  *    of any contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * Alternatively, this software may be distributed under the terms of the
     27  * GNU General Public License ("GPL") version 2 as published by the Free
     28  * Software Foundation.
     29  *
     30  * NO WARRANTY
     31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
     34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     41  * POSSIBILITY OF SUCH DAMAGES.
     42  */
     43 
     44 #include "aslcompiler.h"
     45 #include "aslcompiler.y.h"
     46 #include "acparser.h"
     47 #include "amlcode.h"
     48 
     49 
     50 #define _COMPONENT          ACPI_COMPILER
     51         ACPI_MODULE_NAME    ("aslwalks")
     52 
     53 
     54 /* Local prototypes */
     55 
     56 static void
     57 AnAnalyzeStoreOperator (
     58     ACPI_PARSE_OBJECT       *Op);
     59 
     60 
     61 /*******************************************************************************
     62  *
     63  * FUNCTION:    AnMethodTypingWalkEnd
     64  *
     65  * PARAMETERS:  ASL_WALK_CALLBACK
     66  *
     67  * RETURN:      Status
     68  *
     69  * DESCRIPTION: Ascending callback for typing walk. Complete the method
     70  *              return analysis. Check methods for:
     71  *              1) Initialized local variables
     72  *              2) Valid arguments
     73  *              3) Return types
     74  *
     75  ******************************************************************************/
     76 
     77 ACPI_STATUS
     78 AnMethodTypingWalkEnd (
     79     ACPI_PARSE_OBJECT       *Op,
     80     UINT32                  Level,
     81     void                    *Context)
     82 {
     83     UINT32                  ThisOpBtype;
     84 
     85 
     86     switch (Op->Asl.ParseOpcode)
     87     {
     88     case PARSEOP_METHOD:
     89 
     90         Op->Asl.CompileFlags |= NODE_METHOD_TYPED;
     91         break;
     92 
     93     case PARSEOP_RETURN:
     94 
     95         if ((Op->Asl.Child) &&
     96             (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
     97         {
     98             ThisOpBtype = AnGetBtype (Op->Asl.Child);
     99 
    100             if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_METHODCALL) &&
    101                 (ThisOpBtype == (ACPI_UINT32_MAX -1)))
    102             {
    103                 /*
    104                  * The called method is untyped at this time (typically a
    105                  * forward reference).
    106                  *
    107                  * Check for a recursive method call first. Note: the
    108                  * Child->Node will be null if the method has not been
    109                  * resolved.
    110                  */
    111                 if (Op->Asl.Child->Asl.Node &&
    112                     (Op->Asl.ParentMethod != Op->Asl.Child->Asl.Node->Op))
    113                 {
    114                     /* We must type the method here */
    115 
    116                     TrWalkParseTree (Op->Asl.Child->Asl.Node->Op,
    117                         ASL_WALK_VISIT_UPWARD, NULL,
    118                         AnMethodTypingWalkEnd, NULL);
    119 
    120                     ThisOpBtype = AnGetBtype (Op->Asl.Child);
    121                 }
    122             }
    123 
    124             /* Returns a value, save the value type */
    125 
    126             if (Op->Asl.ParentMethod)
    127             {
    128                 Op->Asl.ParentMethod->Asl.AcpiBtype |= ThisOpBtype;
    129             }
    130         }
    131         break;
    132 
    133     default:
    134 
    135         break;
    136     }
    137 
    138     return (AE_OK);
    139 }
    140 
    141 
    142 /*******************************************************************************
    143  *
    144  * FUNCTION:    AnOperandTypecheckWalkEnd
    145  *
    146  * PARAMETERS:  ASL_WALK_CALLBACK
    147  *
    148  * RETURN:      Status
    149  *
    150  * DESCRIPTION: Ascending callback for analysis walk. Complete method
    151  *              return analysis.
    152  *
    153  ******************************************************************************/
    154 
    155 ACPI_STATUS
    156 AnOperandTypecheckWalkEnd (
    157     ACPI_PARSE_OBJECT       *Op,
    158     UINT32                  Level,
    159     void                    *Context)
    160 {
    161     const ACPI_OPCODE_INFO  *OpInfo;
    162     UINT32                  RuntimeArgTypes;
    163     UINT32                  RuntimeArgTypes2;
    164     UINT32                  RequiredBtypes;
    165     UINT32                  ThisNodeBtype;
    166     UINT32                  CommonBtypes;
    167     UINT32                  OpcodeClass;
    168     ACPI_PARSE_OBJECT       *ArgOp;
    169     UINT32                  ArgType;
    170 
    171 
    172     switch (Op->Asl.AmlOpcode)
    173     {
    174     case AML_RAW_DATA_BYTE:
    175     case AML_RAW_DATA_WORD:
    176     case AML_RAW_DATA_DWORD:
    177     case AML_RAW_DATA_QWORD:
    178     case AML_RAW_DATA_BUFFER:
    179     case AML_RAW_DATA_CHAIN:
    180     case AML_PACKAGE_LENGTH:
    181     case AML_UNASSIGNED_OPCODE:
    182     case AML_DEFAULT_ARG_OP:
    183 
    184         /* Ignore the internal (compiler-only) AML opcodes */
    185 
    186         return (AE_OK);
    187 
    188     default:
    189 
    190         break;
    191     }
    192 
    193     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
    194     if (!OpInfo)
    195     {
    196         return (AE_OK);
    197     }
    198 
    199     ArgOp = Op->Asl.Child;
    200     OpcodeClass = OpInfo->Class;
    201     RuntimeArgTypes = OpInfo->RuntimeArgs;
    202 
    203 #ifdef ASL_ERROR_NAMED_OBJECT_IN_WHILE
    204     /*
    205      * Update 11/2008: In practice, we can't perform this check. A simple
    206      * analysis is not sufficient. Also, it can cause errors when compiling
    207      * disassembled code because of the way Switch operators are implemented
    208      * (a While(One) loop with a named temp variable created within.)
    209      */
    210 
    211     /*
    212      * If we are creating a named object, check if we are within a while loop
    213      * by checking if the parent is a WHILE op. This is a simple analysis, but
    214      * probably sufficient for many cases.
    215      *
    216      * Allow Scope(), Buffer(), and Package().
    217      */
    218     if (((OpcodeClass == AML_CLASS_NAMED_OBJECT) && (Op->Asl.AmlOpcode != AML_SCOPE_OP)) ||
    219         ((OpcodeClass == AML_CLASS_CREATE) && (OpInfo->Flags & AML_NSNODE)))
    220     {
    221         if (Op->Asl.Parent->Asl.AmlOpcode == AML_WHILE_OP)
    222         {
    223             AslError (ASL_ERROR, ASL_MSG_NAMED_OBJECT_IN_WHILE, Op, NULL);
    224         }
    225     }
    226 #endif
    227 
    228     /*
    229      * Special case for control opcodes IF/RETURN/WHILE since they
    230      * have no runtime arg list (at this time)
    231      */
    232     switch (Op->Asl.AmlOpcode)
    233     {
    234     case AML_IF_OP:
    235     case AML_WHILE_OP:
    236     case AML_RETURN_OP:
    237 
    238         if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
    239         {
    240             /* Check for an internal method */
    241 
    242             if (AnIsInternalMethod (ArgOp))
    243             {
    244                 return (AE_OK);
    245             }
    246 
    247             /* The lone arg is a method call, check it */
    248 
    249             RequiredBtypes = AnMapArgTypeToBtype (ARGI_INTEGER);
    250             if (Op->Asl.AmlOpcode == AML_RETURN_OP)
    251             {
    252                 RequiredBtypes = 0xFFFFFFFF;
    253             }
    254 
    255             ThisNodeBtype = AnGetBtype (ArgOp);
    256             if (ThisNodeBtype == ACPI_UINT32_MAX)
    257             {
    258                 return (AE_OK);
    259             }
    260 
    261             AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
    262                 RequiredBtypes, ThisNodeBtype);
    263         }
    264         return (AE_OK);
    265 
    266     case AML_EXTERNAL_OP:
    267         /*
    268          * Not really a "runtime" opcode since it used by disassembler only.
    269          * The parser will find any issues with the operands.
    270          */
    271         return (AE_OK);
    272 
    273     default:
    274 
    275         break;
    276     }
    277 
    278     /* Ignore the non-executable opcodes */
    279 
    280     if (RuntimeArgTypes == ARGI_INVALID_OPCODE)
    281     {
    282         return (AE_OK);
    283     }
    284 
    285     /*
    286      * Special handling for certain opcodes.
    287      */
    288     switch (Op->Asl.AmlOpcode)
    289     {
    290         /* BankField has one TermArg */
    291 
    292     case AML_BANK_FIELD_OP:
    293 
    294         OpcodeClass = AML_CLASS_EXECUTE;
    295         ArgOp = ArgOp->Asl.Next;
    296         ArgOp = ArgOp->Asl.Next;
    297         break;
    298 
    299         /* Operation Region has 2 TermArgs */
    300 
    301     case AML_REGION_OP:
    302 
    303         OpcodeClass = AML_CLASS_EXECUTE;
    304         ArgOp = ArgOp->Asl.Next;
    305         ArgOp = ArgOp->Asl.Next;
    306         break;
    307 
    308         /* DataTableRegion has 3 TermArgs */
    309 
    310     case AML_DATA_REGION_OP:
    311 
    312         OpcodeClass = AML_CLASS_EXECUTE;
    313         ArgOp = ArgOp->Asl.Next;
    314         break;
    315 
    316         /* Buffers/Packages have a length that is a TermArg */
    317 
    318     case AML_BUFFER_OP:
    319     case AML_PACKAGE_OP:
    320     case AML_VAR_PACKAGE_OP:
    321 
    322             /* If length is a constant, we are done */
    323 
    324         if ((ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER) ||
    325             (ArgOp->Asl.ParseOpcode == PARSEOP_RAW_DATA))
    326         {
    327             return (AE_OK);
    328         }
    329         break;
    330 
    331         /* Store can write any object to the Debug object */
    332 
    333     case AML_STORE_OP:
    334         /*
    335          * If this is a Store() to the Debug object, we don't need
    336          * to perform any further validation -- because a Store of
    337          * any object to Debug is permitted and supported.
    338          */
    339         if (ArgOp->Asl.Next->Asl.AmlOpcode == AML_DEBUG_OP)
    340         {
    341             return (AE_OK);
    342         }
    343         break;
    344 
    345     default:
    346         break;
    347     }
    348 
    349     switch (OpcodeClass)
    350     {
    351     case AML_CLASS_EXECUTE:
    352     case AML_CLASS_CREATE:
    353     case AML_CLASS_CONTROL:
    354     case AML_CLASS_RETURN_VALUE:
    355 
    356         /* Reverse the runtime argument list */
    357 
    358         RuntimeArgTypes2 = 0;
    359         while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes)))
    360         {
    361             RuntimeArgTypes2 <<= ARG_TYPE_WIDTH;
    362             RuntimeArgTypes2 |= ArgType;
    363             INCREMENT_ARG_LIST (RuntimeArgTypes);
    364         }
    365 
    366         /* Typecheck each argument */
    367 
    368         while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2)))
    369         {
    370             /* Get the required type(s) for the argument */
    371 
    372             RequiredBtypes = AnMapArgTypeToBtype (ArgType);
    373 
    374             if (!ArgOp)
    375             {
    376                 AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
    377                     "Null ArgOp in argument loop");
    378                 AslAbort ();
    379             }
    380 
    381             /* Get the actual type of the argument */
    382 
    383             ThisNodeBtype = AnGetBtype (ArgOp);
    384             if (ThisNodeBtype == ACPI_UINT32_MAX)
    385             {
    386                 goto NextArgument;
    387             }
    388 
    389             /* Examine the arg based on the required type of the arg */
    390 
    391             switch (ArgType)
    392             {
    393             case ARGI_TARGETREF:
    394 
    395                 if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO)
    396                 {
    397                     /* ZERO is the placeholder for "don't store result" */
    398 
    399                     ThisNodeBtype = RequiredBtypes;
    400                     break;
    401                 }
    402 
    403             /* Fallthrough */
    404 
    405             case ARGI_STORE_TARGET:
    406 
    407                 if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER)
    408                 {
    409                     /*
    410                      * This is the case where an original reference to a resource
    411                      * descriptor field has been replaced by an (Integer) offset.
    412                      * These named fields are supported at compile-time only;
    413                      * the names are not passed to the interpreter (via the AML).
    414                      */
    415                     if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
    416                         (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
    417                     {
    418                         AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD,
    419                             ArgOp, NULL);
    420                     }
    421                     else
    422                     {
    423                         AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE,
    424                             ArgOp, NULL);
    425                     }
    426                 }
    427                 break;
    428 
    429 
    430 #ifdef __FUTURE_IMPLEMENTATION
    431 /*
    432  * Possible future typechecking support
    433  */
    434             case ARGI_REFERENCE:            /* References */
    435             case ARGI_INTEGER_REF:
    436             case ARGI_OBJECT_REF:
    437             case ARGI_DEVICE_REF:
    438 
    439                 switch (ArgOp->Asl.ParseOpcode)
    440                 {
    441                 case PARSEOP_LOCAL0:
    442                 case PARSEOP_LOCAL1:
    443                 case PARSEOP_LOCAL2:
    444                 case PARSEOP_LOCAL3:
    445                 case PARSEOP_LOCAL4:
    446                 case PARSEOP_LOCAL5:
    447                 case PARSEOP_LOCAL6:
    448                 case PARSEOP_LOCAL7:
    449 
    450                     /* TBD: implement analysis of current value (type) of the local */
    451                     /* For now, just treat any local as a typematch */
    452 
    453                     /*ThisNodeBtype = RequiredBtypes;*/
    454                     break;
    455 
    456                 case PARSEOP_ARG0:
    457                 case PARSEOP_ARG1:
    458                 case PARSEOP_ARG2:
    459                 case PARSEOP_ARG3:
    460                 case PARSEOP_ARG4:
    461                 case PARSEOP_ARG5:
    462                 case PARSEOP_ARG6:
    463 
    464                     /* Hard to analyze argument types, so we won't */
    465                     /* for now. Just treat any arg as a typematch */
    466 
    467                     /* ThisNodeBtype = RequiredBtypes; */
    468                     break;
    469 
    470                 case PARSEOP_DEBUG:
    471                 case PARSEOP_REFOF:
    472                 case PARSEOP_INDEX:
    473                 default:
    474 
    475                     break;
    476                 }
    477                 break;
    478 #endif
    479             case ARGI_INTEGER:
    480             default:
    481 
    482                 break;
    483             }
    484 
    485 
    486             /* Check for a type mismatch (required versus actual) */
    487 
    488             CommonBtypes = ThisNodeBtype & RequiredBtypes;
    489 
    490             if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
    491             {
    492                 if (AnIsInternalMethod (ArgOp))
    493                 {
    494                     return (AE_OK);
    495                 }
    496 
    497                 /* Check a method call for a valid return value */
    498 
    499                 AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
    500                     RequiredBtypes, ThisNodeBtype);
    501             }
    502 
    503             /*
    504              * Now check if the actual type(s) match at least one
    505              * bit to the required type
    506              */
    507             else if (!CommonBtypes)
    508             {
    509                 /* No match -- this is a type mismatch error */
    510 
    511                 AnFormatBtype (StringBuffer, ThisNodeBtype);
    512                 AnFormatBtype (StringBuffer2, RequiredBtypes);
    513 
    514                 sprintf (MsgBuffer, "[%s] found, %s operator requires [%s]",
    515                     StringBuffer, OpInfo->Name, StringBuffer2);
    516 
    517                 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE,
    518                     ArgOp, MsgBuffer);
    519             }
    520 
    521         NextArgument:
    522             ArgOp = ArgOp->Asl.Next;
    523             INCREMENT_ARG_LIST (RuntimeArgTypes2);
    524         }
    525         break;
    526 
    527     default:
    528 
    529         break;
    530     }
    531 
    532     return (AE_OK);
    533 }
    534 
    535 
    536 /*******************************************************************************
    537  *
    538  * FUNCTION:    AnOtherSemanticAnalysisWalkBegin
    539  *
    540  * PARAMETERS:  ASL_WALK_CALLBACK
    541  *
    542  * RETURN:      Status
    543  *
    544  * DESCRIPTION: Descending callback for the analysis walk. Checks for
    545  *              miscellaneous issues in the code.
    546  *
    547  ******************************************************************************/
    548 
    549 ACPI_STATUS
    550 AnOtherSemanticAnalysisWalkBegin (
    551     ACPI_PARSE_OBJECT       *Op,
    552     UINT32                  Level,
    553     void                    *Context)
    554 {
    555     ACPI_PARSE_OBJECT       *ArgOp;
    556     ACPI_PARSE_OBJECT       *PrevArgOp = NULL;
    557     const ACPI_OPCODE_INFO  *OpInfo;
    558     ACPI_NAMESPACE_NODE     *Node;
    559 
    560 
    561     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
    562 
    563 
    564     /*
    565      * Determine if an execution class operator actually does something by
    566      * checking if it has a target and/or the function return value is used.
    567      * (Target is optional, so a standalone statement can actually do nothing.)
    568      */
    569     if ((OpInfo->Class == AML_CLASS_EXECUTE) &&
    570         (OpInfo->Flags & AML_HAS_RETVAL) &&
    571         (!AnIsResultUsed (Op)))
    572     {
    573         if (OpInfo->Flags & AML_HAS_TARGET)
    574         {
    575             /*
    576              * Find the target node, it is always the last child. If the target
    577              * is not specified in the ASL, a default node of type Zero was
    578              * created by the parser.
    579              */
    580             ArgOp = Op->Asl.Child;
    581             while (ArgOp->Asl.Next)
    582             {
    583                 PrevArgOp = ArgOp;
    584                 ArgOp = ArgOp->Asl.Next;
    585             }
    586 
    587             /* Divide() is the only weird case, it has two targets */
    588 
    589             if (Op->Asl.AmlOpcode == AML_DIVIDE_OP)
    590             {
    591                 if ((ArgOp->Asl.ParseOpcode == PARSEOP_ZERO) &&
    592                     (PrevArgOp) &&
    593                     (PrevArgOp->Asl.ParseOpcode == PARSEOP_ZERO))
    594                 {
    595                     AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
    596                         Op, Op->Asl.ExternalName);
    597                 }
    598             }
    599 
    600             else if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO)
    601             {
    602                 AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
    603                     Op, Op->Asl.ExternalName);
    604             }
    605         }
    606         else
    607         {
    608             /*
    609              * Has no target and the result is not used. Only a couple opcodes
    610              * can have this combination.
    611              */
    612             switch (Op->Asl.ParseOpcode)
    613             {
    614             case PARSEOP_ACQUIRE:
    615             case PARSEOP_WAIT:
    616             case PARSEOP_LOADTABLE:
    617 
    618                 break;
    619 
    620             default:
    621 
    622                 AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
    623                     Op, Op->Asl.ExternalName);
    624                 break;
    625             }
    626         }
    627     }
    628 
    629 
    630     /*
    631      * Semantic checks for individual ASL operators
    632      */
    633     switch (Op->Asl.ParseOpcode)
    634     {
    635     case PARSEOP_STORE:
    636 
    637         if (Gbl_DoTypechecking)
    638         {
    639             AnAnalyzeStoreOperator (Op);
    640         }
    641         break;
    642 
    643 
    644     case PARSEOP_ACQUIRE:
    645     case PARSEOP_WAIT:
    646         /*
    647          * Emit a warning if the timeout parameter for these operators is not
    648          * ACPI_WAIT_FOREVER, and the result value from the operator is not
    649          * checked, meaning that a timeout could happen, but the code
    650          * would not know about it.
    651          */
    652 
    653         /* First child is the namepath, 2nd child is timeout */
    654 
    655         ArgOp = Op->Asl.Child;
    656         ArgOp = ArgOp->Asl.Next;
    657 
    658         /*
    659          * Check for the WAIT_FOREVER case - defined by the ACPI spec to be
    660          * 0xFFFF or greater
    661          */
    662         if (((ArgOp->Asl.ParseOpcode == PARSEOP_WORDCONST) ||
    663              (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER))  &&
    664              (ArgOp->Asl.Value.Integer >= (UINT64) ACPI_WAIT_FOREVER))
    665         {
    666             break;
    667         }
    668 
    669         /*
    670          * The operation could timeout. If the return value is not used
    671          * (indicates timeout occurred), issue a warning
    672          */
    673         if (!AnIsResultUsed (Op))
    674         {
    675             AslError (ASL_WARNING, ASL_MSG_TIMEOUT, ArgOp,
    676                 Op->Asl.ExternalName);
    677         }
    678         break;
    679 
    680     case PARSEOP_CREATEFIELD:
    681         /*
    682          * Check for a zero Length (NumBits) operand. NumBits is the 3rd operand
    683          */
    684         ArgOp = Op->Asl.Child;
    685         ArgOp = ArgOp->Asl.Next;
    686         ArgOp = ArgOp->Asl.Next;
    687 
    688         if ((ArgOp->Asl.ParseOpcode == PARSEOP_ZERO) ||
    689            ((ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER) &&
    690             (ArgOp->Asl.Value.Integer == 0)))
    691         {
    692             AslError (ASL_ERROR, ASL_MSG_NON_ZERO, ArgOp, NULL);
    693         }
    694         break;
    695 
    696     case PARSEOP_CONNECTION:
    697         /*
    698          * Ensure that the referenced operation region has the correct SPACE_ID.
    699          * From the grammar/parser, we know the parent is a FIELD definition.
    700          */
    701         ArgOp = Op->Asl.Parent;     /* Field definition */
    702         ArgOp = ArgOp->Asl.Child;   /* First child is the OpRegion Name */
    703         Node = ArgOp->Asl.Node;     /* OpRegion namespace node */
    704         if (!Node)
    705         {
    706             break;
    707         }
    708 
    709         ArgOp = Node->Op;           /* OpRegion definition */
    710         ArgOp = ArgOp->Asl.Child;   /* First child is the OpRegion Name */
    711         ArgOp = ArgOp->Asl.Next;    /* Next peer is the SPACE_ID (what we want) */
    712 
    713         /*
    714          * The Connection() operator is only valid for the following operation
    715          * region SpaceIds: GeneralPurposeIo and GenericSerialBus.
    716          */
    717         if ((ArgOp->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) &&
    718             (ArgOp->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS))
    719         {
    720             AslError (ASL_ERROR, ASL_MSG_CONNECTION_INVALID, Op, NULL);
    721         }
    722         break;
    723 
    724     case PARSEOP_FIELD:
    725         /*
    726          * Ensure that fields for GeneralPurposeIo and GenericSerialBus
    727          * contain at least one Connection() operator
    728          */
    729         ArgOp = Op->Asl.Child;      /* 1st child is the OpRegion Name */
    730         Node = ArgOp->Asl.Node;     /* OpRegion namespace node */
    731         if (!Node)
    732         {
    733             break;
    734         }
    735 
    736         ArgOp = Node->Op;           /* OpRegion definition */
    737         ArgOp = ArgOp->Asl.Child;   /* First child is the OpRegion Name */
    738         ArgOp = ArgOp->Asl.Next;    /* Next peer is the SPACE_ID (what we want) */
    739 
    740         /* We are only interested in GeneralPurposeIo and GenericSerialBus */
    741 
    742         if ((ArgOp->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) &&
    743             (ArgOp->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS))
    744         {
    745             break;
    746         }
    747 
    748         ArgOp = Op->Asl.Child;      /* 1st child is the OpRegion Name */
    749         ArgOp = ArgOp->Asl.Next;    /* AccessType */
    750         ArgOp = ArgOp->Asl.Next;    /* LockRule */
    751         ArgOp = ArgOp->Asl.Next;    /* UpdateRule */
    752         ArgOp = ArgOp->Asl.Next;    /* Start of FieldUnitList */
    753 
    754         /* Walk the FieldUnitList */
    755 
    756         while (ArgOp)
    757         {
    758             if (ArgOp->Asl.ParseOpcode == PARSEOP_CONNECTION)
    759             {
    760                 break;
    761             }
    762             else if (ArgOp->Asl.ParseOpcode == PARSEOP_NAMESEG)
    763             {
    764                 AslError (ASL_ERROR, ASL_MSG_CONNECTION_MISSING, ArgOp, NULL);
    765                 break;
    766             }
    767 
    768             ArgOp = ArgOp->Asl.Next;
    769         }
    770         break;
    771 
    772     default:
    773 
    774         break;
    775     }
    776 
    777     return (AE_OK);
    778 }
    779 
    780 
    781 /*******************************************************************************
    782  *
    783  * FUNCTION:    AnAnalyzeStoreOperator
    784  *
    785  * PARAMETERS:  Op                  - Store() operator
    786  *
    787  * RETURN:      None
    788  *
    789  * DESCRIPTION: Analyze a store operator. Mostly for stores to/from package
    790  *              objects where there are more restrictions than other data
    791  *              types.
    792  *
    793  ******************************************************************************/
    794 
    795 static void
    796 AnAnalyzeStoreOperator (
    797     ACPI_PARSE_OBJECT       *Op)
    798 {
    799     ACPI_NAMESPACE_NODE     *SourceNode;
    800     ACPI_NAMESPACE_NODE     *TargetNode;
    801     ACPI_PARSE_OBJECT       *SourceOperandOp;
    802     ACPI_PARSE_OBJECT       *TargetOperandOp;
    803     UINT32                  SourceOperandBtype;
    804     UINT32                  TargetOperandBtype;
    805 
    806 
    807     /* Extract the two operands for STORE */
    808 
    809     SourceOperandOp = Op->Asl.Child;
    810     TargetOperandOp = SourceOperandOp->Asl.Next;
    811 
    812     /*
    813      * Ignore these Source operand opcodes, they cannot be typechecked,
    814      * the actual result is unknown here.
    815      */
    816     switch (SourceOperandOp->Asl.ParseOpcode)
    817     {
    818     /* For these, type of the returned value is unknown at compile time */
    819 
    820     case PARSEOP_DEREFOF:
    821     case PARSEOP_METHODCALL:
    822     case PARSEOP_STORE:
    823     case PARSEOP_COPYOBJECT:
    824 
    825         return;
    826 
    827     case PARSEOP_INDEX:
    828     case PARSEOP_REFOF:
    829 
    830         if (!Gbl_EnableReferenceTypechecking)
    831         {
    832             return;
    833         }
    834 
    835         /*
    836          * These opcodes always return an object reference, and thus
    837          * the result can only be stored to a Local, Arg, or Debug.
    838          */
    839         if (TargetOperandOp->Asl.AmlOpcode == AML_DEBUG_OP)
    840         {
    841             return;
    842         }
    843 
    844         if ((TargetOperandOp->Asl.AmlOpcode < AML_LOCAL0) ||
    845             (TargetOperandOp->Asl.AmlOpcode > AML_ARG6))
    846         {
    847             AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, TargetOperandOp,
    848                 "Source [Reference], Target must be [Local/Arg/Debug]");
    849         }
    850         return;
    851 
    852     default:
    853         break;
    854     }
    855 
    856     /*
    857      * Ignore these Target operand opcodes, they cannot be typechecked
    858      */
    859     switch (TargetOperandOp->Asl.ParseOpcode)
    860     {
    861     case PARSEOP_DEBUG:
    862     case PARSEOP_DEREFOF:
    863     case PARSEOP_REFOF:
    864     case PARSEOP_INDEX:
    865 
    866         return;
    867 
    868     case PARSEOP_METHODCALL:
    869         /*
    870          * A target is not allowed to be a method call.
    871          * It is not supported by the ACPICA interpreter, nor is it
    872          * supported by the MS ASL compiler or the MS interpreter.
    873          * Although legal syntax up until ACPI 6.1, support for this
    874          * will be removed for ACPI 6.2 (02/2016)
    875          */
    876         AslError (ASL_ERROR, ASL_MSG_SYNTAX,
    877             TargetOperandOp, "Illegal method invocation as a target operand");
    878         return;
    879 
    880     default:
    881         break;
    882     }
    883 
    884     /*
    885      * Ignore typecheck for External() operands of type "UnknownObj",
    886      * we don't know the actual type (source or target).
    887      */
    888     SourceNode = SourceOperandOp->Asl.Node;
    889     if (SourceNode &&
    890         (SourceNode->Flags & ANOBJ_IS_EXTERNAL) &&
    891         (SourceNode->Type == ACPI_TYPE_ANY))
    892     {
    893         return;
    894     }
    895 
    896     TargetNode = TargetOperandOp->Asl.Node;
    897     if (TargetNode &&
    898         (TargetNode->Flags & ANOBJ_IS_EXTERNAL) &&
    899         (TargetNode->Type == ACPI_TYPE_ANY))
    900     {
    901         return;
    902     }
    903 
    904     /*
    905      * A NULL node with a namepath AML opcode indicates non-existent
    906      * name. Just return, the error message is generated elsewhere.
    907      */
    908     if ((!SourceNode && (SourceOperandOp->Asl.AmlOpcode == AML_INT_NAMEPATH_OP)) ||
    909         (!TargetNode && (TargetOperandOp->Asl.AmlOpcode == AML_INT_NAMEPATH_OP)))
    910     {
    911         return;
    912     }
    913 
    914     /*
    915      * Simple check for source same as target via NS node.
    916      * -- Could be expanded to locals and args.
    917      */
    918     if (SourceNode && TargetNode)
    919     {
    920         if (SourceNode == TargetNode)
    921         {
    922             AslError (ASL_WARNING, ASL_MSG_DUPLICATE_ITEM,
    923                 TargetOperandOp, "Source is the same as Target");
    924             return;
    925         }
    926     }
    927 
    928     /* Ignore typecheck if either source or target is a local or arg */
    929 
    930     if ((SourceOperandOp->Asl.AmlOpcode >= AML_LOCAL0) &&
    931         (SourceOperandOp->Asl.AmlOpcode <= AML_ARG6))
    932     {
    933         return; /* Cannot type a local/arg at compile time */
    934     }
    935 
    936     if ((TargetOperandOp->Asl.AmlOpcode >= AML_LOCAL0) &&
    937         (TargetOperandOp->Asl.AmlOpcode <= AML_ARG6))
    938     {
    939         return; /* Cannot type a local/arg at compile time */
    940     }
    941 
    942     /*
    943      * Package objects are a special case because they cannot by implicitly
    944      * converted to/from anything. Check for these two illegal cases:
    945      *
    946      *      Store (non-package, package)
    947      *      Store (package, non-package)
    948      */
    949     SourceOperandBtype = AnGetBtype (SourceOperandOp);
    950     TargetOperandBtype = AnGetBtype (TargetOperandOp);
    951 
    952     /* Check source first for (package, non-package) case */
    953 
    954     if (SourceOperandBtype & ACPI_BTYPE_PACKAGE)
    955     {
    956         /* If Source is PACKAGE-->Target must be PACKAGE */
    957 
    958         if (!(TargetOperandBtype & ACPI_BTYPE_PACKAGE))
    959         {
    960             AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, TargetOperandOp,
    961                 "Source is [Package], Target must be a package also");
    962         }
    963     }
    964 
    965     /* Else check target for (non-package, package) case */
    966 
    967     else if (TargetOperandBtype & ACPI_BTYPE_PACKAGE)
    968     {
    969         /* If Target is PACKAGE, Source must be PACKAGE */
    970 
    971         if (!(SourceOperandBtype & ACPI_BTYPE_PACKAGE))
    972         {
    973             AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, SourceOperandOp,
    974                 "Target is [Package], Source must be a package also");
    975         }
    976     }
    977 }
    978