harec

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

commit 9f60dab67d65cda180878cac0b6f48bdfb263272
parent cd4dfcf87c170daeafcc1df59d6cd834d4895726
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sun,  4 Jul 2021 11:31:32 -0400

gen: implement string constants

Signed-off-by: Drew DeVault <sir@cmpwn.com>

Diffstat:
Msrc/gen.c | 50+++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/qtype.c | 6+++++-
2 files changed, 54 insertions(+), 2 deletions(-)

diff --git a/src/gen.c b/src/gen.c @@ -444,6 +444,51 @@ gen_expr_const_array(struct gen_context *ctx, } static void +gen_expr_const_string(struct gen_context *ctx, + size_t length, const char *value, + const struct gen_temp *out) +{ + struct qbe_value global = {0}; + gen_qtemp(ctx, &global, ctx->arch.ptr, "strdata.%d"); + global.kind = QV_GLOBAL; + + struct qbe_def *def = xcalloc(1, sizeof(struct qbe_def)); + def->name = global.name; + def->kind = Q_DATA; + def->data.items.type = QD_STRING; + def->data.items.str = xcalloc(1, length); + memcpy(def->data.items.str, value, length); + def->data.items.sz = length; + + if (length != 0) { + qbe_append_def(ctx->out, def); + } else { + free(def); + constl(&global, 0); + } + + assert(out->indirect); // Invariant + struct qbe_value qout = {0}, temp = {0}; + qval_temp(ctx, &qout, out); + gen_qtemp(ctx, &temp, ctx->arch.ptr, "str.%d"); + pushi(ctx->current, &temp, Q_COPY, &qout, NULL); + + struct qbe_value offset = {0}, qlength = {0}; + const struct type *voidptr = type_store_lookup_pointer(ctx->store, + &builtin_type_void, 0); + pushi(ctx->current, NULL, store_for_type(ctx, voidptr), + &global, &temp, NULL); + constl(&offset, voidptr->size); + constl(&qlength, length); + pushi(ctx->current, &temp, Q_ADD, &temp, &offset, NULL); + pushi(ctx->current, NULL, store_for_type(ctx, &builtin_type_size), + &qlength, &temp, NULL); + pushi(ctx->current, &temp, Q_ADD, &temp, &offset, NULL); + pushi(ctx->current, NULL, store_for_type(ctx, &builtin_type_size), + &qlength, &temp, NULL); +} + +static void gen_expr_constant(struct gen_context *ctx, const struct expression *expr, const struct gen_temp *out) @@ -500,11 +545,14 @@ gen_expr_constant(struct gen_context *ctx, gen_expr_const_array(ctx, type_dealias(expr->result), constexpr->array, out); return; + case STORAGE_STRING: + gen_expr_const_string(ctx, constexpr->string.len, + constexpr->string.value, out); + return; case STORAGE_UINTPTR: case STORAGE_POINTER: case STORAGE_NULL: case STORAGE_SLICE: - case STORAGE_STRING: case STORAGE_TAGGED: case STORAGE_TUPLE: assert(0); // TODO diff --git a/src/qtype.c b/src/qtype.c @@ -44,7 +44,11 @@ aggregate_lookup(struct gen_context *ctx, const struct type *type) field->type = qtype_lookup(ctx, type->array.members, true); break; case STORAGE_STRING: - assert(0); // TODO + // XXX: This assertion does not hold for all architectures + assert(ctx->arch.ptr->stype == ctx->arch.sz->stype); + field->type = ctx->arch.ptr; + field->count = 3; + break; case STORAGE_STRUCT: case STORAGE_UNION: assert(type->struct_union.c_compat); // TODO