Skip to content

Commit

Permalink
Merge pull request #37994 from jcouv/il-verify2
Browse files Browse the repository at this point in the history
 Add IL verification with ILVerify in addition to PEVerify
  • Loading branch information
jcouv authored Feb 11, 2022
1 parent 5985aeb commit 262a650
Show file tree
Hide file tree
Showing 103 changed files with 756 additions and 377 deletions.
1 change: 1 addition & 0 deletions NuGet.config
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<add key="dotnet-tools" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json" />
<add key="dotnet5" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json" />
<add key="dotnet6" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6/nuget/v3/index.json" />
<add key="dotnet7" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet7/nuget/v3/index.json" />
<add key="dotnet-public" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public/nuget/v3/index.json" />
<add key="nuget-build" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/nuget-build/nuget/v3/index.json" />
<add key="vssdk" value="https://pkgs.dev.azure.com/azure-public/vside/_packaging/vssdk/nuget/v3/index.json" />
Expand Down
1 change: 1 addition & 0 deletions eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
but not higher than our minimum dogfoodable Visual Studio version, or else
the generators we build would load on the command line but not load in IDEs. -->
<SourceGeneratorMicrosoftCodeAnalysisVersion>3.8.0</SourceGeneratorMicrosoftCodeAnalysisVersion>
<MicrosoftILVerificationVersion>7.0.0-alpha.1.22060.1</MicrosoftILVerificationVersion>
</PropertyGroup>
<!--
Dependency versions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6161,7 +6161,7 @@ public static async IAsyncEnumerator<int> GetAsyncEnumerator(this Range range)
options: TestOptions.DebugExe,
parseOptions: TestOptions.Regular9);
comp.VerifyDiagnostics();
CompileAndVerify(comp, expectedOutput: "123");
CompileAndVerify(comp, expectedOutput: "123", verify: Verification.FailsILVerify);
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7614,7 +7614,7 @@ static void Main()
}

[Fact]
void InvokeVarForLvalueInParens()
public void InvokeVarForLvalueInParens()
{
var source = @"
class Program
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9603,7 +9603,7 @@ .locals init (int V_0, //a
IL_0066: callvirt ""void <>A{00000004}<System.Runtime.CompilerServices.CallSite, int, object>.Invoke(System.Runtime.CompilerServices.CallSite, ref int, object)""
IL_006b: ret
}
");
", verify: Verification.FailsILVerify); // ILVerify doesn't support TypedReference
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3117,9 +3117,10 @@ public static void Main()
}
}";

// PEVerify: [ : Test::Main][mdToken=0x6000001][offset 0x00000009][found Native Int][expected unmanaged pointer] Unexpected type on the stack.
var c = CompileAndVerifyUtil(text,
options: TestOptions.UnsafeReleaseDll,
verify: Verification.Fails);
verify: Verification.FailsPEVerify);

c.VerifyDiagnostics();
}
Expand Down
27 changes: 18 additions & 9 deletions src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenForEachTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1384,7 +1384,8 @@ ref struct DisposableEnumerator
public bool MoveNext() { return ++x < 4; }
public void Dispose() { System.Console.WriteLine(""Done with DisposableEnumerator""); }
}";
var compilation = CompileAndVerify(source, expectedOutput: @"
// ILVerify: Return type is ByRef, TypedReference, ArgHandle, or ArgIterator.
var compilation = CompileAndVerify(source, verify: Verification.FailsILVerify, expectedOutput: @"
1
2
3
Expand Down Expand Up @@ -1447,7 +1448,8 @@ ref struct DisposableEnumerator
public bool MoveNext() { return ++x < 4; }
public void Dispose(params object[] args) { System.Console.WriteLine($""Done with DisposableEnumerator. args was {args}, length {args.Length}""); }
}";
var compilation = CompileAndVerify(source, expectedOutput: @"
// ILVerify: Return type is ByRef, TypedReference, ArgHandle, or ArgIterator.
var compilation = CompileAndVerify(source, verify: Verification.FailsILVerify, expectedOutput: @"
1
2
3
Expand Down Expand Up @@ -1481,7 +1483,8 @@ ref struct DisposableEnumerator
public bool MoveNext() { return ++x < 4; }
public void Dispose(int arg = 1) { System.Console.WriteLine($""Done with DisposableEnumerator. arg was {arg}""); }
}";
var compilation = CompileAndVerify(source, expectedOutput: @"
// ILVerify: Return type is ByRef, TypedReference, ArgHandle, or ArgIterator.
var compilation = CompileAndVerify(source, verify: Verification.FailsILVerify, expectedOutput: @"
1
2
3
Expand Down Expand Up @@ -1521,7 +1524,8 @@ static class DisposeExtension
}
";
// extension methods do not contribute to disposal
CompileAndVerify(source, expectedOutput: @"123");
// ILVerify: Return type is ByRef, TypedReference, ArgHandle, or ArgIterator.
CompileAndVerify(source, verify: Verification.FailsILVerify, expectedOutput: @"123");
}

[Fact]
Expand Down Expand Up @@ -1561,7 +1565,8 @@ static class DisposeExtension2
}
";
// extension methods do not contribute to disposal
CompileAndVerify(source, expectedOutput: @"123");
// ILVerify: Return type is ByRef, TypedReference, ArgHandle, or ArgIterator.
CompileAndVerify(source, verify: Verification.FailsILVerify, expectedOutput: @"123");
}

