Created
October 11, 2014 17:00
-
-
Save sbourdeauducq/110330e158114ae2848a to your computer and use it in GitHub Desktop.
basic llvmpy example without llvmpy
This file contains hidden or 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
from cffi import FFI | |
ffi = FFI() | |
ffi.cdef(""" | |
typedef int LLVMBool; | |
void LLVMDisposeMessage(char *Message); | |
typedef struct LLVMOpaqueModule *LLVMModuleRef; | |
LLVMModuleRef LLVMModuleCreateWithName(const char *ModuleID); | |
char *LLVMPrintModuleToString(LLVMModuleRef M); | |
void LLVMDisposeModule(LLVMModuleRef M); | |
typedef struct LLVMOpaqueType *LLVMTypeRef; | |
LLVMTypeRef LLVMIntType(unsigned NumBits); | |
LLVMTypeRef LLVMFunctionType(LLVMTypeRef ReturnType, | |
LLVMTypeRef *ParamTypes, unsigned ParamCount, | |
LLVMBool IsVarArg); | |
char *LLVMPrintTypeToString(LLVMTypeRef Val); | |
typedef struct LLVMOpaqueValue *LLVMValueRef; | |
LLVMValueRef LLVMAddFunction(LLVMModuleRef M, const char *Name, | |
LLVMTypeRef FunctionTy); | |
LLVMValueRef LLVMGetParam(LLVMValueRef Fn, unsigned Index); | |
typedef struct LLVMOpaqueBasicBlock *LLVMBasicBlockRef; | |
LLVMBasicBlockRef LLVMAppendBasicBlock(LLVMValueRef Fn, const char *Name); | |
typedef struct LLVMOpaqueBuilder *LLVMBuilderRef; | |
LLVMBuilderRef LLVMCreateBuilder(void); | |
void LLVMPositionBuilderAtEnd(LLVMBuilderRef Builder, LLVMBasicBlockRef Block); | |
void LLVMDisposeBuilder(LLVMBuilderRef Builder); | |
LLVMValueRef LLVMBuildAdd(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, | |
const char *Name); | |
LLVMValueRef LLVMBuildRet(LLVMBuilderRef, LLVMValueRef V); | |
void LLVMSetValueName(LLVMValueRef Val, const char *Name); | |
char *LLVMPrintValueToString(LLVMValueRef Val); | |
""") | |
C = ffi.dlopen("/home/sb/llvmtest/lib/libLLVMCore.so") | |
def _message_to_str(s): | |
r = ffi.string(s) | |
C.LLVMDisposeMessage(s) | |
return r.decode() | |
class Module: | |
def __init__(self, ptr): | |
self._ptr = ptr | |
@staticmethod | |
def new(name): | |
return Module(C.LLVMModuleCreateWithName(name.encode())) | |
def add_function(self, ty, name): | |
return Function(C.LLVMAddFunction(self._ptr, name.encode(), ty._ptr)) | |
def __del__(self): | |
C.LLVMDisposeModule(self._ptr) | |
def __str__(self): | |
return _message_to_str(C.LLVMPrintModuleToString(self._ptr)) | |
class Type: | |
def __init__(self, ptr): | |
self._ptr = ptr | |
@staticmethod | |
def int(bits=32): | |
return Type(C.LLVMIntType(bits)) | |
@staticmethod | |
def function(return_ty, param_tys, var_arg=False): | |
param_tys_array = ffi.new("LLVMTypeRef[]", [ty._ptr for ty in param_tys]) | |
param_tys_count = len(param_tys_array) | |
return Type(C.LLVMFunctionType(return_ty._ptr, param_tys_array, param_tys_count, var_arg)) | |
def __str__(self): | |
return _message_to_str(C.LLVMPrintTypeToString(self._ptr)) | |
class Value: | |
def __init__(self, ptr): | |
self._ptr = ptr | |
def _get_name(self): | |
return ffi.string(C.LLVMGetValueName(self._ptr)) | |
def _set_name(self, value): | |
C.LLVMSetValueName(self._ptr, value.encode()) | |
name = property(_get_name, _set_name) | |
class FunctionArg(Value): | |
def __init__(self, function, index): | |
self.function = function | |
Value.__init__(self, C.LLVMGetParam(function._ptr, index)) | |
class FunctionArgs: | |
def __init__(self, function): | |
self.function = function | |
def __getitem__(self, key): | |
if isinstance(key, int): | |
return FunctionArg(self.function, key) | |
else: | |
return [FunctionArg(self.function, i) for i in range(key.start, key.stop, key.step)] | |
class Function: | |
def __init__(self, ptr): | |
self._ptr = ptr | |
self.args = FunctionArgs(self) | |
def append_basic_block(self, name): | |
return BasicBlock(C.LLVMAppendBasicBlock(self._ptr, name.encode())) | |
class BasicBlock: | |
def __init__(self, ptr): | |
self._ptr = ptr | |
class Builder: | |
def __init__(self, ptr): | |
self._ptr = ptr | |
@staticmethod | |
def new(basic_block): | |
r = Builder(C.LLVMCreateBuilder()) | |
r.position_at_end(basic_block) | |
return r | |
def position_at_end(self, bblk): | |
C.LLVMPositionBuilderAtEnd(self._ptr, bblk._ptr) | |
def add(self, lhs, rhs, name=""): | |
return Value(C.LLVMBuildAdd(self._ptr, lhs._ptr, rhs._ptr, name.encode())) | |
def ret(self, value): | |
return Value(C.LLVMBuildRet(self._ptr, value._ptr)) | |
def __del__(self): | |
C.LLVMDisposeBuilder(self._ptr) | |
my_module = Module.new("my_module") | |
ty_int = Type.int() | |
ty_func = Type.function(ty_int, [ty_int, ty_int]) | |
f_sum = my_module.add_function(ty_func, "sum") | |
f_sum.args[0].name = "a" | |
f_sum.args[1].name = "b" | |
bb = f_sum.append_basic_block("entry") | |
builder = Builder.new(bb) | |
tmp = builder.add(f_sum.args[0], f_sum.args[1], "tmp") | |
builder.ret(tmp) | |
print(my_module) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment