From 28a0dec343bf4c932bb05cc2eb3aa35a797b1a06 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Mon, 19 Jul 2021 17:10:13 +0200 Subject: [PATCH] Fixes: Extname works on global variables. Bug with boolean in ternary in some cases. Global declarations would not parse attributes. --- src/compiler/llvm_codegen.c | 12 +++- src/compiler/llvm_codegen_expr.c | 4 +- src/compiler/parse_global.c | 71 ++++++++++++---------- test/test_suite/globals/global_extname.c3t | 7 +++ 4 files changed, 59 insertions(+), 35 deletions(-) create mode 100644 test/test_suite/globals/global_extname.c3t diff --git a/src/compiler/llvm_codegen.c b/src/compiler/llvm_codegen.c index 25aeab7c8..01341e79c 100644 --- a/src/compiler/llvm_codegen.c +++ b/src/compiler/llvm_codegen.c @@ -361,7 +361,7 @@ void llvm_emit_global_variable_init(GenContext *c, Decl *decl) // TODO fix name LLVMValueRef old = decl->backend_ref; - decl->backend_ref = LLVMAddGlobal(c->module, LLVMTypeOf(init_value), decl->external_name); + decl->backend_ref = LLVMAddGlobal(c->module, LLVMTypeOf(init_value), decl->extname ?: decl->external_name); llvm_set_alignment(decl->backend_ref, alignment); LLVMValueRef failable_ref = decl->var.failable_ref; @@ -833,7 +833,15 @@ void llvm_value_addr(GenContext *c, BEValue *value) void llvm_value_rvalue(GenContext *c, BEValue *value) { - if (value->kind != BE_ADDRESS && value->kind != BE_ADDRESS_FAILABLE) return; + if (value->kind != BE_ADDRESS && value->kind != BE_ADDRESS_FAILABLE) + { + if (value->type->type_kind == TYPE_BOOL && value->kind != BE_BOOLEAN) + { + value->value = LLVMBuildTrunc(c->builder, value->value, c->bool_type, ""); + value->kind = BE_BOOLEAN; + } + return; + } llvm_value_fold_failable(c, value); value->value = llvm_emit_load_aligned(c, llvm_get_type(c, value->type), diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 058570fe9..15ddf666e 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -2765,7 +2765,7 @@ void llvm_emit_call_expr(GenContext *c, BEValue *be_value, Expr *expr) // 12. Basically void returns or empty structs. // Here we know we don't have a failable or any return value that can be used. assert(!signature->failable && "Failable should have produced a return value."); - *be_value = (BEValue) {}; + *be_value = (BEValue) { .type = type_void, .kind = BE_VALUE }; return; case ABI_ARG_INDIRECT: @@ -2910,7 +2910,7 @@ void llvm_emit_call_expr(GenContext *c, BEValue *be_value, Expr *expr) // 17g. If void, be_value contents should be skipped. if (!signature->ret_abi_info) { - *be_value = (BEValue) {}; + *be_value = (BEValue) { .type = type_void, .kind = BE_VALUE }; return; } diff --git a/src/compiler/parse_global.c b/src/compiler/parse_global.c index fd753ed78..82b0908b2 100644 --- a/src/compiler/parse_global.c +++ b/src/compiler/parse_global.c @@ -837,37 +837,6 @@ static inline bool is_function_start(Context *context) return tok == TOKEN_LPAREN; } -/** - * global_declaration - * : failable_type IDENT ';' - * | failable_type IDENT '=' expression ';' - * | failable_type func_definition - * ; - * - * @param visibility - * @return true if parsing succeeded - */ -static inline Decl *parse_global_declaration(Context *context, Visibility visibility) -{ - TypeInfo *type = TRY_TYPE_OR(parse_type(context), poisoned_decl); - - Decl *decl = decl_new_var(context->tok.id, type, VARDECL_GLOBAL, visibility); - - - if (TOKEN_IS(TOKEN_CONST_IDENT)) - { - SEMA_TOKEN_ERROR(context->tok, "This looks like a constant variable, did you forget 'const'?"); - return poisoned_decl; - } - if (!consume_ident(context, "global variable")) return poisoned_decl; - - if (try_consume(context, TOKEN_EQ)) - { - decl->var.init_expr = TRY_EXPR_OR(parse_initializer(context), poisoned_decl); - } - TRY_CONSUME_EOS_OR(poisoned_decl); - return decl; -} static inline Decl *parse_incremental_array(Context *context) { @@ -1028,6 +997,46 @@ static inline bool parse_attributes(Context *context, Decl *parent_decl) } +/** + * global_declaration + * : failable_type IDENT ';' + * | failable_type IDENT '=' expression ';' + * | failable_type func_definition + * ; + * + * @param visibility + * @return true if parsing succeeded + */ +static inline Decl *parse_global_declaration(Context *context, Visibility visibility) +{ + TypeInfo *type = TRY_TYPE_OR(parse_type(context), poisoned_decl); + + Decl *decl = decl_new_var(context->tok.id, type, VARDECL_GLOBAL, visibility); + + if (TOKEN_IS(TOKEN_CONST_IDENT)) + { + SEMA_TOKEN_ERROR(context->tok, "This looks like a constant variable, did you forget 'const'?"); + return poisoned_decl; + } + + if (!try_consume(context, TOKEN_IDENT)) + { + if (token_is_some_ident(context->tok.type)) + { + SEMA_TOKEN_ERROR(context->tok, "I expected a variable name here, but global variables need to start with lower case."); + return poisoned_decl; + } + CONSUME_OR(TOKEN_IDENT, poisoned_decl); + } + + if (!parse_attributes(context, decl)) return poisoned_decl; + if (try_consume(context, TOKEN_EQ)) + { + decl->var.init_expr = TRY_EXPR_OR(parse_initializer(context), poisoned_decl); + } + TRY_CONSUME_EOS_OR(poisoned_decl); + return decl; +} diff --git a/test/test_suite/globals/global_extname.c3t b/test/test_suite/globals/global_extname.c3t new file mode 100644 index 000000000..26f486e22 --- /dev/null +++ b/test/test_suite/globals/global_extname.c3t @@ -0,0 +1,7 @@ +module foo; + +int baz @extname("foobar") = 123; + +// #expect: foo.ll + +@foobar = global i32 123, align 4 \ No newline at end of file