From 560e24950e72d2d93b8d4e8706985d29c01f160d Mon Sep 17 00:00:00 2001 From: servostar Date: Wed, 12 Jun 2024 00:08:13 +0200 Subject: [PATCH] added: string constants to backend llvm --- src/cfg/opt.c | 4 ++++ src/cfg/opt.h | 1 + src/compiler.c | 39 ++++++++++++++++++++++++++++++++++++--- src/llvm/llvm-ir/expr.c | 28 ++++++++++++++++++++++++++++ src/llvm/llvm-ir/types.c | 16 +++++++++++++--- src/llvm/parser.c | 3 +++ src/set/set.c | 7 ++++--- src/set/set.h | 5 +++++ 8 files changed, 94 insertions(+), 9 deletions(-) diff --git a/src/cfg/opt.c b/src/cfg/opt.c index d907961..57ed113 100644 --- a/src/cfg/opt.c +++ b/src/cfg/opt.c @@ -106,6 +106,7 @@ TargetConfig* default_target_config() { config->link_search_paths = g_array_new(FALSE, FALSE, sizeof(char*)); config->lld_fatal_warnings = FALSE; config->gsc_fatal_warnings = FALSE; + config->import_paths = mem_new_g_array(MemoryNamespaceOpt, sizeof(char*)); return config; } @@ -208,6 +209,9 @@ TargetConfig* default_target_config_from_args() { g_array_free(files, TRUE); } + char* default_import_path = mem_strdup(MemoryNamespaceOpt, "."); + g_array_append_val(config->import_paths, default_import_path); + return config; } diff --git a/src/cfg/opt.h b/src/cfg/opt.h index 53fe5f6..9b61def 100644 --- a/src/cfg/opt.h +++ b/src/cfg/opt.h @@ -61,6 +61,7 @@ typedef struct TargetConfig_t { bool lld_fatal_warnings; // treat parser warnings as errors bool gsc_fatal_warnings; + GArray* import_paths; } TargetConfig; /** diff --git a/src/compiler.c b/src/compiler.c index b9dcf9f..01fb79c 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -164,7 +164,35 @@ static void run_backend_codegen(const Module* module, const TargetConfig* target err = deinit_backend(); } -static AST_NODE_PTR compile_module_with_dependencies(ModuleFileStack *unit, ModuleFile* file) { +const char* get_absolute_import_path(const TargetConfig* config, const char* import_target_name) { + INFO("resolving absolute path for import target: %s", import_target_name); + + for (guint i = 0; i < config->import_paths->len; i++) { + const char* import_directory_path = g_array_index(config->import_paths, char*, i); + + char* path = g_build_filename(import_directory_path, import_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) { + INFO("import target found at: %s", canonical); + return canonical; + } + + g_free(canonical); + } + + // file not found + return NULL; +} + +static AST_NODE_PTR compile_module_with_dependencies(ModuleFileStack *unit, ModuleFile* file, const TargetConfig *target) { AST_NODE_PTR root_module = AST_new_node(empty_location(), AST_Module, NULL); if (compile_file_to_ast(root_module, file) == EXIT_SUCCESS) { @@ -175,7 +203,12 @@ static AST_NODE_PTR compile_module_with_dependencies(ModuleFileStack *unit, Modu if (child->kind == AST_Import) { AST_NODE_PTR imported_module = AST_new_node(empty_location(), AST_Module, NULL); - ModuleFile *imported_file = push_file(unit, child->value); + const char* path = get_absolute_import_path(target, child->value); + if (path == NULL) { + return NULL; + } + + ModuleFile *imported_file = push_file(unit, path); if (compile_file_to_ast(imported_module, imported_file) == EXIT_SUCCESS) { AST_merge_modules(root_module, i + 1, imported_module); @@ -196,7 +229,7 @@ static void build_target(ModuleFileStack *unit, const TargetConfig *target) { print_message(Info, "Building target: %s", target->name); ModuleFile *file = push_file(unit, target->root_module); - AST_NODE_PTR ast = compile_module_with_dependencies(unit, file); + AST_NODE_PTR ast = compile_module_with_dependencies(unit, file, target); if (ast != NULL) { if (setup_target_environment(target) == 0) { diff --git a/src/llvm/llvm-ir/expr.c b/src/llvm/llvm-ir/expr.c index 9c13729..5b2d0d3 100644 --- a/src/llvm/llvm-ir/expr.c +++ b/src/llvm/llvm-ir/expr.c @@ -5,6 +5,7 @@ #include #include #include +#include BackendError impl_bitwise_operation(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, @@ -394,6 +395,29 @@ BackendError impl_address_of(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope return SUCCESS; } +BackendError impl_deref(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, + LLVMBuilderRef builder, Dereference* dereference, + LLVMValueRef *llvm_result) { + BackendError err; + + LLVMValueRef llvm_pointer = get_variable(scope, dereference->variable->impl.variable->name); + LLVMTypeRef llvm_deref_type = NULL; + err = get_type_impl(unit, scope->func_scope->global_scope, dereference->variable->result, &llvm_deref_type); + if (err.kind != Success) { + return err; + } + + LLVMValueRef* index = mem_alloc(MemoryNamespaceLlvm, sizeof(LLVMValueRef)); + err = impl_expr(unit, scope, builder, dereference->index, FALSE, index); + if (err.kind != Success) { + return err; + } + + *llvm_result = LLVMBuildGEP2(builder, llvm_deref_type, llvm_pointer, index, 1, "expr.deref"); + + return err; +} + BackendError impl_expr(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, LLVMBuilderRef builder, Expression *expr, LLVMBool reference, @@ -427,6 +451,10 @@ BackendError impl_expr(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope, err = impl_address_of(unit, scope, builder, &expr->impl.addressOf, llvm_result); break; + case ExpressionKindDereference: + err = impl_deref(unit, scope, builder, &expr->impl.dereference, + llvm_result); + break; default: err = new_backend_impl_error(Implementation, NULL, "unknown expression"); break; diff --git a/src/llvm/llvm-ir/types.c b/src/llvm/llvm-ir/types.c index a9458e8..e577440 100644 --- a/src/llvm/llvm-ir/types.c +++ b/src/llvm/llvm-ir/types.c @@ -5,6 +5,7 @@ #include #include #include +#include #define BASE_BYTES 4 #define BITS_PER_BYTE 8 @@ -33,6 +34,17 @@ static BackendError get_const_composite_value(CompositeType composite, llvm_value); } +BackendError impl_reference_const(TypeValue* value, LLVMValueRef* llvm_value) { + BackendError err = SUCCESS; + if (value->type->kind == TypeKindReference && compareTypes(value->type, (Type*) &StringLiteralType)) { + // is string literal + *llvm_value = LLVMConstString(value->value, strlen(value->value), FALSE); + } else { + err = new_backend_impl_error(Implementation, value->nodePtr, "reference initializer can only be string literals"); + } + return err; +} + BackendError get_const_type_value(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope, TypeValue* gemstone_value, @@ -58,9 +70,7 @@ BackendError get_const_type_value(LLVMBackendCompileUnit* unit, llvm_value); break; case TypeKindReference: - err = - new_backend_impl_error(Implementation, gemstone_value->nodePtr, - "reference cannot be constant value"); + err = impl_reference_const(gemstone_value, llvm_value); break; case TypeKindBox: err = diff --git a/src/llvm/parser.c b/src/llvm/parser.c index 19f0d04..735c8c1 100644 --- a/src/llvm/parser.c +++ b/src/llvm/parser.c @@ -207,6 +207,9 @@ static BackendError build_module(LLVMBackendCompileUnit* unit, } err = impl_functions(unit, global_scope, module->functions); + if (err.kind != Success) { + return err; + } char* error = NULL; if (LLVMVerifyModule(unit->module, LLVMAbortProcessAction, &error)) { diff --git a/src/set/set.c b/src/set/set.c index 4ef19a1..07ffd54 100644 --- a/src/set/set.c +++ b/src/set/set.c @@ -1292,7 +1292,8 @@ int createDeref(Expression *ParentExpression, AST_NODE_PTR currentNode) { assert(currentNode->child_count == 2); Dereference deref; deref.nodePtr = currentNode; - deref.index = createExpression(AST_get_node(currentNode, 0)); + AST_NODE_PTR expression_node = AST_get_node(currentNode, 1); + deref.index = createExpression(expression_node); //index has to be made if (deref.index == NULL) { @@ -1323,11 +1324,11 @@ int createDeref(Expression *ParentExpression, AST_NODE_PTR currentNode) { } } - deref.variable = createExpression(AST_get_node(currentNode, 1)); + deref.variable = createExpression(AST_get_node(currentNode, 0)); //variable has to be made if (deref.index == NULL) { - print_diagnostic(current_file, &AST_get_node(currentNode, 1)->location, Error, "Invalid index"); + print_diagnostic(current_file, &AST_get_node(currentNode, 0)->location, Error, "Invalid index"); return SEMANTIC_ERROR; } diff --git a/src/set/set.h b/src/set/set.h index e321fd4..21c3f1c 100644 --- a/src/set/set.h +++ b/src/set/set.h @@ -7,8 +7,13 @@ #define SEMANTIC_OK 0 #define SEMANTIC_ERROR 1 +// type of string literal +extern const Type StringLiteralType; + Module * create_set(AST_NODE_PTR rootNodePtr ); void delete_set(Module* module); +bool compareTypes(Type *leftType, Type *rightType); + #endif