454 lines
20 KiB
C#
454 lines
20 KiB
C#
using System.Collections.Immutable;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Linq;
|
|
using Microsoft.CodeAnalysis.CSharp.Symbols;
|
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
|
using Microsoft.CodeAnalysis.PooledObjects;
|
|
using Microsoft.CodeAnalysis.Shared.Collections;
|
|
using Roslyn.Utilities;
|
|
|
|
namespace Microsoft.CodeAnalysis.CSharp;
|
|
|
|
internal sealed class LocalStateTracingInstrumenter : CompoundInstrumenter
|
|
{
|
|
private sealed class Scope
|
|
{
|
|
public LocalSymbol ContextVariable;
|
|
|
|
private ArrayBuilder<LocalSymbol>? _lazyPreviousContextVariables;
|
|
|
|
public Scope(LocalSymbol contextVariable)
|
|
{
|
|
ContextVariable = contextVariable;
|
|
}
|
|
|
|
public void Open(LocalSymbol local)
|
|
{
|
|
if (_lazyPreviousContextVariables == null)
|
|
{
|
|
_lazyPreviousContextVariables = ArrayBuilder<LocalSymbol>.GetInstance();
|
|
}
|
|
ArrayBuilderExtensions.Push<LocalSymbol>(_lazyPreviousContextVariables, ContextVariable);
|
|
ContextVariable = local;
|
|
}
|
|
|
|
public void Close(bool isMethodBody)
|
|
{
|
|
ArrayBuilder<LocalSymbol> lazyPreviousContextVariables = _lazyPreviousContextVariables;
|
|
if (lazyPreviousContextVariables != null && lazyPreviousContextVariables.Count > 0)
|
|
{
|
|
ContextVariable = ArrayBuilderExtensions.Pop<LocalSymbol>(_lazyPreviousContextVariables);
|
|
}
|
|
if (isMethodBody)
|
|
{
|
|
_lazyPreviousContextVariables?.Free();
|
|
_lazyPreviousContextVariables = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
private readonly Scope _scope;
|
|
|
|
private readonly SyntheticBoundNodeFactory _factory;
|
|
|
|
private readonly BindingDiagnosticBag _diagnostics;
|
|
|
|
private readonly TypeSymbol _contextType;
|
|
|
|
private LocalStateTracingInstrumenter(Scope scope, TypeSymbol contextType, SyntheticBoundNodeFactory factory, BindingDiagnosticBag diagnostics, Instrumenter previous)
|
|
: base(previous)
|
|
{
|
|
_scope = scope;
|
|
_contextType = contextType;
|
|
_factory = factory;
|
|
_diagnostics = diagnostics;
|
|
}
|
|
|
|
protected override CompoundInstrumenter WithPreviousImpl(Instrumenter previous)
|
|
{
|
|
return new LocalStateTracingInstrumenter(_scope, _contextType, _factory, _diagnostics, previous);
|
|
}
|
|
|
|
public static bool TryCreate(MethodSymbol method, BoundStatement methodBody, SyntheticBoundNodeFactory factory, BindingDiagnosticBag diagnostics, Instrumenter previous, [NotNullWhen(true)] out LocalStateTracingInstrumenter? instrumenter)
|
|
{
|
|
instrumenter = null;
|
|
if (method.IsImplicitlyDeclared && !method.IsImplicitConstructor)
|
|
{
|
|
return false;
|
|
}
|
|
if (method is SourceMemberMethodSymbol sourceMemberMethodSymbol)
|
|
{
|
|
(BlockSyntax, ArrowExpressionClauseSyntax) bodies = sourceMemberMethodSymbol.Bodies;
|
|
if (bodies.Item2 == null && bodies.Item1 == null && !(sourceMemberMethodSymbol is SynthesizedSimpleProgramEntryPointSymbol))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
NamedTypeSymbol wellKnownType = factory.Compilation.GetWellKnownType((WellKnownType)265);
|
|
if (IsSameOrNestedType(method.ContainingType, wellKnownType))
|
|
{
|
|
return false;
|
|
}
|
|
Scope scope = new Scope(factory.SynthesizedLocal(wellKnownType, methodBody.Syntax, isPinned: false, isKnownToReferToTempIfReferenceType: false, (RefKind)0, (SynthesizedLocalKind)36));
|
|
instrumenter = new LocalStateTracingInstrumenter(scope, wellKnownType, factory, diagnostics, previous);
|
|
return true;
|
|
}
|
|
|
|
private static bool IsSameOrNestedType(NamedTypeSymbol type, NamedTypeSymbol otherType)
|
|
{
|
|
while (true)
|
|
{
|
|
if (type.Equals(otherType))
|
|
{
|
|
return true;
|
|
}
|
|
if ((object)type.ContainingType == null)
|
|
{
|
|
break;
|
|
}
|
|
type = type.ContainingType;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private MethodSymbol? GetLocalOrParameterStoreLogger(TypeSymbol variableType, Symbol targetSymbol, bool? refAssignmentSourceIsLocal, SyntaxNode syntax)
|
|
{
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0008: Invalid comparison between Unknown and I4
|
|
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0090: Expected I4, but got Unknown
|
|
//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_01af: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0173: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_017a: Invalid comparison between Unknown and I4
|
|
int num = (((int)targetSymbol.Kind == 13) ? 13 : 0);
|
|
WellKnownMember? val;
|
|
if (refAssignmentSourceIsLocal.HasValue)
|
|
{
|
|
val = ((refAssignmentSourceIsLocal != true) ? new WellKnownMember?((WellKnownMember)374) : new WellKnownMember?((WellKnownMember)388));
|
|
}
|
|
else
|
|
{
|
|
SpecialType specialType = variableType.EnumUnderlyingTypeOrSelf().SpecialType;
|
|
WellKnownMember? val2;
|
|
switch (specialType - 7)
|
|
{
|
|
case 0:
|
|
val2 = (WellKnownMember)362;
|
|
break;
|
|
case 2:
|
|
case 3:
|
|
val2 = (WellKnownMember)363;
|
|
break;
|
|
case 1:
|
|
case 4:
|
|
case 5:
|
|
val2 = (WellKnownMember)364;
|
|
break;
|
|
case 6:
|
|
case 7:
|
|
val2 = (WellKnownMember)365;
|
|
break;
|
|
case 8:
|
|
case 9:
|
|
val2 = (WellKnownMember)366;
|
|
break;
|
|
case 11:
|
|
val2 = (WellKnownMember)367;
|
|
break;
|
|
case 12:
|
|
val2 = (WellKnownMember)368;
|
|
break;
|
|
case 10:
|
|
val2 = (WellKnownMember)369;
|
|
break;
|
|
case 13:
|
|
val2 = (WellKnownMember)370;
|
|
break;
|
|
default:
|
|
val2 = ((!variableType.IsPointerOrFunctionPointer()) ? (variableType.IsManagedTypeNoUseSiteDiagnostics ? ((variableType.IsRefLikeType && !hasOverriddenToString(variableType)) ? ((WellKnownMember?)null) : (((int)variableType.TypeKind != 10) ? new WellKnownMember?((WellKnownMember)371) : new WellKnownMember?((WellKnownMember)370))) : new WellKnownMember?((WellKnownMember)373)) : new WellKnownMember?((WellKnownMember)372));
|
|
break;
|
|
}
|
|
val = val2;
|
|
}
|
|
WellKnownMember? val3 = val;
|
|
if (!val3.HasValue)
|
|
{
|
|
return null;
|
|
}
|
|
WellKnownMember overload = (WellKnownMember)(val3.Value + num);
|
|
return GetWellKnownMethodSymbol(overload, syntax);
|
|
static bool hasOverriddenToString(TypeSymbol typeSymbol)
|
|
{
|
|
return typeSymbol.GetMembers("ToString").Any((Symbol m) => (object)m.GetOverriddenMember() != null);
|
|
}
|
|
}
|
|
|
|
private MethodSymbol? GetWellKnownMethodSymbol(WellKnownMember overload, SyntaxNode syntax)
|
|
{
|
|
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
|
|
return (MethodSymbol)Binder.GetWellKnownTypeMember(_factory.Compilation, overload, _diagnostics, null, syntax);
|
|
}
|
|
|
|
public override void PreInstrumentBlock(BoundBlock original, LocalRewriter rewriter)
|
|
{
|
|
base.Previous.PreInstrumentBlock(original, rewriter);
|
|
if (rewriter.CurrentLambdaBody == original)
|
|
{
|
|
_scope.Open(_factory.SynthesizedLocal(_contextType, original.Syntax, isPinned: false, isKnownToReferToTempIfReferenceType: false, (RefKind)0, (SynthesizedLocalKind)36));
|
|
}
|
|
}
|
|
|
|
public override void InstrumentBlock(BoundBlock original, LocalRewriter rewriter, ref TemporaryArray<LocalSymbol> additionalLocals, out BoundStatement? prologue, out BoundStatement? epilogue, out BoundBlockInstrumentation? instrumentation)
|
|
{
|
|
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_009c: Invalid comparison between Unknown and I4
|
|
//IL_029c: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
|
|
base.InstrumentBlock(original, rewriter, ref additionalLocals, out BoundStatement prologue2, out epilogue, out instrumentation);
|
|
bool flag = rewriter.CurrentMethodBody == original;
|
|
bool flag2 = rewriter.CurrentLambdaBody == original;
|
|
if (!flag && !flag2)
|
|
{
|
|
prologue = prologue2;
|
|
return;
|
|
}
|
|
bool flag3 = _factory.CurrentFunction.IsAsync || _factory.CurrentFunction.IsIterator;
|
|
ArrayBuilder<BoundStatement> instance = ArrayBuilder<BoundStatement>.GetInstance(_factory.CurrentFunction.ParameterCount);
|
|
ImmutableArray<ParameterSymbol>.Enumerator enumerator = _factory.CurrentFunction.Parameters.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
ParameterSymbol current = enumerator.Current;
|
|
if ((int)current.RefKind != 2 && !current.IsDiscard)
|
|
{
|
|
MethodSymbol localOrParameterStoreLogger = GetLocalOrParameterStoreLogger(current.Type, current, null, _factory.Syntax);
|
|
if (localOrParameterStoreLogger != null)
|
|
{
|
|
instance.Add((BoundStatement)_factory.ExpressionStatement(_factory.Call(_factory.Local(_scope.ContextVariable), localOrParameterStoreLogger, MakeStoreLoggerArguments(localOrParameterStoreLogger.Parameters[0], current, current.Type, _factory.Parameter(current), null, _factory.Literal((int)(ushort)current.Ordinal)))));
|
|
}
|
|
}
|
|
}
|
|
if (prologue2 != null)
|
|
{
|
|
instance.Add(prologue2);
|
|
}
|
|
prologue = _factory.StatementList(instance.ToImmutableAndFree());
|
|
(WellKnownMember, BoundExpression[]) tuple = ((!flag2) ? (flag3 ? ((WellKnownMember)358, new BoundExpression[2]
|
|
{
|
|
_factory.MethodDefIndex(_factory.TopLevelMethod),
|
|
_factory.StateMachineInstanceId()
|
|
}) : ((WellKnownMember)356, new BoundExpression[1] { _factory.MethodDefIndex(_factory.TopLevelMethod) })) : (flag3 ? ((WellKnownMember)359, new BoundExpression[3]
|
|
{
|
|
_factory.MethodDefIndex(_factory.TopLevelMethod),
|
|
_factory.MethodDefIndex(_factory.CurrentFunction),
|
|
_factory.StateMachineInstanceId()
|
|
}) : ((WellKnownMember)357, new BoundExpression[2]
|
|
{
|
|
_factory.MethodDefIndex(_factory.TopLevelMethod),
|
|
_factory.MethodDefIndex(_factory.CurrentFunction)
|
|
})));
|
|
(WellKnownMember, BoundExpression[]) tuple2 = tuple;
|
|
WellKnownMember item = tuple2.Item1;
|
|
BoundExpression[] item2 = tuple2.Item2;
|
|
MethodSymbol wellKnownMethodSymbol = GetWellKnownMethodSymbol(item, _factory.Syntax);
|
|
BoundStatement prologue3 = ((wellKnownMethodSymbol != null) ? _factory.Assignment(_factory.Local(_scope.ContextVariable), _factory.Call(null, wellKnownMethodSymbol, item2)) : _factory.NoOp(NoOpStatementFlavor.Default));
|
|
MethodSymbol wellKnownMethodSymbol2 = GetWellKnownMethodSymbol((WellKnownMember)360, _factory.Syntax);
|
|
BoundStatement epilogue2 = ((wellKnownMethodSymbol2 != null) ? _factory.ExpressionStatement(_factory.Call(_factory.Local(_scope.ContextVariable), wellKnownMethodSymbol2)) : _factory.NoOp(NoOpStatementFlavor.Default));
|
|
instrumentation = new BoundBlockInstrumentation(_factory.Syntax, _scope.ContextVariable, prologue3, epilogue2);
|
|
_scope.Close(flag);
|
|
}
|
|
|
|
public override BoundExpression InstrumentUserDefinedLocalAssignment(BoundAssignmentOperator original)
|
|
{
|
|
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
|
|
BoundExpression boundExpression = base.InstrumentUserDefinedLocalAssignment(original);
|
|
bool? refAssignmentSourceIsLocal;
|
|
BoundExpression refAssignmentSourceIndex;
|
|
if (original.IsRef)
|
|
{
|
|
if (original.Right is BoundLocal boundLocal)
|
|
{
|
|
LocalSymbol localSymbol = boundLocal.LocalSymbol;
|
|
if ((object)localSymbol != null && (int)localSymbol.SynthesizedKind == 0)
|
|
{
|
|
refAssignmentSourceIsLocal = true;
|
|
refAssignmentSourceIndex = _factory.LocalId(boundLocal.LocalSymbol);
|
|
goto IL_008e;
|
|
}
|
|
}
|
|
if (!(original.Right is BoundParameter boundParameter))
|
|
{
|
|
return boundExpression;
|
|
}
|
|
refAssignmentSourceIsLocal = false;
|
|
refAssignmentSourceIndex = _factory.ParameterId(boundParameter.ParameterSymbol);
|
|
}
|
|
else
|
|
{
|
|
refAssignmentSourceIsLocal = null;
|
|
refAssignmentSourceIndex = null;
|
|
}
|
|
goto IL_008e;
|
|
IL_008e:
|
|
if (!TryGetLocalOrParameterInfo(original.Left, out Symbol symbol, out TypeSymbol type, out BoundExpression indexExpression))
|
|
{
|
|
throw ExceptionUtilities.UnexpectedValue((object)original.Left);
|
|
}
|
|
MethodSymbol localOrParameterStoreLogger = GetLocalOrParameterStoreLogger(type, symbol, refAssignmentSourceIsLocal, original.Syntax);
|
|
if ((object)localOrParameterStoreLogger == null)
|
|
{
|
|
return boundExpression;
|
|
}
|
|
SyntheticBoundNodeFactory factory = _factory;
|
|
BoundExpression[] sideEffects = new BoundCall[1] { _factory.Call(_factory.Local(_scope.ContextVariable), localOrParameterStoreLogger, MakeStoreLoggerArguments(localOrParameterStoreLogger.Parameters[0], symbol, type, boundExpression, refAssignmentSourceIndex, indexExpression)) };
|
|
return factory.Sequence(sideEffects, VariableRead(symbol));
|
|
}
|
|
|
|
private bool TryGetLocalOrParameterInfo(BoundNode node, [NotNullWhen(true)] out Symbol? symbol, [NotNullWhen(true)] out TypeSymbol? type, [NotNullWhen(true)] out BoundExpression? indexExpression)
|
|
{
|
|
if (node is BoundLocal boundLocal)
|
|
{
|
|
LocalSymbol localSymbol = (LocalSymbol)(symbol = boundLocal.LocalSymbol);
|
|
type = localSymbol.Type;
|
|
indexExpression = _factory.LocalId(localSymbol);
|
|
return true;
|
|
}
|
|
if (node is BoundParameter boundParameter)
|
|
{
|
|
ParameterSymbol parameterSymbol = (ParameterSymbol)(symbol = boundParameter.ParameterSymbol);
|
|
type = parameterSymbol.Type;
|
|
indexExpression = _factory.ParameterId(parameterSymbol);
|
|
return true;
|
|
}
|
|
symbol = null;
|
|
indexExpression = null;
|
|
type = null;
|
|
return false;
|
|
}
|
|
|
|
private ImmutableArray<BoundExpression> MakeStoreLoggerArguments(ParameterSymbol parameter, Symbol targetSymbol, TypeSymbol targetType, BoundExpression value, BoundExpression? refAssignmentSourceIndex, BoundExpression index)
|
|
{
|
|
//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00ce: Invalid comparison between Unknown and I4
|
|
//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00d8: Invalid comparison between Unknown and I4
|
|
if (refAssignmentSourceIndex != null)
|
|
{
|
|
return ImmutableArray.Create(_factory.Sequence(new BoundExpression[1] { value }, refAssignmentSourceIndex), index);
|
|
}
|
|
if (parameter.Type.IsVoidPointer() && !targetType.IsPointerOrFunctionPointer())
|
|
{
|
|
bool flag = ((value is BoundLocal || value is BoundParameter) ? true : false);
|
|
return ImmutableArray.Create(flag ? ((BoundExpression)new BoundAddressOfOperator(_factory.Syntax, value, isManaged: false, parameter.Type)) : ((BoundExpression)_factory.Sequence(new BoundExpression[1] { value }, new BoundAddressOfOperator(_factory.Syntax, VariableRead(targetSymbol), isManaged: false, parameter.Type))), _factory.Sizeof(targetType), index);
|
|
}
|
|
if ((int)parameter.Type.SpecialType == 20 && (int)targetType.SpecialType != 20)
|
|
{
|
|
MethodSymbol wellKnownMethodSymbol = GetWellKnownMethodSymbol((WellKnownMember)0, value.Syntax);
|
|
BoundExpression item = (((object)wellKnownMethodSymbol != null) ? ((BoundExpression)_factory.Call(value, wellKnownMethodSymbol)) : ((BoundExpression)_factory.Literal("")));
|
|
return ImmutableArray.Create(item, index);
|
|
}
|
|
return ImmutableArray.Create(_factory.Convert(parameter.Type, value), index);
|
|
}
|
|
|
|
private BoundExpression VariableRead(Symbol localOrParameterSymbol)
|
|
{
|
|
if (!(localOrParameterSymbol is LocalSymbol local))
|
|
{
|
|
if (localOrParameterSymbol is ParameterSymbol p)
|
|
{
|
|
return _factory.Parameter(p);
|
|
}
|
|
throw ExceptionUtilities.UnexpectedValue((object)localOrParameterSymbol);
|
|
}
|
|
return _factory.Local(local);
|
|
}
|
|
|
|
public override void InstrumentCatchBlock(BoundCatchBlock original, ref BoundExpression? rewrittenSource, ref BoundStatementList? rewrittenFilterPrologue, ref BoundExpression? rewrittenFilter, ref BoundBlock rewrittenBody, ref TypeSymbol? rewrittenType, SyntheticBoundNodeFactory factory)
|
|
{
|
|
base.InstrumentCatchBlock(original, ref rewrittenSource, ref rewrittenFilterPrologue, ref rewrittenFilter, ref rewrittenBody, ref rewrittenType, factory);
|
|
if (original.WasCompilerGenerated)
|
|
{
|
|
return;
|
|
}
|
|
LocalSymbol localSymbol = original.Locals.FirstOrDefault((LocalSymbol l) => (int)l.SynthesizedKind == 0);
|
|
if ((object)localSymbol != null)
|
|
{
|
|
TypeSymbol type = localSymbol.Type;
|
|
BoundExpression index = _factory.LocalId(localSymbol);
|
|
MethodSymbol localOrParameterStoreLogger = GetLocalOrParameterStoreLogger(type, localSymbol, null, original.Syntax);
|
|
if ((object)localOrParameterStoreLogger != null)
|
|
{
|
|
BoundExpressionStatement boundExpressionStatement = _factory.ExpressionStatement(_factory.Call(_factory.Local(_scope.ContextVariable), localOrParameterStoreLogger, MakeStoreLoggerArguments(localOrParameterStoreLogger.Parameters[0], localSymbol, type, VariableRead(localSymbol), null, index)));
|
|
rewrittenFilterPrologue = _factory.StatementList((rewrittenFilterPrologue != null) ? ImmutableArray.Create((BoundStatement)boundExpressionStatement, (BoundStatement)rewrittenFilterPrologue) : ImmutableArray.Create((BoundStatement)boundExpressionStatement));
|
|
}
|
|
}
|
|
}
|
|
|
|
public override BoundExpression InstrumentCall(BoundCall original, BoundExpression rewritten)
|
|
{
|
|
return InstrumentCall(base.InstrumentCall(original, rewritten), original.Arguments, original.ArgumentRefKindsOpt);
|
|
}
|
|
|
|
public override BoundExpression InstrumentObjectCreationExpression(BoundObjectCreationExpression original, BoundExpression rewritten)
|
|
{
|
|
return InstrumentCall(base.InstrumentObjectCreationExpression(original, rewritten), original.Arguments, original.ArgumentRefKindsOpt);
|
|
}
|
|
|
|
public override BoundExpression InstrumentFunctionPointerInvocation(BoundFunctionPointerInvocation original, BoundExpression rewritten)
|
|
{
|
|
return InstrumentCall(base.InstrumentFunctionPointerInvocation(original, rewritten), original.Arguments, original.ArgumentRefKindsOpt);
|
|
}
|
|
|
|
private BoundExpression InstrumentCall(BoundExpression invocation, ImmutableArray<BoundExpression> arguments, ImmutableArray<RefKind> refKinds)
|
|
{
|
|
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_001f: Invalid comparison between Unknown and I4
|
|
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_005d: Invalid comparison between Unknown and I4
|
|
if (refKinds.IsDefaultOrEmpty)
|
|
{
|
|
return invocation;
|
|
}
|
|
ArrayBuilder<BoundExpression> instance = ArrayBuilder<BoundExpression>.GetInstance();
|
|
BoundLocal boundLocal = null;
|
|
if ((int)invocation.Type.SpecialType != 6)
|
|
{
|
|
boundLocal = _factory.StoreToTemp(invocation, out BoundAssignmentOperator store, (RefKind)0, (SynthesizedLocalKind)(-2));
|
|
instance.Add((BoundExpression)store);
|
|
}
|
|
else
|
|
{
|
|
instance.Add(invocation);
|
|
}
|
|
for (int i = 0; i < arguments.Length; i++)
|
|
{
|
|
RefKind val = refKinds[i];
|
|
bool flag = val - 1 <= 1;
|
|
if (flag && TryGetLocalOrParameterInfo(arguments[i], out Symbol symbol, out TypeSymbol type, out BoundExpression indexExpression))
|
|
{
|
|
MethodSymbol localOrParameterStoreLogger = GetLocalOrParameterStoreLogger(type, symbol, null, invocation.Syntax);
|
|
if ((object)localOrParameterStoreLogger != null)
|
|
{
|
|
instance.Add((BoundExpression)_factory.Call(_factory.Local(_scope.ContextVariable), localOrParameterStoreLogger, MakeStoreLoggerArguments(localOrParameterStoreLogger.Parameters[0], symbol, type, VariableRead(symbol), null, indexExpression)));
|
|
}
|
|
}
|
|
}
|
|
if (boundLocal != null)
|
|
{
|
|
return _factory.Sequence(ImmutableArray.Create(boundLocal.LocalSymbol), instance.ToImmutableAndFree(), boundLocal);
|
|
}
|
|
BoundExpression result = instance.Last();
|
|
instance.RemoveLast();
|
|
return _factory.Sequence(ImmutableArray<LocalSymbol>.Empty, instance.ToImmutableAndFree(), result);
|
|
}
|
|
}
|