Commit e8120fb1 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Clean up tracebacks, and enable tracebacks for interpreted code

parent 39ac322d
......@@ -21,7 +21,6 @@
#include "core/types.h"
namespace llvm {
class DILineInfo;
class ExecutionEngine;
class JITEventListener;
class LLVMContext;
......@@ -84,7 +83,7 @@ extern GlobalState g;
// in runtime_hooks.cpp:
void initGlobalFuncs(GlobalState& g);
const llvm::DILineInfo* getLineInfoFor(uint64_t addr);
const LineInfo* getLineInfoFor(uint64_t inst_addr);
}
......
......@@ -20,6 +20,7 @@
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
......@@ -206,6 +207,8 @@ static void set(SymMap& symbols, const llvm::BasicBlock::iterator& it, Val v) {
}
static std::unordered_map<void*, const SymMap*> interpreter_roots;
static std::unordered_map<void*, llvm::Instruction*> cur_instruction_map;
void gatherInterpreterRootsForFrame(GCVisitor* visitor, void* frame_ptr) {
auto it = interpreter_roots.find(frame_ptr);
if (it == interpreter_roots.end()) {
......@@ -235,9 +238,31 @@ public:
~UnregisterHelper() {
assert(interpreter_roots.count(frame_ptr));
interpreter_roots.erase(frame_ptr);
assert(cur_instruction_map.count(frame_ptr));
cur_instruction_map.erase(frame_ptr);
}
};
static std::unordered_map<llvm::Instruction*, LineInfo*> line_infos;
const LineInfo* getLineInfoForInterpretedFrame(void* frame_ptr) {
llvm::Instruction* cur_instruction = cur_instruction_map[frame_ptr];
assert(cur_instruction);
auto it = line_infos.find(cur_instruction);
if (it == line_infos.end()) {
const llvm::DebugLoc& debug_loc = cur_instruction->getDebugLoc();
llvm::DISubprogram subprog(debug_loc.getScope(g.context));
// TODO better lifetime management
LineInfo *rtn = new LineInfo(debug_loc.getLine(), debug_loc.getCol(), subprog.getFilename(), subprog.getName());
line_infos.insert(it, std::make_pair(cur_instruction, rtn));
return rtn;
} else {
return it->second;
}
}
Box* interpretFunction(llvm::Function* f, int nargs, Box* arg1, Box* arg2, Box* arg3, Box** args) {
assert(f);
......@@ -291,6 +316,7 @@ Box* interpretFunction(llvm::Function* f, int nargs, Box* arg1, Box* arg2, Box*
while (true) {
for (llvm::Instruction& _inst : *curblock) {
llvm::Instruction* inst = &_inst;
cur_instruction_map[frame_ptr] = inst;
if (VERBOSITY("interpreter") >= 2) {
printf("executing in %s: ", f->getName().data());
......
......@@ -23,9 +23,13 @@ namespace pyston {
class Box;
class GCVisitor;
class LineInfo;
void gatherInterpreterRootsForFrame(GCVisitor* visitor, void* frame_ptr);
Box* interpretFunction(llvm::Function* f, int nargs, Box* arg1, Box* arg2, Box* arg3, Box** args);
void gatherInterpreterRootsForFrame(GCVisitor* visitor, void* frame_ptr);
const LineInfo* getLineInfoForInterpretedFrame(void* frame_ptr);
}
#endif
......@@ -75,20 +75,25 @@ class LineTableRegistry {
private:
struct LineTableRegistryEntry {
const uint64_t addr, size;
const llvm::DILineInfoTable linetable;
LineTableRegistryEntry(uint64_t addr, uint64_t size, llvm::DILineInfoTable linetable) :
addr(addr), size(size), linetable(linetable) {
std::vector<std::pair<uint64_t, LineInfo> > linetable;
LineTableRegistryEntry(uint64_t addr, uint64_t size) :
addr(addr), size(size) {
}
};
std::vector<LineTableRegistryEntry> entries;
public:
void registerLineTable(uint64_t addr, uint64_t size, llvm::DILineInfoTable linetable) {
entries.push_back(LineTableRegistryEntry(addr, size, linetable));
void registerLineTable(uint64_t addr, uint64_t size, llvm::DILineInfoTable& lines) {
entries.push_back(LineTableRegistryEntry(addr, size));
auto& entry = entries.back();
for (int i = 0; i < lines.size(); i++) {
entry.linetable.push_back(std::make_pair(lines[i].first, LineInfo(lines[i].second.Line, lines[i].second.Column, lines[i].second.FileName, lines[i].second.FunctionName)));
}
}
const llvm::DILineInfo* getLineInfoFor(uint64_t addr) {
const LineInfo* getLineInfoFor(uint64_t addr) {
for (const auto& entry : entries) {
if (addr < entry.addr || addr >= entry.addr + entry.size)
continue;
......@@ -105,7 +110,7 @@ public:
};
static LineTableRegistry line_table_registry;
const llvm::DILineInfo* getLineInfoFor(uint64_t addr) {
const LineInfo* getLineInfoFor(uint64_t addr) {
return line_table_registry.getLineInfoFor(addr);
}
......@@ -130,6 +135,7 @@ public:
if (I->getSize(Size))
continue;
// TODO this should be the Python name, not the C name:
#if LLVMREV < 208921
llvm::DILineInfoTable lines = Context->getLineInfoForAddressRange(
Addr, Size, llvm::DILineInfoSpecifier::FunctionName | llvm::DILineInfoSpecifier::FileLineInfo | llvm::DILineInfoSpecifier::AbsoluteFilePath);
......
......@@ -391,7 +391,18 @@ void addToSysPath(const std::string& path);
void addToSysArgv(const char* str);
std::string formatException(Box* e);
void printTraceback();
void printLastTraceback();
struct LineInfo {
public:
const int line, column;
std::string file, func;
LineInfo(int line, int column, const std::string& file, const std::string& func) :
line(line), column(column), file(file), func(func) {
}
};
}
#endif
......@@ -146,7 +146,7 @@ int main(int argc, char** argv) {
}
catch (Box* b) {
std::string msg = formatException(b);
printTraceback();
printLastTraceback();
fprintf(stderr, "%s\n", msg.c_str());
exit(1);
}
......@@ -231,7 +231,7 @@ int main(int argc, char** argv) {
}
catch (Box* b) {
std::string msg = formatException(b);
printTraceback();
printLastTraceback();
fprintf(stderr, "%s\n", msg.c_str());
}
}
......
......@@ -18,6 +18,7 @@
#include "llvm/DebugInfo/DIContext.h"
#include "codegen/codegen.h"
#include "codegen/llvm_interpreter.h"
#include "core/options.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
......@@ -115,16 +116,16 @@ void raiseExc(Box* exc_obj) {
abort();
}
static std::vector<const llvm::DILineInfo*> last_tb;
void printTraceback() {
static std::vector<const LineInfo*> last_tb;
void printLastTraceback() {
fprintf(stderr, "Traceback (most recent call last):\n");
for (auto line : last_tb) {
fprintf(stderr, " File \"%s\", line %d, in %s:\n", line->FileName.c_str(), line->Line, line->FunctionName.c_str());
fprintf(stderr, " File \"%s\", line %d, in %s:\n", line->file.c_str(), line->line, line->func.c_str());
FILE* f = fopen(line->FileName.c_str(), "r");
FILE* f = fopen(line->file.c_str(), "r");
if (f) {
for (int i = 1; i < line->Line; i++) {
for (int i = 1; i < line->line; i++) {
char* buf = NULL;
size_t size;
size_t r = getline(&buf, &size, f);
......@@ -151,12 +152,12 @@ void printTraceback() {
}
}
static std::vector<const llvm::DILineInfo*> getTracebackEntries() {
std::vector<const llvm::DILineInfo*> entries;
static std::vector<const LineInfo*> getTracebackEntries() {
std::vector<const LineInfo*> entries;
unw_cursor_t cursor;
unw_context_t uc;
unw_word_t ip, sp;
unw_word_t ip, bp;
unw_getcontext(&uc);
unw_init_local(&cursor, &uc);
......@@ -167,9 +168,21 @@ static std::vector<const llvm::DILineInfo*> getTracebackEntries() {
while (unw_step(&cursor) > 0) {
unw_get_reg(&cursor, UNW_REG_IP, &ip);
const llvm::DILineInfo* line = getLineInfoFor((uint64_t)ip);
const LineInfo* line = getLineInfoFor((uint64_t)ip);
if (line) {
entries.push_back(line);
} else {
unw_get_reg(&cursor, UNW_TDEP_BP, &bp);
unw_proc_info_t pip;
code = unw_get_proc_info(&cursor, &pip);
RELEASE_ASSERT(code == 0, "%d", code);
if (pip.start_ip == (intptr_t)interpretFunction) {
line = getLineInfoForInterpretedFrame((void*)bp);
assert(line);
entries.push_back(line);
}
}
}
std::reverse(entries.begin(), entries.end());
......
......@@ -205,8 +205,7 @@ extern "C" void conservativeGCHandler(GCVisitor* v, void* p) {
extern "C" {
BoxedClass* object_cls, *type_cls, *none_cls, *bool_cls, *int_cls, *float_cls, *str_cls, *function_cls,
*instancemethod_cls, *list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls, *file_cls, *member_cls,
*traceback_cls;
*instancemethod_cls, *list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls, *file_cls, *member_cls;
const ObjectFlavor object_flavor(&boxGCHandler, NULL);
const ObjectFlavor type_flavor(&typeGCHandler, NULL);
......@@ -224,7 +223,6 @@ const ObjectFlavor dict_flavor(&dictGCHandler, NULL);
const ObjectFlavor tuple_flavor(&tupleGCHandler, NULL);
const ObjectFlavor file_flavor(&boxGCHandler, NULL);
const ObjectFlavor member_flavor(&boxGCHandler, NULL);
const ObjectFlavor traceback_flavor(&boxGCHandler, NULL);
const AllocationKind untracked_kind(NULL, NULL);
const AllocationKind hc_kind(&hcGCHandler, NULL);
......@@ -446,7 +444,6 @@ void setupRuntime() {
file_cls = new BoxedClass(object_cls, 0, sizeof(BoxedFile), false);
set_cls = new BoxedClass(object_cls, 0, sizeof(BoxedSet), false);
member_cls = new BoxedClass(object_cls, 0, sizeof(BoxedMemberDescriptor), false);
traceback_cls = new BoxedClass(object_cls, 0, sizeof(BoxedTraceback), false);
STR = typeFromClass(str_cls);
BOXED_INT = typeFromClass(int_cls);
......
......@@ -17,10 +17,6 @@
#include "core/types.h"
namespace llvm {
class DILineInfo;
}
namespace pyston {
extern bool IN_SHUTDOWN;
......@@ -64,13 +60,12 @@ BoxedList* getSysPath();
extern "C" {
extern BoxedClass* object_cls, *type_cls, *bool_cls, *int_cls, *float_cls, *str_cls, *function_cls, *none_cls,
*instancemethod_cls, *list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls, *file_cls, *xrange_cls, *member_cls,
*traceback_cls;
*instancemethod_cls, *list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls, *file_cls, *xrange_cls, *member_cls;
}
extern "C" {
extern const ObjectFlavor object_flavor, type_flavor, bool_flavor, int_flavor, float_flavor, str_flavor,
function_flavor, none_flavor, instancemethod_flavor, list_flavor, slice_flavor, module_flavor, dict_flavor,
tuple_flavor, file_flavor, xrange_flavor, member_flavor, traceback_flavor;
tuple_flavor, file_flavor, xrange_flavor, member_flavor;
}
extern "C" { extern Box* None, *NotImplemented, *True, *False; }
extern "C" {
......@@ -298,15 +293,6 @@ public:
BoxedMemberDescriptor(MemberType type, int offset) : Box(&member_flavor, member_cls), type(type), offset(offset) {}
};
class BoxedTraceback : public Box {
public:
const std::vector<const llvm::DILineInfo*> entries;
BoxedTraceback(const std::vector<const llvm::DILineInfo*> &&entries) : Box(&traceback_flavor, traceback_cls),
entries(std::move(entries)) {
}
};
extern "C" void boxGCHandler(GCVisitor* v, void* p);
Box* exceptionNew1(BoxedClass* cls);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment