From f35b7e32809c5d54850ce75c4dad1a8598235cf0 Mon Sep 17 00:00:00 2001 From: Matthew Sotoudeh Date: Wed, 26 Jul 2023 10:53:27 -0700 Subject: simplify code a fair bit --- codegen.c | 270 ++++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 203 insertions(+), 67 deletions(-) (limited to 'codegen.c') diff --git a/codegen.c b/codegen.c index 9eaac4a..7e8565a 100644 --- a/codegen.c +++ b/codegen.c @@ -8,25 +8,60 @@ int is_bad_number(double x) { return (x != x) || (x == 1./0.) || (-x == 1./0.); } -static FILE *output_file; -static int RETURN_TMP; - -static void printnoln(char *fmt, ...); -static void println(char *fmt, ...); -static void print_tok(Token *tok); - -FILE *BUFFER; -int DO_BUFFER; - -static void flush_buffer() { - rewind(BUFFER); +/////////// PRINTING +static FILE *CURR_BUFFER, + // the typedefs at the very beginning + *TYPE_BUFFER, + // everything after the typedefs + *MAIN_BUFFER, + // code inside a function (after all declarations, which go into + // the main buffer immediately) + *CODE_BUFFER; + +FILE *BUFFER_STACK[8]; +int N_BUFFER_STACK; +static void push_buffer(FILE *which) { + assert(N_BUFFER_STACK < 8); + BUFFER_STACK[N_BUFFER_STACK++] = which; + CURR_BUFFER = which; +} +static void pop_buffer(FILE *which) { + assert(N_BUFFER_STACK--); + assert(BUFFER_STACK[N_BUFFER_STACK] == which); + CURR_BUFFER = BUFFER_STACK[N_BUFFER_STACK - 1]; +} +static void flush_buffer(FILE *to_buffer, FILE *from_buffer) { + rewind(from_buffer); int c; - while ((c = fgetc(BUFFER)) != EOF) - fputc(c, output_file); - rewind(BUFFER); - ftruncate(fileno(BUFFER), 0); + while ((c = fgetc(from_buffer)) != EOF) + fputc(c, to_buffer); + rewind(from_buffer); + ftruncate(fileno(from_buffer), 0); +} +__attribute__((format(printf, 1, 2))) +static void printnoln(char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + vfprintf(CURR_BUFFER, fmt, ap); + va_end(ap); +} +__attribute__((format(printf, 1, 2))) +static void println(char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + vfprintf(CURR_BUFFER, fmt, ap); + va_end(ap); + fputc('\n', CURR_BUFFER); +} +/////////// END PRINTING + +static int count(void) { + static int i = 1; + return i++; } +static int RETURN_TMP; + void print_label(char *label) { printnoln("_l"); for (; *label; label++) { @@ -57,52 +92,147 @@ void print_obj(Obj *obj) { } } +///////// TYPES +const void typedecl(Type *type) { + if (type->id) return; + Type *hashed = hash_lookup(type); + if (hashed && !(hashed->typedecling)) { + assert(hashed->id); + type->id = hashed->id; + if (hashed->pointer_type) type->pointer_type = hashed->pointer_type; + if (hashed->return_ty) type->return_ty = hashed->return_ty; + if (hashed->params) type->params = hashed->params; + return; + } + type->typedecling = 1; + type->id = count(); + hash_insert(type); + switch (type->kind) { + case TY_FLOAT: + println("typedef float Type_%d ;", type->id); + break; + case TY_DOUBLE: + println("typedef double Type_%d ;", type->id); + break; + case TY_LDOUBLE: + println("typedef long double Type_%d ;", type->id); + break; + case TY_INT: + if (type->is_unsigned) + println("typedef unsigned int Type_%d ;", type->id); + else + println("typedef int Type_%d ;", type->id); + break; + case TY_LONG: + if (type->is_unsigned) + println("typedef unsigned long Type_%d ;", type->id); + else + println("typedef long Type_%d ;", type->id); + break; + case TY_SHORT: + if (type->is_unsigned) + println("typedef unsigned short Type_%d ;", type->id); + else + println("typedef short Type_%d ;", type->id); + break; + case TY_VOID: + println("typedef void Type_%d ;", type->id); + break; + case TY_BOOL: + println("typedef _Bool Type_%d ;", type->id); + break; + case TY_CHAR: + println("typedef char Type_%d ;", type->id); + break; + case TY_PTR: + typedecl(type->base); + println("typedef Type_%d * Type_%d ;", type->base->id, type->id); + break; + case TY_FUNC: { + typedecl(type->return_ty); + for (Type *p = type->params; p; p = p->next) + typedecl(p); + printnoln("typedef Type_%d Type_%d ( ", type->return_ty->id, type->id); + + int i = 0; + for (Type *p = type->params; p; p = p->next, i++) + if (i) printnoln(", Type_%d ", p->id); + else printnoln("Type_%d ", p->id); + + if (type->is_variadic) { + if (i) printnoln(", ... "); + // else printnoln("... "); + } + println(") ;"); + break; + } + case TY_ARRAY: + typedecl(type->base); + if (type->array_len == -1) + println("typedef Type_%d Type_%d [ ] ;", type->base->id, type->id); + else + println("typedef Type_%d Type_%d [ %d ] ;", type->base->id, type->id, + type->array_len); + break; + case TY_STRUCT: + case TY_UNION: + if (type->kind == TY_STRUCT) + println("typedef struct Struct_%d Type_%d ;", type->id, type->id); + else + println("typedef union Union_%d Type_%d ;", type->id, type->id); + + for (Member *m = type->members; m; m = m->next) + typedecl(m->ty); + + if (type->kind == TY_STRUCT) printnoln("struct Struct_%d { ", type->id); + else printnoln("union Union_%d { ", type->id); + for (Member *m = type->members; m; m = m->next) { + printnoln("Type_%d ", m->ty->id); + if (m->name) + print_tok(m->name); + else if (m->ty->kind == TY_STRUCT || m->ty->kind == TY_UNION) + printnoln("___dietc_f%d", m->idx); + else + printnoln("__field_%d", count()); + printnoln(" ; "); + } + println("} ;"); + break; + case TY_ENUM: + println("typedef enum Enum_%d { EN_%d } Type_%d ;", type->id, type->id, type->id); + break; + case TY_VLA: + assert(!"unimplemented vla?"); + break; + default: + assert(!"unimplemented?"); + break; + } + type->typedecling = 0; +} +void ensure_pointer_to(Type *type) { + if (type->pointer_type) return; + type->pointer_type = pointer_to(type); +} +//////////// END TYPES + const void print_type(Type *type) { if (type->kind == TY_FUNC) { - assert(type->pointer_type); + ensure_pointer_to(type); print_type(type->pointer_type); } else { + push_buffer(TYPE_BUFFER); + typedecl(type); + pop_buffer(TYPE_BUFFER); assert(type->id); printnoln("Type_%d", type->id); } } -static int depth; static Obj *current_fn; static void gen_expr(Node *node, int to_tmp); static void gen_stmt(Node *node); -__attribute__((format(printf, 1, 2))) -static void println(char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - if (DO_BUFFER) - vfprintf(BUFFER, fmt, ap); - else - vfprintf(output_file, fmt, ap); - va_end(ap); - if (DO_BUFFER) - fprintf(BUFFER, "\n"); - else - fprintf(output_file, "\n"); -} - -__attribute__((format(printf, 1, 2))) -static void printnoln(char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - if (DO_BUFFER) - vfprintf(BUFFER, fmt, ap); - else - vfprintf(output_file, fmt, ap); - va_end(ap); -} - -static int count(void) { - static int i = 1; - return i++; -} - // Round up `n` to the nearest multiple of `align`. For instance, // align_to(5, 8) returns 8 and align_to(11, 8) returns 16. int align_to(int n, int align) { @@ -110,15 +240,16 @@ int align_to(int n, int align) { } void decltmp(Type *type, int c) { - DO_BUFFER = 0; + // Write directly to the main buffer so it decls before the code. + push_buffer(MAIN_BUFFER); printnoln("\t"); print_type(type); println(" t%d ;", c); - DO_BUFFER = 1; + pop_buffer(MAIN_BUFFER); } void decltmpptr(Type *type, int c) { - assert(type->pointer_type); + ensure_pointer_to(type); decltmp(type->pointer_type, c); } @@ -268,6 +399,7 @@ static void gen_expr(Node *node, int to_tmp) { int c = count(); if (node->ty->kind == TY_VOID) { gen_expr(node->lhs, c); + push_buffer(TYPE_BUFFER); typedecl(node->ty); pop_buffer(TYPE_BUFFER); println("\t( Type_%d ) t%d ;", node->ty->id, c); } else if (node->lhs->ty->kind == TY_UNION) { // union *tuptr = &union @@ -531,16 +663,11 @@ static void assign_lvar_offsets(Obj *prog) { if (!fn->is_function) continue; - // If a function has many parameters, some parameters are - // inevitably passed by stack rather than by register. - // The first passed-by-stack parameter resides at RBP+16. - int c = 1; - for (Obj *var = fn->params; var; var = var->next) - var->offset = c++; + var->offset = count(); for (Obj *var = fn->locals; var; var = var->next) if (!(var->offset)) - var->offset = c++; + var->offset = count(); } } @@ -663,6 +790,9 @@ void emit_constant(int pos, char *data, Relocation **rel, Type *type) { static void emit_data(Obj *prog) { for (Obj *var = prog; var; var = var->next) { + push_buffer(TYPE_BUFFER); + typedecl(var->ty); + pop_buffer(TYPE_BUFFER); if (var->is_static && var->is_function) { printnoln("static Type_%d ", var->ty->id); print_obj(var); println(" ;"); @@ -732,7 +862,6 @@ static void emit_text(Obj *prog) { } for (Obj *var = fn->locals; var; var = var->next) { - if (!(var->ty->id)) continue; if (var->is_param) continue; if (var == fn->va_area) continue; if (var == fn->alloca_bottom) continue; @@ -744,11 +873,10 @@ static void emit_text(Obj *prog) { } // Emit code - DO_BUFFER = 1; + push_buffer(CODE_BUFFER); gen_stmt(fn->body); - assert(depth == 0); - flush_buffer(); - DO_BUFFER = 0; + pop_buffer(CODE_BUFFER); + flush_buffer(MAIN_BUFFER, CODE_BUFFER); println("\t_L_RETURN :"); if (fn->ty->return_ty->kind != TY_VOID) { @@ -762,10 +890,18 @@ static void emit_text(Obj *prog) { } void codegen(Obj *prog, FILE *out) { - output_file = out; - - BUFFER = tmpfile(); + TYPE_BUFFER = tmpfile(); + MAIN_BUFFER = tmpfile(); + CODE_BUFFER = tmpfile(); assign_lvar_offsets(prog); + + // Everything defaults to writing to main + push_buffer(MAIN_BUFFER); emit_data(prog); emit_text(prog); + pop_buffer(MAIN_BUFFER); + + fprintf(out, "#include \"%s/scripts/dietc_helpers.h\"\n", DIETC_ROOT); + flush_buffer(out, TYPE_BUFFER); + flush_buffer(out, MAIN_BUFFER); } -- cgit v1.2.3