mirror of https://github.com/m-labs/artiq.git
switch to llvmlite
This commit is contained in:
parent
b93b969e2a
commit
159f632a65
|
@ -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,
|
||||
var_arg=var_arg_fixcount is not None))
|
||||
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,
|
||||
exception_occured,
|
||||
lc.Constant.int(lc.Type.int(), 0))
|
||||
jmpbuf = builder.call(self.eh_push, [])
|
||||
exception_occured = builder.call(self.eh_setjmp, [jmpbuf])
|
||||
return builder.icmp_signed("!=",
|
||||
exception_occured,
|
||||
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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(),
|
||||
handler.type.elts[0].args[0].n))
|
||||
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)
|
||||
|
|
|
@ -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):
|
||||
|
@ -102,7 +102,7 @@ class VInt(VGeneric):
|
|||
ef = builder.sext
|
||||
r.auto_store(
|
||||
builder, ef(self.auto_load(builder),
|
||||
r.get_llvm_type()))
|
||||
r.get_llvm_type()))
|
||||
return r
|
||||
o_roundx = o_intx
|
||||
|
||||
|
@ -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))
|
||||
|
|
|
@ -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,
|
||||
other.auto_load()),
|
||||
builder.icmp(lc.ICMP_EQ, b,
|
||||
lc.Constant.int(lc.Type.int(64), 1)))
|
||||
builder.icmp_signed("==", a,
|
||||
other.auto_load()),
|
||||
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):
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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(
|
||||
|
@ -60,14 +60,14 @@ class VGeneric:
|
|||
def _make_binary_operator(op_name):
|
||||
def op(l, r, builder):
|
||||
try:
|
||||
opf = getattr(l, "o_"+op_name)
|
||||
opf = getattr(l, "o_" + op_name)
|
||||
except AttributeError:
|
||||
result = NotImplemented
|
||||
else:
|
||||
result = opf(r, builder)
|
||||
if result is NotImplemented:
|
||||
try:
|
||||
ropf = getattr(r, "or_"+op_name)
|
||||
ropf = getattr(r, "or_" + op_name)
|
||||
except AttributeError:
|
||||
result = NotImplemented
|
||||
else:
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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()
|
||||
|
|
@ -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):
|
||||
|
|
Loading…
Reference in New Issue