diff --git a/README.md b/README.md index 4628d4f..e124a13 100644 --- a/README.md +++ b/README.md @@ -96,11 +96,7 @@ $ sh boot.sh ### 关键字 -本语言包含的关键字即为支持的标量类型的关键字和流程控制的关键字,还有 `const` 和 `extern` 和 `enum`。 - -#### `const` 关键字 - -`const` 关键字可以在类型中使用,会被直接忽略。支持它是为了更好兼容 C 程序。 +本语言包含的关键字即为支持的标量类型的关键字和流程控制的关键字,还有 `extern` 和 `enum`。 #### `extern` 关键字 @@ -162,7 +158,7 @@ $ sh boot.sh 编译过程中涉及的以下参数: - 符号表总长度、字符串表总长度 -- 符号数、字符串数、局部变量数、虚拟寄存器数 +- 符号数、字符串数、局部变量数、(虚拟)寄存器数 不能超过源代码中指定的常数。 diff --git a/boot.c b/boot.c index d47ee7b..0b88404 100644 --- a/boot.c +++ b/boot.c @@ -8,16 +8,16 @@ * Purely for educational purposes. Do not use in production. */ -// libc dependency +// glibc dependency extern void* stdin; extern void* stdout; extern void* stderr; -int printf(const char* format, ...); +int printf(char* format, ...); int getchar(); void exit(int status); -int fprintf(void* file, const char* format, ...); +int fprintf(void* file, char* format, ...); int ungetc(int ch, void* file); void ungetchar(int ch) { @@ -98,7 +98,6 @@ enum { TOKEN_RETURN, TOKEN_ENUM, TOKEN_EXTERN, - TOKEN_CONST, TOKEN_VOID = 128, TOKEN_INT, @@ -159,7 +158,7 @@ enum { REG_T6, }; -const char* reg_name(int reg) { +char* reg_name(int reg) { // special begin if (reg == REG_ZERO) return "zero"; if (reg == REG_RA) return "ra"; @@ -200,7 +199,7 @@ const char* reg_name(int reg) { // lexer -int streq(const char* s1, const char* s2) { +int streq(char* s1, char* s2) { while (*s1 && *s2 && *s1 == *s2) { s1++; s2++; @@ -351,8 +350,6 @@ void parse_id_like(int ch) { token_type = TOKEN_RETURN; } else if (streq(id, "void")) { token_type = TOKEN_VOID; - } else if (streq(id, "const")) { - token_type = TOKEN_CONST; } else if (streq(id, "char")) { token_type = TOKEN_CHAR; } else if (streq(id, "for")) { @@ -586,7 +583,7 @@ void next_token() { if (0) { fprintf(stderr, "token: %d\n", token_type); if (token_type == TOKEN_ID) { - const char* name = id_table + id_lut[token_data]; + char* name = id_table + id_lut[token_data]; fprintf(stderr, " id: %s\n", name); } else if (token_type == TOKEN_NUMBER) { fprintf(stderr, " number: %d\n", token_data); @@ -602,21 +599,12 @@ void expect_token(int expected_type) { } } -void ignore_const() { - if (token_type == TOKEN_CONST) { - next_token(); - } -} - int parse_type() { - ignore_const(); if (token_type == TOKEN_INT || token_type == TOKEN_CHAR || token_type == TOKEN_VOID) { int type = token_type & ~TYPE_TOKEN_MASK; next_token(); - ignore_const(); if (token_type == TOKEN_MUL) { next_token(); - ignore_const(); type |= TYPE_PTR_MASK; } unget_token(); @@ -757,7 +745,7 @@ int check_itype_immediate(int value) { return value >= -2048 && value <= 2047; } -void asm_ld(const char* rd, int imm, const char* rs) { +void asm_ld(char* rd, int imm, char* rs) { if (check_itype_immediate(imm)) { printf(" ld %s, %d(%s)\n", rd, imm, rs); } else { @@ -767,7 +755,7 @@ void asm_ld(const char* rd, int imm, const char* rs) { } } -void asm_sd(const char* rs1, int imm, const char* rs2) { +void asm_sd(char* rs1, int imm, char* rs2) { if (check_itype_immediate(imm)) { printf(" sd %s, %d(%s)\n", rs1, imm, rs2); } else { @@ -777,7 +765,7 @@ void asm_sd(const char* rs1, int imm, const char* rs2) { } } -void asm_addi(const char* rd, const char* rs, int imm) { +void asm_addi(char* rd, char* rs, int imm) { if (check_itype_immediate(imm)) { printf(" addi %s, %s, %d\n", rd, rs, imm); } else { @@ -788,7 +776,7 @@ void asm_addi(const char* rd, const char* rs, int imm) { // assembly helpers -const char* load_op_of_type(int type) { +char* load_op_of_type(int type) { if (type & TYPE_PTR_MASK) { return "ld"; } else if (type == TYPE_CHAR) { @@ -798,7 +786,7 @@ const char* load_op_of_type(int type) { } } -const char* store_op_of_type(int type) { +char* store_op_of_type(int type) { if (type & TYPE_PTR_MASK) { return "sd"; } else if (type == TYPE_CHAR) { @@ -816,8 +804,8 @@ void load_local_address(int rd, int slot_id) { // load a non-trivial register into trivial one void load(int rd, int rs) { - const char* op = load_op_of_type(reg_type[rs]); - const char* rd_name = reg_name(rd); + char* op = load_op_of_type(reg_type[rs]); + char* rd_name = reg_name(rd); if (is_overflow(rs)) { load_local_address(rd, overflow[rs]); if (indirection[rs]) { @@ -829,8 +817,8 @@ void load(int rd, int rs) { } // store a trivial register into a non-trivial one -void store(const char* rs, int reg) { - const char* op = store_op_of_type(reg_type[reg]); +void store(char* rs, int reg) { + char* op = store_op_of_type(reg_type[reg]); if (is_overflow(reg)) { load_local_address(REG_T2, overflow[reg]); if (indirection[reg]) { @@ -845,7 +833,7 @@ int is_nontrivial(int reg) { return is_overflow(reg) || indirection[reg]; } -const char* trivialize(int rs, int t) { +char* trivialize(int rs, int t) { if (is_nontrivial(rs)) { load(t, rs); return reg_name(t); @@ -853,10 +841,10 @@ const char* trivialize(int rs, int t) { return reg_name(rs); } -void _asm_r(const char* op, int rd, int rs1) { - const char* rd_name = reg_name(rd); +void _asm_r(char* op, int rd, int rs1) { + char* rd_name = reg_name(rd); if (is_nontrivial(rd)) rd_name = "t0"; - const char* rs1_name = trivialize(rs1, REG_T0); + char* rs1_name = trivialize(rs1, REG_T0); printf(" %s %s, %s\n", op, rd_name, rs1_name); if (is_nontrivial(rd)) { store("t0", rd); @@ -864,20 +852,20 @@ void _asm_r(const char* op, int rd, int rs1) { } void asm_mv(int rd, int rs1) { - const char* rs1_name = trivialize(rs1, REG_T0); + char* rs1_name = trivialize(rs1, REG_T0); if (is_nontrivial(rd)) { store(rs1_name, rd); } else { - const char* rd_name = reg_name(rd); + char* rd_name = reg_name(rd); if (!streq(rd_name, rs1_name)) printf(" mv %s, %s\n", rd_name, rs1_name); } } -void _asm_rr(const char* op, int rd, int rs1, int rs2) { - const char* rd_name = reg_name(rd); - const char* rs1_name = trivialize(rs1, REG_T0); - const char* rs2_name = trivialize(rs2, REG_T1); +void _asm_rr(char* op, int rd, int rs1, int rs2) { + char* rd_name = reg_name(rd); + char* rs1_name = trivialize(rs1, REG_T0); + char* rs2_name = trivialize(rs2, REG_T1); if (is_nontrivial(rd)) rd_name = "t0"; printf(" %s %s, %s, %s\n", op, rd_name, rs1_name, rs2_name); if (is_nontrivial(rd)) { @@ -885,23 +873,23 @@ void _asm_rr(const char* op, int rd, int rs1, int rs2) { } } -void _asm_ri(const char* op, int rd, int rs1, int imm) { - const char* rd_name = reg_name(rd); +void _asm_ri(char* op, int rd, int rs1, int imm) { + char* rd_name = reg_name(rd); if (is_nontrivial(rd)) rd_name = "t0"; - const char* rs1_name = trivialize(rs1, REG_T0); + char* rs1_name = trivialize(rs1, REG_T0); printf(" %s %s, %s, %d\n", op, rd_name, rs1_name, imm); if (is_nontrivial(rd)) { store("t0", rd); } } -void asm_branch(const char* op, int rs1, int label) { - const char* rs1_name = trivialize(rs1, REG_T0); +void asm_branch(char* op, int rs1, int label) { + char* rs1_name = trivialize(rs1, REG_T0); 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); +void _asm_i(char* op, int rd, char* prefix1, char* prefix2, int imm) { + 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)) { @@ -913,14 +901,14 @@ int is_not_reusable(int rs1, int expected_type) { return indirection[rs1] || reg_type[rs1] != expected_type || rs1 == REG_ZERO; } -int asm_r(int type, const char* op, int rs1) { +int asm_r(int type, char* op, int rs1) { int rd = rs1; if (is_not_reusable(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 asm_rr(int type, char* op, int rs1, int rs2) { int rd = rs1; if (is_not_reusable(rs1, type)) rd = rs2; if (is_not_reusable(rs2, type)) rd = next_reg(type); @@ -929,7 +917,7 @@ int asm_rr(int type, const char* op, int rs1, int rs2) { } void store_into_local(int rs1, int slot) { - const char* rs1_name = trivialize(rs1, REG_T0); + char* rs1_name = trivialize(rs1, REG_T0); load_local_address(REG_T2, slot); printf(" %s %s, 0(t2)\n", store_op_of_type(local_type[slot]), rs1_name); } @@ -968,7 +956,7 @@ int lookup(int id) { if (is_const[id]) { return load_imm(const_table[id]); } - const char* name = id_table + id_lut[id]; + char* name = id_table + id_lut[id]; if (global_kind[id]) { if (global_kind[id] == KIND_FUNCTION) { fprintf(stderr, "function name must not appear outside function call: %s\n", name); @@ -982,7 +970,7 @@ int lookup(int id) { exit(1); } -int asm_r_arith(const char* op, int rs1) { +int asm_r_arith(char* op, int rs1) { if (reg_type[rs1] & TYPE_PTR_MASK) { fprintf(stderr, "pointer cannot be arithmetically operated by %s\n", op); exit(1); @@ -990,7 +978,7 @@ int asm_r_arith(const char* op, int rs1) { return asm_r(TYPE_INT, op, rs1); } -int asm_rr_arith(const char* op, int rs1, int rs2) { +int asm_rr_arith(char* op, int rs1, int rs2) { if (reg_type[rs1] & TYPE_PTR_MASK || reg_type[rs2] & TYPE_PTR_MASK) { fprintf(stderr, "pointer cannot be arithmetically operated by %s\n", op); exit(1); @@ -998,7 +986,7 @@ int asm_rr_arith(const char* op, int rs1, int rs2) { return asm_rr(TYPE_INT, op, rs1, rs2); } -int asm_rr_cmp(const char* op, int rs1, int rs2) { +int asm_rr_cmp(char* op, int rs1, int rs2) { // since NULL is virtually 0, it is considered a valid example of a pointer comparing with an integer return asm_rr(TYPE_INT, op, rs1, rs2); } @@ -1151,7 +1139,7 @@ int parse_expr(); int parse_assign_expr(); int parse_function_call(int id) { - const char* name = id_table + id_lut[id]; + char* name = id_table + id_lut[id]; if (global_kind[id] != KIND_FUNCTION) { fprintf(stderr, "not a function name: %s\n", name); exit(1); @@ -1774,7 +1762,7 @@ void parse_stmt() { reset_temp(); } -void parse_function(const char* name) { +void parse_function(char* name) { reset_local(); int arg = 0; int args[8]; @@ -1879,7 +1867,7 @@ void parse_function(const char* name) { reset_local_table(); } -void parse_global_variable(int id, const char* name, int type) { +void parse_global_variable(int id, char* name, int type) { printf(".data\n"); printf(".globl %s\n", name); printf(".align 5\n"); diff --git a/demo/add.c b/demo/add.c index 3623da5..45876ad 100644 --- a/demo/add.c +++ b/demo/add.c @@ -1,5 +1,4 @@ -int printf(const char format[], ...); -int scanf(const char format[], ...); +int printf(char* format, ...); void should_be(int expected, int actual) { if (expected != actual) { diff --git a/demo/hello.c b/demo/hello.c index c94a263..65311ff 100644 --- a/demo/hello.c +++ b/demo/hello.c @@ -1,4 +1,4 @@ -int printf(const char* format, ...); +int printf(char* format, ...); int main() { printf("hello world %d\n", 42); diff --git a/demo/lut.c b/demo/lut.c deleted file mode 100644 index b4ed157..0000000 --- a/demo/lut.c +++ /dev/null @@ -1,46 +0,0 @@ -int printf(const char format[], ...); -int getchar(); - -char string_table[65536]; -int string_offset; -int string_lut[4096]; -int string_lut_size; - -int parse_string() { - int offset = string_offset; - int ch; - while ((ch = getchar()) != '"') { - if (ch == -1 || ch == '\n') { - printf("expecting '\"'\n"); - return 1; - } - string_table[string_offset++] = ch; - } - string_table[string_offset++] = 0; - string_lut[string_lut_size] = offset; - return string_lut_size++; -} - - -int streq(const char* s1, const char* s2) { - while (*s1 && *s2 && *s1 == *s2) { - s1++; - s2++; - } - return *s1 == *s2; -} - -void dump_string_table() { - printf(".data\n"); - for (int i = 0; i < string_lut_size; ++i) { - char* id = string_table + string_lut[i]; - printf(".LC%d: .string \"%s\", const: %d\n", - i, id, streq(id, "const")); - } -} - -int main() { - char ch; - while ((ch = getchar()) == '"') parse_string(); - dump_string_table(); -} \ No newline at end of file diff --git a/demo/queen.c b/demo/queen.c index 2789ed3..855793e 100644 --- a/demo/queen.c +++ b/demo/queen.c @@ -1,4 +1,4 @@ -int printf(const char format[], ...); +int printf(char* format, ...); int putchar(int ch); int a[9]; diff --git a/demo/sort.c b/demo/sort.c index 8248c54..c8e5c0f 100644 --- a/demo/sort.c +++ b/demo/sort.c @@ -1,5 +1,5 @@ -int printf(const char format[], ...); -int scanf(const char format[], ...); +int printf(char* format, ...); +int scanf(char* format, ...); void sort(int a[], int n) { for (int i = 0; i < n; i++) { diff --git a/demo/strcmp.c b/demo/strcmp.c index 50fe8aa..c880e7d 100644 --- a/demo/strcmp.c +++ b/demo/strcmp.c @@ -1,6 +1,6 @@ -int printf(const char* format, ...); +int printf(char* format, ...); -int strcmp(const char* s1, const char* s2) { +int strcmp(char* s1, char* s2) { while (*s1 && *s2 && *s1 == *s2) { s1++; s2++; @@ -9,8 +9,8 @@ int strcmp(const char* s1, const char* s2) { } int main() { - const char* s1 = "helloworld"; - const char* s2 = "world"; + char* s1 = "helloworld"; + char* s2 = "world"; printf("%d\n", strcmp(s1, s2)); printf("%d\n", strcmp(s1 + 5, s2)); } \ No newline at end of file