commit ebf6048bcef837d211d9bdb15a7ae3eda08b45df
parent 6498602e151d782f2845d91f26bd9954abb9b399
Author: Drew DeVault <sir@cmpwn.com>
Date: Fri, 13 Aug 2021 09:26:44 +0200
gen: implement variadic insert
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/src/gen.c b/src/gen.c
@@ -1613,7 +1613,20 @@ gen_expr_insert(struct gen_context *ctx, const struct expression *expr)
struct qbe_value newlen = mkqtmp(ctx, ctx->arch.sz, ".%d");
pushi(ctx->current, &newlen, Q_ADD, &len, &nadd, NULL);
- assert(!expr->insert.variadic); // TODO
+ struct gen_value vobj;
+ struct qbe_value vlen = constl(0), vdata;
+ if (expr->insert.variadic) {
+ vobj = gen_expr(ctx, expr->insert.variadic);
+ struct qbe_value lval = mklval(ctx, &vobj);
+ vdata = mkqtmp(ctx, ctx->arch.ptr, ".%d");
+ pushi(ctx->current, &vdata, load, &lval, NULL);
+
+ struct qbe_value vptr = mkqtmp(ctx, ctx->arch.ptr, ".%d");
+ vlen = mkqtmp(ctx, ctx->arch.sz, ".%d");
+ pushi(ctx->current, &vptr, Q_ADD, &lval, &offs, NULL);
+ pushi(ctx->current, &vlen, load, &vptr, NULL);
+ pushi(ctx->current, &newlen, Q_ADD, &newlen, &vlen, NULL);
+ }
enum qbe_instr store = store_for_type(ctx, &builtin_type_size);
pushi(ctx->current, NULL, store, &newlen, &lenptr, NULL);
@@ -1633,7 +1646,8 @@ gen_expr_insert(struct gen_context *ctx, const struct expression *expr)
pushi(ctx->current, &src, Q_ADD, &base, &src, NULL);
struct qbe_value nbyte = mkqtmp(ctx, ctx->arch.sz, ".%d");
struct qbe_value dest = mkqtmp(ctx, ctx->arch.ptr, ".%d");
- pushi(ctx->current, &nbyte, Q_MUL, &nadd, &membsz, NULL);
+ pushi(ctx->current, &nbyte, Q_ADD, &nadd, &vlen, NULL);
+ pushi(ctx->current, &nbyte, Q_MUL, &nbyte, &membsz, NULL);
pushi(ctx->current, &dest, Q_ADD, &src, &nbyte, NULL);
rtfunc = mkrtfunc(ctx, "rt.memmove");
@@ -1649,6 +1663,11 @@ gen_expr_insert(struct gen_context *ctx, const struct expression *expr)
gen_expr_at(ctx, value->expr, gv);
pushi(ctx->current, &src, Q_ADD, &src, &membsz, NULL);
}
+ if (expr->insert.variadic) {
+ rtfunc = mkrtfunc(ctx, "rt.memcpy");
+ pushi(ctx->current, &nbyte, Q_MUL, &vlen, &membsz, NULL);
+ pushi(ctx->current, NULL, Q_CALL, &rtfunc, &src, &vdata, &nbyte, NULL);
+ }
return gv_void;
}