This machine mirrors various open-source projects.
20 Gbit/s uplink.
If there are any issues or you want another project mirrored, please contact
mirror-service -=AT=- netcologne DOT de !
00001 //===-- codegen/HandlerEmitter.cpp ---------------------------- -*- C++ -*-===// 00002 // 00003 // This file is distributed under the MIT license. See LICENSE.txt for details. 00004 // 00005 // Copyright (C) 2009, Stephen Wilson 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 // Mandatory args to llvm.eh.selector. 00030 args.push_back(exception); 00031 args.push_back(RT.getEHPersonality()); 00032 00033 // Push an exinfo object for each named exception choice. 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 // Always emit a catch-all. We simply resume the exception occurrence if 00045 // there isn't an actual catch-all handler present. 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 // Remove the landing pad the current set of handlers target. This is 00061 // required to ensure that any exceptions thrown in the handlers themselves 00062 // propagate. 00063 frame()->removeLandingPad(); 00064 00065 // Obtain the thrown exception object and the selection index. 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 // Catch-all's can simply branch directly to the handler body. 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 // Emit the body for this handler, then switch back to the next landing 00096 // pad. 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 // We always match a thrown exception. If there isn't a catch-all handler 00107 // explicitly associated with this sequence then the current insertion point 00108 // is set to our implicit handler. Propagate the exception. 00109 if (!seq->hasCatchAll()) 00110 RT.reraise(frame(), exception); 00111 00112 Builder.SetInsertPoint(mergeBB); 00113 } 00114 00115 00116