[WebAssembly] Update a stale comment. NFC.
[oota-llvm.git] / examples / ExceptionDemo / ExceptionDemo.cpp
index 264ef5481f5718442feef11c00e41ccb25dcf1a3..444ee2649fa734f2c700d55c61a85a66948345ae 100644 (file)
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/Analysis/Verifier.h"
-#include "llvm/ExecutionEngine/ExecutionEngine.h"
-#include "llvm/ExecutionEngine/JIT.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/IR/Verifier.h"
+#include "llvm/ExecutionEngine/MCJIT.h"
+#include "llvm/ExecutionEngine/SectionMemoryManager.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/LegacyPassManager.h"
 #include "llvm/IR/Module.h"
-#include "llvm/PassManager.h"
 #include "llvm/Support/Dwarf.h"
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/Target/TargetOptions.h"
@@ -76,6 +77,7 @@
 #include <sstream>
 #include <stdexcept>
 
+#include <inttypes.h>
 
 #ifndef USE_GLOBAL_STR_CONSTS
 #define USE_GLOBAL_STR_CONSTS true
@@ -318,7 +320,7 @@ void printStr(char *toPrint) {
 }
 
 
-/// Deletes the true previosly allocated exception whose address
+/// Deletes the true previously allocated exception whose address
 /// is calculated from the supplied OurBaseException_t::unwindException
 /// member address. Handles (ignores), NULL pointers.
 /// @param expToDelete exception to delete
