On Wed, Jan 31, 2024 at 07:11:20PM +0100, Jakub Jelinek wrote:
> On Wed, Jan 31, 2024 at 09:39:12AM -0800, H.J. Lu wrote:
> > GNU binutils has no issues with it:
>
> I know, I meant gcc.
> So, it seems get_section handles section purely by name lookup
> and isn't prepared to deal with multiple different sections
> of the same name, but different comdat group.
>
> Thus, maybe at least temporarily we need to use unique
> section names here, say
> .data.rel.ro.local.pool.<comdat_name>
> .data.rel.ro.pool.<comdat_name>
> .rodata.pool.<comdat_name>
> where <comdat_name> would be the name of the comdat group, i.e.
> IDENTIFIER_POINTER (DECL_COMDAT_GROUP (decl))
Here is an untested patch which implements that:
2024-01-31 Jakub Jelinek <jakub@redhat.com>
H.J. Lu <hjl.tools@gmail.com>
PR rtl-optimization/113617
* varasm.cc (default_elf_select_rtx_section): For
references to private symbols in comdat sections
use .data.relro.local.pool.<comdat>, .data.relro.pool.<comdat>
or .rodata.<comdat> comdat sections.
* g++.dg/other/pr113617.C: New test.
* g++.dg/other/pr113617.h: New test.
* g++.dg/other/pr113617-aux.cc: New test.
Jakub
On Wed, Jan 31, 2024 at 07:58:50PM +0100, Jakub Jelinek wrote:
> On Wed, Jan 31, 2024 at 07:11:20PM +0100, Jakub Jelinek wrote:
> > On Wed, Jan 31, 2024 at 09:39:12AM -0800, H.J. Lu wrote:
> > > GNU binutils has no issues with it:
> >
> > I know, I meant gcc.
> > So, it seems get_section handles section purely by name lookup
> > and isn't prepared to deal with multiple different sections
> > of the same name, but different comdat group.
> >
> > Thus, maybe at least temporarily we need to use unique
> > section names here, say
> > .data.rel.ro.local.pool.<comdat_name>
> > .data.rel.ro.pool.<comdat_name>
> > .rodata.pool.<comdat_name>
> > where <comdat_name> would be the name of the comdat group, i.e.
> > IDENTIFIER_POINTER (DECL_COMDAT_GROUP (decl))
>
> Here is an untested patch which implements that:
>
> 2024-01-31 Jakub Jelinek <jakub@redhat.com>
> H.J. Lu <hjl.tools@gmail.com>
>
> PR rtl-optimization/113617
> * varasm.cc (default_elf_select_rtx_section): For
> references to private symbols in comdat sections
> use .data.relro.local.pool.<comdat>, .data.relro.pool.<comdat>
> or .rodata.<comdat> comdat sections.
>
> * g++.dg/other/pr113617.C: New test.
> * g++.dg/other/pr113617.h: New test.
> * g++.dg/other/pr113617-aux.cc: New test.
Bootstrapped/regtested on x86_64-linux and i686-linux successfully,
ok for trunk?
Jakub
@@ -7458,17 +7458,63 @@ default_elf_select_rtx_section (machine_
unsigned HOST_WIDE_INT align)
{
int reloc = compute_reloc_for_rtx (x);
+ tree decl = nullptr;
+ const char *prefix = nullptr;
+ int flags = 0;
+
+ /* If it is a private COMDAT function symbol reference, call
+ function_rodata_section for the read-only or relocated read-only
+ data section associated with function DECL so that the COMDAT
+ section will be used for the private COMDAT function symbol. */
+ if (HAVE_COMDAT_GROUP)
+ {
+ if (GET_CODE (x) == CONST
+ && GET_CODE (XEXP (x, 0)) == PLUS
+ && CONST_INT_P (XEXP (XEXP (x, 0), 1)))
+ x = XEXP (XEXP (x, 0), 0);
+
+ if (GET_CODE (x) == SYMBOL_REF)
+ {
+ decl = SYMBOL_REF_DECL (x);
+ if (decl
+ && (TREE_CODE (decl) != FUNCTION_DECL
+ || !DECL_COMDAT_GROUP (decl)
+ || TREE_PUBLIC (decl)))
+ decl = nullptr;
+ }
+ }
/* ??? Handle small data here somehow. */
if (reloc & targetm.asm_out.reloc_rw_mask ())
{
- if (reloc == 1)
+ if (decl)
+ {
+ prefix = reloc == 1 ? ".data.rel.ro.local" : ".data.rel.ro";
+ flags = SECTION_WRITE | SECTION_RELRO;
+ }
+ else if (reloc == 1)
return get_named_section (NULL, ".data.rel.ro.local", 1);
else
return get_named_section (NULL, ".data.rel.ro", 3);
}
+ if (decl)
+ {
+ const char *comdat = IDENTIFIER_POINTER (DECL_COMDAT_GROUP (decl));
+ if (!prefix)
+ prefix = ".rodata";
+ size_t prefix_len = strlen (prefix);
+ size_t comdat_len = strlen (comdat);
+ size_t len = prefix_len + sizeof (".pool.") + comdat_len;
+ char *name = XALLOCAVEC (char, len);
+ memcpy (name, prefix, prefix_len);
+ memcpy (name + prefix_len, ".pool.", sizeof (".pool.") - 1);
+ memcpy (name + prefix_len + sizeof (".pool.") - 1, comdat,
+ comdat_len + 1);
+ return get_section (name, flags | SECTION_LINKONCE, decl);
+ }
+
return mergeable_constant_section (mode, align, 0);
}
@@ -0,0 +1,27 @@
+// PR rtl-optimization/113617
+// { dg-do link { target c++11 } }
+// { dg-options "-O2" }
+// { dg-additional-options "-fPIC" { target fpic } } */
+// { dg-additional-options "-shared" { target shared } } */
+// { dg-additional-sources pr113617-aux.cc }
+
+#include "pr113617.h"
+
+int z;
+long xx1;
+void corge() {
+ A<long long> a;
+ a.foo(xx1, 0);
+}
+
+typedef unsigned long int VV __attribute__((vector_size (2 * sizeof (long))));
+VV vv;
+__attribute__((noipa)) static void fn1 (void) {}
+__attribute__((noipa)) static void fn2 (void) {}
+
+void
+fn3 ()
+{
+ VV a = { (unsigned long) &fn1, (unsigned long) &fn2 };
+ vv = a;
+}
@@ -0,0 +1,132 @@
+namespace {
+template <int V> struct J { static constexpr int value = V; };
+template <bool V> using K = J<V>;
+using M = K<true>;
+template <int> struct L { template <typename _Tp, typename> using type = _Tp; };
+template <bool _Cond, typename _If, typename _Else> using N = typename L<_Cond>::type<_If, _Else>;
+M k;
+template <typename _Tp> struct O { using type = _Tp; };
+template <typename _Up>
+struct P : N<M ::value, O<_Up>, _Up> {};
+template <typename _Tp> struct Q { using type = typename P<_Tp>::type; };
+}
+namespace R {
+struct H;
+enum G {};
+template <typename> class S;
+struct T { using U = bool (*) (H &, const H &, G); U F; };
+template <typename, typename> class B;
+template <typename _R, typename _F, typename... _A>
+struct B<_R(_A...), _F> {
+ static bool F(H &, const H &, G) { return false; }
+ __attribute__((noipa)) static _R bar(const H &) {}
+};
+template <typename _R, typename... _A>
+struct S<_R(_A...)> : T {
+ template <typename _F> using AH = B<_R(), _F>;
+ template <typename _F> S(_F) {
+ using AG = AH<_F>;
+ barr = AG::bar;
+ F = AG::F;
+ }
+ using AF = _R (*)(const H &);
+ AF barr;
+};
+template <typename> class I;
+template <typename _F, typename... _B>
+struct I<_F(_B...)> {};
+template <typename> using W = decltype(k);
+template <int, typename _F, typename... _B> struct V {
+ typedef I<typename Q<_F>::type(typename Q<_B>::type...)> type;
+};
+template <typename _F, typename... _B>
+__attribute__((noipa)) typename V<W<_F>::value, _F, _B...>::type
+baz(_F, _B...) { return typename V<W<_F>::value, _F, _B...>::type (); }
+template <typename _Tp> struct AJ {
+ template <typename _Up> struct _Ptr { using type = _Up *; };
+ using AI = typename _Ptr<_Tp>::type;
+};
+template <typename _Tp> struct Y {
+ using AI = typename AJ<_Tp>::AI;
+ AI operator->();
+};
+}
+extern int z;
+namespace N1 {
+namespace N2 {
+namespace N3 {
+enum Z { Z1, Z2 };
+template <int> struct X {
+ template <typename _F>
+ __attribute__((noipa)) void boo(long long, long long, long long, _F &) {}
+};
+struct AC {
+ AC(int);
+ void m1(R::S<void()>);
+};
+template <typename>
+__attribute__((noipa)) void garply(void *, long long, long long, long long) {}
+template <>
+template <typename _F>
+void X<Z2>::boo(long long, long long x, long long y, _F &fi) {
+ AC pool(z);
+ for (;;) {
+ auto job = R::baz(garply<_F>, &fi, y, y, x);
+ pool.m1(job);
+ }
+}
+struct AB {
+ static AB &bleh();
+ template <typename _F>
+ void boo(long first, long x, long y, _F fi) {
+ switch (ab1) {
+ case Z1:
+ ab2->boo(first, x, y, fi);
+ case Z2:
+ ab3->boo(first, x, y, fi);
+ }
+ }
+ Z ab1;
+ R::Y<X<Z1>> ab2;
+ R::Y<X<Z2>> ab3;
+};
+template <typename, bool> struct C;
+template <typename _F> struct C<_F, false> {
+ __attribute__((noipa)) C(_F) {}
+ void boo(long first, long x, long y) {
+ auto u = AB::bleh();
+ u.boo(first, x, y, *this);
+ }
+};
+template <typename _F> struct AA { typedef C<_F, 0> type; };
+}
+}
+}
+struct AD {
+ template <typename _F>
+ static void boo(long first, long x, long y, _F f) {
+ typename N1::N2::N3::AA<_F>::type fi(f);
+ fi.boo(first, x, y);
+ }
+ template <typename _F>
+ static void boo(long first, long x, _F f) {
+ boo(first, x, 0, f);
+ }
+};
+template <typename> struct A {
+ void foo(long long, long long);
+ int *c;
+};
+namespace {
+template <typename> struct D { __attribute__((noipa)) D(int *) {} };
+}
+template <typename T>
+void A<T>::foo(long long x, long long y)
+{
+ int e;
+ D<T> d(&e);
+ AD::boo(0, y, d);
+ long p;
+ for (p = 0; p < x; p++)
+ c[p] = c[p - 1];
+}
@@ -0,0 +1,9 @@
+// PR rtl-optimization/113617
+// { dg-do link { target { c++17 && c++14_down } } }
+
+#include "pr113617.h"
+
+void qux() {
+ A<long long> a;
+ a.foo(0, 0);
+}