|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#if NET
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using Microsoft.CodeAnalysis.CSharp.EditAndContinue.UnitTests;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
public class LocalStateTracingTests : CSharpTestBase
{
// TODO: https://github.com/dotnet/roslyn/issues/66809
// arrays (stloc, stelem),
// collections, anonymous types, tuples
// LogLocalStoreUnmanaged with local/parameter typed to a generic parameter
// Primary constructor with field initializers
private static readonly EmitOptions s_emitOptions = GetEmitOptions(InstrumentationKindExtensions.LocalStateTracing);
private static EmitOptions GetEmitOptions(params InstrumentationKind[] kinds)
{
var options = EmitOptions.Default.WithInstrumentationKinds(ImmutableArray.CreateRange(kinds));
options.TestOnly_AllowLocalStateTracing();
return options;
}
private const string TrackerTypeName = "Microsoft.CodeAnalysis.Runtime.LocalStoreTracker";
private static readonly string s_helpers = """
namespace Microsoft.CodeAnalysis.Runtime
{
using System;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Threading;
using static System.Console;
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
public unsafe readonly ref partial struct LocalStoreTracker
{
private static int s_stateMachineId;
private readonly MethodBase M;
private readonly ParameterInfo[] Parameters;
private LocalStoreTracker(MethodBase m)
{
M = m;
Parameters = m.GetParameters();
}
public static LocalStoreTracker LogMethodEntry(int methodId)
=> Entry(methodId, lambdaId: 0, stateMachineId: 0);
public static LocalStoreTracker LogLambdaEntry(int methodId, int lambdaId)
=> Entry(methodId, lambdaId, stateMachineId: 0);
public static LocalStoreTracker LogStateMachineMethodEntry(int methodId, ulong stateMachineId)
=> Entry(methodId, lambdaId: 0, stateMachineId);
public static LocalStoreTracker LogStateMachineLambdaEntry(int methodId, int lambdaId, ulong stateMachineId)
=> Entry(methodId, lambdaId, stateMachineId);
public void LogReturn()
=> WriteLine($"{M.Name}: Returned");
public static ulong GetNewStateMachineInstanceId()
=> unchecked((ulong)Interlocked.Increment(ref s_stateMachineId));
private static LocalStoreTracker Entry(int methodId, int lambdaId, ulong stateMachineId)
{
var module = typeof(LocalStoreTracker).Assembly.Modules.Single();
var method = module.ResolveMethod(methodId + 0x06000000);
var message = $"{method.Name}: Entered";
if (lambdaId > 0)
{
var lambda = module.ResolveMethod(lambdaId + 0x06000000);
message += $" lambda '{lambda.Name}'";
method = lambda;
}
if (stateMachineId > 0)
{
message += $" state machine #{stateMachineId}";
}
WriteLine(message);
return new(method);
}
private void WL(object value, int index)
=> WriteLine($"{M.Name}: {L(index)} = {ConvertToString(value)}");
private void WP(object value, int index)
=> WriteLine($"{M.Name}: {P(index)} = {ConvertToString(value)}");
private string L(int index)
=> (index >= 0x10000) ? $"L'{UnmangleFieldName(M.Module.ResolveField(index - 0x10000 + 0x04000000).Name)}'" : $"L{index}";
private string P(int index)
=> (index >= 0x10000) ? $"P'{M.Module.ResolveField(index - 0x10000 + 0x04000000).Name}'" : $"P'{Parameters[index].Name}'[{index}]";
private static string UnmangleFieldName(string name)
=> (name[0] == '<') ? name.Substring(1, name.IndexOf('>') - 1) : name;
private static string MemoryToString(void* address, int size)
=> "<" + BitConverter.ToString(new Span<byte>(address, size).ToArray()) + ">";
private string ConvertToString(object value) => value switch
{
IFormattable f => f.ToString(null, CultureInfo.InvariantCulture),
object o => o.ToString(),
null => "null",
};
public void LogLocalStore(bool value, int index) => WL(value, index);
public void LogLocalStore(byte value, int index) => WL(value, index);
public void LogLocalStore(ushort value, int index) => WL(value, index);
public void LogLocalStore(uint value, int index) => WL(value, index);
public void LogLocalStore(ulong value, int index) => WL(value, index);
public void LogLocalStore(float value, int index) => WL(value, index);
public void LogLocalStore(double value, int index) => WL(value, index);
public void LogLocalStore(decimal value, int index) => WL(value, index);
public void LogLocalStore(string value, int index) => WL(value, index);
public void LogLocalStore(object value, int index) => WL(value, index);
public void LogLocalStore(void* value, int index) => WL((nuint)value, index);
public void LogLocalStoreUnmanaged(void* address, int size, int index) => WL(MemoryToString(address, size), index);
public void LogLocalStoreParameterAlias(int sourceParameterIndex, int targetLocalIndex) { WriteLine($"{M.Name}: {L(targetLocalIndex)} -> {P(sourceParameterIndex)}"); }
public void LogParameterStore(bool value, int index) => WP(value, index);
public void LogParameterStore(byte value, int index) => WP(value, index);
public void LogParameterStore(ushort value, int index) => WP(value, index);
public void LogParameterStore(uint value, int index) => WP(value, index);
public void LogParameterStore(ulong value, int index) => WP(value, index);
public void LogParameterStore(float value, int index) => WP(value, index);
public void LogParameterStore(double value, int index) => WP(value, index);
public void LogParameterStore(decimal value, int index) => WP(value, index);
public void LogParameterStore(string value, int index) => WP(value, index);
public void LogParameterStore(object value, int index) => WP(value, index);
public void LogParameterStore(void* value, int index) => WP((nuint)value, index);
public void LogParameterStoreUnmanaged(void* address, int size, int index) => WP(MemoryToString(address, size), index);
public void LogParameterStoreParameterAlias(int sourceParameterIndex, int targetParameterIndex) { WriteLine($"{M.Name}: {P(targetParameterIndex)} -> {P(sourceParameterIndex)}"); }
public void LogLocalStoreLocalAlias(int sourceLocalIndex, int targetLocalIndex) { WriteLine($"{M.Name}: {L(targetLocalIndex)} -> {L(sourceLocalIndex)}"); }
}
}
""";
private static string WithHelpers(string source)
=> source + s_helpers;
private const TargetFramework s_targetFramework = TargetFramework.Net70;
private static readonly Verification s_verification = Verification.Fails with
{
ILVerifyMessage = """
[LogMethodEntry]: Return type is ByRef, TypedReference, ArgHandle, or ArgIterator. { Offset = 0x9 }
[LogLambdaEntry]: Return type is ByRef, TypedReference, ArgHandle, or ArgIterator. { Offset = 0x9 }
[LogStateMachineMethodEntry]: Return type is ByRef, TypedReference, ArgHandle, or ArgIterator. { Offset = 0x8 }
[LogStateMachineLambdaEntry]: Return type is ByRef, TypedReference, ArgHandle, or ArgIterator. { Offset = 0x8 }
[Entry]: Return type is ByRef, TypedReference, ArgHandle, or ArgIterator. { Offset = 0xbc }
[MemoryToString]: Unmanaged pointers are not a verifiable type. { Offset = 0x5 }
[LogLocalStore]: Unmanaged pointers are not a verifiable type. { Offset = 0x1 }
[LogLocalStoreUnmanaged]: Unmanaged pointers are not a verifiable type. { Offset = 0x1 }
[LogParameterStore]: Unmanaged pointers are not a verifiable type. { Offset = 0x1 }
[LogParameterStoreUnmanaged]: Unmanaged pointers are not a verifiable type. { Offset = 0x1 }
"""
};
private CompilationVerifier CompileAndVerify(string source, string? ilVerifyMessage = null, string? expectedOutput = null, TargetFramework targetFramework = s_targetFramework)
=> CompileAndVerify(
source,
options: (expectedOutput != null) ? TestOptions.UnsafeDebugExe : TestOptions.UnsafeDebugDll,
emitOptions: s_emitOptions,
verify: s_verification with { ILVerifyMessage = ilVerifyMessage + Environment.NewLine + s_verification.ILVerifyMessage },
targetFramework: targetFramework,
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)
=> CompileAndVerify(
source,
options: (expectedOutput != null) ? TestOptions.UnsafeDebugExe : TestOptions.UnsafeDebugDll,
emitOptions: s_emitOptions,
verify: Verification.Fails,
targetFramework: s_targetFramework,
expectedOutput: null);
private static void AssertNotInstrumented(CompilationVerifier verifier, string qualifiedMethodName)
=> AssertInstrumented(verifier, qualifiedMethodName, expected: false);
private static void AssertInstrumented(CompilationVerifier verifier, string qualifiedMethodName, bool expected = true)
{
var il = verifier.VisualizeIL(qualifiedMethodName);
var isInstrumented = il.Contains(TrackerTypeName);
AssertEx.AreEqual(expected, isInstrumented,
$"Method '{qualifiedMethodName}' should {(expected ? "be" : "not be")} instrumented. Actual IL:{Environment.NewLine}{il}");
}
[Fact]
public void Composition_AllInstrumentations()
{
var source = WithHelpers(@"
class C
{
static void Main(string[] p)
{
string[] a = p = null;
Microsoft.CodeAnalysis.Runtime.Instrumentation.FlushPayload();
}
}
") + CSharpInstrumentationChecker.InstrumentationHelperSource;
var verifier = CompileAndVerify(
source,
options: TestOptions.UnsafeDebugExe,
emitOptions: GetEmitOptions(
InstrumentationKindExtensions.LocalStateTracing,
InstrumentationKind.TestCoverage,
InstrumentationKind.ModuleCancellation,
InstrumentationKind.StackOverflowProbing),
verify: s_verification with
{
ILVerifyMessage = """
[LogMethodEntry]: Return type is ByRef, TypedReference, ArgHandle, or ArgIterator. { Offset = 0x19 }
[LogLambdaEntry]: Return type is ByRef, TypedReference, ArgHandle, or ArgIterator. { Offset = 0x19 }
[LogStateMachineMethodEntry]: Return type is ByRef, TypedReference, ArgHandle, or ArgIterator. { Offset = 0x18 }
[LogStateMachineLambdaEntry]: Return type is ByRef, TypedReference, ArgHandle, or ArgIterator. { Offset = 0x18 }
[Entry]: Return type is ByRef, TypedReference, ArgHandle, or ArgIterator. { Offset = 0xcc }
[MemoryToString]: Unmanaged pointers are not a verifiable type. { Offset = 0x15 }
[LogLocalStore]: Unmanaged pointers are not a verifiable type. { Offset = 0x11 }
[LogLocalStoreUnmanaged]: Unmanaged pointers are not a verifiable type. { Offset = 0x11 }
[LogParameterStore]: Unmanaged pointers are not a verifiable type. { Offset = 0x11 }
[LogParameterStoreUnmanaged]: Unmanaged pointers are not a verifiable type. { Offset = 0x11 }
[CreatePayload]: Expected numeric type on the stack. { Offset = 0x1f, Found = address of '[System.Runtime]System.Guid' }
[CreatePayload]: Expected numeric type on the stack. { Offset = 0x1f, Found = address of '[System.Runtime]System.Guid' }
"""
},
targetFramework: s_targetFramework);
verifier.VerifyMethodBody("C.Main", @"
{
// Code size 144 (0x90)
.maxstack 5
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
string[] V_1, //a
bool[] V_2)
// sequence point: <hidden>
IL_0000: ldsflda ""System.Threading.CancellationToken <PrivateImplementationDetails>.ModuleCancellationToken""
IL_0005: call ""void System.Threading.CancellationToken.ThrowIfCancellationRequested()""
IL_000a: call ""void System.Runtime.CompilerServices.RuntimeHelpers.EnsureSufficientExecutionStack()""
IL_000f: nop
IL_0010: ldtoken ""void C.Main(string[])""
IL_0015: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_001a: stloc.0
.try
{
// sequence point: {
IL_001b: ldsfld ""bool[][] <PrivateImplementationDetails>.PayloadRoot0""
IL_0020: ldtoken ""void C.Main(string[])""
IL_0025: ldelem.ref
IL_0026: stloc.2
IL_0027: ldloc.2
IL_0028: brtrue.s IL_004f
IL_002a: ldsfld ""System.Guid <PrivateImplementationDetails>.MVID""
IL_002f: ldtoken ""void C.Main(string[])""
IL_0034: ldtoken Source Document 0
IL_0039: ldsfld ""bool[][] <PrivateImplementationDetails>.PayloadRoot0""
IL_003e: ldtoken ""void C.Main(string[])""
IL_0043: ldelema ""bool[]""
IL_0048: ldc.i4.3
IL_0049: call ""bool[] Microsoft.CodeAnalysis.Runtime.Instrumentation.CreatePayload(System.Guid, int, int, ref bool[], int)""
IL_004e: stloc.2
IL_004f: ldloc.2
IL_0050: ldc.i4.0
IL_0051: ldc.i4.1
IL_0052: stelem.i1
IL_0053: ldloca.s V_0
IL_0055: ldarg.0
IL_0056: ldc.i4.0
IL_0057: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(object, int)""
IL_005c: nop
// sequence point: string[] a = p = null;
IL_005d: ldloc.2
IL_005e: ldc.i4.1
IL_005f: ldc.i4.1
IL_0060: stelem.i1
IL_0061: ldloca.s V_0
IL_0063: ldloca.s V_0
IL_0065: ldnull
IL_0066: dup
IL_0067: starg.s V_0
IL_0069: ldc.i4.0
IL_006a: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(object, int)""
IL_006f: nop
IL_0070: ldarg.0
IL_0071: dup
IL_0072: stloc.1
IL_0073: ldc.i4.1
IL_0074: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(object, int)""
IL_0079: nop
// sequence point: Microsoft.CodeAnalysis.Runtime.Instrumentation.FlushPayload();
IL_007a: ldloc.2
IL_007b: ldc.i4.2
IL_007c: ldc.i4.1
IL_007d: stelem.i1
IL_007e: call ""void Microsoft.CodeAnalysis.Runtime.Instrumentation.FlushPayload()""
IL_0083: nop
// sequence point: }
IL_0084: leave.s IL_008f
}
finally
{
// sequence point: <hidden>
IL_0086: ldloca.s V_0
IL_0088: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_008d: nop
IL_008e: endfinally
}
// sequence point: }
IL_008f: ret
}
");
}
[Fact]
public void Composition_LocalStateTracing_TestCoverage_LocallySuppressed()
{
var source = WithHelpers(@"
class C
{
static void Main()
{
[System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
void F()
{
int a = 1;
}
F();
Microsoft.CodeAnalysis.Runtime.Instrumentation.FlushPayload();
}
}
") + CSharpInstrumentationChecker.InstrumentationHelperSource;
var verifier = CompileAndVerify(
source,
options: TestOptions.UnsafeDebugExe,
emitOptions: GetEmitOptions(InstrumentationKindExtensions.LocalStateTracing, InstrumentationKind.TestCoverage),
verify: s_verification with
{
ILVerifyMessage = s_verification.ILVerifyMessage + Environment.NewLine + """
[CreatePayload]: Expected numeric type on the stack. { Offset = 0xf, Found = address of '[System.Runtime]System.Guid' }
[CreatePayload]: Expected numeric type on the stack. { Offset = 0xf, Found = address of '[System.Runtime]System.Guid' }
"""
},
targetFramework: s_targetFramework);
verifier.VerifyMethodBody("C.<Main>g__F|0_0", @"
{
// Code size 41 (0x29)
.maxstack 3
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
int V_1) //a
// sequence point: <hidden>
IL_0000: ldtoken ""void C.Main()""
IL_0005: ldtoken ""void C.<Main>g__F|0_0()""
IL_000a: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLambdaEntry(int, int)""
IL_000f: stloc.0
.try
{
// sequence point: {
IL_0010: nop
// sequence point: int a = 1;
IL_0011: ldloca.s V_0
IL_0013: ldc.i4.1
IL_0014: dup
IL_0015: stloc.1
IL_0016: ldc.i4.1
IL_0017: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_001c: nop
// sequence point: }
IL_001d: leave.s IL_0028
}
finally
{
// sequence point: <hidden>
IL_001f: ldloca.s V_0
IL_0021: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0026: nop
IL_0027: endfinally
}
// sequence point: }
IL_0028: ret
}
");
}
[Fact]
public void EmitDifference()
{
var source = WithHelpers(@"
class C
{
static void F()
{
int a = 0xFFFF;
static void LF() { int b = 0xEEEE; }
LF();
}
}
");
var compilation0 = CreateCompilation(source, options: TestOptions.UnsafeDebugDll, targetFramework: s_targetFramework);
var compilation1 = compilation0.WithSource(source);
var f0 = (IMethodSymbol)compilation0.GetMember("C.F").GetPublicSymbol();
var f1 = (IMethodSymbol)compilation1.GetMember("C.F").GetPublicSymbol();
using var md0 = ModuleMetadata.CreateFromImage(compilation0.EmitToArray());
var generation0 = EmitBaseline.CreateInitialBaseline(compilation0, md0, debugInformationProvider: _ => default, localSignatureProvider: _ => default, hasPortableDebugInformation: true);
var diff = compilation1.EmitDifference(
generation0,
edits: ImmutableArray.Create(
new SemanticEdit(f0, f1, ImmutableArray.Create(InstrumentationKindExtensions.LocalStateTracing))));
diff.VerifyIL(@"
{
// Code size 47 (0x2f)
.maxstack 3
IL_0000: ldc.i4 0x3
IL_0005: call 0x06000007
IL_000a: stloc.0
IL_000b: nop
IL_000c: ldloca.s V_0
IL_000e: ldc.i4 0xffff
IL_0013: dup
IL_0014: stloc.1
IL_0015: ldc.i4.1
IL_0016: call 0x06000018
IL_001b: nop
IL_001c: nop
IL_001d: call 0x06000030
IL_0022: nop
IL_0023: leave.s IL_002e
IL_0025: ldloca.s V_0
IL_0027: call 0x0600000B
IL_002c: nop
IL_002d: endfinally
IL_002e: ret
}
{
// Code size 45 (0x2d)
.maxstack 3
IL_0000: ldc.i4 0x3
IL_0005: ldc.i4 0x30
IL_000a: call 0x06000008
IL_000f: stloc.0
IL_0010: nop
IL_0011: ldloca.s V_0
IL_0013: ldc.i4 0xeeee
IL_0018: dup
IL_0019: stloc.1
IL_001a: ldc.i4.1
IL_001b: call 0x06000018
IL_0020: nop
IL_0021: leave.s IL_002c
IL_0023: ldloca.s V_0
IL_0025: call 0x0600000B
IL_002a: nop
IL_002b: endfinally
IL_002c: ret
}
");
}
[Fact]
public void HelpersNotInstrumented()
{
var source = WithHelpers(@"
namespace Microsoft.CodeAnalysis.Runtime
{
partial struct LocalStoreTracker
{
public class NestedHelpers
{
void F(int a) => a = 1;
public class SuperNestedHelpers
{
void F(int a) => a = 1;
}
}
}
}
");
var verifier = CompileAndVerify(source);
foreach (var entry in verifier.TestData.Methods)
{
string actualIL = verifier.VisualizeIL(entry.Value);
Assert.False(actualIL.Contains(TrackerTypeName + ".Log"));
}
}
[Fact]
public void HelpersMissing()
{
var source = @"
using System;
class C
{
DateTime F(int p, ref int q)
{
var a = DateTime.Now;
p = 1;
q = 1;
ref var r = ref a;
ref var s = ref q;
return a;
}
} ";
var compilation = CreateCompilation(source, options: TestOptions.UnsafeDebugDll, targetFramework: s_targetFramework);
compilation.VerifyEmitDiagnostics(s_emitOptions,
// (4,1): error CS0656: Missing compiler required member 'Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry'
// class C
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, @"class C
{
DateTime F(int p, ref int q)
{
var a = DateTime.Now;
p = 1;
q = 1;
ref var r = ref a;
ref var s = ref q;
return a;
}
}").WithArguments("Microsoft.CodeAnalysis.Runtime.LocalStoreTracker", "LogMethodEntry").WithLocation(4, 1),
// (4,1): error CS0656: Missing compiler required member 'Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn'
// class C
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, @"class C
{
DateTime F(int p, ref int q)
{
var a = DateTime.Now;
p = 1;
q = 1;
ref var r = ref a;
ref var s = ref q;
return a;
}
}").WithArguments("Microsoft.CodeAnalysis.Runtime.LocalStoreTracker", "LogReturn").WithLocation(4, 1),
// (7,5): error CS0656: Missing compiler required member 'Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore'
// {
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, @"{
var a = DateTime.Now;
p = 1;
q = 1;
ref var r = ref a;
ref var s = ref q;
return a;
}").WithArguments("Microsoft.CodeAnalysis.Runtime.LocalStoreTracker", "LogParameterStore").WithLocation(7, 5),
// (7,5): error CS0656: Missing compiler required member 'Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore'
// {
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, @"{
var a = DateTime.Now;
p = 1;
q = 1;
ref var r = ref a;
ref var s = ref q;
return a;
}").WithArguments("Microsoft.CodeAnalysis.Runtime.LocalStoreTracker", "LogParameterStore").WithLocation(7, 5),
// (7,5): error CS0656: Missing compiler required member 'Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry'
// {
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, @"{
var a = DateTime.Now;
p = 1;
q = 1;
ref var r = ref a;
ref var s = ref q;
return a;
}").WithArguments("Microsoft.CodeAnalysis.Runtime.LocalStoreTracker", "LogMethodEntry").WithLocation(7, 5),
// (7,5): error CS0656: Missing compiler required member 'Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn'
// {
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, @"{
var a = DateTime.Now;
p = 1;
q = 1;
ref var r = ref a;
ref var s = ref q;
return a;
}").WithArguments("Microsoft.CodeAnalysis.Runtime.LocalStoreTracker", "LogReturn").WithLocation(7, 5),
// (8,13): error CS0656: Missing compiler required member 'Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStoreUnmanaged'
// var a = DateTime.Now;
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "a = DateTime.Now").WithArguments("Microsoft.CodeAnalysis.Runtime.LocalStoreTracker", "LogLocalStoreUnmanaged").WithLocation(8, 13),
// (9,9): error CS0656: Missing compiler required member 'Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore'
// p = 1;
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "p = 1").WithArguments("Microsoft.CodeAnalysis.Runtime.LocalStoreTracker", "LogParameterStore").WithLocation(9, 9),
// (10,9): error CS0656: Missing compiler required member 'Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore'
// q = 1;
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "q = 1").WithArguments("Microsoft.CodeAnalysis.Runtime.LocalStoreTracker", "LogParameterStore").WithLocation(10, 9),
// (12,17): error CS0656: Missing compiler required member 'Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStoreLocalAlias'
// ref var r = ref a;
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "r = ref a").WithArguments("Microsoft.CodeAnalysis.Runtime.LocalStoreTracker", "LogLocalStoreLocalAlias").WithLocation(12, 17),
// (13,17): error CS0656: Missing compiler required member 'Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStoreParameterAlias'
// ref var s = ref q;
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "s = ref q").WithArguments("Microsoft.CodeAnalysis.Runtime.LocalStoreTracker", "LogLocalStoreParameterAlias").WithLocation(13, 17));
}
[Fact]
public void ObjectInitializers_NotInstrumented()
{
var source = WithHelpers(@"
class C
{
int X;
public C F() => new C() { X = 1 };
}
");
var verifier = CompileAndVerify(source);
verifier.VerifyMethodBody("C.F", @"
{
// Code size 37 (0x25)
.maxstack 3
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
C V_1)
// sequence point: <hidden>
IL_0000: ldtoken ""C C.F()""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: new C() { X = 1 }
IL_000b: newobj ""C..ctor()""
IL_0010: dup
IL_0011: ldc.i4.1
IL_0012: stfld ""int C.X""
IL_0017: stloc.1
IL_0018: leave.s IL_0023
}
finally
{
// sequence point: <hidden>
IL_001a: ldloca.s V_0
IL_001c: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0021: nop
IL_0022: endfinally
}
// sequence point: <hidden>
IL_0023: ldloc.1
IL_0024: ret
}
");
}
[Fact]
public void WithExpressions_NotInstrumented()
{
var source = WithHelpers(@"
record class C(int X)
{
public C F() => new C(0) with { X = 1 };
}
");
var verifier = CompileAndVerify(source);
verifier.VerifyMethodBody("C.F", @"
{
// Code size 44 (0x2c)
.maxstack 3
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
C V_1)
// sequence point: <hidden>
IL_0000: ldtoken ""C C.F()""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: new C(0) with { X = 1 }
IL_000b: ldc.i4.0
IL_000c: newobj ""C..ctor(int)""
IL_0011: callvirt ""C C.<Clone>$()""
IL_0016: dup
IL_0017: ldc.i4.1
IL_0018: callvirt ""void C.X.init""
IL_001d: nop
IL_001e: stloc.1
IL_001f: leave.s IL_002a
}
finally
{
// sequence point: <hidden>
IL_0021: ldloca.s V_0
IL_0023: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0028: nop
IL_0029: endfinally
}
// sequence point: <hidden>
IL_002a: ldloc.1
IL_002b: ret
}
");
}
[Fact]
public void MemberAssignment_NotInstrumented()
{
var source = WithHelpers(@"
class C
{
int X;
int P { get => 1; set { X = value; } }
public void F() { X = 1; P = 2; }
}
");
var verifier = CompileAndVerify(source);
verifier.VerifyMethodBody("C.F", @"
{
// Code size 39 (0x27)
.maxstack 2
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0)
// sequence point: <hidden>
IL_0000: ldtoken ""void C.F()""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: {
IL_000b: nop
// sequence point: X = 1;
IL_000c: ldarg.0
IL_000d: ldc.i4.1
IL_000e: stfld ""int C.X""
// sequence point: P = 2;
IL_0013: ldarg.0
IL_0014: ldc.i4.2
IL_0015: call ""void C.P.set""
IL_001a: nop
// sequence point: }
IL_001b: leave.s IL_0026
}
finally
{
// sequence point: <hidden>
IL_001d: ldloca.s V_0
IL_001f: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0024: nop
IL_0025: endfinally
}
// sequence point: }
IL_0026: ret
}
");
}
[Fact]
public void AutoPropertyAccessors_NotInstrumented()
{
var source = WithHelpers(@"
class C
{
int P { get; set; }
}
");
var verifier = CompileAndVerify(source);
AssertNotInstrumented(verifier, "C.P.get");
AssertNotInstrumented(verifier, "C.P.set");
}
[Fact]
public void EventAccessors_NotInstrumented()
{
var source = WithHelpers(@"
using System;
class C
{
event Action E;
}
");
var verifier = CompileAndVerify(source);
AssertNotInstrumented(verifier, "C.E.add");
AssertNotInstrumented(verifier, "C.E.remove");
}
[Fact]
public void SimpleLocalsAndParameters()
{
var source = WithHelpers(@"
class C
{
public void F(int p, int q)
{
int x = 1;
p = x = 2;
for (int i = 0; i < 10; i++)
{
q = x += 2;
}
}
}
");
var verifier = CompileAndVerify(source);
verifier.VerifyMethodBody("C.F", @"
{
// Code size 150 (0x96)
.maxstack 4
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
int V_1, //x
int V_2, //i
int V_3,
bool V_4)
// sequence point: <hidden>
IL_0000: ldtoken ""void C.F(int, int)""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: {
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: ldloca.s V_0
IL_0017: ldarg.2
IL_0018: ldc.i4.1
IL_0019: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(uint, int)""
IL_001e: nop
// sequence point: int x = 1;
IL_001f: ldloca.s V_0
IL_0021: ldc.i4.1
IL_0022: dup
IL_0023: stloc.1
IL_0024: ldc.i4.1
IL_0025: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_002a: nop
// sequence point: p = x = 2;
IL_002b: ldloca.s V_0
IL_002d: ldloca.s V_0
IL_002f: ldc.i4.2
IL_0030: dup
IL_0031: stloc.1
IL_0032: ldc.i4.1
IL_0033: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0038: nop
IL_0039: ldloc.1
IL_003a: dup
IL_003b: starg.s V_1
IL_003d: ldc.i4.0
IL_003e: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(uint, int)""
IL_0043: nop
// sequence point: int i = 0
IL_0044: ldloca.s V_0
IL_0046: ldc.i4.0
IL_0047: dup
IL_0048: stloc.2
IL_0049: ldc.i4.2
IL_004a: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_004f: nop
// sequence point: <hidden>
IL_0050: br.s IL_007f
// sequence point: {
IL_0052: nop
// sequence point: q = x += 2;
IL_0053: ldloca.s V_0
IL_0055: ldloca.s V_0
IL_0057: ldloc.1
IL_0058: ldc.i4.2
IL_0059: add
IL_005a: dup
IL_005b: stloc.1
IL_005c: ldc.i4.1
IL_005d: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0062: nop
IL_0063: ldloc.1
IL_0064: dup
IL_0065: starg.s V_2
IL_0067: ldc.i4.1
IL_0068: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(uint, int)""
IL_006d: nop
// sequence point: }
IL_006e: nop
// sequence point: i++
IL_006f: ldloc.2
IL_0070: stloc.3
IL_0071: ldloca.s V_0
IL_0073: ldloc.3
IL_0074: ldc.i4.1
IL_0075: add
IL_0076: dup
IL_0077: stloc.2
IL_0078: ldc.i4.2
IL_0079: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_007e: nop
// sequence point: i < 10
IL_007f: ldloc.2
IL_0080: ldc.i4.s 10
IL_0082: clt
IL_0084: stloc.s V_4
// sequence point: <hidden>
IL_0086: ldloc.s V_4
IL_0088: brtrue.s IL_0052
// sequence point: }
IL_008a: leave.s IL_0095
}
finally
{
// sequence point: <hidden>
IL_008c: ldloca.s V_0
IL_008e: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0093: nop
IL_0094: endfinally
}
// sequence point: }
IL_0095: ret
}
");
}
[Theory]
[InlineData("I", "object", "c", "C")]
[InlineData("C", "object", "c", "C")]
[InlineData("object", "object", "c", "C")]
[InlineData("string", "string", "\"str\"", "str")]
[InlineData("bool", "bool", "true", "True")]
[InlineData("byte", "byte", "123", "123")]
[InlineData("ushort", "ushort", "15", "15")]
[InlineData("char", "ushort", "'c'", "99")]
[InlineData("int", "uint", "-58", "4294967238")]
[InlineData("uint", "uint", "74", "74")]
[InlineData("long", "ulong", "942254", "942254")]
[InlineData("ulong", "ulong", "1321321321321", "1321321321321")]
[InlineData("float", "float", "1.2345F", "1.2345")]
[InlineData("double", "double", "1.245656", "1.245656")]
[InlineData("decimal", "decimal", "20.34M", "20.34")]
[InlineData("void*", "void*", "(void*)100000", "100000", false)]
[InlineData("byte*", "void*", "(byte*)100000", "100000", false)]
[InlineData("delegate*<int>", "void*", "(delegate*<int>)100000", "100000")]
public void SpecialTypes_NoConv(string typeName, string targetType, string valueSource, string value, bool verificationPasses = true)
{
var source = WithHelpers($$"""
interface I {}
unsafe class C : I
{
static readonly C c = new();
static readonly {{typeName}} s = {{valueSource}};
static void F({{typeName}} p)
{
var x = p = s;
}
static void Main() => F(s);
}
""");
var verifier = CompileAndVerify(
source,
ilVerifyMessage: verificationPasses ? "" : @"
[F]: Unmanaged pointers are not a verifiable type. { Offset = 0xd }
[F]: Unmanaged pointers are not a verifiable type. { Offset = 0x28 }
",
expectedOutput: $@"
Main: Entered
.cctor: Entered
.ctor: Entered
.ctor: Returned
.cctor: Returned
F: Entered
F: P'p'[0] = {value}
F: P'p'[0] = {value}
F: L1 = {value}
F: Returned
Main: Returned
");
verifier.VerifyMethodBody("C.F", $@"
{{
// Code size 62 (0x3e)
.maxstack 4
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
{typeName} V_1) //x
// sequence point: <hidden>
IL_0000: ldtoken ""void C.F({typeName})""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{{
// sequence point: {{
IL_000b: ldloca.s V_0
IL_000d: ldarg.0
IL_000e: ldc.i4.0
IL_000f: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore({targetType}, int)""
IL_0014: nop
// sequence point: var x = p = s;
IL_0015: ldloca.s V_0
IL_0017: ldloca.s V_0
IL_0019: ldsfld ""{typeName} C.s""
IL_001e: dup
IL_001f: starg.s V_0
IL_0021: ldc.i4.0
IL_0022: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore({targetType}, int)""
IL_0027: nop
IL_0028: ldarg.0
IL_0029: dup
IL_002a: stloc.1
IL_002b: ldc.i4.1
IL_002c: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore({targetType}, int)""
IL_0031: nop
// sequence point: }}
IL_0032: leave.s IL_003d
}}
finally
{{
// sequence point: <hidden>
IL_0034: ldloca.s V_0
IL_0036: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_003b: nop
IL_003c: endfinally
}}
// sequence point: }}
IL_003d: ret
}}
");
}
[Theory]
[InlineData("sbyte", "byte", "conv.u1", "-1", "255")]
[InlineData("short", "ushort", "conv.u2", "-1", "65535")]
public void SpecialTypes_ConvU(string typeName, string targetType, string conversion, string valueSource, string value)
{
var source = WithHelpers($$"""
class C
{
static readonly {{typeName}} s = {{valueSource}};
static void F({{typeName}} p)
{
var x = p = s;
}
static void Main() => F(s);
}
""");
var verifier = CompileAndVerify(source, expectedOutput: $@"
Main: Entered
.cctor: Entered
.cctor: Returned
F: Entered
F: P'p'[0] = {value}
F: P'p'[0] = {value}
F: L1 = {value}
F: Returned
Main: Returned
");
verifier.VerifyMethodBody("C.F", $@"
{{
// Code size 65 (0x41)
.maxstack 4
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
{typeName} V_1) //x
// sequence point: <hidden>
IL_0000: ldtoken ""void C.F({typeName})""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{{
// sequence point: {{
IL_000b: ldloca.s V_0
IL_000d: ldarg.0
IL_000e: {conversion}
IL_000f: ldc.i4.0
IL_0010: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore({targetType}, int)""
IL_0015: nop
// sequence point: var x = p = s;
IL_0016: ldloca.s V_0
IL_0018: ldloca.s V_0
IL_001a: ldsfld ""{typeName} C.s""
IL_001f: dup
IL_0020: starg.s V_0
IL_0022: {conversion}
IL_0023: ldc.i4.0
IL_0024: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore({targetType}, int)""
IL_0029: nop
IL_002a: ldarg.0
IL_002b: dup
IL_002c: stloc.1
IL_002d: {conversion}
IL_002e: ldc.i4.1
IL_002f: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore({targetType}, int)""
IL_0034: nop
// sequence point: }}
IL_0035: leave.s IL_0040
}}
finally
{{
// sequence point: <hidden>
IL_0037: ldloca.s V_0
IL_0039: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_003e: nop
IL_003f: endfinally
}}
// sequence point: }}
IL_0040: ret
}}
");
}
[Theory]
[InlineData("byte", "byte")]
[InlineData("ushort", "ushort")]
[InlineData("int", "uint")]
[InlineData("uint", "uint")]
[InlineData("long", "ulong")]
[InlineData("ulong", "ulong")]
public void Enums_NoConv(string typeName, string targetType)
{
var source = WithHelpers($$"""
enum E : {{typeName}}
{
}
class C
{
private static readonly E s;
public void F(E p)
{
var x = p = s;
}
}
""");
var verifier = CompileAndVerify(source);
verifier.VerifyMethodBody("C.F", $@"
{{
// Code size 62 (0x3e)
.maxstack 4
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
E V_1) //x
// sequence point: <hidden>
IL_0000: ldtoken ""void C.F(E)""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{{
// sequence point: {{
IL_000b: ldloca.s V_0
IL_000d: ldarg.1
IL_000e: ldc.i4.0
IL_000f: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore({targetType}, int)""
IL_0014: nop
// sequence point: var x = p = s;
IL_0015: ldloca.s V_0
IL_0017: ldloca.s V_0
IL_0019: ldsfld ""E C.s""
IL_001e: dup
IL_001f: starg.s V_1
IL_0021: ldc.i4.0
IL_0022: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore({targetType}, int)""
IL_0027: nop
IL_0028: ldarg.1
IL_0029: dup
IL_002a: stloc.1
IL_002b: ldc.i4.1
IL_002c: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore({targetType}, int)""
IL_0031: nop
// sequence point: }}
IL_0032: leave.s IL_003d
}}
finally
{{
// sequence point: <hidden>
IL_0034: ldloca.s V_0
IL_0036: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_003b: nop
IL_003c: endfinally
}}
// sequence point: }}
IL_003d: ret
}}
");
}
[Theory]
[InlineData("sbyte", "byte", "conv.u1")]
[InlineData("short", "ushort", "conv.u2")]
public void Enums_ConvU(string typeName, string targetType, string conversion)
{
var source = WithHelpers($$"""
enum E : {{typeName}}
{
}
class C
{
private static readonly E s;
public void F(E p)
{
var x = p = s;
}
}
""");
var verifier = CompileAndVerify(source);
verifier.VerifyMethodBody("C.F", $@"
{{
// Code size 65 (0x41)
.maxstack 4
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
E V_1) //x
// sequence point: <hidden>
IL_0000: ldtoken ""void C.F(E)""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{{
// sequence point: {{
IL_000b: ldloca.s V_0
IL_000d: ldarg.1
IL_000e: {conversion}
IL_000f: ldc.i4.0
IL_0010: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore({targetType}, int)""
IL_0015: nop
// sequence point: var x = p = s;
IL_0016: ldloca.s V_0
IL_0018: ldloca.s V_0
IL_001a: ldsfld ""E C.s""
IL_001f: dup
IL_0020: starg.s V_1
IL_0022: {conversion}
IL_0023: ldc.i4.0
IL_0024: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore({targetType}, int)""
IL_0029: nop
IL_002a: ldarg.1
IL_002b: dup
IL_002c: stloc.1
IL_002d: {conversion}
IL_002e: ldc.i4.1
IL_002f: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore({targetType}, int)""
IL_0034: nop
// sequence point: }}
IL_0035: leave.s IL_0040
}}
finally
{{
// sequence point: <hidden>
IL_0037: ldloca.s V_0
IL_0039: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_003e: nop
IL_003f: endfinally
}}
// sequence point: }}
IL_0040: ret
}}
");
}
#pragma warning disable
private struct S1 { }
private struct S2<T> where T : struct { T t; }
private struct S3 { System.DateTime X; System.Guid Y; decimal Z; unsafe void* P; }
#pragma warning restore
public static IEnumerable<object[]> UnmanagedStruct_TestData
{
get
{
yield return new object[] { "", "nint", "IntPtr", Unsafe.SizeOf<nint>() };
yield return new object[] { "", "nuint", "UIntPtr", Unsafe.SizeOf<nuint>() };
yield return new object[] { "", "System.Int128", "'[System.Runtime]System.Int128'", Unsafe.SizeOf<Int128>() };
yield return new object[] { "", "System.Guid", "'[System.Runtime]System.Guid'", Unsafe.SizeOf<Guid>() };
yield return new object[] { "", "System.ValueTuple<int, bool>", "'[System.Runtime]System.ValueTuple`2<int32,bool>'", Unsafe.SizeOf<(int, bool)>() };
yield return new object[] { "struct S { }", "S", "'S'", Unsafe.SizeOf<S1>() };
yield return new object[] { "struct S<T> where T : struct { T t; }", "S<int>", "'S`1<int32>'", Unsafe.SizeOf<S2<int>>() };
yield return new object[] { "struct S { System.DateTime X; System.Guid Y; decimal Z; unsafe void* P; }", "S", "'S'", Unsafe.SizeOf<S3>() };
yield return new object[] { "", "System.ValueTuple<int?, bool?>", "'[System.Runtime]System.ValueTuple`2<System.Nullable`1<int32>,System.Nullable`1<bool>>'", Unsafe.SizeOf<(int?, bool?)>() };
yield return new object[] { "", "int?", "'[System.Runtime]System.Nullable`1<int32>'", Unsafe.SizeOf<int?>() };
}
}
[Theory]
[MemberData(nameof(UnmanagedStruct_TestData))]
public void UnmanagedStruct(string definition, string typeName, string ilTypeName, int expectedSize)
{
var expectedValue = $"<{string.Join("-", Enumerable.Repeat("00", expectedSize))}>";
var source = WithHelpers($$"""
C.F(default);
{{definition}}
class C
{
static readonly {{typeName}} s;
public static void F({{typeName}} p)
{
var x = p = s;
}
}
""");
var verifier = CompileAndVerify(
source,
ilVerifyMessage: $@"
[F]: Expected numeric type on the stack. {{ Offset = 0xf, Found = address of {ilTypeName} }}
",
expectedOutput: $@"
<Main>$: Entered
<Main>$: P'args'[0] = System.String[]
F: Entered
F: P'p'[0] = {expectedValue}
F: P'p'[0] = {expectedValue}
F: L1 = {expectedValue}
F: Returned
<Main>$: Returned
");
verifier.VerifyMethodBody("C.F", $@"
{{
// Code size 86 (0x56)
.maxstack 5
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
{typeName} V_1) //x
// sequence point: <hidden>
IL_0000: ldtoken ""void C.F({typeName})""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{{
// sequence point: {{
IL_000b: ldloca.s V_0
IL_000d: ldarga.s V_0
IL_000f: conv.u
IL_0010: sizeof ""{typeName}""
IL_0016: ldc.i4.0
IL_0017: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStoreUnmanaged(void*, int, int)""
IL_001c: nop
// sequence point: var x = p = s;
IL_001d: ldloca.s V_0
IL_001f: ldloca.s V_0
IL_0021: ldsfld ""{typeName} C.s""
IL_0026: starg.s V_0
IL_0028: ldarga.s V_0
IL_002a: conv.u
IL_002b: sizeof ""{typeName}""
IL_0031: ldc.i4.0
IL_0032: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStoreUnmanaged(void*, int, int)""
IL_0037: nop
IL_0038: ldarg.0
IL_0039: stloc.1
IL_003a: ldloca.s V_1
IL_003c: conv.u
IL_003d: sizeof ""{typeName}""
IL_0043: ldc.i4.1
IL_0044: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStoreUnmanaged(void*, int, int)""
IL_0049: nop
// sequence point: }}
IL_004a: leave.s IL_0055
}}
finally
{{
// sequence point: <hidden>
IL_004c: ldloca.s V_0
IL_004e: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0053: nop
IL_0054: endfinally
}}
// sequence point: }}
IL_0055: ret
}}
");
}
[Theory]
[InlineData("", "System.ValueTuple<int, string>", "(0, )")]
[InlineData("struct S { string A; }", "S", "S")]
[InlineData("struct S { string A; }", "S?", "")]
public void ManagedStruct(string definition, string typeName, string value)
{
var source = WithHelpers($$"""
C.F(default);
{{definition}}
class C
{
private static readonly {{typeName}} s;
public static void F({{typeName}} p)
{
var x = p = s;
}
}
""");
var verifier = CompileAndVerify(source, expectedOutput: $@"
<Main>$: Entered
<Main>$: P'args'[0] = System.String[]
F: Entered
F: P'p'[0] = {value}
F: P'p'[0] = {value}
F: L1 = {value}
F: Returned
<Main>$: Returned
");
// TODO: why is the stloc+ldloc.a of V_2 emitted? https://github.com/dotnet/roslyn/issues/66810
// IL_0045: stloc.2
// IL_0046: ldloca.s V_2
verifier.VerifyMethodBody("C.F", $@"
{{
// Code size 102 (0x66)
.maxstack 4
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
{typeName} V_1, //x
{typeName} V_2)
// sequence point: <hidden>
IL_0000: ldtoken ""void C.F({typeName})""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{{
// sequence point: {{
IL_000b: ldloca.s V_0
IL_000d: ldarga.s V_0
IL_000f: constrained. ""{typeName}""
IL_0015: callvirt ""string object.ToString()""
IL_001a: ldc.i4.0
IL_001b: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(string, int)""
IL_0020: nop
// sequence point: var x = p = s;
IL_0021: ldloca.s V_0
IL_0023: ldloca.s V_0
IL_0025: ldsfld ""{typeName} C.s""
IL_002a: dup
IL_002b: starg.s V_0
IL_002d: stloc.2
IL_002e: ldloca.s V_2
IL_0030: constrained. ""{typeName}""
IL_0036: callvirt ""string object.ToString()""
IL_003b: ldc.i4.0
IL_003c: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(string, int)""
IL_0041: nop
IL_0042: ldarg.0
IL_0043: dup
IL_0044: stloc.1
IL_0045: stloc.2
IL_0046: ldloca.s V_2
IL_0048: constrained. ""{typeName}""
IL_004e: callvirt ""string object.ToString()""
IL_0053: ldc.i4.1
IL_0054: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(string, int)""
IL_0059: nop
// sequence point: }}
IL_005a: leave.s IL_0065
}}
finally
{{
// sequence point: <hidden>
IL_005c: ldloca.s V_0
IL_005e: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0063: nop
IL_0064: endfinally
}}
// sequence point: }}
IL_0065: ret
}}
");
}
[Fact]
public void RefStructWithRefFieldAndNoToStringOverride()
{
var source = WithHelpers("""
S.F(new S());
ref struct S
{
ref int X;
public static void F(S p)
{
int a = 1;
var x = p = new S();
}
}
""");
var verifier = CompileAndVerify(source, expectedOutput: @"
<Main>$: Entered
<Main>$: P'args'[0] = System.String[]
F: Entered
F: L1 = 1
F: Returned
<Main>$: Returned
");
// writes to x and p are not logged since we can't invoke ToString()
verifier.VerifyMethodBody("S.F", @"
{
// Code size 46 (0x2e)
.maxstack 3
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
int V_1, //a
S V_2) //x
// sequence point: <hidden>
IL_0000: ldtoken ""void S.F(S)""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: {
IL_000b: nop
// sequence point: int a = 1;
IL_000c: ldloca.s V_0
IL_000e: ldc.i4.1
IL_000f: dup
IL_0010: stloc.1
IL_0011: ldc.i4.1
IL_0012: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0017: nop
// sequence point: var x = p = new S();
IL_0018: ldarga.s V_0
IL_001a: initobj ""S""
IL_0020: ldarg.0
IL_0021: stloc.2
// sequence point: }
IL_0022: leave.s IL_002d
}
finally
{
// sequence point: <hidden>
IL_0024: ldloca.s V_0
IL_0026: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_002b: nop
IL_002c: endfinally
}
// sequence point: }
IL_002d: ret
}
");
}
[Fact]
public void RefStructWithRefFieldAndToStringOverride()
{
var source = WithHelpers("""
S.F(new S());
ref struct S
{
ref int X;
public static void F(S p)
{
var x = p = new S();
}
public override string ToString() => "str";
}
""");
var verifier = CompileAndVerify(source, expectedOutput: @"
<Main>$: Entered
<Main>$: P'args'[0] = System.String[]
F: Entered
ToString: Entered
ToString: Returned
F: P'p'[0] = str
ToString: Entered
ToString: Returned
F: P'p'[0] = str
ToString: Entered
ToString: Returned
F: L1 = str
F: Returned
<Main>$: Returned
");
verifier.VerifyMethodBody("S.F", @"
{
// Code size 103 (0x67)
.maxstack 4
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
S V_1, //x
S V_2)
// sequence point: <hidden>
IL_0000: ldtoken ""void S.F(S)""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: {
IL_000b: ldloca.s V_0
IL_000d: ldarga.s V_0
IL_000f: constrained. ""S""
IL_0015: callvirt ""string object.ToString()""
IL_001a: ldc.i4.0
IL_001b: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(string, int)""
IL_0020: nop
// sequence point: var x = p = new S();
IL_0021: ldloca.s V_0
IL_0023: ldloca.s V_0
IL_0025: ldarga.s V_0
IL_0027: initobj ""S""
IL_002d: ldarg.0
IL_002e: stloc.2
IL_002f: ldloca.s V_2
IL_0031: constrained. ""S""
IL_0037: callvirt ""string object.ToString()""
IL_003c: ldc.i4.0
IL_003d: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(string, int)""
IL_0042: nop
IL_0043: ldarg.0
IL_0044: dup
IL_0045: stloc.1
IL_0046: stloc.2
IL_0047: ldloca.s V_2
IL_0049: constrained. ""S""
IL_004f: callvirt ""string object.ToString()""
IL_0054: ldc.i4.1
IL_0055: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(string, int)""
IL_005a: nop
// sequence point: }
IL_005b: leave.s IL_0066
}
finally
{
// sequence point: <hidden>
IL_005d: ldloca.s V_0
IL_005f: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0064: nop
IL_0065: endfinally
}
// sequence point: }
IL_0066: ret
}");
}
[Fact]
public void RefStructTypeParameter()
{
var source = WithHelpers("""
S.F(new S());
ref struct S
{
ref int X;
public static void F<T>(T p)
where T : struct, allows ref struct
{
int a = 1;
var x = p = default(T);
}
}
""");
var verifier = CompileAndVerify(
source,
targetFramework: TargetFramework.Net90,
expectedOutput: @"
<Main>$: Entered
<Main>$: P'args'[0] = System.String[]
F: Entered
F: L1 = 1
F: Returned
<Main>$: Returned
");
// writes to x and p are not logged since we can't invoke ToString()
verifier.VerifyMethodBody("S.F<T>(T)", @"
{
// Code size 46 (0x2e)
.maxstack 3
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
int V_1, //a
T V_2) //x
// sequence point: <hidden>
IL_0000: ldtoken ""void S.F<T>(T)""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: {
IL_000b: nop
// sequence point: int a = 1;
IL_000c: ldloca.s V_0
IL_000e: ldc.i4.1
IL_000f: dup
IL_0010: stloc.1
IL_0011: ldc.i4.1
IL_0012: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0017: nop
// sequence point: var x = p = default(T);
IL_0018: ldarga.s V_0
IL_001a: initobj ""T""
IL_0020: ldarg.0
IL_0021: stloc.2
// sequence point: }
IL_0022: leave.s IL_002d
}
finally
{
// sequence point: <hidden>
IL_0024: ldloca.s V_0
IL_0026: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_002b: nop
IL_002c: endfinally
}
// sequence point: }
IL_002d: ret
}
");
}
[Fact]
public void UnmanagedRefStruct()
{
var source = WithHelpers($$"""
C.F(default);
ref struct S { int X; }
class C
{
public static void F(S p)
{
var x = p = new S();
}
}
""");
var verifier = CompileAndVerify(
source,
expectedOutput: @"
<Main>$: Entered
<Main>$: P'args'[0] = System.String[]
F: Entered
F: P'p'[0] = <00-00-00-00>
F: P'p'[0] = <00-00-00-00>
F: L1 = <00-00-00-00>
F: Returned
<Main>$: Returned
",
ilVerifyMessage: @"
[F]: Expected numeric type on the stack. { Offset = 0xf, Found = address of 'S' }
");
verifier.VerifyMethodBody("C.F", $@"
{{
// Code size 87 (0x57)
.maxstack 5
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
S V_1) //x
// sequence point: <hidden>
IL_0000: ldtoken ""void C.F(S)""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{{
// sequence point: {{
IL_000b: ldloca.s V_0
IL_000d: ldarga.s V_0
IL_000f: conv.u
IL_0010: sizeof ""S""
IL_0016: ldc.i4.0
IL_0017: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStoreUnmanaged(void*, int, int)""
IL_001c: nop
// sequence point: var x = p = new S();
IL_001d: ldloca.s V_0
IL_001f: ldloca.s V_0
IL_0021: ldarga.s V_0
IL_0023: initobj ""S""
IL_0029: ldarga.s V_0
IL_002b: conv.u
IL_002c: sizeof ""S""
IL_0032: ldc.i4.0
IL_0033: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStoreUnmanaged(void*, int, int)""
IL_0038: nop
IL_0039: ldarg.0
IL_003a: stloc.1
IL_003b: ldloca.s V_1
IL_003d: conv.u
IL_003e: sizeof ""S""
IL_0044: ldc.i4.1
IL_0045: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStoreUnmanaged(void*, int, int)""
IL_004a: nop
// sequence point: }}
IL_004b: leave.s IL_0056
}}
finally
{{
// sequence point: <hidden>
IL_004d: ldloca.s V_0
IL_004f: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0054: nop
IL_0055: endfinally
}}
// sequence point: }}
IL_0056: ret
}}");
}
[Fact]
public void Dynamic()
{
var source = WithHelpers(@"
class C
{
static void Main()
{
dynamic x = 1;
x++;
}
}
");
var verifier = CompileAndVerify(source, expectedOutput: @"
Main: Entered
Main: L1 = 1
Main: L1 = 2
Main: Returned
");
verifier.VerifyMethodBody("C.Main", @"
{
// Code size 128 (0x80)
.maxstack 9
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
object V_1, //x
object V_2)
// sequence point: <hidden>
IL_0000: ldtoken ""void C.Main()""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: {
IL_000b: nop
// sequence point: dynamic x = 1;
IL_000c: ldloca.s V_0
IL_000e: ldc.i4.1
IL_000f: box ""int""
IL_0014: dup
IL_0015: stloc.1
IL_0016: ldc.i4.1
IL_0017: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(object, int)""
IL_001c: nop
// sequence point: x++;
IL_001d: ldloc.1
IL_001e: stloc.2
IL_001f: ldloca.s V_0
IL_0021: ldsfld ""System.Runtime.CompilerServices.CallSite<System.Func<System.Runtime.CompilerServices.CallSite, dynamic, dynamic>> C.<>o__0.<>p__0""
IL_0026: brfalse.s IL_002a
IL_0028: br.s IL_0056
IL_002a: ldc.i4.0
IL_002b: ldc.i4.s 54
IL_002d: ldtoken ""C""
IL_0032: call ""System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)""
IL_0037: ldc.i4.1
IL_0038: newarr ""Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo""
IL_003d: dup
IL_003e: ldc.i4.0
IL_003f: ldc.i4.0
IL_0040: ldnull
IL_0041: call ""Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, string)""
IL_0046: stelem.ref
IL_0047: call ""System.Runtime.CompilerServices.CallSiteBinder Microsoft.CSharp.RuntimeBinder.Binder.UnaryOperation(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, System.Linq.Expressions.ExpressionType, System.Type, System.Collections.Generic.IEnumerable<Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo>)""
IL_004c: call ""System.Runtime.CompilerServices.CallSite<System.Func<System.Runtime.CompilerServices.CallSite, dynamic, dynamic>> System.Runtime.CompilerServices.CallSite<System.Func<System.Runtime.CompilerServices.CallSite, dynamic, dynamic>>.Create(System.Runtime.CompilerServices.CallSiteBinder)""
IL_0051: stsfld ""System.Runtime.CompilerServices.CallSite<System.Func<System.Runtime.CompilerServices.CallSite, dynamic, dynamic>> C.<>o__0.<>p__0""
IL_0056: ldsfld ""System.Runtime.CompilerServices.CallSite<System.Func<System.Runtime.CompilerServices.CallSite, dynamic, dynamic>> C.<>o__0.<>p__0""
IL_005b: ldfld ""System.Func<System.Runtime.CompilerServices.CallSite, dynamic, dynamic> System.Runtime.CompilerServices.CallSite<System.Func<System.Runtime.CompilerServices.CallSite, dynamic, dynamic>>.Target""
IL_0060: ldsfld ""System.Runtime.CompilerServices.CallSite<System.Func<System.Runtime.CompilerServices.CallSite, dynamic, dynamic>> C.<>o__0.<>p__0""
IL_0065: ldloc.2
IL_0066: callvirt ""dynamic System.Func<System.Runtime.CompilerServices.CallSite, dynamic, dynamic>.Invoke(System.Runtime.CompilerServices.CallSite, dynamic)""
IL_006b: dup
IL_006c: stloc.1
IL_006d: ldc.i4.1
IL_006e: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(object, int)""
IL_0073: nop
// sequence point: }
IL_0074: leave.s IL_007f
}
finally
{
// sequence point: <hidden>
IL_0076: ldloca.s V_0
IL_0078: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_007d: nop
IL_007e: endfinally
}
// sequence point: }
IL_007f: ret
}
");
}
[Fact]
public void ThisAssignment_NotInstrumented()
{
var source = WithHelpers($$"""
struct S
{
void F()
{
this = new S();
}
}
""");
var verifier = CompileAndVerify(source);
verifier.VerifyMethodBody("S.F", @"
{
// Code size 31 (0x1f)
.maxstack 1
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0)
// sequence point: <hidden>
IL_0000: ldtoken ""void S.F()""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: {
IL_000b: nop
// sequence point: this = new S();
IL_000c: ldarg.0
IL_000d: initobj ""S""
// sequence point: }
IL_0013: leave.s IL_001e
}
finally
{
// sequence point: <hidden>
IL_0015: ldloca.s V_0
IL_0017: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_001c: nop
IL_001d: endfinally
}
// sequence point: }
IL_001e: ret
}
");
}
[Fact]
public void RefAssignments()
{
var source = WithHelpers(@"
class C
{
static void G(int p1, ref int p2, out int p3, ref int p4)
{
int a = 1;
int b = 2;
p3 = 3;
p4 = ref p2;
ref int r1 = ref a;
ref int r2 = ref p1;
ref int r3 = ref p2;
ref int r4 = ref p3;
ref int r5 = ref r1;
if (F(ref r1, ref r2, ref r3, ref r4, out r5))
{
r1 = r2;
}
}
static bool F(ref int a1, ref int a2, ref int a3, ref int a4, out int a5)
{
a5 = 0;
return true;
}
static void Main()
{
int a = 1;
G(1, ref a, out var b, ref a);
}
}
");
var verifier = CompileAndVerify(source, expectedOutput: @"
Main: Entered
Main: L1 = 1
G: Entered
G: P'p1'[0] = 1
G: P'p2'[1] = 1
G: P'p4'[3] = 1
G: L1 = 1
G: L2 = 2
G: P'p3'[2] = 3
G: P'p4'[3] -> P'p2'[1]
G: L3 -> L1
G: L4 -> P'p1'[0]
G: L5 -> P'p2'[1]
G: L6 -> P'p3'[2]
G: L7 -> L3
F: Entered
F: P'a1'[0] = 1
F: P'a2'[1] = 1
F: P'a3'[2] = 1
F: P'a4'[3] = 3
F: P'a5'[4] = 0
F: Returned
G: L3 = 0
G: L4 = 1
G: L5 = 1
G: L6 = 3
G: L7 = 0
G: L3 = 1
G: Returned
Main: L1 = 1
Main: L2 = 3
Main: L1 = 1
Main: Returned
");
// TODO: eliminate https://github.com/dotnet/roslyn/issues/66810
// IL_007b: ldloc.2
// IL_007c: ldind.i4
// IL_007d: pop
verifier.VerifyMethodBody("C.G", @"
{
// Code size 297 (0x129)
.maxstack 5
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
int V_1, //a
int V_2, //b
int& V_3, //r1
int& V_4, //r2
int& V_5, //r3
int& V_6, //r4
int& V_7, //r5
int V_8,
bool V_9)
// sequence point: <hidden>
IL_0000: ldtoken ""void C.G(int, ref int, out int, ref int)""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: {
IL_000b: ldloca.s V_0
IL_000d: ldarg.0
IL_000e: ldc.i4.0
IL_000f: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(uint, int)""
IL_0014: nop
IL_0015: ldloca.s V_0
IL_0017: ldarg.1
IL_0018: ldind.i4
IL_0019: ldc.i4.1
IL_001a: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(uint, int)""
IL_001f: nop
IL_0020: ldloca.s V_0
IL_0022: ldarg.3
IL_0023: ldind.i4
IL_0024: ldc.i4.3
IL_0025: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(uint, int)""
IL_002a: nop
// sequence point: int a = 1;
IL_002b: ldloca.s V_0
IL_002d: ldc.i4.1
IL_002e: dup
IL_002f: stloc.1
IL_0030: ldc.i4.1
IL_0031: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0036: nop
// sequence point: int b = 2;
IL_0037: ldloca.s V_0
IL_0039: ldc.i4.2
IL_003a: dup
IL_003b: stloc.2
IL_003c: ldc.i4.2
IL_003d: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0042: nop
// sequence point: p3 = 3;
IL_0043: ldloca.s V_0
IL_0045: ldarg.2
IL_0046: ldc.i4.3
IL_0047: dup
IL_0048: stloc.s V_8
IL_004a: stind.i4
IL_004b: ldloc.s V_8
IL_004d: ldc.i4.2
IL_004e: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(uint, int)""
IL_0053: nop
// sequence point: p4 = ref p2;
IL_0054: ldloca.s V_0
IL_0056: ldarg.1
IL_0057: starg.s V_3
IL_0059: ldc.i4.1
IL_005a: ldc.i4.3
IL_005b: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStoreParameterAlias(int, int)""
IL_0060: nop
// sequence point: ref int r1 = ref a;
IL_0061: ldloca.s V_0
IL_0063: ldloca.s V_1
IL_0065: stloc.3
IL_0066: ldc.i4.1
IL_0067: ldc.i4.3
IL_0068: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStoreLocalAlias(int, int)""
IL_006d: nop
IL_006e: ldloc.3
IL_006f: ldind.i4
IL_0070: pop
// sequence point: ref int r2 = ref p1;
IL_0071: ldloca.s V_0
IL_0073: ldarga.s V_0
IL_0075: stloc.s V_4
IL_0077: ldc.i4.0
IL_0078: ldc.i4.4
IL_0079: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStoreParameterAlias(int, int)""
IL_007e: nop
IL_007f: ldloc.s V_4
IL_0081: ldind.i4
IL_0082: pop
// sequence point: ref int r3 = ref p2;
IL_0083: ldloca.s V_0
IL_0085: ldarg.1
IL_0086: stloc.s V_5
IL_0088: ldc.i4.1
IL_0089: ldc.i4.5
IL_008a: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStoreParameterAlias(int, int)""
IL_008f: nop
IL_0090: ldloc.s V_5
IL_0092: ldind.i4
IL_0093: pop
// sequence point: ref int r4 = ref p3;
IL_0094: ldloca.s V_0
IL_0096: ldarg.2
IL_0097: stloc.s V_6
IL_0099: ldc.i4.2
IL_009a: ldc.i4.6
IL_009b: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStoreParameterAlias(int, int)""
IL_00a0: nop
IL_00a1: ldloc.s V_6
IL_00a3: ldind.i4
IL_00a4: pop
// sequence point: ref int r5 = ref r1;
IL_00a5: ldloca.s V_0
IL_00a7: ldloc.3
IL_00a8: stloc.s V_7
IL_00aa: ldc.i4.3
IL_00ab: ldc.i4.7
IL_00ac: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStoreLocalAlias(int, int)""
IL_00b1: nop
IL_00b2: ldloc.s V_7
IL_00b4: ldind.i4
IL_00b5: pop
// sequence point: if (F(ref r1, ref r2, ref r3, ref r4, out r5))
IL_00b6: ldloc.3
IL_00b7: ldloc.s V_4
IL_00b9: ldloc.s V_5
IL_00bb: ldloc.s V_6
IL_00bd: ldloc.s V_7
IL_00bf: call ""bool C.F(ref int, ref int, ref int, ref int, out int)""
IL_00c4: ldloca.s V_0
IL_00c6: ldloc.3
IL_00c7: ldind.i4
IL_00c8: ldc.i4.3
IL_00c9: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_00ce: nop
IL_00cf: ldloca.s V_0
IL_00d1: ldloc.s V_4
IL_00d3: ldind.i4
IL_00d4: ldc.i4.4
IL_00d5: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_00da: nop
IL_00db: ldloca.s V_0
IL_00dd: ldloc.s V_5
IL_00df: ldind.i4
IL_00e0: ldc.i4.5
IL_00e1: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_00e6: nop
IL_00e7: ldloca.s V_0
IL_00e9: ldloc.s V_6
IL_00eb: ldind.i4
IL_00ec: ldc.i4.6
IL_00ed: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_00f2: nop
IL_00f3: ldloca.s V_0
IL_00f5: ldloc.s V_7
IL_00f7: ldind.i4
IL_00f8: ldc.i4.7
IL_00f9: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_00fe: nop
IL_00ff: stloc.s V_9
// sequence point: <hidden>
IL_0101: ldloc.s V_9
IL_0103: brfalse.s IL_011d
// sequence point: {
IL_0105: nop
// sequence point: r1 = r2;
IL_0106: ldloca.s V_0
IL_0108: ldloc.3
IL_0109: ldloc.s V_4
IL_010b: ldind.i4
IL_010c: dup
IL_010d: stloc.s V_8
IL_010f: stind.i4
IL_0110: ldloc.s V_8
IL_0112: ldc.i4.3
IL_0113: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0118: nop
IL_0119: ldloc.3
IL_011a: ldind.i4
IL_011b: pop
// sequence point: }
IL_011c: nop
// sequence point: }
IL_011d: leave.s IL_0128
}
finally
{
// sequence point: <hidden>
IL_011f: ldloca.s V_0
IL_0121: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0126: nop
IL_0127: endfinally
}
// sequence point: }
IL_0128: ret
}");
}
/// <summary>
/// We don't currently track local aliases to ref fields.
/// </summary>
[Fact]
public void RefAssignments_RefFields_NotInstrumented()
{
var source = WithHelpers(@"
ref struct S
{
public ref int X;
public ref int Y;
public override string ToString() => ""str"";
}
class C
{
static void Main()
{
int a = 1;
scoped var s = new S();
s.X = ref a; // ignored
s.X = 2; // not recognized as update of a
ref int x = ref s.X; // ignored
x = 3; // not recognized as update of a
s.Y = ref s.X; // ignored
s.Y = 4; // not recognized as update of a
}
}
");
var verifier = CompileAndVerify(source, expectedOutput: @"
Main: Entered
Main: L1 = 1
ToString: Entered
ToString: Returned
Main: L2 = str
Main: L3 = 3
Main: Returned
");
verifier.VerifyMethodBody("C.Main", @"
{
// Code size 136 (0x88)
.maxstack 4
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
int V_1, //a
S V_2, //s
int& V_3, //x
S V_4,
int V_5)
// sequence point: <hidden>
IL_0000: ldtoken ""void C.Main()""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: {
IL_000b: nop
// sequence point: int a = 1;
IL_000c: ldloca.s V_0
IL_000e: ldc.i4.1
IL_000f: dup
IL_0010: stloc.1
IL_0011: ldc.i4.1
IL_0012: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0017: nop
// sequence point: scoped var s = new S();
IL_0018: ldloca.s V_0
IL_001a: ldloca.s V_2
IL_001c: initobj ""S""
IL_0022: ldloc.2
IL_0023: stloc.s V_4
IL_0025: ldloca.s V_4
IL_0027: constrained. ""S""
IL_002d: callvirt ""string object.ToString()""
IL_0032: ldc.i4.2
IL_0033: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(string, int)""
IL_0038: nop
// sequence point: s.X = ref a;
IL_0039: ldloca.s V_2
IL_003b: ldloca.s V_1
IL_003d: stfld ""ref int S.X""
// sequence point: s.X = 2;
IL_0042: ldloc.2
IL_0043: ldfld ""ref int S.X""
IL_0048: ldc.i4.2
IL_0049: stind.i4
// sequence point: ref int x = ref s.X;
IL_004a: ldloca.s V_2
IL_004c: ldfld ""ref int S.X""
IL_0051: stloc.3
// sequence point: x = 3;
IL_0052: ldloca.s V_0
IL_0054: ldloc.3
IL_0055: ldc.i4.3
IL_0056: dup
IL_0057: stloc.s V_5
IL_0059: stind.i4
IL_005a: ldloc.s V_5
IL_005c: ldc.i4.3
IL_005d: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0062: nop
IL_0063: ldloc.3
IL_0064: ldind.i4
IL_0065: pop
// sequence point: s.Y = ref s.X;
IL_0066: ldloca.s V_2
IL_0068: ldloca.s V_2
IL_006a: ldfld ""ref int S.X""
IL_006f: stfld ""ref int S.Y""
// sequence point: s.Y = 4;
IL_0074: ldloc.2
IL_0075: ldfld ""ref int S.Y""
IL_007a: ldc.i4.4
IL_007b: stind.i4
// sequence point: }
IL_007c: leave.s IL_0087
}
finally
{
// sequence point: <hidden>
IL_007e: ldloca.s V_0
IL_0080: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0085: nop
IL_0086: endfinally
}
// sequence point: }
IL_0087: ret
}
");
}
[Fact]
public void RefArguments_Call()
{
var source = WithHelpers(@"
class C
{
static int G(ref int x, ref long y) => 1;
static void Main()
{
int a = 1;
long b = 2;
int c = G(y: ref b, x: ref a) + 1;
}
}
");
var verifier = CompileAndVerify(source, expectedOutput: @"
Main: Entered
Main: L1 = 1
Main: L2 = 2
G: Entered
G: P'x'[0] = 1
G: P'y'[1] = 2
G: Returned
Main: L2 = 2
Main: L1 = 1
Main: L3 = 2
Main: Returned
");
verifier.VerifyMethodBody("C.Main", @"
{
// Code size 91 (0x5b)
.maxstack 5
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
int V_1, //a
long V_2, //b
int V_3) //c
// sequence point: <hidden>
IL_0000: ldtoken ""void C.Main()""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: {
IL_000b: nop
// sequence point: int a = 1;
IL_000c: ldloca.s V_0
IL_000e: ldc.i4.1
IL_000f: dup
IL_0010: stloc.1
IL_0011: ldc.i4.1
IL_0012: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0017: nop
// sequence point: long b = 2;
IL_0018: ldloca.s V_0
IL_001a: ldc.i4.2
IL_001b: conv.i8
IL_001c: dup
IL_001d: stloc.2
IL_001e: ldc.i4.2
IL_001f: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(ulong, int)""
IL_0024: nop
// sequence point: int c = G(y: ref b, x: ref a) + 1;
IL_0025: ldloca.s V_0
IL_0027: ldloca.s V_1
IL_0029: ldloca.s V_2
IL_002b: call ""int C.G(ref int, ref long)""
IL_0030: ldloca.s V_0
IL_0032: ldloc.2
IL_0033: ldc.i4.2
IL_0034: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(ulong, int)""
IL_0039: nop
IL_003a: ldloca.s V_0
IL_003c: ldloc.1
IL_003d: ldc.i4.1
IL_003e: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0043: nop
IL_0044: ldc.i4.1
IL_0045: add
IL_0046: dup
IL_0047: stloc.3
IL_0048: ldc.i4.3
IL_0049: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_004e: nop
// sequence point: }
IL_004f: leave.s IL_005a
}
finally
{
// sequence point: <hidden>
IL_0051: ldloca.s V_0
IL_0053: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0058: nop
IL_0059: endfinally
}
// sequence point: }
IL_005a: ret
}
");
}
[Fact]
public void RefArguments_Call_Void()
{
var source = WithHelpers(@"
class C
{
static void G(ref int x, ref long y)
{
}
static void Main()
{
int a = 1;
long b = 2;
G(y: ref b, x: ref a);
}
}
");
var verifier = CompileAndVerify(source, expectedOutput: @"
Main: Entered
Main: L1 = 1
Main: L2 = 2
G: Entered
G: P'x'[0] = 1
G: P'y'[1] = 2
G: Returned
Main: L2 = 2
Main: L1 = 1
Main: Returned
");
verifier.VerifyMethodBody("C.Main", @"
{
// Code size 79 (0x4f)
.maxstack 3
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
int V_1, //a
long V_2) //b
// sequence point: <hidden>
IL_0000: ldtoken ""void C.Main()""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: {
IL_000b: nop
// sequence point: int a = 1;
IL_000c: ldloca.s V_0
IL_000e: ldc.i4.1
IL_000f: dup
IL_0010: stloc.1
IL_0011: ldc.i4.1
IL_0012: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0017: nop
// sequence point: long b = 2;
IL_0018: ldloca.s V_0
IL_001a: ldc.i4.2
IL_001b: conv.i8
IL_001c: dup
IL_001d: stloc.2
IL_001e: ldc.i4.2
IL_001f: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(ulong, int)""
IL_0024: nop
// sequence point: G(y: ref b, x: ref a);
IL_0025: ldloca.s V_1
IL_0027: ldloca.s V_2
IL_0029: call ""void C.G(ref int, ref long)""
IL_002e: nop
IL_002f: ldloca.s V_0
IL_0031: ldloc.2
IL_0032: ldc.i4.2
IL_0033: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(ulong, int)""
IL_0038: nop
IL_0039: ldloca.s V_0
IL_003b: ldloc.1
IL_003c: ldc.i4.1
IL_003d: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0042: nop
// sequence point: }
IL_0043: leave.s IL_004e
}
finally
{
// sequence point: <hidden>
IL_0045: ldloca.s V_0
IL_0047: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_004c: nop
IL_004d: endfinally
}
// sequence point: }
IL_004e: ret
}
");
}
[Fact]
public void RefArguments_Call_IgnoreNonLocalRefs()
{
var source = WithHelpers(@"
class C
{
int A;
long[] B;
public void G(ref int x, ref long y)
{
}
public void F()
{
var c = new C();
G(y: ref c.B[1], x: ref c.A);
}
}
");
var verifier = CompileAndVerify(source);
verifier.VerifyMethodBody("C.F", @"
{
// Code size 67 (0x43)
.maxstack 3
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
C V_1, //c
long& V_2)
// sequence point: <hidden>
IL_0000: ldtoken ""void C.F()""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: {
IL_000b: nop
// sequence point: var c = new C();
IL_000c: ldloca.s V_0
IL_000e: newobj ""C..ctor()""
IL_0013: dup
IL_0014: stloc.1
IL_0015: ldc.i4.1
IL_0016: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(object, int)""
IL_001b: nop
// sequence point: G(y: ref c.B[1], x: ref c.A);
IL_001c: ldarg.0
IL_001d: ldloc.1
IL_001e: ldfld ""long[] C.B""
IL_0023: ldc.i4.1
IL_0024: ldelema ""long""
IL_0029: stloc.2
IL_002a: ldloc.1
IL_002b: ldflda ""int C.A""
IL_0030: ldloc.2
IL_0031: call ""void C.G(ref int, ref long)""
IL_0036: nop
// sequence point: }
IL_0037: leave.s IL_0042
}
finally
{
// sequence point: <hidden>
IL_0039: ldloca.s V_0
IL_003b: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0040: nop
IL_0041: endfinally
}
// sequence point: }
IL_0042: ret
}
");
}
[Fact]
public void RefArguments_ObjectCreation()
{
var source = WithHelpers(@"
class C
{
public C(ref int x, ref long y)
{
}
public void F()
{
int a = 1;
long b = 2;
var c = new C(y: ref b, x: ref a);
}
}
");
var verifier = CompileAndVerify(source);
verifier.VerifyMethodBody("C.F", @"
{
// Code size 89 (0x59)
.maxstack 5
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
int V_1, //a
long V_2, //b
C V_3) //c
// sequence point: <hidden>
IL_0000: ldtoken ""void C.F()""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: {
IL_000b: nop
// sequence point: int a = 1;
IL_000c: ldloca.s V_0
IL_000e: ldc.i4.1
IL_000f: dup
IL_0010: stloc.1
IL_0011: ldc.i4.1
IL_0012: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0017: nop
// sequence point: long b = 2;
IL_0018: ldloca.s V_0
IL_001a: ldc.i4.2
IL_001b: conv.i8
IL_001c: dup
IL_001d: stloc.2
IL_001e: ldc.i4.2
IL_001f: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(ulong, int)""
IL_0024: nop
// sequence point: var c = new C(y: ref b, x: ref a);
IL_0025: ldloca.s V_0
IL_0027: ldloca.s V_1
IL_0029: ldloca.s V_2
IL_002b: newobj ""C..ctor(ref int, ref long)""
IL_0030: ldloca.s V_0
IL_0032: ldloc.2
IL_0033: ldc.i4.2
IL_0034: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(ulong, int)""
IL_0039: nop
IL_003a: ldloca.s V_0
IL_003c: ldloc.1
IL_003d: ldc.i4.1
IL_003e: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0043: nop
IL_0044: dup
IL_0045: stloc.3
IL_0046: ldc.i4.3
IL_0047: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(object, int)""
IL_004c: nop
// sequence point: }
IL_004d: leave.s IL_0058
}
finally
{
// sequence point: <hidden>
IL_004f: ldloca.s V_0
IL_0051: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0056: nop
IL_0057: endfinally
}
// sequence point: }
IL_0058: ret
}
");
}
[Fact]
public void RefArguments_RefSelf()
{
var source = WithHelpers(@"
static class C
{
static void F()
{
int a = 1;
long b = 2;
a.G(y: ref b, x: ref a);
}
static void G(this ref int self, ref int x, ref long y) { }
}
");
var verifier = CompileAndVerify(source);
verifier.VerifyMethodBody("C.F", @"
{
// Code size 91 (0x5b)
.maxstack 3
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
int V_1, //a
long V_2) //b
// sequence point: <hidden>
IL_0000: ldtoken ""void C.F()""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: {
IL_000b: nop
// sequence point: int a = 1;
IL_000c: ldloca.s V_0
IL_000e: ldc.i4.1
IL_000f: dup
IL_0010: stloc.1
IL_0011: ldc.i4.1
IL_0012: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0017: nop
// sequence point: long b = 2;
IL_0018: ldloca.s V_0
IL_001a: ldc.i4.2
IL_001b: conv.i8
IL_001c: dup
IL_001d: stloc.2
IL_001e: ldc.i4.2
IL_001f: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(ulong, int)""
IL_0024: nop
// sequence point: a.G(y: ref b, x: ref a);
IL_0025: ldloca.s V_1
IL_0027: ldloca.s V_1
IL_0029: ldloca.s V_2
IL_002b: call ""void C.G(ref int, ref int, ref long)""
IL_0030: nop
IL_0031: ldloca.s V_0
IL_0033: ldloc.1
IL_0034: ldc.i4.1
IL_0035: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_003a: nop
IL_003b: ldloca.s V_0
IL_003d: ldloc.2
IL_003e: ldc.i4.2
IL_003f: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(ulong, int)""
IL_0044: nop
IL_0045: ldloca.s V_0
IL_0047: ldloc.1
IL_0048: ldc.i4.1
IL_0049: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_004e: nop
// sequence point: }
IL_004f: leave.s IL_005a
}
finally
{
// sequence point: <hidden>
IL_0051: ldloca.s V_0
IL_0053: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0058: nop
IL_0059: endfinally
}
// sequence point: }
IL_005a: ret
}");
}
[Fact]
public void RefArguments_CollectionInitializer()
{
var source = WithHelpers(@"
using System.Collections;
using System.Collections.Generic;
struct C : IEnumerable<int>
{
public void F()
{
var c = new C() { {1} };
}
public IEnumerator<int> GetEnumerator() => null;
IEnumerator IEnumerable.GetEnumerator() => null;
}
static class Extensions
{
public static void Add(this ref C self, int item) { }
}
");
var verifier = CompileAndVerify(source, ilVerifyMessage: @"
[F]: Expected numeric type on the stack. { Offset = 0x23, Found = address of 'C' }
[Add]: Expected numeric type on the stack. { Offset = 0xe, Found = address of 'C' }
");
verifier.VerifyMethodBody("C.F", @"
{
// Code size 61 (0x3d)
.maxstack 4
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
C V_1, //c
C V_2)
// sequence point: <hidden>
IL_0000: ldtoken ""void C.F()""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: {
IL_000b: nop
// sequence point: var c = new C() { {1} };
IL_000c: ldloca.s V_0
IL_000e: ldloca.s V_2
IL_0010: initobj ""C""
IL_0016: ldloca.s V_2
IL_0018: ldc.i4.1
IL_0019: call ""void Extensions.Add(ref C, int)""
IL_001e: nop
IL_001f: ldloc.2
IL_0020: stloc.1
IL_0021: ldloca.s V_1
IL_0023: conv.u
IL_0024: sizeof ""C""
IL_002a: ldc.i4.1
IL_002b: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStoreUnmanaged(void*, int, int)""
IL_0030: nop
// sequence point: }
IL_0031: leave.s IL_003c
}
finally
{
// sequence point: <hidden>
IL_0033: ldloca.s V_0
IL_0035: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_003a: nop
IL_003b: endfinally
}
// sequence point: }
IL_003c: ret
}
");
}
[Fact]
public void RefArguments_FunctionPointerInvocation()
{
var source = WithHelpers(@"
unsafe class C
{
void F(delegate*<ref int, ref long, void> f)
{
int a = 1;
long b = 2;
f(ref a, ref b);
}
}
");
var verifier = CompileAndVerify(source, ilVerifyMessage: """
[F]: ImportCalli not implemented
""");
verifier.VerifyMethodBody("C.F", @"
{
// Code size 91 (0x5b)
.maxstack 3
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
int V_1, //a
long V_2, //b
delegate*<ref int, ref long, void> V_3)
// sequence point: <hidden>
IL_0000: ldtoken ""void C.F(delegate*<ref int, ref long, void>)""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: {
IL_000b: ldloca.s V_0
IL_000d: ldarg.1
IL_000e: ldc.i4.0
IL_000f: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(void*, int)""
IL_0014: nop
// sequence point: int a = 1;
IL_0015: ldloca.s V_0
IL_0017: ldc.i4.1
IL_0018: dup
IL_0019: stloc.1
IL_001a: ldc.i4.1
IL_001b: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0020: nop
// sequence point: long b = 2;
IL_0021: ldloca.s V_0
IL_0023: ldc.i4.2
IL_0024: conv.i8
IL_0025: dup
IL_0026: stloc.2
IL_0027: ldc.i4.2
IL_0028: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(ulong, int)""
IL_002d: nop
// sequence point: f(ref a, ref b);
IL_002e: ldarg.1
IL_002f: stloc.3
IL_0030: ldloca.s V_1
IL_0032: ldloca.s V_2
IL_0034: ldloc.3
IL_0035: calli ""delegate*<ref int, ref long, void>""
IL_003a: nop
IL_003b: ldloca.s V_0
IL_003d: ldloc.1
IL_003e: ldc.i4.1
IL_003f: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0044: nop
IL_0045: ldloca.s V_0
IL_0047: ldloc.2
IL_0048: ldc.i4.2
IL_0049: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(ulong, int)""
IL_004e: nop
// sequence point: }
IL_004f: leave.s IL_005a
}
finally
{
// sequence point: <hidden>
IL_0051: ldloca.s V_0
IL_0053: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0058: nop
IL_0059: endfinally
}
// sequence point: }
IL_005a: ret
}
");
}
[Fact]
public void Initializers_NoConstructorBody_Static()
{
var source = WithHelpers(@"
C.F(out var _);
class C
{
static int A = F(out var x) + (x = 1);
static int B = F(out var x) + (x = 2);
public static int F(out int a) => a = 1;
}
");
var verifier = CompileAndVerify(source, expectedOutput: @"
<Main>$: Entered
<Main>$: P'args'[0] = System.String[]
F: Entered
F: P'a'[0] = 1
F: Returned
<Main>$: Returned
");
verifier.VerifyMethodBody("C..cctor", @"
{
// Code size 95 (0x5f)
.maxstack 4
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
int V_1, //x
int V_2) //x
// sequence point: <hidden>
IL_0000: ldtoken ""C..cctor()""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: static int A = F(out var x) + (x = 1);
IL_000b: ldloca.s V_1
IL_000d: call ""int C.F(out int)""
IL_0012: ldloca.s V_0
IL_0014: ldloc.1
IL_0015: ldc.i4.1
IL_0016: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_001b: nop
IL_001c: ldloca.s V_0
IL_001e: ldc.i4.1
IL_001f: dup
IL_0020: stloc.1
IL_0021: ldc.i4.1
IL_0022: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0027: nop
IL_0028: ldloc.1
IL_0029: add
IL_002a: stsfld ""int C.A""
// sequence point: static int B = F(out var x) + (x = 2);
IL_002f: ldloca.s V_2
IL_0031: call ""int C.F(out int)""
IL_0036: ldloca.s V_0
IL_0038: ldloc.2
IL_0039: ldc.i4.2
IL_003a: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_003f: nop
IL_0040: ldloca.s V_0
IL_0042: ldc.i4.2
IL_0043: dup
IL_0044: stloc.2
IL_0045: ldc.i4.2
IL_0046: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_004b: nop
IL_004c: ldloc.2
IL_004d: add
IL_004e: stsfld ""int C.B""
IL_0053: leave.s IL_005e
}
finally
{
// sequence point: <hidden>
IL_0055: ldloca.s V_0
IL_0057: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_005c: nop
IL_005d: endfinally
}
// sequence point: <hidden>
IL_005e: ret
}");
}
[Fact]
public void Initializers_Lambda()
{
var source = WithHelpers(@"
using System;
class C
{
static Action A = new Action(() => { int x = 1; });
static void Main() { A(); }
}
");
var expectedOutput = @"
Main: Entered
.cctor: Entered
.cctor: Returned
.cctor: Entered lambda '<.cctor>b__3_0'
<.cctor>b__3_0: L1 = 1
<.cctor>b__3_0: Returned
Main: Returned
";
var verifier = CompileAndVerify(source, expectedOutput: expectedOutput);
verifier.VerifyMethodBody("C..cctor", @"
{
// Code size 44 (0x2c)
.maxstack 2
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0)
// sequence point: <hidden>
IL_0000: ldtoken ""C..cctor()""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: static Action A = new Action(() => { int x = 1; });
IL_000b: ldsfld ""C.<>c C.<>c.<>9""
IL_0010: ldftn ""void C.<>c.<.cctor>b__3_0()""
IL_0016: newobj ""System.Action..ctor(object, nint)""
IL_001b: stsfld ""System.Action C.A""
IL_0020: leave.s IL_002b
}
finally
{
// sequence point: <hidden>
IL_0022: ldloca.s V_0
IL_0024: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0029: nop
IL_002a: endfinally
}
// sequence point: <hidden>
IL_002b: ret
}
");
// TODO: is this sequence point correct? https://github.com/dotnet/roslyn/issues/66811
// sequence point: }
// IL_001d: leave.s IL_0028
verifier.VerifyMethodBody("C.<>c.<.cctor>b__3_0", @"
{
// Code size 41 (0x29)
.maxstack 3
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
int V_1) //x
// sequence point: <hidden>
IL_0000: ldtoken ""C..cctor()""
IL_0005: ldtoken ""void C.<>c.<.cctor>b__3_0()""
IL_000a: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLambdaEntry(int, int)""
IL_000f: stloc.0
.try
{
// sequence point: {
IL_0010: nop
// sequence point: int x = 1;
IL_0011: ldloca.s V_0
IL_0013: ldc.i4.1
IL_0014: dup
IL_0015: stloc.1
IL_0016: ldc.i4.1
IL_0017: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_001c: nop
// sequence point: }
IL_001d: leave.s IL_0028
}
finally
{
// sequence point: <hidden>
IL_001f: ldloca.s V_0
IL_0021: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0026: nop
IL_0027: endfinally
}
// sequence point: }
IL_0028: ret
}
");
}
[Fact]
public void Initializers_NoContructorBody()
{
var source = WithHelpers(@"
var _ = new C();
class C
{
int A = F(out var x) + (x = 2);
public static int F(out int a) => a = 1;
}
");
var verifier = CompileAndVerify(source, expectedOutput: @"
<Main>$: Entered
<Main>$: P'args'[0] = System.String[]
.ctor: Entered
F: Entered
F: P'a'[0] = 1
F: Returned
.ctor: L1 = 1
.ctor: L1 = 2
.ctor: Returned
<Main>$: L1 = C
<Main>$: Returned
");
verifier.VerifyMethodBody("C..ctor", @"
{
// Code size 67 (0x43)
.maxstack 5
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
int V_1) //x
// sequence point: <hidden>
IL_0000: ldtoken ""C..ctor()""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: int A = F(out var x) + (x = 2);
IL_000b: ldarg.0
IL_000c: ldloca.s V_1
IL_000e: call ""int C.F(out int)""
IL_0013: ldloca.s V_0
IL_0015: ldloc.1
IL_0016: ldc.i4.1
IL_0017: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_001c: nop
IL_001d: ldloca.s V_0
IL_001f: ldc.i4.2
IL_0020: dup
IL_0021: stloc.1
IL_0022: ldc.i4.1
IL_0023: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0028: nop
IL_0029: ldloc.1
IL_002a: add
IL_002b: stfld ""int C.A""
IL_0030: ldarg.0
IL_0031: call ""object..ctor()""
IL_0036: nop
IL_0037: leave.s IL_0042
}
finally
{
// sequence point: <hidden>
IL_0039: ldloca.s V_0
IL_003b: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0040: nop
IL_0041: endfinally
}
// sequence point: <hidden>
IL_0042: ret
}");
}
[Fact]
public void Constructors()
{
var source = WithHelpers(@"
class B
{
public B(int p) {}
}
class C : B
{
int A = F(out var x) + (x = 1);
C() : base(F(out var y) + (y = 2))
{
int z = 3;
}
static int F(out int a) => a = 4;
static void Main() => new C();
}
");
var verifier = CompileAndVerify(source, expectedOutput: @"
Main: Entered
.ctor: Entered
F: Entered
F: P'a'[0] = 4
F: Returned
.ctor: L2 = 4
.ctor: L2 = 1
F: Entered
F: P'a'[0] = 4
F: Returned
.ctor: L1 = 4
.ctor: L1 = 2
.ctor: Entered
.ctor: P'p'[0] = 6
.ctor: Returned
.ctor: L3 = 3
.ctor: Returned
Main: Returned
");
verifier.VerifyMethodBody("B..ctor", @"
{
// Code size 41 (0x29)
.maxstack 3
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0)
// sequence point: <hidden>
IL_0000: ldtoken ""B..ctor(int)""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: <hidden>
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
// sequence point: public B(int p)
IL_0015: ldarg.0
IL_0016: call ""object..ctor()""
IL_001b: nop
// sequence point: {
IL_001c: nop
// sequence point: }
IL_001d: leave.s IL_0028
}
finally
{
// sequence point: <hidden>
IL_001f: ldloca.s V_0
IL_0021: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0026: nop
IL_0027: endfinally
}
// sequence point: }
IL_0028: ret
}
");
verifier.VerifyMethodBody("C..ctor", @"
{
// Code size 111 (0x6f)
.maxstack 5
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
int V_1, //y
int V_2, //x
int V_3) //z
// sequence point: <hidden>
IL_0000: ldtoken ""C..ctor()""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: int A = F(out var x) + (x = 1);
IL_000b: ldarg.0
IL_000c: ldloca.s V_2
IL_000e: call ""int C.F(out int)""
IL_0013: ldloca.s V_0
IL_0015: ldloc.2
IL_0016: ldc.i4.2
IL_0017: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_001c: nop
IL_001d: ldloca.s V_0
IL_001f: ldc.i4.1
IL_0020: dup
IL_0021: stloc.2
IL_0022: ldc.i4.2
IL_0023: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0028: nop
IL_0029: ldloc.2
IL_002a: add
IL_002b: stfld ""int C.A""
// sequence point: base(F(out var y) + (y = 2))
IL_0030: ldarg.0
IL_0031: ldloca.s V_1
IL_0033: call ""int C.F(out int)""
IL_0038: ldloca.s V_0
IL_003a: ldloc.1
IL_003b: ldc.i4.1
IL_003c: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0041: nop
IL_0042: ldloca.s V_0
IL_0044: ldc.i4.2
IL_0045: dup
IL_0046: stloc.1
IL_0047: ldc.i4.1
IL_0048: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_004d: nop
IL_004e: ldloc.1
IL_004f: add
IL_0050: call ""B..ctor(int)""
IL_0055: nop
// sequence point: {
IL_0056: nop
// sequence point: int z = 3;
IL_0057: ldloca.s V_0
IL_0059: ldc.i4.3
IL_005a: dup
IL_005b: stloc.3
IL_005c: ldc.i4.3
IL_005d: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0062: nop
// sequence point: }
IL_0063: leave.s IL_006e
}
finally
{
// sequence point: <hidden>
IL_0065: ldloca.s V_0
IL_0067: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_006c: nop
IL_006d: endfinally
}
// sequence point: }
IL_006e: ret
}
");
}
[Fact]
public void EmbeddedStatement()
{
var source = WithHelpers(@"
class C
{
void M()
{
while(true)
G(F(out var x), x = 1);
}
int F(out int a) => a = 1;
void G(int a, int b) {}
}
");
var verifier = CompileAndVerify(source);
verifier.VerifyMethodBody("C.M", @"
{
// Code size 65 (0x41)
.maxstack 5
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
int V_1, //x
bool V_2)
// sequence point: <hidden>
IL_0000: ldtoken ""void C.M()""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: {
IL_000b: nop
// sequence point: <hidden>
IL_000c: br.s IL_0034
// sequence point: G(F(out var x), x = 1);
IL_000e: ldarg.0
IL_000f: ldarg.0
IL_0010: ldloca.s V_1
IL_0012: call ""int C.F(out int)""
IL_0017: ldloca.s V_0
IL_0019: ldloc.1
IL_001a: ldc.i4.1
IL_001b: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0020: nop
IL_0021: ldloca.s V_0
IL_0023: ldc.i4.1
IL_0024: dup
IL_0025: stloc.1
IL_0026: ldc.i4.1
IL_0027: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_002c: nop
IL_002d: ldloc.1
IL_002e: call ""void C.G(int, int)""
IL_0033: nop
// sequence point: while(true)
IL_0034: ldc.i4.1
IL_0035: stloc.2
IL_0036: br.s IL_000e
}
finally
{
// sequence point: <hidden>
IL_0038: ldloca.s V_0
IL_003a: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_003f: nop
IL_0040: endfinally
}
}
");
}
[Fact]
public void Lambdas()
{
var source = WithHelpers(@"
using System;
class C
{
static void Main()
{
int a = 1;
{
int b = 2;
{
int c = 3;
F(() => c += 1);
}
F(() => a += b);
}
}
static void F(Func<int> f) { f(); }
}
");
var verifier = CompileAndVerify(source, expectedOutput: @"
Main: Entered
Main: L'a' = 1
Main: L'b' = 2
Main: L'c' = 3
F: Entered
F: P'f'[0] = System.Func`1[System.Int32]
Main: Entered lambda '<Main>b__1'
<Main>b__1: L'c' = 4
<Main>b__1: Returned
F: Returned
F: Entered
F: P'f'[0] = System.Func`1[System.Int32]
Main: Entered lambda '<Main>b__0'
<Main>b__0: L'a' = 3
<Main>b__0: Returned
F: Returned
Main: Returned
");
verifier.VerifyMethodBody("C.<>c__DisplayClass0_1.<Main>b__0()", @"
{
// Code size 86 (0x56)
.maxstack 4
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
int V_1,
int V_2)
// sequence point: <hidden>
IL_0000: ldtoken ""void C.Main()""
IL_0005: ldtoken ""int C.<>c__DisplayClass0_1.<Main>b__0()""
IL_000a: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLambdaEntry(int, int)""
IL_000f: stloc.0
.try
{
// sequence point: a += b
IL_0010: ldloca.s V_0
IL_0012: ldarg.0
IL_0013: ldfld ""C.<>c__DisplayClass0_0 C.<>c__DisplayClass0_1.CS$<>8__locals1""
IL_0018: ldarg.0
IL_0019: ldfld ""C.<>c__DisplayClass0_0 C.<>c__DisplayClass0_1.CS$<>8__locals1""
IL_001e: ldfld ""int C.<>c__DisplayClass0_0.a""
IL_0023: ldarg.0
IL_0024: ldfld ""int C.<>c__DisplayClass0_1.b""
IL_0029: add
IL_002a: dup
IL_002b: stloc.1
IL_002c: stfld ""int C.<>c__DisplayClass0_0.a""
IL_0031: ldloc.1
IL_0032: ldtoken ""int C.<>c__DisplayClass0_0.a""
IL_0037: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_003c: nop
IL_003d: ldarg.0
IL_003e: ldfld ""C.<>c__DisplayClass0_0 C.<>c__DisplayClass0_1.CS$<>8__locals1""
IL_0043: ldfld ""int C.<>c__DisplayClass0_0.a""
IL_0048: stloc.2
IL_0049: leave.s IL_0054
}
finally
{
// sequence point: <hidden>
IL_004b: ldloca.s V_0
IL_004d: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0052: nop
IL_0053: endfinally
}
// sequence point: <hidden>
IL_0054: ldloc.2
IL_0055: ret
}
");
verifier.VerifyMethodBody("C.<>c__DisplayClass0_2.<Main>b__1()", @"
{
// Code size 66 (0x42)
.maxstack 4
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
int V_1,
int V_2)
// sequence point: <hidden>
IL_0000: ldtoken ""void C.Main()""
IL_0005: ldtoken ""int C.<>c__DisplayClass0_2.<Main>b__1()""
IL_000a: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLambdaEntry(int, int)""
IL_000f: stloc.0
.try
{
// sequence point: c += 1
IL_0010: ldloca.s V_0
IL_0012: ldarg.0
IL_0013: ldarg.0
IL_0014: ldfld ""int C.<>c__DisplayClass0_2.c""
IL_0019: ldc.i4.1
IL_001a: add
IL_001b: dup
IL_001c: stloc.1
IL_001d: stfld ""int C.<>c__DisplayClass0_2.c""
IL_0022: ldloc.1
IL_0023: ldtoken ""int C.<>c__DisplayClass0_2.c""
IL_0028: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_002d: nop
IL_002e: ldarg.0
IL_002f: ldfld ""int C.<>c__DisplayClass0_2.c""
IL_0034: stloc.2
IL_0035: leave.s IL_0040
}
finally
{
// sequence point: <hidden>
IL_0037: ldloca.s V_0
IL_0039: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_003e: nop
IL_003f: endfinally
}
// sequence point: <hidden>
IL_0040: ldloc.2
IL_0041: ret
}
");
verifier.VerifyMethodBody("C.Main", @"
{
// Code size 183 (0xb7)
.maxstack 4
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
C.<>c__DisplayClass0_0 V_1, //CS$<>8__locals0
int V_2,
C.<>c__DisplayClass0_1 V_3, //CS$<>8__locals1
C.<>c__DisplayClass0_2 V_4) //CS$<>8__locals2
// sequence point: <hidden>
IL_0000: ldtoken ""void C.Main()""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: <hidden>
IL_000b: newobj ""C.<>c__DisplayClass0_0..ctor()""
IL_0010: stloc.1
// sequence point: {
IL_0011: nop
// sequence point: int a = 1;
IL_0012: ldloca.s V_0
IL_0014: ldloc.1
IL_0015: ldc.i4.1
IL_0016: dup
IL_0017: stloc.2
IL_0018: stfld ""int C.<>c__DisplayClass0_0.a""
IL_001d: ldloc.2
IL_001e: ldtoken ""int C.<>c__DisplayClass0_0.a""
IL_0023: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0028: nop
IL_0029: ldloc.1
IL_002a: ldfld ""int C.<>c__DisplayClass0_0.a""
IL_002f: pop
// sequence point: <hidden>
IL_0030: newobj ""C.<>c__DisplayClass0_1..ctor()""
IL_0035: stloc.3
IL_0036: ldloc.3
IL_0037: ldloc.1
IL_0038: stfld ""C.<>c__DisplayClass0_0 C.<>c__DisplayClass0_1.CS$<>8__locals1""
// sequence point: {
IL_003d: nop
// sequence point: int b = 2;
IL_003e: ldloca.s V_0
IL_0040: ldloc.3
IL_0041: ldc.i4.2
IL_0042: dup
IL_0043: stloc.2
IL_0044: stfld ""int C.<>c__DisplayClass0_1.b""
IL_0049: ldloc.2
IL_004a: ldtoken ""int C.<>c__DisplayClass0_1.b""
IL_004f: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0054: nop
IL_0055: ldloc.3
IL_0056: ldfld ""int C.<>c__DisplayClass0_1.b""
IL_005b: pop
// sequence point: <hidden>
IL_005c: newobj ""C.<>c__DisplayClass0_2..ctor()""
IL_0061: stloc.s V_4
// sequence point: {
IL_0063: nop
// sequence point: int c = 3;
IL_0064: ldloca.s V_0
IL_0066: ldloc.s V_4
IL_0068: ldc.i4.3
IL_0069: dup
IL_006a: stloc.2
IL_006b: stfld ""int C.<>c__DisplayClass0_2.c""
IL_0070: ldloc.2
IL_0071: ldtoken ""int C.<>c__DisplayClass0_2.c""
IL_0076: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_007b: nop
IL_007c: ldloc.s V_4
IL_007e: ldfld ""int C.<>c__DisplayClass0_2.c""
IL_0083: pop
// sequence point: F(() => c += 1);
IL_0084: ldloc.s V_4
IL_0086: ldftn ""int C.<>c__DisplayClass0_2.<Main>b__1()""
IL_008c: newobj ""System.Func<int>..ctor(object, nint)""
IL_0091: call ""void C.F(System.Func<int>)""
IL_0096: nop
// sequence point: }
IL_0097: nop
// sequence point: F(() => a += b);
IL_0098: ldloc.3
IL_0099: ldftn ""int C.<>c__DisplayClass0_1.<Main>b__0()""
IL_009f: newobj ""System.Func<int>..ctor(object, nint)""
IL_00a4: call ""void C.F(System.Func<int>)""
IL_00a9: nop
// sequence point: }
IL_00aa: nop
// sequence point: }
IL_00ab: leave.s IL_00b6
}
finally
{
// sequence point: <hidden>
IL_00ad: ldloca.s V_0
IL_00af: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_00b4: nop
IL_00b5: endfinally
}
// sequence point: }
IL_00b6: ret
}
");
}
[Fact]
public void Lambdas_Parameters()
{
var source = WithHelpers(@"
using System;
class C
{
static void Main()
{
F(b =>
{
int a = 1;
b = 2;
ref int c = ref a;
ref int d = ref b;
});
}
static void F(Action<int> f) => f(3);
}
");
var verifier = CompileAndVerify(source, expectedOutput: @"
Main: Entered
F: Entered
F: P'f'[0] = System.Action`1[System.Int32]
Main: Entered lambda '<Main>b__0_0'
<Main>b__0_0: P'b'[0] = 3
<Main>b__0_0: L1 = 1
<Main>b__0_0: P'b'[0] = 2
<Main>b__0_0: L2 -> L1
<Main>b__0_0: L3 -> P'b'[0]
<Main>b__0_0: Returned
F: Returned
Main: Returned
");
verifier.VerifyMethodBody("C.<>c.<Main>b__0_0", @"
{
// Code size 95 (0x5f)
.maxstack 3
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
int V_1, //a
int& V_2, //c
int& V_3) //d
// sequence point: <hidden>
IL_0000: ldtoken ""void C.Main()""
IL_0005: ldtoken ""void C.<>c.<Main>b__0_0(int)""
IL_000a: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLambdaEntry(int, int)""
IL_000f: stloc.0
.try
{
// sequence point: {
IL_0010: ldloca.s V_0
IL_0012: ldarg.1
IL_0013: ldc.i4.0
IL_0014: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(uint, int)""
IL_0019: nop
// sequence point: int a = 1;
IL_001a: ldloca.s V_0
IL_001c: ldc.i4.1
IL_001d: dup
IL_001e: stloc.1
IL_001f: ldc.i4.1
IL_0020: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0025: nop
// sequence point: b = 2;
IL_0026: ldloca.s V_0
IL_0028: ldc.i4.2
IL_0029: dup
IL_002a: starg.s V_1
IL_002c: ldc.i4.0
IL_002d: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(uint, int)""
IL_0032: nop
// sequence point: ref int c = ref a;
IL_0033: ldloca.s V_0
IL_0035: ldloca.s V_1
IL_0037: stloc.2
IL_0038: ldc.i4.1
IL_0039: ldc.i4.2
IL_003a: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStoreLocalAlias(int, int)""
IL_003f: nop
IL_0040: ldloc.2
IL_0041: ldind.i4
IL_0042: pop
// sequence point: ref int d = ref b;
IL_0043: ldloca.s V_0
IL_0045: ldarga.s V_1
IL_0047: stloc.3
IL_0048: ldc.i4.0
IL_0049: ldc.i4.3
IL_004a: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStoreParameterAlias(int, int)""
IL_004f: nop
IL_0050: ldloc.3
IL_0051: ldind.i4
IL_0052: pop
// sequence point: }
IL_0053: leave.s IL_005e
}
finally
{
// sequence point: <hidden>
IL_0055: ldloca.s V_0
IL_0057: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_005c: nop
IL_005d: endfinally
}
// sequence point: }
IL_005e: ret
}
");
}
[Fact]
public void Lambdas_LiftedParameters()
{
var source = WithHelpers(@"
using System;
class C
{
static void Main()
{
G(1);
}
static void G(int a)
{
F(b =>
{
a = b;
return F(c => ++b);
});
}
static int F(Func<int, int> f) => f(2);
}
");
var verifier = CompileAndVerify(source, expectedOutput: @"
Main: Entered
G: Entered
G: P'a'[0] = 1
F: Entered
F: P'f'[0] = System.Func`2[System.Int32,System.Int32]
G: Entered lambda '<G>b__0'
<G>b__0: P'b'[0] = 2
<G>b__0: P'a' = 2
F: Entered
F: P'f'[0] = System.Func`2[System.Int32,System.Int32]
G: Entered lambda '<G>b__1'
<G>b__1: P'c'[0] = 2
<G>b__1: P'b' = 3
<G>b__1: Returned
F: Returned
<G>b__0: Returned
F: Returned
G: Returned
Main: Returned
");
verifier.VerifyMethodBody("C.G", @"
{
// Code size 69 (0x45)
.maxstack 3
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
C.<>c__DisplayClass1_0 V_1) //CS$<>8__locals0
// sequence point: <hidden>
IL_0000: ldtoken ""void C.G(int)""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: <hidden>
IL_000b: newobj ""C.<>c__DisplayClass1_0..ctor()""
IL_0010: stloc.1
IL_0011: ldloc.1
IL_0012: ldarg.0
IL_0013: stfld ""int C.<>c__DisplayClass1_0.a""
// sequence point: {
IL_0018: ldloca.s V_0
IL_001a: ldloc.1
IL_001b: ldfld ""int C.<>c__DisplayClass1_0.a""
IL_0020: ldc.i4.0
IL_0021: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(uint, int)""
IL_0026: nop
// sequence point: F(b => ... });
IL_0027: ldloc.1
IL_0028: ldftn ""int C.<>c__DisplayClass1_0.<G>b__0(int)""
IL_002e: newobj ""System.Func<int, int>..ctor(object, nint)""
IL_0033: call ""int C.F(System.Func<int, int>)""
IL_0038: pop
// sequence point: }
IL_0039: leave.s IL_0044
}
finally
{
// sequence point: <hidden>
IL_003b: ldloca.s V_0
IL_003d: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0042: nop
IL_0043: endfinally
}
// sequence point: }
IL_0044: ret
}
");
verifier.VerifyMethodBody("C.<>c__DisplayClass1_0.<G>b__0", @"
{
// Code size 110 (0x6e)
.maxstack 4
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
C.<>c__DisplayClass1_1 V_1, //CS$<>8__locals0
int V_2,
int V_3)
// sequence point: <hidden>
IL_0000: ldtoken ""void C.G(int)""
IL_0005: ldtoken ""int C.<>c__DisplayClass1_0.<G>b__0(int)""
IL_000a: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLambdaEntry(int, int)""
IL_000f: stloc.0
.try
{
// sequence point: <hidden>
IL_0010: newobj ""C.<>c__DisplayClass1_1..ctor()""
IL_0015: stloc.1
IL_0016: ldloc.1
IL_0017: ldarg.1
IL_0018: stfld ""int C.<>c__DisplayClass1_1.b""
// sequence point: {
IL_001d: ldloca.s V_0
IL_001f: ldloc.1
IL_0020: ldfld ""int C.<>c__DisplayClass1_1.b""
IL_0025: ldc.i4.0
IL_0026: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(uint, int)""
IL_002b: nop
// sequence point: a = b;
IL_002c: ldloca.s V_0
IL_002e: ldarg.0
IL_002f: ldloc.1
IL_0030: ldfld ""int C.<>c__DisplayClass1_1.b""
IL_0035: dup
IL_0036: stloc.2
IL_0037: stfld ""int C.<>c__DisplayClass1_0.a""
IL_003c: ldloc.2
IL_003d: ldtoken ""int C.<>c__DisplayClass1_0.a""
IL_0042: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(uint, int)""
IL_0047: nop
IL_0048: ldarg.0
IL_0049: ldfld ""int C.<>c__DisplayClass1_0.a""
IL_004e: pop
// sequence point: return F(c => ++b);
IL_004f: ldloc.1
IL_0050: ldftn ""int C.<>c__DisplayClass1_1.<G>b__1(int)""
IL_0056: newobj ""System.Func<int, int>..ctor(object, nint)""
IL_005b: call ""int C.F(System.Func<int, int>)""
IL_0060: stloc.3
IL_0061: leave.s IL_006c
}
finally
{
// sequence point: <hidden>
IL_0063: ldloca.s V_0
IL_0065: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_006a: nop
IL_006b: endfinally
}
// sequence point: }
IL_006c: ldloc.3
IL_006d: ret
}");
verifier.VerifyMethodBody("C.<>c__DisplayClass1_1.<G>b__1", @"
{
// Code size 80 (0x50)
.maxstack 4
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
int V_1,
int V_2,
int V_3)
// sequence point: <hidden>
IL_0000: ldtoken ""void C.G(int)""
IL_0005: ldtoken ""int C.<>c__DisplayClass1_1.<G>b__1(int)""
IL_000a: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLambdaEntry(int, int)""
IL_000f: stloc.0
.try
{
IL_0010: ldloca.s V_0
IL_0012: ldarg.1
IL_0013: ldc.i4.0
IL_0014: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(uint, int)""
IL_0019: nop
// sequence point: ++b
IL_001a: ldarg.0
IL_001b: ldfld ""int C.<>c__DisplayClass1_1.b""
IL_0020: ldc.i4.1
IL_0021: add
IL_0022: stloc.1
IL_0023: ldloca.s V_0
IL_0025: ldarg.0
IL_0026: ldloc.1
IL_0027: dup
IL_0028: stloc.2
IL_0029: stfld ""int C.<>c__DisplayClass1_1.b""
IL_002e: ldloc.2
IL_002f: ldtoken ""int C.<>c__DisplayClass1_1.b""
IL_0034: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(uint, int)""
IL_0039: nop
IL_003a: ldarg.0
IL_003b: ldfld ""int C.<>c__DisplayClass1_1.b""
IL_0040: pop
IL_0041: ldloc.1
IL_0042: stloc.3
IL_0043: leave.s IL_004e
}
finally
{
// sequence point: <hidden>
IL_0045: ldloca.s V_0
IL_0047: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_004c: nop
IL_004d: endfinally
}
// sequence point: <hidden>
IL_004e: ldloc.3
IL_004f: ret
}
");
}
[Fact]
public void StateMachine_Async()
{
var source = WithHelpers(@"
using System.Threading.Tasks;
class C
{
static async Task M(int p)
{
int a = p;
F(out var b);
await Task.FromResult(1);
int c = b;
}
static int F(out int a) => a = 1;
static async Task Main() => await M(2);
}
");
var verifier = CompileAndVerify(source, expectedOutput: @"
Main: Entered state machine #1
M: Entered state machine #2
M: P'p'[0] = 2
M: L'a' = 2
F: Entered
F: P'a'[0] = 1
F: Returned
M: L'b' = 1
M: L'c' = 1
M: Returned
Main: Returned
");
verifier.VerifyMethodBody("C.M", @"
{
// Code size 67 (0x43)
.maxstack 2
.locals init (C.<M>d__0 V_0)
IL_0000: newobj ""C.<M>d__0..ctor()""
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: call ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Create()""
IL_000c: stfld ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<M>d__0.<>t__builder""
IL_0011: ldloc.0
IL_0012: ldarg.0
IL_0013: stfld ""int C.<M>d__0.p""
IL_0018: ldloc.0
IL_0019: ldc.i4.m1
IL_001a: stfld ""int C.<M>d__0.<>1__state""
IL_001f: ldloc.0
IL_0020: call ""ulong Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.GetNewStateMachineInstanceId()""
IL_0025: stfld ""ulong C.<M>d__0.<>I""
IL_002a: ldloc.0
IL_002b: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<M>d__0.<>t__builder""
IL_0030: ldloca.s V_0
IL_0032: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start<C.<M>d__0>(ref C.<M>d__0)""
IL_0037: ldloc.0
IL_0038: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<M>d__0.<>t__builder""
IL_003d: call ""System.Threading.Tasks.Task System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Task.get""
IL_0042: ret
}
");
verifier.VerifyMethodBody("C.<M>d__0..ctor", @"
{
// Code size 8 (0x8)
.maxstack 1
IL_0000: ldarg.0
IL_0001: call ""object..ctor()""
IL_0006: nop
IL_0007: ret
}
");
// TODO: remove unnecessary IL: https://github.com/dotnet/roslyn/issues/66810
// IL_0038: ldarg.0
// IL_0039: ldfld ""int C.<Main>d__0.<a>5__1""
// IL_003e: pop
verifier.VerifyMethodBody("C.<M>d__0.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", @"
{
// Code size 304 (0x130)
.maxstack 4
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
int V_1,
int V_2,
System.Runtime.CompilerServices.TaskAwaiter<int> V_3,
C.<M>d__0 V_4,
System.Exception V_5)
// sequence point: <hidden>
IL_0000: ldtoken ""System.Threading.Tasks.Task C.M(int)""
IL_0005: ldarg.0
IL_0006: ldfld ""ulong C.<M>d__0.<>I""
IL_000b: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogStateMachineMethodEntry(int, ulong)""
IL_0010: stloc.0
.try
{
// sequence point: <hidden>
IL_0011: ldarg.0
IL_0012: ldfld ""int C.<M>d__0.<>1__state""
IL_0017: stloc.1
.try
{
// sequence point: <hidden>
IL_0018: ldloc.1
IL_0019: brfalse.s IL_001d
IL_001b: br.s IL_0022
IL_001d: br IL_00ad
// sequence point: {
IL_0022: ldloca.s V_0
IL_0024: ldarg.0
IL_0025: ldfld ""int C.<M>d__0.p""
IL_002a: ldc.i4.0
IL_002b: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(uint, int)""
IL_0030: nop
// sequence point: int a = p;
IL_0031: ldloca.s V_0
IL_0033: ldarg.0
IL_0034: ldarg.0
IL_0035: ldfld ""int C.<M>d__0.p""
IL_003a: dup
IL_003b: stloc.2
IL_003c: stfld ""int C.<M>d__0.<a>5__1""
IL_0041: ldloc.2
IL_0042: ldtoken ""int C.<M>d__0.<a>5__1""
IL_0047: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_004c: nop
IL_004d: ldarg.0
IL_004e: ldfld ""int C.<M>d__0.<a>5__1""
IL_0053: pop
// sequence point: F(out var b);
IL_0054: ldarg.0
IL_0055: ldflda ""int C.<M>d__0.<b>5__2""
IL_005a: call ""int C.F(out int)""
IL_005f: pop
IL_0060: ldloca.s V_0
IL_0062: ldarg.0
IL_0063: ldfld ""int C.<M>d__0.<b>5__2""
IL_0068: ldtoken ""int C.<M>d__0.<b>5__2""
IL_006d: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0072: nop
// sequence point: await Task.FromResult(1);
IL_0073: ldc.i4.1
IL_0074: call ""System.Threading.Tasks.Task<int> System.Threading.Tasks.Task.FromResult<int>(int)""
IL_0079: callvirt ""System.Runtime.CompilerServices.TaskAwaiter<int> System.Threading.Tasks.Task<int>.GetAwaiter()""
IL_007e: stloc.3
// sequence point: <hidden>
IL_007f: ldloca.s V_3
IL_0081: call ""bool System.Runtime.CompilerServices.TaskAwaiter<int>.IsCompleted.get""
IL_0086: brtrue.s IL_00c9
IL_0088: ldarg.0
IL_0089: ldc.i4.0
IL_008a: dup
IL_008b: stloc.1
IL_008c: stfld ""int C.<M>d__0.<>1__state""
// async: yield
IL_0091: ldarg.0
IL_0092: ldloc.3
IL_0093: stfld ""System.Runtime.CompilerServices.TaskAwaiter<int> C.<M>d__0.<>u__1""
IL_0098: ldarg.0
IL_0099: stloc.s V_4
IL_009b: ldarg.0
IL_009c: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<M>d__0.<>t__builder""
IL_00a1: ldloca.s V_3
IL_00a3: ldloca.s V_4
IL_00a5: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter<int>, C.<M>d__0>(ref System.Runtime.CompilerServices.TaskAwaiter<int>, ref C.<M>d__0)""
IL_00aa: nop
IL_00ab: leave.s IL_0124
// async: resume
IL_00ad: ldarg.0
IL_00ae: ldfld ""System.Runtime.CompilerServices.TaskAwaiter<int> C.<M>d__0.<>u__1""
IL_00b3: stloc.3
IL_00b4: ldarg.0
IL_00b5: ldflda ""System.Runtime.CompilerServices.TaskAwaiter<int> C.<M>d__0.<>u__1""
IL_00ba: initobj ""System.Runtime.CompilerServices.TaskAwaiter<int>""
IL_00c0: ldarg.0
IL_00c1: ldc.i4.m1
IL_00c2: dup
IL_00c3: stloc.1
IL_00c4: stfld ""int C.<M>d__0.<>1__state""
IL_00c9: ldloca.s V_3
IL_00cb: call ""int System.Runtime.CompilerServices.TaskAwaiter<int>.GetResult()""
IL_00d0: pop
// sequence point: int c = b;
IL_00d1: ldloca.s V_0
IL_00d3: ldarg.0
IL_00d4: ldarg.0
IL_00d5: ldfld ""int C.<M>d__0.<b>5__2""
IL_00da: dup
IL_00db: stloc.2
IL_00dc: stfld ""int C.<M>d__0.<c>5__3""
IL_00e1: ldloc.2
IL_00e2: ldtoken ""int C.<M>d__0.<c>5__3""
IL_00e7: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_00ec: nop
IL_00ed: ldarg.0
IL_00ee: ldfld ""int C.<M>d__0.<c>5__3""
IL_00f3: pop
IL_00f4: leave.s IL_0110
}
catch System.Exception
{
// sequence point: <hidden>
IL_00f6: stloc.s V_5
IL_00f8: ldarg.0
IL_00f9: ldc.i4.s -2
IL_00fb: stfld ""int C.<M>d__0.<>1__state""
IL_0100: ldarg.0
IL_0101: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<M>d__0.<>t__builder""
IL_0106: ldloc.s V_5
IL_0108: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)""
IL_010d: nop
IL_010e: leave.s IL_0124
}
// sequence point: }
IL_0110: ldarg.0
IL_0111: ldc.i4.s -2
IL_0113: stfld ""int C.<M>d__0.<>1__state""
// sequence point: <hidden>
IL_0118: ldarg.0
IL_0119: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<M>d__0.<>t__builder""
IL_011e: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()""
IL_0123: nop
IL_0124: leave.s IL_012f
}
finally
{
// sequence point: <hidden>
IL_0126: ldloca.s V_0
IL_0128: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_012d: nop
IL_012e: endfinally
}
// sequence point: <hidden>
IL_012f: ret
}
");
}
[Fact]
public void StateMachine_Iterator()
{
var source = WithHelpers(@"
using System.Linq;
using System.Collections.Generic;
class C
{
static IEnumerable<int> M(int p)
{
int a = p;
F(out var b);
yield return 1;
int c = b;
}
static int F(out int a) => a = 1;
static void Main() => M(2).ToArray();
}
");
var verifier = CompileAndVerify(source, expectedOutput: @"
Main: Entered
M: Entered state machine #1
M: P'p'[0] = 2
M: L'a' = 2
F: Entered
F: P'a'[0] = 1
F: Returned
M: L'b' = 1
M: Returned
M: Entered state machine #1
M: L'c' = 1
M: Returned
Main: Returned
");
verifier.VerifyMethodBody("C.M", @"
{
// Code size 15 (0xf)
.maxstack 3
IL_0000: ldc.i4.s -2
IL_0002: newobj ""C.<M>d__0..ctor(int)""
IL_0007: dup
IL_0008: ldarg.0
IL_0009: stfld ""int C.<M>d__0.<>3__p""
IL_000e: ret
}
");
verifier.VerifyMethodBody("C.<M>d__0..ctor", @"
{
// Code size 37 (0x25)
.maxstack 2
IL_0000: ldarg.0
IL_0001: call ""object..ctor()""
IL_0006: nop
IL_0007: ldarg.0
IL_0008: ldarg.1
IL_0009: stfld ""int C.<M>d__0.<>1__state""
IL_000e: ldarg.0
IL_000f: call ""int System.Environment.CurrentManagedThreadId.get""
IL_0014: stfld ""int C.<M>d__0.<>l__initialThreadId""
IL_0019: ldarg.0
IL_001a: call ""ulong Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.GetNewStateMachineInstanceId()""
IL_001f: stfld ""ulong C.<M>d__0.<>I""
IL_0024: ret
}
");
// TODO: remove unnecessary IL:
// ldarg.0
// ldfld ""int C.<M>d__0.<a>5__1""
// pop
verifier.VerifyMethodBody("C.<M>d__0.System.Collections.IEnumerator.MoveNext()", @"
{
// Code size 209 (0xd1)
.maxstack 4
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
int V_1,
bool V_2,
int V_3)
// sequence point: <hidden>
IL_0000: ldtoken ""System.Collections.Generic.IEnumerable<int> C.M(int)""
IL_0005: ldarg.0
IL_0006: ldfld ""ulong C.<M>d__0.<>I""
IL_000b: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogStateMachineMethodEntry(int, ulong)""
IL_0010: stloc.0
.try
{
// sequence point: <hidden>
IL_0011: ldarg.0
IL_0012: ldfld ""int C.<M>d__0.<>1__state""
IL_0017: stloc.1
IL_0018: ldloc.1
IL_0019: brfalse.s IL_0023
IL_001b: br.s IL_001d
IL_001d: ldloc.1
IL_001e: ldc.i4.1
IL_001f: beq.s IL_0025
IL_0021: br.s IL_0027
IL_0023: br.s IL_002e
IL_0025: br.s IL_0098
IL_0027: ldc.i4.0
IL_0028: stloc.2
IL_0029: leave IL_00cf
IL_002e: ldarg.0
IL_002f: ldc.i4.m1
IL_0030: stfld ""int C.<M>d__0.<>1__state""
// sequence point: {
IL_0035: ldloca.s V_0
IL_0037: ldarg.0
IL_0038: ldfld ""int C.<M>d__0.p""
IL_003d: ldc.i4.0
IL_003e: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(uint, int)""
IL_0043: nop
// sequence point: int a = p;
IL_0044: ldloca.s V_0
IL_0046: ldarg.0
IL_0047: ldarg.0
IL_0048: ldfld ""int C.<M>d__0.p""
IL_004d: dup
IL_004e: stloc.3
IL_004f: stfld ""int C.<M>d__0.<a>5__1""
IL_0054: ldloc.3
IL_0055: ldtoken ""int C.<M>d__0.<a>5__1""
IL_005a: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_005f: nop
IL_0060: ldarg.0
IL_0061: ldfld ""int C.<M>d__0.<a>5__1""
IL_0066: pop
// sequence point: F(out var b);
IL_0067: ldarg.0
IL_0068: ldflda ""int C.<M>d__0.<b>5__2""
IL_006d: call ""int C.F(out int)""
IL_0072: pop
IL_0073: ldloca.s V_0
IL_0075: ldarg.0
IL_0076: ldfld ""int C.<M>d__0.<b>5__2""
IL_007b: ldtoken ""int C.<M>d__0.<b>5__2""
IL_0080: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0085: nop
// sequence point: yield return 1;
IL_0086: ldarg.0
IL_0087: ldc.i4.1
IL_0088: stfld ""int C.<M>d__0.<>2__current""
IL_008d: ldarg.0
IL_008e: ldc.i4.1
IL_008f: stfld ""int C.<M>d__0.<>1__state""
IL_0094: ldc.i4.1
IL_0095: stloc.2
IL_0096: leave.s IL_00cf
// sequence point: <hidden>
IL_0098: ldarg.0
IL_0099: ldc.i4.m1
IL_009a: stfld ""int C.<M>d__0.<>1__state""
// sequence point: int c = b;
IL_009f: ldloca.s V_0
IL_00a1: ldarg.0
IL_00a2: ldarg.0
IL_00a3: ldfld ""int C.<M>d__0.<b>5__2""
IL_00a8: dup
IL_00a9: stloc.3
IL_00aa: stfld ""int C.<M>d__0.<c>5__3""
IL_00af: ldloc.3
IL_00b0: ldtoken ""int C.<M>d__0.<c>5__3""
IL_00b5: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_00ba: nop
IL_00bb: ldarg.0
IL_00bc: ldfld ""int C.<M>d__0.<c>5__3""
IL_00c1: pop
// sequence point: }
IL_00c2: ldc.i4.0
IL_00c3: stloc.2
IL_00c4: leave.s IL_00cf
}
finally
{
// sequence point: <hidden>
IL_00c6: ldloca.s V_0
IL_00c8: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_00cd: nop
IL_00ce: endfinally
}
// sequence point: <hidden>
IL_00cf: ldloc.2
IL_00d0: ret
}");
}
[Fact]
public void StateMachine_AsyncIterator()
{
var source = WithHelpers(@"
using System.Collections.Generic;
using System.Threading.Tasks;
class C
{
static async IAsyncEnumerable<int> M(int p)
{
await Task.FromResult(1);
int a = p;
F(out var b);
yield return 1;
int c = b;
}
static int F(out int a) => a = 1;
static async Task Main()
{
await foreach (var n in M(2)) {}
}
}
");
var verifier = CompileAndVerify(source, expectedOutput: @"
Main: Entered state machine #1
M: Entered state machine #2
M: P'p'[0] = 2
M: L'a' = 2
F: Entered
F: P'a'[0] = 1
F: Returned
M: L'b' = 1
M: Returned
Main: L'n' = 1
M: Entered state machine #2
M: L'c' = 1
M: Returned
Main: Returned
");
verifier.VerifyMethodBody("C.M", @"
{
// Code size 15 (0xf)
.maxstack 3
IL_0000: ldc.i4.s -2
IL_0002: newobj ""C.<M>d__0..ctor(int)""
IL_0007: dup
IL_0008: ldarg.0
IL_0009: stfld ""int C.<M>d__0.<>3__p""
IL_000e: ret
}
");
// TODO: remove unnecessary IL: https://github.com/dotnet/roslyn/issues/66810
// IL_0038: ldarg.0
// IL_0039: ldfld ""int C.<M>d__0.<a>5__1""
// IL_003e: pop
verifier.VerifyMethodBody("C.<M>d__0.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", @"
{
// Code size 457 (0x1c9)
.maxstack 4
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
int V_1,
System.Runtime.CompilerServices.TaskAwaiter<int> V_2,
C.<M>d__0 V_3,
int V_4,
System.Exception V_5)
// sequence point: <hidden>
IL_0000: ldtoken ""System.Collections.Generic.IAsyncEnumerable<int> C.M(int)""
IL_0005: ldarg.0
IL_0006: ldfld ""ulong C.<M>d__0.<>I""
IL_000b: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogStateMachineMethodEntry(int, ulong)""
IL_0010: stloc.0
.try
{
// sequence point: <hidden>
IL_0011: ldarg.0
IL_0012: ldfld ""int C.<M>d__0.<>1__state""
IL_0017: stloc.1
.try
{
// sequence point: <hidden>
IL_0018: ldloc.1
IL_0019: ldc.i4.s -4
IL_001b: sub
IL_001c: switch (
IL_0037,
IL_003c,
IL_0040,
IL_0040,
IL_003e)
IL_0035: br.s IL_0040
IL_0037: br IL_011f
IL_003c: br.s IL_0040
IL_003e: br.s IL_00a1
IL_0040: ldarg.0
IL_0041: ldfld ""bool C.<M>d__0.<>w__disposeMode""
IL_0046: brfalse.s IL_004d
IL_0048: leave IL_0186
IL_004d: ldarg.0
IL_004e: ldc.i4.m1
IL_004f: dup
IL_0050: stloc.1
IL_0051: stfld ""int C.<M>d__0.<>1__state""
// sequence point: {
IL_0056: ldloca.s V_0
IL_0058: ldarg.0
IL_0059: ldfld ""int C.<M>d__0.p""
IL_005e: ldc.i4.0
IL_005f: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(uint, int)""
IL_0064: nop
// sequence point: await Task.FromResult(1);
IL_0065: ldc.i4.1
IL_0066: call ""System.Threading.Tasks.Task<int> System.Threading.Tasks.Task.FromResult<int>(int)""
IL_006b: callvirt ""System.Runtime.CompilerServices.TaskAwaiter<int> System.Threading.Tasks.Task<int>.GetAwaiter()""
IL_0070: stloc.2
// sequence point: <hidden>
IL_0071: ldloca.s V_2
IL_0073: call ""bool System.Runtime.CompilerServices.TaskAwaiter<int>.IsCompleted.get""
IL_0078: brtrue.s IL_00bd
IL_007a: ldarg.0
IL_007b: ldc.i4.0
IL_007c: dup
IL_007d: stloc.1
IL_007e: stfld ""int C.<M>d__0.<>1__state""
// async: yield
IL_0083: ldarg.0
IL_0084: ldloc.2
IL_0085: stfld ""System.Runtime.CompilerServices.TaskAwaiter<int> C.<M>d__0.<>u__1""
IL_008a: ldarg.0
IL_008b: stloc.3
IL_008c: ldarg.0
IL_008d: ldflda ""System.Runtime.CompilerServices.AsyncIteratorMethodBuilder C.<M>d__0.<>t__builder""
IL_0092: ldloca.s V_2
IL_0094: ldloca.s V_3
IL_0096: call ""void System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter<int>, C.<M>d__0>(ref System.Runtime.CompilerServices.TaskAwaiter<int>, ref C.<M>d__0)""
IL_009b: nop
IL_009c: leave IL_01bd
// async: resume
IL_00a1: ldarg.0
IL_00a2: ldfld ""System.Runtime.CompilerServices.TaskAwaiter<int> C.<M>d__0.<>u__1""
IL_00a7: stloc.2
IL_00a8: ldarg.0
IL_00a9: ldflda ""System.Runtime.CompilerServices.TaskAwaiter<int> C.<M>d__0.<>u__1""
IL_00ae: initobj ""System.Runtime.CompilerServices.TaskAwaiter<int>""
IL_00b4: ldarg.0
IL_00b5: ldc.i4.m1
IL_00b6: dup
IL_00b7: stloc.1
IL_00b8: stfld ""int C.<M>d__0.<>1__state""
IL_00bd: ldloca.s V_2
IL_00bf: call ""int System.Runtime.CompilerServices.TaskAwaiter<int>.GetResult()""
IL_00c4: pop
// sequence point: int a = p;
IL_00c5: ldloca.s V_0
IL_00c7: ldarg.0
IL_00c8: ldarg.0
IL_00c9: ldfld ""int C.<M>d__0.p""
IL_00ce: dup
IL_00cf: stloc.s V_4
IL_00d1: stfld ""int C.<M>d__0.<a>5__1""
IL_00d6: ldloc.s V_4
IL_00d8: ldtoken ""int C.<M>d__0.<a>5__1""
IL_00dd: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_00e2: nop
IL_00e3: ldarg.0
IL_00e4: ldfld ""int C.<M>d__0.<a>5__1""
IL_00e9: pop
// sequence point: F(out var b);
IL_00ea: ldarg.0
IL_00eb: ldflda ""int C.<M>d__0.<b>5__2""
IL_00f0: call ""int C.F(out int)""
IL_00f5: pop
IL_00f6: ldloca.s V_0
IL_00f8: ldarg.0
IL_00f9: ldfld ""int C.<M>d__0.<b>5__2""
IL_00fe: ldtoken ""int C.<M>d__0.<b>5__2""
IL_0103: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0108: nop
// sequence point: yield return 1;
IL_0109: ldarg.0
IL_010a: ldc.i4.1
IL_010b: stfld ""int C.<M>d__0.<>2__current""
IL_0110: ldarg.0
IL_0111: ldc.i4.s -4
IL_0113: dup
IL_0114: stloc.1
IL_0115: stfld ""int C.<M>d__0.<>1__state""
IL_011a: leave IL_01b0
// sequence point: <hidden>
IL_011f: ldarg.0
IL_0120: ldc.i4.m1
IL_0121: dup
IL_0122: stloc.1
IL_0123: stfld ""int C.<M>d__0.<>1__state""
IL_0128: ldarg.0
IL_0129: ldfld ""bool C.<M>d__0.<>w__disposeMode""
IL_012e: brfalse.s IL_0132
IL_0130: leave.s IL_0186
// sequence point: int c = b;
IL_0132: ldloca.s V_0
IL_0134: ldarg.0
IL_0135: ldarg.0
IL_0136: ldfld ""int C.<M>d__0.<b>5__2""
IL_013b: dup
IL_013c: stloc.s V_4
IL_013e: stfld ""int C.<M>d__0.<c>5__3""
IL_0143: ldloc.s V_4
IL_0145: ldtoken ""int C.<M>d__0.<c>5__3""
IL_014a: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_014f: nop
IL_0150: ldarg.0
IL_0151: ldfld ""int C.<M>d__0.<c>5__3""
IL_0156: pop
IL_0157: leave.s IL_0186
}
catch System.Exception
{
// sequence point: <hidden>
IL_0159: stloc.s V_5
IL_015b: ldarg.0
IL_015c: ldc.i4.s -2
IL_015e: stfld ""int C.<M>d__0.<>1__state""
IL_0163: ldarg.0
IL_0164: ldc.i4.0
IL_0165: stfld ""int C.<M>d__0.<>2__current""
IL_016a: ldarg.0
IL_016b: ldflda ""System.Runtime.CompilerServices.AsyncIteratorMethodBuilder C.<M>d__0.<>t__builder""
IL_0170: call ""void System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Complete()""
IL_0175: nop
IL_0176: ldarg.0
IL_0177: ldflda ""System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore<bool> C.<M>d__0.<>v__promiseOfValueOrEnd""
IL_017c: ldloc.s V_5
IL_017e: call ""void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore<bool>.SetException(System.Exception)""
IL_0183: nop
IL_0184: leave.s IL_01bd
}
// sequence point: }
IL_0186: ldarg.0
IL_0187: ldc.i4.s -2
IL_0189: stfld ""int C.<M>d__0.<>1__state""
// sequence point: <hidden>
IL_018e: ldarg.0
IL_018f: ldc.i4.0
IL_0190: stfld ""int C.<M>d__0.<>2__current""
IL_0195: ldarg.0
IL_0196: ldflda ""System.Runtime.CompilerServices.AsyncIteratorMethodBuilder C.<M>d__0.<>t__builder""
IL_019b: call ""void System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Complete()""
IL_01a0: nop
IL_01a1: ldarg.0
IL_01a2: ldflda ""System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore<bool> C.<M>d__0.<>v__promiseOfValueOrEnd""
IL_01a7: ldc.i4.0
IL_01a8: call ""void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore<bool>.SetResult(bool)""
IL_01ad: nop
IL_01ae: leave.s IL_01c8
IL_01b0: ldarg.0
IL_01b1: ldflda ""System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore<bool> C.<M>d__0.<>v__promiseOfValueOrEnd""
IL_01b6: ldc.i4.1
IL_01b7: call ""void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore<bool>.SetResult(bool)""
IL_01bc: nop
IL_01bd: leave.s IL_01c8
}
finally
{
// sequence point: <hidden>
IL_01bf: ldloca.s V_0
IL_01c1: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_01c6: nop
IL_01c7: endfinally
}
// sequence point: <hidden>
IL_01c8: ret
}");
}
[Fact]
public void StateMachine_Lambda_Async()
{
var source = WithHelpers(@"
using System;
using System.Threading.Tasks;
class C
{
static async Task Main()
{
await F(async p =>
{
int a = p;
return await Task.FromResult(1);
});
}
static async Task F(Func<int, Task<int>> t) => await t(2);
}
");
var verifier = CompileAndVerify(source, expectedOutput: @"
Main: Entered state machine #1
F: Entered state machine #2
F: P't'[0] = System.Func`2[System.Int32,System.Threading.Tasks.Task`1[System.Int32]]
Main: Entered lambda '<Main>b__0_0' state machine #3
<Main>b__0_0: P'p'[0] = 2
<Main>b__0_0: L'a' = 2
<Main>b__0_0: Returned
F: Returned
Main: Returned
");
verifier.VerifyMethodBody("C.<>c.<<Main>b__0_0>d.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", @"
{
// Code size 256 (0x100)
.maxstack 4
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
int V_1,
int V_2,
int V_3,
System.Runtime.CompilerServices.TaskAwaiter<int> V_4,
C.<>c.<<Main>b__0_0>d V_5,
System.Exception V_6)
// sequence point: <hidden>
IL_0000: ldtoken ""System.Threading.Tasks.Task C.Main()""
IL_0005: ldtoken ""System.Threading.Tasks.Task<int> C.<>c.<Main>b__0_0(int)""
IL_000a: ldarg.0
IL_000b: ldfld ""ulong C.<>c.<<Main>b__0_0>d.<>I""
IL_0010: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogStateMachineLambdaEntry(int, int, ulong)""
IL_0015: stloc.0
.try
{
// sequence point: <hidden>
IL_0016: ldarg.0
IL_0017: ldfld ""int C.<>c.<<Main>b__0_0>d.<>1__state""
IL_001c: stloc.1
.try
{
// sequence point: <hidden>
IL_001d: ldloc.1
IL_001e: brfalse.s IL_0022
IL_0020: br.s IL_0024
IL_0022: br.s IL_0092
// sequence point: {
IL_0024: ldloca.s V_0
IL_0026: ldarg.0
IL_0027: ldfld ""int C.<>c.<<Main>b__0_0>d.p""
IL_002c: ldc.i4.0
IL_002d: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(uint, int)""
IL_0032: nop
// sequence point: int a = p;
IL_0033: ldloca.s V_0
IL_0035: ldarg.0
IL_0036: ldarg.0
IL_0037: ldfld ""int C.<>c.<<Main>b__0_0>d.p""
IL_003c: dup
IL_003d: stloc.3
IL_003e: stfld ""int C.<>c.<<Main>b__0_0>d.<a>5__1""
IL_0043: ldloc.3
IL_0044: ldtoken ""int C.<>c.<<Main>b__0_0>d.<a>5__1""
IL_0049: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_004e: nop
IL_004f: ldarg.0
IL_0050: ldfld ""int C.<>c.<<Main>b__0_0>d.<a>5__1""
IL_0055: pop
// sequence point: return await Task.FromResult(1);
IL_0056: ldc.i4.1
IL_0057: call ""System.Threading.Tasks.Task<int> System.Threading.Tasks.Task.FromResult<int>(int)""
IL_005c: callvirt ""System.Runtime.CompilerServices.TaskAwaiter<int> System.Threading.Tasks.Task<int>.GetAwaiter()""
IL_0061: stloc.s V_4
// sequence point: <hidden>
IL_0063: ldloca.s V_4
IL_0065: call ""bool System.Runtime.CompilerServices.TaskAwaiter<int>.IsCompleted.get""
IL_006a: brtrue.s IL_00af
IL_006c: ldarg.0
IL_006d: ldc.i4.0
IL_006e: dup
IL_006f: stloc.1
IL_0070: stfld ""int C.<>c.<<Main>b__0_0>d.<>1__state""
// async: yield
IL_0075: ldarg.0
IL_0076: ldloc.s V_4
IL_0078: stfld ""System.Runtime.CompilerServices.TaskAwaiter<int> C.<>c.<<Main>b__0_0>d.<>u__1""
IL_007d: ldarg.0
IL_007e: stloc.s V_5
IL_0080: ldarg.0
IL_0081: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> C.<>c.<<Main>b__0_0>d.<>t__builder""
IL_0086: ldloca.s V_4
IL_0088: ldloca.s V_5
IL_008a: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter<int>, C.<>c.<<Main>b__0_0>d>(ref System.Runtime.CompilerServices.TaskAwaiter<int>, ref C.<>c.<<Main>b__0_0>d)""
IL_008f: nop
IL_0090: leave.s IL_00f4
// async: resume
IL_0092: ldarg.0
IL_0093: ldfld ""System.Runtime.CompilerServices.TaskAwaiter<int> C.<>c.<<Main>b__0_0>d.<>u__1""
IL_0098: stloc.s V_4
IL_009a: ldarg.0
IL_009b: ldflda ""System.Runtime.CompilerServices.TaskAwaiter<int> C.<>c.<<Main>b__0_0>d.<>u__1""
IL_00a0: initobj ""System.Runtime.CompilerServices.TaskAwaiter<int>""
IL_00a6: ldarg.0
IL_00a7: ldc.i4.m1
IL_00a8: dup
IL_00a9: stloc.1
IL_00aa: stfld ""int C.<>c.<<Main>b__0_0>d.<>1__state""
IL_00af: ldarg.0
IL_00b0: ldloca.s V_4
IL_00b2: call ""int System.Runtime.CompilerServices.TaskAwaiter<int>.GetResult()""
IL_00b7: stfld ""int C.<>c.<<Main>b__0_0>d.<>s__2""
IL_00bc: ldarg.0
IL_00bd: ldfld ""int C.<>c.<<Main>b__0_0>d.<>s__2""
IL_00c2: stloc.2
IL_00c3: leave.s IL_00df
}
catch System.Exception
{
// sequence point: <hidden>
IL_00c5: stloc.s V_6
IL_00c7: ldarg.0
IL_00c8: ldc.i4.s -2
IL_00ca: stfld ""int C.<>c.<<Main>b__0_0>d.<>1__state""
IL_00cf: ldarg.0
IL_00d0: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> C.<>c.<<Main>b__0_0>d.<>t__builder""
IL_00d5: ldloc.s V_6
IL_00d7: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.SetException(System.Exception)""
IL_00dc: nop
IL_00dd: leave.s IL_00f4
}
// sequence point: }
IL_00df: ldarg.0
IL_00e0: ldc.i4.s -2
IL_00e2: stfld ""int C.<>c.<<Main>b__0_0>d.<>1__state""
// sequence point: <hidden>
IL_00e7: ldarg.0
IL_00e8: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> C.<>c.<<Main>b__0_0>d.<>t__builder""
IL_00ed: ldloc.2
IL_00ee: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.SetResult(int)""
IL_00f3: nop
IL_00f4: leave.s IL_00ff
}
finally
{
// sequence point: <hidden>
IL_00f6: ldloca.s V_0
IL_00f8: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_00fd: nop
IL_00fe: endfinally
}
// sequence point: <hidden>
IL_00ff: ret
}
");
}
[Fact]
public void StateMachine_LocalFunction_Iterator()
{
var source = WithHelpers(@"
using System;
using System.Collections.Generic;
class C
{
static void Main()
{
IEnumerable<int> f(int p)
{
int a = p;
yield return 1;
}
foreach (var n in M(f))
{
}
}
static IEnumerable<int> M(Func<int, IEnumerable<int>> p)
=> p(2);
}
");
var verifier = CompileAndVerify(source, expectedOutput: @"
Main: Entered
M: Entered
M: P'p'[0] = System.Func`2[System.Int32,System.Collections.Generic.IEnumerable`1[System.Int32]]
M: Returned
Main: Entered lambda '<Main>g__f|0_0' state machine #1
<Main>g__f|0_0: P'p'[0] = 2
<Main>g__f|0_0: L'a' = 2
<Main>g__f|0_0: Returned
Main: L2 = 1
Main: Entered lambda '<Main>g__f|0_0' state machine #1
<Main>g__f|0_0: Returned
Main: Returned
");
verifier.VerifyMethodBody("C.<<Main>g__f|0_0>d.System.Collections.IEnumerator.MoveNext()", @"
{
// Code size 145 (0x91)
.maxstack 4
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
int V_1,
bool V_2,
int V_3)
// sequence point: <hidden>
IL_0000: ldtoken ""void C.Main()""
IL_0005: ldtoken ""System.Collections.Generic.IEnumerable<int> C.<Main>g__f|0_0(int)""
IL_000a: ldarg.0
IL_000b: ldfld ""ulong C.<<Main>g__f|0_0>d.<>I""
IL_0010: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogStateMachineLambdaEntry(int, int, ulong)""
IL_0015: stloc.0
.try
{
// sequence point: <hidden>
IL_0016: ldarg.0
IL_0017: ldfld ""int C.<<Main>g__f|0_0>d.<>1__state""
IL_001c: stloc.1
IL_001d: ldloc.1
IL_001e: brfalse.s IL_0028
IL_0020: br.s IL_0022
IL_0022: ldloc.1
IL_0023: ldc.i4.1
IL_0024: beq.s IL_002a
IL_0026: br.s IL_002c
IL_0028: br.s IL_0030
IL_002a: br.s IL_007b
IL_002c: ldc.i4.0
IL_002d: stloc.2
IL_002e: leave.s IL_008f
IL_0030: ldarg.0
IL_0031: ldc.i4.m1
IL_0032: stfld ""int C.<<Main>g__f|0_0>d.<>1__state""
// sequence point: {
IL_0037: ldloca.s V_0
IL_0039: ldarg.0
IL_003a: ldfld ""int C.<<Main>g__f|0_0>d.p""
IL_003f: ldc.i4.0
IL_0040: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(uint, int)""
IL_0045: nop
// sequence point: int a = p;
IL_0046: ldloca.s V_0
IL_0048: ldarg.0
IL_0049: ldarg.0
IL_004a: ldfld ""int C.<<Main>g__f|0_0>d.p""
IL_004f: dup
IL_0050: stloc.3
IL_0051: stfld ""int C.<<Main>g__f|0_0>d.<a>5__1""
IL_0056: ldloc.3
IL_0057: ldtoken ""int C.<<Main>g__f|0_0>d.<a>5__1""
IL_005c: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0061: nop
IL_0062: ldarg.0
IL_0063: ldfld ""int C.<<Main>g__f|0_0>d.<a>5__1""
IL_0068: pop
// sequence point: yield return 1;
IL_0069: ldarg.0
IL_006a: ldc.i4.1
IL_006b: stfld ""int C.<<Main>g__f|0_0>d.<>2__current""
IL_0070: ldarg.0
IL_0071: ldc.i4.1
IL_0072: stfld ""int C.<<Main>g__f|0_0>d.<>1__state""
IL_0077: ldc.i4.1
IL_0078: stloc.2
IL_0079: leave.s IL_008f
// sequence point: <hidden>
IL_007b: ldarg.0
IL_007c: ldc.i4.m1
IL_007d: stfld ""int C.<<Main>g__f|0_0>d.<>1__state""
// sequence point: }
IL_0082: ldc.i4.0
IL_0083: stloc.2
IL_0084: leave.s IL_008f
}
finally
{
// sequence point: <hidden>
IL_0086: ldloca.s V_0
IL_0088: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_008d: nop
IL_008e: endfinally
}
// sequence point: <hidden>
IL_008f: ldloc.2
IL_0090: ret
}");
}
[Fact]
public void StateMachine_LocalFunction_AsyncIterator()
{
var source = WithHelpers(@"
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
class C
{
static async Task Main()
{
async IAsyncEnumerable<int> f(int p)
{
await Task.FromResult(1);
int a = p;
yield return 1;
}
await foreach (var n in M(f))
{
}
}
static IAsyncEnumerable<int> M(Func<int, IAsyncEnumerable<int>> p)
=> p(2);
}
");
var verifier = CompileAndVerify(source, expectedOutput: @"
Main: Entered state machine #1
M: Entered
M: P'p'[0] = System.Func`2[System.Int32,System.Collections.Generic.IAsyncEnumerable`1[System.Int32]]
M: Returned
Main: Entered lambda '<Main>g__f|0_0' state machine #2
<Main>g__f|0_0: P'p'[0] = 2
<Main>g__f|0_0: L'a' = 2
<Main>g__f|0_0: Returned
Main: L'n' = 1
Main: Entered lambda '<Main>g__f|0_0' state machine #2
<Main>g__f|0_0: Returned
Main: Returned
");
verifier.VerifyMethodBody("C.<<Main>g__f|0_0>d.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", @"
{
// Code size 391 (0x187)
.maxstack 4
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
int V_1,
System.Runtime.CompilerServices.TaskAwaiter<int> V_2,
C.<<Main>g__f|0_0>d V_3,
int V_4,
System.Exception V_5)
// sequence point: <hidden>
IL_0000: ldtoken ""System.Threading.Tasks.Task C.Main()""
IL_0005: ldtoken ""System.Collections.Generic.IAsyncEnumerable<int> C.<Main>g__f|0_0(int)""
IL_000a: ldarg.0
IL_000b: ldfld ""ulong C.<<Main>g__f|0_0>d.<>I""
IL_0010: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogStateMachineLambdaEntry(int, int, ulong)""
IL_0015: stloc.0
.try
{
// sequence point: <hidden>
IL_0016: ldarg.0
IL_0017: ldfld ""int C.<<Main>g__f|0_0>d.<>1__state""
IL_001c: stloc.1
.try
{
// sequence point: <hidden>
IL_001d: ldloc.1
IL_001e: ldc.i4.s -4
IL_0020: sub
IL_0021: switch (
IL_003c,
IL_0041,
IL_0045,
IL_0045,
IL_0043)
IL_003a: br.s IL_0045
IL_003c: br IL_0102
IL_0041: br.s IL_0045
IL_0043: br.s IL_00a6
IL_0045: ldarg.0
IL_0046: ldfld ""bool C.<<Main>g__f|0_0>d.<>w__disposeMode""
IL_004b: brfalse.s IL_0052
IL_004d: leave IL_0144
IL_0052: ldarg.0
IL_0053: ldc.i4.m1
IL_0054: dup
IL_0055: stloc.1
IL_0056: stfld ""int C.<<Main>g__f|0_0>d.<>1__state""
// sequence point: {
IL_005b: ldloca.s V_0
IL_005d: ldarg.0
IL_005e: ldfld ""int C.<<Main>g__f|0_0>d.p""
IL_0063: ldc.i4.0
IL_0064: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(uint, int)""
IL_0069: nop
// sequence point: await Task.FromResult(1);
IL_006a: ldc.i4.1
IL_006b: call ""System.Threading.Tasks.Task<int> System.Threading.Tasks.Task.FromResult<int>(int)""
IL_0070: callvirt ""System.Runtime.CompilerServices.TaskAwaiter<int> System.Threading.Tasks.Task<int>.GetAwaiter()""
IL_0075: stloc.2
// sequence point: <hidden>
IL_0076: ldloca.s V_2
IL_0078: call ""bool System.Runtime.CompilerServices.TaskAwaiter<int>.IsCompleted.get""
IL_007d: brtrue.s IL_00c2
IL_007f: ldarg.0
IL_0080: ldc.i4.0
IL_0081: dup
IL_0082: stloc.1
IL_0083: stfld ""int C.<<Main>g__f|0_0>d.<>1__state""
// async: yield
IL_0088: ldarg.0
IL_0089: ldloc.2
IL_008a: stfld ""System.Runtime.CompilerServices.TaskAwaiter<int> C.<<Main>g__f|0_0>d.<>u__1""
IL_008f: ldarg.0
IL_0090: stloc.3
IL_0091: ldarg.0
IL_0092: ldflda ""System.Runtime.CompilerServices.AsyncIteratorMethodBuilder C.<<Main>g__f|0_0>d.<>t__builder""
IL_0097: ldloca.s V_2
IL_0099: ldloca.s V_3
IL_009b: call ""void System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter<int>, C.<<Main>g__f|0_0>d>(ref System.Runtime.CompilerServices.TaskAwaiter<int>, ref C.<<Main>g__f|0_0>d)""
IL_00a0: nop
IL_00a1: leave IL_017b
// async: resume
IL_00a6: ldarg.0
IL_00a7: ldfld ""System.Runtime.CompilerServices.TaskAwaiter<int> C.<<Main>g__f|0_0>d.<>u__1""
IL_00ac: stloc.2
IL_00ad: ldarg.0
IL_00ae: ldflda ""System.Runtime.CompilerServices.TaskAwaiter<int> C.<<Main>g__f|0_0>d.<>u__1""
IL_00b3: initobj ""System.Runtime.CompilerServices.TaskAwaiter<int>""
IL_00b9: ldarg.0
IL_00ba: ldc.i4.m1
IL_00bb: dup
IL_00bc: stloc.1
IL_00bd: stfld ""int C.<<Main>g__f|0_0>d.<>1__state""
IL_00c2: ldloca.s V_2
IL_00c4: call ""int System.Runtime.CompilerServices.TaskAwaiter<int>.GetResult()""
IL_00c9: pop
// sequence point: int a = p;
IL_00ca: ldloca.s V_0
IL_00cc: ldarg.0
IL_00cd: ldarg.0
IL_00ce: ldfld ""int C.<<Main>g__f|0_0>d.p""
IL_00d3: dup
IL_00d4: stloc.s V_4
IL_00d6: stfld ""int C.<<Main>g__f|0_0>d.<a>5__1""
IL_00db: ldloc.s V_4
IL_00dd: ldtoken ""int C.<<Main>g__f|0_0>d.<a>5__1""
IL_00e2: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_00e7: nop
IL_00e8: ldarg.0
IL_00e9: ldfld ""int C.<<Main>g__f|0_0>d.<a>5__1""
IL_00ee: pop
// sequence point: yield return 1;
IL_00ef: ldarg.0
IL_00f0: ldc.i4.1
IL_00f1: stfld ""int C.<<Main>g__f|0_0>d.<>2__current""
IL_00f6: ldarg.0
IL_00f7: ldc.i4.s -4
IL_00f9: dup
IL_00fa: stloc.1
IL_00fb: stfld ""int C.<<Main>g__f|0_0>d.<>1__state""
IL_0100: leave.s IL_016e
// sequence point: <hidden>
IL_0102: ldarg.0
IL_0103: ldc.i4.m1
IL_0104: dup
IL_0105: stloc.1
IL_0106: stfld ""int C.<<Main>g__f|0_0>d.<>1__state""
IL_010b: ldarg.0
IL_010c: ldfld ""bool C.<<Main>g__f|0_0>d.<>w__disposeMode""
IL_0111: brfalse.s IL_0115
IL_0113: leave.s IL_0144
// sequence point: <hidden>
IL_0115: leave.s IL_0144
}
catch System.Exception
{
// sequence point: <hidden>
IL_0117: stloc.s V_5
IL_0119: ldarg.0
IL_011a: ldc.i4.s -2
IL_011c: stfld ""int C.<<Main>g__f|0_0>d.<>1__state""
IL_0121: ldarg.0
IL_0122: ldc.i4.0
IL_0123: stfld ""int C.<<Main>g__f|0_0>d.<>2__current""
IL_0128: ldarg.0
IL_0129: ldflda ""System.Runtime.CompilerServices.AsyncIteratorMethodBuilder C.<<Main>g__f|0_0>d.<>t__builder""
IL_012e: call ""void System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Complete()""
IL_0133: nop
IL_0134: ldarg.0
IL_0135: ldflda ""System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore<bool> C.<<Main>g__f|0_0>d.<>v__promiseOfValueOrEnd""
IL_013a: ldloc.s V_5
IL_013c: call ""void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore<bool>.SetException(System.Exception)""
IL_0141: nop
IL_0142: leave.s IL_017b
}
// sequence point: }
IL_0144: ldarg.0
IL_0145: ldc.i4.s -2
IL_0147: stfld ""int C.<<Main>g__f|0_0>d.<>1__state""
// sequence point: <hidden>
IL_014c: ldarg.0
IL_014d: ldc.i4.0
IL_014e: stfld ""int C.<<Main>g__f|0_0>d.<>2__current""
IL_0153: ldarg.0
IL_0154: ldflda ""System.Runtime.CompilerServices.AsyncIteratorMethodBuilder C.<<Main>g__f|0_0>d.<>t__builder""
IL_0159: call ""void System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Complete()""
IL_015e: nop
IL_015f: ldarg.0
IL_0160: ldflda ""System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore<bool> C.<<Main>g__f|0_0>d.<>v__promiseOfValueOrEnd""
IL_0165: ldc.i4.0
IL_0166: call ""void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore<bool>.SetResult(bool)""
IL_016b: nop
IL_016c: leave.s IL_0186
IL_016e: ldarg.0
IL_016f: ldflda ""System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore<bool> C.<<Main>g__f|0_0>d.<>v__promiseOfValueOrEnd""
IL_0174: ldc.i4.1
IL_0175: call ""void System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore<bool>.SetResult(bool)""
IL_017a: nop
IL_017b: leave.s IL_0186
}
finally
{
// sequence point: <hidden>
IL_017d: ldloca.s V_0
IL_017f: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0184: nop
IL_0185: endfinally
}
// sequence point: <hidden>
IL_0186: ret
}");
}
[Fact]
public void LocalFunctions()
{
var source = WithHelpers(@"
using System;
class C
{
static void Main()
{
int a = 1;
{
int b = 2;
{
int c = 3;
int f() => c += 1;
f();
}
int g() => a += b;
g();
}
}
}
");
var verifier = CompileAndVerify(source, expectedOutput: @"
Main: Entered
Main: L'a' = 1
Main: L'b' = 2
Main: L'c' = 3
Main: Entered lambda '<Main>g__f|0_1'
<Main>g__f|0_1: L'c' = 4
<Main>g__f|0_1: Returned
Main: Entered lambda '<Main>g__g|0_0'
<Main>g__g|0_0: L'a' = 3
<Main>g__g|0_0: Returned
Main: Returned
");
verifier.VerifyMethodBody("C.<Main>g__f|0_1", @"
{
// Code size 66 (0x42)
.maxstack 4
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
int V_1,
int V_2)
// sequence point: <hidden>
IL_0000: ldtoken ""void C.Main()""
IL_0005: ldtoken ""int C.<Main>g__f|0_1(ref C.<>c__DisplayClass0_2)""
IL_000a: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLambdaEntry(int, int)""
IL_000f: stloc.0
.try
{
// sequence point: c += 1
IL_0010: ldloca.s V_0
IL_0012: ldarg.0
IL_0013: ldarg.0
IL_0014: ldfld ""int C.<>c__DisplayClass0_2.c""
IL_0019: ldc.i4.1
IL_001a: add
IL_001b: dup
IL_001c: stloc.1
IL_001d: stfld ""int C.<>c__DisplayClass0_2.c""
IL_0022: ldloc.1
IL_0023: ldtoken ""int C.<>c__DisplayClass0_2.c""
IL_0028: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_002d: nop
IL_002e: ldarg.0
IL_002f: ldfld ""int C.<>c__DisplayClass0_2.c""
IL_0034: stloc.2
IL_0035: leave.s IL_0040
}
finally
{
// sequence point: <hidden>
IL_0037: ldloca.s V_0
IL_0039: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_003e: nop
IL_003f: endfinally
}
// sequence point: <hidden>
IL_0040: ldloc.2
IL_0041: ret
}
");
verifier.VerifyMethodBody("C.<Main>g__g|0_0", @"
{
// Code size 71 (0x47)
.maxstack 4
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
int V_1,
int V_2)
// sequence point: <hidden>
IL_0000: ldtoken ""void C.Main()""
IL_0005: ldtoken ""int C.<Main>g__g|0_0(ref C.<>c__DisplayClass0_0, ref C.<>c__DisplayClass0_1)""
IL_000a: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLambdaEntry(int, int)""
IL_000f: stloc.0
.try
{
// sequence point: a += b
IL_0010: ldloca.s V_0
IL_0012: ldarg.0
IL_0013: ldarg.0
IL_0014: ldfld ""int C.<>c__DisplayClass0_0.a""
IL_0019: ldarg.1
IL_001a: ldfld ""int C.<>c__DisplayClass0_1.b""
IL_001f: add
IL_0020: dup
IL_0021: stloc.1
IL_0022: stfld ""int C.<>c__DisplayClass0_0.a""
IL_0027: ldloc.1
IL_0028: ldtoken ""int C.<>c__DisplayClass0_0.a""
IL_002d: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0032: nop
IL_0033: ldarg.0
IL_0034: ldfld ""int C.<>c__DisplayClass0_0.a""
IL_0039: stloc.2
IL_003a: leave.s IL_0045
}
finally
{
// sequence point: <hidden>
IL_003c: ldloca.s V_0
IL_003e: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0043: nop
IL_0044: endfinally
}
// sequence point: <hidden>
IL_0045: ldloc.2
IL_0046: ret
}");
verifier.VerifyMethodBody("C.Main", @"
{
// Code size 120 (0x78)
.maxstack 4
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
C.<>c__DisplayClass0_0 V_1, //CS$<>8__locals0
int V_2,
C.<>c__DisplayClass0_1 V_3, //CS$<>8__locals1
C.<>c__DisplayClass0_2 V_4) //CS$<>8__locals2
// sequence point: <hidden>
IL_0000: ldtoken ""void C.Main()""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: {
IL_000b: nop
// sequence point: int a = 1;
IL_000c: ldloca.s V_0
IL_000e: ldloca.s V_1
IL_0010: ldc.i4.1
IL_0011: dup
IL_0012: stloc.2
IL_0013: stfld ""int C.<>c__DisplayClass0_0.a""
IL_0018: ldloc.2
IL_0019: ldtoken ""int C.<>c__DisplayClass0_0.a""
IL_001e: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0023: nop
// sequence point: {
IL_0024: nop
// sequence point: int b = 2;
IL_0025: ldloca.s V_0
IL_0027: ldloca.s V_3
IL_0029: ldc.i4.2
IL_002a: dup
IL_002b: stloc.2
IL_002c: stfld ""int C.<>c__DisplayClass0_1.b""
IL_0031: ldloc.2
IL_0032: ldtoken ""int C.<>c__DisplayClass0_1.b""
IL_0037: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_003c: nop
// sequence point: {
IL_003d: nop
// sequence point: int c = 3;
IL_003e: ldloca.s V_0
IL_0040: ldloca.s V_4
IL_0042: ldc.i4.3
IL_0043: dup
IL_0044: stloc.2
IL_0045: stfld ""int C.<>c__DisplayClass0_2.c""
IL_004a: ldloc.2
IL_004b: ldtoken ""int C.<>c__DisplayClass0_2.c""
IL_0050: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0055: nop
IL_0056: nop
// sequence point: f();
IL_0057: ldloca.s V_4
IL_0059: call ""int C.<Main>g__f|0_1(ref C.<>c__DisplayClass0_2)""
IL_005e: pop
// sequence point: }
IL_005f: nop
IL_0060: nop
// sequence point: g();
IL_0061: ldloca.s V_1
IL_0063: ldloca.s V_3
IL_0065: call ""int C.<Main>g__g|0_0(ref C.<>c__DisplayClass0_0, ref C.<>c__DisplayClass0_1)""
IL_006a: pop
// sequence point: }
IL_006b: nop
// sequence point: }
IL_006c: leave.s IL_0077
}
finally
{
// sequence point: <hidden>
IL_006e: ldloca.s V_0
IL_0070: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0075: nop
IL_0076: endfinally
}
// sequence point: }
IL_0077: ret
}
");
}
[Fact]
public void Queries()
{
var source = WithHelpers(@"
using System;
using System.Linq;
class C
{
static void Main()
{
int a = 1;
{
int b = 2;
var x = from item in new[] { 10, 20 }
let c = a + b
select item + (a = b);
x.ToArray();
}
}
}
");
var verifier = CompileAndVerify(source, expectedOutput: @"
Main: Entered
Main: L'a' = 1
Main: L'b' = 2
Main: L4 = System.Linq.Enumerable+ArraySelectIterator`2[System.Int32,System.Int32]
Main: Entered lambda '<Main>b__0'
<Main>b__0: P'item'[0] = 10
<Main>b__0: Returned
Main: Entered lambda '<Main>b__1'
<Main>b__1: P'<>h__TransparentIdentifier0'[0] = { item = 10, c = 3 }
<Main>b__1: L'a' = 2
<Main>b__1: Returned
Main: Entered lambda '<Main>b__0'
<Main>b__0: P'item'[0] = 20
<Main>b__0: Returned
Main: Entered lambda '<Main>b__1'
<Main>b__1: P'<>h__TransparentIdentifier0'[0] = { item = 20, c = 4 }
<Main>b__1: L'a' = 2
<Main>b__1: Returned
Main: Returned
");
verifier.VerifyMethodBody("C.<>c__DisplayClass0_1.<Main>b__1", @"
{
// Code size 91 (0x5b)
.maxstack 5
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
int V_1,
int V_2)
// sequence point: <hidden>
IL_0000: ldtoken ""void C.Main()""
IL_0005: ldtoken ""int C.<>c__DisplayClass0_1.<Main>b__1(<anonymous type: int item, int c>)""
IL_000a: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLambdaEntry(int, int)""
IL_000f: stloc.0
.try
{
IL_0010: ldloca.s V_0
IL_0012: ldarg.1
IL_0013: ldc.i4.0
IL_0014: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(object, int)""
IL_0019: nop
// sequence point: item + (a = b)
IL_001a: ldarg.1
IL_001b: callvirt ""int <>f__AnonymousType0<int, int>.item.get""
IL_0020: ldloca.s V_0
IL_0022: ldarg.0
IL_0023: ldfld ""C.<>c__DisplayClass0_0 C.<>c__DisplayClass0_1.CS$<>8__locals1""
IL_0028: ldarg.0
IL_0029: ldfld ""int C.<>c__DisplayClass0_1.b""
IL_002e: dup
IL_002f: stloc.1
IL_0030: stfld ""int C.<>c__DisplayClass0_0.a""
IL_0035: ldloc.1
IL_0036: ldtoken ""int C.<>c__DisplayClass0_0.a""
IL_003b: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0040: nop
IL_0041: ldarg.0
IL_0042: ldfld ""C.<>c__DisplayClass0_0 C.<>c__DisplayClass0_1.CS$<>8__locals1""
IL_0047: ldfld ""int C.<>c__DisplayClass0_0.a""
IL_004c: add
IL_004d: stloc.2
IL_004e: leave.s IL_0059
}
finally
{
// sequence point: <hidden>
IL_0050: ldloca.s V_0
IL_0052: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0057: nop
IL_0058: endfinally
}
// sequence point: <hidden>
IL_0059: ldloc.2
IL_005a: ret
}");
verifier.VerifyMethodBody("C.<>c__DisplayClass0_1.<Main>b__0", @"
{
// Code size 64 (0x40)
.maxstack 3
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
<>f__AnonymousType0<int, int> V_1)
// sequence point: <hidden>
IL_0000: ldtoken ""void C.Main()""
IL_0005: ldtoken ""<anonymous type: int item, int c> C.<>c__DisplayClass0_1.<Main>b__0(int)""
IL_000a: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLambdaEntry(int, int)""
IL_000f: stloc.0
.try
{
IL_0010: ldloca.s V_0
IL_0012: ldarg.1
IL_0013: ldc.i4.0
IL_0014: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(uint, int)""
IL_0019: nop
// sequence point: a + b
IL_001a: ldarg.1
IL_001b: ldarg.0
IL_001c: ldfld ""C.<>c__DisplayClass0_0 C.<>c__DisplayClass0_1.CS$<>8__locals1""
IL_0021: ldfld ""int C.<>c__DisplayClass0_0.a""
IL_0026: ldarg.0
IL_0027: ldfld ""int C.<>c__DisplayClass0_1.b""
IL_002c: add
IL_002d: newobj ""<>f__AnonymousType0<int, int>..ctor(int, int)""
IL_0032: stloc.1
IL_0033: leave.s IL_003e
}
finally
{
// sequence point: <hidden>
IL_0035: ldloca.s V_0
IL_0037: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_003c: nop
IL_003d: endfinally
}
// sequence point: <hidden>
IL_003e: ldloc.1
IL_003f: ret
}");
}
[Fact]
public void ExpressionLambdas()
{
var source = WithHelpers(@"
using System;
using System.Linq.Expressions;
Expression<Func<int, int>> expression = a => a + 1;
");
var verifier = CompileAndVerify(source, expectedOutput: @"
<Main>$: Entered
<Main>$: P'args'[0] = System.String[]
<Main>$: L1 = a => (a + 1)
<Main>$: Returned
");
verifier.VerifyMethodBody("<top-level-statements-entry-point>", @"
{
// Code size 107 (0x6b)
.maxstack 6
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
System.Linq.Expressions.Expression<System.Func<int, int>> V_1, //expression
System.Linq.Expressions.ParameterExpression V_2)
// sequence point: <hidden>
IL_0000: ldtoken ""<top-level-statements-entry-point>""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: <hidden>
IL_000b: ldloca.s V_0
IL_000d: ldarg.0
IL_000e: ldc.i4.0
IL_000f: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(object, int)""
IL_0014: nop
// sequence point: Expression<Func<int, int>> expression = a => a + 1;
IL_0015: ldloca.s V_0
IL_0017: ldtoken ""int""
IL_001c: call ""System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)""
IL_0021: ldstr ""a""
IL_0026: call ""System.Linq.Expressions.ParameterExpression System.Linq.Expressions.Expression.Parameter(System.Type, string)""
IL_002b: stloc.2
IL_002c: ldloc.2
IL_002d: ldc.i4.1
IL_002e: box ""int""
IL_0033: ldtoken ""int""
IL_0038: call ""System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)""
IL_003d: call ""System.Linq.Expressions.ConstantExpression System.Linq.Expressions.Expression.Constant(object, System.Type)""
IL_0042: call ""System.Linq.Expressions.BinaryExpression System.Linq.Expressions.Expression.Add(System.Linq.Expressions.Expression, System.Linq.Expressions.Expression)""
IL_0047: ldc.i4.1
IL_0048: newarr ""System.Linq.Expressions.ParameterExpression""
IL_004d: dup
IL_004e: ldc.i4.0
IL_004f: ldloc.2
IL_0050: stelem.ref
IL_0051: call ""System.Linq.Expressions.Expression<System.Func<int, int>> System.Linq.Expressions.Expression.Lambda<System.Func<int, int>>(System.Linq.Expressions.Expression, params System.Linq.Expressions.ParameterExpression[])""
IL_0056: dup
IL_0057: stloc.1
IL_0058: ldc.i4.1
IL_0059: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(object, int)""
IL_005e: nop
IL_005f: leave.s IL_006a
}
finally
{
// sequence point: <hidden>
IL_0061: ldloca.s V_0
IL_0063: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0068: nop
IL_0069: endfinally
}
// sequence point: <hidden>
IL_006a: ret
}
");
}
[Fact]
public void TopLevelCode()
{
var source = WithHelpers(@"
int a = 1;
int b = 2;
");
var verifier = CompileAndVerify(source, expectedOutput: @"
<Main>$: Entered
<Main>$: P'args'[0] = System.String[]
<Main>$: L1 = 1
<Main>$: L2 = 2
<Main>$: Returned
");
verifier.VerifyMethodBody("<top-level-statements-entry-point>", @"
{
// Code size 57 (0x39)
.maxstack 3
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
int V_1, //a
int V_2) //b
// sequence point: <hidden>
IL_0000: ldtoken ""<top-level-statements-entry-point>""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: <hidden>
IL_000b: ldloca.s V_0
IL_000d: ldarg.0
IL_000e: ldc.i4.0
IL_000f: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(object, int)""
IL_0014: nop
// sequence point: int a = 1;
IL_0015: ldloca.s V_0
IL_0017: ldc.i4.1
IL_0018: dup
IL_0019: stloc.1
IL_001a: ldc.i4.1
IL_001b: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_0020: nop
// sequence point: int b = 2;
IL_0021: ldloca.s V_0
IL_0023: ldc.i4.2
IL_0024: dup
IL_0025: stloc.2
IL_0026: ldc.i4.2
IL_0027: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_002c: nop
IL_002d: leave.s IL_0038
}
finally
{
// sequence point: <hidden>
IL_002f: ldloca.s V_0
IL_0031: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0036: nop
IL_0037: endfinally
}
// sequence point: <hidden>
IL_0038: ret
}
");
}
[Fact]
public void ExceptionHandler_CatchAll()
{
var source = WithHelpers(@"
class C
{
static void Main(string[] args)
{
string s;
try
{
s = args[0];
}
catch
{
s = ""error"";
}
}
}
");
var verifier = CompileAndVerify(source, expectedOutput: @"
Main: Entered
Main: P'args'[0] = System.String[]
Main: L1 = error
Main: Returned
");
verifier.VerifyMethodBody("C.Main", @"
{
// Code size 72 (0x48)
.maxstack 3
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
string V_1) //s
// sequence point: <hidden>
IL_0000: ldtoken ""void C.Main(string[])""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: {
IL_000b: ldloca.s V_0
IL_000d: ldarg.0
IL_000e: ldc.i4.0
IL_000f: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(object, int)""
IL_0014: nop
.try
{
// sequence point: {
IL_0015: nop
// sequence point: s = args[0];
IL_0016: ldloca.s V_0
IL_0018: ldarg.0
IL_0019: ldc.i4.0
IL_001a: ldelem.ref
IL_001b: dup
IL_001c: stloc.1
IL_001d: ldc.i4.1
IL_001e: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(string, int)""
IL_0023: nop
// sequence point: }
IL_0024: nop
IL_0025: leave.s IL_003c
}
catch object
{
// sequence point: catch
IL_0027: pop
// sequence point: {
IL_0028: nop
// sequence point: s = ""error"";
IL_0029: ldloca.s V_0
IL_002b: ldstr ""error""
IL_0030: dup
IL_0031: stloc.1
IL_0032: ldc.i4.1
IL_0033: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(string, int)""
IL_0038: nop
// sequence point: }
IL_0039: nop
IL_003a: leave.s IL_003c
}
// sequence point: }
IL_003c: leave.s IL_0047
}
finally
{
// sequence point: <hidden>
IL_003e: ldloca.s V_0
IL_0040: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0045: nop
IL_0046: endfinally
}
// sequence point: }
IL_0047: ret
}");
}
[Fact]
public void ExceptionHandler_CatchType()
{
var source = WithHelpers(@"
class C
{
static void Main(string[] args)
{
string s;
try
{
s = args[0];
}
catch (System.Exception)
{
s = ""error"";
}
}
}
");
var verifier = CompileAndVerify(source);
verifier.VerifyMethodBody("C.Main", @"
{
// Code size 72 (0x48)
.maxstack 3
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
string V_1) //s
// sequence point: <hidden>
IL_0000: ldtoken ""void C.Main(string[])""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: {
IL_000b: ldloca.s V_0
IL_000d: ldarg.0
IL_000e: ldc.i4.0
IL_000f: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(object, int)""
IL_0014: nop
.try
{
// sequence point: {
IL_0015: nop
// sequence point: s = args[0];
IL_0016: ldloca.s V_0
IL_0018: ldarg.0
IL_0019: ldc.i4.0
IL_001a: ldelem.ref
IL_001b: dup
IL_001c: stloc.1
IL_001d: ldc.i4.1
IL_001e: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(string, int)""
IL_0023: nop
// sequence point: }
IL_0024: nop
IL_0025: leave.s IL_003c
}
catch System.Exception
{
// sequence point: catch (System.Exception)
IL_0027: pop
// sequence point: {
IL_0028: nop
// sequence point: s = ""error"";
IL_0029: ldloca.s V_0
IL_002b: ldstr ""error""
IL_0030: dup
IL_0031: stloc.1
IL_0032: ldc.i4.1
IL_0033: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(string, int)""
IL_0038: nop
// sequence point: }
IL_0039: nop
IL_003a: leave.s IL_003c
}
// sequence point: }
IL_003c: leave.s IL_0047
}
finally
{
// sequence point: <hidden>
IL_003e: ldloca.s V_0
IL_0040: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0045: nop
IL_0046: endfinally
}
// sequence point: }
IL_0047: ret
}");
}
[Fact]
public void ExceptionHandler_CatchTypeWithVariable()
{
var source = WithHelpers(@"
class C
{
static void Main(string[] args)
{
string s;
try
{
s = args[0];
}
catch (System.Exception e)
{
s = ""error"";
}
}
}
");
var verifier = CompileAndVerify(source, expectedOutput: @"
Main: Entered
Main: P'args'[0] = System.String[]
Main: L2 = System.IndexOutOfRangeException: Index was outside the bounds of the array.
at C.Main(String[] args)
Main: L1 = error
Main: Returned
");
verifier.VerifyMethodBody("C.Main", @"
{
// Code size 82 (0x52)
.maxstack 3
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
string V_1, //s
System.Exception V_2) //e
// sequence point: <hidden>
IL_0000: ldtoken ""void C.Main(string[])""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: {
IL_000b: ldloca.s V_0
IL_000d: ldarg.0
IL_000e: ldc.i4.0
IL_000f: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(object, int)""
IL_0014: nop
.try
{
// sequence point: {
IL_0015: nop
// sequence point: s = args[0];
IL_0016: ldloca.s V_0
IL_0018: ldarg.0
IL_0019: ldc.i4.0
IL_001a: ldelem.ref
IL_001b: dup
IL_001c: stloc.1
IL_001d: ldc.i4.1
IL_001e: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(string, int)""
IL_0023: nop
// sequence point: }
IL_0024: nop
IL_0025: leave.s IL_0046
}
catch System.Exception
{
// sequence point: catch (System.Exception e)
IL_0027: stloc.2
IL_0028: ldloca.s V_0
IL_002a: ldloc.2
IL_002b: ldc.i4.2
IL_002c: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(object, int)""
IL_0031: nop
// sequence point: {
IL_0032: nop
// sequence point: s = ""error"";
IL_0033: ldloca.s V_0
IL_0035: ldstr ""error""
IL_003a: dup
IL_003b: stloc.1
IL_003c: ldc.i4.1
IL_003d: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(string, int)""
IL_0042: nop
// sequence point: }
IL_0043: nop
IL_0044: leave.s IL_0046
}
// sequence point: }
IL_0046: leave.s IL_0051
}
finally
{
// sequence point: <hidden>
IL_0048: ldloca.s V_0
IL_004a: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_004f: nop
IL_0050: endfinally
}
// sequence point: }
IL_0051: ret
}
");
}
[Fact]
public void ExceptionHandler_CatchTypeWithVariableAndLocalsInCatchBlock()
{
var source = WithHelpers(@"
class C
{
static void Main(string[] args)
{
string s;
try
{
s = args[0];
}
catch (System.Exception e)
{
int a = 1;
int b = 2;
}
}
}
");
var verifier = CompileAndVerify(source, expectedOutput: @"
Main: Entered
Main: P'args'[0] = System.String[]
Main: L2 = System.IndexOutOfRangeException: Index was outside the bounds of the array.
at C.Main(String[] args)
Main: L3 = 1
Main: L4 = 2
Main: Returned
");
verifier.VerifyMethodBody("C.Main", @"
{
// Code size 91 (0x5b)
.maxstack 3
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
string V_1, //s
System.Exception V_2, //e
int V_3, //a
int V_4) //b
// sequence point: <hidden>
IL_0000: ldtoken ""void C.Main(string[])""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: {
IL_000b: ldloca.s V_0
IL_000d: ldarg.0
IL_000e: ldc.i4.0
IL_000f: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(object, int)""
IL_0014: nop
.try
{
// sequence point: {
IL_0015: nop
// sequence point: s = args[0];
IL_0016: ldloca.s V_0
IL_0018: ldarg.0
IL_0019: ldc.i4.0
IL_001a: ldelem.ref
IL_001b: dup
IL_001c: stloc.1
IL_001d: ldc.i4.1
IL_001e: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(string, int)""
IL_0023: nop
// sequence point: }
IL_0024: nop
IL_0025: leave.s IL_004f
}
catch System.Exception
{
// sequence point: catch (System.Exception e)
IL_0027: stloc.2
IL_0028: ldloca.s V_0
IL_002a: ldloc.2
IL_002b: ldc.i4.2
IL_002c: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(object, int)""
IL_0031: nop
// sequence point: {
IL_0032: nop
// sequence point: int a = 1;
IL_0033: ldloca.s V_0
IL_0035: ldc.i4.1
IL_0036: dup
IL_0037: stloc.3
IL_0038: ldc.i4.3
IL_0039: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_003e: nop
// sequence point: int b = 2;
IL_003f: ldloca.s V_0
IL_0041: ldc.i4.2
IL_0042: dup
IL_0043: stloc.s V_4
IL_0045: ldc.i4.4
IL_0046: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(uint, int)""
IL_004b: nop
// sequence point: }
IL_004c: nop
IL_004d: leave.s IL_004f
}
// sequence point: }
IL_004f: leave.s IL_005a
}
finally
{
// sequence point: <hidden>
IL_0051: ldloca.s V_0
IL_0053: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0058: nop
IL_0059: endfinally
}
// sequence point: }
IL_005a: ret
}
");
}
[Fact]
public void ExceptionHandler_CatchTypeWithFilter()
{
var source = WithHelpers(@"
class C
{
static void Main(string[] args)
{
bool b = false;
string s;
try
{
s = args[0];
}
catch (System.Exception e) when (b = true)
{
s = ""error"";
}
}
}
");
var verifier = CompileAndVerify(source, expectedOutput: @"
Main: Entered
Main: P'args'[0] = System.String[]
Main: L1 = False
Main: L3 = System.IndexOutOfRangeException: Index was outside the bounds of the array.
at C.Main(String[] args)
Main: L1 = True
Main: L2 = error
Main: Returned
");
verifier.VerifyMethodBody("C.Main", @"
{
// Code size 129 (0x81)
.maxstack 3
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
bool V_1, //b
string V_2, //s
System.Exception V_3, //e
bool V_4)
// sequence point: <hidden>
IL_0000: ldtoken ""void C.Main(string[])""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: {
IL_000b: ldloca.s V_0
IL_000d: ldarg.0
IL_000e: ldc.i4.0
IL_000f: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(object, int)""
IL_0014: nop
// sequence point: bool b = false;
IL_0015: ldloca.s V_0
IL_0017: ldc.i4.0
IL_0018: dup
IL_0019: stloc.1
IL_001a: ldc.i4.1
IL_001b: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(bool, int)""
IL_0020: nop
.try
{
// sequence point: {
IL_0021: nop
// sequence point: s = args[0];
IL_0022: ldloca.s V_0
IL_0024: ldarg.0
IL_0025: ldc.i4.0
IL_0026: ldelem.ref
IL_0027: dup
IL_0028: stloc.2
IL_0029: ldc.i4.2
IL_002a: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(string, int)""
IL_002f: nop
// sequence point: }
IL_0030: nop
IL_0031: leave.s IL_0075
}
filter
{
// sequence point: <hidden>
IL_0033: isinst ""System.Exception""
IL_0038: dup
IL_0039: brtrue.s IL_003f
IL_003b: pop
IL_003c: ldc.i4.0
IL_003d: br.s IL_005e
IL_003f: stloc.3
IL_0040: ldloca.s V_0
IL_0042: ldloc.3
IL_0043: ldc.i4.3
IL_0044: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(object, int)""
IL_0049: nop
// sequence point: when (b = true)
IL_004a: ldloca.s V_0
IL_004c: ldc.i4.1
IL_004d: dup
IL_004e: stloc.1
IL_004f: ldc.i4.1
IL_0050: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(bool, int)""
IL_0055: nop
IL_0056: ldloc.1
IL_0057: stloc.s V_4
// sequence point: <hidden>
IL_0059: ldloc.s V_4
IL_005b: ldc.i4.0
IL_005c: cgt.un
IL_005e: endfilter
} // end filter
{ // handler
// sequence point: <hidden>
IL_0060: pop
// sequence point: {
IL_0061: nop
// sequence point: s = ""error"";
IL_0062: ldloca.s V_0
IL_0064: ldstr ""error""
IL_0069: dup
IL_006a: stloc.2
IL_006b: ldc.i4.2
IL_006c: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(string, int)""
IL_0071: nop
// sequence point: }
IL_0072: nop
IL_0073: leave.s IL_0075
}
// sequence point: }
IL_0075: leave.s IL_0080
}
finally
{
// sequence point: <hidden>
IL_0077: ldloca.s V_0
IL_0079: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_007e: nop
IL_007f: endfinally
}
// sequence point: }
IL_0080: ret
}
");
}
[Fact]
public void ExceptionHandler_CatchAllWithFilter()
{
var source = WithHelpers(@"
class C
{
static void Main(string[] args)
{
bool b = false;
string s;
try
{
s = args[0];
}
catch when (b = true)
{
s = ""error"";
}
}
}
");
var verifier = CompileAndVerify(source, expectedOutput: @"
Main: Entered
Main: P'args'[0] = System.String[]
Main: L1 = False
Main: L1 = True
Main: L2 = error
Main: Returned
");
verifier.VerifyMethodBody("C.Main", @"
{
// Code size 105 (0x69)
.maxstack 3
.locals init (Microsoft.CodeAnalysis.Runtime.LocalStoreTracker V_0,
bool V_1, //b
string V_2, //s
bool V_3)
// sequence point: <hidden>
IL_0000: ldtoken ""void C.Main(string[])""
IL_0005: call ""Microsoft.CodeAnalysis.Runtime.LocalStoreTracker Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogMethodEntry(int)""
IL_000a: stloc.0
.try
{
// sequence point: {
IL_000b: ldloca.s V_0
IL_000d: ldarg.0
IL_000e: ldc.i4.0
IL_000f: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogParameterStore(object, int)""
IL_0014: nop
// sequence point: bool b = false;
IL_0015: ldloca.s V_0
IL_0017: ldc.i4.0
IL_0018: dup
IL_0019: stloc.1
IL_001a: ldc.i4.1
IL_001b: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(bool, int)""
IL_0020: nop
.try
{
// sequence point: {
IL_0021: nop
// sequence point: s = args[0];
IL_0022: ldloca.s V_0
IL_0024: ldarg.0
IL_0025: ldc.i4.0
IL_0026: ldelem.ref
IL_0027: dup
IL_0028: stloc.2
IL_0029: ldc.i4.2
IL_002a: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(string, int)""
IL_002f: nop
// sequence point: }
IL_0030: nop
IL_0031: leave.s IL_005d
}
filter
{
// sequence point: <hidden>
IL_0033: pop
// sequence point: when (b = true)
IL_0034: ldloca.s V_0
IL_0036: ldc.i4.1
IL_0037: dup
IL_0038: stloc.1
IL_0039: ldc.i4.1
IL_003a: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(bool, int)""
IL_003f: nop
IL_0040: ldloc.1
IL_0041: stloc.3
// sequence point: <hidden>
IL_0042: ldloc.3
IL_0043: ldc.i4.0
IL_0044: cgt.un
IL_0046: endfilter
} // end filter
{ // handler
// sequence point: <hidden>
IL_0048: pop
// sequence point: {
IL_0049: nop
// sequence point: s = ""error"";
IL_004a: ldloca.s V_0
IL_004c: ldstr ""error""
IL_0051: dup
IL_0052: stloc.2
IL_0053: ldc.i4.2
IL_0054: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogLocalStore(string, int)""
IL_0059: nop
// sequence point: }
IL_005a: nop
IL_005b: leave.s IL_005d
}
// sequence point: }
IL_005d: leave.s IL_0068
}
finally
{
// sequence point: <hidden>
IL_005f: ldloca.s V_0
IL_0061: call ""void Microsoft.CodeAnalysis.Runtime.LocalStoreTracker.LogReturn()""
IL_0066: nop
IL_0067: endfinally
}
// sequence point: }
IL_0068: ret
}");
}
[Fact]
public void Recursion()
{
var source = WithHelpers(@"
class C
{
static void M(int depth)
{
if (depth == 4)
{
return;
}
int a = depth;
int b = depth;
M(depth + 1);
a += 10;
if (depth % 2 == 0) b += 10;
}
static void Main() => M(0);
}
");
CompileAndVerify(source, expectedOutput: @"
Main: Entered
M: Entered
M: P'depth'[0] = 0
M: L1 = 0
M: L2 = 0
M: Entered
M: P'depth'[0] = 1
M: L1 = 1
M: L2 = 1
M: Entered
M: P'depth'[0] = 2
M: L1 = 2
M: L2 = 2
M: Entered
M: P'depth'[0] = 3
M: L1 = 3
M: L2 = 3
M: Entered
M: P'depth'[0] = 4
M: Returned
M: L1 = 13
M: Returned
M: L1 = 12
M: L2 = 12
M: Returned
M: L1 = 11
M: Returned
M: L1 = 10
M: L2 = 10
M: Returned
Main: Returned
");
}
[Fact]
public void Discards()
{
var source = WithHelpers(@"
using System;
_ = G(y: out var a, x: out _, z: out _);
F((_, _) => _ = 1);
static int G(out int x, out int y, out int z) => x = y = z = 1;
static int F(Func<int, int, int> f) => f(1, 2);
");
CompileAndVerify(source, expectedOutput: @"
<Main>$: Entered
<Main>$: P'args'[0] = System.String[]
<Main>$: Entered lambda '<<Main>$>g__G|0_1'
<<Main>$>g__G|0_1: P'z'[2] = 1
<<Main>$>g__G|0_1: P'y'[1] = 1
<<Main>$>g__G|0_1: P'x'[0] = 1
<<Main>$>g__G|0_1: Returned
<Main>$: L1 = 1
<Main>$: Entered lambda '<<Main>$>g__F|0_2'
<<Main>$>g__F|0_2: P'f'[0] = System.Func`3[System.Int32,System.Int32,System.Int32]
<Main>$: Entered lambda '<<Main>$>b__0_0'
<<Main>$>b__0_0: Returned
<<Main>$>g__F|0_2: Returned
<Main>$: Returned
");
}
}
}
#endif
|