aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS1
-rw-r--r--src/compiler.js4
-rw-r--r--src/jsifier.js25
-rw-r--r--src/library.js25
-rw-r--r--src/modules.js2
-rw-r--r--src/runtime.js2
-rw-r--r--src/settings.js7
-rw-r--r--system/lib/libcextra.symbols7
-rw-r--r--tests/cases/uadd_overflow_64_ta2.ll6
-rw-r--r--tests/cases/uadd_overflow_64_ta2.txt1
-rwxr-xr-xtests/runner.py10
11 files changed, 35 insertions, 55 deletions
diff --git a/AUTHORS b/AUTHORS
index 1c6cf0ec..f0055f2e 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -68,3 +68,4 @@ a license to everyone to use it as detailed in LICENSE.)
* Llorens Marti Garcia <lgarcia@imvu.com> (copyright owned by IMVU)
* Jinsuck Kim <jkim@imvu.com> (copyright owned by IMVU)
* Todd Lee <tlee@imvu.com> (copyright owned by IMVU)
+* Anthony Pesch <inolen@gmail.com> \ No newline at end of file
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..957f69bd 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 + (((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); // 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 - (((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/runtime.js b/src/runtime.js
index 5b9a8134..5269301c 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -350,7 +350,7 @@ var Runtime = {
assert(sig);
if (!Runtime.funcWrappers[func]) {
Runtime.funcWrappers[func] = function() {
- Runtime.dynCall(sig, func, arguments);
+ return Runtime.dynCall(sig, func, arguments);
};
}
return Runtime.funcWrappers[func];
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/system/lib/libcextra.symbols b/system/lib/libcextra.symbols
index 97805c96..86e6e8ee 100644
--- a/system/lib/libcextra.symbols
+++ b/system/lib/libcextra.symbols
@@ -1,19 +1,12 @@
- U __errno
- U __fsmu8
T btowc
- U malloc
T mblen
T mbrlen
- d mbrlen.internal
T mbrtowc
- d mbrtowc.internal_state
T mbsinit
T mbsnrtowcs
T mbsrtowcs
T mbstowcs
T mbtowc
- U towlower
- t twoway_wcsstr
T wcpcpy
T wcpncpy
T wcrtomb
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 7ae2dc41..5602fd94 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -2310,6 +2310,7 @@ cat |umber one top notchfi FI FO FUM WHEN WHERE WHY HOW WHO|''', ['wowie', 'too'
self.do_run(src, 'Assertion failed: 1 == false')
def test_libcextra(self):
+ if self.emcc_args is None: return self.skip('needs emcc for libcextra')
src = r'''
#include <stdio.h>
#include <wchar.h>
@@ -8170,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'''
@@ -8249,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
@@ -10356,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)