Browse Source

Fix #1605: Inline ref locals more aggressively; this is necessary for VB compound assignments.

pull/1612/head
Daniel Grunwald 6 years ago
parent
commit
df13f0ce01
  1. 4
      ICSharpCode.Decompiler.Tests/Helpers/Tester.VB.cs
  2. 2
      ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
  3. 4
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/RefLocalsAndReturns.cs
  4. 1
      ICSharpCode.Decompiler.Tests/TestCases/VBPretty/.gitignore
  5. 20
      ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBCompoundAssign.cs
  6. 14
      ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBCompoundAssign.vb
  7. 14
      ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs
  8. 8
      ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs

4
ICSharpCode.Decompiler.Tests/Helpers/Tester.VB.cs

@ -56,10 +56,10 @@ namespace ICSharpCode.Decompiler.Tests.Helpers @@ -56,10 +56,10 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
var provider = new VBCodeProvider(new Dictionary<string, string> { { "CompilerVersion", "v4.0" } });
CompilerParameters options = new CompilerParameters();
options.GenerateExecutable = !flags.HasFlag(CompilerOptions.Library);
options.CompilerOptions = "/o" + (flags.HasFlag(CompilerOptions.Optimize) ? "+" : "-");
options.CompilerOptions = "/optimize" + (flags.HasFlag(CompilerOptions.Optimize) ? "+" : "-");
options.CompilerOptions += (flags.HasFlag(CompilerOptions.UseDebug) ? " /debug" : "");
options.CompilerOptions += (flags.HasFlag(CompilerOptions.Force32Bit) ? " /platform:anycpu32bitpreferred" : "");
options.CompilerOptions += "/optioninfer+ /optionexplicit+";
options.CompilerOptions += " /optioninfer+ /optionexplicit+";
if (preprocessorSymbols.Count > 0) {
options.CompilerOptions += " /d:" + string.Join(",", preprocessorSymbols.Select(p => $"{p.Key}={p.Value}"));
}

2
ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj

@ -81,6 +81,7 @@ @@ -81,6 +81,7 @@
<Compile Include="DisassemblerPrettyTestRunner.cs" />
<Compile Include="TestCases\ILPretty\ConstantBlobs.cs" />
<Compile Include="TestCases\Pretty\OutVariables.cs" />
<None Include="TestCases\VBPretty\VBCompoundAssign.cs" />
<None Include="TestCases\ILPretty\Issue1145.cs" />
<Compile Include="TestCases\ILPretty\Issue1157.cs" />
<None Include="TestCases\ILPretty\Unsafe.cs" />
@ -243,6 +244,7 @@ @@ -243,6 +244,7 @@
<None Include="TestCases\ILPretty\Issue379.il" />
<None Include="TestCases\ILPretty\Issue982.il" />
<None Include="TestCases\Pretty\Readme.txt" />
<None Include="TestCases\VBPretty\VBCompoundAssign.vb" />
<None Include="TestCases\VBPretty\Async.vb" />
</ItemGroup>

4
ICSharpCode.Decompiler.Tests/TestCases/Pretty/RefLocalsAndReturns.cs

@ -193,7 +193,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -193,7 +193,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
ref NormalStruct @ref = ref GetRef<NormalStruct>();
RefReassignment(ref @ref);
@ref = ref GetRef<NormalStruct>();
if (s.GetHashCode() == 0) {
@ref = ref GetRef<NormalStruct>();
}
RefReassignment(ref @ref.GetHashCode() == 4 ? ref @ref : ref s);
}

1
ICSharpCode.Decompiler.Tests/TestCases/VBPretty/.gitignore vendored

@ -0,0 +1 @@ @@ -0,0 +1 @@
*.dll

20
ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBCompoundAssign.cs

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
using Microsoft.VisualBasic;
using Microsoft.VisualBasic.CompilerServices;
[StandardModule]
internal sealed class VBCompoundAssign
{
public static double[] Sum3(int[] v)
{
double[] array = new double[4];
int num = Information.UBound(v);
checked {
for (int i = 0; i <= num; i += 3) {
array[0] += v[i];
array[1] += v[i + 1];
array[2] += v[i + 2];
}
return array;
}
}
}

14
ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBCompoundAssign.vb

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
Imports System
Imports Microsoft.VisualBasic
Module VBCompoundAssign
Function Sum3(v As Int32()) As Double()
Dim arr(3) As Double
For i = 0 To UBound(v) Step 3
arr(0) += v(i)
arr(1) += v(i + 1)
arr(2) += v(i + 2)
Next
Return arr
End Function
End Module

14
ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs

@ -61,17 +61,27 @@ namespace ICSharpCode.Decompiler.Tests @@ -61,17 +61,27 @@ namespace ICSharpCode.Decompiler.Tests
};
[Test, Ignore("Implement VB async/await")]
public void Async([ValueSource("defaultOptions")] CompilerOptions options)
public void Async([ValueSource(nameof(defaultOptions))] CompilerOptions options)
{
Run(options: options);
}
[Test] // TODO: legacy VB compound assign
public void VBCompoundAssign([ValueSource(nameof(roslynOnlyOptions))] CompilerOptions options)
{
Run(options: options | CompilerOptions.Library);
}
void Run([CallerMemberName] string testName = null, CompilerOptions options = CompilerOptions.UseDebug, DecompilerSettings settings = null)
{
var vbFile = Path.Combine(TestCasePath, testName + ".vb");
var csFile = Path.Combine(TestCasePath, testName + ".cs");
var exeFile = Path.Combine(TestCasePath, testName) + Tester.GetSuffix(options) + ".exe";
if (options.HasFlag(CompilerOptions.Library)) {
exeFile = Path.ChangeExtension(exeFile, ".dll");
}
var executable = Tester.CompileVB(vbFile, options);
var executable = Tester.CompileVB(vbFile, options | CompilerOptions.ReferenceVisualBasic, exeFile);
var decompiled = Tester.DecompileCSharp(executable.PathToAssembly, settings);
CodeAssert.FilesAreEqual(csFile, decompiled);

8
ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs

@ -404,7 +404,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -404,7 +404,13 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
break;
}
if (inlinedExpression.ResultType == StackType.Ref) {
// VB likes to use ref locals for compound assignment
// (the C# compiler uses ref stack slots instead).
// We want to avoid unnecessary ref locals, so we'll always inline them if possible.
return true;
}
var parent = loadInst.Parent;
if (NullableLiftingTransform.MatchNullableCtor(parent, out _, out _)) {
// inline into nullable ctor call in lifted operator

Loading…
Cancel
Save