Skip to content

Commit 159f632

Browse files
committedDec 5, 2014
switch to llvmlite
1 parent b93b969 commit 159f632

16 files changed

+258
-303
lines changed
 

‎artiq/coredevice/runtime.py

+45-45
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import os
2-
from fractions import Fraction
32

4-
from llvm import core as lc
5-
from llvm import target as lt
3+
import llvmlite.ir as ll
4+
import llvmlite.binding as llvm
65

76
from artiq.py2llvm import base_types
87
from artiq.language import units
98

109

11-
lt.initialize_all()
10+
llvm.initialize()
11+
llvm.initialize_all_targets()
12+
llvm.initialize_all_asmprinters()
1213

1314
_syscalls = {
1415
"rpc": "i+:i",
@@ -23,10 +24,10 @@
2324
}
2425

2526
_chr_to_type = {
26-
"n": lambda: lc.Type.void(),
27-
"b": lambda: lc.Type.int(1),
28-
"i": lambda: lc.Type.int(32),
29-
"I": lambda: lc.Type.int(64)
27+
"n": lambda: ll.VoidType(),
28+
"b": lambda: ll.IntType(1),
29+
"i": lambda: ll.IntType(32),
30+
"I": lambda: ll.IntType(64)
3031
}
3132

3233
_chr_to_value = {
@@ -45,45 +46,50 @@ def _str_to_functype(s):
4546
type_args = []
4647
for n, c in enumerate(s[:-2]):
4748
if c == "+":
48-
type_args.append(lc.Type.int())
49+
type_args.append(ll.IntType(32))
4950
var_arg_fixcount = n
5051
elif c != "n":
5152
type_args.append(_chr_to_type[c]())
5253
return (var_arg_fixcount,
53-
lc.Type.function(type_ret, type_args,
54-
var_arg=var_arg_fixcount is not None))
54+
ll.FunctionType(type_ret, type_args,
55+
var_arg=var_arg_fixcount is not None))
5556

5657

5758
class LinkInterface:
5859
def init_module(self, module):
59-
self.llvm_module = module.llvm_module
60+
self.module = module
61+
llvm_module = self.module.llvm_module
6062

6163
# syscalls
64+
self.syscalls = dict()
6265
self.var_arg_fixcount = dict()
6366
for func_name, func_type_str in _syscalls.items():
6467
var_arg_fixcount, func_type = _str_to_functype(func_type_str)
6568
if var_arg_fixcount is not None:
6669
self.var_arg_fixcount[func_name] = var_arg_fixcount
67-
self.llvm_module.add_function(func_type, "__syscall_"+func_name)
70+
self.syscalls[func_name] = ll.Function(
71+
llvm_module, func_type, "__syscall_" + func_name)
6872

6973
# exception handling
70-
func_type = lc.Type.function(lc.Type.int(), [lc.Type.pointer(lc.Type.int(8))])
71-
function = self.llvm_module.add_function(func_type, "__eh_setjmp")
72-
function.add_attribute(lc.ATTR_NO_UNWIND)
73-
function.add_attribute(lc.ATTR_RETURNS_TWICE)
74+
func_type = ll.FunctionType(ll.IntType(32),
75+
[ll.PointerType(ll.IntType(8))])
76+
self.eh_setjmp = ll.Function(llvm_module, func_type,
77+
"__eh_setjmp")
78+
self.eh_setjmp.attributes.add("nounwind")
79+
self.eh_setjmp.attributes.add("returns_twice")
7480

75-
func_type = lc.Type.function(lc.Type.pointer(lc.Type.int(8)), [])
76-
self.llvm_module.add_function(func_type, "__eh_push")
81+
func_type = ll.FunctionType(ll.PointerType(ll.IntType(8)), [])
82+
self.eh_push = ll.Function(llvm_module, func_type, "__eh_push")
7783

78-
func_type = lc.Type.function(lc.Type.void(), [lc.Type.int()])
79-
self.llvm_module.add_function(func_type, "__eh_pop")
84+
func_type = ll.FunctionType(ll.VoidType(), [ll.IntType(32)])
85+
self.eh_pop = ll.Function(llvm_module, func_type, "__eh_pop")
8086

81-
func_type = lc.Type.function(lc.Type.int(), [])
82-
self.llvm_module.add_function(func_type, "__eh_getid")
87+
func_type = ll.FunctionType(ll.IntType(32), [])
88+
self.eh_getid = ll.Function(llvm_module, func_type, "__eh_getid")
8389

84-
func_type = lc.Type.function(lc.Type.void(), [lc.Type.int()])
85-
function = self.llvm_module.add_function(func_type, "__eh_raise")
86-
function.add_attribute(lc.ATTR_NO_RETURN)
90+
func_type = ll.FunctionType(ll.VoidType(), [ll.IntType(32)])
91+
self.eh_raise = ll.Function(llvm_module, func_type, "__eh_raise")
92+
self.eh_raise.attributes.add("noreturn")
8793

8894
def build_syscall(self, syscall_name, args, builder):
8995
r = _chr_to_value[_syscalls[syscall_name][-1]]()
@@ -92,33 +98,27 @@ def build_syscall(self, syscall_name, args, builder):
9298
if syscall_name in self.var_arg_fixcount:
9399
fixcount = self.var_arg_fixcount[syscall_name]
94100
args = args[:fixcount] \
95-
+ [lc.Constant.int(lc.Type.int(), len(args) - fixcount)] \
101+
+ [ll.Constant(ll.IntType(32), len(args) - fixcount)] \
96102
+ args[fixcount:]
97-
llvm_function = self.llvm_module.get_function_named(
98-
"__syscall_" + syscall_name)
99-
r.auto_store(builder, builder.call(llvm_function, args))
103+
r.auto_store(builder, builder.call(self.syscalls[syscall_name],
104+
args))
100105
return r
101106

