<commit_before>// A helper for the llvm backend

#include <llvm/Transforms/Utils/Cloning.h>
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/InstCombine/InstCombine.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Scalar/GVN.h"
#include "llvm/Transforms/Utils.h"
#include "llvm/Bitcode/BitcodeReader.h"
#include <llvm/Linker/Linker.h>
#include <llvm/Demangle/Demangle.h>

#include "tlang_util.h"
#include "taichi_llvm_context.h"
#include "backends/llvm_jit.h"

TLANG_NAMESPACE_BEGIN

static llvm::ExitOnError exit_on_err;

TaichiLLVMContext::TaichiLLVMContext(Arch arch) : arch(arch) {
  llvm::remove_fatal_error_handler();
  llvm::install_fatal_error_handler(
      [](void *user_data, const std::string &reason, bool gen_crash_diag) {
        TC_ERROR("LLVM Fatal Error: {}", reason);
      },
      nullptr);

  if (arch == Arch::x86_64) {
    llvm::InitializeNativeTarget();
    llvm::InitializeNativeTargetAsmPrinter();
    llvm::InitializeNativeTargetAsmParser();
  } else {
#if defined(TLANG_WITH_CUDA)
    LLVMInitializeNVPTXTarget();
    LLVMInitializeNVPTXTargetMC();
    LLVMInitializeNVPTXTargetInfo();
    LLVMInitializeNVPTXAsmPrinter();
#else
	TC_NOT_IMPLEMENTED
#endif
  }
  ctx = std::make_unique<llvm::LLVMContext>();
  TC_INFO("Creating llvm context for arch: {}", arch_name(arch));
  jit = exit_on_err(TaichiLLVMJIT::create(arch));
}

TaichiLLVMContext::~TaichiLLVMContext() {
}

llvm::Type *TaichiLLVMContext::get_data_type(DataType dt) {
  if (dt == DataType::i32) {
    return llvm::Type::getInt32Ty(*ctx);
  } else if (dt == DataType::i8) {
    return llvm::Type::getInt8Ty(*ctx);
  } else if (dt == DataType::i16) {
    return llvm::Type::getInt16Ty(*ctx);
  } else if (dt == DataType::i64) {
    return llvm::Type::getInt64Ty(*ctx);
  } else if (dt == DataType::f32) {
    return llvm::Type::getFloatTy(*ctx);
  } else if (dt == DataType::f64) {
    return llvm::Type::getDoubleTy(*ctx);
  } else {
    TC_INFO(data_type_name(dt));
    TC_NOT_IMPLEMENTED
  }
  return nullptr;
}

std::string find_existing_command(const std::vector<std::string> &commands) {
  for (auto &cmd : commands) {
    if (command_exist(cmd)) {
      return cmd;
    }
  }
  TC_P(commands);
  TC_ERROR("No command found.");
}

std::string get_runtime_fn(Arch arch) {
  return fmt::format("runtime_{}.bc", arch_name(arch));
}

std::string get_runtime_dir() {
  return get_repo_dir() + "/taichi/runtime/";
}

void compile_runtime_bitcode(Arch arch) {
  if (is_release())
    return;
  TI_AUTO_PROF;
  static std::set<int> runtime_compiled;
  if (runtime_compiled.find((int)arch) == runtime_compiled.end()) {
    auto clang = find_existing_command({"clang-7", "clang"});
    TC_ASSERT(command_exist("llvm-as"));
    TC_TRACE("Compiling runtime module bitcode...");
    auto runtime_folder = get_runtime_dir();
    std::string macro = fmt::format(" -D ARCH_{} ", arch_name(arch));
    int ret = std::system(
        fmt::format(
            "{} -S {}runtime.cpp -o {}runtime.ll -emit-llvm -std=c++17 {}",
            clang, runtime_folder, runtime_folder, macro)
            .c_str());
    if (ret) {
      TC_ERROR("Runtime compilation failed.");
    }
    std::system(fmt::format("llvm-as {}runtime.ll -o {}{}", runtime_folder,
                            runtime_folder, get_runtime_fn(arch))
                    .c_str());
    runtime_compiled.insert((int)arch);
  }
}

