switch to llvmlite

This commit is contained in:
Sebastien Bourdeauducq 2014-12-05 17:05:43 +08:00
parent b93b969e2a
commit 159f632a65
16 changed files with 258 additions and 303 deletions

View File

@ -1,14 +1,15 @@
import os
from fractions import Fraction
from llvm import core as lc
from llvm import target as lt
import llvmlite.ir as ll
import llvmlite.binding as llvm
from artiq.py2llvm import base_types
from artiq.language import units
lt.initialize_all()
llvm.initialize()
llvm.initialize_all_targets()
llvm.initialize_all_asmprinters()
_syscalls = {
"rpc": "i+:i",
@ -23,10 +24,10 @@ _syscalls = {
}
_chr_to_type = {
"n": lambda: lc.Type.void(),
"b": lambda: lc.Type.int(1),
"i": lambda: lc.Type.int(32),
"I": lambda: lc.Type.int(64)
"n": lambda: ll.VoidType(),
"b": lambda: ll.IntType(1),
"i": lambda: ll.IntType(32),
"I": lambda: ll.IntType(64)
}
_chr_to_value = {
@ -45,45 +46,50 @@ def _str_to_functype(s):
type_args = []
for n, c in enumerate(s[:-2]):
if c == "+":
type_args.append(lc.Type.int())
type_args.append(ll.IntType(32))
var_arg_fixcount = n
elif c != "n":
type_args.append(_chr_to_type[c]())
return (var_arg_fixcount,
lc.Type.function(type_ret, type_args,
ll.FunctionType(type_ret, type_args,
var_arg=var_arg_fixcount is not None))
class LinkInterface:
def init_module(self, module):
self.llvm_module = module.llvm_module
self.module = module
llvm_module = self.module.llvm_module
# syscalls
self.syscalls = dict()
self.var_arg_fixcount = dict()
for func_name, func_type_str in _syscalls.items():
var_arg_fixcount, func_type = _str_to_functype(func_type_str)
if var_arg_fixcount is not None:
self.var_arg_fixcount[func_name] = var_arg_fixcount
self.llvm_module.add_function(func_type, "__syscall_"+func_name)
self.syscalls[func_name] = ll.Function(
llvm_module, func_type, "__syscall_" + func_name)
# exception handling
func_type = lc.Type.function(lc.Type.int(), [lc.Type.pointer(lc.Type.int(8))])
function = self.llvm_module.add_function(func_type, "__eh_setjmp")
function.add_attribute(lc.ATTR_NO_UNWIND)
function.add_attribute(lc.ATTR_RETURNS_TWICE)
func_type = ll.FunctionType(ll.IntType(32),
[ll.PointerType(ll.IntType(8))])
self.eh_setjmp = ll.Function(llvm_module, func_type,
"__eh_setjmp")
self.eh_setjmp.attributes.add("nounwind")
self.eh_setjmp.attributes.add("returns_twice")
func_type = lc.Type.function(lc.Type.pointer(lc.Type.int(8)), [])
self.llvm_module.add_function(func_type, "__eh_push")
func_type = ll.FunctionType(ll.PointerType(ll.IntType(8)), [])
self.eh_push = ll.Function(llvm_module, func_type, "__eh_push")
func_type = lc.Type.function(lc.Type.void(), [lc.Type.int()])
self.llvm_module.add_function(func_type, "__eh_pop")
func_type = ll.FunctionType(ll.VoidType(), [ll.IntType(32)])
self.eh_pop = ll.Function(llvm_module, func_type, "__eh_pop")
func_type = lc.Type.function(lc.Type.int(), [])
self.llvm_module.add_function(func_type, "__eh_getid")
func_type = ll.FunctionType(ll.IntType(32), [])
self.eh_getid = ll.Function(llvm_module, func_type, "__eh_getid")
func_type = lc.Type.function(lc.Type.void(), [lc.Type.int()])
function = self.llvm_module.add_function(func_type, "__eh_raise")
function.add_attribute(lc.ATTR_NO_RETURN)
func_type = ll.FunctionType(ll.VoidType(), [ll.IntType(32)])
self.eh_raise = ll.Function(llvm_module, func_type, "__eh_raise")
self.eh_raise.attributes.add("noreturn")
def build_syscall(self, syscall_name, args, builder):
r = _chr_to_value[_syscalls[syscall_name][-1]]()
@ -92,33 +98,27 @@ class LinkInterface:
if syscall_name in self.var_arg_fixcount:
fixcount = self.var_arg_fixcount[syscall_name]
args = args[:fixcount] \
+ [lc.Constant.int(lc.Type.int(), len(args) - fixcount)] \
+ [ll.Constant(ll.IntType(32), len(args) - fixcount)] \
+ args[fixcount:]
llvm_function = self.llvm_module.get_function_named(
"__syscall_" + syscall_name)
r.auto_store(builder, builder.call(llvm_function, args))
r.auto_store(builder, builder.call(self.syscalls[syscall_name],
args))
return r
def build_catch(self, builder):
eh_setjmp = self.llvm_module.get_function_named("__eh_setjmp")
eh_push = self.llvm_module.get_function_named("__eh_push")
jmpbuf = builder.call(eh_push, [])
exception_occured = builder.call(eh_setjmp, [jmpbuf])
return builder.icmp(lc.ICMP_NE,
jmpbuf = builder.call(self.eh_push, [])
exception_occured = builder.call(self.eh_setjmp, [jmpbuf])
return builder.icmp_signed("!=",
exception_occured,
lc.Constant.int(lc.Type.int(), 0))
ll.Constant(ll.IntType(32), 0))
def build_pop(self, builder, levels):
eh_pop = self.llvm_module.get_function_named("__eh_pop")
builder.call(eh_pop, [lc.Constant.int(lc.Type.int(), levels)])
builder.call(self.eh_pop, [ll.Constant(ll.IntType(32), levels)])
def build_getid(self, builder):
eh_getid = self.llvm_module.get_function_named("__eh_getid")
return builder.call(eh_getid, [])
return builder.call(self.eh_getid, [])
def build_raise(self, builder, eid):
eh_raise = self.llvm_module.get_function_named("__eh_raise")
builder.call(eh_raise, [eid])
builder.call(self.eh_raise, [eid])
def _debug_dump_obj(obj):
@ -148,8 +148,8 @@ class Environment(LinkInterface):
self.warmup_time = 1*units.ms
def emit_object(self):
tm = lt.TargetMachine.new(triple=self.cpu_type, cpu="generic")
obj = tm.emit_object(self.llvm_module)
tm = llvm.Target.from_triple(self.cpu_type).create_target_machine()
obj = tm.emit_object(self.module.llvm_module)
_debug_dump_obj(obj)
return obj

View File

@ -1,4 +1,4 @@
from llvm import core as lc
import llvmlite.ir as ll
from artiq.py2llvm.values import VGeneric
from artiq.py2llvm.base_types import VInt
@ -13,7 +13,7 @@ class VArray(VGeneric):
raise TypeError("Arrays must have at least one element")
def get_llvm_type(self):
return lc.Type.array(self.el_init.get_llvm_type(), self.count)
return ll.ArrayType(self.el_init.get_llvm_type(), self.count)
def __repr__(self):
return "<VArray:{} x{}>".format(repr(self.el_init), self.count)
@ -42,7 +42,7 @@ class VArray(VGeneric):
i = VInt()
i.alloca(builder, "ai_i")
i.auto_store(builder, lc.Constant.int(lc.Type.int(), 0))
i.auto_store(builder, ll.Constant(ll.IntType(32), 0))
function = builder.basic_block.function
copy_block = function.append_basic_block("ai_copy")
@ -52,10 +52,10 @@ class VArray(VGeneric):
builder.position_at_end(copy_block)
self.o_subscript(i, builder).set_value(builder, v.el_init)
i.auto_store(builder, builder.add(
i.auto_load(builder), lc.Constant.int(lc.Type.int(), 1)))
cont = builder.icmp(
lc.ICMP_SLT, i.auto_load(builder),
lc.Constant.int(lc.Type.int(), self.count))
i.auto_load(builder), ll.Constant(ll.IntType(32), 1)))
cont = builder.icmp_signed(
"<", i.auto_load(builder),
ll.Constant(ll.IntType(32), self.count))
builder.cbranch(cont, copy_block, end_block)
builder.position_at_end(end_block)
@ -65,6 +65,6 @@ class VArray(VGeneric):
if builder is not None:
index = index.o_int(builder).auto_load(builder)
ssa_r = builder.gep(self.llvm_value, [
lc.Constant.int(lc.Type.int(), 0), index])
ll.Constant(ll.IntType(32), 0), index])
r.auto_store(builder, ssa_r)
return r

View File

@ -1,5 +1,6 @@
import ast
from llvm import core as lc
import llvmlite.ir as ll
from artiq.py2llvm import values, base_types, fractions, arrays, iterators
from artiq.py2llvm.tools import is_terminated
@ -368,13 +369,13 @@ class Visitor:
if self._active_exception_stack:
finally_block, propagate, propagate_eid = (
self._active_exception_stack[-1])
self.builder.store(lc.Constant.int(lc.Type.int(1), 1), propagate)
self.builder.store(ll.Constant(ll.IntType(1), 1), propagate)
if node.exc is not None:
eid = lc.Constant.int(lc.Type.int(), node.exc.args[0].n)
eid = ll.Constant(ll.IntType(32), node.exc.args[0].n)
self.builder.store(eid, propagate_eid)
self.builder.branch(finally_block)
else:
eid = lc.Constant.int(lc.Type.int(), node.exc.args[0].n)
eid = ll.Constant(ll.IntType(32), node.exc.args[0].n)
self.env.build_raise(self.builder, eid)
def _handle_exception(self, function, finally_block,
@ -382,7 +383,7 @@ class Visitor:
eid = self.env.build_getid(self.builder)
self._active_exception_stack.append(
(finally_block, propagate, propagate_eid))
self.builder.store(lc.Constant.int(lc.Type.int(1), 1), propagate)
self.builder.store(ll.Constant(ll.IntType(1), 1), propagate)
self.builder.store(eid, propagate_eid)
for handler in handlers:
@ -392,23 +393,23 @@ class Visitor:
self.builder.branch(handled_exc_block)
else:
if isinstance(handler.type, ast.Tuple):
match = self.builder.icmp(
lc.ICMP_EQ, eid,
lc.Constant.int(lc.Type.int(),
match = self.builder.icmp_signed(
"==", eid,
ll.Constant(ll.IntType(32),
handler.type.elts[0].args[0].n))
for elt in handler.type.elts[1:]:
match = self.builder.or_(
match,
self.builder.icmp(
lc.ICMP_EQ, eid,
lc.Constant.int(lc.Type.int(), elt.args[0].n)))
self.builder.icmp_signed(
"==", eid,
ll.Constant(ll.IntType(32), elt.args[0].n)))
else:
match = self.builder.icmp(
lc.ICMP_EQ, eid,
lc.Constant.int(lc.Type.int(), handler.type.args[0].n))
match = self.builder.icmp_signed(
"==", eid,
ll.Constant(ll.IntType(32), handler.type.args[0].n))
self.builder.cbranch(match, handled_exc_block, cont_exc_block)
self.builder.position_at_end(handled_exc_block)
self.builder.store(lc.Constant.int(lc.Type.int(1), 0), propagate)
self.builder.store(ll.Constant(ll.IntType(1), 0), propagate)
self.visit_statements(handler.body)
if not self._bb_terminated():
self.builder.branch(finally_block)
@ -423,10 +424,10 @@ class Visitor:
exc_block = function.append_basic_block("try_exc")
finally_block = function.append_basic_block("try_finally")
propagate = self.builder.alloca(lc.Type.int(1),
propagate = self.builder.alloca(ll.IntType(1),
name="propagate")
self.builder.store(lc.Constant.int(lc.Type.int(1), 0), propagate)
propagate_eid = self.builder.alloca(lc.Type.int(),
self.builder.store(ll.Constant(ll.IntType(1), 0), propagate)
propagate_eid = self.builder.alloca(ll.IntType(32),
name="propagate_eid")
exception_occured = self.env.build_catch(self.builder)
self.builder.cbranch(exception_occured, exc_block, noexc_block)

View File

@ -1,11 +1,11 @@
from llvm import core as lc
import llvmlite.ir as ll
from artiq.py2llvm.values import VGeneric
class VNone(VGeneric):
def get_llvm_type(self):
return lc.Type.void()
return ll.VoidType()
def alloca(self, builder, name):
pass
@ -29,7 +29,7 @@ class VInt(VGeneric):
self.nbits = nbits
def get_llvm_type(self):
return lc.Type.int(self.nbits)
return ll.IntType(self.nbits)
def __repr__(self):
return "<VInt:{}>".format(self.nbits)
@ -50,16 +50,16 @@ class VInt(VGeneric):
builder, n.o_intx(self.nbits, builder).auto_load(builder))
def set_const_value(self, builder, n):
self.auto_store(builder, lc.Constant.int(self.get_llvm_type(), n))
self.auto_store(builder, ll.Constant(self.get_llvm_type(), n))
def o_bool(self, builder, inv=False):
r = VBool()
if builder is not None:
r.auto_store(
builder, builder.icmp(
lc.ICMP_EQ if inv else lc.ICMP_NE,
builder, builder.icmp_signed(
"==" if inv else "!=",
self.auto_load(builder),
lc.Constant.int(self.get_llvm_type(), 0)))
ll.Constant(self.get_llvm_type(), 0)))
return r
def o_float(self, builder):
@ -82,7 +82,7 @@ class VInt(VGeneric):
r.auto_store(
builder, builder.mul(
self.auto_load(builder),
lc.Constant.int(self.get_llvm_type(), -1)))
ll.Constant(self.get_llvm_type(), -1)))
return r
def o_intx(self, target_bits, builder):
@ -157,7 +157,7 @@ def _make_vint_cmp_method(icmp_val):
right = other.o_intx(target_bits, builder)
r.auto_store(
builder,
builder.icmp(
builder.icmp_signed(
icmp_val, left.auto_load(builder),
right.auto_load(builder)))
return r
@ -165,12 +165,12 @@ def _make_vint_cmp_method(icmp_val):
return NotImplemented
return cmp_method
for _method_name, _icmp_val in (("o_eq", lc.ICMP_EQ),
("o_ne", lc.ICMP_NE),
("o_lt", lc.ICMP_SLT),
("o_le", lc.ICMP_SLE),
("o_gt", lc.ICMP_SGT),
("o_ge", lc.ICMP_SGE)):
for _method_name, _icmp_val in (("o_eq", "=="),
("o_ne", "!="),
("o_lt", "<"),
("o_le", "<="),
("o_gt", ">"),
("o_ge", ">=")):
setattr(VInt, _method_name, _make_vint_cmp_method(_icmp_val))
@ -188,7 +188,7 @@ class VBool(VInt):
class VFloat(VGeneric):
def get_llvm_type(self):
return lc.Type.double()
return ll.DoubleType()
def set_value(self, builder, v):
if not isinstance(v, VFloat):
@ -196,7 +196,7 @@ class VFloat(VGeneric):
self.auto_store(builder, v.auto_load(builder))
def set_const_value(self, builder, n):
self.auto_store(builder, lc.Constant.real(self.get_llvm_type(), n))
self.auto_store(builder, ll.Constant(self.get_llvm_type(), n))
def o_float(self, builder):
r = VFloat()
@ -208,10 +208,10 @@ class VFloat(VGeneric):
r = VBool()
if builder is not None:
r.auto_store(
builder, builder.fcmp(
lc.FCMP_UEQ if inv else lc.FCMP_UNE,
builder, builder.fcmp_ordered(
"==" if inv else "!=",
self.auto_load(builder),
lc.Constant.real(self.get_llvm_type(), 0.0)))
ll.Constant(self.get_llvm_type(), 0.0)))
return r
def o_not(self, builder):
@ -223,7 +223,7 @@ class VFloat(VGeneric):
r.auto_store(
builder, builder.fmul(
self.auto_load(builder),
lc.Constant.real(self.get_llvm_type(), -1.0)))
ll.Constant(self.get_llvm_type(), -1.0)))
return r
def o_intx(self, target_bits, builder):
@ -244,10 +244,10 @@ class VFloat(VGeneric):
half.alloca(builder, "half")
half.set_const_value(builder, 0.5)
condition = builder.icmp(
lc.FCMP_OLT,
condition = builder.fcmp_ordered(
"<",
self.auto_load(builder),
lc.Constant.real(self.get_llvm_type(), 0.0))
ll.Constant(self.get_llvm_type(), 0.0))
builder.cbranch(condition, neg_block, merge_block)
builder.position_at_end(neg_block)
@ -299,16 +299,16 @@ def _make_vfloat_cmp_method(fcmp_val):
right = other.o_float(builder)
r.auto_store(
builder,
builder.fcmp(
builder.fcmp_ordered(
fcmp_val, left.auto_load(builder),
right.auto_load(builder)))
return r
return cmp_method
for _method_name, _fcmp_val in (("o_eq", lc.FCMP_OEQ),
("o_ne", lc.FCMP_ONE),
("o_lt", lc.FCMP_OLT),
("o_le", lc.FCMP_OLE),
("o_gt", lc.FCMP_OGT),
("o_ge", lc.FCMP_OGE)):
for _method_name, _fcmp_val in (("o_eq", "=="),
("o_ne", "!="),
("o_lt", "<"),
("o_le", "<="),
("o_gt", ">"),
("o_ge", ">=")):
setattr(VFloat, _method_name, _make_vfloat_cmp_method(_fcmp_val))

View File

@ -1,7 +1,7 @@
import inspect
import ast
from llvm import core as lc
import llvmlite.ir as ll
from artiq.py2llvm.values import VGeneric, operators
from artiq.py2llvm.base_types import VBool, VInt, VFloat
@ -21,11 +21,15 @@ def init_module(module):
func_def = ast.parse(inspect.getsource(_gcd)).body[0]
function, _ = module.compile_function(func_def,
{"a": VInt(64), "b": VInt(64)})
function.linkage = lc.LINKAGE_INTERNAL
function.linkage = "internal"
def _reduce(builder, a, b):
gcd_f = builder.basic_block.function.module.get_function_named("_gcd")
module = builder.basic_block.function.module
for f in module.functions:
if f.name == "_gcd":
gcd_f = f
break
gcd = builder.call(gcd_f, [a, b])
a = builder.sdiv(a, gcd)
b = builder.sdiv(b, gcd)
@ -38,21 +42,21 @@ def _signnum(builder, a, b):
swap_block = function.append_basic_block("sn_swap")
merge_block = function.append_basic_block("sn_merge")
condition = builder.icmp(
lc.ICMP_SLT, b, lc.Constant.int(lc.Type.int(64), 0))
condition = builder.icmp_signed(
"<", b, ll.Constant(ll.IntType(64), 0))
builder.cbranch(condition, swap_block, merge_block)
builder.position_at_end(swap_block)
minusone = lc.Constant.int(lc.Type.int(64), -1)
minusone = ll.Constant(ll.IntType(64), -1)
a_swp = builder.mul(minusone, a)
b_swp = builder.mul(minusone, b)
builder.branch(merge_block)
builder.position_at_end(merge_block)
a_phi = builder.phi(lc.Type.int(64))
a_phi = builder.phi(ll.IntType(64))
a_phi.add_incoming(a, orig_block)
a_phi.add_incoming(a_swp, swap_block)
b_phi = builder.phi(lc.Type.int(64))
b_phi = builder.phi(ll.IntType(64))
b_phi.add_incoming(b, orig_block)
b_phi.add_incoming(b_swp, swap_block)
@ -60,24 +64,20 @@ def _signnum(builder, a, b):
def _make_ssa(builder, n, d):
value = lc.Constant.undef(lc.Type.vector(lc.Type.int(64), 2))
value = builder.insert_element(
value, n, lc.Constant.int(lc.Type.int(), 0))
value = builder.insert_element(
value, d, lc.Constant.int(lc.Type.int(), 1))
value = ll.Constant(ll.ArrayType(ll.IntType(64), 2), ll.Undefined)
value = builder.insert_value(value, n, 0)
value = builder.insert_value(value, d, 1)
return value
class VFraction(VGeneric):
def get_llvm_type(self):
return lc.Type.vector(lc.Type.int(64), 2)
return ll.ArrayType(ll.IntType(64), 2)
def _nd(self, builder):
ssa_value = self.auto_load(builder)
a = builder.extract_element(
ssa_value, lc.Constant.int(lc.Type.int(), 0))
b = builder.extract_element(
ssa_value, lc.Constant.int(lc.Type.int(), 1))
a = builder.extract_value(ssa_value, 0)
b = builder.extract_value(ssa_value, 1)
return a, b
def set_value_nd(self, builder, a, b):
@ -101,19 +101,16 @@ class VFraction(VGeneric):
raise AttributeError
r = VInt(64)
if builder is not None:
elt = builder.extract_element(
self.auto_load(builder),
lc.Constant.int(lc.Type.int(), idx))
elt = builder.extract_value(self.auto_load(builder), idx)
r.auto_store(builder, elt)
return r
def o_bool(self, builder):
r = VBool()
if builder is not None:
zero = lc.Constant.int(lc.Type.int(64), 0)
a = builder.extract_element(
self.auto_load(builder), lc.Constant.int(lc.Type.int(), 0))
r.auto_store(builder, builder.icmp(lc.ICMP_NE, a, zero))
zero = ll.Constant(ll.IntType(64), 0)
a = builder.extract_element(self.auto_load(builder), 0)
r.auto_store(builder, builder.icmp_signed("!=", a, zero))
return r
def o_intx(self, target_bits, builder):
@ -131,15 +128,15 @@ class VFraction(VGeneric):
else:
r = VInt(64)
a, b = self._nd(builder)
h_b = builder.ashr(b, lc.Constant.int(lc.Type.int(64), 1))
h_b = builder.ashr(b, ll.Constant(ll.IntType(64), 1))
function = builder.basic_block.function
add_block = function.append_basic_block("fr_add")
sub_block = function.append_basic_block("fr_sub")
merge_block = function.append_basic_block("fr_merge")
condition = builder.icmp(
lc.ICMP_SLT, a, lc.Constant.int(lc.Type.int(64), 0))
condition = builder.icmp_signed(
"<", a, ll.Constant(ll.IntType(64), 0))
builder.cbranch(condition, sub_block, add_block)
builder.position_at_end(add_block)
@ -150,7 +147,7 @@ class VFraction(VGeneric):
builder.branch(merge_block)
builder.position_at_end(merge_block)
a = builder.phi(lc.Type.int(64))
a = builder.phi(ll.IntType(64))
a.add_incoming(a_add, add_block)
a.add_incoming(a_sub, sub_block)
r.auto_store(builder, builder.sdiv(a, b))
@ -165,19 +162,19 @@ class VFraction(VGeneric):
other = other.o_int64(builder)
a, b = self._nd(builder)
ssa_r = builder.and_(
builder.icmp(lc.ICMP_EQ, a,
builder.icmp_signed("==", a,
other.auto_load()),
builder.icmp(lc.ICMP_EQ, b,
lc.Constant.int(lc.Type.int(64), 1)))
builder.icmp_signed("==", b,
ll.Constant(ll.IntType(64), 1)))
else:
a, b = self._nd(builder)
c, d = other._nd(builder)
ssa_r = builder.and_(
builder.icmp(lc.ICMP_EQ, a, c),
builder.icmp(lc.ICMP_EQ, b, d))
builder.icmp_signed("==", a, c),
builder.icmp_signed("==", b, d))
if ne:
ssa_r = builder.xor(ssa_r,
lc.Constant.int(lc.Type.int(1), 1))
ll.Constant(ll.IntType(1), 1))
r.auto_store(builder, ssa_r)
return r
@ -194,24 +191,23 @@ class VFraction(VGeneric):
r = VBool()
if builder is not None:
diff = diff.auto_load(builder)
a = builder.extract_element(
diff, lc.Constant.int(lc.Type.int(), 0))
zero = lc.Constant.int(lc.Type.int(64), 0)
a = builder.extract_value(diff, 0)
zero = ll.Constant(ll.IntType(64), 0)
ssa_r = builder.icmp(icmp, a, zero)
r.auto_store(builder, ssa_r)
return r
def o_lt(self, other, builder):
return self._o_cmp(other, lc.ICMP_SLT, builder)
return self._o_cmp(other, "<", builder)
def o_le(self, other, builder):
return self._o_cmp(other, lc.ICMP_SLE, builder)
return self._o_cmp(other, "<=", builder)
def o_gt(self, other, builder):
return self._o_cmp(other, lc.ICMP_SGT, builder)
return self._o_cmp(other, ">", builder)
def o_ge(self, other, builder):
return self._o_cmp(other, lc.ICMP_SGE, builder)
return self._o_cmp(other, ">=", builder)
def _o_addsub(self, other, builder, sub, invert=False):
if isinstance(other, VFloat):

