aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests/038.sh
diff options
context:
space:
mode:
Diffstat (limited to 'tests/038.sh')
-rw-r--r--tests/038.sh1816
1 files changed, 0 insertions, 1816 deletions
diff --git a/tests/038.sh b/tests/038.sh
deleted file mode 100644
index 4b6a983..0000000
--- a/tests/038.sh
+++ /dev/null
@@ -1,1816 +0,0 @@
-set -e
-
-cat <<'EOF' > expected
-EOF
-bash ../../test_diff.sh <<'EOF'
-int atoi();
-void* calloc();
-void exit();
-int getchar();
-int isalnum();
-int isalpha();
-int isdigit();
-int isspace();
-void* malloc();
-void* memcpy();
-void* memset();
-int printf();
-int putchar();
-int sprintf();
-int strcmp();
-char* strstr();
-long strtol();
-
-#define NULL 0
-
-void fatal_error(char* msg) {
- printf("%s\n", msg);
- exit(1);
-}
-
-int read_all(char* buf) {
- int c;
- int n = 0;
- for (0; (c = getchar()) != -1; 0) {
- buf[n] = c;
- n = n + 1;
- }
- return n;
-}
-
-#define TK_EOF 0
-
-#define TK_AND 1
-#define TK_ANDAND 2
-#define TK_ARROW 3
-#define TK_ASSIGN 4
-#define TK_BRACE_L 5
-#define TK_BRACE_R 6
-#define TK_BRACKET_L 7
-#define TK_BRACKET_R 8
-#define TK_COMMA 9
-#define TK_DOT 10
-#define TK_EQ 11
-#define TK_GE 12
-#define TK_GT 13
-#define TK_IDENT 14
-#define TK_K_BREAK 15
-#define TK_K_CHAR 16
-#define TK_K_CONTINUE 17
-#define TK_K_ELSE 18
-#define TK_K_FOR 19
-#define TK_K_IF 20
-#define TK_K_INT 21
-#define TK_K_LONG 22
-#define TK_K_RETURN 23
-#define TK_K_SIZEOF 24
-#define TK_K_STRUCT 25
-#define TK_K_VOID 26
-#define TK_LE 27
-#define TK_LT 28
-#define TK_L_INT 29
-#define TK_L_STR 30
-#define TK_MINUS 31
-#define TK_NE 32
-#define TK_NOT 33
-#define TK_OROR 34
-#define TK_PAREN_L 35
-#define TK_PAREN_R 36
-#define TK_PERCENT 37
-#define TK_PLUS 38
-#define TK_SEMICOLON 39
-#define TK_SLASH 40
-#define TK_STAR 41
-
-struct Token {
- int kind;
- char* value;
-};
-
-struct Define {
- char* from;
- struct Token* to;
-};
-
-struct Token* tokenize(char* src, int len) {
- struct Token* tokens = calloc(1024*1024, sizeof(struct Token));
- struct Token* tok = tokens;
- struct Define* defines = calloc(1024, sizeof(struct Define));
- struct Define* def = defines;
- int pos = 0;
- int ch;
- int start;
- for (0; pos < len; 0) {
- char c = src[pos];
- if (c == '(') {
- pos = pos + 1;
- tok->kind = TK_PAREN_L;
- tok = tok + 1;
- } else if (c == ')') {
- pos = pos + 1;
- tok->kind = TK_PAREN_R;
- tok = tok + 1;
- } else if (c == '{') {
- pos = pos + 1;
- tok->kind = TK_BRACE_L;
- tok = tok + 1;
- } else if (c == '}') {
- pos = pos + 1;
- tok->kind = TK_BRACE_R;
- tok = tok + 1;
- } else if (c == '[') {
- pos = pos + 1;
- tok->kind = TK_BRACKET_L;
- tok = tok + 1;
- } else if (c == ']') {
- pos = pos + 1;
- tok->kind = TK_BRACKET_R;
- tok = tok + 1;
- } else if (c == ',') {
- pos = pos + 1;
- tok->kind = TK_COMMA;
- tok = tok + 1;
- } else if (c == ';') {
- pos = pos + 1;
- tok->kind = TK_SEMICOLON;
- tok = tok + 1;
- } else if (c == '+') {
- pos = pos + 1;
- tok->kind = TK_PLUS;
- tok = tok + 1;
- } else if (c == '|') {
- pos = pos + 2;
- tok->kind = TK_OROR;
- tok = tok + 1;
- } else if (c == '&') {
- pos = pos + 1;
- if (src[pos] == '&') {
- pos = pos + 1;
- tok->kind = TK_ANDAND;
- tok = tok + 1;
- } else {
- tok->kind = TK_AND;
- tok = tok + 1;
- }
- } else if (c == '-') {
- pos = pos + 1;
- if (src[pos] == '>') {
- pos = pos + 1;
- tok->kind = TK_ARROW;
- tok = tok + 1;
- } else {
- tok->kind = TK_MINUS;
- tok = tok + 1;
- }
- } else if (c == '*') {
- pos = pos + 1;
- tok->kind = TK_STAR;
- tok = tok + 1;
- } else if (c == '/') {
- pos = pos + 1;
- tok->kind = TK_SLASH;
- tok = tok + 1;
- } else if (c == '%') {
- pos = pos + 1;
- tok->kind = TK_PERCENT;
- tok = tok + 1;
- } else if (c == '.') {
- pos = pos + 1;
- tok->kind = TK_DOT;
- tok = tok + 1;
- } else if (c == '!') {
- pos = pos + 1;
- if (src[pos] == '=') {
- pos = pos + 1;
- tok->kind = TK_NE;
- tok = tok + 1;
- } else {
- tok->kind = TK_NOT;
- tok = tok + 1;
- }
- } else if (c == '=') {
- pos = pos + 1;
- if (src[pos] == '=') {
- pos = pos + 1;
- tok->kind = TK_EQ;
- tok = tok + 1;
- } else {
- tok->kind = TK_ASSIGN;
- tok = tok + 1;
- }
- } else if (c == '<') {
- pos = pos + 1;
- if (src[pos] == '=') {
- pos = pos + 1;
- tok->kind = TK_LE;
- tok = tok + 1;
- } else {
- tok->kind = TK_LT;
- tok = tok + 1;
- }
- } else if (c == '>') {
- pos = pos + 1;
- if (src[pos] == '=') {
- pos = pos + 1;
- tok->kind = TK_GE;
- tok = tok + 1;
- } else {
- tok->kind = TK_GT;
- tok = tok + 1;
- }
- } else if (c == '\'') {
- pos = pos + 1;
- ch = src[pos];
- if (ch == '\\') {
- pos = pos + 1;
- ch = src[pos];
- if (ch == 'n') {
- ch = '\n';
- }
- }
- pos = pos + 2;
- tok->kind = TK_L_INT;
- tok->value = calloc(4, sizeof(char));
- sprintf(tok->value, "%d", ch);
- tok = tok + 1;
- } else if (c == '"') {
- pos = pos + 1;
- start = pos;
- for (0; 1; 0) {
- ch = src[pos];
- if (ch == '\\') {
- pos = pos + 1;
- } else if (ch == '"') {
- break;
- }
- pos = pos + 1;
- }
- tok->kind = TK_L_STR;
- tok->value = calloc(pos - start + 1, sizeof(char));
- memcpy(tok->value, src + start, pos - start);
- pos = pos + 1;
- tok = tok + 1;
- } else if (isdigit(c)) {
- start = pos;
- for (0; isdigit(src[pos]); 0) {
- pos = pos + 1;
- }
- tok->kind = TK_L_INT;
- tok->value = calloc(pos - start + 1, sizeof(char));
- memcpy(tok->value, src + start, pos - start);
- tok = tok + 1;
- } else if (isalpha(c)) {
- start = pos;
- for (0; isalnum(src[pos]) || src[pos] == '_'; 0) {
- pos = pos + 1;
- }
- int ident_len = pos - start;
- if (ident_len == 5 && strstr(src + start, "break") == src + start) {
- tok->kind = TK_K_BREAK;
- } else if (ident_len == 4 && strstr(src + start, "char") == src + start) {
- tok->kind = TK_K_CHAR;
- } else if (ident_len == 8 && strstr(src + start, "continue") == src + start) {
- tok->kind = TK_K_CONTINUE;
- } else if (ident_len == 4 && strstr(src + start, "else") == src + start) {
- tok->kind = TK_K_ELSE;
- } else if (ident_len == 3 && strstr(src + start, "for") == src + start) {
- tok->kind = TK_K_FOR;
- } else if (ident_len == 2 && strstr(src + start, "if") == src + start) {
- tok->kind = TK_K_IF;
- } else if (ident_len == 3 && strstr(src + start, "int") == src + start) {
- tok->kind = TK_K_INT;
- } else if (ident_len == 4 && strstr(src + start, "long") == src + start) {
- tok->kind = TK_K_LONG;
- } else if (ident_len == 6 && strstr(src + start, "return") == src + start) {
- tok->kind = TK_K_RETURN;
- } else if (ident_len == 6 && strstr(src + start, "sizeof") == src + start) {
- tok->kind = TK_K_SIZEOF;
- } else if (ident_len == 6 && strstr(src + start, "struct") == src + start) {
- tok->kind = TK_K_STRUCT;
- } else if (ident_len == 4 && strstr(src + start, "void") == src + start) {
- tok->kind = TK_K_VOID;
- } else {
- tok->value = calloc(ident_len + 1, sizeof(char));
- memcpy(tok->value, src + start, ident_len);
- int i = 0;
- for (0; defines + i != def; 0) {
- if (strcmp(tok->value, defines[i].from) == 0) {
- tok->kind = defines[i].to->kind;
- tok->value = defines[i].to->value;
- break;
- }
- i = i + 1;
- }
- if (defines + i == def) {
- tok->kind = TK_IDENT;
- }
- }
- tok = tok + 1;
- } else if (isspace(c)) {
- pos = pos + 1;
- } else if (c == '#') {
- pos = pos + 1;
- pos = pos + 6;
- for (0; isspace(src[pos]); 0) {
- pos = pos + 1;
- }
- start = pos;
- for (0; isalnum(src[pos]) || src[pos] == '_'; 0) {
- pos = pos + 1;
- }
- def->from = calloc(pos - start + 1, sizeof(char));
- memcpy(def->from, src + start, pos - start);
- for (0; isspace(src[pos]); 0) {
- pos = pos + 1;
- }
- int start2 = pos;
- for (0; isdigit(src[pos]); 0) {
- pos = pos + 1;
- }
- def->to = calloc(1, sizeof(struct Token));
- def->to->kind = TK_L_INT;
- def->to->value = calloc(pos - start2 + 1, sizeof(char));
- memcpy(def->to->value, src + start2, pos - start2);
- def = def + 1;
- } else {
- fatal_error("unknown token");
- }
- }
- return tokens;
-}
-
-#define TY_UNKNOWN 0
-
-#define TY_CHAR 1
-#define TY_INT 2
-#define TY_LONG 3
-#define TY_VOID 4
-#define TY_PTR 5
-#define TY_STRUCT 6
-
-struct AstNode;
-
-struct Type {
- int kind;
- struct Type* to;
- struct AstNode* struct_def;
-};
-
-struct Type* type_new(int kind) {
- struct Type* ty = calloc(1, sizeof(struct Type));
- ty->kind = kind;
- return ty;
-}
-
-struct Type* type_new_ptr(struct Type* to) {
- struct Type* ty = calloc(1, sizeof(struct Type));
- ty->kind = TY_PTR;
- ty->to = to;
- return ty;
-}
-
-int type_is_unsized_type(struct Type* ty) {
- return ty->kind != TY_VOID;
-}
-
-int type_sizeof_struct(struct Type* ty);
-int type_alignof_struct(struct Type* ty);
-
-int type_sizeof(struct Type* ty) {
- if (!type_is_unsized_type(ty)) {
- fatal_error("type_sizeof: type size cannot be determined");
- }
-
- if (ty->kind == TY_PTR) {
- return 8;
- } else if (ty->kind == TY_CHAR) {
- return 1;
- } else if (ty->kind == TY_INT) {
- return 4;
- } else if (ty->kind == TY_LONG) {
- return 8;
- } else {
- return type_sizeof_struct(ty);
- }
-}
-
-int type_alignof(struct Type* ty) {
- if (!type_is_unsized_type(ty)) {
- fatal_error("type_alignof: type size cannot be determined");
- }
-
- if (ty->kind == TY_PTR) {
- return 8;
- } else if (ty->kind == TY_CHAR) {
- return 1;
- } else if (ty->kind == TY_INT) {
- return 4;
- } else if (ty->kind == TY_LONG) {
- return 8;
- } else {
- return type_alignof_struct(ty);
- }
-}
-
-#define AST_UNKNOWN 0
-
-#define AST_ARG_LIST 1
-#define AST_ASSIGN_EXPR 2
-#define AST_BINARY_EXPR 3
-#define AST_BLOCK 4
-#define AST_BREAK_STMT 5
-#define AST_CONTINUE_STMT 6
-#define AST_DEREF_EXPR 7
-#define AST_EXPR_STMT 8
-#define AST_FOR_STMT 9
-#define AST_FUNC_CALL 10
-#define AST_FUNC_DECL 11
-#define AST_FUNC_DEF 12
-#define AST_IF_STMT 13
-#define AST_INT_LIT_EXPR 14
-#define AST_LVAR 15
-#define AST_OFFSETOF 16
-#define AST_PARAM 17
-#define AST_PARAM_LIST 18
-#define AST_PROGRAM 19
-#define AST_REF_EXPR 20
-#define AST_RETURN_STMT 21
-#define AST_STRUCT_DECL 22
-#define AST_STRUCT_DEF 23
-#define AST_STRUCT_MEMBER 24
-#define AST_STRUCT_MEMBER_LIST 25
-#define AST_STR_LIT_EXPR 26
-#define AST_TYPE 27
-#define AST_UNARY_EXPR 28
-#define AST_VAR_DECL 29
-
-struct AstNode {
- int kind;
- struct AstNode* next;
- struct AstNode* last;
- char* name;
- struct AstNode* func_params;
- struct AstNode* func_body;
- int int_value;
- struct AstNode* expr1;
- struct AstNode* expr2;
- struct AstNode* expr3;
- int op;
- struct Type* ty;
- int var_index;
- struct AstNode* node1;
- struct AstNode* node2;
- char** str_literals;
-};
-
-struct AstNode* ast_new(int kind) {
- struct AstNode* ast = calloc(1, sizeof(struct AstNode));
- ast->kind = kind;
- return ast;
-}
-
-struct AstNode* ast_new_list(int kind) {
- if (kind != AST_PROGRAM && kind != AST_BLOCK && kind != AST_ARG_LIST && kind != AST_PARAM_LIST && kind != AST_STRUCT_MEMBER_LIST) {
- fatal_error("ast_new_list: non-list ast");
- }
- struct AstNode* ast = ast_new(kind);
- ast->last = ast;
- return ast;
-}
-
-struct AstNode* ast_new_unary_expr(int op, struct AstNode* operand) {
- struct AstNode* e = ast_new(AST_UNARY_EXPR);
- e->op = op;
- e->expr1 = operand;
- return e;
-}
-
-struct AstNode* ast_new_binary_expr(int op, struct AstNode* lhs, struct AstNode* rhs) {
- struct AstNode* e = ast_new(AST_BINARY_EXPR);
- e->op = op;
- e->expr1 = lhs;
- e->expr2 = rhs;
- return e;
-}
-
-struct AstNode* ast_new_assign_expr(int op, struct AstNode* lhs, struct AstNode* rhs) {
- struct AstNode* e = ast_new(AST_ASSIGN_EXPR);
- e->op = op;
- e->expr1 = lhs;
- e->expr2 = rhs;
- return e;
-}
-
-int type_sizeof_struct(struct Type* ty) {
- int next_offset = 0;
- int struct_align = 0;
- int padding;
-
- struct AstNode* member = ty->struct_def->node1->next;
- for (0; member; 0) {
- int size = type_sizeof(member->ty);
- int align = type_alignof(member->ty);
-
- if (next_offset % align != 0) {
- padding = align - next_offset % align;
- next_offset = next_offset + padding;
- }
- next_offset = next_offset + size;
- if (struct_align < align) {
- struct_align = align;
- }
-
- member = member->next;
- }
- if (next_offset % struct_align != 0) {
- padding = struct_align - next_offset % struct_align;
- next_offset = next_offset + padding;
- }
- return next_offset;
-}
-
-int type_alignof_struct(struct Type* ty) {
- int struct_align = 0;
-
- struct AstNode* member = ty->struct_def->node1->next;
- for (0; member; 0) {
- int align = type_alignof(member->ty);
-
- if (struct_align < align) {
- struct_align = align;
- }
-
- member = member->next;
- }
- return struct_align;
-}
-
-int type_offsetof(struct Type* ty, char* name) {
- if (ty->kind != TY_STRUCT) {
- fatal_error("type_offsetof: type is not a struct");
- }
-
- int next_offset = 0;
-
- struct AstNode* member = ty->struct_def->node1->next;
- for (0; member; 0) {
- int size = type_sizeof(member->ty);
- int align = type_alignof(member->ty);
-
- if (next_offset % align != 0) {
- int padding = align - next_offset % align;
- next_offset = next_offset + padding;
- }
- if (strcmp(member->name, name) == 0) {
- return next_offset;
- }
- next_offset = next_offset + size;
-
- member = member->next;
- }
-
- fatal_error("type_offsetof: member not found");
-}
-
-struct Type* type_member_typeof(struct Type* ty, char* name) {
- if (ty->kind != TY_STRUCT) {
- fatal_error("type_offsetof: type is not a struct");
- }
-
- struct AstNode* member = ty->struct_def->node1->next;
- for (0; member; 0) {
- if (strcmp(member->name, name) == 0) {
- return member->ty;
- }
- member = member->next;
- }
-
- fatal_error("type_offsetof: member not found");
-}
-
-#define LVAR_MAX 32
-
-struct LVar {
- char* name;
- struct Type* ty;
-};
-
-struct Func {
- char* name;
- struct Type* ty;
-};
-
-struct Parser {
- struct Token* tokens;
- int pos;
- struct LVar* locals;
- int n_locals;
- struct Func* funcs;
- int n_funcs;
- struct AstNode* structs;
- int n_structs;
- char** str_literals;
- int n_str_literals;
-};
-
-struct Parser* parser_new(struct Token* tokens) {
- struct Parser* p = calloc(1, sizeof(struct Parser));
- p->tokens = tokens;
- p->funcs = calloc(128, sizeof(struct Func));
- p->structs = calloc(64, sizeof(struct AstNode));
- p->str_literals = calloc(1024, sizeof(char*));
- return p;
-}
-
-struct Token* peek_token(struct Parser* p) {
- return p->tokens + p->pos;
-}
-
-struct Token* next_token(struct Parser* p) {
- p->pos = p->pos + 1;
- return p->tokens + p->pos - 1;
-}
-
-int eof(struct Parser* p) {
- return peek_token(p)->kind != TK_EOF;
-}
-
-struct Token* expect(struct Parser* p, int expected) {
- struct Token* t = next_token(p);
- if (t->kind == expected) {
- return t;
- }
-
- char* buf = calloc(1024, sizeof(char));
- sprintf(buf, "expected %d, but got %d", expected, t->kind);
- fatal_error(buf);
-}
-
-int find_lvar(struct Parser* p, char* name) {
- int i;
- for (i = 0; i < p->n_locals; i = i + 1) {
- if (strcmp(p->locals[i].name, name) == 0) {
- return i;
- }
- }
- return -1;
-}
-
-int find_func(struct Parser* p, char* name) {
- int i;
- for (i = 0; i < p->n_funcs; i = i + 1) {
- if (strcmp(p->funcs[i].name, name) == 0) {
- return i;
- }
- }
- return -1;
-}
-
-struct AstNode* parse_expr(struct Parser* p);
-struct AstNode* parse_stmt(struct Parser* p);
-
-char* parse_ident(struct Parser* p) {
- return expect(p, TK_IDENT)->value;
-}
-
-int register_str_lit(struct Parser* p, char* s) {
- p->str_literals[p->n_str_literals] = s;
- p->n_str_literals = p->n_str_literals + 1;
- return p->n_str_literals;
-}
-
-struct AstNode* parse_primary_expr(struct Parser* p) {
- struct Token* t = next_token(p);
- struct AstNode* e;
- char* buf;
- if (t->kind == TK_L_INT) {
- e = ast_new(AST_INT_LIT_EXPR);
- e->int_value = atoi(t->value);
- e->ty = type_new(TY_INT);
- return e;
- } else if (t->kind == TK_L_STR) {
- int str_lit_index = register_str_lit(p, t->value);
- e = ast_new(AST_STR_LIT_EXPR);
- e->int_value = str_lit_index;
- return e;
- } else if (t->kind == TK_PAREN_L) {
- e = parse_expr(p);
- expect(p, TK_PAREN_R);
- return e;
- } else if (t->kind == TK_IDENT) {
- char* name = t->value;
-
- if (peek_token(p)->kind == TK_PAREN_L) {
- e = ast_new(AST_FUNC_CALL);
- int func_index = find_func(p, name);
- if (func_index == -1) {
- buf = calloc(1024, sizeof(char));
- sprintf(buf, "undefined function: %s", name);
- fatal_error(buf);
- }
- e->name = name;
- e->ty = p->funcs[func_index].ty;
- return e;
- }
-
- int var_index = find_lvar(p, name);
- if (var_index == -1) {
- buf = calloc(1024, sizeof(char));
- sprintf(buf, "undefined variable: %s", name);
- fatal_error(buf);
- }
-
- e = ast_new(AST_LVAR);
- e->name = name;
- e->var_index = var_index;
- e->ty = p->locals[var_index].ty;
- return e;
- } else {
- buf = calloc(1024, sizeof(char));
- sprintf(buf, "expected primary expression, but got %d", t->kind);
- fatal_error(buf);
- }
-}
-
-struct AstNode* parse_arg_list(struct Parser* p) {
- struct AstNode* list = ast_new_list(AST_ARG_LIST);
- for (0; peek_token(p)->kind != TK_PAREN_R; 0) {
- struct AstNode* arg = parse_expr(p);
- list->last->next = arg;
- list->last = arg;
- int tk = peek_token(p)->kind;
- if (tk == TK_COMMA) {
- next_token(p);
- } else {
- break;
- }
- }
- return list;
-}
-
-struct AstNode* parse_postfix_expr(struct Parser* p) {
- struct AstNode* ret = parse_primary_expr(p);
- struct AstNode* e;
- struct AstNode* ptr_expr;
- struct AstNode* offset_node;
- int offset;
- char* name;
- for (0; 1; 0) {
- int tk = peek_token(p)->kind;
- if (tk == TK_PAREN_L) {
- next_token(p);
- struct AstNode* args = parse_arg_list(p);
- expect(p, TK_PAREN_R);
- ret->expr1 = args;
- } else if (tk == TK_BRACKET_L) {
- next_token(p);
- struct AstNode* idx = parse_expr(p);
- expect(p, TK_BRACKET_R);
-
- e = ast_new(AST_DEREF_EXPR);
- ptr_expr = ast_new_binary_expr(TK_PLUS, ret, idx);
- ptr_expr->ty = ret->ty;
- e->expr1 = ptr_expr;
- e->ty = ret->ty->to;
-
- ret = e;
- } else if (tk == TK_DOT) {
- next_token(p);
- name = parse_ident(p);
-
- e = ast_new(AST_DEREF_EXPR);
- struct AstNode* ref_of_ret = ast_new(AST_REF_EXPR);
- ref_of_ret->expr1 = ret;
- ref_of_ret->ty = type_new_ptr(ret->ty);
- offset = type_offsetof(ret->ty, name);
- offset_node = ast_new(AST_OFFSETOF);
- offset_node->int_value = offset;
- offset_node->ty = type_new(TY_INT);
- ptr_expr = ast_new_binary_expr(TK_PLUS, ref_of_ret, offset_node);
- ptr_expr->ty = ref_of_ret->ty;
- e->expr1 = ptr_expr;
- e->ty = type_member_typeof(ret->ty, name);
-
- ret = e;
- } else if (tk == TK_ARROW) {
- next_token(p);
- name = parse_ident(p);
-
- e = ast_new(AST_DEREF_EXPR);
- offset = type_offsetof(ret->ty->to, name);
- offset_node = ast_new(AST_OFFSETOF);
- offset_node->int_value = offset;
- offset_node->ty = type_new(TY_INT);
- ptr_expr = ast_new_binary_expr(TK_PLUS, ret, offset_node);
- ptr_expr->ty = ret->ty;
- e->expr1 = ptr_expr;
- e->ty = type_member_typeof(ret->ty->to, name);
-
- ret = e;
- } else {
- break;
- }
- }
- return ret;
-}
-
-int is_type_token(int token_kind) {
- return token_kind == TK_K_INT || token_kind == TK_K_LONG || token_kind == TK_K_CHAR || token_kind == TK_K_VOID || token_kind == TK_K_STRUCT;
-}
-
-struct Type* parse_type(struct Parser* p) {
- struct Token* t = next_token(p);
- char* buf;
- if (!is_type_token(t->kind)) {
- buf = calloc(1024, sizeof(char));
- sprintf(buf, "parse_type: unknown type, %d", t->kind);
- fatal_error(buf);
- }
- struct Type* ty = type_new(TY_UNKNOWN);
- if (t->kind == TK_K_INT) {
- ty->kind = TY_INT;
- } else if (t->kind == TK_K_LONG) {
- ty->kind = TY_LONG;
- } else if (t->kind == TK_K_CHAR) {
- ty->kind = TY_CHAR;
- } else if (t->kind == TK_K_VOID) {
- ty->kind = TY_VOID;
- } else if (t->kind == TK_K_STRUCT) {
- ty->kind = TY_STRUCT;
- char* name = parse_ident(p);
- int struct_index;
- for (struct_index = 0; struct_index < p->n_structs; struct_index = struct_index + 1) {
- if (strcmp(name, p->structs[struct_index].name) == 0) {
- break;
- }
- }
- if (struct_index == p->n_structs) {
- buf = calloc(1024, sizeof(char));
- sprintf(buf, "parse_type: unknown struct, %s", name);
- fatal_error(buf);
- }
- ty->struct_def = p->structs + struct_index;
- } else {
- fatal_error("unreachable");
- }
- for (0; 1; 0) {
- struct Token* t2 = peek_token(p);
- if (t2->kind == TK_STAR) {
- next_token(p);
- ty = type_new_ptr(ty);
- } else {
- break;
- }
- }
- return ty;
-}
-
-struct AstNode* parse_prefix_expr(struct Parser* p) {
- struct AstNode* e;
- struct AstNode* operand;
- int op = peek_token(p)->kind;
- if (op == TK_MINUS) {
- next_token(p);
- operand = parse_prefix_expr(p);
- struct AstNode* lhs = ast_new(AST_INT_LIT_EXPR);
- lhs->int_value = 0;
- lhs->ty = type_new(TY_INT);
- e = ast_new_binary_expr(op, lhs, operand);
- e->ty = type_new(TY_INT);
- return e;
- } else if (op == TK_NOT) {
- next_token(p);
- operand = parse_prefix_expr(p);
- e = ast_new_unary_expr(op, operand);
- e->ty = type_new(TY_INT);
- return e;
- } else if (op == TK_AND) {
- next_token(p);
- operand = parse_prefix_expr(p);
- e = ast_new(AST_REF_EXPR);
- e->expr1 = operand;
- e->ty = type_new_ptr(operand->ty);
- return e;
- } else if (op == TK_STAR) {
- next_token(p);
- operand = parse_prefix_expr(p);
- e = ast_new(AST_DEREF_EXPR);
- e->expr1 = operand;
- e->ty = operand->ty->to;
- return e;
- } else if (op == TK_K_SIZEOF) {
- next_token(p);
- expect(p, TK_PAREN_L);
- struct Type* ty = parse_type(p);
- expect(p, TK_PAREN_R);
- e = ast_new(AST_INT_LIT_EXPR);
- e->int_value = type_sizeof(ty);
- e->ty = type_new(TY_INT);
- return e;
- }
- return parse_postfix_expr(p);
-}
-
-struct AstNode* parse_multiplicative_expr(struct Parser* p) {
- struct AstNode* lhs = parse_prefix_expr(p);
- for (0; 1; 0) {
- int op = peek_token(p)->kind;
- if (op == TK_STAR || op == TK_SLASH || op == TK_PERCENT) {
- next_token(p);
- struct AstNode* rhs = parse_prefix_expr(p);
- lhs = ast_new_binary_expr(op, lhs, rhs);
- lhs->ty = type_new(TY_INT);
- } else {
- break;
- }
- }
- return lhs;
-}
-
-struct AstNode* parse_additive_expr(struct Parser* p) {
- struct AstNode* lhs = parse_multiplicative_expr(p);
- struct AstNode* rhs;
- struct Type* result_type;
- for (0; 1; 0) {
- int op = peek_token(p)->kind;
- if (op == TK_PLUS) {
- next_token(p);
- rhs = parse_multiplicative_expr(p);
- if (lhs->ty->kind == TY_PTR) {
- result_type = lhs->ty;
- } else if (rhs->ty->kind == TY_PTR) {
- result_type = rhs->ty;
- } else {
- result_type = type_new(TY_INT);
- }
- lhs = ast_new_binary_expr(op, lhs, rhs);
- lhs->ty = result_type;
- } else if (op == TK_MINUS) {
- next_token(p);
- rhs = parse_multiplicative_expr(p);
- if (lhs->ty->kind == TY_PTR) {
- result_type = lhs->ty;
- } else {
- result_type = type_new(TY_INT);
- }
- lhs = ast_new_binary_expr(op, lhs, rhs);
- lhs->ty = result_type;
- } else {
- break;
- }
- }
- return lhs;
-}
-
-struct AstNode* parse_relational_expr(struct Parser* p) {
- struct AstNode* lhs = parse_additive_expr(p);
- struct AstNode* rhs;
- for (0; 1; 0) {
- int op = peek_token(p)->kind;
- if (op == TK_LT || op == TK_LE) {
- next_token(p);
- rhs = parse_additive_expr(p);
- lhs = ast_new_binary_expr(op, lhs, rhs);
- lhs->ty = type_new(TY_INT);
- } else if (op == TK_GT) {
- next_token(p);
- rhs = parse_additive_expr(p);
- lhs = ast_new_binary_expr(TK_LT, rhs, lhs);
- lhs->ty = type_new(TY_INT);
- } else if (op == TK_GE) {
- next_token(p);
- rhs = parse_additive_expr(p);
- lhs = ast_new_binary_expr(TK_LE, rhs, lhs);
- lhs->ty = type_new(TY_INT);
- } else {
- break;
- }
- }
- return lhs;
-}
-
-struct AstNode* parse_equality_expr(struct Parser* p) {
- struct AstNode* lhs = parse_relational_expr(p);
- for (0; 1; 0) {
- int op = peek_token(p)->kind;
- if (op == TK_EQ || op == TK_NE) {
- next_token(p);
- struct AstNode* rhs = parse_relational_expr(p);
- lhs = ast_new_binary_expr(op, lhs, rhs);
- lhs->ty = type_new(TY_INT);
- } else {
- break;
- }
- }
- return lhs;
-}
-
-struct AstNode* parse_logical_and_expr(struct Parser* p) {
- struct AstNode* lhs = parse_equality_expr(p);
- for (0; 1; 0) {
- int op = peek_token(p)->kind;
- if (op == TK_ANDAND) {
- next_token(p);
- struct AstNode* rhs = parse_equality_expr(p);
- lhs = ast_new_binary_expr(op, lhs, rhs);
- lhs->ty = type_new(TY_INT);
- } else {
- break;
- }
- }
- return lhs;
-}
-
-struct AstNode* parse_logical_or_expr(struct Parser* p) {
- struct AstNode* lhs = parse_logical_and_expr(p);
- for (0; 1; 0) {
- int op = peek_token(p)->kind;
- if (op == TK_OROR) {
- next_token(p);
- struct AstNode* rhs = parse_logical_and_expr(p);
- lhs = ast_new_binary_expr(op, lhs, rhs);
- lhs->ty = type_new(TY_INT);
- } else {
- break;
- }
- }
- return lhs;
-}
-
-struct AstNode* parse_assignment_expr(struct Parser *p) {
- struct AstNode* lhs = parse_logical_or_expr(p);
- for (0; 1; 0) {
- int op = peek_token(p)->kind;
- if (op == TK_ASSIGN) {
- next_token(p);
- struct AstNode* rhs = parse_logical_or_expr(p);
- lhs = ast_new_assign_expr(op, lhs, rhs);
- lhs->ty = rhs->ty;
- } else {
- break;
- }
- }
- return lhs;
-}
-
-struct AstNode* parse_expr(struct Parser* p) {
- return parse_assignment_expr(p);
-}
-
-struct AstNode* parse_return_stmt(struct Parser* p) {
- expect(p, TK_K_RETURN);
- if (peek_token(p)->kind == TK_SEMICOLON) {
- next_token(p);
- return ast_new(AST_RETURN_STMT);
- }
-
- struct AstNode* expr = parse_expr(p);
- expect(p, TK_SEMICOLON);
-
- struct AstNode* ret = ast_new(AST_RETURN_STMT);
- ret->expr1 = expr;
- return ret;
-}
-
-struct AstNode* parse_if_stmt(struct Parser* p) {
- expect(p, TK_K_IF);
- expect(p, TK_PAREN_L);
- struct AstNode* cond = parse_expr(p);
- expect(p, TK_PAREN_R);
- struct AstNode* then_body = parse_stmt(p);
- struct AstNode* else_body = NULL;
- if (peek_token(p)->kind == TK_K_ELSE) {
- next_token(p);
- else_body = parse_stmt(p);
- }
-
- struct AstNode* stmt = ast_new(AST_IF_STMT);
- stmt->expr1 = cond;
- stmt->node1 = then_body;
- stmt->node2 = else_body;
- return stmt;
-}
-
-struct AstNode* parse_for_stmt(struct Parser* p) {
- expect(p, TK_K_FOR);
- expect(p, TK_PAREN_L);
- struct AstNode* init = parse_expr(p);
- expect(p, TK_SEMICOLON);
- struct AstNode* cond = parse_expr(p);
- expect(p, TK_SEMICOLON);
- struct AstNode* update = parse_expr(p);
- expect(p, TK_PAREN_R);
- struct AstNode* body = parse_stmt(p);
-
- struct AstNode* stmt = ast_new(AST_FOR_STMT);
- stmt->expr1 = init;
- stmt->expr2 = cond;
- stmt->expr3 = update;
- stmt->node1 = body;
- return stmt;
-}
-
-struct AstNode* parse_break_stmt(struct Parser* p) {
- expect(p, TK_K_BREAK);
- expect(p, TK_SEMICOLON);
- return ast_new(AST_BREAK_STMT);
-}
-
-struct AstNode* parse_continue_stmt(struct Parser* p) {
- expect(p, TK_K_CONTINUE);
- expect(p, TK_SEMICOLON);
- return ast_new(AST_CONTINUE_STMT);
-}
-
-struct AstNode* parse_var_decl(struct Parser* p) {
- struct Type* ty = parse_type(p);
- if (!type_is_unsized_type(ty)) {
- fatal_error("parse_var_decl: invalid type for variable");
- }
- char* name = parse_ident(p);
-
- struct AstNode* init = NULL;
- if (peek_token(p)->kind == TK_ASSIGN) {
- next_token(p);
- init = parse_expr(p);
- }
- expect(p, TK_SEMICOLON);
-
- if (find_lvar(p, name) != -1) {
- char* buf = calloc(1024, sizeof(char));
- sprintf(buf, "parse_var_decl: %s redeclared", name);
- fatal_error(buf);
- }
- p->locals[p->n_locals].name = name;
- p->locals[p->n_locals].ty = ty;
- p->n_locals = p->n_locals + 1;
-
- struct AstNode* ret;
- if (init) {
- struct AstNode* lhs = ast_new(AST_LVAR);
- lhs->name = name;
- lhs->var_index = p->n_locals - 1;
- lhs->ty = ty;
- struct AstNode* assign = ast_new_assign_expr(TK_ASSIGN, lhs, init);
- assign->ty = ty;
- ret = ast_new(AST_EXPR_STMT);
- ret->expr1 = assign;
- } else {
- ret = ast_new(AST_VAR_DECL);
- }
- return ret;
-}
-
-struct AstNode* parse_expr_stmt(struct Parser* p) {
- struct AstNode* e = parse_expr(p);
- expect(p, TK_SEMICOLON);
- struct AstNode* stmt = ast_new(AST_EXPR_STMT);
- stmt->expr1 = e;
- return stmt;
-}
-
-struct AstNode* parse_block_stmt(struct Parser* p) {
- struct AstNode* list = ast_new_list(AST_BLOCK);
- expect(p, TK_BRACE_L);
- for (0; peek_token(p)->kind != TK_BRACE_R; 0) {
- struct AstNode* stmt = parse_stmt(p);
- list->last->next = stmt;
- list->last = stmt;
- }
- expect(p, TK_BRACE_R);
- return list;
-}
-
-struct AstNode* parse_stmt(struct Parser* p) {
- struct Token* t = peek_token(p);
- if (t->kind == TK_K_RETURN) {
- return parse_return_stmt(p);
- } else if (t->kind == TK_K_IF) {
- return parse_if_stmt(p);
- } else if (t->kind == TK_K_FOR) {
- return parse_for_stmt(p);
- } else if (t->kind == TK_K_BREAK) {
- return parse_break_stmt(p);
- } else if (t->kind == TK_K_CONTINUE) {
- return parse_continue_stmt(p);
- } else if (t->kind == TK_BRACE_L) {
- return parse_block_stmt(p);
- } else if (is_type_token(t->kind)) {
- return parse_var_decl(p);
- } else {
- return parse_expr_stmt(p);
- }
-}
-
-void enter_func(struct Parser* p) {
- p->locals = calloc(LVAR_MAX, sizeof(struct LVar));
- p->n_locals = 0;
-}
-
-void register_params(struct Parser* p, struct AstNode* params) {
- struct AstNode* param = params->next;
- for (0; param; 0) {
- p->locals[p->n_locals].name = param->name;
- p->locals[p->n_locals].ty = param->ty;
- p->n_locals = p->n_locals + 1;
- param = param->next;
- }
-}
-
-void register_func(struct Parser* p, char* name, struct Type* ty) {
- p->funcs[p->n_funcs].name = name;
- p->funcs[p->n_funcs].ty = ty;
- p->n_funcs = p->n_funcs + 1;
-}
-
-struct AstNode* parse_param(struct Parser* p) {
- struct Type* ty = parse_type(p);
- if (!type_is_unsized_type(ty)) {
- fatal_error("parse_param: invalid type for variable");
- }
- char* name = parse_ident(p);
- struct AstNode* param = ast_new(AST_PARAM);
- param->ty = ty;
- param->name = name;
- return param;
-}
-
-struct AstNode* parse_param_list(struct Parser* p) {
- struct AstNode* list = ast_new_list(AST_PARAM_LIST);
- for (0; peek_token(p)->kind != TK_PAREN_R; 0) {
- struct AstNode* param = parse_param(p);
- list->last->next = param;
- list->last = param;
- int tk = peek_token(p)->kind;
- if (tk == TK_COMMA) {
- next_token(p);
- } else {
- break;
- }
- }
- return list;
-}
-
-struct AstNode* parse_func_decl_or_def(struct Parser* p) {
- struct Type* ty = parse_type(p);
- char* name = parse_ident(p);
- register_func(p, name, ty);
- expect(p, TK_PAREN_L);
- struct AstNode* params = parse_param_list(p);
- expect(p, TK_PAREN_R);
- if (peek_token(p)->kind == TK_SEMICOLON) {
- next_token(p);
- return ast_new(AST_FUNC_DECL);
- }
- enter_func(p);
- register_params(p, params);
- struct AstNode* body = parse_block_stmt(p);
- struct AstNode* func = ast_new(AST_FUNC_DEF);
- func->ty = ty;
- func->name = name;
- func->func_params = params;
- func->func_body = body;
- return func;
-}
-
-struct AstNode* parse_struct_member(struct Parser* p) {
- struct Type* ty = parse_type(p);
- char* name = parse_ident(p);
- expect(p, TK_SEMICOLON);
- struct AstNode* member = ast_new(AST_STRUCT_MEMBER);
- member->name = name;
- member->ty = ty;
- return member;
-}
-
-struct AstNode* parse_struct_members(struct Parser* p) {
- struct AstNode* list = ast_new_list(AST_STRUCT_MEMBER_LIST);
- for (0; peek_token(p)->kind != TK_BRACE_R; 0) {
- struct AstNode* member = parse_struct_member(p);
- list->last->next = member;
- list->last = member;
- }
- return list;
-}
-
-struct AstNode* parse_struct_decl_or_def(struct Parser* p) {
- expect(p, TK_K_STRUCT);
- char* name = parse_ident(p);
-
- if (peek_token(p)->kind != TK_SEMICOLON && peek_token(p)->kind != TK_BRACE_L) {
- p->pos = p->pos - 2;
- return parse_func_decl_or_def(p);
- }
-
- int struct_index;
- for (struct_index = 0; struct_index < p->n_structs; struct_index = struct_index + 1) {
- if (strcmp(name, p->structs[struct_index].name) == 0) {
- break;
- }
- }
- if (struct_index == p->n_structs) {
- p->structs[struct_index].kind = AST_STRUCT_DEF;
- p->structs[struct_index].name = name;
- p->n_structs = p->n_structs + 1;
- }
- if (peek_token(p)->kind == TK_SEMICOLON) {
- next_token(p);
- return ast_new(AST_STRUCT_DECL);
- }
- if (p->structs[struct_index].node1) {
- char* buf = calloc(1024, sizeof(char));
- sprintf(buf, "parse_struct_decl_or_def: struct %s redefined", name);
- fatal_error(buf);
- }
- expect(p, TK_BRACE_L);
- struct AstNode* members = parse_struct_members(p);
- expect(p, TK_BRACE_R);
- expect(p, TK_SEMICOLON);
- p->structs[struct_index].node1 = members;
- return p->structs + struct_index;
-}
-
-struct AstNode* parse_toplevel(struct Parser* p) {
- if (peek_token(p)->kind == TK_K_STRUCT) {
- return parse_struct_decl_or_def(p);
- } else {
- return parse_func_decl_or_def(p);
- }
-}
-
-struct AstNode* parse(struct Parser* p) {
- struct AstNode* list = ast_new_list(AST_PROGRAM);
- for (0; eof(p); 0) {
- struct AstNode* n = parse_toplevel(p);
- list->last->next = n;
- list->last = n;
- }
- list->str_literals = p->str_literals;
- return list;
-}
-
-#define GEN_LVAL 0
-#define GEN_RVAL 1
-
-struct CodeGen {
- int next_label;
- int* loop_labels;
-};
-
-struct CodeGen* codegen_new() {
- struct CodeGen* g = calloc(1, sizeof(struct CodeGen));
- g->next_label = 1;
- g->loop_labels = calloc(1024, sizeof(int));
- return g;
-}
-
-void assert_ast_kind(struct AstNode* ast, int kind) {
- if (ast->kind != kind) {
- char* buf = calloc(1024, sizeof(char));
- sprintf(buf, "invalid ast kind: expected %d, but got %d", kind, ast->kind);
- fatal_error(buf);
- }
-}
-
-int gen_new_label(struct CodeGen* g) {
- int new_label = g->next_label;
- g->next_label = g->next_label + 1;
- return new_label;
-}
-
-void gen_expr(struct CodeGen* g, struct AstNode* ast, int gen_mode);
-void gen_stmt(struct CodeGen* g, struct AstNode* ast);
-
-void gen_func_prologue(struct CodeGen* g, struct AstNode* ast) {
- printf(" # gen_func_prologue\n");
-
- printf(" push rbp\n");
- printf(" mov rbp, rsp\n");
- int param_index = 0;
- struct AstNode* param = ast->func_params->next;
- for (0; param; 0) {
- if (param_index == 0) {
- printf(" push rdi\n");
- } else if (param_index == 1) {
- printf(" push rsi\n");
- } else if (param_index == 2) {
- printf(" push rdx\n");
- } else if (param_index == 3) {
- printf(" push rcx\n");
- } else if (param_index == 4) {
- printf(" push r8\n");
- } else if (param_index == 5) {
- printf(" push r9\n");
- } else {
- fatal_error("gen_func_prologue: too many params");
- }
- param_index = param_index + 1;
- param = param->next;
- }
- printf(" sub rsp, %d\n", 8 * LVAR_MAX);
-}
-
-void gen_func_epilogue(struct CodeGen* g, struct AstNode* ast) {
- printf(" # gen_func_epilogue\n");
-
- printf(" mov rsp, rbp\n");
- printf(" pop rbp\n");
- printf(" ret\n");
-}
-
-void gen_int_lit_expr(struct CodeGen* g, struct AstNode* ast) {
- assert_ast_kind(ast, AST_INT_LIT_EXPR);
- printf(" # gen_int_lit_expr\n");
-
- printf(" push %d\n", ast->int_value);
-}
-
-void gen_offsetof(struct CodeGen* g, struct AstNode* ast) {
- assert_ast_kind(ast, AST_OFFSETOF);
- printf(" # gen_offsetof\n");
-
- printf(" push %d\n", ast->int_value);
-}
-
-void gen_str_lit_expr(struct CodeGen* g, struct AstNode* ast) {
- assert_ast_kind(ast, AST_STR_LIT_EXPR);
- printf(" # gen_str_lit_expr\n");
-
- printf(" mov rax, OFFSET FLAG:.Lstr__%d\n", ast->int_value);
- printf(" push rax\n");
-}
-
-void gen_unary_expr(struct CodeGen* g, struct AstNode* ast) {
- assert_ast_kind(ast, AST_UNARY_EXPR);
- printf(" # gen_unary_expr\n");
-
- gen_expr(g, ast->expr1, GEN_RVAL);
- if (ast->op == TK_NOT) {
- printf(" pop rax\n");
- printf(" mov rdi, 0\n");
- printf(" cmp rax, rdi\n");
- printf(" sete al\n");
- printf(" movzb rax, al\n");
- printf(" push rax\n");
- } else {
- fatal_error("gen_unary_expr: unknown unary op");
- }
-}
-
-void gen_ref_expr(struct CodeGen* g, struct AstNode* ast, int gen_mode) {
- assert_ast_kind(ast, AST_REF_EXPR);
- printf(" # gen_ref_expr\n");
-
- gen_expr(g, ast->expr1, GEN_LVAL);
-}
-
-void gen_deref_expr(struct CodeGen* g, struct AstNode* ast, int gen_mode) {
- assert_ast_kind(ast, AST_DEREF_EXPR);
- printf(" # gen_deref_expr\n");
-
- if (gen_mode == GEN_LVAL) {
- gen_expr(g, ast->expr1, GEN_RVAL);
- } else {
- gen_expr(g, ast->expr1, GEN_RVAL);
- printf(" pop rax\n");
- printf(" push [rax]\n");
- }
-}
-
-void gen_logical_expr(struct CodeGen* g, struct AstNode* ast) {
- assert_ast_kind(ast, AST_BINARY_EXPR);
- printf(" # gen_logical_expr\n");
-
- int label = gen_new_label(g);
-
- if (ast->op == TK_ANDAND) {
- gen_expr(g, ast->expr1, GEN_RVAL);
- printf(" pop rax\n");
- printf(" cmp rax, 0\n");
- printf(" je .Lelse%d\n", label);
- gen_expr(g, ast->expr2, GEN_RVAL);
- printf(" jmp .Lend%d\n", label);
- printf(".Lelse%d:\n", label);
- printf(" push 0\n");
- printf(".Lend%d:\n", label);
- } else {
- gen_expr(g, ast->expr1, GEN_RVAL);
- printf(" pop rax\n");
- printf(" cmp rax, 0\n");
- printf(" je .Lelse%d\n", label);
- printf(" push 1\n");
- printf(" jmp .Lend%d\n", label);
- printf(".Lelse%d:\n", label);
- gen_expr(g, ast->expr2, GEN_RVAL);
- printf(".Lend%d:\n", label);
- }
-}
-
-void gen_binary_expr(struct CodeGen* g, struct AstNode* ast, int gen_mode) {
- assert_ast_kind(ast, AST_BINARY_EXPR);
- printf(" # gen_binary_expr\n");
-
- if (ast->op == TK_ANDAND || ast->op == TK_OROR) {
- gen_logical_expr(g, ast);
- return;
- }
-
- gen_expr(g, ast->expr1, gen_mode);
- gen_expr(g, ast->expr2, gen_mode);
- printf(" pop rdi\n");
- printf(" pop rax\n");
- if (ast->op == TK_PLUS) {
- if (ast->expr1->ty->kind == TY_PTR) {
- if (ast->expr2->kind != AST_OFFSETOF) {
- printf(" imul rdi, %d\n", type_sizeof(ast->expr1->ty->to));
- }
- printf(" add rax, rdi\n");
- } else if (ast->expr2->ty->kind == TY_PTR) {
- if (ast->expr1->kind != AST_OFFSETOF) {
- printf(" imul rax, %d\n", type_sizeof(ast->expr2->ty->to));
- }
- printf(" add rax, rdi\n");
- } else {
- printf(" add rax, rdi\n");
- }
- } else if (ast->op == TK_MINUS) {
- if (ast->expr2->ty->kind == TY_PTR) {
- fatal_error("todo");
- } else if (ast->expr1->ty->kind == TY_PTR) {
- printf(" imul rdi, %d\n", type_sizeof(ast->expr1->ty->to));
- printf(" sub rax, rdi\n");
- } else {
- printf(" sub rax, rdi\n");
- }
- } else if (ast->op == TK_STAR) {
- printf(" imul rax, rdi\n");
- } else if (ast->op == TK_SLASH) {
- printf(" cqo\n");
- printf(" idiv rdi\n");
- } else if (ast->op == TK_PERCENT) {
- printf(" cqo\n");
- printf(" idiv rdi\n");
- printf(" mov rax, rdx\n");
- } else if (ast->op == TK_EQ) {
- printf(" cmp rax, rdi\n");
- printf(" sete al\n");
- printf(" movzb rax, al\n");
- } else if (ast->op == TK_NE) {
- printf(" cmp rax, rdi\n");
- printf(" setne al\n");
- printf(" movzb rax, al\n");
- } else if (ast->op == TK_LT) {
- printf(" cmp rax, rdi\n");
- printf(" setl al\n");
- printf(" movzb rax, al\n");
- } else if (ast->op == TK_LE) {
- printf(" cmp rax, rdi\n");
- printf(" setle al\n");
- printf(" movzb rax, al\n");
- } else {
- char* buf = calloc(1024, sizeof(char));
- sprintf(buf, "gen_binary_expr: unknown op, %d", ast->op);
- fatal_error(buf);
- }
- printf(" push rax\n");
-}
-
-void gen_assign_expr(struct CodeGen* g, struct AstNode* ast) {
- assert_ast_kind(ast, AST_ASSIGN_EXPR);
- printf(" # gen_assign_expr\n");
-
- gen_expr(g, ast->expr1, GEN_LVAL);
- gen_expr(g, ast->expr2, GEN_RVAL);
- printf(" pop rdi\n");
- printf(" pop rax\n");
- if (ast->op == TK_ASSIGN) {
- printf(" mov [rax], rdi\n");
- printf(" push rdi\n");
- } else {
- fatal_error("gen_assign_expr: unknown assign op");
- }
-}
-
-void gen_func_call(struct CodeGen* g, struct AstNode* ast) {
- assert_ast_kind(ast, AST_FUNC_CALL);
- printf(" # gen_func_call\n");
-
- char* func_name = ast->name;
- struct AstNode* args = ast->expr1;
- struct AstNode* arg = args->next;
- int n_args = 0;
- for (0; arg; 0) {
- n_args = n_args + 1;
- gen_expr(g, arg, GEN_RVAL);
- arg = arg->next;
- }
- int i;
- for (i = n_args - 1; i >= 0; i = i - 1) {
- if (i == 0) {
- printf(" pop rdi\n");
- } else if (i == 1) {
- printf(" pop rsi\n");
- } else if (i == 2) {
- printf(" pop rdx\n");
- } else if (i == 3) {
- printf(" pop rcx\n");
- } else if (i == 4) {
- printf(" pop r8\n");
- } else if (i == 5) {
- printf(" pop r9\n");
- } else {
- fatal_error("gen_func_call: too many args");
- }
- }
- printf(" mov rax, 0\n");
- printf(" call %s\n", func_name);
- printf(" push rax\n");
-}
-
-void gen_lvar(struct CodeGen* g, struct AstNode* ast, int gen_mode) {
- assert_ast_kind(ast, AST_LVAR);
- printf(" # gen_lvar\n");
-
- int offset = 8 + ast->var_index * 8;
- printf(" mov rax, rbp\n");
- printf(" sub rax, %d\n", offset);
- printf(" push rax\n");
- if (gen_mode == GEN_RVAL) {
- printf(" pop rax\n");
- printf(" push [rax]\n");
- }
-}
-
-void gen_expr(struct CodeGen* g, struct AstNode* ast, int gen_mode) {
- if (ast->kind == AST_INT_LIT_EXPR) {
- gen_int_lit_expr(g, ast);
- } else if (ast->kind == AST_OFFSETOF) {
- gen_offsetof(g, ast);
- } else if (ast->kind == AST_STR_LIT_EXPR) {
- gen_str_lit_expr(g, ast);
- } else if (ast->kind == AST_UNARY_EXPR) {
- gen_unary_expr(g, ast);
- } else if (ast->kind == AST_REF_EXPR) {
- gen_ref_expr(g, ast, gen_mode);
- } else if (ast->kind == AST_DEREF_EXPR) {
- gen_deref_expr(g, ast, gen_mode);
- } else if (ast->kind == AST_BINARY_EXPR) {
- gen_binary_expr(g, ast, gen_mode);
- } else if (ast->kind == AST_ASSIGN_EXPR) {
- gen_assign_expr(g, ast);
- } else if (ast->kind == AST_FUNC_CALL) {
- gen_func_call(g, ast);
- } else if (ast->kind == AST_LVAR) {
- gen_lvar(g, ast, gen_mode);
- } else {
- fatal_error("gen_expr: unknown expr");
- }
-}
-
-void gen_return_stmt(struct CodeGen* g, struct AstNode* ast) {
- assert_ast_kind(ast, AST_RETURN_STMT);
- printf(" # gen_return_stmt\n");
-
- if (ast->expr1) {
- gen_expr(g, ast->expr1, GEN_RVAL);
- printf(" pop rax\n");
- }
- gen_func_epilogue(g, ast);
-}
-
-void gen_if_stmt(struct CodeGen* g, struct AstNode* ast) {
- assert_ast_kind(ast, AST_IF_STMT);
- printf(" # gen_if_stmt\n");
-
- int label = gen_new_label(g);
-
- gen_expr(g, ast->expr1, GEN_RVAL);
- printf(" pop rax\n");
- printf(" cmp rax, 0\n");
- printf(" je .Lelse%d\n", label);
- gen_stmt(g, ast->node1);
- printf(" jmp .Lend%d\n", label);
- printf(".Lelse%d:\n", label);
- if (ast->node2) {
- gen_stmt(g, ast->node2);
- }
- printf(".Lend%d:\n", label);
-}
-
-void gen_for_stmt(struct CodeGen* g, struct AstNode* ast) {
- assert_ast_kind(ast, AST_FOR_STMT);
- printf(" # gen_for_stmt\n");
-
- int label = gen_new_label(g);
- g->loop_labels = g->loop_labels + 1;
- *g->loop_labels = label;
-
- gen_expr(g, ast->expr1, GEN_RVAL);
- printf(".Lbegin%d:\n", label);
- gen_expr(g, ast->expr2, GEN_RVAL);
- printf(" pop rax\n");
- printf(" cmp rax, 0\n");
- printf(" je .Lend%d\n", label);
- gen_stmt(g, ast->node1);
- printf(".Lcontinue%d:\n", label);
- gen_expr(g, ast->expr3, GEN_RVAL);
- printf(" pop rax\n");
- printf(" jmp .Lbegin%d\n", label);
- printf(".Lend%d:\n", label);
-
- g->loop_labels = g->loop_labels - 1;
-}
-
-void gen_break_stmt(struct CodeGen* g, struct AstNode* ast) {
- assert_ast_kind(ast, AST_BREAK_STMT);
- printf(" # gen_break_stmt\n");
-
- int label = *g->loop_labels;
- printf(" jmp .Lend%d\n", label);
-}
-
-void gen_continue_stmt(struct CodeGen* g, struct AstNode* ast) {
- assert_ast_kind(ast, AST_CONTINUE_STMT);
- printf(" # gen_continue_stmt\n");
-
- int label = *g->loop_labels;
- printf(" jmp .Lcontinue%d\n", label);
-}
-
-void gen_expr_stmt(struct CodeGen* g, struct AstNode* ast) {
- gen_expr(g, ast->expr1, GEN_RVAL);
- printf(" pop rax\n");
-}
-
-void gen_var_decl(struct CodeGen* g, struct AstNode* ast) {
-}
-
-void gen_block_stmt(struct CodeGen* g, struct AstNode* ast) {
- assert_ast_kind(ast, AST_BLOCK);
- struct AstNode* stmt = ast->next;
- for (0; stmt; 0) {
- gen_stmt(g, stmt);
- stmt = stmt->next;
- }
-}
-
-void gen_stmt(struct CodeGen* g, struct AstNode* ast) {
- if (ast->kind == AST_BLOCK) {
- gen_block_stmt(g, ast);
- } else if (ast->kind == AST_RETURN_STMT) {
- gen_return_stmt(g, ast);
- } else if (ast->kind == AST_IF_STMT) {
- gen_if_stmt(g, ast);
- } else if (ast->kind == AST_FOR_STMT) {
- gen_for_stmt(g, ast);
- } else if (ast->kind == AST_BREAK_STMT) {
- gen_break_stmt(g, ast);
- } else if (ast->kind == AST_CONTINUE_STMT) {
- gen_continue_stmt(g, ast);
- } else if (ast->kind == AST_EXPR_STMT) {
- gen_expr_stmt(g, ast);
- } else if (ast->kind == AST_VAR_DECL) {
- gen_var_decl(g, ast);
- } else {
- char* buf = calloc(1024, sizeof(char));
- sprintf(buf, "gen_stmt: expected statement ast, but got %d", ast->kind);
- fatal_error(buf);
- }
-}
-
-void gen_func(struct CodeGen* g, struct AstNode* ast) {
- assert_ast_kind(ast, AST_FUNC_DEF);
- printf("%s:\n", ast->name);
-
- gen_func_prologue(g, ast);
- gen_stmt(g, ast->func_body);
- gen_func_epilogue(g, ast);
- printf("\n");
-}
-
-void gen(struct CodeGen* g, struct AstNode* ast) {
- assert_ast_kind(ast, AST_PROGRAM);
-
- printf(".intel_syntax noprefix\n\n");
-
- int idx = 0;
- for (idx = 0; ast->str_literals[idx]; idx = idx + 1) {
- printf(".Lstr__%d:\n", idx + 1);
- printf(" .string \"%s\"\n\n", ast->str_literals[idx]);
- }
-
- printf(".globl main\n\n");
-
- struct AstNode* func = ast->next;
- for (0; func; 0) {
- if (func->kind == AST_FUNC_DEF) {
- gen_func(g, func);
- }
- func = func->next;
- }
-}
-
-int main() {
- return 0;
-}
-EOF