Ejemplo n.º 1
0
        public AddedOrChangedMethodInfo(
            DebugId methodId,
            ImmutableArray<EncLocalInfo> locals,
            ImmutableArray<LambdaDebugInfo> lambdaDebugInfo,
            ImmutableArray<ClosureDebugInfo> closureDebugInfo,
            string stateMachineTypeNameOpt,
            ImmutableArray<EncHoistedLocalInfo> stateMachineHoistedLocalSlotsOpt,
            ImmutableArray<Cci.ITypeReference> stateMachineAwaiterSlotsOpt)
        {
            // An updated method will carry its id over,
            // an added method id has generation set to the current generation ordinal.
            Debug.Assert(methodId.Generation >= 0);

            // each state machine has to have awaiters:
            Debug.Assert(stateMachineAwaiterSlotsOpt.IsDefault == (stateMachineTypeNameOpt == null));

            // a state machine might not have hoisted variables:
            Debug.Assert(stateMachineHoistedLocalSlotsOpt.IsDefault || (stateMachineTypeNameOpt != null));

            this.MethodId = methodId;
            this.Locals = locals;
            this.LambdaDebugInfo = lambdaDebugInfo;
            this.ClosureDebugInfo = closureDebugInfo;
            this.StateMachineTypeNameOpt = stateMachineTypeNameOpt;
            this.StateMachineHoistedLocalSlotsOpt = stateMachineHoistedLocalSlotsOpt;
            this.StateMachineAwaiterSlotsOpt = stateMachineAwaiterSlotsOpt;
        }
Ejemplo n.º 2
0
        internal SynthesizedClosureEnvironment(
            MethodSymbol topLevelMethod,
            MethodSymbol containingMethod,
            bool isStruct,
            SyntaxNode scopeSyntaxOpt,
            DebugId methodId,
            DebugId closureId)
            : base(MakeName(scopeSyntaxOpt, methodId, closureId), containingMethod)
        {
            TypeKind                    = isStruct ? TypeKind.Struct : TypeKind.Class;
            _topLevelMethod             = topLevelMethod;
            OriginalContainingMethodOpt = containingMethod;
            Constructor                 = isStruct ? null : new SynthesizedClosureEnvironmentConstructor(this);
            this.ClosureOrdinal         = closureId.Ordinal;

            // static lambdas technically have the class scope so the scope syntax is null
            if (scopeSyntaxOpt == null)
            {
                StaticConstructor = new SynthesizedStaticConstructor(this);
                var cacheVariableName = GeneratedNames.MakeCachedFrameInstanceFieldName();
                SingletonCache = new SynthesizedLambdaCacheFieldSymbol(this, this, cacheVariableName, topLevelMethod, isReadOnly: true, isStatic: true);
            }

            AssertIsClosureScopeSyntax(scopeSyntaxOpt);
            this.ScopeSyntaxOpt = scopeSyntaxOpt;
        }
Ejemplo n.º 3
0
        public AddedOrChangedMethodInfo(
            DebugId methodId,
            ImmutableArray <EncLocalInfo> locals,
            ImmutableArray <LambdaDebugInfo> lambdaDebugInfo,
            ImmutableArray <ClosureDebugInfo> closureDebugInfo,
            string stateMachineTypeNameOpt,
            ImmutableArray <EncHoistedLocalInfo> stateMachineHoistedLocalSlotsOpt,
            ImmutableArray <Cci.ITypeReference> stateMachineAwaiterSlotsOpt)
        {
            // An updated method will carry its id over,
            // an added method id has generation set to the current generation ordinal.
            Debug.Assert(methodId.Generation >= 0);

            // each state machine has to have awaiters:
            Debug.Assert(stateMachineAwaiterSlotsOpt.IsDefault == (stateMachineTypeNameOpt == null));

            // a state machine might not have hoisted variables:
            Debug.Assert(stateMachineHoistedLocalSlotsOpt.IsDefault || (stateMachineTypeNameOpt != null));

            this.MethodId                         = methodId;
            this.Locals                           = locals;
            this.LambdaDebugInfo                  = lambdaDebugInfo;
            this.ClosureDebugInfo                 = closureDebugInfo;
            this.StateMachineTypeNameOpt          = stateMachineTypeNameOpt;
            this.StateMachineHoistedLocalSlotsOpt = stateMachineHoistedLocalSlotsOpt;
            this.StateMachineAwaiterSlotsOpt      = stateMachineAwaiterSlotsOpt;
        }
        public EncVariableSlotAllocator(
            SymbolMatcher symbolMap,
            Func <SyntaxNode, SyntaxNode?>?syntaxMap,
            IMethodSymbolInternal previousTopLevelMethod,
            DebugId methodId,
            ImmutableArray <EncLocalInfo> previousLocals,
            IReadOnlyDictionary <int, KeyValuePair <DebugId, int> >?lambdaMap,
            IReadOnlyDictionary <int, DebugId>?closureMap,
            string?stateMachineTypeName,
            int hoistedLocalSlotCount,
            IReadOnlyDictionary <EncHoistedLocalInfo, int>?hoistedLocalSlots,
            int awaiterCount,
            IReadOnlyDictionary <Cci.ITypeReference, int>?awaiterMap,
            IReadOnlyDictionary <int, int>?stateMachineStateMap,
            int?firstUnusedIncreasingStateMachineState,
            int?firstUnusedDecreasingStateMachineState,
            LambdaSyntaxFacts lambdaSyntaxFacts)
        {
            Debug.Assert(!previousLocals.IsDefault);

            _symbolMap              = symbolMap;
            _syntaxMap              = syntaxMap;
            _previousLocals         = previousLocals;
            _previousTopLevelMethod = previousTopLevelMethod;
            _methodId              = methodId;
            _hoistedLocalSlots     = hoistedLocalSlots;
            _hoistedLocalSlotCount = hoistedLocalSlotCount;
            _stateMachineTypeName  = stateMachineTypeName;
            _awaiterCount          = awaiterCount;
            _awaiterMap            = awaiterMap;
            _stateMachineStateMap  = stateMachineStateMap;
            _lambdaMap             = lambdaMap;
            _closureMap            = closureMap;
            _lambdaSyntaxFacts     = lambdaSyntaxFacts;
            _firstUnusedIncreasingStateMachineState = firstUnusedIncreasingStateMachineState;
            _firstUnusedDecreasingStateMachineState = firstUnusedDecreasingStateMachineState;

            // Create a map from local info to slot.
            var previousLocalInfoToSlot = new Dictionary <EncLocalInfo, int>();

            for (int slot = 0; slot < previousLocals.Length; slot++)
            {
                var localInfo = previousLocals[slot];
                Debug.Assert(!localInfo.IsDefault);
                if (localInfo.IsUnused)
                {
                    // Unrecognized or deleted local.
                    continue;
                }

                previousLocalInfoToSlot.Add(localInfo, slot);
            }

            _previousLocalSlots = previousLocalInfoToSlot;
        }
