diff options
author | tstellar <tstellar@91177308-0d34-0410-b5e6-96231b3b80d8> | 2012-10-16 17:52:57 +0000 |
---|---|---|
committer | tstellar <tstellar@91177308-0d34-0410-b5e6-96231b3b80d8> | 2012-10-16 17:52:57 +0000 |
commit | 47ca737da5de48d621fa88adb89b6265fe224453 (patch) | |
tree | 7e60638529c99989f22bff7a0f40a71a9c3a7399 /examples | |
parent | 5f65515268b0a646b3e5ccedd85b6e0b5f831ac3 (diff) |
Merge master branch
git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/R600/@166033 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'examples')
-rw-r--r-- | examples/ExceptionDemo/ExceptionDemo.cpp | 1177 |
1 files changed, 588 insertions, 589 deletions
diff --git a/examples/ExceptionDemo/ExceptionDemo.cpp b/examples/ExceptionDemo/ExceptionDemo.cpp index 56d4d81b5c7..215cb4d3714 100644 --- a/examples/ExceptionDemo/ExceptionDemo.cpp +++ b/examples/ExceptionDemo/ExceptionDemo.cpp @@ -10,13 +10,13 @@ // Demo program which implements an example LLVM exception implementation, and // shows several test cases including the handling of foreign exceptions. // It is run with type info types arguments to throw. A test will -// be run for each given type info type. While type info types with the value +// be run for each given type info type. While type info types with the value // of -1 will trigger a foreign C++ exception to be thrown; type info types -// <= 6 and >= 1 will cause the associated generated exceptions to be thrown +// <= 6 and >= 1 will cause the associated generated exceptions to be thrown // and caught by generated 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. In all cases, -// the "finally" blocks of every generated test functions will executed +// the "finally" blocks of every generated test functions will executed // regardless of whether or not that test function ignores or catches the // thrown exception. // @@ -25,25 +25,25 @@ // ExceptionDemo // // causes a usage to be printed to stderr -// +// // ExceptionDemo 2 3 7 -1 // // results in the following cases: -// - Value 2 causes an exception with a type info type of 2 to be +// - Value 2 causes an exception with a type info type of 2 to be // thrown and caught by an inner generated test function. -// - Value 3 causes an exception with a type info type of 3 to be +// - Value 3 causes an exception with a type info type of 3 to be // thrown and caught by an outer generated test function. -// - Value 7 causes an exception with a type info type of 7 to be +// - Value 7 causes an exception with a type info type of 7 to be // thrown and NOT be caught by any generated function. // - Value -1 causes a foreign C++ exception to be thrown and not be // caught by any generated function // // 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 explained by: example in rules 1.6.4 in +// of a C++ catch(...) clause catching a generated exception with a +// 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 +// This code uses code from the llvm compiler-rt project and the llvm // Kaleidoscope project. // //===----------------------------------------------------------------------===// @@ -63,12 +63,12 @@ #include "llvm/Support/Dwarf.h" #include "llvm/Support/TargetSelect.h" -// FIXME: Although all systems tested with (Linux, OS X), do not need this -// header file included. A user on ubuntu reported, undefined symbols +// 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 +// 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> @@ -81,11 +81,11 @@ #define USE_GLOBAL_STR_CONSTS true #endif -// System C++ ABI unwind types from: +// System C++ ABI unwind types from: // http://sourcery.mentor.com/public/cxx-abi/abi-eh.html (v1.22) extern "C" { - + typedef enum { _URC_NO_REASON = 0, _URC_FOREIGN_EXCEPTION_CAUGHT = 1, @@ -97,7 +97,7 @@ extern "C" { _URC_INSTALL_CONTEXT = 7, _URC_CONTINUE_UNWIND = 8 } _Unwind_Reason_Code; - + typedef enum { _UA_SEARCH_PHASE = 1, _UA_CLEANUP_PHASE = 2, @@ -105,34 +105,34 @@ extern "C" { _UA_FORCE_UNWIND = 8, _UA_END_OF_STACK = 16 } _Unwind_Action; - + struct _Unwind_Exception; - + typedef void (*_Unwind_Exception_Cleanup_Fn) (_Unwind_Reason_Code, struct _Unwind_Exception *); - + struct _Unwind_Exception { uint64_t exception_class; _Unwind_Exception_Cleanup_Fn exception_cleanup; - - uintptr_t private_1; - uintptr_t private_2; - + + uintptr_t private_1; + uintptr_t private_2; + // @@@ The IA-64 ABI says that this structure must be double-word aligned. - // Taking that literally does not make much sense generically. Instead + // Taking that literally does not make much sense generically. Instead // we provide the maximum alignment required by any type for the machine. } __attribute__((__aligned__)); - + struct _Unwind_Context; typedef struct _Unwind_Context *_Unwind_Context_t; - + 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); extern uintptr_t _Unwind_GetIP (_Unwind_Context_t context); extern uintptr_t _Unwind_GetRegionStart (_Unwind_Context_t context); - + } // extern "C" // @@ -148,13 +148,13 @@ struct OurExceptionType_t { /// This is our Exception class which relies on a negative offset to calculate /// pointers to its instances from pointers to its unwindException member. -/// +/// /// Note: The above unwind.h defines struct _Unwind_Exception to be aligned /// on a double word boundary. This is necessary to match the standard: /// http://refspecs.freestandards.org/abi-eh-1.21.html struct OurBaseException_t { struct OurExceptionType_t type; - + // Note: This is properly aligned in unwind.h struct _Unwind_Exception unwindException; }; @@ -165,7 +165,7 @@ typedef struct OurBaseException_t OurException; typedef struct _Unwind_Exception OurUnwindException; // -// Various globals used to support typeinfo and generatted exceptions in +// Various globals used to support typeinfo and generatted exceptions in // general // @@ -173,7 +173,7 @@ static std::map<std::string, llvm::Value*> namedValues; int64_t ourBaseFromUnwindOffset; -const unsigned char ourBaseExcpClassChars[] = +const unsigned char ourBaseExcpClassChars[] = {'o', 'b', 'j', '\0', 'b', 'a', 's', '\0'}; @@ -203,7 +203,7 @@ typedef std::vector<llvm::Type*> ArgTypes; /// @param retType function return type /// @param theArgTypes function's ordered argument types /// @param theArgNames function's ordered arguments needed if use of this -/// function corresponds to a function definition. Use empty +/// function corresponds to a function definition. Use empty /// aggregate for function declarations. /// @param functName function name /// @param linkage function linkage @@ -224,17 +224,17 @@ llvm::Function *createFunction(llvm::Module &module, llvm::Function::Create(functType, linkage, functName, &module); if (!ret || declarationOnly) return(ret); - + namedValues.clear(); - unsigned i = 0; + unsigned i = 0; for (llvm::Function::arg_iterator argIndex = ret->arg_begin(); i != theArgNames.size(); ++argIndex, ++i) { - + argIndex->setName(theArgNames[i]); namedValues[theArgNames[i]] = argIndex; } - + return(ret); } @@ -250,13 +250,13 @@ static llvm::AllocaInst *createEntryBlockAlloca(llvm::Function &function, const std::string &varName, llvm::Type *type, llvm::Constant *initWith = 0) { - llvm::BasicBlock &block = function.getEntryBlock(); + llvm::BasicBlock &block = function.getEntryBlock(); llvm::IRBuilder<> tmp(&block, block.begin()); llvm::AllocaInst *ret = tmp.CreateAlloca(type, 0, varName.c_str()); - - if (initWith) + + if (initWith) tmp.CreateStore(initWith, ret); - + return(ret); } @@ -266,7 +266,7 @@ static llvm::AllocaInst *createEntryBlockAlloca(llvm::Function &function, // // -// Runtime C Library functions +// Runtime C Library functions // // Note: using an extern "C" block so that static functions can be used @@ -275,7 +275,7 @@ extern "C" { // Note: Better ways to decide on bit width // /// Prints a 32 bit number, according to the format, to stderr. -/// @param intToPrint integer to print +/// @param intToPrint integer to print /// @param format printf like format to use when printing void print32Int(int intToPrint, const char *format) { if (format) { @@ -292,7 +292,7 @@ void print32Int(int intToPrint, const char *format) { // Note: Better ways to decide on bit width // /// Prints a 64 bit number, according to the format, to stderr. -/// @param intToPrint integer to print +/// @param intToPrint integer to print /// @param format printf like format to use when printing void print64Int(long int intToPrint, const char *format) { if (format) { @@ -327,19 +327,19 @@ void deleteOurException(OurUnwindException *expToDelete) { fprintf(stderr, "deleteOurException(...).\n"); #endif - + if (expToDelete && (expToDelete->exception_class == ourBaseExceptionClass)) { - + free(((char*) expToDelete) + ourBaseFromUnwindOffset); } } -/// This function is the struct _Unwind_Exception API mandated delete function -/// used by foreign exception handlers when deleting our exception +/// This function is the struct _Unwind_Exception API mandated delete function +/// used by foreign exception handlers when deleting our exception /// (OurException), instances. -/// @param reason @link http://refspecs.freestandards.org/abi-eh-1.21.html +/// @param reason @link http://refspecs.freestandards.org/abi-eh-1.21.html /// @unlink /// @param expToDelete exception instance to delete void deleteFromUnwindOurException(_Unwind_Reason_Code reason, @@ -348,7 +348,7 @@ void deleteFromUnwindOurException(_Unwind_Reason_Code reason, fprintf(stderr, "deleteFromUnwindOurException(...).\n"); #endif - + deleteOurException(expToDelete); } @@ -362,13 +362,13 @@ OurUnwindException *createOurException(int type) { (ret->type).type = type; (ret->unwindException).exception_class = ourBaseExceptionClass; (ret->unwindException).exception_cleanup = deleteFromUnwindOurException; - + return(&(ret->unwindException)); } -/// Read a uleb128 encoded value and advance pointer -/// See Variable Length Data in: +/// Read a uleb128 encoded value and advance pointer +/// See Variable Length Data in: /// @link http://dwarfstd.org/Dwarf3.pdf @unlink /// @param data reference variable holding memory pointer to decode from /// @returns decoded value @@ -377,22 +377,22 @@ static uintptr_t readULEB128(const uint8_t **data) { uintptr_t shift = 0; unsigned char byte; const uint8_t *p = *data; - + do { byte = *p++; result |= (byte & 0x7f) << shift; shift += 7; - } + } while (byte & 0x80); - + *data = p; - + return result; } -/// Read a sleb128 encoded value and advance pointer -/// See Variable Length Data in: +/// Read a sleb128 encoded value and advance pointer +/// See Variable Length Data in: /// @link http://dwarfstd.org/Dwarf3.pdf @unlink /// @param data reference variable holding memory pointer to decode from /// @returns decoded value @@ -401,26 +401,26 @@ static uintptr_t readSLEB128(const uint8_t **data) { uintptr_t shift = 0; unsigned char byte; const uint8_t *p = *data; - + do { byte = *p++; result |= (byte & 0x7f) << shift; shift += 7; - } + } while (byte & 0x80); - + *data = p; - + if ((byte & 0x40) && (shift < (sizeof(result) << 3))) { result |= (~0 << shift); } - + return result; } -/// Read a pointer encoded value and advance pointer -/// See Variable Length Data in: +/// Read a pointer encoded value and advance pointer +/// See Variable Length Data in: /// @link http://dwarfstd.org/Dwarf3.pdf @unlink /// @param data reference variable holding memory pointer to decode from /// @param encoding dwarf encoding type @@ -428,11 +428,11 @@ static uintptr_t readSLEB128(const uint8_t **data) { static uintptr_t readEncodedPointer(const uint8_t **data, uint8_t encoding) { uintptr_t result = 0; const uint8_t *p = *data; - - if (encoding == llvm::dwarf::DW_EH_PE_omit) + + if (encoding == llvm::dwarf::DW_EH_PE_omit) return(result); - - // first get value + + // first get value switch (encoding & 0x0F) { case llvm::dwarf::DW_EH_PE_absptr: result = *((uintptr_t*)p); @@ -470,15 +470,15 @@ static uintptr_t readEncodedPointer(const uint8_t **data, uint8_t encoding) { p += sizeof(int64_t); break; default: - // not supported + // not supported abort(); break; } - - // then add relative offset + + // then add relative offset switch (encoding & 0x70) { case llvm::dwarf::DW_EH_PE_absptr: - // do nothing + // do nothing break; case llvm::dwarf::DW_EH_PE_pcrel: result += (uintptr_t)(*data); @@ -488,34 +488,34 @@ static uintptr_t readEncodedPointer(const uint8_t **data, uint8_t encoding) { case llvm::dwarf::DW_EH_PE_funcrel: case llvm::dwarf::DW_EH_PE_aligned: default: - // not supported + // not supported abort(); break; } - - // then apply indirection + + // then apply indirection if (encoding & llvm::dwarf::DW_EH_PE_indirect) { result = *((uintptr_t*)result); } - + *data = p; - + return result; } -/// Deals with Dwarf actions matching our type infos -/// (OurExceptionType_t instances). Returns whether or not a dwarf emitted -/// action matches the supplied exception type. If such a match succeeds, -/// the resultAction argument will be set with > 0 index value. Only -/// corresponding llvm.eh.selector type info arguments, cleanup arguments +/// Deals with Dwarf actions matching our type infos +/// (OurExceptionType_t instances). Returns whether or not a dwarf emitted +/// action matches the supplied exception type. If such a match succeeds, +/// the resultAction argument will be set with > 0 index value. Only +/// corresponding llvm.eh.selector type info arguments, cleanup arguments /// are supported. Filters are not supported. -/// See Variable Length Data in: +/// See Variable Length Data in: /// @link http://dwarfstd.org/Dwarf3.pdf @unlink /// Also see @link http://refspecs.freestandards.org/abi-eh-1.21.html @unlink /// @param resultAction reference variable which will be set with result /// @param classInfo our array of type info pointers (to globals) -/// @param actionEntry index into above type info array or 0 (clean up). +/// @param actionEntry index into above type info array or 0 (clean up). /// We do not support filters. /// @param exceptionClass exception class (_Unwind_Exception::exception_class) /// of thrown exception. @@ -523,22 +523,22 @@ static uintptr_t readEncodedPointer(const uint8_t **data, uint8_t encoding) { /// @returns whether or not a type info was found. False is returned if only /// a cleanup was found static bool handleActionValue(int64_t *resultAction, - struct OurExceptionType_t **classInfo, - uintptr_t actionEntry, - uint64_t exceptionClass, + struct OurExceptionType_t **classInfo, + uintptr_t actionEntry, + uint64_t exceptionClass, struct _Unwind_Exception *exceptionObject) { bool ret = false; - - if (!resultAction || - !exceptionObject || + + if (!resultAction || + !exceptionObject || (exceptionClass != ourBaseExceptionClass)) return(ret); - + struct OurBaseException_t *excp = (struct OurBaseException_t*) (((char*) exceptionObject) + ourBaseFromUnwindOffset); struct OurExceptionType_t *excpType = &(excp->type); int type = excpType->type; - + #ifdef DEBUG fprintf(stderr, "handleActionValue(...): exceptionObject = <%p>, " @@ -546,12 +546,12 @@ static bool handleActionValue(int64_t *resultAction, exceptionObject, excp); #endif - + const uint8_t *actionPos = (uint8_t*) actionEntry, *tempActionPos; int64_t typeOffset = 0, actionOffset; - + for (int i = 0; true; ++i) { // Each emitted dwarf action corresponds to a 2 tuple of // type info address offset, and action offset to the next @@ -559,7 +559,7 @@ static bool handleActionValue(int64_t *resultAction, typeOffset = readSLEB128(&actionPos); tempActionPos = actionPos; actionOffset = readSLEB128(&tempActionPos); - + #ifdef DEBUG fprintf(stderr, "handleActionValue(...):typeOffset: <%lld>, " @@ -567,9 +567,9 @@ static bool handleActionValue(int64_t *resultAction, typeOffset, actionOffset); #endif - assert((typeOffset >= 0) && + assert((typeOffset >= 0) && "handleActionValue(...):filters are not supported."); - + // Note: A typeOffset == 0 implies that a cleanup llvm.eh.selector // argument has been matched. if ((typeOffset > 0) && @@ -583,17 +583,17 @@ static bool handleActionValue(int64_t *resultAction, ret = true; break; } - + #ifdef DEBUG fprintf(stderr, "handleActionValue(...):actionValue not found.\n"); #endif if (!actionOffset) break; - + actionPos += actionOffset; } - + return(ret); } @@ -602,52 +602,52 @@ static bool handleActionValue(int64_t *resultAction, /// See @link http://refspecs.freestandards.org/abi-eh-1.21.html @unlink /// @param version unsupported (ignored), unwind version /// @param lsda language specific data area -/// @param _Unwind_Action actions minimally supported unwind stage +/// @param _Unwind_Action actions minimally supported unwind stage /// (forced specifically not supported) /// @param exceptionClass exception class (_Unwind_Exception::exception_class) /// of thrown exception. /// @param exceptionObject thrown _Unwind_Exception instance. /// @param context unwind system context -/// @returns minimally supported unwinding control indicator -static _Unwind_Reason_Code handleLsda(int version, +/// @returns minimally supported unwinding control indicator +static _Unwind_Reason_Code handleLsda(int version, const uint8_t *lsda, _Unwind_Action actions, - uint64_t exceptionClass, + uint64_t exceptionClass, struct _Unwind_Exception *exceptionObject, _Unwind_Context_t context) { _Unwind_Reason_Code ret = _URC_CONTINUE_UNWIND; - + if (!lsda) return(ret); - + #ifdef DEBUG - fprintf(stderr, + fprintf(stderr, "handleLsda(...):lsda is non-zero.\n"); #endif - + // Get the current instruction pointer and offset it before next // instruction in the current frame which threw the exception. uintptr_t pc = _Unwind_GetIP(context)-1; - - // Get beginning current frame's code (as defined by the + + // Get beginning current frame's code (as defined by the // emitted dwarf code) uintptr_t funcStart = _Unwind_GetRegionStart(context); uintptr_t pcOffset = pc - funcStart; struct OurExceptionType_t **classInfo = NULL; - + // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding // dwarf emission - + // Parse LSDA header. uint8_t lpStartEncoding = *lsda++; - + if (lpStartEncoding != llvm::dwarf::DW_EH_PE_omit) { - readEncodedPointer(&lsda, lpStartEncoding); + readEncodedPointer(&lsda, lpStartEncoding); } - + uint8_t ttypeEncoding = *lsda++; uintptr_t classInfoOffset; - + if (ttypeEncoding != llvm::dwarf::DW_EH_PE_omit) { // Calculate type info locations in emitted dwarf code which // were flagged by type info arguments to llvm.eh.selector @@ -655,47 +655,47 @@ static _Unwind_Reason_Code handleLsda(int version, classInfoOffset = readULEB128(&lsda); classInfo = (struct OurExceptionType_t**) (lsda + classInfoOffset); } - - // Walk call-site table looking for range that - // includes current PC. - + + // Walk call-site table looking for range that + // includes current PC. + uint8_t callSiteEncoding = *lsda++; uint32_t callSiteTableLength = readULEB128(&lsda); const uint8_t *callSiteTableStart = lsda; - const uint8_t *callSiteTableEnd = callSiteTableStart + + const uint8_t *callSiteTableEnd = callSiteTableStart + callSiteTableLength; const uint8_t *actionTableStart = callSiteTableEnd; const uint8_t *callSitePtr = callSiteTableStart; - + bool foreignException = false; - + while (callSitePtr < callSiteTableEnd) { - uintptr_t start = readEncodedPointer(&callSitePtr, + uintptr_t start = readEncodedPointer(&callSitePtr, callSiteEncoding); - uintptr_t length = readEncodedPointer(&callSitePtr, + uintptr_t length = readEncodedPointer(&callSitePtr, callSiteEncoding); - uintptr_t landingPad = readEncodedPointer(&callSitePtr, + uintptr_t landingPad = readEncodedPointer(&callSitePtr, callSiteEncoding); - + // Note: Action value uintptr_t actionEntry = readULEB128(&callSitePtr); - + if (exceptionClass != ourBaseExceptionClass) { // We have been notified of a foreign exception being thrown, // and we therefore need to execute cleanup landing pads actionEntry = 0; foreignException = true; } - + if (landingPad == 0) { #ifdef DEBUG fprintf(stderr, "handleLsda(...): No landing pad found.\n"); #endif - + continue; // no landing pad for this entry } - + if (actionEntry) { actionEntry += ((uintptr_t) actionTableStart) - 1; } @@ -705,55 +705,55 @@ static _Unwind_Reason_Code handleLsda(int version, "handleLsda(...):No action table found.\n"); #endif } - + bool exceptionMatched = false; - + if ((start <= pcOffset) && (pcOffset < (start + length))) { #ifdef DEBUG fprintf(stderr, "handleLsda(...): Landing pad found.\n"); #endif int64_t actionValue = 0; - + if (actionEntry) { exceptionMatched = handleActionValue(&actionValue, - classInfo, - actionEntry, - exceptionClass, + classInfo, + actionEntry, + exceptionClass, exceptionObject); } - + if (!(actions & _UA_SEARCH_PHASE)) { #ifdef DEBUG fprintf(stderr, "handleLsda(...): installed landing pad " "context.\n"); #endif - + // Found landing pad for the PC. - // Set Instruction Pointer to so we re-enter function - // at landing pad. The landing pad is created by the + // Set Instruction Pointer to so we re-enter function + // at landing pad. The landing pad is created by the // compiler to take two parameters in registers. - _Unwind_SetGR(context, - __builtin_eh_return_data_regno(0), + _Unwind_SetGR(context, + __builtin_eh_return_data_regno(0), (uintptr_t)exceptionObject); - + // Note: this virtual register directly corresponds // to the return of the llvm.eh.selector intrinsic if (!actionEntry || !exceptionMatched) { // We indicate cleanup only - _Unwind_SetGR(context, - __builtin_eh_return_data_regno(1), + _Unwind_SetGR(context, + __builtin_eh_return_data_regno(1), 0); } else { // Matched type info index of llvm.eh.selector intrinsic // passed here. - _Unwind_SetGR(context, - __builtin_eh_return_data_regno(1), + _Unwind_SetGR(context, + __builtin_eh_return_data_regno(1), actionValue); } - + // To execute landing pad set here _Unwind_SetIP(context, funcStart + landingPad); ret = _URC_INSTALL_CONTEXT; @@ -767,19 +767,19 @@ static _Unwind_Reason_Code handleLsda(int version, } else { // Note: Only non-clean up handlers are marked as - // found. Otherwise the clean up handlers will be - // re-found and executed during the clean up + // found. Otherwise the clean up handlers will be + // re-found and executed during the clean up // phase. #ifdef DEBUG fprintf(stderr, "handleLsda(...): cleanup handler found.\n"); #endif } - + break; } } - + return(ret); } @@ -788,23 +788,23 @@ static _Unwind_Reason_Code handleLsda(int version, /// dwarf unwind info block. Again see: JITDwarfEmitter.cpp. /// See @link http://refspecs.freestandards.org/abi-eh-1.21.html @unlink /// @param version unsupported (ignored), unwind version -/// @param _Unwind_Action actions minimally supported unwind stage +/// @param _Unwind_Action actions minimally supported unwind stage /// (forced specifically not supported) /// @param exceptionClass exception class (_Unwind_Exception::exception_class) /// of thrown exception. /// @param exceptionObject thrown _Unwind_Exception instance. /// @param context unwind system context -/// @returns minimally supported unwinding control indicator -_Unwind_Reason_Code ourPersonality(int version, +/// @returns minimally supported unwinding control indicator +_Unwind_Reason_Code ourPersonality(int version, _Unwind_Action actions, - uint64_t exceptionClass, + uint64_t exceptionClass, struct _Unwind_Exception *exceptionObject, _Unwind_Context_t context) { #ifdef DEBUG - fprintf(stderr, + fprintf(stderr, "We are in ourPersonality(...):actions is <%d>.\n", actions); - + if (actions & _UA_SEARCH_PHASE) { fprintf(stderr, "ourPersonality(...):In search phase.\n"); } @@ -812,15 +812,15 @@ _Unwind_Reason_Code ourPersonality(int version, fprintf(stderr, "ourPersonality(...):In non-search phase.\n"); } #endif - + const uint8_t *lsda = _Unwind_GetLanguageSpecificData(context); - + #ifdef DEBUG - fprintf(stderr, + fprintf(stderr, "ourPersonality(...):lsda = <%p>.\n", lsda); #endif - + // The real work of the personality function is captured here return(handleLsda(version, lsda, @@ -841,12 +841,12 @@ _Unwind_Reason_Code ourPersonality(int version, uint64_t genClass(const unsigned char classChars[], size_t classCharsSize) { uint64_t ret = classChars[0]; - + for (unsigned i = 1; i < classCharsSize; ++i) { ret <<= 8; ret += classChars[i]; } - + return(ret); } @@ -865,37 +865,37 @@ uint64_t genClass(const unsigned char classChars[], size_t classCharsSize) /// @param module code for module instance /// @param builder builder instance /// @param toPrint string to print -/// @param useGlobal A value of true (default) indicates a GlobalValue is -/// generated, and is used to hold the constant string. A value of -/// false indicates that the constant string will be stored on the +/// @param useGlobal A value of true (default) indicates a GlobalValue is +/// 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, +void generateStringPrint(llvm::LLVMContext &context, llvm::Module &module, - llvm::IRBuilder<> &builder, + 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::ConstantDataArray::getString(context, toPrint); - + if (useGlobal) { // Note: Does not work without allocation - stringVar = - new llvm::GlobalVariable(module, + stringVar = + new llvm::GlobalVariable(module, stringConstant->getType(), - true, - llvm::GlobalValue::LinkerPrivateLinkage, - stringConstant, + true, + llvm::GlobalValue::LinkerPrivateLinkage, + stringConstant, ""); } else { stringVar = builder.CreateAlloca(stringConstant->getType()); builder.CreateStore(stringConstant, stringVar); } - - llvm::Value *cast = builder.CreatePointerCast(stringVar, + + llvm::Value *cast = builder.CreatePointerCast(stringVar, builder.getInt8PtrTy()); builder.CreateCall(printFunct, cast); } @@ -909,49 +909,49 @@ void generateStringPrint(llvm::LLVMContext &context, /// @param printFunct function used to "print" integer /// @param toPrint string to print /// @param format printf like formating string for print -/// @param useGlobal A value of true (default) indicates a GlobalValue is -/// generated, and is used to hold the constant string. A value of -/// false indicates that the constant string will be stored on the +/// @param useGlobal A value of true (default) indicates a GlobalValue is +/// 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, +void generateIntegerPrint(llvm::LLVMContext &context, llvm::Module &module, - llvm::IRBuilder<> &builder, + llvm::IRBuilder<> &builder, llvm::Function &printFunct, llvm::Value &toPrint, - std::string format, + std::string format, bool useGlobal = true) { llvm::Constant *stringConstant = llvm::ConstantDataArray::getString(context, format); llvm::Value *stringVar; - + if (useGlobal) { // Note: Does not seem to work without allocation - stringVar = - new llvm::GlobalVariable(module, + stringVar = + new llvm::GlobalVariable(module, stringConstant->getType(), - true, - llvm::GlobalValue::LinkerPrivateLinkage, - stringConstant, + true, + llvm::GlobalValue::LinkerPrivateLinkage, + stringConstant, ""); } else { stringVar = builder.CreateAlloca(stringConstant->getType()); builder.CreateStore(stringConstant, stringVar); } - - llvm::Value *cast = builder.CreateBitCast(stringVar, + + llvm::Value *cast = builder.CreateBitCast(stringVar, builder.getInt8PtrTy()); builder.CreateCall2(&printFunct, &toPrint, cast); } -/// Generates code to handle finally block type semantics: always runs -/// regardless of whether a thrown exception is passing through or the -/// parent function is simply exiting. In addition to printing some state -/// to stderr, this code will resume the exception handling--runs the -/// unwind resume block, if the exception has not been previously caught -/// by a catch clause, and will otherwise execute the end block (terminator -/// block). In addition this function creates the corresponding function's +/// Generates code to handle finally block type semantics: always runs +/// regardless of whether a thrown exception is passing through or the +/// parent function is simply exiting. In addition to printing some state +/// to stderr, this code will resume the exception handling--runs the +/// unwind resume block, if the exception has not been previously caught +/// by a catch clause, and will otherwise execute the end block (terminator +/// block). In addition this function creates the corresponding function's /// stack storage for the exception pointer and catch flag status. /// @param context llvm context /// @param module code for module instance @@ -965,9 +965,9 @@ void generateIntegerPrint(llvm::LLVMContext &context, /// @param exceptionStorage reference to exception pointer storage /// @param caughtResultStorage reference to landingpad result storage /// @returns newly created block -static llvm::BasicBlock *createFinallyBlock(llvm::LLVMContext &context, - llvm::Module &module, - llvm::IRBuilder<> &builder, +static llvm::BasicBlock *createFinallyBlock(llvm::LLVMContext &context, + llvm::Module &module, + llvm::IRBuilder<> &builder, llvm::Function &toAddTo, std::string &blockName, std::string &functionId, @@ -976,21 +976,21 @@ static llvm::BasicBlock *createFinallyBlock(llvm::LLVMContext &context, llvm::Value **exceptionCaughtFlag, llvm::Value **exceptionStorage, llvm::Value **caughtResultStorage) { - assert(exceptionCaughtFlag && + assert(exceptionCaughtFlag && "ExceptionDemo::createFinallyBlock(...):exceptionCaughtFlag " "is NULL"); - assert(exceptionStorage && + assert(exceptionStorage && "ExceptionDemo::createFinallyBlock(...):exceptionStorage " "is NULL"); - assert(caughtResultStorage && + assert(caughtResultStorage && "ExceptionDemo::createFinallyBlock(...):caughtResultStorage " "is NULL"); - + *exceptionCaughtFlag = createEntryBlockAlloca(toAddTo, "exceptionCaught", ourExceptionNotThrownState->getType(), ourExceptionNotThrownState); - + llvm::PointerType *exceptionStorageType = builder.getInt8PtrTy(); *exceptionStorage = createEntryBlockAlloca(toAddTo, "exceptionStorage", @@ -1002,35 +1002,35 @@ static llvm::BasicBlock *createFinallyBlock(llvm::LLVMContext &context, ourCaughtResultType, llvm::ConstantAggregateZero::get( ourCaughtResultType)); - + llvm::BasicBlock *ret = llvm::BasicBlock::Create(context, blockName, &toAddTo); - + builder.SetInsertPoint(ret); - + std::ostringstream bufferToPrint; bufferToPrint << "Gen: Executing finally block " << blockName << " in " << functionId << "\n"; - generateStringPrint(context, - module, - builder, + generateStringPrint(context, + module, + builder, bufferToPrint.str(), USE_GLOBAL_STR_CONSTS); - + llvm::SwitchInst *theSwitch = builder.CreateSwitch(builder.CreateLoad( - *exceptionCaughtFlag), + *exceptionCaughtFlag), &terminatorBlock, 2); theSwitch->addCase(ourExceptionCaughtState, &terminatorBlock); theSwitch->addCase(ourExceptionThrownState, &unwindResumeBlock); - + return(ret); } /// Generates catch block semantics which print a string to indicate type of -/// catch executed, sets an exception caught flag, and executes passed in +/// catch executed, sets an exception caught flag, and executes passed in /// end block (terminator block). /// @param context llvm context /// @param module code for module instance @@ -1041,52 +1041,52 @@ static llvm::BasicBlock *createFinallyBlock(llvm::LLVMContext &context, /// @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, +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, &toAddTo); - + builder.SetInsertPoint(ret); - + std::ostringstream bufferToPrint; bufferToPrint << "Gen: Executing catch block " << blockName << " in " << functionId << std::endl; - generateStringPrint(context, - module, - builder, + generateStringPrint(context, + module, + builder, bufferToPrint.str(), USE_GLOBAL_STR_CONSTS); builder.CreateStore(ourExceptionCaughtState, &exceptionCaughtFlag); builder.CreateBr(&terminatorBlock); - + return(ret); } -/// Generates a function which invokes a function (toInvoke) and, whose -/// unwind block will "catch" the type info types correspondingly held in the -/// exceptionTypesToCatch argument. If the toInvoke function throws an -/// exception which does not match any type info types contained in -/// exceptionTypesToCatch, the generated code will call _Unwind_Resume -/// with the raised exception. On the other hand the generated code will +/// Generates a function which invokes a function (toInvoke) and, whose +/// unwind block will "catch" the type info types correspondingly held in the +/// exceptionTypesToCatch argument. If the toInvoke function throws an +/// exception which does not match any type info types contained in +/// exceptionTypesToCatch, the generated code will call _Unwind_Resume +/// with the raised exception. On the other hand the generated code will /// normally exit if the toInvoke function does not throw an exception. -/// The generated "finally" block is always run regardless of the cause of +/// The generated "finally" block is always run regardless of the cause of /// the generated function exit. /// The generated function is returned after being verified. /// @param module code for module instance /// @param builder builder instance -/// @param fpm a function pass manager holding optional IR to IR +/// @param fpm a function pass manager holding optional IR to IR /// transformations /// @param toInvoke inner function to invoke /// @param ourId id used to printing purposes @@ -1094,76 +1094,76 @@ static llvm::BasicBlock *createCatchBlock(llvm::LLVMContext &context, /// @param exceptionTypesToCatch array of type info types to "catch" /// @returns generated function static -llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module, - llvm::IRBuilder<> &builder, +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; argTypes.push_back(builder.getInt32Ty()); - + ArgNames argNames; argNames.push_back("exceptTypeToThrow"); - - llvm::Function *ret = createFunction(module, + + llvm::Function *ret = createFunction(module, builder.getVoidTy(), - argTypes, - argNames, + argTypes, + argNames, ourId, - llvm::Function::ExternalLinkage, - false, + llvm::Function::ExternalLinkage, + false, false); - + // Block which calls invoke llvm::BasicBlock *entryBlock = llvm::BasicBlock::Create(context, - "entry", + "entry", ret); // Normal block for invoke - llvm::BasicBlock *normalBlock = llvm::BasicBlock::Create(context, - "normal", + llvm::BasicBlock *normalBlock = llvm::BasicBlock::Create(context, + "normal", ret); // Unwind block for invoke - llvm::BasicBlock *exceptionBlock = llvm::BasicBlock::Create(context, - "exception", + 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", + llvm::BasicBlock *exceptionRouteBlock = llvm::BasicBlock::Create(context, + "exceptionRoute", ret); - + // Foreign exception handler - llvm::BasicBlock *externalExceptionBlock = llvm::BasicBlock::Create(context, - "externalException", + llvm::BasicBlock *externalExceptionBlock = llvm::BasicBlock::Create(context, + "externalException", ret); - + // Block which calls _Unwind_Resume - llvm::BasicBlock *unwindResumeBlock = llvm::BasicBlock::Create(context, - "unwindResume", + 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); - + std::string nextName; std::vector<llvm::BasicBlock*> catchBlocks(numExceptionsToCatch); llvm::Value *exceptionCaughtFlag = NULL; llvm::Value *exceptionStorage = NULL; llvm::Value *caughtResultStorage = NULL; - - // Finally block which will branch to unwindResumeBlock if + + // Finally block which will branch to unwindResumeBlock if // exception is not caught. Initializes/allocates stack locations. - llvm::BasicBlock *finallyBlock = createFinallyBlock(context, - module, - builder, - *ret, - nextName = "finally", + llvm::BasicBlock *finallyBlock = createFinallyBlock(context, + module, + builder, + *ret, + nextName = "finally", ourId, *endBlock, *unwindResumeBlock, @@ -1171,74 +1171,74 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module, &exceptionStorage, &caughtResultStorage ); - + for (unsigned i = 0; i < numExceptionsToCatch; ++i) { nextName = ourTypeInfoNames[exceptionTypesToCatch[i]]; - + // One catch block per type info to be caught - catchBlocks[i] = createCatchBlock(context, - module, - builder, + catchBlocks[i] = createCatchBlock(context, + module, + builder, *ret, - nextName, + nextName, ourId, *finallyBlock, *exceptionCaughtFlag); } - + // Entry Block - + builder.SetInsertPoint(entryBlock); - + std::vector<llvm::Value*> args; args.push_back(namedValues["exceptTypeToThrow"]); - builder.CreateInvoke(&toInvoke, - normalBlock, - exceptionBlock, + builder.CreateInvoke(&toInvoke, + normalBlock, + exceptionBlock, args); - + // End Block - + builder.SetInsertPoint(endBlock); - - generateStringPrint(context, + + generateStringPrint(context, module, - builder, + builder, "Gen: In end block: exiting in " + ourId + ".\n", USE_GLOBAL_STR_CONSTS); llvm::Function *deleteOurException = module.getFunction("deleteOurException"); - + // Note: function handles NULL exceptions - builder.CreateCall(deleteOurException, + builder.CreateCall(deleteOurException, builder.CreateLoad(exceptionStorage)); builder.CreateRetVoid(); - + // Normal Block - + builder.SetInsertPoint(normalBlock); - - generateStringPrint(context, + + generateStringPrint(context, module, - builder, + builder, "Gen: No exception in " + ourId + "!\n", USE_GLOBAL_STR_CONSTS); - + // Finally block is always called builder.CreateBr(finallyBlock); - + // Unwind Resume Block - + builder.SetInsertPoint(unwindResumeBlock); - + builder.CreateResume(builder.CreateLoad(caughtResultStorage)); - + // Exception Block - + builder.SetInsertPoint(exceptionBlock); - + llvm::Function *personality = module.getFunction("ourPersonality"); - - llvm::LandingPadInst *caughtResult = + + llvm::LandingPadInst *caughtResult = builder.CreateLandingPad(ourCaughtResultType, personality, numExceptionsToCatch, @@ -1255,48 +1255,48 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module, 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 + // FIXME: Redundant storage which, beyond utilizing value of + // caughtResultStore for unwindException storage, may be alleviated // altogether with a block rearrangement builder.CreateStore(caughtResult, caughtResultStorage); builder.CreateStore(unwindException, exceptionStorage); builder.CreateStore(ourExceptionThrownState, exceptionCaughtFlag); - - // Retrieve exception_class member from thrown exception + + // 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()), + builder.CreatePointerCast(unwindException, + ourUnwindExceptionType->getPointerTo()), 0)); - + // Branch to the externalExceptionBlock if the exception is foreign or // to a catch router if not. Either way the finally block will be run. builder.CreateCondBr(builder.CreateICmpEQ(unwindExceptionClass, - llvm::ConstantInt::get(builder.getInt64Ty(), + llvm::ConstantInt::get(builder.getInt64Ty(), ourBaseExceptionClass)), exceptionRouteBlock, externalExceptionBlock); - + // External Exception Block - + builder.SetInsertPoint(externalExceptionBlock); - - generateStringPrint(context, + + generateStringPrint(context, module, - builder, + builder, "Gen: Foreign exception received.\n", USE_GLOBAL_STR_CONSTS); - + // Branch to the finally block builder.CreateBr(finallyBlock); - + // Exception Route Block - + builder.SetInsertPoint(exceptionRouteBlock); - - // Casts exception pointer (_Unwind_Exception instance) to parent + + // Casts exception pointer (_Unwind_Exception instance) to parent // (OurException instance). // // Note: ourBaseFromUnwindOffset is usually negative @@ -1304,34 +1304,34 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module, builder.CreateConstGEP1_64(unwindException, ourBaseFromUnwindOffset), ourExceptionType->getPointerTo()); - + // Retrieve thrown exception type info type // // Note: Index is not relative to pointer but instead to structure // unlike a true getelementptr (GEP) instruction typeInfoThrown = builder.CreateStructGEP(typeInfoThrown, 0); - - llvm::Value *typeInfoThrownType = + + llvm::Value *typeInfoThrownType = builder.CreateStructGEP(typeInfoThrown, 0); - - generateIntegerPrint(context, + + generateIntegerPrint(context, module, - builder, - *toPrint32Int, + builder, + *toPrint32Int, *(builder.CreateLoad(typeInfoThrownType)), - "Gen: Exception type <%d> received (stack unwound) " - " in " + - ourId + + "Gen: Exception type <%d> received (stack unwound) " + " in " + + ourId + ".\n", USE_GLOBAL_STR_CONSTS); - + // Route to matched type info catch block or run cleanup finally block - llvm::SwitchInst *switchToCatchBlock = builder.CreateSwitch(retTypeInfoIndex, - finallyBlock, + llvm::SwitchInst *switchToCatchBlock = builder.CreateSwitch(retTypeInfoIndex, + finallyBlock, numExceptionsToCatch); - + unsigned nextTypeToCatch; - + for (unsigned i = 1; i <= numExceptionsToCatch; ++i) { nextTypeToCatch = i - 1; switchToCatchBlock->addCase(llvm::ConstantInt::get( @@ -1341,18 +1341,18 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module, llvm::verifyFunction(*ret); fpm.run(*ret); - + return(ret); } /// Generates function which throws either an exception matched to a runtime -/// determined type info type (argument to generated function), or if this -/// runtime value matches nativeThrowType, throws a foreign exception by +/// determined type info type (argument to generated function), or if this +/// runtime value matches nativeThrowType, throws a foreign exception by /// calling nativeThrowFunct. /// @param module code for module instance /// @param builder builder instance -/// @param fpm a function pass manager holding optional IR to IR +/// @param fpm a function pass manager holding optional IR to IR /// transformations /// @param ourId id used to printing purposes /// @param nativeThrowType a runtime argument of this value results in @@ -1361,8 +1361,8 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module, /// if the above nativeThrowType matches generated function's arg. /// @returns generated function static -llvm::Function *createThrowExceptionFunction(llvm::Module &module, - llvm::IRBuilder<> &builder, +llvm::Function *createThrowExceptionFunction(llvm::Module &module, + llvm::IRBuilder<> &builder, llvm::FunctionPassManager &fpm, std::string ourId, int32_t nativeThrowType, @@ -1373,7 +1373,7 @@ llvm::Function *createThrowExceptionFunction(llvm::Module &module, unwindArgTypes.push_back(builder.getInt32Ty()); ArgNames unwindArgNames; unwindArgNames.push_back("exceptTypeToThrow"); - + llvm::Function *ret = createFunction(module, builder.getVoidTy(), unwindArgTypes, @@ -1382,88 +1382,88 @@ llvm::Function *createThrowExceptionFunction(llvm::Module &module, llvm::Function::ExternalLinkage, false, false); - + // Throws either one of our exception or a native C++ exception depending // on a runtime argument value containing a type info type. llvm::BasicBlock *entryBlock = llvm::BasicBlock::Create(context, - "entry", + "entry", ret); // Throws a foreign exception llvm::BasicBlock *nativeThrowBlock = llvm::BasicBlock::Create(context, - "nativeThrow", + "nativeThrow", ret); // Throws one of our Exceptions llvm::BasicBlock *generatedThrowBlock = llvm::BasicBlock::Create(context, - "generatedThrow", + "generatedThrow", ret); // Retrieved runtime type info type to throw llvm::Value *exceptionType = namedValues["exceptTypeToThrow"]; - + // nativeThrowBlock block - + builder.SetInsertPoint(nativeThrowBlock); - + // Throws foreign exception builder.CreateCall(&nativeThrowFunct, exceptionType); builder.CreateUnreachable(); - + // entry block - + builder.SetInsertPoint(entryBlock); - + llvm::Function *toPrint32Int = module.getFunction("print32Int"); - generateIntegerPrint(context, + generateIntegerPrint(context, module, - builder, - *toPrint32Int, - *exceptionType, - "\nGen: About to throw exception type <%d> in " + - ourId + + builder, + *toPrint32Int, + *exceptionType, + "\nGen: About to throw exception type <%d> in " + + ourId + ".\n", USE_GLOBAL_STR_CONSTS); - + // Switches on runtime type info type value to determine whether or not - // a foreign exception is thrown. Defaults to throwing one of our + // a foreign exception is thrown. Defaults to throwing one of our // generated exceptions. llvm::SwitchInst *theSwitch = builder.CreateSwitch(exceptionType, generatedThrowBlock, 1); - - theSwitch->addCase(llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), + + theSwitch->addCase(llvm::ConstantInt::get(llvm::Type::getInt32Ty(context), nativeThrowType), nativeThrowBlock); - + // generatedThrow block - + builder.SetInsertPoint(generatedThrowBlock); - + 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, + llvm::Value *exception = builder.CreateCall(createOurException, namedValues["exceptTypeToThrow"]); - + // Throw generated Exception builder.CreateCall(raiseOurException, exception); builder.CreateUnreachable(); - + llvm::verifyFunction(*ret); fpm.run(*ret); - + return(ret); } static void createStandardUtilityFunctions(unsigned numTypeInfos, - llvm::Module &module, + llvm::Module &module, llvm::IRBuilder<> &builder); -/// Creates test code by generating and organizing these functions into the +/// Creates test code by generating and organizing these functions into the /// test case. The test case consists of an outer function setup to invoke -/// an inner function within an environment having multiple catch and single +/// an inner function within an environment having multiple catch and single /// finally blocks. This inner function is also setup to invoke a throw -/// function within an evironment similar in nature to the outer function's +/// function within an evironment similar in nature to the outer function's /// catch and finally blocks. Each of these two functions catch mutually /// exclusive subsets (even or odd) of the type info types configured /// for this this. All generated functions have a runtime argument which @@ -1474,26 +1474,26 @@ static void createStandardUtilityFunctions(unsigned numTypeInfos, /// a supplied a function which in turn will throw a foreign exception. /// @param module code for module instance /// @param builder builder instance -/// @param fpm a function pass manager holding optional IR to IR +/// @param fpm a function pass manager holding optional IR to IR /// transformations /// @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::Function *createUnwindExceptionTest(llvm::Module &module, + llvm::IRBuilder<> &builder, llvm::FunctionPassManager &fpm, std::string nativeThrowFunctName) { // Number of type infos to generate unsigned numTypeInfos = 6; - + // Initialze intrisics and external functions to use along with exception // and type info globals. createStandardUtilityFunctions(numTypeInfos, module, builder); llvm::Function *nativeThrowFunct = module.getFunction(nativeThrowFunctName); - - // Create exception throw function using the value ~0 to cause + + // Create exception throw function using the value ~0 to cause // foreign exceptions to be thrown. llvm::Function *throwFunct = createThrowExceptionFunction(module, builder, @@ -1503,9 +1503,9 @@ llvm::Function *createUnwindExceptionTest(llvm::Module &module, *nativeThrowFunct); // Inner function will catch even type infos unsigned innerExceptionTypesToCatch[] = {6, 2, 4}; - size_t numExceptionTypesToCatch = sizeof(innerExceptionTypesToCatch) / + size_t numExceptionTypesToCatch = sizeof(innerExceptionTypesToCatch) / sizeof(unsigned); - + // Generate inner function. llvm::Function *innerCatchFunct = createCatchWrappedInvokeFunction(module, builder, @@ -1514,12 +1514,12 @@ llvm::Function *createUnwindExceptionTest(llvm::Module &module, "innerCatchFunct", numExceptionTypesToCatch, innerExceptionTypesToCatch); - + // Outer function will catch odd type infos unsigned outerExceptionTypesToCatch[] = {3, 1, 5}; - numExceptionTypesToCatch = sizeof(outerExceptionTypesToCatch) / + numExceptionTypesToCatch = sizeof(outerExceptionTypesToCatch) / sizeof(unsigned); - + // Generate outer function llvm::Function *outerCatchFunct = createCatchWrappedInvokeFunction(module, builder, @@ -1528,7 +1528,7 @@ llvm::Function *createUnwindExceptionTest(llvm::Module &module, "outerCatchFunct", numExceptionTypesToCatch, outerExceptionTypesToCatch); - + // Return outer function to run return(outerCatchFunct); } @@ -1539,15 +1539,15 @@ class OurCppRunException : public std::runtime_error { public: OurCppRunException(const std::string reason) : std::runtime_error(reason) {} - + OurCppRunException (const OurCppRunException &toCopy) : std::runtime_error(toCopy) {} - + OurCppRunException &operator = (const OurCppRunException &toCopy) { return(reinterpret_cast<OurCppRunException&>( std::runtime_error::operator=(toCopy))); } - + ~OurCppRunException (void) throw () {} }; @@ -1562,7 +1562,7 @@ void throwCppException (int32_t ignoreIt) { typedef void (*OurExceptionThrowFunctType) (int32_t typeToThrow); -/// This is a test harness which runs test by executing generated +/// This is a test harness which runs test by executing generated /// 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. @@ -1572,15 +1572,15 @@ typedef void (*OurExceptionThrowFunctType) (int32_t typeToThrow); /// @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 - OurExceptionThrowFunctType functPtr = + OurExceptionThrowFunctType functPtr = reinterpret_cast<OurExceptionThrowFunctType>( reinterpret_cast<intptr_t>(engine->getPointerToFunction(function))); - + try { // Run test (*functPtr)(typeToThrow); @@ -1589,15 +1589,15 @@ void runExceptionThrow(llvm::ExecutionEngine *engine, // Catch foreign C++ exception fprintf(stderr, "\nrunExceptionThrow(...):In C++ catch OurCppRunException " - "with reason: %s.\n", + "with reason: %s.\n", exc.what()); } catch (...) { - // Catch all exceptions including our generated ones. This latter + // 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 + // 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"); @@ -1610,32 +1610,32 @@ void runExceptionThrow(llvm::ExecutionEngine *engine, typedef llvm::ArrayRef<llvm::Type*> TypeArray; -/// This initialization routine creates type info globals and +/// This initialization routine creates type info globals and /// adds external function declarations to module. /// @param numTypeInfos number of linear type info associated type info types /// to create as GlobalVariable instances, starting with the value 1. /// @param module code for module instance /// @param builder builder instance static void createStandardUtilityFunctions(unsigned numTypeInfos, - llvm::Module &module, + llvm::Module &module, llvm::IRBuilder<> &builder) { - + llvm::LLVMContext &context = module.getContext(); - + // Exception initializations - + // Setup exception catch state - ourExceptionNotThrownState = + ourExceptionNotThrownState = llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 0), - ourExceptionThrownState = + ourExceptionThrownState = llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 1), - ourExceptionCaughtState = + ourExceptionCaughtState = llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 2), - - - + + + // Create our type info type - ourTypeInfoType = llvm::StructType::get(context, + ourTypeInfoType = llvm::StructType::get(context, TypeArray(builder.getInt32Ty())); llvm::Type *caughtResultFieldTypes[] = { @@ -1648,47 +1648,47 @@ static void createStandardUtilityFunctions(unsigned numTypeInfos, TypeArray(caughtResultFieldTypes)); // Create OurException type - ourExceptionType = llvm::StructType::get(context, + ourExceptionType = llvm::StructType::get(context, TypeArray(ourTypeInfoType)); - + // Create portion of _Unwind_Exception type // // Note: Declaring only a portion of the _Unwind_Exception struct. // Does this cause problems? ourUnwindExceptionType = - llvm::StructType::get(context, + llvm::StructType::get(context, TypeArray(builder.getInt64Ty())); struct OurBaseException_t dummyException; - + // Calculate offset of OurException::unwindException member. - ourBaseFromUnwindOffset = ((uintptr_t) &dummyException) - + ourBaseFromUnwindOffset = ((uintptr_t) &dummyException) - ((uintptr_t) &(dummyException.unwindException)); - + #ifdef DEBUG fprintf(stderr, "createStandardUtilityFunctions(...):ourBaseFromUnwindOffset " "= %lld, sizeof(struct OurBaseException_t) - " "sizeof(struct _Unwind_Exception) = %lu.\n", ourBaseFromUnwindOffset, - sizeof(struct OurBaseException_t) - + sizeof(struct OurBaseException_t) - sizeof(struct _Unwind_Exception)); #endif - + size_t numChars = sizeof(ourBaseExcpClassChars) / sizeof(char); - + // Create our _Unwind_Exception::exception_class value ourBaseExceptionClass = genClass(ourBaseExcpClassChars, numChars); - + // Type infos - + std::string baseStr = "typeInfo", typeInfoName; std::ostringstream typeInfoNameBuilder; std::vector<llvm::Constant*> structVals; - + llvm::Constant *nextStruct; llvm::GlobalVariable *nextGlobal = NULL; - + // Generate each type info // // Note: First type info is not used. @@ -1696,202 +1696,202 @@ static void createStandardUtilityFunctions(unsigned numTypeInfos, structVals.clear(); structVals.push_back(llvm::ConstantInt::get(builder.getInt32Ty(), i)); nextStruct = llvm::ConstantStruct::get(ourTypeInfoType, structVals); - + typeInfoNameBuilder.str(""); typeInfoNameBuilder << baseStr << i; typeInfoName = typeInfoNameBuilder.str(); - + // Note: Does not seem to work without allocation - nextGlobal = - new llvm::GlobalVariable(module, - ourTypeInfoType, - true, - llvm::GlobalValue::ExternalLinkage, - nextStruct, + nextGlobal = + new llvm::GlobalVariable(module, + ourTypeInfoType, + true, + llvm::GlobalValue::ExternalLinkage, + nextStruct, typeInfoName); - + ourTypeInfoNames.push_back(typeInfoName); ourTypeInfoNamesIndex[i] = typeInfoName; } - + ArgNames argNames; ArgTypes argTypes; llvm::Function *funct = NULL; - + // print32Int - + llvm::Type *retType = builder.getVoidTy(); - + argTypes.clear(); argTypes.push_back(builder.getInt32Ty()); argTypes.push_back(builder.getInt8PtrTy()); - + argNames.clear(); - - createFunction(module, - retType, - argTypes, - argNames, - "print32Int", - llvm::Function::ExternalLinkage, - true, + + createFunction(module, + retType, + argTypes, + argNames, + "print32Int", + llvm::Function::ExternalLinkage, + true, false); - + // print64Int - + retType = builder.getVoidTy(); - + argTypes.clear(); argTypes.push_back(builder.getInt64Ty()); argTypes.push_back(builder.getInt8PtrTy()); - + argNames.clear(); - - createFunction(module, - retType, - argTypes, - argNames, - "print64Int", - llvm::Function::ExternalLinkage, - true, + + createFunction(module, + retType, + argTypes, + argNames, + "print64Int", + llvm::Function::ExternalLinkage, + true, false); - + // printStr - + retType = builder.getVoidTy(); - + argTypes.clear(); argTypes.push_back(builder.getInt8PtrTy()); - + argNames.clear(); - - createFunction(module, - retType, - argTypes, - argNames, - "printStr", - llvm::Function::ExternalLinkage, - true, + + createFunction(module, + retType, + argTypes, + argNames, + "printStr", + llvm::Function::ExternalLinkage, + true, false); - + // throwCppException - + retType = builder.getVoidTy(); - + argTypes.clear(); argTypes.push_back(builder.getInt32Ty()); - + argNames.clear(); - - createFunction(module, - retType, - argTypes, - argNames, - "throwCppException", - llvm::Function::ExternalLinkage, - true, + + createFunction(module, + retType, + argTypes, + argNames, + "throwCppException", + llvm::Function::ExternalLinkage, + true, false); - + // deleteOurException - + retType = builder.getVoidTy(); - + argTypes.clear(); argTypes.push_back(builder.getInt8PtrTy()); - + argNames.clear(); - - createFunction(module, - retType, - argTypes, - argNames, - "deleteOurException", - llvm::Function::ExternalLinkage, - true, + + createFunction(module, + retType, + argTypes, + argNames, + "deleteOurException", + llvm::Function::ExternalLinkage, + true, false); - + // createOurException - + retType = builder.getInt8PtrTy(); - + argTypes.clear(); argTypes.push_back(builder.getInt32Ty()); - + argNames.clear(); - - createFunction(module, - retType, - argTypes, - argNames, - "createOurException", - llvm::Function::ExternalLinkage, - true, + + createFunction(module, + retType, + argTypes, + argNames, + "createOurException", + llvm::Function::ExternalLinkage, + true, false); - + // _Unwind_RaiseException - + retType = builder.getInt32Ty(); - + argTypes.clear(); argTypes.push_back(builder.getInt8PtrTy()); - + argNames.clear(); - - funct = createFunction(module, - retType, - argTypes, - argNames, - "_Unwind_RaiseException", - llvm::Function::ExternalLinkage, - true, + + funct = createFunction(module, + retType, + argTypes, + argNames, + "_Unwind_RaiseException", + llvm::Function::ExternalLinkage, + true, false); - - funct->addFnAttr(llvm::Attribute::NoReturn); - + + funct->setDoesNotReturn(); + // _Unwind_Resume - + retType = builder.getInt32Ty(); - + argTypes.clear(); argTypes.push_back(builder.getInt8PtrTy()); - + argNames.clear(); - - funct = createFunction(module, - retType, - argTypes, - argNames, - "_Unwind_Resume", - llvm::Function::ExternalLinkage, - true, + + funct = createFunction(module, + retType, + argTypes, + argNames, + "_Unwind_Resume", + llvm::Function::ExternalLinkage, + true, false); - - funct->addFnAttr(llvm::Attribute::NoReturn); - + + funct->setDoesNotReturn(); + // ourPersonality - + retType = builder.getInt32Ty(); - + argTypes.clear(); argTypes.push_back(builder.getInt32Ty()); argTypes.push_back(builder.getInt32Ty()); argTypes.push_back(builder.getInt64Ty()); argTypes.push_back(builder.getInt8PtrTy()); argTypes.push_back(builder.getInt8PtrTy()); - + argNames.clear(); - - createFunction(module, - retType, - argTypes, - argNames, - "ourPersonality", - llvm::Function::ExternalLinkage, - true, + + createFunction(module, + retType, + argTypes, + argNames, + "ourPersonality", + llvm::Function::ExternalLinkage, + true, false); - + // llvm.eh.typeid.for intrinsic - + getDeclaration(&module, llvm::Intrinsic::eh_typeid_for); } @@ -1901,7 +1901,7 @@ static void createStandardUtilityFunctions(unsigned numTypeInfos, //===----------------------------------------------------------------------===// /// Demo main routine which takes the type info types to throw. A test will -/// be run for each given type info type. While type info types with the value +/// be run for each given type info type. While type info types with the value /// of -1 will trigger a foreign C++ exception to be thrown; type info types /// <= 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 @@ -1920,87 +1920,86 @@ int main(int argc, char *argv[]) { " for a full test.\n\n"); return(0); } - + // If not set, exception handling will not be turned on llvm::TargetOptions Opts; Opts.JITExceptionHandling = true; - + llvm::InitializeNativeTarget(); 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); - + // Build engine with JIT llvm::EngineBuilder factory(module); factory.setEngineKind(llvm::EngineKind::JIT); factory.setAllocateGVsWithCode(false); factory.setTargetOptions(Opts); llvm::ExecutionEngine *executionEngine = factory.create(); - + { llvm::FunctionPassManager fpm(module); - - // Set up the optimizer pipeline. + + // Set up the optimizer pipeline. // Start with registering info about how the // target lays out data structures. fpm.add(new llvm::DataLayout(*executionEngine->getDataLayout())); - + // Optimizations turned on #ifdef ADD_OPT_PASSES - + // Basic AliasAnslysis support for GVN. fpm.add(llvm::createBasicAliasAnalysisPass()); - + // Promote allocas to registers. fpm.add(llvm::createPromoteMemoryToRegisterPass()); - + // Do simple "peephole" optimizations and bit-twiddling optzns. fpm.add(llvm::createInstructionCombiningPass()); - + // Reassociate expressions. fpm.add(llvm::createReassociatePass()); - + // Eliminate Common SubExpressions. fpm.add(llvm::createGVNPass()); - - // Simplify the control flow graph (deleting unreachable + + // Simplify the control flow graph (deleting unreachable // blocks, etc). fpm.add(llvm::createCFGSimplificationPass()); #endif // ADD_OPT_PASSES - + fpm.doInitialization(); - + // Generate test code using function throwCppException(...) as // the function which throws foreign exceptions. - llvm::Function *toRun = - createUnwindExceptionTest(*module, - theBuilder, + llvm::Function *toRun = + createUnwindExceptionTest(*module, + theBuilder, fpm, "throwCppException"); - + fprintf(stderr, "\nBegin module dump:\n\n"); - + module->dump(); - + fprintf(stderr, "\nEnd module dump:\n"); - + fprintf(stderr, "\n\nBegin Test:\n"); - + for (int i = 1; i < argc; ++i) { // Run test for each argument whose value is the exception // type to throw. - runExceptionThrow(executionEngine, - toRun, + runExceptionThrow(executionEngine, + toRun, (unsigned) strtoul(argv[i], NULL, 10)); } - + fprintf(stderr, "\nEnd Test:\n\n"); - } - + } + delete executionEngine; - + return 0; } - |