@@ -339,7 +341,7 @@ void deleteOurException(OurUnwindException *expToDelete) {
 /// This function is the struct _Unwind_Exception API mandated delete function
 /// used by foreign exception handlers when deleting our exception
 /// (OurException), instances.
-/// @param reason @link http://mentorembedded.github.com/cxx-abi/abi-eh.html
+/// @param reason See @link http://mentorembedded.github.com/cxx-abi/abi-eh.html
 /// @unlink
 /// @param expToDelete exception instance to delete
 void deleteFromUnwindOurException(_Unwind_Reason_Code reason,
@@ -418,6 +420,30 @@ static uintptr_t readSLEB128(const uint8_t **data) {
   return result;
 }
 
+unsigned getEncodingSize(uint8_t Encoding) {
+  if (Encoding == llvm::dwarf::DW_EH_PE_omit)
+    return 0;
+
+  switch (Encoding & 0x0F) {
+  case llvm::dwarf::DW_EH_PE_absptr:
+    return sizeof(uintptr_t);
+  case llvm::dwarf::DW_EH_PE_udata2:
+    return sizeof(uint16_t);
+  case llvm::dwarf::DW_EH_PE_udata4:
+    return sizeof(uint32_t);
+  case llvm::dwarf::DW_EH_PE_udata8:
+    return sizeof(uint64_t);
+  case llvm::dwarf::DW_EH_PE_sdata2:
+    return sizeof(int16_t);
+  case llvm::dwarf::DW_EH_PE_sdata4:
+    return sizeof(int32_t);
+  case llvm::dwarf::DW_EH_PE_sdata8:
+    return sizeof(int64_t);
+  default:
+    // not supported
+    abort();
+  }
+}
 
 /// Read a pointer encoded value and advance pointer
 /// See Variable Length Data in:
@@ -523,7 +549,8 @@ static uintptr_t readEncodedPointer(const uint8_t **data, uint8_t encoding) {
 /// @returns whether or not a type info was found. False is returned if only
 ///          a cleanup was found
 static bool handleActionValue(int64_t *resultAction,
-                              struct OurExceptionType_t **classInfo,
+                              uint8_t TTypeEncoding,
+                              const uint8_t *ClassInfo,
                               uintptr_t actionEntry,
                               uint64_t exceptionClass,
                               struct _Unwind_Exception *exceptionObject) {
@@ -543,8 +570,8 @@ static bool handleActionValue(int64_t *resultAction,
   fprintf(stderr,
           "handleActionValue(...): exceptionObject = <%p>, "
           "excp = <%p>.\n",
-          exceptionObject,
-          excp);
+          (void*)exceptionObject,
+          (void*)excp);
 #endif
 
   const uint8_t *actionPos = (uint8_t*) actionEntry,
@@ -562,8 +589,8 @@ static bool handleActionValue(int64_t *resultAction,
 
 #ifdef DEBUG
     fprintf(stderr,
-            "handleActionValue(...):typeOffset: <%lld>, "
-            "actionOffset: <%lld>.\n",
+            "handleActionValue(...):typeOffset: <%" PRIi64 ">, "
+            "actionOffset: <%" PRIi64 ">.\n",
             typeOffset,
             actionOffset);
 #endif
@@ -572,16 +599,22 @@ static bool handleActionValue(int64_t *resultAction,
 
     // Note: A typeOffset == 0 implies that a cleanup llvm.eh.selector
     //       argument has been matched.
-    if ((typeOffset > 0) &&
-        (type == (classInfo[-typeOffset])->type)) {
+    if (typeOffset > 0) {
 #ifdef DEBUG
       fprintf(stderr,
               "handleActionValue(...):actionValue <%d> found.\n",
               i);
 #endif
-      *resultAction = i + 1;
-      ret = true;
-      break;
+      unsigned EncSize = getEncodingSize(TTypeEncoding);
+      const uint8_t *EntryP = ClassInfo - typeOffset * EncSize;
+      uintptr_t P = readEncodedPointer(&EntryP, TTypeEncoding);
+      struct OurExceptionType_t *ThisClassInfo =
+        reinterpret_cast<struct OurExceptionType_t *>(P);
+      if (ThisClassInfo->type == type) {
+        *resultAction = i + 1;
+        ret = true;
+        break;
+      }
     }
 
 #ifdef DEBUG
@@ -633,7 +666,7 @@ static _Unwind_Reason_Code handleLsda(int version,
   // emitted dwarf code)
   uintptr_t funcStart = _Unwind_GetRegionStart(context);
   uintptr_t pcOffset = pc - funcStart;
-  struct OurExceptionType_t **classInfo = NULL;
+  const uint8_t *ClassInfo = NULL;
 
   // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding
   //       dwarf emission
@@ -653,7 +686,7 @@ static _Unwind_Reason_Code handleLsda(int version,
     // were flagged by type info arguments to llvm.eh.selector
     // intrinsic
     classInfoOffset = readULEB128(&lsda);
-    classInfo = (struct OurExceptionType_t**) (lsda + classInfoOffset);
+    ClassInfo = lsda + classInfoOffset;
   }
 
   // Walk call-site table looking for range that
@@ -714,7 +747,8 @@ static _Unwind_Reason_Code handleLsda(int version,
 
       if (actionEntry) {
         exceptionMatched = handleActionValue(&actionValue,
-                                             classInfo,
+                                             ttypeEncoding,
+                                             ClassInfo,
                                              actionEntry,
                                              exceptionClass,
                                              exceptionObject);
@@ -815,7 +849,7 @@ _Unwind_Reason_Code ourPersonality(int version,
 #ifdef DEBUG
   fprintf(stderr,
           "ourPersonality(...):lsda = <%p>.\n",
-          lsda);
+          (void*)lsda);
 #endif
 
   // The real work of the personality function is captured here
@@ -883,7 +917,7 @@ void generateStringPrint(llvm::LLVMContext &context,
     new llvm::GlobalVariable(module,
                              stringConstant->getType(),
                              true,
-                             llvm::GlobalValue::LinkerPrivateLinkage,
+                             llvm::GlobalValue::PrivateLinkage,
                              stringConstant,
                              "");
   }
@@ -927,7 +961,7 @@ void generateIntegerPrint(llvm::LLVMContext &context,
     new llvm::GlobalVariable(module,
                              stringConstant->getType(),
                              true,
-                             llvm::GlobalValue::LinkerPrivateLinkage,
+                             llvm::GlobalValue::PrivateLinkage,
                              stringConstant,
                              "");
   }
@@ -938,7 +972,7 @@ void generateIntegerPrint(llvm::LLVMContext &context,
 
   llvm::Value *cast = builder.CreateBitCast(stringVar,
                                             builder.getInt8PtrTy());
-  builder.CreateCall2(&printFunct, &toPrint, cast);
+  builder.CreateCall(&printFunct, {&toPrint, cast});
 }
 
 
@@ -1090,14 +1124,11 @@ static llvm::BasicBlock *createCatchBlock(llvm::LLVMContext &context,
 /// @param numExceptionsToCatch length of exceptionTypesToCatch array
 /// @param exceptionTypesToCatch array of type info types to "catch"
 /// @returns generated function
-static
-llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
-                                             llvm::IRBuilder<> &builder,
-                                             llvm::FunctionPassManager &fpm,
-                                             llvm::Function &toInvoke,
-                                             std::string ourId,
-                                             unsigned numExceptionsToCatch,
-                                             unsigned exceptionTypesToCatch[]) {
+static llvm::Function *createCatchWrappedInvokeFunction(
+    llvm::Module &module, llvm::IRBuilder<> &builder,
+    llvm::legacy::FunctionPassManager &fpm, llvm::Function &toInvoke,
+    std::string ourId, unsigned numExceptionsToCatch,
+    unsigned exceptionTypesToCatch[]) {
 
   llvm::LLVMContext &context = module.getContext();
   llvm::Function *toPrint32Int = module.getFunction("print32Int");
@@ -1234,10 +1265,10 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
   builder.SetInsertPoint(exceptionBlock);
 
   llvm::Function *personality = module.getFunction("ourPersonality");
+  ret->setPersonalityFn(personality);
 
   llvm::LandingPadInst *caughtResult =
     builder.CreateLandingPad(ourCaughtResultType,
-                             personality,
                              numExceptionsToCatch,
                              "landingPad");
 
@@ -1263,10 +1294,11 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
   // (_Unwind_Exception instance). This member tells us whether or not
   // the exception is foreign.
   llvm::Value *unwindExceptionClass =
-    builder.CreateLoad(builder.CreateStructGEP(
-             builder.CreatePointerCast(unwindException,
-                                       ourUnwindExceptionType->getPointerTo()),
-                                               0));
+      builder.CreateLoad(builder.CreateStructGEP(
+          ourUnwindExceptionType,
+          builder.CreatePointerCast(unwindException,
+                                    ourUnwindExceptionType->getPointerTo()),
+          0));
 
   // Branch to the externalExceptionBlock if the exception is foreign or
   // to a catch router if not. Either way the finally block will be run.
@@ -1306,10 +1338,10 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
   //
   // Note: Index is not relative to pointer but instead to structure
   //       unlike a true getelementptr (GEP) instruction
-  typeInfoThrown = builder.CreateStructGEP(typeInfoThrown, 0);
+  typeInfoThrown = builder.CreateStructGEP(ourExceptionType, typeInfoThrown, 0);
 
   llvm::Value *typeInfoThrownType =
-  builder.CreateStructGEP(typeInfoThrown, 0);
+      builder.CreateStructGEP(builder.getInt8PtrTy(), typeInfoThrown, 0);
 
   generateIntegerPrint(context,
                        module,
@@ -1357,13 +1389,11 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
 /// @param nativeThrowFunct function which will throw a foreign exception
 ///        if the above nativeThrowType matches generated function's arg.
 /// @returns generated function
-static
-llvm::Function *createThrowExceptionFunction(llvm::Module &module,
-                                             llvm::IRBuilder<> &builder,
-                                             llvm::FunctionPassManager &fpm,
-                                             std::string ourId,
-                                             int32_t nativeThrowType,
-                                             llvm::Function &nativeThrowFunct) {
+static llvm::Function *
+createThrowExceptionFunction(llvm::Module &module, llvm::IRBuilder<> &builder,
+                             llvm::legacy::FunctionPassManager &fpm,
+                             std::string ourId, int32_t nativeThrowType,
+                             llvm::Function &nativeThrowFunct) {
   llvm::LLVMContext &context = module.getContext();
   namedValues.clear();
   ArgTypes unwindArgTypes;
@@ -1476,10 +1506,10 @@ static void createStandardUtilityFunctions(unsigned numTypeInfos,
 /// @param nativeThrowFunctName name of external function which will throw
 ///        a foreign exception
 /// @returns outermost generated test function.
-llvm::Function *createUnwindExceptionTest(llvm::Module &module,
-                                          llvm::IRBuilder<> &builder,
-                                          llvm::FunctionPassManager &fpm,
-                                          std::string nativeThrowFunctName) {
+llvm::Function *
+createUnwindExceptionTest(llvm::Module &module, llvm::IRBuilder<> &builder,
+                          llvm::legacy::FunctionPassManager &fpm,
+                          std::string nativeThrowFunctName) {
   // Number of type infos to generate
   unsigned numTypeInfos = 6;
 
@@ -1530,7 +1560,7 @@ llvm::Function *createUnwindExceptionTest(llvm::Module &module,
   return(outerCatchFunct);
 }
 
-
+namespace {
 /// Represents our foreign exceptions
 class OurCppRunException : public std::runtime_error {
 public:
@@ -1545,9 +1575,9 @@ public:
                                  std::runtime_error::operator=(toCopy)));
   }
 
-  ~OurCppRunException (void) throw () {}
+  ~OurCppRunException(void) throw() override {}
 };
-
+} // end anonymous namespace
 
 /// Throws foreign C++ exception.
 /// @param ignoreIt unused parameter that allows function to match implied
@@ -1665,7 +1695,7 @@ static void createStandardUtilityFunctions(unsigned numTypeInfos,
 #ifdef DEBUG
   fprintf(stderr,
           "createStandardUtilityFunctions(...):ourBaseFromUnwindOffset "
-          "= %lld, sizeof(struct OurBaseException_t) - "
+          "= %" PRIi64 ", sizeof(struct OurBaseException_t) - "
           "sizeof(struct _Unwind_Exception) = %lu.\n",
           ourBaseFromUnwindOffset,
           sizeof(struct OurBaseException_t) -
@@ -1918,29 +1948,33 @@ int main(int argc, char *argv[]) {
 
   // If not set, exception handling will not be turned on
   llvm::TargetOptions Opts;
-  Opts.JITExceptionHandling = true;
 
   llvm::InitializeNativeTarget();
+  llvm::InitializeNativeTargetAsmPrinter();
   llvm::LLVMContext &context = llvm::getGlobalContext();
   llvm::IRBuilder<> theBuilder(context);
 
   // Make the module, which holds all the code.
-  llvm::Module *module = new llvm::Module("my cool jit", context);
+  std::unique_ptr<llvm::Module> Owner =
+      llvm::make_unique<llvm::Module>("my cool jit", context);
+  llvm::Module *module = Owner.get();
+
+  std::unique_ptr<llvm::RTDyldMemoryManager> MemMgr(new llvm::SectionMemoryManager());
 
   // Build engine with JIT
-  llvm::EngineBuilder factory(module);
+  llvm::EngineBuilder factory(std::move(Owner));
   factory.setEngineKind(llvm::EngineKind::JIT);
-  factory.setAllocateGVsWithCode(false);
   factory.setTargetOptions(Opts);
+  factory.setMCJITMemoryManager(std::move(MemMgr));
   llvm::ExecutionEngine *executionEngine = factory.create();
 
   {
-    llvm::FunctionPassManager fpm(module);
+    llvm::legacy::FunctionPassManager fpm(module);
 
     // Set up the optimizer pipeline.
     // Start with registering info about how the
     // target lays out data structures.
-    fpm.add(new llvm::DataLayout(*executionEngine->getDataLayout()));
+    module->setDataLayout(executionEngine->getDataLayout());
 
     // Optimizations turned on
 #ifdef ADD_OPT_PASSES
@@ -1975,6 +2009,8 @@ int main(int argc, char *argv[]) {
                               fpm,
                               "throwCppException");
 
+    executionEngine->finalizeObject();
+
     fprintf(stderr, "\nBegin module dump:\n\n");
 
     module->dump();