102107
def build_catch(self, builder):
103-
eh_setjmp = self.llvm_module.get_function_named("__eh_setjmp")
104-
eh_push = self.llvm_module.get_function_named("__eh_push")
105-
jmpbuf = builder.call(eh_push, [])
106-
exception_occured = builder.call(eh_setjmp, [jmpbuf])
107-
return builder.icmp(lc.ICMP_NE,
108-
exception_occured,
109-
lc.Constant.int(lc.Type.int(), 0))
108+
jmpbuf = builder.call(self.eh_push, [])
109+
exception_occured = builder.call(self.eh_setjmp, [jmpbuf])
110+
return builder.icmp_signed("!=",
111+
exception_occured,
112+
ll.Constant(ll.IntType(32), 0))
110113

111114
def build_pop(self, builder, levels):
112-
eh_pop = self.llvm_module.get_function_named("__eh_pop")
113-
builder.call(eh_pop, [lc.Constant.int(lc.Type.int(), levels)])
115+
builder.call(self.eh_pop, [ll.Constant(ll.IntType(32), levels)])
114116

115117
def build_getid(self, builder):
116-
eh_getid = self.llvm_module.get_function_named("__eh_getid")
117-
return builder.call(eh_getid, [])
118+
return builder.call(self.eh_getid, [])
118119

119120
def build_raise(self, builder, eid):
120-
eh_raise = self.llvm_module.get_function_named("__eh_raise")
121-
builder.call(eh_raise, [eid])
121+
builder.call(self.eh_raise, [eid])
122122

123123

124124
def _debug_dump_obj(obj):
@@ -148,8 +148,8 @@ def __init__(self, internal_ref_period):
148148
self.warmup_time = 1*units.ms
149149

150150
def emit_object(self):
151-
tm = lt.TargetMachine.new(triple=self.cpu_type, cpu="generic")
152-
obj = tm.emit_object(self.llvm_module)
151+
tm = llvm.Target.from_triple(self.cpu_type).create_target_machine()
152+
obj = tm.emit_object(self.module.llvm_module)
153153
_debug_dump_obj(obj)
154154
return obj
155155

‎artiq/py2llvm/arrays.py

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from llvm import core as lc
1+
import llvmlite.ir as ll
22

33
from artiq.py2llvm.values import VGeneric
44
from artiq.py2llvm.base_types import VInt
@@ -13,7 +13,7 @@ def __init__(self, el_init, count):
1313
raise TypeError("Arrays must have at least one element")
1414

1515
def get_llvm_type(self):
16-
return lc.Type.array(self.el_init.get_llvm_type(), self.count)
16+
return ll.ArrayType(self.el_init.get_llvm_type(), self.count)
1717

1818
def __repr__(self):
1919
return "<VArray:{} x{}>".format(repr(self.el_init), self.count)
@@ -42,7 +42,7 @@ def set_value(self, builder, v):
4242

4343
i = VInt()
4444
i.alloca(builder, "ai_i")
45-
i.auto_store(builder, lc.Constant.int(lc.Type.int(), 0))
45+
i.auto_store(builder, ll.Constant(ll.IntType(32), 0))
4646

4747
function = builder.basic_block.function
4848
copy_block = function.append_basic_block("ai_copy")
@@ -52,10 +52,10 @@ def set_value(self, builder, v):
5252
builder.position_at_end(copy_block)
5353
self.o_subscript(i, builder).set_value(builder, v.el_init)
5454
i.auto_store(builder, builder.add(
55-
i.auto_load(builder), lc.Constant.int(lc.Type.int(), 1)))
56-
cont = builder.icmp(
57-
lc.ICMP_SLT, i.auto_load(builder),
58-
lc.Constant.int(lc.Type.int(), self.count))
55+
i.auto_load(builder), ll.Constant(ll.IntType(32), 1)))
56+
cont = builder.icmp_signed(
57+
"<", i.auto_load(builder),
58+
ll.Constant(ll.IntType(32), self.count))
5959
builder.cbranch(cont, copy_block, end_block)
6060

6161
builder.position_at_end(end_block)
@@ -65,6 +65,6 @@ def o_subscript(self, index, builder):
6565
if builder is not None:
6666
index = index.o_int(builder).auto_load(builder)
6767
ssa_r = builder.gep(self.llvm_value, [
68-
lc.Constant.int(lc.Type.int(), 0), index])
68+
ll.Constant(ll.IntType(32), 0), index])
6969
r.auto_store(builder, ssa_r)
7070
return r

‎artiq/py2llvm/ast_body.py

+20-19
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import ast
2-
from llvm import core as lc
2+
3+
import llvmlite.ir as ll
34

45
from artiq.py2llvm import values, base_types, fractions, arrays, iterators
56
from artiq.py2llvm.tools import is_terminated
@@ -368,21 +369,21 @@ def _visit_stmt_Raise(self, node):
368369
if self._active_exception_stack:
369370
finally_block, propagate, propagate_eid = (
370371
self._active_exception_stack[-1])
371-
self.builder.store(lc.Constant.int(lc.Type.int(1), 1), propagate)
372+
self.builder.store(ll.Constant(ll.IntType(1), 1), propagate)
372373
if node.exc is not None:
373-
eid = lc.Constant.int(lc.Type.int(), node.exc.args[0].n)
374+
eid = ll.Constant(ll.IntType(32), node.exc.args[0].n)
374375
self.builder.store(eid, propagate_eid)
375376
self.builder.branch(finally_block)
376377
else:
377-
eid = lc.Constant.int(lc.Type.int(), node.exc.args[0].n)
378+
eid = ll.Constant(ll.IntType(32), node.exc.args[0].n)
378379
self.env.build_raise(self.builder, eid)
379380

