1 /******************************************************************************
3 * Module Name: asltree - parse tree management
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2015, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
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.
44 #include "aslcompiler.h"
45 #include "aslcompiler.y.h"
49 #define _COMPONENT ACPI_COMPILER
50 ACPI_MODULE_NAME ("asltree")
52 /* Local prototypes */
54 static ACPI_PARSE_OBJECT *
59 /*******************************************************************************
61 * FUNCTION: TrGetNextNode
65 * RETURN: New parse node. Aborts on allocation failure
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.)
71 ******************************************************************************/
73 static ACPI_PARSE_OBJECT *
77 ASL_CACHE_INFO *Cache;
80 if (Gbl_ParseOpCacheNext >= Gbl_ParseOpCacheLast)
82 /* Allocate a new buffer */
84 Cache = UtLocalCalloc (sizeof (Cache->Next) +
85 (sizeof (ACPI_PARSE_OBJECT) * ASL_PARSEOP_CACHE_SIZE));
87 /* Link new cache buffer to head of list */
89 Cache->Next = Gbl_ParseOpCacheList;
90 Gbl_ParseOpCacheList = Cache;
92 /* Setup cache management pointers */
94 Gbl_ParseOpCacheNext = ACPI_CAST_PTR (ACPI_PARSE_OBJECT, Cache->Buffer);
95 Gbl_ParseOpCacheLast = Gbl_ParseOpCacheNext + ASL_PARSEOP_CACHE_SIZE;
99 return (Gbl_ParseOpCacheNext++);
103 /*******************************************************************************
105 * FUNCTION: TrAllocateNode
107 * PARAMETERS: ParseOpcode - Opcode to be assigned to the node
109 * RETURN: New parse node. Aborts on allocation failure
111 * DESCRIPTION: Allocate and initialize a new parse node for the parse tree
113 ******************************************************************************/
119 ACPI_PARSE_OBJECT *Op;
122 Op = TrGetNextNode ();
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;
131 UtSetParseOpName (Op);
136 /*******************************************************************************
138 * FUNCTION: TrReleaseNode
140 * PARAMETERS: Op - Op to be released
144 * DESCRIPTION: "release" a node. In truth, nothing is done since the node
145 * is part of a larger buffer
147 ******************************************************************************/
151 ACPI_PARSE_OBJECT *Op)
158 /*******************************************************************************
160 * FUNCTION: TrUpdateNode
162 * PARAMETERS: ParseOpcode - New opcode to be assigned to the node
163 * Op - An existing parse node
165 * RETURN: The updated node
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)
172 ******************************************************************************/
177 ACPI_PARSE_OBJECT *Op)
185 DbgPrint (ASL_PARSE_OUTPUT,
186 "\nUpdateNode: Old - %s, New - %s\n",
187 UtGetOpName (Op->Asl.ParseOpcode),
188 UtGetOpName (ParseOpcode));
190 /* Assign new opcode and name */
192 if (Op->Asl.ParseOpcode == PARSEOP_ONES)
196 case PARSEOP_BYTECONST:
198 Op->Asl.Value.Integer = ACPI_UINT8_MAX;
201 case PARSEOP_WORDCONST:
203 Op->Asl.Value.Integer = ACPI_UINT16_MAX;
206 case PARSEOP_DWORDCONST:
208 Op->Asl.Value.Integer = ACPI_UINT32_MAX;
211 /* Don't need to do the QWORD case */
215 /* Don't care about others */
220 Op->Asl.ParseOpcode = (UINT16) ParseOpcode;
221 UtSetParseOpName (Op);
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
229 case PARSEOP_BYTECONST:
231 UtCheckIntegerRange (Op, 0x00, ACPI_UINT8_MAX);
232 Op->Asl.Value.Integer &= ACPI_UINT8_MAX;
235 case PARSEOP_WORDCONST:
237 UtCheckIntegerRange (Op, 0x00, ACPI_UINT16_MAX);
238 Op->Asl.Value.Integer &= ACPI_UINT16_MAX;
241 case PARSEOP_DWORDCONST:
243 UtCheckIntegerRange (Op, 0x00, ACPI_UINT32_MAX);
244 Op->Asl.Value.Integer &= ACPI_UINT32_MAX;
249 /* Don't care about others, don't need to check QWORD */
258 /*******************************************************************************
260 * FUNCTION: TrPrintNodeCompileFlags
262 * PARAMETERS: Flags - Flags word to be decoded
266 * DESCRIPTION: Decode a flags word to text. Displays all flags that are set.
268 ******************************************************************************/
271 TrPrintNodeCompileFlags (
276 char *FlagName = NULL;
279 for (i = 0; i < 32; i++)
281 switch (Flags & FlagBit)
285 FlagName = "NODE_VISITED";
288 case NODE_AML_PACKAGE:
290 FlagName = "NODE_AML_PACKAGE";
295 FlagName = "NODE_IS_TARGET";
298 case NODE_IS_RESOURCE_DESC:
300 FlagName = "NODE_IS_RESOURCE_DESC";
303 case NODE_IS_RESOURCE_FIELD:
305 FlagName = "NODE_IS_RESOURCE_FIELD";
308 case NODE_HAS_NO_EXIT:
310 FlagName = "NODE_HAS_NO_EXIT";
313 case NODE_IF_HAS_NO_EXIT:
315 FlagName = "NODE_IF_HAS_NO_EXIT";
318 case NODE_NAME_INTERNALIZED:
320 FlagName = "NODE_NAME_INTERNALIZED";
323 case NODE_METHOD_NO_RETVAL:
325 FlagName = "NODE_METHOD_NO_RETVAL";
328 case NODE_METHOD_SOME_NO_RETVAL:
330 FlagName = "NODE_METHOD_SOME_NO_RETVAL";
333 case NODE_RESULT_NOT_USED:
335 FlagName = "NODE_RESULT_NOT_USED";
338 case NODE_METHOD_TYPED:
340 FlagName = "NODE_METHOD_TYPED";
343 case NODE_COULD_NOT_REDUCE:
345 FlagName = "NODE_COULD_NOT_REDUCE";
348 case NODE_COMPILE_TIME_CONST:
350 FlagName = "NODE_COMPILE_TIME_CONST";
353 case NODE_IS_TERM_ARG:
355 FlagName = "NODE_IS_TERM_ARG";
358 case NODE_WAS_ONES_OP:
360 FlagName = "NODE_WAS_ONES_OP";
363 case NODE_IS_NAME_DECLARATION:
365 FlagName = "NODE_IS_NAME_DECLARATION";
368 case NODE_COMPILER_EMITTED:
370 FlagName = "NODE_COMPILER_EMITTED";
373 case NODE_IS_DUPLICATE:
375 FlagName = "NODE_IS_DUPLICATE";
378 case NODE_IS_RESOURCE_DATA:
380 FlagName = "NODE_IS_RESOURCE_DATA";
383 case NODE_IS_NULL_RETURN:
385 FlagName = "NODE_IS_NULL_RETURN";
394 DbgPrint (ASL_PARSE_OUTPUT, " %s", FlagName);
403 /*******************************************************************************
405 * FUNCTION: TrSetNodeFlags
407 * PARAMETERS: Op - An existing parse node
408 * Flags - New flags word
410 * RETURN: The updated parser op
412 * DESCRIPTION: Set bits in the node flags word. Will not clear bits, only set
414 ******************************************************************************/
418 ACPI_PARSE_OBJECT *Op,
427 DbgPrint (ASL_PARSE_OUTPUT,
428 "\nSetNodeFlags: %s Op %p, %8.8X", Op->Asl.ParseOpName, Op, Flags);
430 TrPrintNodeCompileFlags (Flags);
431 DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
433 Op->Asl.CompileFlags |= Flags;
438 /*******************************************************************************
440 * FUNCTION: TrSetNodeAmlLength
442 * PARAMETERS: Op - An existing parse node
443 * Length - AML Length
445 * RETURN: The updated parser op
447 * DESCRIPTION: Set the AML Length in a node. Used by the parser to indicate
448 * the presence of a node that must be reduced to a fixed length
451 ******************************************************************************/
455 ACPI_PARSE_OBJECT *Op,
459 DbgPrint (ASL_PARSE_OUTPUT,
460 "\nSetNodeAmlLength: Op %p, %8.8X\n", Op, Length);
467 Op->Asl.AmlLength = Length;
472 /*******************************************************************************
474 * FUNCTION: TrSetEndLineNumber
476 * PARAMETERS: Op - An existing parse node
480 * DESCRIPTION: Set the ending line numbers (file line and logical line) of a
481 * parse node to the current line numbers.
483 ******************************************************************************/
487 ACPI_PARSE_OBJECT *Op)
490 /* If the end line # is already set, just return */
497 Op->Asl.EndLine = Gbl_CurrentLineNumber;
498 Op->Asl.EndLogicalLine = Gbl_LogicalLineNumber;
502 /*******************************************************************************
504 * FUNCTION: TrCreateAssignmentNode
506 * PARAMETERS: Target - Assignment target
507 * Source - Assignment source
509 * RETURN: Pointer to the new node. Aborts on allocation failure
511 * DESCRIPTION: Implements the C-style '=' operator. It changes the parse
512 * tree if possible to utilize the last argument of the math
513 * operators which is a target operand -- thus saving invocation
514 * of and additional Store() operator. An optimization.
516 ******************************************************************************/
519 TrCreateAssignmentNode (
520 ACPI_PARSE_OBJECT *Target,
521 ACPI_PARSE_OBJECT *Source)
523 ACPI_PARSE_OBJECT *TargetOp;
524 ACPI_PARSE_OBJECT *SourceOp1;
525 ACPI_PARSE_OBJECT *SourceOp2;
526 ACPI_PARSE_OBJECT *Operator;
529 DbgPrint (ASL_PARSE_OUTPUT,
530 "\nTrCreateAssignmentNode Line [%u to %u] Source %s Target %s\n",
531 Source->Asl.LineNumber, Source->Asl.EndLine,
532 UtGetOpName (Source->Asl.ParseOpcode),
533 UtGetOpName (Target->Asl.ParseOpcode));
535 TrSetNodeFlags (Target, NODE_IS_TARGET);
537 switch (Source->Asl.ParseOpcode)
540 * Only these operators can be optimized because they have
548 case PARSEOP_MULTIPLY:
551 case PARSEOP_SHIFTLEFT:
552 case PARSEOP_SHIFTRIGHT:
553 case PARSEOP_SUBTRACT:
558 /* Otherwise, just create a normal Store operator */
566 * Transform the parse tree such that the target is moved to the
567 * last operand of the operator
569 SourceOp1 = Source->Asl.Child;
570 SourceOp2 = SourceOp1->Asl.Next;
572 /* NOT only has one operand, but has a target */
574 if (Source->Asl.ParseOpcode == PARSEOP_NOT)
576 SourceOp2 = SourceOp1;
579 /* DIVIDE has an extra target operand (remainder) */
581 if (Source->Asl.ParseOpcode == PARSEOP_DIVIDE)
583 SourceOp2 = SourceOp2->Asl.Next;
586 TargetOp = SourceOp2->Asl.Next;
589 * Can't perform this optimization if there already is a target
590 * for the operator (ZERO is a "no target" placeholder).
592 if (TargetOp->Asl.ParseOpcode != PARSEOP_ZERO)
597 /* Link in the target as the final operand */
599 SourceOp2->Asl.Next = Target;
600 Target->Asl.Parent = Source;
607 Operator = TrAllocateNode (PARSEOP_STORE);
608 TrLinkChildren (Operator, 2, Source, Target);
610 /* Set the appropriate line numbers for the new node */
612 Operator->Asl.LineNumber = Target->Asl.LineNumber;
613 Operator->Asl.LogicalLineNumber = Target->Asl.LogicalLineNumber;
614 Operator->Asl.LogicalByteOffset = Target->Asl.LogicalByteOffset;
615 Operator->Asl.Column = Target->Asl.Column;
621 /*******************************************************************************
623 * FUNCTION: TrCreateLeafNode
625 * PARAMETERS: ParseOpcode - New opcode to be assigned to the node
627 * RETURN: Pointer to the new node. Aborts on allocation failure
629 * DESCRIPTION: Create a simple leaf node (no children or peers, and no value
630 * assigned to the node)
632 ******************************************************************************/
638 ACPI_PARSE_OBJECT *Op;
641 Op = TrAllocateNode (ParseOpcode);
643 DbgPrint (ASL_PARSE_OUTPUT,
644 "\nCreateLeafNode Ln/Col %u/%u NewNode %p Op %s\n\n",
645 Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName (ParseOpcode));
651 /*******************************************************************************
653 * FUNCTION: TrCreateNullTarget
657 * RETURN: Pointer to the new node. Aborts on allocation failure
659 * DESCRIPTION: Create a "null" target node. This is defined by the ACPI
660 * specification to be a zero AML opcode, and indicates that
661 * no target has been specified for the parent operation
663 ******************************************************************************/
669 ACPI_PARSE_OBJECT *Op;
672 Op = TrAllocateNode (PARSEOP_ZERO);
673 Op->Asl.CompileFlags |= (NODE_IS_TARGET | NODE_COMPILE_TIME_CONST);
675 DbgPrint (ASL_PARSE_OUTPUT,
676 "\nCreateNullTarget Ln/Col %u/%u NewNode %p Op %s\n",
677 Op->Asl.LineNumber, Op->Asl.Column, Op,
678 UtGetOpName (Op->Asl.ParseOpcode));
684 /*******************************************************************************
686 * FUNCTION: TrCreateConstantLeafNode
688 * PARAMETERS: ParseOpcode - The constant opcode
690 * RETURN: Pointer to the new node. Aborts on allocation failure
692 * DESCRIPTION: Create a leaf node (no children or peers) for one of the
693 * special constants - __LINE__, __FILE__, and __DATE__.
695 * Note: An implemenation of __FUNC__ cannot happen here because we don't
696 * have a full parse tree at this time and cannot find the parent control
697 * method. If it is ever needed, __FUNC__ must be implemented later, after
698 * the parse tree has been fully constructed.
700 ******************************************************************************/
703 TrCreateConstantLeafNode (
706 ACPI_PARSE_OBJECT *Op = NULL;
708 char *StaticTimeString;
715 case PARSEOP___LINE__:
717 Op = TrAllocateNode (PARSEOP_INTEGER);
718 Op->Asl.Value.Integer = Op->Asl.LineNumber;
721 case PARSEOP___PATH__:
723 Op = TrAllocateNode (PARSEOP_STRING_LITERAL);
725 /* Op.Asl.Filename contains the full pathname to the file */
727 Op->Asl.Value.String = Op->Asl.Filename;
730 case PARSEOP___FILE__:
732 Op = TrAllocateNode (PARSEOP_STRING_LITERAL);
734 /* Get the simple filename from the full path */
736 FlSplitInputPathname (Op->Asl.Filename, NULL, &Filename);
737 Op->Asl.Value.String = Filename;
740 case PARSEOP___DATE__:
742 Op = TrAllocateNode (PARSEOP_STRING_LITERAL);
744 /* Get a copy of the current time */
746 CurrentTime = time (NULL);
747 StaticTimeString = ctime (&CurrentTime);
748 TimeString = UtLocalCalloc (strlen (StaticTimeString) + 1);
749 strcpy (TimeString, StaticTimeString);
751 TimeString[strlen(TimeString) -1] = 0; /* Remove trailing newline */
752 Op->Asl.Value.String = TimeString;
755 default: /* This would be an internal error */
760 DbgPrint (ASL_PARSE_OUTPUT,
761 "\nCreateConstantLeafNode Ln/Col %u/%u NewNode %p "
762 "Op %s Value %8.8X%8.8X \n",
763 Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName (ParseOpcode),
764 ACPI_FORMAT_UINT64 (Op->Asl.Value.Integer));
769 /*******************************************************************************
771 * FUNCTION: TrCreateTargetOperand
773 * PARAMETERS: OriginalOp - Op to be copied
775 * RETURN: Pointer to the new node. Aborts on allocation failure
777 * DESCRIPTION: Copy an existing node (and subtree). Used in ASL+ (C-style)
778 * expressions where the target is the same as one of the
779 * operands. A new node and subtree must be created from the
780 * original so that the parse tree can be linked properly.
782 * NOTE: This code is specific to target operands that are the last
783 * operand in an ASL/AML operator. Meaning that the top-level
784 * parse Op in a possible subtree has a NULL Next pointer.
785 * This simplifies the recursion.
788 * DeRefOf (Local1) += 32
790 * This gets converted to:
791 * Add (DeRefOf (Local1), 32, DeRefOf (Local1))
793 * Each DeRefOf has a single child, Local1. Even more complex
794 * subtrees can be created via the Index and DeRefOf operators.
796 ******************************************************************************/
799 TrCreateTargetOperand (
800 ACPI_PARSE_OBJECT *OriginalOp,
801 ACPI_PARSE_OBJECT *ParentOp)
803 ACPI_PARSE_OBJECT *Op;
811 Op = TrGetNextNode ();
813 /* Copy the pertinent values (omit link pointer fields) */
815 Op->Asl.Value = OriginalOp->Asl.Value;
816 Op->Asl.Filename = OriginalOp->Asl.Filename;
817 Op->Asl.LineNumber = OriginalOp->Asl.LineNumber;
818 Op->Asl.LogicalLineNumber = OriginalOp->Asl.LogicalLineNumber;
819 Op->Asl.LogicalByteOffset = OriginalOp->Asl.LogicalByteOffset;
820 Op->Asl.Column = OriginalOp->Asl.Column;
821 Op->Asl.Flags = OriginalOp->Asl.Flags;
822 Op->Asl.CompileFlags = OriginalOp->Asl.CompileFlags;
823 Op->Asl.AmlOpcode = OriginalOp->Asl.AmlOpcode;
824 Op->Asl.ParseOpcode = OriginalOp->Asl.ParseOpcode;
825 Op->Asl.Parent = ParentOp;
826 UtSetParseOpName (Op);
828 /* Copy a possible subtree below this node */
830 if (OriginalOp->Asl.Child)
832 Op->Asl.Child = TrCreateTargetOperand (OriginalOp->Asl.Child, Op);
835 if (OriginalOp->Asl.Next) /* Null for top-level node */
837 Op->Asl.Next = TrCreateTargetOperand (OriginalOp->Asl.Next, ParentOp);
844 /*******************************************************************************
846 * FUNCTION: TrCreateValuedLeafNode
848 * PARAMETERS: ParseOpcode - New opcode to be assigned to the node
849 * Value - Value to be assigned to the node
851 * RETURN: Pointer to the new node. Aborts on allocation failure
853 * DESCRIPTION: Create a leaf node (no children or peers) with a value
856 ******************************************************************************/
859 TrCreateValuedLeafNode (
863 ACPI_PARSE_OBJECT *Op;
866 Op = TrAllocateNode (ParseOpcode);
868 DbgPrint (ASL_PARSE_OUTPUT,
869 "\nCreateValuedLeafNode Ln/Col %u/%u NewNode %p "
870 "Op %s Value %8.8X%8.8X ",
871 Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName(ParseOpcode),
872 ACPI_FORMAT_UINT64 (Value));
873 Op->Asl.Value.Integer = Value;
877 case PARSEOP_STRING_LITERAL:
879 DbgPrint (ASL_PARSE_OUTPUT, "STRING->%s", Value);
882 case PARSEOP_NAMESEG:
884 DbgPrint (ASL_PARSE_OUTPUT, "NAMESEG->%s", Value);
887 case PARSEOP_NAMESTRING:
889 DbgPrint (ASL_PARSE_OUTPUT, "NAMESTRING->%s", Value);
894 DbgPrint (ASL_PARSE_OUTPUT, "EISAID->%s", Value);
899 DbgPrint (ASL_PARSE_OUTPUT, "METHOD");
902 case PARSEOP_INTEGER:
904 DbgPrint (ASL_PARSE_OUTPUT, "INTEGER->%8.8X%8.8X",
905 ACPI_FORMAT_UINT64 (Value));
913 DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
918 /*******************************************************************************
920 * FUNCTION: TrCreateNode
922 * PARAMETERS: ParseOpcode - Opcode to be assigned to the node
923 * NumChildren - Number of children to follow
924 * ... - A list of child nodes to link to the new
925 * node. NumChildren long.
927 * RETURN: Pointer to the new node. Aborts on allocation failure
929 * DESCRIPTION: Create a new parse node and link together a list of child
930 * nodes underneath the new node.
932 ******************************************************************************/
940 ACPI_PARSE_OBJECT *Op;
941 ACPI_PARSE_OBJECT *Child;
942 ACPI_PARSE_OBJECT *PrevChild;
948 va_start (ap, NumChildren);
950 /* Allocate one new node */
952 Op = TrAllocateNode (ParseOpcode);
954 DbgPrint (ASL_PARSE_OUTPUT,
955 "\nCreateNode Ln/Col %u/%u NewParent %p Child %u Op %s ",
956 Op->Asl.LineNumber, Op->Asl.Column, Op,
957 NumChildren, UtGetOpName(ParseOpcode));
959 /* Some extra debug output based on the parse opcode */
963 case PARSEOP_ASL_CODE:
966 Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
967 DbgPrint (ASL_PARSE_OUTPUT, "ASLCODE (Tree Completed)->");
970 case PARSEOP_DEFINITION_BLOCK:
972 DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->");
975 case PARSEOP_OPERATIONREGION:
977 DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->");
982 DbgPrint (ASL_PARSE_OUTPUT, "OR->");
987 /* Nothing to do for other opcodes */
992 /* Link the new node to its children */
996 for (i = 0; i < NumChildren; i++)
998 /* Get the next child */
1000 Child = va_arg (ap, ACPI_PARSE_OBJECT *);
1001 DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child);
1004 * If child is NULL, this means that an optional argument
1005 * was omitted. We must create a placeholder with a special
1006 * opcode (DEFAULT_ARG) so that the code generator will know
1007 * that it must emit the correct default for this argument
1011 Child = TrAllocateNode (PARSEOP_DEFAULT_ARG);
1014 /* Link first child to parent */
1019 Op->Asl.Child = Child;
1022 /* Point all children to parent */
1024 Child->Asl.Parent = Op;
1026 /* Link children in a peer list */
1030 PrevChild->Asl.Next = Child;
1034 * This child might be a list, point all nodes in the list
1035 * to the same parent
1037 while (Child->Asl.Next)
1039 Child = Child->Asl.Next;
1040 Child->Asl.Parent = Op;
1047 DbgPrint (ASL_PARSE_OUTPUT, "\n");
1052 /*******************************************************************************
1054 * FUNCTION: TrLinkChildren
1056 * PARAMETERS: Op - An existing parse node
1057 * NumChildren - Number of children to follow
1058 * ... - A list of child nodes to link to the new
1059 * node. NumChildren long.
1061 * RETURN: The updated (linked) node
1063 * DESCRIPTION: Link a group of nodes to an existing parse node
1065 ******************************************************************************/
1069 ACPI_PARSE_OBJECT *Op,
1073 ACPI_PARSE_OBJECT *Child;
1074 ACPI_PARSE_OBJECT *PrevChild;
1080 va_start (ap, NumChildren);
1083 TrSetEndLineNumber (Op);
1085 DbgPrint (ASL_PARSE_OUTPUT,
1086 "\nLinkChildren Line [%u to %u] NewParent %p Child %u Op %s ",
1087 Op->Asl.LineNumber, Op->Asl.EndLine,
1088 Op, NumChildren, UtGetOpName(Op->Asl.ParseOpcode));
1090 switch (Op->Asl.ParseOpcode)
1092 case PARSEOP_ASL_CODE:
1095 Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1096 DbgPrint (ASL_PARSE_OUTPUT, "ASLCODE (Tree Completed)->");
1099 case PARSEOP_DEFINITION_BLOCK:
1101 DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->");
1104 case PARSEOP_OPERATIONREGION:
1106 DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->");
1111 DbgPrint (ASL_PARSE_OUTPUT, "OR->");
1116 /* Nothing to do for other opcodes */
1121 /* Link the new node to it's children */
1125 for (i = 0; i < NumChildren; i++)
1127 Child = va_arg (ap, ACPI_PARSE_OBJECT *);
1129 if ((Child == PrevChild) && (Child != NULL))
1131 AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Child,
1132 "Child node list invalid");
1137 DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child);
1140 * If child is NULL, this means that an optional argument
1141 * was omitted. We must create a placeholder with a special
1142 * opcode (DEFAULT_ARG) so that the code generator will know
1143 * that it must emit the correct default for this argument
1147 Child = TrAllocateNode (PARSEOP_DEFAULT_ARG);
1150 /* Link first child to parent */
1155 Op->Asl.Child = Child;
1158 /* Point all children to parent */
1160 Child->Asl.Parent = Op;
1162 /* Link children in a peer list */
1166 PrevChild->Asl.Next = Child;
1170 * This child might be a list, point all nodes in the list
1171 * to the same parent
1173 while (Child->Asl.Next)
1175 Child = Child->Asl.Next;
1176 Child->Asl.Parent = Op;
1183 DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
1188 /*******************************************************************************
1190 * FUNCTION: TrLinkPeerNode
1192 * PARAMETERS: Op1 - First peer
1195 * RETURN: Op1 or the non-null node.
1197 * DESCRIPTION: Link two nodes as peers. Handles cases where one peer is null.
1199 ******************************************************************************/
1203 ACPI_PARSE_OBJECT *Op1,
1204 ACPI_PARSE_OBJECT *Op2)
1206 ACPI_PARSE_OBJECT *Next;
1209 DbgPrint (ASL_PARSE_OUTPUT,
1210 "\nLinkPeerNode: 1=%p (%s), 2=%p (%s)\n",
1211 Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode) : NULL,
1212 Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode) : NULL);
1215 if ((!Op1) && (!Op2))
1217 DbgPrint (ASL_PARSE_OUTPUT, "\nTwo Null nodes!\n");
1221 /* If one of the nodes is null, just return the non-null node */
1235 DbgPrint (ASL_DEBUG_OUTPUT,
1236 "\n************* Internal error, linking node to itself %p\n",
1238 AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op1,
1239 "Linking node to itself");
1243 Op1->Asl.Parent = Op2->Asl.Parent;
1246 * Op 1 may already have a peer list (such as an IF/ELSE pair),
1247 * so we must walk to the end of the list and attach the new
1251 while (Next->Asl.Next)
1253 Next = Next->Asl.Next;
1256 Next->Asl.Next = Op2;
1261 /*******************************************************************************
1263 * FUNCTION: TrLinkPeerNodes
1265 * PARAMETERS: NumPeers - The number of nodes in the list to follow
1266 * ... - A list of nodes to link together as peers
1268 * RETURN: The first node in the list (head of the peer list)
1270 * DESCRIPTION: Link together an arbitrary number of peer nodes.
1272 ******************************************************************************/
1279 ACPI_PARSE_OBJECT *This;
1280 ACPI_PARSE_OBJECT *Next;
1283 ACPI_PARSE_OBJECT *Start;
1286 DbgPrint (ASL_PARSE_OUTPUT,
1287 "\nLinkPeerNodes: (%u) ", NumPeers);
1289 va_start (ap, NumPeers);
1290 This = va_arg (ap, ACPI_PARSE_OBJECT *);
1296 for (i = 0; i < (NumPeers -1); i++)
1298 DbgPrint (ASL_PARSE_OUTPUT, "%u=%p ", (i+1), This);
1300 while (This->Asl.Next)
1302 This = This->Asl.Next;
1305 /* Get another peer node */
1307 Next = va_arg (ap, ACPI_PARSE_OBJECT *);
1310 Next = TrAllocateNode (PARSEOP_DEFAULT_ARG);
1313 /* link new node to the current node */
1315 This->Asl.Next = Next;
1320 DbgPrint (ASL_PARSE_OUTPUT,"\n");
1325 /*******************************************************************************
1327 * FUNCTION: TrLinkChildNode
1329 * PARAMETERS: Op1 - Parent node
1330 * Op2 - Op to become a child
1332 * RETURN: The parent node
1334 * DESCRIPTION: Link two nodes together as a parent and child
1336 ******************************************************************************/
1340 ACPI_PARSE_OBJECT *Op1,
1341 ACPI_PARSE_OBJECT *Op2)
1343 ACPI_PARSE_OBJECT *Next;
1346 DbgPrint (ASL_PARSE_OUTPUT,
1347 "\nLinkChildNode: Parent=%p (%s), Child=%p (%s)\n",
1348 Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode): NULL,
1349 Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode): NULL);
1356 Op1->Asl.Child = Op2;
1358 /* Set the child and all peers of the child to point to the parent */
1363 Next->Asl.Parent = Op1;
1364 Next = Next->Asl.Next;
1371 /*******************************************************************************
1373 * FUNCTION: TrWalkParseTree
1375 * PARAMETERS: Visitation - Type of walk
1376 * DescendingCallback - Called during tree descent
1377 * AscendingCallback - Called during tree ascent
1378 * Context - To be passed to the callbacks
1380 * RETURN: Status from callback(s)
1382 * DESCRIPTION: Walk the entire parse tree.
1384 ******************************************************************************/
1388 ACPI_PARSE_OBJECT *Op,
1390 ASL_WALK_CALLBACK DescendingCallback,
1391 ASL_WALK_CALLBACK AscendingCallback,
1395 BOOLEAN NodePreviouslyVisited;
1396 ACPI_PARSE_OBJECT *StartOp = Op;
1406 NodePreviouslyVisited = FALSE;
1410 case ASL_WALK_VISIT_DOWNWARD:
1414 if (!NodePreviouslyVisited)
1416 /* Let the callback process the node. */
1418 Status = DescendingCallback (Op, Level, Context);
1419 if (ACPI_SUCCESS (Status))
1421 /* Visit children first, once */
1430 else if (Status != AE_CTRL_DEPTH)
1432 /* Exit immediately on any error */
1438 /* Terminate walk at start op */
1445 /* No more children, visit peers */
1450 NodePreviouslyVisited = FALSE;
1454 /* No children or peers, re-visit parent */
1460 Op = Op->Asl.Parent;
1461 NodePreviouslyVisited = TRUE;
1466 case ASL_WALK_VISIT_UPWARD:
1470 /* Visit leaf node (no children) or parent node on return trip */
1472 if ((!Op->Asl.Child) ||
1473 (NodePreviouslyVisited))
1475 /* Let the callback process the node. */
1477 Status = AscendingCallback (Op, Level, Context);
1478 if (ACPI_FAILURE (Status))
1485 /* Visit children first, once */
1492 /* Terminate walk at start op */
1499 /* No more children, visit peers */
1504 NodePreviouslyVisited = FALSE;
1508 /* No children or peers, re-visit parent */
1514 Op = Op->Asl.Parent;
1515 NodePreviouslyVisited = TRUE;
1520 case ASL_WALK_VISIT_TWICE:
1524 if (NodePreviouslyVisited)
1526 Status = AscendingCallback (Op, Level, Context);
1527 if (ACPI_FAILURE (Status))
1534 /* Let the callback process the node. */
1536 Status = DescendingCallback (Op, Level, Context);
1537 if (ACPI_SUCCESS (Status))
1539 /* Visit children first, once */
1548 else if (Status != AE_CTRL_DEPTH)
1550 /* Exit immediately on any error */
1556 /* Terminate walk at start op */
1563 /* No more children, visit peers */
1568 NodePreviouslyVisited = FALSE;
1572 /* No children or peers, re-visit parent */
1578 Op = Op->Asl.Parent;
1579 NodePreviouslyVisited = TRUE;
1585 /* No other types supported */
1589 /* If we get here, the walk completed with no errors */