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