Commit 14b247f7 authored by Kevin Modzelewski's avatar Kevin Modzelewski

'raise Exception' behaves the same as 'raise Exception()'

The python stdlib apparently uses a bunch of old-style ways
of doing things.

Instead of doing the throwing directly in the generated IR, call
a runtime function raise1 which will take care of the semantics
of checking the type of the raised object, etc.
parent 212383bf
...@@ -31,13 +31,6 @@ ...@@ -31,13 +31,6 @@
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
#include "runtime/types.h" #include "runtime/types.h"
extern "C" {
// Hack: we only need RTTI for a single type (Box*), which we know will get emmitted,
// so just use the mangled name directly instead of using typeid() since that requires
// turning on RTTI for *everything* (including llvm)
extern void* _ZTIPN6pyston3BoxE;
}
namespace pyston { namespace pyston {
llvm::Value* IRGenState::getScratchSpace(int min_bytes) { llvm::Value* IRGenState::getScratchSpace(int min_bytes) {
...@@ -1745,15 +1738,7 @@ private: ...@@ -1745,15 +1738,7 @@ private:
ConcreteCompilerVariable* converted_arg0 = arg0->makeConverted(emitter, arg0->getBoxType()); ConcreteCompilerVariable* converted_arg0 = arg0->makeConverted(emitter, arg0->getBoxType());
arg0->decvref(emitter); arg0->decvref(emitter);
llvm::Value* exc_mem emitter.createCall(exc_info, g.funcs.raise1, { converted_arg0->getValue() });
= emitter.getBuilder()->CreateCall(g.funcs.__cxa_allocate_exception, getConstantInt(sizeof(void*), g.i64));
llvm::Value* bitcasted = emitter.getBuilder()->CreateBitCast(exc_mem, g.llvm_value_type_ptr->getPointerTo());
emitter.getBuilder()->CreateStore(converted_arg0->getValue(), bitcasted);
converted_arg0->decvref(emitter);
void* type_id = &_ZTIPN6pyston3BoxE /* &typeid(Box*) */;
emitter.createCall(exc_info, g.funcs.__cxa_throw,
{ exc_mem, embedConstantPtr(type_id, g.i8_ptr), embedConstantPtr(nullptr, g.i8_ptr) });
emitter.getBuilder()->CreateUnreachable(); emitter.getBuilder()->CreateUnreachable();
endBlock(DEAD); endBlock(DEAD);
......
...@@ -41,8 +41,6 @@ ...@@ -41,8 +41,6 @@
extern "C" void* __cxa_begin_catch(void*); extern "C" void* __cxa_begin_catch(void*);
extern "C" void __cxa_end_catch(); extern "C" void __cxa_end_catch();
extern "C" void* __cxa_allocate_exception(size_t);
extern "C" void __cxa_throw(void*, void*, void (*)(void*));
namespace pyston { namespace pyston {
...@@ -221,8 +219,7 @@ void initGlobalFuncs(GlobalState& g) { ...@@ -221,8 +219,7 @@ void initGlobalFuncs(GlobalState& g) {
GET(__cxa_begin_catch); GET(__cxa_begin_catch);
g.funcs.__cxa_end_catch = addFunc((void*)__cxa_end_catch, g.void_); g.funcs.__cxa_end_catch = addFunc((void*)__cxa_end_catch, g.void_);
g.funcs.__cxa_allocate_exception = addFunc((void*)__cxa_allocate_exception, g.i8_ptr, g.i64); GET(raise1);
g.funcs.__cxa_throw = addFunc((void*)__cxa_throw, g.void_, g.i8_ptr, g.i8_ptr, g.i8_ptr);
g.funcs.div_i64_i64 = getFunc((void*)div_i64_i64, "div_i64_i64"); g.funcs.div_i64_i64 = getFunc((void*)div_i64_i64, "div_i64_i64");
g.funcs.mod_i64_i64 = getFunc((void*)mod_i64_i64, "mod_i64_i64"); g.funcs.mod_i64_i64 = getFunc((void*)mod_i64_i64, "mod_i64_i64");
......
...@@ -43,7 +43,8 @@ struct GlobalFuncs { ...@@ -43,7 +43,8 @@ struct GlobalFuncs {
llvm::Value* callattr0, *callattr1, *callattr2, *callattr3, *callattr; llvm::Value* callattr0, *callattr1, *callattr2, *callattr3, *callattr;
llvm::Value* reoptCompiledFunc, *compilePartialFunc; llvm::Value* reoptCompiledFunc, *compilePartialFunc;
llvm::Value* __cxa_begin_catch, *__cxa_end_catch, *__cxa_allocate_exception, *__cxa_throw; llvm::Value* __cxa_begin_catch, *__cxa_end_catch;
llvm::Value* raise1;
llvm::Value* div_i64_i64, *mod_i64_i64, *pow_i64_i64; llvm::Value* div_i64_i64, *mod_i64_i64, *pow_i64_i64;
llvm::Value* div_float_float, *mod_float_float, *pow_float_float; llvm::Value* div_float_float, *mod_float_float, *pow_float_float;
......
...@@ -1413,6 +1413,9 @@ public: ...@@ -1413,6 +1413,9 @@ public:
remapped->arg2 = remapExpr(node->arg2); remapped->arg2 = remapExpr(node->arg2);
push_back(remapped); push_back(remapped);
if (!curblock)
return true;
curblock->push_back(new AST_Unreachable()); curblock->push_back(new AST_Unreachable());
curblock = NULL; curblock = NULL;
......
...@@ -90,6 +90,8 @@ void force() { ...@@ -90,6 +90,8 @@ void force() {
FORCE(runtimeCall); FORCE(runtimeCall);
FORCE(callattr); FORCE(callattr);
FORCE(raise1);
FORCE(div_i64_i64); FORCE(div_i64_i64);
FORCE(mod_i64_i64); FORCE(mod_i64_i64);
FORCE(pow_i64_i64); FORCE(pow_i64_i64);
......
...@@ -28,7 +28,13 @@ class BoxedInt; ...@@ -28,7 +28,13 @@ class BoxedInt;
class BoxedList; class BoxedList;
class BoxedString; class BoxedString;
void raiseExc(Box*) __attribute__((__noreturn__)); // "raw" raising function that will engage the unwinding machinery
void raiseRaw(Box*) __attribute__((__noreturn__));
// user-level raise function that implements some python-level semantics
extern "C" void raise1(Box*) __attribute__((__noreturn__));
extern "C" void raise2(Box*, Box*) __attribute__((__noreturn__));
extern "C" void raise3(Box*, Box*, Box*) __attribute__((__noreturn__));
// helper function for raising from the runtime:
void raiseExcHelper(BoxedClass*, const char* fmt, ...) __attribute__((__noreturn__)); void raiseExcHelper(BoxedClass*, const char* fmt, ...) __attribute__((__noreturn__));
extern "C" const std::string* getTypeName(Box* o); extern "C" const std::string* getTypeName(Box* o);
......
...@@ -99,7 +99,7 @@ void unwindExc(Box* exc_obj) { ...@@ -99,7 +99,7 @@ void unwindExc(Box* exc_obj) {
abort(); abort();
} }
void raiseExc(Box* exc_obj) { void raiseRaw(Box* exc_obj) {
// Using libgcc: // Using libgcc:
throw exc_obj; throw exc_obj;
...@@ -183,6 +183,23 @@ static std::vector<const LineInfo*> getTracebackEntries() { ...@@ -183,6 +183,23 @@ static std::vector<const LineInfo*> getTracebackEntries() {
return entries; return entries;
} }
void raise1(Box* b) {
if (b->cls == type_cls) {
BoxedClass* c = static_cast<BoxedClass*>(b);
if (isSubclass(c, Exception)) {
auto exc_obj = exceptionNew1(c);
raiseRaw(exc_obj);
} else {
raiseExcHelper(TypeError, "exceptions must be old-style classes or derived from BaseException, not %s",
getTypeName(b)->c_str());
}
}
// TODO: should only allow throwing of old-style classes or things derived
// from BaseException:
raiseRaw(b);
}
void raiseExcHelper(BoxedClass* cls, const char* msg, ...) { void raiseExcHelper(BoxedClass* cls, const char* msg, ...) {
auto entries = getTracebackEntries(); auto entries = getTracebackEntries();
last_tb = std::move(entries); last_tb = std::move(entries);
...@@ -203,10 +220,10 @@ void raiseExcHelper(BoxedClass* cls, const char* msg, ...) { ...@@ -203,10 +220,10 @@ void raiseExcHelper(BoxedClass* cls, const char* msg, ...) {
BoxedString* message = boxStrConstant(buf); BoxedString* message = boxStrConstant(buf);
Box* exc_obj = exceptionNew2(cls, message); Box* exc_obj = exceptionNew2(cls, message);
raiseExc(exc_obj); raiseRaw(exc_obj);
} else { } else {
Box* exc_obj = exceptionNew1(cls); Box* exc_obj = exceptionNew1(cls);
raiseExc(exc_obj); raiseRaw(exc_obj);
} }
} }
...@@ -223,6 +240,8 @@ std::string formatException(Box* b) { ...@@ -223,6 +240,8 @@ std::string formatException(Box* b) {
assert(r->cls == str_cls); assert(r->cls == str_cls);
const std::string* msg = &r->s; const std::string* msg = &r->s;
if (msg->size())
return *name + ": " + *msg; return *name + ": " + *msg;
return *name;
} }
} }
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