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 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 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 AddIncoming(this LLVMValueRef phiValue, LLVMValueRef incomingValue, LLVMBasicBlockRef incomingBlock) { phiValue.AddIncoming(new LLVMValueRef[] { incomingValue }, new LLVMBasicBlockRef[] { incomingBlock }, 1u); }