aboutsummaryrefslogtreecommitdiff
path: root/src/sema
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-09-08 11:26:42 +0200
committerhachem <im@hachem.wtf>2026-09-08 11:26:42 +0200
commit21be45a904a0afc767214298721bd2bbce19a054 (patch)
tree4e97ae690457f82cbedd30bb8f7cf67898e578a5 /src/sema
parent8d73e3f2cdba9ce3591bab5c02e5d90ce62a8de3 (diff)
feat: add signed memory loads
Diffstat (limited to 'src/sema')
-rw-r--r--src/sema/sema.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/src/sema/sema.c b/src/sema/sema.c
index 6505077..748ccbe 100644
--- a/src/sema/sema.c
+++ b/src/sema/sema.c
@@ -103,10 +103,11 @@ static bool is_program_const(const struct Program* program, struct Token name)
return false;
}
-static struct Token first_token(struct Expr* expr)
+static struct Token first_token(const struct Expr* expr)
{
switch (expr->kind)
{
+ case EXPR_UNARY: return expr->unary.op;
case EXPR_BINARY: return first_token(expr->binary.left);
case EXPR_MEMBER: return first_token(expr->member.object);
case EXPR_DEREF: return first_token(expr->deref.address);
@@ -116,6 +117,9 @@ static struct Token first_token(struct Expr* expr)
static bool check_const_value(struct Source source, struct Program* program, struct Expr* expr)
{
+ if (expr->kind == EXPR_UNARY)
+ return check_const_value(source, program, expr->unary.operand);
+
if (expr->kind == EXPR_BINARY)
{
bool left = check_const_value(source, program, expr->binary.left);
@@ -319,9 +323,18 @@ static void check_expr(struct RefCheck* check, const struct Expr* expr)
check_expr(check, expr->binary.left);
check_expr(check, expr->binary.right);
break;
+ case EXPR_UNARY:
+ check_expr(check, expr->unary.operand);
+ break;
case EXPR_DEREF:
{
const struct Expr* address = expr->deref.address;
+ if (expr->deref.is_signed
+ && expr->deref.size != STORE_SIZE_BYTE
+ && expr->deref.size != STORE_SIZE_WORD
+ && expr->deref.size != STORE_SIZE_DWORD)
+ ref_error(check, first_token(expr), "signed load requires a byte, word, or dword size");
+
if (address->kind == EXPR_PRIMARY
&& (is_register(check, address->primary.token) || is_param(check, address->primary.token)))
break;
@@ -406,6 +419,9 @@ static void check_stack_size(struct RefCheck* check, struct Expr* expr)
check_stack_size(check, expr->binary.left);
check_stack_size(check, expr->binary.right);
break;
+ case EXPR_UNARY:
+ check_stack_size(check, expr->unary.operand);
+ break;
case EXPR_MEMBER:
{
const struct Expr* object = expr->member.object;