コード例 #1
0
 /// <summary>
 /// Returns an index of a slot that stores specified hoisted local variable in the previous generation.
 /// </summary>
 public abstract bool TryGetPreviousHoistedLocalSlotIndex(
     SyntaxNode currentDeclarator,
     Cci.ITypeReference currentType,
     SynthesizedLocalKind synthesizedKind,
     LocalDebugId currentId,
     DiagnosticBag diagnostics,
     out int slotIndex);
コード例 #2
0
        public int AssignLocalOrdinal(SynthesizedLocalKind localKind, int syntaxOffset)
        {
#if !DEBUG
            // Optimization (avoid growing the dictionary below): 
            // User-defined locals have to have a distinct syntax offset, thus ordinal is always 0.
            if (localKind == SynthesizedLocalKind.UserDefined)
            {
                return 0;
            }
#endif
            int ordinal;
            long key = MakeKey(localKind, syntaxOffset);

            // Group by syntax offset and kind.
            // Variables associated with the same syntax and kind will be assigned different ordinals.
            if (_lazyMap == null)
            {
                _lazyMap = PooledDictionary<long, int>.GetInstance();
                ordinal = 0;
            }
            else if (!_lazyMap.TryGetValue(key, out ordinal))
            {
                ordinal = 0;
            }

            _lazyMap[key] = ordinal + 1;
            Debug.Assert(ordinal == 0 || localKind != SynthesizedLocalKind.UserDefined);
            return ordinal;
        }
コード例 #3
0
 internal SynthesizedLocal WithSynthesizedLocalKind(SynthesizedLocalKind kind)
 {
     return new SynthesizedLocal(
         this.containingMethodOpt,
         this.type,
         kind,
         this.syntaxOpt,
         this.isPinned, 
         this.refKind);
 }
コード例 #4
0
ファイル: SynthesizedLocal.cs プロジェクト: GloryChou/roslyn
 internal SynthesizedLocal WithSynthesizedLocalKindAndSyntax(SynthesizedLocalKind kind, SyntaxNode syntax)
 {
     return new SynthesizedLocal(
         _containingMethodOpt,
         _type,
         kind,
         syntax,
         _isPinned,
         _refKind);
 }
コード例 #5
0
        public EncHoistedLocalMetadata(string name, Cci.ITypeReference type, SynthesizedLocalKind synthesizedKind)
        {
            Debug.Assert(name != null);
            Debug.Assert(type != null);
            Debug.Assert(synthesizedKind.IsLongLived());

            this.Name = name;
            this.Type = type;
            this.SynthesizedKind = synthesizedKind;
        }
コード例 #6
0
 public abstract LocalDefinition GetPreviousLocal(
     Cci.ITypeReference type,
     ILocalSymbolInternal symbol,
     string nameOpt,
     SynthesizedLocalKind kind,
     LocalDebugId id,
     LocalVariableAttributes pdbAttributes,
     LocalSlotConstraints constraints,
     bool isDynamic,
     ImmutableArray<TypedConstant> dynamicTransformFlags);
コード例 #7
0
ファイル: SynthesizedLocal.cs プロジェクト: GloryChou/roslyn
 internal SynthesizedLocal(
     MethodSymbol containingMethodOpt,
     TypeSymbol type,
     SynthesizedLocalKind kind,
     SyntaxNode syntaxOpt = null,
     bool isPinned = false,
     RefKind refKind = RefKind.None)
 {
     _containingMethodOpt = containingMethodOpt;
     _type = type;
     _kind = kind;
     _syntaxOpt = syntaxOpt;
     _isPinned = isPinned;
     _refKind = refKind;
 }
コード例 #8
0
 internal SynthesizedLocal(
     MethodSymbol containingMethodOpt,
     TypeSymbol type,
     SynthesizedLocalKind kind,
     CSharpSyntaxNode syntaxOpt = null,
     bool isPinned = false,
     RefKind refKind = RefKind.None)
 {
     this.containingMethodOpt = containingMethodOpt;
     this.type = type;
     this.kind = kind;
     this.syntaxOpt = syntaxOpt;
     this.isPinned = isPinned;
     this.refKind = refKind;
 }
コード例 #9
0
        internal SynthesizedLocal(
            MethodSymbol containingMethodOpt,
            TypeSymbol type,
            SynthesizedLocalKind kind,
            CSharpSyntaxNode syntaxOpt = null,
            bool isPinned = false,
            RefKind refKind = RefKind.None, 
            [CallerLineNumber]int createdAtLineNumber = 0, 
            [CallerFilePath]string createdAtFilePath = null)
        {
            Debug.Assert(type.SpecialType != SpecialType.System_Void);

            this.containingMethodOpt = containingMethodOpt;
            this.type = type;
            this.kind = kind;
            this.syntaxOpt = syntaxOpt;
            this.isPinned = isPinned;
            this.refKind = refKind;

            this.createdAtLineNumber = createdAtLineNumber;
            this.createdAtFilePath = createdAtFilePath;
        }
