harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit f45f75b96ab4fc6efc559440b16763eacd4ebca2
parent 604d9918562b12c009981c1ce1884f9bdeedaaf5
Author: Drew DeVault <sir@cmpwn.com>
Date:   Tue, 12 Jan 2021 14:05:42 -0500

check: implement globals

Diffstat:
Minclude/check.h | 7++++++-
Msrc/check.c | 116++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
Msrc/gen.c | 16+++++++++++-----
3 files changed, 105 insertions(+), 34 deletions(-)

diff --git a/include/check.h b/include/check.h @@ -27,10 +27,14 @@ struct function_decl { const struct type *type; struct expression *body; struct scope *scope; - char *symbol; unsigned int flags; // enum function_flags }; +struct global_decl { + const struct type *type; + struct expression *value; // EXPR_CONSTANT +}; + enum declaration_type { DECL_FUNC, DECL_TYPE, @@ -44,6 +48,7 @@ struct declaration { bool exported; union { struct function_decl func; + struct global_decl global; }; }; diff --git a/src/check.c b/src/check.c @@ -1001,6 +1001,44 @@ check_function(struct context *ctx, return decl; } +static struct declaration * +check_global(struct context *ctx, + const struct ast_decl *adecl) +{ + const struct ast_global_decl *agdecl = &adecl->global; + const struct type *type = type_store_lookup_atype( + &ctx->store, agdecl->type); + + // TODO: Free initialier + struct expression *initializer = + xcalloc(1, sizeof(struct expression)); + check_expression(ctx, agdecl->init, initializer); + + expect(&agdecl->init->loc, + type_is_assignable(&ctx->store, type, initializer->result), + "Constant type is not assignable from initializer type"); + initializer = lower_implicit_cast(type, initializer); + + struct expression *value = + xcalloc(1, sizeof(struct expression)); + enum eval_result r = eval_expr(ctx, initializer, value); + expect(&agdecl->init->loc, r == EVAL_OK, + "Unable to evaluate global initializer at compile time"); + + struct declaration *decl = xcalloc(1, sizeof(struct declaration)); + decl->type = DECL_GLOBAL; + decl->global.type = type; + decl->global.value = value; + + if (agdecl->symbol) { + decl->ident.name = strdup(agdecl->symbol); + } else { + mkident(ctx, &decl->ident, &agdecl->ident); + } + + return decl; +} + static struct declarations ** check_declarations(struct context *ctx, const struct ast_decls *adecls, @@ -1017,7 +1055,8 @@ check_declarations(struct context *ctx, case AST_DECL_TYPE: break; // Handled in scan case AST_DECL_GLOBAL: - assert(0); // TODO + decl = check_global(ctx, adecl); + break; case AST_DECL_CONST: break; // Handled in scan } @@ -1037,6 +1076,39 @@ check_declarations(struct context *ctx, } static void +scan_const(struct context *ctx, const struct ast_global_decl *decl) +{ + trenter(TR_SCAN, "constant"); + assert(!decl->symbol); // Invariant + + const struct type *type = type_store_lookup_atype( + &ctx->store, decl->type); + // TODO: + // - Free the initializer + // - Defer if we can't evaluate it now (for forward references) + struct expression *initializer = + xcalloc(1, sizeof(struct expression)); + check_expression(ctx, decl->init, initializer); + + expect(&decl->init->loc, type_is_assignable(&ctx->store, type, initializer->result), + "Constant type is not assignable from initializer type"); + initializer = lower_implicit_cast(type, initializer); + + struct expression *value = + xcalloc(1, sizeof(struct expression)); + enum eval_result r = eval_expr(ctx, initializer, value); + // TODO: More forward reference issues: + expect(&decl->init->loc, r == EVAL_OK, + "Unable to evaluate constant initializer at compile time"); + + struct identifier ident = {0}; + mkident(ctx, &ident, &decl->ident); + scope_insert(ctx->unit, O_CONST, &ident, &decl->ident, type, value); + + trleave(TR_SCAN, NULL); +} + +static void scan_function(struct context *ctx, const struct ast_function_decl *decl) { trenter(TR_SCAN, "function"); @@ -1063,34 +1135,21 @@ scan_function(struct context *ctx, const struct ast_function_decl *decl) } static void -scan_const(struct context *ctx, const struct ast_global_decl *decl) +scan_global(struct context *ctx, const struct ast_global_decl *decl) { - trenter(TR_SCAN, "constant"); - assert(!decl->symbol); // Invariant + trenter(TR_SCAN, "global"); const struct type *type = type_store_lookup_atype( &ctx->store, decl->type); - // TODO: - // - Free the initializer - // - Defer if we can't evaluate it now (for forward references) - struct expression *initializer = - xcalloc(1, sizeof(struct expression)); - check_expression(ctx, decl->init, initializer); - - // TODO: Lower implicit casts - expect(&decl->init->loc, type_is_assignable(&ctx->store, type, initializer->result), - "Constant type is not assignable from initializer type"); - - struct expression *value = - xcalloc(1, sizeof(struct expression)); - enum eval_result r = eval_expr(ctx, initializer, value); - // TODO: More forward reference issues: - expect(&decl->init->loc, r == EVAL_OK, - "Unable to evaluate initializer at compile time"); + assert(type); // TODO: Forward references struct identifier ident = {0}; - mkident(ctx, &ident, &decl->ident); - scope_insert(ctx->unit, O_CONST, &ident, &decl->ident, type, value); + if (decl->symbol) { + ident.name = strdup(decl->symbol); + } else { + mkident(ctx, &ident, &decl->ident); + } + scope_insert(ctx->unit, O_DECL, &ident, &decl->ident, type, NULL); trleave(TR_SCAN, NULL); } @@ -1115,17 +1174,18 @@ scan_declarations(struct context *ctx, const struct ast_decls *decls) while (decls) { const struct ast_decl *decl = &decls->decl; switch (decl->decl_type) { + case AST_DECL_CONST: + scan_const(ctx, &decl->constant); + break; case AST_DECL_FUNC: scan_function(ctx, &decl->function); break; + case AST_DECL_GLOBAL: + scan_global(ctx, &decl->global); + break; case AST_DECL_TYPE: scan_type(ctx, &decl->type); break; - case AST_DECL_GLOBAL: - assert(0); // TODO - case AST_DECL_CONST: - scan_const(ctx, &decl->constant); - break; } decls = decls->next; } diff --git a/src/gen.c b/src/gen.c @@ -1197,7 +1197,6 @@ gen_expression(struct gen_context *ctx, static void gen_function_decl(struct gen_context *ctx, const struct declaration *decl) { - // XXX: AUDIT ME assert(decl->type == DECL_FUNC); const struct function_decl *func = &decl->func; const struct type *fntype = func->type; @@ -1206,8 +1205,7 @@ gen_function_decl(struct gen_context *ctx, const struct declaration *decl) struct qbe_def *qdef = xcalloc(1, sizeof(struct qbe_def)); qdef->kind = Q_FUNC; qdef->exported = decl->exported; - qdef->name = func->symbol ? strdup(func->symbol) - : ident_to_sym(&decl->ident); + qdef->name = ident_to_sym(&decl->ident); qdef->func.returns = qtype_for_type(ctx, fntype->func.result, false); ctx->current = &qdef->func; @@ -1289,16 +1287,24 @@ gen_function_decl(struct gen_context *ctx, const struct declaration *decl) } static void +gen_global_decl(struct gen_context *ctx, const struct declaration *decl) +{ + assert(0); // TODO +} + +static void gen_decl(struct gen_context *ctx, const struct declaration *decl) { switch (decl->type) { case DECL_FUNC: gen_function_decl(ctx, decl); break; - case DECL_TYPE: case DECL_GLOBAL: + gen_global_decl(ctx, decl); + break; + case DECL_TYPE: case DECL_CONSTANT: - assert(0); // TODO + assert(0); // Invariant } }