This is the mail archive of the mailing list for the GCC project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Darwin] Patch: enable linkonce support for Darwin

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,, It also fixes, which is a P2 bug.

Testing: bootstrapped (C, C++, Java) on OS X 10.3, no regressions in the C, C++, or libstdc++ testsuites.

OK, this is a large and invasive patch (but with one important feature: I claim it is obvious that this patch will not change the behavior of the compiler on any platform other than Darwin). So I should walk people through some of the high points. Most of the patch is pretty clear if you think about it 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. Two more target macros associated with this: TARGET_SUPPORTS_HIDDEN (no, HAVE_GAS_HIDDEN doesn't cover this; see the comments, and see also the place in the configure script where HAVE_GAS_HIDDEN is set) and DEFAULT_USE_HIDDEN_WEAK.

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.

Whew! I hope I've answered most of the major questions here. Now the patch.

OK to commit to mainline?


Attachment: weak-darwin.txt
Description: Text document

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]