[llvm-commits] [llvm-gcc-4.2] r79251 - in /llvm-gcc-4.2/trunk/gcc: llvm-convert.cpp llvm-internal.h
Jim Grosbach
grosbach at apple.com
Mon Aug 17 09:50:09 PDT 2009
Author: grosbach
Date: Mon Aug 17 11:50:09 2009
New Revision: 79251
URL: http://llvm.org/viewvc/llvm-project?rev=79251&view=rev
Log:
Move the sjlj exception handling conversions to a back-end pass where they
more properly belong. This allows removing the front-end conditionalized
SJLJ code, and cleans up the generated IR considerably. All of the
infrastructure code (calling _Unwind_SjLj_Register/Unregister, etc) is
added by the SjLjEHPrepare pass.
Modified:
llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
llvm-gcc-4.2/trunk/gcc/llvm-internal.h
Modified: llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp?rev=79251&r1=79250&r2=79251&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp Mon Aug 17 11:50:09 2009
@@ -158,7 +158,7 @@
TD(getTargetData()), Builder(Context, *TheFolder) {
FnDecl = fndecl;
Fn = 0;
- ReturnBB = UnwindBB = DispatchBB = 0;
+ ReturnBB = UnwindBB = 0;
ReturnOffset = 0;
if (TheDebugInfo) {
@@ -635,114 +635,14 @@
EmitAutomaticVariableDecl(TREE_VALUE(t));
}
- // Register the frame with the unwind machinery if there are exception
- // handling regions in the function.
- if (USING_SJLJ_EXCEPTIONS && current_function_has_exception_handlers()) {
- // We have exception regions, but we may or may not actually end up
- // needing to actively do anything about it. We'll know at the end
- // of the function by whether any landing pads have been created.
- // So for now, we just create a block for where to add the necessary
- // bits.
- SjLjEHSetupBB = BasicBlock::Create(Context, "setup_sjlj_eh");
- Builder.CreateBr(SjLjEHSetupBB);
- PostEntryBB = BasicBlock::Create(Context, "post_entry");
- EmitBlock(PostEntryBB);
- }
-
// Create a new block for the return node, but don't insert it yet.
ReturnBB = BasicBlock::Create(Context, "return");
}
Function *TreeToLLVM::FinishFunctionBody() {
- // If we're using SJLJ exceptions and there are any landing pads for this
- // function, we need to insert the setup code in the prologue, and add
- // the unregister call here.
- if (USING_SJLJ_EXCEPTIONS && current_function_has_exception_handlers()) {
- // Send the current BB to the return block just like it would if we
- // weren't doing this bit.
- Builder.CreateBr(ReturnBB);
-
- assert(SjLjEHSetupBB && "Exception handling needed but no setup block??");
- EmitBlock(SjLjEHSetupBB);
-
- if (LandingPads.size() > 0) {
- // Get a pointer to the function context
- llvm::Value *Idxs[2];
- Idxs[0] = ConstantInt::get(Type::getInt32Ty(Context), 0);
-
- // Assign the unwind personality function address
- Idxs[1] = ConstantInt::get(Type::getInt32Ty(Context), 3);
- Value *FieldPtr = Builder.CreateGEP (FunctionContext.Ptr, Idxs, Idxs+2,
- "personality_gep");
- const Type *FieldTy =
- cast<PointerType>(FieldPtr->getType())->getElementType();
- Value *Val =
- Builder.CreateBitCast(DECL_LLVM(llvm_eh_personality_libfunc), FieldTy);
- Builder.CreateStore(Val, FieldPtr);
-
- // Load the address for the language specific data area (LSDA)
- Idxs[1] = ConstantInt::get(Type::getInt32Ty(Context), 4);
- FieldPtr
- = Builder.CreateGEP (FunctionContext.Ptr, Idxs, Idxs+2, "lsda_gep");
- FieldTy = cast<PointerType>(FieldPtr->getType())->getElementType();
- Val =
- Builder.CreateCall(Intrinsic::getDeclaration(TheModule,
- Intrinsic::eh_sjlj_lsda),
- "eh_lsda");
- Builder.CreateStore(Val, FieldPtr);
-
- // builtin_setjmp() stuff goes here.
- // 1. Save the frame pointer.
- Idxs[1] = ConstantInt::get(Type::getInt32Ty(Context), 5);
- FieldPtr
- = Builder.CreateGEP (FunctionContext.Ptr, Idxs, Idxs+2, "jbuf_gep");
- Idxs[1] = ConstantInt::get(Type::getInt32Ty(Context), 0);
- Value *ElemPtr
- = Builder.CreateGEP (FieldPtr, Idxs, Idxs+2, "jbuf_fp_gep");
- FieldTy = cast<PointerType>(ElemPtr->getType())->getElementType();
- // FIXME: The EmitBuiltinExtractReturnAddr() function comes close to
- // what we want here. Refactor it so that it does, or make a common
- // helper function.
- Val = Builder.CreateCall
- (Intrinsic::getDeclaration(TheModule, Intrinsic::frameaddress),
- ConstantInt::get(Type::getInt32Ty(Context), 0));
- Val = BitCastToType(Val, FieldTy);
- Builder.CreateStore(Val, ElemPtr);
-
- FieldPtr =
- BitCastToType(FieldPtr, Type::getInt8Ty(Context)->getPointerTo());
- Value *DispatchVal = Builder.CreateCall
- (Intrinsic::getDeclaration(TheModule, Intrinsic::eh_sjlj_setjmp),
- FieldPtr);
- // check the return value of the setjmp. non-zero goes to dispatcher
- Value *Zero = ConstantInt::get(Type::getInt32Ty(Context), 0);
- Value *Compare = Builder.CreateICmpEQ(DispatchVal, Zero);
-
- // Branch on the compare.
- DispatchBB = BasicBlock::Create(Context, "dispatch");
- BasicBlock *PostSetupBB = BasicBlock::Create(Context, "sjlj_eh_register");
- Builder.CreateCondBr(Compare, PostSetupBB, DispatchBB);
- EmitBlock(PostSetupBB);
-
- // Register the context and note that this call cannot throw
- CallInst *RegisterCall =
- Builder.CreateCall(DECL_LLVM(llvm_unwind_sjlj_register_libfunc),
- FunctionContext.Ptr);
- }
- // Go back to the end of the prologue
- Builder.CreateBr(PostEntryBB);
- }
-
// Insert the return block at the end of the function.
EmitBlock(ReturnBB);
- if (USING_SJLJ_EXCEPTIONS && LandingPads.size() > 0) {
- // Un-register the frame with the unwind machinery if there are exception
- // handling regions in the function.
- Builder.CreateCall(DECL_LLVM(llvm_unwind_sjlj_unregister_libfunc),
- FunctionContext.Ptr);
- }
-
SmallVector <Value *, 4> RetVals;
// If the function returns a value, get it into a register and return it now.
@@ -802,22 +702,15 @@
Builder.CreateAggregateRet(RetVals.data(), RetVals.size());
// Emit pending exception handling code.
- if (USING_SJLJ_EXCEPTIONS) {
- EmitSjLjLandingPads();
- EmitPostPads();
- EmitSjLjDispatcher();
- EmitUnwindBlock();
- } else {
- EmitLandingPads();
- EmitPostPads();
- EmitUnwindBlock();
- }
+ EmitLandingPads();
+ EmitPostPads();
+ EmitUnwindBlock();
// If this function takes the address of a label, emit the indirect goto
// block.
if (IndirectGotoBlock) {
EmitBlock(IndirectGotoBlock);
-
+
// Change the default destination to go to one of the other destinations, if
// there is any other dest.
SwitchInst *SI = cast<SwitchInst>(IndirectGotoBlock->getTerminator());
@@ -2018,9 +1911,6 @@
(IntPtr == Type::getInt32Ty(Context) ?
Intrinsic::eh_typeid_for_i32 :
Intrinsic::eh_typeid_for_i64));
- // For SJLJ, create a function context on the stack
- if (USING_SJLJ_EXCEPTIONS)
- FunctionContext = CreateTempLoc (ConvertType(sjlj_fc_type_node));
}
/// getPostPad - Return the post landing pad for the given exception handling
@@ -2041,158 +1931,6 @@
((std::vector<struct eh_region *> *)data)->push_back(region);
}
-/// EmitSjLjDispatcher - Emit SJLJ EH dispatcher
-void TreeToLLVM::EmitSjLjDispatcher () {
- if (DispatchBB) {
- assert(LandingPads.size() > 0 && "Dispatch block without landing pads?");
-
- EmitBlock(DispatchBB);
-
- // Get the call_site value
- llvm::Value *Idxs[2];
- Idxs[0] = ConstantInt::get(llvm::Type::getInt32Ty(Context), 0);
- Idxs[1] = ConstantInt::get(llvm::Type::getInt32Ty(Context), 1);
- Value *FieldPtr = Builder.CreateGEP (FunctionContext.Ptr, Idxs, Idxs+2,
- "call_site_gep");
- Value *CallSite = Builder.CreateLoad(FieldPtr, "call_site");
-
- // Figure out which landing pad to go to via the call_site
- // FIXME: would this be better as a switch? Probably.
- unsigned FirstPad = 0;
- for (unsigned region = 1 ; region < LandingPads.size() ; ++region) {
- if (LandingPads[region]) {
- if (!FirstPad) FirstPad = region;
- Value *RegionNo = ConstantInt::get(llvm::Type::getInt32Ty(Context), region - 1);
- Value *Compare = Builder.CreateICmpEQ(CallSite, RegionNo);
- // Branch on the compare.
- BasicBlock *NextDispatch = BasicBlock::Create(Context, "dispatch");
- Builder.CreateCondBr(Compare, LandingPads[region], NextDispatch);
- EmitBlock(NextDispatch);
- }
- }
- assert(FirstPad && "EH dispatcher, but no landing pads present!");
- Builder.CreateBr(LandingPads[FirstPad]);
- }
-}
-
-
-/// EmitSjLjLandingPads - Emit EH landing pads.
-void TreeToLLVM::EmitSjLjLandingPads() {
- std::vector<Value*> Args;
- std::vector<struct eh_region *> Handlers;
-
- for (unsigned i = 1; i < LandingPads.size(); ++i) {
- BasicBlock *LandingPad = LandingPads[i];
-
- if (!LandingPad)
- continue;
-
- CreateExceptionValues();
- EmitBlock(LandingPad);
-
- // Get the exception value from the function context
- llvm::Value *Idxs[2];
- Idxs[0] = ConstantInt::get(llvm::Type::getInt32Ty(Context), 0);
- Idxs[1] = ConstantInt::get(llvm::Type::getInt32Ty(Context), 2);
- Value *FCDataPtr
- = Builder.CreateGEP (FunctionContext.Ptr, Idxs, Idxs+2, "fc_data_gep");
- Idxs[1] = ConstantInt::get(llvm::Type::getInt32Ty(Context), 0);
- Value *ElemPtr
- = Builder.CreateGEP (FCDataPtr, Idxs, Idxs+2, "exception_gep");
- Value *Ex = Builder.CreateLoad (ElemPtr);
- const Type *ExceptionValueTy =
- cast<PointerType>(ExceptionValue->getType())->getElementType();
- Ex = CastToAnyType(Ex, false, ExceptionValueTy, false);
- Builder.CreateStore(Ex, ExceptionValue);
-
-
- // The exception and the personality function.
- Args.push_back(Builder.CreateLoad(ExceptionValue, "eh_ptr"));
- assert(llvm_eh_personality_libfunc
- && "no exception handling personality function!");
- Args.push_back(BitCastToType(DECL_LLVM(llvm_eh_personality_libfunc),
- PointerType::getUnqual(Type::getInt8Ty(Context))));
- // Add selections for each handler.
- foreach_reachable_handler(i, false, AddHandler, &Handlers);
-
- for (std::vector<struct eh_region *>::iterator I = Handlers.begin(),
- E = Handlers.end(); I != E; ++I) {
- struct eh_region *region = *I;
-
- // Create a post landing pad for the handler.
- getPostPad(get_eh_region_number(region));
- int RegionKind = classify_eh_handler(region);
- if (RegionKind < 0) {
- // Filter - note the length.
- tree TypeList = get_eh_type_list(region);
- unsigned Length = list_length(TypeList);
- Args.reserve(Args.size() + Length + 1);
- Args.push_back(ConstantInt::get(Type::getInt32Ty(Context), Length + 1));
-
- // Add the type infos.
- for (; TypeList; TypeList = TREE_CHAIN(TypeList)) {
- tree TType = lookup_type_for_runtime(TREE_VALUE(TypeList));
- Args.push_back(Emit(TType, 0));
- }
- } else if (RegionKind > 0) {
- // Catch.
- tree TypeList = get_eh_type_list(region);
-
- if (!TypeList) {
- // Catch-all - push a null pointer.
- Args.push_back(Constant::getNullValue(
- PointerType::getUnqual(Type::getInt8Ty(Context))));
- } else {
- // Add the type infos.
- for (; TypeList; TypeList = TREE_CHAIN(TypeList)) {
- tree TType = lookup_type_for_runtime(TREE_VALUE(TypeList));
- Args.push_back(Emit(TType, 0));
- }
- }
- }
- }
- if (can_throw_external_1(i, false)) {
- // Some exceptions from this region may not be caught by any handler.
- // Since invokes are required to branch to the unwind label no matter
- // what exception is being unwound, append a catch-all.
-
- // The representation of a catch-all is language specific.
- Value *Catch_All;
- // SJLJ exception runtime handles "all cleanups" just fine, unlike
- // DWARF.
- if (USING_SJLJ_EXCEPTIONS || !lang_eh_catch_all) {
- // Use a "cleanup" - this should be good enough for most languages.
- Catch_All = ConstantInt::get(Type::getInt32Ty(Context), 0);
- } else {
- tree catch_all_type = lang_eh_catch_all();
- if (catch_all_type == NULL_TREE)
- // Use a C++ style null catch-all object.
- Catch_All =
- Constant::getNullValue(PointerType::getUnqual(Type::getInt8Ty(Context)));
- else
- // This language has a type that catches all others.
- Catch_All = Emit(catch_all_type, 0);
- }
- Args.push_back(Catch_All);
- }
- // Emit the selector call.
- Builder.CreateCall(FuncEHSelector, Args.begin(), Args.end(),
- "eh_select");
- // Fetch and store the exception selector.
- Idxs[1] = ConstantInt::get(llvm::Type::getInt32Ty(Context), 1);
- ElemPtr = Builder.CreateGEP (FCDataPtr, Idxs, Idxs+2, "handler_gep");
- Value *Select = Builder.CreateLoad (ElemPtr);
- Builder.CreateStore(Select, ExceptionSelectorValue);
- // Branch to the post landing pad for the first reachable handler.
- assert(!Handlers.empty() && "Landing pad but no handler?");
- Builder.CreateBr(getPostPad(get_eh_region_number(*Handlers.begin())));
-
- Handlers.clear();
- Args.clear();
- }
-}
-
-
/// EmitLandingPads - Emit EH landing pads.
void TreeToLLVM::EmitLandingPads() {
std::vector<Value*> Args;
@@ -2270,7 +2008,7 @@
// The representation of a catch-all is language specific.
Value *CatchAll;
- if (!lang_eh_catch_all) {
+ if (USING_SJLJ_EXCEPTIONS || !lang_eh_catch_all) {
// Use a "cleanup" - this should be good enough for most languages.
CatchAll = ConstantInt::get(Type::getInt32Ty(Context), 0);
} else {
@@ -2418,17 +2156,6 @@
if (UnwindBB) {
CreateExceptionValues();
EmitBlock(UnwindBB);
- if (USING_SJLJ_EXCEPTIONS) {
- // Mark the call_site as -1 since we're signalling to continue
- // the unwind now.
- llvm::Value *Idxs[2];
- Idxs[0] = ConstantInt::get(llvm::Type::getInt32Ty(Context), 0);
- Idxs[1] = ConstantInt::get(llvm::Type::getInt32Ty(Context), 1);
- Value *FieldPtr = Builder.CreateGEP (FunctionContext.Ptr, Idxs, Idxs+2,
- "call_site_gep");
- const Type *FieldTy = cast<PointerType>(FieldPtr->getType())->getElementType();
- Builder.CreateStore(ConstantInt::get(FieldTy, (uint64_t)-1, true), FieldPtr);
- }
// Fetch and store exception handler.
Value *Arg = Builder.CreateLoad(ExceptionValue, "eh_ptr");
assert(llvm_unwind_resume_libfunc && "no unwind resume function!");
@@ -2935,25 +2662,6 @@
ThisPad = BasicBlock::Create(Context, "lpad");
LandingPad = ThisPad;
-
- if (USING_SJLJ_EXCEPTIONS) {
- CreateExceptionValues();
- // Mark the call site so we'll dispatch to the right landing pad
- // when we get an exception passed back.
- llvm::Value *Idxs[2];
- Idxs[0] = ConstantInt::get(llvm::Type::getInt32Ty(Context), 0);
- Idxs[1] = ConstantInt::get(llvm::Type::getInt32Ty(Context), 1);
- Value *FieldPtr = Builder.CreateGEP (FunctionContext.Ptr,
- Idxs, Idxs+2, "call_site_gep");
- const Type *FieldTy =
- cast<PointerType>(FieldPtr->getType())->getElementType();
- Constant *CallSiteIdx = ConstantInt::get(FieldTy, RegionNo, true);
- Builder.CreateStore(CallSiteIdx, FieldPtr);
- // Tell the back end what the call-site value is
- Builder.CreateCall
- (Intrinsic::getDeclaration(TheModule, Intrinsic::eh_sjlj_callsite),
- CallSiteIdx);
- }
} else {
assert(can_throw_external_1(RegionNo, false) &&
"Must-not-throw region handled by runtime?");
Modified: llvm-gcc-4.2/trunk/gcc/llvm-internal.h
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-internal.h?rev=79251&r1=79250&r2=79251&view=diff
==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-internal.h (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-internal.h Mon Aug 17 11:50:09 2009
@@ -296,13 +296,9 @@
const TargetData &TD;
tree_node *FnDecl;
Function *Fn;
- BasicBlock *SjLjEHSetupBB;
- BasicBlock *PostEntryBB;
BasicBlock *ReturnBB;
BasicBlock *UnwindBB;
- BasicBlock *DispatchBB;
unsigned ReturnOffset;
- MemRef FunctionContext; // For SJLJ exception handling
// State that changes as the function is emitted.
More information about the llvm-commits
mailing list