asltransform.c revision 167802
1118611Snjl 2118611Snjl/****************************************************************************** 3118611Snjl * 4118611Snjl * Module Name: asltransform - Parse tree transforms 5167802Sjkim * $Revision: 1.42 $ 6118611Snjl * 7118611Snjl *****************************************************************************/ 8118611Snjl 9118611Snjl/****************************************************************************** 10118611Snjl * 11118611Snjl * 1. Copyright Notice 12118611Snjl * 13167802Sjkim * Some or all of this work - Copyright (c) 1999 - 2007, Intel Corp. 14118611Snjl * All rights reserved. 15118611Snjl * 16118611Snjl * 2. License 17118611Snjl * 18118611Snjl * 2.1. This is your license from Intel Corp. under its intellectual property 19118611Snjl * rights. You may have additional license terms from the party that provided 20118611Snjl * you this software, covering your right to use that party's intellectual 21118611Snjl * property rights. 22118611Snjl * 23118611Snjl * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 24118611Snjl * copy of the source code appearing in this file ("Covered Code") an 25118611Snjl * irrevocable, perpetual, worldwide license under Intel's copyrights in the 26118611Snjl * base code distributed originally by Intel ("Original Intel Code") to copy, 27118611Snjl * make derivatives, distribute, use and display any portion of the Covered 28118611Snjl * Code in any form, with the right to sublicense such rights; and 29118611Snjl * 30118611Snjl * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 31118611Snjl * license (with the right to sublicense), under only those claims of Intel 32118611Snjl * patents that are infringed by the Original Intel Code, to make, use, sell, 33118611Snjl * offer to sell, and import the Covered Code and derivative works thereof 34118611Snjl * solely to the minimum extent necessary to exercise the above copyright 35118611Snjl * license, and in no event shall the patent license extend to any additions 36118611Snjl * to or modifications of the Original Intel Code. No other license or right 37118611Snjl * is granted directly or by implication, estoppel or otherwise; 38118611Snjl * 39118611Snjl * The above copyright and patent license is granted only if the following 40118611Snjl * conditions are met: 41118611Snjl * 42118611Snjl * 3. Conditions 43118611Snjl * 44118611Snjl * 3.1. Redistribution of Source with Rights to Further Distribute Source. 45118611Snjl * Redistribution of source code of any substantial portion of the Covered 46118611Snjl * Code or modification with rights to further distribute source must include 47118611Snjl * the above Copyright Notice, the above License, this list of Conditions, 48118611Snjl * and the following Disclaimer and Export Compliance provision. In addition, 49118611Snjl * Licensee must cause all Covered Code to which Licensee contributes to 50118611Snjl * contain a file documenting the changes Licensee made to create that Covered 51118611Snjl * Code and the date of any change. Licensee must include in that file the 52118611Snjl * documentation of any changes made by any predecessor Licensee. Licensee 53118611Snjl * must include a prominent statement that the modification is derived, 54118611Snjl * directly or indirectly, from Original Intel Code. 55118611Snjl * 56118611Snjl * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 57118611Snjl * Redistribution of source code of any substantial portion of the Covered 58118611Snjl * Code or modification without rights to further distribute source must 59118611Snjl * include the following Disclaimer and Export Compliance provision in the 60118611Snjl * documentation and/or other materials provided with distribution. In 61118611Snjl * addition, Licensee may not authorize further sublicense of source of any 62118611Snjl * portion of the Covered Code, and must include terms to the effect that the 63118611Snjl * license from Licensee to its licensee is limited to the intellectual 64118611Snjl * property embodied in the software Licensee provides to its licensee, and 65118611Snjl * not to intellectual property embodied in modifications its licensee may 66118611Snjl * make. 67118611Snjl * 68118611Snjl * 3.3. Redistribution of Executable. Redistribution in executable form of any 69118611Snjl * substantial portion of the Covered Code or modification must reproduce the 70118611Snjl * above Copyright Notice, and the following Disclaimer and Export Compliance 71118611Snjl * provision in the documentation and/or other materials provided with the 72118611Snjl * distribution. 73118611Snjl * 74118611Snjl * 3.4. Intel retains all right, title, and interest in and to the Original 75118611Snjl * Intel Code. 76118611Snjl * 77118611Snjl * 3.5. Neither the name Intel nor any other trademark owned or controlled by 78118611Snjl * Intel shall be used in advertising or otherwise to promote the sale, use or 79118611Snjl * other dealings in products derived from or relating to the Covered Code 80118611Snjl * without prior written authorization from Intel. 81118611Snjl * 82118611Snjl * 4. Disclaimer and Export Compliance 83118611Snjl * 84118611Snjl * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 85118611Snjl * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 86118611Snjl * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 87118611Snjl * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 88118611Snjl * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 89118611Snjl * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 90118611Snjl * PARTICULAR PURPOSE. 91118611Snjl * 92118611Snjl * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 93118611Snjl * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 94118611Snjl * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 95118611Snjl * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 96118611Snjl * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 97118611Snjl * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 98118611Snjl * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 99118611Snjl * LIMITED REMEDY. 100118611Snjl * 101118611Snjl * 4.3. Licensee shall not export, either directly or indirectly, any of this 102118611Snjl * software or system incorporating such software without first obtaining any 103118611Snjl * required license or other approval from the U. S. Department of Commerce or 104118611Snjl * any other agency or department of the United States Government. In the 105118611Snjl * event Licensee exports any such software from the United States or 106118611Snjl * re-exports any such software from a foreign destination, Licensee shall 107118611Snjl * ensure that the distribution and export/re-export of the software is in 108118611Snjl * compliance with all laws, regulations, orders, or other restrictions of the 109118611Snjl * U.S. Export Administration Regulations. Licensee agrees that neither it nor 110118611Snjl * any of its subsidiaries will export/re-export any technical data, process, 111118611Snjl * software, or service, directly or indirectly, to any country for which the 112118611Snjl * United States government or any agency thereof requires an export license, 113118611Snjl * other governmental approval, or letter of assurance, without first obtaining 114118611Snjl * such license, approval or letter. 115118611Snjl * 116118611Snjl *****************************************************************************/ 117118611Snjl 118118611Snjl 119151937Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h> 120118611Snjl#include "aslcompiler.y.h" 121118611Snjl 122118611Snjl#define _COMPONENT ACPI_COMPILER 123118611Snjl ACPI_MODULE_NAME ("asltransform") 124118611Snjl 125151937Sjkim/* Local prototypes */ 126118611Snjl 127151937Sjkimstatic void 128151937SjkimTrTransformSubtree ( 129151937Sjkim ACPI_PARSE_OBJECT *Op); 130151937Sjkim 131151937Sjkimstatic char * 132151937SjkimTrAmlGetNextTempName ( 133151937Sjkim ACPI_PARSE_OBJECT *Op, 134151937Sjkim UINT8 *TempCount); 135151937Sjkim 136151937Sjkimstatic void 137151937SjkimTrAmlInitLineNumbers ( 138151937Sjkim ACPI_PARSE_OBJECT *Op, 139151937Sjkim ACPI_PARSE_OBJECT *Neighbor); 140151937Sjkim 141151937Sjkimstatic void 142151937SjkimTrAmlInitNode ( 143151937Sjkim ACPI_PARSE_OBJECT *Op, 144151937Sjkim UINT16 ParseOpcode); 145151937Sjkim 146151937Sjkimstatic void 147151937SjkimTrAmlSetSubtreeParent ( 148151937Sjkim ACPI_PARSE_OBJECT *Op, 149151937Sjkim ACPI_PARSE_OBJECT *Parent); 150151937Sjkim 151151937Sjkimstatic void 152151937SjkimTrAmlInsertPeer ( 153151937Sjkim ACPI_PARSE_OBJECT *Op, 154151937Sjkim ACPI_PARSE_OBJECT *NewPeer); 155151937Sjkim 156151937Sjkimstatic void 157151937SjkimTrDoDefinitionBlock ( 158151937Sjkim ACPI_PARSE_OBJECT *Op); 159151937Sjkim 160151937Sjkimstatic void 161151937SjkimTrDoSwitch ( 162151937Sjkim ACPI_PARSE_OBJECT *StartNode); 163151937Sjkim 164151937Sjkim 165118611Snjl/******************************************************************************* 166118611Snjl * 167118611Snjl * FUNCTION: TrAmlGetNextTempName 168118611Snjl * 169151937Sjkim * PARAMETERS: Op - Current parse op 170151937Sjkim * TempCount - Current temporary counter. Was originally 171151937Sjkim * per-module; Currently per method, could be 172151937Sjkim * expanded to per-scope. 173118611Snjl * 174151937Sjkim * RETURN: A pointer to name (allocated here). 175118611Snjl * 176138287Smarks * DESCRIPTION: Generate an ACPI name of the form _T_x. These names are 177151937Sjkim * reserved for use by the ASL compiler. (_T_0 through _T_Z) 178118611Snjl * 179118611Snjl ******************************************************************************/ 180118611Snjl 181151937Sjkimstatic char * 182118611SnjlTrAmlGetNextTempName ( 183151937Sjkim ACPI_PARSE_OBJECT *Op, 184151937Sjkim UINT8 *TempCount) 185118611Snjl{ 186118611Snjl char *TempName; 187118611Snjl 188118611Snjl 189151937Sjkim if (*TempCount >= (10+26)) /* 0-35 valid: 0-9 and A-Z for TempName[3] */ 190118611Snjl { 191118611Snjl /* Too many temps */ 192151937Sjkim 193151937Sjkim AslError (ASL_ERROR, ASL_MSG_TOO_MANY_TEMPS, Op, NULL); 194151937Sjkim return (NULL); 195118611Snjl } 196118611Snjl 197151937Sjkim TempName = UtLocalCalloc (5); 198138287Smarks 199151937Sjkim if (*TempCount < 10) /* 0-9 */ 200138287Smarks { 201151937Sjkim TempName[3] = (char) (*TempCount + '0'); 202138287Smarks } 203151937Sjkim else /* 10-35: A-Z */ 204138287Smarks { 205151937Sjkim TempName[3] = (char) (*TempCount + ('A' - 10)); 206138287Smarks } 207151937Sjkim (*TempCount)++; 208118611Snjl 209151937Sjkim /* First three characters are always "_T_" */ 210118611Snjl 211151937Sjkim TempName[0] = '_'; 212151937Sjkim TempName[1] = 'T'; 213151937Sjkim TempName[2] = '_'; 214118611Snjl 215151937Sjkim return (TempName); 216118611Snjl} 217118611Snjl 218118611Snjl 219118611Snjl/******************************************************************************* 220118611Snjl * 221118611Snjl * FUNCTION: TrAmlInitLineNumbers 222118611Snjl * 223151937Sjkim * PARAMETERS: Op - Op to be initialized 224118611Snjl * Neighbor - Op used for initialization values 225118611Snjl * 226118611Snjl * RETURN: None 227118611Snjl * 228118611Snjl * DESCRIPTION: Initialized the various line numbers for a parse node. 229118611Snjl * 230118611Snjl ******************************************************************************/ 231118611Snjl 232151937Sjkimstatic void 233118611SnjlTrAmlInitLineNumbers ( 234118611Snjl ACPI_PARSE_OBJECT *Op, 235118611Snjl ACPI_PARSE_OBJECT *Neighbor) 236118611Snjl{ 237118611Snjl 238118611Snjl Op->Asl.EndLine = Neighbor->Asl.EndLine; 239118611Snjl Op->Asl.EndLogicalLine = Neighbor->Asl.EndLogicalLine; 240118611Snjl Op->Asl.LineNumber = Neighbor->Asl.LineNumber; 241118611Snjl Op->Asl.LogicalByteOffset = Neighbor->Asl.LogicalByteOffset; 242118611Snjl Op->Asl.LogicalLineNumber = Neighbor->Asl.LogicalLineNumber; 243118611Snjl} 244118611Snjl 245118611Snjl 246118611Snjl/******************************************************************************* 247118611Snjl * 248118611Snjl * FUNCTION: TrAmlInitNode 249118611Snjl * 250151937Sjkim * PARAMETERS: Op - Op to be initialized 251118611Snjl * ParseOpcode - Opcode for this node 252118611Snjl * 253118611Snjl * RETURN: None 254118611Snjl * 255118611Snjl * DESCRIPTION: Initialize a node with the parse opcode and opcode name. 256118611Snjl * 257118611Snjl ******************************************************************************/ 258118611Snjl 259151937Sjkimstatic void 260118611SnjlTrAmlInitNode ( 261118611Snjl ACPI_PARSE_OBJECT *Op, 262118611Snjl UINT16 ParseOpcode) 263118611Snjl{ 264118611Snjl 265118611Snjl Op->Asl.ParseOpcode = ParseOpcode; 266118611Snjl UtSetParseOpName (Op); 267118611Snjl} 268118611Snjl 269118611Snjl 270118611Snjl/******************************************************************************* 271118611Snjl * 272118611Snjl * FUNCTION: TrAmlSetSubtreeParent 273118611Snjl * 274151937Sjkim * PARAMETERS: Op - First node in a list of peer nodes 275118611Snjl * Parent - Parent of the subtree 276118611Snjl * 277118611Snjl * RETURN: None 278118611Snjl * 279118611Snjl * DESCRIPTION: Set the parent for all peer nodes in a subtree 280118611Snjl * 281118611Snjl ******************************************************************************/ 282118611Snjl 283151937Sjkimstatic void 284118611SnjlTrAmlSetSubtreeParent ( 285118611Snjl ACPI_PARSE_OBJECT *Op, 286118611Snjl ACPI_PARSE_OBJECT *Parent) 287118611Snjl{ 288118611Snjl ACPI_PARSE_OBJECT *Next; 289118611Snjl 290118611Snjl 291118611Snjl Next = Op; 292118611Snjl while (Next) 293118611Snjl { 294118611Snjl Next->Asl.Parent = Parent; 295118611Snjl Next = Next->Asl.Next; 296118611Snjl } 297118611Snjl} 298118611Snjl 299118611Snjl 300118611Snjl/******************************************************************************* 301118611Snjl * 302118611Snjl * FUNCTION: TrAmlInsertPeer 303118611Snjl * 304151937Sjkim * PARAMETERS: Op - First node in a list of peer nodes 305118611Snjl * NewPeer - Peer node to insert 306118611Snjl * 307118611Snjl * RETURN: None 308118611Snjl * 309118611Snjl * DESCRIPTION: Insert a new peer node into a list of peers. 310118611Snjl * 311118611Snjl ******************************************************************************/ 312118611Snjl 313151937Sjkimstatic void 314118611SnjlTrAmlInsertPeer ( 315118611Snjl ACPI_PARSE_OBJECT *Op, 316118611Snjl ACPI_PARSE_OBJECT *NewPeer) 317118611Snjl{ 318118611Snjl 319118611Snjl NewPeer->Asl.Next = Op->Asl.Next; 320118611Snjl Op->Asl.Next = NewPeer; 321118611Snjl} 322118611Snjl 323118611Snjl 324118611Snjl/******************************************************************************* 325118611Snjl * 326118611Snjl * FUNCTION: TrAmlTransformWalk 327118611Snjl * 328118611Snjl * PARAMETERS: ASL_WALK_CALLBACK 329118611Snjl * 330118611Snjl * RETURN: None 331118611Snjl * 332118611Snjl * DESCRIPTION: Parse tree walk to generate both the AML opcodes and the AML 333118611Snjl * operands. 334118611Snjl * 335118611Snjl ******************************************************************************/ 336118611Snjl 337118611SnjlACPI_STATUS 338118611SnjlTrAmlTransformWalk ( 339118611Snjl ACPI_PARSE_OBJECT *Op, 340118611Snjl UINT32 Level, 341118611Snjl void *Context) 342118611Snjl{ 343118611Snjl 344118611Snjl TrTransformSubtree (Op); 345118611Snjl return (AE_OK); 346118611Snjl} 347118611Snjl 348118611Snjl 349118611Snjl/******************************************************************************* 350118611Snjl * 351118611Snjl * FUNCTION: TrTransformSubtree 352118611Snjl * 353118611Snjl * PARAMETERS: Op - The parent parse node 354118611Snjl * 355118611Snjl * RETURN: None 356118611Snjl * 357118611Snjl * DESCRIPTION: Prepare nodes to be output as AML data and operands. The more 358118611Snjl * complex AML opcodes require processing of the child nodes 359118611Snjl * (arguments/operands). 360118611Snjl * 361118611Snjl ******************************************************************************/ 362118611Snjl 363151937Sjkimstatic void 364118611SnjlTrTransformSubtree ( 365118611Snjl ACPI_PARSE_OBJECT *Op) 366118611Snjl{ 367118611Snjl 368118611Snjl if (Op->Asl.AmlOpcode == AML_RAW_DATA_BYTE) 369118611Snjl { 370118611Snjl return; 371118611Snjl } 372118611Snjl 373118611Snjl switch (Op->Asl.ParseOpcode) 374118611Snjl { 375118611Snjl case PARSEOP_DEFINITIONBLOCK: 376118611Snjl TrDoDefinitionBlock (Op); 377118611Snjl break; 378118611Snjl 379118611Snjl case PARSEOP_SWITCH: 380118611Snjl TrDoSwitch (Op); 381118611Snjl break; 382118611Snjl 383151937Sjkim case PARSEOP_METHOD: 384151937Sjkim 385151937Sjkim /* 386151937Sjkim * TBD: Zero the tempname (_T_x) count. Probably shouldn't be a global, 387151937Sjkim * however 388151937Sjkim */ 389151937Sjkim Gbl_TempCount = 0; 390151937Sjkim break; 391151937Sjkim 392118611Snjl default: 393118611Snjl /* Nothing to do here for other opcodes */ 394118611Snjl break; 395118611Snjl } 396118611Snjl} 397118611Snjl 398118611Snjl 399118611Snjl/******************************************************************************* 400118611Snjl * 401118611Snjl * FUNCTION: TrDoDefinitionBlock 402118611Snjl * 403118611Snjl * PARAMETERS: Op - Parse node 404118611Snjl * 405118611Snjl * RETURN: None 406118611Snjl * 407118611Snjl * DESCRIPTION: Find the end of the definition block and set a global to this 408118611Snjl * node. It is used by the compiler to insert compiler-generated 409118611Snjl * names at the root level of the namespace. 410118611Snjl * 411118611Snjl ******************************************************************************/ 412118611Snjl 413151937Sjkimstatic void 414118611SnjlTrDoDefinitionBlock ( 415118611Snjl ACPI_PARSE_OBJECT *Op) 416118611Snjl{ 417118611Snjl ACPI_PARSE_OBJECT *Next; 418118611Snjl UINT32 i; 419118611Snjl 420118611Snjl 421118611Snjl Next = Op->Asl.Child; 422118611Snjl for (i = 0; i < 5; i++) 423118611Snjl { 424118611Snjl Next = Next->Asl.Next; 425151937Sjkim if (i == 0) 426151937Sjkim { 427151937Sjkim /* 428151937Sjkim * This is the table signature. Only the DSDT can be assumed 429151937Sjkim * to be at the root of the namespace; Therefore, namepath 430151937Sjkim * optimization can only be performed on the DSDT. 431151937Sjkim */ 432167802Sjkim if (!ACPI_COMPARE_NAME (Next->Asl.Value.String, ACPI_SIG_DSDT)) 433151937Sjkim { 434151937Sjkim Gbl_ReferenceOptimizationFlag = FALSE; 435151937Sjkim } 436151937Sjkim } 437118611Snjl } 438118611Snjl 439118611Snjl Gbl_FirstLevelInsertionNode = Next; 440118611Snjl} 441118611Snjl 442118611Snjl 443118611Snjl/******************************************************************************* 444118611Snjl * 445118611Snjl * FUNCTION: TrDoSwitch 446118611Snjl * 447118611Snjl * PARAMETERS: StartNode - Parse node for SWITCH 448118611Snjl * 449118611Snjl * RETURN: None 450118611Snjl * 451118611Snjl * 452118611Snjl * DESCRIPTION: Translate ASL SWITCH statement to if/else pairs. There is 453118611Snjl * no actual AML opcode for SWITCH -- it must be simulated. 454118611Snjl * 455118611Snjl ******************************************************************************/ 456118611Snjl 457151937Sjkimstatic void 458118611SnjlTrDoSwitch ( 459118611Snjl ACPI_PARSE_OBJECT *StartNode) 460118611Snjl{ 461118611Snjl ACPI_PARSE_OBJECT *Next; 462118611Snjl ACPI_PARSE_OBJECT *CaseOp = NULL; 463118611Snjl ACPI_PARSE_OBJECT *CaseBlock = NULL; 464118611Snjl ACPI_PARSE_OBJECT *DefaultOp = NULL; 465118611Snjl ACPI_PARSE_OBJECT *CurrentParentNode; 466118611Snjl ACPI_PARSE_OBJECT *Conditional = NULL; 467118611Snjl ACPI_PARSE_OBJECT *Predicate; 468118611Snjl ACPI_PARSE_OBJECT *Peer; 469118611Snjl ACPI_PARSE_OBJECT *NewOp; 470118611Snjl ACPI_PARSE_OBJECT *NewOp2; 471118611Snjl char *PredicateValueName; 472151937Sjkim UINT16 Index; 473151937Sjkim UINT32 Btype; 474118611Snjl 475118611Snjl 476151937Sjkim /* Start node is the Switch() node */ 477151937Sjkim 478118611Snjl CurrentParentNode = StartNode; 479118611Snjl 480151937Sjkim /* Create a new temp name of the form _T_x */ 481118611Snjl 482151937Sjkim PredicateValueName = TrAmlGetNextTempName (StartNode, &Gbl_TempCount); 483151937Sjkim if (!PredicateValueName) 484151937Sjkim { 485151937Sjkim return; 486151937Sjkim } 487151937Sjkim 488151937Sjkim /* First child is the Switch() predicate */ 489151937Sjkim 490118611Snjl Next = StartNode->Asl.Child; 491118611Snjl 492151937Sjkim /* 493151937Sjkim * Examine the return type of the Switch Value - 494151937Sjkim * must be Integer/Buffer/String 495151937Sjkim */ 496151937Sjkim Index = (UINT16) (Next->Asl.ParseOpcode - ASL_PARSE_OPCODE_BASE); 497151937Sjkim Btype = AslKeywordMapping[Index].AcpiBtype; 498151937Sjkim if ((Btype != ACPI_BTYPE_INTEGER) && 499151937Sjkim (Btype != ACPI_BTYPE_STRING) && 500151937Sjkim (Btype != ACPI_BTYPE_BUFFER)) 501151937Sjkim { 502151937Sjkim AslError (ASL_WARNING, ASL_MSG_SWITCH_TYPE, Next, NULL); 503151937Sjkim Btype = ACPI_BTYPE_INTEGER; 504151937Sjkim } 505151937Sjkim 506118611Snjl /* CASE statements start at next child */ 507118611Snjl 508151937Sjkim Peer = Next->Asl.Next; 509118611Snjl while (Peer) 510118611Snjl { 511118611Snjl Next = Peer; 512118611Snjl Peer = Next->Asl.Next; 513118611Snjl 514118611Snjl if (Next->Asl.ParseOpcode == PARSEOP_CASE) 515118611Snjl { 516118611Snjl if (CaseOp) 517118611Snjl { 518118611Snjl /* Add an ELSE to complete the previous CASE */ 519118611Snjl 520151937Sjkim if (!Conditional) 521151937Sjkim { 522151937Sjkim return; 523151937Sjkim } 524118611Snjl NewOp = TrCreateLeafNode (PARSEOP_ELSE); 525118611Snjl NewOp->Asl.Parent = Conditional->Asl.Parent; 526118611Snjl TrAmlInitLineNumbers (NewOp, NewOp->Asl.Parent); 527118611Snjl 528118611Snjl /* Link ELSE node as a peer to the previous IF */ 529118611Snjl 530118611Snjl TrAmlInsertPeer (Conditional, NewOp); 531118611Snjl CurrentParentNode = NewOp; 532118611Snjl } 533118611Snjl 534118611Snjl CaseOp = Next; 535118611Snjl Conditional = CaseOp; 536118611Snjl CaseBlock = CaseOp->Asl.Child->Asl.Next; 537118611Snjl Conditional->Asl.Child->Asl.Next = NULL; 538138287Smarks Predicate = CaseOp->Asl.Child; 539118611Snjl 540151937Sjkim if ((Predicate->Asl.ParseOpcode == PARSEOP_PACKAGE) || 541151937Sjkim (Predicate->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE)) 542138287Smarks { 543138287Smarks /* 544138287Smarks * Convert the package declaration to this form: 545138287Smarks * 546151937Sjkim * If (LNotEqual (Match (Package(<size>){<data>}, 547151937Sjkim * MEQ, _T_x, MTR, Zero, Zero), Ones)) 548138287Smarks */ 549138287Smarks NewOp2 = TrCreateLeafNode (PARSEOP_MATCHTYPE_MEQ); 550138287Smarks Predicate->Asl.Next = NewOp2; 551138287Smarks TrAmlInitLineNumbers (NewOp2, Conditional); 552118611Snjl 553138287Smarks NewOp = NewOp2; 554138287Smarks NewOp2 = TrCreateValuedLeafNode (PARSEOP_NAMESTRING, 555151937Sjkim (ACPI_INTEGER) ACPI_TO_INTEGER (PredicateValueName)); 556138287Smarks NewOp->Asl.Next = NewOp2; 557138287Smarks TrAmlInitLineNumbers (NewOp2, Predicate); 558118611Snjl 559138287Smarks NewOp = NewOp2; 560138287Smarks NewOp2 = TrCreateLeafNode (PARSEOP_MATCHTYPE_MTR); 561138287Smarks NewOp->Asl.Next = NewOp2; 562138287Smarks TrAmlInitLineNumbers (NewOp2, Predicate); 563118611Snjl 564138287Smarks NewOp = NewOp2; 565138287Smarks NewOp2 = TrCreateLeafNode (PARSEOP_ZERO); 566138287Smarks NewOp->Asl.Next = NewOp2; 567138287Smarks TrAmlInitLineNumbers (NewOp2, Predicate); 568118611Snjl 569138287Smarks NewOp = NewOp2; 570138287Smarks NewOp2 = TrCreateLeafNode (PARSEOP_ZERO); 571138287Smarks NewOp->Asl.Next = NewOp2; 572138287Smarks TrAmlInitLineNumbers (NewOp2, Predicate); 573118611Snjl 574138287Smarks NewOp2 = TrCreateLeafNode (PARSEOP_MATCH); 575138287Smarks NewOp2->Asl.Child = Predicate; /* PARSEOP_PACKAGE */ 576138287Smarks TrAmlInitLineNumbers (NewOp2, Conditional); 577138287Smarks TrAmlSetSubtreeParent (Predicate, NewOp2); 578138287Smarks 579138287Smarks NewOp = NewOp2; 580138287Smarks NewOp2 = TrCreateLeafNode (PARSEOP_ONES); 581138287Smarks NewOp->Asl.Next = NewOp2; 582138287Smarks TrAmlInitLineNumbers (NewOp2, Conditional); 583138287Smarks 584138287Smarks NewOp2 = TrCreateLeafNode (PARSEOP_LEQUAL); 585138287Smarks NewOp2->Asl.Child = NewOp; 586138287Smarks NewOp->Asl.Parent = NewOp2; 587138287Smarks TrAmlInitLineNumbers (NewOp2, Conditional); 588138287Smarks TrAmlSetSubtreeParent (NewOp, NewOp2); 589138287Smarks 590138287Smarks NewOp = NewOp2; 591138287Smarks NewOp2 = TrCreateLeafNode (PARSEOP_LNOT); 592138287Smarks NewOp2->Asl.Child = NewOp; 593138287Smarks NewOp2->Asl.Parent = Conditional; 594138287Smarks NewOp->Asl.Parent = NewOp2; 595138287Smarks TrAmlInitLineNumbers (NewOp2, Conditional); 596138287Smarks 597138287Smarks Conditional->Asl.Child = NewOp2; 598138287Smarks NewOp2->Asl.Next = CaseBlock; 599138287Smarks } 600138287Smarks else 601138287Smarks { 602138287Smarks /* 603151937Sjkim * Integer and Buffer case. 604151937Sjkim * 605151937Sjkim * Change CaseOp() to: If (LEqual (SwitchValue, CaseValue)) {...} 606151937Sjkim * Note: SwitchValue is first to allow the CaseValue to be implicitly 607151937Sjkim * converted to the type of SwitchValue if necessary. 608151937Sjkim * 609138287Smarks * CaseOp->Child is the case value 610138287Smarks * CaseOp->Child->Peer is the beginning of the case block 611138287Smarks */ 612138287Smarks NewOp = TrCreateValuedLeafNode (PARSEOP_NAMESTRING, 613151937Sjkim (ACPI_INTEGER) ACPI_TO_INTEGER (PredicateValueName)); 614151937Sjkim NewOp->Asl.Next = Predicate; 615138287Smarks TrAmlInitLineNumbers (NewOp, Predicate); 616138287Smarks 617138287Smarks NewOp2 = TrCreateLeafNode (PARSEOP_LEQUAL); 618138287Smarks NewOp2->Asl.Parent = Conditional; 619151937Sjkim NewOp2->Asl.Child = NewOp; 620138287Smarks TrAmlInitLineNumbers (NewOp2, Conditional); 621138287Smarks 622151937Sjkim TrAmlSetSubtreeParent (NewOp, NewOp2); 623138287Smarks 624138287Smarks Predicate = NewOp2; 625138287Smarks Predicate->Asl.Next = CaseBlock; 626138287Smarks 627138287Smarks TrAmlSetSubtreeParent (Predicate, Conditional); 628138287Smarks Conditional->Asl.Child = Predicate; 629138287Smarks } 630138287Smarks 631118611Snjl /* Reinitialize the CASE node to an IF node */ 632118611Snjl 633118611Snjl TrAmlInitNode (Conditional, PARSEOP_IF); 634118611Snjl 635118611Snjl /* 636118611Snjl * The first CASE(IF) is not nested under an ELSE. 637118611Snjl * All other CASEs are children of a parent ELSE. 638118611Snjl */ 639118611Snjl if (CurrentParentNode == StartNode) 640118611Snjl { 641118611Snjl Conditional->Asl.Parent = CurrentParentNode->Asl.Parent; 642118611Snjl 643118611Snjl /* Link IF into the peer list */ 644118611Snjl 645118611Snjl TrAmlInsertPeer (CurrentParentNode, Conditional); 646118611Snjl } 647118611Snjl else 648118611Snjl { 649118611Snjl /* 650118611Snjl * The IF is a child of previous IF/ELSE. It 651118611Snjl * is therefore without peer. 652118611Snjl */ 653118611Snjl CurrentParentNode->Asl.Child = Conditional; 654118611Snjl Conditional->Asl.Parent = CurrentParentNode; 655118611Snjl Conditional->Asl.Next = NULL; 656118611Snjl } 657118611Snjl } 658118611Snjl else if (Next->Asl.ParseOpcode == PARSEOP_DEFAULT) 659118611Snjl { 660118611Snjl if (DefaultOp) 661118611Snjl { 662138287Smarks /* 663138287Smarks * More than one Default 664167802Sjkim * (Parser does not catch this, must check here) 665138287Smarks */ 666167802Sjkim AslError (ASL_ERROR, ASL_MSG_MULTIPLE_DEFAULT, Next, NULL); 667118611Snjl } 668167802Sjkim else 669167802Sjkim { 670167802Sjkim /* Save the DEFAULT node for later, after CASEs */ 671118611Snjl 672167802Sjkim DefaultOp = Next; 673167802Sjkim } 674118611Snjl } 675118611Snjl else 676118611Snjl { 677138287Smarks /* Unknown peer opcode */ 678118611Snjl 679151937Sjkim AcpiOsPrintf ("Unknown parse opcode for switch statement: %s (%d)\n", 680118611Snjl Next->Asl.ParseOpName, Next->Asl.ParseOpcode); 681118611Snjl } 682118611Snjl } 683118611Snjl 684151937Sjkim /* Add the default case at the end of the if/else construct */ 685151937Sjkim 686118611Snjl if (DefaultOp) 687118611Snjl { 688138287Smarks /* If no CASE statements, this is an error - see below */ 689138287Smarks 690118611Snjl if (CaseOp) 691118611Snjl { 692138287Smarks /* Convert the DEFAULT node to an ELSE */ 693118611Snjl 694151937Sjkim if (!Conditional) 695151937Sjkim { 696151937Sjkim return; 697151937Sjkim } 698118611Snjl TrAmlInitNode (DefaultOp, PARSEOP_ELSE); 699118611Snjl DefaultOp->Asl.Parent = Conditional->Asl.Parent; 700118611Snjl 701138287Smarks /* Link ELSE node as a peer to the previous IF */ 702138287Smarks 703138287Smarks TrAmlInsertPeer (Conditional, DefaultOp); 704118611Snjl } 705118611Snjl } 706118611Snjl 707138287Smarks if (!CaseOp) 708138287Smarks { 709138287Smarks AslError (ASL_ERROR, ASL_MSG_NO_CASES, StartNode, NULL); 710138287Smarks } 711138287Smarks 712167802Sjkim 713118611Snjl /* 714167802Sjkim * Create a Name(_T_x, ...) statement. This statement must appear at the 715167802Sjkim * method level, in case a loop surrounds the switch statement and could 716167802Sjkim * cause the name to be created twice (error). 717118611Snjl */ 718167802Sjkim 719167802Sjkim /* Create the Name node */ 720167802Sjkim 721151937Sjkim Predicate = StartNode->Asl.Child; 722167802Sjkim NewOp = TrCreateLeafNode (PARSEOP_NAME); 723151937Sjkim 724167802Sjkim /* Find the parent method */ 725151937Sjkim 726167802Sjkim Next = StartNode; 727167802Sjkim while ((Next->Asl.ParseOpcode != PARSEOP_METHOD) && 728167802Sjkim (Next->Asl.ParseOpcode != PARSEOP_DEFINITIONBLOCK)) 729167802Sjkim { 730167802Sjkim Next = Next->Asl.Parent; 731167802Sjkim } 732167802Sjkim 733138287Smarks NewOp->Asl.CompileFlags |= NODE_COMPILER_EMITTED; 734167802Sjkim NewOp->Asl.Parent = Next; 735118611Snjl 736167802Sjkim /* Insert name after the method name and arguments */ 737167802Sjkim 738167802Sjkim Next = Next->Asl.Child; 739167802Sjkim Next = Next->Asl.Next; 740167802Sjkim Next = Next->Asl.Next; 741167802Sjkim Next = Next->Asl.Next; 742167802Sjkim Next = Next->Asl.Next; 743167802Sjkim Next = Next->Asl.Next; 744167802Sjkim 745167802Sjkim TrAmlInsertPeer (Next, NewOp); 746167802Sjkim TrAmlInitLineNumbers (NewOp, Next); 747167802Sjkim 748167802Sjkim /* Create the NameSeg child for the Name node */ 749167802Sjkim 750151937Sjkim NewOp2 = TrCreateValuedLeafNode (PARSEOP_NAMESEG, 751151937Sjkim (ACPI_INTEGER) ACPI_TO_INTEGER (PredicateValueName)); 752151937Sjkim NewOp2->Asl.CompileFlags |= NODE_IS_NAME_DECLARATION; 753118611Snjl NewOp->Asl.Child = NewOp2; 754118611Snjl 755167802Sjkim /* Create the initial value for the Name. Btype was already validated above */ 756118611Snjl 757151937Sjkim switch (Btype) 758151937Sjkim { 759151937Sjkim case ACPI_BTYPE_INTEGER: 760167802Sjkim NewOp2->Asl.Next = TrCreateValuedLeafNode (PARSEOP_ZERO, 761151937Sjkim (ACPI_INTEGER) 0); 762151937Sjkim break; 763118611Snjl 764151937Sjkim case ACPI_BTYPE_STRING: 765151937Sjkim NewOp2->Asl.Next = TrCreateValuedLeafNode (PARSEOP_STRING_LITERAL, 766151937Sjkim (ACPI_INTEGER) ""); 767151937Sjkim break; 768118611Snjl 769151937Sjkim case ACPI_BTYPE_BUFFER: 770151937Sjkim (void) TrLinkPeerNode (NewOp2, TrCreateValuedLeafNode (PARSEOP_BUFFER, 771151937Sjkim (ACPI_INTEGER) 0)); 772151937Sjkim Next = NewOp2->Asl.Next; 773151937Sjkim (void) TrLinkChildren (Next, 1, TrCreateValuedLeafNode (PARSEOP_ZERO, 774151937Sjkim (ACPI_INTEGER) 1)); 775151937Sjkim (void) TrLinkPeerNode (Next->Asl.Child, 776151937Sjkim TrCreateValuedLeafNode (PARSEOP_DEFAULT_ARG, (ACPI_INTEGER) 0)); 777151937Sjkim 778151937Sjkim TrAmlSetSubtreeParent (Next->Asl.Child, Next); 779151937Sjkim break; 780151937Sjkim 781151937Sjkim default: 782151937Sjkim break; 783151937Sjkim } 784151937Sjkim 785151937Sjkim TrAmlSetSubtreeParent (NewOp2, NewOp); 786151937Sjkim 787118611Snjl /* 788167802Sjkim * Transform the Switch() into a Store() node which will be used to save the 789151937Sjkim * Switch() value. The store is of the form: Store (Value, _T_x) 790151937Sjkim * where _T_x is the temp variable. 791118611Snjl */ 792167802Sjkim TrAmlInitNode (StartNode, PARSEOP_STORE); 793167802Sjkim StartNode->Asl.Child = NULL; 794118611Snjl 795151937Sjkim /* Complete the Store subtree */ 796151937Sjkim 797167802Sjkim StartNode->Asl.Child = Predicate; 798167802Sjkim Predicate->Asl.Parent = StartNode; 799151937Sjkim 800151937Sjkim NewOp = TrCreateValuedLeafNode (PARSEOP_NAMESEG, 801151937Sjkim (ACPI_INTEGER) ACPI_TO_INTEGER (PredicateValueName)); 802167802Sjkim NewOp->Asl.Parent = StartNode; 803118611Snjl Predicate->Asl.Next = NewOp; 804118611Snjl} 805118611Snjl 806118611Snjl 807