1 /****************************************************************************** 2 * 3 * Module Name: aslmethod.c - Control method analysis walk 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2016, 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 #include "aslcompiler.h" 45 #include "aslcompiler.y.h" 46 #include "acparser.h" 47 #include "amlcode.h" 48 49 50 #define _COMPONENT ACPI_COMPILER 51 ACPI_MODULE_NAME ("aslmethod") 52 53 54 /* Local prototypes */ 55 56 void 57 MtCheckNamedObjectInMethod ( 58 ACPI_PARSE_OBJECT *Op, 59 ASL_METHOD_INFO *MethodInfo); 60 61 62 /******************************************************************************* 63 * 64 * FUNCTION: MtMethodAnalysisWalkBegin 65 * 66 * PARAMETERS: ASL_WALK_CALLBACK 67 * 68 * RETURN: Status 69 * 70 * DESCRIPTION: Descending callback for the analysis walk. Check methods for: 71 * 1) Initialized local variables 72 * 2) Valid arguments 73 * 3) Return types 74 * 75 ******************************************************************************/ 76 77 ACPI_STATUS 78 MtMethodAnalysisWalkBegin ( 79 ACPI_PARSE_OBJECT *Op, 80 UINT32 Level, 81 void *Context) 82 { 83 ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context; 84 ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack; 85 ACPI_PARSE_OBJECT *Next; 86 UINT32 RegisterNumber; 87 UINT32 i; 88 char LocalName[] = "Local0"; 89 char ArgName[] = "Arg0"; 90 ACPI_PARSE_OBJECT *ArgNode; 91 ACPI_PARSE_OBJECT *NextType; 92 ACPI_PARSE_OBJECT *NextParamType; 93 UINT8 ActualArgs = 0; 94 95 96 switch (Op->Asl.ParseOpcode) 97 { 98 case PARSEOP_METHOD: 99 100 TotalMethods++; 101 102 /* Create and init method info */ 103 104 MethodInfo = UtLocalCalloc (sizeof (ASL_METHOD_INFO)); 105 MethodInfo->Next = WalkInfo->MethodStack; 106 MethodInfo->Op = Op; 107 108 WalkInfo->MethodStack = MethodInfo; 109 110 /* 111 * Special handling for _PSx methods. Dependency rules (same scope): 112 * 113 * 1) _PS0 - One of these must exist: _PS1, _PS2, _PS3 114 * 2) _PS1/_PS2/_PS3: A _PS0 must exist 115 */ 116 if (ACPI_COMPARE_NAME (METHOD_NAME__PS0, Op->Asl.NameSeg)) 117 { 118 /* For _PS0, one of _PS1/_PS2/_PS3 must exist */ 119 120 if ((!ApFindNameInScope (METHOD_NAME__PS1, Op)) && 121 (!ApFindNameInScope (METHOD_NAME__PS2, Op)) && 122 (!ApFindNameInScope (METHOD_NAME__PS3, Op))) 123 { 124 AslError (ASL_WARNING, ASL_MSG_MISSING_DEPENDENCY, Op, 125 "_PS0 requires one of _PS1/_PS2/_PS3 in same scope"); 126 } 127 } 128 else if ( 129 ACPI_COMPARE_NAME (METHOD_NAME__PS1, Op->Asl.NameSeg) || 130 ACPI_COMPARE_NAME (METHOD_NAME__PS2, Op->Asl.NameSeg) || 131 ACPI_COMPARE_NAME (METHOD_NAME__PS3, Op->Asl.NameSeg)) 132 { 133 /* For _PS1/_PS2/_PS3, a _PS0 must exist */ 134 135 if (!ApFindNameInScope (METHOD_NAME__PS0, Op)) 136 { 137 sprintf (MsgBuffer, 138 "%4.4s requires _PS0 in same scope", Op->Asl.NameSeg); 139 140 AslError (ASL_WARNING, ASL_MSG_MISSING_DEPENDENCY, Op, 141 MsgBuffer); 142 } 143 } 144 145 /* Get the name node */ 146 147 Next = Op->Asl.Child; 148 149 /* Get the NumArguments node */ 150 151 Next = Next->Asl.Next; 152 MethodInfo->NumArguments = (UINT8) 153 (((UINT8) Next->Asl.Value.Integer) & 0x07); 154 155 /* Get the SerializeRule and SyncLevel nodes, ignored here */ 156 157 Next = Next->Asl.Next; 158 MethodInfo->ShouldBeSerialized = (UINT8) Next->Asl.Value.Integer; 159 160 Next = Next->Asl.Next; 161 ArgNode = Next; 162 163 /* Get the ReturnType node */ 164 165 Next = Next->Asl.Next; 166 167 NextType = Next->Asl.Child; 168 while (NextType) 169 { 170 /* Get and map each of the ReturnTypes */ 171 172 MethodInfo->ValidReturnTypes |= AnMapObjTypeToBtype (NextType); 173 NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 174 NextType = NextType->Asl.Next; 175 } 176 177 /* Get the ParameterType node */ 178 179 Next = Next->Asl.Next; 180 181 NextType = Next->Asl.Child; 182 while (NextType) 183 { 184 if (NextType->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) 185 { 186 NextParamType = NextType->Asl.Child; 187 while (NextParamType) 188 { 189 MethodInfo->ValidArgTypes[ActualArgs] |= 190 AnMapObjTypeToBtype (NextParamType); 191 192 NextParamType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 193 NextParamType = NextParamType->Asl.Next; 194 } 195 } 196 else 197 { 198 MethodInfo->ValidArgTypes[ActualArgs] = 199 AnMapObjTypeToBtype (NextType); 200 201 NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG; 202 ActualArgs++; 203 } 204 205 NextType = NextType->Asl.Next; 206 } 207 208 if ((MethodInfo->NumArguments) && 209 (MethodInfo->NumArguments != ActualArgs)) 210 { 211 /* error: Param list did not match number of args */ 212 } 213 214 /* Allow numarguments == 0 for Function() */ 215 216 if ((!MethodInfo->NumArguments) && (ActualArgs)) 217 { 218 MethodInfo->NumArguments = ActualArgs; 219 ArgNode->Asl.Value.Integer |= ActualArgs; 220 } 221 222 /* 223 * Actual arguments are initialized at method entry. 224 * All other ArgX "registers" can be used as locals, so we 225 * track their initialization. 226 */ 227 for (i = 0; i < MethodInfo->NumArguments; i++) 228 { 229 MethodInfo->ArgInitialized[i] = TRUE; 230 } 231 break; 232 233 case PARSEOP_METHODCALL: 234 235 if (MethodInfo && 236 (Op->Asl.Node == MethodInfo->Op->Asl.Node)) 237 { 238 AslError (ASL_REMARK, ASL_MSG_RECURSION, Op, Op->Asl.ExternalName); 239 } 240 break; 241 242 case PARSEOP_LOCAL0: 243 case PARSEOP_LOCAL1: 244 case PARSEOP_LOCAL2: 245 case PARSEOP_LOCAL3: 246 case PARSEOP_LOCAL4: 247 case PARSEOP_LOCAL5: 248 case PARSEOP_LOCAL6: 249 case PARSEOP_LOCAL7: 250 251 if (!MethodInfo) 252 { 253 /* 254 * Local was used outside a control method, or there was an error 255 * in the method declaration. 256 */ 257 AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, 258 Op, Op->Asl.ExternalName); 259 return (AE_ERROR); 260 } 261 262 RegisterNumber = (Op->Asl.AmlOpcode & 0x0007); 263 264 /* 265 * If the local is being used as a target, mark the local 266 * initialized 267 */ 268 if (Op->Asl.CompileFlags & NODE_IS_TARGET) 269 { 270 MethodInfo->LocalInitialized[RegisterNumber] = TRUE; 271 } 272 273 /* 274 * Otherwise, this is a reference, check if the local 275 * has been previously initialized. 276 * 277 * The only operator that accepts an uninitialized value is ObjectType() 278 */ 279 else if ((!MethodInfo->LocalInitialized[RegisterNumber]) && 280 (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE)) 281 { 282 LocalName[strlen (LocalName) -1] = (char) (RegisterNumber + 0x30); 283 AslError (ASL_ERROR, ASL_MSG_LOCAL_INIT, Op, LocalName); 284 } 285 break; 286 287 case PARSEOP_ARG0: 288 case PARSEOP_ARG1: 289 case PARSEOP_ARG2: 290 case PARSEOP_ARG3: 291 case PARSEOP_ARG4: 292 case PARSEOP_ARG5: 293 case PARSEOP_ARG6: 294 295 if (!MethodInfo) 296 { 297 /* 298 * Arg was used outside a control method, or there was an error 299 * in the method declaration. 300 */ 301 AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, 302 Op, Op->Asl.ExternalName); 303 return (AE_ERROR); 304 } 305 306 RegisterNumber = (Op->Asl.AmlOpcode & 0x000F) - 8; 307 ArgName[strlen (ArgName) -1] = (char) (RegisterNumber + 0x30); 308 309 /* 310 * If the Arg is being used as a target, mark the local 311 * initialized 312 */ 313 if (Op->Asl.CompileFlags & NODE_IS_TARGET) 314 { 315 MethodInfo->ArgInitialized[RegisterNumber] = TRUE; 316 } 317 318 /* 319 * Otherwise, this is a reference, check if the Arg 320 * has been previously initialized. 321 * 322 * The only operator that accepts an uninitialized value is ObjectType() 323 */ 324 else if ((!MethodInfo->ArgInitialized[RegisterNumber]) && 325 (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE)) 326 { 327 AslError (ASL_ERROR, ASL_MSG_ARG_INIT, Op, ArgName); 328 } 329 330 /* Flag this arg if it is not a "real" argument to the method */ 331 332 if (RegisterNumber >= MethodInfo->NumArguments) 333 { 334 AslError (ASL_REMARK, ASL_MSG_NOT_PARAMETER, Op, ArgName); 335 } 336 break; 337 338 case PARSEOP_RETURN: 339 340 if (!MethodInfo) 341 { 342 /* 343 * Probably was an error in the method declaration, 344 * no additional error here 345 */ 346 ACPI_WARNING ((AE_INFO, "%p, No parent method", Op)); 347 return (AE_ERROR); 348 } 349 350 /* 351 * A child indicates a possible return value. A simple Return or 352 * Return() is marked with NODE_IS_NULL_RETURN by the parser so 353 * that it is not counted as a "real" return-with-value, although 354 * the AML code that is actually emitted is Return(0). The AML 355 * definition of Return has a required parameter, so we are 356 * forced to convert a null return to Return(0). 357 */ 358 if ((Op->Asl.Child) && 359 (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && 360 (!(Op->Asl.Child->Asl.CompileFlags & NODE_IS_NULL_RETURN))) 361 { 362 MethodInfo->NumReturnWithValue++; 363 } 364 else 365 { 366 MethodInfo->NumReturnNoValue++; 367 } 368 break; 369 370 case PARSEOP_BREAK: 371 case PARSEOP_CONTINUE: 372 373 Next = Op->Asl.Parent; 374 while (Next) 375 { 376 if (Next->Asl.ParseOpcode == PARSEOP_WHILE) 377 { 378 break; 379 } 380 Next = Next->Asl.Parent; 381 } 382 383 if (!Next) 384 { 385 AslError (ASL_ERROR, ASL_MSG_NO_WHILE, Op, NULL); 386 } 387 break; 388 389 case PARSEOP_STALL: 390 391 /* We can range check if the argument is an integer */ 392 393 if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) && 394 (Op->Asl.Child->Asl.Value.Integer > ACPI_UINT8_MAX)) 395 { 396 AslError (ASL_ERROR, ASL_MSG_INVALID_TIME, Op, NULL); 397 } 398 break; 399 400 case PARSEOP_DEVICE: 401 402 Next = Op->Asl.Child; 403 404 if (!ApFindNameInScope (METHOD_NAME__HID, Next) && 405 !ApFindNameInScope (METHOD_NAME__ADR, Next)) 406 { 407 AslError (ASL_WARNING, ASL_MSG_MISSING_DEPENDENCY, Op, 408 "Device object requires a _HID or _ADR in same scope"); 409 } 410 break; 411 412 case PARSEOP_EVENT: 413 case PARSEOP_MUTEX: 414 case PARSEOP_OPERATIONREGION: 415 case PARSEOP_POWERRESOURCE: 416 case PARSEOP_PROCESSOR: 417 case PARSEOP_THERMALZONE: 418 419 /* 420 * The first operand is a name to be created in the namespace. 421 * Check against the reserved list. 422 */ 423 i = ApCheckForPredefinedName (Op, Op->Asl.NameSeg); 424 if (i < ACPI_VALID_RESERVED_NAME_MAX) 425 { 426 AslError (ASL_ERROR, ASL_MSG_RESERVED_USE, 427 Op, Op->Asl.ExternalName); 428 } 429 break; 430 431 case PARSEOP_NAME: 432 433 /* Typecheck any predefined names statically defined with Name() */ 434 435 ApCheckForPredefinedObject (Op, Op->Asl.NameSeg); 436 437 /* Special typechecking for _HID */ 438 439 if (!strcmp (METHOD_NAME__HID, Op->Asl.NameSeg)) 440 { 441 Next = Op->Asl.Child->Asl.Next; 442 AnCheckId (Next, ASL_TYPE_HID); 443 } 444 445 /* Special typechecking for _CID */ 446 447 else if (!strcmp (METHOD_NAME__CID, Op->Asl.NameSeg)) 448 { 449 Next = Op->Asl.Child->Asl.Next; 450 451 if ((Next->Asl.ParseOpcode == PARSEOP_PACKAGE) || 452 (Next->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE)) 453 { 454 Next = Next->Asl.Child; 455 while (Next) 456 { 457 AnCheckId (Next, ASL_TYPE_CID); 458 Next = Next->Asl.Next; 459 } 460 } 461 else 462 { 463 AnCheckId (Next, ASL_TYPE_CID); 464 } 465 } 466 467 break; 468 469 default: 470 471 break; 472 } 473 474 /* Check for named object creation within a non-serialized method */ 475 476 MtCheckNamedObjectInMethod (Op, MethodInfo); 477 return (AE_OK); 478 } 479 480 481 /******************************************************************************* 482 * 483 * FUNCTION: MtCheckNamedObjectInMethod 484 * 485 * PARAMETERS: Op - Current parser op 486 * MethodInfo - Info for method being parsed 487 * 488 * RETURN: None 489 * 490 * DESCRIPTION: Detect if a non-serialized method is creating a named object, 491 * which could possibly cause problems if two threads execute 492 * the method concurrently. Emit a remark in this case. 493 * 494 ******************************************************************************/ 495 496 void 497 MtCheckNamedObjectInMethod ( 498 ACPI_PARSE_OBJECT *Op, 499 ASL_METHOD_INFO *MethodInfo) 500 { 501 const ACPI_OPCODE_INFO *OpInfo; 502 503 504 /* We don't care about actual method declarations or scopes */ 505 506 if ((Op->Asl.AmlOpcode == AML_METHOD_OP) || 507 (Op->Asl.AmlOpcode == AML_SCOPE_OP)) 508 { 509 return; 510 } 511 512 /* Determine if we are creating a named object */ 513 514 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode); 515 if (OpInfo->Class == AML_CLASS_NAMED_OBJECT) 516 { 517 /* 518 * If we have a named object created within a non-serialized method, 519 * emit a remark that the method should be serialized. 520 * 521 * Reason: If a thread blocks within the method for any reason, and 522 * another thread enters the method, the method will fail because an 523 * attempt will be made to create the same object twice. 524 */ 525 if (MethodInfo && !MethodInfo->ShouldBeSerialized) 526 { 527 AslError (ASL_REMARK, ASL_MSG_SERIALIZED_REQUIRED, MethodInfo->Op, 528 "due to creation of named objects within"); 529 530 /* Emit message only ONCE per method */ 531 532 MethodInfo->ShouldBeSerialized = TRUE; 533 } 534 } 535 } 536 537 538 /******************************************************************************* 539 * 540 * FUNCTION: MtMethodAnalysisWalkEnd 541 * 542 * PARAMETERS: ASL_WALK_CALLBACK 543 * 544 * RETURN: Status 545 * 546 * DESCRIPTION: Ascending callback for analysis walk. Complete method 547 * return analysis. 548 * 549 ******************************************************************************/ 550 551 ACPI_STATUS 552 MtMethodAnalysisWalkEnd ( 553 ACPI_PARSE_OBJECT *Op, 554 UINT32 Level, 555 void *Context) 556 { 557 ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context; 558 ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack; 559 560 561 switch (Op->Asl.ParseOpcode) 562 { 563 case PARSEOP_METHOD: 564 case PARSEOP_RETURN: 565 566 if (!MethodInfo) 567 { 568 printf ("No method info for method! [%s]\n", Op->Asl.Namepath); 569 AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op, 570 "No method info for this method"); 571 572 CmCleanupAndExit (); 573 return (AE_AML_INTERNAL); 574 } 575 break; 576 577 default: 578 579 break; 580 } 581 582 switch (Op->Asl.ParseOpcode) 583 { 584 case PARSEOP_METHOD: 585 586 WalkInfo->MethodStack = MethodInfo->Next; 587 588 /* 589 * Check if there is no return statement at the end of the 590 * method AND we can actually get there -- i.e., the execution 591 * of the method can possibly terminate without a return statement. 592 */ 593 if ((!AnLastStatementIsReturn (Op)) && 594 (!(Op->Asl.CompileFlags & NODE_HAS_NO_EXIT))) 595 { 596 /* 597 * No return statement, and execution can possibly exit 598 * via this path. This is equivalent to Return () 599 */ 600 MethodInfo->NumReturnNoValue++; 601 } 602 603 /* 604 * Check for case where some return statements have a return value 605 * and some do not. Exit without a return statement is a return with 606 * no value 607 */ 608 if (MethodInfo->NumReturnNoValue && 609 MethodInfo->NumReturnWithValue) 610 { 611 AslError (ASL_WARNING, ASL_MSG_RETURN_TYPES, Op, 612 Op->Asl.ExternalName); 613 } 614 615 /* 616 * If there are any RETURN() statements with no value, or there is a 617 * control path that allows the method to exit without a return value, 618 * we mark the method as a method that does not return a value. This 619 * knowledge can be used to check method invocations that expect a 620 * returned value. 621 */ 622 if (MethodInfo->NumReturnNoValue) 623 { 624 if (MethodInfo->NumReturnWithValue) 625 { 626 Op->Asl.CompileFlags |= NODE_METHOD_SOME_NO_RETVAL; 627 } 628 else 629 { 630 Op->Asl.CompileFlags |= NODE_METHOD_NO_RETVAL; 631 } 632 } 633 634 /* 635 * Check predefined method names for correct return behavior 636 * and correct number of arguments. Also, some special checks 637 * For GPE and _REG methods. 638 */ 639 if (ApCheckForPredefinedMethod (Op, MethodInfo)) 640 { 641 /* Special check for two names like _L01 and _E01 in same scope */ 642 643 ApCheckForGpeNameConflict (Op); 644 645 /* 646 * Special check for _REG: Must have an operation region definition 647 * within the same scope! 648 */ 649 ApCheckRegMethod (Op); 650 } 651 652 ACPI_FREE (MethodInfo); 653 break; 654 655 case PARSEOP_NAME: 656 657 /* Special check for two names like _L01 and _E01 in same scope */ 658 659 ApCheckForGpeNameConflict (Op); 660 break; 661 662 case PARSEOP_RETURN: 663 664 /* 665 * If the parent is a predefined method name, attempt to typecheck 666 * the return value. Only static types can be validated. 667 */ 668 ApCheckPredefinedReturnValue (Op, MethodInfo); 669 670 /* 671 * The parent block does not "exit" and continue execution -- the 672 * method is terminated here with the Return() statement. 673 */ 674 Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; 675 676 /* Used in the "typing" pass later */ 677 678 Op->Asl.ParentMethod = MethodInfo->Op; 679 680 /* 681 * If there is a peer node after the return statement, then this 682 * node is unreachable code -- i.e., it won't be executed because of 683 * the preceding Return() statement. 684 */ 685 if (Op->Asl.Next) 686 { 687 AslError (ASL_WARNING, ASL_MSG_UNREACHABLE_CODE, 688 Op->Asl.Next, NULL); 689 } 690 break; 691 692 case PARSEOP_IF: 693 694 if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && 695 (Op->Asl.Next) && 696 (Op->Asl.Next->Asl.ParseOpcode == PARSEOP_ELSE)) 697 { 698 /* 699 * This IF has a corresponding ELSE. The IF block has no exit, 700 * (it contains an unconditional Return) 701 * mark the ELSE block to remember this fact. 702 */ 703 Op->Asl.Next->Asl.CompileFlags |= NODE_IF_HAS_NO_EXIT; 704 } 705 break; 706 707 case PARSEOP_ELSE: 708 709 if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && 710 (Op->Asl.CompileFlags & NODE_IF_HAS_NO_EXIT)) 711 { 712 /* 713 * This ELSE block has no exit and the corresponding IF block 714 * has no exit either. Therefore, the parent node has no exit. 715 */ 716 Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; 717 } 718 break; 719 720 721 default: 722 723 if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) && 724 (Op->Asl.Parent)) 725 { 726 /* If this node has no exit, then the parent has no exit either */ 727 728 Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT; 729 } 730 break; 731 } 732 733 return (AE_OK); 734 } 735