Avoid using RELOCATABLE by default when building with MAIN_MODULE
By building main module as non-relocatable we can improve the code size
and performance of the main module. There is no good reason to build
the main module as relocatable, only the side module really need this.
One downside is that this reduces our coverage of the `RELOCATABLE`
option to just a few isolated test cases. I wonder if we should consider
removing this option unless there are other compelling use cases?
This change depends and llvm-side change: https://reviews.llvm.org/D91577
diff --git a/emcc.py b/emcc.py
index 34df446..8d3473b 100755
--- a/emcc.py
+++ b/emcc.py
@@ -698,7 +698,7 @@
# on the dynamic linker to create them on the fly.
# TODO(sbc): Integrate with metadata['invokeFuncs'] that comes from the
# main module to avoid creating new invoke functions at runtime.
- imports = set(i for i in imports if not i.startswith('invoke_'))
+ imports = set(i for i in imports if not i.startswith('invoke_') and i not in ('__memory_base',))
weak_imports = imports.intersection(exports)
strong_imports = imports.difference(exports)
logger.debug('Adding symbols requirements from `%s`: %s', dylib, imports)
@@ -850,9 +850,12 @@
if settings.INLINING_LIMIT:
cflags.append('-fno-inline-functions')
- if settings.RELOCATABLE and '-fPIC' not in user_args:
+ if (settings.RELOCATABLE or settings.MAIN_MODULE) and '-fPIC' not in user_args:
cflags.append('-fPIC')
+ if settings.MAIN_MODULE:
+ cflags.append('-mmutable-globals')
+
# We use default visiibilty=default in emscripten even though the upstream
# backend defaults visibility=hidden. This matched the expectations of C/C++
# code in the wild which expects undecorated symbols to be exported to other
@@ -1419,7 +1422,7 @@
'unused-command-line-argument',
"compiler flag ignored during linking: '%s'" % arg)
- if settings.MAIN_MODULE or settings.SIDE_MODULE:
+ if settings.SIDE_MODULE:
settings.RELOCATABLE = 1
# Pthreads and Wasm Workers require targeting shared Wasm memory (SAB).
@@ -1472,14 +1475,13 @@
def setup_pthreads(target):
- if settings.RELOCATABLE:
- # phtreads + dyanmic linking has certain limitations
- if settings.SIDE_MODULE:
- diagnostics.warning('experimental', '-s SIDE_MODULE + pthreads is experimental')
- elif settings.MAIN_MODULE:
- diagnostics.warning('experimental', '-s MAIN_MODULE + pthreads is experimental')
- elif settings.LINKABLE:
- diagnostics.warning('experimental', '-s LINKABLE + pthreads is experimental')
+ # phtreads + dyanmic linking has certain limitations
+ if settings.SIDE_MODULE:
+ diagnostics.warning('experimental', '-s SIDE_MODULE + pthreads is experimental')
+ elif settings.MAIN_MODULE:
+ diagnostics.warning('experimental', '-s MAIN_MODULE + pthreads is experimental')
+ elif settings.LINKABLE:
+ diagnostics.warning('experimental', '-s LINKABLE + pthreads is experimental')
if settings.ALLOW_MEMORY_GROWTH:
diagnostics.warning('pthreads-mem-growth', 'USE_PTHREADS + ALLOW_MEMORY_GROWTH may run non-wasm code slowly, see https://github.com/WebAssembly/design/issues/1271')
@@ -1817,7 +1819,7 @@
assert not settings.SIDE_MODULE
if settings.MAIN_MODULE == 1:
settings.INCLUDE_FULL_LIBRARY = 1
- settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$preloadDylibs']
+ settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$loadDylibDeps']
elif settings.SIDE_MODULE:
assert not settings.MAIN_MODULE
# memory init file is not supported with side modules, must be executable synchronously (for dlopen)
@@ -1835,28 +1837,38 @@
if settings.LINKABLE and settings.USER_EXPORTED_FUNCTIONS:
diagnostics.warning('unused-command-line-argument', 'EXPORTED_FUNCTIONS is not valid with LINKABLE set (normally due to SIDE_MODULE=1/MAIN_MODULE=1) since all functions are exported this mode. To export only a subset use SIDE_MODULE=2/MAIN_MODULE=2')
- if settings.MAIN_MODULE:
- settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += [
- '$getDylinkMetadata',
- '$mergeLibSymbols',
- ]
-
if settings.USE_PTHREADS:
settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += [
'$registerTlsInit',
]
- if settings.RELOCATABLE:
+ if settings.RELOCATABLE or settings.MAIN_MODULE:
+ settings.SUPPORT_DYLINK = 1
+
+ if settings.SUPPORT_DYLINK:
settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += [
'$reportUndefinedSymbols',
'$relocateExports',
+ '$normalizeExports',
+ '$updateGOT',
'$GOTHandler',
- '__heap_base',
- '__stack_pointer',
+ ]
+
+ if settings.MAIN_MODULE:
+ settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += [
+ '$getDylinkMetadata',
+ '$mergeLibSymbols',
]
# Unconditional dependency in library_dylink.js
- settings.REQUIRED_EXPORTS += ['setThrew']
+ settings.REQUIRED_EXPORTS += [
+ '_emscripten_sbrk_addr',
+ 'setThrew',
+ '__stack_pointer',
+ '__heap_base'
+ ]
+ default_setting(user_settings, 'ALLOW_TABLE_GROWTH', 1)
+ if settings.RELOCATABLE:
if settings.MINIMAL_RUNTIME:
exit_with_error('MINIMAL_RUNTIME is not compatible with relocatable output')
if settings.WASM2JS:
@@ -2394,7 +2406,7 @@
# by SAFE_HEAP as a null pointer dereference.
exit_with_error('ASan does not work with SAFE_HEAP')
- if settings.RELOCATABLE:
+ if settings.SUPPORT_DYLINK:
exit_with_error('ASan does not support dynamic linking')
if sanitize and settings.GENERATE_SOURCE_MAP:
@@ -2416,7 +2428,7 @@
settings.REQUIRED_EXPORTS += ['__funcs_on_exit']
# various settings require malloc/free support from JS
- if settings.RELOCATABLE or \
+ if settings.MAIN_MODULE or \
settings.BUILD_AS_WORKER or \
settings.USE_WEBGPU or \
settings.USE_PTHREADS or \
@@ -2535,7 +2547,7 @@
# Export tag objects which are likely needed by the native code, but which are
# currently not reported in the metadata of wasm-emscripten-finalize
- if settings.RELOCATABLE:
+ if settings.MAIN_MODULE:
if settings.EXCEPTION_HANDLING:
settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE.append('__cpp_exception')
if settings.SUPPORT_LONGJMP == 'wasm':
diff --git a/emscripten.py b/emscripten.py
index cd0c27d..b3934f4 100644
--- a/emscripten.py
+++ b/emscripten.py
@@ -212,8 +212,7 @@
# PROXY_TO_PTHREAD only makes sense with a main(), so error if one is
# missing. note that when main() might arrive from another module we cannot
# error here.
- if settings.PROXY_TO_PTHREAD and '_main' not in defined_symbols and \
- not settings.RELOCATABLE:
+ if settings.PROXY_TO_PTHREAD and '_main' not in defined_symbols and not settings.SUPPORT_DYLINK:
exit_with_error('PROXY_TO_PTHREAD proxies main() for you, but no main exists')
if settings.IGNORE_MISSING_MAIN:
@@ -495,7 +494,7 @@
# When we dynamically link our JS loader adds functions from wasm modules to
# the table. It must add the original versions of them, not legalized ones,
# so that indirect calls have the right type, so export those.
- if settings.RELOCATABLE:
+ if settings.SUPPORT_DYLINK:
args.append('--pass-arg=legalize-js-interface-export-originals')
modify_wasm = True
else:
@@ -608,6 +607,8 @@
if settings.RELOCATABLE:
send_items_map['__indirect_function_table'] = 'wasmTable'
+
+ if settings.MAIN_MODULE:
if settings.EXCEPTION_HANDLING:
send_items_map['__cpp_exception'] = '___cpp_exception'
if settings.SUPPORT_LONGJMP == 'wasm':
diff --git a/src/jsifier.js b/src/jsifier.js
index 3cf4fd7..5cab4fc 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -174,7 +174,7 @@
warn('To build in STANDALONE_WASM mode without a main(), use emcc --no-entry');
}
}
- if (!RELOCATABLE) {
+ if (!MAIN_MODULE) {
// emit a stub that will fail at runtime
LibraryManager.library[ident] = new Function(`err('missing function: ${ident}'); abort(-1);`);
// We have already warned/errored about this function, so for the purposes of Closure use, mute all type checks
diff --git a/src/library.js b/src/library.js
index 8eddff6..858452a 100644
--- a/src/library.js
+++ b/src/library.js
@@ -3509,6 +3509,8 @@
// global, basically).
__heap_base: '{{{ to64(HEAP_BASE) }}}',
__heap_base__import: true,
+#endif
+
#if EXCEPTION_HANDLING
// In dynamic linking we define tags here and feed them to each module
__cpp_exception: "new WebAssembly.Tag({'parameters': ['{{{ POINTER_TYPE }}}']})",
@@ -3518,7 +3520,6 @@
__c_longjmp: "new WebAssembly.Tag({'parameters': ['{{{ POINTER_TYPE }}}']})",
__c_longjmp_import: true,
#endif
-#endif
};
function autoAddDeps(object, name) {
diff --git a/src/library_dylink.js b/src/library_dylink.js
index e71ceb1..edd17bc 100644
--- a/src/library_dylink.js
+++ b/src/library_dylink.js
@@ -6,7 +6,7 @@
var dlopenMissingError = "'To use dlopen, you need enable dynamic linking, see https://github.com/emscripten-core/emscripten/wiki/Linking'"
var LibraryDylink = {
-#if RELOCATABLE
+#if SUPPORT_DYLINK
$resolveGlobalSymbol__internal: true,
$resolveGlobalSymbol__deps: ['$asmjsMangle'],
$resolveGlobalSymbol: function(symName, direct) {
@@ -65,6 +65,9 @@
$isInternalSym: function(symName) {
// TODO: find a way to mark these in the binary or avoid exporting them.
return [
+ 'memory',
+ '__indirect_function_table',
+ '__stack_pointer',
'__cpp_exception',
'__c_longjmp',
'__wasm_apply_data_relocs',
@@ -85,6 +88,7 @@
$updateGOT__internal: true,
$updateGOT__deps: ['$GOT', '$isInternalSym'],
+ $updateGOT__docs: '/** @param {boolean=} replace */',
$updateGOT: function(exports, replace) {
#if DYLINK_DEBUG
err("updateGOT: adding " + Object.keys(exports).length + " symbols");
@@ -136,13 +140,26 @@
#endif
},
+ $normalizeExports__internal: true,
+ $normalizeExports: function(exports) {
+ var normalized = {}
+ for (var e in exports) {
+ var value = exports[e];
+ if (!isInternalSym(e) && typeof value == 'object' && typeof value.value != 'undefined') {
+ // a breaking change in the wasm spec, globals are now objects
+ // https://github.com/WebAssembly/mutable-global/issues/1
+ normalized[e] = value.value;
+ } else {
+ normalized[e] = value;
+ }
+ }
+ return normalized;
+ },
+
// Applies relocations to exported things.
$relocateExports__internal: true,
- $relocateExports__deps: ['$updateGOT'],
- $relocateExports__docs: '/** @param {boolean=} replace */',
- $relocateExports: function(exports, memoryBase, replace) {
+ $relocateExports: function(exports, memoryBase) {
var relocated = {};
-
for (var e in exports) {
var value = exports[e];
#if SPLIT_MODULE
@@ -152,17 +169,8 @@
continue;
}
#endif
- if (typeof value == 'object') {
- // a breaking change in the wasm spec, globals are now objects
- // https://github.com/WebAssembly/mutable-global/issues/1
- value = value.value;
- }
- if (typeof value == 'number') {
- value += memoryBase;
- }
- relocated[e] = value;
+ relocated[e] = typeof value == 'number' ? value + memoryBase : value;
}
- updateGOT(relocated, replace);
return relocated;
},
@@ -198,7 +206,7 @@
err('done reportUndefinedSymbols');
#endif
},
-#endif
+#endif // SUPPORT_DYLINK
#if !MAIN_MODULE
#if !ALLOW_UNIMPLEMENTED_SYSCALLS
@@ -271,7 +279,7 @@
// use normally malloc from the main program to do these allocations).
// Allocate memory even if malloc isn't ready yet.
- $getMemory__deps: ['$GOT', '__heap_base'],
+ $getMemory__deps: ['$GOT', '__heap_base', '_emscripten_sbrk_addr'],
$getMemory: function(size) {
// After the runtime is initialized, we must only use sbrk() normally.
#if DYLINK_DEBUG
@@ -279,20 +287,30 @@
#endif
if (runtimeInitialized)
return _malloc(size);
+
var ret = ___heap_base;
var end = (ret + size + 15) & -16;
#if ASSERTIONS
assert(end <= HEAP8.length, 'failure to getMemory - memory growth etc. is not supported there, call malloc/sbrk directly or increase INITIAL_MEMORY');
#endif
+#if USE_PTHREADS
+ if (!ENVIRONMENT_IS_PTHREAD) {
+#endif
+#if DYLINK_DEBUG
+ err('__emscripten_sbrk_addr[' + __emscripten_sbrk_addr + '] : ' + ret + ' -> ' + end);
+#endif
+ {{{ makeSetValue('__emscripten_sbrk_addr', '0', 'end', POINTER_TYPE) }}};
+#if USE_PTHREADS
+ }
+#endif
___heap_base = end;
- GOT['__heap_base'].value = end;
return ret;
},
// returns the side module metadata as an object
// { memorySize, memoryAlign, tableSize, tableAlign, neededDynlibs}
$getDylinkMetadata__internal: true,
- $getDylinkMetadata: function(binary) {
+ $getDylinkMetadata: function(binary, optional = false) {
var offset = 0;
var end = 0;
@@ -330,6 +348,9 @@
name = 'dylink'
dylinkSection = WebAssembly.Module.customSections(binary, name);
}
+ if (!dylinkSection.length && optional) {
+ return undefined;
+ }
failIf(dylinkSection.length === 0, 'need dylink section');
binary = new Uint8Array(dylinkSection[0]);
end = binary.length
@@ -420,7 +441,7 @@
$mergeLibSymbols: function(exports, libName) {
// add symbols into global namespace TODO: weak linking etc.
for (var sym in exports) {
- if (!exports.hasOwnProperty(sym)) {
+ if (!Object.prototype.hasOwnProperty.call(exports, sym)) {
continue;
}
@@ -463,8 +484,9 @@
$loadWebAssemblyModule__docs: '/** @param {number=} handle */',
$loadWebAssemblyModule__deps: [
'$loadDynamicLibrary', '$createInvokeFunction', '$getMemory',
- '$relocateExports', '$resolveGlobalSymbol', '$GOTHandler',
+ '$normalizeExports', '$relocateExports', '$resolveGlobalSymbol', '$GOTHandler',
'$getDylinkMetadata', '$alignMemory', '$zeroMemory',
+ '$updateGOT',
],
$loadWebAssemblyModule: function(binary, flags, handle) {
var metadata = getDylinkMetadata(binary);
@@ -582,7 +604,9 @@
#endif
// add new entries to functionsInTableMap
updateTableMap(tableBase, metadata.tableSize);
- moduleExports = relocateExports(instance.exports, memoryBase);
+ moduleExports = normalizeExports(instance.exports);
+ moduleExports = relocateExports(moduleExports, memoryBase);
+ updateGOT(moduleExports);
if (!flags.allowUndefined) {
reportUndefinedSymbols();
}
@@ -791,32 +815,36 @@
return true;
},
- $preloadDylibs__internal: true,
- $preloadDylibs__deps: ['$loadDynamicLibrary', '$reportUndefinedSymbols'],
- $preloadDylibs: function() {
+ $loadDylibDeps__internal: true,
+ $loadDylibDeps__deps: ['$loadDynamicLibrary', '$reportUndefinedSymbols'],
+ $loadDylibDeps: function() {
#if DYLINK_DEBUG
- err('preloadDylibs');
+ err('loadDylibDeps');
#endif
if (!dynamicLibraries.length) {
#if DYLINK_DEBUG
- err('preloadDylibs: no libraries to preload');
+ err('loadDylibDeps: no libraries to preload');
#endif
+#if !USE_PTHREADS
reportUndefinedSymbols();
+#endif
return;
}
// Load binaries asynchronously
- addRunDependency('preloadDylibs');
+ addRunDependency('loadDylibDeps');
dynamicLibraries.reduce(function(chain, lib) {
return chain.then(function() {
return loadDynamicLibrary(lib, {loadAsync: true, global: true, nodelete: true, allowUndefined: true});
});
}, Promise.resolve()).then(function() {
// we got them all, wonderful
+#if !USE_PTHREADS
reportUndefinedSymbols();
- removeRunDependency('preloadDylibs');
+#endif
+ removeRunDependency('loadDylibDeps');
#if DYLINK_DEBUG
- err('preloadDylibs done!');
+ err('loadDylibDeps done!');
#endif
});
},
diff --git a/src/library_pthread.js b/src/library_pthread.js
index 780407f..1085f6c 100644
--- a/src/library_pthread.js
+++ b/src/library_pthread.js
@@ -37,6 +37,9 @@
#if !MINIMAL_RUNTIME
'$handleException',
#endif
+#if SUPPORT_DYLINK
+ '$reportUndefinedSymbols',
+#endif
],
$PThread: {
// Contains all Workers that are idle/unused and not currently hosting an
@@ -240,6 +243,11 @@
for (var i in PThread.tlsInitFunctions) {
if (PThread.tlsInitFunctions.hasOwnProperty(i)) PThread.tlsInitFunctions[i]();
}
+#if SUPPORT_DYLINK
+ // Until TLS initializtion is done we could have can have TLS symbols
+ // with address zero.
+ reportUndefinedSymbols();
+#endif
},
// Loads the WebAssembly module into the given list of Workers.
// onFinishedLoading: A callback function that will be called once all of
@@ -510,6 +518,7 @@
},
#if MAIN_MODULE
+ $registerTlsInit__deps: ['$relocateExports', '$normalizeExports', '$updateGOT'],
$registerTlsInit: function(tlsInitFunc, moduleExports, metadata) {
#if DYLINK_DEBUG
err("registerTlsInit: " + tlsInitFunc);
@@ -532,7 +541,9 @@
for (var sym in metadata.tlsExports) {
metadata.tlsExports[sym] = moduleExports[sym];
}
- relocateExports(metadata.tlsExports, __tls_base, /*replace=*/true);
+ var normalized = normalizeExports(metadata.tlsExports);
+ var relocated = relocateExports(normalized, __tls_base);
+ updateGOT(relocated, /*replace=*/true);
}
// Register this function so that its gets called for each thread on
diff --git a/src/postamble.js b/src/postamble.js
index 6d814b3..b6107e4 100644
--- a/src/postamble.js
+++ b/src/postamble.js
@@ -209,7 +209,12 @@
#endif // HAS_MAIN
#if STACK_OVERFLOW_CHECK
+var doneStackCheckInit = false;
function stackCheckInit() {
+ if (doneStackCheckInit)
+ return false;
+ doneStackCheckInit = true;
+ //err("stackCheckInit");
// This is normally called automatically during __wasm_call_ctors but need to
// get these values before even running any of the ctors so we call it redundantly
// here.
@@ -223,7 +228,7 @@
}
#endif
-#if RELOCATABLE
+#if MAIN_MODULE
var dylibsLoaded = false;
#endif
@@ -242,25 +247,23 @@
stackCheckInit();
#endif
-#if RELOCATABLE
- if (!dylibsLoaded) {
- // Loading of dynamic libraries needs to happen on each thread, so we can't
- // use the normal __ATPRERUN__ mechanism.
#if MAIN_MODULE
- preloadDylibs();
-#else
- reportUndefinedSymbols();
-#endif
+ if (!dylibsLoaded) {
+ // Loading of dynamic libraries needs to happen on each thread, so we can't
+ // use the normal __ATPRERUN__ mechanism.
+ loadDylibDeps();
dylibsLoaded = true;
// Loading dylibs can add run dependencies.
if (runDependencies > 0) {
#if RUNTIME_LOGGING
- err('preloadDylibs added run() dependencies, not running yet');
+ err('loadDylibDeps added run() dependencies, not running yet');
#endif
return;
}
}
+#elif RELOCATABLE
+ reportUndefinedSymbols();
#endif
#if WASM_WORKERS
diff --git a/src/preamble.js b/src/preamble.js
index de8610b..0997cdd 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -19,7 +19,7 @@
out = err = () => {};
#endif
-#if RELOCATABLE
+#if MAIN_MODULE
{{{ makeModuleReceiveWithVar('dynamicLibraries', undefined, '[]', true) }}}
#endif
@@ -373,8 +373,8 @@
#endif
#if STACK_OVERFLOW_CHECK >= 2
-#if RUNTIME_LOGGING
err('__set_stack_limits: ' + _emscripten_stack_get_base() + ', ' + _emscripten_stack_get_end());
+#if RUNTIME_LOGGING
#endif
___set_stack_limits(_emscripten_stack_get_base(), _emscripten_stack_get_end());
#endif
@@ -992,7 +992,7 @@
#if SPLIT_MODULE
'placeholder': new Proxy({}, splitModuleProxyHandler),
#endif
-#if RELOCATABLE
+#if MAIN_MODULE || RELOCATABLE
'GOT.mem': new Proxy(asmLibraryArg, GOTHandler),
'GOT.func': new Proxy(asmLibraryArg, GOTHandler),
#endif
@@ -1004,9 +1004,21 @@
function receiveInstance(instance, module) {
var exports = instance.exports;
+#if !RELOCATABLE
+ Module['asm'] = exports;
+ wasmTable = Module['asm']['__indirect_function_table'];
+#if ASSERTIONS && !PURE_WASI
+ assert(wasmTable, "table not found in wasm exports");
+#endif
+#endif
+
+#if MAIN_MODULE || RELOCATABLE
+ exports = normalizeExports(exports);
#if RELOCATABLE
exports = relocateExports(exports, {{{ GLOBAL_BASE }}});
#endif
+ updateGOT(exports);
+#endif
#if MEMORY64
exports = instrumentWasmExportsForMemory64(exports);
@@ -1023,9 +1035,9 @@
Module['asm'] = exports;
#if MAIN_MODULE
- var metadata = getDylinkMetadata(module);
+ var metadata = getDylinkMetadata(module, true);
#if AUTOLOAD_DYLIBS
- if (metadata.neededDynlibs) {
+ if (metadata && metadata.neededDynlibs) {
dynamicLibraries = metadata.neededDynlibs.concat(dynamicLibraries);
}
#endif
@@ -1055,13 +1067,6 @@
runMemoryInitializer();
#endif
-#if !RELOCATABLE
- wasmTable = Module['asm']['__indirect_function_table'];
-#if ASSERTIONS && !PURE_WASI
- assert(wasmTable, "table not found in wasm exports");
-#endif
-#endif
-
#if hasExportedFunction('___wasm_call_ctors')
addOnInit(Module['asm']['__wasm_call_ctors']);
#endif
@@ -1138,7 +1143,7 @@
assert(Module === trueModule, 'the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?');
trueModule = null;
#endif
-#if SHARED_MEMORY || RELOCATABLE
+#if SHARED_MEMORY || SUPPORT_DYLINK
receiveInstance(result['instance'], result['module']);
#else
// TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193, the above line no longer optimizes out down to the following line.
diff --git a/src/settings_internal.js b/src/settings_internal.js
index 61dec1c..a6d8641 100644
--- a/src/settings_internal.js
+++ b/src/settings_internal.js
@@ -231,3 +231,5 @@
// A copy of the default the default INCOMING_MODULE_JS_API. (Soon to
// include additional items).
var ALL_INCOMING_MODULE_JS_API = []
+
+var SUPPORT_DYLINK = 0;
diff --git a/system/lib/sbrk.c b/system/lib/sbrk.c
index 13a9428..e001a79 100644
--- a/system/lib/sbrk.c
+++ b/system/lib/sbrk.c
@@ -31,7 +31,7 @@
extern size_t __heap_base;
-static uintptr_t sbrk_val = (uintptr_t)&__heap_base;
+uintptr_t _emscripten_sbrk_addr = (uintptr_t)&__heap_base;
uintptr_t* emscripten_get_sbrk_ptr() {
#ifdef __PIC__
@@ -39,12 +39,12 @@
// potentially *before* the setup of the dynamically-linked __heap_base, when
// using SAFE_HEAP. (SAFE_HEAP instruments *all* memory accesses, so even the
// code doing dynamic linking itself ends up instrumented, which is why we can
- // get such an instrumented call before sbrk_val has its proper value.)
- if (sbrk_val == 0) {
- sbrk_val = (uintptr_t)&__heap_base;
+ // get such an instrumented call before _emscripten_sbrk_addr has its proper value.)
+ if (_emscripten_sbrk_addr == 0) {
+ _emscripten_sbrk_addr = (uintptr_t)&__heap_base;
}
#endif
- return &sbrk_val;
+ return &_emscripten_sbrk_addr;
}
void *sbrk(intptr_t increment_) {
diff --git a/tests/core/test_dlfcn_self.exports b/tests/core/test_dlfcn_self.exports
index 9dc3e6a..bc1adb8 100644
--- a/tests/core/test_dlfcn_self.exports
+++ b/tests/core/test_dlfcn_self.exports
@@ -1,6 +1,7 @@
__THREW__
___environ
__environ
+__heap_base
__optpos
__optreset
__progname
@@ -8,7 +9,9 @@
__sig_actions
__sig_pending
__signgam
+__stack_pointer
__threwValue
+_emscripten_sbrk_addr
_environ
_ns_flagdata
daylight
diff --git a/tests/other/metadce/hello_world_O3_MAIN_MODULE_2.exports b/tests/other/metadce/hello_world_O3_MAIN_MODULE_2.exports
index d01b136..8ca2b5c 100644
--- a/tests/other/metadce/hello_world_O3_MAIN_MODULE_2.exports
+++ b/tests/other/metadce/hello_world_O3_MAIN_MODULE_2.exports
@@ -1,7 +1,14 @@
+__errno_location
+__heap_base
+__indirect_function_table
+__stack_pointer
__wasm_call_ctors
+_emscripten_sbrk_addr
dynCall_jiji
+free
main
malloc
+memory
setThrew
stackAlloc
stackRestore
diff --git a/tests/other/metadce/hello_world_O3_MAIN_MODULE_2.funcs b/tests/other/metadce/hello_world_O3_MAIN_MODULE_2.funcs
index dc45913..d4fe431 100644
--- a/tests/other/metadce/hello_world_O3_MAIN_MODULE_2.funcs
+++ b/tests/other/metadce/hello_world_O3_MAIN_MODULE_2.funcs
@@ -1,11 +1,11 @@
$__emscripten_stdout_close
$__emscripten_stdout_seek
+$__errno_location
$__fwritex
$__stdio_write
$__towrite
-$__wasm_apply_data_relocs
$__wasm_call_ctors
-$__wasm_start
+$dlfree
$dlmalloc
$legalstub$dynCall_jiji
$main
diff --git a/tests/other/metadce/hello_world_O3_MAIN_MODULE_2.imports b/tests/other/metadce/hello_world_O3_MAIN_MODULE_2.imports
index 8051a88..b5d318b 100644
--- a/tests/other/metadce/hello_world_O3_MAIN_MODULE_2.imports
+++ b/tests/other/metadce/hello_world_O3_MAIN_MODULE_2.imports
@@ -1,10 +1,4 @@
-GOT.mem.__heap_base
-env.__indirect_function_table
-env.__memory_base
-env.__stack_pointer
-env.__table_base
env.emscripten_memcpy_big
env.emscripten_resize_heap
-env.memory
env.setTempRet0
wasi_snapshot_preview1.fd_write
diff --git a/tests/other/metadce/hello_world_O3_MAIN_MODULE_2.sent b/tests/other/metadce/hello_world_O3_MAIN_MODULE_2.sent
index e67c7ea..beb30a5 100644
--- a/tests/other/metadce/hello_world_O3_MAIN_MODULE_2.sent
+++ b/tests/other/metadce/hello_world_O3_MAIN_MODULE_2.sent
@@ -1,10 +1,4 @@
-__heap_base
-__indirect_function_table
-__memory_base
-__stack_pointer
-__table_base
emscripten_memcpy_big
emscripten_resize_heap
fd_write
-memory
setTempRet0
diff --git a/tests/test_core.py b/tests/test_core.py
index e07af44..a9d5dd4 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -3872,8 +3872,10 @@
''', '''
#include "header.h"
+ int foo = 11;
+
int sidey() {
- return 11;
+ return foo;
}
''', 'other says 11.', 'int sidey();', force_c=True, **kwargs)
diff --git a/tests/test_other.py b/tests/test_other.py
index 1de3152..01fff26 100644
--- a/tests/test_other.py
+++ b/tests/test_other.py
@@ -6138,8 +6138,7 @@
def build_main(args):
print(args)
with env_modify({'EMCC_FORCE_STDLIBS': 'libc++abi'}):
- self.run_process([EMXX, 'main.cpp', '-sMAIN_MODULE',
- '--embed-file', 'libside.wasm'] + args)
+ self.run_process([EMXX, 'main.cpp', '-sMAIN_MODULE=2', 'libside.wasm'] + args)
build_main([])
out = self.run_js('a.out.js', assert_returncode=NON_ZERO)
@@ -10796,7 +10795,7 @@
self.assertContained('ASan does not support dynamic linking', err)
def test_wasm2js_no_dylink(self):
- for arg in ['-sMAIN_MODULE', '-sSIDE_MODULE', '-sRELOCATABLE']:
+ for arg in ['-sSIDE_MODULE', '-sRELOCATABLE']:
print(arg)
err = self.expect_fail([EMCC, test_file('hello_world.c'), '-sWASM=0', arg])
self.assertContained('WASM2JS is not compatible with relocatable output', err)
@@ -11839,7 +11838,7 @@
@require_v8
def test_extended_const(self):
self.v8_args = ['--experimental-wasm-extended-const']
- self.do_runf(test_file('hello_world.c'), emcc_args=['-mextended-const', '-sMAIN_MODULE=2'])
+ self.do_runf(test_file('hello_world.c'), emcc_args=['-mextended-const', '-sMAIN_MODULE=2', '-sRELOCATABLE'])
wat = self.get_wasm_text('hello_world.wasm')
# Test that extended-const expressions are used in the data segments.
self.assertTrue(re.search(r'\(data \(i32.add\s+\(global.get \$\S+\)\s+\(i32.const \d+\)', wat))
diff --git a/tools/building.py b/tools/building.py
index 0633b5e..4ba5f40 100644
--- a/tools/building.py
+++ b/tools/building.py
@@ -269,7 +269,10 @@
def lld_flags_for_executable(external_symbols):
cmd = []
- if external_symbols:
+ if settings.MAIN_MODULE:
+ cmd.append('--experimental-pic')
+ cmd.append('--unresolved-symbols=import-dynamic')
+ elif external_symbols:
undefs = shared.get_temp_files().get('.undefined').name
utils.write_file(undefs, '\n'.join(external_symbols))
cmd.append('--allow-undefined-file=%s' % undefs)
@@ -967,7 +970,7 @@
js_file = acorn_optimizer(js_file, passes)
# if we can optimize this js+wasm combination under the assumption no one else
# will see the internals, do so
- if not settings.LINKABLE:
+ if not settings.LINKABLE and not settings.SUPPORT_DYLINK:
# if we are optimizing for size, shrink the combined wasm+JS
# TODO: support this when a symbol map is used
if expensive_optimizations:
diff --git a/tools/cache.py b/tools/cache.py
index 2219060..7e61ddf 100644
--- a/tools/cache.py
+++ b/tools/cache.py
@@ -115,7 +115,7 @@
subdir.append('thinlto')
else:
subdir.append('lto')
- if settings.RELOCATABLE:
+ if settings.RELOCATABLE or settings.MAIN_MODULE:
subdir.append('pic')
if subdir:
path = os.path.join(path, '-'.join(subdir))
diff --git a/tools/system_libs.py b/tools/system_libs.py
index 41d5af0..b25bb94 100644
--- a/tools/system_libs.py
+++ b/tools/system_libs.py
@@ -46,7 +46,7 @@
flags = ['-g']
if settings.LTO and not force_object_files:
flags += ['-flto=' + settings.LTO]
- if settings.RELOCATABLE:
+ if settings.RELOCATABLE or settings.MAIN_MODULE:
flags += ['-sRELOCATABLE']
if settings.MEMORY64:
flags += ['-sMEMORY64=' + str(settings.MEMORY64)]