Ejemplo n.º 5
0
        private static string MakeName(SyntaxNode scopeSyntaxOpt, DebugId methodId, DebugId closureId)
        {
            if (scopeSyntaxOpt == null)
            {
                // Display class is shared among static non-generic lambdas across generations, method ordinal is -1 in that case.
                // A new display class of a static generic lambda is created for each method and each generation.
                return GeneratedNames.MakeStaticLambdaDisplayClassName(methodId.Ordinal, methodId.Generation);
            }

            Debug.Assert(methodId.Ordinal >= 0);
            return GeneratedNames.MakeLambdaDisplayClassName(methodId.Ordinal, methodId.Generation, closureId.Ordinal, closureId.Generation);
        }
 private static string MakeName(string topLevelMethodName, DebugId topLevelMethodId, ClosureKind closureKind, DebugId lambdaId)
 {
     // Lambda method name must contain the declaring method ordinal to be unique unless the method is emitted into a closure class exclusive to the declaring method.
     // Lambdas that only close over "this" are emitted directly into the top-level method containing type.
     // Lambdas that don't close over anything (static) are emitted into a shared closure singleton.
     return GeneratedNames.MakeLambdaMethodName(
         topLevelMethodName,
         (closureKind == ClosureKind.General) ? -1 : topLevelMethodId.Ordinal,
         topLevelMethodId.Generation,
         lambdaId.Ordinal,
         lambdaId.Generation);
 }
        public override bool TryGetPreviousClosure(SyntaxNode scopeSyntax, out DebugId closureId)
        {
            if (_closureMap != null &&
                TryGetPreviousSyntaxOffset(scopeSyntax, out int syntaxOffset) &&
                _closureMap.TryGetValue(syntaxOffset, out closureId))
            {
                return(true);
            }

            closureId = default;
            return(false);
        }
Ejemplo n.º 8
0
 private static string MakeName(string topLevelMethodName, DebugId topLevelMethodId, ClosureKind closureKind, DebugId lambdaId)
 {
     // Lambda method name must contain the declaring method ordinal to be unique unless the method is emitted into a closure class exclusive to the declaring method.
     // Lambdas that only close over "this" are emitted directly into the top-level method containing type.
     // Lambdas that don't close over anything (static) are emitted into a shared closure singleton.
     return(GeneratedNames.MakeLambdaMethodName(
                topLevelMethodName,
                (closureKind == ClosureKind.General) ? -1 : topLevelMethodId.Ordinal,
                topLevelMethodId.Generation,
                lambdaId.Ordinal,
                lambdaId.Generation));
 }
Ejemplo n.º 9
0
        private static string MakeName(SyntaxNode scopeSyntaxOpt, DebugId methodId, DebugId closureId)
        {
            if (scopeSyntaxOpt == null)
            {
                // Display class is shared among static non-generic lambdas across generations, method ordinal is -1 in that case.
                // A new display class of a static generic lambda is created for each method and each generation.
                return(GeneratedNames.MakeStaticLambdaDisplayClassName(methodId.Ordinal, methodId.Generation));
            }

            Debug.Assert(methodId.Ordinal >= 0);
            return(GeneratedNames.MakeLambdaDisplayClassName(methodId.Ordinal, methodId.Generation, closureId.Ordinal, closureId.Generation));
        }
Ejemplo n.º 10
0
        private readonly IReadOnlyDictionary <int, DebugId> _closureMapOpt;                     // SyntaxOffset -> Id

        public EncVariableSlotAllocator(
            CommonMessageProvider messageProvider,
            SymbolMatcher symbolMap,
            Func <SyntaxNode, SyntaxNode> syntaxMapOpt,
            IMethodSymbolInternal previousTopLevelMethod,
            DebugId methodId,
            ImmutableArray <EncLocalInfo> previousLocals,
            IReadOnlyDictionary <int, KeyValuePair <DebugId, int> > lambdaMapOpt,
            IReadOnlyDictionary <int, DebugId> closureMapOpt,
            string stateMachineTypeNameOpt,
            int hoistedLocalSlotCount,
            IReadOnlyDictionary <EncHoistedLocalInfo, int> hoistedLocalSlotsOpt,
            int awaiterCount,
            IReadOnlyDictionary <Cci.ITypeReference, int> awaiterMapOpt)
        {
            Debug.Assert(messageProvider != null);
            Debug.Assert(symbolMap != null);
            Debug.Assert(previousTopLevelMethod != null);
            Debug.Assert(!previousLocals.IsDefault);

            _messageProvider        = messageProvider;
            _symbolMap              = symbolMap;
            _syntaxMapOpt           = syntaxMapOpt;
            _previousLocals         = previousLocals;
            _previousTopLevelMethod = previousTopLevelMethod;
            _methodId                = methodId;
            _hoistedLocalSlotsOpt    = hoistedLocalSlotsOpt;
            _hoistedLocalSlotCount   = hoistedLocalSlotCount;
            _stateMachineTypeNameOpt = stateMachineTypeNameOpt;
            _awaiterCount            = awaiterCount;
            _awaiterMapOpt           = awaiterMapOpt;
            _lambdaMapOpt            = lambdaMapOpt;
            _closureMapOpt           = closureMapOpt;

            // Create a map from local info to slot.
            var previousLocalInfoToSlot = new Dictionary <EncLocalInfo, int>();

            for (int slot = 0; slot < previousLocals.Length; slot++)
            {
                var localInfo = previousLocals[slot];
                Debug.Assert(!localInfo.IsDefault);
                if (localInfo.IsUnused)
                {
                    // Unrecognized or deleted local.
                    continue;
                }

                previousLocalInfoToSlot.Add(localInfo, slot);
            }

            _previousLocalSlots = previousLocalInfoToSlot;
        }
Ejemplo n.º 11
0
        public EncVariableSlotAllocator(
            CommonMessageProvider messageProvider,
            SymbolMatcher symbolMap,
            Func<SyntaxNode, SyntaxNode> syntaxMapOpt,
            IMethodSymbolInternal previousTopLevelMethod,
            DebugId methodId,
            ImmutableArray<EncLocalInfo> previousLocals,
            IReadOnlyDictionary<int, KeyValuePair<DebugId, int>> lambdaMapOpt,
            IReadOnlyDictionary<int, DebugId> closureMapOpt,
            string stateMachineTypeNameOpt,
            int hoistedLocalSlotCount,
            IReadOnlyDictionary<EncHoistedLocalInfo, int> hoistedLocalSlotsOpt,
            int awaiterCount,
            IReadOnlyDictionary<Cci.ITypeReference, int> awaiterMapOpt)
        {
            Debug.Assert(messageProvider != null);
            Debug.Assert(symbolMap != null);
            Debug.Assert(previousTopLevelMethod != null);
            Debug.Assert(!previousLocals.IsDefault);

            _messageProvider = messageProvider;
            _symbolMap = symbolMap;
            _syntaxMapOpt = syntaxMapOpt;
            _previousLocals = previousLocals;
            _previousTopLevelMethod = previousTopLevelMethod;
            _methodId = methodId;
            _hoistedLocalSlotsOpt = hoistedLocalSlotsOpt;
            _hoistedLocalSlotCount = hoistedLocalSlotCount;
            _stateMachineTypeNameOpt = stateMachineTypeNameOpt;
            _awaiterCount = awaiterCount;
            _awaiterMapOpt = awaiterMapOpt;
            _lambdaMapOpt = lambdaMapOpt;
            _closureMapOpt = closureMapOpt;

            // Create a map from local info to slot.
            var previousLocalInfoToSlot = new Dictionary<EncLocalInfo, int>();
            for (int slot = 0; slot < previousLocals.Length; slot++)
            {
                var localInfo = previousLocals[slot];
                Debug.Assert(!localInfo.IsDefault);
                if (localInfo.IsUnused)
                {
                    // Unrecognized or deleted local.
                    continue;
                }

                previousLocalInfoToSlot.Add(localInfo, slot);
            }

            _previousLocalSlots = previousLocalInfoToSlot;
        }