コード例 #10
0
ファイル: LocalDefinition.cs プロジェクト: XieShuquan/roslyn
 /// <summary>
 /// Creates a new LocalDefinition.
 /// </summary>
 /// <param name="symbolOpt">Local symbol, used by edit and continue only, null otherwise.</param>
 /// <param name="nameOpt">Name associated with the slot.</param>
 /// <param name="type">Type associated with the slot.</param>
 /// <param name="slot">Slot position in the signature.</param>
 /// <param name="synthesizedKind">Local kind.</param>
 /// <param name="id">Local id.</param>
 /// <param name="pdbAttributes">Value to emit in the attributes field in the PDB.</param>
 /// <param name="constraints">Specifies whether slot type should have pinned modifier and whether slot should have byref constraint.</param>
 /// <param name="dynamicTransformFlags">The synthesized dynamic attributes of the local.</param>
 /// <param name="tupleElementNames">Tuple element names of the local.</param>
 public LocalDefinition(
     ILocalSymbol symbolOpt,
     string nameOpt,
     Cci.ITypeReference type,
     int slot,
     SynthesizedLocalKind synthesizedKind,
     LocalDebugId id,
     LocalVariableAttributes pdbAttributes,
     LocalSlotConstraints constraints,
     ImmutableArray<TypedConstant> dynamicTransformFlags,
     ImmutableArray<TypedConstant> tupleElementNames)
 {
     _symbolOpt = symbolOpt;
     _nameOpt = nameOpt;
     _type = type;
     _slot = slot;
     _slotInfo = new LocalSlotDebugInfo(synthesizedKind, id);
     _pdbAttributes = pdbAttributes;
     _dynamicTransformFlags = dynamicTransformFlags.NullToEmpty();
     _tupleElementNames = tupleElementNames.NullToEmpty();
     _constraints = constraints;
 }
コード例 #11
0
ファイル: LocalDefinition.cs プロジェクト: elemk0vv/roslyn-1
 /// <summary>
 /// Creates a new LocalDefinition.
 /// </summary>
 /// <param name="symbolOpt">Local symbol, used by edit and continue only, null otherwise.</param>
 /// <param name="nameOpt">Name associated with the slot.</param>
 /// <param name="type">Type associated with the slot.</param>
 /// <param name="slot">Slot position in the signature.</param>
 /// <param name="dynamicTransformFlags">Contains the synthesized dynamic attributes of the local</param>
 /// <param name="synthesizedKind">Local kind.</param>
 /// <param name="id">Local id.</param>
 /// <param name="pdbAttributes">Value to emit in the attributes field in the PDB.</param>
 /// <param name="constraints">Specifies whether slot type should have pinned modifier and whether slot should have byref constraint.</param>
 /// <param name="isDynamic">Specifies if the type is Dynamic.</param>
 public LocalDefinition(
     ILocalSymbol symbolOpt,
     string nameOpt,
     Cci.ITypeReference type,
     int slot,
     SynthesizedLocalKind synthesizedKind,
     LocalDebugId id,
     uint pdbAttributes,
     LocalSlotConstraints constraints,
     bool isDynamic,
     ImmutableArray<TypedConstant> dynamicTransformFlags)
 {
     _symbolOpt = symbolOpt;
     _nameOpt = nameOpt;
     _type = type;
     _slot = slot;
     _slotInfo = new LocalSlotDebugInfo(synthesizedKind, id);
     _pdbAttributes = pdbAttributes;
     _dynamicTransformFlags = dynamicTransformFlags;
     _constraints = constraints;
     _isDynamic = isDynamic;
 }
コード例 #12
0
ファイル: SynthesizedLocal.cs プロジェクト: GloryChou/roslyn
        internal SynthesizedLocal(
            MethodSymbol containingMethodOpt,
            TypeSymbol type,
            SynthesizedLocalKind kind,
            SyntaxNode syntaxOpt = null,
            bool isPinned = false,
            RefKind refKind = RefKind.None,
            [CallerLineNumber]int createdAtLineNumber = 0,
            [CallerFilePath]string createdAtFilePath = null)
        {
            Debug.Assert(type.SpecialType != SpecialType.System_Void);
            Debug.Assert(!kind.IsLongLived() || syntaxOpt != null);

            _containingMethodOpt = containingMethodOpt;
            _type = type;
            _kind = kind;
            _syntaxOpt = syntaxOpt;
            _isPinned = isPinned;
            _refKind = refKind;

            _createdAtLineNumber = createdAtLineNumber;
            _createdAtFilePath = createdAtFilePath;
        }
コード例 #13
0
        public override LocalDefinition GetPreviousLocal(
            Cci.ITypeReference currentType,
            ILocalSymbolInternal currentLocalSymbol,
            string nameOpt,
            SynthesizedLocalKind kind,
            LocalDebugId id,
            uint pdbAttributes,
            LocalSlotConstraints constraints,
            bool isDynamic,
            ImmutableArray<TypedConstant> dynamicTransformFlags)
        {
            if (id.IsNone)
            {
                return null;
            }

            LocalDebugId previousId;
            if (!TryGetPreviousLocalId(currentLocalSymbol.GetDeclaratorSyntax(), id, out previousId))
            {
                return null;
            }

            var previousType = _symbolMap.MapReference(currentType);
            if (previousType == null)
            {
                return null;
            }

            // TODO (bug #781309): Should report a warning if the type of the local has changed
            // and the previous value will be dropped.
            var localKey = new EncLocalInfo(new LocalSlotDebugInfo(kind, previousId), previousType, constraints, signature: null);

            int slot;
            if (!_previousLocalSlots.TryGetValue(localKey, out slot))
            {
                return null;
            }

            return new LocalDefinition(
                currentLocalSymbol,
                nameOpt,
                currentType,
                slot,
                kind,
                id,
                pdbAttributes,
                constraints,
                isDynamic,
                dynamicTransformFlags);
        }
