Skip to content

Commit 2ece5cc

Browse files
authored
[ExceptionDemo] Correct and update example ExceptionDemo (#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 #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)