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; } }
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; } }
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; } }
public ABIParameterInfo(ABIParameterInfoKind kind, TypeRef coerceType) { if (kind != ABIParameterInfoKind.Coerced) throw new ArgumentException("kind"); Kind = kind; CoerceType = coerceType; }
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; }
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); }
/// <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"); }
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; }
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); }
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); }
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); }
public ABIParameterInfo(ABIParameterInfoKind kind) { Kind = kind; CoerceType = TypeRef.Empty; }
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; }