Пример #1
0
        /// <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;
        }
Пример #2
0
        /// <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();
        }
Пример #3
0
        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;
            }
        }
Пример #4
0
 /// <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);
 }
Пример #5
0
        /// <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;
        }
Пример #6
0
        /// <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;
        }
Пример #7
0
        /// <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);
            }
        }
Пример #9
0
        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;
        }
Пример #10
0
        /// <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();
        }
Пример #11
0
 public GenericEntry(CilGenericType openType, SigType[] genericArguments, CilGenericType patchedType)
 {
     this.openType = openType;
     this.genericArguments = genericArguments;
     this.patchedType = patchedType;
 }
Пример #12
0
        /// <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;
        }
Пример #13
0
        /// <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);
        }