Пример #1
0
 private void CacheTopLevelMetadataType(
     ref MetadataTypeName emittedName,
     NamedTypeSymbol result)
 {
     NamedTypeSymbol result1 = null;
     result1 = _emittedNameToTypeMap.GetOrAdd(emittedName.ToKey(), result);
     Debug.Assert(result1 == result); // object identity may differ in error cases
 }
Пример #2
0
        private NamedTypeSymbol LookupTopLevelMetadataTypeInCache(ref MetadataTypeName emittedName)
        {
            NamedTypeSymbol result = null;
            if (_emittedNameToTypeMap.TryGetValue(emittedName.ToKey(), out result))
            {
                return result;
            }

            return null;
        }
Пример #3
0
        /// <summary>
        /// Lookup a top level type referenced from metadata, names should be
        /// compared case-sensitively.
        /// </summary>
        /// <param name="emittedName">
        /// Full type name, possibly with generic name mangling.
        /// </param>
        /// <returns>
        /// Symbol for the type, or MissingMetadataSymbol if the type isn't found.
        /// </returns>
        /// <remarks></remarks>
        internal sealed override NamedTypeSymbol LookupTopLevelMetadataType(ref MetadataTypeName emittedName)
        {
            NamedTypeSymbol result;
            NamespaceSymbol scope = this.GlobalNamespace; //.LookupNestedNamespace(emittedName.NamespaceSegments);

            if ((object)scope == null)
            {
                // We failed to locate the namespace
                throw new NotImplementedException();
                //result = new MissingMetadataTypeSymbol.TopLevel(this, ref emittedName);
            }
            else
            {
                result = scope.LookupMetadataType(ref emittedName);
            }

            Debug.Assert((object)result != null);
            return result;
        }
Пример #4
0
 /// <summary>
 /// If this module forwards the given type to another assembly, return that assembly;
 /// otherwise, return null.
 /// </summary>
 /// <param name="fullName">Type to look up.</param>
 /// <returns>Assembly symbol or null.</returns>
 /// <remarks>
 /// The returned assembly may also forward the type.
 /// </remarks>
 internal AssemblySymbol GetAssemblyForForwardedType(ref MetadataTypeName fullName)
 {
     try
     {
         string matchedName;
         AssemblyReferenceHandle assemblyRef = Module.GetAssemblyForForwardedType(fullName.FullName, ignoreCase: false, matchedName: out matchedName);
         return assemblyRef.IsNil ? null : this.ReferencedAssemblySymbols[Module.GetAssemblyReferenceIndexOrThrow(assemblyRef)];
     }
     catch (BadImageFormatException)
     {
         return null;
     }
 }
Пример #5
0
 /// <summary>
 /// Look up the given metadata type, if it is forwarded.
 /// </summary>
 internal virtual NamedTypeSymbol TryLookupForwardedMetadataTypeWithCycleDetection(ref MetadataTypeName emittedName, ConsList<AssemblySymbol> visitedAssemblies)
 {
     return null;
 }
Пример #6
0
 internal ErrorTypeSymbol CreateCycleInTypeForwarderErrorTypeSymbol(ref MetadataTypeName emittedName)
 {
     //DiagnosticInfo diagnosticInfo = new CSDiagnosticInfo(ErrorCode.ERR_CycleInTypeForwarder, emittedName.FullName, this.Name);
     //return new MissingMetadataTypeSymbol.TopLevelWithCustomErrorInfo(this.Modules[0], ref emittedName, diagnosticInfo);
     return new MissingMetadataTypeSymbol(emittedName.FullName, emittedName.ForcedArity, emittedName.IsMangled);
 }
Пример #7
0
 /// <summary>
 /// Lookup a top level type referenced from metadata, names should be
 /// compared case-sensitively.  Detect cycles during lookup.
 /// </summary>
 /// <param name="emittedName">
 /// Full type name, possibly with generic name mangling.
 /// </param>
 /// <param name="visitedAssemblies">
 /// List of assemblies lookup has already visited (since type forwarding can introduce cycles).
 /// </param>
 /// <param name="digThroughForwardedTypes">
 /// Take forwarded types into account.
 /// </param>
 internal abstract NamedTypeSymbol LookupTopLevelMetadataTypeWithCycleDetection(ref MetadataTypeName emittedName, ConsList<AssemblySymbol> visitedAssemblies, bool digThroughForwardedTypes);
