diff --git a/compiler/main/avr_code_gen/cg_avr_basic_block.c b/compiler/main/avr_code_gen/cg_avr_basic_block.c index 0f3258e9..8d44238a 100644 --- a/compiler/main/avr_code_gen/cg_avr_basic_block.c +++ b/compiler/main/avr_code_gen/cg_avr_basic_block.c @@ -1,6 +1,7 @@ #include #include +#include "compiler/cli/flags/flags.h" #include "tables/symtable/symtable.h" #include "tac/tac.h" @@ -21,6 +22,10 @@ void emit_asm_avr_basic_block(struct BasicBlock* block, struct Ctx* ctx, struct if (block == NULL || block->visited_emit_asm) return; + if (flags_debug(ctx_flags(ctx))) { + printf("%s\n", __func__); + } + block->visited_emit_asm = true; //create register allocation table for the basic block. @@ -32,15 +37,16 @@ void emit_asm_avr_basic_block(struct BasicBlock* block, struct Ctx* ctx, struct //TODO: use better approach allocate_registers(block->buffer, rat, ctx_tables(ctx)); + if (flags_debug(ctx_flags(ctx))) { + rat_print(rat); + } + for (size_t i = 0; i < tacbuffer_count(block->buffer); i++) { struct TAC* t = tacbuffer_get(block->buffer, i); emit_asm_avr_single_tac(rat, t, ctx, ibu); } - //if(ctx->flags->debug) - //rat_print(rat); - rat_dtor(rat); //false/default branch gets emitted first, @@ -119,12 +125,16 @@ static void allocate_registers_single_tac(struct TAC* t, struct RAT* rat, struct case TAC_LOAD_CONST_ADDR: rat_ensure_register(rat, t->dest, false, true); + //TODO: know the width of the load break; case TAC_LOAD: //sadly we do not know what is all going to be added/subtracted //from what we load there, could be a pointer, so it must be wide - rat_ensure_register(rat, t->dest, false, true); + { + const bool iswide = t->const_value >= 2; + rat_ensure_register(rat, t->dest, false, iswide); + } break; default: break; diff --git a/compiler/main/avr_code_gen/compile_ir/compile_tac_call.c b/compiler/main/avr_code_gen/compile_ir/compile_tac_call.c index 153be69d..00c6cd9f 100644 --- a/compiler/main/avr_code_gen/compile_ir/compile_tac_call.c +++ b/compiler/main/avr_code_gen/compile_ir/compile_tac_call.c @@ -14,6 +14,8 @@ void compile_tac_call(struct RAT* rat, struct TAC* tac, struct IBuffer* ibu, str int reg_dest = rat_get_register(rat, tac->dest); const int RAT_SCRATCH_REG = rat_scratch_reg(rat); + const bool wide_dest = rat_is_wide(rat, tac->dest); + //in case of tests, where SST may not be filled correctly char* function_name = "main"; @@ -23,9 +25,15 @@ void compile_tac_call(struct RAT* rat, struct TAC* tac, struct IBuffer* ibu, str call(function_name, "TAC_CALL"); - if (reg_dest != 0) + if (reg_dest != 0) { mov(reg_dest, 0, "TAC_CALL"); + if (wide_dest) { + // TODO: check if function return type is wide + mov(reg_dest + 1, 1, "TAC_CALL"); + } + } + struct SST* sst = ctx_tables(ctx)->sst; //for the case of tests on raw TACBuffers @@ -40,4 +48,9 @@ void compile_tac_call(struct RAT* rat, struct TAC* tac, struct IBuffer* ibu, str for (uint32_t i = 0; i < size; i++) { pop(RAT_SCRATCH_REG, "remove call params"); } + + // load possibly corrupted frame pointer + //load base pointer Y + in(YL, SPL, "restore frame pointer Y after call"); + in(YH, SPH, "restore frame pointer Y after call"); } diff --git a/compiler/main/avr_code_gen/compile_ir/compile_tac_load.c b/compiler/main/avr_code_gen/compile_ir/compile_tac_load.c index e1f0c91c..3ca31f0c 100644 --- a/compiler/main/avr_code_gen/compile_ir/compile_tac_load.c +++ b/compiler/main/avr_code_gen/compile_ir/compile_tac_load.c @@ -24,12 +24,20 @@ void compile_tac_load(struct RAT* rat, struct TAC* tac, struct IBuffer* ibu) { else ldi(XH, 0, c); - if (rat_is_wide(rat, tac->dest)) { + // TODO: make a 'wide' property in struct TAC + // to avoid encoding this in different places + const bool tac_says_wide = tac->const_value == 2; + + if (tac_says_wide) { // what if we want to load a 16 bit value? ldXpostInc(reg_dest, c); ldX(reg_dest + 1, c); } else { ldX(reg_dest, c); + + if (rat_is_wide(rat, tac->dest)) { + clr(reg_dest + 1, c); + } } } diff --git a/compiler/main/avr_code_gen/compile_ir/compile_tac_load_const_addr.c b/compiler/main/avr_code_gen/compile_ir/compile_tac_load_const_addr.c index 28b6c554..43cd0f0c 100644 --- a/compiler/main/avr_code_gen/compile_ir/compile_tac_load_const_addr.c +++ b/compiler/main/avr_code_gen/compile_ir/compile_tac_load_const_addr.c @@ -1,5 +1,3 @@ -#include - #include "tac/tacbuffer.h" #include "tac/tac.h" #include "avr_code_gen/compile_ir/compile_tac.h" @@ -8,7 +6,13 @@ void compile_tac_load_const_addr(struct RAT* rat, struct TAC* tac, struct IBuffe const int reg_dest = rat_get_register(rat, tac->dest); + const bool is_wide = rat_is_wide(rat, tac->dest); + const uint32_t addr = tac->const_value; lds(reg_dest, addr, "TAC_LOAD_CONST_ADDR"); + + if (is_wide) { + lds(reg_dest + 1, addr + 1, "TAC_LOAD_CONST_ADDR"); + } } diff --git a/compiler/main/avr_code_gen/compile_ir/compile_tac_param.c b/compiler/main/avr_code_gen/compile_ir/compile_tac_param.c index 915b64dc..3129eeb6 100644 --- a/compiler/main/avr_code_gen/compile_ir/compile_tac_param.c +++ b/compiler/main/avr_code_gen/compile_ir/compile_tac_param.c @@ -1,5 +1,6 @@ #include #include +#include #include "rat/rat.h" @@ -8,12 +9,27 @@ void compile_tac_param(struct RAT* rat, struct TAC* tac, struct IBuffer* ibu) { - const char* c = "TAC_PARAM"; + char* c = "TAC_PARAM"; const int reg_dest = rat_get_register(rat, tac->dest); - push(reg_dest, c); + assert(tac->const_value % 8 == 0); + assert(tac->const_value <= 64); + + if (tac->const_value == 16) { + // this means it's a 16 bit parameter + // so we must push twice + + //TODO: ensure that the temporary has the correct width in RAT + //assert(rat_is_wide(rat, tac->dest)); - if (rat_is_wide(rat, tac->dest) && tac->const_value == 16) - push(reg_dest + 1, c); + if (rat_is_wide(rat, tac->dest)) { + push(reg_dest + 1, c); + } else { + ldi(rat_scratch_reg(rat), 0, c); + push(rat_scratch_reg(rat), c); + } + } + + push(reg_dest, c); } diff --git a/compiler/main/avr_code_gen/compile_ir/compile_tac_store_const_addr.c b/compiler/main/avr_code_gen/compile_ir/compile_tac_store_const_addr.c index c99c82a5..4b0cfc69 100644 --- a/compiler/main/avr_code_gen/compile_ir/compile_tac_store_const_addr.c +++ b/compiler/main/avr_code_gen/compile_ir/compile_tac_store_const_addr.c @@ -10,5 +10,11 @@ void compile_tac_store_const_addr(struct RAT* rat, struct TAC* tac, struct IBuff const uint32_t addr = tac->const_value; - sts(addr, reg_src, "TAC_STORE_CONST_ADDR"); + char* c = "TAC_STORE_CONST_ADDR"; + + sts(addr, reg_src, c); + + if (rat_is_wide(rat, tac->arg1)) { + sts(addr + 1, reg_src + 1, c); + } } diff --git a/compiler/main/compiler.c b/compiler/main/compiler.c index fafe4ad6..997d5a50 100644 --- a/compiler/main/compiler.c +++ b/compiler/main/compiler.c @@ -58,16 +58,20 @@ bool compile(struct Flags* flags) { ast->namespaces[i] = ns; } - struct Ctx* ctx = ctx_ctor(flags, st_ctor(flags_debug(flags))); + struct Ctx* ctx = ctx_ctor(flags, st_ctor()); fill_tables(ast, ctx); - struct TCError* errors = typecheck_ast(ast, ctx_tables(ctx), true); + struct TCError* errors = typecheck_ast(ast, ctx, true); if (errors != NULL) { return false; } + if (flags_debug(flags)) { + printf("[debug] running analyzers...\n"); + } + analyze_functions(ctx_tables(ctx), ast); analyze_dead_code(ctx_tables(ctx), ast); analyze_termination(ctx_tables(ctx)); diff --git a/compiler/main/gen_tac/gen_tac_call.c b/compiler/main/gen_tac/gen_tac_call.c index f0027376..006f4861 100644 --- a/compiler/main/gen_tac/gen_tac_call.c +++ b/compiler/main/gen_tac/gen_tac_call.c @@ -1,5 +1,6 @@ #include #include +#include #include "tac/tac.h" #include "tac/tacbuffer.h" @@ -11,26 +12,86 @@ #include "gen_tac.h" -void tac_call(struct TACBuffer* buffer, struct Call* call, struct Ctx* ctx) { +static void tac_call_case_sst(struct TACBuffer* buffer, struct Call* call, struct Ctx* ctx); +static void tac_call_case_lvst(struct TACBuffer* buffer, struct Call* call, struct Ctx* ctx); - const char* fname = call->callable->simple_var->name; +static void tac_call_prep_param(struct TACBuffer* buffer, struct Call* call, struct Ctx* ctx, int i, const bool push16) { + struct Expr* expr = call->args[i]; - struct SST* sst = ctx_tables(ctx)->sst; - struct SSTLine* line = sst_get(sst, fname); + tac_expr(buffer, expr, ctx); + struct TAC* t = makeTACParam(tacbuffer_last_dest(buffer), push16); + + tacbuffer_append(buffer, t); +} + +static void tac_call_prep_params_case_sst(struct TACBuffer* buffer, struct Call* call, struct Ctx* ctx, struct MethodDecl* decl) { for (size_t i = 0; i < call->count_args; i++) { + const uint32_t param_width = lvst_sizeof_type(decl->args[i]->type); + assert(param_width <= 8); + const bool push16 = param_width == 2; + + tac_call_prep_param(buffer, call, ctx, i, push16); + } +} - struct Expr* expr = call->args[i]; +static void tac_call_prep_params_case_lvst(struct TACBuffer* buffer, struct Call* call, struct Ctx* ctx, struct LVSTLine* line) { + for (size_t i = 0; i < call->count_args; i++) { + struct Type* arg_type = line->type->basic_type->subr_type->arg_types[i]; + const uint32_t param_width = lvst_sizeof_type(arg_type); + assert(param_width <= 8); + const bool push16 = param_width == 2; - tac_expr(buffer, expr, ctx); + tac_call_prep_param(buffer, call, ctx, i, push16); + } +} - const bool push16 = 16 == lvst_sizeof_type(line->method->decl->args[i]->type); +void tac_call(struct TACBuffer* buffer, struct Call* call, struct Ctx* ctx) { - struct TAC* t = makeTACParam(tacbuffer_last_dest(buffer), push16); + char* fname = call->callable->simple_var->name; + struct SST* sst = ctx_tables(ctx)->sst; + struct LVST* lvst = ctx_tables(ctx)->lvst; - tacbuffer_append(buffer, t); + if (sst_contains(sst, fname)) { + tac_call_case_sst(buffer, call, ctx); + return; + } + if (lvst_contains(lvst, fname)) { + tac_call_case_lvst(buffer, call, ctx); + return; } + fprintf(stderr, "did not find symbol '%s' in LVST or SST, cannot call.\n", fname); + fprintf(stderr, "exiting."); + exit(1); +} + +static void tac_call_case_lvst(struct TACBuffer* buffer, struct Call* call, struct Ctx* ctx) { + + struct LVST* lvst = ctx_tables(ctx)->lvst; + char* fname = call->callable->simple_var->name; + + struct LVSTLine* line = lvst_get(lvst, fname); + tac_call_prep_params_case_lvst(buffer, call, ctx, line); + uint32_t tmp = make_temp(); + struct TAC* t1 = makeTACLoadLocal(tmp, lvst_index_of(lvst, fname)); + struct TAC* t2 = makeTACICall(make_temp(), tmp); + + tacbuffer_append(buffer, t1); + tacbuffer_append(buffer, t2); +} + +static void tac_call_case_sst(struct TACBuffer* buffer, struct Call* call, struct Ctx* ctx) { + + const char* fname = call->callable->simple_var->name; + + struct SST* sst = ctx_tables(ctx)->sst; + struct SSTLine* line = sst_get(sst, fname); + + struct MethodDecl* decl = line->method->decl; + + tac_call_prep_params_case_sst(buffer, call, ctx, decl); + if (call->callable->member_access != NULL) { printf("member access calls currently unsupported on avr_code_gen\n"); exit(1); diff --git a/compiler/main/gen_tac/gen_tac_mdirect.c b/compiler/main/gen_tac/gen_tac_mdirect.c index 81340b25..84704617 100644 --- a/compiler/main/gen_tac/gen_tac_mdirect.c +++ b/compiler/main/gen_tac/gen_tac_mdirect.c @@ -33,7 +33,8 @@ static void case_variable_addr(struct TACBuffer* buffer, struct Expr* expr, stru tac_expr(buffer, expr, ctx); - struct TAC* t = makeTACLoad(make_temp(), tacbuffer_last_dest(buffer)); + // TODO: for x86, this needs to be 8 bytes, not 2 + struct TAC* t = makeTACLoad(make_temp(), tacbuffer_last_dest(buffer), 2); tacbuffer_append(buffer, t); } diff --git a/compiler/main/gen_tac/gen_tac_simplevar.c b/compiler/main/gen_tac/gen_tac_simplevar.c index 1f2bcc69..a84f3945 100644 --- a/compiler/main/gen_tac/gen_tac_simplevar.c +++ b/compiler/main/gen_tac/gen_tac_simplevar.c @@ -20,7 +20,10 @@ void tac_simplevar(struct TACBuffer* buffer, struct SimpleVar* v, struct Ctx* ct uint32_t tlast = tacbuffer_last_dest(buffer); - tacbuffer_append(buffer, makeTACLoad(make_temp(), tlast)); + struct LVST* lvst = ctx_tables(ctx)->lvst; + const uint8_t simplevar_width = lvst_sizeof_var(lvst, v->name); + + tacbuffer_append(buffer, makeTACLoad(make_temp(), tlast, simplevar_width)); } void tac_simplevar_addr(struct TACBuffer* buffer, struct SimpleVar* sv, struct Ctx* ctx) { diff --git a/compiler/main/gen_tac/gen_tac_variable.c b/compiler/main/gen_tac/gen_tac_variable.c index 4521f259..8e014e2d 100644 --- a/compiler/main/gen_tac/gen_tac_variable.c +++ b/compiler/main/gen_tac/gen_tac_variable.c @@ -20,7 +20,10 @@ void tac_variable(struct TACBuffer* buffer, struct Variable* v, struct Ctx* ctx) uint32_t tlast = tacbuffer_last_dest(buffer); - tacbuffer_append(buffer, makeTACLoad(make_temp(), tlast)); + // TODO: do not assume the variable has 2 bytes + // on avr, it can only be 1 byte + // on x86 it can be up to 8 + tacbuffer_append(buffer, makeTACLoad(make_temp(), tlast, 2)); } void tac_variable_addr(struct TACBuffer* buffer, struct Variable* v, struct Ctx* ctx) { diff --git a/compiler/main/gen_tac/helper_gen_tac_derefll.c b/compiler/main/gen_tac/helper_gen_tac_derefll.c index 4df4aafe..9bcd1f76 100644 --- a/compiler/main/gen_tac/helper_gen_tac_derefll.c +++ b/compiler/main/gen_tac/helper_gen_tac_derefll.c @@ -46,7 +46,8 @@ void tac_derefll_single(struct TACBuffer* buffer, struct DerefLL* dll, struct Ty } break; case DEREFLL_DEREF: - tacbuffer_append(buffer, makeTACLoad(make_temp(), tacbuffer_last_dest(buffer))); + // TODO: the width there needs to be architecture specific, for x86 it's not 2 but 8 bytes + tacbuffer_append(buffer, makeTACLoad(make_temp(), tacbuffer_last_dest(buffer), 2)); break; } } diff --git a/compiler/main/typechecker/tc_assignstmt.c b/compiler/main/typechecker/tc_assignstmt.c index bbedeb2b..4437aa3c 100644 --- a/compiler/main/typechecker/tc_assignstmt.c +++ b/compiler/main/typechecker/tc_assignstmt.c @@ -25,6 +25,10 @@ static bool check_type_rules_assign(struct AssignStmt* a, struct TCCtx* tcctx); bool tc_assignstmt(struct AssignStmt* a, struct TCCtx* tcctx) { + if (tcctx->debug) { + printf("[debug] typecheck assign stmt\n"); + } + tcctx->current_line_num = a->super.line_num; struct LVSTLine* line = lvst_get(tcctx->st->lvst, a->var->simple_var->name); diff --git a/compiler/main/typechecker/tc_forstmt.c b/compiler/main/typechecker/tc_forstmt.c index e9382a1d..ab5ac96b 100644 --- a/compiler/main/typechecker/tc_forstmt.c +++ b/compiler/main/typechecker/tc_forstmt.c @@ -16,6 +16,10 @@ bool tc_forstmt(struct ForStmt* f, struct TCCtx* tcctx) { + if (tcctx->debug) { + printf("[debug] typecheck for stmt\n"); + } + tcctx->current_line_num = f->super.line_num; if (!tc_range(f->range, tcctx)) { return false; } @@ -25,4 +29,4 @@ bool tc_forstmt(struct ForStmt* f, struct TCCtx* tcctx) { tcctx->depth_inside_loop--; return is_ok; -} \ No newline at end of file +} diff --git a/compiler/main/typechecker/tc_ifstmt.c b/compiler/main/typechecker/tc_ifstmt.c index 8fa5d1df..3a53bfda 100644 --- a/compiler/main/typechecker/tc_ifstmt.c +++ b/compiler/main/typechecker/tc_ifstmt.c @@ -16,6 +16,10 @@ bool tc_ifstmt(struct IfStmt* i, struct TCCtx* tcctx) { + if (tcctx->debug) { + printf("[debug] typecheck if stmt\n"); + } + tcctx->current_line_num = i->super.line_num; struct Type* type = infer_type_expr(tcctx->st, i->condition); diff --git a/compiler/main/typechecker/tc_method.c b/compiler/main/typechecker/tc_method.c index b494558b..38499cff 100644 --- a/compiler/main/typechecker/tc_method.c +++ b/compiler/main/typechecker/tc_method.c @@ -16,6 +16,10 @@ bool tc_method(struct Method* m, struct TCCtx* tcctx) { + if (tcctx->debug) { + printf("[debug] typecheck method: %s\n", m->decl->name); + } + tcctx->current_line_num = m->super.line_num; tcctx->current_fn = m; @@ -24,4 +28,4 @@ bool tc_method(struct Method* m, struct TCCtx* tcctx) { lvst_fill(m, tcctx->st); return tc_stmtblock(m->block, tcctx); -} \ No newline at end of file +} diff --git a/compiler/main/typechecker/tc_methodcall.c b/compiler/main/typechecker/tc_methodcall.c index 6c21938b..4971a1a5 100644 --- a/compiler/main/typechecker/tc_methodcall.c +++ b/compiler/main/typechecker/tc_methodcall.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -36,6 +37,10 @@ static bool tc_methodcall_arg( bool tc_methodcall(struct Call* m, struct TCCtx* tcctx) { + if (tcctx->debug) { + printf("[debug] typecheck methodcall\n"); + } + tcctx->current_line_num = m->super.line_num; if (!tc_var(m->callable, tcctx)) { return false; } @@ -73,6 +78,11 @@ static bool tc_methodcall_args( struct Type** expect_types, uint8_t expect_args, struct TCCtx* tcctx) { + + if (tcctx->debug) { + printf("[debug] typecheck methodcall args\n"); + } + const uint8_t actual_args = m->count_args; if (actual_args != expect_args) { @@ -108,6 +118,9 @@ static bool tc_methodcall_arg( struct Type* actual_type = infer_type_expr(tcctx->st, actual_expr); + assert(expect_type != NULL); + assert(actual_type != NULL); + //TODO: we can get rid of the integer special cases maybe //thansk to tc_type_contains if (is_integer_type(expect_type) && is_integer_type(actual_type)) { return true; } diff --git a/compiler/main/typechecker/tc_retstmt.c b/compiler/main/typechecker/tc_retstmt.c index 101f1d4c..83a18ce0 100644 --- a/compiler/main/typechecker/tc_retstmt.c +++ b/compiler/main/typechecker/tc_retstmt.c @@ -17,6 +17,10 @@ bool tc_retstmt(struct RetStmt* r, struct TCCtx* tcctx) { + if (tcctx->debug) { + printf("[debug] typecheck return stmt\n"); + } + tcctx->current_line_num = r->super.line_num; struct Type* returnType = tcctx->current_fn->decl->return_type; diff --git a/compiler/main/typechecker/tc_stmts.c b/compiler/main/typechecker/tc_stmts.c index ba2c13fd..7ba78c4e 100644 --- a/compiler/main/typechecker/tc_stmts.c +++ b/compiler/main/typechecker/tc_stmts.c @@ -11,11 +11,16 @@ #include "typechecker/util/tc_errors.h" #include "typechecker/util/tc_utils.h" #include "tcctx.h" +#include bool tc_stmt(struct Stmt* s, struct TCCtx* tcctx) { tcctx->current_line_num = s->super.line_num; + if (tcctx->debug) { + printf("[debug] typecheck statement line %d\n", tcctx->current_line_num); + } + switch (s->kind) { case 1: return tc_methodcall(s->ptr.m1, tcctx); diff --git a/compiler/main/typechecker/tc_whilestmt.c b/compiler/main/typechecker/tc_whilestmt.c index 104e47b1..66a05847 100644 --- a/compiler/main/typechecker/tc_whilestmt.c +++ b/compiler/main/typechecker/tc_whilestmt.c @@ -16,6 +16,10 @@ bool tc_whilestmt(struct WhileStmt* w, struct TCCtx* tcctx) { + if (tcctx->debug) { + printf("[debug] typecheck while stmt\n"); + } + tcctx->current_line_num = w->super.line_num; struct Type* type = infer_type_expr(tcctx->st, w->condition); diff --git a/compiler/main/typechecker/tcctx.h b/compiler/main/typechecker/tcctx.h index ace236ef..3093c9a5 100644 --- a/compiler/main/typechecker/tcctx.h +++ b/compiler/main/typechecker/tcctx.h @@ -68,6 +68,8 @@ struct TCCtx { char* current_filename; uint32_t current_line_num; + + bool debug; }; #endif diff --git a/compiler/main/typechecker/typecheck.c b/compiler/main/typechecker/typecheck.c index b11416bc..e12375f7 100644 --- a/compiler/main/typechecker/typecheck.c +++ b/compiler/main/typechecker/typecheck.c @@ -6,8 +6,11 @@ #include "ast/ast.h" //Table Includes +#include "compiler/cli/flags/flags.h" #include "tables/symtable/symtable.h" +#include "util/ctx.h" + //Typechecker Includes #include "_tc.h" #include "typecheck.h" @@ -16,15 +19,27 @@ static void init_tcctx(struct TCCtx* tcctx); -struct TCError* typecheck_ast(struct AST* ast, struct ST* st, bool print_errors) { +struct TCError* typecheck_ast(struct AST* ast, struct Ctx* ctx, bool print_errors) { + + if (flags_debug(ctx_flags(ctx))) { + printf("[debug] typechecking AST...\n"); + } + struct ST* st = ctx_tables(ctx); struct TCCtx* tcctx = exit_malloc(sizeof(struct TCCtx)); init_tcctx(tcctx); tcctx->print_errors = print_errors; tcctx->st = st; + tcctx->debug = flags_debug(ctx_flags(ctx)); for (uint16_t i = 0; i < ast->count_namespaces; i++) { + + if (tcctx->debug) { + printf("[debug] typecheck namespace: %d\n", i); + printf("[debug] src_path: %s\n", ast->namespaces[i]->src_path); + } + tc_namespace(ast->namespaces[i], tcctx); } @@ -71,4 +86,6 @@ static void init_tcctx(struct TCCtx* tcctx) { tcctx->current_fn = NULL; tcctx->depth_inside_loop = 0; + + tcctx->debug = false; } diff --git a/compiler/main/typechecker/typecheck.h b/compiler/main/typechecker/typecheck.h index 4f3abdf2..ef6a61e9 100644 --- a/compiler/main/typechecker/typecheck.h +++ b/compiler/main/typechecker/typecheck.h @@ -5,6 +5,8 @@ struct AST; struct ST; #include "tcctx.h" +#include "util/ctx.h" + /* This Module provides Facilities * for typechecking smalldragon Programs. * @@ -24,6 +26,6 @@ struct ST; * inferring the type of '3 + myfunction' */ -struct TCError* typecheck_ast(struct AST* ast, struct ST* st, bool print_errors); +struct TCError* typecheck_ast(struct AST* ast, struct Ctx* ctx, bool print_errors); #endif diff --git a/compiler/main/typeinference/typeinfer_const.c b/compiler/main/typeinference/typeinfer_const.c index bf395fdd..e4f645a7 100644 --- a/compiler/main/typeinference/typeinfer_const.c +++ b/compiler/main/typeinference/typeinfer_const.c @@ -32,7 +32,11 @@ struct Type* infer_type_constvalue(struct ST* st, struct ConstValue* cv) { case 1: return typeFromStrPrimitive(st, "bool"); case 2: return infer_type_constvalue_int(st, cv->ptr.m2_int_const); case 3: return typeFromStrPrimitive(st, "char"); + case 6: // binary constant case 5: return infer_type_constvalue_int(st, cv->ptr.m5_hex_const); - default: return NULL; + default: + fprintf(stderr, "in %s: could not infer type of const value, extiting.\n", __func__); + exit(1); + return NULL; } } diff --git a/compiler/main/util/fill_tables.c b/compiler/main/util/fill_tables.c index 0c62e6a5..6e826239 100644 --- a/compiler/main/util/fill_tables.c +++ b/compiler/main/util/fill_tables.c @@ -12,6 +12,10 @@ void fill_tables(struct AST* ast, struct Ctx* ctx) { + if (flags_debug(ctx_flags(ctx))) { + printf("[debug] filling SST, STST tables...\n"); + } + sst_clear(ctx_tables(ctx)->sst); for (int i = 0; i < ast->count_namespaces; i++) { diff --git a/compiler/test/avr_code_gen/compile_ir/test_compile_tac.h b/compiler/test/avr_code_gen/compile_ir/test_compile_tac.h index 41a00629..86dfb16e 100644 --- a/compiler/test/avr_code_gen/compile_ir/test_compile_tac.h +++ b/compiler/test/avr_code_gen/compile_ir/test_compile_tac.h @@ -9,8 +9,14 @@ void test_compile_tac_nop(); void test_compile_tac_const_value_test_8bit(); void test_compile_tac_const_value_test_16bit(); -void test_compile_tac_store_const_addr(); -void test_compile_tac_load_const_addr(); +void test_compile_tac_store_const_addr_case_8bit_value_addr_0x118(); +void test_compile_tac_store_const_addr_case_8bit_value_addr_0x119(); +void test_compile_tac_store_const_addr_case_16bit_value_addr_0x118(); +void test_compile_tac_store_const_addr_case_16bit_value_addr_0x119(); +void test_compile_tac_load_const_addr_case_8bit_value_0x55(); +void test_compile_tac_load_const_addr_case_8bit_value_0x56(); +void test_compile_tac_load_const_addr_case_16bit_value_0x1234(); +void test_compile_tac_load_const_addr_case_16bit_value_0x4321(); // TAC_BINARY_OP_IMMEDIATE void test_compile_tac_binary_op_immediate_case_add_8bit(); @@ -94,7 +100,10 @@ void test_compile_tac_if_cmp_goto_case_ge_false_8bit(); void test_compile_tac_if_cmp_goto_case_ge_false_16bit(); // TAC_RETURN -void test_compile_tac_return(); +void test_compile_tac_return_case_8bit_0x54(); +void test_compile_tac_return_case_8bit_0x55(); +void test_compile_tac_return_case_16bit_0x5432(); +void test_compile_tac_return_case_16bit_0x4321(); // TAC_COPY void test_compile_tac_copy_case_8bit(); @@ -106,16 +115,23 @@ void test_compile_tac_param_case_16bit(); // TAC_CALL void test_compile_tac_call_case_recurses(); -void test_compile_tac_call_case_returns_value(); +void test_compile_tac_call_case_returns_value_8bit(); +void test_compile_tac_call_case_returns_value_16bit(); void test_compile_tac_call_case_1_param(); // TAC_LOAD -void test_compile_tac_load_case_8bit_addr(); -void test_compile_tac_load_case_16bit_addr(); +void test_compile_tac_load_case_8bit_addr_8bit_value(); +void test_compile_tac_load_case_8bit_addr_16bit_value(); +void test_compile_tac_load_case_16bit_addr_8bit_value(); +void test_compile_tac_load_case_16bit_addr_16bit_value(); // TAC_STORE -void test_compile_tac_store_case_8bit_value_8bit_addr(); -void test_compile_tac_store_case_16bit_value_8bit_addr(); +void test_compile_tac_store_case_8bit_value_8bit_addr_c7(); +void test_compile_tac_store_case_8bit_value_8bit_addr_c8(); + +void test_compile_tac_store_case_16bit_value_8bit_addr_c7_f03(); +void test_compile_tac_store_case_16bit_value_8bit_addr_c8_f03(); + void test_compile_tac_store_case_8bit_value_16bit_addr(); void test_compile_tac_store_case_16bit_value_16bit_addr(); diff --git a/compiler/test/avr_code_gen/compile_ir/test_compile_tac_binary_op.c b/compiler/test/avr_code_gen/compile_ir/test_compile_tac_binary_op.c index f5183305..a8728621 100644 --- a/compiler/test/avr_code_gen/compile_ir/test_compile_tac_binary_op.c +++ b/compiler/test/avr_code_gen/compile_ir/test_compile_tac_binary_op.c @@ -15,10 +15,6 @@ #include "test_compile_tac.h" -static int16_t make16(uint8_t high, uint8_t low) { - return (high << 8) | low; -} - void test_compile_tac_binary_op_add_8bit() { status_test_codegen("TAC_BINARY_OP + (8 bit)"); @@ -73,10 +69,9 @@ void test_compile_tac_binary_op_add_16bit() { vmcu_system_step_n(system, 8); - const int8_t r0 = vmcu_system_read_gpr(system, 0); - const int8_t r1 = vmcu_system_read_gpr(system, 1); + const int16_t actual = vmcu_system_read_2_gpr(system, 0); - assert(make16(r1, r0) == expected); + assert(actual == expected); vmcu_system_dtor(system); } @@ -132,10 +127,9 @@ void test_compile_tac_binary_op_sub_16bit() { vmcu_system_step_n(system, 8); - const uint8_t r0 = vmcu_system_read_gpr(system, 0); - const uint8_t r1 = vmcu_system_read_gpr(system, 1); + const int16_t actual = vmcu_system_read_2_gpr(system, 0); - assert(make16(r1, r0) == expected); + assert(actual == expected); vmcu_system_dtor(system); } @@ -191,10 +185,9 @@ void test_compile_tac_binary_op_and_16bit() { vmcu_system_step_n(system, 8); - int8_t r0 = vmcu_system_read_gpr(system, 0); - int8_t r1 = vmcu_system_read_gpr(system, 1); + const int16_t actual = vmcu_system_read_2_gpr(system, 0); - assert(make16(r1, r0) == expected); + assert(actual == expected); vmcu_system_dtor(system); } @@ -249,10 +242,9 @@ void test_compile_tac_binary_op_or_16bit() { vmcu_system_step_n(system, 8); - uint8_t r0 = vmcu_system_read_gpr(system, 0); - uint8_t r1 = vmcu_system_read_gpr(system, 1); + const int16_t actual = vmcu_system_read_2_gpr(system, 0); - assert(make16(r1, r0) == expected); + assert(actual == expected); vmcu_system_dtor(system); } @@ -307,10 +299,7 @@ void test_compile_tac_binary_op_xor_16bit() { vmcu_system_step_n(system, 10); - uint8_t r0 = vmcu_system_read_gpr(system, 0); - uint8_t r1 = vmcu_system_read_gpr(system, 1); - - uint16_t actual = make16(r1, r0); + const uint16_t actual = vmcu_system_read_2_gpr(system, 0); //printf("0x%x ^ 0x%x == 0x%x (actual: 0x%x)\n", start, change, expected, actual); @@ -340,10 +329,7 @@ void test_compile_tac_binary_op_xor_mixed1() { vmcu_system_step_n(system, 10); - uint8_t r0 = vmcu_system_read_gpr(system, 0); - uint8_t r1 = vmcu_system_read_gpr(system, 1); - - uint16_t actual = make16(r1, r0); + const uint16_t actual = vmcu_system_read_2_gpr(system, 0); assert(actual == 0xff00); @@ -372,10 +358,7 @@ void test_compile_tac_binary_op_xor_mixed2() { vmcu_system_step_n(system, 10); - uint8_t r0 = vmcu_system_read_gpr(system, 0); - uint8_t r1 = vmcu_system_read_gpr(system, 1); - - uint16_t actual = make16(r1, r0); + const uint16_t actual = vmcu_system_read_2_gpr(system, 0); assert(actual == expected); diff --git a/compiler/test/avr_code_gen/compile_ir/test_compile_tac_binary_op_immediate.c b/compiler/test/avr_code_gen/compile_ir/test_compile_tac_binary_op_immediate.c index 109bebf4..289d6fdf 100644 --- a/compiler/test/avr_code_gen/compile_ir/test_compile_tac_binary_op_immediate.c +++ b/compiler/test/avr_code_gen/compile_ir/test_compile_tac_binary_op_immediate.c @@ -68,12 +68,7 @@ void test_compile_tac_binary_op_immediate_case_add_16bit() { vmcu_system_step_n(system, 20); - uint8_t r0 = vmcu_system_read_gpr(system, 0); - uint8_t r1 = vmcu_system_read_gpr(system, 1); - - //printf("r0 = 0x%x, r1 = 0x%x\n", r0, r1); - - int16_t actual = r0 | (r1 << 8); + int16_t actual = vmcu_system_read_2_gpr(system, 0); //printf("actual %d (0x%x)\n", actual, actual); //printf("expected %d (0x%x)\n", expected, expected); @@ -133,10 +128,7 @@ void test_compile_tac_binary_op_immediate_case_sub_16bit() { vmcu_system_step_n(system, 10); - uint8_t r0 = (uint8_t)vmcu_system_read_gpr(system, 0); - uint8_t r1 = (uint8_t)vmcu_system_read_gpr(system, 1); - - int16_t actual = (int16_t)(r0 | (r1 << 8)); + int16_t actual = vmcu_system_read_2_gpr(system, 0); //printf("expected: %d\n", expected); //printf("actual: %d\n", actual); @@ -191,10 +183,7 @@ void test_compile_tac_binary_op_immediate_case_and_16bit() { vmcu_system_step_n(system, 12); - uint8_t r0 = vmcu_system_read_gpr(system, 0); - uint8_t r1 = vmcu_system_read_gpr(system, 1); - - uint16_t actual = (r1 << 8) | r0; + int16_t actual = vmcu_system_read_2_gpr(system, 0); assert(actual == expected); @@ -246,10 +235,7 @@ void test_compile_tac_binary_op_immediate_case_or_16bit() { vmcu_system_step_n(system, 10); - uint8_t r0 = vmcu_system_read_gpr(system, 0); - uint8_t r1 = vmcu_system_read_gpr(system, 1); - - uint16_t actual = (r1 << 8) | r0; + uint16_t actual = vmcu_system_read_2_gpr(system, 0); assert(actual == expected); @@ -301,10 +287,7 @@ void test_compile_tac_binary_op_immediate_case_xor_16bit() { vmcu_system_step_n(system, 10); - uint8_t r0 = vmcu_system_read_gpr(system, 0); - uint8_t r1 = vmcu_system_read_gpr(system, 1); - - uint16_t actual = (r1 << 8) | r0; + uint16_t actual = vmcu_system_read_2_gpr(system, 0); assert(actual == expected); @@ -362,10 +345,7 @@ void test_compile_tac_binary_op_immediate_case_shift_left_16bit() { vmcu_system_step_n(system, 8 + change * 2); - uint8_t r0 = (uint8_t)vmcu_system_read_gpr(system, 0); - uint8_t r1 = (uint8_t)vmcu_system_read_gpr(system, 1); - - uint16_t actual = (r1 << 8) | r0; + uint16_t actual = vmcu_system_read_2_gpr(system, 0); //printf("actual 0x%x\n", actual); @@ -423,10 +403,7 @@ void test_compile_tac_binary_op_immediate_case_shift_right_16bit() { vmcu_system_step_n(system, 8 + change * 2); - uint8_t r0 = (uint8_t)vmcu_system_read_gpr(system, 0); - uint8_t r1 = (uint8_t)vmcu_system_read_gpr(system, 1); - - uint16_t actual = (r1 << 8) | r0; + uint16_t actual = vmcu_system_read_2_gpr(system, 0); assert(actual == expected); diff --git a/compiler/test/avr_code_gen/compile_ir/test_compile_tac_call.c b/compiler/test/avr_code_gen/compile_ir/test_compile_tac_call.c index 9f760dc0..782ece65 100644 --- a/compiler/test/avr_code_gen/compile_ir/test_compile_tac_call.c +++ b/compiler/test/avr_code_gen/compile_ir/test_compile_tac_call.c @@ -44,9 +44,9 @@ void test_compile_tac_call_case_recurses() { vmcu_system_dtor(system); } -void test_compile_tac_call_case_returns_value() { +void test_compile_tac_call_case_returns_value_8bit() { - status_test_codegen("TAC_CALL - returns value"); + status_test_codegen("TAC_CALL - returns value (8 bit)"); const int8_t value = 0x63; @@ -67,6 +67,35 @@ void test_compile_tac_call_case_returns_value() { vmcu_system_dtor(system); } +void test_compile_tac_call_case_returns_value_16bit() { + + status_test_codegen("TAC_CALL - returns value (16 bit)"); + + const uint16_t value = 0x6385; + + struct TACBuffer* b = tacbuffer_ctor(); + + //main + tacbuffer_append(b, makeTACLabelFunction(0)); + tacbuffer_append(b, makeTACConst(0, value)); + + tacbuffer_append(b, makeTACReturn(0)); + + vmcu_system_t* system = prepare_vmcu_system_from_tacbuffer(b); + + vmcu_system_step_n(system, 20); + + const uint16_t retval = vmcu_system_read_2_gpr(system, 0); + + if (retval != value) { + printf("retval = 0x%x, value = 0x%x\n)", retval, value); + } + + assert(retval == value); + + vmcu_system_dtor(system); +} + void test_compile_tac_call_case_1_param() { status_test_codegen("TAC_CALL - 1 param [TODO]"); diff --git a/compiler/test/avr_code_gen/compile_ir/test_compile_tac_const_value.c b/compiler/test/avr_code_gen/compile_ir/test_compile_tac_const_value.c index 9b343c82..f9cfd1e9 100644 --- a/compiler/test/avr_code_gen/compile_ir/test_compile_tac_const_value.c +++ b/compiler/test/avr_code_gen/compile_ir/test_compile_tac_const_value.c @@ -61,14 +61,12 @@ void test_compile_tac_const_value_test_16bit() { //and the upper half to the reg above it bool found = false; - for (int i = 0; i < 32; i++) { - - if (vmcu_system_read_gpr(system, i) == (int8_t)(fixed_value & 0xff)) { - found = true; + for (int i = 0; i < 31; i++) { - int8_t rn = vmcu_system_read_gpr(system, i + 1); + const int16_t value = (int16_t)vmcu_system_read_2_gpr(system, i); - assert(rn == (int8_t)((fixed_value >> 8) & 0xff)); + if (value == fixed_value) { + found = true; } } diff --git a/compiler/test/avr_code_gen/compile_ir/test_compile_tac_copy.c b/compiler/test/avr_code_gen/compile_ir/test_compile_tac_copy.c index 0fe700b8..51a24547 100644 --- a/compiler/test/avr_code_gen/compile_ir/test_compile_tac_copy.c +++ b/compiler/test/avr_code_gen/compile_ir/test_compile_tac_copy.c @@ -53,13 +53,9 @@ void test_compile_tac_copy_case_16bit() { vmcu_system_step_n(system, 10); - int8_t r0 = vmcu_system_read_gpr(system, 0); - int8_t r1 = vmcu_system_read_gpr(system, 1); + const uint16_t value = vmcu_system_read_2_gpr(system, 0); - //printf("r0 0x%x %d, r1 0x%x %d\n", r0, (uint8_t)r0, r1, (uint8_t)r1); - - assert((uint8_t)r0 == (fixed_value & 0xff)); - assert((uint8_t)r1 == (fixed_value & 0xff00) >> 8); + assert(value == fixed_value); vmcu_system_dtor(system); } diff --git a/compiler/test/avr_code_gen/compile_ir/test_compile_tac_load.c b/compiler/test/avr_code_gen/compile_ir/test_compile_tac_load.c index cdb61864..adb9bb55 100644 --- a/compiler/test/avr_code_gen/compile_ir/test_compile_tac_load.c +++ b/compiler/test/avr_code_gen/compile_ir/test_compile_tac_load.c @@ -1,11 +1,8 @@ #include -#include #include #include "libvmcu/libvmcu_system.h" -#include "libvmcu/libvmcu_analyzer.h" -#include "avr_code_gen/cg_avr.h" #include "avr_code_gen/cg_avr_basic_block.h" #include "tac/tacbuffer.h" @@ -15,58 +12,75 @@ #include "test_compile_tac.h" -void test_compile_tac_load_case_8bit_addr() { +static void common(const uint16_t addr, const uint16_t fixed_value, bool wide) { - status_test_codegen("TAC_LOAD (8 bit address)"); + const uint8_t redzone = 0xff; - const uint16_t addr = 0xc7; - for (int8_t fixed_value = 0x33; fixed_value < 0x36; fixed_value++) { + struct TACBuffer* b = tacbuffer_ctor(); - struct TACBuffer* b = tacbuffer_ctor(); + tacbuffer_append(b, makeTACConst(1, 0x1010)); + tacbuffer_append(b, makeTACConst(2, addr)); + tacbuffer_append(b, makeTACLoad(1, 2, (wide) ? 2 : 1)); + tacbuffer_append(b, makeTACReturn(1)); - tacbuffer_append(b, makeTACConst(1, 0x00)); - tacbuffer_append(b, makeTACConst(2, addr)); - tacbuffer_append(b, makeTACLoad(1, 2)); - tacbuffer_append(b, makeTACReturn(1)); + vmcu_system_t* system = prepare_vmcu_system_from_tacbuffer_with_redzone(b, addr, redzone); - vmcu_system_t* system = prepare_vmcu_system_from_tacbuffer(b); + vmcu_system_write_data(system, addr, fixed_value); + if (wide) { + vmcu_system_write_data(system, addr + 1, (fixed_value >> 8)); + } - vmcu_system_write_data(system, addr, fixed_value); + vmcu_system_step_n(system, 20); - vmcu_system_step_n(system, 20); + const uint16_t value = vmcu_system_read_2_gpr(system, 0); - int8_t r0 = vmcu_system_read_gpr(system, 0); + if (value != fixed_value) { + printf("[0x%x] (may read 2 bytes) == 0x%x, expected 0x%x\n", addr, value, fixed_value); + } - assert(r0 == fixed_value); + assert(value == fixed_value); - vmcu_system_dtor(system); - } + assert_redzone(system, addr, (wide) ? 2 : 1, redzone); + + vmcu_system_dtor(system); } -void test_compile_tac_load_case_16bit_addr() { +void test_compile_tac_load_case_8bit_addr_8bit_value() { - status_test_codegen("TAC_LOAD (16 bit address)"); + status_test_codegen("TAC_LOAD (8 bit addr, 8 bit value)"); - const uint16_t addr = 0x0103; - for (int8_t fixed_value = 0x20; fixed_value < 0x24; fixed_value++) { + const uint16_t addr = 0xc7; + const uint8_t fixed_value = 0x33; - struct TACBuffer* b = tacbuffer_ctor(); + common(addr, fixed_value, false); +} - tacbuffer_append(b, makeTACConst(1, 0x00)); - tacbuffer_append(b, makeTACConst(2, addr)); - tacbuffer_append(b, makeTACLoad(1, 2)); - tacbuffer_append(b, makeTACReturn(1)); +void test_compile_tac_load_case_8bit_addr_16bit_value() { - vmcu_system_t* system = prepare_vmcu_system_from_tacbuffer(b); + status_test_codegen("TAC_LOAD (8 bit addr, 16 bit value)"); - vmcu_system_write_data(system, addr, fixed_value); + const uint16_t addr = 0xc7; + const uint16_t fixed_value = 0x3456; - vmcu_system_step_n(system, 20); + common(addr, fixed_value, true); +} - int8_t r0 = vmcu_system_read_gpr(system, 0); +void test_compile_tac_load_case_16bit_addr_8bit_value() { - assert(r0 == fixed_value); + status_test_codegen("TAC_LOAD (16 bit addr, 8 bit value)"); - vmcu_system_dtor(system); - } + const uint16_t addr = 0x0103; + const int8_t fixed_value = 0x20; + + common(addr, fixed_value, false); +} + +void test_compile_tac_load_case_16bit_addr_16bit_value() { + + status_test_codegen("TAC_LOAD (16 bit addr, 16 bit value)"); + + const uint16_t addr = 0x0103; + const uint16_t fixed_value = 0x2087; + + common(addr, fixed_value, true); } diff --git a/compiler/test/avr_code_gen/compile_ir/test_compile_tac_load_const_addr.c b/compiler/test/avr_code_gen/compile_ir/test_compile_tac_load_const_addr.c index 404543ff..d79cb482 100644 --- a/compiler/test/avr_code_gen/compile_ir/test_compile_tac_load_const_addr.c +++ b/compiler/test/avr_code_gen/compile_ir/test_compile_tac_load_const_addr.c @@ -1,11 +1,8 @@ #include -#include #include #include "libvmcu/libvmcu_system.h" -#include "libvmcu/libvmcu_analyzer.h" -#include "avr_code_gen/cg_avr.h" #include "avr_code_gen/cg_avr_basic_block.h" #include "tac/tacbuffer.h" @@ -15,31 +12,80 @@ #include "test_compile_tac.h" -void test_compile_tac_load_const_addr() { +static void common(const uint16_t addr, const uint16_t fixed_value, bool wide) { - status_test_codegen("TAC_LOAD_CONST_ADDR"); + const uint8_t redzone = 0xff; + + struct TACBuffer* b = tacbuffer_ctor(); + + tacbuffer_append(b, makeTACConst(1, 0xf1f1)); + tacbuffer_append(b, makeTACLoadConstAddr(1, addr)); + tacbuffer_append(b, makeTACReturn(1)); + + vmcu_system_t* system = prepare_vmcu_system_from_tacbuffer_with_redzone(b, addr, redzone); + + //write value to be read later + vmcu_system_write_data(system, addr, fixed_value & 0xff); + if (wide) { + vmcu_system_write_data(system, addr + 1, (fixed_value >> 8) & 0xff); + } + + vmcu_system_step_n(system, 10); + + uint16_t value; + if (wide) { + value = vmcu_system_read_2_gpr(system, 0); + } else { + value = vmcu_system_read_gpr(system, 0); + } + + if (value != fixed_value) { + printf("[0x%x] (may read 2 bytes) = 0x%x, expected 0x%x\n", addr, value, fixed_value); + } + + assert(value == fixed_value); + + assert_redzone(system, addr, (wide) ? 2 : 1, redzone); + + vmcu_system_dtor(system); +} + +void test_compile_tac_load_const_addr_case_8bit_value_0x55() { + + status_test_codegen("TAC_LOAD_CONST_ADDR (8 bit value = 0x55)"); const uint16_t addr = 0x100 + 17; + const uint8_t fixed_value = 0x55; - for (int8_t fixed_value = 0x55; fixed_value < 0x65; fixed_value += 2) { + common(addr, fixed_value, false); +} - struct TACBuffer* b = tacbuffer_ctor(); +void test_compile_tac_load_const_addr_case_8bit_value_0x56() { - tacbuffer_append(b, makeTACConst(1, 0x00)); - tacbuffer_append(b, makeTACLoadConstAddr(1, addr)); - tacbuffer_append(b, makeTACReturn(1)); + status_test_codegen("TAC_LOAD_CONST_ADDR (8 bit value = 0x56)"); - vmcu_system_t* system = prepare_vmcu_system_from_tacbuffer(b); + const uint16_t addr = 0x100 + 17; + const uint8_t fixed_value = 0x56; - //write value to be read later - vmcu_system_write_data(system, addr, fixed_value); + common(addr, fixed_value, false); +} - vmcu_system_step_n(system, 10); +void test_compile_tac_load_const_addr_case_16bit_value_0x1234() { - int8_t r0 = vmcu_system_read_gpr(system, 0); + status_test_codegen("TAC_LOAD_CONST_ADDR (16 bit value = 0x1234)"); - assert(r0 == fixed_value); + const uint16_t addr = 0x100 + 17; + const uint16_t fixed_value = 0x1234; - vmcu_system_dtor(system); - } + common(addr, fixed_value, true); +} + +void test_compile_tac_load_const_addr_case_16bit_value_0x4321() { + + status_test_codegen("TAC_LOAD_CONST_ADDR (16 bit value = 0x4321)"); + + const uint16_t addr = 0x100 + 17; + const uint16_t fixed_value = 0x4321; + + common(addr, fixed_value, true); } diff --git a/compiler/test/avr_code_gen/compile_ir/test_compile_tac_param.c b/compiler/test/avr_code_gen/compile_ir/test_compile_tac_param.c index ace06bd6..102416f7 100644 --- a/compiler/test/avr_code_gen/compile_ir/test_compile_tac_param.c +++ b/compiler/test/avr_code_gen/compile_ir/test_compile_tac_param.c @@ -86,8 +86,8 @@ void test_compile_tac_param_case_16bit() { assert(sp == sp_old - 2); //assert that fixed_value is on the stack - assert((uint8_t)vmcu_system_read_data(system, sp_old - 1) == 0x0a); - assert((uint8_t)vmcu_system_read_data(system, sp_old) == 0xbc); + assert((uint8_t)vmcu_system_read_data(system, sp_old) == 0x0a); + assert((uint8_t)vmcu_system_read_data(system, sp_old - 1) == 0xbc); vmcu_system_dtor(system); } diff --git a/compiler/test/avr_code_gen/compile_ir/test_compile_tac_return.c b/compiler/test/avr_code_gen/compile_ir/test_compile_tac_return.c index d845ead7..6ffb73c2 100644 --- a/compiler/test/avr_code_gen/compile_ir/test_compile_tac_return.c +++ b/compiler/test/avr_code_gen/compile_ir/test_compile_tac_return.c @@ -1,9 +1,9 @@ #include -#include +//#include #include #include "libvmcu/libvmcu_system.h" -#include "libvmcu/libvmcu_analyzer.h" +//#include "libvmcu/libvmcu_analyzer.h" #include "avr_code_gen/cg_avr.h" #include "avr_code_gen/cg_avr_basic_block.h" @@ -15,27 +15,94 @@ #include "test_compile_tac.h" -void test_compile_tac_return() { +void test_compile_tac_return_case_8bit_0x54() { - status_test_codegen("TAC_RETURN"); + status_test_codegen("TAC_RETURN (8 bit value = 0x54)"); - for (int8_t value = 0x54; value < 0x58; value++) { + const int8_t value = 0x54; - struct TACBuffer* b = tacbuffer_ctor(); + struct TACBuffer* b = tacbuffer_ctor(); - tacbuffer_append(b, makeTACSetupSP()); - tacbuffer_append(b, makeTACConst(0, value + 1)); - tacbuffer_append(b, makeTACConst(1, value)); - tacbuffer_append(b, makeTACConst(2, value - 1)); - tacbuffer_append(b, makeTACReturn(1)); + tacbuffer_append(b, makeTACSetupSP()); + tacbuffer_append(b, makeTACConst(0, value + 1)); + tacbuffer_append(b, makeTACConst(1, value)); + tacbuffer_append(b, makeTACConst(2, value - 1)); + tacbuffer_append(b, makeTACReturn(1)); - vmcu_system_t* system = prepare_vmcu_system_from_tacbuffer(b); + vmcu_system_t* system = prepare_vmcu_system_from_tacbuffer(b); - vmcu_system_step_n(system, 8); + vmcu_system_step_n(system, 8); - //returned value should be in r0 - assert(vmcu_system_read_gpr(system, 0) == value); + assert(vmcu_system_read_gpr(system, 0) == value); - vmcu_system_dtor(system); - } + vmcu_system_dtor(system); +} + +void test_compile_tac_return_case_8bit_0x55() { + + status_test_codegen("TAC_RETURN (8 bit value = 0x55)"); + + const int8_t value = 0x55; + + struct TACBuffer* b = tacbuffer_ctor(); + + tacbuffer_append(b, makeTACSetupSP()); + tacbuffer_append(b, makeTACConst(0, value + 1)); + tacbuffer_append(b, makeTACConst(1, value)); + tacbuffer_append(b, makeTACConst(2, value - 1)); + tacbuffer_append(b, makeTACReturn(1)); + + vmcu_system_t* system = prepare_vmcu_system_from_tacbuffer(b); + + vmcu_system_step_n(system, 8); + + assert(vmcu_system_read_gpr(system, 0) == value); + + vmcu_system_dtor(system); +} + +void test_compile_tac_return_case_16bit_0x5432() { + + status_test_codegen("TAC_RETURN (16 bit value = 0x5432)"); + + const uint16_t value = 0x5432; + + struct TACBuffer* b = tacbuffer_ctor(); + + tacbuffer_append(b, makeTACSetupSP()); + tacbuffer_append(b, makeTACConst(0, value + 1)); + tacbuffer_append(b, makeTACConst(1, value)); + tacbuffer_append(b, makeTACConst(2, value - 1)); + tacbuffer_append(b, makeTACReturn(1)); + + vmcu_system_t* system = prepare_vmcu_system_from_tacbuffer(b); + + vmcu_system_step_n(system, 12); + + assert(vmcu_system_read_2_gpr(system, 0) == value); + + vmcu_system_dtor(system); +} + +void test_compile_tac_return_case_16bit_0x4321() { + + status_test_codegen("TAC_RETURN (16 bit value = 0x4321)"); + + const uint16_t value = 0x4321; + + struct TACBuffer* b = tacbuffer_ctor(); + + tacbuffer_append(b, makeTACSetupSP()); + tacbuffer_append(b, makeTACConst(0, value + 1)); + tacbuffer_append(b, makeTACConst(1, value)); + tacbuffer_append(b, makeTACConst(2, value - 1)); + tacbuffer_append(b, makeTACReturn(1)); + + vmcu_system_t* system = prepare_vmcu_system_from_tacbuffer(b); + + vmcu_system_step_n(system, 12); + + assert(vmcu_system_read_2_gpr(system, 0) == value); + + vmcu_system_dtor(system); } diff --git a/compiler/test/avr_code_gen/compile_ir/test_compile_tac_store.c b/compiler/test/avr_code_gen/compile_ir/test_compile_tac_store.c index d40f56c7..2890f65a 100644 --- a/compiler/test/avr_code_gen/compile_ir/test_compile_tac_store.c +++ b/compiler/test/avr_code_gen/compile_ir/test_compile_tac_store.c @@ -15,9 +15,9 @@ #include "test_compile_tac.h" -static vmcu_system_t* common(uint16_t addr, int16_t value); +static vmcu_system_t* common(uint16_t addr, int16_t value, uint8_t redzone); -static vmcu_system_t* common(uint16_t addr, int16_t value) { +static vmcu_system_t* common(uint16_t addr, int16_t value, uint8_t redzone) { struct TACBuffer* b = tacbuffer_ctor(); @@ -25,54 +25,85 @@ static vmcu_system_t* common(uint16_t addr, int16_t value) { tacbuffer_append(b, makeTACConst(2, addr)); tacbuffer_append(b, makeTACStore(2, 1)); - tacbuffer_append(b, makeTACReturn(1)); - - vmcu_system_t* system = prepare_vmcu_system_from_tacbuffer(b); + vmcu_system_t* system = prepare_vmcu_system_from_tacbuffer_with_redzone(b, addr, redzone); vmcu_system_step_n(system, 10); return system; } -void test_compile_tac_store_case_8bit_value_8bit_addr() { +void test_compile_tac_store_case_8bit_value_8bit_addr_c7() { - status_test_codegen("TAC_STORE (8 bit value, 8 bit addr)"); + status_test_codegen("TAC_STORE (8 bit value, 8 bit addr = 0xc7)"); - for (uint16_t addr = 0xc7; addr < 0xcb; addr++) { + const uint16_t addr = 0xc7; + const uint8_t fixed_value = 0x2; + const uint8_t redzone = 0xff; - for (int8_t fixed_value = 1; fixed_value < 3; fixed_value++) { + vmcu_system_t* system = common(addr, fixed_value, redzone); - vmcu_system_t* system = common(addr, fixed_value); + const uint8_t stored = vmcu_system_read_data(system, addr); - const int8_t stored = vmcu_system_read_data(system, addr); + assert_redzone(system, addr, 1, redzone); - assert(stored == fixed_value); + vmcu_system_dtor(system); +} - vmcu_system_dtor(system); - } - } +void test_compile_tac_store_case_8bit_value_8bit_addr_c8() { + + status_test_codegen("TAC_STORE (8 bit value, 8 bit addr = 0xc8)"); + + const uint16_t addr = 0xc8; + const uint8_t fixed_value = 0x2; + const uint8_t redzone = 0xff; + + vmcu_system_t* system = common(addr, fixed_value, redzone); + + const uint8_t stored = vmcu_system_read_data(system, addr); + + assert(stored == fixed_value); + + assert_redzone(system, addr, 1, redzone); + + vmcu_system_dtor(system); } -void test_compile_tac_store_case_16bit_value_8bit_addr() { +void test_compile_tac_store_case_16bit_value_8bit_addr_c7_f03() { - status_test_codegen("TAC_STORE (16 bit value, 8 bit addr)"); + status_test_codegen("TAC_STORE (16 bit value = 0xf03, 8 bit addr = 0xc7)"); - for (uint16_t addr = 0xc7; addr < 0xcb; addr++) { + const uint8_t redzone = 0xff; + const uint16_t addr = 0xc7; + const uint16_t fixed_value = 0x0f03; - for (uint16_t fixed_value = 0x0f00; fixed_value < 0x0f03; fixed_value++) { + vmcu_system_t* system = common(addr, fixed_value, redzone); - vmcu_system_t* system = common(addr, fixed_value); + const uint16_t stored = vmcu_system_read_data16(system, addr); - const uint8_t low = vmcu_system_read_data(system, addr); - const uint8_t high = vmcu_system_read_data(system, addr + 1); + assert(stored == fixed_value); - const int16_t stored = (high << 8) | low; + assert_redzone(system, addr, 2, redzone); - assert(stored == fixed_value); + vmcu_system_dtor(system); +} - vmcu_system_dtor(system); - } - } +void test_compile_tac_store_case_16bit_value_8bit_addr_c8_f03() { + + status_test_codegen("TAC_STORE (16 bit value = 0xf03, 8 bit addr = 0xc8)"); + + const uint8_t redzone = 0xff; + const uint16_t addr = 0xc7; + const uint16_t fixed_value = 0x0f03; + + vmcu_system_t* system = common(addr, fixed_value, redzone); + + const uint16_t stored = vmcu_system_read_data16(system, addr); + + assert(stored == fixed_value); + + assert_redzone(system, addr, 2, redzone); + + vmcu_system_dtor(system); } void test_compile_tac_store_case_8bit_value_16bit_addr() { @@ -80,10 +111,11 @@ void test_compile_tac_store_case_8bit_value_16bit_addr() { status_test_codegen("TAC_STORE (8 bit value, 16 bit addr)"); const uint16_t addr = 1200; + const uint8_t redzone = 0xff; for (int8_t fixed_value = 1; fixed_value < 3; fixed_value++) { - vmcu_system_t* system = common(addr, fixed_value); + vmcu_system_t* system = common(addr, fixed_value, redzone); const int8_t stored = vmcu_system_read_data(system, addr); @@ -98,15 +130,13 @@ void test_compile_tac_store_case_16bit_value_16bit_addr() { status_test_codegen("TAC_STORE (16 bit value, 16 bit addr)"); const uint16_t addr = 1200; + const uint8_t redzone = 0xff; for (uint16_t fixed_value = 0x0f00; fixed_value < 0x0f03; fixed_value++) { - vmcu_system_t* system = common(addr, fixed_value); - - const uint8_t low = vmcu_system_read_data(system, addr); - const uint8_t high = vmcu_system_read_data(system, addr + 1); + vmcu_system_t* system = common(addr, fixed_value, redzone); - const int16_t stored = (high << 8) | low; + const uint16_t stored = vmcu_system_read_data16(system, addr); assert(stored == fixed_value); diff --git a/compiler/test/avr_code_gen/compile_ir/test_compile_tac_store_const_addr.c b/compiler/test/avr_code_gen/compile_ir/test_compile_tac_store_const_addr.c index 455f99cc..1b6786e6 100644 --- a/compiler/test/avr_code_gen/compile_ir/test_compile_tac_store_const_addr.c +++ b/compiler/test/avr_code_gen/compile_ir/test_compile_tac_store_const_addr.c @@ -15,30 +15,70 @@ #include "test_compile_tac.h" -void test_compile_tac_store_const_addr() { +static void common(const uint16_t addr, const uint16_t fixed_value, bool wide) { - status_test_codegen("TAC_STORE_CONST_ADDR"); + //const uint16_t addr = 0x118; + //const uint8_t fixed_value = 0x44; + const uint8_t redzone = 0xff; - for (uint16_t addr = 0x118; addr < 0x140; addr += 5) { + struct TACBuffer* b = tacbuffer_ctor(); - const int8_t fixed_value = 0x44; + tacbuffer_append(b, makeTACConst(1, fixed_value)); + tacbuffer_append(b, makeTACStoreConstAddr(addr, 1)); - struct TACBuffer* b = tacbuffer_ctor(); + vmcu_system_t* system = prepare_vmcu_system_from_tacbuffer_with_redzone(b, addr, redzone); - tacbuffer_append(b, makeTACConst(1, fixed_value)); - tacbuffer_append(b, makeTACStoreConstAddr(addr, 1)); - tacbuffer_append(b, makeTACReturn(1)); + vmcu_system_step_n(system, 10); - vmcu_system_t* system = prepare_vmcu_system_from_tacbuffer(b); + uint16_t value; + if (wide) { + value = vmcu_system_read_data16(system, addr); + } else { + value = vmcu_system_read_data(system, addr); + } - vmcu_system_step_n(system, 10); + if (value != fixed_value) { + printf("[0x%x] == 0x%x, expected 0x%x\n", addr, value, fixed_value); + } - //check that the value was written + //check that the value was written + assert(value == fixed_value); - int8_t value = vmcu_system_read_data(system, addr); + assert_redzone(system, addr, (wide) ? 2 : 1, redzone); - assert(value == fixed_value); + vmcu_system_dtor(system); +} +void test_compile_tac_store_const_addr_case_8bit_value_addr_0x118() { - vmcu_system_dtor(system); - } + status_test_codegen("TAC_STORE_CONST_ADDR (8 bit value, address = 0x118)"); + + const uint16_t addr = 0x118; + const uint8_t fixed_value = 0x44; + common(addr, fixed_value, false); +} + +void test_compile_tac_store_const_addr_case_8bit_value_addr_0x119() { + + status_test_codegen("TAC_STORE_CONST_ADDR (8 bit value, address = 0x119)"); + + const uint16_t addr = 0x119; + const uint8_t fixed_value = 0x45; + common(addr, fixed_value, false); +} +void test_compile_tac_store_const_addr_case_16bit_value_addr_0x118() { + + status_test_codegen("TAC_STORE_CONST_ADDR (16 bit value, address = 0x118)"); + + const uint16_t addr = 0x118; + const uint16_t fixed_value = 0x4567; + common(addr, fixed_value, true); +} + +void test_compile_tac_store_const_addr_case_16bit_value_addr_0x119() { + + status_test_codegen("TAC_STORE_CONST_ADDR (16 bit value, address = 0x119)"); + + const uint16_t addr = 0x119; + const uint16_t fixed_value = 0x5678; + common(addr, fixed_value, true); } diff --git a/compiler/test/avr_code_gen/compile_ir/test_compile_tac_unary_op.c b/compiler/test/avr_code_gen/compile_ir/test_compile_tac_unary_op.c index a2f581e4..050a1a1f 100644 --- a/compiler/test/avr_code_gen/compile_ir/test_compile_tac_unary_op.c +++ b/compiler/test/avr_code_gen/compile_ir/test_compile_tac_unary_op.c @@ -55,10 +55,7 @@ void test_compile_tac_unary_op_case_minus_16bit() { vmcu_system_step_n(system, 20); - const uint8_t r0 = vmcu_system_read_gpr(system, 0); - const uint8_t r1 = vmcu_system_read_gpr(system, 1); - - int16_t actual = (r1 << 8) | r0; + int16_t actual = (int16_t)vmcu_system_read_2_gpr(system, 0); assert(actual == -start); @@ -132,10 +129,7 @@ void test_compile_tac_unary_op_case_bitwise_neg_16bit() { vmcu_system_step_n(system, 10); - const uint8_t r0 = vmcu_system_read_gpr(system, 0); - const uint8_t r1 = vmcu_system_read_gpr(system, 1); - - const uint16_t actual = (r1 << 8) | r0; + const uint16_t actual = vmcu_system_read_2_gpr(system, 0); assert(actual == expect); diff --git a/compiler/test/avr_code_gen/test_avr_code_gen_util.c b/compiler/test/avr_code_gen/test_avr_code_gen_util.c index 812d244f..b9fc873b 100644 --- a/compiler/test/avr_code_gen/test_avr_code_gen_util.c +++ b/compiler/test/avr_code_gen/test_avr_code_gen_util.c @@ -1,4 +1,4 @@ - +#include #include #include #include "libvmcu/libvmcu_system.h" @@ -26,6 +26,38 @@ static void print_defs(FILE* fout); +void assert_redzone(vmcu_system_t* system, uint16_t addr, uint8_t width, uint8_t redzone) { + + assert(width <= 8); + + const uint16_t addr1 = addr - 1; + const uint16_t addr2 = addr + width; + + const uint8_t before = vmcu_system_read_data(system, addr1); + const uint8_t after = vmcu_system_read_data(system, addr2); + + if ((before != redzone) || (after != redzone)) { + for (uint16_t a = addr1 - 1; a <= addr2 + 1; a++) { + const uint8_t value = vmcu_system_read_data(system, a); + printf("[0x%x] = 0x%x\n", a, value); + } + } + assert(before == redzone); + assert(after == redzone); +} + +vmcu_system_t* prepare_vmcu_system_from_tacbuffer_with_redzone(struct TACBuffer* buffer, uint16_t addr_redzone, uint8_t redzone) { + vmcu_system_t* system = prepare_vmcu_system_from_tacbuffer(buffer); + + // fill the area with red zone to detect unintended writes + // and reads around the address + for (uint16_t a = addr_redzone - 2; a < addr_redzone + 4; a++) { + vmcu_system_write_data(system, a, redzone); + } + + return system; +} + vmcu_system_t* prepare_vmcu_system_from_tacbuffer(struct TACBuffer* buffer) { //create the file diff --git a/compiler/test/avr_code_gen/test_avr_code_gen_util.h b/compiler/test/avr_code_gen/test_avr_code_gen_util.h index 419a24b8..8181f081 100644 --- a/compiler/test/avr_code_gen/test_avr_code_gen_util.h +++ b/compiler/test/avr_code_gen/test_avr_code_gen_util.h @@ -13,4 +13,11 @@ struct TACBuffer; vmcu_system_t* prepare_vmcu_system_from_tacbuffer(struct TACBuffer* buffer); +// additionally creates a red zone around the given address, +// to be able to later check if any unintended writes or reads happened there +vmcu_system_t* prepare_vmcu_system_from_tacbuffer_with_redzone(struct TACBuffer* buffer, uint16_t addr_redzone, uint8_t redzone); + +// assert that the values around the address still have 'redzone' value +void assert_redzone(vmcu_system_t* system, uint16_t addr, uint8_t width, uint8_t redzone); + #endif diff --git a/compiler/test/gen_tac/test_gen_tac.h b/compiler/test/gen_tac/test_gen_tac.h index 70dae1ef..2f287649 100644 --- a/compiler/test/gen_tac/test_gen_tac.h +++ b/compiler/test/gen_tac/test_gen_tac.h @@ -71,9 +71,12 @@ void test_gen_tac_variable_case_2_member_access(); // call void test_gen_tac_call_case_no_args(); void test_gen_tac_call_case_1_args_return(); -void test_gen_tac_call_case_1_args_write(); +void test_gen_tac_call_case_1_args_write_8bit(); +void test_gen_tac_call_case_1_args_write_16bit(); void test_gen_tac_call_case_1_args_write_3fns(); void test_gen_tac_call_case_2_args(); +void test_gen_tac_call_case_frame_pointer_restored_after_call(); +void test_gen_tac_call_case_frame_pointer_restored_after_call_caller_has_locals(); // struct decl void test_gen_tac_structdecl_case_read_struct(); diff --git a/compiler/test/gen_tac/test_gen_tac_assignstmt.c b/compiler/test/gen_tac/test_gen_tac_assignstmt.c index 752a3a57..db4487b0 100644 --- a/compiler/test/gen_tac/test_gen_tac_assignstmt.c +++ b/compiler/test/gen_tac/test_gen_tac_assignstmt.c @@ -40,11 +40,7 @@ void test_gen_tac_assignstmt_case_local_int_16bit() { vmcu_system_step_n(system, 30); - //assert that value is returned in r0 as it should be - - uint8_t value1_low = vmcu_system_read_gpr(system, 0); - uint8_t value1_high = vmcu_system_read_gpr(system, 1); - const uint16_t value1 = (value1_high << 8) | value1_low; + const uint16_t value1 = vmcu_system_read_2_gpr(system, 0); assert(value1 == value); diff --git a/compiler/test/gen_tac/test_gen_tac_call.c b/compiler/test/gen_tac/test_gen_tac_call.c index 2f917ff9..54f96dc2 100644 --- a/compiler/test/gen_tac/test_gen_tac_call.c +++ b/compiler/test/gen_tac/test_gen_tac_call.c @@ -55,9 +55,84 @@ void test_gen_tac_call_case_1_args_return() { vmcu_system_dtor(system); } -void test_gen_tac_call_case_1_args_write() { +void test_gen_tac_call_case_frame_pointer_restored_after_call() { - status_test_codegen_tac("Call - 1 args - write to SRAM"); + status_test_codegen_tac("Call - frame pointer YL:YH restored after call (caller has no locals)"); + + char* template = "fn main()->int{ return f(3); }" + " fn f(uint8 a)->int{ " + "uint8 b = 83; " + "uint8 c = 3; " + "uint8 d = 4; " + "return b; " + "}"; + + vmcu_system_t* system = prepare_vmcu_system_from_code_snippet(template); + + vmcu_system_step_n(system, 50); + + const uint8_t r0 = vmcu_system_read_gpr(system, 0); + + assert(r0 == 83); + + uint16_t sp = vmcu_system_read_sp(system); + uint16_t y = vmcu_system_read_y(system); + + if (sp != y + 2) { + printf("sp=0x%x, Y=0x%x\n", sp, y); + } + + // This is because 'main' was not called, + // it is the first function to run after the initial boilerplate. + // So since we did return, SP will be higher by 2 + assert(sp == y + 2); + + vmcu_system_dtor(system); +} + +void test_gen_tac_call_case_frame_pointer_restored_after_call_caller_has_locals() { + + status_test_codegen_tac("Call - frame pointer YL:YH restored after call (caller has locals)"); + + char* template = "fn main()->int{ " + "uint8 x = 3; " + "return f(3); " + "} " + "fn f(uint8 a)->int{ " + "uint8 b = 73; " + "return b; " + "} "; + + vmcu_system_t* system = prepare_vmcu_system_from_code_snippet(template); + + vmcu_system_step_n(system, 50); + + const uint8_t r0 = vmcu_system_read_gpr(system, 0); + + assert(r0 == 73); + + uint16_t sp = vmcu_system_read_sp(system); + uint16_t y = vmcu_system_read_y(system); + + if (sp != y + 3) { + printf("sp=0x%x, Y=0x%x\n", sp, y); + } + + // This is because 'main' was not called, + // it is the first function to run after the initial boilerplate. + // So since we did return, SP will be higher by 2. + // And since the frame pointer YL:YH is created after space has been made on the stack + // for local variables + // (our frame pointer only ever applies offsets >= 0 for both locals and args), + // YL:YH will further be higher by 1 byte due to the uint8 local variable. + assert(sp == y + 3); + + vmcu_system_dtor(system); +} + +void test_gen_tac_call_case_1_args_write_8bit() { + + status_test_codegen_tac("Call - 1 args - write to SRAM (8 bit)"); const uint8_t expected = 0xab; @@ -76,6 +151,32 @@ void test_gen_tac_call_case_1_args_write() { vmcu_system_dtor(system); } +void test_gen_tac_call_case_1_args_write_16bit() { + + status_test_codegen_tac("Call - 1 args - write to SRAM (16 bit)"); + + const uint16_t expected = 0x5973; + + char snippet[200]; + char* template = "fn main()->int{ f(%d); return 0; } fn f(uint16 a)->int { [0x100]=a; return 0; }"; + sprintf(snippet, template, expected); + + vmcu_system_t* system = prepare_vmcu_system_from_code_snippet(snippet); + + vmcu_system_step_n(system, 50); + + const uint16_t actual = vmcu_system_read_data16(system, 0x100); + + if (actual != expected) { + printf("actual: 0x%x\n", actual); + printf("expected: 0x%x\n", expected); + } + + assert(actual == expected); + + vmcu_system_dtor(system); +} + void test_gen_tac_call_case_1_args_write_3fns() { status_test_codegen_tac("Call - 1 args - write to SRAM - 3 functions"); diff --git a/compiler/test/libvmcu_utils/libvmcu_utils.c b/compiler/test/libvmcu_utils/libvmcu_utils.c index 41f61e13..447f59d1 100644 --- a/compiler/test/libvmcu_utils/libvmcu_utils.c +++ b/compiler/test/libvmcu_utils/libvmcu_utils.c @@ -36,3 +36,18 @@ uint16_t vmcu_system_read_y(vmcu_system_t* system) { return (YH << 8 | YL); } + +uint16_t vmcu_system_read_data16(vmcu_system_t* system, uint16_t addr) { + + const uint8_t low = vmcu_system_read_data(system, addr); + const uint8_t high = vmcu_system_read_data(system, addr + 1); + + return (high << 8) | low; +} + +uint16_t vmcu_system_read_2_gpr(vmcu_system_t* system, const int low_reg) { + + const uint8_t low = vmcu_system_read_gpr(system, low_reg); + const uint8_t high = vmcu_system_read_gpr(system, low_reg + 1); + return (high << 8) | low; +} diff --git a/compiler/test/libvmcu_utils/libvmcu_utils.h b/compiler/test/libvmcu_utils/libvmcu_utils.h index 5db55f97..d675060b 100644 --- a/compiler/test/libvmcu_utils/libvmcu_utils.h +++ b/compiler/test/libvmcu_utils/libvmcu_utils.h @@ -12,4 +12,9 @@ uint16_t vmcu_system_read_sp(vmcu_system_t* system); uint16_t vmcu_system_read_y(vmcu_system_t* system); +uint16_t vmcu_system_read_data16(vmcu_system_t* system, uint16_t addr); + +// read 16 bit value from 2 adjacent gprs +uint16_t vmcu_system_read_2_gpr(vmcu_system_t* system, const int low_reg); + #endif diff --git a/compiler/test/testcases.c b/compiler/test/testcases.c index fcf745d3..7ef6e463 100644 --- a/compiler/test/testcases.c +++ b/compiler/test/testcases.c @@ -56,8 +56,14 @@ void (*tests_avr_codegen[])() = { test_compile_tac_const_value_test_8bit, test_compile_tac_const_value_test_16bit, - test_compile_tac_store_const_addr, - test_compile_tac_load_const_addr, + test_compile_tac_store_const_addr_case_8bit_value_addr_0x118, + test_compile_tac_store_const_addr_case_8bit_value_addr_0x119, + test_compile_tac_store_const_addr_case_16bit_value_addr_0x118, + test_compile_tac_store_const_addr_case_16bit_value_addr_0x119, + test_compile_tac_load_const_addr_case_8bit_value_0x55, + test_compile_tac_load_const_addr_case_8bit_value_0x56, + test_compile_tac_load_const_addr_case_16bit_value_0x1234, + test_compile_tac_load_const_addr_case_16bit_value_0x4321, //TAC_BINARY_OP_IMMEDIATE test_compile_tac_binary_op_immediate_case_add_8bit, @@ -141,7 +147,10 @@ void (*tests_avr_codegen[])() = { test_compile_tac_if_cmp_goto_case_ge_false_16bit, // TAC_RETURN - test_compile_tac_return, + test_compile_tac_return_case_8bit_0x54, + test_compile_tac_return_case_8bit_0x55, + test_compile_tac_return_case_16bit_0x5432, + test_compile_tac_return_case_16bit_0x4321, // TAC_COPY test_compile_tac_copy_case_8bit, @@ -153,19 +162,24 @@ void (*tests_avr_codegen[])() = { // TAC_CALL test_compile_tac_call_case_recurses, - test_compile_tac_call_case_returns_value, + test_compile_tac_call_case_returns_value_8bit, + test_compile_tac_call_case_returns_value_16bit, test_compile_tac_call_case_1_param, // TAC_SETUP_STACKFRAME test_compile_tac_setup_stackframe, // TAC_LOAD - test_compile_tac_load_case_8bit_addr, - test_compile_tac_load_case_16bit_addr, + test_compile_tac_load_case_8bit_addr_8bit_value, + test_compile_tac_load_case_8bit_addr_16bit_value, + test_compile_tac_load_case_16bit_addr_8bit_value, + test_compile_tac_load_case_16bit_addr_16bit_value, // TAC_STORE - test_compile_tac_store_case_8bit_value_8bit_addr, - test_compile_tac_store_case_16bit_value_8bit_addr, + test_compile_tac_store_case_8bit_value_8bit_addr_c7, + test_compile_tac_store_case_8bit_value_8bit_addr_c8, + test_compile_tac_store_case_16bit_value_8bit_addr_c7_f03, + test_compile_tac_store_case_16bit_value_8bit_addr_c8_f03, test_compile_tac_store_case_8bit_value_16bit_addr, test_compile_tac_store_case_16bit_value_16bit_addr, @@ -241,9 +255,12 @@ void (*tests_tac_codegen[])() = { // call test_gen_tac_call_case_no_args, test_gen_tac_call_case_1_args_return, - test_gen_tac_call_case_1_args_write, + test_gen_tac_call_case_1_args_write_8bit, + test_gen_tac_call_case_1_args_write_16bit, test_gen_tac_call_case_1_args_write_3fns, test_gen_tac_call_case_2_args, + test_gen_tac_call_case_frame_pointer_restored_after_call, + test_gen_tac_call_case_frame_pointer_restored_after_call_caller_has_locals, // struct decl test_gen_tac_structdecl_case_read_struct, diff --git a/compiler/test/typechecker/test_typechecker_util.c b/compiler/test/typechecker/test_typechecker_util.c index d176bf94..e1a7340a 100644 --- a/compiler/test/typechecker/test_typechecker_util.c +++ b/compiler/test/typechecker/test_typechecker_util.c @@ -36,7 +36,7 @@ struct TCError* typecheck_file(char* filename) { fill_tables(ast, ctx); - struct TCError* errors = typecheck_ast(ast, ctx_tables(ctx), false); + struct TCError* errors = typecheck_ast(ast, ctx, false); ctx_dtor(ctx); diff --git a/compiler/test/x86_code_gen/compile_ir/test_compile_tac_load.c b/compiler/test/x86_code_gen/compile_ir/test_compile_tac_load.c index 613acf3b..d5076854 100644 --- a/compiler/test/x86_code_gen/compile_ir/test_compile_tac_load.c +++ b/compiler/test/x86_code_gen/compile_ir/test_compile_tac_load.c @@ -30,7 +30,7 @@ static void test_fixed_value(uint64_t fixed_value, bool debug) { tacbuffer_append(b, makeTACConst(1, 0x00)); tacbuffer_append(b, makeTACConst(2, addr)); - tacbuffer_append(b, makeTACLoad(1, 2)); + tacbuffer_append(b, makeTACLoad(1, 2, 8)); struct sd_uc_engine* system = sd_uc_engine_from_tacbuffer_v2(b, debug); diff --git a/docs/html/tac.html b/docs/html/tac.html index 5fb40c20..75835657 100644 --- a/docs/html/tac.html +++ b/docs/html/tac.html @@ -231,7 +231,7 @@

