Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions ast/ast/ast_expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ struct Term {
struct MDirect {
struct ASTNode super;
struct Expr* expr;

// width of the load/store, in bytes
uint8_t load_store_width;
};

#endif
1 change: 1 addition & 0 deletions ast/util/copy_ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ struct Op* copy_op(struct Op* op){
struct MDirect* copy_mdirect(struct MDirect* m) {
struct MDirect* res = make(MDirect);
res->expr = copy_expr(m->expr);
res->load_store_width = m->load_store_width;
return res;
}

Expand Down
4 changes: 2 additions & 2 deletions ast/util/str_ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -426,8 +426,8 @@ char* str_term(struct Term* t) {
char* str_mdirect(struct MDirect* m) {

char* se = str_expr(m->expr);
char* res = exit_malloc(3 + strlen(se));
sprintf(res, "[%s]", se);
char* res;
asprintf(&res, "[%s, %d]", se, m->load_store_width);

free(se);
return res;
Expand Down
2 changes: 2 additions & 0 deletions compiler/main/avr_code_gen/compile_ir/compile_tac_binary_op.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ static void case_arithmetic(struct RAT* rat, struct TAC* tac, struct IBuffer* ib
case TAC_OP_MUL:
mul(rdest, rsrc, "");
//TODO: figure out the case with wide temporaries
// after MUL, result is stored in r1:r0 (r0 is the low byte)
mov(rdest, r0, "move multiplication result");
break;

case TAC_OP_AND:
Expand Down
10 changes: 6 additions & 4 deletions compiler/main/avr_code_gen/compile_ir/compile_tac_load.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <assert.h>

#include "rat/rat.h"
#include "tac/tac.h"
Expand All @@ -24,11 +25,12 @@ void compile_tac_load(struct RAT* rat, struct TAC* tac, struct IBuffer* ibu) {
else
ldi(XH, 0, c);

// TODO: make a 'wide' property in struct TAC
// to avoid encoding this in different places
const bool tac_says_wide = tac_const_value(tac) == 2;
const uint8_t width = tac_load_store_width(tac);

if (tac_says_wide) {
assert(width <= 2);
assert(width >= 1);

if (width == 2) {

// what if we want to load a 16 bit value?
ldXpostInc(reg_dest, c);
Expand Down
4 changes: 3 additions & 1 deletion compiler/main/gen_tac/gen_tac.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ void tac_method(struct TACBuffer* buffer, struct Method* m, struct Ctx* ctx);
void tac_stmtblock(struct TACBuffer* buffer, struct StmtBlock* block, struct Ctx* ctx);

void tac_variable(struct TACBuffer* buffer, struct Variable* v, struct Ctx* ctx);
void tac_variable_addr(struct TACBuffer* buffer, struct Variable* v, struct Ctx* ctx);

// @param last_type_width used for the final load. can pass NULL here if dont care
void tac_variable_addr(struct TACBuffer* buffer, struct Variable* v, struct Ctx* ctx, uint8_t* last_type_width);

void tac_simplevar(struct TACBuffer* buffer, struct SimpleVar* sv, struct Ctx* ctx);
void tac_simplevar_addr(struct TACBuffer* buffer, struct SimpleVar* sv, struct Ctx* ctx);
Expand Down
2 changes: 1 addition & 1 deletion compiler/main/gen_tac/gen_tac_assignstmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ static void case_member(struct TACBuffer* buffer, struct AssignStmt* a, struct C
uint32_t texpr = tacbuffer_last_dest(buffer);

//find out the address of the variable
tac_variable_addr(buffer, a->var, ctx);
tac_variable_addr(buffer, a->var, ctx, NULL);

uint32_t taddr = tacbuffer_last_dest(buffer);

Expand Down
2 changes: 1 addition & 1 deletion compiler/main/gen_tac/gen_tac_massignstmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ static void case_variable_addr(struct TACBuffer* buffer, struct MAssignStmt* m,
tac_expr(buffer, lhs, ctx);
uint32_t taddr = tacbuffer_last_dest(buffer);

tacbuffer_append(buffer, makeTACStore(taddr, texpr, width));
tacbuffer_append(buffer, makeTACStore(taddr, texpr, m->lhs->load_store_width));
}

void tac_massignstmt(struct TACBuffer* buffer, struct MAssignStmt* m, struct Ctx* ctx) {
Expand Down
3 changes: 1 addition & 2 deletions compiler/main/gen_tac/gen_tac_mdirect.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ void tac_mdirect(struct TACBuffer* buffer, struct MDirect* m, struct Ctx* ctx) {

tac_expr(buffer, m->expr, ctx);

// TODO: for x86, this needs to be 8 bytes, not 2
struct TAC* t = makeTACLoad(make_temp(), tacbuffer_last_dest(buffer), 2);
struct TAC* t = makeTACLoad(make_temp(), tacbuffer_last_dest(buffer), m->load_store_width);

tacbuffer_append(buffer, t);
}
21 changes: 12 additions & 9 deletions compiler/main/gen_tac/gen_tac_variable.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@

void tac_variable(struct TACBuffer* buf, struct Variable* v, struct Ctx* ctx) {

tac_variable_addr(buf, v, ctx);
uint8_t last_type_width;

tac_variable_addr(buf, v, ctx, &last_type_width);

const uint32_t tlast = tacbuffer_last_dest(buf);

Expand All @@ -29,18 +31,17 @@ void tac_variable(struct TACBuffer* buf, struct Variable* v, struct Ctx* ctx) {
}
}

// 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(buf, makeTACLoad(make_temp(), tlast, 2));
tacbuffer_append(buf, makeTACLoad(make_temp(), tlast, last_type_width));
}

void tac_variable_addr(struct TACBuffer* buffer, struct Variable* v, struct Ctx* ctx) {
void tac_variable_addr(struct TACBuffer* buffer, struct Variable* v, struct Ctx* ctx, uint8_t* last_type_width) {

if (flags_debug(ctx_flags(ctx))) {
printf("[debug] %s\n", __func__);
}

const bool x86 = flags_x86(ctx_flags(ctx));

struct DerefLL* dll = derefll_ctor_variable(v, ctx);

derefll_annotate_types(dll, ctx, NULL);
Expand All @@ -50,14 +51,16 @@ void tac_variable_addr(struct TACBuffer* buffer, struct Variable* v, struct Ctx*
struct DerefLL* current = dll;
struct Type* prev_type = NULL;

while (true) {
while (current != NULL) {

tac_derefll_single(buffer, current, prev_type, ctx);

if (last_type_width && current->type) {
*last_type_width = lvst_sizeof_type(current->type, x86);
}

prev_type = current->type;
current = current->next;

if (current == NULL) break;
}

derefll_dtor(dll);
Expand Down
1 change: 0 additions & 1 deletion compiler/test/avr_code_gen/compile_ir/test_compile_tac.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ void test_compile_tac_param_case_16bit();
void test_compile_tac_call_case_recurses();
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_8bit_value();
Expand Down
5 changes: 0 additions & 5 deletions compiler/test/avr_code_gen/compile_ir/test_compile_tac_call.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,3 @@ void test_compile_tac_call_case_returns_value_16bit() {

vmcu_system_dtor(system);
}

void test_compile_tac_call_case_1_param() {

status_test_codegen("TAC_CALL - 1 param [TODO]");
}
6 changes: 4 additions & 2 deletions compiler/test/gen_tac/test_gen_tac.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ void test_gen_tac_assignstmt_case_local_struct();
void test_gen_tac_assignstmt_case_local_array();

// massign stmt
void test_gen_tac_massignstmt_case_const_addr();
void test_gen_tac_massignstmt_case_variable_addr();
void test_gen_tac_massignstmt_case_const_addr_1_byte();
void test_gen_tac_massignstmt_case_const_addr_2_byte();
void test_gen_tac_massignstmt_case_variable_addr_1_byte();
void test_gen_tac_massignstmt_case_variable_addr_2_byte();

// mdirect
void test_gen_tac_mdirect_case_const_addr();
Expand Down
7 changes: 3 additions & 4 deletions compiler/test/gen_tac/test_gen_tac_assignstmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,16 @@ void test_gen_tac_assignstmt_case_local_int_16bit() {

void test_gen_tac_assignstmt_case_local_struct() {

status_test_codegen_tac("AssignStmt - local struct [TODO]");
return;
status_test_codegen_tac("AssignStmt - local struct");

const int8_t value = 0x23;

char snippet[200];
sprintf(snippet, "struct A {int x;}; fn main() -> int { A m; m.x = %d; return m.x; }", value);
sprintf(snippet, "struct A {int x;} fn main() -> int { local A m; m.x = %d; return m.x; }", value);

vmcu_system_t* system = prepare_vmcu_system_from_code_snippet(snippet);

vmcu_system_step_n(system, 20);
vmcu_system_step_n(system, 40);

//assert that value is returned in r0 as it should be

Expand Down
6 changes: 3 additions & 3 deletions compiler/test/gen_tac/test_gen_tac_call.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ void test_gen_tac_call_case_1_args_write_8bit() {
const uint8_t expected = 0xab;

char snippet[200];
char* template = "fn main()->int{ f(%d); return 0; } fn f(uint8 a)->int { [0x100]=a; return 0; }";
char* template = "fn main()->int{ f(%d); return 0; } fn f(uint8 a)->int { [0x100, 1]=a; return 0; }";
sprintf(snippet, template, expected);

vmcu_system_t* system = prepare_vmcu_system_from_code_snippet(snippet);
Expand All @@ -158,7 +158,7 @@ void test_gen_tac_call_case_1_args_write_16bit() {
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; }";
char* template = "fn main()->int{ f(%d); return 0; } fn f(uint16 a)->int { [0x100, 2]=a; return 0; }";
sprintf(snippet, template, expected);

vmcu_system_t* system = prepare_vmcu_system_from_code_snippet(snippet);
Expand All @@ -184,7 +184,7 @@ void test_gen_tac_call_case_1_args_write_3fns() {
const uint8_t expected = (0x20) | 0x1;

char snippet[200];
char* template = "fn main()->int{ return f1(%d); } fn f1(uint8 a)->int {return f2(a);} fn f2 (uint8 b)->int{ [0x101]=b; return 0; }";
char* template = "fn main()->int{ return f1(%d); } fn f1(uint8 a)->int {return f2(a);} fn f2 (uint8 b)->int{ [0x101, 1]=b; return 0; }";
sprintf(snippet, template, expected);

vmcu_system_t* system = prepare_vmcu_system_from_code_snippet(snippet);
Expand Down
45 changes: 29 additions & 16 deletions compiler/test/gen_tac/test_gen_tac_expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,31 +58,44 @@ void test_gen_tac_expr_minus() {
}
}
}
static void test_gen_tac_expr_mul_single(uint8_t value1, uint8_t value2) {

void test_gen_tac_expr_mul() {
char snippet[200];
sprintf(snippet, "fn main() -> int { int x = %d * %d; return x; }", value1, value2);

status_test_codegen_tac("Expr *");
//compile snippet and init a vmcu
vmcu_system_t* system = prepare_vmcu_system_from_code_snippet(snippet);

for (int8_t value1 = 0; value1 < 3; value1++) {
for (int8_t value2 = 0; value2 < 3; value2++) {
//step it past the main function
vmcu_system_step_n(system, 40);

char snippet[200];
sprintf(snippet, "fn main() -> int { int x = %d * %d; return x; }", value1, value2);
//assert that value is returned in r0 as it should be
const uint8_t r0 = vmcu_system_read_gpr(system, 0);

//compile snippet and init a vmcu
vmcu_system_t* system = prepare_vmcu_system_from_code_snippet(snippet);
if (r0 != (value1 * value2)) {
printf("r0 = 0x%x, expected 0x%x\n", r0, (value1 * value2));
}
assert(r0 == (value1 * value2));

//step it past the main function
vmcu_system_step_n(system, 20);
vmcu_system_dtor(system);
}

//assert that value is returned in r0 as it should be
int8_t r0_value = vmcu_system_read_gpr(system, 0);
void test_gen_tac_expr_mul() {

assert(r0_value == (value1 * value2));
status_test_codegen_tac("Expr *");

vmcu_system_dtor(system);
}
}
test_gen_tac_expr_mul_single(0, 0);
test_gen_tac_expr_mul_single(0, 1);
test_gen_tac_expr_mul_single(0, 2);

test_gen_tac_expr_mul_single(3, 0);
test_gen_tac_expr_mul_single(3, 1);
test_gen_tac_expr_mul_single(3, 2);

test_gen_tac_expr_mul_single(4, 0);
test_gen_tac_expr_mul_single(4, 8);
test_gen_tac_expr_mul_single(4, 8);
test_gen_tac_expr_mul_single(7, 8);
}

void test_gen_tac_expr_and() {
Expand Down
58 changes: 52 additions & 6 deletions compiler/test/gen_tac/test_gen_tac_massignstmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@

#include "test_gen_tac.h"

void test_gen_tac_massignstmt_case_const_addr() {
void test_gen_tac_massignstmt_case_const_addr_1_byte() {

status_test_codegen_tac("MAssignStmt - const Address");
status_test_codegen_tac("MAssignStmt - const Address (1 byte)");

for (int8_t value = 0; value < 5; value++) {

char snippet[200];
sprintf(snippet, "fn main() -> int { [0x100] = %d; return 0; }", value);
sprintf(snippet, "fn main() -> int { [0x100, 1] = %d; return 0; }", value);

vmcu_system_t* system = prepare_vmcu_system_from_code_snippet(snippet);

Expand All @@ -26,17 +26,38 @@ void test_gen_tac_massignstmt_case_const_addr() {
}
}

void test_gen_tac_massignstmt_case_variable_addr() {
void test_gen_tac_massignstmt_case_const_addr_2_byte() {

status_test_codegen_tac("MAssignStmt - variable Address");
status_test_codegen_tac("MAssignStmt - const Address (2 byte)");

for (uint16_t value = 392; value < 399; value++) {

char snippet[200];
sprintf(snippet, "fn main() -> int { [0x100, 2] = %d; return 0; }", value);

vmcu_system_t* system = prepare_vmcu_system_from_code_snippet(snippet);

vmcu_system_step_n(system, 20);

uint16_t actual = vmcu_system_read_data16(system, 0x100);

assert(actual == value);

vmcu_system_dtor(system);
}
}

void test_gen_tac_massignstmt_case_variable_addr_1_byte() {

status_test_codegen_tac("MAssignStmt - variable Address (1 byte)");

const uint8_t addr = 0xc7;
for (uint8_t offset = 0; offset < 5; offset++) {

const int8_t value = 0x31;

char snippet[200];
char* template = "fn main() -> int { int x = %d; [x + 0xc7] = %d; return 0; }";
char* template = "fn main() -> int { int x = %d; [x + 0xc7, 1] = %d; return 0; }";
sprintf(snippet, template, offset, value);

vmcu_system_t* system = prepare_vmcu_system_from_code_snippet(snippet);
Expand All @@ -50,3 +71,28 @@ void test_gen_tac_massignstmt_case_variable_addr() {
vmcu_system_dtor(system);
}
}

void test_gen_tac_massignstmt_case_variable_addr_2_byte() {

status_test_codegen_tac("MAssignStmt - variable Address (2 byte)");

const uint8_t addr = 0xc7;
for (uint8_t offset = 0; offset < 5; offset++) {

const uint16_t value = 0x312a;

char snippet[200];
char* template = "fn main() -> int { int x = %d; [x + 0xc7, 1] = %d; return 0; }";
sprintf(snippet, template, offset, value);

vmcu_system_t* system = prepare_vmcu_system_from_code_snippet(snippet);

vmcu_system_step_n(system, 40);

uint16_t actual = vmcu_system_read_data16(system, addr + offset);

assert(actual == value);

vmcu_system_dtor(system);
}
}
Loading