Home | History | Annotate | Line # | Download | only in compiler
asltransform.c revision 1.1.1.1
      1 
      2 /******************************************************************************
      3  *
      4  * Module Name: asltransform - Parse tree transforms
      5  *
      6  *****************************************************************************/
      7 
      8 /******************************************************************************
      9  *
     10  * 1. Copyright Notice
     11  *
     12  * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
     13  * All rights reserved.
     14  *
     15  * 2. License
     16  *
     17  * 2.1. This is your license from Intel Corp. under its intellectual property
     18  * rights.  You may have additional license terms from the party that provided
     19  * you this software, covering your right to use that party's intellectual
     20  * property rights.
     21  *
     22  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
     23  * copy of the source code appearing in this file ("Covered Code") an
     24  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
     25  * base code distributed originally by Intel ("Original Intel Code") to copy,
     26  * make derivatives, distribute, use and display any portion of the Covered
     27  * Code in any form, with the right to sublicense such rights; and
     28  *
     29  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
     30  * license (with the right to sublicense), under only those claims of Intel
     31  * patents that are infringed by the Original Intel Code, to make, use, sell,
     32  * offer to sell, and import the Covered Code and derivative works thereof
     33  * solely to the minimum extent necessary to exercise the above copyright
     34  * license, and in no event shall the patent license extend to any additions
     35  * to or modifications of the Original Intel Code.  No other license or right
     36  * is granted directly or by implication, estoppel or otherwise;
     37  *
     38  * The above copyright and patent license is granted only if the following
     39  * conditions are met:
     40  *
     41  * 3. Conditions
     42  *
     43  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
     44  * Redistribution of source code of any substantial portion of the Covered
     45  * Code or modification with rights to further distribute source must include
     46  * the above Copyright Notice, the above License, this list of Conditions,
     47  * and the following Disclaimer and Export Compliance provision.  In addition,
     48  * Licensee must cause all Covered Code to which Licensee contributes to
     49  * contain a file documenting the changes Licensee made to create that Covered
     50  * Code and the date of any change.  Licensee must include in that file the
     51  * documentation of any changes made by any predecessor Licensee.  Licensee
     52  * must include a prominent statement that the modification is derived,
     53  * directly or indirectly, from Original Intel Code.
     54  *
     55  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
     56  * Redistribution of source code of any substantial portion of the Covered
     57  * Code or modification without rights to further distribute source must
     58  * include the following Disclaimer and Export Compliance provision in the
     59  * documentation and/or other materials provided with distribution.  In
     60  * addition, Licensee may not authorize further sublicense of source of any
     61  * portion of the Covered Code, and must include terms to the effect that the
     62  * license from Licensee to its licensee is limited to the intellectual
     63  * property embodied in the software Licensee provides to its licensee, and
     64  * not to intellectual property embodied in modifications its licensee may
     65  * make.
     66  *
     67  * 3.3. Redistribution of Executable. Redistribution in executable form of any
     68  * substantial portion of the Covered Code or modification must reproduce the
     69  * above Copyright Notice, and the following Disclaimer and Export Compliance
     70  * provision in the documentation and/or other materials provided with the
     71  * distribution.
     72  *
     73  * 3.4. Intel retains all right, title, and interest in and to the Original
     74  * Intel Code.
     75  *
     76  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
     77  * Intel shall be used in advertising or otherwise to promote the sale, use or
     78  * other dealings in products derived from or relating to the Covered Code
     79  * without prior written authorization from Intel.
     80  *
     81  * 4. Disclaimer and Export Compliance
     82  *
     83  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
     84  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
     85  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
     86  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
     87  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
     88  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
     89  * PARTICULAR PURPOSE.
     90  *
     91  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
     92  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
     93  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
     94  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
     95  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
     96  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
     97  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
     98  * LIMITED REMEDY.
     99  *
    100  * 4.3. Licensee shall not export, either directly or indirectly, any of this
    101  * software or system incorporating such software without first obtaining any
    102  * required license or other approval from the U. S. Department of Commerce or
    103  * any other agency or department of the United States Government.  In the
    104  * event Licensee exports any such software from the United States or
    105  * re-exports any such software from a foreign destination, Licensee shall
    106  * ensure that the distribution and export/re-export of the software is in
    107  * compliance with all laws, regulations, orders, or other restrictions of the
    108  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
    109  * any of its subsidiaries will export/re-export any technical data, process,
    110  * software, or service, directly or indirectly, to any country for which the
    111  * United States government or any agency thereof requires an export license,
    112  * other governmental approval, or letter of assurance, without first obtaining
    113  * such license, approval or letter.
    114  *
    115  *****************************************************************************/
    116 
    117 
    118 #include "aslcompiler.h"
    119 #include "aslcompiler.y.h"
    120 
    121 #define _COMPONENT          ACPI_COMPILER
    122         ACPI_MODULE_NAME    ("asltransform")
    123 
    124 /* Local prototypes */
    125 
    126 static void
    127 TrTransformSubtree (
    128     ACPI_PARSE_OBJECT       *Op);
    129 
    130 static char *
    131 TrAmlGetNextTempName (
    132     ACPI_PARSE_OBJECT       *Op,
    133     UINT8                   *TempCount);
    134 
    135 static void
    136 TrAmlInitLineNumbers (
    137     ACPI_PARSE_OBJECT       *Op,
    138     ACPI_PARSE_OBJECT       *Neighbor);
    139 
    140 static void
    141 TrAmlInitNode (
    142     ACPI_PARSE_OBJECT       *Op,
    143     UINT16                  ParseOpcode);
    144 
    145 static void
    146 TrAmlSetSubtreeParent (
    147     ACPI_PARSE_OBJECT       *Op,
    148     ACPI_PARSE_OBJECT       *Parent);
    149 
    150 static void
    151 TrAmlInsertPeer (
    152     ACPI_PARSE_OBJECT       *Op,
    153     ACPI_PARSE_OBJECT       *NewPeer);
    154 
    155 static void
    156 TrDoDefinitionBlock (
    157     ACPI_PARSE_OBJECT       *Op);
    158 
    159 static void
    160 TrDoSwitch (
    161     ACPI_PARSE_OBJECT       *StartNode);
    162 
    163 
    164 /*******************************************************************************
    165  *
    166  * FUNCTION:    TrAmlGetNextTempName
    167  *
    168  * PARAMETERS:  Op              - Current parse op
    169  *              TempCount       - Current temporary counter. Was originally
    170  *                                per-module; Currently per method, could be
    171  *                                expanded to per-scope.
    172  *
    173  * RETURN:      A pointer to name (allocated here).
    174  *
    175  * DESCRIPTION: Generate an ACPI name of the form _T_x.  These names are
    176  *              reserved for use by the ASL compiler. (_T_0 through _T_Z)
    177  *
    178  ******************************************************************************/
    179 
    180 static char *
    181 TrAmlGetNextTempName (
    182     ACPI_PARSE_OBJECT       *Op,
    183     UINT8                   *TempCount)
    184 {
    185     char                    *TempName;
    186 
    187 
    188     if (*TempCount >= (10+26))  /* 0-35 valid: 0-9 and A-Z for TempName[3] */
    189     {
    190         /* Too many temps */
    191 
    192         AslError (ASL_ERROR, ASL_MSG_TOO_MANY_TEMPS, Op, NULL);
    193         return (NULL);
    194     }
    195 
    196     TempName = UtLocalCalloc (5);
    197 
    198     if (*TempCount < 10)    /* 0-9 */
    199     {
    200         TempName[3] = (char) (*TempCount + '0');
    201     }
    202     else                    /* 10-35: A-Z */
    203     {
    204         TempName[3] = (char) (*TempCount + ('A' - 10));
    205     }
    206     (*TempCount)++;
    207 
    208     /* First three characters are always "_T_" */
    209 
    210     TempName[0] = '_';
    211     TempName[1] = 'T';
    212     TempName[2] = '_';
    213 
    214     return (TempName);
    215 }
    216 
    217 
    218 /*******************************************************************************
    219  *
    220  * FUNCTION:    TrAmlInitLineNumbers
    221  *
    222  * PARAMETERS:  Op              - Op to be initialized
    223  *              Neighbor        - Op used for initialization values
    224  *
    225  * RETURN:      None
    226  *
    227  * DESCRIPTION: Initialized the various line numbers for a parse node.
    228  *
    229  ******************************************************************************/
    230 
    231 static void
    232 TrAmlInitLineNumbers (
    233     ACPI_PARSE_OBJECT       *Op,
    234     ACPI_PARSE_OBJECT       *Neighbor)
    235 {
    236 
    237     Op->Asl.EndLine           = Neighbor->Asl.EndLine;
    238     Op->Asl.EndLogicalLine    = Neighbor->Asl.EndLogicalLine;
    239     Op->Asl.LineNumber        = Neighbor->Asl.LineNumber;
    240     Op->Asl.LogicalByteOffset = Neighbor->Asl.LogicalByteOffset;
    241     Op->Asl.LogicalLineNumber = Neighbor->Asl.LogicalLineNumber;
    242 }
    243 
    244 
    245 /*******************************************************************************
    246  *
    247  * FUNCTION:    TrAmlInitNode
    248  *
    249  * PARAMETERS:  Op              - Op to be initialized
    250  *              ParseOpcode     - Opcode for this node
    251  *
    252  * RETURN:      None
    253  *
    254  * DESCRIPTION: Initialize a node with the parse opcode and opcode name.
    255  *
    256  ******************************************************************************/
    257 
    258 static void
    259 TrAmlInitNode (
    260     ACPI_PARSE_OBJECT       *Op,
    261     UINT16                  ParseOpcode)
    262 {
    263 
    264     Op->Asl.ParseOpcode = ParseOpcode;
    265     UtSetParseOpName (Op);
    266 }
    267 
    268 
    269 /*******************************************************************************
    270  *
    271  * FUNCTION:    TrAmlSetSubtreeParent
    272  *
    273  * PARAMETERS:  Op              - First node in a list of peer nodes
    274  *              Parent          - Parent of the subtree
    275  *
    276  * RETURN:      None
    277  *
    278  * DESCRIPTION: Set the parent for all peer nodes in a subtree
    279  *
    280  ******************************************************************************/
    281 
    282 static void
    283 TrAmlSetSubtreeParent (
    284     ACPI_PARSE_OBJECT       *Op,
    285     ACPI_PARSE_OBJECT       *Parent)
    286 {
    287     ACPI_PARSE_OBJECT       *Next;
    288 
    289 
    290     Next = Op;
    291     while (Next)
    292     {
    293         Next->Asl.Parent = Parent;
    294         Next             = Next->Asl.Next;
    295     }
    296 }
    297 
    298 
    299 /*******************************************************************************
    300  *
    301  * FUNCTION:    TrAmlInsertPeer
    302  *
    303  * PARAMETERS:  Op              - First node in a list of peer nodes
    304  *              NewPeer         - Peer node to insert
    305  *
    306  * RETURN:      None
    307  *
    308  * DESCRIPTION: Insert a new peer node into a list of peers.
    309  *
    310  ******************************************************************************/
    311 
    312 static void
    313 TrAmlInsertPeer (
    314     ACPI_PARSE_OBJECT       *Op,
    315     ACPI_PARSE_OBJECT       *NewPeer)
    316 {
    317 
    318     NewPeer->Asl.Next = Op->Asl.Next;
    319     Op->Asl.Next      = NewPeer;
    320 }
    321 
    322 
    323 /*******************************************************************************
    324  *
    325  * FUNCTION:    TrAmlTransformWalk
    326  *
    327  * PARAMETERS:  ASL_WALK_CALLBACK
    328  *
    329  * RETURN:      None
    330  *
    331  * DESCRIPTION: Parse tree walk to generate both the AML opcodes and the AML
    332  *              operands.
    333  *
    334  ******************************************************************************/
    335 
    336 ACPI_STATUS
    337 TrAmlTransformWalk (
    338     ACPI_PARSE_OBJECT       *Op,
    339     UINT32                  Level,
    340     void                    *Context)
    341 {
    342 
    343     TrTransformSubtree (Op);
    344     return (AE_OK);
    345 }
    346 
    347 
    348 /*******************************************************************************
    349  *
    350  * FUNCTION:    TrTransformSubtree
    351  *
    352  * PARAMETERS:  Op        - The parent parse node
    353  *
    354  * RETURN:      None
    355  *
    356  * DESCRIPTION: Prepare nodes to be output as AML data and operands.  The more
    357  *              complex AML opcodes require processing of the child nodes
    358  *              (arguments/operands).
    359  *
    360  ******************************************************************************/
    361 
    362 static void
    363 TrTransformSubtree (
    364     ACPI_PARSE_OBJECT           *Op)
    365 {
    366 
    367     if (Op->Asl.AmlOpcode == AML_RAW_DATA_BYTE)
    368     {
    369         return;
    370     }
    371 
    372     switch (Op->Asl.ParseOpcode)
    373     {
    374     case PARSEOP_DEFINITIONBLOCK:
    375         TrDoDefinitionBlock (Op);
    376         break;
    377 
    378     case PARSEOP_SWITCH:
    379         TrDoSwitch (Op);
    380         break;
    381 
    382     case PARSEOP_METHOD:
    383 
    384         /*
    385          * TBD: Zero the tempname (_T_x) count. Probably shouldn't be a global,
    386          * however
    387          */
    388         Gbl_TempCount = 0;
    389         break;
    390 
    391     default:
    392         /* Nothing to do here for other opcodes */
    393         break;
    394     }
    395 }
    396 
    397 
    398 /*******************************************************************************
    399  *
    400  * FUNCTION:    TrDoDefinitionBlock
    401  *
    402  * PARAMETERS:  Op        - Parse node
    403  *
    404  * RETURN:      None
    405  *
    406  * DESCRIPTION: Find the end of the definition block and set a global to this
    407  *              node.  It is used by the compiler to insert compiler-generated
    408  *              names at the root level of the namespace.
    409  *
    410  ******************************************************************************/
    411 
    412 static void
    413 TrDoDefinitionBlock (
    414     ACPI_PARSE_OBJECT       *Op)
    415 {
    416     ACPI_PARSE_OBJECT       *Next;
    417     UINT32                  i;
    418 
    419 
    420     Next = Op->Asl.Child;
    421     for (i = 0; i < 5; i++)
    422     {
    423         Next = Next->Asl.Next;
    424         if (i == 0)
    425         {
    426             /*
    427              * This is the table signature. Only the DSDT can be assumed
    428              * to be at the root of the namespace;  Therefore, namepath
    429              * optimization can only be performed on the DSDT.
    430              */
    431             if (!ACPI_COMPARE_NAME (Next->Asl.Value.String, ACPI_SIG_DSDT))
    432             {
    433                 Gbl_ReferenceOptimizationFlag = FALSE;
    434             }
    435         }
    436     }
    437 
    438     Gbl_FirstLevelInsertionNode = Next;
    439 }
    440 
    441 
    442 /*******************************************************************************
    443  *
    444  * FUNCTION:    TrDoSwitch
    445  *
    446  * PARAMETERS:  StartNode        - Parse node for SWITCH
    447  *
    448  * RETURN:      None
    449  *
    450  *
    451  * DESCRIPTION: Translate ASL SWITCH statement to if/else pairs.  There is
    452  *              no actual AML opcode for SWITCH -- it must be simulated.
    453  *
    454  ******************************************************************************/
    455 
    456 static void
    457 TrDoSwitch (
    458     ACPI_PARSE_OBJECT       *StartNode)
    459 {
    460     ACPI_PARSE_OBJECT       *Next;
    461     ACPI_PARSE_OBJECT       *CaseOp = NULL;
    462     ACPI_PARSE_OBJECT       *CaseBlock = NULL;
    463     ACPI_PARSE_OBJECT       *DefaultOp = NULL;
    464     ACPI_PARSE_OBJECT       *CurrentParentNode;
    465     ACPI_PARSE_OBJECT       *Conditional = NULL;
    466     ACPI_PARSE_OBJECT       *Predicate;
    467     ACPI_PARSE_OBJECT       *Peer;
    468     ACPI_PARSE_OBJECT       *NewOp;
    469     ACPI_PARSE_OBJECT       *NewOp2;
    470     ACPI_PARSE_OBJECT       *MethodOp;
    471     ACPI_PARSE_OBJECT       *StoreOp;
    472     ACPI_PARSE_OBJECT       *BreakOp;
    473     char                    *PredicateValueName;
    474     UINT16                  Index;
    475     UINT32                  Btype;
    476 
    477 
    478     /* Start node is the Switch() node */
    479 
    480     CurrentParentNode  = StartNode;
    481 
    482     /* Create a new temp name of the form _T_x */
    483 
    484     PredicateValueName = TrAmlGetNextTempName (StartNode, &Gbl_TempCount);
    485     if (!PredicateValueName)
    486     {
    487         return;
    488     }
    489 
    490     /* First child is the Switch() predicate */
    491 
    492     Next = StartNode->Asl.Child;
    493 
    494     /*
    495      * Examine the return type of the Switch Value -
    496      * must be Integer/Buffer/String
    497      */
    498     Index = (UINT16) (Next->Asl.ParseOpcode - ASL_PARSE_OPCODE_BASE);
    499     Btype = AslKeywordMapping[Index].AcpiBtype;
    500     if ((Btype != ACPI_BTYPE_INTEGER) &&
    501         (Btype != ACPI_BTYPE_STRING)  &&
    502         (Btype != ACPI_BTYPE_BUFFER))
    503     {
    504         AslError (ASL_WARNING, ASL_MSG_SWITCH_TYPE, Next, NULL);
    505         Btype = ACPI_BTYPE_INTEGER;
    506     }
    507 
    508     /* CASE statements start at next child */
    509 
    510     Peer = Next->Asl.Next;
    511     while (Peer)
    512     {
    513         Next = Peer;
    514         Peer = Next->Asl.Next;
    515 
    516         if (Next->Asl.ParseOpcode == PARSEOP_CASE)
    517         {
    518             if (CaseOp)
    519             {
    520                 /* Add an ELSE to complete the previous CASE */
    521 
    522                 if (!Conditional)
    523                 {
    524                     return;
    525                 }
    526                 NewOp             = TrCreateLeafNode (PARSEOP_ELSE);
    527                 NewOp->Asl.Parent = Conditional->Asl.Parent;
    528                 TrAmlInitLineNumbers (NewOp, NewOp->Asl.Parent);
    529 
    530                 /* Link ELSE node as a peer to the previous IF */
    531 
    532                 TrAmlInsertPeer (Conditional, NewOp);
    533                 CurrentParentNode = NewOp;
    534             }
    535 
    536             CaseOp      = Next;
    537             Conditional = CaseOp;
    538             CaseBlock   = CaseOp->Asl.Child->Asl.Next;
    539             Conditional->Asl.Child->Asl.Next = NULL;
    540             Predicate = CaseOp->Asl.Child;
    541 
    542             if ((Predicate->Asl.ParseOpcode == PARSEOP_PACKAGE) ||
    543                 (Predicate->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE))
    544             {
    545                 /*
    546                  * Convert the package declaration to this form:
    547                  *
    548                  * If (LNotEqual (Match (Package(<size>){<data>},
    549                  *                       MEQ, _T_x, MTR, Zero, Zero), Ones))
    550                  */
    551                 NewOp2              = TrCreateLeafNode (PARSEOP_MATCHTYPE_MEQ);
    552                 Predicate->Asl.Next = NewOp2;
    553                 TrAmlInitLineNumbers (NewOp2, Conditional);
    554 
    555                 NewOp               = NewOp2;
    556                 NewOp2              = TrCreateValuedLeafNode (PARSEOP_NAMESTRING,
    557                                         (UINT64) ACPI_TO_INTEGER (PredicateValueName));
    558                 NewOp->Asl.Next     = NewOp2;
    559                 TrAmlInitLineNumbers (NewOp2, Predicate);
    560 
    561                 NewOp               = NewOp2;
    562                 NewOp2              = TrCreateLeafNode (PARSEOP_MATCHTYPE_MTR);
    563                 NewOp->Asl.Next     = NewOp2;
    564                 TrAmlInitLineNumbers (NewOp2, Predicate);
    565 
    566                 NewOp               = NewOp2;
    567                 NewOp2              = TrCreateLeafNode (PARSEOP_ZERO);
    568                 NewOp->Asl.Next     = NewOp2;
    569                 TrAmlInitLineNumbers (NewOp2, Predicate);
    570 
    571                 NewOp               = NewOp2;
    572                 NewOp2              = TrCreateLeafNode (PARSEOP_ZERO);
    573                 NewOp->Asl.Next     = NewOp2;
    574                 TrAmlInitLineNumbers (NewOp2, Predicate);
    575 
    576                 NewOp2              = TrCreateLeafNode (PARSEOP_MATCH);
    577                 NewOp2->Asl.Child   = Predicate;  /* PARSEOP_PACKAGE */
    578                 TrAmlInitLineNumbers (NewOp2, Conditional);
    579                 TrAmlSetSubtreeParent (Predicate, NewOp2);
    580 
    581                 NewOp               = NewOp2;
    582                 NewOp2              = TrCreateLeafNode (PARSEOP_ONES);
    583                 NewOp->Asl.Next     = NewOp2;
    584                 TrAmlInitLineNumbers (NewOp2, Conditional);
    585 
    586                 NewOp2              = TrCreateLeafNode (PARSEOP_LEQUAL);
    587                 NewOp2->Asl.Child   = NewOp;
    588                 NewOp->Asl.Parent   = NewOp2;
    589                 TrAmlInitLineNumbers (NewOp2, Conditional);
    590                 TrAmlSetSubtreeParent (NewOp, NewOp2);
    591 
    592                 NewOp               = NewOp2;
    593                 NewOp2              = TrCreateLeafNode (PARSEOP_LNOT);
    594                 NewOp2->Asl.Child   = NewOp;
    595                 NewOp2->Asl.Parent  = Conditional;
    596                 NewOp->Asl.Parent   = NewOp2;
    597                 TrAmlInitLineNumbers (NewOp2, Conditional);
    598 
    599                 Conditional->Asl.Child = NewOp2;
    600                 NewOp2->Asl.Next = CaseBlock;
    601             }
    602             else
    603             {
    604                 /*
    605                  * Integer and Buffer case.
    606                  *
    607                  * Change CaseOp() to:  If (LEqual (SwitchValue, CaseValue)) {...}
    608                  * Note: SwitchValue is first to allow the CaseValue to be implicitly
    609                  * converted to the type of SwitchValue if necessary.
    610                  *
    611                  * CaseOp->Child is the case value
    612                  * CaseOp->Child->Peer is the beginning of the case block
    613                  */
    614                 NewOp = TrCreateValuedLeafNode (PARSEOP_NAMESTRING,
    615                             (UINT64) ACPI_TO_INTEGER (PredicateValueName));
    616                 NewOp->Asl.Next = Predicate;
    617                 TrAmlInitLineNumbers (NewOp, Predicate);
    618 
    619                 NewOp2              = TrCreateLeafNode (PARSEOP_LEQUAL);
    620                 NewOp2->Asl.Parent  = Conditional;
    621                 NewOp2->Asl.Child   = NewOp;
    622                 TrAmlInitLineNumbers (NewOp2, Conditional);
    623 
    624                 TrAmlSetSubtreeParent (NewOp, NewOp2);
    625 
    626                 Predicate           = NewOp2;
    627                 Predicate->Asl.Next = CaseBlock;
    628 
    629                 TrAmlSetSubtreeParent (Predicate, Conditional);
    630                 Conditional->Asl.Child = Predicate;
    631             }
    632 
    633             /* Reinitialize the CASE node to an IF node */
    634 
    635             TrAmlInitNode (Conditional, PARSEOP_IF);
    636 
    637             /*
    638              * The first CASE(IF) is not nested under an ELSE.
    639              * All other CASEs are children of a parent ELSE.
    640              */
    641             if (CurrentParentNode == StartNode)
    642             {
    643                 Conditional->Asl.Next = NULL;
    644             }
    645             else
    646             {
    647                 /*
    648                  * The IF is a child of previous IF/ELSE.  It
    649                  * is therefore without peer.
    650                  */
    651                 CurrentParentNode->Asl.Child = Conditional;
    652                 Conditional->Asl.Parent      = CurrentParentNode;
    653                 Conditional->Asl.Next        = NULL;
    654             }
    655         }
    656         else if (Next->Asl.ParseOpcode == PARSEOP_DEFAULT)
    657         {
    658             if (DefaultOp)
    659             {
    660                 /*
    661                  * More than one Default
    662                  * (Parser does not catch this, must check here)
    663                  */
    664                 AslError (ASL_ERROR, ASL_MSG_MULTIPLE_DEFAULT, Next, NULL);
    665             }
    666             else
    667             {
    668                 /* Save the DEFAULT node for later, after CASEs */
    669 
    670                 DefaultOp = Next;
    671             }
    672         }
    673         else
    674         {
    675             /* Unknown peer opcode */
    676 
    677             AcpiOsPrintf ("Unknown parse opcode for switch statement: %s (%u)\n",
    678                         Next->Asl.ParseOpName, Next->Asl.ParseOpcode);
    679         }
    680     }
    681 
    682     /* Add the default case at the end of the if/else construct */
    683 
    684     if (DefaultOp)
    685     {
    686         /* If no CASE statements, this is an error - see below */
    687 
    688         if (CaseOp)
    689         {
    690             /* Convert the DEFAULT node to an ELSE */
    691 
    692             if (!Conditional)
    693             {
    694                 return;
    695             }
    696 
    697             TrAmlInitNode (DefaultOp, PARSEOP_ELSE);
    698             DefaultOp->Asl.Parent = Conditional->Asl.Parent;
    699 
    700             /* Link ELSE node as a peer to the previous IF */
    701 
    702             TrAmlInsertPeer (Conditional, DefaultOp);
    703         }
    704     }
    705 
    706     if (!CaseOp)
    707     {
    708         AslError (ASL_ERROR, ASL_MSG_NO_CASES, StartNode, NULL);
    709     }
    710 
    711 
    712     /*
    713      * Create a Name(_T_x, ...) statement. This statement must appear at the
    714      * method level, in case a loop surrounds the switch statement and could
    715      * cause the name to be created twice (error).
    716      */
    717 
    718     /* Create the Name node */
    719 
    720     Predicate = StartNode->Asl.Child;
    721     NewOp = TrCreateLeafNode (PARSEOP_NAME);
    722 
    723     /* Find the parent method */
    724 
    725     Next = StartNode;
    726     while ((Next->Asl.ParseOpcode != PARSEOP_METHOD) &&
    727            (Next->Asl.ParseOpcode != PARSEOP_DEFINITIONBLOCK))
    728     {
    729         Next = Next->Asl.Parent;
    730     }
    731     MethodOp = Next;
    732 
    733     NewOp->Asl.CompileFlags |= NODE_COMPILER_EMITTED;
    734     NewOp->Asl.Parent = Next;
    735 
    736     /* Insert name after the method name and arguments */
    737 
    738     Next = Next->Asl.Child; /* Name */
    739     Next = Next->Asl.Next;  /* NumArgs */
    740     Next = Next->Asl.Next;  /* SerializeRule */
    741 
    742     /*
    743      * If method is not Serialized, we must make is so, because of the way
    744      * that Switch() must be implemented -- we cannot allow multiple threads
    745      * to execute this method concurrently since we need to create local
    746      * temporary name(s).
    747      */
    748     if (Next->Asl.ParseOpcode != PARSEOP_SERIALIZERULE_SERIAL)
    749     {
    750         AslError (ASL_REMARK, ASL_MSG_SERIALIZED, MethodOp, "Due to use of Switch operator");
    751         Next->Asl.ParseOpcode = PARSEOP_SERIALIZERULE_SERIAL;
    752     }
    753 
    754     Next = Next->Asl.Next;  /* SyncLevel */
    755     Next = Next->Asl.Next;  /* ReturnType */
    756     Next = Next->Asl.Next;  /* ParameterTypes */
    757 
    758     TrAmlInsertPeer (Next, NewOp);
    759     TrAmlInitLineNumbers (NewOp, Next);
    760 
    761     /* Create the NameSeg child for the Name node */
    762 
    763     NewOp2 = TrCreateValuedLeafNode (PARSEOP_NAMESEG,
    764                 (UINT64) ACPI_TO_INTEGER (PredicateValueName));
    765     NewOp2->Asl.CompileFlags |= NODE_IS_NAME_DECLARATION;
    766     NewOp->Asl.Child  = NewOp2;
    767 
    768     /* Create the initial value for the Name. Btype was already validated above */
    769 
    770     switch (Btype)
    771     {
    772     case ACPI_BTYPE_INTEGER:
    773         NewOp2->Asl.Next = TrCreateValuedLeafNode (PARSEOP_ZERO,
    774                                 (UINT64) 0);
    775         break;
    776 
    777     case ACPI_BTYPE_STRING:
    778         NewOp2->Asl.Next = TrCreateValuedLeafNode (PARSEOP_STRING_LITERAL,
    779                                 (UINT64) ACPI_TO_INTEGER (""));
    780         break;
    781 
    782     case ACPI_BTYPE_BUFFER:
    783         (void) TrLinkPeerNode (NewOp2, TrCreateValuedLeafNode (PARSEOP_BUFFER,
    784                                     (UINT64) 0));
    785         Next = NewOp2->Asl.Next;
    786         (void) TrLinkChildren (Next, 1, TrCreateValuedLeafNode (PARSEOP_ZERO,
    787                                     (UINT64) 1));
    788         (void) TrLinkPeerNode (Next->Asl.Child,
    789             TrCreateValuedLeafNode (PARSEOP_DEFAULT_ARG, (UINT64) 0));
    790 
    791         TrAmlSetSubtreeParent (Next->Asl.Child, Next);
    792         break;
    793 
    794     default:
    795         break;
    796     }
    797 
    798     TrAmlSetSubtreeParent (NewOp2, NewOp);
    799 
    800     /*
    801      * Transform the Switch() into a While(One)-Break node.
    802      * And create a Store() node which will be used to save the
    803      * Switch() value.  The store is of the form: Store (Value, _T_x)
    804      * where _T_x is the temp variable.
    805      */
    806     TrAmlInitNode (StartNode, PARSEOP_WHILE);
    807     NewOp = TrCreateLeafNode (PARSEOP_ONE);
    808     NewOp->Asl.Next = Predicate->Asl.Next;
    809     NewOp->Asl.Parent = StartNode;
    810     StartNode->Asl.Child = NewOp;
    811 
    812     /* Create a Store() node */
    813 
    814     StoreOp = TrCreateLeafNode (PARSEOP_STORE);
    815     StoreOp->Asl.Parent = StartNode;
    816     TrAmlInsertPeer (NewOp, StoreOp);
    817 
    818     /* Complete the Store subtree */
    819 
    820     StoreOp->Asl.Child = Predicate;
    821     Predicate->Asl.Parent = StoreOp;
    822 
    823     NewOp = TrCreateValuedLeafNode (PARSEOP_NAMESEG,
    824                 (UINT64) ACPI_TO_INTEGER (PredicateValueName));
    825     NewOp->Asl.Parent    = StoreOp;
    826     Predicate->Asl.Next  = NewOp;
    827 
    828     /* Create a Break() node and insert it into the end of While() */
    829 
    830     Conditional = StartNode->Asl.Child;
    831     while (Conditional->Asl.Next)
    832     {
    833         Conditional = Conditional->Asl.Next;
    834     }
    835 
    836     BreakOp = TrCreateLeafNode (PARSEOP_BREAK);
    837     BreakOp->Asl.Parent = StartNode;
    838     TrAmlInsertPeer (Conditional, BreakOp);
    839 }
    840 
    841 
    842