diff --git a/boot.c b/boot.c index 6ff3bff..6714bd6 100644 --- a/boot.c +++ b/boot.c @@ -524,6 +524,10 @@ void asm_addi(const char* rd, const char* rs, int imm) { } void load_address(int rd, int id) { + if (id == -1) { + eprintf("void cannot be arithmetically operated\n"); + exit(1); + } int offset = -id * 8 - 8; if (indirection[id]) { if (check_itype_immediate(offset)) { @@ -573,7 +577,7 @@ int materialize_t0(int type) { return reg; } -int indirection_of(int reg) { +int dereference(int reg) { local_type[reg] = local_type[reg] & ~TYPE_PTR_MASK; indirection[reg] = 1; return reg; @@ -593,7 +597,7 @@ int lookup(int 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_SCALAR) { - reg = indirection_of(reg); + reg = dereference(reg); } if (global_marker[id] == MARKER_FUNCTION) { indirection[reg] = 1; @@ -703,6 +707,10 @@ int asm_add(int lhs, int rhs) { idx = lhs; } int ptr_type = local_type[ptr]; + if (ptr_type == TYPE_VOID_PTR) { + eprintf("void pointer cannot be arithmetically operated\n"); + exit(1); + } load(0, idx); load(1, ptr); asm_shift_t0("slli", ptr_type); @@ -717,14 +725,23 @@ int asm_add(int lhs, int rhs) { } int asm_sub(int lhs, int rhs) { - int type1 = local_type[lhs] & TYPE_PTR_MASK; - int type2 = local_type[rhs] & TYPE_PTR_MASK; + int lhs_type = local_type[lhs]; + int rhs_type = local_type[rhs]; + int type1 = lhs_type & TYPE_PTR_MASK; + int type2 = rhs_type & TYPE_PTR_MASK; if (type1 && type2) { + if (lhs_type != rhs_type) { + eprintf("pointer type mismatch\n"); + exit(1); + } + if (lhs_type == TYPE_VOID_PTR) { + eprintf("void pointer cannot be arithmetically operated\n"); + exit(1); + } load(0, lhs); load(1, rhs); - int ptr_type = local_type[lhs]; printf(" sub t0, t0, t1\n"); - asm_shift_t0("srli", ptr_type); + asm_shift_t0("srli", lhs_type); return materialize_t0(TYPE_INT); } if (type1) { @@ -763,6 +780,44 @@ int parse_primary_expr() { } } +int parse_function_call(int func) { + int arg = 0; + int args[8]; + while (1) { + next_token(); + if (token_type == TOKEN_PAREN_RIGHT) { + break; + } + unget_token(); + if (arg >= 8) { + eprintf("too many arguments\n"); + exit(1); + } + args[arg++] = parse_expr(); + next_token(); + if (token_type == TOKEN_COMMA) { + // continue; + } else if (token_type == TOKEN_PAREN_RIGHT) { + break; + } else { + eprintf("expecting ',' or ')'\n"); + exit(1); + } + } + for (int i = 0; i < arg; ++i) { + load(0, args[i]); + printf(" mv a%d, t0\n", i); + } + load_address(0, func); + printf(" jalr t0\n"); + int type = local_type[func]; + if (type != TYPE_VOID) { + printf(" mv t0, a0\n"); + return materialize_t0(type); + } + return -1; +} + int parse_postfix_expr() { int lhs = parse_primary_expr(); while (1) { @@ -786,39 +841,9 @@ int parse_postfix_expr() { } else if (token_type == TOKEN_BRACKET_LEFT) { int rhs = parse_expr(); expect_token(TOKEN_BRACKET_RIGHT); - lhs = indirection_of(asm_add(lhs, rhs)); + lhs = dereference(asm_add(lhs, rhs)); } else if (token_type == TOKEN_PAREN_LEFT) { - int arg = 0; - int args[8]; - while (1) { - next_token(); - if (token_type == TOKEN_PAREN_RIGHT) { - break; - } - unget_token(); - if (arg >= 8) { - eprintf("too many arguments\n"); - exit(1); - } - args[arg++] = parse_expr(); - next_token(); - if (token_type == TOKEN_COMMA) { - // continue; - } else if (token_type == TOKEN_PAREN_RIGHT) { - break; - } else { - eprintf("expecting ',' or ')'\n"); - exit(1); - } - } - for (int i = 0; i < arg; ++i) { - load(0, args[i]); - printf(" mv a%d, t0\n", i); - } - load_address(0, lhs); - printf(" jalr t0\n"); - printf(" mv t0, a0\n"); - lhs = materialize_t0(local_type[lhs]); + lhs = parse_function_call(lhs); } else { unget_token(); break; @@ -829,14 +854,28 @@ int parse_postfix_expr() { int parse_prefix_expr() { next_token(); - if (token_type == TOKEN_AND) { + if (token_type == TOKEN_AND) { int reg = parse_postfix_expr(); + int type = local_type[reg]; + if (type & TYPE_PTR_MASK) { + eprintf("cannot take address of a pointer\n"); + exit(1); + } load_address(0, reg); - return materialize_t0(local_type[reg] | TYPE_PTR_MASK); + return materialize_t0(type | TYPE_PTR_MASK); } else if (token_type == TOKEN_STAR) { int reg = parse_postfix_expr(); + int type = local_type[reg]; + if (!(type & TYPE_PTR_MASK)) { + eprintf("cannot dereference a non-pointer\n"); + exit(1); + } + if (type == TYPE_VOID_PTR) { + eprintf("cannot dereference void pointer\n"); + exit(1); + } load(0, reg); - return indirection_of(materialize_t0(local_type[reg])); + return dereference(materialize_t0(type)); } else if (token_type == TOKEN_MINUS) { int reg = parse_postfix_expr(); return asm_r("neg", reg); @@ -1314,16 +1353,16 @@ void parse_function(const char* name) { parse_stmt(); } asm_j(epilog_label); - int shift = max_local_id * 8; - if (shift % 16 != 0) { - shift = shift + 8; + int frame_size = max_local_id * 8; + if (frame_size % 16 != 0) { + frame_size = frame_size + 8; } // prolog asm_label(prolog_label); - asm_addi("sp", "sp", -shift); - asm_sd("ra", shift - 8, "sp"); - asm_sd("fp", shift - 16, "sp"); - asm_addi("fp", "sp", shift); + asm_addi("sp", "sp", -frame_size); + asm_sd("ra", frame_size - 8, "sp"); + asm_sd("fp", frame_size - 16, "sp"); + asm_addi("fp", "sp", frame_size); for (int i = 0; i < arg; ++i) { printf(" mv t0, a%d\n", i); store_t0(args[i]); @@ -1331,9 +1370,9 @@ void parse_function(const char* name) { asm_j(label); // epilog asm_label(epilog_label); - asm_ld("fp", shift - 16, "sp"); - asm_ld("ra", shift - 8, "sp"); - asm_addi("sp", "sp", shift); + asm_ld("fp", frame_size - 16, "sp"); + asm_ld("ra", frame_size - 8, "sp"); + asm_addi("sp", "sp", frame_size); printf(" ret\n"); }