aslwalks.c revision 249112
1218585Sjkim/******************************************************************************
2218585Sjkim *
3245582Sjkim * Module Name: aslwalks.c - Miscellaneous analytical parse tree walks
4218585Sjkim *
5218585Sjkim *****************************************************************************/
6218585Sjkim
7218585Sjkim/*
8245582Sjkim * Copyright (C) 2000 - 2013, Intel Corp.
9218585Sjkim * All rights reserved.
10218585Sjkim *
11218585Sjkim * Redistribution and use in source and binary forms, with or without
12218585Sjkim * modification, are permitted provided that the following conditions
13218585Sjkim * are met:
14218585Sjkim * 1. Redistributions of source code must retain the above copyright
15218585Sjkim *    notice, this list of conditions, and the following disclaimer,
16218585Sjkim *    without modification.
17218585Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18218585Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19218585Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20218585Sjkim *    including a substantially similar Disclaimer requirement for further
21218585Sjkim *    binary redistribution.
22218585Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23218585Sjkim *    of any contributors may be used to endorse or promote products derived
24218585Sjkim *    from this software without specific prior written permission.
25218585Sjkim *
26218585Sjkim * Alternatively, this software may be distributed under the terms of the
27218585Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28218585Sjkim * Software Foundation.
29218585Sjkim *
30218585Sjkim * NO WARRANTY
31218585Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32218585Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33218585Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34218585Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35218585Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36218585Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37218585Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38218585Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39218585Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40218585Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41218585Sjkim * POSSIBILITY OF SUCH DAMAGES.
42218585Sjkim */
43218585Sjkim
44218585Sjkim
45218590Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h>
46218585Sjkim#include "aslcompiler.y.h"
47218590Sjkim#include <contrib/dev/acpica/include/acparser.h>
48218590Sjkim#include <contrib/dev/acpica/include/amlcode.h>
49218585Sjkim
50218585Sjkim
51218585Sjkim#define _COMPONENT          ACPI_COMPILER
52218585Sjkim        ACPI_MODULE_NAME    ("aslwalks")
53218585Sjkim
54218585Sjkim
55218585Sjkim/*******************************************************************************
56218585Sjkim *
57218585Sjkim * FUNCTION:    AnMethodTypingWalkEnd
58218585Sjkim *
59218585Sjkim * PARAMETERS:  ASL_WALK_CALLBACK
60218585Sjkim *
61218585Sjkim * RETURN:      Status
62218585Sjkim *
63218585Sjkim * DESCRIPTION: Ascending callback for typing walk. Complete the method
64218585Sjkim *              return analysis. Check methods for:
65218585Sjkim *              1) Initialized local variables
66218585Sjkim *              2) Valid arguments
67218585Sjkim *              3) Return types
68218585Sjkim *
69218585Sjkim ******************************************************************************/
70218585Sjkim
71218585SjkimACPI_STATUS
72218585SjkimAnMethodTypingWalkEnd (
73218585Sjkim    ACPI_PARSE_OBJECT       *Op,
74218585Sjkim    UINT32                  Level,
75218585Sjkim    void                    *Context)
76218585Sjkim{
77218585Sjkim    UINT32                  ThisNodeBtype;
78218585Sjkim
79218585Sjkim
80218585Sjkim    switch (Op->Asl.ParseOpcode)
81218585Sjkim    {
82218585Sjkim    case PARSEOP_METHOD:
83218585Sjkim
84218585Sjkim        Op->Asl.CompileFlags |= NODE_METHOD_TYPED;
85218585Sjkim        break;
86218585Sjkim
87218585Sjkim    case PARSEOP_RETURN:
88218585Sjkim
89218585Sjkim        if ((Op->Asl.Child) &&
90218585Sjkim            (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
91218585Sjkim        {
92218585Sjkim            ThisNodeBtype = AnGetBtype (Op->Asl.Child);
93218585Sjkim
94218585Sjkim            if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_METHODCALL) &&
95218585Sjkim                (ThisNodeBtype == (ACPI_UINT32_MAX -1)))
96218585Sjkim            {
97218585Sjkim                /*
98218585Sjkim                 * The called method is untyped at this time (typically a
99218585Sjkim                 * forward reference).
100218585Sjkim                 *
101218585Sjkim                 * Check for a recursive method call first.
102218585Sjkim                 */
103218585Sjkim                if (Op->Asl.ParentMethod != Op->Asl.Child->Asl.Node->Op)
104218585Sjkim                {
105218585Sjkim                    /* We must type the method here */
106218585Sjkim
107218585Sjkim                    TrWalkParseTree (Op->Asl.Child->Asl.Node->Op,
108218585Sjkim                        ASL_WALK_VISIT_UPWARD, NULL,
109218585Sjkim                        AnMethodTypingWalkEnd, NULL);
110218585Sjkim
111218585Sjkim                    ThisNodeBtype = AnGetBtype (Op->Asl.Child);
112218585Sjkim                }
113218585Sjkim            }
114218585Sjkim
115218585Sjkim            /* Returns a value, save the value type */
116218585Sjkim
117218585Sjkim            if (Op->Asl.ParentMethod)
118218585Sjkim            {
119218585Sjkim                Op->Asl.ParentMethod->Asl.AcpiBtype |= ThisNodeBtype;
120218585Sjkim            }
121218585Sjkim        }
122218585Sjkim        break;
123218585Sjkim
124218585Sjkim    default:
125218585Sjkim        break;
126218585Sjkim    }
127218585Sjkim
128218585Sjkim    return (AE_OK);
129218585Sjkim}
130218585Sjkim
131218585Sjkim
132218585Sjkim/*******************************************************************************
133218585Sjkim *
134218585Sjkim * FUNCTION:    AnOperandTypecheckWalkEnd
135218585Sjkim *
136218585Sjkim * PARAMETERS:  ASL_WALK_CALLBACK
137218585Sjkim *
138218585Sjkim * RETURN:      Status
139218585Sjkim *
140218585Sjkim * DESCRIPTION: Ascending callback for analysis walk. Complete method
141218585Sjkim *              return analysis.
142218585Sjkim *
143218585Sjkim ******************************************************************************/
144218585Sjkim
145218585SjkimACPI_STATUS
146218585SjkimAnOperandTypecheckWalkEnd (
147218585Sjkim    ACPI_PARSE_OBJECT       *Op,
148218585Sjkim    UINT32                  Level,
149218585Sjkim    void                    *Context)
150218585Sjkim{
151218585Sjkim    const ACPI_OPCODE_INFO  *OpInfo;
152218585Sjkim    UINT32                  RuntimeArgTypes;
153218585Sjkim    UINT32                  RuntimeArgTypes2;
154218585Sjkim    UINT32                  RequiredBtypes;
155218585Sjkim    UINT32                  ThisNodeBtype;
156218585Sjkim    UINT32                  CommonBtypes;
157218585Sjkim    UINT32                  OpcodeClass;
158218585Sjkim    ACPI_PARSE_OBJECT       *ArgOp;
159218585Sjkim    UINT32                  ArgType;
160218585Sjkim
161218585Sjkim
162218585Sjkim    switch (Op->Asl.AmlOpcode)
163218585Sjkim    {
164218585Sjkim    case AML_RAW_DATA_BYTE:
165218585Sjkim    case AML_RAW_DATA_WORD:
166218585Sjkim    case AML_RAW_DATA_DWORD:
167218585Sjkim    case AML_RAW_DATA_QWORD:
168218585Sjkim    case AML_RAW_DATA_BUFFER:
169218585Sjkim    case AML_RAW_DATA_CHAIN:
170218585Sjkim    case AML_PACKAGE_LENGTH:
171218585Sjkim    case AML_UNASSIGNED_OPCODE:
172218585Sjkim    case AML_DEFAULT_ARG_OP:
173218585Sjkim
174218585Sjkim        /* Ignore the internal (compiler-only) AML opcodes */
175218585Sjkim
176218585Sjkim        return (AE_OK);
177218585Sjkim
178218585Sjkim    default:
179218585Sjkim        break;
180218585Sjkim    }
181218585Sjkim
182218585Sjkim    OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
183218585Sjkim    if (!OpInfo)
184218585Sjkim    {
185218585Sjkim        return (AE_OK);
186218585Sjkim    }
187218585Sjkim
188218585Sjkim    ArgOp           = Op->Asl.Child;
189218585Sjkim    RuntimeArgTypes = OpInfo->RuntimeArgs;
190218585Sjkim    OpcodeClass     = OpInfo->Class;
191218585Sjkim
192218585Sjkim#ifdef ASL_ERROR_NAMED_OBJECT_IN_WHILE
193218585Sjkim    /*
194218585Sjkim     * Update 11/2008: In practice, we can't perform this check. A simple
195218585Sjkim     * analysis is not sufficient. Also, it can cause errors when compiling
196218585Sjkim     * disassembled code because of the way Switch operators are implemented
197218585Sjkim     * (a While(One) loop with a named temp variable created within.)
198218585Sjkim     */
199218585Sjkim
200218585Sjkim    /*
201218585Sjkim     * If we are creating a named object, check if we are within a while loop
202218585Sjkim     * by checking if the parent is a WHILE op. This is a simple analysis, but
203218585Sjkim     * probably sufficient for many cases.
204218585Sjkim     *
205218585Sjkim     * Allow Scope(), Buffer(), and Package().
206218585Sjkim     */
207218585Sjkim    if (((OpcodeClass == AML_CLASS_NAMED_OBJECT) && (Op->Asl.AmlOpcode != AML_SCOPE_OP)) ||
208218585Sjkim        ((OpcodeClass == AML_CLASS_CREATE) && (OpInfo->Flags & AML_NSNODE)))
209218585Sjkim    {
210218585Sjkim        if (Op->Asl.Parent->Asl.AmlOpcode == AML_WHILE_OP)
211218585Sjkim        {
212218585Sjkim            AslError (ASL_ERROR, ASL_MSG_NAMED_OBJECT_IN_WHILE, Op, NULL);
213218585Sjkim        }
214218585Sjkim    }
215218585Sjkim#endif
216218585Sjkim
217218585Sjkim    /*
218218585Sjkim     * Special case for control opcodes IF/RETURN/WHILE since they
219218585Sjkim     * have no runtime arg list (at this time)
220218585Sjkim     */
221218585Sjkim    switch (Op->Asl.AmlOpcode)
222218585Sjkim    {
223218585Sjkim    case AML_IF_OP:
224218585Sjkim    case AML_WHILE_OP:
225218585Sjkim    case AML_RETURN_OP:
226218585Sjkim
227218585Sjkim        if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
228218585Sjkim        {
229218585Sjkim            /* Check for an internal method */
230218585Sjkim
231218585Sjkim            if (AnIsInternalMethod (ArgOp))
232218585Sjkim            {
233218585Sjkim                return (AE_OK);
234218585Sjkim            }
235218585Sjkim
236218585Sjkim            /* The lone arg is a method call, check it */
237218585Sjkim
238218585Sjkim            RequiredBtypes = AnMapArgTypeToBtype (ARGI_INTEGER);
239218585Sjkim            if (Op->Asl.AmlOpcode == AML_RETURN_OP)
240218585Sjkim            {
241218585Sjkim                RequiredBtypes = 0xFFFFFFFF;
242218585Sjkim            }
243218585Sjkim
244218585Sjkim            ThisNodeBtype = AnGetBtype (ArgOp);
245218585Sjkim            if (ThisNodeBtype == ACPI_UINT32_MAX)
246218585Sjkim            {
247218585Sjkim                return (AE_OK);
248218585Sjkim            }
249218585Sjkim            AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
250218585Sjkim                RequiredBtypes, ThisNodeBtype);
251218585Sjkim        }
252218585Sjkim        return (AE_OK);
253218585Sjkim
254218585Sjkim    default:
255218585Sjkim        break;
256218585Sjkim    }
257218585Sjkim
258218585Sjkim    /* Ignore the non-executable opcodes */
259218585Sjkim
260218585Sjkim    if (RuntimeArgTypes == ARGI_INVALID_OPCODE)
261218585Sjkim    {
262218585Sjkim        return (AE_OK);
263218585Sjkim    }
264218585Sjkim
265218585Sjkim    switch (OpcodeClass)
266218585Sjkim    {
267218585Sjkim    case AML_CLASS_EXECUTE:
268218585Sjkim    case AML_CLASS_CREATE:
269218585Sjkim    case AML_CLASS_CONTROL:
270218585Sjkim    case AML_CLASS_RETURN_VALUE:
271218585Sjkim
272218585Sjkim        /* TBD: Change class or fix typechecking for these */
273218585Sjkim
274218585Sjkim        if ((Op->Asl.AmlOpcode == AML_BUFFER_OP)        ||
275218585Sjkim            (Op->Asl.AmlOpcode == AML_PACKAGE_OP)       ||
276218585Sjkim            (Op->Asl.AmlOpcode == AML_VAR_PACKAGE_OP))
277218585Sjkim        {
278218585Sjkim            break;
279218585Sjkim        }
280218585Sjkim
281218585Sjkim        /* Reverse the runtime argument list */
282218585Sjkim
283218585Sjkim        RuntimeArgTypes2 = 0;
284218585Sjkim        while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes)))
285218585Sjkim        {
286218585Sjkim            RuntimeArgTypes2 <<= ARG_TYPE_WIDTH;
287218585Sjkim            RuntimeArgTypes2 |= ArgType;
288218585Sjkim            INCREMENT_ARG_LIST (RuntimeArgTypes);
289218585Sjkim        }
290218585Sjkim
291218585Sjkim        while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2)))
292218585Sjkim        {
293218585Sjkim            RequiredBtypes = AnMapArgTypeToBtype (ArgType);
294218585Sjkim
295218585Sjkim            ThisNodeBtype = AnGetBtype (ArgOp);
296218585Sjkim            if (ThisNodeBtype == ACPI_UINT32_MAX)
297218585Sjkim            {
298218585Sjkim                goto NextArgument;
299218585Sjkim            }
300218585Sjkim
301218585Sjkim            /* Examine the arg based on the required type of the arg */
302218585Sjkim
303218585Sjkim            switch (ArgType)
304218585Sjkim            {
305218585Sjkim            case ARGI_TARGETREF:
306218585Sjkim
307218585Sjkim                if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO)
308218585Sjkim                {
309218585Sjkim                    /* ZERO is the placeholder for "don't store result" */
310218585Sjkim
311218585Sjkim                    ThisNodeBtype = RequiredBtypes;
312218585Sjkim                    break;
313218585Sjkim                }
314218585Sjkim
315218585Sjkim                if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER)
316218585Sjkim                {
317218585Sjkim                    /*
318218585Sjkim                     * This is the case where an original reference to a resource
319218585Sjkim                     * descriptor field has been replaced by an (Integer) offset.
320218585Sjkim                     * These named fields are supported at compile-time only;
321218585Sjkim                     * the names are not passed to the interpreter (via the AML).
322218585Sjkim                     */
323218585Sjkim                    if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
324218585Sjkim                        (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
325218585Sjkim                    {
326218585Sjkim                        AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD, ArgOp, NULL);
327218585Sjkim                    }
328218585Sjkim                    else
329218585Sjkim                    {
330218585Sjkim                        AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, NULL);
331218585Sjkim                    }
332218585Sjkim                    break;
333218585Sjkim                }
334218585Sjkim
335218585Sjkim                if ((ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) ||
336218585Sjkim                    (ArgOp->Asl.ParseOpcode == PARSEOP_DEREFOF))
337218585Sjkim                {
338218585Sjkim                    break;
339218585Sjkim                }
340218585Sjkim
341218585Sjkim                ThisNodeBtype = RequiredBtypes;
342218585Sjkim                break;
343218585Sjkim
344218585Sjkim
345218585Sjkim            case ARGI_REFERENCE:            /* References */
346218585Sjkim            case ARGI_INTEGER_REF:
347218585Sjkim            case ARGI_OBJECT_REF:
348218585Sjkim            case ARGI_DEVICE_REF:
349218585Sjkim
350218585Sjkim                switch (ArgOp->Asl.ParseOpcode)
351218585Sjkim                {
352218585Sjkim                case PARSEOP_LOCAL0:
353218585Sjkim                case PARSEOP_LOCAL1:
354218585Sjkim                case PARSEOP_LOCAL2:
355218585Sjkim                case PARSEOP_LOCAL3:
356218585Sjkim                case PARSEOP_LOCAL4:
357218585Sjkim                case PARSEOP_LOCAL5:
358218585Sjkim                case PARSEOP_LOCAL6:
359218585Sjkim                case PARSEOP_LOCAL7:
360218585Sjkim
361218585Sjkim                    /* TBD: implement analysis of current value (type) of the local */
362218585Sjkim                    /* For now, just treat any local as a typematch */
363218585Sjkim
364218585Sjkim                    /*ThisNodeBtype = RequiredBtypes;*/
365218585Sjkim                    break;
366218585Sjkim
367218585Sjkim                case PARSEOP_ARG0:
368218585Sjkim                case PARSEOP_ARG1:
369218585Sjkim                case PARSEOP_ARG2:
370218585Sjkim                case PARSEOP_ARG3:
371218585Sjkim                case PARSEOP_ARG4:
372218585Sjkim                case PARSEOP_ARG5:
373218585Sjkim                case PARSEOP_ARG6:
374218585Sjkim
375218585Sjkim                    /* Hard to analyze argument types, sow we won't */
376218585Sjkim                    /* For now, just treat any arg as a typematch */
377218585Sjkim
378218585Sjkim                    /* ThisNodeBtype = RequiredBtypes; */
379218585Sjkim                    break;
380218585Sjkim
381218585Sjkim                case PARSEOP_DEBUG:
382218585Sjkim                    break;
383218585Sjkim
384218585Sjkim                case PARSEOP_REFOF:
385218585Sjkim                case PARSEOP_INDEX:
386218585Sjkim                default:
387218585Sjkim                    break;
388218585Sjkim
389218585Sjkim                }
390218585Sjkim                break;
391218585Sjkim
392218585Sjkim            case ARGI_INTEGER:
393218585Sjkim            default:
394218585Sjkim                break;
395218585Sjkim            }
396218585Sjkim
397218585Sjkim
398218585Sjkim            CommonBtypes = ThisNodeBtype & RequiredBtypes;
399218585Sjkim
400218585Sjkim            if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
401218585Sjkim            {
402218585Sjkim                if (AnIsInternalMethod (ArgOp))
403218585Sjkim                {
404218585Sjkim                    return (AE_OK);
405218585Sjkim                }
406218585Sjkim
407218585Sjkim                /* Check a method call for a valid return value */
408218585Sjkim
409218585Sjkim                AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
410218585Sjkim                    RequiredBtypes, ThisNodeBtype);
411218585Sjkim            }
412218585Sjkim
413218585Sjkim            /*
414218585Sjkim             * Now check if the actual type(s) match at least one
415218585Sjkim             * bit to the required type
416218585Sjkim             */
417218585Sjkim            else if (!CommonBtypes)
418218585Sjkim            {
419218585Sjkim                /* No match -- this is a type mismatch error */
420218585Sjkim
421218585Sjkim                AnFormatBtype (StringBuffer, ThisNodeBtype);
422218585Sjkim                AnFormatBtype (StringBuffer2, RequiredBtypes);
423218585Sjkim
424218585Sjkim                sprintf (MsgBuffer, "[%s] found, %s operator requires [%s]",
425218585Sjkim                            StringBuffer, OpInfo->Name, StringBuffer2);
426218585Sjkim
427218585Sjkim                AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer);
428218585Sjkim            }
429218585Sjkim
430218585Sjkim        NextArgument:
431218585Sjkim            ArgOp = ArgOp->Asl.Next;
432218585Sjkim            INCREMENT_ARG_LIST (RuntimeArgTypes2);
433218585Sjkim        }
434218585Sjkim        break;
435218585Sjkim
436218585Sjkim    default:
437218585Sjkim        break;
438218585Sjkim    }
439218585Sjkim
440218585Sjkim    return (AE_OK);
441218585Sjkim}
442218585Sjkim
443218585Sjkim
444218585Sjkim/*******************************************************************************
445218585Sjkim *
446218585Sjkim * FUNCTION:    AnOtherSemanticAnalysisWalkBegin
447218585Sjkim *
448218585Sjkim * PARAMETERS:  ASL_WALK_CALLBACK
449218585Sjkim *
450218585Sjkim * RETURN:      Status
451218585Sjkim *
452218585Sjkim * DESCRIPTION: Descending callback for the analysis walk. Checks for
453218585Sjkim *              miscellaneous issues in the code.
454218585Sjkim *
455218585Sjkim ******************************************************************************/
456218585Sjkim
457218585SjkimACPI_STATUS
458218585SjkimAnOtherSemanticAnalysisWalkBegin (
459218585Sjkim    ACPI_PARSE_OBJECT       *Op,
460218585Sjkim    UINT32                  Level,
461218585Sjkim    void                    *Context)
462218585Sjkim{
463218585Sjkim    ACPI_PARSE_OBJECT       *ArgNode;
464218585Sjkim    ACPI_PARSE_OBJECT       *PrevArgNode = NULL;
465218585Sjkim    const ACPI_OPCODE_INFO  *OpInfo;
466228110Sjkim    ACPI_NAMESPACE_NODE     *Node;
467218585Sjkim
468218585Sjkim
469218585Sjkim    OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
470218585Sjkim
471218585Sjkim    /*
472218585Sjkim     * Determine if an execution class operator actually does something by
473218585Sjkim     * checking if it has a target and/or the function return value is used.
474218585Sjkim     * (Target is optional, so a standalone statement can actually do nothing.)
475218585Sjkim     */
476218585Sjkim    if ((OpInfo->Class == AML_CLASS_EXECUTE) &&
477218585Sjkim        (OpInfo->Flags & AML_HAS_RETVAL) &&
478218585Sjkim        (!AnIsResultUsed (Op)))
479218585Sjkim    {
480218585Sjkim        if (OpInfo->Flags & AML_HAS_TARGET)
481218585Sjkim        {
482218585Sjkim            /*
483218585Sjkim             * Find the target node, it is always the last child. If the traget
484218585Sjkim             * is not specified in the ASL, a default node of type Zero was
485218585Sjkim             * created by the parser.
486218585Sjkim             */
487218585Sjkim            ArgNode = Op->Asl.Child;
488218585Sjkim            while (ArgNode->Asl.Next)
489218585Sjkim            {
490218585Sjkim                PrevArgNode = ArgNode;
491218585Sjkim                ArgNode = ArgNode->Asl.Next;
492218585Sjkim            }
493218585Sjkim
494218585Sjkim            /* Divide() is the only weird case, it has two targets */
495218585Sjkim
496218585Sjkim            if (Op->Asl.AmlOpcode == AML_DIVIDE_OP)
497218585Sjkim            {
498218585Sjkim                if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) &&
499218585Sjkim                    (PrevArgNode) &&
500218585Sjkim                    (PrevArgNode->Asl.ParseOpcode == PARSEOP_ZERO))
501218585Sjkim                {
502249112Sjkim                    AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
503218585Sjkim                        Op, Op->Asl.ExternalName);
504218585Sjkim                }
505218585Sjkim            }
506218585Sjkim            else if (ArgNode->Asl.ParseOpcode == PARSEOP_ZERO)
507218585Sjkim            {
508249112Sjkim                AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
509218585Sjkim                    Op, Op->Asl.ExternalName);
510218585Sjkim            }
511218585Sjkim        }
512218585Sjkim        else
513218585Sjkim        {
514218585Sjkim            /*
515218585Sjkim             * Has no target and the result is not used. Only a couple opcodes
516218585Sjkim             * can have this combination.
517218585Sjkim             */
518218585Sjkim            switch (Op->Asl.ParseOpcode)
519218585Sjkim            {
520218585Sjkim            case PARSEOP_ACQUIRE:
521218585Sjkim            case PARSEOP_WAIT:
522218585Sjkim            case PARSEOP_LOADTABLE:
523218585Sjkim                break;
524218585Sjkim
525218585Sjkim            default:
526249112Sjkim                AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
527218585Sjkim                    Op, Op->Asl.ExternalName);
528218585Sjkim                break;
529218585Sjkim            }
530218585Sjkim        }
531218585Sjkim    }
532218585Sjkim
533218585Sjkim
534218585Sjkim    /*
535218585Sjkim     * Semantic checks for individual ASL operators
536218585Sjkim     */
537218585Sjkim    switch (Op->Asl.ParseOpcode)
538218585Sjkim    {
539218585Sjkim    case PARSEOP_ACQUIRE:
540218585Sjkim    case PARSEOP_WAIT:
541218585Sjkim        /*
542218585Sjkim         * Emit a warning if the timeout parameter for these operators is not
543218585Sjkim         * ACPI_WAIT_FOREVER, and the result value from the operator is not
544218585Sjkim         * checked, meaning that a timeout could happen, but the code
545218585Sjkim         * would not know about it.
546218585Sjkim         */
547218585Sjkim
548218585Sjkim        /* First child is the namepath, 2nd child is timeout */
549218585Sjkim
550218585Sjkim        ArgNode = Op->Asl.Child;
551218585Sjkim        ArgNode = ArgNode->Asl.Next;
552218585Sjkim
553218585Sjkim        /*
554218585Sjkim         * Check for the WAIT_FOREVER case - defined by the ACPI spec to be
555218585Sjkim         * 0xFFFF or greater
556218585Sjkim         */
557218585Sjkim        if (((ArgNode->Asl.ParseOpcode == PARSEOP_WORDCONST) ||
558218585Sjkim             (ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER))  &&
559218585Sjkim             (ArgNode->Asl.Value.Integer >= (UINT64) ACPI_WAIT_FOREVER))
560218585Sjkim        {
561218585Sjkim            break;
562218585Sjkim        }
563218585Sjkim
564218585Sjkim        /*
565218585Sjkim         * The operation could timeout. If the return value is not used
566218585Sjkim         * (indicates timeout occurred), issue a warning
567218585Sjkim         */
568218585Sjkim        if (!AnIsResultUsed (Op))
569218585Sjkim        {
570218585Sjkim            AslError (ASL_WARNING, ASL_MSG_TIMEOUT, ArgNode,
571218585Sjkim                Op->Asl.ExternalName);
572218585Sjkim        }
573218585Sjkim        break;
574218585Sjkim
575218585Sjkim    case PARSEOP_CREATEFIELD:
576218585Sjkim        /*
577218585Sjkim         * Check for a zero Length (NumBits) operand. NumBits is the 3rd operand
578218585Sjkim         */
579218585Sjkim        ArgNode = Op->Asl.Child;
580218585Sjkim        ArgNode = ArgNode->Asl.Next;
581218585Sjkim        ArgNode = ArgNode->Asl.Next;
582218585Sjkim
583218585Sjkim        if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) ||
584218585Sjkim           ((ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER) &&
585218585Sjkim            (ArgNode->Asl.Value.Integer == 0)))
586218585Sjkim        {
587218585Sjkim            AslError (ASL_ERROR, ASL_MSG_NON_ZERO, ArgNode, NULL);
588218585Sjkim        }
589218585Sjkim        break;
590218585Sjkim
591228110Sjkim    case PARSEOP_CONNECTION:
592228110Sjkim        /*
593228110Sjkim         * Ensure that the referenced operation region has the correct SPACE_ID.
594228110Sjkim         * From the grammar/parser, we know the parent is a FIELD definition.
595228110Sjkim         */
596228110Sjkim        ArgNode = Op->Asl.Parent;       /* Field definition */
597228110Sjkim        ArgNode = ArgNode->Asl.Child;   /* First child is the OpRegion Name */
598228110Sjkim        Node = ArgNode->Asl.Node;       /* OpRegion namespace node */
599228110Sjkim
600228110Sjkim        ArgNode = Node->Op;             /* OpRegion definition */
601228110Sjkim        ArgNode = ArgNode->Asl.Child;   /* First child is the OpRegion Name */
602228110Sjkim        ArgNode = ArgNode->Asl.Next;    /* Next peer is the SPACE_ID (what we want) */
603228110Sjkim
604228110Sjkim        /*
605228110Sjkim         * The Connection() operator is only valid for the following operation
606228110Sjkim         * region SpaceIds: GeneralPurposeIo and GenericSerialBus.
607228110Sjkim         */
608228110Sjkim        if ((ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) &&
609228110Sjkim            (ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS))
610228110Sjkim        {
611228110Sjkim            AslError (ASL_ERROR, ASL_MSG_CONNECTION_INVALID, Op, NULL);
612228110Sjkim        }
613228110Sjkim        break;
614228110Sjkim
615228110Sjkim    case PARSEOP_FIELD:
616228110Sjkim        /*
617228110Sjkim         * Ensure that fields for GeneralPurposeIo and GenericSerialBus
618228110Sjkim         * contain at least one Connection() operator
619228110Sjkim         */
620228110Sjkim        ArgNode = Op->Asl.Child;        /* 1st child is the OpRegion Name */
621228110Sjkim        Node = ArgNode->Asl.Node;       /* OpRegion namespace node */
622228110Sjkim        if (!Node)
623228110Sjkim        {
624228110Sjkim            break;
625228110Sjkim        }
626228110Sjkim
627228110Sjkim        ArgNode = Node->Op;             /* OpRegion definition */
628228110Sjkim        ArgNode = ArgNode->Asl.Child;   /* First child is the OpRegion Name */
629228110Sjkim        ArgNode = ArgNode->Asl.Next;    /* Next peer is the SPACE_ID (what we want) */
630228110Sjkim
631228110Sjkim        /* We are only interested in GeneralPurposeIo and GenericSerialBus */
632228110Sjkim
633228110Sjkim        if ((ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) &&
634228110Sjkim            (ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS))
635228110Sjkim        {
636228110Sjkim            break;
637228110Sjkim        }
638228110Sjkim
639228110Sjkim        ArgNode = Op->Asl.Child;        /* 1st child is the OpRegion Name */
640228110Sjkim        ArgNode = ArgNode->Asl.Next;    /* AccessType */
641228110Sjkim        ArgNode = ArgNode->Asl.Next;    /* LockRule */
642228110Sjkim        ArgNode = ArgNode->Asl.Next;    /* UpdateRule */
643228110Sjkim        ArgNode = ArgNode->Asl.Next;    /* Start of FieldUnitList */
644228110Sjkim
645228110Sjkim        /* Walk the FieldUnitList */
646228110Sjkim
647228110Sjkim        while (ArgNode)
648228110Sjkim        {
649228110Sjkim            if (ArgNode->Asl.ParseOpcode == PARSEOP_CONNECTION)
650228110Sjkim            {
651228110Sjkim                break;
652228110Sjkim            }
653228110Sjkim            else if (ArgNode->Asl.ParseOpcode == PARSEOP_NAMESEG)
654228110Sjkim            {
655228110Sjkim                AslError (ASL_ERROR, ASL_MSG_CONNECTION_MISSING, ArgNode, NULL);
656228110Sjkim                break;
657228110Sjkim            }
658228110Sjkim
659228110Sjkim            ArgNode = ArgNode->Asl.Next;
660228110Sjkim        }
661228110Sjkim        break;
662228110Sjkim
663218585Sjkim    default:
664218585Sjkim        break;
665218585Sjkim    }
666218585Sjkim
667218585Sjkim    return (AE_OK);
668218585Sjkim}
669