// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

// TODO(wesm): LLVM 7 produces pesky C4244 that disable pragmas around the LLVM
// includes seem to not fix as with LLVM 6
#if defined(_MSC_VER)
#  pragma warning(disable : 4244)
#endif

#include "gandiva/engine.h"

#include <iostream>
#include <memory>
#include <mutex>
#include <sstream>
#include <string>
#include <unordered_set>
#include <utility>

#include <arrow/util/io_util.h>
#include <arrow/util/logging_internal.h>

#if defined(_MSC_VER)
#  pragma warning(push)
#  pragma warning(disable : 4141)
#  pragma warning(disable : 4146)
#  pragma warning(disable : 4244)
#  pragma warning(disable : 4267)
#  pragma warning(disable : 4624)
#endif

#include <llvm/Analysis/Passes.h>
#include <llvm/Analysis/TargetTransformInfo.h>
#include <llvm/Bitcode/BitcodeReader.h>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
#include <llvm/ExecutionEngine/Orc/LLJIT.h>
#include <llvm/IR/DataLayout.h>
#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/LegacyPassManager.h>
#include <llvm/IR/Verifier.h>
#include <llvm/Linker/Linker.h>
#include <llvm/Transforms/Utils/Cloning.h>
#if LLVM_VERSION_MAJOR >= 17
#  include <llvm/TargetParser/SubtargetFeature.h>
#else
#  include <llvm/MC/SubtargetFeature.h>
#endif
#include <llvm/Passes/PassBuilder.h>
#include <llvm/Support/DynamicLibrary.h>
#if LLVM_VERSION_MAJOR >= 18
#  include <llvm/TargetParser/Host.h>
#else
#  include <llvm/Support/Host.h>
#endif
#include <llvm/Transforms/IPO/GlobalDCE.h>
#include <llvm/Transforms/IPO/Internalize.h>
#if LLVM_VERSION_MAJOR >= 14
#  include <llvm/IR/PassManager.h>
#  include <llvm/MC/TargetRegistry.h>
#  include <llvm/Passes/PassPlugin.h>
#  include <llvm/Transforms/IPO/GlobalOpt.h>
#  include <llvm/Transforms/Scalar/NewGVN.h>
#  include <llvm/Transforms/Scalar/SimplifyCFG.h>
#  include <llvm/Transforms/Utils/Mem2Reg.h>
#  include <llvm/Transforms/Vectorize/LoopVectorize.h>
#  include <llvm/Transforms/Vectorize/SLPVectorizer.h>
#else
#  include <llvm/Support/TargetRegistry.h>
#  include <llvm/Transforms/IPO/PassManagerBuilder.h>
#endif
#include <llvm/Support/TargetSelect.h>
#include <llvm/Support/raw_ostream.h>
#include <llvm/Transforms/IPO.h>
#include <llvm/Transforms/InstCombine/InstCombine.h>
#include <llvm/Transforms/Scalar.h>
#include <llvm/Transforms/Scalar/GVN.h>
#include <llvm/Transforms/Utils.h>
#if LLVM_VERSION_MAJOR <= 17
#  include <llvm/Transforms/Vectorize.h>
#endif

// JITLink is available in LLVM 9+
// but the `InProcessMemoryManager::Create` API was added since LLVM 14
#if LLVM_VERSION_MAJOR >= 14 && !defined(_WIN32)
#  define JIT_LINK_SUPPORTED
#  include <llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h>
#endif

#if defined(_MSC_VER)
#  pragma warning(pop)
#endif

#include "gandiva/configuration.h"
#include "gandiva/decimal_ir.h"
#include "gandiva/exported_funcs.h"
#include "gandiva/exported_funcs_registry.h"

namespace gandiva {

extern const unsigned char kPrecompiledBitcode[];
extern const size_t kPrecompiledBitcodeSize;

namespace {

std::once_flag llvm_init_once_flag;
bool llvm_init = false;
llvm::StringRef cpu_name;
std::vector<std::string> cpu_attrs;
std::once_flag register_exported_funcs_flag;

template <typename T>
arrow::Result<T> AsArrowResult(llvm::Expected<T>& expected,
                               const std::string& error_context) {
  if (!expected) {
    return Status::CodeGenError(error_context, llvm::toString(expected.takeError()));
  }
  return std::move(expected.get());
}

Result<llvm::orc::JITTargetMachineBuilder> MakeTargetMachineBuilder(
    const Configuration& conf) {
  llvm::orc::JITTargetMachineBuilder jtmb(
      (llvm::Triple(llvm::sys::getDefaultTargetTriple())));
  if (conf.target_host_cpu()) {
    jtmb.setCPU(cpu_name.str());
    jtmb.addFeatures(cpu_attrs);
  }
#if LLVM_VERSION_MAJOR >= 18
  using CodeGenOptLevel = llvm::CodeGenOptLevel;
#else
  using CodeGenOptLevel = llvm::CodeGenOpt::Level;
#endif
  const auto opt_level =
      conf.optimize() ? CodeGenOptLevel::Aggressive : CodeGenOptLevel::None;
  jtmb.setCodeGenOptLevel(opt_level);
  return jtmb;
}

std::string DumpModuleIR(const llvm::Module& module) {
  std::string ir;
  llvm::raw_string_ostream stream(ir);
  module.print(stream, nullptr);
  return ir;
}

void AddAbsoluteSymbol(llvm::orc::LLJIT& lljit, const std::string& name,
                       void* function_ptr) {
  llvm::orc::MangleAndInterner mangle(lljit.getExecutionSession(), lljit.getDataLayout());

  // https://github.com/llvm/llvm-project/commit/8b1771bd9f304be39d4dcbdcccedb6d3bcd18200#diff-77984a824d9182e5c67a481740f3bc5da78d5bd4cf6e1716a083ddb30a4a4931
  // LLVM 17 introduced ExecutorSymbolDef and move most of ORC APIs to ExecutorAddr
#if LLVM_VERSION_MAJOR >= 17
  llvm::orc::ExecutorSymbolDef symbol(
      llvm::orc::ExecutorAddr(reinterpret_cast<uint64_t>(function_ptr)),
      llvm::JITSymbolFlags::Exported);
#else
  llvm::JITEvaluatedSymbol symbol(reinterpret_cast<llvm::JITTargetAddress>(function_ptr),
                                  llvm::JITSymbolFlags::Exported);
#endif

  auto error = lljit.getMainJITDylib().define(
      llvm::orc::absoluteSymbols({{mangle(name), symbol}}));
  llvm::cantFail(std::move(error));
}

// add current process symbol to dylib
// LLVM >= 18 does this automatically
void AddProcessSymbol(llvm::orc::LLJIT& lljit) {
  lljit.getMainJITDylib().addGenerator(
      llvm::cantFail(llvm::orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(
          lljit.getDataLayout().getGlobalPrefix())));
  // the `atexit` symbol cannot be found for ASAN
#if defined(ADDRESS_SANITIZER) && LLVM_VERSION_MAJOR < 18
  if (!lljit.lookup("atexit")) {
    AddAbsoluteSymbol(lljit, "atexit", reinterpret_cast<void*>(atexit));
  }
#endif
}

#ifdef JIT_LINK_SUPPORTED
Result<std::unique_ptr<llvm::jitlink::InProcessMemoryManager>> CreateMemmoryManager() {
  auto maybe_mem_manager = llvm::jitlink::InProcessMemoryManager::Create();
  return AsArrowResult(maybe_mem_manager, "Could not create memory manager: ");
}

Status UseJITLinkIfEnabled(llvm::orc::LLJITBuilder& jit_builder) {
  static auto maybe_use_jit_link = ::arrow::internal::GetEnvVar("GANDIVA_USE_JIT_LINK");
  if (maybe_use_jit_link.ok()) {
    ARROW_ASSIGN_OR_RAISE(static auto memory_manager, CreateMemmoryManager());
#  if LLVM_VERSION_MAJOR >= 21
    jit_builder.setObjectLinkingLayerCreator([&](llvm::orc::ExecutionSession& ES) {
      return std::make_unique<llvm::orc::ObjectLinkingLayer>(ES, *memory_manager);
    });
#  else
    jit_builder.setObjectLinkingLayerCreator(
        [&](llvm::orc::ExecutionSession& ES, const llvm::Triple& TT) {
          return std::make_unique<llvm::orc::ObjectLinkingLayer>(ES, *memory_manager);
        });
#  endif
  }
  return Status::OK();
}
#endif

Result<std::unique_ptr<llvm::orc::LLJIT>> BuildJIT(
    llvm::orc::JITTargetMachineBuilder jtmb,
    std::shared_ptr<llvm::TargetMachine> target_machine,
    std::optional<std::reference_wrapper<GandivaObjectCache>> object_cache) {
  auto data_layout = target_machine->createDataLayout();

  llvm::orc::LLJITBuilder jit_builder;

#ifdef JIT_LINK_SUPPORTED
  ARROW_RETURN_NOT_OK(UseJITLinkIfEnabled(jit_builder));
#endif

  jit_builder.setJITTargetMachineBuilder(std::move(jtmb));
  jit_builder.setDataLayout(std::make_optional(data_layout));

  if (object_cache.has_value()) {
    jit_builder.setCompileFunctionCreator(
        [tm = std::move(target_machine),
         &object_cache](llvm::orc::JITTargetMachineBuilder JTMB)
            -> llvm::Expected<std::unique_ptr<llvm::orc::IRCompileLayer::IRCompiler>> {
          // after compilation, the object code will be stored into the given object
          // cache
          return std::make_unique<llvm::orc::SimpleCompiler>(*tm,
                                                             &object_cache.value().get());
        });
  }

  auto maybe_jit = jit_builder.create();
  ARROW_ASSIGN_OR_RAISE(auto jit,
                        AsArrowResult(maybe_jit, "Could not create LLJIT instance: "));

  AddProcessSymbol(*jit);
  return jit;
}

arrow::Status VerifyAndLinkModule(
    llvm::Module& dest_module,
    llvm::Expected<std::unique_ptr<llvm::Module>> src_module_or_error) {
  ARROW_ASSIGN_OR_RAISE(
      auto src_ir_module,
      AsArrowResult(src_module_or_error, "Failed to verify and link module: "));

  src_ir_module->setDataLayout(dest_module.getDataLayout());

  std::string error_info;
  llvm::raw_string_ostream error_stream(error_info);
  ARROW_RETURN_IF(
      llvm::verifyModule(*src_ir_module, &error_stream),
      Status::CodeGenError("verify of IR Module failed: " + error_stream.str()));

  ARROW_RETURN_IF(llvm::Linker::linkModules(dest_module, std::move(src_ir_module)),
                  Status::CodeGenError("failed to link IR Modules"));

  return Status::OK();
}

}  // namespace

Status Engine::SetLLVMObjectCache(GandivaObjectCache& object_cache) {
  auto cached_buffer = object_cache.getObject(nullptr);
  if (cached_buffer) {
    auto error = lljit_->addObjectFile(std::move(cached_buffer));
    if (error) {
      return Status::CodeGenError("Failed to add cached object file to LLJIT: ",
                                  llvm::toString(std::move(error)));
    }
  }
  return Status::OK();
}

void Engine::InitOnce() {
  DCHECK_EQ(llvm_init, false);

  llvm::InitializeNativeTarget();
  llvm::InitializeNativeTargetAsmPrinter();
  llvm::InitializeNativeTargetAsmParser();
  llvm::InitializeNativeTargetDisassembler();
  llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr);

