Lets check how TLS looks like in RTL. I wrote simple
test:
(insn 29 8 10 3 (set (reg:SI 0 ax [orig:82 _1 ] [82])
(mem/c:SI (const:DI (unspec:DI [
(symbol_ref:DI ("tls_state") [flags 0x2a] <var_decl 0x7f61bce052d0 tls_state>)
] UNSPEC_NTPOFF)) [2 tls_state.idx+0 S4 A32 AS1])) "stest.cc":15:37 81 {*movsi_internal}
(nil))
We can see attribute UNSPEC here - it can be extracted as XINT (in_rtx, 1) for GET_CODE == UNSPEC. The first problem here is that values UNSPEC_XXX are machine-specific. For example the same code while cross-compiling for mips:
insn 60 13 61 (set (reg:SI 3 $3)
(unspec:SI [
(const_int 0 [0])
] UNSPEC_TLS_GET_TP)) "stest.cc":15:37 706 {*tls_get_tp_si_split}
(nil))
(insn 61 60 15 (set (reg:SI 2 $2 [201])
(reg:SI 3 $3)) "stest.cc":15:37 313 {*movsi_internal}
(nil))
(insn 15 61 16 (set (reg:SI 3 $3 [202])
(high:SI (const:SI (unspec:SI [
(symbol_ref:SI ("tls_state") [flags 0x2a] <var_decl 0x7ff96a9dfcf0 tls_state>)
] 306)))) "stest.cc":15:37 313 {*movsi_internal}
(nil))
Second - NTPOFF in comments marked as belonging to "Relocation specifiers" while
;; TLS support
UNSPEC_TP
UNSPEC_TLS_GD
UNSPEC_TLS_LD_BASE
UNSPEC_TLSDESC
UNSPEC_TLS_IE_SUN
Thirdly - lets recompile the same file with -fPIC option:
(call_insn/u 9 8 11 3 (parallel [
(set (reg:DI 0 ax)
(call:DI (mem:QI (symbol_ref:DI ("__tls_get_addr")) [0 S1 A8])
(const_int 0 [0])))
(unspec:DI [
(symbol_ref:DI ("tls_state") [flags 0x10] <var_decl 0x7fcea13c92d0 tls_state>)
(reg/f:DI 7 sp)
] UNSPEC_TLS_GD)
]) "stest.cc":15:37 1048 {*tls_global_dynamic_64_di}
(expr_list:REG_EH_REGION (const_int -2147483648 [0xffffffff80000000])
(nil))
(nil))
(insn 11 9 46 3 (set (reg:SI 0 ax [orig:82 _1 ] [82])
(mem/c:SI (reg/f:DI 0 ax [88]) [2 tls_state.idx+0 S4 A32])) "stest.cc":15:37 81 {*movsi_internal}
(nil))
You can notice that address of TLS var gathered with __tls_get_addr but next access to it not marked in any way - just regular chain set mem component_ref. Disgusting
Just note for myself what else cannot be extracted from gcc RTL:
- pointer to members -
despite the fact that in file cp/cp-tree.def there are OFFSET_REF & PTRMEM_CST in real RTL they are just integer constants - pointer to member methods - similalry
- TLS are indistinguishable from regular global vars
- to be continued