summaryrefslogtreecommitdiff
path: root/cgen.c
diff options
context:
space:
mode:
Diffstat (limited to 'cgen.c')
-rw-r--r--cgen.c253
1 files changed, 132 insertions, 121 deletions
diff --git a/cgen.c b/cgen.c
index 4351466..873c6ec 100644
--- a/cgen.c
+++ b/cgen.c
@@ -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 */