  cpu_name = llvm::sys::getHostCPUName();
#if LLVM_VERSION_MAJOR >= 19
  auto host_features = llvm::sys::getHostCPUFeatures();
  const bool have_host_features = true;
#else
  llvm::StringMap<bool> host_features;
  const auto have_host_features = llvm::sys::getHostCPUFeatures(host_features);
#endif
  std::string cpu_attrs_str;
  if (have_host_features) {
    for (auto& f : host_features) {
      std::string attr = f.second ? std::string("+") + f.first().str()
                                  : std::string("-") + f.first().str();
      cpu_attrs.push_back(attr);
      cpu_attrs_str += " " + attr;
    }
  }
  ARROW_LOG(INFO) << "Detected CPU Name : " << cpu_name.str();
  ARROW_LOG(INFO) << "Detected CPU Features: [" << cpu_attrs_str << "]";
  llvm_init = true;
}

Engine::Engine(const std::shared_ptr<Configuration>& conf,
               std::unique_ptr<llvm::orc::LLJIT> lljit,
               std::shared_ptr<llvm::TargetMachine> target_machine, bool cached)
    : context_(std::make_unique<llvm::LLVMContext>()),
      lljit_(std::move(lljit)),
      ir_builder_(std::make_unique<llvm::IRBuilder<>>(*context_)),
      types_(*context_),
      optimize_(conf->optimize()),
      cached_(cached),
      function_registry_(conf->function_registry()),
      target_machine_(std::move(target_machine)),
      conf_(conf) {
  // LLVM 10 doesn't like the expr function name to be the same as the module name
  auto module_id = "gdv_module_" + std::to_string(reinterpret_cast<uintptr_t>(this));
  module_ = std::make_unique<llvm::Module>(module_id, *context_);
  module_->setDataLayout(target_machine_->createDataLayout());
}

Engine::~Engine() {}

Status Engine::Init() {
  std::call_once(register_exported_funcs_flag, gandiva::RegisterExportedFuncs);

  // Add mappings for global functions that can be accessed from LLVM/IR module.
  ARROW_RETURN_NOT_OK(AddGlobalMappings());
  return Status::OK();
}

Status Engine::LoadFunctionIRs() {
  if (!functions_loaded_) {
    ARROW_RETURN_NOT_OK(LoadPreCompiledIR());
    ARROW_RETURN_NOT_OK(DecimalIR::AddFunctions(this));
    ARROW_RETURN_NOT_OK(LoadExternalPreCompiledIR());
    functions_loaded_ = true;
  }
  return Status::OK();
}

llvm::Constant* Engine::CreateGlobalStringPtr(const std::string& string) {
  auto gloval_variable = ir_builder()->CreateGlobalString(string);
  auto zero = llvm::ConstantInt::get(llvm::Type::getInt32Ty(*context()), 0);
  llvm::Constant* indices[] = {zero, zero};
  return llvm::ConstantExpr::getInBoundsGetElementPtr(gloval_variable->getValueType(),
                                                      gloval_variable, indices);
}

/// factory method to construct the engine.
Result<std::unique_ptr<Engine>> Engine::Make(
    const std::shared_ptr<Configuration>& conf, bool cached,
    std::optional<std::reference_wrapper<GandivaObjectCache>> object_cache) {
  std::call_once(llvm_init_once_flag, InitOnce);

  // Create the target machine
  ARROW_ASSIGN_OR_RAISE(auto jtmb, MakeTargetMachineBuilder(*conf));
  auto maybe_tm = jtmb.createTargetMachine();
  ARROW_ASSIGN_OR_RAISE(auto target_machine,
                        AsArrowResult(maybe_tm, "Could not create target machine: "));

  auto shared_target_machine =
      std::shared_ptr<llvm::TargetMachine>(std::move(target_machine));

  // Build the LLJIT instance
  ARROW_ASSIGN_OR_RAISE(auto jit,
                        BuildJIT(std::move(jtmb), shared_target_machine, object_cache));

  std::unique_ptr<Engine> engine{
      new Engine(conf, std::move(jit), std::move(shared_target_machine), cached)};

  ARROW_RETURN_NOT_OK(engine->Init());
  return engine;
}

llvm::Module* Engine::module() {
  DCHECK(!module_finalized_) << "module cannot be accessed after finalized";
  return module_.get();
}

// Handling for pre-compiled IR libraries.
Status Engine::LoadPreCompiledIR() {
  const auto bitcode = llvm::StringRef(reinterpret_cast<const char*>(kPrecompiledBitcode),
                                       kPrecompiledBitcodeSize);

  /// Read from file into memory buffer.
  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> buffer_or_error =
      llvm::MemoryBuffer::getMemBuffer(bitcode, "precompiled", false);

  ARROW_RETURN_IF(!buffer_or_error,
                  Status::CodeGenError("Could not load module from IR: ",
                                       buffer_or_error.getError().message()));

  std::unique_ptr<llvm::MemoryBuffer> buffer = std::move(buffer_or_error.get());

  /// Parse the IR module.
  llvm::Expected<std::unique_ptr<llvm::Module>> module_or_error =
      llvm::getOwningLazyBitcodeModule(std::move(buffer), *context());
  // NOTE: llvm::handleAllErrors() fails linking with RTTI-disabled LLVM builds
  // (ARROW-5148)
  ARROW_RETURN_NOT_OK(VerifyAndLinkModule(*module_, std::move(module_or_error)));
  return Status::OK();
}

