Skip to content

Instantly share code, notes, and snippets.

@sbourdeauducq
Created October 11, 2014 17:00
Show Gist options
  • Save sbourdeauducq/110330e158114ae2848a to your computer and use it in GitHub Desktop.
Save sbourdeauducq/110330e158114ae2848a to your computer and use it in GitHub Desktop.
basic llvmpy example without llvmpy
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