380381
def _handle_exception(self, function, finally_block,
381382
propagate, propagate_eid, handlers):
382383
eid = self.env.build_getid(self.builder)
383384
self._active_exception_stack.append(
384385
(finally_block, propagate, propagate_eid))
385-
self.builder.store(lc.Constant.int(lc.Type.int(1), 1), propagate)
386+
self.builder.store(ll.Constant(ll.IntType(1), 1), propagate)
386387
self.builder.store(eid, propagate_eid)
387388

388389
for handler in handlers:
@@ -392,23 +393,23 @@ def _handle_exception(self, function, finally_block,
392393
self.builder.branch(handled_exc_block)
393394
else:
394395
if isinstance(handler.type, ast.Tuple):
395-
match = self.builder.icmp(
396-
lc.ICMP_EQ, eid,
397-
lc.Constant.int(lc.Type.int(),
398-
handler.type.elts[0].args[0].n))
396+
match = self.builder.icmp_signed(
397+
"==", eid,
398+
ll.Constant(ll.IntType(32),
399+
handler.type.elts[0].args[0].n))
399400
for elt in handler.type.elts[1:]:
400401
match = self.builder.or_(
401402
match,
402-
self.builder.icmp(
403-
lc.ICMP_EQ, eid,
404-
lc.Constant.int(lc.Type.int(), elt.args[0].n)))
403+
self.builder.icmp_signed(
404+
"==", eid,
405+
ll.Constant(ll.IntType(32), elt.args[0].n)))
405406
else:
406-
match = self.builder.icmp(
407-
lc.ICMP_EQ, eid,
408-
lc.Constant.int(lc.Type.int(), handler.type.args[0].n))
407+
match = self.builder.icmp_signed(
408+
"==", eid,
409+
ll.Constant(ll.IntType(32), handler.type.args[0].n))
409410
self.builder.cbranch(match, handled_exc_block, cont_exc_block)
410411
self.builder.position_at_end(handled_exc_block)
411-
self.builder.store(lc.Constant.int(lc.Type.int(1), 0), propagate)
412+
self.builder.store(ll.Constant(ll.IntType(1), 0), propagate)
412413
self.visit_statements(handler.body)
413414
if not self._bb_terminated():
414415
self.builder.branch(finally_block)
@@ -423,10 +424,10 @@ def _visit_stmt_Try(self, node):
423424
exc_block = function.append_basic_block("try_exc")
424425
finally_block = function.append_basic_block("try_finally")
425426

426-
propagate = self.builder.alloca(lc.Type.int(1),
427+
propagate = self.builder.alloca(ll.IntType(1),
427428
name="propagate")
428-
self.builder.store(lc.Constant.int(lc.Type.int(1), 0), propagate)
429-
propagate_eid = self.builder.alloca(lc.Type.int(),
429+
self.builder.store(ll.Constant(ll.IntType(1), 0), propagate)
430+
propagate_eid = self.builder.alloca(ll.IntType(32),
430431
name="propagate_eid")
431432
exception_occured = self.env.build_catch(self.builder)
432433
self.builder.cbranch(exception_occured, exc_block, noexc_block)

‎artiq/py2llvm/base_types.py

+32-32
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
from llvm import core as lc
1+
import llvmlite.ir as ll
22

33
from artiq.py2llvm.values import VGeneric
44

55

66
class VNone(VGeneric):
77
def get_llvm_type(self):
8-
return lc.Type.void()
8+
return ll.VoidType()
99

1010
def alloca(self, builder, name):
1111
pass
@@ -29,7 +29,7 @@ def __init__(self, nbits=32):
2929
self.nbits = nbits
3030

3131
def get_llvm_type(self):
32-
return lc.Type.int(self.nbits)
32+
return ll.IntType(self.nbits)
3333

3434
def __repr__(self):
3535
return "<VInt:{}>".format(self.nbits)
@@ -50,16 +50,16 @@ def set_value(self, builder, n):
5050
builder, n.o_intx(self.nbits, builder).auto_load(builder))
5151

5252
def set_const_value(self, builder, n):
53-
self.auto_store(builder, lc.Constant.int(self.get_llvm_type(), n))
53+
self.auto_store(builder, ll.Constant(self.get_llvm_type(), n))
5454

5555
def o_bool(self, builder, inv=False):
5656
r = VBool()
5757
if builder is not None:
5858
r.auto_store(
59-
builder, builder.icmp(
60-
lc.ICMP_EQ if inv else lc.ICMP_NE,
59+
builder, builder.icmp_signed(
60+
"==" if inv else "!=",
6161
self.auto_load(builder),
62-
lc.Constant.int(self.get_llvm_type(), 0)))
62+
ll.Constant(self.get_llvm_type(), 0)))
6363
return r
6464

6565
def o_float(self, builder):
@@ -82,7 +82,7 @@ def o_neg(self, builder):
8282
r.auto_store(
8383
builder, builder.mul(
8484
self.auto_load(builder),
85-
lc.Constant.int(self.get_llvm_type(), -1)))
85+
ll.Constant(self.get_llvm_type(), -1)))
8686
return r
8787

