Example #1
0
        public Function(Type declaringType, MethodReference methodReference, TypeRef functionType, ValueRef generatedValue, FunctionSignature signature)
        {
            Signature = signature;
            DeclaringType = declaringType;
            MethodReference = methodReference;
            FunctionType = functionType;
            GeneratedValue = generatedValue;
            VirtualSlot = -1;

            MethodDefinition = methodReference.Resolve();

            ParameterTypes = signature.ParameterTypes.Select(x => x.Type).ToArray();

            // Generate function type when being called from vtable/IMT (if it applies)
            // If declaring type is a value type, needs to unbox "this" for virtual method
            if (DeclaringType.TypeDefinitionCecil.IsValueType
                && (MethodDefinition.Attributes & MethodAttributes.Virtual) != 0)
            {
                bool hasStructValueReturn = signature.ReturnType.ABIParameterInfo.Kind == ABIParameterInfoKind.Indirect;

                // Create function type with boxed "this"
                var argumentCount = LLVM.CountParamTypes(FunctionType);
                var argumentTypes = new TypeRef[argumentCount];
                LLVM.GetParamTypes(FunctionType, argumentTypes);
                // Change first type to boxed "this"
                var thisIndex = hasStructValueReturn ? 1 : 0;
                argumentTypes[thisIndex] = LLVM.PointerType(DeclaringType.ObjectTypeLLVM, 0);
                VirtualFunctionType = LLVM.FunctionType(LLVM.GetReturnType(FunctionType), argumentTypes, LLVM.IsFunctionVarArg(FunctionType));
            }
            else
            {
                VirtualFunctionType = FunctionType;
            }
        }
Example #2
0
        public Type(TypeReference typeReference, TypeDefinition typeDefinition, TypeRef dataType, TypeRef valueType, TypeRef objectType, StackValueType stackType)
        {
            TypeReferenceCecil = typeReference;
            TypeDefinitionCecil = typeDefinition;
            DataTypeLLVM = dataType;
            ObjectTypeLLVM = objectType;
            StackType = stackType;
            ValueTypeLLVM = valueType;
            DefaultTypeLLVM = stackType == StackValueType.Object ? LLVM.PointerType(ObjectTypeLLVM, 0) : DataTypeLLVM;

            switch (stackType)
            {
                case StackValueType.NativeInt:
                    TypeOnStackLLVM = LLVM.PointerType(LLVM.Int8TypeInContext(LLVM.GetTypeContext(dataType)), 0);
                    break;
                case StackValueType.Float:
                    TypeOnStackLLVM = LLVM.DoubleTypeInContext(LLVM.GetTypeContext(dataType));
                    break;
                case StackValueType.Int32:
                    TypeOnStackLLVM = LLVM.Int32TypeInContext(LLVM.GetTypeContext(dataType));
                    break;
                case StackValueType.Int64:
                    TypeOnStackLLVM = LLVM.Int64TypeInContext(LLVM.GetTypeContext(dataType));
                    break;
                case StackValueType.Value:
                case StackValueType.Object:
                case StackValueType.Reference:
                    TypeOnStackLLVM = DefaultTypeLLVM;
                    break;
            }
        }
Example #3
0
        public Type(TypeReference typeReference, TypeRef dataType, TypeRef objectType, StackValueType stackType)
        {
            TypeReference = typeReference;
            DataType = dataType;
            ObjectType = objectType;
            StackType = stackType;
            DefaultType = stackType == StackValueType.Object ? LLVM.PointerType(ObjectType, 0) : DataType;
            StackType = stackType;

            switch (stackType)
            {
                case StackValueType.NativeInt:
                    TypeOnStack = LLVM.PointerType(LLVM.Int8TypeInContext(LLVM.GetTypeContext(dataType)), 0);
                    break;
                case StackValueType.Float:
                    TypeOnStack = LLVM.DoubleTypeInContext(LLVM.GetTypeContext(dataType));
                    break;
                case StackValueType.Int32:
                    TypeOnStack = LLVM.Int32TypeInContext(LLVM.GetTypeContext(dataType));
                    break;
                case StackValueType.Int64:
                    TypeOnStack = LLVM.Int64TypeInContext(LLVM.GetTypeContext(dataType));
                    break;
                case StackValueType.Value:
                case StackValueType.Object:
                case StackValueType.Reference:
                    TypeOnStack = DefaultType;
                    break;
            }
        }
