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))); }
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)); }
internal static void BuildOptionToPanicResultFunction(FunctionModuleContext moduleContext, NIType signature, LLVMValueRef optionToPanicResultFunction) { LLVMTypeRef elementLLVMType = moduleContext.LLVMContext.AsLLVMType(signature.GetGenericParameters().First()); LLVMBasicBlockRef entryBlock = optionToPanicResultFunction.AppendBasicBlock("entry"), someBlock = optionToPanicResultFunction.AppendBasicBlock("some"), noneBlock = optionToPanicResultFunction.AppendBasicBlock("none"); var builder = moduleContext.LLVMContext.CreateIRBuilder(); builder.PositionBuilderAtEnd(entryBlock); LLVMValueRef option = optionToPanicResultFunction.GetParam(0u), isSome = builder.CreateExtractValue(option, 0u, "isSome"); LLVMValueRef branch = builder.CreateCondBr(isSome, someBlock, noneBlock); // TODO: if possible, set metadata that indicates the some branch is more likely to be taken LLVMTypeRef panicResultType = moduleContext.LLVMContext.CreateLLVMPanicResultType(elementLLVMType); builder.PositionBuilderAtEnd(someBlock); LLVMValueRef innerValue = builder.CreateExtractValue(option, 1u, "innerValue"); LLVMValueRef panicContinueResult = builder.BuildStructValue(panicResultType, new LLVMValueRef[] { moduleContext.LLVMContext.AsLLVMValue(true), innerValue }, "panicContinueResult"); builder.CreateStore(panicContinueResult, optionToPanicResultFunction.GetParam(1u)); builder.CreateRetVoid(); builder.PositionBuilderAtEnd(noneBlock); LLVMValueRef panicResult = LLVMSharp.LLVM.ConstNull(panicResultType); builder.CreateStore(panicResult, optionToPanicResultFunction.GetParam(1u)); builder.CreateRetVoid(); }
public static bool TryGetCloneFunction(this FunctionModuleContext moduleContext, NIType valueType, out LLVMValueRef cloneFunction) { cloneFunction = default(LLVMValueRef); var functionBuilder = Signatures.CreateCopyType.DefineFunctionFromExisting(); functionBuilder.Name = "Clone"; functionBuilder.ReplaceGenericParameters(valueType, NIType.Unset); NIType signature = functionBuilder.CreateType(); NIType innerType; if (valueType == NITypes.String) { cloneFunction = moduleContext.FunctionImporter.GetImportedCommonFunction(CommonModules.StringCloneName); return(true); } if (valueType.TryDestructureSharedType(out innerType)) { cloneFunction = moduleContext.GetSpecializedFunctionWithSignature(signature, FunctionCompiler.BuildSharedCloneFunction); return(true); } if (valueType.TryDestructureVectorType(out innerType)) { cloneFunction = moduleContext.GetSpecializedFunctionWithSignature(signature, FunctionCompiler.BuildVectorCloneFunction); return(true); } if (valueType.TypeHasCloneTrait()) { throw new NotSupportedException("Clone function not found for type: " + valueType); } return(false); }
internal static void BuildCreateNotifierPairFunction(FunctionModuleContext moduleContext, NIType signature, LLVMValueRef createNotifierPairFunction) { LLVMTypeRef valueType = moduleContext.LLVMContext.AsLLVMType(signature.GetGenericParameters().First()), notifierReaderType = moduleContext.LLVMContext.CreateLLVMNotifierReaderType(valueType), notifierWriterType = moduleContext.LLVMContext.CreateLLVMNotifierWriterType(valueType); LLVMBasicBlockRef entryBlock = createNotifierPairFunction.AppendBasicBlock("entry"); var builder = moduleContext.LLVMContext.CreateIRBuilder(); builder.PositionBuilderAtEnd(entryBlock); LLVMTypeRef sharedDataType = moduleContext.LLVMContext.CreateLLVMNotifierSharedDataType(valueType); LLVMTypeRef refCountType = moduleContext.LLVMContext.CreateLLVMRefCountType(sharedDataType); LLVMValueRef refCountAllocationPtr = moduleContext.CreateMalloc(builder, refCountType, "refCountAllocationPtr"), refCount = builder.BuildStructValue( refCountType, new LLVMValueRef[] { moduleContext.LLVMContext.AsLLVMValue(2), LLVMSharp.LLVM.ConstNull(sharedDataType) }, "refCount"); builder.CreateStore(refCount, refCountAllocationPtr); LLVMValueRef notifierReader = builder.BuildStructValue(notifierReaderType, new[] { refCountAllocationPtr }); builder.CreateStore(notifierReader, createNotifierPairFunction.GetParam(0u)); LLVMValueRef notifierWriter = builder.BuildStructValue(notifierWriterType, new[] { refCountAllocationPtr }); builder.CreateStore(notifierWriter, createNotifierPairFunction.GetParam(1u)); builder.CreateRetVoid(); }
internal static void BuildOptionDropFunction(FunctionModuleContext moduleContext, NIType signature, LLVMValueRef optionDropFunction) { NIType innerType; signature.GetGenericParameters().First().TryDestructureOptionType(out innerType); LLVMBasicBlockRef entryBlock = optionDropFunction.AppendBasicBlock("entry"), isSomeBlock = optionDropFunction.AppendBasicBlock("isSome"), endBlock = optionDropFunction.AppendBasicBlock("end"); var builder = moduleContext.LLVMContext.CreateIRBuilder(); builder.PositionBuilderAtEnd(entryBlock); LLVMValueRef optionPtr = optionDropFunction.GetParam(0u), isSomePtr = builder.CreateStructGEP(optionPtr, 0u, "isSomePtr"), isSome = builder.CreateLoad(isSomePtr, "isSome"); builder.CreateCondBr(isSome, isSomeBlock, endBlock); builder.PositionBuilderAtEnd(isSomeBlock); moduleContext.CreateDropCallIfDropFunctionExists(builder, innerType, b => b.CreateStructGEP(optionPtr, 1u, "innerValuePtr")); builder.CreateBr(endBlock); builder.PositionBuilderAtEnd(endBlock); builder.CreateRetVoid(); }
private static LLVMValueRef GetDecrementRefCountFunction(FunctionModuleContext moduleContext, NIType valueType) { string specializedName = FunctionNames.MonomorphizeFunctionName("decrementRefCount", valueType.ToEnumerable()); return(moduleContext.FunctionImporter.GetCachedFunction( specializedName, () => BuildDecrementRefCountFunction(moduleContext, specializedName, valueType))); }
public static LLVMValueRef GetImportedSynchronousFunction(this FunctionModuleContext moduleContext, MethodCallNode methodCallNode) { string targetFunctionName = FunctionCompileHandler.FunctionLLVMName(methodCallNode.TargetName); return(moduleContext.GetImportedFunction( FunctionNames.GetSynchronousFunctionName(targetFunctionName), () => moduleContext.LLVMContext.TranslateFunctionType(methodCallNode.Signature))); }
public static LLVMValueRef GetImportedInitializeStateFunction(this FunctionModuleContext moduleContext, CreateMethodCallPromise createMethodCallPromise) { string targetFunctionName = FunctionCompileHandler.FunctionLLVMName(createMethodCallPromise.TargetName); return(moduleContext.GetImportedFunction( FunctionNames.GetInitializeStateFunctionName(targetFunctionName), () => moduleContext.TranslateInitializeFunctionType(createMethodCallPromise.Signature))); }
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 void BuildVectorCloneFunction(FunctionModuleContext moduleContext, NIType signature, LLVMValueRef vectorCloneFunction) { NIType elementType; signature.GetGenericParameters().First().TryDestructureVectorType(out elementType); LLVMTypeRef elementLLVMType = moduleContext.LLVMContext.AsLLVMType(elementType); LLVMBasicBlockRef entryBlock = vectorCloneFunction.AppendBasicBlock("entry"); var builder = moduleContext.LLVMContext.CreateIRBuilder(); builder.PositionBuilderAtEnd(entryBlock); LLVMValueRef existingVectorPtr = vectorCloneFunction.GetParam(0u), existingVector = builder.CreateLoad(existingVectorPtr, "existingVector"), existingVectorAllocationPtr = builder.CreateExtractValue(existingVector, 0u, "existingVectorAllocationPtr"), existingVectorSize = builder.CreateExtractValue(existingVector, 1u, "existingVectorSize"), existingVectorCapacity = builder.CreateExtractValue(existingVector, 2u, "existingVectorCapacity"), newVectorAllocationPtr = moduleContext.CreateArrayMalloc(builder, elementLLVMType, existingVectorCapacity, "newVectorAllocationPtr"); LLVMValueRef elementCloneFunction; if (moduleContext.TryGetCloneFunction(elementType, out elementCloneFunction)) { LLVMBasicBlockRef loopStartBlock = vectorCloneFunction.AppendBasicBlock("loopStart"), loopBodyBlock = vectorCloneFunction.AppendBasicBlock("loopBody"), loopEndBlock = vectorCloneFunction.AppendBasicBlock("loopEnd"); builder.CreateBr(loopStartBlock); builder.PositionBuilderAtEnd(loopStartBlock); LLVMValueRef index = builder.CreatePhi(moduleContext.LLVMContext.Int32Type, "index"); LLVMValueRef indexLessThanSize = builder.CreateICmp(LLVMIntPredicate.LLVMIntSLT, index, existingVectorSize, "indexLessThanSize"); builder.CreateCondBr(indexLessThanSize, loopBodyBlock, loopEndBlock); builder.PositionBuilderAtEnd(loopBodyBlock); LLVMValueRef existingElementPtr = builder.CreateGEP(existingVectorAllocationPtr, new LLVMValueRef[] { index }, "existingElementPtr"), newElementPtr = builder.CreateGEP(newVectorAllocationPtr, new LLVMValueRef[] { index }, "newElementPtr"); builder.CreateCall(elementCloneFunction, new LLVMValueRef[] { existingElementPtr, newElementPtr }, string.Empty); LLVMValueRef incrementIndex = builder.CreateAdd(index, moduleContext.LLVMContext.AsLLVMValue(1), "incrementIndex"); builder.CreateBr(loopStartBlock); index.AddIncoming(moduleContext.LLVMContext.AsLLVMValue(0), entryBlock); index.AddIncoming(incrementIndex, loopBodyBlock); builder.PositionBuilderAtEnd(loopEndBlock); } else { LLVMValueRef existingVectorSizeExtend = builder.CreateSExt(existingVectorSize, moduleContext.LLVMContext.Int64Type, "existingVectorSizeExtend"), bytesToCopy = builder.CreateMul(existingVectorSizeExtend, elementLLVMType.SizeOf(), "bytesToCopy"); moduleContext.CreateCallToCopyMemory(builder, newVectorAllocationPtr, existingVectorAllocationPtr, bytesToCopy); } LLVMValueRef newVector = builder.CreateInsertValue(existingVector, newVectorAllocationPtr, 0u, "newVector"), newVectorPtr = vectorCloneFunction.GetParam(1u); builder.CreateStore(newVector, newVectorPtr); builder.CreateRetVoid(); }
public FunctionCompiler( FunctionModuleBuilder moduleBuilder, FunctionCompilerSharedData sharedData, int codeGenValueIndices) { _moduleBuilder = moduleBuilder; _sharedData = sharedData; ModuleContext = new FunctionModuleContext(_sharedData.Context, _sharedData.Module, _sharedData.FunctionImporter); _codeGenValues = new LLVMValueRef[codeGenValueIndices]; }
public static void CreateCallToCopyMemory(this FunctionModuleContext moduleContext, IRBuilder builder, LLVMValueRef destinationPtr, LLVMValueRef sourcePtr, LLVMValueRef bytesToCopy) { LLVMValueRef bytesToCopyExtend = builder.CreateSExt(bytesToCopy, moduleContext.LLVMContext.Int64Type, "bytesToCopyExtend"), sourcePtrCast = builder.CreateBitCast(sourcePtr, moduleContext.LLVMContext.BytePointerType(), "sourcePtrCast"), destinationPtrCast = builder.CreateBitCast(destinationPtr, moduleContext.LLVMContext.BytePointerType(), "destinationPtrCast"); builder.CreateCall( moduleContext.FunctionImporter.GetImportedCommonFunction(CommonModules.CopyMemoryName), new LLVMValueRef[] { destinationPtrCast, sourcePtrCast, bytesToCopyExtend }, string.Empty); }
public static LLVMValueRef GetSpecializedFunctionWithSignature(this FunctionModuleContext moduleContext, NIType specializedSignature, Action <FunctionModuleContext, NIType, LLVMValueRef> createFunction) { string specializedFunctionName = specializedSignature.MonomorphizeFunctionName(); return(moduleContext.FunctionImporter.GetCachedFunction(specializedFunctionName, () => { LLVMValueRef function = moduleContext.Module.AddFunction(specializedFunctionName, moduleContext.LLVMContext.TranslateFunctionType(specializedSignature)); createFunction(moduleContext, specializedSignature, function); return function; })); }
public static bool TryGetDropFunction(NIType type, FunctionModuleContext moduleContext, out LLVMValueRef dropFunction) { dropFunction = default(LLVMValueRef); Func <FunctionModuleContext, LLVMValueRef> dropFunctionCreator; if (TryGetDropFunctionCreator(type, out dropFunctionCreator)) { dropFunction = dropFunctionCreator(moduleContext); return(true); } return(false); }
internal static void BuildSharedGetValueFunction(FunctionModuleContext functionCompiler, NIType signature, LLVMValueRef sharedGetValueFunction) { LLVMBasicBlockRef entryBlock = sharedGetValueFunction.AppendBasicBlock("entry"); var builder = functionCompiler.LLVMContext.CreateIRBuilder(); builder.PositionBuilderAtEnd(entryBlock); LLVMValueRef shared = builder.CreateLoad(sharedGetValueFunction.GetParam(0u), "shared"), valuePtr = builder.CreateStructGEP(shared, 1u, "valuePtr"), valuePtrPtr = sharedGetValueFunction.GetParam(1u); builder.CreateStore(valuePtr, valuePtrPtr); builder.CreateRetVoid(); }
internal static void BuildSetNotifierValueFunction(FunctionModuleContext moduleContext, NIType signature, LLVMValueRef setNotifierValueFunction) { NIType valueType = signature.GetGenericParameters().First(); LLVMTypeRef valueLLVMType = moduleContext.LLVMContext.AsLLVMType(valueType); LLVMBasicBlockRef entryBlock = setNotifierValueFunction.AppendBasicBlock("entry"), readerWasWaitingBlock = setNotifierValueFunction.AppendBasicBlock("readerWasWaiting"), readerWasDroppedBlock = setNotifierValueFunction.AppendBasicBlock("readerWasDropped"), exitBlock = setNotifierValueFunction.AppendBasicBlock("exit"); var builder = moduleContext.LLVMContext.CreateIRBuilder(); builder.PositionBuilderAtEnd(entryBlock); LLVMValueRef notifierWriter = setNotifierValueFunction.GetParam(0u), value = setNotifierValueFunction.GetParam(1u), refCountPtr = builder.CreateExtractValue(notifierWriter, 0u, "refCountPtr"), sharedDataPtr = builder.CreateStructGEP(refCountPtr, 1u, "sharedDataPtr"), valuePtr = builder.CreateStructGEP(sharedDataPtr, SharedDataValueFieldIndex, "valuePtr"), statePtr = builder.CreateStructGEP(sharedDataPtr, SharedDataStateFieldIndex, "statePtr"); builder.CreateStore(value, valuePtr); // This is Release because it needs the reader thread to observe the value store above, // and Acquire because it may need to observe the reader thread's waker store below. LLVMValueRef oldState = builder.CreateAtomicRMW( LLVMAtomicRMWBinOp.LLVMAtomicRMWBinOpOr, statePtr, moduleContext.LLVMContext.AsLLVMValue(WriterDroppedWithValue), LLVMAtomicOrdering.LLVMAtomicOrderingAcquireRelease, false); LLVMValueRef oldReaderState = builder.CreateAnd(oldState, moduleContext.LLVMContext.AsLLVMValue(ReaderStateMask), "oldReaderState"), readerStateSwitch = builder.CreateSwitch(oldReaderState, exitBlock, 2u); readerStateSwitch.AddCase(moduleContext.LLVMContext.AsLLVMValue(ReaderWaitingForValue), readerWasWaitingBlock); readerStateSwitch.AddCase(moduleContext.LLVMContext.AsLLVMValue(ReaderDropped), readerWasDroppedBlock); builder.PositionBuilderAtEnd(readerWasWaitingBlock); LLVMValueRef wakerPtr = builder.CreateStructGEP(sharedDataPtr, SharedDataWakerFieldIndex, "wakerPtr"), waker = builder.CreateLoad(wakerPtr, "waker"); builder.CreateCall(moduleContext.FunctionImporter.GetImportedCommonFunction(CommonModules.InvokeName), new LLVMValueRef[] { waker }, string.Empty); builder.CreateBr(exitBlock); builder.PositionBuilderAtEnd(readerWasDroppedBlock); moduleContext.CreateDropCallIfDropFunctionExists(builder, valueType, _ => valuePtr); builder.CreateBr(exitBlock); builder.PositionBuilderAtEnd(exitBlock); LLVMValueRef decrementRefCountFunction = GetDecrementRefCountFunction(moduleContext, valueType.CreateNotifierSharedDataType()); builder.CreateCall(decrementRefCountFunction, new LLVMValueRef[] { refCountPtr }, string.Empty); builder.CreateRetVoid(); }
public static void CreateDropCallIfDropFunctionExists( this FunctionModuleContext moduleContext, IRBuilder builder, NIType droppedValueType, Func <IRBuilder, LLVMValueRef> getDroppedValuePtr) { LLVMValueRef dropFunction; if (TraitHelpers.TryGetDropFunction(droppedValueType, moduleContext, out dropFunction)) { LLVMValueRef droppedValuePtr = getDroppedValuePtr(builder); builder.CreateCall(dropFunction, new LLVMValueRef[] { droppedValuePtr }, string.Empty); } }
public FunctionCompilerSharedData( ContextWrapper context, Module module, IReadOnlyList <ParameterInfo> orderedParameters, FunctionAllocationSet allocationSet, FunctionVariableStorage variableStorage, FunctionImporter functionImporter) { Context = context; Module = module; OrderedParameters = orderedParameters; AllocationSet = allocationSet; VariableStorage = variableStorage; FunctionImporter = functionImporter; ModuleContext = new FunctionModuleContext(context, module, functionImporter); }
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(); }
internal static void BuildSharedDropFunction(FunctionModuleContext moduleContext, NIType signature, LLVMValueRef sharedDropFunction) { NIType valueType; signature.GetGenericParameters().First().TryDestructureSharedType(out valueType); LLVMBasicBlockRef entryBlock = sharedDropFunction.AppendBasicBlock("entry"); var builder = moduleContext.LLVMContext.CreateIRBuilder(); builder.PositionBuilderAtEnd(entryBlock); LLVMValueRef decrementRefCountFunction = GetDecrementRefCountFunction(moduleContext, valueType), shared = builder.CreateLoad(sharedDropFunction.GetParam(0u), "shared"); builder.CreateCall(decrementRefCountFunction, new LLVMValueRef[] { shared }, string.Empty); builder.CreateRetVoid(); }
internal static void CreateSliceToIteratorFunction(FunctionModuleContext moduleContext, NIType signature, LLVMValueRef sliceToIteratorFunction) { LLVMBasicBlockRef entryBlock = sliceToIteratorFunction.AppendBasicBlock("entry"); var builder = new IRBuilder(); builder.PositionBuilderAtEnd(entryBlock); LLVMValueRef sliceRef = sliceToIteratorFunction.GetParam(0u), sliceIteratorPtr = sliceToIteratorFunction.GetParam(1u), sliceIterator = builder.BuildStructValue( sliceIteratorPtr.TypeOf().GetElementType(), new LLVMValueRef[] { sliceRef, moduleContext.LLVMContext.AsLLVMValue(0) }, "sliceIterator"); builder.CreateStore(sliceIterator, sliceIteratorPtr); builder.CreateRetVoid(); }
internal static void BuildYieldPromisePollFunction(FunctionModuleContext moduleContext, NIType signature, LLVMValueRef yieldPromisePollFunction) { LLVMTypeRef valueType = moduleContext.LLVMContext.AsLLVMType(signature.GetGenericParameters().ElementAt(1)), valueOptionType = moduleContext.LLVMContext.CreateLLVMOptionType(valueType); LLVMBasicBlockRef entryBlock = yieldPromisePollFunction.AppendBasicBlock("entry"); var builder = moduleContext.LLVMContext.CreateIRBuilder(); builder.PositionBuilderAtEnd(entryBlock); LLVMValueRef yieldPromisePtr = yieldPromisePollFunction.GetParam(0u), valuePtr = builder.CreateStructGEP(yieldPromisePtr, 0u, "valuePtr"), value = builder.CreateLoad(valuePtr, "value"), someValue = moduleContext.LLVMContext.BuildOptionValue(builder, valueOptionType, value); builder.CreateStore(someValue, yieldPromisePollFunction.GetParam(2u)); builder.CreateRetVoid(); }
internal static void BuildVectorInitializeFunction(FunctionModuleContext moduleContext, NIType signature, LLVMValueRef vectorInitializeFunction) { LLVMTypeRef elementLLVMType = moduleContext.LLVMContext.AsLLVMType(signature.GetGenericParameters().First()); LLVMTypeRef vectorLLVMType = moduleContext.LLVMContext.CreateLLVMVectorType(elementLLVMType); LLVMBasicBlockRef entryBlock = vectorInitializeFunction.AppendBasicBlock("entry"); var builder = moduleContext.LLVMContext.CreateIRBuilder(); builder.PositionBuilderAtEnd(entryBlock); LLVMValueRef element = vectorInitializeFunction.GetParam(0u), size = vectorInitializeFunction.GetParam(1u), vectorPtr = vectorInitializeFunction.GetParam(2u), allocationPtr = moduleContext.CreateArrayMalloc(builder, elementLLVMType, size, "allocationPtr"); LLVMBasicBlockRef loopStartBlock = vectorInitializeFunction.AppendBasicBlock("loopStart"), loopBodyBlock = vectorInitializeFunction.AppendBasicBlock("loopBody"), loopEndBlock = vectorInitializeFunction.AppendBasicBlock("loopEnd"); builder.CreateBr(loopStartBlock); builder.PositionBuilderAtEnd(loopStartBlock); LLVMValueRef index = builder.CreatePhi(moduleContext.LLVMContext.Int32Type, "index"); LLVMValueRef indexLessThanSize = builder.CreateICmp(LLVMIntPredicate.LLVMIntSLT, index, size, "indexLessThanSize"); builder.CreateCondBr(indexLessThanSize, loopBodyBlock, loopEndBlock); builder.PositionBuilderAtEnd(loopBodyBlock); LLVMValueRef vectorIndexPtr = builder.CreateGEP(allocationPtr, new LLVMValueRef[] { index }, "vectorIndexPtr"); builder.CreateStore(element, vectorIndexPtr); LLVMValueRef incrementIndex = builder.CreateAdd(index, moduleContext.LLVMContext.AsLLVMValue(1), "incrementIndex"); builder.CreateBr(loopStartBlock); builder.PositionBuilderAtEnd(loopEndBlock); LLVMValueRef vector = builder.BuildStructValue( vectorLLVMType, new LLVMValueRef[] { allocationPtr, size, size }, "vector"); builder.CreateStore(vector, vectorPtr); builder.CreateRetVoid(); index.AddIncoming(moduleContext.LLVMContext.AsLLVMValue(0), entryBlock); index.AddIncoming(incrementIndex, loopBodyBlock); }
internal static void BuildVectorRemoveLastFunction(FunctionModuleContext moduleContext, NIType signature, LLVMValueRef vectorRemoveLastFunction) { NIType elementType = signature.GetGenericParameters().First(); LLVMTypeRef elementLLVMType = moduleContext.LLVMContext.AsLLVMType(elementType), elementOptionLLVMType = moduleContext.LLVMContext.CreateLLVMOptionType(elementLLVMType); LLVMBasicBlockRef entryBlock = vectorRemoveLastFunction.AppendBasicBlock("entry"), hasElementsBlock = vectorRemoveLastFunction.AppendBasicBlock("hasElements"), noElementsBlock = vectorRemoveLastFunction.AppendBasicBlock("noElements"), endBlock = vectorRemoveLastFunction.AppendBasicBlock("end"); var builder = moduleContext.LLVMContext.CreateIRBuilder(); builder.PositionBuilderAtEnd(entryBlock); LLVMValueRef vectorPtr = vectorRemoveLastFunction.GetParam(0u), vectorSizePtr = builder.CreateStructGEP(vectorPtr, 1u, "vectorSizePtr"), vectorSize = builder.CreateLoad(vectorSizePtr, "vectorSize"), optionElementPtr = vectorRemoveLastFunction.GetParam(1u), hasElements = builder.CreateICmp(LLVMIntPredicate.LLVMIntSGT, vectorSize, moduleContext.LLVMContext.AsLLVMValue(0), "hasElements"); builder.CreateCondBr(hasElements, hasElementsBlock, noElementsBlock); builder.PositionBuilderAtEnd(hasElementsBlock); LLVMValueRef vectorAllocationPtrPtr = builder.CreateStructGEP(vectorPtr, 0u, "vectorAllocationPtrPtr"), vectorAllocationPtr = builder.CreateLoad(vectorAllocationPtrPtr, "vectorAllocationPtr"), lastIndex = builder.CreateSub(vectorSize, moduleContext.LLVMContext.AsLLVMValue(1), "lastIndex"), elementToRemovePtr = builder.CreateGEP(vectorAllocationPtr, new LLVMValueRef[] { lastIndex }, "elementToRemovePtr"), elementToRemove = builder.CreateLoad(elementToRemovePtr, "elementToRemove"), someElement = moduleContext.LLVMContext.BuildOptionValue(builder, elementOptionLLVMType, elementToRemove); builder.CreateStore(lastIndex, vectorSizePtr); builder.CreateBr(endBlock); builder.PositionBuilderAtEnd(noElementsBlock); LLVMValueRef noneElement = moduleContext.LLVMContext.BuildOptionValue(builder, elementOptionLLVMType, null); builder.CreateBr(endBlock); builder.PositionBuilderAtEnd(endBlock); LLVMValueRef optionElement = builder.CreatePhi(elementOptionLLVMType, "optionElement"); optionElement.AddIncoming(someElement, hasElementsBlock); optionElement.AddIncoming(noneElement, noElementsBlock); builder.CreateStore(optionElement, optionElementPtr); builder.CreateRetVoid(); }
internal static void BuildVectorDropFunction(FunctionModuleContext moduleContext, NIType signature, LLVMValueRef vectorDropFunction) { NIType elementType; signature.GetGenericParameters().First().TryDestructureVectorType(out elementType); LLVMBasicBlockRef entryBlock = vectorDropFunction.AppendBasicBlock("entry"); var builder = moduleContext.LLVMContext.CreateIRBuilder(); builder.PositionBuilderAtEnd(entryBlock); LLVMValueRef vectorPtr = vectorDropFunction.GetParam(0u), vectorAllocationPtrPtr = builder.CreateStructGEP(vectorPtr, 0u, "vectorAllocationPtrPtr"), vectorAllocationPtr = builder.CreateLoad(vectorAllocationPtrPtr, "vectorAllocationPtr"); LLVMValueRef elementDropFunction; if (TraitHelpers.TryGetDropFunction(elementType, moduleContext, out elementDropFunction)) { LLVMValueRef vectorSizePtr = builder.CreateStructGEP(vectorPtr, 1u, "vectorSizePtr"), vectorSize = builder.CreateLoad(vectorSizePtr, "vectorSize"); LLVMBasicBlockRef loopStartBlock = vectorDropFunction.AppendBasicBlock("loopStart"), loopBodyBlock = vectorDropFunction.AppendBasicBlock("loopBody"), loopEndBlock = vectorDropFunction.AppendBasicBlock("loopEnd"); builder.CreateBr(loopStartBlock); builder.PositionBuilderAtEnd(loopStartBlock); LLVMValueRef index = builder.CreatePhi(moduleContext.LLVMContext.Int32Type, "index"); LLVMValueRef indexLessThanSize = builder.CreateICmp(LLVMIntPredicate.LLVMIntSLT, index, vectorSize, "indexLessThanSize"); builder.CreateCondBr(indexLessThanSize, loopBodyBlock, loopEndBlock); builder.PositionBuilderAtEnd(loopBodyBlock); LLVMValueRef elementPtr = builder.CreateGEP(vectorAllocationPtr, new LLVMValueRef[] { index }, "elementPtr"); builder.CreateCall(elementDropFunction, new LLVMValueRef[] { elementPtr }, string.Empty); LLVMValueRef incrementIndex = builder.CreateAdd(index, moduleContext.LLVMContext.AsLLVMValue(1), "incrementIndex"); builder.CreateBr(loopStartBlock); index.AddIncoming(moduleContext.LLVMContext.AsLLVMValue(0), entryBlock); index.AddIncoming(incrementIndex, loopBodyBlock); builder.PositionBuilderAtEnd(loopEndBlock); } builder.CreateFree(vectorAllocationPtr); builder.CreateRetVoid(); }
internal static void BuildGetNotifierReaderPromiseFunction(FunctionModuleContext moduleContext, NIType signature, LLVMValueRef getNotifierReaderPromiseFunction) { LLVMTypeRef valueType = moduleContext.LLVMContext.AsLLVMType(signature.GetGenericParameters().First()), notifierReaderType = moduleContext.LLVMContext.CreateLLVMNotifierReaderType(valueType), notifierReaderPromiseType = moduleContext.LLVMContext.CreateLLVMNotifierReaderPromiseType(valueType); LLVMBasicBlockRef entryBlock = getNotifierReaderPromiseFunction.AppendBasicBlock("entry"); var builder = moduleContext.LLVMContext.CreateIRBuilder(); builder.PositionBuilderAtEnd(entryBlock); // Transfer the refCount pointer from the reader to the promise LLVMValueRef notifierReader = getNotifierReaderPromiseFunction.GetParam(0u), refCountPtr = builder.CreateExtractValue(notifierReader, 0u, "refCountPtr"), notifierReaderPromise = builder.BuildStructValue(notifierReaderPromiseType, new[] { refCountPtr }); builder.CreateStore(notifierReaderPromise, getNotifierReaderPromiseFunction.GetParam(1u)); builder.CreateRetVoid(); }
internal static void BuildVectorCreateFunction(FunctionModuleContext moduleContext, NIType signature, LLVMValueRef vectorCreateFunction) { LLVMTypeRef elementLLVMType = moduleContext.LLVMContext.AsLLVMType(signature.GetGenericParameters().First()); LLVMBasicBlockRef entryBlock = vectorCreateFunction.AppendBasicBlock("entry"); var builder = moduleContext.LLVMContext.CreateIRBuilder(); builder.PositionBuilderAtEnd(entryBlock); LLVMValueRef vectorPtr = vectorCreateFunction.GetParam(0u), vectorCapacity = moduleContext.LLVMContext.AsLLVMValue(4), allocationPtr = moduleContext.CreateArrayMalloc(builder, elementLLVMType, vectorCapacity, "allocationPtr"), vector = builder.BuildStructValue( moduleContext.LLVMContext.CreateLLVMVectorType(elementLLVMType), new LLVMValueRef[] { allocationPtr, moduleContext.LLVMContext.AsLLVMValue(0), vectorCapacity }, "vector"); builder.CreateStore(vector, vectorPtr); builder.CreateRetVoid(); }
internal static void BuildVectorToSliceFunction(FunctionModuleContext moduleContext, NIType signature, LLVMValueRef vectorToSliceFunction) { LLVMTypeRef sliceElementType = moduleContext.LLVMContext.AsLLVMType(signature.GetGenericParameters().First()); LLVMTypeRef sliceReferenceType = moduleContext.LLVMContext.CreateLLVMSliceReferenceType(sliceElementType); LLVMBasicBlockRef entryBlock = vectorToSliceFunction.AppendBasicBlock("entry"); var builder = moduleContext.LLVMContext.CreateIRBuilder(); builder.PositionBuilderAtEnd(entryBlock); LLVMValueRef vectorPtr = vectorToSliceFunction.GetParam(0u), vectorBufferPtrPtr = builder.CreateStructGEP(vectorPtr, 0u, "vectorBufferPtrPtr"), vectorBufferPtr = builder.CreateLoad(vectorBufferPtrPtr, "vectorBufferPtr"), vectorSizePtr = builder.CreateStructGEP(vectorPtr, 1u, "vectorSizePtr"), vectorSize = builder.CreateLoad(vectorSizePtr, "vectorSize"), sliceRef = builder.BuildSliceReferenceValue(sliceReferenceType, vectorBufferPtr, vectorSize); builder.CreateStore(sliceRef, vectorToSliceFunction.GetParam(1u)); builder.CreateRetVoid(); }
internal static void BuildNotifierWriterDropFunction(FunctionModuleContext moduleContext, NIType signature, LLVMValueRef notifierValueDropFunction) { NIType notifierWriterType = signature.GetGenericParameters().First(), valueType = notifierWriterType.GetGenericParameters().First(); LLVMBasicBlockRef entryBlock = notifierValueDropFunction.AppendBasicBlock("entry"), readerWasWaitingBlock = notifierValueDropFunction.AppendBasicBlock("readerWasWaiting"), exitBlock = notifierValueDropFunction.AppendBasicBlock("exit"); var builder = moduleContext.LLVMContext.CreateIRBuilder(); builder.PositionBuilderAtEnd(entryBlock); LLVMValueRef notifierWriterPtr = notifierValueDropFunction.GetParam(0u), notifierWriter = builder.CreateLoad(notifierWriterPtr, "notifierWriter"), refCountPtr = builder.CreateExtractValue(notifierWriter, 0u, "refCountPtr"), sharedDataPtr = builder.CreateStructGEP(refCountPtr, 1u, "sharedDataPtr"), valuePtr = builder.CreateStructGEP(sharedDataPtr, SharedDataValueFieldIndex, "valuePtr"), statePtr = builder.CreateStructGEP(sharedDataPtr, SharedDataStateFieldIndex, "statePtr"); // This is Acquire because it may need to observe the reader thread's waker store below. LLVMValueRef oldState = builder.CreateAtomicRMW( LLVMAtomicRMWBinOp.LLVMAtomicRMWBinOpOr, statePtr, moduleContext.LLVMContext.AsLLVMValue(WriterDroppedWithoutValue), LLVMAtomicOrdering.LLVMAtomicOrderingAcquire, false); LLVMValueRef oldReaderState = builder.CreateAnd(oldState, moduleContext.LLVMContext.AsLLVMValue(ReaderStateMask), "oldReaderState"), readerWasWaiting = builder.CreateICmp(LLVMIntPredicate.LLVMIntEQ, oldReaderState, moduleContext.LLVMContext.AsLLVMValue(ReaderWaitingForValue), "readerWasWaiting"); builder.CreateCondBr(readerWasWaiting, readerWasWaitingBlock, exitBlock); builder.PositionBuilderAtEnd(readerWasWaitingBlock); LLVMValueRef wakerPtr = builder.CreateStructGEP(sharedDataPtr, SharedDataWakerFieldIndex, "wakerPtr"), waker = builder.CreateLoad(wakerPtr, "waker"); builder.CreateCall(moduleContext.FunctionImporter.GetImportedCommonFunction(CommonModules.InvokeName), new LLVMValueRef[] { waker }, string.Empty); builder.CreateBr(exitBlock); builder.PositionBuilderAtEnd(exitBlock); LLVMValueRef decrementRefCountFunction = GetDecrementRefCountFunction(moduleContext, valueType.CreateNotifierSharedDataType()); builder.CreateCall(decrementRefCountFunction, new LLVMValueRef[] { refCountPtr }, string.Empty); builder.CreateRetVoid(); }