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 }
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 }
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; }
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); }
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); } } }
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()); }
// 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); }
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; }
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; }
// 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; }
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; }
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(); }
/// <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; }