xref: /freebsd/sys/contrib/dev/acpica/compiler/asltransform.c (revision f4b37ed0f8b307b1f3f0f630ca725d68f1dff30d)
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 <contrib/dev/acpica/compiler/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