//
// 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.
#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
+// for stderr, and fprintf, and the addition of this include fixed the
+// issue for them. Given that LLVM's best practices include the goal
+// of reducing the number of redundant header files included, the
+// correct solution would be to find out why these symbols are not
+// defined for the system in question, and fix the issue by finding out
+// which LLVM header file, if any, would include these symbols.
+#include <cstdio>
#include <sstream>
#include <stdexcept>
#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" {
} __attribute__((__aligned__));
struct _Unwind_Context;
- typedef struct _Unwind_Context* _Unwind_Context_t;
+ typedef struct _Unwind_Context *_Unwind_Context_t;
- extern const uint8_t* _Unwind_GetLanguageSpecificData (_Unwind_Context_t c);
+ extern const uint8_t *_Unwind_GetLanguageSpecificData (_Unwind_Context_t c);
extern uintptr_t _Unwind_GetGR (_Unwind_Context_t c, int i);
extern void _Unwind_SetGR (_Unwind_Context_t c, int i, uintptr_t n);
extern void _Unwind_SetIP (_Unwind_Context_t, uintptr_t new_value);
static std::vector<std::string> ourTypeInfoNames;
static std::map<int, std::string> ourTypeInfoNamesIndex;
-static llvm::StructType* ourTypeInfoType;
-static llvm::StructType* ourExceptionType;
-static llvm::StructType* ourUnwindExceptionType;
+static llvm::StructType *ourTypeInfoType;
+#ifndef OLD_EXC_SYSTEM
+static llvm::StructType *ourCaughtResultType;
+#endif
+static llvm::StructType *ourExceptionType;
+static llvm::StructType *ourUnwindExceptionType;
-static llvm::ConstantInt* ourExceptionNotThrownState;
-static llvm::ConstantInt* ourExceptionThrownState;
-static llvm::ConstantInt* ourExceptionCaughtState;
+static llvm::ConstantInt *ourExceptionNotThrownState;
+static llvm::ConstantInt *ourExceptionThrownState;
+static llvm::ConstantInt *ourExceptionCaughtState;
typedef std::vector<std::string> ArgNames;
-typedef std::vector<const llvm::Type*> ArgTypes;
+typedef std::vector<llvm::Type*> ArgTypes;
//
// Code Generation Utilities
/// @param declarationOnly for function declarations
/// @param isVarArg function uses vararg arguments
/// @returns function instance
-llvm::Function *createFunction(llvm::Module& module,
- const llvm::Type* retType,
- const ArgTypes& theArgTypes,
- const ArgNames& theArgNames,
- const std::string& functName,
+llvm::Function *createFunction(llvm::Module &module,
+ llvm::Type *retType,
+ const ArgTypes &theArgTypes,
+ const ArgNames &theArgNames,
+ const std::string &functName,
llvm::GlobalValue::LinkageTypes linkage,
bool declarationOnly,
bool isVarArg) {
/// @param type stack variable type
/// @param initWith optional constant initialization value
/// @returns AllocaInst instance
-static llvm::AllocaInst *createEntryBlockAlloca(llvm::Function& function,
+static llvm::AllocaInst *createEntryBlockAlloca(llvm::Function &function,
const std::string &varName,
- const llvm::Type* type,
- llvm::Constant* initWith = 0) {
- llvm::BasicBlock& block = function.getEntryBlock();
+ llvm::Type *type,
+ llvm::Constant *initWith = 0) {
+ llvm::BasicBlock &block = function.getEntryBlock();
llvm::IRBuilder<> tmp(&block, block.begin());
- llvm::AllocaInst* ret = tmp.CreateAlloca(type, 0, varName.c_str());
+ llvm::AllocaInst *ret = tmp.CreateAlloca(type, 0, varName.c_str());
if (initWith)
tmp.CreateStore(initWith, ret);
/// Prints a 32 bit number, according to the format, to stderr.
/// @param intToPrint integer to print
/// @param format printf like format to use when printing
-void print32Int(int intToPrint, const char* format) {
+void print32Int(int intToPrint, const char *format) {
if (format) {
// Note: No NULL check
fprintf(stderr, format, intToPrint);
/// Prints a 64 bit number, according to the format, to stderr.
/// @param intToPrint integer to print
/// @param format printf like format to use when printing
-void print64Int(long int intToPrint, const char* format) {
+void print64Int(long int intToPrint, const char *format) {
if (format) {
// Note: No NULL check
fprintf(stderr, format, intToPrint);
/// Prints a C string to stderr
/// @param toPrint string to print
-void printStr(char* toPrint) {
+void printStr(char *toPrint) {
if (toPrint) {
fprintf(stderr, "%s", toPrint);
}
/// is calculated from the supplied OurBaseException_t::unwindException
/// member address. Handles (ignores), NULL pointers.
/// @param expToDelete exception to delete
-void deleteOurException(OurUnwindException* expToDelete) {
+void deleteOurException(OurUnwindException *expToDelete) {
#ifdef DEBUG
fprintf(stderr,
"deleteOurException(...).\n");
/// @unlink
/// @param expToDelete exception instance to delete
void deleteFromUnwindOurException(_Unwind_Reason_Code reason,
- OurUnwindException* expToDelete) {
+ OurUnwindException *expToDelete) {
#ifdef DEBUG
fprintf(stderr,
"deleteFromUnwindOurException(...).\n");
/// Creates (allocates on the heap), an exception (OurException instance),
/// of the supplied type info type.
/// @param type type info type
-OurUnwindException* createOurException(int type) {
+OurUnwindException *createOurException(int type) {
size_t size = sizeof(OurException);
- OurException* ret = (OurException*) memset(malloc(size), 0, size);
+ OurException *ret = (OurException*) memset(malloc(size), 0, size);
(ret->type).type = type;
(ret->unwindException).exception_class = ourBaseExceptionClass;
(ret->unwindException).exception_cleanup = deleteFromUnwindOurException;
/// @link http://dwarfstd.org/Dwarf3.pdf @unlink
/// @param data reference variable holding memory pointer to decode from
/// @returns decoded value
-static uintptr_t readULEB128(const uint8_t** data) {
+static uintptr_t readULEB128(const uint8_t **data) {
uintptr_t result = 0;
uintptr_t shift = 0;
unsigned char byte;
- const uint8_t* p = *data;
+ const uint8_t *p = *data;
do {
byte = *p++;
/// @link http://dwarfstd.org/Dwarf3.pdf @unlink
/// @param data reference variable holding memory pointer to decode from
/// @returns decoded value
-static uintptr_t readSLEB128(const uint8_t** data) {
+static uintptr_t readSLEB128(const uint8_t **data) {
uintptr_t result = 0;
uintptr_t shift = 0;
unsigned char byte;
- const uint8_t* p = *data;
+ const uint8_t *p = *data;
do {
byte = *p++;
/// @param data reference variable holding memory pointer to decode from
/// @param encoding dwarf encoding type
/// @returns decoded value
-static uintptr_t readEncodedPointer(const uint8_t** data, uint8_t encoding) {
+static uintptr_t readEncodedPointer(const uint8_t **data, uint8_t encoding) {
uintptr_t result = 0;
- const uint8_t* p = *data;
+ const uint8_t *p = *data;
if (encoding == llvm::dwarf::DW_EH_PE_omit)
return(result);
(exceptionClass != ourBaseExceptionClass))
return(ret);
- struct OurBaseException_t* excp = (struct OurBaseException_t*)
+ struct OurBaseException_t *excp = (struct OurBaseException_t*)
(((char*) exceptionObject) + ourBaseFromUnwindOffset);
struct OurExceptionType_t *excpType = &(excp->type);
int type = excpType->type;
/// @param context unwind system context
/// @returns minimally supported unwinding control indicator
static _Unwind_Reason_Code handleLsda(int version,
- const uint8_t* lsda,
+ const uint8_t *lsda,
_Unwind_Action actions,
uint64_t exceptionClass,
- struct _Unwind_Exception* exceptionObject,
+ struct _Unwind_Exception *exceptionObject,
_Unwind_Context_t context) {
_Unwind_Reason_Code ret = _URC_CONTINUE_UNWIND;
// emitted dwarf code)
uintptr_t funcStart = _Unwind_GetRegionStart(context);
uintptr_t pcOffset = pc - funcStart;
- struct OurExceptionType_t** classInfo = NULL;
+ struct OurExceptionType_t **classInfo = NULL;
// Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding
// dwarf emission
uint8_t callSiteEncoding = *lsda++;
uint32_t callSiteTableLength = readULEB128(&lsda);
- const uint8_t* callSiteTableStart = lsda;
- const uint8_t* callSiteTableEnd = callSiteTableStart +
+ const uint8_t *callSiteTableStart = lsda;
+ const uint8_t *callSiteTableEnd = callSiteTableStart +
callSiteTableLength;
- const uint8_t* actionTableStart = callSiteTableEnd;
- const uint8_t* callSitePtr = callSiteTableStart;
+ const uint8_t *actionTableStart = callSiteTableEnd;
+ const uint8_t *callSitePtr = callSiteTableStart;
bool foreignException = false;
int64_t actionValue = 0;
if (actionEntry) {
- exceptionMatched = handleActionValue
- (
- &actionValue,
- classInfo,
- actionEntry,
- exceptionClass,
- exceptionObject
- );
+ exceptionMatched = handleActionValue(&actionValue,
+ classInfo,
+ actionEntry,
+ exceptionClass,
+ exceptionObject);
}
if (!(actions & _UA_SEARCH_PHASE)) {
_Unwind_Reason_Code ourPersonality(int version,
_Unwind_Action actions,
uint64_t exceptionClass,
- struct _Unwind_Exception* exceptionObject,
+ struct _Unwind_Exception *exceptionObject,
_Unwind_Context_t context) {
#ifdef DEBUG
fprintf(stderr,
}
#endif
- const uint8_t* lsda = _Unwind_GetLanguageSpecificData(context);
+ const uint8_t *lsda = _Unwind_GetLanguageSpecificData(context);
#ifdef DEBUG
fprintf(stderr,
/// generated, and is used to hold the constant string. A value of
/// false indicates that the constant string will be stored on the
/// stack.
-void generateStringPrint(llvm::LLVMContext& context,
- llvm::Module& module,
- llvm::IRBuilder<>& builder,
+void generateStringPrint(llvm::LLVMContext &context,
+ llvm::Module &module,
+ llvm::IRBuilder<> &builder,
std::string toPrint,
bool useGlobal = true) {
llvm::Function *printFunct = module.getFunction("printStr");
llvm::Value *stringVar;
- llvm::Constant* stringConstant =
+ llvm::Constant *stringConstant =
llvm::ConstantArray::get(context, toPrint);
if (useGlobal) {
builder.CreateStore(stringConstant, stringVar);
}
- llvm::Value* cast =
- builder.CreatePointerCast(stringVar,
- builder.getInt8Ty()->getPointerTo());
+ llvm::Value *cast = builder.CreatePointerCast(stringVar,
+ builder.getInt8PtrTy());
builder.CreateCall(printFunct, cast);
}
/// generated, and is used to hold the constant string. A value of
/// false indicates that the constant string will be stored on the
/// stack.
-void generateIntegerPrint(llvm::LLVMContext& context,
- llvm::Module& module,
- llvm::IRBuilder<>& builder,
- llvm::Function& printFunct,
- llvm::Value& toPrint,
+void generateIntegerPrint(llvm::LLVMContext &context,
+ llvm::Module &module,
+ llvm::IRBuilder<> &builder,
+ llvm::Function &printFunct,
+ llvm::Value &toPrint,
std::string format,
bool useGlobal = true) {
llvm::Constant *stringConstant = llvm::ConstantArray::get(context, format);
builder.CreateStore(stringConstant, stringVar);
}
- llvm::Value* cast =
- builder.CreateBitCast(stringVar,
- builder.getInt8Ty()->getPointerTo());
+ llvm::Value *cast = builder.CreateBitCast(stringVar,
+ builder.getInt8PtrTy());
builder.CreateCall2(&printFunct, &toPrint, cast);
}
/// @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,
- llvm::IRBuilder<>& builder,
- llvm::Function& toAddTo,
- std::string& blockName,
- std::string& functionId,
- llvm::BasicBlock& terminatorBlock,
- llvm::BasicBlock& unwindResumeBlock,
- llvm::Value** exceptionCaughtFlag,
- llvm::Value** exceptionStorage) {
+static llvm::BasicBlock *createFinallyBlock(llvm::LLVMContext &context,
+ llvm::Module &module,
+ llvm::IRBuilder<> &builder,
+ llvm::Function &toAddTo,
+ std::string &blockName,
+ std::string &functionId,
+ llvm::BasicBlock &terminatorBlock,
+ llvm::BasicBlock &unwindResumeBlock,
+ llvm::Value **exceptionCaughtFlag,
+ 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.getInt8Ty()->getPointerTo();
- *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,
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);
/// @param terminatorBlock terminator "end" block
/// @param exceptionCaughtFlag exception caught/thrown status
/// @returns newly created block
-static llvm::BasicBlock* createCatchBlock(llvm::LLVMContext& context,
- llvm::Module& module,
- llvm::IRBuilder<>& builder,
- llvm::Function& toAddTo,
- std::string& blockName,
- std::string& functionId,
- llvm::BasicBlock& terminatorBlock,
- llvm::Value& exceptionCaughtFlag) {
+static llvm::BasicBlock *createCatchBlock(llvm::LLVMContext &context,
+ llvm::Module &module,
+ llvm::IRBuilder<> &builder,
+ llvm::Function &toAddTo,
+ std::string &blockName,
+ std::string &functionId,
+ llvm::BasicBlock &terminatorBlock,
+ llvm::Value &exceptionCaughtFlag) {
llvm::BasicBlock *ret = llvm::BasicBlock::Create(context,
blockName,
/// @param exceptionTypesToCatch array of type info types to "catch"
/// @returns generated function
static
-llvm::Function* createCatchWrappedInvokeFunction(llvm::Module& module,
- llvm::IRBuilder<>& builder,
- llvm::FunctionPassManager& fpm,
- llvm::Function& toInvoke,
- std::string ourId,
- unsigned numExceptionsToCatch,
- unsigned exceptionTypesToCatch[]) {
-
- llvm::LLVMContext& context = module.getContext();
+llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
+ llvm::IRBuilder<> &builder,
+ llvm::FunctionPassManager &fpm,
+ llvm::Function &toInvoke,
+ std::string ourId,
+ unsigned numExceptionsToCatch,
+ unsigned exceptionTypesToCatch[]) {
+
+ llvm::LLVMContext &context = module.getContext();
llvm::Function *toPrint32Int = module.getFunction("print32Int");
ArgTypes argTypes;
ArgNames argNames;
argNames.push_back("exceptTypeToThrow");
- llvm::Function* ret = createFunction(module,
+ llvm::Function *ret = createFunction(module,
builder.getVoidTy(),
argTypes,
argNames,
"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;
+ 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.
- llvm::BasicBlock* finallyBlock = createFinallyBlock(context,
+ llvm::BasicBlock *finallyBlock = createFinallyBlock(context,
module,
builder,
*ret,
*endBlock,
*unwindResumeBlock,
&exceptionCaughtFlag,
- &exceptionStorage);
+ &exceptionStorage
+#ifndef OLD_EXC_SYSTEM
+ ,&caughtResultStorage
+#endif
+ );
for (unsigned i = 0; i < numExceptionsToCatch; ++i) {
nextName = ourTypeInfoNames[exceptionTypesToCatch[i]];
builder.CreateInvoke(&toInvoke,
normalBlock,
exceptionBlock,
- args.begin(),
- args.end());
+ args);
// End Block
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,
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);
+ 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.getInt8Ty()->getPointerTo());
+ llvm::Value *functPtr = builder.CreatePointerCast(personality,
+ builder.getInt8PtrTy());
args.clear();
args.push_back(unwindException);
// 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
// the exception is foreign.
- llvm::Value* unwindExceptionClass =
+ llvm::Value *unwindExceptionClass =
builder.CreateLoad(builder.CreateStructGEP(
builder.CreatePointerCast(unwindException,
ourUnwindExceptionType->getPointerTo()),
// (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
//
// unlike a true getelementptr (GEP) instruction
typeInfoThrown = builder.CreateStructGEP(typeInfoThrown, 0);
- llvm::Value* typeInfoThrownType =
+ llvm::Value *typeInfoThrownType =
builder.CreateStructGEP(typeInfoThrown, 0);
generateIntegerPrint(context,
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;
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);
/// if the above nativeThrowType matches generated function's arg.
/// @returns generated function
static
-llvm::Function* createThrowExceptionFunction(llvm::Module& module,
- llvm::IRBuilder<>& builder,
- llvm::FunctionPassManager& fpm,
+llvm::Function *createThrowExceptionFunction(llvm::Module &module,
+ llvm::IRBuilder<> &builder,
+ llvm::FunctionPassManager &fpm,
std::string ourId,
int32_t nativeThrowType,
- llvm::Function& nativeThrowFunct) {
- llvm::LLVMContext& context = module.getContext();
+ llvm::Function &nativeThrowFunct) {
+ llvm::LLVMContext &context = module.getContext();
namedValues.clear();
ArgTypes unwindArgTypes;
unwindArgTypes.push_back(builder.getInt32Ty());
"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"];
+ llvm::Value *exceptionType = namedValues["exceptTypeToThrow"];
// nativeThrowBlock block
// Switches on runtime type info type value to determine whether or not
// a foreign exception is thrown. Defaults to throwing one of our
// generated exceptions.
- llvm::SwitchInst* theSwitch = builder.CreateSwitch(exceptionType,
+ llvm::SwitchInst *theSwitch = builder.CreateSwitch(exceptionType,
generatedThrowBlock,
1);
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);
}
static void createStandardUtilityFunctions(unsigned numTypeInfos,
- llvm::Module& module,
- llvm::IRBuilder<>& builder);
+ llvm::Module &module,
+ llvm::IRBuilder<> &builder);
/// Creates test code by generating and organizing these functions into the
/// test case. The test case consists of an outer function setup to invoke
/// @param nativeThrowFunctName name of external function which will throw
/// a foreign exception
/// @returns outermost generated test function.
-llvm::Function* createUnwindExceptionTest(llvm::Module& module,
- llvm::IRBuilder<>& builder,
- llvm::FunctionPassManager& fpm,
+llvm::Function *createUnwindExceptionTest(llvm::Module &module,
+ llvm::IRBuilder<> &builder,
+ llvm::FunctionPassManager &fpm,
std::string nativeThrowFunctName) {
// Number of type infos to generate
unsigned numTypeInfos = 6;
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};
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);
OurCppRunException(const std::string reason) :
std::runtime_error(reason) {}
- OurCppRunException (const OurCppRunException& toCopy) :
+ OurCppRunException (const OurCppRunException &toCopy) :
std::runtime_error(toCopy) {}
- OurCppRunException& operator = (const OurCppRunException& toCopy) {
+ OurCppRunException &operator = (const OurCppRunException &toCopy) {
return(reinterpret_cast<OurCppRunException&>(
std::runtime_error::operator=(toCopy)));
}
typedef void (*OurExceptionThrowFunctType) (int32_t typeToThrow);
/// This is a test harness which runs test by executing generated
-/// function with a type info type to throw. Harness wraps the excecution
+/// function with a type info type to throw. Harness wraps the execution
/// of generated function in a C++ try catch clause.
/// @param engine execution engine to use for executing generated function.
/// This demo program expects this to be a JIT instance for demo
/// @param typeToThrow type info type of generated exception to throw, or
/// indicator to cause foreign exception to be thrown.
static
-void runExceptionThrow(llvm::ExecutionEngine* engine,
- llvm::Function* function,
+void runExceptionThrow(llvm::ExecutionEngine *engine,
+ llvm::Function *function,
int32_t typeToThrow) {
// Find test's function pointer
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");
}
// End test functions
//
-typedef llvm::ArrayRef<const llvm::Type*> TypeArray;
+typedef llvm::ArrayRef<llvm::Type*> TypeArray;
/// This initialization routine creates type info globals and
/// adds external function declarations to module.
/// @param module code for module instance
/// @param builder builder instance
static void createStandardUtilityFunctions(unsigned numTypeInfos,
- llvm::Module& module,
- llvm::IRBuilder<>& builder) {
+ llvm::Module &module,
+ llvm::IRBuilder<> &builder) {
- llvm::LLVMContext& context = module.getContext();
+ llvm::LLVMContext &context = module.getContext();
// Exception initializations
// 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()));
-
+
+#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));
// Note: Declaring only a portion of the _Unwind_Exception struct.
// Does this cause problems?
ourUnwindExceptionType =
- llvm::StructType::get(context, TypeArray(builder.getInt64Ty()));
+ llvm::StructType::get(context,
+ TypeArray(builder.getInt64Ty()));
+
struct OurBaseException_t dummyException;
// Calculate offset of OurException::unwindException member.
ourBaseFromUnwindOffset = ((uintptr_t) &dummyException) -
- ((uintptr_t) &(dummyException.unwindException));
+ ((uintptr_t) &(dummyException.unwindException));
#ifdef DEBUG
fprintf(stderr,
std::vector<llvm::Constant*> structVals;
llvm::Constant *nextStruct;
- llvm::GlobalVariable* nextGlobal = NULL;
+ llvm::GlobalVariable *nextGlobal = NULL;
// Generate each type info
//
ArgNames argNames;
ArgTypes argTypes;
- llvm::Function* funct = NULL;
+ llvm::Function *funct = NULL;
// print32Int
- const llvm::Type* retType = builder.getVoidTy();
+ llvm::Type *retType = builder.getVoidTy();
argTypes.clear();
argTypes.push_back(builder.getInt32Ty());
- argTypes.push_back(builder.getInt8Ty()->getPointerTo());
+ argTypes.push_back(builder.getInt8PtrTy());
argNames.clear();
argTypes.clear();
argTypes.push_back(builder.getInt64Ty());
- argTypes.push_back(builder.getInt8Ty()->getPointerTo());
+ argTypes.push_back(builder.getInt8PtrTy());
argNames.clear();
retType = builder.getVoidTy();
argTypes.clear();
- argTypes.push_back(builder.getInt8Ty()->getPointerTo());
+ argTypes.push_back(builder.getInt8PtrTy());
argNames.clear();
retType = builder.getVoidTy();
argTypes.clear();
- argTypes.push_back(builder.getInt8Ty()->getPointerTo());
+ argTypes.push_back(builder.getInt8PtrTy());
argNames.clear();
// createOurException
- retType = builder.getInt8Ty()->getPointerTo();
+ retType = builder.getInt8PtrTy();
argTypes.clear();
argTypes.push_back(builder.getInt32Ty());
retType = builder.getInt32Ty();
argTypes.clear();
- argTypes.push_back(builder.getInt8Ty()->getPointerTo());
+ argTypes.push_back(builder.getInt8PtrTy());
argNames.clear();
retType = builder.getInt32Ty();
argTypes.clear();
- argTypes.push_back(builder.getInt8Ty()->getPointerTo());
+ argTypes.push_back(builder.getInt8PtrTy());
argNames.clear();
argTypes.push_back(builder.getInt32Ty());
argTypes.push_back(builder.getInt32Ty());
argTypes.push_back(builder.getInt64Ty());
- argTypes.push_back(builder.getInt8Ty()->getPointerTo());
- argTypes.push_back(builder.getInt8Ty()->getPointerTo());
+ argTypes.push_back(builder.getInt8PtrTy());
+ argTypes.push_back(builder.getInt8PtrTy());
argNames.clear();
/// <= 6 and >= 1 will be caught by test functions; and type info types > 6
/// will result in exceptions which pass through to the test harness. All other
/// type info types are not supported and could cause a crash.
-int main(int argc, char* argv[]) {
+int main(int argc, char *argv[]) {
if (argc == 1) {
fprintf(stderr,
"\nUsage: ExceptionDemo <exception type to throw> "
}
// If not set, exception handling will not be turned on
- llvm::JITExceptionHandling = true;
+ llvm::TargetOptions Opts;
+ Opts.JITExceptionHandling = true;
llvm::InitializeNativeTarget();
- llvm::LLVMContext& context = llvm::getGlobalContext();
+ llvm::LLVMContext &context = llvm::getGlobalContext();
llvm::IRBuilder<> theBuilder(context);
// Make the module, which holds all the code.
- llvm::Module* module = new llvm::Module("my cool jit", context);
+ llvm::Module *module = new llvm::Module("my cool jit", context);
// Build engine with JIT
llvm::EngineBuilder factory(module);
factory.setEngineKind(llvm::EngineKind::JIT);
factory.setAllocateGVsWithCode(false);
- llvm::ExecutionEngine* executionEngine = factory.create();
+ factory.setTargetOptions(Opts);
+ llvm::ExecutionEngine *executionEngine = factory.create();
{
llvm::FunctionPassManager fpm(module);
// Generate test code using function throwCppException(...) as
// the function which throws foreign exceptions.
- llvm::Function* toRun =
+ llvm::Function *toRun =
createUnwindExceptionTest(*module,
theBuilder,
fpm,