aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--ast.c30
-rw-r--r--codegen.c4
-rw-r--r--parse.c11
-rw-r--r--tests/068.sh29
4 files changed, 71 insertions, 3 deletions
diff --git a/ast.c b/ast.c
index d67bb01..0326855 100644
--- a/ast.c
+++ b/ast.c
@@ -6,6 +6,7 @@ enum TypeKind {
TypeKind_long,
TypeKind_void,
TypeKind_ptr,
+ TypeKind_array,
TypeKind_enum,
TypeKind_struct,
};
@@ -16,6 +17,7 @@ struct AstNode;
struct Type {
TypeKind kind;
struct Type* to;
+ int array_size;
struct AstNode* def;
};
typedef struct Type Type;
@@ -33,6 +35,18 @@ Type* type_new_ptr(Type* to) {
return ty;
}
+Type* type_new_array(Type* elem, int size) {
+ Type* ty = calloc(1, sizeof(Type));
+ ty->kind = TypeKind_array;
+ ty->to = elem;
+ ty->array_size = size;
+ return ty;
+}
+
+Type* type_array_to_ptr(Type* ty) {
+ return type_new_ptr(ty->to);
+}
+
int type_is_unsized(Type* ty) {
return ty->kind != TypeKind_void;
}
@@ -57,6 +71,8 @@ int type_sizeof(Type* ty) {
return 8;
} else if (ty->kind == TypeKind_enum) {
return 4;
+ } else if (ty->kind == TypeKind_array) {
+ return type_sizeof(ty->to) * ty->array_size;
} else {
return type_sizeof_struct(ty);
}
@@ -77,6 +93,8 @@ int type_alignof(Type* ty) {
return 8;
} else if (ty->kind == TypeKind_enum) {
return 4;
+ } else if (ty->kind == TypeKind_array) {
+ return type_alignof(ty->to);
} else {
return type_alignof_struct(ty);
}
@@ -209,14 +227,20 @@ AstNode* ast_new_binary_expr(int op, AstNode* lhs, AstNode* rhs) {
if (op == TokenKind_plus) {
if (lhs->ty->kind == TypeKind_ptr) {
e->ty = lhs->ty;
+ } else if (lhs->ty->kind == TypeKind_array) {
+ e->ty = type_array_to_ptr(lhs->ty);
} else if (rhs->ty->kind == TypeKind_ptr) {
e->ty = rhs->ty;
+ } else if (rhs->ty->kind == TypeKind_array) {
+ e->ty = type_array_to_ptr(rhs->ty);
} else {
e->ty = type_new(TypeKind_int);
}
} else if (op == TokenKind_minus) {
if (lhs->ty->kind == TypeKind_ptr) {
e->ty = lhs->ty;
+ } else if (lhs->ty->kind == TypeKind_array) {
+ e->ty = type_array_to_ptr(lhs->ty);
} else {
e->ty = type_new(TypeKind_int);
}
@@ -236,16 +260,16 @@ AstNode* ast_new_assign_expr(int op, AstNode* lhs, AstNode* rhs) {
}
AstNode* ast_new_assign_add_expr(AstNode* lhs, AstNode* rhs) {
- if (lhs->ty->kind == TypeKind_ptr) {
+ if (lhs->ty->kind == TypeKind_ptr || lhs->ty->kind == TypeKind_array) {
rhs = ast_new_binary_expr(TokenKind_star, rhs, ast_new_int(type_sizeof(lhs->ty->to)));
- } else if (rhs->ty->kind == TypeKind_ptr) {
+ } else if (rhs->ty->kind == TypeKind_ptr || rhs->ty->kind == TypeKind_array) {
lhs = ast_new_binary_expr(TokenKind_star, lhs, ast_new_int(type_sizeof(rhs->ty->to)));
}
return ast_new_assign_expr(TokenKind_assign_add, lhs, rhs);
}
AstNode* ast_new_assign_sub_expr(AstNode* lhs, AstNode* rhs) {
- if (lhs->ty->kind == TypeKind_ptr) {
+ if (lhs->ty->kind == TypeKind_ptr || lhs->ty->kind == TypeKind_array) {
rhs = ast_new_binary_expr(TokenKind_star, rhs, ast_new_int(type_sizeof(lhs->ty->to)));
}
return ast_new_assign_expr(TokenKind_assign_sub, lhs, rhs);
diff --git a/codegen.c b/codegen.c
index 0a90602..5b6f4c8 100644
--- a/codegen.c
+++ b/codegen.c
@@ -88,6 +88,10 @@ void codegen_ref_expr(CodeGen* g, AstNode* ast, GenMode gen_mode) {
}
void codegen_lval2rval(Type* ty) {
+ if (ty->kind == TypeKind_array) {
+ return;
+ }
+
int size = type_sizeof(ty);
printf(" pop rax\n");
diff --git a/parse.c b/parse.c
index d08269e..0b682e2 100644
--- a/parse.c
+++ b/parse.c
@@ -702,6 +702,17 @@ AstNode* parse_var_decl(Parser* p) {
}
String* name = parse_ident(p);
+ if (peek_token(p)->kind == TokenKind_bracket_l) {
+ next_token(p);
+ AstNode* size_expr = parse_expr(p);
+ if (size_expr->kind != AstNodeKind_int_expr) {
+ fatal_error("parse_var_decl: invalid array size");
+ }
+ int size = size_expr->node_int_value;
+ expect(p, TokenKind_bracket_r);
+ ty = type_new_array(ty, size);
+ }
+
AstNode* init = NULL;
if (peek_token(p)->kind == TokenKind_assign) {
next_token(p);
diff --git a/tests/068.sh b/tests/068.sh
new file mode 100644
index 0000000..648e822
--- /dev/null
+++ b/tests/068.sh
@@ -0,0 +1,29 @@
+set -e
+
+cat <<'EOF' > expected
+0
+1
+4
+9
+16
+25
+36
+49
+64
+81
+EOF
+
+bash ../../test_diff.sh <<'EOF'
+int printf();
+
+int main() {
+ int i;
+ int a[10];
+ for (i = 0; i < 10; ++i) {
+ a[i] = i * i;
+ }
+ for (i = 0; i < 10; ++i) {
+ printf("%d\n", a[i]);
+ }
+}
+EOF