From 21be45a904a0afc767214298721bd2bbce19a054 Mon Sep 17 00:00:00 2001 From: hachem Date: Tue, 8 Sep 2026 11:26:42 +0200 Subject: feat: add signed memory loads --- src/codegen/nasm.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 2 deletions(-) (limited to 'src/codegen/nasm.c') diff --git a/src/codegen/nasm.c b/src/codegen/nasm.c index 8bcdda3..198cb5c 100644 --- a/src/codegen/nasm.c +++ b/src/codegen/nasm.c @@ -14,6 +14,10 @@ static void emit_const_expr(struct Expr* expr, FILE* out) case EXPR_PRIMARY: fprintf(out, "%.*s", (int)expr->primary.token.length, expr->primary.token.start); break; + case EXPR_UNARY: + fprintf(out, "%.*s", (int)expr->unary.op.length, expr->unary.op.start); + emit_const_expr(expr->unary.operand, out); + break; case EXPR_BINARY: emit_const_expr(expr->binary.left, out); fprintf(out, " %.*s ", (int)expr->binary.op.length, expr->binary.op.start); @@ -370,6 +374,14 @@ static bool fold_const(struct Program* program, struct Expr* expr, uint64_t* out return fold_const(program, program->consts[i].value, out); return false; } + case EXPR_UNARY: + { + uint64_t value; + if (!fold_const(program, expr->unary.operand, &value)) + return false; + *out = 0 - value; + return true; + } case EXPR_BINARY: { uint64_t left; @@ -470,6 +482,14 @@ static bool emit_operand(struct Emitter* emitter, struct Expr* expr) fprintf(emitter->out, ".%.*s", (int)expr->member.member.length, expr->member.member.start); return true; } + case EXPR_UNARY: + { + uint64_t value; + if (!fold_const(emitter->program, expr, &value)) + return false; + fprintf(emitter->out, "%lld", (long long)value); + return true; + } case EXPR_BINARY: case EXPR_DEREF: return false; @@ -536,10 +556,22 @@ static bool expr_supported(struct Emitter* emitter, struct Expr* expr) case EXPR_MEMBER: case EXPR_DEREF: return true; + case EXPR_UNARY: + { + uint64_t value; + return fold_const(emitter->program, expr, &value); + } case EXPR_BINARY: if (expr->binary.right->kind != EXPR_PRIMARY && - expr->binary.right->kind != EXPR_MEMBER) + expr->binary.right->kind != EXPR_MEMBER && + expr->binary.right->kind != EXPR_UNARY) return false; + if (expr->binary.right->kind == EXPR_UNARY) + { + uint64_t value; + if (!fold_const(emitter->program, expr->binary.right, &value)) + return false; + } if (expr->binary.right->kind == EXPR_PRIMARY && is_buffer_name(emitter, expr->binary.right->primary.token)) return false; @@ -549,10 +581,35 @@ static bool expr_supported(struct Emitter* emitter, struct Expr* expr) return false; } -// dst = [address], zero-extending narrower loads into the full register +// dst = [address], extending narrower loads into the full register. Unsigned +// loads zero-extend (movzx / a 32-bit mov); signed loads sign-extend (movsx, +// or movsxd for a dword). static void emit_load(struct Emitter* emitter, const char* dst, struct DerefExpr* deref) { FILE* out = emitter->out; + if (deref->is_signed) + { + switch (deref->size) + { + case STORE_SIZE_BYTE: + fprintf(out, "\tmovsx %s, byte [", dst); + break; + case STORE_SIZE_WORD: + fprintf(out, "\tmovsx %s, word [", dst); + break; + case STORE_SIZE_DWORD: + fprintf(out, "\tmovsxd %s, dword [", dst); + break; + default: + fprintf(out, "\tmov %s, [", dst); + break; + } + + emit_operand(emitter, deref->address); + fprintf(out, "]\n"); + return; + } + switch (deref->size) { case STORE_SIZE_BYTE: @@ -1073,6 +1130,9 @@ static void collect_floats_expr(struct FloatTable* floats, struct Expr* expr) case EXPR_PRIMARY: collect_float(floats, expr->primary.token); break; + case EXPR_UNARY: + collect_floats_expr(floats, expr->unary.operand); + break; case EXPR_BINARY: collect_floats_expr(floats, expr->binary.left); collect_floats_expr(floats, expr->binary.right); -- cgit v1.3