Commit 7bb48009 authored by Kevin Modzelewski's avatar Kevin Modzelewski

LANDINGPAD now returns an ExcInfo triple

ie we now can handle catching the new ExcInfo objects from JITted code.

This should also allow try-finally blocks more easily.
parent 44b63a61
...@@ -224,8 +224,8 @@ void gatherInterpreterRoots(GCVisitor* visitor) { ...@@ -224,8 +224,8 @@ void gatherInterpreterRoots(GCVisitor* visitor) {
ASTInterpreter::ASTInterpreter(CompiledFunction* compiled_function) ASTInterpreter::ASTInterpreter(CompiledFunction* compiled_function)
: compiled_func(compiled_function), source_info(compiled_function->clfunc->source), scope_info(0), next_block(0), : compiled_func(compiled_function), source_info(compiled_function->clfunc->source), scope_info(0), next_block(0),
current_block(0), current_inst(0), last_exception(NULL, NULL, NULL), passed_closure(0), created_closure(0), generator(0), current_block(0), current_inst(0), last_exception(NULL, NULL, NULL), passed_closure(0), created_closure(0),
edgecount(0) { generator(0), edgecount(0) {
CLFunction* f = compiled_function->clfunc; CLFunction* f = compiled_function->clfunc;
if (!source_info->cfg) if (!source_info->cfg)
...@@ -561,10 +561,12 @@ Value ASTInterpreter::visit_langPrimitive(AST_LangPrimitive* node) { ...@@ -561,10 +561,12 @@ Value ASTInterpreter::visit_langPrimitive(AST_LangPrimitive* node) {
} else if (node->opcode == AST_LangPrimitive::NONE) { } else if (node->opcode == AST_LangPrimitive::NONE) {
v = None; v = None;
} else if (node->opcode == AST_LangPrimitive::LANDINGPAD) { } else if (node->opcode == AST_LangPrimitive::LANDINGPAD) {
abort(); assert(last_exception.type);
// Have to figure out how to represent landingpads Box* type = last_exception.type;
//v = last_exception; Box* value = last_exception.value ? last_exception.value : None;
//last_exception = nullptr; Box* traceback = last_exception.traceback ? last_exception.traceback : None;
v = new BoxedTuple({ type, value, traceback });
last_exception = ExcInfo(NULL, NULL, NULL);
} else if (node->opcode == AST_LangPrimitive::ISINSTANCE) { } else if (node->opcode == AST_LangPrimitive::ISINSTANCE) {
assert(node->args.size() == 3); assert(node->args.size() == 3);
Value obj = visit_expr(node->args[0]); Value obj = visit_expr(node->args[0]);
......
...@@ -72,6 +72,7 @@ struct GlobalState { ...@@ -72,6 +72,7 @@ struct GlobalState {
llvm::Type* llvm_str_type_ptr; llvm::Type* llvm_str_type_ptr;
llvm::Type* llvm_clfunction_type_ptr, *llvm_closure_type_ptr, *llvm_generator_type_ptr; llvm::Type* llvm_clfunction_type_ptr, *llvm_closure_type_ptr, *llvm_generator_type_ptr;
llvm::Type* llvm_module_type_ptr, *llvm_bool_type_ptr; llvm::Type* llvm_module_type_ptr, *llvm_bool_type_ptr;
llvm::Type* llvm_excinfo_type;
llvm::Type* i1, *i8, *i8_ptr, *i32, *i64, *void_, *double_; llvm::Type* i1, *i8, *i8_ptr, *i32, *i64, *void_, *double_;
llvm::Type* vector_ptr; llvm::Type* vector_ptr;
......
...@@ -37,6 +37,10 @@ ...@@ -37,6 +37,10 @@
namespace pyston { namespace pyston {
extern "C" void dumpLLVM(llvm::Value* v) {
v->dump();
}
llvm::Value* IRGenState::getScratchSpace(int min_bytes) { llvm::Value* IRGenState::getScratchSpace(int min_bytes) {
llvm::BasicBlock& entry_block = getLLVMFunction()->getEntryBlock(); llvm::BasicBlock& entry_block = getLLVMFunction()->getEntryBlock();
...@@ -397,22 +401,36 @@ private: ...@@ -397,22 +401,36 @@ private:
llvm::StructType::create(std::vector<llvm::Type*>{ g.i8_ptr, g.i64 }), personality_func, 1); llvm::StructType::create(std::vector<llvm::Type*>{ g.i8_ptr, g.i64 }), personality_func, 1);
landing_pad->addClause(embedConstantPtr(NULL, g.i8_ptr)); landing_pad->addClause(embedConstantPtr(NULL, g.i8_ptr));
llvm::Value* exc_pointer = emitter.getBuilder()->CreateExtractValue(landing_pad, { 0 }); llvm::Value* cxaexc_pointer = emitter.getBuilder()->CreateExtractValue(landing_pad, { 0 });
llvm::Value* exc_obj;
if (irstate->getEffortLevel() != EffortLevel::INTERPRETED) { if (irstate->getEffortLevel() != EffortLevel::INTERPRETED) {
llvm::Value* exc_obj_pointer llvm::Value* excinfo_pointer
= emitter.getBuilder()->CreateCall(g.funcs.__cxa_begin_catch, exc_pointer); = emitter.getBuilder()->CreateCall(g.funcs.__cxa_begin_catch, cxaexc_pointer);
llvm::Value* exc_obj_pointer_casted llvm::Value* excinfo_pointer_casted
= emitter.getBuilder()->CreateBitCast(exc_obj_pointer, g.llvm_value_type_ptr->getPointerTo()); = emitter.getBuilder()->CreateBitCast(excinfo_pointer, g.llvm_excinfo_type->getPointerTo());
exc_obj = emitter.getBuilder()->CreateLoad(exc_obj_pointer_casted);
emitter.getBuilder()->CreateCall(g.funcs.__cxa_end_catch); auto* builder = emitter.getBuilder();
llvm::Value* exc_type
= builder->CreateLoad(builder->CreateConstInBoundsGEP2_32(excinfo_pointer_casted, 0, 0));
llvm::Value* exc_value
= builder->CreateLoad(builder->CreateConstInBoundsGEP2_32(excinfo_pointer_casted, 0, 1));
llvm::Value* exc_traceback
= builder->CreateLoad(builder->CreateConstInBoundsGEP2_32(excinfo_pointer_casted, 0, 2));
assert(exc_type->getType() == g.llvm_value_type_ptr);
assert(exc_value->getType() == g.llvm_value_type_ptr);
assert(exc_traceback->getType() == g.llvm_value_type_ptr);
return makeTuple({ new ConcreteCompilerVariable(UNKNOWN, exc_type, true),
new ConcreteCompilerVariable(UNKNOWN, exc_value, true),
new ConcreteCompilerVariable(UNKNOWN, exc_traceback, true) });
} else { } else {
// TODO This doesn't get hit, right?
abort();
// The interpreter can't really support the full C++ exception handling model since it's // The interpreter can't really support the full C++ exception handling model since it's
// itself written in C++. Let's make it easier for the interpreter and use a simpler interface: // itself written in C++. Let's make it easier for the interpreter and use a simpler interface:
exc_obj = emitter.getBuilder()->CreateBitCast(exc_pointer, g.llvm_value_type_ptr); llvm::Value* exc_obj = emitter.getBuilder()->CreateBitCast(cxaexc_pointer, g.llvm_value_type_ptr);
} }
return new ConcreteCompilerVariable(UNKNOWN, exc_obj, true);
} }
case AST_LangPrimitive::LOCALS: { case AST_LangPrimitive::LOCALS: {
assert(node->args.size() == 0); assert(node->args.size() == 0);
......
...@@ -143,6 +143,9 @@ void initGlobalFuncs(GlobalState& g) { ...@@ -143,6 +143,9 @@ void initGlobalFuncs(GlobalState& g) {
g.llvm_generator_type_ptr = g.stdlib_module->getTypeByName("class.pyston::BoxedGenerator")->getPointerTo(); g.llvm_generator_type_ptr = g.stdlib_module->getTypeByName("class.pyston::BoxedGenerator")->getPointerTo();
assert(g.llvm_generator_type_ptr); assert(g.llvm_generator_type_ptr);
g.llvm_excinfo_type = g.stdlib_module->getTypeByName("struct.pyston::ExcInfo");
assert(g.llvm_excinfo_type);
#define GET(N) g.funcs.N = getFunc((void*)N, STRINGIFY(N)) #define GET(N) g.funcs.N = getFunc((void*)N, STRINGIFY(N))
g.funcs.printf = addFunc((void*)printf, g.i8_ptr, true); g.funcs.printf = addFunc((void*)printf, g.i8_ptr, true);
......
...@@ -78,7 +78,7 @@ private: ...@@ -78,7 +78,7 @@ private:
struct ExcBlockInfo { struct ExcBlockInfo {
CFGBlock* exc_dest; CFGBlock* exc_dest;
std::string exc_obj_name; std::string exc_type_name, exc_value_name, exc_traceback_name;
}; };
std::vector<ExcBlockInfo> exc_handlers; std::vector<ExcBlockInfo> exc_handlers;
...@@ -460,6 +460,12 @@ private: ...@@ -460,6 +460,12 @@ private:
#endif #endif
} }
std::string nodeName(AST* node, const std::string& suffix) {
char buf[50];
snprintf(buf, 50, "#%p_%s", node, suffix.c_str());
return std::string(buf);
}
std::string nodeName(AST* node, const std::string& suffix, int idx) { std::string nodeName(AST* node, const std::string& suffix, int idx) {
char buf[50]; char buf[50];
snprintf(buf, 50, "#%p_%s_%d", node, suffix.c_str(), idx); snprintf(buf, 50, "#%p_%s_%d", node, suffix.c_str(), idx);
...@@ -1102,7 +1108,12 @@ public: ...@@ -1102,7 +1108,12 @@ public:
curblock = exc_dest; curblock = exc_dest;
AST_Assign* exc_asgn = new AST_Assign(); AST_Assign* exc_asgn = new AST_Assign();
exc_asgn->targets.push_back(makeName(exc_info.exc_obj_name, AST_TYPE::Store, node->lineno)); AST_Tuple* target = new AST_Tuple();
target->elts.push_back(makeName(exc_info.exc_type_name, AST_TYPE::Store, node->lineno));
target->elts.push_back(makeName(exc_info.exc_value_name, AST_TYPE::Store, node->lineno));
target->elts.push_back(makeName(exc_info.exc_traceback_name, AST_TYPE::Store, node->lineno));
exc_asgn->targets.push_back(target);
exc_asgn->value = new AST_LangPrimitive(AST_LangPrimitive::LANDINGPAD); exc_asgn->value = new AST_LangPrimitive(AST_LangPrimitive::LANDINGPAD);
curblock->push_back(exc_asgn); curblock->push_back(exc_asgn);
...@@ -1811,8 +1822,10 @@ public: ...@@ -1811,8 +1822,10 @@ public:
assert(node->handlers.size() > 0); assert(node->handlers.size() > 0);
CFGBlock* exc_handler_block = cfg->addDeferredBlock(); CFGBlock* exc_handler_block = cfg->addDeferredBlock();
std::string exc_obj_name = nodeName(node); std::string exc_type_name = nodeName(node, "type");
exc_handlers.push_back({ exc_handler_block, exc_obj_name }); std::string exc_value_name = nodeName(node, "value");
std::string exc_traceback_name = nodeName(node, "traceback");
exc_handlers.push_back({ exc_handler_block, exc_type_name, exc_value_name, exc_traceback_name });
for (AST_stmt* subnode : node->body) { for (AST_stmt* subnode : node->body) {
subnode->accept(this); subnode->accept(this);
...@@ -1838,7 +1851,8 @@ public: ...@@ -1838,7 +1851,8 @@ public:
cfg->placeBlock(exc_handler_block); cfg->placeBlock(exc_handler_block);
curblock = exc_handler_block; curblock = exc_handler_block;
AST_expr* exc_obj = makeName(exc_obj_name, AST_TYPE::Load, node->lineno); // TODO: this should be an EXCEPTION_MATCHES(exc_type_name)
AST_expr* exc_obj = makeName(exc_value_name, AST_TYPE::Load, node->lineno);
bool caught_all = false; bool caught_all = false;
for (AST_ExceptHandler* exc_handler : node->handlers) { for (AST_ExceptHandler* exc_handler : node->handlers) {
...@@ -2231,7 +2245,7 @@ CFG* computeCFG(SourceInfo* source, std::vector<AST_stmt*> body) { ...@@ -2231,7 +2245,7 @@ CFG* computeCFG(SourceInfo* source, std::vector<AST_stmt*> body) {
} }
} }
if (VERBOSITY("cfg") >= 2) { if (VERBOSITY("cfg") >= 1) {
printf("Final cfg:\n"); printf("Final cfg:\n");
rtn->print(); rtn->print();
} }
......
...@@ -476,7 +476,6 @@ struct ExcInfo { ...@@ -476,7 +476,6 @@ struct ExcInfo {
ExcInfo(Box* type, Box* value, Box* traceback) : type(type), value(value), traceback(traceback) {} ExcInfo(Box* type, Box* value, Box* traceback) : type(type), value(value), traceback(traceback) {}
bool matches(BoxedClass* cls) const; bool matches(BoxedClass* cls) const;
}; };
} }
#endif #endif
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