Example #4
0
        public ABIParameterInfo(ABIParameterInfoKind kind, TypeRef coerceType)
        {
            if (kind != ABIParameterInfoKind.Coerced)
                throw new ArgumentException("kind");

            Kind = kind;
            CoerceType = coerceType;
        }
Example #5
0
 public Function(Type declaringType, MethodReference methodReference, TypeRef functionType, ValueRef generatedValue, Type returnType, Type[] parameterTypes)
 {
     Signature = new FunctionSignature(returnType, parameterTypes);
     DeclaringType = declaringType;
     MethodReference = methodReference;
     FunctionType = functionType;
     GeneratedValue = generatedValue;
     VirtualSlot = -1;
 }
Example #6
0
        private FunctionSignature CreateFunctionSignature(MethodReference context, CallSite callSite)
        {
            var numParams = callSite.Parameters.Count;
            if (callSite.HasThis)
                numParams++;
            var parameterTypes = new Type[numParams];
            var parameterTypesLLVM = new TypeRef[numParams];
            for (int index = 0; index < numParams; index++)
            {
                TypeReference parameterTypeReference;
                var parameter = callSite.Parameters[index];
                parameterTypeReference = ResolveGenericsVisitor.Process(context, parameter.ParameterType);
                var parameterType = CreateType(parameterTypeReference);
                if (parameterType.DefaultType.Value == IntPtr.Zero)
                    throw new InvalidOperationException();
                parameterTypes[index] = parameterType;
                parameterTypesLLVM[index] = parameterType.DefaultType;
            }

            var returnType = CreateType(ResolveGenericsVisitor.Process(context, context.ReturnType));

            return new FunctionSignature(returnType, parameterTypes);
        }
