Skip to content

Commit 2ece5cc

Browse files
authored
[ExceptionDemo] Correct and update example ExceptionDemo (llvm#69485)
The ExceptionDemo example was no longer compiling (since llvm 14 at least). The PR makes the example work with the current API and also transition from MCJIT to ORC. Fixes llvm#63702
1 parent eb10310 commit 2ece5cc

File tree

2 files changed

+77
-108
lines changed

2 files changed

+77
-108
lines changed

llvm/examples/ExceptionDemo/CMakeLists.txt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
set(LLVM_LINK_COMPONENTS
22
Core
33
ExecutionEngine
4-
MC
5-
MCJIT
6-
RuntimeDyld
4+
ORCJIT
75
Support
86
Target
97
nativecodegen

llvm/examples/ExceptionDemo/ExceptionDemo.cpp

Lines changed: 76 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,9 @@
4949

5050
#include "llvm/ADT/STLExtras.h"
5151
#include "llvm/BinaryFormat/Dwarf.h"
52-
#include "llvm/ExecutionEngine/MCJIT.h"
53-
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
52+
#include "llvm/ExecutionEngine/Orc/Core.h"
53+
#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
54+
#include "llvm/ExecutionEngine/Orc/LLJIT.h"
5455
#include "llvm/IR/DataLayout.h"
5556
#include "llvm/IR/DerivedTypes.h"
5657
#include "llvm/IR/IRBuilder.h"
@@ -84,6 +85,8 @@
8485
#define USE_GLOBAL_STR_CONSTS true
8586
#endif
8687

88+
llvm::ExitOnError ExitOnErr;
89+
8790
//
8891
// Example types
8992
//
@@ -142,6 +145,7 @@ static llvm::ConstantInt *ourExceptionCaughtState;
142145

143146
typedef std::vector<std::string> ArgNames;
144147
typedef std::vector<llvm::Type*> ArgTypes;
148+
typedef llvm::ArrayRef<llvm::Type *> TypeArray;
145149

146150
//
147151
// Code Generation Utilities
@@ -892,13 +896,10 @@ void generateStringPrint(llvm::LLVMContext &context,
892896
/// generated, and is used to hold the constant string. A value of
893897
/// false indicates that the constant string will be stored on the
894898
/// stack.
895-
void generateIntegerPrint(llvm::LLVMContext &context,
896-
llvm::Module &module,
899+
void generateIntegerPrint(llvm::LLVMContext &context, llvm::Module &module,
897900
llvm::IRBuilder<> &builder,
898-
llvm::Function &printFunct,
899-
llvm::Value &toPrint,
900-
std::string format,
901-
bool useGlobal = true) {
901+
llvm::Function &printFunct, llvm::Value *toPrint,
902+
std::string format, bool useGlobal = true) {
902903
llvm::Constant *stringConstant =
903904
llvm::ConstantDataArray::getString(context, format);
904905
llvm::Value *stringVar;
@@ -920,10 +921,9 @@ void generateIntegerPrint(llvm::LLVMContext &context,
920921

921922
llvm::Value *cast = builder.CreateBitCast(stringVar,
922923
builder.getPtrTy());
923-
builder.CreateCall(&printFunct, {&toPrint, cast});
924+
builder.CreateCall(&printFunct, {toPrint, cast});
924925
}
925926

926-
927927
/// Generates code to handle finally block type semantics: always runs
928928
/// regardless of whether a thrown exception is passing through or the
929929
/// parent function is simply exiting. In addition to printing some state
@@ -997,10 +997,10 @@ static llvm::BasicBlock *createFinallyBlock(llvm::LLVMContext &context,
997997
bufferToPrint.str(),
998998
USE_GLOBAL_STR_CONSTS);
999999

1000-
llvm::SwitchInst *theSwitch = builder.CreateSwitch(builder.CreateLoad(
1001-
*exceptionCaughtFlag),
1002-
&terminatorBlock,
1003-
2);
1000+
llvm::SwitchInst *theSwitch = builder.CreateSwitch(
1001+
builder.CreateLoad(ourExceptionNotThrownState->getType(),
1002+
*exceptionCaughtFlag),
1003+
&terminatorBlock, 2);
10041004
theSwitch->addCase(ourExceptionCaughtState, &terminatorBlock);
10051005
theSwitch->addCase(ourExceptionThrownState, &unwindResumeBlock);
10061006

@@ -1186,7 +1186,7 @@ static llvm::Function *createCatchWrappedInvokeFunction(
11861186

11871187
// Note: function handles NULL exceptions
11881188
builder.CreateCall(deleteOurException,
1189-
builder.CreateLoad(exceptionStorage));
1189+
builder.CreateLoad(builder.getPtrTy(), exceptionStorage));
11901190
builder.CreateRetVoid();
11911191

11921192
// Normal Block
@@ -1206,7 +1206,8 @@ static llvm::Function *createCatchWrappedInvokeFunction(
12061206

12071207
builder.SetInsertPoint(unwindResumeBlock);
12081208

1209-
builder.CreateResume(builder.CreateLoad(caughtResultStorage));
1209+
builder.CreateResume(
1210+
builder.CreateLoad(ourCaughtResultType, caughtResultStorage));
12101211

12111212
// Exception Block
12121213

@@ -1241,8 +1242,9 @@ static llvm::Function *createCatchWrappedInvokeFunction(
12411242
// Retrieve exception_class member from thrown exception
12421243
// (_Unwind_Exception instance). This member tells us whether or not
12431244
// the exception is foreign.
1244-
llvm::Value *unwindExceptionClass =
1245-
builder.CreateLoad(builder.CreateStructGEP(
1245+
llvm::Value *unwindExceptionClass = builder.CreateLoad(
1246+
builder.getInt64Ty(),
1247+
builder.CreateStructGEP(
12461248
ourUnwindExceptionType,
12471249
builder.CreatePointerCast(unwindException,
12481250
ourUnwindExceptionType->getPointerTo()),
@@ -1278,9 +1280,9 @@ static llvm::Function *createCatchWrappedInvokeFunction(
12781280
//
12791281
// Note: ourBaseFromUnwindOffset is usually negative
12801282
llvm::Value *typeInfoThrown = builder.CreatePointerCast(
1281-
builder.CreateConstGEP1_64(unwindException,
1282-
ourBaseFromUnwindOffset),
1283-
ourExceptionType->getPointerTo());
1283+
builder.CreateConstGEP1_64(builder.getPtrTy(), unwindException,
1284+
ourBaseFromUnwindOffset),
1285+
ourExceptionType->getPointerTo());
12841286

12851287
// Retrieve thrown exception type info type
12861288
//
@@ -1289,17 +1291,15 @@ static llvm::Function *createCatchWrappedInvokeFunction(
12891291
typeInfoThrown = builder.CreateStructGEP(ourExceptionType, typeInfoThrown, 0);
12901292

12911293
llvm::Value *typeInfoThrownType =
1292-
builder.CreateStructGEP(builder.getPtrTy(), typeInfoThrown, 0);
1294+
builder.CreateStructGEP(ourTypeInfoType, typeInfoThrown, 0);
12931295

1294-
generateIntegerPrint(context,
1295-
module,
1296-
builder,
1297-
*toPrint32Int,
1298-
*(builder.CreateLoad(typeInfoThrownType)),
1296+
llvm::Value *ti8 =
1297+
builder.CreateLoad(builder.getInt8Ty(), typeInfoThrownType);
1298+
generateIntegerPrint(context, module, builder, *toPrint32Int,
1299+
builder.CreateZExt(ti8, builder.getInt32Ty()),
12991300
"Gen: Exception type <%d> received (stack unwound) "
13001301
" in " +
1301-
ourId +
1302-
".\n",
1302+
ourId + ".\n",
13031303
USE_GLOBAL_STR_CONSTS);
13041304

13051305
// Route to matched type info catch block or run cleanup finally block
@@ -1311,8 +1311,7 @@ static llvm::Function *createCatchWrappedInvokeFunction(
13111311

13121312
for (unsigned i = 1; i <= numExceptionsToCatch; ++i) {
13131313
nextTypeToCatch = i - 1;
1314-
switchToCatchBlock->addCase(llvm::ConstantInt::get(
1315-
llvm::Type::getInt32Ty(context), i),
1314+
switchToCatchBlock->addCase(llvm::ConstantInt::get(builder.getInt32Ty(), i),
13161315
catchBlocks[nextTypeToCatch]);
13171316
}
13181317

@@ -1387,14 +1386,10 @@ createThrowExceptionFunction(llvm::Module &module, llvm::IRBuilder<> &builder,
13871386
builder.SetInsertPoint(entryBlock);
13881387

13891388
llvm::Function *toPrint32Int = module.getFunction("print32Int");
1390-
generateIntegerPrint(context,
1391-
module,
1392-
builder,
1393-
*toPrint32Int,
1394-
*exceptionType,
1395-
"\nGen: About to throw exception type <%d> in " +
1396-
ourId +
1397-
".\n",
1389+
generateIntegerPrint(context, module, builder, *toPrint32Int,
1390+
builder.CreateZExt(exceptionType, builder.getInt32Ty()),
1391+
"\nGen: About to throw exception type <%d> in " + ourId +
1392+
".\n",
13981393
USE_GLOBAL_STR_CONSTS);
13991394

14001395
// Switches on runtime type info type value to determine whether or not
@@ -1546,15 +1541,13 @@ typedef void (*OurExceptionThrowFunctType) (int32_t typeToThrow);
15461541
/// @param function generated test function to run
15471542
/// @param typeToThrow type info type of generated exception to throw, or
15481543
/// indicator to cause foreign exception to be thrown.
1549-
static
1550-
void runExceptionThrow(llvm::ExecutionEngine *engine,
1551-
llvm::Function *function,
1552-
int32_t typeToThrow) {
1544+
static void runExceptionThrow(llvm::orc::LLJIT *JIT, std::string function,
1545+
int32_t typeToThrow) {
15531546

15541547
// Find test's function pointer
15551548
OurExceptionThrowFunctType functPtr =
1556-
reinterpret_cast<OurExceptionThrowFunctType>(
1557-
reinterpret_cast<intptr_t>(engine->getPointerToFunction(function)));
1549+
reinterpret_cast<OurExceptionThrowFunctType>(reinterpret_cast<uintptr_t>(
1550+
ExitOnErr(JIT->lookup(function)).getValue()));
15581551

15591552
try {
15601553
// Run test
@@ -1583,8 +1576,6 @@ void runExceptionThrow(llvm::ExecutionEngine *engine,
15831576
// End test functions
15841577
//
15851578

1586-
typedef llvm::ArrayRef<llvm::Type*> TypeArray;
1587-
15881579
/// This initialization routine creates type info globals and
15891580
/// adds external function declarations to module.
15901581
/// @param numTypeInfos number of linear type info associated type info types
@@ -1894,93 +1885,73 @@ int main(int argc, char *argv[]) {
18941885
return(0);
18951886
}
18961887

1897-
// If not set, exception handling will not be turned on
1898-
llvm::TargetOptions Opts;
1899-
19001888
llvm::InitializeNativeTarget();
19011889
llvm::InitializeNativeTargetAsmPrinter();
1902-
llvm::LLVMContext Context;
1903-
llvm::IRBuilder<> theBuilder(Context);
1890+
auto Context = std::make_unique<llvm::LLVMContext>();
1891+
llvm::IRBuilder<> theBuilder(*Context);
19041892

19051893
// Make the module, which holds all the code.
19061894
std::unique_ptr<llvm::Module> Owner =
1907-
std::make_unique<llvm::Module>("my cool jit", Context);
1895+
std::make_unique<llvm::Module>("my cool jit", *Context);
19081896
llvm::Module *module = Owner.get();
19091897

1910-
std::unique_ptr<llvm::RTDyldMemoryManager> MemMgr(new llvm::SectionMemoryManager());
1898+
// Build LLJIT
1899+
std::unique_ptr<llvm::orc::LLJIT> JIT =
1900+
ExitOnErr(llvm::orc::LLJITBuilder().create());
19111901

1912-
// Build engine with JIT
1913-
llvm::EngineBuilder factory(std::move(Owner));
1914-
factory.setEngineKind(llvm::EngineKind::JIT);
1915-
factory.setTargetOptions(Opts);
1916-
factory.setMCJITMemoryManager(std::move(MemMgr));
1917-
llvm::ExecutionEngine *executionEngine = factory.create();
1902+
// Set up the optimizer pipeline.
1903+
llvm::legacy::FunctionPassManager fpm(module);
19181904

1919-
{
1920-
llvm::legacy::FunctionPassManager fpm(module);
1921-
1922-
// Set up the optimizer pipeline.
1923-
// Start with registering info about how the
1924-
// target lays out data structures.
1925-
module->setDataLayout(executionEngine->getDataLayout());
1926-
1927-
// Optimizations turned on
1905+
// Optimizations turned on
19281906
#ifdef ADD_OPT_PASSES
19291907

1930-
// Basic AliasAnslysis support for GVN.
1931-
fpm.add(llvm::createBasicAliasAnalysisPass());
1908+
// Basic AliasAnslysis support for GVN.
1909+
fpm.add(llvm::createBasicAliasAnalysisPass());
19321910

1933-
// Promote allocas to registers.
1934-
fpm.add(llvm::createPromoteMemoryToRegisterPass());
1911+
// Promote allocas to registers.
1912+
fpm.add(llvm::createPromoteMemoryToRegisterPass());
19351913

1936-
// Do simple "peephole" optimizations and bit-twiddling optzns.
1937-
fpm.add(llvm::createInstructionCombiningPass());
1914+
// Do simple "peephole" optimizations and bit-twiddling optzns.
1915+
fpm.add(llvm::createInstructionCombiningPass());
19381916

1939-
// Reassociate expressions.
1940-
fpm.add(llvm::createReassociatePass());
1917+
// Reassociate expressions.
1918+
fpm.add(llvm::createReassociatePass());
19411919

1942-
// Eliminate Common SubExpressions.
1943-
fpm.add(llvm::createGVNPass());
1920+
// Eliminate Common SubExpressions.
1921+
fpm.add(llvm::createGVNPass());
19441922

1945-
// Simplify the control flow graph (deleting unreachable
1946-
// blocks, etc).
1947-
fpm.add(llvm::createCFGSimplificationPass());
1923+
// Simplify the control flow graph (deleting unreachable
1924+
// blocks, etc).
1925+
fpm.add(llvm::createCFGSimplificationPass());
19481926
#endif // ADD_OPT_PASSES
19491927

1950-
fpm.doInitialization();
1928+
fpm.doInitialization();
19511929

1952-
// Generate test code using function throwCppException(...) as
1953-
// the function which throws foreign exceptions.
1954-
llvm::Function *toRun =
1955-
createUnwindExceptionTest(*module,
1956-
theBuilder,
1957-
fpm,
1958-
"throwCppException");
1930+
// Generate test code using function throwCppException(...) as
1931+
// the function which throws foreign exceptions.
1932+
createUnwindExceptionTest(*module, theBuilder, fpm, "throwCppException");
19591933

1960-
executionEngine->finalizeObject();
1934+
ExitOnErr(JIT->addIRModule(
1935+
llvm::orc::ThreadSafeModule(std::move(Owner), std::move(Context))));
19611936

19621937
#ifndef NDEBUG
1963-
fprintf(stderr, "\nBegin module dump:\n\n");
1938+
fprintf(stderr, "\nBegin module dump:\n\n");
19641939

1965-
module->dump();
1940+
module->print(llvm::errs(), nullptr);
19661941

1967-
fprintf(stderr, "\nEnd module dump:\n");
1942+
fprintf(stderr, "\nEnd module dump:\n");
19681943
#endif
19691944

1970-
fprintf(stderr, "\n\nBegin Test:\n");
1971-
1972-
for (int i = 1; i < argc; ++i) {
1973-
// Run test for each argument whose value is the exception
1974-
// type to throw.
1975-
runExceptionThrow(executionEngine,
1976-
toRun,
1977-
(unsigned) strtoul(argv[i], NULL, 10));
1978-
}
1945+
fprintf(stderr, "\n\nBegin Test:\n");
1946+
std::string toRun = "outerCatchFunct";
19791947

1980-
fprintf(stderr, "\nEnd Test:\n\n");
1948+
for (int i = 1; i < argc; ++i) {
1949+
// Run test for each argument whose value is the exception
1950+
// type to throw.
1951+
runExceptionThrow(JIT.get(), toRun, (unsigned)strtoul(argv[i], NULL, 10));
19811952
}
19821953

1983-
delete executionEngine;
1954+
fprintf(stderr, "\nEnd Test:\n\n");
19841955

19851956
return 0;
19861957
}

0 commit comments

Comments
 (0)