Skip to content

Commit

Permalink
Add <<, >>, <<= and >>=
Browse files Browse the repository at this point in the history
  • Loading branch information
rui314 committed Dec 7, 2020
1 parent 044d9ae commit d0c0cb7
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 8 deletions.
2 changes: 2 additions & 0 deletions chibicc.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,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 @@ -329,6 +329,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 @@ -97,6 +97,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 @@ -844,6 +845,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 @@ -874,6 +876,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 @@ -955,30 +963,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;
}
5 changes: 3 additions & 2 deletions tokenize.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,9 @@ static int from_hex(char c) {
// Read a punctuator token from p and returns its length.
static int read_punct(char *p) {
static char *kw[] = {
"==", "!=", "<=", ">=", "->", "+=", "-=", "*=", "/=", "++", "--",
"%=", "&=", "|=", "^=", "&&", "||",
"<<=", ">>=", "==", "!=", "<=", ">=", "->", "+=",
"-=", "*=", "/=", "++", "--", "%=", "&=", "|=", "^=", "&&",
"||", "<<", ">>",
};

for (int i = 0; i < sizeof(kw) / sizeof(*kw); i++)
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 d0c0cb7

Please sign in to comment.