Example #7
0
        /// <summary>
        /// Creates the function.
        /// </summary>
        /// <param name="method">The method.</param>
        /// <returns></returns>
        Function CreateFunction(MethodReference method)
        {
            Function function;
            if (functions.TryGetValue(method, out function))
                return function;

            var numParams = method.Parameters.Count;
            if (method.HasThis)
                numParams++;
            var parameterTypes = new Type[numParams];
            var parameterTypesLLVM = new TypeRef[numParams];
            var declaringType = CreateType(ResolveGenericsVisitor.Process(method, method.DeclaringType));
            for (int index = 0; index < numParams; index++)
            {
                TypeReference parameterTypeReference;
                if (method.HasThis && index == 0)
                {
                    parameterTypeReference = declaringType.TypeReference;

                    // Value type uses ByReference type for this
                    if (parameterTypeReference.IsValueType)
                        parameterTypeReference = parameterTypeReference.MakeByReferenceType();
                }
                else
                {
                    var parameter = method.Parameters[method.HasThis ? index - 1 : index];
                    parameterTypeReference = ResolveGenericsVisitor.Process(method, parameter.ParameterType);
                }
                var parameterType = CreateType(parameterTypeReference);
                if (parameterType.DefaultType.Value == IntPtr.Zero)
                    throw new InvalidOperationException();
                parameterTypes[index] = parameterType;
                parameterTypesLLVM[index] = parameterType.DefaultType;
            }

            var returnType = CreateType(ResolveGenericsVisitor.Process(method, method.ReturnType));

            // Generate function global
            bool isExternal = method.DeclaringType.Resolve().Module.Assembly != assembly;
            var methodMangledName = Regex.Replace(method.FullName, @"(\W)", "_");
            var functionType = LLVM.FunctionType(returnType.DefaultType, parameterTypesLLVM, false);

            var resolvedMethod = method.Resolve();
            var hasDefinition = resolvedMethod != null
                && (resolvedMethod.HasBody
                    || ((resolvedMethod.ImplAttributes & (MethodImplAttributes.InternalCall | MethodImplAttributes.Runtime)) != 0));
            var functionGlobal = hasDefinition
                ? LLVM.AddFunction(module, methodMangledName, functionType)
                : LLVM.ConstPointerNull(LLVM.PointerType(functionType, 0));

            function = new Function(declaringType, method, functionType, functionGlobal, returnType, parameterTypes);
            functions.Add(method, function);

            if (hasDefinition)
            {
                if (isExternal)
                {
                    // External weak linkage
                    LLVM.SetLinkage(functionGlobal, Linkage.ExternalWeakLinkage);
                }
                else
                {
                    // Need to compile
                    EmitFunction(function);
                }
            }

            return function;
        }
        public void InitializeCommonTypes()
        {
            // Load runtime
            runtimeModule = LoadModule(context, LocateRuntimeModule(triple));

            // Load data layout from runtime
            var dataLayout = LLVM.GetDataLayout(runtimeModule);
            targetData = LLVM.CreateTargetData(dataLayout);

            // Initialize LLVM types
            intPtrLLVM = LLVM.PointerType(LLVM.Int8TypeInContext(context), 0);
            int32LLVM = LLVM.Int32TypeInContext(context);
            int64LLVM = LLVM.Int64TypeInContext(context);
            intPtrSize = (int)LLVM.ABISizeOfType(targetData, intPtrLLVM);
            nativeIntLLVM = LLVM.IntTypeInContext(context, (uint)intPtrSize * 8);

            // Prepare system types, for easier access
            intPtr = GetType(corlib.MainModule.GetType(typeof(IntPtr).FullName), TypeState.StackComplete);
            int8 = GetType(corlib.MainModule.GetType(typeof(sbyte).FullName), TypeState.StackComplete);
            int16 = GetType(corlib.MainModule.GetType(typeof(short).FullName), TypeState.StackComplete);
            int32 = GetType(corlib.MainModule.GetType(typeof(int).FullName), TypeState.StackComplete);
            int64 = GetType(corlib.MainModule.GetType(typeof(long).FullName), TypeState.StackComplete);
            uint8 = GetType(corlib.MainModule.GetType(typeof(byte).FullName), TypeState.StackComplete);
            uint16 = GetType(corlib.MainModule.GetType(typeof(ushort).FullName), TypeState.StackComplete);
            uint32 = GetType(corlib.MainModule.GetType(typeof(uint).FullName), TypeState.StackComplete);
            uint64 = GetType(corlib.MainModule.GetType(typeof(ulong).FullName), TypeState.StackComplete);
            @bool = GetType(corlib.MainModule.GetType(typeof(bool).FullName), TypeState.StackComplete);
            @float = GetType(corlib.MainModule.GetType(typeof(float).FullName), TypeState.StackComplete);
            @double = GetType(corlib.MainModule.GetType(typeof(double).FullName), TypeState.StackComplete);
            @char = GetType(corlib.MainModule.GetType(typeof(char).FullName), TypeState.StackComplete);
            @object = GetType(corlib.MainModule.GetType(typeof(object).FullName), TypeState.StackComplete);
            @void = GetType(corlib.MainModule.GetType(typeof(void).FullName), TypeState.StackComplete);

            // struct IMTEntry { i8* interfaceFunctionPtr, i8* functionPtr }
            imtEntryLLVM = LLVM.StructCreateNamed(context, "IMTEntry");
            LLVM.StructSetBody(imtEntryLLVM, new[] { intPtrLLVM, intPtrLLVM }, false);

            // struct CaughtResultType { i8*, i32 }
            caughtResultLLVM = LLVM.StructCreateNamed(context, "CaughtResultType");
            LLVM.StructSetBody(caughtResultLLVM, new[] { intPtrLLVM, int32LLVM }, false);

            // Prepare types used to emit metadata and reflection
            if (!TestMode)
            {
                sharpLangTypeType = GetType(corlib.MainModule.GetType("System.SharpLangType"), TypeState.StackComplete);
                sharpLangModuleType = GetType(corlib.MainModule.GetType("System.SharpLangModule"), TypeState.StackComplete);
            }
            else
            {
                sharpLangTypeType = intPtr;
                sharpLangModuleType = intPtr;
            }

            // struct TypeDef { SharpLangModule*, i32 }
            typeDefLLVM = LLVM.StructCreateNamed(context, "TypeDef");
            LLVM.StructSetBody(typeDefLLVM, new[] { sharpLangModuleType.DefaultTypeLLVM, int32LLVM }, false);

            // Import runtime methods
            allocObjectFunctionLLVM = ImportRuntimeFunction(module, "allocObject");
            resolveInterfaceCallFunctionLLVM = ImportRuntimeFunction(module, "resolveInterfaceCall");
            isInstInterfaceFunctionLLVM = ImportRuntimeFunction(module, "isInstInterface");
            throwExceptionFunctionLLVM = ImportRuntimeFunction(module, "throwException");
            sharpPersonalityFunctionLLVM = ImportRuntimeFunction(module, "sharpPersonality");
            pinvokeLoadLibraryFunctionLLVM = ImportRuntimeFunction(module, "PInvokeOpenLibrary");
            pinvokeGetProcAddressFunctionLLVM = ImportRuntimeFunction(module, "PInvokeGetProcAddress");
        }
