aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2013-01-10 10:38:23 -0800
committerAlon Zakai <alonzakai@gmail.com>2013-01-10 10:38:23 -0800
commita3c256bf34521cbb250e6a136b2a7c98d1b9b489 (patch)
tree50005da3ce60697560d4e00b7b77c47bae49bbbd
parent987fd9f26b3355dfdba2832e6cf5721b53798068 (diff)
link in memcpy after opts and lto if it shows up only at that time
-rwxr-xr-xemcc28
-rw-r--r--src/library.js6
-rwxr-xr-xtests/runner.py42
3 files changed, 73 insertions, 3 deletions
diff --git a/emcc b/emcc
index d6b6ed17..e927fbd8 100755
--- a/emcc
+++ b/emcc
@@ -90,6 +90,8 @@ LLVM_OPT_LEVEL = {
3: 3,
}
+MEMCPY_ALIASES = ['memcpy', 'llvm.memcpy.i32', 'llvm.memcpy.i64', 'llvm.memcpy.p0i8.p0i8.i32', 'llvm.memcpy.p0i8.p0i8.i64']
+
DEBUG = int(os.environ.get('EMCC_DEBUG') or 0)
TEMP_DIR = os.environ.get('EMCC_TEMP_DIR')
LEAVE_INPUTS_RAW = os.environ.get('EMCC_LEAVE_INPUTS_RAW') # Do not compile .ll files into .bc, just compile them with emscripten directly
@@ -947,7 +949,7 @@ try:
def fix_libc(need):
# If an intrinsic alias of memcpy is used, we need memcpy
- for memcpy_alias in ['llvm.memcpy.i32', 'llvm.memcpy.i64', 'llvm.memcpy.p0i8.p0i8.i32', 'llvm.memcpy.p0i8.p0i8.i64']:
+ for memcpy_alias in MEMCPY_ALIASES:
if memcpy_alias in need:
if '_memcpy' not in shared.Settings.EXPORTED_FUNCTIONS:
shared.Settings.EXPORTED_FUNCTIONS.append('_memcpy')
@@ -1087,6 +1089,30 @@ try:
shared.Building.llvm_opt(in_temp(target_basename + '.bc'), link_opts)
if DEBUG: save_intermediate('linktime', 'bc')
+ # Optimization and lto can add new intrinsics like memcpy that were not present before. We
+ # are now *after* linking in libc, so we missed our chance to get memcpy - check and add it now
+ # if necessary
+ final_symbols = shared.Building.llvm_nm(final)
+ need_memcpy = False
+ for symbol in final_symbols.undefs:
+ if symbol in MEMCPY_ALIASES:
+ need_memcpy = True
+ break
+ has_memcpy = False
+ for symbol in final_symbols.defs:
+ if symbol in MEMCPY_ALIASES:
+ has_memcpy = True
+ break
+ if need_memcpy and not has_memcpy:
+ if DEBUG: print >> sys.stderr, 'memcpy intrinsic added in optimizations, linking in optimized memcpy'
+ memcpy = in_temp('memcpy.bc')
+ execute([shared.PYTHON, shared.EMCC, shared.path_from_root('system', 'lib', 'libc', 'musl', 'memcpy.c'), '-o', memcpy], stdout=stdout, stderr=stderr)
+ shared.Building.llvm_opt(memcpy, llvm_opts) # optimize it just like normal code; no point in lto though
+ next = final + '.postrinsics.bc'
+ shared.Building.link([final, memcpy], next)
+ final = next
+ if DEBUG: save_intermediate('postrinsics', 'bc')
+
# Prepare .ll for Emscripten
if not LEAVE_INPUTS_RAW:
final = shared.Building.llvm_dis(final, final + '.ll')
diff --git a/src/library.js b/src/library.js
index 74425e4f..f9cab641 100644
--- a/src/library.js
+++ b/src/library.js
@@ -4202,8 +4202,10 @@ LibraryManager.library = {
memcpy: function (dest, src, num) {
// simple version, in general it should not be used - we should pull it in from libc
-#if ASSERTIONS
- Module.printErr('warning: library.js memcpy should not be running!');
+ if (!_memcpy.shown) {
+ _memcpy.shown = true;
+ Module.printErr('warning: library.js memcpy should not be running, it is only for testing!');
+ }
#endif
while (num--) {
HEAP8[dest++] = HEAP8[src++];
diff --git a/tests/runner.py b/tests/runner.py
index 35a484be..ea124c30 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -8754,6 +8754,48 @@ f.close()
Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'main.cpp')]).communicate()
self.assertContained('1234, 1234, 4321\n', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+ def test_link_memcpy(self):
+ # memcpy can show up *after* optimizations, so after our opportunity to link in libc, so it must be special-cased
+ open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(r'''
+ #include <stdio.h>
+
+ int main(int argc, char **argv) {
+ int num = argc + 10;
+ char buf[num], buf2[num];
+ for (int i = 0; i < num; i++) {
+ buf[i] = i*i+i/3;
+ }
+ for (int i = 1; i < num; i++) {
+ buf[i] += buf[i-1];
+ }
+ for (int i = 0; i < num; i++) {
+ buf2[i] = buf[i];
+ }
+ for (int i = 1; i < num; i++) {
+ buf2[i] += buf2[i-1];
+ }
+ for (int i = 0; i < num; i++) {
+ printf("%d:%d\n", i, buf2[i]);
+ }
+ return 0;
+ }
+ ''')
+ Popen([PYTHON, EMCC, '-O2', '--closure', '-0', os.path.join(self.get_dir(), 'main.cpp')]).communicate()
+ output = run_js(os.path.join(self.get_dir(), 'a.out.js'), full_output=True, stderr=PIPE)
+ self.assertContained('''0:0
+1:1
+2:6
+3:21
+4:53
+5:111
+6:-49
+7:98
+8:55
+9:96
+10:-16
+''', output)
+ self.assertNotContained('warning: library.js memcpy should not be running, it is only for testing!', output)
+
def test_warn_undefined(self):
open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(r'''
#include <stdio.h>