]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/contrib/dev/acpica/compiler/asltree.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / sys / contrib / dev / acpica / compiler / asltree.c
1 /******************************************************************************
2  *
3  * Module Name: asltree - parse tree management
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 #include <contrib/dev/acpica/include/acapps.h>
47 #include <time.h>
48
49 #define _COMPONENT          ACPI_COMPILER
50         ACPI_MODULE_NAME    ("asltree")
51
52 /* Local prototypes */
53
54 static ACPI_PARSE_OBJECT *
55 TrGetNextNode (
56     void);
57
58
59 /*******************************************************************************
60  *
61  * FUNCTION:    TrGetNextNode
62  *
63  * PARAMETERS:  None
64  *
65  * RETURN:      New parse node. Aborts on allocation failure
66  *
67  * DESCRIPTION: Allocate a new parse node for the parse tree. Bypass the local
68  *              dynamic memory manager for performance reasons (This has a
69  *              major impact on the speed of the compiler.)
70  *
71  ******************************************************************************/
72
73 static ACPI_PARSE_OBJECT *
74 TrGetNextNode (
75     void)
76 {
77     ASL_CACHE_INFO          *Cache;
78
79
80     if (Gbl_ParseOpCacheNext >= Gbl_ParseOpCacheLast)
81     {
82         /* Allocate a new buffer */
83
84         Cache = UtLocalCalloc (sizeof (Cache->Next) +
85             (sizeof (ACPI_PARSE_OBJECT) * ASL_PARSEOP_CACHE_SIZE));
86
87         /* Link new cache buffer to head of list */
88
89         Cache->Next = Gbl_ParseOpCacheList;
90         Gbl_ParseOpCacheList = Cache;
91
92         /* Setup cache management pointers */
93
94         Gbl_ParseOpCacheNext = ACPI_CAST_PTR (ACPI_PARSE_OBJECT, Cache->Buffer);
95         Gbl_ParseOpCacheLast = Gbl_ParseOpCacheNext + ASL_PARSEOP_CACHE_SIZE;
96     }
97
98     Gbl_ParseOpCount++;
99     return (Gbl_ParseOpCacheNext++);
100 }
101
102
103 /*******************************************************************************
104  *
105  * FUNCTION:    TrAllocateNode
106  *
107  * PARAMETERS:  ParseOpcode         - Opcode to be assigned to the node
108  *
109  * RETURN:      New parse node. Aborts on allocation failure
110  *
111  * DESCRIPTION: Allocate and initialize a new parse node for the parse tree
112  *
113  ******************************************************************************/
114
115 ACPI_PARSE_OBJECT *
116 TrAllocateNode (
117     UINT32                  ParseOpcode)
118 {
119     ACPI_PARSE_OBJECT       *Op;
120
121
122     Op = TrGetNextNode ();
123
124     Op->Asl.ParseOpcode       = (UINT16) ParseOpcode;
125     Op->Asl.Filename          = Gbl_Files[ASL_FILE_INPUT].Filename;
126     Op->Asl.LineNumber        = Gbl_CurrentLineNumber;
127     Op->Asl.LogicalLineNumber = Gbl_LogicalLineNumber;
128     Op->Asl.LogicalByteOffset = Gbl_CurrentLineOffset;
129     Op->Asl.Column            = Gbl_CurrentColumn;
130
131     UtSetParseOpName (Op);
132     return (Op);
133 }
134
135
136 /*******************************************************************************
137  *
138  * FUNCTION:    TrReleaseNode
139  *
140  * PARAMETERS:  Op            - Op to be released
141  *
142  * RETURN:      None
143  *
144  * DESCRIPTION: "release" a node. In truth, nothing is done since the node
145  *              is part of a larger buffer
146  *
147  ******************************************************************************/
148
149 void
150 TrReleaseNode (
151     ACPI_PARSE_OBJECT       *Op)
152 {
153
154     return;
155 }
156
157
158 /*******************************************************************************
159  *
160  * FUNCTION:    TrUpdateNode
161  *
162  * PARAMETERS:  ParseOpcode         - New opcode to be assigned to the node
163  *              Op                - An existing parse node
164  *
165  * RETURN:      The updated node
166  *
167  * DESCRIPTION: Change the parse opcode assigned to a node. Usually used to
168  *              change an opcode to DEFAULT_ARG so that the node is ignored
169  *              during the code generation. Also used to set generic integers
170  *              to a specific size (8, 16, 32, or 64 bits)
171  *
172  ******************************************************************************/
173
174 ACPI_PARSE_OBJECT *
175 TrUpdateNode (
176     UINT32                  ParseOpcode,
177     ACPI_PARSE_OBJECT       *Op)
178 {
179
180     if (!Op)
181     {
182         return (NULL);
183     }
184
185     DbgPrint (ASL_PARSE_OUTPUT,
186         "\nUpdateNode: Old - %s, New - %s\n",
187         UtGetOpName (Op->Asl.ParseOpcode),
188         UtGetOpName (ParseOpcode));
189
190     /* Assign new opcode and name */
191
192     if (Op->Asl.ParseOpcode == PARSEOP_ONES)
193     {
194         switch (ParseOpcode)
195         {
196         case PARSEOP_BYTECONST:
197
198             Op->Asl.Value.Integer = ACPI_UINT8_MAX;
199             break;
200
201         case PARSEOP_WORDCONST:
202
203             Op->Asl.Value.Integer = ACPI_UINT16_MAX;
204             break;
205
206         case PARSEOP_DWORDCONST:
207
208             Op->Asl.Value.Integer = ACPI_UINT32_MAX;
209             break;
210
211         /* Don't need to do the QWORD case */
212
213         default:
214
215             /* Don't care about others */
216             break;
217         }
218     }
219
220     Op->Asl.ParseOpcode = (UINT16) ParseOpcode;
221     UtSetParseOpName (Op);
222
223     /*
224      * For the BYTE, WORD, and DWORD constants, make sure that the integer
225      * that was passed in will actually fit into the data type
226      */
227     switch (ParseOpcode)
228     {
229     case PARSEOP_BYTECONST:
230
231         UtCheckIntegerRange (Op, 0x00, ACPI_UINT8_MAX);
232         Op->Asl.Value.Integer &= ACPI_UINT8_MAX;
233         break;
234
235     case PARSEOP_WORDCONST:
236
237         UtCheckIntegerRange (Op, 0x00, ACPI_UINT16_MAX);
238         Op->Asl.Value.Integer &= ACPI_UINT16_MAX;
239         break;
240
241     case PARSEOP_DWORDCONST:
242
243         UtCheckIntegerRange (Op, 0x00, ACPI_UINT32_MAX);
244         Op->Asl.Value.Integer &= ACPI_UINT32_MAX;
245         break;
246
247     default:
248
249         /* Don't care about others, don't need to check QWORD */
250
251         break;
252     }
253
254     return (Op);
255 }
256
257
258 /*******************************************************************************
259  *
260  * FUNCTION:    TrPrintNodeCompileFlags
261  *
262  * PARAMETERS:  Flags               - Flags word to be decoded
263  *
264  * RETURN:      None
265  *
266  * DESCRIPTION: Decode a flags word to text. Displays all flags that are set.
267  *
268  ******************************************************************************/
269
270 void
271 TrPrintNodeCompileFlags (
272     UINT32                  Flags)
273 {
274     UINT32                  i;
275     UINT32                  FlagBit = 1;
276     char                    *FlagName = NULL;
277
278
279     for (i = 0; i < 32; i++)
280     {
281         switch (Flags & FlagBit)
282         {
283         case NODE_VISITED:
284
285             FlagName = "NODE_VISITED";
286             break;
287
288         case NODE_AML_PACKAGE:
289
290             FlagName = "NODE_AML_PACKAGE";
291             break;
292
293         case NODE_IS_TARGET:
294
295             FlagName = "NODE_IS_TARGET";
296             break;
297
298         case NODE_IS_RESOURCE_DESC:
299
300             FlagName = "NODE_IS_RESOURCE_DESC";
301             break;
302
303         case NODE_IS_RESOURCE_FIELD:
304
305             FlagName = "NODE_IS_RESOURCE_FIELD";
306             break;
307
308         case NODE_HAS_NO_EXIT:
309
310             FlagName = "NODE_HAS_NO_EXIT";
311             break;
312
313         case NODE_IF_HAS_NO_EXIT:
314
315             FlagName = "NODE_IF_HAS_NO_EXIT";
316             break;
317
318         case NODE_NAME_INTERNALIZED:
319
320             FlagName = "NODE_NAME_INTERNALIZED";
321             break;
322
323         case NODE_METHOD_NO_RETVAL:
324
325             FlagName = "NODE_METHOD_NO_RETVAL";
326             break;
327
328         case NODE_METHOD_SOME_NO_RETVAL:
329
330             FlagName = "NODE_METHOD_SOME_NO_RETVAL";
331             break;
332
333         case NODE_RESULT_NOT_USED:
334
335             FlagName = "NODE_RESULT_NOT_USED";
336             break;
337
338         case NODE_METHOD_TYPED:
339
340             FlagName = "NODE_METHOD_TYPED";
341             break;
342
343         case NODE_COMPILE_TIME_CONST:
344
345             FlagName = "NODE_COMPILE_TIME_CONST";
346             break;
347
348         case NODE_IS_TERM_ARG:
349
350             FlagName = "NODE_IS_TERM_ARG";
351             break;
352
353         case NODE_WAS_ONES_OP:
354
355             FlagName = "NODE_WAS_ONES_OP";
356             break;
357
358         case NODE_IS_NAME_DECLARATION:
359
360             FlagName = "NODE_IS_NAME_DECLARATION";
361             break;
362
363         case NODE_COMPILER_EMITTED:
364
365             FlagName = "NODE_COMPILER_EMITTED";
366             break;
367
368         case NODE_IS_DUPLICATE:
369
370             FlagName = "NODE_IS_DUPLICATE";
371             break;
372
373         case NODE_IS_RESOURCE_DATA:
374
375             FlagName = "NODE_IS_RESOURCE_DATA";
376             break;
377
378         case NODE_IS_NULL_RETURN:
379
380             FlagName = "NODE_IS_NULL_RETURN";
381             break;
382
383         default:
384             break;
385         }
386
387         if (FlagName)
388         {
389             DbgPrint (ASL_PARSE_OUTPUT, " %s", FlagName);
390             FlagName = NULL;
391         }
392
393         FlagBit <<= 1;
394     }
395 }
396
397
398 /*******************************************************************************
399  *
400  * FUNCTION:    TrSetNodeFlags
401  *
402  * PARAMETERS:  Op                  - An existing parse node
403  *              Flags               - New flags word
404  *
405  * RETURN:      The updated parser op
406  *
407  * DESCRIPTION: Set bits in the node flags word. Will not clear bits, only set
408  *
409  ******************************************************************************/
410
411 ACPI_PARSE_OBJECT *
412 TrSetNodeFlags (
413     ACPI_PARSE_OBJECT       *Op,
414     UINT32                  Flags)
415 {
416
417     if (!Op)
418     {
419         return (NULL);
420     }
421
422     DbgPrint (ASL_PARSE_OUTPUT,
423         "\nSetNodeFlags: %s Op %p, %8.8X", Op->Asl.ParseOpName, Op, Flags);
424
425     TrPrintNodeCompileFlags (Flags);
426     DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
427
428     Op->Asl.CompileFlags |= Flags;
429     return (Op);
430 }
431
432
433 /*******************************************************************************
434  *
435  * FUNCTION:    TrSetNodeAmlLength
436  *
437  * PARAMETERS:  Op                  - An existing parse node
438  *              Length              - AML Length
439  *
440  * RETURN:      The updated parser op
441  *
442  * DESCRIPTION: Set the AML Length in a node. Used by the parser to indicate
443  *              the presence of a node that must be reduced to a fixed length
444  *              constant.
445  *
446  ******************************************************************************/
447
448 ACPI_PARSE_OBJECT *
449 TrSetNodeAmlLength (
450     ACPI_PARSE_OBJECT       *Op,
451     UINT32                  Length)
452 {
453
454     DbgPrint (ASL_PARSE_OUTPUT,
455         "\nSetNodeAmlLength: Op %p, %8.8X\n", Op, Length);
456
457     if (!Op)
458     {
459         return (NULL);
460     }
461
462     Op->Asl.AmlLength = Length;
463     return (Op);
464 }
465
466
467 /*******************************************************************************
468  *
469  * FUNCTION:    TrSetEndLineNumber
470  *
471  * PARAMETERS:  Op                - An existing parse node
472  *
473  * RETURN:      None.
474  *
475  * DESCRIPTION: Set the ending line numbers (file line and logical line) of a
476  *              parse node to the current line numbers.
477  *
478  ******************************************************************************/
479
480 void
481 TrSetEndLineNumber (
482     ACPI_PARSE_OBJECT       *Op)
483 {
484
485     /* If the end line # is already set, just return */
486
487     if (Op->Asl.EndLine)
488     {
489         return;
490     }
491
492     Op->Asl.EndLine        = Gbl_CurrentLineNumber;
493     Op->Asl.EndLogicalLine = Gbl_LogicalLineNumber;
494 }
495
496
497 /*******************************************************************************
498  *
499  * FUNCTION:    TrCreateAssignmentNode
500  *
501  * PARAMETERS:  Target              - Assignment target
502  *              Source              - Assignment source
503  *
504  * RETURN:      Pointer to the new node. Aborts on allocation failure
505  *
506  * DESCRIPTION: Implements the C-style '=' operator. It changes the parse
507  *              tree if possible to utilize the last argument of the math
508  *              operators which is a target operand -- thus saving invocation
509  *              of and additional Store() operator. An optimization.
510  *
511  ******************************************************************************/
512
513 ACPI_PARSE_OBJECT *
514 TrCreateAssignmentNode (
515     ACPI_PARSE_OBJECT       *Target,
516     ACPI_PARSE_OBJECT       *Source)
517 {
518     ACPI_PARSE_OBJECT       *TargetOp;
519     ACPI_PARSE_OBJECT       *SourceOp1;
520     ACPI_PARSE_OBJECT       *SourceOp2;
521     ACPI_PARSE_OBJECT       *Operator;
522
523
524     DbgPrint (ASL_PARSE_OUTPUT,
525         "\nTrCreateAssignmentNode  Line [%u to %u] Source %s Target %s\n",
526         Source->Asl.LineNumber, Source->Asl.EndLine,
527         UtGetOpName (Source->Asl.ParseOpcode),
528         UtGetOpName (Target->Asl.ParseOpcode));
529
530     TrSetNodeFlags (Target, NODE_IS_TARGET);
531
532     switch (Source->Asl.ParseOpcode)
533     {
534     /*
535      * Only these operators can be optimized because they have
536      * a target operand
537      */
538     case PARSEOP_ADD:
539     case PARSEOP_AND:
540     case PARSEOP_DIVIDE:
541     case PARSEOP_MOD:
542     case PARSEOP_MULTIPLY:
543     case PARSEOP_NOT:
544     case PARSEOP_OR:
545     case PARSEOP_SHIFTLEFT:
546     case PARSEOP_SHIFTRIGHT:
547     case PARSEOP_SUBTRACT:
548     case PARSEOP_XOR:
549
550         break;
551
552     /* Otherwise, just create a normal Store operator */
553
554     default:
555
556         goto CannotOptimize;
557     }
558
559     /*
560      * Transform the parse tree such that the target is moved to the
561      * last operand of the operator
562      */
563     SourceOp1 = Source->Asl.Child;
564     SourceOp2 = SourceOp1->Asl.Next;
565
566     /* NOT only has one operand, but has a target */
567
568     if (Source->Asl.ParseOpcode == PARSEOP_NOT)
569     {
570         SourceOp2 = SourceOp1;
571     }
572
573     /* DIVIDE has an extra target operand (remainder) */
574
575     if (Source->Asl.ParseOpcode == PARSEOP_DIVIDE)
576     {
577         SourceOp2 = SourceOp2->Asl.Next;
578     }
579
580     TargetOp = SourceOp2->Asl.Next;
581
582     /*
583      * Can't perform this optimization if there already is a target
584      * for the operator (ZERO is a "no target" placeholder).
585      */
586     if (TargetOp->Asl.ParseOpcode != PARSEOP_ZERO)
587     {
588         goto CannotOptimize;
589     }
590
591     /* Link in the target as the final operand */
592
593     SourceOp2->Asl.Next = Target;
594     Target->Asl.Parent = Source;
595
596     return (Source);
597
598
599 CannotOptimize:
600
601     Operator = TrAllocateNode (PARSEOP_STORE);
602     TrLinkChildren (Operator, 2, Source, Target);
603
604     /* Set the appropriate line numbers for the new node */
605
606     Operator->Asl.LineNumber        = Target->Asl.LineNumber;
607     Operator->Asl.LogicalLineNumber = Target->Asl.LogicalLineNumber;
608     Operator->Asl.LogicalByteOffset = Target->Asl.LogicalByteOffset;
609     Operator->Asl.Column            = Target->Asl.Column;
610
611     return (Operator);
612 }
613
614
615 /*******************************************************************************
616  *
617  * FUNCTION:    TrCreateLeafNode
618  *
619  * PARAMETERS:  ParseOpcode         - New opcode to be assigned to the node
620  *
621  * RETURN:      Pointer to the new node. Aborts on allocation failure
622  *
623  * DESCRIPTION: Create a simple leaf node (no children or peers, and no value
624  *              assigned to the node)
625  *
626  ******************************************************************************/
627
628 ACPI_PARSE_OBJECT *
629 TrCreateLeafNode (
630     UINT32                  ParseOpcode)
631 {
632     ACPI_PARSE_OBJECT       *Op;
633
634
635     Op = TrAllocateNode (ParseOpcode);
636
637     DbgPrint (ASL_PARSE_OUTPUT,
638         "\nCreateLeafNode  Ln/Col %u/%u NewNode %p  Op %s\n\n",
639         Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName (ParseOpcode));
640
641     return (Op);
642 }
643
644
645 /*******************************************************************************
646  *
647  * FUNCTION:    TrCreateNullTarget
648  *
649  * PARAMETERS:  None
650  *
651  * RETURN:      Pointer to the new node. Aborts on allocation failure
652  *
653  * DESCRIPTION: Create a "null" target node. This is defined by the ACPI
654  *              specification to be a zero AML opcode, and indicates that
655  *              no target has been specified for the parent operation
656  *
657  ******************************************************************************/
658
659 ACPI_PARSE_OBJECT *
660 TrCreateNullTarget (
661     void)
662 {
663     ACPI_PARSE_OBJECT       *Op;
664
665
666     Op = TrAllocateNode (PARSEOP_ZERO);
667     Op->Asl.CompileFlags |= (NODE_IS_TARGET | NODE_COMPILE_TIME_CONST);
668
669     DbgPrint (ASL_PARSE_OUTPUT,
670         "\nCreateNullTarget  Ln/Col %u/%u NewNode %p  Op %s\n",
671         Op->Asl.LineNumber, Op->Asl.Column, Op,
672         UtGetOpName (Op->Asl.ParseOpcode));
673
674     return (Op);
675 }
676
677
678 /*******************************************************************************
679  *
680  * FUNCTION:    TrCreateConstantLeafNode
681  *
682  * PARAMETERS:  ParseOpcode         - The constant opcode
683  *
684  * RETURN:      Pointer to the new node. Aborts on allocation failure
685  *
686  * DESCRIPTION: Create a leaf node (no children or peers) for one of the
687  *              special constants - __LINE__, __FILE__, and __DATE__.
688  *
689  * Note: An implemenation of __FUNC__ cannot happen here because we don't
690  * have a full parse tree at this time and cannot find the parent control
691  * method. If it is ever needed, __FUNC__ must be implemented later, after
692  * the parse tree has been fully constructed.
693  *
694  ******************************************************************************/
695
696 ACPI_PARSE_OBJECT *
697 TrCreateConstantLeafNode (
698     UINT32                  ParseOpcode)
699 {
700     ACPI_PARSE_OBJECT       *Op = NULL;
701     time_t                  CurrentTime;
702     char                    *StaticTimeString;
703     char                    *TimeString;
704     char                    *Filename;
705
706
707     switch (ParseOpcode)
708     {
709     case PARSEOP___LINE__:
710
711         Op = TrAllocateNode (PARSEOP_INTEGER);
712         Op->Asl.Value.Integer = Op->Asl.LineNumber;
713         break;
714
715     case PARSEOP___PATH__:
716
717         Op = TrAllocateNode (PARSEOP_STRING_LITERAL);
718
719         /* Op.Asl.Filename contains the full pathname to the file */
720
721         Op->Asl.Value.String = Op->Asl.Filename;
722         break;
723
724     case PARSEOP___FILE__:
725
726         Op = TrAllocateNode (PARSEOP_STRING_LITERAL);
727
728         /* Get the simple filename from the full path */
729
730         FlSplitInputPathname (Op->Asl.Filename, NULL, &Filename);
731         Op->Asl.Value.String = Filename;
732         break;
733
734     case PARSEOP___DATE__:
735
736         Op = TrAllocateNode (PARSEOP_STRING_LITERAL);
737
738         /* Get a copy of the current time */
739
740         CurrentTime = time (NULL);
741         StaticTimeString = ctime (&CurrentTime);
742         TimeString = UtLocalCalloc (strlen (StaticTimeString) + 1);
743         strcpy (TimeString, StaticTimeString);
744
745         TimeString[strlen(TimeString) -1] = 0;  /* Remove trailing newline */
746         Op->Asl.Value.String = TimeString;
747         break;
748
749     default: /* This would be an internal error */
750
751         return (NULL);
752     }
753
754     DbgPrint (ASL_PARSE_OUTPUT,
755         "\nCreateConstantLeafNode  Ln/Col %u/%u NewNode %p  Op %s  Value %8.8X%8.8X  \n",
756         Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName (ParseOpcode),
757         ACPI_FORMAT_UINT64 (Op->Asl.Value.Integer));
758     return (Op);
759 }
760
761
762 /*******************************************************************************
763  *
764  * FUNCTION:    TrCreateTargetOperand
765  *
766  * PARAMETERS:  OriginalOp          - Op to be copied
767  *
768  * RETURN:      Pointer to the new node. Aborts on allocation failure
769  *
770  * DESCRIPTION: Copy an existing node (and subtree). Used in ASL+ (C-style)
771  *              expressions where the target is the same as one of the
772  *              operands. A new node and subtree must be created from the
773  *              original so that the parse tree can be linked properly.
774  *
775  * NOTE:        This code is specific to target operands that are the last
776  *              operand in an ASL/AML operator. Meaning that the top-level
777  *              parse Op in a possible subtree has a NULL Next pointer.
778  *              This simplifies the recursion.
779  *
780  *              Subtree example:
781  *                  DeRefOf (Local1) += 32
782  *
783  *              This gets converted to:
784  *                  Add (DeRefOf (Local1), 32, DeRefOf (Local1))
785  *
786  *              Each DeRefOf has a single child, Local1. Even more complex
787  *              subtrees can be created via the Index and DeRefOf operators.
788  *
789  ******************************************************************************/
790
791 ACPI_PARSE_OBJECT *
792 TrCreateTargetOperand (
793     ACPI_PARSE_OBJECT       *OriginalOp,
794     ACPI_PARSE_OBJECT       *ParentOp)
795 {
796     ACPI_PARSE_OBJECT       *Op;
797
798
799     if (!OriginalOp)
800     {
801         return (NULL);
802     }
803
804     Op = TrGetNextNode ();
805
806     /* Copy the pertinent values (omit link pointer fields) */
807
808     Op->Asl.Value               = OriginalOp->Asl.Value;
809     Op->Asl.Filename            = OriginalOp->Asl.Filename;
810     Op->Asl.LineNumber          = OriginalOp->Asl.LineNumber;
811     Op->Asl.LogicalLineNumber   = OriginalOp->Asl.LogicalLineNumber;
812     Op->Asl.LogicalByteOffset   = OriginalOp->Asl.LogicalByteOffset;
813     Op->Asl.Column              = OriginalOp->Asl.Column;
814     Op->Asl.Flags               = OriginalOp->Asl.Flags;
815     Op->Asl.CompileFlags        = OriginalOp->Asl.CompileFlags;
816     Op->Asl.AmlOpcode           = OriginalOp->Asl.AmlOpcode;
817     Op->Asl.ParseOpcode         = OriginalOp->Asl.ParseOpcode;
818     Op->Asl.Parent              = ParentOp;
819     UtSetParseOpName (Op);
820
821     /* Copy a possible subtree below this node */
822
823     if (OriginalOp->Asl.Child)
824     {
825         Op->Asl.Child = TrCreateTargetOperand (OriginalOp->Asl.Child, Op);
826     }
827
828     if (OriginalOp->Asl.Next) /* Null for top-level node */
829     {
830         Op->Asl.Next = TrCreateTargetOperand (OriginalOp->Asl.Next, ParentOp);
831     }
832
833     return (Op);
834 }
835
836
837 /*******************************************************************************
838  *
839  * FUNCTION:    TrCreateValuedLeafNode
840  *
841  * PARAMETERS:  ParseOpcode         - New opcode to be assigned to the node
842  *              Value               - Value to be assigned to the node
843  *
844  * RETURN:      Pointer to the new node. Aborts on allocation failure
845  *
846  * DESCRIPTION: Create a leaf node (no children or peers) with a value
847  *              assigned to it
848  *
849  ******************************************************************************/
850
851 ACPI_PARSE_OBJECT *
852 TrCreateValuedLeafNode (
853     UINT32                  ParseOpcode,
854     UINT64                  Value)
855 {
856     ACPI_PARSE_OBJECT       *Op;
857
858
859     Op = TrAllocateNode (ParseOpcode);
860
861     DbgPrint (ASL_PARSE_OUTPUT,
862         "\nCreateValuedLeafNode  Ln/Col %u/%u NewNode %p  Op %s  Value %8.8X%8.8X  ",
863         Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName(ParseOpcode),
864         ACPI_FORMAT_UINT64 (Value));
865     Op->Asl.Value.Integer = Value;
866
867     switch (ParseOpcode)
868     {
869     case PARSEOP_STRING_LITERAL:
870
871         DbgPrint (ASL_PARSE_OUTPUT, "STRING->%s", Value);
872         break;
873
874     case PARSEOP_NAMESEG:
875
876         DbgPrint (ASL_PARSE_OUTPUT, "NAMESEG->%s", Value);
877         break;
878
879     case PARSEOP_NAMESTRING:
880
881         DbgPrint (ASL_PARSE_OUTPUT, "NAMESTRING->%s", Value);
882         break;
883
884     case PARSEOP_EISAID:
885
886         DbgPrint (ASL_PARSE_OUTPUT, "EISAID->%s", Value);
887         break;
888
889     case PARSEOP_METHOD:
890
891         DbgPrint (ASL_PARSE_OUTPUT, "METHOD");
892         break;
893
894     case PARSEOP_INTEGER:
895
896         DbgPrint (ASL_PARSE_OUTPUT, "INTEGER->%8.8X%8.8X",
897             ACPI_FORMAT_UINT64 (Value));
898         break;
899
900     default:
901
902         break;
903     }
904
905     DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
906     return (Op);
907 }
908
909
910 /*******************************************************************************
911  *
912  * FUNCTION:    TrCreateNode
913  *
914  * PARAMETERS:  ParseOpcode         - Opcode to be assigned to the node
915  *              NumChildren         - Number of children to follow
916  *              ...                 - A list of child nodes to link to the new
917  *                                    node. NumChildren long.
918  *
919  * RETURN:      Pointer to the new node. Aborts on allocation failure
920  *
921  * DESCRIPTION: Create a new parse node and link together a list of child
922  *              nodes underneath the new node.
923  *
924  ******************************************************************************/
925
926 ACPI_PARSE_OBJECT *
927 TrCreateNode (
928     UINT32                  ParseOpcode,
929     UINT32                  NumChildren,
930     ...)
931 {
932     ACPI_PARSE_OBJECT       *Op;
933     ACPI_PARSE_OBJECT       *Child;
934     ACPI_PARSE_OBJECT       *PrevChild;
935     va_list                 ap;
936     UINT32                  i;
937     BOOLEAN                 FirstChild;
938
939
940     va_start (ap, NumChildren);
941
942     /* Allocate one new node */
943
944     Op = TrAllocateNode (ParseOpcode);
945
946     DbgPrint (ASL_PARSE_OUTPUT,
947         "\nCreateNode  Ln/Col %u/%u NewParent %p Child %u Op %s  ",
948         Op->Asl.LineNumber, Op->Asl.Column, Op, NumChildren, UtGetOpName(ParseOpcode));
949
950     /* Some extra debug output based on the parse opcode */
951
952     switch (ParseOpcode)
953     {
954     case PARSEOP_DEFINITIONBLOCK:
955
956         RootNode = Op;
957         DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->");
958         break;
959
960     case PARSEOP_OPERATIONREGION:
961
962         DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->");
963         break;
964
965     case PARSEOP_OR:
966
967         DbgPrint (ASL_PARSE_OUTPUT, "OR->");
968         break;
969
970     default:
971
972         /* Nothing to do for other opcodes */
973
974         break;
975     }
976
977     /* Link the new node to its children */
978
979     PrevChild = NULL;
980     FirstChild = TRUE;
981     for (i = 0; i < NumChildren; i++)
982     {
983         /* Get the next child */
984
985         Child = va_arg (ap, ACPI_PARSE_OBJECT *);
986         DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child);
987
988         /*
989          * If child is NULL, this means that an optional argument
990          * was omitted. We must create a placeholder with a special
991          * opcode (DEFAULT_ARG) so that the code generator will know
992          * that it must emit the correct default for this argument
993          */
994         if (!Child)
995         {
996             Child = TrAllocateNode (PARSEOP_DEFAULT_ARG);
997         }
998
999         /* Link first child to parent */
1000
1001         if (FirstChild)
1002         {
1003             FirstChild = FALSE;
1004             Op->Asl.Child = Child;
1005         }
1006
1007         /* Point all children to parent */
1008
1009         Child->Asl.Parent = Op;
1010
1011         /* Link children in a peer list */
1012
1013         if (PrevChild)
1014         {
1015             PrevChild->Asl.Next = Child;
1016         };
1017
1018         /*
1019          * This child might be a list, point all nodes in the list
1020          * to the same parent
1021          */
1022         while (Child->Asl.Next)
1023         {
1024             Child = Child->Asl.Next;
1025             Child->Asl.Parent = Op;
1026         }
1027
1028         PrevChild = Child;
1029     }
1030     va_end(ap);
1031
1032     DbgPrint (ASL_PARSE_OUTPUT, "\n");
1033     return (Op);
1034 }
1035
1036
1037 /*******************************************************************************
1038  *
1039  * FUNCTION:    TrLinkChildren
1040  *
1041  * PARAMETERS:  Op                - An existing parse node
1042  *              NumChildren         - Number of children to follow
1043  *              ...                 - A list of child nodes to link to the new
1044  *                                    node. NumChildren long.
1045  *
1046  * RETURN:      The updated (linked) node
1047  *
1048  * DESCRIPTION: Link a group of nodes to an existing parse node
1049  *
1050  ******************************************************************************/
1051
1052 ACPI_PARSE_OBJECT *
1053 TrLinkChildren (
1054     ACPI_PARSE_OBJECT       *Op,
1055     UINT32                  NumChildren,
1056     ...)
1057 {
1058     ACPI_PARSE_OBJECT       *Child;
1059     ACPI_PARSE_OBJECT       *PrevChild;
1060     va_list                 ap;
1061     UINT32                  i;
1062     BOOLEAN                 FirstChild;
1063
1064
1065     va_start (ap, NumChildren);
1066
1067
1068     TrSetEndLineNumber (Op);
1069
1070     DbgPrint (ASL_PARSE_OUTPUT,
1071         "\nLinkChildren  Line [%u to %u] NewParent %p Child %u Op %s  ",
1072         Op->Asl.LineNumber, Op->Asl.EndLine,
1073         Op, NumChildren, UtGetOpName(Op->Asl.ParseOpcode));
1074
1075     switch (Op->Asl.ParseOpcode)
1076     {
1077     case PARSEOP_DEFINITIONBLOCK:
1078
1079         RootNode = Op;
1080         DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->");
1081         break;
1082
1083     case PARSEOP_OPERATIONREGION:
1084
1085         DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->");
1086         break;
1087
1088     case PARSEOP_OR:
1089
1090         DbgPrint (ASL_PARSE_OUTPUT, "OR->");
1091         break;
1092
1093     default:
1094
1095         /* Nothing to do for other opcodes */
1096
1097         break;
1098     }
1099
1100     /* Link the new node to it's children */
1101
1102     PrevChild = NULL;
1103     FirstChild = TRUE;
1104     for (i = 0; i < NumChildren; i++)
1105     {
1106         Child = va_arg (ap, ACPI_PARSE_OBJECT *);
1107
1108         if ((Child == PrevChild) && (Child != NULL))
1109         {
1110             AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Child,
1111                 "Child node list invalid");
1112             va_end(ap);
1113             return (Op);
1114         }
1115
1116         DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child);
1117
1118         /*
1119          * If child is NULL, this means that an optional argument
1120          * was omitted. We must create a placeholder with a special
1121          * opcode (DEFAULT_ARG) so that the code generator will know
1122          * that it must emit the correct default for this argument
1123          */
1124         if (!Child)
1125         {
1126             Child = TrAllocateNode (PARSEOP_DEFAULT_ARG);
1127         }
1128
1129         /* Link first child to parent */
1130
1131         if (FirstChild)
1132         {
1133             FirstChild = FALSE;
1134             Op->Asl.Child = Child;
1135         }
1136
1137         /* Point all children to parent */
1138
1139         Child->Asl.Parent = Op;
1140
1141         /* Link children in a peer list */
1142
1143         if (PrevChild)
1144         {
1145             PrevChild->Asl.Next = Child;
1146         };
1147
1148         /*
1149          * This child might be a list, point all nodes in the list
1150          * to the same parent
1151          */
1152         while (Child->Asl.Next)
1153         {
1154             Child = Child->Asl.Next;
1155             Child->Asl.Parent = Op;
1156         }
1157         PrevChild = Child;
1158     }
1159
1160     va_end(ap);
1161     DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
1162     return (Op);
1163 }
1164
1165
1166 /*******************************************************************************
1167  *
1168  * FUNCTION:    TrLinkPeerNode
1169  *
1170  * PARAMETERS:  Op1           - First peer
1171  *              Op2           - Second peer
1172  *
1173  * RETURN:      Op1 or the non-null node.
1174  *
1175  * DESCRIPTION: Link two nodes as peers. Handles cases where one peer is null.
1176  *
1177  ******************************************************************************/
1178
1179 ACPI_PARSE_OBJECT *
1180 TrLinkPeerNode (
1181     ACPI_PARSE_OBJECT       *Op1,
1182     ACPI_PARSE_OBJECT       *Op2)
1183 {
1184     ACPI_PARSE_OBJECT       *Next;
1185
1186
1187     DbgPrint (ASL_PARSE_OUTPUT,
1188         "\nLinkPeerNode: 1=%p (%s), 2=%p (%s)\n",
1189         Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode) : NULL,
1190         Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode) : NULL);
1191
1192
1193     if ((!Op1) && (!Op2))
1194     {
1195         DbgPrint (ASL_PARSE_OUTPUT, "\nTwo Null nodes!\n");
1196         return (Op1);
1197     }
1198
1199     /* If one of the nodes is null, just return the non-null node */
1200
1201     if (!Op2)
1202     {
1203         return (Op1);
1204     }
1205
1206     if (!Op1)
1207     {
1208         return (Op2);
1209     }
1210
1211     if (Op1 == Op2)
1212     {
1213         DbgPrint (ASL_DEBUG_OUTPUT,
1214             "\n************* Internal error, linking node to itself %p\n",
1215             Op1);
1216         AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op1,
1217             "Linking node to itself");
1218         return (Op1);
1219     }
1220
1221     Op1->Asl.Parent = Op2->Asl.Parent;
1222
1223     /*
1224      * Op 1 may already have a peer list (such as an IF/ELSE pair),
1225      * so we must walk to the end of the list and attach the new
1226      * peer at the end
1227      */
1228     Next = Op1;
1229     while (Next->Asl.Next)
1230     {
1231         Next = Next->Asl.Next;
1232     }
1233
1234     Next->Asl.Next = Op2;
1235     return (Op1);
1236 }
1237
1238
1239 /*******************************************************************************
1240  *
1241  * FUNCTION:    TrLinkPeerNodes
1242  *
1243  * PARAMETERS:  NumPeers            - The number of nodes in the list to follow
1244  *              ...                 - A list of nodes to link together as peers
1245  *
1246  * RETURN:      The first node in the list (head of the peer list)
1247  *
1248  * DESCRIPTION: Link together an arbitrary number of peer nodes.
1249  *
1250  ******************************************************************************/
1251
1252 ACPI_PARSE_OBJECT *
1253 TrLinkPeerNodes (
1254     UINT32                  NumPeers,
1255     ...)
1256 {
1257     ACPI_PARSE_OBJECT       *This;
1258     ACPI_PARSE_OBJECT       *Next;
1259     va_list                 ap;
1260     UINT32                  i;
1261     ACPI_PARSE_OBJECT       *Start;
1262
1263
1264     DbgPrint (ASL_PARSE_OUTPUT,
1265         "\nLinkPeerNodes: (%u) ", NumPeers);
1266
1267     va_start (ap, NumPeers);
1268     This = va_arg (ap, ACPI_PARSE_OBJECT *);
1269     Start = This;
1270
1271     /*
1272      * Link all peers
1273      */
1274     for (i = 0; i < (NumPeers -1); i++)
1275     {
1276         DbgPrint (ASL_PARSE_OUTPUT, "%u=%p ", (i+1), This);
1277
1278         while (This->Asl.Next)
1279         {
1280             This = This->Asl.Next;
1281         }
1282
1283         /* Get another peer node */
1284
1285         Next = va_arg (ap, ACPI_PARSE_OBJECT *);
1286         if (!Next)
1287         {
1288             Next = TrAllocateNode (PARSEOP_DEFAULT_ARG);
1289         }
1290
1291         /* link new node to the current node */
1292
1293         This->Asl.Next = Next;
1294         This = Next;
1295     }
1296     va_end (ap);
1297
1298     DbgPrint (ASL_PARSE_OUTPUT,"\n");
1299     return (Start);
1300 }
1301
1302
1303 /*******************************************************************************
1304  *
1305  * FUNCTION:    TrLinkChildNode
1306  *
1307  * PARAMETERS:  Op1           - Parent node
1308  *              Op2           - Op to become a child
1309  *
1310  * RETURN:      The parent node
1311  *
1312  * DESCRIPTION: Link two nodes together as a parent and child
1313  *
1314  ******************************************************************************/
1315
1316 ACPI_PARSE_OBJECT *
1317 TrLinkChildNode (
1318     ACPI_PARSE_OBJECT       *Op1,
1319     ACPI_PARSE_OBJECT       *Op2)
1320 {
1321     ACPI_PARSE_OBJECT       *Next;
1322
1323
1324     DbgPrint (ASL_PARSE_OUTPUT,
1325         "\nLinkChildNode: Parent=%p (%s), Child=%p (%s)\n",
1326         Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode): NULL,
1327         Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode): NULL);
1328
1329     if (!Op1 || !Op2)
1330     {
1331         return (Op1);
1332     }
1333
1334     Op1->Asl.Child = Op2;
1335
1336     /* Set the child and all peers of the child to point to the parent */
1337
1338     Next = Op2;
1339     while (Next)
1340     {
1341         Next->Asl.Parent = Op1;
1342         Next = Next->Asl.Next;
1343     }
1344
1345     return (Op1);
1346 }
1347
1348
1349 /*******************************************************************************
1350  *
1351  * FUNCTION:    TrWalkParseTree
1352  *
1353  * PARAMETERS:  Visitation              - Type of walk
1354  *              DescendingCallback      - Called during tree descent
1355  *              AscendingCallback       - Called during tree ascent
1356  *              Context                 - To be passed to the callbacks
1357  *
1358  * RETURN:      Status from callback(s)
1359  *
1360  * DESCRIPTION: Walk the entire parse tree.
1361  *
1362  ******************************************************************************/
1363
1364 ACPI_STATUS
1365 TrWalkParseTree (
1366     ACPI_PARSE_OBJECT       *Op,
1367     UINT32                  Visitation,
1368     ASL_WALK_CALLBACK       DescendingCallback,
1369     ASL_WALK_CALLBACK       AscendingCallback,
1370     void                    *Context)
1371 {
1372     UINT32                  Level;
1373     BOOLEAN                 NodePreviouslyVisited;
1374     ACPI_PARSE_OBJECT       *StartOp = Op;
1375     ACPI_STATUS             Status;
1376
1377
1378     if (!RootNode)
1379     {
1380         return (AE_OK);
1381     }
1382
1383     Level = 0;
1384     NodePreviouslyVisited = FALSE;
1385
1386     switch (Visitation)
1387     {
1388     case ASL_WALK_VISIT_DOWNWARD:
1389
1390         while (Op)
1391         {
1392             if (!NodePreviouslyVisited)
1393             {
1394                 /* Let the callback process the node. */
1395
1396                 Status = DescendingCallback (Op, Level, Context);
1397                 if (ACPI_SUCCESS (Status))
1398                 {
1399                     /* Visit children first, once */
1400
1401                     if (Op->Asl.Child)
1402                     {
1403                         Level++;
1404                         Op = Op->Asl.Child;
1405                         continue;
1406                     }
1407                 }
1408                 else if (Status != AE_CTRL_DEPTH)
1409                 {
1410                     /* Exit immediately on any error */
1411
1412                     return (Status);
1413                 }
1414             }
1415
1416             /* Terminate walk at start op */
1417
1418             if (Op == StartOp)
1419             {
1420                 break;
1421             }
1422
1423             /* No more children, visit peers */
1424
1425             if (Op->Asl.Next)
1426             {
1427                 Op = Op->Asl.Next;
1428                 NodePreviouslyVisited = FALSE;
1429             }
1430             else
1431             {
1432                 /* No children or peers, re-visit parent */
1433
1434                 if (Level != 0 )
1435                 {
1436                     Level--;
1437                 }
1438                 Op = Op->Asl.Parent;
1439                 NodePreviouslyVisited = TRUE;
1440             }
1441         }
1442         break;
1443
1444     case ASL_WALK_VISIT_UPWARD:
1445
1446         while (Op)
1447         {
1448             /* Visit leaf node (no children) or parent node on return trip */
1449
1450             if ((!Op->Asl.Child) ||
1451                 (NodePreviouslyVisited))
1452             {
1453                 /* Let the callback process the node. */
1454
1455                 Status = AscendingCallback (Op, Level, Context);
1456                 if (ACPI_FAILURE (Status))
1457                 {
1458                     return (Status);
1459                 }
1460             }
1461             else
1462             {
1463                 /* Visit children first, once */
1464
1465                 Level++;
1466                 Op = Op->Asl.Child;
1467                 continue;
1468             }
1469
1470             /* Terminate walk at start op */
1471
1472             if (Op == StartOp)
1473             {
1474                 break;
1475             }
1476
1477             /* No more children, visit peers */
1478
1479             if (Op->Asl.Next)
1480             {
1481                 Op = Op->Asl.Next;
1482                 NodePreviouslyVisited = FALSE;
1483             }
1484             else
1485             {
1486                 /* No children or peers, re-visit parent */
1487
1488                 if (Level != 0 )
1489                 {
1490                     Level--;
1491                 }
1492                 Op = Op->Asl.Parent;
1493                 NodePreviouslyVisited = TRUE;
1494             }
1495         }
1496         break;
1497
1498      case ASL_WALK_VISIT_TWICE:
1499
1500         while (Op)
1501         {
1502             if (NodePreviouslyVisited)
1503             {
1504                 Status = AscendingCallback (Op, Level, Context);
1505                 if (ACPI_FAILURE (Status))
1506                 {
1507                     return (Status);
1508                 }
1509             }
1510             else
1511             {
1512                 /* Let the callback process the node. */
1513
1514                 Status = DescendingCallback (Op, Level, Context);
1515                 if (ACPI_SUCCESS (Status))
1516                 {
1517                     /* Visit children first, once */
1518
1519                     if (Op->Asl.Child)
1520                     {
1521                         Level++;
1522                         Op = Op->Asl.Child;
1523                         continue;
1524                     }
1525                 }
1526                 else if (Status != AE_CTRL_DEPTH)
1527                 {
1528                     /* Exit immediately on any error */
1529
1530                     return (Status);
1531                 }
1532             }
1533
1534             /* Terminate walk at start op */
1535
1536             if (Op == StartOp)
1537             {
1538                 break;
1539             }
1540
1541             /* No more children, visit peers */
1542
1543             if (Op->Asl.Next)
1544             {
1545                 Op = Op->Asl.Next;
1546                 NodePreviouslyVisited = FALSE;
1547             }
1548             else
1549             {
1550                 /* No children or peers, re-visit parent */
1551
1552                 if (Level != 0 )
1553                 {
1554                     Level--;
1555                 }
1556                 Op = Op->Asl.Parent;
1557                 NodePreviouslyVisited = TRUE;
1558             }
1559         }
1560         break;
1561
1562     default:
1563         /* No other types supported */
1564         break;
1565     }
1566
1567     /* If we get here, the walk completed with no errors */
1568
1569     return (AE_OK);
1570 }