void compile_runtimes() {
  compile_runtime_bitcode(Arch::x86_64);
#if defined(TLANG_WITH_CUDA)
  compile_runtime_bitcode(Arch::gpu);
#endif
}

std::string libdevice_path() {
#if defined(TLANG_WITH_CUDA)
  auto folder =
      fmt::format("/usr/local/cuda-{}/nvvm/libdevice/", TLANG_CUDA_VERSION);
  if (is_release()) {
    folder = compiled_lib_dir;
  }
  auto cuda_version_major = int(std::atof(TLANG_CUDA_VERSION));
  return fmt::format("{}/libdevice.{}.bc", folder, cuda_version_major);
#else
  TC_NOT_IMPLEMENTED;
  return "";
#endif
}

std::unique_ptr<llvm::Module> TaichiLLVMContext::get_init_module() {
  return clone_runtime_module();
}

std::unique_ptr<llvm::Module> module_from_bitcode_file(std::string bitcode_path,
                                                       llvm::LLVMContext *ctx) {
  TI_AUTO_PROF
  std::ifstream ifs(bitcode_path);
  std::string bitcode(std::istreambuf_iterator<char>(ifs),
                      (std::istreambuf_iterator<char>()));
  auto runtime =
      parseBitcodeFile(MemoryBufferRef(bitcode, "runtime_bitcode"), *ctx);
  if (!runtime) {
	auto error = runtime.takeError();
	TC_WARN("Bitcode loading error message:");
	llvm::errs() << error << "\n";
    TC_ERROR("Runtime bitcode load failure.");
  }
  bool module_broken = llvm::verifyModule(*runtime.get(), &llvm::errs());
  TC_ERROR_IF(module_broken, "Module broken");
  return std::move(runtime.get());
}

