mirror of
https://github.com/acpica/acpica/
synced 2025-01-15 22:09:17 +03:00
iASL: Fix constant folding for fixed-length constants.
This change fixes a problem where the constant folding code was not invoked for arguments that compile to fixed-length constants (either Byte, Word, DWord, or QWord.) ACPICA BZ 970.
This commit is contained in:
parent
c5667d3f74
commit
ffefc5e308
@ -665,6 +665,11 @@ TrSetNodeFlags (
|
||||
ACPI_PARSE_OBJECT *Op,
|
||||
UINT32 Flags);
|
||||
|
||||
ACPI_PARSE_OBJECT *
|
||||
TrSetNodeAmlLength (
|
||||
ACPI_PARSE_OBJECT *Op,
|
||||
UINT32 Length);
|
||||
|
||||
ACPI_PARSE_OBJECT *
|
||||
TrLinkPeerNodes (
|
||||
UINT32 NumPeers,
|
||||
|
@ -2579,30 +2579,38 @@ ConstExprTerm
|
||||
| PARSEOP___PATH__ {$$ = TrCreateConstantLeafNode (PARSEOP___PATH__);}
|
||||
;
|
||||
|
||||
/*
|
||||
* The NODE_COMPILE_TIME_CONST flag in the following constant expressions
|
||||
* enables compile-time constant folding to reduce the Type3Opcodes/Type2IntegerOpcodes
|
||||
* to simple integers. It is an error if these types of expressions cannot be
|
||||
* reduced, since the AML grammar for ****ConstExpr requires a simple constant.
|
||||
* Note: The required byte length of the constant is passed through to the
|
||||
* constant folding code in the node AmlLength field.
|
||||
*/
|
||||
ByteConstExpr
|
||||
: Type3Opcode {$$ = TrUpdateNode (PARSEOP_BYTECONST, $1);}
|
||||
| Type2IntegerOpcode {$$ = TrUpdateNode (PARSEOP_BYTECONST, $1);}
|
||||
: Type3Opcode {$$ = TrSetNodeFlags ($1, NODE_COMPILE_TIME_CONST); TrSetNodeAmlLength ($1, 1);}
|
||||
| Type2IntegerOpcode {$$ = TrSetNodeFlags ($1, NODE_COMPILE_TIME_CONST); TrSetNodeAmlLength ($1, 1);}
|
||||
| ConstExprTerm {$$ = TrUpdateNode (PARSEOP_BYTECONST, $1);}
|
||||
| ByteConst {}
|
||||
;
|
||||
|
||||
WordConstExpr
|
||||
: Type3Opcode {$$ = TrUpdateNode (PARSEOP_WORDCONST, $1);}
|
||||
| Type2IntegerOpcode {$$ = TrUpdateNode (PARSEOP_WORDCONST, $1);}
|
||||
: Type3Opcode {$$ = TrSetNodeFlags ($1, NODE_COMPILE_TIME_CONST); TrSetNodeAmlLength ($1, 2);}
|
||||
| Type2IntegerOpcode {$$ = TrSetNodeFlags ($1, NODE_COMPILE_TIME_CONST); TrSetNodeAmlLength ($1, 2);}
|
||||
| ConstExprTerm {$$ = TrUpdateNode (PARSEOP_WORDCONST, $1);}
|
||||
| WordConst {}
|
||||
;
|
||||
|
||||
DWordConstExpr
|
||||
: Type3Opcode {$$ = TrUpdateNode (PARSEOP_DWORDCONST, $1);}
|
||||
| Type2IntegerOpcode {$$ = TrUpdateNode (PARSEOP_DWORDCONST, $1);}
|
||||
: Type3Opcode {$$ = TrSetNodeFlags ($1, NODE_COMPILE_TIME_CONST); TrSetNodeAmlLength ($1, 4);}
|
||||
| Type2IntegerOpcode {$$ = TrSetNodeFlags ($1, NODE_COMPILE_TIME_CONST); TrSetNodeAmlLength ($1, 4);}
|
||||
| ConstExprTerm {$$ = TrUpdateNode (PARSEOP_DWORDCONST, $1);}
|
||||
| DWordConst {}
|
||||
;
|
||||
|
||||
QWordConstExpr
|
||||
: Type3Opcode {$$ = TrUpdateNode (PARSEOP_QWORDCONST, $1);}
|
||||
| Type2IntegerOpcode {$$ = TrUpdateNode (PARSEOP_QWORDCONST, $1);}
|
||||
: Type3Opcode {$$ = TrSetNodeFlags ($1, NODE_COMPILE_TIME_CONST); TrSetNodeAmlLength ($1, 8);}
|
||||
| Type2IntegerOpcode {$$ = TrSetNodeFlags ($1, NODE_COMPILE_TIME_CONST); TrSetNodeAmlLength ($1, 8);}
|
||||
| ConstExprTerm {$$ = TrUpdateNode (PARSEOP_QWORDCONST, $1);}
|
||||
| QWordConst {}
|
||||
;
|
||||
|
@ -145,6 +145,11 @@ OpcAmlCheckForConstant (
|
||||
UINT32 Level,
|
||||
void *Context);
|
||||
|
||||
static void
|
||||
OpcUpdateIntegerNode (
|
||||
ACPI_PARSE_OBJECT *Op,
|
||||
UINT64 Value);
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
@ -393,8 +398,8 @@ OpcAmlConstantWalk (
|
||||
|
||||
WalkState->NextOp = NULL;
|
||||
WalkState->Params = NULL;
|
||||
WalkState->CallerReturnDesc = &ObjDesc;
|
||||
WalkState->WalkType = WalkType;
|
||||
WalkState->CallerReturnDesc = &ObjDesc;
|
||||
|
||||
/*
|
||||
* Examine the entire subtree -- all nodes must be constants
|
||||
@ -454,22 +459,26 @@ OpcAmlConstantWalk (
|
||||
|
||||
Status = AcpiDsResultPop (&ObjDesc, WalkState);
|
||||
}
|
||||
|
||||
/* Check for error from the ACPICA core */
|
||||
|
||||
if (ACPI_FAILURE (Status))
|
||||
{
|
||||
AslCoreSubsystemError (Op, Status,
|
||||
"Failure during constant evaluation", FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
if (ACPI_FAILURE (Status))
|
||||
{
|
||||
/* We could not resolve the subtree for some reason */
|
||||
|
||||
AslCoreSubsystemError (Op, Status,
|
||||
"Failure during constant evaluation", FALSE);
|
||||
AslError (ASL_ERROR, ASL_MSG_CONSTANT_EVALUATION, Op,
|
||||
Op->Asl.ParseOpName);
|
||||
|
||||
/* Set the subtree value to ZERO anyway. Eliminates further errors */
|
||||
|
||||
Op->Asl.ParseOpcode = PARSEOP_INTEGER;
|
||||
Op->Common.Value.Integer = 0;
|
||||
OpcSetOptimalIntegerSize (Op);
|
||||
OpcUpdateIntegerNode (Op, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -484,13 +493,12 @@ OpcAmlConstantWalk (
|
||||
{
|
||||
case ACPI_TYPE_INTEGER:
|
||||
|
||||
Op->Asl.ParseOpcode = PARSEOP_INTEGER;
|
||||
Op->Common.Value.Integer = ObjDesc->Integer.Value;
|
||||
OpcSetOptimalIntegerSize (Op);
|
||||
OpcUpdateIntegerNode (Op, ObjDesc->Integer.Value);
|
||||
|
||||
DbgPrint (ASL_PARSE_OUTPUT,
|
||||
"Constant expression reduced to (INTEGER) %8.8X%8.8X\n",
|
||||
ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value));
|
||||
"Constant expression reduced to (%s) %8.8X%8.8X\n",
|
||||
Op->Asl.ParseOpName,
|
||||
ACPI_FORMAT_UINT64 (Op->Common.Value.Integer));
|
||||
break;
|
||||
|
||||
|
||||
@ -557,7 +565,62 @@ OpcAmlConstantWalk (
|
||||
Op->Asl.Child = NULL;
|
||||
|
||||
AcpiDsDeleteWalkState (WalkState);
|
||||
|
||||
return (AE_CTRL_DEPTH);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: OpcUpdateIntegerNode
|
||||
*
|
||||
* PARAMETERS: Op - Current parse object
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Update node to the correct integer type.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static void
|
||||
OpcUpdateIntegerNode (
|
||||
ACPI_PARSE_OBJECT *Op,
|
||||
UINT64 Value)
|
||||
{
|
||||
|
||||
Op->Common.Value.Integer = Value;
|
||||
|
||||
/*
|
||||
* The AmlLength is used by the parser to indicate a constant,
|
||||
* (if non-zero). Length is either (1/2/4/8)
|
||||
*/
|
||||
switch (Op->Asl.AmlLength)
|
||||
{
|
||||
case 1:
|
||||
TrUpdateNode (PARSEOP_BYTECONST, Op);
|
||||
Op->Asl.AmlOpcode = AML_RAW_DATA_BYTE;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
TrUpdateNode (PARSEOP_WORDCONST, Op);
|
||||
Op->Asl.AmlOpcode = AML_RAW_DATA_WORD;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
TrUpdateNode (PARSEOP_DWORDCONST, Op);
|
||||
Op->Asl.AmlOpcode = AML_RAW_DATA_DWORD;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
TrUpdateNode (PARSEOP_QWORDCONST, Op);
|
||||
Op->Asl.AmlOpcode = AML_RAW_DATA_QWORD;
|
||||
break;
|
||||
|
||||
case 0:
|
||||
default:
|
||||
OpcSetOptimalIntegerSize (Op);
|
||||
TrUpdateNode (PARSEOP_INTEGER, Op);
|
||||
break;
|
||||
}
|
||||
|
||||
Op->Asl.AmlLength = 0;
|
||||
}
|
||||
|
@ -269,6 +269,7 @@ typedef enum
|
||||
ASL_MSG_UPPER_CASE,
|
||||
ASL_MSG_VENDOR_LIST,
|
||||
ASL_MSG_WRITE,
|
||||
ASL_MSG_RANGE,
|
||||
|
||||
/* These messages are used by the Preprocessor only */
|
||||
|
||||
@ -443,6 +444,7 @@ char *AslMessages [] = {
|
||||
/* ASL_MSG_UPPER_CASE */ "Non-hex letters must be upper case",
|
||||
/* ASL_MSG_VENDOR_LIST */ "Too many vendor data bytes (7 max)",
|
||||
/* ASL_MSG_WRITE */ "Could not write file",
|
||||
/* ASL_MSG_RANGE */ "Constant out of range",
|
||||
|
||||
/* Preprocessor */
|
||||
|
||||
|
@ -258,19 +258,21 @@ TrUpdateNode (
|
||||
switch (ParseOpcode)
|
||||
{
|
||||
case PARSEOP_BYTECONST:
|
||||
Op->Asl.Value.Integer = 0xFF;
|
||||
Op->Asl.Value.Integer = ACPI_UINT8_MAX;
|
||||
break;
|
||||
|
||||
case PARSEOP_WORDCONST:
|
||||
Op->Asl.Value.Integer = 0xFFFF;
|
||||
Op->Asl.Value.Integer = ACPI_UINT16_MAX;
|
||||
break;
|
||||
|
||||
case PARSEOP_DWORDCONST:
|
||||
Op->Asl.Value.Integer = 0xFFFFFFFF;
|
||||
Op->Asl.Value.Integer = ACPI_UINT32_MAX;
|
||||
break;
|
||||
|
||||
/* Don't need to do the QWORD case */
|
||||
|
||||
default:
|
||||
/* Don't care about others, don't need to check QWORD */
|
||||
/* Don't care about others */
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -285,15 +287,18 @@ TrUpdateNode (
|
||||
switch (ParseOpcode)
|
||||
{
|
||||
case PARSEOP_BYTECONST:
|
||||
Op = UtCheckIntegerRange (Op, 0x00, ACPI_UINT8_MAX);
|
||||
UtCheckIntegerRange (Op, 0x00, ACPI_UINT8_MAX);
|
||||
Op->Asl.Value.Integer &= ACPI_UINT8_MAX;
|
||||
break;
|
||||
|
||||
case PARSEOP_WORDCONST:
|
||||
Op = UtCheckIntegerRange (Op, 0x00, ACPI_UINT16_MAX);
|
||||
UtCheckIntegerRange (Op, 0x00, ACPI_UINT16_MAX);
|
||||
Op->Asl.Value.Integer &= ACPI_UINT16_MAX;
|
||||
break;
|
||||
|
||||
case PARSEOP_DWORDCONST:
|
||||
Op = UtCheckIntegerRange (Op, 0x00, ACPI_UINT32_MAX);
|
||||
UtCheckIntegerRange (Op, 0x00, ACPI_UINT32_MAX);
|
||||
Op->Asl.Value.Integer &= ACPI_UINT32_MAX;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -407,8 +412,41 @@ TrSetNodeFlags (
|
||||
}
|
||||
|
||||
Op->Asl.CompileFlags |= Flags;
|
||||
return (Op);
|
||||
}
|
||||
|
||||
return Op;
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: TrSetNodeAmlLength
|
||||
*
|
||||
* PARAMETERS: Op - An existing parse node
|
||||
* Length - AML Length
|
||||
*
|
||||
* RETURN: The updated parser op
|
||||
*
|
||||
* DESCRIPTION: Set the AML Length in a node. Used by the parser to indicate
|
||||
* the presence of a node that must be reduced to a fixed length
|
||||
* constant.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
ACPI_PARSE_OBJECT *
|
||||
TrSetNodeAmlLength (
|
||||
ACPI_PARSE_OBJECT *Op,
|
||||
UINT32 Length)
|
||||
{
|
||||
|
||||
DbgPrint (ASL_PARSE_OUTPUT,
|
||||
"\nSetNodeAmlLength: Op %p, %8.8X\n", Op, Length);
|
||||
|
||||
if (!Op)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Op->Asl.AmlLength = Length;
|
||||
return (Op);
|
||||
}
|
||||
|
||||
|
||||
|
@ -663,36 +663,23 @@ UtCheckIntegerRange (
|
||||
UINT32 LowValue,
|
||||
UINT32 HighValue)
|
||||
{
|
||||
char *ParseError = NULL;
|
||||
char Buffer[64];
|
||||
|
||||
|
||||
if (!Op)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (Op->Asl.Value.Integer < LowValue)
|
||||
if ((Op->Asl.Value.Integer < LowValue) ||
|
||||
(Op->Asl.Value.Integer > HighValue))
|
||||
{
|
||||
ParseError = "Value below valid range";
|
||||
Op->Asl.Value.Integer = LowValue;
|
||||
sprintf (MsgBuffer, "0x%X, allowable: 0x%X-0x%X",
|
||||
(UINT32) Op->Asl.Value.Integer, LowValue, HighValue);
|
||||
|
||||
AslError (ASL_ERROR, ASL_MSG_RANGE, Op, MsgBuffer);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (Op->Asl.Value.Integer > HighValue)
|
||||
{
|
||||
ParseError = "Value above valid range";
|
||||
Op->Asl.Value.Integer = HighValue;
|
||||
}
|
||||
|
||||
if (ParseError)
|
||||
{
|
||||
sprintf (Buffer, "%s 0x%X-0x%X", ParseError, LowValue, HighValue);
|
||||
AslCompilererror (Buffer);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return Op;
|
||||
return (Op);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user