commit 73d32ab237ae360fe25ad74a56344b6a7855832c
parent 05841a240381fe6d0bc5567dfbe1cb0688a6436b
Author: Alexey Yerin <yyp@disroot.org>
Date: Mon, 9 Aug 2021 22:25:10 +0300
gen: implement @test functions
Signed-off-by: Alexey Yerin <yyp@disroot.org>
Diffstat:
M | src/gen.c | | | 50 | +++++++++++++++++++++++++++++++++++++++++++++++--- |
1 file changed, 47 insertions(+), 3 deletions(-)
diff --git a/src/gen.c b/src/gen.c
@@ -2038,6 +2038,8 @@ gen_expr_with(struct gen_context *ctx,
return gen_expr(ctx, expr);
}
+static struct qbe_data_item *gen_data_item(struct gen_context *,
+ struct expression *, struct qbe_data_item *);
static void
gen_function_decl(struct gen_context *ctx, const struct declaration *decl)
{
@@ -2050,10 +2052,15 @@ 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 = decl->symbol ? strdup(decl->symbol)
- : ident_to_sym(&decl->ident);
ctx->current = &qdef->func;
+ if (func->flags & FN_TEST) {
+ qdef->name = gen_name(ctx, "testfunc.%d");
+ } else {
+ qdef->name = decl->symbol ? strdup(decl->symbol)
+ : ident_to_sym(&decl->ident);
+ }
+
struct qbe_statement start_label = {0};
mklabel(ctx, &start_label, "start.%d");
push(&qdef->func.prelude, &start_label);
@@ -2173,7 +2180,44 @@ gen_function_decl(struct gen_context *ctx, const struct declaration *decl)
qbe_append_def(ctx->out, fini);
}
- if (func->flags & FN_TEST) assert(0); // TODO
+ if (func->flags & FN_TEST) {
+ struct qbe_def *test = xcalloc(1, sizeof *test);
+ test->kind = Q_DATA;
+ test->exported = false;
+ test->data.align = 8;
+ test->data.section = ".test_array";
+ test->data.secflags = "aw";
+
+ size_t n = snprintf(NULL, 0, ".test.%s", qdef->name);
+ test->name = xcalloc(n + 1, 1);
+ snprintf(test->name, n + 1, ".test.%s", qdef->name);
+
+ char *ident = identifier_unparse(&decl->ident);
+
+ struct qbe_data_item *dataitem = &test->data.items;
+ struct expression expr = {
+ .type = EXPR_CONSTANT,
+ .result = &builtin_type_str,
+ .constant = {
+ .object = NULL,
+ .string = {
+ .value = ident,
+ .len = strlen(ident),
+ },
+ },
+ };
+ dataitem = gen_data_item(ctx, &expr, dataitem);
+
+ struct qbe_data_item *next = xcalloc(1, sizeof *next);
+ next->type = QD_VALUE;
+ next->value.kind = QV_GLOBAL;
+ next->value.type = &qbe_long;
+ next->value.name = strdup(qdef->name);
+ next->next = NULL;
+ dataitem->next = next;
+
+ qbe_append_def(ctx->out, test);
+ }
ctx->current = NULL;
}