asltransform.c revision 209746
1118611Snjl 2118611Snjl/****************************************************************************** 3118611Snjl * 4118611Snjl * Module Name: asltransform - Parse tree transforms 5118611Snjl * 6118611Snjl *****************************************************************************/ 7118611Snjl 8118611Snjl/****************************************************************************** 9118611Snjl * 10118611Snjl * 1. Copyright Notice 11118611Snjl * 12202771Sjkim * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. 13118611Snjl * All rights reserved. 14118611Snjl * 15118611Snjl * 2. License 16118611Snjl * 17118611Snjl * 2.1. This is your license from Intel Corp. under its intellectual property 18118611Snjl * rights. You may have additional license terms from the party that provided 19118611Snjl * you this software, covering your right to use that party's intellectual 20118611Snjl * property rights. 21118611Snjl * 22118611Snjl * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 23118611Snjl * copy of the source code appearing in this file ("Covered Code") an 24118611Snjl * irrevocable, perpetual, worldwide license under Intel's copyrights in the 25118611Snjl * base code distributed originally by Intel ("Original Intel Code") to copy, 26118611Snjl * make derivatives, distribute, use and display any portion of the Covered 27118611Snjl * Code in any form, with the right to sublicense such rights; and 28118611Snjl * 29118611Snjl * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 30118611Snjl * license (with the right to sublicense), under only those claims of Intel 31118611Snjl * patents that are infringed by the Original Intel Code, to make, use, sell, 32118611Snjl * offer to sell, and import the Covered Code and derivative works thereof 33118611Snjl * solely to the minimum extent necessary to exercise the above copyright 34118611Snjl * license, and in no event shall the patent license extend to any additions 35118611Snjl * to or modifications of the Original Intel Code. No other license or right 36118611Snjl * is granted directly or by implication, estoppel or otherwise; 37118611Snjl * 38118611Snjl * The above copyright and patent license is granted only if the following 39118611Snjl * conditions are met: 40118611Snjl * 41118611Snjl * 3. Conditions 42118611Snjl * 43118611Snjl * 3.1. Redistribution of Source with Rights to Further Distribute Source. 44118611Snjl * Redistribution of source code of any substantial portion of the Covered 45118611Snjl * Code or modification with rights to further distribute source must include 46118611Snjl * the above Copyright Notice, the above License, this list of Conditions, 47118611Snjl * and the following Disclaimer and Export Compliance provision. In addition, 48118611Snjl * Licensee must cause all Covered Code to which Licensee contributes to 49118611Snjl * contain a file documenting the changes Licensee made to create that Covered 50118611Snjl * Code and the date of any change. Licensee must include in that file the 51118611Snjl * documentation of any changes made by any predecessor Licensee. Licensee 52118611Snjl * must include a prominent statement that the modification is derived, 53118611Snjl * directly or indirectly, from Original Intel Code. 54118611Snjl * 55118611Snjl * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 56118611Snjl * Redistribution of source code of any substantial portion of the Covered 57118611Snjl * Code or modification without rights to further distribute source must 58118611Snjl * include the following Disclaimer and Export Compliance provision in the 59118611Snjl * documentation and/or other materials provided with distribution. In 60118611Snjl * addition, Licensee may not authorize further sublicense of source of any 61118611Snjl * portion of the Covered Code, and must include terms to the effect that the 62118611Snjl * license from Licensee to its licensee is limited to the intellectual 63118611Snjl * property embodied in the software Licensee provides to its licensee, and 64118611Snjl * not to intellectual property embodied in modifications its licensee may 65118611Snjl * make. 66118611Snjl * 67118611Snjl * 3.3. Redistribution of Executable. Redistribution in executable form of any 68118611Snjl * substantial portion of the Covered Code or modification must reproduce the 69118611Snjl * above Copyright Notice, and the following Disclaimer and Export Compliance 70118611Snjl * provision in the documentation and/or other materials provided with the 71118611Snjl * distribution. 72118611Snjl * 73118611Snjl * 3.4. Intel retains all right, title, and interest in and to the Original 74118611Snjl * Intel Code. 75118611Snjl * 76118611Snjl * 3.5. Neither the name Intel nor any other trademark owned or controlled by 77118611Snjl * Intel shall be used in advertising or otherwise to promote the sale, use or 78118611Snjl * other dealings in products derived from or relating to the Covered Code 79118611Snjl * without prior written authorization from Intel. 80118611Snjl * 81118611Snjl * 4. Disclaimer and Export Compliance 82118611Snjl * 83118611Snjl * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 84118611Snjl * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 85118611Snjl * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 86118611Snjl * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 87118611Snjl * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 88118611Snjl * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 89118611Snjl * PARTICULAR PURPOSE. 90118611Snjl * 91118611Snjl * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 92118611Snjl * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 93118611Snjl * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 94118611Snjl * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 95118611Snjl * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 96118611Snjl * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 97118611Snjl * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 98118611Snjl * LIMITED REMEDY. 99118611Snjl * 100118611Snjl * 4.3. Licensee shall not export, either directly or indirectly, any of this 101118611Snjl * software or system incorporating such software without first obtaining any 102118611Snjl * required license or other approval from the U. S. Department of Commerce or 103118611Snjl * any other agency or department of the United States Government. In the 104118611Snjl * event Licensee exports any such software from the United States or 105118611Snjl * re-exports any such software from a foreign destination, Licensee shall 106118611Snjl * ensure that the distribution and export/re-export of the software is in 107118611Snjl * compliance with all laws, regulations, orders, or other restrictions of the 108118611Snjl * U.S. Export Administration Regulations. Licensee agrees that neither it nor 109118611Snjl * any of its subsidiaries will export/re-export any technical data, process, 110118611Snjl * software, or service, directly or indirectly, to any country for which the 111118611Snjl * United States government or any agency thereof requires an export license, 112118611Snjl * other governmental approval, or letter of assurance, without first obtaining 113118611Snjl * such license, approval or letter. 114118611Snjl * 115118611Snjl *****************************************************************************/ 116118611Snjl 117118611Snjl 118151937Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h> 119118611Snjl#include "aslcompiler.y.h" 120118611Snjl 121118611Snjl#define _COMPONENT ACPI_COMPILER 122118611Snjl ACPI_MODULE_NAME ("asltransform") 123118611Snjl 124151937Sjkim/* Local prototypes */ 125118611Snjl 126151937Sjkimstatic void 127151937SjkimTrTransformSubtree ( 128151937Sjkim ACPI_PARSE_OBJECT *Op); 129151937Sjkim 130151937Sjkimstatic char * 131151937SjkimTrAmlGetNextTempName ( 132151937Sjkim ACPI_PARSE_OBJECT *Op, 133151937Sjkim UINT8 *TempCount); 134151937Sjkim 135151937Sjkimstatic void 136151937SjkimTrAmlInitLineNumbers ( 137151937Sjkim ACPI_PARSE_OBJECT *Op, 138151937Sjkim ACPI_PARSE_OBJECT *Neighbor); 139151937Sjkim 140151937Sjkimstatic void 141151937SjkimTrAmlInitNode ( 142151937Sjkim ACPI_PARSE_OBJECT *Op, 143151937Sjkim UINT16 ParseOpcode); 144151937Sjkim 145151937Sjkimstatic void 146151937SjkimTrAmlSetSubtreeParent ( 147151937Sjkim ACPI_PARSE_OBJECT *Op, 148151937Sjkim ACPI_PARSE_OBJECT *Parent); 149151937Sjkim 150151937Sjkimstatic void 151151937SjkimTrAmlInsertPeer ( 152151937Sjkim ACPI_PARSE_OBJECT *Op, 153151937Sjkim ACPI_PARSE_OBJECT *NewPeer); 154151937Sjkim 155151937Sjkimstatic void 156151937SjkimTrDoDefinitionBlock ( 157151937Sjkim ACPI_PARSE_OBJECT *Op); 158151937Sjkim 159151937Sjkimstatic void 160151937SjkimTrDoSwitch ( 161151937Sjkim ACPI_PARSE_OBJECT *StartNode); 162151937Sjkim 163151937Sjkim 164118611Snjl/******************************************************************************* 165118611Snjl * 166118611Snjl * FUNCTION: TrAmlGetNextTempName 167118611Snjl * 168151937Sjkim * PARAMETERS: Op - Current parse op 169151937Sjkim * TempCount - Current temporary counter. Was originally 170151937Sjkim * per-module; Currently per method, could be 171151937Sjkim * expanded to per-scope. 172118611Snjl * 173151937Sjkim * RETURN: A pointer to name (allocated here). 174118611Snjl * 175138287Smarks * DESCRIPTION: Generate an ACPI name of the form _T_x. These names are 176151937Sjkim * reserved for use by the ASL compiler. (_T_0 through _T_Z) 177118611Snjl * 178118611Snjl ******************************************************************************/ 179118611Snjl 180151937Sjkimstatic char * 181118611SnjlTrAmlGetNextTempName ( 182151937Sjkim ACPI_PARSE_OBJECT *Op, 183151937Sjkim UINT8 *TempCount) 184118611Snjl{ 185118611Snjl char *TempName; 186118611Snjl 187118611Snjl 188151937Sjkim if (*TempCount >= (10+26)) /* 0-35 valid: 0-9 and A-Z for TempName[3] */ 189118611Snjl { 190118611Snjl /* Too many temps */ 191151937Sjkim 192151937Sjkim AslError (ASL_ERROR, ASL_MSG_TOO_MANY_TEMPS, Op, NULL); 193151937Sjkim return (NULL); 194118611Snjl } 195118611Snjl 196151937Sjkim TempName = UtLocalCalloc (5); 197138287Smarks 198151937Sjkim if (*TempCount < 10) /* 0-9 */ 199138287Smarks { 200151937Sjkim TempName[3] = (char) (*TempCount + '0'); 201138287Smarks } 202151937Sjkim else /* 10-35: A-Z */ 203138287Smarks { 204151937Sjkim TempName[3] = (char) (*TempCount + ('A' - 10)); 205138287Smarks } 206151937Sjkim (*TempCount)++; 207118611Snjl 208151937Sjkim /* First three characters are always "_T_" */ 209118611Snjl 210151937Sjkim TempName[0] = '_'; 211151937Sjkim TempName[1] = 'T'; 212151937Sjkim TempName[2] = '_'; 213118611Snjl 214151937Sjkim return (TempName); 215118611Snjl} 216118611Snjl 217118611Snjl 218118611Snjl/******************************************************************************* 219118611Snjl * 220118611Snjl * FUNCTION: TrAmlInitLineNumbers 221118611Snjl * 222151937Sjkim * PARAMETERS: Op - Op to be initialized 223118611Snjl * Neighbor - Op used for initialization values 224118611Snjl * 225118611Snjl * RETURN: None 226118611Snjl * 227118611Snjl * DESCRIPTION: Initialized the various line numbers for a parse node. 228118611Snjl * 229118611Snjl ******************************************************************************/ 230118611Snjl 231151937Sjkimstatic void 232118611SnjlTrAmlInitLineNumbers ( 233118611Snjl ACPI_PARSE_OBJECT *Op, 234118611Snjl ACPI_PARSE_OBJECT *Neighbor) 235118611Snjl{ 236118611Snjl 237118611Snjl Op->Asl.EndLine = Neighbor->Asl.EndLine; 238118611Snjl Op->Asl.EndLogicalLine = Neighbor->Asl.EndLogicalLine; 239118611Snjl Op->Asl.LineNumber = Neighbor->Asl.LineNumber; 240118611Snjl Op->Asl.LogicalByteOffset = Neighbor->Asl.LogicalByteOffset; 241118611Snjl Op->Asl.LogicalLineNumber = Neighbor->Asl.LogicalLineNumber; 242118611Snjl} 243118611Snjl 244118611Snjl 245118611Snjl/******************************************************************************* 246118611Snjl * 247118611Snjl * FUNCTION: TrAmlInitNode 248118611Snjl * 249151937Sjkim * PARAMETERS: Op - Op to be initialized 250118611Snjl * ParseOpcode - Opcode for this node 251118611Snjl * 252118611Snjl * RETURN: None 253118611Snjl * 254118611Snjl * DESCRIPTION: Initialize a node with the parse opcode and opcode name. 255118611Snjl * 256118611Snjl ******************************************************************************/ 257118611Snjl 258151937Sjkimstatic void 259118611SnjlTrAmlInitNode ( 260118611Snjl ACPI_PARSE_OBJECT *Op, 261118611Snjl UINT16 ParseOpcode) 262118611Snjl{ 263118611Snjl 264118611Snjl Op->Asl.ParseOpcode = ParseOpcode; 265118611Snjl UtSetParseOpName (Op); 266118611Snjl} 267118611Snjl 268118611Snjl 269118611Snjl/******************************************************************************* 270118611Snjl * 271118611Snjl * FUNCTION: TrAmlSetSubtreeParent 272118611Snjl * 273151937Sjkim * PARAMETERS: Op - First node in a list of peer nodes 274118611Snjl * Parent - Parent of the subtree 275118611Snjl * 276118611Snjl * RETURN: None 277118611Snjl * 278118611Snjl * DESCRIPTION: Set the parent for all peer nodes in a subtree 279118611Snjl * 280118611Snjl ******************************************************************************/ 281118611Snjl 282151937Sjkimstatic void 283118611SnjlTrAmlSetSubtreeParent ( 284118611Snjl ACPI_PARSE_OBJECT *Op, 285118611Snjl ACPI_PARSE_OBJECT *Parent) 286118611Snjl{ 287118611Snjl ACPI_PARSE_OBJECT *Next; 288118611Snjl 289118611Snjl 290118611Snjl Next = Op; 291118611Snjl while (Next) 292118611Snjl { 293118611Snjl Next->Asl.Parent = Parent; 294118611Snjl Next = Next->Asl.Next; 295118611Snjl } 296118611Snjl} 297118611Snjl 298118611Snjl 299118611Snjl/******************************************************************************* 300118611Snjl * 301118611Snjl * FUNCTION: TrAmlInsertPeer 302118611Snjl * 303151937Sjkim * PARAMETERS: Op - First node in a list of peer nodes 304118611Snjl * NewPeer - Peer node to insert 305118611Snjl * 306118611Snjl * RETURN: None 307118611Snjl * 308118611Snjl * DESCRIPTION: Insert a new peer node into a list of peers. 309118611Snjl * 310118611Snjl ******************************************************************************/ 311118611Snjl 312151937Sjkimstatic void 313118611SnjlTrAmlInsertPeer ( 314118611Snjl ACPI_PARSE_OBJECT *Op, 315118611Snjl ACPI_PARSE_OBJECT *NewPeer) 316118611Snjl{ 317118611Snjl 318118611Snjl NewPeer->Asl.Next = Op->Asl.Next; 319118611Snjl Op->Asl.Next = NewPeer; 320118611Snjl} 321118611Snjl 322118611Snjl 323118611Snjl/******************************************************************************* 324118611Snjl * 325118611Snjl * FUNCTION: TrAmlTransformWalk 326118611Snjl * 327118611Snjl * PARAMETERS: ASL_WALK_CALLBACK 328118611Snjl * 329118611Snjl * RETURN: None 330118611Snjl * 331118611Snjl * DESCRIPTION: Parse tree walk to generate both the AML opcodes and the AML 332118611Snjl * operands. 333118611Snjl * 334118611Snjl ******************************************************************************/ 335118611Snjl 336118611SnjlACPI_STATUS 337118611SnjlTrAmlTransformWalk ( 338118611Snjl ACPI_PARSE_OBJECT *Op, 339118611Snjl UINT32 Level, 340118611Snjl void *Context) 341118611Snjl{ 342118611Snjl 343118611Snjl TrTransformSubtree (Op); 344118611Snjl return (AE_OK); 345118611Snjl} 346118611Snjl 347118611Snjl 348118611Snjl/******************************************************************************* 349118611Snjl * 350118611Snjl * FUNCTION: TrTransformSubtree 351118611Snjl * 352118611Snjl * PARAMETERS: Op - The parent parse node 353118611Snjl * 354118611Snjl * RETURN: None 355118611Snjl * 356118611Snjl * DESCRIPTION: Prepare nodes to be output as AML data and operands. The more 357118611Snjl * complex AML opcodes require processing of the child nodes 358118611Snjl * (arguments/operands). 359118611Snjl * 360118611Snjl ******************************************************************************/ 361118611Snjl 362151937Sjkimstatic void 363118611SnjlTrTransformSubtree ( 364118611Snjl ACPI_PARSE_OBJECT *Op) 365118611Snjl{ 366118611Snjl 367118611Snjl if (Op->Asl.AmlOpcode == AML_RAW_DATA_BYTE) 368118611Snjl { 369118611Snjl return; 370118611Snjl } 371118611Snjl 372118611Snjl switch (Op->Asl.ParseOpcode) 373118611Snjl { 374118611Snjl case PARSEOP_DEFINITIONBLOCK: 375118611Snjl TrDoDefinitionBlock (Op); 376118611Snjl break; 377118611Snjl 378118611Snjl case PARSEOP_SWITCH: 379118611Snjl TrDoSwitch (Op); 380118611Snjl break; 381118611Snjl 382151937Sjkim case PARSEOP_METHOD: 383151937Sjkim 384151937Sjkim /* 385151937Sjkim * TBD: Zero the tempname (_T_x) count. Probably shouldn't be a global, 386151937Sjkim * however 387151937Sjkim */ 388151937Sjkim Gbl_TempCount = 0; 389151937Sjkim break; 390151937Sjkim 391118611Snjl default: 392118611Snjl /* Nothing to do here for other opcodes */ 393118611Snjl break; 394118611Snjl } 395118611Snjl} 396118611Snjl 397118611Snjl 398118611Snjl/******************************************************************************* 399118611Snjl * 400118611Snjl * FUNCTION: TrDoDefinitionBlock 401118611Snjl * 402118611Snjl * PARAMETERS: Op - Parse node 403118611Snjl * 404118611Snjl * RETURN: None 405118611Snjl * 406118611Snjl * DESCRIPTION: Find the end of the definition block and set a global to this 407118611Snjl * node. It is used by the compiler to insert compiler-generated 408118611Snjl * names at the root level of the namespace. 409118611Snjl * 410118611Snjl ******************************************************************************/ 411118611Snjl 412151937Sjkimstatic void 413118611SnjlTrDoDefinitionBlock ( 414118611Snjl ACPI_PARSE_OBJECT *Op) 415118611Snjl{ 416118611Snjl ACPI_PARSE_OBJECT *Next; 417118611Snjl UINT32 i; 418118611Snjl 419118611Snjl 420118611Snjl Next = Op->Asl.Child; 421118611Snjl for (i = 0; i < 5; i++) 422118611Snjl { 423118611Snjl Next = Next->Asl.Next; 424151937Sjkim if (i == 0) 425151937Sjkim { 426151937Sjkim /* 427151937Sjkim * This is the table signature. Only the DSDT can be assumed 428151937Sjkim * to be at the root of the namespace; Therefore, namepath 429151937Sjkim * optimization can only be performed on the DSDT. 430151937Sjkim */ 431167802Sjkim if (!ACPI_COMPARE_NAME (Next->Asl.Value.String, ACPI_SIG_DSDT)) 432151937Sjkim { 433151937Sjkim Gbl_ReferenceOptimizationFlag = FALSE; 434151937Sjkim } 435151937Sjkim } 436118611Snjl } 437118611Snjl 438118611Snjl Gbl_FirstLevelInsertionNode = Next; 439118611Snjl} 440118611Snjl 441118611Snjl 442118611Snjl/******************************************************************************* 443118611Snjl * 444118611Snjl * FUNCTION: TrDoSwitch 445118611Snjl * 446118611Snjl * PARAMETERS: StartNode - Parse node for SWITCH 447118611Snjl * 448118611Snjl * RETURN: None 449118611Snjl * 450118611Snjl * 451118611Snjl * DESCRIPTION: Translate ASL SWITCH statement to if/else pairs. There is 452118611Snjl * no actual AML opcode for SWITCH -- it must be simulated. 453118611Snjl * 454118611Snjl ******************************************************************************/ 455118611Snjl 456151937Sjkimstatic void 457118611SnjlTrDoSwitch ( 458118611Snjl ACPI_PARSE_OBJECT *StartNode) 459118611Snjl{ 460118611Snjl ACPI_PARSE_OBJECT *Next; 461118611Snjl ACPI_PARSE_OBJECT *CaseOp = NULL; 462118611Snjl ACPI_PARSE_OBJECT *CaseBlock = NULL; 463118611Snjl ACPI_PARSE_OBJECT *DefaultOp = NULL; 464118611Snjl ACPI_PARSE_OBJECT *CurrentParentNode; 465118611Snjl ACPI_PARSE_OBJECT *Conditional = NULL; 466118611Snjl ACPI_PARSE_OBJECT *Predicate; 467118611Snjl ACPI_PARSE_OBJECT *Peer; 468118611Snjl ACPI_PARSE_OBJECT *NewOp; 469118611Snjl ACPI_PARSE_OBJECT *NewOp2; 470193529Sjkim ACPI_PARSE_OBJECT *MethodOp; 471199337Sjkim ACPI_PARSE_OBJECT *StoreOp; 472199337Sjkim ACPI_PARSE_OBJECT *BreakOp; 473118611Snjl char *PredicateValueName; 474151937Sjkim UINT16 Index; 475151937Sjkim UINT32 Btype; 476118611Snjl 477118611Snjl 478151937Sjkim /* Start node is the Switch() node */ 479151937Sjkim 480118611Snjl CurrentParentNode = StartNode; 481118611Snjl 482151937Sjkim /* Create a new temp name of the form _T_x */ 483118611Snjl 484151937Sjkim PredicateValueName = TrAmlGetNextTempName (StartNode, &Gbl_TempCount); 485151937Sjkim if (!PredicateValueName) 486151937Sjkim { 487151937Sjkim return; 488151937Sjkim } 489151937Sjkim 490151937Sjkim /* First child is the Switch() predicate */ 491151937Sjkim 492118611Snjl Next = StartNode->Asl.Child; 493118611Snjl 494151937Sjkim /* 495151937Sjkim * Examine the return type of the Switch Value - 496151937Sjkim * must be Integer/Buffer/String 497151937Sjkim */ 498151937Sjkim Index = (UINT16) (Next->Asl.ParseOpcode - ASL_PARSE_OPCODE_BASE); 499151937Sjkim Btype = AslKeywordMapping[Index].AcpiBtype; 500151937Sjkim if ((Btype != ACPI_BTYPE_INTEGER) && 501151937Sjkim (Btype != ACPI_BTYPE_STRING) && 502151937Sjkim (Btype != ACPI_BTYPE_BUFFER)) 503151937Sjkim { 504151937Sjkim AslError (ASL_WARNING, ASL_MSG_SWITCH_TYPE, Next, NULL); 505151937Sjkim Btype = ACPI_BTYPE_INTEGER; 506151937Sjkim } 507151937Sjkim 508118611Snjl /* CASE statements start at next child */ 509118611Snjl 510151937Sjkim Peer = Next->Asl.Next; 511118611Snjl while (Peer) 512118611Snjl { 513118611Snjl Next = Peer; 514118611Snjl Peer = Next->Asl.Next; 515118611Snjl 516118611Snjl if (Next->Asl.ParseOpcode == PARSEOP_CASE) 517118611Snjl { 518118611Snjl if (CaseOp) 519118611Snjl { 520118611Snjl /* Add an ELSE to complete the previous CASE */ 521118611Snjl 522151937Sjkim if (!Conditional) 523151937Sjkim { 524151937Sjkim return; 525151937Sjkim } 526118611Snjl NewOp = TrCreateLeafNode (PARSEOP_ELSE); 527118611Snjl NewOp->Asl.Parent = Conditional->Asl.Parent; 528118611Snjl TrAmlInitLineNumbers (NewOp, NewOp->Asl.Parent); 529118611Snjl 530118611Snjl /* Link ELSE node as a peer to the previous IF */ 531118611Snjl 532118611Snjl TrAmlInsertPeer (Conditional, NewOp); 533118611Snjl CurrentParentNode = NewOp; 534118611Snjl } 535118611Snjl 536118611Snjl CaseOp = Next; 537118611Snjl Conditional = CaseOp; 538118611Snjl CaseBlock = CaseOp->Asl.Child->Asl.Next; 539118611Snjl Conditional->Asl.Child->Asl.Next = NULL; 540138287Smarks Predicate = CaseOp->Asl.Child; 541118611Snjl 542151937Sjkim if ((Predicate->Asl.ParseOpcode == PARSEOP_PACKAGE) || 543151937Sjkim (Predicate->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE)) 544138287Smarks { 545138287Smarks /* 546138287Smarks * Convert the package declaration to this form: 547138287Smarks * 548151937Sjkim * If (LNotEqual (Match (Package(<size>){<data>}, 549151937Sjkim * MEQ, _T_x, MTR, Zero, Zero), Ones)) 550138287Smarks */ 551138287Smarks NewOp2 = TrCreateLeafNode (PARSEOP_MATCHTYPE_MEQ); 552138287Smarks Predicate->Asl.Next = NewOp2; 553138287Smarks TrAmlInitLineNumbers (NewOp2, Conditional); 554118611Snjl 555138287Smarks NewOp = NewOp2; 556138287Smarks NewOp2 = TrCreateValuedLeafNode (PARSEOP_NAMESTRING, 557202771Sjkim (UINT64) ACPI_TO_INTEGER (PredicateValueName)); 558138287Smarks NewOp->Asl.Next = NewOp2; 559138287Smarks TrAmlInitLineNumbers (NewOp2, Predicate); 560118611Snjl 561138287Smarks NewOp = NewOp2; 562138287Smarks NewOp2 = TrCreateLeafNode (PARSEOP_MATCHTYPE_MTR); 563138287Smarks NewOp->Asl.Next = NewOp2; 564138287Smarks TrAmlInitLineNumbers (NewOp2, Predicate); 565118611Snjl 566138287Smarks NewOp = NewOp2; 567138287Smarks NewOp2 = TrCreateLeafNode (PARSEOP_ZERO); 568138287Smarks NewOp->Asl.Next = NewOp2; 569138287Smarks TrAmlInitLineNumbers (NewOp2, Predicate); 570118611Snjl 571138287Smarks NewOp = NewOp2; 572138287Smarks NewOp2 = TrCreateLeafNode (PARSEOP_ZERO); 573138287Smarks NewOp->Asl.Next = NewOp2; 574138287Smarks TrAmlInitLineNumbers (NewOp2, Predicate); 575118611Snjl 576138287Smarks NewOp2 = TrCreateLeafNode (PARSEOP_MATCH); 577138287Smarks NewOp2->Asl.Child = Predicate; /* PARSEOP_PACKAGE */ 578138287Smarks TrAmlInitLineNumbers (NewOp2, Conditional); 579138287Smarks TrAmlSetSubtreeParent (Predicate, NewOp2); 580138287Smarks 581138287Smarks NewOp = NewOp2; 582138287Smarks NewOp2 = TrCreateLeafNode (PARSEOP_ONES); 583138287Smarks NewOp->Asl.Next = NewOp2; 584138287Smarks TrAmlInitLineNumbers (NewOp2, Conditional); 585138287Smarks 586138287Smarks NewOp2 = TrCreateLeafNode (PARSEOP_LEQUAL); 587138287Smarks NewOp2->Asl.Child = NewOp; 588138287Smarks NewOp->Asl.Parent = NewOp2; 589138287Smarks TrAmlInitLineNumbers (NewOp2, Conditional); 590138287Smarks TrAmlSetSubtreeParent (NewOp, NewOp2); 591138287Smarks 592138287Smarks NewOp = NewOp2; 593138287Smarks NewOp2 = TrCreateLeafNode (PARSEOP_LNOT); 594138287Smarks NewOp2->Asl.Child = NewOp; 595138287Smarks NewOp2->Asl.Parent = Conditional; 596138287Smarks NewOp->Asl.Parent = NewOp2; 597138287Smarks TrAmlInitLineNumbers (NewOp2, Conditional); 598138287Smarks 599138287Smarks Conditional->Asl.Child = NewOp2; 600138287Smarks NewOp2->Asl.Next = CaseBlock; 601138287Smarks } 602138287Smarks else 603138287Smarks { 604138287Smarks /* 605151937Sjkim * Integer and Buffer case. 606151937Sjkim * 607151937Sjkim * Change CaseOp() to: If (LEqual (SwitchValue, CaseValue)) {...} 608151937Sjkim * Note: SwitchValue is first to allow the CaseValue to be implicitly 609151937Sjkim * converted to the type of SwitchValue if necessary. 610151937Sjkim * 611138287Smarks * CaseOp->Child is the case value 612138287Smarks * CaseOp->Child->Peer is the beginning of the case block 613138287Smarks */ 614138287Smarks NewOp = TrCreateValuedLeafNode (PARSEOP_NAMESTRING, 615202771Sjkim (UINT64) ACPI_TO_INTEGER (PredicateValueName)); 616151937Sjkim NewOp->Asl.Next = Predicate; 617138287Smarks TrAmlInitLineNumbers (NewOp, Predicate); 618138287Smarks 619138287Smarks NewOp2 = TrCreateLeafNode (PARSEOP_LEQUAL); 620138287Smarks NewOp2->Asl.Parent = Conditional; 621151937Sjkim NewOp2->Asl.Child = NewOp; 622138287Smarks TrAmlInitLineNumbers (NewOp2, Conditional); 623138287Smarks 624151937Sjkim TrAmlSetSubtreeParent (NewOp, NewOp2); 625138287Smarks 626138287Smarks Predicate = NewOp2; 627138287Smarks Predicate->Asl.Next = CaseBlock; 628138287Smarks 629138287Smarks TrAmlSetSubtreeParent (Predicate, Conditional); 630138287Smarks Conditional->Asl.Child = Predicate; 631138287Smarks } 632138287Smarks 633118611Snjl /* Reinitialize the CASE node to an IF node */ 634118611Snjl 635118611Snjl TrAmlInitNode (Conditional, PARSEOP_IF); 636118611Snjl 637118611Snjl /* 638118611Snjl * The first CASE(IF) is not nested under an ELSE. 639118611Snjl * All other CASEs are children of a parent ELSE. 640118611Snjl */ 641118611Snjl if (CurrentParentNode == StartNode) 642118611Snjl { 643199337Sjkim Conditional->Asl.Next = NULL; 644118611Snjl } 645118611Snjl else 646118611Snjl { 647118611Snjl /* 648118611Snjl * The IF is a child of previous IF/ELSE. It 649118611Snjl * is therefore without peer. 650118611Snjl */ 651118611Snjl CurrentParentNode->Asl.Child = Conditional; 652118611Snjl Conditional->Asl.Parent = CurrentParentNode; 653118611Snjl Conditional->Asl.Next = NULL; 654118611Snjl } 655118611Snjl } 656118611Snjl else if (Next->Asl.ParseOpcode == PARSEOP_DEFAULT) 657118611Snjl { 658118611Snjl if (DefaultOp) 659118611Snjl { 660138287Smarks /* 661138287Smarks * More than one Default 662167802Sjkim * (Parser does not catch this, must check here) 663138287Smarks */ 664167802Sjkim AslError (ASL_ERROR, ASL_MSG_MULTIPLE_DEFAULT, Next, NULL); 665118611Snjl } 666167802Sjkim else 667167802Sjkim { 668167802Sjkim /* Save the DEFAULT node for later, after CASEs */ 669118611Snjl 670167802Sjkim DefaultOp = Next; 671167802Sjkim } 672118611Snjl } 673118611Snjl else 674118611Snjl { 675138287Smarks /* Unknown peer opcode */ 676118611Snjl 677209746Sjkim AcpiOsPrintf ("Unknown parse opcode for switch statement: %s (%u)\n", 678118611Snjl Next->Asl.ParseOpName, Next->Asl.ParseOpcode); 679118611Snjl } 680118611Snjl } 681118611Snjl 682151937Sjkim /* Add the default case at the end of the if/else construct */ 683151937Sjkim 684118611Snjl if (DefaultOp) 685118611Snjl { 686138287Smarks /* If no CASE statements, this is an error - see below */ 687138287Smarks 688118611Snjl if (CaseOp) 689118611Snjl { 690138287Smarks /* Convert the DEFAULT node to an ELSE */ 691118611Snjl 692151937Sjkim if (!Conditional) 693151937Sjkim { 694151937Sjkim return; 695151937Sjkim } 696199337Sjkim 697118611Snjl TrAmlInitNode (DefaultOp, PARSEOP_ELSE); 698118611Snjl DefaultOp->Asl.Parent = Conditional->Asl.Parent; 699118611Snjl 700138287Smarks /* Link ELSE node as a peer to the previous IF */ 701138287Smarks 702138287Smarks TrAmlInsertPeer (Conditional, DefaultOp); 703118611Snjl } 704118611Snjl } 705118611Snjl 706138287Smarks if (!CaseOp) 707138287Smarks { 708138287Smarks AslError (ASL_ERROR, ASL_MSG_NO_CASES, StartNode, NULL); 709138287Smarks } 710138287Smarks 711167802Sjkim 712118611Snjl /* 713167802Sjkim * Create a Name(_T_x, ...) statement. This statement must appear at the 714167802Sjkim * method level, in case a loop surrounds the switch statement and could 715167802Sjkim * cause the name to be created twice (error). 716118611Snjl */ 717167802Sjkim 718167802Sjkim /* Create the Name node */ 719167802Sjkim 720151937Sjkim Predicate = StartNode->Asl.Child; 721167802Sjkim NewOp = TrCreateLeafNode (PARSEOP_NAME); 722151937Sjkim 723167802Sjkim /* Find the parent method */ 724151937Sjkim 725167802Sjkim Next = StartNode; 726167802Sjkim while ((Next->Asl.ParseOpcode != PARSEOP_METHOD) && 727167802Sjkim (Next->Asl.ParseOpcode != PARSEOP_DEFINITIONBLOCK)) 728167802Sjkim { 729167802Sjkim Next = Next->Asl.Parent; 730167802Sjkim } 731193529Sjkim MethodOp = Next; 732167802Sjkim 733138287Smarks NewOp->Asl.CompileFlags |= NODE_COMPILER_EMITTED; 734167802Sjkim NewOp->Asl.Parent = Next; 735118611Snjl 736167802Sjkim /* Insert name after the method name and arguments */ 737167802Sjkim 738193529Sjkim Next = Next->Asl.Child; /* Name */ 739193529Sjkim Next = Next->Asl.Next; /* NumArgs */ 740193529Sjkim Next = Next->Asl.Next; /* SerializeRule */ 741167802Sjkim 742193529Sjkim /* 743193529Sjkim * If method is not Serialized, we must make is so, because of the way 744193529Sjkim * that Switch() must be implemented -- we cannot allow multiple threads 745193529Sjkim * to execute this method concurrently since we need to create local 746193529Sjkim * temporary name(s). 747193529Sjkim */ 748193529Sjkim if (Next->Asl.ParseOpcode != PARSEOP_SERIALIZERULE_SERIAL) 749193529Sjkim { 750193529Sjkim AslError (ASL_REMARK, ASL_MSG_SERIALIZED, MethodOp, "Due to use of Switch operator"); 751193529Sjkim Next->Asl.ParseOpcode = PARSEOP_SERIALIZERULE_SERIAL; 752193529Sjkim } 753193529Sjkim 754193529Sjkim Next = Next->Asl.Next; /* SyncLevel */ 755193529Sjkim Next = Next->Asl.Next; /* ReturnType */ 756193529Sjkim Next = Next->Asl.Next; /* ParameterTypes */ 757193529Sjkim 758167802Sjkim TrAmlInsertPeer (Next, NewOp); 759167802Sjkim TrAmlInitLineNumbers (NewOp, Next); 760167802Sjkim 761167802Sjkim /* Create the NameSeg child for the Name node */ 762167802Sjkim 763151937Sjkim NewOp2 = TrCreateValuedLeafNode (PARSEOP_NAMESEG, 764202771Sjkim (UINT64) ACPI_TO_INTEGER (PredicateValueName)); 765151937Sjkim NewOp2->Asl.CompileFlags |= NODE_IS_NAME_DECLARATION; 766118611Snjl NewOp->Asl.Child = NewOp2; 767118611Snjl 768167802Sjkim /* Create the initial value for the Name. Btype was already validated above */ 769118611Snjl 770151937Sjkim switch (Btype) 771151937Sjkim { 772151937Sjkim case ACPI_BTYPE_INTEGER: 773167802Sjkim NewOp2->Asl.Next = TrCreateValuedLeafNode (PARSEOP_ZERO, 774202771Sjkim (UINT64) 0); 775151937Sjkim break; 776118611Snjl 777151937Sjkim case ACPI_BTYPE_STRING: 778151937Sjkim NewOp2->Asl.Next = TrCreateValuedLeafNode (PARSEOP_STRING_LITERAL, 779202771Sjkim (UINT64) ACPI_TO_INTEGER ("")); 780151937Sjkim break; 781118611Snjl 782151937Sjkim case ACPI_BTYPE_BUFFER: 783151937Sjkim (void) TrLinkPeerNode (NewOp2, TrCreateValuedLeafNode (PARSEOP_BUFFER, 784202771Sjkim (UINT64) 0)); 785151937Sjkim Next = NewOp2->Asl.Next; 786151937Sjkim (void) TrLinkChildren (Next, 1, TrCreateValuedLeafNode (PARSEOP_ZERO, 787202771Sjkim (UINT64) 1)); 788151937Sjkim (void) TrLinkPeerNode (Next->Asl.Child, 789202771Sjkim TrCreateValuedLeafNode (PARSEOP_DEFAULT_ARG, (UINT64) 0)); 790151937Sjkim 791151937Sjkim TrAmlSetSubtreeParent (Next->Asl.Child, Next); 792151937Sjkim break; 793151937Sjkim 794151937Sjkim default: 795151937Sjkim break; 796151937Sjkim } 797151937Sjkim 798151937Sjkim TrAmlSetSubtreeParent (NewOp2, NewOp); 799151937Sjkim 800118611Snjl /* 801199337Sjkim * Transform the Switch() into a While(One)-Break node. 802199337Sjkim * And create a Store() node which will be used to save the 803151937Sjkim * Switch() value. The store is of the form: Store (Value, _T_x) 804151937Sjkim * where _T_x is the temp variable. 805118611Snjl */ 806199337Sjkim TrAmlInitNode (StartNode, PARSEOP_WHILE); 807199337Sjkim NewOp = TrCreateLeafNode (PARSEOP_ONE); 808199337Sjkim NewOp->Asl.Next = Predicate->Asl.Next; 809199337Sjkim NewOp->Asl.Parent = StartNode; 810199337Sjkim StartNode->Asl.Child = NewOp; 811118611Snjl 812199337Sjkim /* Create a Store() node */ 813199337Sjkim 814199337Sjkim StoreOp = TrCreateLeafNode (PARSEOP_STORE); 815199337Sjkim StoreOp->Asl.Parent = StartNode; 816199337Sjkim TrAmlInsertPeer (NewOp, StoreOp); 817199337Sjkim 818151937Sjkim /* Complete the Store subtree */ 819151937Sjkim 820199337Sjkim StoreOp->Asl.Child = Predicate; 821199337Sjkim Predicate->Asl.Parent = StoreOp; 822151937Sjkim 823151937Sjkim NewOp = TrCreateValuedLeafNode (PARSEOP_NAMESEG, 824202771Sjkim (UINT64) ACPI_TO_INTEGER (PredicateValueName)); 825199337Sjkim NewOp->Asl.Parent = StoreOp; 826118611Snjl Predicate->Asl.Next = NewOp; 827199337Sjkim 828199337Sjkim /* Create a Break() node and insert it into the end of While() */ 829199337Sjkim 830199337Sjkim Conditional = StartNode->Asl.Child; 831199337Sjkim while (Conditional->Asl.Next) 832199337Sjkim { 833199337Sjkim Conditional = Conditional->Asl.Next; 834199337Sjkim } 835199337Sjkim 836199337Sjkim BreakOp = TrCreateLeafNode (PARSEOP_BREAK); 837199337Sjkim BreakOp->Asl.Parent = StartNode; 838199337Sjkim TrAmlInsertPeer (Conditional, BreakOp); 839118611Snjl} 840118611Snjl 841118611Snjl 842