commit f45f75b96ab4fc6efc559440b16763eacd4ebca2
parent 604d9918562b12c009981c1ce1884f9bdeedaaf5
Author: Drew DeVault <sir@cmpwn.com>
Date: Tue, 12 Jan 2021 14:05:42 -0500
check: implement globals
Diffstat:
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
}
}