Пример #8
0
 /// <summary>
 /// Lookup a top level type referenced from metadata, names should be
 /// compared case-sensitively.
 /// </summary>
 /// <param name="emittedName">
 /// Full type name with generic name mangling.
 /// </param>
 /// <param name="digThroughForwardedTypes">
 /// Take forwarded types into account.
 /// </param>
 /// <remarks></remarks>
 internal NamedTypeSymbol LookupTopLevelMetadataType(ref MetadataTypeName emittedName, bool digThroughForwardedTypes)
 {
     return LookupTopLevelMetadataTypeWithCycleDetection(ref emittedName, visitedAssemblies: null, digThroughForwardedTypes: digThroughForwardedTypes);
 }
Пример #9
0
 /// <summary>
 /// Lookup a type defined in this module.
 /// </summary>
 protected abstract TypeSymbol LookupTopLevelTypeDefSymbol(ref MetadataTypeName emittedName, out bool isNoPiaLocalType);
Пример #10
0
        /// <summary>
        /// Look up the assembly to which the given metadata type is forwarded.
        /// </summary>
        /// <param name="emittedName"></param>
        /// <returns>
        /// The assembly to which the given type is forwarded or null, if there isn't one.
        /// </returns>
        /// <remarks>
        /// The returned assembly may also forward the type.
        /// </remarks>
        internal AssemblySymbol LookupAssemblyForForwardedMetadataType(ref MetadataTypeName emittedName)
        {
            // Look in the type forwarders of the primary module of this assembly, clr does not honor type forwarder
            // in non-primary modules.

            // Examine the type forwarders, but only from the primary module.
            return this.PrimaryModule.GetAssemblyForForwardedType(ref emittedName);
        }
Пример #11
0
        internal override NamedTypeSymbol TryLookupForwardedMetadataTypeWithCycleDetection(ref MetadataTypeName emittedName, ConsList<AssemblySymbol> visitedAssemblies)
        {
            // Check if it is a forwarded type.
            var forwardedToAssembly = LookupAssemblyForForwardedMetadataType(ref emittedName);
            if ((object)forwardedToAssembly != null)
            {
                // Don't bother to check the forwarded-to assembly if we've already seen it.
                if (visitedAssemblies != null && visitedAssemblies.Contains(forwardedToAssembly))
                {
                    return CreateCycleInTypeForwarderErrorTypeSymbol(ref emittedName);
                }
                else
                {
                    visitedAssemblies = new ConsList<AssemblySymbol>(this, visitedAssemblies ?? ConsList<AssemblySymbol>.Empty);
                    return forwardedToAssembly.LookupTopLevelMetadataTypeWithCycleDetection(ref emittedName, visitedAssemblies, digThroughForwardedTypes: true);
                }
            }

            return null;
        }
Пример #12
0
 /// <summary>
 /// Lookup a top level type referenced from metadata, names should be
 /// compared case-sensitively.
 /// </summary>
 /// <param name="emittedName">
 /// Full type name, possibly with generic name mangling.
 /// </param>
 /// <returns>
 /// Symbol for the type, or MissingMetadataSymbol if the type isn't found.
 /// </returns>
 /// <remarks></remarks>
 internal abstract NamedTypeSymbol LookupTopLevelMetadataType(ref MetadataTypeName emittedName);
Пример #13
0
 protected abstract TypeSymbol LookupNestedTypeDefSymbol(TypeSymbol container, ref MetadataTypeName emittedName);
Пример #14
0
 /// <summary>
 /// Lookup a type defined in referenced assembly.
 /// </summary>
 protected abstract TypeSymbol LookupTopLevelTypeDefSymbol(int referencedAssemblyIndex, ref MetadataTypeName emittedName);
