예제 #1
0
        internal SynthesizedLocal(
            MethodSymbol containingMethodOpt,
            TypeSymbol type,
            SynthesizedLocalKind kind,
            SyntaxNode syntaxOpt = null,
            bool isPinned        = false,
            RefKind refKind      = RefKind.None
#if DEBUG
            ,
            [CallerLineNumber] int createdAtLineNumber = 0,
            [CallerFilePath] string createdAtFilePath  = null
#endif
            )
        {
            Debug.Assert(type.SpecialType != SpecialType.System_Void);
            Debug.Assert(!kind.IsLongLived() || syntaxOpt != null);
            Debug.Assert(refKind != RefKind.Out);

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

#if DEBUG
            _createdAtLineNumber = createdAtLineNumber;
            _createdAtFilePath   = createdAtFilePath;
#endif
        }
예제 #2
0
        internal SynthesizedLocal(
            MethodSymbol containingMethodOpt,
            TypeWithAnnotations type,
            SynthesizedLocalKind kind,
            SyntaxNode syntaxOpt = null,
            bool isPinned        = false,
            RefKind refKind      = RefKind.None
#if DEBUG
            ,
            [CallerLineNumber] int createdAtLineNumber = 0,
            [CallerFilePath] string createdAtFilePath  = null
#endif
            )
        {
            Debug.Assert(!type.IsVoidType());
            Debug.Assert(!kind.IsLongLived() || syntaxOpt != null);
            Debug.Assert(refKind != RefKind.Out);
            Debug.Assert(containingMethodOpt is null || containingMethodOpt.DeclaringCompilation is not null);

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

#if DEBUG
            _createdAtLineNumber = createdAtLineNumber;
            _createdAtFilePath   = createdAtFilePath;
#endif
        }
예제 #3
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;
        }
예제 #4
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;
        }
예제 #5
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);
        }
예제 #6
0
        internal void SerializeLocalSlots(Cci.BinaryWriter writer)
        {
            int syntaxOffsetBaseline = -1;

            foreach (LocalSlotDebugInfo localSlot in this.LocalSlots)
            {
                if (localSlot.Id.SyntaxOffset < syntaxOffsetBaseline)
                {
                    syntaxOffsetBaseline = localSlot.Id.SyntaxOffset;
                }
            }

            if (syntaxOffsetBaseline != -1)
            {
                writer.WriteByte(SyntaxOffsetBaseline);
                writer.WriteCompressedUInt((uint)(-syntaxOffsetBaseline));
            }

            foreach (LocalSlotDebugInfo localSlot in this.LocalSlots)
            {
                SynthesizedLocalKind kind = localSlot.SynthesizedKind;
                Debug.Assert(kind <= SynthesizedLocalKind.MaxValidValueForLocalVariableSerializedToDebugInformation);

                if (!kind.IsLongLived())
                {
                    writer.WriteByte(0);
                    continue;
                }

                byte b = (byte)(kind + 1);
                Debug.Assert((b & (1 << 7)) == 0);

                bool hasOrdinal = localSlot.Id.Ordinal > 0;

                if (hasOrdinal)
                {
                    b |= 1 << 7;
                }

                writer.WriteByte(b);
                writer.WriteCompressedUInt((uint)(localSlot.Id.SyntaxOffset - syntaxOffsetBaseline));

                if (hasOrdinal)
                {
                    writer.WriteCompressedUInt((uint)localSlot.Id.Ordinal);
                }
            }
        }
예제 #7
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());
        }
예제 #8
0
        // 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));
        }
        /// <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);
        }
예제 #10
0
        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;
        }
예제 #11
0
        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);

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

            this.createdAtLineNumber = createdAtLineNumber;
            this.createdAtFilePath   = createdAtFilePath;
        }
예제 #12
0
        // 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);
        }
예제 #13
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;
        }
예제 #14
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;
        }
예제 #15
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();
        }
예제 #16
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;
        }