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