diff --git a/.github/workflows/cpp.yml b/.github/workflows/cpp.yml index 2642a6ec1a2..9c7e09382ab 100644 --- a/.github/workflows/cpp.yml +++ b/.github/workflows/cpp.yml @@ -56,7 +56,7 @@ jobs: name: ${{ matrix.title }} runs-on: ubuntu-latest if: ${{ !contains(github.event.pull_request.title, 'WIP') }} - timeout-minutes: 60 + timeout-minutes: 75 strategy: fail-fast: false matrix: @@ -122,7 +122,7 @@ jobs: name: AMD64 macOS 11 C++ runs-on: macos-latest if: ${{ !contains(github.event.pull_request.title, 'WIP') }} - timeout-minutes: 60 + timeout-minutes: 75 strategy: fail-fast: false env: @@ -179,7 +179,11 @@ jobs: key: cpp-ccache-macos-${{ hashFiles('cpp/**') }} restore-keys: cpp-ccache-macos- - name: Build - run: ci/scripts/cpp_build.sh $(pwd) $(pwd)/build + # use brew version of clang, to be consistent with LLVM lib, see ARROW-17790. + run: | + export CC=$(brew --prefix llvm)/bin/clang + export CXX=$(brew --prefix llvm)/bin/clang++ + ci/scripts/cpp_build.sh $(pwd) $(pwd)/build - name: Test shell: bash run: | diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 5ccbceabea7..1c72f1b706c 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -160,7 +160,10 @@ jobs: -r python/requirements-test.txt - name: Build shell: bash + # use brew version of clang, to be consistent with LLVM lib, see ARROW-17790. run: | + export CC=$(brew --prefix llvm)/bin/clang + export CXX=$(brew --prefix llvm)/bin/clang++ export PYTHON=python3 ci/scripts/cpp_build.sh $(pwd) $(pwd)/build ci/scripts/python_build.sh $(pwd) $(pwd)/build diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 4dd61befab6..35cc1b1c29d 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -164,7 +164,10 @@ jobs: key: ruby-ccache-macos-${{ hashFiles('cpp/**') }} restore-keys: ruby-ccache-macos- - name: Build C++ + # use brew version of clang, to be consistent with LLVM lib, see ARROW-17790. run: | + export CC=$(brew --prefix llvm)/bin/clang + export CXX=$(brew --prefix llvm)/bin/clang++ ci/scripts/cpp_build.sh $(pwd) $(pwd)/build - name: Build GLib run: | diff --git a/cpp/src/arrow/array/array_test.cc b/cpp/src/arrow/array/array_test.cc index c00e54ecb80..d4ad1578b77 100644 --- a/cpp/src/arrow/array/array_test.cc +++ b/cpp/src/arrow/array/array_test.cc @@ -2831,8 +2831,6 @@ class DecimalTest : public ::testing::TestWithParam { auto type = std::make_shared(precision, 4); auto builder = std::make_shared(type); - size_t null_count = 0; - const size_t size = draw.size(); ARROW_EXPECT_OK(builder->Reserve(size)); @@ -2842,7 +2840,6 @@ class DecimalTest : public ::testing::TestWithParam { ARROW_EXPECT_OK(builder->Append(draw[i])); } else { ARROW_EXPECT_OK(builder->AppendNull()); - ++null_count; } } diff --git a/cpp/src/arrow/filesystem/gcsfs_test.cc b/cpp/src/arrow/filesystem/gcsfs_test.cc index 48d56f7b7bb..f64834e591b 100644 --- a/cpp/src/arrow/filesystem/gcsfs_test.cc +++ b/cpp/src/arrow/filesystem/gcsfs_test.cc @@ -17,6 +17,7 @@ #include // Missing include in boost/process +#define BOOST_NO_CXX98_FUNCTION_BASE // ARROW-17805 // This boost/asio/io_context.hpp include is needless for no MinGW // build. // diff --git a/cpp/src/arrow/filesystem/s3_test_util.cc b/cpp/src/arrow/filesystem/s3_test_util.cc index f5a054a8efa..d7e0cbc92d7 100644 --- a/cpp/src/arrow/filesystem/s3_test_util.cc +++ b/cpp/src/arrow/filesystem/s3_test_util.cc @@ -34,6 +34,7 @@ #ifdef __MINGW32__ #include #endif +#define BOOST_NO_CXX98_FUNCTION_BASE // ARROW-17805 // We need BOOST_USE_WINDOWS_H definition with MinGW when we use // boost/process.hpp. See BOOST_USE_WINDOWS_H=1 in // cpp/cmake_modules/ThirdpartyToolchain.cmake for details. diff --git a/cpp/src/arrow/flight/test_util.cc b/cpp/src/arrow/flight/test_util.cc index d858c15db6d..41e4dcaeddb 100644 --- a/cpp/src/arrow/flight/test_util.cc +++ b/cpp/src/arrow/flight/test_util.cc @@ -30,11 +30,12 @@ // We need Windows fixes before including Boost #include "arrow/util/windows_compatibility.h" +#include #include +#define BOOST_NO_CXX98_FUNCTION_BASE // ARROW-17805 // We need BOOST_USE_WINDOWS_H definition with MinGW when we use // boost/process.hpp. See BOOST_USE_WINDOWS_H=1 in // cpp/cmake_modules/ThirdpartyToolchain.cmake for details. -#include #include #include "arrow/array.h" diff --git a/cpp/src/gandiva/decimal_ir.cc b/cpp/src/gandiva/decimal_ir.cc index 5d5d30b4a75..b22e7ad5b5e 100644 --- a/cpp/src/gandiva/decimal_ir.cc +++ b/cpp/src/gandiva/decimal_ir.cc @@ -96,8 +96,9 @@ void DecimalIR::InitializeIntrinsics() { // CPP: return kScaleMultipliers[scale] llvm::Value* DecimalIR::GetScaleMultiplier(llvm::Value* scale) { auto const_array = module()->getGlobalVariable(kScaleMultipliersName); - auto ptr = CreateGEP(ir_builder(), const_array, {types()->i32_constant(0), scale}); - return CreateLoad(ir_builder(), ptr); + auto ptr = ir_builder()->CreateGEP(const_array->getValueType(), const_array, + {types()->i32_constant(0), scale}); + return ir_builder()->CreateLoad(types()->i128_type(), ptr); } // CPP: x <= y ? y : x @@ -248,8 +249,8 @@ llvm::Value* DecimalIR::AddLarge(const ValueFull& x, const ValueFull& y, ir_builder()->CreateCall(module()->getFunction("add_large_decimal128_decimal128"), args); - auto out_high = CreateLoad(ir_builder(), out_high_ptr); - auto out_low = CreateLoad(ir_builder(), out_low_ptr); + auto out_high = ir_builder()->CreateLoad(types()->i64_type(), out_high_ptr); + auto out_low = ir_builder()->CreateLoad(types()->i64_type(), out_low_ptr); auto sum = ValueSplit(out_high, out_low).AsInt128(this); ADD_TRACE_128("AddLarge : sum", sum); return sum; @@ -445,8 +446,8 @@ llvm::Value* DecimalIR::CallDecimalFunction(const std::string& function_name, // Make call to pre-compiled IR function. ir_builder()->CreateCall(module()->getFunction(function_name), dis_assembled_args); - auto out_high = CreateLoad(ir_builder(), out_high_ptr); - auto out_low = CreateLoad(ir_builder(), out_low_ptr); + auto out_high = ir_builder()->CreateLoad(i64, out_high_ptr); + auto out_low = ir_builder()->CreateLoad(i64, out_low_ptr); result = ValueSplit(out_high, out_low).AsInt128(this); } else { DCHECK_NE(return_type, types()->void_type()); diff --git a/cpp/src/gandiva/engine.cc b/cpp/src/gandiva/engine.cc index 3bd52917756..8d1057e9c57 100644 --- a/cpp/src/gandiva/engine.cc +++ b/cpp/src/gandiva/engine.cc @@ -234,11 +234,11 @@ Status Engine::LoadPreCompiledIR() { Status::CodeGenError("Could not load module from IR: ", buffer_or_error.getError().message())); - std::unique_ptr buffer = move(buffer_or_error.get()); + std::unique_ptr buffer = std::move(buffer_or_error.get()); /// Parse the IR module. llvm::Expected> module_or_error = - llvm::getOwningLazyBitcodeModule(move(buffer), *context()); + llvm::getOwningLazyBitcodeModule(std::move(buffer), *context()); if (!module_or_error) { // NOTE: llvm::handleAllErrors() fails linking with RTTI-disabled LLVM builds // (ARROW-5148) @@ -247,14 +247,14 @@ Status Engine::LoadPreCompiledIR() { stream << module_or_error.takeError(); return Status::CodeGenError(stream.str()); } - std::unique_ptr ir_module = move(module_or_error.get()); + std::unique_ptr ir_module = std::move(module_or_error.get()); // set dataLayout SetDataLayout(ir_module.get()); ARROW_RETURN_IF(llvm::verifyModule(*ir_module, &llvm::errs()), Status::CodeGenError("verify of IR Module failed")); - ARROW_RETURN_IF(llvm::Linker::linkModules(*module_, move(ir_module)), + ARROW_RETURN_IF(llvm::Linker::linkModules(*module_, std::move(ir_module)), Status::CodeGenError("failed to link IR Modules")); return Status::OK(); diff --git a/cpp/src/gandiva/engine_llvm_test.cc b/cpp/src/gandiva/engine_llvm_test.cc index 0bf6413cf65..9baaa82d2e0 100644 --- a/cpp/src/gandiva/engine_llvm_test.cc +++ b/cpp/src/gandiva/engine_llvm_test.cc @@ -80,8 +80,9 @@ class TestEngine : public ::testing::Test { loop_var->addIncoming(loop_update, loop_body); // get the current value - llvm::Value* offset = CreateGEP(builder, arg_elements, loop_var, "offset"); - llvm::Value* current_value = CreateLoad(builder, offset, "value"); + llvm::Value* offset = + builder->CreateGEP(types->i64_type(), arg_elements, loop_var, "offset"); + llvm::Value* current_value = builder->CreateLoad(types->i64_type(), offset, "value"); // setup sum PHI llvm::Value* sum_update = builder->CreateAdd(sum, current_value, "sum+ith"); diff --git a/cpp/src/gandiva/llvm_generator.cc b/cpp/src/gandiva/llvm_generator.cc index 58efef9676f..06159099745 100644 --- a/cpp/src/gandiva/llvm_generator.cc +++ b/cpp/src/gandiva/llvm_generator.cc @@ -26,6 +26,7 @@ #include "gandiva/dex.h" #include "gandiva/expr_decomposer.h" #include "gandiva/expression.h" +#include "gandiva/llvm_types.h" #include "gandiva/lvalue.h" namespace gandiva { @@ -162,18 +163,18 @@ Status LLVMGenerator::Execute(const arrow::RecordBatch& record_batch, return Status::OK(); } -llvm::Value* LLVMGenerator::LoadVectorAtIndex(llvm::Value* arg_addrs, int idx, - const std::string& name) { +llvm::Value* LLVMGenerator::LoadVectorAtIndex(llvm::Value* arg_addrs, llvm::Type* type, + int idx, const std::string& name) { auto* idx_val = types()->i32_constant(idx); - auto* offset = CreateGEP(ir_builder(), arg_addrs, idx_val, name + "_mem_addr"); - return CreateLoad(ir_builder(), offset, name + "_mem"); + auto* offset = ir_builder()->CreateGEP(type, arg_addrs, idx_val, name + "_mem_addr"); + return ir_builder()->CreateLoad(type, offset, name + "_mem"); } /// Get reference to validity array at specified index in the args list. llvm::Value* LLVMGenerator::GetValidityReference(llvm::Value* arg_addrs, int idx, FieldPtr field) { const std::string& name = field->name(); - llvm::Value* load = LoadVectorAtIndex(arg_addrs, idx, name); + llvm::Value* load = LoadVectorAtIndex(arg_addrs, types()->i64_type(), idx, name); return ir_builder()->CreateIntToPtr(load, types()->i64_ptr_type(), name + "_varray"); } @@ -181,7 +182,7 @@ llvm::Value* LLVMGenerator::GetValidityReference(llvm::Value* arg_addrs, int idx llvm::Value* LLVMGenerator::GetDataBufferPtrReference(llvm::Value* arg_addrs, int idx, FieldPtr field) { const std::string& name = field->name(); - llvm::Value* load = LoadVectorAtIndex(arg_addrs, idx, name); + llvm::Value* load = LoadVectorAtIndex(arg_addrs, types()->i64_type(), idx, name); return ir_builder()->CreateIntToPtr(load, types()->i8_ptr_type(), name + "_buf_ptr"); } @@ -189,7 +190,7 @@ llvm::Value* LLVMGenerator::GetDataBufferPtrReference(llvm::Value* arg_addrs, in llvm::Value* LLVMGenerator::GetDataReference(llvm::Value* arg_addrs, int idx, FieldPtr field) { const std::string& name = field->name(); - llvm::Value* load = LoadVectorAtIndex(arg_addrs, idx, name); + llvm::Value* load = LoadVectorAtIndex(arg_addrs, types()->i64_type(), idx, name); llvm::Type* base_type = types()->DataVecType(field->type()); llvm::Value* ret; if (base_type->isPointerTy()) { @@ -205,13 +206,13 @@ llvm::Value* LLVMGenerator::GetDataReference(llvm::Value* arg_addrs, int idx, llvm::Value* LLVMGenerator::GetOffsetsReference(llvm::Value* arg_addrs, int idx, FieldPtr field) { const std::string& name = field->name(); - llvm::Value* load = LoadVectorAtIndex(arg_addrs, idx, name); + llvm::Value* load = LoadVectorAtIndex(arg_addrs, types()->i64_type(), idx, name); return ir_builder()->CreateIntToPtr(load, types()->i32_ptr_type(), name + "_oarray"); } /// Get reference to local bitmap array at specified index in the args list. llvm::Value* LLVMGenerator::GetLocalBitMapReference(llvm::Value* arg_bitmaps, int idx) { - llvm::Value* load = LoadVectorAtIndex(arg_bitmaps, idx, ""); + llvm::Value* load = LoadVectorAtIndex(arg_bitmaps, types()->i64_type(), idx, ""); return ir_builder()->CreateIntToPtr(load, types()->i64_ptr_type(), std::to_string(idx) + "_lbmap"); } @@ -278,16 +279,21 @@ Status LLVMGenerator::CodeGenExprValue(DexPtr value_expr, int buffer_count, arguments.push_back(types()->i64_ptr_type()); // offsets arguments.push_back(types()->i64_ptr_type()); // bitmaps arguments.push_back(types()->i64_ptr_type()); // holders + llvm::Type* selection_vector_type; switch (selection_vector_mode) { case SelectionVector::MODE_NONE: case SelectionVector::MODE_UINT16: arguments.push_back(types()->ptr_type(types()->i16_type())); + selection_vector_type = types()->i16_type(); break; case SelectionVector::MODE_UINT32: arguments.push_back(types()->i32_ptr_type()); + selection_vector_type = types()->i32_type(); break; case SelectionVector::MODE_UINT64: arguments.push_back(types()->i64_ptr_type()); + selection_vector_type = types()->i64_type(); + break; } arguments.push_back(types()->i64_type()); // ctx_ptr arguments.push_back(types()->i64_type()); // nrec @@ -338,8 +344,9 @@ Status LLVMGenerator::CodeGenExprValue(DexPtr value_expr, int buffer_count, std::vector slice_offsets; for (int idx = 0; idx < buffer_count; idx++) { - auto offsetAddr = CreateGEP(builder, arg_addr_offsets, types()->i32_constant(idx)); - auto offset = CreateLoad(builder, offsetAddr); + auto offsetAddr = builder->CreateGEP(types()->i64_type(), arg_addr_offsets, + types()->i32_constant(idx)); + auto offset = builder->CreateLoad(types()->i64_type(), offsetAddr); slice_offsets.push_back(offset); } @@ -351,9 +358,11 @@ Status LLVMGenerator::CodeGenExprValue(DexPtr value_expr, int buffer_count, llvm::Value* position_var = loop_var; if (selection_vector_mode != SelectionVector::MODE_NONE) { + auto selection_vector_addr = + builder->CreateGEP(selection_vector_type, arg_selection_vector, loop_var); position_var = builder->CreateIntCast( - CreateLoad(builder, CreateGEP(builder, arg_selection_vector, loop_var), - "uncasted_position_var"), + builder->CreateLoad(selection_vector_type, selection_vector_addr, + "uncasted_position_var"), types()->i64_type(), true, "position_var"); } @@ -378,7 +387,8 @@ Status LLVMGenerator::CodeGenExprValue(DexPtr value_expr, int buffer_count, SetPackedBitValue(output_ref, loop_var, output_value->data()); } else if (arrow::is_primitive(output_type_id) || output_type_id == arrow::Type::DECIMAL) { - llvm::Value* slot_offset = CreateGEP(builder, output_ref, loop_var); + auto slot_offset = + builder->CreateGEP(types()->IRType(output_type_id), output_ref, loop_var); builder->CreateStore(output_value->data(), slot_offset); } else if (arrow::is_binary_like(output_type_id)) { // Var-len output. Make a function call to populate the data. @@ -564,6 +574,7 @@ LLVMGenerator::Visitor::Visitor(LLVMGenerator* generator, llvm::Function* functi void LLVMGenerator::Visitor::Visit(const VectorReadFixedLenValueDex& dex) { llvm::IRBuilder<>* builder = ir_builder(); + auto types = generator_->types(); llvm::Value* slot_ref = GetBufferReference(dex.DataIdx(), kBufferTypeData, dex.Field()); llvm::Value* slot_index = builder->CreateAdd(loop_var_, GetSliceOffset(dex.DataIdx())); llvm::Value* slot_value; @@ -576,15 +587,16 @@ void LLVMGenerator::Visitor::Visit(const VectorReadFixedLenValueDex& dex) { break; case arrow::Type::DECIMAL: { - auto slot_offset = CreateGEP(builder, slot_ref, slot_index); - slot_value = CreateLoad(builder, slot_offset, dex.FieldName()); + auto slot_offset = builder->CreateGEP(types->i128_type(), slot_ref, slot_index); + slot_value = builder->CreateLoad(types->i128_type(), slot_offset, dex.FieldName()); lvalue = generator_->BuildDecimalLValue(slot_value, dex.FieldType()); break; } default: { - auto slot_offset = CreateGEP(builder, slot_ref, slot_index); - slot_value = CreateLoad(builder, slot_offset, dex.FieldName()); + auto type = types->IRType(dex.FieldType()->id()); + auto slot_offset = builder->CreateGEP(type, slot_ref, slot_index); + slot_value = builder->CreateLoad(type, slot_offset, dex.FieldName()); lvalue = std::make_shared(slot_value); break; } @@ -597,6 +609,7 @@ void LLVMGenerator::Visitor::Visit(const VectorReadFixedLenValueDex& dex) { void LLVMGenerator::Visitor::Visit(const VectorReadVarLenValueDex& dex) { llvm::IRBuilder<>* builder = ir_builder(); llvm::Value* slot; + auto types = generator_->types(); // compute len from the offsets array. llvm::Value* offsets_slot_ref = @@ -605,14 +618,15 @@ void LLVMGenerator::Visitor::Visit(const VectorReadVarLenValueDex& dex) { builder->CreateAdd(loop_var_, GetSliceOffset(dex.OffsetsIdx())); // => offset_start = offsets[loop_var] - slot = CreateGEP(builder, offsets_slot_ref, offsets_slot_index); - llvm::Value* offset_start = CreateLoad(builder, slot, "offset_start"); + slot = builder->CreateGEP(types->i32_type(), offsets_slot_ref, offsets_slot_index); + llvm::Value* offset_start = + builder->CreateLoad(types->i32_type(), slot, "offset_start"); // => offset_end = offsets[loop_var + 1] llvm::Value* offsets_slot_index_next = builder->CreateAdd( offsets_slot_index, generator_->types()->i64_constant(1), "loop_var+1"); - slot = CreateGEP(builder, offsets_slot_ref, offsets_slot_index_next); - llvm::Value* offset_end = CreateLoad(builder, slot, "offset_end"); + slot = builder->CreateGEP(types->i32_type(), offsets_slot_ref, offsets_slot_index_next); + auto offset_end = builder->CreateLoad(types->i32_type(), slot, "offset_end"); // => len_value = offset_end - offset_start llvm::Value* len_value = @@ -621,7 +635,7 @@ void LLVMGenerator::Visitor::Visit(const VectorReadVarLenValueDex& dex) { // get the data from the data array, at offset 'offset_start'. llvm::Value* data_slot_ref = GetBufferReference(dex.DataIdx(), kBufferTypeData, dex.Field()); - llvm::Value* data_value = CreateGEP(builder, data_slot_ref, offset_start); + auto data_value = builder->CreateGEP(types->i8_type(), data_slot_ref, offset_start); ADD_VISITOR_TRACE("visit var-len data vector " + dex.FieldName() + " len %T", len_value); result_.reset(new LValue(data_value, len_value)); @@ -831,7 +845,7 @@ void LLVMGenerator::Visitor::Visit(const NullableInternalFuncDex& dex) { result_ = BuildFunctionCall(native_function, arrow_return_type, ¶ms); // load the result validity and truncate to i1. - llvm::Value* result_valid_i8 = CreateLoad(builder, result_valid_ptr); + auto result_valid_i8 = builder->CreateLoad(types->i8_type(), result_valid_ptr); llvm::Value* result_valid = builder->CreateTrunc(result_valid_i8, types->i1_type()); // set validity bit in the local bitmap. @@ -1038,7 +1052,7 @@ void LLVMGenerator::Visitor::VisitInExpression(const InExprDexBase& dex) { builder->SetInsertPoint(entry_block_); llvm::Value* in_holder = generator_->LoadVectorAtIndex( - arg_holder_ptrs_, dex_instance.get_holder_idx(), "in_holder"); + arg_holder_ptrs_, types->i64_type(), dex_instance.get_holder_idx(), "in_holder"); builder->SetInsertPoint(saved_block); params.push_back(in_holder); @@ -1255,7 +1269,9 @@ LValuePtr LLVMGenerator::Visitor::BuildFunctionCall(const NativeFunction* func, ? decimalIR.CallDecimalFunction(func->pc_name(), llvm_return_type, *params) : generator_->AddFunctionCall(func->pc_name(), llvm_return_type, *params); auto value_len = - (result_len_ptr == nullptr) ? nullptr : CreateLoad(builder, result_len_ptr); + (result_len_ptr == nullptr) + ? nullptr + : builder->CreateLoad(result_len_ptr->getAllocatedType(), result_len_ptr); return std::make_shared(value, value_len); } } @@ -1278,8 +1294,8 @@ std::vector LLVMGenerator::Visitor::BuildParams( llvm::BasicBlock* saved_block = builder->GetInsertBlock(); builder->SetInsertPoint(entry_block_); - llvm::Value* holder = - generator_->LoadVectorAtIndex(arg_holder_ptrs_, holder_idx, "holder"); + auto holder = generator_->LoadVectorAtIndex( + arg_holder_ptrs_, generator_->types()->i64_type(), holder_idx, "holder"); builder->SetInsertPoint(saved_block); params.push_back(holder); diff --git a/cpp/src/gandiva/llvm_generator.h b/cpp/src/gandiva/llvm_generator.h index 693119128ea..fa13af74350 100644 --- a/cpp/src/gandiva/llvm_generator.h +++ b/cpp/src/gandiva/llvm_generator.h @@ -183,7 +183,7 @@ class GANDIVA_EXPORT LLVMGenerator { Status Add(const ExpressionPtr expr, const FieldDescriptorPtr output); /// Generate code to load the vector at specified index in the 'arg_addrs' array. - llvm::Value* LoadVectorAtIndex(llvm::Value* arg_addrs, int idx, + llvm::Value* LoadVectorAtIndex(llvm::Value* arg_addrs, llvm::Type* type, int idx, const std::string& name); /// Generate code to load the vector at specified index and cast it as bitmap. diff --git a/cpp/src/gandiva/llvm_includes.h b/cpp/src/gandiva/llvm_includes.h index 37f915eb571..3d455591895 100644 --- a/cpp/src/gandiva/llvm_includes.h +++ b/cpp/src/gandiva/llvm_includes.h @@ -41,16 +41,3 @@ #if defined(_MSC_VER) #pragma warning(pop) #endif - -// Workaround for deprecated builder methods as of LLVM 13: ARROW-14363 -inline llvm::Value* CreateGEP(llvm::IRBuilder<>* builder, llvm::Value* Ptr, - llvm::ArrayRef IdxList, - const llvm::Twine& Name = "") { - return builder->CreateGEP(Ptr->getType()->getScalarType()->getPointerElementType(), Ptr, - IdxList, Name); -} - -inline llvm::LoadInst* CreateLoad(llvm::IRBuilder<>* builder, llvm::Value* Ptr, - const llvm::Twine& Name = "") { - return builder->CreateLoad(Ptr->getType()->getPointerElementType(), Ptr, Name); -}