aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/analyzer.js2
-rw-r--r--src/intertyper.js2
-rw-r--r--src/jsifier.js14
-rw-r--r--src/library.js69
-rw-r--r--src/library_gc.js13
-rw-r--r--src/modules.js2
-rw-r--r--src/settings.js1
-rw-r--r--src/utility.js2
-rw-r--r--system/include/gc.h10
-rw-r--r--system/include/net/netinet/in.h20
-rw-r--r--system/include/sys/poll.h1
-rw-r--r--system/include/sys/socket.h5
-rwxr-xr-xtests/runner.py60
-rw-r--r--third_party/closure-compiler/README12
-rw-r--r--third_party/closure-compiler/compiler.jarbin5427247 -> 5856710 bytes
15 files changed, 167 insertions, 46 deletions
diff --git a/src/analyzer.js b/src/analyzer.js
index c09739e9..014579f4 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -690,6 +690,8 @@ function analyzer(data, sidePass) {
var subType = check[2];
addTypeInternal(subType, data); // needed for anonymous structure definitions (see below)
+ // Huge structural types are represented very inefficiently, both here and in generated JS. Best to avoid them - for example static char x[10*1024*1024]; is bad, while static char *x = malloc(10*1024*1024) is fine.
+ if (num >= 10*1024*1024) warnOnce('warning: very large fixed-size structural type: ' + type + ' - can you reduce it? (compilation may be slow)');
Types.types[nonPointing] = {
name_: nonPointing,
fields: range(num).map(function() { return subType }),
diff --git a/src/intertyper.js b/src/intertyper.js
index b1bd2ba8..8e7bb418 100644
--- a/src/intertyper.js
+++ b/src/intertyper.js
@@ -674,7 +674,7 @@ function intertyper(data, sidePass, baseLineNums) {
// Inline assembly is just JavaScript that we paste into the code
item.intertype = 'value';
if (tokensLeft[0].text == 'sideeffect') tokensLeft.splice(0, 1);
- item.ident = tokensLeft[0].text.substr(1, tokensLeft[0].text.length-2);
+ item.ident = tokensLeft[0].text.substr(1, tokensLeft[0].text.length-2) || ';'; // use ; for empty inline assembly
return { forward: null, ret: [item], item: item };
}
if (item.ident.substr(-2) == '()') {
diff --git a/src/jsifier.js b/src/jsifier.js
index 6d3fe781..2791c65b 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -332,7 +332,7 @@ function JSify(data, functionsOnly, givenFunctions) {
if (item.ident.substr(0, 5) == '__ZTV') {
js += '\n' + makePointer('[0]', null, BUILD_AS_SHARED_LIB ? 'ALLOC_NORMAL' : 'ALLOC_STATIC', ['void*']) + ';';
}
- if (item.ident in EXPORTED_GLOBALS) {
+ if (EXPORT_ALL || (item.ident in EXPORTED_GLOBALS)) {
js += '\nModule["' + item.ident + '"] = ' + item.ident + ';';
}
if (BUILD_AS_SHARED_LIB == 2 && !item.private_) {
@@ -442,7 +442,7 @@ function JSify(data, functionsOnly, givenFunctions) {
}
var text = (deps ? '\n' + deps.map(addFromLibrary).filter(function(x) { return x != '' }).join('\n') : '');
text += isFunction ? snippet : 'var ' + ident + '=' + snippet + ';';
- if (ident in EXPORTED_FUNCTIONS) {
+ if (EXPORT_ALL || (ident in EXPORTED_FUNCTIONS)) {
text += '\nModule["' + ident + '"] = ' + ident + ';';
}
return text;
@@ -702,7 +702,7 @@ function JSify(data, functionsOnly, givenFunctions) {
func.JS += '\n//FUNCTION_END_MARKER_OF_SOURCE_FILE_' + associatedSourceFile + '\n';
}
- if (func.ident in EXPORTED_FUNCTIONS) {
+ if (EXPORT_ALL || (func.ident in EXPORTED_FUNCTIONS)) {
func.JS += 'Module["' + func.ident + '"] = ' + func.ident + ';';
}
@@ -1069,12 +1069,12 @@ function JSify(data, functionsOnly, givenFunctions) {
var param1 = finalizeLLVMParameter(item.params[0]);
var param2 = finalizeLLVMParameter(item.params[1]);
switch (item.op) {
- case 'add': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, 'tempValue+' + param2, type) + ',tempValue)';
- case 'sub': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, 'tempValue-' + param2, type) + ',tempValue)';
- case 'xchg': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, param2, type) + ',tempValue)';
+ case 'add': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, 'tempValue+' + param2, type, null, null, null, null, ',') + ',tempValue)';
+ case 'sub': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, 'tempValue-' + param2, type, null, null, null, null, ',') + ',tempValue)';
+ case 'xchg': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, param2, type, null, null, null, null, ',') + ',tempValue)';
case 'cmpxchg': {
var param3 = finalizeLLVMParameter(item.params[2]);
- return '(tempValue=' + makeGetValue(param1, 0, type) + ',(' + makeGetValue(param1, 0, type) + '==' + param2 + ' && (' + makeSetValue(param1, 0, param3, type) + ')),tempValue)';
+ return '(tempValue=' + makeGetValue(param1, 0, type) + ',(' + makeGetValue(param1, 0, type) + '==' + param2 + ' && (' + makeSetValue(param1, 0, param3, type, null, null, null, null, ',') + ')),tempValue)';
}
default: throw 'unhandled atomic op: ' + item.op;
}
diff --git a/src/library.js b/src/library.js
index a281fc10..837ed71d 100644
--- a/src/library.js
+++ b/src/library.js
@@ -2457,20 +2457,22 @@ LibraryManager.library = {
var argIndex = 0;
var next;
- next = 1;
mainLoop:
- for (var formatIndex = 0; formatIndex < format.length; formatIndex++) {
+ for (var formatIndex = 0; formatIndex < format.length;) {
+ if (format[formatIndex] === '%' && format[formatIndex+1] == 'n') {
+ var argPtr = {{{ makeGetValue('varargs', 'argIndex', 'void*') }}};
+ {{{ makeSetValue('argPtr', 0, 'soFar', 'i32') }}};
+ formatIndex += 2;
+ continue;
+ }
+
// remove whitespace
while (1) {
next = get();
if (next == 0) return fields;
if (!(next in __scanString.whiteSpace)) break;
- }
- unget(next);
-
- if (next <= 0) return fields;
- var next = get();
- if (next <= 0) return fields; // End of input.
+ }
+ unget();
if (format[formatIndex] === '%') {
formatIndex++;
@@ -2504,6 +2506,7 @@ LibraryManager.library = {
// Read characters according to the format. floats are trickier, they may be in an unfloat state in the middle, then be a valid float later
if (type == 'f') {
var last = 0;
+ next = get();
while (next > 0) {
buffer.push(String.fromCharCode(next));
if (__isFloat(buffer.join(''))) {
@@ -2511,12 +2514,12 @@ LibraryManager.library = {
}
next = get();
}
- unget(next);
- while (buffer.length > last) {
- unget(buffer.pop().charCodeAt(0));
+ for (var i = 0; i < buffer.length - last + 1; i++) {
+ unget();
}
+ buffer.length = last;
+ } else {
next = get();
- } else if (type != 'n') {
var first = true;
while ((curr < max_ || isNaN(max_)) && next > 0) {
if (!(next in __scanString.whiteSpace) && // stop on whitespace
@@ -2530,13 +2533,14 @@ LibraryManager.library = {
buffer.push(String.fromCharCode(next));
next = get();
curr++;
+ first = false;
} else {
break;
}
- first = false;
}
+ unget();
}
- if (buffer.length === 0 && type != 'n') return 0; // Failure.
+ if (buffer.length === 0) return 0; // Failure.
var text = buffer.join('');
var argPtr = {{{ makeGetValue('varargs', 'argIndex', 'void*') }}};
argIndex += Runtime.getNativeFieldSize('void*');
@@ -2566,31 +2570,26 @@ LibraryManager.library = {
{{{ makeSetValue('argPtr', 'j', 'array[j]', 'i8') }}}
}
break;
- case 'n':
- {{{ makeSetValue('argPtr', 0, 'soFar-1', 'i32') }}}
- break;
}
- if (type != 'n') fields++;
- if (next <= 0) break mainLoop; // End of input.
+ fields++;
} else if (format[formatIndex] in __scanString.whiteSpace) {
+ next = get();
while (next in __scanString.whiteSpace) {
- next = get();
if (next <= 0) break mainLoop; // End of input.
+ next = get();
}
unget(next);
+ formatIndex++;
} else {
// Not a specifier.
+ next = get();
if (format[formatIndex].charCodeAt(0) !== next) {
unget(next);
break mainLoop;
}
+ formatIndex++;
}
}
- // 'n' is special in that it needs no input. so it can be at the end, even with nothing left to read
- if (format[formatIndex-1] == '%' && format[formatIndex] == 'n') {
- var argPtr = {{{ makeGetValue('varargs', 'argIndex', 'void*') }}};
- {{{ makeSetValue('argPtr', 0, 'soFar-1', 'i32') }}}
- }
return fields;
},
// Performs prtinf-style formatting.
@@ -3455,8 +3454,9 @@ LibraryManager.library = {
// int fscanf(FILE *restrict stream, const char *restrict format, ... );
// http://pubs.opengroup.org/onlinepubs/000095399/functions/scanf.html
if (FS.streams[stream]) {
- var get = function() { return _fgetc(stream); };
- var unget = function(c) { return _ungetc(c, stream); };
+ var stack = [];
+ var get = function() { var ret = _fgetc(stream); stack.push(ret); return ret };
+ var unget = function(c) { return _ungetc(stack.pop(), stream) };
return __scanString(format, get, unget, varargs);
} else {
return -1;
@@ -4745,6 +4745,10 @@ LibraryManager.library = {
return 32;
},
+ llvm_trap: function() {
+ throw 'trap! ' + new Error().stack;
+ },
+
__assert_fail: function(condition, file, line) {
ABORT = true;
throw 'Assertion failed: ' + Pointer_stringify(condition);//JSON.stringify(arguments)//condition;
@@ -6465,6 +6469,17 @@ LibraryManager.library = {
_pthread_key_create.keys[key] = value;
},
+ pthread_cleanup_push: function(routine, arg) {
+ __ATEXIT__.push({ func: function() { FUNCTION_TABLE[routine](arg) } })
+ _pthread_cleanup_push.level = __ATEXIT__.length;
+ },
+
+ pthread_cleanup_pop: function() {
+ assert(_pthread_cleanup_push.level == __ATEXIT__.length, 'cannot pop if something else added meanwhile!');
+ __ATEXIT__.pop();
+ _pthread_cleanup_push.level = __ATEXIT__.length;
+ },
+
// ==========================================================================
// malloc.h
// ==========================================================================
diff --git a/src/library_gc.js b/src/library_gc.js
index bf0a6aff..a06e2f01 100644
--- a/src/library_gc.js
+++ b/src/library_gc.js
@@ -16,6 +16,11 @@ if (GC_SUPPORT) {
init: function() {
assert(!GC.initted);
GC.initted = true;
+
+ _GC_finalize_on_demand = _malloc(4); setValue(_GC_finalize_on_demand, 0, 'i32')
+ _GC_java_finalization = _malloc(4); setValue(_GC_java_finalization, 0, 'i32');
+ _GC_finalizer_notifier = _malloc(4); setValue(_GC_finalizer_notifier, 0, 'i32');
+
if (ENVIRONMENT_IS_WEB) {
setInterval(function() {
GC.maybeCollect();
@@ -159,7 +164,13 @@ if (GC_SUPPORT) {
GC_FORCE_COLLECT__deps: ['$GC'],
GC_FORCE_COLLECT: function() {
GC.collect();
- }
+ },
+
+ GC_finalize_on_demand: 0,
+ GC_java_finalization: 0,
+ GC_finalizer_notifier: 0,
+
+ GC_enable_incremental: function(){},
};
mergeInto(LibraryManager.library, LibraryGC);
diff --git a/src/modules.js b/src/modules.js
index 781bed45..06677936 100644
--- a/src/modules.js
+++ b/src/modules.js
@@ -5,7 +5,7 @@
var LLVM = {
LINKAGES: set('private', 'linker_private', 'linker_private_weak', 'linker_private_weak_def_auto', 'internal',
'available_externally', 'linkonce', 'common', 'weak', 'appending', 'extern_weak', 'linkonce_odr',
- 'weak_odr', 'externally_visible', 'dllimport', 'dllexport', 'unnamed_addr'),
+ 'weak_odr', 'externally_visible', 'dllimport', 'dllexport', 'unnamed_addr', 'thread_local'),
VISIBILITIES: set('default', 'hidden', 'protected'),
PARAM_ATTR: set('noalias', 'signext', 'zeroext', 'inreg', 'sret', 'nocapture', 'nest'),
FUNC_ATTR: set('hidden', 'nounwind', 'define', 'inlinehint', '{'),
diff --git a/src/settings.js b/src/settings.js
index 9cdb496b..5dc1e2eb 100644
--- a/src/settings.js
+++ b/src/settings.js
@@ -196,6 +196,7 @@ var PGO = 0; // Profile-guided optimization.
var PROFILE = 0; // Enables runtime profiling. See test_profiling for a usage example.
+var EXPORT_ALL = 0; // If true, we export all the symbols
var EXPORTED_FUNCTIONS = ['_main', '_malloc', '_free']; // Functions that are explicitly exported, so they are guaranteed to
// be accessible outside of the generated code even after running closure compiler.
// Note the necessary prefix of "_".
diff --git a/src/utility.js b/src/utility.js
index 632ee08c..f3ece90b 100644
--- a/src/utility.js
+++ b/src/utility.js
@@ -184,7 +184,7 @@ function dprint() {
text = text(); // Allows deferred calculation, so dprints don't slow us down when not needed
}
text = DPRINT_INDENT + '// ' + text;
- print(text);
+ printErr(text);
}
var PROF_ORIGIN = Date.now();
diff --git a/system/include/gc.h b/system/include/gc.h
index 996bc9ec..e0419dcb 100644
--- a/system/include/gc.h
+++ b/system/include/gc.h
@@ -8,7 +8,7 @@
extern "C" {
#endif
-void __attribute__((used)) __GC_KEEPALIVE__() {
+static void __attribute__((used)) __GC_KEEPALIVE__() {
// Force inclusion of necessary dlmalloc functions
static int times = 1;
void *x = malloc(times);
@@ -44,6 +44,14 @@ void GC_MAYBE_COLLECT();
/* Forces a GC. Mainly useful for testing, but call it if you know a good time to GC in your app. */
void GC_FORCE_COLLECT();
+typedef void (*GC_finalization_proc)(void *func, void *arg);
+extern void (*GC_finalizer_notifier)();
+
+extern int GC_finalize_on_demand;
+extern int GC_java_finalization;
+
+void GC_enable_incremental();
+
#ifdef __cplusplus
}
#endif
diff --git a/system/include/net/netinet/in.h b/system/include/net/netinet/in.h
index 2e4e4e57..2ac98dfe 100644
--- a/system/include/net/netinet/in.h
+++ b/system/include/net/netinet/in.h
@@ -48,6 +48,26 @@ struct ip_mreq {
struct in_addr imr_interface;
};
+#define IP_MULTICAST_IF 32
+#define IP_MULTICAST_TTL 33
+#define IP_MULTICAST_LOOP 34
+#define IP_ADD_MEMBERSHIP 35
+#define IP_DROP_MEMBERSHIP 36
+#define IP_UNBLOCK_SOURCE 37
+#define IP_BLOCK_SOURCE 38
+#define IP_ADD_SOURCE_MEMBERSHIP 39
+#define IP_DROP_SOURCE_MEMBERSHIP 40
+#define IP_MSFILTER 41
+#define MCAST_JOIN_GROUP 42
+#define MCAST_BLOCK_SOURCE 43
+#define MCAST_UNBLOCK_SOURCE 44
+#define MCAST_LEAVE_GROUP 45
+#define MCAST_JOIN_SOURCE_GROUP 46
+#define MCAST_LEAVE_SOURCE_GROUP 47
+#define MCAST_MSFILTER 48
+#define IP_MULTICAST_ALL 49
+#define IP_UNICAST_IF 50
+
#ifdef __cplusplus
}
#endif
diff --git a/system/include/sys/poll.h b/system/include/sys/poll.h
index 55e85237..7521ed0e 100644
--- a/system/include/sys/poll.h
+++ b/system/include/sys/poll.h
@@ -11,6 +11,7 @@ extern "C" {
#define POLLNVAL 4
#define POLLERR 8
#define POLLHUP 16
+#define POLLPRI 32
struct pollfd {
int fd;
diff --git a/system/include/sys/socket.h b/system/include/sys/socket.h
index efbbe6f0..c50a3786 100644
--- a/system/include/sys/socket.h
+++ b/system/include/sys/socket.h
@@ -28,6 +28,11 @@ extern "C" {
#define SO_LINGER 70
#define SO_NOSIGPIPE 80
#define SO_KEEPALIVE 90
+#define SO_OOBINLINE 100
+#define SO_NO_CHECK 110
+#define SO_PRIORITY 120
+#define SO_LINGER 130
+#define SO_BSDCOMPAT 140
#define SHUT_RD 1
#define SHUT_RDWR 2
diff --git a/tests/runner.py b/tests/runner.py
index 99af7109..6404a211 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -4560,7 +4560,22 @@ Pass: 0.000012 0.000012''')
self.do_run(src, '3\n123,1073741823,1125899906842620\n' +
'3\n-123,-1073741823,-1125899906842620\n')
-
+
+ def test_sscanf_4(self):
+ src = r'''
+ #include <stdio.h>
+
+ int main()
+ {
+ char pYear[16], pMonth[16], pDay[16], pDate[64];
+ printf("%d\n", sscanf("Nov 19 2012", "%s%s%s", pMonth, pDay, pYear));
+ printf("day %s, month %s, year %s \n", pDay, pMonth, pYear);
+ return(0);
+ }
+ '''
+
+ self.do_run(src, '3\nday 19, month Nov, year 2012');
+
def test_langinfo(self):
src = open(path_from_root('tests', 'langinfo', 'test.c'), 'r').read()
expected = open(path_from_root('tests', 'langinfo', 'output.txt'), 'r').read()
@@ -7680,6 +7695,22 @@ f.close()
Popen(['python', EMCC, os.path.join(self.get_dir(), 'test.cpp'), '-s', 'UNALIGNED_MEMORY=1']).communicate()
self.assertContained('data: 67452301\ndata[0,1] 16bit: 2301\ndata[1,2] 16bit: 4523', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+ def test_unaligned_memory_2(self):
+ open(os.path.join(self.get_dir(), 'test.cpp'), 'w').write(r'''
+ #include <string>
+ #include <stdio.h>
+
+ int main( int argc, char ** argv )
+ {
+ std::string testString( "Hello, World!" );
+
+ printf( "testString = %s\n", testString.c_str() );
+ return 0;
+ }
+ ''')
+ Popen(['python', EMCC, os.path.join(self.get_dir(), 'test.cpp'), '-s', 'UNALIGNED_MEMORY=1']).communicate()
+ self.assertContained('testString = Hello, World!', run_js(os.path.join(self.get_dir(), 'a.out.js')))
+
def test_l_link(self):
# Linking with -lLIBNAME and -L/DIRNAME should work
@@ -8126,6 +8157,33 @@ f.close()
output = Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp')], stderr=PIPE).communicate()
self.assertNotContained('Unresolved symbol: _something\n', output[1])
+ def test_toobig(self):
+ open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(r'''
+ #include <stdio.h>
+
+ #define BYTES 100*1024*1024
+
+ int main(int argc, char **argv) {
+ if (argc == 100) {
+ static char buf[BYTES];
+ static char buf2[BYTES];
+ for (int i = 0; i < BYTES; i++) {
+ buf[i] = i*i;
+ buf2[i] = i/3;
+ }
+ for (int i = 0; i < BYTES; i++) {
+ buf[i] = buf2[i/2];
+ buf2[i] = buf[i/3];
+ }
+ printf("%d\n", buf[10] + buf2[20]);
+ }
+ return 0;
+ }
+ ''')
+ output = Popen(['python', EMCC, os.path.join(self.get_dir(), 'main.cpp')], stderr=PIPE).communicate()[1]
+ assert 'Emscripten failed' in output, output
+ assert 'warning: very large fixed-size structural type' in output, output
+
def test_prepost(self):
open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write('''
#include <stdio.h>
diff --git a/third_party/closure-compiler/README b/third_party/closure-compiler/README
index 77ab89db..270cfc27 100644
--- a/third_party/closure-compiler/README
+++ b/third_party/closure-compiler/README
@@ -171,7 +171,7 @@ lib/args4j.jar
Args4j
URL: https://args4j.dev.java.net/
-Version: 2.0.12
+Version: 2.0.16
License: MIT
Description:
@@ -187,7 +187,7 @@ lib/guava.jar
Guava Libraries
URL: http://code.google.com/p/guava-libraries/
-Version: r08
+Version: 13.0.1
License: Apache License 2.0
Description: Google's core Java libraries.
@@ -230,7 +230,7 @@ lib/junit.jar
JUnit
URL: http://sourceforge.net/projects/junit/
-Version: 4.8.2
+Version: 4.10
License: Common Public License 1.0
Description: A framework for writing and running automated tests in Java.
@@ -244,7 +244,7 @@ lib/protobuf-java.jar
Protocol Buffers
URL: http://code.google.com/p/protobuf/
-Version: 2.3.0
+Version: 2.4.1
License: New BSD License
Description: Supporting libraries for protocol buffers,
@@ -281,9 +281,9 @@ Local Modifications: None
---
Code in:
-tools/maven-ant-tasks-2.1.1.jar
+tools/maven-ant-tasks-2.1.3.jar
URL: http://maven.apache.org
-Version 2.1.1
+Version 2.1.3
License: Apache License 2.0
Description:
Maven Ant tasks are used to manage dependencies and to install/deploy to
diff --git a/third_party/closure-compiler/compiler.jar b/third_party/closure-compiler/compiler.jar
index da191b01..e23352ff 100644
--- a/third_party/closure-compiler/compiler.jar
+++ b/third_party/closure-compiler/compiler.jar
Binary files differ