コード例 #14
0
 public StateMachineFieldSymbol StateMachineField(TypeSymbol type, string name, SynthesizedLocalKind synthesizedKind, int slotIndex)
 {
     var result = new StateMachineFieldSymbol(CurrentType, type, name, synthesizedKind, slotIndex, isPublic: false);
     AddField(CurrentType, result);
     return result;
 }
コード例 #15
0
 public StateMachineFieldSymbol(NamedTypeSymbol stateMachineType, TypeSymbol type, string name, SynthesizedLocalKind synthesizedKind, int slotIndex, bool isPublic)
     : this(stateMachineType, type, name, new LocalSlotDebugInfo(synthesizedKind, LocalDebugId.None), slotIndex, isPublic: isPublic)
 {
 }
コード例 #16
0
 public static bool IsSlotReusable(this SynthesizedLocalKind kind, OptimizationLevel optimizations)
 {
     return(kind.IsSlotReusable(optimizations != OptimizationLevel.Release));
 }
コード例 #17
0
        public override bool TryGetPreviousHoistedLocalSlotIndex(SyntaxNode currentDeclarator, Cci.ITypeReference currentType, SynthesizedLocalKind synthesizedKind, LocalDebugId currentId, out int slotIndex)
        {
            Debug.Assert(_hoistedLocalSlotsOpt != null);

            LocalDebugId previousId;

            if (!TryGetPreviousLocalId(currentDeclarator, currentId, out previousId))
            {
                slotIndex = -1;
                return(false);
            }

            var previousType = _symbolMap.MapReference(currentType);

            if (previousType == null)
            {
                slotIndex = -1;
                return(false);
            }

            // TODO (bug #781309): Should report a warning if the type of the local has changed
            // and the previous value will be dropped.
            var localKey = new EncHoistedLocalInfo(new LocalSlotDebugInfo(synthesizedKind, previousId), previousType);

            return(_hoistedLocalSlotsOpt.TryGetValue(localKey, out slotIndex));
        }
コード例 #18
0
 private void AddSynthesizedLocal(SynthesizedLocalKind synthesizedKind)
 {
     AddLocalImpl(ref synthesizedSlotIndex, synthesizedKind);
 }
コード例 #19
0
ファイル: SourceLocalSymbol.cs プロジェクト: CAPCHIK/roslyn
 internal override LocalSymbol WithSynthesizedLocalKindAndSyntax(SynthesizedLocalKind kind, SyntaxNode syntax)
 {
     throw ExceptionUtilities.Unreachable;
 }
コード例 #20
0
 public LocalSymbol SynthesizedLocal(TypeSymbol type, CSharpSyntaxNode syntax = null, bool isPinned = false, RefKind refKind = RefKind.None, SynthesizedLocalKind kind = SynthesizedLocalKind.LoweringTemp)
 {
     return(new SynthesizedLocal(CurrentMethod, type, kind, syntax, isPinned, refKind));
 }
コード例 #21
0
 public LocalName(SynthesizedLocalKind kind, int uniqueId)
 {
     this.UserDefinedName = null;
     this.Kind            = kind;
     this.UniqueId        = uniqueId;
 }
コード例 #22
0
 public StateMachineFieldSymbol(NamedTypeSymbol stateMachineType, TypeSymbol type, string name, SynthesizedLocalKind synthesizedKind, int slotIndex, bool isPublic)
     : this(stateMachineType, type, name, new LocalSlotDebugInfo(synthesizedKind, LocalDebugId.None), slotIndex, isPublic : isPublic)
 {
 }
コード例 #23
0
        public override LocalDefinition?GetPreviousLocal(
            Cci.ITypeReference currentType,
            ILocalSymbolInternal currentLocalSymbol,
            string?name,
            SynthesizedLocalKind kind,
            LocalDebugId id,
            LocalVariableAttributes pdbAttributes,
            LocalSlotConstraints constraints,
            ImmutableArray <bool> dynamicTransformFlags,
            ImmutableArray <string> tupleElementNames
            )
        {
            if (id.IsNone)
            {
                return(null);
            }

            if (
                !TryGetPreviousLocalId(
                    currentLocalSymbol.GetDeclaratorSyntax(),
                    id,
                    out LocalDebugId previousId
                    )
                )
            {
                return(null);
            }

            var previousType = _symbolMap.MapReference(currentType);

            if (previousType == null)
            {
                return(null);
            }

            // TODO (bug #781309): Should report a warning if the type of the local has changed
            // and the previous value will be dropped.
            var localKey = new EncLocalInfo(
                new LocalSlotDebugInfo(kind, previousId),
                previousType,
                constraints,
                signature: null
                );

            if (!_previousLocalSlots.TryGetValue(localKey, out int slot))
            {
                return(null);
            }

            return(new LocalDefinition(
                       currentLocalSymbol,
                       name,
                       currentType,
                       slot,
                       kind,
                       id,
                       pdbAttributes,
                       constraints,
                       dynamicTransformFlags,
                       tupleElementNames
                       ));
        }
