Browse Source

#1055: Use more type hints in ExpressionBuilder.

pull/1087/head
Daniel Grunwald 8 years ago
parent
commit
480ddc0c8f
  1. 5
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs
  2. 35
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.il
  3. 28
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.opt.il
  4. 24
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.opt.roslyn.il
  5. 30
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.roslyn.il
  6. 6
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  7. 27
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  8. 6
      ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

5
ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.cs

@ -239,5 +239,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -239,5 +239,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
return v;
}
public bool EnumInConditionalOperator(bool b)
{
return string.Equals("", "", b ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
}
}
}

35
ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.il

@ -10,7 +10,7 @@ @@ -10,7 +10,7 @@
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly fpugcpej
.assembly mu5mxl5m
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
@ -20,15 +20,15 @@ @@ -20,15 +20,15 @@
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module fpugcpej.dll
// MVID: {F42443CE-6C18-4149-B04E-77437B350B2C}
.module mu5mxl5m.dll
// MVID: {DBFE6CB1-ED58-473D-986E-A633C15C8AEE}
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// Image base: 0x01650000
// Image base: 0x04E10000
// =============== CLASS MEMBERS DECLARATION ===================
@ -821,6 +821,33 @@ @@ -821,6 +821,33 @@
IL_000b: ret
} // end of method TypeAnalysisTests::ImplicitConversionToDecimal
.method public hidebysig instance bool
EnumInConditionalOperator(bool b) cil managed
{
// Code size 29 (0x1d)
.maxstack 3
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldstr ""
IL_0006: ldstr ""
IL_000b: ldarg.1
IL_000c: brtrue.s IL_0011
IL_000e: ldc.i4.5
IL_000f: br.s IL_0012
IL_0011: ldc.i4.4
IL_0012: nop
IL_0013: call bool [mscorlib]System.String::Equals(string,
string,
valuetype [mscorlib]System.StringComparison)
IL_0018: stloc.0
IL_0019: br.s IL_001b
IL_001b: ldloc.0
IL_001c: ret
} // end of method TypeAnalysisTests::EnumInConditionalOperator
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{

28
ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.opt.il

@ -10,7 +10,7 @@ @@ -10,7 +10,7 @@
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly '31uigzt1'
.assembly tbojr2zd
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
@ -20,15 +20,15 @@ @@ -20,15 +20,15 @@
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module '31uigzt1.dll'
// MVID: {77B7D9D4-A6DF-4CC8-B1E3-7B3B553633FF}
.module tbojr2zd.dll
// MVID: {A417EC21-8726-4629-9E82-47FE9895CD81}
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// Image base: 0x01360000
// Image base: 0x05150000
// =============== CLASS MEMBERS DECLARATION ===================
@ -566,6 +566,26 @@ @@ -566,6 +566,26 @@
IL_0006: ret
} // end of method TypeAnalysisTests::ImplicitConversionToDecimal
.method public hidebysig instance bool
EnumInConditionalOperator(bool b) cil managed
{
// Code size 23 (0x17)
.maxstack 8
IL_0000: ldstr ""
IL_0005: ldstr ""
IL_000a: ldarg.1
IL_000b: brtrue.s IL_0010
IL_000d: ldc.i4.5
IL_000e: br.s IL_0011
IL_0010: ldc.i4.4
IL_0011: call bool [mscorlib]System.String::Equals(string,
string,
valuetype [mscorlib]System.StringComparison)
IL_0016: ret
} // end of method TypeAnalysisTests::EnumInConditionalOperator
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{

24
ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.opt.roslyn.il

@ -25,14 +25,14 @@ @@ -25,14 +25,14 @@
.ver 0:0:0:0
}
.module TypeAnalysisTests.dll
// MVID: {6215C6B8-0FF3-4C9E-999F-BE9720986F05}
// MVID: {A4070ABB-2C83-48F4-BD1F-AFD93DD2EF34}
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// Image base: 0x03030000
// Image base: 0x00B60000
// =============== CLASS MEMBERS DECLARATION ===================
@ -568,6 +568,26 @@ @@ -568,6 +568,26 @@
IL_0006: ret
} // end of method TypeAnalysisTests::ImplicitConversionToDecimal
.method public hidebysig instance bool
EnumInConditionalOperator(bool b) cil managed
{
// Code size 23 (0x17)
.maxstack 8
IL_0000: ldstr ""
IL_0005: ldstr ""
IL_000a: ldarg.1
IL_000b: brtrue.s IL_0010
IL_000d: ldc.i4.5
IL_000e: br.s IL_0011
IL_0010: ldc.i4.4
IL_0011: call bool [mscorlib]System.String::Equals(string,
string,
valuetype [mscorlib]System.StringComparison)
IL_0016: ret
} // end of method TypeAnalysisTests::EnumInConditionalOperator
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{

30
ICSharpCode.Decompiler.Tests/TestCases/Pretty/TypeAnalysisTests.roslyn.il

@ -25,14 +25,14 @@ @@ -25,14 +25,14 @@
.ver 0:0:0:0
}
.module TypeAnalysisTests.dll
// MVID: {3A10F4E7-88B8-4945-8775-A3643132F64B}
// MVID: {052B0385-6029-49B3-BCD3-93C26CCA8399}
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// Image base: 0x01720000
// Image base: 0x03100000
// =============== CLASS MEMBERS DECLARATION ===================
@ -820,6 +820,32 @@ @@ -820,6 +820,32 @@
IL_000b: ret
} // end of method TypeAnalysisTests::ImplicitConversionToDecimal
.method public hidebysig instance bool
EnumInConditionalOperator(bool b) cil managed
{
// Code size 28 (0x1c)
.maxstack 3
.locals init (bool V_0)
IL_0000: nop
IL_0001: ldstr ""
IL_0006: ldstr ""
IL_000b: ldarg.1
IL_000c: brtrue.s IL_0011
IL_000e: ldc.i4.5
IL_000f: br.s IL_0012
IL_0011: ldc.i4.4
IL_0012: call bool [mscorlib]System.String::Equals(string,
string,
valuetype [mscorlib]System.StringComparison)
IL_0017: stloc.0
IL_0018: br.s IL_001a
IL_001a: ldloc.0
IL_001b: ret
} // end of method TypeAnalysisTests::EnumInConditionalOperator
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{

6
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -95,7 +95,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -95,7 +95,7 @@ namespace ICSharpCode.Decompiler.CSharp
bool isExpandedForm = false;
for (int i = 0; i < method.Parameters.Count; i++) {
var parameter = expectedParameters[i];
var arg = expressionBuilder.Translate(callArguments[firstParamIndex + i]);
var arg = expressionBuilder.Translate(callArguments[firstParamIndex + i], parameter.Type);
if (parameter.IsParams && i + 1 == method.Parameters.Count) {
// Parameter is marked params
// If the argument is an array creation, inline all elements into the call and add missing default values.
@ -438,11 +438,11 @@ namespace ICSharpCode.Decompiler.CSharp @@ -438,11 +438,11 @@ namespace ICSharpCode.Decompiler.CSharp
TranslatedExpression target;
IType targetType;
if (method.IsExtensionMethod && invokeMethod != null && method.Parameters.Count - 1 == invokeMethod.Parameters.Count) {
target = expressionBuilder.Translate(inst.Arguments[0]);
targetType = method.Parameters[0].Type;
target = expressionBuilder.Translate(inst.Arguments[0], targetType);
} else {
target = expressionBuilder.TranslateTarget(method, inst.Arguments[0], func.OpCode == OpCode.LdFtn);
targetType = method.DeclaringType;
target = expressionBuilder.TranslateTarget(method, inst.Arguments[0], func.OpCode == OpCode.LdFtn);
}
var lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentAssembly);
var or = new OverloadResolution(resolver.Compilation, method.Parameters.SelectArray(p => new TypeResolveResult(p.Type)));

27
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -274,9 +274,10 @@ namespace ICSharpCode.Decompiler.CSharp @@ -274,9 +274,10 @@ namespace ICSharpCode.Decompiler.CSharp
if (ShouldDisplayAsHex(inst.Value, inst.Parent)) {
literalValue = $"0x{inst.Value:X}";
}
return new PrimitiveExpression(inst.Value, literalValue)
var expr = new PrimitiveExpression(inst.Value, literalValue)
.WithILInstruction(inst)
.WithRR(new ConstantResolveResult(compilation.FindType(KnownTypeCode.Int32), inst.Value));
return AdjustConstantExpressionToType(expr, context.TypeHint);
}
protected internal override TranslatedExpression VisitLdcI8(LdcI8 inst, TranslationContext context)
@ -461,7 +462,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -461,7 +462,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (inst.Kind == ComparisonKind.Equality && inst.Right.MatchLdcI4(0)) {
// lifted logic.not
var targetType = NullableType.Create(compilation, compilation.FindType(KnownTypeCode.Boolean));
var arg = Translate(inst.Left).ConvertTo(targetType, this);
var arg = Translate(inst.Left, targetType).ConvertTo(targetType, this);
return new UnaryOperatorExpression(UnaryOperatorType.Not, arg.Expression)
.WithRR(new OperatorResolveResult(targetType, ExpressionType.Not, arg.ResolveResult))
.WithILInstruction(inst);
@ -1509,7 +1510,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1509,7 +1510,7 @@ namespace ICSharpCode.Decompiler.CSharp
.WithILInstruction(target)
.WithRR(new ThisResolveResult(member.DeclaringType, nonVirtualInvocation));
} else {
var translatedTarget = Translate(target);
var translatedTarget = Translate(target, constrainedTo ?? member.DeclaringType);
if (CallInstruction.ExpectedTypeForThisPointer(constrainedTo ?? member.DeclaringType) == StackType.Ref && translatedTarget.Type.GetStackType().IsIntegerType()) {
// when accessing members on value types, ensure we use a reference and not a pointer
translatedTarget = translatedTarget.ConvertTo(new ByReferenceType(constrainedTo ?? member.DeclaringType), this);
@ -1874,11 +1875,11 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1874,11 +1875,11 @@ namespace ICSharpCode.Decompiler.CSharp
if (lastElement.Indices?.Length > 0) {
var indexer = new IndexerExpression(null, lastElement.Indices.SelectArray(i => Translate(i is LdLoc ld ? indexVariables[ld.Variable] : i).Expression))
.WithILInstruction(inst).WithRR(memberRR);
elementsStack.Peek().Add(Assignment(indexer, Translate(info.Values.Single())));
elementsStack.Peek().Add(Assignment(indexer, Translate(info.Values.Single(), typeHint: indexer.Type)));
} else {
var target = new IdentifierExpression(lastElement.Member.Name)
.WithILInstruction(inst).WithRR(memberRR);
elementsStack.Peek().Add(Assignment(target, Translate(info.Values.Single())));
elementsStack.Peek().Add(Assignment(target, Translate(info.Values.Single(), typeHint: target.Type)));
}
break;
}
@ -1907,11 +1908,13 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1907,11 +1908,13 @@ namespace ICSharpCode.Decompiler.CSharp
Expression MakeInitializerElements(List<ILInstruction> values, IList<IParameter> parameters)
{
if (values.Count == 1)
return Translate(values[0]).ConvertTo(parameters[0].Type, this);
if (values.Count == 1) {
return Translate(values[0], typeHint: parameters[0].Type).ConvertTo(parameters[0].Type, this);
}
var expressions = new Expression[values.Count];
for (int i = 0; i < values.Count; i++)
expressions[i] = Translate(values[i]).ConvertTo(parameters[i].Type, this);
for (int i = 0; i < values.Count; i++) {
expressions[i] = Translate(values[i], typeHint: parameters[i].Type).ConvertTo(parameters[i].Type, this);
}
return new ArrayInitializerExpression(expressions);
}
@ -1952,7 +1955,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1952,7 +1955,7 @@ namespace ICSharpCode.Decompiler.CSharp
container.Peek().Elements.Add(aie);
container.Push(aie);
}
var val = Translate(value).ConvertTo(type, this, allowImplicitConversion: true);
var val = Translate(value, typeHint: type).ConvertTo(type, this, allowImplicitConversion: true);
container.Peek().Elements.Add(val);
elementResolveResults.Add(val.ResolveResult);
while (container.Count > 0 && container.Peek().Elements.Count == dimensionSizes[container.Count - 1]) {
@ -2053,8 +2056,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2053,8 +2056,8 @@ namespace ICSharpCode.Decompiler.CSharp
protected internal override TranslatedExpression VisitIfInstruction(IfInstruction inst, TranslationContext context)
{
var condition = TranslateCondition(inst.Condition);
var trueBranch = Translate(inst.TrueInst);
var falseBranch = Translate(inst.FalseInst);
var trueBranch = Translate(inst.TrueInst, typeHint: context.TypeHint);
var falseBranch = Translate(inst.FalseInst, typeHint: context.TypeHint);
BinaryOperatorType op = BinaryOperatorType.Any;
TranslatedExpression rhs = default(TranslatedExpression);

6
ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

@ -264,7 +264,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -264,7 +264,7 @@ namespace ICSharpCode.Decompiler.CSharp
return new YieldBreakStatement();
else if (!inst.Value.MatchNop()) {
IType targetType = currentFunction.IsAsync ? currentFunction.AsyncReturnType : currentFunction.ReturnType;
return new ReturnStatement(exprBuilder.Translate(inst.Value).ConvertTo(targetType, exprBuilder, allowImplicitConversion: true));
return new ReturnStatement(exprBuilder.Translate(inst.Value, typeHint: targetType).ConvertTo(targetType, exprBuilder, allowImplicitConversion: true));
} else
return new ReturnStatement();
}
@ -290,7 +290,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -290,7 +290,7 @@ namespace ICSharpCode.Decompiler.CSharp
{
var elementType = currentFunction.ReturnType.GetElementTypeFromIEnumerable(typeSystem.Compilation, true, out var isGeneric);
return new YieldReturnStatement {
Expression = exprBuilder.Translate(inst.Value).ConvertTo(elementType, exprBuilder)
Expression = exprBuilder.Translate(inst.Value, typeHint: elementType).ConvertTo(elementType, exprBuilder)
};
}
@ -706,7 +706,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -706,7 +706,7 @@ namespace ICSharpCode.Decompiler.CSharp
if (inst.Init.OpCode == OpCode.ArrayToPointer) {
initExpr = exprBuilder.Translate(((ArrayToPointer)inst.Init).Array);
} else {
initExpr = exprBuilder.Translate(inst.Init).ConvertTo(inst.Variable.Type, exprBuilder);
initExpr = exprBuilder.Translate(inst.Init, typeHint: inst.Variable.Type).ConvertTo(inst.Variable.Type, exprBuilder);
}
fixedStmt.Variables.Add(new VariableInitializer(inst.Variable.Name, initExpr).WithILVariable(inst.Variable));
fixedStmt.EmbeddedStatement = Convert(inst.Body);

Loading…
Cancel
Save