diff options
Diffstat (limited to 'tests/codegen_test.c')
| -rw-r--r-- | tests/codegen_test.c | 68 |
1 files changed, 67 insertions, 1 deletions
diff --git a/tests/codegen_test.c b/tests/codegen_test.c index 2ccba98..24cac6d 100644 --- a/tests/codegen_test.c +++ b/tests/codegen_test.c @@ -1,9 +1,9 @@ #include <stdio.h> #include <string.h> -#include "nasm.h" #include "tests.h" #include "parser.h" +#include "codegen.h" static void generate_to_buffer(struct Program* program, char* buffer, size_t size) { @@ -23,6 +23,24 @@ static void generate_to_buffer(struct Program* program, char* buffer, size_t siz fclose(out); } +static void generate_fasm_to_buffer(struct Program* program, char* buffer, size_t size) +{ + FILE* out = tmpfile(); + if (out == NULL) + { + buffer[0] = '\0'; + return; + } + + generate_fasm(program, out); + fflush(out); + rewind(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"); @@ -41,6 +59,33 @@ static void test_generate_consts_and_data(struct TestContext* context) free_program(&program); } +static void test_generate_fasm(struct TestContext* context) +{ + struct Lexer lexer = create_lexer( + "[entry: main]\nconst N = 5\ndata msg = \"hi\\n\"\nproc main\n{\nrax = N\nsyscall\n}\n"); + struct Program program; + check(context, parse_program(&lexer, &program)); + + char buffer[1024]; + generate_fasm_to_buffer(&program, buffer, sizeof(buffer)); + + // fasm framing differs from nasm + check(context, strstr(buffer, "format ELF64") != NULL); + check(context, strstr(buffer, "N = 5") != NULL); + check(context, strstr(buffer, "section '.data' writeable") != NULL); + check(context, strstr(buffer, "msg db \"hi\", 10") != NULL); // escape expanded to a byte + check(context, strstr(buffer, ".len = $ - msg") != NULL); + check(context, strstr(buffer, "section '.text' executable") != NULL); + check(context, strstr(buffer, "public main") != NULL); + // instruction bodies are identical to nasm + check(context, strstr(buffer, "mov rax, N") != NULL); + // nasm-only forms must be absent + check(context, strstr(buffer, "%define") == NULL); + check(context, strstr(buffer, "bits 64") == NULL); + + free_program(&program); +} + static void test_generate_text(struct TestContext* context) { struct Lexer lexer = create_lexer( @@ -121,6 +166,25 @@ static void test_generate_while(struct TestContext* context) free_program(&program); } +static void test_generate_while_named(struct TestContext* context) +{ + struct Lexer lexer = create_lexer( + "proc main\n{\nwhile .drain rcx > 0\n{\nrcx -= 1\n}\n}\n"); + struct Program program; + check(context, parse_program(&lexer, &program)); + + char buffer[1024]; + generate_to_buffer(&program, buffer, sizeof(buffer)); + + check(context, strstr(buffer, ".drain:") != NULL); + check(context, strstr(buffer, "jle .drain_end") != NULL); + check(context, strstr(buffer, "jmp .drain") != NULL); + check(context, strstr(buffer, ".drain_end:") != NULL); + check(context, strstr(buffer, ".while_0") == NULL); + + free_program(&program); +} + static void test_generate_negative(struct TestContext* context) { struct Lexer lexer = create_lexer( @@ -524,10 +588,12 @@ void run_codegen_tests(struct TestContext* context) test_generate_entry_and_bits(context); test_generate_no_entry(context); test_generate_consts_and_data(context); + test_generate_fasm(context); test_generate_text(context); test_generate_if(context); test_generate_if_else(context); test_generate_while(context); + test_generate_while_named(context); test_generate_negative(context); test_generate_call(context); test_generate_param_substitution(context); |
