summaryrefslogtreecommitdiff
path: root/cgen.c
diff options
context:
space:
mode:
Diffstat (limited to 'cgen.c')
-rw-r--r--cgen.c89
1 files changed, 56 insertions, 33 deletions
diff --git a/cgen.c b/cgen.c
index 947ad0d..aa21857 100644
--- a/cgen.c
+++ b/cgen.c
@@ -13,7 +13,7 @@ static bool cgen_val_ptr(CGenerator *g, void *v, Type *t, Location where);
static void cgen_create(CGenerator *g, FILE *out, Identifiers *ids, Evaluator *ev) {
g->outc = out;
- g->ident_counter = 0;
+ g->ident_counter = 1; /* some places use 0 to mean no id */
g->main_ident = ident_get(ids, "main");
g->evalr = ev;
g->will_indent = true;
@@ -185,9 +185,15 @@ static bool cgen_type_pre(CGenerator *g, Type *t, Location where) {
/* We should never try to generate this type */
assert(0);
return false;
- case TYPE_USER:
- cgen_ident(g, t->user.name);
- break;
+ case TYPE_USER: {
+ Declaration *d = ident_decl(t->user.name)->decl;
+ assert(d->c.ids);
+ long i = decl_ident_index(d, t->user.name);
+ if (d->c.ids[i])
+ cgen_ident_id(g, d->c.ids[i]);
+ else
+ cgen_ident(g, t->user.name);
+ } break;
}
return true;
}
@@ -200,14 +206,8 @@ static bool cgen_type_post(CGenerator *g, Type *t, Location where) {
return false;
break;
case TYPE_ARR:
- if (t->flags & TYPE_FLAG_RESOLVED)
- cgen_write(g, "[%lu])", (unsigned long)t->arr.n);
- else {
- cgen_write(g, "[");
- if (!cgen_expr(g, t->arr.n_expr))
- return false;
- cgen_write(g, "])");
- }
+ assert(t->flags & TYPE_FLAG_RESOLVED);
+ cgen_write(g, "[%lu])", (unsigned long)t->arr.n);
if (!cgen_type_post(g, t->arr.of, where))
return false;
break;
@@ -644,11 +644,36 @@ static bool cgen_expr_pre(CGenerator *g, Expression *e) {
if (!cgen_block(g, &e->block, ret_name, 0))
return false;
break;
- case EXPR_CALL:
+ case EXPR_CALL: {
if (!cgen_expr_pre(g, e->call.fn)) return false;
arr_foreach(e->call.arg_exprs, Expression, arg)
if (!cgen_expr_pre(g, arg)) return false;
- break;
+ if (cgen_uses_ptr(&e->type)) {
+ e->call.c.id = g->ident_counter++;
+ if (!cgen_type_pre(g, &e->type, e->where)) return false;
+ cgen_write(g, " ");
+ cgen_ident_id(g, e->call.c.id);
+ if (!cgen_type_post(g, &e->type, e->where)) return false;
+ cgen_write(g, ";"); cgen_nl(g);
+ if (!cgen_expr(g, e->call.fn)) return false;
+ cgen_write(g, "(");
+ bool any_args = false;
+ arr_foreach(e->call.arg_exprs, Expression, arg) {
+ any_args = true;
+ if (arg != e->call.arg_exprs)
+ cgen_write(g, ", ");
+ if (!cgen_expr(g, arg))
+ return false;
+ }
+ if (any_args) {
+ cgen_write(g, ", ");
+ }
+ cgen_write(g, "&");
+ cgen_ident_id(g, e->call.c.id);
+ cgen_write(g, ");");
+ cgen_nl(g);
+ }
+ } break;
case EXPR_UNARY_OP:
if (!cgen_expr_pre(g, e->unary.of)) return false;
break;
@@ -895,17 +920,21 @@ static bool cgen_expr(CGenerator *g, Expression *e) {
cgen_ident_id(g, e->block_ret_id);
break;
case EXPR_CALL:
- cgen_write(g, "(");
- if (!cgen_expr(g, e->call.fn))
- return false;
- cgen_write(g, "(");
- arr_foreach(e->call.arg_exprs, Expression, arg) {
- if (arg != e->call.arg_exprs)
- cgen_write(g, ", ");
- if (!cgen_expr(g, arg))
+ if (cgen_uses_ptr(&e->type)) {
+ cgen_ident_id(g, e->call.c.id);
+ } else {
+ cgen_write(g, "(");
+ if (!cgen_expr(g, e->call.fn))
return false;
+ cgen_write(g, "(");
+ arr_foreach(e->call.arg_exprs, Expression, arg) {
+ if (arg != e->call.arg_exprs)
+ cgen_write(g, ", ");
+ if (!cgen_expr(g, arg))
+ return false;
+ }
+ cgen_write(g, "))");
}
- cgen_write(g, "))");
break;
case EXPR_DIRECT:
switch (e->direct.which) {
@@ -1174,13 +1203,7 @@ static bool cgen_decl(CGenerator *g, Declaration *d) {
Type *type = is_tuple ? &d->type.tuple[idx] : &d->type;
Value *val = is_tuple ? &d->val.tuple[idx] : &d->val;
if (type->kind == TYPE_TYPE) {
- cgen_write(g, "typedef ");
- if (!cgen_type_pre(g, val->type, d->where)) return false;
- cgen_write(g, " ");
- cgen_ident(g, i);
- if (!cgen_type_post(g, val->type, d->where)) return false;
- cgen_write(g, ";");
- cgen_nl(g);
+ /* handled in decls_cgen */
continue;
}
if (!cgen_val_pre(g, val, type, d->where))
@@ -1285,15 +1308,13 @@ static bool cgen_stmt(CGenerator *g, Statement *s) {
cgen_nl(g);
break;
case STMT_RET:
- if (!cgen_ret(g, s->ret.flags & RET_FLAG_EXPR ? &s->ret.expr : NULL))
+ if (!cgen_ret(g, s->ret.flags & RET_HAS_EXPR ? &s->ret.expr : NULL))
return false;
break;
}
return true;
}
-static bool cgen_decls_file(CGenerator *g, ParsedFile *f);
-
static bool cgen_file(CGenerator *g, ParsedFile *f) {
g->block = NULL;
g->file = f;
@@ -1316,6 +1337,8 @@ static bool cgen_file(CGenerator *g, ParsedFile *f) {
"static void *e__calloc(size_t n, size_t sz) { void *ret = calloc(n, sz); if (!ret) { fprintf(stderr, \"Out of memory.\\n\"); abort(); } return ret; }\n"
"#define false ((bool)0)\n"
"#define true ((bool)1)\n\n\n");
+ if (!typedefs_file(g, f))
+ return false;
if (!cgen_decls_file(g, f))
return false;
cgen_write(g, "/* code */\n");