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 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;

View File

@ -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();
}