[llvm-commits] [124438] EH support.
jlaskey at apple.com
jlaskey at apple.com
Thu Mar 1 15:11:14 PST 2007
Revision: 124438
Author: jlaskey
Date: 2007-03-01 15:11:13 -0800 (Thu, 01 Mar 2007)
Log Message:
-----------
EH support.
Modified Paths:
--------------
apple-local/branches/llvm/gcc/llvm-convert.cpp
apple-local/branches/llvm/gcc/llvm-internal.h
Modified: apple-local/branches/llvm/gcc/llvm-convert.cpp
===================================================================
--- apple-local/branches/llvm/gcc/llvm-convert.cpp 2007-03-01 10:54:52 UTC (rev 124437)
+++ apple-local/branches/llvm/gcc/llvm-convert.cpp 2007-03-01 23:11:13 UTC (rev 124438)
@@ -58,10 +58,13 @@
#include "flags.h"
#include "target.h"
#include "hard-reg-set.h"
+#include "except.h"
extern bool tree_could_throw_p(tree); // tree-flow.h uses non-C++ C constructs.
extern int get_pointer_alignment (tree exp, unsigned int max_align);
}
+#define ITANIUM_STYLE_EXCEPTIONS
+
//===----------------------------------------------------------------------===//
// Matching LLVM Values with GCC DECL trees
//===----------------------------------------------------------------------===//
@@ -261,6 +264,16 @@
}
AllocaInsertionPoint = 0;
+
+ ExceptionValue = 0;
+ ExceptionSelectorValue = 0;
+ FuncEHException = 0;
+ FuncEHSelector = 0;
+ FuncEHFilter = 0;
+ FuncEHGetTypeID = 0;
+ FuncCPPPersonality = 0;
+ FuncUnwindResume = 0;
+
NumAddressTakenBlocks = 0;
IndirectGotoBlock = 0;
CurrentEHScopes.reserve(16);
@@ -596,7 +609,19 @@
// If this function has exceptions, emit the lazily created unwind block.
if (UnwindBB) {
EmitBlock(UnwindBB);
+#ifdef ITANIUM_STYLE_EXCEPTIONS
+ if (ExceptionValue) {
+ // Fetch and store exception handler.
+ std::vector<Value*> Args;
+ Args.push_back(new LoadInst(ExceptionValue, "eh_ptr", CurBB));
+ new CallInst(FuncUnwindResume,
+ &Args[0], Args.size(), "",
+ CurBB);
+ new UnreachableInst(CurBB);
+ }
+#else
new UnwindInst(UnwindBB);
+#endif
}
// If this function takes the address of a label, emit the indirect goto
@@ -640,15 +665,8 @@
std::cerr << "Unhandled expression!\n";
debug_tree(exp);
abort();
- case EH_FILTER_EXPR:
- case CATCH_EXPR: {
- static bool PrintedWarning = false;
- if (!PrintedWarning) std::cerr << "WARNING: EH not supported yet!\n";
- PrintedWarning = true;
- return 0;
- }
- // Basic lists and binding scopes
+ // Basic lists and binding scopes
case BIND_EXPR: Result = EmitBIND_EXPR(exp, DestLoc); break;
case STATEMENT_LIST: Result = EmitSTATEMENT_LIST(exp, DestLoc); break;
@@ -660,6 +678,9 @@
case SWITCH_EXPR: Result = EmitSWITCH_EXPR(exp); break;
case TRY_FINALLY_EXPR:
case TRY_CATCH_EXPR: Result = EmitTRY_EXPR(exp); break;
+ case EXC_PTR_EXPR: Result = EmitEXC_PTR_EXPR(exp); break;
+ case CATCH_EXPR: Result = EmitCATCH_EXPR(exp); break;
+ case EH_FILTER_EXPR: Result = EmitEH_FILTER_EXPR(exp); break;
// Expressions
case VAR_DECL:
@@ -1737,6 +1758,132 @@
walk_tree_without_duplicates(&code, StripLLVMTranslationFn, 0);
}
+
+/// GatherTypeInfo - Walk through the expression gathering all the
+/// typeinfos that are used.
+void TreeToLLVM::GatherTypeInfo(tree exp,
+ std::vector<Value *> &TypeInfos) {
+ if (TREE_CODE(exp) == CATCH_EXPR || TREE_CODE(exp) == EH_FILTER_EXPR) {
+ tree Types = TREE_CODE(exp) == CATCH_EXPR ? CATCH_TYPES(exp)
+ : EH_FILTER_TYPES(exp);
+
+ if (!Types) {
+ // Catch all.
+ TypeInfos.push_back(Constant::getNullValue(Type::Int32Ty));
+ } else if (TREE_CODE(Types) != TREE_LIST) {
+ // Construct typeinfo object. Each call will produce a new expression
+ // even if duplicate.
+ tree TypeInfoNopExpr = (*lang_eh_runtime_type)(Types);
+ // Produce value. Duplicate typeinfo get folded here.
+ Value *TypeInfo = Emit(TypeInfoNopExpr, 0);
+ // Capture typeinfo.
+ TypeInfos.push_back(TypeInfo);
+ } else {
+ for (; Types; Types = TREE_CHAIN (Types)) {
+ // Construct typeinfo object. Each call will produce a new expression
+ // even if duplicate.
+ tree TypeInfoNopExpr = (*lang_eh_runtime_type)(TREE_VALUE(Types));
+ // Produce value. Duplicate typeinfo get folded here.
+ Value *TypeInfo = Emit(TypeInfoNopExpr, 0);
+ // Capture typeinfo.
+ TypeInfos.push_back(TypeInfo);
+ }
+ }
+ } else {
+ assert(TREE_CODE(exp) == STATEMENT_LIST && "Need an exp with typeinfo");
+ // Each statement in the statement list will be a catch.
+ for (tree_stmt_iterator I = tsi_start(exp); !tsi_end_p(I); tsi_next(&I))
+ GatherTypeInfo(tsi_stmt(I), TypeInfos);
+ }
+}
+
+
+/// AddLandingPad - Insert code to fetch and save the exception and exception
+/// selector.
+void TreeToLLVM::AddLandingPad() {
+ tree TryCatch = 0;
+ for (std::vector<EHScope>::reverse_iterator I = CurrentEHScopes.rbegin(),
+ E = CurrentEHScopes.rend();
+ I != E; ++I) {
+ if (TREE_CODE(I->TryExpr) == TRY_CATCH_EXPR) {
+ TryCatch = I->TryExpr;
+ break;
+ }
+ }
+
+ if (!TryCatch) return;
+
+ // Gather the typeinfo.
+ std::vector<Value *> TypeInfos;
+ tree Catches = TREE_OPERAND(TryCatch, 1);
+ GatherTypeInfo(Catches, TypeInfos);
+
+ CreateExceptionValues();
+
+ // Choose type of landing pad type.
+ Function *F = FuncEHSelector;
+
+ if (TREE_CODE(Catches) == STATEMENT_LIST &&
+ !tsi_end_p(tsi_start(Catches)) &&
+ TREE_CODE(tsi_stmt(tsi_start(Catches))) == EH_FILTER_EXPR) {
+ F = FuncEHFilter;
+ }
+
+ // Fetch and store the exception.
+ Value *Ex = new CallInst(FuncEHException, "eh_ptr", CurBB);
+ new StoreInst(Ex, ExceptionValue, CurBB);
+
+ // Fetch and store exception handler.
+ std::vector<Value*> Args;
+ Args.push_back(new LoadInst(ExceptionValue, "eh_ptr", CurBB));
+ Args.push_back(CastToType(Instruction::BitCast, FuncCPPPersonality,
+ PointerType::get(Type::Int8Ty)));
+ for (unsigned i = 0, N = TypeInfos.size(); i < N; ++i)
+ Args.push_back(TypeInfos[i]);
+ Value *Select = new CallInst(F, &Args[0], Args.size(), "eh_select", CurBB);
+ new StoreInst(Select, ExceptionSelectorValue, CurBB);
+}
+
+
+/// CreateExceptionValues - Create values used internally by exception handling.
+///
+void TreeToLLVM::CreateExceptionValues() {
+ // Check to see if the exception values have been constructed.
+ if (ExceptionValue) return;
+
+ ExceptionValue = CreateTemporary(PointerType::get(Type::Int8Ty));
+ ExceptionValue->setName("eh_exception");
+
+ ExceptionSelectorValue = CreateTemporary(Type::Int32Ty);
+ ExceptionSelectorValue->setName("eh_selector");
+
+ FuncEHException = Intrinsic::getDeclaration(TheModule,
+ Intrinsic::eh_exception);
+ FuncEHSelector = Intrinsic::getDeclaration(TheModule,
+ Intrinsic::eh_selector);
+ FuncEHFilter = Intrinsic::getDeclaration(TheModule,
+ Intrinsic::eh_filter);
+ FuncEHGetTypeID = Intrinsic::getDeclaration(TheModule,
+ Intrinsic::eh_typeid_for);
+
+ FuncCPPPersonality = cast<Function>(
+ TheModule->getOrInsertFunction("__gxx_personality_v0",
+ Type::getPrimitiveType(Type::VoidTyID),
+ NULL));
+ FuncCPPPersonality->setLinkage(Function::ExternalLinkage);
+ FuncCPPPersonality->setCallingConv(CallingConv::C);
+
+ FuncUnwindResume = cast<Function>(
+ TheModule->getOrInsertFunction("_Unwind_Resume",
+ Type::getPrimitiveType(Type::VoidTyID),
+ PointerType::get(Type::Int8Ty),
+ NULL));
+ FuncUnwindResume->setLinkage(Function::ExternalLinkage);
+ FuncUnwindResume->setCallingConv(CallingConv::C);
+
+}
+
+
/// EmitTRY_EXPR - Handle TRY_FINALLY_EXPR and TRY_CATCH_EXPR.
Value *TreeToLLVM::EmitTRY_EXPR(tree exp) {
// The C++ front-end produces a lot of TRY_FINALLY_EXPR nodes that have empty
@@ -1847,32 +1994,40 @@
// Add a basic block to emit the code into.
BasicBlock *CleanupBB = new BasicBlock("cleanup");
EmitBlock(CleanupBB);
-
+
+ // Provide exit point for cleanup code.
+ FinallyStack.push_back(FinallyBlock);
+
// Emit the code.
Emit(CleanupCode, 0);
+ // Clear exit point for cleanup code.
+ FinallyStack.pop_back();
+
// Because we can emit the same cleanup in more than one context, we must
// strip off LLVM information from the decls in the code. Otherwise, the
// we will try to insert the same label into multiple places in the code.
StripLLVMTranslation(CleanupCode);
+
- // Because we can emit the same cleanup in more than one context, we must
- // strip off LLVM information from the decls in the code. Otherwise, the
- // we will try to insert the same label into multiple places in the code.
- //StripLLVMTranslation(CleanupCode);
+ // Catches will supply own terminator.
+ if (!CurBB->getTerminator()) {
+ // Emit a branch to the new target.
+ BranchInst *BI = new BranchInst(FixupBr->getSuccessor(0), CurBB);
- // Emit a branch to the new target.
- BranchInst *BI = new BranchInst(FixupBr->getSuccessor(0), CurBB);
+ // The old branch now goes to the cleanup block.
+ FixupBr->setSuccessor(0, CleanupBB);
- // The old branch now goes to the cleanup block.
- FixupBr->setSuccessor(0, CleanupBB);
-
- // Fixup this new branch now.
- FixupBr = BI;
-
- // Add the fixup to the next cleanup scope if there is one.
- if (!CurrentEHScopes.empty())
- AddBranchFixup(FixupBr, FixupIsExceptionEdge);
+ // Fixup this new branch now.
+ FixupBr = BI;
+
+ // Add the fixup to the next cleanup scope if there is one.
+ if (!CurrentEHScopes.empty())
+ AddBranchFixup(FixupBr, FixupIsExceptionEdge);
+ } else {
+ // The old branch now goes to the cleanup block.
+ FixupBr->setSuccessor(0, CleanupBB);
+ }
}
// Move the finally block to the end of the function so we can continue
@@ -1895,6 +2050,138 @@
}
+/// EmitCATCH_EXPR - Handle CATCH_EXPR.
+///
+Value *TreeToLLVM::EmitCATCH_EXPR(tree exp) {
+#ifndef ITANIUM_STYLE_EXCEPTIONS
+ return 0;
+#endif
+
+ // Make sure we have all the exception values in place.
+ CreateExceptionValues();
+
+ // Break out parts of catch.
+ tree Types = CATCH_TYPES(exp);
+ tree Body = CATCH_BODY(exp);
+
+ // Destinations of the catch entry conditions.
+ BasicBlock *ThenBlock = 0;
+ BasicBlock *ElseBlock = 0;
+
+ // FiXME - Determine last case so we don't need to emit test.
+ if (!Types) {
+ // Catch all - no testing required.
+ } else if (TREE_CODE(Types) != TREE_LIST) {
+ // Construct typeinfo object. Each call will produce a new expression
+ // even if duplicate.
+ tree TypeInfoNopExpr = (*lang_eh_runtime_type)(Types);
+ // Produce value. Duplicate typeinfo get folded here.
+ Value *TypeInfo = Emit(TypeInfoNopExpr, 0);
+
+ // Call get eh type id.
+ std::vector<Value*> Args;
+ Args.push_back(TypeInfo);
+ Value *TypeID = new CallInst(cast<Value>(FuncEHGetTypeID),
+ &Args[0], Args.size(), "eh_typeid", CurBB);
+ Value *Select = new LoadInst(ExceptionSelectorValue, "tmp", CurBB);
+
+ // Compare with the exception selector.
+ Value *Compare =
+ new ICmpInst(ICmpInst::ICMP_EQ, Select, TypeID, "tmp", CurBB);
+ ThenBlock = new BasicBlock("eh_then");
+ ElseBlock = new BasicBlock("eh_else");
+
+ // Branch on the compare.
+ new BranchInst(ThenBlock, ElseBlock, Compare, CurBB);
+ } else {
+ ThenBlock = new BasicBlock("eh_then");
+
+ for (; Types; Types = TREE_CHAIN (Types)) {
+ if (ElseBlock) EmitBlock(ElseBlock);
+
+ // Construct typeinfo object. Each call will produce a new expression
+ // even if duplicate.
+ tree TypeInfoNopExpr = (*lang_eh_runtime_type)(TREE_VALUE(Types));
+ // Produce value. Duplicate typeinfo get folded here.
+ Value *TypeInfo = Emit(TypeInfoNopExpr, 0);
+
+ // Call get eh type id.
+ std::vector<Value*> Args;
+ Args.push_back(TypeInfo);
+ Value *TypeID = new CallInst(cast<Value>(FuncEHGetTypeID),
+ &Args[0], Args.size(), "eh_typeid", CurBB);
+ Value *Select = new LoadInst(ExceptionSelectorValue, "tmp", CurBB);
+
+ // Compare with the exception selector.
+ Value *Compare =
+ new ICmpInst(ICmpInst::ICMP_EQ, Select, TypeID, "tmp", CurBB);
+ ElseBlock = new BasicBlock("eh_else");
+
+ // Branch on the compare.
+ new BranchInst(ThenBlock, ElseBlock, Compare, CurBB);
+ }
+ }
+
+ // Start the then block.
+ if (ThenBlock) EmitBlock(ThenBlock);
+
+ // Emit the body.
+ Emit(Body, 0);
+
+ // Branch to the try exit.
+ assert(!FinallyStack.empty() && "Need an exit point");
+ if (!CurBB->getTerminator())
+ new BranchInst(FinallyStack.back(), CurBB);
+
+ // Start the else block.
+ if (ElseBlock) EmitBlock(ElseBlock);
+
+ return 0;
+}
+
+/// EmitEXC_PTR_EXPR - Handle EXC_PTR_EXPR.
+///
+Value *TreeToLLVM::EmitEXC_PTR_EXPR(tree exp) {
+#ifndef ITANIUM_STYLE_EXCEPTIONS
+ return 0;
+#endif
+
+ // Load exception address.
+ CreateExceptionValues();
+ return new LoadInst(ExceptionValue, "eh_value", CurBB);
+}
+
+/// EmitEH_FILTER_EXPR - Handle EH_FILTER_EXPR.
+///
+Value *TreeToLLVM::EmitEH_FILTER_EXPR(tree exp) {
+#ifndef ITANIUM_STYLE_EXCEPTIONS
+ return 0;
+#endif
+
+ CreateExceptionValues();
+
+ // The result of a filter landing pad will be a negative index if there is
+ // a match.
+ Value *Select = new LoadInst(ExceptionSelectorValue, "tmp", CurBB);
+
+ // Compare with the filter action value.
+ Value *Zero = ConstantInt::get(Type::Int32Ty, 0);
+ Value *Compare =
+ new ICmpInst(ICmpInst::ICMP_SLT, Select, Zero, "tmp", CurBB);
+
+ // Branch on the compare.
+ BasicBlock *FilterBB = new BasicBlock("filter");
+ BasicBlock *NoFilterBB = new BasicBlock("nofilter");
+ new BranchInst(FilterBB, NoFilterBB, Compare, CurBB);
+
+ EmitBlock(FilterBB);
+ Emit(EH_FILTER_FAILURE(exp), 0);
+
+ EmitBlock(NoFilterBB);
+
+ return 0;
+}
+
//===----------------------------------------------------------------------===//
// ... Expressions ...
//===----------------------------------------------------------------------===//
@@ -2170,13 +2457,6 @@
if (UnwindBB == 0)
UnwindBB = new BasicBlock("Unwind");
UnwindBlock = UnwindBB;
-FIXME: "Call terminate if needed!";
-#if 0
- if (ThrownExceptionsCallTerminate())
- UnwindBlock = getTerminateBlock();
- else
- UnwindBlock = getInvokeDestination();
-#endif
}
SmallVector<Value*, 16> CallOperands;
@@ -2264,10 +2544,16 @@
// branch in.
if (CurrentEHScopes.back().UnwindBlock == 0) {
EmitBlock(CurrentEHScopes.back().UnwindBlock = new BasicBlock("unwind"));
- // This branch to the unwind edge should have exception cleanups inserted
- // onto it.
+
+#ifdef ITANIUM_STYLE_EXCEPTIONS
+ // Add landing pad entry code.
+ AddLandingPad();
+#endif
+ // This branch to the unwind edge should have exception cleanups
+ // inserted onto it.
EmitBranchInternal(UnwindBlock, true);
}
+
cast<InvokeInst>(Call)->setUnwindDest(CurrentEHScopes.back().UnwindBlock);
EmitBlock(NextBlock);
Modified: apple-local/branches/llvm/gcc/llvm-internal.h
===================================================================
--- apple-local/branches/llvm/gcc/llvm-internal.h 2007-03-01 10:54:52 UTC (rev 124437)
+++ apple-local/branches/llvm/gcc/llvm-internal.h 2007-03-01 23:11:13 UTC (rev 124438)
@@ -242,6 +242,42 @@
/// this map.
std::map<BasicBlock*, unsigned> BlockEHScope;
+ /// ExceptionValue - Is the local to receive the current exception.
+ ///
+ Value *ExceptionValue;
+
+ /// ExceptionSelectorValue - Is the local to receive the current exception
+ /// selector.
+ Value *ExceptionSelectorValue;
+
+ /// FuncEHException - Function used to receive the exception.
+ ///
+ Function *FuncEHException;
+
+ /// FuncEHSelector - Function used to receive the exception selector.
+ ///
+ Function *FuncEHSelector;
+
+ /// FuncEHFilter - Function used to handle the exception filtering.
+ ///
+ Function *FuncEHFilter;
+
+ /// FuncEHGetTypeID - Function used to return type id for give typeinfo.
+ ///
+ Function *FuncEHGetTypeID;
+
+ /// FuncCPPPersonality - Function handling c++ personality.
+ ///
+ Function *FuncCPPPersonality;
+
+ /// FuncUnwindResume - Function used to continue exception unwinding.
+ ///
+ Function *FuncUnwindResume;
+
+ /// FinallyStack - Stack for nested try exit points.
+ ///
+ std::vector<BasicBlock *> FinallyStack;
+
/// NumAddressTakenBlocks - Count the number of labels whose addresses are
/// taken.
uint64_t NumAddressTakenBlocks;
@@ -368,6 +404,18 @@
void HandleMultiplyDefinedGCCTemp(tree_node *var);
private:
+ /// GatherTypeInfo - Walk through the expression gathering all the
+ /// typeinfos that are used.
+ void GatherTypeInfo(tree_node *exp, std::vector<Value *> &TypeInfos);
+
+ /// AddLandingPad - Insert code to fetch and save the exception and exception
+ /// selector.
+ void AddLandingPad();
+
+ /// CreateExceptionValues - Create values used internally by exception handling.
+ ///
+ void CreateExceptionValues();
+
// Emit* - These are delgates from Emit, and have the same parameter
// characteristics.
@@ -382,6 +430,9 @@
Value *EmitCOND_EXPR(tree_node *exp);
Value *EmitSWITCH_EXPR(tree_node *exp);
Value *EmitTRY_EXPR(tree_node *exp);
+ Value *EmitCATCH_EXPR(tree_node *exp);
+ Value *EmitEXC_PTR_EXPR(tree_node *exp);
+ Value *EmitEH_FILTER_EXPR(tree_node *exp);
// Expressions.
void EmitINTEGER_CST_Aggregate(tree_node *exp, Value *DestLoc);
More information about the llvm-commits
mailing list