Disassembler: Fix missing code problem with ElseIf conversion

During conversion of Else...If sequences to ASL ElseIf statements,
blocks of code can become detached from the parse tree and lost.
This change fixes the problem.
This commit is contained in:
Robert Moore 2016-09-23 12:45:33 -07:00
parent d14099ff86
commit 39ec745ded

View File

@ -136,6 +136,10 @@ static void
AcpiDmConvertToElseIf (
ACPI_PARSE_OBJECT *Op);
static void
AcpiDmPromoteSubtree (
ACPI_PARSE_OBJECT *StartOp);
/*******************************************************************************
*
@ -1139,16 +1143,26 @@ AcpiDmConvertToElseIf (
* be the only blocks under the original Else.
*/
IfOp = OriginalElseOp->Common.Value.Arg;
if (!IfOp ||
(IfOp->Common.AmlOpcode != AML_IF_OP) ||
(IfOp->Asl.Next && (IfOp->Asl.Next->Common.AmlOpcode != AML_ELSE_OP)))
{
/* Not an Else..If sequence, cannot convert to ElseIf */
/* Not a proper Else..If sequence, cannot convert to ElseIf */
AcpiOsPrintf ("%s", "Else");
return;
}
/* Cannot have anything following the If...Else block */
ElseOp = IfOp->Common.Next;
if (ElseOp && ElseOp->Common.Next)
{
AcpiOsPrintf ("%s", "Else");
return;
}
/* Emit ElseIf, mark the IF as now an ELSEIF */
AcpiOsPrintf ("%s", "ElseIf");
@ -1172,7 +1186,10 @@ AcpiDmConvertToElseIf (
/* If an ELSE matches the IF, promote it also */
ElseOp->Common.Parent = OriginalElseOp->Common.Parent;
ElseOp->Common.Next = OriginalElseOp->Common.Next;
/* Promote the entire block under the ElseIf (All Next OPs) */
AcpiDmPromoteSubtree (OriginalElseOp);
}
else
{
@ -1194,3 +1211,48 @@ AcpiDmConvertToElseIf (
OriginalElseOp->Common.Next = IfOp;
}
/*******************************************************************************
*
* FUNCTION: AcpiDmPromoteSubtree
*
* PARAMETERS: StartOpOp - Original parent of the entire subtree
*
* RETURN: None
*
* DESCRIPTION: Promote an entire parse subtree up one level.
*
******************************************************************************/
static void
AcpiDmPromoteSubtree (
ACPI_PARSE_OBJECT *StartOp)
{
ACPI_PARSE_OBJECT *Op;
ACPI_PARSE_OBJECT *ParentOp;
/* New parent for subtree elements */
ParentOp = StartOp->Common.Parent;
/* First child starts the subtree */
Op = StartOp->Common.Value.Arg;
/* Walk the top-level elements of the subtree */
while (Op)
{
Op->Common.Parent = ParentOp;
if (!Op->Common.Next)
{
/* Last Op in list, update its next field */
Op->Common.Next = StartOp->Common.Next;
break;
}
Op = Op->Common.Next;
}
}