Bug fix, make sure to initialize exception object (to rethrow) even

when there are no @catch blocks.

Also, eliminated unneeded alloca for the rethrow object.

Also, avoid generating code to rethrow exception if the exception will
trivially always be caught.

llvm-svn: 56751
This commit is contained in:
Daniel Dunbar 2008-09-27 07:03:52 +00:00
parent da04d7f4ec
commit b22ff59750
1 changed files with 38 additions and 38 deletions

View File

@ -1422,19 +1422,17 @@ void CGObjCMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
// Emit the "exception in @try" block. // Emit the "exception in @try" block.
CGF.EmitBlock(ExceptionInTryBlock); CGF.EmitBlock(ExceptionInTryBlock);
if (const ObjCAtCatchStmt* CatchStmt = S.getCatchStmts()) { // Retrieve the exception object. We may emit multiple blocks but
// Allocate memory for the caught exception and extract it from the // nothing can cross this so the value is already in SSA form.
// exception data. llvm::Value *Caught = CGF.Builder.CreateCall(ObjCTypes.ExceptionExtractFn,
llvm::Value *CaughtPtr = CGF.CreateTempAlloca(ObjCTypes.ObjectPtrTy); ExceptionData,
llvm::Value *Extract = CGF.Builder.CreateCall(ObjCTypes.ExceptionExtractFn, "caught");
ExceptionData); if (const ObjCAtCatchStmt* CatchStmt = S.getCatchStmts()) {
CGF.Builder.CreateStore(Extract, CaughtPtr); // Enter a new exception try block (in case a @catch block throws
// an exception).
// Enter a new exception try block
// (in case a @catch block throws an exception).
CGF.Builder.CreateCall(ObjCTypes.ExceptionTryEnterFn, ExceptionData); CGF.Builder.CreateCall(ObjCTypes.ExceptionTryEnterFn, ExceptionData);
llvm::Value *SetJmpResult = CGF.Builder.CreateCall(ObjCTypes.SetJmpFn, llvm::Value *SetJmpResult = CGF.Builder.CreateCall(ObjCTypes.SetJmpFn,
JmpBufPtr, "result"); JmpBufPtr, "result");
@ -1450,29 +1448,31 @@ void CGObjCMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
CGF.EmitBlock(CatchBlock); CGF.EmitBlock(CatchBlock);
// Handle catch list // Handle catch list. As a special case we check if everything is
// matched and avoid generating code for falling off the end if
// so.
bool AllMatched = false;
for (; CatchStmt; CatchStmt = CatchStmt->getNextCatchStmt()) { for (; CatchStmt; CatchStmt = CatchStmt->getNextCatchStmt()) {
llvm::BasicBlock *NextCatchBlock = llvm::BasicBlock::Create("nextcatch"); llvm::BasicBlock *NextCatchBlock = llvm::BasicBlock::Create("nextcatch");
llvm::Value *Caught = CGF.Builder.CreateLoad(CaughtPtr, "caught");
QualType T; QualType T;
bool MatchesAll = false;
const DeclStmt *CatchParam = const DeclStmt *CatchParam =
cast_or_null<DeclStmt>(CatchStmt->getCatchParamStmt()); cast_or_null<DeclStmt>(CatchStmt->getCatchParamStmt());
const ValueDecl *VD = 0;
// catch(...) always matches. // catch(...) always matches.
if (!CatchParam) if (!CatchParam) {
MatchesAll = true; AllMatched = true;
else { } else {
QualType PT = cast<ValueDecl>(CatchParam->getDecl())->getType(); VD = cast<ValueDecl>(CatchParam->getDecl());
T = PT->getAsPointerType()->getPointeeType();
// catch(id e) always matches. // catch(id e) always matches.
if (CGF.getContext().isObjCIdType(T)) const PointerType *PT = VD->getType()->getAsPointerType();
MatchesAll = true; if (PT && CGF.getContext().isObjCIdType(PT->getPointeeType()))
AllMatched = true;
} }
if (MatchesAll) { if (AllMatched) {
if (CatchParam) { if (CatchParam) {
CGF.EmitStmt(CatchParam); CGF.EmitStmt(CatchParam);
@ -1485,7 +1485,6 @@ void CGObjCMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
CGF.EmitStmt(CatchStmt->getCatchBody()); CGF.EmitStmt(CatchStmt->getCatchBody());
CGF.Builder.CreateBr(FinallyBlock); CGF.Builder.CreateBr(FinallyBlock);
CGF.EmitBlock(NextCatchBlock);
break; break;
} }
@ -1523,20 +1522,21 @@ void CGObjCMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
CGF.EmitBlock(NextCatchBlock); CGF.EmitBlock(NextCatchBlock);
} }
// None of the handlers caught the exception, so store it and rethrow if (!AllMatched) {
// it later. // None of the handlers caught the exception, so store it to be
llvm::Value *Caught = CGF.Builder.CreateLoad(CaughtPtr, "caught"); // rethrown at the end of the @finally block.
CGF.Builder.CreateStore(Caught, RethrowPtr);
CGF.Builder.CreateCall(ObjCTypes.ExceptionTryExitFn, ExceptionData);
CGF.Builder.CreateBr(FinallyBlock);
}
// Emit the exception handler for the @catch blocks.
CGF.EmitBlock(ExceptionInCatchBlock);
CGF.Builder.CreateStore(CGF.Builder.CreateCall(ObjCTypes.ExceptionExtractFn,
ExceptionData),
RethrowPtr);
} else {
CGF.Builder.CreateStore(Caught, RethrowPtr); CGF.Builder.CreateStore(Caught, RethrowPtr);
CGF.Builder.CreateCall(ObjCTypes.ExceptionTryExitFn,
ExceptionData);
CGF.Builder.CreateBr(FinallyBlock);
CGF.EmitBlock(ExceptionInCatchBlock);
Extract = CGF.Builder.CreateCall(ObjCTypes.ExceptionExtractFn,
ExceptionData);
CGF.Builder.CreateStore(Extract, RethrowPtr);
} }
// Emit the @finally block. // Emit the @finally block.