8888
def o_intx(self, target_bits, builder):
@@ -102,7 +102,7 @@ def o_intx(self, target_bits, builder):
102102
ef = builder.sext
103103
r.auto_store(
104104
builder, ef(self.auto_load(builder),
105-
r.get_llvm_type()))
105+
r.get_llvm_type()))
106106
return r
107107
o_roundx = o_intx
108108

@@ -157,20 +157,20 @@ def cmp_method(self, other, builder):
157157
right = other.o_intx(target_bits, builder)
158158
r.auto_store(
159159
builder,
160-
builder.icmp(
160+
builder.icmp_signed(
161161
icmp_val, left.auto_load(builder),
162162
right.auto_load(builder)))
163163
return r
164164
else:
165165
return NotImplemented
166166
return cmp_method
167167

168-
for _method_name, _icmp_val in (("o_eq", lc.ICMP_EQ),
169-
("o_ne", lc.ICMP_NE),
170-
("o_lt", lc.ICMP_SLT),
171-
("o_le", lc.ICMP_SLE),
172-
("o_gt", lc.ICMP_SGT),
173-
("o_ge", lc.ICMP_SGE)):
168+
for _method_name, _icmp_val in (("o_eq", "=="),
169+
("o_ne", "!="),
170+
("o_lt", "<"),
171+
("o_le", "<="),
172+
("o_gt", ">"),
173+
("o_ge", ">=")):
174174
setattr(VInt, _method_name, _make_vint_cmp_method(_icmp_val))
175175

176176

@@ -188,15 +188,15 @@ def set_const_value(self, builder, b):
188188

189189
class VFloat(VGeneric):
190190
def get_llvm_type(self):
191-
return lc.Type.double()
191+
return ll.DoubleType()
192192

193193
def set_value(self, builder, v):
194194
if not isinstance(v, VFloat):
195195
raise TypeError
196196
self.auto_store(builder, v.auto_load(builder))
197197

198198
def set_const_value(self, builder, n):
199-
self.auto_store(builder, lc.Constant.real(self.get_llvm_type(), n))
199+
self.auto_store(builder, ll.Constant(self.get_llvm_type(), n))
200200

201201
def o_float(self, builder):
202202
r = VFloat()
@@ -208,10 +208,10 @@ def o_bool(self, builder, inv=False):
208208
r = VBool()
209209
if builder is not None:
210210
r.auto_store(
211-
builder, builder.fcmp(
212-
lc.FCMP_UEQ if inv else lc.FCMP_UNE,
211+
builder, builder.fcmp_ordered(
212+
"==" if inv else "!=",
213213
self.auto_load(builder),
214-
lc.Constant.real(self.get_llvm_type(), 0.0)))
214+
ll.Constant(self.get_llvm_type(), 0.0)))
215215
return r
216216

217217
def o_not(self, builder):
@@ -223,7 +223,7 @@ def o_neg(self, builder):
223223
r.auto_store(
224224
builder, builder.fmul(
225225
self.auto_load(builder),
226-
lc.Constant.real(self.get_llvm_type(), -1.0)))
226+
ll.Constant(self.get_llvm_type(), -1.0)))
227227
return r
228228

229229
def o_intx(self, target_bits, builder):
@@ -244,10 +244,10 @@ def o_roundx(self, target_bits, builder):
244244
half.alloca(builder, "half")
245245
half.set_const_value(builder, 0.5)
246246

247-
condition = builder.icmp(
248-
lc.FCMP_OLT,
247+
condition = builder.fcmp_ordered(
248+
"<",
249249
self.auto_load(builder),
250-
lc.Constant.real(self.get_llvm_type(), 0.0))
250+
ll.Constant(self.get_llvm_type(), 0.0))
251251
builder.cbranch(condition, neg_block, merge_block)
252252

