1118611Snjl/****************************************************************************** 2118611Snjl * 3118611Snjl * Module Name: asltree - parse tree management 4118611Snjl * 5118611Snjl *****************************************************************************/ 6118611Snjl 7217365Sjkim/* 8306536Sjkim * Copyright (C) 2000 - 2016, Intel Corp. 9118611Snjl * All rights reserved. 10118611Snjl * 11217365Sjkim * Redistribution and use in source and binary forms, with or without 12217365Sjkim * modification, are permitted provided that the following conditions 13217365Sjkim * are met: 14217365Sjkim * 1. Redistributions of source code must retain the above copyright 15217365Sjkim * notice, this list of conditions, and the following disclaimer, 16217365Sjkim * without modification. 17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20217365Sjkim * including a substantially similar Disclaimer requirement for further 21217365Sjkim * binary redistribution. 22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23217365Sjkim * of any contributors may be used to endorse or promote products derived 24217365Sjkim * from this software without specific prior written permission. 25118611Snjl * 26217365Sjkim * Alternatively, this software may be distributed under the terms of the 27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28217365Sjkim * Software Foundation. 29118611Snjl * 30217365Sjkim * NO WARRANTY 31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41217365Sjkim * POSSIBILITY OF SUCH DAMAGES. 42217365Sjkim */ 43118611Snjl 44151937Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h> 45118611Snjl#include "aslcompiler.y.h" 46228110Sjkim#include <contrib/dev/acpica/include/acapps.h> 47218590Sjkim#include <time.h> 48118611Snjl 49118611Snjl#define _COMPONENT ACPI_COMPILER 50118611Snjl ACPI_MODULE_NAME ("asltree") 51118611Snjl 52151937Sjkim/* Local prototypes */ 53118611Snjl 54151937Sjkimstatic ACPI_PARSE_OBJECT * 55151937SjkimTrGetNextNode ( 56151937Sjkim void); 57151937Sjkim 58151937Sjkim 59118611Snjl/******************************************************************************* 60118611Snjl * 61306536Sjkim * FUNCTION: TrSetParent 62306536Sjkim * 63306536Sjkim * PARAMETERS: Op - To be set to new parent 64306536Sjkim * ParentOp - The parent 65306536Sjkim * 66306536Sjkim * RETURN: None, sets Op parent directly 67306536Sjkim * 68306536Sjkim * DESCRIPTION: Change the parent of a parse op. 69306536Sjkim * 70306536Sjkim ******************************************************************************/ 71306536Sjkim 72306536Sjkimvoid 73306536SjkimTrSetParent ( 74306536Sjkim ACPI_PARSE_OBJECT *Op, 75306536Sjkim ACPI_PARSE_OBJECT *ParentOp) 76306536Sjkim{ 77306536Sjkim 78306536Sjkim Op->Asl.Parent = ParentOp; 79306536Sjkim} 80306536Sjkim 81306536Sjkim 82306536Sjkim/******************************************************************************* 83306536Sjkim * 84118611Snjl * FUNCTION: TrGetNextNode 85118611Snjl * 86118611Snjl * PARAMETERS: None 87118611Snjl * 88239340Sjkim * RETURN: New parse node. Aborts on allocation failure 89118611Snjl * 90239340Sjkim * DESCRIPTION: Allocate a new parse node for the parse tree. Bypass the local 91118611Snjl * dynamic memory manager for performance reasons (This has a 92118611Snjl * major impact on the speed of the compiler.) 93118611Snjl * 94118611Snjl ******************************************************************************/ 95118611Snjl 96151937Sjkimstatic ACPI_PARSE_OBJECT * 97151937SjkimTrGetNextNode ( 98151937Sjkim void) 99118611Snjl{ 100281075Sdim ASL_CACHE_INFO *Cache; 101118611Snjl 102281075Sdim 103281075Sdim if (Gbl_ParseOpCacheNext >= Gbl_ParseOpCacheLast) 104118611Snjl { 105281075Sdim /* Allocate a new buffer */ 106281075Sdim 107281075Sdim Cache = UtLocalCalloc (sizeof (Cache->Next) + 108281075Sdim (sizeof (ACPI_PARSE_OBJECT) * ASL_PARSEOP_CACHE_SIZE)); 109281075Sdim 110281075Sdim /* Link new cache buffer to head of list */ 111281075Sdim 112281075Sdim Cache->Next = Gbl_ParseOpCacheList; 113281075Sdim Gbl_ParseOpCacheList = Cache; 114281075Sdim 115281075Sdim /* Setup cache management pointers */ 116281075Sdim 117281075Sdim Gbl_ParseOpCacheNext = ACPI_CAST_PTR (ACPI_PARSE_OBJECT, Cache->Buffer); 118281075Sdim Gbl_ParseOpCacheLast = Gbl_ParseOpCacheNext + ASL_PARSEOP_CACHE_SIZE; 119118611Snjl } 120118611Snjl 121281075Sdim Gbl_ParseOpCount++; 122281075Sdim return (Gbl_ParseOpCacheNext++); 123118611Snjl} 124118611Snjl 125118611Snjl 126118611Snjl/******************************************************************************* 127118611Snjl * 128118611Snjl * FUNCTION: TrAllocateNode 129118611Snjl * 130118611Snjl * PARAMETERS: ParseOpcode - Opcode to be assigned to the node 131118611Snjl * 132239340Sjkim * RETURN: New parse node. Aborts on allocation failure 133118611Snjl * 134118611Snjl * DESCRIPTION: Allocate and initialize a new parse node for the parse tree 135118611Snjl * 136118611Snjl ******************************************************************************/ 137118611Snjl 138118611SnjlACPI_PARSE_OBJECT * 139118611SnjlTrAllocateNode ( 140118611Snjl UINT32 ParseOpcode) 141118611Snjl{ 142118611Snjl ACPI_PARSE_OBJECT *Op; 143118611Snjl 144118611Snjl 145118611Snjl Op = TrGetNextNode (); 146118611Snjl 147118611Snjl Op->Asl.ParseOpcode = (UINT16) ParseOpcode; 148118611Snjl Op->Asl.Filename = Gbl_Files[ASL_FILE_INPUT].Filename; 149118611Snjl Op->Asl.LineNumber = Gbl_CurrentLineNumber; 150118611Snjl Op->Asl.LogicalLineNumber = Gbl_LogicalLineNumber; 151118611Snjl Op->Asl.LogicalByteOffset = Gbl_CurrentLineOffset; 152118611Snjl Op->Asl.Column = Gbl_CurrentColumn; 153118611Snjl 154118611Snjl UtSetParseOpName (Op); 155241973Sjkim return (Op); 156118611Snjl} 157118611Snjl 158118611Snjl 159118611Snjl/******************************************************************************* 160118611Snjl * 161118611Snjl * FUNCTION: TrReleaseNode 162118611Snjl * 163118611Snjl * PARAMETERS: Op - Op to be released 164118611Snjl * 165118611Snjl * RETURN: None 166118611Snjl * 167239340Sjkim * DESCRIPTION: "release" a node. In truth, nothing is done since the node 168118611Snjl * is part of a larger buffer 169118611Snjl * 170118611Snjl ******************************************************************************/ 171118611Snjl 172118611Snjlvoid 173118611SnjlTrReleaseNode ( 174118611Snjl ACPI_PARSE_OBJECT *Op) 175118611Snjl{ 176118611Snjl 177118611Snjl return; 178118611Snjl} 179118611Snjl 180118611Snjl 181118611Snjl/******************************************************************************* 182118611Snjl * 183306536Sjkim * FUNCTION: TrSetCurrentFilename 184306536Sjkim * 185306536Sjkim * PARAMETERS: Op - An existing parse node 186306536Sjkim * 187306536Sjkim * RETURN: None 188306536Sjkim * 189306536Sjkim * DESCRIPTION: Save the include file filename. Used for debug output only. 190306536Sjkim * 191306536Sjkim ******************************************************************************/ 192306536Sjkim 193306536Sjkimvoid 194306536SjkimTrSetCurrentFilename ( 195306536Sjkim ACPI_PARSE_OBJECT *Op) 196306536Sjkim{ 197306536Sjkim Op->Asl.Filename = Gbl_PreviousIncludeFilename; 198306536Sjkim} 199306536Sjkim 200306536Sjkim 201306536Sjkim/******************************************************************************* 202306536Sjkim * 203118611Snjl * FUNCTION: TrUpdateNode 204118611Snjl * 205118611Snjl * PARAMETERS: ParseOpcode - New opcode to be assigned to the node 206306536Sjkim * Op - An existing parse node 207118611Snjl * 208118611Snjl * RETURN: The updated node 209118611Snjl * 210239340Sjkim * DESCRIPTION: Change the parse opcode assigned to a node. Usually used to 211118611Snjl * change an opcode to DEFAULT_ARG so that the node is ignored 212239340Sjkim * during the code generation. Also used to set generic integers 213118611Snjl * to a specific size (8, 16, 32, or 64 bits) 214118611Snjl * 215118611Snjl ******************************************************************************/ 216118611Snjl 217118611SnjlACPI_PARSE_OBJECT * 218118611SnjlTrUpdateNode ( 219118611Snjl UINT32 ParseOpcode, 220118611Snjl ACPI_PARSE_OBJECT *Op) 221118611Snjl{ 222118611Snjl 223118611Snjl if (!Op) 224118611Snjl { 225241973Sjkim return (NULL); 226118611Snjl } 227118611Snjl 228118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 229281687Sjkim "\nUpdateNode: Old - %s, New - %s\n", 230118611Snjl UtGetOpName (Op->Asl.ParseOpcode), 231118611Snjl UtGetOpName (ParseOpcode)); 232118611Snjl 233118611Snjl /* Assign new opcode and name */ 234118611Snjl 235118611Snjl if (Op->Asl.ParseOpcode == PARSEOP_ONES) 236118611Snjl { 237118611Snjl switch (ParseOpcode) 238118611Snjl { 239118611Snjl case PARSEOP_BYTECONST: 240250838Sjkim 241239340Sjkim Op->Asl.Value.Integer = ACPI_UINT8_MAX; 242118611Snjl break; 243118611Snjl 244118611Snjl case PARSEOP_WORDCONST: 245250838Sjkim 246239340Sjkim Op->Asl.Value.Integer = ACPI_UINT16_MAX; 247118611Snjl break; 248118611Snjl 249118611Snjl case PARSEOP_DWORDCONST: 250250838Sjkim 251239340Sjkim Op->Asl.Value.Integer = ACPI_UINT32_MAX; 252118611Snjl break; 253118611Snjl 254239340Sjkim /* Don't need to do the QWORD case */ 255239340Sjkim 256118611Snjl default: 257250838Sjkim 258239340Sjkim /* Don't care about others */ 259118611Snjl break; 260118611Snjl } 261118611Snjl } 262118611Snjl 263118611Snjl Op->Asl.ParseOpcode = (UINT16) ParseOpcode; 264118611Snjl UtSetParseOpName (Op); 265118611Snjl 266118611Snjl /* 267118611Snjl * For the BYTE, WORD, and DWORD constants, make sure that the integer 268118611Snjl * that was passed in will actually fit into the data type 269118611Snjl */ 270118611Snjl switch (ParseOpcode) 271118611Snjl { 272118611Snjl case PARSEOP_BYTECONST: 273250838Sjkim 274239340Sjkim UtCheckIntegerRange (Op, 0x00, ACPI_UINT8_MAX); 275239340Sjkim Op->Asl.Value.Integer &= ACPI_UINT8_MAX; 276118611Snjl break; 277118611Snjl 278118611Snjl case PARSEOP_WORDCONST: 279250838Sjkim 280239340Sjkim UtCheckIntegerRange (Op, 0x00, ACPI_UINT16_MAX); 281239340Sjkim Op->Asl.Value.Integer &= ACPI_UINT16_MAX; 282118611Snjl break; 283118611Snjl 284118611Snjl case PARSEOP_DWORDCONST: 285250838Sjkim 286239340Sjkim UtCheckIntegerRange (Op, 0x00, ACPI_UINT32_MAX); 287239340Sjkim Op->Asl.Value.Integer &= ACPI_UINT32_MAX; 288118611Snjl break; 289118611Snjl 290118611Snjl default: 291250838Sjkim 292118611Snjl /* Don't care about others, don't need to check QWORD */ 293250838Sjkim 294118611Snjl break; 295118611Snjl } 296118611Snjl 297241973Sjkim return (Op); 298118611Snjl} 299118611Snjl 300118611Snjl 301118611Snjl/******************************************************************************* 302118611Snjl * 303281687Sjkim * FUNCTION: TrPrintNodeCompileFlags 304118611Snjl * 305118611Snjl * PARAMETERS: Flags - Flags word to be decoded 306118611Snjl * 307281687Sjkim * RETURN: None 308118611Snjl * 309281687Sjkim * DESCRIPTION: Decode a flags word to text. Displays all flags that are set. 310118611Snjl * 311118611Snjl ******************************************************************************/ 312118611Snjl 313281687Sjkimvoid 314281687SjkimTrPrintNodeCompileFlags ( 315118611Snjl UINT32 Flags) 316118611Snjl{ 317281687Sjkim UINT32 i; 318281687Sjkim UINT32 FlagBit = 1; 319281687Sjkim char *FlagName = NULL; 320118611Snjl 321281687Sjkim 322281687Sjkim for (i = 0; i < 32; i++) 323118611Snjl { 324281687Sjkim switch (Flags & FlagBit) 325281687Sjkim { 326281687Sjkim case NODE_VISITED: 327250838Sjkim 328281687Sjkim FlagName = "NODE_VISITED"; 329281687Sjkim break; 330118611Snjl 331281687Sjkim case NODE_AML_PACKAGE: 332250838Sjkim 333281687Sjkim FlagName = "NODE_AML_PACKAGE"; 334281687Sjkim break; 335118611Snjl 336281687Sjkim case NODE_IS_TARGET: 337250838Sjkim 338281687Sjkim FlagName = "NODE_IS_TARGET"; 339281687Sjkim break; 340118611Snjl 341281687Sjkim case NODE_IS_RESOURCE_DESC: 342250838Sjkim 343281687Sjkim FlagName = "NODE_IS_RESOURCE_DESC"; 344281687Sjkim break; 345118611Snjl 346281687Sjkim case NODE_IS_RESOURCE_FIELD: 347250838Sjkim 348281687Sjkim FlagName = "NODE_IS_RESOURCE_FIELD"; 349281687Sjkim break; 350118611Snjl 351281687Sjkim case NODE_HAS_NO_EXIT: 352250838Sjkim 353281687Sjkim FlagName = "NODE_HAS_NO_EXIT"; 354281687Sjkim break; 355118611Snjl 356281687Sjkim case NODE_IF_HAS_NO_EXIT: 357250838Sjkim 358281687Sjkim FlagName = "NODE_IF_HAS_NO_EXIT"; 359281687Sjkim break; 360118611Snjl 361281687Sjkim case NODE_NAME_INTERNALIZED: 362250838Sjkim 363281687Sjkim FlagName = "NODE_NAME_INTERNALIZED"; 364281687Sjkim break; 365118611Snjl 366281687Sjkim case NODE_METHOD_NO_RETVAL: 367250838Sjkim 368281687Sjkim FlagName = "NODE_METHOD_NO_RETVAL"; 369281687Sjkim break; 370118611Snjl 371281687Sjkim case NODE_METHOD_SOME_NO_RETVAL: 372250838Sjkim 373281687Sjkim FlagName = "NODE_METHOD_SOME_NO_RETVAL"; 374281687Sjkim break; 375118611Snjl 376281687Sjkim case NODE_RESULT_NOT_USED: 377250838Sjkim 378281687Sjkim FlagName = "NODE_RESULT_NOT_USED"; 379281687Sjkim break; 380118611Snjl 381281687Sjkim case NODE_METHOD_TYPED: 382250838Sjkim 383281687Sjkim FlagName = "NODE_METHOD_TYPED"; 384281687Sjkim break; 385118611Snjl 386306536Sjkim case NODE_COULD_NOT_REDUCE: 387306536Sjkim 388306536Sjkim FlagName = "NODE_COULD_NOT_REDUCE"; 389306536Sjkim break; 390306536Sjkim 391281687Sjkim case NODE_COMPILE_TIME_CONST: 392250838Sjkim 393281687Sjkim FlagName = "NODE_COMPILE_TIME_CONST"; 394281687Sjkim break; 395118611Snjl 396281687Sjkim case NODE_IS_TERM_ARG: 397250838Sjkim 398281687Sjkim FlagName = "NODE_IS_TERM_ARG"; 399281687Sjkim break; 400118611Snjl 401281687Sjkim case NODE_WAS_ONES_OP: 402250838Sjkim 403281687Sjkim FlagName = "NODE_WAS_ONES_OP"; 404281687Sjkim break; 405118611Snjl 406281687Sjkim case NODE_IS_NAME_DECLARATION: 407250838Sjkim 408281687Sjkim FlagName = "NODE_IS_NAME_DECLARATION"; 409281687Sjkim break; 410118611Snjl 411281687Sjkim case NODE_COMPILER_EMITTED: 412250838Sjkim 413281687Sjkim FlagName = "NODE_COMPILER_EMITTED"; 414281687Sjkim break; 415281687Sjkim 416281687Sjkim case NODE_IS_DUPLICATE: 417281687Sjkim 418281687Sjkim FlagName = "NODE_IS_DUPLICATE"; 419281687Sjkim break; 420281687Sjkim 421281687Sjkim case NODE_IS_RESOURCE_DATA: 422281687Sjkim 423281687Sjkim FlagName = "NODE_IS_RESOURCE_DATA"; 424281687Sjkim break; 425281687Sjkim 426281687Sjkim case NODE_IS_NULL_RETURN: 427281687Sjkim 428281687Sjkim FlagName = "NODE_IS_NULL_RETURN"; 429281687Sjkim break; 430281687Sjkim 431281687Sjkim default: 432281687Sjkim break; 433281687Sjkim } 434281687Sjkim 435281687Sjkim if (FlagName) 436281687Sjkim { 437281687Sjkim DbgPrint (ASL_PARSE_OUTPUT, " %s", FlagName); 438281687Sjkim FlagName = NULL; 439281687Sjkim } 440281687Sjkim 441281687Sjkim FlagBit <<= 1; 442118611Snjl } 443118611Snjl} 444118611Snjl 445118611Snjl 446118611Snjl/******************************************************************************* 447118611Snjl * 448118611Snjl * FUNCTION: TrSetNodeFlags 449118611Snjl * 450151937Sjkim * PARAMETERS: Op - An existing parse node 451118611Snjl * Flags - New flags word 452118611Snjl * 453151937Sjkim * RETURN: The updated parser op 454118611Snjl * 455239340Sjkim * DESCRIPTION: Set bits in the node flags word. Will not clear bits, only set 456118611Snjl * 457118611Snjl ******************************************************************************/ 458118611Snjl 459118611SnjlACPI_PARSE_OBJECT * 460118611SnjlTrSetNodeFlags ( 461118611Snjl ACPI_PARSE_OBJECT *Op, 462118611Snjl UINT32 Flags) 463118611Snjl{ 464118611Snjl 465118611Snjl if (!Op) 466118611Snjl { 467241973Sjkim return (NULL); 468118611Snjl } 469118611Snjl 470281687Sjkim DbgPrint (ASL_PARSE_OUTPUT, 471281687Sjkim "\nSetNodeFlags: %s Op %p, %8.8X", Op->Asl.ParseOpName, Op, Flags); 472281687Sjkim 473281687Sjkim TrPrintNodeCompileFlags (Flags); 474281687Sjkim DbgPrint (ASL_PARSE_OUTPUT, "\n\n"); 475281687Sjkim 476118611Snjl Op->Asl.CompileFlags |= Flags; 477239340Sjkim return (Op); 478239340Sjkim} 479118611Snjl 480239340Sjkim 481239340Sjkim/******************************************************************************* 482239340Sjkim * 483239340Sjkim * FUNCTION: TrSetNodeAmlLength 484239340Sjkim * 485239340Sjkim * PARAMETERS: Op - An existing parse node 486239340Sjkim * Length - AML Length 487239340Sjkim * 488239340Sjkim * RETURN: The updated parser op 489239340Sjkim * 490239340Sjkim * DESCRIPTION: Set the AML Length in a node. Used by the parser to indicate 491239340Sjkim * the presence of a node that must be reduced to a fixed length 492239340Sjkim * constant. 493239340Sjkim * 494239340Sjkim ******************************************************************************/ 495239340Sjkim 496239340SjkimACPI_PARSE_OBJECT * 497239340SjkimTrSetNodeAmlLength ( 498239340Sjkim ACPI_PARSE_OBJECT *Op, 499239340Sjkim UINT32 Length) 500239340Sjkim{ 501239340Sjkim 502239340Sjkim DbgPrint (ASL_PARSE_OUTPUT, 503239340Sjkim "\nSetNodeAmlLength: Op %p, %8.8X\n", Op, Length); 504239340Sjkim 505239340Sjkim if (!Op) 506239340Sjkim { 507241973Sjkim return (NULL); 508239340Sjkim } 509239340Sjkim 510239340Sjkim Op->Asl.AmlLength = Length; 511239340Sjkim return (Op); 512118611Snjl} 513118611Snjl 514118611Snjl 515118611Snjl/******************************************************************************* 516118611Snjl * 517118611Snjl * FUNCTION: TrSetEndLineNumber 518118611Snjl * 519118611Snjl * PARAMETERS: Op - An existing parse node 520118611Snjl * 521118611Snjl * RETURN: None. 522118611Snjl * 523118611Snjl * DESCRIPTION: Set the ending line numbers (file line and logical line) of a 524118611Snjl * parse node to the current line numbers. 525118611Snjl * 526118611Snjl ******************************************************************************/ 527118611Snjl 528118611Snjlvoid 529118611SnjlTrSetEndLineNumber ( 530118611Snjl ACPI_PARSE_OBJECT *Op) 531118611Snjl{ 532118611Snjl 533118611Snjl /* If the end line # is already set, just return */ 534118611Snjl 535118611Snjl if (Op->Asl.EndLine) 536118611Snjl { 537118611Snjl return; 538118611Snjl } 539118611Snjl 540306536Sjkim Op->Asl.EndLine = Gbl_CurrentLineNumber; 541118611Snjl Op->Asl.EndLogicalLine = Gbl_LogicalLineNumber; 542118611Snjl} 543118611Snjl 544118611Snjl 545118611Snjl/******************************************************************************* 546118611Snjl * 547281075Sdim * FUNCTION: TrCreateAssignmentNode 548281075Sdim * 549281075Sdim * PARAMETERS: Target - Assignment target 550281075Sdim * Source - Assignment source 551281075Sdim * 552281075Sdim * RETURN: Pointer to the new node. Aborts on allocation failure 553281075Sdim * 554281075Sdim * DESCRIPTION: Implements the C-style '=' operator. It changes the parse 555281075Sdim * tree if possible to utilize the last argument of the math 556281075Sdim * operators which is a target operand -- thus saving invocation 557281075Sdim * of and additional Store() operator. An optimization. 558281075Sdim * 559281075Sdim ******************************************************************************/ 560281075Sdim 561281075SdimACPI_PARSE_OBJECT * 562281075SdimTrCreateAssignmentNode ( 563281075Sdim ACPI_PARSE_OBJECT *Target, 564281075Sdim ACPI_PARSE_OBJECT *Source) 565281075Sdim{ 566281075Sdim ACPI_PARSE_OBJECT *TargetOp; 567281075Sdim ACPI_PARSE_OBJECT *SourceOp1; 568281075Sdim ACPI_PARSE_OBJECT *SourceOp2; 569281075Sdim ACPI_PARSE_OBJECT *Operator; 570281075Sdim 571281075Sdim 572281075Sdim DbgPrint (ASL_PARSE_OUTPUT, 573281075Sdim "\nTrCreateAssignmentNode Line [%u to %u] Source %s Target %s\n", 574281075Sdim Source->Asl.LineNumber, Source->Asl.EndLine, 575281075Sdim UtGetOpName (Source->Asl.ParseOpcode), 576281075Sdim UtGetOpName (Target->Asl.ParseOpcode)); 577281075Sdim 578281075Sdim TrSetNodeFlags (Target, NODE_IS_TARGET); 579281075Sdim 580281075Sdim switch (Source->Asl.ParseOpcode) 581281075Sdim { 582281075Sdim /* 583281075Sdim * Only these operators can be optimized because they have 584281075Sdim * a target operand 585281075Sdim */ 586281075Sdim case PARSEOP_ADD: 587281075Sdim case PARSEOP_AND: 588281075Sdim case PARSEOP_DIVIDE: 589306536Sjkim case PARSEOP_INDEX: 590281075Sdim case PARSEOP_MOD: 591281075Sdim case PARSEOP_MULTIPLY: 592281075Sdim case PARSEOP_NOT: 593281075Sdim case PARSEOP_OR: 594281075Sdim case PARSEOP_SHIFTLEFT: 595281075Sdim case PARSEOP_SHIFTRIGHT: 596281075Sdim case PARSEOP_SUBTRACT: 597281075Sdim case PARSEOP_XOR: 598281075Sdim 599281075Sdim break; 600281075Sdim 601281075Sdim /* Otherwise, just create a normal Store operator */ 602281075Sdim 603281075Sdim default: 604281075Sdim 605281075Sdim goto CannotOptimize; 606281075Sdim } 607281075Sdim 608281075Sdim /* 609281075Sdim * Transform the parse tree such that the target is moved to the 610281075Sdim * last operand of the operator 611281075Sdim */ 612281075Sdim SourceOp1 = Source->Asl.Child; 613281075Sdim SourceOp2 = SourceOp1->Asl.Next; 614281075Sdim 615281075Sdim /* NOT only has one operand, but has a target */ 616281075Sdim 617281075Sdim if (Source->Asl.ParseOpcode == PARSEOP_NOT) 618281075Sdim { 619281075Sdim SourceOp2 = SourceOp1; 620281075Sdim } 621281075Sdim 622281075Sdim /* DIVIDE has an extra target operand (remainder) */ 623281075Sdim 624281075Sdim if (Source->Asl.ParseOpcode == PARSEOP_DIVIDE) 625281075Sdim { 626281075Sdim SourceOp2 = SourceOp2->Asl.Next; 627281075Sdim } 628281075Sdim 629281075Sdim TargetOp = SourceOp2->Asl.Next; 630281075Sdim 631281075Sdim /* 632281075Sdim * Can't perform this optimization if there already is a target 633281075Sdim * for the operator (ZERO is a "no target" placeholder). 634281075Sdim */ 635281075Sdim if (TargetOp->Asl.ParseOpcode != PARSEOP_ZERO) 636281075Sdim { 637281075Sdim goto CannotOptimize; 638281075Sdim } 639281075Sdim 640281075Sdim /* Link in the target as the final operand */ 641281075Sdim 642281075Sdim SourceOp2->Asl.Next = Target; 643281075Sdim Target->Asl.Parent = Source; 644281075Sdim 645281075Sdim return (Source); 646281075Sdim 647281075Sdim 648281075SdimCannotOptimize: 649281075Sdim 650281075Sdim Operator = TrAllocateNode (PARSEOP_STORE); 651281075Sdim TrLinkChildren (Operator, 2, Source, Target); 652281075Sdim 653281075Sdim /* Set the appropriate line numbers for the new node */ 654281075Sdim 655281075Sdim Operator->Asl.LineNumber = Target->Asl.LineNumber; 656281075Sdim Operator->Asl.LogicalLineNumber = Target->Asl.LogicalLineNumber; 657281075Sdim Operator->Asl.LogicalByteOffset = Target->Asl.LogicalByteOffset; 658281075Sdim Operator->Asl.Column = Target->Asl.Column; 659281075Sdim 660281075Sdim return (Operator); 661281075Sdim} 662281075Sdim 663281075Sdim 664281075Sdim/******************************************************************************* 665281075Sdim * 666118611Snjl * FUNCTION: TrCreateLeafNode 667118611Snjl * 668118611Snjl * PARAMETERS: ParseOpcode - New opcode to be assigned to the node 669118611Snjl * 670239340Sjkim * RETURN: Pointer to the new node. Aborts on allocation failure 671118611Snjl * 672118611Snjl * DESCRIPTION: Create a simple leaf node (no children or peers, and no value 673118611Snjl * assigned to the node) 674118611Snjl * 675118611Snjl ******************************************************************************/ 676118611Snjl 677118611SnjlACPI_PARSE_OBJECT * 678118611SnjlTrCreateLeafNode ( 679118611Snjl UINT32 ParseOpcode) 680118611Snjl{ 681118611Snjl ACPI_PARSE_OBJECT *Op; 682118611Snjl 683118611Snjl 684118611Snjl Op = TrAllocateNode (ParseOpcode); 685118611Snjl 686118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 687209746Sjkim "\nCreateLeafNode Ln/Col %u/%u NewNode %p Op %s\n\n", 688281687Sjkim Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName (ParseOpcode)); 689118611Snjl 690241973Sjkim return (Op); 691118611Snjl} 692118611Snjl 693118611Snjl 694118611Snjl/******************************************************************************* 695118611Snjl * 696281687Sjkim * FUNCTION: TrCreateNullTarget 697281687Sjkim * 698281687Sjkim * PARAMETERS: None 699281687Sjkim * 700281687Sjkim * RETURN: Pointer to the new node. Aborts on allocation failure 701281687Sjkim * 702281687Sjkim * DESCRIPTION: Create a "null" target node. This is defined by the ACPI 703281687Sjkim * specification to be a zero AML opcode, and indicates that 704281687Sjkim * no target has been specified for the parent operation 705281687Sjkim * 706281687Sjkim ******************************************************************************/ 707281687Sjkim 708281687SjkimACPI_PARSE_OBJECT * 709281687SjkimTrCreateNullTarget ( 710281687Sjkim void) 711281687Sjkim{ 712281687Sjkim ACPI_PARSE_OBJECT *Op; 713281687Sjkim 714281687Sjkim 715281687Sjkim Op = TrAllocateNode (PARSEOP_ZERO); 716281687Sjkim Op->Asl.CompileFlags |= (NODE_IS_TARGET | NODE_COMPILE_TIME_CONST); 717281687Sjkim 718281687Sjkim DbgPrint (ASL_PARSE_OUTPUT, 719281687Sjkim "\nCreateNullTarget Ln/Col %u/%u NewNode %p Op %s\n", 720281687Sjkim Op->Asl.LineNumber, Op->Asl.Column, Op, 721281687Sjkim UtGetOpName (Op->Asl.ParseOpcode)); 722281687Sjkim 723281687Sjkim return (Op); 724281687Sjkim} 725281687Sjkim 726281687Sjkim 727281687Sjkim/******************************************************************************* 728281687Sjkim * 729218590Sjkim * FUNCTION: TrCreateConstantLeafNode 730218590Sjkim * 731218590Sjkim * PARAMETERS: ParseOpcode - The constant opcode 732218590Sjkim * 733239340Sjkim * RETURN: Pointer to the new node. Aborts on allocation failure 734218590Sjkim * 735218590Sjkim * DESCRIPTION: Create a leaf node (no children or peers) for one of the 736218590Sjkim * special constants - __LINE__, __FILE__, and __DATE__. 737218590Sjkim * 738218590Sjkim * Note: An implemenation of __FUNC__ cannot happen here because we don't 739218590Sjkim * have a full parse tree at this time and cannot find the parent control 740218590Sjkim * method. If it is ever needed, __FUNC__ must be implemented later, after 741218590Sjkim * the parse tree has been fully constructed. 742218590Sjkim * 743218590Sjkim ******************************************************************************/ 744218590Sjkim 745218590SjkimACPI_PARSE_OBJECT * 746218590SjkimTrCreateConstantLeafNode ( 747218590Sjkim UINT32 ParseOpcode) 748218590Sjkim{ 749218590Sjkim ACPI_PARSE_OBJECT *Op = NULL; 750218590Sjkim time_t CurrentTime; 751218590Sjkim char *StaticTimeString; 752218590Sjkim char *TimeString; 753228110Sjkim char *Filename; 754218590Sjkim 755218590Sjkim 756218590Sjkim switch (ParseOpcode) 757218590Sjkim { 758218590Sjkim case PARSEOP___LINE__: 759250838Sjkim 760218590Sjkim Op = TrAllocateNode (PARSEOP_INTEGER); 761218590Sjkim Op->Asl.Value.Integer = Op->Asl.LineNumber; 762218590Sjkim break; 763218590Sjkim 764228110Sjkim case PARSEOP___PATH__: 765250838Sjkim 766218590Sjkim Op = TrAllocateNode (PARSEOP_STRING_LITERAL); 767218590Sjkim 768218590Sjkim /* Op.Asl.Filename contains the full pathname to the file */ 769218590Sjkim 770218590Sjkim Op->Asl.Value.String = Op->Asl.Filename; 771218590Sjkim break; 772218590Sjkim 773228110Sjkim case PARSEOP___FILE__: 774250838Sjkim 775218590Sjkim Op = TrAllocateNode (PARSEOP_STRING_LITERAL); 776218590Sjkim 777228110Sjkim /* Get the simple filename from the full path */ 778228110Sjkim 779281687Sjkim FlSplitInputPathname (Op->Asl.Filename, NULL, &Filename); 780228110Sjkim Op->Asl.Value.String = Filename; 781228110Sjkim break; 782228110Sjkim 783228110Sjkim case PARSEOP___DATE__: 784250838Sjkim 785228110Sjkim Op = TrAllocateNode (PARSEOP_STRING_LITERAL); 786228110Sjkim 787218590Sjkim /* Get a copy of the current time */ 788218590Sjkim 789218590Sjkim CurrentTime = time (NULL); 790218590Sjkim StaticTimeString = ctime (&CurrentTime); 791218590Sjkim TimeString = UtLocalCalloc (strlen (StaticTimeString) + 1); 792218590Sjkim strcpy (TimeString, StaticTimeString); 793218590Sjkim 794218590Sjkim TimeString[strlen(TimeString) -1] = 0; /* Remove trailing newline */ 795218590Sjkim Op->Asl.Value.String = TimeString; 796218590Sjkim break; 797218590Sjkim 798218590Sjkim default: /* This would be an internal error */ 799250838Sjkim 800218590Sjkim return (NULL); 801218590Sjkim } 802218590Sjkim 803218590Sjkim DbgPrint (ASL_PARSE_OUTPUT, 804306536Sjkim "\nCreateConstantLeafNode Ln/Col %u/%u NewNode %p " 805306536Sjkim "Op %s Value %8.8X%8.8X \n", 806218590Sjkim Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName (ParseOpcode), 807218590Sjkim ACPI_FORMAT_UINT64 (Op->Asl.Value.Integer)); 808218590Sjkim return (Op); 809218590Sjkim} 810218590Sjkim 811218590Sjkim 812218590Sjkim/******************************************************************************* 813218590Sjkim * 814281075Sdim * FUNCTION: TrCreateTargetOperand 815281075Sdim * 816281075Sdim * PARAMETERS: OriginalOp - Op to be copied 817281075Sdim * 818281075Sdim * RETURN: Pointer to the new node. Aborts on allocation failure 819281075Sdim * 820281075Sdim * DESCRIPTION: Copy an existing node (and subtree). Used in ASL+ (C-style) 821281075Sdim * expressions where the target is the same as one of the 822281075Sdim * operands. A new node and subtree must be created from the 823281075Sdim * original so that the parse tree can be linked properly. 824281075Sdim * 825281075Sdim * NOTE: This code is specific to target operands that are the last 826281075Sdim * operand in an ASL/AML operator. Meaning that the top-level 827281075Sdim * parse Op in a possible subtree has a NULL Next pointer. 828281075Sdim * This simplifies the recursion. 829281075Sdim * 830281075Sdim * Subtree example: 831281075Sdim * DeRefOf (Local1) += 32 832281075Sdim * 833281075Sdim * This gets converted to: 834281075Sdim * Add (DeRefOf (Local1), 32, DeRefOf (Local1)) 835281075Sdim * 836281075Sdim * Each DeRefOf has a single child, Local1. Even more complex 837281075Sdim * subtrees can be created via the Index and DeRefOf operators. 838281075Sdim * 839281075Sdim ******************************************************************************/ 840281075Sdim 841281075SdimACPI_PARSE_OBJECT * 842281075SdimTrCreateTargetOperand ( 843281075Sdim ACPI_PARSE_OBJECT *OriginalOp, 844281075Sdim ACPI_PARSE_OBJECT *ParentOp) 845281075Sdim{ 846281075Sdim ACPI_PARSE_OBJECT *Op; 847281075Sdim 848281075Sdim 849281075Sdim if (!OriginalOp) 850281075Sdim { 851281075Sdim return (NULL); 852281075Sdim } 853281075Sdim 854281075Sdim Op = TrGetNextNode (); 855281075Sdim 856281075Sdim /* Copy the pertinent values (omit link pointer fields) */ 857281075Sdim 858281075Sdim Op->Asl.Value = OriginalOp->Asl.Value; 859281075Sdim Op->Asl.Filename = OriginalOp->Asl.Filename; 860281075Sdim Op->Asl.LineNumber = OriginalOp->Asl.LineNumber; 861281075Sdim Op->Asl.LogicalLineNumber = OriginalOp->Asl.LogicalLineNumber; 862281075Sdim Op->Asl.LogicalByteOffset = OriginalOp->Asl.LogicalByteOffset; 863281075Sdim Op->Asl.Column = OriginalOp->Asl.Column; 864281075Sdim Op->Asl.Flags = OriginalOp->Asl.Flags; 865281075Sdim Op->Asl.CompileFlags = OriginalOp->Asl.CompileFlags; 866281075Sdim Op->Asl.AmlOpcode = OriginalOp->Asl.AmlOpcode; 867281075Sdim Op->Asl.ParseOpcode = OriginalOp->Asl.ParseOpcode; 868281075Sdim Op->Asl.Parent = ParentOp; 869281075Sdim UtSetParseOpName (Op); 870281075Sdim 871281075Sdim /* Copy a possible subtree below this node */ 872281075Sdim 873281075Sdim if (OriginalOp->Asl.Child) 874281075Sdim { 875281075Sdim Op->Asl.Child = TrCreateTargetOperand (OriginalOp->Asl.Child, Op); 876281075Sdim } 877281075Sdim 878281075Sdim if (OriginalOp->Asl.Next) /* Null for top-level node */ 879281075Sdim { 880281075Sdim Op->Asl.Next = TrCreateTargetOperand (OriginalOp->Asl.Next, ParentOp); 881281075Sdim } 882281075Sdim 883281075Sdim return (Op); 884281075Sdim} 885281075Sdim 886281075Sdim 887281075Sdim/******************************************************************************* 888281075Sdim * 889118611Snjl * FUNCTION: TrCreateValuedLeafNode 890118611Snjl * 891118611Snjl * PARAMETERS: ParseOpcode - New opcode to be assigned to the node 892118611Snjl * Value - Value to be assigned to the node 893118611Snjl * 894239340Sjkim * RETURN: Pointer to the new node. Aborts on allocation failure 895118611Snjl * 896118611Snjl * DESCRIPTION: Create a leaf node (no children or peers) with a value 897118611Snjl * assigned to it 898118611Snjl * 899118611Snjl ******************************************************************************/ 900118611Snjl 901118611SnjlACPI_PARSE_OBJECT * 902118611SnjlTrCreateValuedLeafNode ( 903118611Snjl UINT32 ParseOpcode, 904202771Sjkim UINT64 Value) 905118611Snjl{ 906118611Snjl ACPI_PARSE_OBJECT *Op; 907118611Snjl 908118611Snjl 909118611Snjl Op = TrAllocateNode (ParseOpcode); 910118611Snjl 911118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 912306536Sjkim "\nCreateValuedLeafNode Ln/Col %u/%u NewNode %p " 913306536Sjkim "Op %s Value %8.8X%8.8X ", 914167802Sjkim Op->Asl.LineNumber, Op->Asl.Column, Op, UtGetOpName(ParseOpcode), 915123315Snjl ACPI_FORMAT_UINT64 (Value)); 916118611Snjl Op->Asl.Value.Integer = Value; 917118611Snjl 918118611Snjl switch (ParseOpcode) 919118611Snjl { 920118611Snjl case PARSEOP_STRING_LITERAL: 921250838Sjkim 922118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "STRING->%s", Value); 923118611Snjl break; 924118611Snjl 925118611Snjl case PARSEOP_NAMESEG: 926250838Sjkim 927118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "NAMESEG->%s", Value); 928118611Snjl break; 929118611Snjl 930118611Snjl case PARSEOP_NAMESTRING: 931250838Sjkim 932118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "NAMESTRING->%s", Value); 933118611Snjl break; 934118611Snjl 935118611Snjl case PARSEOP_EISAID: 936250838Sjkim 937118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "EISAID->%s", Value); 938118611Snjl break; 939118611Snjl 940118611Snjl case PARSEOP_METHOD: 941250838Sjkim 942118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "METHOD"); 943118611Snjl break; 944118611Snjl 945118611Snjl case PARSEOP_INTEGER: 946250838Sjkim 947281687Sjkim DbgPrint (ASL_PARSE_OUTPUT, "INTEGER->%8.8X%8.8X", 948281687Sjkim ACPI_FORMAT_UINT64 (Value)); 949118611Snjl break; 950118611Snjl 951118611Snjl default: 952250838Sjkim 953118611Snjl break; 954118611Snjl } 955118611Snjl 956118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "\n\n"); 957241973Sjkim return (Op); 958118611Snjl} 959118611Snjl 960118611Snjl 961118611Snjl/******************************************************************************* 962118611Snjl * 963118611Snjl * FUNCTION: TrCreateNode 964118611Snjl * 965118611Snjl * PARAMETERS: ParseOpcode - Opcode to be assigned to the node 966118611Snjl * NumChildren - Number of children to follow 967118611Snjl * ... - A list of child nodes to link to the new 968239340Sjkim * node. NumChildren long. 969118611Snjl * 970239340Sjkim * RETURN: Pointer to the new node. Aborts on allocation failure 971118611Snjl * 972118611Snjl * DESCRIPTION: Create a new parse node and link together a list of child 973118611Snjl * nodes underneath the new node. 974118611Snjl * 975118611Snjl ******************************************************************************/ 976118611Snjl 977118611SnjlACPI_PARSE_OBJECT * 978118611SnjlTrCreateNode ( 979118611Snjl UINT32 ParseOpcode, 980118611Snjl UINT32 NumChildren, 981118611Snjl ...) 982118611Snjl{ 983118611Snjl ACPI_PARSE_OBJECT *Op; 984118611Snjl ACPI_PARSE_OBJECT *Child; 985118611Snjl ACPI_PARSE_OBJECT *PrevChild; 986118611Snjl va_list ap; 987118611Snjl UINT32 i; 988118611Snjl BOOLEAN FirstChild; 989118611Snjl 990118611Snjl 991118611Snjl va_start (ap, NumChildren); 992118611Snjl 993118611Snjl /* Allocate one new node */ 994118611Snjl 995118611Snjl Op = TrAllocateNode (ParseOpcode); 996118611Snjl 997118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 998209746Sjkim "\nCreateNode Ln/Col %u/%u NewParent %p Child %u Op %s ", 999306536Sjkim Op->Asl.LineNumber, Op->Asl.Column, Op, 1000306536Sjkim NumChildren, UtGetOpName(ParseOpcode)); 1001118611Snjl 1002118611Snjl /* Some extra debug output based on the parse opcode */ 1003118611Snjl 1004118611Snjl switch (ParseOpcode) 1005118611Snjl { 1006306536Sjkim case PARSEOP_ASL_CODE: 1007250838Sjkim 1008306536Sjkim Gbl_ParseTreeRoot = Op; 1009306536Sjkim Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 1010306536Sjkim DbgPrint (ASL_PARSE_OUTPUT, "ASLCODE (Tree Completed)->"); 1011306536Sjkim break; 1012306536Sjkim 1013306536Sjkim case PARSEOP_DEFINITION_BLOCK: 1014306536Sjkim 1015118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->"); 1016118611Snjl break; 1017118611Snjl 1018118611Snjl case PARSEOP_OPERATIONREGION: 1019250838Sjkim 1020118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->"); 1021118611Snjl break; 1022118611Snjl 1023118611Snjl case PARSEOP_OR: 1024250838Sjkim 1025118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "OR->"); 1026118611Snjl break; 1027118611Snjl 1028118611Snjl default: 1029250838Sjkim 1030118611Snjl /* Nothing to do for other opcodes */ 1031250838Sjkim 1032118611Snjl break; 1033118611Snjl } 1034118611Snjl 1035118611Snjl /* Link the new node to its children */ 1036118611Snjl 1037118611Snjl PrevChild = NULL; 1038118611Snjl FirstChild = TRUE; 1039118611Snjl for (i = 0; i < NumChildren; i++) 1040118611Snjl { 1041118611Snjl /* Get the next child */ 1042118611Snjl 1043118611Snjl Child = va_arg (ap, ACPI_PARSE_OBJECT *); 1044118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child); 1045118611Snjl 1046118611Snjl /* 1047118611Snjl * If child is NULL, this means that an optional argument 1048239340Sjkim * was omitted. We must create a placeholder with a special 1049118611Snjl * opcode (DEFAULT_ARG) so that the code generator will know 1050118611Snjl * that it must emit the correct default for this argument 1051118611Snjl */ 1052118611Snjl if (!Child) 1053118611Snjl { 1054118611Snjl Child = TrAllocateNode (PARSEOP_DEFAULT_ARG); 1055118611Snjl } 1056118611Snjl 1057118611Snjl /* Link first child to parent */ 1058118611Snjl 1059118611Snjl if (FirstChild) 1060118611Snjl { 1061118611Snjl FirstChild = FALSE; 1062118611Snjl Op->Asl.Child = Child; 1063118611Snjl } 1064118611Snjl 1065118611Snjl /* Point all children to parent */ 1066118611Snjl 1067118611Snjl Child->Asl.Parent = Op; 1068118611Snjl 1069118611Snjl /* Link children in a peer list */ 1070118611Snjl 1071118611Snjl if (PrevChild) 1072118611Snjl { 1073118611Snjl PrevChild->Asl.Next = Child; 1074118611Snjl }; 1075118611Snjl 1076118611Snjl /* 1077118611Snjl * This child might be a list, point all nodes in the list 1078118611Snjl * to the same parent 1079118611Snjl */ 1080118611Snjl while (Child->Asl.Next) 1081118611Snjl { 1082118611Snjl Child = Child->Asl.Next; 1083118611Snjl Child->Asl.Parent = Op; 1084118611Snjl } 1085118611Snjl 1086118611Snjl PrevChild = Child; 1087118611Snjl } 1088118611Snjl va_end(ap); 1089118611Snjl 1090281687Sjkim DbgPrint (ASL_PARSE_OUTPUT, "\n"); 1091241973Sjkim return (Op); 1092118611Snjl} 1093118611Snjl 1094118611Snjl 1095118611Snjl/******************************************************************************* 1096118611Snjl * 1097118611Snjl * FUNCTION: TrLinkChildren 1098118611Snjl * 1099118611Snjl * PARAMETERS: Op - An existing parse node 1100118611Snjl * NumChildren - Number of children to follow 1101118611Snjl * ... - A list of child nodes to link to the new 1102239340Sjkim * node. NumChildren long. 1103118611Snjl * 1104118611Snjl * RETURN: The updated (linked) node 1105118611Snjl * 1106118611Snjl * DESCRIPTION: Link a group of nodes to an existing parse node 1107118611Snjl * 1108118611Snjl ******************************************************************************/ 1109118611Snjl 1110118611SnjlACPI_PARSE_OBJECT * 1111118611SnjlTrLinkChildren ( 1112118611Snjl ACPI_PARSE_OBJECT *Op, 1113118611Snjl UINT32 NumChildren, 1114118611Snjl ...) 1115118611Snjl{ 1116118611Snjl ACPI_PARSE_OBJECT *Child; 1117118611Snjl ACPI_PARSE_OBJECT *PrevChild; 1118118611Snjl va_list ap; 1119118611Snjl UINT32 i; 1120118611Snjl BOOLEAN FirstChild; 1121118611Snjl 1122118611Snjl 1123118611Snjl va_start (ap, NumChildren); 1124118611Snjl 1125118611Snjl 1126118611Snjl TrSetEndLineNumber (Op); 1127118611Snjl 1128118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 1129209746Sjkim "\nLinkChildren Line [%u to %u] NewParent %p Child %u Op %s ", 1130118611Snjl Op->Asl.LineNumber, Op->Asl.EndLine, 1131118611Snjl Op, NumChildren, UtGetOpName(Op->Asl.ParseOpcode)); 1132118611Snjl 1133118611Snjl switch (Op->Asl.ParseOpcode) 1134118611Snjl { 1135306536Sjkim case PARSEOP_ASL_CODE: 1136250838Sjkim 1137306536Sjkim Gbl_ParseTreeRoot = Op; 1138306536Sjkim Op->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 1139306536Sjkim DbgPrint (ASL_PARSE_OUTPUT, "ASLCODE (Tree Completed)->"); 1140306536Sjkim break; 1141306536Sjkim 1142306536Sjkim case PARSEOP_DEFINITION_BLOCK: 1143306536Sjkim 1144118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "DEFINITION_BLOCK (Tree Completed)->"); 1145118611Snjl break; 1146118611Snjl 1147118611Snjl case PARSEOP_OPERATIONREGION: 1148250838Sjkim 1149118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "OPREGION->"); 1150118611Snjl break; 1151118611Snjl 1152118611Snjl case PARSEOP_OR: 1153250838Sjkim 1154118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "OR->"); 1155118611Snjl break; 1156118611Snjl 1157118611Snjl default: 1158250838Sjkim 1159118611Snjl /* Nothing to do for other opcodes */ 1160250838Sjkim 1161118611Snjl break; 1162118611Snjl } 1163118611Snjl 1164118611Snjl /* Link the new node to it's children */ 1165118611Snjl 1166118611Snjl PrevChild = NULL; 1167118611Snjl FirstChild = TRUE; 1168118611Snjl for (i = 0; i < NumChildren; i++) 1169118611Snjl { 1170118611Snjl Child = va_arg (ap, ACPI_PARSE_OBJECT *); 1171118611Snjl 1172118611Snjl if ((Child == PrevChild) && (Child != NULL)) 1173118611Snjl { 1174151937Sjkim AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Child, 1175151937Sjkim "Child node list invalid"); 1176252279Sjkim va_end(ap); 1177241973Sjkim return (Op); 1178118611Snjl } 1179118611Snjl 1180118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "%p, ", Child); 1181118611Snjl 1182118611Snjl /* 1183118611Snjl * If child is NULL, this means that an optional argument 1184239340Sjkim * was omitted. We must create a placeholder with a special 1185118611Snjl * opcode (DEFAULT_ARG) so that the code generator will know 1186118611Snjl * that it must emit the correct default for this argument 1187118611Snjl */ 1188118611Snjl if (!Child) 1189118611Snjl { 1190118611Snjl Child = TrAllocateNode (PARSEOP_DEFAULT_ARG); 1191118611Snjl } 1192118611Snjl 1193118611Snjl /* Link first child to parent */ 1194118611Snjl 1195118611Snjl if (FirstChild) 1196118611Snjl { 1197118611Snjl FirstChild = FALSE; 1198118611Snjl Op->Asl.Child = Child; 1199118611Snjl } 1200118611Snjl 1201118611Snjl /* Point all children to parent */ 1202118611Snjl 1203118611Snjl Child->Asl.Parent = Op; 1204118611Snjl 1205118611Snjl /* Link children in a peer list */ 1206118611Snjl 1207118611Snjl if (PrevChild) 1208118611Snjl { 1209118611Snjl PrevChild->Asl.Next = Child; 1210118611Snjl }; 1211118611Snjl 1212118611Snjl /* 1213118611Snjl * This child might be a list, point all nodes in the list 1214118611Snjl * to the same parent 1215118611Snjl */ 1216118611Snjl while (Child->Asl.Next) 1217118611Snjl { 1218118611Snjl Child = Child->Asl.Next; 1219118611Snjl Child->Asl.Parent = Op; 1220118611Snjl } 1221306536Sjkim 1222118611Snjl PrevChild = Child; 1223118611Snjl } 1224252279Sjkim 1225118611Snjl va_end(ap); 1226118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "\n\n"); 1227241973Sjkim return (Op); 1228118611Snjl} 1229118611Snjl 1230118611Snjl 1231118611Snjl/******************************************************************************* 1232118611Snjl * 1233118611Snjl * FUNCTION: TrLinkPeerNode 1234118611Snjl * 1235118611Snjl * PARAMETERS: Op1 - First peer 1236118611Snjl * Op2 - Second peer 1237118611Snjl * 1238118611Snjl * RETURN: Op1 or the non-null node. 1239118611Snjl * 1240239340Sjkim * DESCRIPTION: Link two nodes as peers. Handles cases where one peer is null. 1241118611Snjl * 1242118611Snjl ******************************************************************************/ 1243118611Snjl 1244118611SnjlACPI_PARSE_OBJECT * 1245118611SnjlTrLinkPeerNode ( 1246118611Snjl ACPI_PARSE_OBJECT *Op1, 1247118611Snjl ACPI_PARSE_OBJECT *Op2) 1248118611Snjl{ 1249118611Snjl ACPI_PARSE_OBJECT *Next; 1250118611Snjl 1251118611Snjl 1252118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 1253281687Sjkim "\nLinkPeerNode: 1=%p (%s), 2=%p (%s)\n", 1254118611Snjl Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode) : NULL, 1255118611Snjl Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode) : NULL); 1256118611Snjl 1257118611Snjl 1258118611Snjl if ((!Op1) && (!Op2)) 1259118611Snjl { 1260118611Snjl DbgPrint (ASL_PARSE_OUTPUT, "\nTwo Null nodes!\n"); 1261241973Sjkim return (Op1); 1262118611Snjl } 1263118611Snjl 1264118611Snjl /* If one of the nodes is null, just return the non-null node */ 1265118611Snjl 1266118611Snjl if (!Op2) 1267118611Snjl { 1268241973Sjkim return (Op1); 1269118611Snjl } 1270118611Snjl 1271118611Snjl if (!Op1) 1272118611Snjl { 1273241973Sjkim return (Op2); 1274118611Snjl } 1275118611Snjl 1276118611Snjl if (Op1 == Op2) 1277118611Snjl { 1278118611Snjl DbgPrint (ASL_DEBUG_OUTPUT, 1279281687Sjkim "\n************* Internal error, linking node to itself %p\n", 1280151937Sjkim Op1); 1281151937Sjkim AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op1, 1282151937Sjkim "Linking node to itself"); 1283241973Sjkim return (Op1); 1284118611Snjl } 1285118611Snjl 1286118611Snjl Op1->Asl.Parent = Op2->Asl.Parent; 1287118611Snjl 1288118611Snjl /* 1289118611Snjl * Op 1 may already have a peer list (such as an IF/ELSE pair), 1290118611Snjl * so we must walk to the end of the list and attach the new 1291118611Snjl * peer at the end 1292118611Snjl */ 1293118611Snjl Next = Op1; 1294118611Snjl while (Next->Asl.Next) 1295118611Snjl { 1296118611Snjl Next = Next->Asl.Next; 1297118611Snjl } 1298118611Snjl 1299118611Snjl Next->Asl.Next = Op2; 1300241973Sjkim return (Op1); 1301118611Snjl} 1302118611Snjl 1303118611Snjl 1304118611Snjl/******************************************************************************* 1305118611Snjl * 1306118611Snjl * FUNCTION: TrLinkPeerNodes 1307118611Snjl * 1308118611Snjl * PARAMETERS: NumPeers - The number of nodes in the list to follow 1309118611Snjl * ... - A list of nodes to link together as peers 1310118611Snjl * 1311118611Snjl * RETURN: The first node in the list (head of the peer list) 1312118611Snjl * 1313118611Snjl * DESCRIPTION: Link together an arbitrary number of peer nodes. 1314118611Snjl * 1315118611Snjl ******************************************************************************/ 1316118611Snjl 1317118611SnjlACPI_PARSE_OBJECT * 1318118611SnjlTrLinkPeerNodes ( 1319118611Snjl UINT32 NumPeers, 1320118611Snjl ...) 1321118611Snjl{ 1322118611Snjl ACPI_PARSE_OBJECT *This; 1323118611Snjl ACPI_PARSE_OBJECT *Next; 1324118611Snjl va_list ap; 1325118611Snjl UINT32 i; 1326118611Snjl ACPI_PARSE_OBJECT *Start; 1327118611Snjl 1328118611Snjl 1329118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 1330209746Sjkim "\nLinkPeerNodes: (%u) ", NumPeers); 1331118611Snjl 1332118611Snjl va_start (ap, NumPeers); 1333118611Snjl This = va_arg (ap, ACPI_PARSE_OBJECT *); 1334118611Snjl Start = This; 1335118611Snjl 1336118611Snjl /* 1337118611Snjl * Link all peers 1338118611Snjl */ 1339118611Snjl for (i = 0; i < (NumPeers -1); i++) 1340118611Snjl { 1341209746Sjkim DbgPrint (ASL_PARSE_OUTPUT, "%u=%p ", (i+1), This); 1342118611Snjl 1343118611Snjl while (This->Asl.Next) 1344118611Snjl { 1345118611Snjl This = This->Asl.Next; 1346118611Snjl } 1347118611Snjl 1348118611Snjl /* Get another peer node */ 1349118611Snjl 1350118611Snjl Next = va_arg (ap, ACPI_PARSE_OBJECT *); 1351118611Snjl if (!Next) 1352118611Snjl { 1353118611Snjl Next = TrAllocateNode (PARSEOP_DEFAULT_ARG); 1354118611Snjl } 1355118611Snjl 1356118611Snjl /* link new node to the current node */ 1357118611Snjl 1358118611Snjl This->Asl.Next = Next; 1359118611Snjl This = Next; 1360118611Snjl } 1361193529Sjkim va_end (ap); 1362118611Snjl 1363281687Sjkim DbgPrint (ASL_PARSE_OUTPUT,"\n"); 1364118611Snjl return (Start); 1365118611Snjl} 1366118611Snjl 1367118611Snjl 1368118611Snjl/******************************************************************************* 1369118611Snjl * 1370118611Snjl * FUNCTION: TrLinkChildNode 1371118611Snjl * 1372118611Snjl * PARAMETERS: Op1 - Parent node 1373118611Snjl * Op2 - Op to become a child 1374118611Snjl * 1375118611Snjl * RETURN: The parent node 1376118611Snjl * 1377118611Snjl * DESCRIPTION: Link two nodes together as a parent and child 1378118611Snjl * 1379118611Snjl ******************************************************************************/ 1380118611Snjl 1381118611SnjlACPI_PARSE_OBJECT * 1382118611SnjlTrLinkChildNode ( 1383118611Snjl ACPI_PARSE_OBJECT *Op1, 1384118611Snjl ACPI_PARSE_OBJECT *Op2) 1385118611Snjl{ 1386118611Snjl ACPI_PARSE_OBJECT *Next; 1387118611Snjl 1388118611Snjl 1389118611Snjl DbgPrint (ASL_PARSE_OUTPUT, 1390281687Sjkim "\nLinkChildNode: Parent=%p (%s), Child=%p (%s)\n", 1391118611Snjl Op1, Op1 ? UtGetOpName(Op1->Asl.ParseOpcode): NULL, 1392118611Snjl Op2, Op2 ? UtGetOpName(Op2->Asl.ParseOpcode): NULL); 1393118611Snjl 1394118611Snjl if (!Op1 || !Op2) 1395118611Snjl { 1396241973Sjkim return (Op1); 1397118611Snjl } 1398118611Snjl 1399118611Snjl Op1->Asl.Child = Op2; 1400118611Snjl 1401118611Snjl /* Set the child and all peers of the child to point to the parent */ 1402118611Snjl 1403118611Snjl Next = Op2; 1404118611Snjl while (Next) 1405118611Snjl { 1406118611Snjl Next->Asl.Parent = Op1; 1407118611Snjl Next = Next->Asl.Next; 1408118611Snjl } 1409118611Snjl 1410241973Sjkim return (Op1); 1411118611Snjl} 1412118611Snjl 1413118611Snjl 1414118611Snjl/******************************************************************************* 1415118611Snjl * 1416118611Snjl * FUNCTION: TrWalkParseTree 1417118611Snjl * 1418118611Snjl * PARAMETERS: Visitation - Type of walk 1419118611Snjl * DescendingCallback - Called during tree descent 1420118611Snjl * AscendingCallback - Called during tree ascent 1421118611Snjl * Context - To be passed to the callbacks 1422118611Snjl * 1423118611Snjl * RETURN: Status from callback(s) 1424118611Snjl * 1425118611Snjl * DESCRIPTION: Walk the entire parse tree. 1426118611Snjl * 1427118611Snjl ******************************************************************************/ 1428118611Snjl 1429118611SnjlACPI_STATUS 1430118611SnjlTrWalkParseTree ( 1431118611Snjl ACPI_PARSE_OBJECT *Op, 1432118611Snjl UINT32 Visitation, 1433118611Snjl ASL_WALK_CALLBACK DescendingCallback, 1434118611Snjl ASL_WALK_CALLBACK AscendingCallback, 1435118611Snjl void *Context) 1436118611Snjl{ 1437118611Snjl UINT32 Level; 1438118611Snjl BOOLEAN NodePreviouslyVisited; 1439118611Snjl ACPI_PARSE_OBJECT *StartOp = Op; 1440118611Snjl ACPI_STATUS Status; 1441118611Snjl 1442118611Snjl 1443306536Sjkim if (!Gbl_ParseTreeRoot) 1444118611Snjl { 1445118611Snjl return (AE_OK); 1446118611Snjl } 1447118611Snjl 1448118611Snjl Level = 0; 1449118611Snjl NodePreviouslyVisited = FALSE; 1450118611Snjl 1451118611Snjl switch (Visitation) 1452118611Snjl { 1453118611Snjl case ASL_WALK_VISIT_DOWNWARD: 1454118611Snjl 1455118611Snjl while (Op) 1456118611Snjl { 1457118611Snjl if (!NodePreviouslyVisited) 1458118611Snjl { 1459151937Sjkim /* Let the callback process the node. */ 1460151937Sjkim 1461118611Snjl Status = DescendingCallback (Op, Level, Context); 1462118611Snjl if (ACPI_SUCCESS (Status)) 1463118611Snjl { 1464118611Snjl /* Visit children first, once */ 1465118611Snjl 1466118611Snjl if (Op->Asl.Child) 1467118611Snjl { 1468118611Snjl Level++; 1469118611Snjl Op = Op->Asl.Child; 1470118611Snjl continue; 1471118611Snjl } 1472118611Snjl } 1473118611Snjl else if (Status != AE_CTRL_DEPTH) 1474118611Snjl { 1475118611Snjl /* Exit immediately on any error */ 1476118611Snjl 1477118611Snjl return (Status); 1478118611Snjl } 1479118611Snjl } 1480118611Snjl 1481118611Snjl /* Terminate walk at start op */ 1482118611Snjl 1483118611Snjl if (Op == StartOp) 1484118611Snjl { 1485118611Snjl break; 1486118611Snjl } 1487118611Snjl 1488118611Snjl /* No more children, visit peers */ 1489118611Snjl 1490118611Snjl if (Op->Asl.Next) 1491118611Snjl { 1492118611Snjl Op = Op->Asl.Next; 1493118611Snjl NodePreviouslyVisited = FALSE; 1494118611Snjl } 1495118611Snjl else 1496118611Snjl { 1497118611Snjl /* No children or peers, re-visit parent */ 1498118611Snjl 1499118611Snjl if (Level != 0 ) 1500118611Snjl { 1501118611Snjl Level--; 1502118611Snjl } 1503118611Snjl Op = Op->Asl.Parent; 1504118611Snjl NodePreviouslyVisited = TRUE; 1505118611Snjl } 1506118611Snjl } 1507118611Snjl break; 1508118611Snjl 1509118611Snjl case ASL_WALK_VISIT_UPWARD: 1510118611Snjl 1511118611Snjl while (Op) 1512118611Snjl { 1513118611Snjl /* Visit leaf node (no children) or parent node on return trip */ 1514118611Snjl 1515118611Snjl if ((!Op->Asl.Child) || 1516118611Snjl (NodePreviouslyVisited)) 1517118611Snjl { 1518151937Sjkim /* Let the callback process the node. */ 1519151937Sjkim 1520118611Snjl Status = AscendingCallback (Op, Level, Context); 1521118611Snjl if (ACPI_FAILURE (Status)) 1522118611Snjl { 1523118611Snjl return (Status); 1524118611Snjl } 1525118611Snjl } 1526118611Snjl else 1527118611Snjl { 1528118611Snjl /* Visit children first, once */ 1529118611Snjl 1530118611Snjl Level++; 1531118611Snjl Op = Op->Asl.Child; 1532118611Snjl continue; 1533118611Snjl } 1534118611Snjl 1535118611Snjl /* Terminate walk at start op */ 1536118611Snjl 1537118611Snjl if (Op == StartOp) 1538118611Snjl { 1539118611Snjl break; 1540118611Snjl } 1541118611Snjl 1542118611Snjl /* No more children, visit peers */ 1543118611Snjl 1544118611Snjl if (Op->Asl.Next) 1545118611Snjl { 1546118611Snjl Op = Op->Asl.Next; 1547118611Snjl NodePreviouslyVisited = FALSE; 1548118611Snjl } 1549118611Snjl else 1550118611Snjl { 1551118611Snjl /* No children or peers, re-visit parent */ 1552118611Snjl 1553118611Snjl if (Level != 0 ) 1554118611Snjl { 1555118611Snjl Level--; 1556118611Snjl } 1557118611Snjl Op = Op->Asl.Parent; 1558118611Snjl NodePreviouslyVisited = TRUE; 1559118611Snjl } 1560118611Snjl } 1561118611Snjl break; 1562118611Snjl 1563118611Snjl case ASL_WALK_VISIT_TWICE: 1564118611Snjl 1565118611Snjl while (Op) 1566118611Snjl { 1567118611Snjl if (NodePreviouslyVisited) 1568118611Snjl { 1569118611Snjl Status = AscendingCallback (Op, Level, Context); 1570118611Snjl if (ACPI_FAILURE (Status)) 1571118611Snjl { 1572118611Snjl return (Status); 1573118611Snjl } 1574118611Snjl } 1575118611Snjl else 1576118611Snjl { 1577151937Sjkim /* Let the callback process the node. */ 1578151937Sjkim 1579118611Snjl Status = DescendingCallback (Op, Level, Context); 1580118611Snjl if (ACPI_SUCCESS (Status)) 1581118611Snjl { 1582118611Snjl /* Visit children first, once */ 1583118611Snjl 1584118611Snjl if (Op->Asl.Child) 1585118611Snjl { 1586118611Snjl Level++; 1587118611Snjl Op = Op->Asl.Child; 1588118611Snjl continue; 1589118611Snjl } 1590118611Snjl } 1591118611Snjl else if (Status != AE_CTRL_DEPTH) 1592118611Snjl { 1593118611Snjl /* Exit immediately on any error */ 1594118611Snjl 1595118611Snjl return (Status); 1596118611Snjl } 1597118611Snjl } 1598118611Snjl 1599118611Snjl /* Terminate walk at start op */ 1600118611Snjl 1601118611Snjl if (Op == StartOp) 1602118611Snjl { 1603118611Snjl break; 1604118611Snjl } 1605118611Snjl 1606118611Snjl /* No more children, visit peers */ 1607118611Snjl 1608118611Snjl if (Op->Asl.Next) 1609118611Snjl { 1610118611Snjl Op = Op->Asl.Next; 1611118611Snjl NodePreviouslyVisited = FALSE; 1612118611Snjl } 1613118611Snjl else 1614118611Snjl { 1615118611Snjl /* No children or peers, re-visit parent */ 1616118611Snjl 1617118611Snjl if (Level != 0 ) 1618118611Snjl { 1619118611Snjl Level--; 1620118611Snjl } 1621118611Snjl Op = Op->Asl.Parent; 1622118611Snjl NodePreviouslyVisited = TRUE; 1623118611Snjl } 1624118611Snjl } 1625118611Snjl break; 1626118611Snjl 1627118611Snjl default: 1628118611Snjl /* No other types supported */ 1629118611Snjl break; 1630118611Snjl } 1631118611Snjl 1632118611Snjl /* If we get here, the walk completed with no errors */ 1633118611Snjl 1634118611Snjl return (AE_OK); 1635118611Snjl} 1636