[Fact]
Expand Down Expand Up @@ -1597,7 +1602,8 @@ static class DisposeExtension
}
";
// extension methods do not contribute to disposal
CompileAndVerify(source, expectedOutput: @"123");
// ILVerify: Return type is ByRef, TypedReference, ArgHandle, or ArgIterator.
CompileAndVerify(source, verify: Verification.FailsILVerify, expectedOutput: @"123");
}

[Fact]
Expand Down Expand Up @@ -1633,7 +1639,8 @@ static class DisposeExtension
}
";
// extension methods do not contribute to disposal
CompileAndVerify(source, expectedOutput: @"123");
// ILVerify: Return type is ByRef, TypedReference, ArgHandle, or ArgIterator.
CompileAndVerify(source, verify: Verification.FailsILVerify, expectedOutput: @"123");
}

[Fact]
Expand Down Expand Up @@ -1729,7 +1736,8 @@ ref struct DisposableEnumerator
public bool MoveNext() { return ++x < 4; }
public void Dispose() { System.Console.WriteLine(""Done with DisposableEnumerator""); }
}";
var compilation = CompileAndVerify(source, parseOptions: TestOptions.Regular7_3, expectedOutput: @"
// ILVerify: Return type is ByRef, TypedReference, ArgHandle, or ArgIterator.
var compilation = CompileAndVerify(source, parseOptions: TestOptions.Regular7_3, verify: Verification.FailsILVerify, expectedOutput: @"
1
2
3");
Expand Down Expand Up @@ -4725,7 +4733,8 @@ ref struct Enumerator
public bool MoveNext() => Current++ != 3;
public void Dispose() { Console.Write(""Disposed""); }
}";
CompileAndVerify(source, parseOptions: TestOptions.Regular9, expectedOutput: @"123Disposed")
// ILVerify: Return type is ByRef, TypedReference, ArgHandle, or ArgIterator.
CompileAndVerify(source, parseOptions: TestOptions.Regular9, verify: Verification.FailsILVerify, expectedOutput: @"123Disposed")
.VerifyIL("C.Main", @"
{
// Code size 45 (0x2d)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3982,7 +3982,8 @@ private void Test2(in int y, ref int f)

var compilation = CreateCompilation(code, options: TestOptions.ReleaseExe);

var verifier = CompileAndVerify(compilation, expectedOutput: "0011", verify: Verification.Fails);
// PEVerify: Cannot change initonly field outside its .ctor.
var verifier = CompileAndVerify(compilation, expectedOutput: "0011", verify: Verification.FailsPEVerify);

verifier.VerifyIL("Test..ctor()", @"
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System;
using System.Globalization;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;

Expand Down Expand Up @@ -1033,7 +1034,7 @@ public static void Main()
}
}
";
base.CompileAndVerify(source, expectedOutput: "12").
base.CompileAndVerify(source, verify: Verification.FailsILVerify, expectedOutput: "12").
VerifyIL("Test.Main",
@"
{
Expand Down
3 changes: 2 additions & 1 deletion src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenIterators.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2387,7 +2387,8 @@ public System.Collections.IEnumerable SomeNumbers()
}";
// The compilation succeeds even though CompilerGeneratedAttribute and DebuggerNonUserCodeAttribute are not available.
var compilation = CreateEmptyCompilation(new[] { Parse(source), Parse(corlib) });
var verifier = CompileAndVerify(compilation, verify: Verification.Fails);
// PEVerify: System.Enum must extend System.ValueType.
var verifier = CompileAndVerify(compilation, verify: Verification.FailsPEVerify);
verifier.VerifyDiagnostics(
// warning CS8021: No value for RuntimeMetadataVersion found. No assembly containing System.Object was found nor was a value for RuntimeMetadataVersion specified through options.
Diagnostic(ErrorCode.WRN_NoRuntimeMetadataVersion).WithLocation(1, 1));
Expand Down
8 changes: 8 additions & 0 deletions src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenMscorlib.cs
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,12 @@ void Main()
//IMPORTANT: we should NOT delegate E1.GetHashCode() to int.GetHashCode()
// it is entirely possible that Enum.GetHashCode and int.GetHashCode
// have different implementations

// PEVerify:
// Error: Token 0x02000009 following ELEMENT_TYPE_CLASS (_VALUETYPE) in signature is a ValueType (Class,respectively).
// Error: Token 0x02000009 following ELEMENT_TYPE_CLASS(_VALUETYPE) in signature is a ValueType (Class, respectively).
// Type load failed.
// ILVerify: Failed to load type 'System.String' from assembly ...
CompileAndVerify(comp, verify: Verification.Fails).
VerifyIL("program.Main()",
@"
Expand Down Expand Up @@ -871,6 +877,8 @@ void Main()
// but see the bug see VSW #396011, JIT needs references when loading
// fields of certain clr-ambiguous structs (only possible when building mscorlib)

// PEVerify: Type load failed.
// ILVerify: Failed to load type 'System.String' from assembly ...
CompileAndVerify(comp, verify: Verification.Fails).
VerifyIL("System.IntPtr..ctor(int)", @"
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2557,7 +2557,7 @@ public static void Main()
// from assembly 'Dev10, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'
// is overriding a method that is not visible from that assembly.

CompileAndVerify(outerCompilation, verify: Verification.Fails).VerifyIL("Test.Main", @"
CompileAndVerify(outerCompilation, verify: Verification.FailsPEVerify).VerifyIL("Test.Main", @"
{
// Code size 65 (0x41)
.maxstack 4
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ public override string ToString()
}
";

var comp = CompileAndVerify(text, parseOptions: TestOptions.Regular, verify: Verification.Fails, expectedOutput: @"12");
var comp = CompileAndVerify(text, parseOptions: TestOptions.Regular, verify: Verification.FailsPEVerify, expectedOutput: @"12");

comp.VerifyIL("Program.Main", @"
{
Expand Down Expand Up @@ -258,7 +258,8 @@ public override string ToString()
}
";

var comp = CompileAndVerify(text, parseOptions: TestOptions.Regular, verify: Verification.Fails, expectedOutput: @"hello2");
// PEVerify: Cannot change initonly field outside its .ctor.
var comp = CompileAndVerify(text, parseOptions: TestOptions.Regular, verify: Verification.FailsPEVerify, expectedOutput: @"hello2");

comp.VerifyIL("Program.Main", @"
{
Expand Down Expand Up @@ -338,7 +339,8 @@ static void Main()
}
";

var comp = CompileAndVerify(text, new[] { ref1 }, parseOptions: TestOptions.Regular, verify: Verification.Fails, expectedOutput: @"hello2");
// PEVerify: Cannot change initonly field outside its .ctor.
var comp = CompileAndVerify(text, new[] { ref1 }, parseOptions: TestOptions.Regular, verify: Verification.FailsPEVerify, expectedOutput: @"hello2");

comp.VerifyIL("Program.Main", @"
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1060,7 +1060,8 @@ public static void RoExtension(in this S1 self)
}
";

var comp = CompileAndVerifyWithMscorlib40(source, references: new[] { TestMetadata.Net40.System, ValueTupleRef, TestMetadata.Net40.SystemCore }, expectedOutput: "00", verify: Verification.Fails);
// PEVerify: Cannot change initonly field outside its .ctor.
var comp = CompileAndVerifyWithMscorlib40(source, references: new[] { TestMetadata.Net40.System, ValueTupleRef, TestMetadata.Net40.SystemCore }, expectedOutput: "00", verify: Verification.FailsPEVerify);
comp.VerifyDiagnostics();

comp.VerifyIL("Program.Main", @"
Expand Down Expand Up @@ -1147,8 +1148,8 @@ public override string ToString()
}
}
";

var comp = CompileAndVerify(source, expectedOutput: "00", verify: Verification.Fails);
// PEVerify: Cannot change initonly field outside its .ctor.
var comp = CompileAndVerify(source, expectedOutput: "00", verify: Verification.FailsPEVerify);
comp.VerifyDiagnostics();

comp.VerifyIL("Program.Test", @"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,7 @@ public void SubmissionEntryPoint()
"s0.dll",
SyntaxFactory.ParseSyntaxTree(source0, options: TestOptions.Script),
references);
var verifier = CompileAndVerify(s0, verify: Verification.Fails);
var verifier = CompileAndVerify(s0, verify: Verification.FailsPEVerify);
var methodData = verifier.TestData.GetMethodData("<Initialize>");
Assert.Equal("System.Threading.Tasks.Task<object>", ((MethodSymbol)methodData.Method).ReturnType.ToDisplayString());
methodData.VerifyIL(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5233,7 +5233,8 @@ public RefLike M()
public ref struct RefLike{}
}
";
var verifier = CompileAndVerify(source, options: TestOptions.DebugExe.WithAllowUnsafe(true), expectedOutput: @"---
// ILVerify: Return type is ByRef, TypedReference, ArgHandle, or ArgIterator.
var verifier = CompileAndVerify(source, verify: Verification.FailsILVerify, options: TestOptions.DebugExe.WithAllowUnsafe(true), expectedOutput: @"---
M
---
---");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -488,10 +488,11 @@ static void Main()
}
}
";
// PEVerify: [ : C::Main][mdToken=0x6000002][offset 0x00000002][found Native Int][expected unmanaged pointer] Unexpected type on the stack.
CompileAndVerify(text,
parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7_3),
options: TestOptions.UnsafeReleaseExe,
verify: Verification.Fails).VerifyIL("C.Main",
verify: Verification.FailsPEVerify).VerifyIL("C.Main",
@"{
// Code size 8 (0x8)
.maxstack 1
Expand Down
10 changes: 6 additions & 4 deletions src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenStructsAndEnum.cs
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,8 @@ static void Main(string[] args)
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"");
// ILVerify: Unexpected type on the stack. { Offset = 20, Found = readonly address of '[...]S1', Expected = address of '[...]S1' }
var compilation = CompileAndVerify(source, verify: Verification.FailsILVerify, expectedOutput: @"");

compilation.VerifyIL("S1.Equals(object)",
@"
Expand Down Expand Up @@ -448,7 +449,8 @@ static void Main()
}
}
";
var compilation = CompileAndVerify(source, expectedOutput: @"
// ILVerify: Unexpected type on the stack. { Offset = 31, Found = readonly address of '[...]NS.N2.S`2<string,uint8>', Expected = address of '[...]NS.N2.S`2<string,uint8>' }
var compilation = CompileAndVerify(source, verify: Verification.FailsILVerify, expectedOutput: @"
Abc
255
q");
Expand Down Expand Up @@ -2365,8 +2367,8 @@ static void Main(string[] args)
}
";

var compilation = CompileAndVerify(source, expectedOutput: "0");
// ILVerify: Unexpected type on the stack. { Offset = 10, Found = readonly address of '[...]C1', Expected = address of '[...]C1' }
var compilation = CompileAndVerify(source, verify: Verification.FailsILVerify, expectedOutput: "0");

compilation.VerifyIL("Program.Main",
@"
Expand Down
Loading

0 comments on commit 262a650

Please sign in to comment.