Skip to content

Commit 6f5332f

Browse files
author
whitequark
committedMar 28, 2016
compiler: allow flagging syscalls, providing information to optimizer.
This also fixes a crash in test_cache introduced in 1d8b0d4.
1 parent 049bd11 commit 6f5332f

File tree

9 files changed

+47
-33
lines changed

9 files changed

+47
-33
lines changed
 

‎artiq/compiler/embedding.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -693,7 +693,7 @@ def proxy_diagnostic(diag):
693693
# Let the rest of the program decide.
694694
return types.TVar()
695695

696-
def _quote_foreign_function(self, function, loc, syscall):
696+
def _quote_foreign_function(self, function, loc, syscall, flags):
697697
signature = inspect.signature(function)
698698

699699
arg_types = OrderedDict()
@@ -742,7 +742,7 @@ def _quote_foreign_function(self, function, loc, syscall):
742742
service=self.object_map.store(function))
743743
else:
744744
function_type = types.TCFunction(arg_types, ret_type,
745-
name=syscall)
745+
name=syscall, flags=flags)
746746

747747
self.functions[function] = function_type
748748

@@ -779,7 +779,8 @@ def _quote_function(self, function, loc):
779779
# Insert a storage-less global whose type instructs the compiler
780780
# to perform a system call instead of a regular call.
781781
self._quote_foreign_function(function, loc,
782-
syscall=function.artiq_embedded.syscall)
782+
syscall=function.artiq_embedded.syscall,
783+
flags=function.artiq_embedded.flags)
783784
elif function.artiq_embedded.forbidden is not None:
784785
diag = diagnostic.Diagnostic("fatal",
785786
"this function cannot be called as an RPC", {},
@@ -791,7 +792,7 @@ def _quote_function(self, function, loc):
791792
else:
792793
# Insert a storage-less global whose type instructs the compiler
793794
# to perform an RPC instead of a regular call.
794-
self._quote_foreign_function(function, loc, syscall=None)
795+
self._quote_foreign_function(function, loc, syscall=None, flags=None)
795796

796797
function_type = self.functions[function]
797798
if types.is_rpc_function(function_type):

‎artiq/compiler/transforms/llvm_ir_generator.py

+12-7
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,8 @@ def __init__(self, engine, module_name, target, function_map, object_map, type_m
184184
self.tbaa_tree = self.llmodule.add_metadata([
185185
ll.MetaDataString(self.llmodule, "ARTIQ TBAA")
186186
])
187-
self.tbaa_noalias_call = self.llmodule.add_metadata([
188-
ll.MetaDataString(self.llmodule, "non-aliasing function call"),
187+
self.tbaa_nowrite_call = self.llmodule.add_metadata([
188+
ll.MetaDataString(self.llmodule, "ref-only function call"),
189189
self.tbaa_tree,
190190
ll.Constant(lli64, 1)
191191
])
@@ -401,6 +401,9 @@ def llbuiltin(self, name):
401401
llglobal = ll.Function(self.llmodule, llty, name)
402402
if name in ("__artiq_raise", "__artiq_reraise", "llvm.trap"):
403403
llglobal.attributes.add("noreturn")
404+
if name in ("rtio_log", "send_rpc", "watchdog_set", "watchdog_clear",
405+
self.target.print_function):
406+
llglobal.attributes.add("nounwind")
404407
else:
405408
llglobal = ll.GlobalVariable(self.llmodule, llty, name)
406409

@@ -1117,6 +1120,8 @@ def _prepare_ffi_call(self, insn):
11171120
byvals = [i + 1 for i in byvals]
11181121
for i in byvals:
11191122
llfun.args[i].add_attribute('byval')
1123+
if 'nounwind' in insn.target_function().type.flags:
1124+
llfun.attributes.add('nounwind')
11201125

11211126
return llfun, list(llargs)
11221127

@@ -1282,14 +1287,14 @@ def process_Call(self, insn):
12821287
else:
12831288
llcall = llresult = self.llbuilder.call(llfun, llargs, name=insn.name)
12841289

1290+
# Never add TBAA nowrite metadata to a functon with sret!
1291+
# This leads to miscompilations.
1292+
if types.is_c_function(functiontyp) and 'nowrite' in functiontyp.flags:
1293+
llcall.metadata['tbaa'] = self.tbaa_nowrite_call
1294+
12851295
if insn.is_cold:
12861296
llcall.cconv = 'coldcc'
12871297

1288-
if types.is_c_function(functiontyp):
1289-
# All our global state is confined to our compilation unit,
1290-
# so by definition no FFI call can mutate it.
1291-
llcall.metadata['tbaa'] = self.tbaa_noalias_call
1292-
12931298
return llresult
12941299

12951300
def process_Invoke(self, insn):

‎artiq/compiler/types.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -342,14 +342,21 @@ class TCFunction(TFunction):
342342
A function type of a runtime-provided C function.
343343
344344
:ivar name: (str) C function name
345+
:ivar flags: (set of str) C function flags.
346+
Flag ``nounwind`` means the function never raises an exception.
347+
Flag ``nowrite`` means the function never writes any memory
348+
that the ARTIQ Python code can observe.
345349
"""
346350

347351
attributes = OrderedDict()
348352

349-
def __init__(self, args, ret, name):
353+
def __init__(self, args, ret, name, flags={}):
354+
for flag in flags:
355+
assert flag in {'nounwind', 'nowrite'}
350356
super().__init__(args, OrderedDict(), ret)
351357
self.name = name
352358
self.delay = TFixedDelay(iodelay.Const(0))
359+
self.flags = flags
353360

354361
def unify(self, other):
355362
if isinstance(other, TCFunction) and \

‎artiq/coredevice/cache.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
from artiq.language.types import *
33

44

5-
@syscall
5+
@syscall("cache_get", flags={"nounwind", "nowrite"})
66
def cache_get(key: TStr) -> TList(TInt32):
77
raise NotImplementedError("syscall not simulated")
88

9-
@syscall
9+
@syscall("cache_put", flags={"nowrite"})
1010
def cache_put(key: TStr, value: TList(TInt32)) -> TNone:
1111
raise NotImplementedError("syscall not simulated")
1212

‎artiq/coredevice/core.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def __str__(self):
3737
return "\n" + _render_diagnostic(self.diagnostic, colored=colors_supported)
3838

3939

40-
@syscall
40+
@syscall("rtio_get_counter", flags={"nounwind", "nowrite"})
4141
def rtio_get_counter() -> TInt64:
4242
raise NotImplementedError("syscall not simulated")
4343

‎artiq/coredevice/dds.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,20 @@
1010
PHASE_MODE_TRACKING = 2
1111

1212

13-
@syscall
13+
@syscall("dds_init", flags={"nowrite"})
1414
def dds_init(time_mu: TInt64, bus_channel: TInt32, channel: TInt32) -> TNone:
1515
raise NotImplementedError("syscall not simulated")
1616

17-
@syscall
17+
@syscall("dds_set", flags={"nowrite"})
1818
def dds_set(time_mu: TInt64, bus_channel: TInt32, channel: TInt32, ftw: TInt32,
1919
pow: TInt32, phase_mode: TInt32, amplitude: TInt32) -> TNone:
2020
raise NotImplementedError("syscall not simulated")
2121

22-
@syscall
22+
@syscall("dds_batch_enter", flags={"nowrite"})
2323
def dds_batch_enter(time_mu: TInt64) -> TNone:
2424
raise NotImplementedError("syscall not simulated")
2525

26-
@syscall
26+
@syscall("dds_batch_exit", flags={"nowrite"})
2727
def dds_batch_exit() -> TNone:
2828
raise NotImplementedError("syscall not simulated")
2929

‎artiq/coredevice/i2c.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,27 @@
33
from artiq.coredevice.exceptions import I2CError
44

55

6-
@syscall
6+
@syscall("i2c_init", flags={"nowrite"})
77
def i2c_init(busno: TInt32) -> TNone:
88
raise NotImplementedError("syscall not simulated")
99

1010

11-
@syscall
11+
@syscall("i2c_start", flags={"nounwind", "nowrite"})
1212
def i2c_start(busno: TInt32) -> TNone:
1313
raise NotImplementedError("syscall not simulated")
1414

1515

16-
@syscall
16+
@syscall("i2c_stop", flags={"nounwind", "nowrite"})
1717
def i2c_stop(busno: TInt32) -> TNone:
1818
raise NotImplementedError("syscall not simulated")
1919

2020

21-
@syscall
21+
@syscall("i2c_write", flags={"nounwind", "nowrite"})
2222
def i2c_write(busno: TInt32, b: TInt32) -> TBool:
2323
raise NotImplementedError("syscall not simulated")
2424

2525

26-
@syscall
26+
@syscall("i2c_read", flags={"nounwind", "nowrite"})
2727
def i2c_read(busno: TInt32, ack: TBool) -> TInt32:
2828
raise NotImplementedError("syscall not simulated")
2929

‎artiq/coredevice/rtio.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@
22
from artiq.language.types import TInt64, TInt32, TNone
33

44

5-
@syscall
5+
@syscall("rtio_output", flags={"nowrite"})
66
def rtio_output(time_mu: TInt64, channel: TInt32, addr: TInt32, data: TInt32
77
) -> TNone:
88
raise NotImplementedError("syscall not simulated")
99

1010

11-
@syscall
11+
@syscall("rtio_input_timestamp", flags={"nowrite"})
1212
def rtio_input_timestamp(timeout_mu: TInt64, channel: TInt32) -> TInt64:
1313
raise NotImplementedError("syscall not simulated")
1414

1515

16-
@syscall
16+
@syscall("rtio_input_data", flags={"nowrite"})
1717
def rtio_input_data(channel: TInt32) -> TInt32:
1818
raise NotImplementedError("syscall not simulated")

‎artiq/language/core.py

+7-6
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ def round(value, width=32):
163163

164164

165165
_ARTIQEmbeddedInfo = namedtuple("_ARTIQEmbeddedInfo",
166-
"core_name function syscall forbidden")
166+
"core_name function syscall forbidden flags")
167167

168168
def kernel(arg):
169169
"""
@@ -192,7 +192,7 @@ def run_on_core(self, *k_args, **k_kwargs):
192192
return getattr(self, arg).run(run_on_core, ((self,) + k_args), k_kwargs)
193193
run_on_core.artiq_embedded = _ARTIQEmbeddedInfo(
194194
core_name=arg, function=function, syscall=None,
195-
forbidden=False)
195+
forbidden=False, flags={})
196196
return run_on_core
197197
return inner_decorator
198198
else:
@@ -210,10 +210,10 @@ def portable(function):
210210
"""
211211
function.artiq_embedded = \
212212
_ARTIQEmbeddedInfo(core_name=None, function=function, syscall=None,
213-
forbidden=False)
213+
forbidden=False, flags={})
214214
return function
215215

216-
def syscall(arg):
216+
def syscall(arg, flags={}):
217217
"""
218218
This decorator marks a function as a system call. When executed on a core
219219
device, a C function with the provided name (or the same name as
@@ -228,7 +228,8 @@ def syscall(arg):
228228
def inner_decorator(function):
229229
function.artiq_embedded = \
230230
_ARTIQEmbeddedInfo(core_name=None, function=None,
231-
syscall=function.__name__, forbidden=False)
231+
syscall=function.__name__, forbidden=False,
232+
flags=flags)
232233
return function
233234
return inner_decorator
234235
else:
@@ -241,7 +242,7 @@ def host_only(function):
241242
"""
242243
function.artiq_embedded = \
243244
_ARTIQEmbeddedInfo(core_name=None, function=None, syscall=None,
244-
forbidden=True)
245+
forbidden=True, flags={})
245246
return function
246247

247248

0 commit comments

Comments
 (0)
Please sign in to comment.