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.
Related
I want to instrument some code that gets executed before any other code in my module.
I thought about calling the code in the start of the main function. But there is not always a main function or it is not always named "main". Or it is a library and it doesn't even have a main function.
Are there some other, smarter ways?
You can put the code you want to run early into a function and add that function to llvm.global_ctors. This is the equivalent of using __attribute__((constructor)) in C or C++.
To do this from a pass, you can use the llvm::appendToGlobalCtors function, which is declared in llvm/Transforms/Utils/ModuleUtils.h.
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'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.
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'm trying to compile a lua script that calls some exported functions, save the resulting bytecode to a file and then load this bytecode and execute it, but I haven't found any example on how to do this. Is there any example available on how to do this? How can I do this?
Edit: I'm using Lua + Luabind (C++)
This is all very simple.
First, you load the Lua script without executing it. It does not matter if you have connected the Lua state with your exported functions; all you're doing is compiling the script file.
You could use luaL_loadfile, which uses C-standard library functions to read a file from disk and load it into the lua_State. Alternatively, you can load the file yourself into a string and use luaL_loadstring to load it into the lua_State.
Both of these functions will emit return values and compiler errors as per the documentation for lua_load.
If the compilation was successful, the lua_State now has the compiled Lua chunk as a Lua function at the top of the stack. To get the compiled binary, you must use the lua_dump function. It's rather complicated as it uses a callback interface to pass you data. See the documentation for details.
After that process, you have the compiled Lua byte code. Shove that into a file of your choice. Just remember: write it as binary, not with text translation.
When it comes time to load the byte code, all you need to do is... exactly what you did before. Well, almost. Lua has heuristics to detect that a "string" it is given is a Lua source string or byte code. So yes, you can load byte code with luaL_loadfile just like before.
The difference is that you can't use luaL_loadstring with byte code. That function expects a NULL-terminated string, which is bad. Byte code can have embedded NULL characters in it, which would screw everything up. So if you want to do the file IO yourself (because you're using a special filesystem or something), you have to use lua_load directly (or luaL_loadbuffer). Which also uses a callback interface like lua_dump. So read up on how to use it.