Example #9
0
        private ValueRef ConvertToInt(ValueRef value, TypeRef intTypeLLVM)
        {
            var valueType = LLVM.TypeOf(value);

            // NatveInt: cast to integer
            if (LLVM.GetTypeKind(valueType) == TypeKind.PointerTypeKind)
                return LLVM.BuildPtrToInt(builder, value, intTypeLLVM, string.Empty);

            // Integer of different size: cast
            if (valueType != intTypeLLVM)
                return LLVM.BuildIntCast(builder, value, intTypeLLVM, string.Empty);

            // Otherwise, return as is
            return value;
        }
Example #10
0
        private void EmitStaticInvokeCall(ValueRef invokeMethodHelper)
        {
            // Get Delegate type and _methodPtrAux field
            var delegateType = corlib.MainModule.GetType(typeof(Delegate).FullName);
            var methodPtrAuxField = delegateType.Fields.First(x => x.Name == "_methodPtrAux");

            var invokeFunctionType = LLVM.GetElementType(LLVM.TypeOf(invokeMethodHelper));

            // Ignore first arguments
            var helperArgs = new ValueRef[LLVM.CountParams(invokeMethodHelper) - 1];
            var helperArgTypes = new TypeRef[helperArgs.Length];
            for (int i = 0; i < helperArgs.Length; ++i)
            {
                helperArgs[i] = LLVM.GetParam(invokeMethodHelper, (uint)i + 1);
                helperArgTypes[i] = LLVM.TypeOf(helperArgs[i]);
            }
            var helperFunctionType = LLVM.FunctionType(LLVM.GetReturnType(invokeFunctionType), helperArgTypes, false);

            // 1. Load static function pointers (arg0->_methodPtrAux)
            var @this = LLVM.GetParam(invokeMethodHelper, 0);

            // Compute field address
            var instructionFlags = InstructionFlags.None;
            var fieldAddress = ComputeFieldAddress(builder2, GetType(delegateType, TypeState.TypeComplete).Fields[methodPtrAuxField], StackValueType.Object, @this, ref instructionFlags);

            //    Load value from field
            var methodPtrAux = LLVM.BuildLoad(builder2, fieldAddress, string.Empty);
            methodPtrAux = LLVM.BuildPointerCast(builder2, methodPtrAux, LLVM.PointerType(helperFunctionType, 0), string.Empty);

            // 2. Call method
            var methodPtrAuxCall = LLVM.BuildCall(builder2, methodPtrAux, helperArgs, string.Empty);
            LLVM.SetTailCall(methodPtrAuxCall, true);

            // Return value
            if (LLVM.GetReturnType(invokeFunctionType) != LLVM.VoidTypeInContext(context))
                LLVM.BuildRet(builder2, methodPtrAuxCall);
            else
                LLVM.BuildRetVoid(builder2);
        }
