mirror of https://github.com/colgm/colgm.git
581 lines
15 KiB
C++
581 lines
15 KiB
C++
#pragma once
|
|
|
|
#include "sema/symbol.h"
|
|
#include "report.h"
|
|
|
|
#include <iostream>
|
|
#include <vector>
|
|
#include <cstring>
|
|
#include <sstream>
|
|
|
|
namespace colgm::mir {
|
|
|
|
enum class kind {
|
|
mir_block = 1,
|
|
mir_unary,
|
|
mir_binary,
|
|
mir_type_convert,
|
|
mir_nil,
|
|
mir_number,
|
|
mir_string,
|
|
mir_char,
|
|
mir_bool,
|
|
mir_array,
|
|
mir_struct_init,
|
|
mir_call,
|
|
mir_call_id,
|
|
mir_call_index,
|
|
mir_call_func,
|
|
mir_get_field,
|
|
mir_get_path,
|
|
mir_ptr_get_field,
|
|
mir_define,
|
|
mir_assign,
|
|
mir_if,
|
|
mir_branch,
|
|
mir_break,
|
|
mir_continue,
|
|
mir_loop,
|
|
mir_return
|
|
};
|
|
|
|
class visitor;
|
|
|
|
class mir {
|
|
protected:
|
|
kind mir_kind;
|
|
span location;
|
|
|
|
public:
|
|
mir(kind k, const span& loc): mir_kind(k), location(loc) {}
|
|
virtual ~mir() = default;
|
|
virtual void dump(const std::string&, std::ostream&) {}
|
|
virtual void accept(visitor*);
|
|
|
|
public:
|
|
auto get_kind() const { return mir_kind; }
|
|
const auto& get_location() const { return location; }
|
|
};
|
|
|
|
class mir_block: public mir {
|
|
private:
|
|
std::vector<mir*> content;
|
|
|
|
public:
|
|
mir_block(const span& loc): mir(kind::mir_block, loc) {}
|
|
~mir_block() override {
|
|
for(auto i : content) {
|
|
delete i;
|
|
}
|
|
}
|
|
void dump(const std::string&, std::ostream&) override;
|
|
void accept(visitor*) override;
|
|
|
|
public:
|
|
void add_content(mir* n) { content.push_back(n); }
|
|
const auto& get_content() const { return content; }
|
|
auto& get_mutable_content() { return content; }
|
|
};
|
|
|
|
class mir_unary: public mir {
|
|
public:
|
|
enum class opr_kind {
|
|
neg,
|
|
bnot,
|
|
lnot
|
|
};
|
|
|
|
private:
|
|
opr_kind opr;
|
|
type resolve_type;
|
|
mir_block* value;
|
|
|
|
public:
|
|
mir_unary(const span& loc, opr_kind o, const type& t, mir_block* v):
|
|
mir(kind::mir_unary, loc), opr(o), resolve_type(t), value(v) {}
|
|
~mir_unary() override {
|
|
delete value;
|
|
}
|
|
void dump(const std::string&, std::ostream&) override;
|
|
void accept(visitor*) override;
|
|
|
|
public:
|
|
auto get_value() const { return value; }
|
|
auto get_opr() const { return opr; }
|
|
const auto& get_type() const { return resolve_type; }
|
|
};
|
|
|
|
class mir_binary: public mir {
|
|
public:
|
|
enum class opr_kind {
|
|
add,
|
|
sub,
|
|
mult,
|
|
div,
|
|
rem,
|
|
cmpeq,
|
|
cmpneq,
|
|
less,
|
|
leq,
|
|
grt,
|
|
geq,
|
|
cmpand,
|
|
cmpor,
|
|
band,
|
|
bor,
|
|
bxor,
|
|
};
|
|
|
|
private:
|
|
opr_kind opr;
|
|
type resolve_type;
|
|
mir_block* left;
|
|
mir_block* right;
|
|
|
|
public:
|
|
mir_binary(const span& loc,
|
|
opr_kind o,
|
|
const type& t,
|
|
mir_block* l,
|
|
mir_block* r):
|
|
mir(kind::mir_binary, loc), opr(o), resolve_type(t),
|
|
left(l), right(r) {}
|
|
~mir_binary() override {
|
|
delete left;
|
|
delete right;
|
|
}
|
|
void dump(const std::string&, std::ostream&) override;
|
|
void accept(visitor*) override;
|
|
|
|
public:
|
|
auto get_left() const { return left; }
|
|
auto get_right() const { return right; }
|
|
auto get_opr() const { return opr; }
|
|
const auto& get_type() const { return resolve_type; }
|
|
};
|
|
|
|
class mir_type_convert: public mir {
|
|
private:
|
|
mir_block* source;
|
|
type target_type;
|
|
|
|
public:
|
|
mir_type_convert(const span& loc, mir_block* src, const type& tt):
|
|
mir(kind::mir_type_convert, loc), source(src), target_type(tt) {}
|
|
~mir_type_convert() override {
|
|
delete source;
|
|
}
|
|
void dump(const std::string&, std::ostream&) override;
|
|
void accept(visitor*) override;
|
|
|
|
public:
|
|
const auto& get_target_type() const { return target_type; }
|
|
auto get_source() const { return source; }
|
|
};
|
|
|
|
class mir_nil: public mir {
|
|
private:
|
|
type resolve_type;
|
|
|
|
public:
|
|
mir_nil(const span& loc, const type& t):
|
|
mir(kind::mir_nil, loc), resolve_type(t) {}
|
|
~mir_nil() override = default;
|
|
void dump(const std::string&, std::ostream&) override;
|
|
void accept(visitor*) override;
|
|
|
|
public:
|
|
const auto& get_type() const { return resolve_type; }
|
|
};
|
|
|
|
class mir_number: public mir {
|
|
private:
|
|
std::string literal;
|
|
type resolve_type;
|
|
|
|
public:
|
|
mir_number(const span& loc, const std::string& l, const type& t):
|
|
mir(kind::mir_number, loc), literal(l), resolve_type(t) {}
|
|
~mir_number() override = default;
|
|
void dump(const std::string&, std::ostream&) override;
|
|
void accept(visitor*) override;
|
|
|
|
public:
|
|
const auto& get_literal() const { return literal; }
|
|
const auto& get_type() const { return resolve_type; }
|
|
};
|
|
|
|
class mir_string: public mir {
|
|
private:
|
|
std::string literal;
|
|
type resolve_type;
|
|
|
|
public:
|
|
mir_string(const span& loc, const std::string& l, const type& t):
|
|
mir(kind::mir_string, loc), literal(l), resolve_type(t) {}
|
|
~mir_string() override = default;
|
|
void dump(const std::string&, std::ostream&) override;
|
|
void accept(visitor*) override;
|
|
|
|
public:
|
|
const auto& get_literal() const { return literal; }
|
|
const auto& get_type() const { return resolve_type; }
|
|
};
|
|
|
|
class mir_char: public mir {
|
|
private:
|
|
char literal;
|
|
type resolve_type;
|
|
|
|
public:
|
|
mir_char(const span& loc, const char l, const type& t):
|
|
mir(kind::mir_char, loc), literal(l), resolve_type(t) {}
|
|
~mir_char() override = default;
|
|
void dump(const std::string&, std::ostream&) override;
|
|
void accept(visitor*) override;
|
|
|
|
public:
|
|
auto get_literal() const { return literal; }
|
|
const auto& get_type() const { return resolve_type; }
|
|
};
|
|
|
|
class mir_bool: public mir {
|
|
private:
|
|
bool literal;
|
|
type resolve_type;
|
|
|
|
public:
|
|
mir_bool(const span& loc, const bool l, const type& t):
|
|
mir(kind::mir_bool, loc), literal(l), resolve_type(t) {}
|
|
~mir_bool() override = default;
|
|
void dump(const std::string&, std::ostream&) override;
|
|
void accept(visitor*) override;
|
|
|
|
public:
|
|
auto get_literal() const { return literal; }
|
|
const auto& get_type() const { return resolve_type; }
|
|
};
|
|
|
|
class mir_array: public mir {
|
|
private:
|
|
u64 size;
|
|
type resolve_type;
|
|
|
|
public:
|
|
mir_array(const span& loc, u64 sz, const type& t):
|
|
mir(kind::mir_array, loc), size(sz), resolve_type(t) {}
|
|
~mir_array() override = default;
|
|
void dump(const std::string&, std::ostream&) override;
|
|
void accept(visitor*) override;
|
|
|
|
public:
|
|
auto get_size() const { return size; }
|
|
const auto& get_type() const { return resolve_type; }
|
|
};
|
|
|
|
class mir_struct_init: public mir {
|
|
public:
|
|
struct field {
|
|
std::string name;
|
|
mir_block* content;
|
|
type resolve_type;
|
|
};
|
|
|
|
private:
|
|
std::vector<field> fields;
|
|
type resolve_type;
|
|
|
|
public:
|
|
mir_struct_init(const span& loc, const type& t):
|
|
mir(kind::mir_struct_init, loc), resolve_type(t) {}
|
|
~mir_struct_init() override;
|
|
void dump(const std::string&, std::ostream&) override;
|
|
void accept(visitor*) override;
|
|
|
|
public:
|
|
void add_field(const std::string& n, mir_block* c, const type& t) {
|
|
fields.push_back({n, c, t});
|
|
}
|
|
const auto& get_fields() const { return fields; }
|
|
const auto& get_type() const { return resolve_type; }
|
|
|
|
};
|
|
|
|
class mir_call: public mir {
|
|
private:
|
|
mir_block* content;
|
|
type resolve_type;
|
|
|
|
public:
|
|
mir_call(const span& loc, const type& t, mir_block* c):
|
|
mir(kind::mir_call, loc), resolve_type(t), content(c) {}
|
|
~mir_call() override {
|
|
delete content;
|
|
}
|
|
void dump(const std::string&, std::ostream&) override;
|
|
void accept(visitor*) override;
|
|
|
|
public:
|
|
auto get_content() const { return content; }
|
|
const auto& get_type() const { return resolve_type; }
|
|
};
|
|
|
|
class mir_call_id: public mir {
|
|
private:
|
|
std::string name;
|
|
type resolve_type;
|
|
|
|
public:
|
|
mir_call_id(const span& loc, const std::string& n, const type& t):
|
|
mir(kind::mir_call_id, loc), name(n), resolve_type(t) {}
|
|
~mir_call_id() override = default;
|
|
void dump(const std::string&, std::ostream&) override;
|
|
void accept(visitor*) override;
|
|
|
|
public:
|
|
const auto& get_name() const { return name; }
|
|
const auto& get_type() const { return resolve_type; }
|
|
};
|
|
|
|
class mir_call_index: public mir {
|
|
private:
|
|
type resolve_type;
|
|
mir_block* index;
|
|
|
|
public:
|
|
mir_call_index(const span& loc, const type& t, mir_block* i):
|
|
mir(kind::mir_call_index, loc), resolve_type(t), index(i) {}
|
|
~mir_call_index() override {
|
|
delete index;
|
|
}
|
|
void dump(const std::string&, std::ostream&) override;
|
|
void accept(visitor*) override;
|
|
|
|
public:
|
|
auto get_index() const { return index; }
|
|
const auto& get_type() const { return resolve_type; }
|
|
};
|
|
|
|
class mir_call_func: public mir {
|
|
private:
|
|
mir_block* args;
|
|
type resolve_type;
|
|
|
|
public:
|
|
mir_call_func(const span& loc, mir_block* a, const type& t):
|
|
mir(kind::mir_call_func, loc), args(a), resolve_type(t) {}
|
|
~mir_call_func() override { delete args; }
|
|
void dump(const std::string&, std::ostream&) override;
|
|
void accept(visitor*) override;
|
|
|
|
public:
|
|
auto get_args() const { return args; }
|
|
const auto& get_type() const { return resolve_type; }
|
|
};
|
|
|
|
class mir_get_field: public mir {
|
|
private:
|
|
std::string name;
|
|
type resolve_type;
|
|
|
|
public:
|
|
mir_get_field(const span& loc, const std::string& n, const type& t):
|
|
mir(kind::mir_get_field, loc), name(n), resolve_type(t) {}
|
|
~mir_get_field() override = default;
|
|
void dump(const std::string&, std::ostream&) override;
|
|
void accept(visitor*) override;
|
|
|
|
public:
|
|
const auto& get_name() const { return name; }
|
|
const auto& get_type() const { return resolve_type; }
|
|
};
|
|
|
|
class mir_ptr_get_field: public mir {
|
|
private:
|
|
std::string name;
|
|
type resolve_type;
|
|
|
|
public:
|
|
mir_ptr_get_field(const span& loc, const std::string& n, const type& t):
|
|
mir(kind::mir_ptr_get_field, loc), name(n), resolve_type(t) {}
|
|
~mir_ptr_get_field() override = default;
|
|
void dump(const std::string&, std::ostream&) override;
|
|
void accept(visitor*) override;
|
|
|
|
public:
|
|
const auto& get_name() const { return name; }
|
|
const auto& get_type() const { return resolve_type; }
|
|
};
|
|
|
|
class mir_get_path: public mir {
|
|
private:
|
|
std::string name;
|
|
type resolve_type;
|
|
|
|
public:
|
|
mir_get_path(const span& loc, const std::string& n, const type& t):
|
|
mir(kind::mir_get_path, loc), name(n), resolve_type(t) {}
|
|
~mir_get_path() override = default;
|
|
void dump(const std::string&, std::ostream&) override;
|
|
void accept(visitor*) override;
|
|
|
|
public:
|
|
const auto& get_name() const { return name; }
|
|
const auto& get_type() const { return resolve_type; }
|
|
};
|
|
|
|
class mir_define: public mir {
|
|
private:
|
|
std::string name;
|
|
mir_block* init_value;
|
|
type resolve_type;
|
|
|
|
public:
|
|
mir_define(const span& loc,
|
|
const std::string& n,
|
|
mir_block* iv,
|
|
const type& rt):
|
|
mir(kind::mir_define, loc), name(n),
|
|
init_value(iv), resolve_type(rt) {}
|
|
~mir_define() override {
|
|
delete init_value;
|
|
}
|
|
void dump(const std::string&, std::ostream&) override;
|
|
void accept(visitor*) override;
|
|
|
|
public:
|
|
const auto& get_name() const { return name; }
|
|
const auto& get_type() const { return resolve_type; }
|
|
auto get_init_value() const { return init_value; }
|
|
};
|
|
|
|
class mir_assign: public mir {
|
|
public:
|
|
enum class opr_kind {
|
|
eq,
|
|
addeq,
|
|
subeq,
|
|
multeq,
|
|
diveq,
|
|
remeq,
|
|
andeq,
|
|
xoreq,
|
|
oreq
|
|
};
|
|
|
|
private:
|
|
opr_kind opr;
|
|
mir_block* left;
|
|
mir_block* right;
|
|
|
|
public:
|
|
mir_assign(const span& loc, const opr_kind o, mir_block* l, mir_block* r):
|
|
mir(kind::mir_assign, loc), opr(o), left(l), right(r) {}
|
|
~mir_assign() override {
|
|
delete left;
|
|
delete right;
|
|
}
|
|
void dump(const std::string&, std::ostream&) override;
|
|
void accept(visitor*) override;
|
|
|
|
public:
|
|
auto get_left() const { return left; }
|
|
auto get_right() const { return right; }
|
|
auto get_opr() const { return opr; }
|
|
};
|
|
|
|
class mir_if: public mir {
|
|
private:
|
|
mir_block* condition;
|
|
mir_block* content;
|
|
|
|
public:
|
|
mir_if(const span& loc, mir_block* cond, mir_block* ct):
|
|
mir(kind::mir_if, loc), condition(cond), content(ct) {}
|
|
~mir_if() override {
|
|
delete condition;
|
|
delete content;
|
|
}
|
|
void dump(const std::string&, std::ostream&) override;
|
|
void accept(visitor*) override;
|
|
|
|
public:
|
|
auto get_condition() const { return condition; }
|
|
auto get_content() const { return content; }
|
|
};
|
|
|
|
class mir_branch: public mir {
|
|
private:
|
|
std::vector<mir_if*> branch;
|
|
|
|
public:
|
|
mir_branch(const span& loc):
|
|
mir(kind::mir_branch, loc) {}
|
|
~mir_branch() override {
|
|
for(auto i : branch) {
|
|
delete i;
|
|
}
|
|
}
|
|
void dump(const std::string&, std::ostream&) override;
|
|
void accept(visitor*) override;
|
|
|
|
public:
|
|
void add(mir_if* b) { branch.push_back(b); }
|
|
const auto& get_branch() const { return branch; }
|
|
};
|
|
|
|
class mir_break: public mir {
|
|
public:
|
|
mir_break(const span& loc): mir(kind::mir_break, loc) {}
|
|
~mir_break() override = default;
|
|
void dump(const std::string&, std::ostream&) override;
|
|
void accept(visitor*) override;
|
|
};
|
|
|
|
class mir_continue: public mir {
|
|
public:
|
|
mir_continue(const span& loc): mir(kind::mir_continue, loc) {}
|
|
~mir_continue() override = default;
|
|
void dump(const std::string&, std::ostream&) override;
|
|
void accept(visitor*) override;
|
|
};
|
|
|
|
class mir_loop: public mir {
|
|
private:
|
|
mir_block* condition;
|
|
mir_block* content;
|
|
mir_block* update;
|
|
|
|
public:
|
|
mir_loop(const span& loc, mir_block* cond, mir_block* ct, mir_block* ud):
|
|
mir(kind::mir_loop, loc), condition(cond), content(ct), update(ud) {}
|
|
~mir_loop() override {
|
|
delete condition;
|
|
delete content;
|
|
delete update;
|
|
}
|
|
void dump(const std::string&, std::ostream&) override;
|
|
void accept(visitor*) override;
|
|
|
|
public:
|
|
auto get_condition() const { return condition; }
|
|
auto get_content() const { return content; }
|
|
auto get_update() const { return update; }
|
|
};
|
|
|
|
class mir_return: public mir {
|
|
private:
|
|
mir_block* value;
|
|
|
|
public:
|
|
mir_return(const span& loc, mir_block* v):
|
|
mir(kind::mir_return, loc), value(v) {}
|
|
~mir_return() override { delete value; }
|
|
void dump(const std::string&, std::ostream&) override;
|
|
void accept(visitor*) override;
|
|
|
|
public:
|
|
auto get_value() const { return value; }
|
|
};
|
|
|
|
} |