Home | History | Annotate | Line # | Download | only in compiler
aslfold.c revision 1.1.1.2
      1 
      2 /******************************************************************************
      3  *
      4  * Module Name: aslfold - Constant folding
      5  *
      6  *****************************************************************************/
      7 
      8 /*
      9  * Copyright (C) 2000 - 2011, Intel Corp.
     10  * All rights reserved.
     11  *
     12  * Redistribution and use in source and binary forms, with or without
     13  * modification, are permitted provided that the following conditions
     14  * are met:
     15  * 1. Redistributions of source code must retain the above copyright
     16  *    notice, this list of conditions, and the following disclaimer,
     17  *    without modification.
     18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
     19  *    substantially similar to the "NO WARRANTY" disclaimer below
     20  *    ("Disclaimer") and any redistribution must be conditioned upon
     21  *    including a substantially similar Disclaimer requirement for further
     22  *    binary redistribution.
     23  * 3. Neither the names of the above-listed copyright holders nor the names
     24  *    of any contributors may be used to endorse or promote products derived
     25  *    from this software without specific prior written permission.
     26  *
     27  * Alternatively, this software may be distributed under the terms of the
     28  * GNU General Public License ("GPL") version 2 as published by the Free
     29  * Software Foundation.
     30  *
     31  * NO WARRANTY
     32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
     35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     42  * POSSIBILITY OF SUCH DAMAGES.
     43  */
     44 
     45 
     46 #include "aslcompiler.h"
     47 #include "aslcompiler.y.h"
     48 #include "amlcode.h"
     49 
     50 #include "acdispat.h"
     51 #include "acparser.h"
     52 
     53 #define _COMPONENT          ACPI_COMPILER
     54         ACPI_MODULE_NAME    ("aslfold")
     55 
     56 /* Local prototypes */
     57 
     58 static ACPI_STATUS
     59 OpcAmlEvaluationWalk1 (
     60     ACPI_PARSE_OBJECT       *Op,
     61     UINT32                  Level,
     62     void                    *Context);
     63 
     64 static ACPI_STATUS
     65 OpcAmlEvaluationWalk2 (
     66     ACPI_PARSE_OBJECT       *Op,
     67     UINT32                  Level,
     68     void                    *Context);
     69 
     70 static ACPI_STATUS
     71 OpcAmlCheckForConstant (
     72     ACPI_PARSE_OBJECT       *Op,
     73     UINT32                  Level,
     74     void                    *Context);
     75 
     76 
     77 /*******************************************************************************
     78  *
     79  * FUNCTION:    OpcAmlEvaluationWalk1
     80  *
     81  * PARAMETERS:  ASL_WALK_CALLBACK
     82  *
     83  * RETURN:      Status
     84  *
     85  * DESCRIPTION: Descending callback for AML execution of constant subtrees
     86  *
     87  ******************************************************************************/
     88 
     89 static ACPI_STATUS
     90 OpcAmlEvaluationWalk1 (
     91     ACPI_PARSE_OBJECT       *Op,
     92     UINT32                  Level,
     93     void                    *Context)
     94 {
     95     ACPI_WALK_STATE         *WalkState = Context;
     96     ACPI_STATUS             Status;
     97     ACPI_PARSE_OBJECT       *OutOp;
     98 
     99 
    100     WalkState->Op = Op;
    101     WalkState->Opcode = Op->Common.AmlOpcode;
    102     WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
    103 
    104     /* Copy child pointer to Arg for compatibility with Interpreter */
    105 
    106     if (Op->Asl.Child)
    107     {
    108         Op->Common.Value.Arg = Op->Asl.Child;
    109     }
    110 
    111     /* Call AML dispatcher */
    112 
    113     Status = AcpiDsExecBeginOp (WalkState, &OutOp);
    114     if (ACPI_FAILURE (Status))
    115     {
    116         AcpiOsPrintf ("Constant interpretation failed - %s\n",
    117                         AcpiFormatException (Status));
    118     }
    119 
    120     return (Status);
    121 }
    122 
    123 
    124 /*******************************************************************************
    125  *
    126  * FUNCTION:    OpcAmlEvaluationWalk2
    127  *
    128  * PARAMETERS:  ASL_WALK_CALLBACK
    129  *
    130  * RETURN:      Status
    131  *
    132  * DESCRIPTION: Ascending callback for AML execution of constant subtrees
    133  *
    134  ******************************************************************************/
    135 
    136 static ACPI_STATUS
    137 OpcAmlEvaluationWalk2 (
    138     ACPI_PARSE_OBJECT       *Op,
    139     UINT32                  Level,
    140     void                    *Context)
    141 {
    142     ACPI_WALK_STATE         *WalkState = Context;
    143     ACPI_STATUS             Status;
    144 
    145 
    146     WalkState->Op = Op;
    147     WalkState->Opcode = Op->Common.AmlOpcode;
    148     WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
    149 
    150     /* Copy child pointer to Arg for compatibility with Interpreter */
    151 
    152     if (Op->Asl.Child)
    153     {
    154         Op->Common.Value.Arg = Op->Asl.Child;
    155     }
    156 
    157     /* Call AML dispatcher */
    158 
    159     Status = AcpiDsExecEndOp (WalkState);
    160     if (ACPI_FAILURE (Status))
    161     {
    162         AcpiOsPrintf ("Constant interpretation failed - %s\n",
    163                         AcpiFormatException (Status));
    164     }
    165 
    166     return (Status);
    167 }
    168 
    169 
    170 /*******************************************************************************
    171  *
    172  * FUNCTION:    OpcAmlCheckForConstant
    173  *
    174  * PARAMETERS:  ASL_WALK_CALLBACK
    175  *
    176  * RETURN:      Status
    177  *
    178  * DESCRIPTION: Check one Op for a type 3/4/5 AML opcode
    179  *
    180  ******************************************************************************/
    181 
    182 static ACPI_STATUS
    183 OpcAmlCheckForConstant (
    184     ACPI_PARSE_OBJECT       *Op,
    185     UINT32                  Level,
    186     void                    *Context)
    187 {
    188     ACPI_WALK_STATE         *WalkState = Context;
    189 
    190 
    191     WalkState->Op = Op;
    192     WalkState->Opcode = Op->Common.AmlOpcode;
    193     WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
    194 
    195     DbgPrint (ASL_PARSE_OUTPUT, "[%.4d] Opcode: %12.12s ",
    196                 Op->Asl.LogicalLineNumber, Op->Asl.ParseOpName);
    197 
    198     if (!(WalkState->OpInfo->Flags & AML_CONSTANT))
    199     {
    200         /* The opcode is not a Type 3/4/5 opcode */
    201 
    202         if (Op->Asl.CompileFlags & NODE_IS_TARGET)
    203         {
    204             DbgPrint (ASL_PARSE_OUTPUT,
    205                 "**** Valid Target, cannot reduce ****\n");
    206         }
    207         else
    208         {
    209             DbgPrint (ASL_PARSE_OUTPUT,
    210                 "**** Not a Type 3/4/5 opcode ****\n");
    211         }
    212 
    213         if (WalkState->WalkType == ACPI_WALK_CONST_OPTIONAL)
    214         {
    215             /*
    216              * We are looking at at normal expression to see if it can be
    217              * reduced.  It can't.  No error
    218              */
    219             return (AE_TYPE);
    220         }
    221 
    222         /*
    223          * This is an expression that MUST reduce to a constant, and it
    224          * can't be reduced.  This is an error
    225          */
    226         if (Op->Asl.CompileFlags & NODE_IS_TARGET)
    227         {
    228             AslError (ASL_ERROR, ASL_MSG_INVALID_TARGET, Op,
    229                 Op->Asl.ParseOpName);
    230         }
    231         else
    232         {
    233             AslError (ASL_ERROR, ASL_MSG_INVALID_CONSTANT_OP, Op,
    234                 Op->Asl.ParseOpName);
    235         }
    236 
    237         return (AE_TYPE);
    238     }
    239 
    240     /* Debug output */
    241 
    242     DbgPrint (ASL_PARSE_OUTPUT, "TYPE_345");
    243 
    244     if (Op->Asl.CompileFlags & NODE_IS_TARGET)
    245     {
    246         DbgPrint (ASL_PARSE_OUTPUT, " TARGET");
    247     }
    248     if (Op->Asl.CompileFlags & NODE_IS_TERM_ARG)
    249     {
    250         DbgPrint (ASL_PARSE_OUTPUT, " TERMARG");
    251     }
    252     DbgPrint (ASL_PARSE_OUTPUT, "\n");
    253 
    254     return (AE_OK);
    255 }
    256 
    257 
    258 /*******************************************************************************
    259  *
    260  * FUNCTION:    OpcAmlConstantWalk
    261  *
    262  * PARAMETERS:  ASL_WALK_CALLBACK
    263  *
    264  * RETURN:      Status
    265  *
    266  * DESCRIPTION: Reduce an Op and its subtree to a constant if possible
    267  *
    268  ******************************************************************************/
    269 
    270 ACPI_STATUS
    271 OpcAmlConstantWalk (
    272     ACPI_PARSE_OBJECT       *Op,
    273     UINT32                  Level,
    274     void                    *Context)
    275 {
    276     ACPI_WALK_STATE         *WalkState;
    277     ACPI_STATUS             Status = AE_OK;
    278     ACPI_OPERAND_OBJECT     *ObjDesc;
    279     ACPI_PARSE_OBJECT       *RootOp;
    280     ACPI_PARSE_OBJECT       *OriginalParentOp;
    281     UINT8                   WalkType;
    282 
    283 
    284     /*
    285      * Only interested in subtrees that could possibly contain
    286      * expressions that can be evaluated at this time
    287      */
    288     if ((!(Op->Asl.CompileFlags & NODE_COMPILE_TIME_CONST)) ||
    289           (Op->Asl.CompileFlags & NODE_IS_TARGET))
    290     {
    291         return (AE_OK);
    292     }
    293 
    294     /* Set the walk type based on the reduction used for this op */
    295 
    296     if (Op->Asl.CompileFlags & NODE_IS_TERM_ARG)
    297     {
    298         /* Op is a TermArg, constant folding is merely optional */
    299 
    300         if (!Gbl_FoldConstants)
    301         {
    302             return (AE_CTRL_DEPTH);
    303         }
    304 
    305         WalkType = ACPI_WALK_CONST_OPTIONAL;
    306     }
    307     else
    308     {
    309         /* Op is a DataObject, the expression MUST reduced to a constant */
    310 
    311         WalkType = ACPI_WALK_CONST_REQUIRED;
    312     }
    313 
    314     /* Create a new walk state */
    315 
    316     WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);
    317     if (!WalkState)
    318     {
    319         return AE_NO_MEMORY;
    320     }
    321 
    322     WalkState->NextOp               = NULL;
    323     WalkState->Params               = NULL;
    324     WalkState->CallerReturnDesc     = &ObjDesc;
    325     WalkState->WalkType             = WalkType;
    326 
    327     /*
    328      * Examine the entire subtree -- all nodes must be constants
    329      * or type 3/4/5 opcodes
    330      */
    331     Status = TrWalkParseTree (Op, ASL_WALK_VISIT_DOWNWARD,
    332                 OpcAmlCheckForConstant, NULL, WalkState);
    333 
    334     /*
    335      * Did we find an entire subtree that contains all constants and type 3/4/5
    336      * opcodes?  (Only AE_OK or AE_TYPE returned from above)
    337      */
    338     if (Status == AE_TYPE)
    339     {
    340         /* Subtree cannot be reduced to a constant */
    341 
    342         if (WalkState->WalkType == ACPI_WALK_CONST_OPTIONAL)
    343         {
    344             AcpiDsDeleteWalkState (WalkState);
    345             return (AE_OK);
    346         }
    347 
    348         /* Don't descend any further, and use a default "constant" value */
    349 
    350         Status = AE_CTRL_DEPTH;
    351     }
    352     else
    353     {
    354         /* Subtree can be reduced */
    355 
    356         /* Allocate a new temporary root for this subtree */
    357 
    358         RootOp = TrAllocateNode (PARSEOP_INTEGER);
    359         if (!RootOp)
    360         {
    361             return (AE_NO_MEMORY);
    362         }
    363 
    364         RootOp->Common.AmlOpcode = AML_INT_EVAL_SUBTREE_OP;
    365 
    366         OriginalParentOp = Op->Common.Parent;
    367         Op->Common.Parent = RootOp;
    368 
    369         /* Hand off the subtree to the AML interpreter */
    370 
    371         Status = TrWalkParseTree (Op, ASL_WALK_VISIT_TWICE,
    372                     OpcAmlEvaluationWalk1, OpcAmlEvaluationWalk2, WalkState);
    373         Op->Common.Parent = OriginalParentOp;
    374 
    375         /* TBD: we really *should* release the RootOp node */
    376 
    377         if (ACPI_SUCCESS (Status))
    378         {
    379             TotalFolds++;
    380 
    381             /* Get the final result */
    382 
    383             Status = AcpiDsResultPop (&ObjDesc, WalkState);
    384         }
    385     }
    386 
    387     if (ACPI_FAILURE (Status))
    388     {
    389         /* We could not resolve the subtree for some reason */
    390 
    391         AslCoreSubsystemError (Op, Status,
    392             "Failure during constant evaluation", FALSE);
    393         AslError (ASL_ERROR, ASL_MSG_CONSTANT_EVALUATION, Op,
    394             Op->Asl.ParseOpName);
    395 
    396         /* Set the subtree value to ZERO anyway.  Eliminates further errors */
    397 
    398         Op->Asl.ParseOpcode      = PARSEOP_INTEGER;
    399         Op->Common.Value.Integer = 0;
    400         OpcSetOptimalIntegerSize (Op);
    401     }
    402     else
    403     {
    404         AslError (ASL_OPTIMIZATION, ASL_MSG_CONSTANT_FOLDED, Op,
    405             Op->Asl.ParseOpName);
    406 
    407         /*
    408          * Because we know we executed type 3/4/5 opcodes above, we know that
    409          * the result must be either an Integer, String, or Buffer.
    410          */
    411         switch (ObjDesc->Common.Type)
    412         {
    413         case ACPI_TYPE_INTEGER:
    414 
    415             Op->Asl.ParseOpcode      = PARSEOP_INTEGER;
    416             Op->Common.Value.Integer = ObjDesc->Integer.Value;
    417             OpcSetOptimalIntegerSize (Op);
    418 
    419             DbgPrint (ASL_PARSE_OUTPUT,
    420                 "Constant expression reduced to (INTEGER) %8.8X%8.8X\n",
    421                 ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value));
    422             break;
    423 
    424 
    425         case ACPI_TYPE_STRING:
    426 
    427             Op->Asl.ParseOpcode     = PARSEOP_STRING_LITERAL;
    428             Op->Common.AmlOpcode    = AML_STRING_OP;
    429             Op->Asl.AmlLength       = ACPI_STRLEN (ObjDesc->String.Pointer) + 1;
    430             Op->Common.Value.String = ObjDesc->String.Pointer;
    431 
    432             DbgPrint (ASL_PARSE_OUTPUT,
    433                 "Constant expression reduced to (STRING) %s\n",
    434                 Op->Common.Value.String);
    435 
    436             break;
    437 
    438 
    439         case ACPI_TYPE_BUFFER:
    440 
    441             Op->Asl.ParseOpcode     = PARSEOP_BUFFER;
    442             Op->Common.AmlOpcode    = AML_BUFFER_OP;
    443             Op->Asl.CompileFlags    = NODE_AML_PACKAGE;
    444             UtSetParseOpName (Op);
    445 
    446             /* Child node is the buffer length */
    447 
    448             RootOp = TrAllocateNode (PARSEOP_INTEGER);
    449 
    450             RootOp->Asl.AmlOpcode     = AML_DWORD_OP;
    451             RootOp->Asl.Value.Integer = ObjDesc->Buffer.Length;
    452             RootOp->Asl.Parent        = Op;
    453 
    454             (void) OpcSetOptimalIntegerSize (RootOp);
    455 
    456             Op->Asl.Child = RootOp;
    457             Op = RootOp;
    458             UtSetParseOpName (Op);
    459 
    460             /* Peer to the child is the raw buffer data */
    461 
    462             RootOp = TrAllocateNode (PARSEOP_RAW_DATA);
    463             RootOp->Asl.AmlOpcode     = AML_RAW_DATA_BUFFER;
    464             RootOp->Asl.AmlLength     = ObjDesc->Buffer.Length;
    465             RootOp->Asl.Value.String  = (char *) ObjDesc->Buffer.Pointer;
    466             RootOp->Asl.Parent        = Op->Asl.Parent;
    467 
    468             Op->Asl.Next = RootOp;
    469             Op = RootOp;
    470 
    471             DbgPrint (ASL_PARSE_OUTPUT,
    472                 "Constant expression reduced to (BUFFER) length %X\n",
    473                 ObjDesc->Buffer.Length);
    474             break;
    475 
    476 
    477         default:
    478             printf ("Unsupported return type: %s\n",
    479                         AcpiUtGetObjectTypeName (ObjDesc));
    480             break;
    481         }
    482     }
    483 
    484     UtSetParseOpName (Op);
    485     Op->Asl.Child = NULL;
    486 
    487     AcpiDsDeleteWalkState (WalkState);
    488 
    489     return (AE_CTRL_DEPTH);
    490 }
    491 
    492