forked from M-Labs/artiq
compiler: add builtinInvoke for subkernel raising functions
This commit is contained in:
parent
fb8dd01e8d
commit
c5c5708f49
|
@ -1047,6 +1047,42 @@ class Builtin(Instruction):
|
||||||
def opcode(self):
|
def opcode(self):
|
||||||
return "builtin({})".format(self.op)
|
return "builtin({})".format(self.op)
|
||||||
|
|
||||||
|
class BuiltinInvoke(Terminator):
|
||||||
|
"""
|
||||||
|
A builtin operation which can raise exceptions.
|
||||||
|
|
||||||
|
:ivar op: (string) operation name
|
||||||
|
"""
|
||||||
|
|
||||||
|
"""
|
||||||
|
:param op: (string) operation name
|
||||||
|
:param normal: (:class:`BasicBlock`) normal target
|
||||||
|
:param exn: (:class:`BasicBlock`) exceptional target
|
||||||
|
"""
|
||||||
|
def __init__(self, op, operands, typ, normal, exn, name=None):
|
||||||
|
assert isinstance(op, str)
|
||||||
|
for operand in operands: assert isinstance(operand, Value)
|
||||||
|
assert isinstance(normal, BasicBlock)
|
||||||
|
assert isinstance(exn, BasicBlock)
|
||||||
|
if name is None:
|
||||||
|
name = "BLTINV.{}".format(op)
|
||||||
|
super().__init__(operands + [normal, exn], typ, name)
|
||||||
|
self.op = op
|
||||||
|
|
||||||
|
def copy(self, mapper):
|
||||||
|
self_copy = super().copy(mapper)
|
||||||
|
self_copy.op = self.op
|
||||||
|
return self_copy
|
||||||
|
|
||||||
|
def normal_target(self):
|
||||||
|
return self.operands[-2]
|
||||||
|
|
||||||
|
def exception_target(self):
|
||||||
|
return self.operands[-1]
|
||||||
|
|
||||||
|
def opcode(self):
|
||||||
|
return "builtinInvokable({})".format(self.op)
|
||||||
|
|
||||||
class Closure(Instruction):
|
class Closure(Instruction):
|
||||||
"""
|
"""
|
||||||
A closure creation operation.
|
A closure creation operation.
|
||||||
|
|
|
@ -2544,10 +2544,22 @@ class ARTIQIRGenerator(algorithm.Visitor):
|
||||||
fn = types.get_method_function(fn)
|
fn = types.get_method_function(fn)
|
||||||
sid = ir.Constant(fn.sid, builtins.TInt32())
|
sid = ir.Constant(fn.sid, builtins.TInt32())
|
||||||
if not builtins.is_none(fn.ret):
|
if not builtins.is_none(fn.ret):
|
||||||
|
if self.unwind_target is None:
|
||||||
ret = self.append(ir.Builtin("subkernel_retrieve_return", [sid, timeout], fn.ret))
|
ret = self.append(ir.Builtin("subkernel_retrieve_return", [sid, timeout], fn.ret))
|
||||||
|
else:
|
||||||
|
after_invoke = self.add_block("invoke")
|
||||||
|
ret = self.append(ir.BuiltinInvoke("subkernel_retrieve_return", [sid, timeout],
|
||||||
|
fn.ret, after_invoke, self.unwind_target))
|
||||||
|
self.current_block = after_invoke
|
||||||
else:
|
else:
|
||||||
ret = ir.Constant(None, builtins.TNone())
|
ret = ir.Constant(None, builtins.TNone())
|
||||||
|
if self.unwind_target is None:
|
||||||
self.append(ir.Builtin("subkernel_await_finish", [sid, timeout], builtins.TNone()))
|
self.append(ir.Builtin("subkernel_await_finish", [sid, timeout], builtins.TNone()))
|
||||||
|
else:
|
||||||
|
after_invoke = self.add_block("invoke")
|
||||||
|
self.append(ir.BuiltinInvoke("subkernel_await_finish", [sid, timeout],
|
||||||
|
builtins.TNone(), after_invoke, self.unwind_target))
|
||||||
|
self.current_block = after_invoke
|
||||||
return ret
|
return ret
|
||||||
elif types.is_builtin(typ, "subkernel_preload"):
|
elif types.is_builtin(typ, "subkernel_preload"):
|
||||||
if len(node.args) == 1 and len(node.keywords) == 0:
|
if len(node.args) == 1 and len(node.keywords) == 0:
|
||||||
|
@ -2594,7 +2606,14 @@ class ARTIQIRGenerator(algorithm.Visitor):
|
||||||
{"name": name, "recv": vartype, "send": msg.value_type},
|
{"name": name, "recv": vartype, "send": msg.value_type},
|
||||||
node.loc)
|
node.loc)
|
||||||
self.engine.process(diag)
|
self.engine.process(diag)
|
||||||
return self.append(ir.Builtin("subkernel_recv", [msg_id, timeout], vartype))
|
if self.unwind_target is None:
|
||||||
|
ret = self.append(ir.Builtin("subkernel_recv", [msg_id, timeout], vartype))
|
||||||
|
else:
|
||||||
|
after_invoke = self.add_block("invoke")
|
||||||
|
ret = self.append(ir.BuiltinInvoke("subkernel_recv", [msg_id, timeout],
|
||||||
|
vartype, after_invoke, self.unwind_target))
|
||||||
|
self.current_block = after_invoke
|
||||||
|
return ret
|
||||||
elif types.is_exn_constructor(typ):
|
elif types.is_exn_constructor(typ):
|
||||||
return self.alloc_exn(node.type, *[self.visit(arg_node) for arg_node in node.args])
|
return self.alloc_exn(node.type, *[self.visit(arg_node) for arg_node in node.args])
|
||||||
elif types.is_constructor(typ):
|
elif types.is_constructor(typ):
|
||||||
|
@ -2946,7 +2965,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
|
||||||
format_string += ")"
|
format_string += ")"
|
||||||
elif builtins.is_exception(value.type):
|
elif builtins.is_exception(value.type):
|
||||||
# message may not be an actual string...
|
# message may not be an actual string...
|
||||||
# so we cannot really print it
|
# so we cannot really print itInvoke
|
||||||
name = self.append(ir.GetAttr(value, "#__name__"))
|
name = self.append(ir.GetAttr(value, "#__name__"))
|
||||||
param1 = self.append(ir.GetAttr(value, "#__param0__"))
|
param1 = self.append(ir.GetAttr(value, "#__param0__"))
|
||||||
param2 = self.append(ir.GetAttr(value, "#__param1__"))
|
param2 = self.append(ir.GetAttr(value, "#__param1__"))
|
||||||
|
|
|
@ -1437,6 +1437,44 @@ class LLVMIRGenerator:
|
||||||
else:
|
else:
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
|
def process_BuiltinInvoke(self, insn):
|
||||||
|
llnormalblock = self.map(insn.normal_target())
|
||||||
|
llunwindblock = self.map(insn.exception_target())
|
||||||
|
if insn.op == "subkernel_retrieve_return":
|
||||||
|
llsid = self.map(insn.operands[0])
|
||||||
|
lltimeout = self.map(insn.operands[1])
|
||||||
|
lltagptr = self._build_subkernel_tags([insn.type])
|
||||||
|
llheadu = self.llbuilder.append_basic_block(name="subkernel.await.unwind")
|
||||||
|
self.llbuilder.invoke(self.llbuiltin("subkernel_await_message"),
|
||||||
|
[llsid, lltimeout, lltagptr, ll.Constant(lli8, 1), ll.Constant(lli8, 1)],
|
||||||
|
llheadu, llunwindblock,
|
||||||
|
name="subkernel.await.message")
|
||||||
|
self.llbuilder.position_at_end(llheadu)
|
||||||
|
llstackptr = self.llbuilder.call(self.llbuiltin("llvm.stacksave"), [],
|
||||||
|
name="subkernel.arg.stack")
|
||||||
|
return self._build_rpc_recv(insn.type, llstackptr, llnormalblock, llunwindblock)
|
||||||
|
elif insn.op == "subkernel_await_finish":
|
||||||
|
llsid = self.map(insn.operands[0])
|
||||||
|
lltimeout = self.map(insn.operands[1])
|
||||||
|
return self.llbuilder.invoke(self.llbuiltin("subkernel_await_finish"), [llsid, lltimeout],
|
||||||
|
llnormalblock, llunwindblock,
|
||||||
|
name="subkernel.await.finish")
|
||||||
|
elif insn.op == "subkernel_recv":
|
||||||
|
llmsgid = self.map(insn.operands[0])
|
||||||
|
lltimeout = self.map(insn.operands[1])
|
||||||
|
lltagptr = self._build_subkernel_tags([insn.type])
|
||||||
|
llheadu = self.llbuilder.append_basic_block(name="subkernel.await.unwind")
|
||||||
|
self.llbuilder.invoke(self.llbuiltin("subkernel_await_message"),
|
||||||
|
[llmsgid, lltimeout, lltagptr, ll.Constant(lli8, 1), ll.Constant(lli8, 1)],
|
||||||
|
llheadu, llunwindblock,
|
||||||
|
name="subkernel.await.message")
|
||||||
|
self.llbuilder.position_at_end(llheadu)
|
||||||
|
llstackptr = self.llbuilder.call(self.llbuiltin("llvm.stacksave"), [],
|
||||||
|
name="subkernel.arg.stack")
|
||||||
|
return self._build_rpc_recv(insn.type, llstackptr, llnormalblock, llunwindblock)
|
||||||
|
else:
|
||||||
|
assert False
|
||||||
|
|
||||||
def process_SubkernelAwaitArgs(self, insn):
|
def process_SubkernelAwaitArgs(self, insn):
|
||||||
llmin = self.map(insn.operands[0])
|
llmin = self.map(insn.operands[0])
|
||||||
llmax = self.map(insn.operands[1])
|
llmax = self.map(insn.operands[1])
|
||||||
|
|
|
@ -278,8 +278,15 @@ pub mod subkernel {
|
||||||
{
|
{
|
||||||
let mut reader = Cursor::new(buffer);
|
let mut reader = Cursor::new(buffer);
|
||||||
|
|
||||||
let _sync = reader.read_u32()?;
|
let mut byte = reader.read_u8()?;
|
||||||
let _9 = reader.read_u8()?;
|
// to sync
|
||||||
|
while byte != 0x5a {
|
||||||
|
byte = reader.read_u8()?;
|
||||||
|
}
|
||||||
|
// skip sync bytes, 0x09 indicates exception
|
||||||
|
while byte != 0x09 {
|
||||||
|
byte = reader.read_u8()?;
|
||||||
|
}
|
||||||
let _len = reader.read_u32()?;
|
let _len = reader.read_u32()?;
|
||||||
// ignore the remaining exceptions, stack traces etc. - unwinding from another device would be unwise anyway
|
// ignore the remaining exceptions, stack traces etc. - unwinding from another device would be unwise anyway
|
||||||
Ok(Exception {
|
Ok(Exception {
|
||||||
|
|
Loading…
Reference in New Issue