public static void AddDependenciesDueToCustomAttributes(ref DependencyList dependencies, NodeFactory factory, EcmaType type) { TypeDefinition typeDef = type.MetadataReader.GetTypeDefinition(type.Handle); AddDependenciesDueToCustomAttributes(ref dependencies, factory, type.EcmaModule, typeDef.GetCustomAttributes()); }
private void EmitTypeToken(EcmaType type, SignatureContext context) { ModuleToken token = context.GetModuleTokenForType(type); EmitToken(token.Token); }
public MethodDesc ResolveMethodID(long handle, bool throwIfNotFound = true) { lock (_lock) { MethodDescInfo minfo; if (_methods.TryGetValue(handle, out minfo)) { if (minfo.Method != null) { return(minfo.Method); } TypeDesc owningType = ResolveTypeHandle(minfo.MethodDetailsTraceData.TypeID, throwIfNotFound); if (owningType == null) { return(null); } MetadataType owningMDType = owningType as MetadataType; if (owningMDType == null) { throw new Exception("Method not parented by MetadataType"); } if ((minfo.MethodDetailsTraceData.MethodToken & 0xFF000000) != 0x06000000) { throw new Exception($"Invalid methoddef {minfo.MethodDetailsTraceData.MethodToken:4x}"); } MethodDefinitionHandle methoddef = MetadataTokens.MethodDefinitionHandle(minfo.MethodDetailsTraceData.MethodToken & 0xFFFFFF); MethodDesc uninstantiatedMethod = null; foreach (MethodDesc m in owningMDType.GetMethods()) { EcmaMethod ecmaMeth = m.GetTypicalMethodDefinition() as EcmaMethod; if (ecmaMeth == null) { continue; } if (ecmaMeth.Handle == methoddef) { uninstantiatedMethod = m; break; } } if (uninstantiatedMethod == null) { if (throwIfNotFound) { EcmaType ecmaType = owningMDType.GetTypeDefinition() as EcmaType; throw new Exception($"Unknown MethodID value finding MethodDef {minfo.MethodDetailsTraceData.MethodToken:x} on type {owningMDType} from module {ecmaType.Module.Assembly.GetName().Name}"); } return(null); } // Instantiate the type if requested if (minfo.MethodDetailsTraceData.TypeParameters.Length != 0) { if (uninstantiatedMethod.Instantiation.Length != minfo.MethodDetailsTraceData.TypeParameters.Length) { throw new Exception($"Invalid TypeParameterCount {minfo.MethodDetailsTraceData.TypeParameters.Length} expected {uninstantiatedMethod.Instantiation.Length} as needed by '{uninstantiatedMethod}'"); } TypeDesc[] instantiation = new TypeDesc[minfo.MethodDetailsTraceData.TypeParameters.Length]; for (int i = 0; i < instantiation.Length; i++) { instantiation[i] = ResolveTypeHandle((long)minfo.MethodDetailsTraceData.TypeParameters[i], throwIfNotFound); if (instantiation[i] == null) { return(null); } } minfo.Method = _context.GetInstantiatedMethod(uninstantiatedMethod, new Instantiation(instantiation)); if (minfo.Method == null) { if (throwIfNotFound) { StringBuilder s = new StringBuilder(); foreach (TypeDesc type in instantiation) { if (s.Length != 0) { s.Append(','); } s.Append(type); } throw new Exception("Unable to instantiate {uninstantiatedMethod} over <{s}>"); } return(null); } } else { minfo.Method = uninstantiatedMethod; } if (minfo.Method == null) { if (throwIfNotFound) { throw new Exception("Unknown MethodID value"); } return(null); } return(minfo.Method); } else { if (throwIfNotFound) { throw new Exception("Unknown MethodID value"); } return(null); } } }
public static void AddDependenciesDueToCustomAttributes(ref DependencyList dependencies, NodeFactory factory, EcmaType type) { MetadataReader reader = type.MetadataReader; TypeDefinition typeDef = reader.GetTypeDefinition(type.Handle); AddDependenciesDueToCustomAttributes(ref dependencies, factory, type.EcmaModule, typeDef.GetCustomAttributes()); // Handle custom attributes on generic type parameters foreach (GenericParameterHandle genericParameterHandle in typeDef.GetGenericParameters()) { GenericParameter parameter = reader.GetGenericParameter(genericParameterHandle); AddDependenciesDueToCustomAttributes(ref dependencies, factory, type.EcmaModule, parameter.GetCustomAttributes()); } }
/// <summary> /// If given <param name="type"/> is an <see cref="EcmaType"/> precompute its mangled type name /// along with all the other types from the same module as <param name="type"/>. /// Otherwise, it is a constructed type and to the EcmaType's mangled name we add a suffix to /// show what kind of constructed type it is (e.g. appending __Array for an array type). /// </summary> /// <param name="type">Type to mangled</param> /// <returns>Mangled name for <param name="type"/>.</returns> private string ComputeMangledTypeName(TypeDesc type) { if (type is EcmaType) { EcmaType ecmaType = (EcmaType)type; string assemblyName = ((EcmaAssembly)ecmaType.EcmaModule).GetName().Name; bool isSystemPrivate = assemblyName.StartsWith("System.Private."); // Abbreviate System.Private to S.P. This might conflict with user defined assembly names, // but we already have a problem due to running SanitizeName without disambiguating the result // This problem needs a better fix. if (isSystemPrivate && !_mangleForCplusPlus) { assemblyName = "S.P." + assemblyName.Substring(15); } string prependAssemblyName = SanitizeName(assemblyName); var deduplicator = new HashSet <string>(); // Add consistent names for all types in the module, independent on the order in which // they are compiled lock (this) { bool isSystemModule = ecmaType.Module == ecmaType.Context.SystemModule; if (!_mangledTypeNames.ContainsKey(type)) { foreach (MetadataType t in ecmaType.EcmaModule.GetAllTypes()) { string name = t.GetFullName(); // Include encapsulating type DefType containingType = t.ContainingType; while (containingType != null) { name = containingType.GetFullName() + "_" + name; containingType = containingType.ContainingType; } name = SanitizeName(name, true); if (_mangleForCplusPlus) { // Always generate a fully qualified name name = "::" + prependAssemblyName + "::" + name; } else { name = prependAssemblyName + "_" + name; // If this is one of the well known types, use a shorter name // We know this won't conflict because all the other types are // prefixed by the assembly name. if (isSystemModule) { switch (t.Category) { case TypeFlags.Boolean: name = "Bool"; break; case TypeFlags.Byte: name = "UInt8"; break; case TypeFlags.SByte: name = "Int8"; break; case TypeFlags.UInt16: name = "UInt16"; break; case TypeFlags.Int16: name = "Int16"; break; case TypeFlags.UInt32: name = "UInt32"; break; case TypeFlags.Int32: name = "Int32"; break; case TypeFlags.UInt64: name = "UInt64"; break; case TypeFlags.Int64: name = "Int64"; break; case TypeFlags.Char: name = "Char"; break; case TypeFlags.Double: name = "Double"; break; case TypeFlags.Single: name = "Single"; break; case TypeFlags.IntPtr: name = "IntPtr"; break; case TypeFlags.UIntPtr: name = "UIntPtr"; break; default: if (t.IsObject) { name = "Object"; } else if (t.IsString) { name = "String"; } break; } } } // Ensure that name is unique and update our tables accordingly. name = DisambiguateName(name, deduplicator); deduplicator.Add(name); _mangledTypeNames.Add(t, name); } } return(_mangledTypeNames[type]); } } string mangledName; switch (type.Category) { case TypeFlags.Array: mangledName = "__MDArray" + EnterNameScopeSequence + GetMangledTypeName(((ArrayType)type).ElementType) + DelimitNameScopeSequence + ((ArrayType)type).Rank.ToStringInvariant() + ExitNameScopeSequence; break; case TypeFlags.SzArray: mangledName = "__Array" + NestMangledName(GetMangledTypeName(((ArrayType)type).ElementType)); break; case TypeFlags.ByRef: mangledName = GetMangledTypeName(((ByRefType)type).ParameterType) + NestMangledName("ByRef"); break; case TypeFlags.Pointer: mangledName = GetMangledTypeName(((PointerType)type).ParameterType) + NestMangledName("Pointer"); break; default: // Case of a generic type. If `type' is a type definition we use the type name // for mangling, otherwise we use the mangling of the type and its generic type // parameters, e.g. A <B> becomes A_<___B_>_ in RyuJIT compilation, or A_A___B_V_ // in C++ compilation. var typeDefinition = type.GetTypeDefinition(); if (typeDefinition != type) { mangledName = GetMangledTypeName(typeDefinition); var inst = type.Instantiation; string mangledInstantiation = ""; for (int i = 0; i < inst.Length; i++) { string instArgName = GetMangledTypeName(inst[i]); if (_mangleForCplusPlus) { instArgName = instArgName.Replace("::", "_"); } if (i > 0) { mangledInstantiation += "__"; } mangledInstantiation += instArgName; } mangledName += NestMangledName(mangledInstantiation); } else if (type is IPrefixMangledMethod) { mangledName = GetPrefixMangledMethodName((IPrefixMangledMethod)type).ToString(); } else if (type is IPrefixMangledType) { mangledName = GetPrefixMangledTypeName((IPrefixMangledType)type).ToString(); } else { // This is a type definition. Since we didn't fall in the `is EcmaType` case above, // it's likely a compiler-generated type. mangledName = SanitizeName(((DefType)type).GetFullName(), true); // Always generate a fully qualified name if (_mangleForCplusPlus) { mangledName = "::" + mangledName; } } break; } lock (this) { // Ensure that name is unique and update our tables accordingly. if (!_mangledTypeNames.ContainsKey(type)) { _mangledTypeNames.Add(type, mangledName); } } return(mangledName); }
/// <summary> /// If given <param name="type"/> is an <see cref="EcmaType"/> precompute its mangled type name /// along with all the other types from the same module as <param name="type"/>. /// Otherwise, it is a constructed type and to the EcmaType's mangled name we add a suffix to /// show what kind of constructed type it is (e.g. appending __Array for an array type). /// </summary> /// <param name="type">Type to mangled</param> /// <returns>Mangled name for <param name="type"/>.</returns> private string ComputeMangledTypeName(TypeDesc type) { if (type is EcmaType) { EcmaType ecmaType = (EcmaType)type; string prependAssemblyName = SanitizeName(((EcmaAssembly)ecmaType.EcmaModule).GetName().Name); var deduplicator = new HashSet <string>(); // Add consistent names for all types in the module, independent on the order in which // they are compiled lock (this) { if (!_mangledTypeNames.ContainsKey(type)) { foreach (MetadataType t in ((EcmaType)type).EcmaModule.GetAllTypes()) { string name = t.GetFullName(); // Include encapsulating type DefType containingType = t.ContainingType; while (containingType != null) { name = containingType.GetFullName() + "_" + name; containingType = containingType.ContainingType; } name = SanitizeName(name, true); if (_mangleForCplusPlus) { // Always generate a fully qualified name name = "::" + prependAssemblyName + "::" + name; } else { name = prependAssemblyName + "_" + name; } // Ensure that name is unique and update our tables accordingly. name = DisambiguateName(name, deduplicator); deduplicator.Add(name); _mangledTypeNames = _mangledTypeNames.Add(t, name); } } } return(_mangledTypeNames[type]); } string mangledName; switch (type.Category) { case TypeFlags.Array: case TypeFlags.SzArray: mangledName = GetMangledTypeName(((ArrayType)type).ElementType) + "__"; if (type.IsMdArray) { mangledName += NestMangledName("ArrayRank" + ((ArrayType)type).Rank.ToStringInvariant()); } else { mangledName += NestMangledName("Array"); } break; case TypeFlags.ByRef: mangledName = GetMangledTypeName(((ByRefType)type).ParameterType) + NestMangledName("ByRef"); break; case TypeFlags.Pointer: mangledName = GetMangledTypeName(((PointerType)type).ParameterType) + NestMangledName("Pointer"); break; default: // Case of a generic type. If `type' is a type definition we use the type name // for mangling, otherwise we use the mangling of the type and its generic type // parameters, e.g. A <B> becomes A_<___B_>_ in RyuJIT compilation, or A_A___B_V_ // in C++ compilation. var typeDefinition = type.GetTypeDefinition(); if (typeDefinition != type) { mangledName = GetMangledTypeName(typeDefinition); var inst = type.Instantiation; string mangledInstantiation = ""; for (int i = 0; i < inst.Length; i++) { string instArgName = GetMangledTypeName(inst[i]); if (_mangleForCplusPlus) { instArgName = instArgName.Replace("::", "_"); } if (i > 0) { mangledInstantiation += "__"; } mangledInstantiation += instArgName; } mangledName += NestMangledName(mangledInstantiation); } else { mangledName = SanitizeName(((DefType)type).GetFullName(), true); } break; } lock (this) { // Ensure that name is unique and update our tables accordingly. if (!_mangledTypeNames.ContainsKey(type)) { _mangledTypeNames = _mangledTypeNames.Add(type, mangledName); } } return(mangledName); }
// LookupIbcTypeToken and (possibly) find the module associated with it. // externalModule may be null if the exact assembly isn't known private uint LookupIbcTypeToken(ref EcmaModule externalModule, uint ibcToken, Dictionary <IBCBlobKey, BlobEntry> blobs) { if (!blobs.TryGetValue(new IBCBlobKey(ibcToken, BlobType.ExternalTypeDef), out BlobEntry externalTypeDefBlob)) { if (_logger.IsVerbose) { _logger.Writer.WriteLine($"Ibc TypeToken {ibcToken:x} unable to find external typedef"); } return(Cor.Macros.RidToToken(0, CorTokenType.mdtTypeDef)); // Nil TypeDef token } var typeEntry = (BlobEntry.ExternalTypeEntry)externalTypeDefBlob; string typeNamespace = ""; string typeName = Encoding.UTF8.GetString(typeEntry.Name, 0, typeEntry.Name.Length - 1 /* these strings are null terminated */); TypeDefinitionHandle enclosingType = default; if (!Cor.Macros.IsNilToken(typeEntry.NamespaceToken)) { if (!Cor.Macros.IsNilToken(typeEntry.NestedClassToken)) { // Do not support typedef with namespace that is nested throw new Exception($"Ibc TypeToken {ibcToken:x} has both Namespace and NestedClass tokens"); } uint nameSpaceToken = typeEntry.NamespaceToken; if (Cor.Macros.TypeFromToken(nameSpaceToken) != CorTokenType.ibcExternalNamespace) { throw new Exception($"Ibc TypeToken {ibcToken:x} has Namespace tokens that is not a ibcExternalNamespace"); } if (!blobs.TryGetValue(new IBCBlobKey(nameSpaceToken, BlobType.ExternalNamespaceDef), out BlobEntry namespaceEntryBlob)) { if (_logger.IsVerbose) { _logger.Writer.WriteLine($"Ibc TypeToken {ibcToken:x} unable to find external namespace blob '{nameSpaceToken:x}"); } return(Cor.Macros.RidToToken(0, CorTokenType.mdtTypeDef)); // Nil TypeDef token } var namespaceEntry = (BlobEntry.ExternalNamespaceEntry)namespaceEntryBlob; typeNamespace = Encoding.UTF8.GetString(namespaceEntry.Name, 0, namespaceEntry.Name.Length - 1 /* these strings are null terminated */); } else if (!Cor.Macros.IsNilToken(typeEntry.NestedClassToken)) { uint enclosingTypeTokenValue = LookupIbcTypeToken(ref externalModule, typeEntry.NestedClassToken, blobs); if (Cor.Macros.TypeFromToken(enclosingTypeTokenValue) != CorTokenType.mdtTypeDef) { throw new Exception($"Ibc TypeToken {ibcToken:x} has NestedClass token which does not resolve to a type definition"); } enclosingType = MetadataTokens.TypeDefinitionHandle((int)Cor.Macros.RidFromToken(enclosingTypeTokenValue)); if (enclosingType.IsNil && _logger.IsVerbose) { _logger.Writer.WriteLine($"Ibc TypeToken {ibcToken:x} has NestedClass token which resolves to a nil token"); } } if (enclosingType.IsNil) { EcmaType foundType = null; if (externalModule == null) { // Lookup actual module scenario. foreach (ModuleDesc m in _possibleReferenceModules) { if (!(m is EcmaModule)) { continue; } foundType = (EcmaType)m.GetType(typeNamespace, typeName, throwIfNotFound: false); if (foundType != null) { externalModule = foundType.EcmaModule; break; } } } else { foundType = (EcmaType)externalModule.GetType(typeNamespace, typeName, throwIfNotFound: false); } if (foundType == null) { if (_logger.IsVerbose) { _logger.Writer.WriteLine($"Ibc TypeToken {ibcToken:x} has type token which resolves to a nil token"); } return(Cor.Macros.RidToToken(0, CorTokenType.mdtTypeDef)); // Nil TypeDef token } return((uint)externalModule.MetadataReader.GetToken(foundType.Handle)); } else { TypeDefinition nestedClassDefinition = externalModule.MetadataReader.GetTypeDefinition(enclosingType); MetadataStringComparer stringComparer = externalModule.MetadataReader.StringComparer; foreach (TypeDefinitionHandle tdNested in nestedClassDefinition.GetNestedTypes()) { TypeDefinition candidateClassDefinition = externalModule.MetadataReader.GetTypeDefinition(tdNested); if (stringComparer.Equals(candidateClassDefinition.Name, typeName)) { return((uint)externalModule.MetadataReader.GetToken(tdNested)); } } if (_logger.IsVerbose) { _logger.Writer.WriteLine($"Ibc TypeToken {ibcToken:x} unable to find nested type '{typeName}' on type '{externalModule.MetadataReader.GetToken(enclosingType):x}'"); } return(Cor.Macros.RidToToken(0, CorTokenType.mdtTypeDef)); // Nil TypeDef token } }
public ModuleToken GetModuleTokenForType(EcmaType type, bool throwIfNotFound = true) { return(Resolver.GetModuleTokenForType(type, allowDynamicallyCreatedReference: true, throwIfNotFound: throwIfNotFound)); }
public void VerifyInterfaces() { TypeDefinition typeDefinition = _module.MetadataReader.GetTypeDefinition(_typeDefinitionHandle); EcmaType type = (EcmaType)_module.GetType(_typeDefinitionHandle); if (type.IsInterface) { return; } InterfaceImplementationHandleCollection interfaceHandles = typeDefinition.GetInterfaceImplementations(); int count = interfaceHandles.Count; if (count == 0) { return; } // Look for duplicates and prepare distinct list of implemented interfaces to avoid // subsequent error duplication List <InterfaceMetadataObjects> implementedInterfaces = new List <InterfaceMetadataObjects>(); foreach (InterfaceImplementationHandle interfaceHandle in interfaceHandles) { InterfaceImplementation interfaceImplementation = _module.MetadataReader.GetInterfaceImplementation(interfaceHandle); TypeDesc interfaceTypeDesc = _module.GetType(interfaceImplementation.Interface) as TypeDesc; if (interfaceTypeDesc == null) { ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadBadFormat, type); } InterfaceMetadataObjects imo = new InterfaceMetadataObjects { InterfaceType = interfaceTypeDesc, InterfaceImplementation = interfaceImplementation }; if (!implementedInterfaces.Contains(imo)) { implementedInterfaces.Add(imo); } else { VerificationError(VerifierError.InterfaceImplHasDuplicate, Format(type), Format(imo.InterfaceType, _module, imo.InterfaceImplementation)); } } foreach (InterfaceMetadataObjects implementedInterface in implementedInterfaces) { if (!type.IsAbstract) { // Look for missing method implementation foreach (MethodDesc method in implementedInterface.InterfaceType.GetAllMethods()) { if (method.Signature.IsStatic) { continue; } MethodDesc resolvedMethod = type.ResolveInterfaceMethodTarget(method); if (resolvedMethod is null) { VerificationError(VerifierError.InterfaceMethodNotImplemented, Format(type), Format(implementedInterface.InterfaceType, _module, implementedInterface.InterfaceImplementation), Format(method)); } } } } }
public BlockingState(EcmaType type, bool isBlocked) { Type = type; IsBlocked = isBlocked; }