Ejemplo n.º 12
0
 private static string MakeName(
     string topLevelMethodName,
     string localFunctionName,
     DebugId topLevelMethodId,
     ClosureKind closureKind,
     DebugId lambdaId
     )
 {
     return(GeneratedNames.MakeLocalFunctionName(
                topLevelMethodName,
                localFunctionName,
                (closureKind == ClosureKind.General) ? -1 : topLevelMethodId.Ordinal,
                topLevelMethodId.Generation,
                lambdaId.Ordinal,
                lambdaId.Generation
                ));
 }
Ejemplo n.º 13
0
        public MethodBody(
            ImmutableArray<byte> ilBits,
            ushort maxStack,
            Cci.IMethodDefinition parent,
            DebugId methodId,
            ImmutableArray<Cci.ILocalDefinition> locals,
            SequencePointList sequencePoints,
            DebugDocumentProvider debugDocumentProvider,
            ImmutableArray<Cci.ExceptionHandlerRegion> exceptionHandlers,
            ImmutableArray<Cci.LocalScope> localScopes,
            bool hasDynamicLocalVariables,
            Cci.IImportScope importScopeOpt,
            ImmutableArray<LambdaDebugInfo> lambdaDebugInfo,
            ImmutableArray<ClosureDebugInfo> closureDebugInfo,
            string stateMachineTypeNameOpt,
            ImmutableArray<Cci.StateMachineHoistedLocalScope> stateMachineHoistedLocalScopes,
            ImmutableArray<EncHoistedLocalInfo> stateMachineHoistedLocalSlots,
            ImmutableArray<Cci.ITypeReference> stateMachineAwaiterSlots,
            Cci.AsyncMethodBodyDebugInfo asyncMethodDebugInfo,
            DynamicAnalysisMethodBodyData dynamicAnalysisDataOpt)
        {
            Debug.Assert(!locals.IsDefault);
            Debug.Assert(!exceptionHandlers.IsDefault);
            Debug.Assert(!localScopes.IsDefault);

            _ilBits = ilBits;
            _asyncMethodDebugInfo = asyncMethodDebugInfo;
            _maxStack = maxStack;
            _parent = parent;
            _methodId = methodId;
            _locals = locals;
            _sequencePoints = sequencePoints;
            _debugDocumentProvider = debugDocumentProvider;
            _exceptionHandlers = exceptionHandlers;
            _localScopes = localScopes;
            _hasDynamicLocalVariables = hasDynamicLocalVariables;
            _importScopeOpt = importScopeOpt;
            _lambdaDebugInfo = lambdaDebugInfo;
            _closureDebugInfo = closureDebugInfo;
            _stateMachineTypeNameOpt = stateMachineTypeNameOpt;
            _stateMachineHoistedLocalScopes = stateMachineHoistedLocalScopes;
            _stateMachineHoistedLocalSlots = stateMachineHoistedLocalSlots;
            _stateMachineAwaiterSlots = stateMachineAwaiterSlots;
            _dynamicAnalysisDataOpt = dynamicAnalysisDataOpt;
        }
Ejemplo n.º 14
0
        internal LambdaFrame(MethodSymbol topLevelMethod, CSharpSyntaxNode scopeSyntaxOpt, DebugId methodId, DebugId closureId)
            : base(MakeName(scopeSyntaxOpt, methodId, closureId), topLevelMethod)
        {
            _topLevelMethod = topLevelMethod;
            _constructor = new LambdaFrameConstructor(this);
            this.ClosureOrdinal = closureId.Ordinal;

            // static lambdas technically have the class scope so the scope syntax is null 
            if (scopeSyntaxOpt == null)
            {
                _staticConstructor = new SynthesizedStaticConstructor(this);
                var cacheVariableName = GeneratedNames.MakeCachedFrameInstanceFieldName();
                _singletonCache = new SynthesizedLambdaCacheFieldSymbol(this, this, cacheVariableName, topLevelMethod, isReadOnly: true, isStatic: true);
            }

            AssertIsClosureScopeSyntax(scopeSyntaxOpt);
            this.ScopeSyntaxOpt = scopeSyntaxOpt;
        }
        internal SynthesizedLambdaMethod(
            NamedTypeSymbol containingType,
            ClosureKind closureKind,
            MethodSymbol topLevelMethod,
            DebugId topLevelMethodId,
            BoundLambda lambdaNode,
            DebugId lambdaId)
            : base(containingType,
                   lambdaNode.Symbol,
                   null,
                   lambdaNode.SyntaxTree.GetReference(lambdaNode.Body.Syntax),
                   lambdaNode.Syntax.GetLocation(),
                   MakeName(topLevelMethod.Name, topLevelMethodId, closureKind, lambdaId),
                   (closureKind == ClosureKind.ThisOnly ? DeclarationModifiers.Private : DeclarationModifiers.Internal)
                       | (lambdaNode.Symbol.IsAsync ? DeclarationModifiers.Async : 0))
        {
            _topLevelMethod = topLevelMethod;

            TypeMap typeMap;
            ImmutableArray<TypeParameterSymbol> typeParameters;
            LambdaFrame lambdaFrame;

            if (!topLevelMethod.IsGenericMethod)
            {
                typeMap = TypeMap.Empty;
                typeParameters = ImmutableArray<TypeParameterSymbol>.Empty;
            }
            else if ((object)(lambdaFrame = this.ContainingType as LambdaFrame) != null)
            {
                typeMap = lambdaFrame.TypeMap;
                typeParameters = ImmutableArray<TypeParameterSymbol>.Empty;
            }
            else
            {
                typeMap = TypeMap.Empty.WithAlphaRename(topLevelMethod, this, out typeParameters);
            }

            AssignTypeMapAndTypeParameters(typeMap, typeParameters);
        }
