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