/// <summary> /// Initializes a new instance of the <see cref="CilGenericField"/> class. /// </summary> /// <param name="module">The module.</param> /// <param name="genericField">The generic field.</param> /// <param name="signature">The signature.</param> /// <param name="declaringType">Type of the declaring.</param> public CilGenericField(ITypeModule module, RuntimeField genericField, FieldSignature signature, CilGenericType declaringType) : base(module, declaringType) { this.Signature = signature; this.Attributes = genericField.Attributes; //TODO //this.SetAttributes(genericField.CustomAttributes); base.Name = genericField.Name; }
/// <summary> /// Patches the field. /// </summary> /// <param name="typeModule">The type module.</param> /// <param name="enclosingType">Type of the closed.</param> /// <param name="openField">The open field.</param> /// <returns></returns> RuntimeField IGenericTypePatcher.PatchField(ITypeModule typeModule, CilGenericType enclosingType, RuntimeField openField) { var openType = openField.DeclaringType as CilGenericType; var genericArguments = CloseGenericArguments(enclosingType, openType); var patchedType = GetType(openType, genericArguments); if (patchedType == null) { var typeToken = new Token(0xFE000000 | ++typeTokenCounter); var signatureToken = new Token(0xFD000000 | ++signatureTokenCounter); var sigtype = new TypeSigType(signatureToken, CilElementType.Var); var signature = new GenericInstSigType(sigtype, genericArguments); // FIXME: There has got to be a better way to do this... try { patchedType = new CilGenericType(enclosingType.Module, typeToken, openType.BaseGenericType, signature); } catch (Exception) { foreach (var module in typeModule.TypeSystem.TypeModules) { try { patchedType = new CilGenericType(module, typeToken, openType.BaseGenericType, signature); break; } catch (Exception) { ; } } } AddType(patchedType, genericArguments); } foreach (var field in patchedType.Fields) { if (field.Name == openField.Name) { return field; } } throw new MissingFieldException(); }
private CilGenericType GetType(CilGenericType type, SigType[] signature) { // TODO: Look up in typeSpecs first! // FIXME: Do not use a hash based lookup without handling of collision long signatureHash = ComputeSignatureHash(signature); if (typeDictionary.ContainsKey(type.FullName) && typeDictionary[type.FullName].ContainsKey(signatureHash)) { return typeDictionary[type.FullName][signatureHash]; } else { return null; } }
/// <summary> /// Closes the generic arguments. /// </summary> /// <param name="enclosingType">Type of the enclosing.</param> /// <param name="openType">Type of the open.</param> /// <returns></returns> private SigType[] CloseGenericArguments(CilGenericType enclosingType, GenericInstSigType openType) { return CloseGenericArguments(enclosingType.GenericArguments, openType.GenericArguments); }
/// <summary> /// Adds the type. /// </summary> /// <param name="patchedType">The type.</param> /// <param name="signature">The signature.</param> private void AddType(CilGenericType patchedType, SigType[] signature) { (typeSystem.InternalTypeModule as InternalTypeModule).AddType(patchedType); long signatureHash = ComputeSignatureHash(signature); if (!typeDictionary.ContainsKey(patchedType.BaseGenericType.FullName)) { typeDictionary[patchedType.BaseGenericType.FullName] = new Dictionary<long, CilGenericType>(); } typeDictionary[patchedType.BaseGenericType.FullName][signatureHash] = patchedType; }
/// <summary> /// Patches the type. /// </summary> /// <param name="typeModule">The type module.</param> /// <param name="enclosingType">Type of the enclosing.</param> /// <param name="openType">Type of the open.</param> /// <returns></returns> RuntimeType IGenericTypePatcher.PatchType(ITypeModule typeModule, CilGenericType enclosingType, CilGenericType openType) { var genericArguments = CloseGenericArguments(enclosingType, openType); var patchedType = GetType(openType, genericArguments); if (patchedType == null) { var typeToken = new Token(0xFE000000 | ++typeTokenCounter); var signatureToken = new Token(0xFD000000 | ++signatureTokenCounter); var sigtype = new TypeSigType(signatureToken, CilElementType.Var); var signature = new GenericInstSigType(sigtype, genericArguments); patchedType = new CilGenericType(enclosingType.InstantiationModule, typeToken, openType.BaseGenericType, signature); AddType(patchedType, genericArguments); } return patchedType; }
/// <summary> /// Patches the method. /// </summary> /// <param name="typeModule">The type module.</param> /// <param name="enclosingType">Type of the enclosing.</param> /// <param name="openMethod">The open method.</param> /// <returns></returns> RuntimeMethod IGenericTypePatcher.PatchMethod(ITypeModule typeModule, CilGenericType enclosingType, RuntimeMethod openMethod) { var openType = openMethod.DeclaringType as CilGenericType; var genericArguments = CloseGenericArguments(enclosingType, openType); var patchedType = GetType(openType, genericArguments); if (patchedType == null) { var typeToken = new Token(0xFE000000 | ++typeTokenCounter); var signatureToken = new Token(0xFD000000 | ++signatureTokenCounter); var sigtype = new TypeSigType(signatureToken, CilElementType.Var); var signature = new GenericInstSigType(sigtype, genericArguments); patchedType = new CilGenericType(enclosingType.InstantiationModule, typeToken, openType.BaseGenericType, signature); AddType(patchedType, genericArguments); } var methodIndex = GetMethodIndex(openMethod); return patchedType.Methods[methodIndex]; }
/// <summary> /// Visitation function for Newobj instruction. /// </summary> /// <param name="context">The context.</param> void CIL.ICILVisitor.Newobj(Context context) { Operand thisReference = context.Result; Debug.Assert(thisReference != null, @"Newobj didn't specify class signature?"); RuntimeType classType = null; if (thisReference.Type is ClassSigType) { var classSigType = thisReference.Type as ClassSigType; classType = typeModule.GetType(classSigType.Token); } else if (thisReference.Type is GenericInstSigType) { var genericInstSigType = thisReference.Type as GenericInstSigType; var baseSigType = genericInstSigType.BaseType as ValueTypeSigType; classType = typeModule.GetType(baseSigType.Token); } if (classType.ContainsOpenGenericParameters) { if (!(classType is CilGenericType)) classType = new CilGenericType(classType.Module, classType.Token, classType, thisReference.Type as GenericInstSigType); classType = methodCompiler.Compiler.GenericTypePatcher.PatchType(this.typeModule, methodCompiler.Method.DeclaringType as CilGenericType, classType as CilGenericType); } List<Operand> ctorOperands = new List<Operand>(context.Operands); RuntimeMethod ctorMethod = context.InvokeTarget; if (!ReplaceWithInternalCall(context, ctorMethod)) { Context before = context.InsertBefore(); before.SetInstruction(IRInstruction.Nop); ReplaceWithVmCall(before, VmCall.AllocateObject); Operand methodTableSymbol = GetMethodTableSymbol(classType); before.SetOperand(1, methodTableSymbol); before.SetOperand(2, Operand.CreateConstant(BuiltInSigType.Int32, typeLayout.GetTypeSize(classType))); before.OperandCount = 2; before.Result = thisReference; // Result is the this pointer, now invoke the real constructor Operand symbolOperand = Operand.CreateSymbolFromMethod(ctorMethod); ctorOperands.Insert(0, thisReference); ProcessInvokeInstruction(context, symbolOperand, null, ctorOperands); } }
RuntimeType ITypeSystem.ResolveGenericType(ITypeModule typeModule, TypeSpecSignature typeSpecSignature, Token token) { var genericInstSigType = typeSpecSignature.Type as GenericInstSigType; if (genericInstSigType == null) return null; RuntimeType genericType = null; SigType sigType = genericInstSigType; switch (genericInstSigType.Type) { case CilElementType.ValueType: goto case CilElementType.Class; case CilElementType.Class: TypeSigType typeSigType = (TypeSigType)sigType; genericType = typeModule.GetType(typeSigType.Token); break; case CilElementType.GenericInst: var genericBaseType = typeModule.GetType(genericInstSigType.BaseType.Token); genericType = new CilGenericType(typeModule, token, genericBaseType, genericInstSigType); break; default: throw new NotSupportedException(String.Format(@"LoadTypeSpecs does not support CilElementType.{0}", genericInstSigType.Type)); } return genericType; }
/// <summary> /// Patches the field. /// </summary> /// <param name="typeModule">The type module.</param> /// <param name="enclosingType">Type of the closed.</param> /// <param name="openField">The open field.</param> /// <returns></returns> RuntimeField IGenericTypePatcher.PatchField(ITypeModule typeModule, CilGenericType enclosingType, RuntimeField openField) { var openType = openField.DeclaringType as CilGenericType; var genericArguments = CloseGenericArguments(enclosingType, openType); var patchedType = GetPatchedType(openType, genericArguments); if (patchedType == null) { var typeToken = new Token(0xFE000000 | ++typeTokenCounter); var signatureToken = new Token(0xFD000000 | ++signatureTokenCounter); var sigtype = new TypeSigType(signatureToken, CilElementType.Var); var signature = new GenericInstSigType(sigtype, genericArguments); patchedType = new CilGenericType(enclosingType.InstantiationModule, typeToken, openType.BaseGenericType, signature); AddPatchedType(openType, genericArguments, patchedType); } foreach (var field in patchedType.Fields) { if (field.Name == openField.Name) { return field; } } throw new MissingFieldException(); }
public GenericEntry(CilGenericType openType, SigType[] genericArguments, CilGenericType patchedType) { this.openType = openType; this.genericArguments = genericArguments; this.patchedType = patchedType; }
/// <summary> /// Gets the type. /// </summary> /// <param name="openType">Type of the open.</param> /// <param name="genericArguments">The generic arguments.</param> /// <returns></returns> private CilGenericType GetPatchedType(CilGenericType openType, SigType[] genericArguments) { foreach (var genericEntry in patchedTypes) { if (genericEntry.openType == openType && CompareSignatures(genericEntry.genericArguments, genericArguments)) return genericEntry.patchedType; } return null; }
/// <summary> /// Adds the type. /// </summary> /// <param name="patchedType">The type.</param> /// <param name="signature">The signature.</param> private void AddPatchedType(CilGenericType openType, SigType[] signature, CilGenericType patchedType) { (typeSystem.InternalTypeModule as InternalTypeModule).AddType(patchedType); GenericEntry genericEntry = new GenericEntry(openType, signature, patchedType); patchedTypes.Add(genericEntry); }