commit 97cbdab969488853362d591e656fa19c06afe8c6
parent da5beb0f312268972e26cb09c00eb5ab05beddaf
Author: Drew DeVault <sir@cmpwn.com>
Date: Mon, 28 Dec 2020 13:23:03 -0500
gen: fix various issues with call
Diffstat:
3 files changed, 21 insertions(+), 14 deletions(-)
diff --git a/src/emit.c b/src/emit.c
@@ -15,11 +15,10 @@ emit_qtype(const struct qbe_type *type, FILE *out)
case Q_DOUBLE:
fprintf(out, "%c", (char)type->stype);
break;
+ case Q__AGGREGATE:
+ assert(0); // TODO
case Q__VOID:
break; // no-op
- case Q__AGGREGATE:
- fprintf(out, "l"); // XXX: ARCH
- break;
}
}
diff --git a/src/gen.c b/src/gen.c
@@ -147,10 +147,9 @@ gen_store(struct gen_context *ctx,
assert(dest->indirect);
// XXX: ARCH
pushi(ctx->current, NULL, Q_STOREL, src, dest, NULL);
- } else if (dest->type->stype == Q__AGGREGATE) {
+ } else if (!dest->indirect && dest->type->stype == Q__AGGREGATE) {
assert(0); // TODO: memcpy
} else {
- assert(dest->type == &qbe_long);
pushi(ctx->current, dest, Q_COPY, src, NULL);
}
return;
@@ -363,15 +362,18 @@ gen_expr_binarithm(struct gen_context *ctx,
}
static void
-gen_call(struct gen_context *ctx,
+gen_expr_call(struct gen_context *ctx,
const struct expression *expr,
const struct qbe_value *out)
{
- // XXX: AUDIT ME
+ struct qbe_value result = {0};
+ gen_temp(ctx, &result, qtype_for_type(ctx,
+ expr->call.lvalue->result->func.result, true), "returns.%d");
+
struct qbe_statement call = {
.type = Q_INSTR,
.instr = Q_CALL,
- .out = out ? qval_dup(out) : NULL,
+ .out = qval_dup(&result),
};
struct qbe_arguments *arg, **next = &call.args;
@@ -385,14 +387,21 @@ gen_call(struct gen_context *ctx,
assert(!carg->variadic); // TODO
arg = *next = xcalloc(1, sizeof(struct qbe_arguments));
gen_temp(ctx, &arg->value,
- qtype_for_type(ctx, carg->value->result, false),
+ qtype_for_type(ctx, carg->value->result, true),
"arg.%d");
+ if (type_is_aggregate(carg->value->result)) {
+ qval_address(&arg->value);
+ }
gen_expression(ctx, carg->value, &arg->value);
carg = carg->next;
next = &arg->next;
}
push(&ctx->current->body, &call);
+
+ if (out) {
+ gen_store(ctx, out, &result);
+ }
}
static void
@@ -424,7 +433,7 @@ gen_array(struct gen_context *ctx,
}
static void
-gen_constant(struct gen_context *ctx,
+gen_expr_constant(struct gen_context *ctx,
const struct expression *expr,
const struct qbe_value *out)
{
@@ -621,12 +630,12 @@ gen_expression(struct gen_context *ctx,
case EXPR_BREAK:
assert(0); // TODO
case EXPR_CALL:
- gen_call(ctx, expr, out);
+ gen_expr_call(ctx, expr, out);
break;
case EXPR_CAST:
assert(0); // TODO
case EXPR_CONSTANT:
- gen_constant(ctx, expr, out);
+ gen_expr_constant(ctx, expr, out);
break;
case EXPR_CONTINUE:
case EXPR_FOR:
diff --git a/src/qtype.c b/src/qtype.c
@@ -170,9 +170,8 @@ type_is_aggregate(const struct type *type)
case TYPE_STORAGE_STRUCT:
case TYPE_STORAGE_TAGGED_UNION:
case TYPE_STORAGE_UNION:
- return true;
case TYPE_STORAGE_FUNCTION:
- assert(0); // Invariant
+ return true;
}
assert(0); // Unreachable
}