Ejemplo n.º 16
0
            internal DebugId GetClosureId(SyntaxNode syntax, ArrayBuilder <ClosureDebugInfo> closureDebugInfo)
            {
                Debug.Assert(syntax != null);

                DebugId closureId;
                DebugId previousClosureId;

                if (_slotAllocatorOpt != null && _slotAllocatorOpt.TryGetPreviousClosure(syntax, out previousClosureId))
                {
                    closureId = previousClosureId;
                }
                else
                {
                    closureId = new DebugId(closureDebugInfo.Count, _compilationState.ModuleBuilderOpt.CurrentGenerationOrdinal);
                }

                int syntaxOffset = _topLevelMethod.CalculateLocalSyntaxOffset(syntax.SpanStart, syntax.SyntaxTree);

                closureDebugInfo.Add(new ClosureDebugInfo(syntaxOffset, closureId));

                return(closureId);
            }
Ejemplo n.º 17
0
        internal SynthesizedLambdaMethod(
            NamedTypeSymbol containingType,
            ClosureKind closureKind,
            MethodSymbol topLevelMethod,
            DebugId topLevelMethodId,
            BoundLambda lambdaNode,
            DebugId lambdaId)
            : base(containingType,
                   lambdaNode.Symbol,
                   null,
                   lambdaNode.SyntaxTree.GetReference(lambdaNode.Body.Syntax),
                   lambdaNode.Syntax.GetLocation(),
                   MakeName(topLevelMethod.Name, topLevelMethodId, closureKind, lambdaId),
                   (closureKind == ClosureKind.ThisOnly ? DeclarationModifiers.Private : DeclarationModifiers.Internal)
                   | (lambdaNode.Symbol.IsAsync ? DeclarationModifiers.Async : 0))
        {
            _topLevelMethod = topLevelMethod;

            TypeMap typeMap;
            ImmutableArray <TypeParameterSymbol> typeParameters;
            LambdaFrame lambdaFrame;

            if (!topLevelMethod.IsGenericMethod)
            {
                typeMap        = TypeMap.Empty;
                typeParameters = ImmutableArray <TypeParameterSymbol> .Empty;
            }
            else if ((object)(lambdaFrame = this.ContainingType as LambdaFrame) != null)
            {
                typeMap        = lambdaFrame.TypeMap;
                typeParameters = ImmutableArray <TypeParameterSymbol> .Empty;
            }
            else
            {
                typeMap = TypeMap.Empty.WithAlphaRename(topLevelMethod, this, out typeParameters);
            }

            AssignTypeMapAndTypeParameters(typeMap, typeParameters);
        }
Ejemplo n.º 18
0
        public override bool TryGetPreviousLambda(
            SyntaxNode lambdaOrLambdaBodySyntax,
            bool isLambdaBody,
            out DebugId lambdaId
            )
        {
            if (
                _lambdaMap != null &&
                TryGetPreviousLambdaSyntaxOffset(
                    lambdaOrLambdaBodySyntax,
                    isLambdaBody,
                    out int syntaxOffset
                    ) &&
                _lambdaMap.TryGetValue(syntaxOffset, out var idAndClosureOrdinal)
                )
            {
                lambdaId = idAndClosureOrdinal.Key;
                return(true);
            }

            lambdaId = default;
            return(false);
        }
Ejemplo n.º 19
0
 public override bool TryGetPreviousLambda(SyntaxNode lambdaOrLambdaBodySyntax, bool isLambdaBody, out DebugId lambdaId)
 {
     lambdaId = default(DebugId);
     return false;
 }
        public override bool TryGetPreviousLambda(SyntaxNode lambdaOrLambdaBodySyntax, bool isLambdaBody, out DebugId lambdaId)
        {
            KeyValuePair<DebugId, int> idAndClosureOrdinal;

            int syntaxOffset;
            if (_lambdaMapOpt != null &&
                TryGetPreviousLambdaSyntaxOffset(lambdaOrLambdaBodySyntax, isLambdaBody, out syntaxOffset) &&
                _lambdaMapOpt.TryGetValue(syntaxOffset, out idAndClosureOrdinal))
            {
                lambdaId = idAndClosureOrdinal.Key;
                return true;
            }

            lambdaId = default(DebugId);
            return false;
        }
        public override bool TryGetPreviousClosure(SyntaxNode scopeSyntax, out DebugId closureId)
        {
            int syntaxOffset;
            if (_closureMapOpt != null &&
                TryGetPreviousSyntaxOffset(scopeSyntax, out syntaxOffset) &&
                _closureMapOpt.TryGetValue(syntaxOffset, out closureId))
            {
                return true;
            }

            closureId = default(DebugId);
            return false;
        }
