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