Created
December 18, 2019 10:41
-
-
Save o-/f09a075a39c67b7da42dc29b93f8755f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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