xref: /netbsd-src/sys/external/bsd/acpica/dist/compiler/aslmethod.c (revision 046a29855e04359424fd074e8313af6b6be8cfb6)
1ff4a156dSchristos /******************************************************************************
2ff4a156dSchristos  *
3ff4a156dSchristos  * Module Name: aslmethod.c - Control method analysis walk
4ff4a156dSchristos  *
5ff4a156dSchristos  *****************************************************************************/
6ff4a156dSchristos 
7ff4a156dSchristos /*
8*046a2985Schristos  * Copyright (C) 2000 - 2023, Intel Corp.
9ff4a156dSchristos  * All rights reserved.
10ff4a156dSchristos  *
11ff4a156dSchristos  * Redistribution and use in source and binary forms, with or without
12ff4a156dSchristos  * modification, are permitted provided that the following conditions
13ff4a156dSchristos  * are met:
14ff4a156dSchristos  * 1. Redistributions of source code must retain the above copyright
15ff4a156dSchristos  *    notice, this list of conditions, and the following disclaimer,
16ff4a156dSchristos  *    without modification.
17ff4a156dSchristos  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18ff4a156dSchristos  *    substantially similar to the "NO WARRANTY" disclaimer below
19ff4a156dSchristos  *    ("Disclaimer") and any redistribution must be conditioned upon
20ff4a156dSchristos  *    including a substantially similar Disclaimer requirement for further
21ff4a156dSchristos  *    binary redistribution.
22ff4a156dSchristos  * 3. Neither the names of the above-listed copyright holders nor the names
23ff4a156dSchristos  *    of any contributors may be used to endorse or promote products derived
24ff4a156dSchristos  *    from this software without specific prior written permission.
25ff4a156dSchristos  *
26ff4a156dSchristos  * Alternatively, this software may be distributed under the terms of the
27ff4a156dSchristos  * GNU General Public License ("GPL") version 2 as published by the Free
28ff4a156dSchristos  * Software Foundation.
29ff4a156dSchristos  *
30ff4a156dSchristos  * NO WARRANTY
31ff4a156dSchristos  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32ff4a156dSchristos  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3346a330b4Schristos  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34ff4a156dSchristos  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35ff4a156dSchristos  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36ff4a156dSchristos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37ff4a156dSchristos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38ff4a156dSchristos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39ff4a156dSchristos  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40ff4a156dSchristos  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41ff4a156dSchristos  * POSSIBILITY OF SUCH DAMAGES.
42ff4a156dSchristos  */
43ff4a156dSchristos 
44ff4a156dSchristos #include "aslcompiler.h"
45ff4a156dSchristos #include "aslcompiler.y.h"
463fd31de5Schristos #include "acnamesp.h"
47ff4a156dSchristos #include "acparser.h"
48ff4a156dSchristos #include "amlcode.h"
49ff4a156dSchristos 
50ff4a156dSchristos 
51ff4a156dSchristos #define _COMPONENT          ACPI_COMPILER
52ff4a156dSchristos         ACPI_MODULE_NAME    ("aslmethod")
53ff4a156dSchristos 
54ff4a156dSchristos 
55ff4a156dSchristos /* Local prototypes */
56ff4a156dSchristos 
57cfbb7280Schristos static void
58ff4a156dSchristos MtCheckNamedObjectInMethod (
59ff4a156dSchristos     ACPI_PARSE_OBJECT       *Op,
60ff4a156dSchristos     ASL_METHOD_INFO         *MethodInfo);
61ff4a156dSchristos 
623fd31de5Schristos static void
633fd31de5Schristos MtCheckStaticOperationRegionInMethod (
643fd31de5Schristos     ACPI_PARSE_OBJECT       *Op);
653fd31de5Schristos 
66ff4a156dSchristos 
67ff4a156dSchristos /*******************************************************************************
68ff4a156dSchristos  *
69ff4a156dSchristos  * FUNCTION:    MtMethodAnalysisWalkBegin
70ff4a156dSchristos  *
71ff4a156dSchristos  * PARAMETERS:  ASL_WALK_CALLBACK
72ff4a156dSchristos  *
73ff4a156dSchristos  * RETURN:      Status
74ff4a156dSchristos  *
75ff4a156dSchristos  * DESCRIPTION: Descending callback for the analysis walk. Check methods for:
76ff4a156dSchristos  *              1) Initialized local variables
77ff4a156dSchristos  *              2) Valid arguments
78ff4a156dSchristos  *              3) Return types
79ff4a156dSchristos  *
80ff4a156dSchristos  ******************************************************************************/
81ff4a156dSchristos 
82ff4a156dSchristos ACPI_STATUS
MtMethodAnalysisWalkBegin(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)83ff4a156dSchristos MtMethodAnalysisWalkBegin (
84ff4a156dSchristos     ACPI_PARSE_OBJECT       *Op,
85ff4a156dSchristos     UINT32                  Level,
86ff4a156dSchristos     void                    *Context)
87ff4a156dSchristos {
88ff4a156dSchristos     ASL_ANALYSIS_WALK_INFO  *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
89ff4a156dSchristos     ASL_METHOD_INFO         *MethodInfo = WalkInfo->MethodStack;
90ff4a156dSchristos     ACPI_PARSE_OBJECT       *Next;
91ff4a156dSchristos     UINT32                  RegisterNumber;
92ff4a156dSchristos     UINT32                  i;
93ff4a156dSchristos     char                    LocalName[] = "Local0";
94ff4a156dSchristos     char                    ArgName[] = "Arg0";
95ff4a156dSchristos     ACPI_PARSE_OBJECT       *ArgNode;
96ff4a156dSchristos     ACPI_PARSE_OBJECT       *NextType;
97ff4a156dSchristos     UINT8                   ActualArgs = 0;
9832aedd46Schristos     BOOLEAN                 HidExists;
9932aedd46Schristos     BOOLEAN                 AdrExists;
10030370826Schristos     BOOLEAN                 PrsExists;
10130370826Schristos     BOOLEAN                 CrsExists;
10230370826Schristos     BOOLEAN                 SrsExists;
10330370826Schristos     BOOLEAN                 DisExists;
104ff4a156dSchristos 
105ff4a156dSchristos 
106cfbb7280Schristos     /* Build cross-reference output file if requested */
107cfbb7280Schristos 
1084c4e8184Schristos     if (AslGbl_CrossReferenceOutput)
109cfbb7280Schristos     {
110cfbb7280Schristos         OtXrefWalkPart1 (Op, Level, MethodInfo);
111cfbb7280Schristos     }
112cfbb7280Schristos 
113ff4a156dSchristos     switch (Op->Asl.ParseOpcode)
114ff4a156dSchristos     {
115ff4a156dSchristos     case PARSEOP_METHOD:
116ff4a156dSchristos 
1174c4e8184Schristos         AslGbl_TotalMethods++;
118ff4a156dSchristos 
119ff4a156dSchristos         /* Create and init method info */
120ff4a156dSchristos 
121ff4a156dSchristos         MethodInfo = UtLocalCalloc (sizeof (ASL_METHOD_INFO));
122ff4a156dSchristos         MethodInfo->Next = WalkInfo->MethodStack;
123ff4a156dSchristos         MethodInfo->Op = Op;
124ff4a156dSchristos 
125ff4a156dSchristos         WalkInfo->MethodStack = MethodInfo;
126ff4a156dSchristos 
127460301d4Schristos         /*
128460301d4Schristos          * Special handling for _PSx methods. Dependency rules (same scope):
129460301d4Schristos          *
130460301d4Schristos          * 1) _PS0 - One of these must exist: _PS1, _PS2, _PS3
131460301d4Schristos          * 2) _PS1/_PS2/_PS3: A _PS0 must exist
132460301d4Schristos          */
13394783addSchristos         if (ACPI_COMPARE_NAMESEG (METHOD_NAME__PS0, Op->Asl.NameSeg))
134460301d4Schristos         {
135460301d4Schristos             /* For _PS0, one of _PS1/_PS2/_PS3 must exist */
136460301d4Schristos 
137460301d4Schristos             if ((!ApFindNameInScope (METHOD_NAME__PS1, Op)) &&
138460301d4Schristos                 (!ApFindNameInScope (METHOD_NAME__PS2, Op)) &&
139460301d4Schristos                 (!ApFindNameInScope (METHOD_NAME__PS3, Op)))
140460301d4Schristos             {
141460301d4Schristos                 AslError (ASL_WARNING, ASL_MSG_MISSING_DEPENDENCY, Op,
142460301d4Schristos                     "_PS0 requires one of _PS1/_PS2/_PS3 in same scope");
143460301d4Schristos             }
144460301d4Schristos         }
145460301d4Schristos         else if (
14694783addSchristos             ACPI_COMPARE_NAMESEG (METHOD_NAME__PS1, Op->Asl.NameSeg) ||
14794783addSchristos             ACPI_COMPARE_NAMESEG (METHOD_NAME__PS2, Op->Asl.NameSeg) ||
14894783addSchristos             ACPI_COMPARE_NAMESEG (METHOD_NAME__PS3, Op->Asl.NameSeg))
149460301d4Schristos         {
150460301d4Schristos             /* For _PS1/_PS2/_PS3, a _PS0 must exist */
151460301d4Schristos 
152460301d4Schristos             if (!ApFindNameInScope (METHOD_NAME__PS0, Op))
153460301d4Schristos             {
1544c4e8184Schristos                 sprintf (AslGbl_MsgBuffer,
155460301d4Schristos                     "%4.4s requires _PS0 in same scope", Op->Asl.NameSeg);
156460301d4Schristos 
157460301d4Schristos                 AslError (ASL_WARNING, ASL_MSG_MISSING_DEPENDENCY, Op,
1584c4e8184Schristos                     AslGbl_MsgBuffer);
159460301d4Schristos             }
160460301d4Schristos         }
161460301d4Schristos 
162460301d4Schristos         /* Get the name node */
163ff4a156dSchristos 
164ff4a156dSchristos         Next = Op->Asl.Child;
165ff4a156dSchristos 
166ff4a156dSchristos         /* Get the NumArguments node */
167ff4a156dSchristos 
168ff4a156dSchristos         Next = Next->Asl.Next;
169ff4a156dSchristos         MethodInfo->NumArguments = (UINT8)
170ff4a156dSchristos             (((UINT8) Next->Asl.Value.Integer) & 0x07);
171ff4a156dSchristos 
172ff4a156dSchristos         /* Get the SerializeRule and SyncLevel nodes, ignored here */
173ff4a156dSchristos 
174ff4a156dSchristos         Next = Next->Asl.Next;
175ff4a156dSchristos         MethodInfo->ShouldBeSerialized = (UINT8) Next->Asl.Value.Integer;
176ff4a156dSchristos 
177ff4a156dSchristos         Next = Next->Asl.Next;
178ff4a156dSchristos         ArgNode = Next;
179ff4a156dSchristos 
180ff4a156dSchristos         /* Get the ReturnType node */
181ff4a156dSchristos 
182ff4a156dSchristos         Next = Next->Asl.Next;
183ff4a156dSchristos 
184ff4a156dSchristos         NextType = Next->Asl.Child;
185ff4a156dSchristos 
1863fd31de5Schristos         MethodInfo->ValidReturnTypes = MtProcessTypeOp (NextType);
18746a330b4Schristos         Op->Asl.AcpiBtype |= MethodInfo->ValidReturnTypes;
188ff4a156dSchristos 
189ff4a156dSchristos         /* Get the ParameterType node */
190ff4a156dSchristos 
191ff4a156dSchristos         Next = Next->Asl.Next;
192ff4a156dSchristos 
193ff4a156dSchristos         NextType = Next->Asl.Child;
1943fd31de5Schristos         if (!NextType)
195ff4a156dSchristos         {
1963fd31de5Schristos             /*
1973fd31de5Schristos              * The optional parameter types list was omitted  at the source
1983fd31de5Schristos              * level. Use the Argument count parameter instead.
1993fd31de5Schristos              */
2003fd31de5Schristos             ActualArgs = MethodInfo->NumArguments;
201ff4a156dSchristos         }
202ff4a156dSchristos         else
203ff4a156dSchristos         {
2043fd31de5Schristos             ActualArgs = MtProcessParameterTypeList (NextType,
2053fd31de5Schristos                 MethodInfo->ValidArgTypes);
20667c34082Schristos             MethodInfo->NumArguments = ActualArgs;
20767c34082Schristos             ArgNode->Asl.Value.Integer |= ActualArgs;
208ff4a156dSchristos         }
209ff4a156dSchristos 
210ff4a156dSchristos         if ((MethodInfo->NumArguments) &&
211ff4a156dSchristos             (MethodInfo->NumArguments != ActualArgs))
212ff4a156dSchristos         {
2133fd31de5Schristos             sprintf (AslGbl_MsgBuffer,
2143fd31de5Schristos                 "Length = %u", ActualArgs);
2153fd31de5Schristos             AslError (ASL_ERROR, ASL_MSG_ARG_COUNT_MISMATCH,
2163fd31de5Schristos                 Op->Asl.Child->Asl.Next, AslGbl_MsgBuffer);
217ff4a156dSchristos         }
218ff4a156dSchristos 
219ff4a156dSchristos         /* Allow numarguments == 0 for Function() */
220ff4a156dSchristos 
221ff4a156dSchristos         if ((!MethodInfo->NumArguments) && (ActualArgs))
222ff4a156dSchristos         {
223ff4a156dSchristos             MethodInfo->NumArguments = ActualArgs;
224ff4a156dSchristos             ArgNode->Asl.Value.Integer |= ActualArgs;
225ff4a156dSchristos         }
226ff4a156dSchristos 
227ff4a156dSchristos         /*
228ff4a156dSchristos          * Actual arguments are initialized at method entry.
229ff4a156dSchristos          * All other ArgX "registers" can be used as locals, so we
230ff4a156dSchristos          * track their initialization.
231ff4a156dSchristos          */
232ff4a156dSchristos         for (i = 0; i < MethodInfo->NumArguments; i++)
233ff4a156dSchristos         {
234ff4a156dSchristos             MethodInfo->ArgInitialized[i] = TRUE;
235ff4a156dSchristos         }
236ff4a156dSchristos         break;
237ff4a156dSchristos 
238ff4a156dSchristos     case PARSEOP_METHODCALL:
239ff4a156dSchristos 
240b406f703Schristos         /* Check for a recursive method call */
241b406f703Schristos 
242ff4a156dSchristos         if (MethodInfo &&
243ff4a156dSchristos            (Op->Asl.Node == MethodInfo->Op->Asl.Node))
244ff4a156dSchristos         {
245b406f703Schristos             if (MethodInfo->CreatesNamedObjects)
246b406f703Schristos             {
247b406f703Schristos                 /*
248b406f703Schristos                  * This is an error, as it will fail at runtime on all ACPI
249b406f703Schristos                  * implementations. Any named object declarations will be
250b406f703Schristos                  * executed twice, causing failure the second time. Note,
251b406f703Schristos                  * this is independent of whether the method is declared
252b406f703Schristos                  * Serialized, because the same thread is attempting to
253b406f703Schristos                  * reenter the method, and this will always succeed.
254b406f703Schristos                  */
255b406f703Schristos                 AslDualParseOpError (ASL_ERROR, ASL_MSG_ILLEGAL_RECURSION, Op,
256b406f703Schristos                     Op->Asl.Value.String, ASL_MSG_FOUND_HERE, MethodInfo->Op,
257b406f703Schristos                     MethodInfo->Op->Asl.ExternalName);
258b406f703Schristos             }
259b406f703Schristos             else
260b406f703Schristos             {
261b406f703Schristos                 /* Method does not create objects, issue a remark */
262b406f703Schristos 
263ff4a156dSchristos                 AslError (ASL_REMARK, ASL_MSG_RECURSION, Op, Op->Asl.ExternalName);
264ff4a156dSchristos             }
265b406f703Schristos         }
266ff4a156dSchristos         break;
267ff4a156dSchristos 
268ff4a156dSchristos     case PARSEOP_LOCAL0:
269ff4a156dSchristos     case PARSEOP_LOCAL1:
270ff4a156dSchristos     case PARSEOP_LOCAL2:
271ff4a156dSchristos     case PARSEOP_LOCAL3:
272ff4a156dSchristos     case PARSEOP_LOCAL4:
273ff4a156dSchristos     case PARSEOP_LOCAL5:
274ff4a156dSchristos     case PARSEOP_LOCAL6:
275ff4a156dSchristos     case PARSEOP_LOCAL7:
276ff4a156dSchristos 
277ff4a156dSchristos         if (!MethodInfo)
278ff4a156dSchristos         {
279ff4a156dSchristos             /*
280ff4a156dSchristos              * Local was used outside a control method, or there was an error
281ff4a156dSchristos              * in the method declaration.
282ff4a156dSchristos              */
28371e38f1dSchristos             AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD,
28471e38f1dSchristos                 Op, Op->Asl.ExternalName);
285ff4a156dSchristos             return (AE_ERROR);
286ff4a156dSchristos         }
287ff4a156dSchristos 
288c72da027Schristos         RegisterNumber = (Op->Asl.AmlOpcode & 0x0007);
289ff4a156dSchristos 
290ff4a156dSchristos         /*
291ff4a156dSchristos          * If the local is being used as a target, mark the local
292ff4a156dSchristos          * initialized
293ff4a156dSchristos          */
29489b8eb6cSchristos         if (Op->Asl.CompileFlags & OP_IS_TARGET)
295ff4a156dSchristos         {
296ff4a156dSchristos             MethodInfo->LocalInitialized[RegisterNumber] = TRUE;
297ff4a156dSchristos         }
298ff4a156dSchristos 
299ff4a156dSchristos         /*
300ff4a156dSchristos          * Otherwise, this is a reference, check if the local
301ff4a156dSchristos          * has been previously initialized.
302ff4a156dSchristos          *
303ff4a156dSchristos          * The only operator that accepts an uninitialized value is ObjectType()
304ff4a156dSchristos          */
305ff4a156dSchristos         else if ((!MethodInfo->LocalInitialized[RegisterNumber]) &&
306ff4a156dSchristos                  (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
307ff4a156dSchristos         {
308ff4a156dSchristos             LocalName[strlen (LocalName) -1] = (char) (RegisterNumber + 0x30);
309ff4a156dSchristos             AslError (ASL_ERROR, ASL_MSG_LOCAL_INIT, Op, LocalName);
310ff4a156dSchristos         }
311ff4a156dSchristos         break;
312ff4a156dSchristos 
313ff4a156dSchristos     case PARSEOP_ARG0:
314ff4a156dSchristos     case PARSEOP_ARG1:
315ff4a156dSchristos     case PARSEOP_ARG2:
316ff4a156dSchristos     case PARSEOP_ARG3:
317ff4a156dSchristos     case PARSEOP_ARG4:
318ff4a156dSchristos     case PARSEOP_ARG5:
319ff4a156dSchristos     case PARSEOP_ARG6:
320ff4a156dSchristos 
321ff4a156dSchristos         if (!MethodInfo)
322ff4a156dSchristos         {
323ff4a156dSchristos             /*
324ff4a156dSchristos              * Arg was used outside a control method, or there was an error
325ff4a156dSchristos              * in the method declaration.
326ff4a156dSchristos              */
32771e38f1dSchristos             AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD,
32871e38f1dSchristos                 Op, Op->Asl.ExternalName);
329ff4a156dSchristos             return (AE_ERROR);
330ff4a156dSchristos         }
331ff4a156dSchristos 
332ff4a156dSchristos         RegisterNumber = (Op->Asl.AmlOpcode & 0x000F) - 8;
333ff4a156dSchristos         ArgName[strlen (ArgName) -1] = (char) (RegisterNumber + 0x30);
334ff4a156dSchristos 
335ff4a156dSchristos         /*
336ff4a156dSchristos          * If the Arg is being used as a target, mark the local
337ff4a156dSchristos          * initialized
338ff4a156dSchristos          */
33989b8eb6cSchristos         if (Op->Asl.CompileFlags & OP_IS_TARGET)
340ff4a156dSchristos         {
341ff4a156dSchristos             MethodInfo->ArgInitialized[RegisterNumber] = TRUE;
342ff4a156dSchristos         }
343ff4a156dSchristos 
344ff4a156dSchristos         /*
345ff4a156dSchristos          * Otherwise, this is a reference, check if the Arg
346ff4a156dSchristos          * has been previously initialized.
347ff4a156dSchristos          *
348ff4a156dSchristos          * The only operator that accepts an uninitialized value is ObjectType()
349ff4a156dSchristos          */
350ff4a156dSchristos         else if ((!MethodInfo->ArgInitialized[RegisterNumber]) &&
351ff4a156dSchristos             (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
352ff4a156dSchristos         {
353ff4a156dSchristos             AslError (ASL_ERROR, ASL_MSG_ARG_INIT, Op, ArgName);
354ff4a156dSchristos         }
355ff4a156dSchristos 
356ff4a156dSchristos         /* Flag this arg if it is not a "real" argument to the method */
357ff4a156dSchristos 
358ff4a156dSchristos         if (RegisterNumber >= MethodInfo->NumArguments)
359ff4a156dSchristos         {
360ff4a156dSchristos             AslError (ASL_REMARK, ASL_MSG_NOT_PARAMETER, Op, ArgName);
361ff4a156dSchristos         }
362ff4a156dSchristos         break;
363ff4a156dSchristos 
364ff4a156dSchristos     case PARSEOP_RETURN:
365ff4a156dSchristos 
366ff4a156dSchristos         if (!MethodInfo)
367ff4a156dSchristos         {
368ff4a156dSchristos             /*
369ff4a156dSchristos              * Probably was an error in the method declaration,
370ff4a156dSchristos              * no additional error here
371ff4a156dSchristos              */
372ff4a156dSchristos             ACPI_WARNING ((AE_INFO, "%p, No parent method", Op));
373ff4a156dSchristos             return (AE_ERROR);
374ff4a156dSchristos         }
375ff4a156dSchristos 
376ff4a156dSchristos         /*
377ff4a156dSchristos          * A child indicates a possible return value. A simple Return or
37889b8eb6cSchristos          * Return() is marked with OP_IS_NULL_RETURN by the parser so
379ff4a156dSchristos          * that it is not counted as a "real" return-with-value, although
380ff4a156dSchristos          * the AML code that is actually emitted is Return(0). The AML
381ff4a156dSchristos          * definition of Return has a required parameter, so we are
382ff4a156dSchristos          * forced to convert a null return to Return(0).
383ff4a156dSchristos          */
384ff4a156dSchristos         if ((Op->Asl.Child) &&
385ff4a156dSchristos             (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
38689b8eb6cSchristos             (!(Op->Asl.Child->Asl.CompileFlags & OP_IS_NULL_RETURN)))
387ff4a156dSchristos         {
388ff4a156dSchristos             MethodInfo->NumReturnWithValue++;
389ff4a156dSchristos         }
390ff4a156dSchristos         else
391ff4a156dSchristos         {
392ff4a156dSchristos             MethodInfo->NumReturnNoValue++;
393ff4a156dSchristos         }
394ff4a156dSchristos         break;
395ff4a156dSchristos 
396ff4a156dSchristos     case PARSEOP_BREAK:
397ff4a156dSchristos     case PARSEOP_CONTINUE:
398ff4a156dSchristos 
399ff4a156dSchristos         Next = Op->Asl.Parent;
400ff4a156dSchristos         while (Next)
401ff4a156dSchristos         {
402ff4a156dSchristos             if (Next->Asl.ParseOpcode == PARSEOP_WHILE)
403ff4a156dSchristos             {
404ff4a156dSchristos                 break;
405ff4a156dSchristos             }
406ff4a156dSchristos             Next = Next->Asl.Parent;
407ff4a156dSchristos         }
408ff4a156dSchristos 
409ff4a156dSchristos         if (!Next)
410ff4a156dSchristos         {
411ff4a156dSchristos             AslError (ASL_ERROR, ASL_MSG_NO_WHILE, Op, NULL);
412ff4a156dSchristos         }
413ff4a156dSchristos         break;
414ff4a156dSchristos 
415ff4a156dSchristos     case PARSEOP_STALL:
416ff4a156dSchristos 
417ff4a156dSchristos         /* We can range check if the argument is an integer */
418ff4a156dSchristos 
419ff4a156dSchristos         if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
420ff4a156dSchristos             (Op->Asl.Child->Asl.Value.Integer > ACPI_UINT8_MAX))
421ff4a156dSchristos         {
422ff4a156dSchristos             AslError (ASL_ERROR, ASL_MSG_INVALID_TIME, Op, NULL);
423ff4a156dSchristos         }
424ff4a156dSchristos         break;
425ff4a156dSchristos 
426ff4a156dSchristos     case PARSEOP_DEVICE:
427460301d4Schristos 
42832aedd46Schristos         /* Check usage of _HID and _ADR objects */
42932aedd46Schristos 
43032aedd46Schristos         HidExists = ApFindNameInDeviceTree (METHOD_NAME__HID, Op);
43132aedd46Schristos         AdrExists = ApFindNameInDeviceTree (METHOD_NAME__ADR, Op);
43232aedd46Schristos 
43332aedd46Schristos         if (!HidExists && !AdrExists)
434460301d4Schristos         {
43530370826Schristos             AslError (ASL_ERROR, ASL_MSG_MISSING_DEPENDENCY, Op,
43630370826Schristos                 "Device object requires a _HID or _ADR");
437460301d4Schristos         }
43832aedd46Schristos         else if (HidExists && AdrExists)
43932aedd46Schristos         {
44032aedd46Schristos             /*
44132aedd46Schristos              * According to the ACPI spec, "A device object must contain
44232aedd46Schristos              * either an _HID object or an _ADR object, but should not contain
44332aedd46Schristos              * both".
44432aedd46Schristos              */
44532aedd46Schristos             AslError (ASL_WARNING, ASL_MSG_MULTIPLE_TYPES, Op,
44632aedd46Schristos                 "Device object requires either a _HID or _ADR, but not both");
44732aedd46Schristos         }
44830370826Schristos 
44930370826Schristos         /*
45030370826Schristos          * Check usage of _CRS, _DIS, _PRS, and _SRS objects (July 2021).
45130370826Schristos          *
45230370826Schristos          * Under the Device Object:
45330370826Schristos          *
45430370826Schristos          * 1) If _PRS present, must have _CRS and _SRS
45530370826Schristos          * 2) If _SRS present, must have _PRS (_PRS requires _CRS and _SRS)
45630370826Schristos          * 3) If _DIS present, must have _SRS (_SRS requires _PRS, _PRS requires _CRS and _SRS)
45730370826Schristos          * 4) If _SRS present, probably should have a _DIS (Remark only)
45830370826Schristos          */
45930370826Schristos         CrsExists = ApFindNameInDeviceTree (METHOD_NAME__CRS, Op);
46030370826Schristos         DisExists = ApFindNameInDeviceTree (METHOD_NAME__DIS, Op);
46130370826Schristos         PrsExists = ApFindNameInDeviceTree (METHOD_NAME__PRS, Op);
46230370826Schristos         SrsExists = ApFindNameInDeviceTree (METHOD_NAME__SRS, Op);
46330370826Schristos 
46430370826Schristos         /* 1) If _PRS is present, must have a _CRS and _SRS */
46530370826Schristos 
46630370826Schristos         if (PrsExists)
46730370826Schristos         {
46830370826Schristos             if (!CrsExists)
46930370826Schristos             {
47030370826Schristos                 AslError (ASL_WARNING, ASL_MSG_MISSING_DEPENDENCY, Op,
47130370826Schristos                     "Device has a _PRS, missing a _CRS, required");
47230370826Schristos             }
47330370826Schristos             if (!SrsExists)
47430370826Schristos             {
47530370826Schristos                 AslError (ASL_WARNING, ASL_MSG_MISSING_DEPENDENCY, Op,
47630370826Schristos                     "Device has a _PRS, missing a _SRS, required");
47730370826Schristos             }
47830370826Schristos         }
47930370826Schristos 
48030370826Schristos         /* 2) If _SRS is present, must have _PRS (_PRS requires _CRS and _SRS) */
48130370826Schristos 
48230370826Schristos         if ((SrsExists) && (!PrsExists))
48330370826Schristos         {
48430370826Schristos             AslError (ASL_WARNING, ASL_MSG_MISSING_DEPENDENCY, Op,
48530370826Schristos                 "Device has a _SRS, missing a _PRS, required");
48630370826Schristos         }
48730370826Schristos 
48830370826Schristos         /* 3) If _DIS is present, must have a _SRS */
48930370826Schristos 
49030370826Schristos         if ((DisExists) && (!SrsExists))
49130370826Schristos         {
49230370826Schristos             AslError (ASL_WARNING, ASL_MSG_MISSING_DEPENDENCY, Op,
49330370826Schristos                 "Device has a _DIS, missing a _SRS, required");
49430370826Schristos         }
49530370826Schristos 
49630370826Schristos         /*
49730370826Schristos          * 4) If _SRS is present, should have a _DIS (_PRS requires _CRS
49830370826Schristos          * and _SRS)  Remark only.
49930370826Schristos          */
50030370826Schristos         if ((SrsExists) && (!DisExists))
50130370826Schristos         {
50230370826Schristos             AslError (ASL_REMARK, ASL_MSG_MISSING_DEPENDENCY, Op,
50330370826Schristos                 "Device has a _SRS, no corresponding _DIS");
50430370826Schristos         }
505460301d4Schristos         break;
506460301d4Schristos 
507ff4a156dSchristos     case PARSEOP_EVENT:
508ff4a156dSchristos     case PARSEOP_MUTEX:
509ff4a156dSchristos     case PARSEOP_OPERATIONREGION:
510ff4a156dSchristos     case PARSEOP_POWERRESOURCE:
511ff4a156dSchristos     case PARSEOP_PROCESSOR:
512ff4a156dSchristos     case PARSEOP_THERMALZONE:
513ff4a156dSchristos 
514ff4a156dSchristos         /*
515ff4a156dSchristos          * The first operand is a name to be created in the namespace.
516ff4a156dSchristos          * Check against the reserved list.
517ff4a156dSchristos          */
518ff4a156dSchristos         i = ApCheckForPredefinedName (Op, Op->Asl.NameSeg);
519ff4a156dSchristos         if (i < ACPI_VALID_RESERVED_NAME_MAX)
520ff4a156dSchristos         {
52171e38f1dSchristos             AslError (ASL_ERROR, ASL_MSG_RESERVED_USE,
52271e38f1dSchristos                 Op, Op->Asl.ExternalName);
523ff4a156dSchristos         }
5243fd31de5Schristos 
5253fd31de5Schristos         MtCheckStaticOperationRegionInMethod (Op);
526ff4a156dSchristos         break;
527ff4a156dSchristos 
528ff4a156dSchristos     case PARSEOP_NAME:
529ff4a156dSchristos 
530ff4a156dSchristos         /* Typecheck any predefined names statically defined with Name() */
531ff4a156dSchristos 
532ff4a156dSchristos         ApCheckForPredefinedObject (Op, Op->Asl.NameSeg);
533ff4a156dSchristos 
534ff4a156dSchristos         /* Special typechecking for _HID */
535ff4a156dSchristos 
53632aedd46Schristos         if (ACPI_COMPARE_NAMESEG (METHOD_NAME__HID, Op->Asl.NameSeg))
537ff4a156dSchristos         {
538ff4a156dSchristos             Next = Op->Asl.Child->Asl.Next;
539ff4a156dSchristos             AnCheckId (Next, ASL_TYPE_HID);
540ff4a156dSchristos         }
541ff4a156dSchristos 
542ff4a156dSchristos         /* Special typechecking for _CID */
543ff4a156dSchristos 
54432aedd46Schristos         else if (ACPI_COMPARE_NAMESEG (METHOD_NAME__CID, Op->Asl.NameSeg))
545ff4a156dSchristos         {
546ff4a156dSchristos             Next = Op->Asl.Child->Asl.Next;
547ff4a156dSchristos 
548ff4a156dSchristos             if ((Next->Asl.ParseOpcode == PARSEOP_PACKAGE) ||
549ff4a156dSchristos                 (Next->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE))
550ff4a156dSchristos             {
551ff4a156dSchristos                 Next = Next->Asl.Child;
552ff4a156dSchristos                 while (Next)
553ff4a156dSchristos                 {
554ff4a156dSchristos                     AnCheckId (Next, ASL_TYPE_CID);
555ff4a156dSchristos                     Next = Next->Asl.Next;
556ff4a156dSchristos                 }
557ff4a156dSchristos             }
558ff4a156dSchristos             else
559ff4a156dSchristos             {
560ff4a156dSchristos                 AnCheckId (Next, ASL_TYPE_CID);
561ff4a156dSchristos             }
562ff4a156dSchristos         }
563460301d4Schristos 
564ff4a156dSchristos         break;
565ff4a156dSchristos 
566ff4a156dSchristos     default:
567ff4a156dSchristos 
568ff4a156dSchristos         break;
569ff4a156dSchristos     }
570ff4a156dSchristos 
571ff4a156dSchristos     /* Check for named object creation within a non-serialized method */
572ff4a156dSchristos 
573ff4a156dSchristos     MtCheckNamedObjectInMethod (Op, MethodInfo);
574ff4a156dSchristos     return (AE_OK);
575ff4a156dSchristos }
576ff4a156dSchristos 
577ff4a156dSchristos 
578ff4a156dSchristos /*******************************************************************************
579ff4a156dSchristos  *
5803fd31de5Schristos  * FUNCTION:    MtProcessTypeOp
5813fd31de5Schristos  *
5823fd31de5Schristos  * PARAMETERS:  Op                  - Op representing a btype
5833fd31de5Schristos  *
5843fd31de5Schristos  * RETURN:      Btype represented by Op
5853fd31de5Schristos  *
5863fd31de5Schristos  * DESCRIPTION: Process a parse object that represents single parameter type or
5873fd31de5Schristos  *              a return type in method, function, and external declarations.
5883fd31de5Schristos  *
5893fd31de5Schristos  ******************************************************************************/
5903fd31de5Schristos 
5913fd31de5Schristos UINT32
MtProcessTypeOp(ACPI_PARSE_OBJECT * TypeOp)5923fd31de5Schristos MtProcessTypeOp (
5933fd31de5Schristos     ACPI_PARSE_OBJECT       *TypeOp)
5943fd31de5Schristos {
5953fd31de5Schristos     UINT32                  Btype = ACPI_BTYPE_ANY;
5963fd31de5Schristos 
5973fd31de5Schristos 
5983fd31de5Schristos     while (TypeOp)
5993fd31de5Schristos     {
6003fd31de5Schristos         Btype |= AnMapObjTypeToBtype (TypeOp);
6013fd31de5Schristos         TypeOp->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
6023fd31de5Schristos         TypeOp = TypeOp->Asl.Next;
6033fd31de5Schristos     }
6043fd31de5Schristos 
6053fd31de5Schristos     return (Btype);
6063fd31de5Schristos }
6073fd31de5Schristos 
6083fd31de5Schristos 
6093fd31de5Schristos /*******************************************************************************
6103fd31de5Schristos  *
6113fd31de5Schristos  * FUNCTION:    MtProcessParameterTypeList
6123fd31de5Schristos  *
6133fd31de5Schristos  * PARAMETERS:  Op                  - Op representing a btype
6143fd31de5Schristos  *
6153fd31de5Schristos  * RETURN:      Btype represented by Op
6163fd31de5Schristos  *
6173fd31de5Schristos  * DESCRIPTION: Process a parse object that represents a parameter type list in
6183fd31de5Schristos  *              method, function, and external declarations.
6193fd31de5Schristos  *
6203fd31de5Schristos  ******************************************************************************/
6213fd31de5Schristos 
6223fd31de5Schristos UINT8
MtProcessParameterTypeList(ACPI_PARSE_OBJECT * ParamTypeOp,UINT32 * TypeList)6233fd31de5Schristos MtProcessParameterTypeList (
6243fd31de5Schristos     ACPI_PARSE_OBJECT       *ParamTypeOp,
6253fd31de5Schristos     UINT32                  *TypeList)
6263fd31de5Schristos {
6273fd31de5Schristos     UINT8                   ParameterCount = 0;
6283fd31de5Schristos 
6293fd31de5Schristos 
63067c34082Schristos     if (ParamTypeOp && ParamTypeOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)
63167c34082Schristos     {
63267c34082Schristos         /* Special case for a single parameter without braces */
63367c34082Schristos 
63467c34082Schristos         TypeList[ParameterCount] =
63567c34082Schristos             MtProcessTypeOp (ParamTypeOp);
63667c34082Schristos 
63767c34082Schristos         return (1);
63867c34082Schristos     }
63967c34082Schristos 
6403fd31de5Schristos     while (ParamTypeOp)
6413fd31de5Schristos     {
6423fd31de5Schristos         TypeList[ParameterCount] =
6433fd31de5Schristos             MtProcessTypeOp (ParamTypeOp->Asl.Child);
6443fd31de5Schristos 
6453fd31de5Schristos         ParameterCount++;
6463fd31de5Schristos         ParamTypeOp = ParamTypeOp->Asl.Next;
6473fd31de5Schristos     }
6483fd31de5Schristos 
6493fd31de5Schristos     return (ParameterCount);
6503fd31de5Schristos }
6513fd31de5Schristos 
6523fd31de5Schristos 
6533fd31de5Schristos /*******************************************************************************
6543fd31de5Schristos  *
655ff4a156dSchristos  * FUNCTION:    MtCheckNamedObjectInMethod
656ff4a156dSchristos  *
657ff4a156dSchristos  * PARAMETERS:  Op                  - Current parser op
658ff4a156dSchristos  *              MethodInfo          - Info for method being parsed
659ff4a156dSchristos  *
660ff4a156dSchristos  * RETURN:      None
661ff4a156dSchristos  *
662ff4a156dSchristos  * DESCRIPTION: Detect if a non-serialized method is creating a named object,
663ff4a156dSchristos  *              which could possibly cause problems if two threads execute
664ff4a156dSchristos  *              the method concurrently. Emit a remark in this case.
665ff4a156dSchristos  *
666ff4a156dSchristos  ******************************************************************************/
667ff4a156dSchristos 
668cfbb7280Schristos static void
MtCheckNamedObjectInMethod(ACPI_PARSE_OBJECT * Op,ASL_METHOD_INFO * MethodInfo)669ff4a156dSchristos MtCheckNamedObjectInMethod (
670ff4a156dSchristos     ACPI_PARSE_OBJECT       *Op,
671ff4a156dSchristos     ASL_METHOD_INFO         *MethodInfo)
672ff4a156dSchristos {
673ff4a156dSchristos     const ACPI_OPCODE_INFO  *OpInfo;
6743fd31de5Schristos     char                    *ExternalPath;
675ff4a156dSchristos 
676ff4a156dSchristos 
67771e38f1dSchristos     /* We don't care about actual method declarations or scopes */
678ff4a156dSchristos 
67971e38f1dSchristos     if ((Op->Asl.AmlOpcode == AML_METHOD_OP) ||
68071e38f1dSchristos         (Op->Asl.AmlOpcode == AML_SCOPE_OP))
681ff4a156dSchristos     {
682ff4a156dSchristos         return;
683ff4a156dSchristos     }
684ff4a156dSchristos 
685b406f703Schristos     /* Determine if we are creating a named object within a method */
686b406f703Schristos 
687b406f703Schristos     if (!MethodInfo)
688b406f703Schristos     {
689b406f703Schristos         return;
690b406f703Schristos     }
691ff4a156dSchristos 
692ff4a156dSchristos     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
69367c34082Schristos     if ((OpInfo->Class == AML_CLASS_NAMED_OBJECT) && (Op->Asl.AmlOpcode != AML_FIELD_OP))
694ff4a156dSchristos     {
695ff4a156dSchristos         /*
696b406f703Schristos          * 1) Mark the method as a method that creates named objects.
697b406f703Schristos          *
6983fd31de5Schristos          * 2) Issue a remark indicating the inefficiency of creating named
6993fd31de5Schristos          * objects within a method (Except for compiler-emitted temporary
7003fd31de5Schristos          * variables).
7013fd31de5Schristos          *
7023fd31de5Schristos          * 3) If the method is non-serialized, emit a remark that the method
703b406f703Schristos          * should be serialized.
704ff4a156dSchristos          *
705ff4a156dSchristos          * Reason: If a thread blocks within the method for any reason, and
706b406f703Schristos          * another thread enters the method, the method will fail because
707b406f703Schristos          * an attempt will be made to create the same object twice.
70867c34082Schristos          *
70967c34082Schristos          * Note: The Field opcode is disallowed here because Field() does not
71067c34082Schristos          * create a new named object.
711ff4a156dSchristos          */
7123fd31de5Schristos         ExternalPath = AcpiNsGetNormalizedPathname (MethodInfo->Op->Asl.Node, TRUE);
7133fd31de5Schristos 
7143fd31de5Schristos         /* No error for compiler temp variables (name starts with "_T_") */
7153fd31de5Schristos 
7163fd31de5Schristos         if ((Op->Asl.NameSeg[0] != '_') &&
7173fd31de5Schristos             (Op->Asl.NameSeg[1] != 'T') &&
7183fd31de5Schristos             (Op->Asl.NameSeg[2] != '_'))
7193fd31de5Schristos         {
7203fd31de5Schristos             AslError (ASL_REMARK, ASL_MSG_NAMED_OBJECT_CREATION, Op,
7213fd31de5Schristos                 ExternalPath);
7223fd31de5Schristos         }
7233fd31de5Schristos 
724b406f703Schristos         MethodInfo->CreatesNamedObjects = TRUE;
725b406f703Schristos         if (!MethodInfo->ShouldBeSerialized)
726ff4a156dSchristos         {
727ff4a156dSchristos             AslError (ASL_REMARK, ASL_MSG_SERIALIZED_REQUIRED, MethodInfo->Op,
7283fd31de5Schristos                 ExternalPath);
729ff4a156dSchristos 
730ff4a156dSchristos             /* Emit message only ONCE per method */
731ff4a156dSchristos 
732ff4a156dSchristos             MethodInfo->ShouldBeSerialized = TRUE;
733ff4a156dSchristos         }
7343fd31de5Schristos 
7353fd31de5Schristos         if (ExternalPath)
7363fd31de5Schristos         {
7373fd31de5Schristos             ACPI_FREE (ExternalPath);
738ff4a156dSchristos         }
739ff4a156dSchristos     }
7403fd31de5Schristos }
7413fd31de5Schristos 
7423fd31de5Schristos 
7433fd31de5Schristos /*******************************************************************************
7443fd31de5Schristos  *
7453fd31de5Schristos  * FUNCTION:    MtCheckStaticOperationRegionInMethod
7463fd31de5Schristos  *
7473fd31de5Schristos  * PARAMETERS:  Op                  - Current parser op
7483fd31de5Schristos  *
7493fd31de5Schristos  * RETURN:      None
7503fd31de5Schristos  *
7513fd31de5Schristos  * DESCRIPTION: Warns if an Operation Region with static address or length
7523fd31de5Schristos  *              is declared inside a control method
7533fd31de5Schristos  *
7543fd31de5Schristos  ******************************************************************************/
7553fd31de5Schristos 
7563fd31de5Schristos static void
MtCheckStaticOperationRegionInMethod(ACPI_PARSE_OBJECT * Op)7573fd31de5Schristos MtCheckStaticOperationRegionInMethod(
7583fd31de5Schristos     ACPI_PARSE_OBJECT*       Op)
7593fd31de5Schristos {
7603fd31de5Schristos     ACPI_PARSE_OBJECT*       AddressOp;
7613fd31de5Schristos     ACPI_PARSE_OBJECT*       LengthOp;
7623fd31de5Schristos 
7633fd31de5Schristos 
7643fd31de5Schristos     if (Op->Asl.ParseOpcode != PARSEOP_OPERATIONREGION)
7653fd31de5Schristos     {
7663fd31de5Schristos         return;
7673fd31de5Schristos     }
7683fd31de5Schristos 
7693fd31de5Schristos     /*
7703fd31de5Schristos      * OperationRegion should have 4 arguments defined. At this point, we
7713fd31de5Schristos      * assume that the parse tree is well-formed.
7723fd31de5Schristos      */
7733fd31de5Schristos     AddressOp = Op->Asl.Child->Asl.Next->Asl.Next;
7743fd31de5Schristos     LengthOp = Op->Asl.Child->Asl.Next->Asl.Next->Asl.Next;
7753fd31de5Schristos 
7763fd31de5Schristos     if (UtGetParentMethodOp (Op) &&
7773fd31de5Schristos         AddressOp->Asl.ParseOpcode == PARSEOP_INTEGER &&
7783fd31de5Schristos         LengthOp->Asl.ParseOpcode == PARSEOP_INTEGER)
7793fd31de5Schristos     {
7803fd31de5Schristos         /*
7813fd31de5Schristos          * At this point, a static operation region declared inside of a
7823fd31de5Schristos          * control method has been found. Throw a warning because this is
7833fd31de5Schristos          * highly inefficient.
7843fd31de5Schristos          */
7853fd31de5Schristos         AslError(ASL_WARNING, ASL_MSG_STATIC_OPREGION_IN_METHOD, Op, NULL);
7863fd31de5Schristos     }
7873fd31de5Schristos 
7883fd31de5Schristos     return;
7893fd31de5Schristos }
790ff4a156dSchristos 
791ff4a156dSchristos 
792ff4a156dSchristos /*******************************************************************************
793ff4a156dSchristos  *
794ff4a156dSchristos  * FUNCTION:    MtMethodAnalysisWalkEnd
795ff4a156dSchristos  *
796ff4a156dSchristos  * PARAMETERS:  ASL_WALK_CALLBACK
797ff4a156dSchristos  *
798ff4a156dSchristos  * RETURN:      Status
799ff4a156dSchristos  *
800ff4a156dSchristos  * DESCRIPTION: Ascending callback for analysis walk. Complete method
801ff4a156dSchristos  *              return analysis.
802ff4a156dSchristos  *
803ff4a156dSchristos  ******************************************************************************/
804ff4a156dSchristos 
805ff4a156dSchristos ACPI_STATUS
MtMethodAnalysisWalkEnd(ACPI_PARSE_OBJECT * Op,UINT32 Level,void * Context)806ff4a156dSchristos MtMethodAnalysisWalkEnd (
807ff4a156dSchristos     ACPI_PARSE_OBJECT       *Op,
808ff4a156dSchristos     UINT32                  Level,
809ff4a156dSchristos     void                    *Context)
810ff4a156dSchristos {
811ff4a156dSchristos     ASL_ANALYSIS_WALK_INFO  *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
812ff4a156dSchristos     ASL_METHOD_INFO         *MethodInfo = WalkInfo->MethodStack;
8133fd31de5Schristos     char                    *ExternalPath;
814ff4a156dSchristos 
815ff4a156dSchristos 
816ff4a156dSchristos     switch (Op->Asl.ParseOpcode)
817ff4a156dSchristos     {
818ff4a156dSchristos     case PARSEOP_METHOD:
819ff4a156dSchristos     case PARSEOP_RETURN:
820ff4a156dSchristos 
821ff4a156dSchristos         if (!MethodInfo)
822ff4a156dSchristos         {
823ff4a156dSchristos             printf ("No method info for method! [%s]\n", Op->Asl.Namepath);
824ff4a156dSchristos             AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
825ff4a156dSchristos                 "No method info for this method");
826ff4a156dSchristos 
827ff4a156dSchristos             CmCleanupAndExit ();
828ff4a156dSchristos             return (AE_AML_INTERNAL);
829ff4a156dSchristos         }
830ff4a156dSchristos         break;
831ff4a156dSchristos 
832ff4a156dSchristos     default:
833ff4a156dSchristos 
834ff4a156dSchristos         break;
835ff4a156dSchristos     }
836ff4a156dSchristos 
837ff4a156dSchristos     switch (Op->Asl.ParseOpcode)
838ff4a156dSchristos     {
839ff4a156dSchristos     case PARSEOP_METHOD:
840ff4a156dSchristos 
841ff4a156dSchristos         WalkInfo->MethodStack = MethodInfo->Next;
842ff4a156dSchristos 
843ff4a156dSchristos         /*
844ff4a156dSchristos          * Check if there is no return statement at the end of the
845ff4a156dSchristos          * method AND we can actually get there -- i.e., the execution
846ff4a156dSchristos          * of the method can possibly terminate without a return statement.
847ff4a156dSchristos          */
848ff4a156dSchristos         if ((!AnLastStatementIsReturn (Op)) &&
84989b8eb6cSchristos             (!(Op->Asl.CompileFlags & OP_HAS_NO_EXIT)))
850ff4a156dSchristos         {
851ff4a156dSchristos             /*
852ff4a156dSchristos              * No return statement, and execution can possibly exit
853ff4a156dSchristos              * via this path. This is equivalent to Return ()
854ff4a156dSchristos              */
855ff4a156dSchristos             MethodInfo->NumReturnNoValue++;
856ff4a156dSchristos         }
857ff4a156dSchristos 
858ff4a156dSchristos         /*
859ff4a156dSchristos          * Check for case where some return statements have a return value
860ff4a156dSchristos          * and some do not. Exit without a return statement is a return with
861ff4a156dSchristos          * no value
862ff4a156dSchristos          */
863ff4a156dSchristos         if (MethodInfo->NumReturnNoValue &&
864ff4a156dSchristos             MethodInfo->NumReturnWithValue)
865ff4a156dSchristos         {
8663fd31de5Schristos             ExternalPath = AcpiNsGetNormalizedPathname (Op->Asl.Node, TRUE);
8673fd31de5Schristos 
868ff4a156dSchristos             AslError (ASL_WARNING, ASL_MSG_RETURN_TYPES, Op,
8693fd31de5Schristos                 ExternalPath);
8703fd31de5Schristos 
8713fd31de5Schristos             if (ExternalPath)
8723fd31de5Schristos             {
8733fd31de5Schristos                 ACPI_FREE (ExternalPath);
8743fd31de5Schristos             }
875ff4a156dSchristos         }
876ff4a156dSchristos 
877ff4a156dSchristos         /*
878ff4a156dSchristos          * If there are any RETURN() statements with no value, or there is a
879ff4a156dSchristos          * control path that allows the method to exit without a return value,
880ff4a156dSchristos          * we mark the method as a method that does not return a value. This
881ff4a156dSchristos          * knowledge can be used to check method invocations that expect a
882ff4a156dSchristos          * returned value.
883ff4a156dSchristos          */
884ff4a156dSchristos         if (MethodInfo->NumReturnNoValue)
885ff4a156dSchristos         {
886ff4a156dSchristos             if (MethodInfo->NumReturnWithValue)
887ff4a156dSchristos             {
88889b8eb6cSchristos                 Op->Asl.CompileFlags |= OP_METHOD_SOME_NO_RETVAL;
889ff4a156dSchristos             }
890ff4a156dSchristos             else
891ff4a156dSchristos             {
89289b8eb6cSchristos                 Op->Asl.CompileFlags |= OP_METHOD_NO_RETVAL;
893ff4a156dSchristos             }
894ff4a156dSchristos         }
895ff4a156dSchristos 
896ff4a156dSchristos         /*
897ff4a156dSchristos          * Check predefined method names for correct return behavior
898ff4a156dSchristos          * and correct number of arguments. Also, some special checks
899ff4a156dSchristos          * For GPE and _REG methods.
900ff4a156dSchristos          */
901ff4a156dSchristos         if (ApCheckForPredefinedMethod (Op, MethodInfo))
902ff4a156dSchristos         {
903ff4a156dSchristos             /* Special check for two names like _L01 and _E01 in same scope */
904ff4a156dSchristos 
905ff4a156dSchristos             ApCheckForGpeNameConflict (Op);
906ff4a156dSchristos 
907ff4a156dSchristos             /*
908ff4a156dSchristos              * Special check for _REG: Must have an operation region definition
909ff4a156dSchristos              * within the same scope!
910ff4a156dSchristos              */
911ff4a156dSchristos             ApCheckRegMethod (Op);
912ff4a156dSchristos         }
913ff4a156dSchristos 
914ff4a156dSchristos         ACPI_FREE (MethodInfo);
915ff4a156dSchristos         break;
916ff4a156dSchristos 
917ff4a156dSchristos     case PARSEOP_NAME:
918ff4a156dSchristos 
919ff4a156dSchristos          /* Special check for two names like _L01 and _E01 in same scope */
920ff4a156dSchristos 
921ff4a156dSchristos         ApCheckForGpeNameConflict (Op);
922ff4a156dSchristos         break;
923ff4a156dSchristos 
924ff4a156dSchristos     case PARSEOP_RETURN:
925ff4a156dSchristos 
926ff4a156dSchristos         /*
927ff4a156dSchristos          * If the parent is a predefined method name, attempt to typecheck
928ff4a156dSchristos          * the return value. Only static types can be validated.
929ff4a156dSchristos          */
930ff4a156dSchristos         ApCheckPredefinedReturnValue (Op, MethodInfo);
931ff4a156dSchristos 
932ff4a156dSchristos         /*
933ff4a156dSchristos          * The parent block does not "exit" and continue execution -- the
934ff4a156dSchristos          * method is terminated here with the Return() statement.
935ff4a156dSchristos          */
93689b8eb6cSchristos         Op->Asl.Parent->Asl.CompileFlags |= OP_HAS_NO_EXIT;
937ff4a156dSchristos 
938ff4a156dSchristos         /* Used in the "typing" pass later */
939ff4a156dSchristos 
940ff4a156dSchristos         Op->Asl.ParentMethod = MethodInfo->Op;
941ff4a156dSchristos 
942ff4a156dSchristos         /*
943ff4a156dSchristos          * If there is a peer node after the return statement, then this
944ff4a156dSchristos          * node is unreachable code -- i.e., it won't be executed because of
945ff4a156dSchristos          * the preceding Return() statement.
946ff4a156dSchristos          */
947ff4a156dSchristos         if (Op->Asl.Next)
948ff4a156dSchristos         {
94971e38f1dSchristos             AslError (ASL_WARNING, ASL_MSG_UNREACHABLE_CODE,
95071e38f1dSchristos                 Op->Asl.Next, NULL);
951ff4a156dSchristos         }
952ff4a156dSchristos         break;
953ff4a156dSchristos 
954ff4a156dSchristos     case PARSEOP_IF:
955ff4a156dSchristos 
95689b8eb6cSchristos         if ((Op->Asl.CompileFlags & OP_HAS_NO_EXIT) &&
957ff4a156dSchristos             (Op->Asl.Next) &&
958ff4a156dSchristos             (Op->Asl.Next->Asl.ParseOpcode == PARSEOP_ELSE))
959ff4a156dSchristos         {
960ff4a156dSchristos             /*
961ff4a156dSchristos              * This IF has a corresponding ELSE. The IF block has no exit,
962ff4a156dSchristos              * (it contains an unconditional Return)
963ff4a156dSchristos              * mark the ELSE block to remember this fact.
964ff4a156dSchristos              */
96589b8eb6cSchristos             Op->Asl.Next->Asl.CompileFlags |= OP_IF_HAS_NO_EXIT;
966ff4a156dSchristos         }
967ff4a156dSchristos         break;
968ff4a156dSchristos 
969ff4a156dSchristos     case PARSEOP_ELSE:
970ff4a156dSchristos 
97189b8eb6cSchristos         if ((Op->Asl.CompileFlags & OP_HAS_NO_EXIT) &&
97289b8eb6cSchristos             (Op->Asl.CompileFlags & OP_IF_HAS_NO_EXIT))
973ff4a156dSchristos         {
974ff4a156dSchristos             /*
975ff4a156dSchristos              * This ELSE block has no exit and the corresponding IF block
976ff4a156dSchristos              * has no exit either. Therefore, the parent node has no exit.
977ff4a156dSchristos              */
97889b8eb6cSchristos             Op->Asl.Parent->Asl.CompileFlags |= OP_HAS_NO_EXIT;
979ff4a156dSchristos         }
980ff4a156dSchristos         break;
981ff4a156dSchristos 
982ff4a156dSchristos 
983ff4a156dSchristos     default:
984ff4a156dSchristos 
98589b8eb6cSchristos         if ((Op->Asl.CompileFlags & OP_HAS_NO_EXIT) &&
986ff4a156dSchristos             (Op->Asl.Parent))
987ff4a156dSchristos         {
988ff4a156dSchristos             /* If this node has no exit, then the parent has no exit either */
989ff4a156dSchristos 
99089b8eb6cSchristos             Op->Asl.Parent->Asl.CompileFlags |= OP_HAS_NO_EXIT;
991ff4a156dSchristos         }
992ff4a156dSchristos         break;
993ff4a156dSchristos     }
994ff4a156dSchristos 
995ff4a156dSchristos     return (AE_OK);
996ff4a156dSchristos }
997