Пример #15
0
        /// <summary>
        /// Lookup an immediately nested type referenced from metadata, names should be
        /// compared case-sensitively.
        /// </summary>
        /// <param name="emittedTypeName">
        /// Simple type name, possibly with generic name mangling.
        /// </param>
        /// <returns>
        /// Symbol for the type, or MissingMetadataSymbol if the type isn't found.
        /// </returns>
        internal virtual NamedTypeSymbol LookupMetadataType(ref MetadataTypeName emittedTypeName)
        {
            Debug.Assert(!emittedTypeName.IsNull);

            NamespaceOrTypeSymbol scope = this;

            if (scope.Kind == SymbolKind.ErrorType)
            {
                throw new NotImplementedException();
                //return new MissingMetadataTypeSymbol.Nested((NamedTypeSymbol)scope, ref emittedTypeName);
            }

            NamedTypeSymbol namedType = null;

            ImmutableArray<NamedTypeSymbol> namespaceOrTypeMembers;
            bool isTopLevel = scope.IsNamespace;

            //Debug.Assert(!isTopLevel || scope.ToDisplayString(SymbolDisplayFormat.QualifiedNameOnlyFormat) == emittedTypeName.NamespaceName);

            if (emittedTypeName.IsMangled)
            {
                Debug.Assert(!emittedTypeName.UnmangledTypeName.Equals(emittedTypeName.TypeName) && emittedTypeName.InferredArity > 0);

                if (emittedTypeName.ForcedArity == -1 || emittedTypeName.ForcedArity == emittedTypeName.InferredArity)
                {
                    // Let's handle mangling case first.
                    //namespaceOrTypeMembers = scope.GetTypeMembers(emittedTypeName.UnmangledTypeName);
                    namespaceOrTypeMembers = scope.GetTypeMembers(emittedTypeName.FullName);

                    foreach (var named in namespaceOrTypeMembers)
                    {
                        if (emittedTypeName.InferredArity == named.Arity && named.MangleName)
                        {
                            if ((object)namedType != null)
                            {
                                namedType = null;
                                break;
                            }

                            namedType = named;
                        }
                    }
                }
            }
            else
            {
                Debug.Assert(ReferenceEquals(emittedTypeName.UnmangledTypeName, emittedTypeName.TypeName) && emittedTypeName.InferredArity == 0);
            }

            // Now try lookup without removing generic arity mangling.
            int forcedArity = emittedTypeName.ForcedArity;

            if (emittedTypeName.UseCLSCompliantNameArityEncoding)
            {
                // Only types with arity 0 are acceptable, we already examined types with mangled names.
                if (emittedTypeName.InferredArity > 0)
                {
                    goto Done;
                }
                else if (forcedArity == -1)
                {
                    forcedArity = 0;
                }
                else if (forcedArity != 0)
                {
                    goto Done;
                }
                else
                {
                    Debug.Assert(forcedArity == emittedTypeName.InferredArity);
                }
            }

            namespaceOrTypeMembers = scope.GetTypeMembers(emittedTypeName.FullName);

            foreach (var named in namespaceOrTypeMembers)
            {
                if (!named.MangleName && (forcedArity == -1 || forcedArity == named.Arity))
                {
                    if ((object)namedType != null)
                    {
                        namedType = null;
                        break;
                    }

                    namedType = named;
                }
            }

            Done:
            if ((object)namedType == null)
            {
                return new MissingMetadataTypeSymbol(emittedTypeName.FullName, emittedTypeName.ForcedArity, emittedTypeName.IsMangled);
                //if (isTopLevel)
                //{
                //    return new MissingMetadataTypeSymbol.TopLevel(scope.ContainingModule, ref emittedTypeName);
                //}
                //else
                //{
                //    return new MissingMetadataTypeSymbol.Nested((NamedTypeSymbol)scope, ref emittedTypeName);
                //}
            }

            return namedType;
        }
