harec

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

commit 880dea36a4dcda574262dc70349b4baa08c9f4b8
parent 8b17d5954c0c53b8d57e5f9c1598408f99af6621
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sun, 10 Jan 2021 11:34:38 -0500

gen: implement struct expressions

Diffstat:
Msrc/check.c | 7+++++--
Msrc/gen.c | 24++++++++++++++++++++++++
Msrc/qtype.c | 16++++++++++++++--
3 files changed, 43 insertions(+), 4 deletions(-)

diff --git a/src/check.c b/src/check.c @@ -685,12 +685,13 @@ check_expr_struct(struct context *ctx, expr->result = type_store_lookup_atype(&ctx->store, &stype); - tfield = stype.struct_union.next; + tfield = &stype.struct_union; sexpr = &expr->_struct; while (tfield) { const struct struct_field *field = type_lookup_field( expr->result, tfield->field.name); // TODO: Use more specific error location + expect(&aexpr->loc, field, "No field by this name exists for this type"); expect(&aexpr->loc, type_is_assignable(&ctx->store, field->type, sexpr->value->result), "Cannot initialize struct field from value of this type"); @@ -698,7 +699,9 @@ check_expr_struct(struct context *ctx, sexpr->value = lower_implicit_cast(field->type, sexpr->value); struct ast_struct_union_type *next = tfield->next; - free(tfield); + if (tfield != &stype.struct_union) { + free(tfield); + } tfield = next; sexpr = sexpr->next; } diff --git a/src/gen.c b/src/gen.c @@ -959,6 +959,27 @@ gen_expr_return(struct gen_context *ctx, } static void +gen_expr_struct(struct gen_context *ctx, + const struct expression *expr, + const struct qbe_value *out) +{ + // XXX: ARCH + struct qbe_value base = {0}, ptr = {0}, offset = {0}; + gen_temp(ctx, &base, &qbe_long, "base.%d"); + gen_temp(ctx, &ptr, &qbe_long, "ptr.%d"); + pushi(ctx->current, &base, Q_COPY, out, NULL); + + const struct expression_struct *field = &expr->_struct; + while (field) { + constl(&offset, field->field->offset); + pushi(ctx->current, &ptr, Q_ADD, &base, &offset, NULL); + ptr.indirect = !type_is_aggregate(field->field->type); + gen_expression(ctx, field->value, &ptr); + field = field->next; + } +} + +static void gen_expr_address(struct gen_context *ctx, const struct expression *expr, const struct qbe_value *out) @@ -1072,7 +1093,10 @@ gen_expression(struct gen_context *ctx, gen_expr_return(ctx, expr, out); break; case EXPR_SLICE: + assert(0); // TODO case EXPR_STRUCT: + gen_expr_struct(ctx, expr, out); + break; case EXPR_SWITCH: assert(0); // TODO case EXPR_UNARITHM: diff --git a/src/qtype.c b/src/qtype.c @@ -130,11 +130,23 @@ lookup_aggregate(struct gen_context *ctx, const struct type *type) field->type = &qbe_long; // XXX: ARCH field->count = 3; break; + case TYPE_STORAGE_STRUCT: + case TYPE_STORAGE_UNION: + assert(type->struct_union.c_compat); // TODO + for (struct struct_field *tfield = type->struct_union.fields; + tfield; tfield = tfield->next) { + field->type = qtype_for_type(ctx, tfield->type, true); + field->count = 1; + + if (tfield->next) { + field->next = xcalloc(1, sizeof(struct qbe_field)); + field = field->next; + } + } + break; case TYPE_STORAGE_ENUM: case TYPE_STORAGE_SLICE: - case TYPE_STORAGE_STRUCT: case TYPE_STORAGE_TAGGED_UNION: - case TYPE_STORAGE_UNION: assert(0); // TODO case TYPE_STORAGE_ARRAY: case TYPE_STORAGE_ALIAS: