aslwalks.c revision 218590
1/****************************************************************************** 2 * 3 * Module Name: aslwalks.c - major analytical parse tree walks 4 * 5 *****************************************************************************/ 6 7/* 8 * Copyright (C) 2000 - 2011, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 45#include <contrib/dev/acpica/compiler/aslcompiler.h> 46#include "aslcompiler.y.h" 47#include <contrib/dev/acpica/include/acparser.h> 48#include <contrib/dev/acpica/include/amlcode.h> 49 50 51#define _COMPONENT ACPI_COMPILER 52 ACPI_MODULE_NAME ("aslwalks") 53 54 55/******************************************************************************* 56 * 57 * FUNCTION: AnMethodAnalysisWalkBegin 58 * 59 * PARAMETERS: ASL_WALK_CALLBACK 60 * 61 * RETURN: Status 62 * 63 * DESCRIPTION: Descending callback for the analysis walk. Check methods for: 64 * 1) Initialized local variables 65 * 2) Valid arguments 66 * 3) Return types 67 * 68 ******************************************************************************/ 69 70ACPI_STATUS 71AnMethodAnalysisWalkBegin ( 72 ACPI_PARSE_OBJECT *Op, 73 UINT32 Level, 74 void *Context) 75{ 76 ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context; 77 ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack; 78 ACPI_PARSE_OBJECT *Next; 79 UINT32 RegisterNumber; 80 UINT32 i; 81 char LocalName[] = "Local0"; 82 char ArgName[] = "Arg0"; 83 ACPI_PARSE_OBJECT *ArgNode; 84 ACPI_PARSE_OBJECT *NextType; 85 ACPI_PARSE_OBJECT *NextParamType; 86 UINT8 ActualArgs = 0; 87 88 89 switch (Op->Asl.ParseOpcode) 90 { 91 case PARSEOP_METHOD: 92 93 TotalMethods++; 94 95 /* Create and init method info */ 96 97 MethodInfo = UtLocalCalloc (sizeof (ASL_METHOD_INFO)); 98 MethodInfo->Next = WalkInfo->MethodStack; 99 MethodInfo->Op = Op; 100 101 WalkInfo->MethodStack = MethodInfo; 102 103 /* Get the name node, ignored here */ 104 105 Next = Op->Asl.Child; 106 107 /* Get the NumArguments node */ 108 109 Next = Next->Asl.Next; 110 MethodInfo->NumArguments = (UINT8) 111 (((UINT8) Next->Asl.Value.Integer) & 0x07); 112 113 /* Get the SerializeRule and SyncLevel nodes, ignored here */ 114 115 Next = Next->Asl.Next; 116 Next = Next->Asl.Next; 117 ArgNode = Next; 118 119 /* Get the ReturnType node */ 120 121 Next = Next->Asl.Next; 122 123 NextType = Next->Asl.Child; 124 while (NextType) 125 { 126 /* Get and map each of the ReturnTypes */ 127 128 MethodInfo->ValidReturnTypes |= AnMapObjTypeToBtype (NextType); 129 NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 130 NextType = NextType->Asl.Next; 131 } 132 133 /* Get the ParameterType node */ 134 135 Next = Next->Asl.Next; 136 137 NextType = Next->Asl.Child; 138 while (NextType) 139 { 140 if (NextType->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) 141 { 142 NextParamType = NextType->Asl.Child; 143 while (NextParamType) 144 { 145 MethodInfo->ValidArgTypes[ActualArgs] |= AnMapObjTypeToBtype (NextParamType); 146 NextParamType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 147 NextParamType = NextParamType->Asl.Next; 148 } 149 } 150 else 151 { 152 MethodInfo->ValidArgTypes[ActualArgs] = 153 AnMapObjTypeToBtype (NextType); 154 NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 155 ActualArgs++; 156 } 157 158 NextType = NextType->Asl.Next; 159 } 160 161 if ((MethodInfo->NumArguments) && 162 (MethodInfo->NumArguments != ActualArgs)) 163 { 164 /* error: Param list did not match number of args */ 165 } 166 167 /* Allow numarguments == 0 for Function() */ 168 169 if ((!MethodInfo->NumArguments) && (ActualArgs)) 170 { 171 MethodInfo->NumArguments = ActualArgs; 172 ArgNode->Asl.Value.Integer |= ActualArgs; 173 } 174 175 /* 176 * Actual arguments are initialized at method entry. 177 * All other ArgX "registers" can be used as locals, so we 178 * track their initialization. 179 */ 180 for (i = 0; i < MethodInfo->NumArguments; i++) 181 { 182 MethodInfo->ArgInitialized[i] = TRUE; 183 } 184 break; 185 186 187 case PARSEOP_METHODCALL: 188 189 if (MethodInfo && 190 (Op->Asl.Node == MethodInfo->Op->Asl.Node)) 191 { 192 AslError (ASL_REMARK, ASL_MSG_RECURSION, Op, Op->Asl.ExternalName); 193 } 194 break; 195 196 197 case PARSEOP_LOCAL0: 198 case PARSEOP_LOCAL1: 199 case PARSEOP_LOCAL2: 200 case PARSEOP_LOCAL3: 201 case PARSEOP_LOCAL4: 202 case PARSEOP_LOCAL5: 203 case PARSEOP_LOCAL6: 204 case PARSEOP_LOCAL7: 205 206 if (!MethodInfo) 207 { 208 /* 209 * Local was used outside a control method, or there was an error 210 * in the method declaration. 211 */ 212 AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName); 213 return (AE_ERROR); 214 } 215 216 RegisterNumber = (Op->Asl.AmlOpcode & 0x000F); 217 218 /* 219 * If the local is being used as a target, mark the local 220 * initialized 221 */ 222 if (Op->Asl.CompileFlags & NODE_IS_TARGET) 223 { 224 MethodInfo->LocalInitialized[RegisterNumber] = TRUE; 225 } 226 227 /* 228 * Otherwise, this is a reference, check if the local 229 * has been previously initialized. 230 * 231 * The only operator that accepts an uninitialized value is ObjectType() 232 */ 233 else if ((!MethodInfo->LocalInitialized[RegisterNumber]) && 234 (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE)) 235 { 236 LocalName[strlen (LocalName) -1] = (char) (RegisterNumber + 0x30); 237 AslError (ASL_ERROR, ASL_MSG_LOCAL_INIT, Op, LocalName); 238 } 239 break; 240 241 242 case PARSEOP_ARG0: 243 case PARSEOP_ARG1: 244 case PARSEOP_ARG2: 245 case PARSEOP_ARG3: 246 case PARSEOP_ARG4: 247 case PARSEOP_ARG5: 248 case PARSEOP_ARG6: 249 250 if (!MethodInfo) 251 { 252 /* 253 * Arg was used outside a control method, or there was an error 254 * in the method declaration. 255 */ 256 AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName); 257 return (AE_ERROR); 258 } 259 260 RegisterNumber = (Op->Asl.AmlOpcode & 0x000F) - 8; 261 ArgName[strlen (ArgName) -1] = (char) (RegisterNumber + 0x30); 262 263 /* 264 * If the Arg is being used as a target, mark the local 265 * initialized 266 */ 267 if (Op->Asl.CompileFlags & NODE_IS_TARGET) 268 { 269 MethodInfo->ArgInitialized[RegisterNumber] = TRUE; 270 } 271 272 /* 273 * Otherwise, this is a reference, check if the Arg 274 * has been previously initialized. 275 * 276 * The only operator that accepts an uninitialized value is ObjectType() 277 */ 278 else if ((!MethodInfo->ArgInitialized[RegisterNumber]) && 279 (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE)) 280 { 281 AslError (ASL_ERROR, ASL_MSG_ARG_INIT, Op, ArgName); 282 } 283 284 /* Flag this arg if it is not a "real" argument to the method */ 285 286 if (RegisterNumber >= MethodInfo->NumArguments) 287 { 288 AslError (ASL_REMARK, ASL_MSG_NOT_PARAMETER, Op, ArgName); 289 } 290 break; 291 292 293 case PARSEOP_RETURN: 294 295 if (!MethodInfo) 296 { 297 /* 298 * Probably was an error in the method declaration, 299 * no additional error here 300 */ 301 ACPI_WARNING ((AE_INFO, "%p, No parent method", Op)); 302 return (AE_ERROR); 303 } 304 305 /* Child indicates a return value */ 306 307 if ((Op->Asl.Child) && 308 (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)) 309 { 310 MethodInfo->NumReturnWithValue++; 311 } 312 else 313 { 314 MethodInfo->NumReturnNoValue++; 315 } 316 break; 317 318 319 case PARSEOP_BREAK: 320 case PARSEOP_CONTINUE: 321 322 Next = Op->Asl.Parent; 323 while (Next) 324 { 325 if (Next->Asl.ParseOpcode == PARSEOP_WHILE) 326 { 327 break; 328 } 329 Next = Next->Asl.Parent; 330 } 331 332 if (!Next) 333 { 334 AslError (ASL_ERROR, ASL_MSG_NO_WHILE, Op, NULL); 335 } 336 break; 337 338 339 case PARSEOP_STALL: 340 341 /* We can range check if the argument is an integer */ 342 343 if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) && 344 (Op->Asl.Child->Asl.Value.Integer > ACPI_UINT8_MAX)) 345 { 346 AslError (ASL_ERROR, ASL_MSG_INVALID_TIME, Op, NULL); 347 } 348 break; 349 350 351 case PARSEOP_DEVICE: 352 case PARSEOP_EVENT: 353 case PARSEOP_MUTEX: 354 case PARSEOP_OPERATIONREGION: 355 case PARSEOP_POWERRESOURCE: 356 case PARSEOP_PROCESSOR: 357 case PARSEOP_THERMALZONE: 358 359 /* 360 * The first operand is a name to be created in the namespace. 361 * Check against the reserved list. 362 */ 363 i = ApCheckForPredefinedName (Op, Op->Asl.NameSeg); 364 if (i < ACPI_VALID_RESERVED_NAME_MAX) 365 { 366 AslError (ASL_ERROR, ASL_MSG_RESERVED_USE, Op, Op->Asl.ExternalName); 367 } 368 break; 369 370 371 case PARSEOP_NAME: 372 373 /* Typecheck any predefined names statically defined with Name() */ 374 375 ApCheckForPredefinedObject (Op, Op->Asl.NameSeg); 376 377 /* Special typechecking for _HID */ 378 379 if (!ACPI_STRCMP (METHOD_NAME__HID, Op->Asl.NameSeg)) 380 { 381 Next = Op->Asl.Child->Asl.Next; 382 AnCheckId (Next, ASL_TYPE_HID); 383 } 384 385 /* Special typechecking for _CID */ 386 387 else if (!ACPI_STRCMP (METHOD_NAME__CID, Op->Asl.NameSeg)) 388 { 389 Next = Op->Asl.Child->Asl.Next; 390 391 if ((Next->Asl.ParseOpcode == PARSEOP_PACKAGE) || 392 (Next->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE)) 393 { 394 Next = Next->Asl.Child; 395 while (Next) 396 { 397 AnCheckId (Next, ASL_TYPE_CID); 398 Next = Next->Asl.Next; 399 } 400 } 401 else 402 { 403 AnCheckId (Next, ASL_TYPE_CID); 404 } 405 } 406 break; 407 408 409 default: 410 break; 411 } 412 413 return (AE_OK); 414} 415 416 417/******************************************************************************* 418 * 419 * FUNCTION: AnMethodAnalysisWalkEnd 420 * 421 * PARAMETERS: ASL_WALK_CALLBACK 422 * 423 * RETURN: Status 424 * 425 * DESCRIPTION: Ascending callback for analysis walk. Complete method 426 * return analysis. 427 * 428 ******************************************************************************/ 429 430ACPI_STATUS 431AnMethodAnalysisWalkEnd ( 432 ACPI_PARSE_OBJECT *Op, 433 UINT32 Level, 434 void *Context) 435{ 436 ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context; 437 ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack; 438 439 440 switch (Op->Asl.ParseOpcode) 441 { 442 case PARSEOP_METHOD: 443 case PARSEOP_RETURN: 444 if (!MethodInfo) 445 { 446 printf ("No method info for method! [%s]\n", Op->Asl.Namepath); 447 AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op, 448 "No method info for this method"); 449 450 CmCleanupAndExit (); 451 return (AE_AML_INTERNAL); 452 } 453 break; 454 455 default: 456 break; 457 } 458 459 switch (Op->Asl.ParseOpcode) 460 { 461 case PARSEOP_METHOD: 462 463 WalkInfo->MethodStack = MethodInfo->Next; 464 465 /* 466 * Check if there is no return statement at the end of the 467 * method AND we can actually get there -- i.e., the execution 468 * of the method can possibly terminate without a return statement. 469 */ 470 if ((!AnLastStatementIsReturn (Op)) && 471 (!(Op->Asl.CompileFlags & NODE_HAS_NO_EXIT))) 472 { 473 /* 474 * No return statement, and execution can possibly exit 475 * via this path. This is equivalent to Return () 476 */ 477 MethodInfo->NumReturnNoValue++; 478 } 479 480 /* 481 * Check for case where some return statements have a return value 482 * and some do not. Exit without a return statement is a return with 483 * no value 484 */ 485 if (MethodInfo->NumReturnNoValue && 486 MethodInfo->NumReturnWithValue) 487 { 488 AslError (ASL_WARNING, ASL_MSG_RETURN_TYPES, Op, 489 Op->Asl.ExternalName); 490 } 491 492 /* 493 * If there are any RETURN() statements with no value, or there is a 494 * control path that allows the method to exit without a return value, 495 * we mark the method as a method that does not return a value. This 496 * knowledge can be used to check method invocations that expect a 497 * returned value. 498 */ 499 if (MethodInfo->NumReturnNoValue) 500 { 501 if (MethodInfo->NumReturnWithValue) 502 { 503 Op->Asl.CompileFlags |= NODE_METHOD_SOME_NO_RETVAL; 504 } 505 else 506 { 507 Op->Asl.CompileFlags |= NODE_METHOD_NO_RETVAL; 508 } 509 } 510 511 /* 512 * Check predefined method names for correct return behavior 513 * and correct number of arguments 514 */ 515 ApCheckForPredefinedMethod (Op, MethodInfo); 516 517 /* Special check for two names like _L01 and _E01 in same scope */ 518 519 ApCheckForGpeNameConflict (Op); 520 ACPI_FREE (MethodInfo); 521 break; 522 523 524 case PARSEOP_NAME: 525 526 /* Special check for two names like _L01 and _E01 in same scope */ 527 528 ApCheckForGpeNameConflict (Op); 529 break; 530 531 532 case PARSEOP_RETURN: 533 534 /* 535 * If the parent is a predefined method name, attempt to typecheck 536 * the return value. Only static types can be validated. 537 */ 538 ApCheckPredefinedReturnValue (Op, MethodInfo); 539 540 /* 541 * The parent block does not "exit" and continue execution -- the 542 * method is terminated here with the Return() statement. 543 */ 544 Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; 545 546 /* Used in the "typing" pass later */ 547 548 Op->Asl.ParentMethod = MethodInfo->Op; 549 550 /* 551 * If there is a peer node after the return statement, then this 552 * node is unreachable code -- i.e., it won't be executed because of 553 * the preceeding Return() statement. 554 */ 555 if (Op->Asl.Next) 556 { 557 AslError (ASL_WARNING, ASL_MSG_UNREACHABLE_CODE, Op->Asl.Next, NULL); 558 } 559 break; 560 561 562 case PARSEOP_IF: 563 564 if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && 565 (Op->Asl.Next) && 566 (Op->Asl.Next->Asl.ParseOpcode == PARSEOP_ELSE)) 567 { 568 /* 569 * This IF has a corresponding ELSE. The IF block has no exit, 570 * (it contains an unconditional Return) 571 * mark the ELSE block to remember this fact. 572 */ 573 Op->Asl.Next->Asl.CompileFlags |= NODE_IF_HAS_NO_EXIT; 574 } 575 break; 576 577 578 case PARSEOP_ELSE: 579 580 if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && 581 (Op->Asl.CompileFlags & NODE_IF_HAS_NO_EXIT)) 582 { 583 /* 584 * This ELSE block has no exit and the corresponding IF block 585 * has no exit either. Therefore, the parent node has no exit. 586 */ 587 Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; 588 } 589 break; 590 591 592 default: 593 594 if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && 595 (Op->Asl.Parent)) 596 { 597 /* If this node has no exit, then the parent has no exit either */ 598 599 Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; 600 } 601 break; 602 } 603 604 return (AE_OK); 605} 606 607 608/******************************************************************************* 609 * 610 * FUNCTION: AnMethodTypingWalkEnd 611 * 612 * PARAMETERS: ASL_WALK_CALLBACK 613 * 614 * RETURN: Status 615 * 616 * DESCRIPTION: Ascending callback for typing walk. Complete the method 617 * return analysis. Check methods for: 618 * 1) Initialized local variables 619 * 2) Valid arguments 620 * 3) Return types 621 * 622 ******************************************************************************/ 623 624ACPI_STATUS 625AnMethodTypingWalkEnd ( 626 ACPI_PARSE_OBJECT *Op, 627 UINT32 Level, 628 void *Context) 629{ 630 UINT32 ThisNodeBtype; 631 632 633 switch (Op->Asl.ParseOpcode) 634 { 635 case PARSEOP_METHOD: 636 637 Op->Asl.CompileFlags |= NODE_METHOD_TYPED; 638 break; 639 640 case PARSEOP_RETURN: 641 642 if ((Op->Asl.Child) && 643 (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)) 644 { 645 ThisNodeBtype = AnGetBtype (Op->Asl.Child); 646 647 if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_METHODCALL) && 648 (ThisNodeBtype == (ACPI_UINT32_MAX -1))) 649 { 650 /* 651 * The called method is untyped at this time (typically a 652 * forward reference). 653 * 654 * Check for a recursive method call first. 655 */ 656 if (Op->Asl.ParentMethod != Op->Asl.Child->Asl.Node->Op) 657 { 658 /* We must type the method here */ 659 660 TrWalkParseTree (Op->Asl.Child->Asl.Node->Op, 661 ASL_WALK_VISIT_UPWARD, NULL, 662 AnMethodTypingWalkEnd, NULL); 663 664 ThisNodeBtype = AnGetBtype (Op->Asl.Child); 665 } 666 } 667 668 /* Returns a value, save the value type */ 669 670 if (Op->Asl.ParentMethod) 671 { 672 Op->Asl.ParentMethod->Asl.AcpiBtype |= ThisNodeBtype; 673 } 674 } 675 break; 676 677 default: 678 break; 679 } 680 681 return (AE_OK); 682} 683 684 685/******************************************************************************* 686 * 687 * FUNCTION: AnOperandTypecheckWalkEnd 688 * 689 * PARAMETERS: ASL_WALK_CALLBACK 690 * 691 * RETURN: Status 692 * 693 * DESCRIPTION: Ascending callback for analysis walk. Complete method 694 * return analysis. 695 * 696 ******************************************************************************/ 697 698ACPI_STATUS 699AnOperandTypecheckWalkEnd ( 700 ACPI_PARSE_OBJECT *Op, 701 UINT32 Level, 702 void *Context) 703{ 704 const ACPI_OPCODE_INFO *OpInfo; 705 UINT32 RuntimeArgTypes; 706 UINT32 RuntimeArgTypes2; 707 UINT32 RequiredBtypes; 708 UINT32 ThisNodeBtype; 709 UINT32 CommonBtypes; 710 UINT32 OpcodeClass; 711 ACPI_PARSE_OBJECT *ArgOp; 712 UINT32 ArgType; 713 714 715 switch (Op->Asl.AmlOpcode) 716 { 717 case AML_RAW_DATA_BYTE: 718 case AML_RAW_DATA_WORD: 719 case AML_RAW_DATA_DWORD: 720 case AML_RAW_DATA_QWORD: 721 case AML_RAW_DATA_BUFFER: 722 case AML_RAW_DATA_CHAIN: 723 case AML_PACKAGE_LENGTH: 724 case AML_UNASSIGNED_OPCODE: 725 case AML_DEFAULT_ARG_OP: 726 727 /* Ignore the internal (compiler-only) AML opcodes */ 728 729 return (AE_OK); 730 731 default: 732 break; 733 } 734 735 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 736 if (!OpInfo) 737 { 738 return (AE_OK); 739 } 740 741 ArgOp = Op->Asl.Child; 742 RuntimeArgTypes = OpInfo->RuntimeArgs; 743 OpcodeClass = OpInfo->Class; 744 745#ifdef ASL_ERROR_NAMED_OBJECT_IN_WHILE 746 /* 747 * Update 11/2008: In practice, we can't perform this check. A simple 748 * analysis is not sufficient. Also, it can cause errors when compiling 749 * disassembled code because of the way Switch operators are implemented 750 * (a While(One) loop with a named temp variable created within.) 751 */ 752 753 /* 754 * If we are creating a named object, check if we are within a while loop 755 * by checking if the parent is a WHILE op. This is a simple analysis, but 756 * probably sufficient for many cases. 757 * 758 * Allow Scope(), Buffer(), and Package(). 759 */ 760 if (((OpcodeClass == AML_CLASS_NAMED_OBJECT) && (Op->Asl.AmlOpcode != AML_SCOPE_OP)) || 761 ((OpcodeClass == AML_CLASS_CREATE) && (OpInfo->Flags & AML_NSNODE))) 762 { 763 if (Op->Asl.Parent->Asl.AmlOpcode == AML_WHILE_OP) 764 { 765 AslError (ASL_ERROR, ASL_MSG_NAMED_OBJECT_IN_WHILE, Op, NULL); 766 } 767 } 768#endif 769 770 /* 771 * Special case for control opcodes IF/RETURN/WHILE since they 772 * have no runtime arg list (at this time) 773 */ 774 switch (Op->Asl.AmlOpcode) 775 { 776 case AML_IF_OP: 777 case AML_WHILE_OP: 778 case AML_RETURN_OP: 779 780 if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) 781 { 782 /* Check for an internal method */ 783 784 if (AnIsInternalMethod (ArgOp)) 785 { 786 return (AE_OK); 787 } 788 789 /* The lone arg is a method call, check it */ 790 791 RequiredBtypes = AnMapArgTypeToBtype (ARGI_INTEGER); 792 if (Op->Asl.AmlOpcode == AML_RETURN_OP) 793 { 794 RequiredBtypes = 0xFFFFFFFF; 795 } 796 797 ThisNodeBtype = AnGetBtype (ArgOp); 798 if (ThisNodeBtype == ACPI_UINT32_MAX) 799 { 800 return (AE_OK); 801 } 802 AnCheckMethodReturnValue (Op, OpInfo, ArgOp, 803 RequiredBtypes, ThisNodeBtype); 804 } 805 return (AE_OK); 806 807 default: 808 break; 809 } 810 811 /* Ignore the non-executable opcodes */ 812 813 if (RuntimeArgTypes == ARGI_INVALID_OPCODE) 814 { 815 return (AE_OK); 816 } 817 818 switch (OpcodeClass) 819 { 820 case AML_CLASS_EXECUTE: 821 case AML_CLASS_CREATE: 822 case AML_CLASS_CONTROL: 823 case AML_CLASS_RETURN_VALUE: 824 825 /* TBD: Change class or fix typechecking for these */ 826 827 if ((Op->Asl.AmlOpcode == AML_BUFFER_OP) || 828 (Op->Asl.AmlOpcode == AML_PACKAGE_OP) || 829 (Op->Asl.AmlOpcode == AML_VAR_PACKAGE_OP)) 830 { 831 break; 832 } 833 834 /* Reverse the runtime argument list */ 835 836 RuntimeArgTypes2 = 0; 837 while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes))) 838 { 839 RuntimeArgTypes2 <<= ARG_TYPE_WIDTH; 840 RuntimeArgTypes2 |= ArgType; 841 INCREMENT_ARG_LIST (RuntimeArgTypes); 842 } 843 844 while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2))) 845 { 846 RequiredBtypes = AnMapArgTypeToBtype (ArgType); 847 848 ThisNodeBtype = AnGetBtype (ArgOp); 849 if (ThisNodeBtype == ACPI_UINT32_MAX) 850 { 851 goto NextArgument; 852 } 853 854 /* Examine the arg based on the required type of the arg */ 855 856 switch (ArgType) 857 { 858 case ARGI_TARGETREF: 859 860 if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO) 861 { 862 /* ZERO is the placeholder for "don't store result" */ 863 864 ThisNodeBtype = RequiredBtypes; 865 break; 866 } 867 868 if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER) 869 { 870 /* 871 * This is the case where an original reference to a resource 872 * descriptor field has been replaced by an (Integer) offset. 873 * These named fields are supported at compile-time only; 874 * the names are not passed to the interpreter (via the AML). 875 */ 876 if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) || 877 (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE)) 878 { 879 AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD, ArgOp, NULL); 880 } 881 else 882 { 883 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, NULL); 884 } 885 break; 886 } 887 888 if ((ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) || 889 (ArgOp->Asl.ParseOpcode == PARSEOP_DEREFOF)) 890 { 891 break; 892 } 893 894 ThisNodeBtype = RequiredBtypes; 895 break; 896 897 898 case ARGI_REFERENCE: /* References */ 899 case ARGI_INTEGER_REF: 900 case ARGI_OBJECT_REF: 901 case ARGI_DEVICE_REF: 902 903 switch (ArgOp->Asl.ParseOpcode) 904 { 905 case PARSEOP_LOCAL0: 906 case PARSEOP_LOCAL1: 907 case PARSEOP_LOCAL2: 908 case PARSEOP_LOCAL3: 909 case PARSEOP_LOCAL4: 910 case PARSEOP_LOCAL5: 911 case PARSEOP_LOCAL6: 912 case PARSEOP_LOCAL7: 913 914 /* TBD: implement analysis of current value (type) of the local */ 915 /* For now, just treat any local as a typematch */ 916 917 /*ThisNodeBtype = RequiredBtypes;*/ 918 break; 919 920 case PARSEOP_ARG0: 921 case PARSEOP_ARG1: 922 case PARSEOP_ARG2: 923 case PARSEOP_ARG3: 924 case PARSEOP_ARG4: 925 case PARSEOP_ARG5: 926 case PARSEOP_ARG6: 927 928 /* Hard to analyze argument types, sow we won't */ 929 /* For now, just treat any arg as a typematch */ 930 931 /* ThisNodeBtype = RequiredBtypes; */ 932 break; 933 934 case PARSEOP_DEBUG: 935 break; 936 937 case PARSEOP_REFOF: 938 case PARSEOP_INDEX: 939 default: 940 break; 941 942 } 943 break; 944 945 case ARGI_INTEGER: 946 default: 947 break; 948 } 949 950 951 CommonBtypes = ThisNodeBtype & RequiredBtypes; 952 953 if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) 954 { 955 if (AnIsInternalMethod (ArgOp)) 956 { 957 return (AE_OK); 958 } 959 960 /* Check a method call for a valid return value */ 961 962 AnCheckMethodReturnValue (Op, OpInfo, ArgOp, 963 RequiredBtypes, ThisNodeBtype); 964 } 965 966 /* 967 * Now check if the actual type(s) match at least one 968 * bit to the required type 969 */ 970 else if (!CommonBtypes) 971 { 972 /* No match -- this is a type mismatch error */ 973 974 AnFormatBtype (StringBuffer, ThisNodeBtype); 975 AnFormatBtype (StringBuffer2, RequiredBtypes); 976 977 sprintf (MsgBuffer, "[%s] found, %s operator requires [%s]", 978 StringBuffer, OpInfo->Name, StringBuffer2); 979 980 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer); 981 } 982 983 NextArgument: 984 ArgOp = ArgOp->Asl.Next; 985 INCREMENT_ARG_LIST (RuntimeArgTypes2); 986 } 987 break; 988 989 default: 990 break; 991 } 992 993 return (AE_OK); 994} 995 996 997/******************************************************************************* 998 * 999 * FUNCTION: AnOtherSemanticAnalysisWalkBegin 1000 * 1001 * PARAMETERS: ASL_WALK_CALLBACK 1002 * 1003 * RETURN: Status 1004 * 1005 * DESCRIPTION: Descending callback for the analysis walk. Checks for 1006 * miscellaneous issues in the code. 1007 * 1008 ******************************************************************************/ 1009 1010ACPI_STATUS 1011AnOtherSemanticAnalysisWalkBegin ( 1012 ACPI_PARSE_OBJECT *Op, 1013 UINT32 Level, 1014 void *Context) 1015{ 1016 ACPI_PARSE_OBJECT *ArgNode; 1017 ACPI_PARSE_OBJECT *PrevArgNode = NULL; 1018 const ACPI_OPCODE_INFO *OpInfo; 1019 1020 1021 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 1022 1023 /* 1024 * Determine if an execution class operator actually does something by 1025 * checking if it has a target and/or the function return value is used. 1026 * (Target is optional, so a standalone statement can actually do nothing.) 1027 */ 1028 if ((OpInfo->Class == AML_CLASS_EXECUTE) && 1029 (OpInfo->Flags & AML_HAS_RETVAL) && 1030 (!AnIsResultUsed (Op))) 1031 { 1032 if (OpInfo->Flags & AML_HAS_TARGET) 1033 { 1034 /* 1035 * Find the target node, it is always the last child. If the traget 1036 * is not specified in the ASL, a default node of type Zero was 1037 * created by the parser. 1038 */ 1039 ArgNode = Op->Asl.Child; 1040 while (ArgNode->Asl.Next) 1041 { 1042 PrevArgNode = ArgNode; 1043 ArgNode = ArgNode->Asl.Next; 1044 } 1045 1046 /* Divide() is the only weird case, it has two targets */ 1047 1048 if (Op->Asl.AmlOpcode == AML_DIVIDE_OP) 1049 { 1050 if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) && 1051 (PrevArgNode) && 1052 (PrevArgNode->Asl.ParseOpcode == PARSEOP_ZERO)) 1053 { 1054 AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED, 1055 Op, Op->Asl.ExternalName); 1056 } 1057 } 1058 else if (ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) 1059 { 1060 AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED, 1061 Op, Op->Asl.ExternalName); 1062 } 1063 } 1064 else 1065 { 1066 /* 1067 * Has no target and the result is not used. Only a couple opcodes 1068 * can have this combination. 1069 */ 1070 switch (Op->Asl.ParseOpcode) 1071 { 1072 case PARSEOP_ACQUIRE: 1073 case PARSEOP_WAIT: 1074 case PARSEOP_LOADTABLE: 1075 break; 1076 1077 default: 1078 AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED, 1079 Op, Op->Asl.ExternalName); 1080 break; 1081 } 1082 } 1083 } 1084 1085 1086 /* 1087 * Semantic checks for individual ASL operators 1088 */ 1089 switch (Op->Asl.ParseOpcode) 1090 { 1091 case PARSEOP_ACQUIRE: 1092 case PARSEOP_WAIT: 1093 /* 1094 * Emit a warning if the timeout parameter for these operators is not 1095 * ACPI_WAIT_FOREVER, and the result value from the operator is not 1096 * checked, meaning that a timeout could happen, but the code 1097 * would not know about it. 1098 */ 1099 1100 /* First child is the namepath, 2nd child is timeout */ 1101 1102 ArgNode = Op->Asl.Child; 1103 ArgNode = ArgNode->Asl.Next; 1104 1105 /* 1106 * Check for the WAIT_FOREVER case - defined by the ACPI spec to be 1107 * 0xFFFF or greater 1108 */ 1109 if (((ArgNode->Asl.ParseOpcode == PARSEOP_WORDCONST) || 1110 (ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER)) && 1111 (ArgNode->Asl.Value.Integer >= (UINT64) ACPI_WAIT_FOREVER)) 1112 { 1113 break; 1114 } 1115 1116 /* 1117 * The operation could timeout. If the return value is not used 1118 * (indicates timeout occurred), issue a warning 1119 */ 1120 if (!AnIsResultUsed (Op)) 1121 { 1122 AslError (ASL_WARNING, ASL_MSG_TIMEOUT, ArgNode, 1123 Op->Asl.ExternalName); 1124 } 1125 break; 1126 1127 case PARSEOP_CREATEFIELD: 1128 /* 1129 * Check for a zero Length (NumBits) operand. NumBits is the 3rd operand 1130 */ 1131 ArgNode = Op->Asl.Child; 1132 ArgNode = ArgNode->Asl.Next; 1133 ArgNode = ArgNode->Asl.Next; 1134 1135 if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) || 1136 ((ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER) && 1137 (ArgNode->Asl.Value.Integer == 0))) 1138 { 1139 AslError (ASL_ERROR, ASL_MSG_NON_ZERO, ArgNode, NULL); 1140 } 1141 break; 1142 1143 default: 1144 break; 1145 } 1146 1147 return (AE_OK); 1148} 1149