aslfold.c revision 199767f8919635c4928607450d9e0abb932109ce
/******************************************************************************
*
* Module Name: aslfold - Constant folding
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2015, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include "aslcompiler.y.h"
#define _COMPONENT ACPI_COMPILER
ACPI_MODULE_NAME ("aslfold")
/* Local prototypes */
static ACPI_STATUS
void *Context);
static ACPI_STATUS
void *Context);
static ACPI_STATUS
void *Context);
static void
static ACPI_STATUS
static ACPI_STATUS
static void
/*******************************************************************************
*
* FUNCTION: OpcAmlConstantWalk
*
* PARAMETERS: ASL_WALK_CALLBACK
*
* RETURN: Status
*
* DESCRIPTION: Reduce an Op and its subtree to a constant if possible
*
******************************************************************************/
void *Context)
{
{
return (AE_OK);
}
/*
* Only interested in subtrees that could possibly contain
* expressions that can be evaluated at this time
*/
{
return (AE_OK);
}
/* Create a new walk state */
if (!WalkState)
{
return (AE_NO_MEMORY);
}
/*
* Examine the entire subtree -- all nodes must be constants
* or type 3/4/5 opcodes
*/
/*
* Did we find an entire subtree that contains all constants
* and type 3/4/5 opcodes?
*/
switch (Status)
{
case AE_OK:
/* Simple case, like Add(3,4) -> 7 */
break;
case AE_CTRL_RETURN_VALUE:
/* More complex case, like Add(3,4,Local0) -> Store(7,Local0) */
break;
case AE_TYPE:
return (AE_OK);
default:
break;
}
if (ACPI_FAILURE (Status))
{
/* We could not resolve the subtree for some reason */
(char *) AcpiFormatException (Status));
/* Set the subtree value to ZERO anyway. Eliminates further errors */
OpcUpdateIntegerNode (Op, 0);
}
/* Abort the walk of this subtree, we are done with it */
return (AE_CTRL_DEPTH);
}
/*******************************************************************************
*
* FUNCTION: OpcAmlCheckForConstant
*
* PARAMETERS: ASL_WALK_CALLBACK
*
* RETURN: Status
*
* DESCRIPTION: Check one Op for a type 3/4/5 AML opcode
*
******************************************************************************/
static ACPI_STATUS
void *Context)
{
/*
* TBD: Ignore buffer constants for now. The problem is that these
* constants have been transformed into RAW_DATA at this point, from
* the parse tree transform process which currently happens before
* the constant folding process. We may need to defer this transform
* for buffer until after the constant folding.
*/
{
"\nBuffer+Buffer->Buffer constant reduction is not supported yet");
goto CleanupAndExit;
}
/*
* These opcodes do not appear in the OpcodeInfo table, but
* they represent constants, so abort the constant walk now.
*/
{
goto CleanupAndExit;
}
/* Type 3/4/5 opcodes have the AML_CONSTANT flag set */
{
/* Not 3/4/5 opcode, but maybe can convert to STORE */
{
"**** Valid Target, transform to Store ****\n");
return (AE_CTRL_RETURN_VALUE);
}
/* Expression cannot be reduced */
"**** Not a Type 3/4/5 opcode (%s) ****",
goto CleanupAndExit;
}
/* Debug output */
{
{
}
else
{
}
}
{
}
/* Dump the node compile flags also */
return (Status);
}
/*******************************************************************************
*
* FUNCTION: TrSimpleConstantReduction
*
* PARAMETERS: Op - Parent operator to be transformed
* WalkState - Current walk state
*
* RETURN: Status
*
* DESCRIPTION: Reduce an entire AML operation to a single constant. The
* operation must not have a target operand.
*
* Add (32,64) --> 96
*
******************************************************************************/
static ACPI_STATUS
{
"Simple subtree constant reduction, operator to constant\n");
/* Allocate a new temporary root for this subtree */
if (!RootOp)
{
return (AE_NO_MEMORY);
}
/* Hand off the subtree to the AML interpreter */
/* Restore original parse tree */
if (ACPI_FAILURE (Status))
{
"Constant Subtree evaluation(1), %s\n",
return (Status);
}
/* Get the final result */
if (ACPI_FAILURE (Status))
{
"Constant Subtree evaluation(2), %s\n",
return (Status);
}
/* Disconnect any existing children, install new constant */
return (AE_OK);
}
/*******************************************************************************
*
* FUNCTION: TrTransformToStoreOp
*
* PARAMETERS: Op - Parent operator to be transformed
* WalkState - Current walk state
*
* RETURN: Status
*
* DESCRIPTION: Transforms a single AML operation with a constant and target
* to a simple store operation:
*
* Add (32,64,DATA) --> Store (96,DATA)
*
******************************************************************************/
static ACPI_STATUS
{
/* Extract the operands */
/*
* Special case for DIVIDE -- it has two targets. The first
* is for the remainder and if present, we will not attempt
* to reduce the expression.
*/
{
{
"Cannot reduce DIVIDE - has two targets\n\n");
return (AE_OK);
}
}
/*
* Create a NULL (zero) target so that we can use the
* interpreter to evaluate the expression.
*/
NewTarget = TrCreateNullTarget ();
/* Handle one-operand cases (NOT, TOBCD, etc.) */
{
}
/* Link in new NULL target as the last operand */
/* Hand off the subtree to the AML interpreter */
if (ACPI_FAILURE (Status))
{
"Constant Subtree evaluation(3), %s\n",
goto EvalError;
}
/* Get the final result */
if (ACPI_FAILURE (Status))
{
"Constant Subtree evaluation(4), %s\n",
goto EvalError;
}
/* Truncate any subtree expressions, they have been evaluated */
/* Folded constant is in ObjDesc, store into Child1 */
/* Convert operator to STORE */
/* First child is the folded constant */
/* Second child will be the target */
return (AE_OK);
/* Restore original links */
return (Status);
}
/*******************************************************************************
*
* FUNCTION: TrInstallReducedConstant
*
* PARAMETERS: Op - Parent operator to be transformed
* ObjDesc - Reduced constant to be installed
*
* RETURN: None
*
* DESCRIPTION: Transform the original operator to a simple constant.
* Handles Integers, Strings, and Buffers.
*
******************************************************************************/
static void
{
TotalFolds++;
/*
* Because we know we executed type 3/4/5 opcodes above, we know that
* the result must be either an Integer, String, or Buffer.
*/
{
case ACPI_TYPE_INTEGER:
"Constant expression reduced to (%s) %8.8X%8.8X\n\n",
break;
case ACPI_TYPE_STRING:
"Constant expression reduced to (STRING) %s\n\n",
break;
case ACPI_TYPE_BUFFER:
/*
* Create a new parse subtree of the form:
*
* BUFFER (Buffer AML opcode)
* INTEGER (Buffer length in bytes)
* RAW_DATA (Buffer byte data)
*/
/* Child node is the buffer length */
(void) OpcSetOptimalIntegerSize (LengthOp);
/* Next child is the raw buffer data */
"Constant expression reduced to (BUFFER) length %X\n\n",
break;
default:
break;
}
}
/*******************************************************************************
*
* FUNCTION: OpcUpdateIntegerNode
*
* PARAMETERS: Op - Current parse object
* Value - Value for the integer op
*
* RETURN: None
*
* DESCRIPTION: Update node to the correct Integer type and value
*
******************************************************************************/
static void
{
/*
* The AmlLength is used by the parser to indicate a constant,
* (if non-zero). Length is either (1/2/4/8)
*/
{
case 1:
break;
case 2:
break;
case 4:
break;
case 8:
break;
case 0:
default:
break;
}
}
/*******************************************************************************
*
* FUNCTION: OpcAmlEvaluationWalk1
*
* PARAMETERS: ASL_WALK_CALLBACK
*
* RETURN: Status
*
* DESCRIPTION: Descending callback for AML execution of constant subtrees
*
******************************************************************************/
static ACPI_STATUS
void *Context)
{
/* Copy child pointer to Arg for compatibility with Interpreter */
{
}
/* Call AML dispatcher */
if (ACPI_FAILURE (Status))
{
"%s Constant interpretation failed (1) - %s\n",
}
return (Status);
}
/*******************************************************************************
*
* FUNCTION: OpcAmlEvaluationWalk2
*
* PARAMETERS: ASL_WALK_CALLBACK
*
* RETURN: Status
*
* DESCRIPTION: Ascending callback for AML execution of constant subtrees
*
******************************************************************************/
static ACPI_STATUS
void *Context)
{
/* Copy child pointer to Arg for compatibility with Interpreter */
{
}
/* Call AML dispatcher */
if (ACPI_FAILURE (Status))
{
"%s: Constant interpretation failed (2) - %s\n",
}
return (Status);
}