diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f0c9979..2178f390 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 diff --git a/codon/compiler/debug_listener.cpp b/codon/compiler/debug_listener.cpp new file mode 100644 index 00000000..b7e496b9 --- /dev/null +++ b/codon/compiler/debug_listener.cpp @@ -0,0 +1,50 @@ +#include "debug_listener.h" + +#include +#include + +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 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(pc - o.getStart()), + llvm::object::SectionedAddress::UndefSection}); + } + } + return llvm::DILineInfo(); +} + +} // namespace codon diff --git a/codon/compiler/debug_listener.h b/codon/compiler/debug_listener.h new file mode 100644 index 00000000..ebd50b87 --- /dev/null +++ b/codon/compiler/debug_listener.h @@ -0,0 +1,49 @@ +#pragma once + +#include +#include +#include + +#include "codon/sir/llvm/llvm.h" + +namespace codon { + +class DebugListener : public llvm::JITEventListener { +public: + class ObjectInfo { + private: + ObjectKey key; + std::unique_ptr object; + std::unique_ptr buffer; + intptr_t start; + intptr_t stop; + + public: + ObjectInfo(ObjectKey key, std::unique_ptr object, + std::unique_ptr 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 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 symbolize(intptr_t pc) const; +}; + +} // namespace codon diff --git a/codon/compiler/engine.cpp b/codon/compiler/engine.cpp index 6e37c613..8d8db4dd 100644 --- a/codon/compiler/engine.cpp +++ b/codon/compiler/engine.cpp @@ -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 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(); }), + []() { return std::make_unique(); }), compileLayer(*this->sess, objectLayer, std::make_unique(std::move(jtmb))), optimizeLayer(*this->sess, compileLayer, optimizeModule), diff --git a/codon/sir/llvm/memory_manager.cpp b/codon/compiler/memory_manager.cpp similarity index 96% rename from codon/sir/llvm/memory_manager.cpp rename to codon/compiler/memory_manager.cpp index 85507535..abaeb097 100644 --- a/codon/sir/llvm/memory_manager.cpp +++ b/codon/compiler/memory_manager.cpp @@ -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 diff --git a/codon/sir/llvm/memory_manager.h b/codon/compiler/memory_manager.h similarity index 95% rename from codon/sir/llvm/memory_manager.h rename to codon/compiler/memory_manager.h index 52eb63ae..0718956d 100644 --- a/codon/sir/llvm/memory_manager.h +++ b/codon/compiler/memory_manager.h @@ -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 diff --git a/codon/sir/llvm/llvisitor.cpp b/codon/sir/llvm/llvisitor.cpp index 3959a89a..d8039389 100644 --- a/codon/sir/llvm/llvisitor.cpp +++ b/codon/sir/llvm/llvisitor.cpp @@ -7,9 +7,10 @@ #include #include +#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 &args, EB.setMCJITMemoryManager(std::make_unique()); llvm::ExecutionEngine *eng = EB.create(); - auto dbListener = std::unique_ptr(); + auto dbListener = std::unique_ptr(); if (db.debug) { - dbListener = std::make_unique(); + dbListener = std::make_unique(); eng->RegisterJITEventListener(dbListener.get()); } @@ -470,11 +471,8 @@ void LLVMVisitor::run(const std::vector &args, auto invalid = [](const std::string &name) { return name == ""; }; 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))