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