xref: /freebsd/sys/contrib/dev/acpica/compiler/asltransform.c (revision 70e0bbedef95258a4dadc996d641a9bebd3f107d)
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     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                 if (!Conditional)
452                 {
453                     return;
454                 }
455                 NewOp             = TrCreateLeafNode (PARSEOP_ELSE);
456                 NewOp->Asl.Parent = Conditional->Asl.Parent;
457                 TrAmlInitLineNumbers (NewOp, NewOp->Asl.Parent);
458 
459                 /* Link ELSE node as a peer to the previous IF */
460 
461                 TrAmlInsertPeer (Conditional, NewOp);
462                 CurrentParentNode = NewOp;
463             }
464 
465             CaseOp      = Next;
466             Conditional = CaseOp;
467             CaseBlock   = CaseOp->Asl.Child->Asl.Next;
468             Conditional->Asl.Child->Asl.Next = NULL;
469             Predicate = CaseOp->Asl.Child;
470 
471             if ((Predicate->Asl.ParseOpcode == PARSEOP_PACKAGE) ||
472                 (Predicate->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE))
473             {
474                 /*
475                  * Convert the package declaration to this form:
476                  *
477                  * If (LNotEqual (Match (Package(<size>){<data>},
478                  *                       MEQ, _T_x, MTR, Zero, Zero), Ones))
479                  */
480                 NewOp2              = TrCreateLeafNode (PARSEOP_MATCHTYPE_MEQ);
481                 Predicate->Asl.Next = NewOp2;
482                 TrAmlInitLineNumbers (NewOp2, Conditional);
483 
484                 NewOp               = NewOp2;
485                 NewOp2              = TrCreateValuedLeafNode (PARSEOP_NAMESTRING,
486                                         (UINT64) ACPI_TO_INTEGER (PredicateValueName));
487                 NewOp->Asl.Next     = NewOp2;
488                 TrAmlInitLineNumbers (NewOp2, Predicate);
489 
490                 NewOp               = NewOp2;
491                 NewOp2              = TrCreateLeafNode (PARSEOP_MATCHTYPE_MTR);
492                 NewOp->Asl.Next     = NewOp2;
493                 TrAmlInitLineNumbers (NewOp2, Predicate);
494 
495                 NewOp               = NewOp2;
496                 NewOp2              = TrCreateLeafNode (PARSEOP_ZERO);
497                 NewOp->Asl.Next     = NewOp2;
498                 TrAmlInitLineNumbers (NewOp2, Predicate);
499 
500                 NewOp               = NewOp2;
501                 NewOp2              = TrCreateLeafNode (PARSEOP_ZERO);
502                 NewOp->Asl.Next     = NewOp2;
503                 TrAmlInitLineNumbers (NewOp2, Predicate);
504 
505                 NewOp2              = TrCreateLeafNode (PARSEOP_MATCH);
506                 NewOp2->Asl.Child   = Predicate;  /* PARSEOP_PACKAGE */
507                 TrAmlInitLineNumbers (NewOp2, Conditional);
508                 TrAmlSetSubtreeParent (Predicate, NewOp2);
509 
510                 NewOp               = NewOp2;
511                 NewOp2              = TrCreateLeafNode (PARSEOP_ONES);
512                 NewOp->Asl.Next     = NewOp2;
513                 TrAmlInitLineNumbers (NewOp2, Conditional);
514 
515                 NewOp2              = TrCreateLeafNode (PARSEOP_LEQUAL);
516                 NewOp2->Asl.Child   = NewOp;
517                 NewOp->Asl.Parent   = NewOp2;
518                 TrAmlInitLineNumbers (NewOp2, Conditional);
519                 TrAmlSetSubtreeParent (NewOp, NewOp2);
520 
521                 NewOp               = NewOp2;
522                 NewOp2              = TrCreateLeafNode (PARSEOP_LNOT);
523                 NewOp2->Asl.Child   = NewOp;
524                 NewOp2->Asl.Parent  = Conditional;
525                 NewOp->Asl.Parent   = NewOp2;
526                 TrAmlInitLineNumbers (NewOp2, Conditional);
527 
528                 Conditional->Asl.Child = NewOp2;
529                 NewOp2->Asl.Next = CaseBlock;
530             }
531             else
532             {
533                 /*
534                  * Integer and Buffer case.
535                  *
536                  * Change CaseOp() to:  If (LEqual (SwitchValue, CaseValue)) {...}
537                  * Note: SwitchValue is first to allow the CaseValue to be implicitly
538                  * converted to the type of SwitchValue if necessary.
539                  *
540                  * CaseOp->Child is the case value
541                  * CaseOp->Child->Peer is the beginning of the case block
542                  */
543                 NewOp = TrCreateValuedLeafNode (PARSEOP_NAMESTRING,
544                             (UINT64) ACPI_TO_INTEGER (PredicateValueName));
545                 NewOp->Asl.Next = Predicate;
546                 TrAmlInitLineNumbers (NewOp, Predicate);
547 
548                 NewOp2              = TrCreateLeafNode (PARSEOP_LEQUAL);
549                 NewOp2->Asl.Parent  = Conditional;
550                 NewOp2->Asl.Child   = NewOp;
551                 TrAmlInitLineNumbers (NewOp2, Conditional);
552 
553                 TrAmlSetSubtreeParent (NewOp, NewOp2);
554 
555                 Predicate           = NewOp2;
556                 Predicate->Asl.Next = CaseBlock;
557 
558                 TrAmlSetSubtreeParent (Predicate, Conditional);
559                 Conditional->Asl.Child = Predicate;
560             }
561 
562             /* Reinitialize the CASE node to an IF node */
563 
564             TrAmlInitNode (Conditional, PARSEOP_IF);
565 
566             /*
567              * The first CASE(IF) is not nested under an ELSE.
568              * All other CASEs are children of a parent ELSE.
569              */
570             if (CurrentParentNode == StartNode)
571             {
572                 Conditional->Asl.Next = NULL;
573             }
574             else
575             {
576                 /*
577                  * The IF is a child of previous IF/ELSE.  It
578                  * is therefore without peer.
579                  */
580                 CurrentParentNode->Asl.Child = Conditional;
581                 Conditional->Asl.Parent      = CurrentParentNode;
582                 Conditional->Asl.Next        = NULL;
583             }
584         }
585         else if (Next->Asl.ParseOpcode == PARSEOP_DEFAULT)
586         {
587             if (DefaultOp)
588             {
589                 /*
590                  * More than one Default
591                  * (Parser does not catch this, must check here)
592                  */
593                 AslError (ASL_ERROR, ASL_MSG_MULTIPLE_DEFAULT, Next, NULL);
594             }
595             else
596             {
597                 /* Save the DEFAULT node for later, after CASEs */
598 
599                 DefaultOp = Next;
600             }
601         }
602         else
603         {
604             /* Unknown peer opcode */
605 
606             AcpiOsPrintf ("Unknown parse opcode for switch statement: %s (%u)\n",
607                         Next->Asl.ParseOpName, Next->Asl.ParseOpcode);
608         }
609     }
610 
611     /* Add the default case at the end of the if/else construct */
612 
613     if (DefaultOp)
614     {
615         /* If no CASE statements, this is an error - see below */
616 
617         if (CaseOp)
618         {
619             /* Convert the DEFAULT node to an ELSE */
620 
621             if (!Conditional)
622             {
623                 return;
624             }
625 
626             TrAmlInitNode (DefaultOp, PARSEOP_ELSE);
627             DefaultOp->Asl.Parent = Conditional->Asl.Parent;
628 
629             /* Link ELSE node as a peer to the previous IF */
630 
631             TrAmlInsertPeer (Conditional, DefaultOp);
632         }
633     }
634 
635     if (!CaseOp)
636     {
637         AslError (ASL_ERROR, ASL_MSG_NO_CASES, StartNode, NULL);
638     }
639 
640 
641     /*
642      * Create a Name(_T_x, ...) statement. This statement must appear at the
643      * method level, in case a loop surrounds the switch statement and could
644      * cause the name to be created twice (error).
645      */
646 
647     /* Create the Name node */
648 
649     Predicate = StartNode->Asl.Child;
650     NewOp = TrCreateLeafNode (PARSEOP_NAME);
651     TrAmlInitLineNumbers (NewOp, StartNode);
652 
653     /* Find the parent method */
654 
655     Next = StartNode;
656     while ((Next->Asl.ParseOpcode != PARSEOP_METHOD) &&
657            (Next->Asl.ParseOpcode != PARSEOP_DEFINITIONBLOCK))
658     {
659         Next = Next->Asl.Parent;
660     }
661     MethodOp = Next;
662 
663     NewOp->Asl.CompileFlags |= NODE_COMPILER_EMITTED;
664     NewOp->Asl.Parent = Next;
665 
666     /* Insert name after the method name and arguments */
667 
668     Next = Next->Asl.Child; /* Name */
669     Next = Next->Asl.Next;  /* NumArgs */
670     Next = Next->Asl.Next;  /* SerializeRule */
671 
672     /*
673      * If method is not Serialized, we must make is so, because of the way
674      * that Switch() must be implemented -- we cannot allow multiple threads
675      * to execute this method concurrently since we need to create local
676      * temporary name(s).
677      */
678     if (Next->Asl.ParseOpcode != PARSEOP_SERIALIZERULE_SERIAL)
679     {
680         AslError (ASL_REMARK, ASL_MSG_SERIALIZED, MethodOp, "Due to use of Switch operator");
681         Next->Asl.ParseOpcode = PARSEOP_SERIALIZERULE_SERIAL;
682     }
683 
684     Next = Next->Asl.Next;  /* SyncLevel */
685     Next = Next->Asl.Next;  /* ReturnType */
686     Next = Next->Asl.Next;  /* ParameterTypes */
687 
688     TrAmlInsertPeer (Next, NewOp);
689     TrAmlInitLineNumbers (NewOp, Next);
690 
691     /* Create the NameSeg child for the Name node */
692 
693     NewOp2 = TrCreateValuedLeafNode (PARSEOP_NAMESEG,
694                 (UINT64) ACPI_TO_INTEGER (PredicateValueName));
695     TrAmlInitLineNumbers (NewOp2, NewOp);
696     NewOp2->Asl.CompileFlags |= NODE_IS_NAME_DECLARATION;
697     NewOp->Asl.Child  = NewOp2;
698 
699     /* Create the initial value for the Name. Btype was already validated above */
700 
701     switch (Btype)
702     {
703     case ACPI_BTYPE_INTEGER:
704         NewOp2->Asl.Next = TrCreateValuedLeafNode (PARSEOP_ZERO,
705                                 (UINT64) 0);
706         TrAmlInitLineNumbers (NewOp2->Asl.Next, NewOp);
707         break;
708 
709     case ACPI_BTYPE_STRING:
710         NewOp2->Asl.Next = TrCreateValuedLeafNode (PARSEOP_STRING_LITERAL,
711                                 (UINT64) ACPI_TO_INTEGER (""));
712         TrAmlInitLineNumbers (NewOp2->Asl.Next, NewOp);
713         break;
714 
715     case ACPI_BTYPE_BUFFER:
716         (void) TrLinkPeerNode (NewOp2, TrCreateValuedLeafNode (PARSEOP_BUFFER,
717                                     (UINT64) 0));
718         Next = NewOp2->Asl.Next;
719         TrAmlInitLineNumbers (Next, NewOp2);
720         (void) TrLinkChildren (Next, 1, TrCreateValuedLeafNode (PARSEOP_ZERO,
721                                     (UINT64) 1));
722         TrAmlInitLineNumbers (Next->Asl.Child, Next);
723 
724         BufferOp = TrCreateValuedLeafNode (PARSEOP_DEFAULT_ARG, (UINT64) 0);
725         TrAmlInitLineNumbers (BufferOp, Next->Asl.Child);
726         (void) TrLinkPeerNode (Next->Asl.Child, BufferOp);
727 
728         TrAmlSetSubtreeParent (Next->Asl.Child, Next);
729         break;
730 
731     default:
732         break;
733     }
734 
735     TrAmlSetSubtreeParent (NewOp2, NewOp);
736 
737     /*
738      * Transform the Switch() into a While(One)-Break node.
739      * And create a Store() node which will be used to save the
740      * Switch() value.  The store is of the form: Store (Value, _T_x)
741      * where _T_x is the temp variable.
742      */
743     TrAmlInitNode (StartNode, PARSEOP_WHILE);
744     NewOp = TrCreateLeafNode (PARSEOP_ONE);
745     TrAmlInitLineNumbers (NewOp, StartNode);
746     NewOp->Asl.Next = Predicate->Asl.Next;
747     NewOp->Asl.Parent = StartNode;
748     StartNode->Asl.Child = NewOp;
749 
750     /* Create a Store() node */
751 
752     StoreOp = TrCreateLeafNode (PARSEOP_STORE);
753     TrAmlInitLineNumbers (StoreOp, NewOp);
754     StoreOp->Asl.Parent = StartNode;
755     TrAmlInsertPeer (NewOp, StoreOp);
756 
757     /* Complete the Store subtree */
758 
759     StoreOp->Asl.Child = Predicate;
760     Predicate->Asl.Parent = StoreOp;
761 
762     NewOp = TrCreateValuedLeafNode (PARSEOP_NAMESEG,
763                 (UINT64) ACPI_TO_INTEGER (PredicateValueName));
764     TrAmlInitLineNumbers (NewOp, StoreOp);
765     NewOp->Asl.Parent    = StoreOp;
766     Predicate->Asl.Next  = NewOp;
767 
768     /* Create a Break() node and insert it into the end of While() */
769 
770     Conditional = StartNode->Asl.Child;
771     while (Conditional->Asl.Next)
772     {
773         Conditional = Conditional->Asl.Next;
774     }
775 
776     BreakOp = TrCreateLeafNode (PARSEOP_BREAK);
777     TrAmlInitLineNumbers (BreakOp, NewOp);
778     BreakOp->Asl.Parent = StartNode;
779     TrAmlInsertPeer (Conditional, BreakOp);
780 }
781 
782 
783