int num_instructions(llvm::Function *func) {
  int counter = 0;
  for (BasicBlock &bb : *func)<commit_msg>fixed windows bitcode loading<commit_after>// A helper for the llvm backend

#include <llvm/Transforms/Utils/Cloning.h>
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/InstCombine/InstCombine.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Scalar/GVN.h"
#include "llvm/Transforms/Utils.h"
#include "llvm/Bitcode/BitcodeReader.h"
#include <llvm/Linker/Linker.h>
#include <llvm/Demangle/Demangle.h>

#include "tlang_util.h"
#include "taichi_llvm_context.h"
#include "backends/llvm_jit.h"

TLANG_NAMESPACE_BEGIN

static llvm::ExitOnError exit_on_err;

TaichiLLVMContext::TaichiLLVMContext(Arch arch) : arch(arch) {
  llvm::remove_fatal_error_handler();
  llvm::install_fatal_error_handler(
      [](void *user_data, const std::string &reason, bool gen_crash_diag) {
        TC_ERROR("LLVM Fatal Error: {}", reason);
      },
      nullptr);

  if (arch == Arch::x86_64) {
    llvm::InitializeNativeTarget();
    llvm::InitializeNativeTargetAsmPrinter();
    llvm::InitializeNativeTargetAsmParser();
  } else {
#if defined(TLANG_WITH_CUDA)
    LLVMInitializeNVPTXTarget();
    LLVMInitializeNVPTXTargetMC();
    LLVMInitializeNVPTXTargetInfo();
    LLVMInitializeNVPTXAsmPrinter();
#else
	TC_NOT_IMPLEMENTED
#endif
  }
  ctx = std::make_unique<llvm::LLVMContext>();
  TC_INFO("Creating llvm context for arch: {}", arch_name(arch));
  jit = exit_on_err(TaichiLLVMJIT::create(arch));
}

TaichiLLVMContext::~TaichiLLVMContext() {
}

llvm::Type *TaichiLLVMContext::get_data_type(DataType dt) {
  if (dt == DataType::i32) {
    return llvm::Type::getInt32Ty(*ctx);
  } else if (dt == DataType::i8) {
    return llvm::Type::getInt8Ty(*ctx);
  } else if (dt == DataType::i16) {
    return llvm::Type::getInt16Ty(*ctx);
  } else if (dt == DataType::i64) {
    return llvm::Type::getInt64Ty(*ctx);
  } else if (dt == DataType::f32) {
    return llvm::Type::getFloatTy(*ctx);
  } else if (dt == DataType::f64) {
    return llvm::Type::getDoubleTy(*ctx);
  } else {
    TC_INFO(data_type_name(dt));
    TC_NOT_IMPLEMENTED
  }
  return nullptr;
}

std::string find_existing_command(const std::vector<std::string> &commands) {
  for (auto &cmd : commands) {
    if (command_exist(cmd)) {
      return cmd;
    }
  }
  TC_P(commands);
  TC_ERROR("No command found.");
}

std::string get_runtime_fn(Arch arch) {
  return fmt::format("runtime_{}.bc", arch_name(arch));
}

std::string get_runtime_dir() {
  return get_repo_dir() + "/taichi/runtime/";
}

void compile_runtime_bitcode(Arch arch) {
  if (is_release())
    return;
  TI_AUTO_PROF;
  static std::set<int> runtime_compiled;
  if (runtime_compiled.find((int)arch) == runtime_compiled.end()) {
    auto clang = find_existing_command({"clang-7", "clang"});
    TC_ASSERT(command_exist("llvm-as"));
    TC_TRACE("Compiling runtime module bitcode...");
    auto runtime_folder = get_runtime_dir();
    std::string macro = fmt::format(" -D ARCH_{} ", arch_name(arch));
    int ret = std::system(
        fmt::format(
            "{} -S {}runtime.cpp -o {}runtime.ll -emit-llvm -std=c++17 {}",
            clang, runtime_folder, runtime_folder, macro)
            .c_str());
    if (ret) {
      TC_ERROR("Runtime compilation failed.");
    }
    std::system(fmt::format("llvm-as {}runtime.ll -o {}{}", runtime_folder,
                            runtime_folder, get_runtime_fn(arch))
                    .c_str());
    runtime_compiled.insert((int)arch);
  }
}

void compile_runtimes() {
  compile_runtime_bitcode(Arch::x86_64);
#if defined(TLANG_WITH_CUDA)
  compile_runtime_bitcode(Arch::gpu);
#endif
}

std::string libdevice_path() {
#if defined(TLANG_WITH_CUDA)
  auto folder =
      fmt::format("/usr/local/cuda-{}/nvvm/libdevice/", TLANG_CUDA_VERSION);
  if (is_release()) {
    folder = compiled_lib_dir;
  }
  auto cuda_version_major = int(std::atof(TLANG_CUDA_VERSION));
  return fmt::format("{}/libdevice.{}.bc", folder, cuda_version_major);
#else
  TC_NOT_IMPLEMENTED;
  return "";
#endif
}

std::unique_ptr<llvm::Module> TaichiLLVMContext::get_init_module() {
  return clone_runtime_module();
}

std::unique_ptr<llvm::Module> module_from_bitcode_file(std::string bitcode_path,
                                                       llvm::LLVMContext *ctx) {
  TI_AUTO_PROF
  std::ifstream ifs(bitcode_path, std::ios::binary);
  std::string bitcode(std::istreambuf_iterator<char>(ifs),
                      (std::istreambuf_iterator<char>()));
  auto runtime =
      parseBitcodeFile(MemoryBufferRef(bitcode, "runtime_bitcode"), *ctx);
  if (!runtime) {
	auto error = runtime.takeError();
	TC_WARN("Bitcode loading error message:");
	llvm::errs() << error << "\n";
    TC_ERROR("Runtime bitcode load failure.");
  }
  bool module_broken = llvm::verifyModule(*runtime.get(), &llvm::errs());
  TC_ERROR_IF(module_broken, "Module broken");
  return std::move(runtime.get());
}

int num_instructions(llvm::Function *func) {
  int counter = 0;
  for (BasicBlock &bb : *func)
{'fraction_non_alphanumeric': 0.1579675396532645, 'fraction_numerical': 0.005533013648100332, 'mean_word_length': 4.452488687782806, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2338579', 'n_tokens_mistral': 3897, 'n_tokens_neox': 3865, 'n_words': 649}