+ // Clean up block which delete exception if needed
+ llvm::BasicBlock *endBlock = llvm::BasicBlock::Create(context, "end", ret);
+
+ std::string nextName;
+ std::vector<llvm::BasicBlock*> catchBlocks(numExceptionsToCatch);
+ llvm::Value *exceptionCaughtFlag = NULL;
+ llvm::Value *exceptionStorage = NULL;
+ llvm::Value *caughtResultStorage = NULL;
+
+ // Finally block which will branch to unwindResumeBlock if
+ // exception is not caught. Initializes/allocates stack locations.
+ llvm::BasicBlock *finallyBlock = createFinallyBlock(context,
+ module,
+ builder,
+ *ret,
+ nextName = "finally",
+ ourId,
+ *endBlock,
+ *unwindResumeBlock,
+ &exceptionCaughtFlag,
+ &exceptionStorage,
+ &caughtResultStorage
+ );
+
+ for (unsigned i = 0; i < numExceptionsToCatch; ++i) {
+ nextName = ourTypeInfoNames[exceptionTypesToCatch[i]];
+
+ // One catch block per type info to be caught
+ catchBlocks[i] = createCatchBlock(context,
+ module,
+ builder,
+ *ret,
+ nextName,
+ ourId,
+ *finallyBlock,
+ *exceptionCaughtFlag);
+ }
+
+ // Entry Block
+
+ builder.SetInsertPoint(entryBlock);
+
+ std::vector<llvm::Value*> args;
+ args.push_back(namedValues["exceptTypeToThrow"]);
+ builder.CreateInvoke(&toInvoke,
+ normalBlock,
+ exceptionBlock,
+ args);
+
+ // End Block
+
+ builder.SetInsertPoint(endBlock);
+
+ generateStringPrint(context,
+ module,
+ builder,
+ "Gen: In end block: exiting in " + ourId + ".\n",
+ USE_GLOBAL_STR_CONSTS);
+ llvm::Function *deleteOurException = module.getFunction("deleteOurException");
+
+ // Note: function handles NULL exceptions
+ builder.CreateCall(deleteOurException,
+ builder.CreateLoad(exceptionStorage));
+ builder.CreateRetVoid();
+
+ // Normal Block
+
+ builder.SetInsertPoint(normalBlock);
+
+ generateStringPrint(context,
+ module,
+ builder,
+ "Gen: No exception in " + ourId + "!\n",
+ USE_GLOBAL_STR_CONSTS);
+
+ // Finally block is always called
+ builder.CreateBr(finallyBlock);
+
+ // Unwind Resume Block
+
+ builder.SetInsertPoint(unwindResumeBlock);
+
+ builder.CreateResume(builder.CreateLoad(caughtResultStorage));
+
+ // Exception Block
+
+ builder.SetInsertPoint(exceptionBlock);
+
+ llvm::Function *personality = module.getFunction("ourPersonality");
+
+ llvm::LandingPadInst *caughtResult =
+ 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
+ // altogether with a block rearrangement
+ builder.CreateStore(caughtResult, caughtResultStorage);
+ builder.CreateStore(unwindException, exceptionStorage);
+ builder.CreateStore(ourExceptionThrownState, exceptionCaughtFlag);
+
+ // Retrieve exception_class member from thrown exception
+ // (_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));
+
+ // Branch to the externalExceptionBlock if the exception is foreign or
+ // to a catch router if not. Either way the finally block will be run.
+ builder.CreateCondBr(builder.CreateICmpEQ(unwindExceptionClass,
+ llvm::ConstantInt::get(builder.getInt64Ty(),
+ ourBaseExceptionClass)),
+ exceptionRouteBlock,
+ externalExceptionBlock);
+
+ // External Exception Block
+
+ builder.SetInsertPoint(externalExceptionBlock);
+
+ generateStringPrint(context,
+ module,
+ builder,
+ "Gen: Foreign exception received.\n",
+ USE_GLOBAL_STR_CONSTS);
+
+ // Branch to the finally block
+ builder.CreateBr(finallyBlock);
+
+ // Exception Route Block
+
+ builder.SetInsertPoint(exceptionRouteBlock);
+
+ // Casts exception pointer (_Unwind_Exception instance) to parent
+ // (OurException instance).
+ //
+ // Note: ourBaseFromUnwindOffset is usually negative
+ llvm::Value *typeInfoThrown = builder.CreatePointerCast(
+ builder.CreateConstGEP1_64(unwindException,
+ ourBaseFromUnwindOffset),
+ ourExceptionType->getPointerTo());
+
+ // Retrieve thrown exception type info type
+ //
+ // Note: Index is not relative to pointer but instead to structure
+ // unlike a true getelementptr (GEP) instruction
+ typeInfoThrown = builder.CreateStructGEP(typeInfoThrown, 0);
+
+ llvm::Value *typeInfoThrownType =
+ builder.CreateStructGEP(typeInfoThrown, 0);
+
+ generateIntegerPrint(context,
+ module,
+ builder,
+ *toPrint32Int,
+ *(builder.CreateLoad(typeInfoThrownType)),
+ "Gen: Exception type <%d> received (stack unwound) "
+ " in " +
+ ourId +
+ ".\n",
+ USE_GLOBAL_STR_CONSTS);
+
+ // Route to matched type info catch block or run cleanup finally block
+ llvm::SwitchInst *switchToCatchBlock = builder.CreateSwitch(retTypeInfoIndex,
+ finallyBlock,
+ numExceptionsToCatch);
+
+ unsigned nextTypeToCatch;
+
+ for (unsigned i = 1; i <= numExceptionsToCatch; ++i) {
+ nextTypeToCatch = i - 1;
+ switchToCatchBlock->addCase(llvm::ConstantInt::get(
+ llvm::Type::getInt32Ty(context), i),
+ catchBlocks[nextTypeToCatch]);
+ }
+
+ llvm::verifyFunction(*ret);
+ fpm.run(*ret);
+
+ return(ret);
+}