Skip to content

Commit

Permalink
Add <pointer> + <number> and <pointer> - <number>.
Browse files Browse the repository at this point in the history
  • Loading branch information
rui314 committed Aug 22, 2018
1 parent e43b738 commit 19ab268
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 7 deletions.
1 change: 1 addition & 0 deletions 9cc.h
Expand Up @@ -132,6 +132,7 @@ typedef struct Node {
} Node;

Vector *parse(Vector *tokens);
int size_of(Type *ty);

/// sema.c

Expand Down
20 changes: 17 additions & 3 deletions gen_ir.c
Expand Up @@ -173,9 +173,23 @@ static int gen_expr(Node *node) {
return lhs;
}
case '+':
return gen_binop(IR_ADD, node->lhs, node->rhs);
case '-':
return gen_binop(IR_SUB, node->lhs, node->rhs);
case '-': {
int insn = (node->op == '+') ? IR_ADD : IR_SUB;

if (node->lhs->ty->ty != PTR)
return gen_binop(insn, node->lhs, node->rhs);

int rhs = gen_expr(node->rhs);
int r = nreg++;
add(IR_IMM, r, size_of(node->lhs->ty->ptr_of));
add(IR_MUL, rhs, r);
kill(r);

int lhs = gen_expr(node->lhs);
add(insn, lhs, rhs);
kill(rhs);
return lhs;
}
case '*':
return gen_binop(IR_MUL, node->lhs, node->rhs);
case '/':
Expand Down
26 changes: 25 additions & 1 deletion sema.c
Expand Up @@ -10,6 +10,19 @@ typedef struct {
static Map *vars;
static int stacksize;

int size_of(Type *ty) {
if (ty->ty == INT)
return 4;
assert(ty->ty == PTR);
return 8;
}

static void swap(Node **p, Node **q) {
Node *r = *p;
*p = *q;
*q = r;
}

static void walk(Node *node) {
switch (node->op) {
case ND_NUM:
Expand Down Expand Up @@ -49,11 +62,17 @@ static void walk(Node *node) {
walk(node->body);
return;
case '+':
case '-':
walk(node->lhs);
walk(node->rhs);

if (node->rhs->ty->ty == PTR)
swap(&node->lhs, &node->rhs);
if (node->rhs->ty->ty == PTR)
error("'pointer %c pointer' is not defined", node->op);

node->ty = node->lhs->ty;
return;
case '-':
case '*':
case '/':
case '=':
Expand All @@ -65,6 +84,11 @@ static void walk(Node *node) {
node->ty = node->lhs->ty;
return;
case ND_DEREF:
walk(node->expr);
if (node->expr->ty->ty != PTR)
error("operand must be a pointer");
node->ty = node->expr->ty->ptr_of;
return;
case ND_RETURN:
walk(node->expr);
return;
Expand Down
26 changes: 23 additions & 3 deletions test.sh
Expand Up @@ -19,11 +19,29 @@ try() {
cat <<EOF | gcc -xc -c -o tmp-test.o -
int plus(int x, int y) { return x + y; }
int *alloc(int x) {
static int arr[1];
int *alloc1(int x, int y) {
static int arr[2];
arr[0] = x;
arr[1] = y;
return arr;
}
int *alloc2(int x, int y) {
static int arr[2];
arr[0] = x;
arr[1] = y;
return arr + 1;
}
int **alloc_ptr_ptr(int x) {
static int **p;
static int *q;
static int r;
r = x;
q = &r;
p = &q;
return p;
}
EOF

try 1 'int main() { return 1; }'
Expand Down Expand Up @@ -73,6 +91,8 @@ try 1 'int main() { return 1>0; }'
try 60 'int main() { int sum=0; int i; for (i=10; i<15; i=i+1) sum = sum + i; return sum;}'
try 89 'int main() { int i=1; int j=1; for (int k=0; k<10; k=k+1) { int m=i+j; i=j; j=m; } return i;}'

try 42 'int main() { int *p = alloc(42); return *p; }'
try 8 'int main() { int *p = alloc1(3, 5); return *p + *(p + 1); }'
try 9 'int main() { int *p = alloc2(2, 7); return *p + *(p - 1); }'
try 2 'int main() { int **p = alloc_ptr_ptr(2); return **p; }'

echo OK

0 comments on commit 19ab268

Please sign in to comment.