253253
builder.position_at_end(neg_block)
@@ -299,16 +299,16 @@ def cmp_method(self, other, builder):
299299
right = other.o_float(builder)
300300
r.auto_store(
301301
builder,
302-
builder.fcmp(
302+
builder.fcmp_ordered(
303303
fcmp_val, left.auto_load(builder),
304304
right.auto_load(builder)))
305305
return r
306306
return cmp_method
307307

308-
for _method_name, _fcmp_val in (("o_eq", lc.FCMP_OEQ),
309-
("o_ne", lc.FCMP_ONE),
310-
("o_lt", lc.FCMP_OLT),
311-
("o_le", lc.FCMP_OLE),
312-
("o_gt", lc.FCMP_OGT),
313-
("o_ge", lc.FCMP_OGE)):
308+
for _method_name, _fcmp_val in (("o_eq", "=="),
309+
("o_ne", "!="),
310+
("o_lt", "<"),
311+
("o_le", "<="),
312+
("o_gt", ">"),
313+
("o_ge", ">=")):
314314
setattr(VFloat, _method_name, _make_vfloat_cmp_method(_fcmp_val))

‎artiq/py2llvm/fractions.py

+39-43
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import inspect
22
import ast
33

4-
from llvm import core as lc
4+
import llvmlite.ir as ll
55

66
from artiq.py2llvm.values import VGeneric, operators
77
from artiq.py2llvm.base_types import VBool, VInt, VFloat
@@ -21,11 +21,15 @@ def init_module(module):
2121
func_def = ast.parse(inspect.getsource(_gcd)).body[0]
2222
function, _ = module.compile_function(func_def,
2323
{"a": VInt(64), "b": VInt(64)})
24-
function.linkage = lc.LINKAGE_INTERNAL
24+
function.linkage = "internal"
2525

2626

2727
def _reduce(builder, a, b):
28-
gcd_f = builder.basic_block.function.module.get_function_named("_gcd")
28+
module = builder.basic_block.function.module
29+
for f in module.functions:
30+
if f.name == "_gcd":
31+
gcd_f = f
32+
break
2933
gcd = builder.call(gcd_f, [a, b])
3034
a = builder.sdiv(a, gcd)
3135
b = builder.sdiv(b, gcd)
@@ -38,46 +42,42 @@ def _signnum(builder, a, b):
3842
swap_block = function.append_basic_block("sn_swap")
3943
merge_block = function.append_basic_block("sn_merge")
4044

41-
condition = builder.icmp(
42-
lc.ICMP_SLT, b, lc.Constant.int(lc.Type.int(64), 0))
45+
condition = builder.icmp_signed(
46+
"<", b, ll.Constant(ll.IntType(64), 0))
4347
builder.cbranch(condition, swap_block, merge_block)
4448

4549
builder.position_at_end(swap_block)
46-
minusone = lc.Constant.int(lc.Type.int(64), -1)
50+
minusone = ll.Constant(ll.IntType(64), -1)
4751
a_swp = builder.mul(minusone, a)
4852
b_swp = builder.mul(minusone, b)
4953
builder.branch(merge_block)
5054

5155
builder.position_at_end(merge_block)
52-
a_phi = builder.phi(lc.Type.int(64))
56+
a_phi = builder.phi(ll.IntType(64))
5357
a_phi.add_incoming(a, orig_block)
5458
a_phi.add_incoming(a_swp, swap_block)
55-
b_phi = builder.phi(lc.Type.int(64))
59+
b_phi = builder.phi(ll.IntType(64))
5660
b_phi.add_incoming(b, orig_block)
5761
b_phi.add_incoming(b_swp, swap_block)
5862

5963
return a_phi, b_phi
6064

6165

6266
def _make_ssa(builder, n, d):
63-
value = lc.Constant.undef(lc.Type.vector(lc.Type.int(64), 2))
64-
value = builder.insert_element(
65-
value, n, lc.Constant.int(lc.Type.int(), 0))
66-
value = builder.insert_element(
67-
value, d, lc.Constant.int(lc.Type.int(), 1))
67+
value = ll.Constant(ll.ArrayType(ll.IntType(64), 2), ll.Undefined)
68+
value = builder.insert_value(value, n, 0)
69+
value = builder.insert_value(value, d, 1)
6870
return value
6971

7072

7173
class VFraction(VGeneric):
7274
def get_llvm_type(self):
73-
return lc.Type.vector(lc.Type.int(64), 2)
75+
return ll.ArrayType(ll.IntType(64), 2)
7476

7577
def _nd(self, builder):
7678
ssa_value = self.auto_load(builder)
77-
a = builder.extract_element(
78-
ssa_value, lc.Constant.int(lc.Type.int(), 0))
79-
b = builder.extract_element(
80-
ssa_value, lc.Constant.int(lc.Type.int(), 1))
79+
a = builder.extract_value(ssa_value, 0)
80+
b = builder.extract_value(ssa_value, 1)
8181
return a, b
8282

8383
def set_value_nd(self, builder, a, b):
@@ -101,19 +101,16 @@ def o_getattr(self, attr, builder):
101101
raise AttributeError
102102
r = VInt(64)
103103
if builder is not None:
104-
elt = builder.extract_element(
105-
self.auto_load(builder),
106-
lc.Constant.int(lc.Type.int(), idx))
104+
elt = builder.extract_value(self.auto_load(builder), idx)
107105
r.auto_store(builder, elt)
108106
return r
109107

110108
def o_bool(self, builder):
111109
r = VBool()
112110
if builder is not None:
113-
zero = lc.Constant.int(lc.Type.int(64), 0)
114-
a = builder.extract_element(
115-
self.auto_load(builder), lc.Constant.int(lc.Type.int(), 0))
116-
r.auto_store(builder, builder.icmp(lc.ICMP_NE, a, zero))
111+
zero = ll.Constant(ll.IntType(64), 0)
112+
a = builder.extract_element(self.auto_load(builder), 0)
113+
r.auto_store(builder, builder.icmp_signed("!=", a, zero))
117114
return r
118115

119116
def o_intx(self, target_bits, builder):
@@ -131,15 +128,15 @@ def o_roundx(self, target_bits, builder):
131128
else:
132129
r = VInt(64)
133130
a, b = self._nd(builder)
134-
h_b = builder.ashr(b, lc.Constant.int(lc.Type.int(64), 1))
131+
h_b = builder.ashr(b, ll.Constant(ll.IntType(64), 1))
135132

136133
function = builder.basic_block.function
137134
add_block = function.append_basic_block("fr_add")
138135
sub_block = function.append_basic_block("fr_sub")
139136
merge_block = function.append_basic_block("fr_merge")
140137

141-
condition = builder.icmp(
142-
lc.ICMP_SLT, a, lc.Constant.int(lc.Type.int(64), 0))
138+
condition = builder.icmp_signed(
139+
"<", a, ll.Constant(ll.IntType(64), 0))
143140
builder.cbranch(condition, sub_block, add_block)
144141

145142
builder.position_at_end(add_block)
@@ -150,7 +147,7 @@ def o_roundx(self, target_bits, builder):
150147
builder.branch(merge_block)
151148

152149
builder.position_at_end(merge_block)
153-
a = builder.phi(lc.Type.int(64))
150+
a = builder.phi(ll.IntType(64))
154151
a.add_incoming(a_add, add_block)
155152
a.add_incoming(a_sub, sub_block)
156153
r.auto_store(builder, builder.sdiv(a, b))
@@ -165,19 +162,19 @@ def _o_eq_inv(self, other, builder, ne):
165162
other = other.o_int64(builder)
166163
a, b = self._nd(builder)
167164
ssa_r = builder.and_(
168-
builder.icmp(lc.ICMP_EQ, a,
169-
other.auto_load()),
170-
builder.icmp(lc.ICMP_EQ, b,
171-
lc.Constant.int(lc.Type.int(64), 1)))
165+
builder.icmp_signed("==", a,
166+
other.auto_load()),
167+
builder.icmp_signed("==", b,
168+
ll.Constant(ll.IntType(64), 1)))
172169
else:
173170
a, b = self._nd(builder)
174171
c, d = other._nd(builder)
175172
ssa_r = builder.and_(
176-
builder.icmp(lc.ICMP_EQ, a, c),
177-
builder.icmp(lc.ICMP_EQ, b, d))
173+
builder.icmp_signed("==", a, c),
174+
builder.icmp_signed("==", b, d))
178175
if ne:
179176
ssa_r = builder.xor(ssa_r,
180-
lc.Constant.int(lc.Type.int(1), 1))
177+
ll.Constant(ll.IntType(1), 1))
181178
r.auto_store(builder, ssa_r)
182179
return r
183180

