diff options
-rwxr-xr-x | emscripten.py | 19 | ||||
-rw-r--r-- | src/hello_world.js (renamed from tests/hello_world.js) | 0 | ||||
-rw-r--r-- | src/jsifier.js | 4 | ||||
-rw-r--r-- | src/library.js | 95 | ||||
-rw-r--r-- | src/modules.js | 7 | ||||
-rw-r--r-- | src/simd.js | 7 | ||||
-rw-r--r-- | src/utility.js | 8 | ||||
-rw-r--r-- | tests/sockets/test_getprotobyname.c | 87 | ||||
-rw-r--r-- | tests/test_other.py | 14 | ||||
-rw-r--r-- | tests/test_sockets.py | 3 | ||||
-rw-r--r-- | tools/shared.py | 4 |
11 files changed, 226 insertions, 22 deletions
diff --git a/emscripten.py b/emscripten.py index 907e88ce..ae46ca07 100755 --- a/emscripten.py +++ b/emscripten.py @@ -804,6 +804,13 @@ def emscript_fast(infile, settings, outfile, libraries=[], compiler_engine=None, if DEBUG: logging.debug('emscript: js compiler glue') + # Settings changes + assert settings['TARGET_LE32'] == 1 + settings['TARGET_LE32'] = 2 + if 'i64Add' in metadata['declares']: # TODO: others, once we split them up + settings['PRECISE_I64_MATH'] = 2 + metadata['declares'] = filter(lambda i64_func: i64_func not in ['getHigh32', 'setHigh32', '__muldi3', '__divdi3', '__remdi3', '__udivdi3', '__uremdi3'], metadata['declares']) # FIXME: do these one by one as normal js lib funcs + # Integrate info from backend settings['DEFAULT_LIBRARY_FUNCS_TO_INCLUDE'] = list( set(settings['DEFAULT_LIBRARY_FUNCS_TO_INCLUDE'] + map(shared.JS.to_nice_ident, metadata['declares'])).difference( @@ -811,10 +818,6 @@ def emscript_fast(infile, settings, outfile, libraries=[], compiler_engine=None, ) ) + map(lambda x: x[1:], metadata['externs']) - # Settings changes - assert settings['TARGET_LE32'] == 1 - settings['TARGET_LE32'] = 2 - # Save settings to a file to work around v8 issue 1579 settings_file = temp_files.get('.txt').name def save_settings(): @@ -885,18 +888,14 @@ def emscript_fast(infile, settings, outfile, libraries=[], compiler_engine=None, #if DEBUG: outfile.write('// funcs\n') if settings.get('ASM_JS'): - #print >> sys.stderr, '<<<<<<', post, '>>>>>>' - post_funcs = '' #, post_rest = post.split('// EMSCRIPTEN_END_FUNCS\n') - #post = post_rest - # Move preAsms to their right place def move_preasm(m): contents = m.groups(0)[0] outfile.write(contents + '\n') return '' - post_funcs = re.sub(r'/\* PRE_ASM \*/(.*)\n', lambda m: move_preasm(m), post_funcs) + funcs_js[1] = re.sub(r'/\* PRE_ASM \*/(.*)\n', lambda m: move_preasm(m), funcs_js[1]) - funcs_js += ['\n' + post_funcs + '// EMSCRIPTEN_END_FUNCS\n'] + funcs_js += ['\n// EMSCRIPTEN_END_FUNCS\n'] simple = os.environ.get('EMCC_SIMPLE_ASM') class Counter: diff --git a/tests/hello_world.js b/src/hello_world.js index 01082eb4..01082eb4 100644 --- a/tests/hello_world.js +++ b/src/hello_world.js diff --git a/src/jsifier.js b/src/jsifier.js index 907855e7..b5502741 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -1859,10 +1859,10 @@ function JSify(data, functionsOnly, givenFunctions) { // first row are utilities called from generated code, second are needed from fastLong ['i64Add', 'i64Subtract', 'bitshift64Shl', 'bitshift64Lshr', 'bitshift64Ashr', 'llvm_ctlz_i32', 'llvm_cttz_i32'].forEach(function(func) { - if (!Functions.libraryFunctions[func]) { + if (!Functions.libraryFunctions[func] || (phase == 'glue' && func[0] === 'l')) { // TODO: one-by-one in fastcomp glue mode print(processLibraryFunction(LibraryManager.library[func], func)); // must be first to be close to generated code Functions.implementedFunctions['_' + func] = LibraryManager.library[func + '__sig']; - Functions.libraryFunctions[func] = 1; + Functions.libraryFunctions[func] = phase == 'glue' ? 2 : 1; // XXX // limited dependency handling var deps = LibraryManager.library[func + '__deps']; if (deps) { diff --git a/src/library.js b/src/library.js index 26d766e9..bdc0a39e 100644 --- a/src/library.js +++ b/src/library.js @@ -1868,14 +1868,13 @@ LibraryManager.library = { #endif #if USE_TYPED_ARRAYS == 2 } else if (type == 'i64') { - -#if TARGET_LE32 +#if TARGET_LE32 == 1 ret = [{{{ makeGetValue('varargs', 'argIndex', 'i32', undefined, undefined, true) }}}, {{{ makeGetValue('varargs', 'argIndex+8', 'i32', undefined, undefined, true) }}}]; argIndex += {{{ STACK_ALIGN }}}; // each 32-bit chunk is in a 64-bit block #else - ret = [{{{ makeGetValue('varargs', 'argIndex', 'i32', undefined, undefined, true) }}}, - {{{ makeGetValue('varargs', 'argIndex+4', 'i32', undefined, undefined, true) }}}]; + ret = [{{{ makeGetValue('varargs', 'argIndex', 'i32', undefined, undefined, true, 4) }}}, + {{{ makeGetValue('varargs', 'argIndex+4', 'i32', undefined, undefined, true, 4) }}}]; #endif #else @@ -7702,6 +7701,94 @@ LibraryManager.library = { return _gai_strerror.buffer; }, + // Implement netdb.h protocol entry (getprotoent, getprotobyname, getprotobynumber, setprotoent, endprotoent) + // http://pubs.opengroup.org/onlinepubs/9699919799/functions/getprotobyname.html + // The Protocols object holds our 'fake' protocols 'database'. + $Protocols: { + list: [], + map: {} + }, + setprotoent__deps: ['$Protocols'], + setprotoent: function(stayopen) { + // void setprotoent(int stayopen); + + // Allocate and populate a protoent structure given a name, protocol number and array of aliases + function allocprotoent(name, proto, aliases) { + // write name into buffer + var nameBuf = _malloc(name.length + 1); + writeAsciiToMemory(name, nameBuf); + + // write aliases into buffer + var j = 0; + var length = aliases.length; + var aliasListBuf = _malloc((length + 1) * 4); // Use length + 1 so we have space for the terminating NULL ptr. + + for (var i = 0; i < length; i++, j += 4) { + var alias = aliases[i]; + var aliasBuf = _malloc(alias.length + 1); + writeAsciiToMemory(alias, aliasBuf); + {{{ makeSetValue('aliasListBuf', 'j', 'aliasBuf', 'i8*') }}}; + } + {{{ makeSetValue('aliasListBuf', 'j', '0', 'i8*') }}}; // Terminating NULL pointer. + + // generate protoent + var pe = _malloc({{{ C_STRUCTS.protoent.__size__ }}}); + {{{ makeSetValue('pe', C_STRUCTS.protoent.p_name, 'nameBuf', 'i8*') }}}; + {{{ makeSetValue('pe', C_STRUCTS.protoent.p_aliases, 'aliasListBuf', 'i8**') }}}; + {{{ makeSetValue('pe', C_STRUCTS.protoent.p_proto, 'proto', 'i32') }}}; + return pe; + }; + + // Populate the protocol 'database'. The entries are limited to tcp and udp, though it is fairly trivial + // to add extra entries from /etc/protocols if desired - though not sure if that'd actually be useful. + var list = Protocols.list; + var map = Protocols.map; + if (list.length === 0) { + var entry = allocprotoent('tcp', 6, ['TCP']); + list.push(entry); + map['tcp'] = map['6'] = entry; + entry = allocprotoent('udp', 17, ['UDP']); + list.push(entry); + map['udp'] = map['17'] = entry; + } + + _setprotoent.index = 0; + }, + + endprotoent: function() { + // void endprotoent(void); + // We're not using a real protocol database so we don't do a real close. + }, + + getprotoent__deps: ['setprotoent', '$Protocols'], + getprotoent: function(number) { + // struct protoent *getprotoent(void); + // reads the next entry from the protocols 'database' or return NULL if 'eof' + if (_setprotoent.index === Protocols.list.length) { + return 0; + } else { + var result = Protocols.list[_setprotoent.index++]; + return result; + } + }, + + getprotobyname__deps: ['setprotoent', '$Protocols'], + getprotobyname: function(name) { + // struct protoent *getprotobyname(const char *); + name = Pointer_stringify(name); + _setprotoent(true); + var result = Protocols.map[name]; + return result; + }, + + getprotobynumber__deps: ['setprotoent', '$Protocols'], + getprotobynumber: function(number) { + // struct protoent *getprotobynumber(int proto); + _setprotoent(true); + var result = Protocols.map[number]; + return result; + }, + // ========================================================================== // sockets. Note that the implementation assumes all sockets are always // nonblocking diff --git a/src/modules.js b/src/modules.js index e80115c4..b9b8ab5e 100644 --- a/src/modules.js +++ b/src/modules.js @@ -282,7 +282,12 @@ var Functions = { sig += Functions.getSignatureLetter(type); } else { var chunks = getNumIntChunks(type); - for (var j = 0; j < chunks; j++) sig += 'i'; + if (chunks > 0) { + for (var j = 0; j < chunks; j++) sig += 'i'; + } else { + // some special type like a SIMD vector + sig += Functions.getSignatureLetter(type); + } } } if (hasVarArgs) sig += 'i'; diff --git a/src/simd.js b/src/simd.js index c7f5ff48..6e3e3675 100644 --- a/src/simd.js +++ b/src/simd.js @@ -848,8 +848,11 @@ var SIMD = (function () { * @return {float32x4} a bit-wise copy of t as a float32x4. */ bitsToFloat32x4: function(t) { - var alias = new Float32Array(t.storage_.buffer); - return new float32x4(alias[0], alias[1], alias[2], alias[3]); + var temp_storage = new Int32Array([t.storage_[0], t.storage_[1], t.storage_[2], t.storage_[3]]); + var alias = new Float32Array(temp_storage.buffer); + var fx4 = float32x4.zero(); + fx4.storage_ = alias; + return fx4; }, /** * @param {int32x4} t An instance of int32x4. diff --git a/src/utility.js b/src/utility.js index cd27b209..178c596b 100644 --- a/src/utility.js +++ b/src/utility.js @@ -346,13 +346,19 @@ function sortedJsonCompare(x, y) { return true; } +function escapeJSONKey(x) { + if (/^[\d\w_]+$/.exec(x) || x[0] === '"' || x[0] === "'") return x; + assert(x.indexOf("'") < 0, 'cannot have internal single quotes in keys: ' + x); + return "'" + x + "'"; +} + function stringifyWithFunctions(obj) { if (typeof obj === 'function') return obj.toString(); if (obj === null || typeof obj !== 'object') return JSON.stringify(obj); if (isArray(obj)) { return '[' + obj.map(stringifyWithFunctions).join(',') + ']'; } else { - return '{' + keys(obj).map(function(key) { return key + ':' + stringifyWithFunctions(obj[key]) }).join(',') + '}'; + return '{' + keys(obj).map(function(key) { return escapeJSONKey(key) + ':' + stringifyWithFunctions(obj[key]) }).join(',') + '}'; } } diff --git a/tests/sockets/test_getprotobyname.c b/tests/sockets/test_getprotobyname.c new file mode 100644 index 00000000..571a287e --- /dev/null +++ b/tests/sockets/test_getprotobyname.c @@ -0,0 +1,87 @@ +#include <assert.h> +#include <errno.h> +#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +void checkEntryByValue(char* name, int port, char** aliasArray) { + struct protoent* entry; + char** aliases; + + // Perform a protocol look up by name + entry = getprotobyname(name); + assert(entry != NULL); + + // Check results + assert(strcmp(name, entry->p_name) == 0); + assert(port == entry->p_proto); + + aliases = entry->p_aliases; + for (int i = 0; aliases[i] != NULL; i++) { + assert(strcmp(aliases[i], aliasArray[i]) == 0); + } + + // Perform a protocol look up by number + entry = getprotobynumber(port); + assert(entry != NULL); + + // Check results + assert(strcmp(name, entry->p_name) == 0); + assert(port == entry->p_proto); + + aliases = entry->p_aliases; + for (int i = 0; aliases[i] != NULL; i++) { + assert(strcmp(aliases[i], aliasArray[i]) == 0); + } +} + +void checkEntryDatabase() { + struct protoent* entry; + + // Don't call setprotoent() initially as getprotoent() should open the "database" if necessary. + entry = getprotoent(); + assert(entry != NULL); + assert(strcmp("tcp", entry->p_name) == 0); + + entry = getprotoent(); + assert(entry != NULL); + assert(strcmp("udp", entry->p_name) == 0); + + // Check that setprotoent() correctly sets the next entry to the first entry + setprotoent(1); + + entry = getprotoent(); + assert(entry != NULL); + assert(strcmp("tcp", entry->p_name) == 0); + + entry = getprotoent(); + assert(entry != NULL); + assert(strcmp("udp", entry->p_name) == 0); + + // If we do a getprotoent() that goes past the end of the 'database' check that it returns NULL. + entry = getprotoent(); + assert(entry == NULL); +} + +int main() { + // First check getprotobyname() and getprotobynumber() + char* aliases[] = {"TCP"}; + checkEntryByValue("tcp", 6, aliases); + + aliases[0] = "UDP"; + checkEntryByValue("udp", 17, aliases); + + // Check that the doomsday protocol hasn't been implemented :-) ...... + assert(getprotobyname("doomsday") == NULL); + + // Now check setprotoent() and getprotoent() + checkEntryDatabase(); + + endprotoent(); + + puts("success"); + + return EXIT_SUCCESS; +} + diff --git a/tests/test_other.py b/tests/test_other.py index 5100db72..b10ae13b 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -2136,3 +2136,17 @@ int main() assert 'test.o' in head, 'Invalid dependency target' assert 'test.cpp' in tail and 'test.hpp' in tail, 'Invalid dependencies generated' + def test_quoted_js_lib_key(self): + open('lib.js', 'w').write(r''' +mergeInto(LibraryManager.library, { + __internal_data:{ + '<' : 0, + 'white space' : 1 + }, + printf__deps: ['__internal_data', 'fprintf'] +}); +''') + + Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.cpp'), '--js-library', 'lib.js']).communicate() + self.assertContained('hello, world!', run_js(os.path.join(self.get_dir(), 'a.out.js'))) + diff --git a/tests/test_sockets.py b/tests/test_sockets.py index 1229aa70..f9dcbc68 100644 --- a/tests/test_sockets.py +++ b/tests/test_sockets.py @@ -228,6 +228,9 @@ class sockets(BrowserCore): def test_gethostbyname(self): self.do_run(open(path_from_root('tests', 'sockets', 'test_gethostbyname.c')).read(), 'success') + def test_getprotobyname(self): + self.do_run(open(path_from_root('tests', 'sockets', 'test_getprotobyname.c')).read(), 'success') + def test_sockets_echo(self): sockets_include = '-I'+path_from_root('tests', 'sockets') diff --git a/tools/shared.py b/tools/shared.py index 3eb72a1e..3456ab18 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -316,7 +316,7 @@ def check_sanity(force=False): try: reason = None if not CONFIG_FILE: - if not force: return # config stored directly in EM_CONFIG => skip sanity checks + return # config stored directly in EM_CONFIG => skip sanity checks else: settings_mtime = os.stat(CONFIG_FILE).st_mtime sanity_file = CONFIG_FILE + '_sanity' @@ -637,7 +637,7 @@ def check_engine(engine): try: if not CONFIG_FILE: return True # config stored directly in EM_CONFIG => skip engine check - return 'hello, world!' in run_js(path_from_root('tests', 'hello_world.js'), engine) + return 'hello, world!' in run_js(path_from_root('src', 'hello_world.js'), engine) except Exception, e: print 'Checking JS engine %s failed. Check %s. Details: %s' % (str(engine), EM_CONFIG, str(e)) return False |