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

Add VerifyMethodBody helper as a replacement of VerifyIL #66536

Merged
merged 8 commits into from
Feb 6, 2023
Merged
Show file tree
Hide file tree
Changes from 2 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
Original file line number Diff line number Diff line change
Expand Up @@ -3176,8 +3176,7 @@ internal override StrongNameKeys StrongNameKeys
// testData is only passed when running tests.
if (testData != null)
{
moduleBeingBuilt.SetMethodTestData(testData.Methods);
testData.Module = moduleBeingBuilt;
moduleBeingBuilt.SetTestData(testData);
}

return moduleBeingBuilt;
Expand Down
5 changes: 1 addition & 4 deletions src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1594,10 +1594,7 @@ private static MethodBody GenerateMethodBody(
}

// We will only save the IL builders when running tests.
if (moduleBuilder.SaveTestData)
{
moduleBuilder.SetMethodTestData(method, builder.GetSnapshot());
}
moduleBuilder.TestData?.SetMethodILBuilder(method, builder.GetSnapshot());

var stateMachineHoistedLocalSlots = default(ImmutableArray<EncHoistedLocalInfo>);
var stateMachineAwaiterSlots = default(ImmutableArray<Cci.ITypeReference>);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,7 @@ internal static EmitDifferenceResult EmitDifference(

if (testData != null)
{
moduleBeingBuilt.SetMethodTestData(testData.Methods);
testData.Module = moduleBeingBuilt;
moduleBeingBuilt.SetTestData(testData);
}

var definitionMap = moduleBeingBuilt.PreviousDefinitions;
Expand Down
184 changes: 96 additions & 88 deletions src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5728,94 +5728,102 @@ public async Task M(int? val)
var comp = CSharpTestBase.CreateCompilation(source, options: TestOptions.ReleaseDll);
comp.VerifyEmitDiagnostics();
var verifier = CompileAndVerify(comp);
verifier.VerifyIL("C.<M>d__1.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", source: source, expectedIL: @"
{
// Code size 176 (0xb0)
.maxstack 3
.locals init (int V_0,
C V_1,
int? V_2,
int V_3,
System.Runtime.CompilerServices.TaskAwaiter<int> V_4,
System.Exception V_5)
IL_0000: ldarg.0
IL_0001: ldfld ""int C.<M>d__1.<>1__state""
IL_0006: stloc.0
IL_0007: ldarg.0
IL_0008: ldfld ""C C.<M>d__1.<>4__this""
IL_000d: stloc.1
.try
{
IL_000e: ldloc.0
IL_000f: brfalse.s IL_0062
IL_0011: ldarg.0
IL_0012: ldfld ""int? C.<M>d__1.val""
IL_0017: stloc.2
IL_0018: ldloca.s V_2
IL_001a: call ""bool int?.HasValue.get""
IL_001f: brfalse.s IL_002b
IL_0021: ldloca.s V_2
IL_0023: call ""int int?.GetValueOrDefault()""
IL_0028: stloc.3
IL_0029: br.s IL_0087
IL_002b: ldloc.1
IL_002c: call ""System.Threading.Tasks.Task<int> C.Get()""
IL_0031: callvirt ""System.Runtime.CompilerServices.TaskAwaiter<int> System.Threading.Tasks.Task<int>.GetAwaiter()""
IL_0036: stloc.s V_4
IL_0038: ldloca.s V_4
IL_003a: call ""bool System.Runtime.CompilerServices.TaskAwaiter<int>.IsCompleted.get""
IL_003f: brtrue.s IL_007f
IL_0041: ldarg.0
IL_0042: ldc.i4.0
IL_0043: dup
IL_0044: stloc.0
IL_0045: stfld ""int C.<M>d__1.<>1__state""
IL_004a: ldarg.0
IL_004b: ldloc.s V_4
IL_004d: stfld ""System.Runtime.CompilerServices.TaskAwaiter<int> C.<M>d__1.<>u__1""
IL_0052: ldarg.0
IL_0053: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<M>d__1.<>t__builder""
IL_0058: ldloca.s V_4
IL_005a: ldarg.0
IL_005b: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter<int>, C.<M>d__1>(ref System.Runtime.CompilerServices.TaskAwaiter<int>, ref C.<M>d__1)""
IL_0060: leave.s IL_00af
IL_0062: ldarg.0
IL_0063: ldfld ""System.Runtime.CompilerServices.TaskAwaiter<int> C.<M>d__1.<>u__1""
IL_0068: stloc.s V_4
IL_006a: ldarg.0
IL_006b: ldflda ""System.Runtime.CompilerServices.TaskAwaiter<int> C.<M>d__1.<>u__1""
IL_0070: initobj ""System.Runtime.CompilerServices.TaskAwaiter<int>""
IL_0076: ldarg.0
IL_0077: ldc.i4.m1
IL_0078: dup
IL_0079: stloc.0
IL_007a: stfld ""int C.<M>d__1.<>1__state""
IL_007f: ldloca.s V_4
IL_0081: call ""int System.Runtime.CompilerServices.TaskAwaiter<int>.GetResult()""
IL_0086: stloc.3
IL_0087: ldloc.3
IL_0088: ldc.i4.1
IL_0089: pop
IL_008a: pop
IL_008b: ldsfld ""string string.Empty""
IL_0090: newobj ""System.NotImplementedException..ctor(string)""
IL_0095: throw
}
catch System.Exception
{
IL_0096: stloc.s V_5
IL_0098: ldarg.0
IL_0099: ldc.i4.s -2
IL_009b: stfld ""int C.<M>d__1.<>1__state""
IL_00a0: ldarg.0
IL_00a1: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<M>d__1.<>t__builder""
IL_00a6: ldloc.s V_5
IL_00a8: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)""
IL_00ad: leave.s IL_00af
}
IL_00af: ret
}
");
verifier.VerifyMethodBody("C.<M>d__1.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", @"
tmat marked this conversation as resolved.
Show resolved Hide resolved
{
// Code size 176 (0xb0)
.maxstack 3
.locals init (int V_0,
C V_1,
int? V_2,
int V_3,
System.Runtime.CompilerServices.TaskAwaiter<int> V_4,
System.Exception V_5)
// sequence point: <hidden>
IL_0000: ldarg.0
IL_0001: ldfld ""int C.<M>d__1.<>1__state""
IL_0006: stloc.0
IL_0007: ldarg.0
IL_0008: ldfld ""C C.<M>d__1.<>4__this""
IL_000d: stloc.1
.try
{
// sequence point: <hidden>
IL_000e: ldloc.0
IL_000f: brfalse.s IL_0062
// sequence point: switch (val ?? await Get())
IL_0011: ldarg.0
IL_0012: ldfld ""int? C.<M>d__1.val""
IL_0017: stloc.2
IL_0018: ldloca.s V_2
IL_001a: call ""bool int?.HasValue.get""
IL_001f: brfalse.s IL_002b
IL_0021: ldloca.s V_2
IL_0023: call ""int int?.GetValueOrDefault()""
IL_0028: stloc.3
IL_0029: br.s IL_0087
IL_002b: ldloc.1
IL_002c: call ""System.Threading.Tasks.Task<int> C.Get()""
IL_0031: callvirt ""System.Runtime.CompilerServices.TaskAwaiter<int> System.Threading.Tasks.Task<int>.GetAwaiter()""
IL_0036: stloc.s V_4
// sequence point: <hidden>
IL_0038: ldloca.s V_4
IL_003a: call ""bool System.Runtime.CompilerServices.TaskAwaiter<int>.IsCompleted.get""
IL_003f: brtrue.s IL_007f
IL_0041: ldarg.0
IL_0042: ldc.i4.0
IL_0043: dup
IL_0044: stloc.0
IL_0045: stfld ""int C.<M>d__1.<>1__state""
// async: yield
IL_004a: ldarg.0
IL_004b: ldloc.s V_4
IL_004d: stfld ""System.Runtime.CompilerServices.TaskAwaiter<int> C.<M>d__1.<>u__1""
IL_0052: ldarg.0
IL_0053: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<M>d__1.<>t__builder""
IL_0058: ldloca.s V_4
IL_005a: ldarg.0
IL_005b: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter<int>, C.<M>d__1>(ref System.Runtime.CompilerServices.TaskAwaiter<int>, ref C.<M>d__1)""
IL_0060: leave.s IL_00af
// async: resume
IL_0062: ldarg.0
IL_0063: ldfld ""System.Runtime.CompilerServices.TaskAwaiter<int> C.<M>d__1.<>u__1""
IL_0068: stloc.s V_4
IL_006a: ldarg.0
IL_006b: ldflda ""System.Runtime.CompilerServices.TaskAwaiter<int> C.<M>d__1.<>u__1""
IL_0070: initobj ""System.Runtime.CompilerServices.TaskAwaiter<int>""
IL_0076: ldarg.0
IL_0077: ldc.i4.m1
IL_0078: dup
IL_0079: stloc.0
IL_007a: stfld ""int C.<M>d__1.<>1__state""
IL_007f: ldloca.s V_4
IL_0081: call ""int System.Runtime.CompilerServices.TaskAwaiter<int>.GetResult()""
IL_0086: stloc.3
IL_0087: ldloc.3
// sequence point: <hidden>
IL_0088: ldc.i4.1
IL_0089: pop
IL_008a: pop
// sequence point: throw new NotImplementedException(string.Empty);
IL_008b: ldsfld ""string string.Empty""
IL_0090: newobj ""System.NotImplementedException..ctor(string)""
IL_0095: throw
}
catch System.Exception
{
// sequence point: <hidden>
IL_0096: stloc.s V_5
IL_0098: ldarg.0
IL_0099: ldc.i4.s -2
IL_009b: stfld ""int C.<M>d__1.<>1__state""
IL_00a0: ldarg.0
IL_00a1: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<M>d__1.<>t__builder""
IL_00a6: ldloc.s V_5
IL_00a8: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)""
IL_00ad: leave.s IL_00af
}
IL_00af: ret
}");
}

