Home | History | Annotate | Line # | Download | only in compiler
      1 /******************************************************************************
      2  *
      3  * Module Name: aslfold - Constant folding
      4  *
      5  *****************************************************************************/
      6 
      7 /******************************************************************************
      8  *
      9  * 1. Copyright Notice
     10  *
     11  * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
     12  * All rights reserved.
     13  *
     14  * 2. License
     15  *
     16  * 2.1. This is your license from Intel Corp. under its intellectual property
     17  * rights. You may have additional license terms from the party that provided
     18  * you this software, covering your right to use that party's intellectual
     19  * property rights.
     20  *
     21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
     22  * copy of the source code appearing in this file ("Covered Code") an
     23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
     24  * base code distributed originally by Intel ("Original Intel Code") to copy,
     25  * make derivatives, distribute, use and display any portion of the Covered
     26  * Code in any form, with the right to sublicense such rights; and
     27  *
     28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
     29  * license (with the right to sublicense), under only those claims of Intel
     30  * patents that are infringed by the Original Intel Code, to make, use, sell,
     31  * offer to sell, and import the Covered Code and derivative works thereof
     32  * solely to the minimum extent necessary to exercise the above copyright
     33  * license, and in no event shall the patent license extend to any additions
     34  * to or modifications of the Original Intel Code. No other license or right
     35  * is granted directly or by implication, estoppel or otherwise;
     36  *
     37  * The above copyright and patent license is granted only if the following
     38  * conditions are met:
     39  *
     40  * 3. Conditions
     41  *
     42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
     43  * Redistribution of source code of any substantial portion of the Covered
     44  * Code or modification with rights to further distribute source must include
     45  * the above Copyright Notice, the above License, this list of Conditions,
     46  * and the following Disclaimer and Export Compliance provision. In addition,
     47  * Licensee must cause all Covered Code to which Licensee contributes to
     48  * contain a file documenting the changes Licensee made to create that Covered
     49  * Code and the date of any change. Licensee must include in that file the
     50  * documentation of any changes made by any predecessor Licensee. Licensee
     51  * must include a prominent statement that the modification is derived,
     52  * directly or indirectly, from Original Intel Code.
     53  *
     54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
     55  * Redistribution of source code of any substantial portion of the Covered
     56  * Code or modification without rights to further distribute source must
     57  * include the following Disclaimer and Export Compliance provision in the
     58  * documentation and/or other materials provided with distribution. In
     59  * addition, Licensee may not authorize further sublicense of source of any
     60  * portion of the Covered Code, and must include terms to the effect that the
     61  * license from Licensee to its licensee is limited to the intellectual
     62  * property embodied in the software Licensee provides to its licensee, and
     63  * not to intellectual property embodied in modifications its licensee may
     64  * make.
     65  *
     66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
     67  * substantial portion of the Covered Code or modification must reproduce the
     68  * above Copyright Notice, and the following Disclaimer and Export Compliance
     69  * provision in the documentation and/or other materials provided with the
     70  * distribution.
     71  *
     72  * 3.4. Intel retains all right, title, and interest in and to the Original
     73  * Intel Code.
     74  *
     75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
     76  * Intel shall be used in advertising or otherwise to promote the sale, use or
     77  * other dealings in products derived from or relating to the Covered Code
     78  * without prior written authorization from Intel.
     79  *
     80  * 4. Disclaimer and Export Compliance
     81  *
     82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
     83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
     84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
     85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
     86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
     87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
     88  * PARTICULAR PURPOSE.
     89  *
     90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
     91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
     92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
     93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
     94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
     95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
     96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
     97  * LIMITED REMEDY.
     98  *
     99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
    100  * software or system incorporating such software without first obtaining any
    101  * required license or other approval from the U. S. Department of Commerce or
    102  * any other agency or department of the United States Government. In the
    103  * event Licensee exports any such software from the United States or
    104  * re-exports any such software from a foreign destination, Licensee shall
    105  * ensure that the distribution and export/re-export of the software is in
    106  * compliance with all laws, regulations, orders, or other restrictions of the
    107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
    108  * any of its subsidiaries will export/re-export any technical data, process,
    109  * software, or service, directly or indirectly, to any country for which the
    110  * United States government or any agency thereof requires an export license,
    111  * other governmental approval, or letter of assurance, without first obtaining
    112  * such license, approval or letter.
    113  *
    114  *****************************************************************************
    115  *
    116  * Alternatively, you may choose to be licensed under the terms of the
    117  * following license:
    118  *
    119  * Redistribution and use in source and binary forms, with or without
    120  * modification, are permitted provided that the following conditions
    121  * are met:
    122  * 1. Redistributions of source code must retain the above copyright
    123  *    notice, this list of conditions, and the following disclaimer,
    124  *    without modification.
    125  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
    126  *    substantially similar to the "NO WARRANTY" disclaimer below
    127  *    ("Disclaimer") and any redistribution must be conditioned upon
    128  *    including a substantially similar Disclaimer requirement for further
    129  *    binary redistribution.
    130  * 3. Neither the names of the above-listed copyright holders nor the names
    131  *    of any contributors may be used to endorse or promote products derived
    132  *    from this software without specific prior written permission.
    133  *
    134  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    135  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    136  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    137  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    138  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    139  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    140  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    141  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    142  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    143  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    144  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    145  *
    146  * Alternatively, you may choose to be licensed under the terms of the
    147  * GNU General Public License ("GPL") version 2 as published by the Free
    148  * Software Foundation.
    149  *
    150  *****************************************************************************/
    151 
    152 #include "aslcompiler.h"
    153 #include "aslcompiler.y.h"
    154 #include "amlcode.h"
    155 
    156 #include "acdispat.h"
    157 #include "acparser.h"
    158 
    159 #define _COMPONENT          ACPI_COMPILER
    160         ACPI_MODULE_NAME    ("aslfold")
    161 
    162 /* Local prototypes */
    163 
    164 static ACPI_STATUS
    165 OpcAmlEvaluationWalk1 (
    166     ACPI_PARSE_OBJECT       *Op,
    167     UINT32                  Level,
    168     void                    *Context);
    169 
    170 static ACPI_STATUS
    171 OpcAmlEvaluationWalk2 (
    172     ACPI_PARSE_OBJECT       *Op,
    173     UINT32                  Level,
    174     void                    *Context);
    175 
    176 static ACPI_STATUS
    177 OpcAmlCheckForConstant (
    178     ACPI_PARSE_OBJECT       *Op,
    179     UINT32                  Level,
    180     void                    *Context);
    181 
    182 static void
    183 OpcUpdateIntegerNode (
    184     ACPI_PARSE_OBJECT       *Op,
    185     UINT64                  Value);
    186 
    187 static ACPI_STATUS
    188 TrTransformToStoreOp (
    189     ACPI_PARSE_OBJECT       *Op,
    190     ACPI_WALK_STATE         *WalkState);
    191 
    192 static ACPI_STATUS
    193 TrSimpleConstantReduction (
    194     ACPI_PARSE_OBJECT       *Op,
    195     ACPI_WALK_STATE         *WalkState);
    196 
    197 static void
    198 TrInstallReducedConstant (
    199     ACPI_PARSE_OBJECT       *Op,
    200     ACPI_OPERAND_OBJECT     *ObjDesc);
    201 
    202 
    203 /*******************************************************************************
    204  *
    205  * FUNCTION:    OpcAmlConstantWalk
    206  *
    207  * PARAMETERS:  ASL_WALK_CALLBACK
    208  *
    209  * RETURN:      Status
    210  *
    211  * DESCRIPTION: Reduce an Op and its subtree to a constant if possible.
    212  *              Called during ascent of the parse tree.
    213  *
    214  ******************************************************************************/
    215 
    216 ACPI_STATUS
    217 OpcAmlConstantWalk (
    218     ACPI_PARSE_OBJECT       *Op,
    219     UINT32                  Level,
    220     void                    *Context)
    221 {
    222     ACPI_WALK_STATE         *WalkState;
    223     ACPI_STATUS             Status = AE_OK;
    224 
    225 
    226     if (Op->Asl.CompileFlags == 0)
    227     {
    228         return (AE_OK);
    229     }
    230 
    231     /*
    232      * Only interested in subtrees that could possibly contain
    233      * expressions that can be evaluated at this time
    234      */
    235     if ((!(Op->Asl.CompileFlags & OP_COMPILE_TIME_CONST)) ||
    236           (Op->Asl.CompileFlags & OP_IS_TARGET))
    237     {
    238         return (AE_OK);
    239     }
    240 
    241     /* Create a new walk state */
    242 
    243     WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);
    244     if (!WalkState)
    245     {
    246         return (AE_NO_MEMORY);
    247     }
    248 
    249     WalkState->NextOp = NULL;
    250     WalkState->Params = NULL;
    251 
    252     /*
    253      * Examine the entire subtree -- all nodes must be constants
    254      * or type 3/4/5 opcodes
    255      */
    256     Status = TrWalkParseTree (Op, ASL_WALK_VISIT_DOWNWARD,
    257         OpcAmlCheckForConstant, NULL, WalkState);
    258 
    259     /*
    260      * Did we find an entire subtree that contains all constants
    261      * and type 3/4/5 opcodes?
    262      */
    263     switch (Status)
    264     {
    265     case AE_OK:
    266 
    267         /* Simple case, like Add(3,4) -> 7 */
    268 
    269         Status = TrSimpleConstantReduction (Op, WalkState);
    270         break;
    271 
    272     case AE_CTRL_RETURN_VALUE:
    273 
    274         /* More complex case, like Add(3,4,Local0) -> Store(7,Local0) */
    275 
    276         Status = TrTransformToStoreOp (Op, WalkState);
    277         break;
    278 
    279     case AE_TYPE:
    280 
    281         AcpiDsDeleteWalkState (WalkState);
    282         return (AE_OK);
    283 
    284     default:
    285         AcpiDsDeleteWalkState (WalkState);
    286         break;
    287     }
    288 
    289     if (ACPI_FAILURE (Status))
    290     {
    291         DbgPrint (ASL_PARSE_OUTPUT, "Cannot resolve, %s\n",
    292             AcpiFormatException (Status));
    293 
    294         /* We could not resolve the subtree for some reason */
    295 
    296         AslError (ASL_ERROR, ASL_MSG_CONSTANT_EVALUATION, Op,
    297             (char *) AcpiFormatException (Status));
    298 
    299         /* Set the subtree value to ZERO anyway. Eliminates further errors */
    300 
    301         OpcUpdateIntegerNode (Op, 0);
    302     }
    303 
    304     return (AE_OK);
    305 }
    306 
    307 
    308 /*******************************************************************************
    309  *
    310  * FUNCTION:    OpcAmlCheckForConstant
    311  *
    312  * PARAMETERS:  ASL_WALK_CALLBACK
    313  *
    314  * RETURN:      Status
    315  *
    316  * DESCRIPTION: Check one Op for a reducible type 3/4/5 AML opcode.
    317  *              This is performed via an upward walk of the parse subtree.
    318  *
    319  ******************************************************************************/
    320 
    321 static ACPI_STATUS
    322 OpcAmlCheckForConstant (
    323     ACPI_PARSE_OBJECT       *Op,
    324     UINT32                  Level,
    325     void                    *Context)
    326 {
    327     ACPI_WALK_STATE         *WalkState = Context;
    328     ACPI_STATUS             Status = AE_OK;
    329     ACPI_PARSE_OBJECT       *NextOp;
    330     const ACPI_OPCODE_INFO  *OpInfo;
    331 
    332 
    333     WalkState->Op = Op;
    334     WalkState->Opcode = Op->Common.AmlOpcode;
    335     WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
    336 
    337     DbgPrint (ASL_PARSE_OUTPUT, "[%.4d] Opcode: %12.12s ",
    338         Op->Asl.LogicalLineNumber, Op->Asl.ParseOpName);
    339 
    340     /*
    341      * These opcodes do not appear in the OpcodeInfo table, but
    342      * they represent constants, so abort the constant walk now.
    343      */
    344     if ((WalkState->Opcode == AML_RAW_DATA_BYTE) ||
    345         (WalkState->Opcode == AML_RAW_DATA_WORD) ||
    346         (WalkState->Opcode == AML_RAW_DATA_DWORD) ||
    347         (WalkState->Opcode == AML_RAW_DATA_QWORD))
    348     {
    349         DbgPrint (ASL_PARSE_OUTPUT, "RAW DATA");
    350         Status = AE_TYPE;
    351         goto CleanupAndExit;
    352     }
    353 
    354     /*
    355      * Search upwards for a possible Name() operator. This is done
    356      * because a type 3/4/5 opcode within a Name() expression
    357      * MUST be reduced to a simple constant.
    358      */
    359     NextOp = Op->Asl.Parent;
    360     while (NextOp)
    361     {
    362         /* Finished if we find a Name() opcode */
    363 
    364         if (NextOp->Asl.AmlOpcode == AML_NAME_OP)
    365         {
    366             break;
    367         }
    368 
    369         /*
    370          * Any "deferred" opcodes contain one or more TermArg parameters,
    371          * and thus are not required to be folded to constants at compile
    372          * time. This affects things like Buffer() and Package() objects.
    373          * We just ignore them here. However, any sub-expressions can and
    374          * will still be typechecked. Note: These are called the
    375          * "deferred" opcodes in the AML interpreter.
    376          */
    377         OpInfo = AcpiPsGetOpcodeInfo (NextOp->Common.AmlOpcode);
    378         if (OpInfo->Flags & AML_DEFER)
    379         {
    380             NextOp = NULL;
    381             break;
    382         }
    383 
    384         NextOp = NextOp->Asl.Parent;
    385     }
    386 
    387     /* Type 3/4/5 opcodes have the AML_CONSTANT flag set */
    388 
    389     if (!(WalkState->OpInfo->Flags & AML_CONSTANT))
    390     {
    391         /*
    392          * From the ACPI specification:
    393          *
    394          * "The Type 3/4/5 opcodes return a value and can be used in an
    395          * expression that evaluates to a constant. These opcodes may be
    396          * evaluated at ASL compile-time. To ensure that these opcodes
    397          * will evaluate to a constant, the following rules apply: The
    398          * term cannot have a destination (target) operand, and must have
    399          * either a Type3Opcode, Type4Opcode, Type5Opcode, ConstExprTerm,
    400          * Integer, BufferTerm, Package, or String for all arguments."
    401          */
    402 
    403         /*
    404          * The value (second) operand for the Name() operator MUST
    405          * reduce to a single constant, as per the ACPI specification
    406          * (the operand is a DataObject). This also implies that there
    407          * can be no target operand. Name() is the only ASL operator
    408          * with a "DataObject" as an operand and is thus special-
    409          * cased here.
    410          */
    411         if (NextOp) /* Inspect a Name() operator */
    412         {
    413             /* Error if there is a target operand */
    414 
    415             if (Op->Asl.CompileFlags & OP_IS_TARGET)
    416             {
    417                 AslError (ASL_ERROR, ASL_MSG_INVALID_TARGET, Op, NULL);
    418                 Status = AE_TYPE;
    419             }
    420 
    421             /* Error if expression cannot be reduced (folded) */
    422 
    423             if (!(NextOp->Asl.CompileFlags & OP_COULD_NOT_REDUCE))
    424             {
    425                 /* Ensure only one error message per statement */
    426 
    427                 NextOp->Asl.CompileFlags |= OP_COULD_NOT_REDUCE;
    428                 DbgPrint (ASL_PARSE_OUTPUT,
    429                     "**** Could not reduce operands for NAME opcode ****\n");
    430 
    431                 AslError (ASL_ERROR, ASL_MSG_CONSTANT_REQUIRED, Op,
    432                     "Constant is required for Name operator");
    433                 Status = AE_TYPE;
    434             }
    435         }
    436 
    437         if (ACPI_FAILURE (Status))
    438         {
    439             goto CleanupAndExit;
    440         }
    441 
    442         /* This is not a 3/4/5 opcode, but maybe can convert to STORE */
    443 
    444         if (Op->Asl.CompileFlags & OP_IS_TARGET)
    445         {
    446             DbgPrint (ASL_PARSE_OUTPUT,
    447                 "**** Valid Target, transform to Store or CopyObject ****\n");
    448             return (AE_CTRL_RETURN_VALUE);
    449         }
    450 
    451         /* Expression cannot be reduced */
    452 
    453         DbgPrint (ASL_PARSE_OUTPUT,
    454             "**** Not a Type 3/4/5 opcode or cannot reduce/fold (%s) ****\n",
    455              Op->Asl.ParseOpName);
    456 
    457         Status = AE_TYPE;
    458         goto CleanupAndExit;
    459     }
    460 
    461     /*
    462      * TBD: Ignore buffer constants for now. The problem is that these
    463      * constants have been transformed into RAW_DATA at this point, from
    464      * the parse tree transform process which currently happens before
    465      * the constant folding process. We may need to defer this transform
    466      * for buffer until after the constant folding.
    467      */
    468     if (WalkState->Opcode == AML_BUFFER_OP)
    469     {
    470         DbgPrint (ASL_PARSE_OUTPUT,
    471             "\nBuffer constant reduction is currently not supported\n");
    472 
    473         if (NextOp) /* Found a Name() operator, error */
    474         {
    475             AslError (ASL_ERROR, ASL_MSG_UNSUPPORTED, Op,
    476                 "Buffer expression cannot be reduced");
    477         }
    478 
    479         Status = AE_TYPE;
    480         goto CleanupAndExit;
    481     }
    482 
    483     /* Debug output */
    484 
    485     DbgPrint (ASL_PARSE_OUTPUT, "TYPE_345");
    486 
    487     if (Op->Asl.CompileFlags & OP_IS_TARGET)
    488     {
    489         if (Op->Asl.ParseOpcode == PARSEOP_ZERO)
    490         {
    491             DbgPrint (ASL_PARSE_OUTPUT, "%-16s", " NULL TARGET");
    492         }
    493         else
    494         {
    495             DbgPrint (ASL_PARSE_OUTPUT, "%-16s", " VALID TARGET");
    496         }
    497     }
    498 
    499     if (Op->Asl.CompileFlags & OP_IS_TERM_ARG)
    500     {
    501         DbgPrint (ASL_PARSE_OUTPUT, "%-16s", " TERMARG");
    502     }
    503 
    504 CleanupAndExit:
    505 
    506     /* Dump the node compile flags also */
    507 
    508     TrPrintOpFlags (Op->Asl.CompileFlags, ASL_PARSE_OUTPUT);
    509     DbgPrint (ASL_PARSE_OUTPUT, "\n");
    510     return (Status);
    511 }
    512 
    513 
    514 /*******************************************************************************
    515  *
    516  * FUNCTION:    TrSimpleConstantReduction
    517  *
    518  * PARAMETERS:  Op                  - Parent operator to be transformed
    519  *              WalkState           - Current walk state
    520  *
    521  * RETURN:      Status
    522  *
    523  * DESCRIPTION: Reduce an entire AML operation to a single constant. The
    524  *              operation must not have a target operand.
    525  *
    526  *              Add (32,64) --> 96
    527  *
    528  ******************************************************************************/
    529 
    530 static ACPI_STATUS
    531 TrSimpleConstantReduction (
    532     ACPI_PARSE_OBJECT       *Op,
    533     ACPI_WALK_STATE         *WalkState)
    534 {
    535     ACPI_PARSE_OBJECT       *RootOp;
    536     ACPI_PARSE_OBJECT       *OriginalParentOp;
    537     ACPI_OPERAND_OBJECT     *ObjDesc;
    538     ACPI_STATUS             Status;
    539 
    540 
    541     DbgPrint (ASL_PARSE_OUTPUT,
    542         "Simple subtree constant reduction, operator to constant\n");
    543 
    544     /* Allocate a new temporary root for this subtree */
    545 
    546     RootOp = TrAllocateOp (PARSEOP_INTEGER);
    547     if (!RootOp)
    548     {
    549         return (AE_NO_MEMORY);
    550     }
    551 
    552     RootOp->Common.AmlOpcode = AML_INT_EVAL_SUBTREE_OP;
    553 
    554     OriginalParentOp = Op->Common.Parent;
    555     Op->Common.Parent = RootOp;
    556 
    557     /* Hand off the subtree to the AML interpreter */
    558 
    559     WalkState->CallerReturnDesc = &ObjDesc;
    560 
    561     Status = TrWalkParseTree (Op, ASL_WALK_VISIT_TWICE,
    562         OpcAmlEvaluationWalk1, OpcAmlEvaluationWalk2, WalkState);
    563 
    564     /* Restore original parse tree */
    565 
    566     Op->Common.Parent = OriginalParentOp;
    567 
    568     if (ACPI_FAILURE (Status))
    569     {
    570         DbgPrint (ASL_PARSE_OUTPUT,
    571             "Constant Subtree evaluation(1), %s\n",
    572             AcpiFormatException (Status));
    573         return (Status);
    574     }
    575 
    576     /* Get the final result */
    577 
    578     Status = AcpiDsResultPop (&ObjDesc, WalkState);
    579     if (ACPI_FAILURE (Status))
    580     {
    581         DbgPrint (ASL_PARSE_OUTPUT,
    582             "Constant Subtree evaluation(2), %s\n",
    583             AcpiFormatException (Status));
    584         return (Status);
    585     }
    586 
    587     /* Disconnect any existing children, install new constant */
    588 
    589     Op->Asl.Child = NULL;
    590     TrInstallReducedConstant (Op, ObjDesc);
    591 
    592     UtSetParseOpName (Op);
    593     return (AE_OK);
    594 }
    595 
    596 
    597 /*******************************************************************************
    598  *
    599  * FUNCTION:    TrTransformToStoreOp
    600  *
    601  * PARAMETERS:  Op                  - Parent operator to be transformed
    602  *              WalkState           - Current walk state
    603  *
    604  * RETURN:      Status
    605  *
    606  * DESCRIPTION: Transforms a single AML operation with a constant and target
    607  *              to a simple store operation:
    608  *
    609  *              Add (32,64,DATA) --> Store (96,DATA)
    610  *
    611  ******************************************************************************/
    612 
    613 static ACPI_STATUS
    614 TrTransformToStoreOp (
    615     ACPI_PARSE_OBJECT       *Op,
    616     ACPI_WALK_STATE         *WalkState)
    617 {
    618     ACPI_PARSE_OBJECT       *OriginalTarget;
    619     ACPI_PARSE_OBJECT       *NewTarget;
    620     ACPI_PARSE_OBJECT       *Child1;
    621     ACPI_PARSE_OBJECT       *Child2;
    622     ACPI_OPERAND_OBJECT     *ObjDesc;
    623     ACPI_PARSE_OBJECT       *NewParent;
    624     ACPI_PARSE_OBJECT       *OriginalParent;
    625     ACPI_STATUS             Status;
    626     UINT16                  NewParseOpcode;
    627     UINT16                  NewAmlOpcode;
    628 
    629 
    630     /* Extract the operands */
    631 
    632     Child1 = Op->Asl.Child;
    633     Child2 = Child1->Asl.Next;
    634 
    635     /*
    636      * Special case for DIVIDE -- it has two targets. The first
    637      * is for the remainder and if present, we will not attempt
    638      * to reduce the expression.
    639      */
    640     if (Op->Asl.ParseOpcode == PARSEOP_DIVIDE)
    641     {
    642         Child2 = Child2->Asl.Next;
    643         if (Child2->Asl.ParseOpcode != PARSEOP_ZERO)
    644         {
    645             DbgPrint (ASL_PARSE_OUTPUT,
    646                 "Cannot reduce DIVIDE - has two targets\n\n");
    647             return (AE_OK);
    648         }
    649     }
    650 
    651     switch (Op->Asl.ParseOpcode)
    652     {
    653     /*
    654      * Folding of the explicit conversion opcodes must use CopyObject
    655      * instead of Store. This can change the object type of the target
    656      * operand, as per the ACPI specification:
    657      *
    658      * "If the ASL operator is one of the explicit conversion operators
    659      * (ToString, ToInteger, etc., and the CopyObject operator), no
    660      * [implicit] conversion is performed. (In other words, the result
    661      * object is stored directly to the target and completely overwrites
    662      * any existing object already stored at the target)"
    663      */
    664     case PARSEOP_TOINTEGER:
    665     case PARSEOP_TOSTRING:
    666     case PARSEOP_TOBUFFER:
    667     case PARSEOP_TODECIMALSTRING:
    668     case PARSEOP_TOHEXSTRING:
    669     case PARSEOP_TOBCD:
    670     case PARSEOP_FROMBCD:
    671 
    672         NewParseOpcode = PARSEOP_COPYOBJECT;
    673         NewAmlOpcode = AML_COPY_OBJECT_OP;
    674 
    675         DbgPrint (ASL_PARSE_OUTPUT,
    676             "Reduction/Transform to CopyObjectOp: CopyObject(%s, %s)\n",
    677             Child1->Asl.ParseOpName, Child2->Asl.ParseOpName);
    678         break;
    679 
    680     default:
    681 
    682         NewParseOpcode = PARSEOP_STORE;
    683         NewAmlOpcode = AML_STORE_OP;
    684 
    685         DbgPrint (ASL_PARSE_OUTPUT,
    686             "Reduction/Transform to StoreOp: Store(%s, %s)\n",
    687             Child1->Asl.ParseOpName, Child2->Asl.ParseOpName);
    688         break;
    689     }
    690 
    691     /*
    692      * Create a NULL (zero) target so that we can use the
    693      * interpreter to evaluate the expression.
    694      */
    695     NewTarget = TrCreateNullTargetOp ();
    696     NewTarget->Common.AmlOpcode = AML_INT_NAMEPATH_OP;
    697 
    698     /* Handle one-operand cases (NOT, TOBCD, etc.) */
    699 
    700     if (!Child2->Asl.Next)
    701     {
    702         Child2 = Child1;
    703     }
    704 
    705     /* Link in new NULL target as the last operand */
    706 
    707     OriginalTarget = Child2->Asl.Next;
    708     Child2->Asl.Next = NewTarget;
    709     NewTarget->Asl.Parent = OriginalTarget->Asl.Parent;
    710 
    711     NewParent = TrAllocateOp (PARSEOP_INTEGER);
    712     NewParent->Common.AmlOpcode = AML_INT_EVAL_SUBTREE_OP;
    713 
    714     OriginalParent = Op->Common.Parent;
    715     Op->Common.Parent = NewParent;
    716 
    717     /* Hand off the subtree to the AML interpreter */
    718 
    719     WalkState->CallerReturnDesc = &ObjDesc;
    720 
    721     Status = TrWalkParseTree (Op, ASL_WALK_VISIT_TWICE,
    722         OpcAmlEvaluationWalk1, OpcAmlEvaluationWalk2, WalkState);
    723     if (ACPI_FAILURE (Status))
    724     {
    725         DbgPrint (ASL_PARSE_OUTPUT,
    726             "Constant Subtree evaluation(3), %s\n",
    727             AcpiFormatException (Status));
    728         goto EvalError;
    729     }
    730 
    731     /* Get the final result */
    732 
    733     Status = AcpiDsResultPop (&ObjDesc, WalkState);
    734     if (ACPI_FAILURE (Status))
    735     {
    736         DbgPrint (ASL_PARSE_OUTPUT,
    737             "Constant Subtree evaluation(4), %s\n",
    738             AcpiFormatException (Status));
    739         goto EvalError;
    740     }
    741 
    742     /* Truncate any subtree expressions, they have been evaluated */
    743 
    744     Child1->Asl.Child = NULL;
    745 
    746     /* Folded constant is in ObjDesc, store into Child1 */
    747 
    748     TrInstallReducedConstant (Child1, ObjDesc);
    749 
    750     /* Convert operator to STORE or COPYOBJECT */
    751 
    752     Op->Asl.ParseOpcode = NewParseOpcode;
    753     Op->Asl.AmlOpcode = NewAmlOpcode;
    754     UtSetParseOpName (Op);
    755     Op->Common.Parent = OriginalParent;
    756 
    757     /* First child is the folded constant */
    758 
    759     /* Second child will be the target */
    760 
    761     Child1->Asl.Next = OriginalTarget;
    762     return (AE_OK);
    763 
    764 
    765 EvalError:
    766 
    767     /* Restore original links */
    768 
    769     Op->Common.Parent = OriginalParent;
    770     Child2->Asl.Next = OriginalTarget;
    771     return (Status);
    772 }
    773 
    774 
    775 /*******************************************************************************
    776  *
    777  * FUNCTION:    TrInstallReducedConstant
    778  *
    779  * PARAMETERS:  Op                  - Parent operator to be transformed
    780  *              ObjDesc             - Reduced constant to be installed
    781  *
    782  * RETURN:      None
    783  *
    784  * DESCRIPTION: Transform the original operator to a simple constant.
    785  *              Handles Integers, Strings, and Buffers.
    786  *
    787  ******************************************************************************/
    788 
    789 static void
    790 TrInstallReducedConstant (
    791     ACPI_PARSE_OBJECT       *Op,
    792     ACPI_OPERAND_OBJECT     *ObjDesc)
    793 {
    794     ACPI_PARSE_OBJECT       *LengthOp;
    795     ACPI_PARSE_OBJECT       *DataOp;
    796 
    797 
    798     AslGbl_TotalFolds++;
    799     AslError (ASL_OPTIMIZATION, ASL_MSG_CONSTANT_FOLDED, Op,
    800         Op->Asl.ParseOpName);
    801 
    802     /*
    803      * Because we know we executed type 3/4/5 opcodes above, we know that
    804      * the result must be either an Integer, String, or Buffer.
    805      */
    806     switch (ObjDesc->Common.Type)
    807     {
    808     case ACPI_TYPE_INTEGER:
    809 
    810         OpcUpdateIntegerNode (Op, ObjDesc->Integer.Value);
    811 
    812         DbgPrint (ASL_PARSE_OUTPUT,
    813             "Constant expression reduced to (%s) %8.8X%8.8X\n\n",
    814             Op->Asl.ParseOpName,
    815             ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
    816         break;
    817 
    818     case ACPI_TYPE_STRING:
    819 
    820         Op->Asl.ParseOpcode = PARSEOP_STRING_LITERAL;
    821         Op->Common.AmlOpcode = AML_STRING_OP;
    822         Op->Asl.AmlLength = strlen (ObjDesc->String.Pointer) + 1;
    823         Op->Common.Value.String = ObjDesc->String.Pointer;
    824 
    825         DbgPrint (ASL_PARSE_OUTPUT,
    826             "Constant expression reduced to (STRING) %s\n\n",
    827             Op->Common.Value.String);
    828         break;
    829 
    830     case ACPI_TYPE_BUFFER:
    831         /*
    832          * Create a new parse subtree of the form:
    833          *
    834          * BUFFER (Buffer AML opcode)
    835          *    INTEGER (Buffer length in bytes)
    836          *    RAW_DATA (Buffer byte data)
    837          */
    838         Op->Asl.ParseOpcode = PARSEOP_BUFFER;
    839         Op->Common.AmlOpcode = AML_BUFFER_OP;
    840         Op->Asl.CompileFlags = OP_AML_PACKAGE;
    841         UtSetParseOpName (Op);
    842 
    843         /* Child node is the buffer length */
    844 
    845         LengthOp = TrAllocateOp (PARSEOP_INTEGER);
    846 
    847         LengthOp->Asl.AmlOpcode = AML_DWORD_OP;
    848         LengthOp->Asl.Value.Integer = ObjDesc->Buffer.Length;
    849         LengthOp->Asl.Parent = Op;
    850         (void) OpcSetOptimalIntegerSize (LengthOp);
    851 
    852         Op->Asl.Child = LengthOp;
    853 
    854         /* Next child is the raw buffer data */
    855 
    856         DataOp = TrAllocateOp (PARSEOP_RAW_DATA);
    857         DataOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;
    858         DataOp->Asl.AmlLength = ObjDesc->Buffer.Length;
    859         DataOp->Asl.Value.String = (char *) ObjDesc->Buffer.Pointer;
    860         DataOp->Asl.Parent = Op;
    861 
    862         LengthOp->Asl.Next = DataOp;
    863 
    864         DbgPrint (ASL_PARSE_OUTPUT,
    865             "Constant expression reduced to (BUFFER) length %X\n\n",
    866             ObjDesc->Buffer.Length);
    867         break;
    868 
    869     default:
    870         break;
    871     }
    872 }
    873 
    874 
    875 /*******************************************************************************
    876  *
    877  * FUNCTION:    OpcUpdateIntegerNode
    878  *
    879  * PARAMETERS:  Op                  - Current parse object
    880  *              Value               - Value for the integer op
    881  *
    882  * RETURN:      None
    883  *
    884  * DESCRIPTION: Update node to the correct Integer type and value
    885  *
    886  ******************************************************************************/
    887 
    888 static void
    889 OpcUpdateIntegerNode (
    890     ACPI_PARSE_OBJECT       *Op,
    891     UINT64                  Value)
    892 {
    893 
    894     Op->Common.Value.Integer = Value;
    895 
    896     /*
    897      * The AmlLength is used by the parser to indicate a constant,
    898      * (if non-zero). Length is either (1/2/4/8)
    899      */
    900     switch (Op->Asl.AmlLength)
    901     {
    902     case 1:
    903 
    904         TrSetOpIntegerValue (PARSEOP_BYTECONST, Op);
    905         Op->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
    906         break;
    907 
    908     case 2:
    909 
    910         TrSetOpIntegerValue (PARSEOP_WORDCONST, Op);
    911         Op->Asl.AmlOpcode = AML_RAW_DATA_WORD;
    912         break;
    913 
    914     case 4:
    915 
    916         TrSetOpIntegerValue (PARSEOP_DWORDCONST, Op);
    917         Op->Asl.AmlOpcode = AML_RAW_DATA_DWORD;
    918         break;
    919 
    920     case 8:
    921 
    922         TrSetOpIntegerValue (PARSEOP_QWORDCONST, Op);
    923         Op->Asl.AmlOpcode = AML_RAW_DATA_QWORD;
    924         break;
    925 
    926     case 0:
    927     default:
    928 
    929         OpcSetOptimalIntegerSize (Op);
    930         TrSetOpIntegerValue (PARSEOP_INTEGER, Op);
    931         break;
    932     }
    933 
    934     Op->Asl.AmlLength = 0;
    935 }
    936 
    937 
    938 /*******************************************************************************
    939  *
    940  * FUNCTION:    OpcAmlEvaluationWalk1
    941  *
    942  * PARAMETERS:  ASL_WALK_CALLBACK
    943  *
    944  * RETURN:      Status
    945  *
    946  * DESCRIPTION: Descending callback for AML execution of constant subtrees
    947  *
    948  ******************************************************************************/
    949 
    950 static ACPI_STATUS
    951 OpcAmlEvaluationWalk1 (
    952     ACPI_PARSE_OBJECT       *Op,
    953     UINT32                  Level,
    954     void                    *Context)
    955 {
    956     ACPI_WALK_STATE         *WalkState = Context;
    957     ACPI_STATUS             Status;
    958     ACPI_PARSE_OBJECT       *OutOp;
    959 
    960 
    961     WalkState->Op = Op;
    962     WalkState->Opcode = Op->Common.AmlOpcode;
    963     WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
    964 
    965     /* Copy child pointer to Arg for compatibility with Interpreter */
    966 
    967     if (Op->Asl.Child)
    968     {
    969         Op->Common.Value.Arg = Op->Asl.Child;
    970     }
    971 
    972     /* Call AML dispatcher */
    973 
    974     Status = AcpiDsExecBeginOp (WalkState, &OutOp);
    975     if (ACPI_FAILURE (Status))
    976     {
    977         DbgPrint (ASL_PARSE_OUTPUT,
    978             "%s Constant interpretation failed (1) - %s\n",
    979             Op->Asl.ParseOpName, AcpiFormatException (Status));
    980     }
    981 
    982     return (Status);
    983 }
    984 
    985 
    986 /*******************************************************************************
    987  *
    988  * FUNCTION:    OpcAmlEvaluationWalk2
    989  *
    990  * PARAMETERS:  ASL_WALK_CALLBACK
    991  *
    992  * RETURN:      Status
    993  *
    994  * DESCRIPTION: Ascending callback for AML execution of constant subtrees
    995  *
    996  ******************************************************************************/
    997 
    998 static ACPI_STATUS
    999 OpcAmlEvaluationWalk2 (
   1000     ACPI_PARSE_OBJECT       *Op,
   1001     UINT32                  Level,
   1002     void                    *Context)
   1003 {
   1004     ACPI_WALK_STATE         *WalkState = Context;
   1005     ACPI_STATUS             Status;
   1006 
   1007 
   1008     WalkState->Op = Op;
   1009     WalkState->Opcode = Op->Common.AmlOpcode;
   1010     WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
   1011 
   1012     /* Copy child pointer to Arg for compatibility with Interpreter */
   1013 
   1014     if (Op->Asl.Child)
   1015     {
   1016         Op->Common.Value.Arg = Op->Asl.Child;
   1017     }
   1018 
   1019     /* Call AML dispatcher */
   1020 
   1021     Status = AcpiDsExecEndOp (WalkState);
   1022     if (ACPI_FAILURE (Status))
   1023     {
   1024         DbgPrint (ASL_PARSE_OUTPUT,
   1025             "%s: Constant interpretation failed (2) - %s\n",
   1026             Op->Asl.ParseOpName, AcpiFormatException (Status));
   1027     }
   1028 
   1029     return (Status);
   1030 }
   1031