From 44051c7985a020bbe8d80e07cba18f92e64390c2 Mon Sep 17 00:00:00 2001 From: Yaossg Date: Fri, 29 Nov 2024 09:49:57 +0800 Subject: [PATCH] use sp to find local --- boot.c | 143 ++++++++++++++++++++++++++++++----------------------- demo/add.c | 12 ++++- 2 files changed, 91 insertions(+), 64 deletions(-) diff --git a/boot.c b/boot.c index 3dbf328..a7b16de 100644 --- a/boot.c +++ b/boot.c @@ -429,8 +429,8 @@ int parse_type() { int epilog_label; int local_table[4096]; // id -> local id -int next_local_id = 12; -int max_local_id = 12; +int next_local_id = 1; +int max_local_id = 1; const int MARKER_TEMP = 0; const int MARKER_SCALAR = 1; @@ -534,8 +534,9 @@ int is_overflow(int reg) { } void reset_local() { - next_local_id = 12; - max_local_id = 12; + next_local_id = 1; + max_local_id = 1; + max_reg_id = REG_S2; for (int i = 0; i < 4096; ++i) { local_table[i] = 0; local_marker[i] = MARKER_TEMP; @@ -545,7 +546,7 @@ void reset_local() { } 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; } reset_reg(); @@ -569,8 +570,9 @@ int declare_local(int id, int type) { int declare_local_array(int id, int type, int size) { if (local_table[id] != 0) return local_table[id]; - int slot; - for (int i = 0; i < size; ++i) local_marker[slot = next_local_slot(type)] = MARKER_ARRAY; + int slot = next_local_slot(type); + 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; } @@ -632,21 +634,19 @@ void asm_addi(const char* rd, const char* rs, int imm) { // assembly helpers // 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) { - // TODO use sp instead - int offset = -slot_id * 8 - 8; + int offset = slot_id * 8 - 8; const char* rd_name = reg_name(rd); if (check_itype_immediate(offset)) { - printf(" addi %s, fp, %d\n", rd_name, offset); + printf(" addi %s, sp, %d\n", rd_name, offset); } else { 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) { - int type = reg_type[reg]; +const char* load_op_of_type(int type) { if (type & TYPE_PTR_MASK) { return "ld"; } 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 // rd must be one of t0, t1, t2 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); if (is_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 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)) { load_local_address(REG_T2, overflow[reg]); if (indirection[reg]) { @@ -710,7 +706,8 @@ void _asm_r(const char* op, int rd, int rs1) { rs1_name = "t0"; 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)) { 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); } +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 rd = next_reg(type); + int rd = rs1; + if (indirection[rs1] || reg_type[rs1] != type) rd = next_reg(type); _asm_r(op, rd, rs1); return rd; } 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); return rd; } @@ -774,25 +783,34 @@ void asm_mv(int rd, int rs1) { _asm_r("mv", rd, rs1); } -int materialize_t0(int type) { - int rd = next_reg(type); - asm_mv(rd, REG_T0); - return rd; +void store_into_local(int rs1, int slot) { + const char* rs1_name = reg_name(rs1); + if (is_nontrivial(rs1)) { + 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) { type = type | TYPE_PTR_MASK; } - int rd = materialize_t0(TYPE_VOID_PTR); reg_type[rd] = type; indirection[rd] = marker == MARKER_SCALAR; return rd; } int lookup_from_slot(int slot) { - load_local_address(REG_T0, slot); - return materialize_address(local_type[slot], local_marker[slot]); + int reg = next_reg(TYPE_VOID_PTR); + 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) { @@ -805,9 +823,10 @@ int lookup(int id) { if (global_marker[id] == MARKER_FUNCTION) { eprintf("function name must not appear outside function call: %s\n", name); exit(1); - } - printf(" la t0, %s # id: %d\n", name, id); - return materialize_address(global_type[id], global_marker[id]); + } + int reg = next_reg(TYPE_VOID_PTR); + _asm_i("la", reg, name, " # id: ", id); + return materialize_address(reg, global_type[id], global_marker[id]); } eprintf("unresolved identifier: %s\n", name); exit(1); @@ -933,8 +952,8 @@ int asm_sub(int lhs, int rhs) { } int difference = asm_rr(TYPE_INT, "sub", lhs, rhs); int shift = 2 * (lhs_type == TYPE_INT_PTR); - _asm_ri("slli", REG_T0, difference, shift); - return materialize_t0(TYPE_INT); + _asm_ri("slli", difference, difference, shift); + return difference; } if (type1) { int neg = asm_r_arith("neg", rhs); @@ -998,13 +1017,12 @@ int parse_function_call(int id) { for (int i = 0; i < arg; ++i) { asm_mv(i + REG_A0, args[i]); } - // TODO saved by caller printf(" call %s\n", name); - // TODO saved by caller int type = global_type[id]; if (type != TYPE_VOID) { - printf(" mv t0, a0\n"); - return materialize_t0(type); + int rd = next_reg(type); + asm_mv(rd, REG_A0); + return rd; } return -1; } @@ -1014,8 +1032,9 @@ int parse_primary_expr() { if (token_type == TOKEN_EOF) { exit(1); } else if (token_type == TOKEN_NUMBER) { - printf(" li t0, %d\n", token_data); - return materialize_t0(TYPE_INT); + int reg = next_reg(TYPE_INT); + _asm_i("li", reg, "", "", token_data); + return reg; } else if (token_type == TOKEN_ID) { next_token(); if (token_type == TOKEN_PAREN_LEFT) { @@ -1024,8 +1043,9 @@ int parse_primary_expr() { unget_token(); return lookup(token_data); } else if (token_type == TOKEN_STRING) { - printf(" la t0, .LC%d\n", token_data); - return materialize_t0(TYPE_CHAR_PTR); + int reg = next_reg(TYPE_CHAR_PTR); + _asm_i("la", reg, ".LC", "", token_data); + return reg; } else if (token_type == TOKEN_PAREN_LEFT) { int reg = parse_expr(); expect_token(TOKEN_PAREN_RIGHT); @@ -1343,7 +1363,7 @@ void parse_local_variable(int type) { next_token(); if (token_type == TOKEN_BRACKET_LEFT) { 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); } expect_token(TOKEN_NUMBER); @@ -1364,9 +1384,7 @@ void parse_local_variable(int type) { eprintf("type mismatch in assignment\n"); exit(1); } - asm_mv(REG_T0, reg); - load_local_address(REG_T2, slot); - printf(" %s t0, 0(t2)\n", store_op_of_type(type)); + store_into_local(reg, slot); } void parse_stmt(); @@ -1533,7 +1551,7 @@ void parse_function(const char* name) { expect_token(TOKEN_BRACKET_RIGHT); next_token(); 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); } arg_type = arg_type | TYPE_PTR_MASK; @@ -1571,7 +1589,9 @@ void parse_function(const char* name) { parse_stmt(); } 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) { frame_size = frame_size + 8; } @@ -1580,22 +1600,22 @@ void parse_function(const char* name) { asm_addi("sp", "sp", -frame_size); asm_sd("ra", frame_size - 8, "sp"); asm_sd("fp", frame_size - 16, "sp"); - for (int reg = REG_S2; reg <= REG_S11; ++reg) { - asm_sd(reg_name(reg), frame_size - reg * 8 + 15 * 8, "sp"); + for (int i = 0; i < reg_used; ++i) { + int reg = REG_S2 + i; + asm_sd(reg_name(reg), frame_size - 24 - i * 8, "sp"); } asm_addi("fp", "sp", frame_size); for (int i = 0; i < arg; ++i) { - int slot = args[i]; - load_local_address(REG_T2, slot); - printf(" %s a%d, 0(t2)\n", store_op_of_type(local_type[slot]), i); + store_into_local(REG_A0 + i, args[i]); } asm_j(label); // epilog asm_label(epilog_label); asm_ld("ra", frame_size - 8, "sp"); asm_ld("fp", frame_size - 16, "sp"); - for (int reg = REG_S2; reg <= REG_S11; ++reg) { - asm_ld(reg_name(reg), frame_size - reg * 8 + 15 * 8, "sp"); + for (int i = 0; i < reg_used; ++i) { + int reg = REG_S2 + i; + asm_ld(reg_name(reg), frame_size - 24 - i * 8, "sp"); } asm_addi("sp", "sp", frame_size); 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"); exit(1); } - if (type & TYPE_PTR_MASK) { - eprintf("global variable of pointer is not supported\n"); - exit(1); - } printf(".data\n"); printf(".globl %s\n", name); printf(".align 5\n"); @@ -1618,6 +1634,10 @@ void parse_global_variable(int id, const char* name, int type) { expect_token(TOKEN_NUMBER); printf(" .word %d\n", token_data); } 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); int size = token_data; expect_token(TOKEN_BRACKET_RIGHT); @@ -1691,7 +1711,6 @@ void dump_string_table() { } int main() { - eprintf("start compiling...\n"); parse_top_level(); dump_string_table(); return 0; diff --git a/demo/add.c b/demo/add.c index aa3f2f6..6c54b5f 100644 --- a/demo/add.c +++ b/demo/add.c @@ -2,8 +2,16 @@ int printf(const char format[], ...); int scanf(const char format[], ...); 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 a = 1; - return (a+(a+(a+(a+(a+(a+(a+(a+(a+(a+(a))))))))))); + int a[15]; + p = a; + for (int i = 0; i < 15; ++i) a[i] = i; + return f1(); } \ No newline at end of file