diff --git a/ir/irlandingpad.cpp b/ir/irlandingpad.cpp index f7dce480..73602e10 100644 --- a/ir/irlandingpad.cpp +++ b/ir/irlandingpad.cpp @@ -21,17 +21,20 @@ IRLandingPadInfo::IRLandingPadInfo(Catch* catchstmt, llvm::BasicBlock* end) catchstmt->var->ir.irLocal->value = gIR->ir->CreateBitCast(catch_var, getPtrToType(DtoType(catchstmt->var->type))); } - // emit handler - assert(catchstmt->handler); - catchstmt->handler->toIR(gIR); + // emit handler, if there is one + // handler is zero for instance for 'catch { debug foo(); }' + if(catchstmt->handler); + catchstmt->handler->toIR(gIR); if (!gIR->scopereturned()) gIR->ir->CreateBr(end); assert(catchstmt->type); - catchType = catchstmt->type->isClassHandle(); - DtoForceDeclareDsymbol(catchType); + //TODO: Is toBasetype correct here? Should catch handlers with typedefed + // classes behave differently? + catchType = catchstmt->type->toBasetype()->isClassHandle(); assert(catchType); + DtoForceDeclareDsymbol(catchType); } IRLandingPadInfo::IRLandingPadInfo(Statement* finallystmt) @@ -122,11 +125,10 @@ void IRLandingPad::constructLandingPad(llvm::BasicBlock* inBB) // if there's a finally, the eh table has to have a 0 action if(hasFinally) selectorargs.push_back(llvm::ConstantInt::get(LLType::Int32Ty, 0)); - // if there is a catch, store exception object - if(catchToInt.size()) + // if there is a catch and some catch allocated storage, store exception object + if(catchToInt.size() && catch_var) { const LLType* objectTy = DtoType(ClassDeclaration::object->type); - assert(catch_var); gIR->ir->CreateStore(gIR->ir->CreateBitCast(eh_ptr, objectTy), catch_var); } diff --git a/ir/irlandingpad.h b/ir/irlandingpad.h index b01fd33b..80608433 100644 --- a/ir/irlandingpad.h +++ b/ir/irlandingpad.h @@ -7,6 +7,8 @@ #include #include +// only to be used within IRLandingPad +// holds information about a single catch or finally struct IRLandingPadInfo { // default constructor for being able to store in a vector @@ -14,7 +16,10 @@ struct IRLandingPadInfo : target(NULL), finallyBody(NULL), catchType(NULL) {} + // constructor for catch IRLandingPadInfo(Catch* catchstmt, llvm::BasicBlock* end); + + // constructor for finally IRLandingPadInfo(Statement* finallystmt); // the target catch bb if this is a catch @@ -28,6 +33,9 @@ struct IRLandingPadInfo ClassDeclaration* catchType; }; + +// holds information about all possible catch and finally actions +// and can emit landing pads to be called from the unwind runtime struct IRLandingPad { IRLandingPad() : catch_var(NULL) {} @@ -36,7 +44,9 @@ struct IRLandingPad // and the ones on the stack. also stores it as invoke target void push(llvm::BasicBlock* inBB); + // add catch information, will be used in next call to push void addCatch(Catch* catchstmt, llvm::BasicBlock* end); + // add finally information, will be used in next call to push void addFinally(Statement* finallystmt); // pops the most recently constructed landing pad bb