@@ -194,24 +191,23 @@ def _o_cmp(self, other, icmp, builder):
194191
r = VBool()
195192
if builder is not None:
196193
diff = diff.auto_load(builder)
197-
a = builder.extract_element(
198-
diff, lc.Constant.int(lc.Type.int(), 0))
199-
zero = lc.Constant.int(lc.Type.int(64), 0)
194+
a = builder.extract_value(diff, 0)
195+
zero = ll.Constant(ll.IntType(64), 0)
200196
ssa_r = builder.icmp(icmp, a, zero)
201197
r.auto_store(builder, ssa_r)
202198
return r
203199

204200
def o_lt(self, other, builder):
205-
return self._o_cmp(other, lc.ICMP_SLT, builder)
201+
return self._o_cmp(other, "<", builder)
206202

207203
def o_le(self, other, builder):
208-
return self._o_cmp(other, lc.ICMP_SLE, builder)
204+
return self._o_cmp(other, "<=", builder)
209205

210206
def o_gt(self, other, builder):
211-
return self._o_cmp(other, lc.ICMP_SGT, builder)
207+
return self._o_cmp(other, ">", builder)
212208

213209
def o_ge(self, other, builder):
214-
return self._o_cmp(other, lc.ICMP_SGE, builder)
210+
return self._o_cmp(other, ">=", builder)
215211

216212
def _o_addsub(self, other, builder, sub, invert=False):
217213
if isinstance(other, VFloat):

‎artiq/py2llvm/iterators.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
from llvm import core as lc
2-
31
from artiq.py2llvm.values import operators
4-
from artiq.py2llvm.base_types import VBool, VInt
2+
from artiq.py2llvm.base_types import VInt
53

64
class IRange:
75
def __init__(self, builder, args):

‎artiq/py2llvm/module.py

+17-15
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,32 @@
1-
from llvm import core as lc
2-
from llvm import passes as lp
3-
from llvm import ee as le
1+
import llvmlite.ir as ll
2+
import llvmlite.binding as llvm
43

54
from artiq.py2llvm import infer_types, ast_body, base_types, fractions, tools
65

76

87
class Module:
98
def __init__(self, env=None):
10-
self.llvm_module = lc.Module.new("main")
9+
self.llvm_module = ll.Module("main")
1110
self.env = env
1211

1312
if self.env is not None:
1413
self.env.init_module(self)
1514
fractions.init_module(self)
1615

1716
def finalize(self):
18-
pass_manager = lp.PassManager.new()
19-
pass_manager.add(lp.PASS_MEM2REG)
20-
pass_manager.add(lp.PASS_INSTCOMBINE)
21-
pass_manager.add(lp.PASS_REASSOCIATE)
22-
pass_manager.add(lp.PASS_GVN)
23-
pass_manager.add(lp.PASS_SIMPLIFYCFG)
24-
pass_manager.run(self.llvm_module)
17+
self.llvm_module = llvm.parse_assembly(str(self.llvm_module)) # FIXME
18+
pmb = llvm.create_pass_manager_builder()
19+
pmb.opt_level = 2
20+
pm = llvm.create_module_pass_manager()
21+
pmb.populate(pm)
22+
pm.run(self.llvm_module)
2523

2624
def get_ee(self):
2725
self.finalize()
28-
return le.ExecutionEngine.new(self.llvm_module)
26+
tm = llvm.Target.from_default_triple().create_target_machine()
27+
ee = llvm.create_mcjit_compiler(self.llvm_module, tm)
28+
ee.finalize_object()
29+
return ee
2930

3031
def emit_object(self):
3132
self.finalize()
@@ -35,11 +36,12 @@ def compile_function(self, func_def, param_types):
3536
ns = infer_types.infer_function_types(self.env, func_def, param_types)
3637
retval = ns["return"]
3738