static llvm::MemoryBufferRef AsLLVMMemoryBuffer(const arrow::Buffer& arrow_buffer) {
  const auto data = reinterpret_cast<const char*>(arrow_buffer.data());
  const auto size = arrow_buffer.size();
  return {llvm::StringRef(data, size), "external_bitcode"};
}

Status Engine::LoadExternalPreCompiledIR() {
  const auto& buffers = function_registry_->GetBitcodeBuffers();
  for (const auto& buffer : buffers) {
    auto llvm_memory_buffer_ref = AsLLVMMemoryBuffer(*buffer);
    auto module_or_error = llvm::parseBitcodeFile(llvm_memory_buffer_ref, *context());
    ARROW_RETURN_NOT_OK(VerifyAndLinkModule(*module_, std::move(module_or_error)));
  }

  return Status::OK();
}

// Get rid of all functions that don't need to be compiled.
// This helps in reducing the overall compilation time. This pass is trivial,
// and is always done since the number of functions in gandiva is very high.
// (Adapted from Apache Impala)
//
// Done by marking all the unused functions as internal, and then, running
// a pass for dead code elimination.
Status Engine::RemoveUnusedFunctions() {
  // Setup an optimiser pipeline
  llvm::PassBuilder pass_builder;
  llvm::ModuleAnalysisManager module_am;

  pass_builder.registerModuleAnalyses(module_am);
  llvm::ModulePassManager module_pm;

  std::unordered_set<std::string> used_functions;
  used_functions.insert(functions_to_compile_.begin(), functions_to_compile_.end());

  module_pm.addPass(
      llvm::InternalizePass([&used_functions](const llvm::GlobalValue& variable) -> bool {
        return used_functions.find(variable.getName().str()) != used_functions.end();
      }));
  module_pm.addPass(llvm::GlobalDCEPass());

  module_pm.run(*module_, module_am);
  return Status::OK();
}

// several passes requiring LLVM 14+ that are not available in the legacy pass manager
#if LLVM_VERSION_MAJOR >= 14
static void OptimizeModuleWithNewPassManager(llvm::Module& module,
                                             llvm::TargetIRAnalysis target_analysis) {
  // Setup an optimiser pipeline
  llvm::PassBuilder pass_builder;
  llvm::LoopAnalysisManager loop_am;
  llvm::FunctionAnalysisManager function_am;
  llvm::CGSCCAnalysisManager cgscc_am;
  llvm::ModuleAnalysisManager module_am;

  function_am.registerPass([&] { return target_analysis; });

  // Register required analysis managers
  pass_builder.registerModuleAnalyses(module_am);
  pass_builder.registerCGSCCAnalyses(cgscc_am);
  pass_builder.registerFunctionAnalyses(function_am);
  pass_builder.registerLoopAnalyses(loop_am);
  pass_builder.crossRegisterProxies(loop_am, function_am, cgscc_am, module_am);

  pass_builder.registerPipelineStartEPCallback([&](llvm::ModulePassManager& module_pm,
                                                   llvm::OptimizationLevel Level) {
    module_pm.addPass(llvm::ModuleInlinerPass());

    llvm::FunctionPassManager function_pm;
    function_pm.addPass(llvm::InstCombinePass());
    function_pm.addPass(llvm::PromotePass());
    function_pm.addPass(llvm::GVNPass());
    function_pm.addPass(llvm::NewGVNPass());
    function_pm.addPass(llvm::SimplifyCFGPass());
    function_pm.addPass(llvm::LoopVectorizePass());
    function_pm.addPass(llvm::SLPVectorizerPass());
    module_pm.addPass(llvm::createModuleToFunctionPassAdaptor(std::move(function_pm)));

    module_pm.addPass(llvm::GlobalOptPass());
  });

  pass_builder.buildPerModuleDefaultPipeline(llvm::OptimizationLevel::O3)
      .run(module, module_am);
}
#else
static void OptimizeModuleWithLegacyPassManager(llvm::Module& module,
                                                llvm::TargetIRAnalysis target_analysis) {
  std::unique_ptr<llvm::legacy::PassManager> pass_manager(
      new llvm::legacy::PassManager());

  pass_manager->add(
      llvm::createTargetTransformInfoWrapperPass(std::move(target_analysis)));
  pass_manager->add(llvm::createFunctionInliningPass());
  pass_manager->add(llvm::createInstructionCombiningPass());
  pass_manager->add(llvm::createPromoteMemoryToRegisterPass());
  pass_manager->add(llvm::createGVNPass());
  pass_manager->add(llvm::createNewGVNPass());
  pass_manager->add(llvm::createCFGSimplificationPass());
  pass_manager->add(llvm::createLoopVectorizePass());
  pass_manager->add(llvm::createSLPVectorizerPass());
  pass_manager->add(llvm::createGlobalOptimizerPass());

  // run the optimiser
  llvm::PassManagerBuilder pass_builder;
  pass_builder.OptLevel = 3;
  pass_builder.populateModulePassManager(*pass_manager);
  pass_manager->run(module);
}
#endif

