Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2216 Serge 1
/******************************************************************************
2
 *
3
 * Module Name: aslwalks.c - major analytical parse tree walks
4
 *
5
 *****************************************************************************/
6
 
7
/******************************************************************************
8
 *
9
 * 1. Copyright Notice
10
 *
11
 * Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp.
12
 * All rights reserved.
13
 *
14
 * 2. License
15
 *
16
 * 2.1. This is your license from Intel Corp. under its intellectual property
17
 * rights.  You may have additional license terms from the party that provided
18
 * you this software, covering your right to use that party's intellectual
19
 * property rights.
20
 *
21
 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22
 * copy of the source code appearing in this file ("Covered Code") an
23
 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24
 * base code distributed originally by Intel ("Original Intel Code") to copy,
25
 * make derivatives, distribute, use and display any portion of the Covered
26
 * Code in any form, with the right to sublicense such rights; and
27
 *
28
 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29
 * license (with the right to sublicense), under only those claims of Intel
30
 * patents that are infringed by the Original Intel Code, to make, use, sell,
31
 * offer to sell, and import the Covered Code and derivative works thereof
32
 * solely to the minimum extent necessary to exercise the above copyright
33
 * license, and in no event shall the patent license extend to any additions
34
 * to or modifications of the Original Intel Code.  No other license or right
35
 * is granted directly or by implication, estoppel or otherwise;
36
 *
37
 * The above copyright and patent license is granted only if the following
38
 * conditions are met:
39
 *
40
 * 3. Conditions
41
 *
42
 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43
 * Redistribution of source code of any substantial portion of the Covered
44
 * Code or modification with rights to further distribute source must include
45
 * the above Copyright Notice, the above License, this list of Conditions,
46
 * and the following Disclaimer and Export Compliance provision.  In addition,
47
 * Licensee must cause all Covered Code to which Licensee contributes to
48
 * contain a file documenting the changes Licensee made to create that Covered
49
 * Code and the date of any change.  Licensee must include in that file the
50
 * documentation of any changes made by any predecessor Licensee.  Licensee
51
 * must include a prominent statement that the modification is derived,
52
 * directly or indirectly, from Original Intel Code.
53
 *
54
 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55
 * Redistribution of source code of any substantial portion of the Covered
56
 * Code or modification without rights to further distribute source must
57
 * include the following Disclaimer and Export Compliance provision in the
58
 * documentation and/or other materials provided with distribution.  In
59
 * addition, Licensee may not authorize further sublicense of source of any
60
 * portion of the Covered Code, and must include terms to the effect that the
61
 * license from Licensee to its licensee is limited to the intellectual
62
 * property embodied in the software Licensee provides to its licensee, and
63
 * not to intellectual property embodied in modifications its licensee may
64
 * make.
65
 *
66
 * 3.3. Redistribution of Executable. Redistribution in executable form of any
67
 * substantial portion of the Covered Code or modification must reproduce the
68
 * above Copyright Notice, and the following Disclaimer and Export Compliance
69
 * provision in the documentation and/or other materials provided with the
70
 * distribution.
71
 *
72
 * 3.4. Intel retains all right, title, and interest in and to the Original
73
 * Intel Code.
74
 *
75
 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76
 * Intel shall be used in advertising or otherwise to promote the sale, use or
77
 * other dealings in products derived from or relating to the Covered Code
78
 * without prior written authorization from Intel.
79
 *
80
 * 4. Disclaimer and Export Compliance
81
 *
82
 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83
 * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84
 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
85
 * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
86
 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
87
 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88
 * PARTICULAR PURPOSE.
89
 *
90
 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91
 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92
 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93
 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94
 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95
 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
96
 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97
 * LIMITED REMEDY.
98
 *
99
 * 4.3. Licensee shall not export, either directly or indirectly, any of this
100
 * software or system incorporating such software without first obtaining any
101
 * required license or other approval from the U. S. Department of Commerce or
102
 * any other agency or department of the United States Government.  In the
103
 * event Licensee exports any such software from the United States or
104
 * re-exports any such software from a foreign destination, Licensee shall
105
 * ensure that the distribution and export/re-export of the software is in
106
 * compliance with all laws, regulations, orders, or other restrictions of the
107
 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108
 * any of its subsidiaries will export/re-export any technical data, process,
109
 * software, or service, directly or indirectly, to any country for which the
110
 * United States government or any agency thereof requires an export license,
111
 * other governmental approval, or letter of assurance, without first obtaining
112
 * such license, approval or letter.
113
 *
114
 *****************************************************************************/
115
 
116
 
117
#include "aslcompiler.h"
118
#include "aslcompiler.y.h"
119
#include "acparser.h"
120
#include "amlcode.h"
121
 
122
 
123
#define _COMPONENT          ACPI_COMPILER
124
        ACPI_MODULE_NAME    ("aslwalks")
125
 
126
 
127
/*******************************************************************************
128
 *
129
 * FUNCTION:    AnMethodAnalysisWalkBegin
130
 *
131
 * PARAMETERS:  ASL_WALK_CALLBACK
132
 *
133
 * RETURN:      Status
134
 *
135
 * DESCRIPTION: Descending callback for the analysis walk. Check methods for:
136
 *              1) Initialized local variables
137
 *              2) Valid arguments
138
 *              3) Return types
139
 *
140
 ******************************************************************************/
141
 
142
ACPI_STATUS
143
AnMethodAnalysisWalkBegin (
144
    ACPI_PARSE_OBJECT       *Op,
145
    UINT32                  Level,
146
    void                    *Context)
