@@ -869,10 +869,24 @@ void Writer::createInitMemoryFunction() {
869
869
LLVM_DEBUG (dbgs () << " createInitMemoryFunction\n " );
870
870
assert (WasmSym::initMemoryFlag);
871
871
uint64_t flagAddress = WasmSym::initMemoryFlag->getVirtualAddress ();
872
+ bool is64 = config->is64 .getValueOr (false );
872
873
std::string bodyContent;
873
874
{
874
875
raw_string_ostream os (bodyContent);
875
- writeUleb128 (os, 0 , " num locals" );
876
+ // With PIC code we cache the flag address in local 0
877
+ if (config->isPic ) {
878
+ writeUleb128 (os, 1 , " num local decls" );
879
+ writeUleb128 (os, 1 , " local count" );
880
+ writeU8 (os, is64 ? WASM_TYPE_I64 : WASM_TYPE_I32, " address type" );
881
+ writeU8 (os, WASM_OPCODE_GLOBAL_GET, " GLOBAL_GET" );
882
+ writeUleb128 (os, WasmSym::memoryBase->getGlobalIndex (), " memory_base" );
883
+ writePtrConst (os, flagAddress, is64, " flag address" );
884
+ writeU8 (os, WASM_OPCODE_I32_ADD, " add" );
885
+ writeU8 (os, WASM_OPCODE_LOCAL_SET, " local.set" );
886
+ writeUleb128 (os, 0 , " local 0" );
887
+ } else {
888
+ writeUleb128 (os, 0 , " num locals" );
889
+ }
876
890
877
891
if (hasPassiveInitializedSegments ()) {
878
892
// Initialize memory in a thread-safe manner. The thread that successfully
@@ -916,11 +930,24 @@ void Writer::createInitMemoryFunction() {
916
930
// )
917
931
// ( ... drop data segments ... )
918
932
// )
933
+ //
934
+ // When we are building with PIC, calculate the flag location using:
935
+ //
936
+ // (global.get $__memory_base)
937
+ // (i32.const $__init_memory_flag)
938
+ // (i32.const 1)
919
939
920
- bool is64 = config->is64 .getValueOr (false );
940
+ auto writeGetFlagAddress = [&]() {
941
+ if (config->isPic ) {
942
+ writeU8 (os, WASM_OPCODE_LOCAL_GET, " local.get" );
943
+ writeUleb128 (os, 0 , " local 0" );
944
+ } else {
945
+ writePtrConst (os, flagAddress, is64, " flag address" );
946
+ }
947
+ };
921
948
922
949
// Atomically check whether this is the main thread.
923
- writePtrConst (os, flagAddress, is64, " flag address " );
950
+ writeGetFlagAddress ( );
924
951
writeI32Const (os, 0 , " expected flag value" );
925
952
writeI32Const (os, 1 , " flag value" );
926
953
writeU8 (os, WASM_OPCODE_ATOMICS_PREFIX, " atomics prefix" );
@@ -930,7 +957,7 @@ void Writer::createInitMemoryFunction() {
930
957
writeU8 (os, WASM_TYPE_NORESULT, " blocktype" );
931
958
932
959
// Did not increment 0, so wait for main thread to initialize memory
933
- writePtrConst (os, flagAddress, is64, " flag address " );
960
+ writeGetFlagAddress ( );
934
961
writeI32Const (os, 1 , " expected flag value" );
935
962
writeI64Const (os, -1 , " timeout" );
936
963
@@ -946,6 +973,12 @@ void Writer::createInitMemoryFunction() {
946
973
if (needsPassiveInitialization (s)) {
947
974
// destination address
948
975
writePtrConst (os, s->startVA , is64, " destination address" );
976
+ if (config->isPic ) {
977
+ writeU8 (os, WASM_OPCODE_GLOBAL_GET, " GLOBAL_GET" );
978
+ writeUleb128 (os, WasmSym::memoryBase->getGlobalIndex (),
979
+ " memory_base" );
980
+ writeU8 (os, WASM_OPCODE_I32_ADD, " i32.add" );
981
+ }
949
982
// source segment offset
950
983
writeI32Const (os, 0 , " segment offset" );
951
984
// memory region size
@@ -959,14 +992,14 @@ void Writer::createInitMemoryFunction() {
959
992
}
960
993
961
994
// Set flag to 2 to mark end of initialization
962
- writePtrConst (os, flagAddress, is64, " flag address " );
995
+ writeGetFlagAddress ( );
963
996
writeI32Const (os, 2 , " flag value" );
964
997
writeU8 (os, WASM_OPCODE_ATOMICS_PREFIX, " atomics prefix" );
965
998
writeUleb128 (os, WASM_OPCODE_I32_ATOMIC_STORE, " i32.atomic.store" );
966
999
writeMemArg (os, 2 , 0 );
967
1000
968
1001
// Notify any waiters that memory initialization is complete
969
- writePtrConst (os, flagAddress, is64, " flag address " );
1002
+ writeGetFlagAddress ( );
970
1003
writeI32Const (os, -1 , " number of waiters" );
971
1004
writeU8 (os, WASM_OPCODE_ATOMICS_PREFIX, " atomics prefix" );
972
1005
writeUleb128 (os, WASM_OPCODE_ATOMIC_NOTIFY, " atomic.notify" );
@@ -1095,9 +1128,6 @@ void Writer::createCommandExportWrapper(uint32_t functionIndex,
1095
1128
}
1096
1129
1097
1130
void Writer::createInitTLSFunction () {
1098
- if (!WasmSym::initTLS->isLive ())
1099
- return ;
1100
-
1101
1131
std::string bodyContent;
1102
1132
{
1103
1133
raw_string_ostream os (bodyContent);
@@ -1244,7 +1274,7 @@ void Writer::run() {
1244
1274
}
1245
1275
}
1246
1276
1247
- if (!config-> relocatable && config-> sharedMemory && !config-> shared )
1277
+ if (WasmSym::initTLS && WasmSym::initTLS-> isLive () )
1248
1278
createInitTLSFunction ();
1249
1279
1250
1280
if (errorCount ())
0 commit comments