primary function call
This commit is contained in:
parent
653d42ccf3
commit
b8108acb2e
@ -78,7 +78,8 @@ $ sh boot.sh
|
|||||||
|
|
||||||
- 函数和数组不是类型系统的一部分。
|
- 函数和数组不是类型系统的一部分。
|
||||||
- 可以认为数组的类型就是其元素对应的指针类型。
|
- 可以认为数组的类型就是其元素对应的指针类型。
|
||||||
- 函数保存了其返回值的类型,建议仅用于直接调用,其它操作可视为 UB。
|
- 函数的参数类型和个数不会检查,返回值会参与类型检查。
|
||||||
|
- 函数名只能被用于调用,函数调用被视为初等表达式。
|
||||||
- 数组只支持一维数组,且数组的元素不能是指针类型。
|
- 数组只支持一维数组,且数组的元素不能是指针类型。
|
||||||
- 全局变量不能是指针类型。
|
- 全局变量不能是指针类型。
|
||||||
- 整数和字符字面量的类型是 `int`,字符串字面量的类型是 `char*`
|
- 整数和字符字面量的类型是 `int`,字符串字面量的类型是 `char*`
|
||||||
@ -95,7 +96,8 @@ $ sh boot.sh
|
|||||||
|
|
||||||
| 运算符 | 含义 | 结合性 |
|
| 运算符 | 含义 | 结合性 |
|
||||||
| --------------------------------- | ----------------------------------------------- | -------- |
|
| --------------------------------- | ----------------------------------------------- | -------- |
|
||||||
| `++` `--` `()` `[]` | 后缀自增自减 函数调用 数组下标 | 从左到右 |
|
| `()` | 初等表达式(字面量、标识符、函数调用、括号) | |
|
||||||
|
| `++` `--` `[]` | 后缀自增自减 数组下标 | 从左到右 |
|
||||||
| `++` `--` `+` `-` `*` `&` `!` `~` | 前缀自增自减 正负号 取地址 解引用 逻辑非 按位非 | 从右到左 |
|
| `++` `--` `+` `-` `*` `&` `!` `~` | 前缀自增自减 正负号 取地址 解引用 逻辑非 按位非 | 从右到左 |
|
||||||
| `*` `/` `%` | 乘除余 | 从左到右 |
|
| `*` `/` `%` | 乘除余 | 从左到右 |
|
||||||
| `+` `-` | 加减 | 从左到右 |
|
| `+` `-` | 加减 | 从左到右 |
|
||||||
@ -116,7 +118,6 @@ $ sh boot.sh
|
|||||||
- 逻辑与和逻辑或支持短路求值。
|
- 逻辑与和逻辑或支持短路求值。
|
||||||
- 表达式没有左值和右值之分。可以认为右值总是存在一个临时的变量中。
|
- 表达式没有左值和右值之分。可以认为右值总是存在一个临时的变量中。
|
||||||
- 赋值不检查类型。强制类型转换可以用赋值给特定类型的变量实现。
|
- 赋值不检查类型。强制类型转换可以用赋值给特定类型的变量实现。
|
||||||
- 函数的参数类型和个数不会检查,返回值会参与类型检查。
|
|
||||||
|
|
||||||
### 其它支持与不支持
|
### 其它支持与不支持
|
||||||
|
|
||||||
|
76
boot.c
76
boot.c
@ -80,7 +80,6 @@ const int TYPE_INT_PTR = 17;
|
|||||||
const int TYPE_CHAR_PTR = 18;
|
const int TYPE_CHAR_PTR = 18;
|
||||||
|
|
||||||
const int TYPE_PTR_MASK = 16;
|
const int TYPE_PTR_MASK = 16;
|
||||||
const int TYPE_FUNC_MASK = 32;
|
|
||||||
const int TYPE_TOKEN_MASK = 128;
|
const int TYPE_TOKEN_MASK = 128;
|
||||||
|
|
||||||
int parse_int(int ch) {
|
int parse_int(int ch) {
|
||||||
@ -436,6 +435,7 @@ int max_local_id = 2;
|
|||||||
const int MARKER_TEMP = 0;
|
const int MARKER_TEMP = 0;
|
||||||
const int MARKER_SCALAR = 1;
|
const int MARKER_SCALAR = 1;
|
||||||
const int MARKER_ARRAY = 2;
|
const int MARKER_ARRAY = 2;
|
||||||
|
const int MARKER_FUNCTION = 3;
|
||||||
|
|
||||||
int local_marker[4096];
|
int local_marker[4096];
|
||||||
int global_marker[4096];
|
int global_marker[4096];
|
||||||
@ -552,7 +552,7 @@ void load(int rd, int id) {
|
|||||||
const char* op = "lw"; // int
|
const char* op = "lw"; // int
|
||||||
if (type == TYPE_CHAR) {
|
if (type == TYPE_CHAR) {
|
||||||
op = "lb";
|
op = "lb";
|
||||||
} else if (type & TYPE_PTR_MASK || type & TYPE_FUNC_MASK) {
|
} else if (type & TYPE_PTR_MASK) {
|
||||||
op = "ld";
|
op = "ld";
|
||||||
}
|
}
|
||||||
printf(" %s t%d, 0(t%d) # id: type %d\n", op, rd, rd, type);
|
printf(" %s t%d, 0(t%d) # id: type %d\n", op, rd, rd, type);
|
||||||
@ -564,7 +564,7 @@ void store_t0(int id) {
|
|||||||
const char* op = "sw"; // int
|
const char* op = "sw"; // int
|
||||||
if (type == TYPE_CHAR) {
|
if (type == TYPE_CHAR) {
|
||||||
op = "sb";
|
op = "sb";
|
||||||
} else if (type & TYPE_PTR_MASK || type & TYPE_FUNC_MASK) {
|
} else if (type & TYPE_PTR_MASK) {
|
||||||
op = "sd";
|
op = "sd";
|
||||||
}
|
}
|
||||||
printf(" %s t0, 0(t1) # id: type %d\n", op, type);
|
printf(" %s t0, 0(t1) # id: type %d\n", op, type);
|
||||||
@ -593,6 +593,10 @@ int lookup(int id) {
|
|||||||
}
|
}
|
||||||
const char* name = id_table + id_lut[id];
|
const char* name = id_table + id_lut[id];
|
||||||
if (global_marker[id]) {
|
if (global_marker[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);
|
printf(" la t0, %s # id: %d\n", name, id);
|
||||||
int reg = materialize_t0(global_type[id] | TYPE_PTR_MASK);
|
int reg = materialize_t0(global_type[id] | TYPE_PTR_MASK);
|
||||||
if (global_marker[id] == MARKER_SCALAR) {
|
if (global_marker[id] == MARKER_SCALAR) {
|
||||||
@ -631,7 +635,7 @@ int asm_r(const char* op, int rs1) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int asm_r_arith(const char* op, int rs1) {
|
int asm_r_arith(const char* op, int rs1) {
|
||||||
if (local_type[rs1] & TYPE_PTR_MASK || local_type[rs1] & TYPE_FUNC_MASK) {
|
if (local_type[rs1] & TYPE_PTR_MASK) {
|
||||||
eprintf("pointer cannot be arithmetically operated by %s\n", op);
|
eprintf("pointer cannot be arithmetically operated by %s\n", op);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@ -654,8 +658,7 @@ int asm_rr(const char* op, int rs1, int rs2) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int asm_rr_arith(const char* op, int rs1, int rs2) {
|
int asm_rr_arith(const char* op, int rs1, int rs2) {
|
||||||
if (local_type[rs1] & TYPE_PTR_MASK || local_type[rs2] & TYPE_PTR_MASK
|
if (local_type[rs1] & TYPE_PTR_MASK || local_type[rs2] & TYPE_PTR_MASK) {
|
||||||
|| local_type[rs1] & TYPE_FUNC_MASK || local_type[rs2] & TYPE_FUNC_MASK) {
|
|
||||||
eprintf("pointer cannot be arithmetically operated by %s\n", op);
|
eprintf("pointer cannot be arithmetically operated by %s\n", op);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@ -778,29 +781,12 @@ int asm_sub(int lhs, int rhs) {
|
|||||||
// parser
|
// parser
|
||||||
int parse_expr();
|
int parse_expr();
|
||||||
|
|
||||||
int parse_primary_expr() {
|
int parse_function_call(int id) {
|
||||||
next_token();
|
const char* name = id_table + id_lut[id];
|
||||||
if (token_type == TOKEN_EOF) {
|
if (global_marker[id] != MARKER_FUNCTION) {
|
||||||
exit(1);
|
eprintf("not a function name: %s\n", name);
|
||||||
} else if (token_type == TOKEN_NUMBER) {
|
|
||||||
printf(" li t0, %d\n", token_data);
|
|
||||||
return materialize_t0(TYPE_INT);
|
|
||||||
} else if (token_type == TOKEN_ID) {
|
|
||||||
return lookup(token_data);
|
|
||||||
} else if (token_type == TOKEN_STRING) {
|
|
||||||
printf(" la t0, .LC%d\n", token_data);
|
|
||||||
return materialize_t0(TYPE_CHAR_PTR);
|
|
||||||
} else if (token_type == TOKEN_PAREN_LEFT) {
|
|
||||||
int reg = parse_expr();
|
|
||||||
expect_token(TOKEN_PAREN_RIGHT);
|
|
||||||
return reg;
|
|
||||||
} else {
|
|
||||||
eprintf("unexpected token in primary expression: %d\n", token_type);
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
int parse_function_call(int func) {
|
|
||||||
int arg = 0;
|
int arg = 0;
|
||||||
int args[8];
|
int args[8];
|
||||||
while (1) {
|
while (1) {
|
||||||
@ -828,9 +814,8 @@ int parse_function_call(int func) {
|
|||||||
load(0, args[i]);
|
load(0, args[i]);
|
||||||
printf(" mv a%d, t0\n", i);
|
printf(" mv a%d, t0\n", i);
|
||||||
}
|
}
|
||||||
load_address(0, func);
|
printf(" call %s\n", name);
|
||||||
printf(" jalr t0\n");
|
int type = global_type[id];
|
||||||
int type = local_type[func];
|
|
||||||
if (type != TYPE_VOID) {
|
if (type != TYPE_VOID) {
|
||||||
printf(" mv t0, a0\n");
|
printf(" mv t0, a0\n");
|
||||||
return materialize_t0(type);
|
return materialize_t0(type);
|
||||||
@ -838,6 +823,33 @@ int parse_function_call(int func) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int parse_primary_expr() {
|
||||||
|
next_token();
|
||||||
|
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);
|
||||||
|
} else if (token_type == TOKEN_ID) {
|
||||||
|
next_token();
|
||||||
|
if (token_type == TOKEN_PAREN_LEFT) {
|
||||||
|
return parse_function_call(token_data);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
} else if (token_type == TOKEN_PAREN_LEFT) {
|
||||||
|
int reg = parse_expr();
|
||||||
|
expect_token(TOKEN_PAREN_RIGHT);
|
||||||
|
return reg;
|
||||||
|
} else {
|
||||||
|
eprintf("unexpected token in primary expression: %d\n", token_type);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int parse_postfix_expr() {
|
int parse_postfix_expr() {
|
||||||
int lhs = parse_primary_expr();
|
int lhs = parse_primary_expr();
|
||||||
while (1) {
|
while (1) {
|
||||||
@ -862,8 +874,6 @@ int parse_postfix_expr() {
|
|||||||
int rhs = parse_expr();
|
int rhs = parse_expr();
|
||||||
expect_token(TOKEN_BRACKET_RIGHT);
|
expect_token(TOKEN_BRACKET_RIGHT);
|
||||||
lhs = dereference(asm_add(lhs, rhs));
|
lhs = dereference(asm_add(lhs, rhs));
|
||||||
} else if (token_type == TOKEN_PAREN_LEFT) {
|
|
||||||
lhs = parse_function_call(lhs);
|
|
||||||
} else {
|
} else {
|
||||||
unget_token();
|
unget_token();
|
||||||
break;
|
break;
|
||||||
@ -1440,7 +1450,7 @@ void parse_global_declaration() {
|
|||||||
char* name = id_table + id_lut[id];
|
char* name = id_table + id_lut[id];
|
||||||
next_token();
|
next_token();
|
||||||
if (token_type == TOKEN_PAREN_LEFT) {
|
if (token_type == TOKEN_PAREN_LEFT) {
|
||||||
declare_global(id, MARKER_SCALAR, type | TYPE_FUNC_MASK);
|
declare_global(id, MARKER_FUNCTION, type);
|
||||||
parse_function(name);
|
parse_function(name);
|
||||||
} else {
|
} else {
|
||||||
declare_global(id, MARKER_SCALAR, type);
|
declare_global(id, MARKER_SCALAR, type);
|
||||||
|
Loading…
Reference in New Issue
Block a user