commit 6a318a2529db284b56aeaad5beb5643fa23c7acf
parent 8a0d1c0409c7cff4ec9713bca05df7788db59745
Author: Drew DeVault <sir@cmpwn.com>
Date: Thu, 24 Dec 2020 09:49:55 -0500
gen: implement unary pointer dereference
Diffstat:
3 files changed, 69 insertions(+), 7 deletions(-)
diff --git a/src/check.c b/src/check.c
@@ -321,7 +321,10 @@ check_expr_unarithm(struct context *ctx,
&ctx->store, operand->result, 0);
break;
case UN_DEREF:
- assert(0); // TODO
+ expect(operand->result->storage == TYPE_STORAGE_POINTER,
+ "Cannot de-reference non-pointer type");
+ expr->result = operand->result->pointer.referent;
+ break;
}
trleave(TR_CHECK, NULL);
diff --git a/src/gen.c b/src/gen.c
@@ -98,6 +98,25 @@ qval_for_object(struct gen_context *ctx,
val->name = binding ? strdup(binding->name) : ident_to_sym(&obj->ident);
}
+// Given a pointer temporary, convert it to a dereferenced pointer for the given
+// secondary type
+static void
+qval_deref(struct gen_context *ctx,
+ struct qbe_value *val, const struct type *type)
+{
+ assert(val->type == &qbe_long); // Invariant // XXX: ARCH
+ val->indirect = true;
+ val->type = qtype_for_type(ctx, type, false);
+}
+
+// Given a non-pointer temporary, convert it to a pointer
+static void
+qval_address(struct qbe_value *val)
+{
+ val->type = &qbe_long; // XXX: ARCH
+ val->indirect = false;
+}
+
// Given value src of type A, and value dest of type pointer to A, store src in
// dest.
static void
@@ -178,9 +197,7 @@ gen_assign(struct gen_context *ctx,
struct qbe_value dest = {0};
gen_temp(ctx, &dest, &qbe_long, "indirect.%d"); // XXX: ARCH
gen_expression(ctx, object, &dest);
- // TODO: We might want a helper to dereference a qval
- dest.indirect = true;
- dest.type = qtype_for_type(ctx, value->result, false);
+ qval_deref(ctx, &dest, value->result);
gen_expression(ctx, value, &dest);
} else {
assert(object->type == EXPR_ACCESS); // Invariant
@@ -321,7 +338,7 @@ gen_expr_unarithm(struct gen_context *ctx,
struct qbe_value src = {0};
qval_for_object(ctx, &src, obj);
- src.type = &qbe_long; // XXX: ARCH
+ qval_address(&src);
gen_store(ctx, out, &src);
return;
}
@@ -353,7 +370,9 @@ gen_expr_unarithm(struct gen_context *ctx,
result = operand;
break;
case UN_DEREF:
- assert(0); // TODO
+ qval_deref(ctx, &operand, expr->result);
+ gen_load(ctx, &result, &operand, type_is_signed(expr->result));
+ break;
case UN_ADDRESS:
assert(0); // Invariant
}
diff --git a/src/type_store.c b/src/type_store.c
@@ -250,7 +250,47 @@ static bool
type_eq_type(struct type_store *store,
const struct type *a, const struct type *b)
{
- assert(0); // TODO
+ if (a->storage != b->storage || a->flags != b->flags) {
+ return false;
+ }
+
+ switch (a->storage) {
+ case TYPE_STORAGE_BOOL:
+ case TYPE_STORAGE_CHAR:
+ case TYPE_STORAGE_F32:
+ case TYPE_STORAGE_F64:
+ case TYPE_STORAGE_I8:
+ case TYPE_STORAGE_I16:
+ case TYPE_STORAGE_I32:
+ case TYPE_STORAGE_I64:
+ case TYPE_STORAGE_INT:
+ case TYPE_STORAGE_RUNE:
+ case TYPE_STORAGE_SIZE:
+ case TYPE_STORAGE_U8:
+ case TYPE_STORAGE_U16:
+ case TYPE_STORAGE_U32:
+ case TYPE_STORAGE_U64:
+ case TYPE_STORAGE_UINT:
+ case TYPE_STORAGE_UINTPTR:
+ case TYPE_STORAGE_VOID:
+ return true;
+ case TYPE_STORAGE_ALIAS:
+ case TYPE_STORAGE_ARRAY:
+ case TYPE_STORAGE_ENUM:
+ case TYPE_STORAGE_FUNCTION:
+ assert(0); // TODO
+ case TYPE_STORAGE_POINTER:
+ return a->pointer.flags == b->pointer.flags &&
+ type_eq_type(store, a->pointer.referent, b->pointer.referent);
+ case TYPE_STORAGE_SLICE:
+ case TYPE_STORAGE_STRING:
+ case TYPE_STORAGE_STRUCT:
+ case TYPE_STORAGE_TAGGED_UNION:
+ case TYPE_STORAGE_UNION:
+ assert(0); // TODO
+ }
+
+ assert(0); // Unreachable
}
static void