diff --git a/artiq/compiler/builtins.py b/artiq/compiler/builtins.py index 2cdb09383..efc0b72fe 100644 --- a/artiq/compiler/builtins.py +++ b/artiq/compiler/builtins.py @@ -177,6 +177,9 @@ def fn_mu_to_seconds(): def fn_seconds_to_mu(): return types.TBuiltinFunction("seconds_to_mu") +def fn_rtio_log(): + return types.TBuiltinFunction("rtio_log") + # Accessors def is_none(typ): diff --git a/artiq/compiler/embedding.py b/artiq/compiler/embedding.py index 571023349..7cd53eaaa 100644 --- a/artiq/compiler/embedding.py +++ b/artiq/compiler/embedding.py @@ -18,6 +18,9 @@ from . import types, builtins, asttyped, prelude from .transforms import ASTTypedRewriter, Inferencer, IntMonomorphizer +def coredevice_print(x): print(x) + + class ObjectMap: def __init__(self): self.current_key = 0 @@ -264,7 +267,9 @@ class StitchingASTTypedRewriter(ASTTypedRewriter): loc=node.loc) else: # Try to find this value in the host environment and quote it. - if node.id in self.host_environment: + if node.id == "print": + return self.quote(coredevice_print, node.loc) + elif node.id in self.host_environment: return self.quote(self.host_environment[node.id], node.loc) else: names = set() @@ -450,6 +455,7 @@ class Stitcher: self.typedtree = [] self.inject_at = 0 self.prelude = prelude.globals() + self.prelude.pop("print") self.globals = {} self.functions = {} diff --git a/artiq/compiler/prelude.py b/artiq/compiler/prelude.py index b45686204..6f6e06e42 100644 --- a/artiq/compiler/prelude.py +++ b/artiq/compiler/prelude.py @@ -43,4 +43,7 @@ def globals(): "at_mu": builtins.fn_at_mu(), "mu_to_seconds": builtins.fn_mu_to_seconds(), "seconds_to_mu": builtins.fn_seconds_to_mu(), + + # ARTIQ utility functions + "rtio_log": builtins.fn_rtio_log(), } diff --git a/artiq/compiler/targets.py b/artiq/compiler/targets.py index d6b3aa8c2..5ee8213ed 100644 --- a/artiq/compiler/targets.py +++ b/artiq/compiler/targets.py @@ -61,7 +61,6 @@ class Target: triple = "unknown" data_layout = "" features = [] - print_function = "printf" def __init__(self): @@ -176,4 +175,3 @@ class OR1KTarget(Target): triple = "or1k-linux" data_layout = "E-m:e-p:32:32-i64:32-f64:32-v64:32-v128:32-a:0:32-n32" features = ["mul", "div", "ffl1", "cmov", "addc"] - print_function = "lognonl" diff --git a/artiq/compiler/transforms/artiq_ir_generator.py b/artiq/compiler/transforms/artiq_ir_generator.py index 49826b11c..74040ca54 100644 --- a/artiq/compiler/transforms/artiq_ir_generator.py +++ b/artiq/compiler/transforms/artiq_ir_generator.py @@ -1608,9 +1608,10 @@ class ARTIQIRGenerator(algorithm.Visitor): return self.append(ir.Builtin("round", [arg], node.type)) else: assert False - elif types.is_builtin(typ, "print"): + elif types.is_builtin(typ, "print") or types.is_builtin(typ, "rtio_log"): self.polymorphic_print([self.visit(arg) for arg in node.args], - separator=" ", suffix="\n") + separator=" ", suffix="\n", + as_rtio=types.is_builtin(typ, "rtio_log")) return ir.Constant(None, builtins.TNone()) elif types.is_builtin(typ, "now"): if len(node.args) == 0 and len(node.keywords) == 0: @@ -1822,14 +1823,21 @@ class ARTIQIRGenerator(algorithm.Visitor): tail = self.current_block = self.add_block() self.append(ir.BranchIf(cond, tail, if_failed), block=head) - def polymorphic_print(self, values, separator, suffix="", as_repr=False): + def polymorphic_print(self, values, separator, suffix="", as_repr=False, as_rtio=False): + def printf(format_string, *args): + format = ir.Constant(format_string, builtins.TStr()) + if as_rtio: + now_mu = self.append(ir.Builtin("now_mu", [], builtins.TInt64())) + self.append(ir.Builtin("rtio_log", [now_mu, format, *args], builtins.TNone())) + else: + self.append(ir.Builtin("printf", [format, *args], builtins.TNone())) + format_string = "" args = [] def flush(): nonlocal format_string, args if format_string != "": - format_arg = [ir.Constant(format_string, builtins.TStr())] - self.append(ir.Builtin("printf", format_arg + args, builtins.TNone())) + printf(format_string, *args) format_string = "" args = [] @@ -1841,7 +1849,7 @@ class ARTIQIRGenerator(algorithm.Visitor): format_string += "("; flush() self.polymorphic_print([self.append(ir.GetAttr(value, index)) for index in range(len(value.type.elts))], - separator=", ", as_repr=True) + separator=", ", as_repr=True, as_rtio=as_rtio) if len(value.type.elts) == 1: format_string += ",)" else: @@ -1882,13 +1890,12 @@ class ARTIQIRGenerator(algorithm.Visitor): last = self.append(ir.Arith(ast.Sub(loc=None), length, ir.Constant(1, length.type))) def body_gen(index): elt = self.iterable_get(value, index) - self.polymorphic_print([elt], separator="", as_repr=True) + self.polymorphic_print([elt], separator="", as_repr=True, as_rtio=as_rtio) is_last = self.append(ir.Compare(ast.Lt(loc=None), index, last)) head = self.current_block if_last = self.current_block = self.add_block() - self.append(ir.Builtin("printf", - [ir.Constant(", ", builtins.TStr())], builtins.TNone())) + printf(", ") tail = self.current_block = self.add_block() if_last.append(ir.Branch(tail)) @@ -1907,7 +1914,7 @@ class ARTIQIRGenerator(algorithm.Visitor): start = self.append(ir.GetAttr(value, "start")) stop = self.append(ir.GetAttr(value, "stop")) step = self.append(ir.GetAttr(value, "step")) - self.polymorphic_print([start, stop, step], separator=", ") + self.polymorphic_print([start, stop, step], separator=", ", as_rtio=as_rtio) format_string += ")" elif builtins.is_exception(value.type): diff --git a/artiq/compiler/transforms/inferencer.py b/artiq/compiler/transforms/inferencer.py index 8432f9cae..fd226a7c5 100644 --- a/artiq/compiler/transforms/inferencer.py +++ b/artiq/compiler/transforms/inferencer.py @@ -753,7 +753,7 @@ class Inferencer(algorithm.Visitor): node.loc, None) else: diagnose(valid_forms()) - elif types.is_builtin(typ, "print"): + elif types.is_builtin(typ, "print") or types.is_builtin(typ, "rtio_log"): valid_forms = lambda: [ valid_form("print(args...) -> None"), ] diff --git a/artiq/compiler/transforms/llvm_ir_generator.py b/artiq/compiler/transforms/llvm_ir_generator.py index eb8c1e1f1..37ad5add4 100644 --- a/artiq/compiler/transforms/llvm_ir_generator.py +++ b/artiq/compiler/transforms/llvm_ir_generator.py @@ -358,8 +358,10 @@ class LLVMIRGenerator: llty = ll.FunctionType(llptr, []) elif name == "llvm.stackrestore": llty = ll.FunctionType(llvoid, [llptr]) - elif name == self.target.print_function: + elif name == "printf": llty = ll.FunctionType(llvoid, [llptr], var_arg=True) + elif name == "rtio_log": + llty = ll.FunctionType(llvoid, [lli64, llptr], var_arg=True) elif name == "__artiq_personality": llty = ll.FunctionType(lli32, [], var_arg=True) elif name == "__artiq_raise": @@ -892,10 +894,10 @@ class LLVMIRGenerator: elif insn.op == "len": lst, = insn.operands return self.llbuilder.extract_value(self.map(lst), 0) - elif insn.op == "printf": + elif insn.op in ("printf", "rtio_log"): # We only get integers, floats, pointers and strings here. llargs = map(self.map, insn.operands) - return self.llbuilder.call(self.llbuiltin(self.target.print_function), llargs, + return self.llbuilder.call(self.llbuiltin(insn.op), llargs, name=insn.name) elif insn.op == "exncast": # This is an identity cast at LLVM IR level. diff --git a/artiq/runtime/ksupport.c b/artiq/runtime/ksupport.c index eb2c4fa1c..c8a0f24db 100644 --- a/artiq/runtime/ksupport.c +++ b/artiq/runtime/ksupport.c @@ -102,8 +102,7 @@ static const struct symbol runtime_exports[] = { {"watchdog_set", &watchdog_set}, {"watchdog_clear", &watchdog_clear}, - {"core_log", &core_log}, - {"rtio_log", &rtio_log}, + {"printf", &core_log}, {"send_rpc", &send_rpc}, {"recv_rpc", &recv_rpc},