[Fact, WorkItem(46843, "https://github.com/dotnet/roslyn/issues/46843")]
Expand Down
21 changes: 19 additions & 2 deletions src/Compilers/Core/Portable/CodeGen/CompilationTestData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.Cci;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.Symbols;
using Microsoft.DiaSymReader;
using Roslyn.Utilities;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Threading;

Expand All @@ -34,15 +37,29 @@ public MethodData(ILBuilder ilBuilder, IMethodSymbolInternal method)
// The emitted module.
public CommonPEModuleBuilder? Module;

// MetadataWriter used to emit metadata
public MetadataWriter? MetadataWriter { get; private set; }

public Func<ISymWriterMetadataProvider, SymUnmanagedWriter>? SymWriterFactory;

private ImmutableDictionary<string, MethodData>? _lazyMethodsByName;

public void SetMetadataWriter(MetadataWriter writer)
{
Debug.Assert(MetadataWriter == null);
MetadataWriter = writer;
}

public void SetMethodILBuilder(IMethodSymbolInternal method, ILBuilder builder)
{
Methods.Add(method, new MethodData(builder, method));
}

public ILBuilder GetIL(Func<IMethodSymbolInternal, bool> predicate)
{
return Methods.Single(p => predicate(p.Key)).Value.ILBuilder;
}

