/// <summary> /// Constructs a new instance of <see cref="DelegateCreationInfo"/> set up to construct a delegate of type /// '<paramref name="delegateType"/>' pointing to '<paramref name="targetMethod"/>'. /// </summary> public static DelegateCreationInfo Create(TypeDesc delegateType, MethodDesc targetMethod, NodeFactory factory) { var context = (CompilerTypeSystemContext)delegateType.Context; var systemDelegate = targetMethod.Context.GetWellKnownType(WellKnownType.MulticastDelegate).BaseType; int paramCountTargetMethod = targetMethod.Signature.Length; if (!targetMethod.Signature.IsStatic) { paramCountTargetMethod++; } DelegateInfo delegateInfo = context.GetDelegateInfo(delegateType.GetTypeDefinition()); int paramCountDelegateClosed = delegateInfo.Signature.Length + 1; bool closed = false; if (paramCountDelegateClosed == paramCountTargetMethod) { closed = true; } else { Debug.Assert(paramCountDelegateClosed == paramCountTargetMethod + 1); } if (targetMethod.Signature.IsStatic) { MethodDesc invokeThunk; if (!closed) { // Open delegate to a static method invokeThunk = delegateInfo.Thunks[DelegateThunkKind.OpenStaticThunk]; } else { // Closed delegate to a static method (i.e. delegate to an extension method that locks the first parameter) invokeThunk = delegateInfo.Thunks[DelegateThunkKind.ClosedStaticThunk]; } var instantiatedDelegateType = delegateType as InstantiatedType; if (instantiatedDelegateType != null) invokeThunk = context.GetMethodForInstantiatedType(invokeThunk, instantiatedDelegateType); // We use InitializeClosedStaticThunk for both because RyuJIT generates same code for both, // but passes null as the first parameter for the open one. return new DelegateCreationInfo( factory.MethodEntrypoint(systemDelegate.GetKnownMethod("InitializeClosedStaticThunk", null)), factory.MethodEntrypoint(targetMethod), factory.MethodEntrypoint(invokeThunk)); } else { if (!closed) throw new NotImplementedException("Open instance delegates"); bool useUnboxingStub = targetMethod.OwningType.IsValueType; return new DelegateCreationInfo( factory.MethodEntrypoint(systemDelegate.GetKnownMethod("InitializeClosedInstance", null)), factory.MethodEntrypoint(targetMethod, useUnboxingStub)); } }
private bool IsBlocked(Cts.TypeDesc type) { if (type.IsArray || type.IsByRef || type.IsPointer) { return(IsBlocked(((Cts.ParameterizedType)type).ParameterType)); } if (type.IsSignatureVariable) { return(false); } if (!type.IsTypeDefinition) { if (IsBlocked(type.GetTypeDefinition())) { return(true); } foreach (var arg in type.Instantiation) { if (IsBlocked(arg)) { return(true); } } return(false); } return(_policy.IsBlocked((Cts.MetadataType)type)); }
private bool IsBlocked(Cts.TypeDesc type) { switch (type.Category) { case Cts.TypeFlags.SzArray: case Cts.TypeFlags.Array: case Cts.TypeFlags.Pointer: case Cts.TypeFlags.ByRef: return(IsBlocked(((Cts.ParameterizedType)type).ParameterType)); case Cts.TypeFlags.SignatureMethodVariable: case Cts.TypeFlags.SignatureTypeVariable: return(false); case Cts.TypeFlags.FunctionPointer: { Cts.MethodSignature pointerSignature = ((Cts.FunctionPointerType)type).Signature; if (IsBlocked(pointerSignature.ReturnType)) { return(true); } for (int i = 0; i < pointerSignature.Length; i++) { if (IsBlocked(pointerSignature[i])) { return(true); } } return(false); } default: Debug.Assert(type.IsDefType); if (!type.IsTypeDefinition) { if (IsBlocked(type.GetTypeDefinition())) { return(true); } foreach (var arg in type.Instantiation) { if (IsBlocked(arg)) { return(true); } } return(false); } return(_policy.IsBlocked((Cts.MetadataType)type)); } }
/// <summary> /// Get the NativeLayout for a type from a ReadyToRun image. /// </summary> public bool TryGetMetadataNativeLayout(TypeDesc concreteType, out IntPtr nativeLayoutInfoModule, out uint nativeLayoutInfoToken) { nativeLayoutInfoModule = default(IntPtr); nativeLayoutInfoToken = 0; #if SUPPORTS_NATIVE_METADATA_TYPE_LOADING var nativeMetadataType = concreteType.GetTypeDefinition() as TypeSystem.NativeFormat.NativeFormatType; if (nativeMetadataType == null) return false; var canonForm = concreteType.ConvertToCanonForm(CanonicalFormKind.Specific); var hashCode = canonForm.GetHashCode(); var loadedModulesCount = RuntimeAugments.GetLoadedModules(null); var loadedModuleHandles = new IntPtr[loadedModulesCount]; var loadedModules = RuntimeAugments.GetLoadedModules(loadedModuleHandles); Debug.Assert(loadedModulesCount == loadedModules); #if SUPPORTS_R2R_LOADING foreach (var moduleHandle in loadedModuleHandles) { ExternalReferencesTable externalFixupsTable; NativeHashtable typeTemplatesHashtable = LoadHashtable(moduleHandle, ReflectionMapBlob.MetadataBasedTypeTemplateMap, out externalFixupsTable); if (typeTemplatesHashtable.IsNull) continue; var enumerator = typeTemplatesHashtable.Lookup(hashCode); var nativeMetadataUnit = nativeMetadataType.Context.ResolveMetadataUnit(moduleHandle); NativeParser entryParser; while (!(entryParser = enumerator.GetNext()).IsNull) { var entryTypeHandle = entryParser.GetUnsigned().AsHandle(); TypeDesc typeDesc = nativeMetadataUnit.GetType(entryTypeHandle); Debug.Assert(typeDesc != null); if (typeDesc == canonForm) { TypeLoaderLogger.WriteLine("Found metadata template for type " + concreteType.ToString() + ": " + typeDesc.ToString()); nativeLayoutInfoToken = (uint)externalFixupsTable.GetRvaFromIndex(entryParser.GetUnsigned()); if (nativeLayoutInfoToken == BadTokenFixupValue) { throw new BadImageFormatException(); } nativeLayoutInfoModule = moduleHandle; return true; } } } #endif #endif return false; }
private void InitializeTypeInstance(Cts.TypeDesc entity, TypeSpecification record) { var sig = new TypeInstantiationSignature { GenericType = HandleType(entity.GetTypeDefinition()), }; for (int i = 0; i < entity.Instantiation.Length; i++) { sig.GenericTypeArguments.Add(HandleType(entity.Instantiation[i])); } record.Signature = sig; }
public override IEnumerable<MethodDesc> ComputeAllVirtualMethods(TypeDesc type) { var context = (CompilerTypeSystemContext)type.Context; InstantiatedType instantiatedType = type as InstantiatedType; if (instantiatedType != null) { DelegateInfo info = context.GetDelegateInfo(type.GetTypeDefinition()); yield return context.GetMethodForInstantiatedType(info.GetThunkMethod, instantiatedType); } else { DelegateInfo info = context.GetDelegateInfo(type); yield return info.GetThunkMethod; } }
protected IEnumerable <MethodDesc> GetAllMethodsForEnum(TypeDesc enumType) { TypeDesc enumTypeDefinition = enumType.GetTypeDefinition(); EnumInfo info = _enumInfoHashtable.GetOrCreateValue(enumTypeDefinition); if (enumType != enumTypeDefinition) { yield return(GetMethodForInstantiatedType(info.GetHashCodeMethod, (InstantiatedType)enumType)); yield return(GetMethodForInstantiatedType(info.EqualsMethod, (InstantiatedType)enumType)); } else { yield return(info.GetHashCodeMethod); yield return(info.EqualsMethod); } }
public static bool CheckConstraints(this TypeDesc type) { TypeDesc uninstantiatedType = type.GetTypeDefinition(); // Non-generic types always pass constraints check if (uninstantiatedType == type) { return(true); } for (int i = 0; i < uninstantiatedType.Instantiation.Length; i++) { if (!VerifyGenericParamConstraint(type.Instantiation, default(Instantiation), (GenericParameterDesc)uninstantiatedType.Instantiation[i], type.Instantiation[i])) { return(false); } } return(true); }
protected virtual IEnumerable <MethodDesc> GetAllMethodsForValueType(TypeDesc valueType) { TypeDesc valueTypeDefinition = valueType.GetTypeDefinition(); if (RequiresGetFieldHelperMethod((MetadataType)valueTypeDefinition)) { MethodDesc getFieldHelperMethod = _valueTypeMethodHashtable.GetOrCreateValue((DefType)valueTypeDefinition); if (valueType != valueTypeDefinition) { yield return(GetMethodForInstantiatedType(getFieldHelperMethod, (InstantiatedType)valueType)); } else { yield return(getFieldHelperMethod); } } foreach (MethodDesc method in valueType.GetMethods()) { yield return(method); } }
protected virtual IEnumerable<MethodDesc> GetAllMethodsForValueType(TypeDesc valueType) { TypeDesc valueTypeDefinition = valueType.GetTypeDefinition(); if (RequiresGetFieldHelperMethod((MetadataType)valueTypeDefinition)) { MethodDesc getFieldHelperMethod = _valueTypeMethodHashtable.GetOrCreateValue((DefType)valueTypeDefinition); // Check that System.ValueType has the method we're overriding. Debug.Assert(valueTypeDefinition.BaseType.GetMethod(getFieldHelperMethod.Name, null) != null); if (valueType != valueTypeDefinition) { yield return GetMethodForInstantiatedType(getFieldHelperMethod, (InstantiatedType)valueType); } else { yield return getFieldHelperMethod; } } foreach (MethodDesc method in valueType.GetMethods()) yield return method; }
public MethodDesc TryResolveConstrainedEnumMethod(TypeDesc enumType, MethodDesc virtualMethod) { Debug.Assert(enumType.IsEnum); if (!virtualMethod.OwningType.IsObject) { return(null); } // Also handle the odd case of generic enums TypeDesc enumTypeDefinition = enumType.GetTypeDefinition(); EnumInfo info = _enumInfoHashtable.GetOrCreateValue(enumTypeDefinition); MethodDesc resolvedMethod; if (virtualMethod.Name == "Equals") { resolvedMethod = info.EqualsMethod; } else if (virtualMethod.Name == "GetHashCode") { resolvedMethod = info.GetHashCodeMethod; } else { return(null); } if (enumType != enumTypeDefinition) { return(GetMethodForInstantiatedType(resolvedMethod, (InstantiatedType)enumType)); } return(resolvedMethod); }
protected virtual IEnumerable <MethodDesc> GetAllMethodsForEnum(TypeDesc enumType, bool virtualOnly) { if (virtualOnly) { // We devirtualize these, but they're not actually virtual. We don't want standalone method bodies // referenced from vtables. The base implementation on System.Enum is perflectly adequate. yield break; } if (_objectEqualsMethod == null) { _objectEqualsMethod = GetWellKnownType(WellKnownType.Object).GetMethod("Equals", null); } // If the classlib doesn't have Object.Equals, we don't need this. if (_objectEqualsMethod == null) { yield break; } TypeDesc enumTypeDefinition = enumType.GetTypeDefinition(); EnumInfo info = _enumInfoHashtable.GetOrCreateValue(enumTypeDefinition); if (enumType != enumTypeDefinition) { yield return(GetMethodForInstantiatedType(info.GetHashCodeMethod, (InstantiatedType)enumType)); yield return(GetMethodForInstantiatedType(info.EqualsMethod, (InstantiatedType)enumType)); } else { yield return(info.GetHashCodeMethod); yield return(info.EqualsMethod); } }
/// <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) { 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 = "Array<" + GetSignatureCPPTypeName(((ArrayType)type).ElementType) + ">"; mangledName = GetMangledTypeName(((ArrayType)type).ElementType) + "__Array"; if (!type.IsSzArray) mangledName += "Rank" + ((ArrayType)type).Rank.ToStringInvariant(); break; case TypeFlags.ByRef: mangledName = GetMangledTypeName(((ByRefType)type).ParameterType) + "__ByRef"; break; case TypeFlags.Pointer: mangledName = GetMangledTypeName(((PointerType)type).ParameterType) + "__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. var typeDefinition = type.GetTypeDefinition(); if (typeDefinition != type) { mangledName = GetMangledTypeName(typeDefinition); var inst = type.Instantiation; for (int i = 0; i < inst.Length; i++) { string instArgName = GetMangledTypeName(inst[i]); if (_mangleForCplusPlus) instArgName = instArgName.Replace("::", "_"); mangledName += "__" + instArgName; } } else { mangledName = SanitizeName(((DefType)type).GetFullName(), true); } break; } lock (this) { // Ensure that name is unique and update our tables accordingly. _mangledTypeNames = _mangledTypeNames.Add(type, mangledName); } return mangledName; }
/// <summary> /// Determine if two types share the same type definition /// </summary> public bool HasSameTypeDefinition(TypeDesc otherType) { return(GetTypeDefinition() == otherType.GetTypeDefinition()); }
private static bool CanCastByVarianceToInterfaceOrDelegate(this TypeDesc thisType, TypeDesc otherType, StackOverflowProtect protectInput) { if (!thisType.HasSameTypeDefinition(otherType)) { return(false); } var stackOverflowProtectKey = new CastingPair(thisType, otherType); if (protectInput != null) { if (protectInput.Contains(stackOverflowProtectKey)) { return(false); } } StackOverflowProtect protect = new StackOverflowProtect(stackOverflowProtectKey, protectInput); Instantiation instantiationThis = thisType.Instantiation; Instantiation instantiationTarget = otherType.Instantiation; Instantiation instantiationOpen = thisType.GetTypeDefinition().Instantiation; Debug.Assert(instantiationThis.Length == instantiationTarget.Length && instantiationThis.Length == instantiationOpen.Length); for (int i = 0; i < instantiationThis.Length; i++) { TypeDesc arg = instantiationThis[i]; TypeDesc targetArg = instantiationTarget[i]; if (arg != targetArg) { GenericParameterDesc openArgType = (GenericParameterDesc)instantiationOpen[i]; switch (openArgType.Variance) { case GenericVariance.Covariant: if (!arg.IsBoxedAndCanCastTo(targetArg, protect)) { return(false); } break; case GenericVariance.Contravariant: if (!targetArg.IsBoxedAndCanCastTo(arg, protect)) { return(false); } break; default: // non-variant Debug.Assert(openArgType.Variance == GenericVariance.None); return(false); } } } return(true); }
/// <summary> /// Determine if two types share the same type definition /// </summary> public bool HasSameTypeDefinition(TypeDesc otherType) { return GetTypeDefinition() == otherType.GetTypeDefinition(); }
/// <summary> /// Locate field on native format type and fill in the field access flags and offset. /// </summary> /// <param name="type">Metadata reader for the declaring type</param> /// <param name="fieldName">Field name</param> /// <param name="fieldAccessMetadata">Output - metadata information for field accessor construction</param> /// <returns>true when found, false otherwise</returns> private static bool TryGetFieldAccessMetadataForNativeFormatType( TypeDesc type, string fieldName, ref FieldAccessMetadata fieldAccessMetadata) { #if SUPPORTS_NATIVE_METADATA_TYPE_LOADING FieldDesc fieldDesc = type.GetField(fieldName); if (fieldDesc == null) { return false; } fieldAccessMetadata.MappingTableModule = IntPtr.Zero; #if SUPPORTS_R2R_LOADING fieldAccessMetadata.MappingTableModule = ModuleList.Instance.GetModuleForMetadataReader(((NativeFormatType)type.GetTypeDefinition()).MetadataReader); #endif fieldAccessMetadata.Offset = fieldDesc.Offset; fieldAccessMetadata.Flags = FieldTableFlags.HasMetadataHandle; if (fieldDesc.IsThreadStatic) { // Specify that the data is thread local fieldAccessMetadata.Flags |= FieldTableFlags.ThreadStatic; // Specify that the general purpose field access routine that only relies on offset should be used. fieldAccessMetadata.Flags |= FieldTableFlags.IsUniversalCanonicalEntry; } else if (fieldDesc.IsStatic) { uint nonGcStaticsRVA = 0; uint gcStaticsRVA = 0; bool nonGenericCase = false; if (type is MetadataType) { // Static fields on Non-Generic types are contained within the module, and their offsets // are adjusted by their static rva base. nonGenericCase = true; #if SUPPORTS_R2R_LOADING if (!TryGetStaticsTableEntry((MetadataType)type, nonGcStaticsRVA: out nonGcStaticsRVA, gcStaticsRVA: out gcStaticsRVA)) #endif { Environment.FailFast( "Failed to locate statics table entry for for field '" + fieldName + "' on type " + type.ToString()); } } if (fieldDesc.HasGCStaticBase) { if ((gcStaticsRVA == 0) && nonGenericCase) { Environment.FailFast( "GC statics region was not found for field '" + fieldName + "' on type " + type.ToString()); } fieldAccessMetadata.Offset += (int)gcStaticsRVA; fieldAccessMetadata.Flags |= FieldTableFlags.IsGcSection; } else { if ((nonGcStaticsRVA == 0) && nonGenericCase) { Environment.FailFast( "Non-GC statics region was not found for field '" + fieldName + "' on type " + type.ToString()); } fieldAccessMetadata.Offset += (int)nonGcStaticsRVA; } fieldAccessMetadata.Flags |= FieldTableFlags.Static; return true; } else { // Instance field fieldAccessMetadata.Flags |= FieldTableFlags.Instance; } return true; #else return false; #endif }
/// <summary> /// Replace some of the types in a type's construction with a new set of types. This function does not /// support any situation where there is an instantiated generic that is not represented by an /// InstantiatedType. Does not replace the open generics that may be instantiated over in this type. /// /// For instance, Given MyType<object, int[]>, /// an array of types to replace such as {int,object}, and /// an array of replacement types such as {string,__Canon}. /// The result shall be MyType<__Canon, string[]> /// /// This function cannot be used to replace MyType in the above example. /// </summary> public static TypeDesc ReplaceTypesInConstructionOfType(this TypeDesc type, TypeDesc[] typesToReplace, TypeDesc[] replacementTypes) { int directReplacementIndex = Array.IndexOf(typesToReplace, type); if (directReplacementIndex != -1) { return(replacementTypes[directReplacementIndex]); } if (type.HasInstantiation) { TypeDesc[] newInstantiation = null; Debug.Assert(type is InstantiatedType); int instantiationIndex = 0; for (; instantiationIndex < type.Instantiation.Length; instantiationIndex++) { TypeDesc oldType = type.Instantiation[instantiationIndex]; TypeDesc newType = oldType.ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes); if ((oldType != newType) || (newInstantiation != null)) { if (newInstantiation == null) { newInstantiation = new TypeDesc[type.Instantiation.Length]; for (int i = 0; i < instantiationIndex; i++) { newInstantiation[i] = type.Instantiation[i]; } } newInstantiation[instantiationIndex] = newType; } } if (newInstantiation != null) { return(type.Context.GetInstantiatedType((MetadataType)type.GetTypeDefinition(), new Instantiation(newInstantiation))); } } else if (type.IsParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType)type; TypeDesc oldParameter = parameterizedType.ParameterType; TypeDesc newParameter = oldParameter.ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes); if (oldParameter != newParameter) { if (type.IsArray) { ArrayType arrayType = (ArrayType)type; if (arrayType.IsSzArray) { return(type.Context.GetArrayType(newParameter)); } else { return(type.Context.GetArrayType(newParameter, arrayType.Rank)); } } else if (type.IsPointer) { return(type.Context.GetPointerType(newParameter)); } else if (type.IsByRef) { return(type.Context.GetByRefType(newParameter)); } Debug.Fail("Unknown form of type"); } } else if (type.IsFunctionPointer) { MethodSignature oldSig = ((FunctionPointerType)type).Signature; MethodSignatureBuilder sigBuilder = new MethodSignatureBuilder(oldSig); sigBuilder.ReturnType = oldSig.ReturnType.ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes); for (int paramIndex = 0; paramIndex < oldSig.Length; paramIndex++) { sigBuilder[paramIndex] = oldSig[paramIndex].ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes); } MethodSignature newSig = sigBuilder.ToSignature(); if (newSig != oldSig) { return(type.Context.GetFunctionPointerType(newSig)); } } return(type); }
private string ComputeMangledTypeName(TypeDesc type) { if (type is EcmaType) { string prependAssemblyName = SanitizeName(((EcmaType)type).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) { foreach (MetadataType t in ((EcmaType)type).EcmaModule.GetAllTypes()) { string name = t.GetFullName(); // Include encapsulating type MetadataType containingType = t.ContainingType; while (containingType != null) { name = containingType.GetFullName() + "_" + name; containingType = containingType.ContainingType; } name = SanitizeName(name, true); if (deduplicator.Contains(name)) { string nameWithIndex; for (int index = 1; ; index++) { nameWithIndex = name + "_" + index.ToString(CultureInfo.InvariantCulture); if (!deduplicator.Contains(nameWithIndex)) break; } name = nameWithIndex; } deduplicator.Add(name); if (_compilation.IsCppCodeGen) name = prependAssemblyName + "::" + name; else name = prependAssemblyName + "_" + name; _mangledTypeNames = _mangledTypeNames.Add(t, name); } } return _mangledTypeNames[type]; } string mangledName; switch (type.Category) { case TypeFlags.Array: // mangledName = "Array<" + GetSignatureCPPTypeName(((ArrayType)type).ElementType) + ">"; mangledName = GetMangledTypeName(((ArrayType)type).ElementType) + "__Array"; if (((ArrayType)type).Rank != 1) mangledName += "Rank" + ((ArrayType)type).Rank.ToString(); break; case TypeFlags.ByRef: mangledName = GetMangledTypeName(((ByRefType)type).ParameterType) + "__ByRef"; break; case TypeFlags.Pointer: mangledName = GetMangledTypeName(((PointerType)type).ParameterType) + "__Pointer"; break; default: var typeDefinition = type.GetTypeDefinition(); if (typeDefinition != type) { mangledName = GetMangledTypeName(typeDefinition); var inst = type.Instantiation; for (int i = 0; i < inst.Length; i++) { string instArgName = GetMangledTypeName(inst[i]); if (_compilation.IsCppCodeGen) instArgName = instArgName.Replace("::", "_"); mangledName += "__" + instArgName; } } else { mangledName = SanitizeName(((MetadataType)type).GetFullName(), true); } break; } lock (this) { _mangledTypeNames = _mangledTypeNames.Add(type, mangledName); } return mangledName; }
private void EncodeType(BlobBuilder blobBuilder, TypeDesc type, EmbeddedSignatureDataEmitter signatureDataEmitter) { signatureDataEmitter.Push(); signatureDataEmitter.Push(); signatureDataEmitter.EmitAtCurrentIndexStack(blobBuilder); signatureDataEmitter.Pop(); signatureDataEmitter.Push(); if (type.IsPrimitive) { SignatureTypeCode primitiveCode; switch (type.Category) { case TypeFlags.Void: primitiveCode = SignatureTypeCode.Void; break; case TypeFlags.Boolean: primitiveCode = SignatureTypeCode.Boolean; break; case TypeFlags.Char: primitiveCode = SignatureTypeCode.Char; break; case TypeFlags.SByte: primitiveCode = SignatureTypeCode.SByte; break; case TypeFlags.Byte: primitiveCode = SignatureTypeCode.Byte; break; case TypeFlags.Int16: primitiveCode = SignatureTypeCode.Int16; break; case TypeFlags.UInt16: primitiveCode = SignatureTypeCode.UInt16; break; case TypeFlags.Int32: primitiveCode = SignatureTypeCode.Int32; break; case TypeFlags.UInt32: primitiveCode = SignatureTypeCode.UInt32; break; case TypeFlags.Int64: primitiveCode = SignatureTypeCode.Int64; break; case TypeFlags.UInt64: primitiveCode = SignatureTypeCode.UInt64; break; case TypeFlags.IntPtr: primitiveCode = SignatureTypeCode.IntPtr; break; case TypeFlags.UIntPtr: primitiveCode = SignatureTypeCode.UIntPtr; break; case TypeFlags.Single: primitiveCode = SignatureTypeCode.Single; break; case TypeFlags.Double: primitiveCode = SignatureTypeCode.Double; break; default: throw new Exception("Unknown primitive type"); } blobBuilder.WriteByte((byte)primitiveCode); } else if (type.IsSzArray) { blobBuilder.WriteByte((byte)SignatureTypeCode.SZArray); EncodeType(blobBuilder, type.GetParameterType(), signatureDataEmitter); } else if (type.IsArray) { var arrayType = (ArrayType)type; blobBuilder.WriteByte((byte)SignatureTypeCode.Array); EncodeType(blobBuilder, type.GetParameterType(), signatureDataEmitter); signatureDataEmitter.EmitArrayShapeAtCurrentIndexStack(blobBuilder, arrayType.Rank); } else if (type.IsPointer) { blobBuilder.WriteByte((byte)SignatureTypeCode.Pointer); EncodeType(blobBuilder, type.GetParameterType(), signatureDataEmitter); } else if (type.IsFunctionPointer) { FunctionPointerType fnptrType = (FunctionPointerType)type; blobBuilder.WriteByte((byte)SignatureTypeCode.FunctionPointer); EncodeMethodSignature(blobBuilder, fnptrType.Signature, signatureDataEmitter); } else if (type.IsByRef) { blobBuilder.WriteByte((byte)SignatureTypeCode.ByReference); EncodeType(blobBuilder, type.GetParameterType(), signatureDataEmitter); } else if (type.IsObject) { blobBuilder.WriteByte((byte)SignatureTypeCode.Object); } else if (type.IsString) { blobBuilder.WriteByte((byte)SignatureTypeCode.String); } else if (type.IsWellKnownType(WellKnownType.TypedReference)) { blobBuilder.WriteByte((byte)SignatureTypeCode.TypedReference); } else if (type.IsWellKnownType(WellKnownType.Void)) { blobBuilder.WriteByte((byte)SignatureTypeCode.Void); } else if (type is SignatureVariable) { SignatureVariable sigVar = (SignatureVariable)type; SignatureTypeCode code = sigVar.IsMethodSignatureVariable ? SignatureTypeCode.GenericMethodParameter : SignatureTypeCode.GenericTypeParameter; blobBuilder.WriteByte((byte)code); blobBuilder.WriteCompressedInteger(sigVar.Index); } else if (type is InstantiatedType) { blobBuilder.WriteByte((byte)SignatureTypeCode.GenericTypeInstance); EncodeType(blobBuilder, type.GetTypeDefinition(), signatureDataEmitter); blobBuilder.WriteCompressedInteger(type.Instantiation.Length); foreach (var instantiationArg in type.Instantiation) { EncodeType(blobBuilder, instantiationArg, signatureDataEmitter); } } else if (type is MetadataType) { var metadataType = (MetadataType)type; // Must be class or valuetype blobBuilder.WriteByte(type.IsValueType ? (byte)SignatureTypeKind.ValueType : (byte)SignatureTypeKind.Class); int codedIndex = CodedIndex.TypeDefOrRef(GetTypeRef(metadataType)); blobBuilder.WriteCompressedInteger(codedIndex); } else { throw new Exception("Unexpected type"); } signatureDataEmitter.Pop(); signatureDataEmitter.Pop(); }