Commit e23c2e2e authored by lxq's avatar lxq

finish argument pass, need to do float part

parent b4870a73
...@@ -132,6 +132,8 @@ op6: <8, 8> ...@@ -132,6 +132,8 @@ op6: <8, 8>
这实际是指令选择部分的内容: 这实际是指令选择部分的内容:
因为在cminus中并没有bool变量,这些IR指令用到的i1类型都是临时的:只为分支指令服务,所以直接将这些指令集成到分支跳转的判断中。 因为在cminus中并没有bool变量,这些IR指令用到的i1类型都是临时的:只为分支指令服务,所以直接将这些指令集成到分支跳转的判断中。
一个例外是隐式的类型转化,将比较的结果`i1`隐式转换为`i32`,此时是`zext`指令与`cmp`捆绑,特殊为`zext`指令分配寄存器。
- `call`指令:使用栈传参,caller保存自己用到的寄存器,被保存的寄存器的活跃区间覆盖`call`指令的程序点。 - `call`指令:使用栈传参,caller保存自己用到的寄存器,被保存的寄存器的活跃区间覆盖`call`指令的程序点。
......
...@@ -11,10 +11,12 @@ ...@@ -11,10 +11,12 @@
#include "liverange.hpp" #include "liverange.hpp"
#include "regalloc.hpp" #include "regalloc.hpp"
#include <functional>
#include <string> #include <string>
#define __PRINT_ORI__ #define __PRINT_ORI__
#define __RO_PART__ #define __RO_PART__
#define __PRINT_COMMENT__
// #a = 8, #t = 9, reserve $t0, $t1 for temporary // #a = 8, #t = 9, reserve $t0, $t1 for temporary
#define R_USABLE 17 - 2 #define R_USABLE 17 - 2
#define ARG_R 8 #define ARG_R 8
...@@ -27,6 +29,11 @@ ...@@ -27,6 +29,11 @@
// #define STACK_ALIGN(x) (((x / 16) + (x % 16 ? 1 : 0)) * 16) // #define STACK_ALIGN(x) (((x / 16) + (x % 16 ? 1 : 0)) * 16)
#define STACK_ALIGN(x) ALIGN(x, 16) #define STACK_ALIGN(x) ALIGN(x, 16)
#define CONST_0 ConstantInt::get(0, m)
#define FP "$fp"
#define SP "$sp"
#define RA_reg "$ra"
using std::map; using std::map;
using std::string; using std::string;
using std::vector; using std::vector;
...@@ -38,6 +45,10 @@ class CodeGen { ...@@ -38,6 +45,10 @@ class CodeGen {
string print() { string print() {
string result; string result;
for (auto line : output) { for (auto line : output) {
#ifndef __PRINT_COMMENT__
if (line.find("#") != string::npos)
continue;
#endif
if (line.find(":") == string::npos and line != "") if (line.find(":") == string::npos and line != "")
result += "\t"; // 添加缩进 result += "\t"; // 添加缩进
result += line + "\n"; result += line + "\n";
...@@ -58,6 +69,7 @@ class CodeGen { ...@@ -58,6 +69,7 @@ class CodeGen {
std::map<BasicBlock *, std::vector<std::pair<Value *, Value *>>> phi_map; std::map<BasicBlock *, std::vector<std::pair<Value *, Value *>>> phi_map;
std::map<Constant *, std::string> ROdata; std::map<Constant *, std::string> ROdata;
unsigned int stackN; // function local vars and so on unsigned int stackN; // function local vars and so on
uint cmp_zext_cnt;
Function *cur_func; Function *cur_func;
...@@ -79,11 +91,16 @@ class CodeGen { ...@@ -79,11 +91,16 @@ class CodeGen {
// In the case of register allocation, this function will return the // In the case of register allocation, this function will return the
// allocated register for that value, if the value possesses no register, // allocated register for that value, if the value possesses no register,
// choose from from $t0 or $t1 based on id, or the input string(not "") // choose from from $t0 or $t1 based on id, or the input string(not "")
__attribute__((warn_unused_result)) string value2reg(Value *, int i = 0, string = ""); __attribute__((warn_unused_result)) string value2reg(Value *,
int i = 0,
string = "");
// load the content in ptr to specified register. // load the content in ptr to specified register.
void ptrContent2reg(Value *, string); void ptrContent2reg(Value *, string);
void pass_arguments(CallInst *);
void compute_arg_info(Function *); void compute_arg_info(Function *);
string bool2branch(Instruction *); string bool2branch(Instruction *);
void getPhiMap(); void getPhiMap();
void copystmt(BasicBlock *bb) { void copystmt(BasicBlock *bb) {
// all the phi instruction is transformed to copy-stmt // all the phi instruction is transformed to copy-stmt
...@@ -97,6 +114,26 @@ class CodeGen { ...@@ -97,6 +114,26 @@ class CodeGen {
} }
} }
// this is a decorated version of push_back, it checks intermediat number in
// the instruction, make sure imm will not overflow
void makeSureInRange(string instr_ir,
string reg1,
string reg2,
int imm,
string tinstr,
int bits = 12,
string treg = "$t0",
bool u = false) {
auto [l, h] = immRange(bits, u);
if (l <= imm and imm <= h)
output.push_back(instr_ir + " " + reg1 + ", " + reg2 + ", " +
to_string(imm));
else {
assert(value2reg(ConstantInt::get(imm, m), 0, treg) == treg);
output.push_back(tinstr + " " + reg1 + ", " + reg2 + ", " + treg);
}
}
// if reg-allocation, store to the specific register // if reg-allocation, store to the specific register
// or is stack-allocation, set last_reg for back2stack() // or is stack-allocation, set last_reg for back2stack()
bool gencopy(Value *lhs, string rhs_reg) { bool gencopy(Value *lhs, string rhs_reg) {
...@@ -122,7 +159,7 @@ class CodeGen { ...@@ -122,7 +159,7 @@ class CodeGen {
string label_in_assem(BasicBlock *bb) const { string label_in_assem(BasicBlock *bb) const {
return cur_func->get_name() + bb->get_name().substr(5); return cur_func->get_name() + bb->get_name().substr(5);
} }
int typeLen(Type *type) const { static int typeLen(Type *type) {
if (type->is_float_type()) if (type->is_float_type())
return 4; return 4;
else if (type->is_integer_type()) { else if (type->is_integer_type()) {
...@@ -149,11 +186,16 @@ class CodeGen { ...@@ -149,11 +186,16 @@ class CodeGen {
string instr_ir = type->is_float_type() ? "fst" : "st"; string instr_ir = type->is_float_type() ? "fst" : "st";
string suff = suffix(type); string suff = suffix(type);
// string reg = type->is_float_type() ? "$fa0" : "$a0"; // string reg = type->is_float_type() ? "$fa0" : "$a0";
string addr = "$fp, -" + std::to_string(off.at(instr)); makeSureInRange(instr_ir + suff,
output.push_back(instr_ir + suff + " " + last_reg + ", " + addr); last_reg,
FP,
-off.at(instr),
instr_ir + "x" + suff);
// string addr = "$fp, -" + std::to_string(off.at(instr));
// output.push_back(instr_ir + suff + " " + last_reg + ", " + addr);
} }
string suffix(Type *type) const { static string suffix(Type *type) {
int len = typeLen(type); int len = typeLen(type);
switch (len) { switch (len) {
case 1: case 1:
...@@ -198,6 +240,20 @@ class CodeGen { ...@@ -198,6 +240,20 @@ class CodeGen {
return name; return name;
} }
static pair<int, int> immRange(int bit, bool u) {
pair<int, int> res;
if (u) {
res.first = 0;
res.second = (1 << bit) - 1;
} else {
bit--;
res.first = -(1 << bit);
res.second = (1 << bit) - 1;
}
return res;
};
pair<string, bool> getRegName(Value *, int = 0) const; pair<string, bool> getRegName(Value *, int = 0) const;
void IR2assem(Instruction &, BasicBlock &); void IR2assem(Instruction &, BasicBlock &);
...@@ -211,12 +267,12 @@ class CodeGen { ...@@ -211,12 +267,12 @@ class CodeGen {
void IR2assem(FpToSiInst *); void IR2assem(FpToSiInst *);
void IR2assem(SiToFpInst *); void IR2assem(SiToFpInst *);
void IR2assem(PhiInst *) {} void IR2assem(PhiInst *) {}
void IR2assem(ZextInst *);
// The Instructions below will do nothing // The Instructions below will do nothing
void IR2assem(AllocaInst *) {} void IR2assem(AllocaInst *) {}
// integration with BranchInst // integration with BranchInst and ZextInst
void IR2assem(CmpInst *) {} void IR2assem(CmpInst *) {}
void IR2assem(FCmpInst *) {} void IR2assem(FCmpInst *) {}
void IR2assem(ZextInst *) {}
}; };
#endif #endif
...@@ -20,7 +20,7 @@ using std::vector; ...@@ -20,7 +20,7 @@ using std::vector;
namespace LRA { namespace LRA {
struct Interval { struct Interval {
Interval(int a = 0, int b = 0) : i(a), j(b) {} Interval(int a = -1, int b = -1) : i(a), j(b) {}
int i; // 0 means uninitialized int i; // 0 means uninitialized
int j; int j;
}; };
......
...@@ -34,13 +34,15 @@ main(int argc, char **argv) { ...@@ -34,13 +34,15 @@ main(int argc, char **argv) {
bool gvn = false; bool gvn = false;
bool dump_json = false; bool dump_json = false;
bool emit = false; bool emit = false;
bool assembly = true; bool assembly = false;
for (int i = 1; i < argc; ++i) { for (int i = 1; i < argc; ++i) {
if (argv[i] == "-h"s || argv[i] == "--help"s) { if (argv[i] == "-h"s || argv[i] == "--help"s) {
print_help(argv[0]); print_help(argv[0]);
return 0; return 0;
} else if (argv[i] == "-o"s || argv[i] == "-S"s) { } else if (argv[i] == "-o"s || argv[i] == "-S"s) {
if (argv[i] == "-S"s)
assembly = true;
if (target_path.empty() && i + 1 < argc) { if (target_path.empty() && i + 1 < argc) {
target_path = argv[i + 1]; target_path = argv[i + 1];
if (target_path.rfind(".") != std::string::npos) if (target_path.rfind(".") != std::string::npos)
...@@ -54,8 +56,6 @@ main(int argc, char **argv) { ...@@ -54,8 +56,6 @@ main(int argc, char **argv) {
emit = true; emit = true;
} else if (argv[i] == "-mem2reg"s) { } else if (argv[i] == "-mem2reg"s) {
mem2reg = true; mem2reg = true;
} else if (argv[i] == "-S"s) {
assembly = true;
} else if (argv[i] == "-gvn"s) { } else if (argv[i] == "-gvn"s) {
gvn = true; gvn = true;
} else if (argv[i] == "-dump-json"s) { } else if (argv[i] == "-dump-json"s) {
...@@ -123,6 +123,7 @@ main(int argc, char **argv) { ...@@ -123,6 +123,7 @@ main(int argc, char **argv) {
auto IR = m->print(); auto IR = m->print();
if (assembly) { if (assembly) {
CodeGen codegen(m.get()); CodeGen codegen(m.get());
codegen.run(); codegen.run();
std::ofstream target_file(target_path + ".s"); std::ofstream target_file(target_path + ".s");
......
This diff is collapsed.
...@@ -124,10 +124,13 @@ LiveRangeAnalyzer::run(Function *func) { ...@@ -124,10 +124,13 @@ LiveRangeAnalyzer::run(Function *func) {
} }
} }
} }
// argument should be in the IN-set of Entry
for (auto arg : func->get_args())
IN[1].insert(arg);
make_interval(func); make_interval(func);
#ifdef __LRA_PRINT__ #ifdef __LRA_PRINT__
print(func, false, true); print(func, true, true);
#endif #endif
} }
...@@ -136,20 +139,20 @@ LiveRangeAnalyzer::make_interval(Function *) { ...@@ -136,20 +139,20 @@ LiveRangeAnalyzer::make_interval(Function *) {
for (int time = 1; time <= ir_cnt; ++time) { for (int time = 1; time <= ir_cnt; ++time) {
for (auto op : IN.at(time)) { for (auto op : IN.at(time)) {
auto &interval = intervalmap[op]; auto &interval = intervalmap[op];
if (interval.i == 0) // uninitialized if (interval.i == -1) // uninitialized
interval.i = time - 1; interval.i = time - 1;
else else
interval.j = time - 1; interval.j = time - 1;
} }
for (auto op : OUT.at(time)) { for (auto op : OUT.at(time)) {
auto &interval = intervalmap[op]; auto &interval = intervalmap[op];
if (interval.i == 0) // uninitialized if (interval.i == -1) // uninitialized
interval.i = time; interval.i = time;
else else
interval.j = time; interval.j = time;
} }
} }
for (auto [op, interval] : intervalmap) for (auto &[op, interval] : intervalmap)
liveIntervals.insert({interval, op}); liveIntervals.insert({interval, op});
} }
......
...@@ -26,10 +26,30 @@ bool ...@@ -26,10 +26,30 @@ bool
RegAllocator::no_reg_alloca(Value *v) const { RegAllocator::no_reg_alloca(Value *v) const {
auto instr = dynamic_cast<Instruction *>(v); auto instr = dynamic_cast<Instruction *>(v);
auto arg = dynamic_cast<Argument *>(v); auto arg = dynamic_cast<Argument *>(v);
if (instr) if (instr) {
return instr->is_alloca() or instr->is_cmp() or instr->is_fcmp() or // never allocate register
instr->is_zext(); if (instr->is_alloca() or instr->is_cmp() or instr->is_fcmp())
if (arg) { return true;
else if (instr->is_zext()) { // only alloca for true use
for (auto use : instr->get_use_list())
if (not dynamic_cast<Instruction *>(use.val_)->is_br()) {
auto instr = static_cast<Instruction *>(use.val_);
if (instr->is_cmp()) { // special case for cmp again
auto cmp = static_cast<CmpInst *>(instr);
assert(cmp->get_cmp_op() == CmpInst::NE);
auto uses = instr->get_use_list();
assert(uses.size() == 1 and
dynamic_cast<Instruction *>(uses.begin()->val_)
->is_br());
} else
return false;
}
return true;
} else // then always allocate
return false;
}
if (arg) { // only allocate for the first 8 args
return get_arg_id(arg) > ARG_MAX_R; return get_arg_id(arg) > ARG_MAX_R;
} else } else
assert(false && "only instruction and argument's LiveInterval exits"); assert(false && "only instruction and argument's LiveInterval exits");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment