Skip to content

Commit

Permalink
feat: add <<, >>, <<=, >>>=
Browse files Browse the repository at this point in the history
  • Loading branch information
diohabara committed Jul 26, 2023
1 parent 4cbd6ca commit 1adbe08
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 9 deletions.
4 changes: 4 additions & 0 deletions ccc.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ typedef enum {
ND_BITXOR, // ^
ND_LOGAND, // &&
ND_LOGOR, // ||
ND_SHL, // <<
ND_SHR, // >>
ND_A_SHL, // <<=
ND_A_SHR, // >>=
} NodeKind;
// AST node type
typedef struct Node Node;
Expand Down
19 changes: 19 additions & 0 deletions codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,8 @@ void gen(Node *node) {
case ND_A_MUL:
case ND_A_DIV:
case ND_A_MOD:
case ND_A_SHL:
case ND_A_SHR: {
gen_lval(node->lhs);
printf(" push [rsp]\n");
load(node->ty);
Expand Down Expand Up @@ -427,10 +429,19 @@ void gen(Node *node) {
printf(" idiv rdi\n");
printf(" mov rax, rdx\n");
break;
case ND_A_SHL:
printf(" mov cl, dil\n");
printf(" shl rax, cl\n");
break;
case ND_A_SHR:
printf(" mov cl, dil\n");
printf(" sar rax, cl\n");
break;
}
printf(" push rax\n");
store(node->ty);
return;
}
case ND_NOT:
gen(node->lhs);
printf(" pop rax\n");
Expand Down Expand Up @@ -500,6 +511,14 @@ void gen(Node *node) {
case ND_BITXOR:
printf(" xor rax, rdi\n");
break;
case ND_SHL:
printf(" mov cl, dil\n");
printf(" shl rax, cl\n");
break;
case ND_SHR:
printf(" mov cl, dil\n");
printf(" sar rax, cl\n");
break;
}
printf(" push rax\n");
}
Expand Down
37 changes: 30 additions & 7 deletions parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ Node *logand();
Node *logor();
Node *equality();
Node *relational();
Node *shift();
Node *add();
Node *mul();
Node *cast();
Expand Down Expand Up @@ -820,7 +821,7 @@ Node *expr() {
return node;
}
// assign = logor (assign-op assign)?
// assign-op = "=" | "+=" | "-=" | "*=" | "/=" | "%="
// assign-op = "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "<<=" | ">>="
Node *assign() {
Node *node = logor();
Token *tok;
Expand All @@ -842,6 +843,12 @@ Node *assign() {
if (tok = consume("%=")) {
node = new_binary(ND_A_MOD, node, assign(), tok);
}
if (tok = consume("<<=")) {
node = new_binary(ND_A_SHL, node, assign(), tok);
}
if (tok = consume(">>=")) {
node = new_binary(ND_A_SHR, node, assign(), tok);
}
return node;
}

Expand Down Expand Up @@ -909,24 +916,40 @@ Node *equality() {
}
}

// relational = add ("<" add | "<=" add | ">" add | ">=" add)*
// relational = shift ("<" shift | "<=" shift | ">" shift | ">=" shift)*
Node *relational() {
Node *node = add();
Node *node = shift();
Token *tok;
for (;;) {
if (tok = consume("<"))
node = new_binary(ND_LT, node, add(), tok);
node = new_binary(ND_LT, node, shift(), tok);
else if (tok = consume("<="))
node = new_binary(ND_LE, node, add(), tok);
node = new_binary(ND_LE, node, shift(), tok);
else if (tok = consume(">"))
node = new_binary(ND_LT, add(), node, tok);
node = new_binary(ND_LT, shift(), node, tok);
else if (tok = consume(">="))
node = new_binary(ND_LE, add(), node, tok);
node = new_binary(ND_LE, shift(), node, tok);
else
return node;
}
}

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

for (;;) {
if (tok = consume("<<")) {
node = new_binary(ND_SHL, node, add(), tok);
} else if (tok = consume(">>")) {
node = new_binary(ND_SHR, node, add(), tok);
} else {
return node;
}
}
}

// add = mul ("+" mul | "-" mul)*
Node *add() {
Node *node = mul();
Expand Down
13 changes: 13 additions & 0 deletions tests
Original file line number Diff line number Diff line change
Expand Up @@ -811,6 +811,19 @@ int main() {
assert(1, ({ struct T { struct T *next; int x; } a; struct T b; b.x=1; a.next=&b; a.next->x; }), "struct T { struct T *next; int x; } a; struct T b; b.x=1; a.next=&b; a.next->x;");

voidfn();

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

printf("OK\n");
return 0;
Expand Down
4 changes: 2 additions & 2 deletions tokenize.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,8 @@ char *starts_with_reserved(char *p) {
}
}
// Multi-letter punctuator
static char *ops[] = {"==", "!=", "<=", ">=", "->", "++", "--",
"+=", "-=", "*=", "/=", "&=", "&&", "||"};
static char *ops[] = {"<<=", ">>=", "==", "!=", "<=", ">=", "->", "++", "--",
"<<", ">>", "+=", "-=", "*=", "/=", "&&", "||"};
for (int i = 0; i < sizeof(ops) / sizeof(*ops); i++)
if (startswith(p, ops[i])) {
return ops[i];
Expand Down
4 changes: 4 additions & 0 deletions type.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ void visit(Node* node) {
node->ty = node->lhs->ty;
return;
case ND_ASSIGN:
case ND_SHL:
case ND_SHR:
case ND_PRE_INC:
case ND_PRE_DEC:
case ND_POST_INC:
Expand All @@ -158,6 +160,8 @@ void visit(Node* node) {
case ND_A_MUL:
case ND_A_DIV:
case ND_A_MOD:
case ND_A_SHL:
case ND_A_SHR:
case ND_BITNOT:
node->ty = node->lhs->ty;
return;
Expand Down

0 comments on commit 1adbe08

Please sign in to comment.