use sp to find local
This commit is contained in:
parent
2097d9fd34
commit
44051c7985
143
boot.c
143
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;
|
||||
|
12
demo/add.c
12
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();
|
||||
}
|
Loading…
Reference in New Issue
Block a user