Home | History | Annotate | Download | only in ExceptionDemo
      1 //===-- ExceptionDemo.cpp - An example using llvm Exceptions --------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // Demo program which implements an example LLVM exception implementation, and
     11 // shows several test cases including the handling of foreign exceptions.
     12 // It is run with type info types arguments to throw. A test will
     13 // be run for each given type info type. While type info types with the value
     14 // of -1 will trigger a foreign C++ exception to be thrown; type info types
     15 // <= 6 and >= 1 will cause the associated generated exceptions to be thrown
     16 // and caught by generated test functions; and type info types > 6
     17 // will result in exceptions which pass through to the test harness. All other
     18 // type info types are not supported and could cause a crash. In all cases,
     19 // the "finally" blocks of every generated test functions will executed
     20 // regardless of whether or not that test function ignores or catches the
     21 // thrown exception.
     22 //
     23 // examples:
     24 //
     25 // ExceptionDemo
     26 //
     27 //     causes a usage to be printed to stderr
     28 //
     29 // ExceptionDemo 2 3 7 -1
     30 //
     31 //     results in the following cases:
     32 //         - Value 2 causes an exception with a type info type of 2 to be
     33 //           thrown and caught by an inner generated test function.
     34 //         - Value 3 causes an exception with a type info type of 3 to be
     35 //           thrown and caught by an outer generated test function.
     36 //         - Value 7 causes an exception with a type info type of 7 to be
     37 //           thrown and NOT be caught by any generated function.
     38 //         - Value -1 causes a foreign C++ exception to be thrown and not be
     39 //           caught by any generated function
     40 //
     41 //     Cases -1 and 7 are caught by a C++ test harness where the validity of
     42 //         of a C++ catch(...) clause catching a generated exception with a
     43 //         type info type of 7 is explained by: example in rules 1.6.4 in
     44 //         http://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html (v1.22)
     45 //
     46 // This code uses code from the llvm compiler-rt project and the llvm
     47 // Kaleidoscope project.
     48 //
     49 //===----------------------------------------------------------------------===//
     50 
     51 #include "llvm/ADT/STLExtras.h"
     52 #include "llvm/BinaryFormat/Dwarf.h"
     53 #include "llvm/ExecutionEngine/MCJIT.h"
     54 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
     55 #include "llvm/IR/DataLayout.h"
     56 #include "llvm/IR/DerivedTypes.h"
     57 #include "llvm/IR/IRBuilder.h"
     58 #include "llvm/IR/Intrinsics.h"
     59 #include "llvm/IR/LLVMContext.h"
     60 #include "llvm/IR/LegacyPassManager.h"
     61 #include "llvm/IR/Module.h"
     62 #include "llvm/IR/Verifier.h"
     63 #include "llvm/Support/TargetSelect.h"
     64 #include "llvm/Target/TargetOptions.h"
     65 #include "llvm/Transforms/Scalar.h"
     66 
     67 // FIXME: Although all systems tested with (Linux, OS X), do not need this
     68 //        header file included. A user on ubuntu reported, undefined symbols
     69 //        for stderr, and fprintf, and the addition of this include fixed the
     70 //        issue for them. Given that LLVM's best practices include the goal
     71 //        of reducing the number of redundant header files included, the
     72 //        correct solution would be to find out why these symbols are not
     73 //        defined for the system in question, and fix the issue by finding out
     74 //        which LLVM header file, if any, would include these symbols.
     75 #include <cstdio>
     76 
     77 #include <sstream>
     78 #include <stdexcept>
     79 
     80 #include <inttypes.h>
     81 
     82 #include <unwind.h>
     83 
     84 #ifndef USE_GLOBAL_STR_CONSTS
     85 #define USE_GLOBAL_STR_CONSTS true
     86 #endif
     87 
     88 //
     89 // Example types
     90 //
     91 
     92 /// This is our simplistic type info
     93 struct OurExceptionType_t {
     94   /// type info type
     95   int type;
     96 };
     97 
     98 
     99 /// This is our Exception class which relies on a negative offset to calculate
    100 /// pointers to its instances from pointers to its unwindException member.
    101 ///
    102 /// Note: The above unwind.h defines struct _Unwind_Exception to be aligned
    103 ///       on a double word boundary. This is necessary to match the standard:
    104 ///       http://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html
    105 struct OurBaseException_t {
    106   struct OurExceptionType_t type;
    107 
    108   // Note: This is properly aligned in unwind.h
    109   struct _Unwind_Exception unwindException;
    110 };
    111 
    112 
    113 // Note: Not needed since we are C++
    114 typedef struct OurBaseException_t OurException;
    115 typedef struct _Unwind_Exception OurUnwindException;
    116 
    117 //
    118 // Various globals used to support typeinfo and generatted exceptions in
    119 // general
    120 //
    121 
    122 static std::map<std::string, llvm::Value*> namedValues;
    123 
    124 int64_t ourBaseFromUnwindOffset;
    125 
    126 const unsigned char ourBaseExcpClassChars[] =
    127 {'o', 'b', 'j', '\0', 'b', 'a', 's', '\0'};
    128 
    129 
    130 static uint64_t ourBaseExceptionClass = 0;
    131 
    132 static std::vector<std::string> ourTypeInfoNames;
    133 static std::map<int, std::string> ourTypeInfoNamesIndex;
    134 
    135 static llvm::StructType *ourTypeInfoType;
    136 static llvm::StructType *ourCaughtResultType;
    137 static llvm::StructType *ourExceptionType;
    138 static llvm::StructType *ourUnwindExceptionType;
    139 
    140 static llvm::ConstantInt *ourExceptionNotThrownState;
    141 static llvm::ConstantInt *ourExceptionThrownState;
    142 static llvm::ConstantInt *ourExceptionCaughtState;
    143 
    144 typedef std::vector<std::string> ArgNames;
    145 typedef std::vector<llvm::Type*> ArgTypes;
    146 
    147 //
    148 // Code Generation Utilities
    149 //
    150 
    151 /// Utility used to create a function, both declarations and definitions
    152 /// @param module for module instance
    153 /// @param retType function return type
    154 /// @param theArgTypes function's ordered argument types
    155 /// @param theArgNames function's ordered arguments needed if use of this
    156 ///        function corresponds to a function definition. Use empty
    157 ///        aggregate for function declarations.
    158 /// @param functName function name
    159 /// @param linkage function linkage
    160 /// @param declarationOnly for function declarations
    161 /// @param isVarArg function uses vararg arguments
    162 /// @returns function instance
    163 llvm::Function *createFunction(llvm::Module &module,
    164                                llvm::Type *retType,
    165                                const ArgTypes &theArgTypes,
    166                                const ArgNames &theArgNames,
    167                                const std::string &functName,
    168                                llvm::GlobalValue::LinkageTypes linkage,
    169                                bool declarationOnly,
    170                                bool isVarArg) {
    171   llvm::FunctionType *functType =
    172     llvm::FunctionType::get(retType, theArgTypes, isVarArg);
    173   llvm::Function *ret =
    174     llvm::Function::Create(functType, linkage, functName, &module);
    175   if (!ret || declarationOnly)
    176     return(ret);
    177 
    178   namedValues.clear();
    179   unsigned i = 0;
    180   for (llvm::Function::arg_iterator argIndex = ret->arg_begin();
    181        i != theArgNames.size();
    182        ++argIndex, ++i) {
    183 
    184     argIndex->setName(theArgNames[i]);
    185     namedValues[theArgNames[i]] = argIndex;
    186   }
    187 
    188   return(ret);
    189 }
    190 
    191 
    192 /// Create an alloca instruction in the entry block of
    193 /// the parent function.  This is used for mutable variables etc.
    194 /// @param function parent instance
    195 /// @param varName stack variable name
    196 /// @param type stack variable type
    197 /// @param initWith optional constant initialization value
    198 /// @returns AllocaInst instance
    199 static llvm::AllocaInst *createEntryBlockAlloca(llvm::Function &function,
    200                                                 const std::string &varName,
    201                                                 llvm::Type *type,
    202                                                 llvm::Constant *initWith = 0) {
    203   llvm::BasicBlock &block = function.getEntryBlock();
    204   llvm::IRBuilder<> tmp(&block, block.begin());
    205   llvm::AllocaInst *ret = tmp.CreateAlloca(type, 0, varName);
    206 
    207   if (initWith)
    208     tmp.CreateStore(initWith, ret);
    209 
    210   return(ret);
    211 }
    212 
    213 
    214 //
    215 // Code Generation Utilities End
    216 //
    217 
    218 //
    219 // Runtime C Library functions
    220 //
    221 
    222 namespace {
    223 template <typename Type_>
    224 uintptr_t ReadType(const uint8_t *&p) {
    225   Type_ value;
    226   memcpy(&value, p, sizeof(Type_));
    227   p += sizeof(Type_);
    228   return static_cast<uintptr_t>(value);
    229 }
    230 }
    231 
    232 // Note: using an extern "C" block so that static functions can be used
    233 extern "C" {
    234 
    235 // Note: Better ways to decide on bit width
    236 //
    237 /// Prints a 32 bit number, according to the format, to stderr.
    238 /// @param intToPrint integer to print
    239 /// @param format printf like format to use when printing
    240 void print32Int(int intToPrint, const char *format) {
    241   if (format) {
    242     // Note: No NULL check
    243     fprintf(stderr, format, intToPrint);
    244   }
    245   else {
    246     // Note: No NULL check
    247     fprintf(stderr, "::print32Int(...):NULL arg.\n");
    248   }
    249 }
    250 
    251 
    252 // Note: Better ways to decide on bit width
    253 //
    254 /// Prints a 64 bit number, according to the format, to stderr.
    255 /// @param intToPrint integer to print
    256 /// @param format printf like format to use when printing
    257 void print64Int(long int intToPrint, const char *format) {
    258   if (format) {
    259     // Note: No NULL check
    260     fprintf(stderr, format, intToPrint);
    261   }
    262   else {
    263     // Note: No NULL check
    264     fprintf(stderr, "::print64Int(...):NULL arg.\n");
    265   }
    266 }
    267 
    268 
    269 /// Prints a C string to stderr
    270 /// @param toPrint string to print
    271 void printStr(char *toPrint) {
    272   if (toPrint) {
    273     fprintf(stderr, "%s", toPrint);
    274   }
    275   else {
    276     fprintf(stderr, "::printStr(...):NULL arg.\n");
    277   }
    278 }
    279 
    280 
    281 /// Deletes the true previously allocated exception whose address
    282 /// is calculated from the supplied OurBaseException_t::unwindException
    283 /// member address. Handles (ignores), NULL pointers.
    284 /// @param expToDelete exception to delete
    285 void deleteOurException(OurUnwindException *expToDelete) {
    286 #ifdef DEBUG
    287   fprintf(stderr,
    288           "deleteOurException(...).\n");
    289 #endif
    290 
    291   if (expToDelete &&
    292       (expToDelete->exception_class == ourBaseExceptionClass)) {
    293 
    294     free(((char*) expToDelete) + ourBaseFromUnwindOffset);
    295   }
    296 }
    297 
    298 
    299 /// This function is the struct _Unwind_Exception API mandated delete function
    300 /// used by foreign exception handlers when deleting our exception
    301 /// (OurException), instances.
    302 /// @param reason See @link http://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html
    303 /// @unlink
    304 /// @param expToDelete exception instance to delete
    305 void deleteFromUnwindOurException(_Unwind_Reason_Code reason,
    306                                   OurUnwindException *expToDelete) {
    307 #ifdef DEBUG
    308   fprintf(stderr,
    309           "deleteFromUnwindOurException(...).\n");
    310 #endif
    311 
    312   deleteOurException(expToDelete);
    313 }
    314 
    315 
    316 /// Creates (allocates on the heap), an exception (OurException instance),
    317 /// of the supplied type info type.
    318 /// @param type type info type
    319 OurUnwindException *createOurException(int type) {
    320   size_t size = sizeof(OurException);
    321   OurException *ret = (OurException*) memset(malloc(size), 0, size);
    322   (ret->type).type = type;
    323   (ret->unwindException).exception_class = ourBaseExceptionClass;
    324   (ret->unwindException).exception_cleanup = deleteFromUnwindOurException;
    325 
    326   return(&(ret->unwindException));
    327 }
    328 
    329 
    330 /// Read a uleb128 encoded value and advance pointer
    331 /// See Variable Length Data in:
    332 /// @link http://dwarfstd.org/Dwarf3.pdf @unlink
    333 /// @param data reference variable holding memory pointer to decode from
    334 /// @returns decoded value
    335 static uintptr_t readULEB128(const uint8_t **data) {
    336   uintptr_t result = 0;
    337   uintptr_t shift = 0;
    338   unsigned char byte;
    339   const uint8_t *p = *data;
    340 
    341   do {
    342     byte = *p++;
    343     result |= (byte & 0x7f) << shift;
    344     shift += 7;
    345   }
    346   while (byte & 0x80);
    347 
    348   *data = p;
    349 
    350   return result;
    351 }
    352 
    353 
    354 /// Read a sleb128 encoded value and advance pointer
    355 /// See Variable Length Data in:
    356 /// @link http://dwarfstd.org/Dwarf3.pdf @unlink
    357 /// @param data reference variable holding memory pointer to decode from
    358 /// @returns decoded value
    359 static uintptr_t readSLEB128(const uint8_t **data) {
    360   uintptr_t result = 0;
    361   uintptr_t shift = 0;
    362   unsigned char byte;
    363   const uint8_t *p = *data;
    364 
    365   do {
    366     byte = *p++;
    367     result |= (byte & 0x7f) << shift;
    368     shift += 7;
    369   }
    370   while (byte & 0x80);
    371 
    372   *data = p;
    373 
    374   if ((byte & 0x40) && (shift < (sizeof(result) << 3))) {
    375     result |= (~0 << shift);
    376   }
    377 
    378   return result;
    379 }
    380 
    381 unsigned getEncodingSize(uint8_t Encoding) {
    382   if (Encoding == llvm::dwarf::DW_EH_PE_omit)
    383     return 0;
    384 
    385   switch (Encoding & 0x0F) {
    386   case llvm::dwarf::DW_EH_PE_absptr:
    387     return sizeof(uintptr_t);
    388   case llvm::dwarf::DW_EH_PE_udata2:
    389     return sizeof(uint16_t);
    390   case llvm::dwarf::DW_EH_PE_udata4:
    391     return sizeof(uint32_t);
    392   case llvm::dwarf::DW_EH_PE_udata8:
    393     return sizeof(uint64_t);
    394   case llvm::dwarf::DW_EH_PE_sdata2:
    395     return sizeof(int16_t);
    396   case llvm::dwarf::DW_EH_PE_sdata4:
    397     return sizeof(int32_t);
    398   case llvm::dwarf::DW_EH_PE_sdata8:
    399     return sizeof(int64_t);
    400   default:
    401     // not supported
    402     abort();
    403   }
    404 }
    405 
    406 /// Read a pointer encoded value and advance pointer
    407 /// See Variable Length Data in:
    408 /// @link http://dwarfstd.org/Dwarf3.pdf @unlink
    409 /// @param data reference variable holding memory pointer to decode from
    410 /// @param encoding dwarf encoding type
    411 /// @returns decoded value
    412 static uintptr_t readEncodedPointer(const uint8_t **data, uint8_t encoding) {
    413   uintptr_t result = 0;
    414   const uint8_t *p = *data;
    415 
    416   if (encoding == llvm::dwarf::DW_EH_PE_omit)
    417     return(result);
    418 
    419   // first get value
    420   switch (encoding & 0x0F) {
    421     case llvm::dwarf::DW_EH_PE_absptr:
    422       result = ReadType<uintptr_t>(p);
    423       break;
    424     case llvm::dwarf::DW_EH_PE_uleb128:
    425       result = readULEB128(&p);
    426       break;
    427       // Note: This case has not been tested
    428     case llvm::dwarf::DW_EH_PE_sleb128:
    429       result = readSLEB128(&p);
    430       break;
    431     case llvm::dwarf::DW_EH_PE_udata2:
    432       result = ReadType<uint16_t>(p);
    433       break;
    434     case llvm::dwarf::DW_EH_PE_udata4:
    435       result = ReadType<uint32_t>(p);
    436       break;
    437     case llvm::dwarf::DW_EH_PE_udata8:
    438       result = ReadType<uint64_t>(p);
    439       break;
    440     case llvm::dwarf::DW_EH_PE_sdata2:
    441       result = ReadType<int16_t>(p);
    442       break;
    443     case llvm::dwarf::DW_EH_PE_sdata4:
    444       result = ReadType<int32_t>(p);
    445       break;
    446     case llvm::dwarf::DW_EH_PE_sdata8:
    447       result = ReadType<int64_t>(p);
    448       break;
    449     default:
    450       // not supported
    451       abort();
    452       break;
    453   }
    454 
    455   // then add relative offset
    456   switch (encoding & 0x70) {
    457     case llvm::dwarf::DW_EH_PE_absptr:
    458       // do nothing
    459       break;
    460     case llvm::dwarf::DW_EH_PE_pcrel:
    461       result += (uintptr_t)(*data);
    462       break;
    463     case llvm::dwarf::DW_EH_PE_textrel:
    464     case llvm::dwarf::DW_EH_PE_datarel:
    465     case llvm::dwarf::DW_EH_PE_funcrel:
    466     case llvm::dwarf::DW_EH_PE_aligned:
    467     default:
    468       // not supported
    469       abort();
    470       break;
    471   }
    472 
    473   // then apply indirection
    474   if (encoding & llvm::dwarf::DW_EH_PE_indirect) {
    475     result = *((uintptr_t*)result);
    476   }
    477 
    478   *data = p;
    479 
    480   return result;
    481 }
    482 
    483 
    484 /// Deals with Dwarf actions matching our type infos
    485 /// (OurExceptionType_t instances). Returns whether or not a dwarf emitted
    486 /// action matches the supplied exception type. If such a match succeeds,
    487 /// the resultAction argument will be set with > 0 index value. Only
    488 /// corresponding llvm.eh.selector type info arguments, cleanup arguments
    489 /// are supported. Filters are not supported.
    490 /// See Variable Length Data in:
    491 /// @link http://dwarfstd.org/Dwarf3.pdf @unlink
    492 /// Also see @link http://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html @unlink
    493 /// @param resultAction reference variable which will be set with result
    494 /// @param classInfo our array of type info pointers (to globals)
    495 /// @param actionEntry index into above type info array or 0 (clean up).
    496 ///        We do not support filters.
    497 /// @param exceptionClass exception class (_Unwind_Exception::exception_class)
    498 ///        of thrown exception.
    499 /// @param exceptionObject thrown _Unwind_Exception instance.
    500 /// @returns whether or not a type info was found. False is returned if only
    501 ///          a cleanup was found
    502 static bool handleActionValue(int64_t *resultAction,
    503                               uint8_t TTypeEncoding,
    504                               const uint8_t *ClassInfo,
    505                               uintptr_t actionEntry,
    506                               uint64_t exceptionClass,
    507                               struct _Unwind_Exception *exceptionObject) {
    508   bool ret = false;
    509 
    510   if (!resultAction ||
    511       !exceptionObject ||
    512       (exceptionClass != ourBaseExceptionClass))
    513     return(ret);
    514 
    515   struct OurBaseException_t *excp = (struct OurBaseException_t*)
    516   (((char*) exceptionObject) + ourBaseFromUnwindOffset);
    517   struct OurExceptionType_t *excpType = &(excp->type);
    518   int type = excpType->type;
    519 
    520 #ifdef DEBUG
    521   fprintf(stderr,
    522           "handleActionValue(...): exceptionObject = <%p>, "
    523           "excp = <%p>.\n",
    524           (void*)exceptionObject,
    525           (void*)excp);
    526 #endif
    527 
    528   const uint8_t *actionPos = (uint8_t*) actionEntry,
    529   *tempActionPos;
    530   int64_t typeOffset = 0,
    531   actionOffset;
    532 
    533   for (int i = 0; true; ++i) {
    534     // Each emitted dwarf action corresponds to a 2 tuple of
    535     // type info address offset, and action offset to the next
    536     // emitted action.
    537     typeOffset = readSLEB128(&actionPos);
    538     tempActionPos = actionPos;
    539     actionOffset = readSLEB128(&tempActionPos);
    540 
    541 #ifdef DEBUG
    542     fprintf(stderr,
    543             "handleActionValue(...):typeOffset: <%" PRIi64 ">, "
    544             "actionOffset: <%" PRIi64 ">.\n",
    545             typeOffset,
    546             actionOffset);
    547 #endif
    548     assert((typeOffset >= 0) &&
    549            "handleActionValue(...):filters are not supported.");
    550 
    551     // Note: A typeOffset == 0 implies that a cleanup llvm.eh.selector
    552     //       argument has been matched.
    553     if (typeOffset > 0) {
    554 #ifdef DEBUG
    555       fprintf(stderr,
    556               "handleActionValue(...):actionValue <%d> found.\n",
    557               i);
    558 #endif
    559       unsigned EncSize = getEncodingSize(TTypeEncoding);
    560       const uint8_t *EntryP = ClassInfo - typeOffset * EncSize;
    561       uintptr_t P = readEncodedPointer(&EntryP, TTypeEncoding);
    562       struct OurExceptionType_t *ThisClassInfo =
    563         reinterpret_cast<struct OurExceptionType_t *>(P);
    564       if (ThisClassInfo->type == type) {
    565         *resultAction = i + 1;
    566         ret = true;
    567         break;
    568       }
    569     }
    570 
    571 #ifdef DEBUG
    572     fprintf(stderr,
    573             "handleActionValue(...):actionValue not found.\n");
    574 #endif
    575     if (!actionOffset)
    576       break;
    577 
    578     actionPos += actionOffset;
    579   }
    580 
    581   return(ret);
    582 }
    583 
    584 
    585 /// Deals with the Language specific data portion of the emitted dwarf code.
    586 /// See @link http://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html @unlink
    587 /// @param version unsupported (ignored), unwind version
    588 /// @param lsda language specific data area
    589 /// @param _Unwind_Action actions minimally supported unwind stage
    590 ///        (forced specifically not supported)
    591 /// @param exceptionClass exception class (_Unwind_Exception::exception_class)
    592 ///        of thrown exception.
    593 /// @param exceptionObject thrown _Unwind_Exception instance.
    594 /// @param context unwind system context
    595 /// @returns minimally supported unwinding control indicator
    596 static _Unwind_Reason_Code handleLsda(int version, const uint8_t *lsda,
    597                                       _Unwind_Action actions,
    598                                       _Unwind_Exception_Class exceptionClass,
    599                                       struct _Unwind_Exception *exceptionObject,
    600                                       struct _Unwind_Context *context) {
    601   _Unwind_Reason_Code ret = _URC_CONTINUE_UNWIND;
    602 
    603   if (!lsda)
    604     return(ret);
    605 
    606 #ifdef DEBUG
    607   fprintf(stderr,
    608           "handleLsda(...):lsda is non-zero.\n");
    609 #endif
    610 
    611   // Get the current instruction pointer and offset it before next
    612   // instruction in the current frame which threw the exception.
    613   uintptr_t pc = _Unwind_GetIP(context)-1;
    614 
    615   // Get beginning current frame's code (as defined by the
    616   // emitted dwarf code)
    617   uintptr_t funcStart = _Unwind_GetRegionStart(context);
    618   uintptr_t pcOffset = pc - funcStart;
    619   const uint8_t *ClassInfo = NULL;
    620 
    621   // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding
    622   //       dwarf emission
    623 
    624   // Parse LSDA header.
    625   uint8_t lpStartEncoding = *lsda++;
    626 
    627   if (lpStartEncoding != llvm::dwarf::DW_EH_PE_omit) {
    628     readEncodedPointer(&lsda, lpStartEncoding);
    629   }
    630 
    631   uint8_t ttypeEncoding = *lsda++;
    632   uintptr_t classInfoOffset;
    633 
    634   if (ttypeEncoding != llvm::dwarf::DW_EH_PE_omit) {
    635     // Calculate type info locations in emitted dwarf code which
    636     // were flagged by type info arguments to llvm.eh.selector
    637     // intrinsic
    638     classInfoOffset = readULEB128(&lsda);
    639     ClassInfo = lsda + classInfoOffset;
    640   }
    641 
    642   // Walk call-site table looking for range that
    643   // includes current PC.
    644 
    645   uint8_t         callSiteEncoding = *lsda++;
    646   uint32_t        callSiteTableLength = readULEB128(&lsda);
    647   const uint8_t   *callSiteTableStart = lsda;
    648   const uint8_t   *callSiteTableEnd = callSiteTableStart +
    649   callSiteTableLength;
    650   const uint8_t   *actionTableStart = callSiteTableEnd;
    651   const uint8_t   *callSitePtr = callSiteTableStart;
    652 
    653   while (callSitePtr < callSiteTableEnd) {
    654     uintptr_t start = readEncodedPointer(&callSitePtr,
    655                                          callSiteEncoding);
    656     uintptr_t length = readEncodedPointer(&callSitePtr,
    657                                           callSiteEncoding);
    658     uintptr_t landingPad = readEncodedPointer(&callSitePtr,
    659                                               callSiteEncoding);
    660 
    661     // Note: Action value
    662     uintptr_t actionEntry = readULEB128(&callSitePtr);
    663 
    664     if (exceptionClass != ourBaseExceptionClass) {
    665       // We have been notified of a foreign exception being thrown,
    666       // and we therefore need to execute cleanup landing pads
    667       actionEntry = 0;
    668     }
    669 
    670     if (landingPad == 0) {
    671 #ifdef DEBUG
    672       fprintf(stderr,
    673               "handleLsda(...): No landing pad found.\n");
    674 #endif
    675 
    676       continue; // no landing pad for this entry
    677     }
    678 
    679     if (actionEntry) {
    680       actionEntry += ((uintptr_t) actionTableStart) - 1;
    681     }
    682     else {
    683 #ifdef DEBUG
    684       fprintf(stderr,
    685               "handleLsda(...):No action table found.\n");
    686 #endif
    687     }
    688 
    689     bool exceptionMatched = false;
    690 
    691     if ((start <= pcOffset) && (pcOffset < (start + length))) {
    692 #ifdef DEBUG
    693       fprintf(stderr,
    694               "handleLsda(...): Landing pad found.\n");
    695 #endif
    696       int64_t actionValue = 0;
    697 
    698       if (actionEntry) {
    699         exceptionMatched = handleActionValue(&actionValue,
    700                                              ttypeEncoding,
    701                                              ClassInfo,
    702                                              actionEntry,
    703                                              exceptionClass,
    704                                              exceptionObject);
    705       }
    706 
    707       if (!(actions & _UA_SEARCH_PHASE)) {
    708 #ifdef DEBUG
    709         fprintf(stderr,
    710                 "handleLsda(...): installed landing pad "
    711                 "context.\n");
    712 #endif
    713 
    714         // Found landing pad for the PC.
    715         // Set Instruction Pointer to so we re-enter function
    716         // at landing pad. The landing pad is created by the
    717         // compiler to take two parameters in registers.
    718         _Unwind_SetGR(context,
    719                       __builtin_eh_return_data_regno(0),
    720                       (uintptr_t)exceptionObject);
    721 
    722         // Note: this virtual register directly corresponds
    723         //       to the return of the llvm.eh.selector intrinsic
    724         if (!actionEntry || !exceptionMatched) {
    725           // We indicate cleanup only
    726           _Unwind_SetGR(context,
    727                         __builtin_eh_return_data_regno(1),
    728                         0);
    729         }
    730         else {
    731           // Matched type info index of llvm.eh.selector intrinsic
    732           // passed here.
    733           _Unwind_SetGR(context,
    734                         __builtin_eh_return_data_regno(1),
    735                         actionValue);
    736         }
    737 
    738         // To execute landing pad set here
    739         _Unwind_SetIP(context, funcStart + landingPad);
    740         ret = _URC_INSTALL_CONTEXT;
    741       }
    742       else if (exceptionMatched) {
    743 #ifdef DEBUG
    744         fprintf(stderr,
    745                 "handleLsda(...): setting handler found.\n");
    746 #endif
    747         ret = _URC_HANDLER_FOUND;
    748       }
    749       else {
    750         // Note: Only non-clean up handlers are marked as
    751         //       found. Otherwise the clean up handlers will be
    752         //       re-found and executed during the clean up
    753         //       phase.
    754 #ifdef DEBUG
    755         fprintf(stderr,
    756                 "handleLsda(...): cleanup handler found.\n");
    757 #endif
    758       }
    759 
    760       break;
    761     }
    762   }
    763 
    764   return(ret);
    765 }
    766 
    767 
    768 /// This is the personality function which is embedded (dwarf emitted), in the
    769 /// dwarf unwind info block. Again see: JITDwarfEmitter.cpp.
    770 /// See @link http://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html @unlink
    771 /// @param version unsupported (ignored), unwind version
    772 /// @param _Unwind_Action actions minimally supported unwind stage
    773 ///        (forced specifically not supported)
    774 /// @param exceptionClass exception class (_Unwind_Exception::exception_class)
    775 ///        of thrown exception.
    776 /// @param exceptionObject thrown _Unwind_Exception instance.
    777 /// @param context unwind system context
    778 /// @returns minimally supported unwinding control indicator
    779 _Unwind_Reason_Code ourPersonality(int version, _Unwind_Action actions,
    780                                    _Unwind_Exception_Class exceptionClass,
    781                                    struct _Unwind_Exception *exceptionObject,
    782                                    struct _Unwind_Context *context) {
    783 #ifdef DEBUG
    784   fprintf(stderr,
    785           "We are in ourPersonality(...):actions is <%d>.\n",
    786           actions);
    787 
    788   if (actions & _UA_SEARCH_PHASE) {
    789     fprintf(stderr, "ourPersonality(...):In search phase.\n");
    790   }
    791   else {
    792     fprintf(stderr, "ourPersonality(...):In non-search phase.\n");
    793   }
    794 #endif
    795 
    796   const uint8_t *lsda = _Unwind_GetLanguageSpecificData(context);
    797 
    798 #ifdef DEBUG
    799   fprintf(stderr,
    800           "ourPersonality(...):lsda = <%p>.\n",
    801           (void*)lsda);
    802 #endif
    803 
    804   // The real work of the personality function is captured here
    805   return(handleLsda(version,
    806                     lsda,
    807                     actions,
    808                     exceptionClass,
    809                     exceptionObject,
    810                     context));
    811 }
    812 
    813 
    814 /// Generates our _Unwind_Exception class from a given character array.
    815 /// thereby handling arbitrary lengths (not in standard), and handling
    816 /// embedded \0s.
    817 /// See @link http://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html @unlink
    818 /// @param classChars char array to encode. NULL values not checkedf
    819 /// @param classCharsSize number of chars in classChars. Value is not checked.
    820 /// @returns class value
    821 uint64_t genClass(const unsigned char classChars[], size_t classCharsSize)
    822 {
    823   uint64_t ret = classChars[0];
    824 
    825   for (unsigned i = 1; i < classCharsSize; ++i) {
    826     ret <<= 8;
    827     ret += classChars[i];
    828   }
    829 
    830   return(ret);
    831 }
    832 
    833 } // extern "C"
    834 
    835 //
    836 // Runtime C Library functions End
    837 //
    838 
    839 //
    840 // Code generation functions
    841 //
    842 
    843 /// Generates code to print given constant string
    844 /// @param context llvm context
    845 /// @param module code for module instance
    846 /// @param builder builder instance
    847 /// @param toPrint string to print
    848 /// @param useGlobal A value of true (default) indicates a GlobalValue is
    849 ///        generated, and is used to hold the constant string. A value of
    850 ///        false indicates that the constant string will be stored on the
    851 ///        stack.
    852 void generateStringPrint(llvm::LLVMContext &context,
    853                          llvm::Module &module,
    854                          llvm::IRBuilder<> &builder,
    855                          std::string toPrint,
    856                          bool useGlobal = true) {
    857   llvm::Function *printFunct = module.getFunction("printStr");
    858 
    859   llvm::Value *stringVar;
    860   llvm::Constant *stringConstant =
    861   llvm::ConstantDataArray::getString(context, toPrint);
    862 
    863   if (useGlobal) {
    864     // Note: Does not work without allocation
    865     stringVar =
    866     new llvm::GlobalVariable(module,
    867                              stringConstant->getType(),
    868                              true,
    869                              llvm::GlobalValue::PrivateLinkage,
    870                              stringConstant,
    871                              "");
    872   }
    873   else {
    874     stringVar = builder.CreateAlloca(stringConstant->getType());
    875     builder.CreateStore(stringConstant, stringVar);
    876   }
    877 
    878   llvm::Value *cast = builder.CreatePointerCast(stringVar,
    879                                                 builder.getInt8PtrTy());
    880   builder.CreateCall(printFunct, cast);
    881 }
    882 
    883 
    884 /// Generates code to print given runtime integer according to constant
    885 /// string format, and a given print function.
    886 /// @param context llvm context
    887 /// @param module code for module instance
    888 /// @param builder builder instance
    889 /// @param printFunct function used to "print" integer
    890 /// @param toPrint string to print
    891 /// @param format printf like formating string for print
    892 /// @param useGlobal A value of true (default) indicates a GlobalValue is
    893 ///        generated, and is used to hold the constant string. A value of
    894 ///        false indicates that the constant string will be stored on the
    895 ///        stack.
    896 void generateIntegerPrint(llvm::LLVMContext &context,
    897                           llvm::Module &module,
    898                           llvm::IRBuilder<> &builder,
    899                           llvm::Function &printFunct,
    900                           llvm::Value &toPrint,
    901                           std::string format,
    902                           bool useGlobal = true) {
    903   llvm::Constant *stringConstant =
    904     llvm::ConstantDataArray::getString(context, format);
    905   llvm::Value *stringVar;
    906 
    907   if (useGlobal) {
    908     // Note: Does not seem to work without allocation
    909     stringVar =
    910     new llvm::GlobalVariable(module,
    911                              stringConstant->getType(),
    912                              true,
    913                              llvm::GlobalValue::PrivateLinkage,
    914                              stringConstant,
    915                              "");
    916   }
    917   else {
    918     stringVar = builder.CreateAlloca(stringConstant->getType());
    919     builder.CreateStore(stringConstant, stringVar);
    920   }
    921 
    922   llvm::Value *cast = builder.CreateBitCast(stringVar,
    923                                             builder.getInt8PtrTy());
    924   builder.CreateCall(&printFunct, {&toPrint, cast});
    925 }
    926 
    927 
    928 /// Generates code to handle finally block type semantics: always runs
    929 /// regardless of whether a thrown exception is passing through or the
    930 /// parent function is simply exiting. In addition to printing some state
    931 /// to stderr, this code will resume the exception handling--runs the
    932 /// unwind resume block, if the exception has not been previously caught
    933 /// by a catch clause, and will otherwise execute the end block (terminator
    934 /// block). In addition this function creates the corresponding function's
    935 /// stack storage for the exception pointer and catch flag status.
    936 /// @param context llvm context
    937 /// @param module code for module instance
    938 /// @param builder builder instance
    939 /// @param toAddTo parent function to add block to
    940 /// @param blockName block name of new "finally" block.
    941 /// @param functionId output id used for printing
    942 /// @param terminatorBlock terminator "end" block
    943 /// @param unwindResumeBlock unwind resume block
    944 /// @param exceptionCaughtFlag reference exception caught/thrown status storage
    945 /// @param exceptionStorage reference to exception pointer storage
    946 /// @param caughtResultStorage reference to landingpad result storage
    947 /// @returns newly created block
    948 static llvm::BasicBlock *createFinallyBlock(llvm::LLVMContext &context,
    949                                             llvm::Module &module,
    950                                             llvm::IRBuilder<> &builder,
    951                                             llvm::Function &toAddTo,
    952                                             std::string &blockName,
    953                                             std::string &functionId,
    954                                             llvm::BasicBlock &terminatorBlock,
    955                                             llvm::BasicBlock &unwindResumeBlock,
    956                                             llvm::Value **exceptionCaughtFlag,
    957                                             llvm::Value **exceptionStorage,
    958                                             llvm::Value **caughtResultStorage) {
    959   assert(exceptionCaughtFlag &&
    960          "ExceptionDemo::createFinallyBlock(...):exceptionCaughtFlag "
    961          "is NULL");
    962   assert(exceptionStorage &&
    963          "ExceptionDemo::createFinallyBlock(...):exceptionStorage "
    964          "is NULL");
    965   assert(caughtResultStorage &&
    966          "ExceptionDemo::createFinallyBlock(...):caughtResultStorage "
    967          "is NULL");
    968 
    969   *exceptionCaughtFlag = createEntryBlockAlloca(toAddTo,
    970                                          "exceptionCaught",
    971                                          ourExceptionNotThrownState->getType(),
    972                                          ourExceptionNotThrownState);
    973 
    974   llvm::PointerType *exceptionStorageType = builder.getInt8PtrTy();
    975   *exceptionStorage = createEntryBlockAlloca(toAddTo,
    976                                              "exceptionStorage",
    977                                              exceptionStorageType,
    978                                              llvm::ConstantPointerNull::get(
    979                                                exceptionStorageType));
    980   *caughtResultStorage = createEntryBlockAlloca(toAddTo,
    981                                               "caughtResultStorage",
    982                                               ourCaughtResultType,
    983                                               llvm::ConstantAggregateZero::get(
    984                                                 ourCaughtResultType));
    985 
    986   llvm::BasicBlock *ret = llvm::BasicBlock::Create(context,
    987                                                    blockName,
    988                                                    &toAddTo);
    989 
    990   builder.SetInsertPoint(ret);
    991 
    992   std::ostringstream bufferToPrint;
    993   bufferToPrint << "Gen: Executing finally block "
    994     << blockName << " in " << functionId << "\n";
    995   generateStringPrint(context,
    996                       module,
    997                       builder,
    998                       bufferToPrint.str(),
    999                       USE_GLOBAL_STR_CONSTS);
   1000 
   1001   llvm::SwitchInst *theSwitch = builder.CreateSwitch(builder.CreateLoad(
   1002                                                        *exceptionCaughtFlag),
   1003                                                      &terminatorBlock,
   1004                                                      2);
   1005   theSwitch->addCase(ourExceptionCaughtState, &terminatorBlock);
   1006   theSwitch->addCase(ourExceptionThrownState, &unwindResumeBlock);
   1007 
   1008   return(ret);
   1009 }
   1010 
   1011 
   1012 /// Generates catch block semantics which print a string to indicate type of
   1013 /// catch executed, sets an exception caught flag, and executes passed in
   1014 /// end block (terminator block).
   1015 /// @param context llvm context
   1016 /// @param module code for module instance
   1017 /// @param builder builder instance
   1018 /// @param toAddTo parent function to add block to
   1019 /// @param blockName block name of new "catch" block.
   1020 /// @param functionId output id used for printing
   1021 /// @param terminatorBlock terminator "end" block
   1022 /// @param exceptionCaughtFlag exception caught/thrown status
   1023 /// @returns newly created block
   1024 static llvm::BasicBlock *createCatchBlock(llvm::LLVMContext &context,
   1025                                           llvm::Module &module,
   1026                                           llvm::IRBuilder<> &builder,
   1027                                           llvm::Function &toAddTo,
   1028                                           std::string &blockName,
   1029                                           std::string &functionId,
   1030                                           llvm::BasicBlock &terminatorBlock,
   1031                                           llvm::Value &exceptionCaughtFlag) {
   1032 
   1033   llvm::BasicBlock *ret = llvm::BasicBlock::Create(context,
   1034                                                    blockName,
   1035                                                    &toAddTo);
   1036 
   1037   builder.SetInsertPoint(ret);
   1038 
   1039   std::ostringstream bufferToPrint;
   1040   bufferToPrint << "Gen: Executing catch block "
   1041   << blockName
   1042   << " in "
   1043   << functionId
   1044   << std::endl;
   1045   generateStringPrint(context,
   1046                       module,
   1047                       builder,
   1048                       bufferToPrint.str(),
   1049                       USE_GLOBAL_STR_CONSTS);
   1050   builder.CreateStore(ourExceptionCaughtState, &exceptionCaughtFlag);
   1051   builder.CreateBr(&terminatorBlock);
   1052 
   1053   return(ret);
   1054 }
   1055 
   1056 
   1057 /// Generates a function which invokes a function (toInvoke) and, whose
   1058 /// unwind block will "catch" the type info types correspondingly held in the
   1059 /// exceptionTypesToCatch argument. If the toInvoke function throws an
   1060 /// exception which does not match any type info types contained in
   1061 /// exceptionTypesToCatch, the generated code will call _Unwind_Resume
   1062 /// with the raised exception. On the other hand the generated code will
   1063 /// normally exit if the toInvoke function does not throw an exception.
   1064 /// The generated "finally" block is always run regardless of the cause of
   1065 /// the generated function exit.
   1066 /// The generated function is returned after being verified.
   1067 /// @param module code for module instance
   1068 /// @param builder builder instance
   1069 /// @param fpm a function pass manager holding optional IR to IR
   1070 ///        transformations
   1071 /// @param toInvoke inner function to invoke
   1072 /// @param ourId id used to printing purposes
   1073 /// @param numExceptionsToCatch length of exceptionTypesToCatch array
   1074 /// @param exceptionTypesToCatch array of type info types to "catch"
   1075 /// @returns generated function
   1076 static llvm::Function *createCatchWrappedInvokeFunction(
   1077     llvm::Module &module, llvm::IRBuilder<> &builder,
   1078     llvm::legacy::FunctionPassManager &fpm, llvm::Function &toInvoke,
   1079     std::string ourId, unsigned numExceptionsToCatch,
   1080     unsigned exceptionTypesToCatch[]) {
   1081 
   1082   llvm::LLVMContext &context = module.getContext();
   1083   llvm::Function *toPrint32Int = module.getFunction("print32Int");
   1084 
   1085   ArgTypes argTypes;
   1086   argTypes.push_back(builder.getInt32Ty());
   1087 
   1088   ArgNames argNames;
   1089   argNames.push_back("exceptTypeToThrow");
   1090 
   1091   llvm::Function *ret = createFunction(module,
   1092                                        builder.getVoidTy(),
   1093                                        argTypes,
   1094                                        argNames,
   1095                                        ourId,
   1096                                        llvm::Function::ExternalLinkage,
   1097                                        false,
   1098                                        false);
   1099 
   1100   // Block which calls invoke
   1101   llvm::BasicBlock *entryBlock = llvm::BasicBlock::Create(context,
   1102                                                           "entry",
   1103                                                           ret);
   1104   // Normal block for invoke
   1105   llvm::BasicBlock *normalBlock = llvm::BasicBlock::Create(context,
   1106                                                            "normal",
   1107                                                            ret);
   1108   // Unwind block for invoke
   1109   llvm::BasicBlock *exceptionBlock = llvm::BasicBlock::Create(context,
   1110                                                               "exception",
   1111                                                               ret);
   1112 
   1113   // Block which routes exception to correct catch handler block
   1114   llvm::BasicBlock *exceptionRouteBlock = llvm::BasicBlock::Create(context,
   1115                                                              "exceptionRoute",
   1116                                                              ret);
   1117 
   1118   // Foreign exception handler
   1119   llvm::BasicBlock *externalExceptionBlock = llvm::BasicBlock::Create(context,
   1120                                                           "externalException",
   1121                                                           ret);
   1122 
   1123   // Block which calls _Unwind_Resume
   1124   llvm::BasicBlock *unwindResumeBlock = llvm::BasicBlock::Create(context,
   1125                                                                "unwindResume",
   1126                                                                ret);
   1127 
   1128   // Clean up block which delete exception if needed
   1129   llvm::BasicBlock *endBlock = llvm::BasicBlock::Create(context, "end", ret);
   1130 
   1131   std::string nextName;
   1132   std::vector<llvm::BasicBlock*> catchBlocks(numExceptionsToCatch);
   1133   llvm::Value *exceptionCaughtFlag = NULL;
   1134   llvm::Value *exceptionStorage = NULL;
   1135   llvm::Value *caughtResultStorage = NULL;
   1136 
   1137   // Finally block which will branch to unwindResumeBlock if
   1138   // exception is not caught. Initializes/allocates stack locations.
   1139   llvm::BasicBlock *finallyBlock = createFinallyBlock(context,
   1140                                                       module,
   1141                                                       builder,
   1142                                                       *ret,
   1143                                                       nextName = "finally",
   1144                                                       ourId,
   1145                                                       *endBlock,
   1146                                                       *unwindResumeBlock,
   1147                                                       &exceptionCaughtFlag,
   1148                                                       &exceptionStorage,
   1149                                                       &caughtResultStorage
   1150                                                       );
   1151 
   1152   for (unsigned i = 0; i < numExceptionsToCatch; ++i) {
   1153     nextName = ourTypeInfoNames[exceptionTypesToCatch[i]];
   1154 
   1155     // One catch block per type info to be caught
   1156     catchBlocks[i] = createCatchBlock(context,
   1157                                       module,
   1158                                       builder,
   1159                                       *ret,
   1160                                       nextName,
   1161                                       ourId,
   1162                                       *finallyBlock,
   1163                                       *exceptionCaughtFlag);
   1164   }
   1165 
   1166   // Entry Block
   1167 
   1168   builder.SetInsertPoint(entryBlock);
   1169 
   1170   std::vector<llvm::Value*> args;
   1171   args.push_back(namedValues["exceptTypeToThrow"]);
   1172   builder.CreateInvoke(&toInvoke,
   1173                        normalBlock,
   1174                        exceptionBlock,
   1175                        args);
   1176 
   1177   // End Block
   1178 
   1179   builder.SetInsertPoint(endBlock);
   1180 
   1181   generateStringPrint(context,
   1182                       module,
   1183                       builder,
   1184                       "Gen: In end block: exiting in " + ourId + ".\n",
   1185                       USE_GLOBAL_STR_CONSTS);
   1186   llvm::Function *deleteOurException = module.getFunction("deleteOurException");
   1187 
   1188   // Note: function handles NULL exceptions
   1189   builder.CreateCall(deleteOurException,
   1190                      builder.CreateLoad(exceptionStorage));
   1191   builder.CreateRetVoid();
   1192 
   1193   // Normal Block
   1194 
   1195   builder.SetInsertPoint(normalBlock);
   1196 
   1197   generateStringPrint(context,
   1198                       module,
   1199                       builder,
   1200                       "Gen: No exception in " + ourId + "!\n",
   1201                       USE_GLOBAL_STR_CONSTS);
   1202 
   1203   // Finally block is always called
   1204   builder.CreateBr(finallyBlock);
   1205 
   1206   // Unwind Resume Block
   1207 
   1208   builder.SetInsertPoint(unwindResumeBlock);
   1209 
   1210   builder.CreateResume(builder.CreateLoad(caughtResultStorage));
   1211 
   1212   // Exception Block
   1213 
   1214   builder.SetInsertPoint(exceptionBlock);
   1215 
   1216   llvm::Function *personality = module.getFunction("ourPersonality");
   1217   ret->setPersonalityFn(personality);
   1218 
   1219   llvm::LandingPadInst *caughtResult =
   1220     builder.CreateLandingPad(ourCaughtResultType,
   1221                              numExceptionsToCatch,
   1222                              "landingPad");
   1223 
   1224   caughtResult->setCleanup(true);
   1225 
   1226   for (unsigned i = 0; i < numExceptionsToCatch; ++i) {
   1227     // Set up type infos to be caught
   1228     caughtResult->addClause(module.getGlobalVariable(
   1229                              ourTypeInfoNames[exceptionTypesToCatch[i]]));
   1230   }
   1231 
   1232   llvm::Value *unwindException = builder.CreateExtractValue(caughtResult, 0);
   1233   llvm::Value *retTypeInfoIndex = builder.CreateExtractValue(caughtResult, 1);
   1234 
   1235   // FIXME: Redundant storage which, beyond utilizing value of
   1236   //        caughtResultStore for unwindException storage, may be alleviated
   1237   //        altogether with a block rearrangement
   1238   builder.CreateStore(caughtResult, caughtResultStorage);
   1239   builder.CreateStore(unwindException, exceptionStorage);
   1240   builder.CreateStore(ourExceptionThrownState, exceptionCaughtFlag);
   1241 
   1242   // Retrieve exception_class member from thrown exception
   1243   // (_Unwind_Exception instance). This member tells us whether or not
   1244   // the exception is foreign.
   1245   llvm::Value *unwindExceptionClass =
   1246       builder.CreateLoad(builder.CreateStructGEP(
   1247           ourUnwindExceptionType,
   1248           builder.CreatePointerCast(unwindException,
   1249                                     ourUnwindExceptionType->getPointerTo()),
   1250           0));
   1251 
   1252   // Branch to the externalExceptionBlock if the exception is foreign or
   1253   // to a catch router if not. Either way the finally block will be run.
   1254   builder.CreateCondBr(builder.CreateICmpEQ(unwindExceptionClass,
   1255                             llvm::ConstantInt::get(builder.getInt64Ty(),
   1256                                                    ourBaseExceptionClass)),
   1257                        exceptionRouteBlock,
   1258                        externalExceptionBlock);
   1259 
   1260   // External Exception Block
   1261 
   1262   builder.SetInsertPoint(externalExceptionBlock);
   1263 
   1264   generateStringPrint(context,
   1265                       module,
   1266                       builder,
   1267                       "Gen: Foreign exception received.\n",
   1268                       USE_GLOBAL_STR_CONSTS);
   1269 
   1270   // Branch to the finally block
   1271   builder.CreateBr(finallyBlock);
   1272 
   1273   // Exception Route Block
   1274 
   1275   builder.SetInsertPoint(exceptionRouteBlock);
   1276 
   1277   // Casts exception pointer (_Unwind_Exception instance) to parent
   1278   // (OurException instance).
   1279   //
   1280   // Note: ourBaseFromUnwindOffset is usually negative
   1281   llvm::Value *typeInfoThrown = builder.CreatePointerCast(
   1282                                   builder.CreateConstGEP1_64(unwindException,
   1283                                                        ourBaseFromUnwindOffset),
   1284                                   ourExceptionType->getPointerTo());
   1285 
   1286   // Retrieve thrown exception type info type
   1287   //
   1288   // Note: Index is not relative to pointer but instead to structure
   1289   //       unlike a true getelementptr (GEP) instruction
   1290   typeInfoThrown = builder.CreateStructGEP(ourExceptionType, typeInfoThrown, 0);
   1291 
   1292   llvm::Value *typeInfoThrownType =
   1293       builder.CreateStructGEP(builder.getInt8PtrTy(), typeInfoThrown, 0);
   1294 
   1295   generateIntegerPrint(context,
   1296                        module,
   1297                        builder,
   1298                        *toPrint32Int,
   1299                        *(builder.CreateLoad(typeInfoThrownType)),
   1300                        "Gen: Exception type <%d> received (stack unwound) "
   1301                        " in " +
   1302                        ourId +
   1303                        ".\n",
   1304                        USE_GLOBAL_STR_CONSTS);
   1305 
   1306   // Route to matched type info catch block or run cleanup finally block
   1307   llvm::SwitchInst *switchToCatchBlock = builder.CreateSwitch(retTypeInfoIndex,
   1308                                                           finallyBlock,
   1309                                                           numExceptionsToCatch);
   1310 
   1311   unsigned nextTypeToCatch;
   1312 
   1313   for (unsigned i = 1; i <= numExceptionsToCatch; ++i) {
   1314     nextTypeToCatch = i - 1;
   1315     switchToCatchBlock->addCase(llvm::ConstantInt::get(
   1316                                    llvm::Type::getInt32Ty(context), i),
   1317                                 catchBlocks[nextTypeToCatch]);
   1318   }
   1319 
   1320   llvm::verifyFunction(*ret);
   1321   fpm.run(*ret);
   1322 
   1323   return(ret);
   1324 }
   1325 
   1326 
   1327 /// Generates function which throws either an exception matched to a runtime
   1328 /// determined type info type (argument to generated function), or if this
   1329 /// runtime value matches nativeThrowType, throws a foreign exception by
   1330 /// calling nativeThrowFunct.
   1331 /// @param module code for module instance
   1332 /// @param builder builder instance
   1333 /// @param fpm a function pass manager holding optional IR to IR
   1334 ///        transformations
   1335 /// @param ourId id used to printing purposes
   1336 /// @param nativeThrowType a runtime argument of this value results in
   1337 ///        nativeThrowFunct being called to generate/throw exception.
   1338 /// @param nativeThrowFunct function which will throw a foreign exception
   1339 ///        if the above nativeThrowType matches generated function's arg.
   1340 /// @returns generated function
   1341 static llvm::Function *
   1342 createThrowExceptionFunction(llvm::Module &module, llvm::IRBuilder<> &builder,
   1343                              llvm::legacy::FunctionPassManager &fpm,
   1344                              std::string ourId, int32_t nativeThrowType,
   1345                              llvm::Function &nativeThrowFunct) {
   1346   llvm::LLVMContext &context = module.getContext();
   1347   namedValues.clear();
   1348   ArgTypes unwindArgTypes;
   1349   unwindArgTypes.push_back(builder.getInt32Ty());
   1350   ArgNames unwindArgNames;
   1351   unwindArgNames.push_back("exceptTypeToThrow");
   1352 
   1353   llvm::Function *ret = createFunction(module,
   1354                                        builder.getVoidTy(),
   1355                                        unwindArgTypes,
   1356                                        unwindArgNames,
   1357                                        ourId,
   1358                                        llvm::Function::ExternalLinkage,
   1359                                        false,
   1360                                        false);
   1361 
   1362   // Throws either one of our exception or a native C++ exception depending
   1363   // on a runtime argument value containing a type info type.
   1364   llvm::BasicBlock *entryBlock = llvm::BasicBlock::Create(context,
   1365                                                           "entry",
   1366                                                           ret);
   1367   // Throws a foreign exception
   1368   llvm::BasicBlock *nativeThrowBlock = llvm::BasicBlock::Create(context,
   1369                                                                 "nativeThrow",
   1370                                                                 ret);
   1371   // Throws one of our Exceptions
   1372   llvm::BasicBlock *generatedThrowBlock = llvm::BasicBlock::Create(context,
   1373                                                              "generatedThrow",
   1374                                                              ret);
   1375   // Retrieved runtime type info type to throw
   1376   llvm::Value *exceptionType = namedValues["exceptTypeToThrow"];
   1377 
   1378   // nativeThrowBlock block
   1379 
   1380   builder.SetInsertPoint(nativeThrowBlock);
   1381 
   1382   // Throws foreign exception
   1383   builder.CreateCall(&nativeThrowFunct, exceptionType);
   1384   builder.CreateUnreachable();
   1385 
   1386   // entry block
   1387 
   1388   builder.SetInsertPoint(entryBlock);
   1389 
   1390   llvm::Function *toPrint32Int = module.getFunction("print32Int");
   1391   generateIntegerPrint(context,
   1392                        module,
   1393                        builder,
   1394                        *toPrint32Int,
   1395                        *exceptionType,
   1396                        "\nGen: About to throw exception type <%d> in " +
   1397                        ourId +
   1398                        ".\n",
   1399                        USE_GLOBAL_STR_CONSTS);
   1400 
   1401   // Switches on runtime type info type value to determine whether or not
   1402   // a foreign exception is thrown. Defaults to throwing one of our
   1403   // generated exceptions.
   1404   llvm::SwitchInst *theSwitch = builder.CreateSwitch(exceptionType,
   1405                                                      generatedThrowBlock,
   1406                                                      1);
   1407 
   1408   theSwitch->addCase(llvm::ConstantInt::get(llvm::Type::getInt32Ty(context),
   1409                                             nativeThrowType),
   1410                      nativeThrowBlock);
   1411 
   1412   // generatedThrow block
   1413 
   1414   builder.SetInsertPoint(generatedThrowBlock);
   1415 
   1416   llvm::Function *createOurException = module.getFunction("createOurException");
   1417   llvm::Function *raiseOurException = module.getFunction(
   1418                                         "_Unwind_RaiseException");
   1419 
   1420   // Creates exception to throw with runtime type info type.
   1421   llvm::Value *exception = builder.CreateCall(createOurException,
   1422                                               namedValues["exceptTypeToThrow"]);
   1423 
   1424   // Throw generated Exception
   1425   builder.CreateCall(raiseOurException, exception);
   1426   builder.CreateUnreachable();
   1427 
   1428   llvm::verifyFunction(*ret);
   1429   fpm.run(*ret);
   1430 
   1431   return(ret);
   1432 }
   1433 
   1434 static void createStandardUtilityFunctions(unsigned numTypeInfos,
   1435                                            llvm::Module &module,
   1436                                            llvm::IRBuilder<> &builder);
   1437 
   1438 /// Creates test code by generating and organizing these functions into the
   1439 /// test case. The test case consists of an outer function setup to invoke
   1440 /// an inner function within an environment having multiple catch and single
   1441 /// finally blocks. This inner function is also setup to invoke a throw
   1442 /// function within an evironment similar in nature to the outer function's
   1443 /// catch and finally blocks. Each of these two functions catch mutually
   1444 /// exclusive subsets (even or odd) of the type info types configured
   1445 /// for this this. All generated functions have a runtime argument which
   1446 /// holds a type info type to throw that each function takes and passes it
   1447 /// to the inner one if such a inner function exists. This type info type is
   1448 /// looked at by the generated throw function to see whether or not it should
   1449 /// throw a generated exception with the same type info type, or instead call
   1450 /// a supplied a function which in turn will throw a foreign exception.
   1451 /// @param module code for module instance
   1452 /// @param builder builder instance
   1453 /// @param fpm a function pass manager holding optional IR to IR
   1454 ///        transformations
   1455 /// @param nativeThrowFunctName name of external function which will throw
   1456 ///        a foreign exception
   1457 /// @returns outermost generated test function.
   1458 llvm::Function *
   1459 createUnwindExceptionTest(llvm::Module &module, llvm::IRBuilder<> &builder,
   1460                           llvm::legacy::FunctionPassManager &fpm,
   1461                           std::string nativeThrowFunctName) {
   1462   // Number of type infos to generate
   1463   unsigned numTypeInfos = 6;
   1464 
   1465   // Initialze intrisics and external functions to use along with exception
   1466   // and type info globals.
   1467   createStandardUtilityFunctions(numTypeInfos,
   1468                                  module,
   1469                                  builder);
   1470   llvm::Function *nativeThrowFunct = module.getFunction(nativeThrowFunctName);
   1471 
   1472   // Create exception throw function using the value ~0 to cause
   1473   // foreign exceptions to be thrown.
   1474   llvm::Function *throwFunct = createThrowExceptionFunction(module,
   1475                                                             builder,
   1476                                                             fpm,
   1477                                                             "throwFunct",
   1478                                                             ~0,
   1479                                                             *nativeThrowFunct);
   1480   // Inner function will catch even type infos
   1481   unsigned innerExceptionTypesToCatch[] = {6, 2, 4};
   1482   size_t numExceptionTypesToCatch = sizeof(innerExceptionTypesToCatch) /
   1483                                     sizeof(unsigned);
   1484 
   1485   // Generate inner function.
   1486   llvm::Function *innerCatchFunct = createCatchWrappedInvokeFunction(module,
   1487                                                     builder,
   1488                                                     fpm,
   1489                                                     *throwFunct,
   1490                                                     "innerCatchFunct",
   1491                                                     numExceptionTypesToCatch,
   1492                                                     innerExceptionTypesToCatch);
   1493 
   1494   // Outer function will catch odd type infos
   1495   unsigned outerExceptionTypesToCatch[] = {3, 1, 5};
   1496   numExceptionTypesToCatch = sizeof(outerExceptionTypesToCatch) /
   1497   sizeof(unsigned);
   1498 
   1499   // Generate outer function
   1500   llvm::Function *outerCatchFunct = createCatchWrappedInvokeFunction(module,
   1501                                                     builder,
   1502                                                     fpm,
   1503                                                     *innerCatchFunct,
   1504                                                     "outerCatchFunct",
   1505                                                     numExceptionTypesToCatch,
   1506                                                     outerExceptionTypesToCatch);
   1507 
   1508   // Return outer function to run
   1509   return(outerCatchFunct);
   1510 }
   1511 
   1512 namespace {
   1513 /// Represents our foreign exceptions
   1514 class OurCppRunException : public std::runtime_error {
   1515 public:
   1516   OurCppRunException(const std::string reason) :
   1517   std::runtime_error(reason) {}
   1518 
   1519   OurCppRunException (const OurCppRunException &toCopy) :
   1520   std::runtime_error(toCopy) {}
   1521 
   1522   OurCppRunException &operator = (const OurCppRunException &toCopy) {
   1523     return(reinterpret_cast<OurCppRunException&>(
   1524                                  std::runtime_error::operator=(toCopy)));
   1525   }
   1526 
   1527   ~OurCppRunException(void) throw() override {}
   1528 };
   1529 } // end anonymous namespace
   1530 
   1531 /// Throws foreign C++ exception.
   1532 /// @param ignoreIt unused parameter that allows function to match implied
   1533 ///        generated function contract.
   1534 extern "C"
   1535 void throwCppException (int32_t ignoreIt) {
   1536   throw(OurCppRunException("thrown by throwCppException(...)"));
   1537 }
   1538 
   1539 typedef void (*OurExceptionThrowFunctType) (int32_t typeToThrow);
   1540 
   1541 /// This is a test harness which runs test by executing generated
   1542 /// function with a type info type to throw. Harness wraps the execution
   1543 /// of generated function in a C++ try catch clause.
   1544 /// @param engine execution engine to use for executing generated function.
   1545 ///        This demo program expects this to be a JIT instance for demo
   1546 ///        purposes.
   1547 /// @param function generated test function to run
   1548 /// @param typeToThrow type info type of generated exception to throw, or
   1549 ///        indicator to cause foreign exception to be thrown.
   1550 static
   1551 void runExceptionThrow(llvm::ExecutionEngine *engine,
   1552                        llvm::Function *function,
   1553                        int32_t typeToThrow) {
   1554 
   1555   // Find test's function pointer
   1556   OurExceptionThrowFunctType functPtr =
   1557     reinterpret_cast<OurExceptionThrowFunctType>(
   1558        reinterpret_cast<intptr_t>(engine->getPointerToFunction(function)));
   1559 
   1560   try {
   1561     // Run test
   1562     (*functPtr)(typeToThrow);
   1563   }
   1564   catch (OurCppRunException exc) {
   1565     // Catch foreign C++ exception
   1566     fprintf(stderr,
   1567             "\nrunExceptionThrow(...):In C++ catch OurCppRunException "
   1568             "with reason: %s.\n",
   1569             exc.what());
   1570   }
   1571   catch (...) {
   1572     // Catch all exceptions including our generated ones. This latter
   1573     // functionality works according to the example in rules 1.6.4 of
   1574     // http://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html (v1.22),
   1575     // given that these will be exceptions foreign to C++
   1576     // (the _Unwind_Exception::exception_class should be different from
   1577     // the one used by C++).
   1578     fprintf(stderr,
   1579             "\nrunExceptionThrow(...):In C++ catch all.\n");
   1580   }
   1581 }
   1582 
   1583 //
   1584 // End test functions
   1585 //
   1586 
   1587 typedef llvm::ArrayRef<llvm::Type*> TypeArray;
   1588 
   1589 /// This initialization routine creates type info globals and
   1590 /// adds external function declarations to module.
   1591 /// @param numTypeInfos number of linear type info associated type info types
   1592 ///        to create as GlobalVariable instances, starting with the value 1.
   1593 /// @param module code for module instance
   1594 /// @param builder builder instance
   1595 static void createStandardUtilityFunctions(unsigned numTypeInfos,
   1596                                            llvm::Module &module,
   1597                                            llvm::IRBuilder<> &builder) {
   1598 
   1599   llvm::LLVMContext &context = module.getContext();
   1600 
   1601   // Exception initializations
   1602 
   1603   // Setup exception catch state
   1604   ourExceptionNotThrownState =
   1605     llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 0),
   1606   ourExceptionThrownState =
   1607     llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 1),
   1608   ourExceptionCaughtState =
   1609     llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 2),
   1610 
   1611 
   1612 
   1613   // Create our type info type
   1614   ourTypeInfoType = llvm::StructType::get(context,
   1615                                           TypeArray(builder.getInt32Ty()));
   1616 
   1617   llvm::Type *caughtResultFieldTypes[] = {
   1618     builder.getInt8PtrTy(),
   1619     builder.getInt32Ty()
   1620   };
   1621 
   1622   // Create our landingpad result type
   1623   ourCaughtResultType = llvm::StructType::get(context,
   1624                                             TypeArray(caughtResultFieldTypes));
   1625 
   1626   // Create OurException type
   1627   ourExceptionType = llvm::StructType::get(context,
   1628                                            TypeArray(ourTypeInfoType));
   1629 
   1630   // Create portion of _Unwind_Exception type
   1631   //
   1632   // Note: Declaring only a portion of the _Unwind_Exception struct.
   1633   //       Does this cause problems?
   1634   ourUnwindExceptionType =
   1635     llvm::StructType::get(context,
   1636                     TypeArray(builder.getInt64Ty()));
   1637 
   1638   struct OurBaseException_t dummyException;
   1639 
   1640   // Calculate offset of OurException::unwindException member.
   1641   ourBaseFromUnwindOffset = ((uintptr_t) &dummyException) -
   1642                             ((uintptr_t) &(dummyException.unwindException));
   1643 
   1644 #ifdef DEBUG
   1645   fprintf(stderr,
   1646           "createStandardUtilityFunctions(...):ourBaseFromUnwindOffset "
   1647           "= %" PRIi64 ", sizeof(struct OurBaseException_t) - "
   1648           "sizeof(struct _Unwind_Exception) = %lu.\n",
   1649           ourBaseFromUnwindOffset,
   1650           sizeof(struct OurBaseException_t) -
   1651           sizeof(struct _Unwind_Exception));
   1652 #endif
   1653 
   1654   size_t numChars = sizeof(ourBaseExcpClassChars) / sizeof(char);
   1655 
   1656   // Create our _Unwind_Exception::exception_class value
   1657   ourBaseExceptionClass = genClass(ourBaseExcpClassChars, numChars);
   1658 
   1659   // Type infos
   1660 
   1661   std::string baseStr = "typeInfo", typeInfoName;
   1662   std::ostringstream typeInfoNameBuilder;
   1663   std::vector<llvm::Constant*> structVals;
   1664 
   1665   llvm::Constant *nextStruct;
   1666 
   1667   // Generate each type info
   1668   //
   1669   // Note: First type info is not used.
   1670   for (unsigned i = 0; i <= numTypeInfos; ++i) {
   1671     structVals.clear();
   1672     structVals.push_back(llvm::ConstantInt::get(builder.getInt32Ty(), i));
   1673     nextStruct = llvm::ConstantStruct::get(ourTypeInfoType, structVals);
   1674 
   1675     typeInfoNameBuilder.str("");
   1676     typeInfoNameBuilder << baseStr << i;
   1677     typeInfoName = typeInfoNameBuilder.str();
   1678 
   1679     // Note: Does not seem to work without allocation
   1680     new llvm::GlobalVariable(module,
   1681                              ourTypeInfoType,
   1682                              true,
   1683                              llvm::GlobalValue::ExternalLinkage,
   1684                              nextStruct,
   1685                              typeInfoName);
   1686 
   1687     ourTypeInfoNames.push_back(typeInfoName);
   1688     ourTypeInfoNamesIndex[i] = typeInfoName;
   1689   }
   1690 
   1691   ArgNames argNames;
   1692   ArgTypes argTypes;
   1693   llvm::Function *funct = NULL;
   1694 
   1695   // print32Int
   1696 
   1697   llvm::Type *retType = builder.getVoidTy();
   1698 
   1699   argTypes.clear();
   1700   argTypes.push_back(builder.getInt32Ty());
   1701   argTypes.push_back(builder.getInt8PtrTy());
   1702 
   1703   argNames.clear();
   1704 
   1705   createFunction(module,
   1706                  retType,
   1707                  argTypes,
   1708                  argNames,
   1709                  "print32Int",
   1710                  llvm::Function::ExternalLinkage,
   1711                  true,
   1712                  false);
   1713 
   1714   // print64Int
   1715 
   1716   retType = builder.getVoidTy();
   1717 
   1718   argTypes.clear();
   1719   argTypes.push_back(builder.getInt64Ty());
   1720   argTypes.push_back(builder.getInt8PtrTy());
   1721 
   1722   argNames.clear();
   1723 
   1724   createFunction(module,
   1725                  retType,
   1726                  argTypes,
   1727                  argNames,
   1728                  "print64Int",
   1729                  llvm::Function::ExternalLinkage,
   1730                  true,
   1731                  false);
   1732 
   1733   // printStr
   1734 
   1735   retType = builder.getVoidTy();
   1736 
   1737   argTypes.clear();
   1738   argTypes.push_back(builder.getInt8PtrTy());
   1739 
   1740   argNames.clear();
   1741 
   1742   createFunction(module,
   1743                  retType,
   1744                  argTypes,
   1745                  argNames,
   1746                  "printStr",
   1747                  llvm::Function::ExternalLinkage,
   1748                  true,
   1749                  false);
   1750 
   1751   // throwCppException
   1752 
   1753   retType = builder.getVoidTy();
   1754 
   1755   argTypes.clear();
   1756   argTypes.push_back(builder.getInt32Ty());
   1757 
   1758   argNames.clear();
   1759 
   1760   createFunction(module,
   1761                  retType,
   1762                  argTypes,
   1763                  argNames,
   1764                  "throwCppException",
   1765                  llvm::Function::ExternalLinkage,
   1766                  true,
   1767                  false);
   1768 
   1769   // deleteOurException
   1770 
   1771   retType = builder.getVoidTy();
   1772 
   1773   argTypes.clear();
   1774   argTypes.push_back(builder.getInt8PtrTy());
   1775 
   1776   argNames.clear();
   1777 
   1778   createFunction(module,
   1779                  retType,
   1780                  argTypes,
   1781                  argNames,
   1782                  "deleteOurException",
   1783                  llvm::Function::ExternalLinkage,
   1784                  true,
   1785                  false);
   1786 
   1787   // createOurException
   1788 
   1789   retType = builder.getInt8PtrTy();
   1790 
   1791   argTypes.clear();
   1792   argTypes.push_back(builder.getInt32Ty());
   1793 
   1794   argNames.clear();
   1795 
   1796   createFunction(module,
   1797                  retType,
   1798                  argTypes,
   1799                  argNames,
   1800                  "createOurException",
   1801                  llvm::Function::ExternalLinkage,
   1802                  true,
   1803                  false);
   1804 
   1805   // _Unwind_RaiseException
   1806 
   1807   retType = builder.getInt32Ty();
   1808 
   1809   argTypes.clear();
   1810   argTypes.push_back(builder.getInt8PtrTy());
   1811 
   1812   argNames.clear();
   1813 
   1814   funct = createFunction(module,
   1815                          retType,
   1816                          argTypes,
   1817                          argNames,
   1818                          "_Unwind_RaiseException",
   1819                          llvm::Function::ExternalLinkage,
   1820                          true,
   1821                          false);
   1822 
   1823   funct->setDoesNotReturn();
   1824 
   1825   // _Unwind_Resume
   1826 
   1827   retType = builder.getInt32Ty();
   1828 
   1829   argTypes.clear();
   1830   argTypes.push_back(builder.getInt8PtrTy());
   1831 
   1832   argNames.clear();
   1833 
   1834   funct = createFunction(module,
   1835                          retType,
   1836                          argTypes,
   1837                          argNames,
   1838                          "_Unwind_Resume",
   1839                          llvm::Function::ExternalLinkage,
   1840                          true,
   1841                          false);
   1842 
   1843   funct->setDoesNotReturn();
   1844 
   1845   // ourPersonality
   1846 
   1847   retType = builder.getInt32Ty();
   1848 
   1849   argTypes.clear();
   1850   argTypes.push_back(builder.getInt32Ty());
   1851   argTypes.push_back(builder.getInt32Ty());
   1852   argTypes.push_back(builder.getInt64Ty());
   1853   argTypes.push_back(builder.getInt8PtrTy());
   1854   argTypes.push_back(builder.getInt8PtrTy());
   1855 
   1856   argNames.clear();
   1857 
   1858   createFunction(module,
   1859                  retType,
   1860                  argTypes,
   1861                  argNames,
   1862                  "ourPersonality",
   1863                  llvm::Function::ExternalLinkage,
   1864                  true,
   1865                  false);
   1866 
   1867   // llvm.eh.typeid.for intrinsic
   1868 
   1869   getDeclaration(&module, llvm::Intrinsic::eh_typeid_for);
   1870 }
   1871 
   1872 
   1873 //===----------------------------------------------------------------------===//
   1874 // Main test driver code.
   1875 //===----------------------------------------------------------------------===//
   1876 
   1877 /// Demo main routine which takes the type info types to throw. A test will
   1878 /// be run for each given type info type. While type info types with the value
   1879 /// of -1 will trigger a foreign C++ exception to be thrown; type info types
   1880 /// <= 6 and >= 1 will be caught by test functions; and type info types > 6
   1881 /// will result in exceptions which pass through to the test harness. All other
   1882 /// type info types are not supported and could cause a crash.
   1883 int main(int argc, char *argv[]) {
   1884   if (argc == 1) {
   1885     fprintf(stderr,
   1886             "\nUsage: ExceptionDemo <exception type to throw> "
   1887             "[<type 2>...<type n>].\n"
   1888             "   Each type must have the value of 1 - 6 for "
   1889             "generated exceptions to be caught;\n"
   1890             "   the value -1 for foreign C++ exceptions to be "
   1891             "generated and thrown;\n"
   1892             "   or the values > 6 for exceptions to be ignored.\n"
   1893             "\nTry: ExceptionDemo 2 3 7 -1\n"
   1894             "   for a full test.\n\n");
   1895     return(0);
   1896   }
   1897 
   1898   // If not set, exception handling will not be turned on
   1899   llvm::TargetOptions Opts;
   1900 
   1901   llvm::InitializeNativeTarget();
   1902   llvm::InitializeNativeTargetAsmPrinter();
   1903   llvm::LLVMContext Context;
   1904   llvm::IRBuilder<> theBuilder(Context);
   1905 
   1906   // Make the module, which holds all the code.
   1907   std::unique_ptr<llvm::Module> Owner =
   1908       llvm::make_unique<llvm::Module>("my cool jit", Context);
   1909   llvm::Module *module = Owner.get();
   1910 
   1911   std::unique_ptr<llvm::RTDyldMemoryManager> MemMgr(new llvm::SectionMemoryManager());
   1912 
   1913   // Build engine with JIT
   1914   llvm::EngineBuilder factory(std::move(Owner));
   1915   factory.setEngineKind(llvm::EngineKind::JIT);
   1916   factory.setTargetOptions(Opts);
   1917   factory.setMCJITMemoryManager(std::move(MemMgr));
   1918   llvm::ExecutionEngine *executionEngine = factory.create();
   1919 
   1920   {
   1921     llvm::legacy::FunctionPassManager fpm(module);
   1922 
   1923     // Set up the optimizer pipeline.
   1924     // Start with registering info about how the
   1925     // target lays out data structures.
   1926     module->setDataLayout(executionEngine->getDataLayout());
   1927 
   1928     // Optimizations turned on
   1929 #ifdef ADD_OPT_PASSES
   1930 
   1931     // Basic AliasAnslysis support for GVN.
   1932     fpm.add(llvm::createBasicAliasAnalysisPass());
   1933 
   1934     // Promote allocas to registers.
   1935     fpm.add(llvm::createPromoteMemoryToRegisterPass());
   1936 
   1937     // Do simple "peephole" optimizations and bit-twiddling optzns.
   1938     fpm.add(llvm::createInstructionCombiningPass());
   1939 
   1940     // Reassociate expressions.
   1941     fpm.add(llvm::createReassociatePass());
   1942 
   1943     // Eliminate Common SubExpressions.
   1944     fpm.add(llvm::createGVNPass());
   1945 
   1946     // Simplify the control flow graph (deleting unreachable
   1947     // blocks, etc).
   1948     fpm.add(llvm::createCFGSimplificationPass());
   1949 #endif  // ADD_OPT_PASSES
   1950 
   1951     fpm.doInitialization();
   1952 
   1953     // Generate test code using function throwCppException(...) as
   1954     // the function which throws foreign exceptions.
   1955     llvm::Function *toRun =
   1956     createUnwindExceptionTest(*module,
   1957                               theBuilder,
   1958                               fpm,
   1959                               "throwCppException");
   1960 
   1961     executionEngine->finalizeObject();
   1962 
   1963     fprintf(stderr, "\nBegin module dump:\n\n");
   1964 
   1965     module->dump();
   1966 
   1967     fprintf(stderr, "\nEnd module dump:\n");
   1968 
   1969     fprintf(stderr, "\n\nBegin Test:\n");
   1970 
   1971     for (int i = 1; i < argc; ++i) {
   1972       // Run test for each argument whose value is the exception
   1973       // type to throw.
   1974       runExceptionThrow(executionEngine,
   1975                         toRun,
   1976                         (unsigned) strtoul(argv[i], NULL, 10));
   1977     }
   1978 
   1979     fprintf(stderr, "\nEnd Test:\n\n");
   1980   }
   1981 
   1982   delete executionEngine;
   1983 
   1984   return 0;
   1985 }
   1986