147
{
148
    ASL_ANALYSIS_WALK_INFO  *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
149
    ASL_METHOD_INFO         *MethodInfo = WalkInfo->MethodStack;
150
    ACPI_PARSE_OBJECT       *Next;
151
    UINT32                  RegisterNumber;
152
    UINT32                  i;
153
    char                    LocalName[] = "Local0";
154
    char                    ArgName[] = "Arg0";
155
    ACPI_PARSE_OBJECT       *ArgNode;
156
    ACPI_PARSE_OBJECT       *NextType;
157
    ACPI_PARSE_OBJECT       *NextParamType;
158
    UINT8                   ActualArgs = 0;
159
 
160
 
161
    switch (Op->Asl.ParseOpcode)
162
    {
163
    case PARSEOP_METHOD:
164
 
165
        TotalMethods++;
166
 
167
        /* Create and init method info */
168
 
169
        MethodInfo       = UtLocalCalloc (sizeof (ASL_METHOD_INFO));
170
        MethodInfo->Next = WalkInfo->MethodStack;
171
        MethodInfo->Op = Op;
172
 
173
        WalkInfo->MethodStack = MethodInfo;
174
 
175
        /* Get the name node, ignored here */
176
 
177
        Next = Op->Asl.Child;
178
 
179
        /* Get the NumArguments node */
180
 
181
        Next = Next->Asl.Next;
182
        MethodInfo->NumArguments = (UINT8)
183
            (((UINT8) Next->Asl.Value.Integer) & 0x07);
184
 
185
        /* Get the SerializeRule and SyncLevel nodes, ignored here */
186
 
187
        Next = Next->Asl.Next;
188
        Next = Next->Asl.Next;
189
        ArgNode = Next;
190
 
191
        /* Get the ReturnType node */
192
 
193
        Next = Next->Asl.Next;
194
 
195
        NextType = Next->Asl.Child;
196
        while (NextType)
197
        {
198
            /* Get and map each of the ReturnTypes */
199
 
200
            MethodInfo->ValidReturnTypes |= AnMapObjTypeToBtype (NextType);
201
            NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
202
            NextType = NextType->Asl.Next;
203
        }
204
 
205
        /* Get the ParameterType node */
206
 
207
        Next = Next->Asl.Next;
208
 
209
        NextType = Next->Asl.Child;
210
        while (NextType)
211
        {
212
            if (NextType->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG)
213
            {
214
                NextParamType = NextType->Asl.Child;
215
                while (NextParamType)
216
                {
217
                    MethodInfo->ValidArgTypes[ActualArgs] |= AnMapObjTypeToBtype (NextParamType);
218
                    NextParamType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
219
                    NextParamType = NextParamType->Asl.Next;
220
                }
221
            }
222
            else
223
            {
224
                MethodInfo->ValidArgTypes[ActualArgs] =
225
                    AnMapObjTypeToBtype (NextType);
226
                NextType->Asl.ParseOpcode = PARSEOP_DEFAULT_ARG;
227
                ActualArgs++;
228
            }
229
 
230
            NextType = NextType->Asl.Next;
231
        }
232
 
233
        if ((MethodInfo->NumArguments) &&
234
            (MethodInfo->NumArguments != ActualArgs))
235
        {
236
            /* error: Param list did not match number of args */
237
        }
238
 
239
        /* Allow numarguments == 0 for Function() */
240
 
241
        if ((!MethodInfo->NumArguments) && (ActualArgs))
242
        {
243
            MethodInfo->NumArguments = ActualArgs;
244
            ArgNode->Asl.Value.Integer |= ActualArgs;
245
        }
246
 
247
        /*
248
         * Actual arguments are initialized at method entry.
249
         * All other ArgX "registers" can be used as locals, so we
250
         * track their initialization.
251
         */
252
        for (i = 0; i < MethodInfo->NumArguments; i++)
253
        {
254
            MethodInfo->ArgInitialized[i] = TRUE;
255
        }
256
        break;
257
 
258
 
259
    case PARSEOP_METHODCALL:
260
 
261
        if (MethodInfo &&
262
           (Op->Asl.Node == MethodInfo->Op->Asl.Node))
263
        {
264
            AslError (ASL_REMARK, ASL_MSG_RECURSION, Op, Op->Asl.ExternalName);
265
        }
266
        break;
267
 
268
 
269
    case PARSEOP_LOCAL0:
270
    case PARSEOP_LOCAL1:
271
    case PARSEOP_LOCAL2:
272
    case PARSEOP_LOCAL3:
273
    case PARSEOP_LOCAL4:
274
    case PARSEOP_LOCAL5:
275
    case PARSEOP_LOCAL6:
276
    case PARSEOP_LOCAL7:
277
 
278
        if (!MethodInfo)
279
        {
280
            /*
281
             * Local was used outside a control method, or there was an error
282
             * in the method declaration.
283
             */
284
            AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName);
285
            return (AE_ERROR);
286
        }
287
 
288
        RegisterNumber = (Op->Asl.AmlOpcode & 0x000F);
289
 
290
        /*
291
         * If the local is being used as a target, mark the local
292
         * initialized
293
         */
294
        if (Op->Asl.CompileFlags & NODE_IS_TARGET)
295
        {
296
            MethodInfo->LocalInitialized[RegisterNumber] = TRUE;
297
        }
298
 
299
        /*
300
         * Otherwise, this is a reference, check if the local
301
         * has been previously initialized.
302
         *
303
         * The only operator that accepts an uninitialized value is ObjectType()
304
         */
305
        else if ((!MethodInfo->LocalInitialized[RegisterNumber]) &&
306
                 (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
307
        {
308
            LocalName[strlen (LocalName) -1] = (char) (RegisterNumber + 0x30);
309
            AslError (ASL_ERROR, ASL_MSG_LOCAL_INIT, Op, LocalName);
310
        }
311
        break;
312
 
313
 
314
    case PARSEOP_ARG0:
315
    case PARSEOP_ARG1:
316
    case PARSEOP_ARG2:
317
    case PARSEOP_ARG3:
318
    case PARSEOP_ARG4:
319
    case PARSEOP_ARG5:
320
    case PARSEOP_ARG6:
321
 
322
        if (!MethodInfo)
323
        {
324
            /*
325
             * Arg was used outside a control method, or there was an error
326
             * in the method declaration.
327
             */
328
            AslError (ASL_REMARK, ASL_MSG_LOCAL_OUTSIDE_METHOD, Op, Op->Asl.ExternalName);
329
            return (AE_ERROR);
330
        }
331
 
332
        RegisterNumber = (Op->Asl.AmlOpcode & 0x000F) - 8;
333
        ArgName[strlen (ArgName) -1] = (char) (RegisterNumber + 0x30);
334
 
335
        /*
336
         * If the Arg is being used as a target, mark the local
337
         * initialized
338
         */
339
        if (Op->Asl.CompileFlags & NODE_IS_TARGET)
340
        {
341
            MethodInfo->ArgInitialized[RegisterNumber] = TRUE;
342
        }
343
 
344
        /*
345
         * Otherwise, this is a reference, check if the Arg
346
         * has been previously initialized.
347
         *
348
         * The only operator that accepts an uninitialized value is ObjectType()
349
         */
350
        else if ((!MethodInfo->ArgInitialized[RegisterNumber]) &&
351
                 (Op->Asl.Parent->Asl.ParseOpcode != PARSEOP_OBJECTTYPE))
352
        {
353
            AslError (ASL_ERROR, ASL_MSG_ARG_INIT, Op, ArgName);
354
        }
355
 
356
        /* Flag this arg if it is not a "real" argument to the method */
357
 
358
        if (RegisterNumber >= MethodInfo->NumArguments)
359
        {
360
            AslError (ASL_REMARK, ASL_MSG_NOT_PARAMETER, Op, ArgName);
361
        }
362
        break;
363
 
364
 
365
    case PARSEOP_RETURN:
366
 
367
        if (!MethodInfo)
368
        {
369
            /*
370
             * Probably was an error in the method declaration,
371
             * no additional error here
372
             */
373
            ACPI_WARNING ((AE_INFO, "%p, No parent method", Op));
374
            return (AE_ERROR);
375
        }
376
 
377
        /*
378
         * A child indicates a possible return value. A simple Return or
379
         * Return() is marked with NODE_IS_NULL_RETURN by the parser so
380
         * that it is not counted as a "real" return-with-value, although
381
         * the AML code that is actually emitted is Return(0). The AML
382
         * definition of Return has a required parameter, so we are
383
         * forced to convert a null return to Return(0).
384
         */
385
        if ((Op->Asl.Child) &&
386
            (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) &&
387
            (!(Op->Asl.Child->Asl.CompileFlags & NODE_IS_NULL_RETURN)))
388
        {
389
            MethodInfo->NumReturnWithValue++;
390
        }
391
        else
392
        {
393
            MethodInfo->NumReturnNoValue++;
394
        }
395
        break;
396
 
397
 
398
    case PARSEOP_BREAK:
399
    case PARSEOP_CONTINUE:
400
 
401
        Next = Op->Asl.Parent;
402
        while (Next)
403
        {
404
            if (Next->Asl.ParseOpcode == PARSEOP_WHILE)
405
            {
406
                break;
407
            }
408
            Next = Next->Asl.Parent;
409
        }
410
 
411
        if (!Next)
412
        {
413
            AslError (ASL_ERROR, ASL_MSG_NO_WHILE, Op, NULL);
414
        }
415
        break;
416
 
417
 
418
    case PARSEOP_STALL:
419
 
420
        /* We can range check if the argument is an integer */
421
 
422
        if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_INTEGER) &&
423
            (Op->Asl.Child->Asl.Value.Integer > ACPI_UINT8_MAX))
424
        {
425
            AslError (ASL_ERROR, ASL_MSG_INVALID_TIME, Op, NULL);
426
        }
427
        break;
428
 
429
 
430
    case PARSEOP_DEVICE:
431
    case PARSEOP_EVENT:
432
    case PARSEOP_MUTEX:
433
    case PARSEOP_OPERATIONREGION:
434
    case PARSEOP_POWERRESOURCE:
435
    case PARSEOP_PROCESSOR:
436
    case PARSEOP_THERMALZONE:
437
 
438
        /*
439
         * The first operand is a name to be created in the namespace.
440
         * Check against the reserved list.
441
         */
442
        i = ApCheckForPredefinedName (Op, Op->Asl.NameSeg);
443
        if (i < ACPI_VALID_RESERVED_NAME_MAX)
444
        {
445
            AslError (ASL_ERROR, ASL_MSG_RESERVED_USE, Op, Op->Asl.ExternalName);
446
        }
447
        break;
448
 
449
 
450
    case PARSEOP_NAME:
451
 
452
        /* Typecheck any predefined names statically defined with Name() */
453
 
454
        ApCheckForPredefinedObject (Op, Op->Asl.NameSeg);
455
 
456
        /* Special typechecking for _HID */
457
 
458
        if (!ACPI_STRCMP (METHOD_NAME__HID, Op->Asl.NameSeg))
459
        {
460
            Next = Op->Asl.Child->Asl.Next;
461
            AnCheckId (Next, ASL_TYPE_HID);
462
        }
463
 
464
        /* Special typechecking for _CID */
465
 
466
        else if (!ACPI_STRCMP (METHOD_NAME__CID, Op->Asl.NameSeg))
467
        {
468
            Next = Op->Asl.Child->Asl.Next;
469
 
470
            if ((Next->Asl.ParseOpcode == PARSEOP_PACKAGE) ||
471
                (Next->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE))
472
            {
473
                Next = Next->Asl.Child;
474
                while (Next)
475
                {
476
                    AnCheckId (Next, ASL_TYPE_CID);
477
                    Next = Next->Asl.Next;
478
                }
479
            }
480
            else
481
            {
482
                AnCheckId (Next, ASL_TYPE_CID);
483
            }
484
        }
485
        break;
486
 
487
 
488
    default:
489
        break;
490
    }