38-
function_type = lc.Type.function(retval.get_llvm_type(),
39+
function_type = ll.FunctionType(retval.get_llvm_type(),
3940
[ns[arg.arg].get_llvm_type() for arg in func_def.args.args])
40-
function = self.llvm_module.add_function(function_type, func_def.name)
41+
function = ll.Function(self.llvm_module, function_type, func_def.name)
4142
bb = function.append_basic_block("entry")
42-
builder = lc.Builder.new(bb)
43+
builder = ll.IRBuilder()
44+
builder.position_at_end(bb)
4345

4446
for arg_ast, arg_llvm in zip(func_def.args.args, function.args):
4547
arg_llvm.name = arg_ast.arg

‎artiq/py2llvm/tools.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
1+
import llvmlite.ir as ll
2+
13
def is_terminated(basic_block):
2-
return basic_block.instructions and basic_block.instructions[-1].is_terminator
4+
return (basic_block.instructions
5+
and isinstance(basic_block.instructions[-1], ll.Terminator))

‎artiq/py2llvm/values.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from types import SimpleNamespace
22
from copy import copy
33

4-
from llvm import core as lc
4+
import llvmlite.ir as ll
55

66

77
class VGeneric:
@@ -25,15 +25,15 @@ def merge(self, other):
2525
.format(repr(self), repr(other)))
2626

2727
def auto_load(self, builder):
28-
if isinstance(self.llvm_value.type, lc.PointerType):
28+
if isinstance(self.llvm_value.type, ll.PointerType):
2929
return builder.load(self.llvm_value)
3030
else:
3131
return self.llvm_value
3232