Ejemplo n.º 22
0
        internal SynthesizedLambdaMethod(
            NamedTypeSymbol containingType,
            ImmutableArray <TypeSymbol> structClosures,
            ClosureKind closureKind,
            MethodSymbol topLevelMethod,
            DebugId topLevelMethodId,
            IBoundLambdaOrFunction lambdaNode,
            DebugId lambdaId)
            : base(containingType,
                   lambdaNode.Symbol,
                   null,
                   lambdaNode.Syntax.SyntaxTree.GetReference(lambdaNode.Body.Syntax),
                   lambdaNode.Syntax.GetLocation(),
                   lambdaNode is BoundLocalFunctionStatement ?
                   MakeName(topLevelMethod.Name, lambdaNode.Symbol.Name, topLevelMethodId, closureKind, lambdaId) :
                   MakeName(topLevelMethod.Name, topLevelMethodId, closureKind, lambdaId),
                   (closureKind == ClosureKind.ThisOnly ? DeclarationModifiers.Private : DeclarationModifiers.Internal)
                   | (closureKind == ClosureKind.Static ? DeclarationModifiers.Static : 0)
                   | (lambdaNode.Symbol.IsAsync ? DeclarationModifiers.Async : 0))
        {
            _topLevelMethod = topLevelMethod;
            ClosureKind     = closureKind;

            TypeMap typeMap;
            ImmutableArray <TypeParameterSymbol> typeParameters;
            ImmutableArray <TypeParameterSymbol> constructedFromTypeParameters;
            LambdaFrame lambdaFrame;

            lambdaFrame = this.ContainingType as LambdaFrame;
            switch (closureKind)
            {
            case ClosureKind.Singleton:   // all type parameters on method (except the top level method's)
            case ClosureKind.General:     // only lambda's type parameters on method (rest on class)
                Debug.Assert(lambdaFrame != null);
                typeMap = lambdaFrame.TypeMap.WithConcatAlphaRename(lambdaNode.Symbol, this, out typeParameters, out constructedFromTypeParameters, lambdaFrame.ContainingMethod);
                break;

            case ClosureKind.ThisOnly:     // all type parameters on method
            case ClosureKind.Static:
                Debug.Assert(lambdaFrame == null);
                typeMap = TypeMap.Empty.WithConcatAlphaRename(lambdaNode.Symbol, this, out typeParameters, out constructedFromTypeParameters, null);
                break;

            default:
                throw ExceptionUtilities.Unreachable;
            }

            if (!structClosures.IsDefaultOrEmpty && typeParameters.Length != 0)
            {
                var constructedStructClosures = ArrayBuilder <TypeSymbol> .GetInstance();

                foreach (var closure in structClosures)
                {
                    var             frame = (LambdaFrame)closure;
                    NamedTypeSymbol constructed;
                    if (frame.Arity == 0)
                    {
                        constructed = frame;
                    }
                    else
                    {
                        var originals = frame.ConstructedFromTypeParameters;
                        var newArgs   = typeMap.SubstituteTypeParameters(originals);
                        constructed = frame.Construct(newArgs);
                    }
                    constructedStructClosures.Add(constructed);
                }
                structClosures = constructedStructClosures.ToImmutableAndFree();
            }
            _structClosures = structClosures;

            AssignTypeMapAndTypeParameters(typeMap, typeParameters);
        }
        private unsafe static void UncompressLambdaMap(
            ImmutableArray <byte> compressedLambdaMap,
            out int methodOrdinal,
            out ImmutableArray <ClosureDebugInfo> closures,
            out ImmutableArray <LambdaDebugInfo> lambdas)
        {
            methodOrdinal = DebugId.UndefinedOrdinal;
            closures      = default(ImmutableArray <ClosureDebugInfo>);
            lambdas       = default(ImmutableArray <LambdaDebugInfo>);

            if (compressedLambdaMap.IsDefaultOrEmpty)
            {
                return;
            }

            var closuresBuilder = ArrayBuilder <ClosureDebugInfo> .GetInstance();

            var lambdasBuilder = ArrayBuilder <LambdaDebugInfo> .GetInstance();

            fixed(byte *blobPtr = &compressedLambdaMap.ToArray()[0])
            {
                var blobReader = new BlobReader(blobPtr, compressedLambdaMap.Length);

                try
                {
                    // Note: integer operations below can't overflow since compressed integers are in range [0, 0x20000000)

                    // [-1, inf)
                    methodOrdinal = blobReader.ReadCompressedInteger() - 1;

                    int syntaxOffsetBaseline = -blobReader.ReadCompressedInteger();

                    int closureCount = blobReader.ReadCompressedInteger();

                    for (int i = 0; i < closureCount; i++)
                    {
                        int syntaxOffset = blobReader.ReadCompressedInteger();

                        var closureId = new DebugId(closuresBuilder.Count, generation: 0);
                        closuresBuilder.Add(new ClosureDebugInfo(syntaxOffset + syntaxOffsetBaseline, closureId));
                    }

                    while (blobReader.RemainingBytes > 0)
                    {
                        int syntaxOffset   = blobReader.ReadCompressedInteger();
                        int closureOrdinal = blobReader.ReadCompressedInteger() + LambdaDebugInfo.MinClosureOrdinal;

                        if (closureOrdinal >= closureCount)
                        {
                            throw CreateInvalidDataException(compressedLambdaMap, blobReader.Offset);
                        }

                        var lambdaId = new DebugId(lambdasBuilder.Count, generation: 0);
                        lambdasBuilder.Add(new LambdaDebugInfo(syntaxOffset + syntaxOffsetBaseline, lambdaId, closureOrdinal));
                    }
                }
                catch (BadImageFormatException)
                {
                    throw CreateInvalidDataException(compressedLambdaMap, blobReader.Offset);
                }
            }

            closures = closuresBuilder.ToImmutableAndFree();
            lambdas  = lambdasBuilder.ToImmutableAndFree();
        }
Ejemplo n.º 24
0
 /// <summary>
 /// Finds a lambda in the previous generation that corresponds to the specified syntax.
 /// The <paramref name="lambdaOrLambdaBodySyntax"/> is either a lambda syntax (<paramref name="isLambdaBody"/> is false),
 /// or lambda body syntax (<paramref name="isLambdaBody"/> is true).
 /// </summary>
 public abstract bool TryGetPreviousLambda(SyntaxNode lambdaOrLambdaBodySyntax, bool isLambdaBody, out DebugId lambdaId);
Ejemplo n.º 25
0
 /// <summary>
 /// Finds a closure in the previous generation that corresponds to the specified syntax.
 /// </summary>
 /// <remarks>
 /// See LambdaFrame.AssertIsLambdaScopeSyntax for kinds of syntax nodes that represent closures.
 /// </remarks>
 public abstract bool TryGetPreviousClosure(SyntaxNode closureSyntax, out DebugId closureId);
Ejemplo n.º 26
0
        internal VariableSlotAllocator?TryCreateVariableSlotAllocator(EmitBaseline baseline, Compilation compilation, IMethodSymbolInternal method, IMethodSymbolInternal topLevelMethod, DiagnosticBag diagnostics)
        {
            // Top-level methods are always included in the semantic edit list. Lambda methods are not.
            if (!mappedMethods.TryGetValue(topLevelMethod, out var mappedMethod))
            {
                return(null);
            }

            // TODO (bug https://github.com/dotnet/roslyn/issues/2504):
            // Handle cases when the previous method doesn't exist.

            if (!TryGetMethodHandle(baseline, (Cci.IMethodDefinition)method.GetCciAdapter(), out var previousHandle))
            {
                // Unrecognized method. Must have been added in the current compilation.
                return(null);
            }

            ImmutableArray <EncLocalInfo> previousLocals;
            IReadOnlyDictionary <EncHoistedLocalInfo, int>?         hoistedLocalMap = null;
            IReadOnlyDictionary <Cci.ITypeReference, int>?          awaiterMap      = null;
            IReadOnlyDictionary <int, KeyValuePair <DebugId, int> >?lambdaMap       = null;
            IReadOnlyDictionary <int, DebugId>?closureMap           = null;
            IReadOnlyDictionary <int, int>?    stateMachineStateMap = null;
            int?firstUnusedIncreasingStateMachineState = null;
            int?firstUnusedDecreasingStateMachineState = null;

            int           hoistedLocalSlotCount = 0;
            int           awaiterSlotCount      = 0;
            string?       stateMachineTypeName  = null;
            SymbolMatcher symbolMap;

            int     methodIndex = MetadataTokens.GetRowNumber(previousHandle);
            DebugId methodId;

            // Check if method has changed previously. If so, we already have a map.
            if (baseline.AddedOrChangedMethods.TryGetValue(methodIndex, out var addedOrChangedMethod))
            {
                methodId = addedOrChangedMethod.MethodId;

                MakeLambdaAndClosureMaps(addedOrChangedMethod.LambdaDebugInfo, addedOrChangedMethod.ClosureDebugInfo, out lambdaMap, out closureMap);
                MakeStateMachineStateMap(addedOrChangedMethod.StateMachineStates.States, out stateMachineStateMap);

                firstUnusedIncreasingStateMachineState = addedOrChangedMethod.StateMachineStates.FirstUnusedIncreasingStateMachineState;
                firstUnusedDecreasingStateMachineState = addedOrChangedMethod.StateMachineStates.FirstUnusedDecreasingStateMachineState;

                if (addedOrChangedMethod.StateMachineTypeName != null)
                {
                    // method is async/iterator kickoff method
                    GetStateMachineFieldMapFromPreviousCompilation(
                        addedOrChangedMethod.StateMachineHoistedLocalSlotsOpt,
                        addedOrChangedMethod.StateMachineAwaiterSlotsOpt,
                        out hoistedLocalMap,
                        out awaiterMap);

                    hoistedLocalSlotCount = addedOrChangedMethod.StateMachineHoistedLocalSlotsOpt.Length;
                    awaiterSlotCount      = addedOrChangedMethod.StateMachineAwaiterSlotsOpt.Length;

                    // Kickoff method has no interesting locals on its own.
                    // We use the EnC method debug information for hoisted locals.
                    previousLocals = ImmutableArray <EncLocalInfo> .Empty;

                    stateMachineTypeName = addedOrChangedMethod.StateMachineTypeName;
                }
                else
                {
                    previousLocals = addedOrChangedMethod.Locals;
                }

                // All types that AddedOrChangedMethodInfo refers to have been mapped to the previous generation.
                // Therefore we don't need to fall back to metadata if we don't find the type reference, like we do in DefinitionMap.MapReference.
                symbolMap = MapToPreviousSymbolMatcher;
            }
            else
            {
                // Method has not changed since initial generation. Generate a map
                // using the local names provided with the initial metadata.
                EditAndContinueMethodDebugInformation debugInfo;
                StandaloneSignatureHandle             localSignature;
                try
                {
                    debugInfo      = baseline.DebugInformationProvider(previousHandle);
                    localSignature = baseline.LocalSignatureProvider(previousHandle);
                }
                catch (Exception e) when(e is InvalidDataException || e is IOException)
                {
                    diagnostics.Add(MessageProvider.CreateDiagnostic(
                                        MessageProvider.ERR_InvalidDebugInfo,
                                        method.Locations.First(),
                                        method,
                                        MetadataTokens.GetToken(previousHandle),
                                        method.ContainingAssembly
                                        ));

                    return(null);
                }

                methodId = new DebugId(debugInfo.MethodOrdinal, 0);

                if (!debugInfo.Lambdas.IsDefaultOrEmpty)
                {
                    MakeLambdaAndClosureMaps(debugInfo.Lambdas, debugInfo.Closures, out lambdaMap, out closureMap);
                }

                MakeStateMachineStateMap(debugInfo.StateMachineStates, out stateMachineStateMap);

                if (!debugInfo.StateMachineStates.IsDefaultOrEmpty)
                {
                    firstUnusedIncreasingStateMachineState = debugInfo.StateMachineStates.Max(s => s.StateNumber) + 1;
                    firstUnusedDecreasingStateMachineState = debugInfo.StateMachineStates.Min(s => s.StateNumber) - 1;
                }

                ITypeSymbolInternal?stateMachineType = TryGetStateMachineType(previousHandle);
                if (stateMachineType != null)
                {
                    // method is async/iterator kickoff method
                    var localSlotDebugInfo = debugInfo.LocalSlots.NullToEmpty();
                    GetStateMachineFieldMapFromMetadata(stateMachineType, localSlotDebugInfo, out hoistedLocalMap, out awaiterMap, out awaiterSlotCount);
                    hoistedLocalSlotCount = localSlotDebugInfo.Length;

                    // Kickoff method has no interesting locals on its own.
                    // We use the EnC method debug information for hoisted locals.
                    previousLocals = ImmutableArray <EncLocalInfo> .Empty;

                    stateMachineTypeName = stateMachineType.Name;
                }
                else
                {
                    // If the current method is async/iterator then either the previous method wasn't declared as async/iterator and it's updated to be one,
                    // or it was but is not marked by the corresponding state machine attribute because it was missing in the compilation.
                    // In the later case we need to report an error since we don't known how to map to the previous state machine.

                    // The IDE already checked that the attribute type is present in the base compilation, but didn't validate that it is well-formed.
                    // We don't have the base compilation to directly query for the attribute, only the source compilation.
                    // But since constructor signatures can't be updated during EnC we can just check the current compilation.

                    if (method.IsAsync)
                    {
                        if (compilation.CommonGetWellKnownTypeMember(WellKnownMember.System_Runtime_CompilerServices_AsyncStateMachineAttribute__ctor) == null)
                        {
                            ReportMissingStateMachineAttribute(diagnostics, method, AttributeDescription.AsyncStateMachineAttribute.FullName);
                            return(null);
                        }
                    }
                    else if (method.IsIterator)
                    {
                        if (compilation.CommonGetWellKnownTypeMember(WellKnownMember.System_Runtime_CompilerServices_IteratorStateMachineAttribute__ctor) == null)
                        {
                            ReportMissingStateMachineAttribute(diagnostics, method, AttributeDescription.IteratorStateMachineAttribute.FullName);
                            return(null);
                        }
                    }

                    try
                    {
                        previousLocals = localSignature.IsNil ? ImmutableArray <EncLocalInfo> .Empty :
                                         GetLocalSlotMapFromMetadata(localSignature, debugInfo);
                    }
                    catch (Exception e) when(e is UnsupportedSignatureContent || e is BadImageFormatException || e is IOException)
                    {
                        diagnostics.Add(MessageProvider.CreateDiagnostic(
                                            MessageProvider.ERR_InvalidDebugInfo,
                                            method.Locations.First(),
                                            method,
                                            MetadataTokens.GetToken(localSignature),
                                            method.ContainingAssembly
                                            ));

                        return(null);
                    }
                }

                symbolMap = MapToMetadataSymbolMatcher;
            }

            return(new EncVariableSlotAllocator(
                       symbolMap,
                       mappedMethod.SyntaxMap,
                       mappedMethod.PreviousMethod,
                       methodId,
                       previousLocals,
                       lambdaMap,
                       closureMap,
                       stateMachineTypeName,
                       hoistedLocalSlotCount,
                       hoistedLocalMap,
                       awaiterSlotCount,
                       awaiterMap,
                       stateMachineStateMap,
                       firstUnusedIncreasingStateMachineState,
                       firstUnusedDecreasingStateMachineState,
                       GetLambdaSyntaxFacts()));
        }
Ejemplo n.º 27
0
        public override bool TryGetPreviousLambda(SyntaxNode lambdaOrLambdaBodySyntax, bool isLambdaBody, out DebugId lambdaId)
        {
            KeyValuePair <DebugId, int> idAndClosureOrdinal;

            int syntaxOffset;

            if (_lambdaMapOpt != null &&
                TryGetPreviousLambdaSyntaxOffset(lambdaOrLambdaBodySyntax, isLambdaBody, out syntaxOffset) &&
                _lambdaMapOpt.TryGetValue(syntaxOffset, out idAndClosureOrdinal))
            {
                lambdaId = idAndClosureOrdinal.Key;
                return(true);
            }

            lambdaId = default(DebugId);
            return(false);
        }
