diff --git a/src/compiler/ast.c b/src/compiler/ast.c index ead9d2e48..743c449db 100644 --- a/src/compiler/ast.c +++ b/src/compiler/ast.c @@ -483,3 +483,41 @@ bool ast_supports_continue(Ast *stmt) if (stmt->ast_kind != AST_FOR_STMT) return false; return stmt->for_stmt.cond || !stmt->flow.skip_first; } + +void scratch_buffer_set_extern_decl_name(Decl *decl, bool clear) +{ + if (clear) scratch_buffer_clear(); + if (decl->extname) + { + scratch_buffer_append(decl->extname); + return; + } + if (decl->is_extern) + { + scratch_buffer_append(decl->name); + return; + } + if (decl->decl_kind == DECL_FUNC && decl->func_decl.type_parent) + { + Type *parent = type_infoptr(decl->func_decl.type_parent)->type->canonical; + if (type_is_user_defined(parent)) + { + Decl *parent_decl = parent->decl; + if (parent_decl->unit && parent_decl->unit->module) scratch_buffer_append_module(parent_decl->unit->module, decl->is_export); + scratch_buffer_append(decl->is_export ? "__" : "."); + scratch_buffer_append(parent->name); + scratch_buffer_append(decl->is_export ? "__" : "."); + scratch_buffer_append(decl->name); + return; + } + if (decl->unit && decl->unit->module) scratch_buffer_append_module(decl->unit->module, decl->is_export); + scratch_buffer_append(decl->is_export ? "__" : "."); + scratch_buffer_append(parent->name); + scratch_buffer_append(decl->is_export ? "__" : "."); + scratch_buffer_append(decl->name); + return; + } + if (decl->unit && decl->unit->module) scratch_buffer_append_module(decl->unit->module, decl->is_export); + scratch_buffer_append(decl->is_export ? "__" : "."); + scratch_buffer_append(decl->name); +} diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 644892ade..7b05631b4 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -2230,6 +2230,7 @@ bool decl_needs_prefix(Decl *decl); AlignSize decl_find_member_offset(Decl *decl, Decl *member); bool decl_is_externally_visible(Decl *decl); bool decl_is_local(Decl *decl); +void scratch_buffer_set_extern_decl_name(Decl *decl, bool clear); // --- Expression functions @@ -2300,7 +2301,7 @@ bool lexer_next_token(Lexer *lexer); // --- Module functions -void module_copy_extern_name_to_buffer(Module *module); +void scratch_buffer_append_module(Module *module, bool is_export); Decl *module_find_symbol(Module *module, const char *symbol); const char *module_create_object_file_name(Module *module); @@ -3572,10 +3573,6 @@ INLINE Ast *ast_next(AstId *current_ptr) } -INLINE const char *decl_get_extname(Decl *decl) -{ - return decl->extname; -} INLINE void expr_rewrite_const_bool(Expr *expr, Type *type, bool b) diff --git a/src/compiler/context.c b/src/compiler/context.c index a80ff9ecf..293e32aa6 100644 --- a/src/compiler/context.c +++ b/src/compiler/context.c @@ -108,7 +108,7 @@ bool context_set_module(ParseContext *context, Path *path, const char **generic_ void unit_register_external_symbol(CompilationUnit *unit, Decl *decl) { - if (decl_module(decl) == unit->module || !decl->extname) return; + if (decl_module(decl) == unit->module) return; decl->is_external_visible = true; } @@ -174,7 +174,6 @@ void unit_register_global_decl(CompilationUnit *unit, Decl *decl) { vec_add(unit->macros, decl); } - decl_set_external_name(decl); decl_register(decl); break; case DECL_FUNC: @@ -193,7 +192,6 @@ void unit_register_global_decl(CompilationUnit *unit, Decl *decl) case DECL_VAR: assert(decl->name); vec_add(unit->vars, decl); - decl_set_external_name(decl); decl_register(decl); break; case DECL_INTERFACE: @@ -205,19 +203,16 @@ void unit_register_global_decl(CompilationUnit *unit, Decl *decl) case DECL_BITSTRUCT: assert(decl->name); vec_add(unit->types, decl); - decl_set_external_name(decl); decl_register(decl); break; case DECL_DEFINE: assert(decl->name); vec_add(unit->generic_defines, decl); - decl_set_external_name(decl); decl_register(decl); break; case DECL_ENUM: assert(decl->name); vec_add(unit->enums, decl); - decl_set_external_name(decl); decl_register(decl); break; case DECL_ATTRIBUTE: diff --git a/src/compiler/headers.c b/src/compiler/headers.c index b343197f5..cda45595c 100644 --- a/src/compiler/headers.c +++ b/src/compiler/headers.c @@ -11,6 +11,11 @@ static void header_gen_struct_union(FILE *file, int indent, Decl *decl); static void header_gen_maybe_generate_type(FILE *file, HTable *table, Type *type); +INLINE const char *decl_get_extname(Decl *decl) +{ + return decl->extname; +} + static bool type_is_func_pointer(Type *type) { if (type->type_kind != TYPE_DISTINCT && type->type_kind != TYPE_TYPEDEF) return false; diff --git a/src/compiler/llvm_codegen.c b/src/compiler/llvm_codegen.c index b97420024..d6c7b5d22 100644 --- a/src/compiler/llvm_codegen.c +++ b/src/compiler/llvm_codegen.c @@ -518,10 +518,29 @@ void llvm_emit_global_variable_init(GenContext *c, Decl *decl) LLVMValueRef old = decl->backend_ref; - LLVMValueRef global_ref = decl->backend_ref = llvm_add_global_raw(c, - decl_get_extname(decl), - LLVMTypeOf(init_value), - decl->alignment); + scratch_buffer_set_extern_decl_name(decl, true); + char *name = scratch_buffer_copy(); + LLVMValueRef global_ref = decl->backend_ref = llvm_add_global_raw(c, name, LLVMTypeOf(init_value), decl->alignment); + if (llvm_use_debug(c)) + { + SourceSpan loc = decl->span; + decl->var.backend_debug_ref = LLVMDIBuilderCreateGlobalVariableExpression( + c->debug.builder, + c->debug.file.debug_file, + decl->name, + strlen(decl->name), + name, + strlen(name), + c->debug.file.debug_file, + loc.row ? loc.row : 1, + llvm_get_debug_type(c, decl->type), + decl_is_local(decl), + LLVMDIBuilderCreateExpression(c->debug.builder, NULL, 0), + NULL, + decl->alignment); + LLVMGlobalSetMetadata(llvm_get_ref(c, decl), 0, decl->var.backend_debug_ref); + } + if (decl->var.is_addr) { LLVMSetUnnamedAddress(global_ref, LLVMNoUnnamedAddr); @@ -586,11 +605,6 @@ void llvm_emit_global_variable_init(GenContext *c, Decl *decl) LLVMDeleteGlobal(old); } - // Should we set linkage here? - if (llvm_use_debug(c)) - { - llvm_emit_debug_global_var(c, decl); - } } static void gencontext_verify_ir(GenContext *context) { @@ -1012,13 +1026,23 @@ const char *llvm_codegen(void *context) return object_name; } + void llvm_add_global_decl(GenContext *c, Decl *decl) { assert(decl->var.kind == VARDECL_GLOBAL || decl->var.kind == VARDECL_CONST); bool same_module = decl_module(decl) == c->code_module; - const char *name = same_module ? "temp_global" : decl_get_extname(decl); - decl->backend_ref = llvm_add_global(c, name, decl->type, decl->alignment); + LLVMTypeRef type = llvm_get_type(c, decl->type); + if (same_module) + { + // If we initialize it later, we must use a temp name. + decl->backend_ref = llvm_add_global_raw(c, ".tempglobal", type, decl->alignment); + } + else + { + scratch_buffer_set_extern_decl_name(decl, true); + decl->backend_ref = llvm_add_global_raw(c, scratch_buffer_to_string(), type, decl->alignment); + } if (!same_module) { LLVMSetLinkage(decl->backend_ref, LLVMExternalLinkage); @@ -1029,10 +1053,10 @@ void llvm_add_global_decl(GenContext *c, Decl *decl) } if (IS_OPTIONAL(decl)) { - scratch_buffer_clear(); - scratch_buffer_append(decl_get_extname(decl)); + LLVMTypeRef anyfault = llvm_get_type(c, type_anyfault); + scratch_buffer_set_extern_decl_name(decl, true); scratch_buffer_append(".f"); - decl->var.optional_ref = llvm_add_global(c, scratch_buffer_to_string(), type_anyfault, 0); + decl->var.optional_ref = llvm_add_global_raw(c, scratch_buffer_to_string(), anyfault, 0); } llvm_set_global_tls(decl); } @@ -1136,12 +1160,14 @@ void llvm_append_function_attributes(GenContext *c, Decl *decl) { if (c->code_module == decl_module(decl)) { - llvm_attribute_add_string(c, function, "wasm-export-name", decl_get_extname(decl), -1); + scratch_buffer_set_extern_decl_name(decl, true); + llvm_attribute_add_string(c, function, "wasm-export-name", scratch_buffer_to_string(), -1); } } if (decl->is_extern && arch_is_wasm(platform_target.arch)) { - llvm_attribute_add_string(c, function, "wasm-import-name", decl_get_extname(decl), -1); + scratch_buffer_set_extern_decl_name(decl, true); + llvm_attribute_add_string(c, function, "wasm-import-name", scratch_buffer_to_string(), -1); } if (decl->alignment != type_abi_alignment(decl->type)) { @@ -1186,7 +1212,9 @@ LLVMValueRef llvm_get_ref(GenContext *c, Decl *decl) { return decl->backend_ref = llvm_get_selector(c, decl->name); } - backend_ref = decl->backend_ref = LLVMAddFunction(c->module, decl_get_extname(decl), llvm_get_type(c, decl->type)); + LLVMTypeRef type = llvm_get_type(c, decl->type); + scratch_buffer_set_extern_decl_name(decl, true); + backend_ref = decl->backend_ref = LLVMAddFunction(c->module, scratch_buffer_to_string(), type); llvm_append_function_attributes(c, decl); if (decl->is_export && platform_target.os == OS_TYPE_WIN32 && !active_target.win.def && decl->name != kw_main && decl->name != kw_mainstub) { @@ -1246,7 +1274,8 @@ static void llvm_gen_test_main(GenContext *c) LLVMTypeRef main_type = LLVMFunctionType(cint, NULL, 0, true); LLVMTypeRef runner_type = LLVMFunctionType(c->byte_type, NULL, 0, true); LLVMValueRef func = LLVMAddFunction(c->module, kw_main, main_type); - LLVMValueRef other_func = LLVMAddFunction(c->module, test_runner->extname, runner_type); + scratch_buffer_set_extern_decl_name(test_runner, true); + LLVMValueRef other_func = LLVMAddFunction(c->module, scratch_buffer_to_string(), runner_type); LLVMBuilderRef builder = llvm_create_function_entry(c, func, NULL); LLVMValueRef val = LLVMBuildCall2(builder, runner_type, other_func, NULL, 0, ""); val = LLVMBuildSelect(builder, LLVMBuildTrunc(builder, val, c->bool_type, ""), @@ -1275,7 +1304,8 @@ INLINE GenContext *llvm_gen_tests(Module** modules, unsigned module_count, LLVMC FOREACH_BEGIN(Decl *test, module->tests) LLVMValueRef ref; LLVMTypeRef type = opt_test; - ref = LLVMAddFunction(c->module, test->extname, type); + scratch_buffer_set_extern_decl_name(test, true); + ref = LLVMAddFunction(c->module, scratch_buffer_to_string(), type); scratch_buffer_clear(); scratch_buffer_printf("%s::%s", module->name->module, test->name); LLVMValueRef name = llvm_emit_string_const(c, scratch_buffer_to_string(), ".test.name"); @@ -1342,7 +1372,8 @@ static void llvm_gen_benchmark_main(GenContext *c) LLVMTypeRef main_type = LLVMFunctionType(cint, NULL, 0, true); LLVMTypeRef runner_type = LLVMFunctionType(c->byte_type, NULL, 0, true); LLVMValueRef func = LLVMAddFunction(c->module, kw_main, main_type); - LLVMValueRef other_func = LLVMAddFunction(c->module, benchmark_runner->extname, runner_type); + scratch_buffer_set_extern_decl_name(benchmark_runner, true); + LLVMValueRef other_func = LLVMAddFunction(c->module, scratch_buffer_to_string(), runner_type); LLVMBuilderRef builder = llvm_create_function_entry(c, func, NULL); LLVMValueRef val = LLVMBuildCall2(builder, runner_type, other_func, NULL, 0, ""); val = LLVMBuildSelect(builder, LLVMBuildTrunc(builder, val, c->bool_type, ""), @@ -1371,7 +1402,8 @@ INLINE GenContext *llvm_gen_benchmarks(Module** modules, unsigned module_count, FOREACH_BEGIN(Decl *benchmark, module->benchmarks) LLVMValueRef ref; LLVMTypeRef type = opt_benchmark; - ref = LLVMAddFunction(c->module, benchmark->extname, type); + scratch_buffer_set_extern_decl_name(benchmark, true); + ref = LLVMAddFunction(c->module, scratch_buffer_to_string(), type); scratch_buffer_clear(); scratch_buffer_printf("%s::%s", module->name->module, benchmark->name); LLVMValueRef name = llvm_emit_string_const(c, scratch_buffer_to_string(), ".benchmark.name"); diff --git a/src/compiler/llvm_codegen_debug_info.c b/src/compiler/llvm_codegen_debug_info.c index 3df198c8f..f9c9c3c8a 100644 --- a/src/compiler/llvm_codegen_debug_info.c +++ b/src/compiler/llvm_codegen_debug_info.c @@ -40,7 +40,7 @@ static inline LLVMMetadataRef llvm_get_debug_struct(GenContext *c, Type *type, c } LLVMMetadataRef real = LLVMDIBuilderCreateStructType(c->debug.builder, scope, - external_name_len ? type->name : "", external_name_len ? strlen(type->name) : 0, + type->name ? type->name : "", type->name ? strlen(type->name) : 0, file, row, type_size(type) * 8, @@ -80,26 +80,6 @@ LLVMMetadataRef llvm_debug_current_scope(GenContext *context) return context->debug.compile_unit; } -void llvm_emit_debug_global_var(GenContext *c, Decl *global) -{ - SourceSpan loc = global->span; - global->var.backend_debug_ref = LLVMDIBuilderCreateGlobalVariableExpression( - c->debug.builder, - c->debug.file.debug_file, - global->name, - strlen(global->name), - global->extname, - strlen(global->extname), - c->debug.file.debug_file, - loc.row ? loc.row : 1, - llvm_get_debug_type(c, global->type), - decl_is_local(global), - LLVMDIBuilderCreateExpression(c->debug.builder, NULL, 0), - NULL, - global->alignment); - LLVMGlobalSetMetadata(llvm_get_ref(c, global), 0, global->var.backend_debug_ref); -} - void llvm_emit_debug_function(GenContext *c, Decl *decl) { if (!decl->func_decl.body) return; @@ -110,13 +90,13 @@ void llvm_emit_debug_function(GenContext *c, Decl *decl) uint32_t row = decl->span.row; if (!row) row = 1; assert(decl->name); - assert(decl->extname); assert(c->debug.file.debug_file); LLVMMetadataRef debug_type = llvm_get_debug_type(c, decl->type); + scratch_buffer_set_extern_decl_name(decl, true); c->debug.function = LLVMDIBuilderCreateFunction(c->debug.builder, c->debug.file.debug_file, decl->name, strlen(decl->name), - decl->extname, strlen(decl->extname), + scratch_buffer_to_string(), scratch_buffer.len, c->debug.file.debug_file, row, debug_type, @@ -264,8 +244,8 @@ static LLVMMetadataRef llvm_debug_forward_comp(GenContext *c, Type *type, const type_size(type) * 8, type_abi_alignment(type) * 8, flags, - external_name, - strlen(external_name)); + "temp", + 4); } @@ -348,7 +328,7 @@ static LLVMMetadataRef llvm_debug_enum_type(GenContext *c, Type *type, LLVMMetad { Decl *decl = type->decl; - LLVMMetadataRef forward = llvm_debug_forward_comp(c, type, decl->extname, &decl->span, scope, LLVMDIFlagZero); + LLVMMetadataRef forward = llvm_debug_forward_comp(c, type, "temp_enum", &decl->span, scope, LLVMDIFlagZero); type->backend_debug_type = forward; Type *enum_real_type = decl->enums.type_info->type->canonical; @@ -389,7 +369,7 @@ static LLVMMetadataRef llvm_debug_structlike_type(GenContext *c, Type *type, LLV LLVMDIFlags flags = 0; // Create a forward reference in case of recursive data. - LLVMMetadataRef forward = llvm_debug_forward_comp(c, type, decl->extname, &decl->span, scope, flags); + LLVMMetadataRef forward = llvm_debug_forward_comp(c, type, "temp", &decl->span, scope, flags); type->backend_debug_type = forward; LLVMMetadataRef *elements = NULL; @@ -408,24 +388,33 @@ static LLVMMetadataRef llvm_debug_structlike_type(GenContext *c, Type *type, LLV } LLVMMetadataRef real; + + const char *extname = ""; + unsigned extname_len = 0; + if (decl->name) + { + scratch_buffer_set_extern_decl_name(decl, true); + extname = scratch_buffer_to_string(); + extname_len = scratch_buffer.len; + } if (type->type_kind == TYPE_UNION) { unsigned row = decl->span.row; real = LLVMDIBuilderCreateUnionType(c->debug.builder, scope, - type->decl->name ? type->decl->name : "", - type->decl->name ? strlen(type->decl->name) : 0, + decl->name ? decl->name : "", + decl->name ? strlen(decl->name) : 0, c->debug.file.debug_file, row ? row : 1, type_size(type) * 8, type_abi_alignment(type) * 8, LLVMDIFlagZero, elements, vec_size(members), c->debug.runtime_version, - type->decl->name ? decl->extname : "", - type->decl->name ? strlen(decl->extname) : 0); + extname, + extname_len); LLVMMetadataReplaceAllUsesWith(forward, real); return real; } - return llvm_get_debug_struct(c, type, decl->name ? decl->extname : "", elements, vec_size(elements), &decl->span, scope, LLVMDIFlagZero); + return llvm_get_debug_struct(c, type, extname, elements, vec_size(elements), &decl->span, scope, LLVMDIFlagZero); } static LLVMMetadataRef llvm_debug_slice_type(GenContext *c, Type *type) diff --git a/src/compiler/llvm_codegen_function.c b/src/compiler/llvm_codegen_function.c index 631d33b7b..0a30c74de 100644 --- a/src/compiler/llvm_codegen_function.c +++ b/src/compiler/llvm_codegen_function.c @@ -404,7 +404,7 @@ void llvm_emit_return_implicit(GenContext *c) void llvm_emit_function_body(GenContext *c, Decl *decl) { - DEBUG_LOG("Generating function %s.", decl->extname); + DEBUG_LOG("Generating function %s.", decl->name); if (decl->func_decl.attr_dynamic) vec_add(c->dynamic_functions, decl); assert(decl->backend_ref); if (decl->func_decl.attr_init || decl->func_decl.attr_finalizer) @@ -577,8 +577,8 @@ void llvm_emit_dynamic_functions(GenContext *c, Decl **funcs) Type *type = typeget(decl->func_decl.type_parent); scratch_buffer_clear(); scratch_buffer_append("$ct.dyn."); - scratch_buffer_append(decl_get_extname(decl)); - LLVMValueRef global = llvm_add_global_raw(c, scratch_buffer_to_string(), c->dtable_type, 0); + scratch_buffer_set_extern_decl_name(decl, false); + LLVMValueRef global = llvm_add_global_raw(c, scratch_buffer_copy(), c->dtable_type, 0); Decl *proto = declptrzero(decl->func_decl.interface_method); LLVMValueRef proto_ref = proto ? llvm_get_ref(c, proto) : llvm_get_selector(c, decl->name); LLVMValueRef vals[3] = { llvm_get_ref(c, decl), proto_ref, LLVMConstNull(c->ptr_type) }; diff --git a/src/compiler/llvm_codegen_internal.h b/src/compiler/llvm_codegen_internal.h index 6dd107b94..dbc67e5b2 100644 --- a/src/compiler/llvm_codegen_internal.h +++ b/src/compiler/llvm_codegen_internal.h @@ -560,7 +560,6 @@ void llvm_emit_debug_location(GenContext *c, SourceSpan location); LLVMMetadataRef llvm_create_debug_location(GenContext *c, SourceSpan location); void llvm_emit_debug_parameter(GenContext *c, Decl *parameter, unsigned index); void llvm_emit_debug_local_var(GenContext *c, Decl *var); -void llvm_emit_debug_global_var(GenContext *c, Decl *global); #define FRAMEPOINTER (platform_target.arch == ARCH_TYPE_AARCH64 ? 1 : 2) #define UWTABLE (active_target.arch_os_target == MACOS_AARCH64 ? 1 : 2) diff --git a/src/compiler/llvm_codegen_stmt.c b/src/compiler/llvm_codegen_stmt.c index 97c2ac350..e6dd3398c 100644 --- a/src/compiler/llvm_codegen_stmt.c +++ b/src/compiler/llvm_codegen_stmt.c @@ -43,13 +43,15 @@ void llvm_emit_local_static(GenContext *c, Decl *decl, BEValue *value) c->builder = c->global_builder; // Emit the global. - decl->backend_ref = llvm_add_global(c, "temp", type_lowering(decl->type), decl->alignment); + decl->backend_ref = llvm_add_global(c, "temp", decl->type, decl->alignment); if (IS_OPTIONAL(decl)) { - scratch_buffer_clear(); - scratch_buffer_append(decl_get_extname(decl)); + LLVMTypeRef anyfault = llvm_get_type(c, type_anyfault); + scratch_buffer_append(c->cur_func.name); + scratch_buffer_append_char('.'); + scratch_buffer_append(decl->name); scratch_buffer_append(".f"); - decl->var.optional_ref = llvm_add_global(c, scratch_buffer_to_string(), type_anyfault, 0); + decl->var.optional_ref = llvm_add_global_raw(c, scratch_buffer_to_string(), anyfault, 0); } llvm_emit_global_variable_init(c, decl); diff --git a/src/compiler/llvm_codegen_type.c b/src/compiler/llvm_codegen_type.c index 99b823a60..e7827b0e3 100644 --- a/src/compiler/llvm_codegen_type.c +++ b/src/compiler/llvm_codegen_type.c @@ -555,8 +555,7 @@ static LLVMValueRef llvm_get_introspection_for_enum(GenContext *c, Type *type) Decl *associated_value = associated_values[ai]; LLVMValueRef associated_value_arr = mixed ? llvm_get_packed_struct(c, values, elements) : llvm_get_array(val_type, values, elements); - scratch_buffer_clear(); - scratch_buffer_append(decl->extname); + scratch_buffer_set_extern_decl_name(decl, true); scratch_buffer_append("$"); scratch_buffer_append(associated_value->name); LLVMValueRef global_ref = llvm_add_global_raw(c, @@ -598,8 +597,7 @@ static LLVMValueRef llvm_get_introspection_for_fault(GenContext *c, Type *type) LLVMValueRef ref = llvm_generate_temp_introspection_global(c, type); for (unsigned i = 0; i < elements; i++) { - scratch_buffer_clear(); - scratch_buffer_append(decl_get_extname(decl)); + scratch_buffer_set_extern_decl_name(decl, true); scratch_buffer_append_char('$'); Decl *val = fault_vals[i]; scratch_buffer_append(val->name); diff --git a/src/compiler/module.c b/src/compiler/module.c index 502271b3a..9d3339b0a 100644 --- a/src/compiler/module.c +++ b/src/compiler/module.c @@ -9,7 +9,7 @@ Decl *module_find_symbol(Module *module, const char *symbol) return htable_get(&module->symbols, (void*)symbol); } -void module_copy_extern_name_to_buffer(Module *module) +void scratch_buffer_append_module(Module *module, bool is_export) { if (module->extname) { @@ -24,7 +24,7 @@ void module_copy_extern_name_to_buffer(Module *module) { case ':': assert(name[0] == ':'); - scratch_buffer_append_char('_'); + scratch_buffer_append_char(is_export ? '_' : '.'); name++; break; default: diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 0be99c464..155262d9f 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -846,13 +846,6 @@ static bool sema_analyse_interface(SemaContext *context, Decl *decl, bool *erase return false; } } - if (!method->extname) - { - scratch_buffer_clear(); - type_mangle_introspect_name_to_buffer(decl->type); - scratch_buffer_printf(".%s", name); - method->extname = scratch_buffer_copy(); - } } return true; } @@ -1231,7 +1224,6 @@ static inline bool sema_analyse_typedef(SemaContext *context, Decl *decl, bool * if (*erase_decl) return true; bool is_export = decl->is_export; - if (is_export) decl_set_external_name(decl); if (decl->typedef_decl.is_func) { Decl *fn_decl = decl->typedef_decl.decl; @@ -1610,39 +1602,6 @@ static bool sema_check_operator_method_validity(SemaContext *context, Decl *meth UNREACHABLE } -INLINE void sema_set_method_ext_name(CompilationUnit *unit, const char *parent_name, Decl *method_like) -{ - if (method_like->has_extname) return; - scratch_buffer_clear(); - if (method_like->is_export) - { - scratch_buffer_append(parent_name); - scratch_buffer_append("_"); - scratch_buffer_append(method_like->name); - method_like->extname = scratch_buffer_copy(); - return; - } - switch (method_like->visibility) - { - case VISIBLE_PUBLIC: - case VISIBLE_PRIVATE: - scratch_buffer_append(parent_name); - scratch_buffer_append_char('.'); - scratch_buffer_append(method_like->name); - break; - case VISIBLE_LOCAL: - scratch_buffer_append(unit->file->name); - scratch_buffer_append_char('.'); - scratch_buffer_append(parent_name); - scratch_buffer_append_char('.'); - scratch_buffer_append(method_like->name); - break; - default: - UNREACHABLE - } - method_like->extname = scratch_buffer_copy(); -} - bool sema_decl_if_cond(SemaContext *context, Decl *decl) { Attr *attr = attr_find_kind(decl->attributes, ATTRIBUTE_IF); @@ -1686,9 +1645,6 @@ unit_add_base_extension_method(SemaContext *context, CompilationUnit *unit, Type "Only user-defined types support operator oveloading."); } - // As with normal methods, update the name. - sema_set_method_ext_name(unit, parent_type->name, method); - // Add it to the right list of extensions. switch (method->visibility) { @@ -1890,8 +1846,6 @@ static inline bool unit_add_method(SemaContext *context, Type *parent_type, Decl if (!sema_analyse_operator_method(context, parent_type, method)) return false; } - // Set the external name - sema_set_method_ext_name(unit, parent->extname, method); DEBUG_LOG("Method-like '%s.%s' analysed.", parent->name, method->name); // Add it to the correct place: type methods, private extensions, local method extensions @@ -3145,7 +3099,6 @@ static inline bool sema_analyse_func(SemaContext *context, Decl *decl, bool *era } if (!sema_analyse_main_function(context, decl)) return false; } - decl_set_external_name(decl); } // Do we have fn void any.foo(void*) { ... }? @@ -3464,6 +3417,7 @@ bool sema_analyse_var_decl(SemaContext *context, Decl *decl, bool local) case VARDECL_GLOBAL: is_global = true; break; + case VARDECL_CONST: default: break; } @@ -3499,14 +3453,6 @@ bool sema_analyse_var_decl(SemaContext *context, Decl *decl, bool local) bool is_static = decl->var.is_static; bool global_level_var = is_static || decl->var.kind == VARDECL_CONST || is_global; - if (global_level_var && !decl->has_extname) - { - scratch_buffer_clear(); - scratch_buffer_append(context->call_env.kind == CALL_ENV_FUNCTION ? context->call_env.current_function->name : ".global"); - scratch_buffer_append_char('.'); - scratch_buffer_append(decl->name); - decl->extname = scratch_buffer_copy(); - } if (decl->is_extern && decl->var.init_expr) { assert(is_global); @@ -3650,6 +3596,15 @@ bool sema_analyse_var_decl(SemaContext *context, Decl *decl, bool local) } } EXIT_OK:; + // Patch the external name for local consts and static variables. + if ((decl->var.kind == VARDECL_CONST || is_static) && !decl->extname && context->call_env.kind == CALL_ENV_FUNCTION) + { + scratch_buffer_clear(); + scratch_buffer_append(context->call_env.current_function->name); + scratch_buffer_append_char('.'); + scratch_buffer_append(decl->name); + decl->extname = scratch_buffer_copy(); + } if (!decl->alignment) { if (!sema_set_alloca_alignment(context, decl->type, &decl->alignment)) return false; @@ -4109,23 +4064,19 @@ bool sema_analyse_decl(SemaContext *context, Decl *decl) decl->resolve_status = RESOLVE_RUNNING; assert(decl->unit); bool erase_decl = false; - bool set_external_name = false; switch (decl->decl_kind) { case DECL_ERASED: break; case DECL_INTERFACE: if (!sema_analyse_interface(context, decl, &erase_decl)) goto FAILED; - set_external_name = true; break; case DECL_BITSTRUCT: if (!sema_analyse_bitstruct(context, decl, &erase_decl)) goto FAILED; - set_external_name = true; break; case DECL_STRUCT: case DECL_UNION: if (!sema_analyse_struct_union(context, decl, &erase_decl)) goto FAILED; - set_external_name = true; break; case DECL_FNTYPE: if (!sema_analyse_fntype(context, decl, &erase_decl)) goto FAILED; @@ -4138,25 +4089,21 @@ bool sema_analyse_decl(SemaContext *context, Decl *decl) break; case DECL_VAR: if (!sema_analyse_var_decl(context, decl, false)) goto FAILED; - set_external_name = true; break; case DECL_ATTRIBUTE: if (!sema_analyse_attribute_decl(context, context, decl, &erase_decl)) goto FAILED; break; case DECL_DISTINCT: if (!sema_analyse_distinct(context, decl, &erase_decl)) goto FAILED; - set_external_name = true; break; case DECL_TYPEDEF: if (!sema_analyse_typedef(context, decl, &erase_decl)) goto FAILED; break; case DECL_ENUM: if (!sema_analyse_enum(context, decl, &erase_decl)) goto FAILED; - set_external_name = true; break; case DECL_FAULT: if (!sema_analyse_error(context, decl, &erase_decl)) goto FAILED; - set_external_name = true; break; case DECL_DEFINE: if (!sema_analyse_define(context, decl, &erase_decl)) goto FAILED; @@ -4178,9 +4125,7 @@ bool sema_analyse_decl(SemaContext *context, Decl *decl) if (erase_decl) { decl->decl_kind = DECL_ERASED; - set_external_name = false; } - if (set_external_name) decl_set_external_name(decl); decl->resolve_status = RESOLVE_DONE; sema_context_destroy(&temp_context); diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index b277bf6cf..ee06b8d98 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -7372,7 +7372,15 @@ static inline void sema_expr_rewrite_to_type_nameof(Expr *expr, Type *type, Toke if (type_is_func_ptr(type)) type = type->pointer->function.prototype->raw_type; if (name_type == TOKEN_CT_EXTNAMEOF) { - expr_rewrite_to_string(expr, type->decl->extname); + if (type_is_user_defined(type)) + { + scratch_buffer_set_extern_decl_name(type->decl, true); + expr_rewrite_to_string(expr, scratch_buffer_copy()); + } + else + { + expr_rewrite_to_string(expr, type->name); + } return; } @@ -7409,12 +7417,64 @@ static inline bool sema_expr_analyse_ct_nameof(SemaContext *context, Expr *expr) if (name_type == TOKEN_CT_EXTNAMEOF) { - if (!decl->extname) + switch (decl->decl_kind) { - SEMA_ERROR(main_var, "'%s' does not have an external name.", decl->name); - return false; + case DECL_VAR: + switch (decl->var.kind) + { + case VARDECL_CONST: + case VARDECL_GLOBAL: + goto RETURN_CT; + case VARDECL_LOCAL: + case VARDECL_PARAM: + case VARDECL_MEMBER: + case VARDECL_BITMEMBER: + case VARDECL_PARAM_REF: + case VARDECL_PARAM_EXPR: + case VARDECL_UNWRAPPED: + case VARDECL_ERASE: + case VARDECL_REWRAPPED: + case VARDECL_PARAM_CT: + case VARDECL_PARAM_CT_TYPE: + case VARDECL_LOCAL_CT: + case VARDECL_LOCAL_CT_TYPE: + // TODO verify that all of these are correct. + break; + } + FALLTHROUGH; + case DECL_POISONED: + case DECL_ATTRIBUTE: + case DECL_BODYPARAM: + case DECL_CT_ASSERT: + case DECL_CT_ECHO: + case DECL_CT_EXEC: + case DECL_CT_INCLUDE: + case DECL_DECLARRAY: + case DECL_ERASED: + case DECL_GLOBALS: + case DECL_IMPORT: + case DECL_LABEL: + case DECL_MACRO: + case DECL_DEFINE: + RETURN_SEMA_ERROR(main_var, "'%s' does not have an external name.", decl->name); + case DECL_BITSTRUCT: + case DECL_DISTINCT: + case DECL_ENUM: + case DECL_ENUM_CONSTANT: + case DECL_FAULT: + case DECL_FAULTVALUE: + case DECL_FNTYPE: + case DECL_FUNC: + case DECL_INTERFACE: + case DECL_STRUCT: + case DECL_TYPEDEF: + case DECL_UNION: + // TODO verify that all of these are correct + goto RETURN_CT; } - expr_rewrite_to_string(expr, decl->extname); +RETURN_CT: + scratch_buffer_set_extern_decl_name(decl, true); + expr_rewrite_to_string(expr, scratch_buffer_to_string()); return true; } if (!decl->unit || name_type == TOKEN_CT_NAMEOF || decl_is_var_local(decl)) @@ -7808,7 +7868,8 @@ static inline bool sema_expr_analyse_lambda(SemaContext *context, Type *target_t } scratch_buffer_append("$lambda"); scratch_buffer_append_unsigned_int(++unit->lambda_count); - decl->extname = decl->name = scratch_buffer_copy(); + decl->name = scratch_buffer_copy(); + decl->extname = decl->name; decl->type = type_new_func(decl, sig); if (!sema_analyse_function_signature(context, decl, sig->abi, sig)) return false; if (target_type && flat->pointer->function.prototype->raw_type != decl->type->function.prototype->raw_type) diff --git a/src/compiler/types.c b/src/compiler/types.c index e66038620..2f8ff92f2 100644 --- a/src/compiler/types.c +++ b/src/compiler/types.c @@ -633,7 +633,7 @@ void type_mangle_introspect_name_to_buffer(Type *type) type = type->function.prototype->raw_type; if (type->function.decl) { - module_copy_extern_name_to_buffer(decl_module(type->function.decl)); + scratch_buffer_append_module(decl_module(type->function.decl), true); scratch_buffer_append("$"); scratch_buffer_append(type->name); } diff --git a/test/test_suite/debug_symbols/defer_macro.c3t b/test/test_suite/debug_symbols/defer_macro.c3t index 33e42e534..833eb65e7 100644 --- a/test/test_suite/debug_symbols/defer_macro.c3t +++ b/test/test_suite/debug_symbols/defer_macro.c3t @@ -690,11 +690,11 @@ no_match: ; preds = %compare !106 = !{!12} !107 = !DILocalVariable(name: "scratch", scope: !108, file: !5, line: 110, type: !109, align: 8) !108 = distinct !DISubprogram(name: "@scratch", linkageName: "@scratch", scope: !5, file: !5, line: 109, scopeLine: 109, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: -!109 = !DICompositeType(tag: DW_TAG_structure_type, name: "Arena_Cursor", scope: !5, file: !5, line: 88, size: 128, align: 64, elements: !110, identifier: "foo_Arena_Cursor") +!109 = !DICompositeType(tag: DW_TAG_structure_type, name: "Arena_Cursor", scope: !5, file: !5, line: 88, size: 128, align: 64, elements: !110, identifier: "foo__Arena_Cursor") !110 = !{!111, !116} !111 = !DIDerivedType(tag: DW_TAG_member, name: "arena", scope: !109, file: !5, line: 89, baseType: !112, size: 64, align: 64) !112 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "Arena*", baseType: !113, size: 64, align: 64, dwarfAddressSpace: 0) -!113 = !DICompositeType(tag: DW_TAG_structure_type, name: "Arena", scope: !5, file: !5, line: 84, size: 64, align: 64, elements: !114, identifier: "foo_Arena") +!113 = !DICompositeType(tag: DW_TAG_structure_type, name: "Arena", scope: !5, file: !5, line: 84, size: 64, align: 64, elements: !114, identifier: "foo__Arena") !114 = !{!115} !115 = !DIDerivedType(tag: DW_TAG_member, name: "cursor", scope: !113, file: !5, line: 85, baseType: !44, size: 64, align: 64) !116 = !DIDerivedType(tag: DW_TAG_member, name: "cursor", scope: !109, file: !5, line: 90, baseType: !44, size: 64, align: 64, offset: 64) diff --git a/test/test_suite/define/aliased_consts.c3t b/test/test_suite/define/aliased_consts.c3t index 0d92f09a6..943a690d2 100644 --- a/test/test_suite/define/aliased_consts.c3t +++ b/test/test_suite/define/aliased_consts.c3t @@ -12,7 +12,7 @@ fn int main() /* #expect: foo.ll -@foo_data = local_unnamed_addr global <{ { { { float, [4 x float], float, [4 x float], float, [4 x float], float } } }, { { { float, [4 x float], float, [4 x float], float, [4 x float], float } } } }> <{ { { { float, [4 x float], float, [4 x float], float, [4 x float], float } } } { { { float, [4 x float], float, [4 x float], float, [4 x float], float } } { { float, [4 x float], float, [4 x float], float, [4 x float], float } { float 1.000000e+00, [4 x float] zeroinitializer, float 1.000000e+00, [4 x float] zeroinitializer, float 1.000000e+00, [4 x float] zeroinitializer, float 1.000000e+00 } } }, { { { float, [4 x float], float, [4 x float], float, [4 x float], float } } } { { { float, [4 x float], float, [4 x float], float, [4 x float], float } } { { float, [4 x float], float, [4 x float], float, [4 x float], float } { float 1.000000e+00, [4 x float] zeroinitializer, float 1.000000e+00, [4 x float] zeroinitializer, float 1.000000e+00, [4 x float] zeroinitializer, float 1.000000e+00 } } } }>, align 16 +@foo__data = local_unnamed_addr global <{ { { { float, [4 x float], float, [4 x float], float, [4 x float], float } } }, { { { float, [4 x float], float, [4 x float], float, [4 x float], float } } } }> <{ { { { float, [4 x float], float, [4 x float], float, [4 x float], float } } } { { { float, [4 x float], float, [4 x float], float, [4 x float], float } } { { float, [4 x float], float, [4 x float], float, [4 x float], float } { float 1.000000e+00, [4 x float] zeroinitializer, float 1.000000e+00, [4 x float] zeroinitializer, float 1.000000e+00, [4 x float] zeroinitializer, float 1.000000e+00 } } }, { { { float, [4 x float], float, [4 x float], float, [4 x float], float } } } { { { float, [4 x float], float, [4 x float], float, [4 x float], float } } { { float, [4 x float], float, [4 x float], float, [4 x float], float } { float 1.000000e+00, [4 x float] zeroinitializer, float 1.000000e+00, [4 x float] zeroinitializer, float 1.000000e+00, [4 x float] zeroinitializer, float 1.000000e+00 } } } }>, align 16 @foo.x = local_unnamed_addr global { { { float, [4 x float], float, [4 x float], float, [4 x float], float } } } { { { float, [4 x float], float, [4 x float], float, [4 x float], float } } { { float, [4 x float], float, [4 x float], float, [4 x float], float } { float 1.000000e+00, [4 x float] zeroinitializer, float 1.000000e+00, [4 x float] zeroinitializer, float 1.000000e+00, [4 x float] zeroinitializer, float 1.000000e+00 } } }, align 4 entry: diff --git a/test/test_suite/module/module_section_export.c3t b/test/test_suite/module/module_section_export.c3t index f92a4b5d0..c556e4690 100644 --- a/test/test_suite/module/module_section_export.c3t +++ b/test/test_suite/module/module_section_export.c3t @@ -19,11 +19,11 @@ int d @private; /* #expect: test.ll -@TEST_a = local_unnamed_addr global i32 0, align 4 +@TEST__a = local_unnamed_addr global i32 0, align 4 @TEST.b = internal unnamed_addr global i32 0, align 4 -@TEST_c = local_unnamed_addr global i32 0, align 4 -@TEST_d = local_unnamed_addr global i32 0, align 4 +@TEST__c = local_unnamed_addr global i32 0, align 4 +@TEST__d = local_unnamed_addr global i32 0, align 4 define internal void @TEST.hello() -define void @TEST_hello2() -define void @TEST_helloe() \ No newline at end of file +define void @TEST__hello2() +define void @TEST__helloe() \ No newline at end of file diff --git a/test/test_suite/switch/jump_with_inc.c3t b/test/test_suite/switch/jump_with_inc.c3t index b6931fd28..ce8de6db7 100644 --- a/test/test_suite/switch/jump_with_inc.c3t +++ b/test/test_suite/switch/jump_with_inc.c3t @@ -17,7 +17,7 @@ fn int foo(int x) @export } /* #expect: test.ll -define i32 @test_foo(i32 %0) #0 { +define i32 @test__foo(i32 %0) #0 { entry: %x = alloca i32, align 4 %switch = alloca i32, align 4 diff --git a/test/test_suite/switch/switch_in_defer_macro.c3t b/test/test_suite/switch/switch_in_defer_macro.c3t index 7797f0530..65ef115e7 100644 --- a/test/test_suite/switch/switch_in_defer_macro.c3t +++ b/test/test_suite/switch/switch_in_defer_macro.c3t @@ -718,7 +718,7 @@ entry: br i1 %eq, label %and.rhs, label %and.phi and.rhs: ; preds = %entry - %2 = call i8 @char.is_alpha(i8 zeroext %1) + %2 = call i8 @std.ascii.char.is_alpha(i8 zeroext %1) %3 = trunc i8 %2 to i1 br label %and.phi @@ -731,7 +731,7 @@ or.rhs: ; preds = %and.phi br i1 %lt, label %and.rhs1, label %and.phi2 and.rhs1: ; preds = %or.rhs - %4 = call i8 @char.is_alnum(i8 zeroext %1) + %4 = call i8 @std.ascii.char.is_alnum(i8 zeroext %1) %5 = trunc i8 %4 to i1 br label %and.phi2