commit 1bf83d7925fd22fb45c9012b80873e5f8ea57c8c
parent 411297c121980d3df1d85596358014158aae6a66
Author: Drew DeVault <sir@cmpwn.com>
Date: Thu, 24 Dec 2020 09:22:48 -0500
check, gen: implement unary address
Diffstat:
4 files changed, 88 insertions(+), 6 deletions(-)
diff --git a/include/type_store.h b/include/type_store.h
@@ -26,4 +26,7 @@ const struct type *builtin_type_for_storage(
const struct type *type_store_lookup_with_flags(struct type_store *store,
const struct type *type, unsigned int flags);
+const struct type *type_store_lookup_pointer(struct type_store *store,
+ const struct type *referent, unsigned int ptrflags);
+
#endif
diff --git a/src/check.c b/src/check.c
@@ -312,6 +312,9 @@ check_expr_unarithm(struct context *ctx,
expr->result = operand->result;
break;
case UN_ADDRESS:
+ expr->result = type_store_lookup_pointer(
+ &ctx->store, operand->result, 0);
+ break;
case UN_DEREF:
assert(0); // TODO
}
diff --git a/src/gen.c b/src/gen.c
@@ -93,6 +93,7 @@ qval_for_object(struct gen_context *ctx,
{
const struct gen_binding *binding = binding_lookup(ctx, obj);
val->kind = QV_TEMPORARY; // XXX: Is this always the case?
+ val->indirect = true; // XXX: Is this always the case?
val->type = qtype_for_type(ctx, obj->type, false);
val->name = binding ? strdup(binding->name) : ident_to_sym(&obj->ident);
}
@@ -109,7 +110,6 @@ gen_store(struct gen_context *ctx,
assert(qtype->stype != Q__AGGREGATE); // TODO
if (dest->indirect) {
- assert(!src->indirect); // XXX: Correct?
pushi(ctx->current, NULL, store_for_type(qtype->stype), src, dest, NULL);
} else {
pushi(ctx->current, dest, Q_COPY, src, NULL);
@@ -154,6 +154,7 @@ 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;
qval_for_object(ctx, &src, obj);
@@ -303,6 +304,18 @@ gen_expr_unarithm(struct gen_context *ctx,
const struct qbe_type *otype =
qtype_for_type(ctx, expr->unarithm.operand->result, false);
const struct qbe_type *rtype = qtype_for_type(ctx, expr->result, false);
+ if (expr->unarithm.op == UN_ADDRESS) { // Special case
+ const struct expression *operand = expr->unarithm.operand;
+ assert(operand->type == EXPR_ACCESS); // Invariant
+ assert(operand->access.type == ACCESS_IDENTIFIER); // TODO
+ const struct scope_object *obj = operand->access.object;
+
+ struct qbe_value src = {0};
+ qval_for_object(ctx, &src, obj);
+ src.type = &qbe_long; // XXX: ARCH
+ gen_store(ctx, out, &src);
+ return;
+ }
struct qbe_value operand = {0}, result = {0};
gen_temp(ctx, &operand, otype, "operand.%d");
@@ -330,9 +343,10 @@ gen_expr_unarithm(struct gen_context *ctx,
// no-op
result = operand;
break;
- case UN_ADDRESS:
case UN_DEREF:
assert(0); // TODO
+ case UN_ADDRESS:
+ assert(0); // Invariant
}
gen_store(ctx, out, &result);
@@ -444,7 +458,6 @@ gen_function_decl(struct gen_context *ctx, const struct declaration *decl)
// TODO: Update for void type
struct qbe_value rval;
alloc_temp(ctx, &rval, fntype->func.result, "ret.%d");
- rval.indirect = true;
ctx->return_value = &rval;
pushl(&qdef->func, &ctx->id, "body.%d");
diff --git a/src/type_store.c b/src/type_store.c
@@ -98,7 +98,11 @@ atype_hash(struct type_store *store, const struct ast_type *type)
}
break;
case TYPE_STORAGE_ENUM:
+ assert(0); // TODO
case TYPE_STORAGE_POINTER:
+ hash = djb2(hash, type->pointer.flags);
+ hash = atype_hash(store, type->pointer.referent);
+ break;
case TYPE_STORAGE_SLICE:
case TYPE_STORAGE_STRING:
case TYPE_STORAGE_STRUCT:
@@ -147,7 +151,11 @@ type_hash(struct type_store *store, const struct type *type)
}
break;
case TYPE_STORAGE_ENUM:
+ assert(0); // TODO
case TYPE_STORAGE_POINTER:
+ hash = djb2(hash, type->pointer.flags);
+ hash = type_hash(store, type->pointer.referent);
+ break;
case TYPE_STORAGE_SLICE:
case TYPE_STORAGE_STRING:
case TYPE_STORAGE_STRUCT:
@@ -298,12 +306,53 @@ type_init_from_atype(struct type_store *store,
}
}
+static const struct type *type_store_lookup_type(
+ struct type_store *store, const struct type *type);
+
static void
type_init_from_type(struct type_store *store,
- struct type *type,
- const struct type *atype)
+ struct type *new, const struct type *old)
{
- assert(0); // TODO
+ new->storage = old->storage;
+ new->flags = old->flags;
+
+ switch (old->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:
+ assert(0); // Invariant
+ case TYPE_STORAGE_ALIAS:
+ case TYPE_STORAGE_ARRAY:
+ case TYPE_STORAGE_ENUM:
+ case TYPE_STORAGE_FUNCTION:
+ assert(0); // TODO
+ case TYPE_STORAGE_POINTER:
+ new->pointer.flags = old->pointer.flags;
+ new->pointer.referent = type_store_lookup_type(
+ store, old->pointer.referent);
+ break;
+ case TYPE_STORAGE_SLICE:
+ case TYPE_STORAGE_STRING:
+ case TYPE_STORAGE_STRUCT:
+ case TYPE_STORAGE_TAGGED_UNION:
+ case TYPE_STORAGE_UNION:
+ assert(0); // TODO
+ }
}
const struct type *
@@ -368,3 +417,17 @@ type_store_lookup_with_flags(struct type_store *store,
new.flags |= flags;
return type_store_lookup_type(store, &new);
}
+
+const struct type *
+type_store_lookup_pointer(struct type_store *store,
+ const struct type *referent, unsigned int ptrflags)
+{
+ struct type ptr = {
+ .storage = TYPE_STORAGE_POINTER,
+ .pointer = {
+ .referent = referent,
+ .flags = ptrflags,
+ },
+ };
+ return type_store_lookup_type(store, &ptr);
+}