Skip to content

Instantly share code, notes, and snippets.

@o-
Created December 18, 2019 10:41
Show Gist options
  • Save o-/f09a075a39c67b7da42dc29b93f8755f to your computer and use it in GitHub Desktop.
Save o-/f09a075a39c67b7da42dc29b93f8755f to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <llvm-c/Core.h>
#include <llvm-c/ExecutionEngine.h>
#include <llvm-c/Target.h>
#include <llvm-c/Analysis.h>
typedef void(*VoidFun)();
static void callMe() {
puts("it works");
}
// compile with
// cc `llvm-config --cflags --ldflags --system-libs --libs core engine`
int main(int argc, char **argv)
{
LLVMLinkInMCJIT();
LLVMInitializeNativeTarget();
LLVMInitializeNativeAsmPrinter();
LLVMExecutionEngineRef engine;
LLVMModuleRef module = LLVMModuleCreateWithName("");
LLVMBuilderRef builder = LLVMCreateBuilder();
char* msg;
if(LLVMCreateExecutionEngineForModule(&engine, module, &msg) == 1) {
fprintf(stderr, "%s\n", msg);
return 1;
}
// Declare a function to llvm
LLVMTypeRef voidFunT = LLVMFunctionType(
LLVMVoidType(), // return type
NULL, // formal args
0, // number of args
0);
LLVMValueRef fun = LLVMAddFunction(module, "fun", voidFunT);
LLVMSetLinkage(fun, LLVMExternalLinkage);
// Create a basic block
LLVMBasicBlockRef block = LLVMAppendBasicBlock(fun, "entry");
LLVMPositionBuilderAtEnd(builder, block);
// Emit a call to the callback by its address
// 1. Create a constant integer with the address
LLVMValueRef callbackAddr = LLVMConstInt(LLVMInt64Type(), (uintptr_t)&callMe, 0);
// 2. Cast it to a function pointer
LLVMTypeRef voidFunPtrT = LLVMPointerType(voidFunT, 0);
LLVMValueRef callback = LLVMBuildIntToPtr(builder, callbackAddr, voidFunPtrT, "callback");
// 3. Emit call
LLVMBuildCall(builder, callback, NULL, 0, "");
// Add a return instruction
LLVMBuildRet(builder, NULL);
// Print the generated IR to the console
LLVMDumpModule(module);
// Verify the whole module
if(LLVMVerifyFunction(fun, LLVMPrintMessageAction) == 1) {
fprintf(stderr, "Invalid function");
return 1;
}
// Compile the function and get back a function pointer
void (*compiled)() = (VoidFun)(uintptr_t)LLVMGetPointerToGlobal(engine, fun);
// Call the compiled function with a test function as callback. expect to
// see "it works" being printed
puts("calling compiled function:");
compiled();
// Done
LLVMDisposeBuilder(builder);
LLVMDisposeModule(module);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment