complete operators
This commit is contained in:
parent
8114d04fb9
commit
e18bf2c2d3
187
boot.c
187
boot.c
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user