261 lines
7.2 KiB
C++
261 lines
7.2 KiB
C++
#pragma once
|
|
|
|
#include "3rdparty/easylogging++.h"
|
|
#include "common.h"
|
|
#include "llir_type.h"
|
|
#include <cassert>
|
|
#include <list>
|
|
#include <memory>
|
|
#include <shared_mutex>
|
|
#include <string>
|
|
#include <tuple>
|
|
#include <vector>
|
|
|
|
namespace antlrSysY {
|
|
|
|
DEF_PTR_T(Value);
|
|
DEF_PTR_T(BasicBlock);
|
|
DEF_PTR_T(User);
|
|
DEF_PTR_T(Function);
|
|
DEF_PTR_T(Instruction);
|
|
DEF_PTR_T(Constant);
|
|
DEF_PTR_T(ConstantInt);
|
|
|
|
// typedef std::tuple<ValuePtr_t, UserPtr_t, int> UseEdge_t;
|
|
struct Use {
|
|
ValuePtr_t value;
|
|
User* user;
|
|
unsigned op_index;
|
|
};
|
|
// Define, User, operand-index
|
|
// for Instruction, inst `uses` op, so inst is the user
|
|
|
|
class Value {
|
|
public:
|
|
std::string name;
|
|
TypePtr_t type;
|
|
std::list<Use> use_list; // a list of use-edge from this value
|
|
|
|
Value(const std::string &name, TypePtr_t type) : name(name), type(type) {}
|
|
virtual ~Value() = default;
|
|
|
|
template <typename TT>
|
|
static bool is(std::shared_ptr<Value> ptr) {
|
|
if (ptr.get()) {
|
|
// auto &r = *ptr.get();
|
|
// return typeid(r) == typeid(TT);
|
|
return dynamic_cast<TT *>(ptr.get()) != nullptr;
|
|
}
|
|
LOG(WARNING) << "Comparing with nullptr";
|
|
assert(0);
|
|
return false;
|
|
}
|
|
|
|
// it is caller's duty to check before use `asType`
|
|
template <typename TT>
|
|
static std::shared_ptr<TT> as(std::shared_ptr<Value> ptr) {
|
|
return std::dynamic_pointer_cast<TT>(ptr);
|
|
}
|
|
|
|
virtual std::string to_string() {
|
|
return name + ": " + type->to_string();
|
|
}
|
|
|
|
virtual std::string to_IR_string() {
|
|
panic("No applicable for IR gen");
|
|
}
|
|
|
|
void u_remove_use(User* user) {
|
|
// use_list.erase(
|
|
// std::remove_if(
|
|
// use_list.begin(), use_list.end(), [user](const UseEdge_t &use) { return std::get<1>(use) == user; }
|
|
// ),
|
|
// use_list.end()
|
|
// );
|
|
for (auto itr = use_list.begin(); itr != use_list.end();) {
|
|
if (itr->user == user) {
|
|
itr = use_list.erase(itr);
|
|
}
|
|
else {
|
|
++ itr;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
class User : public Value {
|
|
public:
|
|
std::vector<ValuePtr_t> operand_list;
|
|
|
|
User(const std::string &name, TypePtr_t type) : Value(name, type) {}
|
|
void Add_Operand(ValuePtr_t op) {
|
|
op->use_list.push_back({op, this, (unsigned)operand_list.size()});
|
|
operand_list.push_back(op);
|
|
}
|
|
// make anything that use this value use the new value
|
|
void u_replace_users(ValuePtr_t value) {
|
|
if (value == nullptr) {
|
|
assert(!use_list.size() && "No one should use this");
|
|
return;
|
|
}
|
|
for (auto use : use_list) {
|
|
auto user = use.user;
|
|
auto index = use.op_index;
|
|
user->operand_list[index] = value;
|
|
assert(value);
|
|
value->use_list.push_back({value, user, index});
|
|
}
|
|
// all original uses are gone
|
|
use_list.clear();
|
|
}
|
|
// remove this user from its operands
|
|
void u_remove_from_usees() {
|
|
for (auto op : operand_list) {
|
|
assert(op);
|
|
op->u_remove_use(this);
|
|
}
|
|
}
|
|
};
|
|
|
|
class FParam : public Value {
|
|
public:
|
|
int ir_seqno = -1;
|
|
FParam(const std::string &name, TypePtr_t type) : Value(name, type) {}
|
|
virtual std::string to_string() override {
|
|
return type->to_string() + " @" + name + " %" + std::to_string(ir_seqno);
|
|
}
|
|
virtual std::string to_IR_string() override {
|
|
return type->to_IR_string() + " %" + std::to_string(ir_seqno);
|
|
}
|
|
};
|
|
|
|
typedef std::list<std::shared_ptr<antlrSysY::BasicBlock>>::iterator BasicBlockListNode_t;
|
|
|
|
class Function : public Value {
|
|
public:
|
|
std::vector<std::shared_ptr<FParam>> fparam_list;
|
|
std::list<std::shared_ptr<BasicBlock>> bb_list;
|
|
// we use empty basic_block to represent lib function
|
|
Function(const std::string &name, TypePtr_t ret_type) : Value(name, std::make_shared<FunctionType>(ret_type)) {}
|
|
std::shared_ptr<FunctionType> get_type() {
|
|
return std::dynamic_pointer_cast<FunctionType>(type);
|
|
}
|
|
bool is_libfunc() {
|
|
return bb_list.size() == 0;
|
|
}
|
|
virtual std::string to_string() override {
|
|
std::string params_str;
|
|
for (auto fparam : fparam_list) {
|
|
params_str += fparam->to_string() + ",";
|
|
}
|
|
return name + "(" + params_str + ") -> " + type->to_string();
|
|
}
|
|
};
|
|
|
|
class BasicBlock : public Value {
|
|
public:
|
|
int ir_seqno = -1;
|
|
std::list<InstructionPtr_t> inst_list;
|
|
std::shared_ptr<Function> parent;
|
|
BasicBlockListNode_t itr;
|
|
std::list<BasicBlockPtr_t> successors;
|
|
std::list<BasicBlockPtr_t> predecessors;
|
|
|
|
BasicBlockPtr_t idomer; // dominating node
|
|
std::list<BasicBlockPtr_t> idom_list; // immediate dominated nodes
|
|
std::list<BasicBlockPtr_t> dom_list; // dominated nodes
|
|
std::list<BasicBlockPtr_t> dom_frontier;
|
|
int dom_level;
|
|
int _dom_helper_index;
|
|
int dom_dfs_in;
|
|
int dom_dfs_out;
|
|
|
|
BasicBlock(const std::string &name, std::shared_ptr<Function> parent) : Value(name, TypeHelper::TYPE_LABEL) {
|
|
this->parent = parent;
|
|
}
|
|
};
|
|
|
|
class Constant : public Value {
|
|
public:
|
|
Constant(const std::string &name, TypePtr_t type) : Value(name, type) {}
|
|
};
|
|
|
|
class ConstantInt : public Constant {
|
|
public:
|
|
int value;
|
|
ConstantInt(const std::string &name, int value) : Constant(name, TypeHelper::TYPE_I32), value(value) {}
|
|
static std::shared_ptr<ConstantInt> make_shared(int value) {
|
|
return std::make_shared<ConstantInt>("", value);
|
|
}
|
|
virtual std::string to_string() override {
|
|
std::string str = type->to_string() + " " + std::to_string(value);
|
|
return str;
|
|
}
|
|
virtual std::string to_IR_string() override {
|
|
return type->to_IR_string() + " " + std::to_string(value);
|
|
}
|
|
};
|
|
|
|
class ConstantArr : public Constant {
|
|
public:
|
|
std::vector<ValuePtr_t> value_list;
|
|
ConstantArr(const std::string &name, const std::vector<ValuePtr_t> &value_list, std::shared_ptr<ArrayType> type)
|
|
: Constant(name, type), value_list(value_list) {}
|
|
|
|
int real_size() const {
|
|
return std::dynamic_pointer_cast<ArrayType>(type)->element_count;
|
|
}
|
|
static std::shared_ptr<ConstantArr> make_shared(
|
|
const std::string &name,
|
|
const std::vector<ValuePtr_t> &value_list,
|
|
std::shared_ptr<ArrayType> type
|
|
) {
|
|
return std::make_shared<ConstantArr>(name, value_list, type);
|
|
}
|
|
virtual std::string to_string() override {
|
|
std::string str = "{";
|
|
for (auto elem : value_list) {
|
|
if (elem)
|
|
str += elem->to_string() + ", ";
|
|
else
|
|
str += "{...}, ";
|
|
}
|
|
if (real_size() > value_list.size()) {
|
|
str += std::to_string(real_size() - value_list.size()) + " zeros";
|
|
}
|
|
str += "}";
|
|
return str;
|
|
}
|
|
};
|
|
|
|
typedef std::shared_ptr<Constant> ConstantPtr_t;
|
|
|
|
// emmm, actually it is more of a Instruction type
|
|
class GlobalVar : public Value {
|
|
public:
|
|
ConstantPtr_t init_value;
|
|
bool is_const;
|
|
GlobalVar(const std::string &name, TypePtr_t type, ConstantPtr_t init_value, bool is_const)
|
|
: Value(name, PointerType::make_shared(type)), init_value(init_value), is_const(is_const) {}
|
|
static std::shared_ptr<GlobalVar> make_shared(
|
|
const std::string &name,
|
|
TypePtr_t type,
|
|
ConstantPtr_t init_value,
|
|
bool is_const
|
|
) {
|
|
return std::make_shared<GlobalVar>(name, type, init_value, is_const);
|
|
}
|
|
virtual std::string to_IR_string() override {
|
|
std::string str = type->to_IR_string() + " @" + name;
|
|
return str;
|
|
}
|
|
};
|
|
|
|
std::shared_ptr<ConstantArr> gen_arr_hierarchy(
|
|
const std::shared_ptr<ArrayType> array_type,
|
|
const std::vector<ValuePtr_t> &const_array,
|
|
int base,
|
|
int length
|
|
);
|
|
|
|
} // namespace antlrSysY
|