Example #11
0
        private void BuildRuntimeType(Class @class)
        {
            if (@class.IsEmitted)
                return;

            @class.IsEmitted = true;

            // Build IMT
            var interfaceMethodTable = new LinkedList<InterfaceMethodTableEntry>[InterfaceMethodTableSize];
            foreach (var @interface in @class.Interfaces)
            {
                foreach (var interfaceMethod in @interface.Type.TypeReference.Resolve().Methods)
                {
                    var resolvedInterfaceMethod = ResolveGenericMethod(@interface.Type.TypeReference, interfaceMethod);

                    // If method is not fully resolved (generic method in interface), ignore it
                    // We are waiting for actual closed uses.
                    if (ResolveGenericsVisitor.ContainsGenericParameters(resolvedInterfaceMethod))
                        continue;

                    var resolvedFunction = CecilExtensions.TryMatchMethod(@class, resolvedInterfaceMethod);
                    if (resolvedFunction == null && @class.Type.TypeReference is ArrayType)
                    {
                        var arrayType = corlib.MainModule.GetType(typeof(Array).FullName);
                        var matchingMethod = (MethodReference)arrayType.Methods.First(x => x.Name.StartsWith("InternalArray_") && x.Name.EndsWith(resolvedInterfaceMethod.Name));
                        if (matchingMethod != null)
                        {
                            if (matchingMethod.HasGenericParameters)
                            {
                                matchingMethod = matchingMethod.MakeGenericMethod(((ArrayType)@class.Type.TypeReference).ElementType);
                            }

                            resolvedFunction = GetFunction(matchingMethod);

                            // Manually emit Array functions locally (until proper mscorlib + generic instantiation exists).
                            EmitFunction(resolvedFunction);
                        }
                    }

                    if (resolvedFunction == null)
                        throw new InvalidOperationException(string.Format("Could not find matching method for {0} in {1}", resolvedInterfaceMethod, @class));

                    var isInterface = resolvedFunction.DeclaringType.TypeReference.Resolve().IsInterface;
                    if (!isInterface && resolvedFunction.MethodReference.Resolve().IsVirtual && resolvedFunction.VirtualSlot != -1)
                    {
                        // We might have found a base virtual method matching this interface method.
                        // Let's get the actual method override for this virtual slot.
                        resolvedFunction = @class.VirtualTable[resolvedFunction.VirtualSlot];
                    }

                    // If method is not found, it could be due to covariance/contravariance
                    if (resolvedFunction == null)
                        throw new InvalidOperationException("Interface method not found");

                    var methodId = GetMethodId(resolvedInterfaceMethod);
                    var imtSlotIndex = (int) (methodId%interfaceMethodTable.Length);

                    var imtSlot = interfaceMethodTable[imtSlotIndex];
                    if (imtSlot == null)
                        interfaceMethodTable[imtSlotIndex] = imtSlot = new LinkedList<InterfaceMethodTableEntry>();

                    imtSlot.AddLast(new InterfaceMethodTableEntry
                    {
                        Function = resolvedFunction,
                        MethodId = methodId,
                        SlotIndex = imtSlotIndex
                    });
                }
            }
            var interfaceMethodTableConstant = LLVM.ConstArray(intPtrType, interfaceMethodTable.Select(imtSlot =>
            {
                if (imtSlot == null)
                {
                    // No entries: null slot
                    return LLVM.ConstNull(intPtrType);
                }

                if (imtSlot.Count == 1)
                {
                    // Single entry
                    var imtEntry = imtSlot.First.Value;
                    return LLVM.ConstPointerCast(imtEntry.Function.GeneratedValue, intPtrType);
                }
                else
                {
                    // Multiple entries, create IMT array with all entries
                    // TODO: Support covariance/contravariance?
                    var imtEntries = LLVM.ConstArray(imtEntryType, imtSlot.Select(imtEntry =>
                    {
                        return LLVM.ConstNamedStruct(imtEntryType, new[]
                        {
                            LLVM.ConstInt(int32Type, (ulong) imtEntry.MethodId, false), // i32 functionId
                            LLVM.ConstPointerCast(imtEntry.Function.GeneratedValue, intPtrType), // i8* functionPtr
                        });
                    })
                        .Concat(Enumerable.Repeat(LLVM.ConstNull(imtEntryType), 1)).ToArray()); // Append { 0, 0 } terminator
                    var imtEntryGlobal = LLVM.AddGlobal(module, LLVM.TypeOf(imtEntries), @class.Type.TypeReference.MangledName() + ".imt");
                    LLVM.SetInitializer(imtEntryGlobal, imtEntries);

                    // Add 1 to differentiate between single entry and IMT array
                    return LLVM.ConstIntToPtr(
                        LLVM.ConstAdd(
                            LLVM.ConstPtrToInt(imtEntryGlobal, nativeIntType),
                            LLVM.ConstInt(nativeIntType, 1, false)),
                        intPtrType);
                }
            }).ToArray());


            // Build list of super types
            var superTypes = new List<Class>(@class.Depth);
            var currentClass = @class;
            while (currentClass != null)
            {
                superTypes.Add(currentClass);
                currentClass = currentClass.BaseType;
            }

            // Reverse so that the list start with most inherited object
            // (allows faster type checking since a given type will always be at a given index)
            superTypes.Reverse();

            // Build super types
            // Helpful for fast is/as checks on class hierarchy
            var superTypeCount = LLVM.ConstInt(int32Type, (ulong) @class.Depth + 1, false);
            var interfacesCount = LLVM.ConstInt(int32Type, (ulong) @class.Interfaces.Count, false);

            var zero = LLVM.ConstInt(int32Type, 0, false);

            // Super types global
            var superTypesConstantGlobal = LLVM.AddGlobal(module, LLVM.ArrayType(intPtrType, (uint) superTypes.Count),
                @class.Type.TypeReference.MangledName() + ".supertypes");
            var superTypesGlobal = LLVM.ConstInBoundsGEP(superTypesConstantGlobal, new[] {zero, zero});

            // Interface map global
            var interfacesConstantGlobal = LLVM.AddGlobal(module, LLVM.ArrayType(intPtrType, (uint) @class.Interfaces.Count),
                @class.Type.TypeReference.MangledName() + ".interfaces");
            var interfacesGlobal = LLVM.ConstInBoundsGEP(interfacesConstantGlobal, new[] {zero, zero});

            // Build VTable
            var vtableConstant = LLVM.ConstStructInContext(context, @class.VirtualTable.Select(x => x.GeneratedValue).ToArray(), false);

            // Build RTTI
            var runtimeTypeInfoGlobal = @class.GeneratedRuntimeTypeInfoGlobal;
            var runtimeTypeInfoType = LLVM.GetElementType(LLVM.TypeOf(runtimeTypeInfoGlobal));
            var runtimeTypeInfoTypeElements = new TypeRef[LLVM.CountStructElementTypes(runtimeTypeInfoType)];
            LLVM.GetStructElementTypes(runtimeTypeInfoType, runtimeTypeInfoTypeElements);
            var runtimeTypeInfoConstant = LLVM.ConstNamedStruct(runtimeTypeInfoType, new[]
            {
                @class.BaseType != null ? @class.BaseType.GeneratedRuntimeTypeInfoGlobal : LLVM.ConstPointerNull(intPtrType),
                superTypeCount,
                interfacesCount,
                superTypesGlobal,
                interfacesGlobal,
                LLVM.ConstInt(LLVM.Int1TypeInContext(context), 0, false), // Class initialized?
                interfaceMethodTableConstant,
                vtableConstant,
                LLVM.ConstNull(runtimeTypeInfoTypeElements[(int)RuntimeTypeInfoFields.StaticFields]),
            });
            LLVM.SetInitializer(runtimeTypeInfoGlobal, runtimeTypeInfoConstant);

            // Build super type list (after RTTI since we need pointer to RTTI)
            var superTypesConstant = LLVM.ConstArray(intPtrType,
                superTypes.Select(superType => LLVM.ConstPointerCast(superType.GeneratedRuntimeTypeInfoGlobal, intPtrType))
                    .ToArray());
            LLVM.SetInitializer(superTypesConstantGlobal, superTypesConstant);

            // Build interface map
            var interfacesConstant = LLVM.ConstArray(intPtrType,
                @class.Interfaces.Select(
                    @interface => LLVM.ConstPointerCast(@interface.GeneratedRuntimeTypeInfoGlobal, intPtrType)).ToArray());
            LLVM.SetInitializer(interfacesConstantGlobal, interfacesConstant);

            // Mark RTTI as external
            LLVM.SetLinkage(runtimeTypeInfoGlobal, Linkage.ExternalLinkage);
        }
