Skip to content

Commit

Permalink
Add unary & and *
Browse files Browse the repository at this point in the history
  • Loading branch information
rui314 committed Oct 7, 2020
1 parent 3d86277 commit 863e2b8
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 2 deletions.
2 changes: 2 additions & 0 deletions chibicc.h
Expand Up @@ -71,6 +71,8 @@ typedef enum {
ND_LT, // <
ND_LE, // <=
ND_ASSIGN, // =
ND_ADDR, // unary &
ND_DEREF, // unary *
ND_RETURN, // "return"
ND_IF, // "if"
ND_FOR, // "for" or "while"
Expand Down
15 changes: 14 additions & 1 deletion codegen.c
Expand Up @@ -2,6 +2,8 @@

static int depth;

static void gen_expr(Node *node);

static int count(void) {
static int i = 1;
return i++;
Expand All @@ -26,9 +28,13 @@ static int align_to(int n, int align) {
// Compute the absolute address of a given node.
// It's an error if a given node does not reside in memory.
static void gen_addr(Node *node) {
if (node->kind == ND_VAR) {
switch (node->kind) {
case ND_VAR:
printf(" lea %d(%%rbp), %%rax\n", node->var->offset);
return;
case ND_DEREF:
gen_expr(node->lhs);
return;
}

error_tok(node->tok, "not an lvalue");
Expand All @@ -48,6 +54,13 @@ static void gen_expr(Node *node) {
gen_addr(node);
printf(" mov (%%rax), %%rax\n");
return;
case ND_DEREF:
gen_expr(node->lhs);
printf(" mov (%%rax), %%rax\n");
return;
case ND_ADDR:
gen_addr(node->lhs);
return;
case ND_ASSIGN:
gen_addr(node->lhs);
push();
Expand Down
26 changes: 25 additions & 1 deletion parse.c
@@ -1,3 +1,21 @@
// This file contains a recursive descent parser for C.
//
// Most functions in this file are named after the symbols they are
// supposed to read from an input token list. For example, stmt() is
// responsible for reading a statement from a token list. The function
// then construct an AST node representing a statement.
//
// Each function conceptually returns two values, an AST node and
// remaining part of the input tokens. Since C doesn't support
// multiple return values, the remaining tokens are returned to the
// caller via a pointer argument.
//
// Input tokens are represented by a linked list. Unlike many recursive
// descent parsers, we don't have the notion of the "input token stream".
// Most parsing functions don't change the global state of the parser.
// So it is very easy to lookahead arbitrary number of tokens in this
// parser.

#include "chibicc.h"

// All local variable instances created during parsing are
Expand Down Expand Up @@ -263,7 +281,7 @@ static Node *mul(Token **rest, Token *tok) {
}
}

// unary = ("+" | "-") unary
// unary = ("+" | "-" | "*" | "&") unary
// | primary
static Node *unary(Token **rest, Token *tok) {
if (equal(tok, "+"))
Expand All @@ -272,6 +290,12 @@ static Node *unary(Token **rest, Token *tok) {
if (equal(tok, "-"))
return new_unary(ND_NEG, unary(rest, tok->next), tok);

if (equal(tok, "&"))
return new_unary(ND_ADDR, unary(rest, tok->next), tok);

if (equal(tok, "*"))
return new_unary(ND_DEREF, unary(rest, tok->next), tok);

return primary(rest, tok);
}

Expand Down
8 changes: 8 additions & 0 deletions test.sh
Expand Up @@ -74,4 +74,12 @@ assert 3 '{ for (;;) {return 3;} return 5; }'

assert 10 '{ i=0; while(i<10) { i=i+1; } return i; }'

assert 3 '{ x=3; return *&x; }'
assert 3 '{ x=3; y=&x; z=&y; return **z; }'
assert 5 '{ x=3; y=5; return *(&x+8); }'
assert 3 '{ x=3; y=5; return *(&y-8); }'
assert 5 '{ x=3; y=&x; *y=5; return x; }'
assert 7 '{ x=3; y=5; *(&x+8)=7; return y; }'
assert 7 '{ x=3; y=5; *(&y-8)=7; return x; }'

echo OK

0 comments on commit 863e2b8

Please sign in to comment.