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)); }
/// <summary> /// Returns true if this is a type that doesn't require marshalling. /// </summary> private static bool IsBlittableType(TypeDesc type) { type = type.UnderlyingType; if (type.IsValueType) { if (type.IsPrimitive) { // All primitive types except char and bool are blittable TypeFlags category = type.Category; if (category == TypeFlags.Boolean || category == TypeFlags.Char) return false; return true; } foreach (FieldDesc field in type.GetFields()) { if (field.IsStatic) continue; TypeDesc fieldType = field.FieldType; // TODO: we should also reject fields that specify custom marshalling if (!IsBlittableType(fieldType)) return false; } return true; } if (type.IsPointer) return true; return false; }
private bool IsBlockedCustomAttributeConstantValue(Cts.TypeDesc type, object value) { if (type.IsSzArray) { var arrayType = (Cts.ArrayType)type; var arrayValue = (ImmutableArray <Ecma.Decoding.CustomAttributeTypedArgument <Cts.TypeDesc> >)value; if (arrayType.ElementType.UnderlyingType.IsPrimitive || arrayType.ElementType.IsString) { return(false); } foreach (var arrayElement in arrayValue) { if (IsBlockedCustomAttributeConstantValue(arrayElement.Type, arrayElement.Value)) { return(true); } if (arrayElement.Type.IsEnum && IsBlocked(arrayElement.Type)) { return(true); } } } else if (value is Cts.TypeDesc) { Debug.Assert(type is Cts.MetadataType && ((Cts.MetadataType)type).Name == "Type" && ((Cts.MetadataType)type).Namespace == "System"); return(IsBlocked((Cts.TypeDesc)value)); } return(false); }
public static MethodIL EmitIL(MethodDesc target) { Debug.Assert(target.Name == "Call"); Debug.Assert(target.Signature.Length > 0 && target.Signature[0] == target.Context.GetWellKnownType(WellKnownType.IntPtr)); ILEmitter emitter = new ILEmitter(); var codeStream = emitter.NewCodeStream(); // Load all the arguments except the first one (IntPtr address) for (int i = 1; i < target.Signature.Length; i++) { codeStream.EmitLdArg(i); } // now load IntPtr address codeStream.EmitLdArg(0); // Create a signature for the calli by copying the signature of the containing method // while skipping the first argument MethodSignature template = target.Signature; TypeDesc returnType = template.ReturnType; TypeDesc[] parameters = new TypeDesc[template.Length - 1]; for (int i = 1; i < template.Length; i++) { parameters[i - 1] = template[i]; } var signature = new MethodSignature(template.Flags, 0, returnType, parameters); codeStream.Emit(ILOpcode.calli, emitter.NewToken(signature)); codeStream.Emit(ILOpcode.ret); return emitter.Link(); }
public ExternEETypeSymbolNode(NodeFactory factory, TypeDesc type) : base("__EEType_" + NodeFactory.NameMangler.GetMangledTypeName(type)) { _type = type; EETypeNode.CheckCanGenerateEEType(factory, type); }
/// <summary> /// Returns true if <paramref name="type"/> doesn't require marshalling and can be directly passed /// to native code. /// </summary> private static bool IsSimpleType(TypeDesc type) { type = type.UnderlyingType; switch (type.Category) { case TypeFlags.Byte: case TypeFlags.SByte: case TypeFlags.UInt16: case TypeFlags.Int16: case TypeFlags.UInt32: case TypeFlags.Int32: case TypeFlags.UInt64: case TypeFlags.Int64: case TypeFlags.Double: case TypeFlags.Single: case TypeFlags.UIntPtr: case TypeFlags.IntPtr: return true; } if (type.IsPointer) return true; return false; }
public void AppendName(StringBuilder sb, TypeDesc type) { switch (type.Category) { case TypeFlags.Array: case TypeFlags.SzArray: AppendName(sb, (ArrayType)type); return; case TypeFlags.ByRef: AppendName(sb, (ByRefType)type); return; case TypeFlags.Pointer: AppendName(sb, (PointerType)type); return; case TypeFlags.GenericParameter: AppendName(sb, (GenericParameterDesc)type); return; case TypeFlags.SignatureTypeVariable: AppendName(sb, (SignatureTypeVariable)type); return; case TypeFlags.SignatureMethodVariable: AppendName(sb, (SignatureMethodVariable)type); return; default: Debug.Assert(type.IsDefType); AppendName(sb, (DefType)type); return; } }
/// <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)); } }
public FixupCellMetadataResolver(NativeFormatMetadataUnit metadataUnit, TypeDesc typeContext) { _metadataUnit = metadataUnit; _typeContext = typeContext; _methodContext = null; _loadContextFromNativeLayout = null; }
/// <summary> /// Determine if the construction of a type contains one of a given set of types. This is a deep /// scan. For instance, given type MyType<SomeGeneric<int[]>>, and a set of typesToFind /// that includes int, this function will return true. Does not detect the open generics that may be /// instantiated over in this type. IsConstructedOverType would return false if only passed MyType, /// or SomeGeneric for the above examplt. /// </summary> /// <param name="type">type to examine</param> /// <param name="typesToFind">types to search for in the construction of type</param> /// <returns>true if a type in typesToFind is found</returns> public static bool IsConstructedOverType(this TypeDesc type, TypeDesc[] typesToFind) { int directDiscoveryIndex = Array.IndexOf(typesToFind, type); if (directDiscoveryIndex != -1) return true; if (type.HasInstantiation) { for (int instantiationIndex = 0; instantiationIndex < type.Instantiation.Length; instantiationIndex++) { if (type.Instantiation[instantiationIndex].IsConstructedOverType(typesToFind)) { return true; } } } else if (type.IsParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType)type; return parameterizedType.ParameterType.IsConstructedOverType(typesToFind); } return false; }
public DelegateInfo(TypeDesc delegateType) { Debug.Assert(delegateType.IsDelegate); Debug.Assert(delegateType.IsTypeDefinition); _delegateType = delegateType; }
/// <summary> /// Returns a new instantiation that canonicalizes all types in <paramref name="instantiation"/> /// if possible under the policy of '<paramref name="kind"/>' /// </summary> /// <param name="changed">True if the returned instantiation is different from '<paramref name="instantiation"/>'.</param> public static Instantiation ConvertInstantiationToCanonForm(Instantiation instantiation, CanonicalFormKind kind, out bool changed) { TypeDesc[] newInstantiation = null; for (int i = 0; i < instantiation.Length; i++) { TypeDesc typeToConvert = instantiation[i]; TypeDesc convertedType = ConvertToCanon(typeToConvert, kind); if (typeToConvert != convertedType || newInstantiation != null) { if (newInstantiation == null) { newInstantiation = new TypeDesc[instantiation.Length]; for (int j = 0; j < i; j++) newInstantiation[j] = instantiation[j]; } newInstantiation[i] = convertedType; } } changed = newInstantiation != null; if (changed) { return new Instantiation(newInstantiation); } return instantiation; }
// Helper method for nullable transform. Ideally, we would do the nullable transform upfront before // the types is build. Unfortunately, there does not seem to be easy way to test for Nullable<> type definition // without introducing type builder recursion private static RuntimeTypeHandle GetRuntimeTypeHandleWithNullableTransform(TypeBuilder builder, TypeDesc type) { RuntimeTypeHandle th = builder.GetRuntimeTypeHandle(type); if (RuntimeAugments.IsNullable(th)) th = builder.GetRuntimeTypeHandle(((DefType)type).Instantiation[0]); return th; }
private static int GetNumberOfBaseSlots(NodeFactory factory, TypeDesc owningType) { int baseSlots = 0; TypeDesc baseType = owningType.BaseType; while (baseType != null) { // Normalize the base type. Necessary to make this work with the lazy vtable slot // concept - if we start with a canonical type, the base type could end up being // something like Base<__Canon, string>. We would get "0 slots used" for weird // base types like this. baseType = baseType.ConvertToCanonForm(CanonicalFormKind.Specific); // For types that have a generic dictionary, the introduced virtual method slots are // prefixed with a pointer to the generic dictionary. if (baseType.HasGenericDictionarySlot()) baseSlots++; IReadOnlyList<MethodDesc> baseVirtualSlots = factory.VTable(baseType).Slots; baseSlots += baseVirtualSlots.Count; baseType = baseType.BaseType; } return baseSlots; }
private void RootMethods(TypeDesc type, string reason, IRootingServiceProvider rootProvider) { foreach (MethodDesc method in type.GetMethods()) { // Skip methods with no IL and uninstantiated generic methods if (method.IsIntrinsic || method.IsAbstract || method.HasInstantiation) continue; if (method.IsInternalCall) continue; try { CheckCanGenerateMethod(method); rootProvider.AddCompilationRoot(method, reason); } catch (TypeSystemException) { // TODO: fail compilation if a switch was passed // Individual methods can fail to load types referenced in their signatures. // Skip them in library mode since they're not going to be callable. continue; // TODO: Log as a warning } } }
public EETypeNode(TypeDesc type) { Debug.Assert(!type.IsCanonicalSubtype(CanonicalFormKind.Specific)); Debug.Assert(!type.IsRuntimeDeterminedSubtype); _type = type; _optionalFieldsNode = new EETypeOptionalFieldsNode(this); }
public static Instantiation ConvertInstantiationToSharedRuntimeForm(Instantiation instantiation, Instantiation openInstantiation, out bool changed) { Debug.Assert(instantiation.Length == openInstantiation.Length); TypeDesc[] sharedInstantiation = null; CanonicalFormKind currentPolicy = CanonicalFormKind.Specific; CanonicalFormKind startLoopPolicy; do { startLoopPolicy = currentPolicy; for (int instantiationIndex = 0; instantiationIndex < instantiation.Length; instantiationIndex++) { TypeDesc typeToConvert = instantiation[instantiationIndex]; TypeSystemContext context = typeToConvert.Context; TypeDesc canonForm = context.ConvertToCanon(typeToConvert, ref currentPolicy); TypeDesc runtimeDeterminedForm = typeToConvert; Debug.Assert(openInstantiation[instantiationIndex] is GenericParameterDesc); if ((typeToConvert != canonForm) || typeToConvert.IsCanonicalType) { Debug.Assert(canonForm is DefType); if (sharedInstantiation == null) { sharedInstantiation = new TypeDesc[instantiation.Length]; for (int i = 0; i < instantiationIndex; i++) sharedInstantiation[i] = instantiation[i]; } runtimeDeterminedForm = context.GetRuntimeDeterminedType( (DefType)canonForm, (GenericParameterDesc)openInstantiation[instantiationIndex]); } if (sharedInstantiation != null) { sharedInstantiation[instantiationIndex] = runtimeDeterminedForm; } } // Optimization: even if canonical policy changed, we don't actually need to re-run the loop // for instantiations that only have a single element. if (instantiation.Length == 1) { break; } } while (currentPolicy != startLoopPolicy); changed = sharedInstantiation != null; if (changed) { return new Instantiation(sharedInstantiation); } return instantiation; }
public override DefType[] ComputeRuntimeInterfaces(TypeDesc _type) { ArrayType arrayType = (ArrayType)_type; Debug.Assert(arrayType.IsSzArray); TypeDesc arrayOfTInstantiation = _arrayOfTType.MakeInstantiatedType(arrayType.ElementType); return arrayOfTInstantiation.RuntimeInterfaces; }
public string GetMangledTypeName(TypeDesc type) { string mangledName; if (_mangledTypeNames.TryGetValue(type, out mangledName)) return mangledName; return ComputeMangledTypeName(type); }
public override IEnumerable<MethodDesc> ComputeAllVirtualMethods(TypeDesc type) { foreach (var method in type.GetMethods()) { if (method.IsVirtual) yield return method; } }
private void AppendOwningType(StringBuilder sb, TypeDesc type) { // Special case primitive types: we don't want to use short names here if (type.IsPrimitive || type.IsString || type.IsObject) _typeNameFormatter.AppendNameForNamespaceTypeWithoutAliases(sb, (MetadataType)type); else AppendType(sb, type, false); }
public ArrayMethodILEmitter(ArrayMethod method) { _method = method; ArrayType arrayType = (ArrayType)method.OwningType; _rank = arrayType.Rank; _elementType = arrayType.ElementType; }
protected sealed internal override bool ComputeHasStaticConstructor(TypeDesc type) { if (type is MetadataType) { return ((MetadataType)type).GetStaticConstructor() != null; } return false; }
public override DefType[] ComputeRuntimeInterfaces(TypeDesc _type) { ArrayType arrayType = (ArrayType)_type; Debug.Assert(arrayType.IsSzArray); Instantiation arrayInstantiation = new Instantiation(new TypeDesc[] { arrayType.ElementType }); TypeDesc arrayOfTInstantiation = _arrayOfTType.Context.GetInstantiatedType(_arrayOfTType, arrayInstantiation); return arrayOfTInstantiation.RuntimeInterfaces; }
public MethodSignature(MethodSignatureFlags flags, int genericParameterCount, TypeDesc returnType, TypeDesc[] parameters) { _flags = flags; _genericParameterCount = genericParameterCount; _returnType = returnType; _parameters = parameters; Debug.Assert(parameters != null, "Parameters must not be null"); }
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)); } }
private static TypeDesc ConvertToCanon(TypeDesc typeToConvert, ref CanonicalFormKind kind) { TypeSystemContext context = typeToConvert.Context; if (kind == CanonicalFormKind.Universal) { return context.UniversalCanonType; } else if (kind == CanonicalFormKind.Specific) { if (typeToConvert == context.UniversalCanonType) { kind = CanonicalFormKind.Universal; return context.UniversalCanonType; } else if (typeToConvert.IsSignatureVariable) { return typeToConvert; } else if (typeToConvert.IsDefType) { if (!typeToConvert.IsValueType) return context.CanonType; else if (typeToConvert.HasInstantiation) { TypeDesc convertedType = typeToConvert.ConvertToCanonForm(CanonicalFormKind.Specific); if (convertedType.IsCanonicalSubtype(CanonicalFormKind.Universal)) { kind = CanonicalFormKind.Universal; return context.UniversalCanonType; } return convertedType; } else return typeToConvert; } else if (typeToConvert.IsArray) { return context.CanonType; } else { TypeDesc convertedType = typeToConvert.ConvertToCanonForm(CanonicalFormKind.Specific); if (convertedType.IsCanonicalSubtype(CanonicalFormKind.Universal)) { kind = CanonicalFormKind.Universal; return context.UniversalCanonType; } return convertedType; } } else { Debug.Assert(false); return null; } }
public override MetadataRecord HandleType(Cts.TypeDesc type) { MetadataRecord rec; if (type.IsSzArray) { var arrayType = (Cts.ArrayType)type; rec = _types.GetOrCreate(arrayType, _initSzArray ?? (_initSzArray = InitializeSzArray)); } else if (type.IsArray) { var arrayType = (Cts.ArrayType)type; rec = _types.GetOrCreate(arrayType, _initArray ?? (_initArray = InitializeArray)); } else if (type.IsByRef) { var byRefType = (Cts.ByRefType)type; rec = _types.GetOrCreate(byRefType, _initByRef ?? (_initByRef = InitializeByRef)); } else if (type.IsPointer) { var pointerType = (Cts.PointerType)type; rec = _types.GetOrCreate(pointerType, _initPointer ?? (_initPointer = InitializePointer)); } else if (type is Cts.SignatureTypeVariable) { var variable = (Cts.SignatureTypeVariable)type; rec = _types.GetOrCreate(variable, _initTypeVar ?? (_initTypeVar = InitializeTypeVariable)); } else if (type is Cts.SignatureMethodVariable) { var variable = (Cts.SignatureMethodVariable)type; rec = _types.GetOrCreate(variable, _initMethodVar ?? (_initMethodVar = InitializeMethodVariable)); } else if (type is Cts.InstantiatedType) { var instType = (Cts.InstantiatedType)type; rec = _types.GetOrCreate(instType, _initTypeInst ?? (_initTypeInst = InitializeTypeInstance)); } else { var metadataType = (Cts.MetadataType)type; if (_policy.GeneratesMetadata(metadataType)) { rec = _types.GetOrCreate(metadataType, _initTypeDef ?? (_initTypeDef = InitializeTypeDef)); } else { rec = _types.GetOrCreate(metadataType, _initTypeRef ?? (_initTypeRef = InitializeTypeRef)); } } Debug.Assert(rec is TypeDefinition || rec is TypeReference || rec is TypeSpecification); return(rec); }
private TypeDesc GetInstantiationType(ref NativeParser parser, uint arity) { DefType typeDefinition = (DefType)GetType(ref parser); TypeDesc[] typeArguments = new TypeDesc[arity]; for (uint i = 0; i < arity; i++) typeArguments[i] = GetType(ref parser); return _typeSystemContext.ResolveGenericInstantiation(typeDefinition, new Instantiation(typeArguments)); }
/// <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; }
public void AppendType(StringBuilder sb, TypeDesc type, bool forceValueClassPrefix = true) { // Types referenced from the IL show as instantiated over generic parameter. // E.g. "initobj !0" becomes "initobj !T" TypeDesc typeInContext = type.InstantiateSignature( _methodIL.OwningMethod.OwningType.Instantiation, _methodIL.OwningMethod.Instantiation); if (typeInContext.HasInstantiation || forceValueClassPrefix) this.TypeNameFormatter.AppendNameWithValueClassPrefix(sb, typeInContext); else this.TypeNameFormatter.AppendName(sb, typeInContext); }
public static MethodIL EmitIL(MethodDesc target) { Debug.Assert(target.Name == "Call"); Debug.Assert(target.Signature.Length > 0 && target.Signature[0] == target.Context.GetWellKnownType(WellKnownType.IntPtr)); ILEmitter emitter = new ILEmitter(); var codeStream = emitter.NewCodeStream(); // Load all the arguments except the first one (IntPtr address) for (int i = 1; i < target.Signature.Length; i++) { codeStream.EmitLdArg(i); } // now load IntPtr address codeStream.EmitLdArg(0); // Create a signature for the calli by copying the signature of the containing method // while skipping the first argument MethodSignature template = target.Signature; TypeDesc returnType = template.ReturnType; TypeDesc[] parameters = new TypeDesc[template.Length - 1]; for (int i = 1; i < template.Length; i++) { parameters[i - 1] = template[i]; } var signature = new MethodSignature(template.Flags, 0, returnType, parameters); bool useTransformedCalli = true; if ((signature.Flags & MethodSignatureFlags.UnmanagedCallingConventionMask) != 0) { // Fat function pointer only ever exist for managed targets. useTransformedCalli = false; } if (((MetadataType)target.OwningType).Name == "RawCalliHelper") { // RawCalliHelper doesn't need the transform. useTransformedCalli = false; } if (useTransformedCalli) EmitTransformedCalli(emitter, codeStream, signature); else codeStream.Emit(ILOpcode.calli, emitter.NewToken(signature)); codeStream.Emit(ILOpcode.ret); return emitter.Link(target); }
public EETypeNode(NodeFactory factory, TypeDesc type) { Debug.Assert(!type.IsCanonicalSubtype(CanonicalFormKind.Specific)); Debug.Assert(!type.IsRuntimeDeterminedSubtype); _type = type; _optionalFieldsNode = new EETypeOptionalFieldsNode(this); // Note: The fact that you can't create invalid EETypeNode is used from many places that grab // an EETypeNode from the factory with the sole purpose of making sure the validation has run // and that the result of the positive validation is "cached" (by the presence of an EETypeNode). CheckCanGenerateEEType(factory, type); }
// // Is the source type derived from the target type? // static public bool IsDerived(TypeDesc derivedType, TypeDesc baseType) { for (;;) { if (derivedType == baseType) return true; derivedType = derivedType.BaseType; if (derivedType == null) 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; }
private MetadataRecord HandleCustomAttributeConstantValue(Cts.TypeDesc type, object value) { switch (type.UnderlyingType.Category) { case Cts.TypeFlags.Boolean: return(new ConstantBooleanValue { Value = (bool)value }); case Cts.TypeFlags.Byte: return(new ConstantByteValue { Value = (byte)value }); case Cts.TypeFlags.Char: return(new ConstantCharValue { Value = (char)value }); case Cts.TypeFlags.Double: return(new ConstantDoubleValue { Value = (double)value }); case Cts.TypeFlags.Int16: return(new ConstantInt16Value { Value = (short)value }); case Cts.TypeFlags.Int32: return(new ConstantInt32Value { Value = (int)value }); case Cts.TypeFlags.Int64: return(new ConstantInt64Value { Value = (long)value }); case Cts.TypeFlags.SByte: return(new ConstantSByteValue { Value = (sbyte)value }); case Cts.TypeFlags.Single: return(new ConstantSingleValue { Value = (float)value }); case Cts.TypeFlags.UInt16: return(new ConstantUInt16Value { Value = (ushort)value }); case Cts.TypeFlags.UInt32: return(new ConstantUInt32Value { Value = (uint)value }); case Cts.TypeFlags.UInt64: return(new ConstantUInt64Value { Value = (ulong)value }); } if (type.IsString) { return(HandleString((string)value)); } if (value == null) { return(new ConstantReferenceValue()); } if (type.IsSzArray) { return(HandleCustomAttributeConstantArray( (Cts.ArrayType)type, (ImmutableArray <Ecma.CustomAttributeTypedArgument <Cts.TypeDesc> >)value)); } Debug.Assert(value is Cts.TypeDesc); Debug.Assert(type is Cts.MetadataType && ((Cts.MetadataType)type).Name == "Type" && ((Cts.MetadataType)type).Namespace == "System"); return(HandleType((Cts.TypeDesc)value)); }
public TypeDesc ResolveRuntimeTypeHandle(RuntimeTypeHandle rtth) { TypeDesc returnedType; if (_runtimeTypeHandleResolutionCache.TryGetValue(rtth, out returnedType)) { return(returnedType); } if (rtth.Equals(CanonType.RuntimeTypeHandle)) { returnedType = CanonType; } else if (rtth.Equals(UniversalCanonType.RuntimeTypeHandle)) { returnedType = UniversalCanonType; } else if (RuntimeAugments.IsGenericTypeDefinition(rtth)) { returnedType = TryGetMetadataBasedTypeFromRuntimeTypeHandle_Uncached(rtth); if (returnedType == null) { unsafe { TypeDesc[] genericParameters = new TypeDesc[rtth.ToEETypePtr()->GenericArgumentCount]; for (int i = 0; i < genericParameters.Length; i++) { genericParameters[i] = GetSignatureVariable(i, false); } returnedType = new NoMetadataType(this, rtth, null, new Instantiation(genericParameters), rtth.GetHashCode()); } } } else if (RuntimeAugments.IsGenericType(rtth)) { RuntimeTypeHandle typeDefRuntimeTypeHandle; RuntimeTypeHandle[] genericArgRuntimeTypeHandles; typeDefRuntimeTypeHandle = RuntimeAugments.GetGenericInstantiation(rtth, out genericArgRuntimeTypeHandles); DefType typeDef = (DefType)ResolveRuntimeTypeHandle(typeDefRuntimeTypeHandle); Instantiation genericArgs = ResolveRuntimeTypeHandles(genericArgRuntimeTypeHandles); returnedType = ResolveGenericInstantiation(typeDef, genericArgs); } else if (RuntimeAugments.IsArrayType(rtth)) { RuntimeTypeHandle elementTypeHandle = RuntimeAugments.GetRelatedParameterTypeHandle(rtth); TypeDesc elementType = ResolveRuntimeTypeHandle(elementTypeHandle); unsafe { if (rtth.ToEETypePtr()->IsSzArray) { returnedType = GetArrayType(elementType); } else { returnedType = GetArrayType(elementType, rtth.ToEETypePtr()->ArrayRank); } } } else if (RuntimeAugments.IsUnmanagedPointerType(rtth)) { RuntimeTypeHandle targetTypeHandle = RuntimeAugments.GetRelatedParameterTypeHandle(rtth); TypeDesc targetType = ResolveRuntimeTypeHandle(targetTypeHandle); returnedType = GetPointerType(targetType); } else if (RuntimeAugments.IsByRefType(rtth)) { RuntimeTypeHandle targetTypeHandle = RuntimeAugments.GetRelatedParameterTypeHandle(rtth); TypeDesc targetType = ResolveRuntimeTypeHandle(targetTypeHandle); returnedType = GetByRefType(targetType); } else { returnedType = TryGetMetadataBasedTypeFromRuntimeTypeHandle_Uncached(rtth); if (returnedType == null) { returnedType = new NoMetadataType(this, rtth, null, Instantiation.Empty, rtth.GetHashCode()); } } // We either retrieved an existing DefType that is already registered with the runtime // or one that is not associated with an MethodTable yet. If it's not associated, associate it. if (returnedType.RuntimeTypeHandle.IsNull()) { TypeBuilderState state = returnedType.GetTypeBuilderStateIfExist(); bool skipStoringRuntimeTypeHandle = false; // If we've already attempted to lookup and failed to retrieve this type handle, we // may have already decided to create a new one. In that case, do not attempt to abort // that creation process as it may have already begun the process of type creation if (state != null && state.AttemptedAndFailedToRetrieveTypeHandle) { skipStoringRuntimeTypeHandle = true; } if (!skipStoringRuntimeTypeHandle) { returnedType.SetRuntimeTypeHandleUnsafe(rtth); } } _runtimeTypeHandleResolutionCache.Add(rtth, returnedType); return(returnedType.WithDebugName()); }
private bool ComputeCanCompareValueTypeBits(MetadataType type) { Debug.Assert(type.IsValueType); if (type.ContainsGCPointers) return false; if (type.IsGenericDefinition) return false; OverlappingFieldTracker overlappingFieldTracker = new OverlappingFieldTracker(type); bool result = true; foreach (var field in type.GetFields()) { if (field.IsStatic) continue; if (!overlappingFieldTracker.TrackField(field)) { // This field overlaps with another field - can't compare memory result = false; break; } TypeDesc fieldType = field.FieldType; if (fieldType.IsPrimitive || fieldType.IsEnum || fieldType.IsPointer || fieldType.IsFunctionPointer) { TypeFlags category = fieldType.UnderlyingType.Category; if (category == TypeFlags.Single || category == TypeFlags.Double) { // Double/Single have weird behaviors around negative/positive zero result = false; break; } } else { // Would be a suprise if this wasn't a valuetype. We checked ContainsGCPointers above. Debug.Assert(fieldType.IsValueType); MethodDesc objectEqualsMethod = fieldType.Context._objectEqualsMethod; // If the field overrides Equals, we can't use the fast helper because we need to call the method. if (fieldType.FindVirtualFunctionTargetMethodOnObjectType(objectEqualsMethod).OwningType == fieldType) { result = false; break; } if (!_hashtable.GetOrCreateValue((MetadataType)fieldType).CanCompareValueTypeBits) { result = false; break; } } } // If there are gaps, we can't memcompare if (result && overlappingFieldTracker.HasGaps) result = false; return result; }
private MetadataRecord HandleCustomAttributeConstantArray( Cts.ArrayType type, ImmutableArray <Ecma.CustomAttributeTypedArgument <Cts.TypeDesc> > value) { Cts.TypeDesc elementType = type.ElementType; switch (elementType.UnderlyingType.Category) { case Cts.TypeFlags.Boolean: return(new ConstantBooleanArray { Value = GetCustomAttributeConstantArrayElements <bool>(value) }); case Cts.TypeFlags.Byte: return(new ConstantByteArray { Value = GetCustomAttributeConstantArrayElements <byte>(value) }); case Cts.TypeFlags.Char: return(new ConstantCharArray { Value = GetCustomAttributeConstantArrayElements <char>(value) }); case Cts.TypeFlags.Double: return(new ConstantDoubleArray { Value = GetCustomAttributeConstantArrayElements <double>(value) }); case Cts.TypeFlags.Int16: return(new ConstantInt16Array { Value = GetCustomAttributeConstantArrayElements <short>(value) }); case Cts.TypeFlags.Int32: return(new ConstantInt32Array { Value = GetCustomAttributeConstantArrayElements <int>(value) }); case Cts.TypeFlags.Int64: return(new ConstantInt64Array { Value = GetCustomAttributeConstantArrayElements <long>(value) }); case Cts.TypeFlags.SByte: return(new ConstantSByteArray { Value = GetCustomAttributeConstantArrayElements <sbyte>(value) }); case Cts.TypeFlags.Single: return(new ConstantSingleArray { Value = GetCustomAttributeConstantArrayElements <float>(value) }); case Cts.TypeFlags.UInt16: return(new ConstantUInt16Array { Value = GetCustomAttributeConstantArrayElements <ushort>(value) }); case Cts.TypeFlags.UInt32: return(new ConstantUInt32Array { Value = GetCustomAttributeConstantArrayElements <uint>(value) }); case Cts.TypeFlags.UInt64: return(new ConstantUInt64Array { Value = GetCustomAttributeConstantArrayElements <ulong>(value) }); } if (elementType.IsString) { var record = new ConstantStringArray(); record.Value.Capacity = value.Length; foreach (var element in value) { MetadataRecord elementRecord = element.Value == null ? (MetadataRecord) new ConstantReferenceValue() : HandleString((string)element.Value); record.Value.Add(elementRecord); } return(record); } var result = new ConstantHandleArray(); result.Value.Capacity = value.Length; for (int i = 0; i < value.Length; i++) { MetadataRecord elementRecord = HandleCustomAttributeConstantValue(value[i].Type, value[i].Value); if (value[i].Type.IsEnum) { elementRecord = new ConstantBoxedEnumValue { Value = elementRecord, Type = HandleType(value[i].Type) }; } result.Value.Add(elementRecord); } return(result); }
public TypeState(TypeDesc type, TypeStateHashtable hashtable) { Type = type; _hashtable = hashtable; }
/// <summary> /// Attempts to resolve constrained call to <paramref name="interfaceMethod"/> into a concrete non-unboxing /// method on <paramref name="constrainedType"/>. /// The ability to resolve constraint methods is affected by the degree of code sharing we are performing /// for generic code. /// </summary> /// <returns>The resolved method or null if the constraint couldn't be resolved.</returns> static public MethodDesc TryResolveConstraintMethodApprox(this MetadataType constrainedType, TypeDesc interfaceType, MethodDesc interfaceMethod, out bool forceRuntimeLookup) { forceRuntimeLookup = false; // We can't resolve constraint calls effectively for reference types, and there's // not a lot of perf. benefit in doing it anyway. if (!constrainedType.IsValueType) { return(null); } // Non-virtual methods called through constraints simply resolve to the specified method without constraint resolution. if (!interfaceMethod.IsVirtual) { return(null); } MetadataType canonMT = constrainedType; MethodDesc method; MethodDesc genInterfaceMethod = interfaceMethod.GetMethodDefinition(); if (genInterfaceMethod.OwningType.IsInterface) { // Sometimes (when compiling shared generic code) // we don't have enough exact type information at JIT time // even to decide whether we will be able to resolve to an unboxed entry point... // To cope with this case we always go via the helper function if there's any // chance of this happening by checking for all interfaces which might possibly // be compatible with the call (verification will have ensured that // at least one of them will be) // Enumerate all potential interface instantiations // TODO: this code assumes no shared generics Debug.Assert(interfaceType == interfaceMethod.OwningType); method = VirtualFunctionResolution.ResolveInterfaceMethodToVirtualMethodOnType(genInterfaceMethod, constrainedType); } else if (genInterfaceMethod.IsVirtual) { method = VirtualFunctionResolution.FindVirtualFunctionTargetMethodOnObjectType(genInterfaceMethod, constrainedType); } else { // The method will be null if calling a non-virtual instance // methods on System.Object, i.e. when these are used as a constraint. method = null; } if (method == null) { // Fall back to VSD return(null); } //#TryResolveConstraintMethodApprox_DoNotReturnParentMethod // Only return a method if the value type itself declares the method, // otherwise we might get a method from Object or System.ValueType if (!method.OwningType.IsValueType) { // Fall back to VSD return(null); } // We've resolved the method, ignoring its generic method arguments // If the method is a generic method then go and get the instantiated descriptor if (interfaceMethod.HasInstantiation) { method = method.InstantiateSignature(interfaceType.Instantiation, interfaceMethod.Instantiation); } Debug.Assert(method != null); //assert(!pMD->IsUnboxingStub()); return(method); }
/// <summary> /// Returns true if '<paramref name="thisType"/>' can be cast to '<paramref name="otherType"/>'. /// Assumes '<paramref name="thisType"/>' is in it's boxed form if it's a value type (i.e. /// [System.Int32].CanCastTo([System.Object]) will return true). /// </summary> public static bool CanCastTo(this TypeDesc thisType, TypeDesc otherType) { return(thisType.CanCastToInternal(otherType, null)); }
private int _rank; // -1 for regular single dimensional arrays, > 0 for multidimensional arrays internal ArrayType(TypeDesc elementType, int rank) : base(elementType) { _rank = rank; }
/// <summary> /// Replace some of the types in a method's construction with a new set of types. /// Does not replace the open generics that may be instantiated over in this type. /// /// For instance, Given MyType<object, int[]>.Function<short>(), /// an array of types to replace such as {int,short}, and /// an array of replacement types such as {string,char}. /// The result shall be MyType<object, string[]>.Function<char> /// /// This function cannot be used to replace MyType in the above example. /// </summary> public static MethodDesc ReplaceTypesInConstructionOfMethod(this MethodDesc method, TypeDesc[] typesToReplace, TypeDesc[] replacementTypes) { TypeDesc newOwningType = method.OwningType.ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes); MethodDesc methodOnOwningType = null; bool owningTypeChanged = false; if (newOwningType == method.OwningType) { methodOnOwningType = method.GetMethodDefinition(); } else { methodOnOwningType = TypeSystemHelpers.FindMethodOnExactTypeWithMatchingTypicalMethod(newOwningType, method); owningTypeChanged = true; } MethodDesc result; if (!method.HasInstantiation) { result = methodOnOwningType; } else { Debug.Assert(method is InstantiatedMethod); TypeDesc[] newInstantiation = null; int instantiationIndex = 0; for (; instantiationIndex < method.Instantiation.Length; instantiationIndex++) { TypeDesc oldType = method.Instantiation[instantiationIndex]; TypeDesc newType = oldType.ReplaceTypesInConstructionOfType(typesToReplace, replacementTypes); if ((oldType != newType) || (newInstantiation != null)) { if (newInstantiation == null) { newInstantiation = new TypeDesc[method.Instantiation.Length]; for (int i = 0; i < instantiationIndex; i++) { newInstantiation[i] = method.Instantiation[i]; } } newInstantiation[instantiationIndex] = newType; } } if (newInstantiation != null) { result = method.Context.GetInstantiatedMethod(methodOnOwningType, new Instantiation(newInstantiation)); } else if (owningTypeChanged) { result = method.Context.GetInstantiatedMethod(methodOnOwningType, method.Instantiation); } else { result = method; } } return(result); }
public override MetadataRecord HandleType(Cts.TypeDesc type) { MetadataRecord rec; if (_types.TryGet(type, out rec)) { return(rec); } switch (type.Category) { case Cts.TypeFlags.SzArray: rec = _types.Create((Cts.ArrayType)type, _initSzArray ??= InitializeSzArray); break; case Cts.TypeFlags.Array: rec = _types.Create((Cts.ArrayType)type, _initArray ??= InitializeArray); break; case Cts.TypeFlags.ByRef: rec = _types.Create((Cts.ByRefType)type, _initByRef ??= InitializeByRef); break; case Cts.TypeFlags.Pointer: rec = _types.Create((Cts.PointerType)type, _initPointer ??= InitializePointer); break; case Cts.TypeFlags.FunctionPointer: rec = _types.Create((Cts.FunctionPointerType)type, _initFunctionPointer ??= InitializeFunctionPointer); break; case Cts.TypeFlags.SignatureTypeVariable: rec = _types.Create((Cts.SignatureTypeVariable)type, _initTypeVar ??= InitializeTypeVariable); break; case Cts.TypeFlags.SignatureMethodVariable: rec = _types.Create((Cts.SignatureMethodVariable)type, _initMethodVar ??= InitializeMethodVariable); break; default: { Debug.Assert(type.IsDefType); if (!type.IsTypeDefinition) { // Instantiated generic type rec = _types.Create(type, _initTypeInst ??= InitializeTypeInstance); } else { // Type definition var metadataType = (Cts.MetadataType)type; if (_policy.GeneratesMetadata(metadataType)) { Debug.Assert(!_policy.IsBlocked(metadataType)); rec = _types.Create(metadataType, _initTypeDef ??= InitializeTypeDef); } else { rec = _types.Create(metadataType, _initTypeRef ??= InitializeTypeRef); } } } break; } Debug.Assert(rec is TypeDefinition || rec is TypeReference || rec is TypeSpecification); return(rec); }
internal PointerType(TypeDesc parameterType) : base(parameterType) { }
private void InitializeParameterTypeSignature(Cts.TypeDesc entity, ParameterTypeSignature record) { // TODO: CustomModifiers record.Type = HandleType(entity); }
private ParameterTypeSignature HandleParameterTypeSignature(Cts.TypeDesc parameter) { return(_paramSigs.GetOrCreate(parameter, _initParamSig ?? (_initParamSig = InitializeParameterTypeSignature))); }
/// <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 void AddToFieldLayout(int offset, TypeDesc fieldType) { if (fieldType.IsGCPointer) { if (offset % _pointerSize != 0) { // Misaligned ORef ThrowFieldLayoutError(offset); } SetFieldLayout(offset, _pointerSize, FieldLayoutTag.ORef); } else if (fieldType.IsPointer || fieldType.IsFunctionPointer) { SetFieldLayout(offset, _pointerSize, FieldLayoutTag.NonORef); } else if (fieldType.IsValueType) { MetadataType mdType = (MetadataType)fieldType; int fieldSize = mdType.InstanceByteCountUnaligned.AsInt; if (!mdType.ContainsGCPointers && !mdType.IsByRefLike) { // Plain value type, mark the entire range as NonORef SetFieldLayout(offset, fieldSize, FieldLayoutTag.NonORef); } else { if (offset % _pointerSize != 0) { // Misaligned struct with GC pointers or ByRef ThrowFieldLayoutError(offset); } List <FieldLayoutInterval> fieldRefMap = new(); MarkByRefAndORefLocations(mdType, fieldRefMap, offset: 0); // Merge in fieldRefMap from structure specifying not attributed intervals as NonORef int lastGCRegionReportedEnd = 0; foreach (var gcRegion in fieldRefMap) { SetFieldLayout(offset + lastGCRegionReportedEnd, gcRegion.Start - lastGCRegionReportedEnd, FieldLayoutTag.NonORef); Debug.Assert(gcRegion.Tag == FieldLayoutTag.ORef || gcRegion.Tag == FieldLayoutTag.ByRef); SetFieldLayout(offset + gcRegion.Start, gcRegion.Size, gcRegion.Tag); lastGCRegionReportedEnd = gcRegion.EndSentinel; } if (fieldRefMap.Count > 0) { int trailingRegionStart = fieldRefMap[fieldRefMap.Count - 1].EndSentinel; int trailingRegionSize = fieldSize - trailingRegionStart; SetFieldLayout(offset + trailingRegionStart, trailingRegionSize, FieldLayoutTag.NonORef); } } } else if (fieldType.IsByRef) { if (offset % _pointerSize != 0) { // Misaligned pointer field ThrowFieldLayoutError(offset); } SetFieldLayout(offset, _pointerSize, FieldLayoutTag.ByRef); } else { Debug.Assert(false, fieldType.ToString()); } }
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> /// Retrieves an existing <see cref="TypeDefinition"/>, <see cref="TypeReference"/>, /// or <see cref="TypeSpecification"/> record representing specified type in the metadata writer object /// model, or creates a new one. /// </summary> public abstract MetadataRecord HandleType(Cts.TypeDesc type);
/// <summary> /// Parses the string '<paramref name="name"/>' and returns the type corresponding to the parsed type name. /// The type name string should be in the 'SerString' format as defined by the ECMA-335 standard. /// </summary> public static TypeDesc GetTypeByCustomAttributeTypeName(this ModuleDesc module, string name) { TypeDesc loadedType; StringBuilder genericTypeDefName = new StringBuilder(name.Length); var ch = name.Begin(); var nameEnd = name.End(); for (; ch < nameEnd; ++ch) { // Always pass escaped characters through. if (ch.Current == '\\') { genericTypeDefName.Append(ch.Current); ++ch; if (ch < nameEnd) { genericTypeDefName.Append(ch.Current); } continue; } // The type def name ends if // The start of a generic argument list if (ch.Current == '[') { break; } // Indication that the type is a pointer if (ch.Current == '*') { break; } // Indication that the type is a reference if (ch.Current == '&') { break; } // A comma that indicates that the rest of the name is an assembly reference if (ch.Current == ',') { break; } genericTypeDefName.Append(ch.Current); } ModuleDesc homeModule = module; AssemblyName homeAssembly = FindAssemblyIfNamePresent(name); if (homeAssembly != null) { homeModule = module.Context.ResolveAssembly(homeAssembly); } MetadataType typeDef = ResolveCustomAttributeTypeNameToTypeDesc(genericTypeDefName.ToString(), homeModule); ArrayBuilder <TypeDesc> genericArgs = new ArrayBuilder <TypeDesc>(); // Followed by generic instantiation parameters (but check for the array case) if (ch < nameEnd && ch.Current == '[' && (ch + 1) < nameEnd && (ch + 1).Current != ']' && (ch + 1).Current != ',') { ch++; // truncate the '[' var genericInstantiationEnd = ch + ReadTypeArgument(ch, nameEnd, true); // find the end of the instantiation list while (ch < genericInstantiationEnd) { if (ch.Current == ',') { ch++; } int argLen = ReadTypeArgument(ch, name.End(), false); string typeArgName; if (ch.Current == '[') { // This type argument name is stringified, // we need to remove the [] from around it ch++; typeArgName = StringIterator.Substring(ch, ch + (argLen - 2)); ch += argLen - 1; } else { typeArgName = StringIterator.Substring(ch, ch + argLen); ch += argLen; } TypeDesc argType = module.GetTypeByCustomAttributeTypeName(typeArgName); genericArgs.Add(argType); } Debug.Assert(ch == genericInstantiationEnd); ch++; loadedType = typeDef.MakeInstantiatedType(new Instantiation(genericArgs.ToArray())); } else { // Non-generic type loadedType = typeDef; } // At this point the characters following may be any number of * characters to indicate pointer depth while (ch < nameEnd) { if (ch.Current == '*') { loadedType = loadedType.MakePointerType(); } else { break; } ch++; } // Followed by any number of "[]" or "[,*]" pairs to indicate arrays int commasSeen = 0; bool bracketSeen = false; while (ch < nameEnd) { if (ch.Current == '[') { ch++; commasSeen = 0; bracketSeen = true; } else if (ch.Current == ']') { if (!bracketSeen) { break; } ch++; if (commasSeen == 0) { loadedType = loadedType.MakeArrayType(); } else { loadedType = loadedType.MakeArrayType(commasSeen + 1); } bracketSeen = false; } else if (ch.Current == ',') { if (!bracketSeen) { break; } ch++; commasSeen++; } else { break; } } // Followed by at most one & character to indicate a byref. if (ch < nameEnd) { if (ch.Current == '&') { loadedType = loadedType.MakeByRefType(); ch++; } } return(loadedType); }
static public TypeDesc MakePointerType(this TypeDesc type) { return(type.Context.GetPointerType(type)); }
static public TypeDesc MakeArrayType(this TypeDesc type) { return(type.Context.GetArrayType(type)); }
private static bool CanCastGenericParameterTo(this GenericParameterDesc thisType, TypeDesc otherType, StackOverflowProtect protect) { // A boxed variable type can be cast to any of its constraints, or object, if none are specified if (otherType.IsObject) { return(true); } if (thisType.HasNotNullableValueTypeConstraint && otherType.IsWellKnownType(WellKnownType.ValueType)) { return(true); } foreach (var typeConstraint in thisType.TypeConstraints) { if (typeConstraint.CanCastToInternal(otherType, protect)) { return(true); } } return(false); }
public CastingPair(TypeDesc fromType, TypeDesc toType) { FromType = fromType; ToType = toType; }
static public TypeDesc MakeByRefType(this TypeDesc type) { return(type.Context.GetByRefType(type)); }
public override TypeDesc InstantiateSignature(Instantiation typeInstantiation, Instantiation methodInstantiation) { TypeDesc instantiatedParameterType = this.ParameterType.InstantiateSignature(typeInstantiation, methodInstantiation); return(instantiatedParameterType.Context.GetPointerType(instantiatedParameterType)); }
public override DefType[] ComputeRuntimeInterfaces(TypeDesc _type) { return(_type.BaseType.RuntimeInterfaces); }