fix bug create return instructions for 'alive -root-only'
MODIFY
ir/function.cpp
ir/function.cpp
@@ -98,6 +98,14 @@ void Function::addInput(unique_ptr<Input> &&i) {
inputs.emplace_back(move(i));
}
+bool Function::hasReturn() const {
+ for (auto &i : instrs()) {
+ if (dynamic_cast<const Return *>(&i))
+ return true;
+ }
+ return false;
+}
+
Function::instr_iterator::
instr_iterator(vector<BasicBlock*>::const_iterator &&BBI,
vector<BasicBlock*>::const_iterator &&BBE)

MODIFY
ir/function.h
ir/function.h
@@ -42,6 +42,8 @@ public:
}
Instr& back() { return *m_instrs.back(); }
+ bool empty() const { return m_instrs.empty(); }
+
std::unique_ptr<BasicBlock> dup(const std::string &suffix) const;
friend std::ostream& operator<<(std::ostream &os, const BasicBlock &bb);
@@ -95,6 +97,8 @@ public:
return inputs;
}
+ bool hasReturn() const;
+
auto& getBBs() { return BB_order; }
const auto& getBBs() const { return BB_order; }

MODIFY
tools/alive.cpp
tools/alive.cpp
@@ -18,6 +18,29 @@ using namespace util;
using namespace std;
+static bool add_return(Function &f) {
+ if (f.hasReturn())
+ return true;
+
+ auto &bbs = f.getBBs();
+ if (bbs.size() != 1) {
+ cerr << "-root-only only supports single BB transforms\n";
+ return false;
+ }
+
+ auto bb = bbs[0];
+ if (bb->empty()) {
+ cerr << "-root-only doesn't support empty BBs\n";
+ return false;
+ }
+
+ auto &type = get_sym_type();
+ bb->addInstr(make_unique<Return>(type, bb->back()));
+ f.setType(type);
+ return true;
+}
+
+
static void show_help() {
cerr <<
"Usage: alive2 <options> <files.opt>\n"
@@ -38,7 +61,7 @@ static void show_help() {
int main(int argc, char **argv) {
bool verbose = false;
bool show_smt_stats = false;
- bool check_each_var = true;
+ bool root_only = false;
int argc_i = 1;
for (; argc_i < argc; ++argc_i) {
@@ -47,8 +70,7 @@ int main(int argc, char **argv) {
string_view arg(argv[argc_i]);
if (arg == "-root-only")
- // FIXME: add a return instruction to each transform as needed
- check_each_var = false;
+ root_only = true;
else if (arg == "-v")
verbose = true;
else if (arg == "-smt-stats")
@@ -100,10 +122,16 @@ int main(int argc, char **argv) {
try {
for (auto &t : parse(*file_reader(argv[argc_i], PARSER_READ_AHEAD))) {
smt_init.reset();
+
+ if (root_only && (!add_return(t.src) || !add_return(t.tgt))) {
+ ++num_errors;
+ continue;
+ }
+
t.print(cout, print_opts);
cout << '\n';
- TransformVerify tv(t, check_each_var);
+ TransformVerify tv(t, !root_only);
auto types = tv.getTypings();
if (!types) {
cerr << "Doesn't type check!\n";

MODIFY
tools/alive_parser.cpp
tools/alive_parser.cpp
@@ -253,7 +253,7 @@ static Type& get_overflow_type(Type &type) {
return *st.get();
}
-static Type& get_sym_type() {
+Type& get_sym_type() {
return *sym_types.emplace_back(
make_unique<SymbolicType>("symty_" + to_string(sym_num++))).get();
}

MODIFY
tools/alive_parser.h
tools/alive_parser.h
#include <string_view>
#include <vector>
+namespace IR { class Type; }
+
namespace tools {
std::vector<Transform> parse(std::string_view buf);
+IR::Type& get_sym_type();
struct parser_initializer {
parser_initializer();

MODIFY
tools/transform.cpp
tools/transform.cpp
@@ -259,6 +259,11 @@ TransformVerify::TransformVerify(Transform &t, bool check_each_var) :
tgt_instrs.emplace(i.getName(), &i);
}
}
+
+ if (!check_each_var) {
+ assert(t.src.hasReturn());
+ assert(t.tgt.hasReturn());
+ }
}
Errors TransformVerify::verify() const {

fix bug #17: create return instructions for 'alive -root-only'