commit a34531174c345e658267fa8f7bc7bdc0035c0c36
parent ec59e8c5881a3b4c68e9c7d023f11f18c40d83cc
Author: Drew DeVault <sir@cmpwn.com>
Date: Sun, 24 Jan 2021 11:13:32 -0500
gen: fix isssues with aggregate types in return
Diffstat:
2 files changed, 33 insertions(+), 12 deletions(-)
diff --git a/src/emit.c b/src/emit.c
@@ -137,16 +137,22 @@ emit_stmt(struct qbe_statement *stmt, FILE *out)
break;
case Q_INSTR:
fprintf(out, "\t");
+ if (stmt->instr == Q_CALL) {
+ if (stmt->out != NULL) {
+ emit_value(stmt->out, out);
+ fprintf(out, " =");
+ emit_qtype(stmt->out->type, true, out);
+ fprintf(out, " ");
+ }
+ emit_call(stmt, out);
+ break;
+ }
if (stmt->out != NULL) {
emit_value(stmt->out, out);
fprintf(out, " =");
emit_qtype(stmt->out->type, false, out);
fprintf(out, " ");
}
- if (stmt->instr == Q_CALL) {
- emit_call(stmt, out);
- break;
- }
fprintf(out, "%s%s", qbe_instr[stmt->instr],
stmt->args ? " " : "");
struct qbe_arguments *arg = stmt->args;
diff --git a/src/gen.c b/src/gen.c
@@ -623,6 +623,8 @@ gen_expr_assign(struct gen_context *ctx,
} else {
const struct expression *object = expr->assign.object;
address_object(ctx, object, &src);
+ pushc(ctx->current, "assign to object %s (%c)",
+ src.name, (char)src.type->stype);
}
const struct expression *value = expr->assign.value;
@@ -990,6 +992,11 @@ gen_expr_cast(struct gen_context *ctx,
return;
}
+ if (to->storage == TYPE_STORAGE_VOID) {
+ gen_expression(ctx, expr->cast.value, NULL);
+ return;
+ }
+
if (type_is_aggregate(expr->cast.value->result)
&& expr->cast.value->type == EXPR_CONSTANT) {
// This is a stupid fucking hack
@@ -1987,6 +1994,9 @@ gen_function_decl(struct gen_context *ctx, const struct declaration *decl)
struct qbe_value rval = {0};
if (fntype->func.result->storage != TYPE_STORAGE_VOID) {
alloc_temp(ctx, &rval, fntype->func.result, "ret.%d");
+ if (type_is_aggregate(fntype->func.result)) {
+ rval.indirect = false;
+ }
ctx->return_value = &rval;
} else {
ctx->return_value = NULL;
@@ -2000,11 +2010,15 @@ gen_function_decl(struct gen_context *ctx, const struct declaration *decl)
pop_scope(ctx);
if (fntype->func.result->storage != TYPE_STORAGE_VOID) {
- struct qbe_value load = {0};
- gen_loadtemp(ctx, &load, ctx->return_value,
- qdef->func.returns,
- type_is_signed(fntype->func.result));
- pushi(&qdef->func, NULL, Q_RET, &load, NULL);
+ if (type_is_aggregate(fntype->func.result)) {
+ pushi(&qdef->func, NULL, Q_RET, ctx->return_value, NULL);
+ } else {
+ struct qbe_value load = {0};
+ gen_loadtemp(ctx, &load, ctx->return_value,
+ qdef->func.returns,
+ type_is_signed(fntype->func.result));
+ pushi(&qdef->func, NULL, Q_RET, &load, NULL);
+ }
} else {
pushi(&qdef->func, NULL, Q_RET, NULL);
}
@@ -2105,10 +2119,11 @@ gen_data_item(struct gen_context *ctx, struct expression *expr,
break;
case TYPE_STORAGE_ARRAY:
assert(type->array.length != SIZE_UNDEFINED);
- assert(!constant->array->expand); // TODO
- for (struct array_constant *c = constant->array; c; c = c->next) {
+ size_t n = type->array.length;
+ for (struct array_constant *c = constant->array;
+ c && n; c = c->next ? c->next : c, --n) {
gen_data_item(ctx, c->value, item);
- if (c->next) {
+ if (n > 1 || c->next) {
item->next = xcalloc(1,
sizeof(struct qbe_data_item));
item = item->next;