mirror of
https://github.com/exaloop/codon.git
synced 2025-06-03 15:03:52 +08:00
Support run-mode backtraces
This commit is contained in:
parent
9653a1cba0
commit
d69af8a301
@ -323,6 +323,7 @@ llvm_map_components_to_libnames(LLVM_LIBS
|
|||||||
Remarks
|
Remarks
|
||||||
ScalarOpts
|
ScalarOpts
|
||||||
Support
|
Support
|
||||||
|
Symbolize
|
||||||
Target
|
Target
|
||||||
TransformUtils
|
TransformUtils
|
||||||
Vectorize
|
Vectorize
|
||||||
|
@ -79,7 +79,8 @@ int docMode(const std::vector<const char *> &args, const std::string &argv0) {
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<codon::Compiler> processSource(const std::vector<const char *> &args) {
|
std::unique_ptr<codon::Compiler> processSource(const std::vector<const char *> &args,
|
||||||
|
bool standalone) {
|
||||||
llvm::cl::opt<std::string> input(llvm::cl::Positional, llvm::cl::desc("<input file>"),
|
llvm::cl::opt<std::string> input(llvm::cl::Positional, llvm::cl::desc("<input file>"),
|
||||||
llvm::cl::init("-"));
|
llvm::cl::init("-"));
|
||||||
llvm::cl::opt<OptMode> optMode(
|
llvm::cl::opt<OptMode> optMode(
|
||||||
@ -133,6 +134,7 @@ std::unique_ptr<codon::Compiler> processSource(const std::vector<const char *> &
|
|||||||
const bool isDebug = (optMode == OptMode::Debug);
|
const bool isDebug = (optMode == OptMode::Debug);
|
||||||
std::vector<std::string> disabledOptsVec(disabledOpts);
|
std::vector<std::string> disabledOptsVec(disabledOpts);
|
||||||
auto compiler = std::make_unique<codon::Compiler>(args[0], isDebug, disabledOptsVec);
|
auto compiler = std::make_unique<codon::Compiler>(args[0], isDebug, disabledOptsVec);
|
||||||
|
compiler->getLLVMVisitor()->setStandalone(standalone);
|
||||||
|
|
||||||
// load plugins
|
// load plugins
|
||||||
for (const auto &plugin : plugins) {
|
for (const auto &plugin : plugins) {
|
||||||
@ -168,7 +170,7 @@ int runMode(const std::vector<const char *> &args) {
|
|||||||
"l", llvm::cl::desc("Load and link the specified library"));
|
"l", llvm::cl::desc("Load and link the specified library"));
|
||||||
llvm::cl::list<std::string> seqArgs(llvm::cl::ConsumeAfter,
|
llvm::cl::list<std::string> seqArgs(llvm::cl::ConsumeAfter,
|
||||||
llvm::cl::desc("<program arguments>..."));
|
llvm::cl::desc("<program arguments>..."));
|
||||||
auto compiler = processSource(args);
|
auto compiler = processSource(args, /*standalone=*/false);
|
||||||
if (!compiler)
|
if (!compiler)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
std::vector<std::string> libsVec(libs);
|
std::vector<std::string> libsVec(libs);
|
||||||
@ -229,7 +231,7 @@ int buildMode(const std::vector<const char *> &args) {
|
|||||||
"Write compiled output to specified file. Supported extensions: "
|
"Write compiled output to specified file. Supported extensions: "
|
||||||
"none (executable), .o (object file), .ll (LLVM IR), .bc (LLVM bitcode)"));
|
"none (executable), .o (object file), .ll (LLVM IR), .bc (LLVM bitcode)"));
|
||||||
|
|
||||||
auto compiler = processSource(args);
|
auto compiler = processSource(args, /*standalone=*/true);
|
||||||
if (!compiler)
|
if (!compiler)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
std::vector<std::string> libsVec(libs);
|
std::vector<std::string> libsVec(libs);
|
||||||
|
@ -19,9 +19,10 @@ Compiler::Compiler(const std::string &argv0, bool debug,
|
|||||||
module(std::make_unique<ir::Module>()),
|
module(std::make_unique<ir::Module>()),
|
||||||
pm(std::make_unique<ir::transform::PassManager>(debug && !isTest,
|
pm(std::make_unique<ir::transform::PassManager>(debug && !isTest,
|
||||||
disabledPasses)),
|
disabledPasses)),
|
||||||
llvisitor(std::make_unique<ir::LLVMVisitor>(debug)) {
|
llvisitor(std::make_unique<ir::LLVMVisitor>()) {
|
||||||
cache->module = module.get();
|
cache->module = module.get();
|
||||||
module->setCache(cache.get());
|
module->setCache(cache.get());
|
||||||
|
llvisitor->setDebug(debug);
|
||||||
llvisitor->setPluginManager(plm.get());
|
llvisitor->setPluginManager(plm.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ llvm::Expected<std::string> JIT::run(const ir::Func *input,
|
|||||||
try {
|
try {
|
||||||
CaptureOutput(buffer.rdbuf());
|
CaptureOutput(buffer.rdbuf());
|
||||||
(*repl)();
|
(*repl)();
|
||||||
} catch (const seq_jit_error &err) {
|
} catch (const JITError &err) {
|
||||||
return llvm::make_error<error::RuntimeErrorInfo>(err.getOutput(), err.getType(),
|
return llvm::make_error<error::RuntimeErrorInfo>(err.getOutput(), err.getType(),
|
||||||
err.what(), err.getFile(),
|
err.what(), err.getFile(),
|
||||||
err.getLine(), err.getCol());
|
err.getLine(), err.getCol());
|
||||||
|
@ -7,10 +7,14 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <mutex>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#define UNW_LOCAL_ONLY
|
||||||
|
#include <libunwind.h>
|
||||||
|
|
||||||
struct BacktraceFrame {
|
struct BacktraceFrame {
|
||||||
char *function;
|
char *function;
|
||||||
char *filename;
|
char *filename;
|
||||||
@ -42,6 +46,8 @@ struct Backtrace {
|
|||||||
frames[count++] = {functionDup, filenameDup, pc, lineno};
|
frames[count++] = {functionDup, filenameDup, pc, lineno};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void push_back(uintptr_t pc) { push_back("<invalid>", "<invalid>", pc, 0); }
|
||||||
|
|
||||||
void free() {
|
void free() {
|
||||||
for (auto i = 0; i < count; i++) {
|
for (auto i = 0; i < count; i++) {
|
||||||
auto *frame = &frames[i];
|
auto *frame = &frames[i];
|
||||||
@ -55,7 +61,7 @@ struct Backtrace {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void seq_backtrace_error_callback(void *data, const char *msg, int errnum) {
|
void seq_backtrace_error_callback(void *data, const char *msg, int errnum) {
|
||||||
// nothing to do
|
// printf("seq_backtrace_error_callback: %s (errnum = %d)\n", msg, errnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
int seq_backtrace_full_callback(void *data, uintptr_t pc, const char *filename,
|
int seq_backtrace_full_callback(void *data, uintptr_t pc, const char *filename,
|
||||||
@ -140,6 +146,7 @@ static void seq_delete_unwind_exc(_Unwind_Reason_Code reason,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct backtrace_state *state = nullptr;
|
static struct backtrace_state *state = nullptr;
|
||||||
|
static std::mutex stateLock;
|
||||||
|
|
||||||
SEQ_FUNC void *seq_alloc_exc(int type, void *obj) {
|
SEQ_FUNC void *seq_alloc_exc(int type, void *obj) {
|
||||||
const size_t size = sizeof(OurException);
|
const size_t size = sizeof(OurException);
|
||||||
@ -152,11 +159,33 @@ SEQ_FUNC void *seq_alloc_exc(int type, void *obj) {
|
|||||||
if (seq_flags & SEQ_FLAG_DEBUG) {
|
if (seq_flags & SEQ_FLAG_DEBUG) {
|
||||||
e->bt.frames = nullptr;
|
e->bt.frames = nullptr;
|
||||||
e->bt.count = 0;
|
e->bt.count = 0;
|
||||||
if (!state)
|
|
||||||
state = backtrace_create_state(/*filename=*/nullptr, /*threaded=*/0,
|
if (seq_flags & SEQ_FLAG_STANDALONE) {
|
||||||
|
if (!state) {
|
||||||
|
stateLock.lock();
|
||||||
|
if (!state)
|
||||||
|
state =
|
||||||
|
backtrace_create_state(/*filename=*/nullptr, /*threaded=*/1,
|
||||||
seq_backtrace_error_callback, /*data=*/nullptr);
|
seq_backtrace_error_callback, /*data=*/nullptr);
|
||||||
backtrace_full(state, /*skip=*/1, seq_backtrace_full_callback,
|
stateLock.unlock();
|
||||||
seq_backtrace_error_callback, &e->bt);
|
}
|
||||||
|
backtrace_full(state, /*skip=*/1, seq_backtrace_full_callback,
|
||||||
|
seq_backtrace_error_callback, &e->bt);
|
||||||
|
} else {
|
||||||
|
unw_cursor_t cursor;
|
||||||
|
unw_context_t context;
|
||||||
|
|
||||||
|
unw_getcontext(&context);
|
||||||
|
unw_init_local(&cursor, &context);
|
||||||
|
|
||||||
|
while (unw_step(&cursor) > 0) {
|
||||||
|
unw_word_t pc;
|
||||||
|
unw_get_reg(&cursor, UNW_REG_IP, &pc);
|
||||||
|
if (pc == 0)
|
||||||
|
break;
|
||||||
|
e->bt.push_back(pc);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return &(e->unwindException);
|
return &(e->unwindException);
|
||||||
}
|
}
|
||||||
@ -209,7 +238,7 @@ SEQ_FUNC void seq_terminate(void *exc) {
|
|||||||
}
|
}
|
||||||
buf << "\n";
|
buf << "\n";
|
||||||
|
|
||||||
if (seq_flags & SEQ_FLAG_DEBUG) {
|
if ((seq_flags & SEQ_FLAG_DEBUG) && (seq_flags & SEQ_FLAG_STANDALONE)) {
|
||||||
auto *bt = &base->bt;
|
auto *bt = &base->bt;
|
||||||
if (bt->count > 0) {
|
if (bt->count > 0) {
|
||||||
buf << "\n\033[1mBacktrace:\033[0m\n";
|
buf << "\n\033[1mBacktrace:\033[0m\n";
|
||||||
@ -223,14 +252,23 @@ SEQ_FUNC void seq_terminate(void *exc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto output = buf.str();
|
auto output = buf.str();
|
||||||
if (seq_flags & SEQ_FLAG_JIT) {
|
if (seq_flags & SEQ_FLAG_STANDALONE) {
|
||||||
|
fwrite(output.data(), 1, output.size(), stderr);
|
||||||
|
abort();
|
||||||
|
} else {
|
||||||
|
auto *bt = &base->bt;
|
||||||
std::string msg(hdr->msg.str, hdr->msg.len);
|
std::string msg(hdr->msg.str, hdr->msg.len);
|
||||||
std::string file(hdr->file.str, hdr->file.len);
|
std::string file(hdr->file.str, hdr->file.len);
|
||||||
std::string type(hdr->type.str, hdr->type.len);
|
std::string type(hdr->type.str, hdr->type.len);
|
||||||
throw seq_jit_error(output, msg, type, file, (int)hdr->line, (int)hdr->col);
|
|
||||||
} else {
|
std::vector<uintptr_t> backtrace;
|
||||||
fwrite(output.data(), 1, output.size(), stderr);
|
if (seq_flags & SEQ_FLAG_DEBUG) {
|
||||||
abort();
|
for (unsigned i = 0; i < bt->count; i++) {
|
||||||
|
backtrace.push_back(bt->frames[i].pc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw codon::JITError(output, msg, type, file, (int)hdr->line, (int)hdr->col,
|
||||||
|
backtrace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,19 +7,16 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unwind.h>
|
#include <unwind.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#define SEQ_FLAG_DEBUG (1 << 0)
|
#define SEQ_FLAG_DEBUG (1 << 0) // compiled/running in debug mode
|
||||||
#define SEQ_FLAG_JIT (1 << 1)
|
#define SEQ_FLAG_JIT (1 << 1) // compiled/running in JIT mode
|
||||||
|
#define SEQ_FLAG_STANDALONE (1 << 2) // compiled as a standalone object/binary
|
||||||
|
|
||||||
#define SEQ_FUNC extern "C"
|
#define SEQ_FUNC extern "C"
|
||||||
|
|
||||||
typedef int64_t seq_int_t;
|
typedef int64_t seq_int_t;
|
||||||
|
|
||||||
struct seq_t {
|
|
||||||
seq_int_t len;
|
|
||||||
char *seq;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct seq_str_t {
|
struct seq_str_t {
|
||||||
seq_int_t len;
|
seq_int_t len;
|
||||||
char *str;
|
char *str;
|
||||||
@ -80,24 +77,28 @@ SEQ_FUNC void *seq_rlock_new();
|
|||||||
SEQ_FUNC bool seq_rlock_acquire(void *lock, bool block, double timeout);
|
SEQ_FUNC bool seq_rlock_acquire(void *lock, bool block, double timeout);
|
||||||
SEQ_FUNC void seq_rlock_release(void *lock);
|
SEQ_FUNC void seq_rlock_release(void *lock);
|
||||||
|
|
||||||
class seq_jit_error : public std::runtime_error {
|
namespace codon {
|
||||||
|
class JITError : public std::runtime_error {
|
||||||
private:
|
private:
|
||||||
std::string output;
|
std::string output;
|
||||||
std::string type;
|
std::string type;
|
||||||
std::string file;
|
std::string file;
|
||||||
int line;
|
int line;
|
||||||
int col;
|
int col;
|
||||||
|
std::vector<uintptr_t> backtrace;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit seq_jit_error(const std::string &output, const std::string &what,
|
JITError(const std::string &output, const std::string &what, const std::string &type,
|
||||||
const std::string &type, const std::string &file, int line,
|
const std::string &file, int line, int col,
|
||||||
int col)
|
std::vector<uintptr_t> backtrace = {})
|
||||||
: std::runtime_error(what), output(output), type(type), file(file), line(line),
|
: std::runtime_error(what), output(output), type(type), file(file), line(line),
|
||||||
col(col) {}
|
col(col), backtrace(std::move(backtrace)) {}
|
||||||
|
|
||||||
std::string getOutput() const { return output; }
|
std::string getOutput() const { return output; }
|
||||||
std::string getType() const { return type; }
|
std::string getType() const { return type; }
|
||||||
std::string getFile() const { return file; }
|
std::string getFile() const { return file; }
|
||||||
int getLine() const { return line; }
|
int getLine() const { return line; }
|
||||||
int getCol() const { return col; }
|
int getCol() const { return col; }
|
||||||
|
std::vector<uintptr_t> getBacktrace() const { return backtrace; }
|
||||||
};
|
};
|
||||||
|
} // namespace codon
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include "llvisitor.h"
|
#include "llvisitor.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cctype>
|
||||||
|
#include <cstdlib>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@ -27,11 +29,11 @@ llvm::DIFile *LLVMVisitor::DebugInfo::getFile(const std::string &path) {
|
|||||||
return builder->createFile(filename, directory);
|
return builder->createFile(filename, directory);
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVMVisitor::LLVMVisitor(bool debug, bool jit, const std::string &flags)
|
LLVMVisitor::LLVMVisitor()
|
||||||
: util::ConstVisitor(), context(std::make_unique<llvm::LLVMContext>()), M(),
|
: util::ConstVisitor(), context(std::make_unique<llvm::LLVMContext>()), M(),
|
||||||
B(std::make_unique<llvm::IRBuilder<>>(*context)), func(nullptr), block(nullptr),
|
B(std::make_unique<llvm::IRBuilder<>>(*context)), func(nullptr), block(nullptr),
|
||||||
value(nullptr), vars(), funcs(), coro(), loops(), trycatch(),
|
value(nullptr), vars(), funcs(), coro(), loops(), trycatch(), db(),
|
||||||
db(debug, jit, flags), plugins(nullptr) {
|
plugins(nullptr) {
|
||||||
llvm::InitializeAllTargets();
|
llvm::InitializeAllTargets();
|
||||||
llvm::InitializeAllTargetMCs();
|
llvm::InitializeAllTargetMCs();
|
||||||
llvm::InitializeAllAsmPrinters();
|
llvm::InitializeAllAsmPrinters();
|
||||||
@ -376,6 +378,63 @@ void LLVMVisitor::compile(const std::string &filename,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
class DebugInfoListener : public llvm::JITEventListener {
|
||||||
|
public:
|
||||||
|
std::pair<std::unique_ptr<llvm::object::ObjectFile>,
|
||||||
|
std::unique_ptr<llvm::MemoryBuffer>>
|
||||||
|
saved;
|
||||||
|
intptr_t start = 0;
|
||||||
|
|
||||||
|
void notifyObjectLoaded(ObjectKey key, const llvm::object::ObjectFile &obj,
|
||||||
|
const llvm::RuntimeDyld::LoadedObjectInfo &L) override {
|
||||||
|
start = L.getSectionLoadAddress(*obj.section_begin());
|
||||||
|
saved = L.getObjectForDebug(obj).takeBinary();
|
||||||
|
if (!saved.first) {
|
||||||
|
auto buf = llvm::MemoryBuffer::getMemBufferCopy(obj.getData(), obj.getFileName());
|
||||||
|
auto newObj = llvm::cantFail(
|
||||||
|
llvm::object::ObjectFile::createObjectFile(buf->getMemBufferRef()));
|
||||||
|
saved = std::make_pair(std::move(newObj), std::move(buf));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string unmangleType(llvm::StringRef s) {
|
||||||
|
auto p = s.rsplit('.');
|
||||||
|
return (p.second.empty() ? p.first : p.second).str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string unmangleFunc(llvm::StringRef s) {
|
||||||
|
// separate type and function
|
||||||
|
auto p = s.split(':');
|
||||||
|
llvm::StringRef func = s;
|
||||||
|
std::string type;
|
||||||
|
if (!p.second.empty()) {
|
||||||
|
type = unmangleType(p.first);
|
||||||
|
func = p.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
// trim off ".<id>"
|
||||||
|
p = func.rsplit('.');
|
||||||
|
if (!p.second.empty() && p.second.find_if([](char c) { return !std::isdigit(c); }) ==
|
||||||
|
llvm::StringRef::npos)
|
||||||
|
func = p.first;
|
||||||
|
|
||||||
|
// trim off generics
|
||||||
|
func = func.split('[').first;
|
||||||
|
|
||||||
|
// trim off qualified name
|
||||||
|
p = func.rsplit('.');
|
||||||
|
if (!p.second.empty())
|
||||||
|
func = p.second;
|
||||||
|
|
||||||
|
if (!type.empty())
|
||||||
|
return type + "." + func.str();
|
||||||
|
else
|
||||||
|
return func.str();
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
void LLVMVisitor::run(const std::vector<std::string> &args,
|
void LLVMVisitor::run(const std::vector<std::string> &args,
|
||||||
const std::vector<std::string> &libs, const char *const *envp) {
|
const std::vector<std::string> &libs, const char *const *envp) {
|
||||||
runLLVMPipeline();
|
runLLVMPipeline();
|
||||||
@ -384,14 +443,48 @@ void LLVMVisitor::run(const std::vector<std::string> &args,
|
|||||||
EB.setMCJITMemoryManager(std::make_unique<BoehmGCMemoryManager>());
|
EB.setMCJITMemoryManager(std::make_unique<BoehmGCMemoryManager>());
|
||||||
llvm::ExecutionEngine *eng = EB.create();
|
llvm::ExecutionEngine *eng = EB.create();
|
||||||
|
|
||||||
std::string err;
|
auto dbListener = std::unique_ptr<DebugInfoListener>();
|
||||||
|
if (db.debug) {
|
||||||
|
dbListener = std::make_unique<DebugInfoListener>();
|
||||||
|
eng->RegisterJITEventListener(dbListener.get());
|
||||||
|
}
|
||||||
|
|
||||||
for (auto &lib : libs) {
|
for (auto &lib : libs) {
|
||||||
|
std::string err;
|
||||||
if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(lib.c_str(), &err)) {
|
if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(lib.c_str(), &err)) {
|
||||||
compilationError(err);
|
compilationError(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eng->runFunctionAsMain(main, args, envp);
|
try {
|
||||||
|
eng->runFunctionAsMain(main, args, envp);
|
||||||
|
} catch (const JITError &e) {
|
||||||
|
fmt::print(stderr, "{}", e.getOutput());
|
||||||
|
if (db.debug) {
|
||||||
|
llvm::symbolize::LLVMSymbolizer sym;
|
||||||
|
auto invalid = [](const std::string &name) { return name == "<invalid>"; };
|
||||||
|
|
||||||
|
fmt::print(stderr, "\n\033[1mBacktrace:\033[0m\n");
|
||||||
|
auto base = dbListener->start;
|
||||||
|
for (auto pc : e.getBacktrace()) {
|
||||||
|
auto src = sym.symbolizeCode(
|
||||||
|
*dbListener->saved.first,
|
||||||
|
{pc - base, llvm::object::SectionedAddress::UndefSection});
|
||||||
|
if (auto err = src.takeError())
|
||||||
|
break;
|
||||||
|
if (invalid(src->FunctionName) || invalid(src->FileName))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto func = unmangleFunc(src->FunctionName);
|
||||||
|
auto file = src->FileName;
|
||||||
|
auto line = src->Line;
|
||||||
|
auto col = src->Column;
|
||||||
|
fmt::print(stderr, " [\033[33m0x{:016x}\033[0m] \033[32m{}\033[0m {}:{}:{}\n",
|
||||||
|
pc, func, file, line, col);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::abort();
|
||||||
|
}
|
||||||
delete eng;
|
delete eng;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -625,7 +718,8 @@ void LLVMVisitor::visit(const Module *x) {
|
|||||||
llvm::Value *argStorage = getVar(x->getArgVar());
|
llvm::Value *argStorage = getVar(x->getArgVar());
|
||||||
seqassert(argStorage, "argument storage missing");
|
seqassert(argStorage, "argument storage missing");
|
||||||
B->CreateStore(arr, argStorage);
|
B->CreateStore(arr, argStorage);
|
||||||
const int flags = (db.debug ? SEQ_FLAG_DEBUG : 0) | (db.jit ? SEQ_FLAG_JIT : 0);
|
const int flags = (db.debug ? SEQ_FLAG_DEBUG : 0) | (db.jit ? SEQ_FLAG_JIT : 0) |
|
||||||
|
(db.standalone ? SEQ_FLAG_STANDALONE : 0);
|
||||||
B->CreateCall(initFunc, B->getInt32(flags));
|
B->CreateCall(initFunc, B->getInt32(flags));
|
||||||
|
|
||||||
// Put the entire program in a new function
|
// Put the entire program in a new function
|
||||||
|
@ -98,11 +98,14 @@ private:
|
|||||||
bool debug;
|
bool debug;
|
||||||
/// Whether we are compiling in JIT mode
|
/// Whether we are compiling in JIT mode
|
||||||
bool jit;
|
bool jit;
|
||||||
|
/// Whether we are compiling a standalone object/executable
|
||||||
|
bool standalone;
|
||||||
/// Program command-line flags
|
/// Program command-line flags
|
||||||
std::string flags;
|
std::string flags;
|
||||||
|
|
||||||
DebugInfo(bool debug, bool jit, const std::string &flags)
|
DebugInfo()
|
||||||
: builder(), unit(nullptr), debug(debug), jit(jit), flags(flags) {}
|
: builder(), unit(nullptr), debug(false), jit(false), standalone(false),
|
||||||
|
flags() {}
|
||||||
|
|
||||||
llvm::DIFile *getFile(const std::string &path);
|
llvm::DIFile *getFile(const std::string &path);
|
||||||
|
|
||||||
@ -223,11 +226,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs an LLVM visitor.
|
/// Constructs an LLVM visitor.
|
||||||
/// @param debug whether to compile in debug mode
|
LLVMVisitor();
|
||||||
/// @param jit whether to compile in JIT mode
|
|
||||||
/// @param flags command-line flags to be included in debug info
|
|
||||||
explicit LLVMVisitor(bool debug = false, bool jit = false,
|
|
||||||
const std::string &flags = "");
|
|
||||||
|
|
||||||
/// @return true if in debug mode, false otherwise
|
/// @return true if in debug mode, false otherwise
|
||||||
bool getDebug() const { return db.debug; }
|
bool getDebug() const { return db.debug; }
|
||||||
@ -241,6 +240,12 @@ public:
|
|||||||
/// @param j true if JIT mode
|
/// @param j true if JIT mode
|
||||||
void setJIT(bool j = true) { db.jit = j; }
|
void setJIT(bool j = true) { db.jit = j; }
|
||||||
|
|
||||||
|
/// @return true if in standalone mode, false otherwise
|
||||||
|
bool getStandalone() const { return db.standalone; }
|
||||||
|
/// Sets standalone status.
|
||||||
|
/// @param s true if standalone
|
||||||
|
void setStandalone(bool s = true) { db.standalone = s; }
|
||||||
|
|
||||||
/// @return program flags
|
/// @return program flags
|
||||||
std::string getFlags() const { return db.flags; }
|
std::string getFlags() const { return db.flags; }
|
||||||
/// Sets program flags.
|
/// Sets program flags.
|
||||||
|
@ -12,8 +12,10 @@
|
|||||||
#include "llvm/Bitcode/BitcodeWriter.h"
|
#include "llvm/Bitcode/BitcodeWriter.h"
|
||||||
#include "llvm/CodeGen/MachineModuleInfo.h"
|
#include "llvm/CodeGen/MachineModuleInfo.h"
|
||||||
#include "llvm/CodeGen/TargetPassConfig.h"
|
#include "llvm/CodeGen/TargetPassConfig.h"
|
||||||
|
#include "llvm/DebugInfo/Symbolize/Symbolize.h"
|
||||||
#include "llvm/ExecutionEngine/ExecutionEngine.h"
|
#include "llvm/ExecutionEngine/ExecutionEngine.h"
|
||||||
#include "llvm/ExecutionEngine/GenericValue.h"
|
#include "llvm/ExecutionEngine/GenericValue.h"
|
||||||
|
#include "llvm/ExecutionEngine/JITEventListener.h"
|
||||||
#include "llvm/ExecutionEngine/JITSymbol.h"
|
#include "llvm/ExecutionEngine/JITSymbol.h"
|
||||||
#include "llvm/ExecutionEngine/MCJIT.h"
|
#include "llvm/ExecutionEngine/MCJIT.h"
|
||||||
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user