提交 841044b0 编写于 作者: N Neal Gafter 提交者: GitHub

Share pattern-matching temps when they are the same type. (#19378)

Fixes #19280
上级 2223e156
......@@ -64,7 +64,7 @@ internal override BoundStatement BindSwitchExpressionAndSections(SwitchStatement
BoundPatternSwitchLabel defaultLabel;
bool isComplete;
ImmutableArray<BoundPatternSwitchSection> switchSections =
BindPatternSwitchSections(boundSwitchExpression, node.Sections, originalBinder, out defaultLabel, out isComplete, diagnostics);
BindPatternSwitchSections(originalBinder, out defaultLabel, out isComplete, diagnostics);
var locals = GetDeclaredLocalsForScope(node);
var functions = GetDeclaredLocalFunctionsForScope(node);
return new BoundPatternSwitchStatement(
......@@ -101,8 +101,6 @@ internal override void BindPatternSwitchLabelForInference(CasePatternSwitchLabel
/// the decision tree.
/// </summary>
private ImmutableArray<BoundPatternSwitchSection> BindPatternSwitchSections(
BoundExpression boundSwitchExpression,
SyntaxList<SwitchSectionSyntax> sections,
Binder originalBinder,
out BoundPatternSwitchLabel defaultLabel,
out bool isComplete,
......@@ -115,11 +113,11 @@ internal override void BindPatternSwitchLabelForInference(CasePatternSwitchLabel
// Bind match sections
var boundPatternSwitchSectionsBuilder = ArrayBuilder<BoundPatternSwitchSection>.GetInstance();
SubsumptionDiagnosticBuilder subsumption = new SubsumptionDiagnosticBuilder(ContainingMemberOrLambda, this.Conversions, boundSwitchExpression);
foreach (var sectionSyntax in sections)
SubsumptionDiagnosticBuilder subsumption = new SubsumptionDiagnosticBuilder(ContainingMemberOrLambda, SwitchSyntax, this.Conversions, SwitchGoverningExpression);
foreach (var sectionSyntax in SwitchSyntax.Sections)
{
boundPatternSwitchSectionsBuilder.Add(BindPatternSwitchSection(
boundSwitchExpression, sectionSyntax, originalBinder, ref defaultLabel, ref someValueMatched, subsumption, diagnostics));
SwitchGoverningExpression, sectionSyntax, originalBinder, ref defaultLabel, ref someValueMatched, subsumption, diagnostics));
}
isComplete = defaultLabel != null || subsumption.IsComplete || someValueMatched;
......
......@@ -20,11 +20,12 @@ internal class SubsumptionDiagnosticBuilder : DecisionTreeBuilder
private readonly DecisionTree _subsumptionTree;
internal SubsumptionDiagnosticBuilder(Symbol enclosingSymbol,
Conversions conversions,
BoundExpression expression)
: base(enclosingSymbol, conversions)
SyntaxNode syntax,
Conversions conversions,
BoundExpression expression)
: base(enclosingSymbol, syntax, conversions)
{
_subsumptionTree = DecisionTree.Create(expression, expression.Type, enclosingSymbol);
_subsumptionTree = CreateEmptyDecisionTree(expression);
}
/// <summary>
......
......@@ -78,36 +78,6 @@ public DecisionTree(BoundExpression expression, TypeSymbol type, LocalSymbol tem
Debug.Assert(this.Type != null);
}
/// <summary>
/// Create a fresh decision tree for the given input expression of the given type.
/// </summary>
public static DecisionTree Create(BoundExpression expression, TypeSymbol type, Symbol enclosingSymbol)
{
Debug.Assert(expression.Type == type);
LocalSymbol temp = null;
if (expression.ConstantValue == null)
{
// Unless it is a constant, the decision tree acts on a copy of the input expression.
// We create a temp to represent that copy. Lowering will assign into this temp.
temp = new SynthesizedLocal(enclosingSymbol as MethodSymbol, type, SynthesizedLocalKind.PatternMatching, expression.Syntax, false, RefKind.None);
expression = new BoundLocal(expression.Syntax, temp, null, type);
}
if (type.CanContainNull() || type.SpecialType == SpecialType.None)
{
// We need the ByType decision tree to separate null from non-null values.
// Note that, for the purpose of the decision tree (and subsumption), we
// ignore the fact that the input may be a constant, and therefore always
// or never null.
return new ByType(expression, type, temp);
}
else
{
// If it is a (e.g. builtin) value type, we can switch on its (constant) values.
return new ByValue(expression, type, temp);
}
}
/// <summary>
/// A decision tree node that branches based on (1) whether the input value is null, (2) the runtime
/// type of the input expression, and finally (3) a default decision tree if nothing in the previous
......
......@@ -26,17 +26,63 @@ internal abstract class DecisionTreeBuilder
protected readonly Symbol _enclosingSymbol;
protected readonly Conversions _conversions;
protected HashSet<DiagnosticInfo> _useSiteDiagnostics = new HashSet<DiagnosticInfo>();
private Dictionary<TypeSymbol, LocalSymbol> localByType = new Dictionary<TypeSymbol, LocalSymbol>();
protected DecisionTreeBuilder(
Symbol enclosingSymbol,
SyntaxNode syntax,
Conversions conversions)
{
this._enclosingSymbol = enclosingSymbol;
this.Syntax = syntax;
this._conversions = conversions;
}
protected SyntaxNode Syntax { private get; set; }
private LocalSymbol PatternMatchingTemp(TypeSymbol type)
{
LocalSymbol temp;
if (!localByType.TryGetValue(type, out temp))
{
temp = new SynthesizedLocal(_enclosingSymbol as MethodSymbol, type, SynthesizedLocalKind.PatternMatching, Syntax);
localByType.Add(type, temp);
}
return temp;
}
/// <summary>
/// Create a fresh decision tree for the given input expression of the given type.
/// </summary>
protected DecisionTree CreateEmptyDecisionTree(BoundExpression expression)
{
var type = expression.Type;
LocalSymbol temp = null;
if (expression.ConstantValue == null)
{
// Unless it is a constant, the decision tree acts on a copy of the input expression.
// We create a temp to represent that copy. Lowering will assign into this temp.
temp = PatternMatchingTemp(type);
expression = new BoundLocal(expression.Syntax, temp, null, type);
}
if (type.CanContainNull() || type.SpecialType == SpecialType.None)
{
// We need the ByType decision tree to separate null from non-null values.
// Note that, for the purpose of the decision tree (and subsumption), we
// ignore the fact that the input may be a constant, and therefore always
// or never null.
return new DecisionTree.ByType(expression, type, temp);
}
else
{
// If it is a (e.g. builtin) value type, we can switch on its (constant) values.
return new DecisionTree.ByValue(expression, type, temp);
}
}
protected DecisionTree AddToDecisionTree(DecisionTree decisionTree, SyntaxNode sectionSyntax, BoundPatternSwitchLabel label)
{
var pattern = label.Pattern;
......@@ -237,7 +283,7 @@ private DecisionTree AddByValue(DecisionTree.ByType byType, BoundConstantPattern
if (forType == null)
{
var type = value.Value.Type;
var localSymbol = new SynthesizedLocal(_enclosingSymbol as MethodSymbol, type, SynthesizedLocalKind.PatternMatching, Syntax, false, RefKind.None);
var localSymbol = PatternMatchingTemp(type);
var narrowedExpression = new BoundLocal(Syntax, localSymbol, null, type);
forType = new DecisionTree.ByValue(narrowedExpression, value.Value.Type.TupleUnderlyingTypeOrSelf(), localSymbol);
byType.TypeAndDecision.Add(new KeyValuePair<TypeSymbol, DecisionTree>(value.Value.Type, forType));
......@@ -338,7 +384,7 @@ private DecisionTree AddByType(DecisionTree.ByType byType, TypeSymbol type, Deci
if (result == null)
{
var localSymbol = new SynthesizedLocal(_enclosingSymbol as MethodSymbol, type, SynthesizedLocalKind.PatternMatching, Syntax, false, RefKind.None);
var localSymbol = PatternMatchingTemp(type);
var expression = new BoundLocal(Syntax, localSymbol, null, type);
result = makeDecision(expression, type);
Debug.Assert(result.Temp == null);
......
......@@ -38,7 +38,7 @@ private class PatternSwitchLocalRewriter : DecisionTreeBuilder
private ArrayBuilder<BoundStatement> _loweredDecisionTree = ArrayBuilder<BoundStatement>.GetInstance();
private PatternSwitchLocalRewriter(LocalRewriter localRewriter, BoundPatternSwitchStatement node)
: base(localRewriter._factory.CurrentMethod, localRewriter._factory.Compilation.Conversions)
: base(localRewriter._factory.CurrentMethod, node.Syntax, localRewriter._factory.Compilation.Conversions)
{
this._localRewriter = localRewriter;
this._factory = localRewriter._factory;
......@@ -59,15 +59,9 @@ private BoundStatement MakeLoweredForm(BoundPatternSwitchStatement node)
var expression = _localRewriter.VisitExpression(node.Expression);
var result = ArrayBuilder<BoundStatement>.GetInstance();
// if the expression is "too complex", we copy it to a temp.
LocalSymbol initialTemp = null;
if (expression.ConstantValue == null)
{
initialTemp = _factory.SynthesizedLocal(expression.Type, expression.Syntax);
result.Add(_factory.Assignment(_factory.Local(initialTemp), expression));
expression = _factory.Local(initialTemp);
// EnC: We need to insert a hidden sequence point to handle function remapping in case
// EnC: We need to insert a hidden sequence point to handle function remapping in case
// the containing method is edited while methods invoked in the expression are being executed.
if (!node.WasCompilerGenerated && _localRewriter.Instrument)
{
......@@ -85,7 +79,6 @@ private BoundStatement MakeLoweredForm(BoundPatternSwitchStatement node)
}
// at this point the end of result is unreachable.
_declaredTemps.AddOptional(initialTemp);
_declaredTemps.AddRange(node.InnerLocals);
// output the sections of code
......@@ -148,7 +141,7 @@ private void LowerPatternSwitch(BoundExpression loweredExpression, BoundPatternS
BoundExpression loweredExpression,
BoundPatternSwitchStatement node)
{
var loweredDecisionTree = DecisionTree.Create(loweredExpression, loweredExpression.Type, _enclosingSymbol);
var loweredDecisionTree = CreateEmptyDecisionTree(loweredExpression);
BoundPatternSwitchLabel defaultLabel = null;
SyntaxNode defaultSection = null;
foreach (var section in node.SwitchSections)
......@@ -223,15 +216,11 @@ private void LowerDecisionTree(BoundExpression expression, DecisionTree decision
_loweredDecisionTree.Add(_factory.Assignment(decisionTree.Expression, convertedExpression));
}
// If the temp is not yet in the declared temp set, add it now
if (_declaredTempSet.Add(decisionTree.Temp))
{
_declaredTemps.Add(decisionTree.Temp);
}
else
{
// we should only attempt to declare each temp once.
throw ExceptionUtilities.Unreachable;
}
}
switch (decisionTree.Kind)
......
......@@ -2850,7 +2850,6 @@ class Student : Person { public double GPA; }
<slot kind=""35"" offset=""11"" />
<slot kind=""35"" offset=""46"" />
<slot kind=""35"" offset=""237"" />
<slot kind=""temp"" />
<slot kind=""0"" offset=""59"" />
<slot kind=""0"" offset=""163"" />
<slot kind=""0"" offset=""250"" />
......@@ -2861,32 +2860,31 @@ class Student : Person { public double GPA; }
<sequencePoints>
<entry offset=""0x0"" startLine=""19"" startColumn=""5"" endLine=""19"" endColumn=""6"" />
<entry offset=""0x1"" startLine=""20"" startColumn=""9"" endLine=""20"" endColumn=""19"" />
<entry offset=""0x6"" hidden=""true"" />
<entry offset=""0x2a"" hidden=""true"" />
<entry offset=""0x2d"" startLine=""22"" startColumn=""28"" endLine=""22"" endColumn=""44"" />
<entry offset=""0x41"" startLine=""23"" startColumn=""17"" endLine=""23"" endColumn=""57"" />
<entry offset=""0x62"" hidden=""true"" />
<entry offset=""0x67"" startLine=""25"" startColumn=""17"" endLine=""25"" endColumn=""57"" />
<entry offset=""0x88"" hidden=""true"" />
<entry offset=""0x8d"" startLine=""27"" startColumn=""17"" endLine=""27"" endColumn=""59"" />
<entry offset=""0xa9"" startLine=""29"" startColumn=""17"" endLine=""29"" endColumn=""43"" />
<entry offset=""0xbd"" startLine=""31"" startColumn=""5"" endLine=""31"" endColumn=""6"" />
<entry offset=""0x4"" hidden=""true"" />
<entry offset=""0x28"" hidden=""true"" />
<entry offset=""0x2a"" startLine=""22"" startColumn=""28"" endLine=""22"" endColumn=""44"" />
<entry offset=""0x3d"" startLine=""23"" startColumn=""17"" endLine=""23"" endColumn=""57"" />
<entry offset=""0x5c"" hidden=""true"" />
<entry offset=""0x61"" startLine=""25"" startColumn=""17"" endLine=""25"" endColumn=""57"" />
<entry offset=""0x82"" hidden=""true"" />
<entry offset=""0x87"" startLine=""27"" startColumn=""17"" endLine=""27"" endColumn=""59"" />
<entry offset=""0xa3"" startLine=""29"" startColumn=""17"" endLine=""29"" endColumn=""43"" />
<entry offset=""0xb7"" startLine=""31"" startColumn=""5"" endLine=""31"" endColumn=""6"" />
</sequencePoints>
<scope startOffset=""0x0"" endOffset=""0xc0"">
<scope startOffset=""0x2a"" endOffset=""0x62"">
<local name=""s"" il_index=""4"" il_start=""0x2a"" il_end=""0x62"" attributes=""0"" />
<scope startOffset=""0x0"" endOffset=""0xba"">
<scope startOffset=""0x28"" endOffset=""0x5c"">
<local name=""s"" il_index=""3"" il_start=""0x28"" il_end=""0x5c"" attributes=""0"" />
</scope>
<scope startOffset=""0x62"" endOffset=""0x88"">
<local name=""s"" il_index=""5"" il_start=""0x62"" il_end=""0x88"" attributes=""0"" />
<scope startOffset=""0x5c"" endOffset=""0x82"">
<local name=""s"" il_index=""4"" il_start=""0x5c"" il_end=""0x82"" attributes=""0"" />
</scope>
<scope startOffset=""0x88"" endOffset=""0xa9"">
<local name=""t"" il_index=""6"" il_start=""0x88"" il_end=""0xa9"" attributes=""0"" />
<scope startOffset=""0x82"" endOffset=""0xa3"">
<local name=""t"" il_index=""5"" il_start=""0x82"" il_end=""0xa3"" attributes=""0"" />
</scope>
</scope>
</method>
</methods>
</symbols>"
);
</symbols>");
}
[Fact]
......@@ -2943,7 +2941,6 @@ class Student : Person { public double GPA; }
<slot kind=""35"" offset=""11"" />
<slot kind=""35"" offset=""46"" />
<slot kind=""35"" offset=""249"" />
<slot kind=""temp"" />
<slot kind=""1"" offset=""11"" />
<slot kind=""21"" offset=""0"" />
</encLocalSlotMap>
......@@ -2961,27 +2958,26 @@ class Student : Person { public double GPA; }
<entry offset=""0x0"" hidden=""true"" />
<entry offset=""0xd"" startLine=""19"" startColumn=""5"" endLine=""19"" endColumn=""6"" />
<entry offset=""0xe"" hidden=""true"" />
<entry offset=""0x20"" hidden=""true"" />
<entry offset=""0x45"" hidden=""true"" />
<entry offset=""0x4c"" startLine=""22"" startColumn=""28"" endLine=""22"" endColumn=""44"" />
<entry offset=""0x64"" startLine=""23"" startColumn=""17"" endLine=""23"" endColumn=""63"" />
<entry offset=""0x74"" hidden=""true"" />
<entry offset=""0x7d"" startLine=""25"" startColumn=""17"" endLine=""25"" endColumn=""63"" />
<entry offset=""0x8d"" hidden=""true"" />
<entry offset=""0x97"" startLine=""27"" startColumn=""17"" endLine=""27"" endColumn=""65"" />
<entry offset=""0xa7"" startLine=""29"" startColumn=""17"" endLine=""29"" endColumn=""49"" />
<entry offset=""0xb7"" startLine=""31"" startColumn=""5"" endLine=""31"" endColumn=""6"" />
<entry offset=""0x1c"" hidden=""true"" />
<entry offset=""0x41"" hidden=""true"" />
<entry offset=""0x48"" startLine=""22"" startColumn=""28"" endLine=""22"" endColumn=""44"" />
<entry offset=""0x60"" startLine=""23"" startColumn=""17"" endLine=""23"" endColumn=""63"" />
<entry offset=""0x70"" hidden=""true"" />
<entry offset=""0x79"" startLine=""25"" startColumn=""17"" endLine=""25"" endColumn=""63"" />
<entry offset=""0x89"" hidden=""true"" />
<entry offset=""0x93"" startLine=""27"" startColumn=""17"" endLine=""27"" endColumn=""65"" />
<entry offset=""0xa3"" startLine=""29"" startColumn=""17"" endLine=""29"" endColumn=""49"" />
<entry offset=""0xb3"" startLine=""31"" startColumn=""5"" endLine=""31"" endColumn=""6"" />
</sequencePoints>
<scope startOffset=""0x0"" endOffset=""0xba"">
<local name=""CS$&lt;&gt;8__locals0"" il_index=""0"" il_start=""0x0"" il_end=""0xba"" attributes=""0"" />
<scope startOffset=""0xe"" endOffset=""0xb7"">
<local name=""CS$&lt;&gt;8__locals1"" il_index=""1"" il_start=""0xe"" il_end=""0xb7"" attributes=""0"" />
<scope startOffset=""0x0"" endOffset=""0xb6"">
<local name=""CS$&lt;&gt;8__locals0"" il_index=""0"" il_start=""0x0"" il_end=""0xb6"" attributes=""0"" />
<scope startOffset=""0xe"" endOffset=""0xb3"">
<local name=""CS$&lt;&gt;8__locals1"" il_index=""1"" il_start=""0xe"" il_end=""0xb3"" attributes=""0"" />
</scope>
</scope>
</method>
</methods>
</symbols>"
);
</symbols>");
}
#endregion
......@@ -6476,113 +6472,106 @@ static void M(object o)
var c = CreateCompilationWithMscorlibAndSystemCore(source, options: TestOptions.DebugDll);
CompileAndVerify(c).VerifyIL("Program.M",
@"{
// Code size 202 (0xca)
// Code size 194 (0xc2)
.maxstack 2
.locals init (object V_0,
int V_1,
object V_2,
object V_3,
int? V_4,
object V_5,
int V_6,
int? V_3,
object V_4,
int V_5,
object V_6,
object V_7,
object V_8,
object V_9)
object V_8)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: stloc.2
IL_0003: ldloc.2
IL_0004: stloc.3
IL_0005: ldloc.3
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: brtrue.s IL_000c
IL_000a: br.s IL_005a
IL_000c: ldloc.0
IL_000d: isinst ""int?""
IL_0012: unbox.any ""int?""
IL_0017: stloc.s V_4
IL_0019: ldloca.s V_4
IL_001b: call ""int int?.GetValueOrDefault()""
IL_0020: stloc.1
IL_0021: ldloca.s V_4
IL_0023: call ""bool int?.HasValue.get""
IL_0028: brfalse.s IL_005a
IL_002a: ldloc.1
IL_002b: ldc.i4.1
IL_002c: sub
IL_002d: switch (
IL_0048,
IL_0050,
IL_0056,
IL_004e,
IL_0054)
IL_0046: br.s IL_005a
IL_0048: br.s IL_005c
IL_004a: br.s IL_0068
IL_004c: br.s IL_0076
IL_004e: br.s IL_0066
IL_0050: br.s IL_0061
IL_0052: br.s IL_005a
IL_0054: br.s IL_0072
IL_0056: br.s IL_006d
IL_0058: br.s IL_005a
IL_005a: br.s IL_0074
IL_005c: ldarg.0
IL_005d: brfalse.s IL_0066
IL_005f: br.s IL_004a
IL_0061: ldarg.0
IL_0062: brfalse.s IL_0066
IL_0064: br.s IL_0052
IL_0066: br.s IL_0078
IL_0068: ldarg.0
IL_0069: brtrue.s IL_0072
IL_006b: br.s IL_004c
IL_006d: ldarg.0
IL_006e: brtrue.s IL_0072
IL_0070: br.s IL_0058
IL_0072: br.s IL_0078
IL_0074: br.s IL_0078
IL_0076: br.s IL_0078
IL_0078: ldarg.0
IL_0079: stloc.2
IL_007a: ldloc.2
IL_007b: stloc.s V_7
IL_007d: ldloc.s V_7
IL_007f: stloc.s V_5
IL_0081: ldloc.s V_5
IL_0083: brtrue.s IL_0087
IL_0085: br.s IL_00b0
IL_0087: ldloc.s V_5
IL_0089: isinst ""int?""
IL_008e: unbox.any ""int?""
IL_0093: stloc.s V_4
IL_0095: ldloca.s V_4
IL_0097: call ""int int?.GetValueOrDefault()""
IL_009c: stloc.s V_6
IL_009e: ldloca.s V_4
IL_00a0: call ""bool int?.HasValue.get""
IL_00a5: brfalse.s IL_00b0
IL_00a7: ldloc.s V_6
IL_00a9: ldc.i4.1
IL_00aa: beq.s IL_00ae
IL_0004: stloc.0
IL_0005: ldloc.0
IL_0006: brtrue.s IL_000a
IL_0008: br.s IL_0057
IL_000a: ldloc.0
IL_000b: isinst ""int?""
IL_0010: unbox.any ""int?""
IL_0015: stloc.3
IL_0016: ldloca.s V_3
IL_0018: call ""int int?.GetValueOrDefault()""
IL_001d: stloc.1
IL_001e: ldloca.s V_3
IL_0020: call ""bool int?.HasValue.get""
IL_0025: brfalse.s IL_0057
IL_0027: ldloc.1
IL_0028: ldc.i4.1
IL_0029: sub
IL_002a: switch (
IL_0045,
IL_004d,
IL_0053,
IL_004b,
IL_0051)
IL_0043: br.s IL_0057
IL_0045: br.s IL_0059
IL_0047: br.s IL_0065
IL_0049: br.s IL_0073
IL_004b: br.s IL_0063
IL_004d: br.s IL_005e
IL_004f: br.s IL_0057
IL_0051: br.s IL_006f
IL_0053: br.s IL_006a
IL_0055: br.s IL_0057
IL_0057: br.s IL_0071
IL_0059: ldarg.0
IL_005a: brfalse.s IL_0063
IL_005c: br.s IL_0047
IL_005e: ldarg.0
IL_005f: brfalse.s IL_0063
IL_0061: br.s IL_004f
IL_0063: br.s IL_0075
IL_0065: ldarg.0
IL_0066: brtrue.s IL_006f
IL_0068: br.s IL_0049
IL_006a: ldarg.0
IL_006b: brtrue.s IL_006f
IL_006d: br.s IL_0055
IL_006f: br.s IL_0075
IL_0071: br.s IL_0075
IL_0073: br.s IL_0075
IL_0075: ldarg.0
IL_0076: stloc.s V_6
IL_0078: ldloc.s V_6
IL_007a: stloc.s V_4
IL_007c: ldloc.s V_4
IL_007e: brtrue.s IL_0082
IL_0080: br.s IL_00aa
IL_0082: ldloc.s V_4
IL_0084: isinst ""int?""
IL_0089: unbox.any ""int?""
IL_008e: stloc.3
IL_008f: ldloca.s V_3
IL_0091: call ""int int?.GetValueOrDefault()""
IL_0096: stloc.s V_5
IL_0098: ldloca.s V_3
IL_009a: call ""bool int?.HasValue.get""
IL_009f: brfalse.s IL_00aa
IL_00a1: ldloc.s V_5
IL_00a3: ldc.i4.1
IL_00a4: beq.s IL_00a8
IL_00a6: br.s IL_00aa
IL_00a8: br.s IL_00ac
IL_00aa: br.s IL_00ae
IL_00ac: br.s IL_00b0
IL_00ae: br.s IL_00b2
IL_00b0: br.s IL_00b4
IL_00b2: br.s IL_00b6
IL_00b4: br.s IL_00b6
IL_00b6: ldarg.0
IL_00b7: stloc.2
IL_00b8: ldloc.2
IL_00b9: stloc.s V_9
IL_00bb: ldloc.s V_9
IL_00bd: stloc.s V_8
IL_00bf: ldloc.s V_8
IL_00c1: brtrue.s IL_00c5
IL_00c3: br.s IL_00c5
IL_00c5: br.s IL_00c7
IL_00c7: br.s IL_00c9
IL_00c9: ret
IL_00ae: br.s IL_00b0
IL_00b0: ldarg.0
IL_00b1: stloc.s V_8
IL_00b3: ldloc.s V_8
IL_00b5: stloc.s V_7
IL_00b7: ldloc.s V_7
IL_00b9: brtrue.s IL_00bd
IL_00bb: br.s IL_00bd
IL_00bd: br.s IL_00bf
IL_00bf: br.s IL_00c1
IL_00c1: ret
}");
c.VerifyPdb(
@"<symbols>
......@@ -6595,7 +6584,6 @@ .maxstack 2
<encLocalSlotMap>
<slot kind=""35"" offset=""11"" />
<slot kind=""35"" offset=""46"" />
<slot kind=""temp"" />
<slot kind=""1"" offset=""11"" />
<slot kind=""temp"" />
<slot kind=""35"" offset=""378"" />
......@@ -6608,23 +6596,23 @@ .maxstack 2
<sequencePoints>
<entry offset=""0x0"" startLine=""4"" startColumn=""5"" endLine=""4"" endColumn=""6"" />
<entry offset=""0x1"" startLine=""5"" startColumn=""9"" endLine=""5"" endColumn=""19"" />
<entry offset=""0x5"" hidden=""true"" />
<entry offset=""0x5c"" startLine=""7"" startColumn=""20"" endLine=""7"" endColumn=""34"" />
<entry offset=""0x61"" startLine=""9"" startColumn=""20"" endLine=""9"" endColumn=""34"" />
<entry offset=""0x66"" startLine=""10"" startColumn=""17"" endLine=""10"" endColumn=""23"" />
<entry offset=""0x68"" startLine=""11"" startColumn=""20"" endLine=""11"" endColumn=""34"" />
<entry offset=""0x6d"" startLine=""13"" startColumn=""20"" endLine=""13"" endColumn=""34"" />
<entry offset=""0x72"" startLine=""14"" startColumn=""17"" endLine=""14"" endColumn=""23"" />
<entry offset=""0x74"" startLine=""16"" startColumn=""17"" endLine=""16"" endColumn=""23"" />
<entry offset=""0x76"" startLine=""18"" startColumn=""17"" endLine=""18"" endColumn=""23"" />
<entry offset=""0x78"" startLine=""20"" startColumn=""9"" endLine=""20"" endColumn=""19"" />
<entry offset=""0x7d"" hidden=""true"" />
<entry offset=""0xb2"" startLine=""23"" startColumn=""17"" endLine=""23"" endColumn=""23"" />
<entry offset=""0xb4"" startLine=""25"" startColumn=""17"" endLine=""25"" endColumn=""23"" />
<entry offset=""0xb6"" startLine=""27"" startColumn=""9"" endLine=""27"" endColumn=""19"" />
<entry offset=""0xbb"" hidden=""true"" />
<entry offset=""0xc7"" startLine=""30"" startColumn=""17"" endLine=""30"" endColumn=""23"" />
<entry offset=""0xc9"" startLine=""32"" startColumn=""5"" endLine=""32"" endColumn=""6"" />
<entry offset=""0x3"" hidden=""true"" />
<entry offset=""0x59"" startLine=""7"" startColumn=""20"" endLine=""7"" endColumn=""34"" />
<entry offset=""0x5e"" startLine=""9"" startColumn=""20"" endLine=""9"" endColumn=""34"" />
<entry offset=""0x63"" startLine=""10"" startColumn=""17"" endLine=""10"" endColumn=""23"" />
<entry offset=""0x65"" startLine=""11"" startColumn=""20"" endLine=""11"" endColumn=""34"" />
<entry offset=""0x6a"" startLine=""13"" startColumn=""20"" endLine=""13"" endColumn=""34"" />
<entry offset=""0x6f"" startLine=""14"" startColumn=""17"" endLine=""14"" endColumn=""23"" />
<entry offset=""0x71"" startLine=""16"" startColumn=""17"" endLine=""16"" endColumn=""23"" />
<entry offset=""0x73"" startLine=""18"" startColumn=""17"" endLine=""18"" endColumn=""23"" />
<entry offset=""0x75"" startLine=""20"" startColumn=""9"" endLine=""20"" endColumn=""19"" />
<entry offset=""0x78"" hidden=""true"" />
<entry offset=""0xac"" startLine=""23"" startColumn=""17"" endLine=""23"" endColumn=""23"" />
<entry offset=""0xae"" startLine=""25"" startColumn=""17"" endLine=""25"" endColumn=""23"" />
<entry offset=""0xb0"" startLine=""27"" startColumn=""9"" endLine=""27"" endColumn=""19"" />
<entry offset=""0xb3"" hidden=""true"" />
<entry offset=""0xbf"" startLine=""30"" startColumn=""17"" endLine=""30"" endColumn=""23"" />
<entry offset=""0xc1"" startLine=""32"" startColumn=""5"" endLine=""32"" endColumn=""6"" />
</sequencePoints>
</method>
</methods>
......
......@@ -167,12 +167,11 @@ .maxstack 1
.locals init (object V_0,
string V_1,
int V_2,
object V_3,
string V_4, //a
string V_5, //s
int V_6,
object V_7,
int? V_8)
string V_3, //a
string V_4, //s
int V_5,
object V_6,
int? V_7)
IL_0000: ldarg.0
IL_0001: ret
}");
......@@ -183,32 +182,29 @@ .maxstack 1
.locals init (object V_0,
string V_1,
int V_2,
object V_3,
string V_4, //a
string V_5, //s
int V_6,
object V_7,
int? V_8)
string V_3, //a
string V_4, //s
int V_5,
object V_6,
int? V_7)
IL_0000: ldarg.1
IL_0001: ret
}");
VerifyLocal(testData, typeName, locals[2], "<>m2", "a", expectedILOpt:
@"{
// Code size 3 (0x3)
// Code size 2 (0x2)
.maxstack 1
.locals init (object V_0,
string V_1,
int V_2,
object V_3,
string V_4, //a
string V_5, //s
int V_6,
object V_7,
int? V_8)
IL_0000: ldloc.s V_4
IL_0002: ret
}
");
string V_3, //a
string V_4, //s
int V_5,
object V_6,
int? V_7)
IL_0000: ldloc.3
IL_0001: ret
}");
VerifyLocal(testData, typeName, locals[3], "<>m3", "s", expectedILOpt:
@"{
// Code size 3 (0x3)
......@@ -216,13 +212,12 @@ .maxstack 1
.locals init (object V_0,
string V_1,
int V_2,
object V_3,
string V_4, //a
string V_5, //s
int V_6,
object V_7,
int? V_8)
IL_0000: ldloc.s V_5
string V_3, //a
string V_4, //s
int V_5,
object V_6,
int? V_7)
IL_0000: ldloc.s V_4
IL_0002: ret
}");
locals.Free();
......@@ -243,12 +238,11 @@ .maxstack 1
.locals init (object V_0,
string V_1,
int V_2,
object V_3,
string V_4, //a
string V_5,
int V_6, //s
object V_7,
int? V_8)
string V_3, //a
string V_4,
int V_5, //s
object V_6,
int? V_7)
IL_0000: ldarg.0
IL_0001: ret
}");
......@@ -259,32 +253,29 @@ .maxstack 1
.locals init (object V_0,
string V_1,
int V_2,
object V_3,
string V_4, //a
string V_5,
int V_6, //s
object V_7,
int? V_8)
string V_3, //a
string V_4,
int V_5, //s
object V_6,
int? V_7)
IL_0000: ldarg.1
IL_0001: ret
}");
VerifyLocal(testData, typeName, locals[2], "<>m2", "a", expectedILOpt:
@"{
// Code size 3 (0x3)
// Code size 2 (0x2)
.maxstack 1
.locals init (object V_0,
string V_1,
int V_2,
object V_3,
string V_4, //a
string V_5,
int V_6, //s
object V_7,
int? V_8)
IL_0000: ldloc.s V_4
IL_0002: ret
}
");
string V_3, //a
string V_4,
int V_5, //s
object V_6,
int? V_7)
IL_0000: ldloc.3
IL_0001: ret
}");
VerifyLocal(testData, typeName, locals[3], "<>m3", "s", expectedILOpt:
@"{
// Code size 3 (0x3)
......@@ -292,13 +283,12 @@ .maxstack 1
.locals init (object V_0,
string V_1,
int V_2,
object V_3,
string V_4, //a
string V_5,
int V_6, //s
object V_7,
int? V_8)
IL_0000: ldloc.s V_6
string V_3, //a
string V_4,
int V_5, //s
object V_6,
int? V_7)
IL_0000: ldloc.s V_5
IL_0002: ret
}");
locals.Free();
......@@ -358,9 +348,8 @@ .maxstack 1
string V_2,
int V_3,
object V_4,
object V_5,
int? V_6,
System.Action V_7)
int? V_5,
System.Action V_6)
IL_0000: ldarg.0
IL_0001: ret
}");
......@@ -373,9 +362,8 @@ .maxstack 1
string V_2,
int V_3,
object V_4,
object V_5,
int? V_6,
System.Action V_7)
int? V_5,
System.Action V_6)
IL_0000: ldarg.1
IL_0001: ret
}");
......@@ -388,14 +376,12 @@ .maxstack 1
string V_2,
int V_3,
object V_4,
object V_5,
int? V_6,
System.Action V_7)
int? V_5,
System.Action V_6)
IL_0000: ldloc.0
IL_0001: ldfld ""string C.<>c__DisplayClass0_0.a""
IL_0006: ret
}
");
}");
// We should be able to evaluate "s" within this context, https://github.com/dotnet/roslyn/issues/16594.
// VerifyLocal(testData, typeName, locals[3], "<>m3", "s", expectedILOpt:
//@"{
......@@ -435,9 +421,8 @@ .maxstack 1
string V_2,
int V_3,
object V_4,
object V_5,
int? V_6,
System.Action V_7)
int? V_5,
System.Action V_6)
IL_0000: ldarg.0
IL_0001: ret
}");
......@@ -450,9 +435,8 @@ .maxstack 1
string V_2,
int V_3,
object V_4,
object V_5,
int? V_6,
System.Action V_7)
int? V_5,
System.Action V_6)
IL_0000: ldarg.1
IL_0001: ret
}");
......@@ -465,14 +449,12 @@ .maxstack 1
string V_2,
int V_3,
object V_4,
object V_5,
int? V_6,
System.Action V_7)
int? V_5,
System.Action V_6)
IL_0000: ldloc.0
IL_0001: ldfld ""string C.<>c__DisplayClass0_0.a""
IL_0006: ret
}
");
}");
// We should be able to evaluate "s" within this context, https://github.com/dotnet/roslyn/issues/16594.
// VerifyLocal(testData, typeName, locals[3], "<>m3", "s", expectedILOpt:
//@"{
......@@ -607,13 +589,12 @@ .maxstack 1
.locals init (int V_0,
object V_1,
object V_2,
object V_3,
string V_4,
int? V_5,
System.Runtime.CompilerServices.TaskAwaiter<object> V_6,
C.<M>d__1 V_7,
System.Runtime.CompilerServices.TaskAwaiter<object> V_8,
System.Exception V_9)
string V_3,
int? V_4,
System.Runtime.CompilerServices.TaskAwaiter<object> V_5,
C.<M>d__1 V_6,
System.Runtime.CompilerServices.TaskAwaiter<object> V_7,
System.Exception V_8)
IL_0000: ldarg.0
IL_0001: ldfld ""C C.<M>d__1.<>4__this""
IL_0006: ret
......@@ -625,13 +606,12 @@ .maxstack 1
.locals init (int V_0,
object V_1,
object V_2,
object V_3,
string V_4,
int? V_5,
System.Runtime.CompilerServices.TaskAwaiter<object> V_6,
C.<M>d__1 V_7,
System.Runtime.CompilerServices.TaskAwaiter<object> V_8,
System.Exception V_9)
string V_3,
int? V_4,
System.Runtime.CompilerServices.TaskAwaiter<object> V_5,
C.<M>d__1 V_6,
System.Runtime.CompilerServices.TaskAwaiter<object> V_7,
System.Exception V_8)
IL_0000: ldarg.0
IL_0001: ldfld ""object C.<M>d__1.o""
IL_0006: ret
......@@ -643,13 +623,12 @@ .maxstack 1
.locals init (int V_0,
object V_1,
object V_2,
object V_3,
string V_4,
int? V_5,
System.Runtime.CompilerServices.TaskAwaiter<object> V_6,
C.<M>d__1 V_7,
System.Runtime.CompilerServices.TaskAwaiter<object> V_8,
System.Exception V_9)
string V_3,
int? V_4,
System.Runtime.CompilerServices.TaskAwaiter<object> V_5,
C.<M>d__1 V_6,
System.Runtime.CompilerServices.TaskAwaiter<object> V_7,
System.Exception V_8)
IL_0000: ldarg.0
IL_0001: ldfld ""string C.<M>d__1.<a>5__4""
IL_0006: ret
......@@ -661,13 +640,12 @@ .maxstack 1
.locals init (int V_0,
object V_1,
object V_2,
object V_3,
string V_4,
int? V_5,
System.Runtime.CompilerServices.TaskAwaiter<object> V_6,
C.<M>d__1 V_7,
System.Runtime.CompilerServices.TaskAwaiter<object> V_8,
System.Exception V_9)
string V_3,
int? V_4,
System.Runtime.CompilerServices.TaskAwaiter<object> V_5,
C.<M>d__1 V_6,
System.Runtime.CompilerServices.TaskAwaiter<object> V_7,
System.Exception V_8)
IL_0000: ldarg.0
IL_0001: ldfld ""string C.<M>d__1.<s>5__5""
IL_0006: ret
......@@ -690,13 +668,12 @@ .maxstack 1
.locals init (int V_0,
object V_1,
object V_2,
object V_3,
string V_4,
int? V_5,
System.Runtime.CompilerServices.TaskAwaiter<object> V_6,
C.<M>d__1 V_7,
System.Runtime.CompilerServices.TaskAwaiter<object> V_8,
System.Exception V_9)
string V_3,
int? V_4,
System.Runtime.CompilerServices.TaskAwaiter<object> V_5,
C.<M>d__1 V_6,
System.Runtime.CompilerServices.TaskAwaiter<object> V_7,
System.Exception V_8)
IL_0000: ldarg.0
IL_0001: ldfld ""C C.<M>d__1.<>4__this""
IL_0006: ret
......@@ -708,13 +685,12 @@ .maxstack 1
.locals init (int V_0,
object V_1,
object V_2,
object V_3,
string V_4,
int? V_5,
System.Runtime.CompilerServices.TaskAwaiter<object> V_6,
C.<M>d__1 V_7,
System.Runtime.CompilerServices.TaskAwaiter<object> V_8,
System.Exception V_9)
string V_3,
int? V_4,
System.Runtime.CompilerServices.TaskAwaiter<object> V_5,
C.<M>d__1 V_6,
System.Runtime.CompilerServices.TaskAwaiter<object> V_7,
System.Exception V_8)
IL_0000: ldarg.0
IL_0001: ldfld ""object C.<M>d__1.o""
IL_0006: ret
......@@ -726,13 +702,12 @@ .maxstack 1
.locals init (int V_0,
object V_1,
object V_2,
object V_3,
string V_4,
int? V_5,
System.Runtime.CompilerServices.TaskAwaiter<object> V_6,
C.<M>d__1 V_7,
System.Runtime.CompilerServices.TaskAwaiter<object> V_8,
System.Exception V_9)
string V_3,
int? V_4,
System.Runtime.CompilerServices.TaskAwaiter<object> V_5,
C.<M>d__1 V_6,
System.Runtime.CompilerServices.TaskAwaiter<object> V_7,
System.Exception V_8)
IL_0000: ldarg.0
IL_0001: ldfld ""string C.<M>d__1.<a>5__4""
IL_0006: ret
......@@ -744,13 +719,12 @@ .maxstack 1
.locals init (int V_0,
object V_1,
object V_2,
object V_3,
string V_4,
int? V_5,
System.Runtime.CompilerServices.TaskAwaiter<object> V_6,
C.<M>d__1 V_7,
System.Runtime.CompilerServices.TaskAwaiter<object> V_8,
System.Exception V_9)
string V_3,
int? V_4,
System.Runtime.CompilerServices.TaskAwaiter<object> V_5,
C.<M>d__1 V_6,
System.Runtime.CompilerServices.TaskAwaiter<object> V_7,
System.Exception V_8)
IL_0000: ldarg.0
IL_0001: ldfld ""int C.<M>d__1.<s>5__6""
IL_0006: ret
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册