diff options
| -rw-r--r-- | src/codegen.c | 4 | ||||
| -rw-r--r-- | src/parse.c | 47 | ||||
| -rw-r--r-- | tests/114.sh | 26 |
3 files changed, 69 insertions, 8 deletions
diff --git a/src/codegen.c b/src/codegen.c index d66574f..9aa9a77 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -180,8 +180,12 @@ static void codegen_binary_expr(CodeGen* g, AstNode* ast, GenMode gen_mode) { fprintf(g->out, " cqo\n"); fprintf(g->out, " idiv rdi\n"); fprintf(g->out, " mov rax, rdx\n"); + } else if (ast->node_op == TokenKind_and) { + fprintf(g->out, " and rax, rdi\n"); } else if (ast->node_op == TokenKind_or) { fprintf(g->out, " or rax, rdi\n"); + } else if (ast->node_op == TokenKind_xor) { + fprintf(g->out, " xor rax, rdi\n"); } else if (ast->node_op == TokenKind_lshift) { fprintf(g->out, " mov rcx, rdi\n"); fprintf(g->out, " shl rax, cl\n"); diff --git a/src/parse.c b/src/parse.c index 0a63870..422cc64 100644 --- a/src/parse.c +++ b/src/parse.c @@ -691,13 +691,40 @@ static AstNode* parse_equality_expr(Parser* p) { return lhs; } -static AstNode* parse_bitwise_or_expr(Parser* p) { +static AstNode* parse_bitwise_and_expr(Parser* p) { AstNode* lhs = parse_equality_expr(p); while (1) { - TokenKind op = peek_token(p)->kind; - if (consume_token_if(p, TokenKind_or)) { + if (consume_token_if(p, TokenKind_and)) { AstNode* rhs = parse_equality_expr(p); - lhs = ast_new_binary_expr(op, lhs, rhs); + lhs = ast_new_binary_expr(TokenKind_and, lhs, rhs); + lhs->ty = type_new(TypeKind_int); + } else { + break; + } + } + return lhs; +} + +static AstNode* parse_bitwise_xor_expr(Parser* p) { + AstNode* lhs = parse_bitwise_and_expr(p); + while (1) { + if (consume_token_if(p, TokenKind_xor)) { + AstNode* rhs = parse_bitwise_and_expr(p); + lhs = ast_new_binary_expr(TokenKind_xor, lhs, rhs); + lhs->ty = type_new(TypeKind_int); + } else { + break; + } + } + return lhs; +} + +static AstNode* parse_bitwise_or_expr(Parser* p) { + AstNode* lhs = parse_bitwise_xor_expr(p); + while (1) { + if (consume_token_if(p, TokenKind_or)) { + AstNode* rhs = parse_bitwise_xor_expr(p); + lhs = ast_new_binary_expr(TokenKind_or, lhs, rhs); lhs->ty = type_new(TypeKind_int); } else { break; @@ -709,11 +736,10 @@ static AstNode* parse_bitwise_or_expr(Parser* p) { static AstNode* parse_logical_and_expr(Parser* p) { AstNode* lhs = parse_bitwise_or_expr(p); while (1) { - TokenKind op = peek_token(p)->kind; if (consume_token_if(p, TokenKind_andand)) { AstNode* rhs = parse_bitwise_or_expr(p); AstNode* e = ast_new(AstNodeKind_logical_expr); - e->node_op = op; + e->node_op = TokenKind_andand; e->node_lhs = lhs; e->node_rhs = rhs; e->ty = type_new(TypeKind_int); @@ -728,11 +754,10 @@ static AstNode* parse_logical_and_expr(Parser* p) { static AstNode* parse_logical_or_expr(Parser* p) { AstNode* lhs = parse_logical_and_expr(p); while (1) { - TokenKind op = peek_token(p)->kind; if (consume_token_if(p, TokenKind_oror)) { AstNode* rhs = parse_logical_and_expr(p); AstNode* e = ast_new(AstNodeKind_logical_expr); - e->node_op = op; + e->node_op = TokenKind_oror; e->node_lhs = lhs; e->node_rhs = rhs; e->ty = type_new(TypeKind_int); @@ -1846,6 +1871,12 @@ static int eval(AstNode* e) { return v1 << v2; } else if (e->node_op == TokenKind_rshift) { return v1 >> v2; + } else if (e->node_op == TokenKind_and) { + return v1 & v2; + } else if (e->node_op == TokenKind_or) { + return v1 | v2; + } else if (e->node_op == TokenKind_xor) { + return v1 ^ v2; } else { unimplemented(); } diff --git a/tests/114.sh b/tests/114.sh new file mode 100644 index 0000000..1ba1e8a --- /dev/null +++ b/tests/114.sh @@ -0,0 +1,26 @@ +cat <<'EOF' > expected +1 +7 +6 +4 +3 2 3 0 +EOF +test_diff <<'EOF' +int printf(); + +int main() { + int a = 5; + int b = 3; + + printf("%d\n", a & b); + printf("%d\n", a | b); + printf("%d\n", a ^ b); + printf("%d\n", 2 + 3 & 4); + + int c = 1 + 2 & 3; + int d = 4 & 5 ^ 6; + int e = 1 ^ 2 | 3; + int f = 0 | 1 & 2; + printf("%d %d %d %d\n", c, d, e, f); +} +EOF |