Load/Store

t1 = [t2] TMP TMP - - + number of bytes to load (1 or 2) - - diff --git a/examples/Makefile b/examples/Makefile index 5880b1b3..edfa1d5e 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -9,15 +9,17 @@ all: test test: @echo "[Examples] Compiling Example Programs..." - $(CALL2) ifstatement/ifstatement.dg + $(CALL2) ifstatement/ifstatement.dg $(CALL2) local_variables/simple.dg - $(CALL2) loops/whileloop.dg - $(CALL2) loops/forloop.dg - $(CALL2) mathematics/fibonacci.dg - $(CALL2) methodCalls/methodcall.dg - $(CALL2) other/everything.dg + $(CALL2) loops/whileloop.dg + $(CALL2) loops/forloop.dg + $(CALL2) mathematics/fibonacci.dg + $(CALL2) methodCalls/methodcall.dg + $(CALL2) other/everything.dg $(CALL2) typeinference/localvartypeinference.dg $(CALL2) array/array.dg + $(MAKE) -C led_blink_timer + $(MAKE) -C led_blink_no_timer @echo "[Examples] done" diff --git a/examples/led_blink/Makefile b/examples/led_blink/Makefile deleted file mode 100644 index 2f321bad..00000000 --- a/examples/led_blink/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -help: - @echo "make timer, make notimer, make clean" - -timer: clean - sd -debug led_blink.dg ../../stdlib/portb.dg ../../stdlib/timer0.dg - sudo avrdude -c arduino -p atmega328p -P /dev/ttyACM0 -U flash:w:led_blink.hex - -notimer: - sd -debug led_blink_no_timer.dg - sudo avrdude -c arduino -p atmega328p -P /dev/ttyACM0 -U flash:w:led_blink_no_timer.hex -clean: - rm -f *.hex *.obj *.cof *.asm - diff --git a/examples/led_blink_no_timer/Makefile b/examples/led_blink_no_timer/Makefile new file mode 100644 index 00000000..b1998237 --- /dev/null +++ b/examples/led_blink_no_timer/Makefile @@ -0,0 +1,10 @@ +main: compile + +compile: + sd led_blink_no_timer.dg + +flash: + sudo avrdude -c arduino -p atmega328p -P /dev/ttyACM0 -U flash:w:led_blink_no_timer.hex +clean: + rm -f *.hex *.obj *.cof *.asm *.png *.dot + diff --git a/examples/led_blink/led_blink_no_timer.dg b/examples/led_blink_no_timer/led_blink_no_timer.dg similarity index 100% rename from examples/led_blink/led_blink_no_timer.dg rename to examples/led_blink_no_timer/led_blink_no_timer.dg diff --git a/examples/led_blink_timer/Makefile b/examples/led_blink_timer/Makefile new file mode 100644 index 00000000..a1f015c0 --- /dev/null +++ b/examples/led_blink_timer/Makefile @@ -0,0 +1,11 @@ +main: compile + +compile: clean + sd led_blink.dg ../../stdlib/avr/portb.dg ../../stdlib/avr/timer0.dg + +flash: + sudo avrdude -c arduino -p atmega328p -P /dev/ttyACM0 -U flash:w:led_blink.hex + +clean: + rm -f *.hex *.obj *.cof *.asm *.png *.dot + diff --git a/examples/led_blink/led_blink.dg b/examples/led_blink_timer/led_blink.dg similarity index 79% rename from examples/led_blink/led_blink.dg rename to examples/led_blink_timer/led_blink.dg index 43b08790..d42492a8 100644 --- a/examples/led_blink/led_blink.dg +++ b/examples/led_blink_timer/led_blink.dg @@ -18,18 +18,16 @@ D13 PIN -------------------| fn main () ~> int { //set D13 / PB5 - //set PORTB Data Direction Register (DDRB) to enable DDRB5 - //[0x24] = 0b00100000; - - //set everything to output - portb_ddrd(0xff); + portb_ddrd(0xff); // set everything to output while(true){ portb_write(0b00010000); delay(); + delay(); portb_write(0b00100000); delay(); + delay(); } return 1; } @@ -42,8 +40,7 @@ fn delay() -> int { timer0_mode(0x0); //TCCR0B = 0b00000101, set prescaler to 1024 - //timer0_prescaler(0b00000101); - [0x45] = 0x5; + timer0_prescaler(0x5); //while(TCNT0 != 0xfe){} while(timer0_read() != 0xfe){} diff --git a/examples/portb/Makefile b/examples/portb/Makefile new file mode 100644 index 00000000..c20f2569 --- /dev/null +++ b/examples/portb/Makefile @@ -0,0 +1,11 @@ +main: compile + +compile: clean + sd test_portb.dg ../../stdlib/avr/portb.dg + +flash: + sudo avrdude -c arduino -p atmega328p -P /dev/ttyACM0 -U flash:w:test_portb.hex + +clean: + rm -f *.hex *.obj *.cof *.asm *.png *.dot + diff --git a/examples/portb/test_portb.dg b/examples/portb/test_portb.dg new file mode 100644 index 00000000..57146f69 --- /dev/null +++ b/examples/portb/test_portb.dg @@ -0,0 +1,33 @@ +//Program to make an LED glow + +//Arduino Board: +//https://docs.arduino.cc/resources/datasheets/A000066-datasheet.pdf + +/* Hardware Setup + + GND ----- LED ----- Resistor + | +D13 PIN -------------------| + +*/ + +//LED_BUILTIN PB5 +//PB5 is on D13 on the Arduino + +fn main () ~> int { + //set D13 / PB5 + + //set PORTB Data Direction Register (DDRB) to enable DDRB5 + //[0x24] = 0b00100000; + + portb_ddrd(0xff); // set everything to output + + portb_write(0b00010000); + portb_write(0b00100000); + + while(true){ + + } + return 1; +} + diff --git a/examples/usart/Makefile b/examples/usart/Makefile new file mode 100644 index 00000000..e30ad8ac --- /dev/null +++ b/examples/usart/Makefile @@ -0,0 +1,14 @@ +main: compile + +compile: clean + sd \ + main.dg \ + ../../stdlib/avr/timer0.dg \ + ../../stdlib/avr/usart.dg + +flash: + sudo avrdude -c arduino -p atmega328p -P /dev/ttyACM0 -U flash:w:main.hex + +clean: + rm -f *.hex *.obj *.cof *.asm *.png *.dot + diff --git a/examples/usart/main.dg b/examples/usart/main.dg new file mode 100644 index 00000000..8d8bb8c5 --- /dev/null +++ b/examples/usart/main.dg @@ -0,0 +1,52 @@ +// for the atmega328p + +// to debug this, can use cheap AZ Delivery Logic Analyzer +// and following packages (arch linux) +// +// - sigrok-cli +// - sigrok-firmware-fx2lafw (this is needed so it correctly recognizes the logic analyzer) +// - pulseview (gui viewer) + +// in pulseview, add the decoder for USART, then specify: +// +// - baudrate 9600 +// - 8 data bits +// - even parity bit +// - 1 stop bit (even though we send 2, selecting that is not possible) +// - bit order is lsb-first +// - data format is hex for this example (sending increasing numbers) + +fn main () ~> int { + + usart_init(2400); + + uint8 c = 0; + while(true){ + c++; + usart_tx_char('h'); + usart_tx_char('e'); + usart_tx_char('l'); + usart_tx_char('l'); + usart_tx_char('o'); + delay(); + } + + return 0; +} + +fn delay() -> int { + + //using Timer0 + + //TCCR0A = 0x0, set timer mode + timer0_mode(0x0); + + //TCCR0B = 0b00000101, set prescaler to 1024 + timer0_prescaler(0x5); + + //while(TCNT0 != 0xfe){} + while(timer0_read() != 0xfe){} + + return 1; +} + diff --git a/format-code.sh b/format-code.sh index 6ae22cfb..a22eccd1 100755 --- a/format-code.sh +++ b/format-code.sh @@ -6,7 +6,7 @@ SCRIPT_DIR=$(realpath $(dirname $0)) echo "running from" $SCRIPT_DIR -SRC=$(find $SCRIPT_DIR -type d \( -name 'build' -o -name 'dependencies' \) -prune -o \( -name '*.c' -o -name '*.h' \) -print) +SRC=$(find $SCRIPT_DIR -type d \( -name 'build' -o -name 'dependencies' -o -name 'stdlib' -o -name 'examples' \) -prune -o \( -name '*.c' -o -name '*.h' \) -print) echo $SRC diff --git a/stdlib/Makefile b/stdlib/Makefile index aae81479..1955f88d 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -3,7 +3,7 @@ TESTS := tests/test_matrix.dg \ #tests/test_math.dg \ #tests/collections/test_intbintree.dg \ #tests/collections/test_arraylist.dg \ - #tests/collections/test_linkedlist.dg + #tests/collections/test_linkedlist.dg \ #tests/collections/test_array.dg \ #tests/test_primes.dg \ #tests/test_polynomial.dg \ @@ -11,19 +11,25 @@ TESTS := tests/test_matrix.dg \ #tests/collections/test_stack.dg \ SOURCES := test.dg \ - #math.dg \ - #collections/intbintree.dg \ - #collections/linkedlist.dg \ - #collections/arraylist.dg - #collections/array.dg \ - #primes.dg \ - #polynomial.dg \ - #collections/set.dg \ - #collections/stack.dg \ + collections/linkedlist.dg \ + collections/arraylist.dg \ + collections/array.dg \ + collections/set.dg \ + collections/stack.dg \ + collections/intbintree.dg \ + base/math.dg \ + base/primes.dg \ + base/polynomial.dg \ + avr/portb.dg \ + avr/timer0.dg \ test: $(SOURCES) clean - sd $(SOURCES) + sd $(SOURCES) + +debug: $(SOURCES) clean + sd -debug $(SOURCES) clean: - rm -f a.out - rm -f *.c + rm -f a.out + rm -f *.c *.asm *.hex *.obj + rm -f *.dot *.png diff --git a/stdlib/portb.dg b/stdlib/avr/portb.dg similarity index 66% rename from stdlib/portb.dg rename to stdlib/avr/portb.dg index 3f2fcaad..905188fa 100644 --- a/stdlib/portb.dg +++ b/stdlib/avr/portb.dg @@ -2,13 +2,13 @@ // PORTB 0x25 // DDRB 0x24 -fn portb_ddrd(uint16 value) -> int { +fn portb_ddrd(uint8 value) -> int { [0x24] = value; return 0; } -fn portb_write(uint16 value) -> int { +fn portb_write(uint8 value) -> int { [0x25] = value; return 0; diff --git a/stdlib/timer0.dg b/stdlib/avr/timer0.dg similarity index 100% rename from stdlib/timer0.dg rename to stdlib/avr/timer0.dg diff --git a/stdlib/avr/usart.dg b/stdlib/avr/usart.dg new file mode 100644 index 00000000..7038d56e --- /dev/null +++ b/stdlib/avr/usart.dg @@ -0,0 +1,89 @@ +// wip usart driver for the atmega328p + +fn usart_tx_char (char c) ~> uint8 { + + usart_tx_wait_udre(); + [0xc6] = c; +} + +fn usart_tx (uint8 c) ~> uint8 { + + usart_tx_wait_udre(); + + // put data into transmit buffer (UDR0) + [0xc6] = c; + + return 0; +} + +fn usart_tx_wait_udre() ~> uint8 { + + uint8 ucsr0a = [0xc0]; // UCSR0A + // look at UDRE0 (USART data register empty) + + // UCSR0A: RXC0 TXC0 UDRE0 FE0 DOR0 UPE0 U2X0 MPCM0 + while ((ucsr0a & 0b100000) == 0){ + ucsr0a = [0xc0]; + } + + return 0; +} + +fn usart_calc_ubrr0(uint16 baudrate) ~> uint16 { + // assuming clock of 16 MHz + // only listing the most common values here + // reference table 24-7 (Examples of UBRRn) + if (baudrate == 2400) { return 416; } + if (baudrate == 4800) { return 207; } + if (baudrate == 9600) { return 103; } + if (baudrate == 14400) { return 68; } + if (baudrate == 19200) { return 51; } + if (baudrate == 115200) { return 8; } + + return 103; // default 9600 baud +} + +fn usart_init_baudrate(uint16 baudrate) ~> uint8 { + // int(16000000/(16*9600)) -1 + // = 1000000 / 9600 - 1 + // = 104 - 1 = 103 + + uint16 value = usart_calc_ubrr0(baudrate); + + // UBRR0L = 0xc4 + // UBRR0H = 0xc5 + [0xc4] = value & 0xff; + [0xc5] = (value >> 8) & 0xff; + + return 0; +} + +fn usart_set_ucsr0b () ~> uint8 { + // UCSR0B: RXCIE0 TXCIE0 UDRIE0 RXEN0 TXEN0 UCSZ02 RXB80 TXB80 + + // enable receiver and transmitter + // UCSR0B = (1 << RXEN0) | (1 << TXEN0) + //[0xc1] = (1 << 4) | (1 << 3); + [0xc1] = 0b01000; + + return 0; +} + +fn usart_set_ucsr0c () ~> uint8 { + // UCSR0C: UMSEL01 UMSEL00 UPM01 UPM00 USBS0 (UCSZ01 / UDORD0) (UCSZ00 / UCPHA0) UCPOL0 + + // set frame format: 8 data, 2 stop bit + // UCSR0C = (1 << USBS0) | (3 << UCSZ00) + [0xc2] = 0b00101110; + + return 0; +} + +fn usart_init (uint16 baudrate) ~> uint8 { + usart_init_baudrate(baudrate); + usart_set_ucsr0b(); + usart_set_ucsr0c(); + + return 0; +} + diff --git a/stdlib/math.dg b/stdlib/base/math.dg similarity index 89% rename from stdlib/math.dg rename to stdlib/base/math.dg index a5724bd7..9d0156d0 100644 --- a/stdlib/math.dg +++ b/stdlib/base/math.dg @@ -42,7 +42,7 @@ fn min (int a,int b) -> int { if a < b {return a;} return b; } -/* + fn gcd (int a, int b) -> int { if a==0 {return b;} return gcd(mod(b,a), a); @@ -60,30 +60,30 @@ fn mod(int a, int b) -> int { } fn div(int a, int b) -> int { - + //TODO x=0; return x; } -*/ + @halts fn fib(uint n) -> uint { uint a = 0; uint b = 1; - + for i in 1 .. (n-1) { - + uint k = a+b; a = b; b = k; } - + return a; } @halts -fn iseven(int x) -> bool { return x & 0x01 == 0; } +fn iseven(int x) -> bool { return (x & 0x01) == 0; } @halts -fn isodd(int x) -> bool { return x & 0x01 == 1; } +fn isodd(int x) -> bool { return (x & 0x01) == 1; } diff --git a/stdlib/polynomial.dg b/stdlib/base/polynomial.dg similarity index 100% rename from stdlib/polynomial.dg rename to stdlib/base/polynomial.dg diff --git a/stdlib/primes.dg b/stdlib/base/primes.dg similarity index 98% rename from stdlib/primes.dg rename to stdlib/base/primes.dg index 58c3bca2..43ba5a62 100644 --- a/stdlib/primes.dg +++ b/stdlib/base/primes.dg @@ -3,11 +3,11 @@ @halts fn isprime(uint n) -> bool { - + uint count = 0; for k in 1 .. n { - + if mod(n, k) == 0 { count++; } } diff --git a/stdlib/collections/array.dg b/stdlib/collections/array.dg index 3e7b5b23..ffa2980a 100644 --- a/stdlib/collections/array.dg +++ b/stdlib/collections/array.dg @@ -1,21 +1,7 @@ #include //simple functions dealing with arrays of integers -fn array_reduce( - [?T0] arr, - uint size, - ((?T0, ?T0) -> ?T0) reducer, - ?T0 initial -) -> ?T0 { - - ?T0 current = initial; - for i in 0 .. (size - 1) { - current = reducer(current, arr[i]); - } - return current; -} - -fn array_contains([?T0] arr, uint size, ?T0 elem) -> bool { +fn array_contains([int] arr, uint size, int elem) -> bool { for i in 0 .. (size - 1) { if arr[i] == elem { return true; } diff --git a/stdlib/collections/arraylist.dg b/stdlib/collections/arraylist.dg index e5477808..21a0a253 100644 --- a/stdlib/collections/arraylist.dg +++ b/stdlib/collections/arraylist.dg @@ -1,23 +1,23 @@ -struct ArrayList { +struct ArrayList { - @private [?T0] arr; + @private [int] arr; @private uint size; @private uint capacity; } -fn arraylist_size(ArrayList list) -> uint { +fn arraylist_size(ArrayList list) -> uint { return list.size; } -fn arraylist_at(ArrayList list, uint index) -> ?T0 { - +fn arraylist_at(ArrayList list, uint index) -> int { + return list.arr[index]; } -fn arraylist_contains(ArrayList list, ?T0 elem) -> bool { +fn arraylist_contains(ArrayList list, int elem) -> bool { for i in 0 .. (list.size - 1) { if list.arr[i] == elem { return true; } @@ -25,15 +25,15 @@ fn arraylist_contains(ArrayList list, ?T0 elem) -> bool { return false; } -fn arraylist_index_of(ArrayList list, ?T0 elem) -> int { - +fn arraylist_index_of(ArrayList list, int elem) -> int { + for i in 0 .. (list.size - 1) { if list.arr[i] == elem { return i; } } return -1; } -fn arraylist_clear(ArrayList list) ~> bool { +fn arraylist_clear(ArrayList list) ~> bool { list.size = 0; return true; } diff --git a/stdlib/collections/intbintree.dg b/stdlib/collections/intbintree.dg index f09f60d1..5819ecdc 100644 --- a/stdlib/collections/intbintree.dg +++ b/stdlib/collections/intbintree.dg @@ -1,36 +1,35 @@ -#include //an implementation of a binary tree for integers -struct IntBinTree { +struct IntBinTree { @private bool has_root; @private - IntBinTreeNode root; + IntBinTreeNode root; } @private struct IntBinTreeNode { int key; - + bool has_left; IntBinTreeNode left; - + bool has_right; IntBinTreeNode right; } fn intbintree_contains(IntBinTree t, int key) -> bool { - + return intbintreenode_contains(t.root, key); } fn intbintree_size(IntBinTree t) -> uint { if !t.has_root { return 0; } - + return intbintreenode_size(t.root); } @@ -46,22 +45,22 @@ fn intbintree_visit (IntBinTree t, ( (int)->bool ) visitor) -> bool { fn intbintreenode_contains(IntBinTreeNode t, int key) -> bool { current = t; - + while true { - switch compare(key, current.key) { - case 0 { return true; } - case -1 { - if !current.has_left { return false; } - current = current.left; - } - case 1 { - if !current.has_right { return false; } - current = current.right; - } + int c = compare(key, current.key); + + if c == 0 { return true; } + if c == -1 { + if !current.has_left { return false; } + current = current.left; + } + if c == 1 { + if !current.has_right { return false; } + current = current.right; } } - + return false; } @@ -69,20 +68,20 @@ fn intbintreenode_contains(IntBinTreeNode t, int key) -> bool { fn intbintreenode_size(IntBinTreeNode t) -> uint { res = 1; - + if t.has_left { res += intbintreenode_size(t.left); - } + } if t.has_right { res += intbintreenode_size(t.right); } - + return res; } @private fn intbintreenode_visit(IntBinTreeNode t, ((int)->bool) visitor) -> bool { - + if t.has_left { intbintreenode_visit(t.left, visitor); } @@ -90,7 +89,7 @@ fn intbintreenode_visit(IntBinTreeNode t, ((int)->bool) visitor) -> bool { if t.has_right { intbintreenode_visit(t.right, visitor); } - + return true; } diff --git a/stdlib/collections/linkedlist.dg b/stdlib/collections/linkedlist.dg index 95e300db..efef63c3 100644 --- a/stdlib/collections/linkedlist.dg +++ b/stdlib/collections/linkedlist.dg @@ -2,54 +2,54 @@ //A simple double-linked list -struct LinkedList { +struct LinkedList { @private uint size; - + @private bool is_empty; - @private LLNode head; - @private LLNode tail; + @private LLNode head; + @private LLNode tail; } @private -struct LLNode { +struct LLNode { - ?T0 value; + int value; bool has_next; - - LLNode prev; - LLNode next; + + LLNode prev; + LLNode next; } @halts -fn linkedlist_size(LinkedList l) -> uint { - return l.size; +fn linkedlist_size(LinkedList l) -> uint { + return l.size; } -fn linkedlist_contains(LinkedList l, ?T0 value) -> bool { - +fn linkedlist_contains(LinkedList l, int value) -> bool { + return linkedlist_index_of(l, value) >= 0; } -fn linkedlist_index_of(LinkedList l, ?T0 value) -> int { - - LLNode current = l.head; +fn linkedlist_index_of(LinkedList l, int value) -> int { + + LLNode current = l.head; int index = 0; - + while current.has_next { - - if current.value == value { + + if current.value == value { return index; } - + current = current.next; index++; } - - if current.value == value { + + if current.value == value { return index; } - + return -1; } diff --git a/stdlib/collections/set.dg b/stdlib/collections/set.dg index 72a9256b..db8115b0 100644 --- a/stdlib/collections/set.dg +++ b/stdlib/collections/set.dg @@ -1,37 +1,37 @@ #include -struct Set { +struct Set { @private uint size; @private uint capacity; - @private [?T0] arr; + @private [int] arr; } -fn set_size(Set s) -> uint { - +fn set_size(Set s) -> uint { + return s.size; } -fn set_contains(Set s, ?T0 x) -> bool { +fn set_contains(Set s, int x) -> bool { for i in 1 .. s.size { if s.arr[i-1] == x { return true; } } - + return false; } -fn set_remove(Set s, ?T0 x) -> bool { +fn set_remove(Set s, int x) -> bool { if !set_contains(s, x) { return true; } //find the index of the element uint index = 0; for i in 0 .. s.size - 1 { - if s.arr[i] == x { - + if s.arr[i] == x { + index = i; break; } diff --git a/stdlib/collections/stack.dg b/stdlib/collections/stack.dg index 0ff9107f..f9f4fa6f 100644 --- a/stdlib/collections/stack.dg +++ b/stdlib/collections/stack.dg @@ -2,19 +2,19 @@ //A naive implementation of a stack -struct Stack { +struct Stack { @private uint size; @private uint capacity; - @private [?T0] arr; + @private [int] arr; } -fn stack_size(Stack s) -> uint { +fn stack_size(Stack s) -> uint { return s.size; } -fn stack_contains(Stack s, ?T0 elem) -> bool { - +fn stack_contains(Stack s, int elem) -> bool { + for i in 0 .. (s.size - 1) { if s.arr[i] == elem { return true; } } @@ -22,15 +22,15 @@ fn stack_contains(Stack s, ?T0 elem) -> bool { } -fn stack_peek(Stack s) -> ?T0 { +fn stack_peek(Stack s) -> int { return s.arr[s.size - 1]; } -fn stack_pop(Stack s) -> ?T0 { +fn stack_pop(Stack s) -> int { res = stack_peek(s); s.size--; - + return res; } diff --git a/tables/lvst/lvst.c b/tables/lvst/lvst.c index e7524055..4095ac2c 100644 --- a/tables/lvst/lvst.c +++ b/tables/lvst/lvst.c @@ -220,6 +220,7 @@ uint32_t lvst_sizeof_arraytype(struct ArrayType* at) { return 2; } +// returns the size in number of bytes uint32_t lvst_sizeof_type(struct Type* type) { if (type == NULL) { diff --git a/tables/sst/sst.c b/tables/sst/sst.c index 2fb6ceb8..a0c0ec20 100644 --- a/tables/sst/sst.c +++ b/tables/sst/sst.c @@ -15,7 +15,7 @@ #define ERR_SAME_NAME "[SST][Error] 2 subroutines with same name\n" -#define ERR_NOT_FOUND "[SST][Error] subroutine not found\n" +#define ERR_NOT_FOUND "[SST][Error] subroutine not found" struct SST { //Subroutine Symbol Table (SST) @@ -39,7 +39,7 @@ struct SST* sst_ctor() { const int nbytes = sizeof(struct SSTLine*) * sst->capacity; sst->count = 0; - sst->lines = malloc(nbytes); + sst->lines = exit_malloc(nbytes); return sst; } @@ -159,8 +159,7 @@ struct SSTLine* sst_get(struct SST* sst, char* name) { if (strcmp(line->name, name) == 0) { return line; } } - printf(ERR_NOT_FOUND); - printf("\t%s in sst_get\n", name); + printf("%s: '%s'\n", ERR_NOT_FOUND, name); exit(1); return NULL; } diff --git a/tables/stst/stst_print.c b/tables/stst/stst_print.c index ee701e6c..5968c197 100644 --- a/tables/stst/stst_print.c +++ b/tables/stst/stst_print.c @@ -7,7 +7,7 @@ static char* fmt = "%16s|%16s|\n"; void stst_print(struct STST* stst) { - printf("[STST] Struct Symbol Table\n"); + printf("[STST] Struct Symbol Table (%d elements)\n", stst_size(stst)); printf(fmt, "struct name", "member name"); //-------- diff --git a/tables/symtable/symtable.c b/tables/symtable/symtable.c index f4328523..aed01525 100644 --- a/tables/symtable/symtable.c +++ b/tables/symtable/symtable.c @@ -17,7 +17,7 @@ struct ST* st_ctor() { const uint32_t nbytes = sizeof(struct Type*) * st->inferred_types_capacity; - st->inferred_types = malloc(nbytes); + st->inferred_types = exit_malloc(nbytes); st->sst = sst_ctor(); st->stst = stst_ctor(); diff --git a/tac/tac.c b/tac/tac.c index 49ff9b75..14ed3fc3 100644 --- a/tac/tac.c +++ b/tac/tac.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -242,6 +243,14 @@ struct TAC* makeTACCall(uint32_t tmp, uint32_t function_index) { return t; } +struct TAC* makeTACICall(uint32_t tmp, uint32_t tmp_call) { + struct TAC* t = makeTAC(); + t->kind = TAC_ICALL; + t->dest = tmp; + t->arg1 = tmp_call; + return t; +} + struct TAC* makeTACSetupStackframe(uint32_t frame_size) { struct TAC* t = makeTAC(); t->kind = TAC_SETUP_STACKFRAME; @@ -268,11 +277,14 @@ struct TAC* makeTACReturn(uint32_t tmp) { return t; } -struct TAC* makeTACLoad(uint32_t tmp, uint32_t taddr) { +struct TAC* makeTACLoad(uint32_t tmp, uint32_t taddr, uint8_t width) { struct TAC* t = makeTAC(); t->kind = TAC_LOAD; t->dest = tmp; t->arg1 = taddr; + + assert(width <= 8); + t->const_value = width; return t; } diff --git a/tac/tac.h b/tac/tac.h index dcf15933..d122784b 100644 --- a/tac/tac.h +++ b/tac/tac.h @@ -57,6 +57,9 @@ enum TAC_KIND { TAC_CONST_VALUE, TAC_CALL, //call to a label (string) without anything else + TAC_ICALL, // call to a temporary 't1 = call t2'. + // So we can comput arbitrary address to call. + // Good for calling function pointers TAC_PARAM, TAC_RETURN, //return, without arguments @@ -134,12 +137,13 @@ struct TAC* makeTACLoadConstAddr(uint32_t dest, uint32_t addr); struct TAC* makeTACParam(uint32_t dest, bool push16); struct TAC* makeTACCall(uint32_t tmp, uint32_t function_index); +struct TAC* makeTACICall(uint32_t tmp, uint32_t tmp_call); struct TAC* makeTACSetupStackframe(uint32_t frame_size); struct TAC* makeTACSetupSP(); struct TAC* makeTACNop(); -struct TAC* makeTACLoad(uint32_t tmp, uint32_t taddr); +struct TAC* makeTACLoad(uint32_t tmp, uint32_t taddr, uint8_t width); struct TAC* makeTACStore(uint32_t taddr, uint32_t tmp); #endif diff --git a/tac/tac_str.c b/tac/tac_str.c index 8449fb64..7ebcaa4e 100644 --- a/tac/tac_str.c +++ b/tac/tac_str.c @@ -129,6 +129,9 @@ char* tac_tostring(struct TAC* t, struct Ctx* ctx) { } sprintf(buffer, "t%d = call %s", t->dest, function_name); } break; + case TAC_ICALL: { + sprintf(buffer, "t%d = call t%ld", t->dest, t->arg1); + } break; case TAC_PARAM: sprintf(buffer, "param t%d", t->arg1); @@ -146,6 +149,10 @@ char* tac_tostring(struct TAC* t, struct Ctx* ctx) { case TAC_SETUP_SP: sprintf(buffer, "setup SP"); break; + default: + printf("unhandled in %s\n", __func__); + exit(1); + break; } strcat(res, buffer);