aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/codegen_test.c227
-rw-r--r--tests/parser_test.c10
2 files changed, 64 insertions, 173 deletions
diff --git a/tests/codegen_test.c b/tests/codegen_test.c
index 377ddeb..8fe1465 100644
--- a/tests/codegen_test.c
+++ b/tests/codegen_test.c
@@ -5,21 +5,32 @@
#include "codegen/nasm.h"
#include "tests.h"
-static void test_generate_consts_and_data(struct TestContext* context)
+static void generate_to_buffer(struct Program* program, char* buffer, size_t size)
{
- struct Lexer lexer = create_lexer("const N = 5\ndata msg = \"hi\"\n");
- struct Program program;
- check(context, parse_program(&lexer, &program));
-
FILE* out = tmpfile();
- generate_nasm(&program, out);
+ if (out == NULL)
+ {
+ buffer[0] = '\0';
+ return;
+ }
+
+ generate_nasm(program, out);
fflush(out);
rewind(out);
- char buffer[1024];
- size_t read = fread(buffer, 1, sizeof(buffer) - 1, out);
+ size_t read = fread(buffer, 1, size - 1, out);
buffer[read] = '\0';
fclose(out);
+}
+
+static void test_generate_consts_and_data(struct TestContext* context)
+{
+ struct Lexer lexer = create_lexer("const N = 5\ndata msg = \"hi\"\n");
+ struct Program program;
+ check(context, parse_program(&lexer, &program));
+
+ char buffer[1024];
+ generate_to_buffer(&program, buffer, sizeof(buffer));
check(context, strstr(buffer, "%define N (5)") != NULL);
check(context, strstr(buffer, "section .data") != NULL);
@@ -37,15 +48,8 @@ static void test_generate_text(struct TestContext* context)
struct Program program;
check(context, parse_program(&lexer, &program));
- FILE* out = tmpfile();
- generate_nasm(&program, out);
- fflush(out);
- rewind(out);
-
char buffer[1024];
- size_t read = fread(buffer, 1, sizeof(buffer) - 1, out);
- buffer[read] = '\0';
- fclose(out);
+ generate_to_buffer(&program, buffer, sizeof(buffer));
check(context, strstr(buffer, "main:") != NULL);
check(context, strstr(buffer, "mov rax, SYS_WRITE") != NULL);
@@ -65,15 +69,8 @@ static void test_generate_if(struct TestContext* context)
struct Program program;
check(context, parse_program(&lexer, &program));
- FILE* out = tmpfile();
- generate_nasm(&program, out);
- fflush(out);
- rewind(out);
-
char buffer[1024];
- size_t read = fread(buffer, 1, sizeof(buffer) - 1, out);
- buffer[read] = '\0';
- fclose(out);
+ generate_to_buffer(&program, buffer, sizeof(buffer));
check(context, strstr(buffer, "cmp rcx, 0") != NULL);
check(context, strstr(buffer, "je .if_end_0") != NULL);
@@ -90,15 +87,8 @@ static void test_generate_call(struct TestContext* context)
struct Program program;
check(context, parse_program(&lexer, &program));
- FILE* out = tmpfile();
- generate_nasm(&program, out);
- fflush(out);
- rewind(out);
-
char buffer[1024];
- size_t read = fread(buffer, 1, sizeof(buffer) - 1, out);
- buffer[read] = '\0';
- fclose(out);
+ generate_to_buffer(&program, buffer, sizeof(buffer));
check(context, strstr(buffer, "mov rdi, r12") != NULL);
check(context, strstr(buffer, "call print_number") != NULL);
@@ -113,15 +103,8 @@ static void test_generate_param_substitution(struct TestContext* context)
struct Program program;
check(context, parse_program(&lexer, &program));
- FILE* out = tmpfile();
- generate_nasm(&program, out);
- fflush(out);
- rewind(out);
-
char buffer[1024];
- size_t read = fread(buffer, 1, sizeof(buffer) - 1, out);
- buffer[read] = '\0';
- fclose(out);
+ generate_to_buffer(&program, buffer, sizeof(buffer));
check(context, strstr(buffer, "mov rax, rdi") != NULL);
check(context, strstr(buffer, "value") == NULL);
@@ -135,15 +118,8 @@ static void test_generate_divide(struct TestContext* context)
struct Program program;
check(context, parse_program(&lexer, &program));
- FILE* out = tmpfile();
- generate_nasm(&program, out);
- fflush(out);
- rewind(out);
-
char buffer[1024];
- size_t read = fread(buffer, 1, sizeof(buffer) - 1, out);
- buffer[read] = '\0';
- fclose(out);
+ generate_to_buffer(&program, buffer, sizeof(buffer));
check(context, strstr(buffer, "cqo") != NULL);
check(context, strstr(buffer, "idiv rbx") != NULL);
@@ -157,15 +133,8 @@ static void test_generate_multiply(struct TestContext* context)
struct Program program;
check(context, parse_program(&lexer, &program));
- FILE* out = tmpfile();
- generate_nasm(&program, out);
- fflush(out);
- rewind(out);
-
char buffer[1024];
- size_t read = fread(buffer, 1, sizeof(buffer) - 1, out);
- buffer[read] = '\0';
- fclose(out);
+ generate_to_buffer(&program, buffer, sizeof(buffer));
check(context, strstr(buffer, "mov rax, rbx") != NULL);
check(context, strstr(buffer, "imul rax, rcx") != NULL);
@@ -176,6 +145,25 @@ static void test_generate_multiply(struct TestContext* context)
free_program(&program);
}
+static void test_generate_modulo(struct TestContext* context)
+{
+ struct Lexer lexer = create_lexer("proc main\n{\nrbx %= rcx\nrax = rsi % rdi\n}\n");
+ struct Program program;
+ check(context, parse_program(&lexer, &program));
+
+ char buffer[1024];
+ generate_to_buffer(&program, buffer, sizeof(buffer));
+
+ // modulo takes idiv's remainder from rdx
+ check(context, strstr(buffer, "mov rax, rbx") != NULL);
+ check(context, strstr(buffer, "idiv rcx") != NULL);
+ check(context, strstr(buffer, "mov rbx, rdx") != NULL);
+ check(context, strstr(buffer, "mov rax, rdx") != NULL);
+ check(context, strstr(buffer, "; TODO") == NULL);
+
+ free_program(&program);
+}
+
static void test_generate_divide_nonrax(struct TestContext* context)
{
// division into a register other than rax routes through rax:rdx
@@ -183,15 +171,8 @@ static void test_generate_divide_nonrax(struct TestContext* context)
struct Program program;
check(context, parse_program(&lexer, &program));
- FILE* out = tmpfile();
- generate_nasm(&program, out);
- fflush(out);
- rewind(out);
-
char buffer[1024];
- size_t read = fread(buffer, 1, sizeof(buffer) - 1, out);
- buffer[read] = '\0';
- fclose(out);
+ generate_to_buffer(&program, buffer, sizeof(buffer));
check(context, strstr(buffer, "mov rax, rbx") != NULL);
check(context, strstr(buffer, "idiv rcx") != NULL);
@@ -208,15 +189,8 @@ static void test_generate_stack_frame(struct TestContext* context)
struct Program program;
check(context, parse_program(&lexer, &program));
- FILE* out = tmpfile();
- generate_nasm(&program, out);
- fflush(out);
- rewind(out);
-
char buffer[1024];
- size_t read = fread(buffer, 1, sizeof(buffer) - 1, out);
- buffer[read] = '\0';
- fclose(out);
+ generate_to_buffer(&program, buffer, sizeof(buffer));
check(context, strstr(buffer, "push rbp") != NULL);
check(context, strstr(buffer, "mov rbp, rsp") != NULL);
@@ -233,15 +207,8 @@ static void test_generate_address_expr(struct TestContext* context)
struct Program program;
check(context, parse_program(&lexer, &program));
- FILE* out = tmpfile();
- generate_nasm(&program, out);
- fflush(out);
- rewind(out);
-
char buffer[1024];
- size_t read = fread(buffer, 1, sizeof(buffer) - 1, out);
- buffer[read] = '\0';
- fclose(out);
+ generate_to_buffer(&program, buffer, sizeof(buffer));
check(context, strstr(buffer, "lea rsi, [rbp - 32]") != NULL);
check(context, strstr(buffer, "add rsi, 31") != NULL);
@@ -260,15 +227,8 @@ static void test_generate_sized_store(struct TestContext* context)
struct Program program;
check(context, parse_program(&lexer, &program));
- FILE* out = tmpfile();
- generate_nasm(&program, out);
- fflush(out);
- rewind(out);
-
char buffer[1024];
- size_t read = fread(buffer, 1, sizeof(buffer) - 1, out);
- buffer[read] = '\0';
- fclose(out);
+ generate_to_buffer(&program, buffer, sizeof(buffer));
check(context, strstr(buffer, "mov byte [rsi], dl") != NULL);
check(context, strstr(buffer, "mov dword [rsi], eax") != NULL);
@@ -284,15 +244,8 @@ static void test_generate_entry_and_bits(struct TestContext* context)
struct Program program;
check(context, parse_program(&with_entry, &program));
- FILE* out = tmpfile();
- generate_nasm(&program, out);
- fflush(out);
- rewind(out);
-
char buffer[1024];
- size_t read = fread(buffer, 1, sizeof(buffer) - 1, out);
- buffer[read] = '\0';
- fclose(out);
+ generate_to_buffer(&program, buffer, sizeof(buffer));
check(context, strstr(buffer, "bits 64") != NULL);
check(context, strstr(buffer, "global main") != NULL);
@@ -310,15 +263,8 @@ static void test_generate_no_entry(struct TestContext* context)
struct Program program;
check(context, parse_program(&no_entry, &program));
- FILE* out = tmpfile();
- generate_nasm(&program, out);
- fflush(out);
- rewind(out);
-
char buffer[1024];
- size_t read = fread(buffer, 1, sizeof(buffer) - 1, out);
- buffer[read] = '\0';
- fclose(out);
+ generate_to_buffer(&program, buffer, sizeof(buffer));
check(context, strstr(buffer, "global") == NULL);
check(context, strstr(buffer, "main:") != NULL);
@@ -333,15 +279,8 @@ static void test_generate_logical_registers(struct TestContext* context)
struct Program program;
check(context, parse_program(&lexer, &program));
- FILE* out = tmpfile();
- generate_nasm(&program, out);
- fflush(out);
- rewind(out);
-
char buffer[1024];
- size_t read = fread(buffer, 1, sizeof(buffer) - 1, out);
- buffer[read] = '\0';
- fclose(out);
+ generate_to_buffer(&program, buffer, sizeof(buffer));
check(context, strstr(buffer, "mov rax, 5") != NULL); // r1 -> rax
check(context, strstr(buffer, "mov rdx, r11") != NULL); // r4 -> rdx, r10 -> r11
@@ -356,15 +295,8 @@ static void test_generate_logical_disabled(struct TestContext* context)
struct Program program;
check(context, parse_program(&lexer, &program));
- FILE* out = tmpfile();
- generate_nasm(&program, out);
- fflush(out);
- rewind(out);
-
char buffer[1024];
- size_t read = fread(buffer, 1, sizeof(buffer) - 1, out);
- buffer[read] = '\0';
- fclose(out);
+ generate_to_buffer(&program, buffer, sizeof(buffer));
// without the extension, r1 is passed through untouched
check(context, strstr(buffer, "mov r1, 5") != NULL);
@@ -379,15 +311,8 @@ static void test_generate_load(struct TestContext* context)
struct Program program;
check(context, parse_program(&lexer, &program));
- FILE* out = tmpfile();
- generate_nasm(&program, out);
- fflush(out);
- rewind(out);
-
char buffer[1024];
- size_t read = fread(buffer, 1, sizeof(buffer) - 1, out);
- buffer[read] = '\0';
- fclose(out);
+ generate_to_buffer(&program, buffer, sizeof(buffer));
check(context, strstr(buffer, "mov rax, [rsi]") != NULL);
check(context, strstr(buffer, "movzx rbx, byte [rsi]") != NULL);
@@ -408,15 +333,8 @@ static void test_generate_enum_struct(struct TestContext* context)
struct Program program;
check(context, parse_program(&lexer, &program));
- FILE* out = tmpfile();
- generate_nasm(&program, out);
- fflush(out);
- rewind(out);
-
char buffer[1024];
- size_t read = fread(buffer, 1, sizeof(buffer) - 1, out);
- buffer[read] = '\0';
- fclose(out);
+ generate_to_buffer(&program, buffer, sizeof(buffer));
check(context, strstr(buffer, "mov rax, 2") != NULL); // Color.Blue -> 2
check(context, strstr(buffer, "mov rbx, 8") != NULL); // Point.y -> 8
@@ -433,15 +351,8 @@ static void test_generate_floats(struct TestContext* context)
struct Program program;
check(context, parse_program(&lexer, &program));
- FILE* out = tmpfile();
- generate_nasm(&program, out);
- fflush(out);
- rewind(out);
-
char buffer[1024];
- size_t read = fread(buffer, 1, sizeof(buffer) - 1, out);
- buffer[read] = '\0';
- fclose(out);
+ generate_to_buffer(&program, buffer, sizeof(buffer));
check(context, strstr(buffer, "__float0: dq 3.5") != NULL);
check(context, strstr(buffer, "movsd xmm0, [__float0]") != NULL);
@@ -459,15 +370,8 @@ static void test_generate_float_compare(struct TestContext* context)
struct Program program;
check(context, parse_program(&lexer, &program));
- FILE* out = tmpfile();
- generate_nasm(&program, out);
- fflush(out);
- rewind(out);
-
char buffer[1024];
- size_t read = fread(buffer, 1, sizeof(buffer) - 1, out);
- buffer[read] = '\0';
- fclose(out);
+ generate_to_buffer(&program, buffer, sizeof(buffer));
check(context, strstr(buffer, "ucomisd xmm0, [__float0]") != NULL);
check(context, strstr(buffer, "jbe .if_end") != NULL); // '>' skips when <=
@@ -483,15 +387,8 @@ static void test_generate_add_zero_peephole(struct TestContext* context)
struct Program program;
check(context, parse_program(&lexer, &program));
- FILE* out = tmpfile();
- generate_nasm(&program, out);
- fflush(out);
- rewind(out);
-
char buffer[1024];
- size_t read = fread(buffer, 1, sizeof(buffer) - 1, out);
- buffer[read] = '\0';
- fclose(out);
+ generate_to_buffer(&program, buffer, sizeof(buffer));
check(context, strstr(buffer, "add rax, 0") == NULL);
check(context, strstr(buffer, "sub rbx, 0") == NULL);
@@ -506,15 +403,8 @@ static void test_generate_float_memory(struct TestContext* context)
struct Program program;
check(context, parse_program(&lexer, &program));
- FILE* out = tmpfile();
- generate_nasm(&program, out);
- fflush(out);
- rewind(out);
-
char buffer[1024];
- size_t read = fread(buffer, 1, sizeof(buffer) - 1, out);
- buffer[read] = '\0';
- fclose(out);
+ generate_to_buffer(&program, buffer, sizeof(buffer));
check(context, strstr(buffer, "movsd [rsi], xmm0") != NULL); // float store
check(context, strstr(buffer, "movsd xmm1, [rsi]") != NULL); // float load
@@ -542,6 +432,7 @@ void run_codegen_tests(struct TestContext* context)
test_generate_param_substitution(context);
test_generate_divide(context);
test_generate_multiply(context);
+ test_generate_modulo(context);
test_generate_divide_nonrax(context);
test_generate_stack_frame(context);
test_generate_address_expr(context);
diff --git a/tests/parser_test.c b/tests/parser_test.c
index dbb250f..ca1d345 100644
--- a/tests/parser_test.c
+++ b/tests/parser_test.c
@@ -10,7 +10,7 @@ static bool text_is(struct Token token, const char* text)
return token.length == length && memcmp(token.start, text, length) == 0;
}
-static bool primary_is(struct Expr* expr, const char* text)
+static bool primary_is(const struct Expr* expr, const char* text)
{
return expr->kind == EXPR_PRIMARY && text_is(expr->primary.token, text);
}
@@ -37,7 +37,7 @@ static void test_parse_const_expr(struct TestContext* context)
check(context, parse_program(&lexer, &program));
- struct Expr* value = program.consts[1].value;
+ const struct Expr* value = program.consts[1].value;
check(context, value->kind == EXPR_BINARY);
check(context, text_is(value->binary.op, "+"));
check(context, primary_is(value->binary.left, "A"));
@@ -133,13 +133,13 @@ static void test_parse_expressions(struct TestContext* context)
check(context, parse_program(&lexer, &program));
check(context, program.procs[0].body_count == 2);
- struct Expr* sum = program.procs[0].body[0].assign.value;
+ const struct Expr* sum = program.procs[0].body[0].assign.value;
check(context, sum->kind == EXPR_BINARY);
check(context, text_is(sum->binary.op, "+"));
check(context, primary_is(sum->binary.left, "buffer"));
check(context, primary_is(sum->binary.right, "31"));
- struct Expr* member = program.procs[0].body[1].assign.value;
+ const struct Expr* member = program.procs[0].body[1].assign.value;
check(context, member->kind == EXPR_MEMBER);
check(context, primary_is(member->member.object, "message"));
check(context, text_is(member->member.member, "len"));
@@ -257,7 +257,7 @@ static void test_parse_register_size_suffix(struct TestContext* context)
check(context, parse_program(&lexer, &program));
- struct Expr* value = program.procs[0].body[0].assign.value;
+ const struct Expr* value = program.procs[0].body[0].assign.value;
check(context, value->kind == EXPR_MEMBER);
check(context, value->member.member.type == TOKEN_INTEGER);
check(context, text_is(value->member.member, "8"));