Example #12
0
        private TypeRef CreateFunctionTypeLLVM(FunctionSignature functionSignature)
        {
            // Some extra arguments might be preprended:
            //  - Return value pointer if struct returned by value
            //  - "this" if a class
            bool hasStructValueReturn = functionSignature.ReturnType.ABIParameterInfo.Kind == ABIParameterInfoKind.Indirect;

            var numParams = functionSignature.ParameterTypes.Length;
            var firstArgumentIndex = 0;
            if (hasStructValueReturn)
                firstArgumentIndex++;

            var parameterTypesLLVM = new TypeRef[numParams + (hasStructValueReturn ? 1 : 0)];

            for (int index = 0; index < parameterTypesLLVM.Length; index++)
            {
                FunctionParameterType parameterType;
                if (hasStructValueReturn && index == 0)
                {
                    parameterType = functionSignature.ReturnType;
                }
                else
                {
                    parameterType = functionSignature.ParameterTypes[index - firstArgumentIndex];
                }

                if (parameterType.Type.DefaultTypeLLVM.Value == IntPtr.Zero)
                    throw new InvalidOperationException();

                parameterTypesLLVM[index] = GetFunctionInputParameterTypeLLVM(parameterType);
            }

            return LLVM.FunctionType(hasStructValueReturn ? LLVM.VoidTypeInContext(context) : GetFunctionInputParameterTypeLLVM(functionSignature.ReturnType), parameterTypesLLVM, false);
        }
