add dereferenceable constraint when encoding byval attr
MODIFY
ir/attrs.cpp
ir/attrs.cpp
@@ -64,6 +64,16 @@ bool ParamAttrs::undefImpliesUB() const {
return ub;
}
+uint64_t ParamAttrs::getDerefBytes() const {
+ uint64_t bytes = 0;
+ if (has(ParamAttrs::Dereferenceable))
+ bytes = derefBytes;
+ // byval copies bytes; the ptr needs to be dereferenceable
+ if (has(ParamAttrs::ByVal))
+ bytes = max(bytes, (uint64_t)blockSize);
+ return bytes;
+}
+
bool FnAttrs::poisonImpliesUB() const {
return has(NonNull) || has(Dereferenceable) || has(NoUndef) || has(Align) ||
has(NNaN);

MODIFY
ir/attrs.h
ir/attrs.h
@@ -32,6 +32,8 @@ public:
// Returns true if it is UB for the argument to be (partially) undef.
bool undefImpliesUB() const;
+ uint64_t getDerefBytes() const;
+
friend std::ostream& operator<<(std::ostream &os, const ParamAttrs &attr);
};

MODIFY
ir/instr.cpp
ir/instr.cpp
@@ -1689,8 +1689,10 @@ static void unpack_inputs(State &s, Value &argv, Type &ty,
if (ty.isPtrType()) {
Pointer p(s.getMemory(), move(value.value));
p.stripAttrs();
- if (argflag.has(ParamAttrs::Dereferenceable))
- s.addUB(p.isDereferenceable(argflag.derefBytes, argflag.align, false));
+ if (argflag.has(ParamAttrs::Dereferenceable) ||
+ argflag.has(ParamAttrs::ByVal))
+ s.addUB(
+ p.isDereferenceable(argflag.getDerefBytes(), argflag.align, false));
else if (argflag.has(ParamAttrs::Align))
s.addUB(p.isAligned(argflag.align));

MODIFY
ir/value.cpp
ir/value.cpp
@@ -221,9 +221,10 @@ StateValue Input::mkInput(State &s, const Type &ty, unsigned child) const {
if (hasAttribute(ParamAttrs::NonNull))
s.addUB(Pointer(s.getMemory(), val).isNonZero());
- if (hasAttribute(ParamAttrs::Dereferenceable))
+ if (hasAttribute(ParamAttrs::Dereferenceable) ||
+ hasAttribute(ParamAttrs::ByVal))
s.addUB(Pointer(s.getMemory(), val)
- .isDereferenceable(attrs.derefBytes, attrs.align, false));
+ .isDereferenceable(attrs.getDerefBytes(), attrs.align, false));
else if (hasAttribute(ParamAttrs::Align))
s.addUB(Pointer(s.getMemory(), val).isAligned(attrs.align));

ADD
tests/alive-tv/attrs/byval-dereferenceable.srctgt.ll
+define void @src(i8* %p) {
+ call void @f(i8* %p)
+ ret void
+}
+
+define void @tgt(i8* %p) {
+ call void @f(i8* dereferenceable(1) %p)
+ ret void
+}
+
+declare void @f(i8* byval(i8))

ADD
tests/alive-tv/attrs/byval-dereferenceable2.srctgt.ll
+define void @src(i8* %p) {
+ call void @f(i8* %p)
+ ret void
+}
+
+define void @tgt(i8* %p) {
+ call void @f(i8* dereferenceable(2) %p)
+ ret void
+}
+
+declare void @f(i8* byval(i8))
+
+; ERROR: Source is more defined than target

add dereferenceable constraint when encoding byval attr (#648)