Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ExpressionTypeDescender: push array element if binary expression matches with array pattern #1300

Merged
merged 3 commits into from
Dec 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 39 additions & 1 deletion src/Decompiler/Typing/ExpressionTypeDescender.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public class ExpressionTypeDescender : ExpressionVisitor<bool, TypeVariable>
protected readonly TypeStore store;
protected readonly TypeFactory factory;
protected readonly Unifier unifier;
protected readonly ArrayExpressionMatcher aem;
protected readonly Identifier globals;
protected readonly IReadOnlyDictionary<Identifier,LinearInductionVariable> ivs;

Expand All @@ -67,6 +68,7 @@ public ExpressionTypeDescender(IReadOnlyProgram program, TypeStore store, TypeFa
this.store = store;
this.factory = factory;
this.unifier = new DataTypeBuilderUnifier(factory, store);
this.aem = new ArrayExpressionMatcher(program.Platform.PointerType);
}

protected virtual TypeVariable TypeVar(Expression exp)
Expand Down Expand Up @@ -216,7 +218,20 @@ private TypeVariable ArrayField(
TypeVariable tvField)
{
var dtElement = factory.CreateStructureType(null, elementSize);
dtElement.Fields.Add(0, tvField);
if (
tvField.DataType is StructureType strField &&
// Structures with different sizes are not compatible
(strField.Size == 0 || strField.Size == elementSize))
{
foreach (var f in strField.Fields)
{
dtElement.Fields.Add(f);
}
}
else
{
dtElement.Fields.Add(0, tvField);
}
var tvElement = store.CreateTypeVariable(factory);
tvElement.DataType = dtElement;
tvElement.OriginalDataType = dtElement;
Expand Down Expand Up @@ -263,6 +278,7 @@ public bool VisitBinaryExpression(BinaryExpression binExp, TypeVariable tv)
{
case OperatorType.IAdd:
{
PushArrayElement(binExp);
var dt = PushAddendDataType(tvBin.DataType, tvRight.DataType);
if (dt != null)
MeetDataType(eLeft, dt);
Expand Down Expand Up @@ -439,6 +455,28 @@ public bool VisitBinaryExpression(BinaryExpression binExp, TypeVariable tv)
return dtSum;
}

private void PushArrayElement(BinaryExpression binExp)
{
var eLeft = binExp.Left;
var tvBin = TypeVar(binExp);
if (tvBin.DataType is not Pointer binPtr)
return;
if (!aem.Match(binExp))
return;
if (aem.ArrayPointer == eLeft)
{
if (binPtr.Pointee is not TypeVariable tvField)
{
tvField = store.CreateTypeVariable(factory);
tvField.DataType = binPtr.Pointee;
tvField.OriginalDataType = binPtr.Pointee;
}
ArrayField(
null, eLeft, eLeft.DataType.BitSize, 0,
OffsetOf(aem.ElementSize!), 0, tvField);
}
}

private static DataType PushMinuendDataType(DataType dtDiff, DataType dtSub)
{
if (dtDiff.Domain == Domain.Pointer)
Expand Down
41 changes: 41 additions & 0 deletions src/UnitTests/Decompiler/Typing/TypedExpressionRewriterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1567,5 +1567,46 @@ define main
RunStringTest(pb.BuildProgram(), sExp);
}

[Test]
public void TerMultiDimensionalArray()
{
var sExp =
#region Expected
@"// Before ///////
// main
// Return size: 0
define main
main_entry:
// succ: l1
l1:
r0 = Mem0[a + r1 * 0x20<32> + r2 * 4<32>:word32]
main_exit:

// After ///////
// main
// Return size: 0
define main
main_entry:
// succ: l1
l1:
r0 = (a + r1)->a0000[r2]
main_exit:

";
#endregion
var pb = new ProgramBuilder();
pb.Add("main", m =>
{
var r0 = m.Register("r0");
var r1 = m.Register("r1");
var r2 = m.Register("r2");
var a = m.Temp(PrimitiveType.Word32, "a");
m.Assign(
r0,
m.Mem32(m.IAdd(m.IAdd(a, m.IMul(r1, 32)), m.IMul(r2, 4)))
);
});
RunStringTest(pb.BuildProgram(), sExp);
}
}
}
Loading
Loading