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