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):
|
||||
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):
|
||||
"""
|
||||
A closure creation operation.
|
||||
|
|
|
@ -2544,10 +2544,22 @@ class ARTIQIRGenerator(algorithm.Visitor):
|
|||
fn = types.get_method_function(fn)
|
||||
sid = ir.Constant(fn.sid, builtins.TInt32())
|
||||
if not builtins.is_none(fn.ret):
|
||||
ret = self.append(ir.Builtin("subkernel_retrieve_return", [sid, timeout], fn.ret))
|
||||
if self.unwind_target is None:
|
||||
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:
|
||||
ret = ir.Constant(None, builtins.TNone())
|
||||
self.append(ir.Builtin("subkernel_await_finish", [sid, timeout], builtins.TNone()))
|
||||
if self.unwind_target is None:
|
||||
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
|
||||
elif types.is_builtin(typ, "subkernel_preload"):
|
||||
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},
|
||||
node.loc)
|
||||
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):
|
||||
return self.alloc_exn(node.type, *[self.visit(arg_node) for arg_node in node.args])
|
||||
elif types.is_constructor(typ):
|
||||
|
@ -2946,7 +2965,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
|
|||
format_string += ")"
|
||||
elif builtins.is_exception(value.type):
|
||||
# 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__"))
|
||||
param1 = self.append(ir.GetAttr(value, "#__param0__"))
|
||||
param2 = self.append(ir.GetAttr(value, "#__param1__"))
|
||||
|
|
|
@ -1437,6 +1437,44 @@ class LLVMIRGenerator:
|
|||
else:
|
||||
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):
|
||||
llmin = self.map(insn.operands[0])
|
||||
llmax = self.map(insn.operands[1])
|
||||
|
|
|
@ -278,8 +278,15 @@ pub mod subkernel {
|
|||
{
|
||||
let mut reader = Cursor::new(buffer);
|
||||
|
||||
let _sync = reader.read_u32()?;
|
||||
let _9 = reader.read_u8()?;
|
||||
let mut byte = 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()?;
|
||||
// ignore the remaining exceptions, stack traces etc. - unwinding from another device would be unwise anyway
|
||||
Ok(Exception {
|
||||
|
|
Loading…
Reference in New Issue