primary function call
This commit is contained in:
parent
653d42ccf3
commit
b8108acb2e
@ -78,7 +78,8 @@ $ sh boot.sh
|
||||
|
||||
- 函数和数组不是类型系统的一部分。
|
||||
- 可以认为数组的类型就是其元素对应的指针类型。
|
||||
- 函数保存了其返回值的类型,建议仅用于直接调用,其它操作可视为 UB。
|
||||
- 函数的参数类型和个数不会检查,返回值会参与类型检查。
|
||||
- 函数名只能被用于调用,函数调用被视为初等表达式。
|
||||
- 数组只支持一维数组,且数组的元素不能是指针类型。
|
||||
- 全局变量不能是指针类型。
|
||||
- 整数和字符字面量的类型是 `int`,字符串字面量的类型是 `char*`
|
||||
@ -95,7 +96,8 @@ $ sh boot.sh
|
||||
|
||||
| 运算符 | 含义 | 结合性 |
|
||||
| --------------------------------- | ----------------------------------------------- | -------- |
|
||||
| `++` `--` `()` `[]` | 后缀自增自减 函数调用 数组下标 | 从左到右 |
|
||||
| `()` | 初等表达式(字面量、标识符、函数调用、括号) | |
|
||||
| `++` `--` `[]` | 后缀自增自减 数组下标 | 从左到右 |
|
||||
| `++` `--` `+` `-` `*` `&` `!` `~` | 前缀自增自减 正负号 取地址 解引用 逻辑非 按位非 | 从右到左 |
|
||||
| `*` `/` `%` | 乘除余 | 从左到右 |
|
||||
| `+` `-` | 加减 | 从左到右 |
|
||||
@ -106,7 +108,7 @@ $ sh boot.sh
|
||||
| `^` | 按位异或 | 从左到右 |
|
||||
| <code>|</code> | 按位或 | 从左到右 |
|
||||
| `&&` | 逻辑与 | 从左到右 |
|
||||
| <code>||</code> | 逻辑或 | 从左到右 |
|
||||
| <code>||</code> | 逻辑或 | 从左到右 |
|
||||
| `=` | 赋值 | 从右到左 |
|
||||
|
||||
- 同级表达式的求值顺序与结合性一致。
|
||||
@ -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_PTR_MASK = 16;
|
||||
const int TYPE_FUNC_MASK = 32;
|
||||
const int TYPE_TOKEN_MASK = 128;
|
||||
|
||||
int parse_int(int ch) {
|
||||
@ -436,6 +435,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];
|
||||
@ -552,7 +552,7 @@ void load(int rd, int id) {
|
||||
const char* op = "lw"; // int
|
||||
if (type == TYPE_CHAR) {
|
||||
op = "lb";
|
||||
} else if (type & TYPE_PTR_MASK || type & TYPE_FUNC_MASK) {
|
||||
} else if (type & TYPE_PTR_MASK) {
|
||||
op = "ld";
|
||||
}
|
||||
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
|
||||
if (type == TYPE_CHAR) {
|
||||
op = "sb";
|
||||
} else if (type & TYPE_PTR_MASK || type & TYPE_FUNC_MASK) {
|
||||
} else if (type & TYPE_PTR_MASK) {
|
||||
op = "sd";
|
||||
}
|
||||
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];
|
||||
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);
|
||||
int reg = materialize_t0(global_type[id] | TYPE_PTR_MASK);
|
||||
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) {
|
||||
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);
|
||||
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) {
|
||||
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) {
|
||||
if (local_type[rs1] & TYPE_PTR_MASK || local_type[rs2] & TYPE_PTR_MASK) {
|
||||
eprintf("pointer cannot be arithmetically operated by %s\n", op);
|
||||
exit(1);
|
||||
}
|
||||
@ -778,29 +781,12 @@ int asm_sub(int lhs, int rhs) {
|
||||
// parser
|
||||
int parse_expr();
|
||||
|
||||
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) {
|
||||
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);
|
||||
int parse_function_call(int id) {
|
||||
const char* name = id_table + id_lut[id];
|
||||
if (global_marker[id] != MARKER_FUNCTION) {
|
||||
eprintf("not a function name: %s\n", name);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int parse_function_call(int func) {
|
||||
int arg = 0;
|
||||
int args[8];
|
||||
while (1) {
|
||||
@ -828,9 +814,8 @@ int parse_function_call(int func) {
|
||||
load(0, args[i]);
|
||||
printf(" mv a%d, t0\n", i);
|
||||
}
|
||||
load_address(0, func);
|
||||
printf(" jalr t0\n");
|
||||
int type = local_type[func];
|
||||
printf(" call %s\n", name);
|
||||
int type = global_type[id];
|
||||
if (type != TYPE_VOID) {
|
||||
printf(" mv t0, a0\n");
|
||||
return materialize_t0(type);
|
||||
@ -838,6 +823,33 @@ int parse_function_call(int func) {
|
||||
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 lhs = parse_primary_expr();
|
||||
while (1) {
|
||||
@ -862,8 +874,6 @@ int parse_postfix_expr() {
|
||||
int rhs = parse_expr();
|
||||
expect_token(TOKEN_BRACKET_RIGHT);
|
||||
lhs = dereference(asm_add(lhs, rhs));
|
||||
} else if (token_type == TOKEN_PAREN_LEFT) {
|
||||
lhs = parse_function_call(lhs);
|
||||
} else {
|
||||
unget_token();
|
||||
break;
|
||||
@ -1440,7 +1450,7 @@ void parse_global_declaration() {
|
||||
char* name = id_table + id_lut[id];
|
||||
next_token();
|
||||
if (token_type == TOKEN_PAREN_LEFT) {
|
||||
declare_global(id, MARKER_SCALAR, type | TYPE_FUNC_MASK);
|
||||
declare_global(id, MARKER_FUNCTION, type);
|
||||
parse_function(name);
|
||||
} else {
|
||||
declare_global(id, MARKER_SCALAR, type);
|
||||
|
Loading…
Reference in New Issue
Block a user