machine code gen part 1
This commit is contained in:
parent
a2d0c211a4
commit
67a32e446e
@ -2,18 +2,26 @@
|
|||||||
#include "3rdparty/easylogging++.h"
|
#include "3rdparty/easylogging++.h"
|
||||||
#include <any>
|
#include <any>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
#include <list>
|
||||||
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
|
||||||
#include <vector>
|
|
||||||
#include <list>
|
|
||||||
#include <unordered_set>
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
|
#include <vector>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
#define uptr(type) std::unique_ptr<type>
|
#define uptr(type) std::unique_ptr<type>
|
||||||
#define sptr(type) std::shared_ptr<type>
|
#define sptr(type) std::shared_ptr<type>
|
||||||
|
|
||||||
|
template <typename DST, typename SRC>
|
||||||
|
inline sptr(DST) shared_cast(SRC src) {
|
||||||
|
return std::dynamic_pointer_cast<DST>(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FIND(container, val) std::find(container.begin(), container.end(), val)
|
||||||
|
|
||||||
#define panic(message) \
|
#define panic(message) \
|
||||||
do { \
|
do { \
|
||||||
throw GrammarException(__FILE__, __LINE__, (message)); \
|
throw GrammarException(__FILE__, __LINE__, (message)); \
|
||||||
|
|||||||
@ -159,8 +159,8 @@ public:
|
|||||||
std::list<InstructionPtr_t> inst_list;
|
std::list<InstructionPtr_t> inst_list;
|
||||||
std::shared_ptr<Function> parent;
|
std::shared_ptr<Function> parent;
|
||||||
BasicBlockListNode_t itr;
|
BasicBlockListNode_t itr;
|
||||||
std::list<BasicBlockPtr_t> successors;
|
std::list<BasicBlockPtr_t> succ_list;
|
||||||
std::list<BasicBlockPtr_t> predecessors;
|
std::list<BasicBlockPtr_t> pred_list;
|
||||||
|
|
||||||
BasicBlockPtr_t IDOM; // dominating node
|
BasicBlockPtr_t IDOM; // dominating node
|
||||||
std::unordered_set<BasicBlockPtr_t> idom_set; // immediate dominated nodes
|
std::unordered_set<BasicBlockPtr_t> idom_set; // immediate dominated nodes
|
||||||
|
|||||||
2
include/machcode.h
Normal file
2
include/machcode.h
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "mc_inst.h"
|
||||||
@ -1,69 +1,215 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "llir.h"
|
||||||
|
|
||||||
namespace codegen{
|
using std::make_shared;
|
||||||
|
|
||||||
|
namespace codegen {
|
||||||
|
|
||||||
// a?, t?, ra are caller-saved
|
// a?, t?, ra are caller-saved
|
||||||
// s? are callee-saved
|
// s? are callee-saved
|
||||||
// x0,gp,tp are preserved in user-space
|
// x0,gp,tp are preserved in user-space
|
||||||
enum class RV64Reg {
|
enum class RV64Reg {
|
||||||
x0 = 0, // zero
|
x0 = 0, // zero
|
||||||
x1, // ra, caller
|
ra, // ra, caller
|
||||||
x2, // sp, callee
|
sp, // sp, callee
|
||||||
x3, // gp
|
gp, // gp
|
||||||
x4, // tp
|
tp, // tp
|
||||||
x5, // t0, caller
|
t0, // t0, caller
|
||||||
x6,x7, // t1-2, caller
|
t1,
|
||||||
x8, // s0/fp, callee
|
t2, // t1-2, caller
|
||||||
x9, // s1, callee
|
s0, // s0/fp, callee
|
||||||
x10,x11, // a0-1,caller
|
s1, // s1, callee
|
||||||
x12,x13,x14,x15,x16,x17, // a2-7,caller
|
a0,
|
||||||
x18,x19,x20,x21,x22,x23,x24,x25,x26,x27, // s2-11,callee
|
a1, // a0-1,caller
|
||||||
x28,x29,x30,x31, // t3-6,caller
|
a2,
|
||||||
|
a3,
|
||||||
|
a4,
|
||||||
|
a5,
|
||||||
|
a6,
|
||||||
|
a7, // a2-7,caller
|
||||||
|
s2,
|
||||||
|
s3,
|
||||||
|
s4,
|
||||||
|
s5,
|
||||||
|
s6,
|
||||||
|
s7,
|
||||||
|
s8,
|
||||||
|
s9,
|
||||||
|
s10,
|
||||||
|
s11, // s2-11,callee
|
||||||
|
t3,
|
||||||
|
t4,
|
||||||
|
t5,
|
||||||
|
t6, // t3-6,caller
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::string Reg2Name(RV64Reg reg) {
|
// riscv calling convention see: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc
|
||||||
|
|
||||||
|
const int XLEN = 8;
|
||||||
|
|
||||||
|
inline std::string RV64_RegName(RV64Reg reg) {
|
||||||
std::string regname = "x" + std::to_string((int)reg);
|
std::string regname = "x" + std::to_string((int)reg);
|
||||||
return regname;
|
return regname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline RV64Reg RV64_RegOffset(RV64Reg reg, int offset) {
|
||||||
|
auto xi = (int)reg + offset;
|
||||||
|
return (RV64Reg)xi;
|
||||||
|
}
|
||||||
|
|
||||||
|
class MOperand;
|
||||||
|
class MInst;
|
||||||
|
class MBasicBlock;
|
||||||
|
class MFunction;
|
||||||
|
|
||||||
class MOperand {
|
class MOperand {
|
||||||
public:
|
public:
|
||||||
enum class type {
|
enum class OpTag {
|
||||||
Virt,
|
Virt,
|
||||||
Imm,
|
Imm,
|
||||||
Reg,
|
Reg,
|
||||||
} op_type;
|
} op_type = OpTag::Virt;
|
||||||
int value;
|
int value = ~0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
MOperand(OpTag tag, int val) : op_type(tag), value(val) {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static sptr(MOperand) NewVirtReg(int reg_no) {
|
||||||
|
auto mop = std::make_shared<MOperand>(OpTag::Virt, reg_no);
|
||||||
|
return mop;
|
||||||
|
}
|
||||||
|
|
||||||
|
static sptr(MOperand) NewImm(int imm_val) {
|
||||||
|
auto mop = std::make_shared<MOperand>(OpTag::Imm, imm_val);
|
||||||
|
return mop;
|
||||||
|
}
|
||||||
|
|
||||||
|
static sptr(MOperand) NewReg(RV64Reg phy_reg) {
|
||||||
|
auto mop = std::make_shared<MOperand>(OpTag::Reg, (int)phy_reg);
|
||||||
|
return mop;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class MInst {
|
class MInst {
|
||||||
public:
|
public:
|
||||||
enum class MInstTag {
|
enum class MInstTag {
|
||||||
Add, Sub, Rsb, Mul, Div, Mod, Lt, Le, Ge, Gt, Eq, Ne, And, Or,
|
Add,
|
||||||
LongMul, FMA, Mv, Branch, Jump, Return, Load, Store,Compare, Call, Global,
|
Sub,
|
||||||
|
Rsb,
|
||||||
|
Mul,
|
||||||
|
Div,
|
||||||
|
Mod,
|
||||||
|
Lt,
|
||||||
|
Le,
|
||||||
|
Ge,
|
||||||
|
Gt,
|
||||||
|
Eq,
|
||||||
|
Ne,
|
||||||
|
And,
|
||||||
|
Or,
|
||||||
|
Move, // actually a pseudo, mv = addi rt, rs, 0
|
||||||
|
Branch,
|
||||||
|
Jump,
|
||||||
|
Return,
|
||||||
|
Load,
|
||||||
|
Store,
|
||||||
|
Compare,
|
||||||
|
Call,
|
||||||
|
Global,
|
||||||
} tag;
|
} tag;
|
||||||
|
|
||||||
MInst(MInstTag tag) : tag(tag) {}
|
sptr(MBasicBlock) parent_bb;
|
||||||
|
MInst(MInstTag tag, sptr(MBasicBlock) parent_bb) : tag(tag), parent_bb(parent_bb) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class MBasicBlock {
|
class MBasicBlock {
|
||||||
|
public:
|
||||||
|
sptr(antlrSysY::BasicBlock) ir_bb;
|
||||||
|
sptr(MFunction) parent_func;
|
||||||
|
std::list<sptr(MInst)> inst_list;
|
||||||
|
std::list<sptr(MBasicBlock)> pred_list;
|
||||||
|
std::list<sptr(MBasicBlock)> succ_list;
|
||||||
|
|
||||||
|
std::unordered_set<sptr(MOperand)> livein;
|
||||||
|
std::unordered_set<sptr(MOperand)> liveout;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MFunction {
|
class MFunction {
|
||||||
std::list<uptr(MBasicBlock)> bbs;
|
public:
|
||||||
|
std::list<sptr(MBasicBlock)> bb_list;
|
||||||
|
sptr(antlrSysY::Function) ir_func;
|
||||||
|
|
||||||
|
std::list<sptr(MInst)> stack_arg_reloc;
|
||||||
|
|
||||||
|
unsigned virt_reg_cnt = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MGlobalVar {
|
class MGlobalVar {
|
||||||
|
public:
|
||||||
};
|
};
|
||||||
|
|
||||||
class MCModule {
|
class MCModule {
|
||||||
std::list<uptr(MFunction)> functions;
|
public:
|
||||||
std::list<uptr(MGlobalVar)> globals;
|
std::list<sptr(MFunction)> function_list;
|
||||||
|
std::list<sptr(MGlobalVar)> global_list;
|
||||||
|
void IR2MC(const antlrSysY::Module &ir_module);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
class MInstBinary : public MInst {
|
||||||
|
public:
|
||||||
|
};
|
||||||
|
|
||||||
|
class MInstJump : public MInst {
|
||||||
|
public:
|
||||||
|
sptr(MBasicBlock) target;
|
||||||
|
MInstJump(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Jump, parent_bb) {}
|
||||||
|
|
||||||
|
static sptr(MInstJump) New(sptr(MBasicBlock) parent_bb) {
|
||||||
|
auto inst = make_shared<MInstJump>(parent_bb);
|
||||||
|
parent_bb->inst_list.push_back(inst);
|
||||||
|
return inst;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class MInstLoad : public MInst {
|
||||||
|
public:
|
||||||
|
sptr(MOperand) dst;
|
||||||
|
sptr(MOperand) addr;
|
||||||
|
sptr(MOperand) offset;
|
||||||
|
MInstLoad(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Load, parent_bb) {}
|
||||||
|
|
||||||
|
static sptr(MInstLoad) New(sptr(MBasicBlock) parent_bb) {
|
||||||
|
auto inst = make_shared<MInstLoad>(parent_bb);
|
||||||
|
parent_bb->inst_list.push_back(inst);
|
||||||
|
return inst;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class MInstMove : public MInst {
|
||||||
|
public:
|
||||||
|
sptr(MOperand) dst;
|
||||||
|
sptr(MOperand) src;
|
||||||
|
MInstMove(sptr(MBasicBlock) parent_bb) : MInst(MInstTag::Move, parent_bb) {}
|
||||||
|
static sptr(MInstMove) New(sptr(MBasicBlock) parent_bb, bool insert_begin = false) {
|
||||||
|
auto inst = make_shared<MInstMove>(parent_bb);
|
||||||
|
if (insert_begin)
|
||||||
|
parent_bb->inst_list.push_front(inst);
|
||||||
|
else
|
||||||
|
parent_bb->inst_list.push_back(inst);
|
||||||
|
return inst;
|
||||||
|
}
|
||||||
|
static sptr(MInstMove) New(sptr(MInst) rel_inst, bool insert_after = false) {
|
||||||
|
auto parent_bb = rel_inst->parent_bb;
|
||||||
|
auto inst = make_shared<MInstMove>(parent_bb);
|
||||||
|
auto rel_inst_itr = FIND(parent_bb->inst_list, rel_inst);
|
||||||
|
assert(rel_inst_itr != parent_bb->inst_list.end());
|
||||||
|
if (insert_after)
|
||||||
|
std::advance(rel_inst_itr, 1);
|
||||||
|
parent_bb->inst_list.insert(rel_inst_itr, inst);
|
||||||
|
return inst;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace codegen
|
||||||
@ -51,7 +51,7 @@ void gen_dominance(FunctionPtr_t func) {
|
|||||||
auto cur_bb = bb_list[i];
|
auto cur_bb = bb_list[i];
|
||||||
std::vector<bool> temp(N, 1);
|
std::vector<bool> temp(N, 1);
|
||||||
// temp = {i} union (intersect Dom(j)), j in pred(i)
|
// temp = {i} union (intersect Dom(j)), j in pred(i)
|
||||||
for (auto pred : cur_bb->predecessors) {
|
for (auto pred : cur_bb->pred_list) {
|
||||||
_bitwise_and(temp, dom[pred->_dom_helper_index]);
|
_bitwise_and(temp, dom[pred->_dom_helper_index]);
|
||||||
}
|
}
|
||||||
temp[i] = true;
|
temp[i] = true;
|
||||||
@ -112,8 +112,8 @@ void gen_dominance_frontier(FunctionPtr_t func) {
|
|||||||
bb->DF_set.clear();
|
bb->DF_set.clear();
|
||||||
}
|
}
|
||||||
for (auto n : func->bb_list) {
|
for (auto n : func->bb_list) {
|
||||||
if (n->predecessors.size() >= 2) {
|
if (n->pred_list.size() >= 2) {
|
||||||
for (auto pred : n->predecessors) {
|
for (auto pred : n->pred_list) {
|
||||||
auto runner = pred;
|
auto runner = pred;
|
||||||
while (runner != n->IDOM) {
|
while (runner != n->IDOM) {
|
||||||
runner->DF_set.insert(n);
|
runner->DF_set.insert(n);
|
||||||
|
|||||||
17
src/main.cpp
17
src/main.cpp
@ -8,6 +8,7 @@
|
|||||||
#include "llir.h"
|
#include "llir.h"
|
||||||
#include "passes.h"
|
#include "passes.h"
|
||||||
#include "visitor.h"
|
#include "visitor.h"
|
||||||
|
#include "machcode.h"
|
||||||
#include <3rdparty/argparse.hpp>
|
#include <3rdparty/argparse.hpp>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -18,6 +19,7 @@ INITIALIZE_EASYLOGGINGPP
|
|||||||
|
|
||||||
using namespace antlrSysY;
|
using namespace antlrSysY;
|
||||||
using namespace antlr4;
|
using namespace antlr4;
|
||||||
|
using namespace codegen;
|
||||||
|
|
||||||
class AbortErrorListener : public BaseErrorListener {
|
class AbortErrorListener : public BaseErrorListener {
|
||||||
public:
|
public:
|
||||||
@ -42,6 +44,7 @@ int main(int argc, const char **argv) {
|
|||||||
arg_parser.add_argument("-S").implicit_value(true).help("Useless but required by the contest").required();
|
arg_parser.add_argument("-S").implicit_value(true).help("Useless but required by the contest").required();
|
||||||
arg_parser.add_argument("-o").help("Output file name").required();
|
arg_parser.add_argument("-o").help("Output file name").required();
|
||||||
arg_parser.add_argument("-O1").implicit_value(true).default_value(false).help("Performance mode");
|
arg_parser.add_argument("-O1").implicit_value(true).default_value(false).help("Performance mode");
|
||||||
|
arg_parser.add_argument("-O0").implicit_value(true).default_value(false).help("Rudimentary mode");
|
||||||
arg_parser.add_argument("-emit-llvm").implicit_value(true).default_value(false).help("Generate llvm ir");
|
arg_parser.add_argument("-emit-llvm").implicit_value(true).default_value(false).help("Generate llvm ir");
|
||||||
arg_parser.add_argument("--v").default_value(0);
|
arg_parser.add_argument("--v").default_value(0);
|
||||||
try {
|
try {
|
||||||
@ -54,6 +57,7 @@ int main(int argc, const char **argv) {
|
|||||||
auto source_file = arg_parser.get<std::string>("source");
|
auto source_file = arg_parser.get<std::string>("source");
|
||||||
auto output_file = arg_parser.get<std::string>("-o");
|
auto output_file = arg_parser.get<std::string>("-o");
|
||||||
auto flg_O1 = arg_parser["-O1"] == true;
|
auto flg_O1 = arg_parser["-O1"] == true;
|
||||||
|
auto flg_O0 = arg_parser["-O0"] == true;
|
||||||
auto emit_llvm = arg_parser["-emit-llvm"] == true;
|
auto emit_llvm = arg_parser["-emit-llvm"] == true;
|
||||||
// std::cout << source_file << " " << output_file << " " << flg_O1 <<
|
// std::cout << source_file << " " << output_file << " " << flg_O1 <<
|
||||||
// std::endl;
|
// std::endl;
|
||||||
@ -96,12 +100,20 @@ int main(int argc, const char **argv) {
|
|||||||
std::make_shared<PassBuildCFG>(),
|
std::make_shared<PassBuildCFG>(),
|
||||||
std::make_shared<PassMem2Reg>(),
|
std::make_shared<PassMem2Reg>(),
|
||||||
};
|
};
|
||||||
if (flg_O1) {
|
|
||||||
|
if (!flg_O0) {
|
||||||
for (auto pass : passes) {
|
for (auto pass : passes) {
|
||||||
pass->run(visitor.module);
|
pass->run(visitor.module);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<sptr(Pass)> optpasses = {};
|
||||||
|
if (flg_O1) {
|
||||||
|
for (auto pass : optpasses) {
|
||||||
|
pass->run(visitor.module);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (emit_llvm) {
|
if (emit_llvm) {
|
||||||
auto llir_file = output_file.substr(0, output_file.rfind(".")) + ".ll";
|
auto llir_file = output_file.substr(0, output_file.rfind(".")) + ".ll";
|
||||||
std::ofstream ofs_llir_file(llir_file);
|
std::ofstream ofs_llir_file(llir_file);
|
||||||
@ -114,5 +126,8 @@ int main(int argc, const char **argv) {
|
|||||||
|
|
||||||
// std::cout << tree->toStringTree(&parser) << std::endl << std::endl;
|
// std::cout << tree->toStringTree(&parser) << std::endl << std::endl;
|
||||||
|
|
||||||
|
MCModule mc_module;
|
||||||
|
mc_module.IR2MC(visitor.module);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
108
src/mc_codegen.cpp
Normal file
108
src/mc_codegen.cpp
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
#include "common.h"
|
||||||
|
#include "llir.h"
|
||||||
|
#include "mc_inst.h"
|
||||||
|
#include "visitor.h"
|
||||||
|
|
||||||
|
using std::make_shared;
|
||||||
|
|
||||||
|
namespace codegen {
|
||||||
|
|
||||||
|
static sptr(MOperand) value2moperand(
|
||||||
|
sptr(antlrSysY::Value) ir_value,
|
||||||
|
sptr(MBasicBlock) mc_bb,
|
||||||
|
std::unordered_map<sptr(antlrSysY::Value), sptr(MOperand)> &val2mop
|
||||||
|
) {
|
||||||
|
if (auto fparam = shared_cast<antlrSysY::FParam>(ir_value)) {
|
||||||
|
auto itr = val2mop.find(ir_value);
|
||||||
|
if (itr != val2mop.end()) {
|
||||||
|
return itr->second;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
auto vr = MOperand::NewVirtReg(mc_bb->parent_func->virt_reg_cnt++);
|
||||||
|
val2mop.insert({ir_value, vr});
|
||||||
|
auto ir_func = mc_bb->parent_func->ir_func;
|
||||||
|
auto fparam_itr = FIND(ir_func->fparam_list, fparam);
|
||||||
|
assert(fparam_itr != ir_func->fparam_list.end());
|
||||||
|
auto fparam_ndx = std::distance(ir_func->fparam_list.begin(), fparam_itr);
|
||||||
|
// according to RV call conv, we can have a0-a7 for params
|
||||||
|
if (fparam_ndx < 8) {
|
||||||
|
// copy param as an vr in func entry
|
||||||
|
auto inst_move = MInstMove::New(mc_bb->parent_func->bb_list.front(), true);
|
||||||
|
inst_move->src = MOperand::NewReg(RV64_RegOffset(RV64Reg::a0, fparam_ndx));
|
||||||
|
inst_move->dst = vr;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// read from stack, sp + (i - 8) * 8, since ABI requires the stack to be aligned by XLEN=64
|
||||||
|
// this need to be further re-located since sp may have changed
|
||||||
|
// FramePtr won't get used here, for perf reason. Ref:
|
||||||
|
// https://stackoverflow.com/questions/13006371/does-omitting-the-frame-pointers-really-have-a-positive-effect-on-performance-an
|
||||||
|
// auto vr_tmp = MOperand::NewVirtReg(mc_bb->parent_func->virt_reg_cnt++);
|
||||||
|
auto inst_load = MInstLoad::New(mc_bb); // ld vr, (i-8)*8(sp)
|
||||||
|
// auto inst_move = MInstMove::New(inst_load); // lui vr_t,
|
||||||
|
inst_load->addr = MOperand::NewReg(RV64Reg::sp);
|
||||||
|
inst_load->offset = MOperand::NewImm((fparam_ndx - 8) * XLEN);
|
||||||
|
inst_load->dst = vr;
|
||||||
|
mc_bb->parent_func->stack_arg_reloc.push_back(inst_load);
|
||||||
|
}
|
||||||
|
return vr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// plain situation
|
||||||
|
auto itr = val2mop.find(ir_value);
|
||||||
|
if (itr != val2mop.end()) {
|
||||||
|
return itr->second;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
auto vr = MOperand::NewVirtReg(mc_bb->parent_func->virt_reg_cnt++);
|
||||||
|
val2mop.insert({ir_value, vr});
|
||||||
|
return vr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MCModule::IR2MC(const antlrSysY::Module &ir_module) {
|
||||||
|
for (auto glob : ir_module.global_var_list) {
|
||||||
|
// TODO copy globals from ir
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto func : ir_module.function_list) {
|
||||||
|
if (func->is_libfunc()) continue;
|
||||||
|
auto mc_func = make_shared<MFunction>();
|
||||||
|
this->function_list.push_back(mc_func);
|
||||||
|
mc_func->ir_func = func;
|
||||||
|
|
||||||
|
// copy pred/succ info
|
||||||
|
std::unordered_map<sptr(antlrSysY::BasicBlock), sptr(MBasicBlock)> bb_ir2mc;
|
||||||
|
for (auto bb : func->bb_list) {
|
||||||
|
auto mc_bb = make_shared<MBasicBlock>();
|
||||||
|
mc_func->bb_list.push_back(mc_bb);
|
||||||
|
mc_bb->ir_bb = bb;
|
||||||
|
bb_ir2mc.insert({bb, mc_bb});
|
||||||
|
}
|
||||||
|
for (auto bb : func->bb_list) {
|
||||||
|
auto mc_bb = bb_ir2mc.at(bb);
|
||||||
|
assert(bb->succ_list.size() <= 2 && "At most 2 successors");
|
||||||
|
for (auto succ : bb->succ_list) {
|
||||||
|
auto mc_succ = bb_ir2mc.at(succ);
|
||||||
|
mc_bb->succ_list.push_back(mc_succ);
|
||||||
|
}
|
||||||
|
for (auto pred : bb->pred_list) {
|
||||||
|
auto mc_pred = bb_ir2mc.at(pred);
|
||||||
|
mc_bb->pred_list.push_back(mc_pred);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// instruction translate
|
||||||
|
for (auto bb : func->bb_list) {
|
||||||
|
auto mc_bb = bb_ir2mc[bb];
|
||||||
|
for (auto inst : bb->inst_list) {
|
||||||
|
if (auto li = shared_cast<antlrSysY::InstLoad>(inst)) {
|
||||||
|
auto mc_li = MInstLoad::New(mc_bb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace codegen
|
||||||
@ -9,12 +9,12 @@ namespace antlrSysY {
|
|||||||
static void print_cfg_info(BasicBlockPtr_t bb) {
|
static void print_cfg_info(BasicBlockPtr_t bb) {
|
||||||
std::cout << "---" << bb->name << "---\n";
|
std::cout << "---" << bb->name << "---\n";
|
||||||
std::cout << " pred: [";
|
std::cout << " pred: [";
|
||||||
for (auto pred : bb->predecessors) {
|
for (auto pred : bb->pred_list) {
|
||||||
std::cout << pred->name << ", ";
|
std::cout << pred->name << ", ";
|
||||||
}
|
}
|
||||||
std::cout << "]\n";
|
std::cout << "]\n";
|
||||||
std::cout << " succ: [";
|
std::cout << " succ: [";
|
||||||
for (auto succ : bb->successors) {
|
for (auto succ : bb->succ_list) {
|
||||||
std::cout << succ->name << ", ";
|
std::cout << succ->name << ", ";
|
||||||
}
|
}
|
||||||
std::cout << "]\n";
|
std::cout << "]\n";
|
||||||
@ -25,7 +25,7 @@ static void print_cfg(BasicBlockPtr_t rt, bool rst = false) {
|
|||||||
static std::unordered_set<BasicBlockPtr_t> vis;
|
static std::unordered_set<BasicBlockPtr_t> vis;
|
||||||
if (rst) vis.clear();
|
if (rst) vis.clear();
|
||||||
print_cfg_info(rt);
|
print_cfg_info(rt);
|
||||||
for (auto succ : rt->successors) {
|
for (auto succ : rt->succ_list) {
|
||||||
if (!vis.count(succ)) {
|
if (!vis.count(succ)) {
|
||||||
vis.insert(succ);
|
vis.insert(succ);
|
||||||
print_cfg(succ);
|
print_cfg(succ);
|
||||||
@ -34,8 +34,8 @@ static void print_cfg(BasicBlockPtr_t rt, bool rst = false) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void connect(BasicBlockPtr_t pred, BasicBlockPtr_t succ) {
|
static void connect(BasicBlockPtr_t pred, BasicBlockPtr_t succ) {
|
||||||
pred->successors.push_back(succ);
|
pred->succ_list.push_back(succ);
|
||||||
succ->predecessors.push_back(pred);
|
succ->pred_list.push_back(pred);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _build_cfg(const FunctionPtr_t func) {
|
static void _build_cfg(const FunctionPtr_t func) {
|
||||||
@ -73,9 +73,9 @@ static void _build_cfg(const FunctionPtr_t func) {
|
|||||||
// remove unreachable blocks
|
// remove unreachable blocks
|
||||||
for (auto itr = std::next(func->bb_list.begin()); itr != func->bb_list.end();) {
|
for (auto itr = std::next(func->bb_list.begin()); itr != func->bb_list.end();) {
|
||||||
auto bb = *itr;
|
auto bb = *itr;
|
||||||
if (bb->predecessors.size() == 0) {
|
if (bb->pred_list.size() == 0) {
|
||||||
for (auto succ : bb->successors) {
|
for (auto succ : bb->succ_list) {
|
||||||
succ->predecessors.remove(bb);
|
succ->pred_list.remove(bb);
|
||||||
}
|
}
|
||||||
VLOG(6) << "remove unreachable block:" << bb->name;
|
VLOG(6) << "remove unreachable block:" << bb->name;
|
||||||
itr = func->bb_list.erase(itr);
|
itr = func->bb_list.erase(itr);
|
||||||
|
|||||||
@ -94,7 +94,7 @@ static void live_in_blocks(
|
|||||||
if (!livein_blocks.insert(bb).second) continue; // already done
|
if (!livein_blocks.insert(bb).second) continue; // already done
|
||||||
// 如果alloca没有在某个块中被定义,那么它一定是从前面的某个块里面live in过来的
|
// 如果alloca没有在某个块中被定义,那么它一定是从前面的某个块里面live in过来的
|
||||||
// 所以把它也塞进队列进行处理
|
// 所以把它也塞进队列进行处理
|
||||||
for (auto pred : bb->predecessors) {
|
for (auto pred : bb->pred_list) {
|
||||||
if (def_blocks.count(pred)) continue;
|
if (def_blocks.count(pred)) continue;
|
||||||
worklist.push_back(pred);
|
worklist.push_back(pred);
|
||||||
}
|
}
|
||||||
@ -111,12 +111,12 @@ static void print_dom_info(BasicBlockPtr_t bb) {
|
|||||||
std::cout << bb->name << ":\n";
|
std::cout << bb->name << ":\n";
|
||||||
std::cout << " level: " << bb->dom_level << "\n";
|
std::cout << " level: " << bb->dom_level << "\n";
|
||||||
std::cout << " pred: [";
|
std::cout << " pred: [";
|
||||||
for (auto pred : bb->predecessors) {
|
for (auto pred : bb->pred_list) {
|
||||||
std::cout << pred->name << ", ";
|
std::cout << pred->name << ", ";
|
||||||
}
|
}
|
||||||
std::cout << "]\n";
|
std::cout << "]\n";
|
||||||
std::cout << " succ: [";
|
std::cout << " succ: [";
|
||||||
for (auto succ : bb->successors) {
|
for (auto succ : bb->succ_list) {
|
||||||
std::cout << succ->name << ", ";
|
std::cout << succ->name << ", ";
|
||||||
}
|
}
|
||||||
std::cout << "]\n";
|
std::cout << "]\n";
|
||||||
@ -236,7 +236,7 @@ static void _mem_2_reg(FunctionPtr_t func) {
|
|||||||
visited[frontier_index] = true;
|
visited[frontier_index] = true;
|
||||||
// livein-block opt is workable in IDF, but not here
|
// livein-block opt is workable in IDF, but not here
|
||||||
// if (livein_blocks.count(frontier)) {
|
// if (livein_blocks.count(frontier)) {
|
||||||
auto inst_phi = build_InstPhi(TypeHelper::TYPE_I32, frontier->predecessors, frontier, ai->name);
|
auto inst_phi = build_InstPhi(TypeHelper::TYPE_I32, frontier->pred_list, frontier, ai->name);
|
||||||
phi_to_allocaid.insert({inst_phi, i});
|
phi_to_allocaid.insert({inst_phi, i});
|
||||||
// }
|
// }
|
||||||
if (!def_blocks.count(frontier)) {
|
if (!def_blocks.count(frontier)) {
|
||||||
@ -263,7 +263,7 @@ static void _mem_2_reg(FunctionPtr_t func) {
|
|||||||
auto phi = Value::as<InstPhi>(inst);
|
auto phi = Value::as<InstPhi>(inst);
|
||||||
auto alloca_index = phi_to_allocaid.at(phi);
|
auto alloca_index = phi_to_allocaid.at(phi);
|
||||||
int pred_index = -1;
|
int pred_index = -1;
|
||||||
for (auto pred : rename_info.bb->predecessors) {
|
for (auto pred : rename_info.bb->pred_list) {
|
||||||
pred_index++;
|
pred_index++;
|
||||||
if (pred == rename_info.pred) break;
|
if (pred == rename_info.pred) break;
|
||||||
}
|
}
|
||||||
@ -315,7 +315,7 @@ static void _mem_2_reg(FunctionPtr_t func) {
|
|||||||
rename_info.value_list[alloca_index] = phi;
|
rename_info.value_list[alloca_index] = phi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto succ : rename_info.bb->successors) {
|
for (auto succ : rename_info.bb->succ_list) {
|
||||||
rename_list.push_back({succ, rename_info.bb, rename_info.value_list});
|
rename_list.push_back({succ, rename_info.bb, rename_info.value_list});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -150,7 +150,7 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
|
|||||||
if (block_itr != block_list.begin()) {
|
if (block_itr != block_list.begin()) {
|
||||||
ostr << block->ir_seqno << ":";
|
ostr << block->ir_seqno << ":";
|
||||||
ostr << " ;" << block->name << " pred=[";
|
ostr << " ;" << block->name << " pred=[";
|
||||||
for (auto pred : block->predecessors) {
|
for (auto pred : block->pred_list) {
|
||||||
ostr << pred->ir_seqno << ", ";
|
ostr << pred->ir_seqno << ", ";
|
||||||
}
|
}
|
||||||
ostr << "]" << std::endl;
|
ostr << "]" << std::endl;
|
||||||
@ -460,7 +460,7 @@ static void _gen_blocks(std::ostream &ostr, const std::list<BasicBlockPtr_t> &bl
|
|||||||
LOG(WARNING) << "Unexpected type of op: " << op->to_string();
|
LOG(WARNING) << "Unexpected type of op: " << op->to_string();
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
auto pred = inst->parent_bb->predecessors.begin();
|
auto pred = inst->parent_bb->pred_list.begin();
|
||||||
std::advance(pred, i);
|
std::advance(pred, i);
|
||||||
ostr << ", %" << (*pred)->ir_seqno << "]";
|
ostr << ", %" << (*pred)->ir_seqno << "]";
|
||||||
if (i < inst->operand_list.size() - 1) {
|
if (i < inst->operand_list.size() - 1) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user