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