3333
def auto_store(self, builder, llvm_value):
3434
if self.llvm_value is None:
3535
self.llvm_value = llvm_value
36-
elif isinstance(self.llvm_value.type, lc.PointerType):
36+
elif isinstance(self.llvm_value.type, ll.PointerType):
3737
builder.store(llvm_value, self.llvm_value)
3838
else:
3939
raise RuntimeError(
@@ -60,14 +60,14 @@ def o_round64(self, builder):
6060
def _make_binary_operator(op_name):
6161
def op(l, r, builder):
6262
try:
63-
opf = getattr(l, "o_"+op_name)
63+
opf = getattr(l, "o_" + op_name)
6464
except AttributeError:
6565
result = NotImplemented
6666
else:
6767
result = opf(r, builder)
6868
if result is NotImplemented:
6969
try:
70-
ropf = getattr(r, "or_"+op_name)
70+
ropf = getattr(r, "or_" + op_name)
7171
except AttributeError:
7272
result = NotImplemented
7373
else:

‎doc/manual/installing.rst

+12-16
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,9 @@ These steps are required to generate bitstream (``.bit``) files, build the MiSoC
9898
$ cd ~/artiq-dev/misoc
9999
$ ./make.py -X ~/artiq/soc -t artiq all
100100

101-
* Then, build and flash the ARTIQ runtime: ::
101+
* Then, build and flash the ARTIQ runtime:
102+
103+
::
102104

103105
$ cd ~/artiq-dev
104106
$ git clone https://github.com/m-labs/artiq
@@ -120,36 +122,30 @@ The communication parameters are 115200 8-N-1.
120122
Installing the host-side software
121123
---------------------------------
122124

123-
* Install LLVM and its Python bindings:
124-
125-
The main dependency of ARTIQ is LLVM and its Python bindings (http://llvmpy.org). Currently, this installation is tedious because of the OpenRISC support not being merged upstream LLVM and because of incompatibilities between the versions of LLVM that support OpenRISC and the versions of LLVM that support the Python bindings. ::
125+
* Install LLVM and the llvmlite Python bindings: ::
126126

127127
$ cd ~/artiq-dev
128128
$ git clone https://github.com/openrisc/llvm-or1k
129-
$ cd ~/artiq-dev/llvm-or1k
130-
$ git checkout b3a48efb2c05ed6cedc5395ae726c6a6573ef3ba
131-
$ cat ~/artiq-dev/artiq/patches/llvm/* | patch -p1
132-
133129
$ cd ~/artiq-dev/llvm-or1k/tools
134130
$ git clone https://github.com/openrisc/clang-or1k clang
135131
$ cd ~/artiq-dev/llvm-or1k/tools/clang
136-
$ git checkout 02d831c7e7dc1517abed9cc96abdfb937af954eb
137-
$ cat ~/artiq-dev/artiq/patches/clang/* | patch -p1
138132

139133
$ cd ~/artiq-dev/llvm-or1k
140134
$ mkdir build
141135
$ cd ~/artiq-dev/llvm-or1k/build
142136
$ ../configure --prefix=/usr/local/llvm-or1k
143-
$ make ENABLE_OPTIMIZED=1 REQUIRES_RTTI=1 -j4
144-
$ sudo -E make install ENABLE_OPTIMIZED=1 REQUIRES_RTTI=1
137+
$ make ENABLE_OPTIMIZED=1 -j4
138+
$ sudo -E make install ENABLE_OPTIMIZED=1
145139

146140
$ cd ~/artiq-dev
147-
$ git clone https://github.com/llvmpy/llvmpy
148-
$ cd ~/artiq-dev/llvmpy
149-
$ git checkout 7af2f7140391d4f708adf2721e84f23c1b89e97a
150-
$ cat /path_to/artiq/patches/llvmpy/* | patch -p1
141+
$ git clone https://github.com/numba/llvmlite
142+
$ cd ~/artiq-dev/llvmlite
143+
$ cat /path_to/artiq/patches/llvmlite/* | patch -p1
151144
$ LLVM_CONFIG_PATH=/usr/local/llvm-or1k/bin/llvm-config sudo -E python setup.py install
152145

146+
.. note::
147+
llvmlite is in development and its API is not stable yet. Commit ID ``11a8303d02e3d6dd2d1e0e9065701795cd8a979f`` is known to work.
148+
153149
.. note::
154150
Compilation of LLVM can take more than 30 min on some machines.
155151

‎patches/clang/0001-exclude-some-broken-aarch64-builtins.patch

-32
This file was deleted.

‎patches/llvm/0001-or1k-initAsmInfo.patch

-24
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
diff --git a/ffi/initfini.cpp b/ffi/initfini.cpp
2+
index 42c8965..067be62 100644
3+
--- a/ffi/initfini.cpp
4+
+++ b/ffi/initfini.cpp
5+
@@ -37,9 +37,10 @@ LLVMPY_Shutdown(){
6+
// NOTE: it is important that we don't export functions which we don't use,
7+
// especially those which may pull in large amounts of additional code or data.
8+
9+
-// INIT(AllTargetInfos)
10+
-// INIT(AllTargets)
11+
-// INIT(AllTargetMCs)
12+
+INIT(AllTargetInfos)
13+
+INIT(AllTargets)
14+
+INIT(AllTargetMCs)
15+
+INIT(AllAsmPrinters)
16+
INIT(NativeTarget)
17+
INIT(NativeAsmParser)
18+
INIT(NativeAsmPrinter)
19+
diff --git a/llvmlite/binding/initfini.py b/llvmlite/binding/initfini.py
20+
index bfaa5b2..7d0df11 100644
21+
--- a/llvmlite/binding/initfini.py
22+
+++ b/llvmlite/binding/initfini.py
23+
@@ -8,6 +8,15 @@ def initialize():
24+
ffi.lib.LLVMPY_InitializeCore()
25+
26+
27+
+def initialize_all_targets():
28+
+ ffi.lib.LLVMPY_InitializeAllTargetInfos()
29+
+ ffi.lib.LLVMPY_InitializeAllTargets()
30+
+ ffi.lib.LLVMPY_InitializeAllTargetMCs()
31+
+
32+
+def initialize_all_asmprinters():
33+
+ ffi.lib.LLVMPY_InitializeAllAsmPrinters()
34+
+
35+
+
36+
def initialize_native_target():
37+
"""
38+
Initialize the native (host) target. Necessary before doing any

‎patches/llvmpy/0001-use-3.3-opcodes.patch

-25
This file was deleted.

‎patches/llvmpy/0002-add-returns-twice-attribute.patch

-12
This file was deleted.

‎test/py2llvm.py

+37-23
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,21 @@
22
import ast
33
import inspect
44
from fractions import Fraction
5+
from ctypes import CFUNCTYPE, c_int, c_int32, c_int64, c_double
56

6-
from llvm import ee as le
7+
import llvmlite.binding as llvm
78

89
from artiq.language.core import int64, array
910
from artiq.py2llvm.infer_types import infer_function_types
1011
from artiq.py2llvm import base_types, arrays
1112
from artiq.py2llvm.module import Module
1213

1314

15+
llvm.initialize()
16+
llvm.initialize_native_target()
17+
llvm.initialize_native_asmprinter()
18+
19+
1420
def _base_types(choice):
1521
a = 2 # promoted later to int64
1622
b = a + 1 # initially int32, becomes int64 after a is promoted
@@ -81,34 +87,42 @@ def test_array_types(self):
8187
self.assertEqual(self.ns["i"].nbits, 32)
8288

8389

90+
def _value_to_ctype(v):
91+
if isinstance(v, base_types.VBool):
92+
return c_int
93+
elif isinstance(v, base_types.VInt):
94+
if v.nbits == 32:
95+
return c_int32
96+
elif v.nbits == 64:
97+
return c_int64
98+
else:
99+
raise NotImplementedError(str(v))
100+
elif isinstance(v, base_types.VFloat):
101+
return c_double
102+
else:
103+
raise NotImplementedError(str(v))
104+
105+
84106
class CompiledFunction:
85107
def __init__(self, function, param_types):
86108
module = Module()
109+
87110
func_def = ast.parse(inspect.getsource(function)).body[0]
88-
self.function, self.retval = module.compile_function(
89-
func_def, param_types)
90-
self.argval = [param_types[arg.arg] for arg in func_def.args.args]
91-
self.ee = module.get_ee()
111+
function, retval = module.compile_function(func_def, param_types)
112+
argvals = [param_types[arg.arg] for arg in func_def.args.args]
113+
114+
ee = module.get_ee()
115+
cfptr = ee.get_pointer_to_global(
116+
module.llvm_module.get_function(function.name))
117+
retval_ctype = _value_to_ctype(retval)
118+
argval_ctypes = [_value_to_ctype(argval) for argval in argvals]
119+
self.cfunc = CFUNCTYPE(retval_ctype, *argval_ctypes)(cfptr)
120+
121+
# HACK: prevent garbage collection of self.cfunc internals
122+
self.ee = ee
92123

93124
def __call__(self, *args):
94-
args_llvm = []
95-
for av, a in zip(self.argval, args):
96-
if isinstance(av, base_types.VInt):
97-
al = le.GenericValue.int(av.get_llvm_type(), a)
98-
elif isinstance(av, base_types.VFloat):
99-
al = le.GenericValue.real(av.get_llvm_type(), a)
100-
else:
101-
raise NotImplementedError
102-
args_llvm.append(al)
103-
result = self.ee.run_function(self.function, args_llvm)
104-
if isinstance(self.retval, base_types.VBool):
105-
return bool(result.as_int())
106-
elif isinstance(self.retval, base_types.VInt):
107-
return result.as_int_signed()
108-
elif isinstance(self.retval, base_types.VFloat):
109-
return result.as_real(self.retval.get_llvm_type())
110-
else:
111-
raise NotImplementedError
125+
return self.cfunc(*args)
112126

113127

114128
def arith(op, a, b):

0 commit comments

Comments
 (0)
Please sign in to comment.