harec

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

commit 689bdd02034adc68233d4e93dd233ead6d508108
parent 6f6cf46d0098afac20e5cae858129f2e53d6db68
Author: Drew DeVault <sir@cmpwn.com>
Date:   Thu, 31 Dec 2020 10:37:05 -0500

gen: implement len()

Diffstat:
Msrc/check.c | 6++++--
Msrc/gen.c | 25+++++++++++++++++++++++--
2 files changed, 27 insertions(+), 4 deletions(-)

diff --git a/src/check.c b/src/check.c @@ -540,8 +540,10 @@ check_expr_measure(struct context *ctx, expr->measure.value = xcalloc(1, sizeof(struct expression)); check_expression(ctx, aexpr->measure.value, expr->measure.value); enum type_storage vstor = expr->measure.value->result->storage; - expect(vstor == TYPE_STORAGE_ARRAY || vstor == TYPE_STORAGE_SLICE, - "len argument must be of an array or slice type"); + expect(vstor == TYPE_STORAGE_ARRAY + || vstor == TYPE_STORAGE_SLICE + || vstor == TYPE_STORAGE_STRING, + "len argument must be of an array, slice, or str type"); expect(expr->measure.value->result->size != SIZE_UNDEFINED, "Cannot take length of array type with undefined length"); break; diff --git a/src/gen.c b/src/gen.c @@ -858,10 +858,31 @@ gen_expr_measure(struct gen_context *ctx, const struct expression *expr, const struct qbe_value *out) { - struct qbe_value temp = {0}; + struct qbe_value temp = {0}, ptr = {0}; switch (expr->measure.op) { case M_LEN: - assert(0); // TODO + switch (expr->measure.value->result->storage) { + case TYPE_STORAGE_ARRAY: + gen_temp(ctx, &temp, + qtype_for_type(ctx, expr->result, false), + "len.%d"); + constl(&temp, expr->measure.value->result->array.length); + gen_store(ctx, out, &temp); + break; + case TYPE_STORAGE_SLICE: + case TYPE_STORAGE_STRING: + gen_temp(ctx, &ptr, &qbe_long, "ptr.%d"); + qval_address(&ptr); + gen_expression(ctx, expr->measure.value, &ptr); + constl(&temp, builtin_type_size.size); + pushi(ctx->current, &ptr, Q_ADD, &ptr, &temp, NULL); + qval_deref(&ptr); + gen_load(ctx, out, &ptr, false); + break; + default: + assert(0); // Invariant + } + break; case M_SIZE: gen_temp(ctx, &temp, qtype_for_type(ctx, expr->result, false),