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