Check global vars' sizes & constness in src and tgt
MODIFY
ir/function.cpp
ir/function.cpp
@@ -88,6 +88,16 @@ void Function::addConstant(unique_ptr<Value> &&c) {
constants.emplace_back(move(c));
}
+vector<GlobalVariable *> Function::getGlobalVars() const {
+ vector<GlobalVariable *> gvs;
+ for (auto I = constants.begin(), E = constants.end(); I != E; ++I) {
+ const unique_ptr<Value> &c = *I;
+ if (auto *gv = dynamic_cast<GlobalVariable *>(c.get()))
+ gvs.push_back(gv);
+ }
+ return gvs;
+}
+
void Function::addPredicate(unique_ptr<Predicate> &&p) {
predicates.emplace_back(move(p));
}

MODIFY
ir/function.h
ir/function.h
@@ -86,6 +86,8 @@ public:
return constants;
}
+ std::vector<GlobalVariable *> getGlobalVars() const;
+
void addPredicate(std::unique_ptr<Predicate> &&p);
void addUndef(std::unique_ptr<UndefValue> &&c);

MODIFY
ir/value.h
ir/value.h
@@ -99,6 +99,8 @@ public:
Value *initval, bool isconst) :
Value(type, std::move(name)), allocsize(allocsize), align(align),
initval(initval), isconst(isconst) {}
+ int size() const { return allocsize; }
+ int isConst() const { return isconst; }
void print(std::ostream &os) const override;
StateValue toSMT(State &s) const override;
};

ADD
tests/alive-tv/glbconstchk.src.ll
+@g = global i32 0
+
+define i32 @f() {
+ %v = load i32, i32* @g
+ ret i32 %v
+}
+
+; ERROR: Unsupported interprocedural transformation: global variable @g is const in target but not in source

ADD
tests/alive-tv/glbconstchk.tgt.ll
+@g = constant i32 0
+
+define i32 @f() {
+ %v = load i32, i32* @g
+ ret i32 %v
+}

ADD
tests/alive-tv/glbconstchk2.src.ll
+@g = constant i32 0
+
+define i32 @f() {
+ %v = load i32, i32* @g
+ ret i32 %v
+}
+
+; ERROR: Transformation is incorrect because global variable @g is const in source but not in target

ADD
tests/alive-tv/glbconstchk2.tgt.ll
+@g = global i32 0
+
+define i32 @f() {
+ %v = load i32, i32* @g
+ ret i32 %v
+}

ADD
tests/alive-tv/glbsizechk.src.ll
+@g = global i32 0
+
+define i32 @f() {
+ %v = load i32, i32* @g
+ ret i32 %v
+}
+
+; ERROR: Unsupported interprocedural transformation: global variable @g has different size in source and target (4 vs 1 bytes)

ADD
tests/alive-tv/glbsizechk.tgt.ll
+@g = global i8 0
+
+define i32 @f() {
+ %v = load i8, i8* @g
+ %w = zext i8 %v to i32
+ ret i32 %w
+}

MODIFY
tools/transform.cpp
tools/transform.cpp
@@ -301,11 +301,46 @@ TransformVerify::TransformVerify(Transform &t, bool check_each_var) :
tgt_instrs.emplace(i.getName(), &i);
}
}
+}
+Errors TransformVerify::verify() const {
+ try {
t.tgt.syncDataWithSrc(t.src);
+ } catch (AliveException &ae) {
+ return Errors(move(ae));
+ }
+
+ // Check sizes of global variables
+ auto globals_tgt = t.tgt.getGlobalVars();
+ auto globals_src = t.src.getGlobalVars();
+ for (auto GVS : globals_src) {
+ auto I = find_if(globals_tgt.begin(), globals_tgt.end(),
+ [GVS](auto *GV) -> bool { return GVS->getName() == GV->getName(); });
+ if (I == globals_tgt.end())
+ continue;
+
+ auto GVT = *I;
+ if (GVS->size() != GVT->size()) {
+ stringstream ss;
+ ss << "Unsupported interprocedural transformation: global variable "
+ << GVS->getName() << " has different size in source and target ("
+ << GVS->size() << " vs " << GVT->size()
+ << " bytes)";
+ return { ss.str(), false };
+ } else if (GVS->isConst() && !GVT->isConst()) {
+ stringstream ss;
+ ss << "Transformation is incorrect because global variable "
+ << GVS->getName() << " is const in source but not in target";
+ return { ss.str(), true };
+ } else if (!GVS->isConst() && GVT->isConst()) {
+ stringstream ss;
+ ss << "Unsupported interprocedural transformation: global variable "
+ << GVS->getName() << " is const in target but not in source";
+ return { ss.str(), false };
+ }
+
}
-Errors TransformVerify::verify() const {
State::resetGlobals();
State src_state(t.src, true), tgt_state(t.tgt, false);

Check global vars' sizes & constness in src and tgt (#155)