]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/contrib/dev/acpica/compiler/asltransform.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / contrib / dev / acpica / compiler / asltransform.c
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 <contrib/dev/acpica/compiler/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