harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 6f93e47f3a09ac8e9b06f441c831c7a4b9bdf62a
parent 8f9d7c1bb2e85da1fae80ccd06d98c69fb3c35ac
Author: Drew DeVault <sir@cmpwn.com>
Date:   Fri, 13 Aug 2021 08:47:06 +0200

gen: initial implementation of insert

Signed-off-by: Drew DeVault <sir@cmpwn.com>

Diffstat:
Msrc/gen.c | 75++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 74 insertions(+), 1 deletion(-)

diff --git a/src/gen.c b/src/gen.c @@ -497,6 +497,7 @@ gen_expr_append(struct gen_context *ctx, const struct expression *expr) { struct gen_value slice = gen_expr(ctx, expr->append.expr); struct qbe_value qslice = mkqval(ctx, &slice); + // TODO: Automatic dereference here struct qbe_value ptr = mkqtmp(ctx, ctx->arch.ptr, ".%d"); struct qbe_value offs = constl(builtin_type_size.size); @@ -1569,6 +1570,78 @@ gen_expr_if_with(struct gen_context *ctx, } static struct gen_value +gen_expr_insert(struct gen_context *ctx, const struct expression *expr) +{ + const struct expression *objexpr = expr->insert.expr; + assert(objexpr->type == EXPR_ACCESS + && objexpr->access.type == ACCESS_INDEX); + + const struct expression *arrayexpr = objexpr->access.array; + struct gen_value slice = gen_expr_access_addr(ctx, arrayexpr); + struct gen_value index = gen_expr(ctx, objexpr->access.index); + struct qbe_value qindex = mkqval(ctx, &index); + + const struct type *sltype = type_dealias(arrayexpr->result); + const struct type *mtype = type_dealias(sltype)->array.members; + + enum qbe_instr load = load_for_type(ctx, &builtin_type_size); + struct qbe_value qslice = mklval(ctx, &slice); + struct qbe_value offs = constl(builtin_type_size.size); + struct qbe_value lenptr = mkqtmp(ctx, ctx->arch.ptr, ".%d"); + pushi(ctx->current, &lenptr, Q_ADD, &qslice, &offs, NULL); + struct qbe_value len = mkqtmp(ctx, ctx->arch.sz, ".%d"); + pushi(ctx->current, &len, load, &lenptr, NULL); + + size_t args = 0; + for (struct append_values *value = expr->insert.values; + value; value = value->next) { + args++; + } + struct qbe_value nadd = constl(args); + struct qbe_value newlen = mkqtmp(ctx, ctx->arch.sz, ".%d"); + pushi(ctx->current, &newlen, Q_ADD, &len, &nadd, NULL); + + assert(!expr->insert.variadic); // TODO + + enum qbe_instr store = store_for_type(ctx, &builtin_type_size); + pushi(ctx->current, NULL, store, &newlen, &lenptr, NULL); + + assert(!expr->append.is_static); // TODO + + struct qbe_value rtfunc = mkrtfunc(ctx, "rt.ensure"); + struct qbe_value lval = mklval(ctx, &slice); + struct qbe_value membsz = constl(mtype->size); + pushi(ctx->current, NULL, Q_CALL, &rtfunc, &lval, &membsz, NULL); + + struct qbe_value base = mkqtmp(ctx, ctx->arch.ptr, ".%d"); + pushi(ctx->current, &base, load, &qslice, NULL); + + struct qbe_value src = mkqtmp(ctx, ctx->arch.ptr, ".%d"); + pushi(ctx->current, &src, Q_MUL, &qindex, &membsz, NULL); + pushi(ctx->current, &src, Q_ADD, &base, &membsz, 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, &dest, Q_ADD, &src, &nbyte, NULL); + + rtfunc = mkrtfunc(ctx, "rt.memmove"); + pushi(ctx->current, NULL, Q_CALL, &rtfunc, &dest, &src, &nbyte, NULL); + + struct gen_value gv = { + .kind = GV_TEMP, + .type = mtype, + .name = src.name, + }; + for (struct append_values *value = expr->insert.values; + value; value = value->next) { + gen_expr_at(ctx, value->expr, gv); + pushi(ctx->current, &src, Q_ADD, &src, &membsz, NULL); + } + + return gv_void; +} + +static struct gen_value gen_expr_list_with(struct gen_context *ctx, const struct expression *expr, struct gen_value *out) @@ -2281,7 +2354,7 @@ gen_expr(struct gen_context *ctx, const struct expression *expr) case EXPR_IF: return gen_expr_if_with(ctx, expr, NULL); case EXPR_INSERT: - assert(0); // TODO + return gen_expr_insert(ctx, expr); case EXPR_LIST: return gen_expr_list_with(ctx, expr, NULL); case EXPR_MATCH: