From a88b44ed01eef368a0729213e0b40d72a116b0ea Mon Sep 17 00:00:00 2001 From: Siarhei Siamashka Date: Sun, 30 Jan 2022 22:05:16 +0200 Subject: [PATCH] rt.config: Compatibility with GDC '-fno-weak-templates' option The rt.config module provides a set of configuration variables, with various ways to override them as documented here: https://dlang.org/phobos/rt_config.html The desirable assembly output for the 'rt_cmdline_enabled' variable looks like this (that's what is now generated by default): .weak rt_cmdline_enabled .data .type rt_cmdline_enabled, @object .size rt_cmdline_enabled, 1 rt_cmdline_enabled: .byte 1 But unfortunately when GDC11 or GDC12 is used with the '-fno-weak-templates' option, the assembly output for the 'rt_cmdline_enabled' variable changes to: .weak rt_cmdline_enabled .section .data.rt_cmdline_enabled,"awG",@progbits,rt_cmdline_enabled,comdat .type rt_cmdline_enabled, @gnu_unique_object .size rt_cmdline_enabled, 1 rt_cmdline_enabled: .byte 1 And this results in "multiple definition of `rt_cmdline_enabled'; /tmp/ccc5MZMh.o:(.bss+0x0): first defined here" linker error when trying to compile the following small program: import std.stdio; extern(C) __gshared bool rt_cmdline_enabled = false; void main(string[] args) { writeln(args); } This patch solves the problem by setting GDC-specific @attribute("weak") for these variables instead of having them enclosed in a "template { }" block. The assembly output is now always desirable in both '-fweak-templates' and '-fno-weak-templates' configurations. There are very strong reasons to prefer '-fno-weak-templates', because this allows inlining template functions. See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102765 --- src/rt/config.d | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/rt/config.d b/src/rt/config.d index a6605f4d60..d74f4e4a1e 100644 --- a/src/rt/config.d +++ b/src/rt/config.d @@ -43,18 +43,32 @@ Source: $(DRUNTIMESRC rt/_config.d) module rt.config; -// put each variable in its own COMDAT by making them template instances -template rt_envvars_enabled() +version (GNU) { - extern(C) pragma(mangle, "rt_envvars_enabled") __gshared bool rt_envvars_enabled = false; + // mark variables as "weak" by using a GDC-specific attribute + import gcc.attributes; + extern(C) pragma(mangle, "rt_envvars_enabled") @attribute("weak") __gshared bool rt_envvars_enabled_ = false; + extern(C) pragma(mangle, "rt_cmdline_enabled") @attribute("weak") __gshared bool rt_cmdline_enabled_ = true; + extern(C) pragma(mangle, "rt_options") @attribute("weak") __gshared string[] rt_options_ = []; + ref auto rt_envvars_enabled()() { return rt_envvars_enabled_; } + ref auto rt_cmdline_enabled()() { return rt_cmdline_enabled_; } + ref auto rt_options()() { return rt_options_; } } -template rt_cmdline_enabled() +else { - extern(C) pragma(mangle, "rt_cmdline_enabled") __gshared bool rt_cmdline_enabled = true; -} -template rt_options() -{ - extern(C) pragma(mangle, "rt_options") __gshared string[] rt_options = []; + // put each variable in its own COMDAT by making them template instances + template rt_envvars_enabled() + { + extern(C) pragma(mangle, "rt_envvars_enabled") __gshared bool rt_envvars_enabled = false; + } + template rt_cmdline_enabled() + { + extern(C) pragma(mangle, "rt_cmdline_enabled") __gshared bool rt_cmdline_enabled = true; + } + template rt_options() + { + extern(C) pragma(mangle, "rt_options") __gshared string[] rt_options = []; + } } import core.stdc.ctype : toupper;