1 2 /****************************************************************************** 3 * 4 * Module Name: aslfold - Constant folding 5 * $Revision: 1.20 $ 6 * 7 *****************************************************************************/ 8 9 /****************************************************************************** 10 * 11 * 1. Copyright Notice 12 * 13 * Some or all of this work - Copyright (c) 1999 - 2007, Intel Corp. 14 * All rights reserved. 15 * 16 * 2. License 17 * 18 * 2.1. This is your license from Intel Corp. under its intellectual property 19 * rights. You may have additional license terms from the party that provided 20 * you this software, covering your right to use that party's intellectual 21 * property rights. 22 * 23 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 24 * copy of the source code appearing in this file ("Covered Code") an 25 * irrevocable, perpetual, worldwide license under Intel's copyrights in the 26 * base code distributed originally by Intel ("Original Intel Code") to copy, 27 * make derivatives, distribute, use and display any portion of the Covered 28 * Code in any form, with the right to sublicense such rights; and 29 * 30 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 31 * license (with the right to sublicense), under only those claims of Intel 32 * patents that are infringed by the Original Intel Code, to make, use, sell, 33 * offer to sell, and import the Covered Code and derivative works thereof 34 * solely to the minimum extent necessary to exercise the above copyright 35 * license, and in no event shall the patent license extend to any additions 36 * to or modifications of the Original Intel Code. No other license or right 37 * is granted directly or by implication, estoppel or otherwise; 38 * 39 * The above copyright and patent license is granted only if the following 40 * conditions are met: 41 * 42 * 3. Conditions 43 * 44 * 3.1. Redistribution of Source with Rights to Further Distribute Source. 45 * Redistribution of source code of any substantial portion of the Covered 46 * Code or modification with rights to further distribute source must include 47 * the above Copyright Notice, the above License, this list of Conditions, 48 * and the following Disclaimer and Export Compliance provision. In addition, 49 * Licensee must cause all Covered Code to which Licensee contributes to 50 * contain a file documenting the changes Licensee made to create that Covered 51 * Code and the date of any change. Licensee must include in that file the 52 * documentation of any changes made by any predecessor Licensee. Licensee 53 * must include a prominent statement that the modification is derived, 54 * directly or indirectly, from Original Intel Code. 55 * 56 * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 57 * Redistribution of source code of any substantial portion of the Covered 58 * Code or modification without rights to further distribute source must 59 * include the following Disclaimer and Export Compliance provision in the 60 * documentation and/or other materials provided with distribution. In 61 * addition, Licensee may not authorize further sublicense of source of any 62 * portion of the Covered Code, and must include terms to the effect that the 63 * license from Licensee to its licensee is limited to the intellectual 64 * property embodied in the software Licensee provides to its licensee, and 65 * not to intellectual property embodied in modifications its licensee may 66 * make. 67 * 68 * 3.3. Redistribution of Executable. Redistribution in executable form of any 69 * substantial portion of the Covered Code or modification must reproduce the 70 * above Copyright Notice, and the following Disclaimer and Export Compliance 71 * provision in the documentation and/or other materials provided with the 72 * distribution. 73 * 74 * 3.4. Intel retains all right, title, and interest in and to the Original 75 * Intel Code. 76 * 77 * 3.5. Neither the name Intel nor any other trademark owned or controlled by 78 * Intel shall be used in advertising or otherwise to promote the sale, use or 79 * other dealings in products derived from or relating to the Covered Code 80 * without prior written authorization from Intel. 81 * 82 * 4. Disclaimer and Export Compliance 83 * 84 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 85 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 86 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 87 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 88 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 89 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 90 * PARTICULAR PURPOSE. 91 * 92 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 93 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 94 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 95 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 96 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 97 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 98 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 99 * LIMITED REMEDY. 100 * 101 * 4.3. Licensee shall not export, either directly or indirectly, any of this 102 * software or system incorporating such software without first obtaining any 103 * required license or other approval from the U. S. Department of Commerce or 104 * any other agency or department of the United States Government. In the 105 * event Licensee exports any such software from the United States or 106 * re-exports any such software from a foreign destination, Licensee shall 107 * ensure that the distribution and export/re-export of the software is in 108 * compliance with all laws, regulations, orders, or other restrictions of the 109 * U.S. Export Administration Regulations. Licensee agrees that neither it nor 110 * any of its subsidiaries will export/re-export any technical data, process, 111 * software, or service, directly or indirectly, to any country for which the 112 * United States government or any agency thereof requires an export license, 113 * other governmental approval, or letter of assurance, without first obtaining 114 * such license, approval or letter. 115 * 116 *****************************************************************************/ 117 118 119 #include <contrib/dev/acpica/compiler/aslcompiler.h> 120 #include "aslcompiler.y.h" 121 #include <contrib/dev/acpica/amlcode.h> 122 123 #include <contrib/dev/acpica/acdispat.h> 124 #include <contrib/dev/acpica/acparser.h> 125 126 #define _COMPONENT ACPI_COMPILER 127 ACPI_MODULE_NAME ("aslfold") 128 129 /* Local prototypes */ 130 131 static ACPI_STATUS 132 OpcAmlEvaluationWalk1 ( 133 ACPI_PARSE_OBJECT *Op, 134 UINT32 Level, 135 void *Context); 136 137 static ACPI_STATUS 138 OpcAmlEvaluationWalk2 ( 139 ACPI_PARSE_OBJECT *Op, 140 UINT32 Level, 141 void *Context); 142 143 static ACPI_STATUS 144 OpcAmlCheckForConstant ( 145 ACPI_PARSE_OBJECT *Op, 146 UINT32 Level, 147 void *Context); 148 149 150 /******************************************************************************* 151 * 152 * FUNCTION: OpcAmlEvaluationWalk1 153 * 154 * PARAMETERS: ASL_WALK_CALLBACK 155 * 156 * RETURN: Status 157 * 158 * DESCRIPTION: Descending callback for AML execution of constant subtrees 159 * 160 ******************************************************************************/ 161 162 static ACPI_STATUS 163 OpcAmlEvaluationWalk1 ( 164 ACPI_PARSE_OBJECT *Op, 165 UINT32 Level, 166 void *Context) 167 { 168 ACPI_WALK_STATE *WalkState = Context; 169 ACPI_STATUS Status; 170 ACPI_PARSE_OBJECT *OutOp; 171 172 173 WalkState->Op = Op; 174 WalkState->Opcode = Op->Common.AmlOpcode; 175 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 176 177 /* Copy child pointer to Arg for compatibility with Interpreter */ 178 179 if (Op->Asl.Child) 180 { 181 Op->Common.Value.Arg = Op->Asl.Child; 182 } 183 184 /* Call AML dispatcher */ 185 186 Status = AcpiDsExecBeginOp (WalkState, &OutOp); 187 if (ACPI_FAILURE (Status)) 188 { 189 AcpiOsPrintf ("Constant interpretation failed - %s\n", 190 AcpiFormatException (Status)); 191 } 192 193 return (Status); 194 } 195 196 197 /******************************************************************************* 198 * 199 * FUNCTION: OpcAmlEvaluationWalk2 200 * 201 * PARAMETERS: ASL_WALK_CALLBACK 202 * 203 * RETURN: Status 204 * 205 * DESCRIPTION: Ascending callback for AML execution of constant subtrees 206 * 207 ******************************************************************************/ 208 209 static ACPI_STATUS 210 OpcAmlEvaluationWalk2 ( 211 ACPI_PARSE_OBJECT *Op, 212 UINT32 Level, 213 void *Context) 214 { 215 ACPI_WALK_STATE *WalkState = Context; 216 ACPI_STATUS Status; 217 218 219 WalkState->Op = Op; 220 WalkState->Opcode = Op->Common.AmlOpcode; 221 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 222 223 /* Copy child pointer to Arg for compatibility with Interpreter */ 224 225 if (Op->Asl.Child) 226 { 227 Op->Common.Value.Arg = Op->Asl.Child; 228 } 229 230 /* Call AML dispatcher */ 231 232 Status = AcpiDsExecEndOp (WalkState); 233 if (ACPI_FAILURE (Status)) 234 { 235 AcpiOsPrintf ("Constant interpretation failed - %s\n", 236 AcpiFormatException (Status)); 237 } 238 239 return (Status); 240 } 241 242 243 /******************************************************************************* 244 * 245 * FUNCTION: OpcAmlCheckForConstant 246 * 247 * PARAMETERS: ASL_WALK_CALLBACK 248 * 249 * RETURN: Status 250 * 251 * DESCRIPTION: Check one Op for a type 3/4/5 AML opcode 252 * 253 ******************************************************************************/ 254 255 static ACPI_STATUS 256 OpcAmlCheckForConstant ( 257 ACPI_PARSE_OBJECT *Op, 258 UINT32 Level, 259 void *Context) 260 { 261 ACPI_WALK_STATE *WalkState = Context; 262 263 264 WalkState->Op = Op; 265 WalkState->Opcode = Op->Common.AmlOpcode; 266 WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 267 268 DbgPrint (ASL_PARSE_OUTPUT, "[%.4d] Opcode: %12.12s ", 269 Op->Asl.LogicalLineNumber, Op->Asl.ParseOpName); 270 271 if (!(WalkState->OpInfo->Flags & AML_CONSTANT)) 272 { 273 /* The opcode is not a Type 3/4/5 opcode */ 274 275 if (Op->Asl.CompileFlags & NODE_IS_TARGET) 276 { 277 DbgPrint (ASL_PARSE_OUTPUT, 278 "**** Valid Target, cannot reduce ****\n"); 279 } 280 else 281 { 282 DbgPrint (ASL_PARSE_OUTPUT, 283 "**** Not a Type 3/4/5 opcode ****\n"); 284 } 285 286 if (WalkState->WalkType == ACPI_WALK_CONST_OPTIONAL) 287 { 288 /* 289 * We are looking at at normal expression to see if it can be 290 * reduced. It can't. No error 291 */ 292 return (AE_TYPE); 293 } 294 295 /* 296 * This is an expression that MUST reduce to a constant, and it 297 * can't be reduced. This is an error 298 */ 299 if (Op->Asl.CompileFlags & NODE_IS_TARGET) 300 { 301 AslError (ASL_ERROR, ASL_MSG_INVALID_TARGET, Op, 302 Op->Asl.ParseOpName); 303 } 304 else 305 { 306 AslError (ASL_ERROR, ASL_MSG_INVALID_CONSTANT_OP, Op, 307 Op->Asl.ParseOpName); 308 } 309 310 return (AE_TYPE); 311 } 312 313 /* Debug output */ 314 315 DbgPrint (ASL_PARSE_OUTPUT, "TYPE_345"); 316 317 if (Op->Asl.CompileFlags & NODE_IS_TARGET) 318 { 319 DbgPrint (ASL_PARSE_OUTPUT, " TARGET"); 320 } 321 if (Op->Asl.CompileFlags & NODE_IS_TERM_ARG) 322 { 323 DbgPrint (ASL_PARSE_OUTPUT, " TERMARG"); 324 } 325 DbgPrint (ASL_PARSE_OUTPUT, "\n"); 326 327 return (AE_OK); 328 } 329 330 331 /******************************************************************************* 332 * 333 * FUNCTION: OpcAmlConstantWalk 334 * 335 * PARAMETERS: ASL_WALK_CALLBACK 336 * 337 * RETURN: Status 338 * 339 * DESCRIPTION: Reduce an Op and its subtree to a constant if possible 340 * 341 ******************************************************************************/ 342 343 ACPI_STATUS 344 OpcAmlConstantWalk ( 345 ACPI_PARSE_OBJECT *Op, 346 UINT32 Level, 347 void *Context) 348 { 349 ACPI_WALK_STATE *WalkState; 350 ACPI_STATUS Status = AE_OK; 351 ACPI_OPERAND_OBJECT *ObjDesc; 352 ACPI_PARSE_OBJECT *RootOp; 353 ACPI_PARSE_OBJECT *OriginalParentOp; 354 UINT8 WalkType; 355 356 357 /* 358 * Only interested in subtrees that could possibly contain 359 * expressions that can be evaluated at this time 360 */ 361 if ((!(Op->Asl.CompileFlags & NODE_COMPILE_TIME_CONST)) || 362 (Op->Asl.CompileFlags & NODE_IS_TARGET)) 363 { 364 return (AE_OK); 365 } 366 367 /* Set the walk type based on the reduction used for this op */ 368 369 if (Op->Asl.CompileFlags & NODE_IS_TERM_ARG) 370 { 371 /* Op is a TermArg, constant folding is merely optional */ 372 373 if (!Gbl_FoldConstants) 374 { 375 return (AE_CTRL_DEPTH); 376 } 377 378 WalkType = ACPI_WALK_CONST_OPTIONAL; 379 } 380 else 381 { 382 /* Op is a DataObject, the expression MUST reduced to a constant */ 383 384 WalkType = ACPI_WALK_CONST_REQUIRED; 385 } 386 387 /* Create a new walk state */ 388 389 WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL); 390 if (!WalkState) 391 { 392 return AE_NO_MEMORY; 393 } 394 395 WalkState->NextOp = NULL; 396 WalkState->Params = NULL; 397 WalkState->CallerReturnDesc = &ObjDesc; 398 WalkState->WalkType = WalkType; 399 400 /* 401 * Examine the entire subtree -- all nodes must be constants 402 * or type 3/4/5 opcodes 403 */ 404 Status = TrWalkParseTree (Op, ASL_WALK_VISIT_DOWNWARD, 405 OpcAmlCheckForConstant, NULL, WalkState); 406 407 /* 408 * Did we find an entire subtree that contains all constants and type 3/4/5 409 * opcodes? (Only AE_OK or AE_TYPE returned from above) 410 */ 411 if (Status == AE_TYPE) 412 { 413 /* Subtree cannot be reduced to a constant */ 414 415 if (WalkState->WalkType == ACPI_WALK_CONST_OPTIONAL) 416 { 417 AcpiDsDeleteWalkState (WalkState); 418 return (AE_OK); 419 } 420 421 /* Don't descend any further, and use a default "constant" value */ 422 423 Status = AE_CTRL_DEPTH; 424 } 425 else 426 { 427 /* Subtree can be reduced */ 428 429 /* Allocate a new temporary root for this subtree */ 430 431 RootOp = TrAllocateNode (PARSEOP_INTEGER); 432 if (!RootOp) 433 { 434 return (AE_NO_MEMORY); 435 } 436 437 RootOp->Common.AmlOpcode = AML_INT_EVAL_SUBTREE_OP; 438 439 OriginalParentOp = Op->Common.Parent; 440 Op->Common.Parent = RootOp; 441 442 /* Hand off the subtree to the AML interpreter */ 443 444 Status = TrWalkParseTree (Op, ASL_WALK_VISIT_TWICE, 445 OpcAmlEvaluationWalk1, OpcAmlEvaluationWalk2, WalkState); 446 Op->Common.Parent = OriginalParentOp; 447 448 /* TBD: we really *should* release the RootOp node */ 449 450 if (ACPI_SUCCESS (Status)) 451 { 452 TotalFolds++; 453 454 /* Get the final result */ 455 456 Status = AcpiDsResultPop (&ObjDesc, WalkState); 457 } 458 } 459 460 if (ACPI_FAILURE (Status)) 461 { 462 /* We could not resolve the subtree for some reason */ 463 464 AslCoreSubsystemError (Op, Status, 465 "Failure during constant evaluation", FALSE); 466 AslError (ASL_ERROR, ASL_MSG_CONSTANT_EVALUATION, Op, 467 Op->Asl.ParseOpName); 468 469 /* Set the subtree value to ZERO anyway. Eliminates further errors */ 470 471 Op->Asl.ParseOpcode = PARSEOP_INTEGER; 472 Op->Common.Value.Integer = 0; 473 OpcSetOptimalIntegerSize (Op); 474 } 475 else 476 { 477 AslError (ASL_OPTIMIZATION, ASL_MSG_CONSTANT_FOLDED, Op, 478 Op->Asl.ParseOpName); 479 480 /* 481 * Because we know we executed type 3/4/5 opcodes above, we know that 482 * the result must be either an Integer, String, or Buffer. 483 */ 484 switch (ACPI_GET_OBJECT_TYPE (ObjDesc)) 485 { 486 case ACPI_TYPE_INTEGER: 487 488 Op->Asl.ParseOpcode = PARSEOP_INTEGER; 489 Op->Common.Value.Integer = ObjDesc->Integer.Value; 490 OpcSetOptimalIntegerSize (Op); 491 492 DbgPrint (ASL_PARSE_OUTPUT, 493 "Constant expression reduced to (INTEGER) %8.8X%8.8X\n", 494 ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value)); 495 break; 496 497 498 case ACPI_TYPE_STRING: 499 500 Op->Asl.ParseOpcode = PARSEOP_STRING_LITERAL; 501 Op->Common.AmlOpcode = AML_STRING_OP; 502 Op->Asl.AmlLength = ACPI_STRLEN (ObjDesc->String.Pointer) + 1; 503 Op->Common.Value.String = ObjDesc->String.Pointer; 504 505 DbgPrint (ASL_PARSE_OUTPUT, 506 "Constant expression reduced to (STRING) %s\n", 507 Op->Common.Value.String); 508 509 break; 510 511 512 case ACPI_TYPE_BUFFER: 513 514 Op->Asl.ParseOpcode = PARSEOP_BUFFER; 515 Op->Common.AmlOpcode = AML_BUFFER_OP; 516 Op->Asl.CompileFlags = NODE_AML_PACKAGE; 517 UtSetParseOpName (Op); 518 519 /* Child node is the buffer length */ 520 521 RootOp = TrAllocateNode (PARSEOP_INTEGER); 522 523 RootOp->Asl.AmlOpcode = AML_DWORD_OP; 524 RootOp->Asl.Value.Integer = ObjDesc->Buffer.Length; 525 RootOp->Asl.Parent = Op; 526 527 (void) OpcSetOptimalIntegerSize (RootOp); 528 529 Op->Asl.Child = RootOp; 530 Op = RootOp; 531 UtSetParseOpName (Op); 532 533 /* Peer to the child is the raw buffer data */ 534 535 RootOp = TrAllocateNode (PARSEOP_RAW_DATA); 536 RootOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER; 537 RootOp->Asl.AmlLength = ObjDesc->Buffer.Length; 538 RootOp->Asl.Value.String = (char *) ObjDesc->Buffer.Pointer; 539 RootOp->Asl.Parent = Op->Asl.Parent; 540 541 Op->Asl.Next = RootOp; 542 Op = RootOp; 543 544 DbgPrint (ASL_PARSE_OUTPUT, 545 "Constant expression reduced to (BUFFER) length %X\n", 546 ObjDesc->Buffer.Length); 547 break; 548 549 550 default: 551 printf ("Unsupported return type: %s\n", 552 AcpiUtGetObjectTypeName (ObjDesc)); 553 break; 554 } 555 } 556 557 UtSetParseOpName (Op); 558 Op->Asl.Child = NULL; 559 560 AcpiDsDeleteWalkState (WalkState); 561 562 return (AE_CTRL_DEPTH); 563 } 564 565