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(); }
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 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(); }
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); }