Пример #16
0
        /// <summary>
        /// Lookup a top level type referenced from metadata, names should be
        /// compared case-sensitively.  Detect cycles during lookup.
        /// </summary>
        /// <param name="emittedName">
        /// Full type name, possibly with generic name mangling.
        /// </param>
        /// <param name="visitedAssemblies">
        /// List of assemblies lookup has already visited (since type forwarding can introduce cycles).
        /// </param>
        /// <param name="digThroughForwardedTypes">
        /// Take forwarded types into account.
        /// </param>
        internal sealed override NamedTypeSymbol LookupTopLevelMetadataTypeWithCycleDetection(ref MetadataTypeName emittedName, ConsList<AssemblySymbol> visitedAssemblies, bool digThroughForwardedTypes)
        {
            NamedTypeSymbol result = null;

            // This is a cache similar to the one used by MetaImport::GetTypeByName in native
            // compiler. The difference is that native compiler pre-populates the cache when it
            // loads types. Here we are populating the cache only with things we looked for, so that
            // next time we are looking for the same thing, the lookup is fast. This cache also
            // takes care of TypeForwarders. Gives about 8% win on subsequent lookups in some
            // scenarios.     
            //    
            // CONSIDER !!!
            //
            // However, it is questionable how often subsequent lookup by name  is going to happen.
            // Currently it doesn't happen for TypeDef tokens at all, for TypeRef tokens, the
            // lookup by name is done once and the result is cached. So, multiple lookups by name
            // for the same type are going to happen only in these cases:
            // 1) Resolving GetType() in attribute application, type is encoded by name.
            // 2) TypeRef token isn't reused within the same module, i.e. multiple TypeRefs point to
            //    the same type.
            // 3) Different Module refers to the same type, lookup once per Module (with exception of #2).
            // 4) Multitargeting - retargeting the type to a different version of assembly
            result = LookupTopLevelMetadataTypeInCache(ref emittedName);

            if ((object)result != null)
            {
                // We only cache result equivalent to digging through type forwarders, which
                // might produce an forwarder specific ErrorTypeSymbol. We don't want to 
                // return that error symbol, unless digThroughForwardedTypes is true.
                if (digThroughForwardedTypes || (!result.IsErrorType() && (object)result.ContainingAssembly == (object)this))
                {
                    return result;
                }

                // According to the cache, the type wasn't found, or isn't declared in this assembly (forwarded).
                throw new NotImplementedException();
                //return new MissingMetadataTypeSymbol.TopLevel(this.Modules[0], ref emittedName);
            }
            else
            {
                // Now we will look for the type in each module of the assembly and pick the first type
                // we find, this is what native VB compiler does.

                var modules = this.Modules;
                var count = modules.Length;
                var i = 0;

                result = modules[i].LookupTopLevelMetadataType(ref emittedName);

                if (result is ErrorTypeSymbol)
                {
                    for (i = 1; i < count; i++)
                    {
                        var newResult = modules[i].LookupTopLevelMetadataType(ref emittedName);

                        // Hold on to the first missing type result, unless we found the type.
                        if (!(newResult is ErrorTypeSymbol))
                        {
                            result = newResult;
                            break;
                        }
                    }
                }

                bool foundMatchInThisAssembly = (i < count);

                Debug.Assert(!foundMatchInThisAssembly || (object)result.ContainingAssembly == (object)this);

                if (!foundMatchInThisAssembly && digThroughForwardedTypes)
                {
                    // We didn't find the type
                    Debug.Assert(result is ErrorTypeSymbol);

                    NamedTypeSymbol forwarded = TryLookupForwardedMetadataTypeWithCycleDetection(ref emittedName, visitedAssemblies);
                    if ((object)forwarded != null)
                    {
                        result = forwarded;
                    }
                }

                Debug.Assert((object)result != null);

                // Add result of the lookup into the cache
                if (digThroughForwardedTypes || foundMatchInThisAssembly)
                {
                    CacheTopLevelMetadataType(ref emittedName, result);
                }

                return result;
            }
        }
