I've got such a problem. I've written my own IR code generator. It saves IR into a string. And now I want to JIT compile this IR code using LLVM. But all functions and API's I've found only gets llvm::Function as an arg. But how can I compile an IR code saved in the string?
You need the llvm::parseIR function defined here.
Related
I'm working on a library which I'd like certain introspection features to be available. Let's say I'm compiling with clang, so I have access to libtooling or whatever.
What I'd like specifically is for someone to be able to view the LLVM IR of an already-compiled function as part of the program. I know that, when compiling, I can use -emit-llvm to get the IR. But that saves it to a file. What I'd like is for the LLVM IR to be embedded in and retrievable from the program itself -- e.g. my_function_object.llvm_ir()
Is such a thing possible? Thanks!
You're basically trying to have reflection to your program. Reflection requires the existence of metadata in your binary. This doesn't exist out of the box in LLVM, as far as I know.
To achieve an effect like this, you could create a global key-value dictionary in your program, exposed via an exported function - something like IRInstruction* retrieve_llvm_ir_stream(char* name).
This dictionary would map some kind of identifier (for example, the exported name) of a given function to an in-memory array that represents the IR stream of that function (each instruction represented as a custom IRInstruction struct, for example). The types and functions of the representation format (like the custom IRInstruction struct) will have to be included in your source.
At the step of the IR generation, this dictionary will be empty. Immediately after the IR generation step, you'll need to add a custom build step: open the IR file and populate the dictionary with the data - for each exported function of your program, inject its name as a key to the dictionary and its IR stream as a value. The IR stream would be generated from the definitions of your functions, as read by your custom build tool (which would leverage the LLVM API to read the generated IR and convert it to your format).
Then, proceed to the assembler and linker as before.
I am wondering how to convert Julia code into runnable LLVM IR(the *.ll file).
There is a command named code_llvm which can compile a Julia function into LLVM IR. But its result contains something like %jl_value_t* which seems to be an (hidden?) object type, and it doesn't look like pure LLVM IR.
Is there a way to generate runnable LLVM IR from Julia, so that I can run it with lli xx.ll (or do something else)?
The code_llvm function just shows the Function by default, but you can also have it print out a complete module:
open("file.ll", "w") do io
code_llvm(io, +, (Int, Int); raw=true, dump_module=true, optimize=true)
end
This output (file.ll) is now valid to use with other llvm tools, such as llc and opt. However, since it's just the code for this one function, and assumes the existence of all the other code and data, it's not necessarily going to work with lli, so buyer beware.
If you want a complete system, you might be interested in the --output-bc flag to Julia, which will dump a complete object file in LLVM format. This is used extensively internally to build and bootstrap Julia. It's also wrapped into a utility tool at https://github.com/JuliaLang/PackageCompiler.jl to automate some of these steps.
I want a c program to execute a function using llvm IR instead of the c code.
Is it possible?
I do not want to convert the entire module.
Only one function needs to be called in the end.
Are there any helper methods to traverse the AST, basic blocks etc. generated by LLVM compiler for a C code ?
If you're trying to load a module (from a .bc file compiled from a .c file by clang -emit-llvm) and traverse its functions, basic blocks, etc., then you might want to start with the llvm::Module class. It has functions for iterating through global variables and functions. Then the llvm::Function class has functions for iterating through basic blocks. Then the llvm::BasicBlock class has functions for iterating through instructions.
Or if you'd prefer, you can traverse the AST structure created by Clang. Here's some example code: http://eli.thegreenplace.net/2012/06/08/basic-source-to-source-transformation-with-clang/.
Basically, it is impossible to do full operations on the AST in LLVM. Because the LLVM pass works on bitcode level not on the AST. I think what you want is an AST iterator.
You could refer to Chapter 3 in Artem Degrachev: Clang Static Analyzer: A Checker Developer's Guide.
Clang now have a page for checker developers. You could find more following the link.
I want to read (parse) LLVM IR code (which is saved in a text file) and add some of my own code to it. I need some example of doing this, that is, how this is done by using the libraries provided by LLVM for this purpose. So basically what I want is to read in the IR code from a text file into the memory (perhaps the LLVM library represents it in AST form, I dont know), make modifications, like adding some more nodes in the AST and then finally write back the AST in the IR text file.
Although I need to both read and modify the IR code, I would greatly appreciate if someone could provide or refer me to some example which just read (parses) it.
First, to fix an obvious misunderstanding: LLVM is a framework for manipulating code in IR format. There are no ASTs in sight (*) - you read IR, transform/manipulate/analyze it, and you write IR back.
Reading IR is really simple:
int main(int argc, char** argv)
{
if (argc < 2) {
errs() << "Expected an argument - IR file name\n";
exit(1);
}
LLVMContext &Context = getGlobalContext();
SMDiagnostic Err;
Module *Mod = ParseIRFile(argv[1], Err, Context);
if (!Mod) {
Err.print(argv[0], errs());
return 1;
}
[...]
}
This code accepts a file name. This should be an LLVM IR file (textual). It then goes on to parse it into a Module, which represents a module of IR in LLVM's internal in-memory format. This can then be manipulated with the various passes LLVM has or you add on your own. Take a look at some examples in the LLVM code base (such as lib/Transforms/Hello/Hello.cpp) and read this - http://llvm.org/docs/WritingAnLLVMPass.html.
Spitting IR back into a file is even easier. The Module class just writes itself to a stream:
some_stream << *Mod;
That's it.
Now, if you have any specific questions about specific modifications you want to do to IR code, you should really ask something more focused. I hope this answer shows you how to parse IR and write it back.
(*) IR doesn't have an AST representation inside LLVM, because it's a simple assembly-like language. If you go one step up, to C or C++, you can use Clang to parse that into ASTs, and then do manipulations at the AST level. Clang then knows how to produce LLVM IR from its AST. However, you do have to start with C/C++ here, and not LLVM IR. If LLVM IR is all you care about, forget about ASTs.
This is usually done by implementing an LLVM pass/transform. This way you don't have to parse the IR at all because LLVM will do it for you and you will operate on a object-oriented in-memory representation of the IR.
This is the entry point for writing an LLVM pass. Then you can look at any of the already implemented standard passes that come bundled with LLVM (look into lib/Transforms).
The Opt tool takes llvm IR code, runs a pass on it, and then spits out transformed llvm IR on the other side.
The easiest to start hacking is lib\Transforms\Hello\Hello.cpp. Hack it, run through opt with your source file as input, inspect output.
Apart from that, the docs for writing passes is really quite good.
The easiest way to do this is to look at one of the existing tools and steal code from it. In this case, you might want to look at the source for llc. It can take either a bitcode or .ll file as input. You can modify the input file any way you want and then write out the file using something similar to the code in llvm-dis if you want a text file.
As mentioned above the best way it to write a pass. But if you want to simply iterate through the instructions and do something with the LLVM provided an InstVisitor class. It is a class that implements the visitor pattern for instructions. It is very straight forward to user, so if you want to avoid learning how to implement a pass, you could resort to that.