private ImmutableDictionary<string, MethodData>? _lazyMethodsByName;

// Returns map indexed by name for those methods that have a unique name.
public ImmutableDictionary<string, MethodData> GetMethodsByName()
{
Expand Down
2 changes: 2 additions & 0 deletions src/Compilers/Core/Portable/Compilation/Compilation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3407,6 +3407,8 @@ internal static bool SerializePeToStream(
changes,
cancellationToken);

moduleBeingBuilt.TestData?.SetMetadataWriter(writer);

writer.WriteMetadataAndIL(
nativePdbWriter,
metadataStream,
Expand Down
16 changes: 5 additions & 11 deletions src/Compilers/Core/Portable/Emit/CommonPEModuleBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ internal abstract class CommonPEModuleBuilder : Cci.IUnit, Cci.IModuleReference
private ImmutableArray<Cci.ManagedResource> _lazyManagedResources;
private IEnumerable<EmbeddedText> _embeddedTexts = SpecializedCollections.EmptyEnumerable<EmbeddedText>();

// Only set when running tests to allow realized IL for a given method to be looked up by method.
internal ConcurrentDictionary<IMethodSymbolInternal, CompilationTestData.MethodData> TestData { get; private set; }
// Only set when running tests to allow inspection of the emitted data.
internal CompilationTestData TestData { get; private set; }
tmat marked this conversation as resolved.
Show resolved Hide resolved

internal EmitOptions EmitOptions { get; }

Expand Down Expand Up @@ -504,17 +504,11 @@ public IEnumerable<EmbeddedText> EmbeddedTexts
}
}

internal bool SaveTestData => TestData != null;

internal void SetMethodTestData(IMethodSymbolInternal method, ILBuilder builder)
{
TestData.Add(method, new CompilationTestData.MethodData(builder, method));
}

internal void SetMethodTestData(ConcurrentDictionary<IMethodSymbolInternal, CompilationTestData.MethodData> methods)
internal void SetTestData(CompilationTestData testData)
{
Debug.Assert(TestData == null);
TestData = methods;
TestData = testData;
testData.Module = this;
}

public int GetTypeDefinitionGeneration(Cci.INamedTypeDefinition typeDef)
Expand Down
1 change: 1 addition & 0 deletions src/Compilers/Core/Portable/PEWriter/PeWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ internal static bool WritePeToStream(

var properties = context.Module.SerializationProperties;

context.Module.TestData?.SetMetadataWriter(mdWriter);
nativePdbWriterOpt?.SetMetadataEmitter(mdWriter);

// Since we are producing a full assembly, we should not have a module version ID
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Runtime.CompilerServices;
using System.Xml.Linq;
using Microsoft.CodeAnalysis.CodeGen;
using Microsoft.CodeAnalysis.Collections;
using Microsoft.CodeAnalysis.Emit;
Expand Down Expand Up @@ -90,7 +91,7 @@ internal void VerifyIL(
if (!methodToken.IsNil)
{
string actualPdb = PdbToXmlConverter.DeltaPdbToXml(new ImmutableMemoryStream(PdbDelta), new[] { MetadataTokens.GetToken(methodToken) });
sequencePointMarkers = ILValidation.GetSequencePointMarkers(actualPdb);
sequencePointMarkers = ILValidation.GetSequencePointMarkers(XElement.Parse(actualPdb));

Assert.True(sequencePointMarkers.Count > 0, $"No sequence points found in:{Environment.NewLine}{actualPdb}");
}
Expand Down
Loading