Home | History | Annotate | Line # | Download | only in compiler
asltransform.c revision 1.1.1.5
      1 /******************************************************************************
      2  *
      3  * Module Name: asltransform - Parse tree transforms
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2015, 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 
     47 #define _COMPONENT          ACPI_COMPILER
     48         ACPI_MODULE_NAME    ("asltransform")
     49 
     50 /* Local prototypes */
     51 
     52 static void
     53 TrTransformSubtree (
     54     ACPI_PARSE_OBJECT       *Op);
     55 
     56 static char *
     57 TrAmlGetNextTempName (
     58     ACPI_PARSE_OBJECT       *Op,
     59     UINT8                   *TempCount);
     60 
     61 static void
     62 TrAmlInitLineNumbers (
     63     ACPI_PARSE_OBJECT       *Op,
     64     ACPI_PARSE_OBJECT       *Neighbor);
     65 
     66 static void
     67 TrAmlInitNode (
     68     ACPI_PARSE_OBJECT       *Op,
     69     UINT16                  ParseOpcode);
     70 
     71 static void
     72 TrAmlSetSubtreeParent (
     73     ACPI_PARSE_OBJECT       *Op,
     74     ACPI_PARSE_OBJECT       *Parent);
     75 
     76 static void
     77 TrAmlInsertPeer (
     78     ACPI_PARSE_OBJECT       *Op,
     79     ACPI_PARSE_OBJECT       *NewPeer);
     80 
     81 static void
     82 TrDoDefinitionBlock (
     83     ACPI_PARSE_OBJECT       *Op);
     84 
     85 static void
     86 TrDoSwitch (
     87     ACPI_PARSE_OBJECT       *StartNode);
     88 
     89 
     90 /*******************************************************************************
     91  *
     92  * FUNCTION:    TrAmlGetNextTempName
     93  *
     94  * PARAMETERS:  Op              - Current parse op
     95  *              TempCount       - Current temporary counter. Was originally
     96  *                                per-module; Currently per method, could be
     97  *                                expanded to per-scope.
     98  *
     99  * RETURN:      A pointer to name (allocated here).
    100  *
    101  * DESCRIPTION: Generate an ACPI name of the form _T_x. These names are
    102  *              reserved for use by the ASL compiler. (_T_0 through _T_Z)
    103  *
    104  ******************************************************************************/
    105 
    106 static char *
    107 TrAmlGetNextTempName (
    108     ACPI_PARSE_OBJECT       *Op,
    109     UINT8                   *TempCount)
    110 {
    111     char                    *TempName;
    112 
    113 
    114     if (*TempCount >= (10+26))  /* 0-35 valid: 0-9 and A-Z for TempName[3] */
    115     {
    116         /* Too many temps */
    117 
    118         AslError (ASL_ERROR, ASL_MSG_TOO_MANY_TEMPS, Op, NULL);
    119         return (NULL);
    120     }
    121 
    122     TempName = UtLocalCalloc (5);
    123 
    124     if (*TempCount < 10)    /* 0-9 */
    125     {
    126         TempName[3] = (char) (*TempCount + '0');
    127     }
    128     else                    /* 10-35: A-Z */
    129     {
    130         TempName[3] = (char) (*TempCount + ('A' - 10));
    131     }
    132     (*TempCount)++;
    133 
    134     /* First three characters are always "_T_" */
    135 
    136     TempName[0] = '_';
    137     TempName[1] = 'T';
    138     TempName[2] = '_';
    139 
    140     return (TempName);
    141 }
    142 
    143 
    144 /*******************************************************************************
    145  *
    146  * FUNCTION:    TrAmlInitLineNumbers
    147  *
    148  * PARAMETERS:  Op              - Op to be initialized
    149  *              Neighbor        - Op used for initialization values
    150  *
    151  * RETURN:      None
    152  *
    153  * DESCRIPTION: Initialized the various line numbers for a parse node.
    154  *
    155  ******************************************************************************/
    156 
    157 static void
    158 TrAmlInitLineNumbers (
    159     ACPI_PARSE_OBJECT       *Op,
    160     ACPI_PARSE_OBJECT       *Neighbor)
    161 {
    162 
    163     Op->Asl.EndLine           = Neighbor->Asl.EndLine;
    164     Op->Asl.EndLogicalLine    = Neighbor->Asl.EndLogicalLine;
    165     Op->Asl.LineNumber        = Neighbor->Asl.LineNumber;
    166     Op->Asl.LogicalByteOffset = Neighbor->Asl.LogicalByteOffset;
    167     Op->Asl.LogicalLineNumber = Neighbor->Asl.LogicalLineNumber;
    168 }
    169 
    170 
    171 /*******************************************************************************
    172  *
    173  * FUNCTION:    TrAmlInitNode
    174  *
    175  * PARAMETERS:  Op              - Op to be initialized
    176  *              ParseOpcode     - Opcode for this node
    177  *
    178  * RETURN:      None
    179  *
    180  * DESCRIPTION: Initialize a node with the parse opcode and opcode name.
    181  *
    182  ******************************************************************************/
    183 
    184 static void
    185 TrAmlInitNode (
    186     ACPI_PARSE_OBJECT       *Op,
    187     UINT16                  ParseOpcode)
    188 {
    189 
    190     Op->Asl.ParseOpcode = ParseOpcode;
    191     UtSetParseOpName (Op);
    192 }
    193 
    194 
    195 /*******************************************************************************
    196  *
    197  * FUNCTION:    TrAmlSetSubtreeParent
    198  *
    199  * PARAMETERS:  Op              - First node in a list of peer nodes
    200  *              Parent          - Parent of the subtree
    201  *
    202  * RETURN:      None
    203  *
    204  * DESCRIPTION: Set the parent for all peer nodes in a subtree
    205  *
    206  ******************************************************************************/
    207 
    208 static void
    209 TrAmlSetSubtreeParent (
    210     ACPI_PARSE_OBJECT       *Op,
    211     ACPI_PARSE_OBJECT       *Parent)
    212 {
    213     ACPI_PARSE_OBJECT       *Next;
    214 
    215 
    216     Next = Op;
    217     while (Next)
    218     {
    219         Next->Asl.Parent = Parent;
    220         Next             = Next->Asl.Next;
    221     }
    222 }
    223 
    224 
    225 /*******************************************************************************
    226  *
    227  * FUNCTION:    TrAmlInsertPeer
    228  *
    229  * PARAMETERS:  Op              - First node in a list of peer nodes
    230  *              NewPeer         - Peer node to insert
    231  *
    232  * RETURN:      None
    233  *
    234  * DESCRIPTION: Insert a new peer node into a list of peers.
    235  *
    236  ******************************************************************************/
    237 
    238 static void
    239 TrAmlInsertPeer (
    240     ACPI_PARSE_OBJECT       *Op,
    241     ACPI_PARSE_OBJECT       *NewPeer)
    242 {
    243 
    244     NewPeer->Asl.Next = Op->Asl.Next;
    245     Op->Asl.Next      = NewPeer;
    246 }
    247 
    248 
    249 /*******************************************************************************
    250  *
    251  * FUNCTION:    TrAmlTransformWalk
    252  *
    253  * PARAMETERS:  ASL_WALK_CALLBACK
    254  *
    255  * RETURN:      None
    256  *
    257  * DESCRIPTION: Parse tree walk to generate both the AML opcodes and the AML
    258  *              operands.
    259  *
    260  ******************************************************************************/
    261 
    262 ACPI_STATUS
    263 TrAmlTransformWalk (
    264     ACPI_PARSE_OBJECT       *Op,
    265     UINT32                  Level,
    266     void                    *Context)
    267 {
    268 
    269     TrTransformSubtree (Op);
    270     return (AE_OK);
    271 }
    272 
    273 
    274 /*******************************************************************************
    275  *
    276  * FUNCTION:    TrTransformSubtree
    277  *
    278  * PARAMETERS:  Op        - The parent parse node
    279  *
    280  * RETURN:      None
    281  *
    282  * DESCRIPTION: Prepare nodes to be output as AML data and operands. The more
    283  *              complex AML opcodes require processing of the child nodes
    284  *              (arguments/operands).
    285  *
    286  ******************************************************************************/
    287 
    288 static void
    289 TrTransformSubtree (
    290     ACPI_PARSE_OBJECT           *Op)
    291 {
    292 
    293     if (Op->Asl.AmlOpcode == AML_RAW_DATA_BYTE)
    294     {
    295         return;
    296     }
    297 
    298     switch (Op->Asl.ParseOpcode)
    299     {
    300     case PARSEOP_DEFINITIONBLOCK:
    301 
    302         TrDoDefinitionBlock (Op);
    303         break;
    304 
    305     case PARSEOP_SWITCH:
    306 
    307         TrDoSwitch (Op);
    308         break;
    309 
    310     case PARSEOP_METHOD:
    311         /*
    312          * TBD: Zero the tempname (_T_x) count. Probably shouldn't be a global,
    313          * however
    314          */
    315         Gbl_TempCount = 0;
    316         break;
    317 
    318     default:
    319 
    320         /* Nothing to do here for other opcodes */
    321 
    322         break;
    323     }
    324 }
    325 
    326 
    327 /*******************************************************************************
    328  *
    329  * FUNCTION:    TrDoDefinitionBlock
    330  *
    331  * PARAMETERS:  Op        - Parse node
    332  *
    333  * RETURN:      None
    334  *
    335  * DESCRIPTION: Find the end of the definition block and set a global to this
    336  *              node. It is used by the compiler to insert compiler-generated
    337  *              names at the root level of the namespace.
    338  *
    339  ******************************************************************************/
    340 
    341 static void
    342 TrDoDefinitionBlock (
    343     ACPI_PARSE_OBJECT       *Op)
    344 {
    345     ACPI_PARSE_OBJECT       *Next;
    346     UINT32                  i;
    347 
    348 
    349     Next = Op->Asl.Child;
    350     for (i = 0; i < 5; i++)
    351     {
    352         Next = Next->Asl.Next;
    353         if (i == 0)
    354         {
    355             /*
    356              * This is the table signature. Only the DSDT can be assumed
    357              * to be at the root of the namespace;  Therefore, namepath
    358              * optimization can only be performed on the DSDT.
    359              */
    360             if (!ACPI_COMPARE_NAME (Next->Asl.Value.String, ACPI_SIG_DSDT))
    361             {
    362                 Gbl_ReferenceOptimizationFlag = FALSE;
    363             }
    364         }
    365     }
    366 
    367     Gbl_FirstLevelInsertionNode = Next;
    368 }
    369 
    370 
    371 /*******************************************************************************
    372  *
    373  * FUNCTION:    TrDoSwitch
    374  *
    375  * PARAMETERS:  StartNode        - Parse node for SWITCH
    376  *
    377  * RETURN:      None
    378  *
    379  * DESCRIPTION: Translate ASL SWITCH statement to if/else pairs. There is
    380  *              no actual AML opcode for SWITCH -- it must be simulated.
    381  *
    382  ******************************************************************************/
    383 
    384 static void
    385 TrDoSwitch (
    386     ACPI_PARSE_OBJECT       *StartNode)
    387 {
    388     ACPI_PARSE_OBJECT       *Next;
    389     ACPI_PARSE_OBJECT       *CaseOp = NULL;
    390     ACPI_PARSE_OBJECT       *CaseBlock = NULL;
    391     ACPI_PARSE_OBJECT       *DefaultOp = NULL;
    392     ACPI_PARSE_OBJECT       *CurrentParentNode;
    393     ACPI_PARSE_OBJECT       *Conditional = NULL;
    394     ACPI_PARSE_OBJECT       *Predicate;
    395     ACPI_PARSE_OBJECT       *Peer;
    396     ACPI_PARSE_OBJECT       *NewOp;
    397     ACPI_PARSE_OBJECT       *NewOp2;
    398     ACPI_PARSE_OBJECT       *MethodOp;
    399     ACPI_PARSE_OBJECT       *StoreOp;
    400     ACPI_PARSE_OBJECT       *BreakOp;
    401     ACPI_PARSE_OBJECT       *BufferOp;
    402     char                    *PredicateValueName;
    403     UINT16                  Index;
    404     UINT32                  Btype;
    405 
    406 
    407     /* Start node is the Switch() node */
    408 
    409     CurrentParentNode  = StartNode;
    410 
    411     /* Create a new temp name of the form _T_x */
    412 
    413     PredicateValueName = TrAmlGetNextTempName (StartNode, &Gbl_TempCount);
    414     if (!PredicateValueName)
    415     {
    416         return;
    417     }
    418 
    419     /* First child is the Switch() predicate */
    420 
    421     Next = StartNode->Asl.Child;
    422 
    423     /*
    424      * Examine the return type of the Switch Value -
    425      * must be Integer/Buffer/String
    426      */
    427     Index = (UINT16) (Next->Asl.ParseOpcode - ASL_PARSE_OPCODE_BASE);
    428     Btype = AslKeywordMapping[Index].AcpiBtype;
    429     if ((Btype != ACPI_BTYPE_INTEGER) &&
    430         (Btype != ACPI_BTYPE_STRING)  &&
    431         (Btype != ACPI_BTYPE_BUFFER))
    432     {
    433         AslError (ASL_WARNING, ASL_MSG_SWITCH_TYPE, Next, NULL);
    434         Btype = ACPI_BTYPE_INTEGER;
    435     }
    436 
    437     /* CASE statements start at next child */
    438 
    439     Peer = Next->Asl.Next;
    440     while (Peer)
    441     {
    442         Next = Peer;
    443         Peer = Next->Asl.Next;
    444 
    445         if (Next->Asl.ParseOpcode == PARSEOP_CASE)
    446         {
    447             if (CaseOp)
    448             {
    449                 /* Add an ELSE to complete the previous CASE */
    450 
    451                 NewOp             = TrCreateLeafNode (PARSEOP_ELSE);
    452                 NewOp->Asl.Parent = Conditional->Asl.Parent;
    453                 TrAmlInitLineNumbers (NewOp, NewOp->Asl.Parent);
    454 
    455                 /* Link ELSE node as a peer to the previous IF */
    456 
    457                 TrAmlInsertPeer (Conditional, NewOp);
    458                 CurrentParentNode = NewOp;
    459             }
    460 
    461             CaseOp      = Next;
    462             Conditional = CaseOp;
    463             CaseBlock   = CaseOp->Asl.Child->Asl.Next;
    464             Conditional->Asl.Child->Asl.Next = NULL;
    465             Predicate = CaseOp->Asl.Child;
    466 
    467             if ((Predicate->Asl.ParseOpcode == PARSEOP_PACKAGE) ||
    468                 (Predicate->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE))
    469             {
    470                 /*
    471                  * Convert the package declaration to this form:
    472                  *
    473                  * If (LNotEqual (Match (Package(<size>){<data>},
    474                  *                       MEQ, _T_x, MTR, Zero, Zero), Ones))
    475                  */
    476                 NewOp2              = TrCreateLeafNode (PARSEOP_MATCHTYPE_MEQ);
    477                 Predicate->Asl.Next = NewOp2;
    478                 TrAmlInitLineNumbers (NewOp2, Conditional);
    479 
    480                 NewOp               = NewOp2;
    481                 NewOp2              = TrCreateValuedLeafNode (PARSEOP_NAMESTRING,
    482                                         (UINT64) ACPI_TO_INTEGER (PredicateValueName));
    483                 NewOp->Asl.Next     = NewOp2;
    484                 TrAmlInitLineNumbers (NewOp2, Predicate);
    485 
    486                 NewOp               = NewOp2;
    487                 NewOp2              = TrCreateLeafNode (PARSEOP_MATCHTYPE_MTR);
    488                 NewOp->Asl.Next     = NewOp2;
    489                 TrAmlInitLineNumbers (NewOp2, Predicate);
    490 
    491                 NewOp               = NewOp2;
    492                 NewOp2              = TrCreateLeafNode (PARSEOP_ZERO);
    493                 NewOp->Asl.Next     = NewOp2;
    494                 TrAmlInitLineNumbers (NewOp2, Predicate);
    495 
    496                 NewOp               = NewOp2;
    497                 NewOp2              = TrCreateLeafNode (PARSEOP_ZERO);
    498                 NewOp->Asl.Next     = NewOp2;
    499                 TrAmlInitLineNumbers (NewOp2, Predicate);
    500 
    501                 NewOp2              = TrCreateLeafNode (PARSEOP_MATCH);
    502                 NewOp2->Asl.Child   = Predicate;  /* PARSEOP_PACKAGE */
    503                 TrAmlInitLineNumbers (NewOp2, Conditional);
    504                 TrAmlSetSubtreeParent (Predicate, NewOp2);
    505 
    506                 NewOp               = NewOp2;
    507                 NewOp2              = TrCreateLeafNode (PARSEOP_ONES);
    508                 NewOp->Asl.Next     = NewOp2;
    509                 TrAmlInitLineNumbers (NewOp2, Conditional);
    510 
    511                 NewOp2              = TrCreateLeafNode (PARSEOP_LEQUAL);
    512                 NewOp2->Asl.Child   = NewOp;
    513                 NewOp->Asl.Parent   = NewOp2;
    514                 TrAmlInitLineNumbers (NewOp2, Conditional);
    515                 TrAmlSetSubtreeParent (NewOp, NewOp2);
    516 
    517                 NewOp               = NewOp2;
    518                 NewOp2              = TrCreateLeafNode (PARSEOP_LNOT);
    519                 NewOp2->Asl.Child   = NewOp;
    520                 NewOp2->Asl.Parent  = Conditional;
    521                 NewOp->Asl.Parent   = NewOp2;
    522                 TrAmlInitLineNumbers (NewOp2, Conditional);
    523 
    524                 Conditional->Asl.Child = NewOp2;
    525                 NewOp2->Asl.Next = CaseBlock;
    526             }
    527             else
    528             {
    529                 /*
    530                  * Integer and Buffer case.
    531                  *
    532                  * Change CaseOp() to:  If (LEqual (SwitchValue, CaseValue)) {...}
    533                  * Note: SwitchValue is first to allow the CaseValue to be implicitly
    534                  * converted to the type of SwitchValue if necessary.
    535                  *
    536                  * CaseOp->Child is the case value
    537                  * CaseOp->Child->Peer is the beginning of the case block
    538                  */
    539                 NewOp = TrCreateValuedLeafNode (PARSEOP_NAMESTRING,
    540                             (UINT64) ACPI_TO_INTEGER (PredicateValueName));
    541                 NewOp->Asl.Next = Predicate;
    542                 TrAmlInitLineNumbers (NewOp, Predicate);
    543 
    544                 NewOp2              = TrCreateLeafNode (PARSEOP_LEQUAL);
    545                 NewOp2->Asl.Parent  = Conditional;
    546                 NewOp2->Asl.Child   = NewOp;
    547                 TrAmlInitLineNumbers (NewOp2, Conditional);
    548 
    549                 TrAmlSetSubtreeParent (NewOp, NewOp2);
    550 
    551                 Predicate           = NewOp2;
    552                 Predicate->Asl.Next = CaseBlock;
    553 
    554                 TrAmlSetSubtreeParent (Predicate, Conditional);
    555                 Conditional->Asl.Child = Predicate;
    556             }
    557 
    558             /* Reinitialize the CASE node to an IF node */
    559 
    560             TrAmlInitNode (Conditional, PARSEOP_IF);
    561 
    562             /*
    563              * The first CASE(IF) is not nested under an ELSE.
    564              * All other CASEs are children of a parent ELSE.
    565              */
    566             if (CurrentParentNode == StartNode)
    567             {
    568                 Conditional->Asl.Next = NULL;
    569             }
    570             else
    571             {
    572                 /*
    573                  * The IF is a child of previous IF/ELSE. It
    574                  * is therefore without peer.
    575                  */
    576                 CurrentParentNode->Asl.Child = Conditional;
    577                 Conditional->Asl.Parent      = CurrentParentNode;
    578                 Conditional->Asl.Next        = NULL;
    579             }
    580         }
    581         else if (Next->Asl.ParseOpcode == PARSEOP_DEFAULT)
    582         {
    583             if (DefaultOp)
    584             {
    585                 /*
    586                  * More than one Default
    587                  * (Parser does not catch this, must check here)
    588                  */
    589                 AslError (ASL_ERROR, ASL_MSG_MULTIPLE_DEFAULT, Next, NULL);
    590             }
    591             else
    592             {
    593                 /* Save the DEFAULT node for later, after CASEs */
    594 
    595                 DefaultOp = Next;
    596             }
    597         }
    598         else
    599         {
    600             /* Unknown peer opcode */
    601 
    602             AcpiOsPrintf ("Unknown parse opcode for switch statement: %s (%u)\n",
    603                         Next->Asl.ParseOpName, Next->Asl.ParseOpcode);
    604         }
    605     }
    606 
    607     /* Add the default case at the end of the if/else construct */
    608 
    609     if (DefaultOp)
    610     {
    611         /* If no CASE statements, this is an error - see below */
    612 
    613         if (CaseOp)
    614         {
    615             /* Convert the DEFAULT node to an ELSE */
    616 
    617             TrAmlInitNode (DefaultOp, PARSEOP_ELSE);
    618             DefaultOp->Asl.Parent = Conditional->Asl.Parent;
    619 
    620             /* Link ELSE node as a peer to the previous IF */
    621 
    622             TrAmlInsertPeer (Conditional, DefaultOp);
    623         }
    624     }
    625 
    626     if (!CaseOp)
    627     {
    628         AslError (ASL_ERROR, ASL_MSG_NO_CASES, StartNode, NULL);
    629     }
    630 
    631 
    632     /*
    633      * Create a Name(_T_x, ...) statement. This statement must appear at the
    634      * method level, in case a loop surrounds the switch statement and could
    635      * cause the name to be created twice (error).
    636      */
    637 
    638     /* Create the Name node */
    639 
    640     Predicate = StartNode->Asl.Child;
    641     NewOp = TrCreateLeafNode (PARSEOP_NAME);
    642     TrAmlInitLineNumbers (NewOp, StartNode);
    643 
    644     /* Find the parent method */
    645 
    646     Next = StartNode;
    647     while ((Next->Asl.ParseOpcode != PARSEOP_METHOD) &&
    648            (Next->Asl.ParseOpcode != PARSEOP_DEFINITIONBLOCK))
    649     {
    650         Next = Next->Asl.Parent;
    651     }
    652     MethodOp = Next;
    653 
    654     NewOp->Asl.CompileFlags |= NODE_COMPILER_EMITTED;
    655     NewOp->Asl.Parent = Next;
    656 
    657     /* Insert name after the method name and arguments */
    658 
    659     Next = Next->Asl.Child; /* Name */
    660     Next = Next->Asl.Next;  /* NumArgs */
    661     Next = Next->Asl.Next;  /* SerializeRule */
    662 
    663     /*
    664      * If method is not Serialized, we must make is so, because of the way
    665      * that Switch() must be implemented -- we cannot allow multiple threads
    666      * to execute this method concurrently since we need to create local
    667      * temporary name(s).
    668      */
    669     if (Next->Asl.ParseOpcode != PARSEOP_SERIALIZERULE_SERIAL)
    670     {
    671         AslError (ASL_REMARK, ASL_MSG_SERIALIZED, MethodOp, "Due to use of Switch operator");
    672         Next->Asl.ParseOpcode = PARSEOP_SERIALIZERULE_SERIAL;
    673     }
    674 
    675     Next = Next->Asl.Next;  /* SyncLevel */
    676     Next = Next->Asl.Next;  /* ReturnType */
    677     Next = Next->Asl.Next;  /* ParameterTypes */
    678 
    679     TrAmlInsertPeer (Next, NewOp);
    680     TrAmlInitLineNumbers (NewOp, Next);
    681 
    682     /* Create the NameSeg child for the Name node */
    683 
    684     NewOp2 = TrCreateValuedLeafNode (PARSEOP_NAMESEG,
    685                 (UINT64) ACPI_TO_INTEGER (PredicateValueName));
    686     TrAmlInitLineNumbers (NewOp2, NewOp);
    687     NewOp2->Asl.CompileFlags |= NODE_IS_NAME_DECLARATION;
    688     NewOp->Asl.Child  = NewOp2;
    689 
    690     /* Create the initial value for the Name. Btype was already validated above */
    691 
    692     switch (Btype)
    693     {
    694     case ACPI_BTYPE_INTEGER:
    695 
    696         NewOp2->Asl.Next = TrCreateValuedLeafNode (PARSEOP_ZERO,
    697                                 (UINT64) 0);
    698         TrAmlInitLineNumbers (NewOp2->Asl.Next, NewOp);
    699         break;
    700 
    701     case ACPI_BTYPE_STRING:
    702 
    703         NewOp2->Asl.Next = TrCreateValuedLeafNode (PARSEOP_STRING_LITERAL,
    704                                 (UINT64) ACPI_TO_INTEGER (""));
    705         TrAmlInitLineNumbers (NewOp2->Asl.Next, NewOp);
    706         break;
    707 
    708     case ACPI_BTYPE_BUFFER:
    709 
    710         (void) TrLinkPeerNode (NewOp2, TrCreateValuedLeafNode (PARSEOP_BUFFER,
    711                                     (UINT64) 0));
    712         Next = NewOp2->Asl.Next;
    713         TrAmlInitLineNumbers (Next, NewOp2);
    714         (void) TrLinkChildren (Next, 1, TrCreateValuedLeafNode (PARSEOP_ZERO,
    715                                     (UINT64) 1));
    716         TrAmlInitLineNumbers (Next->Asl.Child, Next);
    717 
    718         BufferOp = TrCreateValuedLeafNode (PARSEOP_DEFAULT_ARG, (UINT64) 0);
    719         TrAmlInitLineNumbers (BufferOp, Next->Asl.Child);
    720         (void) TrLinkPeerNode (Next->Asl.Child, BufferOp);
    721 
    722         TrAmlSetSubtreeParent (Next->Asl.Child, Next);
    723         break;
    724 
    725     default:
    726 
    727         break;
    728     }
    729 
    730     TrAmlSetSubtreeParent (NewOp2, NewOp);
    731 
    732     /*
    733      * Transform the Switch() into a While(One)-Break node.
    734      * And create a Store() node which will be used to save the
    735      * Switch() value. The store is of the form: Store (Value, _T_x)
    736      * where _T_x is the temp variable.
    737      */
    738     TrAmlInitNode (StartNode, PARSEOP_WHILE);
    739     NewOp = TrCreateLeafNode (PARSEOP_ONE);
    740     TrAmlInitLineNumbers (NewOp, StartNode);
    741     NewOp->Asl.Next = Predicate->Asl.Next;
    742     NewOp->Asl.Parent = StartNode;
    743     StartNode->Asl.Child = NewOp;
    744 
    745     /* Create a Store() node */
    746 
    747     StoreOp = TrCreateLeafNode (PARSEOP_STORE);
    748     TrAmlInitLineNumbers (StoreOp, NewOp);
    749     StoreOp->Asl.Parent = StartNode;
    750     TrAmlInsertPeer (NewOp, StoreOp);
    751 
    752     /* Complete the Store subtree */
    753 
    754     StoreOp->Asl.Child = Predicate;
    755     Predicate->Asl.Parent = StoreOp;
    756 
    757     NewOp = TrCreateValuedLeafNode (PARSEOP_NAMESEG,
    758                 (UINT64) ACPI_TO_INTEGER (PredicateValueName));
    759     TrAmlInitLineNumbers (NewOp, StoreOp);
    760     NewOp->Asl.Parent    = StoreOp;
    761     Predicate->Asl.Next  = NewOp;
    762 
    763     /* Create a Break() node and insert it into the end of While() */
    764 
    765     Conditional = StartNode->Asl.Child;
    766     while (Conditional->Asl.Next)
    767     {
    768         Conditional = Conditional->Asl.Next;
    769     }
    770 
    771     BreakOp = TrCreateLeafNode (PARSEOP_BREAK);
    772     TrAmlInitLineNumbers (BreakOp, NewOp);
    773     BreakOp->Asl.Parent = StartNode;
    774     TrAmlInsertPeer (Conditional, BreakOp);
    775 }
    776