Пример #17
0
        internal override NamedTypeSymbol TryLookupForwardedMetadataTypeWithCycleDetection(ref MetadataTypeName emittedName, ConsList<AssemblySymbol> visitedAssemblies)
        {
            int forcedArity = emittedName.ForcedArity;

            if (emittedName.UseCLSCompliantNameArityEncoding)
            {
                if (forcedArity == -1)
                {
                    forcedArity = emittedName.InferredArity;
                }
                else if (forcedArity != emittedName.InferredArity)
                {
                    return null;
                }

                Debug.Assert(forcedArity == emittedName.InferredArity);
            }

            //if (_lazyForwardedTypesFromSource == null)
            //{
            //    IDictionary<string, NamedTypeSymbol> forwardedTypesFromSource;
            //    CommonAssemblyWellKnownAttributeData<NamedTypeSymbol> wellKnownAttributeData = GetSourceDecodedWellKnownAttributeData();

            //    if (wellKnownAttributeData != null && wellKnownAttributeData.ForwardedTypes != null)
            //    {
            //        forwardedTypesFromSource = new Dictionary<string, NamedTypeSymbol>();

            //        foreach (NamedTypeSymbol forwardedType in wellKnownAttributeData.ForwardedTypes)
            //        {
            //            NamedTypeSymbol originalDefinition = forwardedType.OriginalDefinition;
            //            Debug.Assert((object)originalDefinition.ContainingType == null, "How did a nested type get forwarded?");

            //            string fullEmittedName = MetadataHelpers.BuildQualifiedName(originalDefinition.ContainingSymbol.ToDisplayString(SymbolDisplayFormat.QualifiedNameOnlyFormat),
            //                                                                        originalDefinition.MetadataName);
            //            // Since we need to allow multiple constructions of the same generic type at the source
            //            // level, we need to de-dup the original definitions.
            //            forwardedTypesFromSource[fullEmittedName] = originalDefinition;
            //        }
            //    }
            //    else
            //    {
            //        forwardedTypesFromSource = SpecializedCollections.EmptyDictionary<string, NamedTypeSymbol>();
            //    }

            //    _lazyForwardedTypesFromSource = forwardedTypesFromSource;
            //}

            //NamedTypeSymbol result;

            //if (_lazyForwardedTypesFromSource.TryGetValue(emittedName.FullName, out result))
            //{
            //    if ((forcedArity == -1 || result.Arity == forcedArity) &&
            //        (!emittedName.UseCLSCompliantNameArityEncoding || result.Arity == 0 || result.MangleName))
            //    {
            //        return result;
            //    }
            //}
            //else if (!_compilation.Options.OutputKind.IsNetModule())
            //{
            //    // See if any of added modules forward the type.

            //    // Similar to attributes, type forwarders from the second added module should override type forwarders from the first added module, etc. 
            //    for (int i = _modules.Length - 1; i > 0; i--)
            //    {
            //        var peModuleSymbol = (Metadata.PE.PEModuleSymbol)_modules[i];

            //        var forwardedToAssembly = peModuleSymbol.GetAssemblyForForwardedType(ref emittedName);
            //        if ((object)forwardedToAssembly != null)
            //        {
            //            // Don't bother to check the forwarded-to assembly if we've already seen it.
            //            if (visitedAssemblies != null && visitedAssemblies.Contains(forwardedToAssembly))
            //            {
            //                return CreateCycleInTypeForwarderErrorTypeSymbol(ref emittedName);
            //            }
            //            else
            //            {
            //                visitedAssemblies = new ConsList<AssemblySymbol>(this, visitedAssemblies ?? ConsList<AssemblySymbol>.Empty);
            //                return forwardedToAssembly.LookupTopLevelMetadataTypeWithCycleDetection(ref emittedName, visitedAssemblies, digThroughForwardedTypes: true);
            //            }
            //        }
            //    }
            //}

            return null;
        }
