aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/codegen.c4
-rw-r--r--src/parse.c47
-rw-r--r--tests/114.sh26
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