mirror of https://github.com/m-labs/artiq.git
syscall: lower nowrite to inaccessiblememonly
In the origin implementation, the `nowrite` flag literally means not writing memory at all.
Due to the usage of flags on certain functions, it results in the same issues found in artiq-zynq after optimization passes. (M-Labs/artiq-zynq#119)
A fix wrote by @dnadlinger can resolve this issue. (c1e46cc7c8
)
This commit is contained in:
parent
6db7280b09
commit
5985f7efb5
|
@ -84,14 +84,6 @@ class LLVMIRGenerator:
|
||||||
self.llobject_map = {}
|
self.llobject_map = {}
|
||||||
self.phis = []
|
self.phis = []
|
||||||
self.empty_metadata = self.llmodule.add_metadata([])
|
self.empty_metadata = self.llmodule.add_metadata([])
|
||||||
self.tbaa_tree = self.llmodule.add_metadata([
|
|
||||||
ll.MetaDataString(self.llmodule, "ARTIQ TBAA")
|
|
||||||
])
|
|
||||||
self.tbaa_nowrite_call = self.llmodule.add_metadata([
|
|
||||||
ll.MetaDataString(self.llmodule, "ref-only function call"),
|
|
||||||
self.tbaa_tree,
|
|
||||||
ll.Constant(lli64, 1)
|
|
||||||
])
|
|
||||||
self.quote_fail_msg = None
|
self.quote_fail_msg = None
|
||||||
|
|
||||||
def needs_sret(self, lltyp, may_be_large=True):
|
def needs_sret(self, lltyp, may_be_large=True):
|
||||||
|
@ -1207,6 +1199,8 @@ class LLVMIRGenerator:
|
||||||
llfun.args[i].add_attribute('byval')
|
llfun.args[i].add_attribute('byval')
|
||||||
if 'nounwind' in insn.target_function().type.flags:
|
if 'nounwind' in insn.target_function().type.flags:
|
||||||
llfun.attributes.add('nounwind')
|
llfun.attributes.add('nounwind')
|
||||||
|
if 'nowrite' in insn.target_function().type.flags:
|
||||||
|
llfun.attributes.add('inaccessiblememonly')
|
||||||
|
|
||||||
return llfun, list(llargs)
|
return llfun, list(llargs)
|
||||||
|
|
||||||
|
@ -1364,11 +1358,6 @@ class LLVMIRGenerator:
|
||||||
# {} elsewhere.
|
# {} elsewhere.
|
||||||
llresult = ll.Constant(llunit, [])
|
llresult = ll.Constant(llunit, [])
|
||||||
|
|
||||||
# Never add TBAA nowrite metadata to a functon with sret!
|
|
||||||
# This leads to miscompilations.
|
|
||||||
if types.is_external_function(functiontyp) and 'nowrite' in functiontyp.flags:
|
|
||||||
llcall.set_metadata('tbaa', self.tbaa_nowrite_call)
|
|
||||||
|
|
||||||
return llresult
|
return llresult
|
||||||
|
|
||||||
def process_Invoke(self, insn):
|
def process_Invoke(self, insn):
|
||||||
|
|
|
@ -304,7 +304,7 @@ class TExternalFunction(TFunction):
|
||||||
mangling rules).
|
mangling rules).
|
||||||
:ivar flags: (set of str) function flags.
|
:ivar flags: (set of str) function flags.
|
||||||
Flag ``nounwind`` means the function never raises an exception.
|
Flag ``nounwind`` means the function never raises an exception.
|
||||||
Flag ``nowrite`` means the function never writes any memory
|
Flag ``nowrite`` means the function never accesses any memory
|
||||||
that the ARTIQ Python code can observe.
|
that the ARTIQ Python code can observe.
|
||||||
:ivar broadcast_across_arrays: (bool)
|
:ivar broadcast_across_arrays: (bool)
|
||||||
If True, the function is transparently applied element-wise when called
|
If True, the function is transparently applied element-wise when called
|
||||||
|
|
|
@ -2,11 +2,11 @@ from artiq.language.core import *
|
||||||
from artiq.language.types import *
|
from artiq.language.types import *
|
||||||
|
|
||||||
|
|
||||||
@syscall(flags={"nounwind", "nowrite"})
|
@syscall(flags={"nounwind"})
|
||||||
def cache_get(key: TStr) -> TList(TInt32):
|
def cache_get(key: TStr) -> TList(TInt32):
|
||||||
raise NotImplementedError("syscall not simulated")
|
raise NotImplementedError("syscall not simulated")
|
||||||
|
|
||||||
@syscall(flags={"nowrite"})
|
@syscall
|
||||||
def cache_put(key: TStr, value: TList(TInt32)) -> TNone:
|
def cache_put(key: TStr, value: TList(TInt32)) -> TNone:
|
||||||
raise NotImplementedError("syscall not simulated")
|
raise NotImplementedError("syscall not simulated")
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
from artiq.language.core import *
|
from artiq.language.core import *
|
||||||
from artiq.language.types import *
|
from artiq.language.types import *
|
||||||
|
|
||||||
# CHECK: call void @foo\(\)(, !dbg !\d+)?, !tbaa !\d+
|
# CHECK: call void @foo\(\)(, !dbg !\d+)?
|
||||||
|
|
||||||
# CHECK-L: ; Function Attrs: nounwind
|
# CHECK-L: ; Function Attrs: inaccessiblememonly nounwind
|
||||||
# CHECK-NEXT-L: declare void @foo()
|
# CHECK-NEXT-L: declare void @foo()
|
||||||
|
|
||||||
@syscall(flags={"nounwind", "nowrite"})
|
@syscall(flags={"nounwind", "nowrite"})
|
||||||
|
|
Loading…
Reference in New Issue