Import acpica-unix-20061109 from Intel.
[dragonfly.git] / sys / contrib / dev / acpica-unix-20061109 / compiler / aslanalyze.c
blob9b3362406107a47256c51ebda49463131033d128
2 /******************************************************************************
4 * Module Name: aslanalyze.c - check for semantic errors
5 * $Revision: 1.114 $
7 *****************************************************************************/
9 /******************************************************************************
11 * 1. Copyright Notice
13 * Some or all of this work - Copyright (c) 1999 - 2006, Intel Corp.
14 * All rights reserved.
16 * 2. License
18 * 2.1. This is your license from Intel Corp. under its intellectual property
19 * rights. You may have additional license terms from the party that provided
20 * you this software, covering your right to use that party's intellectual
21 * property rights.
23 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
24 * copy of the source code appearing in this file ("Covered Code") an
25 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
26 * base code distributed originally by Intel ("Original Intel Code") to copy,
27 * make derivatives, distribute, use and display any portion of the Covered
28 * Code in any form, with the right to sublicense such rights; and
30 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
31 * license (with the right to sublicense), under only those claims of Intel
32 * patents that are infringed by the Original Intel Code, to make, use, sell,
33 * offer to sell, and import the Covered Code and derivative works thereof
34 * solely to the minimum extent necessary to exercise the above copyright
35 * license, and in no event shall the patent license extend to any additions
36 * to or modifications of the Original Intel Code. No other license or right
37 * is granted directly or by implication, estoppel or otherwise;
39 * The above copyright and patent license is granted only if the following
40 * conditions are met:
42 * 3. Conditions
44 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
45 * Redistribution of source code of any substantial portion of the Covered
46 * Code or modification with rights to further distribute source must include
47 * the above Copyright Notice, the above License, this list of Conditions,
48 * and the following Disclaimer and Export Compliance provision. In addition,
49 * Licensee must cause all Covered Code to which Licensee contributes to
50 * contain a file documenting the changes Licensee made to create that Covered
51 * Code and the date of any change. Licensee must include in that file the
52 * documentation of any changes made by any predecessor Licensee. Licensee
53 * must include a prominent statement that the modification is derived,
54 * directly or indirectly, from Original Intel Code.
56 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
57 * Redistribution of source code of any substantial portion of the Covered
58 * Code or modification without rights to further distribute source must
59 * include the following Disclaimer and Export Compliance provision in the
60 * documentation and/or other materials provided with distribution. In
61 * addition, Licensee may not authorize further sublicense of source of any
62 * portion of the Covered Code, and must include terms to the effect that the
63 * license from Licensee to its licensee is limited to the intellectual
64 * property embodied in the software Licensee provides to its licensee, and
65 * not to intellectual property embodied in modifications its licensee may
66 * make.
68 * 3.3. Redistribution of Executable. Redistribution in executable form of any
69 * substantial portion of the Covered Code or modification must reproduce the
70 * above Copyright Notice, and the following Disclaimer and Export Compliance
71 * provision in the documentation and/or other materials provided with the
72 * distribution.
74 * 3.4. Intel retains all right, title, and interest in and to the Original
75 * Intel Code.
77 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
78 * Intel shall be used in advertising or otherwise to promote the sale, use or
79 * other dealings in products derived from or relating to the Covered Code
80 * without prior written authorization from Intel.
82 * 4. Disclaimer and Export Compliance
84 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
85 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
86 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
87 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
88 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
89 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
90 * PARTICULAR PURPOSE.
92 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
93 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
94 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
95 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
96 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
97 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
98 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
99 * LIMITED REMEDY.
101 * 4.3. Licensee shall not export, either directly or indirectly, any of this
102 * software or system incorporating such software without first obtaining any
103 * required license or other approval from the U. S. Department of Commerce or
104 * any other agency or department of the United States Government. In the
105 * event Licensee exports any such software from the United States or
106 * re-exports any such software from a foreign destination, Licensee shall
107 * ensure that the distribution and export/re-export of the software is in
108 * compliance with all laws, regulations, orders, or other restrictions of the
109 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
110 * any of its subsidiaries will export/re-export any technical data, process,
111 * software, or service, directly or indirectly, to any country for which the
112 * United States government or any agency thereof requires an export license,
113 * other governmental approval, or letter of assurance, without first obtaining
114 * such license, approval or letter.
116 *****************************************************************************/
119 #include "aslcompiler.h"
120 #include "aslcompiler.y.h"
121 #include "acparser.h"
122 #include "amlcode.h"
124 #include <ctype.h>
126 #define _COMPONENT ACPI_COMPILER
127 ACPI_MODULE_NAME ("aslanalyze")
129 /* Local prototypes */
131 static UINT32
132 AnMapArgTypeToBtype (
133 UINT32 ArgType);
135 static UINT32
136 AnMapEtypeToBtype (
137 UINT32 Etype);
139 static void
140 AnFormatBtype (
141 char *Buffer,
142 UINT32 Btype);
144 static UINT32
145 AnGetBtype (
146 ACPI_PARSE_OBJECT *Op);
148 static UINT32
149 AnCheckForReservedName (
150 ACPI_PARSE_OBJECT *Op,
151 char *Name);
153 static void
154 AnCheckForReservedMethod (
155 ACPI_PARSE_OBJECT *Op,
156 ASL_METHOD_INFO *MethodInfo);
158 static UINT32
159 AnMapObjTypeToBtype (
160 ACPI_PARSE_OBJECT *Op);
162 static BOOLEAN
163 AnLastStatementIsReturn (
164 ACPI_PARSE_OBJECT *Op);
166 static void
167 AnCheckMethodReturnValue (
168 ACPI_PARSE_OBJECT *Op,
169 const ACPI_OPCODE_INFO *OpInfo,
170 ACPI_PARSE_OBJECT *ArgOp,
171 UINT32 RequiredBtypes,
172 UINT32 ThisNodeBtype);
174 static BOOLEAN
175 AnIsInternalMethod (
176 ACPI_PARSE_OBJECT *Op);
178 static UINT32
179 AnGetInternalMethodReturnType (
180 ACPI_PARSE_OBJECT *Op);
183 /*******************************************************************************
185 * FUNCTION: AnIsInternalMethod
187 * PARAMETERS: Op - Current op
189 * RETURN: Boolean
191 * DESCRIPTION: Check for an internal control method.
193 ******************************************************************************/
195 static BOOLEAN
196 AnIsInternalMethod (
197 ACPI_PARSE_OBJECT *Op)
200 if ((!ACPI_STRCMP (Op->Asl.ExternalName, "\\_OSI")) ||
201 (!ACPI_STRCMP (Op->Asl.ExternalName, "_OSI")))
203 return (TRUE);
206 return (FALSE);
210 /*******************************************************************************
212 * FUNCTION: AnGetInternalMethodReturnType
214 * PARAMETERS: Op - Current op
216 * RETURN: Btype
218 * DESCRIPTION: Get the return type of an internal method
220 ******************************************************************************/
222 static UINT32
223 AnGetInternalMethodReturnType (
224 ACPI_PARSE_OBJECT *Op)
227 if ((!ACPI_STRCMP (Op->Asl.ExternalName, "\\_OSI")) ||
228 (!ACPI_STRCMP (Op->Asl.ExternalName, "_OSI")))
230 return (ACPI_BTYPE_STRING);
233 return (0);
237 /*******************************************************************************
239 * FUNCTION: AnMapArgTypeToBtype
241 * PARAMETERS: ArgType - The ARGI required type(s) for this argument,
242 * from the opcode info table
244 * RETURN: The corresponding Bit-encoded types
246 * DESCRIPTION: Convert an encoded ARGI required argument type code into a
247 * bitfield type code. Implements the implicit source conversion
248 * rules.
250 ******************************************************************************/
252 static UINT32
253 AnMapArgTypeToBtype (
254 UINT32 ArgType)
257 switch (ArgType)
260 /* Simple types */
262 case ARGI_ANYTYPE:
263 return (ACPI_BTYPE_OBJECTS_AND_REFS);
265 case ARGI_PACKAGE:
266 return (ACPI_BTYPE_PACKAGE);
268 case ARGI_EVENT:
269 return (ACPI_BTYPE_EVENT);
271 case ARGI_MUTEX:
272 return (ACPI_BTYPE_MUTEX);
274 case ARGI_DDBHANDLE:
275 return (ACPI_BTYPE_DDB_HANDLE);
277 /* Interchangeable types */
279 * Source conversion rules:
280 * Integer, String, and Buffer are all interchangeable
282 case ARGI_INTEGER:
283 case ARGI_STRING:
284 case ARGI_BUFFER:
285 case ARGI_BUFFER_OR_STRING:
286 case ARGI_COMPUTEDATA:
287 return (ACPI_BTYPE_COMPUTE_DATA);
289 /* References */
291 case ARGI_INTEGER_REF:
292 return (ACPI_BTYPE_INTEGER);
294 case ARGI_OBJECT_REF:
295 return (ACPI_BTYPE_ALL_OBJECTS);
297 case ARGI_DEVICE_REF:
298 return (ACPI_BTYPE_DEVICE_OBJECTS);
300 case ARGI_REFERENCE:
301 return (ACPI_BTYPE_REFERENCE);
303 case ARGI_TARGETREF:
304 case ARGI_FIXED_TARGET:
305 case ARGI_SIMPLE_TARGET:
306 return (ACPI_BTYPE_OBJECTS_AND_REFS);
308 /* Complex types */
310 case ARGI_DATAOBJECT:
313 * Buffer, string, package or reference to a Op -
314 * Used only by SizeOf operator
316 return (ACPI_BTYPE_STRING | ACPI_BTYPE_BUFFER |
317 ACPI_BTYPE_PACKAGE | ACPI_BTYPE_REFERENCE);
319 case ARGI_COMPLEXOBJ:
321 /* Buffer, String, or package */
323 return (ACPI_BTYPE_STRING | ACPI_BTYPE_BUFFER | ACPI_BTYPE_PACKAGE);
325 case ARGI_REF_OR_STRING:
326 return (ACPI_BTYPE_STRING | ACPI_BTYPE_REFERENCE);
328 case ARGI_REGION_OR_BUFFER:
330 /* Used by Load() only. Allow buffers in addition to regions/fields */
332 return (ACPI_BTYPE_REGION | ACPI_BTYPE_BUFFER | ACPI_BTYPE_FIELD_UNIT);
334 case ARGI_DATAREFOBJ:
335 return (ACPI_BTYPE_INTEGER |ACPI_BTYPE_STRING | ACPI_BTYPE_BUFFER |
336 ACPI_BTYPE_PACKAGE | ACPI_BTYPE_REFERENCE | ACPI_BTYPE_DDB_HANDLE);
338 default:
339 break;
342 return (ACPI_BTYPE_OBJECTS_AND_REFS);
346 /*******************************************************************************
348 * FUNCTION: AnMapEtypeToBtype
350 * PARAMETERS: Etype - Encoded ACPI Type
352 * RETURN: Btype corresponding to the Etype
354 * DESCRIPTION: Convert an encoded ACPI type to a bitfield type applying the
355 * operand conversion rules. In other words, returns the type(s)
356 * this Etype is implicitly converted to during interpretation.
358 ******************************************************************************/
360 static UINT32
361 AnMapEtypeToBtype (
362 UINT32 Etype)
366 if (Etype == ACPI_TYPE_ANY)
368 return ACPI_BTYPE_OBJECTS_AND_REFS;
371 /* Try the standard ACPI data types */
373 if (Etype <= ACPI_TYPE_EXTERNAL_MAX)
376 * This switch statement implements the allowed operand conversion
377 * rules as per the "ASL Data Types" section of the ACPI
378 * specification.
380 switch (Etype)
382 case ACPI_TYPE_INTEGER:
383 return (ACPI_BTYPE_COMPUTE_DATA | ACPI_BTYPE_DDB_HANDLE);
385 case ACPI_TYPE_STRING:
386 case ACPI_TYPE_BUFFER:
387 return (ACPI_BTYPE_COMPUTE_DATA);
389 case ACPI_TYPE_PACKAGE:
390 return (ACPI_BTYPE_PACKAGE);
392 case ACPI_TYPE_FIELD_UNIT:
393 return (ACPI_BTYPE_COMPUTE_DATA | ACPI_BTYPE_FIELD_UNIT);
395 case ACPI_TYPE_BUFFER_FIELD:
396 return (ACPI_BTYPE_COMPUTE_DATA | ACPI_BTYPE_BUFFER_FIELD);
398 case ACPI_TYPE_DDB_HANDLE:
399 return (ACPI_BTYPE_INTEGER | ACPI_BTYPE_DDB_HANDLE);
401 case ACPI_BTYPE_DEBUG_OBJECT:
403 /* Cannot be used as a source operand */
405 return (0);
407 default:
408 return (1 << (Etype - 1));
412 /* Try the internal data types */
414 switch (Etype)
416 case ACPI_TYPE_LOCAL_REGION_FIELD:
417 case ACPI_TYPE_LOCAL_BANK_FIELD:
418 case ACPI_TYPE_LOCAL_INDEX_FIELD:
420 /* Named fields can be either Integer/Buffer/String */
422 return (ACPI_BTYPE_COMPUTE_DATA | ACPI_BTYPE_FIELD_UNIT);
424 case ACPI_TYPE_LOCAL_ALIAS:
426 return (ACPI_BTYPE_INTEGER);
429 case ACPI_TYPE_LOCAL_RESOURCE:
430 case ACPI_TYPE_LOCAL_RESOURCE_FIELD:
432 return (ACPI_BTYPE_REFERENCE);
434 default:
435 printf ("Unhandled encoded type: %X\n", Etype);
436 return (0);
441 /*******************************************************************************
443 * FUNCTION: AnFormatBtype
445 * PARAMETERS: Btype - Bitfield of ACPI types
446 * Buffer - Where to put the ascii string
448 * RETURN: None.
450 * DESCRIPTION: Convert a Btype to a string of ACPI types
452 ******************************************************************************/
454 static void
455 AnFormatBtype (
456 char *Buffer,
457 UINT32 Btype)
459 UINT32 Type;
460 BOOLEAN First = TRUE;
463 *Buffer = 0;
465 if (Btype == 0)
467 strcat (Buffer, "NoReturnValue");
468 return;
471 for (Type = 1; Type <= ACPI_TYPE_EXTERNAL_MAX; Type++)
473 if (Btype & 0x00000001)
475 if (!First)
477 strcat (Buffer, "|");
479 First = FALSE;
480 strcat (Buffer, AcpiUtGetTypeName (Type));
482 Btype >>= 1;
485 if (Btype & 0x00000001)
487 if (!First)
489 strcat (Buffer, "|");
491 First = FALSE;
492 strcat (Buffer, "Reference");
495 Btype >>= 1;
496 if (Btype & 0x00000001)
498 if (!First)
500 strcat (Buffer, "|");
502 First = FALSE;
503 strcat (Buffer, "Resource");
508 /*******************************************************************************
510 * FUNCTION: AnGetBtype
512 * PARAMETERS: Op - Parse node whose type will be returned.
514 * RETURN: The Btype associated with the Op.
516 * DESCRIPTION: Get the (bitfield) ACPI type associated with the parse node.
517 * Handles the case where the node is a name or method call and
518 * the actual type must be obtained from the namespace node.
520 ******************************************************************************/
522 static UINT32
523 AnGetBtype (
524 ACPI_PARSE_OBJECT *Op)
526 ACPI_NAMESPACE_NODE *Node;
527 ACPI_PARSE_OBJECT *ReferencedNode;
528 UINT32 ThisNodeBtype = 0;
531 if ((Op->Asl.ParseOpcode == PARSEOP_NAMESEG) ||
532 (Op->Asl.ParseOpcode == PARSEOP_NAMESTRING) ||
533 (Op->Asl.ParseOpcode == PARSEOP_METHODCALL))
535 Node = Op->Asl.Node;
536 if (!Node)
538 DbgPrint (ASL_DEBUG_OUTPUT,
539 "No attached Nsnode: [%s] at line %d name [%s], ignoring typecheck\n",
540 Op->Asl.ParseOpName, Op->Asl.LineNumber,
541 Op->Asl.ExternalName);
542 return ACPI_UINT32_MAX;
545 ThisNodeBtype = AnMapEtypeToBtype (Node->Type);
546 if (!ThisNodeBtype)
548 AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
549 "could not map type");
553 * Since it was a named reference, enable the
554 * reference bit also
556 ThisNodeBtype |= ACPI_BTYPE_REFERENCE;
558 if (Op->Asl.ParseOpcode == PARSEOP_METHODCALL)
560 ReferencedNode = Node->Op;
561 if (!ReferencedNode)
563 /* Check for an internal method */
565 if (AnIsInternalMethod (Op))
567 return (AnGetInternalMethodReturnType (Op));
570 AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
571 "null Op pointer");
572 return ACPI_UINT32_MAX;
575 if (ReferencedNode->Asl.CompileFlags & NODE_METHOD_TYPED)
577 ThisNodeBtype = ReferencedNode->Asl.AcpiBtype;
579 else
581 return (ACPI_UINT32_MAX -1);
585 else
587 ThisNodeBtype = Op->Asl.AcpiBtype;
590 return (ThisNodeBtype);
594 /*******************************************************************************
596 * FUNCTION: AnCheckForReservedName
598 * PARAMETERS: Op - A parse node
599 * Name - NameSeg to check
601 * RETURN: None
603 * DESCRIPTION: Check a NameSeg against the reserved list.
605 ******************************************************************************/
607 static UINT32
608 AnCheckForReservedName (
609 ACPI_PARSE_OBJECT *Op,
610 char *Name)
612 UINT32 i;
615 if (Name[0] == 0)
617 AcpiOsPrintf ("Found a null name, external = %s\n",
618 Op->Asl.ExternalName);
621 /* All reserved names are prefixed with a single underscore */
623 if (Name[0] != '_')
625 return (ACPI_NOT_RESERVED_NAME);
628 /* Check for a standard reserved method name */
630 for (i = 0; ReservedMethods[i].Name; i++)
632 if (ACPI_COMPARE_NAME (Name, ReservedMethods[i].Name))
634 if (ReservedMethods[i].Flags & ASL_RSVD_SCOPE)
636 AslError (ASL_ERROR, ASL_MSG_RESERVED_WORD, Op,
637 Op->Asl.ExternalName);
638 return (ACPI_PREDEFINED_NAME);
640 else if (ReservedMethods[i].Flags & ASL_RSVD_RESOURCE_NAME)
642 AslError (ASL_ERROR, ASL_MSG_RESERVED_WORD, Op,
643 Op->Asl.ExternalName);
644 return (ACPI_PREDEFINED_NAME);
647 /* Return index into reserved array */
649 return i;
654 * Now check for the "special" reserved names --
655 * GPE: _Lxx
656 * GPE: _Exx
657 * EC: _Qxx
659 if ((Name[1] == 'L') ||
660 (Name[1] == 'E') ||
661 (Name[1] == 'Q'))
663 /* The next two characters must be hex digits */
665 if ((isxdigit (Name[2])) &&
666 (isxdigit (Name[3])))
668 return (ACPI_EVENT_RESERVED_NAME);
673 /* Check for the names reserved for the compiler itself: _T_x */
675 else if ((Op->Asl.ExternalName[1] == 'T') &&
676 (Op->Asl.ExternalName[2] == '_'))
678 /* Ignore if actually emitted by the compiler */
680 if (Op->Asl.CompileFlags & NODE_COMPILER_EMITTED)
682 return (ACPI_NOT_RESERVED_NAME);
685 AslError (ASL_ERROR, ASL_MSG_RESERVED_WORD, Op, Op->Asl.ExternalName);
686 return (ACPI_COMPILER_RESERVED_NAME);
690 * The name didn't match any of the known reserved names. Flag it as a
691 * warning, since the entire namespace starting with an underscore is
692 * reserved by the ACPI spec.
694 AslError (ASL_WARNING, ASL_MSG_UNKNOWN_RESERVED_NAME, Op,
695 Op->Asl.ExternalName);
697 return (ACPI_NOT_RESERVED_NAME);
701 /*******************************************************************************
703 * FUNCTION: AnCheckForReservedMethod
705 * PARAMETERS: Op - A parse node of type "METHOD".
706 * MethodInfo - Saved info about this method
708 * RETURN: None
710 * DESCRIPTION: If method is a reserved name, check that the number of arguments
711 * and the return type (returns a value or not) is correct.
713 ******************************************************************************/
715 static void
716 AnCheckForReservedMethod (
717 ACPI_PARSE_OBJECT *Op,
718 ASL_METHOD_INFO *MethodInfo)
720 UINT32 Index;
723 /* Check for a match against the reserved name list */
725 Index = AnCheckForReservedName (Op, Op->Asl.NameSeg);
727 switch (Index)
729 case ACPI_NOT_RESERVED_NAME:
730 case ACPI_PREDEFINED_NAME:
731 case ACPI_COMPILER_RESERVED_NAME:
733 /* Just return, nothing to do */
734 break;
737 case ACPI_EVENT_RESERVED_NAME:
739 Gbl_ReservedMethods++;
741 /* NumArguments must be zero for all _Lxx, _Exx, and _Qxx methods */
743 if (MethodInfo->NumArguments != 0)
745 sprintf (MsgBuffer, "%s requires %d",
746 Op->Asl.ExternalName, 0);
748 AslError (ASL_WARNING, ASL_MSG_RESERVED_ARG_COUNT_HI, Op, MsgBuffer);
750 break;
753 default:
755 Gbl_ReservedMethods++;
757 /* Matched a reserved method name */
759 if (MethodInfo->NumArguments != ReservedMethods[Index].NumArguments)
761 sprintf (MsgBuffer, "%s requires %d",
762 ReservedMethods[Index].Name,
763 ReservedMethods[Index].NumArguments);
765 if (MethodInfo->NumArguments > ReservedMethods[Index].NumArguments)
767 AslError (ASL_WARNING, ASL_MSG_RESERVED_ARG_COUNT_HI, Op,
768 MsgBuffer);
770 else
772 AslError (ASL_WARNING, ASL_MSG_RESERVED_ARG_COUNT_LO, Op,
773 MsgBuffer);
777 if (MethodInfo->NumReturnNoValue &&
778 ReservedMethods[Index].Flags & ASL_RSVD_RETURN_VALUE)
780 sprintf (MsgBuffer, "%s", ReservedMethods[Index].Name);
782 AslError (ASL_WARNING, ASL_MSG_RESERVED_RETURN_VALUE, Op, MsgBuffer);
784 break;
789 /*******************************************************************************
791 * FUNCTION: AnMapObjTypeToBtype
793 * PARAMETERS: Op - A parse node
795 * RETURN: A Btype
797 * DESCRIPTION: Map object to the associated "Btype"
799 ******************************************************************************/
801 static UINT32
802 AnMapObjTypeToBtype (
803 ACPI_PARSE_OBJECT *Op)
806 switch (Op->Asl.ParseOpcode)
808 case PARSEOP_OBJECTTYPE_BFF: /* "BuffFieldObj" */
809 return (ACPI_BTYPE_BUFFER_FIELD);
811 case PARSEOP_OBJECTTYPE_BUF: /* "BuffObj" */
812 return (ACPI_BTYPE_BUFFER);
814 case PARSEOP_OBJECTTYPE_DDB: /* "DDBHandleObj" */
815 return (ACPI_BTYPE_DDB_HANDLE);
817 case PARSEOP_OBJECTTYPE_DEV: /* "DeviceObj" */
818 return (ACPI_BTYPE_DEVICE);
820 case PARSEOP_OBJECTTYPE_EVT: /* "EventObj" */
821 return (ACPI_BTYPE_EVENT);
823 case PARSEOP_OBJECTTYPE_FLD: /* "FieldUnitObj" */
824 return (ACPI_BTYPE_FIELD_UNIT);
826 case PARSEOP_OBJECTTYPE_INT: /* "IntObj" */
827 return (ACPI_BTYPE_INTEGER);
829 case PARSEOP_OBJECTTYPE_MTH: /* "MethodObj" */
830 return (ACPI_BTYPE_METHOD);
832 case PARSEOP_OBJECTTYPE_MTX: /* "MutexObj" */
833 return (ACPI_BTYPE_MUTEX);
835 case PARSEOP_OBJECTTYPE_OPR: /* "OpRegionObj" */
836 return (ACPI_BTYPE_REGION);
838 case PARSEOP_OBJECTTYPE_PKG: /* "PkgObj" */
839 return (ACPI_BTYPE_PACKAGE);
841 case PARSEOP_OBJECTTYPE_POW: /* "PowerResObj" */
842 return (ACPI_BTYPE_POWER);
844 case PARSEOP_OBJECTTYPE_STR: /* "StrObj" */
845 return (ACPI_BTYPE_STRING);
847 case PARSEOP_OBJECTTYPE_THZ: /* "ThermalZoneObj" */
848 return (ACPI_BTYPE_THERMAL);
850 case PARSEOP_OBJECTTYPE_UNK: /* "UnknownObj" */
851 return (ACPI_BTYPE_OBJECTS_AND_REFS);
853 default:
854 return (0);
859 /*******************************************************************************
861 * FUNCTION: AnMethodAnalysisWalkBegin
863 * PARAMETERS: ASL_WALK_CALLBACK
865 * RETURN: Status
867 * DESCRIPTION: Descending callback for the analysis walk. Check methods for:
868 * 1) Initialized local variables
869 * 2) Valid arguments
870 * 3) Return types
872 ******************************************************************************/
874 ACPI_STATUS
875 AnMethodAnalysisWalkBegin (
876 ACPI_PARSE_OBJECT *Op,
877 UINT32 Level,
878 void *Context)
880 ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
881 ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack;
882 ACPI_PARSE_OBJECT *Next;
883 UINT32 RegisterNumber;
884 UINT32 i;
885 char LocalName[] = "Local0";
886 char ArgName[] = "Arg0";
887 ACPI_PARSE_OBJECT *ArgNode;
888 ACPI_PARSE_OBJECT *NextType;
889 ACPI_PARSE_OBJECT *NextParamType;
890 UINT8 ActualArgs = 0;
893 switch (Op->Asl.ParseOpcode)
895 case PARSEOP_METHOD:
897 TotalMethods++;
899 /* Create and init method info */
901 MethodInfo = UtLocalCalloc (sizeof (ASL_METHOD_INFO));
902 MethodInfo->Next = WalkInfo->MethodStack;
903 MethodInfo->Op = Op;
905 WalkInfo->MethodStack = MethodInfo;
907 /* Get the name node, ignored here */
909 Next = Op->Asl.Child;
911 /* Get the NumArguments node */
913 Next = Next->Asl.Next;
914 MethodInfo->NumArguments = (UINT8)
915 (((UINT8) Next->Asl.Value.Integer) & 0x07);
917 /* Get the SerializeRule and SyncLevel nodes, ignored here */
919 Next = Next->Asl.Next;
920 Next = Next->Asl.Next;
921 ArgNode = Next;
923 /* Get the ReturnType node */
925 Next = Next->Asl.Next;
927 NextType = Next->Asl.Child;
928 while (NextType)
930 /* Get and map each of the ReturnTypes */
932 MethodInfo->ValidReturnTypes |= AnMapObjTypeToBtype (NextType);
933 NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
934 NextType = NextType->Asl.Next;
937 /* Get the ParameterType node */
939 Next = Next->Asl.Next;
941 NextType = Next->Asl.Child;
942 while (NextType)
944 if (NextType->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
946 NextParamType = NextType->Asl.Child;
947 while (NextParamType)
949 MethodInfo->ValidArgTypes[ActualArgs] |= AnMapObjTypeToBtype (NextParamType);
950 NextParamType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
951 NextParamType = NextParamType->Asl.Next;
954 else
956 MethodInfo->ValidArgTypes[ActualArgs] =
957 AnMapObjTypeToBtype (NextType);
958 NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
961 ActualArgs++;
962 NextType = NextType->Asl.Next;
965 if ((MethodInfo->NumArguments) &&
966 (MethodInfo->NumArguments != ActualArgs))
968 /* error: Param list did not match number of args */
971 /* Allow numarguments == 0 for Function() */
973 if ((!MethodInfo->NumArguments) && (ActualArgs))
975 MethodInfo->NumArguments = ActualArgs;
976 ArgNode->Asl.Value.Integer |= ActualArgs;
980 * Actual arguments are initialized at method entry.
981 * All other ArgX "registers" can be used as locals, so we
982 * track their initialization.
984 for (i = 0; i < MethodInfo->NumArguments; i++)
986 MethodInfo->ArgInitialized[i] = TRUE;
988 break;
991 case PARSEOP_METHODCALL:
993 if (MethodInfo &&
994 (Op->Asl.Node == MethodInfo->Op->Asl.Node))
996 AslError (ASL_REMARK, ASL_MSG_RECURSION, Op, Op->Asl.ExternalName);
998 break;
1001 case PARSEOP_LOCAL0:
1002 case PARSEOP_LOCAL1:
1003 case PARSEOP_LOCAL2:
1004 case PARSEOP_LOCAL3:
1005 case PARSEOP_LOCAL4:
1006 case PARSEOP_LOCAL5:
1007 case PARSEOP_LOCAL6:
1008 case PARSEOP_LOCAL7:
1010 if (!MethodInfo)
1013 * Probably was an error in the method declaration,
1014 * no additional error here
1016 ACPI_WARNING ((AE_INFO, "%p, No parent method", Op));
1017 return (AE_ERROR);
1020 RegisterNumber = (Op->Asl.AmlOpcode & 0x000F);
1023 * If the local is being used as a target, mark the local
1024 * initialized
1026 if (Op->Asl.CompileFlags & NODE_IS_TARGET)
1028 MethodInfo->LocalInitialized[RegisterNumber] = TRUE;
1032 * Otherwise, this is a reference, check if the local
1033 * has been previously initialized.
1035 * The only operator that accepts an uninitialized value is ObjectType()
1037 else if ((!MethodInfo->LocalInitialized[RegisterNumber]) &&
1038 (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
1040 LocalName[strlen (LocalName) -1] = (char) (RegisterNumber + 0x30);
1041 AslError (ASL_ERROR, ASL_MSG_LOCAL_INIT, Op, LocalName);
1043 break;
1046 case PARSEOP_ARG0:
1047 case PARSEOP_ARG1:
1048 case PARSEOP_ARG2:
1049 case PARSEOP_ARG3:
1050 case PARSEOP_ARG4:
1051 case PARSEOP_ARG5:
1052 case PARSEOP_ARG6:
1054 if (!MethodInfo)
1057 * Probably was an error in the method declaration,
1058 * no additional error here
1060 ACPI_WARNING ((AE_INFO, "%p, No parent method", Op));
1061 return (AE_ERROR);
1064 RegisterNumber = (Op->Asl.AmlOpcode & 0x000F) - 8;
1065 ArgName[strlen (ArgName) -1] = (char) (RegisterNumber + 0x30);
1068 * If the Arg is being used as a target, mark the local
1069 * initialized
1071 if (Op->Asl.CompileFlags & NODE_IS_TARGET)
1073 MethodInfo->ArgInitialized[RegisterNumber] = TRUE;
1077 * Otherwise, this is a reference, check if the Arg
1078 * has been previously initialized.
1080 * The only operator that accepts an uninitialized value is ObjectType()
1082 else if ((!MethodInfo->ArgInitialized[RegisterNumber]) &&
1083 (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
1085 AslError (ASL_ERROR, ASL_MSG_ARG_INIT, Op, ArgName);
1088 /* Flag this arg if it is not a "real" argument to the method */
1090 if (RegisterNumber >= MethodInfo->NumArguments)
1092 AslError (ASL_REMARK, ASL_MSG_NOT_PARAMETER, Op, ArgName);
1094 break;
1097 case PARSEOP_RETURN:
1099 if (!MethodInfo)
1102 * Probably was an error in the method declaration,
1103 * no additional error here
1105 ACPI_WARNING ((AE_INFO, "%p, No parent method", Op));
1106 return (AE_ERROR);
1109 /* Child indicates a return value */
1111 if ((Op->Asl.Child) &&
1112 (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
1114 MethodInfo->NumReturnWithValue++;
1116 else
1118 MethodInfo->NumReturnNoValue++;
1120 break;
1123 case PARSEOP_BREAK:
1124 case PARSEOP_CONTINUE:
1126 Next = Op->Asl.Parent;
1127 while (Next)
1129 if (Next->Asl.ParseOpcode == PARSEOP_WHILE)
1131 break;
1133 Next = Next->Asl.Parent;
1136 if (!Next)
1138 AslError (ASL_ERROR, ASL_MSG_NO_WHILE, Op, NULL);
1140 break;
1143 case PARSEOP_STALL:
1145 /* We can range check if the argument is an integer */
1147 if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
1148 (Op->Asl.Child->Asl.Value.Integer > ACPI_UINT8_MAX))
1150 AslError (ASL_ERROR, ASL_MSG_INVALID_TIME, Op, NULL);
1152 break;
1155 case PARSEOP_DEVICE:
1156 case PARSEOP_EVENT:
1157 case PARSEOP_MUTEX:
1158 case PARSEOP_OPERATIONREGION:
1159 case PARSEOP_POWERRESOURCE:
1160 case PARSEOP_PROCESSOR:
1161 case PARSEOP_THERMALZONE:
1164 * The first operand is a name to be created in the namespace.
1165 * Check against the reserved list.
1167 i = AnCheckForReservedName (Op, Op->Asl.NameSeg);
1168 if (i < ACPI_VALID_RESERVED_NAME_MAX)
1170 AslError (ASL_ERROR, ASL_MSG_RESERVED_USE, Op, Op->Asl.ExternalName);
1172 break;
1175 case PARSEOP_NAME:
1177 i = AnCheckForReservedName (Op, Op->Asl.NameSeg);
1178 if (i < ACPI_VALID_RESERVED_NAME_MAX)
1180 if (ReservedMethods[i].NumArguments > 0)
1183 * This reserved name must be a control method because
1184 * it must have arguments
1186 AslError (ASL_ERROR, ASL_MSG_RESERVED_METHOD, Op,
1187 "with arguments");
1190 /* Typechecking for _HID */
1192 else if (!ACPI_STRCMP (METHOD_NAME__HID, ReservedMethods[i].Name))
1194 /* Examine the second operand to typecheck it */
1196 Next = Op->Asl.Child->Asl.Next;
1198 if ((Next->Asl.ParseOpcode != PARSEOP_INTEGER) &&
1199 (Next->Asl.ParseOpcode != PARSEOP_STRING_LITERAL))
1201 /* _HID must be a string or an integer */
1203 AslError (ASL_ERROR, ASL_MSG_RESERVED_OPERAND_TYPE, Next,
1204 "String or Integer");
1207 if (Next->Asl.ParseOpcode == PARSEOP_STRING_LITERAL)
1210 * _HID is a string, all characters must be alphanumeric.
1211 * One of the things we want to catch here is the use of
1212 * a leading asterisk in the string.
1214 for (i = 0; Next->Asl.Value.String[i]; i++)
1216 if (!isalnum (Next->Asl.Value.String[i]))
1218 AslError (ASL_ERROR, ASL_MSG_ALPHANUMERIC_STRING,
1219 Next, Next->Asl.Value.String);
1220 break;
1226 break;
1229 default:
1230 break;
1233 return AE_OK;
1237 /*******************************************************************************
1239 * FUNCTION: AnLastStatementIsReturn
1241 * PARAMETERS: Op - A method parse node
1243 * RETURN: TRUE if last statement is an ASL RETURN. False otherwise
1245 * DESCRIPTION: Walk down the list of top level statements within a method
1246 * to find the last one. Check if that last statement is in
1247 * fact a RETURN statement.
1249 ******************************************************************************/
1251 static BOOLEAN
1252 AnLastStatementIsReturn (
1253 ACPI_PARSE_OBJECT *Op)
1255 ACPI_PARSE_OBJECT *Next;
1259 * Check if last statement is a return
1261 Next = ASL_GET_CHILD_NODE (Op);
1262 while (Next)
1264 if ((!Next->Asl.Next) &&
1265 (Next->Asl.ParseOpcode == PARSEOP_RETURN))
1267 return TRUE;
1270 Next = ASL_GET_PEER_NODE (Next);
1273 return FALSE;
1277 /*******************************************************************************
1279 * FUNCTION: AnMethodAnalysisWalkEnd
1281 * PARAMETERS: ASL_WALK_CALLBACK
1283 * RETURN: Status
1285 * DESCRIPTION: Ascending callback for analysis walk. Complete method
1286 * return analysis.
1288 ******************************************************************************/
1290 ACPI_STATUS
1291 AnMethodAnalysisWalkEnd (
1292 ACPI_PARSE_OBJECT *Op,
1293 UINT32 Level,
1294 void *Context)
1296 ASL_ANALYSIS_WALK_INFO *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
1297 ASL_METHOD_INFO *MethodInfo = WalkInfo->MethodStack;
1300 switch (Op->Asl.ParseOpcode)
1302 case PARSEOP_METHOD:
1303 case PARSEOP_RETURN:
1304 if (!MethodInfo)
1306 printf ("No method info for method! [%s]\n", Op->Asl.Namepath);
1307 AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
1308 "No method info for this method");
1309 CmCleanupAndExit ();
1310 return (AE_AML_INTERNAL);
1312 break;
1314 default:
1315 break;
1318 switch (Op->Asl.ParseOpcode)
1320 case PARSEOP_METHOD:
1322 WalkInfo->MethodStack = MethodInfo->Next;
1325 * Check if there is no return statement at the end of the
1326 * method AND we can actually get there -- i.e., the execution
1327 * of the method can possibly terminate without a return statement.
1329 if ((!AnLastStatementIsReturn (Op)) &&
1330 (!(Op->Asl.CompileFlags & NODE_HAS_NO_EXIT)))
1333 * No return statement, and execution can possibly exit
1334 * via this path. This is equivalent to Return ()
1336 MethodInfo->NumReturnNoValue++;
1340 * Check for case where some return statements have a return value
1341 * and some do not. Exit without a return statement is a return with
1342 * no value
1344 if (MethodInfo->NumReturnNoValue &&
1345 MethodInfo->NumReturnWithValue)
1347 AslError (ASL_WARNING, ASL_MSG_RETURN_TYPES, Op,
1348 Op->Asl.ExternalName);
1352 * If there are any RETURN() statements with no value, or there is a
1353 * control path that allows the method to exit without a return value,
1354 * we mark the method as a method that does not return a value. This
1355 * knowledge can be used to check method invocations that expect a
1356 * returned value.
1358 if (MethodInfo->NumReturnNoValue)
1360 if (MethodInfo->NumReturnWithValue)
1362 Op->Asl.CompileFlags |= NODE_METHOD_SOME_NO_RETVAL;
1364 else
1366 Op->Asl.CompileFlags |= NODE_METHOD_NO_RETVAL;
1371 * Check predefined method names for correct return behavior
1372 * and correct number of arguments
1374 AnCheckForReservedMethod (Op, MethodInfo);
1375 ACPI_FREE (MethodInfo);
1376 break;
1379 case PARSEOP_RETURN:
1382 * The parent block does not "exit" and continue execution -- the
1383 * method is terminated here with the Return() statement.
1385 Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
1387 /* Used in the "typing" pass later */
1389 Op->Asl.ParentMethod = MethodInfo->Op;
1392 * If there is a peer node after the return statement, then this
1393 * node is unreachable code -- i.e., it won't be executed because of
1394 * the preceeding Return() statement.
1396 if (Op->Asl.Next)
1398 AslError (ASL_WARNING, ASL_MSG_UNREACHABLE_CODE, Op->Asl.Next, NULL);
1400 break;
1403 case PARSEOP_IF:
1405 if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
1406 (Op->Asl.Next) &&
1407 (Op->Asl.Next->Asl.ParseOpcode == PARSEOP_ELSE))
1410 * This IF has a corresponding ELSE. The IF block has no exit,
1411 * (it contains an unconditional Return)
1412 * mark the ELSE block to remember this fact.
1414 Op->Asl.Next->Asl.CompileFlags |= NODE_IF_HAS_NO_EXIT;
1416 break;
1419 case PARSEOP_ELSE:
1421 if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
1422 (Op->Asl.CompileFlags & NODE_IF_HAS_NO_EXIT))
1425 * This ELSE block has no exit and the corresponding IF block
1426 * has no exit either. Therefore, the parent node has no exit.
1428 Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
1430 break;
1433 default:
1435 if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
1436 (Op->Asl.Parent))
1438 /* If this node has no exit, then the parent has no exit either */
1440 Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
1442 break;
1445 return AE_OK;
1449 /*******************************************************************************
1451 * FUNCTION: AnMethodTypingWalkBegin
1453 * PARAMETERS: ASL_WALK_CALLBACK
1455 * RETURN: Status
1457 * DESCRIPTION: Descending callback for the typing walk.
1459 ******************************************************************************/
1461 ACPI_STATUS
1462 AnMethodTypingWalkBegin (
1463 ACPI_PARSE_OBJECT *Op,
1464 UINT32 Level,
1465 void *Context)
1468 return AE_OK;
1472 /*******************************************************************************
1474 * FUNCTION: AnMethodTypingWalkEnd
1476 * PARAMETERS: ASL_WALK_CALLBACK
1478 * RETURN: Status
1480 * DESCRIPTION: Ascending callback for typing walk. Complete the method
1481 * return analysis. Check methods for:
1482 * 1) Initialized local variables
1483 * 2) Valid arguments
1484 * 3) Return types
1486 ******************************************************************************/
1488 ACPI_STATUS
1489 AnMethodTypingWalkEnd (
1490 ACPI_PARSE_OBJECT *Op,
1491 UINT32 Level,
1492 void *Context)
1494 UINT32 ThisNodeBtype;
1497 switch (Op->Asl.ParseOpcode)
1499 case PARSEOP_METHOD:
1501 Op->Asl.CompileFlags |= NODE_METHOD_TYPED;
1502 break;
1504 case PARSEOP_RETURN:
1506 if ((Op->Asl.Child) &&
1507 (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
1509 ThisNodeBtype = AnGetBtype (Op->Asl.Child);
1511 if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_METHODCALL) &&
1512 (ThisNodeBtype == (ACPI_UINT32_MAX -1)))
1515 * The called method is untyped at this time (typically a
1516 * forward reference).
1518 * Check for a recursive method call first.
1520 if (Op->Asl.ParentMethod != Op->Asl.Child->Asl.Node->Op)
1522 /* We must type the method here */
1524 TrWalkParseTree (Op->Asl.Child->Asl.Node->Op,
1525 ASL_WALK_VISIT_TWICE, AnMethodTypingWalkBegin,
1526 AnMethodTypingWalkEnd, NULL);
1528 ThisNodeBtype = AnGetBtype (Op->Asl.Child);
1532 /* Returns a value, save the value type */
1534 if (Op->Asl.ParentMethod)
1536 Op->Asl.ParentMethod->Asl.AcpiBtype |= ThisNodeBtype;
1539 break;
1541 default:
1542 break;
1545 return AE_OK;
1549 /*******************************************************************************
1551 * FUNCTION: AnCheckMethodReturnValue
1553 * PARAMETERS: Op - Parent
1554 * OpInfo - Parent info
1555 * ArgOp - Method invocation op
1556 * RequiredBtypes - What caller requires
1557 * ThisNodeBtype - What this node returns (if anything)
1559 * RETURN: None
1561 * DESCRIPTION: Check a method invocation for 1) A return value and if it does
1562 * in fact return a value, 2) check the type of the return value.
1564 ******************************************************************************/
1566 static void
1567 AnCheckMethodReturnValue (
1568 ACPI_PARSE_OBJECT *Op,
1569 const ACPI_OPCODE_INFO *OpInfo,
1570 ACPI_PARSE_OBJECT *ArgOp,
1571 UINT32 RequiredBtypes,
1572 UINT32 ThisNodeBtype)
1574 ACPI_PARSE_OBJECT *OwningOp;
1575 ACPI_NAMESPACE_NODE *Node;
1578 Node = ArgOp->Asl.Node;
1581 /* Examine the parent op of this method */
1583 OwningOp = Node->Op;
1584 if (OwningOp->Asl.CompileFlags & NODE_METHOD_NO_RETVAL)
1586 /* Method NEVER returns a value */
1588 AslError (ASL_ERROR, ASL_MSG_NO_RETVAL, Op, Op->Asl.ExternalName);
1590 else if (OwningOp->Asl.CompileFlags & NODE_METHOD_SOME_NO_RETVAL)
1592 /* Method SOMETIMES returns a value, SOMETIMES not */
1594 AslError (ASL_WARNING, ASL_MSG_SOME_NO_RETVAL, Op, Op->Asl.ExternalName);
1596 else if (!(ThisNodeBtype & RequiredBtypes))
1598 /* Method returns a value, but the type is wrong */
1600 AnFormatBtype (StringBuffer, ThisNodeBtype);
1601 AnFormatBtype (StringBuffer2, RequiredBtypes);
1605 * The case where the method does not return any value at all
1606 * was already handled in the namespace cross reference
1607 * -- Only issue an error if the method in fact returns a value,
1608 * but it is of the wrong type
1610 if (ThisNodeBtype != 0)
1612 sprintf (MsgBuffer,
1613 "Method returns [%s], %s operator requires [%s]",
1614 StringBuffer, OpInfo->Name, StringBuffer2);
1616 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer);
1622 /*******************************************************************************
1624 * FUNCTION: AnOperandTypecheckWalkBegin
1626 * PARAMETERS: ASL_WALK_CALLBACK
1628 * RETURN: Status
1630 * DESCRIPTION: Descending callback for the analysis walk. Check methods for:
1631 * 1) Initialized local variables
1632 * 2) Valid arguments
1633 * 3) Return types
1635 ******************************************************************************/
1637 ACPI_STATUS
1638 AnOperandTypecheckWalkBegin (
1639 ACPI_PARSE_OBJECT *Op,
1640 UINT32 Level,
1641 void *Context)
1644 return AE_OK;
1648 /*******************************************************************************
1650 * FUNCTION: AnOperandTypecheckWalkEnd
1652 * PARAMETERS: ASL_WALK_CALLBACK
1654 * RETURN: Status
1656 * DESCRIPTION: Ascending callback for analysis walk. Complete method
1657 * return analysis.
1659 ******************************************************************************/
1661 ACPI_STATUS
1662 AnOperandTypecheckWalkEnd (
1663 ACPI_PARSE_OBJECT *Op,
1664 UINT32 Level,
1665 void *Context)
1667 const ACPI_OPCODE_INFO *OpInfo;
1668 UINT32 RuntimeArgTypes;
1669 UINT32 RuntimeArgTypes2;
1670 UINT32 RequiredBtypes;
1671 UINT32 ThisNodeBtype;
1672 UINT32 CommonBtypes;
1673 UINT32 OpcodeClass;
1674 ACPI_PARSE_OBJECT *ArgOp;
1675 UINT32 ArgType;
1678 switch (Op->Asl.AmlOpcode)
1680 case AML_RAW_DATA_BYTE:
1681 case AML_RAW_DATA_WORD:
1682 case AML_RAW_DATA_DWORD:
1683 case AML_RAW_DATA_QWORD:
1684 case AML_RAW_DATA_BUFFER:
1685 case AML_RAW_DATA_CHAIN:
1686 case AML_PACKAGE_LENGTH:
1687 case AML_UNASSIGNED_OPCODE:
1688 case AML_DEFAULT_ARG_OP:
1690 /* Ignore the internal (compiler-only) AML opcodes */
1692 return (AE_OK);
1694 default:
1695 break;
1698 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
1699 if (!OpInfo)
1701 return (AE_OK);
1704 ArgOp = Op->Asl.Child;
1705 RuntimeArgTypes = OpInfo->RuntimeArgs;
1706 OpcodeClass = OpInfo->Class;
1710 * Special case for control opcodes IF/RETURN/WHILE since they
1711 * have no runtime arg list (at this time)
1713 switch (Op->Asl.AmlOpcode)
1715 case AML_IF_OP:
1716 case AML_WHILE_OP:
1717 case AML_RETURN_OP:
1719 if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
1721 /* Check for an internal method */
1723 if (AnIsInternalMethod (ArgOp))
1725 return (AE_OK);
1728 /* The lone arg is a method call, check it */
1730 RequiredBtypes = AnMapArgTypeToBtype (ARGI_INTEGER);
1731 if (Op->Asl.AmlOpcode == AML_RETURN_OP)
1733 RequiredBtypes = 0xFFFFFFFF;
1736 ThisNodeBtype = AnGetBtype (ArgOp);
1737 if (ThisNodeBtype == ACPI_UINT32_MAX)
1739 return (AE_OK);
1741 AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
1742 RequiredBtypes, ThisNodeBtype);
1744 return (AE_OK);
1746 default:
1747 break;
1750 /* Ignore the non-executable opcodes */
1752 if (RuntimeArgTypes == ARGI_INVALID_OPCODE)
1754 return (AE_OK);
1757 switch (OpcodeClass)
1759 case AML_CLASS_EXECUTE:
1760 case AML_CLASS_CREATE:
1761 case AML_CLASS_CONTROL:
1762 case AML_CLASS_RETURN_VALUE:
1764 /* TBD: Change class or fix typechecking for these */
1766 if ((Op->Asl.AmlOpcode == AML_BUFFER_OP) ||
1767 (Op->Asl.AmlOpcode == AML_PACKAGE_OP) ||
1768 (Op->Asl.AmlOpcode == AML_VAR_PACKAGE_OP))
1770 break;
1773 /* Reverse the runtime argument list */
1775 RuntimeArgTypes2 = 0;
1776 while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes)))
1778 RuntimeArgTypes2 <<= ARG_TYPE_WIDTH;
1779 RuntimeArgTypes2 |= ArgType;
1780 INCREMENT_ARG_LIST (RuntimeArgTypes);
1783 while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2)))
1785 RequiredBtypes = AnMapArgTypeToBtype (ArgType);
1787 ThisNodeBtype = AnGetBtype (ArgOp);
1788 if (ThisNodeBtype == ACPI_UINT32_MAX)
1790 goto NextArgument;
1793 /* Examine the arg based on the required type of the arg */
1795 switch (ArgType)
1797 case ARGI_TARGETREF:
1799 if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO)
1801 /* ZERO is the placeholder for "don't store result" */
1803 ThisNodeBtype = RequiredBtypes;
1804 break;
1807 if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER)
1810 * This is the case where an original reference to a resource
1811 * descriptor field has been replaced by an (Integer) offset.
1812 * These named fields are supported at compile-time only;
1813 * the names are not passed to the interpreter (via the AML).
1815 if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
1816 (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
1818 AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD, ArgOp, NULL);
1820 else
1822 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, NULL);
1824 break;
1827 if ((ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) ||
1828 (ArgOp->Asl.ParseOpcode == PARSEOP_DEREFOF))
1830 break;
1833 ThisNodeBtype = RequiredBtypes;
1834 break;
1837 case ARGI_REFERENCE: /* References */
1838 case ARGI_INTEGER_REF:
1839 case ARGI_OBJECT_REF:
1840 case ARGI_DEVICE_REF:
1842 switch (ArgOp->Asl.ParseOpcode)
1844 case PARSEOP_LOCAL0:
1845 case PARSEOP_LOCAL1:
1846 case PARSEOP_LOCAL2:
1847 case PARSEOP_LOCAL3:
1848 case PARSEOP_LOCAL4:
1849 case PARSEOP_LOCAL5:
1850 case PARSEOP_LOCAL6:
1851 case PARSEOP_LOCAL7:
1853 /* TBD: implement analysis of current value (type) of the local */
1854 /* For now, just treat any local as a typematch */
1856 /*ThisNodeBtype = RequiredBtypes;*/
1857 break;
1859 case PARSEOP_ARG0:
1860 case PARSEOP_ARG1:
1861 case PARSEOP_ARG2:
1862 case PARSEOP_ARG3:
1863 case PARSEOP_ARG4:
1864 case PARSEOP_ARG5:
1865 case PARSEOP_ARG6:
1867 /* Hard to analyze argument types, sow we won't */
1868 /* For now, just treat any arg as a typematch */
1870 /* ThisNodeBtype = RequiredBtypes; */
1871 break;
1873 case PARSEOP_DEBUG:
1874 break;
1876 case PARSEOP_REFOF:
1877 case PARSEOP_INDEX:
1878 default:
1879 break;
1882 break;
1884 case ARGI_INTEGER:
1885 default:
1886 break;
1890 CommonBtypes = ThisNodeBtype & RequiredBtypes;
1892 if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
1894 if (AnIsInternalMethod (ArgOp))
1896 return (AE_OK);
1899 /* Check a method call for a valid return value */
1901 AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
1902 RequiredBtypes, ThisNodeBtype);
1906 * Now check if the actual type(s) match at least one
1907 * bit to the required type
1909 else if (!CommonBtypes)
1911 /* No match -- this is a type mismatch error */
1913 AnFormatBtype (StringBuffer, ThisNodeBtype);
1914 AnFormatBtype (StringBuffer2, RequiredBtypes);
1916 sprintf (MsgBuffer, "[%s] found, %s operator requires [%s]",
1917 StringBuffer, OpInfo->Name, StringBuffer2);
1919 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer);
1922 NextArgument:
1923 ArgOp = ArgOp->Asl.Next;
1924 INCREMENT_ARG_LIST (RuntimeArgTypes2);
1926 break;
1928 default:
1929 break;
1932 return (AE_OK);
1936 /*******************************************************************************
1938 * FUNCTION: AnIsResultUsed
1940 * PARAMETERS: Op - Parent op for the operator
1942 * RETURN: TRUE if result from this operation is actually consumed
1944 * DESCRIPTION: Determine if the function result value from an operator is
1945 * used.
1947 ******************************************************************************/
1949 BOOLEAN
1950 AnIsResultUsed (
1951 ACPI_PARSE_OBJECT *Op)
1953 ACPI_PARSE_OBJECT *Parent;
1956 switch (Op->Asl.ParseOpcode)
1958 case PARSEOP_INCREMENT:
1959 case PARSEOP_DECREMENT:
1961 /* These are standalone operators, no return value */
1963 return (TRUE);
1965 default:
1966 break;
1969 /* Examine parent to determine if the return value is used */
1971 Parent = Op->Asl.Parent;
1972 switch (Parent->Asl.ParseOpcode)
1974 /* If/While - check if the operator is the predicate */
1976 case PARSEOP_IF:
1977 case PARSEOP_WHILE:
1979 /* First child is the predicate */
1981 if (Parent->Asl.Child == Op)
1983 return (TRUE);
1985 return (FALSE);
1987 /* Not used if one of these is the parent */
1989 case PARSEOP_METHOD:
1990 case PARSEOP_DEFINITIONBLOCK:
1991 case PARSEOP_ELSE:
1993 return (FALSE);
1995 default:
1996 /* Any other type of parent means that the result is used */
1998 return (TRUE);
2003 /*******************************************************************************
2005 * FUNCTION: AnOtherSemanticAnalysisWalkBegin
2007 * PARAMETERS: ASL_WALK_CALLBACK
2009 * RETURN: Status
2011 * DESCRIPTION: Descending callback for the analysis walk. Checks for
2012 * miscellaneous issues in the code.
2014 ******************************************************************************/
2016 ACPI_STATUS
2017 AnOtherSemanticAnalysisWalkBegin (
2018 ACPI_PARSE_OBJECT *Op,
2019 UINT32 Level,
2020 void *Context)
2022 ACPI_PARSE_OBJECT *ArgNode;
2023 ACPI_PARSE_OBJECT *PrevArgNode = NULL;
2024 const ACPI_OPCODE_INFO *OpInfo;
2027 OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
2030 * Determine if an execution class operator actually does something by
2031 * checking if it has a target and/or the function return value is used.
2032 * (Target is optional, so a standalone statement can actually do nothing.)
2034 if ((OpInfo->Class == AML_CLASS_EXECUTE) &&
2035 (OpInfo->Flags & AML_HAS_RETVAL) &&
2036 (!AnIsResultUsed (Op)))
2038 if (OpInfo->Flags & AML_HAS_TARGET)
2041 * Find the target node, it is always the last child. If the traget
2042 * is not specified in the ASL, a default node of type Zero was
2043 * created by the parser.
2045 ArgNode = Op->Asl.Child;
2046 while (ArgNode->Asl.Next)
2048 PrevArgNode = ArgNode;
2049 ArgNode = ArgNode->Asl.Next;
2052 /* Divide() is the only weird case, it has two targets */
2054 if (Op->Asl.AmlOpcode == AML_DIVIDE_OP)
2056 if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) &&
2057 (PrevArgNode->Asl.ParseOpcode == PARSEOP_ZERO))
2059 AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED, Op, Op->Asl.ExternalName);
2062 else if (ArgNode->Asl.ParseOpcode == PARSEOP_ZERO)
2064 AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED, Op, Op->Asl.ExternalName);
2067 else
2070 * Has no target and the result is not used. Only a couple opcodes
2071 * can have this combination.
2073 switch (Op->Asl.ParseOpcode)
2075 case PARSEOP_ACQUIRE:
2076 case PARSEOP_WAIT:
2077 break;
2079 default:
2080 AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED, Op, Op->Asl.ExternalName);
2081 break;
2088 * Semantic checks for individual ASL operators
2090 switch (Op->Asl.ParseOpcode)
2092 case PARSEOP_ACQUIRE:
2093 case PARSEOP_WAIT:
2095 * Emit a warning if the timeout parameter for these operators is not
2096 * ACPI_WAIT_FOREVER, and the result value from the operator is not
2097 * checked, meaning that a timeout could happen, but the code
2098 * would not know about it.
2101 /* First child is the namepath, 2nd child is timeout */
2103 ArgNode = Op->Asl.Child;
2104 ArgNode = ArgNode->Asl.Next;
2107 * Check for the WAIT_FOREVER case - defined by the ACPI spec to be
2108 * 0xFFFF or greater
2110 if (((ArgNode->Asl.ParseOpcode == PARSEOP_WORDCONST) ||
2111 (ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER)) &&
2112 (ArgNode->Asl.Value.Integer >= (ACPI_INTEGER) ACPI_WAIT_FOREVER))
2114 break;
2118 * The operation could timeout. If the return value is not used
2119 * (indicates timeout occurred), issue a warning
2121 if (!AnIsResultUsed (Op))
2123 AslError (ASL_WARNING, ASL_MSG_TIMEOUT, ArgNode, Op->Asl.ExternalName);
2125 break;
2127 case PARSEOP_CREATEFIELD:
2129 * Check for a zero Length (NumBits) operand. NumBits is the 3rd operand
2131 ArgNode = Op->Asl.Child;
2132 ArgNode = ArgNode->Asl.Next;
2133 ArgNode = ArgNode->Asl.Next;
2135 if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) ||
2136 ((ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER) &&
2137 (ArgNode->Asl.Value.Integer == 0)))
2139 AslError (ASL_ERROR, ASL_MSG_NON_ZERO, ArgNode, NULL);
2141 break;
2143 default:
2144 break;
2147 return AE_OK;
2151 /*******************************************************************************
2153 * FUNCTION: AnOtherSemanticAnalysisWalkEnd
2155 * PARAMETERS: ASL_WALK_CALLBACK
2157 * RETURN: Status
2159 * DESCRIPTION: Ascending callback for analysis walk. Complete method
2160 * return analysis.
2162 ******************************************************************************/
2164 ACPI_STATUS
2165 AnOtherSemanticAnalysisWalkEnd (
2166 ACPI_PARSE_OBJECT *Op,
2167 UINT32 Level,
2168 void *Context)
2171 return AE_OK;
2176 #ifdef ACPI_OBSOLETE_FUNCTIONS
2177 /*******************************************************************************
2179 * FUNCTION: AnMapBtypeToEtype
2181 * PARAMETERS: Btype - Bitfield of ACPI types
2183 * RETURN: The Etype corresponding the the Btype
2185 * DESCRIPTION: Convert a bitfield type to an encoded type
2187 ******************************************************************************/
2189 UINT32
2190 AnMapBtypeToEtype (
2191 UINT32 Btype)
2193 UINT32 i;
2194 UINT32 Etype;
2197 if (Btype == 0)
2199 return 0;
2202 Etype = 1;
2203 for (i = 1; i < Btype; i *= 2)
2205 Etype++;
2208 return (Etype);
2210 #endif