From 847acbbc529133b2300721a809751891200f37f5 Mon Sep 17 00:00:00 2001 From: epitavy <32581827+epitavy@users.noreply.github.com> Date: Thu, 23 Jan 2025 02:40:38 +0100 Subject: [PATCH] [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. --- llvm/examples/ExceptionDemo/CMakeLists.txt | 4 +- llvm/examples/ExceptionDemo/ExceptionDemo.cpp | 183 +++++++----------- 2 files changed, 76 insertions(+), 111 deletions(-) diff --git a/llvm/examples/ExceptionDemo/CMakeLists.txt b/llvm/examples/ExceptionDemo/CMakeLists.txt index 6c125fe20fb6..5d8e4c7d439b 100644 --- a/llvm/examples/ExceptionDemo/CMakeLists.txt +++ b/llvm/examples/ExceptionDemo/CMakeLists.txt @@ -1,9 +1,7 @@ set(LLVM_LINK_COMPONENTS Core ExecutionEngine - MC - MCJIT - RuntimeDyld + ORCJIT Support Target nativecodegen diff --git a/llvm/examples/ExceptionDemo/ExceptionDemo.cpp b/llvm/examples/ExceptionDemo/ExceptionDemo.cpp index 58367a231998..ae334419c8f8 100644 --- a/llvm/examples/ExceptionDemo/ExceptionDemo.cpp +++ b/llvm/examples/ExceptionDemo/ExceptionDemo.cpp @@ -49,8 +49,9 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/BinaryFormat/Dwarf.h" -#include "llvm/ExecutionEngine/MCJIT.h" -#include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include "llvm/ExecutionEngine/Orc/Core.h" +#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" +#include "llvm/ExecutionEngine/Orc/LLJIT.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/IRBuilder.h" @@ -84,6 +85,8 @@ #define USE_GLOBAL_STR_CONSTS true #endif +llvm::ExitOnError ExitOnErr; + // // Example types // @@ -142,6 +145,7 @@ static llvm::ConstantInt *ourExceptionCaughtState; typedef std::vector ArgNames; typedef std::vector ArgTypes; +typedef llvm::ArrayRef TypeArray; // // Code Generation Utilities @@ -891,13 +895,10 @@ void generateStringPrint(llvm::LLVMContext &context, /// generated, and is used to hold the constant string. A value of /// false indicates that the constant string will be stored on the /// stack. -void generateIntegerPrint(llvm::LLVMContext &context, - llvm::Module &module, +void generateIntegerPrint(llvm::LLVMContext &context, llvm::Module &module, llvm::IRBuilder<> &builder, - llvm::Function &printFunct, - llvm::Value &toPrint, - std::string format, - bool useGlobal = true) { + llvm::Function &printFunct, llvm::Value *toPrint, + std::string format, bool useGlobal = true) { llvm::Constant *stringConstant = llvm::ConstantDataArray::getString(context, format); llvm::Value *stringVar; @@ -919,10 +920,9 @@ void generateIntegerPrint(llvm::LLVMContext &context, llvm::Value *cast = builder.CreateBitCast(stringVar, builder.getPtrTy()); - builder.CreateCall(&printFunct, {&toPrint, cast}); + builder.CreateCall(&printFunct, {toPrint, cast}); } - /// Generates code to handle finally block type semantics: always runs /// regardless of whether a thrown exception is passing through or the /// parent function is simply exiting. In addition to printing some state @@ -996,10 +996,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(ourExceptionNotThrownState->getType(), + *exceptionCaughtFlag), + &terminatorBlock, 2); theSwitch->addCase(ourExceptionCaughtState, &terminatorBlock); theSwitch->addCase(ourExceptionThrownState, &unwindResumeBlock); @@ -1185,7 +1185,7 @@ static llvm::Function *createCatchWrappedInvokeFunction( // Note: function handles NULL exceptions builder.CreateCall(deleteOurException, - builder.CreateLoad(exceptionStorage)); + builder.CreateLoad(builder.getPtrTy(), exceptionStorage)); builder.CreateRetVoid(); // Normal Block @@ -1205,7 +1205,8 @@ static llvm::Function *createCatchWrappedInvokeFunction( builder.SetInsertPoint(unwindResumeBlock); - builder.CreateResume(builder.CreateLoad(caughtResultStorage)); + builder.CreateResume( + builder.CreateLoad(ourCaughtResultType, caughtResultStorage)); // Exception Block @@ -1240,11 +1241,9 @@ static llvm::Function *createCatchWrappedInvokeFunction( // 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( - ourUnwindExceptionType, - unwindException, - 0)); + llvm::Value *unwindExceptionClass = builder.CreateLoad( + builder.getInt64Ty(), + builder.CreateStructGEP(ourUnwindExceptionType, unwindException, 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. @@ -1275,8 +1274,8 @@ static llvm::Function *createCatchWrappedInvokeFunction( // (OurException instance). // // Note: ourBaseFromUnwindOffset is usually negative - llvm::Value *typeInfoThrown = builder.CreateConstGEP1_64(unwindException, - ourBaseFromUnwindOffset)); + llvm::Value *typeInfoThrown = builder.CreateConstGEP1_64( + builder.getInt8Ty(), unwindException, ourBaseFromUnwindOffset); // Retrieve thrown exception type info type // @@ -1285,17 +1284,14 @@ static llvm::Function *createCatchWrappedInvokeFunction( typeInfoThrown = builder.CreateStructGEP(ourExceptionType, typeInfoThrown, 0); llvm::Value *typeInfoThrownType = - builder.CreateStructGEP(builder.getPtrTy(), typeInfoThrown, 0); + builder.CreateStructGEP(ourTypeInfoType, typeInfoThrown, 0); - generateIntegerPrint(context, - module, - builder, - *toPrint32Int, - *(builder.CreateLoad(typeInfoThrownType)), + llvm::Value *ti32 = + builder.CreateLoad(builder.getInt32Ty(), typeInfoThrownType); + generateIntegerPrint(context, module, builder, *toPrint32Int, ti32, "Gen: Exception type <%d> received (stack unwound) " " in " + - ourId + - ".\n", + ourId + ".\n", USE_GLOBAL_STR_CONSTS); // 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) { nextTypeToCatch = i - 1; - switchToCatchBlock->addCase(llvm::ConstantInt::get( - llvm::Type::getInt32Ty(context), i), + switchToCatchBlock->addCase(llvm::ConstantInt::get(builder.getInt32Ty(), i), catchBlocks[nextTypeToCatch]); } @@ -1383,14 +1378,10 @@ createThrowExceptionFunction(llvm::Module &module, llvm::IRBuilder<> &builder, builder.SetInsertPoint(entryBlock); llvm::Function *toPrint32Int = module.getFunction("print32Int"); - generateIntegerPrint(context, - module, - builder, - *toPrint32Int, - *exceptionType, - "\nGen: About to throw exception type <%d> in " + - ourId + - ".\n", + generateIntegerPrint(context, module, builder, *toPrint32Int, + builder.CreateZExt(exceptionType, builder.getInt32Ty()), + "\nGen: About to throw exception type <%d> in " + ourId + + ".\n", USE_GLOBAL_STR_CONSTS); // 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 typeToThrow type info type of generated exception to throw, or /// indicator to cause foreign exception to be thrown. -static -void runExceptionThrow(llvm::ExecutionEngine *engine, - llvm::Function *function, - int32_t typeToThrow) { +static void runExceptionThrow(llvm::orc::LLJIT *JIT, std::string function, + int32_t typeToThrow) { // Find test's function pointer OurExceptionThrowFunctType functPtr = - reinterpret_cast( - reinterpret_cast(engine->getPointerToFunction(function))); + ExitOnErr(JIT->lookup(function)).toPtr(); try { // Run test @@ -1579,8 +1567,6 @@ void runExceptionThrow(llvm::ExecutionEngine *engine, // End test functions // -typedef llvm::ArrayRef TypeArray; - /// This initialization routine creates type info globals and /// adds external function declarations to module. /// @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 - 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); } - // If not set, exception handling will not be turned on - llvm::TargetOptions Opts; - llvm::InitializeNativeTarget(); llvm::InitializeNativeTargetAsmPrinter(); - llvm::LLVMContext Context; - llvm::IRBuilder<> theBuilder(Context); + auto Context = std::make_unique(); + llvm::IRBuilder<> theBuilder(*Context); // Make the module, which holds all the code. std::unique_ptr Owner = - std::make_unique("my cool jit", Context); + std::make_unique("my cool jit", *Context); llvm::Module *module = Owner.get(); - std::unique_ptr MemMgr(new llvm::SectionMemoryManager()); + // Build LLJIT + std::unique_ptr JIT = + ExitOnErr(llvm::orc::LLJITBuilder().create()); - // Build engine with JIT - llvm::EngineBuilder factory(std::move(Owner)); - factory.setEngineKind(llvm::EngineKind::JIT); - factory.setTargetOptions(Opts); - factory.setMCJITMemoryManager(std::move(MemMgr)); - llvm::ExecutionEngine *executionEngine = factory.create(); + // Set up the optimizer pipeline. + llvm::legacy::FunctionPassManager fpm(module); - { - 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 + // Optimizations turned on #ifdef ADD_OPT_PASSES - // Basic AliasAnslysis support for GVN. - fpm.add(llvm::createBasicAliasAnalysisPass()); + // Basic AliasAnslysis support for GVN. + fpm.add(llvm::createBasicAliasAnalysisPass()); - // Promote allocas to registers. - fpm.add(llvm::createPromoteMemoryToRegisterPass()); + // Promote allocas to registers. + fpm.add(llvm::createPromoteMemoryToRegisterPass()); - // Do simple "peephole" optimizations and bit-twiddling optzns. - fpm.add(llvm::createInstructionCombiningPass()); + // Do simple "peephole" optimizations and bit-twiddling optzns. + fpm.add(llvm::createInstructionCombiningPass()); - // Reassociate expressions. - fpm.add(llvm::createReassociatePass()); + // Reassociate expressions. + fpm.add(llvm::createReassociatePass()); - // Eliminate Common SubExpressions. - fpm.add(llvm::createGVNPass()); + // Eliminate Common SubExpressions. + fpm.add(llvm::createGVNPass()); - // Simplify the control flow graph (deleting unreachable - // blocks, etc). - fpm.add(llvm::createCFGSimplificationPass()); + // Simplify the control flow graph (deleting unreachable + // blocks, etc). + fpm.add(llvm::createCFGSimplificationPass()); #endif // ADD_OPT_PASSES - fpm.doInitialization(); + fpm.doInitialization(); - // Generate test code using function throwCppException(...) as - // the function which throws foreign exceptions. - llvm::Function *toRun = - createUnwindExceptionTest(*module, - theBuilder, - fpm, - "throwCppException"); + // Generate test code using function throwCppException(...) as + // the function which throws foreign exceptions. + createUnwindExceptionTest(*module, theBuilder, fpm, "throwCppException"); - executionEngine->finalizeObject(); + ExitOnErr(JIT->addIRModule( + llvm::orc::ThreadSafeModule(std::move(Owner), std::move(Context)))); #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 - fprintf(stderr, "\n\nBegin Test:\n"); + fprintf(stderr, "\n\nBegin Test:\n"); + std::string toRun = "outerCatchFunct"; - for (int i = 1; i < argc; ++i) { - // Run test for each argument whose value is the exception - // type to throw. - runExceptionThrow(executionEngine, - toRun, - (unsigned) strtoul(argv[i], NULL, 10)); - } - - fprintf(stderr, "\nEnd Test:\n\n"); + for (int i = 1; i < argc; ++i) { + // Run test for each argument whose value is the exception + // type to throw. + runExceptionThrow(JIT.get(), toRun, (unsigned)strtoul(argv[i], NULL, 10)); } - delete executionEngine; + fprintf(stderr, "\nEnd Test:\n\n"); return 0; }