Skip to content

Commit 5b7c219

Browse files
authored
some progress with thread local data (#21838)
1 parent 7384645 commit 5b7c219

File tree

3 files changed

+104
-4
lines changed

3 files changed

+104
-4
lines changed

compiler/src/dmd/backend/dout.d

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ void outdata(Symbol* s)
8181
debugy && printf("outdata('%s')\n",s.Sident.ptr);
8282

8383
//printf("outdata('%s', ty=x%x)\n",s.Sident.ptr,s.Stype.Tty);
84-
//symbol_print(s);
84+
//symbol_print(*s);
8585

8686
// Data segment variables are always live on exit from a function
8787
s.Sflags |= SFLlivexit;
@@ -257,6 +257,8 @@ void outdata(Symbol* s)
257257
{
258258
assert(config.objfmt == OBJ_MACH && I64);
259259

260+
/* The initializer for the TLS goes into the __thread_data section
261+
*/
260262
seg_data* pseg = objmod.tlsseg_data();
261263
s.Sseg = pseg.SDseg;
262264
objmod.data_start(s, datasize, s.Sseg);
@@ -266,6 +268,22 @@ void outdata(Symbol* s)
266268
}
267269
case mTYthread:
268270
{
271+
if (config.objfmt == OBJ_MACH && config.target_cpu == TARGET_AArch64)
272+
{
273+
// Special handling
274+
import dmd.backend.machobj : MachObj_thread_vars;
275+
targ_size_t offseti;
276+
int segi = MachObj_thread_vars(*s, offseti);
277+
dt_writeToObj(objmod, dtstart, segi, offseti);
278+
Offset(segi) = offseti;
279+
dt_free(dtstart);
280+
281+
// if (s.Sclass == SC.global || s.Sclass == SC.static_)
282+
// objmod.pubdefsize(seg,s,s.Soffset,datasize); // do the definition
283+
284+
// BUG AArch64: symbolic debug info?
285+
return;
286+
}
269287
seg_data* pseg = objmod.tlsseg();
270288
s.Sseg = pseg.SDseg;
271289
objmod.data_start(s, datasize, s.Sseg);

compiler/src/dmd/backend/mach.d

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,9 +213,13 @@ enum
213213
S_16BYTE_LITERALS = 14,
214214
S_DTRACE_DOF = 15,
215215

216+
S_LAZY_DYLIB_SYMBOL_POINTERS = 0x10,
216217
S_THREAD_LOCAL_REGULAR = 0x11, // template of initial values for TLVs
217218
S_THREAD_LOCAL_ZEROFILL = 0x12, // template of initial values for TLVs
218219
S_THREAD_LOCAL_VARIABLES = 0x13, // TLV descriptors
220+
S_THREAD_LOCAL_VARIABLE_POINTERS = 0x14,
221+
S_THREAD_LOCAL_INIT_FUNCTION_POINTERS = 0x15,
222+
S_INIT_FUNC_OFFSETS = 0x16,
219223

220224
SECTION_ATTRIBUTES_USR = 0xFF000000,
221225
S_ATTR_PURE_INSTRUCTIONS = 0x80000000,

compiler/src/dmd/backend/machobj.d

Lines changed: 81 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,7 +1080,23 @@ void MachObj_term(const(char)[] objfilename)
10801080
}
10811081
else
10821082
{
1083-
if (s.Sclass == SC.extern_ ||
1083+
if (AArch64 && s.Sclass == SC.locstat && s.Sfl == FL.tlsdata)
1084+
{
1085+
rel.r_address = cast(int)r.offset;
1086+
rel.r_symbolnum = s.Sxtrnnum;
1087+
rel.r_pcrel = 0;
1088+
rel.r_length = 3;
1089+
rel.r_extern = 1;
1090+
rel.r_type = ARM64_RELOC_UNSIGNED;
1091+
fobjbuf.write(&rel, rel.sizeof);
1092+
foffset += rel.sizeof;
1093+
nreloc++;
1094+
int32_t* p = patchAddr64(seg, r.offset);
1095+
// Absolute address; add in addr of start of targ seg
1096+
*p += SecHdrTab64[SegData[s.Sseg].SDshtidx].addr + s.Soffset;
1097+
//patch(pseg, r.offset, s.Sseg, s.Soffset);
1098+
}
1099+
else if (s.Sclass == SC.extern_ ||
10841100
s.Sclass == SC.comdef ||
10851101
s.Sclass == SC.comdat)
10861102
{
@@ -1346,7 +1362,7 @@ void MachObj_term(const(char)[] objfilename)
13461362
for (int i = 0; i < dysymtab_cmd.nextdefsym; i++)
13471363
{ Symbol* s = (cast(Symbol**)public_symbuf.buf)[i];
13481364

1349-
//printf("Writing public symbol %d:x%x %s\n", s.Sseg, s.Soffset, s.Sident);
1365+
//printf("Writing public symbol %d:x%x %s\n", s.Sseg, cast(int)s.Soffset, s.Sident.ptr);
13501366
nlist_64 sym;
13511367
sym.n_strx = mach_addmangled(s);
13521368
sym.n_type = N_EXT | N_SECT;
@@ -1976,6 +1992,68 @@ seg_data* MachObj_tlsseg()
19761992
return SegData[seg];
19771993
}
19781994

1995+
/*******************************************
1996+
* Emit 24 byte __thread_vars section for AArch64.
1997+
* Returns:
1998+
* segment to write initialization data to
1999+
*/
2000+
@trusted
2001+
int MachObj_thread_vars(ref Symbol s, out targ_size_t offset)
2002+
{
2003+
printf("MachObj_thread_vars(s)\n");
2004+
symbol_print(s);
2005+
/* create _ident$tlv$init Symbol si
2006+
*/
2007+
Symbol* si;
2008+
{
2009+
char[DEST_LEN] dest = void;
2010+
size_t len = strlen(s.Sident.ptr);
2011+
char* destr = dest.ptr;
2012+
if (len > DEST_LEN)
2013+
destr = cast(char*)mem_malloc(len + 1);
2014+
destr[0] = '_';
2015+
memcpy(destr + 1, s.Sident.ptr, len);
2016+
memcpy(destr + 1 + len, "$tlv$init".ptr, 9); // includes terminating 0
2017+
si = symbol_name(destr[0 .. 1 + len + 9], SC.locstat, type_fake(TYint));
2018+
2019+
if (destr != dest.ptr)
2020+
mem_free(dest.ptr);
2021+
}
2022+
2023+
/* write _ident$tlv$init to __thread_data section
2024+
*/
2025+
MachObj_tlsseg_data();
2026+
si.Sseg = seg_tlsseg_data;
2027+
si.Sfl = FL.tlsdata;
2028+
offset = SegData[si.Sseg].SDbuf.length();
2029+
MachObj_pubdef(si.Sseg, si, offset);
2030+
2031+
/* Create __thread_vars section, and s will refer to it
2032+
*/
2033+
seg_data* tvsegdata = MachObj_tlsseg(); // __thread_vars segment
2034+
int tvseg = seg_tlsseg;
2035+
s.Sseg = tvseg;
2036+
MachObj_pubdef(tvseg, &s, tvsegdata.SDbuf.length());
2037+
2038+
/* 3 pointers are written to __thread_vars section:
2039+
* 1. pointer to __tlv_bootstrap
2040+
* 2. null pointer
2041+
* 3. pointer to _ident$tlv$init in the __thread_data section
2042+
*/
2043+
2044+
// 1. pointer to __tlv_bootstrap
2045+
Symbol* stlv_bootstrap = MachObj_tlv_bootstrap();
2046+
MachObj_reftoident(tvseg, tvsegdata.SDbuf.length(), stlv_bootstrap, 0, CFoff | CFoffset64);
2047+
2048+
// 2. null pointer
2049+
MachObj_write_zeros(tvsegdata, 8);
2050+
2051+
// 3. pointer to _ident$tlv$init in the __thread_data section
2052+
MachObj_reftoident(tvseg, tvsegdata.SDbuf.length(), si, 0, CFoff | CFoffset64);
2053+
2054+
assert((tvsegdata.SDbuf.length() % 24) == 0);
2055+
return si.Sseg;
2056+
}
19792057

19802058
/*********************************
19812059
* Define segments for Thread Local Storage.
@@ -2223,7 +2301,7 @@ void MachObj_pubdefsize(int seg, Symbol* s, targ_size_t offset, targ_size_t syms
22232301
void MachObj_pubdef(int seg, Symbol* s, targ_size_t offset)
22242302
{
22252303
//printf("MachObj_pubdef(%d:x%llx s=%p, %s)\n", seg, offset, s, s.Sident.ptr);
2226-
//symbol_print(s);
2304+
//symbol_print(*s);
22272305
symbol_debug(s);
22282306

22292307
s.Soffset = offset;

0 commit comments

Comments
 (0)