commit cffdad98039c202e0c2e39bbf952dfdf6b26f0ab
parent 3520ab2c1510f12b066ab1d1dafcdba6abf2435b
Author: Drew DeVault <sir@cmpwn.com>
Date: Thu, 5 Aug 2021 09:48:09 +0200
gen: commoditize branch consolidation
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
3 files changed, 23 insertions(+), 12 deletions(-)
diff --git a/include/gen.h b/include/gen.h
@@ -74,6 +74,8 @@ struct qbe_value mkqtmp(struct gen_context *ctx,
struct qbe_value mkrtfunc(struct gen_context *ctx, const char *name);
struct qbe_value mklabel(struct gen_context *ctx,
struct qbe_statement *stmt, const char *fmt);
+void branch_copyresult(struct gen_context *ctx, struct gen_value result,
+ struct gen_value merged, struct gen_value *out);
// qinstr.c
enum qbe_instr alloc_for_align(size_t align);
diff --git a/src/gen.c b/src/gen.c
@@ -537,10 +537,8 @@ gen_expr_if_with(struct gen_context *ctx,
struct gen_value *out)
{
struct gen_value gvout = gv_void;
- struct qbe_value qvout;
if (!out && type_dealias(expr->result)->storage != STORAGE_VOID) {
gvout = mktemp(ctx, expr->result, ".%d");
- qvout = mkqval(ctx, &gvout);
}
struct qbe_statement ltrue, lfalse, lend;
@@ -553,20 +551,14 @@ gen_expr_if_with(struct gen_context *ctx,
push(&ctx->current->body, <rue);
struct gen_value vtrue = gen_expr_with(ctx, expr->_if.true_branch, out);
- if (!out && type_dealias(expr->result)->storage != STORAGE_VOID) {
- struct qbe_value qvtrue = mkqval(ctx, &vtrue);
- pushi(ctx->current, &qvout, Q_COPY, &qvtrue, NULL);
- }
+ branch_copyresult(ctx, vtrue, gvout, out);
pushi(ctx->current, NULL, Q_JMP, &bend, NULL);
push(&ctx->current->body, &lfalse);
if (expr->_if.false_branch) {
- struct gen_value vfalse = gen_expr_with(
- ctx, expr->_if.false_branch, out);
- if (!out && type_dealias(expr->result)->storage != STORAGE_VOID) {
- struct qbe_value qvfalse = mkqval(ctx, &vfalse);
- pushi(ctx->current, &qvout, Q_COPY, &qvfalse, NULL);
- }
+ struct gen_value vfalse = gen_expr_with(ctx,
+ expr->_if.false_branch, out);
+ branch_copyresult(ctx, vfalse, gvout, out);
}
push(&ctx->current->body, &lend);
diff --git a/src/genutil.c b/src/genutil.c
@@ -92,3 +92,20 @@ mklabel(struct gen_context *ctx, struct qbe_statement *stmt, const char *fmt)
val.name = strdup(genl(stmt, &ctx->id, fmt));
return val;
}
+
+void
+branch_copyresult(struct gen_context *ctx,
+ struct gen_value result,
+ struct gen_value merged,
+ struct gen_value *out)
+{
+ // Branching expressions written in the _with style may need to
+ // consolodate each branch's result into a single temporary to return to
+ // the caller. This function facilitates that.
+ if (out || type_dealias(result.type)->storage == STORAGE_VOID) {
+ return;
+ }
+ struct qbe_value qmerged = mkqval(ctx, &merged);
+ struct qbe_value qval = mkqval(ctx, &result);
+ pushi(ctx->current, &qmerged, Q_COPY, &qval, NULL);
+}