commit bc94ad21d938bd7616eccc0021cfafb8af4cc099
parent 9f60dab67d65cda180878cac0b6f48bdfb263272
Author: Drew DeVault <sir@cmpwn.com>
Date: Sun, 4 Jul 2021 11:42:19 -0400
gen: implement string copy
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
M | src/gen.c | | | 42 | +++++++++++++++++++++++++++++++++++++++++- |
1 file changed, 41 insertions(+), 1 deletion(-)
diff --git a/src/gen.c b/src/gen.c
@@ -197,6 +197,44 @@ gen_copy_struct(struct gen_context *ctx,
gen_copy_memcpy(ctx, dest, src);
}
+static void
+gen_copy_string(struct gen_context *ctx,
+ const struct gen_temp *dest,
+ const struct gen_temp *src)
+{
+ assert(dest->indirect && src->indirect);
+ const struct type *voidptr = type_store_lookup_pointer(ctx->store,
+ &builtin_type_void, 0);
+ enum qbe_instr store = store_for_type(ctx, voidptr);
+ enum qbe_instr load = load_for_type(ctx, voidptr);
+
+ struct qbe_value dptr = {0}, sptr = {0}, temp = {0}, offset = {0};
+ struct qbe_value qdest = {0}, qsrc = {0};
+ gen_qtemp(ctx, &dptr, ctx->arch.ptr, "dptr.%d");
+ gen_qtemp(ctx, &sptr, ctx->arch.ptr, "sptr.%d");
+ gen_qtemp(ctx, &temp, ctx->arch.ptr, "temp.%d");
+ qval_temp(ctx, &qdest, dest);
+ qval_temp(ctx, &qsrc, src);
+ constl(&offset, voidptr->size);
+
+ pushi(ctx->current, &dptr, Q_COPY, &qdest, NULL);
+ pushi(ctx->current, &sptr, Q_COPY, &qsrc, NULL);
+
+ // Data
+ pushi(ctx->current, &temp, load, &sptr, NULL);
+ pushi(ctx->current, NULL, store, &dptr, &temp, NULL);
+ // Length
+ pushi(ctx->current, &dptr, Q_ADD, &dptr, &offset, NULL);
+ pushi(ctx->current, &sptr, Q_ADD, &sptr, &offset, NULL);
+ pushi(ctx->current, &temp, load, &sptr, NULL);
+ pushi(ctx->current, NULL, store, &dptr, &temp, NULL);
+ // Capacity
+ pushi(ctx->current, &dptr, Q_ADD, &dptr, &offset, NULL);
+ pushi(ctx->current, &sptr, Q_ADD, &sptr, &offset, NULL);
+ pushi(ctx->current, &temp, load, &sptr, NULL);
+ pushi(ctx->current, NULL, store, &dptr, &temp, NULL);
+}
+
// Generates a copy operation from one gen temporary to another. For primitive
// types this is a load+store operation; for aggregate types this may emit more
// complex code or a memcpy.
@@ -239,8 +277,10 @@ gen_copy(struct gen_context *ctx,
case STORAGE_UNION:
gen_copy_memcpy(ctx, dest, src);
return;
- case STORAGE_SLICE:
case STORAGE_STRING:
+ gen_copy_string(ctx, dest, src);
+ return;
+ case STORAGE_SLICE:
case STORAGE_TAGGED:
case STORAGE_TUPLE:
assert(0); // TODO