fix semantics of argmemonly: it was only allowing access to the args' offsets, but it's ok to access any offset
so compare against args' bids only
MODIFY
ir/instr.cpp
ir/instr.cpp
@@ -2550,16 +2550,28 @@ MemInstr::ByteAccessInfo::full(unsigned byteSize) {
return { true, true, true, byteSize };
}
-static expr ptr_only_args(State &s, const FnAttrs &attrs, const expr &p) {
- if (!attrs.has(FnAttrs::ArgMemOnly))
- return true;
+static void eq_bids(OrExpr &acc, Memory &m, const Type &t,
+ const StateValue &val, const expr &bid) {
+ if (auto agg = t.getAsAggregateType()) {
+ for (unsigned i = 0, e = agg->numElementsConst(); i != e; ++i) {
+ eq_bids(acc, m, agg->getChild(i), agg->extract(val, i), bid);
+ }
+ return;
+ }
+
+ if (t.isPtrType()) {
+ acc.add(val.non_poison && Pointer(m, val.value).getBid() == bid);
+ }
+}
+
+static expr ptr_only_args(State &s, const Pointer &p) {
+ expr bid = p.getBid();
+ auto &m = s.getMemory();
OrExpr e;
for (auto &in : s.getFn().getInputs()) {
- if (!in.getType().isPtrType())
- continue;
- auto &in_v = s[in];
- e.add(in_v.non_poison && p == in_v.value);
+ if (hasPtr(in.getType()))
+ eq_bids(e, m, in.getType(), s[in], bid);
}
return e();
}
@@ -2570,8 +2582,8 @@ static void check_can_load(State &s, const expr &p0) {
if (attrs.has(FnAttrs::NoRead))
s.addUB(p.isLocal());
-
- s.addUB(p.isLocal() || ptr_only_args(s, attrs, p0));
+ else if (attrs.has(FnAttrs::ArgMemOnly))
+ s.addUB(p.isLocal() || ptr_only_args(s, p));
}
static void check_can_store(State &s, const expr &p0) {
@@ -2583,8 +2595,8 @@ static void check_can_store(State &s, const expr &p0) {
if (attrs.has(FnAttrs::NoWrite))
s.addUB(p.isLocal());
-
- s.addUB(p.isLocal() || ptr_only_args(s, attrs, p0));
+ else if (attrs.has(FnAttrs::ArgMemOnly))
+ s.addUB(p.isLocal() || ptr_only_args(s, p));
}

fix semantics of argmemonly: it was only allowing access to the args' offsets, but it's ok to access any offset
so compare against args' bids only