diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2011-10-20 21:10:27 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2011-10-20 21:10:27 +0000 | 
| commit | 30815c536baacc07e925f0aef23a5395883173dc (patch) | |
| tree | 2cbcf22585e99f8a87d12d5ff94f392c0d266819 /examples/ExceptionDemo/ExceptionDemo.cpp | |
| parent | 411bd29eea3c360d5b48a18a17b5e87f5671af0e (diff) | |
Notes
Diffstat (limited to 'examples/ExceptionDemo/ExceptionDemo.cpp')
| -rw-r--r-- | examples/ExceptionDemo/ExceptionDemo.cpp | 301 | 
1 files changed, 186 insertions, 115 deletions
diff --git a/examples/ExceptionDemo/ExceptionDemo.cpp b/examples/ExceptionDemo/ExceptionDemo.cpp index e5d94514464c..20516a783b9d 100644 --- a/examples/ExceptionDemo/ExceptionDemo.cpp +++ b/examples/ExceptionDemo/ExceptionDemo.cpp @@ -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. @@ -56,11 +57,16 @@  #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; @@ -209,7 +218,7 @@ typedef std::vector<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.getInt8PtrTy()); +  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.getInt8PtrTy()); +  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.getInt8PtrTy(); -  *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.getInt8PtrTy()); +  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");    } @@ -1640,17 +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())); +                                          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)); @@ -1667,7 +1738,7 @@ static void createStandardUtilityFunctions(unsigned numTypeInfos,    // Calculate offset of OurException::unwindException member.    ourBaseFromUnwindOffset = ((uintptr_t) &dummyException) -  -  ((uintptr_t) &(dummyException.unwindException)); +                            ((uintptr_t) &(dummyException.unwindException));  #ifdef DEBUG    fprintf(stderr, @@ -1724,7 +1795,7 @@ static void createStandardUtilityFunctions(unsigned numTypeInfos,    // print32Int -  const llvm::Type *retType = builder.getVoidTy(); +  llvm::Type *retType = builder.getVoidTy();    argTypes.clear();    argTypes.push_back(builder.getInt32Ty());  | 
