Пример #1
0
 internal abstract Cci.ITypeReference Translate(ITypeSymbolInternal symbol, SyntaxNode syntaxOpt, DiagnosticBag diagnostics);
Пример #2
0
 internal sealed override Cci.ITypeReference EncTranslateType(ITypeSymbolInternal type, DiagnosticBag diagnostics)
 {
     return(EncTranslateLocalVariableType((TTypeSymbol)type, diagnostics));
 }
Пример #3
0
 internal sealed override Cci.ITypeReference Translate(ITypeSymbolInternal symbol, SyntaxNode syntaxNodeOpt, DiagnosticBag diagnostics)
 {
     return(Translate((TTypeSymbol)symbol, (TSyntaxNode)syntaxNodeOpt, diagnostics));
 }
Пример #4
0
        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);
            }
        }
Пример #5
0
 internal abstract Cci.ITypeReference EncTranslateType(ITypeSymbolInternal type, DiagnosticBag diagnostics);
Пример #6
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.
            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()));
        }
Пример #7
0
        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));
        }
Пример #8
0
 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));
 }
Пример #10
0
        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;
        }
Пример #11
0
 internal TypedConstant(ITypeSymbolInternal type, ImmutableArray <TypedConstant> array)
     : this(type, TypedConstantKind.Array, value : array.IsDefault ? null : (object)array)
 {
 }
Пример #12
0
 internal override bool IsSystemTypeReference(ITypeSymbolInternal type)
 {
     return((TypeSymbol)type == GetWellKnownType(WellKnownType.System_Type));
 }