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 <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: 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_COMPILE_TIME_CONST:
345 FlagName = "NODE_COMPILE_TIME_CONST";
348 case NODE_IS_TERM_ARG:
350 FlagName = "NODE_IS_TERM_ARG";
353 case NODE_WAS_ONES_OP:
355 FlagName = "NODE_WAS_ONES_OP";
358 case NODE_IS_NAME_DECLARATION:
360 FlagName = "NODE_IS_NAME_DECLARATION";
363 case NODE_COMPILER_EMITTED:
365 FlagName = "NODE_COMPILER_EMITTED";
368 case NODE_IS_DUPLICATE:
370 FlagName = "NODE_IS_DUPLICATE";
373 case NODE_IS_RESOURCE_DATA:
375 FlagName = "NODE_IS_RESOURCE_DATA";
378 case NODE_IS_NULL_RETURN:
380 FlagName = "NODE_IS_NULL_RETURN";
389 DbgPrint (ASL_PARSE_OUTPUT, " %s", FlagName);
398 /*******************************************************************************
400 * FUNCTION: TrSetNodeFlags
402 * PARAMETERS: Op - An existing parse node
403 * Flags - New flags word
405 * RETURN: The updated parser op
407 * DESCRIPTION: Set bits in the node flags word. Will not clear bits, only set
409 ******************************************************************************/
413 ACPI_PARSE_OBJECT *Op,
422 DbgPrint (ASL_PARSE_OUTPUT,
423 "\nSetNodeFlags: %s Op %p, %8.8X", Op->Asl.ParseOpName, Op, Flags);
425 TrPrintNodeCompileFlags (Flags);
426 DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
428 Op->Asl.CompileFlags |= Flags;
433 /*******************************************************************************
435 * FUNCTION: TrSetNodeAmlLength
437 * PARAMETERS: Op - An existing parse node
438 * Length - AML Length
440 * RETURN: The updated parser op
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
446 ******************************************************************************/
450 ACPI_PARSE_OBJECT *Op,
454 DbgPrint (ASL_PARSE_OUTPUT,
455 "\nSetNodeAmlLength: Op %p, %8.8X\n", Op, Length);
462 Op->Asl.AmlLength = Length;
467 /*******************************************************************************
469 * FUNCTION: TrSetEndLineNumber
471 * PARAMETERS: Op - An existing parse node
475 * DESCRIPTION: Set the ending line numbers (file line and logical line) of a
476 * parse node to the current line numbers.
478 ******************************************************************************/
482 ACPI_PARSE_OBJECT *Op)
485 /* If the end line # is already set, just return */
492 Op->Asl.EndLine = Gbl_CurrentLineNumber;
493 Op->Asl.EndLogicalLine = Gbl_LogicalLineNumber;
497 /*******************************************************************************
499 * FUNCTION: TrCreateAssignmentNode
501 * PARAMETERS: Target - Assignment target
502 * Source - Assignment source
504 * RETURN: Pointer to the new node. Aborts on allocation failure
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.
511 ******************************************************************************/
514 TrCreateAssignmentNode (
515 ACPI_PARSE_OBJECT *Target,
516 ACPI_PARSE_OBJECT *Source)
518 ACPI_PARSE_OBJECT *TargetOp;
519 ACPI_PARSE_OBJECT *SourceOp1;
520 ACPI_PARSE_OBJECT *SourceOp2;
521 ACPI_PARSE_OBJECT *Operator;
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));
530 TrSetNodeFlags (Target, NODE_IS_TARGET);
532 switch (Source->Asl.ParseOpcode)
535 * Only these operators can be optimized because they have
542 case PARSEOP_MULTIPLY:
545 case PARSEOP_SHIFTLEFT:
546 case PARSEOP_SHIFTRIGHT:
547 case PARSEOP_SUBTRACT:
552 /* Otherwise, just create a normal Store operator */
560 * Transform the parse tree such that the target is moved to the
561 * last operand of the operator
563 SourceOp1 = Source->Asl.Child;
564 SourceOp2 = SourceOp1->Asl.Next;
566 /* NOT only has one operand, but has a target */
568 if (Source->Asl.ParseOpcode == PARSEOP_NOT)
570 SourceOp2 = SourceOp1;
573 /* DIVIDE has an extra target operand (remainder) */
575 if (Source->Asl.ParseOpcode == PARSEOP_DIVIDE)
577 SourceOp2 = SourceOp2->Asl.Next;
580 TargetOp = SourceOp2->Asl.Next;
583 * Can't perform this optimization if there already is a target
584 * for the operator (ZERO is a "no target" placeholder).
586 if (TargetOp->Asl.ParseOpcode != PARSEOP_ZERO)
591 /* Link in the target as the final operand */
593 SourceOp2->Asl.Next = Target;
594 Target->Asl.Parent = Source;
601 Operator = TrAllocateNode (PARSEOP_STORE);
602 TrLinkChildren (Operator, 2, Source, Target);
604 /* Set the appropriate line numbers for the new node */
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;
615 /*******************************************************************************
617 * FUNCTION: TrCreateLeafNode
619 * PARAMETERS: ParseOpcode - New opcode to be assigned to the node
621 * RETURN: Pointer to the new node. Aborts on allocation failure
623 * DESCRIPTION: Create a simple leaf node (no children or peers, and no value
624 * assigned to the node)
626 ******************************************************************************/
632 ACPI_PARSE_OBJECT *Op;
635 Op = TrAllocateNode (ParseOpcode);
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));
645 /*******************************************************************************
647 * FUNCTION: TrCreateNullTarget
651 * RETURN: Pointer to the new node. Aborts on allocation failure
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
657 ******************************************************************************/
663 ACPI_PARSE_OBJECT *Op;
666 Op = TrAllocateNode (PARSEOP_ZERO);
667 Op->Asl.CompileFlags |= (NODE_IS_TARGET | NODE_COMPILE_TIME_CONST);
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));
678 /*******************************************************************************
680 * FUNCTION: TrCreateConstantLeafNode
682 * PARAMETERS: ParseOpcode - The constant opcode
684 * RETURN: Pointer to the new node. Aborts on allocation failure
686 * DESCRIPTION: Create a leaf node (no children or peers) for one of the
687 * special constants - __LINE__, __FILE__, and __DATE__.
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.
694 ******************************************************************************/
697 TrCreateConstantLeafNode (
700 ACPI_PARSE_OBJECT *Op = NULL;
702 char *StaticTimeString;
709 case PARSEOP___LINE__:
711 Op = TrAllocateNode (PARSEOP_INTEGER);
712 Op->Asl.Value.Integer = Op->Asl.LineNumber;
715 case PARSEOP___PATH__:
717 Op = TrAllocateNode (PARSEOP_STRING_LITERAL);
719 /* Op.Asl.Filename contains the full pathname to the file */
721 Op->Asl.Value.String = Op->Asl.Filename;
724 case PARSEOP___FILE__:
726 Op = TrAllocateNode (PARSEOP_STRING_LITERAL);
728 /* Get the simple filename from the full path */
730 FlSplitInputPathname (Op->Asl.Filename, NULL, &Filename);
731 Op->Asl.Value.String = Filename;
734 case PARSEOP___DATE__:
736 Op = TrAllocateNode (PARSEOP_STRING_LITERAL);
738 /* Get a copy of the current time */
740 CurrentTime = time (NULL);
741 StaticTimeString = ctime (&CurrentTime);
742 TimeString = UtLocalCalloc (strlen (StaticTimeString) + 1);
743 strcpy (TimeString, StaticTimeString);
745 TimeString[strlen(TimeString) -1] = 0; /* Remove trailing newline */
746 Op->Asl.Value.String = TimeString;
749 default: /* This would be an internal error */
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));
762 /*******************************************************************************
764 * FUNCTION: TrCreateTargetOperand
766 * PARAMETERS: OriginalOp - Op to be copied
768 * RETURN: Pointer to the new node. Aborts on allocation failure
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.
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.
781 * DeRefOf (Local1) += 32
783 * This gets converted to:
784 * Add (DeRefOf (Local1), 32, DeRefOf (Local1))
786 * Each DeRefOf has a single child, Local1. Even more complex
787 * subtrees can be created via the Index and DeRefOf operators.
789 ******************************************************************************/
792 TrCreateTargetOperand (
793 ACPI_PARSE_OBJECT *OriginalOp,
794 ACPI_PARSE_OBJECT *ParentOp)
796 ACPI_PARSE_OBJECT *Op;
804 Op = TrGetNextNode ();
806 /* Copy the pertinent values (omit link pointer fields) */
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);
821 /* Copy a possible subtree below this node */
823 if (OriginalOp->Asl.Child)
825 Op->Asl.Child = TrCreateTargetOperand (OriginalOp->Asl.Child, Op);
828 if (OriginalOp->Asl.Next) /* Null for top-level node */
830 Op->Asl.Next = TrCreateTargetOperand (OriginalOp->Asl.Next, ParentOp);
837 /*******************************************************************************
839 * FUNCTION: TrCreateValuedLeafNode
841 * PARAMETERS: ParseOpcode - New opcode to be assigned to the node
842 * Value - Value to be assigned to the node
844 * RETURN: Pointer to the new node. Aborts on allocation failure
846 * DESCRIPTION: Create a leaf node (no children or peers) with a value
849 ******************************************************************************/
852 TrCreateValuedLeafNode (
856 ACPI_PARSE_OBJECT *Op;
859 Op = TrAllocateNode (ParseOpcode);
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;
869 case PARSEOP_STRING_LITERAL:
871 DbgPrint (ASL_PARSE_OUTPUT, "STRING->%s", Value);
874 case PARSEOP_NAMESEG:
876 DbgPrint (ASL_PARSE_OUTPUT, "NAMESEG->%s", Value);
879 case PARSEOP_NAMESTRING:
881 DbgPrint (ASL_PARSE_OUTPUT, "NAMESTRING->%s", Value);
886 DbgPrint (ASL_PARSE_OUTPUT, "EISAID->%s", Value);
891 DbgPrint (ASL_PARSE_OUTPUT, "METHOD");
894 case PARSEOP_INTEGER:
896 DbgPrint (ASL_PARSE_OUTPUT, "INTEGER->%8.8X%8.8X",
897 ACPI_FORMAT_UINT64 (Value));
905 DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
910 /*******************************************************************************
912 * FUNCTION: TrCreateNode
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.
919 * RETURN: Pointer to the new node. Aborts on allocation failure
921 * DESCRIPTION: Create a new parse node and link together a list of child
922 * nodes underneath the new node.
924 ******************************************************************************/
932 ACPI_PARSE_OBJECT *Op;
933 ACPI_PARSE_OBJECT *Child;
934 ACPI_PARSE_OBJECT *PrevChild;
940 va_start (ap, NumChildren);
942 /* Allocate one new node */
944 Op = TrAllocateNode (ParseOpcode);
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));
950 /* Some extra debug output based on the parse opcode */
954 case PARSEOP_DEFINITIONBLOCK:
957 DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->");
960 case PARSEOP_OPERATIONREGION:
962 DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->");
967 DbgPrint (ASL_PARSE_OUTPUT, "OR->");
972 /* Nothing to do for other opcodes */
977 /* Link the new node to its children */
981 for (i = 0; i < NumChildren; i++)
983 /* Get the next child */
985 Child = va_arg (ap, ACPI_PARSE_OBJECT *);
986 DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child);
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
996 Child = TrAllocateNode (PARSEOP_DEFAULT_ARG);
999 /* Link first child to parent */
1004 Op->Asl.Child = Child;
1007 /* Point all children to parent */
1009 Child->Asl.Parent = Op;
1011 /* Link children in a peer list */
1015 PrevChild->Asl.Next = Child;
1019 * This child might be a list, point all nodes in the list
1020 * to the same parent
1022 while (Child->Asl.Next)
1024 Child = Child->Asl.Next;
1025 Child->Asl.Parent = Op;
1032 DbgPrint (ASL_PARSE_OUTPUT, "\n");
1037 /*******************************************************************************
1039 * FUNCTION: TrLinkChildren
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.
1046 * RETURN: The updated (linked) node
1048 * DESCRIPTION: Link a group of nodes to an existing parse node
1050 ******************************************************************************/
1054 ACPI_PARSE_OBJECT *Op,
1058 ACPI_PARSE_OBJECT *Child;
1059 ACPI_PARSE_OBJECT *PrevChild;
1065 va_start (ap, NumChildren);
1068 TrSetEndLineNumber (Op);
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));
1075 switch (Op->Asl.ParseOpcode)
1077 case PARSEOP_DEFINITIONBLOCK:
1080 DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->");
1083 case PARSEOP_OPERATIONREGION:
1085 DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->");
1090 DbgPrint (ASL_PARSE_OUTPUT, "OR->");
1095 /* Nothing to do for other opcodes */
1100 /* Link the new node to it's children */
1104 for (i = 0; i < NumChildren; i++)
1106 Child = va_arg (ap, ACPI_PARSE_OBJECT *);
1108 if ((Child == PrevChild) && (Child != NULL))
1110 AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Child,
1111 "Child node list invalid");
1116 DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child);
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
1126 Child = TrAllocateNode (PARSEOP_DEFAULT_ARG);
1129 /* Link first child to parent */
1134 Op->Asl.Child = Child;
1137 /* Point all children to parent */
1139 Child->Asl.Parent = Op;
1141 /* Link children in a peer list */
1145 PrevChild->Asl.Next = Child;
1149 * This child might be a list, point all nodes in the list
1150 * to the same parent
1152 while (Child->Asl.Next)
1154 Child = Child->Asl.Next;
1155 Child->Asl.Parent = Op;
1161 DbgPrint (ASL_PARSE_OUTPUT, "\n\n");
1166 /*******************************************************************************
1168 * FUNCTION: TrLinkPeerNode
1170 * PARAMETERS: Op1 - First peer
1173 * RETURN: Op1 or the non-null node.
1175 * DESCRIPTION: Link two nodes as peers. Handles cases where one peer is null.
1177 ******************************************************************************/
1181 ACPI_PARSE_OBJECT *Op1,
1182 ACPI_PARSE_OBJECT *Op2)
1184 ACPI_PARSE_OBJECT *Next;
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);
1193 if ((!Op1) && (!Op2))
1195 DbgPrint (ASL_PARSE_OUTPUT, "\nTwo Null nodes!\n");
1199 /* If one of the nodes is null, just return the non-null node */
1213 DbgPrint (ASL_DEBUG_OUTPUT,
1214 "\n************* Internal error, linking node to itself %p\n",
1216 AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op1,
1217 "Linking node to itself");
1221 Op1->Asl.Parent = Op2->Asl.Parent;
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
1229 while (Next->Asl.Next)
1231 Next = Next->Asl.Next;
1234 Next->Asl.Next = Op2;
1239 /*******************************************************************************
1241 * FUNCTION: TrLinkPeerNodes
1243 * PARAMETERS: NumPeers - The number of nodes in the list to follow
1244 * ... - A list of nodes to link together as peers
1246 * RETURN: The first node in the list (head of the peer list)
1248 * DESCRIPTION: Link together an arbitrary number of peer nodes.
1250 ******************************************************************************/
1257 ACPI_PARSE_OBJECT *This;
1258 ACPI_PARSE_OBJECT *Next;
1261 ACPI_PARSE_OBJECT *Start;
1264 DbgPrint (ASL_PARSE_OUTPUT,
1265 "\nLinkPeerNodes: (%u) ", NumPeers);
1267 va_start (ap, NumPeers);
1268 This = va_arg (ap, ACPI_PARSE_OBJECT *);
1274 for (i = 0; i < (NumPeers -1); i++)
1276 DbgPrint (ASL_PARSE_OUTPUT, "%u=%p ", (i+1), This);
1278 while (This->Asl.Next)
1280 This = This->Asl.Next;
1283 /* Get another peer node */
1285 Next = va_arg (ap, ACPI_PARSE_OBJECT *);
1288 Next = TrAllocateNode (PARSEOP_DEFAULT_ARG);
1291 /* link new node to the current node */
1293 This->Asl.Next = Next;
1298 DbgPrint (ASL_PARSE_OUTPUT,"\n");
1303 /*******************************************************************************
1305 * FUNCTION: TrLinkChildNode
1307 * PARAMETERS: Op1 - Parent node
1308 * Op2 - Op to become a child
1310 * RETURN: The parent node
1312 * DESCRIPTION: Link two nodes together as a parent and child
1314 ******************************************************************************/
1318 ACPI_PARSE_OBJECT *Op1,
1319 ACPI_PARSE_OBJECT *Op2)
1321 ACPI_PARSE_OBJECT *Next;
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);
1334 Op1->Asl.Child = Op2;
1336 /* Set the child and all peers of the child to point to the parent */
1341 Next->Asl.Parent = Op1;
1342 Next = Next->Asl.Next;
1349 /*******************************************************************************
1351 * FUNCTION: TrWalkParseTree
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
1358 * RETURN: Status from callback(s)
1360 * DESCRIPTION: Walk the entire parse tree.
1362 ******************************************************************************/
1366 ACPI_PARSE_OBJECT *Op,
1368 ASL_WALK_CALLBACK DescendingCallback,
1369 ASL_WALK_CALLBACK AscendingCallback,
1373 BOOLEAN NodePreviouslyVisited;
1374 ACPI_PARSE_OBJECT *StartOp = Op;
1384 NodePreviouslyVisited = FALSE;
1388 case ASL_WALK_VISIT_DOWNWARD:
1392 if (!NodePreviouslyVisited)
1394 /* Let the callback process the node. */
1396 Status = DescendingCallback (Op, Level, Context);
1397 if (ACPI_SUCCESS (Status))
1399 /* Visit children first, once */
1408 else if (Status != AE_CTRL_DEPTH)
1410 /* Exit immediately on any error */
1416 /* Terminate walk at start op */
1423 /* No more children, visit peers */
1428 NodePreviouslyVisited = FALSE;
1432 /* No children or peers, re-visit parent */
1438 Op = Op->Asl.Parent;
1439 NodePreviouslyVisited = TRUE;
1444 case ASL_WALK_VISIT_UPWARD:
1448 /* Visit leaf node (no children) or parent node on return trip */
1450 if ((!Op->Asl.Child) ||
1451 (NodePreviouslyVisited))
1453 /* Let the callback process the node. */
1455 Status = AscendingCallback (Op, Level, Context);
1456 if (ACPI_FAILURE (Status))
1463 /* Visit children first, once */
1470 /* Terminate walk at start op */
1477 /* No more children, visit peers */
1482 NodePreviouslyVisited = FALSE;
1486 /* No children or peers, re-visit parent */
1492 Op = Op->Asl.Parent;
1493 NodePreviouslyVisited = TRUE;
1498 case ASL_WALK_VISIT_TWICE:
1502 if (NodePreviouslyVisited)
1504 Status = AscendingCallback (Op, Level, Context);
1505 if (ACPI_FAILURE (Status))
1512 /* Let the callback process the node. */
1514 Status = DescendingCallback (Op, Level, Context);
1515 if (ACPI_SUCCESS (Status))
1517 /* Visit children first, once */
1526 else if (Status != AE_CTRL_DEPTH)
1528 /* Exit immediately on any error */
1534 /* Terminate walk at start op */
1541 /* No more children, visit peers */
1546 NodePreviouslyVisited = FALSE;
1550 /* No children or peers, re-visit parent */
1556 Op = Op->Asl.Parent;
1557 NodePreviouslyVisited = TRUE;
1563 /* No other types supported */
1567 /* If we get here, the walk completed with no errors */