summaryrefslogtreecommitdiff
path: root/cgen.c
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2019-11-19 14:40:56 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2019-11-19 14:40:56 -0500
commit4a1f37e189f518dbde3cfc7911040df0ef748869 (patch)
tree42b4ff09cace24697a0184d77cd835fdf9f2349d /cgen.c
parentc1b40edd57e3474925e620c63d781bf8bf40f5b6 (diff)
fixed problems with const params
Diffstat (limited to 'cgen.c')
-rw-r--r--cgen.c221
1 files changed, 118 insertions, 103 deletions
diff --git a/cgen.c b/cgen.c
index 8191d71..5d98814 100644
--- a/cgen.c
+++ b/cgen.c
@@ -26,106 +26,120 @@ static bool cgen_val_ptr(CGenerator *g, void *v, Type *t, Location where);
static bool cgen_defs_block(CGenerator *g, Block *b);
static bool cgen_defs_decl(CGenerator *g, Declaration *d);
+#define cgen_recurse_subexprs_fn_simple(fn, decl_f, block_f) \
+ if (!fn_enter(fn, 0)) return false; \
+ arr_foreach(fn->params, Declaration, param) \
+ if (!decl_f(g, param)) \
+ return false; \
+ arr_foreach(fn->ret_decls, Declaration, r) \
+ if (!decl_f(g, r)) \
+ return false; \
+ if (!block_f(g, &fn->body)) \
+ return false; \
+ fn_exit(fn);
+
/* calls f on every sub-expression of e, block_f on every sub-block, and decl_f on every sub-declaration. */
-#define cgen_recurse_subexprs(g, e, f, block_f, decl_f) \
- switch (e->kind) { \
- case EXPR_TYPE: \
- case EXPR_VAL: \
- case EXPR_C: \
- case EXPR_DSIZEOF: \
- case EXPR_DALIGNOF: \
- case EXPR_IDENT: \
- case EXPR_LITERAL_BOOL: \
- case EXPR_LITERAL_INT: \
- case EXPR_LITERAL_STR: \
- case EXPR_LITERAL_CHAR: \
- case EXPR_LITERAL_FLOAT: \
- break; \
- case EXPR_UNARY_OP: \
- if (!f(g, e->unary.of)) return false; \
- break; \
- case EXPR_BINARY_OP: \
- if (!f(g, e->binary.lhs)) return false; \
- if (e->binary.op != BINARY_DOT) \
- if (!f(g, e->binary.rhs)) \
- return false; \
- break; \
- case EXPR_CAST: \
- if (!f(g, e->cast.expr)) \
- return false; \
- break; \
- case EXPR_CALL: \
- if (!f(g, e->call.fn)) \
- return false; \
- arr_foreach(e->call.arg_exprs, Expression, arg) \
- if (!f(g, arg)) \
- return false; \
- break; \
- case EXPR_BLOCK: \
- if (!block_f(g, &e->block)) \
- return false; \
- break; \
- case EXPR_IF: \
- if (e->if_.cond) \
- if (!f(g, e->if_.cond)) \
- return false; \
- if (!block_f(g, &e->if_.body)) \
- return false; \
- if (e->if_.next_elif) \
- if (!f(g, e->if_.next_elif)) \
- return false; \
- break; \
- case EXPR_WHILE: \
- if (e->while_.cond) \
- if (!f(g, e->while_.cond)) \
- return false; \
- if (!block_f(g, &e->while_.body)) \
- return false; \
- break; \
- case EXPR_EACH: { \
- EachExpr *ea = &e->each; \
- if (!each_enter(e)) return false; \
- if (ea->flags & EACH_IS_RANGE) { \
- if (!f(g, ea->range.from)) \
- return false; \
- if (ea->range.to && !f(g, ea->range.to)) \
- return false; \
- /* step is a value, not an expression */ \
- } else { \
- if (!f(g, ea->of)) \
- return false; \
- } \
- if (!block_f(g, &ea->body)) return false; \
- each_exit(e); \
- } break; \
- case EXPR_TUPLE: \
- arr_foreach(e->tuple, Expression, x) \
- if (!f(g, x)) \
- return false; \
- break; \
- case EXPR_SLICE: \
- if (!f(g, e->slice.of)) return false; \
- if (e->slice.from && !f(g, e->slice.from)) \
- return false; \
- if (e->slice.to && !f(g, e->slice.to)) \
- return false; \
- break; \
- case EXPR_FN: \
- if (!fn_enter(&e->fn, 0)) return false; \
- arr_foreach(e->fn.params, Declaration, param) \
- if (!decl_f(g, param)) \
- return false; \
- arr_foreach(e->fn.ret_decls, Declaration, r) \
- if (!decl_f(g, r)) \
- return false; \
- if (!block_f(g, &e->fn.body)) \
- return false; \
- fn_exit(&e->fn); \
- break; \
- case EXPR_NEW: \
- if (e->new.n && !f(g, e->new.n)) \
- return false; \
- break; \
+#define cgen_recurse_subexprs(g, e, f, block_f, decl_f) \
+ switch (e->kind) { \
+ case EXPR_TYPE: \
+ case EXPR_VAL: \
+ case EXPR_C: \
+ case EXPR_DSIZEOF: \
+ case EXPR_DALIGNOF: \
+ case EXPR_IDENT: \
+ case EXPR_LITERAL_BOOL: \
+ case EXPR_LITERAL_INT: \
+ case EXPR_LITERAL_STR: \
+ case EXPR_LITERAL_CHAR: \
+ case EXPR_LITERAL_FLOAT: \
+ break; \
+ case EXPR_UNARY_OP: \
+ if (!f(g, e->unary.of)) return false; \
+ break; \
+ case EXPR_BINARY_OP: \
+ if (!f(g, e->binary.lhs)) return false; \
+ if (e->binary.op != BINARY_DOT) \
+ if (!f(g, e->binary.rhs)) \
+ return false; \
+ break; \
+ case EXPR_CAST: \
+ if (!f(g, e->cast.expr)) \
+ return false; \
+ break; \
+ case EXPR_CALL: \
+ if (!f(g, e->call.fn)) \
+ return false; \
+ arr_foreach(e->call.arg_exprs, Expression, arg) \
+ if (!f(g, arg)) \
+ return false; \
+ break; \
+ case EXPR_BLOCK: \
+ if (!block_f(g, &e->block)) \
+ return false; \
+ break; \
+ case EXPR_IF: \
+ if (e->if_.cond) \
+ if (!f(g, e->if_.cond)) \
+ return false; \
+ if (!block_f(g, &e->if_.body)) \
+ return false; \
+ if (e->if_.next_elif) \
+ if (!f(g, e->if_.next_elif)) \
+ return false; \
+ break; \
+ case EXPR_WHILE: \
+ if (e->while_.cond) \
+ if (!f(g, e->while_.cond)) \
+ return false; \
+ if (!block_f(g, &e->while_.body)) \
+ return false; \
+ break; \
+ case EXPR_EACH: { \
+ EachExpr *ea = &e->each; \
+ if (!each_enter(e)) return false; \
+ if (ea->flags & EACH_IS_RANGE) { \
+ if (!f(g, ea->range.from)) \
+ return false; \
+ if (ea->range.to && !f(g, ea->range.to)) \
+ return false; \
+ /* step is a value, not an expression */ \
+ } else { \
+ if (!f(g, ea->of)) \
+ return false; \
+ } \
+ if (!block_f(g, &ea->body)) return false; \
+ each_exit(e); \
+ } break; \
+ case EXPR_TUPLE: \
+ arr_foreach(e->tuple, Expression, x) \
+ if (!f(g, x)) \
+ return false; \
+ break; \
+ case EXPR_SLICE: \
+ if (!f(g, e->slice.of)) return false; \
+ if (e->slice.from && !f(g, e->slice.from)) \
+ return false; \
+ if (e->slice.to && !f(g, e->slice.to)) \
+ return false; \
+ break; \
+ case EXPR_FN: { \
+ FnExpr *fn = &e->fn; \
+ if (e->type.fn.constness) { \
+ Instance **data = fn->instance.data; \
+ for (U64 i = 0; i < f->instances.cap; i++) { \
+ if (f->instances.occupied[i]) { \
+ cgen_recurse_subexprs_fn_simple(&(*data)->fn, decl_f, block_f); \
+ } \
+ data++; \
+ } \
+ } else { \
+ cgen_recurse_subexprs_fn_simple(fn, decl_f, block_f); \
+ } \
+ break; \
+ case EXPR_NEW: \
+ if (e->new.n && !f(g, e->new.n)) \
+ return false; \
+ break; \
}
static bool cgen_block_enter(CGenerator *g, Block *b) {
@@ -1377,7 +1391,7 @@ static bool cgen_expr(CGenerator *g, Expression *e) {
case EXPR_TUPLE:
/* the only time this should happen is if you're stating
a tuple, e.g. 3, 5;, but we've errored about that before
- (the comma operator does not exist in toc!) */
+ */
case EXPR_TYPE:
assert(0);
break;
@@ -1692,7 +1706,7 @@ static bool cgen_decl(CGenerator *g, Declaration *d) {
struct declarations are handled by typedefs_cgen,
and struct definitions are handled by decls_cgen.
we don't need to do anything here.
- */
+ */
continue;
} else if (type->kind == TYPE_FN && (d->flags & DECL_IS_CONST)) {
/* don't generate function pointer declaration for constant fns */
@@ -1766,6 +1780,7 @@ static bool cgen_decl(CGenerator *g, Declaration *d) {
/* does NOT call cgen_expr_pre for ret. */
static bool cgen_ret(CGenerator *g, Expression *ret) {
assert((g->fn->ret_type.kind == TYPE_VOID) == (ret == NULL));
+ if (ret) assert(type_eq(&g->fn->ret_type, &ret->type));
if (!ret) {
cgen_write(g, "return");
} else if (cgen_uses_ptr(&g->fn->ret_type)) {
@@ -1834,7 +1849,7 @@ static bool cgen_defs_expr(CGenerator *g, Expression *e) {
for (U64 i = 0; i < instances->cap; i++) {
if (instances->occupied[i]) {
/* generate this instance */
- if (!cgen_fn(g, f, e->where, is[i]->c.id, is[i]->val.tuple))
+ if (!cgen_fn(g, &is[i]->fn, e->where, is[i]->c.id, is[i]->val.tuple))
return false;
}
}
@@ -1891,7 +1906,7 @@ static bool cgen_file(CGenerator *g, ParsedFile *f) {
/*
TODO: to improve compile times, don't include stdlib.h
(you can even get away with not including stdio.h with posix file descriptors)
- */
+ */
cgen_write(g, "#include <stdint.h>\n"
"#include <stdlib.h>\n"
"#include <stdio.h>\n"