Пример #18
0
        internal TypeSymbol GetTypeSymbol(MetadataHelpers.AssemblyQualifiedTypeName fullName, out bool refersToNoPiaLocalType)
        {
            //
            // Section 23.3 (Custom Attributes) of CLI Spec Partition II:
            //
            // If the parameter kind is System.Type, (also, the middle line in above diagram) its value is
            // stored as a SerString (as defined in the previous paragraph), representing its canonical name.
            // The canonical name is its full type name, followed optionally by the assembly where it is defined,
            // its version, culture and public-key-token. If the assembly name is omitted, the CLI looks first
            // in the current assembly, and then in the system library (mscorlib); in these two special cases,
            // it is permitted to omit the assembly-name, version, culture and public-key-token.

            int referencedAssemblyIndex;

            if (fullName.AssemblyName != null)
            {
                AssemblyIdentity identity;
                if (!AssemblyIdentity.TryParseDisplayName(fullName.AssemblyName, out identity))
                {
                    refersToNoPiaLocalType = false;
                    return(GetUnsupportedMetadataTypeSymbol());
                }

                // the assembly name has to be a full name:
                referencedAssemblyIndex = GetIndexOfReferencedAssembly(identity);
                if (referencedAssemblyIndex == -1)
                {
                    // In rare cases (e.g. assemblies emitted by Reflection.Emit) the identity
                    // might be the identity of the containing assembly. The metadata spec doesn't disallow this.
                    if (!this.IsContainingAssembly(identity))
                    {
                        refersToNoPiaLocalType = false;
                        return(GetUnsupportedMetadataTypeSymbol());
                    }
                }
            }
            else
            {
                // Use this assembly
                referencedAssemblyIndex = -1;
            }

            // Find the top level type
            Debug.Assert(MetadataHelpers.IsValidMetadataIdentifier(fullName.TopLevelType));
            var        mdName    = MetadataTypeName.FromFullName(fullName.TopLevelType);
            TypeSymbol container = LookupTopLevelTypeDefSymbol(ref mdName, referencedAssemblyIndex, out refersToNoPiaLocalType);

            // Process any nested types
            if (fullName.NestedTypes != null)
            {
                if (refersToNoPiaLocalType)
                {
                    // Types nested into local types are not supported.
                    refersToNoPiaLocalType = false;
                    return(GetUnsupportedMetadataTypeSymbol());
                }

                for (int i = 0; i < fullName.NestedTypes.Length; i++)
                {
                    Debug.Assert(MetadataHelpers.IsValidMetadataIdentifier(fullName.NestedTypes[i]));
                    mdName = MetadataTypeName.FromTypeName(fullName.NestedTypes[i]);
                    // Find nested type in the container
                    container = LookupNestedTypeDefSymbol(container, ref mdName);
                }
            }

            //  Substitute type arguments if any
            if (fullName.TypeArguments != null)
            {
                ImmutableArray <bool> argumentRefersToNoPiaLocalType;
                var typeArguments = ResolveTypeArguments(fullName.TypeArguments, out argumentRefersToNoPiaLocalType);
                container = SubstituteTypeParameters(container, typeArguments, argumentRefersToNoPiaLocalType);

                foreach (bool flag in argumentRefersToNoPiaLocalType)
                {
                    if (flag)
                    {
                        refersToNoPiaLocalType = true;
                        break;
                    }
                }
            }
            else
            {
                container = SubstituteWithUnboundIfGeneric(container);
            }

            for (int i = 0; i < fullName.PointerCount; i++)
            {
                container = MakePointerTypeSymbol(container, ImmutableArray <ModifierInfo <TypeSymbol> > .Empty);
            }

            // Process any array type ranks
            if (fullName.ArrayRanks != null)
            {
                foreach (int rank in fullName.ArrayRanks)
                {
                    Debug.Assert(rank >= 0);
                    container = rank == 0 ?
                                GetSZArrayTypeSymbol(container, default(ImmutableArray <ModifierInfo <TypeSymbol> >)) :
                                GetMDArrayTypeSymbol(rank, container, default(ImmutableArray <ModifierInfo <TypeSymbol> >), ImmutableArray <int> .Empty, default(ImmutableArray <int>));
                }
            }

            return(container);
        }