Merge branch 'vendor/OPENBSD_LIBM'
[dragonfly.git] / sys / contrib / dev / acpica / source / compiler / aslmethod.c
1 /******************************************************************************
2  *
3  * Module Name: aslmethod.c - Control method analysis walk
4  *
5  *****************************************************************************/
6
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2020, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights. You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code. No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision. In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change. Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee. Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution. In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88  * PARTICULAR PURPOSE.
89  *
90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97  * LIMITED REMEDY.
98  *
99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
100  * software or system incorporating such software without first obtaining any
101  * required license or other approval from the U. S. Department of Commerce or
102  * any other agency or department of the United States Government. In the
103  * event Licensee exports any such software from the United States or
104  * re-exports any such software from a foreign destination, Licensee shall
105  * ensure that the distribution and export/re-export of the software is in
106  * compliance with all laws, regulations, orders, or other restrictions of the
107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108  * any of its subsidiaries will export/re-export any technical data, process,
109  * software, or service, directly or indirectly, to any country for which the
110  * United States government or any agency thereof requires an export license,
111  * other governmental approval, or letter of assurance, without first obtaining
112  * such license, approval or letter.
113  *
114  *****************************************************************************
115  *
116  * Alternatively, you may choose to be licensed under the terms of the
117  * following license:
118  *
119  * Redistribution and use in source and binary forms, with or without
120  * modification, are permitted provided that the following conditions
121  * are met:
122  * 1. Redistributions of source code must retain the above copyright
123  *    notice, this list of conditions, and the following disclaimer,
124  *    without modification.
125  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
126  *    substantially similar to the "NO WARRANTY" disclaimer below
127  *    ("Disclaimer") and any redistribution must be conditioned upon
128  *    including a substantially similar Disclaimer requirement for further
129  *    binary redistribution.
130  * 3. Neither the names of the above-listed copyright holders nor the names
131  *    of any contributors may be used to endorse or promote products derived
132  *    from this software without specific prior written permission.
133  *
134  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145  *
146  * Alternatively, you may choose to be licensed under the terms of the
147  * GNU General Public License ("GPL") version 2 as published by the Free
148  * Software Foundation.
149  *
150  *****************************************************************************/
151
152 #include "aslcompiler.h"
153 #include "aslcompiler.y.h"
154 #include "acparser.h"
155 #include "amlcode.h"
156
157
158 #define _COMPONENT          ACPI_COMPILER
159         ACPI_MODULE_NAME    ("aslmethod")
160
161
162 /* Local prototypes */
163
164 static void
165 MtCheckNamedObjectInMethod (
166     ACPI_PARSE_OBJECT       *Op,
167     ASL_METHOD_INFO         *MethodInfo);
168
169
170 /*******************************************************************************
171  *
172  * FUNCTION:    MtMethodAnalysisWalkBegin
173  *
174  * PARAMETERS:  ASL_WALK_CALLBACK
175  *
176  * RETURN:      Status
177  *
178  * DESCRIPTION: Descending callback for the analysis walk. Check methods for:
179  *              1) Initialized local variables
180  *              2) Valid arguments
181  *              3) Return types
182  *
183  ******************************************************************************/
184
185 ACPI_STATUS
186 MtMethodAnalysisWalkBegin (
187     ACPI_PARSE_OBJECT       *Op,
188     UINT32                  Level,
189     void                    *Context)
190 {
191     ASL_ANALYSIS_WALK_INFO  *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
192     ASL_METHOD_INFO         *MethodInfo = WalkInfo->MethodStack;
193     ACPI_PARSE_OBJECT       *Next;
194     UINT32                  RegisterNumber;
195     UINT32                  i;
196     char                    LocalName[] = "Local0";
197     char                    ArgName[] = "Arg0";
198     ACPI_PARSE_OBJECT       *ArgNode;
199     ACPI_PARSE_OBJECT       *NextType;
200     ACPI_PARSE_OBJECT       *NextParamType;
201     UINT8                   ActualArgs = 0;
202     BOOLEAN                 HidExists;
203     BOOLEAN                 AdrExists;
204
205
206     /* Build cross-reference output file if requested */
207
208     if (AslGbl_CrossReferenceOutput)
209     {
210         OtXrefWalkPart1 (Op, Level, MethodInfo);
211     }
212
213     switch (Op->Asl.ParseOpcode)
214     {
215     case PARSEOP_METHOD:
216
217         AslGbl_TotalMethods++;
218
219         /* Create and init method info */
220
221         MethodInfo = UtLocalCalloc (sizeof (ASL_METHOD_INFO));
222         MethodInfo->Next = WalkInfo->MethodStack;
223         MethodInfo->Op = Op;
224
225         WalkInfo->MethodStack = MethodInfo;
226
227         /*
228          * Special handling for _PSx methods. Dependency rules (same scope):
229          *
230          * 1) _PS0 - One of these must exist: _PS1, _PS2, _PS3
231          * 2) _PS1/_PS2/_PS3: A _PS0 must exist
232          */
233         if (ACPI_COMPARE_NAMESEG (METHOD_NAME__PS0, Op->Asl.NameSeg))
234         {
235             /* For _PS0, one of _PS1/_PS2/_PS3 must exist */
236
237             if ((!ApFindNameInScope (METHOD_NAME__PS1, Op)) &&
238                 (!ApFindNameInScope (METHOD_NAME__PS2, Op)) &&
239                 (!ApFindNameInScope (METHOD_NAME__PS3, Op)))
240             {
241                 AslError (ASL_WARNING, ASL_MSG_MISSING_DEPENDENCY, Op,
242                     "_PS0 requires one of _PS1/_PS2/_PS3 in same scope");
243             }
244         }
245         else if (
246             ACPI_COMPARE_NAMESEG (METHOD_NAME__PS1, Op->Asl.NameSeg) ||
247             ACPI_COMPARE_NAMESEG (METHOD_NAME__PS2, Op->Asl.NameSeg) ||
248             ACPI_COMPARE_NAMESEG (METHOD_NAME__PS3, Op->Asl.NameSeg))
249         {
250             /* For _PS1/_PS2/_PS3, a _PS0 must exist */
251
252             if (!ApFindNameInScope (METHOD_NAME__PS0, Op))
253             {
254                 sprintf (AslGbl_MsgBuffer,
255                     "%4.4s requires _PS0 in same scope", Op->Asl.NameSeg);
256
257                 AslError (ASL_WARNING, ASL_MSG_MISSING_DEPENDENCY, Op,
258                     AslGbl_MsgBuffer);
259             }
260         }
261
262         /* Get the name node */
263
264         Next = Op->Asl.Child;
265
266         /* Get the NumArguments node */
267
268         Next = Next->Asl.Next;
269         MethodInfo->NumArguments = (UINT8)
270             (((UINT8) Next->Asl.Value.Integer) & 0x07);
271
272         /* Get the SerializeRule and SyncLevel nodes, ignored here */
273
274         Next = Next->Asl.Next;
275         MethodInfo->ShouldBeSerialized = (UINT8) Next->Asl.Value.Integer;
276
277         Next = Next->Asl.Next;
278         ArgNode = Next;
279
280         /* Get the ReturnType node */
281
282         Next = Next->Asl.Next;
283
284         NextType = Next->Asl.Child;
285         while (NextType)
286         {
287             /* Get and map each of the ReturnTypes */
288
289             MethodInfo->ValidReturnTypes |= AnMapObjTypeToBtype (NextType);
290             NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
291             NextType = NextType->Asl.Next;
292         }
293
294         /* Get the ParameterType node */
295
296         Next = Next->Asl.Next;
297
298         NextType = Next->Asl.Child;
299         while (NextType)
300         {
301             if (NextType->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
302             {
303                 NextParamType = NextType->Asl.Child;
304                 while (NextParamType)
305                 {
306                     MethodInfo->ValidArgTypes[ActualArgs] |=
307                         AnMapObjTypeToBtype (NextParamType);
308
309                     NextParamType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
310                     NextParamType = NextParamType->Asl.Next;
311                 }
312             }
313             else
314             {
315                 MethodInfo->ValidArgTypes[ActualArgs] =
316                     AnMapObjTypeToBtype (NextType);
317
318                 NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
319                 ActualArgs++;
320             }
321
322             NextType = NextType->Asl.Next;
323         }
324
325         if ((MethodInfo->NumArguments) &&
326             (MethodInfo->NumArguments != ActualArgs))
327         {
328             /* error: Param list did not match number of args */
329         }
330
331         /* Allow numarguments == 0 for Function() */
332
333         if ((!MethodInfo->NumArguments) && (ActualArgs))
334         {
335             MethodInfo->NumArguments = ActualArgs;
336             ArgNode->Asl.Value.Integer |= ActualArgs;
337         }
338
339         /*
340          * Actual arguments are initialized at method entry.
341          * All other ArgX "registers" can be used as locals, so we
342          * track their initialization.
343          */
344         for (i = 0; i < MethodInfo->NumArguments; i++)
345         {
346             MethodInfo->ArgInitialized[i] = TRUE;
347         }
348         break;
349
350     case PARSEOP_METHODCALL:
351
352         /* Check for a recursive method call */
353
354         if (MethodInfo &&
355            (Op->Asl.Node == MethodInfo->Op->Asl.Node))
356         {
357             if (MethodInfo->CreatesNamedObjects)
358             {
359                 /*
360                  * This is an error, as it will fail at runtime on all ACPI
361                  * implementations. Any named object declarations will be
362                  * executed twice, causing failure the second time. Note,
363                  * this is independent of whether the method is declared
364                  * Serialized, because the same thread is attempting to
365                  * reenter the method, and this will always succeed.
366                  */
367                 AslDualParseOpError (ASL_ERROR, ASL_MSG_ILLEGAL_RECURSION, Op,
368                     Op->Asl.Value.String, ASL_MSG_FOUND_HERE, MethodInfo->Op,
369                     MethodInfo->Op->Asl.ExternalName);
370             }
371             else
372             {
373                 /* Method does not create objects, issue a remark */
374
375                 AslError (ASL_REMARK, ASL_MSG_RECURSION, Op, Op->Asl.ExternalName);
376             }
377         }
378         break;
379
380     case PARSEOP_LOCAL0:
381     case PARSEOP_LOCAL1:
382     case PARSEOP_LOCAL2:
383     case PARSEOP_LOCAL3:
384     case PARSEOP_LOCAL4:
385     case PARSEOP_LOCAL5:
386     case PARSEOP_LOCAL6:
387     case PARSEOP_LOCAL7:
388
389         if (!MethodInfo)
390         {
391             /*
392              * Local was used outside a control method, or there was an error
393              * in the method declaration.
394              */
395             AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD,
396                 Op, Op->Asl.ExternalName);
397             return (AE_ERROR);
398         }
399
400         RegisterNumber = (Op->Asl.AmlOpcode & 0x0007);
401
402         /*
403          * If the local is being used as a target, mark the local
404          * initialized
405          */
406         if (Op->Asl.CompileFlags & OP_IS_TARGET)
407         {
408             MethodInfo->LocalInitialized[RegisterNumber] = TRUE;
409         }
410
411         /*
412          * Otherwise, this is a reference, check if the local
413          * has been previously initialized.
414          *
415          * The only operator that accepts an uninitialized value is ObjectType()
416          */
417         else if ((!MethodInfo->LocalInitialized[RegisterNumber]) &&
418                  (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
419         {
420             LocalName[strlen (LocalName) -1] = (char) (RegisterNumber + 0x30);
421             AslError (ASL_ERROR, ASL_MSG_LOCAL_INIT, Op, LocalName);
422         }
423         break;
424
425     case PARSEOP_ARG0:
426     case PARSEOP_ARG1:
427     case PARSEOP_ARG2:
428     case PARSEOP_ARG3:
429     case PARSEOP_ARG4:
430     case PARSEOP_ARG5:
431     case PARSEOP_ARG6:
432
433         if (!MethodInfo)
434         {
435             /*
436              * Arg was used outside a control method, or there was an error
437              * in the method declaration.
438              */
439             AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD,
440                 Op, Op->Asl.ExternalName);
441             return (AE_ERROR);
442         }
443
444         RegisterNumber = (Op->Asl.AmlOpcode & 0x000F) - 8;
445         ArgName[strlen (ArgName) -1] = (char) (RegisterNumber + 0x30);
446
447         /*
448          * If the Arg is being used as a target, mark the local
449          * initialized
450          */
451         if (Op->Asl.CompileFlags & OP_IS_TARGET)
452         {
453             MethodInfo->ArgInitialized[RegisterNumber] = TRUE;
454         }
455
456         /*
457          * Otherwise, this is a reference, check if the Arg
458          * has been previously initialized.
459          *
460          * The only operator that accepts an uninitialized value is ObjectType()
461          */
462         else if ((!MethodInfo->ArgInitialized[RegisterNumber]) &&
463             (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
464         {
465             AslError (ASL_ERROR, ASL_MSG_ARG_INIT, Op, ArgName);
466         }
467
468         /* Flag this arg if it is not a "real" argument to the method */
469
470         if (RegisterNumber >= MethodInfo->NumArguments)
471         {
472             AslError (ASL_REMARK, ASL_MSG_NOT_PARAMETER, Op, ArgName);
473         }
474         break;
475
476     case PARSEOP_RETURN:
477
478         if (!MethodInfo)
479         {
480             /*
481              * Probably was an error in the method declaration,
482              * no additional error here
483              */
484             ACPI_WARNING ((AE_INFO, "%p, No parent method", Op));
485             return (AE_ERROR);
486         }
487
488         /*
489          * A child indicates a possible return value. A simple Return or
490          * Return() is marked with OP_IS_NULL_RETURN by the parser so
491          * that it is not counted as a "real" return-with-value, although
492          * the AML code that is actually emitted is Return(0). The AML
493          * definition of Return has a required parameter, so we are
494          * forced to convert a null return to Return(0).
495          */
496         if ((Op->Asl.Child) &&
497             (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
498             (!(Op->Asl.Child->Asl.CompileFlags & OP_IS_NULL_RETURN)))
499         {
500             MethodInfo->NumReturnWithValue++;
501         }
502         else
503         {
504             MethodInfo->NumReturnNoValue++;
505         }
506         break;
507
508     case PARSEOP_BREAK:
509     case PARSEOP_CONTINUE:
510
511         Next = Op->Asl.Parent;
512         while (Next)
513         {
514             if (Next->Asl.ParseOpcode == PARSEOP_WHILE)
515             {
516                 break;
517             }
518             Next = Next->Asl.Parent;
519         }
520
521         if (!Next)
522         {
523             AslError (ASL_ERROR, ASL_MSG_NO_WHILE, Op, NULL);
524         }
525         break;
526
527     case PARSEOP_STALL:
528
529         /* We can range check if the argument is an integer */
530
531         if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
532             (Op->Asl.Child->Asl.Value.Integer > ACPI_UINT8_MAX))
533         {
534             AslError (ASL_ERROR, ASL_MSG_INVALID_TIME, Op, NULL);
535         }
536         break;
537
538     case PARSEOP_DEVICE:
539
540         /* Check usage of _HID and _ADR objects */
541
542         HidExists = ApFindNameInDeviceTree (METHOD_NAME__HID, Op);
543         AdrExists = ApFindNameInDeviceTree (METHOD_NAME__ADR, Op);
544
545         if (!HidExists && !AdrExists)
546         {
547             AslError (ASL_WARNING, ASL_MSG_MISSING_DEPENDENCY, Op,
548                 "Device object requires a _HID or _ADR in same scope");
549         }
550         else if (HidExists && AdrExists)
551         {
552             /*
553              * According to the ACPI spec, "A device object must contain
554              * either an _HID object or an _ADR object, but should not contain
555              * both".
556              */
557             AslError (ASL_WARNING, ASL_MSG_MULTIPLE_TYPES, Op,
558                 "Device object requires either a _HID or _ADR, but not both");
559         }
560         break;
561
562     case PARSEOP_EVENT:
563     case PARSEOP_MUTEX:
564     case PARSEOP_OPERATIONREGION:
565     case PARSEOP_POWERRESOURCE:
566     case PARSEOP_PROCESSOR:
567     case PARSEOP_THERMALZONE:
568
569         /*
570          * The first operand is a name to be created in the namespace.
571          * Check against the reserved list.
572          */
573         i = ApCheckForPredefinedName (Op, Op->Asl.NameSeg);
574         if (i < ACPI_VALID_RESERVED_NAME_MAX)
575         {
576             AslError (ASL_ERROR, ASL_MSG_RESERVED_USE,
577                 Op, Op->Asl.ExternalName);
578         }
579         break;
580
581     case PARSEOP_NAME:
582
583         /* Typecheck any predefined names statically defined with Name() */
584
585         ApCheckForPredefinedObject (Op, Op->Asl.NameSeg);
586
587         /* Special typechecking for _HID */
588
589         if (ACPI_COMPARE_NAMESEG (METHOD_NAME__HID, Op->Asl.NameSeg))
590         {
591             Next = Op->Asl.Child->Asl.Next;
592             AnCheckId (Next, ASL_TYPE_HID);
593         }
594
595         /* Special typechecking for _CID */
596
597         else if (ACPI_COMPARE_NAMESEG (METHOD_NAME__CID, Op->Asl.NameSeg))
598         {
599             Next = Op->Asl.Child->Asl.Next;
600
601             if ((Next->Asl.ParseOpcode == PARSEOP_PACKAGE) ||
602                 (Next->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE))
603             {
604                 Next = Next->Asl.Child;
605                 while (Next)
606                 {
607                     AnCheckId (Next, ASL_TYPE_CID);
608                     Next = Next->Asl.Next;
609                 }
610             }
611             else
612             {
613                 AnCheckId (Next, ASL_TYPE_CID);
614             }
615         }
616
617         break;
618
619     default:
620
621         break;
622     }
623
624     /* Check for named object creation within a non-serialized method */
625
626     MtCheckNamedObjectInMethod (Op, MethodInfo);
627     return (AE_OK);
628 }
629
630
631 /*******************************************************************************
632  *
633  * FUNCTION:    MtCheckNamedObjectInMethod
634  *
635  * PARAMETERS:  Op                  - Current parser op
636  *              MethodInfo          - Info for method being parsed
637  *
638  * RETURN:      None
639  *
640  * DESCRIPTION: Detect if a non-serialized method is creating a named object,
641  *              which could possibly cause problems if two threads execute
642  *              the method concurrently. Emit a remark in this case.
643  *
644  ******************************************************************************/
645
646 static void
647 MtCheckNamedObjectInMethod (
648     ACPI_PARSE_OBJECT       *Op,
649     ASL_METHOD_INFO         *MethodInfo)
650 {
651     const ACPI_OPCODE_INFO  *OpInfo;
652
653
654     /* We don't care about actual method declarations or scopes */
655
656     if ((Op->Asl.AmlOpcode == AML_METHOD_OP) ||
657         (Op->Asl.AmlOpcode == AML_SCOPE_OP))
658     {
659         return;
660     }
661
662     /* Determine if we are creating a named object within a method */
663
664     if (!MethodInfo)
665     {
666         return;
667     }
668
669     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
670     if (OpInfo->Class == AML_CLASS_NAMED_OBJECT)
671     {
672         /*
673          * 1) Mark the method as a method that creates named objects.
674          *
675          * 2) If the method is non-serialized, emit a remark that the method
676          * should be serialized.
677          *
678          * Reason: If a thread blocks within the method for any reason, and
679          * another thread enters the method, the method will fail because
680          * an attempt will be made to create the same object twice.
681          */
682         MethodInfo->CreatesNamedObjects = TRUE;
683         if (!MethodInfo->ShouldBeSerialized)
684         {
685             AslError (ASL_REMARK, ASL_MSG_SERIALIZED_REQUIRED, MethodInfo->Op,
686                 "due to creation of named objects within");
687
688             /* Emit message only ONCE per method */
689
690             MethodInfo->ShouldBeSerialized = TRUE;
691         }
692     }
693 }
694
695
696 /*******************************************************************************
697  *
698  * FUNCTION:    MtMethodAnalysisWalkEnd
699  *
700  * PARAMETERS:  ASL_WALK_CALLBACK
701  *
702  * RETURN:      Status
703  *
704  * DESCRIPTION: Ascending callback for analysis walk. Complete method
705  *              return analysis.
706  *
707  ******************************************************************************/
708
709 ACPI_STATUS
710 MtMethodAnalysisWalkEnd (
711     ACPI_PARSE_OBJECT       *Op,
712     UINT32                  Level,
713     void                    *Context)
714 {
715     ASL_ANALYSIS_WALK_INFO  *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
716     ASL_METHOD_INFO         *MethodInfo = WalkInfo->MethodStack;
717
718
719     switch (Op->Asl.ParseOpcode)
720     {
721     case PARSEOP_METHOD:
722     case PARSEOP_RETURN:
723
724         if (!MethodInfo)
725         {
726             printf ("No method info for method! [%s]\n", Op->Asl.Namepath);
727             AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
728                 "No method info for this method");
729
730             CmCleanupAndExit ();
731             return (AE_AML_INTERNAL);
732         }
733         break;
734
735     default:
736
737         break;
738     }
739
740     switch (Op->Asl.ParseOpcode)
741     {
742     case PARSEOP_METHOD:
743
744         WalkInfo->MethodStack = MethodInfo->Next;
745
746         /*
747          * Check if there is no return statement at the end of the
748          * method AND we can actually get there -- i.e., the execution
749          * of the method can possibly terminate without a return statement.
750          */
751         if ((!AnLastStatementIsReturn (Op)) &&
752             (!(Op->Asl.CompileFlags & OP_HAS_NO_EXIT)))
753         {
754             /*
755              * No return statement, and execution can possibly exit
756              * via this path. This is equivalent to Return ()
757              */
758             MethodInfo->NumReturnNoValue++;
759         }
760
761         /*
762          * Check for case where some return statements have a return value
763          * and some do not. Exit without a return statement is a return with
764          * no value
765          */
766         if (MethodInfo->NumReturnNoValue &&
767             MethodInfo->NumReturnWithValue)
768         {
769             AslError (ASL_WARNING, ASL_MSG_RETURN_TYPES, Op,
770                 Op->Asl.ExternalName);
771         }
772
773         /*
774          * If there are any RETURN() statements with no value, or there is a
775          * control path that allows the method to exit without a return value,
776          * we mark the method as a method that does not return a value. This
777          * knowledge can be used to check method invocations that expect a
778          * returned value.
779          */
780         if (MethodInfo->NumReturnNoValue)
781         {
782             if (MethodInfo->NumReturnWithValue)
783             {
784                 Op->Asl.CompileFlags |= OP_METHOD_SOME_NO_RETVAL;
785             }
786             else
787             {
788                 Op->Asl.CompileFlags |= OP_METHOD_NO_RETVAL;
789             }
790         }
791
792         /*
793          * Check predefined method names for correct return behavior
794          * and correct number of arguments. Also, some special checks
795          * For GPE and _REG methods.
796          */
797         if (ApCheckForPredefinedMethod (Op, MethodInfo))
798         {
799             /* Special check for two names like _L01 and _E01 in same scope */
800
801             ApCheckForGpeNameConflict (Op);
802
803             /*
804              * Special check for _REG: Must have an operation region definition
805              * within the same scope!
806              */
807             ApCheckRegMethod (Op);
808         }
809
810         ACPI_FREE (MethodInfo);
811         break;
812
813     case PARSEOP_NAME:
814
815          /* Special check for two names like _L01 and _E01 in same scope */
816
817         ApCheckForGpeNameConflict (Op);
818         break;
819
820     case PARSEOP_RETURN:
821
822         /*
823          * If the parent is a predefined method name, attempt to typecheck
824          * the return value. Only static types can be validated.
825          */
826         ApCheckPredefinedReturnValue (Op, MethodInfo);
827
828         /*
829          * The parent block does not "exit" and continue execution -- the
830          * method is terminated here with the Return() statement.
831          */
832         Op->Asl.Parent->Asl.CompileFlags |= OP_HAS_NO_EXIT;
833
834         /* Used in the "typing" pass later */
835
836         Op->Asl.ParentMethod = MethodInfo->Op;
837
838         /*
839          * If there is a peer node after the return statement, then this
840          * node is unreachable code -- i.e., it won't be executed because of
841          * the preceding Return() statement.
842          */
843         if (Op->Asl.Next)
844         {
845             AslError (ASL_WARNING, ASL_MSG_UNREACHABLE_CODE,
846                 Op->Asl.Next, NULL);
847         }
848         break;
849
850     case PARSEOP_IF:
851
852         if ((Op->Asl.CompileFlags & OP_HAS_NO_EXIT) &&
853             (Op->Asl.Next) &&
854             (Op->Asl.Next->Asl.ParseOpcode == PARSEOP_ELSE))
855         {
856             /*
857              * This IF has a corresponding ELSE. The IF block has no exit,
858              * (it contains an unconditional Return)
859              * mark the ELSE block to remember this fact.
860              */
861             Op->Asl.Next->Asl.CompileFlags |= OP_IF_HAS_NO_EXIT;
862         }
863         break;
864
865     case PARSEOP_ELSE:
866
867         if ((Op->Asl.CompileFlags & OP_HAS_NO_EXIT) &&
868             (Op->Asl.CompileFlags & OP_IF_HAS_NO_EXIT))
869         {
870             /*
871              * This ELSE block has no exit and the corresponding IF block
872              * has no exit either. Therefore, the parent node has no exit.
873              */
874             Op->Asl.Parent->Asl.CompileFlags |= OP_HAS_NO_EXIT;
875         }
876         break;
877
878
879     default:
880
881         if ((Op->Asl.CompileFlags & OP_HAS_NO_EXIT) &&
882             (Op->Asl.Parent))
883         {
884             /* If this node has no exit, then the parent has no exit either */
885
886             Op->Asl.Parent->Asl.CompileFlags |= OP_HAS_NO_EXIT;
887         }
888         break;
889     }
890
891     return (AE_OK);
892 }