use sp to find local

This commit is contained in:
Yaossg 2024-11-29 09:49:57 +08:00
parent 2097d9fd34
commit 44051c7985
2 changed files with 91 additions and 64 deletions

143
boot.c
View File

@ -429,8 +429,8 @@ int parse_type() {
int epilog_label; int epilog_label;
int local_table[4096]; // id -> local id int local_table[4096]; // id -> local id
int next_local_id = 12; int next_local_id = 1;
int max_local_id = 12; int max_local_id = 1;
const int MARKER_TEMP = 0; const int MARKER_TEMP = 0;
const int MARKER_SCALAR = 1; const int MARKER_SCALAR = 1;
@ -534,8 +534,9 @@ int is_overflow(int reg) {
} }
void reset_local() { void reset_local() {
next_local_id = 12; next_local_id = 1;
max_local_id = 12; max_local_id = 1;
max_reg_id = REG_S2;
for (int i = 0; i < 4096; ++i) { for (int i = 0; i < 4096; ++i) {
local_table[i] = 0; local_table[i] = 0;
local_marker[i] = MARKER_TEMP; local_marker[i] = MARKER_TEMP;
@ -545,7 +546,7 @@ void reset_local() {
} }
void reset_temp() { void reset_temp() {
while (next_local_id > 12 && local_marker[next_local_id - 1] == MARKER_TEMP) { while (next_local_id > 1 && local_marker[next_local_id - 1] == MARKER_TEMP) {
--next_local_id; --next_local_id;
} }
reset_reg(); reset_reg();
@ -569,8 +570,9 @@ int declare_local(int id, int type) {
int declare_local_array(int id, int type, int size) { int declare_local_array(int id, int type, int size) {
if (local_table[id] != 0) return local_table[id]; if (local_table[id] != 0) return local_table[id];
int slot; int slot = next_local_slot(type);
for (int i = 0; i < size; ++i) local_marker[slot = next_local_slot(type)] = MARKER_ARRAY; local_marker[slot] = MARKER_ARRAY;
for (int i = 1; i < size; ++i) local_marker[next_local_slot(type)] = MARKER_ARRAY;
return local_table[id] = slot; return local_table[id] = slot;
} }
@ -632,21 +634,19 @@ void asm_addi(const char* rd, const char* rs, int imm) {
// assembly helpers // assembly helpers
// address loaders // address loaders
// rd must be one of 0, 1, 2 // rd must be one of t0, t1, t2
void load_local_address(int rd, int slot_id) { void load_local_address(int rd, int slot_id) {
// TODO use sp instead int offset = slot_id * 8 - 8;
int offset = -slot_id * 8 - 8;
const char* rd_name = reg_name(rd); const char* rd_name = reg_name(rd);
if (check_itype_immediate(offset)) { if (check_itype_immediate(offset)) {
printf(" addi %s, fp, %d\n", rd_name, offset); printf(" addi %s, sp, %d\n", rd_name, offset);
} else { } else {
printf(" li %s, %d\n", rd_name, offset); printf(" li %s, %d\n", rd_name, offset);
printf(" add %s, fp, %s\n", rd_name, rd_name); printf(" add %s, sp, %s\n", rd_name, rd_name);
} }
} }
const char* load_op(int reg) { const char* load_op_of_type(int type) {
int type = reg_type[reg];
if (type & TYPE_PTR_MASK) { if (type & TYPE_PTR_MASK) {
return "ld"; return "ld";
} else if (type == TYPE_CHAR) { } else if (type == TYPE_CHAR) {
@ -666,14 +666,10 @@ const char* store_op_of_type(int type) {
} }
} }
const char* store_op(int reg) {
return store_op_of_type(reg_type[reg]);
}
// load a non-trivial register into t0, t1 or t2 // load a non-trivial register into t0, t1 or t2
// rd must be one of t0, t1, t2 // rd must be one of t0, t1, t2
void load(int rd, int reg) { void load(int rd, int reg) {
const char* op = load_op(reg); const char* op = load_op_of_type(reg_type[reg]);
const char* rd_name = reg_name(rd); const char* rd_name = reg_name(rd);
if (is_overflow(reg)) { if (is_overflow(reg)) {
load_local_address(rd, overflow[reg]); load_local_address(rd, overflow[reg]);
@ -687,7 +683,7 @@ void load(int rd, int reg) {
// store t0 into a non-trivial register // store t0 into a non-trivial register
void store_t0(int reg) { void store_t0(int reg) {
const char* op = store_op(reg); const char* op = store_op_of_type(reg_type[reg]);
if (is_overflow(reg)) { if (is_overflow(reg)) {
load_local_address(REG_T2, overflow[reg]); load_local_address(REG_T2, overflow[reg]);
if (indirection[reg]) { if (indirection[reg]) {
@ -710,7 +706,8 @@ void _asm_r(const char* op, int rd, int rs1) {
rs1_name = "t0"; rs1_name = "t0";
load(REG_T0, rs1); load(REG_T0, rs1);
} }
printf(" %s %s, %s\n", op, rd_name, rs1_name); if (!(streq(op, "mv") && streq(rd_name, rs1_name)))
printf(" %s %s, %s\n", op, rd_name, rs1_name);
if (is_nontrivial(rd)) { if (is_nontrivial(rd)) {
store_t0(rd); store_t0(rd);
} }
@ -758,14 +755,26 @@ void _asm_branch(const char* op, int rs1, int label) {
printf(" %s %s, L%d\n", op, rs1_name, label); printf(" %s %s, L%d\n", op, rs1_name, label);
} }
void _asm_i(const char* op, int rd, const char* prefix1, const char* prefix2, int imm) {
const char* rd_name = reg_name(rd);
if (is_nontrivial(rd)) rd_name = "t0";
printf(" %s %s, %s%s%d\n", op, rd_name, prefix1, prefix2, imm);
if (is_nontrivial(rd)) {
store_t0(rd);
}
}
int asm_r(int type, const char* op, int rs1) { int asm_r(int type, const char* op, int rs1) {
int rd = next_reg(type); int rd = rs1;
if (indirection[rs1] || reg_type[rs1] != type) rd = next_reg(type);
_asm_r(op, rd, rs1); _asm_r(op, rd, rs1);
return rd; return rd;
} }
int asm_rr(int type, const char* op, int rs1, int rs2) { int asm_rr(int type, const char* op, int rs1, int rs2) {
int rd = next_reg(type); int rd = rs1;
if (indirection[rs1] || reg_type[rs1] != type) rd = rs2;
if (indirection[rs2] || reg_type[rs2] != type) rd = next_reg(type);
_asm_rr(op, rd, rs1, rs2); _asm_rr(op, rd, rs1, rs2);
return rd; return rd;
} }
@ -774,25 +783,34 @@ void asm_mv(int rd, int rs1) {
_asm_r("mv", rd, rs1); _asm_r("mv", rd, rs1);
} }
int materialize_t0(int type) { void store_into_local(int rs1, int slot) {
int rd = next_reg(type); const char* rs1_name = reg_name(rs1);
asm_mv(rd, REG_T0); if (is_nontrivial(rs1)) {
return rd; rs1_name = "t0";
load(REG_T0, rs1);
}
load_local_address(REG_T2, slot);
printf(" %s %s, 0(t2)\n", store_op_of_type(local_type[slot]), rs1_name);
} }
int materialize_address(int type, int marker) { int materialize_address(int rd, int type, int marker) {
if (marker == MARKER_ARRAY) { if (marker == MARKER_ARRAY) {
type = type | TYPE_PTR_MASK; type = type | TYPE_PTR_MASK;
} }
int rd = materialize_t0(TYPE_VOID_PTR);
reg_type[rd] = type; reg_type[rd] = type;
indirection[rd] = marker == MARKER_SCALAR; indirection[rd] = marker == MARKER_SCALAR;
return rd; return rd;
} }
int lookup_from_slot(int slot) { int lookup_from_slot(int slot) {
load_local_address(REG_T0, slot); int reg = next_reg(TYPE_VOID_PTR);
return materialize_address(local_type[slot], local_marker[slot]); if (is_nontrivial(reg)) {
load_local_address(REG_T0, slot);
asm_mv(reg, REG_T0);
} else {
load_local_address(reg, slot);
}
return materialize_address(reg, local_type[slot], local_marker[slot]);
} }
int lookup(int id) { int lookup(int id) {
@ -805,9 +823,10 @@ int lookup(int id) {
if (global_marker[id] == MARKER_FUNCTION) { if (global_marker[id] == MARKER_FUNCTION) {
eprintf("function name must not appear outside function call: %s\n", name); eprintf("function name must not appear outside function call: %s\n", name);
exit(1); exit(1);
} }
printf(" la t0, %s # id: %d\n", name, id); int reg = next_reg(TYPE_VOID_PTR);
return materialize_address(global_type[id], global_marker[id]); _asm_i("la", reg, name, " # id: ", id);
return materialize_address(reg, global_type[id], global_marker[id]);
} }
eprintf("unresolved identifier: %s\n", name); eprintf("unresolved identifier: %s\n", name);
exit(1); exit(1);
@ -933,8 +952,8 @@ int asm_sub(int lhs, int rhs) {
} }
int difference = asm_rr(TYPE_INT, "sub", lhs, rhs); int difference = asm_rr(TYPE_INT, "sub", lhs, rhs);
int shift = 2 * (lhs_type == TYPE_INT_PTR); int shift = 2 * (lhs_type == TYPE_INT_PTR);
_asm_ri("slli", REG_T0, difference, shift); _asm_ri("slli", difference, difference, shift);
return materialize_t0(TYPE_INT); return difference;
} }
if (type1) { if (type1) {
int neg = asm_r_arith("neg", rhs); int neg = asm_r_arith("neg", rhs);
@ -998,13 +1017,12 @@ int parse_function_call(int id) {
for (int i = 0; i < arg; ++i) { for (int i = 0; i < arg; ++i) {
asm_mv(i + REG_A0, args[i]); asm_mv(i + REG_A0, args[i]);
} }
// TODO saved by caller
printf(" call %s\n", name); printf(" call %s\n", name);
// TODO saved by caller
int type = global_type[id]; int type = global_type[id];
if (type != TYPE_VOID) { if (type != TYPE_VOID) {
printf(" mv t0, a0\n"); int rd = next_reg(type);
return materialize_t0(type); asm_mv(rd, REG_A0);
return rd;
} }
return -1; return -1;
} }
@ -1014,8 +1032,9 @@ int parse_primary_expr() {
if (token_type == TOKEN_EOF) { if (token_type == TOKEN_EOF) {
exit(1); exit(1);
} else if (token_type == TOKEN_NUMBER) { } else if (token_type == TOKEN_NUMBER) {
printf(" li t0, %d\n", token_data); int reg = next_reg(TYPE_INT);
return materialize_t0(TYPE_INT); _asm_i("li", reg, "", "", token_data);
return reg;
} else if (token_type == TOKEN_ID) { } else if (token_type == TOKEN_ID) {
next_token(); next_token();
if (token_type == TOKEN_PAREN_LEFT) { if (token_type == TOKEN_PAREN_LEFT) {
@ -1024,8 +1043,9 @@ int parse_primary_expr() {
unget_token(); unget_token();
return lookup(token_data); return lookup(token_data);
} else if (token_type == TOKEN_STRING) { } else if (token_type == TOKEN_STRING) {
printf(" la t0, .LC%d\n", token_data); int reg = next_reg(TYPE_CHAR_PTR);
return materialize_t0(TYPE_CHAR_PTR); _asm_i("la", reg, ".LC", "", token_data);
return reg;
} else if (token_type == TOKEN_PAREN_LEFT) { } else if (token_type == TOKEN_PAREN_LEFT) {
int reg = parse_expr(); int reg = parse_expr();
expect_token(TOKEN_PAREN_RIGHT); expect_token(TOKEN_PAREN_RIGHT);
@ -1343,7 +1363,7 @@ void parse_local_variable(int type) {
next_token(); next_token();
if (token_type == TOKEN_BRACKET_LEFT) { if (token_type == TOKEN_BRACKET_LEFT) {
if (type & TYPE_PTR_MASK) { if (type & TYPE_PTR_MASK) {
eprintf("local variable of array of pointers is not supported\n"); eprintf("array of pointers is not supported\n");
exit(1); exit(1);
} }
expect_token(TOKEN_NUMBER); expect_token(TOKEN_NUMBER);
@ -1364,9 +1384,7 @@ void parse_local_variable(int type) {
eprintf("type mismatch in assignment\n"); eprintf("type mismatch in assignment\n");
exit(1); exit(1);
} }
asm_mv(REG_T0, reg); store_into_local(reg, slot);
load_local_address(REG_T2, slot);
printf(" %s t0, 0(t2)\n", store_op_of_type(type));
} }
void parse_stmt(); void parse_stmt();
@ -1533,7 +1551,7 @@ void parse_function(const char* name) {
expect_token(TOKEN_BRACKET_RIGHT); expect_token(TOKEN_BRACKET_RIGHT);
next_token(); next_token();
if (arg_type & TYPE_PTR_MASK) { if (arg_type & TYPE_PTR_MASK) {
eprintf("local variable of array of pointers is not supported\n"); eprintf("array of pointers is not supported\n");
exit(1); exit(1);
} }
arg_type = arg_type | TYPE_PTR_MASK; arg_type = arg_type | TYPE_PTR_MASK;
@ -1571,7 +1589,9 @@ void parse_function(const char* name) {
parse_stmt(); parse_stmt();
} }
asm_j(epilog_label); asm_j(epilog_label);
int frame_size = max_local_id * 8; int reg_used = max_reg_id - REG_S2;
if (reg_used > 10) reg_used = 10;
int frame_size = (max_local_id - 1 + reg_used + 2) * 8;
if (frame_size % 16 != 0) { if (frame_size % 16 != 0) {
frame_size = frame_size + 8; frame_size = frame_size + 8;
} }
@ -1580,22 +1600,22 @@ void parse_function(const char* name) {
asm_addi("sp", "sp", -frame_size); asm_addi("sp", "sp", -frame_size);
asm_sd("ra", frame_size - 8, "sp"); asm_sd("ra", frame_size - 8, "sp");
asm_sd("fp", frame_size - 16, "sp"); asm_sd("fp", frame_size - 16, "sp");
for (int reg = REG_S2; reg <= REG_S11; ++reg) { for (int i = 0; i < reg_used; ++i) {
asm_sd(reg_name(reg), frame_size - reg * 8 + 15 * 8, "sp"); int reg = REG_S2 + i;
asm_sd(reg_name(reg), frame_size - 24 - i * 8, "sp");
} }
asm_addi("fp", "sp", frame_size); asm_addi("fp", "sp", frame_size);
for (int i = 0; i < arg; ++i) { for (int i = 0; i < arg; ++i) {
int slot = args[i]; store_into_local(REG_A0 + i, args[i]);
load_local_address(REG_T2, slot);
printf(" %s a%d, 0(t2)\n", store_op_of_type(local_type[slot]), i);
} }
asm_j(label); asm_j(label);
// epilog // epilog
asm_label(epilog_label); asm_label(epilog_label);
asm_ld("ra", frame_size - 8, "sp"); asm_ld("ra", frame_size - 8, "sp");
asm_ld("fp", frame_size - 16, "sp"); asm_ld("fp", frame_size - 16, "sp");
for (int reg = REG_S2; reg <= REG_S11; ++reg) { for (int i = 0; i < reg_used; ++i) {
asm_ld(reg_name(reg), frame_size - reg * 8 + 15 * 8, "sp"); int reg = REG_S2 + i;
asm_ld(reg_name(reg), frame_size - 24 - i * 8, "sp");
} }
asm_addi("sp", "sp", frame_size); asm_addi("sp", "sp", frame_size);
printf(" ret\n"); printf(" ret\n");
@ -1606,10 +1626,6 @@ void parse_global_variable(int id, const char* name, int type) {
eprintf("global variable of void type is not supported\n"); eprintf("global variable of void type is not supported\n");
exit(1); exit(1);
} }
if (type & TYPE_PTR_MASK) {
eprintf("global variable of pointer is not supported\n");
exit(1);
}
printf(".data\n"); printf(".data\n");
printf(".globl %s\n", name); printf(".globl %s\n", name);
printf(".align 5\n"); printf(".align 5\n");
@ -1618,6 +1634,10 @@ void parse_global_variable(int id, const char* name, int type) {
expect_token(TOKEN_NUMBER); expect_token(TOKEN_NUMBER);
printf(" .word %d\n", token_data); printf(" .word %d\n", token_data);
} else if (token_type == TOKEN_BRACKET_LEFT) { } else if (token_type == TOKEN_BRACKET_LEFT) {
if (type & TYPE_PTR_MASK) {
eprintf("array of pointers is not supported\n");
exit(1);
}
expect_token(TOKEN_NUMBER); expect_token(TOKEN_NUMBER);
int size = token_data; int size = token_data;
expect_token(TOKEN_BRACKET_RIGHT); expect_token(TOKEN_BRACKET_RIGHT);
@ -1691,7 +1711,6 @@ void dump_string_table() {
} }
int main() { int main() {
eprintf("start compiling...\n");
parse_top_level(); parse_top_level();
dump_string_table(); dump_string_table();
return 0; return 0;

View File

@ -2,8 +2,16 @@ int printf(const char format[], ...);
int scanf(const char format[], ...); int scanf(const char format[], ...);
int putchar(int ch); int putchar(int ch);
int* p;
int f1() {
int a = 1;
return *(a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(p))))))))))); // a[10]
}
int main() { int main() {
int a = 1; int a[15];
return (a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a))))))))))); p = a;
for (int i = 0; i < 15; ++i) a[i] = i;
return f1();
} }