diff options
author | Alon Zakai <alonzakai@gmail.com> | 2013-01-10 10:38:23 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2013-01-10 10:38:23 -0800 |
commit | a3c256bf34521cbb250e6a136b2a7c98d1b9b489 (patch) | |
tree | 50005da3ce60697560d4e00b7b77c47bae49bbbd | |
parent | 987fd9f26b3355dfdba2832e6cf5721b53798068 (diff) |
link in memcpy after opts and lto if it shows up only at that time
-rwxr-xr-x | emcc | 28 | ||||
-rw-r--r-- | src/library.js | 6 | ||||
-rwxr-xr-x | tests/runner.py | 42 |
3 files changed, 73 insertions, 3 deletions
@@ -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> |