Skip to content

Commit

Permalink
Add <<, >>, <<= and >>=
Browse files Browse the repository at this point in the history
  • Loading branch information
rui314 committed Sep 28, 2020
1 parent d19058f commit 1fd27bf
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 8 deletions.
2 changes: 2 additions & 0 deletions chibicc.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ typedef enum {
ND_BITAND, // &
ND_BITOR, // |
ND_BITXOR, // ^
ND_SHL, // <<
ND_SHR, // >>
ND_EQ, // ==
ND_NE, // !=
ND_LT, // <
Expand Down
11 changes: 11 additions & 0 deletions codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,17 @@ static void gen_expr(Node *node) {

println(" movzb %%al, %%rax");
return;
case ND_SHL:
println(" mov %%rdi, %%rcx");
println(" shl %%cl, %s", ax);
return;
case ND_SHR:
println(" mov %%rdi, %%rcx");
if (node->ty->size == 8)
println(" sar %%cl, %s", ax);
else
println(" sar %%cl, %s", ax);
return;
}

error_tok(node->tok, "invalid expression");
Expand Down
42 changes: 36 additions & 6 deletions parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ 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 *shift(Token **rest, Token *tok);
static Node *add(Token **rest, Token *tok);
static Node *new_add(Node *lhs, Node *rhs, Token *tok);
static Node *new_sub(Node *lhs, Node *rhs, Token *tok);
Expand Down Expand Up @@ -857,6 +858,7 @@ static Node *to_assign(Node *binary) {

// assign = logor (assign-op assign)?
// assign-op = "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "&=" | "|=" | "^="
// | "<<=" | ">>="
static Node *assign(Token **rest, Token *tok) {
Node *node = logor(&tok, tok);

Expand Down Expand Up @@ -887,6 +889,12 @@ static Node *assign(Token **rest, Token *tok) {
if (equal(tok, "^="))
return to_assign(new_binary(ND_BITXOR, node, assign(rest, tok->next), tok));

if (equal(tok, "<<="))
return to_assign(new_binary(ND_SHL, node, assign(rest, tok->next), tok));

if (equal(tok, ">>="))
return to_assign(new_binary(ND_SHR, node, assign(rest, tok->next), tok));

*rest = tok;
return node;
}
Expand Down Expand Up @@ -968,30 +976,52 @@ static Node *equality(Token **rest, Token *tok) {
}
}

// relational = add ("<" add | "<=" add | ">" add | ">=" add)*
// relational = shift ("<" shift | "<=" shift | ">" shift | ">=" shift)*
static Node *relational(Token **rest, Token *tok) {
Node *node = add(&tok, tok);
Node *node = shift(&tok, tok);

for (;;) {
Token *start = tok;

if (equal(tok, "<")) {
node = new_binary(ND_LT, node, add(&tok, tok->next), start);
node = new_binary(ND_LT, node, shift(&tok, tok->next), start);
continue;
}

if (equal(tok, "<=")) {
node = new_binary(ND_LE, node, add(&tok, tok->next), start);
node = new_binary(ND_LE, node, shift(&tok, tok->next), start);
continue;
}

if (equal(tok, ">")) {
node = new_binary(ND_LT, add(&tok, tok->next), node, start);
node = new_binary(ND_LT, shift(&tok, tok->next), node, start);
continue;
}

if (equal(tok, ">=")) {
node = new_binary(ND_LE, add(&tok, tok->next), node, start);
node = new_binary(ND_LE, shift(&tok, tok->next), node, start);
continue;
}

*rest = tok;
return node;
}
}

// shift = add ("<<" add | ">>" add)*
static Node *shift(Token **rest, Token *tok) {
Node *node = add(&tok, tok);

for (;;) {
Token *start = tok;

if (equal(tok, "<<")) {
node = new_binary(ND_SHL, node, add(&tok, tok->next), start);
continue;
}

if (equal(tok, ">>")) {
node = new_binary(ND_SHR, node, add(&tok, tok->next), start);
continue;
}

Expand Down
13 changes: 13 additions & 0 deletions test/arith.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,19 @@ int main() {
ASSERT(7, ({ int i=6; i|=3; i; }));
ASSERT(10, ({ int i=15; i^=5; i; }));

ASSERT(1, 1<<0);
ASSERT(8, 1<<3);
ASSERT(10, 5<<1);
ASSERT(2, 5>>1);
ASSERT(-1, -1>>1);
ASSERT(1, ({ int i=1; i<<=0; i; }));
ASSERT(8, ({ int i=1; i<<=3; i; }));
ASSERT(10, ({ int i=5; i<<=1; i; }));
ASSERT(2, ({ int i=5; i>>=1; i; }));
ASSERT(-1, -1);
ASSERT(-1, ({ int i=-1; i; }));
ASSERT(-1, ({ int i=-1; i>>=1; i; }));

printf("OK\n");
return 0;
}
12 changes: 10 additions & 2 deletions tokenize.c
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,14 @@ static Token *tokenize(char *filename, char *p) {
continue;
}

// Multi-letter punctuators
// Three-letter punctuators
if (startswith(p, "<<=") || startswith(p, ">>=")) {
cur = cur->next = new_token(TK_RESERVED, p, p + 3);
p += 3;
continue;
}

// Two-letter punctuators
if (startswith(p, "==") || startswith(p, "!=") ||
startswith(p, "<=") || startswith(p, ">=") ||
startswith(p, "->") || startswith(p, "+=") ||
Expand All @@ -341,7 +348,8 @@ 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, ">>")) {
cur = cur->next = new_token(TK_RESERVED, p, p + 2);
p += 2;
continue;
Expand Down
2 changes: 2 additions & 0 deletions type.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ void add_type(Node *node) {
node->ty = ty_int;
return;
case ND_BITNOT:
case ND_SHL:
case ND_SHR:
node->ty = node->lhs->ty;
return;
case ND_VAR:
Expand Down

0 comments on commit 1fd27bf

Please sign in to comment.