Last active
October 5, 2022 09:26
-
-
Save paulsmith/b3778ec32aa7b7d93c7b to your computer and use it in GitHub Desktop.
Simple integer sum function, JIT'ed with the LLVM C API
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
CC=clang | |
CXX=clang++ | |
all: sum | |
sum.o: sum.c | |
$(CC) -g `llvm-config --cflags` -c $< | |
sum: sum.o | |
$(CXX) `llvm-config --cxxflags --ldflags --libs core executionengine jit interpreter analysis native --system-libs` $< -o $@ | |
clean: | |
-rm -f sum.o sum |
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
/** | |
* LLVM equivalent of: | |
* | |
* int sum(int a, int b) { | |
* return a + b; | |
* } | |
*/ | |
#include <llvm-c/Core.h> | |
#include <llvm-c/ExecutionEngine.h> | |
#include <llvm-c/Target.h> | |
#include <llvm-c/Analysis.h> | |
#include <inttypes.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
int main(int argc, char const *argv[]) { | |
LLVMLinkInJIT(); | |
LLVMInitializeNativeTarget(); | |
LLVMModuleRef mod = LLVMModuleCreateWithName("my_module"); | |
LLVMTypeRef param_types[] = { LLVMInt32Type(), LLVMInt32Type() }; | |
LLVMTypeRef ret_type = LLVMFunctionType(LLVMInt32Type(), param_types, 2, 0); | |
LLVMValueRef sum = LLVMAddFunction(mod, "sum", ret_type); | |
LLVMBasicBlockRef entry = LLVMAppendBasicBlock(sum, "entry"); | |
LLVMBuilderRef builder = LLVMCreateBuilder(); | |
LLVMPositionBuilderAtEnd(builder, entry); | |
LLVMValueRef tmp = LLVMBuildAdd(builder, LLVMGetParam(sum, 0), LLVMGetParam(sum, 1), "tmp"); | |
LLVMBuildRet(builder, tmp); | |
char *error = NULL; | |
LLVMVerifyModule(mod, LLVMAbortProcessAction, &error); | |
LLVMDisposeMessage(error); | |
LLVMExecutionEngineRef engine; | |
error = NULL; | |
if (LLVMCreateExecutionEngineForModule(&engine, mod, &error) != 0) { | |
fprintf(stderr, "create ee failed\n"); | |
abort(); | |
} | |
if (error) { | |
fprintf(stderr, "err: %s\n", error); | |
LLVMDisposeMessage(error); | |
exit(EXIT_FAILURE); | |
} | |
if (argc < 3) { | |
fprintf(stderr, "usage: %s x y\n", argv[0]); | |
exit(EXIT_FAILURE); | |
} | |
long long x = strtoll(argv[1], NULL, 10); | |
long long y = strtoll(argv[2], NULL, 10); | |
LLVMGenericValueRef args[] = { | |
LLVMCreateGenericValueOfInt(LLVMInt32Type(), x, 0), | |
LLVMCreateGenericValueOfInt(LLVMInt32Type(), y, 0) | |
}; | |
LLVMGenericValueRef res = LLVMRunFunction(engine, sum, 2, args); | |
printf("%d\n", (int)LLVMGenericValueToInt(res, 0)); | |
LLVMDisposeBuilder(builder); | |
LLVMDisposeExecutionEngine(engine); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment