diff --git a/docs/contributing/Compiler Test Plan.md b/docs/contributing/Compiler Test Plan.md index ffa51afae2e65..8b7bc70c3ed7e 100644 --- a/docs/contributing/Compiler Test Plan.md +++ b/docs/contributing/Compiler Test Plan.md @@ -347,6 +347,12 @@ __makeref( x ) - Declaration Pattern - Constant Pattern - Recursive Pattern +- Parenthesized Pattern +- `and` Pattern +- `or` Pattern +- `not` Pattern +- Relational Pattern +- Type Pattern ## Metadata table numbers / token prefixes diff --git a/src/Compilers/CSharp/Portable/Lowering/Instrumentation/CompoundInstrumenter.cs b/src/Compilers/CSharp/Portable/Lowering/Instrumentation/CompoundInstrumenter.cs index fcffd35d2df64..e151bae961723 100644 --- a/src/Compilers/CSharp/Portable/Lowering/Instrumentation/CompoundInstrumenter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/Instrumentation/CompoundInstrumenter.cs @@ -186,6 +186,11 @@ public override BoundExpression InstrumentSwitchStatementExpression(BoundStateme return Previous.InstrumentSwitchStatementExpression(original, rewrittenExpression, factory); } + public override BoundExpression InstrumentSwitchExpressionArmExpression(BoundExpression original, BoundExpression rewrittenExpression, SyntheticBoundNodeFactory factory) + { + return Previous.InstrumentSwitchExpressionArmExpression(original, rewrittenExpression, factory); + } + public override BoundStatement InstrumentSwitchBindCasePatternVariables(BoundStatement bindings) { return Previous.InstrumentSwitchBindCasePatternVariables(bindings); diff --git a/src/Compilers/CSharp/Portable/Lowering/Instrumentation/DebugInfoInjector.cs b/src/Compilers/CSharp/Portable/Lowering/Instrumentation/DebugInfoInjector.cs index 23db7bba0b292..2eab00173db9c 100644 --- a/src/Compilers/CSharp/Portable/Lowering/Instrumentation/DebugInfoInjector.cs +++ b/src/Compilers/CSharp/Portable/Lowering/Instrumentation/DebugInfoInjector.cs @@ -406,6 +406,11 @@ public override BoundExpression InstrumentSwitchStatementExpression(BoundStateme return AddConditionSequencePoint(base.InstrumentSwitchStatementExpression(original, rewrittenExpression, factory), original.Syntax, factory); } + public override BoundExpression InstrumentSwitchExpressionArmExpression(BoundExpression original, BoundExpression rewrittenExpression, SyntheticBoundNodeFactory factory) + { + return new BoundSequencePointExpression(original.Syntax, base.InstrumentSwitchExpressionArmExpression(original, rewrittenExpression, factory), rewrittenExpression.Type); + } + public override BoundStatement InstrumentSwitchBindCasePatternVariables(BoundStatement bindings) { // Mark the code that binds pattern variables to their values as hidden. diff --git a/src/Compilers/CSharp/Portable/Lowering/Instrumentation/Instrumenter.cs b/src/Compilers/CSharp/Portable/Lowering/Instrumentation/Instrumenter.cs index 840b5c56282f6..c0e14bfd94f28 100644 --- a/src/Compilers/CSharp/Portable/Lowering/Instrumentation/Instrumenter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/Instrumentation/Instrumenter.cs @@ -265,6 +265,15 @@ public virtual BoundExpression InstrumentSwitchStatementExpression(BoundStatemen return rewrittenExpression; } + /// + /// Instrument the expression of a switch arm of a switch expression. + /// + public virtual BoundExpression InstrumentSwitchExpressionArmExpression(BoundExpression original, BoundExpression rewrittenExpression, SyntheticBoundNodeFactory factory) + { + Debug.Assert(factory != null); + return rewrittenExpression; + } + public virtual BoundStatement InstrumentSwitchBindCasePatternVariables(BoundStatement bindings) { return bindings; diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.DecisionDagRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.DecisionDagRewriter.cs index 1dd5cf4b72461..4d2b12e577b8f 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.DecisionDagRewriter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.DecisionDagRewriter.cs @@ -40,8 +40,9 @@ private abstract partial class DecisionDagRewriter : PatternLocalRewriter protected DecisionDagRewriter( SyntaxNode node, - LocalRewriter localRewriter) - : base(node, localRewriter) + LocalRewriter localRewriter, + bool generateInstrumentation) + : base(node, localRewriter, generateInstrumentation) { } @@ -893,7 +894,7 @@ private void LowerWhenClause(BoundWhenDecisionDagNode whenClause) BoundStatement conditionalGoto = _factory.ConditionalGoto(_localRewriter.VisitExpression(whenClause.WhenExpression), trueLabel, jumpIfTrue: true); // Only add instrumentation (such as a sequence point) if the node is not compiler-generated. - if (GenerateSequencePoints && !whenClause.WhenExpression.WasCompilerGenerated) + if (GenerateInstrumentation && !whenClause.WhenExpression.WasCompilerGenerated) { conditionalGoto = _localRewriter._instrumenter.InstrumentSwitchWhenClauseConditionalGotoBody(whenClause.WhenExpression, conditionalGoto); } @@ -904,7 +905,7 @@ private void LowerWhenClause(BoundWhenDecisionDagNode whenClause) // We hide the jump back into the decision dag, as it is not logically part of the when clause BoundStatement jump = _factory.Goto(GetDagNodeLabel(whenFalse)); - sectionBuilder.Add(GenerateSequencePoints ? _factory.HiddenSequencePoint(jump) : jump); + sectionBuilder.Add(GenerateInstrumentation ? _factory.HiddenSequencePoint(jump) : jump); } else { @@ -930,7 +931,7 @@ private void LowerDecisionDagNode(BoundDecisionDagNode node, BoundDecisionDagNod // We add a hidden sequence point after the evaluation's side-effect, which may be a call out // to user code such as `Deconstruct` or a property get, to permit edit-and-continue to // synchronize on changes. - if (GenerateSequencePoints) + if (GenerateInstrumentation) _loweredDecisionDag.Add(_factory.HiddenSequencePoint()); if (nextNode != evaluationNode.Next) diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.PatternLocalRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.PatternLocalRewriter.cs index c7278b4df970c..da9ca6e95398b 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.PatternLocalRewriter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter.PatternLocalRewriter.cs @@ -25,21 +25,23 @@ private abstract class PatternLocalRewriter protected readonly SyntheticBoundNodeFactory _factory; protected readonly DagTempAllocator _tempAllocator; - public PatternLocalRewriter(SyntaxNode node, LocalRewriter localRewriter) + public PatternLocalRewriter(SyntaxNode node, LocalRewriter localRewriter, bool generateInstrumentation) { _localRewriter = localRewriter; _factory = localRewriter._factory; - _tempAllocator = new DagTempAllocator(_factory, node, GenerateSequencePoints); + GenerateInstrumentation = generateInstrumentation; + _tempAllocator = new DagTempAllocator(_factory, node, generateInstrumentation); } /// - /// True if this is a rewriter for a switch statement. This affects - /// - sequence points - /// When clause gets a sequence point in a switch statement, but not in a switch expression. + /// True if we should produce instrumentation and sequence points, which we do for a switch statement and a switch expression. + /// This affects + /// - whether or not we invoke the instrumentation APIs + /// - production of sequence points /// - synthesized local variable kind /// The temp variables must be long lived in a switch statement since their lifetime spans across sequence points. /// - protected abstract bool GenerateSequencePoints { get; } + protected bool GenerateInstrumentation { get; } public void Free() { diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_BasePatternSwitchLocalRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_BasePatternSwitchLocalRewriter.cs index 6f3b1d2ce5273..23d9704c75d00 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_BasePatternSwitchLocalRewriter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_BasePatternSwitchLocalRewriter.cs @@ -39,8 +39,9 @@ protected override ArrayBuilder BuilderForSection(SyntaxNode whe protected BaseSwitchLocalRewriter( SyntaxNode node, LocalRewriter localRewriter, - ImmutableArray arms) - : base(node, localRewriter) + ImmutableArray arms, + bool generateInstrumentation) + : base(node, localRewriter, generateInstrumentation) { foreach (var arm in arms) { @@ -48,7 +49,7 @@ protected BaseSwitchLocalRewriter( // We start each switch block of a switch statement with a hidden sequence point so that // we do not appear to be in the previous switch block when we begin. - if (GenerateSequencePoints) + if (GenerateInstrumentation) armBuilder.Add(_factory.HiddenSequencePoint()); _switchArms.Add(arm, armBuilder); diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_IsPatternOperator.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_IsPatternOperator.cs index d6ea37f359590..9f4d949b5f43d 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_IsPatternOperator.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_IsPatternOperator.cs @@ -86,14 +86,14 @@ private sealed class IsPatternExpressionGeneralLocalRewriter : DecisionDagRewrit { private readonly ArrayBuilder _statements = ArrayBuilder.GetInstance(); - public IsPatternExpressionGeneralLocalRewriter(SyntaxNode node, LocalRewriter localRewriter) : base(node, localRewriter) + public IsPatternExpressionGeneralLocalRewriter( + SyntaxNode node, + LocalRewriter localRewriter) : base(node, localRewriter, generateInstrumentation: false) { } protected override ArrayBuilder BuilderForSection(SyntaxNode section) => _statements; - protected override bool GenerateSequencePoints => false; - public new void Free() { base.Free(); @@ -151,14 +151,12 @@ private sealed class IsPatternExpressionLinearLocalRewriter : PatternLocalRewrit private readonly ArrayBuilder _conjunctBuilder; public IsPatternExpressionLinearLocalRewriter(BoundIsPatternExpression node, LocalRewriter localRewriter) - : base(node.Syntax, localRewriter) + : base(node.Syntax, localRewriter, generateInstrumentation: false) { _conjunctBuilder = ArrayBuilder.GetInstance(); _sideEffectBuilder = ArrayBuilder.GetInstance(); } - protected override bool GenerateSequencePoints => false; - public new void Free() { _conjunctBuilder.Free(); diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_PatternSwitchStatement.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_PatternSwitchStatement.cs index dd8d53035739e..6e0dfd9ac034a 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_PatternSwitchStatement.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_PatternSwitchStatement.cs @@ -26,8 +26,6 @@ private sealed class SwitchStatementLocalRewriter : BaseSwitchLocalRewriter /// private readonly Dictionary _sectionLabels = PooledDictionary.GetInstance(); - protected override bool GenerateSequencePoints => true; - public static BoundStatement Rewrite(LocalRewriter localRewriter, BoundSwitchStatement node) { var rewriter = new SwitchStatementLocalRewriter(node, localRewriter); @@ -65,7 +63,9 @@ protected override LabelSymbol GetDagNodeLabel(BoundDecisionDagNode dag) } private SwitchStatementLocalRewriter(BoundSwitchStatement node, LocalRewriter localRewriter) - : base(node.Syntax, localRewriter, node.SwitchSections.SelectAsArray(section => section.Syntax)) + : base(node.Syntax, localRewriter, node.SwitchSections.SelectAsArray(section => section.Syntax), + // Only add instrumentation (such as sequence points) if the node is not compiler-generated. + generateInstrumentation: localRewriter.Instrument && !node.WasCompilerGenerated) { } @@ -101,7 +101,7 @@ private BoundStatement LowerSwitchStatement(BoundSwitchStatement node) // In a switch statement, there is a hidden sequence point after evaluating the input at the start of // the code to handle the decision dag. This is necessary so that jumps back from a `when` clause into // the decision dag do not appear to jump back up to the enclosing construct. - if (GenerateSequencePoints) + if (GenerateInstrumentation) { // Since there may have been no code to evaluate the input, add a no-op for any previous sequence point to bind to. if (result.Count == 0) @@ -161,15 +161,14 @@ private BoundStatement LowerSwitchStatement(BoundSwitchStatement node) outerVariables.AddRange(_tempAllocator.AllTemps()); _factory.Syntax = node.Syntax; - result.Add(_factory.HiddenSequencePoint()); + if (GenerateInstrumentation) + result.Add(_factory.HiddenSequencePoint()); + result.Add(_factory.Label(node.BreakLabel)); BoundStatement translatedSwitch = _factory.Block(outerVariables.ToImmutableAndFree(), node.InnerLocalFunctions, result.ToImmutableAndFree()); - // Only add instrumentation (such as a sequence point) if the node is not compiler-generated. - if (!node.WasCompilerGenerated && _localRewriter.Instrument) - { + if (GenerateInstrumentation) translatedSwitch = _localRewriter._instrumenter.InstrumentSwitchStatement(node, translatedSwitch); - } return translatedSwitch; } diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_SwitchExpression.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_SwitchExpression.cs index 279729631efe3..0decf1d0507f9 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_SwitchExpression.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_SwitchExpression.cs @@ -29,13 +29,11 @@ public override BoundNode VisitConvertedSwitchExpression(BoundConvertedSwitchExp private sealed class SwitchExpressionLocalRewriter : BaseSwitchLocalRewriter { private SwitchExpressionLocalRewriter(BoundConvertedSwitchExpression node, LocalRewriter localRewriter) - : base(node.Syntax, localRewriter, node.SwitchArms.SelectAsArray(arm => arm.Syntax)) + : base(node.Syntax, localRewriter, node.SwitchArms.SelectAsArray(arm => arm.Syntax), + generateInstrumentation: !node.WasCompilerGenerated && localRewriter.Instrument) { - GenerateSequencePoints = !node.WasCompilerGenerated && localRewriter.Instrument; } - protected override bool GenerateSequencePoints { get; } - public static BoundExpression Rewrite(LocalRewriter localRewriter, BoundConvertedSwitchExpression node) { var rewriter = new SwitchExpressionLocalRewriter(node, localRewriter); @@ -48,7 +46,7 @@ private BoundExpression LowerSwitchExpression(BoundConvertedSwitchExpression nod { // When compiling for Debug (not Release), we produce the most detailed sequence points. var produceDetailedSequencePoints = - GenerateSequencePoints && _localRewriter._compilation.Options.OptimizationLevel != OptimizationLevel.Release; + GenerateInstrumentation && _localRewriter._compilation.Options.OptimizationLevel != OptimizationLevel.Release; _factory.Syntax = node.Syntax; var result = ArrayBuilder.GetInstance(); var outerVariables = ArrayBuilder.GetInstance(); @@ -91,11 +89,8 @@ private BoundExpression LowerSwitchExpression(BoundConvertedSwitchExpression nod sectionBuilder.AddRange(switchSections[arm.Syntax]); sectionBuilder.Add(_factory.Label(arm.Label)); var loweredValue = _localRewriter.VisitExpression(arm.Value); - if (GenerateSequencePoints) - { - // Should go through this._localRewriter._instrumenter; see https://github.com/dotnet/roslyn/issues/42810 - loweredValue = new BoundSequencePointExpression(arm.Value.Syntax, loweredValue, loweredValue.Type); - } + if (GenerateInstrumentation) + loweredValue = this._localRewriter._instrumenter.InstrumentSwitchExpressionArmExpression(arm.Value, loweredValue, _factory); sectionBuilder.Add(_factory.Assignment(_factory.Local(resultTemp), loweredValue)); sectionBuilder.Add(_factory.Goto(afterSwitchExpression)); diff --git a/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/LocalSlotMappingTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/LocalSlotMappingTests.cs index 76d3eafd41add..bef0a1b29fab3 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/LocalSlotMappingTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/LocalSlotMappingTests.cs @@ -4076,7 +4076,7 @@ .locals init (int V_0, //a IL_001b: ldloc.1 IL_001c: brtrue.s IL_0020 IL_001e: br.s IL_0027 - IL_0020: br.s IL_0022 + ~IL_0020: br.s IL_0022 -IL_0022: ldloc.0 IL_0023: stloc.s V_4 IL_0025: br.s IL_002c @@ -4152,7 +4152,7 @@ .locals init (int V_0, //i IL_000e: unbox.any ""int"" IL_0013: stloc.0 ~IL_0014: br.s IL_0016 - IL_0016: br.s IL_0018 + ~IL_0016: br.s IL_0018 IL_0018: ldc.i4.1 IL_0019: brtrue.s IL_001c -IL_001b: nop @@ -4242,7 +4242,7 @@ .locals init (C.d__0 V_0) -IL_001a: stfld ""int C.d__0.<>1__state"" IL_001f: ldloc.0 IL_0020: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__0.<>t__builder"" - ~IL_0025: ldloca.s V_0 + IL_0025: ldloca.s V_0 IL_0027: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Startd__0>(ref C.d__0)"" IL_002c: ldloc.0 IL_002d: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__0.<>t__builder"" @@ -4285,30 +4285,30 @@ static async Task G(Task o) ImmutableArray.Create(SemanticEdit.Create(SemanticEditKind.Update, method0, method1, GetEquivalentNodesMap(method1, method0), preserveLocalVariables: true))); diff1.VerifyIL("C.G", @" -{ - // Code size 56 (0x38) - .maxstack 2 - .locals init (C.d__0 V_0) - ~IL_0000: newobj ""C.d__0..ctor()"" - IL_0005: stloc.0 - IL_0006: ldloc.0 - ~IL_0007: ldarg.0 - IL_0008: stfld ""System.Threading.Tasks.Task C.d__0.o"" - IL_000d: ldloc.0 - -IL_000e: call ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Create()"" - IL_0013: stfld ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__0.<>t__builder"" - IL_0018: ldloc.0 - IL_0019: ldc.i4.m1 - IL_001a: stfld ""int C.d__0.<>1__state"" - IL_001f: ldloc.0 - IL_0020: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__0.<>t__builder"" - IL_0025: ldloca.s V_0 - IL_0027: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Startd__0>(ref C.d__0)"" - IL_002c: ldloc.0 - IL_002d: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__0.<>t__builder"" - IL_0032: call ""System.Threading.Tasks.Task System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Task.get"" - IL_0037: ret -} + { + // Code size 56 (0x38) + .maxstack 2 + .locals init (C.d__0 V_0) + ~IL_0000: newobj ""C.d__0..ctor()"" + IL_0005: stloc.0 + IL_0006: ldloc.0 + ~IL_0007: ldarg.0 + IL_0008: stfld ""System.Threading.Tasks.Task C.d__0.o"" + IL_000d: ldloc.0 + -IL_000e: call ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Create()"" + IL_0013: stfld ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__0.<>t__builder"" + IL_0018: ldloc.0 + IL_0019: ldc.i4.m1 + IL_001a: stfld ""int C.d__0.<>1__state"" + IL_001f: ldloc.0 + IL_0020: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__0.<>t__builder"" + IL_0025: ldloca.s V_0 + IL_0027: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Startd__0>(ref C.d__0)"" + IL_002c: ldloc.0 + C.d__0.<>t__builder"" + IL_0032: call ""System.Threading.Tasks.Task System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Task.get"" + IL_0037: ret + } ", methodToken: diff1.UpdatedMethods.Single()); } @@ -4367,7 +4367,7 @@ .locals init (int V_0, //x ~IL_000e: ldloc.s V_6 IL_0010: brfalse.s IL_0014 IL_0012: br.s IL_0032 - IL_0014: ldc.i4.1 + ~IL_0014: ldc.i4.1 IL_0015: brtrue.s IL_0018 -IL_0017: nop ~IL_0018: ldloc.0 diff --git a/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs b/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs index 7ba551f149da9..52856db662638 100644 --- a/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs +++ b/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs @@ -8911,7 +8911,7 @@ .locals init (int V_0, //a -IL_015e: ldc.i4.2 IL_015f: stloc.s V_8 IL_0161: br.s IL_01ad - IL_0163: br.s IL_0165 + ~IL_0163: br.s IL_0165 -IL_0165: ldc.i4.3 IL_0166: stloc.s V_8 IL_0168: br.s IL_01ad @@ -8930,15 +8930,15 @@ .locals init (int V_0, //a -IL_018c: ldc.i4.6 IL_018d: stloc.s V_8 IL_018f: br.s IL_01ad - IL_0191: br.s IL_0193 + ~IL_0191: br.s IL_0193 -IL_0193: ldc.i4.7 IL_0194: stloc.s V_8 IL_0196: br.s IL_01ad - IL_0198: br.s IL_019a + ~IL_0198: br.s IL_019a -IL_019a: ldc.i4.8 IL_019b: stloc.s V_8 IL_019d: br.s IL_01ad - IL_019f: br.s IL_01a1 + ~IL_019f: br.s IL_01a1 -IL_01a1: ldc.i4.s 9 IL_01a3: stloc.s V_8 IL_01a5: br.s IL_01ad @@ -8973,18 +8973,18 @@ .locals init (int V_0, //a - - - - - - - - - - - - + + + + + + + + + + + + @@ -9010,6 +9010,7 @@ .locals init (int V_0, //a