commit 625862b61dc0d9ef1cdff227c9bb0cb6b624e0cd
parent b74b70a610d9f6b226dac14cabf945cd84ef3290
Author: Drew DeVault <sir@cmpwn.com>
Date: Sat, 26 Dec 2020 14:00:05 -0500
gen: implement indexing instructions
Diffstat:
2 files changed, 40 insertions(+), 14 deletions(-)
diff --git a/src/gen.c b/src/gen.c
@@ -148,6 +148,7 @@ gen_store(struct gen_context *ctx,
const struct qbe_type *qtype = dest->type;
assert(qtype->stype != Q__VOID); // Invariant
+ assert(qtype->stype != Q__AGGREGATE); // TODO
if (dest->indirect) {
pushi(ctx->current, NULL, store_for_type(qtype->stype), src, dest, NULL);
@@ -198,23 +199,47 @@ gen_access(struct gen_context *ctx,
return;
}
- assert(expr->access.type == ACCESS_IDENTIFIER); // TODO
- const struct scope_object *obj = expr->access.object;
- struct qbe_value src = {0};
- qval_for_object(ctx, &src, obj);
+ const struct type *type;
+ struct qbe_value src = {0}, temp = {0}, offset = {0};
+ const struct scope_object *obj;
+ switch (expr->access.type) {
+ case ACCESS_IDENTIFIER:
+ obj = expr->access.object;
+ qval_for_object(ctx, &src, obj);
- struct qbe_value temp = {0};
- switch (obj->otype) {
- case O_BIND:
- gen_loadtemp(ctx, &temp, &src, src.type, type_is_signed(obj->type));
- gen_store(ctx, out, &temp);
+ switch (obj->otype) {
+ case O_BIND:
+ gen_loadtemp(ctx, &temp, &src, src.type, type_is_signed(obj->type));
+ gen_store(ctx, out, &temp);
+ break;
+ case O_DECL:
+ // Skip the extra load
+ gen_store(ctx, out, &src);
+ break;
+ }
break;
- case O_DECL:
- // Skip the extra load
- gen_store(ctx, out, &src);
+ case ACCESS_INDEX:
+ type = expr->access.array->result;
+ gen_temp(ctx, &src, &qbe_long, "source.%d"); // XXX: ARCH
+ gen_expression(ctx, expr->access.array, &src);
+
+ gen_temp(ctx, &offset, &qbe_long, "offset.%d");
+ gen_expression(ctx, expr->access.index, &offset);
+ // TODO: Check if offset is in bounds
+ constl(&temp, type->array.members->size);
+ pushi(ctx->current, &offset, Q_MUL, &offset, &temp, NULL);
+
+ pushi(ctx->current, &src, Q_ADD, &src, &offset, NULL);
+ src.type = qtype_for_type(ctx, type->array.members, false);
+ src.indirect = true;
+ gen_loadtemp(ctx, &temp, &src,
+ qtype_for_type(ctx, type->array.members, true),
+ type_is_signed(type->array.members));
+ gen_store(ctx, out, &temp);
break;
+ case ACCESS_FIELD:
+ assert(0); // TODO
}
-
}
static void
diff --git a/src/qinstr.c b/src/qinstr.c
@@ -57,8 +57,9 @@ load_for_type(enum qbe_stype stype, bool is_signed)
return Q_LOADS;
case Q_DOUBLE:
return Q_LOADD;
- case Q__VOID:
case Q__AGGREGATE:
+ return Q_COPY;
+ case Q__VOID:
assert(0); // Invariant
}
assert(0);