From cf45cf1e2f21715caf1b2f80239cc854c252759e Mon Sep 17 00:00:00 2001 From: Yaossg Date: Sat, 16 Nov 2024 09:34:56 +0800 Subject: [PATCH] pointer arithmetic --- boot.c | 115 +++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 74 insertions(+), 41 deletions(-) diff --git a/boot.c b/boot.c index 0072543..85cc5d0 100644 --- a/boot.c +++ b/boot.c @@ -156,9 +156,10 @@ void rewind_id(int new_data) { } void dedup_id() { - char* latest = &id_table[id_lut[id_lut_size - 1]]; - for (int i = 0; i < id_lut_size - 1; i++) { - char* candidate = &id_table[id_lut[i]]; + int last_id = id_lut_size - 1; + char* latest = id_table + id_lut[last_id]; + for (int i = 0; i < last_id; i++) { + char* candidate = id_table + id_lut[i]; if (streq(candidate, latest)) { rewind_id(i); return; @@ -169,7 +170,7 @@ void dedup_id() { void parse_id_like(int ch) { token_type = TOKEN_ID; token_data = parse_id(ch); - char* id = &id_table[id_lut[token_data]]; + char* id = id_table + id_lut[token_data]; if (streq(id, "int")) { token_type = TOKEN_INT; } else if (streq(id, "if")) { @@ -367,7 +368,7 @@ void next_token() { } eprintf("token: %d\n", token_type); if (token_type == TOKEN_ID) { - const char* name = &id_table[id_lut[token_data]]; + const char* name = id_table + id_lut[token_data]; eprintf(" id: %s\n", name); } else if (token_type == TOKEN_NUMBER) { eprintf(" number: %d\n", token_data); @@ -432,6 +433,7 @@ int max_local_id = 2; const int MARKER_TEMP = 0; const int MARKER_SCALAR = 1; const int MARKER_ARRAY = 2; +const int MARKER_FUNCTION = 3; int local_marker[4096]; int global_marker[4096]; @@ -546,20 +548,28 @@ void load_address(int rd, int id) { void load(int rd, int id) { load_address(rd, id); - const char* op = "ld"; - if (local_type_of(id) == TYPE_CHAR && (id & INDIRECTION)) { + int type = local_type_of(id); + const char* op = "lw"; // int + if (type == TYPE_CHAR) { op = "lb"; } - printf(" %s t%d, 0(t%d) # id: type %d\n", op, rd, rd, local_type_of(id)); + if (type & TYPE_PTR_MASK) { + op = "ld"; + } + printf(" %s t%d, 0(t%d) # id: type %d\n", op, rd, rd, type); } void store_t0(int id) { load_address(1, id); - const char* op = "sd"; - if (local_type_of(id) == TYPE_CHAR && (id & INDIRECTION)) { + int type = local_type_of(id); + const char* op = "sw"; // int + if (type == TYPE_CHAR) { op = "sb"; } - printf(" %s t0, 0(t1) # id: type %d\n", op, local_type_of(id)); + if (type & TYPE_PTR_MASK) { + op = "sd"; + } + printf(" %s t0, 0(t1) # id: type %d\n", op, type); } int materialize_t0(int type) { @@ -582,13 +592,16 @@ int lookup(int id) { } return local; } - const char* name = &id_table[id_lut[id]]; + const char* name = id_table + id_lut[id]; if (global_marker[id]) { printf(" la t0, %s # id: %d\n", name, id); int reg = materialize_t0(global_type[id] | TYPE_PTR_MASK); - if (global_marker[id] != MARKER_ARRAY) { + if (global_marker[id] == MARKER_SCALAR) { reg = indirection_of(reg); } + if (global_marker[id] == MARKER_FUNCTION) { + reg = reg | INDIRECTION; + } return reg; } eprintf("unresolved identifier: %s\n", name); @@ -669,17 +682,44 @@ void asm_pop_label() { int step_of(int type) { if (type == TYPE_INT_PTR) { - return 8; + return 4; } return 1; } void asm_slli_t0(int type) { if (type == TYPE_INT_PTR) { - printf(" slli t0, t0, 3\n"); + printf(" slli t0, t0, 2\n"); } } +int asm_add(int lhs, int rhs) { + int type1 = local_type_of(lhs) & TYPE_PTR_MASK; + int type2 = local_type_of(rhs) & TYPE_PTR_MASK; + if (type1 != type2) { + int ptr; + int idx; + if (type1) { + ptr = lhs; + idx = rhs; + } else { + ptr = rhs; + idx = lhs; + } + int ptr_type = local_type_of(ptr); + load(0, idx); + load(1, ptr); + asm_slli_t0(ptr_type); + printf(" add t0, t0, t1\n"); + return materialize_t0(ptr_type); + } + if (type1 && type2) { + eprintf("operands cannot be both pointers\n"); + exit(1); + } + return asm_rr("add", lhs, rhs); +} + // parser int parse_expr(); @@ -728,27 +768,7 @@ int parse_postfix_expr() { } else if (token_type == TOKEN_BRACKET_LEFT) { int rhs = parse_expr(); expect_token(TOKEN_BRACKET_RIGHT); - int type1 = local_type_of(lhs) & TYPE_PTR_MASK; - int type2 = local_type_of(rhs) & TYPE_PTR_MASK; - if (type1 == type2) { - eprintf("there should be exact one pointer and one integer in array access\n"); - exit(1); - } - int ptr; - int idx; - if (type1) { - ptr = lhs; - idx = rhs; - } else { - ptr = rhs; - idx = lhs; - } - int ptr_type = local_type_of(ptr); - load(0, idx); - load(1, ptr); - asm_slli_t0(ptr_type); - printf(" add t0, t0, t1\n"); - return indirection_of(materialize_t0(ptr_type)); + return indirection_of(asm_add(lhs, rhs)); } else if (token_type == TOKEN_PAREN_LEFT) { int arg = 0; int args[8]; @@ -852,7 +872,7 @@ int parse_add_expr() { next_token(); if (token_type == TOKEN_ADD) { int rhs = parse_mul_expr(); - lhs = asm_rr("add", lhs, rhs); + lhs = asm_add(lhs, rhs); } else if (token_type == TOKEN_MINUS) { int rhs = parse_mul_expr(); lhs = asm_rr("sub", lhs, rhs); @@ -1027,6 +1047,10 @@ void parse_local_variable(int type) { int id = token_data; next_token(); if (token_type == TOKEN_BRACKET_LEFT) { + if (type & TYPE_PTR_MASK) { + eprintf("local variable of array of pointers is not supported\n"); + exit(1); + } expect_token(TOKEN_NUMBER); int size = token_data; expect_token(TOKEN_BRACKET_RIGHT); @@ -1238,6 +1262,10 @@ void parse_function(const char* name) { } void parse_global_variable(int id, const char* name, int type) { + 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"); @@ -1249,10 +1277,14 @@ void parse_global_variable(int id, const char* name, int type) { expect_token(TOKEN_NUMBER); int size = token_data; expect_token(TOKEN_BRACKET_RIGHT); - printf(" .zero %d\n", 8 * size); + int array_size = 4 * size; + if (type == TYPE_CHAR) { + array_size = size; + } + printf(" .zero %d\n", array_size); declare_global(id, MARKER_ARRAY, type); } else { - printf(" .zero %d\n", 8); + printf(" .zero %d\n", 4); unget_token(); } expect_token(TOKEN_SEMICOLON); @@ -1261,12 +1293,13 @@ void parse_global_variable(int id, const char* name, int type) { void parse_decl(int type) { expect_token(TOKEN_ID); int id = token_data; - declare_global(id, MARKER_SCALAR, type); - char* name = &id_table[id_lut[id]]; + char* name = id_table + id_lut[id]; next_token(); if (token_type == TOKEN_PAREN_LEFT) { + declare_global(id, MARKER_FUNCTION, type); parse_function(name); } else { + declare_global(id, MARKER_SCALAR, type); parse_global_variable(id, name, type); } }