491
 
492
    return (AE_OK);
493
}
494
 
495
 
496
/*******************************************************************************
497
 *
498
 * FUNCTION:    AnMethodAnalysisWalkEnd
499
 *
500
 * PARAMETERS:  ASL_WALK_CALLBACK
501
 *
502
 * RETURN:      Status
503
 *
504
 * DESCRIPTION: Ascending callback for analysis walk. Complete method
505
 *              return analysis.
506
 *
507
 ******************************************************************************/
508
 
509
ACPI_STATUS
510
AnMethodAnalysisWalkEnd (
511
    ACPI_PARSE_OBJECT       *Op,
512
    UINT32                  Level,
513
    void                    *Context)
514
{
515
    ASL_ANALYSIS_WALK_INFO  *WalkInfo = (ASL_ANALYSIS_WALK_INFO *) Context;
516
    ASL_METHOD_INFO         *MethodInfo = WalkInfo->MethodStack;
517
 
518
 
519
    switch (Op->Asl.ParseOpcode)
520
    {
521
    case PARSEOP_METHOD:
522
    case PARSEOP_RETURN:
523
        if (!MethodInfo)
524
        {
525
            printf ("No method info for method! [%s]\n", Op->Asl.Namepath);
526
            AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Op,
527
                "No method info for this method");
528
 
529
            CmCleanupAndExit ();
530
            return (AE_AML_INTERNAL);
531
        }
532
        break;
533
 
534
    default:
535
        break;
536
    }
537
 
538
    switch (Op->Asl.ParseOpcode)
539
    {
540
    case PARSEOP_METHOD:
541
 
542
        WalkInfo->MethodStack = MethodInfo->Next;
543
 
544
        /*
545
         * Check if there is no return statement at the end of the
546
         * method AND we can actually get there -- i.e., the execution
547
         * of the method can possibly terminate without a return statement.
548
         */
549
        if ((!AnLastStatementIsReturn (Op)) &&
550
            (!(Op->Asl.CompileFlags & NODE_HAS_NO_EXIT)))
551
        {
552
            /*
553
             * No return statement, and execution can possibly exit
554
             * via this path. This is equivalent to Return ()
555
             */
556
            MethodInfo->NumReturnNoValue++;
557
        }
558
 
559
        /*
560
         * Check for case where some return statements have a return value
561
         * and some do not. Exit without a return statement is a return with
562
         * no value
563
         */
564
        if (MethodInfo->NumReturnNoValue &&
565
            MethodInfo->NumReturnWithValue)
566
        {
567
            AslError (ASL_WARNING, ASL_MSG_RETURN_TYPES, Op,
568
                Op->Asl.ExternalName);
569
        }
570
 
571
        /*
572
         * If there are any RETURN() statements with no value, or there is a
573
         * control path that allows the method to exit without a return value,
574
         * we mark the method as a method that does not return a value. This
575
         * knowledge can be used to check method invocations that expect a
576
         * returned value.
577
         */
578
        if (MethodInfo->NumReturnNoValue)
579
        {
580
            if (MethodInfo->NumReturnWithValue)
581
            {
582
                Op->Asl.CompileFlags |= NODE_METHOD_SOME_NO_RETVAL;
583
            }
584
            else
585
            {
586
                Op->Asl.CompileFlags |= NODE_METHOD_NO_RETVAL;
587
            }
588
        }
589
 
590
        /*
591
         * Check predefined method names for correct return behavior
592
         * and correct number of arguments. Also, some special checks
593
         * For GPE and _REG methods.
594
         */
595
        if (ApCheckForPredefinedMethod (Op, MethodInfo))
596
        {
597
            /* Special check for two names like _L01 and _E01 in same scope */
598
 
599
            ApCheckForGpeNameConflict (Op);
600
 
601
            /*
602
             * Special check for _REG: Must have an operation region definition
603
             * within the same scope!
604
             */
605
            ApCheckRegMethod (Op);
606
        }
607
 
608
        ACPI_FREE (MethodInfo);
609
        break;
610
 
611
 
612
    case PARSEOP_NAME:
613
 
614
         /* Special check for two names like _L01 and _E01 in same scope */
615
 
616
        ApCheckForGpeNameConflict (Op);
617
        break;
618
 
619
 
620
    case PARSEOP_RETURN:
621
 
622
        /*
623
         * If the parent is a predefined method name, attempt to typecheck
624
         * the return value. Only static types can be validated.
625
         */
626
        ApCheckPredefinedReturnValue (Op, MethodInfo);
627
 
628
        /*
629
         * The parent block does not "exit" and continue execution -- the
630
         * method is terminated here with the Return() statement.
631
         */
632
        Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
633
 
634
        /* Used in the "typing" pass later */
635
 
636
        Op->Asl.ParentMethod = MethodInfo->Op;
637
 
638
        /*
639
         * If there is a peer node after the return statement, then this
640
         * node is unreachable code -- i.e., it won't be executed because of
641
         * the preceeding Return() statement.
642
         */
643
        if (Op->Asl.Next)
644
        {
645
            AslError (ASL_WARNING, ASL_MSG_UNREACHABLE_CODE, Op->Asl.Next, NULL);
646
        }
647
        break;
648
 
649
 
650
    case PARSEOP_IF:
651
 
652
        if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
653
            (Op->Asl.Next) &&
654
            (Op->Asl.Next->Asl.ParseOpcode == PARSEOP_ELSE))
