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 }
private NamedTypeSymbol LookupTopLevelMetadataTypeInCache(ref MetadataTypeName emittedName) { NamedTypeSymbol result = null; if (_emittedNameToTypeMap.TryGetValue(emittedName.ToKey(), out result)) { return result; } return null; }
/// <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; }
/// <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; } }
/// <summary> /// Look up the given metadata type, if it is forwarded. /// </summary> internal virtual NamedTypeSymbol TryLookupForwardedMetadataTypeWithCycleDetection(ref MetadataTypeName emittedName, ConsList<AssemblySymbol> visitedAssemblies) { return null; }
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); }
/// <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);
/// <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); }
/// <summary> /// Lookup a type defined in this module. /// </summary> protected abstract TypeSymbol LookupTopLevelTypeDefSymbol(ref MetadataTypeName emittedName, out bool isNoPiaLocalType);
/// <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); }
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; }
/// <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);
protected abstract TypeSymbol LookupNestedTypeDefSymbol(TypeSymbol container, ref MetadataTypeName emittedName);
/// <summary> /// Lookup a type defined in referenced assembly. /// </summary> protected abstract TypeSymbol LookupTopLevelTypeDefSymbol(int referencedAssemblyIndex, ref MetadataTypeName emittedName);
/// <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; }
/// <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; } }
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; }
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); }