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