pointer arithmetic

This commit is contained in:
Yaossg 2024-11-16 09:34:56 +08:00
parent f197671868
commit cf45cf1e2f

115
boot.c
View File

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