summaryrefslogtreecommitdiffstats
path: root/examples/ExceptionDemo/ExceptionDemo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'examples/ExceptionDemo/ExceptionDemo.cpp')
-rw-r--r--examples/ExceptionDemo/ExceptionDemo.cpp301
1 files changed, 186 insertions, 115 deletions
diff --git a/examples/ExceptionDemo/ExceptionDemo.cpp b/examples/ExceptionDemo/ExceptionDemo.cpp
index e5d9451..20516a7 100644
--- a/examples/ExceptionDemo/ExceptionDemo.cpp
+++ b/examples/ExceptionDemo/ExceptionDemo.cpp
@@ -40,7 +40,8 @@
//
// Cases -1 and 7 are caught by a C++ test harness where the validity of
// of a C++ catch(...) clause catching a generated exception with a
-// type info type of 7 is questionable.
+// type info type of 7 is explained by: example in rules 1.6.4 in
+// http://sourcery.mentor.com/public/cxx-abi/abi-eh.html (v1.22)
//
// This code uses code from the llvm compiler-rt project and the llvm
// Kaleidoscope project.
@@ -56,11 +57,16 @@
#include "llvm/Intrinsics.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Target/TargetData.h"
-#include "llvm/Target/TargetSelect.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Support/IRBuilder.h"
#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/TargetSelect.h"
+
+#ifdef OLD_EXC_SYSTEM
+// See use of UpgradeExceptionHandling(...) below
+#include "llvm/AutoUpgrade.h"
+#endif
// FIXME: Although all systems tested with (Linux, OS X), do not need this
// header file included. A user on ubuntu reported, undefined symbols
@@ -81,7 +87,7 @@
#endif
// System C++ ABI unwind types from:
-// http://refspecs.freestandards.org/abi-eh-1.21.html
+// http://sourcery.mentor.com/public/cxx-abi/abi-eh.html (v1.22)
extern "C" {
@@ -182,6 +188,9 @@ static std::vector<std::string> ourTypeInfoNames;
static std::map<int, std::string> ourTypeInfoNamesIndex;
static llvm::StructType *ourTypeInfoType;
+#ifndef OLD_EXC_SYSTEM
+static llvm::StructType *ourCaughtResultType;
+#endif
static llvm::StructType *ourExceptionType;
static llvm::StructType *ourUnwindExceptionType;
@@ -209,7 +218,7 @@ typedef std::vector<llvm::Type*> ArgTypes;
/// @param isVarArg function uses vararg arguments
/// @returns function instance
llvm::Function *createFunction(llvm::Module &module,
- const llvm::Type *retType,
+ llvm::Type *retType,
const ArgTypes &theArgTypes,
const ArgNames &theArgNames,
const std::string &functName,
@@ -246,7 +255,7 @@ llvm::Function *createFunction(llvm::Module &module,
/// @returns AllocaInst instance
static llvm::AllocaInst *createEntryBlockAlloca(llvm::Function &function,
const std::string &varName,
- const llvm::Type *type,
+ llvm::Type *type,
llvm::Constant *initWith = 0) {
llvm::BasicBlock &block = function.getEntryBlock();
llvm::IRBuilder<> tmp(&block, block.begin());
@@ -893,9 +902,8 @@ void generateStringPrint(llvm::LLVMContext &context,
builder.CreateStore(stringConstant, stringVar);
}
- llvm::Value *cast =
- builder.CreatePointerCast(stringVar,
- builder.getInt8PtrTy());
+ llvm::Value *cast = builder.CreatePointerCast(stringVar,
+ builder.getInt8PtrTy());
builder.CreateCall(printFunct, cast);
}
@@ -937,9 +945,8 @@ void generateIntegerPrint(llvm::LLVMContext &context,
builder.CreateStore(stringConstant, stringVar);
}
- llvm::Value *cast =
- builder.CreateBitCast(stringVar,
- builder.getInt8PtrTy());
+ llvm::Value *cast = builder.CreateBitCast(stringVar,
+ builder.getInt8PtrTy());
builder.CreateCall2(&printFunct, &toPrint, cast);
}
@@ -962,6 +969,9 @@ void generateIntegerPrint(llvm::LLVMContext &context,
/// @param unwindResumeBlock unwind resume block
/// @param exceptionCaughtFlag reference exception caught/thrown status storage
/// @param exceptionStorage reference to exception pointer storage
+#ifndef OLD_EXC_SYSTEM
+/// @param caughtResultStorage reference to landingpad result storage
+#endif
/// @returns newly created block
static llvm::BasicBlock *createFinallyBlock(llvm::LLVMContext &context,
llvm::Module &module,
@@ -972,28 +982,42 @@ static llvm::BasicBlock *createFinallyBlock(llvm::LLVMContext &context,
llvm::BasicBlock &terminatorBlock,
llvm::BasicBlock &unwindResumeBlock,
llvm::Value **exceptionCaughtFlag,
- llvm::Value **exceptionStorage) {
+ llvm::Value **exceptionStorage
+#ifndef OLD_EXC_SYSTEM
+ ,llvm::Value **caughtResultStorage
+#endif
+ ) {
assert(exceptionCaughtFlag &&
"ExceptionDemo::createFinallyBlock(...):exceptionCaughtFlag "
"is NULL");
assert(exceptionStorage &&
"ExceptionDemo::createFinallyBlock(...):exceptionStorage "
"is NULL");
+
+#ifndef OLD_EXC_SYSTEM
+ assert(caughtResultStorage &&
+ "ExceptionDemo::createFinallyBlock(...):caughtResultStorage "
+ "is NULL");
+#endif
- *exceptionCaughtFlag =
- createEntryBlockAlloca(toAddTo,
- "exceptionCaught",
- ourExceptionNotThrownState->getType(),
- ourExceptionNotThrownState);
-
- const llvm::PointerType *exceptionStorageType =
- builder.getInt8PtrTy();
- *exceptionStorage =
- createEntryBlockAlloca(toAddTo,
- "exceptionStorage",
- exceptionStorageType,
- llvm::ConstantPointerNull::get(
- exceptionStorageType));
+ *exceptionCaughtFlag = createEntryBlockAlloca(toAddTo,
+ "exceptionCaught",
+ ourExceptionNotThrownState->getType(),
+ ourExceptionNotThrownState);
+
+ llvm::PointerType *exceptionStorageType = builder.getInt8PtrTy();
+ *exceptionStorage = createEntryBlockAlloca(toAddTo,
+ "exceptionStorage",
+ exceptionStorageType,
+ llvm::ConstantPointerNull::get(
+ exceptionStorageType));
+#ifndef OLD_EXC_SYSTEM
+ *caughtResultStorage = createEntryBlockAlloca(toAddTo,
+ "caughtResultStorage",
+ ourCaughtResultType,
+ llvm::ConstantAggregateZero::get(
+ ourCaughtResultType));
+#endif
llvm::BasicBlock *ret = llvm::BasicBlock::Create(context,
blockName,
@@ -1010,10 +1034,10 @@ static llvm::BasicBlock *createFinallyBlock(llvm::LLVMContext &context,
bufferToPrint.str(),
USE_GLOBAL_STR_CONSTS);
- llvm::SwitchInst *theSwitch =
- builder.CreateSwitch(builder.CreateLoad(*exceptionCaughtFlag),
- &terminatorBlock,
- 2);
+ llvm::SwitchInst *theSwitch = builder.CreateSwitch(builder.CreateLoad(
+ *exceptionCaughtFlag),
+ &terminatorBlock,
+ 2);
theSwitch->addCase(ourExceptionCaughtState, &terminatorBlock);
theSwitch->addCase(ourExceptionThrownState, &unwindResumeBlock);
@@ -1121,29 +1145,35 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
"normal",
ret);
// Unwind block for invoke
- llvm::BasicBlock *exceptionBlock =
- llvm::BasicBlock::Create(context, "exception", ret);
+ llvm::BasicBlock *exceptionBlock = llvm::BasicBlock::Create(context,
+ "exception",
+ ret);
// Block which routes exception to correct catch handler block
- llvm::BasicBlock *exceptionRouteBlock =
- llvm::BasicBlock::Create(context, "exceptionRoute", ret);
+ llvm::BasicBlock *exceptionRouteBlock = llvm::BasicBlock::Create(context,
+ "exceptionRoute",
+ ret);
// Foreign exception handler
- llvm::BasicBlock *externalExceptionBlock =
- llvm::BasicBlock::Create(context, "externalException", ret);
+ llvm::BasicBlock *externalExceptionBlock = llvm::BasicBlock::Create(context,
+ "externalException",
+ ret);
// Block which calls _Unwind_Resume
- llvm::BasicBlock *unwindResumeBlock =
- llvm::BasicBlock::Create(context, "unwindResume", ret);
+ llvm::BasicBlock *unwindResumeBlock = llvm::BasicBlock::Create(context,
+ "unwindResume",
+ ret);
// Clean up block which delete exception if needed
- llvm::BasicBlock *endBlock =
- llvm::BasicBlock::Create(context, "end", ret);
+ llvm::BasicBlock *endBlock = llvm::BasicBlock::Create(context, "end", ret);
std::string nextName;
std::vector<llvm::BasicBlock*> catchBlocks(numExceptionsToCatch);
llvm::Value *exceptionCaughtFlag = NULL;
llvm::Value *exceptionStorage = NULL;
+#ifndef OLD_EXC_SYSTEM
+ llvm::Value *caughtResultStorage = NULL;
+#endif
// Finally block which will branch to unwindResumeBlock if
// exception is not caught. Initializes/allocates stack locations.
@@ -1156,7 +1186,11 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
*endBlock,
*unwindResumeBlock,
&exceptionCaughtFlag,
- &exceptionStorage);
+ &exceptionStorage
+#ifndef OLD_EXC_SYSTEM
+ ,&caughtResultStorage
+#endif
+ );
for (unsigned i = 0; i < numExceptionsToCatch; ++i) {
nextName = ourTypeInfoNames[exceptionTypesToCatch[i]];
@@ -1181,8 +1215,7 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
builder.CreateInvoke(&toInvoke,
normalBlock,
exceptionBlock,
- args.begin(),
- args.end());
+ args);
// End Block
@@ -1193,8 +1226,7 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
builder,
"Gen: In end block: exiting in " + ourId + ".\n",
USE_GLOBAL_STR_CONSTS);
- llvm::Function *deleteOurException =
- module.getFunction("deleteOurException");
+ llvm::Function *deleteOurException = module.getFunction("deleteOurException");
// Note: function handles NULL exceptions
builder.CreateCall(deleteOurException,
@@ -1218,28 +1250,57 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
builder.SetInsertPoint(unwindResumeBlock);
- llvm::Function *resumeOurException =
- module.getFunction("_Unwind_Resume");
+
+#ifndef OLD_EXC_SYSTEM
+ builder.CreateResume(builder.CreateLoad(caughtResultStorage));
+#else
+ llvm::Function *resumeOurException = module.getFunction("_Unwind_Resume");
builder.CreateCall(resumeOurException,
builder.CreateLoad(exceptionStorage));
builder.CreateUnreachable();
+#endif
// Exception Block
builder.SetInsertPoint(exceptionBlock);
- llvm::Function *ehException = module.getFunction("llvm.eh.exception");
+ llvm::Function *personality = module.getFunction("ourPersonality");
+#ifndef OLD_EXC_SYSTEM
+ llvm::LandingPadInst *caughtResult =
+ builder.CreateLandingPad(ourCaughtResultType,
+ personality,
+ numExceptionsToCatch,
+ "landingPad");
+
+ caughtResult->setCleanup(true);
+
+ for (unsigned i = 0; i < numExceptionsToCatch; ++i) {
+ // Set up type infos to be caught
+ caughtResult->addClause(module.getGlobalVariable(
+ ourTypeInfoNames[exceptionTypesToCatch[i]]));
+ }
+
+ llvm::Value *unwindException = builder.CreateExtractValue(caughtResult, 0);
+ llvm::Value *retTypeInfoIndex = builder.CreateExtractValue(caughtResult, 1);
+
+ // FIXME: Redundant storage which, beyond utilizing value of
+ // caughtResultStore for unwindException storage, may be alleviated
+ // alltogether with a block rearrangement
+ builder.CreateStore(caughtResult, caughtResultStorage);
+ builder.CreateStore(unwindException, exceptionStorage);
+ builder.CreateStore(ourExceptionThrownState, exceptionCaughtFlag);
+#else
+ llvm::Function *ehException = module.getFunction("llvm.eh.exception");
+
// Retrieve thrown exception
llvm::Value *unwindException = builder.CreateCall(ehException);
// Store exception and flag
builder.CreateStore(unwindException, exceptionStorage);
builder.CreateStore(ourExceptionThrownState, exceptionCaughtFlag);
- llvm::Function *personality = module.getFunction("ourPersonality");
- llvm::Value *functPtr =
- builder.CreatePointerCast(personality,
- builder.getInt8PtrTy());
+ llvm::Value *functPtr = builder.CreatePointerCast(personality,
+ builder.getInt8PtrTy());
args.clear();
args.push_back(unwindException);
@@ -1263,9 +1324,8 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
// handles this call. This landing pad (this exception block), will be
// called either because it nees to cleanup (call finally) or a type
// info was found which matched the thrown exception.
- llvm::Value *retTypeInfoIndex = builder.CreateCall(ehSelector,
- args.begin(),
- args.end());
+ llvm::Value *retTypeInfoIndex = builder.CreateCall(ehSelector, args);
+#endif
// Retrieve exception_class member from thrown exception
// (_Unwind_Exception instance). This member tells us whether or not
@@ -1305,10 +1365,10 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
// (OurException instance).
//
// Note: ourBaseFromUnwindOffset is usually negative
- llvm::Value *typeInfoThrown =
- builder.CreatePointerCast(builder.CreateConstGEP1_64(unwindException,
+ llvm::Value *typeInfoThrown = builder.CreatePointerCast(
+ builder.CreateConstGEP1_64(unwindException,
ourBaseFromUnwindOffset),
- ourExceptionType->getPointerTo());
+ ourExceptionType->getPointerTo());
// Retrieve thrown exception type info type
//
@@ -1331,10 +1391,9 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
USE_GLOBAL_STR_CONSTS);
// Route to matched type info catch block or run cleanup finally block
- llvm::SwitchInst *switchToCatchBlock =
- builder.CreateSwitch(retTypeInfoIndex,
- finallyBlock,
- numExceptionsToCatch);
+ llvm::SwitchInst *switchToCatchBlock = builder.CreateSwitch(retTypeInfoIndex,
+ finallyBlock,
+ numExceptionsToCatch);
unsigned nextTypeToCatch;
@@ -1344,6 +1403,12 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
llvm::Type::getInt32Ty(context), i),
catchBlocks[nextTypeToCatch]);
}
+
+#ifdef OLD_EXC_SYSTEM
+ // Must be run before verifier
+ UpgradeExceptionHandling(&module);
+#endif
+
llvm::verifyFunction(*ret);
fpm.run(*ret);
@@ -1395,15 +1460,13 @@ llvm::Function *createThrowExceptionFunction(llvm::Module &module,
"entry",
ret);
// Throws a foreign exception
- llvm::BasicBlock *nativeThrowBlock =
- llvm::BasicBlock::Create(context,
- "nativeThrow",
- ret);
+ llvm::BasicBlock *nativeThrowBlock = llvm::BasicBlock::Create(context,
+ "nativeThrow",
+ ret);
// Throws one of our Exceptions
- llvm::BasicBlock *generatedThrowBlock =
- llvm::BasicBlock::Create(context,
- "generatedThrow",
- ret);
+ llvm::BasicBlock *generatedThrowBlock = llvm::BasicBlock::Create(context,
+ "generatedThrow",
+ ret);
// Retrieved runtime type info type to throw
llvm::Value *exceptionType = namedValues["exceptTypeToThrow"];
@@ -1445,15 +1508,13 @@ llvm::Function *createThrowExceptionFunction(llvm::Module &module,
builder.SetInsertPoint(generatedThrowBlock);
- llvm::Function *createOurException =
- module.getFunction("createOurException");
- llvm::Function *raiseOurException =
- module.getFunction("_Unwind_RaiseException");
+ llvm::Function *createOurException = module.getFunction("createOurException");
+ llvm::Function *raiseOurException = module.getFunction(
+ "_Unwind_RaiseException");
// Creates exception to throw with runtime type info type.
- llvm::Value *exception =
- builder.CreateCall(createOurException,
- namedValues["exceptTypeToThrow"]);
+ llvm::Value *exception = builder.CreateCall(createOurException,
+ namedValues["exceptTypeToThrow"]);
// Throw generated Exception
builder.CreateCall(raiseOurException, exception);
@@ -1501,32 +1562,29 @@ llvm::Function *createUnwindExceptionTest(llvm::Module &module,
createStandardUtilityFunctions(numTypeInfos,
module,
builder);
- llvm::Function *nativeThrowFunct =
- module.getFunction(nativeThrowFunctName);
+ llvm::Function *nativeThrowFunct = module.getFunction(nativeThrowFunctName);
// Create exception throw function using the value ~0 to cause
// foreign exceptions to be thrown.
- llvm::Function *throwFunct =
- createThrowExceptionFunction(module,
- builder,
- fpm,
- "throwFunct",
- ~0,
- *nativeThrowFunct);
+ llvm::Function *throwFunct = createThrowExceptionFunction(module,
+ builder,
+ fpm,
+ "throwFunct",
+ ~0,
+ *nativeThrowFunct);
// Inner function will catch even type infos
unsigned innerExceptionTypesToCatch[] = {6, 2, 4};
size_t numExceptionTypesToCatch = sizeof(innerExceptionTypesToCatch) /
- sizeof(unsigned);
+ sizeof(unsigned);
// Generate inner function.
- llvm::Function *innerCatchFunct =
- createCatchWrappedInvokeFunction(module,
- builder,
- fpm,
- *throwFunct,
- "innerCatchFunct",
- numExceptionTypesToCatch,
- innerExceptionTypesToCatch);
+ llvm::Function *innerCatchFunct = createCatchWrappedInvokeFunction(module,
+ builder,
+ fpm,
+ *throwFunct,
+ "innerCatchFunct",
+ numExceptionTypesToCatch,
+ innerExceptionTypesToCatch);
// Outer function will catch odd type infos
unsigned outerExceptionTypesToCatch[] = {3, 1, 5};
@@ -1534,14 +1592,13 @@ llvm::Function *createUnwindExceptionTest(llvm::Module &module,
sizeof(unsigned);
// Generate outer function
- llvm::Function *outerCatchFunct =
- createCatchWrappedInvokeFunction(module,
- builder,
- fpm,
- *innerCatchFunct,
- "outerCatchFunct",
- numExceptionTypesToCatch,
- outerExceptionTypesToCatch);
+ llvm::Function *outerCatchFunct = createCatchWrappedInvokeFunction(module,
+ builder,
+ fpm,
+ *innerCatchFunct,
+ "outerCatchFunct",
+ numExceptionTypesToCatch,
+ outerExceptionTypesToCatch);
// Return outer function to run
return(outerCatchFunct);
@@ -1607,12 +1664,12 @@ void runExceptionThrow(llvm::ExecutionEngine *engine,
exc.what());
}
catch (...) {
- // Catch all exceptions including our generated ones. I'm not sure
- // why this latter functionality should work, as it seems that
- // our exceptions should be foreign to C++ (the _Unwind_Exception::
- // exception_class should be different from the one used by C++), and
- // therefore C++ should ignore the generated exceptions.
-
+ // Catch all exceptions including our generated ones. This latter
+ // functionality works according to the example in rules 1.6.4 of
+ // http://sourcery.mentor.com/public/cxx-abi/abi-eh.html (v1.22),
+ // given that these will be exceptions foreign to C++
+ // (the _Unwind_Exception::exception_class should be different from
+ // the one used by C++).
fprintf(stderr,
"\nrunExceptionThrow(...):In C++ catch all.\n");
}
@@ -1640,17 +1697,31 @@ static void createStandardUtilityFunctions(unsigned numTypeInfos,
// Setup exception catch state
ourExceptionNotThrownState =
- llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 0),
+ llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 0),
ourExceptionThrownState =
- llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 1),
+ llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 1),
ourExceptionCaughtState =
- llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 2),
+ llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 2),
// Create our type info type
ourTypeInfoType = llvm::StructType::get(context,
- TypeArray(builder.getInt32Ty()));
+ TypeArray(builder.getInt32Ty()));
+
+#ifndef OLD_EXC_SYSTEM
+
+ llvm::Type *caughtResultFieldTypes[] = {
+ builder.getInt8PtrTy(),
+ builder.getInt32Ty()
+ };
+
+ // Create our landingpad result type
+ ourCaughtResultType = llvm::StructType::get(context,
+ TypeArray(caughtResultFieldTypes));
+
+#endif
+
// Create OurException type
ourExceptionType = llvm::StructType::get(context,
TypeArray(ourTypeInfoType));
@@ -1667,7 +1738,7 @@ static void createStandardUtilityFunctions(unsigned numTypeInfos,
// Calculate offset of OurException::unwindException member.
ourBaseFromUnwindOffset = ((uintptr_t) &dummyException) -
- ((uintptr_t) &(dummyException.unwindException));
+ ((uintptr_t) &(dummyException.unwindException));
#ifdef DEBUG
fprintf(stderr,
@@ -1724,7 +1795,7 @@ static void createStandardUtilityFunctions(unsigned numTypeInfos,
// print32Int
- const llvm::Type *retType = builder.getVoidTy();
+ llvm::Type *retType = builder.getVoidTy();
argTypes.clear();
argTypes.push_back(builder.getInt32Ty());
OpenPOWER on IntegriCloud