harec

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

commit 8b3e46abf8c26b103175dd60d7236b8b393cf661
parent f40b930cd99c4a3d3e0bf2b1acff79939519f8da
Author: Alexey Yerin <yyp@disroot.org>
Date:   Mon,  9 Aug 2021 10:49:50 +0300

gen: implement bounds check for indexing expression

Signed-off-by: Alexey Yerin <yyp@disroot.org>

Diffstat:
Msrc/gen.c | 36++++++++++++++++++++++++++++++++----
1 file changed, 32 insertions(+), 4 deletions(-)

diff --git a/src/gen.c b/src/gen.c @@ -240,11 +240,29 @@ gen_access_index(struct gen_context *ctx, const struct expression *expr) glval = gen_autoderef(ctx, glval); struct qbe_value qlval = mkqval(ctx, &glval); struct qbe_value qival = mkqtmp(ctx, ctx->arch.ptr, ".%d"); - if (type_dealias(glval.type)->storage == STORAGE_SLICE) { + struct qbe_value length; + const struct type *ty = type_dealias(glval.type); + switch (ty->storage) { + case STORAGE_SLICE: { enum qbe_instr load = load_for_type(ctx, &builtin_type_size); + struct qbe_value base = mkqtmp(ctx, ctx->arch.ptr, ".%d"); + pushi(ctx->current, &base, load, &qlval, NULL); + struct qbe_value temp = mkqtmp(ctx, ctx->arch.ptr, ".%d"); - pushi(ctx->current, &temp, load, &qlval, NULL); - qlval = temp; + length = mkqtmp(ctx, ctx->arch.sz, "len.%d"); + struct qbe_value offset = constl(builtin_type_size.size); + pushi(ctx->current, &temp, Q_ADD, &qlval, &offset, NULL); + pushi(ctx->current, &length, load, &temp, NULL); + + qlval = base; + break; + } + case STORAGE_ARRAY: + assert(ty->array.length != SIZE_UNDEFINED); + length = constl(ty->array.length); + break; + default: + assert(0); // Unreachable } struct gen_value index = gen_expr(ctx, expr->access.index); @@ -253,7 +271,17 @@ gen_access_index(struct gen_context *ctx, const struct expression *expr) pushi(ctx->current, &qival, Q_MUL, &qindex, &itemsz, NULL); pushi(ctx->current, &qival, Q_ADD, &qlval, &qival, NULL); - // TODO: Check bounds + struct qbe_value valid = mkqtmp(ctx, &qbe_word, ".%d"); + pushi(ctx->current, &valid, Q_CULTL, &qindex, &length, NULL); + + struct qbe_statement linvalid, lvalid; + struct qbe_value binvalid = mklabel(ctx, &linvalid, ".%d"); + struct qbe_value bvalid = mklabel(ctx, &lvalid, ".%d"); + + pushi(ctx->current, NULL, Q_JNZ, &valid, &bvalid, &binvalid, NULL); + push(&ctx->current->body, &linvalid); + gen_fixed_abort(ctx, expr->loc, ABORT_OOB); + push(&ctx->current->body, &lvalid); return (struct gen_value){ .kind = GV_TEMP,