Ejemplo n.º 28
0
        internal LambdaFrame(MethodSymbol topLevelMethod, CSharpSyntaxNode scopeSyntaxOpt, DebugId methodId, DebugId closureId)
            : base(MakeName(scopeSyntaxOpt, methodId, closureId), topLevelMethod)
        {
            _topLevelMethod     = topLevelMethod;
            _constructor        = new LambdaFrameConstructor(this);
            this.ClosureOrdinal = closureId.Ordinal;

            // static lambdas technically have the class scope so the scope syntax is null
            if (scopeSyntaxOpt == null)
            {
                _staticConstructor = new SynthesizedStaticConstructor(this);
                var cacheVariableName = GeneratedNames.MakeCachedFrameInstanceFieldName();
                _singletonCache = new SynthesizedLambdaCacheFieldSymbol(this, this, cacheVariableName, topLevelMethod, isReadOnly: true, isStatic: true);
            }

            AssertIsClosureScopeSyntax(scopeSyntaxOpt);
            this.ScopeSyntaxOpt = scopeSyntaxOpt;
        }
Ejemplo n.º 29
0
        internal SynthesizedLambdaMethod(
            NamedTypeSymbol containingType,
            ImmutableArray<TypeSymbol> structClosures,
            ClosureKind closureKind,
            MethodSymbol topLevelMethod,
            DebugId topLevelMethodId,
            IBoundLambdaOrFunction lambdaNode,
            DebugId lambdaId)
            : base(containingType,
                   lambdaNode.Symbol,
                   null,
                   lambdaNode.Syntax.SyntaxTree.GetReference(lambdaNode.Body.Syntax),
                   lambdaNode.Syntax.GetLocation(),
                   lambdaNode is BoundLocalFunctionStatement ?
                    MakeName(topLevelMethod.Name, lambdaNode.Symbol.Name, topLevelMethodId, closureKind, lambdaId) :
                    MakeName(topLevelMethod.Name, topLevelMethodId, closureKind, lambdaId),
                   (closureKind == ClosureKind.ThisOnly ? DeclarationModifiers.Private : DeclarationModifiers.Internal)
                       | (closureKind == ClosureKind.Static ? DeclarationModifiers.Static : 0)
                       | (lambdaNode.Symbol.IsAsync ? DeclarationModifiers.Async : 0))
        {
            _topLevelMethod = topLevelMethod;

            TypeMap typeMap;
            ImmutableArray<TypeParameterSymbol> typeParameters;
            ImmutableArray<TypeParameterSymbol> constructedFromTypeParameters;
            LambdaFrame lambdaFrame;

            lambdaFrame = this.ContainingType as LambdaFrame;
            switch (closureKind)
            {
                case ClosureKind.Singleton: // all type parameters on method (except the top level method's)
                case ClosureKind.General: // only lambda's type parameters on method (rest on class)
                    Debug.Assert(lambdaFrame != null);
                    typeMap = lambdaFrame.TypeMap.WithConcatAlphaRename(lambdaNode.Symbol, this, out typeParameters, out constructedFromTypeParameters, lambdaFrame.ContainingMethod);
                    break;
                case ClosureKind.ThisOnly: // all type parameters on method
                case ClosureKind.Static:
                    Debug.Assert(lambdaFrame == null);
                    typeMap = TypeMap.Empty.WithConcatAlphaRename(lambdaNode.Symbol, this, out typeParameters, out constructedFromTypeParameters, null);
                    break;
                default:
                    throw ExceptionUtilities.Unreachable;
            }

            if (!structClosures.IsDefaultOrEmpty && typeParameters.Length != 0)
            {
                var constructedStructClosures = ArrayBuilder<TypeSymbol>.GetInstance();
                foreach (var closure in structClosures)
                {
                    var frame = (LambdaFrame)closure;
                    NamedTypeSymbol constructed;
                    if (frame.Arity == 0)
                    {
                        constructed = frame;
                    }
                    else
                    {
                        var originals = frame.ConstructedFromTypeParameters;
                        var newArgs = typeMap.SubstituteTypeParameters(originals);
                        constructed = frame.Construct(newArgs);
                    }
                    constructedStructClosures.Add(constructed);
                }
                structClosures = constructedStructClosures.ToImmutableAndFree();
            }
            _structClosures = structClosures;

            AssignTypeMapAndTypeParameters(typeMap, typeParameters);
        }
Ejemplo n.º 30
0
 public override bool TryGetPreviousClosure(SyntaxNode closureSyntax, out DebugId closureId)
 {
     closureId = default(DebugId);
     return false;
 }
Ejemplo n.º 31
0
        internal SynthesizedClosureMethod(
            NamedTypeSymbol containingType,
            ImmutableArray <SynthesizedClosureEnvironment> structEnvironments,
            ClosureKind closureKind,
            MethodSymbol topLevelMethod,
            DebugId topLevelMethodId,
            MethodSymbol originalMethod,
            SyntaxReference blockSyntax,
            DebugId lambdaId)
            : base(containingType,
                   originalMethod,
                   null,
                   blockSyntax,
                   originalMethod.DeclaringSyntaxReferences[0].GetLocation(),
                   originalMethod is LocalFunctionSymbol
                    ? MakeName(topLevelMethod.Name, originalMethod.Name, topLevelMethodId, closureKind, lambdaId)
                    : MakeName(topLevelMethod.Name, topLevelMethodId, closureKind, lambdaId),
                   MakeDeclarationModifiers(closureKind, originalMethod))
        {
            _topLevelMethod = topLevelMethod;
            ClosureKind     = closureKind;
            LambdaId        = lambdaId;

            TypeMap typeMap;
            ImmutableArray <TypeParameterSymbol> typeParameters;
            ImmutableArray <TypeParameterSymbol> constructedFromTypeParameters;

            var lambdaFrame = ContainingType as SynthesizedClosureEnvironment;

            switch (closureKind)
            {
            case ClosureKind.Singleton:   // all type parameters on method (except the top level method's)
            case ClosureKind.General:     // only lambda's type parameters on method (rest on class)
                Debug.Assert(lambdaFrame != null);
                typeMap = lambdaFrame.TypeMap.WithConcatAlphaRename(
                    originalMethod,
                    this,
                    out typeParameters,
                    out constructedFromTypeParameters,
                    lambdaFrame.OriginalContainingMethodOpt);
                break;

            case ClosureKind.ThisOnly:     // all type parameters on method
            case ClosureKind.Static:
                Debug.Assert(lambdaFrame == null);
                typeMap = TypeMap.Empty.WithConcatAlphaRename(
                    originalMethod,
                    this,
                    out typeParameters,
                    out constructedFromTypeParameters,
                    stopAt: null);
                break;

            default:
                throw ExceptionUtilities.UnexpectedValue(closureKind);
            }

            if (!structEnvironments.IsDefaultOrEmpty && typeParameters.Length != 0)
            {
                var constructedStructClosures = ArrayBuilder <NamedTypeSymbol> .GetInstance();

                foreach (var env in structEnvironments)
                {
                    NamedTypeSymbol constructed;
                    if (env.Arity == 0)
                    {
                        constructed = env;
                    }
                    else
                    {
                        var originals = env.ConstructedFromTypeParameters;
                        var newArgs   = typeMap.SubstituteTypeParameters(originals);
                        constructed = env.Construct(newArgs);
                    }
                    constructedStructClosures.Add(constructed);
                }
                _structEnvironments = constructedStructClosures.ToImmutableAndFree();
            }
            else
            {
                _structEnvironments = ImmutableArray <NamedTypeSymbol> .CastUp(structEnvironments);
            }

            AssignTypeMapAndTypeParameters(typeMap, typeParameters);
        }
