mirror of https://github.com/exaloop/codon
Add debug listener
parent
9e1aa03bd5
commit
fb04f81d3f
|
@ -83,9 +83,11 @@ add_definitions(${LLVM_DEFINITIONS})
|
|||
|
||||
set(CODON_HPPFILES
|
||||
codon/compiler/compiler.h
|
||||
codon/compiler/debug_listener.h
|
||||
codon/compiler/engine.h
|
||||
codon/compiler/error.h
|
||||
codon/compiler/jit.h
|
||||
codon/compiler/memory_manager.h
|
||||
codon/dsl/dsl.h
|
||||
codon/dsl/plugins.h
|
||||
codon/parser/ast.h
|
||||
|
@ -129,7 +131,6 @@ set(CODON_HPPFILES
|
|||
codon/sir/llvm/coro/Coroutines.h
|
||||
codon/sir/llvm/llvisitor.h
|
||||
codon/sir/llvm/llvm.h
|
||||
codon/sir/llvm/memory_manager.h
|
||||
codon/sir/llvm/optimize.h
|
||||
codon/sir/module.h
|
||||
codon/sir/sir.h
|
||||
|
@ -209,9 +210,11 @@ set(CODON_HPPFILES
|
|||
extra/jupyter/src/codon.h)
|
||||
set(CODON_CPPFILES
|
||||
codon/compiler/compiler.cpp
|
||||
codon/compiler/debug_listener.cpp
|
||||
codon/compiler/engine.cpp
|
||||
codon/compiler/error.cpp
|
||||
codon/compiler/jit.cpp
|
||||
codon/compiler/memory_manager.cpp
|
||||
codon/dsl/plugins.cpp
|
||||
codon/parser/ast/expr.cpp
|
||||
codon/parser/ast/stmt.cpp
|
||||
|
@ -253,7 +256,6 @@ set(CODON_CPPFILES
|
|||
codon/sir/llvm/coro/CoroSplit.cpp
|
||||
codon/sir/llvm/coro/Coroutines.cpp
|
||||
codon/sir/llvm/llvisitor.cpp
|
||||
codon/sir/llvm/memory_manager.cpp
|
||||
codon/sir/llvm/optimize.cpp
|
||||
codon/sir/module.cpp
|
||||
codon/sir/transform/cleanup/canonical.cpp
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
#include "debug_listener.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
namespace codon {
|
||||
|
||||
void DebugListener::notifyObjectLoaded(ObjectKey key,
|
||||
const llvm::object::ObjectFile &obj,
|
||||
const llvm::RuntimeDyld::LoadedObjectInfo &L) {
|
||||
intptr_t start = 0, stop = 0;
|
||||
for (const auto &sec : obj.sections()) {
|
||||
if (sec.isText()) {
|
||||
start = L.getSectionLoadAddress(sec);
|
||||
stop = start + sec.getSize();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto 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));
|
||||
}
|
||||
objects.emplace_back(key, std::move(saved.first), std::move(saved.second), start,
|
||||
stop);
|
||||
}
|
||||
|
||||
void DebugListener::notifyFreeingObject(ObjectKey key) {
|
||||
objects.erase(
|
||||
std::remove_if(objects.begin(), objects.end(),
|
||||
[key](const ObjectInfo &o) { return key == o.getKey(); }),
|
||||
objects.end());
|
||||
}
|
||||
|
||||
llvm::Expected<llvm::DILineInfo> DebugListener::symbolize(intptr_t pc) const {
|
||||
for (const auto &o : objects) {
|
||||
if (o.contains(pc)) {
|
||||
llvm::symbolize::LLVMSymbolizer sym;
|
||||
return sym.symbolizeCode(o.getObject(),
|
||||
{static_cast<uint64_t>(pc - o.getStart()),
|
||||
llvm::object::SectionedAddress::UndefSection});
|
||||
}
|
||||
}
|
||||
return llvm::DILineInfo();
|
||||
}
|
||||
|
||||
} // namespace codon
|
|
@ -0,0 +1,49 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "codon/sir/llvm/llvm.h"
|
||||
|
||||
namespace codon {
|
||||
|
||||
class DebugListener : public llvm::JITEventListener {
|
||||
public:
|
||||
class ObjectInfo {
|
||||
private:
|
||||
ObjectKey key;
|
||||
std::unique_ptr<llvm::object::ObjectFile> object;
|
||||
std::unique_ptr<llvm::MemoryBuffer> buffer;
|
||||
intptr_t start;
|
||||
intptr_t stop;
|
||||
|
||||
public:
|
||||
ObjectInfo(ObjectKey key, std::unique_ptr<llvm::object::ObjectFile> object,
|
||||
std::unique_ptr<llvm::MemoryBuffer> buffer, intptr_t start,
|
||||
intptr_t 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; }
|
||||
const llvm::MemoryBuffer &getBuffer() const { return *buffer; }
|
||||
intptr_t getStart() const { return start; }
|
||||
intptr_t getStop() const { return stop; }
|
||||
bool contains(intptr_t pc) const { return start <= pc && pc < stop; }
|
||||
};
|
||||
|
||||
private:
|
||||
std::vector<ObjectInfo> objects;
|
||||
|
||||
void notifyObjectLoaded(ObjectKey key, const llvm::object::ObjectFile &obj,
|
||||
const llvm::RuntimeDyld::LoadedObjectInfo &L) override;
|
||||
void notifyFreeingObject(ObjectKey key) override;
|
||||
|
||||
public:
|
||||
DebugListener() : llvm::JITEventListener(), objects() {}
|
||||
|
||||
llvm::Expected<llvm::DILineInfo> symbolize(intptr_t pc) const;
|
||||
};
|
||||
|
||||
} // namespace codon
|
|
@ -1,6 +1,6 @@
|
|||
#include "engine.h"
|
||||
|
||||
#include "codon/sir/llvm/memory_manager.h"
|
||||
#include "codon/compiler/memory_manager.h"
|
||||
#include "codon/sir/llvm/optimize.h"
|
||||
|
||||
namespace codon {
|
||||
|
@ -26,7 +26,7 @@ Engine::Engine(std::unique_ptr<llvm::orc::TargetProcessControl> tpc,
|
|||
: tpc(std::move(tpc)), sess(std::move(sess)), tpciu(std::move(tpciu)),
|
||||
layout(std::move(layout)), mangle(*this->sess, this->layout),
|
||||
objectLayer(*this->sess,
|
||||
[]() { return std::make_unique<ir::BoehmGCMemoryManager>(); }),
|
||||
[]() { return std::make_unique<BoehmGCMemoryManager>(); }),
|
||||
compileLayer(*this->sess, objectLayer,
|
||||
std::make_unique<llvm::orc::ConcurrentIRCompiler>(std::move(jtmb))),
|
||||
optimizeLayer(*this->sess, compileLayer, optimizeModule),
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#include "codon/runtime/lib.h"
|
||||
|
||||
namespace codon {
|
||||
namespace ir {
|
||||
|
||||
BoehmGCMemoryManager::BoehmGCMemoryManager() : SectionMemoryManager(), roots() {}
|
||||
|
||||
|
@ -26,5 +25,4 @@ BoehmGCMemoryManager::~BoehmGCMemoryManager() {
|
|||
}
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
} // namespace codon
|
|
@ -6,7 +6,6 @@
|
|||
#include "codon/sir/llvm/llvm.h"
|
||||
|
||||
namespace codon {
|
||||
namespace ir {
|
||||
|
||||
/// Simple extension of LLVM's SectionMemoryManager which catches data section
|
||||
/// allocations and registers them with the GC. This allows the GC to know not
|
||||
|
@ -23,5 +22,4 @@ public:
|
|||
~BoehmGCMemoryManager() override;
|
||||
};
|
||||
|
||||
} // namespace ir
|
||||
} // namespace codon
|
|
@ -7,9 +7,10 @@
|
|||
#include <unistd.h>
|
||||
#include <utility>
|
||||
|
||||
#include "codon/compiler/debug_listener.h"
|
||||
#include "codon/compiler/memory_manager.h"
|
||||
#include "codon/runtime/lib.h"
|
||||
#include "codon/sir/dsl/codegen.h"
|
||||
#include "codon/sir/llvm/memory_manager.h"
|
||||
#include "codon/sir/llvm/optimize.h"
|
||||
#include "codon/util/common.h"
|
||||
|
||||
|
@ -448,9 +449,9 @@ void LLVMVisitor::run(const std::vector<std::string> &args,
|
|||
EB.setMCJITMemoryManager(std::make_unique<BoehmGCMemoryManager>());
|
||||
llvm::ExecutionEngine *eng = EB.create();
|
||||
|
||||
auto dbListener = std::unique_ptr<DebugInfoListener>();
|
||||
auto dbListener = std::unique_ptr<DebugListener>();
|
||||
if (db.debug) {
|
||||
dbListener = std::make_unique<DebugInfoListener>();
|
||||
dbListener = std::make_unique<DebugListener>();
|
||||
eng->RegisterJITEventListener(dbListener.get());
|
||||
}
|
||||
|
||||
|
@ -470,11 +471,8 @@ void LLVMVisitor::run(const std::vector<std::string> &args,
|
|||
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});
|
||||
auto src = dbListener->symbolize(pc);
|
||||
if (auto err = src.takeError())
|
||||
break;
|
||||
if (invalid(src->FunctionName) || invalid(src->FileName))
|
||||
|
|
Loading…
Reference in New Issue