1218585Sjkim/******************************************************************************
2218585Sjkim *
3245582Sjkim * Module Name: aslwalks.c - Miscellaneous analytical parse tree walks
4218585Sjkim *
5218585Sjkim *****************************************************************************/
6218585Sjkim
7218585Sjkim/*
8306536Sjkim * Copyright (C) 2000 - 2016, 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
44218590Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h>
45218585Sjkim#include "aslcompiler.y.h"
46218590Sjkim#include <contrib/dev/acpica/include/acparser.h>
47218590Sjkim#include <contrib/dev/acpica/include/amlcode.h>
48218585Sjkim
49218585Sjkim
50218585Sjkim#define _COMPONENT          ACPI_COMPILER
51218585Sjkim        ACPI_MODULE_NAME    ("aslwalks")
52218585Sjkim
53218585Sjkim
54306536Sjkim/* Local prototypes */
55306536Sjkim
56306536Sjkimstatic void
57306536SjkimAnAnalyzeStoreOperator (
58306536Sjkim    ACPI_PARSE_OBJECT       *Op);
59306536Sjkim
60306536Sjkim
61218585Sjkim/*******************************************************************************
62218585Sjkim *
63218585Sjkim * FUNCTION:    AnMethodTypingWalkEnd
64218585Sjkim *
65218585Sjkim * PARAMETERS:  ASL_WALK_CALLBACK
66218585Sjkim *
67218585Sjkim * RETURN:      Status
68218585Sjkim *
69218585Sjkim * DESCRIPTION: Ascending callback for typing walk. Complete the method
70218585Sjkim *              return analysis. Check methods for:
71218585Sjkim *              1) Initialized local variables
72218585Sjkim *              2) Valid arguments
73218585Sjkim *              3) Return types
74218585Sjkim *
75218585Sjkim ******************************************************************************/
76218585Sjkim
77218585SjkimACPI_STATUS
78218585SjkimAnMethodTypingWalkEnd (
79218585Sjkim    ACPI_PARSE_OBJECT       *Op,
80218585Sjkim    UINT32                  Level,
81218585Sjkim    void                    *Context)
82218585Sjkim{
83306536Sjkim    UINT32                  ThisOpBtype;
84218585Sjkim
85218585Sjkim
86218585Sjkim    switch (Op->Asl.ParseOpcode)
87218585Sjkim    {
88218585Sjkim    case PARSEOP_METHOD:
89218585Sjkim
90218585Sjkim        Op->Asl.CompileFlags |= NODE_METHOD_TYPED;
91218585Sjkim        break;
92218585Sjkim
93218585Sjkim    case PARSEOP_RETURN:
94218585Sjkim
95218585Sjkim        if ((Op->Asl.Child) &&
96218585Sjkim            (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
97218585Sjkim        {
98306536Sjkim            ThisOpBtype = AnGetBtype (Op->Asl.Child);
99218585Sjkim
100218585Sjkim            if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_METHODCALL) &&
101306536Sjkim                (ThisOpBtype == (ACPI_UINT32_MAX -1)))
102218585Sjkim            {
103218585Sjkim                /*
104218585Sjkim                 * The called method is untyped at this time (typically a
105218585Sjkim                 * forward reference).
106218585Sjkim                 *
107306536Sjkim                 * Check for a recursive method call first. Note: the
108306536Sjkim                 * Child->Node will be null if the method has not been
109306536Sjkim                 * resolved.
110218585Sjkim                 */
111306536Sjkim                if (Op->Asl.Child->Asl.Node &&
112306536Sjkim                    (Op->Asl.ParentMethod != Op->Asl.Child->Asl.Node->Op))
113218585Sjkim                {
114218585Sjkim                    /* We must type the method here */
115218585Sjkim
116218585Sjkim                    TrWalkParseTree (Op->Asl.Child->Asl.Node->Op,
117218585Sjkim                        ASL_WALK_VISIT_UPWARD, NULL,
118218585Sjkim                        AnMethodTypingWalkEnd, NULL);
119218585Sjkim
120306536Sjkim                    ThisOpBtype = AnGetBtype (Op->Asl.Child);
121218585Sjkim                }
122218585Sjkim            }
123218585Sjkim
124218585Sjkim            /* Returns a value, save the value type */
125218585Sjkim
126218585Sjkim            if (Op->Asl.ParentMethod)
127218585Sjkim            {
128306536Sjkim                Op->Asl.ParentMethod->Asl.AcpiBtype |= ThisOpBtype;
129218585Sjkim            }
130218585Sjkim        }
131218585Sjkim        break;
132218585Sjkim
133218585Sjkim    default:
134250838Sjkim
135218585Sjkim        break;
136218585Sjkim    }
137218585Sjkim
138218585Sjkim    return (AE_OK);
139218585Sjkim}
140218585Sjkim
141218585Sjkim
142218585Sjkim/*******************************************************************************
143218585Sjkim *
144218585Sjkim * FUNCTION:    AnOperandTypecheckWalkEnd
145218585Sjkim *
146218585Sjkim * PARAMETERS:  ASL_WALK_CALLBACK
147218585Sjkim *
148218585Sjkim * RETURN:      Status
149218585Sjkim *
150218585Sjkim * DESCRIPTION: Ascending callback for analysis walk. Complete method
151218585Sjkim *              return analysis.
152218585Sjkim *
153218585Sjkim ******************************************************************************/
154218585Sjkim
155218585SjkimACPI_STATUS
156218585SjkimAnOperandTypecheckWalkEnd (
157218585Sjkim    ACPI_PARSE_OBJECT       *Op,
158218585Sjkim    UINT32                  Level,
159218585Sjkim    void                    *Context)
160218585Sjkim{
161218585Sjkim    const ACPI_OPCODE_INFO  *OpInfo;
162218585Sjkim    UINT32                  RuntimeArgTypes;
163218585Sjkim    UINT32                  RuntimeArgTypes2;
164218585Sjkim    UINT32                  RequiredBtypes;
165218585Sjkim    UINT32                  ThisNodeBtype;
166218585Sjkim    UINT32                  CommonBtypes;
167218585Sjkim    UINT32                  OpcodeClass;
168218585Sjkim    ACPI_PARSE_OBJECT       *ArgOp;
169218585Sjkim    UINT32                  ArgType;
170218585Sjkim
171218585Sjkim
172218585Sjkim    switch (Op->Asl.AmlOpcode)
173218585Sjkim    {
174218585Sjkim    case AML_RAW_DATA_BYTE:
175218585Sjkim    case AML_RAW_DATA_WORD:
176218585Sjkim    case AML_RAW_DATA_DWORD:
177218585Sjkim    case AML_RAW_DATA_QWORD:
178218585Sjkim    case AML_RAW_DATA_BUFFER:
179218585Sjkim    case AML_RAW_DATA_CHAIN:
180218585Sjkim    case AML_PACKAGE_LENGTH:
181218585Sjkim    case AML_UNASSIGNED_OPCODE:
182218585Sjkim    case AML_DEFAULT_ARG_OP:
183218585Sjkim
184218585Sjkim        /* Ignore the internal (compiler-only) AML opcodes */
185218585Sjkim
186218585Sjkim        return (AE_OK);
187218585Sjkim
188218585Sjkim    default:
189250838Sjkim
190218585Sjkim        break;
191218585Sjkim    }
192218585Sjkim
193218585Sjkim    OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
194218585Sjkim    if (!OpInfo)
195218585Sjkim    {
196218585Sjkim        return (AE_OK);
197218585Sjkim    }
198218585Sjkim
199306536Sjkim    ArgOp = Op->Asl.Child;
200306536Sjkim    OpcodeClass = OpInfo->Class;
201218585Sjkim    RuntimeArgTypes = OpInfo->RuntimeArgs;
202218585Sjkim
203218585Sjkim#ifdef ASL_ERROR_NAMED_OBJECT_IN_WHILE
204218585Sjkim    /*
205218585Sjkim     * Update 11/2008: In practice, we can't perform this check. A simple
206218585Sjkim     * analysis is not sufficient. Also, it can cause errors when compiling
207218585Sjkim     * disassembled code because of the way Switch operators are implemented
208218585Sjkim     * (a While(One) loop with a named temp variable created within.)
209218585Sjkim     */
210218585Sjkim
211218585Sjkim    /*
212218585Sjkim     * If we are creating a named object, check if we are within a while loop
213218585Sjkim     * by checking if the parent is a WHILE op. This is a simple analysis, but
214218585Sjkim     * probably sufficient for many cases.
215218585Sjkim     *
216218585Sjkim     * Allow Scope(), Buffer(), and Package().
217218585Sjkim     */
218218585Sjkim    if (((OpcodeClass == AML_CLASS_NAMED_OBJECT) && (Op->Asl.AmlOpcode != AML_SCOPE_OP)) ||
219218585Sjkim        ((OpcodeClass == AML_CLASS_CREATE) && (OpInfo->Flags & AML_NSNODE)))
220218585Sjkim    {
221218585Sjkim        if (Op->Asl.Parent->Asl.AmlOpcode == AML_WHILE_OP)
222218585Sjkim        {
223218585Sjkim            AslError (ASL_ERROR, ASL_MSG_NAMED_OBJECT_IN_WHILE, Op, NULL);
224218585Sjkim        }
225218585Sjkim    }
226218585Sjkim#endif
227218585Sjkim
228218585Sjkim    /*
229218585Sjkim     * Special case for control opcodes IF/RETURN/WHILE since they
230218585Sjkim     * have no runtime arg list (at this time)
231218585Sjkim     */
232218585Sjkim    switch (Op->Asl.AmlOpcode)
233218585Sjkim    {
234218585Sjkim    case AML_IF_OP:
235218585Sjkim    case AML_WHILE_OP:
236218585Sjkim    case AML_RETURN_OP:
237218585Sjkim
238218585Sjkim        if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
239218585Sjkim        {
240218585Sjkim            /* Check for an internal method */
241218585Sjkim
242218585Sjkim            if (AnIsInternalMethod (ArgOp))
243218585Sjkim            {
244218585Sjkim                return (AE_OK);
245218585Sjkim            }
246218585Sjkim
247218585Sjkim            /* The lone arg is a method call, check it */
248218585Sjkim
249218585Sjkim            RequiredBtypes = AnMapArgTypeToBtype (ARGI_INTEGER);
250218585Sjkim            if (Op->Asl.AmlOpcode == AML_RETURN_OP)
251218585Sjkim            {
252218585Sjkim                RequiredBtypes = 0xFFFFFFFF;
253218585Sjkim            }
254218585Sjkim
255218585Sjkim            ThisNodeBtype = AnGetBtype (ArgOp);
256218585Sjkim            if (ThisNodeBtype == ACPI_UINT32_MAX)
257218585Sjkim            {
258218585Sjkim                return (AE_OK);
259218585Sjkim            }
260306536Sjkim
261218585Sjkim            AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
262218585Sjkim                RequiredBtypes, ThisNodeBtype);
263218585Sjkim        }
264218585Sjkim        return (AE_OK);
265218585Sjkim
266281687Sjkim    case AML_EXTERNAL_OP:
267281687Sjkim        /*
268281687Sjkim         * Not really a "runtime" opcode since it used by disassembler only.
269281687Sjkim         * The parser will find any issues with the operands.
270281687Sjkim         */
271281687Sjkim        return (AE_OK);
272281687Sjkim
273218585Sjkim    default:
274250838Sjkim
275218585Sjkim        break;
276218585Sjkim    }
277218585Sjkim
278218585Sjkim    /* Ignore the non-executable opcodes */
279218585Sjkim
280218585Sjkim    if (RuntimeArgTypes == ARGI_INVALID_OPCODE)
281218585Sjkim    {
282218585Sjkim        return (AE_OK);
283218585Sjkim    }
284218585Sjkim
285306536Sjkim    /*
286306536Sjkim     * Special handling for certain opcodes.
287306536Sjkim     */
288306536Sjkim    switch (Op->Asl.AmlOpcode)
289306536Sjkim    {
290306536Sjkim        /* BankField has one TermArg */
291306536Sjkim
292306536Sjkim    case AML_BANK_FIELD_OP:
293306536Sjkim
294306536Sjkim        OpcodeClass = AML_CLASS_EXECUTE;
295306536Sjkim        ArgOp = ArgOp->Asl.Next;
296306536Sjkim        ArgOp = ArgOp->Asl.Next;
297306536Sjkim        break;
298306536Sjkim
299306536Sjkim        /* Operation Region has 2 TermArgs */
300306536Sjkim
301306536Sjkim    case AML_REGION_OP:
302306536Sjkim
303306536Sjkim        OpcodeClass = AML_CLASS_EXECUTE;
304306536Sjkim        ArgOp = ArgOp->Asl.Next;
305306536Sjkim        ArgOp = ArgOp->Asl.Next;
306306536Sjkim        break;
307306536Sjkim
308306536Sjkim        /* DataTableRegion has 3 TermArgs */
309306536Sjkim
310306536Sjkim    case AML_DATA_REGION_OP:
311306536Sjkim
312306536Sjkim        OpcodeClass = AML_CLASS_EXECUTE;
313306536Sjkim        ArgOp = ArgOp->Asl.Next;
314306536Sjkim        break;
315306536Sjkim
316306536Sjkim        /* Buffers/Packages have a length that is a TermArg */
317306536Sjkim
318306536Sjkim    case AML_BUFFER_OP:
319306536Sjkim    case AML_PACKAGE_OP:
320306536Sjkim    case AML_VAR_PACKAGE_OP:
321306536Sjkim
322306536Sjkim            /* If length is a constant, we are done */
323306536Sjkim
324306536Sjkim        if ((ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER) ||
325306536Sjkim            (ArgOp->Asl.ParseOpcode == PARSEOP_RAW_DATA))
326306536Sjkim        {
327306536Sjkim            return (AE_OK);
328306536Sjkim        }
329306536Sjkim        break;
330306536Sjkim
331306536Sjkim        /* Store can write any object to the Debug object */
332306536Sjkim
333306536Sjkim    case AML_STORE_OP:
334306536Sjkim        /*
335306536Sjkim         * If this is a Store() to the Debug object, we don't need
336306536Sjkim         * to perform any further validation -- because a Store of
337306536Sjkim         * any object to Debug is permitted and supported.
338306536Sjkim         */
339306536Sjkim        if (ArgOp->Asl.Next->Asl.AmlOpcode == AML_DEBUG_OP)
340306536Sjkim        {
341306536Sjkim            return (AE_OK);
342306536Sjkim        }
343306536Sjkim        break;
344306536Sjkim
345306536Sjkim    default:
346306536Sjkim        break;
347306536Sjkim    }
348306536Sjkim
349218585Sjkim    switch (OpcodeClass)
350218585Sjkim    {
351218585Sjkim    case AML_CLASS_EXECUTE:
352218585Sjkim    case AML_CLASS_CREATE:
353218585Sjkim    case AML_CLASS_CONTROL:
354218585Sjkim    case AML_CLASS_RETURN_VALUE:
355218585Sjkim
356218585Sjkim        /* Reverse the runtime argument list */
357218585Sjkim
358218585Sjkim        RuntimeArgTypes2 = 0;
359218585Sjkim        while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes)))
360218585Sjkim        {
361218585Sjkim            RuntimeArgTypes2 <<= ARG_TYPE_WIDTH;
362218585Sjkim            RuntimeArgTypes2 |= ArgType;
363218585Sjkim            INCREMENT_ARG_LIST (RuntimeArgTypes);
364218585Sjkim        }
365218585Sjkim
366306536Sjkim        /* Typecheck each argument */
367306536Sjkim
368218585Sjkim        while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2)))
369218585Sjkim        {
370306536Sjkim            /* Get the required type(s) for the argument */
371306536Sjkim
372218585Sjkim            RequiredBtypes = AnMapArgTypeToBtype (ArgType);
373218585Sjkim
374281075Sdim            if (!ArgOp)
375281075Sdim            {
376281075Sdim                AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
377281075Sdim                    "Null ArgOp in argument loop");
378281075Sdim                AslAbort ();
379281075Sdim            }
380281075Sdim
381306536Sjkim            /* Get the actual type of the argument */
382306536Sjkim
383218585Sjkim            ThisNodeBtype = AnGetBtype (ArgOp);
384218585Sjkim            if (ThisNodeBtype == ACPI_UINT32_MAX)
385218585Sjkim            {
386218585Sjkim                goto NextArgument;
387218585Sjkim            }
388218585Sjkim
389218585Sjkim            /* Examine the arg based on the required type of the arg */
390218585Sjkim
391218585Sjkim            switch (ArgType)
392218585Sjkim            {
393218585Sjkim            case ARGI_TARGETREF:
394218585Sjkim
395218585Sjkim                if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO)
396218585Sjkim                {
397218585Sjkim                    /* ZERO is the placeholder for "don't store result" */
398218585Sjkim
399218585Sjkim                    ThisNodeBtype = RequiredBtypes;
400218585Sjkim                    break;
401218585Sjkim                }
402218585Sjkim
403306536Sjkim            /* Fallthrough */
404306536Sjkim
405306536Sjkim            case ARGI_STORE_TARGET:
406306536Sjkim
407218585Sjkim                if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER)
408218585Sjkim                {
409218585Sjkim                    /*
410218585Sjkim                     * This is the case where an original reference to a resource
411218585Sjkim                     * descriptor field has been replaced by an (Integer) offset.
412218585Sjkim                     * These named fields are supported at compile-time only;
413218585Sjkim                     * the names are not passed to the interpreter (via the AML).
414218585Sjkim                     */
415218585Sjkim                    if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
416218585Sjkim                        (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
417218585Sjkim                    {
418306536Sjkim                        AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD,
419306536Sjkim                            ArgOp, NULL);
420218585Sjkim                    }
421218585Sjkim                    else
422218585Sjkim                    {
423306536Sjkim                        AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE,
424306536Sjkim                            ArgOp, NULL);
425218585Sjkim                    }
426218585Sjkim                }
427218585Sjkim                break;
428218585Sjkim
429218585Sjkim
430306536Sjkim#ifdef __FUTURE_IMPLEMENTATION
431306536Sjkim/*
432306536Sjkim * Possible future typechecking support
433306536Sjkim */
434218585Sjkim            case ARGI_REFERENCE:            /* References */
435218585Sjkim            case ARGI_INTEGER_REF:
436218585Sjkim            case ARGI_OBJECT_REF:
437218585Sjkim            case ARGI_DEVICE_REF:
438218585Sjkim
439218585Sjkim                switch (ArgOp->Asl.ParseOpcode)
440218585Sjkim                {
441218585Sjkim                case PARSEOP_LOCAL0:
442218585Sjkim                case PARSEOP_LOCAL1:
443218585Sjkim                case PARSEOP_LOCAL2:
444218585Sjkim                case PARSEOP_LOCAL3:
445218585Sjkim                case PARSEOP_LOCAL4:
446218585Sjkim                case PARSEOP_LOCAL5:
447218585Sjkim                case PARSEOP_LOCAL6:
448218585Sjkim                case PARSEOP_LOCAL7:
449218585Sjkim
450218585Sjkim                    /* TBD: implement analysis of current value (type) of the local */
451218585Sjkim                    /* For now, just treat any local as a typematch */
452218585Sjkim
453218585Sjkim                    /*ThisNodeBtype = RequiredBtypes;*/
454218585Sjkim                    break;
455218585Sjkim
456218585Sjkim                case PARSEOP_ARG0:
457218585Sjkim                case PARSEOP_ARG1:
458218585Sjkim                case PARSEOP_ARG2:
459218585Sjkim                case PARSEOP_ARG3:
460218585Sjkim                case PARSEOP_ARG4:
461218585Sjkim                case PARSEOP_ARG5:
462218585Sjkim                case PARSEOP_ARG6:
463218585Sjkim
464306536Sjkim                    /* Hard to analyze argument types, so we won't */
465306536Sjkim                    /* for now. Just treat any arg as a typematch */
466218585Sjkim
467218585Sjkim                    /* ThisNodeBtype = RequiredBtypes; */
468218585Sjkim                    break;
469218585Sjkim
470218585Sjkim                case PARSEOP_DEBUG:
471218585Sjkim                case PARSEOP_REFOF:
472218585Sjkim                case PARSEOP_INDEX:
473218585Sjkim                default:
474250838Sjkim
475218585Sjkim                    break;
476218585Sjkim                }
477218585Sjkim                break;
478306536Sjkim#endif
479218585Sjkim            case ARGI_INTEGER:
480218585Sjkim            default:
481250838Sjkim
482218585Sjkim                break;
483218585Sjkim            }
484218585Sjkim
485218585Sjkim
486306536Sjkim            /* Check for a type mismatch (required versus actual) */
487306536Sjkim
488218585Sjkim            CommonBtypes = ThisNodeBtype & RequiredBtypes;
489218585Sjkim
490218585Sjkim            if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
491218585Sjkim            {
492218585Sjkim                if (AnIsInternalMethod (ArgOp))
493218585Sjkim                {
494218585Sjkim                    return (AE_OK);
495218585Sjkim                }
496218585Sjkim
497218585Sjkim                /* Check a method call for a valid return value */
498218585Sjkim
499218585Sjkim                AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
500218585Sjkim                    RequiredBtypes, ThisNodeBtype);
501218585Sjkim            }
502218585Sjkim
503218585Sjkim            /*
504218585Sjkim             * Now check if the actual type(s) match at least one
505218585Sjkim             * bit to the required type
506218585Sjkim             */
507218585Sjkim            else if (!CommonBtypes)
508218585Sjkim            {
509218585Sjkim                /* No match -- this is a type mismatch error */
510218585Sjkim
511218585Sjkim                AnFormatBtype (StringBuffer, ThisNodeBtype);
512218585Sjkim                AnFormatBtype (StringBuffer2, RequiredBtypes);
513218585Sjkim
514218585Sjkim                sprintf (MsgBuffer, "[%s] found, %s operator requires [%s]",
515306536Sjkim                    StringBuffer, OpInfo->Name, StringBuffer2);
516218585Sjkim
517306536Sjkim                AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE,
518306536Sjkim                    ArgOp, MsgBuffer);
519218585Sjkim            }
520218585Sjkim
521218585Sjkim        NextArgument:
522218585Sjkim            ArgOp = ArgOp->Asl.Next;
523218585Sjkim            INCREMENT_ARG_LIST (RuntimeArgTypes2);
524218585Sjkim        }
525218585Sjkim        break;
526218585Sjkim
527218585Sjkim    default:
528250838Sjkim
529218585Sjkim        break;
530218585Sjkim    }
531218585Sjkim
532218585Sjkim    return (AE_OK);
533218585Sjkim}
534218585Sjkim
535218585Sjkim
536218585Sjkim/*******************************************************************************
537218585Sjkim *
538218585Sjkim * FUNCTION:    AnOtherSemanticAnalysisWalkBegin
539218585Sjkim *
540218585Sjkim * PARAMETERS:  ASL_WALK_CALLBACK
541218585Sjkim *
542218585Sjkim * RETURN:      Status
543218585Sjkim *
544218585Sjkim * DESCRIPTION: Descending callback for the analysis walk. Checks for
545218585Sjkim *              miscellaneous issues in the code.
546218585Sjkim *
547218585Sjkim ******************************************************************************/
548218585Sjkim
549218585SjkimACPI_STATUS
550218585SjkimAnOtherSemanticAnalysisWalkBegin (
551218585Sjkim    ACPI_PARSE_OBJECT       *Op,
552218585Sjkim    UINT32                  Level,
553218585Sjkim    void                    *Context)
554218585Sjkim{
555306536Sjkim    ACPI_PARSE_OBJECT       *ArgOp;
556306536Sjkim    ACPI_PARSE_OBJECT       *PrevArgOp = NULL;
557218585Sjkim    const ACPI_OPCODE_INFO  *OpInfo;
558228110Sjkim    ACPI_NAMESPACE_NODE     *Node;
559218585Sjkim
560218585Sjkim
561218585Sjkim    OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
562218585Sjkim
563306536Sjkim
564218585Sjkim    /*
565218585Sjkim     * Determine if an execution class operator actually does something by
566218585Sjkim     * checking if it has a target and/or the function return value is used.
567218585Sjkim     * (Target is optional, so a standalone statement can actually do nothing.)
568218585Sjkim     */
569218585Sjkim    if ((OpInfo->Class == AML_CLASS_EXECUTE) &&
570218585Sjkim        (OpInfo->Flags & AML_HAS_RETVAL) &&
571218585Sjkim        (!AnIsResultUsed (Op)))
572218585Sjkim    {
573218585Sjkim        if (OpInfo->Flags & AML_HAS_TARGET)
574218585Sjkim        {
575218585Sjkim            /*
576306536Sjkim             * Find the target node, it is always the last child. If the target
577218585Sjkim             * is not specified in the ASL, a default node of type Zero was
578218585Sjkim             * created by the parser.
579218585Sjkim             */
580306536Sjkim            ArgOp = Op->Asl.Child;
581306536Sjkim            while (ArgOp->Asl.Next)
582218585Sjkim            {
583306536Sjkim                PrevArgOp = ArgOp;
584306536Sjkim                ArgOp = ArgOp->Asl.Next;
585218585Sjkim            }
586218585Sjkim
587218585Sjkim            /* Divide() is the only weird case, it has two targets */
588218585Sjkim
589218585Sjkim            if (Op->Asl.AmlOpcode == AML_DIVIDE_OP)
590218585Sjkim            {
591306536Sjkim                if ((ArgOp->Asl.ParseOpcode == PARSEOP_ZERO) &&
592306536Sjkim                    (PrevArgOp) &&
593306536Sjkim                    (PrevArgOp->Asl.ParseOpcode == PARSEOP_ZERO))
594218585Sjkim                {
595249112Sjkim                    AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
596218585Sjkim                        Op, Op->Asl.ExternalName);
597218585Sjkim                }
598218585Sjkim            }
599306536Sjkim
600306536Sjkim            else if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO)
601218585Sjkim            {
602249112Sjkim                AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
603218585Sjkim                    Op, Op->Asl.ExternalName);
604218585Sjkim            }
605218585Sjkim        }
606218585Sjkim        else
607218585Sjkim        {
608218585Sjkim            /*
609218585Sjkim             * Has no target and the result is not used. Only a couple opcodes
610218585Sjkim             * can have this combination.
611218585Sjkim             */
612218585Sjkim            switch (Op->Asl.ParseOpcode)
613218585Sjkim            {
614218585Sjkim            case PARSEOP_ACQUIRE:
615218585Sjkim            case PARSEOP_WAIT:
616218585Sjkim            case PARSEOP_LOADTABLE:
617250838Sjkim
618218585Sjkim                break;
619218585Sjkim
620218585Sjkim            default:
621250838Sjkim
622249112Sjkim                AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
623218585Sjkim                    Op, Op->Asl.ExternalName);
624218585Sjkim                break;
625218585Sjkim            }
626218585Sjkim        }
627218585Sjkim    }
628218585Sjkim
629218585Sjkim
630218585Sjkim    /*
631218585Sjkim     * Semantic checks for individual ASL operators
632218585Sjkim     */
633218585Sjkim    switch (Op->Asl.ParseOpcode)
634218585Sjkim    {
635306536Sjkim    case PARSEOP_STORE:
636306536Sjkim
637306536Sjkim        if (Gbl_DoTypechecking)
638306536Sjkim        {
639306536Sjkim            AnAnalyzeStoreOperator (Op);
640306536Sjkim        }
641306536Sjkim        break;
642306536Sjkim
643306536Sjkim
644218585Sjkim    case PARSEOP_ACQUIRE:
645218585Sjkim    case PARSEOP_WAIT:
646218585Sjkim        /*
647218585Sjkim         * Emit a warning if the timeout parameter for these operators is not
648218585Sjkim         * ACPI_WAIT_FOREVER, and the result value from the operator is not
649218585Sjkim         * checked, meaning that a timeout could happen, but the code
650218585Sjkim         * would not know about it.
651218585Sjkim         */
652218585Sjkim
653218585Sjkim        /* First child is the namepath, 2nd child is timeout */
654218585Sjkim
655306536Sjkim        ArgOp = Op->Asl.Child;
656306536Sjkim        ArgOp = ArgOp->Asl.Next;
657218585Sjkim
658218585Sjkim        /*
659218585Sjkim         * Check for the WAIT_FOREVER case - defined by the ACPI spec to be
660218585Sjkim         * 0xFFFF or greater
661218585Sjkim         */
662306536Sjkim        if (((ArgOp->Asl.ParseOpcode == PARSEOP_WORDCONST) ||
663306536Sjkim             (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER))  &&
664306536Sjkim             (ArgOp->Asl.Value.Integer >= (UINT64) ACPI_WAIT_FOREVER))
665218585Sjkim        {
666218585Sjkim            break;
667218585Sjkim        }
668218585Sjkim
669218585Sjkim        /*
670218585Sjkim         * The operation could timeout. If the return value is not used
671218585Sjkim         * (indicates timeout occurred), issue a warning
672218585Sjkim         */
673218585Sjkim        if (!AnIsResultUsed (Op))
674218585Sjkim        {
675306536Sjkim            AslError (ASL_WARNING, ASL_MSG_TIMEOUT, ArgOp,
676218585Sjkim                Op->Asl.ExternalName);
677218585Sjkim        }
678218585Sjkim        break;
679218585Sjkim
680218585Sjkim    case PARSEOP_CREATEFIELD:
681218585Sjkim        /*
682218585Sjkim         * Check for a zero Length (NumBits) operand. NumBits is the 3rd operand
683218585Sjkim         */
684306536Sjkim        ArgOp = Op->Asl.Child;
685306536Sjkim        ArgOp = ArgOp->Asl.Next;
686306536Sjkim        ArgOp = ArgOp->Asl.Next;
687218585Sjkim
688306536Sjkim        if ((ArgOp->Asl.ParseOpcode == PARSEOP_ZERO) ||
689306536Sjkim           ((ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER) &&
690306536Sjkim            (ArgOp->Asl.Value.Integer == 0)))
691218585Sjkim        {
692306536Sjkim            AslError (ASL_ERROR, ASL_MSG_NON_ZERO, ArgOp, NULL);
693218585Sjkim        }
694218585Sjkim        break;
695218585Sjkim
696228110Sjkim    case PARSEOP_CONNECTION:
697228110Sjkim        /*
698228110Sjkim         * Ensure that the referenced operation region has the correct SPACE_ID.
699228110Sjkim         * From the grammar/parser, we know the parent is a FIELD definition.
700228110Sjkim         */
701306536Sjkim        ArgOp = Op->Asl.Parent;     /* Field definition */
702306536Sjkim        ArgOp = ArgOp->Asl.Child;   /* First child is the OpRegion Name */
703306536Sjkim        Node = ArgOp->Asl.Node;     /* OpRegion namespace node */
704281075Sdim        if (!Node)
705281075Sdim        {
706281075Sdim            break;
707281075Sdim        }
708228110Sjkim
709306536Sjkim        ArgOp = Node->Op;           /* OpRegion definition */
710306536Sjkim        ArgOp = ArgOp->Asl.Child;   /* First child is the OpRegion Name */
711306536Sjkim        ArgOp = ArgOp->Asl.Next;    /* Next peer is the SPACE_ID (what we want) */
712228110Sjkim
713228110Sjkim        /*
714228110Sjkim         * The Connection() operator is only valid for the following operation
715228110Sjkim         * region SpaceIds: GeneralPurposeIo and GenericSerialBus.
716228110Sjkim         */
717306536Sjkim        if ((ArgOp->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) &&
718306536Sjkim            (ArgOp->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS))
719228110Sjkim        {
720228110Sjkim            AslError (ASL_ERROR, ASL_MSG_CONNECTION_INVALID, Op, NULL);
721228110Sjkim        }
722228110Sjkim        break;
723228110Sjkim
724228110Sjkim    case PARSEOP_FIELD:
725228110Sjkim        /*
726228110Sjkim         * Ensure that fields for GeneralPurposeIo and GenericSerialBus
727228110Sjkim         * contain at least one Connection() operator
728228110Sjkim         */
729306536Sjkim        ArgOp = Op->Asl.Child;      /* 1st child is the OpRegion Name */
730306536Sjkim        Node = ArgOp->Asl.Node;     /* OpRegion namespace node */
731228110Sjkim        if (!Node)
732228110Sjkim        {
733228110Sjkim            break;
734228110Sjkim        }
735228110Sjkim
736306536Sjkim        ArgOp = Node->Op;           /* OpRegion definition */
737306536Sjkim        ArgOp = ArgOp->Asl.Child;   /* First child is the OpRegion Name */
738306536Sjkim        ArgOp = ArgOp->Asl.Next;    /* Next peer is the SPACE_ID (what we want) */
739228110Sjkim
740228110Sjkim        /* We are only interested in GeneralPurposeIo and GenericSerialBus */
741228110Sjkim
742306536Sjkim        if ((ArgOp->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) &&
743306536Sjkim            (ArgOp->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS))
744228110Sjkim        {
745228110Sjkim            break;
746228110Sjkim        }
747228110Sjkim
748306536Sjkim        ArgOp = Op->Asl.Child;      /* 1st child is the OpRegion Name */
749306536Sjkim        ArgOp = ArgOp->Asl.Next;    /* AccessType */
750306536Sjkim        ArgOp = ArgOp->Asl.Next;    /* LockRule */
751306536Sjkim        ArgOp = ArgOp->Asl.Next;    /* UpdateRule */
752306536Sjkim        ArgOp = ArgOp->Asl.Next;    /* Start of FieldUnitList */
753228110Sjkim
754228110Sjkim        /* Walk the FieldUnitList */
755228110Sjkim
756306536Sjkim        while (ArgOp)
757228110Sjkim        {
758306536Sjkim            if (ArgOp->Asl.ParseOpcode == PARSEOP_CONNECTION)
759228110Sjkim            {
760228110Sjkim                break;
761228110Sjkim            }
762306536Sjkim            else if (ArgOp->Asl.ParseOpcode == PARSEOP_NAMESEG)
763228110Sjkim            {
764306536Sjkim                AslError (ASL_ERROR, ASL_MSG_CONNECTION_MISSING, ArgOp, NULL);
765228110Sjkim                break;
766228110Sjkim            }
767228110Sjkim
768306536Sjkim            ArgOp = ArgOp->Asl.Next;
769228110Sjkim        }
770228110Sjkim        break;
771228110Sjkim
772218585Sjkim    default:
773250838Sjkim
774218585Sjkim        break;
775218585Sjkim    }
776218585Sjkim
777218585Sjkim    return (AE_OK);
778218585Sjkim}
779306536Sjkim
780306536Sjkim
781306536Sjkim/*******************************************************************************
782306536Sjkim *
783306536Sjkim * FUNCTION:    AnAnalyzeStoreOperator
784306536Sjkim *
785306536Sjkim * PARAMETERS:  Op                  - Store() operator
786306536Sjkim *
787306536Sjkim * RETURN:      None
788306536Sjkim *
789306536Sjkim * DESCRIPTION: Analyze a store operator. Mostly for stores to/from package
790306536Sjkim *              objects where there are more restrictions than other data
791306536Sjkim *              types.
792306536Sjkim *
793306536Sjkim ******************************************************************************/
794306536Sjkim
795306536Sjkimstatic void
796306536SjkimAnAnalyzeStoreOperator (
797306536Sjkim    ACPI_PARSE_OBJECT       *Op)
798306536Sjkim{
799306536Sjkim    ACPI_NAMESPACE_NODE     *SourceNode;
800306536Sjkim    ACPI_NAMESPACE_NODE     *TargetNode;
801306536Sjkim    ACPI_PARSE_OBJECT       *SourceOperandOp;
802306536Sjkim    ACPI_PARSE_OBJECT       *TargetOperandOp;
803306536Sjkim    UINT32                  SourceOperandBtype;
804306536Sjkim    UINT32                  TargetOperandBtype;
805306536Sjkim
806306536Sjkim
807306536Sjkim    /* Extract the two operands for STORE */
808306536Sjkim
809306536Sjkim    SourceOperandOp = Op->Asl.Child;
810306536Sjkim    TargetOperandOp = SourceOperandOp->Asl.Next;
811306536Sjkim
812306536Sjkim    /*
813306536Sjkim     * Ignore these Source operand opcodes, they cannot be typechecked,
814306536Sjkim     * the actual result is unknown here.
815306536Sjkim     */
816306536Sjkim    switch (SourceOperandOp->Asl.ParseOpcode)
817306536Sjkim    {
818306536Sjkim    /* For these, type of the returned value is unknown at compile time */
819306536Sjkim
820306536Sjkim    case PARSEOP_DEREFOF:
821306536Sjkim    case PARSEOP_METHODCALL:
822306536Sjkim    case PARSEOP_STORE:
823306536Sjkim    case PARSEOP_COPYOBJECT:
824306536Sjkim
825306536Sjkim        return;
826306536Sjkim
827306536Sjkim    case PARSEOP_INDEX:
828306536Sjkim    case PARSEOP_REFOF:
829306536Sjkim
830306536Sjkim        if (!Gbl_EnableReferenceTypechecking)
831306536Sjkim        {
832306536Sjkim            return;
833306536Sjkim        }
834306536Sjkim
835306536Sjkim        /*
836306536Sjkim         * These opcodes always return an object reference, and thus
837306536Sjkim         * the result can only be stored to a Local, Arg, or Debug.
838306536Sjkim         */
839306536Sjkim        if (TargetOperandOp->Asl.AmlOpcode == AML_DEBUG_OP)
840306536Sjkim        {
841306536Sjkim            return;
842306536Sjkim        }
843306536Sjkim
844306536Sjkim        if ((TargetOperandOp->Asl.AmlOpcode < AML_LOCAL0) ||
845306536Sjkim            (TargetOperandOp->Asl.AmlOpcode > AML_ARG6))
846306536Sjkim        {
847306536Sjkim            AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, TargetOperandOp,
848306536Sjkim                "Source [Reference], Target must be [Local/Arg/Debug]");
849306536Sjkim        }
850306536Sjkim        return;
851306536Sjkim
852306536Sjkim    default:
853306536Sjkim        break;
854306536Sjkim    }
855306536Sjkim
856306536Sjkim    /*
857306536Sjkim     * Ignore these Target operand opcodes, they cannot be typechecked
858306536Sjkim     */
859306536Sjkim    switch (TargetOperandOp->Asl.ParseOpcode)
860306536Sjkim    {
861306536Sjkim    case PARSEOP_DEBUG:
862306536Sjkim    case PARSEOP_DEREFOF:
863306536Sjkim    case PARSEOP_REFOF:
864306536Sjkim    case PARSEOP_INDEX:
865306536Sjkim
866306536Sjkim        return;
867306536Sjkim
868306536Sjkim    case PARSEOP_METHODCALL:
869306536Sjkim        /*
870306536Sjkim         * A target is not allowed to be a method call.
871306536Sjkim         * It is not supported by the ACPICA interpreter, nor is it
872306536Sjkim         * supported by the MS ASL compiler or the MS interpreter.
873306536Sjkim         * Although legal syntax up until ACPI 6.1, support for this
874306536Sjkim         * will be removed for ACPI 6.2 (02/2016)
875306536Sjkim         */
876306536Sjkim        AslError (ASL_ERROR, ASL_MSG_SYNTAX,
877306536Sjkim            TargetOperandOp, "Illegal method invocation as a target operand");
878306536Sjkim        return;
879306536Sjkim
880306536Sjkim    default:
881306536Sjkim        break;
882306536Sjkim    }
883306536Sjkim
884306536Sjkim    /*
885306536Sjkim     * Ignore typecheck for External() operands of type "UnknownObj",
886306536Sjkim     * we don't know the actual type (source or target).
887306536Sjkim     */
888306536Sjkim    SourceNode = SourceOperandOp->Asl.Node;
889306536Sjkim    if (SourceNode &&
890306536Sjkim        (SourceNode->Flags & ANOBJ_IS_EXTERNAL) &&
891306536Sjkim        (SourceNode->Type == ACPI_TYPE_ANY))
892306536Sjkim    {
893306536Sjkim        return;
894306536Sjkim    }
895306536Sjkim
896306536Sjkim    TargetNode = TargetOperandOp->Asl.Node;
897306536Sjkim    if (TargetNode &&
898306536Sjkim        (TargetNode->Flags & ANOBJ_IS_EXTERNAL) &&
899306536Sjkim        (TargetNode->Type == ACPI_TYPE_ANY))
900306536Sjkim    {
901306536Sjkim        return;
902306536Sjkim    }
903306536Sjkim
904306536Sjkim    /*
905306536Sjkim     * A NULL node with a namepath AML opcode indicates non-existent
906306536Sjkim     * name. Just return, the error message is generated elsewhere.
907306536Sjkim     */
908306536Sjkim    if ((!SourceNode && (SourceOperandOp->Asl.AmlOpcode == AML_INT_NAMEPATH_OP)) ||
909306536Sjkim        (!TargetNode && (TargetOperandOp->Asl.AmlOpcode == AML_INT_NAMEPATH_OP)))
910306536Sjkim    {
911306536Sjkim        return;
912306536Sjkim    }
913306536Sjkim
914306536Sjkim    /*
915306536Sjkim     * Simple check for source same as target via NS node.
916306536Sjkim     * -- Could be expanded to locals and args.
917306536Sjkim     */
918306536Sjkim    if (SourceNode && TargetNode)
919306536Sjkim    {
920306536Sjkim        if (SourceNode == TargetNode)
921306536Sjkim        {
922306536Sjkim            AslError (ASL_WARNING, ASL_MSG_DUPLICATE_ITEM,
923306536Sjkim                TargetOperandOp, "Source is the same as Target");
924306536Sjkim            return;
925306536Sjkim        }
926306536Sjkim    }
927306536Sjkim
928306536Sjkim    /* Ignore typecheck if either source or target is a local or arg */
929306536Sjkim
930306536Sjkim    if ((SourceOperandOp->Asl.AmlOpcode >= AML_LOCAL0) &&
931306536Sjkim        (SourceOperandOp->Asl.AmlOpcode <= AML_ARG6))
932306536Sjkim    {
933306536Sjkim        return; /* Cannot type a local/arg at compile time */
934306536Sjkim    }
935306536Sjkim
936306536Sjkim    if ((TargetOperandOp->Asl.AmlOpcode >= AML_LOCAL0) &&
937306536Sjkim        (TargetOperandOp->Asl.AmlOpcode <= AML_ARG6))
938306536Sjkim    {
939306536Sjkim        return; /* Cannot type a local/arg at compile time */
940306536Sjkim    }
941306536Sjkim
942306536Sjkim    /*
943306536Sjkim     * Package objects are a special case because they cannot by implicitly
944306536Sjkim     * converted to/from anything. Check for these two illegal cases:
945306536Sjkim     *
946306536Sjkim     *      Store (non-package, package)
947306536Sjkim     *      Store (package, non-package)
948306536Sjkim     */
949306536Sjkim    SourceOperandBtype = AnGetBtype (SourceOperandOp);
950306536Sjkim    TargetOperandBtype = AnGetBtype (TargetOperandOp);
951306536Sjkim
952306536Sjkim    /* Check source first for (package, non-package) case */
953306536Sjkim
954306536Sjkim    if (SourceOperandBtype & ACPI_BTYPE_PACKAGE)
955306536Sjkim    {
956306536Sjkim        /* If Source is PACKAGE-->Target must be PACKAGE */
957306536Sjkim
958306536Sjkim        if (!(TargetOperandBtype & ACPI_BTYPE_PACKAGE))
959306536Sjkim        {
960306536Sjkim            AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, TargetOperandOp,
961306536Sjkim                "Source is [Package], Target must be a package also");
962306536Sjkim        }
963306536Sjkim    }
964306536Sjkim
965306536Sjkim    /* Else check target for (non-package, package) case */
966306536Sjkim
967306536Sjkim    else if (TargetOperandBtype & ACPI_BTYPE_PACKAGE)
968306536Sjkim    {
969306536Sjkim        /* If Target is PACKAGE, Source must be PACKAGE */
970306536Sjkim
971306536Sjkim        if (!(SourceOperandBtype & ACPI_BTYPE_PACKAGE))
972306536Sjkim        {
973306536Sjkim            AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, SourceOperandOp,
974306536Sjkim                "Target is [Package], Source must be a package also");
975306536Sjkim        }
976306536Sjkim    }
977306536Sjkim}
978