aslfold.c revision 151937
10Sduke
2553Sohair/******************************************************************************
30Sduke *
40Sduke * Module Name: aslfold - Constant folding
50Sduke *              $Revision: 1.18 $
60Sduke *
70Sduke *****************************************************************************/
80Sduke
90Sduke/******************************************************************************
100Sduke *
110Sduke * 1. Copyright Notice
120Sduke *
130Sduke * Some or all of this work - Copyright (c) 1999 - 2005, Intel Corp.
140Sduke * All rights reserved.
150Sduke *
160Sduke * 2. License
170Sduke *
180Sduke * 2.1. This is your license from Intel Corp. under its intellectual property
19553Sohair * rights.  You may have additional license terms from the party that provided
20553Sohair * you this software, covering your right to use that party's intellectual
21553Sohair * property rights.
220Sduke *
230Sduke * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
240Sduke * copy of the source code appearing in this file ("Covered Code") an
250Sduke * irrevocable, perpetual, worldwide license under Intel's copyrights in the
260Sduke * base code distributed originally by Intel ("Original Intel Code") to copy,
270Sduke * make derivatives, distribute, use and display any portion of the Covered
280Sduke * Code in any form, with the right to sublicense such rights; and
290Sduke *
30288Sdarcy * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
310Sduke * license (with the right to sublicense), under only those claims of Intel
320Sduke * patents that are infringed by the Original Intel Code, to make, use, sell,
330Sduke * offer to sell, and import the Covered Code and derivative works thereof
340Sduke * solely to the minimum extent necessary to exercise the above copyright
350Sduke * license, and in no event shall the patent license extend to any additions
360Sduke * to or modifications of the Original Intel Code.  No other license or right
370Sduke * is granted directly or by implication, estoppel or otherwise;
380Sduke *
390Sduke * The above copyright and patent license is granted only if the following
400Sduke * conditions are met:
410Sduke *
420Sduke * 3. Conditions
430Sduke *
440Sduke * 3.1. Redistribution of Source with Rights to Further Distribute Source.
450Sduke * Redistribution of source code of any substantial portion of the Covered
460Sduke * 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.
55 *
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.
67 *
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.
73 *
74 * 3.4. Intel retains all right, title, and interest in and to the Original
75 * Intel Code.
76 *
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.
81 *
82 * 4. Disclaimer and Export Compliance
83 *
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.
91 *
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.
100 *
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.
115 *
116 *****************************************************************************/
117
118
119#include <contrib/dev/acpica/compiler/aslcompiler.h>
120#include "aslcompiler.y.h"
121#include <contrib/dev/acpica/amlcode.h>
122
123#include <contrib/dev/acpica/acdispat.h>
124#include <contrib/dev/acpica/acparser.h>
125
126#define _COMPONENT          ACPI_COMPILER
127        ACPI_MODULE_NAME    ("aslfold")
128
129/* Local prototypes */
130
131static ACPI_STATUS
132OpcAmlEvaluationWalk1 (
133    ACPI_PARSE_OBJECT       *Op,
134    UINT32                  Level,
135    void                    *Context);
136
137static ACPI_STATUS
138OpcAmlEvaluationWalk2 (
139    ACPI_PARSE_OBJECT       *Op,
140    UINT32                  Level,
141    void                    *Context);
142
143static ACPI_STATUS
144OpcAmlCheckForConstant (
145    ACPI_PARSE_OBJECT       *Op,
146    UINT32                  Level,
147    void                    *Context);
148
149
150/*******************************************************************************
151 *
152 * FUNCTION:    OpcAmlEvaluationWalk1
153 *
154 * PARAMETERS:  ASL_WALK_CALLBACK
155 *
156 * RETURN:      Status
157 *
158 * DESCRIPTION: Descending callback for AML execution of constant subtrees
159 *
160 ******************************************************************************/
161
162static ACPI_STATUS
163OpcAmlEvaluationWalk1 (
164    ACPI_PARSE_OBJECT       *Op,
165    UINT32                  Level,
166    void                    *Context)
167{
168    ACPI_WALK_STATE         *WalkState = Context;
169    ACPI_STATUS             Status;
170    ACPI_PARSE_OBJECT       *OutOp;
171
172
173    WalkState->Op = Op;
174    WalkState->Opcode = Op->Common.AmlOpcode;
175    WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
176
177    /* Copy child pointer to Arg for compatibility with Interpreter */
178
179    if (Op->Asl.Child)
180    {
181        Op->Common.Value.Arg = Op->Asl.Child;
182    }
183
184    /* Call AML dispatcher */
185
186    Status = AcpiDsExecBeginOp (WalkState, &OutOp);
187    if (ACPI_FAILURE (Status))
188    {
189        AcpiOsPrintf ("Constant interpretation failed - %s\n",
190                        AcpiFormatException (Status));
191    }
192
193    return (Status);
194}
195
196
197/*******************************************************************************
198 *
199 * FUNCTION:    OpcAmlEvaluationWalk2
200 *
201 * PARAMETERS:  ASL_WALK_CALLBACK
202 *
203 * RETURN:      Status
204 *
205 * DESCRIPTION: Ascending callback for AML execution of constant subtrees
206 *
207 ******************************************************************************/
208
209static ACPI_STATUS
210OpcAmlEvaluationWalk2 (
211    ACPI_PARSE_OBJECT       *Op,
212    UINT32                  Level,
213    void                    *Context)
214{
215    ACPI_WALK_STATE         *WalkState = Context;
216    ACPI_STATUS             Status;
217
218
219    WalkState->Op = Op;
220    WalkState->Opcode = Op->Common.AmlOpcode;
221    WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
222
223    /* Copy child pointer to Arg for compatibility with Interpreter */
224
225    if (Op->Asl.Child)
226    {
227        Op->Common.Value.Arg = Op->Asl.Child;
228    }
229
230    /* Call AML dispatcher */
231
232    Status = AcpiDsExecEndOp (WalkState);
233    if (ACPI_FAILURE (Status))
234    {
235        AcpiOsPrintf ("Constant interpretation failed - %s\n",
236                        AcpiFormatException (Status));
237    }
238
239    return (Status);
240}
241
242
243/*******************************************************************************
244 *
245 * FUNCTION:    OpcAmlCheckForConstant
246 *
247 * PARAMETERS:  ASL_WALK_CALLBACK
248 *
249 * RETURN:      Status
250 *
251 * DESCRIPTION: Check one Op for a type 3/4/5 AML opcode
252 *
253 ******************************************************************************/
254
255static ACPI_STATUS
256OpcAmlCheckForConstant (
257    ACPI_PARSE_OBJECT       *Op,
258    UINT32                  Level,
259    void                    *Context)
260{
261    ACPI_WALK_STATE         *WalkState = Context;
262
263
264    WalkState->Op = Op;
265    WalkState->Opcode = Op->Common.AmlOpcode;
266    WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
267
268    DbgPrint (ASL_PARSE_OUTPUT, "[%.4d] Opcode: %12.12s ",
269                Op->Asl.LogicalLineNumber, Op->Asl.ParseOpName);
270
271    if (!(WalkState->OpInfo->Flags & AML_CONSTANT))
272    {
273        /* The opcode is not a Type 3/4/5 opcode */
274
275        if (Op->Asl.CompileFlags & NODE_IS_TARGET)
276        {
277            DbgPrint (ASL_PARSE_OUTPUT,
278                "**** Valid Target, cannot reduce ****\n");
279        }
280        else
281        {
282            DbgPrint (ASL_PARSE_OUTPUT,
283                "**** Not a Type 3/4/5 opcode ****\n");
284        }
285
286        if (WalkState->WalkType == ACPI_WALK_CONST_OPTIONAL)
287        {
288            /*
289             * We are looking at at normal expression to see if it can be
290             * reduced.  It can't.  No error
291             */
292            return (AE_TYPE);
293        }
294
295        /*
296         * This is an expression that MUST reduce to a constant, and it
297         * can't be reduced.  This is an error
298         */
299        if (Op->Asl.CompileFlags & NODE_IS_TARGET)
300        {
301            AslError (ASL_ERROR, ASL_MSG_INVALID_TARGET, Op,
302                Op->Asl.ParseOpName);
303        }
304        else
305        {
306            AslError (ASL_ERROR, ASL_MSG_INVALID_CONSTANT_OP, Op,
307                Op->Asl.ParseOpName);
308        }
309
310        return (AE_TYPE);
311    }
312
313    /* Debug output */
314
315    DbgPrint (ASL_PARSE_OUTPUT, "TYPE_345");
316
317    if (Op->Asl.CompileFlags & NODE_IS_TARGET)
318    {
319        DbgPrint (ASL_PARSE_OUTPUT, " TARGET");
320    }
321    if (Op->Asl.CompileFlags & NODE_IS_TERM_ARG)
322    {
323        DbgPrint (ASL_PARSE_OUTPUT, " TERMARG");
324    }
325    DbgPrint (ASL_PARSE_OUTPUT, "\n");
326
327    return (AE_OK);
328}
329
330
331/*******************************************************************************
332 *
333 * FUNCTION:    OpcAmlConstantWalk
334 *
335 * PARAMETERS:  ASL_WALK_CALLBACK
336 *
337 * RETURN:      Status
338 *
339 * DESCRIPTION: Reduce an Op and its subtree to a constant if possible
340 *
341 ******************************************************************************/
342
343ACPI_STATUS
344OpcAmlConstantWalk (
345    ACPI_PARSE_OBJECT       *Op,
346    UINT32                  Level,
347    void                    *Context)
348{
349    ACPI_WALK_STATE         *WalkState;
350    ACPI_STATUS             Status = AE_OK;
351    ACPI_OPERAND_OBJECT     *ObjDesc;
352    ACPI_PARSE_OBJECT       *RootOp;
353    ACPI_PARSE_OBJECT       *OriginalParentOp;
354    UINT8                   WalkType;
355
356
357    /*
358     * Only interested in subtrees that could possibly contain
359     * expressions that can be evaluated at this time
360     */
361    if ((!(Op->Asl.CompileFlags & NODE_COMPILE_TIME_CONST)) ||
362          (Op->Asl.CompileFlags & NODE_IS_TARGET))
363    {
364        return (AE_OK);
365    }
366
367    /* Set the walk type based on the reduction used for this op */
368
369    if (Op->Asl.CompileFlags & NODE_IS_TERM_ARG)
370    {
371        /* Op is a TermArg, constant folding is merely optional */
372
373        if (!Gbl_FoldConstants)
374        {
375            return (AE_CTRL_DEPTH);
376        }
377
378        WalkType = ACPI_WALK_CONST_OPTIONAL;
379    }
380    else
381    {
382        /* Op is a DataObject, the expression MUST reduced to a constant */
383
384        WalkType = ACPI_WALK_CONST_REQUIRED;
385    }
386
387    /* Create a new walk state */
388
389    WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);
390    if (!WalkState)
391    {
392        return AE_NO_MEMORY;
393    }
394
395    WalkState->NextOp               = NULL;
396    WalkState->Params               = NULL;
397    WalkState->CallerReturnDesc     = &ObjDesc;
398    WalkState->WalkType             = WalkType;
399
400    /*
401     * Examine the entire subtree -- all nodes must be constants
402     * or type 3/4/5 opcodes
403     */
404    Status = TrWalkParseTree (Op, ASL_WALK_VISIT_DOWNWARD,
405                OpcAmlCheckForConstant, NULL, WalkState);
406
407    /*
408     * Did we find an entire subtree that contains all constants and type 3/4/5
409     * opcodes?  (Only AE_OK or AE_TYPE returned from above)
410     */
411    if (Status == AE_TYPE)
412    {
413        /* Subtree cannot be reduced to a constant */
414
415        if (WalkState->WalkType == ACPI_WALK_CONST_OPTIONAL)
416        {
417            AcpiDsDeleteWalkState (WalkState);
418            return (AE_OK);
419        }
420
421        /* Don't descend any further, and use a default "constant" value */
422
423        Status = AE_CTRL_DEPTH;
424    }
425    else
426    {
427        /* Subtree can be reduced */
428
429        /* Allocate a new temporary root for this subtree */
430
431        RootOp = TrAllocateNode (PARSEOP_INTEGER);
432        if (!RootOp)
433        {
434            return (AE_NO_MEMORY);
435        }
436
437        RootOp->Common.AmlOpcode = AML_INT_EVAL_SUBTREE_OP;
438
439        OriginalParentOp = Op->Common.Parent;
440        Op->Common.Parent = RootOp;
441
442        /* Hand off the subtree to the AML interpreter */
443
444        Status = TrWalkParseTree (Op, ASL_WALK_VISIT_TWICE,
445                    OpcAmlEvaluationWalk1, OpcAmlEvaluationWalk2, WalkState);
446        Op->Common.Parent = OriginalParentOp;
447
448        /* TBD: we really *should* release the RootOp node */
449
450        if (ACPI_SUCCESS (Status))
451        {
452            TotalFolds++;
453
454            /* Get the final result */
455
456            Status = AcpiDsResultPop (&ObjDesc, WalkState);
457        }
458    }
459
460    if (ACPI_FAILURE (Status))
461    {
462        /* We could not resolve the subtree for some reason */
463
464        AslCoreSubsystemError (Op, Status,
465            "Failure during constant evaluation", FALSE);
466        AslError (ASL_ERROR, ASL_MSG_CONSTANT_EVALUATION, Op,
467            Op->Asl.ParseOpName);
468
469        /* Set the subtree value to ZERO anyway.  Eliminates further errors */
470
471        Op->Asl.ParseOpcode      = PARSEOP_INTEGER;
472        Op->Common.Value.Integer = 0;
473        OpcSetOptimalIntegerSize (Op);
474    }
475    else
476    {
477        AslError (ASL_OPTIMIZATION, ASL_MSG_CONSTANT_FOLDED, Op,
478            Op->Asl.ParseOpName);
479
480        /*
481         * Because we know we executed type 3/4/5 opcodes above, we know that
482         * the result must be either an Integer, String, or Buffer.
483         */
484        switch (ACPI_GET_OBJECT_TYPE (ObjDesc))
485        {
486        case ACPI_TYPE_INTEGER:
487
488            Op->Asl.ParseOpcode      = PARSEOP_INTEGER;
489            Op->Common.Value.Integer = ObjDesc->Integer.Value;
490            OpcSetOptimalIntegerSize (Op);
491
492            DbgPrint (ASL_PARSE_OUTPUT,
493                "Constant expression reduced to (INTEGER) %8.8X%8.8X\n",
494                ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value));
495            break;
496
497
498        case ACPI_TYPE_STRING:
499
500            Op->Asl.ParseOpcode     = PARSEOP_STRING_LITERAL;
501            Op->Common.AmlOpcode    = AML_STRING_OP;
502            Op->Asl.AmlLength       = ACPI_STRLEN (ObjDesc->String.Pointer) + 1;
503            Op->Common.Value.String = ObjDesc->String.Pointer;
504
505            DbgPrint (ASL_PARSE_OUTPUT,
506                "Constant expression reduced to (STRING) %s\n",
507                Op->Common.Value.String);
508
509            break;
510
511
512        case ACPI_TYPE_BUFFER:
513
514            Op->Asl.ParseOpcode     = PARSEOP_BUFFER;
515            Op->Common.AmlOpcode    = AML_BUFFER_OP;
516            Op->Asl.CompileFlags    = NODE_AML_PACKAGE;
517            UtSetParseOpName (Op);
518
519            /* Child node is the buffer length */
520
521            RootOp = TrAllocateNode (PARSEOP_INTEGER);
522
523            RootOp->Asl.AmlOpcode     = AML_DWORD_OP;
524            RootOp->Asl.Value.Integer = ObjDesc->Buffer.Length;
525            RootOp->Asl.Parent        = Op;
526
527            (void) OpcSetOptimalIntegerSize (RootOp);
528
529            Op->Asl.Child = RootOp;
530            Op = RootOp;
531            UtSetParseOpName (Op);
532
533            /* Peer to the child is the raw buffer data */
534
535            RootOp = TrAllocateNode (PARSEOP_RAW_DATA);
536            RootOp->Asl.AmlOpcode     = AML_RAW_DATA_BUFFER;
537            RootOp->Asl.AmlLength     = ObjDesc->Buffer.Length;
538            RootOp->Asl.Value.String  = (char *) ObjDesc->Buffer.Pointer;
539            RootOp->Asl.Parent        = Op->Asl.Parent;
540
541            Op->Asl.Next = RootOp;
542            Op = RootOp;
543
544            DbgPrint (ASL_PARSE_OUTPUT,
545                "Constant expression reduced to (BUFFER) length %X\n",
546                ObjDesc->Buffer.Length);
547            break;
548
549
550        default:
551            printf ("Unsupported return type: %s\n",
552                        AcpiUtGetObjectTypeName (ObjDesc));
553            break;
554        }
555    }
556
557    UtSetParseOpName (Op);
558    Op->Asl.Child = NULL;
559
560    AcpiDsDeleteWalkState (WalkState);
561
562    return (AE_CTRL_DEPTH);
563}
564
565