コード例 #24
0
        public override bool TryGetPreviousHoistedLocalSlotIndex(
            SyntaxNode currentDeclarator, 
            Cci.ITypeReference currentType,
            SynthesizedLocalKind synthesizedKind,
            LocalDebugId currentId,
            DiagnosticBag diagnostics, 
            out int slotIndex)
        {
            // Well-formed state machine attribute wasn't found in the baseline (the type is missing or bad).
            // Should rarely happen since the IDE reports a rude edit if the attribute type doesn't exist.
            if (_hoistedLocalSlotsOpt == null)
            {
                // TODO: better error message https://github.com/dotnet/roslyn/issues/9196
                diagnostics.Add(_messageProvider.CreateDiagnostic(_messageProvider.ERR_ModuleEmitFailure, NoLocation.Singleton, _previousTopLevelMethod.ContainingModule.Name));
                slotIndex = -1;
                return false;
            }

            LocalDebugId previousId;
            if (!TryGetPreviousLocalId(currentDeclarator, currentId, out previousId))
            {
                slotIndex = -1;
                return false;
            }

            var previousType = _symbolMap.MapReference(currentType);
            if (previousType == null)
            {
                slotIndex = -1;
                return false;
            }

            // TODO (bug #781309): Should report a warning if the type of the local has changed
            // and the previous value will be dropped.
            var localKey = new EncHoistedLocalInfo(new LocalSlotDebugInfo(synthesizedKind, previousId), previousType);

            return _hoistedLocalSlotsOpt.TryGetValue(localKey, out slotIndex);
        }
コード例 #25
0
        internal static string MakeHoistedLocalFieldName(SynthesizedLocalKind kind, int slotIndex, string localNameOpt = null)
        {
            Debug.Assert((localNameOpt != null) == (kind == SynthesizedLocalKind.UserDefined));
            Debug.Assert(slotIndex >= 0);
            Debug.Assert(kind.IsLongLived());

            // Lambda display class local follows a different naming pattern.
            // EE depends on the name format. 
            // There's logic in the EE to recognize locals that have been captured by a lambda
            // and would have been hoisted for the state machine.  Basically, we just hoist the local containing
            // the instance of the lambda display class and retain its original name (rather than using an
            // iterator local name).  See FUNCBRECEE::ImportIteratorMethodInheritedLocals.

            var result = PooledStringBuilder.GetInstance();
            var builder = result.Builder;
            builder.Append('<');
            if (localNameOpt != null)
            {
                Debug.Assert(localNameOpt.IndexOf('.') == -1);
                builder.Append(localNameOpt);
            }

            builder.Append('>');

            if (kind == SynthesizedLocalKind.LambdaDisplayClass)
            {
                builder.Append((char)GeneratedNameKind.DisplayClassLocalOrField);
            }
            else if (kind == SynthesizedLocalKind.UserDefined)
            {
                builder.Append((char)GeneratedNameKind.HoistedLocalField);
            }
            else
            {
                builder.Append((char)GeneratedNameKind.HoistedSynthesizedLocalField);
            }

            builder.Append("__");
            builder.Append(slotIndex + 1);

            return result.ToStringAndFree();
        }
コード例 #26
0
 private static long MakeKey(SynthesizedLocalKind localKind, int syntaxOffset)
 {
     return((long)syntaxOffset << 8 | (long)localKind);
 }
コード例 #27
0
        /// <summary>
        /// Takes an expression and returns the bound local expression "temp" 
        /// and the bound assignment expression "temp = expr".
        /// </summary>
        public BoundLocal StoreToTemp(BoundExpression argument, out BoundAssignmentOperator store, RefKind refKind = RefKind.None, SynthesizedLocalKind kind = SynthesizedLocalKind.LoweringTemp)
        {
            MethodSymbol containingMethod = this.CurrentMethod;
            var syntax = argument.Syntax;
            var type = argument.Type;

            var local = new BoundLocal(
                syntax,
                new SynthesizedLocal(containingMethod, type, kind, syntax: kind.IsLongLived() ? syntax : null, refKind: refKind),
                null,
                type);

            store = new BoundAssignmentOperator(
                syntax,
                local,
                argument,
                refKind,
                type);

            return local;
        }
コード例 #28
0
 /// <summary>
 /// Returns an index of a slot that stores specified hoisted local variable in the previous generation,
 /// or -1 if there is no such slot.
 /// </summary>
 public abstract int GetPreviousHoistedLocalSlotIndex(
     SyntaxNode currentDeclarator,
     Cci.ITypeReference currentType,
     SynthesizedLocalKind synthesizedKind,
     LocalDebugId currentId);
コード例 #29
0
ファイル: GeneratedNames.cs プロジェクト: afrog33k/csnative
        // Matches names generated by Dev11.
        internal static string MakeLocalName(SynthesizedLocalKind kind, int uniqueId)
        {
            Debug.Assert(kind.IsLongLived());

            if (kind == SynthesizedLocalKind.CachedAnonymousMethodDelegate)
            {
                // TODO: consider removing this special case, EE doesn't depend on the name. 
                return SynthesizedLocalNamePrefix + "<>9__CachedAnonymousMethodDelegate" + uniqueId;
        }

            if (kind == SynthesizedLocalKind.LambdaDisplayClass)
        {
                // Lambda display class local follows a different naming pattern.
                // EE depends on the name format. 
                return MakeLambdaDisplayClassStorageName(uniqueId);
            }

            return string.Format(SynthesizedLocalNamePrefix + "{0}${1:0000}", (int)kind, uniqueId);
        }
