summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xemcc63
-rwxr-xr-xemscripten.py2
-rw-r--r--src/library.js117
-rw-r--r--src/library_openal.js195
-rw-r--r--src/parseTools.js4
-rw-r--r--src/runtime.js4
-rw-r--r--system/include/emscripten/emscripten.h6
-rw-r--r--tests/cases/i96shiftnon32_ta2.ll44
-rw-r--r--tests/cases/i96shiftnon32_ta2.txt1
-rw-r--r--tests/cases/legalizer_b_ta2.ll179
-rw-r--r--tests/cases/legalizer_b_ta2.txt20
-rw-r--r--tests/core/test_exceptions_alias.c15
-rw-r--r--tests/core/test_exceptions_alias.out2
-rw-r--r--tests/core/test_inlinejs3.in3
-rw-r--r--tests/core/test_longjmp_throw.cpp38
-rw-r--r--tests/core/test_longjmp_throw.out4
-rw-r--r--tests/openal_playback.cpp44
-rw-r--r--tests/poppler/utils/pdftoppm.cc5
-rw-r--r--tests/test_core.py31
-rw-r--r--tests/test_other.py27
-rw-r--r--tools/file_packager.py6
-rw-r--r--tools/find_bigis.py2
-rw-r--r--tools/shared.py2
23 files changed, 740 insertions, 74 deletions
diff --git a/emcc b/emcc
index 7460da61..83ce4529 100755
--- a/emcc
+++ b/emcc
@@ -61,6 +61,7 @@ BITCODE_ENDINGS = ('.bc', '.o', '.obj')
DYNAMICLIB_ENDINGS = ('.dylib', '.so', '.dll')
STATICLIB_ENDINGS = ('.a',)
ASSEMBLY_ENDINGS = ('.ll',)
+HEADER_ENDINGS = ('.h', '.hxx', '.hpp', '.hh', '.H', '.HXX', '.HPP', '.HH')
LIB_PREFIXES = ('', 'lib')
@@ -159,7 +160,8 @@ Options that are modified or new in %s include:
output.
-O3 As -O2, plus additional optimizations that can
- take a significant amount of compilation time.
+ take a significant amount of compilation time and/or
+ are relatively new.
For tips on optimizing your code, see
https://github.com/kripken/emscripten/wiki/Optimizing-Code
@@ -484,10 +486,13 @@ Options that are modified or new in %s include:
libraries, and after any link-time optimizations
(if any).
- --memory-init-file <on> If on, we generate a separate memory initialization
- file. This is more efficient than storing the
- memory initialization data embedded inside
- JavaScript as text. (default is off)
+ --memory-init-file <on> 0: Do not emit a separate memory initialization
+ file, keep the static initialization inside
+ the generated JavaScript as text (default)
+ 1: Emit a separate memory initialization file
+ in binary format. This is more efficient than
+ storing it as text inside JavaScript, but does
+ mean you have another file to publish.
-Wno-warn-absolute-paths If not specified, the compiler will warn about any
uses of absolute paths in -I and -L command line
@@ -695,15 +700,12 @@ if len(sys.argv) == 1 or sys.argv[1] in ['x', 't']:
sys.exit(0)
use_cxx = True
-header = False # pre-compiled headers. We fake that by just copying the file
for i in range(1, len(sys.argv)):
arg = sys.argv[i]
if not arg.startswith('-'):
if arg.endswith(('.c','.m')):
use_cxx = False
- if arg.endswith('.h') and sys.argv[i-1] != '-include':
- header = True
if '-M' in sys.argv or '-MM' in sys.argv:
# Just output dependencies, do not compile. Warning: clang and gcc behave differently with -MF! (clang seems to not recognize it)
@@ -737,15 +739,6 @@ if '.' in target:
else:
final_suffix = ''
-if header: # header or such
- if len(sys.argv) >= 3: # if there is a source and a target, then copy, otherwise do nothing
- sys.argv = filter(lambda arg: not arg.startswith('-I'), sys.argv)
- logging.debug('Just copy:' + sys.argv[-1] + target)
- shutil.copy(sys.argv[-1], target)
- else:
- logging.debug('No-op.')
- exit(0)
-
if TEMP_DIR:
temp_dir = TEMP_DIR
if os.path.exists(temp_dir):
@@ -1062,6 +1055,7 @@ try:
input_files = []
has_source_inputs = False
+ has_header_inputs = False
lib_dirs = [shared.path_from_root('system', 'local', 'lib'),
shared.path_from_root('system', 'lib')]
libs = []
@@ -1073,7 +1067,7 @@ try:
prev = newargs[i-1]
if prev in ['-MT', '-MF', '-MQ', '-D', '-U', '-o', '-x', '-Xpreprocessor', '-include', '-imacros', '-idirafter', '-iprefix', '-iwithprefix', '-iwithprefixbefore', '-isysroot', '-imultilib', '-A', '-isystem', '-iquote', '-install_name', '-compatibility_version', '-current_version', '-I', '-L']: continue # ignore this gcc-style argument
- if (os.path.islink(arg) and os.path.realpath(arg).endswith(SOURCE_ENDINGS + BITCODE_ENDINGS + DYNAMICLIB_ENDINGS + ASSEMBLY_ENDINGS)):
+ if (os.path.islink(arg) and os.path.realpath(arg).endswith(SOURCE_ENDINGS + BITCODE_ENDINGS + DYNAMICLIB_ENDINGS + ASSEMBLY_ENDINGS + HEADER_ENDINGS)):
arg = os.path.realpath(arg)
if not arg.startswith('-'):
@@ -1082,11 +1076,14 @@ try:
exit(1)
arg_ending = filename_type_ending(arg)
- if arg_ending.endswith(SOURCE_ENDINGS + BITCODE_ENDINGS + DYNAMICLIB_ENDINGS + ASSEMBLY_ENDINGS) or shared.Building.is_ar(arg): # we already removed -o <target>, so all these should be inputs
+ if arg_ending.endswith(SOURCE_ENDINGS + BITCODE_ENDINGS + DYNAMICLIB_ENDINGS + ASSEMBLY_ENDINGS + HEADER_ENDINGS) or shared.Building.is_ar(arg): # we already removed -o <target>, so all these should be inputs
newargs[i] = ''
if arg_ending.endswith(SOURCE_ENDINGS):
input_files.append(arg)
has_source_inputs = True
+ elif arg_ending.endswith(HEADER_ENDINGS):
+ input_files.append(arg)
+ has_header_inputs = True
elif arg_ending.endswith(ASSEMBLY_ENDINGS) or shared.Building.is_bitcode(arg): # this should be bitcode, make sure it is valid
input_files.append(arg)
elif arg_ending.endswith(STATICLIB_ENDINGS + DYNAMICLIB_ENDINGS):
@@ -1125,7 +1122,7 @@ try:
# -c means do not link in gcc, and for us, the parallel is to not go all the way to JS, but stop at bitcode
has_dash_c = '-c' in newargs
if has_dash_c:
- assert has_source_inputs, 'Must have source code inputs to use -c'
+ assert has_source_inputs or has_header_inputs, 'Must have source code or header inputs to use -c'
target = target_basename + '.o'
final_suffix = 'o'
@@ -1159,7 +1156,7 @@ try:
input_files = filter(lambda input_file: check(input_file), input_files)
if len(input_files) == 0:
- logging.error('no input files\nnote that input files without a known suffix are ignored, make sure your input files end with one of: ' + str(SOURCE_ENDINGS + BITCODE_ENDINGS + DYNAMICLIB_ENDINGS + STATICLIB_ENDINGS + ASSEMBLY_ENDINGS))
+ logging.error('no input files\nnote that input files without a known suffix are ignored, make sure your input files end with one of: ' + str(SOURCE_ENDINGS + BITCODE_ENDINGS + DYNAMICLIB_ENDINGS + STATICLIB_ENDINGS + ASSEMBLY_ENDINGS + HEADER_ENDINGS))
exit(0)
newargs = CC_ADDITIONAL_ARGS + newargs
@@ -1226,7 +1223,8 @@ try:
assert not shared.Settings.PGO, 'cannot run PGO in ASM_JS mode'
if shared.Settings.SAFE_HEAP and not js_opts:
- logging.warning('asm.js+SAFE_HEAP requires js opts to be run (-O1 or above by default)')
+ js_opts = True
+ logging.warning('enabling js opts to allow SAFE_HEAP to work properly')
if shared.Settings.ALLOW_MEMORY_GROWTH:
logging.error('Cannot enable ALLOW_MEMORY_GROWTH with asm.js, build with -s ASM_JS=0 if you need a growable heap');
@@ -1299,6 +1297,15 @@ try:
log_time('parse arguments and setup')
+ # Precompiled headers support
+ if has_header_inputs:
+ for header in input_files:
+ assert header.endswith(HEADER_ENDINGS), 'if you have one header input, we assume you want to precompile headers, and cannot have source files or other inputs as well: ' + str(input_files) + ' : ' + header
+ args = newargs + shared.EMSDK_CXX_OPTS + input_files
+ logging.debug("running (for precompiled headers: " + call + ' ' + ' '.join(args))
+ execute([call] + args) # let compiler frontend print directly, so colors are saved (PIPE kills that)
+ sys.exit(1)
+
# First, generate LLVM bitcode. For each input file, we get base.o with bitcode
for input_file in input_files:
file_ending = filename_type_ending(input_file)
@@ -1992,12 +1999,12 @@ try:
else:
return 'eliminate'
- js_optimizer_queue += [get_eliminate()]
+ if opt_level >= 2:
+ js_optimizer_queue += [get_eliminate()]
- if shared.Settings.AGGRESSIVE_VARIABLE_ELIMINATION:
- js_optimizer_queue += ['aggressiveVariableElimination']
+ if shared.Settings.AGGRESSIVE_VARIABLE_ELIMINATION:
+ js_optimizer_queue += ['aggressiveVariableElimination']
- if opt_level >= 2:
js_optimizer_queue += ['simplifyExpressions']
if closure and not shared.Settings.ASM_JS:
@@ -2016,13 +2023,13 @@ try:
js_optimizer_queue += ['outline']
js_optimizer_extra_info['sizeToOutline'] = shared.Settings.OUTLINING_LIMIT
- if (not closure or shared.Settings.ASM_JS) and shared.Settings.RELOOP and debug_level < 3:
+ if opt_level >= 2 and (not closure or shared.Settings.ASM_JS) and shared.Settings.RELOOP and debug_level < 3:
if shared.Settings.ASM_JS and opt_level >= 3 and shared.Settings.OUTLINING_LIMIT == 0:
js_optimizer_queue += ['registerizeHarder']
else:
js_optimizer_queue += ['registerize']
- if opt_level > 0:
+ if opt_level >= 2:
if debug_level < 2 and shared.Settings.ASM_JS: js_optimizer_queue += ['minifyNames']
if debug_level == 0: js_optimizer_queue += ['minifyWhitespace']
diff --git a/emscripten.py b/emscripten.py
index 725f573f..ce929858 100755
--- a/emscripten.py
+++ b/emscripten.py
@@ -1204,7 +1204,7 @@ Runtime.stackRestore = function(top) { asm['stackRestore'](top) };
if DEBUG: logging.debug(' emscript: final python processing took %s seconds' % (time.time() - t))
-if os.environ.get('EMCC_FAST_COMPILER'):
+if os.environ.get('EMCC_FAST_COMPILER') == '1':
emscript = emscript_fast
def main(args, compiler_engine, cache, jcache, relooper, temp_files, DEBUG, DEBUG_CACHE):
diff --git a/src/library.js b/src/library.js
index fc2e8a64..4c0f790f 100644
--- a/src/library.js
+++ b/src/library.js
@@ -162,7 +162,7 @@ LibraryManager.library = {
if (times) {
// NOTE: We don't keep track of access timestamps.
var offset = {{{ C_STRUCTS.utimbuf.modtime }}};
- time = {{{ makeGetValue('times', 'offset', 'i32') }}}
+ time = {{{ makeGetValue('times', 'offset', 'i32') }}};
time *= 1000;
} else {
time = Date.now();
@@ -1182,7 +1182,7 @@ LibraryManager.library = {
for (var i = 0; i < length; i++) {
{{{ makeSetValue('buf', 'i', 'value.charCodeAt(i)', 'i8') }}};
}
- if (len > length) {{{ makeSetValue('buf', 'i++', '0', 'i8') }}}
+ if (len > length) {{{ makeSetValue('buf', 'i++', '0', 'i8') }}};
return i;
}
},
@@ -3229,22 +3229,34 @@ LibraryManager.library = {
strtoll: function(str, endptr, base) {
return __parseInt64(str, endptr, base, '-9223372036854775808', '9223372036854775807'); // LLONG_MIN, LLONG_MAX.
},
- strtoll_l: 'strtoll', // no locale support yet
+ strtoll_l__deps: ['strtoll'],
+ strtoll_l: function(str, endptr, base) {
+ return _strtoll(str, endptr, base); // no locale support yet
+ },
strtol__deps: ['_parseInt'],
strtol: function(str, endptr, base) {
return __parseInt(str, endptr, base, -2147483648, 2147483647, 32); // LONG_MIN, LONG_MAX.
},
- strtol_l: 'strtol', // no locale support yet
+ strtol_l__deps: ['strtol'],
+ strtol_l: function(str, endptr, base) {
+ return _strtol(str, endptr, base); // no locale support yet
+ },
strtoul__deps: ['_parseInt'],
strtoul: function(str, endptr, base) {
return __parseInt(str, endptr, base, 0, 4294967295, 32, true); // ULONG_MAX.
},
- strtoul_l: 'strtoul', // no locale support yet
+ strtoul_l__deps: ['strtoul'],
+ strtoul_l: function(str, endptr, base) {
+ return _strtoul(str, endptr, base); // no locale support yet
+ },
strtoull__deps: ['_parseInt64'],
strtoull: function(str, endptr, base) {
return __parseInt64(str, endptr, base, 0, '18446744073709551615', true); // ULONG_MAX.
},
- strtoull_l: 'strtoull', // no locale support yet
+ strtoull_l__deps: ['strtoull'],
+ strtoull_l: function(str, endptr, base) {
+ return _strtoull(str, endptr, base); // no locale support yet
+ },
atoi__deps: ['strtol'],
atoi: function(ptr) {
@@ -3735,7 +3747,10 @@ LibraryManager.library = {
},
// We always assume ASCII locale.
strcoll: 'strcmp',
- strcoll_l: 'strcmp',
+ strcoll_l__deps: ['strcoll'],
+ strcoll_l: function(px, py) {
+ return _strcoll(px, py); // no locale support yet
+ },
strcasecmp__asm: true,
strcasecmp__sig: 'iii',
@@ -4000,7 +4015,10 @@ LibraryManager.library = {
}
},
_toupper: 'toupper',
- toupper_l: 'toupper',
+ toupper_l__deps: ['toupper'],
+ toupper_l: function(str, endptr, base) {
+ return _toupper(str, endptr, base); // no locale support yet
+ },
tolower__asm: true,
tolower__sig: 'ii',
@@ -4011,65 +4029,104 @@ LibraryManager.library = {
return (chr - {{{ charCode('A') }}} + {{{ charCode('a') }}})|0;
},
_tolower: 'tolower',
- tolower_l: 'tolower',
+ tolower_l__deps: ['tolower'],
+ tolower_l: function(chr) {
+ return _tolower(chr); // no locale support yet
+ },
// The following functions are defined as macros in glibc.
islower: function(chr) {
return chr >= {{{ charCode('a') }}} && chr <= {{{ charCode('z') }}};
},
- islower_l: 'islower',
+ islower_l__deps: ['islower'],
+ islower_l: function(chr) {
+ return _islower(chr); // no locale support yet
+ },
isupper: function(chr) {
return chr >= {{{ charCode('A') }}} && chr <= {{{ charCode('Z') }}};
},
- isupper_l: 'isupper',
+ isupper_l__deps: ['isupper'],
+ isupper_l: function(chr) {
+ return _isupper(chr); // no locale support yet
+ },
isalpha: function(chr) {
return (chr >= {{{ charCode('a') }}} && chr <= {{{ charCode('z') }}}) ||
(chr >= {{{ charCode('A') }}} && chr <= {{{ charCode('Z') }}});
},
- isalpha_l: 'isalpha',
+ isalpha_l__deps: ['isalpha'],
+ isalpha_l: function(chr) {
+ return _isalpha(chr); // no locale support yet
+ },
isdigit: function(chr) {
return chr >= {{{ charCode('0') }}} && chr <= {{{ charCode('9') }}};
},
- isdigit_l: 'isdigit',
+ isdigit_l__deps: ['isdigit'],
+ isdigit_l: function(chr) {
+ return _isdigit(chr); // no locale support yet
+ },
isxdigit: function(chr) {
return (chr >= {{{ charCode('0') }}} && chr <= {{{ charCode('9') }}}) ||
(chr >= {{{ charCode('a') }}} && chr <= {{{ charCode('f') }}}) ||
(chr >= {{{ charCode('A') }}} && chr <= {{{ charCode('F') }}});
},
- isxdigit_l: 'isxdigit',
+ isxdigit_l__deps: ['isxdigit'],
+ isxdigit_l: function(chr) {
+ return _isxdigit(chr); // no locale support yet
+ },
isalnum: function(chr) {
return (chr >= {{{ charCode('0') }}} && chr <= {{{ charCode('9') }}}) ||
(chr >= {{{ charCode('a') }}} && chr <= {{{ charCode('z') }}}) ||
(chr >= {{{ charCode('A') }}} && chr <= {{{ charCode('Z') }}});
},
- isalnum_l: 'isalnum',
+ isalnum_l__deps: ['isalnum'],
+ isalnum_l: function(chr) {
+ return _isalnum(chr); // no locale support yet
+ },
ispunct: function(chr) {
return (chr >= {{{ charCode('!') }}} && chr <= {{{ charCode('/') }}}) ||
(chr >= {{{ charCode(':') }}} && chr <= {{{ charCode('@') }}}) ||
(chr >= {{{ charCode('[') }}} && chr <= {{{ charCode('`') }}}) ||
(chr >= {{{ charCode('{') }}} && chr <= {{{ charCode('~') }}});
},
- ispunct_l: 'ispunct',
+ ispunct_l__deps: ['ispunct'],
+ ispunct_l: function(chr) {
+ return _ispunct(chr); // no locale support yet
+ },
isspace: function(chr) {
return (chr == 32) || (chr >= 9 && chr <= 13);
},
- isspace_l: 'isspace',
+ isspace_l__deps: ['isspace'],
+ isspace_l: function(chr) {
+ return _isspace(chr); // no locale support yet
+ },
isblank: function(chr) {
return chr == {{{ charCode(' ') }}} || chr == {{{ charCode('\t') }}};
},
- isblank_l: 'isblank',
+ isblank_l__deps: ['isblank'],
+ isblank_l: function(chr) {
+ return _isblank(chr); // no locale support yet
+ },
iscntrl: function(chr) {
return (0 <= chr && chr <= 0x1F) || chr === 0x7F;
},
- iscntrl_l: 'iscntrl',
+ iscntrl_l__deps: ['iscntrl'],
+ iscntrl_l: function(chr) {
+ return _iscntrl(chr); // no locale support yet
+ },
isprint: function(chr) {
return 0x1F < chr && chr < 0x7F;
},
- isprint_l: 'isprint',
+ isprint_l__deps: ['isprint'],
+ isprint_l: function(chr) {
+ return _isprint(chr); // no locale support yet
+ },
isgraph: function(chr) {
return 0x20 < chr && chr < 0x7F;
},
- isgraph_l: 'isgraph',
+ isgraph_l__deps: ['isgraph'],
+ isgraph_l: function(chr) {
+ return _isgraph(chr); // no locale support yet
+ },
// Lookup tables for glibc ctype implementation.
__ctype_b_loc: function() {
// http://refspecs.freestandards.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/baselib---ctype-b-loc.html
@@ -4365,8 +4422,8 @@ LibraryManager.library = {
Module.printErr('Compiled code throwing an exception, ' + [ptr,type,destructor] + ', at ' + stackTrace());
#endif
var header = ptr - ___cxa_exception_header_size;
- {{{ makeSetValue('header', 0, 'type', 'void*') }}}
- {{{ makeSetValue('header', 4, 'destructor', 'void*') }}}
+ {{{ makeSetValue('header', 0, 'type', 'void*') }}};
+ {{{ makeSetValue('header', 4, 'destructor', 'void*') }}};
___cxa_last_thrown_exception = ptr;
if (!("uncaught_exception" in __ZSt18uncaught_exceptionv)) {
__ZSt18uncaught_exceptionv.uncaught_exception = 1;
@@ -4434,7 +4491,7 @@ LibraryManager.library = {
var destructor = {{{ makeGetValue('header', 4, 'void*') }}};
if (destructor) {
Runtime.dynCall('vi', destructor, [ptr]);
- {{{ makeSetValue('header', 4, '0', 'i32') }}}
+ {{{ makeSetValue('header', 4, '0', 'i32') }}};
}
___cxa_free_exception(ptr);
___cxa_last_thrown_exception = 0;
@@ -5887,7 +5944,10 @@ LibraryManager.library = {
writeArrayToMemory(bytes, s);
return bytes.length-1;
},
- strftime_l: 'strftime', // no locale support yet
+ strftime_l__deps: ['strftime'],
+ strftime_l: function(s, maxsize, format, tm) {
+ return _strftime(s, maxsize, format, tm); // no locale support yet
+ },
strptime__deps: ['_isLeapYear', '_arraySum', '_addDays', '_MONTH_DAYS_REGULAR', '_MONTH_DAYS_LEAP'],
strptime: function(buf, format, tm) {
@@ -6129,7 +6189,10 @@ LibraryManager.library = {
return 0;
},
- strptime_l: 'strptime', // no locale support yet
+ strptime_l__deps: ['strptime'],
+ strptime_l: function(buf, format, tm) {
+ return _strptime(buf, format, tm); // no locale support yet
+ },
getdate: function(string) {
// struct tm *getdate(const char *string);
@@ -7630,7 +7693,7 @@ LibraryManager.library = {
node = DNS.lookup_name(node);
addr = __inet_pton4_raw(node);
if (family === {{{ cDefine('AF_UNSPEC') }}}) {
- family = {{{ cDefine('AF_INET') }}}
+ family = {{{ cDefine('AF_INET') }}};
} else if (family === {{{ cDefine('AF_INET6') }}}) {
addr = [0, 0, _htonl(0xffff), addr];
}
diff --git a/src/library_openal.js b/src/library_openal.js
index 67481824..ac49fe95 100644
--- a/src/library_openal.js
+++ b/src/library_openal.js
@@ -5,6 +5,10 @@ var LibraryOpenAL = {
$AL: {
contexts: [],
currentContext: null,
+
+ stringCache: {},
+ alcStringCache: {},
+
QUEUE_INTERVAL: 25,
QUEUE_LOOKAHEAD: 100,
@@ -235,6 +239,42 @@ var LibraryOpenAL = {
return _alGetError();
},
+ alcGetIntegerv: function(device, param, size, data) {
+ if (size == 0 || !data) {
+ AL.currentContext.err = 0xA003 /* AL_INVALID_VALUE */;
+ return;
+ }
+
+ switch(param) {
+ case 0x1000 /* ALC_MAJOR_VERSION */:
+ {{{ makeSetValue('data', '0', '1', 'i32') }}};
+ break;
+ case 0x1001 /* ALC_MINOR_VERSION */:
+ {{{ makeSetValue('data', '0', '1', 'i32') }}};
+ break;
+ case 0x1002 /* ALC_ATTRIBUTES_SIZE */:
+ if (!device) {
+ AL.currentContext.err = 0xA001 /* ALC_INVALID_DEVICE */;
+ return 0;
+ }
+ {{{ makeSetValue('data', '0', '1', 'i32') }}};
+ break;
+ case 0x1003 /* ALC_ALL_ATTRIBUTES */:
+ if (!device) {
+ AL.currentContext.err = 0xA001 /* ALC_INVALID_DEVICE */;
+ return 0;
+ }
+ {{{ makeSetValue('data', '0', '0', 'i32') }}};
+ break;
+ default:
+#if OPENAL_DEBUG
+ console.log("alcGetIntegerv with param " + param + " not implemented yet");
+#endif
+ AL.currentContext.err = 0xA003 /* ALC_INVALID_ENUM */;
+ break;
+ }
+ },
+
alDeleteSources: function(count, sources) {
if (!AL.currentContext) {
#if OPENAL_DEBUG
@@ -334,6 +374,18 @@ var LibraryOpenAL = {
}
},
+ alIsSource: function(sourceId) {
+ if (!AL.currentContext) {
+ return false;
+ }
+
+ if (!AL.currentContext.src[sourceId - 1]) {
+ return false;
+ } else {
+ return true;
+ }
+ },
+
alSourcei__deps: ['updateSource'],
alSourcei: function(source, param, value) {
if (!AL.currentContext) {
@@ -691,6 +743,7 @@ var LibraryOpenAL = {
}
try {
AL.currentContext.buf[buffer - 1] = AL.currentContext.ctx.createBuffer(channels, size / (bytes * channels), freq);
+ AL.currentContext.buf[buffer - 1].bytesPerSample = bytes;
} catch (e) {
AL.currentContext.err = 0xA003 /* AL_INVALID_VALUE */;
return;
@@ -715,6 +768,41 @@ var LibraryOpenAL = {
}
},
+ alGetBufferi: function(buffer, param, value)
+ {
+ if (!AL.currentContext) {
+#if OPENAL_DEBUG
+ console.error("alGetBufferi called without a valid context");
+#endif
+ return;
+ }
+ var buf = AL.currentContext.buf[buffer - 1];
+ if (!buf) {
+#if OPENAL_DEBUG
+ console.error("alGetBufferi called with an invalid buffer");
+#endif
+ AL.currentContext.err = 0xA001 /* AL_INVALID_NAME */;
+ return;
+ }
+ switch (param) {
+ case 0x2001 /* AL_FREQUENCY */:
+ {{{ makeSetValue('value', '0', 'buf.sampleRate', 'i32') }}};
+ break;
+ case 0x2002 /* AL_BITS */:
+ {{{ makeSetValue('value', '0', 'buf.bytesPerSample * 8', 'i32') }}};
+ break;
+ case 0x2003 /* AL_CHANNELS */:
+ {{{ makeSetValue('value', '0', 'buf.numberOfChannels', 'i32') }}};
+ break;
+ case 0x2004 /* AL_SIZE */:
+ {{{ makeSetValue('value', '0', 'buf.length * buf.bytesPerSample * buf.numberOfChannels', 'i32') }}};
+ break;
+ default:
+ AL.currentContext.err = 0xA002 /* AL_INVALID_ENUM */;
+ break;
+ }
+ },
+
alSourcePlay__deps: ['setSourceState'],
alSourcePlay: function(source) {
if (!AL.currentContext) {
@@ -1128,15 +1216,116 @@ var LibraryOpenAL = {
},
alGetString: function(param) {
- return allocate(intArrayFromString('NA'), 'i8', ALLOC_NORMAL);
+ if (AL.stringCache[param]) return AL.stringCache[param];
+ var ret;
+ switch (param) {
+ case 0 /* AL_NO_ERROR */:
+ ret = 'No Error';
+ break;
+ case 0xA001 /* AL_INVALID_NAME */:
+ ret = 'Invalid Name';
+ break;
+ case 0xA002 /* AL_INVALID_ENUM */:
+ ret = 'Invalid Enum';
+ break;
+ case 0xA003 /* AL_INVALID_VALUE */:
+ ret = 'Invalid Value';
+ break;
+ case 0xA004 /* AL_INVALID_OPERATION */:
+ ret = 'Invalid Operation';
+ break;
+ case 0xA005 /* AL_OUT_OF_MEMORY */:
+ ret = 'Out of Memory';
+ break;
+ case 0xB001 /* AL_VENDOR */:
+ ret = 'Emscripten';
+ break;
+ case 0xB002 /* AL_VERSION */:
+ ret = '1.1';
+ break;
+ case 0xB003 /* AL_RENDERER */:
+ ret = 'WebAudio';
+ break;
+ case 0xB004 /* AL_EXTENSIONS */:
+ ret = '';
+ break;
+ default:
+ AL.currentContext.err = 0xA002 /* AL_INVALID_ENUM */;
+ return 0;
+ }
+
+ ret = allocate(intArrayFromString(ret), 'i8', ALLOC_NORMAL);
+
+ AL.stringCache[param] = ret;
+
+ return ret;
},
alGetProcAddress: function(fname) {
return 0;
},
- alcGetString: function(param) {
- return allocate(intArrayFromString('NA'), 'i8', ALLOC_NORMAL);
+ alcGetString: function(device, param) {
+ if (AL.alcStringCache[param]) return AL.alcStringCache[param];
+ var ret;
+ switch (param) {
+ case 0 /* ALC_NO_ERROR */:
+ ret = 'No Error';
+ break;
+ case 0xA001 /* ALC_INVALID_DEVICE */:
+ ret = 'Invalid Device';
+ break;
+ case 0xA002 /* ALC_INVALID_CONTEXT */:
+ ret = 'Invalid Context';
+ break;
+ case 0xA003 /* ALC_INVALID_ENUM */:
+ ret = 'Invalid Enum';
+ break;
+ case 0xA004 /* ALC_INVALID_VALUE */:
+ ret = 'Invalid Value';
+ break;
+ case 0xA005 /* ALC_OUT_OF_MEMORY */:
+ ret = 'Out of Memory';
+ break;
+ case 0x1004 /* ALC_DEFAULT_DEVICE_SPECIFIER */:
+ if (typeof(AudioContext) == "function" ||
+ typeof(webkitAudioContext) == "function") {
+ ret = 'Device';
+ } else {
+ return 0;
+ }
+ break;
+ case 0x1005 /* ALC_DEVICE_SPECIFIER */:
+ if (typeof(AudioContext) == "function" ||
+ typeof(webkitAudioContext) == "function") {
+ ret = 'Device\0';
+ } else {
+ ret = '\0';
+ }
+ break;
+ case 0x311 /* ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER */:
+ return 0;
+ break;
+ case 0x310 /* ALC_CAPTURE_DEVICE_SPECIFIER */:
+ ret = '\0'
+ break;
+ case 0x1006 /* ALC_EXTENSIONS */:
+ if (!device) {
+ AL.currentContext.err = 0xA001 /* ALC_INVALID_DEVICE */;
+ return 0;
+ }
+ ret = '';
+ break;
+ default:
+ AL.currentContext.err = 0xA003 /* ALC_INVALID_ENUM */;
+ return 0;
+ }
+
+ ret = allocate(intArrayFromString(ret), 'i8', ALLOC_NORMAL);
+
+ AL.alcStringCache[param] = ret;
+
+ return ret;
},
alcGetProcAddress: function(device, fname) {
diff --git a/src/parseTools.js b/src/parseTools.js
index e09cd2e2..bad080b7 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -1332,7 +1332,7 @@ function makeGetValue(ptr, pos, type, noNeedFirst, unsigned, ignore, align, noSa
if (printType !== 'null' && printType[0] !== '#') printType = '"' + safeQuote(printType) + '"';
if (printType[0] === '#') printType = printType.substr(1);
if (ASM_JS) {
- if (!ignore) return asmCoercion('SAFE_HEAP_LOAD(' + asmCoercion(offset, 'i32') + ', ' + Runtime.getNativeTypeSize(type) + ', ' + ((type in Runtime.FLOAT_TYPES)|0) + ', ' + (!!unsigned+0) + ')', type);
+ if (!ignore && phase !== 'funcs') return asmCoercion('SAFE_HEAP_LOAD(' + asmCoercion(offset, 'i32') + ', ' + Runtime.getNativeTypeSize(type) + ', ' + ((type in Runtime.FLOAT_TYPES)|0) + ', ' + (!!unsigned+0) + ')', type);
// else fall through
} else {
return asmCoercion('SAFE_HEAP_LOAD(' + offset + ', ' + (ASM_JS ? 0 : printType) + ', ' + (!!unsigned+0) + ', ' + ((!checkSafeHeap() || ignore)|0) + ')', type);
@@ -1444,7 +1444,7 @@ function makeSetValue(ptr, pos, value, type, noNeedFirst, ignore, align, noSafe,
if (printType !== 'null' && printType[0] !== '#') printType = '"' + safeQuote(printType) + '"';
if (printType[0] === '#') printType = printType.substr(1);
if (ASM_JS) {
- if (!ignore) return asmCoercion('SAFE_HEAP_STORE(' + asmCoercion(offset, 'i32') + ', ' + asmCoercion(value, type) + ', ' + Runtime.getNativeTypeSize(type) + ', ' + ((type in Runtime.FLOAT_TYPES)|0) + ')', type);
+ if (!ignore && phase !== 'funcs') return asmCoercion('SAFE_HEAP_STORE(' + asmCoercion(offset, 'i32') + ', ' + asmCoercion(value, type) + ', ' + Runtime.getNativeTypeSize(type) + ', ' + ((type in Runtime.FLOAT_TYPES)|0) + ')', type);
// else fall through
} else {
return 'SAFE_HEAP_STORE(' + offset + ', ' + value + ', ' + (ASM_JS ? 0 : printType) + ', ' + ((!checkSafeHeap() || ignore)|0) + ')';
diff --git a/src/runtime.js b/src/runtime.js
index 4fcca56b..a9265e70 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -565,7 +565,7 @@ function getRuntime() {
// Converts a value we have as signed, into an unsigned value. For
// example, -1 in int32 would be a very large number as unsigned.
-function unSign(value, bits, ignore, sig) {
+function unSign(value, bits, ignore) {
if (value >= 0) {
return value;
}
@@ -578,7 +578,7 @@ function unSign(value, bits, ignore, sig) {
// Converts a value we have as unsigned, into a signed value. For
// example, 200 in a uint8 would be a negative number.
-function reSign(value, bits, ignore, sig) {
+function reSign(value, bits, ignore) {
if (value <= 0) {
return value;
}
diff --git a/system/include/emscripten/emscripten.h b/system/include/emscripten/emscripten.h
index fb456d67..2fc82f50 100644
--- a/system/include/emscripten/emscripten.h
+++ b/system/include/emscripten/emscripten.h
@@ -50,10 +50,14 @@ extern "C" {
* return $0 + $1;
* }, calc(), otherCalc());
*
- * Note the {,}
+ * Note the { and }. If you just want to receive an output value
+ * (int or double) but *not* to pass any values, you can use
+ * EM_ASM_INT_V and EM_ASM_DOUBLE_V respectively.
*/
#define EM_ASM_INT(code, ...) emscripten_asm_const_int(#code, __VA_ARGS__)
#define EM_ASM_DOUBLE(code, ...) emscripten_asm_const_double(#code, __VA_ARGS__)
+#define EM_ASM_INT_V(code) emscripten_asm_const_int(#code)
+#define EM_ASM_DOUBLE_V(code) emscripten_asm_const_double(#code)
/*
* Forces LLVM to not dead-code-eliminate a function. Note that
diff --git a/tests/cases/i96shiftnon32_ta2.ll b/tests/cases/i96shiftnon32_ta2.ll
new file mode 100644
index 00000000..55e84575
--- /dev/null
+++ b/tests/cases/i96shiftnon32_ta2.ll
@@ -0,0 +1,44 @@
+; ModuleID = '/tmp/tmpxFUbAg/test_emcc1.bc'
+target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:32"
+target triple = "le32-unknown-nacl"
+
+%struct.c_s = type { i8, float, i32 }
+
+@.str = private unnamed_addr constant [12 x i8] c"RESULT: %d\0A\00", align 1
+
+define internal fastcc void @f2(%struct.c_s* noalias nocapture sret %agg.result) nounwind {
+ %agg.result.1 = getelementptr inbounds %struct.c_s* %agg.result, i32 0, i32 1
+ store float 0.000000e+00, float* %agg.result.1, align 4
+ %agg.result.2 = getelementptr inbounds %struct.c_s* %agg.result, i32 0, i32 2
+ store i32 43110, i32* %agg.result.2, align 4
+ ret void
+}
+
+define internal fastcc void @f1(%struct.c_s* nocapture %tp) nounwind {
+ %1 = alloca %struct.c_s, align 8
+ call fastcc void @f2(%struct.c_s* sret %1)
+ %2 = bitcast %struct.c_s* %1 to i96*
+ %srcval1 = load i96* %2, align 8
+ %small = trunc i96 %srcval1 to i64
+ %large = zext i64 %small to i96
+ %return = or i96 %srcval1, %large
+ %3 = lshr i96 %return, 4
+ %4 = shl i96 %3, 2
+ %5 = bitcast %struct.c_s* %tp to i96*
+ store i96 %4, i96* %5, align 4
+ ret void
+}
+
+define i32 @main() nounwind {
+ %t = alloca %struct.c_s, align 4
+ %1 = getelementptr inbounds %struct.c_s* %t, i32 0, i32 1
+ store float 1.000000e+00, float* %1, align 4
+ call fastcc void @f1(%struct.c_s* %t)
+ %2 = getelementptr inbounds %struct.c_s* %t, i32 0, i32 2
+ %3 = load i32* %2, align 4
+ %4 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([12 x i8]* @.str, i32 0, i32 0), i32 %3) nounwind
+ ret i32 0
+}
+
+declare i32 @printf(i8* nocapture, ...) nounwind
+
diff --git a/tests/cases/i96shiftnon32_ta2.txt b/tests/cases/i96shiftnon32_ta2.txt
new file mode 100644
index 00000000..1e26a65f
--- /dev/null
+++ b/tests/cases/i96shiftnon32_ta2.txt
@@ -0,0 +1 @@
+RESULT: 10777
diff --git a/tests/cases/legalizer_b_ta2.ll b/tests/cases/legalizer_b_ta2.ll
new file mode 100644
index 00000000..a6214100
--- /dev/null
+++ b/tests/cases/legalizer_b_ta2.ll
@@ -0,0 +1,179 @@
+; ModuleID = 'tests/hello_world.bc'
+target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:32"
+target triple = "le32-unknown-nacl"
+
+@globaliz = global [300 x i8] zeroinitializer
+
+define i64 @retter(i64 %x) {
+ store i128 0, i128* bitcast ([300 x i8]* @globaliz to i128*), align 4 ; wipe it out
+ store i64 %x, i64* bitcast ([300 x i8]* @globaliz to i64*), align 4
+ call i32 (i8*)* @puts(i8* bitcast ([300 x i8]* @globaliz to i8*))
+ ret i64 7017280452245743464
+}
+
+define i32 @main() {
+entry:
+ %buffer = alloca i8, i32 1000, align 4
+ %bundled = bitcast i8* %buffer to i128*
+ store i128 8583909746840200552, i128* %bundled, align 4 ; hello world in there
+ call i32 (i8*)* @puts(i8* %buffer)
+
+ %loaded = load i128* %bundled, align 4 ; save for later
+
+ %backcast = bitcast i128* %bundled to i8*
+ call i32 (i8*)* @puts(i8* %backcast)
+
+ %temp.buffer = bitcast i8* %buffer to [0 x i8]*
+ %buffer1 = getelementptr [0 x i8]* %temp.buffer, i32 0, i32 1
+ %bundled1 = bitcast i8* %buffer1 to i128*
+ store i128 9862834326869351064, i128* %bundled1, align 1 ; unaligned
+ call i32 (i8*)* @puts(i8* %buffer)
+
+; shifts
+ %shifted = lshr i128 %loaded, 16
+ store i128 %shifted, i128* %bundled, align 4
+ call i32 (i8*)* @puts(i8* %buffer)
+ %shifted2 = lshr i128 %loaded, 32
+ store i128 %shifted2, i128* %bundled, align 4
+ call i32 (i8*)* @puts(i8* %buffer)
+
+; store %loaded, make sure has not been modified
+ store i128 %loaded, i128* %bundled, align 4
+ call i32 (i8*)* @puts(i8* %buffer)
+
+ %shifted3 = shl i128 %loaded, 8
+ store i128 %shifted3, i128* %bundled, align 4
+ store i8 113, i8* %buffer ; remove initial 0 ; 'q'
+ call i32 (i8*)* @puts(i8* %buffer)
+
+; trunc
+ %shifted4 = shl i128 %loaded, 64
+ store i128 %shifted4, i128* %bundled, align 4
+ %nonzero64 = trunc i128 %loaded to i64 ; remove initial zeros
+ %bundled64 = bitcast i128* %bundled to i64*
+ store i64 %nonzero64, i64* %bundled64, align 4
+; call i32 (i8*)* @puts(i8* %buffer)
+
+ store i128 0, i128* %bundled, align 4 ; wipe it out
+ %small32 = trunc i128 %loaded to i32
+ %buffer32 = bitcast i8* %buffer to i32*
+ store i32 %small32, i32* %buffer32, align 4
+; call i32 (i8*)* @puts(i8* %buffer)
+
+ store i128 0, i128* %bundled, align 4 ; wipe it out
+ %small16 = trunc i128 %loaded to i16
+ %buffer16 = bitcast i8* %buffer to i16*
+ store i16 %small16, i16* %buffer16, align 4
+ call i32 (i8*)* @puts(i8* %buffer)
+
+ store i128 0, i128* %bundled, align 4 ; wipe it out
+ %small64 = trunc i128 %loaded to i64
+ %buffer64 = bitcast i8* %buffer to i64*
+ store i64 %small64, i64* %buffer64, align 4
+ call i32 (i8*)* @puts(i8* %buffer)
+
+; zext
+ store i128 0, i128* %bundled, align 4 ; wipe it out
+ %pre32 = or i32 6382179, 0
+ %big = zext i32 %pre32 to i128
+ store i128 %big, i128* %bundled, align 4
+ call i32 (i8*)* @puts(i8* %buffer)
+
+ store i128 0, i128* %bundled, align 4 ; wipe it out
+ %pre64 = zext i32 1684366951 to i64
+ %post64 = shl i64 %pre64, 32
+ %big64 = or i64 %pre64, %post64
+ %bigb = zext i64 %big64 to i128
+ store i128 %bigb, i128* %bundled, align 4
+ call i32 (i8*)* @puts(i8* %buffer)
+
+; or, and, xor
+ %ored = or i128 %loaded, 107752139522048 ; constant
+ store i128 %ored, i128* %bundled, align 4
+ call i32 (i8*)* @puts(i8* %buffer)
+
+ %ander = trunc i128 18402271027389267967 to i128
+ %anded = and i128 %loaded, %ander ; variable
+ store i128 %anded, i128* %bundled, align 4
+ call i32 (i8*)* @puts(i8* %buffer)
+
+ %xored = xor i128 %loaded, 0
+ store i128 %xored, i128* %bundled, align 4
+ call i32 (i8*)* @puts(i8* %buffer)
+
+; unfolding
+ store i128 %loaded, i128* bitcast ([300 x i8]* @globaliz to i128*), align 4
+ %loaded.short = load i96* bitcast ([300 x i8]* @globaliz to i96*), align 4
+ store i128 0, i128* bitcast ([300 x i8]* @globaliz to i128*), align 4
+ store i96 %loaded.short, i96* bitcast ([300 x i8]* @globaliz to i96*), align 4
+ call i32 (i8*)* @puts(i8* bitcast ([300 x i8]* @globaliz to i8*))
+
+; phi
+ %if = trunc i128 %ander to i1
+ %first = trunc i128 %xored to i96
+ br i1 %if, label %a17, label %a26
+
+a17:
+ %second = trunc i128 %loaded to i96
+ br label %a26
+
+a26:
+ %a27 = phi i96 [ %first, %entry ], [ %second, %a17 ]
+ store i128 0, i128* %bundled, align 4 ; wipe it out
+ store i96 %a27, i96* bitcast ([300 x i8]* @globaliz to i96*), align 4
+ call i32 (i8*)* @puts(i8* bitcast ([300 x i8]* @globaliz to i8*))
+
+; phi with constants
+ br i1 %if, label %a17b, label %a26b
+
+a17b:
+ br label %a26b
+
+a26b:
+ %a27b = phi i64 [ 55, %a26 ], [ 57, %a17b ]
+ store i128 0, i128* %bundled, align 4 ; wipe it out
+ store i64 %a27b, i64* bitcast ([300 x i8]* @globaliz to i64*), align 4
+ call i32 (i8*)* @puts(i8* bitcast ([300 x i8]* @globaliz to i8*))
+
+ store i128 %ored, i128* %bundled, align 4
+ %iff = zext i1 %if to i64
+ switch i64 %iff, label %a50 [
+ i64 1, label %a30
+ i64 0, label %a40
+ ]
+
+a50:
+ store i128 %xored, i128* %bundled, align 4
+ br label %a40
+
+a30:
+ store i128 %anded, i128* %bundled, align 4
+ br label %a40
+
+a40:
+ call i32 (i8*)* @puts(i8* %buffer)
+
+; invoke return value
+
+ %inv64 = invoke i64 @retter(i64 8174723217654970232)
+ to label %a100 unwind label %a111
+
+a100:
+ store i128 0, i128* bitcast ([300 x i8]* @globaliz to i128*), align 4 ; wipe it out
+ store i64 %inv64, i64* bitcast ([300 x i8]* @globaliz to i64*), align 4
+ call i32 (i8*)* @puts(i8* bitcast ([300 x i8]* @globaliz to i8*))
+ br label %done
+
+a111:
+ %aaaa79 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ cleanup
+ br label %done
+
+done:
+ ret i32 1
+}
+
+declare i32 @puts(i8*)
+declare i32 @__gxx_personality_v0(...)
+declare void @__cxa_throw(i32, i32, i32) ; for asm1, where exceptions are enabled but this test needs a throw to bring in lib stuff
+
diff --git a/tests/cases/legalizer_b_ta2.txt b/tests/cases/legalizer_b_ta2.txt
new file mode 100644
index 00000000..27097159
--- /dev/null
+++ b/tests/cases/legalizer_b_ta2.txt
@@ -0,0 +1,20 @@
+hello, w
+hello, w
+h𚓓𓟈
+llo, w
+o, w
+hello, w
+qhello, w
+he
+hello, w
+cba
+gfedgfed
+hellon w
+hello, w
+hello, w
+hello, w
+hello, w
+9
+hello, w
+xwvutsrq
+hgfedcba
diff --git a/tests/core/test_exceptions_alias.c b/tests/core/test_exceptions_alias.c
new file mode 100644
index 00000000..0c8cc37a
--- /dev/null
+++ b/tests/core/test_exceptions_alias.c
@@ -0,0 +1,15 @@
+#define _POSIX_SOURCE
+#include <locale.h>
+#include <ctype.h>
+#include <stdio.h>
+
+int main(void) {
+ try {
+ printf("*%i*\n", isdigit('0'));
+ printf("*%i*\n", isdigit_l('0', LC_GLOBAL_LOCALE));
+ }
+ catch (...) {
+ printf("EXCEPTION!\n");
+ }
+}
+
diff --git a/tests/core/test_exceptions_alias.out b/tests/core/test_exceptions_alias.out
new file mode 100644
index 00000000..2f67e501
--- /dev/null
+++ b/tests/core/test_exceptions_alias.out
@@ -0,0 +1,2 @@
+*1*
+*1*
diff --git a/tests/core/test_inlinejs3.in b/tests/core/test_inlinejs3.in
index e21ed041..9ddd5907 100644
--- a/tests/core/test_inlinejs3.in
+++ b/tests/core/test_inlinejs3.in
@@ -15,6 +15,9 @@ int main(int argc, char **argv) {
},
i, double(i) / 12);
}
+ EM_ASM_INT({ globalVar = $0 }, sum); // no outputs, just input
+ sum = 0;
+ sum = EM_ASM_INT_V({ return globalVar }); // no inputs, just output
printf("sum: %d\n", sum);
return 0;
}
diff --git a/tests/core/test_longjmp_throw.cpp b/tests/core/test_longjmp_throw.cpp
new file mode 100644
index 00000000..a5b658e8
--- /dev/null
+++ b/tests/core/test_longjmp_throw.cpp
@@ -0,0 +1,38 @@
+#include <stdio.h>
+#include <setjmp.h>
+
+static jmp_buf buf;
+volatile int x = 0;
+
+void second(void) {
+ printf("second\n");
+ if (x == 17) throw 5;
+ else longjmp(buf, -1);
+}
+
+void first(void) {
+ printf("first\n");
+ longjmp(buf, 1);
+}
+
+int main() {
+ int jmpval = setjmp(buf);
+ if (!jmpval) {
+ x++;
+ first();
+ printf("skipped\n");
+ } else if (jmpval == 1) {
+ printf("result: %d %d\n", x, jmpval);
+ x++;
+ try {
+ second();
+ } catch(int a) {
+ x--;
+ second();
+ }
+ } else if (jmpval == -1) {
+ printf("result: %d %d\n", x, jmpval);
+ }
+
+ return 0;
+}
diff --git a/tests/core/test_longjmp_throw.out b/tests/core/test_longjmp_throw.out
new file mode 100644
index 00000000..e9cc7525
--- /dev/null
+++ b/tests/core/test_longjmp_throw.out
@@ -0,0 +1,4 @@
+first
+result: 1 1
+second
+result: 2 -1
diff --git a/tests/openal_playback.cpp b/tests/openal_playback.cpp
index 13d619e6..6a8dae38 100644
--- a/tests/openal_playback.cpp
+++ b/tests/openal_playback.cpp
@@ -3,11 +3,15 @@
#include <AL/al.h>
#include <AL/alc.h>
#include <assert.h>
+#include <stdint.h>
+#include <unistd.h>
+#ifdef EMSCRIPTEN
#include <emscripten.h>
+#endif
void playSource(void* arg)
{
- ALuint source = reinterpret_cast<ALuint>(arg);
+ ALuint source = static_cast<ALuint>(reinterpret_cast<intptr_t>(arg));
ALint state;
alGetSourcei(source, AL_SOURCE_STATE, &state);
assert(state == AL_PLAYING);
@@ -21,15 +25,32 @@ void playSource(void* arg)
alGetSourcei(source, AL_SOURCE_STATE, &state);
assert(state == AL_STOPPED);
+#ifdef EMSCRIPTEN
int result = 1;
REPORT_RESULT();
+#endif
}
int main() {
+ int major, minor;
+ alcGetIntegerv(NULL, ALC_MAJOR_VERSION, 1, &major);
+ alcGetIntegerv(NULL, ALC_MAJOR_VERSION, 1, &minor);
+
+ assert(major == 1);
+
+ printf("ALC version: %i.%i\n", major, minor);
+ printf("Default device: %s\n", alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER));
+
ALCdevice* device = alcOpenDevice(NULL);
ALCcontext* context = alcCreateContext(device, NULL);
alcMakeContextCurrent(context);
+ assert(alGetString(AL_VERSION));
+
+ printf("OpenAL version: %s\n", alGetString(AL_VERSION));
+ printf("OpenAL vendor: %s\n", alGetString(AL_VENDOR));
+ printf("OpenAL renderer: %s\n", alGetString(AL_RENDERER));
+
ALfloat listenerPos[] = {0.0, 0.0, 0.0};
ALfloat listenerVel[] = {0.0, 0.0, 0.0};
ALfloat listenerOri[] = {0.0, 0.0, -1.0, 0.0, 1.0, 0.0};
@@ -42,7 +63,11 @@ int main() {
alGenBuffers(1, buffers);
+#ifdef EMSCRIPTEN
FILE* source = fopen("audio.wav", "rb");
+#else
+ FILE* source = fopen("sounds/audio.wav", "rb");
+#endif
fseek(source, 0, SEEK_END);
int size = ftell(source);
fseek(source, 0, SEEK_SET);
@@ -95,9 +120,21 @@ int main() {
alBufferData(buffers[0], format, &buffer[offset], size - offset, frequency);
+ ALint val;
+ alGetBufferi(buffers[0], AL_FREQUENCY, &val);
+ assert(val == frequency);
+ alGetBufferi(buffers[0], AL_SIZE, &val);
+ assert(val == size - offset);
+ alGetBufferi(buffers[0], AL_BITS, &val);
+ assert(val == bits);
+ alGetBufferi(buffers[0], AL_CHANNELS, &val);
+ assert(val == channels);
+
ALuint sources[1];
alGenSources(1, sources);
+ assert(alIsSource(sources[0]));
+
alSourcei(sources[0], AL_BUFFER, buffers[0]);
ALint state;
@@ -109,7 +146,12 @@ int main() {
alGetSourcei(sources[0], AL_SOURCE_STATE, &state);
assert(state == AL_PLAYING);
+#ifdef EMSCRIPTEN
emscripten_async_call(playSource, reinterpret_cast<void*>(sources[0]), 700);
+#else
+ usleep(700000);
+ playSource(reinterpret_cast<void*>(sources[0]));
+#endif
return 0;
}
diff --git a/tests/poppler/utils/pdftoppm.cc b/tests/poppler/utils/pdftoppm.cc
index f600e5ba..4df0f5d8 100644
--- a/tests/poppler/utils/pdftoppm.cc
+++ b/tests/poppler/utils/pdftoppm.cc
@@ -183,6 +183,10 @@ static void savePageSlice(PDFDoc *doc,
bitmap->writePNMFile(ppmFile);
}
} else {
+#if EMSCRIPTEN // XXX EMSCRIPTEN: avoid writing to stdout, better for benchmarking
+ printf("avoiding writing to stdout\n");
+#else
+
#ifdef _WIN32
setmode(fileno(stdout), O_BINARY);
#endif
@@ -194,6 +198,7 @@ static void savePageSlice(PDFDoc *doc,
} else {
bitmap->writePNMFile(stdout);
}
+#endif
}
}
diff --git a/tests/test_core.py b/tests/test_core.py
index 97cba68f..18d7d74a 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -1157,6 +1157,16 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co
src, output = (test_path + s for s in ('.in', '.out'))
self.do_run_from_file(src, output)
+ def test_longjmp_throw(self):
+ if self.run_name == 'asm3': return self.skip('issue 2069') # FIXME
+
+ for disable_throw in [0, 1]:
+ print disable_throw
+ Settings.DISABLE_EXCEPTION_CATCHING = disable_throw
+ test_path = path_from_root('tests', 'core', 'test_longjmp_throw')
+ src, output = (test_path + s for s in ('.cpp', '.out'))
+ self.do_run_from_file(src, output)
+
def test_setjmp_many(self):
if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp: make MAX_SETJMPS take effect')
@@ -1266,12 +1276,16 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co
def test_exceptions_2(self):
if self.emcc_args is None: return self.skip('need emcc to add in libcxx properly')
- Settings.DISABLE_EXCEPTION_CATCHING = 0
+ if self.run_name == 'asm2x86': return self.skip('TODO')
- test_path = path_from_root('tests', 'core', 'test_exceptions_2')
- src, output = (test_path + s for s in ('.in', '.out'))
+ Settings.DISABLE_EXCEPTION_CATCHING = 0
- self.do_run_from_file(src, output)
+ for safe in [0,1]:
+ print safe
+ Settings.SAFE_HEAP = safe
+ test_path = path_from_root('tests', 'core', 'test_exceptions_2')
+ src, output = (test_path + s for s in ('.in', '.out'))
+ self.do_run_from_file(src, output)
def test_exceptions_white_list(self):
if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp')
@@ -1352,6 +1366,12 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co
self.do_run_from_file(src, output)
+ def test_exceptions_alias(self):
+ Settings.DISABLE_EXCEPTION_CATCHING = 0
+ test_path = path_from_root('tests', 'core', 'test_exceptions_alias')
+ src, output = (test_path + s for s in ('.c', '.out'))
+ self.do_run_from_file(src, output)
+
def test_async_exit(self):
open('main.c', 'w').write(r'''
#include <stdio.h>
@@ -2051,7 +2071,6 @@ def process(filename):
def test_bigswitch(self):
if self.run_name != 'default': return self.skip('TODO: issue #781')
- if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp')
src = open(path_from_root('tests', 'bigswitch.cpp')).read()
self.do_run(src, '''34962: GL_ARRAY_BUFFER (0x8892)
@@ -5082,7 +5101,7 @@ def process(filename):
'structparam', 'uadd_overflow_ta2', 'extendedprecision', 'issue_39', 'emptystruct', 'phinonexist', 'quotedlabel', 'oob_ta2', 'phientryimplicit', 'phiself', 'invokebitcast', # invalid ir
'structphiparam', 'callwithstructural_ta2', 'callwithstructural64_ta2', 'structinparam', # pnacl limitations in ExpandStructRegs
'2xi40', # pnacl limitations in ExpandGetElementPtr
- 'legalizer_ta2', '514_ta2', # pnacl limitation in not legalizing i104, i96, etc.
+ 'legalizer_ta2', # pnacl limitation in not legalizing i104, i96, etc.
'indirectbrphi', 'ptrtoint_blockaddr', 'quoted', # current fastcomp limitations FIXME
'sillyfuncast2', 'sillybitcast', 'atomicrmw_unaligned' # TODO XXX
]: continue
diff --git a/tests/test_other.py b/tests/test_other.py
index 8895a911..bc05826e 100644
--- a/tests/test_other.py
+++ b/tests/test_other.py
@@ -2324,3 +2324,30 @@ var Module = { print: function(x) { throw '<{(' + x + ')}>' } };
output = run_js(os.path.join(self.get_dir(), 'a.out.js'), stderr=PIPE, full_output=True, engine=NODE_JS)
assert r'<{(123456789)}>' in output, output
+ def test_precompiled_headers(self):
+ self.clear()
+
+ open('header.h', 'w').write('#define X 5\n')
+ Popen([PYTHON, EMCC, '-xc++-header', 'header.h', '-c']).communicate()
+ assert os.path.exists('header.h.gch')
+
+ open('src.cpp', 'w').write(r'''
+#include <stdio.h>
+int main() {
+ printf("|%d|\n", X);
+ return 0;
+}
+''')
+ Popen([PYTHON, EMCC, 'src.cpp', '-include', 'header.h']).communicate()
+
+ output = run_js(self.in_dir('a.out.js'), stderr=PIPE, full_output=True, engine=NODE_JS)
+ assert '|5|' in output, output
+
+ # also verify that the gch is actually used
+ err = Popen([PYTHON, EMCC, 'src.cpp', '-include', 'header.h', '-Xclang', '-print-stats'], stderr=PIPE).communicate()
+ assert '*** PCH/Modules Loaded:\nModule: header.h.gch' in err[1], err[1]
+ # and sanity check it is not mentioned when not
+ try_delete('header.h.gch')
+ err = Popen([PYTHON, EMCC, 'src.cpp', '-include', 'header.h', '-Xclang', '-print-stats'], stderr=PIPE).communicate()
+ assert '*** PCH/Modules Loaded:\nModule: header.h.gch' not in err[1], err[1]
+
diff --git a/tools/file_packager.py b/tools/file_packager.py
index 9699730f..874ad942 100644
--- a/tools/file_packager.py
+++ b/tools/file_packager.py
@@ -107,7 +107,11 @@ for arg in sys.argv[2:]:
jsoutput = arg.split('=')[1] if '=' in arg else None
leading = ''
elif arg.startswith('--crunch'):
- from shared import CRUNCH
+ try:
+ from shared import CRUNCH
+ except Exception, e:
+ print >> sys.stderr, 'count not import CRUNCH (make sure it is defined properly in ~/.emscripten)'
+ raise e
crunch = arg.split('=')[1] if '=' in arg else '128'
leading = ''
elif arg.startswith('--plugin'):
diff --git a/tools/find_bigis.py b/tools/find_bigis.py
index d11c1a81..1261e7ff 100644
--- a/tools/find_bigis.py
+++ b/tools/find_bigis.py
@@ -6,7 +6,7 @@ import os, sys, re
filename = sys.argv[1]
data = open(filename).read()
-iss = re.findall('[^%]i\d+ [^=]', data)
+iss = re.findall(' i\d+ [^=]', data)
set_iss = set(iss)
bigs = []
for iss in set_iss:
diff --git a/tools/shared.py b/tools/shared.py
index f88eace0..bd1d1bee 100644
--- a/tools/shared.py
+++ b/tools/shared.py
@@ -345,7 +345,7 @@ def find_temp_directory():
# we re-check sanity when the settings are changed)
# We also re-check sanity and clear the cache when the version changes
-EMSCRIPTEN_VERSION = '1.9.5'
+EMSCRIPTEN_VERSION = '1.10.0'
def generate_sanity():
return EMSCRIPTEN_VERSION + '|' + get_llvm_target() + '|' + LLVM_ROOT + '|' + get_clang_version()