protected void CreateScheduleCallsForAsyncStateGroups(IRBuilder builder, LLVMValueRef statePointer, IEnumerable <AsyncStateGroup> asyncStateGroups) { LLVMTypeRef scheduledTaskType = SharedData.Context.GetScheduledTaskType(); LLVMValueRef bitCastStatePtr = builder.CreateBitCast(statePointer, SharedData.Context.VoidPointerType(), "bitCastStatePtr"); foreach (AsyncStateGroup successor in asyncStateGroups) { AsyncStateGroupData successorData = AsyncStateGroups[successor]; LLVMValueRef bitCastSuccessorFunction = builder.CreateBitCast( successorData.Function, LLVMTypeRef.PointerType(SharedData.Context.ScheduledTaskFunctionType(), 0u), "bitCastFunction"); if (!successor.SignaledConditionally && successor.Predecessors.HasMoreThan(1)) { LLVMValueRef fireCountPtr = ((IAddressableValueSource)successorData.FireCountStateField).GetAddress(builder); builder.CreateCall( SharedData.FunctionImporter.GetImportedCommonFunction(CommonModules.PartialScheduleName), new LLVMValueRef[] { bitCastStatePtr, fireCountPtr, bitCastSuccessorFunction }, string.Empty); } else { builder.CreateCall( SharedData.FunctionImporter.GetImportedCommonFunction(CommonModules.ScheduleName), new LLVMValueRef[] { bitCastSuccessorFunction, bitCastStatePtr }, string.Empty); } } }
public LLVMModuleRef GenerateLLVM() { LLVMTypeRef stringType = LLVMTypeRef.PointerType(LLVMTypeRef.Int8Type(), 0); var printfArguments = new LLVMTypeRef[] { stringType }; var printf = LLVM.AddFunction(_module, "printf", LLVM.FunctionType(LLVMTypeRef.Int32Type(), printfArguments, LLVMBoolTrue)); LLVM.SetLinkage(printf, LLVMLinkage.LLVMExternalLinkage); var scanfArguments = new LLVMTypeRef[] { stringType }; var scanf = LLVM.AddFunction(_module, "scanf", LLVM.FunctionType(LLVMTypeRef.Int32Type(), scanfArguments, LLVMBoolTrue)); LLVM.SetLinkage(scanf, LLVMLinkage.LLVMExternalLinkage); // Generate functions, globals, etc. for (int i = 0; i < _statements.Count; i++) { _statements[i].Accept(this); } // Generate everything inside the functions while (_valueStack.Count > 0) { _valueStack.Peek().Item2.Accept(this); } return(_module); }
public static LLVMValueRef CreateMalloc(this FunctionModuleContext moduleContext, IRBuilder builder, LLVMTypeRef type, string name) { LLVMValueRef mallocFunction = moduleContext.FunctionImporter.GetCachedFunction("malloc", moduleContext.CreateMallocFunction), mallocCall = builder.CreateCall(mallocFunction, new LLVMValueRef[] { type.SizeOf() }, "malloCcall"); return(builder.CreateBitCast(mallocCall, LLVMTypeRef.PointerType(type, 0u), name)); }
public static LLVMTypeRef WakerType(this ContextWrapper context) => context.StructType( new LLVMTypeRef[] { // task function pointer LLVMTypeRef.PointerType(context.ScheduledTaskFunctionType(), 0u), // task state context.VoidPointerType() });
public static void MakePointer(LLVMValueRef pValue, ref LLVMTypeRef pType) { //We want to make pType match pValue, so we only make it a pointer if pValue is also a pointer if (IsPointer(pValue)) { pType = LLVMTypeRef.PointerType(pType, 0); } }
internal static LLVMTypeRef CreateLLVMNotifierWriterType(this ContextWrapper context, LLVMTypeRef innerType) { return(context.StructType( new LLVMTypeRef[] { LLVMTypeRef.PointerType(context.CreateLLVMRefCountType(context.CreateLLVMNotifierSharedDataType(innerType)), 0u) }, false)); }
public static LLVMTypeRef PollFunctionType(ContextWrapper context) => LLVMTypeRef.FunctionType( context.VoidType, new LLVMTypeRef[] { context.VoidPointerType(), LLVMTypeRef.PointerType(context.ScheduledTaskFunctionType(), 0u), 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);
public static LLVMValueRef CreateArrayMalloc(this FunctionModuleContext moduleContext, IRBuilder builder, LLVMTypeRef type, LLVMValueRef size, string name) { LLVMValueRef bitCastSize = builder.CreateZExtOrBitCast(size, moduleContext.LLVMContext.Int64Type, "bitCastSize"), mallocSize = builder.CreateMul(type.SizeOf(), bitCastSize, "mallocSize"), mallocFunction = moduleContext.FunctionImporter.GetCachedFunction("malloc", moduleContext.CreateMallocFunction), mallocCall = builder.CreateCall(mallocFunction, new LLVMValueRef[] { mallocSize }, "malloCcall"); return(builder.CreateBitCast(mallocCall, LLVMTypeRef.PointerType(type, 0u), name)); }
internal static LLVMTypeRef CreateLLVMMethodCallPromiseType(this ContextWrapper context, LLVMTypeRef innerType) { return(context.StructType(new LLVMTypeRef[] { LLVMTypeRef.PointerType(context.MethodPollFunctionType(), 0u), context.VoidPointerType(), innerType, })); }
public static LLVMTypeRef AsLLVMType(this NIType niType) { if (niType.IsInteger()) { switch (niType.GetKind()) { case NITypeKind.UInt8: case NITypeKind.Int8: return(LLVMTypeRef.Int8Type()); case NITypeKind.UInt16: case NITypeKind.Int16: return(LLVMTypeRef.Int16Type()); case NITypeKind.UInt32: case NITypeKind.Int32: return(LLVMTypeRef.Int32Type()); case NITypeKind.UInt64: case NITypeKind.Int64: return(LLVMTypeRef.Int64Type()); } } if (niType.IsBoolean()) { return(LLVMTypeRef.Int1Type()); } if (niType.IsString()) { return(StringType); } if (niType.IsRebarReferenceType()) { NIType referentType = niType.GetReferentType(); if (referentType == DataTypes.StringSliceType) { return(StringSliceReferenceType); } return(LLVMTypeRef.PointerType(referentType.AsLLVMType(), 0u)); } if (niType == DataTypes.FileHandleType) { return(FileHandleType); } NIType innerType; if (niType.TryDestructureOptionType(out innerType)) { return(CreateLLVMOptionType(innerType.AsLLVMType())); } if (niType == DataTypes.RangeIteratorType) { return(RangeIteratorType); } throw new NotSupportedException("Unsupported type: " + niType); }
public static LLVMTypeRef GetScheduledTaskType(this ContextWrapper context) { return(context.GetCachedStructType("scheduled_task", () => new[] { // task function pointer LLVMTypeRef.PointerType(context.ScheduledTaskFunctionType(), 0u), // task state context.VoidPointerType() })); }
internal static LLVMTypeRef CreateLLVMVectorType(this ContextWrapper context, LLVMTypeRef elementType) { return(context.StructType( // { allocationPtr, size, capacity } new LLVMTypeRef[] { LLVMTypeRef.PointerType(elementType, 0u), context.Int32Type, context.Int32Type }, false)); }
bool ICodeGenElementVisitor <bool> .VisitGetVariantFieldValue(GetVariantFieldValue getVariantFieldValue) { LLVMTypeRef fieldLLVMType = Context.AsLLVMType(getVariantFieldValue.FieldType); LLVMValueRef variantAddress = _codeGenValues[getVariantFieldValue.VariantAddressIndex], variantValueFieldPtr = Builder.CreateStructGEP(variantAddress, 1u, "variantValueFieldPtr"), bitCastFieldPtr = Builder.CreateBitCast( variantValueFieldPtr, LLVMTypeRef.PointerType(fieldLLVMType, 0u), "bitCastFieldPtr"); _codeGenValues[getVariantFieldValue.FieldValueIndex] = Builder.CreateLoad(bitCastFieldPtr, "fieldValue"); return(true); }
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); } }
internal static void BuildCreateYieldPromiseFunction(FunctionModuleContext moduleContext, NIType signature, LLVMValueRef createYieldPromiseFunction) { LLVMTypeRef valueType = moduleContext.LLVMContext.AsLLVMType(signature.GetGenericParameters().First()), valueReferenceType = LLVMTypeRef.PointerType(valueType, 0u), yieldPromiseType = moduleContext.LLVMContext.CreateLLVMYieldPromiseType(valueReferenceType); LLVMBasicBlockRef entryBlock = createYieldPromiseFunction.AppendBasicBlock("entry"); var builder = moduleContext.LLVMContext.CreateIRBuilder(); builder.PositionBuilderAtEnd(entryBlock); LLVMValueRef value = createYieldPromiseFunction.GetParam(0u), yieldPromise = builder.BuildStructValue(yieldPromiseType, new[] { value }); builder.CreateStore(yieldPromise, createYieldPromiseFunction.GetParam(1u)); builder.CreateRetVoid(); }
public static LLVMTypeRef LlvmTypeFromName(string name) { // TODO: Implement functionality for pointer types. // Special case for string type. if (name == TypeName.String) { return(LLVMTypeRef.PointerType(LLVMTypeRef.Int8Type(), 0)); } // Otherwise, use LLVM type map. else if (LlvmTypeMap.ContainsKey(name)) { return(LlvmTypeMap[name]()); } // Throw an exception. throw new Exception($"Non-registered type resolver for type '{name}'"); }
internal static void GenerateWakerFromCurrentGroup(IRBuilder builder, ICodeGenValueStorage valueStorage, int outputIndex) { var functionCompiler = (FunctionCompiler)valueStorage; LLVMValueRef bitCastCurrentGroupFunction = builder.CreateBitCast( functionCompiler._moduleBuilder.CurrentGroupData.Function, LLVMTypeRef.PointerType(functionCompiler.Context.ScheduledTaskFunctionType(), 0u), "bitCastCurrentGroupFunction"), bitCastStatePtr = builder.CreateBitCast( functionCompiler.AllocationSet.StatePointer, functionCompiler.Context.VoidPointerType(), "bitCastStatePtr"), waker = builder.BuildStructValue( functionCompiler.Context.AsLLVMType(DataTypes.WakerType), new LLVMValueRef[] { bitCastCurrentGroupFunction, bitCastStatePtr }, "waker"); valueStorage[outputIndex] = waker; }
private static void CreateFileModule(Module fileModule) { CommonExternalFunctions externalFunctions = new CommonExternalFunctions(fileModule); CommonModuleSignatures[OpenFileHandleName] = LLVMSharp.LLVM.FunctionType( LLVMSharp.LLVM.VoidType(), new LLVMTypeRef[] { LLVMExtensions.StringSliceReferenceType, LLVMTypeRef.PointerType(LLVMExtensions.FileHandleType.CreateLLVMOptionType(), 0), }, false); BuildOpenFileHandleFunction(fileModule, externalFunctions); CommonModuleSignatures[ReadLineFromFileHandleName] = LLVMSharp.LLVM.FunctionType( LLVMSharp.LLVM.VoidType(), new LLVMTypeRef[] { LLVMTypeRef.PointerType(LLVMExtensions.FileHandleType, 0), LLVMTypeRef.PointerType(LLVMExtensions.StringType.CreateLLVMOptionType(), 0), }, false); BuildReadLineFromFileHandleFunction(fileModule, externalFunctions); CommonModuleSignatures[WriteStringToFileHandleName] = LLVMSharp.LLVM.FunctionType( LLVMSharp.LLVM.VoidType(), new LLVMTypeRef[] { LLVMTypeRef.PointerType(LLVMExtensions.FileHandleType, 0), LLVMExtensions.StringSliceReferenceType, }, false); BuildWriteStringToFileHandleFunction(fileModule, externalFunctions); CommonModuleSignatures[DropFileHandleName] = LLVMSharp.LLVM.FunctionType( LLVMSharp.LLVM.VoidType(), new LLVMTypeRef[] { LLVMTypeRef.PointerType(LLVMExtensions.FileHandleType, 0), }, false); BuildDropFileHandleFunction(fileModule, externalFunctions); }
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); }
internal static LLVMTypeRef TranslateParameterType(this ContextWrapper context, NIType parameterType) { // TODO: this should probably share code with how we compute the top function LLVM type above bool isInput = parameterType.GetInputParameterPassingRule() != NIParameterPassingRule.NotAllowed, isOutput = parameterType.GetOutputParameterPassingRule() != NIParameterPassingRule.NotAllowed; LLVMTypeRef parameterLLVMType = context.AsLLVMType(parameterType.GetDataType()); if (isInput) // includes inout parameters { if (isOutput && !parameterType.GetDataType().IsRebarReferenceType()) { throw new InvalidOperationException("Inout parameter with non-reference type"); } return(parameterLLVMType); } if (isOutput) { return(LLVMTypeRef.PointerType(parameterLLVMType, 0u)); } throw new NotImplementedException("Parameter direction is wrong"); }
private static void CreateRangeModule(Module rangeModule) { CommonModuleSignatures[RangeIteratorNextName] = LLVMSharp.LLVM.FunctionType( LLVMTypeRef.Int32Type().CreateLLVMOptionType(), new LLVMTypeRef[] { LLVMTypeRef.PointerType(LLVMExtensions.RangeIteratorType, 0) }, false); BuildRangeIteratorNextFunction(rangeModule); CommonModuleSignatures[CreateRangeIteratorName] = LLVMSharp.LLVM.FunctionType( LLVMTypeRef.Int32Type().CreateLLVMOptionType(), new LLVMTypeRef[] { LLVMTypeRef.Int32Type(), LLVMTypeRef.Int32Type(), LLVMTypeRef.PointerType(LLVMExtensions.RangeIteratorType, 0) }, false); BuildCreateRangeIteratorFunction(rangeModule); }
protected IEnumerable <LLVMTypeRef> GetParameterLLVMTypes() { foreach (var parameter in SharedData.OrderedParameters) { NIType parameterType = parameter.ParameterVariable.Type; switch (parameter.Direction) { case Direction.Input: yield return(SharedData.Context.AsLLVMType(parameterType)); break; case Direction.Output: yield return(LLVMTypeRef.PointerType(SharedData.Context.AsLLVMType(parameterType), 0u)); break; default: throw new NotImplementedException("Can only handle in and out parameters"); } } }
internal static void BuildVariantDropFunction(FunctionModuleContext moduleContext, NIType signature, LLVMValueRef variantDropFunction) { NIType variantType = signature.GetGenericParameters().First(); Tuple <NIType, int>[] droppableFields = variantType.GetFields() .Select((field, i) => new Tuple <NIType, int>(field, i)) .Where(field => field.Item1.GetDataType().TypeHasDropTrait()).ToArray(); LLVMBasicBlockRef entryBlock = variantDropFunction.AppendBasicBlock("entry"); Tuple <LLVMBasicBlockRef, int>[] dropBlocks = droppableFields.Select(field => new Tuple <LLVMBasicBlockRef, int>(variantDropFunction.AppendBasicBlock($"drop{field.Item1.GetName()}"), field.Item2)).ToArray(); LLVMBasicBlockRef exitBlock = variantDropFunction.AppendBasicBlock("exit"); var builder = moduleContext.LLVMContext.CreateIRBuilder(); builder.PositionBuilderAtEnd(entryBlock); LLVMValueRef variantPtr = variantDropFunction.GetParam(0u), variantTagPtr = builder.CreateStructGEP(variantPtr, 0u, "variantTagPtr"), variantDataPtr = builder.CreateStructGEP(variantPtr, 1u, "variantDataPtr"), variantTag = builder.CreateLoad(variantTagPtr, "variantTag"), tagSwitch = builder.CreateSwitch(variantTag, exitBlock, (uint)dropBlocks.Length); foreach (var pair in dropBlocks) { tagSwitch.AddCase(moduleContext.LLVMContext.AsLLVMValue((byte)pair.Item2), pair.Item1); } for (int i = 0; i < droppableFields.Length; ++i) { builder.PositionBuilderAtEnd(dropBlocks[i].Item1); NIType fieldType = droppableFields[i].Item1.GetDataType(); LLVMTypeRef fieldLLVMType = moduleContext.LLVMContext.AsLLVMType(fieldType); LLVMValueRef bitCastFieldPtr = builder.CreateBitCast(variantDataPtr, LLVMTypeRef.PointerType(fieldLLVMType, 0u), "bitCastFieldPtr"); moduleContext.CreateDropCallIfDropFunctionExists(builder, fieldType, _ => bitCastFieldPtr); builder.CreateBr(exitBlock); } builder.PositionBuilderAtEnd(exitBlock); builder.CreateRetVoid(); }
private LLVMValueRef BuildPollFunction() { LLVMValueRef pollFunction = Module.AddFunction(FunctionNames.GetPollFunctionName(_functionName), PollFunctionType(SharedData.Context)); LLVMBasicBlockRef entryBlock = pollFunction.AppendBasicBlock("entry"); var builder = SharedData.Context.CreateIRBuilder(); var outerFunctionCompilerState = new OuterFunctionCompilerState(pollFunction, builder); CurrentState = outerFunctionCompilerState; builder.PositionBuilderAtEnd(entryBlock); LLVMValueRef stateVoidPtr = pollFunction.GetParam(0u), statePtr = builder.CreateBitCast(stateVoidPtr, LLVMTypeRef.PointerType(SharedData.AllocationSet.StateType, 0u), "statePtr"); outerFunctionCompilerState.StateMalloc = statePtr; // store the caller waker in the state // TODO: create constants for these positions LLVMValueRef waker = builder.BuildStructValue( SharedData.Context.WakerType(), new LLVMValueRef[] { pollFunction.GetParam(1u), pollFunction.GetParam(2u) }, "callerWaker"); builder.CreateStore(waker, builder.CreateStructGEP(statePtr, 1u, "callerWakerPtr")); // set initial fire counts foreach (AsyncStateGroupData groupData in AsyncStateGroups.Values) { groupData.CreateFireCountReset(builder); } // schedule initial group(s) CreateScheduleCallsForAsyncStateGroups( builder, statePtr, AsyncStateGroups.Keys.Where(group => !group.Predecessors.Any())); builder.CreateRetVoid(); return(pollFunction); }
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); }
public LLVMValueRef EmitMethodHeader(string pName, Syntax.MethodSyntax pMethod, out string pNewName) { //Get method return type LLVMTypeRef ret; if (pMethod.ReturnValues.Count == 0) { ret = LLVMTypeRef.VoidType(); } else if (pMethod.ReturnValues.Count == 1) { ret = SmallTypeCache.GetLLVMType(pMethod.Type, this); } else { LLVMTypeRef[] types = new LLVMTypeRef[pMethod.ReturnValues.Count]; for (int i = 0; i < types.Length; i++) { types[i] = SmallTypeCache.GetLLVMType(pMethod.ReturnValues[i].Type, this); } ret = LLVM.StructType(types, false); Cache.SetLLVMType(pMethod.Type.Name, ret); } //If we are emitting a struct method we need to add "self" as a parameter SmallType[] originalTypes = new SmallType[pMethod.Parameters.Count]; LLVMTypeRef[] parmTypes = null; int start = 0; if (CurrentStruct != null) { parmTypes = new LLVMTypeRef[pMethod.Parameters.Count + 1]; parmTypes[0] = LLVMTypeRef.PointerType(SmallTypeCache.GetLLVMType(CurrentStruct, this), 0); start = 1; } else { parmTypes = new LLVMTypeRef[pMethod.Parameters.Count]; } //Get parameter types for (int i = 0; i < pMethod.Parameters.Count; i++) { var parmType = pMethod.Parameters[i].Type; if (parmType.IsGenericParameter) { originalTypes[i] = TypeMappings[parmType.Name]; } else { originalTypes[i] = parmType; } //For calling external methods with strings, we only want to pass the character array if (pMethod.External && parmType == SmallTypeCache.String) { parmType = parmType.GetElementType(); } parmTypes[start + i] = SmallTypeCache.GetLLVMType(parmType, this); if (pMethod.Parameters[i].Type.IsStruct || pMethod.Parameters[i].Type.IsArray) { parmTypes[start + i] = LLVMTypeRef.PointerType(parmTypes[start + i], 0); } } var result = Cache.FindMethod(out MethodDefinition pDefinition, null, CurrentStruct, pName, originalTypes); Debug.Assert(result == Compiler.FindResult.Found); pNewName = pDefinition.MangledName; //Method header var func = LLVM.GetNamedFunction(CurrentModule, pNewName); if (func.Pointer == IntPtr.Zero) { func = LLVM.AddFunction(CurrentModule, pNewName, LLVM.FunctionType(ret, parmTypes, false)); LLVM.SetLinkage(func, LLVMLinkage.LLVMExternalLinkage); } if (pMethod.External) { //Create attribute so we can find it later when executing var attribute = LLVM.CreateStringAttribute(_context, "external", 8, pMethod.Annotation.Value, (uint)pMethod.Annotation.Value.Length); LLVM.AddAttributeAtIndex(func, LLVMAttributeIndex.LLVMAttributeFunctionIndex, attribute); } return(func); }
bool ICodeGenElementVisitor <bool> .VisitBuildVariant(BuildVariant buildVariant) { LLVMValueRef variantAddress = _codeGenValues[buildVariant.VariantAddressIndex], variantTagFieldPtr = Builder.CreateStructGEP(variantAddress, 0u, "variantTagFieldPtr"), variantDataFieldPtr = Builder.CreateStructGEP(variantAddress, 1u, "variantDataFieldPtr"), inputValue = _codeGenValues[buildVariant.FieldValueIndex], bitCastAllocaFieldPtr = Builder.CreateBitCast(variantDataFieldPtr, LLVMTypeRef.PointerType(inputValue.TypeOf(), 0u), "bitCastAllocaFieldPtr"); Builder.CreateStore(Context.AsLLVMValue((byte)buildVariant.FieldIndex), variantTagFieldPtr); Builder.CreateStore(inputValue, bitCastAllocaFieldPtr); return(true); }
internal static void BuildMethodCallPromisePollFunction(FunctionModuleContext moduleContext, NIType signature, LLVMValueRef methodCallPromisePollFunction) { NIType optionPromiseResultType = signature.GetParameters().ElementAt(2).GetDataType(); NIType promiseResultType; optionPromiseResultType.TryDestructureOptionType(out promiseResultType); NIType resultType; bool mayPanic = promiseResultType.TryDestructurePanicResultType(out resultType); LLVMBasicBlockRef entryBlock = methodCallPromisePollFunction.AppendBasicBlock("entry"), targetDoneBlock = methodCallPromisePollFunction.AppendBasicBlock("targetDone"), targetNotDoneBlock = methodCallPromisePollFunction.AppendBasicBlock("targetNotDone"); LLVMBasicBlockRef targetPanickedBlock = mayPanic ? methodCallPromisePollFunction.AppendBasicBlock("targetPanicked") : default(LLVMBasicBlockRef); var builder = moduleContext.LLVMContext.CreateIRBuilder(); builder.PositionBuilderAtEnd(entryBlock); LLVMTypeRef stateType = moduleContext.LLVMContext.StructType(new[] { FunctionAllocationSet.FunctionCompletionStatusType(moduleContext.LLVMContext), moduleContext.LLVMContext.WakerType(), }); LLVMValueRef promisePtr = methodCallPromisePollFunction.GetParam(0u), promise = builder.CreateLoad(promisePtr, "promise"), stateVoidPtr = builder.CreateExtractValue(promise, MethodCallPromiseStatePtrFieldIndex, "stateVoidPtr"), result = builder.CreateExtractValue(promise, MethodCallPromiseOutputFieldIndex, "result"), statePtr = builder.CreateBitCast(stateVoidPtr, LLVMTypeRef.PointerType(stateType, 0u), "statePtr"), state = builder.CreateLoad(statePtr, "state"), functionCompletionState = builder.CreateExtractValue(state, 0u, "functionCompletionState"), optionResultOutputPtr = methodCallPromisePollFunction.GetParam(2u); LLVMTypeRef optionResultOutputType = optionResultOutputPtr.TypeOf().GetElementType(); uint switchCases = mayPanic ? 2u : 1u; LLVMValueRef completionStateSwitch = builder.CreateSwitch(functionCompletionState, targetNotDoneBlock, switchCases); completionStateSwitch.AddCase(moduleContext.LLVMContext.AsLLVMValue(RuntimeConstants.FunctionCompletedNormallyStatus), targetDoneBlock); if (mayPanic) { completionStateSwitch.AddCase(moduleContext.LLVMContext.AsLLVMValue(RuntimeConstants.FunctionPanickedStatus), targetPanickedBlock); } builder.PositionBuilderAtEnd(targetDoneBlock); builder.CreateFree(stateVoidPtr); LLVMValueRef finalResult = mayPanic ? builder.CreateInsertValue(result, moduleContext.LLVMContext.AsLLVMValue(true), 0u, "okResult") : result; LLVMValueRef someResult = moduleContext.LLVMContext.BuildOptionValue(builder, optionResultOutputType, finalResult); builder.CreateStore(someResult, optionResultOutputPtr); builder.CreateRetVoid(); builder.PositionBuilderAtEnd(targetNotDoneBlock); LLVMValueRef waker = methodCallPromisePollFunction.GetParam(1u), wakerFunctionPtr = builder.CreateExtractValue(waker, 0u, "wakerFunctionPtr"), wakerStatePtr = builder.CreateExtractValue(waker, 1u, "wakerStatePtr"), pollFunctionPtr = builder.CreateExtractValue(promise, MethodCallPromisePollFunctionPtrFieldIndex, "pollFunctionPtr"); builder.CreateCall(pollFunctionPtr, new LLVMValueRef[] { stateVoidPtr, wakerFunctionPtr, wakerStatePtr }, string.Empty); LLVMValueRef noneResult = moduleContext.LLVMContext.BuildOptionValue(builder, optionResultOutputType, null); builder.CreateStore(noneResult, optionResultOutputPtr); builder.CreateRetVoid(); if (mayPanic) { builder.PositionBuilderAtEnd(targetPanickedBlock); LLVMValueRef panicResult = builder.CreateInsertValue(result, moduleContext.LLVMContext.AsLLVMValue(false), 0u, "panicResult"), somePanicResult = moduleContext.LLVMContext.BuildOptionValue(builder, optionResultOutputType, panicResult); builder.CreateStore(somePanicResult, optionResultOutputPtr); builder.CreateRetVoid(); } }
internal static void CreateSliceIndexFunction(FunctionModuleContext moduleContext, NIType signature, LLVMValueRef sliceIndexFunction) { NIType elementType = signature.GetGenericParameters().First(); LLVMTypeRef elementPtrOptionType = moduleContext.LLVMContext.CreateLLVMOptionType(LLVMTypeRef.PointerType(moduleContext.LLVMContext.AsLLVMType(elementType), 0u)); LLVMBasicBlockRef entryBlock = sliceIndexFunction.AppendBasicBlock("entry"), validIndexBlock = sliceIndexFunction.AppendBasicBlock("validIndex"), invalidIndexBlock = sliceIndexFunction.AppendBasicBlock("invalidIndex"); var builder = moduleContext.LLVMContext.CreateIRBuilder(); builder.PositionBuilderAtEnd(entryBlock); LLVMValueRef indexPtr = sliceIndexFunction.GetParam(0u), index = builder.CreateLoad(indexPtr, "index"), sliceRef = sliceIndexFunction.GetParam(1u), sliceLength = builder.CreateExtractValue(sliceRef, 1u, "sliceLength"), indexLessThanSliceLength = builder.CreateICmp(LLVMIntPredicate.LLVMIntSLT, index, sliceLength, "indexLTSliceLength"), indexNonNegative = builder.CreateICmp(LLVMIntPredicate.LLVMIntSGE, index, moduleContext.LLVMContext.AsLLVMValue(0), "indexNonNegative"), indexInBounds = builder.CreateAnd(indexLessThanSliceLength, indexNonNegative, "indexInBounds"), elementPtrOptionPtr = sliceIndexFunction.GetParam(2u); builder.CreateCondBr(indexInBounds, validIndexBlock, invalidIndexBlock); builder.PositionBuilderAtEnd(validIndexBlock); LLVMValueRef sliceBufferPtr = builder.CreateExtractValue(sliceRef, 0u, "sliceBufferPtr"), elementPtr = builder.CreateGEP(sliceBufferPtr, new LLVMValueRef[] { index }, "elementPtr"), someElementPtr = moduleContext.LLVMContext.BuildOptionValue(builder, elementPtrOptionType, elementPtr); builder.CreateStore(someElementPtr, elementPtrOptionPtr); builder.CreateRetVoid(); builder.PositionBuilderAtEnd(invalidIndexBlock); LLVMValueRef noneElementPtr = moduleContext.LLVMContext.BuildOptionValue(builder, elementPtrOptionType, null); builder.CreateStore(noneElementPtr, elementPtrOptionPtr); builder.CreateRetVoid(); }