Python has a package called llvmlite, which was very useful! What a LLVM IR can easily output! I think it's a great first step for LLVM.
That's why I'll try "installing llvmlite"-"trying it a little"!
I virtualized and installed Ubuntu on Windows 7 with VirtualBox. Basically, if it is an Ubuntu-derived distribution, it will work. In fact, I installed it on Linux Mint 17.3 (Cinnamon 64bit) with the same procedure, but it works fine.
Host
Virtualization software
Guest OS
Number of processors
memory
If it is not about 2GB, LLVM make will run out of memory.
Prepare to build LLVM and Python3 development environment.
$ sudo apt-get install build-essential cmake python3-dev python3-pip python3-setuptools zlib1g-dev libtool
llvmlite requires LLVM 3.6. You can get it with apt-get, but I want to manage the installation directory by myself, so I build it myself.
$ wget http://llvm.org/releases/3.6.2/llvm-3.6.2.src.tar.xz
I like to use cmake. Building LLVM takes a bit of time, so wait patiently. (Use make -j4 for parallel build)
$ tar xvf llvm-3.6.2.src.tar.xz
$ cd llvm-3.6.2.src
$ mkdir build
$ cd build
$ cmake -D CMAKE_INSTALL_PREFIX=/usr/local/llvm-3.6 ..
$ make
$ sudo make install
Do it through the path to LLVM
export LLVM_HOME=/usr/local/llvm-3.6
export PATH=${LLVM_HOME}/bin:${PATH}
export LD_LIBRARY_PATH=${LLVM_HOME}/lib:${LD_LIBRARY_PATH}
export LLVM_CONFIG=${LLVM_HOME}/bin/llvm-config
#Also set the C include path just in case
export C_INCLUDE_PATH=${LLVM_HOME}/include:${C_INCLUDE_PATH}
export CPLUS_INCLUDE_PATH=${LLVM_HOME}/include:${CPLUS_INCLUDE_PATH}
$ llvm-config --version
3.6.2
Install what you probably need. Some may be unnecessary. The Python library is apt-get, pip, and there are many ways to install it. Only scipy and matplotlib couldn't be pip, so I installed it with apt-get.
$ sudo -E pip3 install numpy
$ sudo apt-get install python3-scipy python3-matplotlib
$ sudo -E pip3 install pandas statsmodels sympy
Quickly install llvmlite with pip
$ sudo -E pip3 install llvmlite
That's it!
Let's try it out! If you can run the following Python file, it's working!
Below is a sample I made appropriately.
from ctypes import CFUNCTYPE, c_int
import llvmlite.ir as ll
import llvmlite.binding as llvm
"""
Make this with LLVM IR.
def func(x, y):
a = x
b = y
c = 1000
d = a
return a + b + c + d
"""
#Initialization
llvm.initialize()
llvm.initialize_native_target()
llvm.initialize_native_asmprinter()
i32 = ll.IntType(32)
# int func(int, int)
fnty = ll.FunctionType(i32, [i32, i32])
module = ll.Module()
func = ll.Function(module, fnty, name="func")
bb_entry = func.append_basic_block()
builder = ll.IRBuilder()
builder.position_at_end(bb_entry)
#Argument x, y
x, y = func.args
#Variable a,b,c,Define d
ptr_a = builder.alloca(i32)
ptr_b = builder.alloca(i32)
ptr_c = builder.alloca(i32)
ptr_d = builder.alloca(i32)
# store
builder.store(x, ptr_a)
builder.store(y, ptr_b)
builder.store(ll.Constant(i32, 1000), ptr_c)
# load
a = builder.load(ptr_a)
b = builder.load(ptr_b)
c = builder.load(ptr_c)
#Also store
builder.store(a, ptr_d)
#Add and return
ret1 = builder.add(a, b, name="res")
ret2 = builder.add(ret1, c, name="res2")
ret3 = builder.add(ret2, builder.load(ptr_d), name="res3")
builder.ret(ret3)
llvm_ir = str(module)
llvm_ir_parsed = llvm.parse_assembly(llvm_ir)
print("== LLVM IR ====================")
print(llvm_ir_parsed)
# pass
pmb = llvm.create_pass_manager_builder()
pmb.opt_level = 1
pm = llvm.create_module_pass_manager()
pmb.populate(pm)
pm.run(llvm_ir_parsed)
print("== LLVM IR(opt) ===============")
print(llvm_ir_parsed)
target_machine = llvm.Target.from_default_triple().create_target_machine()
print("== Result =====================")
with llvm.create_mcjit_compiler(llvm_ir_parsed, target_machine) as ee:
ee.finalize_object()
cfptr = ee.get_function_address("func")
cfunc = CFUNCTYPE(c_int, c_int, c_int)(cfptr)
res = cfunc(100, 2)
print("res: " + str(res))
== LLVM IR ====================
; ModuleID = '<string>'
target triple = "unknown-unknown-unknown"
define i32 @func(i32 %.1, i32 %.2) {
.4:
%.5 = alloca i32
%.6 = alloca i32
%.7 = alloca i32
%.8 = alloca i32
store i32 %.1, i32* %.5
store i32 %.2, i32* %.6
store i32 1000, i32* %.7
%.12 = load i32* %.5
%.13 = load i32* %.6
%.14 = load i32* %.7
store i32 %.12, i32* %.8
%res = add i32 %.12, %.13
%res2 = add i32 %res, %.14
%.16 = load i32* %.8
%res3 = add i32 %res2, %.16
ret i32 %res3
}
== LLVM IR(opt) ===============
; ModuleID = '<string>'
target triple = "unknown-unknown-unknown"
; Function Attrs: nounwind readnone
define i32 @func(i32 %.1, i32 %.2) #0 {
.4:
%factor = shl i32 %.1, 1
%res2 = add i32 %.2, 1000
%res3 = add i32 %res2, %factor
ret i32 %res3
}
attributes #0 = { nounwind readnone }
== Result =====================
res: 1202
Looking at LLVM IR (opt). You can see that there is no useless part such as store.
example There is also an example on the original Github, so you can refer to it. https://github.com/numba/llvmlite
The LLVM head family has a tutorial called kaleidoscope. The following is an implementation of it with llvmlite, which is very helpful, so I will introduce it.
https://github.com/eliben/pykaleidoscope
Recommended Posts