private static LLVMValueRef CreateMallocFunction(this FunctionModuleContext moduleContext) { return(moduleContext.Module.AddFunction( "malloc", // TODO: should ideally use the native integer size of the context LLVMTypeRef.FunctionType(moduleContext.LLVMContext.VoidPointerType(), new LLVMTypeRef[] { moduleContext.LLVMContext.Int64Type }, IsVarArg: false))); }
private LLVMValueRef BuildInitializeStateFunction(IEnumerable <LLVMTypeRef> parameterTypes) { LLVMTypeRef initializeStateFunctionType = LLVMTypeRef.FunctionType( SharedData.Context.VoidPointerType(), parameterTypes.ToArray(), false); LLVMValueRef initializeStateFunction = Module.AddFunction(FunctionNames.GetInitializeStateFunctionName(_functionName), initializeStateFunctionType); var builder = SharedData.Context.CreateIRBuilder(); LLVMBasicBlockRef entryBlock = initializeStateFunction.AppendBasicBlock("entry"); builder.PositionBuilderAtEnd(entryBlock); LLVMValueRef statePtr = SharedData.ModuleContext.CreateMalloc(builder, SharedData.AllocationSet.StateType, "statePtr"); CurrentState = new OuterFunctionCompilerState(initializeStateFunction, builder) { StateMalloc = statePtr }; GenerateStoreCompletionState(RuntimeConstants.FunctionNotDoneStatus); InitializeParameterAllocations(initializeStateFunction, builder); LLVMValueRef bitCastStatePtr = builder.CreateBitCast(statePtr, SharedData.Context.VoidPointerType(), "bitCastStatePtr"); builder.CreateRet(bitCastStatePtr); return(initializeStateFunction); }
static LLVMValueRef createMain() { var context = LLVM.GetGlobalContext(); LLVMTypeRef funcType = LLVMTypeRef.FunctionType(LLVMTypeRef.Int64Type(), new LLVMTypeRef[] { }, false); LLVMValueRef function = LLVM.AddFunction(module, "main", funcType); return(function); }
public static LLVMTypeRef PollFunctionType(ContextWrapper context) => LLVMTypeRef.FunctionType( context.VoidType, new LLVMTypeRef[] { context.VoidPointerType(), LLVMTypeRef.PointerType(context.ScheduledTaskFunctionType(), 0u), context.VoidPointerType() }, false);
static ulong GetIntrinsic(string name) { var func = LLVM.GetNamedFunction(Module, name); func = func.Pointer == IntPtr.Zero ? LLVM.AddFunction(Module, name, LLVMTypeRef.FunctionType(LLVMTypeRef.VoidType(), new LLVMTypeRef[0], false)) : func; return((ulong)LLVM.GetPointerToGlobal(ExecutionEngine, func)); }
public AsynchronousFunctionModuleBuilder( FunctionCompilerSharedData sharedData, string functionName, IEnumerable <AsyncStateGroup> asyncStateGroups) : base(sharedData) { _functionName = functionName; _asyncStateGroups = asyncStateGroups; var fireCountFields = new Dictionary <AsyncStateGroup, StateFieldValueSource>(); foreach (AsyncStateGroup asyncStateGroup in _asyncStateGroups) { string groupName = asyncStateGroup.Label; if (asyncStateGroup.MaxFireCount > 1) { fireCountFields[asyncStateGroup] = SharedData.AllocationSet.CreateStateField($"{groupName}FireCount", NITypes.Int32); } } SharedData.AllocationSet.InitializeStateType(sharedData.Module, functionName); LLVMTypeRef groupFunctionType = LLVMTypeRef.FunctionType( SharedData.Context.VoidType, new LLVMTypeRef[] { LLVMTypeRef.PointerType(SharedData.AllocationSet.StateType, 0u) }, false); var functions = new Dictionary <string, LLVMValueRef>(); foreach (AsyncStateGroup asyncStateGroup in _asyncStateGroups) { LLVMValueRef groupFunction; if (!functions.TryGetValue(asyncStateGroup.FunctionId, out groupFunction)) { string groupFunctionName = $"{functionName}::{asyncStateGroup.FunctionId}"; groupFunction = Module.AddFunction(groupFunctionName, groupFunctionType); functions[asyncStateGroup.FunctionId] = groupFunction; } LLVMBasicBlockRef groupBasicBlock = groupFunction.AppendBasicBlock($"{asyncStateGroup.Label}_begin"); LLVMBasicBlockRef continueBasicBlock = asyncStateGroup.IsSkippable ? groupFunction.AppendBasicBlock($"{asyncStateGroup.Label}_continue") : default(LLVMBasicBlockRef); LLVMBasicBlockRef endBasicBlock = asyncStateGroup.IsSkippable ? groupFunction.AppendBasicBlock($"{asyncStateGroup.Label}_end") : default(LLVMBasicBlockRef); StateFieldValueSource fireCountStateField; fireCountFields.TryGetValue(asyncStateGroup, out fireCountStateField); AsyncStateGroups[asyncStateGroup] = new AsyncStateGroupData(asyncStateGroup, SharedData.Context, groupFunction, groupBasicBlock, continueBasicBlock, endBasicBlock, fireCountStateField); } }
public static LLVMTypeRef ToLLVMType(this Type type) { if (type.IsConstructedGenericType && type.GetGenericTypeDefinition() == typeof(Vector128 <>)) { var et = type.GetGenericArguments()[0]; return(LLVMTypeRef.VectorType(et.ToLLVMType(), 16U / (uint)Marshal.SizeOf(et))); } if (typeof(MulticastDelegate).IsAssignableFrom(type)) { var mi = type.GetMethod("Invoke"); return(LLVMTypeRef.FunctionType(mi.ReturnType.ToLLVMType(), mi.GetParameters().Select(x => x.ParameterType.ToLLVMType()).ToArray(), false)); } if (type == typeof(void)) { return(LLVMTypeRef.VoidType()); } if (type.IsPointer) { return(LLVMTypeRef.Int64Type()); } switch (Activator.CreateInstance(type)) { case sbyte _: case byte _: return(LLVMTypeRef.Int8Type()); case short _: case ushort _: return(LLVMTypeRef.Int16Type()); case int _: case uint _: return(LLVMTypeRef.Int32Type()); case long _: case ulong _: return(LLVMTypeRef.Int64Type()); case Int128 _: case UInt128 _: return(LLVMTypeRef.IntType(128)); case float _: return(LLVMTypeRef.FloatType()); case double _: return(LLVMTypeRef.DoubleType()); case bool _: return(LLVMTypeRef.IntType(1)); default: throw new NotSupportedException(type.Name); } }
private static LLVMValueRef BuildDecrementRefCountFunction(FunctionModuleContext moduleContext, string functionName, NIType valueType) { LLVMTypeRef functionType = LLVMTypeRef.FunctionType( moduleContext.LLVMContext.VoidType, new LLVMTypeRef[] { LLVMTypeRef.PointerType(moduleContext.LLVMContext.CreateLLVMRefCountType(moduleContext.LLVMContext.AsLLVMType(valueType)), 0u) }, false); LLVMValueRef decrementRefCountFunction = moduleContext.Module.AddFunction(functionName, functionType); LLVMBasicBlockRef entryBlock = decrementRefCountFunction.AppendBasicBlock("entry"), noRefsRemainingBlock = decrementRefCountFunction.AppendBasicBlock("noRefsRemaining"), endBlock = decrementRefCountFunction.AppendBasicBlock("end"); var builder = moduleContext.LLVMContext.CreateIRBuilder(); builder.PositionBuilderAtEnd(entryBlock); LLVMValueRef refCountObjectPtr = decrementRefCountFunction.GetParam(0u), referenceCountPtr = builder.CreateStructGEP(refCountObjectPtr, 0u, "referenceCountPtr"), one = moduleContext.LLVMContext.AsLLVMValue(1), previousReferenceCount = builder.CreateAtomicRMW( LLVMAtomicRMWBinOp.LLVMAtomicRMWBinOpSub, referenceCountPtr, one, // Since the decrement to the reference count does not have any effect until after we branch, // we only need monotonic ordering here. // See the documentation about atomic orderings here: https://llvm.org/docs/LangRef.html#atomic-memory-ordering-constraints LLVMAtomicOrdering.LLVMAtomicOrderingMonotonic, false), noRefsRemaining = builder.CreateICmp(LLVMIntPredicate.LLVMIntEQ, previousReferenceCount, one, "noRefsRemaining"); builder.CreateCondBr(noRefsRemaining, noRefsRemainingBlock, endBlock); builder.PositionBuilderAtEnd(noRefsRemainingBlock); moduleContext.CreateDropCallIfDropFunctionExists(builder, valueType, b => b.CreateStructGEP(refCountObjectPtr, 1u, "valuePtr")); builder.CreateFree(refCountObjectPtr); builder.CreateBr(endBlock); builder.PositionBuilderAtEnd(endBlock); builder.CreateRetVoid(); return(decrementRefCountFunction); }
private static LLVMTypeRef GetLlvmType([NotNull] Type lambdaTypeParam) { switch (lambdaTypeParam) { case PrimaryType primaryType: if (string.Equals(primaryType.Name, "f64", Ordinal)) { return(LLVMSharp.LLVM.DoubleType()); } if (string.Equals(primaryType.Name, "f32", Ordinal)) { return(LLVMTypeRef.FloatType()); } if (string.Equals(primaryType.Name, "i8", Ordinal)) { return(LLVMTypeRef.Int8Type()); } if (string.Equals(primaryType.Name, "i16", Ordinal)) { return(LLVMTypeRef.Int16Type()); } if (string.Equals(primaryType.Name, "i32", Ordinal)) { return(LLVMTypeRef.Int32Type()); } if (string.Equals(primaryType.Name, "i64", Ordinal)) { return(LLVMTypeRef.Int64Type()); } break; case LambdaType lambdaType: return(LLVMTypeRef.FunctionType(GetLlvmType(lambdaType.RetType), (from type in lambdaType.ParamsList select GetLlvmType(type)).ToArray(), false)); case SecondaryType secondaryType: break; } throw new NotImplementedException(); }
private static LLVMValueRef CreateVectorGrowFunction(FunctionModuleContext moduleContext, string functionName, NIType elementType) { LLVMTypeRef elementLLVMType = moduleContext.LLVMContext.AsLLVMType(elementType); LLVMTypeRef vectorGrowFunctionType = LLVMTypeRef.FunctionType( moduleContext.LLVMContext.VoidType, new LLVMTypeRef[] { LLVMTypeRef.PointerType(moduleContext.LLVMContext.CreateLLVMVectorType(elementLLVMType), 0u), }, false); LLVMValueRef vectorGrowFunction = moduleContext.Module.AddFunction(functionName, vectorGrowFunctionType); LLVMBasicBlockRef entryBlock = vectorGrowFunction.AppendBasicBlock("entry"); var builder = moduleContext.LLVMContext.CreateIRBuilder(); builder.PositionBuilderAtEnd(entryBlock); LLVMValueRef vectorPtr = vectorGrowFunction.GetParam(0u), vector = builder.CreateLoad(vectorPtr, "vector"), oldAllocationPtr = builder.CreateExtractValue(vector, 0u, "oldAllocationPtr"), oldVectorCapacity = builder.CreateExtractValue(vector, 2u, "oldVectorCapacity"), // TODO: ideally handle integer overflow; also there are ways this could be smarter newVectorCapacity = builder.CreateMul(oldVectorCapacity, moduleContext.LLVMContext.AsLLVMValue(2), "newVectorCapacity"), // TODO: handle the case where the allocation fails newAllocationPtr = moduleContext.CreateArrayMalloc(builder, elementLLVMType, newVectorCapacity, "newAllocationPtr"), oldVectorCapacityExtend = builder.CreateSExt(oldVectorCapacity, moduleContext.LLVMContext.Int64Type, "oldVectorCapacityExtend"), bytesToCopy = builder.CreateMul(oldVectorCapacityExtend, elementLLVMType.SizeOf(), "bytesToCopy"); moduleContext.CreateCallToCopyMemory(builder, newAllocationPtr, oldAllocationPtr, bytesToCopy); LLVMValueRef newVector0 = builder.CreateInsertValue(vector, newAllocationPtr, 0u, "newVector0"), newVector = builder.CreateInsertValue(newVector0, newVectorCapacity, 2u, "newVector"); builder.CreateStore(newVector, vectorPtr); builder.CreateFree(oldAllocationPtr); builder.CreateRetVoid(); return(vectorGrowFunction); }
private static void declareCFunctions() { LLVMTypeRef PutCharType = LLVMTypeRef.FunctionType(LLVM.Int32Type(), new LLVMTypeRef[] { LLVM.Int32Type() }, false); LLVM.AddFunction(module, "putchar", PutCharType); }
public static LLVMTypeRef ScheduledTaskFunctionType(this ContextWrapper context) => LLVMTypeRef.FunctionType(context.VoidType, new[] { context.VoidPointerType() }, false);
private static LLVMTypeRef MethodPollFunctionType(this ContextWrapper context) => LLVMTypeRef.FunctionType( context.VoidType, new LLVMTypeRef[] { context.VoidPointerType(), LLVMTypeRef.PointerType(context.ScheduledTaskFunctionType(), 0u), context.VoidPointerType() }, false);