00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "CodeGenRoutine.h"
00010 #include "CommaRT.h"
00011 #include "HandlerEmitter.h"
00012 #include "comma/ast/ExceptionRef.h"
00013 #include "comma/ast/Stmt.h"
00014
00015 using namespace comma;
00016
00017 HandlerEmitter::HandlerEmitter(CodeGenRoutine &CGR)
00018 : CGR(CGR), CG(CGR.getCodeGen()), RT(CG.getRuntime()) { }
00019
00020 SRFrame *HandlerEmitter::frame() { return CGR.getSRFrame(); }
00021
00022 llvm::Value *HandlerEmitter::emitSelector(llvm::Value *exception,
00023 StmtSequence *seq)
00024 {
00025 typedef StmtSequence::handler_iter handler_iter;
00026 typedef HandlerStmt::choice_iterator choice_iter;
00027 llvm::SmallVector<llvm::Value*, 8> args;
00028
00029
00030 args.push_back(exception);
00031 args.push_back(RT.getEHPersonality());
00032
00033
00034 for (handler_iter H = seq->handler_begin(); H != seq->handler_end(); ++H) {
00035 HandlerStmt *handler = *H;
00036 choice_iter C = handler->choice_begin();
00037 choice_iter E = handler->choice_end();
00038 for ( ; C != E; ++C) {
00039 ExceptionDecl *target = (*C)->getException();
00040 args.push_back(RT.registerException(target));
00041 }
00042 }
00043
00044
00045
00046 args.push_back(CG.getNullPointer(CG.getInt8PtrTy()));
00047
00048 return frame()->getIRBuilder().CreateCall(
00049 CG.getEHSelectorIntrinsic(), args.begin(), args.end());
00050 }
00051
00052 void HandlerEmitter::emitHandlers(StmtSequence *seq, llvm::BasicBlock *mergeBB)
00053 {
00054 if (mergeBB == 0)
00055 mergeBB = frame()->makeBasicBlock("landingpad.merge");
00056
00057 llvm::IRBuilder<> &Builder = frame()->getIRBuilder();
00058 llvm::BasicBlock *landingPad = frame()->getLandingPad();
00059
00060
00061
00062
00063 frame()->removeLandingPad();
00064
00065
00066 Builder.SetInsertPoint(landingPad);
00067 llvm::Value *exception = Builder.CreateCall(CG.getEHExceptionIntrinsic());
00068 llvm::Value *infoIdx = emitSelector(exception, seq);
00069 llvm::Value *eh_typeid = CG.getEHTypeidIntrinsic();
00070 llvm::BasicBlock *lpadBB = frame()->makeBasicBlock("lpad");
00071 Builder.CreateBr(lpadBB);
00072 Builder.SetInsertPoint(lpadBB);
00073
00074 for (StmtSequence::handler_iter H = seq->handler_begin();
00075 H != seq->handler_end(); ++H) {
00076 HandlerStmt *handler = *H;
00077 llvm::BasicBlock *bodyBB = frame()->makeBasicBlock("lpad.body");
00078
00079
00080 if (handler->isCatchAll())
00081 Builder.CreateBr(bodyBB);
00082 else {
00083 for (HandlerStmt::choice_iterator C = handler->choice_begin();
00084 C != handler->choice_end(); ++C) {
00085 ExceptionDecl *target = (*C)->getException();
00086 llvm::Value *exinfo = RT.registerException(target);
00087 llvm::Value *targetIdx = Builder.CreateCall(eh_typeid, exinfo);
00088 llvm::Value *pred = Builder.CreateICmpEQ(infoIdx, targetIdx);
00089 lpadBB = frame()->makeBasicBlock("lpad");
00090 Builder.CreateCondBr(pred, bodyBB, lpadBB);
00091 Builder.SetInsertPoint(lpadBB);
00092 }
00093 }
00094
00095
00096
00097 Builder.SetInsertPoint(bodyBB);
00098 for (StmtSequence::stmt_iter I = handler->stmt_begin();
00099 I != handler->stmt_end(); ++I)
00100 CGR.emitStmt(*I);
00101 if (!Builder.GetInsertBlock()->getTerminator())
00102 Builder.CreateBr(mergeBB);
00103 Builder.SetInsertPoint(lpadBB);
00104 }
00105
00106
00107
00108
00109 if (!seq->hasCatchAll())
00110 RT.reraise(frame(), exception);
00111
00112 Builder.SetInsertPoint(mergeBB);
00113 }
00114
00115
00116