Path: blob/main/sys/contrib/dev/acpica/compiler/aslfold.c
48373 views
/******************************************************************************1*2* Module Name: aslfold - Constant folding3*4*****************************************************************************/56/******************************************************************************7*8* 1. Copyright Notice9*10* Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.11* All rights reserved.12*13* 2. License14*15* 2.1. This is your license from Intel Corp. under its intellectual property16* rights. You may have additional license terms from the party that provided17* you this software, covering your right to use that party's intellectual18* property rights.19*20* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a21* copy of the source code appearing in this file ("Covered Code") an22* irrevocable, perpetual, worldwide license under Intel's copyrights in the23* base code distributed originally by Intel ("Original Intel Code") to copy,24* make derivatives, distribute, use and display any portion of the Covered25* Code in any form, with the right to sublicense such rights; and26*27* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent28* license (with the right to sublicense), under only those claims of Intel29* patents that are infringed by the Original Intel Code, to make, use, sell,30* offer to sell, and import the Covered Code and derivative works thereof31* solely to the minimum extent necessary to exercise the above copyright32* license, and in no event shall the patent license extend to any additions33* to or modifications of the Original Intel Code. No other license or right34* is granted directly or by implication, estoppel or otherwise;35*36* The above copyright and patent license is granted only if the following37* conditions are met:38*39* 3. Conditions40*41* 3.1. Redistribution of Source with Rights to Further Distribute Source.42* Redistribution of source code of any substantial portion of the Covered43* Code or modification with rights to further distribute source must include44* the above Copyright Notice, the above License, this list of Conditions,45* and the following Disclaimer and Export Compliance provision. In addition,46* Licensee must cause all Covered Code to which Licensee contributes to47* contain a file documenting the changes Licensee made to create that Covered48* Code and the date of any change. Licensee must include in that file the49* documentation of any changes made by any predecessor Licensee. Licensee50* must include a prominent statement that the modification is derived,51* directly or indirectly, from Original Intel Code.52*53* 3.2. Redistribution of Source with no Rights to Further Distribute Source.54* Redistribution of source code of any substantial portion of the Covered55* Code or modification without rights to further distribute source must56* include the following Disclaimer and Export Compliance provision in the57* documentation and/or other materials provided with distribution. In58* addition, Licensee may not authorize further sublicense of source of any59* portion of the Covered Code, and must include terms to the effect that the60* license from Licensee to its licensee is limited to the intellectual61* property embodied in the software Licensee provides to its licensee, and62* not to intellectual property embodied in modifications its licensee may63* make.64*65* 3.3. Redistribution of Executable. Redistribution in executable form of any66* substantial portion of the Covered Code or modification must reproduce the67* above Copyright Notice, and the following Disclaimer and Export Compliance68* provision in the documentation and/or other materials provided with the69* distribution.70*71* 3.4. Intel retains all right, title, and interest in and to the Original72* Intel Code.73*74* 3.5. Neither the name Intel nor any other trademark owned or controlled by75* Intel shall be used in advertising or otherwise to promote the sale, use or76* other dealings in products derived from or relating to the Covered Code77* without prior written authorization from Intel.78*79* 4. Disclaimer and Export Compliance80*81* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED82* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE83* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,84* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY85* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY86* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A87* PARTICULAR PURPOSE.88*89* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES90* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR91* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,92* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY93* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL94* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS95* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY96* LIMITED REMEDY.97*98* 4.3. Licensee shall not export, either directly or indirectly, any of this99* software or system incorporating such software without first obtaining any100* required license or other approval from the U. S. Department of Commerce or101* any other agency or department of the United States Government. In the102* event Licensee exports any such software from the United States or103* re-exports any such software from a foreign destination, Licensee shall104* ensure that the distribution and export/re-export of the software is in105* compliance with all laws, regulations, orders, or other restrictions of the106* U.S. Export Administration Regulations. Licensee agrees that neither it nor107* any of its subsidiaries will export/re-export any technical data, process,108* software, or service, directly or indirectly, to any country for which the109* United States government or any agency thereof requires an export license,110* other governmental approval, or letter of assurance, without first obtaining111* such license, approval or letter.112*113*****************************************************************************114*115* Alternatively, you may choose to be licensed under the terms of the116* following license:117*118* Redistribution and use in source and binary forms, with or without119* modification, are permitted provided that the following conditions120* are met:121* 1. Redistributions of source code must retain the above copyright122* notice, this list of conditions, and the following disclaimer,123* without modification.124* 2. Redistributions in binary form must reproduce at minimum a disclaimer125* substantially similar to the "NO WARRANTY" disclaimer below126* ("Disclaimer") and any redistribution must be conditioned upon127* including a substantially similar Disclaimer requirement for further128* binary redistribution.129* 3. Neither the names of the above-listed copyright holders nor the names130* of any contributors may be used to endorse or promote products derived131* from this software without specific prior written permission.132*133* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS134* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT135* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR136* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT137* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,138* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT139* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,140* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY141* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT142* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE143* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.144*145* Alternatively, you may choose to be licensed under the terms of the146* GNU General Public License ("GPL") version 2 as published by the Free147* Software Foundation.148*149*****************************************************************************/150151#include <contrib/dev/acpica/compiler/aslcompiler.h>152#include "aslcompiler.y.h"153#include <contrib/dev/acpica/include/amlcode.h>154155#include <contrib/dev/acpica/include/acdispat.h>156#include <contrib/dev/acpica/include/acparser.h>157158#define _COMPONENT ACPI_COMPILER159ACPI_MODULE_NAME ("aslfold")160161/* Local prototypes */162163static ACPI_STATUS164OpcAmlEvaluationWalk1 (165ACPI_PARSE_OBJECT *Op,166UINT32 Level,167void *Context);168169static ACPI_STATUS170OpcAmlEvaluationWalk2 (171ACPI_PARSE_OBJECT *Op,172UINT32 Level,173void *Context);174175static ACPI_STATUS176OpcAmlCheckForConstant (177ACPI_PARSE_OBJECT *Op,178UINT32 Level,179void *Context);180181static void182OpcUpdateIntegerNode (183ACPI_PARSE_OBJECT *Op,184UINT64 Value);185186static ACPI_STATUS187TrTransformToStoreOp (188ACPI_PARSE_OBJECT *Op,189ACPI_WALK_STATE *WalkState);190191static ACPI_STATUS192TrSimpleConstantReduction (193ACPI_PARSE_OBJECT *Op,194ACPI_WALK_STATE *WalkState);195196static void197TrInstallReducedConstant (198ACPI_PARSE_OBJECT *Op,199ACPI_OPERAND_OBJECT *ObjDesc);200201202/*******************************************************************************203*204* FUNCTION: OpcAmlConstantWalk205*206* PARAMETERS: ASL_WALK_CALLBACK207*208* RETURN: Status209*210* DESCRIPTION: Reduce an Op and its subtree to a constant if possible.211* Called during ascent of the parse tree.212*213******************************************************************************/214215ACPI_STATUS216OpcAmlConstantWalk (217ACPI_PARSE_OBJECT *Op,218UINT32 Level,219void *Context)220{221ACPI_WALK_STATE *WalkState;222ACPI_STATUS Status = AE_OK;223224225if (Op->Asl.CompileFlags == 0)226{227return (AE_OK);228}229230/*231* Only interested in subtrees that could possibly contain232* expressions that can be evaluated at this time233*/234if ((!(Op->Asl.CompileFlags & OP_COMPILE_TIME_CONST)) ||235(Op->Asl.CompileFlags & OP_IS_TARGET))236{237return (AE_OK);238}239240/* Create a new walk state */241242WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL);243if (!WalkState)244{245return (AE_NO_MEMORY);246}247248WalkState->NextOp = NULL;249WalkState->Params = NULL;250251/*252* Examine the entire subtree -- all nodes must be constants253* or type 3/4/5 opcodes254*/255Status = TrWalkParseTree (Op, ASL_WALK_VISIT_DOWNWARD,256OpcAmlCheckForConstant, NULL, WalkState);257258/*259* Did we find an entire subtree that contains all constants260* and type 3/4/5 opcodes?261*/262switch (Status)263{264case AE_OK:265266/* Simple case, like Add(3,4) -> 7 */267268Status = TrSimpleConstantReduction (Op, WalkState);269break;270271case AE_CTRL_RETURN_VALUE:272273/* More complex case, like Add(3,4,Local0) -> Store(7,Local0) */274275Status = TrTransformToStoreOp (Op, WalkState);276break;277278case AE_TYPE:279280AcpiDsDeleteWalkState (WalkState);281return (AE_OK);282283default:284AcpiDsDeleteWalkState (WalkState);285break;286}287288if (ACPI_FAILURE (Status))289{290DbgPrint (ASL_PARSE_OUTPUT, "Cannot resolve, %s\n",291AcpiFormatException (Status));292293/* We could not resolve the subtree for some reason */294295AslError (ASL_ERROR, ASL_MSG_CONSTANT_EVALUATION, Op,296(char *) AcpiFormatException (Status));297298/* Set the subtree value to ZERO anyway. Eliminates further errors */299300OpcUpdateIntegerNode (Op, 0);301}302303return (AE_OK);304}305306307/*******************************************************************************308*309* FUNCTION: OpcAmlCheckForConstant310*311* PARAMETERS: ASL_WALK_CALLBACK312*313* RETURN: Status314*315* DESCRIPTION: Check one Op for a reducible type 3/4/5 AML opcode.316* This is performed via an upward walk of the parse subtree.317*318******************************************************************************/319320static ACPI_STATUS321OpcAmlCheckForConstant (322ACPI_PARSE_OBJECT *Op,323UINT32 Level,324void *Context)325{326ACPI_WALK_STATE *WalkState = Context;327ACPI_STATUS Status = AE_OK;328ACPI_PARSE_OBJECT *NextOp;329const ACPI_OPCODE_INFO *OpInfo;330331332WalkState->Op = Op;333WalkState->Opcode = Op->Common.AmlOpcode;334WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);335336DbgPrint (ASL_PARSE_OUTPUT, "[%.4d] Opcode: %12.12s ",337Op->Asl.LogicalLineNumber, Op->Asl.ParseOpName);338339/*340* These opcodes do not appear in the OpcodeInfo table, but341* they represent constants, so abort the constant walk now.342*/343if ((WalkState->Opcode == AML_RAW_DATA_BYTE) ||344(WalkState->Opcode == AML_RAW_DATA_WORD) ||345(WalkState->Opcode == AML_RAW_DATA_DWORD) ||346(WalkState->Opcode == AML_RAW_DATA_QWORD))347{348DbgPrint (ASL_PARSE_OUTPUT, "RAW DATA");349Status = AE_TYPE;350goto CleanupAndExit;351}352353/*354* Search upwards for a possible Name() operator. This is done355* because a type 3/4/5 opcode within a Name() expression356* MUST be reduced to a simple constant.357*/358NextOp = Op->Asl.Parent;359while (NextOp)360{361/* Finished if we find a Name() opcode */362363if (NextOp->Asl.AmlOpcode == AML_NAME_OP)364{365break;366}367368/*369* Any "deferred" opcodes contain one or more TermArg parameters,370* and thus are not required to be folded to constants at compile371* time. This affects things like Buffer() and Package() objects.372* We just ignore them here. However, any sub-expressions can and373* will still be typechecked. Note: These are called the374* "deferred" opcodes in the AML interpreter.375*/376OpInfo = AcpiPsGetOpcodeInfo (NextOp->Common.AmlOpcode);377if (OpInfo->Flags & AML_DEFER)378{379NextOp = NULL;380break;381}382383NextOp = NextOp->Asl.Parent;384}385386/* Type 3/4/5 opcodes have the AML_CONSTANT flag set */387388if (!(WalkState->OpInfo->Flags & AML_CONSTANT))389{390/*391* From the ACPI specification:392*393* "The Type 3/4/5 opcodes return a value and can be used in an394* expression that evaluates to a constant. These opcodes may be395* evaluated at ASL compile-time. To ensure that these opcodes396* will evaluate to a constant, the following rules apply: The397* term cannot have a destination (target) operand, and must have398* either a Type3Opcode, Type4Opcode, Type5Opcode, ConstExprTerm,399* Integer, BufferTerm, Package, or String for all arguments."400*/401402/*403* The value (second) operand for the Name() operator MUST404* reduce to a single constant, as per the ACPI specification405* (the operand is a DataObject). This also implies that there406* can be no target operand. Name() is the only ASL operator407* with a "DataObject" as an operand and is thus special-408* cased here.409*/410if (NextOp) /* Inspect a Name() operator */411{412/* Error if there is a target operand */413414if (Op->Asl.CompileFlags & OP_IS_TARGET)415{416AslError (ASL_ERROR, ASL_MSG_INVALID_TARGET, Op, NULL);417Status = AE_TYPE;418}419420/* Error if expression cannot be reduced (folded) */421422if (!(NextOp->Asl.CompileFlags & OP_COULD_NOT_REDUCE))423{424/* Ensure only one error message per statement */425426NextOp->Asl.CompileFlags |= OP_COULD_NOT_REDUCE;427DbgPrint (ASL_PARSE_OUTPUT,428"**** Could not reduce operands for NAME opcode ****\n");429430AslError (ASL_ERROR, ASL_MSG_CONSTANT_REQUIRED, Op,431"Constant is required for Name operator");432Status = AE_TYPE;433}434}435436if (ACPI_FAILURE (Status))437{438goto CleanupAndExit;439}440441/* This is not a 3/4/5 opcode, but maybe can convert to STORE */442443if (Op->Asl.CompileFlags & OP_IS_TARGET)444{445DbgPrint (ASL_PARSE_OUTPUT,446"**** Valid Target, transform to Store or CopyObject ****\n");447return (AE_CTRL_RETURN_VALUE);448}449450/* Expression cannot be reduced */451452DbgPrint (ASL_PARSE_OUTPUT,453"**** Not a Type 3/4/5 opcode or cannot reduce/fold (%s) ****\n",454Op->Asl.ParseOpName);455456Status = AE_TYPE;457goto CleanupAndExit;458}459460/*461* TBD: Ignore buffer constants for now. The problem is that these462* constants have been transformed into RAW_DATA at this point, from463* the parse tree transform process which currently happens before464* the constant folding process. We may need to defer this transform465* for buffer until after the constant folding.466*/467if (WalkState->Opcode == AML_BUFFER_OP)468{469DbgPrint (ASL_PARSE_OUTPUT,470"\nBuffer constant reduction is currently not supported\n");471472if (NextOp) /* Found a Name() operator, error */473{474AslError (ASL_ERROR, ASL_MSG_UNSUPPORTED, Op,475"Buffer expression cannot be reduced");476}477478Status = AE_TYPE;479goto CleanupAndExit;480}481482/* Debug output */483484DbgPrint (ASL_PARSE_OUTPUT, "TYPE_345");485486if (Op->Asl.CompileFlags & OP_IS_TARGET)487{488if (Op->Asl.ParseOpcode == PARSEOP_ZERO)489{490DbgPrint (ASL_PARSE_OUTPUT, "%-16s", " NULL TARGET");491}492else493{494DbgPrint (ASL_PARSE_OUTPUT, "%-16s", " VALID TARGET");495}496}497498if (Op->Asl.CompileFlags & OP_IS_TERM_ARG)499{500DbgPrint (ASL_PARSE_OUTPUT, "%-16s", " TERMARG");501}502503CleanupAndExit:504505/* Dump the node compile flags also */506507TrPrintOpFlags (Op->Asl.CompileFlags, ASL_PARSE_OUTPUT);508DbgPrint (ASL_PARSE_OUTPUT, "\n");509return (Status);510}511512513/*******************************************************************************514*515* FUNCTION: TrSimpleConstantReduction516*517* PARAMETERS: Op - Parent operator to be transformed518* WalkState - Current walk state519*520* RETURN: Status521*522* DESCRIPTION: Reduce an entire AML operation to a single constant. The523* operation must not have a target operand.524*525* Add (32,64) --> 96526*527******************************************************************************/528529static ACPI_STATUS530TrSimpleConstantReduction (531ACPI_PARSE_OBJECT *Op,532ACPI_WALK_STATE *WalkState)533{534ACPI_PARSE_OBJECT *RootOp;535ACPI_PARSE_OBJECT *OriginalParentOp;536ACPI_OPERAND_OBJECT *ObjDesc;537ACPI_STATUS Status;538539540DbgPrint (ASL_PARSE_OUTPUT,541"Simple subtree constant reduction, operator to constant\n");542543/* Allocate a new temporary root for this subtree */544545RootOp = TrAllocateOp (PARSEOP_INTEGER);546if (!RootOp)547{548return (AE_NO_MEMORY);549}550551RootOp->Common.AmlOpcode = AML_INT_EVAL_SUBTREE_OP;552553OriginalParentOp = Op->Common.Parent;554Op->Common.Parent = RootOp;555556/* Hand off the subtree to the AML interpreter */557558WalkState->CallerReturnDesc = &ObjDesc;559560Status = TrWalkParseTree (Op, ASL_WALK_VISIT_TWICE,561OpcAmlEvaluationWalk1, OpcAmlEvaluationWalk2, WalkState);562563/* Restore original parse tree */564565Op->Common.Parent = OriginalParentOp;566567if (ACPI_FAILURE (Status))568{569DbgPrint (ASL_PARSE_OUTPUT,570"Constant Subtree evaluation(1), %s\n",571AcpiFormatException (Status));572return (Status);573}574575/* Get the final result */576577Status = AcpiDsResultPop (&ObjDesc, WalkState);578if (ACPI_FAILURE (Status))579{580DbgPrint (ASL_PARSE_OUTPUT,581"Constant Subtree evaluation(2), %s\n",582AcpiFormatException (Status));583return (Status);584}585586/* Disconnect any existing children, install new constant */587588Op->Asl.Child = NULL;589TrInstallReducedConstant (Op, ObjDesc);590591UtSetParseOpName (Op);592return (AE_OK);593}594595596/*******************************************************************************597*598* FUNCTION: TrTransformToStoreOp599*600* PARAMETERS: Op - Parent operator to be transformed601* WalkState - Current walk state602*603* RETURN: Status604*605* DESCRIPTION: Transforms a single AML operation with a constant and target606* to a simple store operation:607*608* Add (32,64,DATA) --> Store (96,DATA)609*610******************************************************************************/611612static ACPI_STATUS613TrTransformToStoreOp (614ACPI_PARSE_OBJECT *Op,615ACPI_WALK_STATE *WalkState)616{617ACPI_PARSE_OBJECT *OriginalTarget;618ACPI_PARSE_OBJECT *NewTarget;619ACPI_PARSE_OBJECT *Child1;620ACPI_PARSE_OBJECT *Child2;621ACPI_OPERAND_OBJECT *ObjDesc;622ACPI_PARSE_OBJECT *NewParent;623ACPI_PARSE_OBJECT *OriginalParent;624ACPI_STATUS Status;625UINT16 NewParseOpcode;626UINT16 NewAmlOpcode;627628629/* Extract the operands */630631Child1 = Op->Asl.Child;632Child2 = Child1->Asl.Next;633634/*635* Special case for DIVIDE -- it has two targets. The first636* is for the remainder and if present, we will not attempt637* to reduce the expression.638*/639if (Op->Asl.ParseOpcode == PARSEOP_DIVIDE)640{641Child2 = Child2->Asl.Next;642if (Child2->Asl.ParseOpcode != PARSEOP_ZERO)643{644DbgPrint (ASL_PARSE_OUTPUT,645"Cannot reduce DIVIDE - has two targets\n\n");646return (AE_OK);647}648}649650switch (Op->Asl.ParseOpcode)651{652/*653* Folding of the explicit conversion opcodes must use CopyObject654* instead of Store. This can change the object type of the target655* operand, as per the ACPI specification:656*657* "If the ASL operator is one of the explicit conversion operators658* (ToString, ToInteger, etc., and the CopyObject operator), no659* [implicit] conversion is performed. (In other words, the result660* object is stored directly to the target and completely overwrites661* any existing object already stored at the target)"662*/663case PARSEOP_TOINTEGER:664case PARSEOP_TOSTRING:665case PARSEOP_TOBUFFER:666case PARSEOP_TODECIMALSTRING:667case PARSEOP_TOHEXSTRING:668case PARSEOP_TOBCD:669case PARSEOP_FROMBCD:670671NewParseOpcode = PARSEOP_COPYOBJECT;672NewAmlOpcode = AML_COPY_OBJECT_OP;673674DbgPrint (ASL_PARSE_OUTPUT,675"Reduction/Transform to CopyObjectOp: CopyObject(%s, %s)\n",676Child1->Asl.ParseOpName, Child2->Asl.ParseOpName);677break;678679default:680681NewParseOpcode = PARSEOP_STORE;682NewAmlOpcode = AML_STORE_OP;683684DbgPrint (ASL_PARSE_OUTPUT,685"Reduction/Transform to StoreOp: Store(%s, %s)\n",686Child1->Asl.ParseOpName, Child2->Asl.ParseOpName);687break;688}689690/*691* Create a NULL (zero) target so that we can use the692* interpreter to evaluate the expression.693*/694NewTarget = TrCreateNullTargetOp ();695NewTarget->Common.AmlOpcode = AML_INT_NAMEPATH_OP;696697/* Handle one-operand cases (NOT, TOBCD, etc.) */698699if (!Child2->Asl.Next)700{701Child2 = Child1;702}703704/* Link in new NULL target as the last operand */705706OriginalTarget = Child2->Asl.Next;707Child2->Asl.Next = NewTarget;708NewTarget->Asl.Parent = OriginalTarget->Asl.Parent;709710NewParent = TrAllocateOp (PARSEOP_INTEGER);711NewParent->Common.AmlOpcode = AML_INT_EVAL_SUBTREE_OP;712713OriginalParent = Op->Common.Parent;714Op->Common.Parent = NewParent;715716/* Hand off the subtree to the AML interpreter */717718WalkState->CallerReturnDesc = &ObjDesc;719720Status = TrWalkParseTree (Op, ASL_WALK_VISIT_TWICE,721OpcAmlEvaluationWalk1, OpcAmlEvaluationWalk2, WalkState);722if (ACPI_FAILURE (Status))723{724DbgPrint (ASL_PARSE_OUTPUT,725"Constant Subtree evaluation(3), %s\n",726AcpiFormatException (Status));727goto EvalError;728}729730/* Get the final result */731732Status = AcpiDsResultPop (&ObjDesc, WalkState);733if (ACPI_FAILURE (Status))734{735DbgPrint (ASL_PARSE_OUTPUT,736"Constant Subtree evaluation(4), %s\n",737AcpiFormatException (Status));738goto EvalError;739}740741/* Truncate any subtree expressions, they have been evaluated */742743Child1->Asl.Child = NULL;744745/* Folded constant is in ObjDesc, store into Child1 */746747TrInstallReducedConstant (Child1, ObjDesc);748749/* Convert operator to STORE or COPYOBJECT */750751Op->Asl.ParseOpcode = NewParseOpcode;752Op->Asl.AmlOpcode = NewAmlOpcode;753UtSetParseOpName (Op);754Op->Common.Parent = OriginalParent;755756/* First child is the folded constant */757758/* Second child will be the target */759760Child1->Asl.Next = OriginalTarget;761return (AE_OK);762763764EvalError:765766/* Restore original links */767768Op->Common.Parent = OriginalParent;769Child2->Asl.Next = OriginalTarget;770return (Status);771}772773774/*******************************************************************************775*776* FUNCTION: TrInstallReducedConstant777*778* PARAMETERS: Op - Parent operator to be transformed779* ObjDesc - Reduced constant to be installed780*781* RETURN: None782*783* DESCRIPTION: Transform the original operator to a simple constant.784* Handles Integers, Strings, and Buffers.785*786******************************************************************************/787788static void789TrInstallReducedConstant (790ACPI_PARSE_OBJECT *Op,791ACPI_OPERAND_OBJECT *ObjDesc)792{793ACPI_PARSE_OBJECT *LengthOp;794ACPI_PARSE_OBJECT *DataOp;795796797AslGbl_TotalFolds++;798AslError (ASL_OPTIMIZATION, ASL_MSG_CONSTANT_FOLDED, Op,799Op->Asl.ParseOpName);800801/*802* Because we know we executed type 3/4/5 opcodes above, we know that803* the result must be either an Integer, String, or Buffer.804*/805switch (ObjDesc->Common.Type)806{807case ACPI_TYPE_INTEGER:808809OpcUpdateIntegerNode (Op, ObjDesc->Integer.Value);810811DbgPrint (ASL_PARSE_OUTPUT,812"Constant expression reduced to (%s) %8.8X%8.8X\n\n",813Op->Asl.ParseOpName,814ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));815break;816817case ACPI_TYPE_STRING:818819Op->Asl.ParseOpcode = PARSEOP_STRING_LITERAL;820Op->Common.AmlOpcode = AML_STRING_OP;821Op->Asl.AmlLength = strlen (ObjDesc->String.Pointer) + 1;822Op->Common.Value.String = ObjDesc->String.Pointer;823824DbgPrint (ASL_PARSE_OUTPUT,825"Constant expression reduced to (STRING) %s\n\n",826Op->Common.Value.String);827break;828829case ACPI_TYPE_BUFFER:830/*831* Create a new parse subtree of the form:832*833* BUFFER (Buffer AML opcode)834* INTEGER (Buffer length in bytes)835* RAW_DATA (Buffer byte data)836*/837Op->Asl.ParseOpcode = PARSEOP_BUFFER;838Op->Common.AmlOpcode = AML_BUFFER_OP;839Op->Asl.CompileFlags = OP_AML_PACKAGE;840UtSetParseOpName (Op);841842/* Child node is the buffer length */843844LengthOp = TrAllocateOp (PARSEOP_INTEGER);845846LengthOp->Asl.AmlOpcode = AML_DWORD_OP;847LengthOp->Asl.Value.Integer = ObjDesc->Buffer.Length;848LengthOp->Asl.Parent = Op;849(void) OpcSetOptimalIntegerSize (LengthOp);850851Op->Asl.Child = LengthOp;852853/* Next child is the raw buffer data */854855DataOp = TrAllocateOp (PARSEOP_RAW_DATA);856DataOp->Asl.AmlOpcode = AML_RAW_DATA_BUFFER;857DataOp->Asl.AmlLength = ObjDesc->Buffer.Length;858DataOp->Asl.Value.String = (char *) ObjDesc->Buffer.Pointer;859DataOp->Asl.Parent = Op;860861LengthOp->Asl.Next = DataOp;862863DbgPrint (ASL_PARSE_OUTPUT,864"Constant expression reduced to (BUFFER) length %X\n\n",865ObjDesc->Buffer.Length);866break;867868default:869break;870}871}872873874/*******************************************************************************875*876* FUNCTION: OpcUpdateIntegerNode877*878* PARAMETERS: Op - Current parse object879* Value - Value for the integer op880*881* RETURN: None882*883* DESCRIPTION: Update node to the correct Integer type and value884*885******************************************************************************/886887static void888OpcUpdateIntegerNode (889ACPI_PARSE_OBJECT *Op,890UINT64 Value)891{892893Op->Common.Value.Integer = Value;894895/*896* The AmlLength is used by the parser to indicate a constant,897* (if non-zero). Length is either (1/2/4/8)898*/899switch (Op->Asl.AmlLength)900{901case 1:902903TrSetOpIntegerValue (PARSEOP_BYTECONST, Op);904Op->Asl.AmlOpcode = AML_RAW_DATA_BYTE;905break;906907case 2:908909TrSetOpIntegerValue (PARSEOP_WORDCONST, Op);910Op->Asl.AmlOpcode = AML_RAW_DATA_WORD;911break;912913case 4:914915TrSetOpIntegerValue (PARSEOP_DWORDCONST, Op);916Op->Asl.AmlOpcode = AML_RAW_DATA_DWORD;917break;918919case 8:920921TrSetOpIntegerValue (PARSEOP_QWORDCONST, Op);922Op->Asl.AmlOpcode = AML_RAW_DATA_QWORD;923break;924925case 0:926default:927928OpcSetOptimalIntegerSize (Op);929TrSetOpIntegerValue (PARSEOP_INTEGER, Op);930break;931}932933Op->Asl.AmlLength = 0;934}935936937/*******************************************************************************938*939* FUNCTION: OpcAmlEvaluationWalk1940*941* PARAMETERS: ASL_WALK_CALLBACK942*943* RETURN: Status944*945* DESCRIPTION: Descending callback for AML execution of constant subtrees946*947******************************************************************************/948949static ACPI_STATUS950OpcAmlEvaluationWalk1 (951ACPI_PARSE_OBJECT *Op,952UINT32 Level,953void *Context)954{955ACPI_WALK_STATE *WalkState = Context;956ACPI_STATUS Status;957ACPI_PARSE_OBJECT *OutOp;958959960WalkState->Op = Op;961WalkState->Opcode = Op->Common.AmlOpcode;962WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);963964/* Copy child pointer to Arg for compatibility with Interpreter */965966if (Op->Asl.Child)967{968Op->Common.Value.Arg = Op->Asl.Child;969}970971/* Call AML dispatcher */972973Status = AcpiDsExecBeginOp (WalkState, &OutOp);974if (ACPI_FAILURE (Status))975{976DbgPrint (ASL_PARSE_OUTPUT,977"%s Constant interpretation failed (1) - %s\n",978Op->Asl.ParseOpName, AcpiFormatException (Status));979}980981return (Status);982}983984985/*******************************************************************************986*987* FUNCTION: OpcAmlEvaluationWalk2988*989* PARAMETERS: ASL_WALK_CALLBACK990*991* RETURN: Status992*993* DESCRIPTION: Ascending callback for AML execution of constant subtrees994*995******************************************************************************/996997static ACPI_STATUS998OpcAmlEvaluationWalk2 (999ACPI_PARSE_OBJECT *Op,1000UINT32 Level,1001void *Context)1002{1003ACPI_WALK_STATE *WalkState = Context;1004ACPI_STATUS Status;100510061007WalkState->Op = Op;1008WalkState->Opcode = Op->Common.AmlOpcode;1009WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);10101011/* Copy child pointer to Arg for compatibility with Interpreter */10121013if (Op->Asl.Child)1014{1015Op->Common.Value.Arg = Op->Asl.Child;1016}10171018/* Call AML dispatcher */10191020Status = AcpiDsExecEndOp (WalkState);1021if (ACPI_FAILURE (Status))1022{1023DbgPrint (ASL_PARSE_OUTPUT,1024"%s: Constant interpretation failed (2) - %s\n",1025Op->Asl.ParseOpName, AcpiFormatException (Status));1026}10271028return (Status);1029}103010311032