Check whether src and tgt have same param attributes
MODIFY
ir/attrs.cpp
ir/attrs.cpp
@@ -56,10 +56,33 @@ bool ParamAttrs::undefImpliesUB() const {
return ub;
}
+bool ParamAttrs::operator==(const ParamAttrs &rhs) const {
+ if (bits != rhs.bits)
+ return false;
+
+ if (has(Dereferenceable) && derefBytes != rhs.derefBytes)
+ return false;
+ if (has(ByVal) && blockSize != rhs.blockSize)
+ return false;
+ if (has(Align) && align != rhs.align)
+ return false;
+
+ return true;
+}
+
bool FnAttrs::undefImpliesUB() const {
bool ub = has(NoUndef);
assert(!ub || poisonImpliesUB());
return ub;
}
+bool FnAttrs::operator==(const FnAttrs &rhs) const {
+ if (bits != rhs.bits)
+ return false;
+
+ if (has(Dereferenceable) && getDerefBytes() != rhs.getDerefBytes())
+ return false;
+
+ return true;
+}
}

MODIFY
ir/attrs.h
ir/attrs.h
@@ -32,6 +32,9 @@ public:
bool undefImpliesUB() const;
friend std::ostream& operator<<(std::ostream &os, const ParamAttrs &attr);
+
+ bool operator==(const ParamAttrs &rhs) const;
+ bool operator!=(const ParamAttrs &rhs) const { return !(*this == rhs); };
};
@@ -60,6 +63,9 @@ public:
bool undefImpliesUB() const;
friend std::ostream& operator<<(std::ostream &os, const FnAttrs &attr);
+
+ bool operator==(const FnAttrs &rhs) const;
+ bool operator!=(const FnAttrs &rhs) const { return !(*this == rhs); };
};
}

MODIFY
ir/function.cpp
ir/function.cpp
@@ -162,6 +162,36 @@ void Function::addInput(unique_ptr<Value> &&i) {
inputs.emplace_back(move(i));
}
+bool Function::hasSameInputs(const Function &rhs) const {
+ auto litr = inputs.begin(), lend = inputs.end();
+ auto ritr = rhs.inputs.begin(), rend = rhs.inputs.end();
+
+ auto skip_constinputs = [&]() {
+ while (litr != lend && dynamic_cast<ConstantInput *>((*litr).get()))
+ litr++;
+ while (ritr != rend && dynamic_cast<ConstantInput *>((*ritr).get()))
+ ritr++;
+ };
+
+ skip_constinputs();
+
+ while (litr != lend && ritr != rend) {
+ auto *lv = dynamic_cast<Input *>((*litr).get());
+ auto *rv = dynamic_cast<Input *>((*ritr).get());
+ // TODO: &lv->getType() != &rv->getType() doesn't work because
+ // two struct types that are structurally equivalent don't compare equal
+ if (lv->getAttributes() != rv->getAttributes()) {
+ return false;
+ }
+
+ litr++;
+ ritr++;
+ skip_constinputs();
+ }
+
+ return litr == lend && ritr == rend;
+}
+
bool Function::hasReturn() const {
for (auto &i : instrs()) {
if (dynamic_cast<const Return *>(&i))

MODIFY
ir/function.h
ir/function.h
@@ -119,6 +119,7 @@ public:
util::const_strip_unique_ptr<decltype(inputs)> getInputs() const {
return inputs;
}
+ bool hasSameInputs(const Function &rhs) const;
bool hasReturn() const;
unsigned bitsPointers() const { return bits_pointers; }

ADD
tests/alive-tv/issue476.srctgt.ll
+define i32 @src(i8* dereferenceable(4) %p) {
+ ret i32 0
+}
+
+define i32 @tgt(i8* dereferenceable(8) %p) {
+ ret i32 0
+}
+
+; ERROR: Unsupported interprocedural transformation: signature mismatch between src and tgt

MODIFY
tools/transform.cpp
tools/transform.cpp
@@ -884,6 +884,12 @@ TransformVerify::TransformVerify(Transform &t, bool check_each_var) :
}
Errors TransformVerify::verify() const {
+ if (t.src.getFnAttrs() != t.tgt.getFnAttrs() ||
+ !t.src.hasSameInputs(t.tgt)) {
+ return { "Unsupported interprocedural transformation: signature mismatch "
+ "between src and tgt", false };
+ }
+
try {
t.tgt.syncDataWithSrc(t.src);
} catch (AliveException &ae) {

Check whether src and tgt have same param attributes (#507)