github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/jit/cpp_ir.cpp (about)

     1  // Copyright (C) 2018 go-nebulas authors
     2  //
     3  // This file is part of the go-nebulas library.
     4  //
     5  // the go-nebulas library is free software: you can redistribute it and/or
     6  // modify
     7  // it under the terms of the GNU General Public License as published by
     8  // the Free Software Foundation, either version 3 of the License, or
     9  // (at your option) any later version.
    10  //
    11  // the go-nebulas library is distributed in the hope that it will be useful,
    12  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  // GNU General Public License for more details.
    15  //
    16  // You should have received a copy of the GNU General Public License
    17  // along with the go-nebulas library.  If not, see
    18  // <http://www.gnu.org/licenses/>.
    19  //
    20  #include "jit/cpp_ir.h"
    21  #include "fs/util.h"
    22  #include "util/chrono.h"
    23  
    24  namespace neb {
    25  namespace cpp {
    26  std::atomic_int cpp_ir::s_file_counter(1);
    27  
    28  cpp_ir::cpp_ir(const cpp_t &cpp)
    29      : m_name_version(cpp.first), m_cpp_content(cpp.second),
    30        m_b_got_error(false) {}
    31  
    32  neb::bytes cpp_ir::llvm_ir_content() {
    33    if (m_llvm_ir_fp == std::string("") && !m_b_got_error) {
    34  
    35      std::string fp_base = generate_fp() + '_' + m_name_version;
    36      std::string cpp_fp = fp_base + ".cpp";
    37      std::string ir_fp = fp_base + ".bc";
    38      m_cpp_fp = cpp_fp;
    39      m_llvm_ir_fp = ir_fp;
    40  
    41      std::ofstream ofp(cpp_fp);
    42      ofp.write(m_cpp_content.c_str(), m_cpp_content.size());
    43      ofp.close();
    44      auto ret = make_ir_bitcode(cpp_fp, ir_fp);
    45      if (ret != 0) {
    46        m_b_got_error = true;
    47      }
    48    }
    49    if (m_b_got_error) {
    50      return neb::bytes();
    51    }
    52    if (!::neb::fs::exists(m_llvm_ir_fp)) {
    53      return neb::bytes();
    54    }
    55  
    56    std::ifstream ifs;
    57    ifs.open(m_llvm_ir_fp.c_str(), std::ios::in | std::ios::binary);
    58    if (!ifs.is_open())
    59      return neb::bytes();
    60    ifs.seekg(0, ifs.end);
    61    std::ifstream::pos_type size = ifs.tellg();
    62    neb::bytes buf(size);
    63    ifs.seekg(0, ifs.beg);
    64    ifs.read((char *)buf.value(), buf.size());
    65    ifs.close();
    66    return buf;
    67  }
    68  std::string cpp_ir::generate_fp() {
    69    std::string temp_path = neb::fs::tmp_dir();
    70  
    71    std::string name = std::to_string(util::now()) + std::string("_") +
    72                       std::to_string(s_file_counter);
    73    auto t =
    74        neb::fs::join_path(neb::configuration::instance().nbre_db_dir(), name);
    75    s_file_counter++;
    76    return t;
    77  }
    78  
    79  int cpp_ir::make_ir_bitcode(const std::string &cpp_file,
    80                              const std::string &ir_bc_file) {
    81    int result = -1;
    82  
    83    std::string nbre_path = ::neb::configuration::instance().nbre_root_dir();
    84    std::string command_string(
    85        neb::fs::join_path(nbre_path, "lib_llvm/bin/clang") +
    86        " -O2 -c -emit-llvm ");
    87  
    88    std::string include_string =
    89        std::string("-I") +
    90        neb::fs::join_path(::neb::configuration::instance().nbre_root_dir(),
    91                           "lib/include") +
    92        std::string(" ");
    93  
    94    command_string += include_string + " -o " + ir_bc_file;
    95    command_string += std::string(" ") + cpp_file;
    96    std::cout << command_string << std::endl;
    97    LOG(INFO) << command_string;
    98  
    99    result = util::command_executor::execute_command(command_string);
   100    if (result != 0) {
   101      LOG(ERROR) << "error: executed by boost::process::system.";
   102      LOG(ERROR) << "result code = " << result;
   103      return -1;
   104    }
   105    return 0;
   106  }
   107  
   108  } // namespace cpp
   109  } // namespace neb