コード例 #30
0
        private BoundExpression HoistExpression(
            BoundExpression expr,
            AwaitExpressionSyntax awaitSyntaxOpt,
            int syntaxOffset,
            bool isRef,
            ArrayBuilder <BoundExpression> sideEffects,
            ArrayBuilder <StateMachineFieldSymbol> hoistedFields,
            ref bool needsSacrificialEvaluation)
        {
            switch (expr.Kind)
            {
            case BoundKind.ArrayAccess:
            {
                var             array      = (BoundArrayAccess)expr;
                BoundExpression expression = HoistExpression(array.Expression, awaitSyntaxOpt, syntaxOffset, false, sideEffects, hoistedFields, ref needsSacrificialEvaluation);
                var             indices    = ArrayBuilder <BoundExpression> .GetInstance();

                foreach (var index in array.Indices)
                {
                    indices.Add(HoistExpression(index, awaitSyntaxOpt, syntaxOffset, false, sideEffects, hoistedFields, ref needsSacrificialEvaluation));
                }

                needsSacrificialEvaluation = true;         // need to force array index out of bounds exceptions
                return(array.Update(expression, indices.ToImmutableAndFree(), array.Type));
            }

            case BoundKind.FieldAccess:
            {
                var field = (BoundFieldAccess)expr;
                if (field.FieldSymbol.IsStatic)
                {
                    // the address of a static field, and the value of a readonly static field, is stable
                    if (isRef || field.FieldSymbol.IsReadOnly)
                    {
                        return(expr);
                    }
                    goto default;
                }

                if (!isRef)
                {
                    goto default;
                }

                var isFieldOfStruct = !field.FieldSymbol.ContainingType.IsReferenceType;

                var receiver = HoistExpression(field.ReceiverOpt, awaitSyntaxOpt, syntaxOffset, isFieldOfStruct, sideEffects, hoistedFields, ref needsSacrificialEvaluation);
                if (receiver.Kind != BoundKind.ThisReference && !isFieldOfStruct)
                {
                    needsSacrificialEvaluation = true;         // need the null check in field receiver
                }

                return(F.Field(receiver, field.FieldSymbol));
            }

            case BoundKind.ThisReference:
            case BoundKind.BaseReference:
            case BoundKind.DefaultOperator:
                return(expr);

            default:
                if (expr.ConstantValue != null)
                {
                    return(expr);
                }

                if (isRef)
                {
                    throw ExceptionUtilities.UnexpectedValue(expr.Kind);
                }

                TypeSymbol fieldType = expr.Type;
                StateMachineFieldSymbol hoistedField;
                if (F.Compilation.Options.OptimizationLevel == OptimizationLevel.Debug)
                {
                    const SynthesizedLocalKind kind = SynthesizedLocalKind.AwaitByRefSpill;

                    Debug.Assert(awaitSyntaxOpt != null);

                    int ordinal = _synthesizedLocalOrdinals.AssignLocalOrdinal(kind, syntaxOffset);
                    var id      = new LocalDebugId(syntaxOffset, ordinal);

                    // Editing await expression is not allowed. Thus all spilled fields will be present in the previous state machine.
                    // However, it may happen that the type changes, in which case we need to allocate a new slot.
                    int slotIndex;
                    if (slotAllocatorOpt == null ||
                        !slotAllocatorOpt.TryGetPreviousHoistedLocalSlotIndex(
                            awaitSyntaxOpt,
                            F.ModuleBuilderOpt.Translate(fieldType, awaitSyntaxOpt, Diagnostics),
                            kind,
                            id,
                            Diagnostics,
                            out slotIndex))
                    {
                        slotIndex = _nextFreeHoistedLocalSlot++;
                    }

                    string fieldName = GeneratedNames.MakeHoistedLocalFieldName(kind, slotIndex);
                    hoistedField = F.StateMachineField(expr.Type, fieldName, new LocalSlotDebugInfo(kind, id), slotIndex);
                }
                else
                {
                    hoistedField = GetOrAllocateReusableHoistedField(fieldType);
                }

                hoistedFields.Add(hoistedField);

                var replacement = F.Field(F.This(), hoistedField);
                sideEffects.Add(F.AssignmentExpression(replacement, expr));
                return(replacement);
            }
        }
コード例 #31
0
 public override bool TryGetPreviousHoistedLocalSlotIndex(SyntaxNode currentDeclarator, Cci.ITypeReference currentType, SynthesizedLocalKind synthesizedKind, LocalDebugId currentId, DiagnosticBag diagnostics, out int slotIndex)
 {
     slotIndex = -1;
     return(false);
 }
コード例 #32
0
ファイル: LocalSymbol.cs プロジェクト: khm1600/CJing
 internal abstract LocalSymbol WithSynthesizedLocalKindAndSyntax(SynthesizedLocalKind kind, SyntaxNode syntax);
