Bug 93146 - C++ TLS init function not generated on AIX
Summary: C++ TLS init function not generated on AIX
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: unknown
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
: 100641 109091 (view as bug list)
Depends on:
Blocks:
 
Reported: 2020-01-03 16:35 UTC by David Edelsohn
Modified: 2024-04-06 05:40 UTC (History)
4 users (show)

See Also:
Host:
Target: powerpc-ibm-aix*
Build:
Known to work:
Known to fail:
Last reconfirmed: 2020-01-03 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description David Edelsohn 2020-01-03 16:35:07 UTC
SYMPTOM:
On AIX, TLS init elicits linker errors such as

TLS init fuction for thread_local_seg_handler

or

__tls_init


An example C++ program is

$ cat a.cc
#include <atomic>
struct Test {std::atomic<int> x; };

thread_local Test t;

$ cat main.cc
#include <atomic>
struct Test {std::atomic<int> x; };

extern thread_local Test t;
int main () {
  return t.x.load();
}

$ g++ -std=c++14 -pthread a.cc main.cc
ld: 0711-317 ERROR: Undefined symbol: __tls_init


BACKGROUND:

AIX XCOFF symbol aliases do not function the same as ELF symbols aliases: XCOFF generates "hard aliases" (like hard links) with only one definition and the attributes are shared / overwritten, instead of a "symbolic" reference to the other definition with its own attributes.  Because of this gcc/config/rs6000/xcoff.h defines:

/* This is how we tell the assembler to equate two values. 
   The semantic of AIX assembler's .set do not correspond to middle-end expectat
ions.
   We output aliases as alternative symbols in the front of the definition
   via DECLARE_FUNCTION_NAME and DECLARE_OBJECT_NAME.
   We still need to define this macro to let middle-end know that aliases are
   supported.
 */
#define ASM_OUTPUT_DEF(FILE,LABEL1,LABEL2) do { } while (0)

Honza generously provided other AIX-specific code for function aliases that generate alternative labels in front of the definition.

Because of this, GCC internals consider AIX as TARGET_SUPPORTS_ALIASES.  Note that the above macro will not output anything for an alias.

AIX also support TLS.

These two features / behaviors collide for TLS init functions.  gcc/cp/decl2.c get_tls_init_fn() and handle_tls_init() depend upon TARGET_SUPPORTS_ALIASES, e.g.,

      if (TARGET_SUPPORTS_ALIASES && TREE_PUBLIC (var))
        {
          tree single_init_fn = get_tls_init_fn (var);
          if (single_init_fn == NULL_TREE)
            continue;
          cgraph_node *alias
            = cgraph_node::get_create (fn)->create_same_body_alias
                (single_init_fn, fn);
          gcc_assert (alias != NULL);
        }

Disabling TARGET_SUPPORTS_ALIASES within cp/decl2.c does not generate correct code (it switches from a mangled TLS init function to __tls_init).

How can G++ be coerced to generate TLS init functions for AIX?
Comment 1 David Edelsohn 2020-01-03 16:36:15 UTC
Confirmed.
Comment 2 David Edelsohn 2020-01-08 16:58:18 UTC
One option is to force

flag_extern_tls_init=0

as default for AIX, e.g., -fno-extern-tls-init.

That works around the linking issue, but it assumes the limited semantics / assertion of that option always are correct.
Comment 3 Andrew Paprocki 2020-04-17 19:35:21 UTC
Just wanted to echo that I hit this as well because gdb (I'm compiling 9.1) now uses `thread_local`:

ld: 0711-317 ERROR: Undefined symbol: TLS init function for thread_local_segv_handler
ld: 0711-317 ERROR: Undefined symbol: .TLS init function for thread_local_segv_handler

Using `-fno-extern-tls-init` results in a successful build.
Comment 4 Andrew Pinski 2024-04-06 05:39:53 UTC
*** Bug 100641 has been marked as a duplicate of this bug. ***
Comment 5 Andrew Pinski 2024-04-06 05:40:08 UTC
*** Bug 109091 has been marked as a duplicate of this bug. ***