harec

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

commit 190a8f6185546395efbafda908d500e5c50c00d7
parent 0658179a0e430c8caeb0fc860f3af353da74cdeb
Author: Drew DeVault <sir@cmpwn.com>
Date:   Wed,  4 Aug 2021 09:49:45 +0200

gen: implement tuple value access

I also somewhat refactored check et al to remove the unnecessary "value"
sub-expression which was being stored on expression_access. I had to
delete some (probably wrong!) code from eval also, but we'll cross that
bridge later.

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

Diffstat:
Minclude/expr.h | 1-
Msrc/check.c | 8++++----
Msrc/eval.c | 18+-----------------
Msrc/gen.c | 44+++++++++++++++++++++++++++++++-------------
4 files changed, 36 insertions(+), 35 deletions(-)

diff --git a/include/expr.h b/include/expr.h @@ -60,7 +60,6 @@ struct expression_access { }; struct { struct expression *tuple; - struct expression *value; const struct type_tuple *tvalue; }; }; diff --git a/src/check.c b/src/check.c @@ -208,12 +208,12 @@ check_expr_access(struct context *ctx, break; case ACCESS_TUPLE: expr->access.tuple = xcalloc(1, sizeof(struct expression)); - expr->access.value = xcalloc(1, sizeof(struct expression)); + struct expression *value = xcalloc(1, sizeof(struct expression)); errors = check_expression(ctx, aexpr->access.tuple, expr->access.tuple, NULL, errors); errors = check_expression(ctx, aexpr->access.value, - expr->access.value, NULL, errors); - assert(expr->access.value->type == EXPR_CONSTANT); + value, NULL, errors); + assert(value->type == EXPR_CONSTANT); const struct type *ttype = type_dereference(expr->access.tuple->result); @@ -225,7 +225,7 @@ check_expr_access(struct context *ctx, return error(aexpr->access.tuple->loc, expr, errors, "Cannot select value from non-tuple object"); } - if (!type_is_integer(expr->access.value->result)) { + if (!type_is_integer(value->result)) { return error(aexpr->access.tuple->loc, expr, errors, "Cannot use non-integer constant to select tuple value"); } diff --git a/src/eval.c b/src/eval.c @@ -28,23 +28,7 @@ eval_access(struct context *ctx, struct expression *in, struct expression *out) case ACCESS_FIELD: assert(0); // TODO case ACCESS_TUPLE: - out->type = EXPR_CONSTANT; - struct expression tmp = {0}; - enum eval_result r = eval_expr(ctx, in->access.value, &tmp); - if (r != EVAL_OK) { - return r; - } - size_t i = tmp.constant.uval; - // ensure the entire tuple is known at compile time - r = eval_expr(ctx, in->access.tuple, &tmp); - if (r != EVAL_OK) { - return r; - } - const struct tuple_constant *tuple = tmp.constant.tuple; - for (; i > 0; --i) { - tuple = tuple->next; - } - return eval_expr(ctx, tuple->value, out); + assert(0); // TODO } return EVAL_OK; diff --git a/src/gen.c b/src/gen.c @@ -180,6 +180,27 @@ gen_access_ident(struct gen_context *ctx, const struct expression *expr) } static struct gen_value +gen_access_index(struct gen_context *ctx, const struct expression *expr) +{ + struct gen_value glval = gen_expr(ctx, expr->access.array); + glval = gen_autoderef(ctx, glval); + struct qbe_value qlval = mkqval(ctx, &glval); + struct qbe_value qival = mkqtmp(ctx, ctx->arch.ptr, ".%d"); + + struct gen_value index = gen_expr(ctx, expr->access.index); + struct qbe_value qindex = mkqval(ctx, &index); + struct qbe_value itemsz = constl(expr->result->size); + pushi(ctx->current, &qival, Q_MUL, &qindex, &itemsz, NULL); + pushi(ctx->current, &qival, Q_ADD, &qlval, &qival, NULL); + + return (struct gen_value){ + .kind = GV_TEMP, + .type = expr->result, + .name = qival.name, + }; +} + +static struct gen_value gen_access_field(struct gen_context *ctx, const struct expression *expr) { const struct struct_field *field = expr->access.field; @@ -197,23 +218,19 @@ gen_access_field(struct gen_context *ctx, const struct expression *expr) } static struct gen_value -gen_access_index(struct gen_context *ctx, const struct expression *expr) +gen_access_value(struct gen_context *ctx, const struct expression *expr) { - struct gen_value glval = gen_expr(ctx, expr->access.array); + const struct type_tuple *tuple = expr->access.tvalue; + struct gen_value glval = gen_expr(ctx, expr->access.tuple); glval = gen_autoderef(ctx, glval); struct qbe_value qlval = mkqval(ctx, &glval); - struct qbe_value qival = mkqtmp(ctx, ctx->arch.ptr, ".%d"); - - struct gen_value index = gen_expr(ctx, expr->access.index); - struct qbe_value qindex = mkqval(ctx, &index); - struct qbe_value itemsz = constl(expr->result->size); - pushi(ctx->current, &qival, Q_MUL, &qindex, &itemsz, NULL); - pushi(ctx->current, &qival, Q_ADD, &qlval, &qival, NULL); - + struct qbe_value qfval = mkqtmp(ctx, ctx->arch.ptr, "value.%d"); + struct qbe_value offs = constl(tuple->offset); + pushi(ctx->current, &qfval, Q_ADD, &qlval, &offs, NULL); return (struct gen_value){ .kind = GV_TEMP, - .type = expr->result, - .name = qival.name, + .type = tuple->type, + .name = qfval.name, }; } @@ -232,7 +249,8 @@ gen_expr_access_addr(struct gen_context *ctx, const struct expression *expr) addr = gen_access_field(ctx, expr); break; case ACCESS_TUPLE: - assert(0); // TODO + addr = gen_access_value(ctx, expr); + break; } return addr; }