2050 lines
86 KiB
C#
2050 lines
86 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.Immutable;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using Microsoft.Cci;
|
|
using Microsoft.CodeAnalysis.CSharp.Emit.NoPia;
|
|
using Microsoft.CodeAnalysis.CSharp.Symbols;
|
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
|
using Microsoft.CodeAnalysis.CodeGen;
|
|
using Microsoft.CodeAnalysis.Emit;
|
|
using Microsoft.CodeAnalysis.PooledObjects;
|
|
using Microsoft.CodeAnalysis.Text;
|
|
using Roslyn.Utilities;
|
|
|
|
namespace Microsoft.CodeAnalysis.CSharp;
|
|
|
|
internal sealed class ClosureConversion : MethodToClassRewriter
|
|
{
|
|
internal sealed class Analysis : BoundTreeWalkerWithStackGuardWithoutRecursionOnTheLeftOfBinaryOperator
|
|
{
|
|
[DebuggerDisplay("{ToString(), nq}")]
|
|
public sealed class Scope
|
|
{
|
|
public readonly Scope Parent;
|
|
|
|
public readonly ArrayBuilder<Scope> NestedScopes = ArrayBuilder<Scope>.GetInstance();
|
|
|
|
public readonly ArrayBuilder<NestedFunction> NestedFunctions = ArrayBuilder<NestedFunction>.GetInstance();
|
|
|
|
public readonly SetWithInsertionOrder<Symbol> DeclaredVariables = new SetWithInsertionOrder<Symbol>();
|
|
|
|
public readonly BoundNode BoundNode;
|
|
|
|
public readonly NestedFunction ContainingFunctionOpt;
|
|
|
|
public ClosureEnvironment? DeclaredEnvironment;
|
|
|
|
public bool CanMergeWithParent { get; internal set; } = true;
|
|
|
|
public Scope(Scope parent, BoundNode boundNode, NestedFunction containingFunction)
|
|
{
|
|
Parent = parent;
|
|
BoundNode = boundNode;
|
|
ContainingFunctionOpt = containingFunction;
|
|
}
|
|
|
|
public void Free()
|
|
{
|
|
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
|
|
Enumerator<Scope> enumerator = NestedScopes.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
enumerator.Current.Free();
|
|
}
|
|
NestedScopes.Free();
|
|
Enumerator<NestedFunction> enumerator2 = NestedFunctions.GetEnumerator();
|
|
while (enumerator2.MoveNext())
|
|
{
|
|
enumerator2.Current.Free();
|
|
}
|
|
NestedFunctions.Free();
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return ((object)BoundNode.Syntax.GetText((Encoding)null, (SourceHashAlgorithm)1)).ToString();
|
|
}
|
|
}
|
|
|
|
public sealed class NestedFunction
|
|
{
|
|
public readonly MethodSymbol OriginalMethodSymbol;
|
|
|
|
public readonly SyntaxReference BlockSyntax;
|
|
|
|
public readonly PooledHashSet<Symbol> CapturedVariables = PooledHashSet<Symbol>.GetInstance();
|
|
|
|
public readonly ArrayBuilder<ClosureEnvironment> CapturedEnvironments = ArrayBuilder<ClosureEnvironment>.GetInstance();
|
|
|
|
public ClosureEnvironment ContainingEnvironmentOpt;
|
|
|
|
private bool _capturesThis;
|
|
|
|
public SynthesizedClosureMethod SynthesizedLoweredMethod;
|
|
|
|
public bool CapturesThis
|
|
{
|
|
get
|
|
{
|
|
return _capturesThis;
|
|
}
|
|
set
|
|
{
|
|
_capturesThis = value;
|
|
}
|
|
}
|
|
|
|
public NestedFunction(MethodSymbol symbol, SyntaxReference blockSyntax)
|
|
{
|
|
OriginalMethodSymbol = symbol;
|
|
BlockSyntax = blockSyntax;
|
|
}
|
|
|
|
public void Free()
|
|
{
|
|
CapturedVariables.Free();
|
|
CapturedEnvironments.Free();
|
|
}
|
|
}
|
|
|
|
public sealed class ClosureEnvironment
|
|
{
|
|
public readonly SetWithInsertionOrder<Symbol> CapturedVariables;
|
|
|
|
public bool CapturesParent;
|
|
|
|
public readonly bool IsStruct;
|
|
|
|
internal SynthesizedClosureEnvironment SynthesizedEnvironment;
|
|
|
|
public ClosureEnvironment(IEnumerable<Symbol> capturedVariables, bool isStruct)
|
|
{
|
|
CapturedVariables = new SetWithInsertionOrder<Symbol>();
|
|
foreach (Symbol capturedVariable in capturedVariables)
|
|
{
|
|
CapturedVariables.Add(capturedVariable);
|
|
}
|
|
IsStruct = isStruct;
|
|
}
|
|
}
|
|
|
|
private class ScopeTreeBuilder : BoundTreeWalkerWithStackGuardWithoutRecursionOnTheLeftOfBinaryOperator
|
|
{
|
|
private Scope _currentScope;
|
|
|
|
private NestedFunction _currentFunction;
|
|
|
|
private bool _inExpressionTree;
|
|
|
|
private readonly SmallDictionary<Symbol, Scope> _localToScope = new SmallDictionary<Symbol, Scope>();
|
|
|
|
private readonly MethodSymbol _topLevelMethod;
|
|
|
|
private readonly HashSet<MethodSymbol> _methodsConvertedToDelegates;
|
|
|
|
private readonly DiagnosticBag _diagnostics;
|
|
|
|
private readonly PooledDictionary<LabelSymbol, ArrayBuilder<Scope>> _scopesAfterLabel = PooledDictionary<LabelSymbol, ArrayBuilder<Scope>>.GetInstance();
|
|
|
|
private readonly ArrayBuilder<ArrayBuilder<LabelSymbol>> _labelsInScope = ArrayBuilder<ArrayBuilder<LabelSymbol>>.GetInstance();
|
|
|
|
private ScopeTreeBuilder(Scope rootScope, MethodSymbol topLevelMethod, HashSet<MethodSymbol> methodsConvertedToDelegates, DiagnosticBag diagnostics)
|
|
{
|
|
_currentScope = rootScope;
|
|
ArrayBuilderExtensions.Push<ArrayBuilder<LabelSymbol>>(_labelsInScope, ArrayBuilder<LabelSymbol>.GetInstance());
|
|
_topLevelMethod = topLevelMethod;
|
|
_methodsConvertedToDelegates = methodsConvertedToDelegates;
|
|
_diagnostics = diagnostics;
|
|
}
|
|
|
|
public static Scope Build(BoundNode node, MethodSymbol topLevelMethod, HashSet<MethodSymbol> methodsConvertedToDelegates, DiagnosticBag diagnostics)
|
|
{
|
|
Scope scope = new Scope(null, node, null);
|
|
new ScopeTreeBuilder(scope, topLevelMethod, methodsConvertedToDelegates, diagnostics).Build();
|
|
return scope;
|
|
}
|
|
|
|
private void Build()
|
|
{
|
|
DeclareLocals(_currentScope, _topLevelMethod.Parameters);
|
|
if (_topLevelMethod.TryGetThisParameter(out var thisParameter) && (object)thisParameter != null)
|
|
{
|
|
DeclareLocals(_currentScope, ImmutableArray.Create((Symbol)thisParameter));
|
|
}
|
|
Visit(_currentScope.BoundNode);
|
|
foreach (ArrayBuilder<Scope> value in ((Dictionary<LabelSymbol, ArrayBuilder<Scope>>)(object)_scopesAfterLabel).Values)
|
|
{
|
|
value.Free();
|
|
}
|
|
_scopesAfterLabel.Free();
|
|
ArrayBuilderExtensions.Pop<ArrayBuilder<LabelSymbol>>(_labelsInScope).Free();
|
|
_labelsInScope.Free();
|
|
}
|
|
|
|
public override BoundNode VisitMethodGroup(BoundMethodGroup node)
|
|
{
|
|
throw ExceptionUtilities.Unreachable("/_/src/Compilers/CSharp/Portable/Lowering/ClosureConversion/ClosureConversion.Analysis.Tree.cs", 396);
|
|
}
|
|
|
|
public override BoundNode VisitBlock(BoundBlock node)
|
|
{
|
|
Scope currentScope = _currentScope;
|
|
PushOrReuseScope(node, node.Locals);
|
|
BoundNode? result = base.VisitBlock(node);
|
|
PopScope(currentScope);
|
|
return result;
|
|
}
|
|
|
|
public override BoundNode VisitCatchBlock(BoundCatchBlock node)
|
|
{
|
|
Scope currentScope = _currentScope;
|
|
PushOrReuseScope(node, node.Locals);
|
|
BoundNode? result = base.VisitCatchBlock(node);
|
|
PopScope(currentScope);
|
|
return result;
|
|
}
|
|
|
|
public override BoundNode VisitSequence(BoundSequence node)
|
|
{
|
|
Scope currentScope = _currentScope;
|
|
PushOrReuseScope(node, node.Locals);
|
|
BoundNode? result = base.VisitSequence(node);
|
|
PopScope(currentScope);
|
|
return result;
|
|
}
|
|
|
|
public override BoundNode VisitLambda(BoundLambda node)
|
|
{
|
|
bool inExpressionTree = _inExpressionTree;
|
|
_inExpressionTree |= node.Type.IsExpressionTree();
|
|
_methodsConvertedToDelegates.Add(node.Symbol.OriginalDefinition);
|
|
BoundNode? result = VisitNestedFunction(node.Symbol, node.Body);
|
|
_inExpressionTree = inExpressionTree;
|
|
return result;
|
|
}
|
|
|
|
public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
|
|
{
|
|
return VisitNestedFunction(node.Symbol.OriginalDefinition, node.Body);
|
|
}
|
|
|
|
protected override void VisitArguments(BoundCall node)
|
|
{
|
|
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_000d: Invalid comparison between Unknown and I4
|
|
if ((int)node.Method.MethodKind == 17)
|
|
{
|
|
AddIfCaptured(node.Method.OriginalDefinition, node.Syntax);
|
|
}
|
|
base.VisitArguments(node);
|
|
}
|
|
|
|
public override BoundNode VisitDelegateCreationExpression(BoundDelegateCreationExpression node)
|
|
{
|
|
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0014: Invalid comparison between Unknown and I4
|
|
MethodSymbol? methodOpt = node.MethodOpt;
|
|
if ((object)methodOpt != null && (int)methodOpt.MethodKind == 17)
|
|
{
|
|
MethodSymbol originalDefinition = node.MethodOpt.OriginalDefinition;
|
|
AddIfCaptured(originalDefinition, node.Syntax);
|
|
_methodsConvertedToDelegates.Add(originalDefinition);
|
|
}
|
|
return base.VisitDelegateCreationExpression(node);
|
|
}
|
|
|
|
public override BoundNode VisitParameter(BoundParameter node)
|
|
{
|
|
AddIfCaptured(node.ParameterSymbol, node.Syntax);
|
|
return base.VisitParameter(node);
|
|
}
|
|
|
|
public override BoundNode VisitLocal(BoundLocal node)
|
|
{
|
|
AddIfCaptured(node.LocalSymbol, node.Syntax);
|
|
return base.VisitLocal(node);
|
|
}
|
|
|
|
public override BoundNode VisitBaseReference(BoundBaseReference node)
|
|
{
|
|
AddIfCaptured(_topLevelMethod.ThisParameter, node.Syntax);
|
|
return base.VisitBaseReference(node);
|
|
}
|
|
|
|
public override BoundNode VisitThisReference(BoundThisReference node)
|
|
{
|
|
ParameterSymbol thisParameter = _topLevelMethod.ThisParameter;
|
|
if (thisParameter != null)
|
|
{
|
|
AddIfCaptured(thisParameter, node.Syntax);
|
|
}
|
|
return base.VisitThisReference(node);
|
|
}
|
|
|
|
public override BoundNode VisitLabelStatement(BoundLabelStatement node)
|
|
{
|
|
ArrayBuilderExtensions.Peek<ArrayBuilder<LabelSymbol>>(_labelsInScope).Add(node.Label);
|
|
((Dictionary<LabelSymbol, ArrayBuilder<Scope>>)(object)_scopesAfterLabel).Add(node.Label, ArrayBuilder<Scope>.GetInstance());
|
|
return base.VisitLabelStatement(node);
|
|
}
|
|
|
|
public override BoundNode VisitGotoStatement(BoundGotoStatement node)
|
|
{
|
|
CheckCanMergeWithParent(node.Label);
|
|
return base.VisitGotoStatement(node);
|
|
}
|
|
|
|
public override BoundNode VisitConditionalGoto(BoundConditionalGoto node)
|
|
{
|
|
CheckCanMergeWithParent(node.Label);
|
|
return base.VisitConditionalGoto(node);
|
|
}
|
|
|
|
private void CheckCanMergeWithParent(LabelSymbol jumpTarget)
|
|
{
|
|
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
|
|
if (((Dictionary<LabelSymbol, ArrayBuilder<Scope>>)(object)_scopesAfterLabel).TryGetValue(jumpTarget, out ArrayBuilder<Scope> value))
|
|
{
|
|
Enumerator<Scope> enumerator = value.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
enumerator.Current.CanMergeWithParent = false;
|
|
}
|
|
value.Clear();
|
|
}
|
|
}
|
|
|
|
private BoundNode? VisitNestedFunction(MethodSymbol functionSymbol, BoundBlock? body)
|
|
{
|
|
if (body == null)
|
|
{
|
|
_currentScope.NestedFunctions.Add(new NestedFunction(functionSymbol, null));
|
|
return null;
|
|
}
|
|
NestedFunction nestedFunction = new NestedFunction(functionSymbol, body.Syntax.GetReference());
|
|
_currentScope.NestedFunctions.Add(nestedFunction);
|
|
NestedFunction currentFunction = _currentFunction;
|
|
_currentFunction = nestedFunction;
|
|
Scope currentScope = _currentScope;
|
|
CreateAndPushScope(body);
|
|
DeclareLocals(_currentScope, functionSymbol.Parameters, _inExpressionTree);
|
|
BoundNode result = (_inExpressionTree ? base.VisitBlock(body) : VisitBlock(body));
|
|
PopScope(currentScope);
|
|
_currentFunction = currentFunction;
|
|
return result;
|
|
}
|
|
|
|
private void AddIfCaptured(Symbol symbol, SyntaxNode syntax)
|
|
{
|
|
//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00ae: Invalid comparison between Unknown and I4
|
|
if (_currentFunction == null || symbol is LocalSymbol { IsConst: not false } || (symbol is MethodSymbol methodSymbol && _currentFunction.OriginalMethodSymbol == methodSymbol) || !(symbol.ContainingSymbol != _currentFunction.OriginalMethodSymbol))
|
|
{
|
|
return;
|
|
}
|
|
AddDiagnosticIfRestrictedType(symbol, syntax);
|
|
Scope scope = _currentScope;
|
|
NestedFunction nestedFunction = _currentFunction;
|
|
while (nestedFunction != null && symbol.ContainingSymbol != nestedFunction.OriginalMethodSymbol)
|
|
{
|
|
((HashSet<Symbol>)(object)nestedFunction.CapturedVariables).Add(symbol);
|
|
while (scope.ContainingFunctionOpt == nestedFunction)
|
|
{
|
|
scope = scope.Parent;
|
|
}
|
|
nestedFunction = scope.ContainingFunctionOpt;
|
|
}
|
|
Scope scope2 = default(Scope);
|
|
if ((int)symbol.Kind != 9 && _localToScope.TryGetValue(symbol, ref scope2))
|
|
{
|
|
scope2.DeclaredVariables.Add(symbol);
|
|
}
|
|
}
|
|
|
|
private void AddDiagnosticIfRestrictedType(Symbol capturedVariable, SyntaxNode syntax)
|
|
{
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0009: Invalid comparison between Unknown and I4
|
|
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_000e: Invalid comparison between Unknown and I4
|
|
SymbolKind kind = capturedVariable.Kind;
|
|
TypeSymbol type;
|
|
if ((int)kind != 8)
|
|
{
|
|
if ((int)kind != 13)
|
|
{
|
|
return;
|
|
}
|
|
type = ((ParameterSymbol)capturedVariable).Type;
|
|
}
|
|
else
|
|
{
|
|
type = ((LocalSymbol)capturedVariable).Type;
|
|
}
|
|
if (type.IsRestrictedType())
|
|
{
|
|
_diagnostics.Add(ErrorCode.ERR_SpecialByRefInLambda, syntax.Location, type);
|
|
}
|
|
}
|
|
|
|
private void PushOrReuseScope<TSymbol>(BoundNode node, ImmutableArray<TSymbol> locals) where TSymbol : Symbol
|
|
{
|
|
if (!locals.IsEmpty && _currentScope.BoundNode != node)
|
|
{
|
|
CreateAndPushScope(node);
|
|
}
|
|
DeclareLocals(_currentScope, locals);
|
|
}
|
|
|
|
private void CreateAndPushScope(BoundNode node)
|
|
{
|
|
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
|
|
Scope scope = CreateNestedScope(_currentScope, _currentFunction);
|
|
Enumerator<LabelSymbol> enumerator = ArrayBuilderExtensions.Peek<ArrayBuilder<LabelSymbol>>(_labelsInScope).GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
LabelSymbol current = enumerator.Current;
|
|
((Dictionary<LabelSymbol, ArrayBuilder<Scope>>)(object)_scopesAfterLabel)[current].Add(scope);
|
|
}
|
|
ArrayBuilderExtensions.Push<ArrayBuilder<LabelSymbol>>(_labelsInScope, ArrayBuilder<LabelSymbol>.GetInstance());
|
|
_currentScope = scope;
|
|
Scope CreateNestedScope(Scope parentScope, NestedFunction currentFunction)
|
|
{
|
|
Scope scope2 = new Scope(parentScope, node, currentFunction);
|
|
parentScope.NestedScopes.Add(scope2);
|
|
return scope2;
|
|
}
|
|
}
|
|
|
|
private void PopScope(Scope scope)
|
|
{
|
|
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
|
|
if (scope != _currentScope)
|
|
{
|
|
ArrayBuilder<LabelSymbol> val = ArrayBuilderExtensions.Pop<ArrayBuilder<LabelSymbol>>(_labelsInScope);
|
|
Enumerator<LabelSymbol> enumerator = val.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
LabelSymbol current = enumerator.Current;
|
|
((Dictionary<LabelSymbol, ArrayBuilder<Scope>>)(object)_scopesAfterLabel)[current].Free();
|
|
((Dictionary<LabelSymbol, ArrayBuilder<Scope>>)(object)_scopesAfterLabel).Remove(current);
|
|
}
|
|
val.Free();
|
|
_currentScope = _currentScope.Parent;
|
|
}
|
|
}
|
|
|
|
private void DeclareLocals<TSymbol>(Scope scope, ImmutableArray<TSymbol> locals, bool declareAsFree = false) where TSymbol : Symbol
|
|
{
|
|
ImmutableArray<TSymbol>.Enumerator enumerator = locals.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
TSymbol current = enumerator.Current;
|
|
if (!declareAsFree)
|
|
{
|
|
_localToScope.Add((Symbol)current, scope);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public readonly PooledHashSet<MethodSymbol> MethodsConvertedToDelegates;
|
|
|
|
public readonly Scope ScopeTree;
|
|
|
|
private readonly MethodSymbol _topLevelMethod;
|
|
|
|
private readonly int _topLevelMethodOrdinal;
|
|
|
|
private readonly VariableSlotAllocator _slotAllocatorOpt;
|
|
|
|
private readonly TypeCompilationState _compilationState;
|
|
|
|
public bool CanTakeRefParameters(MethodSymbol function)
|
|
{
|
|
if (!function.IsAsync && !function.IsIterator)
|
|
{
|
|
return !((HashSet<MethodSymbol>)(object)MethodsConvertedToDelegates).Contains(function);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private Analysis(Scope scopeTree, PooledHashSet<MethodSymbol> methodsConvertedToDelegates, MethodSymbol topLevelMethod, int topLevelMethodOrdinal, VariableSlotAllocator slotAllocatorOpt, TypeCompilationState compilationState)
|
|
{
|
|
ScopeTree = scopeTree;
|
|
MethodsConvertedToDelegates = methodsConvertedToDelegates;
|
|
_topLevelMethod = topLevelMethod;
|
|
_topLevelMethodOrdinal = topLevelMethodOrdinal;
|
|
_slotAllocatorOpt = slotAllocatorOpt;
|
|
_compilationState = compilationState;
|
|
}
|
|
|
|
public static Analysis Analyze(BoundNode node, MethodSymbol method, int topLevelMethodOrdinal, VariableSlotAllocator slotAllocatorOpt, TypeCompilationState compilationState, DiagnosticBag diagnostics)
|
|
{
|
|
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_003a: Invalid comparison between Unknown and I4
|
|
PooledHashSet<MethodSymbol> instance = PooledHashSet<MethodSymbol>.GetInstance();
|
|
Analysis analysis = new Analysis(ScopeTreeBuilder.Build(node, method, (HashSet<MethodSymbol>)(object)instance, diagnostics), instance, method, topLevelMethodOrdinal, slotAllocatorOpt, compilationState);
|
|
analysis.MakeAndAssignEnvironments();
|
|
analysis.ComputeLambdaScopesAndFrameCaptures();
|
|
if ((int)((CompilationOptions)compilationState.Compilation.Options).OptimizationLevel == 1)
|
|
{
|
|
analysis.MergeEnvironments();
|
|
}
|
|
analysis.InlineThisOnlyEnvironments();
|
|
return analysis;
|
|
}
|
|
|
|
private static BoundNode FindNodeToAnalyze(BoundNode node)
|
|
{
|
|
while (true)
|
|
{
|
|
switch (node.Kind)
|
|
{
|
|
case BoundKind.SequencePoint:
|
|
node = ((BoundSequencePoint)node).StatementOpt;
|
|
break;
|
|
case BoundKind.SequencePointWithSpan:
|
|
node = ((BoundSequencePointWithSpan)node).StatementOpt;
|
|
break;
|
|
case BoundKind.FieldEqualsValue:
|
|
case BoundKind.Block:
|
|
case BoundKind.StatementList:
|
|
return node;
|
|
case BoundKind.GlobalStatementInitializer:
|
|
return ((BoundGlobalStatementInitializer)node).Statement;
|
|
default:
|
|
throw ExceptionUtilities.UnexpectedValue((object)node.Kind);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void ComputeLambdaScopesAndFrameCaptures()
|
|
{
|
|
VisitNestedFunctions(ScopeTree, delegate(Scope scope, NestedFunction function)
|
|
{
|
|
if (function.CapturedEnvironments.Count > 0)
|
|
{
|
|
PooledHashSet<ClosureEnvironment> instance = PooledHashSet<ClosureEnvironment>.GetInstance();
|
|
ISetExtensions.AddAll<ClosureEnvironment>((ISet<ClosureEnvironment>)instance, (IEnumerable<ClosureEnvironment>)function.CapturedEnvironments);
|
|
Scope scope2;
|
|
for (scope2 = scope; scope2 != null; scope2 = scope2.Parent)
|
|
{
|
|
ClosureEnvironment declaredEnvironment = scope2.DeclaredEnvironment;
|
|
if (declaredEnvironment != null && ((HashSet<ClosureEnvironment>)(object)instance).Remove(declaredEnvironment) && !declaredEnvironment.IsStruct)
|
|
{
|
|
function.ContainingEnvironmentOpt = declaredEnvironment;
|
|
break;
|
|
}
|
|
}
|
|
ClosureEnvironment closureEnvironment = scope2?.DeclaredEnvironment;
|
|
scope2 = scope2?.Parent;
|
|
while (scope2 != null && ((HashSet<ClosureEnvironment>)(object)instance).Count != 0)
|
|
{
|
|
ClosureEnvironment declaredEnvironment2 = scope2.DeclaredEnvironment;
|
|
if (declaredEnvironment2 != null)
|
|
{
|
|
if (!declaredEnvironment2.IsStruct)
|
|
{
|
|
closureEnvironment.CapturesParent = true;
|
|
closureEnvironment = declaredEnvironment2;
|
|
}
|
|
((HashSet<ClosureEnvironment>)(object)instance).Remove(declaredEnvironment2);
|
|
}
|
|
scope2 = scope2.Parent;
|
|
}
|
|
if (((HashSet<ClosureEnvironment>)(object)instance).Count > 0)
|
|
{
|
|
throw ExceptionUtilities.Unreachable("/_/src/Compilers/CSharp/Portable/Lowering/ClosureConversion/ClosureConversion.Analysis.cs", 188);
|
|
}
|
|
instance.Free();
|
|
}
|
|
});
|
|
}
|
|
|
|
private void InlineThisOnlyEnvironments()
|
|
{
|
|
if (!_topLevelMethod.TryGetThisParameter(out var thisParameter) || thisParameter == null)
|
|
{
|
|
return;
|
|
}
|
|
ClosureEnvironment env = ScopeTree.DeclaredEnvironment;
|
|
if (env == null || env.CapturedVariables.Count > 1 || !env.CapturedVariables.Contains((Symbol)thisParameter))
|
|
{
|
|
return;
|
|
}
|
|
if (env.IsStruct)
|
|
{
|
|
if (!CheckNestedFunctions(ScopeTree, (Scope scope, NestedFunction closure) => closure.CapturedEnvironments.Contains(env) && closure.ContainingEnvironmentOpt != null))
|
|
{
|
|
RemoveEnv();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((object)VarianceSafety.GetEnclosingVariantInterface(_topLevelMethod) != null)
|
|
{
|
|
return;
|
|
}
|
|
RemoveEnv();
|
|
VisitNestedFunctions(ScopeTree, delegate(Scope scope, NestedFunction closure)
|
|
{
|
|
if (closure.ContainingEnvironmentOpt == env)
|
|
{
|
|
closure.ContainingEnvironmentOpt = null;
|
|
}
|
|
});
|
|
}
|
|
void RemoveEnv()
|
|
{
|
|
ScopeTree.DeclaredEnvironment = null;
|
|
VisitNestedFunctions(ScopeTree, delegate(Scope scope, NestedFunction nested)
|
|
{
|
|
int num = nested.CapturedEnvironments.IndexOf(env);
|
|
if (num >= 0)
|
|
{
|
|
nested.CapturedEnvironments.RemoveAt(num);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
private void MakeAndAssignEnvironments()
|
|
{
|
|
VisitScopeTree(ScopeTree, delegate(Scope scope)
|
|
{
|
|
SetWithInsertionOrder<Symbol> declaredVariables = scope.DeclaredVariables;
|
|
if (declaredVariables.Count == 0)
|
|
{
|
|
return;
|
|
}
|
|
bool isStruct = (object)VarianceSafety.GetEnclosingVariantInterface(_topLevelMethod) == null;
|
|
SetWithInsertionOrder<NestedFunction> closures = new SetWithInsertionOrder<NestedFunction>();
|
|
bool addedItem;
|
|
do
|
|
{
|
|
addedItem = false;
|
|
VisitNestedFunctions(scope, delegate(Scope closureScope, NestedFunction closure)
|
|
{
|
|
if (!closures.Contains(closure) && (((HashSet<Symbol>)(object)closure.CapturedVariables).Overlaps((IEnumerable<Symbol>)scope.DeclaredVariables) || ((HashSet<Symbol>)(object)closure.CapturedVariables).Overlaps((IEnumerable<Symbol>)((IEnumerable<NestedFunction>)closures).Select((NestedFunction c) => c.OriginalMethodSymbol))))
|
|
{
|
|
closures.Add(closure);
|
|
addedItem = true;
|
|
isStruct &= CanTakeRefParameters(closure.OriginalMethodSymbol);
|
|
}
|
|
});
|
|
}
|
|
while (addedItem);
|
|
ClosureEnvironment closureEnvironment = new ClosureEnvironment((IEnumerable<Symbol>)declaredVariables, isStruct);
|
|
scope.DeclaredEnvironment = closureEnvironment;
|
|
_topLevelMethod.TryGetThisParameter(out var thisParameter);
|
|
foreach (NestedFunction item in closures)
|
|
{
|
|
item.CapturedEnvironments.Add(closureEnvironment);
|
|
if (thisParameter != null && closureEnvironment.CapturedVariables.Contains((Symbol)thisParameter))
|
|
{
|
|
item.CapturesThis = true;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
private PooledDictionary<Scope, PooledHashSet<NestedFunction>> CalculateFunctionsCapturingScopeVariables()
|
|
{
|
|
PooledDictionary<Scope, PooledHashSet<NestedFunction>> closuresCapturingScopeVariables = PooledDictionary<Scope, PooledHashSet<NestedFunction>>.GetInstance();
|
|
PooledDictionary<ClosureEnvironment, Scope> environmentsToScopes = PooledDictionary<ClosureEnvironment, Scope>.GetInstance();
|
|
VisitScopeTree(ScopeTree, delegate(Scope scope4)
|
|
{
|
|
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
|
|
if (scope4.DeclaredEnvironment != null)
|
|
{
|
|
((Dictionary<Scope, PooledHashSet<NestedFunction>>)(object)closuresCapturingScopeVariables)[scope4] = PooledHashSet<NestedFunction>.GetInstance();
|
|
((Dictionary<ClosureEnvironment, Scope>)(object)environmentsToScopes)[scope4.DeclaredEnvironment] = scope4;
|
|
}
|
|
Enumerator<NestedFunction> enumerator2 = scope4.NestedFunctions.GetEnumerator();
|
|
while (enumerator2.MoveNext())
|
|
{
|
|
NestedFunction current = enumerator2.Current;
|
|
Enumerator<ClosureEnvironment> enumerator3 = current.CapturedEnvironments.GetEnumerator();
|
|
while (enumerator3.MoveNext())
|
|
{
|
|
ClosureEnvironment current2 = enumerator3.Current;
|
|
((HashSet<NestedFunction>)(object)((Dictionary<Scope, PooledHashSet<NestedFunction>>)(object)closuresCapturingScopeVariables)[((Dictionary<ClosureEnvironment, Scope>)(object)environmentsToScopes)[current2]]).Add(current);
|
|
}
|
|
}
|
|
});
|
|
environmentsToScopes.Free();
|
|
Scope scope = default(Scope);
|
|
PooledHashSet<NestedFunction> val = default(PooledHashSet<NestedFunction>);
|
|
foreach (KeyValuePair<Scope, PooledHashSet<NestedFunction>> item in (Dictionary<Scope, PooledHashSet<NestedFunction>>)(object)closuresCapturingScopeVariables)
|
|
{
|
|
KeyValuePairUtil.Deconstruct<Scope, PooledHashSet<NestedFunction>>(item, ref scope, ref val);
|
|
Scope scope2 = scope;
|
|
PooledHashSet<NestedFunction> val2 = val;
|
|
if (scope2.DeclaredEnvironment == null)
|
|
{
|
|
continue;
|
|
}
|
|
Scope scope3 = scope2;
|
|
while (scope3.DeclaredEnvironment == null || scope3.DeclaredEnvironment.CapturesParent)
|
|
{
|
|
scope3 = scope3.Parent;
|
|
if (scope3 == null)
|
|
{
|
|
throw ExceptionUtilities.Unreachable("/_/src/Compilers/CSharp/Portable/Lowering/ClosureConversion/ClosureConversion.Analysis.cs", 402);
|
|
}
|
|
if (scope3.DeclaredEnvironment != null && !scope3.DeclaredEnvironment.IsStruct)
|
|
{
|
|
ISetExtensions.AddAll<NestedFunction>((ISet<NestedFunction>)((Dictionary<Scope, PooledHashSet<NestedFunction>>)(object)closuresCapturingScopeVariables)[scope3], (IEnumerable<NestedFunction>)val2);
|
|
}
|
|
}
|
|
}
|
|
return closuresCapturingScopeVariables;
|
|
}
|
|
|
|
private void MergeEnvironments()
|
|
{
|
|
PooledDictionary<Scope, PooledHashSet<NestedFunction>> val = CalculateFunctionsCapturingScopeVariables();
|
|
Scope scope = default(Scope);
|
|
PooledHashSet<NestedFunction> val2 = default(PooledHashSet<NestedFunction>);
|
|
foreach (KeyValuePair<Scope, PooledHashSet<NestedFunction>> item in (Dictionary<Scope, PooledHashSet<NestedFunction>>)(object)val)
|
|
{
|
|
KeyValuePairUtil.Deconstruct<Scope, PooledHashSet<NestedFunction>>(item, ref scope, ref val2);
|
|
Scope scope2 = scope;
|
|
PooledHashSet<NestedFunction> val3 = val2;
|
|
if (((HashSet<NestedFunction>)(object)val3).Count == 0)
|
|
{
|
|
continue;
|
|
}
|
|
ClosureEnvironment declaredEnvironment = scope2.DeclaredEnvironment;
|
|
if (declaredEnvironment.IsStruct)
|
|
{
|
|
continue;
|
|
}
|
|
Scope scope3 = scope2;
|
|
Scope scope4 = scope2;
|
|
while (scope4.Parent != null && scope4.CanMergeWithParent)
|
|
{
|
|
Scope parent = scope4.Parent;
|
|
ClosureEnvironment declaredEnvironment2 = parent.DeclaredEnvironment;
|
|
if (declaredEnvironment2 == null || declaredEnvironment2.IsStruct)
|
|
{
|
|
scope4 = parent;
|
|
continue;
|
|
}
|
|
if (!((HashSet<NestedFunction>)(object)((Dictionary<Scope, PooledHashSet<NestedFunction>>)(object)val)[parent]).SetEquals((IEnumerable<NestedFunction>)val3))
|
|
{
|
|
break;
|
|
}
|
|
scope3 = parent;
|
|
scope4 = parent;
|
|
}
|
|
if (scope3 == scope2)
|
|
{
|
|
continue;
|
|
}
|
|
ClosureEnvironment declaredEnvironment3 = scope3.DeclaredEnvironment;
|
|
foreach (Symbol capturedVariable in declaredEnvironment.CapturedVariables)
|
|
{
|
|
declaredEnvironment3.CapturedVariables.Add(capturedVariable);
|
|
}
|
|
scope2.DeclaredEnvironment = null;
|
|
foreach (NestedFunction item2 in (HashSet<NestedFunction>)(object)val3)
|
|
{
|
|
item2.CapturedEnvironments.Remove(declaredEnvironment);
|
|
if (!item2.CapturedEnvironments.Contains(declaredEnvironment3))
|
|
{
|
|
item2.CapturedEnvironments.Add(declaredEnvironment3);
|
|
}
|
|
if (item2.ContainingEnvironmentOpt == declaredEnvironment)
|
|
{
|
|
item2.ContainingEnvironmentOpt = declaredEnvironment3;
|
|
}
|
|
}
|
|
}
|
|
foreach (PooledHashSet<NestedFunction> value in ((Dictionary<Scope, PooledHashSet<NestedFunction>>)(object)val).Values)
|
|
{
|
|
value.Free();
|
|
}
|
|
val.Free();
|
|
}
|
|
|
|
internal DebugId GetTopLevelMethodId()
|
|
{
|
|
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
|
|
VariableSlotAllocator slotAllocatorOpt = _slotAllocatorOpt;
|
|
return (DebugId)(((_003F?)((slotAllocatorOpt != null) ? slotAllocatorOpt.MethodId : ((DebugId?)null))) ?? new DebugId(_topLevelMethodOrdinal, ((CommonPEModuleBuilder)_compilationState.ModuleBuilderOpt).CurrentGenerationOrdinal));
|
|
}
|
|
|
|
internal DebugId GetClosureId(SyntaxNode syntax, ArrayBuilder<ClosureDebugInfo> closureDebugInfo)
|
|
{
|
|
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
|
|
DebugId val = default(DebugId);
|
|
DebugId val2 = default(DebugId);
|
|
if (_slotAllocatorOpt != null && _slotAllocatorOpt.TryGetPreviousClosure(syntax, ref val))
|
|
{
|
|
val2 = val;
|
|
}
|
|
else
|
|
{
|
|
((DebugId)(ref val2))._002Ector(closureDebugInfo.Count, ((CommonPEModuleBuilder)_compilationState.ModuleBuilderOpt).CurrentGenerationOrdinal);
|
|
}
|
|
int num = _topLevelMethod.CalculateLocalSyntaxOffset(LambdaUtilities.GetDeclaratorPosition(syntax), syntax.SyntaxTree);
|
|
closureDebugInfo.Add(new ClosureDebugInfo(num, val2));
|
|
return val2;
|
|
}
|
|
|
|
public static Scope GetVariableDeclarationScope(Scope startingScope, Symbol variable)
|
|
{
|
|
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0021: Invalid comparison between Unknown and I4
|
|
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0026: Invalid comparison between Unknown and I4
|
|
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_002b: Invalid comparison between Unknown and I4
|
|
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
|
|
if (variable is ParameterSymbol { IsThis: not false })
|
|
{
|
|
return null;
|
|
}
|
|
for (Scope scope = startingScope; scope != null; scope = scope.Parent)
|
|
{
|
|
SymbolKind kind = variable.Kind;
|
|
if ((int)kind != 8)
|
|
{
|
|
if ((int)kind == 9)
|
|
{
|
|
Enumerator<NestedFunction> enumerator = scope.NestedFunctions.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
if (enumerator.Current.OriginalMethodSymbol == variable)
|
|
{
|
|
return scope;
|
|
}
|
|
}
|
|
continue;
|
|
}
|
|
if ((int)kind != 13)
|
|
{
|
|
throw ExceptionUtilities.UnexpectedValue((object)variable.Kind);
|
|
}
|
|
}
|
|
if (scope.DeclaredVariables.Contains(variable))
|
|
{
|
|
return scope;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public static Scope GetScopeParent(Scope treeRoot, BoundNode scopeNode)
|
|
{
|
|
return GetScopeWithMatchingBoundNode(treeRoot, scopeNode).Parent;
|
|
}
|
|
|
|
public static Scope GetScopeWithMatchingBoundNode(Scope treeRoot, BoundNode node)
|
|
{
|
|
return Helper(treeRoot) ?? throw ExceptionUtilities.Unreachable("/_/src/Compilers/CSharp/Portable/Lowering/ClosureConversion/ClosureConversion.Analysis.cs", 601);
|
|
Scope Helper(Scope currentScope)
|
|
{
|
|
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
|
|
if (currentScope.BoundNode == node)
|
|
{
|
|
return currentScope;
|
|
}
|
|
Enumerator<Scope> enumerator = currentScope.NestedScopes.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
Scope scope = Helper(enumerator.Current);
|
|
if (scope != null)
|
|
{
|
|
return scope;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public static (NestedFunction, Scope) GetVisibleNestedFunction(Scope startingScope, MethodSymbol functionSymbol)
|
|
{
|
|
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
|
|
for (Scope scope = startingScope; scope != null; scope = scope.Parent)
|
|
{
|
|
Enumerator<NestedFunction> enumerator = scope.NestedFunctions.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
NestedFunction current = enumerator.Current;
|
|
if (current.OriginalMethodSymbol == functionSymbol)
|
|
{
|
|
return (current, scope);
|
|
}
|
|
}
|
|
}
|
|
throw ExceptionUtilities.Unreachable("/_/src/Compilers/CSharp/Portable/Lowering/ClosureConversion/ClosureConversion.Analysis.cs", 643);
|
|
}
|
|
|
|
public static NestedFunction GetNestedFunctionInTree(Scope treeRoot, MethodSymbol functionSymbol)
|
|
{
|
|
return helper(treeRoot) ?? throw ExceptionUtilities.Unreachable("/_/src/Compilers/CSharp/Portable/Lowering/ClosureConversion/ClosureConversion.Analysis.cs", 651);
|
|
NestedFunction helper(Scope scope)
|
|
{
|
|
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
|
|
Enumerator<NestedFunction> enumerator = scope.NestedFunctions.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
NestedFunction current = enumerator.Current;
|
|
if (current.OriginalMethodSymbol == functionSymbol)
|
|
{
|
|
return current;
|
|
}
|
|
}
|
|
Enumerator<Scope> enumerator2 = scope.NestedScopes.GetEnumerator();
|
|
while (enumerator2.MoveNext())
|
|
{
|
|
NestedFunction nestedFunction = helper(enumerator2.Current);
|
|
if (nestedFunction != null)
|
|
{
|
|
return nestedFunction;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public void Free()
|
|
{
|
|
MethodsConvertedToDelegates.Free();
|
|
ScopeTree.Free();
|
|
}
|
|
|
|
public static void VisitNestedFunctions(Scope scope, Action<Scope, NestedFunction> action)
|
|
{
|
|
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
|
|
Enumerator<NestedFunction> enumerator = scope.NestedFunctions.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
NestedFunction current = enumerator.Current;
|
|
action(scope, current);
|
|
}
|
|
Enumerator<Scope> enumerator2 = scope.NestedScopes.GetEnumerator();
|
|
while (enumerator2.MoveNext())
|
|
{
|
|
VisitNestedFunctions(enumerator2.Current, action);
|
|
}
|
|
}
|
|
|
|
public static bool CheckNestedFunctions(Scope scope, Func<Scope, NestedFunction, bool> func)
|
|
{
|
|
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
|
|
Enumerator<NestedFunction> enumerator = scope.NestedFunctions.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
NestedFunction current = enumerator.Current;
|
|
if (func(scope, current))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
Enumerator<Scope> enumerator2 = scope.NestedScopes.GetEnumerator();
|
|
while (enumerator2.MoveNext())
|
|
{
|
|
if (CheckNestedFunctions(enumerator2.Current, func))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static void VisitScopeTree(Scope treeRoot, Action<Scope> action)
|
|
{
|
|
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
|
|
action(treeRoot);
|
|
Enumerator<Scope> enumerator = treeRoot.NestedScopes.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
VisitScopeTree(enumerator.Current, action);
|
|
}
|
|
}
|
|
}
|
|
|
|
private readonly Analysis _analysis;
|
|
|
|
private readonly MethodSymbol _topLevelMethod;
|
|
|
|
private readonly MethodSymbol _substitutedSourceMethod;
|
|
|
|
private readonly int _topLevelMethodOrdinal;
|
|
|
|
private SynthesizedClosureEnvironment _lazyStaticLambdaFrame;
|
|
|
|
private readonly Dictionary<ParameterSymbol, ParameterSymbol> _parameterMap = new Dictionary<ParameterSymbol, ParameterSymbol>();
|
|
|
|
private readonly Dictionary<BoundNode, Analysis.ClosureEnvironment> _frames = new Dictionary<BoundNode, Analysis.ClosureEnvironment>();
|
|
|
|
private readonly Dictionary<NamedTypeSymbol, Symbol> _framePointers = new Dictionary<NamedTypeSymbol, Symbol>();
|
|
|
|
private readonly HashSet<LocalSymbol> _assignLocals;
|
|
|
|
private MethodSymbol _currentMethod;
|
|
|
|
private ParameterSymbol _currentFrameThis;
|
|
|
|
private readonly ArrayBuilder<LambdaDebugInfo> _lambdaDebugInfoBuilder;
|
|
|
|
private int _synthesizedFieldNameIdDispenser;
|
|
|
|
private Symbol _innermostFramePointer;
|
|
|
|
private TypeMap _currentLambdaBodyTypeMap;
|
|
|
|
private ImmutableArray<TypeParameterSymbol> _currentTypeParameters;
|
|
|
|
private BoundExpression _thisProxyInitDeferred;
|
|
|
|
private bool _seenBaseCall;
|
|
|
|
private bool _inExpressionLambda;
|
|
|
|
private ArrayBuilder<LocalSymbol> _addedLocals;
|
|
|
|
private ArrayBuilder<BoundStatement> _addedStatements;
|
|
|
|
private ArrayBuilder<TypeCompilationState.MethodWithBody> _synthesizedMethods;
|
|
|
|
private readonly ImmutableHashSet<Symbol> _allCapturedVariables;
|
|
|
|
protected override TypeMap TypeMap => _currentLambdaBodyTypeMap;
|
|
|
|
protected override MethodSymbol CurrentMethod => _currentMethod;
|
|
|
|
protected override NamedTypeSymbol ContainingType => _topLevelMethod.ContainingType;
|
|
|
|
private ClosureConversion(Analysis analysis, NamedTypeSymbol thisType, ParameterSymbol thisParameterOpt, MethodSymbol method, int methodOrdinal, MethodSymbol substitutedSourceMethod, ArrayBuilder<LambdaDebugInfo> lambdaDebugInfoBuilder, VariableSlotAllocator slotAllocatorOpt, TypeCompilationState compilationState, BindingDiagnosticBag diagnostics, HashSet<LocalSymbol> assignLocals)
|
|
: base(slotAllocatorOpt, compilationState, diagnostics)
|
|
{
|
|
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00a8: Invalid comparison between Unknown and I4
|
|
_topLevelMethod = method;
|
|
_substitutedSourceMethod = substitutedSourceMethod;
|
|
_topLevelMethodOrdinal = methodOrdinal;
|
|
_lambdaDebugInfoBuilder = lambdaDebugInfoBuilder;
|
|
_currentMethod = method;
|
|
_analysis = analysis;
|
|
_assignLocals = assignLocals;
|
|
_currentTypeParameters = method.TypeParameters;
|
|
_currentLambdaBodyTypeMap = TypeMap.Empty;
|
|
_innermostFramePointer = (_currentFrameThis = thisParameterOpt);
|
|
_framePointers[thisType] = thisParameterOpt;
|
|
_seenBaseCall = (int)method.MethodKind != 1;
|
|
_synthesizedFieldNameIdDispenser = 1;
|
|
ImmutableHashSet<Symbol>.Builder allCapturedVars = ImmutableHashSet.CreateBuilder<Symbol>();
|
|
Analysis.VisitNestedFunctions(analysis.ScopeTree, delegate(Analysis.Scope scope, Analysis.NestedFunction function)
|
|
{
|
|
allCapturedVars.UnionWith((IEnumerable<Symbol>)function.CapturedVariables);
|
|
});
|
|
_allCapturedVariables = allCapturedVars.ToImmutable();
|
|
}
|
|
|
|
protected override bool NeedsProxy(Symbol localOrParameter)
|
|
{
|
|
return _allCapturedVariables.Contains(localOrParameter);
|
|
}
|
|
|
|
public static BoundStatement Rewrite(BoundStatement loweredBody, NamedTypeSymbol thisType, ParameterSymbol thisParameter, MethodSymbol method, int methodOrdinal, MethodSymbol substitutedSourceMethod, ArrayBuilder<LambdaDebugInfo> lambdaDebugInfoBuilder, ArrayBuilder<ClosureDebugInfo> closureDebugInfoBuilder, VariableSlotAllocator slotAllocatorOpt, TypeCompilationState compilationState, BindingDiagnosticBag diagnostics, HashSet<LocalSymbol> assignLocals)
|
|
{
|
|
Analysis analysis = Analysis.Analyze(loweredBody, method, methodOrdinal, slotAllocatorOpt, compilationState, ((BindingDiagnosticBag)diagnostics).DiagnosticBag);
|
|
ClosureConversion closureConversion = new ClosureConversion(analysis, thisType, thisParameter, method, methodOrdinal, substitutedSourceMethod, lambdaDebugInfoBuilder, slotAllocatorOpt, compilationState, diagnostics, assignLocals);
|
|
closureConversion.SynthesizeClosureEnvironments(closureDebugInfoBuilder);
|
|
closureConversion.SynthesizeClosureMethods();
|
|
BoundStatement result = closureConversion.AddStatementsIfNeeded((BoundStatement)closureConversion.Visit(loweredBody));
|
|
if (closureConversion._synthesizedMethods != null)
|
|
{
|
|
if (compilationState.SynthesizedMethods == null)
|
|
{
|
|
compilationState.SynthesizedMethods = closureConversion._synthesizedMethods;
|
|
}
|
|
else
|
|
{
|
|
compilationState.SynthesizedMethods.AddRange(closureConversion._synthesizedMethods);
|
|
closureConversion._synthesizedMethods.Free();
|
|
}
|
|
}
|
|
analysis.Free();
|
|
return result;
|
|
}
|
|
|
|
private BoundStatement AddStatementsIfNeeded(BoundStatement body)
|
|
{
|
|
if (_addedLocals != null)
|
|
{
|
|
_addedStatements.Add(body);
|
|
body = new BoundBlock(body.Syntax, _addedLocals.ToImmutableAndFree(), _addedStatements.ToImmutableAndFree())
|
|
{
|
|
WasCompilerGenerated = true
|
|
};
|
|
_addedLocals = null;
|
|
_addedStatements = null;
|
|
}
|
|
return body;
|
|
}
|
|
|
|
private void SynthesizeClosureEnvironments(ArrayBuilder<ClosureDebugInfo> closureDebugInfo)
|
|
{
|
|
Analysis.VisitScopeTree(_analysis.ScopeTree, delegate(Analysis.Scope scope)
|
|
{
|
|
Analysis.ClosureEnvironment declaredEnvironment = scope.DeclaredEnvironment;
|
|
if (declaredEnvironment != null)
|
|
{
|
|
SynthesizedClosureEnvironment synthesizedClosureEnvironment = (declaredEnvironment.SynthesizedEnvironment = MakeFrame(scope, declaredEnvironment));
|
|
((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)CompilationState.ModuleBuilderOpt).AddSynthesizedDefinition(ContainingType, (INestedTypeDefinition)(object)synthesizedClosureEnvironment.GetCciAdapter());
|
|
if (synthesizedClosureEnvironment.Constructor != null)
|
|
{
|
|
AddSynthesizedMethod(synthesizedClosureEnvironment.Constructor, FlowAnalysisPass.AppendImplicitReturn(MethodCompiler.BindSynthesizedMethodBody(synthesizedClosureEnvironment.Constructor, CompilationState, Diagnostics), synthesizedClosureEnvironment.Constructor));
|
|
}
|
|
_frames.Add(scope.BoundNode, declaredEnvironment);
|
|
}
|
|
});
|
|
SynthesizedClosureEnvironment MakeFrame(Analysis.Scope scope, Analysis.ClosureEnvironment env)
|
|
{
|
|
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
|
|
SyntaxNode syntax = scope.BoundNode.Syntax;
|
|
DebugId topLevelMethodId = _analysis.GetTopLevelMethodId();
|
|
DebugId closureId = _analysis.GetClosureId(syntax, closureDebugInfo);
|
|
MethodSymbol methodSymbol = scope.ContainingFunctionOpt?.OriginalMethodSymbol ?? _topLevelMethod;
|
|
if ((object)_substitutedSourceMethod != null && methodSymbol == _topLevelMethod)
|
|
{
|
|
methodSymbol = _substitutedSourceMethod;
|
|
}
|
|
SynthesizedClosureEnvironment synthesizedClosureEnvironment = new SynthesizedClosureEnvironment(_topLevelMethod, methodSymbol, env.IsStruct, syntax, topLevelMethodId, closureId);
|
|
foreach (Symbol capturedVariable in env.CapturedVariables)
|
|
{
|
|
LambdaCapturedVariable lambdaCapturedVariable = LambdaCapturedVariable.Create(synthesizedClosureEnvironment, capturedVariable, ref _synthesizedFieldNameIdDispenser);
|
|
proxies.Add(capturedVariable, new CapturedToFrameSymbolReplacement(lambdaCapturedVariable, isReusable: false));
|
|
synthesizedClosureEnvironment.AddHoistedField(lambdaCapturedVariable);
|
|
((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)CompilationState.ModuleBuilderOpt).AddSynthesizedDefinition((NamedTypeSymbol)synthesizedClosureEnvironment, (IFieldDefinition)(object)lambdaCapturedVariable.GetCciAdapter());
|
|
}
|
|
return synthesizedClosureEnvironment;
|
|
}
|
|
}
|
|
|
|
private void SynthesizeClosureMethods()
|
|
{
|
|
Analysis.VisitNestedFunctions(_analysis.ScopeTree, delegate(Analysis.Scope scope, Analysis.NestedFunction nestedFunction)
|
|
{
|
|
//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
|
|
MethodSymbol originalMethodSymbol = nestedFunction.OriginalMethodSymbol;
|
|
SyntaxNode syntax = originalMethodSymbol.DeclaringSyntaxReferences[0].GetSyntax(default(CancellationToken));
|
|
ClosureKind closureKind;
|
|
NamedTypeSymbol containingType;
|
|
int closureOrdinal;
|
|
if (nestedFunction.ContainingEnvironmentOpt != null)
|
|
{
|
|
SynthesizedClosureEnvironment synthesizedEnvironment = nestedFunction.ContainingEnvironmentOpt.SynthesizedEnvironment;
|
|
closureKind = ClosureKind.General;
|
|
containingType = synthesizedEnvironment;
|
|
closureOrdinal = synthesizedEnvironment.ClosureOrdinal;
|
|
}
|
|
else if (nestedFunction.CapturesThis)
|
|
{
|
|
containingType = _topLevelMethod.ContainingType;
|
|
closureKind = ClosureKind.ThisOnly;
|
|
closureOrdinal = -2;
|
|
}
|
|
else if ((nestedFunction.CapturedEnvironments.Count == 0 && (int)originalMethodSymbol.MethodKind == 0 && ((HashSet<MethodSymbol>)(object)_analysis.MethodsConvertedToDelegates).Contains(originalMethodSymbol)) || (object)VarianceSafety.GetEnclosingVariantInterface(_topLevelMethod) != null)
|
|
{
|
|
containingType = GetStaticFrame(Diagnostics, syntax);
|
|
closureKind = ClosureKind.Singleton;
|
|
closureOrdinal = -1;
|
|
}
|
|
else
|
|
{
|
|
containingType = _topLevelMethod.ContainingType;
|
|
closureKind = ClosureKind.Static;
|
|
closureOrdinal = -1;
|
|
}
|
|
DebugId topLevelMethodId = _analysis.GetTopLevelMethodId();
|
|
DebugId lambdaId = GetLambdaId(syntax, closureKind, closureOrdinal);
|
|
SynthesizedClosureMethod synthesizedLoweredMethod = new SynthesizedClosureMethod(containingType, getStructEnvironments(nestedFunction), closureKind, _topLevelMethod, topLevelMethodId, originalMethodSymbol, nestedFunction.BlockSyntax, lambdaId, CompilationState);
|
|
nestedFunction.SynthesizedLoweredMethod = synthesizedLoweredMethod;
|
|
});
|
|
static ImmutableArray<SynthesizedClosureEnvironment> getStructEnvironments(Analysis.NestedFunction function)
|
|
{
|
|
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
|
|
ArrayBuilder<SynthesizedClosureEnvironment> instance = ArrayBuilder<SynthesizedClosureEnvironment>.GetInstance();
|
|
Enumerator<Analysis.ClosureEnvironment> enumerator = function.CapturedEnvironments.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
Analysis.ClosureEnvironment current = enumerator.Current;
|
|
if (current.IsStruct)
|
|
{
|
|
instance.Add(current.SynthesizedEnvironment);
|
|
}
|
|
}
|
|
return instance.ToImmutableAndFree();
|
|
}
|
|
}
|
|
|
|
private SynthesizedClosureEnvironment GetStaticFrame(BindingDiagnosticBag diagnostics, SyntaxNode syntax)
|
|
{
|
|
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
|
|
if ((object)_lazyStaticLambdaFrame == null)
|
|
{
|
|
bool flag = !_topLevelMethod.IsGenericMethod;
|
|
if (flag)
|
|
{
|
|
_lazyStaticLambdaFrame = CompilationState.StaticLambdaFrame;
|
|
}
|
|
if ((object)_lazyStaticLambdaFrame == null)
|
|
{
|
|
DebugId topLevelMethodId = default(DebugId);
|
|
if (flag)
|
|
{
|
|
((DebugId)(ref topLevelMethodId))._002Ector(-1, ((CommonPEModuleBuilder)CompilationState.ModuleBuilderOpt).CurrentGenerationOrdinal);
|
|
}
|
|
else
|
|
{
|
|
topLevelMethodId = _analysis.GetTopLevelMethodId();
|
|
}
|
|
DebugId closureId = default(DebugId);
|
|
MethodSymbol containingMethod = (flag ? null : (_substitutedSourceMethod ?? _topLevelMethod));
|
|
_lazyStaticLambdaFrame = new SynthesizedClosureEnvironment(_topLevelMethod, containingMethod, isStruct: false, null, topLevelMethodId, closureId);
|
|
if (flag)
|
|
{
|
|
CompilationState.StaticLambdaFrame = _lazyStaticLambdaFrame;
|
|
}
|
|
SynthesizedClosureEnvironment lazyStaticLambdaFrame = _lazyStaticLambdaFrame;
|
|
((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)CompilationState.ModuleBuilderOpt).AddSynthesizedDefinition(ContainingType, (INestedTypeDefinition)(object)lazyStaticLambdaFrame.GetCciAdapter());
|
|
AddSynthesizedMethod(lazyStaticLambdaFrame.Constructor, FlowAnalysisPass.AppendImplicitReturn(MethodCompiler.BindSynthesizedMethodBody(lazyStaticLambdaFrame.Constructor, CompilationState, diagnostics), lazyStaticLambdaFrame.Constructor));
|
|
SyntheticBoundNodeFactory syntheticBoundNodeFactory = new SyntheticBoundNodeFactory(lazyStaticLambdaFrame.StaticConstructor, syntax, CompilationState, diagnostics);
|
|
BoundBlock body = syntheticBoundNodeFactory.Block(syntheticBoundNodeFactory.Assignment(syntheticBoundNodeFactory.Field(null, lazyStaticLambdaFrame.SingletonCache), syntheticBoundNodeFactory.New(lazyStaticLambdaFrame.Constructor)), new BoundReturnStatement(syntax, (RefKind)0, null, @checked: false));
|
|
AddSynthesizedMethod(lazyStaticLambdaFrame.StaticConstructor, body);
|
|
}
|
|
}
|
|
return _lazyStaticLambdaFrame;
|
|
}
|
|
|
|
private BoundExpression FrameOfType(SyntaxNode syntax, NamedTypeSymbol frameType)
|
|
{
|
|
return FramePointer(syntax, frameType.OriginalDefinition);
|
|
}
|
|
|
|
protected override BoundExpression FramePointer(SyntaxNode syntax, NamedTypeSymbol frameClass)
|
|
{
|
|
if ((object)_currentFrameThis != null && TypeSymbol.Equals(_currentFrameThis.Type, frameClass, (TypeCompareKind)0))
|
|
{
|
|
return new BoundThisReference(syntax, frameClass);
|
|
}
|
|
SynthesizedClosureMethod synthesizedClosureMethod = _currentMethod as SynthesizedClosureMethod;
|
|
if (synthesizedClosureMethod != null)
|
|
{
|
|
for (int i = synthesizedClosureMethod.ParameterCount - synthesizedClosureMethod.ExtraSynthesizedParameterCount; i < synthesizedClosureMethod.ParameterCount; i++)
|
|
{
|
|
ParameterSymbol parameterSymbol = synthesizedClosureMethod.Parameters[i];
|
|
if (TypeSymbol.Equals(parameterSymbol.Type.OriginalDefinition, frameClass, (TypeCompareKind)0))
|
|
{
|
|
return new BoundParameter(syntax, parameterSymbol);
|
|
}
|
|
}
|
|
}
|
|
Symbol symbol = _framePointers[frameClass];
|
|
if (proxies.TryGetValue(symbol, out CapturedSymbolReplacement value))
|
|
{
|
|
return value.Replacement(syntax, (NamedTypeSymbol frameType) => FramePointer(syntax, frameType));
|
|
}
|
|
LocalSymbol localSymbol = (LocalSymbol)symbol;
|
|
return new BoundLocal(syntax, localSymbol, null, localSymbol.Type);
|
|
}
|
|
|
|
private static void InsertAndFreePrologue<T>(ArrayBuilder<BoundStatement> result, ArrayBuilder<T> prologue) where T : BoundNode
|
|
{
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
|
Enumerator<T> enumerator = prologue.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
T current = enumerator.Current;
|
|
if (current is BoundStatement boundStatement)
|
|
{
|
|
result.Add(boundStatement);
|
|
}
|
|
else
|
|
{
|
|
result.Add((BoundStatement)new BoundExpressionStatement(current.Syntax, (BoundExpression)(object)current));
|
|
}
|
|
}
|
|
prologue.Free();
|
|
}
|
|
|
|
private BoundNode IntroduceFrame(BoundNode node, Analysis.ClosureEnvironment env, Func<ArrayBuilder<BoundExpression>, ArrayBuilder<LocalSymbol>, BoundNode> F)
|
|
{
|
|
SynthesizedClosureEnvironment synthesizedEnvironment = env.SynthesizedEnvironment;
|
|
ImmutableArray<TypeWithAnnotations> typeArguments = ImmutableArray.Create(ImmutableArrayExtensions.SelectAsArray<TypeParameterSymbol, TypeWithAnnotations>(_currentTypeParameters, (Func<TypeParameterSymbol, TypeWithAnnotations>)((TypeParameterSymbol t) => TypeWithAnnotations.Create(t))), 0, synthesizedEnvironment.Arity);
|
|
NamedTypeSymbol namedTypeSymbol = synthesizedEnvironment.ConstructIfGeneric(typeArguments);
|
|
LocalSymbol localSymbol = new SynthesizedLocal(_topLevelMethod, TypeWithAnnotations.Create(namedTypeSymbol), (SynthesizedLocalKind)30, synthesizedEnvironment.ScopeSyntaxOpt, isPinned: false, isKnownToReferToTempIfReferenceType: false, (RefKind)0);
|
|
SyntaxNode syntax = node.Syntax;
|
|
ArrayBuilder<BoundExpression> instance = ArrayBuilder<BoundExpression>.GetInstance();
|
|
if ((object)synthesizedEnvironment.Constructor != null)
|
|
{
|
|
MethodSymbol constructor = synthesizedEnvironment.Constructor.AsMember(namedTypeSymbol);
|
|
instance.Add((BoundExpression)new BoundAssignmentOperator(syntax, new BoundLocal(syntax, localSymbol, null, namedTypeSymbol), new BoundObjectCreationExpression(syntax, constructor), namedTypeSymbol));
|
|
}
|
|
CapturedSymbolReplacement value = null;
|
|
if ((object)_innermostFramePointer != null)
|
|
{
|
|
proxies.TryGetValue(_innermostFramePointer, out value);
|
|
if (env.CapturesParent)
|
|
{
|
|
LambdaCapturedVariable lambdaCapturedVariable = LambdaCapturedVariable.Create(synthesizedEnvironment, _innermostFramePointer, ref _synthesizedFieldNameIdDispenser);
|
|
FieldSymbol fieldSymbol = lambdaCapturedVariable.AsMember(namedTypeSymbol);
|
|
BoundExpression boundExpression = new BoundFieldAccess(syntax, new BoundLocal(syntax, localSymbol, null, namedTypeSymbol), fieldSymbol, null);
|
|
BoundExpression right = FrameOfType(syntax, fieldSymbol.Type as NamedTypeSymbol);
|
|
BoundExpression boundExpression2 = new BoundAssignmentOperator(syntax, boundExpression, right, boundExpression.Type);
|
|
instance.Add(boundExpression2);
|
|
if (CompilationState.Emitting)
|
|
{
|
|
synthesizedEnvironment.AddHoistedField(lambdaCapturedVariable);
|
|
((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)CompilationState.ModuleBuilderOpt).AddSynthesizedDefinition((NamedTypeSymbol)synthesizedEnvironment, (IFieldDefinition)(object)lambdaCapturedVariable.GetCciAdapter());
|
|
}
|
|
proxies[_innermostFramePointer] = new CapturedToFrameSymbolReplacement(lambdaCapturedVariable, isReusable: false);
|
|
}
|
|
}
|
|
foreach (Symbol capturedVariable in env.CapturedVariables)
|
|
{
|
|
InitVariableProxy(syntax, capturedVariable, localSymbol, instance);
|
|
}
|
|
Symbol innermostFramePointer = _innermostFramePointer;
|
|
if (!localSymbol.Type.IsValueType)
|
|
{
|
|
_innermostFramePointer = localSymbol;
|
|
}
|
|
ArrayBuilder<LocalSymbol> instance2 = ArrayBuilder<LocalSymbol>.GetInstance();
|
|
instance2.Add(localSymbol);
|
|
_framePointers.Add(synthesizedEnvironment, localSymbol);
|
|
BoundNode result = F(instance, instance2);
|
|
_innermostFramePointer = innermostFramePointer;
|
|
if ((object)_innermostFramePointer != null)
|
|
{
|
|
if (value != null)
|
|
{
|
|
proxies[_innermostFramePointer] = value;
|
|
return result;
|
|
}
|
|
proxies.Remove(_innermostFramePointer);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private void InitVariableProxy(SyntaxNode syntax, Symbol symbol, LocalSymbol framePointer, ArrayBuilder<BoundExpression> prologue)
|
|
{
|
|
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0032: Invalid comparison between Unknown and I4
|
|
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0038: Invalid comparison between Unknown and I4
|
|
//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0102: Invalid comparison between Unknown and I4
|
|
if (!proxies.TryGetValue(symbol, out CapturedSymbolReplacement value))
|
|
{
|
|
return;
|
|
}
|
|
SymbolKind kind = symbol.Kind;
|
|
BoundExpression boundExpression;
|
|
if ((int)kind != 8)
|
|
{
|
|
if ((int)kind != 13)
|
|
{
|
|
throw ExceptionUtilities.UnexpectedValue((object)symbol.Kind);
|
|
}
|
|
ParameterSymbol parameterSymbol = (ParameterSymbol)symbol;
|
|
if (!_parameterMap.TryGetValue(parameterSymbol, out var value2))
|
|
{
|
|
value2 = parameterSymbol;
|
|
}
|
|
boundExpression = new BoundParameter(syntax, value2);
|
|
}
|
|
else
|
|
{
|
|
LocalSymbol localSymbol = (LocalSymbol)symbol;
|
|
if (_assignLocals == null || !_assignLocals.Contains(localSymbol))
|
|
{
|
|
return;
|
|
}
|
|
if (!localMap.TryGetValue(localSymbol, out LocalSymbol value3))
|
|
{
|
|
value3 = localSymbol;
|
|
}
|
|
boundExpression = new BoundLocal(syntax, value3, null, value3.Type);
|
|
}
|
|
BoundExpression left = value.Replacement(syntax, (NamedTypeSymbol frameType1) => new BoundLocal(syntax, framePointer, null, framePointer.Type));
|
|
BoundAssignmentOperator boundAssignmentOperator = new BoundAssignmentOperator(syntax, left, boundExpression, boundExpression.Type);
|
|
if ((int)_currentMethod.MethodKind == 1 && symbol == _currentMethod.ThisParameter && !_seenBaseCall && !(_currentMethod is SynthesizedPrimaryConstructor))
|
|
{
|
|
_thisProxyInitDeferred = boundAssignmentOperator;
|
|
}
|
|
else
|
|
{
|
|
prologue.Add((BoundExpression)boundAssignmentOperator);
|
|
}
|
|
}
|
|
|
|
protected override BoundNode VisitUnhoistedParameter(BoundParameter node)
|
|
{
|
|
if (_parameterMap.TryGetValue(node.ParameterSymbol, out var value))
|
|
{
|
|
return new BoundParameter(node.Syntax, value, node.HasErrors);
|
|
}
|
|
return base.VisitUnhoistedParameter(node);
|
|
}
|
|
|
|
public override BoundNode VisitThisReference(BoundThisReference node)
|
|
{
|
|
if (!(_currentMethod == _topLevelMethod) && !(_topLevelMethod.ThisParameter == null))
|
|
{
|
|
return FramePointer(node.Syntax, (NamedTypeSymbol)node.Type);
|
|
}
|
|
return node;
|
|
}
|
|
|
|
public override BoundNode VisitBaseReference(BoundBaseReference node)
|
|
{
|
|
if (_currentMethod.IsStatic || !TypeSymbol.Equals(_currentMethod.ContainingType, _topLevelMethod.ContainingType, (TypeCompareKind)0))
|
|
{
|
|
return FramePointer(node.Syntax, _topLevelMethod.ContainingType);
|
|
}
|
|
return node;
|
|
}
|
|
|
|
public override BoundNode VisitMethodDefIndex(BoundMethodDefIndex node)
|
|
{
|
|
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_001f: Invalid comparison between Unknown and I4
|
|
TypeSymbol type = VisitType(node.Type);
|
|
MethodKind methodKind = node.Method.MethodKind;
|
|
bool flag = (((int)methodKind == 0 || (int)methodKind == 17) ? true : false);
|
|
MethodSymbol method = (flag ? Analysis.GetNestedFunctionInTree(_analysis.ScopeTree, node.Method.OriginalDefinition).SynthesizedLoweredMethod : node.Method);
|
|
return node.Update(method, type);
|
|
}
|
|
|
|
private void RemapLocalFunction(SyntaxNode syntax, MethodSymbol localFunc, out BoundExpression receiver, out MethodSymbol method, ref ImmutableArray<BoundExpression> arguments, ref ImmutableArray<RefKind> argRefKinds)
|
|
{
|
|
SynthesizedClosureMethod synthesizedLoweredMethod = Analysis.GetNestedFunctionInTree(_analysis.ScopeTree, localFunc.OriginalDefinition).SynthesizedLoweredMethod;
|
|
int extraSynthesizedParameterCount = synthesizedLoweredMethod.ExtraSynthesizedParameterCount;
|
|
if (extraSynthesizedParameterCount != 0)
|
|
{
|
|
ArrayBuilder<BoundExpression> instance = ArrayBuilder<BoundExpression>.GetInstance(synthesizedLoweredMethod.ParameterCount);
|
|
instance.AddRange(arguments);
|
|
for (int i = synthesizedLoweredMethod.ParameterCount - extraSynthesizedParameterCount; i < synthesizedLoweredMethod.ParameterCount; i++)
|
|
{
|
|
NamedTypeSymbol namedTypeSymbol = (NamedTypeSymbol)synthesizedLoweredMethod.Parameters[i].Type.OriginalDefinition;
|
|
if (namedTypeSymbol.Arity > 0)
|
|
{
|
|
ImmutableArray<TypeParameterSymbol> constructedFromTypeParameters = ((SynthesizedClosureEnvironment)namedTypeSymbol).ConstructedFromTypeParameters;
|
|
ImmutableArray<TypeParameterSymbol> immutableArray = TypeMap.SubstituteTypeParameters(constructedFromTypeParameters);
|
|
namedTypeSymbol = namedTypeSymbol.Construct(immutableArray);
|
|
}
|
|
BoundExpression boundExpression = FrameOfType(syntax, namedTypeSymbol);
|
|
instance.Add(boundExpression);
|
|
}
|
|
ArrayBuilder<RefKind> instance2 = ArrayBuilder<RefKind>.GetInstance(instance.Count);
|
|
if (!argRefKinds.IsDefault)
|
|
{
|
|
instance2.AddRange(argRefKinds);
|
|
}
|
|
else
|
|
{
|
|
instance2.AddMany((RefKind)0, arguments.Length);
|
|
}
|
|
instance2.AddMany((RefKind)1, extraSynthesizedParameterCount);
|
|
arguments = instance.ToImmutableAndFree();
|
|
argRefKinds = instance2.ToImmutableAndFree();
|
|
}
|
|
method = synthesizedLoweredMethod;
|
|
RemapLambdaOrLocalFunction(syntax, localFunc, SubstituteTypeArguments(localFunc.TypeArgumentsWithAnnotations), synthesizedLoweredMethod.ClosureKind, ref method, out receiver, out var _);
|
|
}
|
|
|
|
private ImmutableArray<TypeWithAnnotations> SubstituteTypeArguments(ImmutableArray<TypeWithAnnotations> typeArguments)
|
|
{
|
|
if (typeArguments.IsEmpty)
|
|
{
|
|
return typeArguments;
|
|
}
|
|
ArrayBuilder<TypeWithAnnotations> instance = ArrayBuilder<TypeWithAnnotations>.GetInstance(typeArguments.Length);
|
|
ImmutableArray<TypeWithAnnotations>.Enumerator enumerator = typeArguments.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
TypeWithAnnotations typeWithAnnotations = enumerator.Current;
|
|
TypeWithAnnotations previous;
|
|
do
|
|
{
|
|
previous = typeWithAnnotations;
|
|
typeWithAnnotations = TypeMap.SubstituteType(previous);
|
|
}
|
|
while (!TypeSymbol.Equals(previous.Type, typeWithAnnotations.Type, (TypeCompareKind)0));
|
|
instance.Add(typeWithAnnotations);
|
|
}
|
|
return instance.ToImmutableAndFree();
|
|
}
|
|
|
|
private void RemapLambdaOrLocalFunction(SyntaxNode syntax, MethodSymbol originalMethod, ImmutableArray<TypeWithAnnotations> typeArgumentsOpt, ClosureKind closureKind, ref MethodSymbol synthesizedMethod, out BoundExpression receiver, out NamedTypeSymbol constructedFrame)
|
|
{
|
|
NamedTypeSymbol containingType = synthesizedMethod.ContainingType;
|
|
SynthesizedClosureEnvironment synthesizedClosureEnvironment = containingType as SynthesizedClosureEnvironment;
|
|
int num = (synthesizedClosureEnvironment?.Arity ?? 0) + synthesizedMethod.Arity;
|
|
ImmutableArray<TypeWithAnnotations> immutableArray = ImmutableArray.Create(ImmutableArrayExtensions.SelectAsArray<TypeParameterSymbol, TypeWithAnnotations>(_currentTypeParameters, (Func<TypeParameterSymbol, TypeWithAnnotations>)((TypeParameterSymbol t) => TypeWithAnnotations.Create(t))), 0, num - originalMethod.Arity);
|
|
if (!typeArgumentsOpt.IsDefault)
|
|
{
|
|
immutableArray = ImmutableArrayExtensions.Concat<TypeWithAnnotations>(immutableArray, typeArgumentsOpt);
|
|
}
|
|
if ((object)synthesizedClosureEnvironment != null && synthesizedClosureEnvironment.Arity != 0)
|
|
{
|
|
ImmutableArray<TypeWithAnnotations> typeArguments = ImmutableArray.Create(immutableArray, 0, synthesizedClosureEnvironment.Arity);
|
|
immutableArray = ImmutableArray.Create(immutableArray, synthesizedClosureEnvironment.Arity, immutableArray.Length - synthesizedClosureEnvironment.Arity);
|
|
constructedFrame = synthesizedClosureEnvironment.Construct(typeArguments);
|
|
}
|
|
else
|
|
{
|
|
constructedFrame = containingType;
|
|
}
|
|
synthesizedMethod = synthesizedMethod.AsMember(constructedFrame);
|
|
if (synthesizedMethod.IsGenericMethod)
|
|
{
|
|
synthesizedMethod = synthesizedMethod.Construct(immutableArray);
|
|
}
|
|
switch (closureKind)
|
|
{
|
|
case ClosureKind.Singleton:
|
|
{
|
|
FieldSymbol fieldSymbol = synthesizedClosureEnvironment.SingletonCache.AsMember(constructedFrame);
|
|
receiver = new BoundFieldAccess(syntax, null, fieldSymbol, null);
|
|
break;
|
|
}
|
|
case ClosureKind.Static:
|
|
receiver = new BoundTypeExpression(syntax, null, synthesizedMethod.ContainingType);
|
|
break;
|
|
default:
|
|
receiver = FrameOfType(syntax, constructedFrame);
|
|
break;
|
|
}
|
|
}
|
|
|
|
public override BoundNode VisitCall(BoundCall node)
|
|
{
|
|
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_000d: Invalid comparison between Unknown and I4
|
|
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
|
|
if ((int)node.Method.MethodKind == 17)
|
|
{
|
|
ImmutableArray<BoundExpression> arguments = VisitList(node.Arguments);
|
|
ImmutableArray<RefKind> argRefKinds = node.ArgumentRefKindsOpt;
|
|
TypeSymbol type = VisitType(node.Type);
|
|
RemapLocalFunction(node.Syntax, node.Method, out var receiver, out var method, ref arguments, ref argRefKinds);
|
|
return node.Update(receiver, node.InitialBindingReceiverIsSubjectToCloning, method, arguments, node.ArgumentNamesOpt, argRefKinds, node.IsDelegateCall, node.Expanded, node.InvokedAsExtensionMethod, node.ArgsToParamsOpt, node.DefaultArguments, node.ResultKind, type);
|
|
}
|
|
BoundNode boundNode = base.VisitCall(node);
|
|
if (boundNode.Kind != BoundKind.Call)
|
|
{
|
|
return boundNode;
|
|
}
|
|
BoundCall boundCall = (BoundCall)boundNode;
|
|
if (!_seenBaseCall && _currentMethod == _topLevelMethod && node.IsConstructorInitializer())
|
|
{
|
|
_seenBaseCall = true;
|
|
if (_thisProxyInitDeferred != null)
|
|
{
|
|
return new BoundSequence(node.Syntax, ImmutableArray<LocalSymbol>.Empty, ImmutableArray.Create((BoundExpression)boundCall), _thisProxyInitDeferred, boundCall.Type);
|
|
}
|
|
}
|
|
return boundCall;
|
|
}
|
|
|
|
private BoundSequence RewriteSequence(BoundSequence node, ArrayBuilder<BoundExpression> prologue, ArrayBuilder<LocalSymbol> newLocals)
|
|
{
|
|
RewriteLocals(node.Locals, newLocals);
|
|
ImmutableArray<BoundExpression>.Enumerator enumerator = node.SideEffects.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
BoundExpression current = enumerator.Current;
|
|
BoundExpression boundExpression = (BoundExpression)Visit(current);
|
|
if (boundExpression != null)
|
|
{
|
|
prologue.Add(boundExpression);
|
|
}
|
|
}
|
|
BoundExpression value = (BoundExpression)Visit(node.Value);
|
|
TypeSymbol type = VisitType(node.Type);
|
|
return node.Update(newLocals.ToImmutableAndFree(), prologue.ToImmutableAndFree(), value, type);
|
|
}
|
|
|
|
public override BoundNode VisitBlock(BoundBlock node)
|
|
{
|
|
if (_frames.TryGetValue(node, out var value))
|
|
{
|
|
return IntroduceFrame(node, value, (ArrayBuilder<BoundExpression> prologue, ArrayBuilder<LocalSymbol> newLocals) => RewriteBlock(node, prologue, newLocals));
|
|
}
|
|
return RewriteBlock(node, ArrayBuilder<BoundExpression>.GetInstance(), ArrayBuilder<LocalSymbol>.GetInstance());
|
|
}
|
|
|
|
private BoundBlock RewriteBlock(BoundBlock node, ArrayBuilder<BoundExpression> prologue, ArrayBuilder<LocalSymbol> newLocals)
|
|
{
|
|
RewriteLocals(node.Locals, newLocals);
|
|
ArrayBuilder<BoundStatement> instance = ArrayBuilder<BoundStatement>.GetInstance();
|
|
if (prologue.Count > 0)
|
|
{
|
|
instance.Add(BoundSequencePoint.CreateHidden());
|
|
}
|
|
InsertAndFreePrologue<BoundExpression>(instance, prologue);
|
|
ImmutableArray<BoundStatement>.Enumerator enumerator = node.Statements.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
BoundStatement current = enumerator.Current;
|
|
BoundStatement boundStatement = (BoundStatement)Visit(current);
|
|
if (boundStatement != null)
|
|
{
|
|
instance.Add(boundStatement);
|
|
}
|
|
}
|
|
BoundBlockInstrumentation boundBlockInstrumentation = node.Instrumentation;
|
|
if (boundBlockInstrumentation != null)
|
|
{
|
|
BoundStatement prologue2 = (BoundStatement)Visit(boundBlockInstrumentation.Prologue);
|
|
BoundStatement epilogue = (BoundStatement)Visit(boundBlockInstrumentation.Epilogue);
|
|
boundBlockInstrumentation = boundBlockInstrumentation.Update(boundBlockInstrumentation.Local, prologue2, epilogue);
|
|
}
|
|
return node.Update(newLocals.ToImmutableAndFree(), node.LocalFunctions, node.HasUnsafeModifier, boundBlockInstrumentation, instance.ToImmutableAndFree());
|
|
}
|
|
|
|
public override BoundNode VisitScope(BoundScope node)
|
|
{
|
|
ArrayBuilder<LocalSymbol> instance = ArrayBuilder<LocalSymbol>.GetInstance();
|
|
RewriteLocals(node.Locals, instance);
|
|
ImmutableArray<BoundStatement> statements = VisitList(node.Statements);
|
|
if (instance.Count == 0)
|
|
{
|
|
instance.Free();
|
|
return new BoundStatementList(node.Syntax, statements);
|
|
}
|
|
return node.Update(instance.ToImmutableAndFree(), statements);
|
|
}
|
|
|
|
public override BoundNode VisitCatchBlock(BoundCatchBlock node)
|
|
{
|
|
if (_frames.TryGetValue(node, out var value))
|
|
{
|
|
return IntroduceFrame(node, value, (ArrayBuilder<BoundExpression> prologue, ArrayBuilder<LocalSymbol> newLocals) => RewriteCatch(node, prologue, newLocals));
|
|
}
|
|
return RewriteCatch(node, ArrayBuilder<BoundExpression>.GetInstance(), ArrayBuilder<LocalSymbol>.GetInstance());
|
|
}
|
|
|
|
private BoundNode RewriteCatch(BoundCatchBlock node, ArrayBuilder<BoundExpression> prologue, ArrayBuilder<LocalSymbol> newLocals)
|
|
{
|
|
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
|
|
RewriteLocals(node.Locals, newLocals);
|
|
ImmutableArray<LocalSymbol> locals = newLocals.ToImmutableAndFree();
|
|
BoundExpression boundExpression = null;
|
|
BoundStatementList boundStatementList = (BoundStatementList)Visit(node.ExceptionFilterPrologueOpt);
|
|
BoundExpression boundExpression2 = (BoundExpression)Visit(node.ExceptionFilterOpt);
|
|
if (node.ExceptionSourceOpt != null)
|
|
{
|
|
boundExpression = (BoundExpression)Visit(node.ExceptionSourceOpt);
|
|
if (prologue.Count > 0)
|
|
{
|
|
boundExpression = new BoundSequence(boundExpression.Syntax, ImmutableArray.Create<LocalSymbol>(), prologue.ToImmutable(), boundExpression, boundExpression.Type);
|
|
}
|
|
}
|
|
else if (prologue.Count > 0)
|
|
{
|
|
ArrayBuilder<BoundStatement> instance = ArrayBuilder<BoundStatement>.GetInstance(prologue.Count);
|
|
Enumerator<BoundExpression> enumerator = prologue.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
BoundExpression current = enumerator.Current;
|
|
instance.Add((BoundStatement)new BoundExpressionStatement(current.Syntax, current)
|
|
{
|
|
WasCompilerGenerated = true
|
|
});
|
|
}
|
|
if (boundStatementList != null)
|
|
{
|
|
instance.AddRange(boundStatementList.Statements);
|
|
}
|
|
boundStatementList = new BoundStatementList(boundExpression2.Syntax, instance.ToImmutableAndFree());
|
|
}
|
|
prologue.Free();
|
|
TypeSymbol exceptionTypeOpt = VisitType(node.ExceptionTypeOpt);
|
|
BoundBlock body = (BoundBlock)Visit(node.Body);
|
|
return node.Update(locals, boundExpression, exceptionTypeOpt, boundStatementList, boundExpression2, body, node.IsSynthesizedAsyncCatchAll);
|
|
}
|
|
|
|
public override BoundNode VisitSequence(BoundSequence node)
|
|
{
|
|
if (_frames.TryGetValue(node, out var value))
|
|
{
|
|
return IntroduceFrame(node, value, (ArrayBuilder<BoundExpression> prologue, ArrayBuilder<LocalSymbol> newLocals) => RewriteSequence(node, prologue, newLocals));
|
|
}
|
|
return RewriteSequence(node, ArrayBuilder<BoundExpression>.GetInstance(), ArrayBuilder<LocalSymbol>.GetInstance());
|
|
}
|
|
|
|
public override BoundNode VisitStatementList(BoundStatementList node)
|
|
{
|
|
if (_frames.TryGetValue(node, out var value))
|
|
{
|
|
return IntroduceFrame(node, value, delegate(ArrayBuilder<BoundExpression> prologue, ArrayBuilder<LocalSymbol> newLocals)
|
|
{
|
|
ArrayBuilder<BoundStatement> instance = ArrayBuilder<BoundStatement>.GetInstance();
|
|
InsertAndFreePrologue<BoundExpression>(instance, prologue);
|
|
ImmutableArray<BoundStatement>.Enumerator enumerator = node.Statements.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
BoundStatement current = enumerator.Current;
|
|
instance.Add((BoundStatement)Visit(current));
|
|
}
|
|
return new BoundBlock(node.Syntax, newLocals.ToImmutableAndFree(), instance.ToImmutableAndFree(), node.HasErrors);
|
|
});
|
|
}
|
|
return base.VisitStatementList(node);
|
|
}
|
|
|
|
public override BoundNode VisitDelegateCreationExpression(BoundDelegateCreationExpression node)
|
|
{
|
|
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0038: Invalid comparison between Unknown and I4
|
|
if (node.Argument.Kind == BoundKind.Lambda)
|
|
{
|
|
return RewriteLambdaConversion((BoundLambda)node.Argument);
|
|
}
|
|
MethodSymbol? methodOpt = node.MethodOpt;
|
|
if ((object)methodOpt != null && (int)methodOpt.MethodKind == 17)
|
|
{
|
|
ImmutableArray<BoundExpression> arguments = default(ImmutableArray<BoundExpression>);
|
|
ImmutableArray<RefKind> argRefKinds = default(ImmutableArray<RefKind>);
|
|
RemapLocalFunction(node.Syntax, node.MethodOpt, out var receiver, out var method, ref arguments, ref argRefKinds);
|
|
return new BoundDelegateCreationExpression(node.Syntax, receiver, method, node.IsExtensionMethod, node.WasTargetTyped, VisitType(node.Type));
|
|
}
|
|
return base.VisitDelegateCreationExpression(node);
|
|
}
|
|
|
|
public override BoundNode VisitFunctionPointerLoad(BoundFunctionPointerLoad node)
|
|
{
|
|
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_000d: Invalid comparison between Unknown and I4
|
|
if ((int)node.TargetMethod.MethodKind == 17)
|
|
{
|
|
ImmutableArray<BoundExpression> arguments = default(ImmutableArray<BoundExpression>);
|
|
ImmutableArray<RefKind> argRefKinds = default(ImmutableArray<RefKind>);
|
|
RemapLocalFunction(node.Syntax, node.TargetMethod, out var _, out var method, ref arguments, ref argRefKinds);
|
|
return node.Update(method, node.ConstrainedToTypeOpt, node.Type);
|
|
}
|
|
return base.VisitFunctionPointerLoad(node);
|
|
}
|
|
|
|
public override BoundNode VisitConversion(BoundConversion conversion)
|
|
{
|
|
if (conversion.ConversionKind == ConversionKind.AnonymousFunction)
|
|
{
|
|
BoundExpression boundExpression = (BoundExpression)RewriteLambdaConversion((BoundLambda)conversion.Operand);
|
|
if (_inExpressionLambda && conversion.ExplicitCastInCode)
|
|
{
|
|
boundExpression = new BoundConversion(conversion.Syntax, boundExpression, conversion.Conversion, isBaseConversion: false, @checked: false, explicitCastInCode: true, conversionGroupOpt: conversion.ConversionGroupOpt, constantValueOpt: conversion.ConstantValueOpt, type: conversion.Type);
|
|
}
|
|
return boundExpression;
|
|
}
|
|
return base.VisitConversion(conversion);
|
|
}
|
|
|
|
public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
|
|
{
|
|
RewriteLambdaOrLocalFunction(node, out var _, out var _, out var _, out var _, out var _, out var _);
|
|
return new BoundNoOpStatement(node.Syntax, NoOpStatementFlavor.Default);
|
|
}
|
|
|
|
private DebugId GetLambdaId(SyntaxNode syntax, ClosureKind closureKind, int closureOrdinal)
|
|
{
|
|
//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
|
|
SyntaxNode val;
|
|
bool flag;
|
|
if (syntax is AnonymousFunctionExpressionSyntax anonymousFunctionExpressionSyntax)
|
|
{
|
|
val = (SyntaxNode)(object)anonymousFunctionExpressionSyntax.Body;
|
|
flag = true;
|
|
}
|
|
else if (syntax is LocalFunctionStatementSyntax localFunctionStatementSyntax)
|
|
{
|
|
val = (SyntaxNode)(((object)localFunctionStatementSyntax.Body) ?? ((object)localFunctionStatementSyntax.ExpressionBody?.Expression));
|
|
if (val == null)
|
|
{
|
|
val = (SyntaxNode)(object)localFunctionStatementSyntax;
|
|
flag = false;
|
|
}
|
|
else
|
|
{
|
|
flag = true;
|
|
}
|
|
}
|
|
else if (LambdaUtilities.IsQueryPairLambda(syntax))
|
|
{
|
|
val = syntax;
|
|
flag = false;
|
|
}
|
|
else
|
|
{
|
|
val = syntax;
|
|
flag = true;
|
|
}
|
|
DebugId val2 = default(DebugId);
|
|
DebugId val3 = default(DebugId);
|
|
if (slotAllocatorOpt != null && slotAllocatorOpt.TryGetPreviousLambda(val, flag, ref val2))
|
|
{
|
|
val3 = val2;
|
|
}
|
|
else
|
|
{
|
|
((DebugId)(ref val3))._002Ector(_lambdaDebugInfoBuilder.Count, ((CommonPEModuleBuilder)CompilationState.ModuleBuilderOpt).CurrentGenerationOrdinal);
|
|
}
|
|
int num = _topLevelMethod.CalculateLocalSyntaxOffset(LambdaUtilities.GetDeclaratorPosition(val), val.SyntaxTree);
|
|
_lambdaDebugInfoBuilder.Add(new LambdaDebugInfo(num, val3, closureOrdinal));
|
|
return val3;
|
|
}
|
|
|
|
private SynthesizedClosureMethod RewriteLambdaOrLocalFunction(IBoundLambdaOrFunction node, out ClosureKind closureKind, out NamedTypeSymbol translatedLambdaContainer, out SynthesizedClosureEnvironment containerAsFrame, out BoundNode lambdaScope, out DebugId topLevelMethodId, out DebugId lambdaId)
|
|
{
|
|
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
|
|
Analysis.NestedFunction function = Analysis.GetNestedFunctionInTree(_analysis.ScopeTree, node.Symbol);
|
|
SynthesizedClosureMethod synthesizedLoweredMethod = function.SynthesizedLoweredMethod;
|
|
closureKind = synthesizedLoweredMethod.ClosureKind;
|
|
translatedLambdaContainer = synthesizedLoweredMethod.ContainingType;
|
|
containerAsFrame = translatedLambdaContainer as SynthesizedClosureEnvironment;
|
|
topLevelMethodId = _analysis.GetTopLevelMethodId();
|
|
lambdaId = synthesizedLoweredMethod.LambdaId;
|
|
if (function.ContainingEnvironmentOpt != null)
|
|
{
|
|
BoundNode tmpScope = null;
|
|
Analysis.VisitScopeTree(_analysis.ScopeTree, delegate(Analysis.Scope scope)
|
|
{
|
|
if (scope.DeclaredEnvironment == function.ContainingEnvironmentOpt)
|
|
{
|
|
tmpScope = scope.BoundNode;
|
|
}
|
|
});
|
|
lambdaScope = tmpScope;
|
|
}
|
|
else
|
|
{
|
|
lambdaScope = null;
|
|
}
|
|
((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)CompilationState.ModuleBuilderOpt).AddSynthesizedDefinition(translatedLambdaContainer, (IMethodDefinition)(object)synthesizedLoweredMethod.GetCciAdapter());
|
|
ImmutableArray<ParameterSymbol>.Enumerator enumerator = node.Symbol.Parameters.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
ParameterSymbol current = enumerator.Current;
|
|
_parameterMap.Add(current, synthesizedLoweredMethod.Parameters[current.Ordinal]);
|
|
}
|
|
MethodSymbol currentMethod = _currentMethod;
|
|
ParameterSymbol currentFrameThis = _currentFrameThis;
|
|
ImmutableArray<TypeParameterSymbol> currentTypeParameters = _currentTypeParameters;
|
|
Symbol innermostFramePointer = _innermostFramePointer;
|
|
TypeMap currentLambdaBodyTypeMap = _currentLambdaBodyTypeMap;
|
|
ArrayBuilder<BoundStatement> addedStatements = _addedStatements;
|
|
ArrayBuilder<LocalSymbol> addedLocals = _addedLocals;
|
|
_addedStatements = null;
|
|
_addedLocals = null;
|
|
_currentMethod = synthesizedLoweredMethod;
|
|
if (closureKind == ClosureKind.Static || closureKind == ClosureKind.Singleton)
|
|
{
|
|
_innermostFramePointer = (_currentFrameThis = null);
|
|
}
|
|
else
|
|
{
|
|
_currentFrameThis = synthesizedLoweredMethod.ThisParameter;
|
|
_framePointers.TryGetValue(translatedLambdaContainer, out _innermostFramePointer);
|
|
}
|
|
SynthesizedClosureEnvironment obj = containerAsFrame;
|
|
_currentTypeParameters = (((object)obj != null) ? ImmutableArrayExtensions.Concat<TypeParameterSymbol>(obj.TypeParameters, synthesizedLoweredMethod.TypeParameters) : synthesizedLoweredMethod.TypeParameters);
|
|
_currentLambdaBodyTypeMap = synthesizedLoweredMethod.TypeMap;
|
|
BoundBlock body = node.Body;
|
|
if (body != null)
|
|
{
|
|
BoundStatement body2 = AddStatementsIfNeeded((BoundStatement)VisitBlock(body));
|
|
AddSynthesizedMethod(synthesizedLoweredMethod, body2);
|
|
}
|
|
_currentMethod = currentMethod;
|
|
_currentFrameThis = currentFrameThis;
|
|
_currentTypeParameters = currentTypeParameters;
|
|
_innermostFramePointer = innermostFramePointer;
|
|
_currentLambdaBodyTypeMap = currentLambdaBodyTypeMap;
|
|
_addedLocals = addedLocals;
|
|
_addedStatements = addedStatements;
|
|
return synthesizedLoweredMethod;
|
|
}
|
|
|
|
private void AddSynthesizedMethod(MethodSymbol method, BoundStatement body)
|
|
{
|
|
if (_synthesizedMethods == null)
|
|
{
|
|
_synthesizedMethods = ArrayBuilder<TypeCompilationState.MethodWithBody>.GetInstance();
|
|
}
|
|
_synthesizedMethods.Add(new TypeCompilationState.MethodWithBody(method, body, CompilationState.CurrentImportChain));
|
|
}
|
|
|
|
private BoundNode RewriteLambdaConversion(BoundLambda node)
|
|
{
|
|
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0102: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0109: Invalid comparison between Unknown and I4
|
|
//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
|
|
bool inExpressionLambda = _inExpressionLambda;
|
|
_inExpressionLambda = _inExpressionLambda || node.Type.IsExpressionTree();
|
|
if (_inExpressionLambda)
|
|
{
|
|
TypeSymbol type = VisitType(node.Type);
|
|
BoundBlock body = (BoundBlock)Visit(node.Body);
|
|
node = node.Update(node.UnboundLambda, node.Symbol, body, node.Diagnostics, node.Binder, type);
|
|
BoundNode result = (inExpressionLambda ? node : ExpressionLambdaRewriter.RewriteLambda(node, CompilationState, TypeMap, base.RecursionDepth, Diagnostics));
|
|
_inExpressionLambda = inExpressionLambda;
|
|
return result;
|
|
}
|
|
ClosureKind closureKind;
|
|
NamedTypeSymbol translatedLambdaContainer;
|
|
SynthesizedClosureEnvironment containerAsFrame;
|
|
BoundNode lambdaScope;
|
|
DebugId topLevelMethodId;
|
|
DebugId lambdaId;
|
|
MethodSymbol synthesizedMethod = RewriteLambdaOrLocalFunction(node, out closureKind, out translatedLambdaContainer, out containerAsFrame, out lambdaScope, out topLevelMethodId, out lambdaId);
|
|
RemapLambdaOrLocalFunction(node.Syntax, node.Symbol, default(ImmutableArray<TypeWithAnnotations>), closureKind, ref synthesizedMethod, out var receiver, out var constructedFrame);
|
|
TypeSymbol type2 = VisitType(node.Type);
|
|
BoundExpression boundExpression = new BoundDelegateCreationExpression(node.Syntax, receiver, synthesizedMethod, isExtensionMethod: false, wasTargetTyped: false, type2);
|
|
bool flag = closureKind == ClosureKind.Singleton && (int)_currentMethod.MethodKind != 14 && !synthesizedMethod.IsGenericMethod;
|
|
bool flag2 = lambdaScope != null && lambdaScope != Analysis.GetScopeParent(_analysis.ScopeTree, node.Body).BoundNode && InLoopOrLambda(node.Syntax, lambdaScope.Syntax);
|
|
if (flag || flag2)
|
|
{
|
|
SyntheticBoundNodeFactory syntheticBoundNodeFactory = new SyntheticBoundNodeFactory(_currentMethod, node.Syntax, CompilationState, Diagnostics);
|
|
try
|
|
{
|
|
if (flag || (flag2 && (object)containerAsFrame != null))
|
|
{
|
|
TypeSymbol type3 = containerAsFrame.TypeMap.SubstituteType(node.Type).Type;
|
|
if (!type3.ContainsMethodTypeParameter())
|
|
{
|
|
string name = GeneratedNames.MakeLambdaCacheFieldName((closureKind == ClosureKind.General) ? (-1) : topLevelMethodId.Ordinal, topLevelMethodId.Generation, lambdaId.Ordinal, lambdaId.Generation);
|
|
SynthesizedLambdaCacheFieldSymbol synthesizedLambdaCacheFieldSymbol = new SynthesizedLambdaCacheFieldSymbol(translatedLambdaContainer, type3, name, _topLevelMethod, isReadOnly: false, closureKind == ClosureKind.Singleton);
|
|
((PEModuleBuilder<CSharpCompilation, SourceModuleSymbol, AssemblySymbol, TypeSymbol, NamedTypeSymbol, MethodSymbol, SyntaxNode, EmbeddedTypesManager, ModuleCompilationState>)CompilationState.ModuleBuilderOpt).AddSynthesizedDefinition(translatedLambdaContainer, (IFieldDefinition)(object)synthesizedLambdaCacheFieldSymbol.GetCciAdapter());
|
|
BoundExpression left = syntheticBoundNodeFactory.Field(receiver, synthesizedLambdaCacheFieldSymbol.AsMember(constructedFrame));
|
|
boundExpression = syntheticBoundNodeFactory.Coalesce(left, syntheticBoundNodeFactory.AssignmentExpression(left, boundExpression));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LocalSymbol localSymbol = syntheticBoundNodeFactory.SynthesizedLocal(type2, null, isPinned: false, isKnownToReferToTempIfReferenceType: false, (RefKind)0, (SynthesizedLocalKind)31);
|
|
if (_addedLocals == null)
|
|
{
|
|
_addedLocals = ArrayBuilder<LocalSymbol>.GetInstance();
|
|
}
|
|
_addedLocals.Add(localSymbol);
|
|
if (_addedStatements == null)
|
|
{
|
|
_addedStatements = ArrayBuilder<BoundStatement>.GetInstance();
|
|
}
|
|
BoundExpression left = syntheticBoundNodeFactory.Local(localSymbol);
|
|
_addedStatements.Add((BoundStatement)syntheticBoundNodeFactory.Assignment(left, syntheticBoundNodeFactory.Null(type2)));
|
|
boundExpression = syntheticBoundNodeFactory.Coalesce(left, syntheticBoundNodeFactory.AssignmentExpression(left, boundExpression));
|
|
}
|
|
}
|
|
catch (SyntheticBoundNodeFactory.MissingPredefinedMember missingPredefinedMember)
|
|
{
|
|
((BindingDiagnosticBag)Diagnostics).Add(missingPredefinedMember.Diagnostic);
|
|
return new BoundBadExpression(syntheticBoundNodeFactory.Syntax, LookupResultKind.Empty, ImmutableArray<Symbol>.Empty, ImmutableArray.Create((BoundExpression)node), node.Type);
|
|
}
|
|
}
|
|
return boundExpression;
|
|
}
|
|
|
|
private static bool InLoopOrLambda(SyntaxNode lambdaSyntax, SyntaxNode scopeSyntax)
|
|
{
|
|
SyntaxNode parent = lambdaSyntax.Parent;
|
|
while (parent != null && parent != scopeSyntax)
|
|
{
|
|
SyntaxKind syntaxKind = parent.Kind();
|
|
if (syntaxKind - 8642 <= SyntaxKind.List || syntaxKind - 8809 <= (SyntaxKind)3 || syntaxKind == SyntaxKind.ForEachVariableStatement)
|
|
{
|
|
return true;
|
|
}
|
|
parent = parent.Parent;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public override BoundNode VisitLambda(BoundLambda node)
|
|
{
|
|
throw ExceptionUtilities.Unreachable("/_/src/Compilers/CSharp/Portable/Lowering/ClosureConversion/ClosureConversion.cs", 1764);
|
|
}
|
|
}
|