View File

@ -1,7 +1,5 @@
from llvm import core as lc
from artiq.py2llvm.values import operators
from artiq.py2llvm.base_types import VBool, VInt
from artiq.py2llvm.base_types import VInt
class IRange:
def __init__(self, builder, args):

View File

@ -1,13 +1,12 @@
from llvm import core as lc
from llvm import passes as lp
from llvm import ee as le
import llvmlite.ir as ll
import llvmlite.binding as llvm
from artiq.py2llvm import infer_types, ast_body, base_types, fractions, tools
class Module:
def __init__(self, env=None):
self.llvm_module = lc.Module.new("main")
self.llvm_module = ll.Module("main")
self.env = env
if self.env is not None:
@ -15,17 +14,19 @@ class Module:
fractions.init_module(self)
def finalize(self):
pass_manager = lp.PassManager.new()
pass_manager.add(lp.PASS_MEM2REG)
pass_manager.add(lp.PASS_INSTCOMBINE)
pass_manager.add(lp.PASS_REASSOCIATE)
pass_manager.add(lp.PASS_GVN)
pass_manager.add(lp.PASS_SIMPLIFYCFG)
pass_manager.run(self.llvm_module)
self.llvm_module = llvm.parse_assembly(str(self.llvm_module)) # FIXME
pmb = llvm.create_pass_manager_builder()
pmb.opt_level = 2
pm = llvm.create_module_pass_manager()
pmb.populate(pm)
pm.run(self.llvm_module)
def get_ee(self):
self.finalize()
return le.ExecutionEngine.new(self.llvm_module)
tm = llvm.Target.from_default_triple().create_target_machine()
ee = llvm.create_mcjit_compiler(self.llvm_module, tm)
ee.finalize_object()
return ee
def emit_object(self):
self.finalize()
@ -35,11 +36,12 @@ class Module:
ns = infer_types.infer_function_types(self.env, func_def, param_types)
retval = ns["return"]
function_type = lc.Type.function(retval.get_llvm_type(),
function_type = ll.FunctionType(retval.get_llvm_type(),
[ns[arg.arg].get_llvm_type() for arg in func_def.args.args])
function = self.llvm_module.add_function(function_type, func_def.name)
function = ll.Function(self.llvm_module, function_type, func_def.name)
bb = function.append_basic_block("entry")
builder = lc.Builder.new(bb)
builder = ll.IRBuilder()
builder.position_at_end(bb)
for arg_ast, arg_llvm in zip(func_def.args.args, function.args):
arg_llvm.name = arg_ast.arg

View File

@ -1,2 +1,5 @@
import llvmlite.ir as ll
def is_terminated(basic_block):
return basic_block.instructions and basic_block.instructions[-1].is_terminator
return (basic_block.instructions
and isinstance(basic_block.instructions[-1], ll.Terminator))

View File

@ -1,7 +1,7 @@
from types import SimpleNamespace
from copy import copy
from llvm import core as lc
import llvmlite.ir as ll
class VGeneric:
@ -25,7 +25,7 @@ class VGeneric:
.format(repr(self), repr(other)))
def auto_load(self, builder):
if isinstance(self.llvm_value.type, lc.PointerType):
if isinstance(self.llvm_value.type, ll.PointerType):
return builder.load(self.llvm_value)
else:
return self.llvm_value
@ -33,7 +33,7 @@ class VGeneric:
def auto_store(self, builder, llvm_value):
if self.llvm_value is None:
self.llvm_value = llvm_value
elif isinstance(self.llvm_value.type, lc.PointerType):
elif isinstance(self.llvm_value.type, ll.PointerType):
builder.store(llvm_value, self.llvm_value)
else:
raise RuntimeError(

View File

@ -98,7 +98,9 @@ These steps are required to generate bitstream (``.bit``) files, build the MiSoC
$ cd ~/artiq-dev/misoc
$ ./make.py -X ~/artiq/soc -t artiq all
* Then, build and flash the ARTIQ runtime: ::
* Then, build and flash the ARTIQ runtime:
::
$ cd ~/artiq-dev
$ git clone https://github.com/m-labs/artiq
@ -120,36 +122,30 @@ The communication parameters are 115200 8-N-1.
Installing the host-side software
---------------------------------
* Install LLVM and its Python bindings:
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. ::
* Install LLVM and the llvmlite Python bindings: ::
$ cd ~/artiq-dev
$ git clone https://github.com/openrisc/llvm-or1k
$ cd ~/artiq-dev/llvm-or1k
$ git checkout b3a48efb2c05ed6cedc5395ae726c6a6573ef3ba
$ cat ~/artiq-dev/artiq/patches/llvm/* | patch -p1
$ cd ~/artiq-dev/llvm-or1k/tools
$ git clone https://github.com/openrisc/clang-or1k clang
$ cd ~/artiq-dev/llvm-or1k/tools/clang
$ git checkout 02d831c7e7dc1517abed9cc96abdfb937af954eb
$ cat ~/artiq-dev/artiq/patches/clang/* | patch -p1
$ cd ~/artiq-dev/llvm-or1k
$ mkdir build
$ cd ~/artiq-dev/llvm-or1k/build
$ ../configure --prefix=/usr/local/llvm-or1k
$ make ENABLE_OPTIMIZED=1 REQUIRES_RTTI=1 -j4
$ sudo -E make install ENABLE_OPTIMIZED=1 REQUIRES_RTTI=1
$ make ENABLE_OPTIMIZED=1 -j4
$ sudo -E make install ENABLE_OPTIMIZED=1
$ cd ~/artiq-dev
$ git clone https://github.com/llvmpy/llvmpy
$ cd ~/artiq-dev/llvmpy
$ git checkout 7af2f7140391d4f708adf2721e84f23c1b89e97a
$ cat /path_to/artiq/patches/llvmpy/* | patch -p1
$ git clone https://github.com/numba/llvmlite
$ cd ~/artiq-dev/llvmlite
$ cat /path_to/artiq/patches/llvmlite/* | patch -p1
$ LLVM_CONFIG_PATH=/usr/local/llvm-or1k/bin/llvm-config sudo -E python setup.py install
.. note::
llvmlite is in development and its API is not stable yet. Commit ID ``11a8303d02e3d6dd2d1e0e9065701795cd8a979f`` is known to work.
.. note::
Compilation of LLVM can take more than 30 min on some machines.

View File

@ -1,32 +0,0 @@
From af106d252693b6af5c94d241fabed1c04cbb2fc6 Mon Sep 17 00:00:00 2001
From: Robert Jordens <jordens@gmail.com>
Date: Tue, 8 Jul 2014 22:35:58 -0600
Subject: [PATCH] exclude some broken aarch64 builtins
---
lib/CodeGen/CGBuiltin.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index 52e40db..d089ad3 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -1760,6 +1760,7 @@ static Value *EmitAArch64ScalarBuiltinExpr(CodeGenFunction &CGF,
// argument that specifies the vector type, need to handle each case.
switch (BuiltinID) {
default: break;
+#if 0
// Scalar Add
case AArch64::BI__builtin_neon_vaddd_s64:
Int = Intrinsic::aarch64_neon_vaddds;
@@ -1945,6 +1946,7 @@ static Value *EmitAArch64ScalarBuiltinExpr(CodeGenFunction &CGF,
case AArch64::BI__builtin_neon_vminnmvq_f32:
Int = Intrinsic::aarch64_neon_vminnmv;
AcrossVec = true; ExtendEle = false; s = "vminnmv"; break;
+#endif
}
if (!Int)
--
1.9.1

View File

@ -1,24 +0,0 @@
From 4dd12eaf0a14196f45ce4f25ed4a9f23bb3f55d5 Mon Sep 17 00:00:00 2001
From: Robert Jordens <jordens@gmail.com>
Date: Tue, 8 Jul 2014 22:37:03 -0600
Subject: [PATCH] or1k: initAsmInfo()
---
lib/Target/OR1K/OR1KTargetMachine.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/Target/OR1K/OR1KTargetMachine.cpp b/lib/Target/OR1K/OR1KTargetMachine.cpp
index 8f260f0..1771bce 100644
--- a/lib/Target/OR1K/OR1KTargetMachine.cpp
+++ b/lib/Target/OR1K/OR1KTargetMachine.cpp
@@ -41,6 +41,7 @@ OR1KTargetMachine(const Target &T, StringRef TT,
"f64:32:32-v64:32:32-v128:32:32-a0:0:32-n32"),
InstrInfo(), TLInfo(*this), TSInfo(*this),
FrameLowering(Subtarget) {
+ initAsmInfo();
}
namespace {
/// OR1K Code Generator Pass Configuration Options.
--
1.9.1

View File

@ -0,0 +1,38 @@
diff --git a/ffi/initfini.cpp b/ffi/initfini.cpp
index 42c8965..067be62 100644
--- a/ffi/initfini.cpp
+++ b/ffi/initfini.cpp
@@ -37,9 +37,10 @@ LLVMPY_Shutdown(){
// NOTE: it is important that we don't export functions which we don't use,
// especially those which may pull in large amounts of additional code or data.
-// INIT(AllTargetInfos)
-// INIT(AllTargets)
-// INIT(AllTargetMCs)
+INIT(AllTargetInfos)
+INIT(AllTargets)
+INIT(AllTargetMCs)
+INIT(AllAsmPrinters)
INIT(NativeTarget)
INIT(NativeAsmParser)
INIT(NativeAsmPrinter)
diff --git a/llvmlite/binding/initfini.py b/llvmlite/binding/initfini.py
index bfaa5b2..7d0df11 100644
--- a/llvmlite/binding/initfini.py
+++ b/llvmlite/binding/initfini.py
@@ -8,6 +8,15 @@ def initialize():
ffi.lib.LLVMPY_InitializeCore()
+def initialize_all_targets():
+ ffi.lib.LLVMPY_InitializeAllTargetInfos()
+ ffi.lib.LLVMPY_InitializeAllTargets()
+ ffi.lib.LLVMPY_InitializeAllTargetMCs()
+
+def initialize_all_asmprinters():
+ ffi.lib.LLVMPY_InitializeAllAsmPrinters()
+
+
def initialize_native_target():
"""
Initialize the native (host) target. Necessary before doing any

View File

@ -1,25 +0,0 @@
From 7f84a57f4a73837e50df7a8c6905773c0de568ab Mon Sep 17 00:00:00 2001
From: Robert Jordens <jordens@gmail.com>
Date: Tue, 8 Jul 2014 22:40:10 -0600
Subject: [PATCH] use 3.3 opcodes
---
llvm/core.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/core.py b/llvm/core.py
index 20ad062..d33860f 100644
--- a/llvm/core.py
+++ b/llvm/core.py
@@ -174,7 +174,7 @@ class OpcodeEnum(Enum):
OPCODE_PTRTOINT = 42
OPCODE_INTTOPTR = 43
OPCODE_BITCAST = 44
- if llvm.version <= (3, 3):
+ if llvm.version <= (3, 3) or True:
OPCODE_ICMP = 45
OPCODE_FCMP = 46
OPCODE_PHI = 47
--
1.9.1

View File

@ -1,12 +0,0 @@
diff --git a/llvm/core.py b/llvm/core.py
index 20ad062..245ac65 100644
--- a/llvm/core.py
+++ b/llvm/core.py
@@ -379,6 +379,7 @@ class AttrEnum(Enum):
ATTR_NAKED = AttrVal.Naked
ATTR_INLINE_HINT = AttrVal.InlineHint
ATTR_STACK_ALIGNMENT = AttrVal.StackAlignment
+ ATTR_RETURNS_TWICE = AttrVal.ReturnsTwice
AttrEnum.declare()

View File

@ -2,8 +2,9 @@ import unittest
import ast
import inspect
from fractions import Fraction
from ctypes import CFUNCTYPE, c_int, c_int32, c_int64, c_double
from llvm import ee as le
import llvmlite.binding as llvm
from artiq.language.core import int64, array
from artiq.py2llvm.infer_types import infer_function_types
@ -11,6 +12,11 @@ from artiq.py2llvm import base_types, arrays
from artiq.py2llvm.module import Module
llvm.initialize()
llvm.initialize_native_target()
llvm.initialize_native_asmprinter()
def _base_types(choice):
a = 2 # promoted later to int64
b = a + 1 # initially int32, becomes int64 after a is promoted
@ -81,34 +87,42 @@ class FunctionArrayTypesCase(unittest.TestCase):
self.assertEqual(self.ns["i"].nbits, 32)
def _value_to_ctype(v):
if isinstance(v, base_types.VBool):
return c_int
elif isinstance(v, base_types.VInt):
if v.nbits == 32:
return c_int32
elif v.nbits == 64:
return c_int64
else:
raise NotImplementedError(str(v))
elif isinstance(v, base_types.VFloat):
return c_double
else:
raise NotImplementedError(str(v))
class CompiledFunction:
def __init__(self, function, param_types):
module = Module()
func_def = ast.parse(inspect.getsource(function)).body[0]
self.function, self.retval = module.compile_function(
func_def, param_types)
self.argval = [param_types[arg.arg] for arg in func_def.args.args]
self.ee = module.get_ee()
function, retval = module.compile_function(func_def, param_types)
argvals = [param_types[arg.arg] for arg in func_def.args.args]
ee = module.get_ee()
cfptr = ee.get_pointer_to_global(
module.llvm_module.get_function(function.name))
retval_ctype = _value_to_ctype(retval)
argval_ctypes = [_value_to_ctype(argval) for argval in argvals]
self.cfunc = CFUNCTYPE(retval_ctype, *argval_ctypes)(cfptr)
# HACK: prevent garbage collection of self.cfunc internals
self.ee = ee
def __call__(self, *args):
args_llvm = []
for av, a in zip(self.argval, args):
if isinstance(av, base_types.VInt):
al = le.GenericValue.int(av.get_llvm_type(), a)
elif isinstance(av, base_types.VFloat):
al = le.GenericValue.real(av.get_llvm_type(), a)
else:
raise NotImplementedError
args_llvm.append(al)
result = self.ee.run_function(self.function, args_llvm)
if isinstance(self.retval, base_types.VBool):
return bool(result.as_int())
elif isinstance(self.retval, base_types.VInt):
return result.as_int_signed()
elif isinstance(self.retval, base_types.VFloat):
return result.as_real(self.retval.get_llvm_type())
else:
raise NotImplementedError
return self.cfunc(*args)
def arith(op, a, b):