Ejemplo n.º 32
0
 public override bool TryGetPreviousClosure(SyntaxNode closureSyntax, out DebugId closureId)
 {
     closureId = default(DebugId);
     return(false);
 }
Ejemplo n.º 33
0
 public override bool TryGetPreviousLambda(SyntaxNode lambdaOrLambdaBodySyntax, bool isLambdaBody, out DebugId lambdaId)
 {
     lambdaId = default(DebugId);
     return(false);
 }
        private unsafe static void UncompressLambdaMap(
            ImmutableArray<byte> compressedLambdaMap,
            out int methodOrdinal,
            out ImmutableArray<ClosureDebugInfo> closures,
            out ImmutableArray<LambdaDebugInfo> lambdas)
        {
            methodOrdinal = DebugId.UndefinedOrdinal;
            closures = default(ImmutableArray<ClosureDebugInfo>);
            lambdas = default(ImmutableArray<LambdaDebugInfo>);

            if (compressedLambdaMap.IsDefaultOrEmpty)
            {
                return;
            }

            var closuresBuilder = ArrayBuilder<ClosureDebugInfo>.GetInstance();
            var lambdasBuilder = ArrayBuilder<LambdaDebugInfo>.GetInstance();

            fixed (byte* blobPtr = &compressedLambdaMap.ToArray()[0])
            {
                var blobReader = new BlobReader(blobPtr, compressedLambdaMap.Length);
                try
                {
                    // Note: integer operations below can't overflow since compressed integers are in range [0, 0x20000000)

                    // [-1, inf)
                    methodOrdinal = blobReader.ReadCompressedInteger() - 1;

                    int syntaxOffsetBaseline = -blobReader.ReadCompressedInteger();

                    int closureCount = blobReader.ReadCompressedInteger();

                    for (int i = 0; i < closureCount; i++)
                    {
                        int syntaxOffset = blobReader.ReadCompressedInteger();

                        var closureId = new DebugId(closuresBuilder.Count, generation: 0);
                        closuresBuilder.Add(new ClosureDebugInfo(syntaxOffset + syntaxOffsetBaseline, closureId));
                    }

                    while (blobReader.RemainingBytes > 0)
                    {
                        int syntaxOffset = blobReader.ReadCompressedInteger();
                        int closureOrdinal = blobReader.ReadCompressedInteger() + LambdaDebugInfo.MinClosureOrdinal;

                        if (closureOrdinal >= closureCount)
                        {
                            throw CreateInvalidDataException(compressedLambdaMap, blobReader.Offset);
                        }

                        var lambdaId = new DebugId(lambdasBuilder.Count, generation: 0);
                        lambdasBuilder.Add(new LambdaDebugInfo(syntaxOffset + syntaxOffsetBaseline, lambdaId, closureOrdinal));
                    }
                }
                catch (BadImageFormatException)
                {
                    throw CreateInvalidDataException(compressedLambdaMap, blobReader.Offset);
                }
            }

            closures = closuresBuilder.ToImmutableAndFree();
            lambdas = lambdasBuilder.ToImmutableAndFree();
        }
Ejemplo n.º 35
0
 private static string MakeName(string topLevelMethodName, string localFunctionName, DebugId topLevelMethodId, ClosureKind closureKind, DebugId lambdaId)
 {
     return GeneratedNames.MakeLocalFunctionName(
         topLevelMethodName,
         localFunctionName,
         (closureKind == ClosureKind.General) ? -1 : topLevelMethodId.Ordinal,
         topLevelMethodId.Generation,
         lambdaId.Ordinal,
         lambdaId.Generation);
 }
Ejemplo n.º 36
0
            private void MakeAndAssignEnvironments(ArrayBuilder <ClosureDebugInfo> closureDebugInfo)
            {
                VisitScopeTree(ScopeTree, scope =>
                {
                    if (scope.DeclaredVariables.Count > 0)
                    {
                        // First walk the nested scopes to find all closures which
                        // capture variables from this scope. They all need to capture
                        // this environment. This includes closures which captured local
                        // functions that capture those variables, so multiple passes may
                        // be needed. This will also decide if the environment is a struct
                        // or a class.
                        bool isStruct = true;
                        var closures  = new SetWithInsertionOrder <Closure>();
                        bool addedItem;
                        do
                        {
                            addedItem = false;
                            VisitClosures(scope, (closureScope, closure) =>
                            {
                                if (!closures.Contains(closure) &&
                                    (closure.CapturedVariables.Overlaps(scope.DeclaredVariables) ||
                                     closure.CapturedVariables.Overlaps(closures.Select(c => c.OriginalMethodSymbol))))
                                {
                                    closures.Add(closure);
                                    addedItem = true;
                                    isStruct &= CanTakeRefParameters(closure.OriginalMethodSymbol);
                                }
                            });
                        } while (addedItem == true);

                        // Next create the environment and add it to the declaration scope
                        // Currently all variables declared in the same scope are added
                        // to the same closure environment
                        var env = MakeEnvironment(scope, scope.DeclaredVariables, isStruct);
                        scope.DeclaredEnvironments.Add(env);

                        foreach (var closure in closures)
                        {
                            closure.CapturedEnvironments.Add(env);
                        }
                    }
                });

                ClosureEnvironment MakeEnvironment(Scope scope, IEnumerable <Symbol> capturedVariables, bool isStruct)
                {
                    var scopeBoundNode = scope.BoundNode;

                    var syntax = scopeBoundNode.Syntax;

                    Debug.Assert(syntax != null);

                    DebugId methodId  = GetTopLevelMethodId();
                    DebugId closureId = GetClosureId(syntax, closureDebugInfo);

                    var containingMethod = scope.ContainingClosureOpt?.OriginalMethodSymbol ?? _topLevelMethod;

                    if ((object)_substitutedSourceMethod != null && containingMethod == _topLevelMethod)
                    {
                        containingMethod = _substitutedSourceMethod;
                    }

                    return(new ClosureEnvironment(
                               capturedVariables,
                               _topLevelMethod,
                               containingMethod,
                               isStruct,
                               syntax,
                               methodId,
                               closureId));
                }
            }