diff --git a/src/Compilers/CSharp/Test/Emit/Emit/DynamicAnalysis/DynamicInstrumentationTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/DynamicAnalysis/DynamicInstrumentationTests.cs index e4416544babb2..069412ca905a9 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/DynamicAnalysis/DynamicInstrumentationTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/DynamicAnalysis/DynamicInstrumentationTests.cs @@ -4109,6 +4109,92 @@ .maxstack 3 """); } + [Fact] + public void UnionDeclaration_01() + { + string source = """ +_ = (TestUnion)123; +Microsoft.CodeAnalysis.Runtime.Instrumentation.FlushPayload(); + +public union TestUnion(string, int); +""" + InstrumentationHelperSource; + + var checker = new CSharpInstrumentationChecker(); + checker.Method(7, 1, snippet: "", expectBodySpan: false) + .True("_ = (TestUnion)123;") + .True("Microsoft.CodeAnalysis.Runtime.Instrumentation.FlushPayload();"); + + var verifier = CompileAndVerify([source, UnionAttributeSource, IUnionSource], options: TestOptions.ReleaseExe); + checker.CompleteCheck(verifier.Compilation, source); + verifier.VerifyDiagnostics(); + + AssertNotInstrumented(verifier, "TestUnion.Value.get"); + AssertInstrumented(verifier, "TestUnion..ctor(int)"); + AssertInstrumented(verifier, "TestUnion..ctor(string)"); + + verifier.VerifyIL("TestUnion..ctor(int)", """ +{ + // Code size 63 (0x3f) + .maxstack 5 + IL_0000: ldsfld "bool[][] .PayloadRoot0" + IL_0005: ldtoken "TestUnion..ctor(int)" + IL_000a: ldelem.ref + IL_000b: brtrue.s IL_0032 + IL_000d: ldsfld "System.Guid .MVID" + IL_0012: ldtoken "TestUnion..ctor(int)" + IL_0017: ldtoken Source Document 0 + IL_001c: ldsfld "bool[][] .PayloadRoot0" + IL_0021: ldtoken "TestUnion..ctor(int)" + IL_0026: ldelema "bool[]" + IL_002b: ldc.i4.0 + IL_002c: call "bool[] Microsoft.CodeAnalysis.Runtime.Instrumentation.CreatePayload(System.Guid, int, int, ref bool[], int)" + IL_0031: pop + IL_0032: ldarg.0 + IL_0033: ldarg.1 + IL_0034: box "int" + IL_0039: stfld "object TestUnion.k__BackingField" + IL_003e: ret +} +"""); + + verifier = CompileAndVerify([source, UnionAttributeSource, IUnionSource], options: TestOptions.DebugExe); + checker.CompleteCheck(verifier.Compilation, source); + verifier.VerifyDiagnostics(); + + AssertNotInstrumented(verifier, "TestUnion.Value.get"); + AssertInstrumented(verifier, "TestUnion..ctor(int)"); + AssertInstrumented(verifier, "TestUnion..ctor(string)"); + + verifier.VerifyIL("TestUnion..ctor(int)", """ +{ + // Code size 66 (0x42) + .maxstack 5 + .locals init (bool[] V_0) + IL_0000: ldsfld "bool[][] .PayloadRoot0" + IL_0005: ldtoken "TestUnion..ctor(int)" + IL_000a: ldelem.ref + IL_000b: stloc.0 + IL_000c: ldloc.0 + IL_000d: brtrue.s IL_0034 + IL_000f: ldsfld "System.Guid .MVID" + IL_0014: ldtoken "TestUnion..ctor(int)" + IL_0019: ldtoken Source Document 0 + IL_001e: ldsfld "bool[][] .PayloadRoot0" + IL_0023: ldtoken "TestUnion..ctor(int)" + IL_0028: ldelema "bool[]" + IL_002d: ldc.i4.0 + IL_002e: call "bool[] Microsoft.CodeAnalysis.Runtime.Instrumentation.CreatePayload(System.Guid, int, int, ref bool[], int)" + IL_0033: stloc.0 + IL_0034: ldarg.0 + IL_0035: ldarg.1 + IL_0036: box "int" + IL_003b: stfld "object TestUnion.k__BackingField" + IL_0040: nop + IL_0041: ret +} +"""); + } + private static void AssertNotInstrumented(CompilationVerifier verifier, string qualifiedMethodName) => AssertInstrumented(verifier, qualifiedMethodName, expected: false); @@ -4123,7 +4209,7 @@ private static void AssertInstrumented(CompilationVerifier verifier, string qual Assert.True(expected == instrumented, $"Method '{qualifiedMethodName}' should {(expected ? "be" : "not be")} instrumented. Actual IL:{Environment.NewLine}{il}"); } - private CompilationVerifier CompileAndVerify(string source, string expectedOutput = null, CSharpCompilationOptions options = null, CSharpParseOptions parseOptions = null, Verification verify = default) + private CompilationVerifier CompileAndVerify(CSharpTestSource source, string expectedOutput = null, CSharpCompilationOptions options = null, CSharpParseOptions parseOptions = null, Verification verify = default) { return base.CompileAndVerify( source, diff --git a/src/Compilers/CSharp/Test/Emit2/Emit/LocalStateTracing/LocalStateTracingTests.cs b/src/Compilers/CSharp/Test/Emit2/Emit/LocalStateTracing/LocalStateTracingTests.cs index c0b7ed922c87a..ea8910f24bbfa 100644 --- a/src/Compilers/CSharp/Test/Emit2/Emit/LocalStateTracing/LocalStateTracingTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Emit/LocalStateTracing/LocalStateTracingTests.cs @@ -190,7 +190,7 @@ private static string WithHelpers(string source, bool displayContainingType = fa """ }; - private CompilationVerifier CompileAndVerify(string source, string? ilVerifyMessage = null, string? expectedOutput = null, TargetFramework targetFramework = s_targetFramework) + private CompilationVerifier CompileAndVerify(CSharpTestSource source, string? ilVerifyMessage = null, string? expectedOutput = null, TargetFramework targetFramework = s_targetFramework) => CompileAndVerify( source, options: (expectedOutput != null) ? TestOptions.UnsafeDebugExe : TestOptions.UnsafeDebugDll, @@ -200,7 +200,7 @@ private CompilationVerifier CompileAndVerify(string source, string? ilVerifyMess expectedOutput: expectedOutput); // Only used to diagnose test verification failures (rename CompileAndVerify to CompileAndVerifyFails and rerun). - public CompilationVerifier CompileAndVerifyFails(string source, string? ilVerifyMessage = null, string? expectedOutput = null) + public CompilationVerifier CompileAndVerifyFails(CSharpTestSource source, string? ilVerifyMessage = null, string? expectedOutput = null) => CompileAndVerify( source, options: (expectedOutput != null) ? TestOptions.UnsafeDebugExe : TestOptions.UnsafeDebugDll, @@ -7447,6 +7447,50 @@ public void M() M: L1 -> P'i1'[0] E.M: Returned Program.
$: Returned +"""); + } + + [Fact] + public void UnionDeclaration_01() + { + var source = WithHelpers(@" +public union TestUnion(string, int); +"); + var verifier = CompileAndVerify([source, UnionAttributeSource, IUnionSource]); + + AssertNotInstrumented(verifier, "TestUnion.Value.get"); + AssertInstrumented(verifier, "TestUnion..ctor(string)"); + verifier.VerifyIL("TestUnion..ctor(int)", $$""" +{ + // Code size 46 (0x2e) + .maxstack 3 + .locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0) + IL_0000: ldtoken "TestUnion..ctor(int)" + IL_0005: call "Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)" + IL_000a: stloc.0 + .try + { + IL_000b: ldloca.s V_0 + IL_000d: ldarg.1 + IL_000e: ldc.i4.0 + IL_000f: call "void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(uint, int)" + IL_0014: nop + IL_0015: ldarg.0 + IL_0016: ldarg.1 + IL_0017: box "int" + IL_001c: stfld "object TestUnion.k__BackingField" + IL_0021: nop + IL_0022: leave.s IL_002d + } + finally + { + IL_0024: ldloca.s V_0 + IL_0026: call "void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()" + IL_002b: nop + IL_002c: endfinally + } + IL_002d: ret +} """); } } diff --git a/src/Compilers/CSharp/Test/Emit2/Emit/RuntimeProbing/ModuleCancellationTests.cs b/src/Compilers/CSharp/Test/Emit2/Emit/RuntimeProbing/ModuleCancellationTests.cs index cb82f66d27300..124c3f57caca6 100644 --- a/src/Compilers/CSharp/Test/Emit2/Emit/RuntimeProbing/ModuleCancellationTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Emit/RuntimeProbing/ModuleCancellationTests.cs @@ -16,7 +16,7 @@ public sealed class ModuleCancellationTests : CSharpTestBase { private static readonly EmitOptions s_emitOptions = EmitOptions.Default.WithInstrumentationKinds([InstrumentationKind.ModuleCancellation]); - private CompilationVerifier CompileAndVerify(string source, string? expectedOutput = null, CSharpCompilationOptions? options = null, Verification? verification = null) + private CompilationVerifier CompileAndVerify(CSharpTestSource source, string? expectedOutput = null, CSharpCompilationOptions? options = null, Verification? verification = null) => CompileAndVerify( source, options: options ?? (expectedOutput != null ? TestOptions.UnsafeDebugExe : TestOptions.UnsafeDebugDll), @@ -2801,4 +2801,31 @@ object G(CancellationToken token = default) // definite assignment flow pass doesn't fail CompileAndVerify(source).VerifyDiagnostics(); } + + [Fact] + public void UnionDeclaration_01() + { + var source = """ + public union TestUnion(string, int); + """; + + var verifier = CompileAndVerify([source, UnionAttributeSource, IUnionSource]); + + AssertNotInstrumented(verifier, "TestUnion.Value.get"); + + verifier.VerifyIL("TestUnion..ctor(int)", $$""" + { + // Code size 24 (0x18) + .maxstack 2 + IL_0000: ldsflda "System.Threading.CancellationToken .ModuleCancellationToken" + IL_0005: call "void System.Threading.CancellationToken.ThrowIfCancellationRequested()" + IL_000a: ldarg.0 + IL_000b: ldarg.1 + IL_000c: box "int" + IL_0011: stfld "object TestUnion.k__BackingField" + IL_0016: nop + IL_0017: ret + } + """); + } } diff --git a/src/Compilers/CSharp/Test/Emit2/Emit/RuntimeProbing/StackOverflowProbingTests.cs b/src/Compilers/CSharp/Test/Emit2/Emit/RuntimeProbing/StackOverflowProbingTests.cs index 71affb7129233..91c19d60ba6ce 100644 --- a/src/Compilers/CSharp/Test/Emit2/Emit/RuntimeProbing/StackOverflowProbingTests.cs +++ b/src/Compilers/CSharp/Test/Emit2/Emit/RuntimeProbing/StackOverflowProbingTests.cs @@ -15,7 +15,7 @@ public sealed class StackOverflowProbingTests : CSharpTestBase { private static readonly EmitOptions s_emitOptions = EmitOptions.Default.WithInstrumentationKinds([InstrumentationKind.StackOverflowProbing]); - private CompilationVerifier CompileAndVerify(string source, string? expectedOutput = null, CSharpCompilationOptions? options = null, Verification? verification = null) + private CompilationVerifier CompileAndVerify(CSharpTestSource source, string? expectedOutput = null, CSharpCompilationOptions? options = null, Verification? verification = null) => CompileAndVerify( source, options: options ?? (expectedOutput != null ? TestOptions.UnsafeDebugExe : TestOptions.UnsafeDebugDll), @@ -764,4 +764,31 @@ .maxstack 2 } """); } + + [Fact] + public void UnionDeclaration_01() + { + var source = """ + public union TestUnion(string, int); + """; + + var verifier = CompileAndVerify([source, UnionAttributeSource, IUnionSource]); + + AssertNotInstrumented(verifier, "TestUnion.Value.get"); + + verifier.VerifyIL("TestUnion..ctor(int)", """ + { + // Code size 20 (0x14) + .maxstack 2 + IL_0000: call "void System.Runtime.CompilerServices.RuntimeHelpers.EnsureSufficientExecutionStack()" + IL_0005: nop + IL_0006: ldarg.0 + IL_0007: ldarg.1 + IL_0008: box "int" + IL_000d: stfld "object TestUnion.k__BackingField" + IL_0012: nop + IL_0013: ret + } + """); + } }