complete operators

This commit is contained in:
Yaossg 2024-11-30 17:47:28 +08:00
parent 8114d04fb9
commit e18bf2c2d3

187
boot.c
View File

@ -21,7 +21,7 @@ int token_data;
const int TOKEN_EOF = 0;
const int TOKEN_SEMICOLON = 1;
const int TOKEN_ADD = 2;
const int TOKEN_MINUS = 3;
const int TOKEN_SUB = 3;
const int TOKEN_MUL = 4;
const int TOKEN_DIV = 5;
const int TOKEN_REM = 6;
@ -40,6 +40,18 @@ const int TOKEN_LOR = 18;
const int TOKEN_ELLIPSIS = 19;
const int TOKEN_INC = 20;
const int TOKEN_DEC = 21;
const int TOKEN_ADD_ASSIGN = 22;
const int TOKEN_SUB_ASSIGN = 23;
const int TOKEN_MUL_ASSIGN = 24;
const int TOKEN_DIV_ASSIGN = 25;
const int TOKEN_REM_ASSIGN = 26;
const int TOKEN_AND_ASSIGN = 27;
const int TOKEN_OR_ASSIGN = 28;
const int TOKEN_XOR_ASSIGN = 29;
const int TOKEN_LSHIFT_ASSIGN = 30;
const int TOKEN_RSHIFT_ASSIGN = 31;
const int TOKEN_QUESTION = 32;
const int TOKEN_COLON = 33;
const int TOKEN_EQ = 40;
const int TOKEN_NE = 41;
@ -85,8 +97,8 @@ const int TYPE_TOKEN_MASK = 128;
int parse_int(int ch) {
int num = ch - '0';
while (is_digit(ch = getchar())) {
num = num * 10;
num = num + ch - '0';
num *= 10;
num += ch - '0';
}
ungetchar(ch);
return num;
@ -264,6 +276,8 @@ void next_token() {
int ch2 = getchar();
if (ch2 == '+') {
token_type = TOKEN_INC;
} else if (ch2 == '=') {
token_type = TOKEN_ADD_ASSIGN;
} else {
ungetchar(ch2);
token_type = TOKEN_ADD;
@ -272,15 +286,25 @@ void next_token() {
int ch2 = getchar();
if (ch2 == '-') {
token_type = TOKEN_DEC;
} else if (ch2 == '=') {
token_type = TOKEN_SUB_ASSIGN;
} else {
ungetchar(ch2);
token_type = TOKEN_MINUS;
token_type = TOKEN_SUB;
}
} else if (ch == '*') {
token_type = TOKEN_MUL;
int ch2 = getchar();
if (ch2 == '=') {
token_type = TOKEN_MUL_ASSIGN;
} else {
ungetchar(ch2);
token_type = TOKEN_MUL;
}
} else if (ch == '/') {
int ch2 = getchar();
if (ch2 == '/') {
if (ch2 == '=') {
token_type = TOKEN_DIV_ASSIGN;
} if (ch2 == '/') {
do ch = getchar(); while (ch != -1 && ch != '\n');
next_token();
return;
@ -305,9 +329,19 @@ void next_token() {
token_type = TOKEN_DIV;
}
} else if (ch == '%') {
token_type = TOKEN_REM;
int ch2 = getchar();
if (ch2 == '=') {
token_type = TOKEN_REM_ASSIGN;
} else {
ungetchar(ch2);
token_type = TOKEN_REM;
}
} else if (ch == ';') {
token_type = TOKEN_SEMICOLON;
} else if (ch == '?') {
token_type = TOKEN_QUESTION;
} else if (ch == ':') {
token_type = TOKEN_COLON;
} else if (ch == ',') {
token_type = TOKEN_COMMA;
} else if (ch == '<') {
@ -315,7 +349,13 @@ void next_token() {
if (ch2 == '=') {
token_type = TOKEN_LE;
} else if (ch2 == '<') {
token_type = TOKEN_LSHIFT;
int ch3 = getchar();
if (ch3 == '=') {
token_type = TOKEN_LSHIFT_ASSIGN;
} else {
ungetchar(ch3);
token_type = TOKEN_LSHIFT;
}
} else {
ungetchar(ch2);
token_type = TOKEN_LT;
@ -325,7 +365,13 @@ void next_token() {
if (ch2 == '=') {
token_type = TOKEN_GE;
} else if (ch2 == '>') {
token_type = TOKEN_RSHIFT;
int ch3 = getchar();
if (ch3 == '=') {
token_type = TOKEN_RSHIFT_ASSIGN;
} else {
ungetchar(ch3);
token_type = TOKEN_RSHIFT;
}
} else {
ungetchar(ch2);
token_type = TOKEN_GT;
@ -348,7 +394,9 @@ void next_token() {
}
} else if (ch == '&') {
int ch2 = getchar();
if (ch2 == '&') {
if (ch2 == '=') {
token_type = TOKEN_AND_ASSIGN;
} else if (ch2 == '&') {
token_type = TOKEN_LAND;
} else {
ungetchar(ch2);
@ -356,14 +404,22 @@ void next_token() {
}
} else if (ch == '|') {
int ch2 = getchar();
if (ch2 == '|') {
if (ch2 == '=') {
token_type = TOKEN_OR_ASSIGN;
} else if (ch2 == '|') {
token_type = TOKEN_LOR;
} else {
ungetchar(ch2);
token_type = TOKEN_OR;
}
} else if (ch == '^') {
token_type = TOKEN_XOR;
int ch2 = getchar();
if (ch2 == '=') {
token_type = TOKEN_XOR_ASSIGN;
} else {
ungetchar(ch2);
token_type = TOKEN_XOR;
}
} else if (ch == '~') {
token_type = TOKEN_COMPL;
} else if (ch == '\'') {
@ -432,7 +488,7 @@ int parse_type() {
if (token_type == TOKEN_MUL) {
next_token();
ignore_const();
type = type | TYPE_PTR_MASK;
type |= TYPE_PTR_MASK;
}
unget_token();
return type;
@ -799,7 +855,7 @@ void store_into_local(int rs1, int slot) {
int materialize_address(int rd, int type, int marker) {
if (marker == MARKER_ARRAY) {
type = type | TYPE_PTR_MASK;
type |= TYPE_PTR_MASK;
}
reg_type[rd] = type;
indirection[rd] = marker == MARKER_SCALAR;
@ -926,7 +982,7 @@ void asm_return() {
}
int log_step_of(int type) {
return 2 * (type == TYPE_INT_PTR);
return type == TYPE_INT_PTR ? 2 : 0;
}
int step_of(int type) {
@ -976,9 +1032,9 @@ int asm_sub(int lhs, int rhs) {
eprintf("void pointer cannot be arithmetically operated\n");
exit(1);
}
int difference = asm_rr(TYPE_INT, "sub", lhs, rhs);
_asm_ri("slli", difference, difference, log_step_of(lhs_type));
return difference;
int diff = asm_rr(TYPE_INT, "sub", lhs, rhs);
_asm_ri("slli", diff, diff, log_step_of(lhs_type));
return diff;
}
if (type1) {
int neg = asm_r_arith("neg", rhs);
@ -1142,7 +1198,7 @@ int parse_prefix_expr() {
exit(1);
}
return dereference(reg);
} else if (token_type == TOKEN_MINUS) {
} else if (token_type == TOKEN_SUB) {
int reg = parse_postfix_expr();
return asm_r_arith("neg", reg);
} else if (token_type == TOKEN_COMPL) {
@ -1193,7 +1249,7 @@ int parse_add_expr() {
if (token_type == TOKEN_ADD) {
int rhs = parse_mul_expr();
lhs = asm_add(lhs, rhs);
} else if (token_type == TOKEN_MINUS) {
} else if (token_type == TOKEN_SUB) {
int rhs = parse_mul_expr();
lhs = asm_sub(lhs, rhs);
} else {
@ -1254,12 +1310,12 @@ int parse_eq_expr() {
next_token();
if (token_type == TOKEN_EQ) {
int rhs = parse_cmp_expr();
int xor0 = asm_rr_cmp("xor", lhs, rhs);
lhs = asm_r(TYPE_INT, "seqz", xor0);
int xor = asm_rr_cmp("xor", lhs, rhs);
lhs = asm_r(TYPE_INT, "seqz", xor);
} else if (token_type == TOKEN_NE) {
int rhs = parse_cmp_expr();
int xor0 = asm_rr_cmp("xor", lhs, rhs);
lhs = asm_r(TYPE_INT, "snez", xor0);
int xor = asm_rr_cmp("xor", lhs, rhs);
lhs = asm_r(TYPE_INT, "snez", xor);
} else {
unget_token();
break;
@ -1372,13 +1428,90 @@ int parse_logical_or_expr() {
return lhs;
}
int parse_conditional_expr() {
int cond = parse_logical_or_expr();
next_token();
if (token_type == TOKEN_QUESTION) {
int label1 = next_label();
int label2 = next_label();
asm_beqz(cond, label1);
int lhs = parse_expr();
int result = next_reg(reg_type[lhs]);
asm_mv(result, lhs);
asm_j(label2);
expect_token(TOKEN_COLON);
asm_label(label1);
int rhs = parse_conditional_expr();
if (reg_type[lhs] != reg_type[rhs]) {
eprintf("type mismatch in conditional expression\n");
exit(1);
}
asm_mv(result, rhs);
asm_label(label2);
return result;
} else {
unget_token();
return cond;
}
}
int parse_assign_expr() {
int lhs = parse_logical_or_expr();
int lhs = parse_conditional_expr();
next_token();
if (token_type == TOKEN_ASSIGN) {
int rhs = parse_assign_expr();
asm_mv(lhs, rhs);
return lhs;
} else if (token_type == TOKEN_ADD_ASSIGN) {
int rhs = parse_assign_expr();
int sum = asm_add(lhs, rhs);
asm_mv(lhs, sum);
return lhs;
} else if (token_type == TOKEN_SUB_ASSIGN) {
int rhs = parse_assign_expr();
int diff = asm_sub(lhs, rhs);
asm_mv(lhs, diff);
return lhs;
} else if (token_type == TOKEN_MUL_ASSIGN) {
int rhs = parse_assign_expr();
int prod = asm_rr_arith("mul", lhs, rhs);
asm_mv(lhs, prod);
return lhs;
} else if (token_type == TOKEN_DIV_ASSIGN) {
int rhs = parse_assign_expr();
int quot = asm_rr_arith("div", lhs, rhs);
asm_mv(lhs, quot);
return lhs;
} else if (token_type == TOKEN_REM_ASSIGN) {
int rhs = parse_assign_expr();
int rem = asm_rr_arith("rem", lhs, rhs);
asm_mv(lhs, rem);
return lhs;
} else if (token_type == TOKEN_LSHIFT_ASSIGN) {
int rhs = parse_assign_expr();
int lshift = asm_rr_arith("sll", lhs, rhs);
asm_mv(lhs, lshift);
return lhs;
} else if (token_type == TOKEN_RSHIFT_ASSIGN) {
int rhs = parse_assign_expr();
int rshift = asm_rr_arith("sra", lhs, rhs);
asm_mv(lhs, rshift);
return lhs;
} else if (token_type == TOKEN_AND_ASSIGN) {
int rhs = parse_assign_expr();
int and = asm_rr_arith("and", lhs, rhs);
asm_mv(lhs, and);
return lhs;
} else if (token_type == TOKEN_XOR_ASSIGN) {
int rhs = parse_assign_expr();
int xor = asm_rr_arith("xor", lhs, rhs);
asm_mv(lhs, xor);
return lhs;
} else if (token_type == TOKEN_OR_ASSIGN) {
int rhs = parse_assign_expr();
int or = asm_rr_arith("or", lhs, rhs);
asm_mv(lhs, or);
return lhs;
} else {
unget_token();
return lhs;
@ -1599,7 +1732,7 @@ void parse_function(const char* name) {
eprintf("array of pointers is not supported\n");
exit(1);
}
arg_type = arg_type | TYPE_PTR_MASK;
arg_type |= TYPE_PTR_MASK;
}
if (arg >= 8) {
eprintf("too many arguments\n");
@ -1646,7 +1779,7 @@ void parse_function(const char* name) {
int frame_size = (max_local_id - 1 + reg_used + 2) * 8;
if (reg_used > 10) reg_used = 10;
if (frame_size % 16 != 0) {
frame_size = frame_size + 8;
frame_size += 8;
}
// prolog
asm_label(prolog_label);