1 /****************************************************************************** 2 * 3 * Module Name: asltree - parse tree management 4 * 5 *****************************************************************************/ 6 7 /****************************************************************************** 8 * 9 * 1. Copyright Notice 10 * 11 * Some or all of this work - Copyright (c) 1999 - 2017, Intel Corp. 12 * All rights reserved. 13 * 14 * 2. License 15 * 16 * 2.1. This is your license from Intel Corp. under its intellectual property 17 * rights. You may have additional license terms from the party that provided 18 * you this software, covering your right to use that party's intellectual 19 * property rights. 20 * 21 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 22 * copy of the source code appearing in this file ("Covered Code") an 23 * irrevocable, perpetual, worldwide license under Intel's copyrights in the 24 * base code distributed originally by Intel ("Original Intel Code") to copy, 25 * make derivatives, distribute, use and display any portion of the Covered 26 * Code in any form, with the right to sublicense such rights; and 27 * 28 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 29 * license (with the right to sublicense), under only those claims of Intel 30 * patents that are infringed by the Original Intel Code, to make, use, sell, 31 * offer to sell, and import the Covered Code and derivative works thereof 32 * solely to the minimum extent necessary to exercise the above copyright 33 * license, and in no event shall the patent license extend to any additions 34 * to or modifications of the Original Intel Code. No other license or right 35 * is granted directly or by implication, estoppel or otherwise; 36 * 37 * The above copyright and patent license is granted only if the following 38 * conditions are met: 39 * 40 * 3. Conditions 41 * 42 * 3.1. Redistribution of Source with Rights to Further Distribute Source. 43 * Redistribution of source code of any substantial portion of the Covered 44 * Code or modification with rights to further distribute source must include 45 * the above Copyright Notice, the above License, this list of Conditions, 46 * and the following Disclaimer and Export Compliance provision. In addition, 47 * Licensee must cause all Covered Code to which Licensee contributes to 48 * contain a file documenting the changes Licensee made to create that Covered 49 * Code and the date of any change. Licensee must include in that file the 50 * documentation of any changes made by any predecessor Licensee. Licensee 51 * must include a prominent statement that the modification is derived, 52 * directly or indirectly, from Original Intel Code. 53 * 54 * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 55 * Redistribution of source code of any substantial portion of the Covered 56 * Code or modification without rights to further distribute source must 57 * include the following Disclaimer and Export Compliance provision in the 58 * documentation and/or other materials provided with distribution. In 59 * addition, Licensee may not authorize further sublicense of source of any 60 * portion of the Covered Code, and must include terms to the effect that the 61 * license from Licensee to its licensee is limited to the intellectual 62 * property embodied in the software Licensee provides to its licensee, and 63 * not to intellectual property embodied in modifications its licensee may 64 * make. 65 * 66 * 3.3. Redistribution of Executable. Redistribution in executable form of any 67 * substantial portion of the Covered Code or modification must reproduce the 68 * above Copyright Notice, and the following Disclaimer and Export Compliance 69 * provision in the documentation and/or other materials provided with the 70 * distribution. 71 * 72 * 3.4. Intel retains all right, title, and interest in and to the Original 73 * Intel Code. 74 * 75 * 3.5. Neither the name Intel nor any other trademark owned or controlled by 76 * Intel shall be used in advertising or otherwise to promote the sale, use or 77 * other dealings in products derived from or relating to the Covered Code 78 * without prior written authorization from Intel. 79 * 80 * 4. Disclaimer and Export Compliance 81 * 82 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 83 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 84 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 85 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 86 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 87 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 88 * PARTICULAR PURPOSE. 89 * 90 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 91 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 92 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 93 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 94 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 95 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 96 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 97 * LIMITED REMEDY. 98 * 99 * 4.3. Licensee shall not export, either directly or indirectly, any of this 100 * software or system incorporating such software without first obtaining any 101 * required license or other approval from the U. S. Department of Commerce or 102 * any other agency or department of the United States Government. In the 103 * event Licensee exports any such software from the United States or 104 * re-exports any such software from a foreign destination, Licensee shall 105 * ensure that the distribution and export/re-export of the software is in 106 * compliance with all laws, regulations, orders, or other restrictions of the 107 * U.S. Export Administration Regulations. Licensee agrees that neither it nor 108 * any of its subsidiaries will export/re-export any technical data, process, 109 * software, or service, directly or indirectly, to any country for which the 110 * United States government or any agency thereof requires an export license, 111 * other governmental approval, or letter of assurance, without first obtaining 112 * such license, approval or letter. 113 * 114 ***************************************************************************** 115 * 116 * Alternatively, you may choose to be licensed under the terms of the 117 * following license: 118 * 119 * Redistribution and use in source and binary forms, with or without 120 * modification, are permitted provided that the following conditions 121 * are met: 122 * 1. Redistributions of source code must retain the above copyright 123 * notice, this list of conditions, and the following disclaimer, 124 * without modification. 125 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 126 * substantially similar to the "NO WARRANTY" disclaimer below 127 * ("Disclaimer") and any redistribution must be conditioned upon 128 * including a substantially similar Disclaimer requirement for further 129 * binary redistribution. 130 * 3. Neither the names of the above-listed copyright holders nor the names 131 * of any contributors may be used to endorse or promote products derived 132 * from this software without specific prior written permission. 133 * 134 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 135 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 136 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 137 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 138 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 139 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 140 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 141 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 142 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 143 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 144 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 145 * 146 * Alternatively, you may choose to be licensed under the terms of the 147 * GNU General Public License ("GPL") version 2 as published by the Free 148 * Software Foundation. 149 * 150 *****************************************************************************/ 151 152 #include "aslcompiler.h" 153 #include "aslcompiler.y.h" 154 #include "acapps.h" 155 #include "acconvert.h" 156 #include <time.h> 157 158 #define _COMPONENT ACPI_COMPILER 159 ACPI_MODULE_NAME ("asltree") 160 161 /* Local prototypes */ 162 163 static ACPI_PARSE_OBJECT * 164 TrGetNextNode ( 165 void); 166 167 168 /******************************************************************************* 169 * 170 * FUNCTION: TrSetParent 171 * 172 * PARAMETERS: Op - To be set to new parent 173 * ParentOp - The parent 174 * 175 * RETURN: None, sets Op parent directly 176 * 177 * DESCRIPTION: Change the parent of a parse op. 178 * 179 ******************************************************************************/ 180 181 void 182 TrSetParent ( 183 ACPI_PARSE_OBJECT *Op, 184 ACPI_PARSE_OBJECT *ParentOp) 185 { 186 187 Op->Asl.Parent = ParentOp; 188 } 189 190 191 /******************************************************************************* 192 * 193 * FUNCTION: TrGetNextNode 194 * 195 * PARAMETERS: None 196 * 197 * RETURN: New parse node. Aborts on allocation failure 198 * 199 * DESCRIPTION: Allocate a new parse node for the parse tree. Bypass the local 200 * dynamic memory manager for performance reasons (This has a 201 * major impact on the speed of the compiler.) 202 * 203 ******************************************************************************/ 204 205 static ACPI_PARSE_OBJECT * 206 TrGetNextNode ( 207 void) 208 { 209 ASL_CACHE_INFO *Cache; 210 211 212 if (Gbl_ParseOpCacheNext >= Gbl_ParseOpCacheLast) 213 { 214 /* Allocate a new buffer */ 215 216 Cache = UtLocalCalloc (sizeof (Cache->Next) + 217 (sizeof (ACPI_PARSE_OBJECT) * ASL_PARSEOP_CACHE_SIZE)); 218 219 /* Link new cache buffer to head of list */ 220 221 Cache->Next = Gbl_ParseOpCacheList; 222 Gbl_ParseOpCacheList = Cache; 223 224 /* Setup cache management pointers */ 225 226 Gbl_ParseOpCacheNext = ACPI_CAST_PTR (ACPI_PARSE_OBJECT, Cache->Buffer); 227 Gbl_ParseOpCacheLast = Gbl_ParseOpCacheNext + ASL_PARSEOP_CACHE_SIZE; 228 } 229 230 Gbl_ParseOpCount++; 231 return (Gbl_ParseOpCacheNext++); 232 } 233 234 235 /******************************************************************************* 236 * 237 * FUNCTION: TrAllocateNode 238 * 239 * PARAMETERS: ParseOpcode - Opcode to be assigned to the node 240 * 241 * RETURN: New parse node. Aborts on allocation failure 242 * 243 * DESCRIPTION: Allocate and initialize a new parse node for the parse tree 244 * 245 ******************************************************************************/ 246 247 ACPI_PARSE_OBJECT * 248 TrAllocateNode ( 249 UINT32 ParseOpcode) 250 { 251 ACPI_PARSE_OBJECT *Op; 252 ACPI_PARSE_OBJECT *LatestNode; 253 254 255 Op = TrGetNextNode (); 256 257 Op->Asl.ParseOpcode = (UINT16) ParseOpcode; 258 Op->Asl.Filename = Gbl_Files[ASL_FILE_INPUT].Filename; 259 Op->Asl.LineNumber = Gbl_CurrentLineNumber; 260 Op->Asl.LogicalLineNumber = Gbl_LogicalLineNumber; 261 Op->Asl.LogicalByteOffset = Gbl_CurrentLineOffset; 262 Op->Asl.Column = Gbl_CurrentColumn; 263 264 UtSetParseOpName (Op); 265 266 /* The following is for capturing comments */ 267 268 if(Gbl_CaptureComments) 269 { 270 LatestNode = Gbl_CommentState.Latest_Parse_Node; 271 Op->Asl.InlineComment = NULL; 272 Op->Asl.EndNodeComment = NULL; 273 Op->Asl.CommentList = NULL; 274 Op->Asl.FileChanged = FALSE; 275 276 /* 277 * Check to see if the file name has changed before resetting the 278 * latest parse node. 279 */ 280 if (LatestNode && 281 (ParseOpcode != PARSEOP_INCLUDE) && 282 (ParseOpcode != PARSEOP_INCLUDE_END) && 283 strcmp (LatestNode->Asl.Filename, Op->Asl.Filename)) 284 { 285 CvDbgPrint ("latest node: %s\n", LatestNode->Asl.ParseOpName); 286 Op->Asl.FileChanged = TRUE; 287 if (Gbl_IncludeFileStack) 288 { 289 Op->Asl.ParentFilename = Gbl_IncludeFileStack->Filename; 290 } 291 else 292 { 293 Op->Asl.ParentFilename = NULL; 294 } 295 } 296 297 Gbl_CommentState.Latest_Parse_Node = Op; 298 if (Gbl_CommentState.Latest_Parse_Node->Asl.ParseOpName) 299 { 300 CvDbgPrint ("trallocatenode=Set latest parse node to this node.\n"); 301 CvDbgPrint (" Op->Asl.ParseOpName = %s\n", 302 Gbl_CommentState.Latest_Parse_Node->Asl.ParseOpName); 303 CvDbgPrint (" Op->Asl.ParseOpcode = 0x%x\n", ParseOpcode); 304 305 if (Op->Asl.FileChanged) 306 { 307 CvDbgPrint(" file has been changed!\n"); 308 } 309 } 310 311 /* 312 * if this parse op's syntax uses () and {} (i.e. Package(1){0x00}) then 313 * set a flag in the comment state. This facilitates paring comments for 314 * these types of opcodes. 315 */ 316 if ((CvParseOpBlockType(Op) == (BLOCK_PAREN | BLOCK_BRACE)) && 317 (ParseOpcode != PARSEOP_DEFINITION_BLOCK)) 318 { 319 CvDbgPrint ("Parsing paren/Brace node now!\n"); 320 Gbl_CommentState.ParsingParenBraceNode = Op; 321 } 322 323 if (Gbl_Comment_List_Head) 324 { 325 CvDbgPrint ("Transferring...\n"); 326 Op->Asl.CommentList = Gbl_Comment_List_Head; 327 Gbl_Comment_List_Head = NULL; 328 Gbl_Comment_List_Tail = NULL; 329 CvDbgPrint (" Transferred current comment list to this node.\n"); 330 CvDbgPrint (" %s\n", Op->Asl.CommentList->Comment); 331 } 332 if (Gbl_Inline_Comment_Buffer) 333 { 334 Op->Asl.InlineComment = Gbl_Inline_Comment_Buffer; 335 Gbl_Inline_Comment_Buffer = NULL; 336 CvDbgPrint ("Transferred current inline comment list to this node.\n"); 337 } 338 339 } 340 341 return (Op); 342 } 343 344 345 /******************************************************************************* 346 * 347 * FUNCTION: TrReleaseNode 348 * 349 * PARAMETERS: Op - Op to be released 350 * 351 * RETURN: None 352 * 353 * DESCRIPTION: "release" a node. In truth, nothing is done since the node 354 * is part of a larger buffer 355 * 356 ******************************************************************************/ 357 358 void 359 TrReleaseNode ( 360 ACPI_PARSE_OBJECT *Op) 361 { 362 363 return; 364 } 365 366 367 /******************************************************************************* 368 * 369 * FUNCTION: TrSetCurrentFilename 370 * 371 * PARAMETERS: Op - An existing parse node 372 * 373 * RETURN: None 374 * 375 * DESCRIPTION: Save the include file filename. Used for debug output only. 376 * 377 ******************************************************************************/ 378 379 void 380 TrSetCurrentFilename ( 381 ACPI_PARSE_OBJECT *Op) 382 { 383 Op->Asl.Filename = Gbl_PreviousIncludeFilename; 384 } 385 386 387 /******************************************************************************* 388 * 389 * FUNCTION: TrUpdateNode 390 * 391 * PARAMETERS: ParseOpcode - New opcode to be assigned to the node 392 * Op - An existing parse node 393 * 394 * RETURN: The updated node 395 * 396 * DESCRIPTION: Change the parse opcode assigned to a node. Usually used to 397 * change an opcode to DEFAULT_ARG so that the node is ignored 398 * during the code generation. Also used to set generic integers 399 * to a specific size (8, 16, 32, or 64 bits) 400 * 401 ******************************************************************************/ 402 403 ACPI_PARSE_OBJECT * 404 TrUpdateNode ( 405 UINT32 ParseOpcode, 406 ACPI_PARSE_OBJECT *Op) 407 { 408 409 if (!Op) 410 { 411 return (NULL); 412 } 413 414 DbgPrint (ASL_PARSE_OUTPUT, 415 "\nUpdateNode: Old - %s, New - %s\n", 416 UtGetOpName (Op->Asl.ParseOpcode), 417 UtGetOpName (ParseOpcode)); 418 419 /* Assign new opcode and name */ 420 421 if (Op->Asl.ParseOpcode == PARSEOP_ONES) 422 { 423 switch (ParseOpcode) 424 { 425 case PARSEOP_BYTECONST: 426 427 Op->Asl.Value.Integer = ACPI_UINT8_MAX; 428 break; 429 430 case PARSEOP_WORDCONST: 431 432 Op->Asl.Value.Integer = ACPI_UINT16_MAX; 433 break; 434 435 case PARSEOP_DWORDCONST: 436 437 Op->Asl.Value.Integer = ACPI_UINT32_MAX; 438 break; 439 440 /* Don't need to do the QWORD case */ 441 442 default: 443 444 /* Don't care about others */ 445 break; 446 } 447 } 448 449 Op->Asl.ParseOpcode = (UINT16) ParseOpcode; 450 UtSetParseOpName (Op); 451 452 /* 453 * For the BYTE, WORD, and DWORD constants, make sure that the integer 454 * that was passed in will actually fit into the data type 455 */ 456 switch (ParseOpcode) 457 { 458 case PARSEOP_BYTECONST: 459 460 UtCheckIntegerRange (Op, 0x00, ACPI_UINT8_MAX); 461 Op->Asl.Value.Integer &= ACPI_UINT8_MAX; 462 break; 463 464 case PARSEOP_WORDCONST: 465 466 UtCheckIntegerRange (Op, 0x00, ACPI_UINT16_MAX); 467 Op->Asl.Value.Integer &= ACPI_UINT16_MAX; 468 break; 469 470 case PARSEOP_DWORDCONST: 471 472 UtCheckIntegerRange (Op, 0x00, ACPI_UINT32_MAX); 473 Op->Asl.Value.Integer &= ACPI_UINT32_MAX; 474 break; 475 476 default: 477 478 /* Don't care about others, don't need to check QWORD */ 479 480 break; 481 } 482 483 /* Converter: if this is a method invocation, turn off capture comments. */ 484 if (Gbl_CaptureComments && 485 (ParseOpcode == PARSEOP_METHODCALL)) 486 { 487 Gbl_CommentState.CaptureComments = FALSE; 488 } 489 490 return (Op); 491 } 492 493 494 /******************************************************************************* 495 * 496 * FUNCTION: TrPrintNodeCompileFlags 497 * 498 * PARAMETERS: Flags - Flags word to be decoded 499 * 500 * RETURN: None 501 * 502 * DESCRIPTION: Decode a flags word to text. Displays all flags that are set. 503 * 504 ******************************************************************************/ 505 506 void 507 TrPrintNodeCompileFlags ( 508 UINT32 Flags) 509 { 510 UINT32 i; 511 UINT32 FlagBit = 1; 512 char *FlagName = NULL; 513 514 515 for (i = 0; i < 32; i++) 516 { 517 switch (Flags & FlagBit) 518 { 519 case NODE_VISITED: 520 521 FlagName = "NODE_VISITED"; 522 break; 523 524 case NODE_AML_PACKAGE: 525 526 FlagName = "NODE_AML_PACKAGE"; 527 break; 528 529 case NODE_IS_TARGET: 530 531 FlagName = "NODE_IS_TARGET"; 532 break; 533 534 case NODE_IS_RESOURCE_DESC: 535 536 FlagName = "NODE_IS_RESOURCE_DESC"; 537 break; 538 539 case NODE_IS_RESOURCE_FIELD: 540 541 FlagName = "NODE_IS_RESOURCE_FIELD"; 542 break; 543 544 case NODE_HAS_NO_EXIT: 545 546 FlagName = "NODE_HAS_NO_EXIT"; 547 break; 548 549 case NODE_IF_HAS_NO_EXIT: 550 551 FlagName = "NODE_IF_HAS_NO_EXIT"; 552 break; 553 554 case NODE_NAME_INTERNALIZED: 555 556 FlagName = "NODE_NAME_INTERNALIZED"; 557 break; 558 559 case NODE_METHOD_NO_RETVAL: 560 561 FlagName = "NODE_METHOD_NO_RETVAL"; 562 break; 563 564 case NODE_METHOD_SOME_NO_RETVAL: 565 566 FlagName = "NODE_METHOD_SOME_NO_RETVAL"; 567 break; 568 569 case NODE_RESULT_NOT_USED: 570 571 FlagName = "NODE_RESULT_NOT_USED"; 572 break; 573 574 case NODE_METHOD_TYPED: 575 576 FlagName = "NODE_METHOD_TYPED"; 577 break; 578 579 case NODE_COULD_NOT_REDUCE: 580 581 FlagName = "NODE_COULD_NOT_REDUCE"; 582 break; 583 584 case NODE_COMPILE_TIME_CONST: 585 586 FlagName = "NODE_COMPILE_TIME_CONST"; 587 break; 588 589 case NODE_IS_TERM_ARG: 590 591 FlagName = "NODE_IS_TERM_ARG"; 592 break; 593 594 case NODE_WAS_ONES_OP: 595 596 FlagName = "NODE_WAS_ONES_OP"; 597 break; 598 599 case NODE_IS_NAME_DECLARATION: 600 601 FlagName = "NODE_IS_NAME_DECLARATION"; 602 break; 603 604 case NODE_COMPILER_EMITTED: 605 606 FlagName = "NODE_COMPILER_EMITTED"; 607 break; 608 609 case NODE_IS_DUPLICATE: 610 611 FlagName = "NODE_IS_DUPLICATE"; 612 break; 613 614 case NODE_IS_RESOURCE_DATA: 615 616 FlagName = "NODE_IS_RESOURCE_DATA"; 617 break; 618 619 case NODE_IS_NULL_RETURN: 620 621 FlagName = "NODE_IS_NULL_RETURN"; 622 break; 623 624 default: 625 break; 626 } 627 628 if (FlagName) 629 { 630 DbgPrint (ASL_PARSE_OUTPUT, " %s", FlagName); 631 FlagName = NULL; 632 } 633 634 FlagBit <<= 1; 635 } 636 } 637 638 639 /******************************************************************************* 640 * 641 * FUNCTION: TrSetNodeFlags 642 * 643 * PARAMETERS: Op - An existing parse node 644 * Flags - New flags word 645 * 646 * RETURN: The updated parser op 647 * 648 * DESCRIPTION: Set bits in the node flags word. Will not clear bits, only set 649 * 650 ******************************************************************************/ 651 652 ACPI_PARSE_OBJECT * 653 TrSetNodeFlags ( 654 ACPI_PARSE_OBJECT *Op, 655 UINT32 Flags) 656 { 657 658 if (!Op) 659 { 660 return (NULL); 661 } 662 663 DbgPrint (ASL_PARSE_OUTPUT, 664 "\nSetNodeFlags: %s Op %p, %8.8X", Op->Asl.ParseOpName, Op, Flags); 665 666 TrPrintNodeCompileFlags (Flags); 667 DbgPrint (ASL_PARSE_OUTPUT, "\n\n"); 668 669 Op->Asl.CompileFlags |= Flags; 670 return (Op); 671 } 672 673 674 /******************************************************************************* 675 * 676 * FUNCTION: TrSetNodeAmlLength 677 * 678 * PARAMETERS: Op - An existing parse node 679 * Length - AML Length 680 * 681 * RETURN: The updated parser op 682 * 683 * DESCRIPTION: Set the AML Length in a node. Used by the parser to indicate 684 * the presence of a node that must be reduced to a fixed length 685 * constant. 686 * 687 ******************************************************************************/ 688 689 ACPI_PARSE_OBJECT * 690 TrSetNodeAmlLength ( 691 ACPI_PARSE_OBJECT *Op, 692 UINT32 Length) 693 { 694 695 DbgPrint (ASL_PARSE_OUTPUT, 696 "\nSetNodeAmlLength: Op %p, %8.8X\n", Op, Length); 697 698 if (!Op) 699 { 700 return (NULL); 701 } 702 703 Op->Asl.AmlLength = Length; 704 return (Op); 705 } 706 707 708 /******************************************************************************* 709 * 710 * FUNCTION: TrSetEndLineNumber 711 * 712 * PARAMETERS: Op - An existing parse node 713 * 714 * RETURN: None. 715 * 716 * DESCRIPTION: Set the ending line numbers (file line and logical line) of a 717 * parse node to the current line numbers. 718 * 719 ******************************************************************************/ 720 721 void 722 TrSetEndLineNumber ( 723 ACPI_PARSE_OBJECT *Op) 724 { 725 726 /* If the end line # is already set, just return */ 727 728 if (Op->Asl.EndLine) 729 { 730 return; 731 } 732 733 Op->Asl.EndLine = Gbl_CurrentLineNumber; 734 Op->Asl.EndLogicalLine = Gbl_LogicalLineNumber; 735 } 736 737 738 /******************************************************************************* 739 * 740 * FUNCTION: TrCreateAssignmentNode 741 * 742 * PARAMETERS: Target - Assignment target 743 * Source - Assignment source 744 * 745 * RETURN: Pointer to the new node. Aborts on allocation failure 746 * 747 * DESCRIPTION: Implements the C-style '=' operator. It changes the parse 748 * tree if possible to utilize the last argument of the math 749 * operators which is a target operand -- thus saving invocation 750 * of and additional Store() operator. An optimization. 751 * 752 ******************************************************************************/ 753 754 ACPI_PARSE_OBJECT * 755 TrCreateAssignmentNode ( 756 ACPI_PARSE_OBJECT *Target, 757 ACPI_PARSE_OBJECT *Source) 758 { 759 ACPI_PARSE_OBJECT *TargetOp; 760 ACPI_PARSE_OBJECT *SourceOp1; 761 ACPI_PARSE_OBJECT *SourceOp2; 762 ACPI_PARSE_OBJECT *Operator; 763 764 765 DbgPrint (ASL_PARSE_OUTPUT, 766 "\nTrCreateAssignmentNode Line [%u to %u] Source %s Target %s\n", 767 Source->Asl.LineNumber, Source->Asl.EndLine, 768 UtGetOpName (Source->Asl.ParseOpcode), 769 UtGetOpName (Target->Asl.ParseOpcode)); 770 771 TrSetNodeFlags (Target, NODE_IS_TARGET); 772 773 switch (Source->Asl.ParseOpcode) 774 { 775 /* 776 * Only these operators can be optimized because they have 777 * a target operand 778 */ 779 case PARSEOP_ADD: 780 case PARSEOP_AND: 781 case PARSEOP_DIVIDE: 782 case PARSEOP_INDEX: 783 case PARSEOP_MOD: 784 case PARSEOP_MULTIPLY: 785 case PARSEOP_NOT: 786 case PARSEOP_OR: 787 case PARSEOP_SHIFTLEFT: 788 case PARSEOP_SHIFTRIGHT: 789 case PARSEOP_SUBTRACT: 790 case PARSEOP_XOR: 791 792 break; 793 794 /* Otherwise, just create a normal Store operator */ 795 796 default: 797 798 goto CannotOptimize; 799 } 800 801 /* 802 * Transform the parse tree such that the target is moved to the 803 * last operand of the operator 804 */ 805 SourceOp1 = Source->Asl.Child; 806 SourceOp2 = SourceOp1->Asl.Next; 807 808 /* NOT only has one operand, but has a target */ 809 810 if (Source->Asl.ParseOpcode == PARSEOP_NOT) 811 { 812 SourceOp2 = SourceOp1; 813 } 814 815 /* DIVIDE has an extra target operand (remainder) */ 816 817 if (Source->Asl.ParseOpcode == PARSEOP_DIVIDE) 818 { 819 SourceOp2 = SourceOp2->Asl.Next; 820 } 821 822 TargetOp = SourceOp2->Asl.Next; 823 824 /* 825 * Can't perform this optimization if there already is a target 826 * for the operator (ZERO is a "no target" placeholder). 827 */ 828 if (TargetOp->Asl.ParseOpcode != PARSEOP_ZERO) 829 { 830 goto CannotOptimize; 831 } 832 833 /* Link in the target as the final operand */ 834 835 SourceOp2->Asl.Next = Target; 836 Target->Asl.Parent = Source; 837 838 return (Source); 839 840 841 CannotOptimize: 842 843 Operator = TrAllocateNode (PARSEOP_STORE); 844 TrLinkChildren (Operator, 2, Source, Target); 845 846 /* Set the appropriate line numbers for the new node */ 847 848 Operator->Asl.LineNumber = Target->Asl.LineNumber; 849 Operator->Asl.LogicalLineNumber = Target->Asl.LogicalLineNumber; 850 Operator->Asl.LogicalByteOffset = Target->Asl.LogicalByteOffset; 851 Operator->Asl.Column = Target->Asl.Column; 852 853 return (Operator); 854 } 855 856 857 /******************************************************************************* 858 * 859 * FUNCTION: TrCreateLeafNode 860 * 861 * PARAMETERS: ParseOpcode - New opcode to be assigned to the node 862 * 863 * RETURN: Pointer to the new node. Aborts on allocation failure 864 * 865 * DESCRIPTION: Create a simple leaf node (no children or peers, and no value 866 * assigned to the node) 867 * 868 ******************************************************************************/ 869 870 ACPI_PARSE_OBJECT * 871 TrCreateLeafNode ( 872 UINT32 ParseOpcode) 873 { 874 ACPI_PARSE_OBJECT *Op; 875 876 877 Op = TrAllocateNode (ParseOpcode); 878 879 DbgPrint (ASL_PARSE_OUTPUT, 880 "\nCreateLeafNode Ln/Col %u/%u NewNode %p Op %s\n\n", 881 Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName (ParseOpcode)); 882 883 return (Op); 884 } 885 886 887 /******************************************************************************* 888 * 889 * FUNCTION: TrCreateNullTarget 890 * 891 * PARAMETERS: None 892 * 893 * RETURN: Pointer to the new node. Aborts on allocation failure 894 * 895 * DESCRIPTION: Create a "null" target node. This is defined by the ACPI 896 * specification to be a zero AML opcode, and indicates that 897 * no target has been specified for the parent operation 898 * 899 ******************************************************************************/ 900 901 ACPI_PARSE_OBJECT * 902 TrCreateNullTarget ( 903 void) 904 { 905 ACPI_PARSE_OBJECT *Op; 906 907 908 Op = TrAllocateNode (PARSEOP_ZERO); 909 Op->Asl.CompileFlags |= (NODE_IS_TARGET | NODE_COMPILE_TIME_CONST); 910 911 DbgPrint (ASL_PARSE_OUTPUT, 912 "\nCreateNullTarget Ln/Col %u/%u NewNode %p Op %s\n", 913 Op->Asl.LineNumber, Op->Asl.Column, Op, 914 UtGetOpName (Op->Asl.ParseOpcode)); 915 916 return (Op); 917 } 918 919 920 /******************************************************************************* 921 * 922 * FUNCTION: TrCreateConstantLeafNode 923 * 924 * PARAMETERS: ParseOpcode - The constant opcode 925 * 926 * RETURN: Pointer to the new node. Aborts on allocation failure 927 * 928 * DESCRIPTION: Create a leaf node (no children or peers) for one of the 929 * special constants - __LINE__, __FILE__, and __DATE__. 930 * 931 * Note: An implemenation of __FUNC__ cannot happen here because we don't 932 * have a full parse tree at this time and cannot find the parent control 933 * method. If it is ever needed, __FUNC__ must be implemented later, after 934 * the parse tree has been fully constructed. 935 * 936 ******************************************************************************/ 937 938 ACPI_PARSE_OBJECT * 939 TrCreateConstantLeafNode ( 940 UINT32 ParseOpcode) 941 { 942 ACPI_PARSE_OBJECT *Op = NULL; 943 time_t CurrentTime; 944 char *StaticTimeString; 945 char *TimeString; 946 char *Filename; 947 948 949 switch (ParseOpcode) 950 { 951 case PARSEOP___LINE__: 952 953 Op = TrAllocateNode (PARSEOP_INTEGER); 954 Op->Asl.Value.Integer = Op->Asl.LineNumber; 955 break; 956 957 case PARSEOP___PATH__: 958 959 Op = TrAllocateNode (PARSEOP_STRING_LITERAL); 960 961 /* Op.Asl.Filename contains the full pathname to the file */ 962 963 Op->Asl.Value.String = Op->Asl.Filename; 964 break; 965 966 case PARSEOP___FILE__: 967 968 Op = TrAllocateNode (PARSEOP_STRING_LITERAL); 969 970 /* Get the simple filename from the full path */ 971 972 FlSplitInputPathname (Op->Asl.Filename, NULL, &Filename); 973 Op->Asl.Value.String = Filename; 974 break; 975 976 case PARSEOP___DATE__: 977 978 Op = TrAllocateNode (PARSEOP_STRING_LITERAL); 979 980 /* Get a copy of the current time */ 981 982 CurrentTime = time (NULL); 983 StaticTimeString = ctime (&CurrentTime); 984 TimeString = UtLocalCalloc (strlen (StaticTimeString) + 1); 985 strcpy (TimeString, StaticTimeString); 986 987 TimeString[strlen(TimeString) -1] = 0; /* Remove trailing newline */ 988 Op->Asl.Value.String = TimeString; 989 break; 990 991 default: /* This would be an internal error */ 992 993 return (NULL); 994 } 995 996 DbgPrint (ASL_PARSE_OUTPUT, 997 "\nCreateConstantLeafNode Ln/Col %u/%u NewNode %p " 998 "Op %s Value %8.8X%8.8X \n", 999 Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName (ParseOpcode), 1000 ACPI_FORMAT_UINT64 (Op->Asl.Value.Integer)); 1001 return (Op); 1002 } 1003 1004 1005 /******************************************************************************* 1006 * 1007 * FUNCTION: TrCreateTargetOperand 1008 * 1009 * PARAMETERS: OriginalOp - Op to be copied 1010 * 1011 * RETURN: Pointer to the new node. Aborts on allocation failure 1012 * 1013 * DESCRIPTION: Copy an existing node (and subtree). Used in ASL+ (C-style) 1014 * expressions where the target is the same as one of the 1015 * operands. A new node and subtree must be created from the 1016 * original so that the parse tree can be linked properly. 1017 * 1018 * NOTE: This code is specific to target operands that are the last 1019 * operand in an ASL/AML operator. Meaning that the top-level 1020 * parse Op in a possible subtree has a NULL Next pointer. 1021 * This simplifies the recursion. 1022 * 1023 * Subtree example: 1024 * DeRefOf (Local1) += 32 1025 * 1026 * This gets converted to: 1027 * Add (DeRefOf (Local1), 32, DeRefOf (Local1)) 1028 * 1029 * Each DeRefOf has a single child, Local1. Even more complex 1030 * subtrees can be created via the Index and DeRefOf operators. 1031 * 1032 ******************************************************************************/ 1033 1034 ACPI_PARSE_OBJECT * 1035 TrCreateTargetOperand ( 1036 ACPI_PARSE_OBJECT *OriginalOp, 1037 ACPI_PARSE_OBJECT *ParentOp) 1038 { 1039 ACPI_PARSE_OBJECT *Op; 1040 1041 1042 if (!OriginalOp) 1043 { 1044 return (NULL); 1045 } 1046 1047 Op = TrGetNextNode (); 1048 1049 /* Copy the pertinent values (omit link pointer fields) */ 1050 1051 Op->Asl.Value = OriginalOp->Asl.Value; 1052 Op->Asl.Filename = OriginalOp->Asl.Filename; 1053 Op->Asl.LineNumber = OriginalOp->Asl.LineNumber; 1054 Op->Asl.LogicalLineNumber = OriginalOp->Asl.LogicalLineNumber; 1055 Op->Asl.LogicalByteOffset = OriginalOp->Asl.LogicalByteOffset; 1056 Op->Asl.Column = OriginalOp->Asl.Column; 1057 Op->Asl.Flags = OriginalOp->Asl.Flags; 1058 Op->Asl.CompileFlags = OriginalOp->Asl.CompileFlags; 1059 Op->Asl.AmlOpcode = OriginalOp->Asl.AmlOpcode; 1060 Op->Asl.ParseOpcode = OriginalOp->Asl.ParseOpcode; 1061 Op->Asl.Parent = ParentOp; 1062 UtSetParseOpName (Op); 1063 1064 /* Copy a possible subtree below this node */ 1065 1066 if (OriginalOp->Asl.Child) 1067 { 1068 Op->Asl.Child = TrCreateTargetOperand (OriginalOp->Asl.Child, Op); 1069 } 1070 1071 if (OriginalOp->Asl.Next) /* Null for top-level node */ 1072 { 1073 Op->Asl.Next = TrCreateTargetOperand (OriginalOp->Asl.Next, ParentOp); 1074 } 1075 1076 return (Op); 1077 } 1078 1079 1080 /******************************************************************************* 1081 * 1082 * FUNCTION: TrCreateValuedLeafNode 1083 * 1084 * PARAMETERS: ParseOpcode - New opcode to be assigned to the node 1085 * Value - Value to be assigned to the node 1086 * 1087 * RETURN: Pointer to the new node. Aborts on allocation failure 1088 * 1089 * DESCRIPTION: Create a leaf node (no children or peers) with a value 1090 * assigned to it 1091 * 1092 ******************************************************************************/ 1093 1094 ACPI_PARSE_OBJECT * 1095 TrCreateValuedLeafNode ( 1096 UINT32 ParseOpcode, 1097 UINT64 Value) 1098 { 1099 ACPI_PARSE_OBJECT *Op; 1100 1101 1102 Op = TrAllocateNode (ParseOpcode); 1103 1104 DbgPrint (ASL_PARSE_OUTPUT, 1105 "\nCreateValuedLeafNode Ln/Col %u/%u NewNode %p " 1106 "Op %s Value %8.8X%8.8X ", 1107 Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName(ParseOpcode), 1108 ACPI_FORMAT_UINT64 (Value)); 1109 Op->Asl.Value.Integer = Value; 1110 1111 switch (ParseOpcode) 1112 { 1113 case PARSEOP_STRING_LITERAL: 1114 1115 DbgPrint (ASL_PARSE_OUTPUT, "STRING->%s", Value); 1116 break; 1117 1118 case PARSEOP_NAMESEG: 1119 1120 DbgPrint (ASL_PARSE_OUTPUT, "NAMESEG->%s", Value); 1121 break; 1122 1123 case PARSEOP_NAMESTRING: 1124 1125 DbgPrint (ASL_PARSE_OUTPUT, "NAMESTRING->%s", Value); 1126 break; 1127 1128 case PARSEOP_EISAID: 1129 1130 DbgPrint (ASL_PARSE_OUTPUT, "EISAID->%s", Value); 1131 break; 1132 1133 case PARSEOP_METHOD: 1134 1135 DbgPrint (ASL_PARSE_OUTPUT, "METHOD"); 1136 break; 1137 1138 case PARSEOP_INTEGER: 1139 1140 DbgPrint (ASL_PARSE_OUTPUT, "INTEGER->%8.8X%8.8X", 1141 ACPI_FORMAT_UINT64 (Value)); 1142 break; 1143 1144 default: 1145 1146 break; 1147 } 1148 1149 DbgPrint (ASL_PARSE_OUTPUT, "\n\n"); 1150 return (Op); 1151 } 1152 1153 1154 /******************************************************************************* 1155 * 1156 * FUNCTION: TrCreateNode 1157 * 1158 * PARAMETERS: ParseOpcode - Opcode to be assigned to the node 1159 * NumChildren - Number of children to follow 1160 * ... - A list of child nodes to link to the new 1161 * node. NumChildren long. 1162 * 1163 * RETURN: Pointer to the new node. Aborts on allocation failure 1164 * 1165 * DESCRIPTION: Create a new parse node and link together a list of child 1166 * nodes underneath the new node. 1167 * 1168 ******************************************************************************/ 1169 1170 ACPI_PARSE_OBJECT * 1171 TrCreateNode ( 1172 UINT32 ParseOpcode, 1173 UINT32 NumChildren, 1174 ...) 1175 { 1176 ACPI_PARSE_OBJECT *Op; 1177 ACPI_PARSE_OBJECT *Child; 1178 ACPI_PARSE_OBJECT *PrevChild; 1179 va_list ap; 1180 UINT32 i; 1181 BOOLEAN FirstChild; 1182 1183 1184 va_start (ap, NumChildren); 1185 1186 /* Allocate one new node */ 1187 1188 Op = TrAllocateNode (ParseOpcode); 1189 1190 DbgPrint (ASL_PARSE_OUTPUT, 1191 "\nCreateNode Ln/Col %u/%u NewParent %p Child %u Op %s ", 1192 Op->Asl.LineNumber, Op->Asl.Column, Op, 1193 NumChildren, UtGetOpName(ParseOpcode)); 1194 1195 /* Some extra debug output based on the parse opcode */ 1196 1197 switch (ParseOpcode) 1198 { 1199 case PARSEOP_ASL_CODE: 1200 1201 Gbl_ParseTreeRoot = Op; 1202 Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 1203 DbgPrint (ASL_PARSE_OUTPUT, "ASLCODE (Tree Completed)->"); 1204 break; 1205 1206 case PARSEOP_DEFINITION_BLOCK: 1207 1208 DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->"); 1209 break; 1210 1211 case PARSEOP_OPERATIONREGION: 1212 1213 DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->"); 1214 break; 1215 1216 case PARSEOP_OR: 1217 1218 DbgPrint (ASL_PARSE_OUTPUT, "OR->"); 1219 break; 1220 1221 default: 1222 1223 /* Nothing to do for other opcodes */ 1224 1225 break; 1226 } 1227 1228 /* Link the new node to its children */ 1229 1230 PrevChild = NULL; 1231 FirstChild = TRUE; 1232 for (i = 0; i < NumChildren; i++) 1233 { 1234 /* Get the next child */ 1235 1236 Child = va_arg (ap, ACPI_PARSE_OBJECT *); 1237 DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child); 1238 1239 /* 1240 * If child is NULL, this means that an optional argument 1241 * was omitted. We must create a placeholder with a special 1242 * opcode (DEFAULT_ARG) so that the code generator will know 1243 * that it must emit the correct default for this argument 1244 */ 1245 if (!Child) 1246 { 1247 Child = TrAllocateNode (PARSEOP_DEFAULT_ARG); 1248 } 1249 1250 /* Link first child to parent */ 1251 1252 if (FirstChild) 1253 { 1254 FirstChild = FALSE; 1255 Op->Asl.Child = Child; 1256 1257 /* 1258 * For the ASL-/ASL+ converter: if the ParseOp is a connection, 1259 * external, offset or accessAs, it means that the comments in the 1260 * FirstChild belongs to their parent due to the parsing order in 1261 * the .y files. To correct this, take the comments in the 1262 * FirstChild place it in the parent. This also means that 1263 * legitimate comments for the child gets put to the parent. 1264 */ 1265 if (Gbl_CaptureComments && 1266 ((ParseOpcode == PARSEOP_CONNECTION) || 1267 (ParseOpcode == PARSEOP_EXTERNAL) || 1268 (ParseOpcode == PARSEOP_OFFSET) || 1269 (ParseOpcode == PARSEOP_ACCESSAS))) 1270 { 1271 Op->Asl.CommentList = Child->Asl.CommentList; 1272 Op->Asl.EndBlkComment = Child->Asl.EndBlkComment; 1273 Op->Asl.InlineComment = Child->Asl.InlineComment; 1274 Op->Asl.FileChanged = Child->Asl.FileChanged; 1275 1276 Child->Asl.CommentList = NULL; 1277 Child->Asl.EndBlkComment = NULL; 1278 Child->Asl.InlineComment = NULL; 1279 Child->Asl.FileChanged = FALSE; 1280 1281 /* 1282 * These do not need to be "passed off". They can be copied 1283 * because the code for these opcodes should be printed in the 1284 * same file. 1285 */ 1286 Op->Asl.Filename = Child->Asl.Filename; 1287 Op->Asl.ParentFilename = Child->Asl.ParentFilename; 1288 } 1289 } 1290 1291 /* Point all children to parent */ 1292 1293 Child->Asl.Parent = Op; 1294 1295 /* Link children in a peer list */ 1296 1297 if (PrevChild) 1298 { 1299 PrevChild->Asl.Next = Child; 1300 }; 1301 1302 /* Get the comment from last child in the resource template call */ 1303 1304 if (Gbl_CaptureComments && 1305 (Op->Asl.ParseOpcode == PARSEOP_RESOURCETEMPLATE)) 1306 { 1307 CvDbgPrint ("Transferred current comment list to this node.\n"); 1308 Op->Asl.CommentList = Child->Asl.CommentList; 1309 Child->Asl.CommentList = NULL; 1310 Op->Asl.InlineComment = Child->Asl.InlineComment; 1311 Child->Asl.InlineComment = NULL; 1312 } 1313 1314 /* 1315 * This child might be a list, point all nodes in the list 1316 * to the same parent 1317 */ 1318 while (Child->Asl.Next) 1319 { 1320 Child = Child->Asl.Next; 1321 Child->Asl.Parent = Op; 1322 } 1323 1324 PrevChild = Child; 1325 } 1326 va_end(ap); 1327 1328 DbgPrint (ASL_PARSE_OUTPUT, "\n"); 1329 return (Op); 1330 } 1331 1332 1333 /******************************************************************************* 1334 * 1335 * FUNCTION: TrLinkChildren 1336 * 1337 * PARAMETERS: Op - An existing parse node 1338 * NumChildren - Number of children to follow 1339 * ... - A list of child nodes to link to the new 1340 * node. NumChildren long. 1341 * 1342 * RETURN: The updated (linked) node 1343 * 1344 * DESCRIPTION: Link a group of nodes to an existing parse node 1345 * 1346 ******************************************************************************/ 1347 1348 ACPI_PARSE_OBJECT * 1349 TrLinkChildren ( 1350 ACPI_PARSE_OBJECT *Op, 1351 UINT32 NumChildren, 1352 ...) 1353 { 1354 ACPI_PARSE_OBJECT *Child; 1355 ACPI_PARSE_OBJECT *PrevChild; 1356 va_list ap; 1357 UINT32 i; 1358 BOOLEAN FirstChild; 1359 1360 1361 va_start (ap, NumChildren); 1362 1363 1364 TrSetEndLineNumber (Op); 1365 1366 DbgPrint (ASL_PARSE_OUTPUT, 1367 "\nLinkChildren Line [%u to %u] NewParent %p Child %u Op %s ", 1368 Op->Asl.LineNumber, Op->Asl.EndLine, 1369 Op, NumChildren, UtGetOpName(Op->Asl.ParseOpcode)); 1370 1371 switch (Op->Asl.ParseOpcode) 1372 { 1373 case PARSEOP_ASL_CODE: 1374 1375 Gbl_ParseTreeRoot = Op; 1376 Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 1377 DbgPrint (ASL_PARSE_OUTPUT, "ASLCODE (Tree Completed)->"); 1378 break; 1379 1380 case PARSEOP_DEFINITION_BLOCK: 1381 1382 DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->"); 1383 break; 1384 1385 case PARSEOP_OPERATIONREGION: 1386 1387 DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->"); 1388 break; 1389 1390 case PARSEOP_OR: 1391 1392 DbgPrint (ASL_PARSE_OUTPUT, "OR->"); 1393 break; 1394 1395 default: 1396 1397 /* Nothing to do for other opcodes */ 1398 1399 break; 1400 } 1401 1402 /* The following is for capturing comments */ 1403 1404 if(Gbl_CaptureComments) 1405 { 1406 /* 1407 * If there are "regular comments" detected at this point, 1408 * then is an endBlk comment. Categorize it as so and distribute 1409 * all regular comments to this parse node. 1410 */ 1411 if (Gbl_Comment_List_Head) 1412 { 1413 Op->Asl.EndBlkComment = Gbl_Comment_List_Head; 1414 CvDbgPrint ("EndBlk Comment for %s: %s", 1415 Op->Asl.ParseOpName, Gbl_Comment_List_Head->Comment); 1416 Gbl_Comment_List_Head = NULL; 1417 Gbl_Comment_List_Tail = NULL; 1418 } 1419 } 1420 1421 /* Link the new node to it's children */ 1422 1423 PrevChild = NULL; 1424 FirstChild = TRUE; 1425 for (i = 0; i < NumChildren; i++) 1426 { 1427 Child = va_arg (ap, ACPI_PARSE_OBJECT *); 1428 1429 if ((Child == PrevChild) && (Child != NULL)) 1430 { 1431 AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Child, 1432 "Child node list invalid"); 1433 va_end(ap); 1434 return (Op); 1435 } 1436 1437 DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child); 1438 1439 /* 1440 * If child is NULL, this means that an optional argument 1441 * was omitted. We must create a placeholder with a special 1442 * opcode (DEFAULT_ARG) so that the code generator will know 1443 * that it must emit the correct default for this argument 1444 */ 1445 if (!Child) 1446 { 1447 Child = TrAllocateNode (PARSEOP_DEFAULT_ARG); 1448 } 1449 1450 /* Link first child to parent */ 1451 1452 if (FirstChild) 1453 { 1454 FirstChild = FALSE; 1455 Op->Asl.Child = Child; 1456 } 1457 1458 /* Point all children to parent */ 1459 1460 Child->Asl.Parent = Op; 1461 1462 /* Link children in a peer list */ 1463 1464 if (PrevChild) 1465 { 1466 PrevChild->Asl.Next = Child; 1467 }; 1468 1469 /* 1470 * This child might be a list, point all nodes in the list 1471 * to the same parent 1472 */ 1473 while (Child->Asl.Next) 1474 { 1475 Child = Child->Asl.Next; 1476 Child->Asl.Parent = Op; 1477 } 1478 1479 PrevChild = Child; 1480 } 1481 1482 va_end(ap); 1483 DbgPrint (ASL_PARSE_OUTPUT, "\n\n"); 1484 1485 1486 if(Gbl_CaptureComments) 1487 { 1488 Gbl_CommentState.Latest_Parse_Node = Op; 1489 CvDbgPrint ("trlinkchildren=====Set latest parse node to this node.\n"); 1490 } 1491 return (Op); 1492 } 1493 1494 1495 /******************************************************************************* 1496 * 1497 * FUNCTION: TrLinkPeerNode 1498 * 1499 * PARAMETERS: Op1 - First peer 1500 * Op2 - Second peer 1501 * 1502 * RETURN: Op1 or the non-null node. 1503 * 1504 * DESCRIPTION: Link two nodes as peers. Handles cases where one peer is null. 1505 * 1506 ******************************************************************************/ 1507 1508 ACPI_PARSE_OBJECT * 1509 TrLinkPeerNode ( 1510 ACPI_PARSE_OBJECT *Op1, 1511 ACPI_PARSE_OBJECT *Op2) 1512 { 1513 ACPI_PARSE_OBJECT *Next; 1514 1515 1516 DbgPrint (ASL_PARSE_OUTPUT, 1517 "\nLinkPeerNode: 1=%p (%s), 2=%p (%s)\n", 1518 Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode) : NULL, 1519 Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode) : NULL); 1520 1521 1522 if ((!Op1) && (!Op2)) 1523 { 1524 DbgPrint (ASL_PARSE_OUTPUT, "\nTwo Null nodes!\n"); 1525 return (Op1); 1526 } 1527 1528 /* If one of the nodes is null, just return the non-null node */ 1529 1530 if (!Op2) 1531 { 1532 return (Op1); 1533 } 1534 1535 if (!Op1) 1536 { 1537 return (Op2); 1538 } 1539 1540 if (Op1 == Op2) 1541 { 1542 DbgPrint (ASL_DEBUG_OUTPUT, 1543 "\n************* Internal error, linking node to itself %p\n", 1544 Op1); 1545 AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op1, 1546 "Linking node to itself"); 1547 return (Op1); 1548 } 1549 1550 Op1->Asl.Parent = Op2->Asl.Parent; 1551 1552 /* 1553 * Op 1 may already have a peer list (such as an IF/ELSE pair), 1554 * so we must walk to the end of the list and attach the new 1555 * peer at the end 1556 */ 1557 Next = Op1; 1558 while (Next->Asl.Next) 1559 { 1560 Next = Next->Asl.Next; 1561 } 1562 1563 Next->Asl.Next = Op2; 1564 return (Op1); 1565 } 1566 1567 1568 /******************************************************************************* 1569 * 1570 * FUNCTION: TrLinkPeerNodes 1571 * 1572 * PARAMETERS: NumPeers - The number of nodes in the list to follow 1573 * ... - A list of nodes to link together as peers 1574 * 1575 * RETURN: The first node in the list (head of the peer list) 1576 * 1577 * DESCRIPTION: Link together an arbitrary number of peer nodes. 1578 * 1579 ******************************************************************************/ 1580 1581 ACPI_PARSE_OBJECT * 1582 TrLinkPeerNodes ( 1583 UINT32 NumPeers, 1584 ...) 1585 { 1586 ACPI_PARSE_OBJECT *This; 1587 ACPI_PARSE_OBJECT *Next; 1588 va_list ap; 1589 UINT32 i; 1590 ACPI_PARSE_OBJECT *Start; 1591 1592 1593 DbgPrint (ASL_PARSE_OUTPUT, 1594 "\nLinkPeerNodes: (%u) ", NumPeers); 1595 1596 va_start (ap, NumPeers); 1597 This = va_arg (ap, ACPI_PARSE_OBJECT *); 1598 Start = This; 1599 1600 /* 1601 * Link all peers 1602 */ 1603 for (i = 0; i < (NumPeers -1); i++) 1604 { 1605 DbgPrint (ASL_PARSE_OUTPUT, "%u=%p ", (i+1), This); 1606 1607 while (This->Asl.Next) 1608 { 1609 This = This->Asl.Next; 1610 } 1611 1612 /* Get another peer node */ 1613 1614 Next = va_arg (ap, ACPI_PARSE_OBJECT *); 1615 if (!Next) 1616 { 1617 Next = TrAllocateNode (PARSEOP_DEFAULT_ARG); 1618 } 1619 1620 /* link new node to the current node */ 1621 1622 This->Asl.Next = Next; 1623 This = Next; 1624 } 1625 va_end (ap); 1626 1627 DbgPrint (ASL_PARSE_OUTPUT,"\n"); 1628 return (Start); 1629 } 1630 1631 1632 /******************************************************************************* 1633 * 1634 * FUNCTION: TrLinkChildNode 1635 * 1636 * PARAMETERS: Op1 - Parent node 1637 * Op2 - Op to become a child 1638 * 1639 * RETURN: The parent node 1640 * 1641 * DESCRIPTION: Link two nodes together as a parent and child 1642 * 1643 ******************************************************************************/ 1644 1645 ACPI_PARSE_OBJECT * 1646 TrLinkChildNode ( 1647 ACPI_PARSE_OBJECT *Op1, 1648 ACPI_PARSE_OBJECT *Op2) 1649 { 1650 ACPI_PARSE_OBJECT *Next; 1651 1652 1653 DbgPrint (ASL_PARSE_OUTPUT, 1654 "\nLinkChildNode: Parent=%p (%s), Child=%p (%s)\n", 1655 Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode): NULL, 1656 Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode): NULL); 1657 1658 /* 1659 * Converter: if TrLinkChildNode is called to link a method call, 1660 * turn on capture comments as it signifies that we are done parsing 1661 * a method call. 1662 */ 1663 if (Gbl_CaptureComments) 1664 { 1665 if (Op1->Asl.ParseOpcode == PARSEOP_METHODCALL) 1666 { 1667 Gbl_CommentState.CaptureComments = TRUE; 1668 } 1669 Gbl_CommentState.Latest_Parse_Node = Op1; 1670 } 1671 if (!Op1 || !Op2) 1672 { 1673 return (Op1); 1674 } 1675 1676 Op1->Asl.Child = Op2; 1677 1678 /* Set the child and all peers of the child to point to the parent */ 1679 1680 Next = Op2; 1681 while (Next) 1682 { 1683 Next->Asl.Parent = Op1; 1684 Next = Next->Asl.Next; 1685 } 1686 1687 return (Op1); 1688 } 1689 1690 1691 /******************************************************************************* 1692 * 1693 * FUNCTION: TrWalkParseTree 1694 * 1695 * PARAMETERS: Visitation - Type of walk 1696 * DescendingCallback - Called during tree descent 1697 * AscendingCallback - Called during tree ascent 1698 * Context - To be passed to the callbacks 1699 * 1700 * RETURN: Status from callback(s) 1701 * 1702 * DESCRIPTION: Walk the entire parse tree. 1703 * 1704 ******************************************************************************/ 1705 1706 ACPI_STATUS 1707 TrWalkParseTree ( 1708 ACPI_PARSE_OBJECT *Op, 1709 UINT32 Visitation, 1710 ASL_WALK_CALLBACK DescendingCallback, 1711 ASL_WALK_CALLBACK AscendingCallback, 1712 void *Context) 1713 { 1714 UINT32 Level; 1715 BOOLEAN NodePreviouslyVisited; 1716 ACPI_PARSE_OBJECT *StartOp = Op; 1717 ACPI_STATUS Status; 1718 1719 1720 if (!Gbl_ParseTreeRoot) 1721 { 1722 return (AE_OK); 1723 } 1724 1725 Level = 0; 1726 NodePreviouslyVisited = FALSE; 1727 1728 switch (Visitation) 1729 { 1730 case ASL_WALK_VISIT_DOWNWARD: 1731 1732 while (Op) 1733 { 1734 if (!NodePreviouslyVisited) 1735 { 1736 /* Let the callback process the node. */ 1737 1738 Status = DescendingCallback (Op, Level, Context); 1739 if (ACPI_SUCCESS (Status)) 1740 { 1741 /* Visit children first, once */ 1742 1743 if (Op->Asl.Child) 1744 { 1745 Level++; 1746 Op = Op->Asl.Child; 1747 continue; 1748 } 1749 } 1750 else if (Status != AE_CTRL_DEPTH) 1751 { 1752 /* Exit immediately on any error */ 1753 1754 return (Status); 1755 } 1756 } 1757 1758 /* Terminate walk at start op */ 1759 1760 if (Op == StartOp) 1761 { 1762 break; 1763 } 1764 1765 /* No more children, visit peers */ 1766 1767 if (Op->Asl.Next) 1768 { 1769 Op = Op->Asl.Next; 1770 NodePreviouslyVisited = FALSE; 1771 } 1772 else 1773 { 1774 /* No children or peers, re-visit parent */ 1775 1776 if (Level != 0 ) 1777 { 1778 Level--; 1779 } 1780 Op = Op->Asl.Parent; 1781 NodePreviouslyVisited = TRUE; 1782 } 1783 } 1784 break; 1785 1786 case ASL_WALK_VISIT_UPWARD: 1787 1788 while (Op) 1789 { 1790 /* Visit leaf node (no children) or parent node on return trip */ 1791 1792 if ((!Op->Asl.Child) || 1793 (NodePreviouslyVisited)) 1794 { 1795 /* Let the callback process the node. */ 1796 1797 Status = AscendingCallback (Op, Level, Context); 1798 if (ACPI_FAILURE (Status)) 1799 { 1800 return (Status); 1801 } 1802 } 1803 else 1804 { 1805 /* Visit children first, once */ 1806 1807 Level++; 1808 Op = Op->Asl.Child; 1809 continue; 1810 } 1811 1812 /* Terminate walk at start op */ 1813 1814 if (Op == StartOp) 1815 { 1816 break; 1817 } 1818 1819 /* No more children, visit peers */ 1820 1821 if (Op->Asl.Next) 1822 { 1823 Op = Op->Asl.Next; 1824 NodePreviouslyVisited = FALSE; 1825 } 1826 else 1827 { 1828 /* No children or peers, re-visit parent */ 1829 1830 if (Level != 0 ) 1831 { 1832 Level--; 1833 } 1834 Op = Op->Asl.Parent; 1835 NodePreviouslyVisited = TRUE; 1836 } 1837 } 1838 break; 1839 1840 case ASL_WALK_VISIT_TWICE: 1841 1842 while (Op) 1843 { 1844 if (NodePreviouslyVisited) 1845 { 1846 Status = AscendingCallback (Op, Level, Context); 1847 if (ACPI_FAILURE (Status)) 1848 { 1849 return (Status); 1850 } 1851 } 1852 else 1853 { 1854 /* Let the callback process the node. */ 1855 1856 Status = DescendingCallback (Op, Level, Context); 1857 if (ACPI_SUCCESS (Status)) 1858 { 1859 /* Visit children first, once */ 1860 1861 if (Op->Asl.Child) 1862 { 1863 Level++; 1864 Op = Op->Asl.Child; 1865 continue; 1866 } 1867 } 1868 else if (Status != AE_CTRL_DEPTH) 1869 { 1870 /* Exit immediately on any error */ 1871 1872 return (Status); 1873 } 1874 } 1875 1876 /* Terminate walk at start op */ 1877 1878 if (Op == StartOp) 1879 { 1880 break; 1881 } 1882 1883 /* No more children, visit peers */ 1884 1885 if (Op->Asl.Next) 1886 { 1887 Op = Op->Asl.Next; 1888 NodePreviouslyVisited = FALSE; 1889 } 1890 else 1891 { 1892 /* No children or peers, re-visit parent */ 1893 1894 if (Level != 0 ) 1895 { 1896 Level--; 1897 } 1898 Op = Op->Asl.Parent; 1899 NodePreviouslyVisited = TRUE; 1900 } 1901 } 1902 break; 1903 1904 default: 1905 /* No other types supported */ 1906 break; 1907 } 1908 1909 /* If we get here, the walk completed with no errors */ 1910 1911 return (AE_OK); 1912 } 1913