Merge branch 'vendor/GREP'
[dragonfly.git] / sys / contrib / dev / acpica / source / compiler / aslwalks.c
1 /******************************************************************************
2  *
3  * Module Name: aslwalks.c - Miscellaneous analytical parse tree walks
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2014, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
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.
25  *
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.
29  *
30  * NO WARRANTY
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.
42  */
43
44 #include "aslcompiler.h"
45 #include "aslcompiler.y.h"
46 #include "acparser.h"
47 #include "amlcode.h"
48
49
50 #define _COMPONENT          ACPI_COMPILER
51         ACPI_MODULE_NAME    ("aslwalks")
52
53
54 /*******************************************************************************
55  *
56  * FUNCTION:    AnMethodTypingWalkEnd
57  *
58  * PARAMETERS:  ASL_WALK_CALLBACK
59  *
60  * RETURN:      Status
61  *
62  * DESCRIPTION: Ascending callback for typing walk. Complete the method
63  *              return analysis. Check methods for:
64  *              1) Initialized local variables
65  *              2) Valid arguments
66  *              3) Return types
67  *
68  ******************************************************************************/
69
70 ACPI_STATUS
71 AnMethodTypingWalkEnd (
72     ACPI_PARSE_OBJECT       *Op,
73     UINT32                  Level,
74     void                    *Context)
75 {
76     UINT32                  ThisNodeBtype;
77
78
79     switch (Op->Asl.ParseOpcode)
80     {
81     case PARSEOP_METHOD:
82
83         Op->Asl.CompileFlags |= NODE_METHOD_TYPED;
84         break;
85
86     case PARSEOP_RETURN:
87
88         if ((Op->Asl.Child) &&
89             (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
90         {
91             ThisNodeBtype = AnGetBtype (Op->Asl.Child);
92
93             if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_METHODCALL) &&
94                 (ThisNodeBtype == (ACPI_UINT32_MAX -1)))
95             {
96                 /*
97                  * The called method is untyped at this time (typically a
98                  * forward reference).
99                  *
100                  * Check for a recursive method call first.
101                  */
102                 if (Op->Asl.ParentMethod != Op->Asl.Child->Asl.Node->Op)
103                 {
104                     /* We must type the method here */
105
106                     TrWalkParseTree (Op->Asl.Child->Asl.Node->Op,
107                         ASL_WALK_VISIT_UPWARD, NULL,
108                         AnMethodTypingWalkEnd, NULL);
109
110                     ThisNodeBtype = AnGetBtype (Op->Asl.Child);
111                 }
112             }
113
114             /* Returns a value, save the value type */
115
116             if (Op->Asl.ParentMethod)
117             {
118                 Op->Asl.ParentMethod->Asl.AcpiBtype |= ThisNodeBtype;
119             }
120         }
121         break;
122
123     default:
124
125         break;
126     }
127
128     return (AE_OK);
129 }
130
131
132 /*******************************************************************************
133  *
134  * FUNCTION:    AnOperandTypecheckWalkEnd
135  *
136  * PARAMETERS:  ASL_WALK_CALLBACK
137  *
138  * RETURN:      Status
139  *
140  * DESCRIPTION: Ascending callback for analysis walk. Complete method
141  *              return analysis.
142  *
143  ******************************************************************************/
144
145 ACPI_STATUS
146 AnOperandTypecheckWalkEnd (
147     ACPI_PARSE_OBJECT       *Op,
148     UINT32                  Level,
149     void                    *Context)
150 {
151     const ACPI_OPCODE_INFO  *OpInfo;
152     UINT32                  RuntimeArgTypes;
153     UINT32                  RuntimeArgTypes2;
154     UINT32                  RequiredBtypes;
155     UINT32                  ThisNodeBtype;
156     UINT32                  CommonBtypes;
157     UINT32                  OpcodeClass;
158     ACPI_PARSE_OBJECT       *ArgOp;
159     UINT32                  ArgType;
160
161
162     switch (Op->Asl.AmlOpcode)
163     {
164     case AML_RAW_DATA_BYTE:
165     case AML_RAW_DATA_WORD:
166     case AML_RAW_DATA_DWORD:
167     case AML_RAW_DATA_QWORD:
168     case AML_RAW_DATA_BUFFER:
169     case AML_RAW_DATA_CHAIN:
170     case AML_PACKAGE_LENGTH:
171     case AML_UNASSIGNED_OPCODE:
172     case AML_DEFAULT_ARG_OP:
173
174         /* Ignore the internal (compiler-only) AML opcodes */
175
176         return (AE_OK);
177
178     default:
179
180         break;
181     }
182
183     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
184     if (!OpInfo)
185     {
186         return (AE_OK);
187     }
188
189     ArgOp           = Op->Asl.Child;
190     RuntimeArgTypes = OpInfo->RuntimeArgs;
191     OpcodeClass     = OpInfo->Class;
192
193 #ifdef ASL_ERROR_NAMED_OBJECT_IN_WHILE
194     /*
195      * Update 11/2008: In practice, we can't perform this check. A simple
196      * analysis is not sufficient. Also, it can cause errors when compiling
197      * disassembled code because of the way Switch operators are implemented
198      * (a While(One) loop with a named temp variable created within.)
199      */
200
201     /*
202      * If we are creating a named object, check if we are within a while loop
203      * by checking if the parent is a WHILE op. This is a simple analysis, but
204      * probably sufficient for many cases.
205      *
206      * Allow Scope(), Buffer(), and Package().
207      */
208     if (((OpcodeClass == AML_CLASS_NAMED_OBJECT) && (Op->Asl.AmlOpcode != AML_SCOPE_OP)) ||
209         ((OpcodeClass == AML_CLASS_CREATE) && (OpInfo->Flags & AML_NSNODE)))
210     {
211         if (Op->Asl.Parent->Asl.AmlOpcode == AML_WHILE_OP)
212         {
213             AslError (ASL_ERROR, ASL_MSG_NAMED_OBJECT_IN_WHILE, Op, NULL);
214         }
215     }
216 #endif
217
218     /*
219      * Special case for control opcodes IF/RETURN/WHILE since they
220      * have no runtime arg list (at this time)
221      */
222     switch (Op->Asl.AmlOpcode)
223     {
224     case AML_IF_OP:
225     case AML_WHILE_OP:
226     case AML_RETURN_OP:
227
228         if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
229         {
230             /* Check for an internal method */
231
232             if (AnIsInternalMethod (ArgOp))
233             {
234                 return (AE_OK);
235             }
236
237             /* The lone arg is a method call, check it */
238
239             RequiredBtypes = AnMapArgTypeToBtype (ARGI_INTEGER);
240             if (Op->Asl.AmlOpcode == AML_RETURN_OP)
241             {
242                 RequiredBtypes = 0xFFFFFFFF;
243             }
244
245             ThisNodeBtype = AnGetBtype (ArgOp);
246             if (ThisNodeBtype == ACPI_UINT32_MAX)
247             {
248                 return (AE_OK);
249             }
250             AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
251                 RequiredBtypes, ThisNodeBtype);
252         }
253         return (AE_OK);
254
255     default:
256
257         break;
258     }
259
260     /* Ignore the non-executable opcodes */
261
262     if (RuntimeArgTypes == ARGI_INVALID_OPCODE)
263     {
264         return (AE_OK);
265     }
266
267     switch (OpcodeClass)
268     {
269     case AML_CLASS_EXECUTE:
270     case AML_CLASS_CREATE:
271     case AML_CLASS_CONTROL:
272     case AML_CLASS_RETURN_VALUE:
273
274         /* TBD: Change class or fix typechecking for these */
275
276         if ((Op->Asl.AmlOpcode == AML_BUFFER_OP)        ||
277             (Op->Asl.AmlOpcode == AML_PACKAGE_OP)       ||
278             (Op->Asl.AmlOpcode == AML_VAR_PACKAGE_OP))
279         {
280             break;
281         }
282
283         /* Reverse the runtime argument list */
284
285         RuntimeArgTypes2 = 0;
286         while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes)))
287         {
288             RuntimeArgTypes2 <<= ARG_TYPE_WIDTH;
289             RuntimeArgTypes2 |= ArgType;
290             INCREMENT_ARG_LIST (RuntimeArgTypes);
291         }
292
293         while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2)))
294         {
295             RequiredBtypes = AnMapArgTypeToBtype (ArgType);
296
297             ThisNodeBtype = AnGetBtype (ArgOp);
298             if (ThisNodeBtype == ACPI_UINT32_MAX)
299             {
300                 goto NextArgument;
301             }
302
303             /* Examine the arg based on the required type of the arg */
304
305             switch (ArgType)
306             {
307             case ARGI_TARGETREF:
308
309                 if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO)
310                 {
311                     /* ZERO is the placeholder for "don't store result" */
312
313                     ThisNodeBtype = RequiredBtypes;
314                     break;
315                 }
316
317                 if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER)
318                 {
319                     /*
320                      * This is the case where an original reference to a resource
321                      * descriptor field has been replaced by an (Integer) offset.
322                      * These named fields are supported at compile-time only;
323                      * the names are not passed to the interpreter (via the AML).
324                      */
325                     if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
326                         (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
327                     {
328                         AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD, ArgOp, NULL);
329                     }
330                     else
331                     {
332                         AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, NULL);
333                     }
334                     break;
335                 }
336
337                 if ((ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) ||
338                     (ArgOp->Asl.ParseOpcode == PARSEOP_DEREFOF))
339                 {
340                     break;
341                 }
342
343                 ThisNodeBtype = RequiredBtypes;
344                 break;
345
346
347             case ARGI_REFERENCE:            /* References */
348             case ARGI_INTEGER_REF:
349             case ARGI_OBJECT_REF:
350             case ARGI_DEVICE_REF:
351
352                 switch (ArgOp->Asl.ParseOpcode)
353                 {
354                 case PARSEOP_LOCAL0:
355                 case PARSEOP_LOCAL1:
356                 case PARSEOP_LOCAL2:
357                 case PARSEOP_LOCAL3:
358                 case PARSEOP_LOCAL4:
359                 case PARSEOP_LOCAL5:
360                 case PARSEOP_LOCAL6:
361                 case PARSEOP_LOCAL7:
362
363                     /* TBD: implement analysis of current value (type) of the local */
364                     /* For now, just treat any local as a typematch */
365
366                     /*ThisNodeBtype = RequiredBtypes;*/
367                     break;
368
369                 case PARSEOP_ARG0:
370                 case PARSEOP_ARG1:
371                 case PARSEOP_ARG2:
372                 case PARSEOP_ARG3:
373                 case PARSEOP_ARG4:
374                 case PARSEOP_ARG5:
375                 case PARSEOP_ARG6:
376
377                     /* Hard to analyze argument types, sow we won't */
378                     /* For now, just treat any arg as a typematch */
379
380                     /* ThisNodeBtype = RequiredBtypes; */
381                     break;
382
383                 case PARSEOP_DEBUG:
384
385                     break;
386
387                 case PARSEOP_REFOF:
388                 case PARSEOP_INDEX:
389                 default:
390
391                     break;
392
393                 }
394                 break;
395
396             case ARGI_INTEGER:
397             default:
398
399                 break;
400             }
401
402
403             CommonBtypes = ThisNodeBtype & RequiredBtypes;
404
405             if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
406             {
407                 if (AnIsInternalMethod (ArgOp))
408                 {
409                     return (AE_OK);
410                 }
411
412                 /* Check a method call for a valid return value */
413
414                 AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
415                     RequiredBtypes, ThisNodeBtype);
416             }
417
418             /*
419              * Now check if the actual type(s) match at least one
420              * bit to the required type
421              */
422             else if (!CommonBtypes)
423             {
424                 /* No match -- this is a type mismatch error */
425
426                 AnFormatBtype (StringBuffer, ThisNodeBtype);
427                 AnFormatBtype (StringBuffer2, RequiredBtypes);
428
429                 sprintf (MsgBuffer, "[%s] found, %s operator requires [%s]",
430                             StringBuffer, OpInfo->Name, StringBuffer2);
431
432                 AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer);
433             }
434
435         NextArgument:
436             ArgOp = ArgOp->Asl.Next;
437             INCREMENT_ARG_LIST (RuntimeArgTypes2);
438         }
439         break;
440
441     default:
442
443         break;
444     }
445
446     return (AE_OK);
447 }
448
449
450 /*******************************************************************************
451  *
452  * FUNCTION:    AnOtherSemanticAnalysisWalkBegin
453  *
454  * PARAMETERS:  ASL_WALK_CALLBACK
455  *
456  * RETURN:      Status
457  *
458  * DESCRIPTION: Descending callback for the analysis walk. Checks for
459  *              miscellaneous issues in the code.
460  *
461  ******************************************************************************/
462
463 ACPI_STATUS
464 AnOtherSemanticAnalysisWalkBegin (
465     ACPI_PARSE_OBJECT       *Op,
466     UINT32                  Level,
467     void                    *Context)
468 {
469     ACPI_PARSE_OBJECT       *ArgNode;
470     ACPI_PARSE_OBJECT       *PrevArgNode = NULL;
471     const ACPI_OPCODE_INFO  *OpInfo;
472     ACPI_NAMESPACE_NODE     *Node;
473
474
475     OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
476
477     /*
478      * Determine if an execution class operator actually does something by
479      * checking if it has a target and/or the function return value is used.
480      * (Target is optional, so a standalone statement can actually do nothing.)
481      */
482     if ((OpInfo->Class == AML_CLASS_EXECUTE) &&
483         (OpInfo->Flags & AML_HAS_RETVAL) &&
484         (!AnIsResultUsed (Op)))
485     {
486         if (OpInfo->Flags & AML_HAS_TARGET)
487         {
488             /*
489              * Find the target node, it is always the last child. If the traget
490              * is not specified in the ASL, a default node of type Zero was
491              * created by the parser.
492              */
493             ArgNode = Op->Asl.Child;
494             while (ArgNode->Asl.Next)
495             {
496                 PrevArgNode = ArgNode;
497                 ArgNode = ArgNode->Asl.Next;
498             }
499
500             /* Divide() is the only weird case, it has two targets */
501
502             if (Op->Asl.AmlOpcode == AML_DIVIDE_OP)
503             {
504                 if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) &&
505                     (PrevArgNode) &&
506                     (PrevArgNode->Asl.ParseOpcode == PARSEOP_ZERO))
507                 {
508                     AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
509                         Op, Op->Asl.ExternalName);
510                 }
511             }
512             else if (ArgNode->Asl.ParseOpcode == PARSEOP_ZERO)
513             {
514                 AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
515                     Op, Op->Asl.ExternalName);
516             }
517         }
518         else
519         {
520             /*
521              * Has no target and the result is not used. Only a couple opcodes
522              * can have this combination.
523              */
524             switch (Op->Asl.ParseOpcode)
525             {
526             case PARSEOP_ACQUIRE:
527             case PARSEOP_WAIT:
528             case PARSEOP_LOADTABLE:
529
530                 break;
531
532             default:
533
534                 AslError (ASL_ERROR, ASL_MSG_RESULT_NOT_USED,
535                     Op, Op->Asl.ExternalName);
536                 break;
537             }
538         }
539     }
540
541
542     /*
543      * Semantic checks for individual ASL operators
544      */
545     switch (Op->Asl.ParseOpcode)
546     {
547     case PARSEOP_ACQUIRE:
548     case PARSEOP_WAIT:
549         /*
550          * Emit a warning if the timeout parameter for these operators is not
551          * ACPI_WAIT_FOREVER, and the result value from the operator is not
552          * checked, meaning that a timeout could happen, but the code
553          * would not know about it.
554          */
555
556         /* First child is the namepath, 2nd child is timeout */
557
558         ArgNode = Op->Asl.Child;
559         ArgNode = ArgNode->Asl.Next;
560
561         /*
562          * Check for the WAIT_FOREVER case - defined by the ACPI spec to be
563          * 0xFFFF or greater
564          */
565         if (((ArgNode->Asl.ParseOpcode == PARSEOP_WORDCONST) ||
566              (ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER))  &&
567              (ArgNode->Asl.Value.Integer >= (UINT64) ACPI_WAIT_FOREVER))
568         {
569             break;
570         }
571
572         /*
573          * The operation could timeout. If the return value is not used
574          * (indicates timeout occurred), issue a warning
575          */
576         if (!AnIsResultUsed (Op))
577         {
578             AslError (ASL_WARNING, ASL_MSG_TIMEOUT, ArgNode,
579                 Op->Asl.ExternalName);
580         }
581         break;
582
583     case PARSEOP_CREATEFIELD:
584         /*
585          * Check for a zero Length (NumBits) operand. NumBits is the 3rd operand
586          */
587         ArgNode = Op->Asl.Child;
588         ArgNode = ArgNode->Asl.Next;
589         ArgNode = ArgNode->Asl.Next;
590
591         if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) ||
592            ((ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER) &&
593             (ArgNode->Asl.Value.Integer == 0)))
594         {
595             AslError (ASL_ERROR, ASL_MSG_NON_ZERO, ArgNode, NULL);
596         }
597         break;
598
599     case PARSEOP_CONNECTION:
600         /*
601          * Ensure that the referenced operation region has the correct SPACE_ID.
602          * From the grammar/parser, we know the parent is a FIELD definition.
603          */
604         ArgNode = Op->Asl.Parent;       /* Field definition */
605         ArgNode = ArgNode->Asl.Child;   /* First child is the OpRegion Name */
606         Node = ArgNode->Asl.Node;       /* OpRegion namespace node */
607         if (!Node)
608         {
609             break;
610         }
611
612         ArgNode = Node->Op;             /* OpRegion definition */
613         ArgNode = ArgNode->Asl.Child;   /* First child is the OpRegion Name */
614         ArgNode = ArgNode->Asl.Next;    /* Next peer is the SPACE_ID (what we want) */
615
616         /*
617          * The Connection() operator is only valid for the following operation
618          * region SpaceIds: GeneralPurposeIo and GenericSerialBus.
619          */
620         if ((ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) &&
621             (ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS))
622         {
623             AslError (ASL_ERROR, ASL_MSG_CONNECTION_INVALID, Op, NULL);
624         }
625         break;
626
627     case PARSEOP_FIELD:
628         /*
629          * Ensure that fields for GeneralPurposeIo and GenericSerialBus
630          * contain at least one Connection() operator
631          */
632         ArgNode = Op->Asl.Child;        /* 1st child is the OpRegion Name */
633         Node = ArgNode->Asl.Node;       /* OpRegion namespace node */
634         if (!Node)
635         {
636             break;
637         }
638
639         ArgNode = Node->Op;             /* OpRegion definition */
640         ArgNode = ArgNode->Asl.Child;   /* First child is the OpRegion Name */
641         ArgNode = ArgNode->Asl.Next;    /* Next peer is the SPACE_ID (what we want) */
642
643         /* We are only interested in GeneralPurposeIo and GenericSerialBus */
644
645         if ((ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GPIO) &&
646             (ArgNode->Asl.Value.Integer != ACPI_ADR_SPACE_GSBUS))
647         {
648             break;
649         }
650
651         ArgNode = Op->Asl.Child;        /* 1st child is the OpRegion Name */
652         ArgNode = ArgNode->Asl.Next;    /* AccessType */
653         ArgNode = ArgNode->Asl.Next;    /* LockRule */
654         ArgNode = ArgNode->Asl.Next;    /* UpdateRule */
655         ArgNode = ArgNode->Asl.Next;    /* Start of FieldUnitList */
656
657         /* Walk the FieldUnitList */
658
659         while (ArgNode)
660         {
661             if (ArgNode->Asl.ParseOpcode == PARSEOP_CONNECTION)
662             {
663                 break;
664             }
665             else if (ArgNode->Asl.ParseOpcode == PARSEOP_NAMESEG)
666             {
667                 AslError (ASL_ERROR, ASL_MSG_CONNECTION_MISSING, ArgNode, NULL);
668                 break;
669             }
670
671             ArgNode = ArgNode->Asl.Next;
672         }
673         break;
674
675     default:
676
677         break;
678     }
679
680     return (AE_OK);
681 }