internal abstract Cci.ITypeReference Translate(ITypeSymbolInternal symbol, SyntaxNode syntaxOpt, DiagnosticBag diagnostics);
internal sealed override Cci.ITypeReference EncTranslateType(ITypeSymbolInternal type, DiagnosticBag diagnostics) { return(EncTranslateLocalVariableType((TTypeSymbol)type, diagnostics)); }
internal sealed override Cci.ITypeReference Translate(ITypeSymbolInternal symbol, SyntaxNode syntaxNodeOpt, DiagnosticBag diagnostics) { return(Translate((TTypeSymbol)symbol, (TSyntaxNode)syntaxNodeOpt, diagnostics)); }
private static void DecodeMarshalAsSafeArray(ref DecodeWellKnownAttributeArguments <TAttributeSyntax, TAttributeData, TAttributeLocation> arguments, CommonMessageProvider messageProvider) { Debug.Assert((object)arguments.AttributeSyntaxOpt != null); Cci.VarEnum? elementTypeVariant = null; ITypeSymbolInternal elementTypeSymbol = null; int symbolIndex = -1; bool hasErrors = false; int position = 1; foreach (var namedArg in arguments.Attribute.NamedArguments) { switch (namedArg.Key) { case "SafeArraySubType": elementTypeVariant = namedArg.Value.DecodeValue <Cci.VarEnum>(SpecialType.System_Enum); if (elementTypeVariant < 0 || (int)elementTypeVariant > MarshalPseudoCustomAttributeData.MaxMarshalInteger) { messageProvider.ReportInvalidNamedArgument(arguments.Diagnostics, arguments.AttributeSyntaxOpt, position, arguments.Attribute.AttributeClass, namedArg.Key); hasErrors = true; } break; case "SafeArrayUserDefinedSubType": elementTypeSymbol = namedArg.Value.DecodeValue <ITypeSymbolInternal>(SpecialType.None); symbolIndex = position; break; case "ArraySubType": case "SizeConst": case "SizeParamIndex": messageProvider.ReportParameterNotValidForType(arguments.Diagnostics, arguments.AttributeSyntaxOpt, position); hasErrors = true; break; // other parameters ignored with no error } position++; } switch (elementTypeVariant) { case Cci.VarEnum.VT_DISPATCH: case Cci.VarEnum.VT_UNKNOWN: case Cci.VarEnum.VT_RECORD: // only these variants accept specification of user defined subtype break; default: if (elementTypeVariant != null && symbolIndex >= 0) { messageProvider.ReportParameterNotValidForType(arguments.Diagnostics, arguments.AttributeSyntaxOpt, symbolIndex); hasErrors = true; } else { // type ignored: elementTypeSymbol = null; } break; } if (!hasErrors) { arguments.GetOrCreateData <TWellKnownAttributeData>().GetOrCreateData().SetMarshalAsSafeArray(elementTypeVariant, elementTypeSymbol); } }
internal abstract Cci.ITypeReference EncTranslateType(ITypeSymbolInternal type, DiagnosticBag diagnostics);
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. MappedMethod mappedMethod; if (!mappedMethods.TryGetValue(topLevelMethod, out mappedMethod)) { return(null); } // TODO (bug https://github.com/dotnet/roslyn/issues/2504): // Handle cases when the previous method doesn't exist. MethodDefinitionHandle previousHandle; if (!TryGetMethodHandle(baseline, (Cci.IMethodDefinition)method.GetCciAdapter(), out 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; int hoistedLocalSlotCount = 0; int awaiterSlotCount = 0; string stateMachineTypeNameOpt = null; SymbolMatcher symbolMap; int methodIndex = MetadataTokens.GetRowNumber(previousHandle); DebugId methodId; // Check if method has changed previously. If so, we already have a map. AddedOrChangedMethodInfo addedOrChangedMethod; if (baseline.AddedOrChangedMethods.TryGetValue(methodIndex, out addedOrChangedMethod)) { methodId = addedOrChangedMethod.MethodId; MakeLambdaAndClosureMaps(addedOrChangedMethod.LambdaDebugInfo, addedOrChangedMethod.ClosureDebugInfo, out lambdaMap, out closureMap); if (addedOrChangedMethod.StateMachineTypeNameOpt != 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; stateMachineTypeNameOpt = addedOrChangedMethod.StateMachineTypeNameOpt; } 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); } 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; stateMachineTypeNameOpt = 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, stateMachineTypeNameOpt, hoistedLocalSlotCount, hoistedLocalMap, awaiterSlotCount, awaiterMap, GetLambdaSyntaxFacts())); }
private static MetadataConstant CreateMetadataConstant(ITypeSymbolInternal type, object value, EmitContext context) { PEModuleBuilder moduleBeingBuilt = (PEModuleBuilder)context.Module; return(moduleBeingBuilt.CreateConstant((TypeSymbol)type, value, syntaxNodeOpt: (CSharpSyntaxNode)context.SyntaxNode, diagnostics: context.Diagnostics)); }
protected abstract void GetStateMachineFieldMapFromMetadata( ITypeSymbolInternal stateMachineType, ImmutableArray <LocalSlotDebugInfo> localSlotDebugInfo, out IReadOnlyDictionary <EncHoistedLocalInfo, int> hoistedLocalMap, out IReadOnlyDictionary <Cci.ITypeReference, int> awaiterMap, out int awaiterSlotCount);
internal override bool IsSystemTypeReference(ITypeSymbolInternal type) { return(TypeSymbol.Equals((TypeSymbol)type, GetWellKnownType(WellKnownType.System_Type), TypeCompareKind.ConsiderEverything2)); }
protected override void GetStateMachineFieldMapFromMetadata( ITypeSymbolInternal stateMachineType, ImmutableArray <LocalSlotDebugInfo> localSlotDebugInfo, out IReadOnlyDictionary <EncHoistedLocalInfo, int> hoistedLocalMap, out IReadOnlyDictionary <Cci.ITypeReference, int> awaiterMap, out int awaiterSlotCount) { // we are working with PE symbols Debug.Assert(stateMachineType.ContainingAssembly is PEAssemblySymbol); var hoistedLocals = new Dictionary <EncHoistedLocalInfo, int>(); var awaiters = new Dictionary <Cci.ITypeReference, int>(); int maxAwaiterSlotIndex = -1; foreach (var member in ((TypeSymbol)stateMachineType).GetMembers()) { if (member.Kind == SymbolKind.Field) { string name = member.Name; int slotIndex; switch (GeneratedNames.GetKind(name)) { case GeneratedNameKind.AwaiterField: if (GeneratedNames.TryParseSlotIndex(name, out slotIndex)) { var field = (FieldSymbol)member; // correct metadata won't contain duplicates, but malformed might, ignore the duplicate: awaiters[(Cci.ITypeReference)field.Type] = slotIndex; if (slotIndex > maxAwaiterSlotIndex) { maxAwaiterSlotIndex = slotIndex; } } break; case GeneratedNameKind.HoistedLocalField: case GeneratedNameKind.HoistedSynthesizedLocalField: if (GeneratedNames.TryParseSlotIndex(name, out slotIndex)) { var field = (FieldSymbol)member; if (slotIndex >= localSlotDebugInfo.Length) { // invalid or missing metadata continue; } var key = new EncHoistedLocalInfo(localSlotDebugInfo[slotIndex], (Cci.ITypeReference)field.Type); // correct metadata won't contain duplicate ids, but malformed might, ignore the duplicate: hoistedLocals[key] = slotIndex; } break; } } } hoistedLocalMap = hoistedLocals; awaiterMap = awaiters; awaiterSlotCount = maxAwaiterSlotIndex + 1; }
internal TypedConstant(ITypeSymbolInternal type, ImmutableArray <TypedConstant> array) : this(type, TypedConstantKind.Array, value : array.IsDefault ? null : (object)array) { }
internal override bool IsSystemTypeReference(ITypeSymbolInternal type) { return((TypeSymbol)type == GetWellKnownType(WellKnownType.System_Type)); }