1 /******************************************************************************
3 * Module Name: asltree - parse tree management
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2016, 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 <contrib/dev/acpica/compiler/aslcompiler.h>
45 #include "aslcompiler.y.h"
46 #include <contrib/dev/acpica/include/acapps.h>
49 #define _COMPONENT ACPI_COMPILER
50 ACPI_MODULE_NAME ("asltree")
52 /* Local prototypes */
54 static ACPI_PARSE_OBJECT *
59 /*******************************************************************************
61 * FUNCTION: TrSetParent
63 * PARAMETERS: Op - To be set to new parent
64 * ParentOp - The parent
66 * RETURN: None, sets Op parent directly
68 * DESCRIPTION: Change the parent of a parse op.
70 ******************************************************************************/
74 ACPI_PARSE_OBJECT *Op,
75 ACPI_PARSE_OBJECT *ParentOp)
78 Op->Asl.Parent = ParentOp;
82 /*******************************************************************************
84 * FUNCTION: TrGetNextNode
88 * RETURN: New parse node. Aborts on allocation failure
90 * DESCRIPTION: Allocate a new parse node for the parse tree. Bypass the local
91 * dynamic memory manager for performance reasons (This has a
92 * major impact on the speed of the compiler.)
94 ******************************************************************************/
96 static ACPI_PARSE_OBJECT *
100 ASL_CACHE_INFO *Cache;
103 if (Gbl_ParseOpCacheNext >= Gbl_ParseOpCacheLast)
105 /* Allocate a new buffer */
107 Cache = UtLocalCalloc (sizeof (Cache->Next) +
108 (sizeof (ACPI_PARSE_OBJECT) * ASL_PARSEOP_CACHE_SIZE));
110 /* Link new cache buffer to head of list */
112 Cache->Next = Gbl_ParseOpCacheList;
113 Gbl_ParseOpCacheList = Cache;
115 /* Setup cache management pointers */
117 Gbl_ParseOpCacheNext = ACPI_CAST_PTR (ACPI_PARSE_OBJECT, Cache->Buffer);
118 Gbl_ParseOpCacheLast = Gbl_ParseOpCacheNext + ASL_PARSEOP_CACHE_SIZE;
122 return (Gbl_ParseOpCacheNext++);
126 /*******************************************************************************
128 * FUNCTION: TrAllocateNode
130 * PARAMETERS: ParseOpcode - Opcode to be assigned to the node
132 * RETURN: New parse node. Aborts on allocation failure
134 * DESCRIPTION: Allocate and initialize a new parse node for the parse tree
136 ******************************************************************************/
142 ACPI_PARSE_OBJECT *Op;
145 Op = TrGetNextNode ();
147 Op->Asl.ParseOpcode = (UINT16) ParseOpcode;
148 Op->Asl.Filename = Gbl_Files[ASL_FILE_INPUT].Filename;
149 Op->Asl.LineNumber = Gbl_CurrentLineNumber;
150 Op->Asl.LogicalLineNumber = Gbl_LogicalLineNumber;
151 Op->Asl.LogicalByteOffset = Gbl_CurrentLineOffset;
152 Op->Asl.Column = Gbl_CurrentColumn;
154 UtSetParseOpName (Op);
159 /*******************************************************************************
161 * FUNCTION: TrReleaseNode
163 * PARAMETERS: Op - Op to be released
167 * DESCRIPTION: "release" a node. In truth, nothing is done since the node
168 * is part of a larger buffer
170 ******************************************************************************/
174 ACPI_PARSE_OBJECT *Op)
181 /*******************************************************************************
183 * FUNCTION: TrSetCurrentFilename
185 * PARAMETERS: Op - An existing parse node
189 * DESCRIPTION: Save the include file filename. Used for debug output only.
191 ******************************************************************************/
194 TrSetCurrentFilename (
195 ACPI_PARSE_OBJECT *Op)
197 Op->Asl.Filename = Gbl_PreviousIncludeFilename;
201 /*******************************************************************************
203 * FUNCTION: TrUpdateNode
205 * PARAMETERS: ParseOpcode - New opcode to be assigned to the node
206 * Op - An existing parse node
208 * RETURN: The updated node
210 * DESCRIPTION: Change the parse opcode assigned to a node. Usually used to
211 * change an opcode to DEFAULT_ARG so that the node is ignored
212 * during the code generation. Also used to set generic integers
213 * to a specific size (8, 16, 32, or 64 bits)
215 ******************************************************************************/
220 ACPI_PARSE_OBJECT *Op)
228 DbgPrint (ASL_PARSE_OUTPUT,
229 "\nUpdateNode: Old - %s, New - %s\n",
230 UtGetOpName (Op->Asl.ParseOpcode),
231 UtGetOpName (ParseOpcode));
233 /* Assign new opcode and name */
235 if (Op->Asl.ParseOpcode == PARSEOP_ONES)
239 case PARSEOP_BYTECONST:
241 Op->Asl.Value.Integer = ACPI_UINT8_MAX;
244 case PARSEOP_WORDCONST:
246 Op->Asl.Value.Integer = ACPI_UINT16_MAX;
249 case PARSEOP_DWORDCONST:
251 Op->Asl.Value.Integer = ACPI_UINT32_MAX;
254 /* Don't need to do the QWORD case */
258 /* Don't care about others */
263 Op->Asl.ParseOpcode = (UINT16) ParseOpcode;
264 UtSetParseOpName (Op);
267 * For the BYTE, WORD, and DWORD constants, make sure that the integer
268 * that was passed in will actually fit into the data type
272 case PARSEOP_BYTECONST:
274 UtCheckIntegerRange (Op, 0x00, ACPI_UINT8_MAX);
275 Op->Asl.Value.Integer &= ACPI_UINT8_MAX;
278 case PARSEOP_WORDCONST:
280 UtCheckIntegerRange (Op, 0x00, ACPI_UINT16_MAX);
281 Op->Asl.Value.Integer &= ACPI_UINT16_MAX;
284 case PARSEOP_DWORDCONST:
286 UtCheckIntegerRange (Op, 0x00, ACPI_UINT32_MAX);
287 Op->Asl.Value.Integer &= ACPI_UINT32_MAX;
292 /* Don't care about others, don't need to check QWORD */
301 /*******************************************************************************
303 * FUNCTION: TrPrintNodeCompileFlags
305 * PARAMETERS: Flags - Flags word to be decoded
309 * DESCRIPTION: Decode a flags word to text. Displays all flags that are set.
311 ******************************************************************************/
314 TrPrintNodeCompileFlags (
319 char *FlagName = NULL;
322 for (i = 0; i < 32; i++)
324 switch (Flags & FlagBit)
328 FlagName = "NODE_VISITED";
331 case NODE_AML_PACKAGE:
333 FlagName = "NODE_AML_PACKAGE";
338 FlagName = "NODE_IS_TARGET";
341 case NODE_IS_RESOURCE_DESC:
343 FlagName = "NODE_IS_RESOURCE_DESC";
346 case NODE_IS_RESOURCE_FIELD:
348 FlagName = "NODE_IS_RESOURCE_FIELD";
351 case NODE_HAS_NO_EXIT:
353 FlagName = "NODE_HAS_NO_EXIT";
356 case NODE_IF_HAS_NO_EXIT:
358 FlagName = "NODE_IF_HAS_NO_EXIT";
361 case NODE_NAME_INTERNALIZED:
363 FlagName = "NODE_NAME_INTERNALIZED";
366 case NODE_METHOD_NO_RETVAL:
368 FlagName = "NODE_METHOD_NO_RETVAL";
371 case NODE_METHOD_SOME_NO_RETVAL:
373 FlagName = "NODE_METHOD_SOME_NO_RETVAL";
376 case NODE_RESULT_NOT_USED:
378 FlagName = "NODE_RESULT_NOT_USED";
381 case NODE_METHOD_TYPED:
383 FlagName = "NODE_METHOD_TYPED";
386 case NODE_COULD_NOT_REDUCE:
388 FlagName = "NODE_COULD_NOT_REDUCE";
391 case NODE_COMPILE_TIME_CONST:
393 FlagName = "NODE_COMPILE_TIME_CONST";
396 case NODE_IS_TERM_ARG:
398 FlagName = "NODE_IS_TERM_ARG";
401 case NODE_WAS_ONES_OP:
403 FlagName = "NODE_WAS_ONES_OP";
406 case NODE_IS_NAME_DECLARATION:
408 FlagName = "NODE_IS_NAME_DECLARATION";
411 case NODE_COMPILER_EMITTED:
413 FlagName = "NODE_COMPILER_EMITTED";
416 case NODE_IS_DUPLICATE:
418 FlagName = "NODE_IS_DUPLICATE";
421 case NODE_IS_RESOURCE_DATA:
423 FlagName = "NODE_IS_RESOURCE_DATA";
426 case NODE_IS_NULL_RETURN:
428 FlagName = "NODE_IS_NULL_RETURN";
437 DbgPrint (ASL_PARSE_OUTPUT, " %s", FlagName);
446 /*******************************************************************************
448 * FUNCTION: TrSetNodeFlags
450 * PARAMETERS: Op - An existing parse node
451 * Flags - New flags word
453 * RETURN: The updated parser op
455 * DESCRIPTION: Set bits in the node flags word. Will not clear bits, only set
457 ******************************************************************************/
461 ACPI_PARSE_OBJECT *Op,
470 DbgPrint (ASL_PARSE_OUTPUT,
471 "\nSetNodeFlags: %s Op %p, %8.8X", Op->Asl.ParseOpName, Op, Flags);
473 TrPrintNodeCompileFlags (Flags);
474 DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
476 Op->Asl.CompileFlags |= Flags;
481 /*******************************************************************************
483 * FUNCTION: TrSetNodeAmlLength
485 * PARAMETERS: Op - An existing parse node
486 * Length - AML Length
488 * RETURN: The updated parser op
490 * DESCRIPTION: Set the AML Length in a node. Used by the parser to indicate
491 * the presence of a node that must be reduced to a fixed length
494 ******************************************************************************/
498 ACPI_PARSE_OBJECT *Op,
502 DbgPrint (ASL_PARSE_OUTPUT,
503 "\nSetNodeAmlLength: Op %p, %8.8X\n", Op, Length);
510 Op->Asl.AmlLength = Length;
515 /*******************************************************************************
517 * FUNCTION: TrSetEndLineNumber
519 * PARAMETERS: Op - An existing parse node
523 * DESCRIPTION: Set the ending line numbers (file line and logical line) of a
524 * parse node to the current line numbers.
526 ******************************************************************************/
530 ACPI_PARSE_OBJECT *Op)
533 /* If the end line # is already set, just return */
540 Op->Asl.EndLine = Gbl_CurrentLineNumber;
541 Op->Asl.EndLogicalLine = Gbl_LogicalLineNumber;
545 /*******************************************************************************
547 * FUNCTION: TrCreateAssignmentNode
549 * PARAMETERS: Target - Assignment target
550 * Source - Assignment source
552 * RETURN: Pointer to the new node. Aborts on allocation failure
554 * DESCRIPTION: Implements the C-style '=' operator. It changes the parse
555 * tree if possible to utilize the last argument of the math
556 * operators which is a target operand -- thus saving invocation
557 * of and additional Store() operator. An optimization.
559 ******************************************************************************/
562 TrCreateAssignmentNode (
563 ACPI_PARSE_OBJECT *Target,
564 ACPI_PARSE_OBJECT *Source)
566 ACPI_PARSE_OBJECT *TargetOp;
567 ACPI_PARSE_OBJECT *SourceOp1;
568 ACPI_PARSE_OBJECT *SourceOp2;
569 ACPI_PARSE_OBJECT *Operator;
572 DbgPrint (ASL_PARSE_OUTPUT,
573 "\nTrCreateAssignmentNode Line [%u to %u] Source %s Target %s\n",
574 Source->Asl.LineNumber, Source->Asl.EndLine,
575 UtGetOpName (Source->Asl.ParseOpcode),
576 UtGetOpName (Target->Asl.ParseOpcode));
578 TrSetNodeFlags (Target, NODE_IS_TARGET);
580 switch (Source->Asl.ParseOpcode)
583 * Only these operators can be optimized because they have
591 case PARSEOP_MULTIPLY:
594 case PARSEOP_SHIFTLEFT:
595 case PARSEOP_SHIFTRIGHT:
596 case PARSEOP_SUBTRACT:
601 /* Otherwise, just create a normal Store operator */
609 * Transform the parse tree such that the target is moved to the
610 * last operand of the operator
612 SourceOp1 = Source->Asl.Child;
613 SourceOp2 = SourceOp1->Asl.Next;
615 /* NOT only has one operand, but has a target */
617 if (Source->Asl.ParseOpcode == PARSEOP_NOT)
619 SourceOp2 = SourceOp1;
622 /* DIVIDE has an extra target operand (remainder) */
624 if (Source->Asl.ParseOpcode == PARSEOP_DIVIDE)
626 SourceOp2 = SourceOp2->Asl.Next;
629 TargetOp = SourceOp2->Asl.Next;
632 * Can't perform this optimization if there already is a target
633 * for the operator (ZERO is a "no target" placeholder).
635 if (TargetOp->Asl.ParseOpcode != PARSEOP_ZERO)
640 /* Link in the target as the final operand */
642 SourceOp2->Asl.Next = Target;
643 Target->Asl.Parent = Source;
650 Operator = TrAllocateNode (PARSEOP_STORE);
651 TrLinkChildren (Operator, 2, Source, Target);
653 /* Set the appropriate line numbers for the new node */
655 Operator->Asl.LineNumber = Target->Asl.LineNumber;
656 Operator->Asl.LogicalLineNumber = Target->Asl.LogicalLineNumber;
657 Operator->Asl.LogicalByteOffset = Target->Asl.LogicalByteOffset;
658 Operator->Asl.Column = Target->Asl.Column;
664 /*******************************************************************************
666 * FUNCTION: TrCreateLeafNode
668 * PARAMETERS: ParseOpcode - New opcode to be assigned to the node
670 * RETURN: Pointer to the new node. Aborts on allocation failure
672 * DESCRIPTION: Create a simple leaf node (no children or peers, and no value
673 * assigned to the node)
675 ******************************************************************************/
681 ACPI_PARSE_OBJECT *Op;
684 Op = TrAllocateNode (ParseOpcode);
686 DbgPrint (ASL_PARSE_OUTPUT,
687 "\nCreateLeafNode Ln/Col %u/%u NewNode %p Op %s\n\n",
688 Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName (ParseOpcode));
694 /*******************************************************************************
696 * FUNCTION: TrCreateNullTarget
700 * RETURN: Pointer to the new node. Aborts on allocation failure
702 * DESCRIPTION: Create a "null" target node. This is defined by the ACPI
703 * specification to be a zero AML opcode, and indicates that
704 * no target has been specified for the parent operation
706 ******************************************************************************/
712 ACPI_PARSE_OBJECT *Op;
715 Op = TrAllocateNode (PARSEOP_ZERO);
716 Op->Asl.CompileFlags |= (NODE_IS_TARGET | NODE_COMPILE_TIME_CONST);
718 DbgPrint (ASL_PARSE_OUTPUT,
719 "\nCreateNullTarget Ln/Col %u/%u NewNode %p Op %s\n",
720 Op->Asl.LineNumber, Op->Asl.Column, Op,
721 UtGetOpName (Op->Asl.ParseOpcode));
727 /*******************************************************************************
729 * FUNCTION: TrCreateConstantLeafNode
731 * PARAMETERS: ParseOpcode - The constant opcode
733 * RETURN: Pointer to the new node. Aborts on allocation failure
735 * DESCRIPTION: Create a leaf node (no children or peers) for one of the
736 * special constants - __LINE__, __FILE__, and __DATE__.
738 * Note: An implemenation of __FUNC__ cannot happen here because we don't
739 * have a full parse tree at this time and cannot find the parent control
740 * method. If it is ever needed, __FUNC__ must be implemented later, after
741 * the parse tree has been fully constructed.
743 ******************************************************************************/
746 TrCreateConstantLeafNode (
749 ACPI_PARSE_OBJECT *Op = NULL;
751 char *StaticTimeString;
758 case PARSEOP___LINE__:
760 Op = TrAllocateNode (PARSEOP_INTEGER);
761 Op->Asl.Value.Integer = Op->Asl.LineNumber;
764 case PARSEOP___PATH__:
766 Op = TrAllocateNode (PARSEOP_STRING_LITERAL);
768 /* Op.Asl.Filename contains the full pathname to the file */
770 Op->Asl.Value.String = Op->Asl.Filename;
773 case PARSEOP___FILE__:
775 Op = TrAllocateNode (PARSEOP_STRING_LITERAL);
777 /* Get the simple filename from the full path */
779 FlSplitInputPathname (Op->Asl.Filename, NULL, &Filename);
780 Op->Asl.Value.String = Filename;
783 case PARSEOP___DATE__:
785 Op = TrAllocateNode (PARSEOP_STRING_LITERAL);
787 /* Get a copy of the current time */
789 CurrentTime = time (NULL);
790 StaticTimeString = ctime (&CurrentTime);
791 TimeString = UtLocalCalloc (strlen (StaticTimeString) + 1);
792 strcpy (TimeString, StaticTimeString);
794 TimeString[strlen(TimeString) -1] = 0; /* Remove trailing newline */
795 Op->Asl.Value.String = TimeString;
798 default: /* This would be an internal error */
803 DbgPrint (ASL_PARSE_OUTPUT,
804 "\nCreateConstantLeafNode Ln/Col %u/%u NewNode %p "
805 "Op %s Value %8.8X%8.8X \n",
806 Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName (ParseOpcode),
807 ACPI_FORMAT_UINT64 (Op->Asl.Value.Integer));
812 /*******************************************************************************
814 * FUNCTION: TrCreateTargetOperand
816 * PARAMETERS: OriginalOp - Op to be copied
818 * RETURN: Pointer to the new node. Aborts on allocation failure
820 * DESCRIPTION: Copy an existing node (and subtree). Used in ASL+ (C-style)
821 * expressions where the target is the same as one of the
822 * operands. A new node and subtree must be created from the
823 * original so that the parse tree can be linked properly.
825 * NOTE: This code is specific to target operands that are the last
826 * operand in an ASL/AML operator. Meaning that the top-level
827 * parse Op in a possible subtree has a NULL Next pointer.
828 * This simplifies the recursion.
831 * DeRefOf (Local1) += 32
833 * This gets converted to:
834 * Add (DeRefOf (Local1), 32, DeRefOf (Local1))
836 * Each DeRefOf has a single child, Local1. Even more complex
837 * subtrees can be created via the Index and DeRefOf operators.
839 ******************************************************************************/
842 TrCreateTargetOperand (
843 ACPI_PARSE_OBJECT *OriginalOp,
844 ACPI_PARSE_OBJECT *ParentOp)
846 ACPI_PARSE_OBJECT *Op;
854 Op = TrGetNextNode ();
856 /* Copy the pertinent values (omit link pointer fields) */
858 Op->Asl.Value = OriginalOp->Asl.Value;
859 Op->Asl.Filename = OriginalOp->Asl.Filename;
860 Op->Asl.LineNumber = OriginalOp->Asl.LineNumber;
861 Op->Asl.LogicalLineNumber = OriginalOp->Asl.LogicalLineNumber;
862 Op->Asl.LogicalByteOffset = OriginalOp->Asl.LogicalByteOffset;
863 Op->Asl.Column = OriginalOp->Asl.Column;
864 Op->Asl.Flags = OriginalOp->Asl.Flags;
865 Op->Asl.CompileFlags = OriginalOp->Asl.CompileFlags;
866 Op->Asl.AmlOpcode = OriginalOp->Asl.AmlOpcode;
867 Op->Asl.ParseOpcode = OriginalOp->Asl.ParseOpcode;
868 Op->Asl.Parent = ParentOp;
869 UtSetParseOpName (Op);
871 /* Copy a possible subtree below this node */
873 if (OriginalOp->Asl.Child)
875 Op->Asl.Child = TrCreateTargetOperand (OriginalOp->Asl.Child, Op);
878 if (OriginalOp->Asl.Next) /* Null for top-level node */
880 Op->Asl.Next = TrCreateTargetOperand (OriginalOp->Asl.Next, ParentOp);
887 /*******************************************************************************
889 * FUNCTION: TrCreateValuedLeafNode
891 * PARAMETERS: ParseOpcode - New opcode to be assigned to the node
892 * Value - Value to be assigned to the node
894 * RETURN: Pointer to the new node. Aborts on allocation failure
896 * DESCRIPTION: Create a leaf node (no children or peers) with a value
899 ******************************************************************************/
902 TrCreateValuedLeafNode (
906 ACPI_PARSE_OBJECT *Op;
909 Op = TrAllocateNode (ParseOpcode);
911 DbgPrint (ASL_PARSE_OUTPUT,
912 "\nCreateValuedLeafNode Ln/Col %u/%u NewNode %p "
913 "Op %s Value %8.8X%8.8X ",
914 Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName(ParseOpcode),
915 ACPI_FORMAT_UINT64 (Value));
916 Op->Asl.Value.Integer = Value;
920 case PARSEOP_STRING_LITERAL:
922 DbgPrint (ASL_PARSE_OUTPUT, "STRING->%s", Value);
925 case PARSEOP_NAMESEG:
927 DbgPrint (ASL_PARSE_OUTPUT, "NAMESEG->%s", Value);
930 case PARSEOP_NAMESTRING:
932 DbgPrint (ASL_PARSE_OUTPUT, "NAMESTRING->%s", Value);
937 DbgPrint (ASL_PARSE_OUTPUT, "EISAID->%s", Value);
942 DbgPrint (ASL_PARSE_OUTPUT, "METHOD");
945 case PARSEOP_INTEGER:
947 DbgPrint (ASL_PARSE_OUTPUT, "INTEGER->%8.8X%8.8X",
948 ACPI_FORMAT_UINT64 (Value));
956 DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
961 /*******************************************************************************
963 * FUNCTION: TrCreateNode
965 * PARAMETERS: ParseOpcode - Opcode to be assigned to the node
966 * NumChildren - Number of children to follow
967 * ... - A list of child nodes to link to the new
968 * node. NumChildren long.
970 * RETURN: Pointer to the new node. Aborts on allocation failure
972 * DESCRIPTION: Create a new parse node and link together a list of child
973 * nodes underneath the new node.
975 ******************************************************************************/
983 ACPI_PARSE_OBJECT *Op;
984 ACPI_PARSE_OBJECT *Child;
985 ACPI_PARSE_OBJECT *PrevChild;
991 va_start (ap, NumChildren);
993 /* Allocate one new node */
995 Op = TrAllocateNode (ParseOpcode);
997 DbgPrint (ASL_PARSE_OUTPUT,
998 "\nCreateNode Ln/Col %u/%u NewParent %p Child %u Op %s ",
999 Op->Asl.LineNumber, Op->Asl.Column, Op,
1000 NumChildren, UtGetOpName(ParseOpcode));
1002 /* Some extra debug output based on the parse opcode */
1004 switch (ParseOpcode)
1006 case PARSEOP_ASL_CODE:
1008 Gbl_ParseTreeRoot = Op;
1009 Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1010 DbgPrint (ASL_PARSE_OUTPUT, "ASLCODE (Tree Completed)->");
1013 case PARSEOP_DEFINITION_BLOCK:
1015 DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->");
1018 case PARSEOP_OPERATIONREGION:
1020 DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->");
1025 DbgPrint (ASL_PARSE_OUTPUT, "OR->");
1030 /* Nothing to do for other opcodes */
1035 /* Link the new node to its children */
1039 for (i = 0; i < NumChildren; i++)
1041 /* Get the next child */
1043 Child = va_arg (ap, ACPI_PARSE_OBJECT *);
1044 DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child);
1047 * If child is NULL, this means that an optional argument
1048 * was omitted. We must create a placeholder with a special
1049 * opcode (DEFAULT_ARG) so that the code generator will know
1050 * that it must emit the correct default for this argument
1054 Child = TrAllocateNode (PARSEOP_DEFAULT_ARG);
1057 /* Link first child to parent */
1062 Op->Asl.Child = Child;
1065 /* Point all children to parent */
1067 Child->Asl.Parent = Op;
1069 /* Link children in a peer list */
1073 PrevChild->Asl.Next = Child;
1077 * This child might be a list, point all nodes in the list
1078 * to the same parent
1080 while (Child->Asl.Next)
1082 Child = Child->Asl.Next;
1083 Child->Asl.Parent = Op;
1090 DbgPrint (ASL_PARSE_OUTPUT, "\n");
1095 /*******************************************************************************
1097 * FUNCTION: TrLinkChildren
1099 * PARAMETERS: Op - An existing parse node
1100 * NumChildren - Number of children to follow
1101 * ... - A list of child nodes to link to the new
1102 * node. NumChildren long.
1104 * RETURN: The updated (linked) node
1106 * DESCRIPTION: Link a group of nodes to an existing parse node
1108 ******************************************************************************/
1112 ACPI_PARSE_OBJECT *Op,
1116 ACPI_PARSE_OBJECT *Child;
1117 ACPI_PARSE_OBJECT *PrevChild;
1123 va_start (ap, NumChildren);
1126 TrSetEndLineNumber (Op);
1128 DbgPrint (ASL_PARSE_OUTPUT,
1129 "\nLinkChildren Line [%u to %u] NewParent %p Child %u Op %s ",
1130 Op->Asl.LineNumber, Op->Asl.EndLine,
1131 Op, NumChildren, UtGetOpName(Op->Asl.ParseOpcode));
1133 switch (Op->Asl.ParseOpcode)
1135 case PARSEOP_ASL_CODE:
1137 Gbl_ParseTreeRoot = Op;
1138 Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
1139 DbgPrint (ASL_PARSE_OUTPUT, "ASLCODE (Tree Completed)->");
1142 case PARSEOP_DEFINITION_BLOCK:
1144 DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->");
1147 case PARSEOP_OPERATIONREGION:
1149 DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->");
1154 DbgPrint (ASL_PARSE_OUTPUT, "OR->");
1159 /* Nothing to do for other opcodes */
1164 /* Link the new node to it's children */
1168 for (i = 0; i < NumChildren; i++)
1170 Child = va_arg (ap, ACPI_PARSE_OBJECT *);
1172 if ((Child == PrevChild) && (Child != NULL))
1174 AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Child,
1175 "Child node list invalid");
1180 DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child);
1183 * If child is NULL, this means that an optional argument
1184 * was omitted. We must create a placeholder with a special
1185 * opcode (DEFAULT_ARG) so that the code generator will know
1186 * that it must emit the correct default for this argument
1190 Child = TrAllocateNode (PARSEOP_DEFAULT_ARG);
1193 /* Link first child to parent */
1198 Op->Asl.Child = Child;
1201 /* Point all children to parent */
1203 Child->Asl.Parent = Op;
1205 /* Link children in a peer list */
1209 PrevChild->Asl.Next = Child;
1213 * This child might be a list, point all nodes in the list
1214 * to the same parent
1216 while (Child->Asl.Next)
1218 Child = Child->Asl.Next;
1219 Child->Asl.Parent = Op;
1226 DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
1231 /*******************************************************************************
1233 * FUNCTION: TrLinkPeerNode
1235 * PARAMETERS: Op1 - First peer
1238 * RETURN: Op1 or the non-null node.
1240 * DESCRIPTION: Link two nodes as peers. Handles cases where one peer is null.
1242 ******************************************************************************/
1246 ACPI_PARSE_OBJECT *Op1,
1247 ACPI_PARSE_OBJECT *Op2)
1249 ACPI_PARSE_OBJECT *Next;
1252 DbgPrint (ASL_PARSE_OUTPUT,
1253 "\nLinkPeerNode: 1=%p (%s), 2=%p (%s)\n",
1254 Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode) : NULL,
1255 Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode) : NULL);
1258 if ((!Op1) && (!Op2))
1260 DbgPrint (ASL_PARSE_OUTPUT, "\nTwo Null nodes!\n");
1264 /* If one of the nodes is null, just return the non-null node */
1278 DbgPrint (ASL_DEBUG_OUTPUT,
1279 "\n************* Internal error, linking node to itself %p\n",
1281 AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op1,
1282 "Linking node to itself");
1286 Op1->Asl.Parent = Op2->Asl.Parent;
1289 * Op 1 may already have a peer list (such as an IF/ELSE pair),
1290 * so we must walk to the end of the list and attach the new
1294 while (Next->Asl.Next)
1296 Next = Next->Asl.Next;
1299 Next->Asl.Next = Op2;
1304 /*******************************************************************************
1306 * FUNCTION: TrLinkPeerNodes
1308 * PARAMETERS: NumPeers - The number of nodes in the list to follow
1309 * ... - A list of nodes to link together as peers
1311 * RETURN: The first node in the list (head of the peer list)
1313 * DESCRIPTION: Link together an arbitrary number of peer nodes.
1315 ******************************************************************************/
1322 ACPI_PARSE_OBJECT *This;
1323 ACPI_PARSE_OBJECT *Next;
1326 ACPI_PARSE_OBJECT *Start;
1329 DbgPrint (ASL_PARSE_OUTPUT,
1330 "\nLinkPeerNodes: (%u) ", NumPeers);
1332 va_start (ap, NumPeers);
1333 This = va_arg (ap, ACPI_PARSE_OBJECT *);
1339 for (i = 0; i < (NumPeers -1); i++)
1341 DbgPrint (ASL_PARSE_OUTPUT, "%u=%p ", (i+1), This);
1343 while (This->Asl.Next)
1345 This = This->Asl.Next;
1348 /* Get another peer node */
1350 Next = va_arg (ap, ACPI_PARSE_OBJECT *);
1353 Next = TrAllocateNode (PARSEOP_DEFAULT_ARG);
1356 /* link new node to the current node */
1358 This->Asl.Next = Next;
1363 DbgPrint (ASL_PARSE_OUTPUT,"\n");
1368 /*******************************************************************************
1370 * FUNCTION: TrLinkChildNode
1372 * PARAMETERS: Op1 - Parent node
1373 * Op2 - Op to become a child
1375 * RETURN: The parent node
1377 * DESCRIPTION: Link two nodes together as a parent and child
1379 ******************************************************************************/
1383 ACPI_PARSE_OBJECT *Op1,
1384 ACPI_PARSE_OBJECT *Op2)
1386 ACPI_PARSE_OBJECT *Next;
1389 DbgPrint (ASL_PARSE_OUTPUT,
1390 "\nLinkChildNode: Parent=%p (%s), Child=%p (%s)\n",
1391 Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode): NULL,
1392 Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode): NULL);
1399 Op1->Asl.Child = Op2;
1401 /* Set the child and all peers of the child to point to the parent */
1406 Next->Asl.Parent = Op1;
1407 Next = Next->Asl.Next;
1414 /*******************************************************************************
1416 * FUNCTION: TrWalkParseTree
1418 * PARAMETERS: Visitation - Type of walk
1419 * DescendingCallback - Called during tree descent
1420 * AscendingCallback - Called during tree ascent
1421 * Context - To be passed to the callbacks
1423 * RETURN: Status from callback(s)
1425 * DESCRIPTION: Walk the entire parse tree.
1427 ******************************************************************************/
1431 ACPI_PARSE_OBJECT *Op,
1433 ASL_WALK_CALLBACK DescendingCallback,
1434 ASL_WALK_CALLBACK AscendingCallback,
1438 BOOLEAN NodePreviouslyVisited;
1439 ACPI_PARSE_OBJECT *StartOp = Op;
1443 if (!Gbl_ParseTreeRoot)
1449 NodePreviouslyVisited = FALSE;
1453 case ASL_WALK_VISIT_DOWNWARD:
1457 if (!NodePreviouslyVisited)
1459 /* Let the callback process the node. */
1461 Status = DescendingCallback (Op, Level, Context);
1462 if (ACPI_SUCCESS (Status))
1464 /* Visit children first, once */
1473 else if (Status != AE_CTRL_DEPTH)
1475 /* Exit immediately on any error */
1481 /* Terminate walk at start op */
1488 /* No more children, visit peers */
1493 NodePreviouslyVisited = FALSE;
1497 /* No children or peers, re-visit parent */
1503 Op = Op->Asl.Parent;
1504 NodePreviouslyVisited = TRUE;
1509 case ASL_WALK_VISIT_UPWARD:
1513 /* Visit leaf node (no children) or parent node on return trip */
1515 if ((!Op->Asl.Child) ||
1516 (NodePreviouslyVisited))
1518 /* Let the callback process the node. */
1520 Status = AscendingCallback (Op, Level, Context);
1521 if (ACPI_FAILURE (Status))
1528 /* Visit children first, once */
1535 /* Terminate walk at start op */
1542 /* No more children, visit peers */
1547 NodePreviouslyVisited = FALSE;
1551 /* No children or peers, re-visit parent */
1557 Op = Op->Asl.Parent;
1558 NodePreviouslyVisited = TRUE;
1563 case ASL_WALK_VISIT_TWICE:
1567 if (NodePreviouslyVisited)
1569 Status = AscendingCallback (Op, Level, Context);
1570 if (ACPI_FAILURE (Status))
1577 /* Let the callback process the node. */
1579 Status = DescendingCallback (Op, Level, Context);
1580 if (ACPI_SUCCESS (Status))
1582 /* Visit children first, once */
1591 else if (Status != AE_CTRL_DEPTH)
1593 /* Exit immediately on any error */
1599 /* Terminate walk at start op */
1606 /* No more children, visit peers */
1611 NodePreviouslyVisited = FALSE;
1615 /* No children or peers, re-visit parent */
1621 Op = Op->Asl.Parent;
1622 NodePreviouslyVisited = TRUE;
1628 /* No other types supported */
1632 /* If we get here, the walk completed with no errors */