1 /******************************************************************************
3 * Module Name: aslwalks.c - Miscellaneous analytical parse tree walks
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2013, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
45 #include "aslcompiler.h"
46 #include "aslcompiler.y.h"
51 #define _COMPONENT ACPI_COMPILER
52 ACPI_MODULE_NAME ("aslwalks")
55 /*******************************************************************************
57 * FUNCTION: AnMethodTypingWalkEnd
59 * PARAMETERS: ASL_WALK_CALLBACK
63 * DESCRIPTION: Ascending callback for typing walk. Complete the method
64 * return analysis. Check methods for:
65 * 1) Initialized local variables
69 ******************************************************************************/
72 AnMethodTypingWalkEnd (
73 ACPI_PARSE_OBJECT
*Op
,
80 switch (Op
->Asl
.ParseOpcode
)
84 Op
->Asl
.CompileFlags
|= NODE_METHOD_TYPED
;
89 if ((Op
->Asl
.Child
) &&
90 (Op
->Asl
.Child
->Asl
.ParseOpcode
!= PARSEOP_DEFAULT_ARG
))
92 ThisNodeBtype
= AnGetBtype (Op
->Asl
.Child
);
94 if ((Op
->Asl
.Child
->Asl
.ParseOpcode
== PARSEOP_METHODCALL
) &&
95 (ThisNodeBtype
== (ACPI_UINT32_MAX
-1)))
98 * The called method is untyped at this time (typically a
101 * Check for a recursive method call first.
103 if (Op
->Asl
.ParentMethod
!= Op
->Asl
.Child
->Asl
.Node
->Op
)
105 /* We must type the method here */
107 TrWalkParseTree (Op
->Asl
.Child
->Asl
.Node
->Op
,
108 ASL_WALK_VISIT_UPWARD
, NULL
,
109 AnMethodTypingWalkEnd
, NULL
);
111 ThisNodeBtype
= AnGetBtype (Op
->Asl
.Child
);
115 /* Returns a value, save the value type */
117 if (Op
->Asl
.ParentMethod
)
119 Op
->Asl
.ParentMethod
->Asl
.AcpiBtype
|= ThisNodeBtype
;
133 /*******************************************************************************
135 * FUNCTION: AnOperandTypecheckWalkEnd
137 * PARAMETERS: ASL_WALK_CALLBACK
141 * DESCRIPTION: Ascending callback for analysis walk. Complete method
144 ******************************************************************************/
147 AnOperandTypecheckWalkEnd (
148 ACPI_PARSE_OBJECT
*Op
,
152 const ACPI_OPCODE_INFO
*OpInfo
;
153 UINT32 RuntimeArgTypes
;
154 UINT32 RuntimeArgTypes2
;
155 UINT32 RequiredBtypes
;
156 UINT32 ThisNodeBtype
;
159 ACPI_PARSE_OBJECT
*ArgOp
;
163 switch (Op
->Asl
.AmlOpcode
)
165 case AML_RAW_DATA_BYTE
:
166 case AML_RAW_DATA_WORD
:
167 case AML_RAW_DATA_DWORD
:
168 case AML_RAW_DATA_QWORD
:
169 case AML_RAW_DATA_BUFFER
:
170 case AML_RAW_DATA_CHAIN
:
171 case AML_PACKAGE_LENGTH
:
172 case AML_UNASSIGNED_OPCODE
:
173 case AML_DEFAULT_ARG_OP
:
175 /* Ignore the internal (compiler-only) AML opcodes */
184 OpInfo
= AcpiPsGetOpcodeInfo (Op
->Asl
.AmlOpcode
);
190 ArgOp
= Op
->Asl
.Child
;
191 RuntimeArgTypes
= OpInfo
->RuntimeArgs
;
192 OpcodeClass
= OpInfo
->Class
;
194 #ifdef ASL_ERROR_NAMED_OBJECT_IN_WHILE
196 * Update 11/2008: In practice, we can't perform this check. A simple
197 * analysis is not sufficient. Also, it can cause errors when compiling
198 * disassembled code because of the way Switch operators are implemented
199 * (a While(One) loop with a named temp variable created within.)
203 * If we are creating a named object, check if we are within a while loop
204 * by checking if the parent is a WHILE op. This is a simple analysis, but
205 * probably sufficient for many cases.
207 * Allow Scope(), Buffer(), and Package().
209 if (((OpcodeClass
== AML_CLASS_NAMED_OBJECT
) && (Op
->Asl
.AmlOpcode
!= AML_SCOPE_OP
)) ||
210 ((OpcodeClass
== AML_CLASS_CREATE
) && (OpInfo
->Flags
& AML_NSNODE
)))
212 if (Op
->Asl
.Parent
->Asl
.AmlOpcode
== AML_WHILE_OP
)
214 AslError (ASL_ERROR
, ASL_MSG_NAMED_OBJECT_IN_WHILE
, Op
, NULL
);
220 * Special case for control opcodes IF/RETURN/WHILE since they
221 * have no runtime arg list (at this time)
223 switch (Op
->Asl
.AmlOpcode
)
229 if (ArgOp
->Asl
.ParseOpcode
== PARSEOP_METHODCALL
)
231 /* Check for an internal method */
233 if (AnIsInternalMethod (ArgOp
))
238 /* The lone arg is a method call, check it */
240 RequiredBtypes
= AnMapArgTypeToBtype (ARGI_INTEGER
);
241 if (Op
->Asl
.AmlOpcode
== AML_RETURN_OP
)
243 RequiredBtypes
= 0xFFFFFFFF;
246 ThisNodeBtype
= AnGetBtype (ArgOp
);
247 if (ThisNodeBtype
== ACPI_UINT32_MAX
)
251 AnCheckMethodReturnValue (Op
, OpInfo
, ArgOp
,
252 RequiredBtypes
, ThisNodeBtype
);
261 /* Ignore the non-executable opcodes */
263 if (RuntimeArgTypes
== ARGI_INVALID_OPCODE
)
270 case AML_CLASS_EXECUTE
:
271 case AML_CLASS_CREATE
:
272 case AML_CLASS_CONTROL
:
273 case AML_CLASS_RETURN_VALUE
:
275 /* TBD: Change class or fix typechecking for these */
277 if ((Op
->Asl
.AmlOpcode
== AML_BUFFER_OP
) ||
278 (Op
->Asl
.AmlOpcode
== AML_PACKAGE_OP
) ||
279 (Op
->Asl
.AmlOpcode
== AML_VAR_PACKAGE_OP
))
284 /* Reverse the runtime argument list */
286 RuntimeArgTypes2
= 0;
287 while ((ArgType
= GET_CURRENT_ARG_TYPE (RuntimeArgTypes
)))
289 RuntimeArgTypes2
<<= ARG_TYPE_WIDTH
;
290 RuntimeArgTypes2
|= ArgType
;
291 INCREMENT_ARG_LIST (RuntimeArgTypes
);
294 while ((ArgType
= GET_CURRENT_ARG_TYPE (RuntimeArgTypes2
)))
296 RequiredBtypes
= AnMapArgTypeToBtype (ArgType
);
298 ThisNodeBtype
= AnGetBtype (ArgOp
);
299 if (ThisNodeBtype
== ACPI_UINT32_MAX
)
304 /* Examine the arg based on the required type of the arg */
310 if (ArgOp
->Asl
.ParseOpcode
== PARSEOP_ZERO
)
312 /* ZERO is the placeholder for "don't store result" */
314 ThisNodeBtype
= RequiredBtypes
;
318 if (ArgOp
->Asl
.ParseOpcode
== PARSEOP_INTEGER
)
321 * This is the case where an original reference to a resource
322 * descriptor field has been replaced by an (Integer) offset.
323 * These named fields are supported at compile-time only;
324 * the names are not passed to the interpreter (via the AML).
326 if ((ArgOp
->Asl
.Node
->Type
== ACPI_TYPE_LOCAL_RESOURCE_FIELD
) ||
327 (ArgOp
->Asl
.Node
->Type
== ACPI_TYPE_LOCAL_RESOURCE
))
329 AslError (ASL_ERROR
, ASL_MSG_RESOURCE_FIELD
, ArgOp
, NULL
);
333 AslError (ASL_ERROR
, ASL_MSG_INVALID_TYPE
, ArgOp
, NULL
);
338 if ((ArgOp
->Asl
.ParseOpcode
== PARSEOP_METHODCALL
) ||
339 (ArgOp
->Asl
.ParseOpcode
== PARSEOP_DEREFOF
))
344 ThisNodeBtype
= RequiredBtypes
;
348 case ARGI_REFERENCE
: /* References */
349 case ARGI_INTEGER_REF
:
350 case ARGI_OBJECT_REF
:
351 case ARGI_DEVICE_REF
:
353 switch (ArgOp
->Asl
.ParseOpcode
)
364 /* TBD: implement analysis of current value (type) of the local */
365 /* For now, just treat any local as a typematch */
367 /*ThisNodeBtype = RequiredBtypes;*/
378 /* Hard to analyze argument types, sow we won't */
379 /* For now, just treat any arg as a typematch */
381 /* ThisNodeBtype = RequiredBtypes; */
404 CommonBtypes
= ThisNodeBtype
& RequiredBtypes
;
406 if (ArgOp
->Asl
.ParseOpcode
== PARSEOP_METHODCALL
)
408 if (AnIsInternalMethod (ArgOp
))
413 /* Check a method call for a valid return value */
415 AnCheckMethodReturnValue (Op
, OpInfo
, ArgOp
,
416 RequiredBtypes
, ThisNodeBtype
);
420 * Now check if the actual type(s) match at least one
421 * bit to the required type
423 else if (!CommonBtypes
)
425 /* No match -- this is a type mismatch error */
427 AnFormatBtype (StringBuffer
, ThisNodeBtype
);
428 AnFormatBtype (StringBuffer2
, RequiredBtypes
);
430 sprintf (MsgBuffer
, "[%s] found, %s operator requires [%s]",
431 StringBuffer
, OpInfo
->Name
, StringBuffer2
);
433 AslError (ASL_ERROR
, ASL_MSG_INVALID_TYPE
, ArgOp
, MsgBuffer
);
437 ArgOp
= ArgOp
->Asl
.Next
;
438 INCREMENT_ARG_LIST (RuntimeArgTypes2
);
451 /*******************************************************************************
453 * FUNCTION: AnOtherSemanticAnalysisWalkBegin
455 * PARAMETERS: ASL_WALK_CALLBACK
459 * DESCRIPTION: Descending callback for the analysis walk. Checks for
460 * miscellaneous issues in the code.
462 ******************************************************************************/
465 AnOtherSemanticAnalysisWalkBegin (
466 ACPI_PARSE_OBJECT
*Op
,
470 ACPI_PARSE_OBJECT
*ArgNode
;
471 ACPI_PARSE_OBJECT
*PrevArgNode
= NULL
;
472 const ACPI_OPCODE_INFO
*OpInfo
;
473 ACPI_NAMESPACE_NODE
*Node
;
476 OpInfo
= AcpiPsGetOpcodeInfo (Op
->Asl
.AmlOpcode
);
479 * Determine if an execution class operator actually does something by
480 * checking if it has a target and/or the function return value is used.
481 * (Target is optional, so a standalone statement can actually do nothing.)
483 if ((OpInfo
->Class
== AML_CLASS_EXECUTE
) &&
484 (OpInfo
->Flags
& AML_HAS_RETVAL
) &&
485 (!AnIsResultUsed (Op
)))
487 if (OpInfo
->Flags
& AML_HAS_TARGET
)
490 * Find the target node, it is always the last child. If the traget
491 * is not specified in the ASL, a default node of type Zero was
492 * created by the parser.
494 ArgNode
= Op
->Asl
.Child
;
495 while (ArgNode
->Asl
.Next
)
497 PrevArgNode
= ArgNode
;
498 ArgNode
= ArgNode
->Asl
.Next
;
501 /* Divide() is the only weird case, it has two targets */
503 if (Op
->Asl
.AmlOpcode
== AML_DIVIDE_OP
)
505 if ((ArgNode
->Asl
.ParseOpcode
== PARSEOP_ZERO
) &&
507 (PrevArgNode
->Asl
.ParseOpcode
== PARSEOP_ZERO
))
509 AslError (ASL_ERROR
, ASL_MSG_RESULT_NOT_USED
,
510 Op
, Op
->Asl
.ExternalName
);
513 else if (ArgNode
->Asl
.ParseOpcode
== PARSEOP_ZERO
)
515 AslError (ASL_ERROR
, ASL_MSG_RESULT_NOT_USED
,
516 Op
, Op
->Asl
.ExternalName
);
522 * Has no target and the result is not used. Only a couple opcodes
523 * can have this combination.
525 switch (Op
->Asl
.ParseOpcode
)
527 case PARSEOP_ACQUIRE
:
529 case PARSEOP_LOADTABLE
:
535 AslError (ASL_ERROR
, ASL_MSG_RESULT_NOT_USED
,
536 Op
, Op
->Asl
.ExternalName
);
544 * Semantic checks for individual ASL operators
546 switch (Op
->Asl
.ParseOpcode
)
548 case PARSEOP_ACQUIRE
:
551 * Emit a warning if the timeout parameter for these operators is not
552 * ACPI_WAIT_FOREVER, and the result value from the operator is not
553 * checked, meaning that a timeout could happen, but the code
554 * would not know about it.
557 /* First child is the namepath, 2nd child is timeout */
559 ArgNode
= Op
->Asl
.Child
;
560 ArgNode
= ArgNode
->Asl
.Next
;
563 * Check for the WAIT_FOREVER case - defined by the ACPI spec to be
566 if (((ArgNode
->Asl
.ParseOpcode
== PARSEOP_WORDCONST
) ||
567 (ArgNode
->Asl
.ParseOpcode
== PARSEOP_INTEGER
)) &&
568 (ArgNode
->Asl
.Value
.Integer
>= (UINT64
) ACPI_WAIT_FOREVER
))
574 * The operation could timeout. If the return value is not used
575 * (indicates timeout occurred), issue a warning
577 if (!AnIsResultUsed (Op
))
579 AslError (ASL_WARNING
, ASL_MSG_TIMEOUT
, ArgNode
,
580 Op
->Asl
.ExternalName
);
584 case PARSEOP_CREATEFIELD
:
586 * Check for a zero Length (NumBits) operand. NumBits is the 3rd operand
588 ArgNode
= Op
->Asl
.Child
;
589 ArgNode
= ArgNode
->Asl
.Next
;
590 ArgNode
= ArgNode
->Asl
.Next
;
592 if ((ArgNode
->Asl
.ParseOpcode
== PARSEOP_ZERO
) ||
593 ((ArgNode
->Asl
.ParseOpcode
== PARSEOP_INTEGER
) &&
594 (ArgNode
->Asl
.Value
.Integer
== 0)))
596 AslError (ASL_ERROR
, ASL_MSG_NON_ZERO
, ArgNode
, NULL
);
600 case PARSEOP_CONNECTION
:
602 * Ensure that the referenced operation region has the correct SPACE_ID.
603 * From the grammar/parser, we know the parent is a FIELD definition.
605 ArgNode
= Op
->Asl
.Parent
; /* Field definition */
606 ArgNode
= ArgNode
->Asl
.Child
; /* First child is the OpRegion Name */
607 Node
= ArgNode
->Asl
.Node
; /* OpRegion namespace node */
609 ArgNode
= Node
->Op
; /* OpRegion definition */
610 ArgNode
= ArgNode
->Asl
.Child
; /* First child is the OpRegion Name */
611 ArgNode
= ArgNode
->Asl
.Next
; /* Next peer is the SPACE_ID (what we want) */
614 * The Connection() operator is only valid for the following operation
615 * region SpaceIds: GeneralPurposeIo and GenericSerialBus.
617 if ((ArgNode
->Asl
.Value
.Integer
!= ACPI_ADR_SPACE_GPIO
) &&
618 (ArgNode
->Asl
.Value
.Integer
!= ACPI_ADR_SPACE_GSBUS
))
620 AslError (ASL_ERROR
, ASL_MSG_CONNECTION_INVALID
, Op
, NULL
);
626 * Ensure that fields for GeneralPurposeIo and GenericSerialBus
627 * contain at least one Connection() operator
629 ArgNode
= Op
->Asl
.Child
; /* 1st child is the OpRegion Name */
630 Node
= ArgNode
->Asl
.Node
; /* OpRegion namespace node */
636 ArgNode
= Node
->Op
; /* OpRegion definition */
637 ArgNode
= ArgNode
->Asl
.Child
; /* First child is the OpRegion Name */
638 ArgNode
= ArgNode
->Asl
.Next
; /* Next peer is the SPACE_ID (what we want) */
640 /* We are only interested in GeneralPurposeIo and GenericSerialBus */
642 if ((ArgNode
->Asl
.Value
.Integer
!= ACPI_ADR_SPACE_GPIO
) &&
643 (ArgNode
->Asl
.Value
.Integer
!= ACPI_ADR_SPACE_GSBUS
))
648 ArgNode
= Op
->Asl
.Child
; /* 1st child is the OpRegion Name */
649 ArgNode
= ArgNode
->Asl
.Next
; /* AccessType */
650 ArgNode
= ArgNode
->Asl
.Next
; /* LockRule */
651 ArgNode
= ArgNode
->Asl
.Next
; /* UpdateRule */
652 ArgNode
= ArgNode
->Asl
.Next
; /* Start of FieldUnitList */
654 /* Walk the FieldUnitList */
658 if (ArgNode
->Asl
.ParseOpcode
== PARSEOP_CONNECTION
)
662 else if (ArgNode
->Asl
.ParseOpcode
== PARSEOP_NAMESEG
)
664 AslError (ASL_ERROR
, ASL_MSG_CONNECTION_MISSING
, ArgNode
, NULL
);
668 ArgNode
= ArgNode
->Asl
.Next
;