harec

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

commit 3fdebb5635f4d7e58a11ad7797dc56cae2700cb6
parent d85361a88b8ab4ae745bfa49feef1da8220bc3bd
Author: Drew DeVault <sir@cmpwn.com>
Date:   Fri,  2 Jul 2021 12:01:16 -0400

gen: implement basic access expressions

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

Diffstat:
Msrc/gen.c | 96+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 96 insertions(+), 0 deletions(-)

diff --git a/src/gen.c b/src/gen.c @@ -86,10 +86,104 @@ load_temp(struct gen_context *ctx, } } +static const struct gen_binding * +binding_lookup(struct gen_context *ctx, const struct scope_object *obj) +{ + for (struct gen_binding *binding = ctx->bindings; + binding; binding = binding->next) { + if (binding->object == obj) { + return binding; + } + } + abort(); // Invariant +} + +// Generates a copy operation from one gen temporary to another. For primitive +// types this is a load+store operation; for aggregate types this may emit more +// complex code or a memcpy. +static void +gen_copy(struct gen_context *ctx, + const struct gen_temp *dest, + const struct gen_temp *src) +{ + const struct type *dtype = type_dealias(dest->type); + switch (dtype->storage) { + case STORAGE_BOOL: + case STORAGE_CHAR: + case STORAGE_ENUM: + case STORAGE_F32: + case STORAGE_F64: + case STORAGE_I16: + case STORAGE_I32: + case STORAGE_I64: + case STORAGE_I8: + case STORAGE_INT: + case STORAGE_NULL: + case STORAGE_RUNE: + case STORAGE_SIZE: + case STORAGE_U16: + case STORAGE_U32: + case STORAGE_U64: + case STORAGE_U8: + case STORAGE_UINT: + case STORAGE_UINTPTR: + // fallthrough + break; + case STORAGE_ARRAY: + case STORAGE_FUNCTION: + case STORAGE_POINTER: + case STORAGE_SLICE: + case STORAGE_STRING: + case STORAGE_STRUCT: + case STORAGE_TAGGED: + case STORAGE_TUPLE: + case STORAGE_UNION: + assert(0); // TODO + case STORAGE_ALIAS: + case STORAGE_FCONST: + case STORAGE_ICONST: + case STORAGE_VOID: + abort(); // Invariant + } + + // Copy between types which have a native qbe representation + struct qbe_value value = {0}, dtemp = {0}; + load_temp(ctx, &value, src); + qval_temp(ctx, &dtemp, dest); + + enum qbe_instr instr = store_for_type(ctx, dtype); + pushi(ctx->current, NULL, instr, &value, &dtemp, NULL); +} + static void gen_expr(struct gen_context *ctx, const struct expression *expr, struct gen_temp *out); static void +gen_access_object(struct gen_context *ctx, + const struct scope_object *obj, + struct gen_temp *out) +{ + const struct gen_binding *binding = binding_lookup(ctx, obj); + gen_copy(ctx, out, &binding->temp); +} + +static void +gen_expr_access(struct gen_context *ctx, + const struct expression *expr, + struct gen_temp *out) +{ + switch (expr->access.type) { + case ACCESS_IDENTIFIER: + gen_access_object(ctx, expr->access.object, out); + break; + case ACCESS_INDEX: + case ACCESS_FIELD: + case ACCESS_TUPLE: + assert(0); // TODO + } +} + +static void gen_expr_binding(struct gen_context *ctx, const struct expression *expr, struct gen_temp *out) @@ -267,6 +361,8 @@ gen_expr(struct gen_context *ctx, { switch (expr->type) { case EXPR_ACCESS: + gen_expr_access(ctx, expr, out); + break; case EXPR_ALLOC: case EXPR_APPEND: case EXPR_ASSERT: