[ExceptionDemo] Transition example from MCJIT to ORC and fix errors (#92504)
ExceptionDemo has been broken for some time. This patch fixes the compilation errors and moves the example from MCJIT to ORC.
This commit is contained in:
@@ -1,9 +1,7 @@
|
|||||||
set(LLVM_LINK_COMPONENTS
|
set(LLVM_LINK_COMPONENTS
|
||||||
Core
|
Core
|
||||||
ExecutionEngine
|
ExecutionEngine
|
||||||
MC
|
ORCJIT
|
||||||
MCJIT
|
|
||||||
RuntimeDyld
|
|
||||||
Support
|
Support
|
||||||
Target
|
Target
|
||||||
nativecodegen
|
nativecodegen
|
||||||
|
|||||||
@@ -49,8 +49,9 @@
|
|||||||
|
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/BinaryFormat/Dwarf.h"
|
#include "llvm/BinaryFormat/Dwarf.h"
|
||||||
#include "llvm/ExecutionEngine/MCJIT.h"
|
#include "llvm/ExecutionEngine/Orc/Core.h"
|
||||||
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
|
#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
|
||||||
|
#include "llvm/ExecutionEngine/Orc/LLJIT.h"
|
||||||
#include "llvm/IR/DataLayout.h"
|
#include "llvm/IR/DataLayout.h"
|
||||||
#include "llvm/IR/DerivedTypes.h"
|
#include "llvm/IR/DerivedTypes.h"
|
||||||
#include "llvm/IR/IRBuilder.h"
|
#include "llvm/IR/IRBuilder.h"
|
||||||
@@ -84,6 +85,8 @@
|
|||||||
#define USE_GLOBAL_STR_CONSTS true
|
#define USE_GLOBAL_STR_CONSTS true
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
llvm::ExitOnError ExitOnErr;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Example types
|
// Example types
|
||||||
//
|
//
|
||||||
@@ -142,6 +145,7 @@ static llvm::ConstantInt *ourExceptionCaughtState;
|
|||||||
|
|
||||||
typedef std::vector<std::string> ArgNames;
|
typedef std::vector<std::string> ArgNames;
|
||||||
typedef std::vector<llvm::Type*> ArgTypes;
|
typedef std::vector<llvm::Type*> ArgTypes;
|
||||||
|
typedef llvm::ArrayRef<llvm::Type *> TypeArray;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Code Generation Utilities
|
// Code Generation Utilities
|
||||||
@@ -891,13 +895,10 @@ void generateStringPrint(llvm::LLVMContext &context,
|
|||||||
/// generated, and is used to hold the constant string. A value of
|
/// generated, and is used to hold the constant string. A value of
|
||||||
/// false indicates that the constant string will be stored on the
|
/// false indicates that the constant string will be stored on the
|
||||||
/// stack.
|
/// stack.
|
||||||
void generateIntegerPrint(llvm::LLVMContext &context,
|
void generateIntegerPrint(llvm::LLVMContext &context, llvm::Module &module,
|
||||||
llvm::Module &module,
|
|
||||||
llvm::IRBuilder<> &builder,
|
llvm::IRBuilder<> &builder,
|
||||||
llvm::Function &printFunct,
|
llvm::Function &printFunct, llvm::Value *toPrint,
|
||||||
llvm::Value &toPrint,
|
std::string format, bool useGlobal = true) {
|
||||||
std::string format,
|
|
||||||
bool useGlobal = true) {
|
|
||||||
llvm::Constant *stringConstant =
|
llvm::Constant *stringConstant =
|
||||||
llvm::ConstantDataArray::getString(context, format);
|
llvm::ConstantDataArray::getString(context, format);
|
||||||
llvm::Value *stringVar;
|
llvm::Value *stringVar;
|
||||||
@@ -919,10 +920,9 @@ void generateIntegerPrint(llvm::LLVMContext &context,
|
|||||||
|
|
||||||
llvm::Value *cast = builder.CreateBitCast(stringVar,
|
llvm::Value *cast = builder.CreateBitCast(stringVar,
|
||||||
builder.getPtrTy());
|
builder.getPtrTy());
|
||||||
builder.CreateCall(&printFunct, {&toPrint, cast});
|
builder.CreateCall(&printFunct, {toPrint, cast});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Generates code to handle finally block type semantics: always runs
|
/// Generates code to handle finally block type semantics: always runs
|
||||||
/// regardless of whether a thrown exception is passing through or the
|
/// regardless of whether a thrown exception is passing through or the
|
||||||
/// parent function is simply exiting. In addition to printing some state
|
/// parent function is simply exiting. In addition to printing some state
|
||||||
@@ -996,10 +996,10 @@ static llvm::BasicBlock *createFinallyBlock(llvm::LLVMContext &context,
|
|||||||
bufferToPrint.str(),
|
bufferToPrint.str(),
|
||||||
USE_GLOBAL_STR_CONSTS);
|
USE_GLOBAL_STR_CONSTS);
|
||||||
|
|
||||||
llvm::SwitchInst *theSwitch = builder.CreateSwitch(builder.CreateLoad(
|
llvm::SwitchInst *theSwitch = builder.CreateSwitch(
|
||||||
*exceptionCaughtFlag),
|
builder.CreateLoad(ourExceptionNotThrownState->getType(),
|
||||||
&terminatorBlock,
|
*exceptionCaughtFlag),
|
||||||
2);
|
&terminatorBlock, 2);
|
||||||
theSwitch->addCase(ourExceptionCaughtState, &terminatorBlock);
|
theSwitch->addCase(ourExceptionCaughtState, &terminatorBlock);
|
||||||
theSwitch->addCase(ourExceptionThrownState, &unwindResumeBlock);
|
theSwitch->addCase(ourExceptionThrownState, &unwindResumeBlock);
|
||||||
|
|
||||||
@@ -1185,7 +1185,7 @@ static llvm::Function *createCatchWrappedInvokeFunction(
|
|||||||
|
|
||||||
// Note: function handles NULL exceptions
|
// Note: function handles NULL exceptions
|
||||||
builder.CreateCall(deleteOurException,
|
builder.CreateCall(deleteOurException,
|
||||||
builder.CreateLoad(exceptionStorage));
|
builder.CreateLoad(builder.getPtrTy(), exceptionStorage));
|
||||||
builder.CreateRetVoid();
|
builder.CreateRetVoid();
|
||||||
|
|
||||||
// Normal Block
|
// Normal Block
|
||||||
@@ -1205,7 +1205,8 @@ static llvm::Function *createCatchWrappedInvokeFunction(
|
|||||||
|
|
||||||
builder.SetInsertPoint(unwindResumeBlock);
|
builder.SetInsertPoint(unwindResumeBlock);
|
||||||
|
|
||||||
builder.CreateResume(builder.CreateLoad(caughtResultStorage));
|
builder.CreateResume(
|
||||||
|
builder.CreateLoad(ourCaughtResultType, caughtResultStorage));
|
||||||
|
|
||||||
// Exception Block
|
// Exception Block
|
||||||
|
|
||||||
@@ -1240,11 +1241,9 @@ static llvm::Function *createCatchWrappedInvokeFunction(
|
|||||||
// Retrieve exception_class member from thrown exception
|
// Retrieve exception_class member from thrown exception
|
||||||
// (_Unwind_Exception instance). This member tells us whether or not
|
// (_Unwind_Exception instance). This member tells us whether or not
|
||||||
// the exception is foreign.
|
// the exception is foreign.
|
||||||
llvm::Value *unwindExceptionClass =
|
llvm::Value *unwindExceptionClass = builder.CreateLoad(
|
||||||
builder.CreateLoad(builder.CreateStructGEP(
|
builder.getInt64Ty(),
|
||||||
ourUnwindExceptionType,
|
builder.CreateStructGEP(ourUnwindExceptionType, unwindException, 0));
|
||||||
unwindException,
|
|
||||||
0));
|
|
||||||
|
|
||||||
// Branch to the externalExceptionBlock if the exception is foreign or
|
// Branch to the externalExceptionBlock if the exception is foreign or
|
||||||
// to a catch router if not. Either way the finally block will be run.
|
// to a catch router if not. Either way the finally block will be run.
|
||||||
@@ -1275,8 +1274,8 @@ static llvm::Function *createCatchWrappedInvokeFunction(
|
|||||||
// (OurException instance).
|
// (OurException instance).
|
||||||
//
|
//
|
||||||
// Note: ourBaseFromUnwindOffset is usually negative
|
// Note: ourBaseFromUnwindOffset is usually negative
|
||||||
llvm::Value *typeInfoThrown = builder.CreateConstGEP1_64(unwindException,
|
llvm::Value *typeInfoThrown = builder.CreateConstGEP1_64(
|
||||||
ourBaseFromUnwindOffset));
|
builder.getInt8Ty(), unwindException, ourBaseFromUnwindOffset);
|
||||||
|
|
||||||
// Retrieve thrown exception type info type
|
// Retrieve thrown exception type info type
|
||||||
//
|
//
|
||||||
@@ -1285,17 +1284,14 @@ static llvm::Function *createCatchWrappedInvokeFunction(
|
|||||||
typeInfoThrown = builder.CreateStructGEP(ourExceptionType, typeInfoThrown, 0);
|
typeInfoThrown = builder.CreateStructGEP(ourExceptionType, typeInfoThrown, 0);
|
||||||
|
|
||||||
llvm::Value *typeInfoThrownType =
|
llvm::Value *typeInfoThrownType =
|
||||||
builder.CreateStructGEP(builder.getPtrTy(), typeInfoThrown, 0);
|
builder.CreateStructGEP(ourTypeInfoType, typeInfoThrown, 0);
|
||||||
|
|
||||||
generateIntegerPrint(context,
|
llvm::Value *ti32 =
|
||||||
module,
|
builder.CreateLoad(builder.getInt32Ty(), typeInfoThrownType);
|
||||||
builder,
|
generateIntegerPrint(context, module, builder, *toPrint32Int, ti32,
|
||||||
*toPrint32Int,
|
|
||||||
*(builder.CreateLoad(typeInfoThrownType)),
|
|
||||||
"Gen: Exception type <%d> received (stack unwound) "
|
"Gen: Exception type <%d> received (stack unwound) "
|
||||||
" in " +
|
" in " +
|
||||||
ourId +
|
ourId + ".\n",
|
||||||
".\n",
|
|
||||||
USE_GLOBAL_STR_CONSTS);
|
USE_GLOBAL_STR_CONSTS);
|
||||||
|
|
||||||
// Route to matched type info catch block or run cleanup finally block
|
// Route to matched type info catch block or run cleanup finally block
|
||||||
@@ -1307,8 +1303,7 @@ static llvm::Function *createCatchWrappedInvokeFunction(
|
|||||||
|
|
||||||
for (unsigned i = 1; i <= numExceptionsToCatch; ++i) {
|
for (unsigned i = 1; i <= numExceptionsToCatch; ++i) {
|
||||||
nextTypeToCatch = i - 1;
|
nextTypeToCatch = i - 1;
|
||||||
switchToCatchBlock->addCase(llvm::ConstantInt::get(
|
switchToCatchBlock->addCase(llvm::ConstantInt::get(builder.getInt32Ty(), i),
|
||||||
llvm::Type::getInt32Ty(context), i),
|
|
||||||
catchBlocks[nextTypeToCatch]);
|
catchBlocks[nextTypeToCatch]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1383,14 +1378,10 @@ createThrowExceptionFunction(llvm::Module &module, llvm::IRBuilder<> &builder,
|
|||||||
builder.SetInsertPoint(entryBlock);
|
builder.SetInsertPoint(entryBlock);
|
||||||
|
|
||||||
llvm::Function *toPrint32Int = module.getFunction("print32Int");
|
llvm::Function *toPrint32Int = module.getFunction("print32Int");
|
||||||
generateIntegerPrint(context,
|
generateIntegerPrint(context, module, builder, *toPrint32Int,
|
||||||
module,
|
builder.CreateZExt(exceptionType, builder.getInt32Ty()),
|
||||||
builder,
|
"\nGen: About to throw exception type <%d> in " + ourId +
|
||||||
*toPrint32Int,
|
".\n",
|
||||||
*exceptionType,
|
|
||||||
"\nGen: About to throw exception type <%d> in " +
|
|
||||||
ourId +
|
|
||||||
".\n",
|
|
||||||
USE_GLOBAL_STR_CONSTS);
|
USE_GLOBAL_STR_CONSTS);
|
||||||
|
|
||||||
// Switches on runtime type info type value to determine whether or not
|
// Switches on runtime type info type value to determine whether or not
|
||||||
@@ -1542,15 +1533,12 @@ typedef void (*OurExceptionThrowFunctType) (int32_t typeToThrow);
|
|||||||
/// @param function generated test function to run
|
/// @param function generated test function to run
|
||||||
/// @param typeToThrow type info type of generated exception to throw, or
|
/// @param typeToThrow type info type of generated exception to throw, or
|
||||||
/// indicator to cause foreign exception to be thrown.
|
/// indicator to cause foreign exception to be thrown.
|
||||||
static
|
static void runExceptionThrow(llvm::orc::LLJIT *JIT, std::string function,
|
||||||
void runExceptionThrow(llvm::ExecutionEngine *engine,
|
int32_t typeToThrow) {
|
||||||
llvm::Function *function,
|
|
||||||
int32_t typeToThrow) {
|
|
||||||
|
|
||||||
// Find test's function pointer
|
// Find test's function pointer
|
||||||
OurExceptionThrowFunctType functPtr =
|
OurExceptionThrowFunctType functPtr =
|
||||||
reinterpret_cast<OurExceptionThrowFunctType>(
|
ExitOnErr(JIT->lookup(function)).toPtr<OurExceptionThrowFunctType>();
|
||||||
reinterpret_cast<intptr_t>(engine->getPointerToFunction(function)));
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Run test
|
// Run test
|
||||||
@@ -1579,8 +1567,6 @@ void runExceptionThrow(llvm::ExecutionEngine *engine,
|
|||||||
// End test functions
|
// End test functions
|
||||||
//
|
//
|
||||||
|
|
||||||
typedef llvm::ArrayRef<llvm::Type*> TypeArray;
|
|
||||||
|
|
||||||
/// This initialization routine creates type info globals and
|
/// This initialization routine creates type info globals and
|
||||||
/// adds external function declarations to module.
|
/// adds external function declarations to module.
|
||||||
/// @param numTypeInfos number of linear type info associated type info types
|
/// @param numTypeInfos number of linear type info associated type info types
|
||||||
@@ -1861,7 +1847,8 @@ static void createStandardUtilityFunctions(unsigned numTypeInfos,
|
|||||||
|
|
||||||
// llvm.eh.typeid.for intrinsic
|
// llvm.eh.typeid.for intrinsic
|
||||||
|
|
||||||
getDeclaration(&module, llvm::Intrinsic::eh_typeid_for, builder.getPtrTy());
|
getOrInsertDeclaration(&module, llvm::Intrinsic::eh_typeid_for,
|
||||||
|
builder.getPtrTy());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1890,93 +1877,73 @@ int main(int argc, char *argv[]) {
|
|||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not set, exception handling will not be turned on
|
|
||||||
llvm::TargetOptions Opts;
|
|
||||||
|
|
||||||
llvm::InitializeNativeTarget();
|
llvm::InitializeNativeTarget();
|
||||||
llvm::InitializeNativeTargetAsmPrinter();
|
llvm::InitializeNativeTargetAsmPrinter();
|
||||||
llvm::LLVMContext Context;
|
auto Context = std::make_unique<llvm::LLVMContext>();
|
||||||
llvm::IRBuilder<> theBuilder(Context);
|
llvm::IRBuilder<> theBuilder(*Context);
|
||||||
|
|
||||||
// Make the module, which holds all the code.
|
// Make the module, which holds all the code.
|
||||||
std::unique_ptr<llvm::Module> Owner =
|
std::unique_ptr<llvm::Module> Owner =
|
||||||
std::make_unique<llvm::Module>("my cool jit", Context);
|
std::make_unique<llvm::Module>("my cool jit", *Context);
|
||||||
llvm::Module *module = Owner.get();
|
llvm::Module *module = Owner.get();
|
||||||
|
|
||||||
std::unique_ptr<llvm::RTDyldMemoryManager> MemMgr(new llvm::SectionMemoryManager());
|
// Build LLJIT
|
||||||
|
std::unique_ptr<llvm::orc::LLJIT> JIT =
|
||||||
|
ExitOnErr(llvm::orc::LLJITBuilder().create());
|
||||||
|
|
||||||
// Build engine with JIT
|
// Set up the optimizer pipeline.
|
||||||
llvm::EngineBuilder factory(std::move(Owner));
|
llvm::legacy::FunctionPassManager fpm(module);
|
||||||
factory.setEngineKind(llvm::EngineKind::JIT);
|
|
||||||
factory.setTargetOptions(Opts);
|
|
||||||
factory.setMCJITMemoryManager(std::move(MemMgr));
|
|
||||||
llvm::ExecutionEngine *executionEngine = factory.create();
|
|
||||||
|
|
||||||
{
|
// Optimizations turned on
|
||||||
llvm::legacy::FunctionPassManager fpm(module);
|
|
||||||
|
|
||||||
// Set up the optimizer pipeline.
|
|
||||||
// Start with registering info about how the
|
|
||||||
// target lays out data structures.
|
|
||||||
module->setDataLayout(executionEngine->getDataLayout());
|
|
||||||
|
|
||||||
// Optimizations turned on
|
|
||||||
#ifdef ADD_OPT_PASSES
|
#ifdef ADD_OPT_PASSES
|
||||||
|
|
||||||
// Basic AliasAnslysis support for GVN.
|
// Basic AliasAnslysis support for GVN.
|
||||||
fpm.add(llvm::createBasicAliasAnalysisPass());
|
fpm.add(llvm::createBasicAliasAnalysisPass());
|
||||||
|
|
||||||
// Promote allocas to registers.
|
// Promote allocas to registers.
|
||||||
fpm.add(llvm::createPromoteMemoryToRegisterPass());
|
fpm.add(llvm::createPromoteMemoryToRegisterPass());
|
||||||
|
|
||||||
// Do simple "peephole" optimizations and bit-twiddling optzns.
|
// Do simple "peephole" optimizations and bit-twiddling optzns.
|
||||||
fpm.add(llvm::createInstructionCombiningPass());
|
fpm.add(llvm::createInstructionCombiningPass());
|
||||||
|
|
||||||
// Reassociate expressions.
|
// Reassociate expressions.
|
||||||
fpm.add(llvm::createReassociatePass());
|
fpm.add(llvm::createReassociatePass());
|
||||||
|
|
||||||
// Eliminate Common SubExpressions.
|
// Eliminate Common SubExpressions.
|
||||||
fpm.add(llvm::createGVNPass());
|
fpm.add(llvm::createGVNPass());
|
||||||
|
|
||||||
// Simplify the control flow graph (deleting unreachable
|
// Simplify the control flow graph (deleting unreachable
|
||||||
// blocks, etc).
|
// blocks, etc).
|
||||||
fpm.add(llvm::createCFGSimplificationPass());
|
fpm.add(llvm::createCFGSimplificationPass());
|
||||||
#endif // ADD_OPT_PASSES
|
#endif // ADD_OPT_PASSES
|
||||||
|
|
||||||
fpm.doInitialization();
|
fpm.doInitialization();
|
||||||
|
|
||||||
// Generate test code using function throwCppException(...) as
|
// Generate test code using function throwCppException(...) as
|
||||||
// the function which throws foreign exceptions.
|
// the function which throws foreign exceptions.
|
||||||
llvm::Function *toRun =
|
createUnwindExceptionTest(*module, theBuilder, fpm, "throwCppException");
|
||||||
createUnwindExceptionTest(*module,
|
|
||||||
theBuilder,
|
|
||||||
fpm,
|
|
||||||
"throwCppException");
|
|
||||||
|
|
||||||
executionEngine->finalizeObject();
|
ExitOnErr(JIT->addIRModule(
|
||||||
|
llvm::orc::ThreadSafeModule(std::move(Owner), std::move(Context))));
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
fprintf(stderr, "\nBegin module dump:\n\n");
|
fprintf(stderr, "\nBegin module dump:\n\n");
|
||||||
|
|
||||||
module->dump();
|
module->print(llvm::errs(), nullptr);
|
||||||
|
|
||||||
fprintf(stderr, "\nEnd module dump:\n");
|
fprintf(stderr, "\nEnd module dump:\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
fprintf(stderr, "\n\nBegin Test:\n");
|
fprintf(stderr, "\n\nBegin Test:\n");
|
||||||
|
std::string toRun = "outerCatchFunct";
|
||||||
|
|
||||||
for (int i = 1; i < argc; ++i) {
|
for (int i = 1; i < argc; ++i) {
|
||||||
// Run test for each argument whose value is the exception
|
// Run test for each argument whose value is the exception
|
||||||
// type to throw.
|
// type to throw.
|
||||||
runExceptionThrow(executionEngine,
|
runExceptionThrow(JIT.get(), toRun, (unsigned)strtoul(argv[i], NULL, 10));
|
||||||
toRun,
|
|
||||||
(unsigned) strtoul(argv[i], NULL, 10));
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stderr, "\nEnd Test:\n\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delete executionEngine;
|
fprintf(stderr, "\nEnd Test:\n\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user