From 16fcd6c8e2feb328b752318613fe963694914d66 Mon Sep 17 00:00:00 2001 From: servostar Date: Thu, 16 May 2024 00:44:02 +0200 Subject: [PATCH] added backend lib --- src/codegen/backend.c | 72 +++++++++++++++++++++++++++++++++++++++++++ src/codegen/backend.h | 68 ++++++++++++++++++++++++++++++++++++++++ src/main.c | 9 ++++++ 3 files changed, 149 insertions(+) create mode 100644 src/codegen/backend.c create mode 100644 src/codegen/backend.h diff --git a/src/codegen/backend.c b/src/codegen/backend.c new file mode 100644 index 0000000..c305961 --- /dev/null +++ b/src/codegen/backend.c @@ -0,0 +1,72 @@ + +#include +#include + +static struct CodegenBackend_t { + codegen_init init_func; + codegen_deinit deinit_func; + codegen codegen_func; + const char* name; +} CodegenBackend; + +BackendError init_backend(void) { + DEBUG("initializing backend: %s", CodegenBackend.name); + + if (CodegenBackend.init_func == NULL) { + ERROR("backend: %s is not properly initialized", CodegenBackend.name); + return NoBackend; + } + + size_t code = CodegenBackend.init_func(); + + if (code) { + ERROR("failed to initialize backend: %s with code: %ld", CodegenBackend.name, code); + return Other; + } + + return Success; +} + +BackendError deinit_backend(void) { + DEBUG("undoing initializing of backend: %s", CodegenBackend.name); + + if (CodegenBackend.deinit_func == NULL) { + ERROR("backend: %s is not properly initialized", CodegenBackend.name); + return NoBackend; + } + + size_t code = CodegenBackend.deinit_func(); + + if (code) { + ERROR("failed to undo initialization of backend: %s with code: %ld", CodegenBackend.name, code); + return Other; + } + + return Success; +} + +BackendError set_backend(const codegen_init init_func, const codegen_deinit deinit_func, const codegen codegen_func, const char* name) { + CodegenBackend.init_func = init_func; + CodegenBackend.deinit_func = deinit_func; + CodegenBackend.codegen_func = codegen_func; + CodegenBackend.name = name; + + return Success; +} + +BackendError generate_code(const AST_NODE_PTR root, void** output) { + DEBUG("generating code with backend: %s", CodegenBackend.name); + + if (CodegenBackend.codegen_func == NULL) { + ERROR("backend: %s is not properly initialized", CodegenBackend.name); + return NoBackend; + } + + size_t code = CodegenBackend.codegen_func(root, output); + if (code) { + ERROR("code generation of backend: %s failed with code: %ld", CodegenBackend.name, code); + return Other; + } + + return Success; +} diff --git a/src/codegen/backend.h b/src/codegen/backend.h new file mode 100644 index 0000000..6e733c3 --- /dev/null +++ b/src/codegen/backend.h @@ -0,0 +1,68 @@ + +#ifndef CODEGN_BACKEND_H_ +#define CODEGN_BACKEND_H_ + +#include + +typedef enum BackendError_t { + Success, + NoBackend, + BackendAlreadySet, + Other +} BackendError; + +/** + * @brief Function called by the compiler backend to generate an intermediate format + * from AST. Returns a custom container for its intermediate language. + */ +typedef size_t (*codegen)(const AST_NODE_PTR, void**); + +/** + * @brief Initialize the code generation backend. + */ +typedef size_t (*codegen_init)(void); + +/** + * @brief Undo initialization of code generation backend. + */ +typedef size_t (*codegen_deinit)(void); + +/** + * @brief Set the backend functions to use + * + * @param init_func the function to call for initializing the backend + * @param deinit_func the function to call for undoing the initialization of the backend + * @param codegen_func the function to call when generating code + * @param name name of the backend + */ +[[nodiscard]] +[[gnu::nonnull(1), gnu::nonnull(2), gnu::nonnull(3), gnu::nonnull(3)]] +BackendError set_backend(const codegen_init init_func, const codegen_deinit deinit_func, const codegen codegen_func, const char* name); + +/** + * @brief Call the initialization function of the backend + * + * @return BackendError + */ +[[nodiscard]] +BackendError init_backend(void); + +/** + * @brief Call the undo initialization function of the backend + * + * @return BackendError + */ +[[nodiscard]] +BackendError deinit_backend(void); + +/** + * @brief Generate intermediate code with the registered backend + * + * @param root the root node of the AST + * @param code output pointer to the intermediate code + * @return BackendError + */ +[[nodiscard]] +BackendError generate_code(const AST_NODE_PTR root, void** code); + +#endif // CODEGN_BACKEND_H_ diff --git a/src/main.c b/src/main.c index 27bca44..45d991c 100644 --- a/src/main.c +++ b/src/main.c @@ -4,6 +4,7 @@ #include #include #include +#include #define LOG_LEVEL LOG_LEVEL_DEBUG @@ -75,6 +76,14 @@ int main(int argc, char *argv[]) { root = AST_new_node(AST_Module, NULL); yyparse(); + set_backend(NULL, NULL, NULL, "LLVM"); + + init_backend(); + + generate_code(root, NULL); + + deinit_backend(); + FILE *output = fopen("test.txt", "w"); AST_fprint_graphviz(output, root); fclose(output);