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
|
import os
|
||||||
from fractions import Fraction
|
|
||||||
|
|
||||||
from llvm import core as lc
|
import llvmlite.ir as ll
|
||||||
from llvm import target as lt
|
import llvmlite.binding as llvm
|
||||||
|
|
||||||
from artiq.py2llvm import base_types
|
from artiq.py2llvm import base_types
|
||||||
from artiq.language import units
|
from artiq.language import units
|
||||||
|
|
||||||
|
|
||||||
lt.initialize_all()
|
llvm.initialize()
|
||||||
|
llvm.initialize_all_targets()
|
||||||
|
llvm.initialize_all_asmprinters()
|
||||||
|
|
||||||
_syscalls = {
|
_syscalls = {
|
||||||
"rpc": "i+:i",
|
"rpc": "i+:i",
|
||||||
|
@ -23,10 +24,10 @@ _syscalls = {
|
||||||
}
|
}
|
||||||
|
|
||||||
_chr_to_type = {
|
_chr_to_type = {
|
||||||
"n": lambda: lc.Type.void(),
|
"n": lambda: ll.VoidType(),
|
||||||
"b": lambda: lc.Type.int(1),
|
"b": lambda: ll.IntType(1),
|
||||||
"i": lambda: lc.Type.int(32),
|
"i": lambda: ll.IntType(32),
|
||||||
"I": lambda: lc.Type.int(64)
|
"I": lambda: ll.IntType(64)
|
||||||
}
|
}
|
||||||
|
|
||||||
_chr_to_value = {
|
_chr_to_value = {
|
||||||
|
@ -45,45 +46,50 @@ def _str_to_functype(s):
|
||||||
type_args = []
|
type_args = []
|
||||||
for n, c in enumerate(s[:-2]):
|
for n, c in enumerate(s[:-2]):
|
||||||
if c == "+":
|
if c == "+":
|
||||||
type_args.append(lc.Type.int())
|
type_args.append(ll.IntType(32))
|
||||||
var_arg_fixcount = n
|
var_arg_fixcount = n
|
||||||
elif c != "n":
|
elif c != "n":
|
||||||
type_args.append(_chr_to_type[c]())
|
type_args.append(_chr_to_type[c]())
|
||||||
return (var_arg_fixcount,
|
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))
|
var_arg=var_arg_fixcount is not None))
|
||||||
|
|
||||||
|
|
||||||
class LinkInterface:
|
class LinkInterface:
|
||||||
def init_module(self, module):
|
def init_module(self, module):
|
||||||
self.llvm_module = module.llvm_module
|
self.module = module
|
||||||
|
llvm_module = self.module.llvm_module
|
||||||
|
|
||||||
# syscalls
|
# syscalls
|
||||||
|
self.syscalls = dict()
|
||||||
self.var_arg_fixcount = dict()
|
self.var_arg_fixcount = dict()
|
||||||
for func_name, func_type_str in _syscalls.items():
|
for func_name, func_type_str in _syscalls.items():
|
||||||
var_arg_fixcount, func_type = _str_to_functype(func_type_str)
|
var_arg_fixcount, func_type = _str_to_functype(func_type_str)
|
||||||
if var_arg_fixcount is not None:
|
if var_arg_fixcount is not None:
|
||||||
self.var_arg_fixcount[func_name] = var_arg_fixcount
|
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
|
# exception handling
|
||||||
func_type = lc.Type.function(lc.Type.int(), [lc.Type.pointer(lc.Type.int(8))])
|
func_type = ll.FunctionType(ll.IntType(32),
|
||||||
function = self.llvm_module.add_function(func_type, "__eh_setjmp")
|
[ll.PointerType(ll.IntType(8))])
|
||||||
function.add_attribute(lc.ATTR_NO_UNWIND)
|
self.eh_setjmp = ll.Function(llvm_module, func_type,
|
||||||
function.add_attribute(lc.ATTR_RETURNS_TWICE)
|
"__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)), [])
|
func_type = ll.FunctionType(ll.PointerType(ll.IntType(8)), [])
|
||||||
self.llvm_module.add_function(func_type, "__eh_push")
|
self.eh_push = ll.Function(llvm_module, func_type, "__eh_push")
|
||||||
|
|
||||||
func_type = lc.Type.function(lc.Type.void(), [lc.Type.int()])
|
func_type = ll.FunctionType(ll.VoidType(), [ll.IntType(32)])
|
||||||
self.llvm_module.add_function(func_type, "__eh_pop")
|
self.eh_pop = ll.Function(llvm_module, func_type, "__eh_pop")
|
||||||
|
|
||||||
func_type = lc.Type.function(lc.Type.int(), [])
|
func_type = ll.FunctionType(ll.IntType(32), [])
|
||||||
self.llvm_module.add_function(func_type, "__eh_getid")
|
self.eh_getid = ll.Function(llvm_module, func_type, "__eh_getid")
|
||||||
|
|
||||||
func_type = lc.Type.function(lc.Type.void(), [lc.Type.int()])
|
func_type = ll.FunctionType(ll.VoidType(), [ll.IntType(32)])
|
||||||
function = self.llvm_module.add_function(func_type, "__eh_raise")
|
self.eh_raise = ll.Function(llvm_module, func_type, "__eh_raise")
|
||||||
function.add_attribute(lc.ATTR_NO_RETURN)
|
self.eh_raise.attributes.add("noreturn")
|
||||||
|
|
||||||
def build_syscall(self, syscall_name, args, builder):
|
def build_syscall(self, syscall_name, args, builder):
|
||||||
r = _chr_to_value[_syscalls[syscall_name][-1]]()
|
r = _chr_to_value[_syscalls[syscall_name][-1]]()
|
||||||
|
@ -92,33 +98,27 @@ class LinkInterface:
|
||||||
if syscall_name in self.var_arg_fixcount:
|
if syscall_name in self.var_arg_fixcount:
|
||||||
fixcount = self.var_arg_fixcount[syscall_name]
|
fixcount = self.var_arg_fixcount[syscall_name]
|
||||||
args = args[:fixcount] \
|
args = args[:fixcount] \
|
||||||
+ [lc.Constant.int(lc.Type.int(), len(args) - fixcount)] \
|
+ [ll.Constant(ll.IntType(32), len(args) - fixcount)] \
|
||||||
+ args[fixcount:]
|
+ args[fixcount:]
|
||||||
llvm_function = self.llvm_module.get_function_named(
|
r.auto_store(builder, builder.call(self.syscalls[syscall_name],
|
||||||
"__syscall_" + syscall_name)
|
args))
|
||||||
r.auto_store(builder, builder.call(llvm_function, args))
|
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def build_catch(self, builder):
|
def build_catch(self, builder):
|
||||||
eh_setjmp = self.llvm_module.get_function_named("__eh_setjmp")
|
jmpbuf = builder.call(self.eh_push, [])
|
||||||
eh_push = self.llvm_module.get_function_named("__eh_push")
|
exception_occured = builder.call(self.eh_setjmp, [jmpbuf])
|
||||||
jmpbuf = builder.call(eh_push, [])
|
return builder.icmp_signed("!=",
|
||||||
exception_occured = builder.call(eh_setjmp, [jmpbuf])
|
exception_occured,
|
||||||
return builder.icmp(lc.ICMP_NE,
|
ll.Constant(ll.IntType(32), 0))
|
||||||
exception_occured,
|
|
||||||
lc.Constant.int(lc.Type.int(), 0))
|
|
||||||
|
|
||||||
def build_pop(self, builder, levels):
|
def build_pop(self, builder, levels):
|
||||||
eh_pop = self.llvm_module.get_function_named("__eh_pop")
|
builder.call(self.eh_pop, [ll.Constant(ll.IntType(32), levels)])
|
||||||
builder.call(eh_pop, [lc.Constant.int(lc.Type.int(), levels)])
|
|
||||||
|
|
||||||
def build_getid(self, builder):
|
def build_getid(self, builder):
|
||||||
eh_getid = self.llvm_module.get_function_named("__eh_getid")
|
return builder.call(self.eh_getid, [])
|
||||||
return builder.call(eh_getid, [])
|
|
||||||
|
|
||||||
def build_raise(self, builder, eid):
|
def build_raise(self, builder, eid):
|
||||||
eh_raise = self.llvm_module.get_function_named("__eh_raise")
|
builder.call(self.eh_raise, [eid])
|
||||||
builder.call(eh_raise, [eid])
|
|
||||||
|
|
||||||
|
|
||||||
def _debug_dump_obj(obj):
|
def _debug_dump_obj(obj):
|
||||||
|
@ -148,8 +148,8 @@ class Environment(LinkInterface):
|
||||||
self.warmup_time = 1*units.ms
|
self.warmup_time = 1*units.ms
|
||||||
|
|
||||||
def emit_object(self):
|
def emit_object(self):
|
||||||
tm = lt.TargetMachine.new(triple=self.cpu_type, cpu="generic")
|
tm = llvm.Target.from_triple(self.cpu_type).create_target_machine()
|
||||||
obj = tm.emit_object(self.llvm_module)
|
obj = tm.emit_object(self.module.llvm_module)
|
||||||
_debug_dump_obj(obj)
|
_debug_dump_obj(obj)
|
||||||
return 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.values import VGeneric
|
||||||
from artiq.py2llvm.base_types import VInt
|
from artiq.py2llvm.base_types import VInt
|
||||||
|
@ -13,7 +13,7 @@ class VArray(VGeneric):
|
||||||
raise TypeError("Arrays must have at least one element")
|
raise TypeError("Arrays must have at least one element")
|
||||||
|
|
||||||
def get_llvm_type(self):
|
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):
|
def __repr__(self):
|
||||||
return "<VArray:{} x{}>".format(repr(self.el_init), self.count)
|
return "<VArray:{} x{}>".format(repr(self.el_init), self.count)
|
||||||
|
@ -42,7 +42,7 @@ class VArray(VGeneric):
|
||||||
|
|
||||||
i = VInt()
|
i = VInt()
|
||||||
i.alloca(builder, "ai_i")
|
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
|
function = builder.basic_block.function
|
||||||
copy_block = function.append_basic_block("ai_copy")
|
copy_block = function.append_basic_block("ai_copy")
|
||||||
|
@ -52,10 +52,10 @@ class VArray(VGeneric):
|
||||||
builder.position_at_end(copy_block)
|
builder.position_at_end(copy_block)
|
||||||
self.o_subscript(i, builder).set_value(builder, v.el_init)
|
self.o_subscript(i, builder).set_value(builder, v.el_init)
|
||||||
i.auto_store(builder, builder.add(
|
i.auto_store(builder, builder.add(
|
||||||
i.auto_load(builder), lc.Constant.int(lc.Type.int(), 1)))
|
i.auto_load(builder), ll.Constant(ll.IntType(32), 1)))
|
||||||
cont = builder.icmp(
|
cont = builder.icmp_signed(
|
||||||
lc.ICMP_SLT, i.auto_load(builder),
|
"<", i.auto_load(builder),
|
||||||
lc.Constant.int(lc.Type.int(), self.count))
|
ll.Constant(ll.IntType(32), self.count))
|
||||||
builder.cbranch(cont, copy_block, end_block)
|
builder.cbranch(cont, copy_block, end_block)
|
||||||
|
|
||||||
builder.position_at_end(end_block)
|
builder.position_at_end(end_block)
|
||||||
|
@ -65,6 +65,6 @@ class VArray(VGeneric):
|
||||||
if builder is not None:
|
if builder is not None:
|
||||||
index = index.o_int(builder).auto_load(builder)
|
index = index.o_int(builder).auto_load(builder)
|
||||||
ssa_r = builder.gep(self.llvm_value, [
|
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)
|
r.auto_store(builder, ssa_r)
|
||||||
return r
|
return r
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import ast
|
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 import values, base_types, fractions, arrays, iterators
|
||||||
from artiq.py2llvm.tools import is_terminated
|
from artiq.py2llvm.tools import is_terminated
|
||||||
|
@ -368,13 +369,13 @@ class Visitor:
|
||||||
if self._active_exception_stack:
|
if self._active_exception_stack:
|
||||||
finally_block, propagate, propagate_eid = (
|
finally_block, propagate, propagate_eid = (
|
||||||
self._active_exception_stack[-1])
|
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:
|
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.store(eid, propagate_eid)
|
||||||
self.builder.branch(finally_block)
|
self.builder.branch(finally_block)
|
||||||
else:
|
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)
|
self.env.build_raise(self.builder, eid)
|
||||||
|
|
||||||
def _handle_exception(self, function, finally_block,
|
def _handle_exception(self, function, finally_block,
|
||||||
|
@ -382,7 +383,7 @@ class Visitor:
|
||||||
eid = self.env.build_getid(self.builder)
|
eid = self.env.build_getid(self.builder)
|
||||||
self._active_exception_stack.append(
|
self._active_exception_stack.append(
|
||||||
(finally_block, propagate, propagate_eid))
|
(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)
|
self.builder.store(eid, propagate_eid)
|
||||||
|
|
||||||
for handler in handlers:
|
for handler in handlers:
|
||||||
|
@ -392,23 +393,23 @@ class Visitor:
|
||||||
self.builder.branch(handled_exc_block)
|
self.builder.branch(handled_exc_block)
|
||||||
else:
|
else:
|
||||||
if isinstance(handler.type, ast.Tuple):
|
if isinstance(handler.type, ast.Tuple):
|
||||||
match = self.builder.icmp(
|
match = self.builder.icmp_signed(
|
||||||
lc.ICMP_EQ, eid,
|
"==", eid,
|
||||||
lc.Constant.int(lc.Type.int(),
|
ll.Constant(ll.IntType(32),
|
||||||
handler.type.elts[0].args[0].n))
|
handler.type.elts[0].args[0].n))
|
||||||
for elt in handler.type.elts[1:]:
|
for elt in handler.type.elts[1:]:
|
||||||
match = self.builder.or_(
|
match = self.builder.or_(
|
||||||
match,
|
match,
|
||||||
self.builder.icmp(
|
self.builder.icmp_signed(
|
||||||
lc.ICMP_EQ, eid,
|
"==", eid,
|
||||||
lc.Constant.int(lc.Type.int(), elt.args[0].n)))
|
ll.Constant(ll.IntType(32), elt.args[0].n)))
|
||||||
else:
|
else:
|
||||||
match = self.builder.icmp(
|
match = self.builder.icmp_signed(
|
||||||
lc.ICMP_EQ, eid,
|
"==", eid,
|
||||||
lc.Constant.int(lc.Type.int(), handler.type.args[0].n))
|
ll.Constant(ll.IntType(32), handler.type.args[0].n))
|
||||||
self.builder.cbranch(match, handled_exc_block, cont_exc_block)
|
self.builder.cbranch(match, handled_exc_block, cont_exc_block)
|
||||||
self.builder.position_at_end(handled_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)
|
self.visit_statements(handler.body)
|
||||||
if not self._bb_terminated():
|
if not self._bb_terminated():
|
||||||
self.builder.branch(finally_block)
|
self.builder.branch(finally_block)
|
||||||
|
@ -423,10 +424,10 @@ class Visitor:
|
||||||
exc_block = function.append_basic_block("try_exc")
|
exc_block = function.append_basic_block("try_exc")
|
||||||
finally_block = function.append_basic_block("try_finally")
|
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")
|
name="propagate")
|
||||||
self.builder.store(lc.Constant.int(lc.Type.int(1), 0), propagate)
|
self.builder.store(ll.Constant(ll.IntType(1), 0), propagate)
|
||||||
propagate_eid = self.builder.alloca(lc.Type.int(),
|
propagate_eid = self.builder.alloca(ll.IntType(32),
|
||||||
name="propagate_eid")
|
name="propagate_eid")
|
||||||
exception_occured = self.env.build_catch(self.builder)
|
exception_occured = self.env.build_catch(self.builder)
|
||||||
self.builder.cbranch(exception_occured, exc_block, noexc_block)
|
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
|
from artiq.py2llvm.values import VGeneric
|
||||||
|
|
||||||
|
|
||||||
class VNone(VGeneric):
|
class VNone(VGeneric):
|
||||||
def get_llvm_type(self):
|
def get_llvm_type(self):
|
||||||
return lc.Type.void()
|
return ll.VoidType()
|
||||||
|
|
||||||
def alloca(self, builder, name):
|
def alloca(self, builder, name):
|
||||||
pass
|
pass
|
||||||
|
@ -29,7 +29,7 @@ class VInt(VGeneric):
|
||||||
self.nbits = nbits
|
self.nbits = nbits
|
||||||
|
|
||||||
def get_llvm_type(self):
|
def get_llvm_type(self):
|
||||||
return lc.Type.int(self.nbits)
|
return ll.IntType(self.nbits)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<VInt:{}>".format(self.nbits)
|
return "<VInt:{}>".format(self.nbits)
|
||||||
|
@ -50,16 +50,16 @@ class VInt(VGeneric):
|
||||||
builder, n.o_intx(self.nbits, builder).auto_load(builder))
|
builder, n.o_intx(self.nbits, builder).auto_load(builder))
|
||||||
|
|
||||||
def set_const_value(self, builder, n):
|
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):
|
def o_bool(self, builder, inv=False):
|
||||||
r = VBool()
|
r = VBool()
|
||||||
if builder is not None:
|
if builder is not None:
|
||||||
r.auto_store(
|
r.auto_store(
|
||||||
builder, builder.icmp(
|
builder, builder.icmp_signed(
|
||||||
lc.ICMP_EQ if inv else lc.ICMP_NE,
|
"==" if inv else "!=",
|
||||||
self.auto_load(builder),
|
self.auto_load(builder),
|
||||||
lc.Constant.int(self.get_llvm_type(), 0)))
|
ll.Constant(self.get_llvm_type(), 0)))
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def o_float(self, builder):
|
def o_float(self, builder):
|
||||||
|
@ -82,7 +82,7 @@ class VInt(VGeneric):
|
||||||
r.auto_store(
|
r.auto_store(
|
||||||
builder, builder.mul(
|
builder, builder.mul(
|
||||||
self.auto_load(builder),
|
self.auto_load(builder),
|
||||||
lc.Constant.int(self.get_llvm_type(), -1)))
|
ll.Constant(self.get_llvm_type(), -1)))
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def o_intx(self, target_bits, builder):
|
def o_intx(self, target_bits, builder):
|
||||||
|
@ -102,7 +102,7 @@ class VInt(VGeneric):
|
||||||
ef = builder.sext
|
ef = builder.sext
|
||||||
r.auto_store(
|
r.auto_store(
|
||||||
builder, ef(self.auto_load(builder),
|
builder, ef(self.auto_load(builder),
|
||||||
r.get_llvm_type()))
|
r.get_llvm_type()))
|
||||||
return r
|
return r
|
||||||
o_roundx = o_intx
|
o_roundx = o_intx
|
||||||
|
|
||||||
|
@ -157,7 +157,7 @@ def _make_vint_cmp_method(icmp_val):
|
||||||
right = other.o_intx(target_bits, builder)
|
right = other.o_intx(target_bits, builder)
|
||||||
r.auto_store(
|
r.auto_store(
|
||||||
builder,
|
builder,
|
||||||
builder.icmp(
|
builder.icmp_signed(
|
||||||
icmp_val, left.auto_load(builder),
|
icmp_val, left.auto_load(builder),
|
||||||
right.auto_load(builder)))
|
right.auto_load(builder)))
|
||||||
return r
|
return r
|
||||||
|
@ -165,12 +165,12 @@ def _make_vint_cmp_method(icmp_val):
|
||||||
return NotImplemented
|
return NotImplemented
|
||||||
return cmp_method
|
return cmp_method
|
||||||
|
|
||||||
for _method_name, _icmp_val in (("o_eq", lc.ICMP_EQ),
|
for _method_name, _icmp_val in (("o_eq", "=="),
|
||||||
("o_ne", lc.ICMP_NE),
|
("o_ne", "!="),
|
||||||
("o_lt", lc.ICMP_SLT),
|
("o_lt", "<"),
|
||||||
("o_le", lc.ICMP_SLE),
|
("o_le", "<="),
|
||||||
("o_gt", lc.ICMP_SGT),
|
("o_gt", ">"),
|
||||||
("o_ge", lc.ICMP_SGE)):
|
("o_ge", ">=")):
|
||||||
setattr(VInt, _method_name, _make_vint_cmp_method(_icmp_val))
|
setattr(VInt, _method_name, _make_vint_cmp_method(_icmp_val))
|
||||||
|
|
||||||
|
|
||||||
|
@ -188,7 +188,7 @@ class VBool(VInt):
|
||||||
|
|
||||||
class VFloat(VGeneric):
|
class VFloat(VGeneric):
|
||||||
def get_llvm_type(self):
|
def get_llvm_type(self):
|
||||||
return lc.Type.double()
|
return ll.DoubleType()
|
||||||
|
|
||||||
def set_value(self, builder, v):
|
def set_value(self, builder, v):
|
||||||
if not isinstance(v, VFloat):
|
if not isinstance(v, VFloat):
|
||||||
|
@ -196,7 +196,7 @@ class VFloat(VGeneric):
|
||||||
self.auto_store(builder, v.auto_load(builder))
|
self.auto_store(builder, v.auto_load(builder))
|
||||||
|
|
||||||
def set_const_value(self, builder, n):
|
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):
|
def o_float(self, builder):
|
||||||
r = VFloat()
|
r = VFloat()
|
||||||
|
@ -208,10 +208,10 @@ class VFloat(VGeneric):
|
||||||
r = VBool()
|
r = VBool()
|
||||||
if builder is not None:
|
if builder is not None:
|
||||||
r.auto_store(
|
r.auto_store(
|
||||||
builder, builder.fcmp(
|
builder, builder.fcmp_ordered(
|
||||||
lc.FCMP_UEQ if inv else lc.FCMP_UNE,
|
"==" if inv else "!=",
|
||||||
self.auto_load(builder),
|
self.auto_load(builder),
|
||||||
lc.Constant.real(self.get_llvm_type(), 0.0)))
|
ll.Constant(self.get_llvm_type(), 0.0)))
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def o_not(self, builder):
|
def o_not(self, builder):
|
||||||
|
@ -223,7 +223,7 @@ class VFloat(VGeneric):
|
||||||
r.auto_store(
|
r.auto_store(
|
||||||
builder, builder.fmul(
|
builder, builder.fmul(
|
||||||
self.auto_load(builder),
|
self.auto_load(builder),
|
||||||
lc.Constant.real(self.get_llvm_type(), -1.0)))
|
ll.Constant(self.get_llvm_type(), -1.0)))
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def o_intx(self, target_bits, builder):
|
def o_intx(self, target_bits, builder):
|
||||||
|
@ -244,10 +244,10 @@ class VFloat(VGeneric):
|
||||||
half.alloca(builder, "half")
|
half.alloca(builder, "half")
|
||||||
half.set_const_value(builder, 0.5)
|
half.set_const_value(builder, 0.5)
|
||||||
|
|
||||||
condition = builder.icmp(
|
condition = builder.fcmp_ordered(
|
||||||
lc.FCMP_OLT,
|
"<",
|
||||||
self.auto_load(builder),
|
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.cbranch(condition, neg_block, merge_block)
|
||||||
|
|
||||||
builder.position_at_end(neg_block)
|
builder.position_at_end(neg_block)
|
||||||
|
@ -299,16 +299,16 @@ def _make_vfloat_cmp_method(fcmp_val):
|
||||||
right = other.o_float(builder)
|
right = other.o_float(builder)
|
||||||
r.auto_store(
|
r.auto_store(
|
||||||
builder,
|
builder,
|
||||||
builder.fcmp(
|
builder.fcmp_ordered(
|
||||||
fcmp_val, left.auto_load(builder),
|
fcmp_val, left.auto_load(builder),
|
||||||
right.auto_load(builder)))
|
right.auto_load(builder)))
|
||||||
return r
|
return r
|
||||||
return cmp_method
|
return cmp_method
|
||||||
|
|
||||||
for _method_name, _fcmp_val in (("o_eq", lc.FCMP_OEQ),
|
for _method_name, _fcmp_val in (("o_eq", "=="),
|
||||||
("o_ne", lc.FCMP_ONE),
|
("o_ne", "!="),
|
||||||
("o_lt", lc.FCMP_OLT),
|
("o_lt", "<"),
|
||||||
("o_le", lc.FCMP_OLE),
|
("o_le", "<="),
|
||||||
("o_gt", lc.FCMP_OGT),
|
("o_gt", ">"),
|
||||||
("o_ge", lc.FCMP_OGE)):
|
("o_ge", ">=")):
|
||||||
setattr(VFloat, _method_name, _make_vfloat_cmp_method(_fcmp_val))
|
setattr(VFloat, _method_name, _make_vfloat_cmp_method(_fcmp_val))
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import inspect
|
import inspect
|
||||||
import ast
|
import ast
|
||||||
|
|
||||||
from llvm import core as lc
|
import llvmlite.ir as ll
|
||||||
|
|
||||||
from artiq.py2llvm.values import VGeneric, operators
|
from artiq.py2llvm.values import VGeneric, operators
|
||||||
from artiq.py2llvm.base_types import VBool, VInt, VFloat
|
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]
|
func_def = ast.parse(inspect.getsource(_gcd)).body[0]
|
||||||
function, _ = module.compile_function(func_def,
|
function, _ = module.compile_function(func_def,
|
||||||
{"a": VInt(64), "b": VInt(64)})
|
{"a": VInt(64), "b": VInt(64)})
|
||||||
function.linkage = lc.LINKAGE_INTERNAL
|
function.linkage = "internal"
|
||||||
|
|
||||||
|
|
||||||
def _reduce(builder, a, b):
|
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])
|
gcd = builder.call(gcd_f, [a, b])
|
||||||
a = builder.sdiv(a, gcd)
|
a = builder.sdiv(a, gcd)
|
||||||
b = builder.sdiv(b, gcd)
|
b = builder.sdiv(b, gcd)
|
||||||
|
@ -38,21 +42,21 @@ def _signnum(builder, a, b):
|
||||||
swap_block = function.append_basic_block("sn_swap")
|
swap_block = function.append_basic_block("sn_swap")
|
||||||
merge_block = function.append_basic_block("sn_merge")
|
merge_block = function.append_basic_block("sn_merge")
|
||||||
|
|
||||||
condition = builder.icmp(
|
condition = builder.icmp_signed(
|
||||||
lc.ICMP_SLT, b, lc.Constant.int(lc.Type.int(64), 0))
|
"<", b, ll.Constant(ll.IntType(64), 0))
|
||||||
builder.cbranch(condition, swap_block, merge_block)
|
builder.cbranch(condition, swap_block, merge_block)
|
||||||
|
|
||||||
builder.position_at_end(swap_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)
|
a_swp = builder.mul(minusone, a)
|
||||||
b_swp = builder.mul(minusone, b)
|
b_swp = builder.mul(minusone, b)
|
||||||
builder.branch(merge_block)
|
builder.branch(merge_block)
|
||||||
|
|
||||||
builder.position_at_end(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, orig_block)
|
||||||
a_phi.add_incoming(a_swp, swap_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, orig_block)
|
||||||
b_phi.add_incoming(b_swp, swap_block)
|
b_phi.add_incoming(b_swp, swap_block)
|
||||||
|
|
||||||
|
@ -60,24 +64,20 @@ def _signnum(builder, a, b):
|
||||||
|
|
||||||
|
|
||||||
def _make_ssa(builder, n, d):
|
def _make_ssa(builder, n, d):
|
||||||
value = lc.Constant.undef(lc.Type.vector(lc.Type.int(64), 2))
|
value = ll.Constant(ll.ArrayType(ll.IntType(64), 2), ll.Undefined)
|
||||||
value = builder.insert_element(
|
value = builder.insert_value(value, n, 0)
|
||||||
value, n, lc.Constant.int(lc.Type.int(), 0))
|
value = builder.insert_value(value, d, 1)
|
||||||
value = builder.insert_element(
|
|
||||||
value, d, lc.Constant.int(lc.Type.int(), 1))
|
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
class VFraction(VGeneric):
|
class VFraction(VGeneric):
|
||||||
def get_llvm_type(self):
|
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):
|
def _nd(self, builder):
|
||||||
ssa_value = self.auto_load(builder)
|
ssa_value = self.auto_load(builder)
|
||||||
a = builder.extract_element(
|
a = builder.extract_value(ssa_value, 0)
|
||||||
ssa_value, lc.Constant.int(lc.Type.int(), 0))
|
b = builder.extract_value(ssa_value, 1)
|
||||||
b = builder.extract_element(
|
|
||||||
ssa_value, lc.Constant.int(lc.Type.int(), 1))
|
|
||||||
return a, b
|
return a, b
|
||||||
|
|
||||||
def set_value_nd(self, builder, a, b):
|
def set_value_nd(self, builder, a, b):
|
||||||
|
@ -101,19 +101,16 @@ class VFraction(VGeneric):
|
||||||
raise AttributeError
|
raise AttributeError
|
||||||
r = VInt(64)
|
r = VInt(64)
|
||||||
if builder is not None:
|
if builder is not None:
|
||||||
elt = builder.extract_element(
|
elt = builder.extract_value(self.auto_load(builder), idx)
|
||||||
self.auto_load(builder),
|
|
||||||
lc.Constant.int(lc.Type.int(), idx))
|
|
||||||
r.auto_store(builder, elt)
|
r.auto_store(builder, elt)
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def o_bool(self, builder):
|
def o_bool(self, builder):
|
||||||
r = VBool()
|
r = VBool()
|
||||||
if builder is not None:
|
if builder is not None:
|
||||||
zero = lc.Constant.int(lc.Type.int(64), 0)
|
zero = ll.Constant(ll.IntType(64), 0)
|
||||||
a = builder.extract_element(
|
a = builder.extract_element(self.auto_load(builder), 0)
|
||||||
self.auto_load(builder), lc.Constant.int(lc.Type.int(), 0))
|
r.auto_store(builder, builder.icmp_signed("!=", a, zero))
|
||||||
r.auto_store(builder, builder.icmp(lc.ICMP_NE, a, zero))
|
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def o_intx(self, target_bits, builder):
|
def o_intx(self, target_bits, builder):
|
||||||
|
@ -131,15 +128,15 @@ class VFraction(VGeneric):
|
||||||
else:
|
else:
|
||||||
r = VInt(64)
|
r = VInt(64)
|
||||||
a, b = self._nd(builder)
|
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
|
function = builder.basic_block.function
|
||||||
add_block = function.append_basic_block("fr_add")
|
add_block = function.append_basic_block("fr_add")
|
||||||
sub_block = function.append_basic_block("fr_sub")
|
sub_block = function.append_basic_block("fr_sub")
|
||||||
merge_block = function.append_basic_block("fr_merge")
|
merge_block = function.append_basic_block("fr_merge")
|
||||||
|
|
||||||
condition = builder.icmp(
|
condition = builder.icmp_signed(
|
||||||
lc.ICMP_SLT, a, lc.Constant.int(lc.Type.int(64), 0))
|
"<", a, ll.Constant(ll.IntType(64), 0))
|
||||||
builder.cbranch(condition, sub_block, add_block)
|
builder.cbranch(condition, sub_block, add_block)
|
||||||
|
|
||||||
builder.position_at_end(add_block)
|
builder.position_at_end(add_block)
|
||||||
|
@ -150,7 +147,7 @@ class VFraction(VGeneric):
|
||||||
builder.branch(merge_block)
|
builder.branch(merge_block)
|
||||||
|
|
||||||
builder.position_at_end(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_add, add_block)
|
||||||
a.add_incoming(a_sub, sub_block)
|
a.add_incoming(a_sub, sub_block)
|
||||||
r.auto_store(builder, builder.sdiv(a, b))
|
r.auto_store(builder, builder.sdiv(a, b))
|
||||||
|
@ -165,19 +162,19 @@ class VFraction(VGeneric):
|
||||||
other = other.o_int64(builder)
|
other = other.o_int64(builder)
|
||||||
a, b = self._nd(builder)
|
a, b = self._nd(builder)
|
||||||
ssa_r = builder.and_(
|
ssa_r = builder.and_(
|
||||||
builder.icmp(lc.ICMP_EQ, a,
|
builder.icmp_signed("==", a,
|
||||||
other.auto_load()),
|
other.auto_load()),
|
||||||
builder.icmp(lc.ICMP_EQ, b,
|
builder.icmp_signed("==", b,
|
||||||
lc.Constant.int(lc.Type.int(64), 1)))
|
ll.Constant(ll.IntType(64), 1)))
|
||||||
else:
|
else:
|
||||||
a, b = self._nd(builder)
|
a, b = self._nd(builder)
|
||||||
c, d = other._nd(builder)
|
c, d = other._nd(builder)
|
||||||
ssa_r = builder.and_(
|
ssa_r = builder.and_(
|
||||||
builder.icmp(lc.ICMP_EQ, a, c),
|
builder.icmp_signed("==", a, c),
|
||||||
builder.icmp(lc.ICMP_EQ, b, d))
|
builder.icmp_signed("==", b, d))
|
||||||
if ne:
|
if ne:
|
||||||
ssa_r = builder.xor(ssa_r,
|
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)
|
r.auto_store(builder, ssa_r)
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
@ -194,24 +191,23 @@ class VFraction(VGeneric):
|
||||||
r = VBool()
|
r = VBool()
|
||||||
if builder is not None:
|
if builder is not None:
|
||||||
diff = diff.auto_load(builder)
|
diff = diff.auto_load(builder)
|
||||||
a = builder.extract_element(
|
a = builder.extract_value(diff, 0)
|
||||||
diff, lc.Constant.int(lc.Type.int(), 0))
|
zero = ll.Constant(ll.IntType(64), 0)
|
||||||
zero = lc.Constant.int(lc.Type.int(64), 0)
|
|
||||||
ssa_r = builder.icmp(icmp, a, zero)
|
ssa_r = builder.icmp(icmp, a, zero)
|
||||||
r.auto_store(builder, ssa_r)
|
r.auto_store(builder, ssa_r)
|
||||||
return r
|
return r
|
||||||
|
|
||||||
def o_lt(self, other, builder):
|
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):
|
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):
|
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):
|
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):
|
def _o_addsub(self, other, builder, sub, invert=False):
|
||||||
if isinstance(other, VFloat):
|
if isinstance(other, VFloat):
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
from llvm import core as lc
|
|
||||||
|
|
||||||
from artiq.py2llvm.values import operators
|
from artiq.py2llvm.values import operators
|
||||||
from artiq.py2llvm.base_types import VBool, VInt
|
from artiq.py2llvm.base_types import VInt
|
||||||
|
|
||||||
class IRange:
|
class IRange:
|
||||||
def __init__(self, builder, args):
|
def __init__(self, builder, args):
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
from llvm import core as lc
|
import llvmlite.ir as ll
|
||||||
from llvm import passes as lp
|
import llvmlite.binding as llvm
|
||||||
from llvm import ee as le
|
|
||||||
|
|
||||||
from artiq.py2llvm import infer_types, ast_body, base_types, fractions, tools
|
from artiq.py2llvm import infer_types, ast_body, base_types, fractions, tools
|
||||||
|
|
||||||
|
|
||||||
class Module:
|
class Module:
|
||||||
def __init__(self, env=None):
|
def __init__(self, env=None):
|
||||||
self.llvm_module = lc.Module.new("main")
|
self.llvm_module = ll.Module("main")
|
||||||
self.env = env
|
self.env = env
|
||||||
|
|
||||||
if self.env is not None:
|
if self.env is not None:
|
||||||
|
@ -15,17 +14,19 @@ class Module:
|
||||||
fractions.init_module(self)
|
fractions.init_module(self)
|
||||||
|
|
||||||
def finalize(self):
|
def finalize(self):
|
||||||
pass_manager = lp.PassManager.new()
|
self.llvm_module = llvm.parse_assembly(str(self.llvm_module)) # FIXME
|
||||||
pass_manager.add(lp.PASS_MEM2REG)
|
pmb = llvm.create_pass_manager_builder()
|
||||||
pass_manager.add(lp.PASS_INSTCOMBINE)
|
pmb.opt_level = 2
|
||||||
pass_manager.add(lp.PASS_REASSOCIATE)
|
pm = llvm.create_module_pass_manager()
|
||||||
pass_manager.add(lp.PASS_GVN)
|
pmb.populate(pm)
|
||||||
pass_manager.add(lp.PASS_SIMPLIFYCFG)
|
pm.run(self.llvm_module)
|
||||||
pass_manager.run(self.llvm_module)
|
|
||||||
|
|
||||||
def get_ee(self):
|
def get_ee(self):
|
||||||
self.finalize()
|
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):
|
def emit_object(self):
|
||||||
self.finalize()
|
self.finalize()
|
||||||
|
@ -35,11 +36,12 @@ class Module:
|
||||||
ns = infer_types.infer_function_types(self.env, func_def, param_types)
|
ns = infer_types.infer_function_types(self.env, func_def, param_types)
|
||||||
retval = ns["return"]
|
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])
|
[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")
|
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):
|
for arg_ast, arg_llvm in zip(func_def.args.args, function.args):
|
||||||
arg_llvm.name = arg_ast.arg
|
arg_llvm.name = arg_ast.arg
|
||||||
|
|
|
@ -1,2 +1,5 @@
|
||||||
|
import llvmlite.ir as ll
|
||||||
|
|
||||||
def is_terminated(basic_block):
|
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 types import SimpleNamespace
|
||||||
from copy import copy
|
from copy import copy
|
||||||
|
|
||||||
from llvm import core as lc
|
import llvmlite.ir as ll
|
||||||
|
|
||||||
|
|
||||||
class VGeneric:
|
class VGeneric:
|
||||||
|
@ -25,7 +25,7 @@ class VGeneric:
|
||||||
.format(repr(self), repr(other)))
|
.format(repr(self), repr(other)))
|
||||||
|
|
||||||
def auto_load(self, builder):
|
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)
|
return builder.load(self.llvm_value)
|
||||||
else:
|
else:
|
||||||
return self.llvm_value
|
return self.llvm_value
|
||||||
|
@ -33,7 +33,7 @@ class VGeneric:
|
||||||
def auto_store(self, builder, llvm_value):
|
def auto_store(self, builder, llvm_value):
|
||||||
if self.llvm_value is None:
|
if self.llvm_value is None:
|
||||||
self.llvm_value = llvm_value
|
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)
|
builder.store(llvm_value, self.llvm_value)
|
||||||
else:
|
else:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
|
@ -60,14 +60,14 @@ class VGeneric:
|
||||||
def _make_binary_operator(op_name):
|
def _make_binary_operator(op_name):
|
||||||
def op(l, r, builder):
|
def op(l, r, builder):
|
||||||
try:
|
try:
|
||||||
opf = getattr(l, "o_"+op_name)
|
opf = getattr(l, "o_" + op_name)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
result = NotImplemented
|
result = NotImplemented
|
||||||
else:
|
else:
|
||||||
result = opf(r, builder)
|
result = opf(r, builder)
|
||||||
if result is NotImplemented:
|
if result is NotImplemented:
|
||||||
try:
|
try:
|
||||||
ropf = getattr(r, "or_"+op_name)
|
ropf = getattr(r, "or_" + op_name)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
result = NotImplemented
|
result = NotImplemented
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -98,7 +98,9 @@ These steps are required to generate bitstream (``.bit``) files, build the MiSoC
|
||||||
$ cd ~/artiq-dev/misoc
|
$ cd ~/artiq-dev/misoc
|
||||||
$ ./make.py -X ~/artiq/soc -t artiq all
|
$ ./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
|
$ cd ~/artiq-dev
|
||||||
$ git clone https://github.com/m-labs/artiq
|
$ 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
|
Installing the host-side software
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
||||||
* Install LLVM and its Python bindings:
|
* Install LLVM and the llvmlite 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. ::
|
|
||||||
|
|
||||||
$ cd ~/artiq-dev
|
$ cd ~/artiq-dev
|
||||||
$ git clone https://github.com/openrisc/llvm-or1k
|
$ 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
|
$ cd ~/artiq-dev/llvm-or1k/tools
|
||||||
$ git clone https://github.com/openrisc/clang-or1k clang
|
$ git clone https://github.com/openrisc/clang-or1k clang
|
||||||
$ cd ~/artiq-dev/llvm-or1k/tools/clang
|
$ cd ~/artiq-dev/llvm-or1k/tools/clang
|
||||||
$ git checkout 02d831c7e7dc1517abed9cc96abdfb937af954eb
|
|
||||||
$ cat ~/artiq-dev/artiq/patches/clang/* | patch -p1
|
|
||||||
|
|
||||||
$ cd ~/artiq-dev/llvm-or1k
|
$ cd ~/artiq-dev/llvm-or1k
|
||||||
$ mkdir build
|
$ mkdir build
|
||||||
$ cd ~/artiq-dev/llvm-or1k/build
|
$ cd ~/artiq-dev/llvm-or1k/build
|
||||||
$ ../configure --prefix=/usr/local/llvm-or1k
|
$ ../configure --prefix=/usr/local/llvm-or1k
|
||||||
$ make ENABLE_OPTIMIZED=1 REQUIRES_RTTI=1 -j4
|
$ make ENABLE_OPTIMIZED=1 -j4
|
||||||
$ sudo -E make install ENABLE_OPTIMIZED=1 REQUIRES_RTTI=1
|
$ sudo -E make install ENABLE_OPTIMIZED=1
|
||||||
|
|
||||||
$ cd ~/artiq-dev
|
$ cd ~/artiq-dev
|
||||||
$ git clone https://github.com/llvmpy/llvmpy
|
$ git clone https://github.com/numba/llvmlite
|
||||||
$ cd ~/artiq-dev/llvmpy
|
$ cd ~/artiq-dev/llvmlite
|
||||||
$ git checkout 7af2f7140391d4f708adf2721e84f23c1b89e97a
|
$ cat /path_to/artiq/patches/llvmlite/* | patch -p1
|
||||||
$ cat /path_to/artiq/patches/llvmpy/* | patch -p1
|
|
||||||
$ LLVM_CONFIG_PATH=/usr/local/llvm-or1k/bin/llvm-config sudo -E python setup.py install
|
$ 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::
|
.. note::
|
||||||
Compilation of LLVM can take more than 30 min on some machines.
|
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 ast
|
||||||
import inspect
|
import inspect
|
||||||
from fractions import Fraction
|
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.language.core import int64, array
|
||||||
from artiq.py2llvm.infer_types import infer_function_types
|
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
|
from artiq.py2llvm.module import Module
|
||||||
|
|
||||||
|
|
||||||
|
llvm.initialize()
|
||||||
|
llvm.initialize_native_target()
|
||||||
|
llvm.initialize_native_asmprinter()
|
||||||
|
|
||||||
|
|
||||||
def _base_types(choice):
|
def _base_types(choice):
|
||||||
a = 2 # promoted later to int64
|
a = 2 # promoted later to int64
|
||||||
b = a + 1 # initially int32, becomes int64 after a is promoted
|
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)
|
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:
|
class CompiledFunction:
|
||||||
def __init__(self, function, param_types):
|
def __init__(self, function, param_types):
|
||||||
module = Module()
|
module = Module()
|
||||||
|
|
||||||
func_def = ast.parse(inspect.getsource(function)).body[0]
|
func_def = ast.parse(inspect.getsource(function)).body[0]
|
||||||
self.function, self.retval = module.compile_function(
|
function, retval = module.compile_function(func_def, param_types)
|
||||||
func_def, param_types)
|
argvals = [param_types[arg.arg] for arg in func_def.args.args]
|
||||||
self.argval = [param_types[arg.arg] for arg in func_def.args.args]
|
|
||||||
self.ee = module.get_ee()
|
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):
|
def __call__(self, *args):
|
||||||
args_llvm = []
|
return self.cfunc(*args)
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
def arith(op, a, b):
|
def arith(op, a, b):
|
||||||
|
|
Loading…
Reference in New Issue