Example #13
0
 public ABIParameterInfo(ABIParameterInfoKind kind)
 {
     Kind = kind;
     CoerceType = TypeRef.Empty;
 }
Example #14
0
        private ValueRef GenerateStaticInvokeThunk(Class declaringClass, TypeDefinition delegateType, FieldDefinition methodPtrAuxField)
        {
            // Reuse same signature as Invoke
            var invokeMethod = declaringClass.Functions.Single(x => x.MethodReference.Name == "Invoke");

            // Create method
            var invokeMethodHelper = LLVM.AddFunction(module, LLVM.GetValueName(invokeMethod.GeneratedValue) + "_Helper",
                invokeMethod.FunctionType);
            LLVM.PositionBuilderAtEnd(builder2,
                LLVM.AppendBasicBlockInContext(context, invokeMethodHelper, string.Empty));

            // Ignore first arguments
            var helperArgs = new ValueRef[LLVM.CountParams(invokeMethodHelper) - 1];
            var helperArgTypes = new TypeRef[helperArgs.Length];
            for (int i = 0; i < helperArgs.Length; ++i)
            {
                helperArgs[i] = LLVM.GetParam(invokeMethodHelper, (uint) i + 1);
                helperArgTypes[i] = LLVM.TypeOf(helperArgs[i]);
            }
            var helperFunctionType = LLVM.FunctionType(LLVM.GetReturnType(invokeMethod.FunctionType), helperArgTypes, false);

            // 1. Load static function pointers (arg0->_methodPtrAux)
            var @this = LLVM.GetParam(invokeMethodHelper, 0);
            var indices = BuildFieldIndices(GetClass(delegateType).Fields[methodPtrAuxField], StackValueType.Object, GetType(declaringClass.Type.TypeReference));

            //    Find field address using GEP
            var fieldAddress = LLVM.BuildInBoundsGEP(builder2, @this, indices, string.Empty);

            //    Load value from field
            var methodPtrAux = LLVM.BuildLoad(builder2, fieldAddress, string.Empty);
            methodPtrAux = LLVM.BuildPointerCast(builder2, methodPtrAux, LLVM.PointerType(helperFunctionType, 0), string.Empty);

            // 2. Call method
            var methodPtrAuxCall = LLVM.BuildCall(builder2, methodPtrAux, helperArgs, string.Empty);

            // Return value
            if (LLVM.GetReturnType(invokeMethod.FunctionType) != LLVM.VoidTypeInContext(context))
                LLVM.BuildRet(builder2, methodPtrAuxCall);
            else
                LLVM.BuildRetVoid(builder2);
            return invokeMethodHelper;
        }