Skip to content

Commit c123e64

Browse files
committed
Add one dimensional arrays
1 parent f252093 commit c123e64

File tree

5 files changed

+102
-31
lines changed

5 files changed

+102
-31
lines changed

chibicc.h

+15-2
Original file line numberDiff line numberDiff line change
@@ -127,17 +127,29 @@ typedef enum {
127127
TY_INT,
128128
TY_PTR,
129129
TY_FUNC,
130+
TY_ARRAY,
130131
} TypeKind;
131132

132133
struct Type {
133134
TypeKind kind;
134-
135-
// Pointer
135+
int size; // sizeof() value
136+
137+
// Pointer-to or array-of type. We intentionally use the same member
138+
// to represent pointer/array duality in C.
139+
//
140+
// In many contexts in which a pointer is expected, we examine this
141+
// member instead of "kind" member to determine whether a type is a
142+
// pointer or not. That means in many contexts "array of T" is
143+
// naturally handled as if it were "pointer to T", as required by
144+
// the C spec.
136145
Type *base;
137146

138147
// Declaration
139148
Token *name;
140149

150+
// Array
151+
int array_len;
152+
141153
// Function type
142154
Type *return_ty;
143155
Type *params;
@@ -150,6 +162,7 @@ bool is_integer(Type *ty);
150162
Type *copy_type(Type *ty);
151163
Type *pointer_to(Type *base);
152164
Type *func_type(Type *return_ty);
165+
Type *array_of(Type *base, int size);
153166
void add_type(Node *node);
154167

155168
//

codegen.c

+25-5
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,27 @@ static void gen_addr(Node *node) {
4242
error_tok(node->tok, "not an lvalue");
4343
}
4444

45+
// Load a value from where %rax is pointing to.
46+
static void load(Type *ty) {
47+
if (ty->kind == TY_ARRAY) {
48+
// If it is an array, do not attempt to load a value to the
49+
// register because in general we can't load an entire array to a
50+
// register. As a result, the result of an evaluation of an array
51+
// becomes not the array itself but the address of the array.
52+
// This is where "array is automatically converted to a pointer to
53+
// the first element of the array in C" occurs.
54+
return;
55+
}
56+
57+
printf(" mov (%%rax), %%rax\n");
58+
}
59+
60+
// Store %rax to an address that the stack top is pointing to.
61+
static void store(void) {
62+
pop("%rdi");
63+
printf(" mov %%rax, (%%rdi)\n");
64+
}
65+
4566
// Generate code for a given node.
4667
static void gen_expr(Node *node) {
4768
switch (node->kind) {
@@ -54,11 +75,11 @@ static void gen_expr(Node *node) {
5475
return;
5576
case ND_VAR:
5677
gen_addr(node);
57-
printf(" mov (%%rax), %%rax\n");
78+
load(node->ty);
5879
return;
5980
case ND_DEREF:
6081
gen_expr(node->lhs);
61-
printf(" mov (%%rax), %%rax\n");
82+
load(node->ty);
6283
return;
6384
case ND_ADDR:
6485
gen_addr(node->lhs);
@@ -67,8 +88,7 @@ static void gen_expr(Node *node) {
6788
gen_addr(node->lhs);
6889
push();
6990
gen_expr(node->rhs);
70-
pop("%rdi");
71-
printf(" mov %%rax, (%%rdi)\n");
91+
store();
7292
return;
7393
case ND_FUNCALL: {
7494
int nargs = 0;
@@ -181,7 +201,7 @@ static void assign_lvar_offsets(Function *prog) {
181201
for (Function *fn = prog; fn; fn = fn->next) {
182202
int offset = 0;
183203
for (Obj *var = fn->locals; var; var = var->next) {
184-
offset += 8;
204+
offset += var->ty->size;
185205
var->offset = -offset;
186206
}
187207
fn->stack_size = align_to(offset, 16);

parse.c

+36-21
Original file line numberDiff line numberDiff line change
@@ -92,34 +92,49 @@ static char *get_ident(Token *tok) {
9292
return strndup(tok->loc, tok->len);
9393
}
9494

95+
static int get_number(Token *tok) {
96+
if (tok->kind != TK_NUM)
97+
error_tok(tok, "expected a number");
98+
return tok->val;
99+
}
100+
95101
// typespec = "int"
96102
static Type *typespec(Token **rest, Token *tok) {
97103
*rest = skip(tok, "int");
98104
return ty_int;
99105
}
100106

101-
// type-suffix = ("(" func-params? ")")?
102-
// func-params = param ("," param)*
107+
// func-params = (param ("," param)*)? ")"
103108
// param = typespec declarator
104-
static Type *type_suffix(Token **rest, Token *tok, Type *ty) {
105-
if (equal(tok, "(")) {
106-
tok = tok->next;
109+
static Type *func_params(Token **rest, Token *tok, Type *ty) {
110+
Type head = {};
111+
Type *cur = &head;
112+
113+
while (!equal(tok, ")")) {
114+
if (cur != &head)
115+
tok = skip(tok, ",");
116+
Type *basety = typespec(&tok, tok);
117+
Type *ty = declarator(&tok, tok, basety);
118+
cur = cur->next = copy_type(ty);
119+
}
107120

108-
Type head = {};
109-
Type *cur = &head;
121+
ty = func_type(ty);
122+
ty->params = head.next;
123+
*rest = tok->next;
124+
return ty;
125+
}
110126

111-
while (!equal(tok, ")")) {
112-
if (cur != &head)
113-
tok = skip(tok, ",");
114-
Type *basety = typespec(&tok, tok);
115-
Type *ty = declarator(&tok, tok, basety);
116-
cur = cur->next = copy_type(ty);
117-
}
127+
// type-suffix = "(" func-params
128+
// | "[" num "]"
129+
// | ε
130+
static Type *type_suffix(Token **rest, Token *tok, Type *ty) {
131+
if (equal(tok, "("))
132+
return func_params(rest, tok->next, ty);
118133

119-
ty = func_type(ty);
120-
ty->params = head.next;
121-
*rest = tok->next;
122-
return ty;
134+
if (equal(tok, "[")) {
135+
int sz = get_number(tok->next);
136+
*rest = skip(tok->next->next, "]");
137+
return array_of(ty, sz);
123138
}
124139

125140
*rest = tok;
@@ -353,7 +368,7 @@ static Node *new_add(Node *lhs, Node *rhs, Token *tok) {
353368
}
354369

355370
// ptr + num
356-
rhs = new_binary(ND_MUL, rhs, new_num(8, tok), tok);
371+
rhs = new_binary(ND_MUL, rhs, new_num(lhs->ty->base->size, tok), tok);
357372
return new_binary(ND_ADD, lhs, rhs, tok);
358373
}
359374

@@ -368,7 +383,7 @@ static Node *new_sub(Node *lhs, Node *rhs, Token *tok) {
368383

369384
// ptr - num
370385
if (lhs->ty->base && is_integer(rhs->ty)) {
371-
rhs = new_binary(ND_MUL, rhs, new_num(8, tok), tok);
386+
rhs = new_binary(ND_MUL, rhs, new_num(lhs->ty->base->size, tok), tok);
372387
add_type(rhs);
373388
Node *node = new_binary(ND_SUB, lhs, rhs, tok);
374389
node->ty = lhs->ty;
@@ -379,7 +394,7 @@ static Node *new_sub(Node *lhs, Node *rhs, Token *tok) {
379394
if (lhs->ty->base && rhs->ty->base) {
380395
Node *node = new_binary(ND_SUB, lhs, rhs, tok);
381396
node->ty = ty_int;
382-
return new_binary(ND_DIV, node, new_num(8, tok), tok);
397+
return new_binary(ND_DIV, node, new_num(lhs->ty->base->size, tok), tok);
383398
}
384399

385400
error_tok(tok, "invalid operands");

test.sh

+6
Original file line numberDiff line numberDiff line change
@@ -112,4 +112,10 @@ assert 7 'int main() { return add2(3,4); } int add2(int x, int y) { return x+y;
112112
assert 1 'int main() { return sub2(4,3); } int sub2(int x, int y) { return x-y; }'
113113
assert 55 'int main() { return fib(9); } int fib(int x) { if (x<=1) return 1; return fib(x-1) + fib(x-2); }'
114114

115+
assert 3 'int main() { int x[2]; int *y=&x; *y=3; return *x; }'
116+
117+
assert 3 'int main() { int x[3]; *x=3; *(x+1)=4; *(x+2)=5; return *x; }'
118+
assert 4 'int main() { int x[3]; *x=3; *(x+1)=4; *(x+2)=5; return *(x+1); }'
119+
assert 5 'int main() { int x[3]; *x=3; *(x+1)=4; *(x+2)=5; return *(x+2); }'
120+
115121
echo OK

type.c

+20-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#include "chibicc.h"
22

3-
Type *ty_int = &(Type){TY_INT};
3+
Type *ty_int = &(Type){TY_INT, 8};
44

55
bool is_integer(Type *ty) {
66
return ty->kind == TY_INT;
@@ -15,6 +15,7 @@ Type *copy_type(Type *ty) {
1515
Type *pointer_to(Type *base) {
1616
Type *ty = calloc(1, sizeof(Type));
1717
ty->kind = TY_PTR;
18+
ty->size = 8;
1819
ty->base = base;
1920
return ty;
2021
}
@@ -26,6 +27,15 @@ Type *func_type(Type *return_ty) {
2627
return ty;
2728
}
2829

30+
Type *array_of(Type *base, int len) {
31+
Type *ty = calloc(1, sizeof(Type));
32+
ty->kind = TY_ARRAY;
33+
ty->size = base->size * len;
34+
ty->base = base;
35+
ty->array_len = len;
36+
return ty;
37+
}
38+
2939
void add_type(Node *node) {
3040
if (!node || node->ty)
3141
return;
@@ -49,7 +59,11 @@ void add_type(Node *node) {
4959
case ND_MUL:
5060
case ND_DIV:
5161
case ND_NEG:
62+
node->ty = node->lhs->ty;
63+
return;
5264
case ND_ASSIGN:
65+
if (node->lhs->ty->kind == TY_ARRAY)
66+
error_tok(node->lhs->tok, "not an lvalue");
5367
node->ty = node->lhs->ty;
5468
return;
5569
case ND_EQ:
@@ -64,10 +78,13 @@ void add_type(Node *node) {
6478
node->ty = node->var->ty;
6579
return;
6680
case ND_ADDR:
67-
node->ty = pointer_to(node->lhs->ty);
81+
if (node->lhs->ty->kind == TY_ARRAY)
82+
node->ty = pointer_to(node->lhs->ty->base);
83+
else
84+
node->ty = pointer_to(node->lhs->ty);
6885
return;
6986
case ND_DEREF:
70-
if (node->lhs->ty->kind != TY_PTR)
87+
if (!node->lhs->ty->base)
7188
error_tok(node->tok, "invalid pointer dereference");
7289
node->ty = node->lhs->ty->base;
7390
return;

0 commit comments

Comments
 (0)