mirror of
https://github.com/exaloop/codon.git
synced 2025-06-03 15:03:52 +08:00
Fix JIT
This commit is contained in:
parent
5149ee4a62
commit
e768ab6a4b
@ -2,6 +2,7 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -187,7 +188,15 @@ std::string jitExec(codon::jit::JIT *jit, const std::string &code) {
|
|||||||
std::string output;
|
std::string output;
|
||||||
llvm::handleAllErrors(
|
llvm::handleAllErrors(
|
||||||
std::move(err), [](const codon::error::ParserErrorInfo &e) { display(e); },
|
std::move(err), [](const codon::error::ParserErrorInfo &e) { display(e); },
|
||||||
[&output](const codon::error::RuntimeErrorInfo &e) { output = e.getOutput(); });
|
[&output](const codon::error::RuntimeErrorInfo &e) {
|
||||||
|
std::stringstream buf;
|
||||||
|
buf << e.getOutput();
|
||||||
|
buf << "\n\033[1mBacktrace:\033[0m\n";
|
||||||
|
for (const auto &line : e.getBacktrace()) {
|
||||||
|
buf << " " << line << "\n";
|
||||||
|
}
|
||||||
|
output = buf.str();
|
||||||
|
});
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
return *result;
|
return *result;
|
||||||
|
@ -59,7 +59,10 @@ void DebugListener::notifyObjectLoaded(ObjectKey key,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
objects.emplace_back(key, &obj, start, stop);
|
auto buf = llvm::MemoryBuffer::getMemBufferCopy(obj.getData(), obj.getFileName());
|
||||||
|
auto newObj = llvm::cantFail(
|
||||||
|
llvm::object::ObjectFile::createObjectFile(buf->getMemBufferRef()));
|
||||||
|
objects.emplace_back(key, std::move(newObj), std::move(buf), start, stop);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugListener::notifyFreeingObject(ObjectKey key) {
|
void DebugListener::notifyFreeingObject(ObjectKey key) {
|
||||||
@ -80,20 +83,27 @@ llvm::Expected<llvm::DILineInfo> DebugListener::symbolize(uintptr_t pc) {
|
|||||||
return llvm::DILineInfo();
|
return llvm::DILineInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
llvm::Expected<std::string> DebugListener::getPrettyBacktrace(uintptr_t pc) {
|
||||||
|
auto invalid = [](const std::string &name) { return name == "<invalid>"; };
|
||||||
|
auto src = symbolize(pc);
|
||||||
|
if (auto err = src.takeError())
|
||||||
|
return std::move(err);
|
||||||
|
if (invalid(src->FunctionName) || invalid(src->FileName))
|
||||||
|
return "";
|
||||||
|
return makeBacktraceFrameString(pc, unmangleFunc(src->FunctionName),
|
||||||
|
simplifyFile(src->FileName), src->Line, src->Column);
|
||||||
|
}
|
||||||
|
|
||||||
std::string DebugListener::getPrettyBacktrace(const std::vector<uintptr_t> &backtrace) {
|
std::string DebugListener::getPrettyBacktrace(const std::vector<uintptr_t> &backtrace) {
|
||||||
auto invalid = [](const std::string &name) { return name == "<invalid>"; };
|
auto invalid = [](const std::string &name) { return name == "<invalid>"; };
|
||||||
std::ostringstream buf;
|
std::ostringstream buf;
|
||||||
buf << "\033[1mBacktrace:\033[0m\n";
|
buf << "\033[1mBacktrace:\033[0m\n";
|
||||||
for (auto pc : backtrace) {
|
for (auto pc : backtrace) {
|
||||||
auto src = symbolize(pc);
|
auto line = getPrettyBacktrace(pc);
|
||||||
if (auto err = src.takeError())
|
if (!line)
|
||||||
break;
|
break;
|
||||||
if (invalid(src->FunctionName) || invalid(src->FileName))
|
if (!line->empty())
|
||||||
continue;
|
buf << " " << *line << "\n";
|
||||||
buf << " "
|
|
||||||
<< makeBacktraceFrameString(pc, unmangleFunc(src->FunctionName),
|
|
||||||
simplifyFile(src->FileName), src->Line, src->Column)
|
|
||||||
<< "\n";
|
|
||||||
}
|
}
|
||||||
return buf.str();
|
return buf.str();
|
||||||
}
|
}
|
||||||
|
@ -12,14 +12,17 @@ public:
|
|||||||
class ObjectInfo {
|
class ObjectInfo {
|
||||||
private:
|
private:
|
||||||
ObjectKey key;
|
ObjectKey key;
|
||||||
const llvm::object::ObjectFile *object;
|
std::unique_ptr<llvm::object::ObjectFile> object;
|
||||||
|
std::unique_ptr<llvm::MemoryBuffer> buffer;
|
||||||
uintptr_t start;
|
uintptr_t start;
|
||||||
uintptr_t stop;
|
uintptr_t stop;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ObjectInfo(ObjectKey key, const llvm::object::ObjectFile *object, uintptr_t start,
|
ObjectInfo(ObjectKey key, std::unique_ptr<llvm::object::ObjectFile> object,
|
||||||
|
std::unique_ptr<llvm::MemoryBuffer> buffer, uintptr_t start,
|
||||||
uintptr_t stop)
|
uintptr_t stop)
|
||||||
: key(key), object(object), start(start), stop(stop) {}
|
: key(key), object(std::move(object)), buffer(std::move(buffer)), start(start),
|
||||||
|
stop(stop) {}
|
||||||
|
|
||||||
ObjectKey getKey() const { return key; }
|
ObjectKey getKey() const { return key; }
|
||||||
const llvm::object::ObjectFile &getObject() const { return *object; }
|
const llvm::object::ObjectFile &getObject() const { return *object; }
|
||||||
@ -40,6 +43,7 @@ public:
|
|||||||
DebugListener() : llvm::JITEventListener(), sym(), objects() {}
|
DebugListener() : llvm::JITEventListener(), sym(), objects() {}
|
||||||
|
|
||||||
llvm::Expected<llvm::DILineInfo> symbolize(uintptr_t pc);
|
llvm::Expected<llvm::DILineInfo> symbolize(uintptr_t pc);
|
||||||
|
llvm::Expected<std::string> getPrettyBacktrace(uintptr_t pc);
|
||||||
std::string getPrettyBacktrace(const std::vector<uintptr_t> &backtrace);
|
std::string getPrettyBacktrace(const std::vector<uintptr_t> &backtrace);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ llvm::Expected<llvm::orc::ThreadSafeModule>
|
|||||||
Engine::optimizeModule(llvm::orc::ThreadSafeModule module,
|
Engine::optimizeModule(llvm::orc::ThreadSafeModule module,
|
||||||
const llvm::orc::MaterializationResponsibility &R) {
|
const llvm::orc::MaterializationResponsibility &R) {
|
||||||
module.withModuleDo(
|
module.withModuleDo(
|
||||||
[](llvm::Module &module) { ir::optimize(&module, /*debug=*/false); });
|
[](llvm::Module &module) { ir::optimize(&module, /*debug=*/true); });
|
||||||
return std::move(module);
|
return std::move(module);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,10 +32,13 @@ Engine::Engine(std::unique_ptr<llvm::orc::TargetProcessControl> tpc,
|
|||||||
optimizeLayer(*this->sess, compileLayer, optimizeModule),
|
optimizeLayer(*this->sess, compileLayer, optimizeModule),
|
||||||
codLayer(*this->sess, optimizeLayer, this->tpciu->getLazyCallThroughManager(),
|
codLayer(*this->sess, optimizeLayer, this->tpciu->getLazyCallThroughManager(),
|
||||||
[this] { return this->tpciu->createIndirectStubsManager(); }),
|
[this] { return this->tpciu->createIndirectStubsManager(); }),
|
||||||
mainJD(this->sess->createBareJITDylib("<main>")) {
|
mainJD(this->sess->createBareJITDylib("<main>")),
|
||||||
|
dbListener(std::make_unique<DebugListener>()) {
|
||||||
mainJD.addGenerator(
|
mainJD.addGenerator(
|
||||||
llvm::cantFail(llvm::orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(
|
llvm::cantFail(llvm::orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(
|
||||||
layout.getGlobalPrefix())));
|
layout.getGlobalPrefix())));
|
||||||
|
objectLayer.setAutoClaimResponsibilityForObjectSymbols(true);
|
||||||
|
objectLayer.registerJITEventListener(*dbListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
Engine::~Engine() {
|
Engine::~Engine() {
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "codon/compiler/debug_listener.h"
|
||||||
#include "codon/sir/llvm/llvm.h"
|
#include "codon/sir/llvm/llvm.h"
|
||||||
|
|
||||||
#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
|
#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
|
||||||
@ -35,6 +36,8 @@ private:
|
|||||||
|
|
||||||
llvm::orc::JITDylib &mainJD;
|
llvm::orc::JITDylib &mainJD;
|
||||||
|
|
||||||
|
std::unique_ptr<DebugListener> dbListener;
|
||||||
|
|
||||||
static void handleLazyCallThroughError();
|
static void handleLazyCallThroughError();
|
||||||
|
|
||||||
static llvm::Expected<llvm::orc::ThreadSafeModule>
|
static llvm::Expected<llvm::orc::ThreadSafeModule>
|
||||||
@ -55,6 +58,8 @@ public:
|
|||||||
|
|
||||||
llvm::orc::JITDylib &getMainJITDylib() { return mainJD; }
|
llvm::orc::JITDylib &getMainJITDylib() { return mainJD; }
|
||||||
|
|
||||||
|
DebugListener *getDebugListener() const { return dbListener.get(); }
|
||||||
|
|
||||||
llvm::Error addModule(llvm::orc::ThreadSafeModule module,
|
llvm::Error addModule(llvm::orc::ThreadSafeModule module,
|
||||||
llvm::orc::ResourceTrackerSP rt = nullptr);
|
llvm::orc::ResourceTrackerSP rt = nullptr);
|
||||||
|
|
||||||
|
@ -81,12 +81,14 @@ private:
|
|||||||
std::string output;
|
std::string output;
|
||||||
std::string type;
|
std::string type;
|
||||||
Message message;
|
Message message;
|
||||||
|
std::vector<std::string> backtrace;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RuntimeErrorInfo(const std::string &output, const std::string &type,
|
RuntimeErrorInfo(const std::string &output, const std::string &type,
|
||||||
const std::string &msg, const std::string &file = "", int line = 0,
|
const std::string &msg, const std::string &file = "", int line = 0,
|
||||||
int col = 0)
|
int col = 0, std::vector<std::string> backtrace = {})
|
||||||
: output(output), type(type), message(msg, file, line, col) {}
|
: output(output), type(type), message(msg, file, line, 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; }
|
||||||
@ -94,6 +96,7 @@ public:
|
|||||||
std::string getFile() const { return message.getFile(); }
|
std::string getFile() const { return message.getFile(); }
|
||||||
int getLine() const { return message.getLine(); }
|
int getLine() const { return message.getLine(); }
|
||||||
int getColumn() const { return message.getColumn(); }
|
int getColumn() const { return message.getColumn(); }
|
||||||
|
std::vector<std::string> getBacktrace() const { return backtrace; }
|
||||||
|
|
||||||
void log(llvm::raw_ostream &out) const override {
|
void log(llvm::raw_ostream &out) const override {
|
||||||
out << type << ": ";
|
out << type << ": ";
|
||||||
|
@ -81,7 +81,6 @@ llvm::Expected<std::string> JIT::run(const ir::Func *input,
|
|||||||
}
|
}
|
||||||
input->accept(*llvisitor);
|
input->accept(*llvisitor);
|
||||||
auto pair = llvisitor->takeModule();
|
auto pair = llvisitor->takeModule();
|
||||||
llvm::StripDebugInfo(*pair.first); // TODO: needed?
|
|
||||||
|
|
||||||
if (auto err = engine->addModule({std::move(pair.first), std::move(pair.second)}))
|
if (auto err = engine->addModule({std::move(pair.first), std::move(pair.second)}))
|
||||||
return std::move(err);
|
return std::move(err);
|
||||||
@ -95,10 +94,16 @@ llvm::Expected<std::string> JIT::run(const ir::Func *input,
|
|||||||
try {
|
try {
|
||||||
CaptureOutput(buffer.rdbuf());
|
CaptureOutput(buffer.rdbuf());
|
||||||
(*repl)();
|
(*repl)();
|
||||||
} catch (const JITError &err) {
|
} catch (const JITError &e) {
|
||||||
return llvm::make_error<error::RuntimeErrorInfo>(err.getOutput(), err.getType(),
|
std::vector<std::string> backtrace;
|
||||||
err.what(), err.getFile(),
|
for (auto pc : e.getBacktrace()) {
|
||||||
err.getLine(), err.getCol());
|
auto line = engine->getDebugListener()->getPrettyBacktrace(pc);
|
||||||
|
if (line && !line->empty())
|
||||||
|
backtrace.push_back(*line);
|
||||||
|
}
|
||||||
|
return llvm::make_error<error::RuntimeErrorInfo>(e.getOutput(), e.getType(),
|
||||||
|
e.what(), e.getFile(), e.getLine(),
|
||||||
|
e.getCol(), backtrace);
|
||||||
}
|
}
|
||||||
return buffer.str();
|
return buffer.str();
|
||||||
}
|
}
|
||||||
|
@ -211,6 +211,7 @@ std::unique_ptr<llvm::Module> LLVMVisitor::makeModule(llvm::LLVMContext &context
|
|||||||
|
|
||||||
std::pair<std::unique_ptr<llvm::Module>, std::unique_ptr<llvm::LLVMContext>>
|
std::pair<std::unique_ptr<llvm::Module>, std::unique_ptr<llvm::LLVMContext>>
|
||||||
LLVMVisitor::takeModule(const SrcInfo *src) {
|
LLVMVisitor::takeModule(const SrcInfo *src) {
|
||||||
|
db.builder->finalize();
|
||||||
auto currentContext = std::move(context);
|
auto currentContext = std::move(context);
|
||||||
auto currentModule = std::move(M);
|
auto currentModule = std::move(M);
|
||||||
|
|
||||||
@ -251,7 +252,10 @@ void LLVMVisitor::process(const Node *x) {
|
|||||||
|
|
||||||
void LLVMVisitor::dump(const std::string &filename) { writeToLLFile(filename, false); }
|
void LLVMVisitor::dump(const std::string &filename) { writeToLLFile(filename, false); }
|
||||||
|
|
||||||
void LLVMVisitor::runLLVMPipeline() { optimize(M.get(), db.debug, plugins); }
|
void LLVMVisitor::runLLVMPipeline() {
|
||||||
|
db.builder->finalize();
|
||||||
|
optimize(M.get(), db.debug, plugins);
|
||||||
|
}
|
||||||
|
|
||||||
void LLVMVisitor::writeToObjectFile(const std::string &filename) {
|
void LLVMVisitor::writeToObjectFile(const std::string &filename) {
|
||||||
runLLVMPipeline();
|
runLLVMPipeline();
|
||||||
@ -688,7 +692,6 @@ void LLVMVisitor::visit(const Module *x) {
|
|||||||
|
|
||||||
B->SetInsertPoint(exitBlock);
|
B->SetInsertPoint(exitBlock);
|
||||||
B->CreateRet(B->getInt32(0));
|
B->CreateRet(B->getInt32(0));
|
||||||
db.builder->finalize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::DISubprogram *LLVMVisitor::getDISubprogramForFunc(const Func *x) {
|
llvm::DISubprogram *LLVMVisitor::getDISubprogramForFunc(const Func *x) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user