Home | History | Annotate | Line # | Download | only in compiler
aslfold.c revision 1.1.1.11
      1 /******************************************************************************
      2  *
      3  * Module Name: aslfold - Constant folding
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2018, 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 or CopyObject ****\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 currently not supported\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     UINT16                  NewParseOpcode;
    519     UINT16                  NewAmlOpcode;
    520 
    521 
    522     /* Extract the operands */
    523 
    524     Child1 = Op->Asl.Child;
    525     Child2 = Child1->Asl.Next;
    526 
    527     /*
    528      * Special case for DIVIDE -- it has two targets. The first
    529      * is for the remainder and if present, we will not attempt
    530      * to reduce the expression.
    531      */
    532     if (Op->Asl.ParseOpcode == PARSEOP_DIVIDE)
    533     {
    534         Child2 = Child2->Asl.Next;
    535         if (Child2->Asl.ParseOpcode != PARSEOP_ZERO)
    536         {
    537             DbgPrint (ASL_PARSE_OUTPUT,
    538                 "Cannot reduce DIVIDE - has two targets\n\n");
    539             return (AE_OK);
    540         }
    541     }
    542 
    543     switch (Op->Asl.ParseOpcode)
    544     {
    545     /*
    546      * Folding of the explicit conversion opcodes must use CopyObject
    547      * instead of Store. This can change the object type of the target
    548      * operand, as per the ACPI specification:
    549      *
    550      * "If the ASL operator is one of the explicit conversion operators
    551      * (ToString, ToInteger, etc., and the CopyObject operator), no
    552      * [implicit] conversion is performed. (In other words, the result
    553      * object is stored directly to the target and completely overwrites
    554      * any existing object already stored at the target)"
    555      */
    556     case PARSEOP_TOINTEGER:
    557     case PARSEOP_TOSTRING:
    558     case PARSEOP_TOBUFFER:
    559     case PARSEOP_TODECIMALSTRING:
    560     case PARSEOP_TOHEXSTRING:
    561     case PARSEOP_TOBCD:
    562     case PARSEOP_FROMBCD:
    563 
    564         NewParseOpcode = PARSEOP_COPYOBJECT;
    565         NewAmlOpcode = AML_COPY_OBJECT_OP;
    566 
    567         DbgPrint (ASL_PARSE_OUTPUT,
    568             "Reduction/Transform to CopyObjectOp: CopyObject(%s, %s)\n",
    569             Child1->Asl.ParseOpName, Child2->Asl.ParseOpName);
    570         break;
    571 
    572     default:
    573 
    574         NewParseOpcode = PARSEOP_STORE;
    575         NewAmlOpcode = AML_STORE_OP;
    576 
    577         DbgPrint (ASL_PARSE_OUTPUT,
    578             "Reduction/Transform to StoreOp: Store(%s, %s)\n",
    579             Child1->Asl.ParseOpName, Child2->Asl.ParseOpName);
    580         break;
    581     }
    582 
    583     /*
    584      * Create a NULL (zero) target so that we can use the
    585      * interpreter to evaluate the expression.
    586      */
    587     NewTarget = TrCreateNullTargetOp ();
    588     NewTarget->Common.AmlOpcode = AML_INT_NAMEPATH_OP;
    589 
    590     /* Handle one-operand cases (NOT, TOBCD, etc.) */
    591 
    592     if (!Child2->Asl.Next)
    593     {
    594         Child2 = Child1;
    595     }
    596 
    597     /* Link in new NULL target as the last operand */
    598 
    599     OriginalTarget = Child2->Asl.Next;
    600     Child2->Asl.Next = NewTarget;
    601     NewTarget->Asl.Parent = OriginalTarget->Asl.Parent;
    602 
    603     NewParent = TrAllocateOp (PARSEOP_INTEGER);
    604     NewParent->Common.AmlOpcode = AML_INT_EVAL_SUBTREE_OP;
    605 
    606     OriginalParent = Op->Common.Parent;
    607     Op->Common.Parent = NewParent;
    608 
    609     /* Hand off the subtree to the AML interpreter */
    610 
    611     WalkState->CallerReturnDesc = &ObjDesc;
    612 
    613     Status = TrWalkParseTree (Op, ASL_WALK_VISIT_TWICE,
    614         OpcAmlEvaluationWalk1, OpcAmlEvaluationWalk2, WalkState);
    615     if (ACPI_FAILURE (Status))
    616     {
    617         DbgPrint (ASL_PARSE_OUTPUT,
    618             "Constant Subtree evaluation(3), %s\n",
    619             AcpiFormatException (Status));
    620         goto EvalError;
    621     }
    622 
    623     /* Get the final result */
    624 
    625     Status = AcpiDsResultPop (&ObjDesc, WalkState);
    626     if (ACPI_FAILURE (Status))
    627     {
    628         DbgPrint (ASL_PARSE_OUTPUT,
    629             "Constant Subtree evaluation(4), %s\n",
    630             AcpiFormatException (Status));
    631         goto EvalError;
    632     }
    633 
    634     /* Truncate any subtree expressions, they have been evaluated */
    635 
    636     Child1->Asl.Child = NULL;
    637 
    638     /* Folded constant is in ObjDesc, store into Child1 */
    639 
    640     TrInstallReducedConstant (Child1, ObjDesc);
    641 
    642     /* Convert operator to STORE or COPYOBJECT */
    643 
    644     Op->Asl.ParseOpcode = NewParseOpcode;
    645     Op->Asl.AmlOpcode = NewAmlOpcode;
    646     UtSetParseOpName (Op);
    647     Op->Common.Parent = OriginalParent;
    648 
    649     /* First child is the folded constant */
    650 
    651     /* Second child will be the target */
    652 
    653     Child1->Asl.Next = OriginalTarget;
    654     return (AE_OK);
    655 
    656 
    657 EvalError:
    658 
    659     /* Restore original links */
    660 
    661     Op->Common.Parent = OriginalParent;
    662     Child2->Asl.Next = OriginalTarget;
    663     return (Status);
    664 }
    665 
    666 
    667 /*******************************************************************************
    668  *
    669  * FUNCTION:    TrInstallReducedConstant
    670  *
    671  * PARAMETERS:  Op                  - Parent operator to be transformed
    672  *              ObjDesc             - Reduced constant to be installed
    673  *
    674  * RETURN:      None
    675  *
    676  * DESCRIPTION: Transform the original operator to a simple constant.
    677  *              Handles Integers, Strings, and Buffers.
    678  *
    679  ******************************************************************************/
    680 
    681 static void
    682 TrInstallReducedConstant (
    683     ACPI_PARSE_OBJECT       *Op,
    684     ACPI_OPERAND_OBJECT     *ObjDesc)
    685 {
    686     ACPI_PARSE_OBJECT       *LengthOp;
    687     ACPI_PARSE_OBJECT       *DataOp;
    688 
    689 
    690     TotalFolds++;
    691     AslError (ASL_OPTIMIZATION, ASL_MSG_CONSTANT_FOLDED, Op,
    692         Op->Asl.ParseOpName);
    693 
    694     /*
    695      * Because we know we executed type 3/4/5 opcodes above, we know that
    696      * the result must be either an Integer, String, or Buffer.
    697      */
    698     switch (ObjDesc->Common.Type)
    699     {
    700     case ACPI_TYPE_INTEGER:
    701 
    702         OpcUpdateIntegerNode (Op, ObjDesc->Integer.Value);
    703 
    704         DbgPrint (ASL_PARSE_OUTPUT,
    705             "Constant expression reduced to (%s) %8.8X%8.8X\n\n",
    706             Op->Asl.ParseOpName,
    707             ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
    708         break;
    709 
    710     case ACPI_TYPE_STRING:
    711 
    712         Op->Asl.ParseOpcode = PARSEOP_STRING_LITERAL;
    713         Op->Common.AmlOpcode = AML_STRING_OP;
    714         Op->Asl.AmlLength = strlen (ObjDesc->String.Pointer) + 1;
    715         Op->Common.Value.String = ObjDesc->String.Pointer;
    716 
    717         DbgPrint (ASL_PARSE_OUTPUT,
    718             "Constant expression reduced to (STRING) %s\n\n",
    719             Op->Common.Value.String);
    720         break;
    721 
    722     case ACPI_TYPE_BUFFER:
    723         /*
    724          * Create a new parse subtree of the form:
    725          *
    726          * BUFFER (Buffer AML opcode)
    727          *    INTEGER (Buffer length in bytes)
    728          *    RAW_DATA (Buffer byte data)
    729          */
    730         Op->Asl.ParseOpcode = PARSEOP_BUFFER;
    731         Op->Common.AmlOpcode = AML_BUFFER_OP;
    732         Op->Asl.CompileFlags = OP_AML_PACKAGE;
    733         UtSetParseOpName (Op);
    734 
    735         /* Child node is the buffer length */
    736 
    737         LengthOp = TrAllocateOp (PARSEOP_INTEGER);
    738 
    739         LengthOp->Asl.AmlOpcode = AML_DWORD_OP;
    740         LengthOp->Asl.Value.Integer = ObjDesc->Buffer.Length;
    741         LengthOp->Asl.Parent = Op;
    742         (void) OpcSetOptimalIntegerSize (LengthOp);
    743 
    744         Op->Asl.Child = LengthOp;
    745 
    746         /* Next child is the raw buffer data */
    747 
    748         DataOp = TrAllocateOp (PARSEOP_RAW_DATA);
    749         DataOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
    750         DataOp->Asl.AmlLength = ObjDesc->Buffer.Length;
    751         DataOp->Asl.Value.String = (char *) ObjDesc->Buffer.Pointer;
    752         DataOp->Asl.Parent = Op;
    753 
    754         LengthOp->Asl.Next = DataOp;
    755 
    756         DbgPrint (ASL_PARSE_OUTPUT,
    757             "Constant expression reduced to (BUFFER) length %X\n\n",
    758             ObjDesc->Buffer.Length);
    759         break;
    760 
    761     default:
    762         break;
    763     }
    764 }
    765 
    766 
    767 /*******************************************************************************
    768  *
    769  * FUNCTION:    OpcUpdateIntegerNode
    770  *
    771  * PARAMETERS:  Op                  - Current parse object
    772  *              Value               - Value for the integer op
    773  *
    774  * RETURN:      None
    775  *
    776  * DESCRIPTION: Update node to the correct Integer type and value
    777  *
    778  ******************************************************************************/
    779 
    780 static void
    781 OpcUpdateIntegerNode (
    782     ACPI_PARSE_OBJECT       *Op,
    783     UINT64                  Value)
    784 {
    785 
    786     Op->Common.Value.Integer = Value;
    787 
    788     /*
    789      * The AmlLength is used by the parser to indicate a constant,
    790      * (if non-zero). Length is either (1/2/4/8)
    791      */
    792     switch (Op->Asl.AmlLength)
    793     {
    794     case 1:
    795 
    796         TrSetOpIntegerValue (PARSEOP_BYTECONST, Op);
    797         Op->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
    798         break;
    799 
    800     case 2:
    801 
    802         TrSetOpIntegerValue (PARSEOP_WORDCONST, Op);
    803         Op->Asl.AmlOpcode = AML_RAW_DATA_WORD;
    804         break;
    805 
    806     case 4:
    807 
    808         TrSetOpIntegerValue (PARSEOP_DWORDCONST, Op);
    809         Op->Asl.AmlOpcode = AML_RAW_DATA_DWORD;
    810         break;
    811 
    812     case 8:
    813 
    814         TrSetOpIntegerValue (PARSEOP_QWORDCONST, Op);
    815         Op->Asl.AmlOpcode = AML_RAW_DATA_QWORD;
    816         break;
    817 
    818     case 0:
    819     default:
    820 
    821         OpcSetOptimalIntegerSize (Op);
    822         TrSetOpIntegerValue (PARSEOP_INTEGER, Op);
    823         break;
    824     }
    825 
    826     Op->Asl.AmlLength = 0;
    827 }
    828 
    829 
    830 /*******************************************************************************
    831  *
    832  * FUNCTION:    OpcAmlEvaluationWalk1
    833  *
    834  * PARAMETERS:  ASL_WALK_CALLBACK
    835  *
    836  * RETURN:      Status
    837  *
    838  * DESCRIPTION: Descending callback for AML execution of constant subtrees
    839  *
    840  ******************************************************************************/
    841 
    842 static ACPI_STATUS
    843 OpcAmlEvaluationWalk1 (
    844     ACPI_PARSE_OBJECT       *Op,
    845     UINT32                  Level,
    846     void                    *Context)
    847 {
    848     ACPI_WALK_STATE         *WalkState = Context;
    849     ACPI_STATUS             Status;
    850     ACPI_PARSE_OBJECT       *OutOp;
    851 
    852 
    853     WalkState->Op = Op;
    854     WalkState->Opcode = Op->Common.AmlOpcode;
    855     WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
    856 
    857     /* Copy child pointer to Arg for compatibility with Interpreter */
    858 
    859     if (Op->Asl.Child)
    860     {
    861         Op->Common.Value.Arg = Op->Asl.Child;
    862     }
    863 
    864     /* Call AML dispatcher */
    865 
    866     Status = AcpiDsExecBeginOp (WalkState, &OutOp);
    867     if (ACPI_FAILURE (Status))
    868     {
    869         DbgPrint (ASL_PARSE_OUTPUT,
    870             "%s Constant interpretation failed (1) - %s\n",
    871             Op->Asl.ParseOpName, AcpiFormatException (Status));
    872     }
    873 
    874     return (Status);
    875 }
    876 
    877 
    878 /*******************************************************************************
    879  *
    880  * FUNCTION:    OpcAmlEvaluationWalk2
    881  *
    882  * PARAMETERS:  ASL_WALK_CALLBACK
    883  *
    884  * RETURN:      Status
    885  *
    886  * DESCRIPTION: Ascending callback for AML execution of constant subtrees
    887  *
    888  ******************************************************************************/
    889 
    890 static ACPI_STATUS
    891 OpcAmlEvaluationWalk2 (
    892     ACPI_PARSE_OBJECT       *Op,
    893     UINT32                  Level,
    894     void                    *Context)
    895 {
    896     ACPI_WALK_STATE         *WalkState = Context;
    897     ACPI_STATUS             Status;
    898 
    899 
    900     WalkState->Op = Op;
    901     WalkState->Opcode = Op->Common.AmlOpcode;
    902     WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
    903 
    904     /* Copy child pointer to Arg for compatibility with Interpreter */
    905 
    906     if (Op->Asl.Child)
    907     {
    908         Op->Common.Value.Arg = Op->Asl.Child;
    909     }
    910 
    911     /* Call AML dispatcher */
    912 
    913     Status = AcpiDsExecEndOp (WalkState);
    914     if (ACPI_FAILURE (Status))
    915     {
    916         DbgPrint (ASL_PARSE_OUTPUT,
    917             "%s: Constant interpretation failed (2) - %s\n",
    918             Op->Asl.ParseOpName, AcpiFormatException (Status));
    919     }
    920 
    921     return (Status);
    922 }
    923