diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2020-03-13 12:58:52 -0400 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2020-03-13 12:58:52 -0400 |
commit | d0e85d320c84068b5d4ca68bf18eb0f68c4a6752 (patch) | |
tree | 4e60eb762310b4d62d2893d780a8cfa6ad33e57d | |
parent | 9cd746f1a358ea626a0748f1d3825397316afb5e (diff) |
got rid of some temporary variables in output
-rw-r--r-- | cgen.c | 253 | ||||
-rw-r--r-- | main.c | 2 |
2 files changed, 132 insertions, 123 deletions
@@ -439,6 +439,119 @@ static void cgen_full_fn_name(CGenerator *g, FnExpr *f) { } } +static void cgen_val_ptr_pre(CGenerator *g, void *v, Type *t) { + assert(t->flags & TYPE_IS_RESOLVED); + switch (t->kind) { + case TYPE_SLICE: { + Slice *s = (Slice *)v; + for (I64 i = 0; i < s->n; ++i) { + cgen_val_ptr_pre(g, (char *)s->data + (U64)i * compiler_sizeof(t->slice), t->slice); + } + cgen_type_pre(g, t->slice); + cgen_write(g, "(d%p_[])", v); /* TODO: improve this somehow? */ + cgen_type_post(g, t->slice); + cgen_write(g, " = {"); + for (I64 i = 0; i < s->n; ++i) { + if (i) cgen_write(g, ", "); + cgen_val_ptr(g, (char *)s->data + (U64)i * compiler_sizeof(t->slice), t->slice); + } + cgen_write(g, "};"); + cgen_nl(g); + } break; + case TYPE_ARR: + for (size_t i = 0; i < t->arr.n; ++i) { + cgen_val_ptr_pre(g, (char *)*(void **)v + i * compiler_sizeof(t->arr.of), t->arr.of); + } + break; + case TYPE_FN: + case TYPE_UNKNOWN: + case TYPE_TUPLE: + case TYPE_VOID: + case TYPE_BUILTIN: + case TYPE_PTR: + case TYPE_STRUCT: + break; + case TYPE_EXPR: + assert(0); + break; + } +} + +/* generate a value from a pointer */ +static void cgen_val_ptr(CGenerator *g, void *v, Type *t) { + assert(t->flags & TYPE_IS_RESOLVED); + switch (t->kind) { + case TYPE_TUPLE: + case TYPE_VOID: + case TYPE_EXPR: + case TYPE_UNKNOWN: + assert(0); + return; + case TYPE_ARR: + cgen_write(g, "{"); + for (size_t i = 0; i < t->arr.n; ++i) { + if (i) cgen_write(g, ", "); + cgen_val_ptr(g, (char *)v + i * compiler_sizeof(t->arr.of), t->arr.of); + } + cgen_write(g, "}"); + break; + case TYPE_SLICE: + cgen_write(g, "{d%p_, %lu}", v, ((Slice *)v)->n); + break; + case TYPE_STRUCT: + cgen_write(g, "{"); + arr_foreach(t->struc->fields, Field, f) { + if (f != t->struc->fields) + cgen_write(g, ", "); + cgen_val_ptr(g, (char *)v + f->offset, &f->type); + } + cgen_write(g, "}"); + break; + case TYPE_FN: + cgen_fn_name(g, *(FnExpr **)v); + break; + case TYPE_PTR: + /* You can't have a constant pointer. */ + assert(0); + break; + case TYPE_BUILTIN: + switch (t->builtin) { + case BUILTIN_I8: cgen_write(g, I8_FMT, *(I8 *)v); break; + case BUILTIN_U8: cgen_write(g, U8_FMT, *(U8 *)v); break; + case BUILTIN_I16: cgen_write(g, I16_FMT, *(I16 *)v); break; + case BUILTIN_U16: cgen_write(g, U16_FMT, *(U16 *)v); break; + case BUILTIN_I32: cgen_write(g, I32_FMT, *(I32 *)v); break; + case BUILTIN_U32: cgen_write(g, U32_FMT, *(U32 *)v); break; + case BUILTIN_I64: cgen_write(g, I64_FMT, *(I64 *)v); break; + case BUILTIN_U64: cgen_write(g, U64_FMT, *(U64 *)v); break; + case BUILTIN_F32: cgen_write(g, F32_FMT "f", *(F32 *)v); break; + case BUILTIN_F64: cgen_write(g, F64_FMT, *(F64 *)v); break; + case BUILTIN_CHAR: cgen_write(g, "'\\x%02x'", *(char *)v); break; + case BUILTIN_BOOL: cgen_write(g, "%s", *(bool *)v ? "true" : "false"); break; + case BUILTIN_TYPE: + case BUILTIN_NMS: + case BUILTIN_VARARGS: + assert(0); + break; + } + break; + } +} + +static void cgen_val_pre(CGenerator *g, Value v, Type *t) { + cgen_val_ptr_pre(g, val_get_ptr(&v, t), t); +} + +/* generates a value fit for use as an initializer */ +static void cgen_val(CGenerator *g, Value v, Type *t) { + cgen_val_ptr(g, val_get_ptr(&v, t), t); +} + +/* can the value generated by cgen_val for this type be used directly (as opposed to being stored in a variable)? */ +static inline bool cgen_is_type_simple(Type *t) { + return t->kind == TYPE_BUILTIN || t->kind == TYPE_FN; +} + static void cgen_fn_params(CGenerator *g, FnExpr *f, U64 which_are_const) { bool out_param = cgen_uses_ptr(&f->ret_type); cgen_write(g, "("); @@ -1157,16 +1270,17 @@ static void cgen_expr_pre(CGenerator *g, Expression *e) { /* TODO: don't make a variable for this if it's not needed */ if (type_is_compileonly(&e->type)) break; - cgen_val_pre(g, e->val, &e->type); - cgen_type_pre(g, &e->type); - e->cgen.id = ++g->ident_counter; - cgen_write(g, " "); - cgen_ident_id(g, e->cgen.id); - cgen_type_post(g, &e->type); - cgen_write(g, " = "); - cgen_val(g, e->val, &e->type); - cgen_write(g, ";"); - cgen_nl(g); + if (!cgen_is_type_simple(&e->type)) { + cgen_val_pre(g, e->val, &e->type); + cgen_type_pre(g, &e->type); + e->cgen.id = ++g->ident_counter; + cgen_write(g, " "); + cgen_ident_id(g, e->cgen.id); + cgen_type_post(g, &e->type); + cgen_write(g, " = "); + cgen_val(g, e->val, &e->type); + cgen_writeln(g, ";"); + } break; case EXPR_TUPLE: arr_foreach(e->tuple, Expression, x) @@ -1544,9 +1658,14 @@ static void cgen_expr(CGenerator *g, Expression *e) { case EXPR_SLICE: cgen_ident_id(g, e->slice.c.id); break; - case EXPR_VAL: - cgen_ident_id(g, e->cgen.id); - break; + case EXPR_VAL: { + Type *t = &e->type; + if (cgen_is_type_simple(t)) { + cgen_val(g, e->val, t); + } else { + cgen_ident_id(g, e->cgen.id); + } + } break; case EXPR_NMS: break; } @@ -1690,114 +1809,6 @@ static void cgen_fn(CGenerator *g, FnExpr *f, Value *compile_time_args) { cgen_nl(g); } -static void cgen_val_ptr_pre(CGenerator *g, void *v, Type *t) { - assert(t->flags & TYPE_IS_RESOLVED); - switch (t->kind) { - case TYPE_SLICE: { - Slice *s = (Slice *)v; - for (I64 i = 0; i < s->n; ++i) { - cgen_val_ptr_pre(g, (char *)s->data + (U64)i * compiler_sizeof(t->slice), t->slice); - } - cgen_type_pre(g, t->slice); - cgen_write(g, "(d%p_[])", v); /* TODO: improve this somehow? */ - cgen_type_post(g, t->slice); - cgen_write(g, " = {"); - for (I64 i = 0; i < s->n; ++i) { - if (i) cgen_write(g, ", "); - cgen_val_ptr(g, (char *)s->data + (U64)i * compiler_sizeof(t->slice), t->slice); - } - cgen_write(g, "};"); - cgen_nl(g); - } break; - case TYPE_ARR: - for (size_t i = 0; i < t->arr.n; ++i) { - cgen_val_ptr_pre(g, (char *)*(void **)v + i * compiler_sizeof(t->arr.of), t->arr.of); - } - break; - case TYPE_FN: - case TYPE_UNKNOWN: - case TYPE_TUPLE: - case TYPE_VOID: - case TYPE_BUILTIN: - case TYPE_PTR: - case TYPE_STRUCT: - break; - case TYPE_EXPR: - assert(0); - break; - } -} - -/* generate a value from a pointer */ -static void cgen_val_ptr(CGenerator *g, void *v, Type *t) { - assert(t->flags & TYPE_IS_RESOLVED); - switch (t->kind) { - case TYPE_TUPLE: - case TYPE_VOID: - case TYPE_EXPR: - case TYPE_UNKNOWN: - assert(0); - return; - case TYPE_ARR: - cgen_write(g, "{"); - for (size_t i = 0; i < t->arr.n; ++i) { - if (i) cgen_write(g, ", "); - cgen_val_ptr(g, (char *)v + i * compiler_sizeof(t->arr.of), t->arr.of); - } - cgen_write(g, "}"); - break; - case TYPE_SLICE: - cgen_write(g, "{d%p_, %lu}", v, ((Slice *)v)->n); - break; - case TYPE_STRUCT: - cgen_write(g, "{"); - arr_foreach(t->struc->fields, Field, f) { - if (f != t->struc->fields) - cgen_write(g, ", "); - cgen_val_ptr(g, (char *)v + f->offset, &f->type); - } - cgen_write(g, "}"); - break; - case TYPE_FN: - cgen_fn_name(g, *(FnExpr **)v); - break; - case TYPE_PTR: - /* see: You can't have a constant pointer. */ - assert(0); - break; - case TYPE_BUILTIN: - switch (t->builtin) { - case BUILTIN_I8: cgen_write(g, I8_FMT, *(I8 *)v); break; - case BUILTIN_U8: cgen_write(g, U8_FMT, *(U8 *)v); break; - case BUILTIN_I16: cgen_write(g, I16_FMT, *(I16 *)v); break; - case BUILTIN_U16: cgen_write(g, U16_FMT, *(U16 *)v); break; - case BUILTIN_I32: cgen_write(g, I32_FMT, *(I32 *)v); break; - case BUILTIN_U32: cgen_write(g, U32_FMT, *(U32 *)v); break; - case BUILTIN_I64: cgen_write(g, I64_FMT, *(I64 *)v); break; - case BUILTIN_U64: cgen_write(g, U64_FMT, *(U64 *)v); break; - case BUILTIN_F32: cgen_write(g, F32_FMT "f", *(F32 *)v); break; - case BUILTIN_F64: cgen_write(g, F64_FMT, *(F64 *)v); break; - case BUILTIN_CHAR: cgen_write(g, "'\\x%02x'", *(char *)v); break; - case BUILTIN_BOOL: cgen_write(g, "%s", *(bool *)v ? "true" : "false"); break; - case BUILTIN_TYPE: - case BUILTIN_NMS: - case BUILTIN_VARARGS: - assert(0); - break; - } - break; - } -} - -static void cgen_val_pre(CGenerator *g, Value v, Type *t) { - cgen_val_ptr_pre(g, val_get_ptr(&v, t), t); -} - -/* generates a value fit for use as an initializer */ -static void cgen_val(CGenerator *g, Value v, Type *t) { - cgen_val_ptr(g, val_get_ptr(&v, t), t); -} - static void cgen_decl(CGenerator *g, Declaration *d) { if (g->block == NULL && g->fn == NULL) return; /* already dealt with */ @@ -8,8 +8,6 @@ /* TODO: -is the current cgen_val situation good? there are probably situations where it could be problematic (i.e. where an expression is replaced with an array value-- try varargs[0][0], where varargs[0] is an array) -EXPR_VALs don't always need temp variables where #returns_code (function/struct body is a block, to be evaluated at compile time, which returns the actual statements -- you can use this for implementation of printf) - struct varargs |