TV: checkpoint work
MODIFY
.gitignore
.gitignore
.vs
*.pyc
+CMakeSettings.json

MODIFY
ir/function.cpp
ir/function.cpp
@@ -119,7 +119,7 @@ void Function::print(ostream &os, bool print_header) const {
}
if (print_header) {
- os << "declare @" << name << '(';
+ os << "declare " << getType() << " @" << name << '(';
bool first = true;
for (auto &input : getInputs()) {
if (!first)

MODIFY
ir/instr.cpp
ir/instr.cpp
@@ -12,8 +12,6 @@ using namespace std;
namespace IR {
-VoidType Instr::voidTy("void");
-
expr Instr::eqType(const Instr &i) const {
return getType() == i.getType();
}

MODIFY
ir/instr.h
ir/instr.h
@@ -12,7 +12,6 @@ class Function;
class Instr : public Value {
protected:
- static VoidType voidTy;
Instr(Type &type, std::string &&name) : Value(type, std::move(name)) {}
public:
@@ -129,7 +128,7 @@ public:
class Unreachable final : public Instr {
public:
- Unreachable() : Instr(Instr::voidTy, "") {}
+ Unreachable() : Instr(Type::voidTy, "") {}
void print(std::ostream &os) const override;
StateValue toSMT(State &s) const override;

MODIFY
ir/type.cpp
ir/type.cpp
@@ -16,6 +16,8 @@ static constexpr unsigned var_bw_bits = 8;
namespace IR {
+VoidType Type::voidTy("void");
+
expr Type::var(const char *var, unsigned bits) const {
auto str = name + '_' + var;
return expr::mkVar(str.c_str(), bits);
@@ -79,6 +81,11 @@ expr Type::enforceIntOrPtrOrVectorType() const {
return false;
}
+ostream& operator<<(ostream &os, const Type &t) {
+ t.print(os);
+ return os;
+}
+
string Type::toString() const {
stringstream s;
print(s);

MODIFY
ir/type.h
ir/type.h
@@ -12,6 +12,8 @@ namespace smt { class Model; }
namespace IR {
+class VoidType;
+
class Type {
protected:
std::string name;
@@ -37,8 +39,11 @@ public:
virtual smt::expr enforceIntOrPtrOrVectorType() const;
virtual void print(std::ostream &os) const = 0;
+ friend std::ostream& operator<<(std::ostream &os, const Type &t);
std::string toString() const;
+ static VoidType voidTy;
+
virtual ~Type();
};

MODIFY
tools/alive_parser.cpp
tools/alive_parser.cpp
#include "ir/value.h"
#include "tools/alive_lexer.h"
#include "util/compiler.h"
+#include <array>
#include <cassert>
#include <memory>
#include <unordered_map>
@@ -32,7 +33,7 @@ static void error(const char *s, token t) {
throw ParseException(string(s) + "; got: " + token_name[t], yylineno);
}
-static vector<unique_ptr<IntType>> int_types;
+static array<unique_ptr<IntType>, 65> int_types;
static unordered_map<string, Value*> identifiers;
static Function *fn;
@@ -570,15 +571,15 @@ vector<Transform> parse(string_view buf) {
parser_initializer::parser_initializer() {
- int_types.emplace_back(nullptr);
+ int_types[0] = nullptr;
for (unsigned i = 1; i <= 64; ++i) {
- int_types.emplace_back(make_unique<IntType>("i" + to_string(i), i));
+ int_types[i] = make_unique<IntType>("i" + to_string(i), i);
}
}
parser_initializer::~parser_initializer() {
- int_types.clear();
+ for_each(int_types.begin(), int_types.end(), [](auto &e) { e.reset(); });
sym_types.clear();
}

MODIFY
tv/tv.cpp
tv/tv.cpp
#include "llvm/IR/Function.h"
#include "llvm/Pass.h"
#include "llvm/Support/raw_ostream.h"
+#include <array>
+#include <iostream>
+#include <optional>
+#include <string>
+#include <unordered_map>
using namespace IR;
using namespace tools;
using namespace util;
using namespace std;
-using namespace llvm;
+using llvm::cast, llvm::errs;
namespace {
-struct TVPass : public FunctionPass {
+string_view s(llvm::StringRef str) {
+ return { str.data(), str.size() };
+}
+
+smt::smt_initializer smt_init;
+array<unique_ptr<IntType>, 65> int_types;
+unordered_map<string, Function> fns;
+unordered_map<const llvm::Value*, Value*> identifiers;
+
+struct alive_init {
+ alive_init() {
+ int_types[0] = nullptr;
+
+ for (unsigned i = 1; i <= 64; ++i) {
+ int_types[i] = make_unique<IntType>("i" + to_string(i), i);
+ }
+ }
+} alive_init;
+
+
+Type* llvm_type2alive(const llvm::Type *ty) {
+ switch (ty->getTypeID()) {
+ case llvm::Type::VoidTyID:
+ return &Type::voidTy;
+ case llvm::Type::IntegerTyID: {
+ auto bits = cast<llvm::IntegerType>(ty)->getBitWidth();
+ return bits <= 64 ? int_types[bits].get() : nullptr;
+ }
+ default:
+ errs() << "Unsupported type: " << *ty << '\n';
+ return nullptr;
+ }
+}
+
+
+unique_ptr<Instr> llvm_instr2alive(const llvm::Instruction &i) {
+ switch (i.getOpcode()) {
+ case llvm::Instruction::Add:
+ case llvm::Instruction::Sub:
+ case llvm::Instruction::Mul:
+ case llvm::Instruction::Shl:
+ {
+ auto ty = llvm_type2alive(i.getType());
+ // FIXME: what about const operands?
+ auto op1 = identifiers[i.getOperand(0)];
+ auto op2 = identifiers[i.getOperand(1)];
+ if (!ty || !op1 || !op2)
+ goto err;
+ // FIXME
+ auto op = make_unique<BinOp>(*ty, i.getName().str(), *op1, *op2, BinOp::Add);
+ identifiers.emplace(&i, op.get());
+ return op;
+ }
+ default:
+ break;
+ }
+err:
+ errs() << "Unsupported instruction: " << i << '\n';
+ return {};
+}
+
+
+optional<Function> llvm2alive(const llvm::Function &f) {
+ identifiers.clear();
+
+ auto type = llvm_type2alive(f.getReturnType());
+ if (!type)
+ return {};
+
+ Function Fn(*type, f.getName());
+
+ for (auto &arg : f.args()) {
+ auto ty = llvm_type2alive(arg.getType());
+ if (!ty)
+ return {};
+ auto val = make_unique<Input>(*ty, arg.getName().str());
+ identifiers.emplace(&arg, val.get());
+ Fn.addInput(move(val));
+ }
+
+ for (auto &bb : f) {
+ auto &BB = Fn.getBB(s(bb.getName()));
+ for (auto &i : bb) {
+ if (auto I = llvm_instr2alive(i))
+ BB.addIntr(move(I));
+ else
+ return {};
+ }
+ }
+
+ return move(Fn);
+}
+
+
+struct TVPass : public llvm::FunctionPass {
static char ID;
- //smt::smt_initializer smt_init; move out
//TransformPrintOpts print_opts;
bool FatalErrors = true;
TVPass() : FunctionPass(ID) {}
bool runOnFunction(llvm::Function &F) override {
- outs() << "verifying " << F.getName() << '\n';
+ auto fn = llvm2alive(F);
+ if (fn)
+ fn->print(cout);
+
+
+ //outs() << "verifying " << F.getName() << '\n';
if (/* !V->verify(F)*/ false && FatalErrors) {
- errs() << "in function " << F.getName() << '\n';
- report_fatal_error("Broken function found, compilation aborted!");
+ //errs() << "in function " << F.getName() << '\n';
+ //report_fatal_error("Broken function found, compilation aborted!");
}
return false;
}
- void getAnalysisUsage(AnalysisUsage &AU) const override {
+ void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
AU.setPreservesAll();
}
};
-}
-
char TVPass::ID = 0;
-static RegisterPass<TVPass> X("tv", "Translation Validator", false, false);
+llvm::RegisterPass<TVPass> X("tv", "Translation Validator", false, false);
+
+}

TV: checkpoint work