From fcc9daa39d20b522a7963e7c5445eef6ea853515 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Thu, 27 Aug 2020 21:57:11 +0900 Subject: [PATCH] Add &, |, ^, &=, |= and ^= --- chibicc.h | 3 +++ codegen.c | 9 +++++++++ parse.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++--- test/arith.c | 16 ++++++++++++++++ tokenize.c | 4 +++- type.c | 3 +++ 6 files changed, 82 insertions(+), 4 deletions(-) diff --git a/chibicc.h b/chibicc.h index a2e4ce8..83f13ae 100644 --- a/chibicc.h +++ b/chibicc.h @@ -90,6 +90,9 @@ typedef enum { ND_MUL, // * ND_DIV, // / ND_MOD, // % + ND_BITAND, // & + ND_BITOR, // | + ND_BITXOR, // ^ ND_EQ, // == ND_NE, // != ND_LT, // < diff --git a/codegen.c b/codegen.c index 606b7b9..2abef40 100644 --- a/codegen.c +++ b/codegen.c @@ -268,6 +268,15 @@ static void gen_expr(Node *node) { if (node->kind == ND_MOD) println(" mov %%rdx, %%rax"); return; + case ND_BITAND: + println(" and %%rdi, %%rax"); + return; + case ND_BITOR: + println(" or %%rdi, %%rax"); + return; + case ND_BITXOR: + println(" xor %%rdi, %%rax"); + return; case ND_EQ: case ND_NE: case ND_LT: diff --git a/parse.c b/parse.c index a7c0651..10b3a61 100644 --- a/parse.c +++ b/parse.c @@ -83,6 +83,9 @@ static Node *stmt(Token **rest, Token *tok); static Node *expr_stmt(Token **rest, Token *tok); static Node *expr(Token **rest, Token *tok); static Node *assign(Token **rest, Token *tok); +static Node *bitor(Token **rest, Token *tok); +static Node *bitxor(Token **rest, Token *tok); +static Node *bitand(Token **rest, Token *tok); static Node *equality(Token **rest, Token *tok); static Node *relational(Token **rest, Token *tok); static Node *add(Token **rest, Token *tok); @@ -702,10 +705,10 @@ static Node *to_assign(Node *binary) { return new_binary(ND_COMMA, expr1, expr2, tok); } -// assign = equality (assign-op assign)? -// assign-op = "=" | "+=" | "-=" | "*=" | "/=" | "%=" +// assign = bitor (assign-op assign)? +// assign-op = "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "&=" | "|=" | "^=" static Node *assign(Token **rest, Token *tok) { - Node *node = equality(&tok, tok); + Node *node = bitor(&tok, tok); if (equal(tok, "=")) return new_binary(ND_ASSIGN, node, assign(rest, tok->next), tok); @@ -725,6 +728,48 @@ static Node *assign(Token **rest, Token *tok) { if (equal(tok, "%=")) return to_assign(new_binary(ND_MOD, node, assign(rest, tok->next), tok)); + if (equal(tok, "&=")) + return to_assign(new_binary(ND_BITAND, node, assign(rest, tok->next), tok)); + + if (equal(tok, "|=")) + return to_assign(new_binary(ND_BITOR, node, assign(rest, tok->next), tok)); + + if (equal(tok, "^=")) + return to_assign(new_binary(ND_BITXOR, node, assign(rest, tok->next), tok)); + + *rest = tok; + return node; +} + +// bitor = bitxor ("|" bitxor)* +static Node *bitor(Token **rest, Token *tok) { + Node *node = bitxor(&tok, tok); + while (equal(tok, "|")) { + Token *start = tok; + node = new_binary(ND_BITOR, node, bitxor(&tok, tok->next), start); + } + *rest = tok; + return node; +} + +// bitxor = bitand ("^" bitand)* +static Node *bitxor(Token **rest, Token *tok) { + Node *node = bitand(&tok, tok); + while (equal(tok, "^")) { + Token *start = tok; + node = new_binary(ND_BITXOR, node, bitand(&tok, tok->next), start); + } + *rest = tok; + return node; +} + +// bitand = equality ("&" equality)* +static Node *bitand(Token **rest, Token *tok) { + Node *node = equality(&tok, tok); + while (equal(tok, "&")) { + Token *start = tok; + node = new_binary(ND_BITAND, node, equality(&tok, tok->next), start); + } *rest = tok; return node; } diff --git a/test/arith.c b/test/arith.c index 6353813..164627a 100644 --- a/test/arith.c +++ b/test/arith.c @@ -79,6 +79,22 @@ int main() { ASSERT(2, ({ int i=10; i%=4; i; })); ASSERT(2, ({ long i=10; i%=4; i; })); + ASSERT(0, 0&1); + ASSERT(1, 3&1); + ASSERT(3, 7&3); + ASSERT(10, -1&10); + + ASSERT(1, 0|1); + ASSERT(0b10011, 0b10000|0b00011); + + ASSERT(0, 0^0); + ASSERT(0, 0b1111^0b1111); + ASSERT(0b110100, 0b111000^0b001100); + + ASSERT(2, ({ int i=6; i&=3; i; })); + ASSERT(7, ({ int i=6; i|=3; i; })); + ASSERT(10, ({ int i=15; i^=5; i; })); + printf("OK\n"); return 0; } diff --git a/tokenize.c b/tokenize.c index edb8531..698f836 100644 --- a/tokenize.c +++ b/tokenize.c @@ -337,7 +337,9 @@ static Token *tokenize(char *filename, char *p) { startswith(p, "->") || startswith(p, "+=") || startswith(p, "-=") || startswith(p, "*=") || startswith(p, "/=") || startswith(p, "++") || - startswith(p, "--") || startswith(p, "%=")) { + startswith(p, "--") || startswith(p, "%=") || + startswith(p, "&=") || startswith(p, "|=") || + startswith(p, "^=")) { cur = new_token(TK_RESERVED, cur, p, 2); p += 2; continue; diff --git a/type.c b/type.c index 0a99a8c..3bcfc46 100644 --- a/type.c +++ b/type.c @@ -99,6 +99,9 @@ void add_type(Node *node) { case ND_MUL: case ND_DIV: case ND_MOD: + case ND_BITAND: + case ND_BITOR: + case ND_BITXOR: usual_arith_conv(&node->lhs, &node->rhs); node->ty = node->lhs->ty; return; -- GitLab