From 56ba8b2a373dd1386950592bda9c68ff9f25c203 Mon Sep 17 00:00:00 2001 From: hachem Date: Thu, 3 Sep 2026 03:36:06 +0200 Subject: fix: i JUST started using a static analyzer for ts --- src/codegen/nasm.c | 44 +++++++++++++++++++++++++++++++++----------- src/lexer/lexer.c | 5 ++++- src/lexer/lexer.h | 2 ++ src/parser/ast.c | 18 +++--------------- src/parser/parser.c | 25 +++++++++++++++++-------- src/sema/sema.c | 26 ++++++++++++++------------ 6 files changed, 73 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/codegen/nasm.c b/src/codegen/nasm.c index 31bcee0..6df22a4 100644 --- a/src/codegen/nasm.c +++ b/src/codegen/nasm.c @@ -93,7 +93,7 @@ static bool is_float_register(struct Token token) return true; } -static size_t float_index(struct FloatTable* floats, struct Token literal) +static size_t float_index(const struct FloatTable* floats, struct Token literal) { for (size_t i = 0; i < floats->count; i += 1) if (floats->items[i].length == literal.length @@ -310,7 +310,7 @@ static bool fold_member(struct Program* program, struct Expr* object, struct Tok return false; struct Token name = object->primary.token; - struct EnumDecl* enumeration = find_enum(program, name); + const struct EnumDecl* enumeration = find_enum(program, name); if (enumeration != NULL) { for (size_t i = 0; i < enumeration->member_count; i += 1) @@ -322,7 +322,7 @@ static bool fold_member(struct Program* program, struct Expr* object, struct Tok return false; } - struct StructDecl* layout = find_struct(program, name); + const struct StructDecl* layout = find_struct(program, name); if (layout != NULL) { uint64_t offset = 0; @@ -400,7 +400,7 @@ static bool fold_const(struct Program* program, struct Expr* expr, uint64_t* out // offset (or the total size for `.size`) static bool emit_named_member(struct Emitter* emitter, struct Token object, struct Token member) { - struct EnumDecl* enumeration = find_enum(emitter->program, object); + const struct EnumDecl* enumeration = find_enum(emitter->program, object); if (enumeration != NULL) { for (size_t i = 0; i < enumeration->member_count; i += 1) @@ -411,7 +411,7 @@ static bool emit_named_member(struct Emitter* emitter, struct Token object, stru } } - struct StructDecl* layout = find_struct(emitter->program, object); + const struct StructDecl* layout = find_struct(emitter->program, object); if (layout != NULL) { uint64_t offset = 0; @@ -494,6 +494,19 @@ static void emit_division(struct Emitter* emitter, const char* dst, struct Expr* fprintf(emitter->out, "\tmov %s, rax\n", dst); } +// idiv leaves the remainder in rdx, so a modulo takes its result from there +static void emit_modulo(struct Emitter* emitter, const char* dst, struct Expr* divisor) +{ + if (strcmp(dst, "rax") != 0) + fprintf(emitter->out, "\tmov rax, %s\n", dst); + fprintf(emitter->out, "\tcqo\n"); + fprintf(emitter->out, "\tidiv "); + emit_operand(emitter, divisor); + fprintf(emitter->out, "\n"); + if (strcmp(dst, "rdx") != 0) + fprintf(emitter->out, "\tmov %s, rdx\n", dst); +} + static void emit_divide(struct Emitter* emitter, struct AssignStatement* assign) { if (assign->target_deref) @@ -505,7 +518,11 @@ static void emit_divide(struct Emitter* emitter, struct AssignStatement* assign) struct Token target = resolve_register(emitter, assign->target); char dst[32]; snprintf(dst, sizeof(dst), "%.*s", (int)target.length, target.start); - emit_division(emitter, dst, assign->value); + + if (assign->op.type == TOKEN_PERCENT_EQUAL) + emit_modulo(emitter, dst, assign->value); + else + emit_division(emitter, dst, assign->value); } // an expression can be evaluated into a register when it is a single term @@ -576,6 +593,11 @@ static void emit_expr_into(struct Emitter* emitter, const char* dst, struct Expr emit_division(emitter, dst, expr->binary.right); return; } + if (expr->binary.op.type == TOKEN_PERCENT) + { + emit_modulo(emitter, dst, expr->binary.right); + return; + } const char* mnemonic = expr->binary.op.type == TOKEN_PLUS ? "add" : @@ -677,7 +699,7 @@ static const char* float_mnemonic(enum TokenType op) } } -static bool value_is_float(struct Emitter* emitter, struct Expr* expr) +static bool value_is_float(struct Emitter* emitter, const struct Expr* expr) { if (expr->kind != EXPR_PRIMARY) return false; @@ -766,7 +788,7 @@ static void emit_assign(struct Emitter* emitter, struct AssignStatement* assign) return; } - if (assign->op.type == TOKEN_SLASH_EQUAL) + if (assign->op.type == TOKEN_SLASH_EQUAL || assign->op.type == TOKEN_PERCENT_EQUAL) { emit_divide(emitter, assign); return; @@ -860,7 +882,7 @@ static struct ProcDecl* find_proc(struct Program* program, struct Token name) static void emit_call(struct Emitter* emitter, struct CallStatement* call) { - struct ProcDecl* callee = find_proc(emitter->program, call->name); + const struct ProcDecl* callee = find_proc(emitter->program, call->name); if (callee == NULL || callee->param_count != call->arg_count) { fprintf(emitter->out, "\t; TODO: unsupported call\n"); @@ -902,7 +924,7 @@ static const char* float_jump_if_false(enum TokenType comparison) } } -static void emit_float_operand(struct Emitter* emitter, struct Expr* expr) +static void emit_float_operand(struct Emitter* emitter, const struct Expr* expr) { if (expr->kind == EXPR_PRIMARY && expr->primary.token.type == TOKEN_FLOAT) { @@ -1082,7 +1104,7 @@ static struct FloatTable collect_floats(struct Program* program) return floats; } -static void emit_float_data(struct FloatTable* floats, FILE* out) +static void emit_float_data(const struct FloatTable* floats, FILE* out) { for (size_t i = 0; i < floats->count; i += 1) fprintf(out, "__float%zu: dq %.*s\n", i, diff --git a/src/lexer/lexer.c b/src/lexer/lexer.c index b4fb7d7..01bbd41 100644 --- a/src/lexer/lexer.c +++ b/src/lexer/lexer.c @@ -114,7 +114,7 @@ static void skip_whitespace(struct Lexer* lexer) } } -static struct Token make_token(struct Lexer* lexer, enum TokenType type, const char* start) +static struct Token make_token(const struct Lexer* lexer, enum TokenType type, const char* start) { struct Token token; token.type = type; @@ -231,6 +231,7 @@ struct Token scan_token(struct Lexer* lexer) case '-': return make_token(lexer, match(lexer, '=') ? TOKEN_MINUS_EQUAL : TOKEN_MINUS, start); case '*': return make_token(lexer, match(lexer, '=') ? TOKEN_STAR_EQUAL : TOKEN_STAR, start); case '/': return make_token(lexer, match(lexer, '=') ? TOKEN_SLASH_EQUAL : TOKEN_SLASH, start); + case '%': return make_token(lexer, match(lexer, '=') ? TOKEN_PERCENT_EQUAL : TOKEN_PERCENT, start); case '^': return make_token(lexer, TOKEN_CARET, start); case '.': return make_token(lexer, TOKEN_DOT, start); @@ -275,6 +276,7 @@ const char* token_type_name(enum TokenType type) case TOKEN_MINUS: return "minus"; case TOKEN_STAR: return "star"; case TOKEN_SLASH: return "slash"; + case TOKEN_PERCENT: return "percent"; case TOKEN_CARET: return "caret"; case TOKEN_BANG: return "bang"; case TOKEN_LESS: return "less"; @@ -294,6 +296,7 @@ const char* token_type_name(enum TokenType type) case TOKEN_MINUS_EQUAL: return "minus_equal"; case TOKEN_STAR_EQUAL: return "star_equal"; case TOKEN_SLASH_EQUAL: return "slash_equal"; + case TOKEN_PERCENT_EQUAL: return "percent_equal"; case TOKEN_LESS_EQUAL: return "less_equal"; case TOKEN_GREATER_EQUAL: return "greater_equal"; case TOKEN_UNKNOWN: return "unknown"; diff --git a/src/lexer/lexer.h b/src/lexer/lexer.h index 5c1e868..45e9b3d 100644 --- a/src/lexer/lexer.h +++ b/src/lexer/lexer.h @@ -31,6 +31,7 @@ enum TokenType TOKEN_MINUS, TOKEN_STAR, TOKEN_SLASH, + TOKEN_PERCENT, TOKEN_CARET, TOKEN_BANG, TOKEN_LESS, @@ -51,6 +52,7 @@ enum TokenType TOKEN_MINUS_EQUAL, TOKEN_STAR_EQUAL, TOKEN_SLASH_EQUAL, + TOKEN_PERCENT_EQUAL, TOKEN_LESS_EQUAL, TOKEN_GREATER_EQUAL, diff --git a/src/parser/ast.c b/src/parser/ast.c index 788341b..a387533 100644 --- a/src/parser/ast.c +++ b/src/parser/ast.c @@ -150,10 +150,7 @@ void add_data(struct Program* program, struct DataDecl decl) struct EnumDecl create_enum(void) { - struct EnumDecl decl; - decl.members = NULL; - decl.member_count = 0; - decl.member_capacity = 0; + struct EnumDecl decl = { 0 }; return decl; } @@ -185,10 +182,7 @@ void add_enum(struct Program* program, struct EnumDecl decl) struct StructDecl create_struct(void) { - struct StructDecl decl; - decl.fields = NULL; - decl.field_count = 0; - decl.field_capacity = 0; + struct StructDecl decl = { 0 }; return decl; } @@ -220,13 +214,7 @@ void add_struct(struct Program* program, struct StructDecl decl) struct ProcDecl create_proc(void) { - struct ProcDecl proc; - proc.params = NULL; - proc.param_count = 0; - proc.param_capacity = 0; - proc.body = NULL; - proc.body_count = 0; - proc.body_capacity = 0; + struct ProcDecl proc = { 0 }; return proc; } diff --git a/src/parser/parser.c b/src/parser/parser.c index 3ed9fff..a83c3c4 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -209,13 +209,15 @@ static bool is_assign_op(enum TokenType type) || type == TOKEN_PLUS_EQUAL || type == TOKEN_MINUS_EQUAL || type == TOKEN_STAR_EQUAL - || type == TOKEN_SLASH_EQUAL; + || type == TOKEN_SLASH_EQUAL + || type == TOKEN_PERCENT_EQUAL; } static struct Expr* alloc_expr(enum ExprKind kind) { struct Expr* expr = malloc(sizeof(struct Expr)); - expr->kind = kind; + if (expr != NULL) + expr->kind = kind; return expr; } @@ -289,13 +291,14 @@ static struct Expr* parse_postfix(struct Parser* parser) return expr; } -static struct Expr* parse_binary(struct Parser* parser, struct Expr* (*operand)(struct Parser*), enum TokenType a, enum TokenType b) +static struct Expr* parse_binary(struct Parser* parser, struct Expr* (*operand)(struct Parser*), + enum TokenType a, enum TokenType b, enum TokenType c) { struct Expr* left = operand(parser); if (left == NULL) return NULL; - while (check(parser, a) || check(parser, b)) + while (check(parser, a) || check(parser, b) || check(parser, c)) { advance_parser(parser); struct Token op = parser->previous; @@ -319,12 +322,12 @@ static struct Expr* parse_binary(struct Parser* parser, struct Expr* (*operand)( static struct Expr* parse_multiplicative(struct Parser* parser) { - return parse_binary(parser, parse_postfix, TOKEN_STAR, TOKEN_SLASH); + return parse_binary(parser, parse_postfix, TOKEN_STAR, TOKEN_SLASH, TOKEN_PERCENT); } static struct Expr* parse_expression(struct Parser* parser) { - return parse_binary(parser, parse_multiplicative, TOKEN_PLUS, TOKEN_MINUS); + return parse_binary(parser, parse_multiplicative, TOKEN_PLUS, TOKEN_MINUS, TOKEN_MINUS); } static bool is_compare_op(enum TokenType type) @@ -354,7 +357,13 @@ static bool parse_call(struct Parser* parser, struct Token name, struct Statemen if (count == capacity) { capacity = capacity < 4 ? 4 : capacity * 2; - args = realloc(args, capacity * sizeof(struct Expr*)); + struct Expr** grown = realloc(args, capacity * sizeof(struct Expr*)); + if (grown == NULL) + { + free_expr(arg); + goto error; + } + args = grown; } args[count] = arg; count += 1; @@ -614,7 +623,7 @@ static bool parse_directive(struct Parser* parser, struct Program* program) bool parse_program(struct Lexer* lexer, struct Program* out) { - struct Parser parser; + struct Parser parser = { 0 }; parser.lexer = lexer; parser.source.name = lexer->name; parser.source.text = lexer->source; diff --git a/src/sema/sema.c b/src/sema/sema.c index 12fd53f..4b4bc26 100644 --- a/src/sema/sema.c +++ b/src/sema/sema.c @@ -33,6 +33,8 @@ static bool check_duplicate_names(struct Source source, struct Program* program) return true; struct Token* names = malloc(count * sizeof(struct Token)); + if (names == NULL) + return true; size_t n = 0; for (size_t i = 0; i < program->const_count; i += 1) { @@ -92,7 +94,7 @@ static bool check_entry_point(struct Source source, struct Program* program) return false; } -static bool is_program_const(struct Program* program, struct Token name) +static bool is_program_const(const struct Program* program, struct Token name) { for (size_t i = 0; i < program->const_count; i += 1) if (names_equal(program->consts[i].name, name)) @@ -227,7 +229,7 @@ static bool is_register(struct RefCheck* check, struct Token token) return check->program->config.logical_registers && is_logical_register(token); } -static bool is_param(struct RefCheck* check, struct Token token) +static bool is_param(const struct RefCheck* check, struct Token token) { for (size_t i = 0; i < check->proc->param_count; i += 1) if (names_equal(check->proc->params[i].name, token)) @@ -236,7 +238,7 @@ static bool is_param(struct RefCheck* check, struct Token token) return false; } -static bool is_const(struct RefCheck* check, struct Token token) +static bool is_const(const struct RefCheck* check, struct Token token) { for (size_t i = 0; i < check->program->const_count; i += 1) if (names_equal(check->program->consts[i].name, token)) @@ -245,7 +247,7 @@ static bool is_const(struct RefCheck* check, struct Token token) return false; } -static bool is_data(struct RefCheck* check, struct Token token) +static bool is_data(const struct RefCheck* check, struct Token token) { for (size_t i = 0; i < check->program->data_count; i += 1) if (names_equal(check->program->data_decls[i].name, token)) @@ -276,7 +278,7 @@ static bool is_stack_buffer(struct RefCheck* check, struct Token token) { for (size_t i = 0; i < check->proc->body_count; i += 1) { - struct Statement* statement = &check->proc->body[i]; + const struct Statement* statement = &check->proc->body[i]; if (statement->kind == STATEMENT_STACK && names_equal(statement->stack.name, token)) return true; } @@ -288,7 +290,7 @@ static bool is_label(struct RefCheck* check, struct Token token) { for (size_t i = 0; i < check->proc->body_count; i += 1) { - struct Statement* statement = &check->proc->body[i]; + const struct Statement* statement = &check->proc->body[i]; if (statement->kind == STATEMENT_LABEL && names_equal(statement->label.name, token)) return true; } @@ -305,7 +307,7 @@ static void check_value_name(struct RefCheck* check, struct Token name) ref_error(check, name, "undefined name '%.*s'", (int)name.length, name.start); } -static void check_expr(struct RefCheck* check, struct Expr* expr) +static void check_expr(struct RefCheck* check, const struct Expr* expr) { switch (expr->kind) { @@ -319,7 +321,7 @@ static void check_expr(struct RefCheck* check, struct Expr* expr) break; case EXPR_DEREF: { - struct Expr* address = expr->deref.address; + const struct Expr* address = expr->deref.address; if (address->kind == EXPR_PRIMARY && (is_register(check, address->primary.token) || is_param(check, address->primary.token))) break; @@ -332,7 +334,7 @@ static void check_expr(struct RefCheck* check, struct Expr* expr) } case EXPR_MEMBER: { - struct Expr* object = expr->member.object; + const struct Expr* object = expr->member.object; struct Token member = expr->member.member; if (member.type == TOKEN_INTEGER) @@ -344,7 +346,7 @@ static void check_expr(struct RefCheck* check, struct Expr* expr) if (object->kind == EXPR_PRIMARY) { - struct EnumDecl* enumeration = find_enum(check, object->primary.token); + const struct EnumDecl* enumeration = find_enum(check, object->primary.token); if (enumeration != NULL) { bool found = false; @@ -358,7 +360,7 @@ static void check_expr(struct RefCheck* check, struct Expr* expr) break; } - struct StructDecl* layout = find_struct(check, object->primary.token); + const struct StructDecl* layout = find_struct(check, object->primary.token); if (layout != NULL) { bool found = token_is(member, "size"); @@ -406,7 +408,7 @@ static void check_stack_size(struct RefCheck* check, struct Expr* expr) break; case EXPR_MEMBER: { - struct Expr* object = expr->member.object; + const struct Expr* object = expr->member.object; if (object->kind == EXPR_PRIMARY && (find_enum(check, object->primary.token) != NULL || find_struct(check, object->primary.token) != NULL)) -- cgit v1.3