655
        {
656
            /*
657
             * This IF has a corresponding ELSE. The IF block has no exit,
658
             * (it contains an unconditional Return)
659
             * mark the ELSE block to remember this fact.
660
             */
661
            Op->Asl.Next->Asl.CompileFlags |= NODE_IF_HAS_NO_EXIT;
662
        }
663
        break;
664
 
665
 
666
    case PARSEOP_ELSE:
667
 
668
        if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
669
            (Op->Asl.CompileFlags & NODE_IF_HAS_NO_EXIT))
670
        {
671
            /*
672
             * This ELSE block has no exit and the corresponding IF block
673
             * has no exit either. Therefore, the parent node has no exit.
674
             */
675
            Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
676
        }
677
        break;
678
 
679
 
680
    default:
681
 
682
        if ((Op->Asl.CompileFlags & NODE_HAS_NO_EXIT) &&
683
            (Op->Asl.Parent))
684
        {
685
            /* If this node has no exit, then the parent has no exit either */
686
 
687
            Op->Asl.Parent->Asl.CompileFlags |= NODE_HAS_NO_EXIT;
688
        }
689
        break;
690
    }
691
 
692
    return (AE_OK);
693
}
694
 
695
 
696
/*******************************************************************************
697
 *
698
 * FUNCTION:    AnMethodTypingWalkEnd
699
 *
700
 * PARAMETERS:  ASL_WALK_CALLBACK
701
 *
702
 * RETURN:      Status
703
 *
704
 * DESCRIPTION: Ascending callback for typing walk. Complete the method
705
 *              return analysis. Check methods for:
706
 *              1) Initialized local variables
707
 *              2) Valid arguments
708
 *              3) Return types
709
 *
710
 ******************************************************************************/
711
 
712
ACPI_STATUS
713
AnMethodTypingWalkEnd (
714
    ACPI_PARSE_OBJECT       *Op,
715
    UINT32                  Level,
716
    void                    *Context)
717
{
718
    UINT32                  ThisNodeBtype;
719
 
720
 
721
    switch (Op->Asl.ParseOpcode)
722
    {
723
    case PARSEOP_METHOD:
724
 
725
        Op->Asl.CompileFlags |= NODE_METHOD_TYPED;
726
        break;
727
 
728
    case PARSEOP_RETURN:
729
 
730
        if ((Op->Asl.Child) &&
731
            (Op->Asl.Child->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG))
732
        {
733
            ThisNodeBtype = AnGetBtype (Op->Asl.Child);
734
 
735
            if ((Op->Asl.Child->Asl.ParseOpcode == PARSEOP_METHODCALL) &&
736
                (ThisNodeBtype == (ACPI_UINT32_MAX -1)))
737
            {
738
                /*
739
                 * The called method is untyped at this time (typically a
740
                 * forward reference).
741
                 *
742
                 * Check for a recursive method call first.
743
                 */
744
                if (Op->Asl.ParentMethod != Op->Asl.Child->Asl.Node->Op)
745
                {
746
                    /* We must type the method here */
747
 
748
                    TrWalkParseTree (Op->Asl.Child->Asl.Node->Op,
749
                        ASL_WALK_VISIT_UPWARD, NULL,
750
                        AnMethodTypingWalkEnd, NULL);
751
 
752
                    ThisNodeBtype = AnGetBtype (Op->Asl.Child);
753
                }
754
            }
755
 
756
            /* Returns a value, save the value type */
757
 
758
            if (Op->Asl.ParentMethod)
759
            {
760
                Op->Asl.ParentMethod->Asl.AcpiBtype |= ThisNodeBtype;
761
            }
762
        }
763
        break;
764
 
765
    default:
766
        break;
767
    }
768
 
769
    return (AE_OK);
770
}
771
 
772
 
773
/*******************************************************************************
774
 *
775
 * FUNCTION:    AnOperandTypecheckWalkEnd
776
 *
777
 * PARAMETERS:  ASL_WALK_CALLBACK
778
 *
779
 * RETURN:      Status
780
 *
781
 * DESCRIPTION: Ascending callback for analysis walk. Complete method
782
 *              return analysis.
783
 *
784
 ******************************************************************************/
785
 
786
ACPI_STATUS
787
AnOperandTypecheckWalkEnd (
788
    ACPI_PARSE_OBJECT       *Op,
789
    UINT32                  Level,
790
    void                    *Context)
791
{
792
    const ACPI_OPCODE_INFO  *OpInfo;
793
    UINT32                  RuntimeArgTypes;
794
    UINT32                  RuntimeArgTypes2;
795
    UINT32                  RequiredBtypes;
796
    UINT32                  ThisNodeBtype;
797
    UINT32                  CommonBtypes;
798
    UINT32                  OpcodeClass;
799
    ACPI_PARSE_OBJECT       *ArgOp;
800
    UINT32                  ArgType;
801
 
802
 
803
    switch (Op->Asl.AmlOpcode)
804
    {
805
    case AML_RAW_DATA_BYTE:
806
    case AML_RAW_DATA_WORD:
807
    case AML_RAW_DATA_DWORD:
808
    case AML_RAW_DATA_QWORD:
809
    case AML_RAW_DATA_BUFFER:
810
    case AML_RAW_DATA_CHAIN:
811
    case AML_PACKAGE_LENGTH:
812
    case AML_UNASSIGNED_OPCODE:
813
    case AML_DEFAULT_ARG_OP:
814
 
815
        /* Ignore the internal (compiler-only) AML opcodes */
816
 
817
        return (AE_OK);
818
 
819
    default:
820
        break;
821
    }
822
 
823
    OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
824
    if (!OpInfo)
825
    {
826
        return (AE_OK);
827
    }
828
 
829
    ArgOp           = Op->Asl.Child;
830
    RuntimeArgTypes = OpInfo->RuntimeArgs;
831
    OpcodeClass     = OpInfo->Class;
832
 
833
#ifdef ASL_ERROR_NAMED_OBJECT_IN_WHILE
834
    /*
835
     * Update 11/2008: In practice, we can't perform this check. A simple
836
     * analysis is not sufficient. Also, it can cause errors when compiling
837
     * disassembled code because of the way Switch operators are implemented
838
     * (a While(One) loop with a named temp variable created within.)
839
     */
840
 
841
    /*
842
     * If we are creating a named object, check if we are within a while loop
843
     * by checking if the parent is a WHILE op. This is a simple analysis, but
844
     * probably sufficient for many cases.
845
     *
846
     * Allow Scope(), Buffer(), and Package().
847
     */
848
    if (((OpcodeClass == AML_CLASS_NAMED_OBJECT) && (Op->Asl.AmlOpcode != AML_SCOPE_OP)) ||
849
        ((OpcodeClass == AML_CLASS_CREATE) && (OpInfo->Flags & AML_NSNODE)))
850
    {
851
        if (Op->Asl.Parent->Asl.AmlOpcode == AML_WHILE_OP)
852
        {
853
            AslError (ASL_ERROR, ASL_MSG_NAMED_OBJECT_IN_WHILE, Op, NULL);
854
        }
855
    }
856
#endif
857
 
858
    /*
859
     * Special case for control opcodes IF/RETURN/WHILE since they
860
     * have no runtime arg list (at this time)
861
     */
862
    switch (Op->Asl.AmlOpcode)
863
    {
864
    case AML_IF_OP:
865
    case AML_WHILE_OP:
866
    case AML_RETURN_OP:
867
 
868
        if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
869
        {
870
            /* Check for an internal method */
871
 
872
            if (AnIsInternalMethod (ArgOp))
873
            {
874
                return (AE_OK);
875
            }
876
 
877
            /* The lone arg is a method call, check it */
878
 
879
            RequiredBtypes = AnMapArgTypeToBtype (ARGI_INTEGER);
880
            if (Op->Asl.AmlOpcode == AML_RETURN_OP)
881
            {
882
                RequiredBtypes = 0xFFFFFFFF;
883
            }
884
 
885
            ThisNodeBtype = AnGetBtype (ArgOp);
886
            if (ThisNodeBtype == ACPI_UINT32_MAX)
887
            {
888
                return (AE_OK);
889
            }
890
            AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
891
                RequiredBtypes, ThisNodeBtype);
892
        }
893
        return (AE_OK);
894
 
895
    default:
896
        break;
897
    }
898
 
899
    /* Ignore the non-executable opcodes */
900
 
901
    if (RuntimeArgTypes == ARGI_INVALID_OPCODE)
902
    {
903
        return (AE_OK);
904
    }
905
 
906
    switch (OpcodeClass)
907
    {
908
    case AML_CLASS_EXECUTE:
909
    case AML_CLASS_CREATE:
910
    case AML_CLASS_CONTROL:
911
    case AML_CLASS_RETURN_VALUE:
912
 
913
        /* TBD: Change class or fix typechecking for these */
914
 
915
        if ((Op->Asl.AmlOpcode == AML_BUFFER_OP)        ||
916
            (Op->Asl.AmlOpcode == AML_PACKAGE_OP)       ||
917
            (Op->Asl.AmlOpcode == AML_VAR_PACKAGE_OP))
918
        {
919
            break;
920
        }
921
 
922
        /* Reverse the runtime argument list */
923
 
924
        RuntimeArgTypes2 = 0;
925
        while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes)))
926
        {
927
            RuntimeArgTypes2 <<= ARG_TYPE_WIDTH;
928
            RuntimeArgTypes2 |= ArgType;
929
            INCREMENT_ARG_LIST (RuntimeArgTypes);
930
        }
931
 
932
        while ((ArgType = GET_CURRENT_ARG_TYPE (RuntimeArgTypes2)))
