1 //===------- HowToUseLLJIT.cpp - An example use of ORC-based LLJIT --------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This small program provides an example of how to quickly build a small 10 // module with a 'add1' function and use of IRBuilder to create add & return 11 // instructions. 12 // 13 // Goal: 14 // The goal of this snippet is to create in the memory 15 // the LLVM module consisting of a function as follow: 16 // 17 // int add1(int x) { 18 // return x+1; 19 // } 20 // add1(42); 21 // 22 // then compile the module via LLJIT, then execute the 'add1' 23 // function and return result to a driver, i.e. to a "host program". 24 // 25 //===----------------------------------------------------------------------===// 26 27 #include "llvm/ExecutionEngine/Orc/LLJIT.h" 28 #include "llvm/IR/Function.h" 29 #include "llvm/IR/IRBuilder.h" 30 #include "llvm/IR/Module.h" 31 #include "llvm/Support/CommandLine.h" 32 #include "llvm/Support/InitLLVM.h" 33 #include "llvm/Support/TargetSelect.h" 34 #include "llvm/Support/raw_ostream.h" 35 36 using namespace llvm; 37 using namespace llvm::orc; 38 39 ExitOnError ExitOnErr; 40 41 ThreadSafeModule createDemoModule() { 42 auto Context = std::make_unique<LLVMContext>(); 43 auto M = std::make_unique<Module>("test", *Context); 44 45 // Create the add1 function entry and insert this entry into module M. The 46 // function will have a return type of "int" and take an argument of "int". 47 Function *Add1F = 48 Function::Create(FunctionType::get(Type::getInt32Ty(*Context), 49 {Type::getInt32Ty(*Context)}, false), 50 Function::ExternalLinkage, "add1", M.get()); 51 52 // Add a basic block to the function. As before, it automatically inserts 53 // because of the last argument. 54 BasicBlock *BB = BasicBlock::Create(*Context, "EntryBlock", Add1F); 55 56 // Create a basic block builder with default parameters. The builder will 57 // automatically append instructions to the basic block `BB'. 58 IRBuilder<> builder(BB); 59 60 // Get pointers to the constant `1'. 61 Value *One = builder.getInt32(1); 62 63 // Get pointers to the integer argument of the add1 function... 64 assert(Add1F->arg_begin() != Add1F->arg_end()); // Make sure there's an arg 65 Argument *ArgX = &*Add1F->arg_begin(); // Get the arg 66 ArgX->setName("AnArg"); // Give it a nice symbolic name for fun. 67 68 // Create the add instruction, inserting it into the end of BB. 69 Value *Add = builder.CreateAdd(One, ArgX); 70 71 // Create the return instruction and add it to the basic block 72 builder.CreateRet(Add); 73 74 return ThreadSafeModule(std::move(M), std::move(Context)); 75 } 76 77 int main(int argc, char *argv[]) { 78 // Initialize LLVM. 79 InitLLVM X(argc, argv); 80 81 InitializeNativeTarget(); 82 InitializeNativeTargetAsmPrinter(); 83 84 cl::ParseCommandLineOptions(argc, argv, "HowToUseLLJIT"); 85 ExitOnErr.setBanner(std::string(argv[0]) + ": "); 86 87 // Create an LLJIT instance. 88 auto J = ExitOnErr(LLJITBuilder().create()); 89 auto M = createDemoModule(); 90 91 ExitOnErr(J->addIRModule(std::move(M))); 92 93 // Look up the JIT'd function, cast it to a function pointer, then call it. 94 auto Add1Sym = ExitOnErr(J->lookup("add1")); 95 int (*Add1)(int) = (int (*)(int))Add1Sym.getAddress(); 96 97 int Result = Add1(42); 98 outs() << "add1(42) = " << Result << "\n"; 99 100 return 0; 101 } 102