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>(args: "test" , args&: *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(Ty: FunctionType::get(Result: Type::getInt32Ty(C&: *Context), |
49 | Params: {Type::getInt32Ty(C&: *Context)}, isVarArg: false), |
50 | Linkage: Function::ExternalLinkage, N: "add1" , M: 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&: *Context, Name: "EntryBlock" , Parent: 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(C: 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(LHS: One, RHS: ArgX); |
70 | |
71 | // Create the return instruction and add it to the basic block |
72 | builder.CreateRet(V: 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, Overview: "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(TSM: std::move(M))); |
92 | |
93 | // Look up the JIT'd function, cast it to a function pointer, then call it. |
94 | auto Add1Addr = ExitOnErr(J->lookup(UnmangledName: "add1" )); |
95 | int (*Add1)(int) = Add1Addr.toPtr<int(int)>(); |
96 | |
97 | int Result = Add1(42); |
98 | outs() << "add1(42) = " << Result << "\n" ; |
99 | |
100 | return 0; |
101 | } |
102 | |