diff --git a/src/codegen/RISCV/codegen.c b/src/codegen/RISCV/codegen.c new file mode 100644 index 0000000..b95b9c3 --- /dev/null +++ b/src/codegen/RISCV/codegen.c @@ -0,0 +1 @@ +// Possibility later diff --git a/src/codegen/RISCV/codegen.h b/src/codegen/RISCV/codegen.h new file mode 100644 index 0000000..616671c --- /dev/null +++ b/src/codegen/RISCV/codegen.h @@ -0,0 +1,3 @@ +// Possibility later + +#pragma once diff --git a/src/codegen/x86/codegen.c b/src/codegen/x86/codegen.c new file mode 100644 index 0000000..e0b317d --- /dev/null +++ b/src/codegen/x86/codegen.c @@ -0,0 +1,80 @@ +#include +#include +#include +#include + +#include "codegen.h" + +#include // tassert + +struct GenState { + // Each bit corresponds with a registers 0-31 where the LSB is 0 + uint32_t registers_in_use; + + unsigned int rsp_offset; +} GEN_STATE; + +void code_gen_init() { + GEN_STATE.registers_in_use = 0; + GEN_STATE.rsp_offset = 0; +} + +char *start_main() { + static char start[256] = "\ +global _start\ +section .text\ +\ +_start:"; + + return start; +} + +char *end_main() { + static char end[256] = "\ +mov rax, 60\ +mov rdi, 0\ +syscall"; + + return end; +} + +char *start_func() { + static char start[256] = "\ +sub rsp, 32\ +mov [rsp], r12\ +mov [rsp+8], r13\ +mov [rsp+16], r14\ +mov [rsp+24], r15"; + + return start; +} + +char *end_func() { + static char end[256] = "\ +mov r12, [rsp]\ +mov r13, [rsp+8]\ +mov r14, [rsp+16]\ +mov r15, [rsp+24]\ +add rsp, 32"; + + return end; +} + +char *init_int_literal(int val) { + GEN_STATE.rsp_offset += 8; + + char *init; + init = (char *)malloc(256 * sizeof(char)); + sprintf(init, "mov [rsp+%d], %d", GEN_STATE.rsp_offset, val); + + return init; +} + +int test_init_int_literal() { + testing_func_setup(); + code_gen_init(); + + tassert(strcmp(init_int_literal(100), "mov [rsp+8], 100") == 0); + + return 0; +} diff --git a/src/codegen/x86/codegen.h b/src/codegen/x86/codegen.h new file mode 100644 index 0000000..4af672d --- /dev/null +++ b/src/codegen/x86/codegen.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +char *start_main(); + +char *end_main(); + +char *start_func(); + +char *end_func(); + +char *init_int_literal(int val); + +int test_init_int_literal(); diff --git a/src/codegen/x86/test_x86.c b/src/codegen/x86/test_x86.c new file mode 100644 index 0000000..50b4948 --- /dev/null +++ b/src/codegen/x86/test_x86.c @@ -0,0 +1,15 @@ +/* + * Run all of the tests at the end of each C file in the lexer module + */ + +#include "codegen.h" +#include + +int test_x86() { + testing_module_setup(); + + test_init_int_literal(); + + testing_module_cleanup(); + return 0; +} diff --git a/src/codegen/x86/test_x86.h b/src/codegen/x86/test_x86.h new file mode 100644 index 0000000..ff48b13 --- /dev/null +++ b/src/codegen/x86/test_x86.h @@ -0,0 +1,10 @@ +/* + * Run all of the tests at the end of each C file in the lexer module + */ + +#pragma once + +#include "codegen.h" +#include + +int test_x86(); diff --git a/src/lexer/lex.c b/src/lexer/lex.c index 000ca7e..2f4f3bf 100644 --- a/src/lexer/lex.c +++ b/src/lexer/lex.c @@ -1,5 +1,6 @@ #include "lex.h" #include // tassert +#include #include #include // memcpy @@ -502,6 +503,8 @@ static const char *ttype_names[] = { const char *ttype_name(TokenType tt) { return ttype_names[tt]; } int test_ttype_from_string() { + testing_func_setup(); + tassert(ttype_from_string("1") == TT_LITERAL); tassert(ttype_from_string("1.2") == TT_LITERAL); diff --git a/src/lexer/test_lexer.c b/src/lexer/test_lexer.c index 120c84e..83a3087 100644 --- a/src/lexer/test_lexer.c +++ b/src/lexer/test_lexer.c @@ -6,10 +6,10 @@ #include int test_lexer() { - testing_setup(); + testing_module_setup(); test_ttype_from_string(); - testing_cleanup(); + testing_module_cleanup(); return 0; } diff --git a/src/lexer/test_lexer.h b/src/lexer/test_lexer.h index 769780d..f4aeb19 100644 --- a/src/lexer/test_lexer.h +++ b/src/lexer/test_lexer.h @@ -1,6 +1,8 @@ /* * Run all of the tests at the end of each C file in the lexer module */ +#pragma once + #include "lex.h" int test_lexer(); diff --git a/src/testing/main.c b/src/testing/main.c index 63038e7..ce9d581 100644 --- a/src/testing/main.c +++ b/src/testing/main.c @@ -1,7 +1,9 @@ #include "lexer/test_lexer.h" +#include "codegen/x86/test_x86.h" int main() { test_lexer(); + test_x86(); return 0; } diff --git a/src/testing/tassert.h b/src/testing/tassert.h index 3f11e5f..01e4212 100644 --- a/src/testing/tassert.h +++ b/src/testing/tassert.h @@ -1,3 +1,5 @@ +#pragma once + #include #define tassert(e) ((void)((e) ? 0 : __assert(#e, __FILE__, __LINE__))) diff --git a/src/testing/test_utils.c b/src/testing/test_utils.c index a2edec0..89b9ad2 100644 --- a/src/testing/test_utils.c +++ b/src/testing/test_utils.c @@ -2,14 +2,21 @@ #include void testing_setup_internal(const char *func_name) { - printf("Running test "); + printf("Running tests from "); fflush(stdout); PRINT_WITH_COLOR(CODE_GREEN, "\"%s\"", func_name); printf(" ...\n"); } void testing_cleanup_internal(const char *func_name) { - printf("Concluded test "); + printf("Concluded tests from "); + fflush(stdout); + PRINT_WITH_COLOR(CODE_GREEN, "\"%s\"", func_name); + printf("\n"); +} + +void testing_single_test_internal(const char *func_name) { + printf("Running "); fflush(stdout); PRINT_WITH_COLOR(CODE_GREEN, "\"%s\"", func_name); printf("\n"); diff --git a/src/testing/test_utils.h b/src/testing/test_utils.h index 7c834db..e0a4f2b 100644 --- a/src/testing/test_utils.h +++ b/src/testing/test_utils.h @@ -1,3 +1,5 @@ +#pragma once + /* Testing utility * Here is an example usage of the testing * @@ -11,30 +13,49 @@ #include int test_lexer() { - testing_setup(); + testing_module_setup(); test_ttype_from_string(); - testing_cleanup(); + testing_module_cleanup(); return 0; } - * After this, include a call to this function in the "testing/main.c" file like how it's done for test_lexer. + * After this, include a call to this function in the "testing/main.c" file like +how it's done for test_lexer. #include "lexer/test_lexer.h" int main() { - test_lexer(); + test_lexer(); - return 0; + return 0; } + * Finally, here is what a test might look like. Make sure to include a call to testing_func_setup at the start. + +int test_ttype_from_string() { + testing_func_setup(); + + tassert(ttype_from_string("1") == TT_LITERAL); + tassert(ttype_from_string("1.2") == TT_LITERAL); + + // ... + + tassert(ttype_from_string(";") == TT_SEMI); + + return 0; +} */ -#define testing_setup() testing_setup_internal(__func__) +#define testing_module_setup() testing_setup_internal(__func__) -#define testing_cleanup() testing_cleanup_internal(__func__) +#define testing_module_cleanup() testing_cleanup_internal(__func__) + +#define testing_func_setup() testing_single_test_internal(__func__) void testing_setup_internal(const char *func_name); void testing_cleanup_internal(const char *func_name); + +void testing_single_test_internal(const char *func_name);