933
        {
934
            RequiredBtypes = AnMapArgTypeToBtype (ArgType);
935
 
936
            ThisNodeBtype = AnGetBtype (ArgOp);
937
            if (ThisNodeBtype == ACPI_UINT32_MAX)
938
            {
939
                goto NextArgument;
940
            }
941
 
942
            /* Examine the arg based on the required type of the arg */
943
 
944
            switch (ArgType)
945
            {
946
            case ARGI_TARGETREF:
947
 
948
                if (ArgOp->Asl.ParseOpcode == PARSEOP_ZERO)
949
                {
950
                    /* ZERO is the placeholder for "don't store result" */
951
 
952
                    ThisNodeBtype = RequiredBtypes;
953
                    break;
954
                }
955
 
956
                if (ArgOp->Asl.ParseOpcode == PARSEOP_INTEGER)
957
                {
958
                    /*
959
                     * This is the case where an original reference to a resource
960
                     * descriptor field has been replaced by an (Integer) offset.
961
                     * These named fields are supported at compile-time only;
962
                     * the names are not passed to the interpreter (via the AML).
963
                     */
964
                    if ((ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE_FIELD) ||
965
                        (ArgOp->Asl.Node->Type == ACPI_TYPE_LOCAL_RESOURCE))
966
                    {
967
                        AslError (ASL_ERROR, ASL_MSG_RESOURCE_FIELD, ArgOp, NULL);
968
                    }
969
                    else
970
                    {
971
                        AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, NULL);
972
                    }
973
                    break;
974
                }
975
 
976
                if ((ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL) ||
977
                    (ArgOp->Asl.ParseOpcode == PARSEOP_DEREFOF))
978
                {
979
                    break;
980
                }
981
 
982
                ThisNodeBtype = RequiredBtypes;
983
                break;
984
 
985
 
986
            case ARGI_REFERENCE:            /* References */
987
            case ARGI_INTEGER_REF:
988
            case ARGI_OBJECT_REF:
989
            case ARGI_DEVICE_REF:
990
 
991
                switch (ArgOp->Asl.ParseOpcode)
992
                {
993
                case PARSEOP_LOCAL0:
994
                case PARSEOP_LOCAL1:
995
                case PARSEOP_LOCAL2:
996
                case PARSEOP_LOCAL3:
997
                case PARSEOP_LOCAL4:
998
                case PARSEOP_LOCAL5:
999
                case PARSEOP_LOCAL6:
1000
                case PARSEOP_LOCAL7:
1001
 
1002
                    /* TBD: implement analysis of current value (type) of the local */
1003
                    /* For now, just treat any local as a typematch */
1004
 
1005
                    /*ThisNodeBtype = RequiredBtypes;*/
1006
                    break;
1007
 
1008
                case PARSEOP_ARG0:
1009
                case PARSEOP_ARG1:
1010
                case PARSEOP_ARG2:
1011
                case PARSEOP_ARG3:
1012
                case PARSEOP_ARG4:
1013
                case PARSEOP_ARG5:
1014
                case PARSEOP_ARG6:
1015
 
1016
                    /* Hard to analyze argument types, sow we won't */
1017
                    /* For now, just treat any arg as a typematch */
1018
 
1019
                    /* ThisNodeBtype = RequiredBtypes; */
1020
                    break;
1021
 
1022
                case PARSEOP_DEBUG:
1023
                    break;
1024
 
1025
                case PARSEOP_REFOF:
1026
                case PARSEOP_INDEX:
1027
                default:
1028
                    break;
1029
 
1030
                }
1031
                break;
1032
 
1033
            case ARGI_INTEGER:
1034
            default:
1035
                break;
1036
            }
1037
 
1038
 
1039
            CommonBtypes = ThisNodeBtype & RequiredBtypes;
1040
 
1041
            if (ArgOp->Asl.ParseOpcode == PARSEOP_METHODCALL)
1042
            {
1043
                if (AnIsInternalMethod (ArgOp))
1044
                {
1045
                    return (AE_OK);
1046
                }
1047
 
1048
                /* Check a method call for a valid return value */
1049
 
1050
                AnCheckMethodReturnValue (Op, OpInfo, ArgOp,
1051
                    RequiredBtypes, ThisNodeBtype);
1052
            }
1053
 
1054
            /*
1055
             * Now check if the actual type(s) match at least one
1056
             * bit to the required type
1057
             */
1058
            else if (!CommonBtypes)
1059
            {
1060
                /* No match -- this is a type mismatch error */
1061
 
1062
                AnFormatBtype (StringBuffer, ThisNodeBtype);
1063
                AnFormatBtype (StringBuffer2, RequiredBtypes);
1064
 
1065
                sprintf (MsgBuffer, "[%s] found, %s operator requires [%s]",
1066
                            StringBuffer, OpInfo->Name, StringBuffer2);
1067
 
1068
                AslError (ASL_ERROR, ASL_MSG_INVALID_TYPE, ArgOp, MsgBuffer);
1069
            }
1070
 
1071
        NextArgument:
1072
            ArgOp = ArgOp->Asl.Next;
1073
            INCREMENT_ARG_LIST (RuntimeArgTypes2);
1074
        }
1075
        break;
1076
 
1077
    default:
1078
        break;
1079
    }
1080
 
1081
    return (AE_OK);
1082
}
1083
 
1084
 
1085
/*******************************************************************************
1086
 *
1087
 * FUNCTION:    AnOtherSemanticAnalysisWalkBegin
1088
 *
1089
 * PARAMETERS:  ASL_WALK_CALLBACK
1090
 *
1091
 * RETURN:      Status
1092
 *
1093
 * DESCRIPTION: Descending callback for the analysis walk. Checks for
1094
 *              miscellaneous issues in the code.
1095
 *
1096
 ******************************************************************************/
