From 16fcd6c8e2feb328b752318613fe963694914d66 Mon Sep 17 00:00:00 2001 From: servostar Date: Thu, 16 May 2024 00:44:02 +0200 Subject: [PATCH 001/124] 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); From 1e60890919d981d203c7d982c477e3daa71a3b14 Mon Sep 17 00:00:00 2001 From: servostar Date: Thu, 16 May 2024 12:29:11 +0200 Subject: [PATCH 002/124] added type interface --- CMakeLists.txt | 12 ++++ src/llvm/backend.c | 40 ++++++++++++ src/llvm/backend.h | 7 ++ src/llvm/type.c | 159 +++++++++++++++++++++++++++++++++++++++++++++ src/main.c | 6 +- 5 files changed, 222 insertions(+), 2 deletions(-) create mode 100644 src/llvm/backend.c create mode 100644 src/llvm/backend.h create mode 100644 src/llvm/type.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 213143c..74d1733 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,6 +68,18 @@ add_custom_command(OUTPUT ${YACC_GENERATED_SOURCE_FILE} COMMENT "generate C source file for parser" VERBATIM) +# ------------------------------------------------ # +# LLVM backend # +# ------------------------------------------------ # + +# Fetch LLVM link configuration +execute_process(COMMAND llvm-config --libs all + OUTPUT_VARIABLE LLVM_LIBS) +# Strip whitespace from output +string(STRIP "${LLVM_LIBS}" LLVM_LIBS) +# Link all targets to LLVM +link_libraries(${LLVM_LIBS}) + # ------------------------------------------------ # # Source # # ------------------------------------------------ # diff --git a/src/llvm/backend.c b/src/llvm/backend.c new file mode 100644 index 0000000..2f7fc6d --- /dev/null +++ b/src/llvm/backend.c @@ -0,0 +1,40 @@ + +#include +#include +#include +#include +#include +#include + +typedef enum LLVMBackendError_t { + UnresolvedImport +} LLVMBackendError; + +static size_t llvm_backend_codegen(const AST_NODE_PTR, void**) { + // we start with a LLVM module + LLVMContextRef context = LLVMContextCreate(); + LLVMModuleRef module = LLVMModuleCreateWithNameInContext("gemstone application", context); + + + + LLVMDisposeModule(module); + LLVMContextDispose(context); + + return Success; +} + +static size_t llvm_backend_codegen_init(void) { + return Success; +} + +static size_t llvm_backend_codegen_deinit(void) { + return Success; +} + +void llvm_backend_init() { + BackendError err = set_backend(&llvm_backend_codegen_init, &llvm_backend_codegen_deinit, &llvm_backend_codegen, "LLVM"); + + if (err != Success) { + PANIC("unable to init llvm backend: %ld", err); + } +} diff --git a/src/llvm/backend.h b/src/llvm/backend.h new file mode 100644 index 0000000..26ef165 --- /dev/null +++ b/src/llvm/backend.h @@ -0,0 +1,7 @@ + +#ifndef LLVM_CODEGEN_BACKEND_H_ +#define LLVM_CODEGEN_BACKEND_H_ + +void llvm_backend_init(void); + +#endif // LLVM_CODEGEN_BACKEND_H_ diff --git a/src/llvm/type.c b/src/llvm/type.c new file mode 100644 index 0000000..c1b178e --- /dev/null +++ b/src/llvm/type.c @@ -0,0 +1,159 @@ + +#include +#include +#include +#include +#include + +#define BITS_PER_BYTE 8 + +enum Sign_t { + Signed, + Unsigned +}; + +enum Precision_t { + ATOM = 1, + HALF = 2, + SINGLE = 4, + DOUBLE = 8, + QUAD = 16, + OCTO = 32 +}; + +enum Primitive_t { + Int, + Float +}; + +typedef struct CompositeType_t { + const char* name; + enum Sign_t sign; + enum Precision_t scale; + enum Primitive_t prim; +} Composite; + +typedef struct TypeScope_t { + // vector of composite data types + Composite* composites; + size_t composite_len; + size_t composite_cap; +} TypeScope; + +Composite* get_composite_type(const char* name); + +typedef struct CompositeType_t* COMPOSITE_REF; + +#define INVALID_COMPOSITE NULL + +LLVMTypeRef llvm_type_from_composite(LLVMContextRef context, const COMPOSITE_REF composite) { + DEBUG("converting composite to LLVM type..."); + + LLVMTypeRef type = INVALID_COMPOSITE; + + if (composite->prim == Int) { + DEBUG("generating integer LLVM type..."); + + type = LLVMIntTypeInContext(context, composite->scale * BITS_PER_BYTE); + } else if (composite->prim == Float && composite->sign == Signed) { + DEBUG("generating float LLVM type..."); + + switch (composite->scale) { + case HALF: + type = LLVMHalfTypeInContext(context); + case SINGLE: + type = LLVMDoubleTypeInContext(context); + break; + case DOUBLE: + type = LLVMDoubleTypeInContext(context); + break; + case QUAD: + type = LLVMFP128TypeInContext(context); + break; + default: + ERROR("Floating point of precision: %ld npt supported", composite->scale); + break; + } + } + + return type; +} + +double get_scale_factor(const char* keyword) { + if (strcmp(keyword, "half") == 0 || strcmp(keyword, "short") == 0) { + return 0.5; + } else if (strcmp(keyword, "double") == 0 || strcmp(keyword, "long") == 0) { + return 2.0; + } + + PANIC("invalid scale factor: %s", keyword); +} + +enum Precision_t collapse_scale_list(const AST_NODE_PTR list) { + double sum = 1.0; + + for (size_t i = 0; i < list->child_count; i++) { + AST_NODE_PTR scale = AST_get_node(list, i); + + sum *= get_scale_factor(scale->value); + } + + if (sum >= 1.0 && sum <= 32) { + return (enum Precision_t) sum; + } + + PANIC("invalid combination of scale factors"); +} + +enum Sign_t string_to_sign(const char* keyword) { + if (strcmp(keyword, "signed") == 0) { + return Signed; + } else if (strcmp(keyword, "signed") == 0) { + return Unsigned; + } + + PANIC("invalid sign: %s", keyword); +} + +struct CompositeType_t ast_type_to_composite(AST_NODE_PTR type) { + size_t count = type->child_count; + + struct CompositeType_t composite; + composite.name = NULL; + composite.prim = Int; + composite.scale = SINGLE; + composite.sign = Signed; + + if (count == 1) { + // only other type given + composite.prim = resolve_primitive(AST_get_node(type, 0)->value); + + } else if (count == 2) { + // either scale and type + // or sign and type + AST_NODE_PTR first_child = AST_get_node(type, 0); + + switch (first_child->kind) { + case AST_List: + composite.scale = collapse_scale_list(first_child); + break; + case AST_Sign: + composite.sign = string_to_sign(first_child->value); + break; + default: + PANIC("unexpected node kind: %s", AST_node_to_string(first_child)); + } + + composite.prim = resolve_primitive(AST_get_node(type, 1)->value); + + } else if (count == 3) { + // sign, scale and type + composite.sign = string_to_sign(AST_get_node(type, 0)->value); + composite.scale = collapse_scale_list(AST_get_node(type, 0)); + composite.prim = resolve_primitive(AST_get_node(type, 2)->value); + } +} + +void generate_builtin_types(LLVMContextRef context) { + +} diff --git a/src/main.c b/src/main.c index 45d991c..a2078bc 100644 --- a/src/main.c +++ b/src/main.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #define LOG_LEVEL LOG_LEVEL_DEBUG @@ -76,11 +77,12 @@ int main(int argc, char *argv[]) { root = AST_new_node(AST_Module, NULL); yyparse(); - set_backend(NULL, NULL, NULL, "LLVM"); + llvm_backend_init(); init_backend(); - generate_code(root, NULL); + void* code = NULL; + generate_code(root, &code); deinit_backend(); From 2804fd552bdb80ef7cc8b05674601672ac702f87 Mon Sep 17 00:00:00 2001 From: servostar Date: Sun, 19 May 2024 16:07:27 +0200 Subject: [PATCH 003/124] added function backend --- src/codegen/backend.c | 45 ++++++++++------ src/codegen/backend.h | 34 ++++++++++-- src/llvm/backend.c | 14 ++--- src/llvm/function/function.c | 75 ++++++++++++++++++++++++++ src/llvm/function/function.h | 42 +++++++++++++++ src/llvm/{type.c => types/composite.c} | 70 +++++++----------------- src/llvm/types/composite.h | 53 ++++++++++++++++++ src/llvm/types/type.c | 23 ++++++++ src/llvm/types/type.h | 43 +++++++++++++++ src/main.c | 29 ++++++---- 10 files changed, 340 insertions(+), 88 deletions(-) create mode 100644 src/llvm/function/function.c create mode 100644 src/llvm/function/function.h rename src/llvm/{type.c => types/composite.c} (77%) create mode 100644 src/llvm/types/composite.h create mode 100644 src/llvm/types/type.c create mode 100644 src/llvm/types/type.h diff --git a/src/codegen/backend.c b/src/codegen/backend.c index c305961..d2eccac 100644 --- a/src/codegen/backend.c +++ b/src/codegen/backend.c @@ -9,22 +9,35 @@ static struct CodegenBackend_t { const char* name; } CodegenBackend; +BackendError new_backend_error(BackendErrorKind kind) { + return new_backend_impl_error(kind, NULL, NULL); +} + +BackendError new_backend_impl_error(BackendErrorKind kind, AST_NODE_PTR node, const char* message) { + BackendError error; + error.kind = kind; + error.impl.ast_node = node; + error.impl.message = message; + + return error; +} + 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; + return new_backend_error(NoBackend); } - size_t code = CodegenBackend.init_func(); + BackendError code = CodegenBackend.init_func(); - if (code) { + if (code.kind != Success) { ERROR("failed to initialize backend: %s with code: %ld", CodegenBackend.name, code); - return Other; + return code; } - return Success; + return new_backend_error(Success); } BackendError deinit_backend(void) { @@ -32,17 +45,17 @@ BackendError deinit_backend(void) { if (CodegenBackend.deinit_func == NULL) { ERROR("backend: %s is not properly initialized", CodegenBackend.name); - return NoBackend; + return new_backend_error(NoBackend); } - size_t code = CodegenBackend.deinit_func(); + BackendError code = CodegenBackend.deinit_func(); - if (code) { + if (code.kind != Success) { ERROR("failed to undo initialization of backend: %s with code: %ld", CodegenBackend.name, code); - return Other; + return code; } - return Success; + return new_backend_error(Success); } BackendError set_backend(const codegen_init init_func, const codegen_deinit deinit_func, const codegen codegen_func, const char* name) { @@ -51,7 +64,7 @@ BackendError set_backend(const codegen_init init_func, const codegen_deinit dein CodegenBackend.codegen_func = codegen_func; CodegenBackend.name = name; - return Success; + return new_backend_error(Success); } BackendError generate_code(const AST_NODE_PTR root, void** output) { @@ -59,14 +72,14 @@ BackendError generate_code(const AST_NODE_PTR root, void** output) { if (CodegenBackend.codegen_func == NULL) { ERROR("backend: %s is not properly initialized", CodegenBackend.name); - return NoBackend; + return new_backend_error(NoBackend); } - size_t code = CodegenBackend.codegen_func(root, output); - if (code) { + BackendError code = CodegenBackend.codegen_func(root, output); + if (code.kind) { ERROR("code generation of backend: %s failed with code: %ld", CodegenBackend.name, code); - return Other; + return code; } - return Success; + return new_backend_error(Success); } diff --git a/src/codegen/backend.h b/src/codegen/backend.h index 6e733c3..02cbc43 100644 --- a/src/codegen/backend.h +++ b/src/codegen/backend.h @@ -4,28 +4,42 @@ #include -typedef enum BackendError_t { +typedef struct BackendImplError_t { + // faulty AST node + AST_NODE_PTR ast_node; + // error message + const char* message; +} BackendImplError; + +typedef enum BackendErrorKind_t { Success, NoBackend, BackendAlreadySet, - Other + Unimplemented, + // some error occurred in the backend implementation + Implementation +} BackendErrorKind; + +typedef struct BackendError_t { + BackendErrorKind kind; + BackendImplError impl; } 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**); +typedef BackendError (*codegen)(const AST_NODE_PTR, void**); /** * @brief Initialize the code generation backend. */ -typedef size_t (*codegen_init)(void); +typedef BackendError (*codegen_init)(void); /** * @brief Undo initialization of code generation backend. */ -typedef size_t (*codegen_deinit)(void); +typedef BackendError (*codegen_deinit)(void); /** * @brief Set the backend functions to use @@ -65,4 +79,14 @@ BackendError deinit_backend(void); [[nodiscard]] BackendError generate_code(const AST_NODE_PTR root, void** code); +/** + * @brief Create a new backend error + * + * @param kind must ne != Implementation + * @return BackendError + */ +BackendError new_backend_error(BackendErrorKind kind); + +BackendError new_backend_impl_error(BackendErrorKind kind, AST_NODE_PTR node, const char* message); + #endif // CODEGN_BACKEND_H_ diff --git a/src/llvm/backend.c b/src/llvm/backend.c index 2f7fc6d..6c31665 100644 --- a/src/llvm/backend.c +++ b/src/llvm/backend.c @@ -10,7 +10,7 @@ typedef enum LLVMBackendError_t { UnresolvedImport } LLVMBackendError; -static size_t llvm_backend_codegen(const AST_NODE_PTR, void**) { +static BackendError llvm_backend_codegen(const AST_NODE_PTR, void**) { // we start with a LLVM module LLVMContextRef context = LLVMContextCreate(); LLVMModuleRef module = LLVMModuleCreateWithNameInContext("gemstone application", context); @@ -20,21 +20,21 @@ static size_t llvm_backend_codegen(const AST_NODE_PTR, void**) { LLVMDisposeModule(module); LLVMContextDispose(context); - return Success; + return new_backend_error(Success); } -static size_t llvm_backend_codegen_init(void) { - return Success; +static BackendError llvm_backend_codegen_init(void) { + return new_backend_error(Success); } -static size_t llvm_backend_codegen_deinit(void) { - return Success; +static BackendError llvm_backend_codegen_deinit(void) { + return new_backend_error(Success); } void llvm_backend_init() { BackendError err = set_backend(&llvm_backend_codegen_init, &llvm_backend_codegen_deinit, &llvm_backend_codegen, "LLVM"); - if (err != Success) { + if (err.kind != Success) { PANIC("unable to init llvm backend: %ld", err); } } diff --git a/src/llvm/function/function.c b/src/llvm/function/function.c new file mode 100644 index 0000000..73daecc --- /dev/null +++ b/src/llvm/function/function.c @@ -0,0 +1,75 @@ + +#include "ast/ast.h" +#include +#include +#include + +static enum IO_Qualifier_t io_qualifier_from_string(const char* str) { + if (strcmp(str, "in") == 0) { + return In; + } + + return Out; +} + +static enum IO_Qualifier_t merge_qualifier(enum IO_Qualifier_t a, enum IO_Qualifier_t b) { + enum IO_Qualifier_t result = Unspec; + + if (a == In && b == Out) { + result = InOut; + } else if (a == Out && b == In) { + result = InOut; + } + + return result; +} + +static enum IO_Qualifier_t io_qualifier_from_ast_list(const AST_NODE_PTR node) { + // node is expected to be a list + if (node->kind != AST_List) { + PANIC("Node must be of type AST_List: %s", AST_node_to_string(node)); + } + + enum IO_Qualifier_t qualifier = Unspec; + + for (size_t i = 0; i < node->child_count; i++) { + + AST_NODE_PTR qualifier_node = AST_get_node(node, i); + + if (qualifier_node->kind != AST_Qualifyier) { + PANIC("Node must be of type AST_Qualifyier: %s", AST_node_to_string(node)); + } + + enum IO_Qualifier_t local_qualifier = io_qualifier_from_string(qualifier_node->value); + + if (qualifier == Unspec) { + qualifier = local_qualifier; + } else { + qualifier = merge_qualifier(qualifier, local_qualifier); + } + } + + if (qualifier == Unspec) + qualifier = In; + + return qualifier; +} + +GemstoneParam param_from_ast(const AST_NODE_PTR node) { + GemstoneParam param; + + // node is expected to be a parameter + if (node->kind != AST_Parameter) { + PANIC("Node must be of type AST_ParamList: %s", AST_node_to_string(node)); + } + + AST_NODE_PTR qualifier_list = AST_get_node(node, 0); + param.qualifier = io_qualifier_from_ast_list(qualifier_list); + + AST_NODE_PTR param_decl = AST_get_node(node, 1); + AST_NODE_PTR param_type = AST_get_node(param_decl, 0); + param.typename = get_type_from_ast(param_type); + param.name = AST_get_node(param_decl, 1)->value; + + return param; +} diff --git a/src/llvm/function/function.h b/src/llvm/function/function.h new file mode 100644 index 0000000..54df9a4 --- /dev/null +++ b/src/llvm/function/function.h @@ -0,0 +1,42 @@ + +#ifndef LLVM_FUNCTION_H_ +#define LLVM_FUNCTION_H_ + +#include +#include + +enum IO_Qualifier_t { + Unspec, + In, + Out, + InOut +}; + +typedef struct GemstoneParam_t { + const char* name; + enum IO_Qualifier_t qualifier; + GemstoneType typename; +} GemstoneParam; + +typedef struct GemstoneFun_t { + const char* name; + // TODO: add array of parameters +} GemstoneFun; + +/** + * @brief Convert an AST node into a function parameter struct + * + * @param node the node starting a function parameter + * @return GemstoneParam + */ +GemstoneParam param_from_ast(const AST_NODE_PTR node); + +/** + * @brief Convert an AST node into a function + * + * @param node the node starting a function + * @return GemstoneFun + */ +GemstoneFun fun_from_ast(const AST_NODE_PTR node); + +#endif // LLVM_FUNCTION_H_ diff --git a/src/llvm/type.c b/src/llvm/types/composite.c similarity index 77% rename from src/llvm/type.c rename to src/llvm/types/composite.c index c1b178e..416087b 100644 --- a/src/llvm/type.c +++ b/src/llvm/types/composite.c @@ -1,52 +1,8 @@ -#include +#include #include -#include -#include -#include -#define BITS_PER_BYTE 8 - -enum Sign_t { - Signed, - Unsigned -}; - -enum Precision_t { - ATOM = 1, - HALF = 2, - SINGLE = 4, - DOUBLE = 8, - QUAD = 16, - OCTO = 32 -}; - -enum Primitive_t { - Int, - Float -}; - -typedef struct CompositeType_t { - const char* name; - enum Sign_t sign; - enum Precision_t scale; - enum Primitive_t prim; -} Composite; - -typedef struct TypeScope_t { - // vector of composite data types - Composite* composites; - size_t composite_len; - size_t composite_cap; -} TypeScope; - -Composite* get_composite_type(const char* name); - -typedef struct CompositeType_t* COMPOSITE_REF; - -#define INVALID_COMPOSITE NULL - -LLVMTypeRef llvm_type_from_composite(LLVMContextRef context, const COMPOSITE_REF composite) { +LLVMTypeRef llvm_type_from_composite(LLVMContextRef context, const CompositeRef composite) { DEBUG("converting composite to LLVM type..."); LLVMTypeRef type = INVALID_COMPOSITE; @@ -61,6 +17,7 @@ LLVMTypeRef llvm_type_from_composite(LLVMContextRef context, const COMPOSITE_REF switch (composite->scale) { case HALF: type = LLVMHalfTypeInContext(context); + break; case SINGLE: type = LLVMDoubleTypeInContext(context); break; @@ -89,7 +46,7 @@ double get_scale_factor(const char* keyword) { PANIC("invalid scale factor: %s", keyword); } -enum Precision_t collapse_scale_list(const AST_NODE_PTR list) { +enum Scale_t collapse_scale_list(const AST_NODE_PTR list) { double sum = 1.0; for (size_t i = 0; i < list->child_count; i++) { @@ -99,7 +56,7 @@ enum Precision_t collapse_scale_list(const AST_NODE_PTR list) { } if (sum >= 1.0 && sum <= 32) { - return (enum Precision_t) sum; + return (enum Scale_t) sum; } PANIC("invalid combination of scale factors"); @@ -115,6 +72,18 @@ enum Sign_t string_to_sign(const char* keyword) { PANIC("invalid sign: %s", keyword); } +static enum Primitive_t resolve_primitive(const char* typename) { + + if (strcmp(typename, "int") == 0) { + return Int; + } else if (strcmp(typename, "float") == 0) { + return Float; + } + + // TODO: implement lookup of ident type + return Int; +} + struct CompositeType_t ast_type_to_composite(AST_NODE_PTR type) { size_t count = type->child_count; @@ -152,8 +121,7 @@ struct CompositeType_t ast_type_to_composite(AST_NODE_PTR type) { composite.scale = collapse_scale_list(AST_get_node(type, 0)); composite.prim = resolve_primitive(AST_get_node(type, 2)->value); } + + return composite; } -void generate_builtin_types(LLVMContextRef context) { - -} diff --git a/src/llvm/types/composite.h b/src/llvm/types/composite.h new file mode 100644 index 0000000..a8df186 --- /dev/null +++ b/src/llvm/types/composite.h @@ -0,0 +1,53 @@ + +#ifndef LLVM_TYPE_H_ +#define LLVM_TYPE_H_ + +#include +#include +#include +#include + +#define BITS_PER_BYTE 8 + +enum Sign_t { + Signed, + Unsigned +}; + +enum Scale_t { + ATOM = 1, + HALF = 2, + SINGLE = 4, + DOUBLE = 8, + QUAD = 16, + OCTO = 32 +}; + +enum Primitive_t { + Int, + Float +}; + +typedef struct CompositeType_t { + const char* name; + enum Sign_t sign; + enum Scale_t scale; + enum Primitive_t prim; +} Composite; + +typedef struct TypeScope_t { + // vector of composite data types + Composite* composites; + size_t composite_len; + size_t composite_cap; +} TypeScope; + +typedef struct CompositeType_t* CompositeRef; + +#define INVALID_COMPOSITE NULL + +LLVMTypeRef llvm_type_from_composite(LLVMContextRef context, const CompositeRef composite); + +struct CompositeType_t ast_type_to_composite(AST_NODE_PTR type); + +#endif // LLVM_TYPE_H_ diff --git a/src/llvm/types/type.c b/src/llvm/types/type.c new file mode 100644 index 0000000..2b8911d --- /dev/null +++ b/src/llvm/types/type.c @@ -0,0 +1,23 @@ + +#include +#include +#include + +GemstoneType get_type_from_ast(const AST_NODE_PTR type_node) { + if (type_node->kind != AST_Type) { + PANIC("Node must be of type AST_Type: %s", AST_node_to_string(type_node)); + } + + GemstoneType type; + + if (type_node->child_count > 1) { + // must be composite + type.kind = TypeComposite; + type.specs.composite = ast_type_to_composite(type_node); + } else { + // either custom type or box + // TODO: resolve concrete type from TypeScope + } + + return type; +} diff --git a/src/llvm/types/type.h b/src/llvm/types/type.h new file mode 100644 index 0000000..d7e2617 --- /dev/null +++ b/src/llvm/types/type.h @@ -0,0 +1,43 @@ + +#ifndef GEMSTONE_TYPE_H_ +#define GEMSTONE_TYPE_H_ + +#include +#include + +enum GemstoneTypeKind_t { + TypeComposite, + TypeReference, + TypeBox +}; + +struct GemstoneType_t; + +typedef struct GemstoneRefType_t { + struct GemstoneType_t* type; +} GemstoneRefType; + +typedef struct GemstoneType_t { + enum GemstoneTypeKind_t kind; + union GemstoneTypeSpecs_t { + Composite composite; + GemstoneRefType reference; + } specs; +} GemstoneType; + +struct TypeScope_t; + +typedef struct TypeScope_t { + // TODO: array of child scopes + // TODO: array of types +} TypeScope; + +/** + * @brief Convert a type declaration into a concrete type. + * + * @param type A type declaration (either identifier or composite) + * @return GemstoneType + */ +GemstoneType get_type_from_ast(const AST_NODE_PTR type); + +#endif // GEMSTONE_TYPE_H_ diff --git a/src/main.c b/src/main.c index a2078bc..e9c484b 100644 --- a/src/main.c +++ b/src/main.c @@ -53,6 +53,24 @@ void setup(void) { DEBUG("finished starting up gemstone..."); } +void run_backend_codegen() { + llvm_backend_init(); + + BackendError err; + err = init_backend(); + if (err.kind != Success) { + return; + } + + void* code = NULL; + err = generate_code(root, &code); + if (err.kind != Success) { + return; + } + + err = deinit_backend(); +} + int main(int argc, char *argv[]) { setup(); @@ -77,16 +95,9 @@ int main(int argc, char *argv[]) { root = AST_new_node(AST_Module, NULL); yyparse(); - llvm_backend_init(); + run_backend_codegen(); - init_backend(); - - void* code = NULL; - generate_code(root, &code); - - deinit_backend(); - - FILE *output = fopen("test.txt", "w"); + FILE *output = fopen("test.gv", "w"); AST_fprint_graphviz(output, root); fclose(output); AST_delete_node(root); From 17e2cd7110d93344389ed61e88617fb7d0bf1211 Mon Sep 17 00:00:00 2001 From: servostar Date: Tue, 21 May 2024 00:17:11 +0200 Subject: [PATCH 004/124] added scope --- src/llvm/function/function.c | 5 +- src/llvm/function/function.h | 6 +-- src/llvm/types/composite-types.h | 35 ++++++++++++++ src/llvm/types/composite.c | 57 ++++++++++++++++++---- src/llvm/types/composite.h | 41 ++-------------- src/llvm/types/scope.c | 75 +++++++++++++++++++++++++++++ src/llvm/types/scope.h | 83 ++++++++++++++++++++++++++++++++ src/llvm/types/structs.h | 36 ++++++++++++++ src/llvm/types/type.c | 60 +++++++++++++++++++++-- src/llvm/types/type.h | 55 +++++++++++---------- 10 files changed, 367 insertions(+), 86 deletions(-) create mode 100644 src/llvm/types/composite-types.h create mode 100644 src/llvm/types/scope.c create mode 100644 src/llvm/types/scope.h create mode 100644 src/llvm/types/structs.h diff --git a/src/llvm/function/function.c b/src/llvm/function/function.c index 73daecc..08a3e45 100644 --- a/src/llvm/function/function.c +++ b/src/llvm/function/function.c @@ -1,5 +1,6 @@ #include "ast/ast.h" +#include "llvm/types/scope.h" #include #include #include @@ -55,7 +56,7 @@ static enum IO_Qualifier_t io_qualifier_from_ast_list(const AST_NODE_PTR node) { return qualifier; } -GemstoneParam param_from_ast(const AST_NODE_PTR node) { +GemstoneParam param_from_ast(const TypeScopeRef scope, const AST_NODE_PTR node) { GemstoneParam param; // node is expected to be a parameter @@ -68,7 +69,7 @@ GemstoneParam param_from_ast(const AST_NODE_PTR node) { AST_NODE_PTR param_decl = AST_get_node(node, 1); AST_NODE_PTR param_type = AST_get_node(param_decl, 0); - param.typename = get_type_from_ast(param_type); + param.typename = get_type_from_ast(scope, param_type); param.name = AST_get_node(param_decl, 1)->value; return param; diff --git a/src/llvm/function/function.h b/src/llvm/function/function.h index 54df9a4..da74126 100644 --- a/src/llvm/function/function.h +++ b/src/llvm/function/function.h @@ -15,7 +15,7 @@ enum IO_Qualifier_t { typedef struct GemstoneParam_t { const char* name; enum IO_Qualifier_t qualifier; - GemstoneType typename; + GemstoneTypeRef typename; } GemstoneParam; typedef struct GemstoneFun_t { @@ -29,7 +29,7 @@ typedef struct GemstoneFun_t { * @param node the node starting a function parameter * @return GemstoneParam */ -GemstoneParam param_from_ast(const AST_NODE_PTR node); +GemstoneParam param_from_ast(const TypeScopeRef scope, const AST_NODE_PTR node); /** * @brief Convert an AST node into a function @@ -37,6 +37,6 @@ GemstoneParam param_from_ast(const AST_NODE_PTR node); * @param node the node starting a function * @return GemstoneFun */ -GemstoneFun fun_from_ast(const AST_NODE_PTR node); +GemstoneFun fun_from_ast(const TypeScopeRef scope, const AST_NODE_PTR node); #endif // LLVM_FUNCTION_H_ diff --git a/src/llvm/types/composite-types.h b/src/llvm/types/composite-types.h new file mode 100644 index 0000000..49f04c2 --- /dev/null +++ b/src/llvm/types/composite-types.h @@ -0,0 +1,35 @@ + +#ifndef LLVM_TYPES_COMPOSITE_TYPES_H_ +#define LLVM_TYPES_COMPOSITE_TYPES_H_ + +#define BITS_PER_BYTE 8 + +enum Sign_t { + Signed = 1, + Unsigned = -1 +}; + +enum Scale_t { + ATOM = 1, + HALF = 2, + SINGLE = 4, + DOUBLE = 8, + QUAD = 16, + OCTO = 32 +}; + +enum Primitive_t { + Int, + Float +}; + +typedef struct CompositeType_t { + enum Sign_t sign; + enum Scale_t scale; + enum Primitive_t prim; +} Composite; + +typedef struct CompositeType_t* CompositeRef; + + +#endif // LLVM_TYPES_COMPOSITE_TYPES_H_ \ No newline at end of file diff --git a/src/llvm/types/composite.c b/src/llvm/types/composite.c index 416087b..f58d2c3 100644 --- a/src/llvm/types/composite.c +++ b/src/llvm/types/composite.c @@ -1,4 +1,7 @@ +#include "llvm/types/composite-types.h" +#include "llvm/types/scope.h" +#include "llvm/types/structs.h" #include #include @@ -46,8 +49,8 @@ double get_scale_factor(const char* keyword) { PANIC("invalid scale factor: %s", keyword); } -enum Scale_t collapse_scale_list(const AST_NODE_PTR list) { - double sum = 1.0; +enum Scale_t collapse_scale_list(const AST_NODE_PTR list, double base) { + double sum = base; for (size_t i = 0; i < list->child_count; i++) { AST_NODE_PTR scale = AST_get_node(list, i); @@ -84,27 +87,49 @@ static enum Primitive_t resolve_primitive(const char* typename) { return Int; } -struct CompositeType_t ast_type_to_composite(AST_NODE_PTR type) { +struct CompositeType_t ast_type_to_composite(const TypeScopeRef scope, AST_NODE_PTR type) { size_t count = type->child_count; struct CompositeType_t composite; - composite.name = NULL; composite.prim = Int; composite.scale = SINGLE; composite.sign = Signed; if (count == 1) { - // only other type given - composite.prim = resolve_primitive(AST_get_node(type, 0)->value); + const char* typename = AST_get_node(type, 0)->value; + GemstoneTypedefRef known_type = type_scope_get_type_from_name(scope, typename); + + if (known_type == NULL) { + // only other type given + composite.prim = resolve_primitive(typename); + } else if (known_type->type->kind == TypeComposite) { + return known_type->type->specs.composite; + } else { + PANIC("not a composite"); + } } else if (count == 2) { // either scale and type // or sign and type AST_NODE_PTR first_child = AST_get_node(type, 0); + const char* typename = AST_get_node(type, 1)->value; + GemstoneTypedefRef known_type = type_scope_get_type_from_name(scope, typename); + + if (known_type == NULL) { + // only other type given + composite.prim = resolve_primitive(typename); + } else if (known_type->type->kind == TypeComposite) { + composite.prim = known_type->type->specs.composite.prim; + composite.scale = known_type->type->specs.composite.scale; + composite.sign = known_type->type->specs.composite.sign; + } else { + PANIC("not a composite"); + } + switch (first_child->kind) { case AST_List: - composite.scale = collapse_scale_list(first_child); + composite.scale = collapse_scale_list(first_child, (double) composite.scale); break; case AST_Sign: composite.sign = string_to_sign(first_child->value); @@ -113,12 +138,24 @@ struct CompositeType_t ast_type_to_composite(AST_NODE_PTR type) { PANIC("unexpected node kind: %s", AST_node_to_string(first_child)); } - composite.prim = resolve_primitive(AST_get_node(type, 1)->value); - } else if (count == 3) { + const char* typename = AST_get_node(type, 3)->value; + GemstoneTypedefRef known_type = type_scope_get_type_from_name(scope, typename); + + if (known_type == NULL) { + // only other type given + composite.prim = resolve_primitive(typename); + } else if (known_type->type->kind == TypeComposite) { + composite.prim = known_type->type->specs.composite.prim; + composite.scale = known_type->type->specs.composite.scale; + composite.sign = known_type->type->specs.composite.sign; + } else { + PANIC("not a composite"); + } + // sign, scale and type composite.sign = string_to_sign(AST_get_node(type, 0)->value); - composite.scale = collapse_scale_list(AST_get_node(type, 0)); + composite.scale = collapse_scale_list(AST_get_node(type, 1), (double) composite.scale); composite.prim = resolve_primitive(AST_get_node(type, 2)->value); } diff --git a/src/llvm/types/composite.h b/src/llvm/types/composite.h index a8df186..5289c6d 100644 --- a/src/llvm/types/composite.h +++ b/src/llvm/types/composite.h @@ -6,48 +6,13 @@ #include #include #include - -#define BITS_PER_BYTE 8 - -enum Sign_t { - Signed, - Unsigned -}; - -enum Scale_t { - ATOM = 1, - HALF = 2, - SINGLE = 4, - DOUBLE = 8, - QUAD = 16, - OCTO = 32 -}; - -enum Primitive_t { - Int, - Float -}; - -typedef struct CompositeType_t { - const char* name; - enum Sign_t sign; - enum Scale_t scale; - enum Primitive_t prim; -} Composite; - -typedef struct TypeScope_t { - // vector of composite data types - Composite* composites; - size_t composite_len; - size_t composite_cap; -} TypeScope; - -typedef struct CompositeType_t* CompositeRef; +#include +#include #define INVALID_COMPOSITE NULL LLVMTypeRef llvm_type_from_composite(LLVMContextRef context, const CompositeRef composite); -struct CompositeType_t ast_type_to_composite(AST_NODE_PTR type); +struct CompositeType_t ast_type_to_composite(const TypeScopeRef scope, AST_NODE_PTR type); #endif // LLVM_TYPE_H_ diff --git a/src/llvm/types/scope.c b/src/llvm/types/scope.c new file mode 100644 index 0000000..659a99f --- /dev/null +++ b/src/llvm/types/scope.c @@ -0,0 +1,75 @@ + +#include +#include +#include + +struct TypeScope_t { + GArray* types; + GArray* scopes; + TypeScopeRef parent; +}; + +TypeScopeRef type_scope_new() { + TypeScopeRef scope = malloc(sizeof(TypeScope)); + + // neither zero termination no initialisazion to zero needed + scope->scopes = g_array_new(FALSE, FALSE, sizeof(TypeScopeRef)); + scope->types = g_array_new(FALSE, FALSE, sizeof(GemstoneTypedefRef)); + scope->parent = NULL; + + return scope; +} + +void type_scope_append_type(TypeScopeRef scope, GemstoneTypedefRef type) { + g_array_append_val(scope->types, type); +} + +void type_scope_append_scope(TypeScopeRef scope, TypeScopeRef child_scope) { + g_array_append_val(scope->scopes, child_scope); + child_scope->parent = scope; +} + +GemstoneTypedefRef type_scope_get_type(TypeScopeRef scope, size_t index) { + return ((GemstoneTypedefRef*) scope->types->data)[index]; +} + +size_t type_scope_types_len(TypeScopeRef scope) { + return scope->types->len; +} + +size_t type_scope_scopes_len(TypeScopeRef scope) { + return scope->scopes->len; +} + +GemstoneTypedefRef type_scope_get_type_from_name(TypeScopeRef scope, const char* name) { + for (guint i = 0; i < scope->types->len; i++) { + GemstoneTypedefRef typeref = ((GemstoneTypedefRef*) scope->types->data)[i]; + + if (strcmp(typeref->name, name) == 0) { + return typeref; + } + } + + if (scope->parent == NULL) { + return NULL; + } + + return type_scope_get_type_from_name(scope->parent, name); +} + +void type_scope_delete(TypeScopeRef scope) { + + for (guint i = 0; i < scope->scopes->len; i++) { + TypeScopeRef scoperef = ((TypeScopeRef*) scope->scopes->data)[i]; + type_scope_delete(scoperef); + } + + for (guint i = 0; i < scope->types->len; i++) { + // TODO: free gemstone type + } + + g_array_free(scope->scopes, TRUE); + g_array_free(scope->types, TRUE); + + free(scope); +} diff --git a/src/llvm/types/scope.h b/src/llvm/types/scope.h new file mode 100644 index 0000000..3e79003 --- /dev/null +++ b/src/llvm/types/scope.h @@ -0,0 +1,83 @@ + +#ifndef LLVM_TYPE_SCOPE_H_ +#define LLVM_TYPE_SCOPE_H_ + +#include +#include + +typedef struct TypeScope_t TypeScope; + +typedef TypeScope* TypeScopeRef; + +/** + * @brief Allocate a new type scope + * + * @return TypeScopeRef + */ +[[nodiscard("heap allocation")]] +TypeScopeRef type_scope_new(); + +/** + * @brief Add a new type to this scope + * + * @param scope + * @param type + */ +[[gnu::nonnull(1)]] +void type_scope_append_type(TypeScopeRef scope, GemstoneTypedefRef type); + +/** + * @brief Add a new child scope to this scope + * + * @param scope + * @param child_scope + */ +[[gnu::nonnull(1), gnu::nonnull(2)]] +void type_scope_append_scope(TypeScopeRef scope, TypeScopeRef child_scope); + +/** + * @brief Get the type at the specified index in this scope level + * + * @param scope + * @param indx + */ +[[gnu::nonnull(1)]] +GemstoneTypedefRef type_scope_get_type(TypeScopeRef scope, size_t indx); + +/** + * @brief Get the number of types in this scope level + * + * @param scope + * @return size_t + */ +[[gnu::nonnull(1)]] +size_t type_scope_types_len(TypeScopeRef scope); + +/** + * @brief Get the number of child scopes + * + * @param scope + * @return size_t + */ +[[gnu::nonnull(1)]] +size_t type_scope_scopes_len(TypeScopeRef scope); + +/** + * @brief Return a type inside this scope which matches the given name. + * @attention Returns NULL if no type by this name is found. + * + * @param name + * @return GemstoneTypedefRef + */ +[[gnu::nonnull(1)]] +GemstoneTypedefRef type_scope_get_type_from_name(TypeScopeRef scope, const char* name); + +/** + * @brief Delete the scope. Deallocates all child scopes + * + * @param scope + */ +[[gnu::nonnull(1)]] +void type_scope_delete(TypeScopeRef scope); + +#endif // LLVM_TYPE_SCOPE_H_ diff --git a/src/llvm/types/structs.h b/src/llvm/types/structs.h new file mode 100644 index 0000000..cca447e --- /dev/null +++ b/src/llvm/types/structs.h @@ -0,0 +1,36 @@ + +#ifndef LLVM_TYPE_STRUCTS_H_ +#define LLVM_TYPE_STRUCTS_H_ + +#include + +enum GemstoneTypeKind_t { + TypeComposite, + TypeReference, + TypeBox +}; + +struct GemstoneType_t; + +typedef struct GemstoneRefType_t { + struct GemstoneType_t* type; +} GemstoneRefType; + +typedef struct GemstoneType_t { + enum GemstoneTypeKind_t kind; + union GemstoneTypeSpecs_t { + Composite composite; + GemstoneRefType reference; + } specs; +} GemstoneType; + +typedef GemstoneType* GemstoneTypeRef; + +typedef struct GemstoneTypedef_t { + const char* name; + GemstoneTypeRef type; +} GemstoneTypedef; + +typedef GemstoneTypedef* GemstoneTypedefRef; + +#endif // LLVM_TYPE_STRUCTS_H_ diff --git a/src/llvm/types/type.c b/src/llvm/types/type.c index 2b8911d..47f1ef9 100644 --- a/src/llvm/types/type.c +++ b/src/llvm/types/type.c @@ -1,23 +1,73 @@ +#include "llvm/types/structs.h" +#include #include #include #include +#include -GemstoneType get_type_from_ast(const AST_NODE_PTR type_node) { +GemstoneTypeRef get_type_from_ast(const TypeScopeRef scope, const AST_NODE_PTR type_node) { if (type_node->kind != AST_Type) { PANIC("Node must be of type AST_Type: %s", AST_node_to_string(type_node)); } - GemstoneType type; + GemstoneTypeRef type = malloc(sizeof(GemstoneType)); if (type_node->child_count > 1) { // must be composite - type.kind = TypeComposite; - type.specs.composite = ast_type_to_composite(type_node); + type->kind = TypeComposite; + type->specs.composite = ast_type_to_composite(scope, type_node); } else { // either custom type or box - // TODO: resolve concrete type from TypeScope + GemstoneTypedefRef resolved_type = type_scope_get_type_from_name(scope, AST_get_node(type_node, 0)->value); + + if (resolved_type == NULL) { + type->kind = TypeComposite; + type->specs.composite = ast_type_to_composite(scope, type_node); + } else { + free(type); + type = resolved_type->type; + } } return type; } + +GemstoneTypedefRef new_typedefref(GemstoneTypeRef type, const char* name) { + GemstoneTypedefRef typedefref = malloc(sizeof(GemstoneTypedef)); + + typedefref->name = name; + typedefref->type = type; + + return typedefref; +} + +void delete_type(GemstoneTypeRef typeref) { + switch(typeref->kind) { + case TypeReference: + delete_type(typeref->specs.reference.type); + break; + case TypeComposite: + break; + case TypeBox: + PANIC("NOT IMPLEMENTED"); + break; + } + + free(typeref); +} + +void delete_typedefref(GemstoneTypedefRef ref) { + delete_type(ref->type); +} + +GemstoneTypedefRef get_type_def_from_ast(const TypeScopeRef scope, const AST_NODE_PTR typdef) { + if (typdef->kind != AST_Typedef) { + PANIC("node must be of type AST_Typedef"); + } + + GemstoneTypeRef type = get_type_from_ast(scope, AST_get_node(typdef, 0)); + const char* name = AST_get_node(typdef, 1)->value; + + return new_typedefref(type, name); +} diff --git a/src/llvm/types/type.h b/src/llvm/types/type.h index d7e2617..c6a2b1b 100644 --- a/src/llvm/types/type.h +++ b/src/llvm/types/type.h @@ -4,33 +4,8 @@ #include #include - -enum GemstoneTypeKind_t { - TypeComposite, - TypeReference, - TypeBox -}; - -struct GemstoneType_t; - -typedef struct GemstoneRefType_t { - struct GemstoneType_t* type; -} GemstoneRefType; - -typedef struct GemstoneType_t { - enum GemstoneTypeKind_t kind; - union GemstoneTypeSpecs_t { - Composite composite; - GemstoneRefType reference; - } specs; -} GemstoneType; - -struct TypeScope_t; - -typedef struct TypeScope_t { - // TODO: array of child scopes - // TODO: array of types -} TypeScope; +#include +#include /** * @brief Convert a type declaration into a concrete type. @@ -38,6 +13,30 @@ typedef struct TypeScope_t { * @param type A type declaration (either identifier or composite) * @return GemstoneType */ -GemstoneType get_type_from_ast(const AST_NODE_PTR type); +GemstoneTypeRef get_type_from_ast(const TypeScopeRef scope, const AST_NODE_PTR type); + +/** + * @brief Convert the type definition AST into a typedef reference + * + * @param typdef + * @return GemstoneTypedefRef + */ +GemstoneTypedefRef get_type_def_from_ast(const TypeScopeRef scope, const AST_NODE_PTR typdef); + +/** + * @brief Create an new typedefine reference + * + * @param type + * @param name + * @return GemstoneTypedefRef + */ +GemstoneTypedefRef new_typedefref(GemstoneTypeRef type, const char* name); + +/** + * @brief Free the type definition reference and its underlying type + * + * @param ref + */ +void delete_typedefref(GemstoneTypedefRef ref); #endif // GEMSTONE_TYPE_H_ From cc1dc790e1390dc98e3f2720b068b60988327e16 Mon Sep 17 00:00:00 2001 From: servostar Date: Tue, 21 May 2024 00:41:03 +0200 Subject: [PATCH 005/124] added test for typedef --- src/llvm/types/composite.c | 5 +- tests/CMakeLists.txt | 3 +- tests/llvm/CMakeLists.txt | 5 ++ tests/llvm/typedef/CMakeLists.txt | 51 +++++++++++++ tests/llvm/typedef/test.txt | 6 ++ tests/llvm/typedef/typedef.c | 114 ++++++++++++++++++++++++++++++ 6 files changed, 180 insertions(+), 4 deletions(-) create mode 100644 tests/llvm/CMakeLists.txt create mode 100644 tests/llvm/typedef/CMakeLists.txt create mode 100644 tests/llvm/typedef/test.txt create mode 100644 tests/llvm/typedef/typedef.c diff --git a/src/llvm/types/composite.c b/src/llvm/types/composite.c index f58d2c3..c1cbfed 100644 --- a/src/llvm/types/composite.c +++ b/src/llvm/types/composite.c @@ -68,7 +68,7 @@ enum Scale_t collapse_scale_list(const AST_NODE_PTR list, double base) { enum Sign_t string_to_sign(const char* keyword) { if (strcmp(keyword, "signed") == 0) { return Signed; - } else if (strcmp(keyword, "signed") == 0) { + } else if (strcmp(keyword, "unsigned") == 0) { return Unsigned; } @@ -139,7 +139,7 @@ struct CompositeType_t ast_type_to_composite(const TypeScopeRef scope, AST_NODE_ } } else if (count == 3) { - const char* typename = AST_get_node(type, 3)->value; + const char* typename = AST_get_node(type, 2)->value; GemstoneTypedefRef known_type = type_scope_get_type_from_name(scope, typename); if (known_type == NULL) { @@ -156,7 +156,6 @@ struct CompositeType_t ast_type_to_composite(const TypeScopeRef scope, AST_NODE_ // sign, scale and type composite.sign = string_to_sign(AST_get_node(type, 0)->value); composite.scale = collapse_scale_list(AST_get_node(type, 1), (double) composite.scale); - composite.prim = resolve_primitive(AST_get_node(type, 2)->value); } return composite; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 1228d2b..57c4c80 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -9,4 +9,5 @@ set(CTEST_BINARY_DIRECTORY ${PROJECT_BINARY_DIR}/tests) add_subdirectory(logging) add_subdirectory(input_file) add_subdirectory(ast) -add_subdirectory(glib) \ No newline at end of file +add_subdirectory(glib) +add_subdirectory(llvm) \ No newline at end of file diff --git a/tests/llvm/CMakeLists.txt b/tests/llvm/CMakeLists.txt new file mode 100644 index 0000000..5f7867d --- /dev/null +++ b/tests/llvm/CMakeLists.txt @@ -0,0 +1,5 @@ +include(CTest) + +# Provide test to run here or include another CMakeLists.txt + +add_subdirectory(typedef) diff --git a/tests/llvm/typedef/CMakeLists.txt b/tests/llvm/typedef/CMakeLists.txt new file mode 100644 index 0000000..84646ce --- /dev/null +++ b/tests/llvm/typedef/CMakeLists.txt @@ -0,0 +1,51 @@ +include(CTest) + +# ------------------------------------------------ # +# Setup Glib 2.0 # +# ------------------------------------------------ # + +find_package(PkgConfig REQUIRED) +pkg_search_module(GLIB REQUIRED IMPORTED_TARGET glib-2.0) + +# ------------------------------------------------ # +# LLVM backend # +# ------------------------------------------------ # + +# Fetch LLVM link configuration +execute_process(COMMAND llvm-config --libs all + OUTPUT_VARIABLE LLVM_LIBS) +# Strip whitespace from output +string(STRIP "${LLVM_LIBS}" LLVM_LIBS) +# Link all targets to LLVM +link_libraries(${LLVM_LIBS}) + +# ------------------------------------------------ # +# Source # +# ------------------------------------------------ # + +include_directories(${PROJECT_SOURCE_DIR}/src) +include_directories(PRIVATE ${GLIB_INCLUDE_DIRS}) + +file(GLOB_RECURSE SOURCE_FILES ${PROJECT_SOURCE_DIR}/src/*.c) +list(REMOVE_ITEM SOURCE_FILES ${PROJECT_SOURCE_DIR}/src/main.c) + +set(LEX_GENERATED_SOURCE_FILE ${PROJECT_SOURCE_DIR}/src/lex/lexer.ll.c) +set(YACC_GENERATED_SOURCE_FILE ${PROJECT_SOURCE_DIR}/src/yacc/parser.tab.c) + +# ------------------------------------------------------- # +# CTEST 1 +# test typedef + +add_executable(typedef + ${SOURCE_FILES} + ${LEX_GENERATED_SOURCE_FILE} + ${YACC_GENERATED_SOURCE_FILE} + typedef.c) +set_target_properties(typedef + PROPERTIES + OUTPUT_NAME "typedef" + RUNTIME_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/tests/llvm) +target_link_libraries(typedef PkgConfig::GLIB) +add_test(NAME typedef + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests/llvm/typedef + COMMAND ${GEMSTONE_BINARY_DIR}/tests/llvm/typedef test.txt) diff --git a/tests/llvm/typedef/test.txt b/tests/llvm/typedef/test.txt new file mode 100644 index 0000000..dc36998 --- /dev/null +++ b/tests/llvm/typedef/test.txt @@ -0,0 +1,6 @@ + +type unsigned half half int: u8 +type unsigned half int: u16 +type unsigned int: u32 +type unsigned double int: u64 +type unsigned double double int: u128 diff --git a/tests/llvm/typedef/typedef.c b/tests/llvm/typedef/typedef.c new file mode 100644 index 0000000..44d8b62 --- /dev/null +++ b/tests/llvm/typedef/typedef.c @@ -0,0 +1,114 @@ +#include "llvm/types/scope.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LOG_LEVEL LOG_LEVEL_DEBUG + +extern FILE *yyin; +AST_NODE_PTR root; + +/** + * @brief Log a debug message to inform about beginning exit procedures + * + */ +void notify_exit(void) { DEBUG("Exiting gemstone..."); } + +/** + * @brief Closes File after compiling. + * + */ + +void close_file(void) { + if (NULL != yyin) { + fclose(yyin); + } +} + +/** + * @brief Run compiler setup here + * + */ +void setup(void) { + // setup preample + + log_init(); + DEBUG("starting gemstone..."); + +#if LOG_LEVEL <= LOG_LEVEL_DEBUG + atexit(¬ify_exit); +#endif + + // actual setup + AST_init(); + + col_init(); + + lex_init(); + + DEBUG("finished starting up gemstone..."); +} + +void run_backend_codegen() { + llvm_backend_init(); + + BackendError err; + err = init_backend(); + if (err.kind != Success) { + return; + } + + void* code = NULL; + err = generate_code(root, &code); + if (err.kind != Success) { + return; + } + + err = deinit_backend(); +} + +void check_typedef(const AST_NODE_PTR node) { + TypeScopeRef scope = type_scope_new(); + + GemstoneTypedefRef typdef = get_type_def_from_ast(scope, node); + + type_scope_delete(scope); +} + +int main(int argc, char *argv[]) { + + setup(); + atexit(close_file); + + // Check for file input as argument + if (2 != argc) { + INFO("Usage: %s \n", argv[0]); + PANIC("No File could be found"); + } + + // filename as first argument + char *filename = argv[1]; + + FILE *file = fopen(filename, "r"); + + if (NULL == file) { + PANIC("File couldn't be opened!"); + } + yyin = file; + + root = AST_new_node(AST_Module, NULL); + yyparse(); + + for (size_t i = 0; i < root->child_count; i++) { + check_typedef(root->children[i]); + } + + AST_delete_node(root); + return 0; +} From 0f85dc259fe17f8253d851d7fa2d58b7464c70ba Mon Sep 17 00:00:00 2001 From: servostar Date: Tue, 21 May 2024 09:56:41 +0200 Subject: [PATCH 006/124] finished type test --- tests/llvm/typedef/test.txt | 15 +++++++++++ tests/llvm/typedef/typedef.c | 49 ++++++++++++++++++++++++++++-------- 2 files changed, 54 insertions(+), 10 deletions(-) diff --git a/tests/llvm/typedef/test.txt b/tests/llvm/typedef/test.txt index dc36998..c9e1fe0 100644 --- a/tests/llvm/typedef/test.txt +++ b/tests/llvm/typedef/test.txt @@ -4,3 +4,18 @@ type unsigned half int: u16 type unsigned int: u32 type unsigned double int: u64 type unsigned double double int: u128 +type unsigned double double double int: u256 + +type signed half half int: i8 +type signed half int: i16 +type signed int: i32 +type signed double int: i64 +type signed double double int: i128 +type signed double double double int: i256 + +type signed double u8: short_int + +type signed short float: f16 +type signed float: f32 +type signed long float: f64 +type signed long double float: f128 diff --git a/tests/llvm/typedef/typedef.c b/tests/llvm/typedef/typedef.c index 44d8b62..0e2633e 100644 --- a/tests/llvm/typedef/typedef.c +++ b/tests/llvm/typedef/typedef.c @@ -1,4 +1,6 @@ -#include "llvm/types/scope.h" +#include "llvm/types/composite-types.h" +#include +#include #include #include #include @@ -8,8 +10,7 @@ #include #include #include - -#define LOG_LEVEL LOG_LEVEL_DEBUG +#include extern FILE *yyin; AST_NODE_PTR root; @@ -73,12 +74,13 @@ void run_backend_codegen() { err = deinit_backend(); } -void check_typedef(const AST_NODE_PTR node) { - TypeScopeRef scope = type_scope_new(); - - GemstoneTypedefRef typdef = get_type_def_from_ast(scope, node); - - type_scope_delete(scope); +void check_type(const TypeScopeRef scope, const char* name, enum Sign_t sign, enum Scale_t scale, enum Primitive_t prim) { + GemstoneTypedefRef type = type_scope_get_type_from_name(scope, name); + INFO("Expected: %d %d %d Given: %d %d %d", sign, scale, prim, type->type->specs.composite.sign, type->type->specs.composite.scale, type->type->specs.composite.prim); + assert(type->type->kind == TypeComposite); + assert(type->type->specs.composite.prim == prim); + assert(type->type->specs.composite.scale == scale); + assert(type->type->specs.composite.sign == sign); } int main(int argc, char *argv[]) { @@ -105,9 +107,36 @@ int main(int argc, char *argv[]) { root = AST_new_node(AST_Module, NULL); yyparse(); + TypeScopeRef scope = type_scope_new(); + for (size_t i = 0; i < root->child_count; i++) { - check_typedef(root->children[i]); + GemstoneTypedefRef typdef = get_type_def_from_ast(scope, root->children[i]); + + type_scope_append_type(scope, typdef); } + + check_type(scope, "u8", Unsigned, ATOM, Int); + check_type(scope, "u16", Unsigned, HALF, Int); + check_type(scope, "u32", Unsigned, SINGLE, Int); + check_type(scope, "u64", Unsigned, DOUBLE, Int); + check_type(scope, "u128", Unsigned, QUAD, Int); + check_type(scope, "u256", Unsigned, OCTO, Int); + + check_type(scope, "i8", Signed, ATOM, Int); + check_type(scope, "i16", Signed, HALF, Int); + check_type(scope, "i32", Signed, SINGLE, Int); + check_type(scope, "i64", Signed, DOUBLE, Int); + check_type(scope, "i128", Signed, QUAD, Int); + check_type(scope, "i256", Signed, OCTO, Int); + + check_type(scope, "short_int", Signed, HALF, Int); + + check_type(scope, "f16", Signed, HALF, Float); + check_type(scope, "f32", Signed, SINGLE, Float); + check_type(scope, "f64", Signed, DOUBLE, Float); + check_type(scope, "f128", Signed, QUAD, Float); + + type_scope_delete(scope); AST_delete_node(root); return 0; From 690e847d548394d16f89f97d7dec58fe4dac87d6 Mon Sep 17 00:00:00 2001 From: servostar Date: Tue, 21 May 2024 10:15:56 +0200 Subject: [PATCH 007/124] added param test --- tests/llvm/CMakeLists.txt | 1 + tests/llvm/params/CMakeLists.txt | 51 +++++++++++++ tests/llvm/params/params.c | 121 +++++++++++++++++++++++++++++++ tests/llvm/params/test.txt | 4 + 4 files changed, 177 insertions(+) create mode 100644 tests/llvm/params/CMakeLists.txt create mode 100644 tests/llvm/params/params.c create mode 100644 tests/llvm/params/test.txt diff --git a/tests/llvm/CMakeLists.txt b/tests/llvm/CMakeLists.txt index 5f7867d..fe495c7 100644 --- a/tests/llvm/CMakeLists.txt +++ b/tests/llvm/CMakeLists.txt @@ -3,3 +3,4 @@ include(CTest) # Provide test to run here or include another CMakeLists.txt add_subdirectory(typedef) +add_subdirectory(params) diff --git a/tests/llvm/params/CMakeLists.txt b/tests/llvm/params/CMakeLists.txt new file mode 100644 index 0000000..712438d --- /dev/null +++ b/tests/llvm/params/CMakeLists.txt @@ -0,0 +1,51 @@ +include(CTest) + +# ------------------------------------------------ # +# Setup Glib 2.0 # +# ------------------------------------------------ # + +find_package(PkgConfig REQUIRED) +pkg_search_module(GLIB REQUIRED IMPORTED_TARGET glib-2.0) + +# ------------------------------------------------ # +# LLVM backend # +# ------------------------------------------------ # + +# Fetch LLVM link configuration +execute_process(COMMAND llvm-config --libs all + OUTPUT_VARIABLE LLVM_LIBS) +# Strip whitespace from output +string(STRIP "${LLVM_LIBS}" LLVM_LIBS) +# Link all targets to LLVM +link_libraries(${LLVM_LIBS}) + +# ------------------------------------------------ # +# Source # +# ------------------------------------------------ # + +include_directories(${PROJECT_SOURCE_DIR}/src) +include_directories(PRIVATE ${GLIB_INCLUDE_DIRS}) + +file(GLOB_RECURSE SOURCE_FILES ${PROJECT_SOURCE_DIR}/src/*.c) +list(REMOVE_ITEM SOURCE_FILES ${PROJECT_SOURCE_DIR}/src/main.c) + +set(LEX_GENERATED_SOURCE_FILE ${PROJECT_SOURCE_DIR}/src/lex/lexer.ll.c) +set(YACC_GENERATED_SOURCE_FILE ${PROJECT_SOURCE_DIR}/src/yacc/parser.tab.c) + +# ------------------------------------------------------- # +# CTEST 1 +# test parameter declarations + +add_executable(params + ${SOURCE_FILES} + ${LEX_GENERATED_SOURCE_FILE} + ${YACC_GENERATED_SOURCE_FILE} + params.c) +set_target_properties(params + PROPERTIES + OUTPUT_NAME "params" + RUNTIME_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/tests/llvm) +target_link_libraries(params PkgConfig::GLIB) +add_test(NAME params + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests/llvm/params + COMMAND ${GEMSTONE_BINARY_DIR}/tests/llvm/params test.txt) diff --git a/tests/llvm/params/params.c b/tests/llvm/params/params.c new file mode 100644 index 0000000..8aa96d3 --- /dev/null +++ b/tests/llvm/params/params.c @@ -0,0 +1,121 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern FILE *yyin; +AST_NODE_PTR root; + +/** + * @brief Log a debug message to inform about beginning exit procedures + * + */ +void notify_exit(void) { DEBUG("Exiting gemstone..."); } + +/** + * @brief Closes File after compiling. + * + */ + +void close_file(void) { + if (NULL != yyin) { + fclose(yyin); + } +} + +/** + * @brief Run compiler setup here + * + */ +void setup(void) { + // setup preample + + log_init(); + DEBUG("starting gemstone..."); + +#if LOG_LEVEL <= LOG_LEVEL_DEBUG + atexit(¬ify_exit); +#endif + + // actual setup + AST_init(); + + col_init(); + + lex_init(); + + DEBUG("finished starting up gemstone..."); +} + +void run_backend_codegen() { + llvm_backend_init(); + + BackendError err; + err = init_backend(); + if (err.kind != Success) { + return; + } + + void* code = NULL; + err = generate_code(root, &code); + if (err.kind != Success) { + return; + } + + err = deinit_backend(); +} + +int main(int argc, char *argv[]) { + + setup(); + atexit(close_file); + + // Check for file input as argument + if (2 != argc) { + INFO("Usage: %s \n", argv[0]); + PANIC("No File could be found"); + } + + // filename as first argument + char *filename = argv[1]; + + FILE *file = fopen(filename, "r"); + + if (NULL == file) { + PANIC("File couldn't be opened!"); + } + yyin = file; + + root = AST_new_node(AST_Module, NULL); + yyparse(); + + TypeScopeRef scope = type_scope_new(); + + AST_NODE_PTR fun = AST_get_node(root, 0); + AST_NODE_PTR list = AST_get_node(fun, 1); + + for (size_t i = 0; i < list->child_count; i++) { + AST_NODE_PTR param_list = AST_get_node(list, i); + + for (size_t k = 0; k < param_list->child_count; k++) { + AST_NODE_PTR param = AST_get_node(param_list, i); + + GemstoneParam par = param_from_ast(scope, param); + } + } + + type_scope_delete(scope); + + AST_delete_node(root); + return 0; +} diff --git a/tests/llvm/params/test.txt b/tests/llvm/params/test.txt new file mode 100644 index 0000000..fa2dc57 --- /dev/null +++ b/tests/llvm/params/test.txt @@ -0,0 +1,4 @@ + +fun a(in int: a, in float: b) { + a = 0 +} \ No newline at end of file From 4a3b974d9fcc0a225ab77e72b4f32590d6c3bad5 Mon Sep 17 00:00:00 2001 From: servostar Date: Tue, 21 May 2024 11:59:44 +0200 Subject: [PATCH 008/124] added functions to scope --- src/llvm/function/function-types.h | 28 ++++++++++++++++++++++++ src/llvm/function/function.c | 35 ++++++++++++++++++++++++++++-- src/llvm/function/function.h | 32 ++++++++++----------------- src/llvm/types/scope.c | 24 ++++++++++++++++++++ src/llvm/types/scope.h | 19 ++++++++++++++++ tests/llvm/params/params.c | 15 ++++--------- tests/llvm/params/test.txt | 2 +- 7 files changed, 120 insertions(+), 35 deletions(-) create mode 100644 src/llvm/function/function-types.h diff --git a/src/llvm/function/function-types.h b/src/llvm/function/function-types.h new file mode 100644 index 0000000..0af0c1a --- /dev/null +++ b/src/llvm/function/function-types.h @@ -0,0 +1,28 @@ + +#ifndef LLVM_TYPES_FUNCTION_TYPES_H_ +#define LLVM_TYPES_FUNCTION_TYPES_H_ + +#include +#include + +enum IO_Qualifier_t { + Unspec, + In, + Out, + InOut +}; + +typedef struct GemstoneParam_t { + const char* name; + enum IO_Qualifier_t qualifier; + GemstoneTypeRef typename; +} GemstoneParam; + +typedef struct GemstoneFun_t { + const char* name; + GArray* params; +} GemstoneFun; + +typedef GemstoneFun* GemstoneFunRef; + +#endif // LLVM_TYPES_FUNCTION_TYPES_H_ diff --git a/src/llvm/function/function.c b/src/llvm/function/function.c index 08a3e45..40323ba 100644 --- a/src/llvm/function/function.c +++ b/src/llvm/function/function.c @@ -1,6 +1,6 @@ -#include "ast/ast.h" -#include "llvm/types/scope.h" +#include +#include #include #include #include @@ -74,3 +74,34 @@ GemstoneParam param_from_ast(const TypeScopeRef scope, const AST_NODE_PTR node) return param; } + +GemstoneFunRef fun_from_ast(const TypeScopeRef scope, const AST_NODE_PTR node) { + if (node->kind != AST_Fun) { + PANIC("Node must be of type AST_Fun: %s", AST_node_to_string(node)); + } + + GemstoneFunRef function = malloc(sizeof(GemstoneFun)); + function->name = AST_get_node(node, 0)->value; + function->params = g_array_new(FALSE, FALSE, sizeof(GemstoneParam)); + + AST_NODE_PTR list = AST_get_node(node, 1); + for (size_t i = 0; i < list->child_count; i++) { + AST_NODE_PTR param_list = AST_get_node(list, i); + + for (size_t k = 0; k < param_list->child_count; k++) { + AST_NODE_PTR param = AST_get_node(param_list, k); + + GemstoneParam par = param_from_ast(scope, param); + + g_array_append_val(function->params, par); + } + } + + // TODO: parse function body + return function; +} + +void fun_delete(const GemstoneFunRef fun) { + g_array_free(fun->params, TRUE); + free(fun); +} diff --git a/src/llvm/function/function.h b/src/llvm/function/function.h index da74126..3e6ceec 100644 --- a/src/llvm/function/function.h +++ b/src/llvm/function/function.h @@ -3,25 +3,8 @@ #define LLVM_FUNCTION_H_ #include -#include - -enum IO_Qualifier_t { - Unspec, - In, - Out, - InOut -}; - -typedef struct GemstoneParam_t { - const char* name; - enum IO_Qualifier_t qualifier; - GemstoneTypeRef typename; -} GemstoneParam; - -typedef struct GemstoneFun_t { - const char* name; - // TODO: add array of parameters -} GemstoneFun; +#include +#include /** * @brief Convert an AST node into a function parameter struct @@ -35,8 +18,15 @@ GemstoneParam param_from_ast(const TypeScopeRef scope, const AST_NODE_PTR node); * @brief Convert an AST node into a function * * @param node the node starting a function - * @return GemstoneFun + * @return GemstoneFunRef */ -GemstoneFun fun_from_ast(const TypeScopeRef scope, const AST_NODE_PTR node); +GemstoneFunRef fun_from_ast(const TypeScopeRef scope, const AST_NODE_PTR node); + +/** + * @brief Delete the given function + * + * @param fun + */ +void fun_delete(const GemstoneFunRef fun); #endif // LLVM_FUNCTION_H_ diff --git a/src/llvm/types/scope.c b/src/llvm/types/scope.c index 659a99f..347b83e 100644 --- a/src/llvm/types/scope.c +++ b/src/llvm/types/scope.c @@ -1,4 +1,5 @@ +#include #include #include #include @@ -6,6 +7,7 @@ struct TypeScope_t { GArray* types; GArray* scopes; + GArray* funcs; TypeScopeRef parent; }; @@ -15,6 +17,7 @@ TypeScopeRef type_scope_new() { // neither zero termination no initialisazion to zero needed scope->scopes = g_array_new(FALSE, FALSE, sizeof(TypeScopeRef)); scope->types = g_array_new(FALSE, FALSE, sizeof(GemstoneTypedefRef)); + scope->funcs = g_array_new(FALSE, FALSE, sizeof(GemstoneFunRef)); scope->parent = NULL; return scope; @@ -70,6 +73,27 @@ void type_scope_delete(TypeScopeRef scope) { g_array_free(scope->scopes, TRUE); g_array_free(scope->types, TRUE); + g_array_free(scope->funcs, TRUE); free(scope); } + +void type_scope_add_fun(TypeScopeRef scope, GemstoneFunRef function) { + g_array_append_val(scope->funcs, function); +} + +GemstoneFunRef type_scope_get_fun_from_name(TypeScopeRef scope, const char* name) { + for (guint i = 0; i < scope->funcs->len; i++) { + GemstoneFunRef funref = ((GemstoneFunRef*) scope->funcs->data)[i]; + + if (strcmp(funref->name, name) == 0) { + return funref; + } + } + + if (scope->parent == NULL) { + return NULL; + } + + return type_scope_get_fun_from_name(scope->parent, name); +} diff --git a/src/llvm/types/scope.h b/src/llvm/types/scope.h index 3e79003..c58a367 100644 --- a/src/llvm/types/scope.h +++ b/src/llvm/types/scope.h @@ -2,6 +2,7 @@ #ifndef LLVM_TYPE_SCOPE_H_ #define LLVM_TYPE_SCOPE_H_ +#include #include #include @@ -80,4 +81,22 @@ GemstoneTypedefRef type_scope_get_type_from_name(TypeScopeRef scope, const char* [[gnu::nonnull(1)]] void type_scope_delete(TypeScopeRef scope); +/** + * @brief Add a function ot the type scope + * + * @param scope + * @param function + */ +void type_scope_add_fun(TypeScopeRef scope, GemstoneFunRef function); + +/** + * @brief Attempts to find a function by its name in the current scope + * + * @param scope + * @param name + * @return GemstoneFunRef + */ +[[gnu::nonnull(1), gnu::nonnull(2)]] +GemstoneFunRef type_scope_get_fun_from_name(TypeScopeRef scope, const char* name); + #endif // LLVM_TYPE_SCOPE_H_ diff --git a/tests/llvm/params/params.c b/tests/llvm/params/params.c index 8aa96d3..36a2ea4 100644 --- a/tests/llvm/params/params.c +++ b/tests/llvm/params/params.c @@ -102,17 +102,10 @@ int main(int argc, char *argv[]) { TypeScopeRef scope = type_scope_new(); AST_NODE_PTR fun = AST_get_node(root, 0); - AST_NODE_PTR list = AST_get_node(fun, 1); - - for (size_t i = 0; i < list->child_count; i++) { - AST_NODE_PTR param_list = AST_get_node(list, i); - - for (size_t k = 0; k < param_list->child_count; k++) { - AST_NODE_PTR param = AST_get_node(param_list, i); - - GemstoneParam par = param_from_ast(scope, param); - } - } + + GemstoneFunRef function = fun_from_ast(scope, fun); + type_scope_add_fun(scope, function); + assert(function->params->len == 3); type_scope_delete(scope); diff --git a/tests/llvm/params/test.txt b/tests/llvm/params/test.txt index fa2dc57..1b94e93 100644 --- a/tests/llvm/params/test.txt +++ b/tests/llvm/params/test.txt @@ -1,4 +1,4 @@ -fun a(in int: a, in float: b) { +fun a(in out int: a, in float: b)(out float: c) { a = 0 } \ No newline at end of file From fa32df1010863a607be1430ad386845d8f819d33 Mon Sep 17 00:00:00 2001 From: servostar Date: Tue, 21 May 2024 13:08:41 +0200 Subject: [PATCH 009/124] backend parses type and function declarations --- src/llvm/backend.c | 34 ++++++++++++++++++++++++++++++++-- src/llvm/function/function.c | 15 +++++++++++++++ src/llvm/types/type.c | 14 ++++++++++++++ src/llvm/types/type.h | 10 ++++++++++ 4 files changed, 71 insertions(+), 2 deletions(-) diff --git a/src/llvm/backend.c b/src/llvm/backend.c index 6c31665..eccdd14 100644 --- a/src/llvm/backend.c +++ b/src/llvm/backend.c @@ -1,4 +1,9 @@ +#include +#include +#include +#include +#include #include #include #include @@ -10,12 +15,37 @@ typedef enum LLVMBackendError_t { UnresolvedImport } LLVMBackendError; -static BackendError llvm_backend_codegen(const AST_NODE_PTR, void**) { +static BackendError llvm_backend_codegen(const AST_NODE_PTR module_node, void**) { // we start with a LLVM module LLVMContextRef context = LLVMContextCreate(); LLVMModuleRef module = LLVMModuleCreateWithNameInContext("gemstone application", context); - + TypeScopeRef global_scope = type_scope_new(); + + for (size_t i = 0; i < module_node->child_count; i++) { + // iterate over all nodes in module + // can either be a function, box, definition, declaration or typedefine + + AST_NODE_PTR global_node = AST_get_node(module_node, i); + + GemstoneTypedefRef typedefref; + GemstoneFunRef funref; + + switch (global_node->kind) { + case AST_Typedef: + typedefref = get_type_def_from_ast(global_scope, global_node); + type_scope_append_type(global_scope, typedefref); + break; + case AST_Fun: + funref = fun_from_ast(global_scope, global_node); + type_scope_add_fun(global_scope, funref); + break; + default: + PANIC("NOT IMPLEMENTED"); + } + } + + type_scope_delete(global_scope); LLVMDisposeModule(module); LLVMContextDispose(context); diff --git a/src/llvm/function/function.c b/src/llvm/function/function.c index 40323ba..4e8c643 100644 --- a/src/llvm/function/function.c +++ b/src/llvm/function/function.c @@ -1,5 +1,7 @@ +#include "llvm/function/function-types.h" #include +#include #include #include #include @@ -105,3 +107,16 @@ void fun_delete(const GemstoneFunRef fun) { g_array_free(fun->params, TRUE); free(fun); } + +LLVMTypeRef get_gemstone_function_llvm_signature(LLVMContextRef context, GemstoneFunRef function) { + unsigned int param_count = function->params->len; + + LLVMTypeRef* params = malloc(sizeof(LLVMTypeRef)); + + for (size_t i = 0; i < param_count; i++) { + GemstoneParam* gem_param = ((GemstoneParam*) function->params->data) + i; + params[i] = llvm_type_from_gemstone_type(context, gem_param->typename); + } + + return LLVMFunctionType(LLVMVoidType(), params, param_count, 0); +} diff --git a/src/llvm/types/type.c b/src/llvm/types/type.c index 47f1ef9..f39c053 100644 --- a/src/llvm/types/type.c +++ b/src/llvm/types/type.c @@ -71,3 +71,17 @@ GemstoneTypedefRef get_type_def_from_ast(const TypeScopeRef scope, const AST_NOD return new_typedefref(type, name); } + +LLVMTypeRef llvm_type_from_gemstone_type(LLVMContextRef context, GemstoneTypeRef type) { + LLVMTypeRef llvmTypeRef = NULL; + + switch (type->kind) { + case TypeComposite: + llvmTypeRef = llvm_type_from_composite(context, &type->specs.composite); + break; + default: + PANIC("NOT IMPLEMENTED"); + } + + return llvmTypeRef; +} diff --git a/src/llvm/types/type.h b/src/llvm/types/type.h index c6a2b1b..135319a 100644 --- a/src/llvm/types/type.h +++ b/src/llvm/types/type.h @@ -3,6 +3,7 @@ #define GEMSTONE_TYPE_H_ #include +#include #include #include #include @@ -32,6 +33,15 @@ GemstoneTypedefRef get_type_def_from_ast(const TypeScopeRef scope, const AST_NOD */ GemstoneTypedefRef new_typedefref(GemstoneTypeRef type, const char* name); +/** + * @brief Create the LLVM function signature + * + * @param context + * @param type + * @return LLVMTypeRef + */ +LLVMTypeRef llvm_type_from_gemstone_type(LLVMContextRef context, GemstoneTypeRef type); + /** * @brief Free the type definition reference and its underlying type * From 6967770d0e5c39751b1d73c31069e62f70d2a244 Mon Sep 17 00:00:00 2001 From: servostar Date: Tue, 21 May 2024 14:36:37 +0200 Subject: [PATCH 010/124] added declarations --- src/llvm/backend.c | 9 ++++++ src/llvm/decl/variable.c | 65 ++++++++++++++++++++++++++++++++++++++++ src/llvm/decl/variable.h | 11 +++++++ src/llvm/types/scope.c | 16 ++++++++++ src/llvm/types/scope.h | 17 +++++++++++ 5 files changed, 118 insertions(+) create mode 100644 src/llvm/decl/variable.c create mode 100644 src/llvm/decl/variable.h diff --git a/src/llvm/backend.c b/src/llvm/backend.c index eccdd14..3621338 100644 --- a/src/llvm/backend.c +++ b/src/llvm/backend.c @@ -1,4 +1,5 @@ +#include #include #include #include @@ -30,6 +31,7 @@ static BackendError llvm_backend_codegen(const AST_NODE_PTR module_node, void**) GemstoneTypedefRef typedefref; GemstoneFunRef funref; + GArray* decls; switch (global_node->kind) { case AST_Typedef: @@ -40,6 +42,13 @@ static BackendError llvm_backend_codegen(const AST_NODE_PTR module_node, void**) funref = fun_from_ast(global_scope, global_node); type_scope_add_fun(global_scope, funref); break; + case AST_Decl: + decls = declaration_from_ast(global_scope, global_node); + for (size_t i = 0; i < decls->len; i++) { + GemstoneDeclRef decl = ((GemstoneDeclRef*) decls->data)[i]; + type_scope_add_variable(global_scope, decl); + } + break; default: PANIC("NOT IMPLEMENTED"); } diff --git a/src/llvm/decl/variable.c b/src/llvm/decl/variable.c new file mode 100644 index 0000000..15e902b --- /dev/null +++ b/src/llvm/decl/variable.c @@ -0,0 +1,65 @@ +#include "llvm/types/structs.h" +#include +#include +#include +#include +#include + +static StorageQualifier get_storage_qualifier_from_ast(AST_NODE_PTR storageQualifierNode) { + if (storageQualifierNode->kind != AST_Storage) { + PANIC("Node must be of type AST_Fun: %s", AST_node_to_string(storageQualifierNode)); + } + + StorageQualifier storageQualifier; + + if (strcmp(storageQualifierNode->value, "local") == 0) { + storageQualifier = StorageQualifierLocal; + } else if (strcmp(storageQualifierNode->value, "static") == 0) { + storageQualifier = StorageQualifierStatic; + } else if (strcmp(storageQualifierNode->value, "global") == 0) { + storageQualifier = StorageQualifierGlobal; + } else { + PANIC("unknown storage qualifier: %s", storageQualifierNode->value); + } + + return storageQualifier; +} + +GArray* declaration_from_ast(TypeScopeRef scope, const AST_NODE_PTR node) { + if (node->kind != AST_Decl) { + PANIC("Node must be of type AST_Fun: %s", AST_node_to_string(node)); + } + + GArray* decls = g_array_new(FALSE, FALSE, sizeof(GemstoneDeclRef)); + + AST_NODE_PTR first_child = AST_get_node(node, 0); + + StorageQualifier qualifier = StorageQualifierLocal; + GemstoneTypeRef type = NULL; + AST_NODE_PTR list = NULL; + + if (first_child->kind == AST_Storage) { + qualifier = get_storage_qualifier_from_ast(first_child); + type = get_type_from_ast(scope, AST_get_node(node, 1)); + list = AST_get_node(node, 2); + + } else { + type = get_type_from_ast(scope, first_child); + list = AST_get_node(node, 1); + } + + if (list->kind != AST_IdentList) { + PANIC("Node must be of type AST_IdentList: %s", AST_node_to_string(node)); + } + + for (size_t i = 0; i < list->child_count; i++) { + GemstoneDeclRef ref = malloc(sizeof(GemstoneDecl)); + ref->name = AST_get_node(list, i)->value; + ref->storageQualifier = qualifier; + ref->type = type; + + g_array_append_val(decls, ref); + } + + return decls; +} diff --git a/src/llvm/decl/variable.h b/src/llvm/decl/variable.h new file mode 100644 index 0000000..8548391 --- /dev/null +++ b/src/llvm/decl/variable.h @@ -0,0 +1,11 @@ + +#ifndef LLVM_DECL_VAR_H_ +#define LLVM_DECL_VAR_H_ + +#include +#include +#include + +GArray* declaration_from_ast(TypeScopeRef scope, const AST_NODE_PTR node); + +#endif // LLVM_DECL_VAR_H_ diff --git a/src/llvm/types/scope.c b/src/llvm/types/scope.c index 347b83e..851da03 100644 --- a/src/llvm/types/scope.c +++ b/src/llvm/types/scope.c @@ -1,4 +1,5 @@ +#include #include #include #include @@ -8,6 +9,7 @@ struct TypeScope_t { GArray* types; GArray* scopes; GArray* funcs; + GHashTable* vars; TypeScopeRef parent; }; @@ -18,6 +20,7 @@ TypeScopeRef type_scope_new() { scope->scopes = g_array_new(FALSE, FALSE, sizeof(TypeScopeRef)); scope->types = g_array_new(FALSE, FALSE, sizeof(GemstoneTypedefRef)); scope->funcs = g_array_new(FALSE, FALSE, sizeof(GemstoneFunRef)); + scope->vars = g_hash_table_new(g_str_hash, g_str_equal); scope->parent = NULL; return scope; @@ -74,10 +77,23 @@ void type_scope_delete(TypeScopeRef scope) { g_array_free(scope->scopes, TRUE); g_array_free(scope->types, TRUE); g_array_free(scope->funcs, TRUE); + g_hash_table_destroy(scope->vars); free(scope); } +void type_scope_add_variable(TypeScopeRef scope, GemstoneDeclRef decl) { + g_hash_table_insert(scope->vars, (gpointer) decl->name, decl); +} + +GemstoneDeclRef type_scope_get_variable(TypeScopeRef scope, const char* name) { + if (g_hash_table_contains(scope->vars, name)) { + return g_hash_table_lookup(scope->vars, name); + } + + return NULL; +} + void type_scope_add_fun(TypeScopeRef scope, GemstoneFunRef function) { g_array_append_val(scope->funcs, function); } diff --git a/src/llvm/types/scope.h b/src/llvm/types/scope.h index c58a367..a8beac2 100644 --- a/src/llvm/types/scope.h +++ b/src/llvm/types/scope.h @@ -6,6 +6,21 @@ #include #include +typedef enum StorageQualifier_t { + StorageQualifierLocal, + StorageQualifierStatic, + StorageQualifierGlobal +} StorageQualifier; + +// Varaible declaration +typedef struct GemstoneDecl_t { + const char* name; + StorageQualifier storageQualifier; + GemstoneTypeRef type; +} GemstoneDecl; + +typedef GemstoneDecl* GemstoneDeclRef; + typedef struct TypeScope_t TypeScope; typedef TypeScope* TypeScopeRef; @@ -99,4 +114,6 @@ void type_scope_add_fun(TypeScopeRef scope, GemstoneFunRef function); [[gnu::nonnull(1), gnu::nonnull(2)]] GemstoneFunRef type_scope_get_fun_from_name(TypeScopeRef scope, const char* name); +void type_scope_add_variable(TypeScopeRef scope, GemstoneDeclRef decl); + #endif // LLVM_TYPE_SCOPE_H_ From 3b78d117b5e8d0e79f5b4b7a36b3e189e42d1667 Mon Sep 17 00:00:00 2001 From: servostar Date: Tue, 21 May 2024 15:55:22 +0200 Subject: [PATCH 011/124] added default values for composites --- src/llvm/backend.c | 2 ++ src/llvm/decl/variable.c | 29 ++++++++++++++++++++++++++++- src/llvm/types/type.c | 33 +++++++++++++++++++++++++++++++++ src/llvm/types/type.h | 2 ++ 4 files changed, 65 insertions(+), 1 deletion(-) diff --git a/src/llvm/backend.c b/src/llvm/backend.c index 3621338..204e06a 100644 --- a/src/llvm/backend.c +++ b/src/llvm/backend.c @@ -48,6 +48,8 @@ static BackendError llvm_backend_codegen(const AST_NODE_PTR module_node, void**) GemstoneDeclRef decl = ((GemstoneDeclRef*) decls->data)[i]; type_scope_add_variable(global_scope, decl); } + // TODO: create LLVMValueRef of global/static variables + break; default: PANIC("NOT IMPLEMENTED"); diff --git a/src/llvm/decl/variable.c b/src/llvm/decl/variable.c index 15e902b..878dc2d 100644 --- a/src/llvm/decl/variable.c +++ b/src/llvm/decl/variable.c @@ -1,9 +1,12 @@ +#include "llvm/types/scope.h" #include "llvm/types/structs.h" +#include #include #include #include #include #include +#include static StorageQualifier get_storage_qualifier_from_ast(AST_NODE_PTR storageQualifierNode) { if (storageQualifierNode->kind != AST_Storage) { @@ -34,7 +37,7 @@ GArray* declaration_from_ast(TypeScopeRef scope, const AST_NODE_PTR node) { AST_NODE_PTR first_child = AST_get_node(node, 0); - StorageQualifier qualifier = StorageQualifierLocal; + StorageQualifier qualifier = StorageQualifierStatic; GemstoneTypeRef type = NULL; AST_NODE_PTR list = NULL; @@ -63,3 +66,27 @@ GArray* declaration_from_ast(TypeScopeRef scope, const AST_NODE_PTR node) { return decls; } + +LLVMValueRef create_declaration_reference(LLVMModuleRef module, LLVMBuilderRef builder, GemstoneDeclRef decl) { + LLVMContextRef context = LLVMGetModuleContext(module); + LLVMTypeRef llvmTypeRef = llvm_type_from_gemstone_type(context, decl->type); + LLVMValueRef defaultValue = llvm_default_value_of_type(context, decl->type); + LLVMValueRef variable = NULL; + + switch(decl->storageQualifier) { + case StorageQualifierLocal: + variable = LLVMBuildAlloca(builder, llvmTypeRef, decl->name); + LLVMBuildStore(builder, defaultValue, variable); + break; + case StorageQualifierStatic: + // add global + variable = LLVMAddGlobal(module, llvmTypeRef, decl->name); + LLVMSetInitializer(variable, defaultValue); + break; + case StorageQualifierGlobal: + PANIC("Global not implemented"); + break; + } + + return variable; +} diff --git a/src/llvm/types/type.c b/src/llvm/types/type.c index f39c053..5bcfd97 100644 --- a/src/llvm/types/type.c +++ b/src/llvm/types/type.c @@ -1,5 +1,8 @@ +#include "llvm/types/composite-types.h" #include "llvm/types/structs.h" +#include +#include #include #include #include @@ -85,3 +88,33 @@ LLVMTypeRef llvm_type_from_gemstone_type(LLVMContextRef context, GemstoneTypeRef return llvmTypeRef; } + +LLVMValueRef llvm_default_value_of_composite(LLVMContextRef context, CompositeRef composite) { + LLVMTypeRef type = llvm_type_from_composite(context, composite); + LLVMValueRef value; + + if (composite->prim == Int) { + value = LLVMConstInt(type, 0, 0); + } else if (composite->prim == Float) { + value = LLVMConstReal(type, 0.0); + } else { + PANIC("Invalid composite type: %d", composite->prim); + } + + return value; +} + +LLVMValueRef llvm_default_value_of_type(LLVMContextRef context, GemstoneTypeRef ref) { + LLVMValueRef value = NULL; + + switch (ref->kind) { + case TypeComposite: + value = llvm_default_value_of_composite(context, &ref->specs.composite); + break; + default: + PANIC("type not implemented"); + break; + } + + return value; +} diff --git a/src/llvm/types/type.h b/src/llvm/types/type.h index 135319a..3b55050 100644 --- a/src/llvm/types/type.h +++ b/src/llvm/types/type.h @@ -49,4 +49,6 @@ LLVMTypeRef llvm_type_from_gemstone_type(LLVMContextRef context, GemstoneTypeRef */ void delete_typedefref(GemstoneTypedefRef ref); +LLVMValueRef llvm_default_value_of_type(LLVMContextRef context, GemstoneTypeRef ref); + #endif // GEMSTONE_TYPE_H_ From 00089a4939796fa2f6bc1650c1b48c0791ce309a Mon Sep 17 00:00:00 2001 From: servostar Date: Wed, 22 May 2024 16:11:00 +0200 Subject: [PATCH 012/124] added error handling --- src/codegen/backend.h | 2 + src/llvm/backend.c | 9 ++- src/llvm/decl/variable.c | 30 +++++----- src/llvm/decl/variable.h | 5 ++ src/llvm/types/scope.c | 124 +++++++++++++++++++-------------------- 5 files changed, 92 insertions(+), 78 deletions(-) diff --git a/src/codegen/backend.h b/src/codegen/backend.h index 02cbc43..c00859b 100644 --- a/src/codegen/backend.h +++ b/src/codegen/backend.h @@ -89,4 +89,6 @@ BackendError new_backend_error(BackendErrorKind kind); BackendError new_backend_impl_error(BackendErrorKind kind, AST_NODE_PTR node, const char* message); +#define SUCCESS new_backend_error(Success) + #endif // CODEGN_BACKEND_H_ diff --git a/src/llvm/backend.c b/src/llvm/backend.c index 204e06a..235f59c 100644 --- a/src/llvm/backend.c +++ b/src/llvm/backend.c @@ -21,6 +21,8 @@ static BackendError llvm_backend_codegen(const AST_NODE_PTR module_node, void**) LLVMContextRef context = LLVMContextCreate(); LLVMModuleRef module = LLVMModuleCreateWithNameInContext("gemstone application", context); + BackendError err; + TypeScopeRef global_scope = type_scope_new(); for (size_t i = 0; i < module_node->child_count; i++) { @@ -47,8 +49,13 @@ static BackendError llvm_backend_codegen(const AST_NODE_PTR module_node, void**) for (size_t i = 0; i < decls->len; i++) { GemstoneDeclRef decl = ((GemstoneDeclRef*) decls->data)[i]; type_scope_add_variable(global_scope, decl); + + LLVMValueRef llvm_decl = NULL; + err = llvm_create_declaration(module, NULL, decl, &llvm_decl); + + if (err.kind != Success) + break; } - // TODO: create LLVMValueRef of global/static variables break; default: diff --git a/src/llvm/decl/variable.c b/src/llvm/decl/variable.c index 878dc2d..d1d7a15 100644 --- a/src/llvm/decl/variable.c +++ b/src/llvm/decl/variable.c @@ -1,12 +1,12 @@ -#include "llvm/types/scope.h" -#include "llvm/types/structs.h" +#include +#include +#include #include #include #include #include #include #include -#include static StorageQualifier get_storage_qualifier_from_ast(AST_NODE_PTR storageQualifierNode) { if (storageQualifierNode->kind != AST_Storage) { @@ -67,26 +67,28 @@ GArray* declaration_from_ast(TypeScopeRef scope, const AST_NODE_PTR node) { return decls; } -LLVMValueRef create_declaration_reference(LLVMModuleRef module, LLVMBuilderRef builder, GemstoneDeclRef decl) { - LLVMContextRef context = LLVMGetModuleContext(module); - LLVMTypeRef llvmTypeRef = llvm_type_from_gemstone_type(context, decl->type); - LLVMValueRef defaultValue = llvm_default_value_of_type(context, decl->type); - LLVMValueRef variable = NULL; +BackendError llvm_create_declaration(LLVMModuleRef llvm_module, LLVMBuilderRef llvm_builder, GemstoneDeclRef gem_decl, LLVMValueRef* llvm_decl) { + LLVMContextRef context = LLVMGetModuleContext(llvm_module); + LLVMTypeRef llvmTypeRef = llvm_type_from_gemstone_type(context, gem_decl->type); + LLVMValueRef defaultValue = llvm_default_value_of_type(context, gem_decl->type); - switch(decl->storageQualifier) { + switch(gem_decl->storageQualifier) { case StorageQualifierLocal: - variable = LLVMBuildAlloca(builder, llvmTypeRef, decl->name); - LLVMBuildStore(builder, defaultValue, variable); + if (llvm_builder == NULL) { + return new_backend_impl_error(Implementation, NULL, "initializing a local variable on non-local scope"); + } + *llvm_decl = LLVMBuildAlloca(llvm_builder, llvmTypeRef, gem_decl->name); + LLVMBuildStore(llvm_builder, defaultValue, *llvm_decl); break; case StorageQualifierStatic: // add global - variable = LLVMAddGlobal(module, llvmTypeRef, decl->name); - LLVMSetInitializer(variable, defaultValue); + *llvm_decl = LLVMAddGlobal(llvm_module, llvmTypeRef, gem_decl->name); + LLVMSetInitializer(*llvm_decl, defaultValue); break; case StorageQualifierGlobal: PANIC("Global not implemented"); break; } - return variable; + return SUCCESS; } diff --git a/src/llvm/decl/variable.h b/src/llvm/decl/variable.h index 8548391..07cd9f2 100644 --- a/src/llvm/decl/variable.h +++ b/src/llvm/decl/variable.h @@ -2,10 +2,15 @@ #ifndef LLVM_DECL_VAR_H_ #define LLVM_DECL_VAR_H_ +#include #include +#include #include #include +#include GArray* declaration_from_ast(TypeScopeRef scope, const AST_NODE_PTR node); +BackendError llvm_create_declaration(LLVMModuleRef llvm_module, LLVMBuilderRef llvm_builder, GemstoneDeclRef gem_decl, LLVMValueRef* llvm_decl); + #endif // LLVM_DECL_VAR_H_ diff --git a/src/llvm/types/scope.c b/src/llvm/types/scope.c index 851da03..445c5ee 100644 --- a/src/llvm/types/scope.c +++ b/src/llvm/types/scope.c @@ -1,115 +1,113 @@ #include #include -#include #include +#include #include struct TypeScope_t { - GArray* types; - GArray* scopes; - GArray* funcs; - GHashTable* vars; - TypeScopeRef parent; + GArray *types; + GArray *scopes; + GArray *funcs; + GHashTable *vars; + TypeScopeRef parent; }; TypeScopeRef type_scope_new() { - TypeScopeRef scope = malloc(sizeof(TypeScope)); + TypeScopeRef scope = malloc(sizeof(TypeScope)); - // neither zero termination no initialisazion to zero needed - scope->scopes = g_array_new(FALSE, FALSE, sizeof(TypeScopeRef)); - scope->types = g_array_new(FALSE, FALSE, sizeof(GemstoneTypedefRef)); - scope->funcs = g_array_new(FALSE, FALSE, sizeof(GemstoneFunRef)); - scope->vars = g_hash_table_new(g_str_hash, g_str_equal); - scope->parent = NULL; + // neither zero termination no initialisazion to zero needed + scope->scopes = g_array_new(FALSE, FALSE, sizeof(TypeScopeRef)); + scope->types = g_array_new(FALSE, FALSE, sizeof(GemstoneTypedefRef)); + scope->funcs = g_array_new(FALSE, FALSE, sizeof(GemstoneFunRef)); + scope->vars = g_hash_table_new(g_str_hash, g_str_equal); + scope->parent = NULL; - return scope; + return scope; } void type_scope_append_type(TypeScopeRef scope, GemstoneTypedefRef type) { - g_array_append_val(scope->types, type); + g_array_append_val(scope->types, type); } void type_scope_append_scope(TypeScopeRef scope, TypeScopeRef child_scope) { - g_array_append_val(scope->scopes, child_scope); - child_scope->parent = scope; + g_array_append_val(scope->scopes, child_scope); + child_scope->parent = scope; } GemstoneTypedefRef type_scope_get_type(TypeScopeRef scope, size_t index) { - return ((GemstoneTypedefRef*) scope->types->data)[index]; + return ((GemstoneTypedefRef *)scope->types->data)[index]; } -size_t type_scope_types_len(TypeScopeRef scope) { - return scope->types->len; -} +size_t type_scope_types_len(TypeScopeRef scope) { return scope->types->len; } -size_t type_scope_scopes_len(TypeScopeRef scope) { - return scope->scopes->len; -} +size_t type_scope_scopes_len(TypeScopeRef scope) { return scope->scopes->len; } -GemstoneTypedefRef type_scope_get_type_from_name(TypeScopeRef scope, const char* name) { - for (guint i = 0; i < scope->types->len; i++) { - GemstoneTypedefRef typeref = ((GemstoneTypedefRef*) scope->types->data)[i]; +GemstoneTypedefRef type_scope_get_type_from_name(TypeScopeRef scope, + const char *name) { + for (guint i = 0; i < scope->types->len; i++) { + GemstoneTypedefRef typeref = ((GemstoneTypedefRef *)scope->types->data)[i]; - if (strcmp(typeref->name, name) == 0) { - return typeref; - } + if (strcmp(typeref->name, name) == 0) { + return typeref; } + } - if (scope->parent == NULL) { - return NULL; - } + if (scope->parent == NULL) { + return NULL; + } - return type_scope_get_type_from_name(scope->parent, name); + return type_scope_get_type_from_name(scope->parent, name); } void type_scope_delete(TypeScopeRef scope) { - for (guint i = 0; i < scope->scopes->len; i++) { - TypeScopeRef scoperef = ((TypeScopeRef*) scope->scopes->data)[i]; - type_scope_delete(scoperef); - } + for (guint i = 0; i < scope->scopes->len; i++) { + TypeScopeRef scoperef = ((TypeScopeRef *)scope->scopes->data)[i]; + type_scope_delete(scoperef); + } - for (guint i = 0; i < scope->types->len; i++) { - // TODO: free gemstone type - } + for (guint i = 0; i < scope->types->len; i++) { + // TODO: free gemstone type + } - g_array_free(scope->scopes, TRUE); - g_array_free(scope->types, TRUE); - g_array_free(scope->funcs, TRUE); - g_hash_table_destroy(scope->vars); + g_array_free(scope->scopes, TRUE); + g_array_free(scope->types, TRUE); + g_array_free(scope->funcs, TRUE); + g_hash_table_destroy(scope->vars); - free(scope); + free(scope); } void type_scope_add_variable(TypeScopeRef scope, GemstoneDeclRef decl) { - g_hash_table_insert(scope->vars, (gpointer) decl->name, decl); + g_hash_table_insert(scope->vars, (gpointer)decl->name, decl); } -GemstoneDeclRef type_scope_get_variable(TypeScopeRef scope, const char* name) { - if (g_hash_table_contains(scope->vars, name)) { - return g_hash_table_lookup(scope->vars, name); - } +GemstoneDeclRef type_scope_get_variable(TypeScopeRef scope, const char *name) { + if (g_hash_table_contains(scope->vars, name)) { + return g_hash_table_lookup(scope->vars, name); + } - return NULL; + return NULL; } void type_scope_add_fun(TypeScopeRef scope, GemstoneFunRef function) { - g_array_append_val(scope->funcs, function); + g_array_append_val(scope->funcs, function); } -GemstoneFunRef type_scope_get_fun_from_name(TypeScopeRef scope, const char* name) { - for (guint i = 0; i < scope->funcs->len; i++) { - GemstoneFunRef funref = ((GemstoneFunRef*) scope->funcs->data)[i]; +GemstoneFunRef type_scope_get_fun_from_name(TypeScopeRef scope, + const char *name) { + for (guint i = 0; i < scope->funcs->len; i++) { + GemstoneFunRef funref = ((GemstoneFunRef *)scope->funcs->data)[i]; - if (strcmp(funref->name, name) == 0) { - return funref; - } + if (strcmp(funref->name, name) == 0) { + return funref; } + } - if (scope->parent == NULL) { - return NULL; - } + if (scope->parent == NULL) { + return NULL; + } - return type_scope_get_fun_from_name(scope->parent, name); + return type_scope_get_fun_from_name(scope->parent, name); } From 8603656e3efbeddd22c1e83531e1c1feac625112 Mon Sep 17 00:00:00 2001 From: servostar Date: Wed, 22 May 2024 20:27:40 +0200 Subject: [PATCH 013/124] added basic expression support --- src/ast/ast.c | 12 +++ src/ast/ast.h | 2 + src/llvm/backend.c | 10 +-- src/llvm/expr/build.c | 134 +++++++++++++++++++++++++++++ src/llvm/expr/build.h | 13 +++ src/llvm/function/function-types.h | 3 + src/llvm/function/function.c | 39 ++++++++- src/llvm/function/function.h | 7 ++ src/llvm/stmt/build.c | 89 +++++++++++++++++++ src/llvm/stmt/build.h | 11 +++ src/llvm/types/scope.c | 12 ++- src/llvm/types/scope.h | 15 +++- 12 files changed, 336 insertions(+), 11 deletions(-) create mode 100644 src/llvm/expr/build.c create mode 100644 src/llvm/expr/build.h create mode 100644 src/llvm/stmt/build.c create mode 100644 src/llvm/stmt/build.h diff --git a/src/ast/ast.c b/src/ast/ast.c index e503e1e..3002570 100644 --- a/src/ast/ast.c +++ b/src/ast/ast.c @@ -287,3 +287,15 @@ void AST_fprint_graphviz(FILE* stream, const struct AST_Node_t* root) { fprintf(stream, "}\n"); } + +AST_NODE_PTR AST_get_node_by_kind(AST_NODE_PTR owner, enum AST_SyntaxElement_t kind) { + for (size_t i = 0; i < owner->child_count; i++) { + AST_NODE_PTR child = AST_get_node(owner, i); + + if (child->kind == kind) { + return child; + } + } + + return NULL; +} \ No newline at end of file diff --git a/src/ast/ast.h b/src/ast/ast.h index ff8297b..5772675 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -213,4 +213,6 @@ void AST_visit_nodes_recurse(struct AST_Node_t *root, [[gnu::nonnull(1), gnu::nonnull(2)]] void AST_fprint_graphviz(FILE* stream, const struct AST_Node_t* node); +AST_NODE_PTR AST_get_node_by_kind(AST_NODE_PTR owner, enum AST_SyntaxElement_t kind); + #endif diff --git a/src/llvm/backend.c b/src/llvm/backend.c index 235f59c..a2fcef9 100644 --- a/src/llvm/backend.c +++ b/src/llvm/backend.c @@ -32,7 +32,6 @@ static BackendError llvm_backend_codegen(const AST_NODE_PTR module_node, void**) AST_NODE_PTR global_node = AST_get_node(module_node, i); GemstoneTypedefRef typedefref; - GemstoneFunRef funref; GArray* decls; switch (global_node->kind) { @@ -41,20 +40,19 @@ static BackendError llvm_backend_codegen(const AST_NODE_PTR module_node, void**) type_scope_append_type(global_scope, typedefref); break; case AST_Fun: - funref = fun_from_ast(global_scope, global_node); - type_scope_add_fun(global_scope, funref); + llvm_generate_function_implementation(global_scope, module, global_node); break; case AST_Decl: decls = declaration_from_ast(global_scope, global_node); for (size_t i = 0; i < decls->len; i++) { GemstoneDeclRef decl = ((GemstoneDeclRef*) decls->data)[i]; - type_scope_add_variable(global_scope, decl); - LLVMValueRef llvm_decl = NULL; - err = llvm_create_declaration(module, NULL, decl, &llvm_decl); + err = llvm_create_declaration(module, NULL, decl, &decl->llvm_value); if (err.kind != Success) break; + + type_scope_add_variable(global_scope, decl); } break; diff --git a/src/llvm/expr/build.c b/src/llvm/expr/build.c new file mode 100644 index 0000000..0bcba93 --- /dev/null +++ b/src/llvm/expr/build.c @@ -0,0 +1,134 @@ +#include +#include +#include +#include +#include +#include + +BackendError llvm_build_arithmetic_operation(LLVMBuilderRef builder, TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR expr_node, enum AST_SyntaxElement_t operation, LLVMValueRef* yield) { + AST_NODE_PTR expr_lhs = AST_get_node(expr_node, 0); + AST_NODE_PTR expr_rhs = AST_get_node(expr_node, 1); + + LLVMValueRef llvm_lhs = NULL; + LLVMValueRef llvm_rhs = NULL; + BackendError err; + + err = llvm_build_expression(builder, scope, module, expr_lhs, &llvm_lhs); + if (err.kind != Success) + return err; + + err = llvm_build_expression(builder, scope, module, expr_rhs, &llvm_rhs); + if (err.kind != Success) + return err; + + switch (operation) { + case AST_Add: + *yield = LLVMBuildAdd(builder, llvm_lhs, llvm_rhs, "Addition"); + break; + case AST_Sub: + *yield = LLVMBuildSub(builder, llvm_lhs, llvm_rhs, "Subtraction"); + break; + case AST_Mul: + *yield = LLVMBuildMul(builder, llvm_lhs, llvm_rhs, "Multiplication"); + break; + case AST_Div: + *yield = LLVMBuildSDiv(builder, llvm_lhs, llvm_rhs, "Division"); + break; + default: + break; + } + + return new_backend_impl_error(Implementation, expr_node, "invalid arithmetic operation"); +} + +BackendError llvm_build_relational_operation(LLVMBuilderRef builder, TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR expr_node, enum AST_SyntaxElement_t operation, LLVMValueRef* yield) { + AST_NODE_PTR expr_lhs = AST_get_node(expr_node, 0); + AST_NODE_PTR expr_rhs = AST_get_node(expr_node, 1); + + LLVMValueRef llvm_lhs = NULL; + LLVMValueRef llvm_rhs = NULL; + BackendError err; + + err = llvm_build_expression(builder, scope, module, expr_lhs, &llvm_lhs); + if (err.kind != Success) + return err; + + err = llvm_build_expression(builder, scope, module, expr_rhs, &llvm_rhs); + if (err.kind != Success) + return err; + + // TODO: make a difference between SignedInt, UnsignedInt and Float + switch (operation) { + case AST_Eq: + *yield = LLVMBuildICmp(builder, LLVMIntEQ, llvm_lhs, llvm_rhs, "Equal"); + break; + case AST_Greater: + *yield = LLVMBuildICmp(builder, LLVMIntSGT, llvm_lhs, llvm_rhs, "Greater"); + break; + case AST_Less: + *yield = LLVMBuildICmp(builder, LLVMIntSLT, llvm_lhs, llvm_rhs, "Less"); + break; + default: + break; + } + + return new_backend_impl_error(Implementation, expr_node, "invalid arithmetic operation"); +} + +BackendError llvm_build_expression(LLVMBuilderRef builder, TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR expr_node, LLVMValueRef* yield) { + + switch (expr_node->kind) { + case AST_Ident: { + AST_NODE_PTR variable_name = AST_get_node(expr_node, 0); + GemstoneDeclRef decl = type_scope_get_variable(scope, variable_name->value); + *yield = decl->llvm_value; + } + break; + case AST_Int: { + AST_NODE_PTR constant = AST_get_node(expr_node, 0); + // TODO: type annotation needed + *yield = LLVMConstIntOfString(LLVMInt32Type(), constant->value, 10); + } + case AST_Float: { + AST_NODE_PTR constant = AST_get_node(expr_node, 0); + // TODO: type annotation needed + *yield = LLVMConstRealOfString(LLVMFloatType(), constant->value); + } + break; + case AST_Add: + case AST_Sub: + case AST_Mul: + case AST_Div: { + BackendError err = llvm_build_arithmetic_operation(builder, scope, module, expr_node, expr_node->kind, yield); + if (err.kind != Success) + return err; + } + case AST_Eq: + case AST_Greater: + case AST_Less: { + BackendError err = llvm_build_relational_operation(builder, scope, module, expr_node, expr_node->kind, yield); + if (err.kind != Success) + return err; + } + break; + } + + return SUCCESS; +} + +BackendError llvm_build_expression_list(LLVMBuilderRef builder, TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR exprlist_node, LLVMValueRef** yields) { + + if (exprlist_node->kind != AST_ExprList) { + return new_backend_impl_error(Implementation, exprlist_node, "expected expression list"); + } + + *yields = malloc(sizeof(LLVMValueRef) * exprlist_node->child_count); + + for (size_t i = 0; i < exprlist_node->child_count; i++) { + AST_NODE_PTR expr = AST_get_node(exprlist_node, 0); + + llvm_build_expression(builder, scope, module, expr, *yields + i); + } + + return SUCCESS; +} diff --git a/src/llvm/expr/build.h b/src/llvm/expr/build.h new file mode 100644 index 0000000..a4d2c28 --- /dev/null +++ b/src/llvm/expr/build.h @@ -0,0 +1,13 @@ + +#ifndef LLVM_EXPR_BUILD_H_ +#define LLVM_EXPR_BUILD_H_ + +#include "codegen/backend.h" +#include "llvm/types/scope.h" +#include + +BackendError llvm_build_expression(LLVMBuilderRef builder, TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR expr_node, LLVMValueRef* yield); + +BackendError llvm_build_expression_list(LLVMBuilderRef builder, TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR expr_node, LLVMValueRef** yields); + +#endif // LLVM_EXPR_BUILD_H_ diff --git a/src/llvm/function/function-types.h b/src/llvm/function/function-types.h index 0af0c1a..211bf54 100644 --- a/src/llvm/function/function-types.h +++ b/src/llvm/function/function-types.h @@ -2,6 +2,7 @@ #ifndef LLVM_TYPES_FUNCTION_TYPES_H_ #define LLVM_TYPES_FUNCTION_TYPES_H_ +#include #include #include @@ -21,6 +22,8 @@ typedef struct GemstoneParam_t { typedef struct GemstoneFun_t { const char* name; GArray* params; + LLVMTypeRef llvm_signature; + LLVMValueRef llvm_function; } GemstoneFun; typedef GemstoneFun* GemstoneFunRef; diff --git a/src/llvm/function/function.c b/src/llvm/function/function.c index 4e8c643..3623f79 100644 --- a/src/llvm/function/function.c +++ b/src/llvm/function/function.c @@ -1,7 +1,10 @@ +#include "codegen/backend.h" #include "llvm/function/function-types.h" +#include "llvm/stmt/build.h" #include #include +#include #include #include #include @@ -108,7 +111,7 @@ void fun_delete(const GemstoneFunRef fun) { free(fun); } -LLVMTypeRef get_gemstone_function_llvm_signature(LLVMContextRef context, GemstoneFunRef function) { +LLVMTypeRef llvm_generate_function_signature(LLVMContextRef context, GemstoneFunRef function) { unsigned int param_count = function->params->len; LLVMTypeRef* params = malloc(sizeof(LLVMTypeRef)); @@ -120,3 +123,37 @@ LLVMTypeRef get_gemstone_function_llvm_signature(LLVMContextRef context, Gemston return LLVMFunctionType(LLVMVoidType(), params, param_count, 0); } + +BackendError llvm_generate_function_implementation(TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR node) { + LLVMContextRef context = LLVMGetModuleContext(module); + GemstoneFunRef gemstone_signature = fun_from_ast(scope, node); + + gemstone_signature->llvm_signature = llvm_generate_function_signature(context, gemstone_signature); + gemstone_signature->llvm_function = LLVMAddFunction(module, gemstone_signature->name, gemstone_signature->llvm_signature); + + type_scope_add_fun(scope, gemstone_signature); + + LLVMBasicBlockRef llvm_body = LLVMAppendBasicBlock(gemstone_signature->llvm_function, "body"); + LLVMBuilderRef llvm_builder = LLVMCreateBuilderInContext(context); + LLVMPositionBuilderAtEnd(llvm_builder, llvm_body); + + // create new function local scope + TypeScopeRef local_scope = type_scope_new(); + size_t local_scope_idx = type_scope_append_scope(scope, local_scope); + + for (size_t i = 0; i < node->child_count; i++) { + AST_NODE_PTR child_node = AST_get_node(node, i); + if (child_node->kind == AST_StmtList) { + llvm_build_statement_list(llvm_builder, local_scope, module, child_node); + } + } + + // automatic return at end of function + LLVMBuildRetVoid(llvm_builder); + + // dispose function local scope + type_scope_remove_scope(scope, local_scope_idx); + type_scope_delete(local_scope); + + return SUCCESS; +} diff --git a/src/llvm/function/function.h b/src/llvm/function/function.h index 3e6ceec..833414f 100644 --- a/src/llvm/function/function.h +++ b/src/llvm/function/function.h @@ -2,9 +2,12 @@ #ifndef LLVM_FUNCTION_H_ #define LLVM_FUNCTION_H_ +#include #include +#include #include #include +#include /** * @brief Convert an AST node into a function parameter struct @@ -29,4 +32,8 @@ GemstoneFunRef fun_from_ast(const TypeScopeRef scope, const AST_NODE_PTR node); */ void fun_delete(const GemstoneFunRef fun); +LLVMTypeRef llvm_generate_function_signature(LLVMContextRef context, GemstoneFunRef function); + +BackendError llvm_generate_function_implementation(TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR body); + #endif // LLVM_FUNCTION_H_ diff --git a/src/llvm/stmt/build.c b/src/llvm/stmt/build.c new file mode 100644 index 0000000..d9234fe --- /dev/null +++ b/src/llvm/stmt/build.c @@ -0,0 +1,89 @@ + +#include "llvm/function/function-types.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +BackendError llvm_build_statement(LLVMBuilderRef builder, TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR stmt_node) { + switch (stmt_node->kind) { + case AST_Decl: { + GArray* decls = declaration_from_ast(scope, stmt_node); + + for (size_t i = 0; i < decls->len; i++) { + GemstoneDeclRef decl = ((GemstoneDeclRef*) decls->data)[i]; + + BackendError err = llvm_create_declaration(module, builder, decl, &decl->llvm_value); + + if (err.kind != Success) + break; + + type_scope_add_variable(scope, decl); + } + + // TODO: make sure all decls are freed later + g_array_free(decls, FALSE); + } + break; + case AST_Assign: { + AST_NODE_PTR variable_name = AST_get_node(stmt_node, 0); + AST_NODE_PTR expression = AST_get_node(stmt_node, 1); + + LLVMValueRef yield = NULL; + BackendError err = llvm_build_expression(builder, scope, module, expression, &yield); + + GemstoneDeclRef variable = type_scope_get_variable(scope, variable_name->value); + + LLVMBuildStore(builder, yield, variable->llvm_value); + } + break; + case AST_Stmt: + llvm_build_statement(builder, scope, module, stmt_node); + break; + case AST_Call: { + AST_NODE_PTR name = AST_get_node(stmt_node, 0); + AST_NODE_PTR expr_list = AST_get_node_by_kind(stmt_node, AST_ExprList); + GemstoneFunRef function_signature = type_scope_get_fun_from_name(scope, name->value); + size_t arg_count = function_signature->params->len; + + LLVMValueRef* args = NULL; + BackendError err = llvm_build_expression_list(builder, scope, module, expr_list, &args); + + LLVMBuildCall2(builder, function_signature->llvm_signature, function_signature->llvm_function, args, arg_count, name->value); + } + break; + case AST_Def: + // TODO: implement definition + break; + case AST_While: + // TODO: implement while + break; + case AST_If: + // TODO: implement if + break; + case AST_IfElse: + // TODO: implement else if + break; + case AST_Else: + // TODO: implement else + break; + default: + ERROR("Invalid AST node: %s", AST_node_to_string(stmt_node)); + return new_backend_impl_error(Implementation, stmt_node, "AST is invalid"); + } + + return SUCCESS; +} + +BackendError llvm_build_statement_list(LLVMBuilderRef builder, TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR node) { + for (size_t i = 0; i < node->child_count; i++) { + AST_NODE_PTR stmt_node = AST_get_node(node, i); + + llvm_build_statement(builder, scope, module, stmt_node); + } +} diff --git a/src/llvm/stmt/build.h b/src/llvm/stmt/build.h new file mode 100644 index 0000000..726813a --- /dev/null +++ b/src/llvm/stmt/build.h @@ -0,0 +1,11 @@ + +#ifndef LLVM_STMT_BUILD_H_ +#define LLVM_STMT_BUILD_H_ + +#include +#include +#include + +BackendError llvm_build_statement_list(LLVMBuilderRef builder, TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR node); + +#endif // LLVM_STMT_BUILD_H_ diff --git a/src/llvm/types/scope.c b/src/llvm/types/scope.c index 445c5ee..15f7634 100644 --- a/src/llvm/types/scope.c +++ b/src/llvm/types/scope.c @@ -30,9 +30,15 @@ void type_scope_append_type(TypeScopeRef scope, GemstoneTypedefRef type) { g_array_append_val(scope->types, type); } -void type_scope_append_scope(TypeScopeRef scope, TypeScopeRef child_scope) { - g_array_append_val(scope->scopes, child_scope); - child_scope->parent = scope; +size_t type_scope_append_scope(TypeScopeRef scope, TypeScopeRef child) { + child->parent = scope; + g_array_append_val(scope->scopes, child); + + return scope->scopes->len - 1; +} + +void type_scope_remove_scope(TypeScopeRef scope, size_t index) { + g_array_remove_index(scope->scopes, index); } GemstoneTypedefRef type_scope_get_type(TypeScopeRef scope, size_t index) { diff --git a/src/llvm/types/scope.h b/src/llvm/types/scope.h index a8beac2..84e37fd 100644 --- a/src/llvm/types/scope.h +++ b/src/llvm/types/scope.h @@ -2,6 +2,7 @@ #ifndef LLVM_TYPE_SCOPE_H_ #define LLVM_TYPE_SCOPE_H_ +#include #include #include #include @@ -17,6 +18,7 @@ typedef struct GemstoneDecl_t { const char* name; StorageQualifier storageQualifier; GemstoneTypeRef type; + LLVMValueRef llvm_value; } GemstoneDecl; typedef GemstoneDecl* GemstoneDeclRef; @@ -49,7 +51,16 @@ void type_scope_append_type(TypeScopeRef scope, GemstoneTypedefRef type); * @param child_scope */ [[gnu::nonnull(1), gnu::nonnull(2)]] -void type_scope_append_scope(TypeScopeRef scope, TypeScopeRef child_scope); +size_t type_scope_append_scope(TypeScopeRef scope, TypeScopeRef child_scope); + +/** + * @brief Remove a new child scope to this scope + * + * @param scope + * @param child_scope + */ +[[gnu::nonnull(1)]] +void type_scope_remove_scope(TypeScopeRef scope, size_t index); /** * @brief Get the type at the specified index in this scope level @@ -116,4 +127,6 @@ GemstoneFunRef type_scope_get_fun_from_name(TypeScopeRef scope, const char* name void type_scope_add_variable(TypeScopeRef scope, GemstoneDeclRef decl); +GemstoneDeclRef type_scope_get_variable(TypeScopeRef scope, const char *name); + #endif // LLVM_TYPE_SCOPE_H_ From 7705aea2388a459ed7e7af7c2fa387bed96b9275 Mon Sep 17 00:00:00 2001 From: servostar Date: Thu, 23 May 2024 21:54:37 +0200 Subject: [PATCH 014/124] added header for semantic tree types --- src/set/types.h | 472 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 472 insertions(+) create mode 100644 src/set/types.h diff --git a/src/set/types.h b/src/set/types.h new file mode 100644 index 0000000..c58dd67 --- /dev/null +++ b/src/set/types.h @@ -0,0 +1,472 @@ + +#ifndef SET_TYPES_H_ +#define SET_TYPES_H_ + +#include +#include + +/** + * @brief Primitive types form the basis of all other types. + * + */ +typedef enum PrimitiveType_t { + // 4 byte signed integer in two's complement + Int, + // 4 byte IEEE-754 single precision + Float +} PrimitiveType; + +/** + * @brief Represents the sign of a composite type. + * + */ +typedef enum Sign_t { + // type has a sign bit + Signed, + // type has no sign bit + Unsigned +} Sign; + +/** + * @brief Represents the scale of composite type which is multiplied + * with the base size in order to retrieve the the composites size. + * @attention Valid value are: { 1/8, 1/4, 1/2, 1, 2, 4, 8 } + * + */ +typedef double Scale; + +/** + * @brief A composite type is an extended definiton of a primitive type. + * + */ +typedef struct CompositeType_t { + // sign of composite + Sign sign; + Scale scale; + PrimitiveType primitive; +} CompositeType; + +/** + * @brief Specifies the specific type of the generic type struct. + * + */ +typedef enum TypeKind_t { + TypeKindPrimitive, + TypeKindComposite, + TypeKindBox, + TypeKindReference +} TypeKind; + +typedef struct Type_t Type; + +/** + * @brief Reference points to a type. + * @attention Can be nested. A reference can point to another reference: REF -> REF -> REF -> Primitive + * + */ +typedef Type* ReferenceType; + +typedef struct BoxType_t BoxType; + +typedef struct BoxMember_t { + const char* name; + Type* type; + BoxType* box; +} BoxMember; + +/** + * @brief Essentially a glorified struct + * + */ +typedef struct BoxType_t { + // hashtable of members. + // Associates the memebers name (const char*) with its type (BoxMember) + GHashTable* member; +} BoxType; + +typedef struct Variable_t Variable; + +typedef struct BoxAccess_t { + // list of recursive box accesses + // contains a list of BoxMembers (each specifying their own type, name and box type) + GArray* member; +} BoxAccess; + +typedef struct Type_t { + // specifiy the kind of this type + // used to determine which implementation to choose + TypeKind kind; + // actual implementation of the type + union TypeImplementation_t { + PrimitiveType primitive; + CompositeType composite; + BoxType box; + ReferenceType reference; + } impl; +} Type; + +typedef struct Typedefine_t { + const char* name; + Type type; +} Typedefine; + +const Type ShortShortUnsingedIntType = { + .kind = TypeKindComposite, + .impl = { + .composite = { + .sign = Unsigned, + .scale = 0.25, + .primitive = Int + } + } +}; + +const Type StringLiteralType = { + .kind = TypeKindReference, + .impl = { + .reference = (ReferenceType) &ShortShortUnsingedIntType, + } +}; + +/** + * @brief Reprents the value of type. Can be used to definitons, initialization and for expressions contants. + * + */ +typedef struct TypeValue_t { + // the type + Type type; + // UTF-8 representation of the type's value + const char* value; +} TypeValue; + +// .------------------------------------------------. +// | Functions | +// '------------------------------------------------' + +/** + * @brief Specifies a parameters I/O properties + * + */ +typedef enum IO_Qualifier_t { + // Can be read from but not written to. + // Function local only. + In, + // Can be written to but not read from. + // Passed back to the functions callee. + Out, + // Can be read from and written to. + // Passed back to the functions callee. + InOut, +} IO_Qualifier; + +/** + * @brief A functions parameter declaration. + * + */ +typedef struct ParameterDeclaration_t { + Type type; + IO_Qualifier qualifier; +} ParameterDeclaration; + +/** + * @brief A functions parameter. + * + */ +typedef struct ParameterDefinition_t { + ParameterDeclaration declaration; + // value to initalize the declaration with + // NOTE: type of initializer and declaration MUST be equal + TypeValue initializer; +} ParameterDefinition; + +typedef enum ParameterKind_t { + ParameterDeclarationKind, + ParameterDefinitionKind +} ParameterKind; + +/** + * @brief A parameter can either be a declaration or a definiton + * + */ +typedef struct Parameter_t { + const char* name; + ParameterKind kind; + union ParameterImplementation { + ParameterDeclaration declaration; + ParameterDefinition definiton; + } impl; +} Paramer; + +typedef struct FunctionDefinition_t { + // hashtable of parameters + // associates a parameters name (const char*) with its parameter declaration (ParameterDeclaration) + GArray* parameter; +} FunctionDefinition; + +// .------------------------------------------------. +// | Variables | +// '------------------------------------------------' + +typedef enum StorageQualifier_t { + Local, + Static, + Global +} StorageQualifier; + +typedef struct VariableDeclaration_t { + StorageQualifier qualifier; + Type type; +} VariableDeclaration; + +/** + * @brief Definiton of a variable + * + * @attention NOTE: The types of the initializer and the declaration must be equal + * + */ +typedef struct VariableDefiniton_t { + VariableDeclaration declaration; + TypeValue initializer; +} VariableDefiniton; + +typedef enum VariableKind_t { + VariableKindDeclaration, + VariableKindDefinition, + VariableKindBoxMember +} VariableKind; + +typedef struct Variable_t { + VariableKind kind; + const char* name; + union VariableImplementation { + VariableDeclaration declaration; + VariableDefiniton definiton; + BoxMember member; + } impl; +} Variable; + +// .------------------------------------------------. +// | Casts | +// '------------------------------------------------' + +/** + * @brief Perform a type cast, converting a value to different type whilest preserving as much of the original + * values information. + * + * @attention NOTE: Must check wether the given value's type can be parsed into + * the target type without loss. + * Lossy mean possibly loosing information such when casting a float into an int (no fraction anymore). + * + */ +typedef struct TypeCast_t { + Type targetType; +} TypeCast; + +/** + * @brief Perform a reinterpret cast. + * + * @attention NOTE: The given value's type must have the size in bytes as the target type. + * Transmuting a short int into a float should yield an error. + * + */ +typedef struct Transmute_t { + Type targetType; +} Transmute; + +// .------------------------------------------------. +// | Arithmetic | +// '------------------------------------------------' + +/** + * @brief Represents the arithmetic operator. + * + */ +typedef enum ArithmeticOperator_t { + Add, + Sub, + Mul, + Div +} ArithmeticOperator; + +// .------------------------------------------------. +// | Relational | +// '------------------------------------------------' + +/** + * @brief Represents the relational operator. + * + */ +typedef enum RelationalOperator_t { + Equal, + Greater, + Less +} RelationalOperator; + +// .------------------------------------------------. +// | Boolean | +// '------------------------------------------------' + +typedef enum BooleanOperator_t { + BooleanAnd, + BooleanOr, + BooleanNot, + BooleanXor, +} BooleanOperator; + +// .------------------------------------------------. +// | Logical | +// '------------------------------------------------' + +typedef enum LogicalOperator_t { + LogicalAnd, + LogicalOr, + LogicalNot, + LogicalXor, +} LogicalOperator; + +// .------------------------------------------------. +// | Logical | +// '------------------------------------------------' + +typedef enum BitwiseOperator_t { + BitwiseAnd, + BitwiseOr, + BitwiseNot, + BitwiseXor, +} BitwiseOperator; + +// .------------------------------------------------. +// | Operations | +// '------------------------------------------------' + +typedef enum OperationKind_t { + Arithmetic, + Relational, + Boolean, + Logical, + Bitwise +} OperationKind; + +typedef struct Operation_t { + // mode of operation + OperationKind kind; + // specific implementation + union OperationImplementation { + ArithmeticOperator arithmetic; + RelationalOperator relational; + BooleanOperator boolean; + LogicalOperator logical; + BitwiseOperator bitwise; + } impl; +} Operation; + +// .------------------------------------------------. +// | Expression | +// '------------------------------------------------' + +typedef enum ExpressionKind_t { + ExpressionKindOperation, + ExpressionKindTypeCast, + ExpressionKindTransmute, + ExpressionKindConstant +} ExpressionKind; + +typedef struct Expression_t { + ExpressionKind kind; + union ExpressionImplementation_t { + Operation operation; + TypeCast typecast; + Transmute transmute; + TypeValue constant; + Variable variable; + } impl; +} Expression; + +// .------------------------------------------------. +// | Function call | +// '------------------------------------------------' + +typedef struct FunctionCall_t { + // function to call + FunctionDefinition* function; + // list of expression arguments + GArray* expressions; +} FunctionCall; + +typedef struct FunctionBoxCall_t { + // function to call + FunctionDefinition* function; + // list of expression arguments + GArray* expressions; + // box which has the function defined for it + // NOTE: must be of TypeKind: Box + Variable selfArgument; +} FunctionBoxCall; + +typedef struct Block_t { + // array of statements + GArray* statemnts; +} Block; + +// .------------------------------------------------. +// | While | +// '------------------------------------------------' + +typedef struct While_t { + Expression conditon; + Block block; +} While; + +// .------------------------------------------------. +// | If/Else | +// '------------------------------------------------' + +typedef struct If_t { + Expression conditon; + Block block; +} If; + +typedef struct ElseIf_t { + Expression conditon; + Block block; +} ElseIf; + +typedef struct Else_t { + Block block; +} Else; + +typedef struct Branch_t { + If ifBranch; + // list of else-ifs (can be empty/NULL) + GArray* elseIfBranches; + Else elseBranch; +} Branch; + +// .------------------------------------------------. +// | Statements | +// '------------------------------------------------' + +typedef struct Assignment_t { + Variable* variable; + Expression value; +} Assignment; + +typedef enum StatementKind_t { + StatementKindFunctionCall, + StatementKindFunctionBoxCall, + StatementKindWhile, + StatementKindBranch, + StatementKindAssignment +} StatementKind; + +typedef struct Statement_t { + union StatementImplementation { + FunctionCall call; + FunctionBoxCall boxCall; + While whileLoop; + Branch branch; + Assignment assignment; + } impl; +} Statement; + +#endif // SET_TYPES_H_ From ed008e0c7d9e104eb64bfb67dde960d123da3a45 Mon Sep 17 00:00:00 2001 From: servostar Date: Sat, 25 May 2024 09:59:38 +0200 Subject: [PATCH 015/124] added standard type definitions --- lib/def/def.h | 25 +++++++++++++++++++++++++ lib/def/mod.gem | 34 ++++++++++++++++++++++++++++++++++ lib/std.gem | 12 ++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 lib/def/def.h create mode 100644 lib/def/mod.gem create mode 100644 lib/std.gem diff --git a/lib/def/def.h b/lib/def/def.h new file mode 100644 index 0000000..b1980a9 --- /dev/null +++ b/lib/def/def.h @@ -0,0 +1,25 @@ +// Author: Sven Vogel +// Edited: 25.05.2024 +// License: GPL-2.0 + +#ifndef GEMSTONE_STD_LIB_DEF_H_ +#define GEMSTONE_STD_LIB_DEF_H_ + +#include + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; + +typedef int8_t i8; +typedef int16_t i16; +typedef int32_t i32; +typedef int64_t i64; + +typedef float f32; +typedef double f64; + +typedef u8* str; + +#endif // GEMSTONE_STD_LIB_DEF_H_ diff --git a/lib/def/mod.gem b/lib/def/mod.gem new file mode 100644 index 0000000..22bfd7f --- /dev/null +++ b/lib/def/mod.gem @@ -0,0 +1,34 @@ +# Author: Sven Vogel +# Edited: 25.05.2024 +# License: GPL-2.0 + +# ,----------------------------------------. +# | Standard Type definitions | +# `----------------------------------------` + +# Unsigned integrals + +type unsgined half half int: u8 +type unsgined half int: u16 +type unsgined int: u32 +type unsgined double int: u64 +type unsgined double double int: u128 + +# Signed integrals + +type signed u8: i8 +type signed u16: i16 +type signed u32: i32 +type signed u64: i64 +type signed u128: i128 + +# IEEE-754 floating point + +type signed half float: f16 +type signed float: f32 +type signed double float: f64 +type signed double double float: f128 + +# String constant + +type ref u8: str diff --git a/lib/std.gem b/lib/std.gem new file mode 100644 index 0000000..402bc1b --- /dev/null +++ b/lib/std.gem @@ -0,0 +1,12 @@ +# Author: Sven Vogel +# Edited: 25.05.2024 +# License: GPL-2.0 + +# ,----------------------------------------. +# | Gemstone Standard Library | +# `----------------------------------------` + +# standard type definitions +import "def/mod.gem" + + From e11297ccfe04f15193719794b35ce9f8ffa8f1fe Mon Sep 17 00:00:00 2001 From: servostar Date: Sat, 25 May 2024 13:50:21 +0200 Subject: [PATCH 016/124] added io library --- lib/CMakeLists.txt | 20 +++++++++++++ lib/def.gem | 38 ++++++++++++++++++++++++ lib/def/def.h | 2 ++ lib/io.gem | 53 +++++++++++++++++++++++++++++++++ lib/io/io.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++ lib/io/io.h | 21 +++++++++++++ lib/std.gem | 2 +- run-lib-build.sh | 30 +++++++++++++++++++ 8 files changed, 239 insertions(+), 1 deletion(-) create mode 100644 lib/CMakeLists.txt create mode 100644 lib/def.gem create mode 100644 lib/io.gem create mode 100644 lib/io/io.c create mode 100644 lib/io/io.h create mode 100755 run-lib-build.sh diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt new file mode 100644 index 0000000..e5aa8cf --- /dev/null +++ b/lib/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.15...3.25) + +project(gemstone_stdlib + VERSION 0.1.0 + DESCRIPTION "gemstone programming language standard library" + LANGUAGES C) + +set(CMAKE_C_STANDARD 23) +set(CMAKE_C_STANDARD_REQUIRED TRUE) + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +include_directories(${PROJECT_SOURCE_DIR}) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/../bin/std") + +# add native module libraries + +file(GLOB_RECURSE STDLIB_IO_SOURCE_FILES io/*.c) +add_library(io ${STDLIB_IO_SOURCE_FILES}) + diff --git a/lib/def.gem b/lib/def.gem new file mode 100644 index 0000000..232d474 --- /dev/null +++ b/lib/def.gem @@ -0,0 +1,38 @@ +# Author: Sven Vogel +# Edited: 25.05.2024 +# License: GPL-2.0 + +# ,----------------------------------------. +# | Standard Type definitions | +# `----------------------------------------` + +# Unsigned integrals + +type unsgined half half int: u8 +type unsgined half int: u16 +type unsgined int: u32 +type unsgined double int: u64 +type unsgined double double int: u128 + +# Signed integrals + +type signed u8: i8 +type signed u16: i16 +type signed u32: i32 +type signed u64: i64 +type signed u128: i128 + +# IEEE-754 floating point + +type signed half float: f16 +type signed float: f32 +type signed double float: f64 +type signed double double float: f128 + +# String constant + +type ref u8: str + +# C style void pointer replacement + +type ref u8: ptr diff --git a/lib/def/def.h b/lib/def/def.h index b1980a9..94ad84d 100644 --- a/lib/def/def.h +++ b/lib/def/def.h @@ -22,4 +22,6 @@ typedef double f64; typedef u8* str; +typedef u8* ptr; + #endif // GEMSTONE_STD_LIB_DEF_H_ diff --git a/lib/io.gem b/lib/io.gem new file mode 100644 index 0000000..bc2c553 --- /dev/null +++ b/lib/io.gem @@ -0,0 +1,53 @@ +# Author: Sven Vogel +# Edited: 25.05.2024 +# License: GPL-2.0 + +# ,----------------------------------------. +# | Generic Input/Output | +# `----------------------------------------` + +import "def.gem" + +# platform specific handle to an I/O device +# can a file, buffer, window or something else +# NOTE: this reference is not meant to be dereferenced +# which can lead to errors and undefined behavior +type ptr: handle + +# Returns a handle to this processes standard input I/O handle +# -- Implementation note +# On Linux this will return 0 as is it convention under UNIX (see: https://www.man7.org/linux/man-pages/man3/stdin.3.html) +# On Windows the library will call `GetStdHandle(STD_INPUT_HANDLE)` +fun getStdinHandle(out handle: stdin) + +# Returns a handle to this processes standard input I/O handle +# -- Implementation note +# On Linux this will return 1 as is it convention under UNIX (see: https://www.man7.org/linux/man-pages/man3/stdout.3.html) +# On Windows the library will call `GetStdHandle(STD_OUTPUT_HANDLE)` +fun getStdoutHandle(out handle: stdout) + +# Returns a handle to this processes standard input I/O handle +# -- Implementation note +# On Linux this will return 1 as is it convention under UNIX (see: https://www.man7.org/linux/man-pages/man3/stderr.3.html) +# On Windows the library will call `GetStdHandle(STD_OUTPUT_HANDLE)` +fun getStderrHandle(out handle: stderr) + +# Write `len` number of bytes from `buf` into the I/O resource specified +# by `dev`. Returns the number of bytes written. +# -- Implementation note +# On Linux this will use the syscall write +# On Windows this will use the WriteFile function +fun writeBytes(in handle: dev, in ref u8: buf, in ref u32: len)(out u32: written) + +# Read atmost `len` bytes to `buf` from the I/O resource specified by `dev` +# Returns the number of read bytes in `written` +# -- Implementation note +# On Linux this will use the syscall read +# On Windows this will use the ReadFile function +fun readBytes(in handle: dev, in ref u8: buf, in ref u32: len)(out u32: read) + +# Flushes the buffers of the I/O resource specified by `dev` +# -- Implementation note +# On Linux this will use the fsync function +# On Windows this will use the FlushFileBuffers function +fun flush(in handle: dev) diff --git a/lib/io/io.c b/lib/io/io.c new file mode 100644 index 0000000..f47dd6f --- /dev/null +++ b/lib/io/io.c @@ -0,0 +1,74 @@ + +#include +#include + +#if defined(_WIN32) || defined (_WIN64) + +// Compile for Windows + +#include + +// FIXME: error in case GetStdHandle return INVALID_HANDLE_VALUE +// FIXME: error in case functions return 0 + +void getStdinHandle(handle* stdin) { + *stdin = (handle) GetStdHandle(STD_INPUT_HANDLE); +} + +void getStdoutHandle(handle* stdout) { + *stdout = (handle) GetStdHandle(STD_OUTPUT_HANDLE); +} + +void getStderrHandle(handle* stderr) { + *stderr = (handle) GetStdHandle(STD_ERROR_HANDLE); +} + +void writeBytes(handle dev, u8* buf, u32 len, u32* bytesWritten) { + WriteFile((HANDLE) dev, buf, len, bytesRead, NULL); +} + +void readBytes(handle dev, u8* buf, u32 len, u32* bytesRead) { + ReadFile((HANDLE) dev, buf, len, bytesRead, NULL); +} + +void flush(handle dev) { + FlushFileBuffers((HANDLE) dev); +} + +#elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__linux__) + +// Compile for Linux and BSD + +#include + +// savely cast a 64-bit pointer down to a 32-bit value +// this assumes that 64-bit system will use 32-bit handles +// which are stored as 64-bit by zero extending +#define TO_INT(x) ((int)(long int)(x)) + +void getStdinHandle(handle* stdin) { + *stdin = (handle) STDIN_FILENO; +} + +void getStdoutHandle(handle* stdout) { + *stdout = (handle) STDOUT_FILENO; +} + +void getStderrHandle(handle* stderr) { + *stderr = (handle) STDERR_FILENO; +} + +void writeBytes(handle dev, u8* buf, u32 len, u32* bytesWritten) { + *bytesWritten = write(TO_INT(dev), buf, len); +} + +void readBytes(handle dev, u8* buf, u32 len, u32* bytesRead) { + *bytesRead = read(TO_INT(dev), buf, len); +} + +void flush(handle dev) { + fsync(TO_INT(dev)); +} + + +#endif diff --git a/lib/io/io.h b/lib/io/io.h new file mode 100644 index 0000000..4e00856 --- /dev/null +++ b/lib/io/io.h @@ -0,0 +1,21 @@ + +#ifndef GEMSTONE_STD_LIB_IO_H_ +#define GEMSTONE_STD_LIB_IO_H_ + +#include + +typedef ptr handle; + +void getStdinHandle(handle* stdin); + +void getStdoutHandle(handle* stdout); + +void getStderrHandle(handle* stderr); + +void writeBytes(handle dev, u8* buf, u32 len, u32* written); + +void readBytes(handle dev, u8* buf, u32 len, u32* read); + +void flush(handle dev); + +#endif //GEMSTONE_STD_LIB_IO_H_ diff --git a/lib/std.gem b/lib/std.gem index 402bc1b..8f50d04 100644 --- a/lib/std.gem +++ b/lib/std.gem @@ -7,6 +7,6 @@ # `----------------------------------------` # standard type definitions -import "def/mod.gem" +import "def.gem" diff --git a/run-lib-build.sh b/run-lib-build.sh new file mode 100755 index 0000000..ccca62c --- /dev/null +++ b/run-lib-build.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +# Author: Sven Vogel +# Created: 25.05.2024 +# Description: Builds the standard library into bin/std + +echo "+--------------------------------------+" +echo "| CONFIGURE STD LIBRARY |" +echo "+--------------------------------------+" + +cmake lib +if [ ! $? -eq 0 ]; then + echo "===> failed to configure build" + exit 1 +fi + +echo "+--------------------------------------+" +echo "| BUILD STD LIBRARY |" +echo "+--------------------------------------+" + +cd lib || exit 1 +make -B +if [ ! $? -eq 0 ]; then + echo "===> failed to build standard library" + exit 1 +fi + +echo "+--------------------------------------+" +echo "| successfully build standard library |" +echo "+--------------------------------------+" From 74ce05e2c63a4f6c48924a4bf8b941dcbb9787f3 Mon Sep 17 00:00:00 2001 From: servostar Date: Sat, 25 May 2024 13:52:59 +0200 Subject: [PATCH 017/124] added std lib build to check test --- run-check-test.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/run-check-test.sh b/run-check-test.sh index bd7e5cc..07c49d7 100644 --- a/run-check-test.sh +++ b/run-check-test.sh @@ -17,6 +17,8 @@ if [ ! $? -eq 0 ]; then exit 1 fi +sh -c ./run-lib-build.sh + echo "+--------------------------------------+" echo "| RUNNING CODE CHECK |" echo "+--------------------------------------+" From 4c8e0992bc6523c030a46169ae912cedb7f361b1 Mon Sep 17 00:00:00 2001 From: servostar Date: Sat, 25 May 2024 13:54:21 +0200 Subject: [PATCH 018/124] added lib build to devkit --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 68265d8..8e503ae 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,5 +10,6 @@ COPY --chown=lorang CMakeLists.txt /home/lorang/ COPY --chown=lorang run-check-test.sh /home/lorang/ COPY --chown=lorang .env /home/lorang/ COPY --chown=lorang run-docker-build.sh /home/lorang/ +COPY --chown=lorang run-lib-build.sh /home/lorang/ RUN cmake . From 9a16546e07ee72e71fecfcf0db0ff45ca8fba136 Mon Sep 17 00:00:00 2001 From: servostar Date: Sat, 25 May 2024 16:38:26 +0200 Subject: [PATCH 019/124] added memory module and refactored filenames in stdlib --- lib/CMakeLists.txt | 2 ++ lib/def/{def.h => api.h} | 0 lib/def/mod.gem | 34 --------------------------- lib/io/{io.h => api.h} | 2 +- lib/io/{io.c => impl.c} | 3 +-- lib/mem.gem | 27 +++++++++++++++++++++ lib/mem/api.h | 17 ++++++++++++++ lib/mem/impl.c | 51 ++++++++++++++++++++++++++++++++++++++++ lib/std.gem | 4 ++++ 9 files changed, 103 insertions(+), 37 deletions(-) rename lib/def/{def.h => api.h} (100%) delete mode 100644 lib/def/mod.gem rename lib/io/{io.h => api.h} (94%) rename lib/io/{io.c => impl.c} (97%) create mode 100644 lib/mem.gem create mode 100644 lib/mem/api.h create mode 100644 lib/mem/impl.c diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index e5aa8cf..ac34f1f 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -18,3 +18,5 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/../bin/std") file(GLOB_RECURSE STDLIB_IO_SOURCE_FILES io/*.c) add_library(io ${STDLIB_IO_SOURCE_FILES}) +file(GLOB_RECURSE STDLIB_MEM_SOURCE_FILES mem/*.c) +add_library(mem ${STDLIB_MEM_SOURCE_FILES}) diff --git a/lib/def/def.h b/lib/def/api.h similarity index 100% rename from lib/def/def.h rename to lib/def/api.h diff --git a/lib/def/mod.gem b/lib/def/mod.gem deleted file mode 100644 index 22bfd7f..0000000 --- a/lib/def/mod.gem +++ /dev/null @@ -1,34 +0,0 @@ -# Author: Sven Vogel -# Edited: 25.05.2024 -# License: GPL-2.0 - -# ,----------------------------------------. -# | Standard Type definitions | -# `----------------------------------------` - -# Unsigned integrals - -type unsgined half half int: u8 -type unsgined half int: u16 -type unsgined int: u32 -type unsgined double int: u64 -type unsgined double double int: u128 - -# Signed integrals - -type signed u8: i8 -type signed u16: i16 -type signed u32: i32 -type signed u64: i64 -type signed u128: i128 - -# IEEE-754 floating point - -type signed half float: f16 -type signed float: f32 -type signed double float: f64 -type signed double double float: f128 - -# String constant - -type ref u8: str diff --git a/lib/io/io.h b/lib/io/api.h similarity index 94% rename from lib/io/io.h rename to lib/io/api.h index 4e00856..c642185 100644 --- a/lib/io/io.h +++ b/lib/io/api.h @@ -2,7 +2,7 @@ #ifndef GEMSTONE_STD_LIB_IO_H_ #define GEMSTONE_STD_LIB_IO_H_ -#include +#include typedef ptr handle; diff --git a/lib/io/io.c b/lib/io/impl.c similarity index 97% rename from lib/io/io.c rename to lib/io/impl.c index f47dd6f..19fe716 100644 --- a/lib/io/io.c +++ b/lib/io/impl.c @@ -1,6 +1,5 @@ -#include -#include +#include #if defined(_WIN32) || defined (_WIN64) diff --git a/lib/mem.gem b/lib/mem.gem new file mode 100644 index 0000000..faecbc4 --- /dev/null +++ b/lib/mem.gem @@ -0,0 +1,27 @@ +# Author: Sven Vogel +# Edited: 25.05.2024 +# License: GPL-2.0 + +# ,----------------------------------------. +# | Memory Management | +# `----------------------------------------` + +import "def.gem" + +# Allocate `len` bytes of heap memory +# Returns a pointer to the memory as `ptr` +fun heap_alloc(in u32: len)(out ref u8: ptr) + +# Rellocate `len` bytes of heap memory +# Returns a pointer to the memory as `ptr` +fun heap_realloc(in u32: len, in out ref u8: ptr) + +# Free a block of memory +fun heap_free(in ref u8: ptr) + +# Copy `len` bytes from `dst` into `src` +fun copy(in ref u8: dst, in ref u8: src, in u32 len) + +# Fill `len` bytes of `dst` with `byte` +fun fill(in ref u8: dst, in u8: byte, in u32 len) + diff --git a/lib/mem/api.h b/lib/mem/api.h new file mode 100644 index 0000000..8ca69c0 --- /dev/null +++ b/lib/mem/api.h @@ -0,0 +1,17 @@ + +#ifndef GEMSTONE_STD_LIB_MEM_H_ +#define GEMSTONE_STD_LIB_MEM_H_ + +#include + +void heap_alloc(u32 len, u8** ptr); + +void heap_realloc(u32 len, u8** ptr); + +void heap_free(u8* ptr); + +void copy(u8* dst, u8* src, u32 len); + +void fill(u8* dst, u8 byte, u32 len); + +#endif // GEMSTONE_STD_LIB_MEM_H_ diff --git a/lib/mem/impl.c b/lib/mem/impl.c new file mode 100644 index 0000000..95863ac --- /dev/null +++ b/lib/mem/impl.c @@ -0,0 +1,51 @@ + +#include + +#if defined(_WIN32) || defined (_WIN64) + +#include + +#define HEAP_API_GLOBAL_FLAGS HEAP_ZERO_MEMORY | HEAP_GENERATE_EXCEPTIONS + +void heap_alloc(u32 len, u8** ptr) { + HANDLE heap = GetProcessHeap(); + *ptr = HeapAlloc(heap, HEAP_API_GLOBAL_FLAGS, len); +} + +void heap_realloc(u32 len, u8** ptr) { + HANDLE heap = GetProcessHeap(); + *ptr = HeapReAlloc(heap, HEAP_API_GLOBAL_FLAGS, *ptr, len); +} + +void heap_free(u8* ptr) { + HANDLE heap = GetProcessHeap(); + HeapFree(heap, ptr); +} + +#elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__linux__) + +#include + +void heap_alloc(u32 len, u8** ptr) { + *ptr = malloc(len); +} + +void heap_realloc(u32 len, u8** ptr) { + *ptr = realloc(*ptr, len); +} + +void heap_free(u8* ptr) { + free(ptr); +} + +#endif + +#include + +void copy(u8* dst, u8* src, u32 len) { + memcpy(dst, src, len); +} + +void fill(u8* dst, u8 byte, u32 len) { + memset(dst, byte, len); +} \ No newline at end of file diff --git a/lib/std.gem b/lib/std.gem index 8f50d04..e135a13 100644 --- a/lib/std.gem +++ b/lib/std.gem @@ -9,4 +9,8 @@ # standard type definitions import "def.gem" +# I/O operations +import "io.gem" +# memory management +import "mem.gem" From 0aa62542b5a36919407383b0a844b4ec1950c7b8 Mon Sep 17 00:00:00 2001 From: servostar Date: Sat, 25 May 2024 17:02:17 +0200 Subject: [PATCH 020/124] added bool definition --- lib/bool.gem | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 lib/bool.gem diff --git a/lib/bool.gem b/lib/bool.gem new file mode 100644 index 0000000..e028294 --- /dev/null +++ b/lib/bool.gem @@ -0,0 +1,7 @@ + +import "def.gem" + +type unsigned int: bool + +static bool: TRUE = 1 +static bool: FALSE = 0 From b7c7fd040ad24cc84f1922fe8c12be19658e1670 Mon Sep 17 00:00:00 2001 From: Filleo Date: Sun, 26 May 2024 16:42:12 +0200 Subject: [PATCH 021/124] added ast pointer to all structs removed StringLiteralType because of multiple definitions if used --- src/set/types.h | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/src/set/types.h b/src/set/types.h index c58dd67..621fe7f 100644 --- a/src/set/types.h +++ b/src/set/types.h @@ -44,6 +44,7 @@ typedef struct CompositeType_t { Sign sign; Scale scale; PrimitiveType primitive; + AST_NODE_PTR nodePtr; } CompositeType; /** @@ -72,6 +73,7 @@ typedef struct BoxMember_t { const char* name; Type* type; BoxType* box; + AST_NODE_PTR nodePtr; } BoxMember; /** @@ -82,6 +84,7 @@ typedef struct BoxType_t { // hashtable of members. // Associates the memebers name (const char*) with its type (BoxMember) GHashTable* member; + AST_NODE_PTR nodePtr; } BoxType; typedef struct Variable_t Variable; @@ -90,6 +93,7 @@ typedef struct BoxAccess_t { // list of recursive box accesses // contains a list of BoxMembers (each specifying their own type, name and box type) GArray* member; + AST_NODE_PTR nodePtr; } BoxAccess; typedef struct Type_t { @@ -103,30 +107,16 @@ typedef struct Type_t { BoxType box; ReferenceType reference; } impl; + AST_NODE_PTR nodePtr; } Type; typedef struct Typedefine_t { const char* name; Type type; + AST_NODE_PTR nodePtr; } Typedefine; -const Type ShortShortUnsingedIntType = { - .kind = TypeKindComposite, - .impl = { - .composite = { - .sign = Unsigned, - .scale = 0.25, - .primitive = Int - } - } -}; -const Type StringLiteralType = { - .kind = TypeKindReference, - .impl = { - .reference = (ReferenceType) &ShortShortUnsingedIntType, - } -}; /** * @brief Reprents the value of type. Can be used to definitons, initialization and for expressions contants. @@ -137,6 +127,7 @@ typedef struct TypeValue_t { Type type; // UTF-8 representation of the type's value const char* value; + AST_NODE_PTR nodePtr; } TypeValue; // .------------------------------------------------. @@ -166,6 +157,7 @@ typedef enum IO_Qualifier_t { typedef struct ParameterDeclaration_t { Type type; IO_Qualifier qualifier; + AST_NODE_PTR nodePtr; } ParameterDeclaration; /** @@ -177,6 +169,7 @@ typedef struct ParameterDefinition_t { // value to initalize the declaration with // NOTE: type of initializer and declaration MUST be equal TypeValue initializer; + AST_NODE_PTR nodePtr; } ParameterDefinition; typedef enum ParameterKind_t { @@ -195,12 +188,14 @@ typedef struct Parameter_t { ParameterDeclaration declaration; ParameterDefinition definiton; } impl; + AST_NODE_PTR nodePtr; } Paramer; typedef struct FunctionDefinition_t { // hashtable of parameters // associates a parameters name (const char*) with its parameter declaration (ParameterDeclaration) GArray* parameter; + AST_NODE_PTR nodePtr; } FunctionDefinition; // .------------------------------------------------. @@ -216,6 +211,7 @@ typedef enum StorageQualifier_t { typedef struct VariableDeclaration_t { StorageQualifier qualifier; Type type; + AST_NODE_PTR nodePtr; } VariableDeclaration; /** @@ -227,6 +223,7 @@ typedef struct VariableDeclaration_t { typedef struct VariableDefiniton_t { VariableDeclaration declaration; TypeValue initializer; + AST_NODE_PTR nodePtr; } VariableDefiniton; typedef enum VariableKind_t { @@ -243,6 +240,7 @@ typedef struct Variable_t { VariableDefiniton definiton; BoxMember member; } impl; + AST_NODE_PTR nodePtr; } Variable; // .------------------------------------------------. @@ -260,6 +258,7 @@ typedef struct Variable_t { */ typedef struct TypeCast_t { Type targetType; + AST_NODE_PTR nodePtr; } TypeCast; /** @@ -271,6 +270,7 @@ typedef struct TypeCast_t { */ typedef struct Transmute_t { Type targetType; + AST_NODE_PTR nodePtr; } Transmute; // .------------------------------------------------. @@ -358,6 +358,7 @@ typedef struct Operation_t { LogicalOperator logical; BitwiseOperator bitwise; } impl; + AST_NODE_PTR nodePtr; } Operation; // .------------------------------------------------. @@ -380,6 +381,7 @@ typedef struct Expression_t { TypeValue constant; Variable variable; } impl; + AST_NODE_PTR nodePtr; } Expression; // .------------------------------------------------. @@ -391,6 +393,7 @@ typedef struct FunctionCall_t { FunctionDefinition* function; // list of expression arguments GArray* expressions; + AST_NODE_PTR nodePtr; } FunctionCall; typedef struct FunctionBoxCall_t { @@ -401,11 +404,13 @@ typedef struct FunctionBoxCall_t { // box which has the function defined for it // NOTE: must be of TypeKind: Box Variable selfArgument; + AST_NODE_PTR nodePtr; } FunctionBoxCall; typedef struct Block_t { // array of statements GArray* statemnts; + AST_NODE_PTR nodePtr; } Block; // .------------------------------------------------. @@ -415,6 +420,7 @@ typedef struct Block_t { typedef struct While_t { Expression conditon; Block block; + AST_NODE_PTR nodePtr; } While; // .------------------------------------------------. @@ -424,15 +430,18 @@ typedef struct While_t { typedef struct If_t { Expression conditon; Block block; + AST_NODE_PTR nodePtr; } If; typedef struct ElseIf_t { Expression conditon; Block block; + AST_NODE_PTR nodePtr; } ElseIf; typedef struct Else_t { Block block; + AST_NODE_PTR nodePtr; } Else; typedef struct Branch_t { @@ -440,6 +449,7 @@ typedef struct Branch_t { // list of else-ifs (can be empty/NULL) GArray* elseIfBranches; Else elseBranch; + AST_NODE_PTR nodePtr; } Branch; // .------------------------------------------------. @@ -449,6 +459,7 @@ typedef struct Branch_t { typedef struct Assignment_t { Variable* variable; Expression value; + AST_NODE_PTR nodePtr; } Assignment; typedef enum StatementKind_t { @@ -467,6 +478,7 @@ typedef struct Statement_t { Branch branch; Assignment assignment; } impl; + AST_NODE_PTR nodePtr; } Statement; #endif // SET_TYPES_H_ From 614c917b81da4e1edee766862c8a0f21034753d0 Mon Sep 17 00:00:00 2001 From: servostar Date: Sun, 26 May 2024 17:07:39 +0200 Subject: [PATCH 022/124] removed redundant files --- src/llvm/backend.c | 46 -------- src/llvm/decl/variable.c | 94 ----------------- src/llvm/decl/variable.h | 16 --- src/llvm/expr/build.c | 134 ------------------------ src/llvm/expr/build.h | 13 --- src/llvm/function/function-types.h | 31 ------ src/llvm/function/function.c | 159 ---------------------------- src/llvm/function/function.h | 39 ------- src/llvm/stmt/build.c | 89 ---------------- src/llvm/stmt/build.h | 11 -- src/llvm/types/composite-types.h | 35 ------- src/llvm/types/composite.c | 163 ----------------------------- src/llvm/types/composite.h | 18 ---- src/llvm/types/scope.c | 119 --------------------- src/llvm/types/scope.h | 132 ----------------------- src/llvm/types/structs.h | 36 ------- src/llvm/types/type.c | 120 --------------------- src/llvm/types/type.h | 54 ---------- 18 files changed, 1309 deletions(-) delete mode 100644 src/llvm/decl/variable.c delete mode 100644 src/llvm/decl/variable.h delete mode 100644 src/llvm/expr/build.c delete mode 100644 src/llvm/expr/build.h delete mode 100644 src/llvm/function/function-types.h delete mode 100644 src/llvm/function/function.c delete mode 100644 src/llvm/function/function.h delete mode 100644 src/llvm/stmt/build.c delete mode 100644 src/llvm/stmt/build.h delete mode 100644 src/llvm/types/composite-types.h delete mode 100644 src/llvm/types/composite.c delete mode 100644 src/llvm/types/composite.h delete mode 100644 src/llvm/types/scope.c delete mode 100644 src/llvm/types/scope.h delete mode 100644 src/llvm/types/structs.h delete mode 100644 src/llvm/types/type.c delete mode 100644 src/llvm/types/type.h diff --git a/src/llvm/backend.c b/src/llvm/backend.c index a2fcef9..30a248d 100644 --- a/src/llvm/backend.c +++ b/src/llvm/backend.c @@ -1,10 +1,4 @@ -#include -#include -#include -#include -#include -#include #include #include #include @@ -23,46 +17,6 @@ static BackendError llvm_backend_codegen(const AST_NODE_PTR module_node, void**) BackendError err; - TypeScopeRef global_scope = type_scope_new(); - - for (size_t i = 0; i < module_node->child_count; i++) { - // iterate over all nodes in module - // can either be a function, box, definition, declaration or typedefine - - AST_NODE_PTR global_node = AST_get_node(module_node, i); - - GemstoneTypedefRef typedefref; - GArray* decls; - - switch (global_node->kind) { - case AST_Typedef: - typedefref = get_type_def_from_ast(global_scope, global_node); - type_scope_append_type(global_scope, typedefref); - break; - case AST_Fun: - llvm_generate_function_implementation(global_scope, module, global_node); - break; - case AST_Decl: - decls = declaration_from_ast(global_scope, global_node); - for (size_t i = 0; i < decls->len; i++) { - GemstoneDeclRef decl = ((GemstoneDeclRef*) decls->data)[i]; - - err = llvm_create_declaration(module, NULL, decl, &decl->llvm_value); - - if (err.kind != Success) - break; - - type_scope_add_variable(global_scope, decl); - } - - break; - default: - PANIC("NOT IMPLEMENTED"); - } - } - - type_scope_delete(global_scope); - LLVMDisposeModule(module); LLVMContextDispose(context); diff --git a/src/llvm/decl/variable.c b/src/llvm/decl/variable.c deleted file mode 100644 index d1d7a15..0000000 --- a/src/llvm/decl/variable.c +++ /dev/null @@ -1,94 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static StorageQualifier get_storage_qualifier_from_ast(AST_NODE_PTR storageQualifierNode) { - if (storageQualifierNode->kind != AST_Storage) { - PANIC("Node must be of type AST_Fun: %s", AST_node_to_string(storageQualifierNode)); - } - - StorageQualifier storageQualifier; - - if (strcmp(storageQualifierNode->value, "local") == 0) { - storageQualifier = StorageQualifierLocal; - } else if (strcmp(storageQualifierNode->value, "static") == 0) { - storageQualifier = StorageQualifierStatic; - } else if (strcmp(storageQualifierNode->value, "global") == 0) { - storageQualifier = StorageQualifierGlobal; - } else { - PANIC("unknown storage qualifier: %s", storageQualifierNode->value); - } - - return storageQualifier; -} - -GArray* declaration_from_ast(TypeScopeRef scope, const AST_NODE_PTR node) { - if (node->kind != AST_Decl) { - PANIC("Node must be of type AST_Fun: %s", AST_node_to_string(node)); - } - - GArray* decls = g_array_new(FALSE, FALSE, sizeof(GemstoneDeclRef)); - - AST_NODE_PTR first_child = AST_get_node(node, 0); - - StorageQualifier qualifier = StorageQualifierStatic; - GemstoneTypeRef type = NULL; - AST_NODE_PTR list = NULL; - - if (first_child->kind == AST_Storage) { - qualifier = get_storage_qualifier_from_ast(first_child); - type = get_type_from_ast(scope, AST_get_node(node, 1)); - list = AST_get_node(node, 2); - - } else { - type = get_type_from_ast(scope, first_child); - list = AST_get_node(node, 1); - } - - if (list->kind != AST_IdentList) { - PANIC("Node must be of type AST_IdentList: %s", AST_node_to_string(node)); - } - - for (size_t i = 0; i < list->child_count; i++) { - GemstoneDeclRef ref = malloc(sizeof(GemstoneDecl)); - ref->name = AST_get_node(list, i)->value; - ref->storageQualifier = qualifier; - ref->type = type; - - g_array_append_val(decls, ref); - } - - return decls; -} - -BackendError llvm_create_declaration(LLVMModuleRef llvm_module, LLVMBuilderRef llvm_builder, GemstoneDeclRef gem_decl, LLVMValueRef* llvm_decl) { - LLVMContextRef context = LLVMGetModuleContext(llvm_module); - LLVMTypeRef llvmTypeRef = llvm_type_from_gemstone_type(context, gem_decl->type); - LLVMValueRef defaultValue = llvm_default_value_of_type(context, gem_decl->type); - - switch(gem_decl->storageQualifier) { - case StorageQualifierLocal: - if (llvm_builder == NULL) { - return new_backend_impl_error(Implementation, NULL, "initializing a local variable on non-local scope"); - } - *llvm_decl = LLVMBuildAlloca(llvm_builder, llvmTypeRef, gem_decl->name); - LLVMBuildStore(llvm_builder, defaultValue, *llvm_decl); - break; - case StorageQualifierStatic: - // add global - *llvm_decl = LLVMAddGlobal(llvm_module, llvmTypeRef, gem_decl->name); - LLVMSetInitializer(*llvm_decl, defaultValue); - break; - case StorageQualifierGlobal: - PANIC("Global not implemented"); - break; - } - - return SUCCESS; -} diff --git a/src/llvm/decl/variable.h b/src/llvm/decl/variable.h deleted file mode 100644 index 07cd9f2..0000000 --- a/src/llvm/decl/variable.h +++ /dev/null @@ -1,16 +0,0 @@ - -#ifndef LLVM_DECL_VAR_H_ -#define LLVM_DECL_VAR_H_ - -#include -#include -#include -#include -#include -#include - -GArray* declaration_from_ast(TypeScopeRef scope, const AST_NODE_PTR node); - -BackendError llvm_create_declaration(LLVMModuleRef llvm_module, LLVMBuilderRef llvm_builder, GemstoneDeclRef gem_decl, LLVMValueRef* llvm_decl); - -#endif // LLVM_DECL_VAR_H_ diff --git a/src/llvm/expr/build.c b/src/llvm/expr/build.c deleted file mode 100644 index 0bcba93..0000000 --- a/src/llvm/expr/build.c +++ /dev/null @@ -1,134 +0,0 @@ -#include -#include -#include -#include -#include -#include - -BackendError llvm_build_arithmetic_operation(LLVMBuilderRef builder, TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR expr_node, enum AST_SyntaxElement_t operation, LLVMValueRef* yield) { - AST_NODE_PTR expr_lhs = AST_get_node(expr_node, 0); - AST_NODE_PTR expr_rhs = AST_get_node(expr_node, 1); - - LLVMValueRef llvm_lhs = NULL; - LLVMValueRef llvm_rhs = NULL; - BackendError err; - - err = llvm_build_expression(builder, scope, module, expr_lhs, &llvm_lhs); - if (err.kind != Success) - return err; - - err = llvm_build_expression(builder, scope, module, expr_rhs, &llvm_rhs); - if (err.kind != Success) - return err; - - switch (operation) { - case AST_Add: - *yield = LLVMBuildAdd(builder, llvm_lhs, llvm_rhs, "Addition"); - break; - case AST_Sub: - *yield = LLVMBuildSub(builder, llvm_lhs, llvm_rhs, "Subtraction"); - break; - case AST_Mul: - *yield = LLVMBuildMul(builder, llvm_lhs, llvm_rhs, "Multiplication"); - break; - case AST_Div: - *yield = LLVMBuildSDiv(builder, llvm_lhs, llvm_rhs, "Division"); - break; - default: - break; - } - - return new_backend_impl_error(Implementation, expr_node, "invalid arithmetic operation"); -} - -BackendError llvm_build_relational_operation(LLVMBuilderRef builder, TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR expr_node, enum AST_SyntaxElement_t operation, LLVMValueRef* yield) { - AST_NODE_PTR expr_lhs = AST_get_node(expr_node, 0); - AST_NODE_PTR expr_rhs = AST_get_node(expr_node, 1); - - LLVMValueRef llvm_lhs = NULL; - LLVMValueRef llvm_rhs = NULL; - BackendError err; - - err = llvm_build_expression(builder, scope, module, expr_lhs, &llvm_lhs); - if (err.kind != Success) - return err; - - err = llvm_build_expression(builder, scope, module, expr_rhs, &llvm_rhs); - if (err.kind != Success) - return err; - - // TODO: make a difference between SignedInt, UnsignedInt and Float - switch (operation) { - case AST_Eq: - *yield = LLVMBuildICmp(builder, LLVMIntEQ, llvm_lhs, llvm_rhs, "Equal"); - break; - case AST_Greater: - *yield = LLVMBuildICmp(builder, LLVMIntSGT, llvm_lhs, llvm_rhs, "Greater"); - break; - case AST_Less: - *yield = LLVMBuildICmp(builder, LLVMIntSLT, llvm_lhs, llvm_rhs, "Less"); - break; - default: - break; - } - - return new_backend_impl_error(Implementation, expr_node, "invalid arithmetic operation"); -} - -BackendError llvm_build_expression(LLVMBuilderRef builder, TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR expr_node, LLVMValueRef* yield) { - - switch (expr_node->kind) { - case AST_Ident: { - AST_NODE_PTR variable_name = AST_get_node(expr_node, 0); - GemstoneDeclRef decl = type_scope_get_variable(scope, variable_name->value); - *yield = decl->llvm_value; - } - break; - case AST_Int: { - AST_NODE_PTR constant = AST_get_node(expr_node, 0); - // TODO: type annotation needed - *yield = LLVMConstIntOfString(LLVMInt32Type(), constant->value, 10); - } - case AST_Float: { - AST_NODE_PTR constant = AST_get_node(expr_node, 0); - // TODO: type annotation needed - *yield = LLVMConstRealOfString(LLVMFloatType(), constant->value); - } - break; - case AST_Add: - case AST_Sub: - case AST_Mul: - case AST_Div: { - BackendError err = llvm_build_arithmetic_operation(builder, scope, module, expr_node, expr_node->kind, yield); - if (err.kind != Success) - return err; - } - case AST_Eq: - case AST_Greater: - case AST_Less: { - BackendError err = llvm_build_relational_operation(builder, scope, module, expr_node, expr_node->kind, yield); - if (err.kind != Success) - return err; - } - break; - } - - return SUCCESS; -} - -BackendError llvm_build_expression_list(LLVMBuilderRef builder, TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR exprlist_node, LLVMValueRef** yields) { - - if (exprlist_node->kind != AST_ExprList) { - return new_backend_impl_error(Implementation, exprlist_node, "expected expression list"); - } - - *yields = malloc(sizeof(LLVMValueRef) * exprlist_node->child_count); - - for (size_t i = 0; i < exprlist_node->child_count; i++) { - AST_NODE_PTR expr = AST_get_node(exprlist_node, 0); - - llvm_build_expression(builder, scope, module, expr, *yields + i); - } - - return SUCCESS; -} diff --git a/src/llvm/expr/build.h b/src/llvm/expr/build.h deleted file mode 100644 index a4d2c28..0000000 --- a/src/llvm/expr/build.h +++ /dev/null @@ -1,13 +0,0 @@ - -#ifndef LLVM_EXPR_BUILD_H_ -#define LLVM_EXPR_BUILD_H_ - -#include "codegen/backend.h" -#include "llvm/types/scope.h" -#include - -BackendError llvm_build_expression(LLVMBuilderRef builder, TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR expr_node, LLVMValueRef* yield); - -BackendError llvm_build_expression_list(LLVMBuilderRef builder, TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR expr_node, LLVMValueRef** yields); - -#endif // LLVM_EXPR_BUILD_H_ diff --git a/src/llvm/function/function-types.h b/src/llvm/function/function-types.h deleted file mode 100644 index 211bf54..0000000 --- a/src/llvm/function/function-types.h +++ /dev/null @@ -1,31 +0,0 @@ - -#ifndef LLVM_TYPES_FUNCTION_TYPES_H_ -#define LLVM_TYPES_FUNCTION_TYPES_H_ - -#include -#include -#include - -enum IO_Qualifier_t { - Unspec, - In, - Out, - InOut -}; - -typedef struct GemstoneParam_t { - const char* name; - enum IO_Qualifier_t qualifier; - GemstoneTypeRef typename; -} GemstoneParam; - -typedef struct GemstoneFun_t { - const char* name; - GArray* params; - LLVMTypeRef llvm_signature; - LLVMValueRef llvm_function; -} GemstoneFun; - -typedef GemstoneFun* GemstoneFunRef; - -#endif // LLVM_TYPES_FUNCTION_TYPES_H_ diff --git a/src/llvm/function/function.c b/src/llvm/function/function.c deleted file mode 100644 index 3623f79..0000000 --- a/src/llvm/function/function.c +++ /dev/null @@ -1,159 +0,0 @@ - -#include "codegen/backend.h" -#include "llvm/function/function-types.h" -#include "llvm/stmt/build.h" -#include -#include -#include -#include -#include -#include -#include - -static enum IO_Qualifier_t io_qualifier_from_string(const char* str) { - if (strcmp(str, "in") == 0) { - return In; - } - - return Out; -} - -static enum IO_Qualifier_t merge_qualifier(enum IO_Qualifier_t a, enum IO_Qualifier_t b) { - enum IO_Qualifier_t result = Unspec; - - if (a == In && b == Out) { - result = InOut; - } else if (a == Out && b == In) { - result = InOut; - } - - return result; -} - -static enum IO_Qualifier_t io_qualifier_from_ast_list(const AST_NODE_PTR node) { - // node is expected to be a list - if (node->kind != AST_List) { - PANIC("Node must be of type AST_List: %s", AST_node_to_string(node)); - } - - enum IO_Qualifier_t qualifier = Unspec; - - for (size_t i = 0; i < node->child_count; i++) { - - AST_NODE_PTR qualifier_node = AST_get_node(node, i); - - if (qualifier_node->kind != AST_Qualifyier) { - PANIC("Node must be of type AST_Qualifyier: %s", AST_node_to_string(node)); - } - - enum IO_Qualifier_t local_qualifier = io_qualifier_from_string(qualifier_node->value); - - if (qualifier == Unspec) { - qualifier = local_qualifier; - } else { - qualifier = merge_qualifier(qualifier, local_qualifier); - } - } - - if (qualifier == Unspec) - qualifier = In; - - return qualifier; -} - -GemstoneParam param_from_ast(const TypeScopeRef scope, const AST_NODE_PTR node) { - GemstoneParam param; - - // node is expected to be a parameter - if (node->kind != AST_Parameter) { - PANIC("Node must be of type AST_ParamList: %s", AST_node_to_string(node)); - } - - AST_NODE_PTR qualifier_list = AST_get_node(node, 0); - param.qualifier = io_qualifier_from_ast_list(qualifier_list); - - AST_NODE_PTR param_decl = AST_get_node(node, 1); - AST_NODE_PTR param_type = AST_get_node(param_decl, 0); - param.typename = get_type_from_ast(scope, param_type); - param.name = AST_get_node(param_decl, 1)->value; - - return param; -} - -GemstoneFunRef fun_from_ast(const TypeScopeRef scope, const AST_NODE_PTR node) { - if (node->kind != AST_Fun) { - PANIC("Node must be of type AST_Fun: %s", AST_node_to_string(node)); - } - - GemstoneFunRef function = malloc(sizeof(GemstoneFun)); - function->name = AST_get_node(node, 0)->value; - function->params = g_array_new(FALSE, FALSE, sizeof(GemstoneParam)); - - AST_NODE_PTR list = AST_get_node(node, 1); - for (size_t i = 0; i < list->child_count; i++) { - AST_NODE_PTR param_list = AST_get_node(list, i); - - for (size_t k = 0; k < param_list->child_count; k++) { - AST_NODE_PTR param = AST_get_node(param_list, k); - - GemstoneParam par = param_from_ast(scope, param); - - g_array_append_val(function->params, par); - } - } - - // TODO: parse function body - return function; -} - -void fun_delete(const GemstoneFunRef fun) { - g_array_free(fun->params, TRUE); - free(fun); -} - -LLVMTypeRef llvm_generate_function_signature(LLVMContextRef context, GemstoneFunRef function) { - unsigned int param_count = function->params->len; - - LLVMTypeRef* params = malloc(sizeof(LLVMTypeRef)); - - for (size_t i = 0; i < param_count; i++) { - GemstoneParam* gem_param = ((GemstoneParam*) function->params->data) + i; - params[i] = llvm_type_from_gemstone_type(context, gem_param->typename); - } - - return LLVMFunctionType(LLVMVoidType(), params, param_count, 0); -} - -BackendError llvm_generate_function_implementation(TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR node) { - LLVMContextRef context = LLVMGetModuleContext(module); - GemstoneFunRef gemstone_signature = fun_from_ast(scope, node); - - gemstone_signature->llvm_signature = llvm_generate_function_signature(context, gemstone_signature); - gemstone_signature->llvm_function = LLVMAddFunction(module, gemstone_signature->name, gemstone_signature->llvm_signature); - - type_scope_add_fun(scope, gemstone_signature); - - LLVMBasicBlockRef llvm_body = LLVMAppendBasicBlock(gemstone_signature->llvm_function, "body"); - LLVMBuilderRef llvm_builder = LLVMCreateBuilderInContext(context); - LLVMPositionBuilderAtEnd(llvm_builder, llvm_body); - - // create new function local scope - TypeScopeRef local_scope = type_scope_new(); - size_t local_scope_idx = type_scope_append_scope(scope, local_scope); - - for (size_t i = 0; i < node->child_count; i++) { - AST_NODE_PTR child_node = AST_get_node(node, i); - if (child_node->kind == AST_StmtList) { - llvm_build_statement_list(llvm_builder, local_scope, module, child_node); - } - } - - // automatic return at end of function - LLVMBuildRetVoid(llvm_builder); - - // dispose function local scope - type_scope_remove_scope(scope, local_scope_idx); - type_scope_delete(local_scope); - - return SUCCESS; -} diff --git a/src/llvm/function/function.h b/src/llvm/function/function.h deleted file mode 100644 index 833414f..0000000 --- a/src/llvm/function/function.h +++ /dev/null @@ -1,39 +0,0 @@ - -#ifndef LLVM_FUNCTION_H_ -#define LLVM_FUNCTION_H_ - -#include -#include -#include -#include -#include -#include - -/** - * @brief Convert an AST node into a function parameter struct - * - * @param node the node starting a function parameter - * @return GemstoneParam - */ -GemstoneParam param_from_ast(const TypeScopeRef scope, const AST_NODE_PTR node); - -/** - * @brief Convert an AST node into a function - * - * @param node the node starting a function - * @return GemstoneFunRef - */ -GemstoneFunRef fun_from_ast(const TypeScopeRef scope, const AST_NODE_PTR node); - -/** - * @brief Delete the given function - * - * @param fun - */ -void fun_delete(const GemstoneFunRef fun); - -LLVMTypeRef llvm_generate_function_signature(LLVMContextRef context, GemstoneFunRef function); - -BackendError llvm_generate_function_implementation(TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR body); - -#endif // LLVM_FUNCTION_H_ diff --git a/src/llvm/stmt/build.c b/src/llvm/stmt/build.c deleted file mode 100644 index d9234fe..0000000 --- a/src/llvm/stmt/build.c +++ /dev/null @@ -1,89 +0,0 @@ - -#include "llvm/function/function-types.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -BackendError llvm_build_statement(LLVMBuilderRef builder, TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR stmt_node) { - switch (stmt_node->kind) { - case AST_Decl: { - GArray* decls = declaration_from_ast(scope, stmt_node); - - for (size_t i = 0; i < decls->len; i++) { - GemstoneDeclRef decl = ((GemstoneDeclRef*) decls->data)[i]; - - BackendError err = llvm_create_declaration(module, builder, decl, &decl->llvm_value); - - if (err.kind != Success) - break; - - type_scope_add_variable(scope, decl); - } - - // TODO: make sure all decls are freed later - g_array_free(decls, FALSE); - } - break; - case AST_Assign: { - AST_NODE_PTR variable_name = AST_get_node(stmt_node, 0); - AST_NODE_PTR expression = AST_get_node(stmt_node, 1); - - LLVMValueRef yield = NULL; - BackendError err = llvm_build_expression(builder, scope, module, expression, &yield); - - GemstoneDeclRef variable = type_scope_get_variable(scope, variable_name->value); - - LLVMBuildStore(builder, yield, variable->llvm_value); - } - break; - case AST_Stmt: - llvm_build_statement(builder, scope, module, stmt_node); - break; - case AST_Call: { - AST_NODE_PTR name = AST_get_node(stmt_node, 0); - AST_NODE_PTR expr_list = AST_get_node_by_kind(stmt_node, AST_ExprList); - GemstoneFunRef function_signature = type_scope_get_fun_from_name(scope, name->value); - size_t arg_count = function_signature->params->len; - - LLVMValueRef* args = NULL; - BackendError err = llvm_build_expression_list(builder, scope, module, expr_list, &args); - - LLVMBuildCall2(builder, function_signature->llvm_signature, function_signature->llvm_function, args, arg_count, name->value); - } - break; - case AST_Def: - // TODO: implement definition - break; - case AST_While: - // TODO: implement while - break; - case AST_If: - // TODO: implement if - break; - case AST_IfElse: - // TODO: implement else if - break; - case AST_Else: - // TODO: implement else - break; - default: - ERROR("Invalid AST node: %s", AST_node_to_string(stmt_node)); - return new_backend_impl_error(Implementation, stmt_node, "AST is invalid"); - } - - return SUCCESS; -} - -BackendError llvm_build_statement_list(LLVMBuilderRef builder, TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR node) { - for (size_t i = 0; i < node->child_count; i++) { - AST_NODE_PTR stmt_node = AST_get_node(node, i); - - llvm_build_statement(builder, scope, module, stmt_node); - } -} diff --git a/src/llvm/stmt/build.h b/src/llvm/stmt/build.h deleted file mode 100644 index 726813a..0000000 --- a/src/llvm/stmt/build.h +++ /dev/null @@ -1,11 +0,0 @@ - -#ifndef LLVM_STMT_BUILD_H_ -#define LLVM_STMT_BUILD_H_ - -#include -#include -#include - -BackendError llvm_build_statement_list(LLVMBuilderRef builder, TypeScopeRef scope, LLVMModuleRef module, AST_NODE_PTR node); - -#endif // LLVM_STMT_BUILD_H_ diff --git a/src/llvm/types/composite-types.h b/src/llvm/types/composite-types.h deleted file mode 100644 index 49f04c2..0000000 --- a/src/llvm/types/composite-types.h +++ /dev/null @@ -1,35 +0,0 @@ - -#ifndef LLVM_TYPES_COMPOSITE_TYPES_H_ -#define LLVM_TYPES_COMPOSITE_TYPES_H_ - -#define BITS_PER_BYTE 8 - -enum Sign_t { - Signed = 1, - Unsigned = -1 -}; - -enum Scale_t { - ATOM = 1, - HALF = 2, - SINGLE = 4, - DOUBLE = 8, - QUAD = 16, - OCTO = 32 -}; - -enum Primitive_t { - Int, - Float -}; - -typedef struct CompositeType_t { - enum Sign_t sign; - enum Scale_t scale; - enum Primitive_t prim; -} Composite; - -typedef struct CompositeType_t* CompositeRef; - - -#endif // LLVM_TYPES_COMPOSITE_TYPES_H_ \ No newline at end of file diff --git a/src/llvm/types/composite.c b/src/llvm/types/composite.c deleted file mode 100644 index c1cbfed..0000000 --- a/src/llvm/types/composite.c +++ /dev/null @@ -1,163 +0,0 @@ - -#include "llvm/types/composite-types.h" -#include "llvm/types/scope.h" -#include "llvm/types/structs.h" -#include -#include - -LLVMTypeRef llvm_type_from_composite(LLVMContextRef context, const CompositeRef composite) { - DEBUG("converting composite to LLVM type..."); - - LLVMTypeRef type = INVALID_COMPOSITE; - - if (composite->prim == Int) { - DEBUG("generating integer LLVM type..."); - - type = LLVMIntTypeInContext(context, composite->scale * BITS_PER_BYTE); - } else if (composite->prim == Float && composite->sign == Signed) { - DEBUG("generating float LLVM type..."); - - switch (composite->scale) { - case HALF: - type = LLVMHalfTypeInContext(context); - break; - case SINGLE: - type = LLVMDoubleTypeInContext(context); - break; - case DOUBLE: - type = LLVMDoubleTypeInContext(context); - break; - case QUAD: - type = LLVMFP128TypeInContext(context); - break; - default: - ERROR("Floating point of precision: %ld npt supported", composite->scale); - break; - } - } - - return type; -} - -double get_scale_factor(const char* keyword) { - if (strcmp(keyword, "half") == 0 || strcmp(keyword, "short") == 0) { - return 0.5; - } else if (strcmp(keyword, "double") == 0 || strcmp(keyword, "long") == 0) { - return 2.0; - } - - PANIC("invalid scale factor: %s", keyword); -} - -enum Scale_t collapse_scale_list(const AST_NODE_PTR list, double base) { - double sum = base; - - for (size_t i = 0; i < list->child_count; i++) { - AST_NODE_PTR scale = AST_get_node(list, i); - - sum *= get_scale_factor(scale->value); - } - - if (sum >= 1.0 && sum <= 32) { - return (enum Scale_t) sum; - } - - PANIC("invalid combination of scale factors"); -} - -enum Sign_t string_to_sign(const char* keyword) { - if (strcmp(keyword, "signed") == 0) { - return Signed; - } else if (strcmp(keyword, "unsigned") == 0) { - return Unsigned; - } - - PANIC("invalid sign: %s", keyword); -} - -static enum Primitive_t resolve_primitive(const char* typename) { - - if (strcmp(typename, "int") == 0) { - return Int; - } else if (strcmp(typename, "float") == 0) { - return Float; - } - - // TODO: implement lookup of ident type - return Int; -} - -struct CompositeType_t ast_type_to_composite(const TypeScopeRef scope, AST_NODE_PTR type) { - size_t count = type->child_count; - - struct CompositeType_t composite; - composite.prim = Int; - composite.scale = SINGLE; - composite.sign = Signed; - - if (count == 1) { - const char* typename = AST_get_node(type, 0)->value; - GemstoneTypedefRef known_type = type_scope_get_type_from_name(scope, typename); - - if (known_type == NULL) { - // only other type given - composite.prim = resolve_primitive(typename); - } else if (known_type->type->kind == TypeComposite) { - return known_type->type->specs.composite; - } else { - PANIC("not a composite"); - } - - } else if (count == 2) { - // either scale and type - // or sign and type - AST_NODE_PTR first_child = AST_get_node(type, 0); - - const char* typename = AST_get_node(type, 1)->value; - GemstoneTypedefRef known_type = type_scope_get_type_from_name(scope, typename); - - if (known_type == NULL) { - // only other type given - composite.prim = resolve_primitive(typename); - } else if (known_type->type->kind == TypeComposite) { - composite.prim = known_type->type->specs.composite.prim; - composite.scale = known_type->type->specs.composite.scale; - composite.sign = known_type->type->specs.composite.sign; - } else { - PANIC("not a composite"); - } - - switch (first_child->kind) { - case AST_List: - composite.scale = collapse_scale_list(first_child, (double) composite.scale); - break; - case AST_Sign: - composite.sign = string_to_sign(first_child->value); - break; - default: - PANIC("unexpected node kind: %s", AST_node_to_string(first_child)); - } - - } else if (count == 3) { - const char* typename = AST_get_node(type, 2)->value; - GemstoneTypedefRef known_type = type_scope_get_type_from_name(scope, typename); - - if (known_type == NULL) { - // only other type given - composite.prim = resolve_primitive(typename); - } else if (known_type->type->kind == TypeComposite) { - composite.prim = known_type->type->specs.composite.prim; - composite.scale = known_type->type->specs.composite.scale; - composite.sign = known_type->type->specs.composite.sign; - } else { - PANIC("not a composite"); - } - - // sign, scale and type - composite.sign = string_to_sign(AST_get_node(type, 0)->value); - composite.scale = collapse_scale_list(AST_get_node(type, 1), (double) composite.scale); - } - - return composite; -} - diff --git a/src/llvm/types/composite.h b/src/llvm/types/composite.h deleted file mode 100644 index 5289c6d..0000000 --- a/src/llvm/types/composite.h +++ /dev/null @@ -1,18 +0,0 @@ - -#ifndef LLVM_TYPE_H_ -#define LLVM_TYPE_H_ - -#include -#include -#include -#include -#include -#include - -#define INVALID_COMPOSITE NULL - -LLVMTypeRef llvm_type_from_composite(LLVMContextRef context, const CompositeRef composite); - -struct CompositeType_t ast_type_to_composite(const TypeScopeRef scope, AST_NODE_PTR type); - -#endif // LLVM_TYPE_H_ diff --git a/src/llvm/types/scope.c b/src/llvm/types/scope.c deleted file mode 100644 index 15f7634..0000000 --- a/src/llvm/types/scope.c +++ /dev/null @@ -1,119 +0,0 @@ - -#include -#include -#include -#include -#include - -struct TypeScope_t { - GArray *types; - GArray *scopes; - GArray *funcs; - GHashTable *vars; - TypeScopeRef parent; -}; - -TypeScopeRef type_scope_new() { - TypeScopeRef scope = malloc(sizeof(TypeScope)); - - // neither zero termination no initialisazion to zero needed - scope->scopes = g_array_new(FALSE, FALSE, sizeof(TypeScopeRef)); - scope->types = g_array_new(FALSE, FALSE, sizeof(GemstoneTypedefRef)); - scope->funcs = g_array_new(FALSE, FALSE, sizeof(GemstoneFunRef)); - scope->vars = g_hash_table_new(g_str_hash, g_str_equal); - scope->parent = NULL; - - return scope; -} - -void type_scope_append_type(TypeScopeRef scope, GemstoneTypedefRef type) { - g_array_append_val(scope->types, type); -} - -size_t type_scope_append_scope(TypeScopeRef scope, TypeScopeRef child) { - child->parent = scope; - g_array_append_val(scope->scopes, child); - - return scope->scopes->len - 1; -} - -void type_scope_remove_scope(TypeScopeRef scope, size_t index) { - g_array_remove_index(scope->scopes, index); -} - -GemstoneTypedefRef type_scope_get_type(TypeScopeRef scope, size_t index) { - return ((GemstoneTypedefRef *)scope->types->data)[index]; -} - -size_t type_scope_types_len(TypeScopeRef scope) { return scope->types->len; } - -size_t type_scope_scopes_len(TypeScopeRef scope) { return scope->scopes->len; } - -GemstoneTypedefRef type_scope_get_type_from_name(TypeScopeRef scope, - const char *name) { - for (guint i = 0; i < scope->types->len; i++) { - GemstoneTypedefRef typeref = ((GemstoneTypedefRef *)scope->types->data)[i]; - - if (strcmp(typeref->name, name) == 0) { - return typeref; - } - } - - if (scope->parent == NULL) { - return NULL; - } - - return type_scope_get_type_from_name(scope->parent, name); -} - -void type_scope_delete(TypeScopeRef scope) { - - for (guint i = 0; i < scope->scopes->len; i++) { - TypeScopeRef scoperef = ((TypeScopeRef *)scope->scopes->data)[i]; - type_scope_delete(scoperef); - } - - for (guint i = 0; i < scope->types->len; i++) { - // TODO: free gemstone type - } - - g_array_free(scope->scopes, TRUE); - g_array_free(scope->types, TRUE); - g_array_free(scope->funcs, TRUE); - g_hash_table_destroy(scope->vars); - - free(scope); -} - -void type_scope_add_variable(TypeScopeRef scope, GemstoneDeclRef decl) { - g_hash_table_insert(scope->vars, (gpointer)decl->name, decl); -} - -GemstoneDeclRef type_scope_get_variable(TypeScopeRef scope, const char *name) { - if (g_hash_table_contains(scope->vars, name)) { - return g_hash_table_lookup(scope->vars, name); - } - - return NULL; -} - -void type_scope_add_fun(TypeScopeRef scope, GemstoneFunRef function) { - g_array_append_val(scope->funcs, function); -} - -GemstoneFunRef type_scope_get_fun_from_name(TypeScopeRef scope, - const char *name) { - for (guint i = 0; i < scope->funcs->len; i++) { - GemstoneFunRef funref = ((GemstoneFunRef *)scope->funcs->data)[i]; - - if (strcmp(funref->name, name) == 0) { - return funref; - } - } - - if (scope->parent == NULL) { - return NULL; - } - - return type_scope_get_fun_from_name(scope->parent, name); -} diff --git a/src/llvm/types/scope.h b/src/llvm/types/scope.h deleted file mode 100644 index 84e37fd..0000000 --- a/src/llvm/types/scope.h +++ /dev/null @@ -1,132 +0,0 @@ - -#ifndef LLVM_TYPE_SCOPE_H_ -#define LLVM_TYPE_SCOPE_H_ - -#include -#include -#include -#include - -typedef enum StorageQualifier_t { - StorageQualifierLocal, - StorageQualifierStatic, - StorageQualifierGlobal -} StorageQualifier; - -// Varaible declaration -typedef struct GemstoneDecl_t { - const char* name; - StorageQualifier storageQualifier; - GemstoneTypeRef type; - LLVMValueRef llvm_value; -} GemstoneDecl; - -typedef GemstoneDecl* GemstoneDeclRef; - -typedef struct TypeScope_t TypeScope; - -typedef TypeScope* TypeScopeRef; - -/** - * @brief Allocate a new type scope - * - * @return TypeScopeRef - */ -[[nodiscard("heap allocation")]] -TypeScopeRef type_scope_new(); - -/** - * @brief Add a new type to this scope - * - * @param scope - * @param type - */ -[[gnu::nonnull(1)]] -void type_scope_append_type(TypeScopeRef scope, GemstoneTypedefRef type); - -/** - * @brief Add a new child scope to this scope - * - * @param scope - * @param child_scope - */ -[[gnu::nonnull(1), gnu::nonnull(2)]] -size_t type_scope_append_scope(TypeScopeRef scope, TypeScopeRef child_scope); - -/** - * @brief Remove a new child scope to this scope - * - * @param scope - * @param child_scope - */ -[[gnu::nonnull(1)]] -void type_scope_remove_scope(TypeScopeRef scope, size_t index); - -/** - * @brief Get the type at the specified index in this scope level - * - * @param scope - * @param indx - */ -[[gnu::nonnull(1)]] -GemstoneTypedefRef type_scope_get_type(TypeScopeRef scope, size_t indx); - -/** - * @brief Get the number of types in this scope level - * - * @param scope - * @return size_t - */ -[[gnu::nonnull(1)]] -size_t type_scope_types_len(TypeScopeRef scope); - -/** - * @brief Get the number of child scopes - * - * @param scope - * @return size_t - */ -[[gnu::nonnull(1)]] -size_t type_scope_scopes_len(TypeScopeRef scope); - -/** - * @brief Return a type inside this scope which matches the given name. - * @attention Returns NULL if no type by this name is found. - * - * @param name - * @return GemstoneTypedefRef - */ -[[gnu::nonnull(1)]] -GemstoneTypedefRef type_scope_get_type_from_name(TypeScopeRef scope, const char* name); - -/** - * @brief Delete the scope. Deallocates all child scopes - * - * @param scope - */ -[[gnu::nonnull(1)]] -void type_scope_delete(TypeScopeRef scope); - -/** - * @brief Add a function ot the type scope - * - * @param scope - * @param function - */ -void type_scope_add_fun(TypeScopeRef scope, GemstoneFunRef function); - -/** - * @brief Attempts to find a function by its name in the current scope - * - * @param scope - * @param name - * @return GemstoneFunRef - */ -[[gnu::nonnull(1), gnu::nonnull(2)]] -GemstoneFunRef type_scope_get_fun_from_name(TypeScopeRef scope, const char* name); - -void type_scope_add_variable(TypeScopeRef scope, GemstoneDeclRef decl); - -GemstoneDeclRef type_scope_get_variable(TypeScopeRef scope, const char *name); - -#endif // LLVM_TYPE_SCOPE_H_ diff --git a/src/llvm/types/structs.h b/src/llvm/types/structs.h deleted file mode 100644 index cca447e..0000000 --- a/src/llvm/types/structs.h +++ /dev/null @@ -1,36 +0,0 @@ - -#ifndef LLVM_TYPE_STRUCTS_H_ -#define LLVM_TYPE_STRUCTS_H_ - -#include - -enum GemstoneTypeKind_t { - TypeComposite, - TypeReference, - TypeBox -}; - -struct GemstoneType_t; - -typedef struct GemstoneRefType_t { - struct GemstoneType_t* type; -} GemstoneRefType; - -typedef struct GemstoneType_t { - enum GemstoneTypeKind_t kind; - union GemstoneTypeSpecs_t { - Composite composite; - GemstoneRefType reference; - } specs; -} GemstoneType; - -typedef GemstoneType* GemstoneTypeRef; - -typedef struct GemstoneTypedef_t { - const char* name; - GemstoneTypeRef type; -} GemstoneTypedef; - -typedef GemstoneTypedef* GemstoneTypedefRef; - -#endif // LLVM_TYPE_STRUCTS_H_ diff --git a/src/llvm/types/type.c b/src/llvm/types/type.c deleted file mode 100644 index 5bcfd97..0000000 --- a/src/llvm/types/type.c +++ /dev/null @@ -1,120 +0,0 @@ - -#include "llvm/types/composite-types.h" -#include "llvm/types/structs.h" -#include -#include -#include -#include -#include -#include -#include - -GemstoneTypeRef get_type_from_ast(const TypeScopeRef scope, const AST_NODE_PTR type_node) { - if (type_node->kind != AST_Type) { - PANIC("Node must be of type AST_Type: %s", AST_node_to_string(type_node)); - } - - GemstoneTypeRef type = malloc(sizeof(GemstoneType)); - - if (type_node->child_count > 1) { - // must be composite - type->kind = TypeComposite; - type->specs.composite = ast_type_to_composite(scope, type_node); - } else { - // either custom type or box - GemstoneTypedefRef resolved_type = type_scope_get_type_from_name(scope, AST_get_node(type_node, 0)->value); - - if (resolved_type == NULL) { - type->kind = TypeComposite; - type->specs.composite = ast_type_to_composite(scope, type_node); - } else { - free(type); - type = resolved_type->type; - } - } - - return type; -} - -GemstoneTypedefRef new_typedefref(GemstoneTypeRef type, const char* name) { - GemstoneTypedefRef typedefref = malloc(sizeof(GemstoneTypedef)); - - typedefref->name = name; - typedefref->type = type; - - return typedefref; -} - -void delete_type(GemstoneTypeRef typeref) { - switch(typeref->kind) { - case TypeReference: - delete_type(typeref->specs.reference.type); - break; - case TypeComposite: - break; - case TypeBox: - PANIC("NOT IMPLEMENTED"); - break; - } - - free(typeref); -} - -void delete_typedefref(GemstoneTypedefRef ref) { - delete_type(ref->type); -} - -GemstoneTypedefRef get_type_def_from_ast(const TypeScopeRef scope, const AST_NODE_PTR typdef) { - if (typdef->kind != AST_Typedef) { - PANIC("node must be of type AST_Typedef"); - } - - GemstoneTypeRef type = get_type_from_ast(scope, AST_get_node(typdef, 0)); - const char* name = AST_get_node(typdef, 1)->value; - - return new_typedefref(type, name); -} - -LLVMTypeRef llvm_type_from_gemstone_type(LLVMContextRef context, GemstoneTypeRef type) { - LLVMTypeRef llvmTypeRef = NULL; - - switch (type->kind) { - case TypeComposite: - llvmTypeRef = llvm_type_from_composite(context, &type->specs.composite); - break; - default: - PANIC("NOT IMPLEMENTED"); - } - - return llvmTypeRef; -} - -LLVMValueRef llvm_default_value_of_composite(LLVMContextRef context, CompositeRef composite) { - LLVMTypeRef type = llvm_type_from_composite(context, composite); - LLVMValueRef value; - - if (composite->prim == Int) { - value = LLVMConstInt(type, 0, 0); - } else if (composite->prim == Float) { - value = LLVMConstReal(type, 0.0); - } else { - PANIC("Invalid composite type: %d", composite->prim); - } - - return value; -} - -LLVMValueRef llvm_default_value_of_type(LLVMContextRef context, GemstoneTypeRef ref) { - LLVMValueRef value = NULL; - - switch (ref->kind) { - case TypeComposite: - value = llvm_default_value_of_composite(context, &ref->specs.composite); - break; - default: - PANIC("type not implemented"); - break; - } - - return value; -} diff --git a/src/llvm/types/type.h b/src/llvm/types/type.h deleted file mode 100644 index 3b55050..0000000 --- a/src/llvm/types/type.h +++ /dev/null @@ -1,54 +0,0 @@ - -#ifndef GEMSTONE_TYPE_H_ -#define GEMSTONE_TYPE_H_ - -#include -#include -#include -#include -#include - -/** - * @brief Convert a type declaration into a concrete type. - * - * @param type A type declaration (either identifier or composite) - * @return GemstoneType - */ -GemstoneTypeRef get_type_from_ast(const TypeScopeRef scope, const AST_NODE_PTR type); - -/** - * @brief Convert the type definition AST into a typedef reference - * - * @param typdef - * @return GemstoneTypedefRef - */ -GemstoneTypedefRef get_type_def_from_ast(const TypeScopeRef scope, const AST_NODE_PTR typdef); - -/** - * @brief Create an new typedefine reference - * - * @param type - * @param name - * @return GemstoneTypedefRef - */ -GemstoneTypedefRef new_typedefref(GemstoneTypeRef type, const char* name); - -/** - * @brief Create the LLVM function signature - * - * @param context - * @param type - * @return LLVMTypeRef - */ -LLVMTypeRef llvm_type_from_gemstone_type(LLVMContextRef context, GemstoneTypeRef type); - -/** - * @brief Free the type definition reference and its underlying type - * - * @param ref - */ -void delete_typedefref(GemstoneTypedefRef ref); - -LLVMValueRef llvm_default_value_of_type(LLVMContextRef context, GemstoneTypeRef ref); - -#endif // GEMSTONE_TYPE_H_ From dcd309c7b41115c8044576ffaabae027b8146238 Mon Sep 17 00:00:00 2001 From: servostar Date: Sun, 26 May 2024 17:11:43 +0200 Subject: [PATCH 023/124] added module type --- src/set/types.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/set/types.h b/src/set/types.h index c58dd67..879c888 100644 --- a/src/set/types.h +++ b/src/set/types.h @@ -469,4 +469,17 @@ typedef struct Statement_t { } impl; } Statement; +// .------------------------------------------------. +// | Module | +// '------------------------------------------------' + +typedef struct Module_t { + GHashTable* boxes; + GHashTable* types; + GHashTable* functions; + GHashTable* variables; + // to be resolved after the module has been parsed completely + GArray* imports; +} Module; + #endif // SET_TYPES_H_ From d0cd74c697b9016b8c8f14b73cb1a2c9015b08fe Mon Sep 17 00:00:00 2001 From: servostar Date: Sun, 26 May 2024 17:23:08 +0200 Subject: [PATCH 024/124] modified codegen backend to use set module --- src/codegen/backend.c | 3 ++- src/codegen/backend.h | 5 +++-- src/llvm/backend.c | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/codegen/backend.c b/src/codegen/backend.c index d2eccac..8e6f5ca 100644 --- a/src/codegen/backend.c +++ b/src/codegen/backend.c @@ -1,4 +1,5 @@ +#include "set/types.h" #include #include @@ -67,7 +68,7 @@ BackendError set_backend(const codegen_init init_func, const codegen_deinit dein return new_backend_error(Success); } -BackendError generate_code(const AST_NODE_PTR root, void** output) { +BackendError generate_code(const Module* root, void** output) { DEBUG("generating code with backend: %s", CodegenBackend.name); if (CodegenBackend.codegen_func == NULL) { diff --git a/src/codegen/backend.h b/src/codegen/backend.h index c00859b..ad3613d 100644 --- a/src/codegen/backend.h +++ b/src/codegen/backend.h @@ -2,6 +2,7 @@ #ifndef CODEGN_BACKEND_H_ #define CODEGN_BACKEND_H_ +#include #include typedef struct BackendImplError_t { @@ -29,7 +30,7 @@ typedef struct BackendError_t { * @brief Function called by the compiler backend to generate an intermediate format * from AST. Returns a custom container for its intermediate language. */ -typedef BackendError (*codegen)(const AST_NODE_PTR, void**); +typedef BackendError (*codegen)(const Module*, void**); /** * @brief Initialize the code generation backend. @@ -77,7 +78,7 @@ BackendError deinit_backend(void); * @return BackendError */ [[nodiscard]] -BackendError generate_code(const AST_NODE_PTR root, void** code); +BackendError generate_code(const Module* root, void** code); /** * @brief Create a new backend error diff --git a/src/llvm/backend.c b/src/llvm/backend.c index 30a248d..5bf2b21 100644 --- a/src/llvm/backend.c +++ b/src/llvm/backend.c @@ -10,7 +10,7 @@ typedef enum LLVMBackendError_t { UnresolvedImport } LLVMBackendError; -static BackendError llvm_backend_codegen(const AST_NODE_PTR module_node, void**) { +static BackendError llvm_backend_codegen(const Module* unit, void**) { // we start with a LLVM module LLVMContextRef context = LLVMContextCreate(); LLVMModuleRef module = LLVMModuleCreateWithNameInContext("gemstone application", context); From 78e6310b05a9da54bd9a939137af686c5f456086 Mon Sep 17 00:00:00 2001 From: servostar Date: Sun, 26 May 2024 17:30:53 +0200 Subject: [PATCH 025/124] moved module generation to backend parser --- src/llvm/backend.c | 16 +++------------- src/llvm/parser.c | 17 +++++++++++++++++ src/llvm/parser.h | 12 ++++++++++++ 3 files changed, 32 insertions(+), 13 deletions(-) create mode 100644 src/llvm/parser.c create mode 100644 src/llvm/parser.h diff --git a/src/llvm/backend.c b/src/llvm/backend.c index 5bf2b21..5abcb95 100644 --- a/src/llvm/backend.c +++ b/src/llvm/backend.c @@ -3,24 +3,14 @@ #include #include #include -#include -#include +#include typedef enum LLVMBackendError_t { UnresolvedImport } LLVMBackendError; -static BackendError llvm_backend_codegen(const Module* unit, void**) { - // we start with a LLVM module - LLVMContextRef context = LLVMContextCreate(); - LLVMModuleRef module = LLVMModuleCreateWithNameInContext("gemstone application", context); - - BackendError err; - - LLVMDisposeModule(module); - LLVMContextDispose(context); - - return new_backend_error(Success); +static BackendError llvm_backend_codegen(const Module* unit, void** output) { + return parse_module(unit, output); } static BackendError llvm_backend_codegen_init(void) { diff --git a/src/llvm/parser.c b/src/llvm/parser.c new file mode 100644 index 0000000..7a6fd55 --- /dev/null +++ b/src/llvm/parser.c @@ -0,0 +1,17 @@ + +#include + +BackendError parse_module(const Module* module, void**) { + LLVMBackendCompileUnit* unit = malloc(sizeof(LLVMBackendCompileUnit)); + + // we start with a LLVM module + unit->context = LLVMContextCreate(); + unit->module = LLVMModuleCreateWithNameInContext("gemstone application", unit->context); + + + + LLVMDisposeModule(unit->module); + LLVMContextDispose(unit->context); + + return new_backend_error(Success); +} diff --git a/src/llvm/parser.h b/src/llvm/parser.h new file mode 100644 index 0000000..ceb908c --- /dev/null +++ b/src/llvm/parser.h @@ -0,0 +1,12 @@ + +#include "set/types.h" +#include +#include +#include + +typedef struct LLVMBackendCompileUnit_t { + LLVMContextRef context; + LLVMModuleRef module; +} LLVMBackendCompileUnit; + +BackendError parse_module(const Module* module, void**); From e3f8e4b461f1ffd5a019db0659190442d3b57253 Mon Sep 17 00:00:00 2001 From: servostar Date: Sun, 26 May 2024 19:03:23 +0200 Subject: [PATCH 026/124] added .clang-format --- .clang-format | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..1076ca2 --- /dev/null +++ b/.clang-format @@ -0,0 +1,3 @@ +BasedOnStyle: Google +IndentWidth: 4 +PointerAlignment: Left From b91c277ac4c18066b823d18ee3d7e1873b601e44 Mon Sep 17 00:00:00 2001 From: servostar Date: Sun, 26 May 2024 22:51:49 +0200 Subject: [PATCH 027/124] added global variables --- src/llvm/parser.c | 61 +++++++- src/llvm/parser.h | 30 +++- src/llvm/types.c | 324 +++++++++++++++++++++++++++++++++++++++++++ src/llvm/types.h | 21 +++ src/llvm/variables.c | 104 ++++++++++++++ src/llvm/variables.h | 15 ++ 6 files changed, 551 insertions(+), 4 deletions(-) create mode 100644 src/llvm/types.c create mode 100644 src/llvm/types.h create mode 100644 src/llvm/variables.c create mode 100644 src/llvm/variables.h diff --git a/src/llvm/parser.c b/src/llvm/parser.c index 7a6fd55..b115650 100644 --- a/src/llvm/parser.c +++ b/src/llvm/parser.c @@ -1,17 +1,72 @@ +#include +#include +#include #include +#include +#include +#include +#include BackendError parse_module(const Module* module, void**) { LLVMBackendCompileUnit* unit = malloc(sizeof(LLVMBackendCompileUnit)); // we start with a LLVM module unit->context = LLVMContextCreate(); - unit->module = LLVMModuleCreateWithNameInContext("gemstone application", unit->context); + unit->module = LLVMModuleCreateWithNameInContext("gemstone application", + unit->context); - + LLVMGlobalScope* global_scope = new_global_scope(); + + BackendError err = new_backend_error(Success); + + err = impl_types(unit, global_scope, module->types); + // NOTE: functions of boxes are not stored in the box itself, + // thus for a box we only implement the type + err = impl_types(unit, global_scope, module->boxes); + + err = impl_global_variables(unit, global_scope, module->variables); + + delete_global_scope(global_scope); LLVMDisposeModule(unit->module); LLVMContextDispose(unit->context); - return new_backend_error(Success); + free(unit); + + return err; +} + +LLVMGlobalScope* new_global_scope() { + LLVMGlobalScope* scope = malloc(sizeof(LLVMGlobalScope)); + + scope->functions = g_hash_table_new(g_str_hash, g_str_equal); + scope->variables = g_hash_table_new(g_str_hash, g_str_equal); + scope->types = g_hash_table_new(g_str_hash, g_str_equal); + + return scope; +} + +LLVMLocalScope* new_local_scope(LLVMGlobalScope* global_scope, + LLVMLocalScope* parent_scope) { + LLVMLocalScope* scope = malloc(sizeof(LLVMLocalScope)); + + scope->variables = g_hash_table_new(g_str_hash, g_str_equal); + scope->params = g_hash_table_new(g_str_hash, g_str_equal); + scope->global_scope = global_scope; + scope->parent_scope = parent_scope; + + return scope; +} + +void delete_local_scope(LLVMLocalScope* scope) { + g_hash_table_unref(scope->variables); + free(scope); +} + +void delete_global_scope(LLVMGlobalScope* scope) { + g_hash_table_unref(scope->functions); + g_hash_table_unref(scope->types); + g_hash_table_unref(scope->variables); + free(scope); } diff --git a/src/llvm/parser.h b/src/llvm/parser.h index ceb908c..9a51e60 100644 --- a/src/llvm/parser.h +++ b/src/llvm/parser.h @@ -1,5 +1,8 @@ -#include "set/types.h" +#ifndef LLVM_BACKEND_PARSE_H_ +#define LLVM_BACKEND_PARSE_H_ + +#include #include #include #include @@ -9,4 +12,29 @@ typedef struct LLVMBackendCompileUnit_t { LLVMModuleRef module; } LLVMBackendCompileUnit; +typedef struct LLVMGlobalScope_t { + GHashTable* types; + GHashTable* variables; + GHashTable* functions; +} LLVMGlobalScope; + +LLVMGlobalScope* new_global_scope(); + +void delete_global_scope(LLVMGlobalScope* scope); + +typedef struct LLVMLocalScope_t LLVMLocalScope; + +typedef struct LLVMLocalScope_t { + LLVMGlobalScope* global_scope; + LLVMLocalScope* parent_scope; + GHashTable* params; + GHashTable* variables; +} LLVMLocalScope; + +LLVMLocalScope* new_local_scope(LLVMGlobalScope* global_scope, LLVMLocalScope* parent_scope); + +void delete_local_scope(LLVMLocalScope* scope); + BackendError parse_module(const Module* module, void**); + +#endif // LLVM_BACKEND_PARSE_H_ diff --git a/src/llvm/types.c b/src/llvm/types.c new file mode 100644 index 0000000..87d87ca --- /dev/null +++ b/src/llvm/types.c @@ -0,0 +1,324 @@ +#include +#include +#include +#include +#include +#include + +BackendError impl_primtive_type(LLVMBackendCompileUnit* unit, + PrimitiveType primtive, + LLVMTypeRef* llvm_type) { + switch (primtive) { + case Int: + *llvm_type = LLVMInt32TypeInContext(unit->context); + break; + case Float: + *llvm_type = LLVMFloatTypeInContext(unit->context); + break; + default: + break; + } + + return SUCCESS; +} + +BackendError impl_integral_type(LLVMBackendCompileUnit* unit, Scale scale, + LLVMTypeRef* llvm_type) { + LLVMTypeRef integral_type = + LLVMIntTypeInContext(unit->context, (int)(4 * scale) * 8); + + *llvm_type = integral_type; + + return SUCCESS; +} + +BackendError impl_float_type(LLVMBackendCompileUnit* unit, Scale scale, + LLVMTypeRef* llvm_type) { + LLVMTypeRef float_type = NULL; + + switch ((int)(scale * 4)) { + case 2: + float_type = LLVMHalfTypeInContext(unit->context); + break; + case 4: + float_type = LLVMFloatTypeInContext(unit->context); + break; + case 8: + float_type = LLVMDoubleTypeInContext(unit->context); + break; + case 16: + float_type = LLVMFP128TypeInContext(unit->context); + break; + default: + break; + } + + if (float_type != NULL) { + *llvm_type = float_type; + return SUCCESS; + } + + return new_backend_impl_error(Implementation, NULL, + "floating point with scale not supported"); +} + +BackendError impl_composite_type(LLVMBackendCompileUnit* unit, + CompositeType* composite, + LLVMTypeRef* llvm_type) { + BackendError err = SUCCESS; + + switch (composite->primitive) { + case Int: + err = impl_integral_type(unit, composite->scale, llvm_type); + break; + case Float: + if (composite->sign == Signed) { + err = impl_float_type(unit, composite->scale, llvm_type); + } else { + err = new_backend_impl_error( + Implementation, composite->nodePtr, + "unsigned floating-point not supported"); + } + break; + default: + break; + } + + return err; +} + +BackendError impl_reference_type(LLVMBackendCompileUnit* unit, + LLVMGlobalScope* scope, + ReferenceType reference, + LLVMTypeRef* llvm_type); + +BackendError impl_box_type(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, + BoxType* reference, LLVMTypeRef* llvm_type); + +BackendError get_type_impl(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, + Type* gemstone_type, LLVMTypeRef* llvm_type) { + BackendError err = + new_backend_impl_error(Implementation, gemstone_type->nodePtr, + "No type implementation covers type"); + + switch (gemstone_type->kind) { + case TypeKindPrimitive: + err = impl_primtive_type(unit, gemstone_type->impl.primitive, + llvm_type); + break; + case TypeKindComposite: + err = impl_composite_type(unit, &gemstone_type->impl.composite, + llvm_type); + break; + case TypeKindReference: + err = impl_reference_type(unit, scope, + gemstone_type->impl.reference, llvm_type); + break; + case TypeKindBox: + err = + impl_box_type(unit, scope, &gemstone_type->impl.box, llvm_type); + break; + } + + return err; +} + +BackendError impl_box_type(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, + BoxType* box, LLVMTypeRef* llvm_type) { + GHashTableIter iterator; + g_hash_table_iter_init(&iterator, box->member); + + gpointer key = NULL; + gpointer val = NULL; + + BackendError err; + + GArray* members = g_array_new(FALSE, FALSE, sizeof(LLVMTypeRef)); + + while (g_hash_table_iter_next(&iterator, &key, &val) != FALSE) { + Type* member_type = ((BoxMember*) val)->type; + + LLVMTypeRef llvm_type = NULL; + err = get_type_impl(unit, scope, member_type, &llvm_type); + + if (err.kind != Success) { + break; + } + + g_array_append_val(members, llvm_type); + } + + if (err.kind == Success) { + *llvm_type = + LLVMStructType((LLVMTypeRef*)members->data, members->len, 0); + } + + g_array_free(members, FALSE); + + return err; +} + +BackendError impl_reference_type(LLVMBackendCompileUnit* unit, + LLVMGlobalScope* scope, + ReferenceType reference, + LLVMTypeRef* llvm_type) { + BackendError err = SUCCESS; + LLVMTypeRef type = NULL; + err = get_type_impl(unit, scope, reference, &type); + + if (err.kind == Success) { + *llvm_type = LLVMPointerType(type, 0); + } + + return err; +} + +BackendError impl_type(LLVMBackendCompileUnit* unit, Type* gemstone_type, + const char* alias, LLVMGlobalScope* scope) { + BackendError err = SUCCESS; + + LLVMTypeRef llvm_type = NULL; + err = get_type_impl(unit, scope, gemstone_type, &llvm_type); + + if (err.kind == Success) { + g_hash_table_insert(scope->types, (gpointer)alias, llvm_type); + } + + return err; +} + +BackendError impl_types(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, + GHashTable* types) { + GHashTableIter iterator; + g_hash_table_iter_init(&iterator, types); + + gpointer key = NULL; + gpointer val = NULL; + + BackendError err; + + while (g_hash_table_iter_next(&iterator, &key, &val) != FALSE) { + err = impl_type(unit, (Type*)val, (const char*)key, scope); + + if (err.kind != Success) { + break; + } + } + + return err; +} + +BackendError get_primitive_default_value(PrimitiveType type, + LLVMTypeRef llvm_type, + LLVMValueRef* llvm_value) { + switch (type) { + case Int: + *llvm_value = LLVMConstIntOfString(llvm_type, "0", 10); + break; + case Float: + *llvm_value = LLVMConstRealOfString(llvm_type, "0"); + break; + default: + return new_backend_impl_error(Implementation, NULL, + "unknown primitive type"); + } + + return SUCCESS; +} + +BackendError get_composite_default_value(CompositeType* composite, + LLVMTypeRef llvm_type, + LLVMValueRef* llvm_value) { + BackendError err = SUCCESS; + + switch (composite->primitive) { + case Int: + err = get_primitive_default_value(Int, llvm_type, llvm_value); + break; + case Float: + if (composite->sign == Signed) { + err = get_primitive_default_value(Float, llvm_type, llvm_value); + } else { + err = new_backend_impl_error( + Implementation, composite->nodePtr, + "unsigned floating-point not supported"); + } + break; + default: + break; + } + + return err; +} + +BackendError get_reference_default_value(LLVMTypeRef llvm_type, + LLVMValueRef* llvm_value) { + *llvm_value = LLVMConstPointerNull(llvm_type); + + return SUCCESS; +} + +BackendError get_box_default_value(LLVMBackendCompileUnit* unit, + LLVMGlobalScope* scope, BoxType* type, + LLVMValueRef* llvm_value) { + GHashTableIter iterator; + g_hash_table_iter_init(&iterator, type->member); + + gpointer key = NULL; + gpointer val = NULL; + + BackendError err; + + GArray* constants = g_array_new(FALSE, FALSE, sizeof(LLVMValueRef)); + + while (g_hash_table_iter_next(&iterator, &key, &val) != FALSE) { + Type* member_type = ((BoxMember*)val)->type; + + LLVMValueRef constant = NULL; + err = get_type_default_value(unit, scope, member_type, &constant); + + if (err.kind != Success) { + break; + } + } + + *llvm_value = LLVMConstStructInContext( + unit->context, (LLVMValueRef*) constants->data, constants->len, 0); + + g_array_free(constants, FALSE); + + return err; +} + +BackendError get_type_default_value(LLVMBackendCompileUnit* unit, + LLVMGlobalScope* scope, Type* gemstone_type, + LLVMValueRef* llvm_value) { + BackendError err = new_backend_impl_error( + Implementation, gemstone_type->nodePtr, "No default value for type"); + + LLVMTypeRef llvm_type = NULL; + get_type_impl(unit, scope, gemstone_type, &llvm_type); + if (err.kind != Success) { + return err; + } + + switch (gemstone_type->kind) { + case TypeKindPrimitive: + err = get_primitive_default_value(gemstone_type->impl.primitive, + llvm_type, llvm_value); + break; + case TypeKindComposite: + err = get_composite_default_value(&gemstone_type->impl.composite, + llvm_type, llvm_value); + break; + case TypeKindReference: + err = get_reference_default_value(llvm_type, llvm_value); + break; + case TypeKindBox: + err = get_box_default_value(unit, scope, &gemstone_type->impl.box, + llvm_value); + break; + } + + return err; +} diff --git a/src/llvm/types.h b/src/llvm/types.h new file mode 100644 index 0000000..c8a873b --- /dev/null +++ b/src/llvm/types.h @@ -0,0 +1,21 @@ + +#ifndef LLVM_BACKEND_TYPES_H_ +#define LLVM_BACKEND_TYPES_H_ + +#include +#include +#include +#include +#include + +BackendError impl_types(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, + GHashTable* types); + +BackendError get_type_impl(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, + Type* gemstone_type, LLVMTypeRef* llvm_type); + +BackendError get_type_default_value(LLVMBackendCompileUnit* unit, + LLVMGlobalScope* scope, Type* gemstone_type, + LLVMValueRef* llvm_value); + +#endif // LLVM_BACKEND_TYPES_H_ diff --git a/src/llvm/variables.c b/src/llvm/variables.c new file mode 100644 index 0000000..51d2170 --- /dev/null +++ b/src/llvm/variables.c @@ -0,0 +1,104 @@ + +#include +#include +#include +#include +#include +#include + +BackendError impl_global_declaration(LLVMBackendCompileUnit* unit, + LLVMGlobalScope* scope, + VariableDeclaration* decl, + const char* name) { + BackendError err = SUCCESS; + LLVMTypeRef llvm_type = NULL; + err = get_type_impl(unit, scope, &decl->type, &llvm_type); + + if (err.kind != Success) { + return err; + } + + LLVMValueRef global = LLVMAddGlobal(unit->module, llvm_type, name); + + LLVMValueRef initial_value = NULL; + err = get_type_default_value(unit, scope, &decl->type, &initial_value); + + if (err.kind == Success) { + LLVMSetInitializer(global, initial_value); + g_hash_table_insert(scope->variables, (gpointer)name, global); + } + + return err; +} + +BackendError impl_global_definiton(LLVMBackendCompileUnit* unit, + LLVMGlobalScope* scope, + VariableDefiniton* def, + const char* name) { + BackendError err = SUCCESS; + LLVMTypeRef llvm_type = NULL; + err = get_type_impl(unit, scope, &def->declaration.type, &llvm_type); + + if (err.kind != Success) { + return err; + } + + LLVMValueRef global = LLVMAddGlobal(unit->module, llvm_type, name); + + // FIXME: resolve initializer expression! + LLVMValueRef initial_value = NULL; + err = get_type_default_value(unit, scope, &def->declaration.type, &initial_value); + + if (err.kind == Success) { + LLVMSetInitializer(global, initial_value); + g_hash_table_insert(scope->variables, (gpointer)name, global); + } + + return err; +} + +BackendError impl_global_variable(LLVMBackendCompileUnit* unit, + Variable* gemstone_var, const char* alias, + LLVMGlobalScope* scope) { + BackendError err = SUCCESS; + + switch (gemstone_var->kind) { + case VariableKindDeclaration: + err = impl_global_declaration( + unit, scope, &gemstone_var->impl.declaration, alias); + break; + case VariableKindDefinition: + err = impl_global_definiton( + unit, scope, &gemstone_var->impl.definiton, alias); + break; + case VariableKindBoxMember: + err = new_backend_impl_error(Implementation, gemstone_var->nodePtr, + "member variable cannot be "); + break; + } + + return err; +} + +BackendError impl_global_variables(LLVMBackendCompileUnit* unit, + LLVMGlobalScope* scope, + GHashTable* variables) { + GHashTableIter iterator; + g_hash_table_iter_init(&iterator, variables); + + gpointer key = NULL; + gpointer val = NULL; + + BackendError err; + + while (g_hash_table_iter_next(&iterator, &key, &val) != FALSE) { + err = + impl_global_variable(unit, (Variable*)val, (const char*)key, scope); + + if (err.kind != Success) { + break; + } + } + + return err; +} diff --git a/src/llvm/variables.h b/src/llvm/variables.h new file mode 100644 index 0000000..346e856 --- /dev/null +++ b/src/llvm/variables.h @@ -0,0 +1,15 @@ + +#ifndef LLVM_BACKEND_VARIABLES_H_ +#define LLVM_BACKEND_VARIABLES_H_ + +#include +#include +#include +#include +#include + +BackendError impl_global_variables(LLVMBackendCompileUnit* unit, + LLVMGlobalScope* scope, + GHashTable* variables); + +#endif // LLVM_BACKEND_VARIABLES_H_ From f16e2cfbaad01dce1aed2c4432aaf02909733ecc Mon Sep 17 00:00:00 2001 From: servostar Date: Sun, 26 May 2024 22:52:48 +0200 Subject: [PATCH 028/124] fixed: mismatched pointer type --- src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.c b/src/main.c index e9c484b..2b4b57d 100644 --- a/src/main.c +++ b/src/main.c @@ -63,7 +63,7 @@ void run_backend_codegen() { } void* code = NULL; - err = generate_code(root, &code); + err = generate_code(NULL, &code); if (err.kind != Success) { return; } From fd1cca119f24a5aa8f6487835225852ec8b7cbbc Mon Sep 17 00:00:00 2001 From: servostar Date: Mon, 27 May 2024 01:24:35 +0200 Subject: [PATCH 029/124] removed llvm test --- tests/CMakeLists.txt | 3 +- tests/llvm/CMakeLists.txt | 6 -- tests/llvm/params/CMakeLists.txt | 51 ----------- tests/llvm/params/params.c | 114 ------------------------ tests/llvm/params/test.txt | 4 - tests/llvm/typedef/CMakeLists.txt | 51 ----------- tests/llvm/typedef/test.txt | 21 ----- tests/llvm/typedef/typedef.c | 143 ------------------------------ 8 files changed, 1 insertion(+), 392 deletions(-) delete mode 100644 tests/llvm/CMakeLists.txt delete mode 100644 tests/llvm/params/CMakeLists.txt delete mode 100644 tests/llvm/params/params.c delete mode 100644 tests/llvm/params/test.txt delete mode 100644 tests/llvm/typedef/CMakeLists.txt delete mode 100644 tests/llvm/typedef/test.txt delete mode 100644 tests/llvm/typedef/typedef.c diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 57c4c80..1228d2b 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -9,5 +9,4 @@ set(CTEST_BINARY_DIRECTORY ${PROJECT_BINARY_DIR}/tests) add_subdirectory(logging) add_subdirectory(input_file) add_subdirectory(ast) -add_subdirectory(glib) -add_subdirectory(llvm) \ No newline at end of file +add_subdirectory(glib) \ No newline at end of file diff --git a/tests/llvm/CMakeLists.txt b/tests/llvm/CMakeLists.txt deleted file mode 100644 index fe495c7..0000000 --- a/tests/llvm/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -include(CTest) - -# Provide test to run here or include another CMakeLists.txt - -add_subdirectory(typedef) -add_subdirectory(params) diff --git a/tests/llvm/params/CMakeLists.txt b/tests/llvm/params/CMakeLists.txt deleted file mode 100644 index 712438d..0000000 --- a/tests/llvm/params/CMakeLists.txt +++ /dev/null @@ -1,51 +0,0 @@ -include(CTest) - -# ------------------------------------------------ # -# Setup Glib 2.0 # -# ------------------------------------------------ # - -find_package(PkgConfig REQUIRED) -pkg_search_module(GLIB REQUIRED IMPORTED_TARGET glib-2.0) - -# ------------------------------------------------ # -# LLVM backend # -# ------------------------------------------------ # - -# Fetch LLVM link configuration -execute_process(COMMAND llvm-config --libs all - OUTPUT_VARIABLE LLVM_LIBS) -# Strip whitespace from output -string(STRIP "${LLVM_LIBS}" LLVM_LIBS) -# Link all targets to LLVM -link_libraries(${LLVM_LIBS}) - -# ------------------------------------------------ # -# Source # -# ------------------------------------------------ # - -include_directories(${PROJECT_SOURCE_DIR}/src) -include_directories(PRIVATE ${GLIB_INCLUDE_DIRS}) - -file(GLOB_RECURSE SOURCE_FILES ${PROJECT_SOURCE_DIR}/src/*.c) -list(REMOVE_ITEM SOURCE_FILES ${PROJECT_SOURCE_DIR}/src/main.c) - -set(LEX_GENERATED_SOURCE_FILE ${PROJECT_SOURCE_DIR}/src/lex/lexer.ll.c) -set(YACC_GENERATED_SOURCE_FILE ${PROJECT_SOURCE_DIR}/src/yacc/parser.tab.c) - -# ------------------------------------------------------- # -# CTEST 1 -# test parameter declarations - -add_executable(params - ${SOURCE_FILES} - ${LEX_GENERATED_SOURCE_FILE} - ${YACC_GENERATED_SOURCE_FILE} - params.c) -set_target_properties(params - PROPERTIES - OUTPUT_NAME "params" - RUNTIME_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/tests/llvm) -target_link_libraries(params PkgConfig::GLIB) -add_test(NAME params - WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests/llvm/params - COMMAND ${GEMSTONE_BINARY_DIR}/tests/llvm/params test.txt) diff --git a/tests/llvm/params/params.c b/tests/llvm/params/params.c deleted file mode 100644 index 36a2ea4..0000000 --- a/tests/llvm/params/params.c +++ /dev/null @@ -1,114 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern FILE *yyin; -AST_NODE_PTR root; - -/** - * @brief Log a debug message to inform about beginning exit procedures - * - */ -void notify_exit(void) { DEBUG("Exiting gemstone..."); } - -/** - * @brief Closes File after compiling. - * - */ - -void close_file(void) { - if (NULL != yyin) { - fclose(yyin); - } -} - -/** - * @brief Run compiler setup here - * - */ -void setup(void) { - // setup preample - - log_init(); - DEBUG("starting gemstone..."); - -#if LOG_LEVEL <= LOG_LEVEL_DEBUG - atexit(¬ify_exit); -#endif - - // actual setup - AST_init(); - - col_init(); - - lex_init(); - - DEBUG("finished starting up gemstone..."); -} - -void run_backend_codegen() { - llvm_backend_init(); - - BackendError err; - err = init_backend(); - if (err.kind != Success) { - return; - } - - void* code = NULL; - err = generate_code(root, &code); - if (err.kind != Success) { - return; - } - - err = deinit_backend(); -} - -int main(int argc, char *argv[]) { - - setup(); - atexit(close_file); - - // Check for file input as argument - if (2 != argc) { - INFO("Usage: %s \n", argv[0]); - PANIC("No File could be found"); - } - - // filename as first argument - char *filename = argv[1]; - - FILE *file = fopen(filename, "r"); - - if (NULL == file) { - PANIC("File couldn't be opened!"); - } - yyin = file; - - root = AST_new_node(AST_Module, NULL); - yyparse(); - - TypeScopeRef scope = type_scope_new(); - - AST_NODE_PTR fun = AST_get_node(root, 0); - - GemstoneFunRef function = fun_from_ast(scope, fun); - type_scope_add_fun(scope, function); - assert(function->params->len == 3); - - type_scope_delete(scope); - - AST_delete_node(root); - return 0; -} diff --git a/tests/llvm/params/test.txt b/tests/llvm/params/test.txt deleted file mode 100644 index 1b94e93..0000000 --- a/tests/llvm/params/test.txt +++ /dev/null @@ -1,4 +0,0 @@ - -fun a(in out int: a, in float: b)(out float: c) { - a = 0 -} \ No newline at end of file diff --git a/tests/llvm/typedef/CMakeLists.txt b/tests/llvm/typedef/CMakeLists.txt deleted file mode 100644 index 84646ce..0000000 --- a/tests/llvm/typedef/CMakeLists.txt +++ /dev/null @@ -1,51 +0,0 @@ -include(CTest) - -# ------------------------------------------------ # -# Setup Glib 2.0 # -# ------------------------------------------------ # - -find_package(PkgConfig REQUIRED) -pkg_search_module(GLIB REQUIRED IMPORTED_TARGET glib-2.0) - -# ------------------------------------------------ # -# LLVM backend # -# ------------------------------------------------ # - -# Fetch LLVM link configuration -execute_process(COMMAND llvm-config --libs all - OUTPUT_VARIABLE LLVM_LIBS) -# Strip whitespace from output -string(STRIP "${LLVM_LIBS}" LLVM_LIBS) -# Link all targets to LLVM -link_libraries(${LLVM_LIBS}) - -# ------------------------------------------------ # -# Source # -# ------------------------------------------------ # - -include_directories(${PROJECT_SOURCE_DIR}/src) -include_directories(PRIVATE ${GLIB_INCLUDE_DIRS}) - -file(GLOB_RECURSE SOURCE_FILES ${PROJECT_SOURCE_DIR}/src/*.c) -list(REMOVE_ITEM SOURCE_FILES ${PROJECT_SOURCE_DIR}/src/main.c) - -set(LEX_GENERATED_SOURCE_FILE ${PROJECT_SOURCE_DIR}/src/lex/lexer.ll.c) -set(YACC_GENERATED_SOURCE_FILE ${PROJECT_SOURCE_DIR}/src/yacc/parser.tab.c) - -# ------------------------------------------------------- # -# CTEST 1 -# test typedef - -add_executable(typedef - ${SOURCE_FILES} - ${LEX_GENERATED_SOURCE_FILE} - ${YACC_GENERATED_SOURCE_FILE} - typedef.c) -set_target_properties(typedef - PROPERTIES - OUTPUT_NAME "typedef" - RUNTIME_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/tests/llvm) -target_link_libraries(typedef PkgConfig::GLIB) -add_test(NAME typedef - WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests/llvm/typedef - COMMAND ${GEMSTONE_BINARY_DIR}/tests/llvm/typedef test.txt) diff --git a/tests/llvm/typedef/test.txt b/tests/llvm/typedef/test.txt deleted file mode 100644 index c9e1fe0..0000000 --- a/tests/llvm/typedef/test.txt +++ /dev/null @@ -1,21 +0,0 @@ - -type unsigned half half int: u8 -type unsigned half int: u16 -type unsigned int: u32 -type unsigned double int: u64 -type unsigned double double int: u128 -type unsigned double double double int: u256 - -type signed half half int: i8 -type signed half int: i16 -type signed int: i32 -type signed double int: i64 -type signed double double int: i128 -type signed double double double int: i256 - -type signed double u8: short_int - -type signed short float: f16 -type signed float: f32 -type signed long float: f64 -type signed long double float: f128 diff --git a/tests/llvm/typedef/typedef.c b/tests/llvm/typedef/typedef.c deleted file mode 100644 index 0e2633e..0000000 --- a/tests/llvm/typedef/typedef.c +++ /dev/null @@ -1,143 +0,0 @@ -#include "llvm/types/composite-types.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern FILE *yyin; -AST_NODE_PTR root; - -/** - * @brief Log a debug message to inform about beginning exit procedures - * - */ -void notify_exit(void) { DEBUG("Exiting gemstone..."); } - -/** - * @brief Closes File after compiling. - * - */ - -void close_file(void) { - if (NULL != yyin) { - fclose(yyin); - } -} - -/** - * @brief Run compiler setup here - * - */ -void setup(void) { - // setup preample - - log_init(); - DEBUG("starting gemstone..."); - -#if LOG_LEVEL <= LOG_LEVEL_DEBUG - atexit(¬ify_exit); -#endif - - // actual setup - AST_init(); - - col_init(); - - lex_init(); - - DEBUG("finished starting up gemstone..."); -} - -void run_backend_codegen() { - llvm_backend_init(); - - BackendError err; - err = init_backend(); - if (err.kind != Success) { - return; - } - - void* code = NULL; - err = generate_code(root, &code); - if (err.kind != Success) { - return; - } - - err = deinit_backend(); -} - -void check_type(const TypeScopeRef scope, const char* name, enum Sign_t sign, enum Scale_t scale, enum Primitive_t prim) { - GemstoneTypedefRef type = type_scope_get_type_from_name(scope, name); - INFO("Expected: %d %d %d Given: %d %d %d", sign, scale, prim, type->type->specs.composite.sign, type->type->specs.composite.scale, type->type->specs.composite.prim); - assert(type->type->kind == TypeComposite); - assert(type->type->specs.composite.prim == prim); - assert(type->type->specs.composite.scale == scale); - assert(type->type->specs.composite.sign == sign); -} - -int main(int argc, char *argv[]) { - - setup(); - atexit(close_file); - - // Check for file input as argument - if (2 != argc) { - INFO("Usage: %s \n", argv[0]); - PANIC("No File could be found"); - } - - // filename as first argument - char *filename = argv[1]; - - FILE *file = fopen(filename, "r"); - - if (NULL == file) { - PANIC("File couldn't be opened!"); - } - yyin = file; - - root = AST_new_node(AST_Module, NULL); - yyparse(); - - TypeScopeRef scope = type_scope_new(); - - for (size_t i = 0; i < root->child_count; i++) { - GemstoneTypedefRef typdef = get_type_def_from_ast(scope, root->children[i]); - - type_scope_append_type(scope, typdef); - } - - check_type(scope, "u8", Unsigned, ATOM, Int); - check_type(scope, "u16", Unsigned, HALF, Int); - check_type(scope, "u32", Unsigned, SINGLE, Int); - check_type(scope, "u64", Unsigned, DOUBLE, Int); - check_type(scope, "u128", Unsigned, QUAD, Int); - check_type(scope, "u256", Unsigned, OCTO, Int); - - check_type(scope, "i8", Signed, ATOM, Int); - check_type(scope, "i16", Signed, HALF, Int); - check_type(scope, "i32", Signed, SINGLE, Int); - check_type(scope, "i64", Signed, DOUBLE, Int); - check_type(scope, "i128", Signed, QUAD, Int); - check_type(scope, "i256", Signed, OCTO, Int); - - check_type(scope, "short_int", Signed, HALF, Int); - - check_type(scope, "f16", Signed, HALF, Float); - check_type(scope, "f32", Signed, SINGLE, Float); - check_type(scope, "f64", Signed, DOUBLE, Float); - check_type(scope, "f128", Signed, QUAD, Float); - - type_scope_delete(scope); - - AST_delete_node(root); - return 0; -} From ad7355c94cc0c0876769ee9b68bc59c2a99f0809 Mon Sep 17 00:00:00 2001 From: servostar Date: Mon, 27 May 2024 01:24:37 +0200 Subject: [PATCH 030/124] removed llvm tests --- src/llvm/parser.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/llvm/parser.c b/src/llvm/parser.c index b115650..e143d0c 100644 --- a/src/llvm/parser.c +++ b/src/llvm/parser.c @@ -27,6 +27,11 @@ BackendError parse_module(const Module* module, void**) { err = impl_global_variables(unit, global_scope, module->variables); + char* err_msg = NULL; + if (LLVMPrintModuleToFile(unit->module, "out.s", &err_msg)) { + err = new_backend_impl_error(Implementation, NULL, err_msg); + } + delete_global_scope(global_scope); LLVMDisposeModule(unit->module); From 92f4708ce7f0c43241b010ec2579d356ed363b73 Mon Sep 17 00:00:00 2001 From: servostar Date: Mon, 27 May 2024 13:05:56 +0200 Subject: [PATCH 031/124] feature: codegen --- src/llvm/backend.c | 45 ++++++++++++++++++++++ src/llvm/backend.h | 29 ++++++++++++++ src/llvm/parser.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 169 insertions(+) diff --git a/src/llvm/backend.c b/src/llvm/backend.c index 5abcb95..8820120 100644 --- a/src/llvm/backend.c +++ b/src/llvm/backend.c @@ -1,10 +1,55 @@ #include +#include +#include #include #include #include #include +Target create_native_target() { + Target target; + + target.triple.str = LLVMGetDefaultTargetTriple(); + target.triple.allocation = LLVM; + + target.cpu.str = LLVMGetHostCPUName(); + target.cpu.allocation = LLVM; + + target.features.str = LLVMGetHostCPUFeatures(); + target.features.allocation = LLVM; + + target.opt = LLVMCodeGenLevelDefault; + target.reloc = LLVMRelocDefault; + target.model = LLVMCodeModelDefault; + + return target; +} + +Target create_target_from_config() { + PANIC("NOT IMPLEMENTED"); +} + +static void delete_string(String string) { + switch (string.allocation) { + case LLVM: + LLVMDisposeMessage(string.str); + break; + case LIBC: + free(string.str); + break; + case NONE: + break; + } +} + +void delete_target(Target target) { + delete_string(target.name); + delete_string(target.cpu); + delete_string(target.features); + delete_string(target.triple); +} + typedef enum LLVMBackendError_t { UnresolvedImport } LLVMBackendError; diff --git a/src/llvm/backend.h b/src/llvm/backend.h index 26ef165..4625aa7 100644 --- a/src/llvm/backend.h +++ b/src/llvm/backend.h @@ -2,6 +2,35 @@ #ifndef LLVM_CODEGEN_BACKEND_H_ #define LLVM_CODEGEN_BACKEND_H_ +#include + +enum StringAllocation_t { + LLVM, + LIBC, + NONE +}; + +typedef struct String_t { + enum StringAllocation_t allocation; + char* str; +} String; + +typedef struct Target_t { + String name; + String triple; + String cpu; + String features; + LLVMCodeGenOptLevel opt; + LLVMRelocMode reloc; + LLVMCodeModel model; +} Target; + +Target create_native_target(); + +Target create_target_from_config(); + +void delete_target(Target target); + void llvm_backend_init(void); #endif // LLVM_CODEGEN_BACKEND_H_ diff --git a/src/llvm/parser.c b/src/llvm/parser.c index e143d0c..4ff827d 100644 --- a/src/llvm/parser.c +++ b/src/llvm/parser.c @@ -1,14 +1,103 @@ #include #include +#include +#include #include #include #include #include #include +#include #include +#include + +#include "llvm/backend.h" + +BackendError export_IR(LLVMBackendCompileUnit* unit) { + BackendError err = SUCCESS; + + char* ir = LLVMPrintModuleToString(unit->module); + + FILE* output = fopen("module.ll", "w"); + if (output == NULL) { + err = new_backend_impl_error(Implementation, NULL, + "unable to open file for writing"); + LLVMDisposeMessage(ir); + } + + fprintf(output, "%s", ir); + fflush(output); + fclose(output); + + LLVMDisposeMessage(ir); + + return err; +} + +BackendError export_object(LLVMBackendCompileUnit* unit, const Target* target) { + LLVMTargetRef llvm_target = NULL; + char* error = NULL; + + if (LLVMGetTargetFromTriple(target->triple.str, &llvm_target, &error) != + 0) { + BackendError err = + new_backend_impl_error(Implementation, NULL, strdup(error)); + LLVMDisposeMessage(error); + return err; + } + + LLVMTargetMachineRef target_machine = LLVMCreateTargetMachine( + llvm_target, target->triple.str, target->cpu.str, target->features.str, + target->opt, target->reloc, target->model); + + LLVMCodeGenFileType file_type = LLVMObjectFile; + + if (LLVMTargetMachineEmitToFile(target_machine, unit->module, "output", + file_type, &error) != 0) { + BackendError err = + new_backend_impl_error(Implementation, NULL, strdup(error)); + LLVMDisposeMessage(error); + return err; + } + + return SUCCESS; +} + +void list_available_targets() { + LLVMInitializeAllTargetInfos(); + + printf("Available targets:\n"); + + LLVMTargetRef target = LLVMGetFirstTarget(); + while (target) { + const char* name = LLVMGetTargetName(target); + const char* desc = LLVMGetTargetDescription(target); + printf(" - %s: (%s)\n", name, desc); + + target = LLVMGetNextTarget(target); + } + + char* default_triple = LLVMGetDefaultTargetTriple(); + + printf("Default: %s\n", default_triple); + + LLVMDisposeMessage(default_triple); +} + +BackendError export_module(LLVMBackendCompileUnit* unit, const Target* target) { + BackendError err = SUCCESS; + + export_object(unit, target); + + return err; +} BackendError parse_module(const Module* module, void**) { + if (module == NULL) { + return new_backend_impl_error(Implementation, NULL, "no module"); + } + LLVMBackendCompileUnit* unit = malloc(sizeof(LLVMBackendCompileUnit)); // we start with a LLVM module @@ -32,6 +121,12 @@ BackendError parse_module(const Module* module, void**) { err = new_backend_impl_error(Implementation, NULL, err_msg); } + Target target = create_native_target(); + + export_module(unit, &target); + + delete_target(target); + delete_global_scope(global_scope); LLVMDisposeModule(unit->module); From e01d4c48084ae0bc4669da30fb3b33f46287621c Mon Sep 17 00:00:00 2001 From: servostar Date: Mon, 27 May 2024 15:56:44 +0200 Subject: [PATCH 032/124] added debug and error messages --- src/llvm/backend.c | 6 ++++ src/llvm/parser.c | 67 ++++++++++++++++++++++++++++++++++++-------- src/llvm/types.c | 51 +++++++++++++++++++++++++++++---- src/llvm/variables.c | 28 ++++++++++++++---- 4 files changed, 128 insertions(+), 24 deletions(-) diff --git a/src/llvm/backend.c b/src/llvm/backend.c index 8820120..dc24897 100644 --- a/src/llvm/backend.c +++ b/src/llvm/backend.c @@ -1,4 +1,5 @@ +#include #include #include #include @@ -8,16 +9,20 @@ #include Target create_native_target() { + DEBUG("creating native target..."); Target target; target.triple.str = LLVMGetDefaultTargetTriple(); target.triple.allocation = LLVM; + assert(target.triple.str != NULL); target.cpu.str = LLVMGetHostCPUName(); target.cpu.allocation = LLVM; + assert(target.cpu.str != NULL); target.features.str = LLVMGetHostCPUFeatures(); target.features.allocation = LLVM; + assert(target.features.str != NULL); target.opt = LLVMCodeGenLevelDefault; target.reloc = LLVMRelocDefault; @@ -31,6 +36,7 @@ Target create_target_from_config() { } static void delete_string(String string) { + DEBUG("deleting string..."); switch (string.allocation) { case LLVM: LLVMDisposeMessage(string.str); diff --git a/src/llvm/parser.c b/src/llvm/parser.c index 4ff827d..e7d8287 100644 --- a/src/llvm/parser.c +++ b/src/llvm/parser.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -11,52 +12,81 @@ #include #include #include +#include -#include "llvm/backend.h" +#define EXPORT_IR 1 + +BackendError export_IR(LLVMBackendCompileUnit* unit, const Target* target) { + DEBUG("exporting module to LLVM-IR..."); -BackendError export_IR(LLVMBackendCompileUnit* unit) { BackendError err = SUCCESS; + // convert module to LLVM-IR char* ir = LLVMPrintModuleToString(unit->module); - FILE* output = fopen("module.ll", "w"); + // construct file name + char* filename = alloca(strlen(target->name.str) + 2); + sprintf(filename, "%s.ll", target->name.str); + + INFO("Writing LLVM-IR to %s", filename); + + DEBUG("opening file..."); + FILE* output = fopen(filename, "w"); if (output == NULL) { + ERROR("unable to open file: %s", filename); err = new_backend_impl_error(Implementation, NULL, "unable to open file for writing"); LLVMDisposeMessage(ir); } - fprintf(output, "%s", ir); + DEBUG("printing LLVM-IR to file..."); + + size_t bytes = fprintf(output, "%s", ir); + + // flush and close output file fflush(output); fclose(output); + INFO("%ld bytes written to %s", bytes, filename); + + // clean up LLVM-IR string LLVMDisposeMessage(ir); return err; } BackendError export_object(LLVMBackendCompileUnit* unit, const Target* target) { + DEBUG("exporting object file..."); + + INFO("Using target (%s): %s with features: %s", target->name.str, + target->triple.str, target->features.str); + LLVMTargetRef llvm_target = NULL; char* error = NULL; + DEBUG("creating target..."); if (LLVMGetTargetFromTriple(target->triple.str, &llvm_target, &error) != 0) { - BackendError err = - new_backend_impl_error(Implementation, NULL, strdup(error)); + ERROR("failed to create target machine: %s", error); + BackendError err = new_backend_impl_error( + Implementation, NULL, "unable to create target machine"); LLVMDisposeMessage(error); return err; } + DEBUG("Creating target machine..."); LLVMTargetMachineRef target_machine = LLVMCreateTargetMachine( llvm_target, target->triple.str, target->cpu.str, target->features.str, target->opt, target->reloc, target->model); LLVMCodeGenFileType file_type = LLVMObjectFile; + DEBUG("Generating code..."); if (LLVMTargetMachineEmitToFile(target_machine, unit->module, "output", file_type, &error) != 0) { + ERROR("failed to emit code: %s", error); BackendError err = - new_backend_impl_error(Implementation, NULL, strdup(error)); + new_backend_impl_error(Implementation, NULL, "failed to emit code"); LLVMDisposeMessage(error); return err; } @@ -65,6 +95,7 @@ BackendError export_object(LLVMBackendCompileUnit* unit, const Target* target) { } void list_available_targets() { + DEBUG("initializing all available targets..."); LLVMInitializeAllTargetInfos(); printf("Available targets:\n"); @@ -86,21 +117,32 @@ void list_available_targets() { } BackendError export_module(LLVMBackendCompileUnit* unit, const Target* target) { + DEBUG("exporting module..."); + BackendError err = SUCCESS; export_object(unit, target); + if (EXPORT_IR) { + export_IR(unit, target); + } else { + DEBUG("not exporting LLVM-IR"); + } + return err; } BackendError parse_module(const Module* module, void**) { + DEBUG("generating code for module %p", module); if (module == NULL) { + ERROR("no module for codegen"); return new_backend_impl_error(Implementation, NULL, "no module"); } LLVMBackendCompileUnit* unit = malloc(sizeof(LLVMBackendCompileUnit)); // we start with a LLVM module + DEBUG("creating LLVM context and module"); unit->context = LLVMContextCreate(); unit->module = LLVMModuleCreateWithNameInContext("gemstone application", unit->context); @@ -109,6 +151,8 @@ BackendError parse_module(const Module* module, void**) { BackendError err = new_backend_error(Success); + DEBUG("generating code..."); + err = impl_types(unit, global_scope, module->types); // NOTE: functions of boxes are not stored in the box itself, // thus for a box we only implement the type @@ -116,11 +160,6 @@ BackendError parse_module(const Module* module, void**) { err = impl_global_variables(unit, global_scope, module->variables); - char* err_msg = NULL; - if (LLVMPrintModuleToFile(unit->module, "out.s", &err_msg)) { - err = new_backend_impl_error(Implementation, NULL, err_msg); - } - Target target = create_native_target(); export_module(unit, &target); @@ -138,6 +177,7 @@ BackendError parse_module(const Module* module, void**) { } LLVMGlobalScope* new_global_scope() { + DEBUG("creating global scope..."); LLVMGlobalScope* scope = malloc(sizeof(LLVMGlobalScope)); scope->functions = g_hash_table_new(g_str_hash, g_str_equal); @@ -149,6 +189,7 @@ LLVMGlobalScope* new_global_scope() { LLVMLocalScope* new_local_scope(LLVMGlobalScope* global_scope, LLVMLocalScope* parent_scope) { + DEBUG("creating local scope..."); LLVMLocalScope* scope = malloc(sizeof(LLVMLocalScope)); scope->variables = g_hash_table_new(g_str_hash, g_str_equal); @@ -160,11 +201,13 @@ LLVMLocalScope* new_local_scope(LLVMGlobalScope* global_scope, } void delete_local_scope(LLVMLocalScope* scope) { + DEBUG("deleting global scope..."); g_hash_table_unref(scope->variables); free(scope); } void delete_global_scope(LLVMGlobalScope* scope) { + DEBUG("deleting global scope..."); g_hash_table_unref(scope->functions); g_hash_table_unref(scope->types); g_hash_table_unref(scope->variables); diff --git a/src/llvm/types.c b/src/llvm/types.c index 87d87ca..e41ff95 100644 --- a/src/llvm/types.c +++ b/src/llvm/types.c @@ -1,21 +1,28 @@ #include #include #include +#include #include #include -#include +#include + +#define BASE_BYTES 4 +#define BITS_PER_BYTE 8 BackendError impl_primtive_type(LLVMBackendCompileUnit* unit, PrimitiveType primtive, LLVMTypeRef* llvm_type) { switch (primtive) { case Int: + DEBUG("implementing primtive integral type..."); *llvm_type = LLVMInt32TypeInContext(unit->context); break; case Float: + DEBUG("implementing primtive float type..."); *llvm_type = LLVMFloatTypeInContext(unit->context); break; default: + PANIC("invalid primitive type"); break; } @@ -24,8 +31,9 @@ BackendError impl_primtive_type(LLVMBackendCompileUnit* unit, BackendError impl_integral_type(LLVMBackendCompileUnit* unit, Scale scale, LLVMTypeRef* llvm_type) { - LLVMTypeRef integral_type = - LLVMIntTypeInContext(unit->context, (int)(4 * scale) * 8); + size_t bits = (int)(4 * scale) * BITS_PER_BYTE; + DEBUG("implementing integral type of size: %ld", bits); + LLVMTypeRef integral_type = LLVMIntTypeInContext(unit->context, bits); *llvm_type = integral_type; @@ -34,9 +42,12 @@ BackendError impl_integral_type(LLVMBackendCompileUnit* unit, Scale scale, BackendError impl_float_type(LLVMBackendCompileUnit* unit, Scale scale, LLVMTypeRef* llvm_type) { + DEBUG("implementing floating point..."); LLVMTypeRef float_type = NULL; - switch ((int)(scale * 4)) { + size_t bytes = (int)(scale * BASE_BYTES); + DEBUG("requested float of bytes: %ld", bytes); + switch (bytes) { case 2: float_type = LLVMHalfTypeInContext(unit->context); break; @@ -50,6 +61,8 @@ BackendError impl_float_type(LLVMBackendCompileUnit* unit, Scale scale, float_type = LLVMFP128TypeInContext(unit->context); break; default: + ERROR("invalid floating point size: %ld bit", + bytes * BITS_PER_BYTE); break; } @@ -65,6 +78,7 @@ BackendError impl_float_type(LLVMBackendCompileUnit* unit, Scale scale, BackendError impl_composite_type(LLVMBackendCompileUnit* unit, CompositeType* composite, LLVMTypeRef* llvm_type) { + DEBUG("implementing composite type..."); BackendError err = SUCCESS; switch (composite->primitive) { @@ -75,12 +89,14 @@ BackendError impl_composite_type(LLVMBackendCompileUnit* unit, if (composite->sign == Signed) { err = impl_float_type(unit, composite->scale, llvm_type); } else { + ERROR("unsgined floating point not supported"); err = new_backend_impl_error( Implementation, composite->nodePtr, "unsigned floating-point not supported"); } break; default: + PANIC("invalid primitive kind: %ld", composite->primitive); break; } @@ -97,6 +113,7 @@ BackendError impl_box_type(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, BackendError get_type_impl(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, Type* gemstone_type, LLVMTypeRef* llvm_type) { + DEBUG("retrieving type implementation..."); BackendError err = new_backend_impl_error(Implementation, gemstone_type->nodePtr, "No type implementation covers type"); @@ -118,6 +135,9 @@ BackendError get_type_impl(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, err = impl_box_type(unit, scope, &gemstone_type->impl.box, llvm_type); break; + default: + PANIC("invalid type kind: %ld", gemstone_type->kind); + break; } return err; @@ -125,6 +145,7 @@ BackendError get_type_impl(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, BackendError impl_box_type(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, BoxType* box, LLVMTypeRef* llvm_type) { + DEBUG("implementing box type..."); GHashTableIter iterator; g_hash_table_iter_init(&iterator, box->member); @@ -135,8 +156,11 @@ BackendError impl_box_type(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, GArray* members = g_array_new(FALSE, FALSE, sizeof(LLVMTypeRef)); + DEBUG("implementing box members..."); while (g_hash_table_iter_next(&iterator, &key, &val) != FALSE) { - Type* member_type = ((BoxMember*) val)->type; + Type* member_type = ((BoxMember*)val)->type; + + DEBUG("implementing member: %s ", ((BoxMember*)val)->name); LLVMTypeRef llvm_type = NULL; err = get_type_impl(unit, scope, member_type, &llvm_type); @@ -147,6 +171,7 @@ BackendError impl_box_type(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, g_array_append_val(members, llvm_type); } + DEBUG("implemented %ld members", members->len); if (err.kind == Success) { *llvm_type = @@ -162,6 +187,7 @@ BackendError impl_reference_type(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, ReferenceType reference, LLVMTypeRef* llvm_type) { + DEBUG("implementing reference type..."); BackendError err = SUCCESS; LLVMTypeRef type = NULL; err = get_type_impl(unit, scope, reference, &type); @@ -176,6 +202,7 @@ BackendError impl_reference_type(LLVMBackendCompileUnit* unit, BackendError impl_type(LLVMBackendCompileUnit* unit, Type* gemstone_type, const char* alias, LLVMGlobalScope* scope) { BackendError err = SUCCESS; + DEBUG("implementing type of kind: %ld as %s", gemstone_type->kind, alias); LLVMTypeRef llvm_type = NULL; err = get_type_impl(unit, scope, gemstone_type, &llvm_type); @@ -189,6 +216,7 @@ BackendError impl_type(LLVMBackendCompileUnit* unit, Type* gemstone_type, BackendError impl_types(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, GHashTable* types) { + DEBUG("implementing given types of %p", types); GHashTableIter iterator; g_hash_table_iter_init(&iterator, types); @@ -211,6 +239,7 @@ BackendError impl_types(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, BackendError get_primitive_default_value(PrimitiveType type, LLVMTypeRef llvm_type, LLVMValueRef* llvm_value) { + DEBUG("building primitive %ld default value", type); switch (type) { case Int: *llvm_value = LLVMConstIntOfString(llvm_type, "0", 10); @@ -219,6 +248,7 @@ BackendError get_primitive_default_value(PrimitiveType type, *llvm_value = LLVMConstRealOfString(llvm_type, "0"); break; default: + ERROR("invalid primitive type: %ld", type); return new_backend_impl_error(Implementation, NULL, "unknown primitive type"); } @@ -229,6 +259,7 @@ BackendError get_primitive_default_value(PrimitiveType type, BackendError get_composite_default_value(CompositeType* composite, LLVMTypeRef llvm_type, LLVMValueRef* llvm_value) { + DEBUG("building composite default value"); BackendError err = SUCCESS; switch (composite->primitive) { @@ -245,6 +276,7 @@ BackendError get_composite_default_value(CompositeType* composite, } break; default: + ERROR("invalid primitive type: %ld", composite->primitive); break; } @@ -253,6 +285,7 @@ BackendError get_composite_default_value(CompositeType* composite, BackendError get_reference_default_value(LLVMTypeRef llvm_type, LLVMValueRef* llvm_value) { + DEBUG("building reference default value"); *llvm_value = LLVMConstPointerNull(llvm_type); return SUCCESS; @@ -261,6 +294,7 @@ BackendError get_reference_default_value(LLVMTypeRef llvm_type, BackendError get_box_default_value(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, BoxType* type, LLVMValueRef* llvm_value) { + DEBUG("building box default value..."); GHashTableIter iterator; g_hash_table_iter_init(&iterator, type->member); @@ -282,8 +316,10 @@ BackendError get_box_default_value(LLVMBackendCompileUnit* unit, } } + DEBUG("build %ld member default values", constants->len); + *llvm_value = LLVMConstStructInContext( - unit->context, (LLVMValueRef*) constants->data, constants->len, 0); + unit->context, (LLVMValueRef*)constants->data, constants->len, 0); g_array_free(constants, FALSE); @@ -318,6 +354,9 @@ BackendError get_type_default_value(LLVMBackendCompileUnit* unit, err = get_box_default_value(unit, scope, &gemstone_type->impl.box, llvm_value); break; + default: + PANIC("invalid type kind: %ld", gemstone_type->kind); + break; } return err; diff --git a/src/llvm/variables.c b/src/llvm/variables.c index 51d2170..4552e39 100644 --- a/src/llvm/variables.c +++ b/src/llvm/variables.c @@ -5,11 +5,13 @@ #include #include #include +#include BackendError impl_global_declaration(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, VariableDeclaration* decl, const char* name) { + DEBUG("implementing global declaration: ", name); BackendError err = SUCCESS; LLVMTypeRef llvm_type = NULL; err = get_type_impl(unit, scope, &decl->type, &llvm_type); @@ -18,12 +20,14 @@ BackendError impl_global_declaration(LLVMBackendCompileUnit* unit, return err; } + DEBUG("creating global variable..."); LLVMValueRef global = LLVMAddGlobal(unit->module, llvm_type, name); LLVMValueRef initial_value = NULL; err = get_type_default_value(unit, scope, &decl->type, &initial_value); if (err.kind == Success) { + DEBUG("setting default value..."); LLVMSetInitializer(global, initial_value); g_hash_table_insert(scope->variables, (gpointer)name, global); } @@ -32,9 +36,9 @@ BackendError impl_global_declaration(LLVMBackendCompileUnit* unit, } BackendError impl_global_definiton(LLVMBackendCompileUnit* unit, - LLVMGlobalScope* scope, - VariableDefiniton* def, - const char* name) { + LLVMGlobalScope* scope, + VariableDefiniton* def, const char* name) { + DEBUG("implementing global definition: %s", name); BackendError err = SUCCESS; LLVMTypeRef llvm_type = NULL; err = get_type_impl(unit, scope, &def->declaration.type, &llvm_type); @@ -43,13 +47,16 @@ BackendError impl_global_definiton(LLVMBackendCompileUnit* unit, return err; } + DEBUG("creating global variable..."); LLVMValueRef global = LLVMAddGlobal(unit->module, llvm_type, name); // FIXME: resolve initializer expression! LLVMValueRef initial_value = NULL; - err = get_type_default_value(unit, scope, &def->declaration.type, &initial_value); + err = get_type_default_value(unit, scope, &def->declaration.type, + &initial_value); if (err.kind == Success) { + DEBUG("setting default value"); LLVMSetInitializer(global, initial_value); g_hash_table_insert(scope->variables, (gpointer)name, global); } @@ -68,13 +75,16 @@ BackendError impl_global_variable(LLVMBackendCompileUnit* unit, unit, scope, &gemstone_var->impl.declaration, alias); break; case VariableKindDefinition: - err = impl_global_definiton( - unit, scope, &gemstone_var->impl.definiton, alias); + err = impl_global_definiton(unit, scope, + &gemstone_var->impl.definiton, alias); break; case VariableKindBoxMember: err = new_backend_impl_error(Implementation, gemstone_var->nodePtr, "member variable cannot be "); break; + default: + PANIC("invalid variable kind: %ld", gemstone_var->kind); + break; } return err; @@ -83,6 +93,7 @@ BackendError impl_global_variable(LLVMBackendCompileUnit* unit, BackendError impl_global_variables(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, GHashTable* variables) { + DEBUG("implementing global variables..."); GHashTableIter iterator; g_hash_table_iter_init(&iterator, variables); @@ -91,6 +102,7 @@ BackendError impl_global_variables(LLVMBackendCompileUnit* unit, BackendError err; + size_t variable_count = 0; while (g_hash_table_iter_next(&iterator, &key, &val) != FALSE) { err = impl_global_variable(unit, (Variable*)val, (const char*)key, scope); @@ -98,7 +110,11 @@ BackendError impl_global_variables(LLVMBackendCompileUnit* unit, if (err.kind != Success) { break; } + + variable_count++; } + DEBUG("implemented %ld global variables", variable_count); + return err; } From 0fcb0d7af86e105b6504af64a92d78a14aebbe87 Mon Sep 17 00:00:00 2001 From: servostar Date: Mon, 27 May 2024 16:47:32 +0200 Subject: [PATCH 033/124] added test for llvm vars --- .gitignore | 1 + src/llvm/backend.c | 3 +++ src/llvm/parser.c | 6 +++++- tests/CMakeLists.txt | 3 ++- tests/llvm/CMakeLists.txt | 36 ++++++++++++++++++++++++++++++++ tests/llvm/global_vars.c | 44 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 tests/llvm/CMakeLists.txt create mode 100644 tests/llvm/global_vars.c diff --git a/.gitignore b/.gitignore index 10613c6..8c4be57 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ build CTestTestfile.cmake DartConfiguration.tcl *.cmake +*.ll diff --git a/src/llvm/backend.c b/src/llvm/backend.c index dc24897..04c23f0 100644 --- a/src/llvm/backend.c +++ b/src/llvm/backend.c @@ -12,6 +12,9 @@ Target create_native_target() { DEBUG("creating native target..."); Target target; + target.name.str = "tmp"; + target.name.allocation = NONE; + target.triple.str = LLVMGetDefaultTargetTriple(); target.triple.allocation = LLVM; assert(target.triple.str != NULL); diff --git a/src/llvm/parser.c b/src/llvm/parser.c index e7d8287..4bda673 100644 --- a/src/llvm/parser.c +++ b/src/llvm/parser.c @@ -25,7 +25,7 @@ BackendError export_IR(LLVMBackendCompileUnit* unit, const Target* target) { char* ir = LLVMPrintModuleToString(unit->module); // construct file name - char* filename = alloca(strlen(target->name.str) + 2); + char* filename = alloca(strlen(target->name.str) + 4); sprintf(filename, "%s.ll", target->name.str); INFO("Writing LLVM-IR to %s", filename); @@ -64,6 +64,10 @@ BackendError export_object(LLVMBackendCompileUnit* unit, const Target* target) { LLVMTargetRef llvm_target = NULL; char* error = NULL; + LLVMInitializeAllTargets(); + LLVMInitializeAllTargetInfos(); + LLVMInitializeAllTargetMCs(); + DEBUG("creating target..."); if (LLVMGetTargetFromTriple(target->triple.str, &llvm_target, &error) != 0) { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 1228d2b..57c4c80 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -9,4 +9,5 @@ set(CTEST_BINARY_DIRECTORY ${PROJECT_BINARY_DIR}/tests) add_subdirectory(logging) add_subdirectory(input_file) add_subdirectory(ast) -add_subdirectory(glib) \ No newline at end of file +add_subdirectory(glib) +add_subdirectory(llvm) \ No newline at end of file diff --git a/tests/llvm/CMakeLists.txt b/tests/llvm/CMakeLists.txt new file mode 100644 index 0000000..e4dcdc9 --- /dev/null +++ b/tests/llvm/CMakeLists.txt @@ -0,0 +1,36 @@ +include(CTest) + +include_directories(${PROJECT_SOURCE_DIR}/src) +include_directories(PRIVATE ${GLIB_INCLUDE_DIRS}) + +find_package(PkgConfig REQUIRED) +pkg_search_module(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +link_libraries(PkgConfig::GLIB) + +# ------------------------------------------------ # +# LLVM backend # +# ------------------------------------------------ # + +# Fetch LLVM link configuration +execute_process(COMMAND llvm-config --libs all + OUTPUT_VARIABLE LLVM_LIBS) +# Strip whitespace from output +string(STRIP "${LLVM_LIBS}" LLVM_LIBS) +# Link all targets to LLVM +link_libraries(${LLVM_LIBS}) + +# ------------------------------------------------------- # +# CTEST 1 +# test llvm backend codegen for global variables + +file(GLOB_RECURSE SOURCE_FILES ${PROJECT_SOURCE_DIR}/src/*.c) +list(REMOVE_ITEM SOURCE_FILES ${PROJECT_SOURCE_DIR}/src/main.c) +add_executable(global_vars +global_vars.c ${SOURCE_FILES}) +set_target_properties(global_vars + PROPERTIES + OUTPUT_NAME "global_vars" + RUNTIME_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/tests/llvm) +add_test(NAME global_vars + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests/llvm + COMMAND ${GEMSTONE_BINARY_DIR}/tests/llvm/global_vars) diff --git a/tests/llvm/global_vars.c b/tests/llvm/global_vars.c new file mode 100644 index 0000000..aca3d42 --- /dev/null +++ b/tests/llvm/global_vars.c @@ -0,0 +1,44 @@ + +#include +#include +#include +#include + +// NOTE: unused +AST_NODE_PTR root; + +Module* create_module() { + Module* module = malloc(sizeof(Module)); + + module->boxes = g_hash_table_new(g_str_hash, g_str_equal); + module->functions = g_hash_table_new(g_str_hash, g_str_equal); + module->imports = g_array_new(FALSE, FALSE, sizeof(Type)); + module->variables = g_hash_table_new(g_str_hash, g_str_equal); + module->types = g_hash_table_new(g_str_hash, g_str_equal); + + return module; +} + +int main() { + log_init(); + + Module* module = create_module(); + + llvm_backend_init(); + + BackendError err; + err = init_backend(); + if (err.kind != Success) { + PANIC("%ld: at [%p] %s", err.kind, err.impl.ast_node, err.impl.message); + } + + err = generate_code(module, NULL); + if (err.kind != Success) { + PANIC("%ld: at [%p] %s", err.kind, err.impl.ast_node, err.impl.message); + } + + err = deinit_backend(); + if (err.kind != Success) { + PANIC("%ld: at [%p] %s", err.kind, err.impl.ast_node, err.impl.message); + } +} From fb6f6e9777bc1bf8ba7cfc5f9c62d90c3bb4b52f Mon Sep 17 00:00:00 2001 From: servostar Date: Mon, 27 May 2024 18:17:15 +0200 Subject: [PATCH 034/124] finished global variable test --- src/llvm/parser.c | 39 ++++++++++++++++------ src/llvm/types.c | 2 +- src/llvm/variables.c | 5 ++- tests/llvm/global_vars.c | 71 ++++++++++++++++++++++++++++++++++++++-- 4 files changed, 103 insertions(+), 14 deletions(-) diff --git a/src/llvm/parser.c b/src/llvm/parser.c index 4bda673..0f22e17 100644 --- a/src/llvm/parser.c +++ b/src/llvm/parser.c @@ -136,6 +136,29 @@ BackendError export_module(LLVMBackendCompileUnit* unit, const Target* target) { return err; } +static BackendError build_module(LLVMBackendCompileUnit* unit, LLVMGlobalScope* global_scope, const Module* module) { + BackendError err = SUCCESS; + + err = impl_types(unit, global_scope, module->types); + if (err.kind != Success) { + return err; + } + + // NOTE: functions of boxes are not stored in the box itself, + // thus for a box we only implement the type + err = impl_types(unit, global_scope, module->boxes); + if (err.kind != Success) { + return err; + } + + err = impl_global_variables(unit, global_scope, module->variables); + if (err.kind != Success) { + return err; + } + + return err; +} + BackendError parse_module(const Module* module, void**) { DEBUG("generating code for module %p", module); if (module == NULL) { @@ -157,18 +180,14 @@ BackendError parse_module(const Module* module, void**) { DEBUG("generating code..."); - err = impl_types(unit, global_scope, module->types); - // NOTE: functions of boxes are not stored in the box itself, - // thus for a box we only implement the type - err = impl_types(unit, global_scope, module->boxes); + err = build_module(unit, global_scope, module); + if (err.kind == Success) { + Target target = create_native_target(); - err = impl_global_variables(unit, global_scope, module->variables); + export_module(unit, &target); - Target target = create_native_target(); - - export_module(unit, &target); - - delete_target(target); + delete_target(target); + } delete_global_scope(global_scope); diff --git a/src/llvm/types.c b/src/llvm/types.c index e41ff95..bc95f83 100644 --- a/src/llvm/types.c +++ b/src/llvm/types.c @@ -333,7 +333,7 @@ BackendError get_type_default_value(LLVMBackendCompileUnit* unit, Implementation, gemstone_type->nodePtr, "No default value for type"); LLVMTypeRef llvm_type = NULL; - get_type_impl(unit, scope, gemstone_type, &llvm_type); + err = get_type_impl(unit, scope, gemstone_type, &llvm_type); if (err.kind != Success) { return err; } diff --git a/src/llvm/variables.c b/src/llvm/variables.c index 4552e39..5519313 100644 --- a/src/llvm/variables.c +++ b/src/llvm/variables.c @@ -11,7 +11,7 @@ BackendError impl_global_declaration(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, VariableDeclaration* decl, const char* name) { - DEBUG("implementing global declaration: ", name); + DEBUG("implementing global declaration: %s", name); BackendError err = SUCCESS; LLVMTypeRef llvm_type = NULL; err = get_type_impl(unit, scope, &decl->type, &llvm_type); @@ -30,6 +30,8 @@ BackendError impl_global_declaration(LLVMBackendCompileUnit* unit, DEBUG("setting default value..."); LLVMSetInitializer(global, initial_value); g_hash_table_insert(scope->variables, (gpointer)name, global); + } else { + ERROR("unable to initialize global variable: %s", err.impl.message); } return err; @@ -67,6 +69,7 @@ BackendError impl_global_definiton(LLVMBackendCompileUnit* unit, BackendError impl_global_variable(LLVMBackendCompileUnit* unit, Variable* gemstone_var, const char* alias, LLVMGlobalScope* scope) { + DEBUG("implementing global variable: %s", alias); BackendError err = SUCCESS; switch (gemstone_var->kind) { diff --git a/tests/llvm/global_vars.c b/tests/llvm/global_vars.c index aca3d42..52a104b 100644 --- a/tests/llvm/global_vars.c +++ b/tests/llvm/global_vars.c @@ -1,4 +1,5 @@ +#include #include #include #include @@ -7,8 +8,25 @@ // NOTE: unused AST_NODE_PTR root; -Module* create_module() { - Module* module = malloc(sizeof(Module)); +[[gnu::always_inline]] +[[clang::always_inline]] +inline Variable* create_variable_decl(const char* name, StorageQualifier qualifier, Type type) { + Variable* variable = alloca(sizeof(Variable)); + + variable->name = name; + variable->kind = VariableKindDeclaration; + variable->nodePtr = NULL; + variable->impl.declaration.nodePtr = NULL; + variable->impl.declaration.qualifier = qualifier; + variable->impl.declaration.type = type; + + return variable; +} + +[[gnu::always_inline]] +[[clang::always_inline]] +inline Module* create_module() { + Module* module = alloca(sizeof(Module)); module->boxes = g_hash_table_new(g_str_hash, g_str_equal); module->functions = g_hash_table_new(g_str_hash, g_str_equal); @@ -16,12 +34,61 @@ Module* create_module() { module->variables = g_hash_table_new(g_str_hash, g_str_equal); module->types = g_hash_table_new(g_str_hash, g_str_equal); + Type type_int; + type_int.kind = TypeKindPrimitive; + type_int.impl.primitive = Int; + + g_hash_table_insert(module->variables, "a", create_variable_decl("a", Global, type_int)); + + Type type_composite; + type_composite.kind = TypeKindComposite; + type_composite.impl.composite.primitive = Float; + type_composite.impl.composite.scale = 2.0; + type_composite.impl.composite.sign = Signed; + + g_hash_table_insert(module->variables, "b", create_variable_decl("b", Global, type_composite)); + + Type type_box; + type_box.kind = TypeKindBox; + type_box.impl.box.member = g_hash_table_new(g_str_hash, g_str_equal); + + BoxMember* member1 = alloca(sizeof(BoxMember)); + member1->box = NULL; + member1->name = "foo"; + member1->type = alloca(sizeof(Type)); + *(member1->type) = type_int; + + g_hash_table_insert(type_box.impl.box.member, "foo", member1); + + Type type_half; + type_half.kind = TypeKindComposite; + type_half.impl.composite.primitive = Float; + type_half.impl.composite.scale = 0.5; + type_half.impl.composite.sign = Signed; + + BoxMember* member2 = alloca(sizeof(BoxMember)); + member2->box = NULL; + member2->name = "bar"; + member2->type = alloca(sizeof(Type)); + *(member2->type) = type_half; + + g_hash_table_insert(type_box.impl.box.member, "bar", member2); + + g_hash_table_insert(module->variables, "c", create_variable_decl("c", Global, type_box)); + + Type type_reference; + type_reference.kind = TypeKindReference; + type_reference.impl.reference = &type_box; + + g_hash_table_insert(module->variables, "d", create_variable_decl("d", Global, type_reference)); + return module; } int main() { log_init(); + // no need to clean up ;-) Module* module = create_module(); llvm_backend_init(); From 9e4b0a1000074cf962ae5eccb1ae46fdef7c5cfe Mon Sep 17 00:00:00 2001 From: servostar Date: Mon, 27 May 2024 19:53:22 +0200 Subject: [PATCH 035/124] added llvm17-dev as dependency to sdk 0.2.5 --- .env | 2 +- CMakeLists.txt | 10 +++------- Dockerfile | 4 ++-- run-check-test.sh | 2 +- sdk/Dockerfile | 4 ++-- 5 files changed, 9 insertions(+), 13 deletions(-) diff --git a/.env b/.env index e09c958..6eb74fb 100644 --- a/.env +++ b/.env @@ -1 +1 @@ -SDK=0.2.4-alpine-3.19.1 \ No newline at end of file +SDK=0.2.5-alpine-3.19.1 diff --git a/CMakeLists.txt b/CMakeLists.txt index 2dad620..61e1ed0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,13 +81,8 @@ pkg_search_module(GLIB REQUIRED IMPORTED_TARGET glib-2.0) # LLVM backend # # ------------------------------------------------ # -# Fetch LLVM link configuration -execute_process(COMMAND llvm-config --libs all - OUTPUT_VARIABLE LLVM_LIBS) -# Strip whitespace from output -string(STRIP "${LLVM_LIBS}" LLVM_LIBS) -# Link all targets to LLVM -link_libraries(${LLVM_LIBS}) +find_package(PkgConfig REQUIRED) +pkg_search_module(LLVM REQUIRED IMPORTED_TARGET llvm17) # ------------------------------------------------ # # Source # @@ -95,6 +90,7 @@ link_libraries(${LLVM_LIBS}) include_directories(${PROJECT_SOURCE_DIR}/src) include_directories(PRIVATE ${GLIB_INCLUDE_DIRS}) +include_directories(PRIVATE ${LLVM_INCLUDE_DIRS}) file(GLOB_RECURSE SOURCE_FILES src/*.c) diff --git a/Dockerfile b/Dockerfile index 68265d8..8e1bb7d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ -FROM servostar/gemstone:sdk-0.2.4-alpine-3.19.1 +FROM servostar/gemstone:sdk-0.2.5-alpine-3.19.1 LABEL authors="servostar" -LABEL version="0.2.4" +LABEL version="0.2.5" LABEL description="docker image for setting up the build pipeline on SDK" LABEL website="https://github.com/Servostar/gemstone" diff --git a/run-check-test.sh b/run-check-test.sh index bd7e5cc..a20f2ad 100644 --- a/run-check-test.sh +++ b/run-check-test.sh @@ -39,4 +39,4 @@ fi echo "+--------------------------------------+" echo "| COMPLETED CHECK + TESTS SUCCESSFULLY |" -echo "+--------------------------------------+" \ No newline at end of file +echo "+--------------------------------------+" diff --git a/sdk/Dockerfile b/sdk/Dockerfile index b5523b3..fb63cad 100644 --- a/sdk/Dockerfile +++ b/sdk/Dockerfile @@ -1,11 +1,11 @@ FROM alpine:3.19.1 LABEL authors="servostar" -LABEL version="0.2.4" +LABEL version="0.2.5" LABEL description="base image for building the gemstone programming language compiler" LABEL website="https://github.com/Servostar/gemstone" # install dependencies -RUN apk add build-base gcc make cmake bison flex git python3 graphviz glib glib-dev +RUN apk add build-base gcc make cmake bison flex git python3 graphviz glib glib-dev llvm17-dev # create user for build RUN adduser --disabled-password lorang From 6197acf3b2365c847551f145513072db36b438fd Mon Sep 17 00:00:00 2001 From: servostar Date: Mon, 27 May 2024 21:22:06 +0200 Subject: [PATCH 036/124] fixed: llvm dependencies in sdk --- CMakeLists.txt | 16 +++++++++++++--- run-docker-build.sh | 2 +- sdk/Dockerfile | 2 +- src/llvm/backend.c | 16 +++++++--------- tests/llvm/CMakeLists.txt | 5 +++++ 5 files changed, 27 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 61e1ed0..7672ede 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,6 +74,7 @@ add_custom_command(OUTPUT ${YACC_GENERATED_SOURCE_FILE} # Setup Glib 2.0 # # ------------------------------------------------ # +include(FindPkgConfig) find_package(PkgConfig REQUIRED) pkg_search_module(GLIB REQUIRED IMPORTED_TARGET glib-2.0) @@ -81,8 +82,18 @@ pkg_search_module(GLIB REQUIRED IMPORTED_TARGET glib-2.0) # LLVM backend # # ------------------------------------------------ # -find_package(PkgConfig REQUIRED) -pkg_search_module(LLVM REQUIRED IMPORTED_TARGET llvm17) +# Fetch LLVM link configuration +execute_process(COMMAND llvm-config --libs all + OUTPUT_VARIABLE LLVM_LIBS) +# Strip whitespace from output +string(STRIP "${LLVM_LIBS}" LLVM_LIBS) +# Link all targets to LLVM +link_libraries(${LLVM_LIBS}) + +execute_process(COMMAND llvm-config --includedir + OUTPUT_VARIABLE LLVM_INCLUDE_DIR) +string(STRIP "${LLVM_INCLUDE_DIR}" LLVM_INCLUDE_DIR) +include_directories(${LLVM_INCLUDE_DIR}) # ------------------------------------------------ # # Source # @@ -90,7 +101,6 @@ pkg_search_module(LLVM REQUIRED IMPORTED_TARGET llvm17) include_directories(${PROJECT_SOURCE_DIR}/src) include_directories(PRIVATE ${GLIB_INCLUDE_DIRS}) -include_directories(PRIVATE ${LLVM_INCLUDE_DIRS}) file(GLOB_RECURSE SOURCE_FILES src/*.c) diff --git a/run-docker-build.sh b/run-docker-build.sh index aaec9c6..0028067 100755 --- a/run-docker-build.sh +++ b/run-docker-build.sh @@ -47,7 +47,7 @@ echo "+--------------------------------------+" echo "| RUNNING check test |" echo "+--------------------------------------+" -docker run servostar/gemstone:devkit-"$SDK" sh run-check-test.sh +docker run --rm --name "devkit-$SDK-check-test"- servostar/gemstone:devkit-"$SDK" sh run-check-test.sh if [ ! $? -eq 0 ]; then echo "===> failed to run build or checks" exit 1 diff --git a/sdk/Dockerfile b/sdk/Dockerfile index fb63cad..1cba1d3 100644 --- a/sdk/Dockerfile +++ b/sdk/Dockerfile @@ -5,7 +5,7 @@ LABEL description="base image for building the gemstone programming language com LABEL website="https://github.com/Servostar/gemstone" # install dependencies -RUN apk add build-base gcc make cmake bison flex git python3 graphviz glib glib-dev llvm17-dev +RUN apk add build-base gcc make cmake bison flex git python3 graphviz glib glib-dev llvm17-libs llvm17-dev # create user for build RUN adduser --disabled-password lorang diff --git a/src/llvm/backend.c b/src/llvm/backend.c index 04c23f0..6bd5997 100644 --- a/src/llvm/backend.c +++ b/src/llvm/backend.c @@ -1,12 +1,12 @@ #include +#include #include #include #include -#include -#include #include #include +#include Target create_native_target() { DEBUG("creating native target..."); @@ -34,9 +34,7 @@ Target create_native_target() { return target; } -Target create_target_from_config() { - PANIC("NOT IMPLEMENTED"); -} +Target create_target_from_config() { PANIC("NOT IMPLEMENTED"); } static void delete_string(String string) { DEBUG("deleting string..."); @@ -59,9 +57,7 @@ void delete_target(Target target) { delete_string(target.triple); } -typedef enum LLVMBackendError_t { - UnresolvedImport -} LLVMBackendError; +typedef enum LLVMBackendError_t { UnresolvedImport } LLVMBackendError; static BackendError llvm_backend_codegen(const Module* unit, void** output) { return parse_module(unit, output); @@ -76,7 +72,9 @@ static BackendError llvm_backend_codegen_deinit(void) { } void llvm_backend_init() { - BackendError err = set_backend(&llvm_backend_codegen_init, &llvm_backend_codegen_deinit, &llvm_backend_codegen, "LLVM"); + BackendError err = + set_backend(&llvm_backend_codegen_init, &llvm_backend_codegen_deinit, + &llvm_backend_codegen, "LLVM"); if (err.kind != Success) { PANIC("unable to init llvm backend: %ld", err); diff --git a/tests/llvm/CMakeLists.txt b/tests/llvm/CMakeLists.txt index e4dcdc9..1fc14cc 100644 --- a/tests/llvm/CMakeLists.txt +++ b/tests/llvm/CMakeLists.txt @@ -19,6 +19,11 @@ string(STRIP "${LLVM_LIBS}" LLVM_LIBS) # Link all targets to LLVM link_libraries(${LLVM_LIBS}) +execute_process(COMMAND llvm-config --includedir + OUTPUT_VARIABLE LLVM_INCLUDE_DIR) +string(STRIP "${LLVM_INCLUDE_DIR}" LLVM_INCLUDE_DIR) +include_directories(${LLVM_INCLUDE_DIR}) + # ------------------------------------------------------- # # CTEST 1 # test llvm backend codegen for global variables From da963e40b760af0f60669215b3265ba6bf9631ef Mon Sep 17 00:00:00 2001 From: servostar Date: Mon, 27 May 2024 21:39:24 +0200 Subject: [PATCH 037/124] fixed: missing symbols in global_vars test Removed lexer and parser files from compilation target --- tests/llvm/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/llvm/CMakeLists.txt b/tests/llvm/CMakeLists.txt index 1fc14cc..bc72f78 100644 --- a/tests/llvm/CMakeLists.txt +++ b/tests/llvm/CMakeLists.txt @@ -30,6 +30,9 @@ include_directories(${LLVM_INCLUDE_DIR}) file(GLOB_RECURSE SOURCE_FILES ${PROJECT_SOURCE_DIR}/src/*.c) list(REMOVE_ITEM SOURCE_FILES ${PROJECT_SOURCE_DIR}/src/main.c) +list(REMOVE_ITEM SOURCE_FILES ${PROJECT_SOURCE_DIR}/src/yacc/parser.tab.c) +list(REMOVE_ITEM SOURCE_FILES ${PROJECT_SOURCE_DIR}/src/lex/lexer.ll.c) +list(REMOVE_ITEM SOURCE_FILES ${PROJECT_SOURCE_DIR}/src/lex/util.c) add_executable(global_vars global_vars.c ${SOURCE_FILES}) set_target_properties(global_vars From 68622fbd001a58d493f567dd45ba39ebc3590302 Mon Sep 17 00:00:00 2001 From: servostar Date: Mon, 27 May 2024 23:50:29 +0200 Subject: [PATCH 038/124] added function parsing --- src/llvm/func.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 src/llvm/func.c diff --git a/src/llvm/func.c b/src/llvm/func.c new file mode 100644 index 0000000..5ac63d8 --- /dev/null +++ b/src/llvm/func.c @@ -0,0 +1,81 @@ + +#include +#include +#include +#include +#include +#include +#include +#include + +BackendError impl_param_type(LLVMBackendCompileUnit* unit, + LLVMGlobalScope* scope, Paramer* param, + LLVMTypeRef* llvm_type) { + BackendError err = SUCCESS; + + Type* gemstone_type = NULL; + IO_Qualifier qualifier = In; + + if (param->kind == ParameterDeclarationKind) { + gemstone_type = ¶m->impl.declaration.type; + qualifier = param->impl.declaration.qualifier; + } else { + gemstone_type = ¶m->impl.definiton.declaration.type; + qualifier = param->impl.definiton.declaration.qualifier; + } + + // wrap output variables as pointers + if (qualifier == Out || qualifier == InOut) { + Type* reference_type = alloca(sizeof(Type)); + + reference_type->kind = TypeKindReference; + reference_type->impl.reference = gemstone_type; + + gemstone_type = reference_type; + } + + err = get_type_impl(unit, scope, gemstone_type, llvm_type); + + return err; +} + +BackendError impl_func_decl(LLVMBackendCompileUnit* unit, + LLVMGlobalScope* scope, FunctionDefinition* fundef, + LLVMValueRef* llvm_fun, const char* name) { + DEBUG("implementing function declaration: %s()", name); + BackendError err = SUCCESS; + + Paramer* params = (Paramer*)fundef->parameter; + GArray* llvm_params = g_array_new(FALSE, FALSE, sizeof(LLVMTypeRef)); + + for (size_t i = 0; i < fundef->parameter->len; i++) { + Paramer* param = ¶ms[i]; + + LLVMTypeRef llvm_type = NULL; + err = impl_param_type(unit, scope, param, &llvm_type); + + if (err.kind != Success) { + break; + } + } + + DEBUG("implemented %ld parameter", llvm_params->len); + + LLVMTypeRef llvm_fun_type = + LLVMFunctionType(LLVMVoidTypeInContext(unit->context), + (LLVMTypeRef*)llvm_params->data, llvm_params->len, 0); + + *llvm_fun = LLVMAddFunction(unit->module, name, llvm_fun_type); + + g_array_free(llvm_params, FALSE); + + return err; +} + +BackendError impl_func(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, + FunctionDefinition* fundef, const char* name) { + BackendError err = SUCCESS; + + + return err; +} From 0d1f312ae214a36ebdc08455ac3bbba25c8e3cce Mon Sep 17 00:00:00 2001 From: servostar Date: Tue, 28 May 2024 00:12:32 +0200 Subject: [PATCH 039/124] fixed: various implementation faults fixed typo of parameter added function struct to group their declaration and definitons added block to function definiton added operands to cast and operators --- src/set/types.h | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/set/types.h b/src/set/types.h index 52744a1..6fcc02c 100644 --- a/src/set/types.h +++ b/src/set/types.h @@ -69,6 +69,8 @@ typedef Type* ReferenceType; typedef struct BoxType_t BoxType; +typedef struct Block_t Block; + typedef struct BoxMember_t { const char* name; Type* type; @@ -88,6 +90,7 @@ typedef struct BoxType_t { } BoxType; typedef struct Variable_t Variable; +typedef struct Expression_t Expression; typedef struct BoxAccess_t { // list of recursive box accesses @@ -168,7 +171,7 @@ typedef struct ParameterDefinition_t { ParameterDeclaration declaration; // value to initalize the declaration with // NOTE: type of initializer and declaration MUST be equal - TypeValue initializer; + Expression initializer; AST_NODE_PTR nodePtr; } ParameterDefinition; @@ -189,15 +192,37 @@ typedef struct Parameter_t { ParameterDefinition definiton; } impl; AST_NODE_PTR nodePtr; -} Paramer; +} Parameter; // fix typo + +typedef enum FunctionKind_t { + FunctionDeclarationKind, + FunctionDefinitionKind +} FunctionKind; typedef struct FunctionDefinition_t { // hashtable of parameters // associates a parameters name (const char*) with its parameter declaration (ParameterDeclaration) GArray* parameter; AST_NODE_PTR nodePtr; + // body of function + Block body; } FunctionDefinition; +typedef struct FunctionDeclaration_t { + // hashtable of parameters + // associates a parameters name (const char*) with its parameter declaration (ParameterDeclaration) + GArray* parameter; + AST_NODE_PTR nodePtr; +} FunctionDeclaration; + +typedef struct Function_t { + FunctionKind kind; + union FunctionImplementation { + FunctionDefinition definition; + FunctionDeclaration declaration; + } impl; +} Function; + // .------------------------------------------------. // | Variables | // '------------------------------------------------' @@ -222,7 +247,7 @@ typedef struct VariableDeclaration_t { */ typedef struct VariableDefiniton_t { VariableDeclaration declaration; - TypeValue initializer; + Expression initializer; AST_NODE_PTR nodePtr; } VariableDefiniton; @@ -258,6 +283,7 @@ typedef struct Variable_t { */ typedef struct TypeCast_t { Type targetType; + Expression* operand; AST_NODE_PTR nodePtr; } TypeCast; @@ -270,6 +296,7 @@ typedef struct TypeCast_t { */ typedef struct Transmute_t { Type targetType; + Expression* operand; AST_NODE_PTR nodePtr; } Transmute; @@ -358,6 +385,7 @@ typedef struct Operation_t { LogicalOperator logical; BitwiseOperator bitwise; } impl; + Expression* operands; AST_NODE_PTR nodePtr; } Operation; From 48110c85f20745d1b7461d10e6c4113f8f75bce5 Mon Sep 17 00:00:00 2001 From: servostar Date: Tue, 28 May 2024 11:51:24 +0200 Subject: [PATCH 040/124] added function definition block --- src/llvm/func.c | 35 ++++++++++++++++++++++++++++++++++- src/llvm/parser.h | 15 ++------------- 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/src/llvm/func.c b/src/llvm/func.c index 5ac63d8..c9a4e65 100644 --- a/src/llvm/func.c +++ b/src/llvm/func.c @@ -7,6 +7,7 @@ #include #include #include +#include BackendError impl_param_type(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, Paramer* param, @@ -72,10 +73,42 @@ BackendError impl_func_decl(LLVMBackendCompileUnit* unit, return err; } -BackendError impl_func(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, +BackendError impl_func(LLVMBackendCompileUnit* unit, LLVMGlobalScope* global_scope, FunctionDefinition* fundef, const char* name) { BackendError err = SUCCESS; + LLVMValueRef llvm_func = NULL; + err = impl_func_decl(unit, global_scope, fundef, &llvm_func, name); + + if (err.kind == Success) { + // create local function scope + // NOTE: lives till the end of the function + LLVMFuncScope* func_scope = alloca(sizeof(LLVMFuncScope)); + + func_scope->llvm_func = llvm_func; + func_scope->global_scope = global_scope; + func_scope->params = g_hash_table_new(g_str_hash, g_str_equal); + + // store function type in global scope + g_hash_table_insert(global_scope->functions, (gpointer) name, llvm_func); + + // create function body builder + LLVMBasicBlockRef body = LLVMAppendBasicBlockInContext(unit->context, llvm_func, "entry"); + LLVMBuilderRef builder = LLVMCreateBuilderInContext(unit->context); + LLVMPositionBuilderAtEnd(builder, body); + + // create value references for parameter + const size_t params = fundef->parameter->len; + for (size_t i = 0; i < params; i++) { + const Paramer* param = ((Paramer*) fundef->parameter) + i; + g_hash_table_insert(func_scope->params, (gpointer) param->name, LLVMGetParam(llvm_func, i)); + } + + // parse function body + + // delete function scope GLib structs + g_hash_table_destroy(func_scope->params); + } return err; } diff --git a/src/llvm/parser.h b/src/llvm/parser.h index 9a51e60..f045f43 100644 --- a/src/llvm/parser.h +++ b/src/llvm/parser.h @@ -14,7 +14,9 @@ typedef struct LLVMBackendCompileUnit_t { typedef struct LLVMGlobalScope_t { GHashTable* types; + // of type LLVMValueRef GHashTable* variables; + // of type LLVMTypeRef GHashTable* functions; } LLVMGlobalScope; @@ -22,19 +24,6 @@ LLVMGlobalScope* new_global_scope(); void delete_global_scope(LLVMGlobalScope* scope); -typedef struct LLVMLocalScope_t LLVMLocalScope; - -typedef struct LLVMLocalScope_t { - LLVMGlobalScope* global_scope; - LLVMLocalScope* parent_scope; - GHashTable* params; - GHashTable* variables; -} LLVMLocalScope; - -LLVMLocalScope* new_local_scope(LLVMGlobalScope* global_scope, LLVMLocalScope* parent_scope); - -void delete_local_scope(LLVMLocalScope* scope); - BackendError parse_module(const Module* module, void**); #endif // LLVM_BACKEND_PARSE_H_ From 1aa82062687510dc689d59868e58299eb0175d26 Mon Sep 17 00:00:00 2001 From: servostar Date: Tue, 28 May 2024 12:36:33 +0200 Subject: [PATCH 041/124] fixed: missing kind in statement --- src/set/types.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/set/types.h b/src/set/types.h index 52744a1..aedb167 100644 --- a/src/set/types.h +++ b/src/set/types.h @@ -471,6 +471,7 @@ typedef enum StatementKind_t { } StatementKind; typedef struct Statement_t { + StatementKind kind; union StatementImplementation { FunctionCall call; FunctionBoxCall boxCall; From 9eddfd75bc7440133c7d0a487be672aa432c5b3c Mon Sep 17 00:00:00 2001 From: servostar Date: Tue, 28 May 2024 13:32:56 +0200 Subject: [PATCH 042/124] added assign implementation --- src/llvm/func.c | 20 ++++++++++++++++++++ src/llvm/stmt.c | 28 ++++++++++++++++++++++++++++ src/llvm/stmt.h | 9 +++++++++ 3 files changed, 57 insertions(+) create mode 100644 src/llvm/stmt.c create mode 100644 src/llvm/stmt.h diff --git a/src/llvm/func.c b/src/llvm/func.c index c9a4e65..5c6024d 100644 --- a/src/llvm/func.c +++ b/src/llvm/func.c @@ -9,6 +9,26 @@ #include #include +static LLVMValueRef get_parameter(const LLVMFuncScope* scope, const char* name) { + if (g_hash_table_contains(scope->params, name)) { + return g_hash_table_lookup(scope->params, name); + } + + return NULL; +} + +LLVMValueRef get_variable(const LLVMLocalScope* scope, const char* name) { + if (g_hash_table_contains(scope->vars, name)) { + return g_hash_table_lookup(scope->vars, name); + } + + if (scope->parent_scope != NULL) { + return get_variable(scope->parent_scope, name); + } + + return get_parameter(scope->func_scope, name); +} + BackendError impl_param_type(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, Paramer* param, LLVMTypeRef* llvm_type) { diff --git a/src/llvm/stmt.c b/src/llvm/stmt.c new file mode 100644 index 0000000..98fec0f --- /dev/null +++ b/src/llvm/stmt.c @@ -0,0 +1,28 @@ +// +// Created by servostar on 5/28/24. +// + +#include +#include +#include +#include + +BackendError impl_assign_stmt(LLVMBackendCompileUnit* unit, + LLVMBuilderRef builder, LLVMLocalScope* scope, + Assignment* assignment) { + // TODO: resolve expression to LLVMValueRef + const LLVMValueRef llvm_value = NULL; + + switch (assignment->variable->kind) { + case VariableKindDeclaration: + case VariableKindDefinition: + const LLVMValueRef llvm_ptr = + get_variable(scope, assignment->variable->name); + LLVMBuildStore(builder, llvm_value, llvm_ptr); + break; + case VariableKindBoxMember: + break; + } +} + +BackendError impl_stmt(LLVMBackendCompileUnit* unit, Statement* stmt) {} diff --git a/src/llvm/stmt.h b/src/llvm/stmt.h new file mode 100644 index 0000000..bde984d --- /dev/null +++ b/src/llvm/stmt.h @@ -0,0 +1,9 @@ +// +// Created by servostar on 5/28/24. +// + +#ifndef LLVM_BACKEND_STMT_H +#define LLVM_BACKEND_STMT_H + + +#endif // LLVM_BACKEND_STMT_H From f590e3c42ea94f81cd06ca5ef8aba892ace07111 Mon Sep 17 00:00:00 2001 From: servostar Date: Tue, 28 May 2024 13:44:40 +0200 Subject: [PATCH 043/124] fixed: missing box member access in assignment --- src/set/types.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/set/types.h b/src/set/types.h index 828783a..cc230f0 100644 --- a/src/set/types.h +++ b/src/set/types.h @@ -484,8 +484,22 @@ typedef struct Branch_t { // | Statements | // '------------------------------------------------' +typedef enum AssignmentKind_t { + // direct access to a variable + AssignmentKindVariable, + // access to a member of a box + // can be nested such as: foo.bar.kee + AssignmentKindBoxMember +} AssignmentKind; + +// Can either be a direct variable access or +// a nested box member access typedef struct Assignment_t { Variable* variable; + AssignmentKind kind; + union AssignmentImplementation_t { + BoxAccess accees; + } impl; Expression value; AST_NODE_PTR nodePtr; } Assignment; From 0fe3fb68a6a482295686d394d15992dabdb53fda Mon Sep 17 00:00:00 2001 From: servostar Date: Tue, 28 May 2024 13:57:13 +0200 Subject: [PATCH 044/124] reverted: removed box access from assignment --- src/set/types.h | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/src/set/types.h b/src/set/types.h index cc230f0..0b92e2b 100644 --- a/src/set/types.h +++ b/src/set/types.h @@ -96,6 +96,8 @@ typedef struct BoxAccess_t { // list of recursive box accesses // contains a list of BoxMembers (each specifying their own type, name and box type) GArray* member; + // box variable to access + Variable* variable; AST_NODE_PTR nodePtr; } BoxAccess; @@ -263,7 +265,7 @@ typedef struct Variable_t { union VariableImplementation { VariableDeclaration declaration; VariableDefiniton definiton; - BoxMember member; + BoxAccess member; } impl; AST_NODE_PTR nodePtr; } Variable; @@ -484,22 +486,8 @@ typedef struct Branch_t { // | Statements | // '------------------------------------------------' -typedef enum AssignmentKind_t { - // direct access to a variable - AssignmentKindVariable, - // access to a member of a box - // can be nested such as: foo.bar.kee - AssignmentKindBoxMember -} AssignmentKind; - -// Can either be a direct variable access or -// a nested box member access typedef struct Assignment_t { Variable* variable; - AssignmentKind kind; - union AssignmentImplementation_t { - BoxAccess accees; - } impl; Expression value; AST_NODE_PTR nodePtr; } Assignment; From 5fae7a12c10c99ed6ffff30ba1bfc6188418cf12 Mon Sep 17 00:00:00 2001 From: servostar Date: Tue, 28 May 2024 15:34:21 +0200 Subject: [PATCH 045/124] added: expressions --- src/llvm/expr.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++ src/llvm/expr.h | 16 ++++++++++ src/llvm/stmt.c | 17 +++++++--- src/llvm/types.c | 65 ++++++++++++++++++++++++++++++++++++++ src/llvm/types.h | 4 +++ 5 files changed, 179 insertions(+), 5 deletions(-) create mode 100644 src/llvm/expr.c create mode 100644 src/llvm/expr.h diff --git a/src/llvm/expr.c b/src/llvm/expr.c new file mode 100644 index 0000000..959936b --- /dev/null +++ b/src/llvm/expr.c @@ -0,0 +1,82 @@ +// +// Created by servostar on 5/28/24. +// + +#include +#include + +BackendError impl_transmute(LLVMBackendCompileUnit* unit, LLVMLocalScope* scope, + LLVMBuilderRef builder, Transmute* transmute, + LLVMValueRef* llvm_result) { + // TODO: resolve sub expression + LLVMValueRef operand = NULL; + LLVMTypeRef target_type = NULL; + BackendError err = get_type_impl(unit, scope->func_scope->global_scope, + &transmute->targetType, &target_type); + // if target type is valid + if (err.kind == Success) { + *llvm_result = + LLVMBuildBitCast(builder, operand, target_type, "transmute"); + } + + return err; +} + +static LLVMBool is_type_signed(const Type* type) { + switch (type->kind) { + case TypeKindPrimitive: + return 1; + case TypeKindComposite: + return type->impl.composite.sign == Signed; + default: + return 0; + } +} + +BackendError impl_typecast(LLVMBackendCompileUnit* unit, LLVMLocalScope* scope, + LLVMBuilderRef builder, TypeCast* typecast, + LLVMValueRef* llvm_result) { + // TODO: resolve sub expression + LLVMValueRef operand = NULL; + LLVMTypeRef target_type = NULL; + BackendError err = get_type_impl(unit, scope->func_scope->global_scope, + &typecast->targetType, &target_type); + // if target type is valid + if (err.kind != Success) { + return err; + } + + LLVMBool dst_signed = is_type_signed(&typecast->targetType); + // TODO: derive source type sign + const LLVMOpcode opcode = + LLVMGetCastOpcode(operand, 0, target_type, dst_signed); + *llvm_result = + LLVMBuildCast(builder, opcode, operand, target_type, "transmute"); + + return err; +} +BackendError impl_expr(LLVMBackendCompileUnit* unit, LLVMLocalScope* scope, + LLVMBuilderRef builder, Expression* expr, + LLVMValueRef* llvm_result) { + BackendError err = SUCCESS; + + switch (expr->kind) { + case ExpressionKindConstant: + err = get_type_value(unit, scope->func_scope->global_scope, + &expr->impl.constant, llvm_result); + break; + case ExpressionKindTransmute: + err = impl_transmute(unit, scope, builder, &expr->impl.transmute, + llvm_result); + break; + case ExpressionKindTypeCast: + err = impl_typecast(unit, scope, builder, &expr->impl.typecast, + llvm_result); + break; + case ExpressionKindOperation: + + break; + } + + return err; +} \ No newline at end of file diff --git a/src/llvm/expr.h b/src/llvm/expr.h new file mode 100644 index 0000000..204b807 --- /dev/null +++ b/src/llvm/expr.h @@ -0,0 +1,16 @@ +// +// Created by servostar on 5/28/24. +// + +#ifndef LLVM_BACKEND_EXPR_H +#define LLVM_BACKEND_EXPR_H + +#include +#include +#include +#include + +BackendError impl_expr(LLVMBackendCompileUnit* unit, LLVMLocalScope* scope, + Expression* expr, LLVMValueRef* llvm_result); + +#endif // LLVM_BACKEND_EXPR_H diff --git a/src/llvm/stmt.c b/src/llvm/stmt.c index 98fec0f..471360c 100644 --- a/src/llvm/stmt.c +++ b/src/llvm/stmt.c @@ -6,10 +6,14 @@ #include #include #include +#include BackendError impl_assign_stmt(LLVMBackendCompileUnit* unit, - LLVMBuilderRef builder, LLVMLocalScope* scope, - Assignment* assignment) { + const LLVMBuilderRef builder, const LLVMLocalScope* scope, + const Assignment* assignment) { + BackendError err = SUCCESS; + DEBUG("implementing assignment for variabel: %s", assignment->variable->name); + // TODO: resolve expression to LLVMValueRef const LLVMValueRef llvm_value = NULL; @@ -18,11 +22,14 @@ BackendError impl_assign_stmt(LLVMBackendCompileUnit* unit, case VariableKindDefinition: const LLVMValueRef llvm_ptr = get_variable(scope, assignment->variable->name); - LLVMBuildStore(builder, llvm_value, llvm_ptr); - break; + LLVMBuildStore(builder, llvm_value, llvm_ptr); + break; case VariableKindBoxMember: - break; + // TODO: resolve LLVMValueRef from BoxAccess + break; } + + return err; } BackendError impl_stmt(LLVMBackendCompileUnit* unit, Statement* stmt) {} diff --git a/src/llvm/types.c b/src/llvm/types.c index bc95f83..65fd661 100644 --- a/src/llvm/types.c +++ b/src/llvm/types.c @@ -9,6 +9,71 @@ #define BASE_BYTES 4 #define BITS_PER_BYTE 8 +static BackendError get_const_primitive_value(PrimitiveType primitive, + LLVMTypeRef llvm_type, + const char* value, + LLVMValueRef* llvm_value) { + switch (primitive) { + case Int: + *llvm_value = LLVMConstIntOfString(llvm_type, value, 10); + break; + case Float: + *llvm_value = LLVMConstRealOfString(llvm_type, value); + break; + } + + return SUCCESS; +} + +static BackendError get_const_composite_value(CompositeType composite, + LLVMTypeRef llvm_type, + const char* value, + LLVMValueRef* llvm_value) { + return get_const_primitive_value(composite.primitive, llvm_type, value, + llvm_value); +} + +BackendError get_const_type_value(LLVMBackendCompileUnit* unit, + LLVMGlobalScope* scope, + TypeValue* gemstone_value, + LLVMValueRef* llvm_value) { + BackendError err = new_backend_impl_error( + Implementation, gemstone_value->nodePtr, "No default value for type"); + + LLVMTypeRef llvm_type = NULL; + err = get_type_impl(unit, scope, &gemstone_value->type, &llvm_type); + if (err.kind != Success) { + return err; + } + + switch (gemstone_value->type.kind) { + case TypeKindPrimitive: + err = get_const_primitive_value(gemstone_value->type.impl.primitive, + llvm_type, gemstone_value->value, + llvm_value); + break; + case TypeKindComposite: + err = get_const_composite_value(gemstone_value->type.impl.composite, + llvm_type, gemstone_value->value, + llvm_value); + break; + case TypeKindReference: + err = + new_backend_impl_error(Implementation, gemstone_value->nodePtr, + "reference cannot be constant value"); + break; + case TypeKindBox: + err = + new_backend_impl_error(Implementation, gemstone_value->nodePtr, + "boxes cannot be constant value"); + break; + default: + PANIC("invalid value kind: %ld", gemstone_value->type.kind); + } + + return err; +} + BackendError impl_primtive_type(LLVMBackendCompileUnit* unit, PrimitiveType primtive, LLVMTypeRef* llvm_type) { diff --git a/src/llvm/types.h b/src/llvm/types.h index c8a873b..edd8b66 100644 --- a/src/llvm/types.h +++ b/src/llvm/types.h @@ -18,4 +18,8 @@ BackendError get_type_default_value(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, Type* gemstone_type, LLVMValueRef* llvm_value); +BackendError get_type_value(LLVMBackendCompileUnit* unit, + LLVMGlobalScope* scope, TypeValue* gemstone_value, + LLVMValueRef* llvm_value); + #endif // LLVM_BACKEND_TYPES_H_ From f9eacef52f2756fa5a02875d100879a99eb002ae Mon Sep 17 00:00:00 2001 From: servostar Date: Tue, 28 May 2024 15:58:30 +0200 Subject: [PATCH 046/124] added bitwise operators --- src/llvm/expr.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) diff --git a/src/llvm/expr.c b/src/llvm/expr.c index 959936b..113b1d1 100644 --- a/src/llvm/expr.c +++ b/src/llvm/expr.c @@ -5,6 +5,90 @@ #include #include +BackendError impl_bitwise_operation(LLVMBackendCompileUnit* unit, + LLVMLocalScope* scope, + LLVMBuilderRef builder, + Operation* operation, + LLVMValueRef* llvm_result) { + // TODO: resolve lhs and rhs or op + LLVMValueRef rhs = NULL; + LLVMValueRef lhs = NULL; + LLVMValueRef op = NULL; + + if (operation->kind == BitwiseNot) { + // single operand + } else { + // two operands + } + + switch (operation->impl.bitwise) { + case BitwiseAnd: + *llvm_result = LLVMBuildAnd(builder, lhs, rhs, "bitwise and"); + break; + case BitwiseOr: + *llvm_result = LLVMBuildOr(builder, lhs, rhs, "bitwise or"); + break; + case BitwiseXor: + *llvm_result = LLVMBuildXor(builder, lhs, rhs, "bitwise xor"); + break; + case BitwiseNot: + *llvm_result = LLVMBuildNot(builder, rhs, "bitwise not"); + break; + } + + return SUCCESS; +} + +BackendError impl_logical_operation(LLVMBackendCompileUnit* unit, + LLVMLocalScope* scope, + LLVMBuilderRef builder, + Operation* operation, + LLVMValueRef* llvm_result) { + // TODO: resolve lhs and rhs or op + LLVMValueRef rhs = NULL; + LLVMValueRef lhs = NULL; + LLVMValueRef op = NULL; + + if (operation->kind == BitwiseNot) { + // single operand + } else { + // two operands + } + + switch (operation->impl.bitwise) { + case LogicalAnd: + // TODO: convert to either 0 or 1 + *llvm_result = LLVMBuildAnd(builder, lhs, rhs, "logical and"); + break; + case LogicalOr: + *llvm_result = LLVMBuildOr(builder, lhs, rhs, "logical or"); + break; + case LogicalXor: + *llvm_result = LLVMBuildXor(builder, lhs, rhs, "logical xor"); + break; + case LogicalNot: + *llvm_result = LLVMBuildNot(builder, rhs, "logical not"); + break; + } + + return SUCCESS; +} + +BackendError impl_operation(LLVMBackendCompileUnit* unit, LLVMLocalScope* scope, + LLVMBuilderRef builder, Operation* operation, + LLVMValueRef* llvm_result) { + switch (operation->kind) { + case Bitwise: + impl_bitwise_operation(unit, scope, builder, operation, + llvm_result); + break; + case Logical: + impl_logical_operation(unit, scope, builder, operation, + llvm_result); + break; + } +} + BackendError impl_transmute(LLVMBackendCompileUnit* unit, LLVMLocalScope* scope, LLVMBuilderRef builder, Transmute* transmute, LLVMValueRef* llvm_result) { @@ -74,7 +158,8 @@ BackendError impl_expr(LLVMBackendCompileUnit* unit, LLVMLocalScope* scope, llvm_result); break; case ExpressionKindOperation: - + err = impl_operation(unit, scope, builder, &expr->impl.operation, + llvm_result); break; } From 28a4f619a0f035164ed27acc4e2ae47ec5cc54b9 Mon Sep 17 00:00:00 2001 From: servostar Date: Tue, 28 May 2024 22:10:04 +0200 Subject: [PATCH 047/124] fixed: added missing header func.h --- src/llvm/func.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/llvm/func.h diff --git a/src/llvm/func.h b/src/llvm/func.h new file mode 100644 index 0000000..ac27a83 --- /dev/null +++ b/src/llvm/func.h @@ -0,0 +1,27 @@ + +#ifndef LLVM_BACKEND_FUNC_H_ +#define LLVM_BACKEND_FUNC_H_ + +#include + +#include + +typedef struct LLVMFuncScope_t { + LLVMGlobalScope* global_scope; + // of LLVMTypeRef + GHashTable* params; + LLVMValueRef llvm_func; +} LLVMFuncScope; + +typedef struct LLVMLocalScope_t LLVMLocalScope; + +typedef struct LLVMLocalScope_t { + // of LLVMTypeRef + GHashTable* vars; + LLVMFuncScope* func_scope; + LLVMLocalScope* parent_scope; +} LLVMLocalScope; + +LLVMValueRef get_variable(const LLVMLocalScope* scope, const char* name); + +#endif // LLVM_BACKEND_FUNC_H_ From 3ba11ec97bb190dd7a462cc6fe80914518c72e3c Mon Sep 17 00:00:00 2001 From: servostar Date: Tue, 28 May 2024 23:12:56 +0200 Subject: [PATCH 048/124] feature: added logical operators --- src/llvm/expr.c | 72 +++++++++++++++++++++++++++++++---------------- src/llvm/parser.c | 19 ------------- 2 files changed, 47 insertions(+), 44 deletions(-) diff --git a/src/llvm/expr.c b/src/llvm/expr.c index 113b1d1..3dc3cd4 100644 --- a/src/llvm/expr.c +++ b/src/llvm/expr.c @@ -5,17 +5,17 @@ #include #include -BackendError impl_bitwise_operation(LLVMBackendCompileUnit* unit, - LLVMLocalScope* scope, +BackendError impl_bitwise_operation(LLVMBackendCompileUnit *unit, + LLVMLocalScope *scope, LLVMBuilderRef builder, - Operation* operation, - LLVMValueRef* llvm_result) { + Operation *operation, + LLVMValueRef *llvm_result) { // TODO: resolve lhs and rhs or op LLVMValueRef rhs = NULL; LLVMValueRef lhs = NULL; LLVMValueRef op = NULL; - if (operation->kind == BitwiseNot) { + if (operation->impl.bitwise == BitwiseNot) { // single operand } else { // two operands @@ -39,11 +39,29 @@ BackendError impl_bitwise_operation(LLVMBackendCompileUnit* unit, return SUCCESS; } -BackendError impl_logical_operation(LLVMBackendCompileUnit* unit, - LLVMLocalScope* scope, +/** + * @brief Convert any integral type (integer) to a boolean value. + * A boolean value hereby meaning an integer of the same type as the input + * value but with the value of either 0 or one. + * @param builder + * @param integral + * @return + */ +static LLVMValueRef convert_integral_to_boolean( + LLVMBuilderRef builder, LLVMValueRef integral) { + // type of input + LLVMTypeRef valueType = LLVMTypeOf(integral); + // zero value of same type as integral + LLVMValueRef zero = LLVMConstIntOfString(valueType, "0", 10); + // returns 1 if integral is not zero and zero otherwise + return LLVMBuildICmp(builder, LLVMIntNE, zero, integral, "to boolean"); +} + +BackendError impl_logical_operation(LLVMBackendCompileUnit *unit, + LLVMLocalScope *scope, LLVMBuilderRef builder, - Operation* operation, - LLVMValueRef* llvm_result) { + Operation *operation, + LLVMValueRef *llvm_result) { // TODO: resolve lhs and rhs or op LLVMValueRef rhs = NULL; LLVMValueRef lhs = NULL; @@ -51,8 +69,11 @@ BackendError impl_logical_operation(LLVMBackendCompileUnit* unit, if (operation->kind == BitwiseNot) { // single operand + op = convert_integral_to_boolean(builder, op); } else { // two operands + lhs = convert_integral_to_boolean(builder, lhs); + rhs = convert_integral_to_boolean(builder, rhs); } switch (operation->impl.bitwise) { @@ -74,9 +95,9 @@ BackendError impl_logical_operation(LLVMBackendCompileUnit* unit, return SUCCESS; } -BackendError impl_operation(LLVMBackendCompileUnit* unit, LLVMLocalScope* scope, - LLVMBuilderRef builder, Operation* operation, - LLVMValueRef* llvm_result) { +BackendError impl_operation(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, + LLVMBuilderRef builder, Operation *operation, + LLVMValueRef *llvm_result) { switch (operation->kind) { case Bitwise: impl_bitwise_operation(unit, scope, builder, operation, @@ -89,9 +110,9 @@ BackendError impl_operation(LLVMBackendCompileUnit* unit, LLVMLocalScope* scope, } } -BackendError impl_transmute(LLVMBackendCompileUnit* unit, LLVMLocalScope* scope, - LLVMBuilderRef builder, Transmute* transmute, - LLVMValueRef* llvm_result) { +BackendError impl_transmute(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, + LLVMBuilderRef builder, Transmute *transmute, + LLVMValueRef *llvm_result) { // TODO: resolve sub expression LLVMValueRef operand = NULL; LLVMTypeRef target_type = NULL; @@ -100,13 +121,13 @@ BackendError impl_transmute(LLVMBackendCompileUnit* unit, LLVMLocalScope* scope, // if target type is valid if (err.kind == Success) { *llvm_result = - LLVMBuildBitCast(builder, operand, target_type, "transmute"); + LLVMBuildBitCast(builder, operand, target_type, "transmute"); } return err; } -static LLVMBool is_type_signed(const Type* type) { +static LLVMBool is_type_signed(const Type *type) { switch (type->kind) { case TypeKindPrimitive: return 1; @@ -117,9 +138,9 @@ static LLVMBool is_type_signed(const Type* type) { } } -BackendError impl_typecast(LLVMBackendCompileUnit* unit, LLVMLocalScope* scope, - LLVMBuilderRef builder, TypeCast* typecast, - LLVMValueRef* llvm_result) { +BackendError impl_typecast(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, + LLVMBuilderRef builder, TypeCast *typecast, + LLVMValueRef *llvm_result) { // TODO: resolve sub expression LLVMValueRef operand = NULL; LLVMTypeRef target_type = NULL; @@ -133,15 +154,16 @@ BackendError impl_typecast(LLVMBackendCompileUnit* unit, LLVMLocalScope* scope, LLVMBool dst_signed = is_type_signed(&typecast->targetType); // TODO: derive source type sign const LLVMOpcode opcode = - LLVMGetCastOpcode(operand, 0, target_type, dst_signed); + LLVMGetCastOpcode(operand, 0, target_type, dst_signed); *llvm_result = - LLVMBuildCast(builder, opcode, operand, target_type, "transmute"); + LLVMBuildCast(builder, opcode, operand, target_type, "transmute"); return err; } -BackendError impl_expr(LLVMBackendCompileUnit* unit, LLVMLocalScope* scope, - LLVMBuilderRef builder, Expression* expr, - LLVMValueRef* llvm_result) { + +BackendError impl_expr(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, + LLVMBuilderRef builder, Expression *expr, + LLVMValueRef *llvm_result) { BackendError err = SUCCESS; switch (expr->kind) { diff --git a/src/llvm/parser.c b/src/llvm/parser.c index 0f22e17..4d00ac0 100644 --- a/src/llvm/parser.c +++ b/src/llvm/parser.c @@ -210,25 +210,6 @@ LLVMGlobalScope* new_global_scope() { return scope; } -LLVMLocalScope* new_local_scope(LLVMGlobalScope* global_scope, - LLVMLocalScope* parent_scope) { - DEBUG("creating local scope..."); - LLVMLocalScope* scope = malloc(sizeof(LLVMLocalScope)); - - scope->variables = g_hash_table_new(g_str_hash, g_str_equal); - scope->params = g_hash_table_new(g_str_hash, g_str_equal); - scope->global_scope = global_scope; - scope->parent_scope = parent_scope; - - return scope; -} - -void delete_local_scope(LLVMLocalScope* scope) { - DEBUG("deleting global scope..."); - g_hash_table_unref(scope->variables); - free(scope); -} - void delete_global_scope(LLVMGlobalScope* scope) { DEBUG("deleting global scope..."); g_hash_table_unref(scope->functions); From 1ac9664c4d3d105951195782632c79cc7cf09d11 Mon Sep 17 00:00:00 2001 From: servostar Date: Wed, 29 May 2024 09:02:46 +0200 Subject: [PATCH 049/124] finished implementing expressions --- src/llvm/expr.c | 154 ++++++++++++++++++++++++++++++++++++++++++++---- src/llvm/expr.h | 5 +- 2 files changed, 146 insertions(+), 13 deletions(-) diff --git a/src/llvm/expr.c b/src/llvm/expr.c index 3dc3cd4..c43c72c 100644 --- a/src/llvm/expr.c +++ b/src/llvm/expr.c @@ -4,6 +4,7 @@ #include #include +#include BackendError impl_bitwise_operation(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, @@ -13,7 +14,6 @@ BackendError impl_bitwise_operation(LLVMBackendCompileUnit *unit, // TODO: resolve lhs and rhs or op LLVMValueRef rhs = NULL; LLVMValueRef lhs = NULL; - LLVMValueRef op = NULL; if (operation->impl.bitwise == BitwiseNot) { // single operand @@ -65,11 +65,10 @@ BackendError impl_logical_operation(LLVMBackendCompileUnit *unit, // TODO: resolve lhs and rhs or op LLVMValueRef rhs = NULL; LLVMValueRef lhs = NULL; - LLVMValueRef op = NULL; - if (operation->kind == BitwiseNot) { + if (operation->kind == LogicalNot) { // single operand - op = convert_integral_to_boolean(builder, op); + rhs = convert_integral_to_boolean(builder, rhs); } else { // two operands lhs = convert_integral_to_boolean(builder, lhs); @@ -78,7 +77,6 @@ BackendError impl_logical_operation(LLVMBackendCompileUnit *unit, switch (operation->impl.bitwise) { case LogicalAnd: - // TODO: convert to either 0 or 1 *llvm_result = LLVMBuildAnd(builder, lhs, rhs, "logical and"); break; case LogicalOr: @@ -95,19 +93,153 @@ BackendError impl_logical_operation(LLVMBackendCompileUnit *unit, return SUCCESS; } +static LLVMBool is_floating_point(LLVMValueRef value) { + LLVMTypeRef valueType = LLVMTypeOf(value); + LLVMTypeKind typeKind = LLVMGetTypeKind(valueType); + + return typeKind == LLVMFloatTypeKind || typeKind == LLVMHalfTypeKind || typeKind == LLVMDoubleTypeKind || + typeKind == LLVMFP128TypeKind; +} + +static LLVMBool is_integral(LLVMValueRef value) { + LLVMTypeRef valueType = LLVMTypeOf(value); + LLVMTypeKind typeKind = LLVMGetTypeKind(valueType); + + return typeKind == LLVMIntegerTypeKind; +} + +BackendError impl_relational_operation(LLVMBackendCompileUnit *unit, + LLVMLocalScope *scope, + LLVMBuilderRef builder, + Operation *operation, + LLVMValueRef *llvm_result) { + // TODO: resolve lhs and rhs or op + LLVMValueRef rhs = NULL; + LLVMValueRef lhs = NULL; + + if ((is_integral(lhs) && is_integral(rhs)) == 1) { + // integral type + LLVMIntPredicate operator = 0; + + switch (operation->impl.relational) { + case Equal: + operator = LLVMIntEQ; + break; + case Greater: + operator = LLVMIntSGT; + break; + case Less: + operator = LLVMIntSLT; + break; + } + + *llvm_result = LLVMBuildICmp(builder, operator, lhs, rhs, "integral comparison"); + } else if ((is_floating_point(lhs) && is_floating_point(rhs)) == 1) { + // integral type + LLVMRealPredicate operator = 0; + + switch (operation->impl.relational) { + case Equal: + operator = LLVMRealOEQ; + break; + case Greater: + operator = LLVMRealOGT; + break; + case Less: + operator = LLVMRealOLT; + break; + } + + *llvm_result = LLVMBuildFCmp(builder, operator, lhs, rhs, "floating point comparison"); + } else { + PANIC("invalid type for relational operator"); + } + + return SUCCESS; +} + +BackendError impl_arithmetic_operation(LLVMBackendCompileUnit *unit, + LLVMLocalScope *scope, + LLVMBuilderRef builder, + Operation *operation, + LLVMValueRef *llvm_result) { + // TODO: resolve lhs and rhs or op + LLVMValueRef rhs = NULL; + LLVMValueRef lhs = NULL; + + if ((is_integral(lhs) && is_integral(rhs)) == 1) { + // integral type + LLVMIntPredicate operator = 0; + + switch (operation->impl.arithmetic) { + case Add: + *llvm_result = LLVMBuildNSWAdd(builder, lhs, rhs, "signed integer addition"); + break; + case Sub: + *llvm_result = LLVMBuildNSWSub(builder, lhs, rhs, "signed integer subtraction"); + break; + case Mul: + *llvm_result = LLVMBuildNSWMul(builder, lhs, rhs, "signed integer multiply"); + break; + case Div: + *llvm_result = LLVMBuildSDiv(builder, lhs, rhs, "signed integer divide"); + break; + } + + } else if ((is_floating_point(lhs) && is_floating_point(rhs)) == 1) { + // integral type + LLVMRealPredicate operator = 0; + + switch (operation->impl.arithmetic) { + case Add: + *llvm_result = LLVMBuildFAdd(builder, lhs, rhs, "floating point addition"); + break; + case Sub: + *llvm_result = LLVMBuildFSub(builder, lhs, rhs, "floating point subtraction"); + break; + case Mul: + *llvm_result = LLVMBuildFMul(builder, lhs, rhs, "floating point multiply"); + break; + case Div: + *llvm_result = LLVMBuildFDiv(builder, lhs, rhs, "floating point divide"); + break; + } + + *llvm_result = LLVMBuildFCmp(builder, operator, lhs, rhs, "floating point comparison"); + } else { + PANIC("invalid type for arithmetic operator"); + } + + return SUCCESS; +} + BackendError impl_operation(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, LLVMBuilderRef builder, Operation *operation, LLVMValueRef *llvm_result) { + BackendError err; + switch (operation->kind) { case Bitwise: - impl_bitwise_operation(unit, scope, builder, operation, - llvm_result); + err = impl_bitwise_operation(unit, scope, builder, operation, + llvm_result); break; - case Logical: - impl_logical_operation(unit, scope, builder, operation, - llvm_result); + case Boolean: + err = impl_logical_operation(unit, scope, builder, operation, + llvm_result); break; + case Relational: + err = impl_relational_operation(unit, scope, builder, operation, + llvm_result); + break; + case Arithmetic: + err = impl_arithmetic_operation(unit, scope, builder, operation, + llvm_result); + break; + default: + PANIC("Invalid operator"); } + + return err; } BackendError impl_transmute(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, @@ -186,4 +318,4 @@ BackendError impl_expr(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, } return err; -} \ No newline at end of file +} diff --git a/src/llvm/expr.h b/src/llvm/expr.h index 204b807..c0c8d47 100644 --- a/src/llvm/expr.h +++ b/src/llvm/expr.h @@ -10,7 +10,8 @@ #include #include -BackendError impl_expr(LLVMBackendCompileUnit* unit, LLVMLocalScope* scope, - Expression* expr, LLVMValueRef* llvm_result); +BackendError impl_expr(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, + LLVMBuilderRef builder, Expression *expr, + LLVMValueRef *llvm_result); #endif // LLVM_BACKEND_EXPR_H From 61249d6eaf4b29a7caa6da63ed1b6ccb584760a8 Mon Sep 17 00:00:00 2001 From: servostar Date: Wed, 29 May 2024 13:03:39 +0200 Subject: [PATCH 050/124] feature: implemented while statement --- src/llvm/func.c | 19 ++++++++++++- src/llvm/func.h | 4 +++ src/llvm/stmt.c | 71 +++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 85 insertions(+), 9 deletions(-) diff --git a/src/llvm/func.c b/src/llvm/func.c index 5c6024d..dc6c8da 100644 --- a/src/llvm/func.c +++ b/src/llvm/func.c @@ -9,6 +9,21 @@ #include #include +LLVMLocalScope* new_local_scope(LLVMLocalScope* parent) { + LLVMLocalScope* scope = malloc(sizeof(LLVMLocalScope)); + + scope->func_scope = parent->func_scope; + scope->vars = g_hash_table_new(g_str_hash, g_str_equal); + scope->parent_scope = parent; + + return scope; +} + +void delete_local_scope(LLVMLocalScope* scope) { + g_hash_table_destroy(scope->vars); + free(scope); +} + static LLVMValueRef get_parameter(const LLVMFuncScope* scope, const char* name) { if (g_hash_table_contains(scope->params, name)) { return g_hash_table_lookup(scope->params, name); @@ -124,7 +139,9 @@ BackendError impl_func(LLVMBackendCompileUnit* unit, LLVMGlobalScope* global_sco g_hash_table_insert(func_scope->params, (gpointer) param->name, LLVMGetParam(llvm_func, i)); } - // parse function body + // TODO: parse function body + + LLVMDisposeBuilder(builder); // delete function scope GLib structs g_hash_table_destroy(func_scope->params); diff --git a/src/llvm/func.h b/src/llvm/func.h index ac27a83..e93eca4 100644 --- a/src/llvm/func.h +++ b/src/llvm/func.h @@ -22,6 +22,10 @@ typedef struct LLVMLocalScope_t { LLVMLocalScope* parent_scope; } LLVMLocalScope; +LLVMLocalScope* new_local_scope(LLVMLocalScope* parent); + +void delete_local_scope(LLVMLocalScope*); + LLVMValueRef get_variable(const LLVMLocalScope* scope, const char* name); #endif // LLVM_BACKEND_FUNC_H_ diff --git a/src/llvm/stmt.c b/src/llvm/stmt.c index 471360c..a77ffed 100644 --- a/src/llvm/stmt.c +++ b/src/llvm/stmt.c @@ -6,11 +6,12 @@ #include #include #include +#include #include -BackendError impl_assign_stmt(LLVMBackendCompileUnit* unit, - const LLVMBuilderRef builder, const LLVMLocalScope* scope, - const Assignment* assignment) { +BackendError impl_assign_stmt(LLVMBackendCompileUnit *unit, + const LLVMBuilderRef builder, const LLVMLocalScope *scope, + const Assignment *assignment) { BackendError err = SUCCESS; DEBUG("implementing assignment for variabel: %s", assignment->variable->name); @@ -21,15 +22,69 @@ BackendError impl_assign_stmt(LLVMBackendCompileUnit* unit, case VariableKindDeclaration: case VariableKindDefinition: const LLVMValueRef llvm_ptr = - get_variable(scope, assignment->variable->name); - LLVMBuildStore(builder, llvm_value, llvm_ptr); - break; + get_variable(scope, assignment->variable->name); + LLVMBuildStore(builder, llvm_value, llvm_ptr); + break; case VariableKindBoxMember: // TODO: resolve LLVMValueRef from BoxAccess - break; + break; } return err; } -BackendError impl_stmt(LLVMBackendCompileUnit* unit, Statement* stmt) {} +BackendError impl_basic_block(LLVMBackendCompileUnit *unit, + LLVMBuilderRef builder, LLVMLocalScope *scope, + const Block *block, LLVMBasicBlockRef *llvm_block) { + BackendError err = SUCCESS; + + LLVMLocalScope *block_scope = new_local_scope(scope); + // append a new LLVM basic block + *llvm_block = LLVMAppendBasicBlockInContext(unit->context, scope->func_scope->llvm_func, + "basic block"); + LLVMPositionBuilderAtEnd(builder, *llvm_block); + + for (size_t i = 0; i < block->statemnts->len; i++) { + Statement *stmt = ((Statement *) block->statemnts->data) + i; + + // TODO: implement statement + } + + delete_local_scope(block_scope); + + return err; +} + +BackendError impl_while(LLVMBackendCompileUnit *unit, + LLVMBuilderRef builder, LLVMLocalScope *scope, + const While *while_stmt) { + BackendError err; + + // Create condition block + LLVMBasicBlockRef while_cond_block = LLVMAppendBasicBlockInContext(unit->context, scope->func_scope->llvm_func, + "loop.while.cond"); + LLVMPositionBuilderAtEnd(builder, while_cond_block); + // Resolve condition in block to a variable + LLVMValueRef cond_result = NULL; + impl_expr(unit, scope, builder, &while_stmt->conditon, &cond_result); + + // build body of loop + LLVMBasicBlockRef while_body_block = NULL; + err = impl_basic_block(unit, builder, scope, &while_stmt->block, &while_body_block); + LLVMPositionBuilderAtEnd(builder, while_body_block); + // jump back to condition after body end + LLVMBuildBr(builder, while_cond_block); + + // builder will continue after the loop + LLVMBasicBlockRef while_after_block = LLVMAppendBasicBlockInContext(unit->context, scope->func_scope->llvm_func, + "loop.while.after"); + // build conditional branch at end of condition block + LLVMPositionBuilderAtEnd(builder, while_cond_block); + LLVMBuildCondBr(builder, cond_result, while_body_block, while_after_block); + + LLVMPositionBuilderAtEnd(builder, while_after_block); + + return err; +} + +BackendError impl_stmt(LLVMBackendCompileUnit *unit, Statement *stmt) {} From a5b5a04762a6b7217b43bce71102791e67222f01 Mon Sep 17 00:00:00 2001 From: servostar Date: Wed, 29 May 2024 21:17:13 +0200 Subject: [PATCH 051/124] feature: added function call --- src/llvm/stmt.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/llvm/stmt.c b/src/llvm/stmt.c index a77ffed..5b317e2 100644 --- a/src/llvm/stmt.c +++ b/src/llvm/stmt.c @@ -87,4 +87,49 @@ BackendError impl_while(LLVMBackendCompileUnit *unit, return err; } +BackendError impl_func_call(LLVMBackendCompileUnit *unit, + LLVMBuilderRef builder, LLVMLocalScope *scope, + const FunctionCall *call) { + BackendError err = SUCCESS; + + GArray *arguments = g_array_new(FALSE, FALSE, sizeof(LLVMValueRef)); + + for (size_t i = 0; i < call->expressions->len; i++) { + Expression *arg = ((Expression *) call->expressions->data) + i; + + LLVMValueRef llvm_arg = NULL; + err = impl_expr(unit, scope, builder, arg, &llvm_arg); + if (err.kind != Success) { + break; + } + + g_array_append_vals(arguments, &llvm_arg, 1); + } + + if (err.kind == Success) { + LLVMValueRef llvm_func = LLVMGetNamedFunction(unit->module, ""); + LLVMTypeRef llvm_func_type = LLVMTypeOf(llvm_func); + LLVMBuildCall2(builder, llvm_func_type, llvm_func, (LLVMValueRef *) arguments->data, arguments->len, + "stmt.call"); + } + + g_array_free(arguments, FALSE); + + return err; +} + +BackendError impl_branch(LLVMBackendCompileUnit *unit, + LLVMBuilderRef builder, LLVMLocalScope *scope, + const Branch *branch) { + BackendError err = SUCCESS; + + LLVMBasicBlockRef if_cond_block = LLVMAppendBasicBlockInContext(unit->context, scope->func_scope->llvm_func, + "stmt.branch.cond"); + // Resolve condition in block to a variable + LLVMValueRef cond_result = NULL; + impl_expr(unit, scope, builder, &branch->ifBranch.conditon, &cond_result); + + return err; +} + BackendError impl_stmt(LLVMBackendCompileUnit *unit, Statement *stmt) {} From 8494df56cd0e7107fdc7d9ba77f16f1ac934e93b Mon Sep 17 00:00:00 2001 From: servostar Date: Wed, 29 May 2024 21:21:03 +0200 Subject: [PATCH 052/124] feature: added name to function --- src/set/types.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/set/types.h b/src/set/types.h index 6fcc02c..974542e 100644 --- a/src/set/types.h +++ b/src/set/types.h @@ -206,6 +206,8 @@ typedef struct FunctionDefinition_t { AST_NODE_PTR nodePtr; // body of function Block body; + // name of function + const char* name; } FunctionDefinition; typedef struct FunctionDeclaration_t { From 875574eb690e2ee9f0ef22904de7c07b6a2d0955 Mon Sep 17 00:00:00 2001 From: servostar Date: Wed, 29 May 2024 21:24:17 +0200 Subject: [PATCH 053/124] fixed: added type to expressions --- src/set/types.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/set/types.h b/src/set/types.h index 974542e..1bead83 100644 --- a/src/set/types.h +++ b/src/set/types.h @@ -404,6 +404,8 @@ typedef enum ExpressionKind_t { typedef struct Expression_t { ExpressionKind kind; + // type of resulting data + Type* result; union ExpressionImplementation_t { Operation operation; TypeCast typecast; From 7e59ac35207dd961898603193b5d63b59e3b8738 Mon Sep 17 00:00:00 2001 From: servostar Date: Thu, 30 May 2024 13:11:51 +0200 Subject: [PATCH 054/124] feature: added if statement --- src/llvm/stmt.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 85 insertions(+), 5 deletions(-) diff --git a/src/llvm/stmt.c b/src/llvm/stmt.c index 5b317e2..9d23c07 100644 --- a/src/llvm/stmt.c +++ b/src/llvm/stmt.c @@ -118,16 +118,96 @@ BackendError impl_func_call(LLVMBackendCompileUnit *unit, return err; } +BackendError +impl_cond_block(LLVMBackendCompileUnit *unit, LLVMBuilderRef builder, LLVMLocalScope *scope, Expression *cond, + Block *block, LLVMBasicBlockRef *cond_block, LLVMBasicBlockRef *body_block, + LLVMValueRef *llvm_cond) { + BackendError err; + + *cond_block = LLVMAppendBasicBlockInContext(unit->context, scope->func_scope->llvm_func, + "stmt.branch.cond"); + LLVMPositionBuilderAtEnd(builder, *cond_block); + // Resolve condition in block to a variable + err = impl_expr(unit, scope, builder, cond, llvm_cond); + if (err.kind == Success) { + // build body of loop + err = impl_basic_block(unit, builder, scope, block, body_block); + } + + return err; +} + BackendError impl_branch(LLVMBackendCompileUnit *unit, LLVMBuilderRef builder, LLVMLocalScope *scope, const Branch *branch) { BackendError err = SUCCESS; - LLVMBasicBlockRef if_cond_block = LLVMAppendBasicBlockInContext(unit->context, scope->func_scope->llvm_func, - "stmt.branch.cond"); - // Resolve condition in block to a variable - LLVMValueRef cond_result = NULL; - impl_expr(unit, scope, builder, &branch->ifBranch.conditon, &cond_result); + GArray *cond_blocks = g_array_new(FALSE, FALSE, sizeof(LLVMBasicBlockRef)); + GArray *body_blocks = g_array_new(FALSE, FALSE, sizeof(LLVMBasicBlockRef)); + GArray *cond_values = g_array_new(FALSE, FALSE, sizeof(LLVMValueRef)); + + // add If to arrays + { + LLVMBasicBlockRef cond_block = NULL; + LLVMBasicBlockRef body_block = NULL; + LLVMValueRef cond_value = NULL; + + err = impl_cond_block(unit, builder, scope, &branch->ifBranch.conditon, &branch->ifBranch.block, &cond_block, + &body_block, &cond_value); + + g_array_append_val(cond_blocks, cond_block); + g_array_append_val(body_blocks, body_block); + g_array_append_val(cond_values, cond_value); + } + + // generate else if(s) + for (size_t i = 0; i < branch->elseIfBranches->len; i++) { + LLVMBasicBlockRef cond_block = NULL; + LLVMBasicBlockRef body_block = NULL; + LLVMValueRef cond_value = NULL; + + ElseIf *elseIf = ((ElseIf *) branch->elseIfBranches->data) + i; + + err = impl_cond_block(unit, builder, scope, &elseIf->conditon, &elseIf->block, &cond_block, + &body_block, &cond_value); + + g_array_append_val(cond_blocks, cond_block); + g_array_append_val(body_blocks, body_block); + g_array_append_val(cond_values, cond_value); + } + + // else block + if (branch->elseBranch.nodePtr != NULL) { + LLVMBasicBlockRef else_block = NULL; + err = impl_basic_block(unit, builder, scope, &branch->elseBranch.block, &else_block); + g_array_append_val(cond_blocks, else_block); + } + + LLVMBasicBlockRef after_block = LLVMAppendBasicBlockInContext(unit->context, scope->func_scope->llvm_func, + "stmt.branch.after"); + LLVMPositionBuilderAtEnd(builder, after_block); + // in case no else block is present + // make the after block the else + if (branch->elseBranch.nodePtr == NULL) { + g_array_append_val(cond_blocks, after_block); + } + + for (size_t i = 0; i < cond_blocks->len - 1; i++) { + LLVMBasicBlockRef next_block = ((LLVMBasicBlockRef*) cond_blocks->data)[i + 1]; + LLVMBasicBlockRef cond_block = ((LLVMBasicBlockRef*) cond_blocks->data)[i]; + LLVMBasicBlockRef body_block = ((LLVMBasicBlockRef*) body_blocks->data)[i]; + LLVMValueRef cond_value = ((LLVMValueRef*) cond_values->data)[i]; + + LLVMPositionBuilderAtEnd(builder, cond_block); + LLVMBuildCondBr(builder, cond_value, body_block, next_block); + + LLVMPositionBuilderAtEnd(builder, body_block); + LLVMBuildBr(builder, after_block); + } + + g_array_free(cond_blocks, TRUE); + g_array_free(body_blocks, TRUE); + g_array_free(cond_values, TRUE); return err; } From 5a06c17fa4b067fb4d1d418666adf9cf052444d8 Mon Sep 17 00:00:00 2001 From: Filleo Date: Fri, 31 May 2024 16:17:06 +0200 Subject: [PATCH 055/124] first implementation of the sematic analysis --- src/lex/lexer.l | 2 +- src/main.c | 3 +- src/set/set.c | 257 ++++++++++++++++++++++++++++++++++++++++++++++ src/set/set.h | 8 ++ src/set/types.h | 18 ++-- src/yacc/parser.y | 6 +- 6 files changed, 281 insertions(+), 13 deletions(-) create mode 100644 src/set/set.c create mode 100644 src/set/set.h diff --git a/src/lex/lexer.l b/src/lex/lexer.l index 7c0cc0c..3df609f 100644 --- a/src/lex/lexer.l +++ b/src/lex/lexer.l @@ -99,7 +99,7 @@ DEBUG("\"%s\" tokenized with \'ValStr\'", yytext); yylval.string = strdup(yytext); return(ValStr);}; \"\"\"([^\"\n]|\\\n)*\"\"\" { yytext = yytext +3; - yytext[yyleng - 4] = 0; + yytext[yyleng - 6] = 0; DEBUG("\"%s\" tokenized with \'ValMultistr\'", yytext); yylval.string = strdup(yytext); return(ValMultistr);}; [ \r\t] { /* ignore whitespace */ }; diff --git a/src/main.c b/src/main.c index 27bca44..9e349fe 100644 --- a/src/main.c +++ b/src/main.c @@ -4,6 +4,7 @@ #include #include #include +#include #define LOG_LEVEL LOG_LEVEL_DEBUG @@ -74,7 +75,7 @@ int main(int argc, char *argv[]) { root = AST_new_node(AST_Module, NULL); yyparse(); - + create_set(root); FILE *output = fopen("test.txt", "w"); AST_fprint_graphviz(output, root); fclose(output); diff --git a/src/set/set.c b/src/set/set.c new file mode 100644 index 0000000..bed1e4d --- /dev/null +++ b/src/set/set.c @@ -0,0 +1,257 @@ +#include +#include +#include +#include +#include +#include + +GHashTable *declaredComposites;//pointer to composites with names, +GHashTable *declaredBoxes;//pointer to typeboxes +GArray *Scope;//last object is current scope + + + + + + +Type *findType(AST_NODE_PTR currentNode){ + + const char *typekind = currentNode->children[currentNode->child_count -1]->value; + if (0 == strcmp(typekind, "int")||0 == strcmp(typekind, "float")){ + + Type *type = malloc(sizeof(Type)); + type->nodePtr = currentNode; + if(AST_Typekind != currentNode->children[0]->kind){ + DEBUG("Type is a Composite"); + type->kind = TypeKindComposite; + + + CompositeType composite; + composite.nodePtr = currentNode; + + + if(0 == strcmp(typekind, "int")){ + composite.primitive = Int; + }else{ + composite.primitive = Float; + } + composite.sign = Signed; + + size_t scalelist = 0; + if(AST_Sign == currentNode->children[0]->kind){ + if(0 == strcmp(currentNode->children[0]->value, "unsigned")){ + composite.sign = Unsigned; + } + scalelist = 1; + } + + composite.scale = 1.0; + if(AST_List == currentNode->children[scalelist]->kind){ + for (size_t i = 0; i < currentNode->children[scalelist]->child_count; i++){ + if (0 == strcmp(currentNode->children[scalelist]->children[i]->value, "short") || 0 == strcmp(currentNode->children[scalelist]->children[i]->value, "half")){ + composite.scale /= 2; + }else{ + composite.scale *= 2; + } + if (0.25 > composite.scale || 8 > composite.scale) { + //TODO scale not right + } + } + } + + type->impl.composite = composite; + + + }else{ + type->kind = TypeKindPrimitive; + if(0 == strcmp(typekind, "int")){ + type->impl.primitive = Int; + }else{ + type->impl.primitive = Float; + } + return type; + } + }else if(g_hash_table_contains(declaredBoxes, typekind)){ + if(AST_Typekind != currentNode->children[0]->kind){ + //TODO composite Box try + } + return (Type *) g_hash_table_lookup(declaredBoxes, typekind); + }else if(g_hash_table_contains(declaredComposites, typekind)){ + if(AST_Typekind != currentNode->children[0]->kind){ + Type *composite = malloc(sizeof(Type)); + + *composite = *(Type*) g_hash_table_lookup(declaredComposites, typekind); + + + + size_t scalelist = 0; + if(AST_Sign == currentNode->children[0]->kind){ + if(0 == strcmp(currentNode->children[0]->value, "unsigned")){ + composite->impl.composite.sign = Unsigned; + }else if(0 == strcmp(currentNode->children[0]->value, "unsigned")){ + composite->impl.composite.sign = Signed; + } + scalelist = 1; + } + + + if(AST_List == currentNode->children[scalelist]->kind){ + for (size_t i = 0; i < currentNode->children[scalelist]->child_count; i++){ + if (0 == strcmp(currentNode->children[scalelist]->children[i]->value, "short") || 0 == strcmp(currentNode->children[scalelist]->children[i]->value, "half")){ + composite->impl.composite.scale /= 2; + }else{ + composite->impl.composite.scale *= 2; + } + if (0.25 > composite->impl.composite.scale || 8 > composite->impl.composite.scale) { + //TODO scale not right + return NULL; + } + } + } + return composite; + } + return (Type *) g_hash_table_lookup(declaredComposites, typekind); + }else{ + //TODO doesnt know typekind + return NULL; + } + return NULL; +} + + + +StorageQualifier Qualifier_from_string(const char *str) { + if (!strncmp(str, "local", 5)) return Local; + if (!strncmp(str, "static", 6)) return Static; + if (!strncmp(str, "global", 6)) return Global; + PANIC("Provided string is not a storagequalifier: %s", str); +} + +Variable **create_decl(AST_NODE_PTR currentNode){ + DEBUG("create declaration"); + Variable **variables = malloc(currentNode->children[currentNode->child_count -1]->child_count * sizeof(Variable)); + + VariableDeclaration decl; + decl.nodePtr = currentNode; + + DEBUG("Child Count: %i", currentNode->child_count); + for (size_t i = 0; i < currentNode->child_count; i++){ + + switch(currentNode->children[i]->kind){ + case AST_Storage: + DEBUG("fill Qualifier"); + decl.qualifier = Qualifier_from_string(currentNode->children[i]->value); + break; + case AST_Type: + DEBUG("fill Type"); + decl.type = findType(currentNode->children[i]); + break; + case AST_IdentList: + for(size_t i = 0; i < currentNode->children[currentNode->child_count -1]->child_count; i++){ + Variable *variable = malloc(sizeof(Variable)); + variable->kind = VariableKindDeclaration; + variable->nodePtr = currentNode; + variable->name = currentNode->children[currentNode->child_count -1]->children[i]->value; + variable->impl.declaration = decl; + variables[i] = variable; + } + break; + default: + //TODO PANIC maybe + break; + } + } + + return variables; +} + +int isVariableInScope(const char* name){ + + for(size_t i = 0; i < Scope->len; i++){ + if(g_hash_table_contains(((GHashTable **) Scope->data)[i], name)) + { + return 1; + } + } + return 0; +} + +int fillTablesWithVars(GHashTable *variableTable,GHashTable *currentScope , Variable** content, size_t amount){ + DEBUG("filling vars in scope and table"); + for(size_t i = 0; i < amount; i++){ + if(isVariableInScope(content[i]->name)){ + DEBUG("this var already exist: ",content[i]->name); + return 1; + } + g_hash_table_insert(variableTable, (gpointer) content[i]->name, content[i] ); + g_hash_table_insert(currentScope, (gpointer) content[i]->name, content[i] ); + } + return 0; +} + + + + +Module *create_set(AST_NODE_PTR currentNode){ + DEBUG("create root Module"); + //create tables for types + declaredComposites = g_hash_table_new(g_str_hash,g_str_equal); + declaredBoxes = g_hash_table_new(g_str_hash,g_str_equal); + + //create scope + Scope = g_array_new(FALSE, FALSE, sizeof(GHashTable*)); + + + //building current scope for module + GHashTable *globalscope = malloc(sizeof(GHashTable*)); + globalscope = g_hash_table_new(g_str_hash,g_str_equal); + g_array_append_val(Scope, globalscope); + + Module *rootModule = malloc(sizeof(Module)); + + GHashTable *boxes = g_hash_table_new(g_str_hash,g_str_equal); + GHashTable *types = g_hash_table_new(g_str_hash,g_str_equal); + GHashTable *functions = g_hash_table_new(g_str_hash,g_str_equal); + GHashTable *variables = g_hash_table_new(g_str_hash,g_str_equal); + GArray *imports = g_array_new(FALSE, FALSE, sizeof(const char*)); + + rootModule->boxes = boxes; + rootModule->types = types; + rootModule->functions = functions; + rootModule->variables = variables; + rootModule->imports = imports; + + DEBUG("created Module struct"); + + + for (size_t i = 0; i < currentNode->child_count; i++){ + DEBUG("created Child: %i" ,currentNode->children[i]->kind); + switch(currentNode->children[i]->kind){ + + case AST_Decl: + if (1 == fillTablesWithVars(variables,globalscope,create_decl(currentNode->children[i]) ,currentNode->children[i]->children[currentNode->children[i]->child_count -1]->child_count)){ + //TODO behandlung, wenn var schon existiert + DEBUG("var already exists"); + break; + } + DEBUG("filled successfull the module and scope with vars"); + break; + case AST_Def: + case AST_Box: + case AST_Fun: + case AST_Import: + DEBUG("create Import"); + g_array_append_val(imports, currentNode->children[i]->value); + break; + default: + INFO("Provided source file could not be parsed beecause of semantic error."); + break; + + } + } + + return rootModule; +} + + + diff --git a/src/set/set.h b/src/set/set.h new file mode 100644 index 0000000..033dee5 --- /dev/null +++ b/src/set/set.h @@ -0,0 +1,8 @@ +#ifndef _SET_H_ +#define _SET_H_ + +#include + +void create_set(AST_NODE_PTR rootNodePtr ); + +#endif diff --git a/src/set/types.h b/src/set/types.h index a035854..4650c86 100644 --- a/src/set/types.h +++ b/src/set/types.h @@ -117,7 +117,7 @@ typedef struct Type_t { typedef struct Typedefine_t { const char* name; - Type type; + Type *type; AST_NODE_PTR nodePtr; } Typedefine; @@ -129,7 +129,7 @@ typedef struct Typedefine_t { */ typedef struct TypeValue_t { // the type - Type type; + Type *type; // UTF-8 representation of the type's value const char* value; AST_NODE_PTR nodePtr; @@ -160,7 +160,7 @@ typedef enum IO_Qualifier_t { * */ typedef struct ParameterDeclaration_t { - Type type; + Type *type; IO_Qualifier qualifier; AST_NODE_PTR nodePtr; } ParameterDeclaration; @@ -173,7 +173,7 @@ typedef struct ParameterDefinition_t { ParameterDeclaration declaration; // value to initalize the declaration with // NOTE: type of initializer and declaration MUST be equal - Expression initializer; + Expression *initializer; AST_NODE_PTR nodePtr; } ParameterDefinition; @@ -207,7 +207,7 @@ typedef struct FunctionDefinition_t { GArray* parameter; AST_NODE_PTR nodePtr; // body of function - Block body; + Block *body; // name of function const char* name; } FunctionDefinition; @@ -239,7 +239,7 @@ typedef enum StorageQualifier_t { typedef struct VariableDeclaration_t { StorageQualifier qualifier; - Type type; + Type *type; AST_NODE_PTR nodePtr; } VariableDeclaration; @@ -251,7 +251,7 @@ typedef struct VariableDeclaration_t { */ typedef struct VariableDefiniton_t { VariableDeclaration declaration; - Expression initializer; + Expression *initializer; AST_NODE_PTR nodePtr; } VariableDefiniton; @@ -286,7 +286,7 @@ typedef struct Variable_t { * */ typedef struct TypeCast_t { - Type targetType; + Type *targetType; Expression* operand; AST_NODE_PTR nodePtr; } TypeCast; @@ -299,7 +299,7 @@ typedef struct TypeCast_t { * */ typedef struct Transmute_t { - Type targetType; + Type *targetType; Expression* operand; AST_NODE_PTR nodePtr; } Transmute; diff --git a/src/yacc/parser.y b/src/yacc/parser.y index 753c7bc..4b8c156 100644 --- a/src/yacc/parser.y +++ b/src/yacc/parser.y @@ -5,6 +5,7 @@ #include #include #include + extern int yylineno; @@ -132,7 +133,8 @@ %left '(' ')' %% -program: program programbody {AST_push_node(root, $2);} +program: program programbody {AST_push_node(root, $2); + } | programbody {AST_push_node(root, $1);}; programbody: moduleimport {$$ = $1;} @@ -365,7 +367,7 @@ decl: type ':' identlist {AST_NODE_PTR decl = AST_new_node(AST_Decl, NULL); AST_push_node(decl, $1); AST_push_node(decl, $2); AST_push_node(decl, $4); - $$ = decl;} + $$ = decl;}; definition: decl '=' expr { AST_NODE_PTR def = AST_new_node(AST_Def, NULL); From 8e1a1664da47c8bf5c1010f9829b3052811e3a57 Mon Sep 17 00:00:00 2001 From: Filleo Date: Fri, 31 May 2024 18:36:40 +0200 Subject: [PATCH 056/124] added enum type values to set --- src/set/set.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++-- src/set/types.h | 3 +- 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/src/set/set.c b/src/set/set.c index bed1e4d..bad66a8 100644 --- a/src/set/set.c +++ b/src/set/set.c @@ -127,7 +127,7 @@ StorageQualifier Qualifier_from_string(const char *str) { PANIC("Provided string is not a storagequalifier: %s", str); } -Variable **create_decl(AST_NODE_PTR currentNode){ +Variable **createDecl(AST_NODE_PTR currentNode){ DEBUG("create declaration"); Variable **variables = malloc(currentNode->children[currentNode->child_count -1]->child_count * sizeof(Variable)); @@ -189,9 +189,76 @@ int fillTablesWithVars(GHashTable *variableTable,GHashTable *currentScope , Vari return 0; } +Variable **createDef(AST_NODE_PTR currentNode){ + +} +TypeValue createTypeValue(AST_NODE_PTR currentNode){ + TypeValue value; + Type *type = malloc(sizeof(Type)); + value.type = type; + type->kind = TypeKindPrimitive; + type->nodePtr = currentNode; + + switch (currentNode->kind) { + + case AST_Int: + type->impl.primitive = Int; + case AST_Float: + type->impl.primitive = Int; + default: + PANIC("Node is not an expression but from kind: %i", currentNode->kind); + break; + } + + value.nodePtr = currentNode; + value.value = currentNode->value; + return value; +} + +Expression *createExpression(AST_NODE_PTR currentNode){ + Expression *expression = malloc(sizeof(Expression)); + + switch(currentNode->kind){ + + case AST_Int: + case AST_Float: + expression->kind = ExpressionKindConstant; + expression->impl.constant = createTypeValue(currentNode); + + case AST_String: + //TODO + case AST_Ident: + + case AST_Add: + case AST_Sub: + case AST_Mul: + case AST_Div: + case AST_Negate: + + case AST_Eq: + case AST_Less: + case AST_Greater: + + case AST_BoolAnd: + case AST_BoolNot: + case AST_BoolOr: + case AST_BoolXor: + + case AST_BitAnd: + case AST_BitOr: + case AST_BitXor: + case AST_BitNot: + + + default: + PANIC("Node is not an expression but from kind: %i", currentNode->kind); + break; + } +} + Module *create_set(AST_NODE_PTR currentNode){ DEBUG("create root Module"); //create tables for types @@ -229,7 +296,7 @@ Module *create_set(AST_NODE_PTR currentNode){ switch(currentNode->children[i]->kind){ case AST_Decl: - if (1 == fillTablesWithVars(variables,globalscope,create_decl(currentNode->children[i]) ,currentNode->children[i]->children[currentNode->children[i]->child_count -1]->child_count)){ + if (1 == fillTablesWithVars(variables,globalscope,createDecl(currentNode->children[i]) ,currentNode->children[i]->children[currentNode->children[i]->child_count -1]->child_count)){ //TODO behandlung, wenn var schon existiert DEBUG("var already exists"); break; @@ -237,6 +304,12 @@ Module *create_set(AST_NODE_PTR currentNode){ DEBUG("filled successfull the module and scope with vars"); break; case AST_Def: + if (1 == fillTablesWithVars(variables,globalscope,createDef(currentNode->children[i]) ,currentNode->children[i]->children[currentNode->children[i]->child_count -1]->child_count)){ + //TODO behandlung, wenn var schon existiert + DEBUG("var already exists"); + break; + } + DEBUG("filled successfull the module and scope with vars"); case AST_Box: case AST_Fun: case AST_Import: diff --git a/src/set/types.h b/src/set/types.h index 4650c86..286a2aa 100644 --- a/src/set/types.h +++ b/src/set/types.h @@ -401,7 +401,8 @@ typedef enum ExpressionKind_t { ExpressionKindOperation, ExpressionKindTypeCast, ExpressionKindTransmute, - ExpressionKindConstant + ExpressionKindConstant, + ExpressionKindVariable } ExpressionKind; typedef struct Expression_t { From 7922fbc8b79435d47c8be1f3a3071fee72e87d66 Mon Sep 17 00:00:00 2001 From: Filleo Date: Sun, 2 Jun 2024 23:26:51 +0200 Subject: [PATCH 057/124] added expressions and types --- src/set/set.c | 190 +++++++++++++++++++++++++++++++++++++++++++++--- src/set/types.h | 8 +- 2 files changed, 184 insertions(+), 14 deletions(-) diff --git a/src/set/set.c b/src/set/set.c index bad66a8..9b673a0 100644 --- a/src/set/set.c +++ b/src/set/set.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -5,13 +6,30 @@ #include #include + GHashTable *declaredComposites;//pointer to composites with names, GHashTable *declaredBoxes;//pointer to typeboxes -GArray *Scope;//last object is current scope - - +GArray *Scope;//list of hashtables. last Hashtable is current depth of program. hashtable key: ident, value: Variable* to var +const Type ShortShortUnsingedIntType = { + .kind = TypeKindComposite, + .impl = { + .composite = { + .sign = Unsigned, + .scale = 0.25, + .primitive = Int + } + }, + .nodePtr = NULL, +}; +const Type StringLiteralType = { + .kind = TypeKindReference, + .impl = { + .reference = (ReferenceType) &ShortShortUnsingedIntType, + }, + .nodePtr = NULL, +}; Type *findType(AST_NODE_PTR currentNode){ @@ -129,7 +147,7 @@ StorageQualifier Qualifier_from_string(const char *str) { Variable **createDecl(AST_NODE_PTR currentNode){ DEBUG("create declaration"); - Variable **variables = malloc(currentNode->children[currentNode->child_count -1]->child_count * sizeof(Variable)); + Variable **variables = malloc(currentNode->children[currentNode->child_count -1]->child_count * sizeof(Variable*)); VariableDeclaration decl; decl.nodePtr = currentNode; @@ -165,21 +183,22 @@ Variable **createDecl(AST_NODE_PTR currentNode){ return variables; } -int isVariableInScope(const char* name){ - +Variable* getVariableFromScope(const char* name){ for(size_t i = 0; i < Scope->len; i++){ if(g_hash_table_contains(((GHashTable **) Scope->data)[i], name)) { - return 1; + return g_hash_table_lookup(((GHashTable**)Scope->data)[i], name); } } - return 0; + return NULL; } + + int fillTablesWithVars(GHashTable *variableTable,GHashTable *currentScope , Variable** content, size_t amount){ DEBUG("filling vars in scope and table"); for(size_t i = 0; i < amount; i++){ - if(isVariableInScope(content[i]->name)){ + if(!(NULL == getVariableFromScope(content[i]->name))){ DEBUG("this var already exist: ",content[i]->name); return 1; } @@ -218,25 +237,167 @@ TypeValue createTypeValue(AST_NODE_PTR currentNode){ return value; } +TypeValue createString(AST_NODE_PTR currentNode){ + TypeValue value; + Type *type =(Type*) &StringLiteralType; + value.type = type; + value.nodePtr = currentNode; + value.value = currentNode->value; + return value; +} + +Expression *createExpression(AST_NODE_PTR currentNode); + + +Type* createTypeFromOperands(Type* LeftOperandType, Type* RightOperandType, AST_NODE_PTR currentNode){ + Type *result = malloc(sizeof(Type)); + result->nodePtr = currentNode; + + + if(LeftOperandType->kind == TypeKindComposite && RightOperandType->kind == TypeKindComposite) + { + result->kind = TypeKindComposite; + CompositeType resultImpl; + + resultImpl.nodePtr = currentNode; + resultImpl.sign = MAX(LeftOperandType->impl.composite.sign, RightOperandType->impl.composite.sign); + resultImpl.scale = MAX(LeftOperandType->impl.composite.scale, RightOperandType->impl.composite.scale); + resultImpl.primitive = MAX(LeftOperandType->impl.composite.primitive , RightOperandType->impl.composite.primitive); + + result->impl.composite = resultImpl; + + + } else if(LeftOperandType->kind == TypeKindPrimitive && RightOperandType->kind == TypeKindPrimitive){ + result->kind = TypeKindPrimitive; + + result->impl.primitive = MAX(LeftOperandType->impl.primitive , RightOperandType->impl.primitive); + + } else if(LeftOperandType->kind == TypeKindPrimitive && RightOperandType->kind == TypeKindComposite){ + result->kind = TypeKindComposite; + + result->impl.composite.sign = Signed; + result->impl.composite.scale = MAX( 1.0, RightOperandType->impl.composite.scale); + result->impl.composite.primitive = MAX(Int, RightOperandType->impl.composite.primitive); + result->impl.composite.nodePtr = currentNode; + + } else if(LeftOperandType->kind == TypeKindComposite && RightOperandType->kind == TypeKindPrimitive){ + result->kind = TypeKindComposite; + + result->impl.composite.sign = Signed; + result->impl.composite.scale = MAX( 1.0, LeftOperandType->impl.composite.scale); + result->impl.composite.primitive = MAX(Int, LeftOperandType->impl.composite.primitive); + result->impl.composite.nodePtr = currentNode; + }else{ + return NULL; + } + return result; +} + +int createArithOperation(Expression* ParentExpression, AST_NODE_PTR currentNode, size_t expectedChildCount){ + + ParentExpression->impl.operation.kind = Arithmetic; + ParentExpression->impl.operation.nodePtr = currentNode; + if (expectedChildCount > currentNode->child_count){ + PANIC("Operation has to many children"); + } + for (size_t i = 0; i < currentNode->child_count; i++){ + Expression* expression = createExpression(currentNode->children[i]); + if(NULL == expression){ + return 1; + } + g_array_append_val(ParentExpression->impl.operation.operands , expression); + + } + + switch (currentNode->kind){ + case AST_Add: + ParentExpression->impl.operation.impl.arithmetic = Add; + case AST_Sub: + ParentExpression->impl.operation.impl.arithmetic = Sub; + case AST_Mul: + ParentExpression->impl.operation.impl.arithmetic = Mul; + case AST_Div: + ParentExpression->impl.operation.impl.arithmetic = Div; + case AST_Negate: + ParentExpression->impl.operation.impl.arithmetic = Negate; + default: + PANIC("Current node is not an arithmetic operater"); + break; + } + + + if(ParentExpression->impl.operation.impl.arithmetic == Negate){ + Type* result = malloc(sizeof(Type)); + result = ((Expression**) ParentExpression->impl.operation.operands->data)[0]->result; + result->nodePtr = currentNode; + if (result->kind == TypeKindReference || result->kind == TypeKindBox){ + return 1; + }else if(result->kind == TypeKindComposite){ + result->impl.composite.sign = Signed; + } + ParentExpression->result = result; + + }else{ + + Type* LeftOperandType = ((Expression**) ParentExpression->impl.operation.operands->data)[0]->result; + Type* RightOperandType = ((Expression**) ParentExpression->impl.operation.operands->data)[1]->result; + + ParentExpression->result = createTypeFromOperands(LeftOperandType, RightOperandType, currentNode); + } + + + + return 0; +} + + + Expression *createExpression(AST_NODE_PTR currentNode){ Expression *expression = malloc(sizeof(Expression)); - + expression->nodePtr = currentNode; switch(currentNode->kind){ case AST_Int: case AST_Float: expression->kind = ExpressionKindConstant; expression->impl.constant = createTypeValue(currentNode); + expression->result = expression->impl.constant.type; case AST_String: - //TODO + expression->kind = ExpressionKindConstant; + expression->impl.constant = createString(currentNode); + expression->result = expression->impl.constant.type; case AST_Ident: + expression->kind = ExpressionKindVariable; + expression->impl.variable = getVariableFromScope(currentNode->value); + if(NULL == expression->impl.variable){ + DEBUG("Identifier is not in current scope"); + return NULL; + } + switch (expression->impl.variable->kind) { + case VariableKindDeclaration: + expression->result = expression->impl.variable->impl.declaration.type; + case VariableKindDefinition: + expression->result = expression->impl.variable->impl.definiton.declaration.type; + default: + PANIC("current Variable should not be an BoxMember"); + break; + } case AST_Add: case AST_Sub: case AST_Mul: case AST_Div: + expression->kind = ExpressionKindOperation; + if(createArithOperation(expression, currentNode, 2)){ + return NULL; + } case AST_Negate: + expression->kind = ExpressionKindOperation; + if(createArithOperation(expression,currentNode, 1)){ + return NULL; + } + case AST_Eq: case AST_Less: @@ -252,6 +413,13 @@ Expression *createExpression(AST_NODE_PTR currentNode){ case AST_BitXor: case AST_BitNot: + case AST_IdentList: + //Box Accsess + case AST_List: + // Box Self Access + case AST_Typekind: + case AST_Transmute: + default: PANIC("Node is not an expression but from kind: %i", currentNode->kind); diff --git a/src/set/types.h b/src/set/types.h index 286a2aa..d425066 100644 --- a/src/set/types.h +++ b/src/set/types.h @@ -188,6 +188,7 @@ typedef enum ParameterKind_t { */ typedef struct Parameter_t { const char* name; + ParameterKind kind; union ParameterImplementation { ParameterDeclaration declaration; @@ -316,7 +317,8 @@ typedef enum ArithmeticOperator_t { Add, Sub, Mul, - Div + Div, + Negate } ArithmeticOperator; // .------------------------------------------------. @@ -389,7 +391,7 @@ typedef struct Operation_t { LogicalOperator logical; BitwiseOperator bitwise; } impl; - Expression* operands; + GArray* operands; //Expression* AST_NODE_PTR nodePtr; } Operation; @@ -414,7 +416,7 @@ typedef struct Expression_t { TypeCast typecast; Transmute transmute; TypeValue constant; - Variable variable; + Variable* variable; } impl; AST_NODE_PTR nodePtr; } Expression; From 70859e0a6a04deb5021d5e8356f31550c19d5da7 Mon Sep 17 00:00:00 2001 From: Filleo Date: Sun, 2 Jun 2024 23:27:22 +0200 Subject: [PATCH 058/124] added default values to enums --- src/set/types.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/set/types.h b/src/set/types.h index d425066..08e8418 100644 --- a/src/set/types.h +++ b/src/set/types.h @@ -11,9 +11,9 @@ */ typedef enum PrimitiveType_t { // 4 byte signed integer in two's complement - Int, + Int =0, // 4 byte IEEE-754 single precision - Float + Float =1 } PrimitiveType; /** @@ -21,10 +21,10 @@ typedef enum PrimitiveType_t { * */ typedef enum Sign_t { - // type has a sign bit - Signed, // type has no sign bit - Unsigned + Unsigned = 0, + // type has a sign bit + Signed = 1 } Sign; /** @@ -387,7 +387,7 @@ typedef struct Operation_t { union OperationImplementation { ArithmeticOperator arithmetic; RelationalOperator relational; - BooleanOperator boolean; + BooleanOperator boolean; LogicalOperator logical; BitwiseOperator bitwise; } impl; From 523a9f19cc7cb27f803b118fd73d0b637a924c4a Mon Sep 17 00:00:00 2001 From: Filleo Date: Mon, 3 Jun 2024 11:53:09 +0200 Subject: [PATCH 059/124] added relational and boolian operands --- src/set/set.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 107 insertions(+), 1 deletion(-) diff --git a/src/set/set.c b/src/set/set.c index 9b673a0..39caba4 100644 --- a/src/set/set.c +++ b/src/set/set.c @@ -345,12 +345,110 @@ int createArithOperation(Expression* ParentExpression, AST_NODE_PTR currentNode, ParentExpression->result = createTypeFromOperands(LeftOperandType, RightOperandType, currentNode); } + if(ParentExpression->result == NULL){ + return 1; + } return 0; } +int createRelationalOperation(Expression* ParentExpression,AST_NODE_PTR currentNode){ + //fill kind and Nodeptr + ParentExpression->impl.operation.kind = Relational; + ParentExpression->impl.operation.nodePtr = currentNode; + //fill Operands + for (size_t i = 0; i < currentNode->child_count; i++){ + Expression* expression = createExpression(currentNode->children[i]); + if(NULL == expression){ + return 1; + } + g_array_append_val(ParentExpression->impl.operation.operands , expression); + } + + //fill impl + switch (currentNode->kind){ + case AST_Eq: + ParentExpression->impl.operation.impl.relational = Equal; + case AST_Less: + ParentExpression->impl.operation.impl.relational = Greater; + case AST_Greater: + ParentExpression->impl.operation.impl.relational= Less; + default: + PANIC("Current node is not an relational operater"); + break; + } + Type * result = malloc(sizeof(Type)); + result->impl.primitive = Int; + result->kind = TypeKindPrimitive; + result->nodePtr = currentNode; + + ParentExpression->result = result; + return 0; +} + + +int createBoolOperation(Expression *ParentExpression, AST_NODE_PTR currentNode){ + //fill kind and Nodeptr + ParentExpression->impl.operation.kind = Boolean; + ParentExpression->impl.operation.nodePtr = currentNode; + + //fill Operands + for (size_t i = 0; i < currentNode->child_count; i++){ + Expression* expression = createExpression(currentNode->children[i]); + if(NULL == expression){ + return 1; + } + g_array_append_val(ParentExpression->impl.operation.operands , expression); + } + + switch (currentNode->kind){ + case AST_BoolAnd: + ParentExpression->impl.operation.impl.boolean = BooleanAnd; + case AST_BoolOr: + ParentExpression->impl.operation.impl.boolean = BooleanOr; + case AST_BoolXor: + ParentExpression->impl.operation.impl.boolean = BooleanXor; + default: + PANIC("Current node is not an boolean operater"); + break; + } + + + Type* LeftOperandType = ((Expression**) ParentExpression->impl.operation.operands->data)[0]->result; + Type* RightOperandType = ((Expression**) ParentExpression->impl.operation.operands->data)[1]->result; + + //should not be a box or a reference + if(LeftOperandType->kind != TypeKindPrimitive && LeftOperandType->kind != TypeKindComposite){ + return 1; + } + if(RightOperandType->kind != TypeKindPrimitive && RightOperandType->kind != TypeKindComposite){ + return 1; + } + //should not be a float + if(LeftOperandType->kind == TypeKindComposite){ + if(LeftOperandType->impl.composite.primitive == Float){ + return 1; + } + }else if(LeftOperandType->kind == TypeKindPrimitive){ + if(LeftOperandType->impl.primitive == Float){ + return 1; + } + }else if(RightOperandType->kind == TypeKindComposite){ + if(RightOperandType->impl.composite.primitive == Float){ + return 1; + } + }else if(RightOperandType->kind == TypeKindPrimitive){ + if(RightOperandType->impl.primitive == Float){ + return 1; + } + } + + + ParentExpression->result = createTypeFromOperands(LeftOperandType, RightOperandType, currentNode); + return 0; +} Expression *createExpression(AST_NODE_PTR currentNode){ Expression *expression = malloc(sizeof(Expression)); @@ -402,11 +500,19 @@ Expression *createExpression(AST_NODE_PTR currentNode){ case AST_Eq: case AST_Less: case AST_Greater: + expression->kind = ExpressionKindOperation; + if(createRelationalOperation(expression,currentNode)){ + return NULL; + } case AST_BoolAnd: - case AST_BoolNot: case AST_BoolOr: case AST_BoolXor: + expression->kind = ExpressionKindOperation; + if(createRelationalOperation(expression,currentNode)){ + return NULL; + } + case AST_BoolNot: case AST_BitAnd: case AST_BitOr: From 8a2eeb63b843173a28c0afb88f3cde0fd9ac990a Mon Sep 17 00:00:00 2001 From: Filleo Date: Mon, 3 Jun 2024 13:54:03 +0200 Subject: [PATCH 060/124] added Bool Not to expression --- src/set/set.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/src/set/set.c b/src/set/set.c index 39caba4..3fda6a3 100644 --- a/src/set/set.c +++ b/src/set/set.c @@ -450,6 +450,48 @@ int createBoolOperation(Expression *ParentExpression, AST_NODE_PTR currentNode){ return 0; } +int createBoolNotOperation(Expression *ParentExpression, AST_NODE_PTR currentNode){ + //fill kind and Nodeptr + ParentExpression->impl.operation.kind = Boolean; + ParentExpression->impl.operation.nodePtr = currentNode; + + //fill Operand + Expression* expression = createExpression(currentNode->children[0]); + if(NULL == expression){ + return 1; + } + g_array_append_val(ParentExpression->impl.operation.operands , expression); + + ParentExpression->impl.operation.impl.boolean = BooleanNot; + + Type* Operand = ((Expression**)ParentExpression->impl.operation.operands)[0]->result; + + Type* result = malloc(sizeof(Type)); + result->nodePtr = currentNode; + if (Operand->kind == TypeKindBox || Operand->kind == TypeKindReference){ + return 1; + } + if(Operand->kind == TypeKindPrimitive){ + if(Operand->impl.primitive == Float){ + return 1; + } + result->kind = Operand->kind; + result->impl = Operand->impl; + }else if(Operand->kind == TypeKindComposite){ + if(Operand->impl.composite.primitive == Float){ + return 1; + } + result->kind = Operand->kind; + result->impl = Operand->impl; + } + + ParentExpression->result = result; + return 0; +} + + + + Expression *createExpression(AST_NODE_PTR currentNode){ Expression *expression = malloc(sizeof(Expression)); expression->nodePtr = currentNode; @@ -509,14 +551,19 @@ Expression *createExpression(AST_NODE_PTR currentNode){ case AST_BoolOr: case AST_BoolXor: expression->kind = ExpressionKindOperation; - if(createRelationalOperation(expression,currentNode)){ + if(createBoolOperation(expression,currentNode)){ return NULL; } case AST_BoolNot: + expression->kind= ExpressionKindOperation; + if(createBoolNotOperation(expression, currentNode)){ + return NULL; + } case AST_BitAnd: case AST_BitOr: case AST_BitXor: + case AST_BitNot: case AST_IdentList: From af4e99b6da0ef2ca95c9e53ab39c294afbf1ca86 Mon Sep 17 00:00:00 2001 From: servostar Date: Mon, 3 Jun 2024 16:23:12 +0200 Subject: [PATCH 061/124] adapted standard library to be a gemstone project --- lib/CMakeLists.txt | 6 +++--- lib/build.toml | 16 ++++++++++++++++ lib/{ => src}/bool.gem | 0 lib/{ => src}/def.gem | 0 lib/{ => src}/def/api.h | 0 lib/{ => src}/io.gem | 0 lib/{ => src}/io/api.h | 0 lib/{ => src}/io/impl.c | 0 lib/{ => src}/mem.gem | 0 lib/{ => src}/mem/api.h | 0 lib/{ => src}/mem/impl.c | 0 lib/{ => src}/std.gem | 0 12 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 lib/build.toml rename lib/{ => src}/bool.gem (100%) rename lib/{ => src}/def.gem (100%) rename lib/{ => src}/def/api.h (100%) rename lib/{ => src}/io.gem (100%) rename lib/{ => src}/io/api.h (100%) rename lib/{ => src}/io/impl.c (100%) rename lib/{ => src}/mem.gem (100%) rename lib/{ => src}/mem/api.h (100%) rename lib/{ => src}/mem/impl.c (100%) rename lib/{ => src}/std.gem (100%) diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index ac34f1f..ffd62ff 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -10,13 +10,13 @@ set(CMAKE_C_STANDARD_REQUIRED TRUE) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -include_directories(${PROJECT_SOURCE_DIR}) +include_directories(${PROJECT_SOURCE_DIR}/src) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/../bin/std") # add native module libraries -file(GLOB_RECURSE STDLIB_IO_SOURCE_FILES io/*.c) +file(GLOB_RECURSE STDLIB_IO_SOURCE_FILES src/io/*.c) add_library(io ${STDLIB_IO_SOURCE_FILES}) -file(GLOB_RECURSE STDLIB_MEM_SOURCE_FILES mem/*.c) +file(GLOB_RECURSE STDLIB_MEM_SOURCE_FILES src/mem/*.c) add_library(mem ${STDLIB_MEM_SOURCE_FILES}) diff --git a/lib/build.toml b/lib/build.toml new file mode 100644 index 0000000..85c5687 --- /dev/null +++ b/lib/build.toml @@ -0,0 +1,16 @@ +[project] +name = "gemstone standard library" +version = "0.1.0" +description = "Cross platform standard library for thr gemstone programming language." +license = "GPL-2.0" +authors = [ "Sven Vogel " ] + +[target.release] +root = "src/std.gem" +mode = "library" +output = "bin" +archive = "archive" +print_ast = false +print_asm = false +print_ir = false +opt = 3 diff --git a/lib/bool.gem b/lib/src/bool.gem similarity index 100% rename from lib/bool.gem rename to lib/src/bool.gem diff --git a/lib/def.gem b/lib/src/def.gem similarity index 100% rename from lib/def.gem rename to lib/src/def.gem diff --git a/lib/def/api.h b/lib/src/def/api.h similarity index 100% rename from lib/def/api.h rename to lib/src/def/api.h diff --git a/lib/io.gem b/lib/src/io.gem similarity index 100% rename from lib/io.gem rename to lib/src/io.gem diff --git a/lib/io/api.h b/lib/src/io/api.h similarity index 100% rename from lib/io/api.h rename to lib/src/io/api.h diff --git a/lib/io/impl.c b/lib/src/io/impl.c similarity index 100% rename from lib/io/impl.c rename to lib/src/io/impl.c diff --git a/lib/mem.gem b/lib/src/mem.gem similarity index 100% rename from lib/mem.gem rename to lib/src/mem.gem diff --git a/lib/mem/api.h b/lib/src/mem/api.h similarity index 100% rename from lib/mem/api.h rename to lib/src/mem/api.h diff --git a/lib/mem/impl.c b/lib/src/mem/impl.c similarity index 100% rename from lib/mem/impl.c rename to lib/src/mem/impl.c diff --git a/lib/std.gem b/lib/src/std.gem similarity index 100% rename from lib/std.gem rename to lib/src/std.gem From a7bd9c2cc623ec47eaec1e1e8a155997644fb443 Mon Sep 17 00:00:00 2001 From: servostar Date: Mon, 3 Jun 2024 18:35:23 +0200 Subject: [PATCH 062/124] added os module --- lib/CMakeLists.txt | 3 +++ lib/src/capi.h | 14 ++++++++++++++ lib/src/def.gem | 2 +- lib/src/def/api.h | 3 ++- lib/src/io/impl.c | 5 +++-- lib/src/mem/impl.c | 5 +++-- lib/src/os.gem | 25 +++++++++++++++++++++++++ lib/src/os/api.h | 18 ++++++++++++++++++ lib/src/os/impl.c | 36 ++++++++++++++++++++++++++++++++++++ 9 files changed, 105 insertions(+), 6 deletions(-) create mode 100644 lib/src/capi.h create mode 100644 lib/src/os.gem create mode 100644 lib/src/os/api.h create mode 100644 lib/src/os/impl.c diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index ffd62ff..6bc0d38 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -20,3 +20,6 @@ add_library(io ${STDLIB_IO_SOURCE_FILES}) file(GLOB_RECURSE STDLIB_MEM_SOURCE_FILES src/mem/*.c) add_library(mem ${STDLIB_MEM_SOURCE_FILES}) + +file(GLOB_RECURSE STDLIB_OS_SOURCE_FILES src/os/*.c) +add_library(os ${STDLIB_OS_SOURCE_FILES}) \ No newline at end of file diff --git a/lib/src/capi.h b/lib/src/capi.h new file mode 100644 index 0000000..0ef22ab --- /dev/null +++ b/lib/src/capi.h @@ -0,0 +1,14 @@ +// +// Created by servostar on 6/3/24. +// + +#ifndef GEMSTONE_STD_LIB_CAPI_H +#define GEMSTONE_STD_LIB_CAPI_H + +#if defined(_WIN32) || defined (_WIN64) +#define PLATFORM_WINDOWS +#elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__linux__) +#define PLATFORM_POSIX +#endif + +#endif // GEMSTONE_STD_LIB_CAPI_H diff --git a/lib/src/def.gem b/lib/src/def.gem index 232d474..5bd344f 100644 --- a/lib/src/def.gem +++ b/lib/src/def.gem @@ -31,7 +31,7 @@ type signed double double float: f128 # String constant -type ref u8: str +type ref u8: cstr # C style void pointer replacement diff --git a/lib/src/def/api.h b/lib/src/def/api.h index 94ad84d..a807865 100644 --- a/lib/src/def/api.h +++ b/lib/src/def/api.h @@ -6,6 +6,7 @@ #define GEMSTONE_STD_LIB_DEF_H_ #include +#include typedef uint8_t u8; typedef uint16_t u16; @@ -20,7 +21,7 @@ typedef int64_t i64; typedef float f32; typedef double f64; -typedef u8* str; +typedef u8* cstr; typedef u8* ptr; diff --git a/lib/src/io/impl.c b/lib/src/io/impl.c index 19fe716..f56c561 100644 --- a/lib/src/io/impl.c +++ b/lib/src/io/impl.c @@ -1,7 +1,8 @@ #include +#include -#if defined(_WIN32) || defined (_WIN64) +#if defined(PLATFORM_WINDOWS) // Compile for Windows @@ -34,7 +35,7 @@ void flush(handle dev) { FlushFileBuffers((HANDLE) dev); } -#elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__linux__) +#elif defined(PLATFORM_POSIX) // Compile for Linux and BSD diff --git a/lib/src/mem/impl.c b/lib/src/mem/impl.c index 95863ac..9d384a8 100644 --- a/lib/src/mem/impl.c +++ b/lib/src/mem/impl.c @@ -1,7 +1,8 @@ #include +#include -#if defined(_WIN32) || defined (_WIN64) +#if defined(PLATFORM_WINDOWS) #include @@ -22,7 +23,7 @@ void heap_free(u8* ptr) { HeapFree(heap, ptr); } -#elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__linux__) +#elif defined(PLATFORM_POSIX) #include diff --git a/lib/src/os.gem b/lib/src/os.gem new file mode 100644 index 0000000..9f51a45 --- /dev/null +++ b/lib/src/os.gem @@ -0,0 +1,25 @@ +# Author: Sven Vogel +# Edited: 03.06.2024 +# License: GPL-2.0 + +# ,----------------------------------------. +# | Operating System | +# `----------------------------------------` + +import "def.gem" + +# Return a hard coded C string identifying the underlying operating system +# Will return one of the following: +# - "windows" (for Windows 7, Windows 10 and Windows 11) +# - "unix" (for GNU/Linux and BSD) +fun getPlatformName(out cstr: name) + +# Return a C string to the value of an environment varible named +# after the C string name. +fun getEnvVar(in cstr: name)(out cstr: value) + +# Set the value of an environment variable with name to value. +fun setEnvVar(in cstr: name, in cstr: value) + +# Unset a specific environment variable +fun unsetEnvVar(in cstr: name) \ No newline at end of file diff --git a/lib/src/os/api.h b/lib/src/os/api.h new file mode 100644 index 0000000..3ed7a1f --- /dev/null +++ b/lib/src/os/api.h @@ -0,0 +1,18 @@ +// +// Created by servostar on 6/3/24. +// + +#ifndef GEMSTONE_STD_LIB_OS_H +#define GEMSTONE_STD_LIB_OS_H + +#include + +void getPlatformName(cstr* name); + +void getEnvVar(cstr name, cstr* value); + +void setEnvVar(cstr name, cstr value); + +void unsetEnvVar(cstr name); + +#endif // GEMSTONE_STD_LIB_OS_H diff --git a/lib/src/os/impl.c b/lib/src/os/impl.c new file mode 100644 index 0000000..7bed097 --- /dev/null +++ b/lib/src/os/impl.c @@ -0,0 +1,36 @@ +// +// Created by servostar on 6/3/24. +// + +#include +#include + +#if defined(PLATFORM_WINDOWS) + +void getPlatformName(cstr* name) { + *name = (u8*) "windows"; +} + +#elif defined(PLATFORM_POSIX) + +void getPlatformName(cstr * name) { + *name = (u8*) "posix"; +} + +#endif + +// Implementation based on libc + +#include + +void getEnvVar(cstr name, cstr* value) { + *value = (cstr) getenv((char*) name); +} + +void setEnvVar(cstr name, cstr value) { + setenv((char*) name, (char*) value, true); +} + +void unsetEnvVar(cstr name) { + unsetenv((char*) name); +} From 879940dee9ce56a05ea60a2c2777315be32841bb Mon Sep 17 00:00:00 2001 From: Filleo Date: Mon, 3 Jun 2024 19:42:58 +0200 Subject: [PATCH 063/124] midway of creating Bit Operation in expression --- src/set/set.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/set/set.c b/src/set/set.c index 3fda6a3..5c73209 100644 --- a/src/set/set.c +++ b/src/set/set.c @@ -489,7 +489,21 @@ int createBoolNotOperation(Expression *ParentExpression, AST_NODE_PTR currentNod return 0; } +int createBitOperation(Expression* ParentExpression, AST_NODE_PTR currentNode){ + //fill kind and Nodeptr + ParentExpression->impl.operation.kind = Boolean; + ParentExpression->impl.operation.nodePtr = currentNode; + //fill Operands + for (size_t i = 0; i < currentNode->child_count; i++){ + Expression* expression = createExpression(currentNode->children[i]); + if(NULL == expression){ + return 1; + } + g_array_append_val(ParentExpression->impl.operation.operands , expression); + } + +} Expression *createExpression(AST_NODE_PTR currentNode){ @@ -563,6 +577,10 @@ Expression *createExpression(AST_NODE_PTR currentNode){ case AST_BitAnd: case AST_BitOr: case AST_BitXor: + expression->kind= ExpressionKindOperation; + if(createBitOperation(expression, currentNode)){ + return NULL; + } case AST_BitNot: From 1de671cd8b877dae094c75fdb42f5190dffd6973 Mon Sep 17 00:00:00 2001 From: Filleo Date: Mon, 3 Jun 2024 21:39:07 +0200 Subject: [PATCH 064/124] major reconstruction Co-authored-by: servostar Co-authored-by: SirTalksalot75 --- src/set/set.c | 354 ++++++++++++++++++++++++++++++++++++++++---------- src/set/set.h | 3 + 2 files changed, 286 insertions(+), 71 deletions(-) diff --git a/src/set/set.c b/src/set/set.c index 5c73209..1e385cb 100644 --- a/src/set/set.c +++ b/src/set/set.c @@ -3,13 +3,15 @@ #include #include #include +#include #include #include +#include +#include - -GHashTable *declaredComposites;//pointer to composites with names, -GHashTable *declaredBoxes;//pointer to typeboxes -GArray *Scope;//list of hashtables. last Hashtable is current depth of program. hashtable key: ident, value: Variable* to var +GHashTable *declaredComposites = NULL;//pointer to composites with names, +GHashTable *declaredBoxes = NULL;//pointer to typeboxes +GArray *Scope = NULL;//list of hashtables. last Hashtable is current depth of program. hashtable key: ident, value: Variable* to var const Type ShortShortUnsingedIntType = { .kind = TypeKindComposite, @@ -31,64 +33,154 @@ const Type StringLiteralType = { .nodePtr = NULL, }; +/** + * @brief Convert a string into a sign typ + * @return 0 on success, 1 otherwise + */ +int sign_from_string(const char* string, Sign* sign) { -Type *findType(AST_NODE_PTR currentNode){ + if (strcmp(string, "unsigned") == 0) { + *sign = Unsigned; + return 0; + } else if (strcmp(string, "signed") == 0) { + *sign = Signed; + return 0; + } + + return 1; +} + +/** + * @brief Convert a string into a primitive type + * @return 0 on success, 1 otherwise + */ +int primitive_from_string(const char* string, PrimitiveType* primitive) { + + if (strcmp(string, "int") == 0) { + *primitive = Int; + return 0; + } else if (strcmp(string, "float") == 0) { + *primitive = Float; + return 0; + } + + return 1; +} + +int scale_factor_from(const char* string, double* factor) { + if (strcmp(string, "half") == 0 || strcmp(string, "short") == 0) { + *factor = 0.5; + return SEMANTIC_OK; + } else if (strcmp(string, "double") == 0 || strcmp(string, "long") == 0) { + *factor = 2.0; + return SEMANTIC_OK; + } + + return SEMANTIC_ERROR; +} + +int merge_scale_list(AST_NODE_PTR scale_list, Scale* scale) { + for (size_t i = 0; i < scale_list->child_count; i++) { + + double scale_in_list = 1.0; + int scale_invalid = scale_factor_from(AST_get_node(scale_list, i)->value, &scale_in_list); + + if (scale_invalid == SEMANTIC_ERROR) { + return SEMANTIC_ERROR; + } + + *scale *= scale_in_list; + + if (0.25 > *scale || 8 > *scale) { + // TODO: print diagnostic: Invalid composite scale + return SEMANTIC_ERROR; + } + } + + return SEMANTIC_OK; +} + +Type *findType(AST_NODE_PTR currentNode); + +int impl_composite_type(AST_NODE_PTR ast_type, CompositeType* composite) { + DEBUG("Type is a Composite"); + + int status = SEMANTIC_OK; + int scaleNodeOffset = 0; + + // check if we have a sign + if (AST_Sign == ast_type->children[0]->kind) { + + status = sign_from_string(ast_type->children[0]->value, &composite->sign); + + if (status == SEMANTIC_ERROR) { + ERROR("invalid sign: %s", ast_type->children[0]->value); + return SEMANTIC_ERROR; + } + + scaleNodeOffset++; + } + + composite->scale = 1.0; + + // check if we have a list of scale factors + if (ast_type->children[scaleNodeOffset]->kind == AST_List) { + + status = merge_scale_list(ast_type->children[scaleNodeOffset], &composite->scale); + + if (status == SEMANTIC_ERROR) { + return SEMANTIC_ERROR; + } + } + + const char* typeKind = ast_type->children[ast_type->child_count - 1]->value; + + status = primitive_from_string(typeKind, &composite->primitive); + + if (status == SEMANTIC_ERROR) { + // not a primitive try to resolve the type by name (must be a composite) + status = impl_composite_type(); + } + + return SEMANTIC_OK; +} + +/** + * @brief Converts the given AST node to a gemstone type implementation. + * @param currentNode AST node of type kind type + * @return the gemstone type implementation + */ +Type *findType(AST_NODE_PTR currentNode) { + assert(currentNode != NULL); + assert(currentNode->kind == AST_Type); + assert(currentNode->child_count > 0); const char *typekind = currentNode->children[currentNode->child_count -1]->value; - if (0 == strcmp(typekind, "int")||0 == strcmp(typekind, "float")){ + + // type implementation + Type *type = malloc(sizeof(Type)); + type->nodePtr = currentNode; + + // primitive type OR composit + if (0 == strcmp(typekind, "int") || 0 == strcmp(typekind, "float")) { - Type *type = malloc(sizeof(Type)); - type->nodePtr = currentNode; - if(AST_Typekind != currentNode->children[0]->kind){ - DEBUG("Type is a Composite"); + if(AST_Typekind != currentNode->children[0]->kind) { + type->kind = TypeKindComposite; - - - CompositeType composite; - composite.nodePtr = currentNode; - - - if(0 == strcmp(typekind, "int")){ - composite.primitive = Int; - }else{ - composite.primitive = Float; - } - composite.sign = Signed; - - size_t scalelist = 0; - if(AST_Sign == currentNode->children[0]->kind){ - if(0 == strcmp(currentNode->children[0]->value, "unsigned")){ - composite.sign = Unsigned; - } - scalelist = 1; - } - - composite.scale = 1.0; - if(AST_List == currentNode->children[scalelist]->kind){ - for (size_t i = 0; i < currentNode->children[scalelist]->child_count; i++){ - if (0 == strcmp(currentNode->children[scalelist]->children[i]->value, "short") || 0 == strcmp(currentNode->children[scalelist]->children[i]->value, "half")){ - composite.scale /= 2; - }else{ - composite.scale *= 2; - } - if (0.25 > composite.scale || 8 > composite.scale) { - //TODO scale not right - } - } - } - - type->impl.composite = composite; - - - }else{ + type->impl.composite.nodePtr = currentNode; + impl_composite_type(currentNode, &type->impl.composite, typekind); + + } else { + // type is a primitive type->kind = TypeKindPrimitive; - if(0 == strcmp(typekind, "int")){ - type->impl.primitive = Int; - }else{ - type->impl.primitive = Float; + + int primitive_invalid = primitive_from_string(typekind, &type->impl.primitive); + + if (primitive_invalid) { + PANIC("invalid primitive: %s", typekind); } - return type; } + }else if(g_hash_table_contains(declaredBoxes, typekind)){ if(AST_Typekind != currentNode->children[0]->kind){ //TODO composite Box try @@ -208,9 +300,7 @@ int fillTablesWithVars(GHashTable *variableTable,GHashTable *currentScope , Vari return 0; } -Variable **createDef(AST_NODE_PTR currentNode){ -} @@ -489,6 +579,16 @@ int createBoolNotOperation(Expression *ParentExpression, AST_NODE_PTR currentNod return 0; } +bool isScaleEqual(double leftScale, double rightScale){ + int leftIntScale =(int)(leftScale *4); + int rightIntScale =(int)(rightScale *4); + + if (leftIntScale == rightIntScale){ + return TRUE; + } + return FALSE; +} + int createBitOperation(Expression* ParentExpression, AST_NODE_PTR currentNode){ //fill kind and Nodeptr ParentExpression->impl.operation.kind = Boolean; @@ -503,6 +603,113 @@ int createBitOperation(Expression* ParentExpression, AST_NODE_PTR currentNode){ g_array_append_val(ParentExpression->impl.operation.operands , expression); } + + switch (currentNode->kind){ + case AST_BitAnd: + ParentExpression->impl.operation.impl.bitwise = BitwiseAnd; + case AST_BitOr: + ParentExpression->impl.operation.impl.bitwise = BitwiseOr; + case AST_BitXor: + ParentExpression->impl.operation.impl.bitwise = BitwiseXor; + default: + PANIC("Current node is not an bitwise operater"); + break; + } + + + Type *result = malloc(sizeof(Type)); + result->nodePtr = currentNode; + + Type* LeftOperandType = ((Expression**) ParentExpression->impl.operation.operands->data)[0]->result; + Type* RightOperandType = ((Expression**) ParentExpression->impl.operation.operands->data)[1]->result; + + //should not be a box or a reference + if(LeftOperandType->kind != TypeKindPrimitive && LeftOperandType->kind != TypeKindComposite){ + return 1; + } + if(RightOperandType->kind != TypeKindPrimitive && RightOperandType->kind != TypeKindComposite){ + return 1; + } + if(LeftOperandType->kind == TypeKindPrimitive && RightOperandType->kind == TypeKindPrimitive){ + if(LeftOperandType->impl.primitive == Float || RightOperandType->impl.primitive == Float){ + return 1; + } + result->kind = TypeKindPrimitive; + result->impl.primitive = Int; + }else if(LeftOperandType->kind == TypeKindPrimitive && RightOperandType->kind == TypeKindComposite){ + if(LeftOperandType->impl.primitive == Float || RightOperandType->impl.composite.primitive == Float){ + return 1; + } + if((int)RightOperandType->impl.composite.scale != 1){ + return 1; + } + result->kind = TypeKindPrimitive; + result->impl.primitive = Int; + }else if(LeftOperandType->kind == TypeKindComposite && RightOperandType->kind == TypeKindPrimitive){ + if(LeftOperandType->impl.composite.primitive == Float || RightOperandType->impl.primitive == Float){ + return 1; + } + if((int)LeftOperandType->impl.composite.scale != 1){ + return 1; + } + result->kind = TypeKindPrimitive; + result->impl.primitive = Int; + }else{ + if(LeftOperandType->impl.composite.primitive == Float || RightOperandType->impl.composite.primitive == Float){ + return 1; + } + if(!isScaleEqual(LeftOperandType->impl.composite.scale, RightOperandType->impl.composite.scale)){ + return 1; + } + result->kind = TypeKindComposite; + result->impl.composite.nodePtr = currentNode; + result->impl.composite.scale = LeftOperandType->impl.composite.scale; + result->impl.composite.sign = MAX(LeftOperandType->impl.composite.sign, RightOperandType->impl.composite.sign); + } + + ParentExpression->result = result; + return 0; +} + +int createBitNotOperation(Expression* ParentExpression, AST_NODE_PTR currentNode){ + //fill kind and Nodeptr + ParentExpression->impl.operation.kind = Bitwise; + ParentExpression->impl.operation.nodePtr = currentNode; + + //fill Operand + Expression* expression = createExpression(currentNode->children[0]); + if(NULL == expression){ + return 1; + } + g_array_append_val(ParentExpression->impl.operation.operands , expression); + + ParentExpression->impl.operation.impl.bitwise = BitwiseNot; + + Type* Operand = ((Expression**)ParentExpression->impl.operation.operands)[0]->result; + + Type* result = malloc(sizeof(Type)); + result->nodePtr = currentNode; + + + if (Operand->kind == TypeKindPrimitive){ + if(Operand->impl.primitive == Float){ + return SEMANTIC_ERROR; + } + result->kind = TypeKindPrimitive; + result->impl.primitive = Int; + }else if(Operand->kind == TypeKindComposite){ + if (Operand->impl.composite.primitive == Float){ + return SEMANTIC_ERROR; + } + result->kind = TypeKindComposite; + result->impl.composite.nodePtr = currentNode; + result->impl.composite.primitive = Int; + result->impl.composite.sign = Operand->impl.composite.sign; + result->impl.composite.scale = Operand->impl.composite.scale; + } + + ParentExpression->result = result; + return SEMANTIC_OK; } @@ -516,11 +723,12 @@ Expression *createExpression(AST_NODE_PTR currentNode){ expression->kind = ExpressionKindConstant; expression->impl.constant = createTypeValue(currentNode); expression->result = expression->impl.constant.type; - + break; case AST_String: expression->kind = ExpressionKindConstant; expression->impl.constant = createString(currentNode); expression->result = expression->impl.constant.type; + break; case AST_Ident: expression->kind = ExpressionKindVariable; expression->impl.variable = getVariableFromScope(currentNode->value); @@ -531,13 +739,15 @@ Expression *createExpression(AST_NODE_PTR currentNode){ switch (expression->impl.variable->kind) { case VariableKindDeclaration: expression->result = expression->impl.variable->impl.declaration.type; + break; case VariableKindDefinition: expression->result = expression->impl.variable->impl.definiton.declaration.type; + break; default: PANIC("current Variable should not be an BoxMember"); break; } - + break; case AST_Add: case AST_Sub: case AST_Mul: @@ -545,14 +755,14 @@ Expression *createExpression(AST_NODE_PTR currentNode){ expression->kind = ExpressionKindOperation; if(createArithOperation(expression, currentNode, 2)){ return NULL; - } + } + break; case AST_Negate: expression->kind = ExpressionKindOperation; if(createArithOperation(expression,currentNode, 1)){ return NULL; } - - + break; case AST_Eq: case AST_Less: case AST_Greater: @@ -560,7 +770,7 @@ Expression *createExpression(AST_NODE_PTR currentNode){ if(createRelationalOperation(expression,currentNode)){ return NULL; } - + break; case AST_BoolAnd: case AST_BoolOr: case AST_BoolXor: @@ -568,12 +778,13 @@ Expression *createExpression(AST_NODE_PTR currentNode){ if(createBoolOperation(expression,currentNode)){ return NULL; } + break; case AST_BoolNot: expression->kind= ExpressionKindOperation; if(createBoolNotOperation(expression, currentNode)){ return NULL; } - + break; case AST_BitAnd: case AST_BitOr: case AST_BitXor: @@ -581,8 +792,13 @@ Expression *createExpression(AST_NODE_PTR currentNode){ if(createBitOperation(expression, currentNode)){ return NULL; } - + break; case AST_BitNot: + expression->kind = ExpressionKindOperation; + if(createBitNotOperation(expression, currentNode)){ + return NULL; + } + break; case AST_IdentList: //Box Accsess @@ -590,12 +806,14 @@ Expression *createExpression(AST_NODE_PTR currentNode){ // Box Self Access case AST_Typekind: case AST_Transmute: - + + default: PANIC("Node is not an expression but from kind: %i", currentNode->kind); break; } + return expression; } Module *create_set(AST_NODE_PTR currentNode){ @@ -643,12 +861,6 @@ Module *create_set(AST_NODE_PTR currentNode){ DEBUG("filled successfull the module and scope with vars"); break; case AST_Def: - if (1 == fillTablesWithVars(variables,globalscope,createDef(currentNode->children[i]) ,currentNode->children[i]->children[currentNode->children[i]->child_count -1]->child_count)){ - //TODO behandlung, wenn var schon existiert - DEBUG("var already exists"); - break; - } - DEBUG("filled successfull the module and scope with vars"); case AST_Box: case AST_Fun: case AST_Import: diff --git a/src/set/set.h b/src/set/set.h index 033dee5..1ec9e85 100644 --- a/src/set/set.h +++ b/src/set/set.h @@ -3,6 +3,9 @@ #include +#define SEMANTIC_OK 0 +#define SEMANTIC_ERROR 1 + void create_set(AST_NODE_PTR rootNodePtr ); #endif From 40ba9ad95dc25c6d436da16b537b559e14d3e869 Mon Sep 17 00:00:00 2001 From: Filleo Date: Mon, 3 Jun 2024 21:52:49 +0200 Subject: [PATCH 065/124] commit before merge --- src/set/set.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/set/set.c b/src/set/set.c index 1e385cb..c2761ea 100644 --- a/src/set/set.c +++ b/src/set/set.c @@ -133,13 +133,13 @@ int impl_composite_type(AST_NODE_PTR ast_type, CompositeType* composite) { } } - const char* typeKind = ast_type->children[ast_type->child_count - 1]->value; + AST_NODE_PTR typeKind = ast_type->children[ast_type->child_count - 1]; - status = primitive_from_string(typeKind, &composite->primitive); + status = primitive_from_string(typeKind->value, &composite->primitive); if (status == SEMANTIC_ERROR) { // not a primitive try to resolve the type by name (must be a composite) - status = impl_composite_type(); + } return SEMANTIC_OK; @@ -861,6 +861,8 @@ Module *create_set(AST_NODE_PTR currentNode){ DEBUG("filled successfull the module and scope with vars"); break; case AST_Def: + DEBUG("created Definition successfully"); + break; case AST_Box: case AST_Fun: case AST_Import: @@ -868,7 +870,7 @@ Module *create_set(AST_NODE_PTR currentNode){ g_array_append_val(imports, currentNode->children[i]->value); break; default: - INFO("Provided source file could not be parsed beecause of semantic error."); + INFO("Provided source file could not be parsed because of semantic error."); break; } From 4d33c81c3feed46752baadb09ebedc254a48a922 Mon Sep 17 00:00:00 2001 From: Filleo Date: Mon, 3 Jun 2024 23:58:19 +0200 Subject: [PATCH 066/124] major reconstruction of SET Co-authored-by: servostar Co-authored-by: SirTalksalot75 --- src/set/set.c | 673 +++++++++++++++++++++++++++++++----------------- src/set/set.h | 3 +- src/set/types.h | 2 +- 3 files changed, 434 insertions(+), 244 deletions(-) diff --git a/src/set/set.c b/src/set/set.c index c2761ea..f63aa83 100644 --- a/src/set/set.c +++ b/src/set/set.c @@ -1,3 +1,5 @@ +#include "io/files.h" +#include "yacc/parser.tab.h" #include #include #include @@ -38,6 +40,8 @@ const Type StringLiteralType = { * @return 0 on success, 1 otherwise */ int sign_from_string(const char* string, Sign* sign) { + assert(string != NULL); + assert(sign != NULL); if (strcmp(string, "unsigned") == 0) { *sign = Unsigned; @@ -55,6 +59,8 @@ int sign_from_string(const char* string, Sign* sign) { * @return 0 on success, 1 otherwise */ int primitive_from_string(const char* string, PrimitiveType* primitive) { + assert(string != NULL); + assert(primitive != NULL); if (strcmp(string, "int") == 0) { *primitive = Int; @@ -68,6 +74,9 @@ int primitive_from_string(const char* string, PrimitiveType* primitive) { } int scale_factor_from(const char* string, double* factor) { + assert(string != NULL); + assert(factor != NULL); + if (strcmp(string, "half") == 0 || strcmp(string, "short") == 0) { *factor = 0.5; return SEMANTIC_OK; @@ -79,7 +88,24 @@ int scale_factor_from(const char* string, double* factor) { return SEMANTIC_ERROR; } +int check_scale_factor(AST_NODE_PTR node, Scale scale) { + assert(node != NULL); + + if (8 > scale) { + print_diagnostic(current_file, &node->location, Error, "Composite scale overflow"); + return SEMANTIC_ERROR; + } + if (0.25 > scale) { + print_diagnostic(current_file, &node->location, Error, "Composite scale underflow"); + return SEMANTIC_ERROR; + } + return SEMANTIC_OK; +} + int merge_scale_list(AST_NODE_PTR scale_list, Scale* scale) { + assert(scale_list != NULL); + assert(scale != NULL); + for (size_t i = 0; i < scale_list->child_count; i++) { double scale_in_list = 1.0; @@ -90,24 +116,39 @@ int merge_scale_list(AST_NODE_PTR scale_list, Scale* scale) { } *scale *= scale_in_list; - - if (0.25 > *scale || 8 > *scale) { - // TODO: print diagnostic: Invalid composite scale - return SEMANTIC_ERROR; - } } return SEMANTIC_OK; } -Type *findType(AST_NODE_PTR currentNode); +/** + * @brief Get an already declared type from its name + */ +int get_type_decl(const char* name, Type** type) { + assert(name != NULL); + assert(type != NULL); + + if (g_hash_table_contains(declaredComposites, name) == TRUE) { + + *type = (Type*) g_hash_table_lookup(declaredComposites, name); + + return SEMANTIC_OK; + } + + return SEMANTIC_ERROR; +} int impl_composite_type(AST_NODE_PTR ast_type, CompositeType* composite) { + assert(ast_type != NULL); + assert(composite != NULL); + DEBUG("Type is a Composite"); int status = SEMANTIC_OK; int scaleNodeOffset = 0; + composite->sign = Signed; + // check if we have a sign if (AST_Sign == ast_type->children[0]->kind) { @@ -137,12 +178,37 @@ int impl_composite_type(AST_NODE_PTR ast_type, CompositeType* composite) { status = primitive_from_string(typeKind->value, &composite->primitive); + // type kind is not primitve, must be a predefined composite + if (status == SEMANTIC_ERROR) { // not a primitive try to resolve the type by name (must be a composite) - + Type* nested_type = NULL; + status = get_type_decl(typeKind->value, &nested_type); + + if (status == SEMANTIC_ERROR) { + print_diagnostic(current_file, &typeKind->location, Error, "Unknown composite type in declaration"); + return SEMANTIC_ERROR; + } + + if (nested_type->kind == TypeKindComposite) { + // valid composite type + + composite->primitive = nested_type->impl.composite.primitive; + + // no sign was set, use sign of type + if (scaleNodeOffset == 0) { + composite->sign = nested_type->impl.composite.sign; + } + + composite->scale = composite->scale * nested_type->impl.composite.scale; + + } else { + print_diagnostic(current_file, &typeKind->location, Error, "Type must be either composite or primitive"); + return SEMANTIC_ERROR; + } } - return SEMANTIC_OK; + return check_scale_factor(ast_type, composite->scale); } /** @@ -150,86 +216,53 @@ int impl_composite_type(AST_NODE_PTR ast_type, CompositeType* composite) { * @param currentNode AST node of type kind type * @return the gemstone type implementation */ -Type *findType(AST_NODE_PTR currentNode) { +int get_type_impl(AST_NODE_PTR currentNode, Type** type) { assert(currentNode != NULL); assert(currentNode->kind == AST_Type); assert(currentNode->child_count > 0); + int status; + const char *typekind = currentNode->children[currentNode->child_count -1]->value; - - // type implementation - Type *type = malloc(sizeof(Type)); - type->nodePtr = currentNode; - // primitive type OR composit - if (0 == strcmp(typekind, "int") || 0 == strcmp(typekind, "float")) { - - if(AST_Typekind != currentNode->children[0]->kind) { - - type->kind = TypeKindComposite; - type->impl.composite.nodePtr = currentNode; - impl_composite_type(currentNode, &type->impl.composite, typekind); - - } else { - // type is a primitive - type->kind = TypeKindPrimitive; - - int primitive_invalid = primitive_from_string(typekind, &type->impl.primitive); - - if (primitive_invalid) { - PANIC("invalid primitive: %s", typekind); - } - } - - }else if(g_hash_table_contains(declaredBoxes, typekind)){ - if(AST_Typekind != currentNode->children[0]->kind){ - //TODO composite Box try - } - return (Type *) g_hash_table_lookup(declaredBoxes, typekind); - }else if(g_hash_table_contains(declaredComposites, typekind)){ - if(AST_Typekind != currentNode->children[0]->kind){ - Type *composite = malloc(sizeof(Type)); - - *composite = *(Type*) g_hash_table_lookup(declaredComposites, typekind); - - - - size_t scalelist = 0; - if(AST_Sign == currentNode->children[0]->kind){ - if(0 == strcmp(currentNode->children[0]->value, "unsigned")){ - composite->impl.composite.sign = Unsigned; - }else if(0 == strcmp(currentNode->children[0]->value, "unsigned")){ - composite->impl.composite.sign = Signed; - } - scalelist = 1; - } - - - if(AST_List == currentNode->children[scalelist]->kind){ - for (size_t i = 0; i < currentNode->children[scalelist]->child_count; i++){ - if (0 == strcmp(currentNode->children[scalelist]->children[i]->value, "short") || 0 == strcmp(currentNode->children[scalelist]->children[i]->value, "half")){ - composite->impl.composite.scale /= 2; - }else{ - composite->impl.composite.scale *= 2; - } - if (0.25 > composite->impl.composite.scale || 8 > composite->impl.composite.scale) { - //TODO scale not right - return NULL; - } - } - } - return composite; - } - return (Type *) g_hash_table_lookup(declaredComposites, typekind); - }else{ - //TODO doesnt know typekind - return NULL; + if (g_hash_table_contains(declaredComposites, typekind) == TRUE) { + *type = g_hash_table_lookup(declaredComposites, typekind); + return SEMANTIC_OK; } - return NULL; + + if (g_hash_table_contains(declaredBoxes, typekind) == TRUE) { + *type = g_hash_table_lookup(declaredBoxes, typekind); + return SEMANTIC_OK; + } + + // type is not yet declared, make a new one + + Type* new_type = malloc(sizeof(Type)); + new_type->nodePtr = currentNode; + + // only one child means either composite or primitive + // try to implement primitive first + // if not successfull continue building a composite + if(currentNode->child_count == 1) { + // type is a primitive + new_type->kind = TypeKindPrimitive; + + status = primitive_from_string(typekind, &new_type->impl.primitive); + + // if err continue at composite construction + if (status == SEMANTIC_OK) { + return SEMANTIC_OK; + } + } + + new_type->kind = TypeKindComposite; + new_type->impl.composite.nodePtr = currentNode; + status = impl_composite_type(currentNode, &new_type->impl.composite); + *type = new_type; + + return status; } - - StorageQualifier Qualifier_from_string(const char *str) { if (!strncmp(str, "local", 5)) return Local; if (!strncmp(str, "static", 6)) return Static; @@ -237,73 +270,127 @@ StorageQualifier Qualifier_from_string(const char *str) { PANIC("Provided string is not a storagequalifier: %s", str); } -Variable **createDecl(AST_NODE_PTR currentNode){ +int createDecl(AST_NODE_PTR currentNode, GArray** variables) { DEBUG("create declaration"); - Variable **variables = malloc(currentNode->children[currentNode->child_count -1]->child_count * sizeof(Variable*)); + + AST_NODE_PTR ident_list = currentNode->children[currentNode->child_count - 1]; + + *variables = g_array_new(FALSE, FALSE, sizeof(Variable*)); VariableDeclaration decl; decl.nodePtr = currentNode; + int status = SEMANTIC_OK; + + DEBUG("Child Count: %i", currentNode->child_count); + + for (size_t i = 0; i < currentNode->child_count; i++) { + switch(currentNode->children[i]->kind){ + case AST_Storage: + DEBUG("fill Qualifier"); + decl.qualifier = Qualifier_from_string(currentNode->children[i]->value); + break; + case AST_Type: + DEBUG("fill Type"); + status = get_type_impl(currentNode->children[i], &decl.type); + break; + case AST_IdentList: + break; + default: + PANIC("invalid node type: %ld", currentNode->children[i]->kind); + break; + } + } + + for(size_t i = 0; i < ident_list->child_count; i++) { + Variable* variable = malloc(sizeof(Variable)); + + variable->kind = VariableKindDeclaration; + variable->nodePtr = currentNode; + variable->name = ident_list->children[i]->value; + variable->impl.declaration = decl; + + g_array_append_val(*variables, variable); + } + + return status; +} + +int createDef(AST_NODE_PTR currentNode, GArray** variables) { + assert(variables != NULL); + assert(currentNode != NULL); + + DEBUG("create definition"); + + AST_NODE_PTR declaration = currentNode->children[currentNode->child_count - 1]; + + * variables = g_array_new(FALSE, FALSE, sizeof(Variable*)); + + VariableDefiniton def; + def.nodePtr = currentNode; + + Variable* variable = malloc(sizeof(Variable)); + variable->kind = VariableKindDefinition; + variable->nodePtr = currentNode; + variable->name = declaration->children[1]->value; + variable->impl.definiton= def; + g_array_append_val(*variables, variable); + + int status = SEMANTIC_OK; + DEBUG("Child Count: %i", currentNode->child_count); for (size_t i = 0; i < currentNode->child_count; i++){ - switch(currentNode->children[i]->kind){ - case AST_Storage: - DEBUG("fill Qualifier"); - decl.qualifier = Qualifier_from_string(currentNode->children[i]->value); - break; - case AST_Type: - DEBUG("fill Type"); - decl.type = findType(currentNode->children[i]); - break; - case AST_IdentList: - for(size_t i = 0; i < currentNode->children[currentNode->child_count -1]->child_count; i++){ - Variable *variable = malloc(sizeof(Variable)); - variable->kind = VariableKindDeclaration; - variable->nodePtr = currentNode; - variable->name = currentNode->children[currentNode->child_count -1]->children[i]->value; - variable->impl.declaration = decl; - variables[i] = variable; - } - break; - default: - //TODO PANIC maybe - break; + switch(currentNode->children[i]->kind) { + case AST_Decl: + break; + default: + PANIC("invalid node type: %ld", currentNode->children[i]->kind); + break; } } + return status; +} + +int getVariableFromScope(const char* name, Variable** variable) { + assert(name != NULL); + assert(variable != NULL); + assert(Scope != NULL); + + // loop through all variable scope and find a variable + for(size_t i = 0; i < Scope->len; i++) { + GHashTable* variable_table = ((GHashTable**) Scope->data)[i]; + + if(g_hash_table_contains(variable_table, name)) { + *variable = g_hash_table_lookup(variable_table, name); + return SEMANTIC_OK; + } + } + + return SEMANTIC_ERROR; +} + +int fillTablesWithVars(GHashTable *variableTable, GHashTable *currentScope , GArray* variables) { + DEBUG("filling vars in scope and table"); + + for(size_t i = 0; i < variables->len; i++) { + Variable* var = (Variable*) variables->data + i; + + // this variable is discarded, only need status code + Variable* tmp = NULL; + if(getVariableFromScope(var->name, &tmp) == SEMANTIC_OK) { + INFO("this var already exist: ", var->name); + return SEMANTIC_ERROR; + } + + g_hash_table_insert(variableTable, (gpointer) var->name, var); + g_hash_table_insert(currentScope, (gpointer) var->name, var); + } - return variables; + return SEMANTIC_OK; } -Variable* getVariableFromScope(const char* name){ - for(size_t i = 0; i < Scope->len; i++){ - if(g_hash_table_contains(((GHashTable **) Scope->data)[i], name)) - { - return g_hash_table_lookup(((GHashTable**)Scope->data)[i], name); - } - } - return NULL; -} - - - -int fillTablesWithVars(GHashTable *variableTable,GHashTable *currentScope , Variable** content, size_t amount){ - DEBUG("filling vars in scope and table"); - for(size_t i = 0; i < amount; i++){ - if(!(NULL == getVariableFromScope(content[i]->name))){ - DEBUG("this var already exist: ",content[i]->name); - return 1; - } - g_hash_table_insert(variableTable, (gpointer) content[i]->name, content[i] ); - g_hash_table_insert(currentScope, (gpointer) content[i]->name, content[i] ); - } - return 0; -} - - - - - +[[nodiscard("type must be freed")]] TypeValue createTypeValue(AST_NODE_PTR currentNode){ TypeValue value; Type *type = malloc(sizeof(Type)); @@ -312,40 +399,36 @@ TypeValue createTypeValue(AST_NODE_PTR currentNode){ type->nodePtr = currentNode; switch (currentNode->kind) { - case AST_Int: type->impl.primitive = Int; case AST_Float: - type->impl.primitive = Int; + type->impl.primitive = Float; default: - PANIC("Node is not an expression but from kind: %i", currentNode->kind); + PANIC("Node is not an expression but from kind: %i", currentNode->kind); break; - } + } value.nodePtr = currentNode; value.value = currentNode->value; return value; } -TypeValue createString(AST_NODE_PTR currentNode){ +TypeValue createString(AST_NODE_PTR currentNode) { TypeValue value; - Type *type =(Type*) &StringLiteralType; + Type *type = (Type*) &StringLiteralType; value.type = type; value.nodePtr = currentNode; value.value = currentNode->value; return value; } -Expression *createExpression(AST_NODE_PTR currentNode); +Expression* createExpression(AST_NODE_PTR currentNode); - -Type* createTypeFromOperands(Type* LeftOperandType, Type* RightOperandType, AST_NODE_PTR currentNode){ +Type* createTypeFromOperands(Type* LeftOperandType, Type* RightOperandType, AST_NODE_PTR currentNode) { Type *result = malloc(sizeof(Type)); result->nodePtr = currentNode; - - if(LeftOperandType->kind == TypeKindComposite && RightOperandType->kind == TypeKindComposite) - { + if (LeftOperandType->kind == TypeKindComposite && RightOperandType->kind == TypeKindComposite) { result->kind = TypeKindComposite; CompositeType resultImpl; @@ -353,81 +436,87 @@ Type* createTypeFromOperands(Type* LeftOperandType, Type* RightOperandType, AST_ resultImpl.sign = MAX(LeftOperandType->impl.composite.sign, RightOperandType->impl.composite.sign); resultImpl.scale = MAX(LeftOperandType->impl.composite.scale, RightOperandType->impl.composite.scale); resultImpl.primitive = MAX(LeftOperandType->impl.composite.primitive , RightOperandType->impl.composite.primitive); - - result->impl.composite = resultImpl; + result->impl.composite = resultImpl; - } else if(LeftOperandType->kind == TypeKindPrimitive && RightOperandType->kind == TypeKindPrimitive){ + } else if (LeftOperandType->kind == TypeKindPrimitive && RightOperandType->kind == TypeKindPrimitive) { result->kind = TypeKindPrimitive; result->impl.primitive = MAX(LeftOperandType->impl.primitive , RightOperandType->impl.primitive); - } else if(LeftOperandType->kind == TypeKindPrimitive && RightOperandType->kind == TypeKindComposite){ + } else if (LeftOperandType->kind == TypeKindPrimitive && RightOperandType->kind == TypeKindComposite) { result->kind = TypeKindComposite; result->impl.composite.sign = Signed; - result->impl.composite.scale = MAX( 1.0, RightOperandType->impl.composite.scale); + result->impl.composite.scale = MAX(1.0, RightOperandType->impl.composite.scale); result->impl.composite.primitive = MAX(Int, RightOperandType->impl.composite.primitive); result->impl.composite.nodePtr = currentNode; - } else if(LeftOperandType->kind == TypeKindComposite && RightOperandType->kind == TypeKindPrimitive){ + } else if (LeftOperandType->kind == TypeKindComposite && RightOperandType->kind == TypeKindPrimitive) { result->kind = TypeKindComposite; result->impl.composite.sign = Signed; - result->impl.composite.scale = MAX( 1.0, LeftOperandType->impl.composite.scale); + result->impl.composite.scale = MAX(1.0, LeftOperandType->impl.composite.scale); result->impl.composite.primitive = MAX(Int, LeftOperandType->impl.composite.primitive); result->impl.composite.nodePtr = currentNode; - }else{ + } else { + free(result); return NULL; } return result; } -int createArithOperation(Expression* ParentExpression, AST_NODE_PTR currentNode, size_t expectedChildCount){ +int createArithOperation(Expression* ParentExpression, AST_NODE_PTR currentNode, [[maybe_unused]] size_t expectedChildCount) { ParentExpression->impl.operation.kind = Arithmetic; ParentExpression->impl.operation.nodePtr = currentNode; - if (expectedChildCount > currentNode->child_count){ - PANIC("Operation has to many children"); - } - for (size_t i = 0; i < currentNode->child_count; i++){ + + assert(expectedChildCount > currentNode->child_count); + + for (size_t i = 0; i < currentNode->child_count; i++) { Expression* expression = createExpression(currentNode->children[i]); - if(NULL == expression){ - return 1; - } - g_array_append_val(ParentExpression->impl.operation.operands , expression); + if(NULL == expression) { + return SEMANTIC_OK; + } + + g_array_append_val(ParentExpression->impl.operation.operands, expression); } - switch (currentNode->kind){ + switch (currentNode->kind) { case AST_Add: ParentExpression->impl.operation.impl.arithmetic = Add; + break; case AST_Sub: ParentExpression->impl.operation.impl.arithmetic = Sub; + break; case AST_Mul: ParentExpression->impl.operation.impl.arithmetic = Mul; + break; case AST_Div: ParentExpression->impl.operation.impl.arithmetic = Div; + break; case AST_Negate: ParentExpression->impl.operation.impl.arithmetic = Negate; + break; default: PANIC("Current node is not an arithmetic operater"); - break; + break; } - - if(ParentExpression->impl.operation.impl.arithmetic == Negate){ - Type* result = malloc(sizeof(Type)); - result = ((Expression**) ParentExpression->impl.operation.operands->data)[0]->result; + if (ParentExpression->impl.operation.impl.arithmetic == Negate) { + Type* result = ((Expression**) ParentExpression->impl.operation.operands->data)[0]->result; result->nodePtr = currentNode; - if (result->kind == TypeKindReference || result->kind == TypeKindBox){ - return 1; - }else if(result->kind == TypeKindComposite){ + + if (result->kind == TypeKindReference || result->kind == TypeKindBox) { + print_diagnostic(current_file, ¤tNode->location, Error, "Invalid type for arithmetic operation"); + return SEMANTIC_ERROR; + } else if(result->kind == TypeKindComposite) { result->impl.composite.sign = Signed; } ParentExpression->result = result; - }else{ + } else { Type* LeftOperandType = ((Expression**) ParentExpression->impl.operation.operands->data)[0]->result; Type* RightOperandType = ((Expression**) ParentExpression->impl.operation.operands->data)[1]->result; @@ -435,41 +524,44 @@ int createArithOperation(Expression* ParentExpression, AST_NODE_PTR currentNode, ParentExpression->result = createTypeFromOperands(LeftOperandType, RightOperandType, currentNode); } - if(ParentExpression->result == NULL){ - return 1; + if (ParentExpression->result == NULL) { + return SEMANTIC_ERROR; } - - return 0; + return SEMANTIC_OK; } -int createRelationalOperation(Expression* ParentExpression,AST_NODE_PTR currentNode){ - //fill kind and Nodeptr +int createRelationalOperation(Expression* ParentExpression, AST_NODE_PTR currentNode) { + // fill kind and Nodeptr ParentExpression->impl.operation.kind = Relational; ParentExpression->impl.operation.nodePtr = currentNode; - //fill Operands - for (size_t i = 0; i < currentNode->child_count; i++){ + // fill Operands + for (size_t i = 0; i < currentNode->child_count; i++) { Expression* expression = createExpression(currentNode->children[i]); if(NULL == expression){ - return 1; + return SEMANTIC_ERROR; } - g_array_append_val(ParentExpression->impl.operation.operands , expression); + g_array_append_val(ParentExpression->impl.operation.operands, expression); } - //fill impl - switch (currentNode->kind){ - case AST_Eq: - ParentExpression->impl.operation.impl.relational = Equal; - case AST_Less: - ParentExpression->impl.operation.impl.relational = Greater; - case AST_Greater: - ParentExpression->impl.operation.impl.relational= Less; - default: - PANIC("Current node is not an relational operater"); - break; + // fill impl + switch (currentNode->kind) { + case AST_Eq: + ParentExpression->impl.operation.impl.relational = Equal; + break; + case AST_Less: + ParentExpression->impl.operation.impl.relational = Greater; + break; + case AST_Greater: + ParentExpression->impl.operation.impl.relational= Less; + break; + default: + PANIC("Current node is not an relational operater"); + break; } - Type * result = malloc(sizeof(Type)); + + Type* result = malloc(sizeof(Type)); result->impl.primitive = Int; result->kind = TypeKindPrimitive; result->nodePtr = currentNode; @@ -478,66 +570,76 @@ int createRelationalOperation(Expression* ParentExpression,AST_NODE_PTR currentN return 0; } - -int createBoolOperation(Expression *ParentExpression, AST_NODE_PTR currentNode){ - //fill kind and Nodeptr +int createBoolOperation(Expression *ParentExpression, AST_NODE_PTR currentNode) { + // fill kind and Nodeptr ParentExpression->impl.operation.kind = Boolean; ParentExpression->impl.operation.nodePtr = currentNode; - //fill Operands + // fill Operands for (size_t i = 0; i < currentNode->child_count; i++){ Expression* expression = createExpression(currentNode->children[i]); - if(NULL == expression){ - return 1; + if (NULL == expression) { + return SEMANTIC_ERROR; } - g_array_append_val(ParentExpression->impl.operation.operands , expression); + g_array_append_val(ParentExpression->impl.operation.operands, expression); } - switch (currentNode->kind){ - case AST_BoolAnd: - ParentExpression->impl.operation.impl.boolean = BooleanAnd; - case AST_BoolOr: - ParentExpression->impl.operation.impl.boolean = BooleanOr; - case AST_BoolXor: - ParentExpression->impl.operation.impl.boolean = BooleanXor; - default: - PANIC("Current node is not an boolean operater"); - break; + switch (currentNode->kind) { + case AST_BoolAnd: + ParentExpression->impl.operation.impl.boolean = BooleanAnd; + break; + case AST_BoolOr: + ParentExpression->impl.operation.impl.boolean = BooleanOr; + break; + case AST_BoolXor: + ParentExpression->impl.operation.impl.boolean = BooleanXor; + break; + default: + PANIC("Current node is not an boolean operater"); + break; } + Expression* lhs = ((Expression**) ParentExpression->impl.operation.operands->data)[0]; + Expression* rhs = ((Expression**) ParentExpression->impl.operation.operands->data)[1]; - Type* LeftOperandType = ((Expression**) ParentExpression->impl.operation.operands->data)[0]->result; - Type* RightOperandType = ((Expression**) ParentExpression->impl.operation.operands->data)[1]->result; + Type* LeftOperandType = lhs->result; + Type* RightOperandType = rhs->result; - //should not be a box or a reference - if(LeftOperandType->kind != TypeKindPrimitive && LeftOperandType->kind != TypeKindComposite){ - return 1; + // should not be a box or a reference + if(LeftOperandType->kind != TypeKindPrimitive && LeftOperandType->kind != TypeKindComposite) { + print_diagnostic(current_file, &lhs->nodePtr->location, Error, "invalid type for boolean operation"); + return SEMANTIC_ERROR; } - if(RightOperandType->kind != TypeKindPrimitive && RightOperandType->kind != TypeKindComposite){ - return 1; + if(RightOperandType->kind != TypeKindPrimitive && RightOperandType->kind != TypeKindComposite) { + print_diagnostic(current_file, &rhs->nodePtr->location, Error, "invalid type for boolean operation"); + return SEMANTIC_ERROR; } - //should not be a float - if(LeftOperandType->kind == TypeKindComposite){ - if(LeftOperandType->impl.composite.primitive == Float){ - return 1; + // should not be a float + if (LeftOperandType->kind == TypeKindComposite) { + if (LeftOperandType->impl.composite.primitive == Float) { + print_diagnostic(current_file, &lhs->nodePtr->location, Error, "operand must not be a float"); + return SEMANTIC_ERROR; } - }else if(LeftOperandType->kind == TypeKindPrimitive){ - if(LeftOperandType->impl.primitive == Float){ - return 1; + } else if (LeftOperandType->kind == TypeKindPrimitive) { + if (LeftOperandType->impl.primitive == Float) { + print_diagnostic(current_file, &lhs->nodePtr->location, Error, "operand must not be a float"); + return SEMANTIC_ERROR; } - }else if(RightOperandType->kind == TypeKindComposite){ - if(RightOperandType->impl.composite.primitive == Float){ - return 1; + } else if (RightOperandType->kind == TypeKindComposite) { + if (RightOperandType->impl.composite.primitive == Float) { + print_diagnostic(current_file, &rhs->nodePtr->location, Error, "operand must not be a float"); + return SEMANTIC_ERROR; } - }else if(RightOperandType->kind == TypeKindPrimitive){ - if(RightOperandType->impl.primitive == Float){ - return 1; + } else if (RightOperandType->kind == TypeKindPrimitive) { + if (RightOperandType->impl.primitive == Float) { + print_diagnostic(current_file, &rhs->nodePtr->location, Error, "operand must not be a float"); + return SEMANTIC_ERROR; } } - ParentExpression->result = createTypeFromOperands(LeftOperandType, RightOperandType, currentNode); - return 0; + + return SEMANTIC_OK; } int createBoolNotOperation(Expression *ParentExpression, AST_NODE_PTR currentNode){ @@ -590,11 +692,11 @@ bool isScaleEqual(double leftScale, double rightScale){ } int createBitOperation(Expression* ParentExpression, AST_NODE_PTR currentNode){ - //fill kind and Nodeptr + // fill kind and Nodeptr ParentExpression->impl.operation.kind = Boolean; ParentExpression->impl.operation.nodePtr = currentNode; - //fill Operands + // fill Operands for (size_t i = 0; i < currentNode->child_count; i++){ Expression* expression = createExpression(currentNode->children[i]); if(NULL == expression){ @@ -712,6 +814,78 @@ int createBitNotOperation(Expression* ParentExpression, AST_NODE_PTR currentNode return SEMANTIC_OK; } +GArray* getBoxMember(Type* currentBoxType, GArray *names){ + + + GArray *members = g_array_new(FALSE, FALSE, sizeof(BoxMember)); + GHashTable* memberList = currentBoxType->impl.box.member; + + const char* currentName = ((const char **) names)[0]; + if(!g_hash_table_contains(memberList, currentName)){ + // TODO: free members + return NULL; + } + BoxMember * currentMember = g_hash_table_lookup(memberList, currentName); + g_array_append_val(members, currentMember); + + g_array_remove_index(names,0); + if (names->len == 0){ + return members; + } + if (currentMember->type->kind == TypeKindBox){ + GArray *otherMember = getBoxMember(currentMember->type, names); + if(NULL == otherMember){ + return NULL; + } + g_array_append_vals(members,(BoxMember *) otherMember->data, otherMember->len); + return members; + } + return NULL; +} + +int createBoxAccess(Expression* ParentExpression,AST_NODE_PTR currentNode) { + + const char* boxname = currentNode->children[0]->value; + Variable* boxVariable = NULL; + int status = getVariableFromScope(boxname, &boxVariable); + + if(status == SEMANTIC_ERROR){ + return SEMANTIC_ERROR; + } + Type* boxType; + + if(boxVariable->kind == VariableKindDeclaration){ + + boxType = boxVariable->impl.declaration.type; + } else if (boxVariable->kind == VariableKindDefinition){ + boxType = boxVariable->impl.definiton.declaration.type; + } else{ + return SEMANTIC_ERROR; + } + if (boxType->kind != TypeKindBox){ + return SEMANTIC_ERROR; + } + //filling boxAccess variable + ParentExpression->impl.variable->kind = VariableKindBoxMember; + ParentExpression->impl.variable->nodePtr = currentNode; + ParentExpression->impl.variable->name = NULL; + ParentExpression->impl.variable->impl.member.nodePtr = currentNode; + + //filling boxacces.variable + ParentExpression->impl.variable->impl.member.variable = boxVariable; + + //first one is the box itself + GArray* names = malloc(sizeof(GArray)); + for (size_t i = 1; i < currentNode->child_count; i++){ + g_array_append_val(names, currentNode->children[1]->value); + } + + GArray * boxMember = getBoxMember(boxType, names); + ParentExpression->impl.variable->impl.member.member = boxMember; + ParentExpression->result = ((BoxMember *)boxMember->data)[boxMember->len].type; + return SEMANTIC_OK; + +} Expression *createExpression(AST_NODE_PTR currentNode){ Expression *expression = malloc(sizeof(Expression)); @@ -731,8 +905,8 @@ Expression *createExpression(AST_NODE_PTR currentNode){ break; case AST_Ident: expression->kind = ExpressionKindVariable; - expression->impl.variable = getVariableFromScope(currentNode->value); - if(NULL == expression->impl.variable){ + int status = getVariableFromScope(currentNode->value, &expression->impl.variable ); + if(status == SEMANTIC_ERROR){ DEBUG("Identifier is not in current scope"); return NULL; } @@ -801,6 +975,8 @@ Expression *createExpression(AST_NODE_PTR currentNode){ break; case AST_IdentList: + expression->kind = ExpressionKindVariable; + //Box Accsess case AST_List: // Box Self Access @@ -816,6 +992,12 @@ Expression *createExpression(AST_NODE_PTR currentNode){ return expression; } + + + + + + Module *create_set(AST_NODE_PTR currentNode){ DEBUG("create root Module"); //create tables for types @@ -852,17 +1034,24 @@ Module *create_set(AST_NODE_PTR currentNode){ DEBUG("created Child: %i" ,currentNode->children[i]->kind); switch(currentNode->children[i]->kind){ - case AST_Decl: - if (1 == fillTablesWithVars(variables,globalscope,createDecl(currentNode->children[i]) ,currentNode->children[i]->children[currentNode->children[i]->child_count -1]->child_count)){ - //TODO behandlung, wenn var schon existiert - DEBUG("var already exists"); + case AST_Decl: { + GArray* vars; + int status = createDecl(currentNode->children[i], &vars); + + if (fillTablesWithVars(variables, globalscope, vars) == SEMANTIC_ERROR) { + print_diagnostic(current_file, ¤tNode->children[i]->location, Error, "Variable already declared"); + INFO("var already exists"); break; } DEBUG("filled successfull the module and scope with vars"); break; - case AST_Def: + } + case AST_Def: { + GArray* vars; + int status = createDef(currentNode->children[i], &vars); DEBUG("created Definition successfully"); break; + } case AST_Box: case AST_Fun: case AST_Import: diff --git a/src/set/set.h b/src/set/set.h index 1ec9e85..e7a5048 100644 --- a/src/set/set.h +++ b/src/set/set.h @@ -2,10 +2,11 @@ #define _SET_H_ #include +#include #define SEMANTIC_OK 0 #define SEMANTIC_ERROR 1 -void create_set(AST_NODE_PTR rootNodePtr ); +Module * create_set(AST_NODE_PTR rootNodePtr ); #endif diff --git a/src/set/types.h b/src/set/types.h index 08e8418..2e5e1ff 100644 --- a/src/set/types.h +++ b/src/set/types.h @@ -79,7 +79,7 @@ typedef struct BoxMember_t { } BoxMember; /** - * @brief Essentially a glorified struct + * @brief Essentially a g lorified struct * */ typedef struct BoxType_t { From 54c7103df1f1106d679f87d3096ccad0a59b1d25 Mon Sep 17 00:00:00 2001 From: servostar Date: Tue, 4 Jun 2024 14:22:12 +0200 Subject: [PATCH 067/124] build bridge between compiler config and backend config --- src/cfg/opt.c | 3 +- src/codegen/backend.c | 4 +- src/codegen/backend.h | 5 +- src/compiler.c | 25 +++++++++- src/llvm/backend.c | 35 +++++++++++-- src/llvm/backend.h | 2 +- src/llvm/expr.c | 2 +- src/llvm/func.c | 44 ++++++++++++++--- src/llvm/func.h | 4 ++ src/llvm/parser.c | 112 +++++++++++++++++++++++++++++------------- src/llvm/parser.h | 8 ++- src/llvm/stmt.c | 3 ++ src/llvm/types.h | 7 +-- src/main.c | 6 +++ 14 files changed, 203 insertions(+), 57 deletions(-) diff --git a/src/cfg/opt.c b/src/cfg/opt.c index 6de694e..256e2eb 100644 --- a/src/cfg/opt.c +++ b/src/cfg/opt.c @@ -181,7 +181,8 @@ void print_help(void) { " --verbose print logs with level information or higher", " --debug print debug logs (if not disabled at compile time)", " --version print the version", - " --help print this hel dialog", + " --list-targets print a list of all available targets supported" + " --help print this help dialog" }; for (unsigned int i = 0; i < sizeof(lines) / sizeof(const char *); i++) { diff --git a/src/codegen/backend.c b/src/codegen/backend.c index 8e6f5ca..9258284 100644 --- a/src/codegen/backend.c +++ b/src/codegen/backend.c @@ -68,7 +68,7 @@ BackendError set_backend(const codegen_init init_func, const codegen_deinit dein return new_backend_error(Success); } -BackendError generate_code(const Module* root, void** output) { +BackendError generate_code(const Module* root, const TargetConfig* target) { DEBUG("generating code with backend: %s", CodegenBackend.name); if (CodegenBackend.codegen_func == NULL) { @@ -76,7 +76,7 @@ BackendError generate_code(const Module* root, void** output) { return new_backend_error(NoBackend); } - BackendError code = CodegenBackend.codegen_func(root, output); + BackendError code = CodegenBackend.codegen_func(root, target); if (code.kind) { ERROR("code generation of backend: %s failed with code: %ld", CodegenBackend.name, code); return code; diff --git a/src/codegen/backend.h b/src/codegen/backend.h index ad3613d..f25e69d 100644 --- a/src/codegen/backend.h +++ b/src/codegen/backend.h @@ -4,6 +4,7 @@ #include #include +#include typedef struct BackendImplError_t { // faulty AST node @@ -30,7 +31,7 @@ typedef struct BackendError_t { * @brief Function called by the compiler backend to generate an intermediate format * from AST. Returns a custom container for its intermediate language. */ -typedef BackendError (*codegen)(const Module*, void**); +typedef BackendError (*codegen)(const Module*, const TargetConfig* target); /** * @brief Initialize the code generation backend. @@ -78,7 +79,7 @@ BackendError deinit_backend(void); * @return BackendError */ [[nodiscard]] -BackendError generate_code(const Module* root, void** code); +BackendError generate_code(const Module* root, const TargetConfig* target); /** * @brief Create a new backend error diff --git a/src/compiler.c b/src/compiler.c index 709592e..a11d556 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -11,6 +11,8 @@ #include #include #include +#include +#include extern void yyrestart(FILE *); @@ -125,6 +127,25 @@ static void print_ast_to_file(const AST_NODE_PTR ast, const TargetConfig *target free((void *) path); } +static void run_backend_codegen(const Module* module, const TargetConfig* target) { + DEBUG("initializing LLVM codegen backend..."); + llvm_backend_init(); + + DEBUG("initiializing backend for codegen..."); + BackendError err = init_backend(); + if (err.kind != Success) { + return; + } + + DEBUG("generating code..."); + err = generate_code(module, target); + if (err.kind != Success) { + return; + } + + err = deinit_backend(); +} + /** * @brief Build the given target * @param unit @@ -142,7 +163,9 @@ static void build_target(ModuleFileStack *unit, const TargetConfig *target) { print_ast_to_file(ast, target); // TODO: parse AST to semantic values - // TODO: backend codegen + Module* module = NULL; + + run_backend_codegen(module, target); } } diff --git a/src/llvm/backend.c b/src/llvm/backend.c index 6bd5997..e2b2646 100644 --- a/src/llvm/backend.c +++ b/src/llvm/backend.c @@ -34,7 +34,35 @@ Target create_native_target() { return target; } -Target create_target_from_config() { PANIC("NOT IMPLEMENTED"); } +LLVMCodeGenOptLevel llvm_opt_from_int(int level) { + switch (level) { + case 1: + return LLVMCodeGenLevelLess; + case 2: + return LLVMCodeGenLevelDefault; + case 3: + return LLVMCodeGenLevelAggressive; + default: + break; + } + PANIC("invalid code generation optimization level: %d", level); +} + +Target create_target_from_config(const TargetConfig* config) { + DEBUG("Building target from configuration"); + + Target target = create_native_target(); + + target.name.str = config->name; + target.name.allocation = NONE; // freed later by compiler + + target.opt = llvm_opt_from_int(config->optimization_level); + + INFO("Configured target: %s/%d: (%s) on %s { %s }", target.name, target.opt, + target.triple, target.cpu, target.features); + + return target; +} static void delete_string(String string) { DEBUG("deleting string..."); @@ -59,8 +87,9 @@ void delete_target(Target target) { typedef enum LLVMBackendError_t { UnresolvedImport } LLVMBackendError; -static BackendError llvm_backend_codegen(const Module* unit, void** output) { - return parse_module(unit, output); +static BackendError llvm_backend_codegen(const Module* unit, + const TargetConfig* target) { + return parse_module(unit, target); } static BackendError llvm_backend_codegen_init(void) { diff --git a/src/llvm/backend.h b/src/llvm/backend.h index 4625aa7..59c2bd1 100644 --- a/src/llvm/backend.h +++ b/src/llvm/backend.h @@ -27,7 +27,7 @@ typedef struct Target_t { Target create_native_target(); -Target create_target_from_config(); +Target create_target_from_config(const TargetConfig* config); void delete_target(Target target); diff --git a/src/llvm/expr.c b/src/llvm/expr.c index c43c72c..e95ffa9 100644 --- a/src/llvm/expr.c +++ b/src/llvm/expr.c @@ -300,7 +300,7 @@ BackendError impl_expr(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, switch (expr->kind) { case ExpressionKindConstant: - err = get_type_value(unit, scope->func_scope->global_scope, + err = get_const_type_value(unit, scope->func_scope->global_scope, &expr->impl.constant, llvm_result); break; case ExpressionKindTransmute: diff --git a/src/llvm/func.c b/src/llvm/func.c index dc6c8da..fc21f27 100644 --- a/src/llvm/func.c +++ b/src/llvm/func.c @@ -3,11 +3,11 @@ #include #include #include +#include #include #include #include #include -#include LLVMLocalScope* new_local_scope(LLVMLocalScope* parent) { LLVMLocalScope* scope = malloc(sizeof(LLVMLocalScope)); @@ -24,7 +24,8 @@ void delete_local_scope(LLVMLocalScope* scope) { free(scope); } -static LLVMValueRef get_parameter(const LLVMFuncScope* scope, const char* name) { +static LLVMValueRef get_parameter(const LLVMFuncScope* scope, + const char* name) { if (g_hash_table_contains(scope->params, name)) { return g_hash_table_lookup(scope->params, name); } @@ -108,7 +109,8 @@ BackendError impl_func_decl(LLVMBackendCompileUnit* unit, return err; } -BackendError impl_func(LLVMBackendCompileUnit* unit, LLVMGlobalScope* global_scope, +BackendError impl_func(LLVMBackendCompileUnit* unit, + LLVMGlobalScope* global_scope, FunctionDefinition* fundef, const char* name) { BackendError err = SUCCESS; @@ -125,18 +127,20 @@ BackendError impl_func(LLVMBackendCompileUnit* unit, LLVMGlobalScope* global_sco func_scope->params = g_hash_table_new(g_str_hash, g_str_equal); // store function type in global scope - g_hash_table_insert(global_scope->functions, (gpointer) name, llvm_func); + g_hash_table_insert(global_scope->functions, (gpointer)name, llvm_func); // create function body builder - LLVMBasicBlockRef body = LLVMAppendBasicBlockInContext(unit->context, llvm_func, "entry"); + LLVMBasicBlockRef body = + LLVMAppendBasicBlockInContext(unit->context, llvm_func, "entry"); LLVMBuilderRef builder = LLVMCreateBuilderInContext(unit->context); LLVMPositionBuilderAtEnd(builder, body); // create value references for parameter const size_t params = fundef->parameter->len; for (size_t i = 0; i < params; i++) { - const Paramer* param = ((Paramer*) fundef->parameter) + i; - g_hash_table_insert(func_scope->params, (gpointer) param->name, LLVMGetParam(llvm_func, i)); + const Paramer* param = ((Paramer*)fundef->parameter) + i; + g_hash_table_insert(func_scope->params, (gpointer)param->name, + LLVMGetParam(llvm_func, i)); } // TODO: parse function body @@ -149,3 +153,29 @@ BackendError impl_func(LLVMBackendCompileUnit* unit, LLVMGlobalScope* global_sco return err; } + +BackendError impl_functions(LLVMBackendCompileUnit* unit, + LLVMGlobalScope* scope, GHashTable* functions) { + DEBUG("implementing functions..."); + GHashTableIter iterator; + g_hash_table_iter_init(&iterator, functions); + + gpointer key = NULL; + gpointer val = NULL; + + BackendError err = SUCCESS; + + size_t variable_count = 0; + while (g_hash_table_iter_next(&iterator, &key, &val) != FALSE) { + err = + impl_func(unit, scope, (FunctionDefinition*)val, (const char*)key); + + if (err.kind != Success) { + break; + } + + variable_count++; + } + + return err; +} diff --git a/src/llvm/func.h b/src/llvm/func.h index e93eca4..acae8a6 100644 --- a/src/llvm/func.h +++ b/src/llvm/func.h @@ -28,4 +28,8 @@ void delete_local_scope(LLVMLocalScope*); LLVMValueRef get_variable(const LLVMLocalScope* scope, const char* name); +BackendError impl_functions(LLVMBackendCompileUnit* unit, + LLVMGlobalScope* scope, + GHashTable* variables); + #endif // LLVM_BACKEND_FUNC_H_ diff --git a/src/llvm/parser.c b/src/llvm/parser.c index 4d00ac0..3a9bfa9 100644 --- a/src/llvm/parser.c +++ b/src/llvm/parser.c @@ -8,15 +8,15 @@ #include #include #include +#include #include #include #include #include #include -#define EXPORT_IR 1 - -BackendError export_IR(LLVMBackendCompileUnit* unit, const Target* target) { +BackendError export_IR(LLVMBackendCompileUnit* unit, const Target* target, + const TargetConfig* config) { DEBUG("exporting module to LLVM-IR..."); BackendError err = SUCCESS; @@ -25,8 +25,8 @@ BackendError export_IR(LLVMBackendCompileUnit* unit, const Target* target) { char* ir = LLVMPrintModuleToString(unit->module); // construct file name - char* filename = alloca(strlen(target->name.str) + 4); - sprintf(filename, "%s.ll", target->name.str); + const char* filename = + make_file_path(target->name.str, ".ll", 1, config->archive_directory); INFO("Writing LLVM-IR to %s", filename); @@ -49,13 +49,52 @@ BackendError export_IR(LLVMBackendCompileUnit* unit, const Target* target) { INFO("%ld bytes written to %s", bytes, filename); + free((char*)filename); + // clean up LLVM-IR string LLVMDisposeMessage(ir); return err; } -BackendError export_object(LLVMBackendCompileUnit* unit, const Target* target) { +BackendError emit_module_to_file(LLVMBackendCompileUnit* unit, + LLVMTargetMachineRef target_machine, + LLVMCodeGenFileType file_type, char* error, + const TargetConfig* config) { + BackendError err = SUCCESS; + DEBUG("Generating code..."); + + const char* filename; + switch (file_type) { + case LLVMAssemblyFile: + filename = make_file_path(config->name, ".s", 1, + config->archive_directory); + break; + case LLVMObjectFile: + filename = make_file_path(config->name, ".o", 1, + config->archive_directory); + break; + default: + return new_backend_impl_error(Implementation, NULL, + "invalid codegen file"); + } + + if (LLVMTargetMachineEmitToFile(target_machine, unit->module, filename, + file_type, &error) != 0) { + ERROR("failed to emit code: %s", error); + err = + new_backend_impl_error(Implementation, NULL, "failed to emit code"); + LLVMDisposeMessage(error); + } + + free((void*)filename); + + return err; +} + +BackendError export_object(LLVMBackendCompileUnit* unit, const Target* target, + const TargetConfig* config) { + BackendError err = SUCCESS; DEBUG("exporting object file..."); INFO("Using target (%s): %s with features: %s", target->name.str, @@ -72,8 +111,8 @@ BackendError export_object(LLVMBackendCompileUnit* unit, const Target* target) { if (LLVMGetTargetFromTriple(target->triple.str, &llvm_target, &error) != 0) { ERROR("failed to create target machine: %s", error); - BackendError err = new_backend_impl_error( - Implementation, NULL, "unable to create target machine"); + err = new_backend_impl_error(Implementation, NULL, + "unable to create target machine"); LLVMDisposeMessage(error); return err; } @@ -83,19 +122,19 @@ BackendError export_object(LLVMBackendCompileUnit* unit, const Target* target) { llvm_target, target->triple.str, target->cpu.str, target->features.str, target->opt, target->reloc, target->model); - LLVMCodeGenFileType file_type = LLVMObjectFile; + if (config->print_asm) { + err = emit_module_to_file(unit, target_machine, LLVMAssemblyFile, error, + config); + } - DEBUG("Generating code..."); - if (LLVMTargetMachineEmitToFile(target_machine, unit->module, "output", - file_type, &error) != 0) { - ERROR("failed to emit code: %s", error); - BackendError err = - new_backend_impl_error(Implementation, NULL, "failed to emit code"); - LLVMDisposeMessage(error); + if (err.kind != Success) { return err; } - return SUCCESS; + err = emit_module_to_file(unit, target_machine, LLVMObjectFile, error, + config); + + return err; } void list_available_targets() { @@ -120,23 +159,25 @@ void list_available_targets() { LLVMDisposeMessage(default_triple); } -BackendError export_module(LLVMBackendCompileUnit* unit, const Target* target) { +BackendError export_module(LLVMBackendCompileUnit* unit, const Target* target, + const TargetConfig* config) { DEBUG("exporting module..."); BackendError err = SUCCESS; - export_object(unit, target); + export_object(unit, target, config); - if (EXPORT_IR) { - export_IR(unit, target); - } else { - DEBUG("not exporting LLVM-IR"); + if (config->print_ir) { + export_IR(unit, target, config); } return err; } -static BackendError build_module(LLVMBackendCompileUnit* unit, LLVMGlobalScope* global_scope, const Module* module) { +static BackendError build_module(LLVMBackendCompileUnit* unit, + LLVMGlobalScope* global_scope, + const Module* module) { + DEBUG("building module..."); BackendError err = SUCCESS; err = impl_types(unit, global_scope, module->types); @@ -156,10 +197,13 @@ static BackendError build_module(LLVMBackendCompileUnit* unit, LLVMGlobalScope* return err; } + // TODO: implement functions + err = impl_functions(unit, global_scope, module->functions); + return err; } -BackendError parse_module(const Module* module, void**) { +BackendError parse_module(const Module* module, const TargetConfig* config) { DEBUG("generating code for module %p", module); if (module == NULL) { ERROR("no module for codegen"); @@ -171,20 +215,19 @@ BackendError parse_module(const Module* module, void**) { // we start with a LLVM module DEBUG("creating LLVM context and module"); unit->context = LLVMContextCreate(); - unit->module = LLVMModuleCreateWithNameInContext("gemstone application", - unit->context); + unit->module = + LLVMModuleCreateWithNameInContext(config->name, unit->context); - LLVMGlobalScope* global_scope = new_global_scope(); - - BackendError err = new_backend_error(Success); + LLVMGlobalScope* global_scope = new_global_scope(module); DEBUG("generating code..."); - err = build_module(unit, global_scope, module); + BackendError err = build_module(unit, global_scope, module); if (err.kind == Success) { - Target target = create_native_target(); + INFO("Module build successfully..."); + Target target = create_target_from_config(config); - export_module(unit, &target); + export_module(unit, &target, config); delete_target(target); } @@ -199,10 +242,11 @@ BackendError parse_module(const Module* module, void**) { return err; } -LLVMGlobalScope* new_global_scope() { +LLVMGlobalScope* new_global_scope(const Module* module) { DEBUG("creating global scope..."); LLVMGlobalScope* scope = malloc(sizeof(LLVMGlobalScope)); + scope->module = (Module*) module; scope->functions = g_hash_table_new(g_str_hash, g_str_equal); scope->variables = g_hash_table_new(g_str_hash, g_str_equal); scope->types = g_hash_table_new(g_str_hash, g_str_equal); diff --git a/src/llvm/parser.h b/src/llvm/parser.h index f045f43..4b740ce 100644 --- a/src/llvm/parser.h +++ b/src/llvm/parser.h @@ -18,12 +18,16 @@ typedef struct LLVMGlobalScope_t { GHashTable* variables; // of type LLVMTypeRef GHashTable* functions; + // module definition + Module* module; } LLVMGlobalScope; -LLVMGlobalScope* new_global_scope(); +LLVMGlobalScope* new_global_scope(const Module* module); + +void list_available_targets(); void delete_global_scope(LLVMGlobalScope* scope); -BackendError parse_module(const Module* module, void**); +BackendError parse_module(const Module* module, const TargetConfig* config); #endif // LLVM_BACKEND_PARSE_H_ diff --git a/src/llvm/stmt.c b/src/llvm/stmt.c index 9d23c07..c712ae5 100644 --- a/src/llvm/stmt.c +++ b/src/llvm/stmt.c @@ -103,6 +103,9 @@ BackendError impl_func_call(LLVMBackendCompileUnit *unit, break; } + Paramer* parameter = (Paramer*) call->function->parameter->data + i; + // TODO: create a pointer to LLVMValueRef in case parameter is `out` + g_array_append_vals(arguments, &llvm_arg, 1); } diff --git a/src/llvm/types.h b/src/llvm/types.h index edd8b66..405aa91 100644 --- a/src/llvm/types.h +++ b/src/llvm/types.h @@ -18,8 +18,9 @@ BackendError get_type_default_value(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, Type* gemstone_type, LLVMValueRef* llvm_value); -BackendError get_type_value(LLVMBackendCompileUnit* unit, - LLVMGlobalScope* scope, TypeValue* gemstone_value, - LLVMValueRef* llvm_value); +BackendError get_const_type_value(LLVMBackendCompileUnit* unit, + LLVMGlobalScope* scope, + TypeValue* gemstone_value, + LLVMValueRef* llvm_value); #endif // LLVM_BACKEND_TYPES_H_ diff --git a/src/main.c b/src/main.c index 3ad368c..b69b613 100644 --- a/src/main.c +++ b/src/main.c @@ -5,6 +5,7 @@ #include #include #include +#include /** * @brief Log a debug message to inform about beginning exit procedures @@ -55,6 +56,11 @@ int main(int argc, char *argv[]) { exit(0); } + if (is_option_set("list-targets")) { + list_available_targets(); + exit(0); + } + run_compiler(); return 0; From 1c476cd5618ab1d9c4700c9b80ee750011e58176 Mon Sep 17 00:00:00 2001 From: servostar Date: Tue, 4 Jun 2024 14:58:40 +0200 Subject: [PATCH 068/124] fixed test not passing --- src/llvm/expr.c | 21 ++++++++++----------- src/llvm/stmt.c | 15 ++++++++++----- tests/llvm/CMakeLists.txt | 8 ++++---- tests/llvm/global_vars.c | 12 +++++++----- 4 files changed, 31 insertions(+), 25 deletions(-) diff --git a/src/llvm/expr.c b/src/llvm/expr.c index e95ffa9..beee0d3 100644 --- a/src/llvm/expr.c +++ b/src/llvm/expr.c @@ -6,8 +6,8 @@ #include #include -BackendError impl_bitwise_operation(LLVMBackendCompileUnit *unit, - LLVMLocalScope *scope, +BackendError impl_bitwise_operation([[maybe_unused]] LLVMBackendCompileUnit *unit, + [[maybe_unused]] LLVMLocalScope *scope, LLVMBuilderRef builder, Operation *operation, LLVMValueRef *llvm_result) { @@ -57,8 +57,8 @@ static LLVMValueRef convert_integral_to_boolean( return LLVMBuildICmp(builder, LLVMIntNE, zero, integral, "to boolean"); } -BackendError impl_logical_operation(LLVMBackendCompileUnit *unit, - LLVMLocalScope *scope, +BackendError impl_logical_operation([[maybe_unused]] LLVMBackendCompileUnit *unit, + [[maybe_unused]] LLVMLocalScope *scope, LLVMBuilderRef builder, Operation *operation, LLVMValueRef *llvm_result) { @@ -66,7 +66,7 @@ BackendError impl_logical_operation(LLVMBackendCompileUnit *unit, LLVMValueRef rhs = NULL; LLVMValueRef lhs = NULL; - if (operation->kind == LogicalNot) { + if (operation->impl.logical == LogicalNot) { // single operand rhs = convert_integral_to_boolean(builder, rhs); } else { @@ -75,7 +75,7 @@ BackendError impl_logical_operation(LLVMBackendCompileUnit *unit, rhs = convert_integral_to_boolean(builder, rhs); } - switch (operation->impl.bitwise) { + switch (operation->impl.logical) { case LogicalAnd: *llvm_result = LLVMBuildAnd(builder, lhs, rhs, "logical and"); break; @@ -108,8 +108,8 @@ static LLVMBool is_integral(LLVMValueRef value) { return typeKind == LLVMIntegerTypeKind; } -BackendError impl_relational_operation(LLVMBackendCompileUnit *unit, - LLVMLocalScope *scope, +BackendError impl_relational_operation([[maybe_unused]] LLVMBackendCompileUnit *unit, + [[maybe_unused]] LLVMLocalScope *scope, LLVMBuilderRef builder, Operation *operation, LLVMValueRef *llvm_result) { @@ -158,8 +158,8 @@ BackendError impl_relational_operation(LLVMBackendCompileUnit *unit, return SUCCESS; } -BackendError impl_arithmetic_operation(LLVMBackendCompileUnit *unit, - LLVMLocalScope *scope, +BackendError impl_arithmetic_operation([[maybe_unused]] LLVMBackendCompileUnit *unit, + [[maybe_unused]] LLVMLocalScope *scope, LLVMBuilderRef builder, Operation *operation, LLVMValueRef *llvm_result) { @@ -169,7 +169,6 @@ BackendError impl_arithmetic_operation(LLVMBackendCompileUnit *unit, if ((is_integral(lhs) && is_integral(rhs)) == 1) { // integral type - LLVMIntPredicate operator = 0; switch (operation->impl.arithmetic) { case Add: diff --git a/src/llvm/stmt.c b/src/llvm/stmt.c index c712ae5..0e1b470 100644 --- a/src/llvm/stmt.c +++ b/src/llvm/stmt.c @@ -9,7 +9,7 @@ #include #include -BackendError impl_assign_stmt(LLVMBackendCompileUnit *unit, +BackendError impl_assign_stmt([[maybe_unused]] LLVMBackendCompileUnit *unit, const LLVMBuilderRef builder, const LLVMLocalScope *scope, const Assignment *assignment) { BackendError err = SUCCESS; @@ -45,6 +45,7 @@ BackendError impl_basic_block(LLVMBackendCompileUnit *unit, LLVMPositionBuilderAtEnd(builder, *llvm_block); for (size_t i = 0; i < block->statemnts->len; i++) { + [[maybe_unused]] Statement *stmt = ((Statement *) block->statemnts->data) + i; // TODO: implement statement @@ -66,7 +67,7 @@ BackendError impl_while(LLVMBackendCompileUnit *unit, LLVMPositionBuilderAtEnd(builder, while_cond_block); // Resolve condition in block to a variable LLVMValueRef cond_result = NULL; - impl_expr(unit, scope, builder, &while_stmt->conditon, &cond_result); + impl_expr(unit, scope, builder, (Expression*) &while_stmt->conditon, &cond_result); // build body of loop LLVMBasicBlockRef while_body_block = NULL; @@ -103,6 +104,7 @@ BackendError impl_func_call(LLVMBackendCompileUnit *unit, break; } + [[maybe_unused]] Paramer* parameter = (Paramer*) call->function->parameter->data + i; // TODO: create a pointer to LLVMValueRef in case parameter is `out` @@ -123,7 +125,7 @@ BackendError impl_func_call(LLVMBackendCompileUnit *unit, BackendError impl_cond_block(LLVMBackendCompileUnit *unit, LLVMBuilderRef builder, LLVMLocalScope *scope, Expression *cond, - Block *block, LLVMBasicBlockRef *cond_block, LLVMBasicBlockRef *body_block, + const Block *block, LLVMBasicBlockRef *cond_block, LLVMBasicBlockRef *body_block, LLVMValueRef *llvm_cond) { BackendError err; @@ -155,7 +157,7 @@ BackendError impl_branch(LLVMBackendCompileUnit *unit, LLVMBasicBlockRef body_block = NULL; LLVMValueRef cond_value = NULL; - err = impl_cond_block(unit, builder, scope, &branch->ifBranch.conditon, &branch->ifBranch.block, &cond_block, + err = impl_cond_block(unit, builder, scope, (Expression*) &branch->ifBranch.conditon, &branch->ifBranch.block, &cond_block, &body_block, &cond_value); g_array_append_val(cond_blocks, cond_block); @@ -215,4 +217,7 @@ BackendError impl_branch(LLVMBackendCompileUnit *unit, return err; } -BackendError impl_stmt(LLVMBackendCompileUnit *unit, Statement *stmt) {} +BackendError impl_stmt([[maybe_unused]] LLVMBackendCompileUnit *unit, [[maybe_unused]] Statement *stmt) { + // TODO: implement + return SUCCESS; +} diff --git a/tests/llvm/CMakeLists.txt b/tests/llvm/CMakeLists.txt index bc72f78..ac84d6e 100644 --- a/tests/llvm/CMakeLists.txt +++ b/tests/llvm/CMakeLists.txt @@ -5,7 +5,9 @@ include_directories(PRIVATE ${GLIB_INCLUDE_DIRS}) find_package(PkgConfig REQUIRED) pkg_search_module(GLIB REQUIRED IMPORTED_TARGET glib-2.0) -link_libraries(PkgConfig::GLIB) +link_libraries(PkgConfig::GLIB) + +include_directories(${PROJECT_SOURCE_DIR}/dep/tomlc99) # ------------------------------------------------ # # LLVM backend # @@ -30,15 +32,13 @@ include_directories(${LLVM_INCLUDE_DIR}) file(GLOB_RECURSE SOURCE_FILES ${PROJECT_SOURCE_DIR}/src/*.c) list(REMOVE_ITEM SOURCE_FILES ${PROJECT_SOURCE_DIR}/src/main.c) -list(REMOVE_ITEM SOURCE_FILES ${PROJECT_SOURCE_DIR}/src/yacc/parser.tab.c) -list(REMOVE_ITEM SOURCE_FILES ${PROJECT_SOURCE_DIR}/src/lex/lexer.ll.c) -list(REMOVE_ITEM SOURCE_FILES ${PROJECT_SOURCE_DIR}/src/lex/util.c) add_executable(global_vars global_vars.c ${SOURCE_FILES}) set_target_properties(global_vars PROPERTIES OUTPUT_NAME "global_vars" RUNTIME_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/tests/llvm) +target_link_libraries(global_vars tomlc99) add_test(NAME global_vars WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests/llvm COMMAND ${GEMSTONE_BINARY_DIR}/tests/llvm/global_vars) diff --git a/tests/llvm/global_vars.c b/tests/llvm/global_vars.c index 52a104b..691a64a 100644 --- a/tests/llvm/global_vars.c +++ b/tests/llvm/global_vars.c @@ -5,9 +5,6 @@ #include #include -// NOTE: unused -AST_NODE_PTR root; - [[gnu::always_inline]] [[clang::always_inline]] inline Variable* create_variable_decl(const char* name, StorageQualifier qualifier, Type type) { @@ -85,7 +82,8 @@ inline Module* create_module() { return module; } -int main() { +int main(int argc, char* argv[]) { + parse_options(argc, argv); log_init(); // no need to clean up ;-) @@ -99,11 +97,15 @@ int main() { PANIC("%ld: at [%p] %s", err.kind, err.impl.ast_node, err.impl.message); } - err = generate_code(module, NULL); + TargetConfig* config = default_target_config(); + + err = generate_code(module, config); if (err.kind != Success) { PANIC("%ld: at [%p] %s", err.kind, err.impl.ast_node, err.impl.message); } + delete_target_config(config); + err = deinit_backend(); if (err.kind != Success) { PANIC("%ld: at [%p] %s", err.kind, err.impl.ast_node, err.impl.message); From 0c5fb4fd41b7ee16bb81ac87a38820abec2296a7 Mon Sep 17 00:00:00 2001 From: servostar Date: Tue, 4 Jun 2024 15:06:17 +0200 Subject: [PATCH 069/124] changed build config for llvm test --- tests/llvm/CMakeLists.txt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/llvm/CMakeLists.txt b/tests/llvm/CMakeLists.txt index ac84d6e..d2d5953 100644 --- a/tests/llvm/CMakeLists.txt +++ b/tests/llvm/CMakeLists.txt @@ -30,10 +30,16 @@ include_directories(${LLVM_INCLUDE_DIR}) # CTEST 1 # test llvm backend codegen for global variables -file(GLOB_RECURSE SOURCE_FILES ${PROJECT_SOURCE_DIR}/src/*.c) +file(GLOB_RECURSE SOURCE_FILES ${PROJECT_SOURCE_DIR}/src/llvm/*.c) list(REMOVE_ITEM SOURCE_FILES ${PROJECT_SOURCE_DIR}/src/main.c) add_executable(global_vars -global_vars.c ${SOURCE_FILES}) + ${PROJECT_SOURCE_DIR}/src/codegen/backend.c + ${PROJECT_SOURCE_DIR}/src/sys/log.c + ${PROJECT_SOURCE_DIR}/src/sys/col.c + ${PROJECT_SOURCE_DIR}/src/cfg/opt.c + ${PROJECT_SOURCE_DIR}/src/io/files.c + global_vars.c + ${SOURCE_FILES}) set_target_properties(global_vars PROPERTIES OUTPUT_NAME "global_vars" From 4ac0ee79d1a66c68e50753882a176416c5912f58 Mon Sep 17 00:00:00 2001 From: servostar Date: Tue, 4 Jun 2024 15:18:22 +0200 Subject: [PATCH 070/124] fixed: missing init of asm parsers --- src/llvm/parser.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/llvm/parser.c b/src/llvm/parser.c index 3a9bfa9..dbe914b 100644 --- a/src/llvm/parser.c +++ b/src/llvm/parser.c @@ -106,6 +106,9 @@ BackendError export_object(LLVMBackendCompileUnit* unit, const Target* target, LLVMInitializeAllTargets(); LLVMInitializeAllTargetInfos(); LLVMInitializeAllTargetMCs(); + // NOTE: for code generation (assmebly or binary) we need the following: + LLVMInitializeAllAsmParsers(); + LLVMInitializeAllAsmPrinters(); DEBUG("creating target..."); if (LLVMGetTargetFromTriple(target->triple.str, &llvm_target, &error) != From e893dd327be6ae815a639358c65afc2bdfb8abad Mon Sep 17 00:00:00 2001 From: servostar Date: Tue, 4 Jun 2024 15:28:41 +0200 Subject: [PATCH 071/124] added llvm/link module --- src/llvm/link/lld.c | 6 ++++++ src/llvm/link/lld.h | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 src/llvm/link/lld.c create mode 100644 src/llvm/link/lld.h diff --git a/src/llvm/link/lld.c b/src/llvm/link/lld.c new file mode 100644 index 0000000..5622b22 --- /dev/null +++ b/src/llvm/link/lld.c @@ -0,0 +1,6 @@ +// +// Created by servostar on 6/4/24. +// + +#include + diff --git a/src/llvm/link/lld.h b/src/llvm/link/lld.h new file mode 100644 index 0000000..1916c3b --- /dev/null +++ b/src/llvm/link/lld.h @@ -0,0 +1,19 @@ +// +// Created by servostar on 6/4/24. +// + +#ifndef LLVM_BACKEND_LLD_H +#define LLVM_BACKEND_LLD_H + +#include +#include + +/** + * @brief Link the target by its configuration to the final output. + * @param target + * @param config + * @return + */ +BackendError link_target(const Target* target, const TargetConfig* config); + +#endif // LLVM_BACKEND_LLD_H From 14c5ba320cc82b88175ff944fcf5ea94a318182c Mon Sep 17 00:00:00 2001 From: servostar Date: Tue, 4 Jun 2024 15:34:47 +0200 Subject: [PATCH 072/124] moved modules for llvm-ir generation into subfolder --- src/llvm/{ => llvm-ir}/expr.c | 4 ++-- src/llvm/{ => llvm-ir}/expr.h | 2 +- src/llvm/{ => llvm-ir}/func.c | 4 ++-- src/llvm/{ => llvm-ir}/func.h | 0 src/llvm/{ => llvm-ir}/stmt.c | 8 ++++---- src/llvm/{ => llvm-ir}/stmt.h | 0 src/llvm/{ => llvm-ir}/types.c | 8 ++++---- src/llvm/{ => llvm-ir}/types.h | 0 src/llvm/{ => llvm-ir}/variables.c | 8 ++++---- src/llvm/{ => llvm-ir}/variables.h | 0 src/llvm/parser.c | 6 +++--- 11 files changed, 20 insertions(+), 20 deletions(-) rename src/llvm/{ => llvm-ir}/expr.c (99%) rename src/llvm/{ => llvm-ir}/expr.h (92%) rename src/llvm/{ => llvm-ir}/func.c (98%) rename src/llvm/{ => llvm-ir}/func.h (100%) rename src/llvm/{ => llvm-ir}/stmt.c (98%) rename src/llvm/{ => llvm-ir}/stmt.h (100%) rename src/llvm/{ => llvm-ir}/types.c (99%) rename src/llvm/{ => llvm-ir}/types.h (100%) rename src/llvm/{ => llvm-ir}/variables.c (98%) rename src/llvm/{ => llvm-ir}/variables.h (100%) diff --git a/src/llvm/expr.c b/src/llvm/llvm-ir/expr.c similarity index 99% rename from src/llvm/expr.c rename to src/llvm/llvm-ir/expr.c index beee0d3..6896ce1 100644 --- a/src/llvm/expr.c +++ b/src/llvm/llvm-ir/expr.c @@ -2,8 +2,8 @@ // Created by servostar on 5/28/24. // -#include -#include +#include +#include #include BackendError impl_bitwise_operation([[maybe_unused]] LLVMBackendCompileUnit *unit, diff --git a/src/llvm/expr.h b/src/llvm/llvm-ir/expr.h similarity index 92% rename from src/llvm/expr.h rename to src/llvm/llvm-ir/expr.h index c0c8d47..15df434 100644 --- a/src/llvm/expr.h +++ b/src/llvm/llvm-ir/expr.h @@ -7,7 +7,7 @@ #include #include -#include +#include #include BackendError impl_expr(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, diff --git a/src/llvm/func.c b/src/llvm/llvm-ir/func.c similarity index 98% rename from src/llvm/func.c rename to src/llvm/llvm-ir/func.c index fc21f27..107b697 100644 --- a/src/llvm/func.c +++ b/src/llvm/llvm-ir/func.c @@ -3,9 +3,9 @@ #include #include #include -#include +#include #include -#include +#include #include #include diff --git a/src/llvm/func.h b/src/llvm/llvm-ir/func.h similarity index 100% rename from src/llvm/func.h rename to src/llvm/llvm-ir/func.h diff --git a/src/llvm/stmt.c b/src/llvm/llvm-ir/stmt.c similarity index 98% rename from src/llvm/stmt.c rename to src/llvm/llvm-ir/stmt.c index 0e1b470..8692168 100644 --- a/src/llvm/stmt.c +++ b/src/llvm/llvm-ir/stmt.c @@ -3,11 +3,11 @@ // #include -#include -#include -#include -#include #include +#include +#include +#include +#include BackendError impl_assign_stmt([[maybe_unused]] LLVMBackendCompileUnit *unit, const LLVMBuilderRef builder, const LLVMLocalScope *scope, diff --git a/src/llvm/stmt.h b/src/llvm/llvm-ir/stmt.h similarity index 100% rename from src/llvm/stmt.h rename to src/llvm/llvm-ir/stmt.h diff --git a/src/llvm/types.c b/src/llvm/llvm-ir/types.c similarity index 99% rename from src/llvm/types.c rename to src/llvm/llvm-ir/types.c index 65fd661..76dcce1 100644 --- a/src/llvm/types.c +++ b/src/llvm/llvm-ir/types.c @@ -1,10 +1,10 @@ #include -#include -#include -#include -#include #include #include +#include +#include +#include +#include #define BASE_BYTES 4 #define BITS_PER_BYTE 8 diff --git a/src/llvm/types.h b/src/llvm/llvm-ir/types.h similarity index 100% rename from src/llvm/types.h rename to src/llvm/llvm-ir/types.h diff --git a/src/llvm/variables.c b/src/llvm/llvm-ir/variables.c similarity index 98% rename from src/llvm/variables.c rename to src/llvm/llvm-ir/variables.c index 5519313..595dd35 100644 --- a/src/llvm/variables.c +++ b/src/llvm/llvm-ir/variables.c @@ -1,11 +1,11 @@ #include -#include -#include -#include -#include #include #include +#include +#include +#include +#include BackendError impl_global_declaration(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, diff --git a/src/llvm/variables.h b/src/llvm/llvm-ir/variables.h similarity index 100% rename from src/llvm/variables.h rename to src/llvm/llvm-ir/variables.h diff --git a/src/llvm/parser.c b/src/llvm/parser.c index dbe914b..57c989e 100644 --- a/src/llvm/parser.c +++ b/src/llvm/parser.c @@ -6,9 +6,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include #include #include From d0b1d367d52d3c52b173c957a11c84d38fd0a2db Mon Sep 17 00:00:00 2001 From: Filleo Date: Wed, 5 Jun 2024 00:31:40 +0200 Subject: [PATCH 073/124] major set building Co-authored-by: SirTalksalot75 Co-authored-by: servostar --- src/io/files.c | 16 +- src/io/files.h | 2 +- src/set/set.c | 552 ++++++++++++++++++++++++++++++++++++++---------- src/set/types.h | 24 ++- 4 files changed, 471 insertions(+), 123 deletions(-) diff --git a/src/io/files.c b/src/io/files.c index 5f3ad02..d091d06 100644 --- a/src/io/files.c +++ b/src/io/files.c @@ -3,6 +3,8 @@ // #include +#include +#include #include #include #include @@ -79,7 +81,7 @@ static void custom_fgets(char *buffer, size_t n, FILE *stream) { } } -void print_diagnostic(ModuleFile *file, TokenLocation *location, Message kind, const char *message) { +void print_diagnostic(ModuleFile *file, TokenLocation *location, Message kind, const char *message, ...) { assert(file->handle != NULL); assert(location != NULL); assert(message != NULL); @@ -117,8 +119,16 @@ void print_diagnostic(ModuleFile *file, TokenLocation *location, Message kind, c const char *absolute_path = get_absolute_path(file->path); - printf("%s%s:%ld:%s %s%s:%s %s\n", BOLD, absolute_path, location->line_start, RESET, accent_color, kind_text, RESET, - message); + printf("%s%s:%ld:%s %s%s:%s ", BOLD, absolute_path, location->line_start, RESET, accent_color, kind_text, RESET); + + va_list args; + va_start(args, format); + + vprintf(message, args); + + va_end(args); + + printf("\n"); free((void *) absolute_path); diff --git a/src/io/files.h b/src/io/files.h index 61c7ebb..1e436b5 100644 --- a/src/io/files.h +++ b/src/io/files.h @@ -92,7 +92,7 @@ TokenLocation empty_location(void); * @param message */ [[gnu::nonnull(1), gnu::nonnull(2)]] -void print_diagnostic(ModuleFile *file, TokenLocation *location, Message kind, const char *message); +void print_diagnostic(ModuleFile *file, TokenLocation *location, Message kind, const char *message, ...); [[gnu::nonnull(2)]] /** diff --git a/src/set/set.c b/src/set/set.c index f63aa83..3ac0add 100644 --- a/src/set/set.c +++ b/src/set/set.c @@ -1,5 +1,5 @@ -#include "io/files.h" -#include "yacc/parser.tab.h" +#include +#include #include #include #include @@ -11,9 +11,17 @@ #include #include -GHashTable *declaredComposites = NULL;//pointer to composites with names, -GHashTable *declaredBoxes = NULL;//pointer to typeboxes -GArray *Scope = NULL;//list of hashtables. last Hashtable is current depth of program. hashtable key: ident, value: Variable* to var +// +// .--. +// | '----------. . +// > | ~ ~ ~ ~ ~ .o O +// | .----------' o +// `--' +// + +static GHashTable *declaredComposites = NULL;//pointer to composites with names +static GHashTable *declaredBoxes = NULL;//pointer to typeboxes +static GArray *Scope = NULL;//list of hashtables. last Hashtable is current depth of program. hashtable key: ident, value: Variable* to var const Type ShortShortUnsingedIntType = { .kind = TypeKindComposite, @@ -264,9 +272,15 @@ int get_type_impl(AST_NODE_PTR currentNode, Type** type) { } StorageQualifier Qualifier_from_string(const char *str) { - if (!strncmp(str, "local", 5)) return Local; - if (!strncmp(str, "static", 6)) return Static; - if (!strncmp(str, "global", 6)) return Global; + assert(str != NULL); + + if (strcmp(str, "local") == 0) + return Local; + if (strcmp(str, "static") == 0) + return Static; + if (strcmp(str, "global") == 0) + return Global; + PANIC("Provided string is not a storagequalifier: %s", str); } @@ -316,42 +330,99 @@ int createDecl(AST_NODE_PTR currentNode, GArray** variables) { return status; } +Expression* createExpression(AST_NODE_PTR currentNode); + int createDef(AST_NODE_PTR currentNode, GArray** variables) { assert(variables != NULL); assert(currentNode != NULL); + assert(currentNode->kind == AST_Def); DEBUG("create definition"); - AST_NODE_PTR declaration = currentNode->children[currentNode->child_count - 1]; + AST_NODE_PTR declaration = currentNode->children[0]; + AST_NODE_PTR expression = currentNode->children[1]; + AST_NODE_PTR ident_list = currentNode->children[0]->children[currentNode->child_count - 1]; - * variables = g_array_new(FALSE, FALSE, sizeof(Variable*)); - + *variables = g_array_new(FALSE, FALSE, sizeof(Variable*)); + + VariableDeclaration decl; VariableDefiniton def; def.nodePtr = currentNode; - Variable* variable = malloc(sizeof(Variable)); - variable->kind = VariableKindDefinition; - variable->nodePtr = currentNode; - variable->name = declaration->children[1]->value; - variable->impl.definiton= def; - g_array_append_val(*variables, variable); - int status = SEMANTIC_OK; - DEBUG("Child Count: %i", currentNode->child_count); - for (size_t i = 0; i < currentNode->child_count; i++){ - - switch(currentNode->children[i]->kind) { - case AST_Decl: + DEBUG("Child Count: %i", declaration->child_count); + for (size_t i = 0; i < declaration->children[i]->child_count; i++){ + switch(declaration->children[i]->kind) { + case AST_Storage: + DEBUG("fill Qualifier"); + decl.qualifier = Qualifier_from_string(currentNode->children[i]->value); + break; + case AST_Type: + DEBUG("fill Type"); + status = get_type_impl(currentNode->children[i], &decl.type); + break; + case AST_IdentList: break; default: PANIC("invalid node type: %ld", currentNode->children[i]->kind); break; - } + } } + + def.declaration = decl; + Expression * name = createExpression(expression); + if (name == NULL){ + status = SEMANTIC_OK; + } + def.initializer = name; + + + for(size_t i = 0; i < ident_list->child_count; i++) { + Variable* variable = malloc(sizeof(Variable)); + + variable->kind = VariableKindDefinition; + variable->nodePtr = currentNode; + variable->name = ident_list->children[i]->value; + variable->impl.definiton = def; + g_array_append_val(*variables, variable); + } + return status; } +//int: a,b,c = 5 +// +//GArray.data: +// 1. Variable +// kind = VariableKindDefinition; +// name = a; +// impl.definition: +// initilizer: +// createExpression(...) +// decl: +// qulifier: +// type: +// pointer +// +// +// 2. Variable +// kind = VariableKindDefinition; +// name = b; +// impl.definition: +// initilizer: 5 +// decl: +// qulifier: +// type: +// pointer +// . +// . +// . +// + + + + int getVariableFromScope(const char* name, Variable** variable) { assert(name != NULL); assert(variable != NULL); @@ -413,17 +484,23 @@ TypeValue createTypeValue(AST_NODE_PTR currentNode){ return value; } +static inline void* clone(int size, void* ptr) { + char* data = malloc(size); + memcpy(data, ptr, size); + return data; +} + +#define CLONE(x) clone(sizeof(x), (void*)&(x)) + TypeValue createString(AST_NODE_PTR currentNode) { TypeValue value; - Type *type = (Type*) &StringLiteralType; + Type *type = CLONE(StringLiteralType); value.type = type; value.nodePtr = currentNode; value.value = currentNode->value; return value; } -Expression* createExpression(AST_NODE_PTR currentNode); - Type* createTypeFromOperands(Type* LeftOperandType, Type* RightOperandType, AST_NODE_PTR currentNode) { Type *result = malloc(sizeof(Type)); result->nodePtr = currentNode; @@ -642,7 +719,7 @@ int createBoolOperation(Expression *ParentExpression, AST_NODE_PTR currentNode) return SEMANTIC_OK; } -int createBoolNotOperation(Expression *ParentExpression, AST_NODE_PTR currentNode){ +int createBoolNotOperation(Expression *ParentExpression, AST_NODE_PTR currentNode) { //fill kind and Nodeptr ParentExpression->impl.operation.kind = Boolean; ParentExpression->impl.operation.nodePtr = currentNode; @@ -650,7 +727,7 @@ int createBoolNotOperation(Expression *ParentExpression, AST_NODE_PTR currentNod //fill Operand Expression* expression = createExpression(currentNode->children[0]); if(NULL == expression){ - return 1; + return SEMANTIC_ERROR; } g_array_append_val(ParentExpression->impl.operation.operands , expression); @@ -660,109 +737,152 @@ int createBoolNotOperation(Expression *ParentExpression, AST_NODE_PTR currentNod Type* result = malloc(sizeof(Type)); result->nodePtr = currentNode; - if (Operand->kind == TypeKindBox || Operand->kind == TypeKindReference){ - return 1; + + if (Operand->kind == TypeKindBox || Operand->kind == TypeKindReference) { + print_diagnostic(current_file, &Operand->nodePtr->location, Error, "Operand must be a variant of primitive type int"); + return SEMANTIC_ERROR; } - if(Operand->kind == TypeKindPrimitive){ - if(Operand->impl.primitive == Float){ - return 1; + + if (Operand->kind == TypeKindPrimitive) { + if (Operand->impl.primitive == Float) { + print_diagnostic(current_file, &Operand->nodePtr->location, Error, "Operand must be a variant of primitive type int"); + return SEMANTIC_ERROR; } result->kind = Operand->kind; result->impl = Operand->impl; - }else if(Operand->kind == TypeKindComposite){ - if(Operand->impl.composite.primitive == Float){ - return 1; + + } else if(Operand->kind == TypeKindComposite) { + if (Operand->impl.composite.primitive == Float) { + print_diagnostic(current_file, &Operand->nodePtr->location, Error, "Operand must be a variant of primitive type int"); + return SEMANTIC_ERROR; } result->kind = Operand->kind; result->impl = Operand->impl; } ParentExpression->result = result; - return 0; + return SEMANTIC_OK; } -bool isScaleEqual(double leftScale, double rightScale){ - int leftIntScale =(int)(leftScale *4); - int rightIntScale =(int)(rightScale *4); +bool isScaleEqual(double leftScale, double rightScale) { + int leftIntScale = (int) (leftScale * BASE_BYTES); + int rightIntScale = (int) (rightScale * BASE_BYTES); - if (leftIntScale == rightIntScale){ - return TRUE; - } - return FALSE; + return leftIntScale == rightIntScale; } -int createBitOperation(Expression* ParentExpression, AST_NODE_PTR currentNode){ +int createBitOperation(Expression* ParentExpression, AST_NODE_PTR currentNode) { // fill kind and Nodeptr ParentExpression->impl.operation.kind = Boolean; ParentExpression->impl.operation.nodePtr = currentNode; // fill Operands - for (size_t i = 0; i < currentNode->child_count; i++){ + for (size_t i = 0; i < currentNode->child_count; i++) { Expression* expression = createExpression(currentNode->children[i]); - if(NULL == expression){ - return 1; + + if(NULL == expression) { + return SEMANTIC_ERROR; } + g_array_append_val(ParentExpression->impl.operation.operands , expression); } - - switch (currentNode->kind){ - case AST_BitAnd: - ParentExpression->impl.operation.impl.bitwise = BitwiseAnd; - case AST_BitOr: - ParentExpression->impl.operation.impl.bitwise = BitwiseOr; - case AST_BitXor: - ParentExpression->impl.operation.impl.bitwise = BitwiseXor; - default: - PANIC("Current node is not an bitwise operater"); - break; + switch (currentNode->kind) { + case AST_BitAnd: + ParentExpression->impl.operation.impl.bitwise = BitwiseAnd; + break; + case AST_BitOr: + ParentExpression->impl.operation.impl.bitwise = BitwiseOr; + break; + case AST_BitXor: + ParentExpression->impl.operation.impl.bitwise = BitwiseXor; + break; + default: + PANIC("Current node is not an bitwise operater"); + break; } - Type *result = malloc(sizeof(Type)); result->nodePtr = currentNode; + + Expression* lhs = ((Expression**) ParentExpression->impl.operation.operands->data)[0]; + Expression* rhs = ((Expression**) ParentExpression->impl.operation.operands->data)[1]; - Type* LeftOperandType = ((Expression**) ParentExpression->impl.operation.operands->data)[0]->result; - Type* RightOperandType = ((Expression**) ParentExpression->impl.operation.operands->data)[1]->result; + Type* LeftOperandType = lhs->result; + Type* RightOperandType = rhs->result; //should not be a box or a reference - if(LeftOperandType->kind != TypeKindPrimitive && LeftOperandType->kind != TypeKindComposite){ - return 1; + if (LeftOperandType->kind != TypeKindPrimitive && LeftOperandType->kind != TypeKindComposite) { + print_diagnostic(current_file, &lhs->nodePtr->location, Error, "Must be a type variant of int"); + return SEMANTIC_ERROR; } - if(RightOperandType->kind != TypeKindPrimitive && RightOperandType->kind != TypeKindComposite){ - return 1; + + if (RightOperandType->kind != TypeKindPrimitive && RightOperandType->kind != TypeKindComposite) { + print_diagnostic(current_file, &rhs->nodePtr->location, Error, "Must be a type variant of int"); + return SEMANTIC_ERROR; } - if(LeftOperandType->kind == TypeKindPrimitive && RightOperandType->kind == TypeKindPrimitive){ - if(LeftOperandType->impl.primitive == Float || RightOperandType->impl.primitive == Float){ - return 1; + + if (LeftOperandType->kind == TypeKindPrimitive && RightOperandType->kind == TypeKindPrimitive) { + + if (LeftOperandType->impl.primitive == Float) { + print_diagnostic(current_file, &lhs->nodePtr->location, Error, "Must be a type variant of int"); + return SEMANTIC_ERROR; } + + if (RightOperandType->impl.primitive == Float) { + print_diagnostic(current_file, &rhs->nodePtr->location, Error, "Must be a type variant of int"); + return SEMANTIC_ERROR; + } + result->kind = TypeKindPrimitive; result->impl.primitive = Int; - }else if(LeftOperandType->kind == TypeKindPrimitive && RightOperandType->kind == TypeKindComposite){ - if(LeftOperandType->impl.primitive == Float || RightOperandType->impl.composite.primitive == Float){ - return 1; + + } else if (LeftOperandType->kind == TypeKindPrimitive && RightOperandType->kind == TypeKindComposite) { + + if (LeftOperandType->impl.primitive == Float) { + print_diagnostic(current_file, &lhs->nodePtr->location, Error, "Must be a type variant of int"); + return SEMANTIC_ERROR; } - if((int)RightOperandType->impl.composite.scale != 1){ - return 1; + + if (RightOperandType->impl.composite.primitive == Float) { + print_diagnostic(current_file, &rhs->nodePtr->location, Error, "Must be a type variant of int"); + return SEMANTIC_ERROR; } + result->kind = TypeKindPrimitive; result->impl.primitive = Int; - }else if(LeftOperandType->kind == TypeKindComposite && RightOperandType->kind == TypeKindPrimitive){ - if(LeftOperandType->impl.composite.primitive == Float || RightOperandType->impl.primitive == Float){ - return 1; + + }else if (LeftOperandType->kind == TypeKindComposite && RightOperandType->kind == TypeKindPrimitive) { + + if (LeftOperandType->impl.composite.primitive == Float) { + print_diagnostic(current_file, &lhs->nodePtr->location, Error, "Must be a type variant of int"); + return SEMANTIC_ERROR; } - if((int)LeftOperandType->impl.composite.scale != 1){ - return 1; + + if (RightOperandType->impl.primitive == Float) { + print_diagnostic(current_file, &rhs->nodePtr->location, Error, "Must be a type variant of int"); + return SEMANTIC_ERROR; } + result->kind = TypeKindPrimitive; result->impl.primitive = Int; - }else{ - if(LeftOperandType->impl.composite.primitive == Float || RightOperandType->impl.composite.primitive == Float){ - return 1; + } else { + + if (RightOperandType->impl.composite.primitive == Float) { + print_diagnostic(current_file, &rhs->nodePtr->location, Error, "Must be a type variant of int"); + return SEMANTIC_ERROR; } - if(!isScaleEqual(LeftOperandType->impl.composite.scale, RightOperandType->impl.composite.scale)){ - return 1; + + if (LeftOperandType->impl.composite.primitive == Float) { + print_diagnostic(current_file, &lhs->nodePtr->location, Error, "Must be a type variant of int"); + return SEMANTIC_ERROR; } + + if (!isScaleEqual(LeftOperandType->impl.composite.scale, RightOperandType->impl.composite.scale)) { + print_diagnostic(current_file, ¤tNode->location, Error, "Operands must be of equal size"); + return SEMANTIC_ERROR; + } + result->kind = TypeKindComposite; result->impl.composite.nodePtr = currentNode; result->impl.composite.scale = LeftOperandType->impl.composite.scale; @@ -773,7 +893,7 @@ int createBitOperation(Expression* ParentExpression, AST_NODE_PTR currentNode){ return 0; } -int createBitNotOperation(Expression* ParentExpression, AST_NODE_PTR currentNode){ +int createBitNotOperation(Expression* ParentExpression, AST_NODE_PTR currentNode) { //fill kind and Nodeptr ParentExpression->impl.operation.kind = Bitwise; ParentExpression->impl.operation.nodePtr = currentNode; @@ -781,28 +901,33 @@ int createBitNotOperation(Expression* ParentExpression, AST_NODE_PTR currentNode //fill Operand Expression* expression = createExpression(currentNode->children[0]); if(NULL == expression){ - return 1; + return SEMANTIC_ERROR; } g_array_append_val(ParentExpression->impl.operation.operands , expression); ParentExpression->impl.operation.impl.bitwise = BitwiseNot; - Type* Operand = ((Expression**)ParentExpression->impl.operation.operands)[0]->result; + Type* Operand = ((Expression**) ParentExpression->impl.operation.operands)[0]->result; Type* result = malloc(sizeof(Type)); result->nodePtr = currentNode; - - if (Operand->kind == TypeKindPrimitive){ - if(Operand->impl.primitive == Float){ + if (Operand->kind == TypeKindPrimitive) { + + if (Operand->impl.primitive == Float) { + print_diagnostic(current_file, &Operand->nodePtr->location, Error, "Operand type must be a variant of int"); return SEMANTIC_ERROR; } + result->kind = TypeKindPrimitive; result->impl.primitive = Int; - }else if(Operand->kind == TypeKindComposite){ - if (Operand->impl.composite.primitive == Float){ + }else if(Operand->kind == TypeKindComposite) { + + if (Operand->impl.composite.primitive == Float) { + print_diagnostic(current_file, &Operand->nodePtr->location, Error, "Operand type must be a variant of int"); return SEMANTIC_ERROR; } + result->kind = TypeKindComposite; result->impl.composite.nodePtr = currentNode; result->impl.composite.primitive = Int; @@ -811,17 +936,17 @@ int createBitNotOperation(Expression* ParentExpression, AST_NODE_PTR currentNode } ParentExpression->result = result; + return SEMANTIC_OK; } -GArray* getBoxMember(Type* currentBoxType, GArray *names){ - +GArray* getBoxMember(Type* currentBoxType, GArray *names) { GArray *members = g_array_new(FALSE, FALSE, sizeof(BoxMember)); GHashTable* memberList = currentBoxType->impl.box.member; const char* currentName = ((const char **) names)[0]; - if(!g_hash_table_contains(memberList, currentName)){ + if(!g_hash_table_contains(memberList, currentName)) { // TODO: free members return NULL; } @@ -829,7 +954,7 @@ GArray* getBoxMember(Type* currentBoxType, GArray *names){ g_array_append_val(members, currentMember); g_array_remove_index(names,0); - if (names->len == 0){ + if (names->len == 0) { return members; } if (currentMember->type->kind == TypeKindBox){ @@ -850,6 +975,7 @@ int createBoxAccess(Expression* ParentExpression,AST_NODE_PTR currentNode) { int status = getVariableFromScope(boxname, &boxVariable); if(status == SEMANTIC_ERROR){ + print_diagnostic(current_file, ¤tNode->children[0]->location, Error, "Variable of name `%s` does not exist"); return SEMANTIC_ERROR; } Type* boxType; @@ -862,10 +988,11 @@ int createBoxAccess(Expression* ParentExpression,AST_NODE_PTR currentNode) { } else{ return SEMANTIC_ERROR; } - if (boxType->kind != TypeKindBox){ + if (boxType->kind != TypeKindBox) { return SEMANTIC_ERROR; } - //filling boxAccess variable + + // filling boxAccess variable ParentExpression->impl.variable->kind = VariableKindBoxMember; ParentExpression->impl.variable->nodePtr = currentNode; ParentExpression->impl.variable->name = NULL; @@ -876,8 +1003,16 @@ int createBoxAccess(Expression* ParentExpression,AST_NODE_PTR currentNode) { //first one is the box itself GArray* names = malloc(sizeof(GArray)); - for (size_t i = 1; i < currentNode->child_count; i++){ - g_array_append_val(names, currentNode->children[1]->value); + if(currentNode->kind == AST_IdentList){ + for (size_t i = 1; i < currentNode->child_count; i++){ + g_array_append_val(names, currentNode->children[i]->value); + } + }else if(currentNode->kind == AST_List){ + for (size_t i = 1; i < currentNode->children[1]->child_count; i++){ + g_array_append_val(names, currentNode->children[1]->children[i]->value); + } + }else{ + PANIC("current Node is not an Access"); } GArray * boxMember = getBoxMember(boxType, names); @@ -887,6 +1022,50 @@ int createBoxAccess(Expression* ParentExpression,AST_NODE_PTR currentNode) { } +int createTypeCast(Expression* ParentExpression, AST_NODE_PTR currentNode){ + ParentExpression->impl.typecast.nodePtr = currentNode; + + ParentExpression->impl.typecast.operand = createExpression(currentNode->children[0]); + if (ParentExpression->impl.typecast.operand == NULL){ + return SEMANTIC_ERROR; + } + + Type* target = malloc(sizeof(Type)); + int status = get_type_impl(currentNode->children[1], &target); + if (status) { + print_diagnostic(current_file, ¤tNode->children[1]->location, Error, "Unknown type"); + return SEMANTIC_ERROR; + } + ParentExpression->impl.typecast.targetType = target; + ParentExpression->result = target; + + return SEMANTIC_OK; +} + +int createTransmute(Expression* ParentExpression, AST_NODE_PTR currentNode){ + ParentExpression->impl.transmute.nodePtr = currentNode; + ParentExpression->impl.transmute.operand = createExpression(currentNode->children[0]); + + if (ParentExpression->impl.transmute.operand == NULL){ + return SEMANTIC_ERROR; + } + + Type* target = malloc(sizeof(Type)); + int status = get_type_impl(currentNode->children[1], &target); + if (status){ + print_diagnostic(current_file, ¤tNode->children[1]->location, Error, "Unknown type"); + return SEMANTIC_ERROR; + } + + ParentExpression->impl.typecast.targetType = target; + ParentExpression->result = target; + + return SEMANTIC_OK; + +} + + + Expression *createExpression(AST_NODE_PTR currentNode){ Expression *expression = malloc(sizeof(Expression)); expression->nodePtr = currentNode; @@ -908,6 +1087,7 @@ Expression *createExpression(AST_NODE_PTR currentNode){ int status = getVariableFromScope(currentNode->value, &expression->impl.variable ); if(status == SEMANTIC_ERROR){ DEBUG("Identifier is not in current scope"); + print_diagnostic(current_file, ¤tNode->location, Error, "Variable not found"); return NULL; } switch (expression->impl.variable->kind) { @@ -975,28 +1155,178 @@ Expression *createExpression(AST_NODE_PTR currentNode){ break; case AST_IdentList: - expression->kind = ExpressionKindVariable; - - //Box Accsess case AST_List: - // Box Self Access - case AST_Typekind: + expression->kind = ExpressionKindVariable; + if(createBoxAccess(expression, currentNode)){ + return NULL; + } + break; + case AST_Typecast: + expression->kind = ExpressionKindTypeCast; + if(createTypeCast(expression, currentNode)){ + return NULL; + } + break; case AST_Transmute: - - - + expression->kind = ExpressionKindTransmute; + if(createTransmute(expression, currentNode)){ + return NULL; + } + break; default: - PANIC("Node is not an expression but from kind: %i", currentNode->kind); + PANIC("Node is not an expression but from kind: %i", currentNode->kind); break; } return expression; } + + + int createAssign(Statement* ParentStatement, AST_NODE_PTR currentNode){ + Assignment assign; + assign.nodePtr = currentNode; + const char* varName = currentNode->children[0]->value; + + int status = getVariableFromScope(varName, &assign.variable); + if(status){ + return SEMANTIC_ERROR; + } + + assign.value = createExpression(currentNode->children[1]); + if(assign.value == NULL){ + return SEMANTIC_ERROR; + } + + ParentStatement->impl.assignment = assign; + return SEMANTIC_ERROR; + } +Statement *createStatement(AST_NODE_PTR currentNode); + +int createWhile(Statement * ParentStatement, AST_NODE_PTR currentNode){ + assert(ParentExpression == NULL); + assert(currentNode == NULL); + assert(currentNode->kind == AST_While); + + While whileStruct; + whileStruct.nodePtr = currentNode; + whileStruct.conditon = createExpression(currentNode->children[0]); + if(NULL == whileStruct.conditon){ + return SEMANTIC_ERROR; + } + AST_NODE_PTR statementList = currentNode->children[1]; + whileStruct.block.nodePtr = statementList; + + for(size_t i = 0; i < statementList->child_count; i++){ + Statement* statement = createStatement(statementList->children[i]); + if (NULL == statement) { + return SEMANTIC_ERROR; + } + g_array_append_val(whileStruct.block.statemnts, statement); + } + ParentStatement->impl.whileLoop = whileStruct; + + return SEMANTIC_OK; +} + +int fillBlock(Block * block,AST_NODE_PTR currentNode){ + block->nodePtr = currentNode; + + for(size_t i = 0; i < currentNode->child_count; i++){ + Statement* statement = createStatement(currentNode->children[i]); + if(statement == NULL){ + return SEMANTIC_ERROR; + } + g_array_append_val(block->statemnts,statement); + } + return SEMANTIC_OK; +} + +int createIf(Branch* Parentbranch, AST_NODE_PTR currentNode){ + If ifbranch; + ifbranch.nodePtr = currentNode; + + Expression* expression = createExpression(currentNode->children[0]); + if (NULL == expression) { + return SEMANTIC_ERROR; + } + ifbranch.conditon = expression; + int status = fillBlock(&ifbranch.block, currentNode->children[1]); + +} + +int createBranch(Statement* ParentStatement,AST_NODE_PTR currentNode){ + Branch Branch; + + for (size_t i = 0; i < currentNode->child_count; i++ ){ + switch (currentNode->children[i]->kind){ + case AST_If: + createIf(&Branch, currentNode->children[i]); + case AST_IfElse: + case AST_Else: + default: + PANIC("current node is not part of a Branch") + break; + + + } + } + +} + +Statement *createStatement(AST_NODE_PTR currentNode){ + Statement* statement = malloc(sizeof(Statement)); + statement->nodePtr = currentNode; + + switch(currentNode->kind){ + case AST_Decl: + statement->kind = StatementKindDeclaration; + + case AST_Def: + statement->kind = StatementKindDefinition; + case AST_While: + statement->kind = StatementKindWhile; + if(createWhile(statement, currentNode)){ + return NULL; + } + case AST_Stmt: + statement->kind = StatementKindBranch; + //ifbrnches: + + case AST_Assign: + statement->kind = StatementKindAssignment; + if(createAssign(statement, currentNode)){ + return NULL; + } + case AST_Call: + //both funcall and boxfuncall + default: + break; + } + +} +Function *createFunction(AST_NODE_PTR currentNode){ + +} +BoxType *createBox(AST_NODE_PTR currentNode){ + BoxType * box = malloc(sizeof(BoxType)); + + box->nodePtr = currentNode; + // + //box + // name + // list + // decl + // def // change BoxMember to have an + // fun //create static function + // a.b(dsadsadas) + + +} Module *create_set(AST_NODE_PTR currentNode){ DEBUG("create root Module"); @@ -1053,7 +1383,9 @@ Module *create_set(AST_NODE_PTR currentNode){ break; } case AST_Box: + case AST_Fun: + case AST_Typedef: case AST_Import: DEBUG("create Import"); g_array_append_val(imports, currentNode->children[i]->value); diff --git a/src/set/types.h b/src/set/types.h index 2e5e1ff..ae157bc 100644 --- a/src/set/types.h +++ b/src/set/types.h @@ -5,6 +5,9 @@ #include #include +// with of primitive types (int/float) in bytes +#define BASE_BYTES 4 + /** * @brief Primitive types form the basis of all other types. * @@ -36,7 +39,7 @@ typedef enum Sign_t { typedef double Scale; /** - * @brief A composite type is an extended definiton of a primitive type. + * @brief A composite type is an extended definition of a primitive type. * */ typedef struct CompositeType_t { @@ -124,7 +127,7 @@ typedef struct Typedefine_t { /** - * @brief Reprents the value of type. Can be used to definitons, initialization and for expressions contants. + * @brief Reprents the value of type. Can be used to definitions, initialization and for expressions contants. * */ typedef struct TypeValue_t { @@ -183,7 +186,7 @@ typedef enum ParameterKind_t { } ParameterKind; /** - * @brief A parameter can either be a declaration or a definiton + * @brief A parameter can either be a declaration or a definition * */ typedef struct Parameter_t { @@ -245,7 +248,7 @@ typedef struct VariableDeclaration_t { } VariableDeclaration; /** - * @brief Definiton of a variable + * @brief Definition of a variable * * @attention NOTE: The types of the initializer and the declaration must be equal * @@ -455,7 +458,7 @@ typedef struct Block_t { // '------------------------------------------------' typedef struct While_t { - Expression conditon; + Expression *conditon; Block block; AST_NODE_PTR nodePtr; } While; @@ -465,13 +468,13 @@ typedef struct While_t { // '------------------------------------------------' typedef struct If_t { - Expression conditon; + Expression *conditon; Block block; AST_NODE_PTR nodePtr; } If; typedef struct ElseIf_t { - Expression conditon; + Expression *conditon; Block block; AST_NODE_PTR nodePtr; } ElseIf; @@ -495,7 +498,7 @@ typedef struct Branch_t { typedef struct Assignment_t { Variable* variable; - Expression value; + Expression* value; AST_NODE_PTR nodePtr; } Assignment; @@ -504,7 +507,9 @@ typedef enum StatementKind_t { StatementKindFunctionBoxCall, StatementKindWhile, StatementKindBranch, - StatementKindAssignment + StatementKindAssignment, + StatementKindDeclaration, + StatementKindDefinition } StatementKind; typedef struct Statement_t { @@ -515,6 +520,7 @@ typedef struct Statement_t { While whileLoop; Branch branch; Assignment assignment; + Variable variable; } impl; AST_NODE_PTR nodePtr; } Statement; From 80c73e8b81c3c7bfcd0f44cd58cb6a8e9b27e993 Mon Sep 17 00:00:00 2001 From: Filleo Date: Wed, 5 Jun 2024 12:53:50 +0200 Subject: [PATCH 074/124] finished if branch --- src/set/set.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/set/set.c b/src/set/set.c index 3ac0add..8ed9f80 100644 --- a/src/set/set.c +++ b/src/set/set.c @@ -18,7 +18,7 @@ // | .----------' o // `--' // - +extern ModuleFile * current_file; static GHashTable *declaredComposites = NULL;//pointer to composites with names static GHashTable *declaredBoxes = NULL;//pointer to typeboxes static GArray *Scope = NULL;//list of hashtables. last Hashtable is current depth of program. hashtable key: ident, value: Variable* to var @@ -1251,6 +1251,15 @@ int createIf(Branch* Parentbranch, AST_NODE_PTR currentNode){ ifbranch.conditon = expression; int status = fillBlock(&ifbranch.block, currentNode->children[1]); + if(status){ + return SEMANTIC_ERROR; + } + Parentbranch->ifBranch = ifbranch; + return SEMANTIC_OK; +} + +int createElse(){ + } int createBranch(Statement* ParentStatement,AST_NODE_PTR currentNode){ @@ -1259,11 +1268,13 @@ int createBranch(Statement* ParentStatement,AST_NODE_PTR currentNode){ for (size_t i = 0; i < currentNode->child_count; i++ ){ switch (currentNode->children[i]->kind){ case AST_If: - createIf(&Branch, currentNode->children[i]); + if(createIf(&Branch, currentNode->children[i])){ + return SEMANTIC_ERROR; + } case AST_IfElse: case AST_Else: default: - PANIC("current node is not part of a Branch") + PANIC("current node is not part of a Branch"); break; From b8660c1595cc3c7d80def9daea181a1c3e67aec0 Mon Sep 17 00:00:00 2001 From: Filleo Date: Wed, 5 Jun 2024 21:16:52 +0200 Subject: [PATCH 075/124] major set build Co-authored-by: SirTalksalot75 --- src/set/set.c | 529 +++++++++++++++++++++++++++++++++++++++++------- src/set/types.h | 20 +- 2 files changed, 468 insertions(+), 81 deletions(-) diff --git a/src/set/set.c b/src/set/set.c index 8ed9f80..ac1af6a 100644 --- a/src/set/set.c +++ b/src/set/set.c @@ -11,13 +11,7 @@ #include #include -// -// .--. -// | '----------. . -// > | ~ ~ ~ ~ ~ .o O -// | .----------' o -// `--' -// + extern ModuleFile * current_file; static GHashTable *declaredComposites = NULL;//pointer to composites with names static GHashTable *declaredBoxes = NULL;//pointer to typeboxes @@ -283,6 +277,7 @@ StorageQualifier Qualifier_from_string(const char *str) { PANIC("Provided string is not a storagequalifier: %s", str); } +int addVarToScope(Variable * variable); int createDecl(AST_NODE_PTR currentNode, GArray** variables) { DEBUG("create declaration"); @@ -325,6 +320,10 @@ int createDecl(AST_NODE_PTR currentNode, GArray** variables) { variable->impl.declaration = decl; g_array_append_val(*variables, variable); + int signal = addVarToScope(variable); + if (signal){ + return SEMANTIC_ERROR; + } } return status; @@ -386,6 +385,10 @@ int createDef(AST_NODE_PTR currentNode, GArray** variables) { variable->name = ident_list->children[i]->value; variable->impl.definiton = def; g_array_append_val(*variables, variable); + int signal = addVarToScope(variable); + if (signal){ + return SEMANTIC_ERROR; + } } return status; @@ -430,7 +433,9 @@ int getVariableFromScope(const char* name, Variable** variable) { // loop through all variable scope and find a variable for(size_t i = 0; i < Scope->len; i++) { - GHashTable* variable_table = ((GHashTable**) Scope->data)[i]; + + + GHashTable* variable_table = g_array_index(Scope,GHashTable* ,i ); if(g_hash_table_contains(variable_table, name)) { *variable = g_hash_table_lookup(variable_table, name); @@ -441,22 +446,33 @@ int getVariableFromScope(const char* name, Variable** variable) { return SEMANTIC_ERROR; } -int fillTablesWithVars(GHashTable *variableTable, GHashTable *currentScope , GArray* variables) { +int addVarToScope(Variable * variable){ + Variable* tmp = NULL; + if(getVariableFromScope(variable->name, &tmp) == SEMANTIC_OK) { + INFO("this var already exist: ", variable->name); + return SEMANTIC_ERROR; + } + GHashTable * currentScope = g_array_index(Scope,GHashTable* ,Scope->len -1); + g_hash_table_insert(currentScope, (gpointer) variable->name, variable); + + return SEMANTIC_OK; +} + +int fillTablesWithVars(GHashTable *variableTable, GArray* variables) { DEBUG("filling vars in scope and table"); for(size_t i = 0; i < variables->len; i++) { - Variable* var = (Variable*) variables->data + i; + + + Variable* var = g_array_index(variables,Variable *,i); // this variable is discarded, only need status code - Variable* tmp = NULL; - if(getVariableFromScope(var->name, &tmp) == SEMANTIC_OK) { - INFO("this var already exist: ", var->name); + if(g_hash_table_contains(variableTable, (gpointer)var->name)){ return SEMANTIC_ERROR; } g_hash_table_insert(variableTable, (gpointer) var->name, var); - g_hash_table_insert(currentScope, (gpointer) var->name, var); - } + } return SEMANTIC_OK; } @@ -472,8 +488,12 @@ TypeValue createTypeValue(AST_NODE_PTR currentNode){ switch (currentNode->kind) { case AST_Int: type->impl.primitive = Int; + break; + case AST_Float: type->impl.primitive = Float; + break; + default: PANIC("Node is not an expression but from kind: %i", currentNode->kind); break; @@ -945,7 +965,7 @@ GArray* getBoxMember(Type* currentBoxType, GArray *names) { GArray *members = g_array_new(FALSE, FALSE, sizeof(BoxMember)); GHashTable* memberList = currentBoxType->impl.box.member; - const char* currentName = ((const char **) names)[0]; + const char* currentName = g_array_index(names,const char *,0); if(!g_hash_table_contains(memberList, currentName)) { // TODO: free members return NULL; @@ -1017,7 +1037,7 @@ int createBoxAccess(Expression* ParentExpression,AST_NODE_PTR currentNode) { GArray * boxMember = getBoxMember(boxType, names); ParentExpression->impl.variable->impl.member.member = boxMember; - ParentExpression->result = ((BoxMember *)boxMember->data)[boxMember->len].type; + ParentExpression->result = g_array_index(boxMember,BoxMember,boxMember->len).type; return SEMANTIC_OK; } @@ -1199,10 +1219,30 @@ Expression *createExpression(AST_NODE_PTR currentNode){ ParentStatement->impl.assignment = assign; return SEMANTIC_ERROR; } -Statement *createStatement(AST_NODE_PTR currentNode); +int createStatement(Block * block, AST_NODE_PTR currentNode); + +int fillBlock(Block * block,AST_NODE_PTR currentNode){ + block->nodePtr = currentNode; + + GHashTable * lowerScope = g_hash_table_new(g_str_hash,g_str_equal); + g_array_append_val(Scope, lowerScope); + + + for(size_t i = 0; i < currentNode->child_count; i++){ + int signal = createStatement(block, currentNode->children[i]); + if(signal){ + return SEMANTIC_ERROR; + } + } + + g_hash_table_destroy(lowerScope); + g_array_remove_index(Scope, Scope->len-1); + + return SEMANTIC_OK; +} int createWhile(Statement * ParentStatement, AST_NODE_PTR currentNode){ - assert(ParentExpression == NULL); + assert(ParentStatement == NULL); assert(currentNode == NULL); assert(currentNode->kind == AST_While); @@ -1213,32 +1253,17 @@ int createWhile(Statement * ParentStatement, AST_NODE_PTR currentNode){ return SEMANTIC_ERROR; } AST_NODE_PTR statementList = currentNode->children[1]; - whileStruct.block.nodePtr = statementList; - - for(size_t i = 0; i < statementList->child_count; i++){ - Statement* statement = createStatement(statementList->children[i]); - if (NULL == statement) { - return SEMANTIC_ERROR; - } - g_array_append_val(whileStruct.block.statemnts, statement); + + int signal = fillBlock(&whileStruct.block,statementList); + if(signal){ + return SEMANTIC_ERROR; } ParentStatement->impl.whileLoop = whileStruct; return SEMANTIC_OK; } -int fillBlock(Block * block,AST_NODE_PTR currentNode){ - block->nodePtr = currentNode; - for(size_t i = 0; i < currentNode->child_count; i++){ - Statement* statement = createStatement(currentNode->children[i]); - if(statement == NULL){ - return SEMANTIC_ERROR; - } - g_array_append_val(block->statemnts,statement); - } - return SEMANTIC_OK; -} int createIf(Branch* Parentbranch, AST_NODE_PTR currentNode){ If ifbranch; @@ -1258,74 +1283,383 @@ int createIf(Branch* Parentbranch, AST_NODE_PTR currentNode){ return SEMANTIC_OK; } -int createElse(){ +int createElse(Branch* Parentbranch, AST_NODE_PTR currentNode){ + Else elseBranch; + elseBranch.nodePtr = currentNode; + int status = fillBlock(&elseBranch.block, currentNode->children[0]); + + if(status){ + return SEMANTIC_ERROR; + } + Parentbranch->elseBranch = elseBranch; + return SEMANTIC_OK; } +int createElseIf(Branch* Parentbranch, AST_NODE_PTR currentNode){ + ElseIf elseIfBranch; + elseIfBranch.nodePtr = currentNode; + + Expression* expression = createExpression(currentNode->children[0]); + if (NULL == expression) { + return SEMANTIC_ERROR; + } + elseIfBranch.conditon = expression; + int status = fillBlock(&elseIfBranch.block, currentNode->children[1]); + + if(status){ + return SEMANTIC_ERROR; + } + g_array_append_val(Parentbranch->elseIfBranches,elseIfBranch); + return SEMANTIC_OK; +} + + + int createBranch(Statement* ParentStatement,AST_NODE_PTR currentNode){ Branch Branch; - + Branch.nodePtr = currentNode; for (size_t i = 0; i < currentNode->child_count; i++ ){ switch (currentNode->children[i]->kind){ case AST_If: if(createIf(&Branch, currentNode->children[i])){ return SEMANTIC_ERROR; } + break; + case AST_IfElse: + if(createElseIf(&Branch, currentNode)){ + return SEMANTIC_ERROR; + } + break; + case AST_Else: + if(createElse(&Branch, currentNode->children[i])){ + return SEMANTIC_ERROR; + } + break; + default: PANIC("current node is not part of a Branch"); break; - - } } - + ParentStatement->impl.branch = Branch; + return SEMANTIC_OK; } -Statement *createStatement(AST_NODE_PTR currentNode){ - Statement* statement = malloc(sizeof(Statement)); - statement->nodePtr = currentNode; - - switch(currentNode->kind){ - case AST_Decl: - statement->kind = StatementKindDeclaration; +int createStatement(Block * Parentblock , AST_NODE_PTR currentNode){ - case AST_Def: - statement->kind = StatementKindDefinition; - case AST_While: - statement->kind = StatementKindWhile; - if(createWhile(statement, currentNode)){ - return NULL; + + switch(currentNode->kind){ + case AST_Decl:{ + GArray *variable= g_array_new(FALSE, FALSE, sizeof(Variable*)); + + int status = createDecl(currentNode, &variable); + if(status){ + return SEMANTIC_ERROR; + } + for(size_t i = 0; i < variable->len ; i++){ + + Statement * statement = malloc(sizeof(Statement)); + statement->nodePtr = currentNode; + statement->kind = StatementKindDeclaration; + + + statement->impl.variable = g_array_index(variable,Variable *,i); + g_array_append_val(Parentblock->statemnts,statement); + } } - case AST_Stmt: - statement->kind = StatementKindBranch; - //ifbrnches: - - case AST_Assign: - statement->kind = StatementKindAssignment; - if(createAssign(statement, currentNode)){ - return NULL; + break; + + case AST_Def:{ + GArray *variable= g_array_new(FALSE, FALSE, sizeof(Variable*)); + + int status = createDef(currentNode, &variable); + + if(status){ + return SEMANTIC_ERROR; + } + for(size_t i = 0; i < variable->len ; i++){ + + Statement * statement = malloc(sizeof(Statement)); + statement->nodePtr = currentNode; + statement->kind = StatementKindDefinition; + + statement->impl.variable = g_array_index(variable,Variable *,i); + g_array_append_val(Parentblock->statemnts,statement); + } + } + break; + case AST_While:{ + Statement * statement = malloc(sizeof(Statement)); + statement->nodePtr = currentNode; + statement->kind = StatementKindWhile; + if(createWhile(statement, currentNode)){ + return SEMANTIC_ERROR; + } + g_array_append_val(Parentblock->statemnts,statement); + } + break; + case AST_Stmt:{ + Statement * statement = malloc(sizeof(Statement)); + statement->nodePtr = currentNode; + statement->kind = StatementKindBranch; + if(createBranch(statement, currentNode)){ + return SEMANTIC_ERROR; + } + g_array_append_val(Parentblock->statemnts,statement); + } + break; + case AST_Assign:{ + Statement * statement = malloc(sizeof(Statement)); + statement->nodePtr = currentNode; + statement->kind = StatementKindAssignment; + if(createAssign(statement, currentNode)){ + return SEMANTIC_ERROR; + } + g_array_append_val(Parentblock->statemnts,statement); + } + break; case AST_Call: - //both funcall and boxfuncall + //TODO both funcall and boxfuncall default: break; } + return SEMANTIC_OK; } +int createParam(GArray * Paramlist ,AST_NODE_PTR currentNode){ + AST_NODE_PTR paramdecl = currentNode->children[1]; + AST_NODE_PTR ioQualifierList = currentNode->children[0]; + + ParameterDeclaration decl; + decl.nodePtr = paramdecl; + + if(ioQualifierList->child_count == 2){ + decl.qualifier = InOut; + }else if(ioQualifierList->child_count == 1){ + if(strcmp(ioQualifierList->children[0]->value , "in")){ + decl.qualifier = In; + }else if(strcmp(ioQualifierList->children[0]->value , "out")){ + decl.qualifier = Out; + }else{ + PANIC("IO_Qualifier is not in or out"); + } + }else{ + PANIC("IO_Qualifier has not the right amount of children"); + } + + int signal = get_type_impl(paramdecl->children[0],&decl.type); + if(signal){ + return SEMANTIC_ERROR; + } -Function *createFunction(AST_NODE_PTR currentNode){ + Parameter param; + param.nodePtr = currentNode; + param.kind = ParameterDeclarationKind; + param.impl.declaration = decl; + param.name = paramdecl->children[1]->value; + + g_array_append_val(Paramlist,param); + return SEMANTIC_OK; } -BoxType *createBox(AST_NODE_PTR currentNode){ + +int createFunDef(Function * Parentfunction ,AST_NODE_PTR currentNode){ + + AST_NODE_PTR nameNode = currentNode->children[0]; + AST_NODE_PTR paramlistlist = currentNode->children[1]; + AST_NODE_PTR statementlist = currentNode->children[2]; + + + + FunctionDefinition fundef; + + fundef.nodePtr = currentNode; + fundef.name = nameNode->value; + fundef.body = malloc(sizeof(Block)); + fundef.parameter = malloc(sizeof(GArray)); + + int signal = fillBlock(fundef.body, statementlist); + if(signal){ + return SEMANTIC_ERROR; + } + + for(size_t i = 0; i < paramlistlist->child_count; i++){ + + //all parameterlists + AST_NODE_PTR paramlist = paramlistlist->children[i]; + + for (size_t j = 0; j < paramlistlist->child_count; j++){ + + int signal = createParam(fundef.parameter ,paramlist->children[i]); + //all params per list + if (signal){ + return SEMANTIC_ERROR; + } + } + } + + Parentfunction->nodePtr = currentNode; + Parentfunction->kind = FunctionDefinitionKind; + Parentfunction->impl.definition = fundef; + return SEMANTIC_OK; + + +} + +int createFunDecl(Function * Parentfunction ,AST_NODE_PTR currentNode){ + + AST_NODE_PTR nameNode = currentNode->children[0]; + AST_NODE_PTR paramlistlist = currentNode->children[1]; + + + + FunctionDeclaration fundecl; + + fundecl.nodePtr = currentNode; + fundecl.name = nameNode->value; + fundecl.parameter = malloc(sizeof(GArray)); + + + for(size_t i = 0; i < paramlistlist->child_count; i++){ + + //all parameterlists + AST_NODE_PTR paramlist = paramlistlist->children[i]; + + for (size_t j = 0; j < paramlistlist->child_count; j++){ + + int signal = createParam(fundecl.parameter ,paramlist->children[i]); + //all params per list + if (signal){ + return SEMANTIC_ERROR; + } + } + } + + Parentfunction->nodePtr = currentNode; + Parentfunction->kind = FunctionDefinitionKind; + Parentfunction->impl.declaration = fundecl; + return SEMANTIC_OK; +} +//TODO check if a function is present and if a declaration is present and identical. + +Function * createFunction( AST_NODE_PTR currentNode){ + Function * fun = malloc(sizeof(Function)); + + + if(currentNode->child_count == 2){ + int signal = createFunDecl(fun, currentNode); + if (signal){ + return NULL; + } + }else if(currentNode->child_count == 3){ + int signal = createFunDef(fun, currentNode); + if (signal){ + return NULL; + } + }else { + PANIC("function should have 2 or 3 children"); + } + + return fun; +} + + + +int createDeclMember(BoxType * ParentBox, AST_NODE_PTR currentNode){ + + Type * declType = malloc(sizeof(Type)); + int status = get_type_impl(currentNode->children[0],&declType); + if(status){ + return SEMANTIC_ERROR; + } + + AST_NODE_PTR nameList = currentNode->children[1]; + for(size_t i = 0; i < nameList->child_count; i++){ + BoxMember * decl = malloc(sizeof(BoxMember)); + decl->name = nameList->children[i]->value; + decl->nodePtr = currentNode; + decl->box = ParentBox; + decl->initalizer = NULL; + decl->type = declType; + if(g_hash_table_contains(ParentBox->member, (gpointer)decl->name)){ + return SEMANTIC_ERROR; + } + g_hash_table_insert(ParentBox->member,(gpointer)decl->name,decl); + } + return SEMANTIC_OK; +} + +int createDefMember(BoxType *ParentBox, AST_NODE_PTR currentNode){ + AST_NODE_PTR declNode = currentNode->children[0]; + AST_NODE_PTR expressionNode = currentNode->children[1]; + AST_NODE_PTR nameList = declNode->children[1]; + + Type * declType = malloc(sizeof(Type)); + int status = get_type_impl(currentNode->children[0],&declType); + if(status){ + return SEMANTIC_ERROR; + } + + Expression * init = createExpression(expressionNode);; + if (init == NULL){ + return SEMANTIC_ERROR; + } + + for (size_t i = 0; i < nameList->child_count; i++){ + BoxMember *def = malloc(sizeof(BoxMember)); + def->box = ParentBox; + def->type = declType; + def->initalizer = init; + def->name = nameList->children[i]->value; + def->nodePtr = currentNode; + if(g_hash_table_contains(ParentBox->member, (gpointer)def->name)){ + return SEMANTIC_ERROR; + } + g_hash_table_insert(ParentBox->member,(gpointer)def->name,def); + } + return SEMANTIC_OK; +} + +int createBox(GHashTable *boxes, AST_NODE_PTR currentNode){ BoxType * box = malloc(sizeof(BoxType)); box->nodePtr = currentNode; + const char * boxName = currentNode->children[0]->value; + AST_NODE_PTR boxMemberList = currentNode->children[1]; + for (size_t i = 0; boxMemberList->child_count; i++){ + switch (boxMemberList->children[i]->kind) { + case AST_Decl: + if(createDeclMember(box, boxMemberList->children[i]->children[i])){ + return SEMANTIC_ERROR; + } + break; + case AST_Def: + if(createDeclMember(box, boxMemberList->children[i]->children[i])){ + return SEMANTIC_ERROR; + } + break; + case AST_Fun: + //TODO FUNCTION Wait for createFunction() + default: + break; + } + + } + if(g_hash_table_contains(boxes, (gpointer)boxName)){ + return SEMANTIC_ERROR; + } + g_hash_table_insert(boxes, (gpointer)boxName, box); + return SEMANTIC_OK; + + // //box // name @@ -1335,9 +1669,40 @@ BoxType *createBox(AST_NODE_PTR currentNode){ // fun //create static function // a.b(dsadsadas) + //type box: boxy { + // + //long short int: a + // + //short short float: floaty = 0.54 + // + //fun main (){ + //int: a = 5 + //} + +} + +int createTypeDef(GHashTable *types, AST_NODE_PTR currentNode){ + AST_NODE_PTR typeNode = currentNode->children[0]; + AST_NODE_PTR nameNode = currentNode->children[1]; -} + Type * type = malloc(sizeof(Type)); + int status = get_type_impl( typeNode, &type); + if(status){ + return SEMANTIC_ERROR; + } + + Typedefine *def = malloc(sizeof(Typedefine)); + def->name = nameNode->value; + def->nodePtr = currentNode; + def->type = type; + + if(g_hash_table_contains(types, (gpointer)def->name)){ + return SEMANTIC_ERROR; + } + g_hash_table_insert(types, (gpointer)def->name, def); + return SEMANTIC_OK; +} Module *create_set(AST_NODE_PTR currentNode){ DEBUG("create root Module"); @@ -1378,8 +1743,10 @@ Module *create_set(AST_NODE_PTR currentNode){ case AST_Decl: { GArray* vars; int status = createDecl(currentNode->children[i], &vars); - - if (fillTablesWithVars(variables, globalscope, vars) == SEMANTIC_ERROR) { + if (status){ + return NULL; + } + if (fillTablesWithVars(variables, vars) == SEMANTIC_ERROR) { print_diagnostic(current_file, ¤tNode->children[i]->location, Error, "Variable already declared"); INFO("var already exists"); break; @@ -1390,13 +1757,29 @@ Module *create_set(AST_NODE_PTR currentNode){ case AST_Def: { GArray* vars; int status = createDef(currentNode->children[i], &vars); + if (status){ + return NULL; + } DEBUG("created Definition successfully"); break; } - case AST_Box: - + case AST_Box:{ + int status = createBox(boxes, currentNode->children[i]); + if (status){ + return NULL; + } + DEBUG("created Box successfully"); + break; + } case AST_Fun: - case AST_Typedef: + case AST_Typedef:{ + int status = createTypeDef(types, currentNode->children[i]); + if (status){ + return NULL; + } + DEBUG("created Typedef successfully"); + break; + } case AST_Import: DEBUG("create Import"); g_array_append_val(imports, currentNode->children[i]->value); diff --git a/src/set/types.h b/src/set/types.h index ae157bc..b73112c 100644 --- a/src/set/types.h +++ b/src/set/types.h @@ -74,10 +74,13 @@ typedef struct BoxType_t BoxType; typedef struct Block_t Block; +typedef struct Expression_t Expression; + typedef struct BoxMember_t { const char* name; Type* type; BoxType* box; + Expression* initalizer; AST_NODE_PTR nodePtr; } BoxMember; @@ -88,12 +91,11 @@ typedef struct BoxMember_t { typedef struct BoxType_t { // hashtable of members. // Associates the memebers name (const char*) with its type (BoxMember) - GHashTable* member; + GHashTable* member; //BoxMember Pointer AST_NODE_PTR nodePtr; } BoxType; typedef struct Variable_t Variable; -typedef struct Expression_t Expression; typedef struct BoxAccess_t { // list of recursive box accesses @@ -208,7 +210,7 @@ typedef enum FunctionKind_t { typedef struct FunctionDefinition_t { // hashtable of parameters // associates a parameters name (const char*) with its parameter declaration (ParameterDeclaration) - GArray* parameter; + GArray* parameter; // Parameter AST_NODE_PTR nodePtr; // body of function Block *body; @@ -219,8 +221,9 @@ typedef struct FunctionDefinition_t { typedef struct FunctionDeclaration_t { // hashtable of parameters // associates a parameters name (const char*) with its parameter declaration (ParameterDeclaration) - GArray* parameter; + GArray* parameter; // Parameter AST_NODE_PTR nodePtr; + const char* name; } FunctionDeclaration; typedef struct Function_t { @@ -229,6 +232,7 @@ typedef struct Function_t { FunctionDefinition definition; FunctionDeclaration declaration; } impl; + AST_NODE_PTR nodePtr; } Function; // .------------------------------------------------. @@ -449,7 +453,7 @@ typedef struct FunctionBoxCall_t { typedef struct Block_t { // array of statements - GArray* statemnts; + GArray* statemnts; // array of type(Statement) AST_NODE_PTR nodePtr; } Block; @@ -520,7 +524,7 @@ typedef struct Statement_t { While whileLoop; Branch branch; Assignment assignment; - Variable variable; + Variable *variable; } impl; AST_NODE_PTR nodePtr; } Statement; @@ -530,8 +534,8 @@ typedef struct Statement_t { // '------------------------------------------------' typedef struct Module_t { - GHashTable* boxes; - GHashTable* types; + GHashTable* boxes; //BoxType + GHashTable* types; // GHashTable* functions; GHashTable* variables; // to be resolved after the module has been parsed completely From 069369ca61644fe68724727e1ba46ab7c01d9e5a Mon Sep 17 00:00:00 2001 From: Filleo Date: Wed, 5 Jun 2024 21:20:21 +0200 Subject: [PATCH 076/124] minor change --- src/io/files.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/io/files.c b/src/io/files.c index d091d06..6e5ab34 100644 --- a/src/io/files.c +++ b/src/io/files.c @@ -122,7 +122,7 @@ void print_diagnostic(ModuleFile *file, TokenLocation *location, Message kind, c printf("%s%s:%ld:%s %s%s:%s ", BOLD, absolute_path, location->line_start, RESET, accent_color, kind_text, RESET); va_list args; - va_start(args, format); + va_start(args, message); vprintf(message, args); From 30230249ae12c1b70ea7039596f7cb5d0a8f692a Mon Sep 17 00:00:00 2001 From: servostar Date: Wed, 5 Jun 2024 21:38:46 +0200 Subject: [PATCH 077/124] added: verification of llvm module after compilation --- src/llvm/parser.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/llvm/parser.c b/src/llvm/parser.c index 57c989e..ae86e32 100644 --- a/src/llvm/parser.c +++ b/src/llvm/parser.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -203,6 +204,15 @@ static BackendError build_module(LLVMBackendCompileUnit* unit, // TODO: implement functions err = impl_functions(unit, global_scope, module->functions); + char* error = NULL; + LLVMVerifyModule(unit->module, LLVMAbortProcessAction, &error); + + if (error) { + print_message(Error, "Unable to compile due to: %s", error); + LLVMDisposeMessage(error); + err = new_backend_impl_error(Implementation, NULL, "LLVM backend verification error, see stdout"); + } + return err; } From 4067339df812c2c90650453c97e50b817876b3d1 Mon Sep 17 00:00:00 2001 From: Filleo Date: Wed, 5 Jun 2024 23:55:30 +0200 Subject: [PATCH 078/124] first kind of working implementation of set --- src/compiler.c | 3 ++- src/set/set.c | 67 ++++++++++++++++++++++++++++++++++++------------- src/set/types.h | 1 + 3 files changed, 53 insertions(+), 18 deletions(-) diff --git a/src/compiler.c b/src/compiler.c index 709592e..8bb446a 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -11,6 +11,7 @@ #include #include #include +#include extern void yyrestart(FILE *); @@ -140,7 +141,7 @@ static void build_target(ModuleFileStack *unit, const TargetConfig *target) { if (setup_target_environment(target) == 0) { print_ast_to_file(ast, target); - + Module * test = create_set(ast); // TODO: parse AST to semantic values // TODO: backend codegen } diff --git a/src/set/set.c b/src/set/set.c index ac1af6a..d16ab0e 100644 --- a/src/set/set.c +++ b/src/set/set.c @@ -93,7 +93,7 @@ int scale_factor_from(const char* string, double* factor) { int check_scale_factor(AST_NODE_PTR node, Scale scale) { assert(node != NULL); - if (8 > scale) { + if (8 < scale) { print_diagnostic(current_file, &node->location, Error, "Composite scale overflow"); return SEMANTIC_ERROR; } @@ -222,6 +222,7 @@ int get_type_impl(AST_NODE_PTR currentNode, Type** type) { assert(currentNode != NULL); assert(currentNode->kind == AST_Type); assert(currentNode->child_count > 0); + DEBUG("start Type"); int status; @@ -340,7 +341,8 @@ int createDef(AST_NODE_PTR currentNode, GArray** variables) { AST_NODE_PTR declaration = currentNode->children[0]; AST_NODE_PTR expression = currentNode->children[1]; - AST_NODE_PTR ident_list = currentNode->children[0]->children[currentNode->child_count - 1]; + AST_NODE_PTR ident_list = declaration->children[currentNode->child_count - 1]; + *variables = g_array_new(FALSE, FALSE, sizeof(Variable*)); @@ -351,20 +353,20 @@ int createDef(AST_NODE_PTR currentNode, GArray** variables) { int status = SEMANTIC_OK; DEBUG("Child Count: %i", declaration->child_count); - for (size_t i = 0; i < declaration->children[i]->child_count; i++){ + for (size_t i = 0; i < declaration->child_count; i++){ switch(declaration->children[i]->kind) { case AST_Storage: DEBUG("fill Qualifier"); - decl.qualifier = Qualifier_from_string(currentNode->children[i]->value); + decl.qualifier = Qualifier_from_string(declaration->children[i]->value); break; case AST_Type: DEBUG("fill Type"); - status = get_type_impl(currentNode->children[i], &decl.type); + status = get_type_impl(declaration->children[i], &decl.type); break; case AST_IdentList: break; default: - PANIC("invalid node type: %ld", currentNode->children[i]->kind); + PANIC("invalid node type: %ld", declaration->children[i]->kind); break; } } @@ -1087,6 +1089,7 @@ int createTransmute(Expression* ParentExpression, AST_NODE_PTR currentNode){ Expression *createExpression(AST_NODE_PTR currentNode){ + DEBUG("create Expression"); Expression *expression = malloc(sizeof(Expression)); expression->nodePtr = currentNode; switch(currentNode->kind){ @@ -1222,6 +1225,7 @@ Expression *createExpression(AST_NODE_PTR currentNode){ int createStatement(Block * block, AST_NODE_PTR currentNode); int fillBlock(Block * block,AST_NODE_PTR currentNode){ + DEBUG("start filling Block"); block->nodePtr = currentNode; GHashTable * lowerScope = g_hash_table_new(g_str_hash,g_str_equal); @@ -1238,6 +1242,7 @@ int fillBlock(Block * block,AST_NODE_PTR currentNode){ g_hash_table_destroy(lowerScope); g_array_remove_index(Scope, Scope->len-1); + DEBUG("created Block successfully"); return SEMANTIC_OK; } @@ -1349,7 +1354,7 @@ int createBranch(Statement* ParentStatement,AST_NODE_PTR currentNode){ } int createStatement(Block * Parentblock , AST_NODE_PTR currentNode){ - + DEBUG("create Statement"); switch(currentNode->kind){ case AST_Decl:{ @@ -1433,12 +1438,18 @@ int createStatement(Block * Parentblock , AST_NODE_PTR currentNode){ int createParam(GArray * Paramlist ,AST_NODE_PTR currentNode){ + DEBUG("start param"); + DEBUG("current node child count: %i",currentNode->kind); + if( currentNode->kind == AST_Parameter){ + DEBUG("current n"); + } AST_NODE_PTR paramdecl = currentNode->children[1]; AST_NODE_PTR ioQualifierList = currentNode->children[0]; ParameterDeclaration decl; decl.nodePtr = paramdecl; + DEBUG("paramnode child count: %i", ioQualifierList->child_count ); if(ioQualifierList->child_count == 2){ decl.qualifier = InOut; }else if(ioQualifierList->child_count == 1){ @@ -1452,7 +1463,7 @@ int createParam(GArray * Paramlist ,AST_NODE_PTR currentNode){ }else{ PANIC("IO_Qualifier has not the right amount of children"); } - + int signal = get_type_impl(paramdecl->children[0],&decl.type); if(signal){ return SEMANTIC_ERROR; @@ -1466,12 +1477,13 @@ int createParam(GArray * Paramlist ,AST_NODE_PTR currentNode){ param.name = paramdecl->children[1]->value; g_array_append_val(Paramlist,param); + DEBUG("created param successfully"); return SEMANTIC_OK; } int createFunDef(Function * Parentfunction ,AST_NODE_PTR currentNode){ - + DEBUG("start fundef"); AST_NODE_PTR nameNode = currentNode->children[0]; AST_NODE_PTR paramlistlist = currentNode->children[1]; AST_NODE_PTR statementlist = currentNode->children[2]; @@ -1508,13 +1520,14 @@ int createFunDef(Function * Parentfunction ,AST_NODE_PTR currentNode){ Parentfunction->nodePtr = currentNode; Parentfunction->kind = FunctionDefinitionKind; Parentfunction->impl.definition = fundef; + Parentfunction->name = fundef.name; return SEMANTIC_OK; } int createFunDecl(Function * Parentfunction ,AST_NODE_PTR currentNode){ - + DEBUG("start fundecl"); AST_NODE_PTR nameNode = currentNode->children[0]; AST_NODE_PTR paramlistlist = currentNode->children[1]; @@ -1545,29 +1558,34 @@ int createFunDecl(Function * Parentfunction ,AST_NODE_PTR currentNode){ Parentfunction->nodePtr = currentNode; Parentfunction->kind = FunctionDefinitionKind; Parentfunction->impl.declaration = fundecl; + Parentfunction->name = fundecl.name; return SEMANTIC_OK; } //TODO check if a function is present and if a declaration is present and identical. -Function * createFunction( AST_NODE_PTR currentNode){ +int createFunction(GHashTable* functions, AST_NODE_PTR currentNode){ + assert(currentNode->kind == AST_Fun); Function * fun = malloc(sizeof(Function)); - + if(currentNode->child_count == 2){ int signal = createFunDecl(fun, currentNode); if (signal){ - return NULL; + return SEMANTIC_ERROR; } }else if(currentNode->child_count == 3){ int signal = createFunDef(fun, currentNode); if (signal){ - return NULL; + return SEMANTIC_ERROR; } }else { PANIC("function should have 2 or 3 children"); } - - return fun; + if(g_hash_table_contains(functions,fun->name)){ + return SEMANTIC_ERROR; + } + g_hash_table_insert(functions,(gpointer)fun->name, fun); + return SEMANTIC_OK; } @@ -1682,6 +1700,7 @@ int createBox(GHashTable *boxes, AST_NODE_PTR currentNode){ } int createTypeDef(GHashTable *types, AST_NODE_PTR currentNode){ + DEBUG("create Type define"); AST_NODE_PTR typeNode = currentNode->children[0]; AST_NODE_PTR nameNode = currentNode->children[1]; @@ -1701,6 +1720,11 @@ int createTypeDef(GHashTable *types, AST_NODE_PTR currentNode){ return SEMANTIC_ERROR; } g_hash_table_insert(types, (gpointer)def->name, def); + if(g_hash_table_contains(declaredComposites, (gpointer)def->name)){ + return SEMANTIC_ERROR; + } + g_hash_table_insert(declaredComposites, (gpointer)def->name, def); + return SEMANTIC_OK; } @@ -1771,7 +1795,16 @@ Module *create_set(AST_NODE_PTR currentNode){ DEBUG("created Box successfully"); break; } - case AST_Fun: + case AST_Fun:{ + DEBUG("start function"); + int status = createFunction(functions,currentNode->children[i]); + if (status){ + return NULL; + } + DEBUG("created function successfully"); + break; + + } case AST_Typedef:{ int status = createTypeDef(types, currentNode->children[i]); if (status){ diff --git a/src/set/types.h b/src/set/types.h index b73112c..1d415c1 100644 --- a/src/set/types.h +++ b/src/set/types.h @@ -233,6 +233,7 @@ typedef struct Function_t { FunctionDeclaration declaration; } impl; AST_NODE_PTR nodePtr; + const char * name; } Function; // .------------------------------------------------. From 3e43960508e589e0a8a6a2b3f796c888ed846167 Mon Sep 17 00:00:00 2001 From: servostar Date: Thu, 6 Jun 2024 11:26:26 +0200 Subject: [PATCH 079/124] transitioned from manual file utilites to glib --- src/cfg/opt.c | 74 +++++++++++++++++++++++++++++++++++++--- src/cfg/opt.h | 8 +++++ src/compiler.c | 28 +++++++++++---- src/io/files.c | 52 +++------------------------- src/io/files.h | 11 ------ src/llvm/parser.c | 20 ++++++----- tests/project/build.toml | 4 +-- 7 files changed, 117 insertions(+), 80 deletions(-) diff --git a/src/cfg/opt.c b/src/cfg/opt.c index 256e2eb..3529ded 100644 --- a/src/cfg/opt.c +++ b/src/cfg/opt.c @@ -102,10 +102,37 @@ TargetConfig* default_target_config() { config->output_directory = strdup("bin"); config->optimization_level = 1; config->root_module = NULL; + config->link_search_paths = g_array_new(FALSE, FALSE, sizeof(char*)); return config; } +const char* get_absolute_link_path(const TargetConfig* config, const char* link_target_name) { + + for (guint i = 0; i < config->link_search_paths->len; i++) { + const char* link_directory_path = g_array_index(config->link_search_paths, char*, i); + + char* path = g_build_filename(link_directory_path, link_target_name, NULL); + char* cwd = g_get_current_dir(); + char* canonical = g_canonicalize_filename(path, cwd); + + const gboolean exists = g_file_test(canonical, G_FILE_TEST_EXISTS); + const gboolean is_dir = g_file_test(canonical, G_FILE_TEST_IS_DIR); + + g_free(path); + g_free(cwd); + + if (exists && !is_dir) { + return canonical; + } + + g_free(canonical); + } + + // file not found + return NULL; +} + TargetConfig* default_target_config_from_args() { DEBUG("generating default target from command line..."); @@ -145,6 +172,36 @@ TargetConfig* default_target_config_from_args() { } } + if (is_option_set("link-paths")) { + const Option* opt = get_option("link-paths"); + + if (opt->value != NULL) { + + const char* start = opt->value; + const char* end = NULL; + while((end = strchr(start, ',')) != NULL) { + + const int len = end - start; + char* link_path = malloc(len + 1); + memcpy(link_path, start, len); + link_path[len] = 0; + + g_array_append_val(config->link_search_paths, link_path); + + start = end; + } + + const int len = strlen(start); + if (len > 0) { + char* link_path = malloc(len + 1); + memcpy(link_path, start, len); + link_path[len] = 0; + + g_array_append_val(config->link_search_paths, link_path); + } + } + } + GArray* files = get_non_options_after("compile"); if (files == NULL) { @@ -172,11 +229,12 @@ void print_help(void) { "Compile non-project file: gsc compile [file]", "Output information: gsc