Home | History | Annotate | Line # | Download | only in compiler
aslfold.c revision 1.1.1.7
      1 /******************************************************************************
      2  *
      3  * Module Name: aslfold - Constant folding
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2016, 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 "amlcode.h"
     47 
     48 #include "acdispat.h"
     49 #include "acparser.h"
     50 
     51 #define _COMPONENT          ACPI_COMPILER
     52         ACPI_MODULE_NAME    ("aslfold")
     53 
     54 /* Local prototypes */
     55 
     56 static ACPI_STATUS
     57 OpcAmlEvaluationWalk1 (
     58     ACPI_PARSE_OBJECT       *Op,
     59     UINT32                  Level,
     60     void                    *Context);
     61 
     62 static ACPI_STATUS
     63 OpcAmlEvaluationWalk2 (
     64     ACPI_PARSE_OBJECT       *Op,
     65     UINT32                  Level,
     66     void                    *Context);
     67 
     68 static ACPI_STATUS
     69 OpcAmlCheckForConstant (
     70     ACPI_PARSE_OBJECT       *Op,
     71     UINT32                  Level,
     72     void                    *Context);
     73 
     74 static void
     75 OpcUpdateIntegerNode (
     76     ACPI_PARSE_OBJECT       *Op,
     77     UINT64                  Value);
     78 
     79 static ACPI_STATUS
     80 TrTransformToStoreOp (
     81     ACPI_PARSE_OBJECT       *Op,
     82     ACPI_WALK_STATE         *WalkState);
     83 
     84 static ACPI_STATUS
     85 TrSimpleConstantReduction (
     86     ACPI_PARSE_OBJECT       *Op,
     87     ACPI_WALK_STATE         *WalkState);
     88 
     89 static void
     90 TrInstallReducedConstant (
     91     ACPI_PARSE_OBJECT       *Op,
     92     ACPI_OPERAND_OBJECT     *ObjDesc);
     93 
     94 
     95 /*******************************************************************************
     96  *
     97  * FUNCTION:    OpcAmlConstantWalk
     98  *
     99  * PARAMETERS:  ASL_WALK_CALLBACK
    100  *
    101  * RETURN:      Status
    102  *
    103  * DESCRIPTION: Reduce an Op and its subtree to a constant if possible.
    104  *
    105  ******************************************************************************/
    106 
    107 ACPI_STATUS
    108 OpcAmlConstantWalk (
    109     ACPI_PARSE_OBJECT       *Op,
    110     UINT32                  Level,
    111     void                    *Context)
    112 {
    113     ACPI_WALK_STATE         *WalkState;
    114     ACPI_STATUS             Status = AE_OK;
    115 
    116 
    117     if (Op->Asl.CompileFlags == 0)
    118     {
    119         return (AE_OK);
    120     }
    121 
    122     /*
    123      * Only interested in subtrees that could possibly contain
    124      * expressions that can be evaluated at this time
    125      */
    126     if ((!(Op->Asl.CompileFlags & NODE_COMPILE_TIME_CONST)) ||
    127           (Op->Asl.CompileFlags & NODE_IS_TARGET))
    128     {
    129         return (AE_OK);
    130     }
    131 
    132     /* Create a new walk state */
    133 
    134     WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);
    135     if (!WalkState)
    136     {
    137         return (AE_NO_MEMORY);
    138     }
    139 
    140     WalkState->NextOp = NULL;
    141     WalkState->Params = NULL;
    142 
    143     /*
    144      * Examine the entire subtree -- all nodes must be constants
    145      * or type 3/4/5 opcodes
    146      */
    147     Status = TrWalkParseTree (Op, ASL_WALK_VISIT_DOWNWARD,
    148         OpcAmlCheckForConstant, NULL, WalkState);
    149 
    150     /*
    151      * Did we find an entire subtree that contains all constants
    152      * and type 3/4/5 opcodes?
    153      */
    154     switch (Status)
    155     {
    156     case AE_OK:
    157 
    158         /* Simple case, like Add(3,4) -> 7 */
    159 
    160         Status = TrSimpleConstantReduction (Op, WalkState);
    161         break;
    162 
    163     case AE_CTRL_RETURN_VALUE:
    164 
    165         /* More complex case, like Add(3,4,Local0) -> Store(7,Local0) */
    166 
    167         Status = TrTransformToStoreOp (Op, WalkState);
    168         break;
    169 
    170     case AE_TYPE:
    171 
    172         AcpiDsDeleteWalkState (WalkState);
    173         return (AE_OK);
    174 
    175     default:
    176         AcpiDsDeleteWalkState (WalkState);
    177         break;
    178     }
    179 
    180     if (ACPI_FAILURE (Status))
    181     {
    182         DbgPrint (ASL_PARSE_OUTPUT, "Cannot resolve, %s\n",
    183             AcpiFormatException (Status));
    184 
    185         /* We could not resolve the subtree for some reason */
    186 
    187         AslError (ASL_ERROR, ASL_MSG_CONSTANT_EVALUATION, Op,
    188             (char *) AcpiFormatException (Status));
    189 
    190         /* Set the subtree value to ZERO anyway. Eliminates further errors */
    191 
    192         OpcUpdateIntegerNode (Op, 0);
    193     }
    194 
    195     /* Abort the walk of this subtree, we are done with it */
    196 
    197     return (AE_CTRL_DEPTH);
    198 }
    199 
    200 
    201 /*******************************************************************************
    202  *
    203  * FUNCTION:    OpcAmlCheckForConstant
    204  *
    205  * PARAMETERS:  ASL_WALK_CALLBACK
    206  *
    207  * RETURN:      Status
    208  *
    209  * DESCRIPTION: Check one Op for a reducible type 3/4/5 AML opcode.
    210  *              This is performed via a downward walk of the parse subtree.
    211  *
    212  ******************************************************************************/
    213 
    214 static ACPI_STATUS
    215 OpcAmlCheckForConstant (
    216     ACPI_PARSE_OBJECT       *Op,
    217     UINT32                  Level,
    218     void                    *Context)
    219 {
    220     ACPI_WALK_STATE         *WalkState = Context;
    221     ACPI_STATUS             Status = AE_OK;
    222     ACPI_PARSE_OBJECT       *NextOp;
    223     const ACPI_OPCODE_INFO  *OpInfo;
    224 
    225 
    226     WalkState->Op = Op;
    227     WalkState->Opcode = Op->Common.AmlOpcode;
    228     WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
    229 
    230     DbgPrint (ASL_PARSE_OUTPUT, "[%.4d] Opcode: %12.12s ",
    231         Op->Asl.LogicalLineNumber, Op->Asl.ParseOpName);
    232 
    233     /*
    234      * These opcodes do not appear in the OpcodeInfo table, but
    235      * they represent constants, so abort the constant walk now.
    236      */
    237     if ((WalkState->Opcode == AML_RAW_DATA_BYTE) ||
    238         (WalkState->Opcode == AML_RAW_DATA_WORD) ||
    239         (WalkState->Opcode == AML_RAW_DATA_DWORD) ||
    240         (WalkState->Opcode == AML_RAW_DATA_QWORD))
    241     {
    242         DbgPrint (ASL_PARSE_OUTPUT, "RAW DATA");
    243         Status = AE_TYPE;
    244         goto CleanupAndExit;
    245     }
    246 
    247     /*
    248      * Search upwards for a possible Name() operator. This is done
    249      * because a type 3/4/5 opcode within a Name() expression
    250      * MUST be reduced to a simple constant.
    251      */
    252     NextOp = Op->Asl.Parent;
    253     while (NextOp)
    254     {
    255         /* Finished if we find a Name() opcode */
    256 
    257         if (NextOp->Asl.AmlOpcode == AML_NAME_OP)
    258         {
    259             break;
    260         }
    261 
    262         /*
    263          * Any "deferred" opcodes contain one or more TermArg parameters,
    264          * and thus are not required to be folded to constants at compile
    265          * time. This affects things like Buffer() and Package() objects.
    266          * We just ignore them here. However, any sub-expressions can and
    267          * will still be typechecked. Note: These are called the
    268          * "deferred" opcodes in the AML interpreter.
    269          */
    270         OpInfo = AcpiPsGetOpcodeInfo (NextOp->Common.AmlOpcode);
    271         if (OpInfo->Flags & AML_DEFER)
    272         {
    273             NextOp = NULL;
    274             break;
    275         }
    276 
    277         NextOp = NextOp->Asl.Parent;
    278     }
    279 
    280     /* Type 3/4/5 opcodes have the AML_CONSTANT flag set */
    281 
    282     if (!(WalkState->OpInfo->Flags & AML_CONSTANT))
    283     {
    284         /*
    285          * From the ACPI specification:
    286          *
    287          * "The Type 3/4/5 opcodes return a value and can be used in an
    288          * expression that evaluates to a constant. These opcodes may be
    289          * evaluated at ASL compile-time. To ensure that these opcodes
    290          * will evaluate to a constant, the following rules apply: The
    291          * term cannot have a destination (target) operand, and must have
    292          * either a Type3Opcode, Type4Opcode, Type5Opcode, ConstExprTerm,
    293          * Integer, BufferTerm, Package, or String for all arguments."
    294          */
    295 
    296         /*
    297          * The value (second) operand for the Name() operator MUST
    298          * reduce to a single constant, as per the ACPI specification
    299          * (the operand is a DataObject). This also implies that there
    300          * can be no target operand. Name() is the only ASL operator
    301          * with a "DataObject" as an operand and is thus special-
    302          * cased here.
    303          */
    304         if (NextOp) /* Inspect a Name() operator */
    305         {
    306             /* Error if there is a target operand */
    307 
    308             if (Op->Asl.CompileFlags & NODE_IS_TARGET)
    309             {
    310                 AslError (ASL_ERROR, ASL_MSG_INVALID_TARGET, Op, NULL);
    311                 Status = AE_TYPE;
    312             }
    313 
    314             /* Error if expression cannot be reduced (folded) */
    315 
    316             if (!(NextOp->Asl.CompileFlags & NODE_COULD_NOT_REDUCE))
    317             {
    318                 /* Ensure only one error message per statement */
    319 
    320                 NextOp->Asl.CompileFlags |= NODE_COULD_NOT_REDUCE;
    321                 DbgPrint (ASL_PARSE_OUTPUT,
    322                     "**** Could not reduce operands for NAME opcode ****\n");
    323 
    324                 AslError (ASL_ERROR, ASL_MSG_CONSTANT_REQUIRED, Op,
    325                     "Constant is required for Name operator");
    326                 Status = AE_TYPE;
    327             }
    328         }
    329 
    330         if (ACPI_FAILURE (Status))
    331         {
    332             goto CleanupAndExit;
    333         }
    334 
    335         /* This is not a 3/4/5 opcode, but maybe can convert to STORE */
    336 
    337         if (Op->Asl.CompileFlags & NODE_IS_TARGET)
    338         {
    339             DbgPrint (ASL_PARSE_OUTPUT,
    340                 "**** Valid Target, transform to Store ****\n");
    341             return (AE_CTRL_RETURN_VALUE);
    342         }
    343 
    344         /* Expression cannot be reduced */
    345 
    346         DbgPrint (ASL_PARSE_OUTPUT,
    347             "**** Not a Type 3/4/5 opcode or cannot reduce/fold (%s) ****\n",
    348              Op->Asl.ParseOpName);
    349 
    350         Status = AE_TYPE;
    351         goto CleanupAndExit;
    352     }
    353 
    354     /*
    355      * TBD: Ignore buffer constants for now. The problem is that these
    356      * constants have been transformed into RAW_DATA at this point, from
    357      * the parse tree transform process which currently happens before
    358      * the constant folding process. We may need to defer this transform
    359      * for buffer until after the constant folding.
    360      */
    361     if (WalkState->Opcode == AML_BUFFER_OP)
    362     {
    363         DbgPrint (ASL_PARSE_OUTPUT,
    364             "\nBuffer constant reduction is not supported yet\n");
    365 
    366         if (NextOp) /* Found a Name() operator, error */
    367         {
    368             AslError (ASL_ERROR, ASL_MSG_UNSUPPORTED, Op,
    369                 "Buffer expression cannot be reduced");
    370         }
    371 
    372         Status = AE_TYPE;
    373         goto CleanupAndExit;
    374     }
    375 
    376 
    377     /* Debug output */
    378 
    379     DbgPrint (ASL_PARSE_OUTPUT, "TYPE_345");
    380 
    381     if (Op->Asl.CompileFlags & NODE_IS_TARGET)
    382     {
    383         if (Op->Asl.ParseOpcode == PARSEOP_ZERO)
    384         {
    385             DbgPrint (ASL_PARSE_OUTPUT, "%-16s", " NULL TARGET");
    386         }
    387         else
    388         {
    389             DbgPrint (ASL_PARSE_OUTPUT, "%-16s", " VALID TARGET");
    390         }
    391     }
    392 
    393     if (Op->Asl.CompileFlags & NODE_IS_TERM_ARG)
    394     {
    395         DbgPrint (ASL_PARSE_OUTPUT, "%-16s", " TERMARG");
    396     }
    397 
    398 CleanupAndExit:
    399 
    400     /* Dump the node compile flags also */
    401 
    402     TrPrintNodeCompileFlags (Op->Asl.CompileFlags);
    403     DbgPrint (ASL_PARSE_OUTPUT, "\n");
    404     return (Status);
    405 }
    406 
    407 
    408 /*******************************************************************************
    409  *
    410  * FUNCTION:    TrSimpleConstantReduction
    411  *
    412  * PARAMETERS:  Op                  - Parent operator to be transformed
    413  *              WalkState           - Current walk state
    414  *
    415  * RETURN:      Status
    416  *
    417  * DESCRIPTION: Reduce an entire AML operation to a single constant. The
    418  *              operation must not have a target operand.
    419  *
    420  *              Add (32,64) --> 96
    421  *
    422  ******************************************************************************/
    423 
    424 static ACPI_STATUS
    425 TrSimpleConstantReduction (
    426     ACPI_PARSE_OBJECT       *Op,
    427     ACPI_WALK_STATE         *WalkState)
    428 {
    429     ACPI_PARSE_OBJECT       *RootOp;
    430     ACPI_PARSE_OBJECT       *OriginalParentOp;
    431     ACPI_OPERAND_OBJECT     *ObjDesc;
    432     ACPI_STATUS             Status;
    433 
    434 
    435     DbgPrint (ASL_PARSE_OUTPUT,
    436         "Simple subtree constant reduction, operator to constant\n");
    437 
    438     /* Allocate a new temporary root for this subtree */
    439 
    440     RootOp = TrAllocateNode (PARSEOP_INTEGER);
    441     if (!RootOp)
    442     {
    443         return (AE_NO_MEMORY);
    444     }
    445 
    446     RootOp->Common.AmlOpcode = AML_INT_EVAL_SUBTREE_OP;
    447 
    448     OriginalParentOp = Op->Common.Parent;
    449     Op->Common.Parent = RootOp;
    450 
    451     /* Hand off the subtree to the AML interpreter */
    452 
    453     WalkState->CallerReturnDesc = &ObjDesc;
    454 
    455     Status = TrWalkParseTree (Op, ASL_WALK_VISIT_TWICE,
    456         OpcAmlEvaluationWalk1, OpcAmlEvaluationWalk2, WalkState);
    457 
    458     /* Restore original parse tree */
    459 
    460     Op->Common.Parent = OriginalParentOp;
    461 
    462     if (ACPI_FAILURE (Status))
    463     {
    464         DbgPrint (ASL_PARSE_OUTPUT,
    465             "Constant Subtree evaluation(1), %s\n",
    466             AcpiFormatException (Status));
    467         return (Status);
    468     }
    469 
    470     /* Get the final result */
    471 
    472     Status = AcpiDsResultPop (&ObjDesc, WalkState);
    473     if (ACPI_FAILURE (Status))
    474     {
    475         DbgPrint (ASL_PARSE_OUTPUT,
    476             "Constant Subtree evaluation(2), %s\n",
    477             AcpiFormatException (Status));
    478         return (Status);
    479     }
    480 
    481     /* Disconnect any existing children, install new constant */
    482 
    483     Op->Asl.Child = NULL;
    484     TrInstallReducedConstant (Op, ObjDesc);
    485 
    486     UtSetParseOpName (Op);
    487     return (AE_OK);
    488 }
    489 
    490 
    491 /*******************************************************************************
    492  *
    493  * FUNCTION:    TrTransformToStoreOp
    494  *
    495  * PARAMETERS:  Op                  - Parent operator to be transformed
    496  *              WalkState           - Current walk state
    497  *
    498  * RETURN:      Status
    499  *
    500  * DESCRIPTION: Transforms a single AML operation with a constant and target
    501  *              to a simple store operation:
    502  *
    503  *              Add (32,64,DATA) --> Store (96,DATA)
    504  *
    505  ******************************************************************************/
    506 
    507 static ACPI_STATUS
    508 TrTransformToStoreOp (
    509     ACPI_PARSE_OBJECT       *Op,
    510     ACPI_WALK_STATE         *WalkState)
    511 {
    512     ACPI_PARSE_OBJECT       *OriginalTarget;
    513     ACPI_PARSE_OBJECT       *NewTarget;
    514     ACPI_PARSE_OBJECT       *Child1;
    515     ACPI_PARSE_OBJECT       *Child2;
    516     ACPI_OPERAND_OBJECT     *ObjDesc;
    517     ACPI_PARSE_OBJECT       *NewParent;
    518     ACPI_PARSE_OBJECT       *OriginalParent;
    519     ACPI_STATUS             Status;
    520 
    521 
    522     DbgPrint (ASL_PARSE_OUTPUT,
    523         "Reduction/Transform to StoreOp: Store(Constant, Target)\n");
    524 
    525     /* Extract the operands */
    526 
    527     Child1 = Op->Asl.Child;
    528     Child2 = Child1->Asl.Next;
    529 
    530     /*
    531      * Special case for DIVIDE -- it has two targets. The first
    532      * is for the remainder and if present, we will not attempt
    533      * to reduce the expression.
    534      */
    535     if (Op->Asl.ParseOpcode == PARSEOP_DIVIDE)
    536     {
    537         Child2 = Child2->Asl.Next;
    538         if (Child2->Asl.ParseOpcode != PARSEOP_ZERO)
    539         {
    540             DbgPrint (ASL_PARSE_OUTPUT,
    541                 "Cannot reduce DIVIDE - has two targets\n\n");
    542             return (AE_OK);
    543         }
    544     }
    545 
    546     /*
    547      * Create a NULL (zero) target so that we can use the
    548      * interpreter to evaluate the expression.
    549      */
    550     NewTarget = TrCreateNullTarget ();
    551     NewTarget->Common.AmlOpcode = AML_INT_NAMEPATH_OP;
    552 
    553     /* Handle one-operand cases (NOT, TOBCD, etc.) */
    554 
    555     if (!Child2->Asl.Next)
    556     {
    557         Child2 = Child1;
    558     }
    559 
    560     /* Link in new NULL target as the last operand */
    561 
    562     OriginalTarget = Child2->Asl.Next;
    563     Child2->Asl.Next = NewTarget;
    564     NewTarget->Asl.Parent = OriginalTarget->Asl.Parent;
    565 
    566     NewParent = TrAllocateNode (PARSEOP_INTEGER);
    567     NewParent->Common.AmlOpcode = AML_INT_EVAL_SUBTREE_OP;
    568 
    569     OriginalParent = Op->Common.Parent;
    570     Op->Common.Parent = NewParent;
    571 
    572     /* Hand off the subtree to the AML interpreter */
    573 
    574     WalkState->CallerReturnDesc = &ObjDesc;
    575 
    576     Status = TrWalkParseTree (Op, ASL_WALK_VISIT_TWICE,
    577         OpcAmlEvaluationWalk1, OpcAmlEvaluationWalk2, WalkState);
    578     if (ACPI_FAILURE (Status))
    579     {
    580         DbgPrint (ASL_PARSE_OUTPUT,
    581             "Constant Subtree evaluation(3), %s\n",
    582             AcpiFormatException (Status));
    583         goto EvalError;
    584     }
    585 
    586     /* Get the final result */
    587 
    588     Status = AcpiDsResultPop (&ObjDesc, WalkState);
    589     if (ACPI_FAILURE (Status))
    590     {
    591         DbgPrint (ASL_PARSE_OUTPUT,
    592             "Constant Subtree evaluation(4), %s\n",
    593             AcpiFormatException (Status));
    594         goto EvalError;
    595     }
    596 
    597     /* Truncate any subtree expressions, they have been evaluated */
    598 
    599     Child1->Asl.Child = NULL;
    600 
    601     /* Folded constant is in ObjDesc, store into Child1 */
    602 
    603     TrInstallReducedConstant (Child1, ObjDesc);
    604 
    605     /* Convert operator to STORE */
    606 
    607     Op->Asl.ParseOpcode = PARSEOP_STORE;
    608     Op->Asl.AmlOpcode = AML_STORE_OP;
    609     UtSetParseOpName (Op);
    610     Op->Common.Parent = OriginalParent;
    611 
    612     /* First child is the folded constant */
    613 
    614     /* Second child will be the target */
    615 
    616     Child1->Asl.Next = OriginalTarget;
    617     return (AE_OK);
    618 
    619 
    620 EvalError:
    621 
    622     /* Restore original links */
    623 
    624     Op->Common.Parent = OriginalParent;
    625     Child2->Asl.Next = OriginalTarget;
    626     return (Status);
    627 }
    628 
    629 
    630 /*******************************************************************************
    631  *
    632  * FUNCTION:    TrInstallReducedConstant
    633  *
    634  * PARAMETERS:  Op                  - Parent operator to be transformed
    635  *              ObjDesc             - Reduced constant to be installed
    636  *
    637  * RETURN:      None
    638  *
    639  * DESCRIPTION: Transform the original operator to a simple constant.
    640  *              Handles Integers, Strings, and Buffers.
    641  *
    642  ******************************************************************************/
    643 
    644 static void
    645 TrInstallReducedConstant (
    646     ACPI_PARSE_OBJECT       *Op,
    647     ACPI_OPERAND_OBJECT     *ObjDesc)
    648 {
    649     ACPI_PARSE_OBJECT       *LengthOp;
    650     ACPI_PARSE_OBJECT       *DataOp;
    651 
    652 
    653     TotalFolds++;
    654     AslError (ASL_OPTIMIZATION, ASL_MSG_CONSTANT_FOLDED, Op,
    655         Op->Asl.ParseOpName);
    656 
    657     /*
    658      * Because we know we executed type 3/4/5 opcodes above, we know that
    659      * the result must be either an Integer, String, or Buffer.
    660      */
    661     switch (ObjDesc->Common.Type)
    662     {
    663     case ACPI_TYPE_INTEGER:
    664 
    665         OpcUpdateIntegerNode (Op, ObjDesc->Integer.Value);
    666 
    667         DbgPrint (ASL_PARSE_OUTPUT,
    668             "Constant expression reduced to (%s) %8.8X%8.8X\n\n",
    669             Op->Asl.ParseOpName,
    670             ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
    671         break;
    672 
    673     case ACPI_TYPE_STRING:
    674 
    675         Op->Asl.ParseOpcode = PARSEOP_STRING_LITERAL;
    676         Op->Common.AmlOpcode = AML_STRING_OP;
    677         Op->Asl.AmlLength = strlen (ObjDesc->String.Pointer) + 1;
    678         Op->Common.Value.String = ObjDesc->String.Pointer;
    679 
    680         DbgPrint (ASL_PARSE_OUTPUT,
    681             "Constant expression reduced to (STRING) %s\n\n",
    682             Op->Common.Value.String);
    683         break;
    684 
    685     case ACPI_TYPE_BUFFER:
    686         /*
    687          * Create a new parse subtree of the form:
    688          *
    689          * BUFFER (Buffer AML opcode)
    690          *    INTEGER (Buffer length in bytes)
    691          *    RAW_DATA (Buffer byte data)
    692          */
    693         Op->Asl.ParseOpcode = PARSEOP_BUFFER;
    694         Op->Common.AmlOpcode = AML_BUFFER_OP;
    695         Op->Asl.CompileFlags = NODE_AML_PACKAGE;
    696         UtSetParseOpName (Op);
    697 
    698         /* Child node is the buffer length */
    699 
    700         LengthOp = TrAllocateNode (PARSEOP_INTEGER);
    701 
    702         LengthOp->Asl.AmlOpcode = AML_DWORD_OP;
    703         LengthOp->Asl.Value.Integer = ObjDesc->Buffer.Length;
    704         LengthOp->Asl.Parent = Op;
    705         (void) OpcSetOptimalIntegerSize (LengthOp);
    706 
    707         Op->Asl.Child = LengthOp;
    708 
    709         /* Next child is the raw buffer data */
    710 
    711         DataOp = TrAllocateNode (PARSEOP_RAW_DATA);
    712         DataOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
    713         DataOp->Asl.AmlLength = ObjDesc->Buffer.Length;
    714         DataOp->Asl.Value.String = (char *) ObjDesc->Buffer.Pointer;
    715         DataOp->Asl.Parent = Op;
    716 
    717         LengthOp->Asl.Next = DataOp;
    718 
    719         DbgPrint (ASL_PARSE_OUTPUT,
    720             "Constant expression reduced to (BUFFER) length %X\n\n",
    721             ObjDesc->Buffer.Length);
    722         break;
    723 
    724     default:
    725         break;
    726     }
    727 }
    728 
    729 
    730 /*******************************************************************************
    731  *
    732  * FUNCTION:    OpcUpdateIntegerNode
    733  *
    734  * PARAMETERS:  Op                  - Current parse object
    735  *              Value               - Value for the integer op
    736  *
    737  * RETURN:      None
    738  *
    739  * DESCRIPTION: Update node to the correct Integer type and value
    740  *
    741  ******************************************************************************/
    742 
    743 static void
    744 OpcUpdateIntegerNode (
    745     ACPI_PARSE_OBJECT       *Op,
    746     UINT64                  Value)
    747 {
    748 
    749     Op->Common.Value.Integer = Value;
    750 
    751     /*
    752      * The AmlLength is used by the parser to indicate a constant,
    753      * (if non-zero). Length is either (1/2/4/8)
    754      */
    755     switch (Op->Asl.AmlLength)
    756     {
    757     case 1:
    758 
    759         TrUpdateNode (PARSEOP_BYTECONST, Op);
    760         Op->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
    761         break;
    762 
    763     case 2:
    764 
    765         TrUpdateNode (PARSEOP_WORDCONST, Op);
    766         Op->Asl.AmlOpcode = AML_RAW_DATA_WORD;
    767         break;
    768 
    769     case 4:
    770 
    771         TrUpdateNode (PARSEOP_DWORDCONST, Op);
    772         Op->Asl.AmlOpcode = AML_RAW_DATA_DWORD;
    773         break;
    774 
    775     case 8:
    776 
    777         TrUpdateNode (PARSEOP_QWORDCONST, Op);
    778         Op->Asl.AmlOpcode = AML_RAW_DATA_QWORD;
    779         break;
    780 
    781     case 0:
    782     default:
    783 
    784         OpcSetOptimalIntegerSize (Op);
    785         TrUpdateNode (PARSEOP_INTEGER, Op);
    786         break;
    787     }
    788 
    789     Op->Asl.AmlLength = 0;
    790 }
    791 
    792 
    793 /*******************************************************************************
    794  *
    795  * FUNCTION:    OpcAmlEvaluationWalk1
    796  *
    797  * PARAMETERS:  ASL_WALK_CALLBACK
    798  *
    799  * RETURN:      Status
    800  *
    801  * DESCRIPTION: Descending callback for AML execution of constant subtrees
    802  *
    803  ******************************************************************************/
    804 
    805 static ACPI_STATUS
    806 OpcAmlEvaluationWalk1 (
    807     ACPI_PARSE_OBJECT       *Op,
    808     UINT32                  Level,
    809     void                    *Context)
    810 {
    811     ACPI_WALK_STATE         *WalkState = Context;
    812     ACPI_STATUS             Status;
    813     ACPI_PARSE_OBJECT       *OutOp;
    814 
    815 
    816     WalkState->Op = Op;
    817     WalkState->Opcode = Op->Common.AmlOpcode;
    818     WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
    819 
    820     /* Copy child pointer to Arg for compatibility with Interpreter */
    821 
    822     if (Op->Asl.Child)
    823     {
    824         Op->Common.Value.Arg = Op->Asl.Child;
    825     }
    826 
    827     /* Call AML dispatcher */
    828 
    829     Status = AcpiDsExecBeginOp (WalkState, &OutOp);
    830     if (ACPI_FAILURE (Status))
    831     {
    832         DbgPrint (ASL_PARSE_OUTPUT,
    833             "%s Constant interpretation failed (1) - %s\n",
    834             Op->Asl.ParseOpName, AcpiFormatException (Status));
    835     }
    836 
    837     return (Status);
    838 }
    839 
    840 
    841 /*******************************************************************************
    842  *
    843  * FUNCTION:    OpcAmlEvaluationWalk2
    844  *
    845  * PARAMETERS:  ASL_WALK_CALLBACK
    846  *
    847  * RETURN:      Status
    848  *
    849  * DESCRIPTION: Ascending callback for AML execution of constant subtrees
    850  *
    851  ******************************************************************************/
    852 
    853 static ACPI_STATUS
    854 OpcAmlEvaluationWalk2 (
    855     ACPI_PARSE_OBJECT       *Op,
    856     UINT32                  Level,
    857     void                    *Context)
    858 {
    859     ACPI_WALK_STATE         *WalkState = Context;
    860     ACPI_STATUS             Status;
    861 
    862 
    863     WalkState->Op = Op;
    864     WalkState->Opcode = Op->Common.AmlOpcode;
    865     WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
    866 
    867     /* Copy child pointer to Arg for compatibility with Interpreter */
    868 
    869     if (Op->Asl.Child)
    870     {
    871         Op->Common.Value.Arg = Op->Asl.Child;
    872     }
    873 
    874     /* Call AML dispatcher */
    875 
    876     Status = AcpiDsExecEndOp (WalkState);
    877     if (ACPI_FAILURE (Status))
    878     {
    879         DbgPrint (ASL_PARSE_OUTPUT,
    880             "%s: Constant interpretation failed (2) - %s\n",
    881             Op->Asl.ParseOpName, AcpiFormatException (Status));
    882     }
    883 
    884     return (Status);
    885 }
    886