harec

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

commit 6294e83e47c6544e86af1bc54e236737d09279b8
parent 2be84a5d9a548d102eb37f48d6aaa485f146e206
Author: Drew DeVault <sir@cmpwn.com>
Date:   Tue, 29 Dec 2020 09:43:38 -0500

gen: implement string constants

Diffstat:
Minclude/qbe.h | 22++++++++++++++++++++++
Msrc/emit.c | 40+++++++++++++++++++++++++++++++++++++---
Msrc/gen.c | 38++++++++++++++++++++++++++++++++++++++
Msrc/qtype.c | 6+++++-
Mtodo.txt | 4++++
5 files changed, 106 insertions(+), 4 deletions(-)

diff --git a/include/qbe.h b/include/qbe.h @@ -216,6 +216,27 @@ struct qbe_func { struct qbe_statements prelude, body; }; +enum qbe_datatype { + QD_VALUE, + QD_ZEROED, + QD_STRING, +}; + +struct qbe_data_item { + enum qbe_datatype type; + union { + struct qbe_value value; + size_t zeroed; + char *str; + }; + struct qbe_data_item *next; +}; + +struct qbe_data { + size_t align; + struct qbe_data_item items; +}; + enum qbe_defkind { Q_TYPE, Q_FUNC, @@ -229,6 +250,7 @@ struct qbe_def { union { struct qbe_func func; struct qbe_type type; + struct qbe_data data; }; struct qbe_def *next; }; diff --git a/src/emit.c b/src/emit.c @@ -161,8 +161,11 @@ static void emit_func(struct qbe_def *def, FILE *out) { assert(def->kind == Q_FUNC); - fprintf(out, "%sfunction ", def->exported ? "export " : ""); - emit_qtype(def->func.returns, out); + fprintf(out, "%sfunction", def->exported ? "export " : ""); + if (def->func.returns->stype != Q__VOID) { + fprintf(out, " "); + emit_qtype(def->func.returns, out); + } fprintf(out, " $%s(", def->name); struct qbe_func_param *param = def->func.params; while (param) { @@ -189,6 +192,36 @@ emit_func(struct qbe_def *def, FILE *out) } static void +emit_data(struct qbe_def *def, FILE *out) +{ + assert(def->kind == Q_DATA); + fprintf(out, "%sdata $%s = {", + def->exported ? "export " : "", + def->name); + + struct qbe_data_item *item = &def->data.items; + while (item) { + switch (item->type) { + case QD_VALUE: + assert(0); // TODO + case QD_ZEROED: + assert(0); // TODO + case QD_STRING: + fprintf(out, " b \"%s\", b 0", item->str); + break; + } + + if (item->next) { + fprintf(out, ","); + } + + item = item->next; + } + + fprintf(out, " }\n\n"); +} + +static void emit_def(struct qbe_def *def, FILE *out) { switch (def->kind) { @@ -199,7 +232,8 @@ emit_def(struct qbe_def *def, FILE *out) emit_func(def, out); break; case Q_DATA: - assert(0); // TODO + emit_data(def, out); + break; } } diff --git a/src/gen.c b/src/gen.c @@ -433,6 +433,41 @@ gen_array(struct gen_context *ctx, } static void +gen_string(struct gen_context *ctx, + const struct expression *expr, + const struct qbe_value *out) +{ + assert(!out->indirect); // Invariant + + struct qbe_value temp = {0}; + gen_temp(ctx, &temp, &qbe_long, "strdata.%d"); + temp.kind = QV_GLOBAL; + + struct qbe_def *def = xcalloc(1, sizeof(struct qbe_def)); + def->name = temp.name; + def->kind = Q_DATA; + def->data.items.type = QD_STRING; + // TODO: Escape special characters + def->data.items.str = strdup(expr->constant.string.value); + qbe_append_def(ctx->out, def); + + struct qbe_value str = {0}; + gen_temp(ctx, &str, &qbe_long, "str.%d"); // XXX: ARCH + pushi(ctx->current, &str, Q_COPY, out, NULL); + str.indirect = true; + + struct qbe_value size = {0}; + constl(&size, expr->constant.string.len); // XXX: ARCH + + gen_store(ctx, &str, &temp); + constl(&temp, 8); // XXX: ARCH + pushi(ctx->current, &str, Q_ADD, &str, &temp, NULL); + gen_store(ctx, &str, &size); + pushi(ctx->current, &str, Q_ADD, &str, &temp, NULL); + gen_store(ctx, &str, &size); +} + +static void gen_expr_constant(struct gen_context *ctx, const struct expression *expr, const struct qbe_value *out) @@ -461,6 +496,9 @@ gen_expr_constant(struct gen_context *ctx, case TYPE_STORAGE_ARRAY: gen_array(ctx, expr, out); return; + case TYPE_STORAGE_STRING: + gen_string(ctx, expr, out); + return; default: // Moving right along break; diff --git a/src/qtype.c b/src/qtype.c @@ -124,10 +124,14 @@ lookup_aggregate(struct gen_context *ctx, const struct type *type) def->type.name = name; def->type.align = SIZE_UNDEFINED; + struct qbe_field *field = &def->type.fields; switch (type->storage) { + case TYPE_STORAGE_STRING: + field->type = &qbe_long; // XXX: ARCH + field->count = 3; + break; case TYPE_STORAGE_ENUM: case TYPE_STORAGE_SLICE: - case TYPE_STORAGE_STRING: case TYPE_STORAGE_STRUCT: case TYPE_STORAGE_TAGGED_UNION: case TYPE_STORAGE_UNION: diff --git a/todo.txt b/todo.txt @@ -15,3 +15,7 @@ confidently implement the remainder of the features. general todos, includes spec updates: - zero-length arrays & slice initializers - allocations +- assign arrays from other arrays (memcpy) +- pass arrays directly into function calls (alloc if needed flag?) +- casts +- implicit casts