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:
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;
}