diff options
-rw-r--r-- | src/compiler.js | 4 | ||||
-rw-r--r-- | src/jsifier.js | 25 | ||||
-rw-r--r-- | src/library.js | 25 | ||||
-rw-r--r-- | src/modules.js | 2 | ||||
-rw-r--r-- | src/settings.js | 7 | ||||
-rw-r--r-- | tests/cases/uadd_overflow_64_ta2.ll | 6 | ||||
-rw-r--r-- | tests/cases/uadd_overflow_64_ta2.txt | 1 | ||||
-rwxr-xr-x | tests/runner.py | 9 |
8 files changed, 32 insertions, 47 deletions
diff --git a/src/compiler.js b/src/compiler.js index d74ff7cb..313fd5f7 100644 --- a/src/compiler.js +++ b/src/compiler.js @@ -169,7 +169,9 @@ EXPORTED_FUNCTIONS = set(EXPORTED_FUNCTIONS); EXPORTED_GLOBALS = set(EXPORTED_GLOBALS); EXCEPTION_CATCHING_WHITELIST = set(EXCEPTION_CATCHING_WHITELIST); -if (DEAD_FUNCTIONS.length && ASSERTIONS) DEFAULT_LIBRARY_FUNCS_TO_INCLUDE.push('putchar'); // for debug output +DEAD_FUNCTIONS.forEach(function(dead) { + DEFAULT_LIBRARY_FUNCS_TO_INCLUDE.push(dead.substr(1)); +}); DEAD_FUNCTIONS = numberedSet(DEAD_FUNCTIONS); RUNTIME_DEBUG = LIBRARY_DEBUG || GL_DEBUG; diff --git a/src/jsifier.js b/src/jsifier.js index 30a06d76..aab21eea 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -484,17 +484,12 @@ function JSify(data, functionsOnly, givenFunctions) { if (BUILD_AS_SHARED_LIB) { // Shared libraries reuse the runtime of their parents. item.JS = ''; - } else if (LibraryManager.library.hasOwnProperty(shortident)) { - item.JS = addFromLibrary(shortident); - } else if (!LibraryManager.library.hasOwnProperty(shortident + '__inline')) { - if (!(item.ident in DEAD_FUNCTIONS)) { - item.JS = 'var ' + item.ident + '; // stub for ' + item.ident; - if (ASM_JS) { - error('Unresolved symbol: ' + item.ident + ', this must be corrected for asm.js validation to succeed. Consider adding it to DEAD_FUNCTIONS.'); - } else if (WARN_ON_UNDEFINED_SYMBOLS) { - warn('Unresolved symbol: ' + item.ident); - } + } else { + if (!LibraryManager.library.hasOwnProperty(shortident) && !LibraryManager.library.hasOwnProperty(shortident + '__inline')) { + if (ASSERTIONS) printErr('warning: missing function: ' + shortident); + LibraryManager.library[shortident] = new Function("Module['printErr']('missing function: " + shortident + "'); abort(-1);"); } + item.JS = addFromLibrary(shortident); } return ret; } @@ -1439,16 +1434,6 @@ function JSify(data, functionsOnly, givenFunctions) { returnType = getReturnType(type); } - if (callIdent in DEAD_FUNCTIONS) { - var ret = 'abort(' + DEAD_FUNCTIONS[callIdent] + ')'; - if (ASM_JS) ret = asmCoercion(ret, returnType); - if (ASSERTIONS) { - assert(DEFAULT_LIBRARY_FUNCS_TO_INCLUDE.indexOf('putchar') >= 0, 'need putchar for DEAD_FUNCTIONS + ASSERTIONS output'); - ret = '(' + makePrintChars('dead:' + callIdent, ',') + ',' + ret + ')'; - } - return ret; - } - if (byPointer) { var sig = Functions.getSignature(returnType, argsTypes, hasVarArgs); if (ASM_JS) { diff --git a/src/library.js b/src/library.js index 29c3386f..5bbf4204 100644 --- a/src/library.js +++ b/src/library.js @@ -4292,7 +4292,7 @@ LibraryManager.library = { ptr = ptr|0; var curr = 0; curr = ptr; - while ({{{ makeGetValueAsm('curr', '0', 'i8') }}}|0 != 0) { + while ({{{ makeGetValueAsm('curr', '0', 'i8') }}}) { curr = (curr + 1)|0; } return (curr - ptr)|0; @@ -4338,7 +4338,7 @@ LibraryManager.library = { do { {{{ makeCopyValues('(pdest+i)|0', '(psrc+i)|0', 1, 'i8', null, 1) }}}; i = (i+1)|0; - } while (({{{ makeGetValue('psrc', 'i-1', 'i8') }}})|0 != 0); + } while ({{{ makeGetValueAsm('psrc', 'i-1', 'i8') }}}); return pdest|0; }, @@ -4397,7 +4397,7 @@ LibraryManager.library = { do { {{{ makeCopyValues('pdest+i', 'psrc+i', 1, 'i8', null, 1) }}}; i = (i+1)|0; - } while ({{{ makeGetValueAsm('psrc', 'i-1', 'i8') }}} != 0); + } while ({{{ makeGetValueAsm('psrc', 'i-1', 'i8') }}}); return pdest|0; }, @@ -5311,6 +5311,8 @@ LibraryManager.library = { llvm_objectsize_i32: function() { return -1 }, // TODO: support this + llvm_dbg_declare__inline: function() { throw 'llvm_debug_declare' }, // avoid warning + // ========================================================================== // llvm-mono integration // ========================================================================== @@ -7509,10 +7511,7 @@ LibraryManager.library = { a = a|0; b = b|0; c = c|0; d = d|0; var l = 0, h = 0; l = (a + c)>>>0; - h = (b + d)>>>0; - if ((l>>>0) < (a>>>0)) { // iff we overflowed - h = (h+1)>>>0; - } + h = (((b + d)>>>0) + (((l>>>0) < (a>>>0))>>>0))>>>0; // Add carry from low word to high word on overflow. {{{ makeStructuralReturn(['l|0', 'h'], true) }}}; }, llvm_uadd_with_overflow_i64__asm: true, @@ -7522,11 +7521,9 @@ LibraryManager.library = { var l = 0, h = 0, overflow = 0; l = (a + c)>>>0; h = (b + d)>>>0; - if ((h>>>0) < (b>>>0)) overflow = 1; - if ((l>>>0) < (a>>>0)) { - h = (h+1)>>>0; - if ((h>>>0) == 0) overflow = 1; // two possibilities to overflow here - } + overflow = ((h>>>0) < (b>>>0))>>>0; // Return whether addition overflowed even the high word. + h = h + (((l>>>0) < (a>>>0))>>>0)>>>0; // Add carry from low word to high word on overflow. + overflow = overflow | (h == 0); // Check again for overflow. {{{ makeStructuralReturn(['l|0', 'h', 'overflow'], true) }}}; }, @@ -7537,9 +7534,7 @@ LibraryManager.library = { var l = 0, h = 0; l = (a - c)>>>0; h = (b - d)>>>0; - if ((l>>>0) > (a>>>0)) { // iff we overflowed - h = (h-1)>>>0; - } + h = (((b - d)>>>0) - (((c>>>0) > (a>>>0))>>>0))>>>0; // Borrow one from high word to low word on underflow. {{{ makeStructuralReturn(['l|0', 'h'], true) }}}; }, diff --git a/src/modules.js b/src/modules.js index 7a769846..ce162ac1 100644 --- a/src/modules.js +++ b/src/modules.js @@ -291,7 +291,7 @@ var Functions = { var sig = ASM_JS ? Functions.implementedFunctions[ident] || Functions.unimplementedFunctions[ident] || LibraryManager.library[ident.substr(1) + '__sig'] : 'x'; assert(sig, ident); if (!tables[sig]) tables[sig] = emptyTable(sig); // TODO: make them compact - tables[sig][this.indexedFunctions[ident]] = ident in DEAD_FUNCTIONS ? '0' : ident; + tables[sig][this.indexedFunctions[ident]] = ident; } var generated = false; var wrapped = {}; diff --git a/src/settings.js b/src/settings.js index 8c7d1f83..c878be92 100644 --- a/src/settings.js +++ b/src/settings.js @@ -342,12 +342,7 @@ var PGO = 0; // Enables profile-guided optimization in the form of runtime check // calling PGOMonitor.dump()); var DEAD_FUNCTIONS = []; // Functions on this list are not converted to JS, and calls to // them are turned into abort()s. This is potentially useful for - // (1) reducing code size, if you know some function will never - // be called (see PGO), and also (2) ASM.js requires all declared - // functions to have a corresponding implementation (even if the - // function is never called) and will emit an error during linking if no - // implementation can be found; with this option, asm.js validation will - // succeed for that function and calls to it. + // reducing code size. // If a dead function is actually called, you will get a runtime // error. // TODO: options to lazily load such functions diff --git a/tests/cases/uadd_overflow_64_ta2.ll b/tests/cases/uadd_overflow_64_ta2.ll index a4f3e40b..6dfbc1e5 100644 --- a/tests/cases/uadd_overflow_64_ta2.ll +++ b/tests/cases/uadd_overflow_64_ta2.ll @@ -19,6 +19,12 @@ entry: %b2 = zext i1 %b1 to i32 call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([11 x i8]* @.str2, i32 0, i32 0), i64 %b0, i32 %b2) ; [#uses=0] + %uadd3 = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 4294967297, i64 18446744073709551615) + %c0 = extractvalue { i64, i1 } %uadd3, 0 + %c1 = extractvalue { i64, i1 } %uadd3, 1 + %c2 = zext i1 %c1 to i32 + call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([11 x i8]* @.str2, i32 0, i32 0), i64 %c0, i32 %c2) ; [#uses=0] + ret i32 1 } diff --git a/tests/cases/uadd_overflow_64_ta2.txt b/tests/cases/uadd_overflow_64_ta2.txt index f5711309..2abb084c 100644 --- a/tests/cases/uadd_overflow_64_ta2.txt +++ b/tests/cases/uadd_overflow_64_ta2.txt @@ -1,2 +1,3 @@ *2705,1* *10c6f7a0dcfc,0* +*100000000,1*
\ No newline at end of file diff --git a/tests/runner.py b/tests/runner.py index a66ef75d..5602fd94 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -8171,11 +8171,12 @@ def process(filename): # Kill off the dead function, still works and it is not emitted Settings.DEAD_FUNCTIONS = ['_unused'] js = test('*9*') - assert 'function _unused(' not in js + assert 'function _unused($' not in js # no compiled code + assert 'function _unused(' in js # lib-generated stub Settings.DEAD_FUNCTIONS = [] # Run the same code with argc that uses the dead function, see abort - test(('dead:_unused' if Settings.ASSERTIONS else 'abort', 'is not a function'), args=['a', 'b'], no_build=True) + test(('missing function: unused'), args=['a', 'b'], no_build=True) # Normal stuff run_all('normal', r''' @@ -8250,7 +8251,7 @@ def process(filename): before = len(open('normal.js').read()) after = len(open('pgoed.js').read()) - assert after < 0.66 * before, [before, after] # expect a big size reduction + assert after < 0.90 * before, [before, after] # expect a size reduction # with response in settings element itself @@ -10357,7 +10358,7 @@ f.close() (1, 0, 3, 2), (1, 1, 3, 4) ]: print asm, linkable, chunks, js_chunks - output, err = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_libcxx.cpp'), '-O1', '-s', 'LINKABLE=%d' % linkable, '-s', 'ASM_JS=%d' % asm, '-s', 'UNRESOLVED_AS_DEAD=1'] + (['-O2'] if asm else []), stdout=PIPE, stderr=PIPE).communicate() + output, err = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_libcxx.cpp'), '-O1', '-s', 'LINKABLE=%d' % linkable, '-s', 'ASM_JS=%d' % asm] + (['-O2'] if asm else []), stdout=PIPE, stderr=PIPE).communicate() ok = False for c in range(chunks, chunks+2): ok = ok or ('phase 2 working on %d chunks' % c in err) |