1097
 
1098
ACPI_STATUS
1099
AnOtherSemanticAnalysisWalkBegin (
1100
    ACPI_PARSE_OBJECT       *Op,
1101
    UINT32                  Level,
1102
    void                    *Context)
1103
{
1104
    ACPI_PARSE_OBJECT       *ArgNode;
1105
    ACPI_PARSE_OBJECT       *PrevArgNode = NULL;
1106
    const ACPI_OPCODE_INFO  *OpInfo;
1107
 
1108
 
1109
    OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
1110
 
1111
    /*
1112
     * Determine if an execution class operator actually does something by
1113
     * checking if it has a target and/or the function return value is used.
1114
     * (Target is optional, so a standalone statement can actually do nothing.)
1115
     */
1116
    if ((OpInfo->Class == AML_CLASS_EXECUTE) &&
1117
        (OpInfo->Flags & AML_HAS_RETVAL) &&
1118
        (!AnIsResultUsed (Op)))
1119
    {
1120
        if (OpInfo->Flags & AML_HAS_TARGET)
1121
        {
1122
            /*
1123
             * Find the target node, it is always the last child. If the traget
1124
             * is not specified in the ASL, a default node of type Zero was
1125
             * created by the parser.
1126
             */
1127
            ArgNode = Op->Asl.Child;
1128
            while (ArgNode->Asl.Next)
1129
            {
1130
                PrevArgNode = ArgNode;
1131
                ArgNode = ArgNode->Asl.Next;
1132
            }
1133
 
1134
            /* Divide() is the only weird case, it has two targets */
1135
 
1136
            if (Op->Asl.AmlOpcode == AML_DIVIDE_OP)
1137
            {
1138
                if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) &&
1139
                    (PrevArgNode) &&
1140
                    (PrevArgNode->Asl.ParseOpcode == PARSEOP_ZERO))
1141
                {
1142
                    AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED,
1143
                        Op, Op->Asl.ExternalName);
1144
                }
1145
            }
1146
            else if (ArgNode->Asl.ParseOpcode == PARSEOP_ZERO)
1147
            {
1148
                AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED,
1149
                    Op, Op->Asl.ExternalName);
1150
            }
1151
        }
1152
        else
1153
        {
1154
            /*
1155
             * Has no target and the result is not used. Only a couple opcodes
1156
             * can have this combination.
1157
             */
1158
            switch (Op->Asl.ParseOpcode)
1159
            {
1160
            case PARSEOP_ACQUIRE:
1161
            case PARSEOP_WAIT:
1162
            case PARSEOP_LOADTABLE:
1163
                break;
1164
 
1165
            default:
1166
                AslError (ASL_WARNING, ASL_MSG_RESULT_NOT_USED,
1167
                    Op, Op->Asl.ExternalName);
1168
                break;
1169
            }
1170
        }
1171
    }
1172
 
1173
 
1174
    /*
1175
     * Semantic checks for individual ASL operators
1176
     */
1177
    switch (Op->Asl.ParseOpcode)
1178
    {
1179
    case PARSEOP_ACQUIRE:
1180
    case PARSEOP_WAIT:
1181
        /*
1182
         * Emit a warning if the timeout parameter for these operators is not
1183
         * ACPI_WAIT_FOREVER, and the result value from the operator is not
1184
         * checked, meaning that a timeout could happen, but the code
1185
         * would not know about it.
1186
         */
1187
 
1188
        /* First child is the namepath, 2nd child is timeout */
1189
 
1190
        ArgNode = Op->Asl.Child;
1191
        ArgNode = ArgNode->Asl.Next;
1192
 
1193
        /*
1194
         * Check for the WAIT_FOREVER case - defined by the ACPI spec to be
1195
         * 0xFFFF or greater
1196
         */
1197
        if (((ArgNode->Asl.ParseOpcode == PARSEOP_WORDCONST) ||
1198
             (ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER))  &&
1199
             (ArgNode->Asl.Value.Integer >= (UINT64) ACPI_WAIT_FOREVER))
1200
        {
1201
            break;
1202
        }
1203
 
1204
        /*
1205
         * The operation could timeout. If the return value is not used
1206
         * (indicates timeout occurred), issue a warning
1207
         */
1208
        if (!AnIsResultUsed (Op))
1209
        {
1210
            AslError (ASL_WARNING, ASL_MSG_TIMEOUT, ArgNode,
1211
                Op->Asl.ExternalName);
1212
        }
1213
        break;
1214
 
1215
    case PARSEOP_CREATEFIELD:
1216
        /*
1217
         * Check for a zero Length (NumBits) operand. NumBits is the 3rd operand
1218
         */
1219
        ArgNode = Op->Asl.Child;
1220
        ArgNode = ArgNode->Asl.Next;
1221
        ArgNode = ArgNode->Asl.Next;
1222
 
1223
        if ((ArgNode->Asl.ParseOpcode == PARSEOP_ZERO) ||
1224
           ((ArgNode->Asl.ParseOpcode == PARSEOP_INTEGER) &&
1225
            (ArgNode->Asl.Value.Integer == 0)))
1226
        {
1227
            AslError (ASL_ERROR, ASL_MSG_NON_ZERO, ArgNode, NULL);
1228
        }
1229
        break;
1230
 
1231
    default:
1232
        break;
1233
    }
1234
 
1235
    return (AE_OK);
1236
}