未验证 提交 0ed2256a 编写于 作者: N Neal Gafter 提交者: GitHub

Permit stackalloc to be used in an async method as long as it need not be spilled. (#37711)

Fixes #37461
上级 a31b284e
......@@ -36,16 +36,21 @@ private BoundExpression RewriteAwaitExpression(BoundExpression rewrittenAwait, b
}
// The await expression will be lowered to code that involves the use of side-effects
// such as jumps and labels, therefore it is represented by a BoundSpillSequence.
// The resulting nodes will be "spilled" to move such statements to the top
// level (i.e. into the enclosing statement list).
// such as jumps and labels, which we can only emit with an empty stack, so we require
// that the await expression itself is produced only when the stack is empty.
// Therefore it is represented by a BoundSpillSequence. The resulting nodes will be "spilled" to move
// such statements to the top level (i.e. into the enclosing statement list). Here we ensure
// that the await result itself is stored into a temp at the statement level, as that is
// the form handled by async lowering.
_needsSpilling = true;
var tempAccess = _factory.StoreToTemp(rewrittenAwait, out BoundAssignmentOperator tempAssignment, syntaxOpt: rewrittenAwait.Syntax,
kind: SynthesizedLocalKind.Spill);
return new BoundSpillSequence(
syntax: rewrittenAwait.Syntax,
locals: ImmutableArray<LocalSymbol>.Empty,
sideEffects: ImmutableArray<BoundStatement>.Empty,
value: rewrittenAwait,
type: rewrittenAwait.Type);
locals: ImmutableArray.Create<LocalSymbol>(tempAccess.LocalSymbol),
sideEffects: ImmutableArray.Create<BoundExpression>(tempAssignment),
value: tempAccess,
type: tempAccess.Type);
}
}
}
......@@ -86,7 +86,7 @@ BoundExpression rewriteNullCoalescingAssignmentForValueType()
// the standard ??= case because it only uses lhsRead once.
if (lhsRead.Kind == BoundKind.Call)
{
var lhsTemp = _factory.StoreToTemp(lhsRead, out var store, kind: SynthesizedLocalKind.Spill);
var lhsTemp = _factory.StoreToTemp(lhsRead, out var store);
stores.Add(store);
temps.Add(lhsTemp.LocalSymbol);
lhsRead = lhsTemp;
......@@ -94,8 +94,7 @@ BoundExpression rewriteNullCoalescingAssignmentForValueType()
// tmp = lhsRead.GetValueOrDefault();
var tmp = _factory.StoreToTemp(BoundCall.Synthesized(leftOperand.Syntax, lhsRead, getValueOrDefault),
out var getValueOrDefaultStore,
kind: SynthesizedLocalKind.Spill);
out var getValueOrDefaultStore);
stores.Add(getValueOrDefaultStore);
temps.Add(tmp.LocalSymbol);
......
......@@ -64,12 +64,20 @@ public override BoundNode VisitStackAllocArrayCreation(BoundStackAllocArrayCreat
type: ErrorTypeSymbol.UnknownResultType);
}
// The stackalloc instruction requires that the evaluation stack contains only its parameter when executed.
// We arrange to clear the stack by wrapping it in a SpillSequence, which will cause pending computations
// to be spilled, and also by storing the result in a temporary local, so that the result does not get
// hoisted/spilled into some state machine. If that temp local needs to be spilled that will result in an
// error.
_needsSpilling = true;
var tempAccess = _factory.StoreToTemp(constructorCall, out BoundAssignmentOperator tempAssignment, syntaxOpt: stackAllocNode.Syntax);
sideEffects.Add(tempAssignment);
locals.Add(tempAccess.LocalSymbol);
return new BoundSpillSequence(
syntax: stackAllocNode.Syntax,
locals: locals.ToImmutableAndFree(),
sideEffects: sideEffects.ToImmutableAndFree(),
value: constructorCall,
value: tempAccess,
type: spanType);
}
else
......
......@@ -551,7 +551,6 @@ public override BoundNode VisitSpillSequence(BoundSpillSequence node)
builder.AddStatements(VisitList(node.SideEffects));
builder.AddLocals(node.Locals);
var value = VisitExpression(ref builder, node.Value);
value = Spill(builder, value);
return builder.Update(value);
}
......
......@@ -107,6 +107,12 @@ protected BoundStatement Rewrite()
// fields for the captured variables of the method
var variablesToHoist = IteratorAndAsyncCaptureWalker.Analyze(F.Compilation, method, body, diagnostics);
if (diagnostics.HasAnyErrors())
{
// Avoid triggering assertions in further lowering.
return new BoundBadStatement(F.Syntax, ImmutableArray<BoundNode>.Empty, hasErrors: true);
}
CreateNonReusableLocalProxies(variablesToHoist, out this.nonReusableLocalProxies, out this.nextFreeHoistedLocalSlot);
this.hoistedVariables = variablesToHoist;
......
......@@ -351,10 +351,10 @@ public async Task M(IDisposable disposable)
<slot kind=""4"" offset=""220"" />
<slot kind=""28"" offset=""281"" />
<slot kind=""28"" offset=""281"" ordinal=""1"" />
<slot kind=""28"" offset=""261"" />
<slot kind=""28"" offset=""281"" ordinal=""2"" />
<slot kind=""28"" offset=""281"" ordinal=""3"" />
<slot kind=""28"" offset=""281"" ordinal=""4"" />
<slot kind=""28"" offset=""281"" ordinal=""5"" />
<slot kind=""4"" offset=""307"" />
<slot kind=""4"" offset=""376"" />
<slot kind=""3"" offset=""410"" />
......
......@@ -3,12 +3,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.CodeGen
......@@ -3391,7 +3389,7 @@ public sealed class JsonSerializerOptions
var v = CompileAndVerify(source, options: TestOptions.DebugExe);
v.VerifyIL("Program.<Serialize>d__1.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", @"
{
{
// Code size 184 (0xb8)
.maxstack 3
.locals init (int V_0,
......@@ -3478,8 +3476,125 @@ .maxstack 3
IL_00b1: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()""
IL_00b6: nop
IL_00b7: ret
}
}
", sequencePoints: "Program.Serialize");
}
[Fact, WorkItem(37461, "https://github.com/dotnet/roslyn/issues/37461")]
public void ShouldNotSpillStackallocToField_01()
{
var source = @"
using System;
using System.Threading.Tasks;
public class P
{
static async Task Main()
{
await Async1(F1(), G(F2(), stackalloc int[] { 40, 500, 6000 }));
}
static int F1() => 70000;
static int F2() => 800000;
static int G(int k, Span<int> span) => k + span.Length + span[0] + span[1] + span[2];
static Task Async1(int k, int i)
{
Console.WriteLine(k + i);
return Task.Delay(1);
}
}
";
var expectedOutput = @"876543";
var comp = CreateCompilationWithMscorlibAndSpan(source, options: TestOptions.DebugExe);
comp.VerifyDiagnostics();
var v = CompileAndVerify(
compilation: comp,
expectedOutput: expectedOutput,
verify: Verification.Fails // localloc is not verifiable.
);
comp = CreateCompilationWithMscorlibAndSpan(source, options: TestOptions.ReleaseExe);
comp.VerifyDiagnostics();
v = CompileAndVerify(
compilation: comp,
expectedOutput: expectedOutput,
verify: Verification.Fails // localloc is not verifiable.
);
}
[Fact, WorkItem(37461, "https://github.com/dotnet/roslyn/issues/37461")]
public void ShouldNotSpillStackallocToField_02()
{
var source = @"
using System;
using System.Threading.Tasks;
public class P
{
static async Task Main()
{
await Async1(F1(), G(F2(), stackalloc int[] { 40, await Task.FromResult(500), 6000 }));
}
static int F1() => 70000;
static int F2() => 800000;
static int G(int k, Span<int> span) => k + span.Length + span[0] + span[1] + span[2];
static Task Async1(int k, int i)
{
Console.WriteLine(k + i);
return Task.Delay(1);
}
}
";
var expectedOutput = @"876543";
var comp = CreateCompilationWithMscorlibAndSpan(source, options: TestOptions.DebugExe);
comp.VerifyDiagnostics();
var v = CompileAndVerify(
compilation: comp,
expectedOutput: expectedOutput,
verify: Verification.Fails // localloc is not verifiable.
);
comp = CreateCompilationWithMscorlibAndSpan(source, options: TestOptions.ReleaseExe);
comp.VerifyDiagnostics();
v = CompileAndVerify(
compilation: comp,
expectedOutput: expectedOutput,
verify: Verification.Fails // localloc is not verifiable.
);
}
[Fact, WorkItem(37461, "https://github.com/dotnet/roslyn/issues/37461")]
public void ShouldNotSpillStackallocToField_03()
{
var source = @"
using System;
using System.Threading.Tasks;
public class P
{
static async Task Main()
{
await Async1(F1(), G(F2(), stackalloc int[] { 1, 2, 3 }, await F3()));
}
static object F1() => 1;
static object F2() => 1;
static Task<object> F3() => Task.FromResult<object>(1);
static int G(object obj, Span<int> span, object o2) => span.Length;
static async Task Async1(Object obj, int i) { await Task.Delay(1); }
}
";
foreach (var options in new[] { TestOptions.DebugExe, TestOptions.ReleaseExe })
{
var comp = CreateCompilationWithMscorlibAndSpan(source, options: options);
comp.VerifyDiagnostics();
comp.VerifyEmitDiagnostics(
// (9,66): error CS4007: 'await' cannot be used in an expression containing the type 'System.Span<int>'
// await Async1(F1(), G(F2(), stackalloc int[] { 1, 2, 3 }, await F3()));
Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "await F3()").WithArguments("System.Span<int>").WithLocation(9, 66)
);
}
}
}
}
......@@ -16211,7 +16211,7 @@ .maxstack 2
}");
comp = CreateCompilationWithMscorlibAndSpan(source, TestOptions.DebugExe);
CompileAndVerify(comp, expectedOutput: expectedOutput, verify: Verification.Fails).VerifyIL("Test.Main", @"
{
{
// Code size 54 (0x36)
.maxstack 2
.locals init (System.Span<int> V_0, //x
......@@ -16236,7 +16236,8 @@ .maxstack 2
IL_002f: call ""void System.Console.Write(int)""
IL_0034: nop
IL_0035: ret
}");
}
");
}
[Fact]
......@@ -16297,7 +16298,7 @@ .maxstack 2
}");
comp = CreateCompilationWithMscorlibAndSpan(source, TestOptions.DebugExe);
CompileAndVerify(comp, expectedOutput: "12345", verify: Verification.Fails).VerifyIL("Test.Main", @"
{
{
// Code size 56 (0x38)
.maxstack 2
.locals init (int V_0, //i
......@@ -16338,7 +16339,8 @@ .maxstack 2
IL_0033: ldloc.s V_4
IL_0035: brtrue.s IL_0005
IL_0037: ret
}");
}
");
}
[Fact]
......@@ -16356,7 +16358,7 @@ public static void Main()
}";
var comp = CreateCompilationWithMscorlibAndSpan(source, TestOptions.ReleaseExe);
CompileAndVerify(comp, expectedOutput: "6", verify: Verification.Fails).VerifyIL("Test.Main", @"
{
{
// Code size 25 (0x19)
.maxstack 2
.locals init (System.Span<int> V_0)
......@@ -16371,10 +16373,11 @@ .locals init (System.Span<int> V_0)
IL_000e: call ""int Test.M(int, System.Span<int>)""
IL_0013: call ""void System.Console.WriteLine(int)""
IL_0018: ret
}");
}
");
comp = CreateCompilationWithMscorlibAndSpan(source, TestOptions.DebugExe);
CompileAndVerify(comp, expectedOutput: "6", verify: Verification.Fails).VerifyIL("Test.Main", @"
{
{
// Code size 27 (0x1b)
.maxstack 2
.locals init (System.Span<int> V_0)
......@@ -16391,7 +16394,8 @@ .locals init (System.Span<int> V_0)
IL_0014: call ""void System.Console.WriteLine(int)""
IL_0019: nop
IL_001a: ret
}");
}
");
}
[Fact]
......@@ -16410,7 +16414,7 @@ public static void Main()
}";
var comp = CreateCompilationWithMscorlibAndSpan(source, TestOptions.ReleaseExe);
CompileAndVerify(comp, expectedOutput: "6", verify: Verification.Fails).VerifyIL("Test.Main", @"
{
{
// Code size 27 (0x1b)
.maxstack 2
.locals init (int V_0,
......@@ -16428,10 +16432,11 @@ .maxstack 2
IL_0010: call ""int Test.M(int, System.Span<int>)""
IL_0015: call ""void System.Console.WriteLine(int)""
IL_001a: ret
}");
}
");
comp = CreateCompilationWithMscorlibAndSpan(source, TestOptions.DebugExe);
CompileAndVerify(comp, expectedOutput: "6", verify: Verification.Fails).VerifyIL("Test.Main", @"
{
{
// Code size 31 (0x1f)
.maxstack 2
.locals init (int V_0, //z
......@@ -16454,7 +16459,8 @@ .maxstack 2
IL_0018: call ""void System.Console.WriteLine(int)""
IL_001d: nop
IL_001e: ret
}");
}
");
}
[Fact]
......@@ -16473,7 +16479,7 @@ public static void Main()
}";
var comp = CreateCompilationWithMscorlibAndSpan(source, TestOptions.ReleaseExe);
CompileAndVerify(comp, expectedOutput: "6", verify: Verification.Fails).VerifyIL("Test.Main", @"
{
{
// Code size 70 (0x46)
.maxstack 4
.locals init (int V_0,
......@@ -16494,7 +16500,7 @@ .maxstack 4
IL_000d: stind.i4
IL_000e: ldc.i4.2
IL_000f: newobj ""System.Span<int>..ctor(void*, int)""
IL_0014: stloc.1
IL_0014: stloc.2
IL_0015: ldc.i4.s 12
IL_0017: conv.u
IL_0018: localloc
......@@ -16504,7 +16510,7 @@ .maxstack 4
IL_001d: dup
IL_001e: ldc.i4.4
IL_001f: add
IL_0020: ldloca.s V_1
IL_0020: ldloca.s V_2
IL_0022: call ""int System.Span<int>.Length.get""
IL_0027: stind.i4
IL_0028: dup
......@@ -16517,17 +16523,18 @@ .maxstack 4
IL_002f: stind.i4
IL_0030: ldc.i4.3
IL_0031: newobj ""System.Span<int>..ctor(void*, int)""
IL_0036: stloc.2
IL_0036: stloc.1
IL_0037: ldloc.0
IL_0038: ldloca.s V_2
IL_0038: ldloca.s V_1
IL_003a: call ""int System.Span<int>.Length.get""
IL_003f: mul
IL_0040: call ""void System.Console.WriteLine(int)""
IL_0045: ret
}");
}
");
comp = CreateCompilationWithMscorlibAndSpan(source, TestOptions.DebugExe);
CompileAndVerify(comp, expectedOutput: "6", verify: Verification.Fails).VerifyIL("Test.Main", @"
{
{
// Code size 74 (0x4a)
.maxstack 4
.locals init (int V_0, //z
......@@ -16552,7 +16559,7 @@ .maxstack 4
IL_0010: stind.i4
IL_0011: ldc.i4.2
IL_0012: newobj ""System.Span<int>..ctor(void*, int)""
IL_0017: stloc.2
IL_0017: stloc.3
IL_0018: ldc.i4.s 12
IL_001a: conv.u
IL_001b: localloc
......@@ -16562,7 +16569,7 @@ .maxstack 4
IL_0020: dup
IL_0021: ldc.i4.4
IL_0022: add
IL_0023: ldloca.s V_2
IL_0023: ldloca.s V_3
IL_0025: call ""int System.Span<int>.Length.get""
IL_002a: stind.i4
IL_002b: dup
......@@ -16575,15 +16582,16 @@ .maxstack 4
IL_0032: stind.i4
IL_0033: ldc.i4.3
IL_0034: newobj ""System.Span<int>..ctor(void*, int)""
IL_0039: stloc.3
IL_0039: stloc.2
IL_003a: ldloc.1
IL_003b: ldloca.s V_3
IL_003b: ldloca.s V_2
IL_003d: call ""int System.Span<int>.Length.get""
IL_0042: mul
IL_0043: call ""void System.Console.WriteLine(int)""
IL_0048: nop
IL_0049: ret
}");
}
");
}
[Fact]
......
......@@ -3165,14 +3165,13 @@ public static void Main()
}
";
var v = CompileAndVerify(source, options: TestOptions.DebugExe);
v.VerifyIL(qualifiedMethodName: "Program.Main",
@"{
// Code size 55 (0x37)
v.VerifyIL(qualifiedMethodName: "Program.Main", @"
{
// Code size 53 (0x35)
.maxstack 2
.locals init (int V_0, //i
Program V_1, //y
Program V_2,
Program V_3)
Program V_2)
// sequence point: {
IL_0000: nop
// sequence point: int i = 0;
......@@ -3196,17 +3195,15 @@ .maxstack 2
IL_0023: stloc.2
IL_0024: br.s IL_0026
IL_0026: ldloc.2
IL_0027: stloc.3
IL_0028: ldloc.3
IL_0029: callvirt ""Program Program.Chain()""
IL_002e: stloc.1
IL_0027: callvirt ""Program Program.Chain()""
IL_002c: stloc.1
// sequence point: y.Chain2();
IL_002f: ldloc.1
IL_0030: callvirt ""Program Program.Chain2()""
IL_0035: pop
IL_002d: ldloc.1
IL_002e: callvirt ""Program Program.Chain2()""
IL_0033: pop
// sequence point: }
IL_0036: ret
}
IL_0034: ret
}
", sequencePoints: "Program.Main", source: source);
}
......@@ -3236,14 +3233,13 @@ static bool M(object o)
var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
if (options.OptimizationLevel == OptimizationLevel.Debug)
{
compVerifier.VerifyIL("Class1.M",
@"{
// Code size 39 (0x27)
compVerifier.VerifyIL("Class1.M", @"
{
// Code size 37 (0x25)
.maxstack 2
.locals init (bool V_0,
int V_1,
bool V_2,
bool V_3)
bool V_2)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: isinst ""int""
......@@ -3263,12 +3259,11 @@ .maxstack 2
IL_001d: br.s IL_001f
IL_001f: ldloc.0
IL_0020: stloc.2
IL_0021: ldloc.2
IL_0022: stloc.3
IL_0023: br.s IL_0025
IL_0025: ldloc.3
IL_0026: ret
}");
IL_0021: br.s IL_0023
IL_0023: ldloc.2
IL_0024: ret
}
");
}
else
{
......
......@@ -4052,17 +4052,15 @@ static object G(object o1, object o2)
ImmutableArray.Create(new SemanticEdit(SemanticEditKind.Update, method0, method1, GetEquivalentNodesMap(method1, method0), preserveLocalVariables: true)));
diff1.VerifyIL("C.G", @"
{
// Code size 58 (0x3a)
{
// Code size 54 (0x36)
.maxstack 1
.locals init (int V_0, //a
string V_1, //b
[int] V_2,
[int] V_3,
[object] V_4,
int V_5,
int V_6,
object V_7)
[object] V_3,
int V_4,
object V_5)
-IL_0000: nop
-IL_0001: ldarg.0
IL_0002: isinst ""int""
......@@ -4078,20 +4076,18 @@ .maxstack 1
IL_001a: br.s IL_0023
IL_001c: br.s IL_001e
IL_001e: ldloc.0
IL_001f: stloc.s V_5
IL_001f: stloc.s V_4
IL_0021: br.s IL_0028
IL_0023: ldc.i4.0
IL_0024: stloc.s V_5
IL_0024: stloc.s V_4
IL_0026: br.s IL_0028
IL_0028: ldloc.s V_5
IL_002a: stloc.s V_6
IL_002c: ldloc.s V_6
IL_002e: box ""int""
IL_0033: stloc.s V_7
IL_0035: br.s IL_0037
-IL_0037: ldloc.s V_7
IL_0039: ret
}
IL_0028: ldloc.s V_4
IL_002a: box ""int""
IL_002f: stloc.s V_5
IL_0031: br.s IL_0033
-IL_0033: ldloc.s V_5
IL_0035: ret
}
", methodToken: diff1.UpdatedMethods.Single());
}
......@@ -4130,24 +4126,20 @@ static object G(object o)
ImmutableArray.Create(new SemanticEdit(SemanticEditKind.Update, method0, method1, GetEquivalentNodesMap(method1, method0), preserveLocalVariables: true)));
diff1.VerifyIL("C.G", @"
{
// Code size 68 (0x44)
{
// Code size 60 (0x3c)
.maxstack 1
.locals init (int V_0, //i
[int] V_1,
[int] V_2,
[int] V_3,
[int] V_4,
[object] V_5,
int V_6,
int V_7,
int V_8,
int V_9,
object V_10)
[object] V_3,
int V_4,
int V_5,
object V_6)
-IL_0000: nop
-IL_0001: ldarg.0
IL_0002: isinst ""int""
IL_0007: brfalse.s IL_002d
IL_0007: brfalse.s IL_0029
IL_0009: ldarg.0
IL_000a: unbox.any ""int""
IL_000f: stloc.0
......@@ -4157,28 +4149,24 @@ .maxstack 1
IL_0015: brfalse.s IL_0019
IL_0017: br.s IL_001e
IL_0019: ldc.i4.1
IL_001a: stloc.s V_8
IL_001a: stloc.s V_5
IL_001c: br.s IL_0023
IL_001e: ldc.i4.2
IL_001f: stloc.s V_8
IL_001f: stloc.s V_5
IL_0021: br.s IL_0023
IL_0023: ldloc.s V_8
IL_0025: stloc.s V_9
IL_0027: ldloc.s V_9
IL_0029: stloc.s V_6
IL_002b: br.s IL_0032
IL_002d: ldc.i4.3
IL_002e: stloc.s V_6
IL_0030: br.s IL_0032
IL_0032: ldloc.s V_6
IL_0034: stloc.s V_7
IL_0036: ldloc.s V_7
IL_0038: box ""int""
IL_003d: stloc.s V_10
IL_003f: br.s IL_0041
-IL_0041: ldloc.s V_10
IL_0043: ret
}
IL_0023: ldloc.s V_5
IL_0025: stloc.s V_4
IL_0027: br.s IL_002e
IL_0029: ldc.i4.3
IL_002a: stloc.s V_4
IL_002c: br.s IL_002e
IL_002e: ldloc.s V_4
IL_0030: box ""int""
IL_0035: stloc.s V_6
IL_0037: br.s IL_0039
-IL_0039: ldloc.s V_6
IL_003b: ret
}
", methodToken: diff1.UpdatedMethods.Single());
}
......@@ -4345,56 +4333,48 @@ static object G()
ImmutableArray.Create(new SemanticEdit(SemanticEditKind.Update, method0, method1, GetEquivalentNodesMap(method1, method0), preserveLocalVariables: true)));
diff1.VerifyIL("C.G", @"
{
// Code size 65 (0x41)
{
// Code size 57 (0x39)
.maxstack 2
.locals init (int V_0, //x
[int] V_1,
[object] V_2,
[int] V_3,
[int] V_4,
[int] V_5,
[object] V_6,
[object] V_4,
int V_5,
object V_6,
int V_7,
object V_8,
int V_9,
int V_10,
int V_11,
object V_12)
object V_8)
-IL_0000: nop
-IL_0001: ldloca.s V_0
IL_0003: call ""object C.N(out int)""
IL_0008: stloc.s V_8
IL_000a: ldloc.s V_8
IL_0008: stloc.s V_6
IL_000a: ldloc.s V_6
IL_000c: brfalse.s IL_0010
IL_000e: br.s IL_002a
IL_000e: br.s IL_0026
IL_0010: ldloc.0
IL_0011: ldc.i4.1
IL_0012: beq.s IL_0016
IL_0014: br.s IL_001b
IL_0016: ldc.i4.1
IL_0017: stloc.s V_10
IL_0017: stloc.s V_7
IL_0019: br.s IL_0020
IL_001b: ldc.i4.2
IL_001c: stloc.s V_10
IL_001c: stloc.s V_7
IL_001e: br.s IL_0020
IL_0020: ldloc.s V_10
IL_0022: stloc.s V_11
IL_0024: ldloc.s V_11
IL_0026: stloc.s V_7
IL_0028: br.s IL_002f
IL_002a: ldc.i4.1
IL_002b: stloc.s V_7
IL_002d: br.s IL_002f
IL_002f: ldloc.s V_7
IL_0031: stloc.s V_9
IL_0033: ldloc.s V_9
IL_0035: box ""int""
IL_003a: stloc.s V_12
IL_003c: br.s IL_003e
-IL_003e: ldloc.s V_12
IL_0040: ret
}
IL_0020: ldloc.s V_7
IL_0022: stloc.s V_5
IL_0024: br.s IL_002b
IL_0026: ldc.i4.1
IL_0027: stloc.s V_5
IL_0029: br.s IL_002b
IL_002b: ldloc.s V_5
IL_002d: box ""int""
IL_0032: stloc.s V_8
IL_0034: br.s IL_0036
-IL_0036: ldloc.s V_8
IL_0038: ret
}
", methodToken: diff1.UpdatedMethods.Single());
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册