| 106 | } |
| 107 | |
| 108 | static void compileFunction(llvm::Module & module, const IFunctionBase & function) |
| 109 | { |
| 110 | const auto & function_argument_types = function.getArgumentTypes(); |
| 111 | |
| 112 | llvm::IRBuilder<> b(module.getContext()); |
| 113 | auto * size_type = b.getIntNTy(sizeof(size_t) * 8); |
| 114 | auto * data_type = buildColumnDataStruct(b); |
| 115 | auto * func_type = llvm::FunctionType::get(b.getVoidTy(), { size_type, data_type->getPointerTo() }, /*isVarArg=*/false); |
| 116 | |
| 117 | /// Create function in module |
| 118 | |
| 119 | auto * func = llvm::Function::Create(func_type, llvm::Function::ExternalLinkage, function.getName(), module); |
| 120 | auto * args = func->args().begin(); |
| 121 | llvm::Value * rows_count_arg = args++; |
| 122 | llvm::Value * columns_arg = args++; |
| 123 | |
| 124 | /// Initialize ColumnDataPlaceholder llvm representation of ColumnData |
| 125 | |
| 126 | auto * entry = llvm::BasicBlock::Create(b.getContext(), "entry", func); |
| 127 | b.SetInsertPoint(entry); |
| 128 | |
| 129 | std::vector<ColumnDataPlaceholder> columns(function_argument_types.size() + 1); |
| 130 | for (size_t i = 0; i <= function_argument_types.size(); ++i) |
| 131 | { |
| 132 | const auto & function_argument_type = i == function_argument_types.size() ? function.getResultType() : function_argument_types[i]; |
| 133 | auto * data = b.CreateLoad(data_type, b.CreateConstInBoundsGEP1_64(data_type, columns_arg, i)); |
| 134 | columns[i].data_ptr = b.CreateExtractValue(data, {0}); |
| 135 | columns[i].data_element_type = toNativeType(b, removeNullable(function_argument_type)); |
| 136 | columns[i].null_data_ptr = function_argument_type->isNullable() ? b.CreateExtractValue(data, {1}) : nullptr; |
| 137 | } |
| 138 | |
| 139 | /// Initialize loop |
| 140 | |
| 141 | auto * end = llvm::BasicBlock::Create(b.getContext(), "end", func); |
| 142 | auto * loop = llvm::BasicBlock::Create(b.getContext(), "loop", func); |
| 143 | b.CreateCondBr(b.CreateICmpEQ(rows_count_arg, llvm::ConstantInt::get(size_type, 0)), end, loop); |
| 144 | |
| 145 | b.SetInsertPoint(loop); |
| 146 | |
| 147 | /// Loop |
| 148 | |
| 149 | auto * counter_phi = b.CreatePHI(rows_count_arg->getType(), 2); |
| 150 | counter_phi->addIncoming(llvm::ConstantInt::get(size_type, 0), entry); |
| 151 | |
| 152 | /// Initialize column row values |
| 153 | |
| 154 | ValuesWithType arguments; |
| 155 | arguments.reserve(function_argument_types.size()); |
| 156 | |
| 157 | for (size_t i = 0; i < function_argument_types.size(); ++i) |
| 158 | { |
| 159 | auto & column = columns[i]; |
| 160 | const auto & type = function_argument_types[i]; |
| 161 | |
| 162 | auto * column_data_ptr = column.data_ptr; |
| 163 | auto * column_element_value = b.CreateLoad(column.data_element_type, b.CreateInBoundsGEP(column.data_element_type, column_data_ptr, counter_phi)); |
| 164 | |
| 165 | if (!type->isNullable()) |
no test coverage detected