This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[Darwin] Patch, take 2: enable linkonce support for Darwin
- From: Matt Austern <austern at apple dot com>
- To: Matt Austern <austern at apple dot com>
- Cc: gcc at gcc dot gnu dot org, gcc-patches at gcc dot gnu dot org
- Date: Fri, 30 Jan 2004 08:34:57 -0800
- Subject: [Darwin] Patch, take 2: enable linkonce support for Darwin
- References: <24F20E06-5275-11D8-AAA9-000A95BCF344@apple.com>
On Jan 29, 2004, at 8:06 AM, Matt Austern wrote:
This patch enables linkonce support, a.k.a. vague linkage, a.k.a
comdat, for Darwin. It fixes a bunch of test case failures from g++.dg
and g++.old-deja. (init/init-ref4.C, parse/attr-ctor1.C,
parse/constant4.C, template/non-dependent2.C,
template/non-dependent3.C, g++.other/comdat3.C, g++.other/mangle3.C,
g++.pt/static3.C, g++.pt/static6.C) It also fixes
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11026, which is a P2 bug.
Testing: bootstrapped (C, C++, Java) on OS X 10.3, no regressions in
the C, C++, or libstdc++ testsuites.
This new and improved patch includes documentation for -fhidden-weak
and for the new target macros, and test cases for -fhidden-weak.
The explanation of the patch is pretty much the same as in the first
version, but I'm reposting it here so people don't have to go back
through the archives. As before, it's pretty easy to understand in
terms of Darwin linker features.
Vague linkage on Darwin uses a feature called coalescing, which is sort
of like ELF weak symbols and sort of like GNU linkonce sections except
that it's not all that much like either of them. A coalesced symbol
must be marked with the .weak_definition directive and must also appear
in a section that is marked with the "coalesced" flag. These aren't
like GNU linkonce sections because we have many symbols per coalesced
section, not one section per symbol. All coalesced function
definitions, for example, go in __TEXT,__textcoal_nt. References to
coalesced symbols must be indirect, even if the compiler thinks it sees
a definition of a coalesced symbol in the same translation unit as the
use. Coalescing is only for defined symbols, and only applies to
symbols with global or private extern scope.
The Darwin linker doesn't have a notion of subsections, so coalescing
simply works at the level of things between one nonlocal symbol (a
nonlocal symbol starts with something other than "L") and the next. A
coalesced section must begin with a nonlocal symbol.
Exceptions are an annoying problem. Here's the problem scenerio:
suppose an FDE in a .o refers to local symbols in a coalesced function
from that same .o, and now suppose that particular copy of the
coalesced function gets discarded by the linker. In that case, the
dangling reference will cause the Darwin linker to die horribly. The
solution we came up with, which Apple has been using in our locally
modified compiler for two years, is to coalesce FDEs too. We give
every FDE its own symbol (the name we choose is <foo>.eh, where <foo>
is the assembler name of the function the FDE corresponds to), so that
the FDEs too are coalesced. We make sure that a function and its FDE
always have the same scope and visibility; the idea is that if the
linker discards a coalesced function, it will also discard the
corresponding coalesced FDE. There's one little subtlety involving
implicit instantiations that have FDEs and explicit instantiations that
don't, and we solve that by sometimes generating dummy FDE labels.
This is admittedly a crude scheme; you can think of it as "poor man's
group COMDAT". It's probably the best we can do given the Darwin
linker, though, and Apple has shown that it can actually work.
To support all this exception machinery I put in a link from
dw_fde_struct back to the associated decl (we'll need that for other
targets, anyway, when and if we move to ELF group COMDAT), and I
introduced a new target macro, ASM_OUTPUT_UNWIND_LABEL, to give FDEs
their labels. Everywhere but Darwin, that macro does nothing.
Two minor quirks of the Darwin linker that we have to accommodate.
First quirk: coalesced symbols can't be put in a static archive's table
of contents. If the linker sees a static archive with duplicate TOC
entries, it will give an unfriendly warning and then behave
unpredictably. That's why (as you'll see if you look in the darwin.c
section of my patch) the __TEXT,__textcoal_nt section is given the
"no_toc" flag. OK, what's the consequence of this? Since you'll never
find a coalesced symbol from the TOC, you have to make sure a symbol
will only be marked as coalesced if it's something that can be
regenerated in every translation unit where it's needed. There's
exactly one obscure corner case where it matters: explicit
instantiation of a class template that's marked as "extern". The
question is whether explicit instantiation of a class template triggers
explicit or implicit instantiation of its member functions. As it
stands, the compiler does an implicit instantiation (with a note in the
comments saying that the standard doesn't say which one it should do).
My patch keeps that behavior in general, but makes it an explicit
instantiation, thus something that will appear in the TOC, for Darwin
in the special case where we're explicitly instantiating a previously
extern template. I introduced a new target macro, TARGET_WEAK_NO_TOC,
to control this behavior.
Second quirk: Common is bad news. Common symbols in Darwin can't have
hidden visibility and can't be exported from dylibs. The second is
deliberate and the first is a bug, but both of them are things we have
to deal with. So we really just shouldn't ever use common to implement
vague linkage, we should always use coalescing instead. I introduced
another target macro, USE_COMMON_FOR_ONE_ONLY, so we can tell the
compiler about targets where common is a poor choice for representing
vague linkage. (Again: this is not the same thing as -fno-common.
Common is fine in its place, just not for vague linkage.)
Finally, one new user-visible feature: -fhidden-weak. This flag makes
the compiler automatically give hidden visibility to symbols that have
vague linkage. This feature has proved useful in Apple compilers,
because sometimes exporting coalesced symbols from dylibs interacts
poorly with some of our more complicated linker features. I also have
the sense from C++ standardization committee discussions that, if the
committee ever standardizes dynamic libraries, something like this is
the direction things are likely to go. I haven't made -fhidden-weak
the default on any platform, not even Darwin, but I've left in the
machinery so it can be made the default. One more target macro
associated with this: TARGET_SUPPORTS_HIDDEN. No, HAVE_GAS_HIDDEN
doesn't cover this; it's a slightly weaker condition.
Potentially questionable decisions. First, I'm keying this off
DECL_ONE_ONLY, not DECL_WEAK. I don't have strong feelings about this,
but I think it's a slightly better choice. DECL_WEAK has just a little
too much baggage associated with it, and there are too many places in
the back end that think that DECL_WEAK means all of the things that
weak symbols mean on ELF. Second, I've introduced target macros and
not target hooks. Again I don't have a strong preference, but (this is
subjective) in my opinion target macros were more consistent with
existing style. The sorts of things I'm doing here seemed more like
the things people are currently doing with target macros than like the
things people are currently doing with hooks.
Here's the patch. OK to commit to mainline?
--Matt
Attachment:
weak-darwin-2.txt
Description: Text document