コード例 #33
0
 public static bool IsLongLived(this SynthesizedLocalKind kind)
 {
     return(kind >= SynthesizedLocalKind.UserDefined);
 }
コード例 #34
0
 public LocalSlotDebugInfo(SynthesizedLocalKind synthesizedKind, LocalDebugId id)
 {
     this.SynthesizedKind = synthesizedKind;
     this.Id = id;
 }
コード例 #35
0
ファイル: SourceLocalSymbol.cs プロジェクト: yourina/roslyn
 internal override LocalSymbol WithSynthesizedLocalKindAndSyntax(SynthesizedLocalKind kind, SyntaxNode syntax)
 {
     throw ExceptionUtilities.Unreachable;
 }
コード例 #36
0
        /// <summary>
        /// Takes an expression and returns the bound local expression "temp"
        /// and the bound assignment expression "temp = expr".
        /// </summary>
        public BoundLocal StoreToTemp(BoundExpression argument, out BoundAssignmentOperator store, RefKind refKind = RefKind.None, SynthesizedLocalKind kind = SynthesizedLocalKind.LoweringTemp)
        {
            MethodSymbol containingMethod = this.CurrentMethod;
            var          syntax           = argument.Syntax;
            var          type             = argument.Type;

            var local = new BoundLocal(
                syntax,
                new SynthesizedLocal(containingMethod, type, kind, syntax: kind.IsLongLived() ? syntax : null, refKind: refKind),
                null,
                type);

            store = new BoundAssignmentOperator(
                syntax,
                local,
                argument,
                refKind,
                type);

            return(local);
        }
コード例 #37
0
        /// <summary>
        /// Takes an expression and returns the bound local expression "temp" 
        /// and the bound assignment expression "temp = expr".
        /// </summary>
        public BoundLocal StoreToTemp(
            BoundExpression argument,
            out BoundAssignmentOperator store,
            RefKind refKind = RefKind.None,
            SynthesizedLocalKind kind = SynthesizedLocalKind.LoweringTemp,
            CSharpSyntaxNode syntaxOpt = null
#if DEBUG
            , [CallerLineNumber]int callerLineNumber = 0
            , [CallerFilePath]string callerFilePath = null
#endif
            )
        {
            MethodSymbol containingMethod = this.CurrentMethod;
            var syntax = argument.Syntax;
            var type = argument.Type;

            var local = new BoundLocal(
                syntax,
                new SynthesizedLocal(
                    containingMethod,
                    type,
                    kind,
#if DEBUG
                    createdAtLineNumber: callerLineNumber,
                    createdAtFilePath: callerFilePath,
#endif
                    syntaxOpt: syntaxOpt ?? (kind.IsLongLived() ? syntax : null),
                    isPinned: false,
                    refKind: refKind),
                null,
                type);

            store = new BoundAssignmentOperator(
                syntax,
                local,
                argument,
                refKind,
                type);

            return local;
        }
コード例 #38
0
 public static uint PdbAttributes(this SynthesizedLocalKind kind)
 {
     return((SynthesizedLocalKind.FirstIgnoredByExpressionCompiler <= kind && kind <= SynthesizedLocalKind.LastIgnoredByExpressionCompiler)
         ? Cci.PdbWriter.HiddenLocalAttributesValue
         : Cci.PdbWriter.DefaultLocalAttributesValue);
 }
コード例 #39
0
 public LocalSymbol SynthesizedLocal(
     TypeSymbol type,
     SyntaxNode syntax = null,
     bool isPinned = false,
     RefKind refKind = RefKind.None,
     SynthesizedLocalKind kind = SynthesizedLocalKind.LoweringTemp,
     [CallerLineNumber]int createdAtLineNumber = 0,
     [CallerFilePath]string createdAtFilePath = null)
 {
     return new SynthesizedLocal(CurrentMethod, type, kind, syntax, isPinned, refKind, createdAtLineNumber, createdAtFilePath);
 }
コード例 #40
0
 public LocalName(string name, SynthesizedLocalKind kind, int uniqueId)
 {
     this.Name     = name;
     this.Kind     = kind;
     this.UniqueId = uniqueId;
 }
コード例 #41
0
        public override bool TryGetPreviousHoistedLocalSlotIndex(SyntaxNode currentDeclarator, Cci.ITypeReference currentType, SynthesizedLocalKind synthesizedKind, LocalDebugId currentId, out int slotIndex)
        {
            Debug.Assert(_hoistedLocalSlotsOpt != null);

            LocalDebugId previousId;
            if (!TryGetPreviousLocalId(currentDeclarator, currentId, out previousId))
            {
                slotIndex = -1;
                return false;
            }

            var previousType = _symbolMap.MapReference(currentType);
            if (previousType == null)
            {
                slotIndex = -1;
                return false;
            }

            // TODO (bug #781309): Should report a warning if the type of the local has changed
            // and the previous value will be dropped.
            var localKey = new EncHoistedLocalInfo(new LocalSlotDebugInfo(synthesizedKind, previousId), previousType);

            return _hoistedLocalSlotsOpt.TryGetValue(localKey, out slotIndex);
        }
コード例 #42
0
        public override bool TryGetPreviousHoistedLocalSlotIndex(
            SyntaxNode currentDeclarator, 
            Cci.ITypeReference currentType,
            SynthesizedLocalKind synthesizedKind,
            LocalDebugId currentId,
            DiagnosticBag diagnostics, 
            out int slotIndex)
        {
            // The previous method was not a state machine (it is allowed to change non-state machine to a state machine):
            if (_hoistedLocalSlotsOpt == null)
            {
                slotIndex = -1;
                return false;
            }

            LocalDebugId previousId;
            if (!TryGetPreviousLocalId(currentDeclarator, currentId, out previousId))
            {
                slotIndex = -1;
                return false;
            }

            var previousType = _symbolMap.MapReference(currentType);
            if (previousType == null)
            {
                slotIndex = -1;
                return false;
            }

            // TODO (bug #781309): Should report a warning if the type of the local has changed
            // and the previous value will be dropped.
            var localKey = new EncHoistedLocalInfo(new LocalSlotDebugInfo(synthesizedKind, previousId), previousType);

            return _hoistedLocalSlotsOpt.TryGetValue(localKey, out slotIndex);
        }
コード例 #43
0
        internal static string MakeSynthesizedLocalName(SynthesizedLocalKind kind, ref int uniqueId)
        {
            Debug.Assert(kind.IsLongLived());

            // Lambda display class local has to be named. EE depends on the name format. 
            if (kind == SynthesizedLocalKind.LambdaDisplayClass)
            {
                return MakeLambdaDisplayLocalName(uniqueId++);
            }

            return null;
        }
コード例 #44
0
        private BoundExpression HoistExpression(
            BoundExpression expr,
            AwaitExpressionSyntax awaitSyntaxOpt,
            int syntaxOffset,
            RefKind refKind,
            ArrayBuilder <BoundExpression> sideEffects,
            ArrayBuilder <StateMachineFieldSymbol> hoistedFields,
            ref bool needsSacrificialEvaluation)
        {
            switch (expr.Kind)
            {
            case BoundKind.ArrayAccess:
            {
                var             array      = (BoundArrayAccess)expr;
                BoundExpression expression = HoistExpression(array.Expression, awaitSyntaxOpt, syntaxOffset, RefKind.None, sideEffects, hoistedFields, ref needsSacrificialEvaluation);
                var             indices    = ArrayBuilder <BoundExpression> .GetInstance();

                foreach (var index in array.Indices)
                {
                    indices.Add(HoistExpression(index, awaitSyntaxOpt, syntaxOffset, RefKind.None, sideEffects, hoistedFields, ref needsSacrificialEvaluation));
                }

                needsSacrificialEvaluation = true;         // need to force array index out of bounds exceptions
                return(array.Update(expression, indices.ToImmutableAndFree(), array.Type));
            }

            case BoundKind.FieldAccess:
            {
                var field = (BoundFieldAccess)expr;
                if (field.FieldSymbol.IsStatic)
                {
                    // the address of a static field, and the value of a readonly static field, is stable
                    if (refKind != RefKind.None || field.FieldSymbol.IsReadOnly)
                    {
                        return(expr);
                    }
                    goto default;
                }

                if (refKind == RefKind.None)
                {
                    goto default;
                }

                var isFieldOfStruct = !field.FieldSymbol.ContainingType.IsReferenceType;

                var receiver = HoistExpression(field.ReceiverOpt, awaitSyntaxOpt, syntaxOffset,
                                               isFieldOfStruct ? refKind : RefKind.None, sideEffects, hoistedFields, ref needsSacrificialEvaluation);
                if (receiver.Kind != BoundKind.ThisReference && !isFieldOfStruct)
                {
                    needsSacrificialEvaluation = true;         // need the null check in field receiver
                }

                return(F.Field(receiver, field.FieldSymbol));
            }

            case BoundKind.ThisReference:
            case BoundKind.BaseReference:
            case BoundKind.DefaultExpression:
                return(expr);

            case BoundKind.Call:
                var call = (BoundCall)expr;
                // NOTE: There are two kinds of 'In' arguments that we may see at this point:
                //       - `RefKindExtensions.StrictIn`     (originally specified with 'In' modifier)
                //       - `RefKind.In`                     (specified with no modifiers and matched an 'In' parameter)
                //
                //       It is allowed to spill ordinary `In` arguments by value if reference-preserving spilling is not possible.
                //       The "strict" ones do not permit implicit copying, so the same situation should result in an error.
                if (refKind != RefKind.None && refKind != RefKind.In)
                {
                    Debug.Assert(call.Method.RefKind != RefKind.None);
                    F.Diagnostics.Add(ErrorCode.ERR_RefReturningCallAndAwait, F.Syntax.Location, call.Method);
                }
                // method call is not referentially transparent, we can only spill the result value.
                refKind = RefKind.None;
                goto default;

            case BoundKind.ConditionalOperator:
                var conditional = (BoundConditionalOperator)expr;
                // NOTE: There are two kinds of 'In' arguments that we may see at this point:
                //       - `RefKindExtensions.StrictIn`     (originally specified with 'In' modifier)
                //       - `RefKind.In`                     (specified with no modifiers and matched an 'In' parameter)
                //
                //       It is allowed to spill ordinary `In` arguments by value if reference-preserving spilling is not possible.
                //       The "strict" ones do not permit implicit copying, so the same situation should result in an error.
                if (refKind != RefKind.None && refKind != RefKind.RefReadOnly)
                {
                    Debug.Assert(conditional.IsRef);
                    F.Diagnostics.Add(ErrorCode.ERR_RefConditionalAndAwait, F.Syntax.Location);
                }
                // conditional expr is not referentially transparent, we can only spill the result value.
                refKind = RefKind.None;
                goto default;

            default:
                if (expr.ConstantValue != null)
                {
                    return(expr);
                }

                if (refKind != RefKind.None)
                {
                    throw ExceptionUtilities.UnexpectedValue(expr.Kind);
                }

                TypeSymbol fieldType = expr.Type;
                StateMachineFieldSymbol hoistedField;
                if (F.Compilation.Options.OptimizationLevel == OptimizationLevel.Debug)
                {
                    const SynthesizedLocalKind kind = SynthesizedLocalKind.AwaitByRefSpill;

                    Debug.Assert(awaitSyntaxOpt != null);

                    int ordinal = _synthesizedLocalOrdinals.AssignLocalOrdinal(kind, syntaxOffset);
                    var id      = new LocalDebugId(syntaxOffset, ordinal);

                    // Editing await expression is not allowed. Thus all spilled fields will be present in the previous state machine.
                    // However, it may happen that the type changes, in which case we need to allocate a new slot.
                    int slotIndex;
                    if (slotAllocatorOpt == null ||
                        !slotAllocatorOpt.TryGetPreviousHoistedLocalSlotIndex(
                            awaitSyntaxOpt,
                            F.ModuleBuilderOpt.Translate(fieldType, awaitSyntaxOpt, Diagnostics),
                            kind,
                            id,
                            Diagnostics,
                            out slotIndex))
                    {
                        slotIndex = _nextFreeHoistedLocalSlot++;
                    }

                    string fieldName = GeneratedNames.MakeHoistedLocalFieldName(kind, slotIndex);
                    hoistedField = F.StateMachineField(expr.Type, fieldName, new LocalSlotDebugInfo(kind, id), slotIndex);
                }
                else
                {
                    hoistedField = GetOrAllocateReusableHoistedField(fieldType, reused: out _);
                }

                hoistedFields.Add(hoistedField);

                var replacement = F.Field(F.This(), hoistedField);
                sideEffects.Add(F.AssignmentExpression(replacement, expr));
                return(replacement);
            }
        }
