@@ -218,6 +218,7 @@ void Writer::writeSections() {
218
218
}
219
219
220
220
static void setGlobalPtr (DefinedGlobal *g, uint64_t memoryPtr) {
221
+ LLVM_DEBUG (dbgs () << " setGlobalPtr " << g->getName () << " -> " << memoryPtr << " \n " );
221
222
g->global ->setPointerValue (memoryPtr);
222
223
}
223
224
@@ -276,13 +277,15 @@ void Writer::layoutMemory() {
276
277
memoryPtr, seg->size , seg->alignment ));
277
278
278
279
if (!config->relocatable && seg->isTLS ()) {
279
- if (config-> sharedMemory ) {
280
+ if (WasmSym::tlsSize ) {
280
281
auto *tlsSize = cast<DefinedGlobal>(WasmSym::tlsSize);
281
282
setGlobalPtr (tlsSize, seg->size );
282
-
283
+ }
284
+ if (WasmSym::tlsAlign) {
283
285
auto *tlsAlign = cast<DefinedGlobal>(WasmSym::tlsAlign);
284
286
setGlobalPtr (tlsAlign, int64_t {1 } << seg->alignment );
285
- } else if (WasmSym::tlsBase) {
287
+ }
288
+ if (!config->sharedMemory && WasmSym::tlsBase) {
286
289
auto *tlsBase = cast<DefinedGlobal>(WasmSym::tlsBase);
287
290
setGlobalPtr (tlsBase, memoryPtr);
288
291
}
@@ -970,9 +973,6 @@ static void createFunction(DefinedFunction *func, StringRef bodyContent) {
970
973
}
971
974
972
975
bool Writer::needsPassiveInitialization (const OutputSegment *segment) {
973
- // TLS segments are initialized separately
974
- if (segment->isTLS ())
975
- return false ;
976
976
// If bulk memory features is supported then we can perform bss initialization
977
977
// (via memory.fill) during `__wasm_init_memory`.
978
978
if (config->importMemory && !segment->requiredInBinary ())
@@ -1002,6 +1002,11 @@ void Writer::createSyntheticInitFunctions() {
1002
1002
" __wasm_init_memory" , WASM_SYMBOL_VISIBILITY_HIDDEN,
1003
1003
make<SyntheticFunction>(nullSignature, " __wasm_init_memory" ));
1004
1004
WasmSym::initMemory->markLive ();
1005
+ if (config->sharedMemory ) {
1006
+ // This global is assigned during __wasm_init_memory in the shared memory
1007
+ // case.
1008
+ WasmSym::tlsBase->markLive ();
1009
+ }
1005
1010
}
1006
1011
1007
1012
if (config->sharedMemory && out.globalSec ->needsTLSRelocations ()) {
@@ -1126,7 +1131,7 @@ void Writer::createInitMemoryFunction() {
1126
1131
// With PIC code we cache the flag address in local 0
1127
1132
if (config->isPic ) {
1128
1133
writeUleb128 (os, 1 , " num local decls" );
1129
- writeUleb128 (os, 1 , " local count" );
1134
+ writeUleb128 (os, 2 , " local count" );
1130
1135
writeU8 (os, is64 ? WASM_TYPE_I64 : WASM_TYPE_I32, " address type" );
1131
1136
writeU8 (os, WASM_OPCODE_GLOBAL_GET, " GLOBAL_GET" );
1132
1137
writeUleb128 (os, WasmSym::memoryBase->getGlobalIndex (), " memory_base" );
@@ -1177,10 +1182,31 @@ void Writer::createInitMemoryFunction() {
1177
1182
if (config->isPic ) {
1178
1183
writeU8 (os, WASM_OPCODE_GLOBAL_GET, " GLOBAL_GET" );
1179
1184
writeUleb128 (os, WasmSym::memoryBase->getGlobalIndex (),
1180
- " memory_base " );
1185
+ " __memory_base " );
1181
1186
writeU8 (os, is64 ? WASM_OPCODE_I64_ADD : WASM_OPCODE_I32_ADD,
1182
1187
" i32.add" );
1183
1188
}
1189
+
1190
+ // When we initialize the TLS segment we also set the `__tls_base`
1191
+ // global. This allows the runtime to use this static copy of the
1192
+ // TLS data for the first/main thread.
1193
+ if (config->sharedMemory && s->isTLS ()) {
1194
+ if (config->isPic ) {
1195
+ // Cache the result of the addionion in local 0
1196
+ writeU8 (os, WASM_OPCODE_LOCAL_TEE, " local.tee" );
1197
+ writeUleb128 (os, 1 , " local 1" );
1198
+ } else {
1199
+ writePtrConst (os, s->startVA , is64, " destination address" );
1200
+ }
1201
+ writeU8 (os, WASM_OPCODE_GLOBAL_SET, " GLOBAL_SET" );
1202
+ writeUleb128 (os, WasmSym::tlsBase->getGlobalIndex (),
1203
+ " __tls_base" );
1204
+ if (config->isPic ) {
1205
+ writeU8 (os, WASM_OPCODE_LOCAL_GET, " local.tee" );
1206
+ writeUleb128 (os, 1 , " local 1" );
1207
+ }
1208
+ }
1209
+
1184
1210
if (s->isBss ) {
1185
1211
writeI32Const (os, 0 , " fill value" );
1186
1212
writeI32Const (os, s->size , " memory region size" );
@@ -1243,6 +1269,10 @@ void Writer::createInitMemoryFunction() {
1243
1269
1244
1270
for (const OutputSegment *s : segments) {
1245
1271
if (needsPassiveInitialization (s) && !s->isBss ) {
1272
+ // The TLS region should not be dropped since its is needed
1273
+ // during the intiailizing of each thread (__wasm_init_tls).
1274
+ if (config->sharedMemory && s->isTLS ())
1275
+ continue ;
1246
1276
// data.drop instruction
1247
1277
writeU8 (os, WASM_OPCODE_MISC_PREFIX, " bulk-memory prefix" );
1248
1278
writeUleb128 (os, WASM_OPCODE_DATA_DROP, " data.drop" );
@@ -1440,7 +1470,6 @@ void Writer::createInitTLSFunction() {
1440
1470
1441
1471
writeU8 (os, WASM_OPCODE_GLOBAL_SET, " global.set" );
1442
1472
writeUleb128 (os, WasmSym::tlsBase->getGlobalIndex (), " global index" );
1443
- WasmSym::tlsBase->markLive ();
1444
1473
1445
1474
// FIXME(wvo): this local needs to be I64 in wasm64, or we need an extend op.
1446
1475
writeU8 (os, WASM_OPCODE_LOCAL_GET, " local.get" );
@@ -1623,8 +1652,10 @@ void Writer::run() {
1623
1652
}
1624
1653
}
1625
1654
1626
- if (WasmSym::initTLS && WasmSym::initTLS->isLive ())
1655
+ if (WasmSym::initTLS && WasmSym::initTLS->isLive ()) {
1656
+ log (" -- createInitTLSFunction" );
1627
1657
createInitTLSFunction ();
1658
+ }
1628
1659
1629
1660
if (errorCount ())
1630
1661
return ;
0 commit comments