xref: /freebsd/sys/contrib/dev/acpica/compiler/aslmethod.c (revision efcc2a30547c400649a351e85e6cd97dab8f3817)
1*efcc2a30SJung-uk Kim /******************************************************************************
2*efcc2a30SJung-uk Kim  *
3*efcc2a30SJung-uk Kim  * Module Name: aslmethod.c - Control method analysis walk
4*efcc2a30SJung-uk Kim  *
5*efcc2a30SJung-uk Kim  *****************************************************************************/
6*efcc2a30SJung-uk Kim 
7*efcc2a30SJung-uk Kim /*
8*efcc2a30SJung-uk Kim  * Copyright (C) 2000 - 2013, Intel Corp.
9*efcc2a30SJung-uk Kim  * All rights reserved.
10*efcc2a30SJung-uk Kim  *
11*efcc2a30SJung-uk Kim  * Redistribution and use in source and binary forms, with or without
12*efcc2a30SJung-uk Kim  * modification, are permitted provided that the following conditions
13*efcc2a30SJung-uk Kim  * are met:
14*efcc2a30SJung-uk Kim  * 1. Redistributions of source code must retain the above copyright
15*efcc2a30SJung-uk Kim  *    notice, this list of conditions, and the following disclaimer,
16*efcc2a30SJung-uk Kim  *    without modification.
17*efcc2a30SJung-uk Kim  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18*efcc2a30SJung-uk Kim  *    substantially similar to the "NO WARRANTY" disclaimer below
19*efcc2a30SJung-uk Kim  *    ("Disclaimer") and any redistribution must be conditioned upon
20*efcc2a30SJung-uk Kim  *    including a substantially similar Disclaimer requirement for further
21*efcc2a30SJung-uk Kim  *    binary redistribution.
22*efcc2a30SJung-uk Kim  * 3. Neither the names of the above-listed copyright holders nor the names
23*efcc2a30SJung-uk Kim  *    of any contributors may be used to endorse or promote products derived
24*efcc2a30SJung-uk Kim  *    from this software without specific prior written permission.
25*efcc2a30SJung-uk Kim  *
26*efcc2a30SJung-uk Kim  * Alternatively, this software may be distributed under the terms of the
27*efcc2a30SJung-uk Kim  * GNU General Public License ("GPL") version 2 as published by the Free
28*efcc2a30SJung-uk Kim  * Software Foundation.
29*efcc2a30SJung-uk Kim  *
30*efcc2a30SJung-uk Kim  * NO WARRANTY
31*efcc2a30SJung-uk Kim  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32*efcc2a30SJung-uk Kim  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33*efcc2a30SJung-uk Kim  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34*efcc2a30SJung-uk Kim  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35*efcc2a30SJung-uk Kim  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36*efcc2a30SJung-uk Kim  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37*efcc2a30SJung-uk Kim  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38*efcc2a30SJung-uk Kim  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39*efcc2a30SJung-uk Kim  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40*efcc2a30SJung-uk Kim  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41*efcc2a30SJung-uk Kim  * POSSIBILITY OF SUCH DAMAGES.
42*efcc2a30SJung-uk Kim  */
43*efcc2a30SJung-uk Kim 
44*efcc2a30SJung-uk Kim 
45*efcc2a30SJung-uk Kim #include <contrib/dev/acpica/compiler/aslcompiler.h>
46*efcc2a30SJung-uk Kim #include "aslcompiler.y.h"
47*efcc2a30SJung-uk Kim 
48*efcc2a30SJung-uk Kim 
49*efcc2a30SJung-uk Kim #define _COMPONENT          ACPI_COMPILER
50*efcc2a30SJung-uk Kim         ACPI_MODULE_NAME    ("aslmethod")
51*efcc2a30SJung-uk Kim 
52*efcc2a30SJung-uk Kim 
53*efcc2a30SJung-uk Kim /*******************************************************************************
54*efcc2a30SJung-uk Kim  *
55*efcc2a30SJung-uk Kim  * FUNCTION:    MtMethodAnalysisWalkBegin
56*efcc2a30SJung-uk Kim  *
57*efcc2a30SJung-uk Kim  * PARAMETERS:  ASL_WALK_CALLBACK
58*efcc2a30SJung-uk Kim  *
59*efcc2a30SJung-uk Kim  * RETURN:      Status
60*efcc2a30SJung-uk Kim  *
61*efcc2a30SJung-uk Kim  * DESCRIPTION: Descending callback for the analysis walk. Check methods for:
62*efcc2a30SJung-uk Kim  *              1) Initialized local variables
63*efcc2a30SJung-uk Kim  *              2) Valid arguments
64*efcc2a30SJung-uk Kim  *              3) Return types
65*efcc2a30SJung-uk Kim  *
66*efcc2a30SJung-uk Kim  ******************************************************************************/
67*efcc2a30SJung-uk Kim 
68*efcc2a30SJung-uk Kim ACPI_STATUS
69*efcc2a30SJung-uk Kim MtMethodAnalysisWalkBegin (
70*efcc2a30SJung-uk Kim     ACPI_PARSE_OBJECT       *Op,
71*efcc2a30SJung-uk Kim     UINT32                  Level,
72*efcc2a30SJung-uk Kim     void                    *Context)
73*efcc2a30SJung-uk Kim {
74*efcc2a30SJung-uk Kim     ASL_ANALYSIS_WALK_INFO  *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
75*efcc2a30SJung-uk Kim     ASL_METHOD_INFO         *MethodInfo = WalkInfo->MethodStack;
76*efcc2a30SJung-uk Kim     ACPI_PARSE_OBJECT       *Next;
77*efcc2a30SJung-uk Kim     UINT32                  RegisterNumber;
78*efcc2a30SJung-uk Kim     UINT32                  i;
79*efcc2a30SJung-uk Kim     char                    LocalName[] = "Local0";
80*efcc2a30SJung-uk Kim     char                    ArgName[] = "Arg0";
81*efcc2a30SJung-uk Kim     ACPI_PARSE_OBJECT       *ArgNode;
82*efcc2a30SJung-uk Kim     ACPI_PARSE_OBJECT       *NextType;
83*efcc2a30SJung-uk Kim     ACPI_PARSE_OBJECT       *NextParamType;
84*efcc2a30SJung-uk Kim     UINT8                   ActualArgs = 0;
85*efcc2a30SJung-uk Kim 
86*efcc2a30SJung-uk Kim 
87*efcc2a30SJung-uk Kim     switch (Op->Asl.ParseOpcode)
88*efcc2a30SJung-uk Kim     {
89*efcc2a30SJung-uk Kim     case PARSEOP_METHOD:
90*efcc2a30SJung-uk Kim 
91*efcc2a30SJung-uk Kim         TotalMethods++;
92*efcc2a30SJung-uk Kim 
93*efcc2a30SJung-uk Kim         /* Create and init method info */
94*efcc2a30SJung-uk Kim 
95*efcc2a30SJung-uk Kim         MethodInfo       = UtLocalCalloc (sizeof (ASL_METHOD_INFO));
96*efcc2a30SJung-uk Kim         MethodInfo->Next = WalkInfo->MethodStack;
97*efcc2a30SJung-uk Kim         MethodInfo->Op = Op;
98*efcc2a30SJung-uk Kim 
99*efcc2a30SJung-uk Kim         WalkInfo->MethodStack = MethodInfo;
100*efcc2a30SJung-uk Kim 
101*efcc2a30SJung-uk Kim         /* Get the name node, ignored here */
102*efcc2a30SJung-uk Kim 
103*efcc2a30SJung-uk Kim         Next = Op->Asl.Child;
104*efcc2a30SJung-uk Kim 
105*efcc2a30SJung-uk Kim         /* Get the NumArguments node */
106*efcc2a30SJung-uk Kim 
107*efcc2a30SJung-uk Kim         Next = Next->Asl.Next;
108*efcc2a30SJung-uk Kim         MethodInfo->NumArguments = (UINT8)
109*efcc2a30SJung-uk Kim             (((UINT8) Next->Asl.Value.Integer) & 0x07);
110*efcc2a30SJung-uk Kim 
111*efcc2a30SJung-uk Kim         /* Get the SerializeRule and SyncLevel nodes, ignored here */
112*efcc2a30SJung-uk Kim 
113*efcc2a30SJung-uk Kim         Next = Next->Asl.Next;
114*efcc2a30SJung-uk Kim         Next = Next->Asl.Next;
115*efcc2a30SJung-uk Kim         ArgNode = Next;
116*efcc2a30SJung-uk Kim 
117*efcc2a30SJung-uk Kim         /* Get the ReturnType node */
118*efcc2a30SJung-uk Kim 
119*efcc2a30SJung-uk Kim         Next = Next->Asl.Next;
120*efcc2a30SJung-uk Kim 
121*efcc2a30SJung-uk Kim         NextType = Next->Asl.Child;
122*efcc2a30SJung-uk Kim         while (NextType)
123*efcc2a30SJung-uk Kim         {
124*efcc2a30SJung-uk Kim             /* Get and map each of the ReturnTypes */
125*efcc2a30SJung-uk Kim 
126*efcc2a30SJung-uk Kim             MethodInfo->ValidReturnTypes |= AnMapObjTypeToBtype (NextType);
127*efcc2a30SJung-uk Kim             NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
128*efcc2a30SJung-uk Kim             NextType = NextType->Asl.Next;
129*efcc2a30SJung-uk Kim         }
130*efcc2a30SJung-uk Kim 
131*efcc2a30SJung-uk Kim         /* Get the ParameterType node */
132*efcc2a30SJung-uk Kim 
133*efcc2a30SJung-uk Kim         Next = Next->Asl.Next;
134*efcc2a30SJung-uk Kim 
135*efcc2a30SJung-uk Kim         NextType = Next->Asl.Child;
136*efcc2a30SJung-uk Kim         while (NextType)
137*efcc2a30SJung-uk Kim         {
138*efcc2a30SJung-uk Kim             if (NextType->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
139*efcc2a30SJung-uk Kim             {
140*efcc2a30SJung-uk Kim                 NextParamType = NextType->Asl.Child;
141*efcc2a30SJung-uk Kim                 while (NextParamType)
142*efcc2a30SJung-uk Kim                 {
143*efcc2a30SJung-uk Kim                     MethodInfo->ValidArgTypes[ActualArgs] |= AnMapObjTypeToBtype (NextParamType);
144*efcc2a30SJung-uk Kim                     NextParamType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
145*efcc2a30SJung-uk Kim                     NextParamType = NextParamType->Asl.Next;
146*efcc2a30SJung-uk Kim                 }
147*efcc2a30SJung-uk Kim             }
148*efcc2a30SJung-uk Kim             else
149*efcc2a30SJung-uk Kim             {
150*efcc2a30SJung-uk Kim                 MethodInfo->ValidArgTypes[ActualArgs] =
151*efcc2a30SJung-uk Kim                     AnMapObjTypeToBtype (NextType);
152*efcc2a30SJung-uk Kim                 NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
153*efcc2a30SJung-uk Kim                 ActualArgs++;
154*efcc2a30SJung-uk Kim             }
155*efcc2a30SJung-uk Kim 
156*efcc2a30SJung-uk Kim             NextType = NextType->Asl.Next;
157*efcc2a30SJung-uk Kim         }
158*efcc2a30SJung-uk Kim 
159*efcc2a30SJung-uk Kim         if ((MethodInfo->NumArguments) &&
160*efcc2a30SJung-uk Kim             (MethodInfo->NumArguments != ActualArgs))
161*efcc2a30SJung-uk Kim         {
162*efcc2a30SJung-uk Kim             /* error: Param list did not match number of args */
163*efcc2a30SJung-uk Kim         }
164*efcc2a30SJung-uk Kim 
165*efcc2a30SJung-uk Kim         /* Allow numarguments == 0 for Function() */
166*efcc2a30SJung-uk Kim 
167*efcc2a30SJung-uk Kim         if ((!MethodInfo->NumArguments) && (ActualArgs))
168*efcc2a30SJung-uk Kim         {
169*efcc2a30SJung-uk Kim             MethodInfo->NumArguments = ActualArgs;
170*efcc2a30SJung-uk Kim             ArgNode->Asl.Value.Integer |= ActualArgs;
171*efcc2a30SJung-uk Kim         }
172*efcc2a30SJung-uk Kim 
173*efcc2a30SJung-uk Kim         /*
174*efcc2a30SJung-uk Kim          * Actual arguments are initialized at method entry.
175*efcc2a30SJung-uk Kim          * All other ArgX "registers" can be used as locals, so we
176*efcc2a30SJung-uk Kim          * track their initialization.
177*efcc2a30SJung-uk Kim          */
178*efcc2a30SJung-uk Kim         for (i = 0; i < MethodInfo->NumArguments; i++)
179*efcc2a30SJung-uk Kim         {
180*efcc2a30SJung-uk Kim             MethodInfo->ArgInitialized[i] = TRUE;
181*efcc2a30SJung-uk Kim         }
182*efcc2a30SJung-uk Kim         break;
183*efcc2a30SJung-uk Kim 
184*efcc2a30SJung-uk Kim 
185*efcc2a30SJung-uk Kim     case PARSEOP_METHODCALL:
186*efcc2a30SJung-uk Kim 
187*efcc2a30SJung-uk Kim         if (MethodInfo &&
188*efcc2a30SJung-uk Kim            (Op->Asl.Node == MethodInfo->Op->Asl.Node))
189*efcc2a30SJung-uk Kim         {
190*efcc2a30SJung-uk Kim             AslError (ASL_REMARK, ASL_MSG_RECURSION, Op, Op->Asl.ExternalName);
191*efcc2a30SJung-uk Kim         }
192*efcc2a30SJung-uk Kim         break;
193*efcc2a30SJung-uk Kim 
194*efcc2a30SJung-uk Kim 
195*efcc2a30SJung-uk Kim     case PARSEOP_LOCAL0:
196*efcc2a30SJung-uk Kim     case PARSEOP_LOCAL1:
197*efcc2a30SJung-uk Kim     case PARSEOP_LOCAL2:
198*efcc2a30SJung-uk Kim     case PARSEOP_LOCAL3:
199*efcc2a30SJung-uk Kim     case PARSEOP_LOCAL4:
200*efcc2a30SJung-uk Kim     case PARSEOP_LOCAL5:
201*efcc2a30SJung-uk Kim     case PARSEOP_LOCAL6:
202*efcc2a30SJung-uk Kim     case PARSEOP_LOCAL7:
203*efcc2a30SJung-uk Kim 
204*efcc2a30SJung-uk Kim         if (!MethodInfo)
205*efcc2a30SJung-uk Kim         {
206*efcc2a30SJung-uk Kim             /*
207*efcc2a30SJung-uk Kim              * Local was used outside a control method, or there was an error
208*efcc2a30SJung-uk Kim              * in the method declaration.
209*efcc2a30SJung-uk Kim              */
210*efcc2a30SJung-uk Kim             AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName);
211*efcc2a30SJung-uk Kim             return (AE_ERROR);
212*efcc2a30SJung-uk Kim         }
213*efcc2a30SJung-uk Kim 
214*efcc2a30SJung-uk Kim         RegisterNumber = (Op->Asl.AmlOpcode & 0x000F);
215*efcc2a30SJung-uk Kim 
216*efcc2a30SJung-uk Kim         /*
217*efcc2a30SJung-uk Kim          * If the local is being used as a target, mark the local
218*efcc2a30SJung-uk Kim          * initialized
219*efcc2a30SJung-uk Kim          */
220*efcc2a30SJung-uk Kim         if (Op->Asl.CompileFlags & NODE_IS_TARGET)
221*efcc2a30SJung-uk Kim         {
222*efcc2a30SJung-uk Kim             MethodInfo->LocalInitialized[RegisterNumber] = TRUE;
223*efcc2a30SJung-uk Kim         }
224*efcc2a30SJung-uk Kim 
225*efcc2a30SJung-uk Kim         /*
226*efcc2a30SJung-uk Kim          * Otherwise, this is a reference, check if the local
227*efcc2a30SJung-uk Kim          * has been previously initialized.
228*efcc2a30SJung-uk Kim          *
229*efcc2a30SJung-uk Kim          * The only operator that accepts an uninitialized value is ObjectType()
230*efcc2a30SJung-uk Kim          */
231*efcc2a30SJung-uk Kim         else if ((!MethodInfo->LocalInitialized[RegisterNumber]) &&
232*efcc2a30SJung-uk Kim                  (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
233*efcc2a30SJung-uk Kim         {
234*efcc2a30SJung-uk Kim             LocalName[strlen (LocalName) -1] = (char) (RegisterNumber + 0x30);
235*efcc2a30SJung-uk Kim             AslError (ASL_ERROR, ASL_MSG_LOCAL_INIT, Op, LocalName);
236*efcc2a30SJung-uk Kim         }
237*efcc2a30SJung-uk Kim         break;
238*efcc2a30SJung-uk Kim 
239*efcc2a30SJung-uk Kim 
240*efcc2a30SJung-uk Kim     case PARSEOP_ARG0:
241*efcc2a30SJung-uk Kim     case PARSEOP_ARG1:
242*efcc2a30SJung-uk Kim     case PARSEOP_ARG2:
243*efcc2a30SJung-uk Kim     case PARSEOP_ARG3:
244*efcc2a30SJung-uk Kim     case PARSEOP_ARG4:
245*efcc2a30SJung-uk Kim     case PARSEOP_ARG5:
246*efcc2a30SJung-uk Kim     case PARSEOP_ARG6:
247*efcc2a30SJung-uk Kim 
248*efcc2a30SJung-uk Kim         if (!MethodInfo)
249*efcc2a30SJung-uk Kim         {
250*efcc2a30SJung-uk Kim             /*
251*efcc2a30SJung-uk Kim              * Arg was used outside a control method, or there was an error
252*efcc2a30SJung-uk Kim              * in the method declaration.
253*efcc2a30SJung-uk Kim              */
254*efcc2a30SJung-uk Kim             AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName);
255*efcc2a30SJung-uk Kim             return (AE_ERROR);
256*efcc2a30SJung-uk Kim         }
257*efcc2a30SJung-uk Kim 
258*efcc2a30SJung-uk Kim         RegisterNumber = (Op->Asl.AmlOpcode & 0x000F) - 8;
259*efcc2a30SJung-uk Kim         ArgName[strlen (ArgName) -1] = (char) (RegisterNumber + 0x30);
260*efcc2a30SJung-uk Kim 
261*efcc2a30SJung-uk Kim         /*
262*efcc2a30SJung-uk Kim          * If the Arg is being used as a target, mark the local
263*efcc2a30SJung-uk Kim          * initialized
264*efcc2a30SJung-uk Kim          */
265*efcc2a30SJung-uk Kim         if (Op->Asl.CompileFlags & NODE_IS_TARGET)
266*efcc2a30SJung-uk Kim         {
267*efcc2a30SJung-uk Kim             MethodInfo->ArgInitialized[RegisterNumber] = TRUE;
268*efcc2a30SJung-uk Kim         }
269*efcc2a30SJung-uk Kim 
270*efcc2a30SJung-uk Kim         /*
271*efcc2a30SJung-uk Kim          * Otherwise, this is a reference, check if the Arg
272*efcc2a30SJung-uk Kim          * has been previously initialized.
273*efcc2a30SJung-uk Kim          *
274*efcc2a30SJung-uk Kim          * The only operator that accepts an uninitialized value is ObjectType()
275*efcc2a30SJung-uk Kim          */
276*efcc2a30SJung-uk Kim         else if ((!MethodInfo->ArgInitialized[RegisterNumber]) &&
277*efcc2a30SJung-uk Kim                  (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
278*efcc2a30SJung-uk Kim         {
279*efcc2a30SJung-uk Kim             AslError (ASL_ERROR, ASL_MSG_ARG_INIT, Op, ArgName);
280*efcc2a30SJung-uk Kim         }
281*efcc2a30SJung-uk Kim 
282*efcc2a30SJung-uk Kim         /* Flag this arg if it is not a "real" argument to the method */
283*efcc2a30SJung-uk Kim 
284*efcc2a30SJung-uk Kim         if (RegisterNumber >= MethodInfo->NumArguments)
285*efcc2a30SJung-uk Kim         {
286*efcc2a30SJung-uk Kim             AslError (ASL_REMARK, ASL_MSG_NOT_PARAMETER, Op, ArgName);
287*efcc2a30SJung-uk Kim         }
288*efcc2a30SJung-uk Kim         break;
289*efcc2a30SJung-uk Kim 
290*efcc2a30SJung-uk Kim 
291*efcc2a30SJung-uk Kim     case PARSEOP_RETURN:
292*efcc2a30SJung-uk Kim 
293*efcc2a30SJung-uk Kim         if (!MethodInfo)
294*efcc2a30SJung-uk Kim         {
295*efcc2a30SJung-uk Kim             /*
296*efcc2a30SJung-uk Kim              * Probably was an error in the method declaration,
297*efcc2a30SJung-uk Kim              * no additional error here
298*efcc2a30SJung-uk Kim              */
299*efcc2a30SJung-uk Kim             ACPI_WARNING ((AE_INFO, "%p, No parent method", Op));
300*efcc2a30SJung-uk Kim             return (AE_ERROR);
301*efcc2a30SJung-uk Kim         }
302*efcc2a30SJung-uk Kim 
303*efcc2a30SJung-uk Kim         /*
304*efcc2a30SJung-uk Kim          * A child indicates a possible return value. A simple Return or
305*efcc2a30SJung-uk Kim          * Return() is marked with NODE_IS_NULL_RETURN by the parser so
306*efcc2a30SJung-uk Kim          * that it is not counted as a "real" return-with-value, although
307*efcc2a30SJung-uk Kim          * the AML code that is actually emitted is Return(0). The AML
308*efcc2a30SJung-uk Kim          * definition of Return has a required parameter, so we are
309*efcc2a30SJung-uk Kim          * forced to convert a null return to Return(0).
310*efcc2a30SJung-uk Kim          */
311*efcc2a30SJung-uk Kim         if ((Op->Asl.Child) &&
312*efcc2a30SJung-uk Kim             (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
313*efcc2a30SJung-uk Kim             (!(Op->Asl.Child->Asl.CompileFlags & NODE_IS_NULL_RETURN)))
314*efcc2a30SJung-uk Kim         {
315*efcc2a30SJung-uk Kim             MethodInfo->NumReturnWithValue++;
316*efcc2a30SJung-uk Kim         }
317*efcc2a30SJung-uk Kim         else
318*efcc2a30SJung-uk Kim         {
319*efcc2a30SJung-uk Kim             MethodInfo->NumReturnNoValue++;
320*efcc2a30SJung-uk Kim         }
321*efcc2a30SJung-uk Kim         break;
322*efcc2a30SJung-uk Kim 
323*efcc2a30SJung-uk Kim 
324*efcc2a30SJung-uk Kim     case PARSEOP_BREAK:
325*efcc2a30SJung-uk Kim     case PARSEOP_CONTINUE:
326*efcc2a30SJung-uk Kim 
327*efcc2a30SJung-uk Kim         Next = Op->Asl.Parent;
328*efcc2a30SJung-uk Kim         while (Next)
329*efcc2a30SJung-uk Kim         {
330*efcc2a30SJung-uk Kim             if (Next->Asl.ParseOpcode == PARSEOP_WHILE)
331*efcc2a30SJung-uk Kim             {
332*efcc2a30SJung-uk Kim                 break;
333*efcc2a30SJung-uk Kim             }
334*efcc2a30SJung-uk Kim             Next = Next->Asl.Parent;
335*efcc2a30SJung-uk Kim         }
336*efcc2a30SJung-uk Kim 
337*efcc2a30SJung-uk Kim         if (!Next)
338*efcc2a30SJung-uk Kim         {
339*efcc2a30SJung-uk Kim             AslError (ASL_ERROR, ASL_MSG_NO_WHILE, Op, NULL);
340*efcc2a30SJung-uk Kim         }
341*efcc2a30SJung-uk Kim         break;
342*efcc2a30SJung-uk Kim 
343*efcc2a30SJung-uk Kim 
344*efcc2a30SJung-uk Kim     case PARSEOP_STALL:
345*efcc2a30SJung-uk Kim 
346*efcc2a30SJung-uk Kim         /* We can range check if the argument is an integer */
347*efcc2a30SJung-uk Kim 
348*efcc2a30SJung-uk Kim         if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
349*efcc2a30SJung-uk Kim             (Op->Asl.Child->Asl.Value.Integer > ACPI_UINT8_MAX))
350*efcc2a30SJung-uk Kim         {
351*efcc2a30SJung-uk Kim             AslError (ASL_ERROR, ASL_MSG_INVALID_TIME, Op, NULL);
352*efcc2a30SJung-uk Kim         }
353*efcc2a30SJung-uk Kim         break;
354*efcc2a30SJung-uk Kim 
355*efcc2a30SJung-uk Kim 
356*efcc2a30SJung-uk Kim     case PARSEOP_DEVICE:
357*efcc2a30SJung-uk Kim     case PARSEOP_EVENT:
358*efcc2a30SJung-uk Kim     case PARSEOP_MUTEX:
359*efcc2a30SJung-uk Kim     case PARSEOP_OPERATIONREGION:
360*efcc2a30SJung-uk Kim     case PARSEOP_POWERRESOURCE:
361*efcc2a30SJung-uk Kim     case PARSEOP_PROCESSOR:
362*efcc2a30SJung-uk Kim     case PARSEOP_THERMALZONE:
363*efcc2a30SJung-uk Kim 
364*efcc2a30SJung-uk Kim         /*
365*efcc2a30SJung-uk Kim          * The first operand is a name to be created in the namespace.
366*efcc2a30SJung-uk Kim          * Check against the reserved list.
367*efcc2a30SJung-uk Kim          */
368*efcc2a30SJung-uk Kim         i = ApCheckForPredefinedName (Op, Op->Asl.NameSeg);
369*efcc2a30SJung-uk Kim         if (i < ACPI_VALID_RESERVED_NAME_MAX)
370*efcc2a30SJung-uk Kim         {
371*efcc2a30SJung-uk Kim             AslError (ASL_ERROR, ASL_MSG_RESERVED_USE, Op, Op->Asl.ExternalName);
372*efcc2a30SJung-uk Kim         }
373*efcc2a30SJung-uk Kim         break;
374*efcc2a30SJung-uk Kim 
375*efcc2a30SJung-uk Kim 
376*efcc2a30SJung-uk Kim     case PARSEOP_NAME:
377*efcc2a30SJung-uk Kim 
378*efcc2a30SJung-uk Kim         /* Typecheck any predefined names statically defined with Name() */
379*efcc2a30SJung-uk Kim 
380*efcc2a30SJung-uk Kim         ApCheckForPredefinedObject (Op, Op->Asl.NameSeg);
381*efcc2a30SJung-uk Kim 
382*efcc2a30SJung-uk Kim         /* Special typechecking for _HID */
383*efcc2a30SJung-uk Kim 
384*efcc2a30SJung-uk Kim         if (!ACPI_STRCMP (METHOD_NAME__HID, Op->Asl.NameSeg))
385*efcc2a30SJung-uk Kim         {
386*efcc2a30SJung-uk Kim             Next = Op->Asl.Child->Asl.Next;
387*efcc2a30SJung-uk Kim             AnCheckId (Next, ASL_TYPE_HID);
388*efcc2a30SJung-uk Kim         }
389*efcc2a30SJung-uk Kim 
390*efcc2a30SJung-uk Kim         /* Special typechecking for _CID */
391*efcc2a30SJung-uk Kim 
392*efcc2a30SJung-uk Kim         else if (!ACPI_STRCMP (METHOD_NAME__CID, Op->Asl.NameSeg))
393*efcc2a30SJung-uk Kim         {
394*efcc2a30SJung-uk Kim             Next = Op->Asl.Child->Asl.Next;
395*efcc2a30SJung-uk Kim 
396*efcc2a30SJung-uk Kim             if ((Next->Asl.ParseOpcode == PARSEOP_PACKAGE) ||
397*efcc2a30SJung-uk Kim                 (Next->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE))
398*efcc2a30SJung-uk Kim             {
399*efcc2a30SJung-uk Kim                 Next = Next->Asl.Child;
400*efcc2a30SJung-uk Kim                 while (Next)
401*efcc2a30SJung-uk Kim                 {
402*efcc2a30SJung-uk Kim                     AnCheckId (Next, ASL_TYPE_CID);
403*efcc2a30SJung-uk Kim                     Next = Next->Asl.Next;
404*efcc2a30SJung-uk Kim                 }
405*efcc2a30SJung-uk Kim             }
406*efcc2a30SJung-uk Kim             else
407*efcc2a30SJung-uk Kim             {
408*efcc2a30SJung-uk Kim                 AnCheckId (Next, ASL_TYPE_CID);
409*efcc2a30SJung-uk Kim             }
410*efcc2a30SJung-uk Kim         }
411*efcc2a30SJung-uk Kim         break;
412*efcc2a30SJung-uk Kim 
413*efcc2a30SJung-uk Kim 
414*efcc2a30SJung-uk Kim     default:
415*efcc2a30SJung-uk Kim         break;
416*efcc2a30SJung-uk Kim     }
417*efcc2a30SJung-uk Kim 
418*efcc2a30SJung-uk Kim     return (AE_OK);
419*efcc2a30SJung-uk Kim }
420*efcc2a30SJung-uk Kim 
421*efcc2a30SJung-uk Kim 
422*efcc2a30SJung-uk Kim /*******************************************************************************
423*efcc2a30SJung-uk Kim  *
424*efcc2a30SJung-uk Kim  * FUNCTION:    MtMethodAnalysisWalkEnd
425*efcc2a30SJung-uk Kim  *
426*efcc2a30SJung-uk Kim  * PARAMETERS:  ASL_WALK_CALLBACK
427*efcc2a30SJung-uk Kim  *
428*efcc2a30SJung-uk Kim  * RETURN:      Status
429*efcc2a30SJung-uk Kim  *
430*efcc2a30SJung-uk Kim  * DESCRIPTION: Ascending callback for analysis walk. Complete method
431*efcc2a30SJung-uk Kim  *              return analysis.
432*efcc2a30SJung-uk Kim  *
433*efcc2a30SJung-uk Kim  ******************************************************************************/
434*efcc2a30SJung-uk Kim 
435*efcc2a30SJung-uk Kim ACPI_STATUS
436*efcc2a30SJung-uk Kim MtMethodAnalysisWalkEnd (
437*efcc2a30SJung-uk Kim     ACPI_PARSE_OBJECT       *Op,
438*efcc2a30SJung-uk Kim     UINT32                  Level,
439*efcc2a30SJung-uk Kim     void                    *Context)
440*efcc2a30SJung-uk Kim {
441*efcc2a30SJung-uk Kim     ASL_ANALYSIS_WALK_INFO  *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
442*efcc2a30SJung-uk Kim     ASL_METHOD_INFO         *MethodInfo = WalkInfo->MethodStack;
443*efcc2a30SJung-uk Kim 
444*efcc2a30SJung-uk Kim 
445*efcc2a30SJung-uk Kim     switch (Op->Asl.ParseOpcode)
446*efcc2a30SJung-uk Kim     {
447*efcc2a30SJung-uk Kim     case PARSEOP_METHOD:
448*efcc2a30SJung-uk Kim     case PARSEOP_RETURN:
449*efcc2a30SJung-uk Kim         if (!MethodInfo)
450*efcc2a30SJung-uk Kim         {
451*efcc2a30SJung-uk Kim             printf ("No method info for method! [%s]\n", Op->Asl.Namepath);
452*efcc2a30SJung-uk Kim             AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
453*efcc2a30SJung-uk Kim                 "No method info for this method");
454*efcc2a30SJung-uk Kim 
455*efcc2a30SJung-uk Kim             CmCleanupAndExit ();
456*efcc2a30SJung-uk Kim             return (AE_AML_INTERNAL);
457*efcc2a30SJung-uk Kim         }
458*efcc2a30SJung-uk Kim         break;
459*efcc2a30SJung-uk Kim 
460*efcc2a30SJung-uk Kim     default:
461*efcc2a30SJung-uk Kim         break;
462*efcc2a30SJung-uk Kim     }
463*efcc2a30SJung-uk Kim 
464*efcc2a30SJung-uk Kim     switch (Op->Asl.ParseOpcode)
465*efcc2a30SJung-uk Kim     {
466*efcc2a30SJung-uk Kim     case PARSEOP_METHOD:
467*efcc2a30SJung-uk Kim 
468*efcc2a30SJung-uk Kim         WalkInfo->MethodStack = MethodInfo->Next;
469*efcc2a30SJung-uk Kim 
470*efcc2a30SJung-uk Kim         /*
471*efcc2a30SJung-uk Kim          * Check if there is no return statement at the end of the
472*efcc2a30SJung-uk Kim          * method AND we can actually get there -- i.e., the execution
473*efcc2a30SJung-uk Kim          * of the method can possibly terminate without a return statement.
474*efcc2a30SJung-uk Kim          */
475*efcc2a30SJung-uk Kim         if ((!AnLastStatementIsReturn (Op)) &&
476*efcc2a30SJung-uk Kim             (!(Op->Asl.CompileFlags & NODE_HAS_NO_EXIT)))
477*efcc2a30SJung-uk Kim         {
478*efcc2a30SJung-uk Kim             /*
479*efcc2a30SJung-uk Kim              * No return statement, and execution can possibly exit
480*efcc2a30SJung-uk Kim              * via this path. This is equivalent to Return ()
481*efcc2a30SJung-uk Kim              */
482*efcc2a30SJung-uk Kim             MethodInfo->NumReturnNoValue++;
483*efcc2a30SJung-uk Kim         }
484*efcc2a30SJung-uk Kim 
485*efcc2a30SJung-uk Kim         /*
486*efcc2a30SJung-uk Kim          * Check for case where some return statements have a return value
487*efcc2a30SJung-uk Kim          * and some do not. Exit without a return statement is a return with
488*efcc2a30SJung-uk Kim          * no value
489*efcc2a30SJung-uk Kim          */
490*efcc2a30SJung-uk Kim         if (MethodInfo->NumReturnNoValue &&
491*efcc2a30SJung-uk Kim             MethodInfo->NumReturnWithValue)
492*efcc2a30SJung-uk Kim         {
493*efcc2a30SJung-uk Kim             AslError (ASL_WARNING, ASL_MSG_RETURN_TYPES, Op,
494*efcc2a30SJung-uk Kim                 Op->Asl.ExternalName);
495*efcc2a30SJung-uk Kim         }
496*efcc2a30SJung-uk Kim 
497*efcc2a30SJung-uk Kim         /*
498*efcc2a30SJung-uk Kim          * If there are any RETURN() statements with no value, or there is a
499*efcc2a30SJung-uk Kim          * control path that allows the method to exit without a return value,
500*efcc2a30SJung-uk Kim          * we mark the method as a method that does not return a value. This
501*efcc2a30SJung-uk Kim          * knowledge can be used to check method invocations that expect a
502*efcc2a30SJung-uk Kim          * returned value.
503*efcc2a30SJung-uk Kim          */
504*efcc2a30SJung-uk Kim         if (MethodInfo->NumReturnNoValue)
505*efcc2a30SJung-uk Kim         {
506*efcc2a30SJung-uk Kim             if (MethodInfo->NumReturnWithValue)
507*efcc2a30SJung-uk Kim             {
508*efcc2a30SJung-uk Kim                 Op->Asl.CompileFlags |= NODE_METHOD_SOME_NO_RETVAL;
509*efcc2a30SJung-uk Kim             }
510*efcc2a30SJung-uk Kim             else
511*efcc2a30SJung-uk Kim             {
512*efcc2a30SJung-uk Kim                 Op->Asl.CompileFlags |= NODE_METHOD_NO_RETVAL;
513*efcc2a30SJung-uk Kim             }
514*efcc2a30SJung-uk Kim         }
515*efcc2a30SJung-uk Kim 
516*efcc2a30SJung-uk Kim         /*
517*efcc2a30SJung-uk Kim          * Check predefined method names for correct return behavior
518*efcc2a30SJung-uk Kim          * and correct number of arguments. Also, some special checks
519*efcc2a30SJung-uk Kim          * For GPE and _REG methods.
520*efcc2a30SJung-uk Kim          */
521*efcc2a30SJung-uk Kim         if (ApCheckForPredefinedMethod (Op, MethodInfo))
522*efcc2a30SJung-uk Kim         {
523*efcc2a30SJung-uk Kim             /* Special check for two names like _L01 and _E01 in same scope */
524*efcc2a30SJung-uk Kim 
525*efcc2a30SJung-uk Kim             ApCheckForGpeNameConflict (Op);
526*efcc2a30SJung-uk Kim 
527*efcc2a30SJung-uk Kim             /*
528*efcc2a30SJung-uk Kim              * Special check for _REG: Must have an operation region definition
529*efcc2a30SJung-uk Kim              * within the same scope!
530*efcc2a30SJung-uk Kim              */
531*efcc2a30SJung-uk Kim             ApCheckRegMethod (Op);
532*efcc2a30SJung-uk Kim         }
533*efcc2a30SJung-uk Kim 
534*efcc2a30SJung-uk Kim         ACPI_FREE (MethodInfo);
535*efcc2a30SJung-uk Kim         break;
536*efcc2a30SJung-uk Kim 
537*efcc2a30SJung-uk Kim 
538*efcc2a30SJung-uk Kim     case PARSEOP_NAME:
539*efcc2a30SJung-uk Kim 
540*efcc2a30SJung-uk Kim          /* Special check for two names like _L01 and _E01 in same scope */
541*efcc2a30SJung-uk Kim 
542*efcc2a30SJung-uk Kim         ApCheckForGpeNameConflict (Op);
543*efcc2a30SJung-uk Kim         break;
544*efcc2a30SJung-uk Kim 
545*efcc2a30SJung-uk Kim 
546*efcc2a30SJung-uk Kim     case PARSEOP_RETURN:
547*efcc2a30SJung-uk Kim 
548*efcc2a30SJung-uk Kim         /*
549*efcc2a30SJung-uk Kim          * If the parent is a predefined method name, attempt to typecheck
550*efcc2a30SJung-uk Kim          * the return value. Only static types can be validated.
551*efcc2a30SJung-uk Kim          */
552*efcc2a30SJung-uk Kim         ApCheckPredefinedReturnValue (Op, MethodInfo);
553*efcc2a30SJung-uk Kim 
554*efcc2a30SJung-uk Kim         /*
555*efcc2a30SJung-uk Kim          * The parent block does not "exit" and continue execution -- the
556*efcc2a30SJung-uk Kim          * method is terminated here with the Return() statement.
557*efcc2a30SJung-uk Kim          */
558*efcc2a30SJung-uk Kim         Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
559*efcc2a30SJung-uk Kim 
560*efcc2a30SJung-uk Kim         /* Used in the "typing" pass later */
561*efcc2a30SJung-uk Kim 
562*efcc2a30SJung-uk Kim         Op->Asl.ParentMethod = MethodInfo->Op;
563*efcc2a30SJung-uk Kim 
564*efcc2a30SJung-uk Kim         /*
565*efcc2a30SJung-uk Kim          * If there is a peer node after the return statement, then this
566*efcc2a30SJung-uk Kim          * node is unreachable code -- i.e., it won't be executed because of
567*efcc2a30SJung-uk Kim          * the preceding Return() statement.
568*efcc2a30SJung-uk Kim          */
569*efcc2a30SJung-uk Kim         if (Op->Asl.Next)
570*efcc2a30SJung-uk Kim         {
571*efcc2a30SJung-uk Kim             AslError (ASL_WARNING, ASL_MSG_UNREACHABLE_CODE, Op->Asl.Next, NULL);
572*efcc2a30SJung-uk Kim         }
573*efcc2a30SJung-uk Kim         break;
574*efcc2a30SJung-uk Kim 
575*efcc2a30SJung-uk Kim 
576*efcc2a30SJung-uk Kim     case PARSEOP_IF:
577*efcc2a30SJung-uk Kim 
578*efcc2a30SJung-uk Kim         if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
579*efcc2a30SJung-uk Kim             (Op->Asl.Next) &&
580*efcc2a30SJung-uk Kim             (Op->Asl.Next->Asl.ParseOpcode == PARSEOP_ELSE))
581*efcc2a30SJung-uk Kim         {
582*efcc2a30SJung-uk Kim             /*
583*efcc2a30SJung-uk Kim              * This IF has a corresponding ELSE. The IF block has no exit,
584*efcc2a30SJung-uk Kim              * (it contains an unconditional Return)
585*efcc2a30SJung-uk Kim              * mark the ELSE block to remember this fact.
586*efcc2a30SJung-uk Kim              */
587*efcc2a30SJung-uk Kim             Op->Asl.Next->Asl.CompileFlags |= NODE_IF_HAS_NO_EXIT;
588*efcc2a30SJung-uk Kim         }
589*efcc2a30SJung-uk Kim         break;
590*efcc2a30SJung-uk Kim 
591*efcc2a30SJung-uk Kim 
592*efcc2a30SJung-uk Kim     case PARSEOP_ELSE:
593*efcc2a30SJung-uk Kim 
594*efcc2a30SJung-uk Kim         if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
595*efcc2a30SJung-uk Kim             (Op->Asl.CompileFlags & NODE_IF_HAS_NO_EXIT))
596*efcc2a30SJung-uk Kim         {
597*efcc2a30SJung-uk Kim             /*
598*efcc2a30SJung-uk Kim              * This ELSE block has no exit and the corresponding IF block
599*efcc2a30SJung-uk Kim              * has no exit either. Therefore, the parent node has no exit.
600*efcc2a30SJung-uk Kim              */
601*efcc2a30SJung-uk Kim             Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
602*efcc2a30SJung-uk Kim         }
603*efcc2a30SJung-uk Kim         break;
604*efcc2a30SJung-uk Kim 
605*efcc2a30SJung-uk Kim 
606*efcc2a30SJung-uk Kim     default:
607*efcc2a30SJung-uk Kim 
608*efcc2a30SJung-uk Kim         if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
609*efcc2a30SJung-uk Kim             (Op->Asl.Parent))
610*efcc2a30SJung-uk Kim         {
611*efcc2a30SJung-uk Kim             /* If this node has no exit, then the parent has no exit either */
612*efcc2a30SJung-uk Kim 
613*efcc2a30SJung-uk Kim             Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
614*efcc2a30SJung-uk Kim         }
615*efcc2a30SJung-uk Kim         break;
616*efcc2a30SJung-uk Kim     }
617*efcc2a30SJung-uk Kim 
618*efcc2a30SJung-uk Kim     return (AE_OK);
619*efcc2a30SJung-uk Kim }
620