コード例 #45
0
 public LocalSymbol SynthesizedLocal(TypeSymbol type, CSharpSyntaxNode syntax = null, bool isPinned = false, RefKind refKind = RefKind.None, SynthesizedLocalKind kind = SynthesizedLocalKind.LoweringTemp)
 {
     return new SynthesizedLocal(CurrentMethod, type, kind, syntax, isPinned, refKind);
 }
コード例 #46
0
ファイル: EEAssemblyBuilder.cs プロジェクト: rgani/roslyn
            public override LocalDefinition GetPreviousLocal(
                Cci.ITypeReference type,
                ILocalSymbolInternal symbol,
                string nameOpt,
                SynthesizedLocalKind synthesizedKind,
                LocalDebugId id,
                uint pdbAttributes,
                LocalSlotConstraints constraints,
                bool isDynamic,
                ImmutableArray<TypedConstant> dynamicTransformFlags)
            {
                var local = symbol as EELocalSymbol;
                if ((object)local == null)
                {
                    return null;
                }

                return _locals[local.Ordinal];
            }
コード例 #47
0
ファイル: Optimizer.cs プロジェクト: rosslyn-cuongle/roslyn
 internal override LocalSymbol WithSynthesizedLocalKindAndSyntax(SynthesizedLocalKind kind, SyntaxNode syntax)
 {
     throw new NotImplementedException();
 }
コード例 #48
0
ファイル: EEAssemblyBuilder.cs プロジェクト: rgani/roslyn
 public override bool TryGetPreviousHoistedLocalSlotIndex(SyntaxNode currentDeclarator, Cci.ITypeReference currentType, SynthesizedLocalKind synthesizedKind, LocalDebugId currentId, DiagnosticBag diagnostics, out int slotIndex)
 {
     slotIndex = -1;
     return false;
 }
コード例 #49
0
ファイル: GeneratedNames.cs プロジェクト: afrog33k/csnative
        internal static bool TryParseLocalName(string name, out SynthesizedLocalKind kind, out int uniqueId)
        {
            if (name.StartsWith(SynthesizedLocalNamePrefix, StringComparison.Ordinal))
            {
                name = name.Substring(SynthesizedLocalNamePrefix.Length);
                int separator = name.IndexOf('$');
                if (separator > 0)
                {
                    int k;
                    int n;
                    if (int.TryParse(name.Substring(0, separator), NumberStyles.None, CultureInfo.InvariantCulture, out k) &&
                        int.TryParse(name.Substring(separator + 1), NumberStyles.None, CultureInfo.InvariantCulture, out n))
                    {
                        kind = (SynthesizedLocalKind)k;
                        uniqueId = n;
                        return true;
                    }
                }
            }

            kind = SynthesizedLocalKind.None;
            uniqueId = 0;
            return false;
        }
コード例 #50
0
 public LocalName(string name)
 {
     this.UserDefinedName = name;
     this.Kind            = SynthesizedLocalKind.None;
     this.UniqueId        = 0;
 }