// Optimise and compile the module.
Status Engine::FinalizeModule() {
  if (!cached_) {
    ARROW_RETURN_NOT_OK(RemoveUnusedFunctions());

    if (optimize_) {
      auto target_analysis = target_machine_->getTargetIRAnalysis();
// misc passes to allow for inlining, vectorization, ..
#if LLVM_VERSION_MAJOR >= 14
      OptimizeModuleWithNewPassManager(*module_, std::move(target_analysis));
#else
      OptimizeModuleWithLegacyPassManager(*module_, std::move(target_analysis));
#endif
    }

    ARROW_RETURN_IF(llvm::verifyModule(*module_, &llvm::errs()),
                    Status::CodeGenError("Module verification failed after optimizer"));

    // print the module IR and save it for later use if IR dumping is needed
    // since the module will be moved to construct LLJIT instance, and it is not
    // available after LLJIT instance is constructed
    if (conf_->dump_ir()) {
      module_ir_ = DumpModuleIR(*module_);
    }

    llvm::orc::ThreadSafeModule tsm(std::move(module_), std::move(context_));
    auto error = lljit_->addIRModule(std::move(tsm));
    if (error) {
      return Status::CodeGenError("Failed to add IR module to LLJIT: ",
                                  llvm::toString(std::move(error)));
    }
  }
  module_finalized_ = true;

  return Status::OK();
}

Result<void*> Engine::CompiledFunction(const std::string& function) {
  DCHECK(module_finalized_)
      << "module must be finalized before getting compiled function";
  auto sym = lljit_->lookup(function);
  if (!sym) {
    return Status::CodeGenError("Failed to look up function: " + function +
                                " error: " + llvm::toString(sym.takeError()));
  }
  // Since LLVM 15, `LLJIT::lookup` returns ExecutorAddrs rather than
  // JITEvaluatedSymbols
#if LLVM_VERSION_MAJOR >= 15
  auto fn_addr = sym->getValue();
#else
  auto fn_addr = sym->getAddress();
#endif
  auto fn_ptr = reinterpret_cast<void*>(fn_addr);
  if (fn_ptr == nullptr) {
    return Status::CodeGenError("Failed to get address for function: " + function);
  }
  return fn_ptr;
}

void Engine::AddGlobalMappingForFunc(const std::string& name, llvm::Type* ret_type,
                                     const std::vector<llvm::Type*>& args, void* func) {
  const auto prototype = llvm::FunctionType::get(ret_type, args, /*is_var_arg*/ false);
  llvm::Function::Create(prototype, llvm::GlobalValue::ExternalLinkage, name, module());
  AddAbsoluteSymbol(*lljit_, name, func);
}

arrow::Status Engine::AddGlobalMappings() {
  ARROW_RETURN_NOT_OK(ExportedFuncsRegistry::AddMappings(this));
  ExternalCFunctions c_funcs(function_registry_);
  return c_funcs.AddMappings(this);
}

const std::string& Engine::ir() {
  DCHECK(!module_ir_.empty()) << "dump_ir in Configuration must be set for dumping IR";
  return module_ir_;
}

}  // namespace gandiva
