summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xemcc16
-rwxr-xr-xemscripten.py59
-rw-r--r--src/analyzer.js9
-rw-r--r--src/compiler.js11
-rw-r--r--src/headless.js5
-rw-r--r--src/jsifier.js56
-rw-r--r--src/library.js683
-rw-r--r--src/library_gl.js109
-rw-r--r--src/library_openal.js541
-rw-r--r--src/library_sdl.js29
-rw-r--r--src/long.js7
-rw-r--r--src/modules.js2
-rw-r--r--src/parseTools.js59
-rw-r--r--src/preamble.js49
-rw-r--r--src/runtime.js51
-rw-r--r--src/settings.js29
-rw-r--r--src/utility.js9
-rw-r--r--system/include/AL/al.h172
-rw-r--r--system/include/AL/alc.h84
-rw-r--r--system/include/libc/ctype.h23
-rw-r--r--system/include/libc/math.h27
-rw-r--r--tests/cases/alignedunaligned.ll6
-rw-r--r--tests/cases/breakinthemiddle3.ll26
-rw-r--r--tests/cases/callundef.ll18
-rw-r--r--tests/cases/phicubed.ll29
-rw-r--r--tests/cases/storestruct.ll5
-rw-r--r--tests/cases/unannotated__noasm.ll (renamed from tests/cases/unannotated.ll)0
-rw-r--r--tests/cases/unannotated__noasm.txt (renamed from tests/cases/unannotated.txt)0
-rw-r--r--tests/gl_ps_strides.c241
-rw-r--r--tests/gl_ps_strides.pngbin0 -> 98713 bytes
-rw-r--r--tests/openal_playback.cpp115
-rwxr-xr-xtests/runner.py239
-rw-r--r--tests/sdl_audio_mix.c2
-rw-r--r--tests/sounds/audio.wavbin0 -> 190764 bytes
-rwxr-xr-xtools/bindings_generator.py5
-rw-r--r--tools/js_optimizer.py2
-rw-r--r--tools/settings_template_readonly.py3
-rw-r--r--tools/shared.py6
38 files changed, 2154 insertions, 573 deletions
diff --git a/emcc b/emcc
index d06bb21c..488f0788 100755
--- a/emcc
+++ b/emcc
@@ -215,6 +215,20 @@ Options that are modified or new in %s include:
(without the external "s in either of those,
you would get an error)
+ You can also specify a file from which the
+ value would be read, for example,
+
+ -s DEAD_FUNCTIONS=@/path/to/file
+
+ The contents of /path/to/file will be read,
+ JSON.parsed and set into DEAD_FUNCTIONS (so
+ the file could contain
+
+ ["_func1", "func2"]
+
+ ). Note that the path must be absolute, not
+ relative.
+
-g Use debug info. Note that you need this during
the last compilation phase from bitcode to
JavaScript, or else we will remove it by
@@ -973,6 +987,8 @@ try:
# Apply -s settings in newargs here (after optimization levels, so they can override them)
for change in settings_changes:
key, value = change.split('=')
+ if value[0] == '@':
+ value = '"' + value + '"'
exec('shared.Settings.' + key + ' = ' + value)
# Apply effects from settings
diff --git a/emscripten.py b/emscripten.py
index bbc4f76d..c9d8505d 100755
--- a/emscripten.py
+++ b/emscripten.py
@@ -34,9 +34,13 @@ MIN_CHUNK_SIZE = 1024*1024
MAX_CHUNK_SIZE = float(os.environ.get('EMSCRIPT_MAX_CHUNK_SIZE') or 'inf') # configuring this is just for debugging purposes
def process_funcs((i, funcs, meta, settings_file, compiler, forwarded_file, libraries, compiler_engine, temp_files, DEBUG)):
- ll = ''.join(funcs) + '\n' + meta
funcs_file = temp_files.get('.func_%d.ll' % i).name
- open(funcs_file, 'w').write(ll)
+ f = open(funcs_file, 'w')
+ f.write(funcs)
+ funcs = None
+ f.write('\n')
+ f.write(meta)
+ f.close()
out = jsrun.run_js(
compiler,
engine=compiler_engine,
@@ -188,6 +192,8 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
funcs, chunk_size,
jcache.get_cachename('emscript_files') if jcache else None)
+ funcs = None
+
if jcache:
# load chunks from cache where we can # TODO: ignore small chunks
cached_outputs = []
@@ -223,6 +229,9 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
outputs = pool.map(process_funcs, commands, chunksize=1)
elif len(chunks) == 1:
outputs = [process_funcs(commands[0])]
+
+ commands = None
+
else:
outputs = []
@@ -235,6 +244,8 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
jcache.set(shortkey, keys, outputs[i])
if out and DEBUG and len(chunks) > 0: print >> sys.stderr, ' saving %d funcchunks to jcache' % len(chunks)
+ chunks = None
+
if jcache: outputs += cached_outputs # TODO: preserve order
outputs = [output.split('//FORWARDED_DATA:') for output in outputs]
@@ -258,8 +269,10 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
for key in curr_forwarded_json['Functions']['indexedFunctions'].iterkeys():
indexed_functions.add(key)
if settings.get('ASM_JS'):
+ export_bindings = settings['EXPORT_BINDINGS']
for key in curr_forwarded_json['Functions']['implementedFunctions'].iterkeys():
- if key in all_exported_functions: exported_implemented_functions.add(key)
+ if key in all_exported_functions or (export_bindings and key.startswith('_emscripten_bind')):
+ exported_implemented_functions.add(key)
for key, value in curr_forwarded_json['Functions']['unimplementedFunctions'].iteritems():
forwarded_json['Functions']['unimplementedFunctions'][key] = value
@@ -268,7 +281,7 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
if len(parts) > 1:
pre = parts[0]
outputs.append([parts[1]])
- funcs_js = ''.join([output[0] for output in outputs])
+ funcs_js = [''.join([output[0] for output in outputs])] # this will be a list of things, so we do not do string appending as we add more
outputs = None
if DEBUG: print >> sys.stderr, ' emscript: phase 2b took %s seconds' % (time.time() - t)
@@ -313,6 +326,10 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
last_forwarded_json = json.loads(last_forwarded_data)
if settings.get('ASM_JS'):
+ post_funcs, post_rest = post.split('// EMSCRIPTEN_END_FUNCS\n')
+ post = post_rest
+ funcs_js += ['\n' + post_funcs + '// EMSCRIPTEN_END_FUNCS\n']
+
simple = os.environ.get('EMCC_SIMPLE_ASM')
class Counter:
i = 0
@@ -320,11 +337,12 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
del last_forwarded_json['Functions']['tables']['pre']
# Find function table calls without function tables generated for them
- for use in set(re.findall(r'{{{ FTM_[\w\d_$]+ }}}', funcs_js)):
- sig = use[8:len(use)-4]
- if sig not in last_forwarded_json['Functions']['tables']:
- if DEBUG: print >> sys.stderr, 'add empty function table', sig
- last_forwarded_json['Functions']['tables'][sig] = 'var FUNCTION_TABLE_' + sig + ' = [0,0];\n'
+ for funcs_js_item in funcs_js:
+ for use in set(re.findall(r'{{{ FTM_[\w\d_$]+ }}}', funcs_js_item)):
+ sig = use[8:len(use)-4]
+ if sig not in last_forwarded_json['Functions']['tables']:
+ if DEBUG: print >> sys.stderr, 'add empty function table', sig
+ last_forwarded_json['Functions']['tables'][sig] = 'var FUNCTION_TABLE_' + sig + ' = [0,0];\n'
def make_table(sig, raw):
i = Counter.i
@@ -340,7 +358,7 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None,
asm_setup = ''
maths = ['Math.' + func for func in ['floor', 'abs', 'sqrt', 'pow', 'cos', 'sin', 'tan', 'acos', 'asin', 'atan', 'atan2', 'exp', 'log', 'ceil', 'imul']]
fundamentals = ['Math', 'Int8Array', 'Int16Array', 'Int32Array', 'Uint8Array', 'Uint16Array', 'Uint32Array', 'Float32Array', 'Float64Array']
- math_envs = ['Runtime.bitshift64', 'Math.min'] # TODO: move min to maths
+ math_envs = ['Math.min'] # TODO: move min to maths
asm_setup += '\n'.join(['var %s = %s;' % (f.replace('.', '_'), f) for f in math_envs])
basic_funcs = ['abort', 'assert', 'asmPrintInt', 'asmPrintFloat', 'copyTempDouble', 'copyTempFloat'] + [m.replace('.', '_') for m in math_envs]
if settings['SAFE_HEAP']: basic_funcs += ['SAFE_HEAP_LOAD', 'SAFE_HEAP_STORE', 'SAFE_HEAP_CLEAR']
@@ -411,9 +429,9 @@ var i64Math_modulo = function(a, b, c, d, e) { i64Math.modulo(a, b, c, d, e) };
# finalize
- if DEBUG: print >> sys.stderr, 'asm text sizes', len(funcs_js), len(asm_setup), len(asm_global_vars), len(asm_global_funcs), len(pre_tables), len('\n'.join(function_tables_impls)), len(function_tables_defs.replace('\n', '\n ')), len(exports), len(the_global), len(sending), len(receiving)
+ if DEBUG: print >> sys.stderr, 'asm text sizes', map(len, funcs_js), len(asm_setup), len(asm_global_vars), len(asm_global_funcs), len(pre_tables), len('\n'.join(function_tables_impls)), len(function_tables_defs.replace('\n', '\n ')), len(exports), len(the_global), len(sending), len(receiving)
- funcs_js = '''
+ funcs_js = ['''
%s
function asmPrintInt(x, y) {
Module.print('int ' + x + ',' + y);// + ' ' + new Error().stack);
@@ -463,7 +481,7 @@ var asm = (function(global, env, buffer) {
value = value|0;
tempRet%d = value;
}
-''' % (i, i) for i in range(10)]) + funcs_js + '''
+''' % (i, i) for i in range(10)])] + funcs_js + ['''
%s
return %s;
@@ -474,7 +492,7 @@ var asm = (function(global, env, buffer) {
Runtime.stackAlloc = function(size) { return asm.stackAlloc(size) };
Runtime.stackSave = function() { return asm.stackSave() };
Runtime.stackRestore = function(top) { asm.stackRestore(top) };
-''' % (pre_tables + '\n'.join(function_tables_impls) + '\n' + function_tables_defs.replace('\n', '\n '), exports, the_global, sending, receiving)
+''' % (pre_tables + '\n'.join(function_tables_impls) + '\n' + function_tables_defs.replace('\n', '\n '), exports, the_global, sending, receiving)]
# Set function table masks
def function_table_maskize(js):
@@ -487,17 +505,20 @@ Runtime.stackRestore = function(top) { asm.stackRestore(top) };
sig = m.groups(0)[0]
return masks[sig]
return re.sub(r'{{{ FTM_([\w\d_$]+) }}}', lambda m: fix(m), js) # masks[m.groups(0)[0]]
- funcs_js = function_table_maskize(funcs_js)
+ funcs_js = map(function_table_maskize, funcs_js)
else:
function_tables_defs = '\n'.join([table for table in last_forwarded_json['Functions']['tables'].itervalues()])
outfile.write(function_tables_defs)
- funcs_js = '''
+ funcs_js = ['''
// EMSCRIPTEN_START_FUNCS
-''' + funcs_js + '''
+'''] + funcs_js + ['''
// EMSCRIPTEN_END_FUNCS
-'''
+''']
- outfile.write(blockaddrsize(indexize(funcs_js)))
+ for funcs_js_item in funcs_js: # do this loop carefully to save memory
+ funcs_js_item = indexize(funcs_js_item)
+ funcs_js_item = blockaddrsize(funcs_js_item)
+ outfile.write(funcs_js_item)
funcs_js = None
outfile.write(indexize(post))
diff --git a/src/analyzer.js b/src/analyzer.js
index 926ac9d3..92b7d8cf 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -18,7 +18,7 @@ function recomputeLines(func) {
// Handy sets
var BRANCH_INVOKE = set('branch', 'invoke');
-var LABEL_ENDERS = set('branch', 'return');
+var LABEL_ENDERS = set('branch', 'return', 'switch');
var SIDE_EFFECT_CAUSERS = set('call', 'invoke', 'atomic');
var UNUNFOLDABLE = set('value', 'structvalue', 'type', 'phiparam');
@@ -653,13 +653,14 @@ function analyzer(data, sidePass) {
if (!isNumber(shifts)) {
// We can't statically legalize this, do the operation at runtime TODO: optimize
assert(sourceBits == 64, 'TODO: handle nonconstant shifts on != 64 bits');
+ assert(PRECISE_I64_MATH, 'Must have precise i64 math for non-constant 64-bit shifts');
+ Types.preciseI64MathUsed = 1;
value.intertype = 'value';
- value.ident = 'Runtime' + (ASM_JS ? '_' : '.') + 'bitshift64(' +
+ value.ident = 'var ' + value.assignTo + '$0 = _bitshift64' + value.op[0].toUpperCase() + value.op.substr(1) + '(' +
asmCoercion(sourceElements[0].ident, 'i32') + ',' +
asmCoercion(sourceElements[1].ident, 'i32') + ',' +
- Runtime['BITSHIFT64_' + value.op.toUpperCase()] + ',' +
asmCoercion(value.params[1].ident + '$0', 'i32') + ');' +
- 'var ' + value.assignTo + '$0 = ' + makeGetTempDouble(0, 'i32') + ', ' + value.assignTo + '$1 = ' + makeGetTempDouble(1, 'i32') + ';';
+ 'var ' + value.assignTo + '$1 = tempRet0;';
value.assignTo = null;
i++;
continue;
diff --git a/src/compiler.js b/src/compiler.js
index 447d34b7..bb72c7dd 100644
--- a/src/compiler.js
+++ b/src/compiler.js
@@ -141,8 +141,13 @@ if (phase == 'pre') {
if (settings_file) {
var settings = JSON.parse(read(settings_file));
- for (setting in settings) {
- eval(setting + ' = ' + JSON.stringify(settings[setting]));
+ for (key in settings) {
+ var value = settings[key];
+ if (value[0] == '@') {
+ // response file type thing, workaround for large inputs: value is @path-to-file
+ value = JSON.parse(read(value.substr(1)));
+ }
+ eval(key + ' = ' + JSON.stringify(value));
}
}
@@ -163,7 +168,7 @@ if (SAFE_HEAP >= 2) {
EXPORTED_FUNCTIONS = set(EXPORTED_FUNCTIONS);
EXPORTED_GLOBALS = set(EXPORTED_GLOBALS);
EXCEPTION_CATCHING_WHITELIST = set(EXCEPTION_CATCHING_WHITELIST);
-DEAD_FUNCTIONS = set(DEAD_FUNCTIONS);
+DEAD_FUNCTIONS = numberedSet(DEAD_FUNCTIONS);
RUNTIME_DEBUG = LIBRARY_DEBUG || GL_DEBUG;
diff --git a/src/headless.js b/src/headless.js
index 8e847d27..d81fb5a3 100644
--- a/src/headless.js
+++ b/src/headless.js
@@ -537,7 +537,7 @@ var document = {
case /* GL_MAX_FRAGMENT_UNIFORM_VECTORS */ 0x8DFD: return 4096;
case /* GL_MAX_VARYING_VECTORS */ 0x8DFC: return 32;
case /* GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS */ 0x8B4D: return 32;
- default: throw 'getParameter ' + pname;
+ default: console.log('getParameter ' + pname + '?'); return 0;
}
},
getSupportedExtensions: function() {
@@ -686,6 +686,7 @@ var document = {
document.callEventListeners('pointerlockchange');
});
},
+ exitPointerLock: function(){},
style: {},
eventListeners: {},
addEventListener: document.addEventListener,
@@ -748,6 +749,8 @@ var document = {
body: {
appendChild: function(){},
},
+ exitPointerLock: function(){},
+ cancelFullScreen: function(){},
};
var alert = function(x) {
print(x);
diff --git a/src/jsifier.js b/src/jsifier.js
index d36f26ce..7db2ee70 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -397,6 +397,20 @@ function JSify(data, functionsOnly, givenFunctions) {
}
});
+ function processLibraryFunction(snippet, ident) {
+ snippet = snippet.toString();
+ assert(snippet.indexOf('XXX missing C define') == -1,
+ 'Trying to include a library function with missing C defines: ' + ident + ' | ' + snippet);
+
+ // name the function; overwrite if it's already named
+ snippet = snippet.replace(/function(?:\s+([^(]+))?\s*\(/, 'function _' + ident + '(');
+ if (LIBRARY_DEBUG) {
+ snippet = snippet.replace('{', '{ var ret = (function() { if (Runtime.debug) Module.printErr("[library call:' + ident + ': " + Array.prototype.slice.call(arguments).map(Runtime.prettyPrint) + "]"); ');
+ snippet = snippet.substr(0, snippet.length-1) + '}).apply(this, arguments); if (Runtime.debug && typeof ret !== "undefined") Module.printErr(" [ return:" + Runtime.prettyPrint(ret)); return ret; \n}';
+ }
+ return snippet;
+ }
+
// functionStub
substrate.addActor('FunctionStub', {
processItem: function(item) {
@@ -434,16 +448,7 @@ function JSify(data, functionsOnly, givenFunctions) {
snippet = stringifyWithFunctions(snippet);
} else if (typeof snippet === 'function') {
isFunction = true;
- snippet = snippet.toString();
- assert(snippet.indexOf('XXX missing C define') == -1,
- 'Trying to include a library function with missing C defines: ' + ident + ' | ' + snippet);
-
- // name the function; overwrite if it's already named
- snippet = snippet.replace(/function(?:\s+([^(]+))?\s*\(/, 'function _' + ident + '(');
- if (LIBRARY_DEBUG) {
- snippet = snippet.replace('{', '{ var ret = (function() { if (Runtime.debug) Module.printErr("[library call:' + ident + ': " + Array.prototype.slice.call(arguments).map(Runtime.prettyPrint) + "]"); ');
- snippet = snippet.substr(0, snippet.length-1) + '}).apply(this, arguments); if (Runtime.debug && typeof ret !== "undefined") Module.printErr(" [ return:" + Runtime.prettyPrint(ret)); return ret; \n}';
- }
+ snippet = processLibraryFunction(snippet, ident);
if (ASM_JS) Functions.libraryFunctions[ident] = 1;
}
@@ -507,9 +512,13 @@ function JSify(data, functionsOnly, givenFunctions) {
} else if (LibraryManager.library.hasOwnProperty(shortident)) {
item.JS = addFromLibrary(shortident);
} else if (!LibraryManager.library.hasOwnProperty(shortident + '__inline')) {
- item.JS = 'var ' + item.ident + '; // stub for ' + item.ident;
- if (WARN_ON_UNDEFINED_SYMBOLS || ASM_JS) { // always warn on undefs in asm, since it breaks validation
- warn('Unresolved symbol: ' + item.ident);
+ if (!(item.ident in DEAD_FUNCTIONS) && !UNRESOLVED_AS_DEAD) {
+ item.JS = 'var ' + item.ident + '; // stub for ' + item.ident;
+ if (ASM_JS) {
+ throw '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);
+ }
}
}
return ret;
@@ -717,6 +726,7 @@ function JSify(data, functionsOnly, givenFunctions) {
ret += indent + 'label = ' + getLabelId(block.entries[0]) + '; ' + (SHOW_LABELS ? '/* ' + getOriginalLabelId(block.entries[0]) + ' */' : '') + '\n';
} // otherwise, should have been set before!
if (func.setjmpTable) {
+ assert(!ASM_JS, 'asm.js mode does not support setjmp yet');
var setjmpTable = {};
ret += indent + 'var mySetjmpIds = {};\n';
ret += indent + 'var setjmpTable = {';
@@ -1316,6 +1326,7 @@ function JSify(data, functionsOnly, givenFunctions) {
} else {
callIdent = ident;
}
+ if (callIdent == '0') return 'abort(-2)';
var args = [];
var argsTypes = [];
@@ -1420,7 +1431,7 @@ function JSify(data, functionsOnly, givenFunctions) {
}
if (callIdent in DEAD_FUNCTIONS) {
- var ret = 'abort(7)';
+ var ret = 'abort(' + DEAD_FUNCTIONS[callIdent] + ')';
if (ASM_JS) ret = asmCoercion(ret, returnType);
return ret;
}
@@ -1563,16 +1574,25 @@ function JSify(data, functionsOnly, givenFunctions) {
// This is the main 'post' pass. Print out the generated code that we have here, together with the
// rest of the output that we started to print out earlier (see comment on the
// "Final shape that will be created").
- if (CORRUPTION_CHECK) {
- assert(!ASM_JS); // cannot monkeypatch asm!
- print(processMacros(read('corruptionCheck.js')));
- }
if (PRECISE_I64_MATH && Types.preciseI64MathUsed) {
+ if (!INCLUDE_FULL_LIBRARY) {
+ ['i64Add', 'bitshift64Shl', 'bitshift64Lshr', 'bitshift64Ashr'].forEach(function(func) {
+ print(processLibraryFunction(LibraryManager.library[func], func)); // must be first to be close to generated code
+ Functions.implementedFunctions['_' + func] = LibraryManager.library[func + '__sig'];
+ });
+ }
+ print('// EMSCRIPTEN_END_FUNCS\n');
print(read('long.js'));
} else {
+ print('// EMSCRIPTEN_END_FUNCS\n');
print('// Warning: printing of i64 values may be slightly rounded! No deep i64 math used, so precise i64 code not included');
print('var i64Math = null;');
}
+
+ if (CORRUPTION_CHECK) {
+ assert(!ASM_JS); // cannot monkeypatch asm!
+ print(processMacros(read('corruptionCheck.js')));
+ }
if (HEADLESS) {
print('if (!ENVIRONMENT_IS_WEB) {');
print(read('headless.js').replace("'%s'", "'http://emscripten.org'").replace("'?%s'", "''").replace('%s,', 'null,').replace('%d', '0'));
diff --git a/src/library.js b/src/library.js
index 3d00a4d5..d5f11cf3 100644
--- a/src/library.js
+++ b/src/library.js
@@ -504,7 +504,7 @@ LibraryManager.library = {
}
var utf8 = new Runtime.UTF8Processor();
function simpleOutput(val) {
- if (val === null || val === '\n'.charCodeAt(0)) {
+ if (val === null || val === {{{ charCode('\n') }}}) {
output.printer(output.buffer.join(''));
output.buffer = [];
} else {
@@ -600,8 +600,8 @@ LibraryManager.library = {
quit: function() {
if (!FS.init.initialized) return;
// Flush any partially-printed lines in stdout and stderr. Careful, they may have been closed
- if (FS.streams[2] && FS.streams[2].object.output.buffer.length > 0) FS.streams[2].object.output('\n'.charCodeAt(0));
- if (FS.streams[3] && FS.streams[3].object.output.buffer.length > 0) FS.streams[3].object.output('\n'.charCodeAt(0));
+ if (FS.streams[2] && FS.streams[2].object.output.buffer.length > 0) FS.streams[2].object.output({{{ charCode('\n') }}});
+ if (FS.streams[3] && FS.streams[3].object.output.buffer.length > 0) FS.streams[3].object.output({{{ charCode('\n') }}});
},
// Standardizes a path. Useful for making comparisons of pathnames work in a consistent manner.
@@ -828,11 +828,11 @@ LibraryManager.library = {
// Null or empty results in '.'.
var me = ___libgenSplitName;
if (!me.ret) {
- me.ret = allocate(['.'.charCodeAt(0), 0], 'i8', ALLOC_NORMAL);
+ me.ret = allocate([{{{ charCode('.') }}}, 0], 'i8', ALLOC_NORMAL);
}
return [me.ret, -1];
} else {
- var slash = '/'.charCodeAt(0);
+ var slash = {{{ charCode('/') }}};
var allSlashes = true;
var slashPositions = [];
for (var i = 0; {{{ makeGetValue('path', 'i', 'i8') }}} !== 0; i++) {
@@ -1730,7 +1730,12 @@ LibraryManager.library = {
}
var contents = stream.object.contents;
var size = Math.min(contents.length - offset, nbyte);
- if (contents.subarray || contents.slice) { // typed array or normal array
+#if USE_TYPED_ARRAYS == 2
+ if (contents.subarray) { // typed array
+ HEAPU8.set(contents.subarray(offset, offset+size), buf);
+ } else
+#endif
+ if (contents.slice) { // normal array
for (var i = 0; i < size; i++) {
{{{ makeSetValue('buf', 'i', 'contents[offset + i]', 'i8') }}}
}
@@ -2452,9 +2457,9 @@ LibraryManager.library = {
_scanString: function(format, get, unget, varargs) {
if (!__scanString.whiteSpace) {
__scanString.whiteSpace = {};
- __scanString.whiteSpace[' '.charCodeAt(0)] = 1;
- __scanString.whiteSpace['\t'.charCodeAt(0)] = 1;
- __scanString.whiteSpace['\n'.charCodeAt(0)] = 1;
+ __scanString.whiteSpace[{{{ charCode(' ') }}}] = 1;
+ __scanString.whiteSpace[{{{ charCode('\t') }}}] = 1;
+ __scanString.whiteSpace[{{{ charCode('\n') }}}] = 1;
__scanString.whiteSpace[' '] = 1;
__scanString.whiteSpace['\t'] = 1;
__scanString.whiteSpace['\n'] = 1;
@@ -2514,8 +2519,8 @@ LibraryManager.library = {
if (format[formatIndex] === '%') {
formatIndex++;
var maxSpecifierStart = formatIndex;
- while (format[formatIndex].charCodeAt(0) >= '0'.charCodeAt(0) &&
- format[formatIndex].charCodeAt(0) <= '9'.charCodeAt(0)) {
+ while (format[formatIndex].charCodeAt(0) >= {{{ charCode('0') }}} &&
+ format[formatIndex].charCodeAt(0) <= {{{ charCode('9') }}}) {
formatIndex++;
}
var max_;
@@ -2561,11 +2566,11 @@ LibraryManager.library = {
while ((curr < max_ || isNaN(max_)) && next > 0) {
if (!(next in __scanString.whiteSpace) && // stop on whitespace
(type == 's' ||
- ((type === 'd' || type == 'u' || type == 'i') && ((next >= '0'.charCodeAt(0) && next <= '9'.charCodeAt(0)) ||
- (first && next == '-'.charCodeAt(0)))) ||
- (type === 'x' && (next >= '0'.charCodeAt(0) && next <= '9'.charCodeAt(0) ||
- next >= 'a'.charCodeAt(0) && next <= 'f'.charCodeAt(0) ||
- next >= 'A'.charCodeAt(0) && next <= 'F'.charCodeAt(0)))) &&
+ ((type === 'd' || type == 'u' || type == 'i') && ((next >= {{{ charCode('0') }}} && next <= {{{ charCode('9') }}}) ||
+ (first && next == {{{ charCode('-') }}}))) ||
+ (type === 'x' && (next >= {{{ charCode('0') }}} && next <= {{{ charCode('9') }}} ||
+ next >= {{{ charCode('a') }}} && next <= {{{ charCode('f') }}} ||
+ next >= {{{ charCode('A') }}} && next <= {{{ charCode('F') }}}))) &&
(formatIndex >= format.length || next !== format[formatIndex].charCodeAt(0))) { // Stop when we read something that is coming up
buffer.push(String.fromCharCode(next));
next = get();
@@ -2633,7 +2638,7 @@ LibraryManager.library = {
}
return fields;
},
- // Performs prtinf-style formatting.
+ // Performs printf-style formatting.
// format: A pointer to the format string.
// varargs: A pointer to the start of the arguments list.
// Returns the resulting string string as a character array.
@@ -2670,7 +2675,7 @@ LibraryManager.library = {
curr = {{{ makeGetValue(0, 'textIndex', 'i8') }}};
if (curr === 0) break;
next = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}};
- if (curr == '%'.charCodeAt(0)) {
+ if (curr == {{{ charCode('%') }}}) {
// Handle flags.
var flagAlwaysSigned = false;
var flagLeftAlign = false;
@@ -2678,16 +2683,16 @@ LibraryManager.library = {
var flagZeroPad = false;
flagsLoop: while (1) {
switch (next) {
- case '+'.charCodeAt(0):
+ case {{{ charCode('+') }}}:
flagAlwaysSigned = true;
break;
- case '-'.charCodeAt(0):
+ case {{{ charCode('-') }}}:
flagLeftAlign = true;
break;
- case '#'.charCodeAt(0):
+ case {{{ charCode('#') }}}:
flagAlternative = true;
break;
- case '0'.charCodeAt(0):
+ case {{{ charCode('0') }}}:
if (flagZeroPad) {
break flagsLoop;
} else {
@@ -2703,13 +2708,13 @@ LibraryManager.library = {
// Handle width.
var width = 0;
- if (next == '*'.charCodeAt(0)) {
+ if (next == {{{ charCode('*') }}}) {
width = getNextArg('i32');
textIndex++;
next = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}};
} else {
- while (next >= '0'.charCodeAt(0) && next <= '9'.charCodeAt(0)) {
- width = width * 10 + (next - '0'.charCodeAt(0));
+ while (next >= {{{ charCode('0') }}} && next <= {{{ charCode('9') }}}) {
+ width = width * 10 + (next - {{{ charCode('0') }}});
textIndex++;
next = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}};
}
@@ -2717,20 +2722,20 @@ LibraryManager.library = {
// Handle precision.
var precisionSet = false;
- if (next == '.'.charCodeAt(0)) {
+ if (next == {{{ charCode('.') }}}) {
var precision = 0;
precisionSet = true;
textIndex++;
next = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}};
- if (next == '*'.charCodeAt(0)) {
+ if (next == {{{ charCode('*') }}}) {
precision = getNextArg('i32');
textIndex++;
} else {
while(1) {
var precisionChr = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}};
- if (precisionChr < '0'.charCodeAt(0) ||
- precisionChr > '9'.charCodeAt(0)) break;
- precision = precision * 10 + (precisionChr - '0'.charCodeAt(0));
+ if (precisionChr < {{{ charCode('0') }}} ||
+ precisionChr > {{{ charCode('9') }}}) break;
+ precision = precision * 10 + (precisionChr - {{{ charCode('0') }}});
textIndex++;
}
}
@@ -2744,7 +2749,7 @@ LibraryManager.library = {
switch (String.fromCharCode(next)) {
case 'h':
var nextNext = {{{ makeGetValue(0, 'textIndex+2', 'i8') }}};
- if (nextNext == 'h'.charCodeAt(0)) {
+ if (nextNext == {{{ charCode('h') }}}) {
textIndex++;
argSize = 1; // char (actually i32 in varargs)
} else {
@@ -2753,7 +2758,7 @@ LibraryManager.library = {
break;
case 'l':
var nextNext = {{{ makeGetValue(0, 'textIndex+2', 'i8') }}};
- if (nextNext == 'l'.charCodeAt(0)) {
+ if (nextNext == {{{ charCode('l') }}}) {
textIndex++;
argSize = 8; // long long
} else {
@@ -2777,226 +2782,249 @@ LibraryManager.library = {
next = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}};
// Handle type specifier.
- if (['d', 'i', 'u', 'o', 'x', 'X', 'p'].indexOf(String.fromCharCode(next)) != -1) {
- // Integer.
- var signed = next == 'd'.charCodeAt(0) || next == 'i'.charCodeAt(0);
- argSize = argSize || 4;
- var currArg = getNextArg('i' + (argSize * 8));
+ switch (String.fromCharCode(next)) {
+ case 'd': case 'i': case 'u': case 'o': case 'x': case 'X': case 'p': {
+ // Integer.
+ var signed = next == {{{ charCode('d') }}} || next == {{{ charCode('i') }}};
+ argSize = argSize || 4;
+ var currArg = getNextArg('i' + (argSize * 8));
#if PRECISE_I64_MATH
- var origArg = currArg;
+ var origArg = currArg;
#endif
- var argText;
+ var argText;
#if USE_TYPED_ARRAYS == 2
- // Flatten i64-1 [low, high] into a (slightly rounded) double
- if (argSize == 8) {
- currArg = Runtime.makeBigInt(currArg[0], currArg[1], next == 'u'.charCodeAt(0));
- }
+ // Flatten i64-1 [low, high] into a (slightly rounded) double
+ if (argSize == 8) {
+ currArg = Runtime.makeBigInt(currArg[0], currArg[1], next == {{{ charCode('u') }}});
+ }
#endif
- // Truncate to requested size.
- if (argSize <= 4) {
- var limit = Math.pow(256, argSize) - 1;
- currArg = (signed ? reSign : unSign)(currArg & limit, argSize * 8);
- }
- // Format the number.
- var currAbsArg = Math.abs(currArg);
- var prefix = '';
- if (next == 'd'.charCodeAt(0) || next == 'i'.charCodeAt(0)) {
+ // Truncate to requested size.
+ if (argSize <= 4) {
+ var limit = Math.pow(256, argSize) - 1;
+ currArg = (signed ? reSign : unSign)(currArg & limit, argSize * 8);
+ }
+ // Format the number.
+ var currAbsArg = Math.abs(currArg);
+ var prefix = '';
+ if (next == {{{ charCode('d') }}} || next == {{{ charCode('i') }}}) {
#if PRECISE_I64_MATH
- if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1], null); else
+ if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1], null); else
#endif
- argText = reSign(currArg, 8 * argSize, 1).toString(10);
- } else if (next == 'u'.charCodeAt(0)) {
+ argText = reSign(currArg, 8 * argSize, 1).toString(10);
+ } else if (next == {{{ charCode('u') }}}) {
#if PRECISE_I64_MATH
- if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1], true); else
+ if (argSize == 8 && i64Math) argText = i64Math.stringify(origArg[0], origArg[1], true); else
#endif
- argText = unSign(currArg, 8 * argSize, 1).toString(10);
- currArg = Math.abs(currArg);
- } else if (next == 'o'.charCodeAt(0)) {
- argText = (flagAlternative ? '0' : '') + currAbsArg.toString(8);
- } else if (next == 'x'.charCodeAt(0) || next == 'X'.charCodeAt(0)) {
- prefix = flagAlternative ? '0x' : '';
+ argText = unSign(currArg, 8 * argSize, 1).toString(10);
+ currArg = Math.abs(currArg);
+ } else if (next == {{{ charCode('o') }}}) {
+ argText = (flagAlternative ? '0' : '') + currAbsArg.toString(8);
+ } else if (next == {{{ charCode('x') }}} || next == {{{ charCode('X') }}}) {
+ prefix = flagAlternative ? '0x' : '';
#if PRECISE_I64_MATH
- if (argSize == 8 && i64Math) argText = (origArg[1]>>>0).toString(16) + (origArg[0]>>>0).toString(16); else
+ if (argSize == 8 && i64Math) {
+ if (origArg[1]) {
+ argText = (origArg[1]>>>0).toString(16);
+ var lower = (origArg[0]>>>0).toString(16);
+ while (lower.length < 8) lower = '0' + lower;
+ argText += lower;
+ } else {
+ argText = (origArg[0]>>>0).toString(16);
+ }
+ } else
#endif
- if (currArg < 0) {
- // Represent negative numbers in hex as 2's complement.
- currArg = -currArg;
- argText = (currAbsArg - 1).toString(16);
- var buffer = [];
- for (var i = 0; i < argText.length; i++) {
- buffer.push((0xF - parseInt(argText[i], 16)).toString(16));
+ if (currArg < 0) {
+ // Represent negative numbers in hex as 2's complement.
+ currArg = -currArg;
+ argText = (currAbsArg - 1).toString(16);
+ var buffer = [];
+ for (var i = 0; i < argText.length; i++) {
+ buffer.push((0xF - parseInt(argText[i], 16)).toString(16));
+ }
+ argText = buffer.join('');
+ while (argText.length < argSize * 2) argText = 'f' + argText;
+ } else {
+ argText = currAbsArg.toString(16);
+ }
+ if (next == {{{ charCode('X') }}}) {
+ prefix = prefix.toUpperCase();
+ argText = argText.toUpperCase();
+ }
+ } else if (next == {{{ charCode('p') }}}) {
+ if (currAbsArg === 0) {
+ argText = '(nil)';
+ } else {
+ prefix = '0x';
+ argText = currAbsArg.toString(16);
}
- argText = buffer.join('');
- while (argText.length < argSize * 2) argText = 'f' + argText;
- } else {
- argText = currAbsArg.toString(16);
- }
- if (next == 'X'.charCodeAt(0)) {
- prefix = prefix.toUpperCase();
- argText = argText.toUpperCase();
- }
- } else if (next == 'p'.charCodeAt(0)) {
- if (currAbsArg === 0) {
- argText = '(nil)';
- } else {
- prefix = '0x';
- argText = currAbsArg.toString(16);
}
- }
- if (precisionSet) {
- while (argText.length < precision) {
- argText = '0' + argText;
+ if (precisionSet) {
+ while (argText.length < precision) {
+ argText = '0' + argText;
+ }
}
- }
- // Add sign if needed
- if (flagAlwaysSigned) {
- if (currArg < 0) {
- prefix = '-' + prefix;
- } else {
- prefix = '+' + prefix;
+ // Add sign if needed
+ if (flagAlwaysSigned) {
+ if (currArg < 0) {
+ prefix = '-' + prefix;
+ } else {
+ prefix = '+' + prefix;
+ }
}
- }
- // Add padding.
- while (prefix.length + argText.length < width) {
- if (flagLeftAlign) {
- argText += ' ';
- } else {
- if (flagZeroPad) {
- argText = '0' + argText;
+ // Add padding.
+ while (prefix.length + argText.length < width) {
+ if (flagLeftAlign) {
+ argText += ' ';
} else {
- prefix = ' ' + prefix;
+ if (flagZeroPad) {
+ argText = '0' + argText;
+ } else {
+ prefix = ' ' + prefix;
+ }
}
}
+
+ // Insert the result into the buffer.
+ argText = prefix + argText;
+ argText.split('').forEach(function(chr) {
+ ret.push(chr.charCodeAt(0));
+ });
+ break;
}
+ case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': {
+ // Float.
+ var currArg = getNextArg('double');
+ var argText;
+
+ if (isNaN(currArg)) {
+ argText = 'nan';
+ flagZeroPad = false;
+ } else if (!isFinite(currArg)) {
+ argText = (currArg < 0 ? '-' : '') + 'inf';
+ flagZeroPad = false;
+ } else {
+ var isGeneral = false;
+ var effectivePrecision = Math.min(precision, 20);
+
+ // Convert g/G to f/F or e/E, as per:
+ // http://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html
+ if (next == {{{ charCode('g') }}} || next == {{{ charCode('G') }}}) {
+ isGeneral = true;
+ precision = precision || 1;
+ var exponent = parseInt(currArg.toExponential(effectivePrecision).split('e')[1], 10);
+ if (precision > exponent && exponent >= -4) {
+ next = ((next == {{{ charCode('g') }}}) ? 'f' : 'F').charCodeAt(0);
+ precision -= exponent + 1;
+ } else {
+ next = ((next == {{{ charCode('g') }}}) ? 'e' : 'E').charCodeAt(0);
+ precision--;
+ }
+ effectivePrecision = Math.min(precision, 20);
+ }
- // Insert the result into the buffer.
- argText = prefix + argText;
- argText.split('').forEach(function(chr) {
- ret.push(chr.charCodeAt(0));
- });
- } else if (['f', 'F', 'e', 'E', 'g', 'G'].indexOf(String.fromCharCode(next)) != -1) {
- // Float.
- var currArg = getNextArg('double');
- var argText;
-
- if (isNaN(currArg)) {
- argText = 'nan';
- flagZeroPad = false;
- } else if (!isFinite(currArg)) {
- argText = (currArg < 0 ? '-' : '') + 'inf';
- flagZeroPad = false;
- } else {
- var isGeneral = false;
- var effectivePrecision = Math.min(precision, 20);
-
- // Convert g/G to f/F or e/E, as per:
- // http://pubs.opengroup.org/onlinepubs/9699919799/functions/printf.html
- if (next == 'g'.charCodeAt(0) || next == 'G'.charCodeAt(0)) {
- isGeneral = true;
- precision = precision || 1;
- var exponent = parseInt(currArg.toExponential(effectivePrecision).split('e')[1], 10);
- if (precision > exponent && exponent >= -4) {
- next = ((next == 'g'.charCodeAt(0)) ? 'f' : 'F').charCodeAt(0);
- precision -= exponent + 1;
+ if (next == {{{ charCode('e') }}} || next == {{{ charCode('E') }}}) {
+ argText = currArg.toExponential(effectivePrecision);
+ // Make sure the exponent has at least 2 digits.
+ if (/[eE][-+]\d$/.test(argText)) {
+ argText = argText.slice(0, -1) + '0' + argText.slice(-1);
+ }
+ } else if (next == {{{ charCode('f') }}} || next == {{{ charCode('F') }}}) {
+ argText = currArg.toFixed(effectivePrecision);
+ }
+
+ var parts = argText.split('e');
+ if (isGeneral && !flagAlternative) {
+ // Discard trailing zeros and periods.
+ while (parts[0].length > 1 && parts[0].indexOf('.') != -1 &&
+ (parts[0].slice(-1) == '0' || parts[0].slice(-1) == '.')) {
+ parts[0] = parts[0].slice(0, -1);
+ }
} else {
- next = ((next == 'g'.charCodeAt(0)) ? 'e' : 'E').charCodeAt(0);
- precision--;
+ // Make sure we have a period in alternative mode.
+ if (flagAlternative && argText.indexOf('.') == -1) parts[0] += '.';
+ // Zero pad until required precision.
+ while (precision > effectivePrecision++) parts[0] += '0';
}
- effectivePrecision = Math.min(precision, 20);
- }
+ argText = parts[0] + (parts.length > 1 ? 'e' + parts[1] : '');
+
+ // Capitalize 'E' if needed.
+ if (next == {{{ charCode('E') }}}) argText = argText.toUpperCase();
- if (next == 'e'.charCodeAt(0) || next == 'E'.charCodeAt(0)) {
- argText = currArg.toExponential(effectivePrecision);
- // Make sure the exponent has at least 2 digits.
- if (/[eE][-+]\d$/.test(argText)) {
- argText = argText.slice(0, -1) + '0' + argText.slice(-1);
+ // Add sign.
+ if (flagAlwaysSigned && currArg >= 0) {
+ argText = '+' + argText;
}
- } else if (next == 'f'.charCodeAt(0) || next == 'F'.charCodeAt(0)) {
- argText = currArg.toFixed(effectivePrecision);
}
- var parts = argText.split('e');
- if (isGeneral && !flagAlternative) {
- // Discard trailing zeros and periods.
- while (parts[0].length > 1 && parts[0].indexOf('.') != -1 &&
- (parts[0].slice(-1) == '0' || parts[0].slice(-1) == '.')) {
- parts[0] = parts[0].slice(0, -1);
+ // Add padding.
+ while (argText.length < width) {
+ if (flagLeftAlign) {
+ argText += ' ';
+ } else {
+ if (flagZeroPad && (argText[0] == '-' || argText[0] == '+')) {
+ argText = argText[0] + '0' + argText.slice(1);
+ } else {
+ argText = (flagZeroPad ? '0' : ' ') + argText;
+ }
}
- } else {
- // Make sure we have a period in alternative mode.
- if (flagAlternative && argText.indexOf('.') == -1) parts[0] += '.';
- // Zero pad until required precision.
- while (precision > effectivePrecision++) parts[0] += '0';
}
- argText = parts[0] + (parts.length > 1 ? 'e' + parts[1] : '');
- // Capitalize 'E' if needed.
- if (next == 'E'.charCodeAt(0)) argText = argText.toUpperCase();
+ // Adjust case.
+ if (next < {{{ charCode('a') }}}) argText = argText.toUpperCase();
- // Add sign.
- if (flagAlwaysSigned && currArg >= 0) {
- argText = '+' + argText;
- }
+ // Insert the result into the buffer.
+ argText.split('').forEach(function(chr) {
+ ret.push(chr.charCodeAt(0));
+ });
+ break;
}
-
- // Add padding.
- while (argText.length < width) {
+ case 's': {
+ // String.
+ var arg = getNextArg('i8*') || nullString;
+ var argLength = _strlen(arg);
+ if (precisionSet) argLength = Math.min(argLength, precision);
+ if (!flagLeftAlign) {
+ while (argLength < width--) {
+ ret.push({{{ charCode(' ') }}});
+ }
+ }
+ for (var i = 0; i < argLength; i++) {
+ ret.push({{{ makeGetValue('arg++', 0, 'i8', null, true) }}});
+ }
if (flagLeftAlign) {
- argText += ' ';
- } else {
- if (flagZeroPad && (argText[0] == '-' || argText[0] == '+')) {
- argText = argText[0] + '0' + argText.slice(1);
- } else {
- argText = (flagZeroPad ? '0' : ' ') + argText;
+ while (argLength < width--) {
+ ret.push({{{ charCode(' ') }}});
}
}
+ break;
}
-
- // Adjust case.
- if (next < 'a'.charCodeAt(0)) argText = argText.toUpperCase();
-
- // Insert the result into the buffer.
- argText.split('').forEach(function(chr) {
- ret.push(chr.charCodeAt(0));
- });
- } else if (next == 's'.charCodeAt(0)) {
- // String.
- var arg = getNextArg('i8*') || nullString;
- var argLength = _strlen(arg);
- if (precisionSet) argLength = Math.min(argLength, precision);
- if (!flagLeftAlign) {
- while (argLength < width--) {
- ret.push(' '.charCodeAt(0));
+ case 'c': {
+ // Character.
+ if (flagLeftAlign) ret.push(getNextArg('i8'));
+ while (--width > 0) {
+ ret.push({{{ charCode(' ') }}});
}
+ if (!flagLeftAlign) ret.push(getNextArg('i8'));
+ break;
}
- for (var i = 0; i < argLength; i++) {
- ret.push({{{ makeGetValue('arg++', 0, 'i8', null, true) }}});
- }
- if (flagLeftAlign) {
- while (argLength < width--) {
- ret.push(' '.charCodeAt(0));
- }
+ case 'n': {
+ // Write the length written so far to the next parameter.
+ var ptr = getNextArg('i32*');
+ {{{ makeSetValue('ptr', '0', 'ret.length', 'i32') }}}
+ break;
}
- } else if (next == 'c'.charCodeAt(0)) {
- // Character.
- if (flagLeftAlign) ret.push(getNextArg('i8'));
- while (--width > 0) {
- ret.push(' '.charCodeAt(0));
+ case '%': {
+ // Literal percent sign.
+ ret.push(curr);
+ break;
}
- if (!flagLeftAlign) ret.push(getNextArg('i8'));
- } else if (next == 'n'.charCodeAt(0)) {
- // Write the length written so far to the next parameter.
- var ptr = getNextArg('i32*');
- {{{ makeSetValue('ptr', '0', 'ret.length', 'i32') }}}
- } else if (next == '%'.charCodeAt(0)) {
- // Literal percent sign.
- ret.push(curr);
- } else {
- // Unknown specifiers remain untouched.
- for (var i = startTextIndex; i < textIndex + 2; i++) {
- ret.push({{{ makeGetValue(0, 'i', 'i8') }}});
+ default: {
+ // Unknown specifiers remain untouched.
+ for (var i = startTextIndex; i < textIndex + 2; i++) {
+ ret.push({{{ makeGetValue(0, 'i', 'i8') }}});
+ }
}
}
textIndex += 2;
@@ -3139,7 +3167,7 @@ LibraryManager.library = {
var streamObj = FS.streams[stream];
if (streamObj.error || streamObj.eof) return 0;
var byte_;
- for (var i = 0; i < n - 1 && byte_ != '\n'.charCodeAt(0); i++) {
+ for (var i = 0; i < n - 1 && byte_ != {{{ charCode('\n') }}}; i++) {
byte_ = _fgetc(stream);
if (byte_ == -1) {
if (streamObj.error || (streamObj.eof && i == 0)) return 0;
@@ -3245,7 +3273,7 @@ LibraryManager.library = {
if (ret < 0) {
return ret;
} else {
- var newlineRet = _fputc('\n'.charCodeAt(0), stdout);
+ var newlineRet = _fputc({{{ charCode('\n') }}}, stdout);
return (newlineRet < 0) ? -1 : ret + 1;
}
},
@@ -3371,8 +3399,8 @@ LibraryManager.library = {
var stdout = {{{ makeGetValue(makeGlobalUse('_stdout'), '0', 'void*') }}};
if (s) {
_fputs(s, stdout);
- _fputc(':'.charCodeAt(0), stdout);
- _fputc(' '.charCodeAt(0), stdout);
+ _fputc({{{ charCode(':') }}}, stdout);
+ _fputc({{{ charCode(' ') }}}, stdout);
}
var errnum = {{{ makeGetValue('___errno_location()', '0', 'i32') }}};
_puts(_strerror(errnum));
@@ -3745,19 +3773,19 @@ LibraryManager.library = {
// Check for a plus/minus sign.
var multiplier = 1;
- if ({{{ makeGetValue('str', 0, 'i8') }}} == '-'.charCodeAt(0)) {
+ if ({{{ makeGetValue('str', 0, 'i8') }}} == {{{ charCode('-') }}}) {
multiplier = -1;
str++;
- } else if ({{{ makeGetValue('str', 0, 'i8') }}} == '+'.charCodeAt(0)) {
+ } else if ({{{ makeGetValue('str', 0, 'i8') }}} == {{{ charCode('+') }}}) {
str++;
}
// Find base.
var finalBase = base;
if (!finalBase) {
- if ({{{ makeGetValue('str', 0, 'i8') }}} == '0'.charCodeAt(0)) {
- if ({{{ makeGetValue('str+1', 0, 'i8') }}} == 'x'.charCodeAt(0) ||
- {{{ makeGetValue('str+1', 0, 'i8') }}} == 'X'.charCodeAt(0)) {
+ if ({{{ makeGetValue('str', 0, 'i8') }}} == {{{ charCode('0') }}}) {
+ if ({{{ makeGetValue('str+1', 0, 'i8') }}} == {{{ charCode('x') }}} ||
+ {{{ makeGetValue('str+1', 0, 'i8') }}} == {{{ charCode('X') }}}) {
finalBase = 16;
str += 2;
} else {
@@ -3821,9 +3849,9 @@ LibraryManager.library = {
while (_isspace({{{ makeGetValue('str', 0, 'i8') }}})) str++;
// Check for a plus/minus sign.
- if ({{{ makeGetValue('str', 0, 'i8') }}} == '-'.charCodeAt(0)) {
+ if ({{{ makeGetValue('str', 0, 'i8') }}} == {{{ charCode('-') }}}) {
str++;
- } else if ({{{ makeGetValue('str', 0, 'i8') }}} == '+'.charCodeAt(0)) {
+ } else if ({{{ makeGetValue('str', 0, 'i8') }}} == {{{ charCode('+') }}}) {
str++;
}
@@ -3831,9 +3859,9 @@ LibraryManager.library = {
var ok = false;
var finalBase = base;
if (!finalBase) {
- if ({{{ makeGetValue('str', 0, 'i8') }}} == '0'.charCodeAt(0)) {
- if ({{{ makeGetValue('str+1', 0, 'i8') }}} == 'x'.charCodeAt(0) ||
- {{{ makeGetValue('str+1', 0, 'i8') }}} == 'X'.charCodeAt(0)) {
+ if ({{{ makeGetValue('str', 0, 'i8') }}} == {{{ charCode('0') }}}) {
+ if ({{{ makeGetValue('str+1', 0, 'i8') }}} == {{{ charCode('x') }}} ||
+ {{{ makeGetValue('str+1', 0, 'i8') }}} == {{{ charCode('X') }}}) {
finalBase = 16;
str += 2;
} else {
@@ -4163,7 +4191,7 @@ LibraryManager.library = {
return ret;
},
- memcpy__asm: 'true',
+ memcpy__asm: true,
memcpy__sig: 'iiii',
memcpy: function (dest, src, num) {
dest = dest|0; src = src|0; num = num|0;
@@ -4324,14 +4352,18 @@ LibraryManager.library = {
}
},
+ strcpy__asm: true,
+ strcpy__sig: 'iii',
strcpy: function(pdest, psrc) {
+ pdest = pdest|0; psrc = psrc|0;
var i = 0;
do {
- {{{ makeCopyValues('pdest+i', 'psrc+i', 1, 'i8', null, 1) }}};
- i ++;
- } while ({{{ makeGetValue('psrc', 'i-1', 'i8') }}} != 0);
- return pdest;
+ {{{ makeCopyValues('(pdest+i)|0', '(psrc+i)|0', 1, 'i8', null, 1) }}};
+ i = (i+1)|0;
+ } while (({{{ makeGetValue('psrc', 'i-1', 'i8') }}})|0 != 0);
+ return pdest|0;
},
+
stpcpy: function(pdest, psrc) {
var i = 0;
do {
@@ -4341,14 +4373,18 @@ LibraryManager.library = {
return pdest + i - 1;
},
+ strncpy__asm: true,
+ strncpy__sig: 'iiii',
strncpy: function(pdest, psrc, num) {
- var padding = false, curr;
- for (var i = 0; i < num; i++) {
- curr = padding ? 0 : {{{ makeGetValue('psrc', 'i', 'i8') }}};
+ pdest = pdest|0; psrc = psrc|0; num = num|0;
+ var padding = 0, curr = 0, i = 0;
+ while ((i|0) < (num|0)) {
+ curr = padding ? 0 : {{{ makeGetValueAsm('psrc', 'i', 'i8') }}};
{{{ makeSetValue('pdest', 'i', 'curr', 'i8') }}}
- padding = padding || {{{ makeGetValue('psrc', 'i', 'i8') }}} == 0;
+ padding = padding ? 1 : ({{{ makeGetValueAsm('psrc', 'i', 'i8') }}} == 0);
+ i = (i+1)|0;
}
- return pdest;
+ return pdest|0;
},
strlwr__deps:['tolower'],
@@ -4373,15 +4409,18 @@ LibraryManager.library = {
}
},
+ strcat__asm: true,
+ strcat__sig: 'iii',
strcat__deps: ['strlen'],
strcat: function(pdest, psrc) {
- var len = _strlen(pdest);
+ pdest = pdest|0; psrc = psrc|0;
var i = 0;
+ pdest = (pdest + _strlen(pdest))|0;
do {
- {{{ makeCopyValues('pdest+len+i', 'psrc+i', 1, 'i8', null, 1) }}};
- i ++;
- } while ({{{ makeGetValue('psrc', 'i-1', 'i8') }}} != 0);
- return pdest;
+ {{{ makeCopyValues('pdest+i', 'psrc+i', 1, 'i8', null, 1) }}};
+ i = (i+1)|0;
+ } while ({{{ makeGetValueAsm('psrc', 'i-1', 'i8') }}} != 0);
+ return pdest|0;
},
strncat__deps: ['strlen'],
@@ -4407,9 +4446,12 @@ LibraryManager.library = {
// We always assume ASCII locale.
strcoll: 'strcmp',
+ strcasecmp__asm: true,
+ strcasecmp__sig: 'iii',
strcasecmp__deps: ['strncasecmp'],
strcasecmp: function(px, py) {
- return _strncasecmp(px, py, TOTAL_MEMORY);
+ px = px|0; py = py|0;
+ return _strncasecmp(px, py, -1)|0;
},
strncmp: function(px, py, n) {
@@ -4430,26 +4472,29 @@ LibraryManager.library = {
return 0;
},
+ strncasecmp__asm: true,
+ strncasecmp__sig: 'iiii',
strncasecmp__deps: ['tolower'],
strncasecmp: function(px, py, n) {
- var i = 0;
- while (i < n) {
- var x = _tolower({{{ makeGetValue('px', 'i', 'i8', 0, 1) }}});
- var y = _tolower({{{ makeGetValue('py', 'i', 'i8', 0, 1) }}});
- if (x == y && x == 0) return 0;
- if (x == 0) return -1;
- if (y == 0) return 1;
- if (x == y) {
- i ++;
+ px = px|0; py = py|0; n = n|0;
+ var i = 0, x = 0, y = 0;
+ while ((i>>>0) < (n>>>0)) {
+ x = _tolower({{{ makeGetValueAsm('px', 'i', 'i8', 0, 1) }}});
+ y = _tolower({{{ makeGetValueAsm('py', 'i', 'i8', 0, 1) }}});
+ if (((x|0) == (y|0)) & ((x|0) == 0)) return 0;
+ if ((x|0) == 0) return -1;
+ if ((y|0) == 0) return 1;
+ if ((x|0) == (y|0)) {
+ i = (i + 1)|0;
continue;
} else {
- return x > y ? 1 : -1;
+ return ((x>>>0) > (y>>>0) ? 1 : -1)|0;
}
}
return 0;
},
- memcmp__asm: 'true',
+ memcmp__asm: true,
memcmp__sig: 'iiii',
memcmp: function(p1, p2, num) {
p1 = p1|0; p2 = p2|0; num = num|0;
@@ -4651,58 +4696,61 @@ LibraryManager.library = {
return chr & 0x7F;
},
toupper: function(chr) {
- if (chr >= 'a'.charCodeAt(0) && chr <= 'z'.charCodeAt(0)) {
- return chr - 'a'.charCodeAt(0) + 'A'.charCodeAt(0);
+ if (chr >= {{{ charCode('a') }}} && chr <= {{{ charCode('z') }}}) {
+ return chr - {{{ charCode('a') }}} + {{{ charCode('A') }}};
} else {
return chr;
}
},
_toupper: 'toupper',
+
+ tolower__asm: true,
+ tolower__sig: 'ii',
tolower: function(chr) {
- if (chr >= 'A'.charCodeAt(0) && chr <= 'Z'.charCodeAt(0)) {
- return chr - 'A'.charCodeAt(0) + 'a'.charCodeAt(0);
- } else {
- return chr;
- }
+ chr = chr|0;
+ if ((chr|0) < {{{ charCode('A') }}}) return chr|0;
+ if ((chr|0) > {{{ charCode('Z') }}}) return chr|0;
+ return (chr - {{{ charCode('A') }}} + {{{ charCode('a') }}})|0;
},
_tolower: 'tolower',
+
// The following functions are defined as macros in glibc.
islower: function(chr) {
- return chr >= 'a'.charCodeAt(0) && chr <= 'z'.charCodeAt(0);
+ return chr >= {{{ charCode('a') }}} && chr <= {{{ charCode('z') }}};
},
isupper: function(chr) {
- return chr >= 'A'.charCodeAt(0) && chr <= 'Z'.charCodeAt(0);
+ return chr >= {{{ charCode('A') }}} && chr <= {{{ charCode('Z') }}};
},
isalpha: function(chr) {
- return (chr >= 'a'.charCodeAt(0) && chr <= 'z'.charCodeAt(0)) ||
- (chr >= 'A'.charCodeAt(0) && chr <= 'Z'.charCodeAt(0));
+ return (chr >= {{{ charCode('a') }}} && chr <= {{{ charCode('z') }}}) ||
+ (chr >= {{{ charCode('A') }}} && chr <= {{{ charCode('Z') }}});
},
isdigit: function(chr) {
- return chr >= '0'.charCodeAt(0) && chr <= '9'.charCodeAt(0);
+ return chr >= {{{ charCode('0') }}} && chr <= {{{ charCode('9') }}};
},
isdigit_l: 'isdigit', // no locale support yet
isxdigit: function(chr) {
- return (chr >= '0'.charCodeAt(0) && chr <= '9'.charCodeAt(0)) ||
- (chr >= 'a'.charCodeAt(0) && chr <= 'f'.charCodeAt(0)) ||
- (chr >= 'A'.charCodeAt(0) && chr <= 'F'.charCodeAt(0));
+ return (chr >= {{{ charCode('0') }}} && chr <= {{{ charCode('9') }}}) ||
+ (chr >= {{{ charCode('a') }}} && chr <= {{{ charCode('f') }}}) ||
+ (chr >= {{{ charCode('A') }}} && chr <= {{{ charCode('F') }}});
},
isxdigit_l: 'isxdigit', // no locale support yet
isalnum: function(chr) {
- return (chr >= '0'.charCodeAt(0) && chr <= '9'.charCodeAt(0)) ||
- (chr >= 'a'.charCodeAt(0) && chr <= 'z'.charCodeAt(0)) ||
- (chr >= 'A'.charCodeAt(0) && chr <= 'Z'.charCodeAt(0));
+ return (chr >= {{{ charCode('0') }}} && chr <= {{{ charCode('9') }}}) ||
+ (chr >= {{{ charCode('a') }}} && chr <= {{{ charCode('z') }}}) ||
+ (chr >= {{{ charCode('A') }}} && chr <= {{{ charCode('Z') }}});
},
ispunct: function(chr) {
- return (chr >= '!'.charCodeAt(0) && chr <= '/'.charCodeAt(0)) ||
- (chr >= ':'.charCodeAt(0) && chr <= '@'.charCodeAt(0)) ||
- (chr >= '['.charCodeAt(0) && chr <= '`'.charCodeAt(0)) ||
- (chr >= '{'.charCodeAt(0) && chr <= '~'.charCodeAt(0));
+ return (chr >= {{{ charCode('!') }}} && chr <= {{{ charCode('/') }}}) ||
+ (chr >= {{{ charCode(':') }}} && chr <= {{{ charCode('@') }}}) ||
+ (chr >= {{{ charCode('[') }}} && chr <= {{{ charCode('`') }}}) ||
+ (chr >= {{{ charCode('{') }}} && chr <= {{{ charCode('~') }}});
},
isspace: function(chr) {
return chr in { 32: 0, 9: 0, 10: 0, 11: 0, 12: 0, 13: 0 };
},
isblank: function(chr) {
- return chr == ' '.charCodeAt(0) || chr == '\t'.charCodeAt(0);
+ return chr == {{{ charCode(' ') }}} || chr == {{{ charCode('\t') }}};
},
iscntrl: function(chr) {
return (0 <= chr && chr <= 0x1F) || chr === 0x7F;
@@ -5206,13 +5254,6 @@ LibraryManager.library = {
{{{ makeStructuralReturn(['(x*y)>>>0', 'x*y > 4294967295']) }}};
},
- llvm_uadd_with_overflow_i64__deps: [function() { Types.preciseI64MathUsed = 1 }],
- llvm_uadd_with_overflow_i64: function(xl, xh, yl, yh) {
- i64Math.add(xl, xh, yl, yh);
- {{{ makeStructuralReturn([makeGetTempDouble(0, 'i32'), makeGetTempDouble(1, 'i32'), '0']) }}};
- // XXX Need to hack support for second param in long.js
- },
-
llvm_umul_with_overflow_i64__deps: [function() { Types.preciseI64MathUsed = 1 }],
llvm_umul_with_overflow_i64: function(xl, xh, yl, yh) {
i64Math.multiply(xl, xh, yl, yh);
@@ -7352,6 +7393,81 @@ LibraryManager.library = {
Module.print(intArrayToString(__formatString(_emscripten_jcache_printf_.buffer, varargs + i*4)).replace('\\n', ''));
Runtime.stackAlloc(-4*i); // free up the stack space we know is ok to free
},
+
+ //============================
+ // i64 math
+ //============================
+
+ i64Add__asm: true,
+ i64Add__sig: 'iiiii',
+ i64Add: function(a, b, c, d) {
+ /*
+ x = a + b*2^32
+ y = c + d*2^32
+ result = l + h*2^32
+ */
+ 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;
+ }
+ {{{ makeStructuralReturn(['l|0', 'h'], true) }}};
+ },
+ llvm_uadd_with_overflow_i64__asm: true,
+ llvm_uadd_with_overflow_i64__sig: 'iiiii',
+ llvm_uadd_with_overflow_i64: function(a, b, c, d) {
+ a = a|0; b = b|0; c = c|0; d = d|0;
+ var l = 0, h = 0, overflow = 0;
+ l = (a + c)>>>0;
+ h = (b + d)>>>0;
+ if ((l>>>0) < (a>>>0)) { // iff we overflowed
+ h = (h+1)>>>0;
+ overflow = 1;
+ }
+ {{{ makeStructuralReturn(['l|0', 'h', 'overflow'], true) }}};
+ },
+
+ bitshift64Shl__asm: true,
+ bitshift64Shl__sig: 'iiii',
+ bitshift64Shl: function(low, high, bits) {
+ low = low|0; high = high|0; bits = bits|0;
+ var ander = 0;
+ if ((bits|0) < 32) {
+ ander = ((1 << bits) - 1)|0;
+ tempRet0 = (high << bits) | ((low&(ander << (32 - bits))) >>> (32 - bits));
+ return low << bits;
+ }
+ tempRet0 = low << (bits - 32);
+ return 0;
+ },
+ bitshift64Ashr__asm: true,
+ bitshift64Ashr__sig: 'iiii',
+ bitshift64Ashr: function(low, high, bits) {
+ low = low|0; high = high|0; bits = bits|0;
+ var ander = 0;
+ if ((bits|0) < 32) {
+ ander = ((1 << bits) - 1)|0;
+ tempRet0 = high >> bits;
+ return (low >>> bits) | ((high&ander) << (32 - bits));
+ }
+ tempRet0 = (high|0) < 0 ? -1 : 0;
+ return (high >> (bits - 32))|0;
+ },
+ bitshift64Lshr__asm: true,
+ bitshift64Lshr__sig: 'iiii',
+ bitshift64Lshr: function(low, high, bits) {
+ low = low|0; high = high|0; bits = bits|0;
+ var ander = 0;
+ if ((bits|0) < 32) {
+ ander = ((1 << bits) - 1)|0;
+ tempRet0 = high >>> bits;
+ return (low >>> bits) | ((high&ander) << (32 - bits));
+ }
+ tempRet0 = 0;
+ return (high >>> (bits - 32))|0;
+ },
};
function autoAddDeps(object, name) {
@@ -7363,3 +7479,4 @@ function autoAddDeps(object, name) {
}
}
+
diff --git a/src/library_gl.js b/src/library_gl.js
index 9e12e4ee..297a36cf 100644
--- a/src/library_gl.js
+++ b/src/library_gl.js
@@ -58,7 +58,12 @@ var LibraryGL = {
return ret;
},
- // Temporary buffers
+ // Mini temp buffer
+ MINI_TEMP_BUFFER_SIZE: 16,
+ miniTempBuffer: null,
+ miniTempBufferViews: [0], // index i has the view of size i+1
+
+ // Large temporary buffers
MAX_TEMP_BUFFER_SIZE: {{{ GL_MAX_TEMP_BUFFER_SIZE }}},
tempBufferIndexLookup: null,
tempVertexBuffers: null,
@@ -311,6 +316,11 @@ var LibraryGL = {
if (!Module.useWebGL) return; // an app might link both gl and 2d backends
+ GL.miniTempBuffer = new Float32Array(GL.MINI_TEMP_BUFFER_SIZE);
+ for (var i = 0; i < GL.MINI_TEMP_BUFFER_SIZE; i++) {
+ GL.miniTempBufferViews[i] = GL.miniTempBuffer.subarray(0, i+1);
+ }
+
GL.maxVertexAttribs = Module.ctx.getParameter(Module.ctx.MAX_VERTEX_ATTRIBS);
#if FULL_ES2
for (var i = 0; i < GL.maxVertexAttribs; i++) {
@@ -832,53 +842,108 @@ var LibraryGL = {
glUniform1fv__sig: 'viii',
glUniform1fv: function(location, count, value) {
location = GL.uniforms[location];
- value = {{{ makeHEAPView('F32', 'value', 'value+count*4') }}};
- Module.ctx.uniform1fv(location, value);
+ var view;
+ if (count == 1) {
+ // avoid allocation for the common case of uploading one uniform
+ view = GL.miniTempBufferViews[0];
+ view[0] = {{{ makeGetValue('value', '0', 'float') }}};
+ } else {
+ view = {{{ makeHEAPView('F32', 'value', 'value+count*4') }}};
+ }
+ Module.ctx.uniform1fv(location, view);
},
glUniform2fv__sig: 'viii',
glUniform2fv: function(location, count, value) {
location = GL.uniforms[location];
- count *= 2;
- value = {{{ makeHEAPView('F32', 'value', 'value+count*4') }}};
- Module.ctx.uniform2fv(location, value);
+ var view;
+ if (count == 1) {
+ // avoid allocation for the common case of uploading one uniform
+ view = GL.miniTempBufferViews[1];
+ view[0] = {{{ makeGetValue('value', '0', 'float') }}};
+ view[1] = {{{ makeGetValue('value', '4', 'float') }}};
+ } else {
+ view = {{{ makeHEAPView('F32', 'value', 'value+count*8') }}};
+ }
+ Module.ctx.uniform2fv(location, view);
},
glUniform3fv__sig: 'viii',
glUniform3fv: function(location, count, value) {
location = GL.uniforms[location];
- count *= 3;
- value = {{{ makeHEAPView('F32', 'value', 'value+count*4') }}};
- Module.ctx.uniform3fv(location, value);
+ var view;
+ if (count == 1) {
+ // avoid allocation for the common case of uploading one uniform
+ view = GL.miniTempBufferViews[2];
+ view[0] = {{{ makeGetValue('value', '0', 'float') }}};
+ view[1] = {{{ makeGetValue('value', '4', 'float') }}};
+ view[2] = {{{ makeGetValue('value', '8', 'float') }}};
+ } else {
+ view = {{{ makeHEAPView('F32', 'value', 'value+count*12') }}};
+ }
+ Module.ctx.uniform3fv(location, view);
},
glUniform4fv__sig: 'viii',
glUniform4fv: function(location, count, value) {
location = GL.uniforms[location];
- count *= 4;
- value = {{{ makeHEAPView('F32', 'value', 'value+count*4') }}};
- Module.ctx.uniform4fv(location, value);
+ var view;
+ if (count == 1) {
+ // avoid allocation for the common case of uploading one uniform
+ view = GL.miniTempBufferViews[3];
+ view[0] = {{{ makeGetValue('value', '0', 'float') }}};
+ view[1] = {{{ makeGetValue('value', '4', 'float') }}};
+ view[2] = {{{ makeGetValue('value', '8', 'float') }}};
+ view[3] = {{{ makeGetValue('value', '12', 'float') }}};
+ } else {
+ view = {{{ makeHEAPView('F32', 'value', 'value+count*16') }}};
+ }
+ Module.ctx.uniform4fv(location, view);
},
glUniformMatrix2fv: function(location, count, transpose, value) {
location = GL.uniforms[location];
- count *= 4;
- value = {{{ makeHEAPView('F32', 'value', 'value+count*4') }}};
- Module.ctx.uniformMatrix2fv(location, transpose, value);
+ var view;
+ if (count == 1) {
+ // avoid allocation for the common case of uploading one uniform matrix
+ view = GL.miniTempBufferViews[3];
+ for (var i = 0; i < 4; i++) {
+ view[i] = {{{ makeGetValue('value', 'i*4', 'float') }}};
+ }
+ } else {
+ view = {{{ makeHEAPView('F32', 'value', 'value+count*16') }}};
+ }
+ Module.ctx.uniformMatrix2fv(location, transpose, view);
},
glUniformMatrix3fv: function(location, count, transpose, value) {
location = GL.uniforms[location];
- count *= 9;
- value = {{{ makeHEAPView('F32', 'value', 'value+count*4') }}};
- Module.ctx.uniformMatrix3fv(location, transpose, value);
+ var view;
+ if (count == 1) {
+ // avoid allocation for the common case of uploading one uniform matrix
+ view = GL.miniTempBufferViews[8];
+ for (var i = 0; i < 9; i++) {
+ view[i] = {{{ makeGetValue('value', 'i*4', 'float') }}};
+ }
+ } else {
+ view = {{{ makeHEAPView('F32', 'value', 'value+count*36') }}};
+ }
+ Module.ctx.uniformMatrix3fv(location, transpose, view);
},
glUniformMatrix4fv: function(location, count, transpose, value) {
location = GL.uniforms[location];
- count *= 16;
- value = {{{ makeHEAPView('F32', 'value', 'value+count*4') }}};
- Module.ctx.uniformMatrix4fv(location, transpose, value);
+ var view;
+ if (count == 1) {
+ // avoid allocation for the common case of uploading one uniform matrix
+ view = GL.miniTempBufferViews[15];
+ for (var i = 0; i < 16; i++) {
+ view[i] = {{{ makeGetValue('value', 'i*4', 'float') }}};
+ }
+ } else {
+ view = {{{ makeHEAPView('F32', 'value', 'value+count*64') }}};
+ }
+ Module.ctx.uniformMatrix4fv(location, transpose, view);
},
glBindBuffer__sig: 'vii',
@@ -1809,6 +1874,8 @@ var LibraryGL = {
var typeIndex = attribute.type - GL.byteSizeByTypeRoot; // ensure it starts at 0 to keep the cache items dense
temp = cacheItem[typeIndex];
cacheItem = temp ? temp : (cacheItem[typeIndex] = GL.immediate.rendererCacheItemTemplate.slice());
+ temp = cacheItem[attribute.stride];
+ cacheItem = temp ? temp : (cacheItem[attribute.stride] = GL.immediate.rendererCacheItemTemplate.slice());
}
var fogParam;
if (GLEmulation.fogEnabled) {
diff --git a/src/library_openal.js b/src/library_openal.js
new file mode 100644
index 00000000..6bd0f6b0
--- /dev/null
+++ b/src/library_openal.js
@@ -0,0 +1,541 @@
+//"use strict";
+
+var LibraryOpenAL = {
+ $AL__deps: ['$Browser'],
+ $AL: {
+ contexts: [],
+ currentContext: null,
+ },
+
+ alcProcessContext: function(context) {},
+ alcSuspendContext: function(context) {},
+
+ alcMakeContextCurrent: function(context) {
+ if (context == 0) {
+ AL.currentContext = null;
+ } else {
+ AL.currentContext = AL.contexts[context - 1];
+ }
+ },
+
+ alcDestroyContext: function(context) {
+ // Stop playback, etc
+ },
+
+ alcCloseDevice: function(device) {
+ // Stop playback, etc
+ },
+
+ alcOpenDevice: function(deviceName) {
+ if (typeof(AudioContext) == "function" ||
+ typeof(webkitAudioContext) == "function") {
+ return 1; // non-null pointer -- we just simulate one device
+ } else {
+ return 0;
+ }
+ },
+
+ alcCreateContext: function(device, attrList) {
+ if (device != 1) {
+ return 0;
+ }
+
+ if (attrList) {
+#if OPENAL_DEBUG
+ console.log("The attrList argument of alcCreateContext is not supported yet");
+#endif
+ return 0;
+ }
+
+ var ctx;
+ try {
+ ctx = new AudioContext();
+ } catch (e) {
+ try {
+ ctx = new webkitAudioContext();
+ } catch (e) {}
+ }
+
+ if (ctx) {
+ AL.contexts.push({ctx: ctx, err: 0, src: [], buf: []});
+ return AL.contexts.length;
+ } else {
+ return 0;
+ }
+ },
+
+ alGetError: function() {
+ if (!AL.currentContext) {
+ return 0xA004 /* AL_INVALID_OPERATION */;
+ } else {
+ return AL.currentContext.err;
+ }
+ },
+
+ alDeleteSources: function(count, sources)
+ {
+ if (!AL.currentContext) {
+#if OPENAL_DEBUG
+ console.error("alDeleteSources called without a valid context");
+#endif
+ return;
+ }
+ for (var i = 0; i < count; ++i) {
+ var sourceIdx = {{{ makeGetValue('sources', 'i', 'i32') }}} - 1;
+ delete AL.currentContext.src[sourceIdx];
+ }
+ },
+
+ alGenSources: function(count, sources) {
+ if (!AL.currentContext) {
+#if OPENAL_DEBUG
+ console.error("alGenSources called without a valid context");
+#endif
+ return;
+ }
+ for (var i = 0; i < count; ++i) {
+ var gain = AL.currentContext.ctx.createGain();
+ var panner = AL.currentContext.ctx.createPanner();
+ if (typeof(webkitAudioContext) == 'function') {
+ gain.connect(panner);
+ panner.connect(AL.currentContext.ctx.destination);
+ } else {
+ // Work around a Firefox bug (bug 849916)
+ gain.connect(AL.currentContext.ctx.destination);
+ }
+ gain.gain.value = 1; // work around a Firefox bug (bug 850970)
+ AL.currentContext.src.push({
+ loop: false,
+ buffer: null,
+ gain: gain,
+ panner: panner,
+ paused: false,
+ playTime: -1,
+ pausedTime: 0
+ });
+ {{{ makeSetValue('sources', 'i', 'AL.currentContext.src.length', 'i32') }}};
+ }
+ },
+
+ alSourcei: function(source, param, value) {
+ if (!AL.currentContext) {
+#if OPENAL_DEBUG
+ console.error("alSourcei called without a valid context");
+#endif
+ return;
+ }
+ if (source > AL.currentContext.src.length) {
+#if OPENAL_DEBUG
+ console.error("alSourcei called with an invalid source");
+#endif
+ return;
+ }
+ switch (param) {
+ case 0x1007 /* AL_LOOPING */:
+ AL.currentContext.src[source - 1].loop = (value != 0 /* AL_FALSE */);
+ break;
+ case 0x1009 /* AL_BUFFER */:
+ if (value == 0) {
+ AL.currentContext.src[source - 1].buffer = null;
+ } else {
+ AL.currentContext.src[source - 1].buffer = AL.currentContext.buf[value - 1].buf;
+ }
+ break;
+ default:
+#if OPENAL_DEBUG
+ console.log("alSourcei with param " + param + " not implemented yet");
+#endif
+ break;
+ }
+ },
+
+ alSourcef: function(source, param, value) {
+ if (!AL.currentContext) {
+#if OPENAL_DEBUG
+ console.error("alSourcef called without a valid context");
+#endif
+ return;
+ }
+ if (source > AL.currentContext.src.length) {
+#if OPENAL_DEBUG
+ console.error("alSourcef called with an invalid source");
+#endif
+ return;
+ }
+ switch (param) {
+ case 0x100A /* AL_GAIN */:
+ AL.currentContext.src[source - 1].gain.gain.value = value;
+ break;
+ case 0x1003 /* AL_PITCH */:
+#if OPENAL_DEBUG
+ console.log("alSourcef was called with AL_PITCH, but Web Audio does not support static pitch changes");
+#endif
+ break;
+ default:
+#if OPENAL_DEBUG
+ console.log("alSourcef with param " + param + " not implemented yet");
+#endif
+ break;
+ }
+ },
+
+ alSourcefv: function(source, param, value) {
+ if (!AL.currentContext) {
+#if OPENAL_DEBUG
+ console.error("alSourcefv called without a valid context");
+#endif
+ return;
+ }
+ if (source > AL.currentContext.src.length) {
+#if OPENAL_DEBUG
+ console.error("alSourcefv called with an invalid source");
+#endif
+ return;
+ }
+ switch (param) {
+ case 0x1004 /* AL_POSITION */:
+ AL.currentContext.src[source - 1].panner.setPosition(
+ {{{ makeGetValue('value', '0', 'float') }}},
+ {{{ makeGetValue('value', '1', 'float') }}},
+ {{{ makeGetValue('value', '2', 'float') }}}
+ );
+ break;
+ case 0x1006 /* AL_VELOCITY */:
+ AL.currentContext.src[source - 1].panner.setVelocity(
+ {{{ makeGetValue('value', '0', 'float') }}},
+ {{{ makeGetValue('value', '1', 'float') }}},
+ {{{ makeGetValue('value', '2', 'float') }}}
+ );
+ break;
+ default:
+#if OPENAL_DEBUG
+ console.log("alSourcefv with param " + param + " not implemented yet");
+#endif
+ break;
+ }
+ },
+
+ alSourceQueueBuffers: function(source, count, buffers) {
+ if (!AL.currentContext) {
+#if OPENAL_DEBUG
+ console.error("alSourceQueueBuffers called without a valid context");
+#endif
+ return;
+ }
+ if (source > AL.currentContext.src.length) {
+#if OPENAL_DEBUG
+ console.error("alSourceQueueBuffers called with an invalid source");
+#endif
+ return;
+ }
+ if (count != 1) {
+#if OPENAL_DEBUG
+ console.error("Queuing multiple buffers using alSourceQueueBuffers is not supported yet");
+#endif
+ return;
+ }
+ for (var i = 0; i < count; ++i) {
+ var buffer = {{{ makeGetValue('buffers', 'i', 'i32') }}};
+ if (buffer > AL.currentContext.buf.length) {
+#if OPENAL_DEBUG
+ console.error("alSourceQueueBuffers called with an invalid buffer");
+#endif
+ return;
+ }
+ AL.currentContext.src[source - 1].buffer = AL.currentContext.buf[buffer - 1].buf;
+ }
+ },
+
+ alSourceUnqueueBuffers: function(source, count, buffers)
+ {
+ if (!AL.currentContext) {
+#if OPENAL_DEBUG
+ console.error("alSourceUnqueueBuffers called without a valid context");
+#endif
+ return;
+ }
+ if (source > AL.currentContext.src.length) {
+#if OPENAL_DEBUG
+ console.error("alSourceUnqueueBuffers called with an invalid source");
+#endif
+ return;
+ }
+ if (count != 1) {
+#if OPENAL_DEBUG
+ console.error("Queuing multiple buffers using alSourceUnqueueBuffers is not supported yet");
+#endif
+ return;
+ }
+ for (var i = 0; i < count; ++i) {
+ var buffer = AL.currentContext.src[source - 1].buffer;
+ for (var j = 0; j < AL.currentContext.buf.length; ++j) {
+ if (buffer == AL.currentContext.buf[j].buf) {
+ {{{ makeSetValue('buffers', 'i', 'j+1', 'i32') }}};
+ AL.currentContext.src[source - 1].buffer = null;
+ break;
+ }
+ }
+ }
+ },
+
+ alDeleteBuffers: function(count, buffers)
+ {
+ if (!AL.currentContext) {
+#if OPENAL_DEBUG
+ console.error("alDeleteBuffers called without a valid context");
+#endif
+ return;
+ }
+ for (var i = 0; i < count; ++i) {
+ var bufferIdx = {{{ makeGetValue('buffers', 'i', 'i32') }}} - 1;
+ var buffer = AL.currentContext.buf[bufferIdx].buf;
+ for (var j = 0; j < AL.currentContext.src.length; ++j) {
+ if (buffer == AL.currentContext.src[j].buffer) {
+ AL.currentContext.err = 0xA004 /* AL_INVALID_OPERATION */;
+ return;
+ }
+ }
+ delete AL.currentContext.buf[bufferIdx];
+ }
+ },
+
+ alGenBuffers: function(count, buffers) {
+ if (!AL.currentContext) {
+#if OPENAL_DEBUG
+ console.error("alGenBuffers called without a valid context");
+#endif
+ return;
+ }
+ for (var i = 0; i < count; ++i) {
+ AL.currentContext.buf.push({buf: null});
+ {{{ makeSetValue('buffers', 'i', 'AL.currentContext.buf.length', 'i32') }}};
+ }
+ },
+
+ alBufferData: function(buffer, format, data, size, freq) {
+ if (!AL.currentContext) {
+#if OPENAL_DEBUG
+ console.error("alBufferData called without a valid context");
+#endif
+ return;
+ }
+ if (buffer > AL.currentContext.buf.length) {
+#if OPENAL_DEBUG
+ console.error("alBufferData called with an invalid buffer");
+#endif
+ return;
+ }
+ var channels, bytes;
+ switch (format) {
+ case 0x1100 /* AL_FORMAT_MONO8 */:
+ bytes = 1;
+ channels = 1;
+ break;
+ case 0x1101 /* AL_FORMAT_MONO16 */:
+ bytes = 2;
+ channels = 1;
+ break;
+ case 0x1102 /* AL_FORMAT_STEREO8 */:
+ bytes = 1;
+ channels = 2;
+ break;
+ case 0x1103 /* AL_FORMAT_STEREO16 */:
+ bytes = 2;
+ channels = 2;
+ break;
+ default:
+#if OPENAL_DEBUG
+ console.error("alBufferData called with invalid format " + format);
+#endif
+ return;
+ }
+ AL.currentContext.buf[buffer - 1].buf = AL.currentContext.ctx.createBuffer(channels, size / (bytes * channels), freq);
+ var buf = new Array(channels);
+ for (var i = 0; i < channels; ++i) {
+ buf[i] = AL.currentContext.buf[buffer - 1].buf.getChannelData(i);
+ }
+ for (var i = 0; i < size / (bytes * channels); ++i) {
+ for (var j = 0; j < channels; ++j) {
+ switch (bytes) {
+ case 1:
+ var val = {{{ makeGetValue('data', 'i*channels+j', 'i8') }}};
+ buf[j][i] = -1.0 + val * (2/256);
+ break;
+ case 2:
+ var val = {{{ makeGetValue('data', '2*(i*channels+j)', 'i16') }}};
+ buf[j][i] = val/32768;
+ break;
+ }
+ }
+ }
+ },
+
+ alSourcePlay__deps: ["alSourceStop"],
+ alSourcePlay: function(source) {
+ if (!AL.currentContext) {
+#if OPENAL_DEBUG
+ console.error("alSourcePlay called without a valid context");
+#endif
+ return;
+ }
+ if (source > AL.currentContext.src.length) {
+#if OPENAL_DEBUG
+ console.error("alSourcePlay called with an invalid source");
+#endif
+ return;
+ }
+ var offset = 0;
+ if ("src" in AL.currentContext.src[source - 1]) {
+ // If the source is already playing, we need to resume from beginning.
+ // We do that by stopping the current source and replaying it.
+ _alSourceStop(source);
+ } else if (AL.currentContext.src[source - 1].paused) {
+ // So now we have to resume playback, remember the offset here.
+ offset = AL.currentContext.src[source - 1].pausedTime -
+ AL.currentContext.src[source - 1].playTime;
+ }
+ var src = AL.currentContext.ctx.createBufferSource();
+ src.loop = AL.currentContext.src[source - 1].loop;
+ src.buffer = AL.currentContext.src[source - 1].buffer;
+ src.connect(AL.currentContext.src[source - 1].gain);
+ src.start(0, offset);
+ // Work around Firefox bug 851338
+ AL.currentContext.src[source - 1].playTime = AL.currentContext.ctx.currentTime || 0;
+ AL.currentContext.src[source - 1].paused = false;
+ AL.currentContext.src[source - 1]['src'] = src;
+ },
+
+ alSourceStop: function(source) {
+ if (!AL.currentContext) {
+#if OPENAL_DEBUG
+ console.error("alSourceStop called without a valid context");
+#endif
+ return;
+ }
+ if (source > AL.currentContext.src.length) {
+#if OPENAL_DEBUG
+ console.error("alSourceStop called with an invalid source");
+#endif
+ return;
+ }
+ if ("src" in AL.currentContext.src[source - 1]) {
+ AL.currentContext.src[source - 1]["src"].stop(0);
+ delete AL.currentContext.src[source - 1]["src"];
+ }
+ },
+
+ alSourcePause: function(source) {
+ if (!AL.currentContext) {
+#if OPENAL_DEBUG
+ console.error("alSourcePause called without a valid context");
+#endif
+ return;
+ }
+ if (source > AL.currentContext.src.length) {
+#if OPENAL_DEBUG
+ console.error("alSourcePause called with an invalid source");
+#endif
+ return;
+ }
+ if ("src" in AL.currentContext.src[source - 1] &&
+ !AL.currentContext.src[source - 1].paused) {
+ AL.currentContext.src[source - 1].paused = true;
+ // Work around Firefox bug 851338
+ AL.currentContext.src[source - 1].pausedTime = AL.currentContext.ctx.currentTime || 0;
+ AL.currentContext.src[source - 1]["src"].stop(0);
+ delete AL.currentContext.src[source - 1].src;
+ }
+ },
+
+ alGetSourcei: function(source, param, value) {
+ if (!AL.currentContext) {
+#if OPENAL_DEBUG
+ console.error("alGetSourcei called without a valid context");
+#endif
+ return;
+ }
+ if (source > AL.currentContext.src.length) {
+#if OPENAL_DEBUG
+ console.error("alGetSourcei called with an invalid source");
+#endif
+ return;
+ }
+ switch (param) {
+ case 0x202 /* AL_SOURCE_RELATIVE */:
+ // Always return 1
+ {{{ makeSetValue('value', '0', '1', 'i32') }}};
+ break;
+ case 0x1009 /* AL_BUFFER */:
+ if (AL.currentContext.src[source - 1].buffer == null) {
+ {{{ makeSetValue('value', '0', '0', 'i32') }}};
+ } else {
+ var buf = AL.currentContext.src[source - 1].buffer;
+ for (var i = 0; i < AL.currentContext.buf.length; ++i) {
+ if (buf == AL.currentContext.buf[i].buf) {
+ {{{ makeSetValue('value', '0', 'i+1', 'i32') }}};
+ return;
+ }
+ }
+ {{{ makeSetValue('value', '0', '0', 'i32') }}};
+ }
+ break;
+ case 0x1010 /* AL_SOURCE_STATE */:
+ if ("src" in AL.currentContext.src[source - 1]) {
+ {{{ makeSetValue('value', '0', '0x1012', 'i32') }}} /* AL_PLAYING */;
+ } else if (AL.currentContext.src[source - 1].paused) {
+ {{{ makeSetValue('value', '0', '0x1013', 'i32') }}} /* AL_PAUSED */;
+ } else if (AL.currentContext.src[source - 1].playTime == -1) {
+ {{{ makeSetValue('value', '0', '0x1011', 'i32') }}} /* AL_INITIAL */;
+ } else {
+ {{{ makeSetValue('value', '0', '0x1014', 'i32') }}} /* AL_STOPPED */;
+ }
+ break;
+ case 0x1015 /* AL_BUFFERS_QUEUED */:
+ if (AL.currentContext.src[source - 1].buffer) {
+ {{{ makeSetValue('value', '0', '1', 'i32') }}}
+ } else {
+ {{{ makeSetValue('value', '0', '0', 'i32') }}}
+ }
+ break;
+ case 0x1016 /* AL_BUFFERS_PROCESSED */:
+ // Always return 1
+ {{{ makeSetValue('value', '0', '1', 'i32') }}}
+ break;
+ }
+ },
+
+ alDistanceModel: function(model) {
+ if (model != 0 /* AL_NONE */) {
+#if OPENAL_DEBUG
+ console.log("Only alDistanceModel(AL_NONE) is currently supported");
+#endif
+ }
+ },
+
+ alListenerfv: function(param, values) {
+#if OPENAL_DEBUG
+ console.log("alListenerfv is not supported yet");
+#endif
+ },
+
+ alIsExtensionPresent: function(extName) {
+ return 0;
+ },
+
+ alcIsExtensionPresent: function(device, extName) {
+ return 0;
+ },
+
+ alGetProcAddress: function(fname) {
+ return 0;
+ },
+
+ alcGetProcAddress: function(device, fname) {
+ return 0;
+ },
+
+};
+
+autoAddDeps(LibraryOpenAL, '$AL');
+mergeInto(LibraryManager.library, LibraryOpenAL);
+
diff --git a/src/library_sdl.js b/src/library_sdl.js
index 3dbb9a33..77305609 100644
--- a/src/library_sdl.js
+++ b/src/library_sdl.js
@@ -35,6 +35,7 @@ var LibrarySDL = {
mixerFormat: 0x8010, // AUDIO_S16LSB
mixerNumChannels: 2,
mixerChunkSize: 1024,
+ channelMinimumNumber: 0,
GL: false, // Set to true if we call SDL_SetVideoMode with SDL_OPENGL, and if so, we do not create 2D canvases&contexts for blitting
// Note that images loaded before SDL_SetVideoMode will not get this optimization
@@ -442,6 +443,23 @@ var LibrarySDL = {
return false;
},
+ offsetsTemp: { left: 0, top: 0 }, // temporary object to avoid generating garbage in offsets(). assumes the object is not captured
+
+ offsets: function(element) {
+ var left = 0;
+ var top = 0;
+
+ do {
+ left += element.offsetLeft;
+ top += element.offsetTop;
+ } while (element = element.offsetParent)
+
+ var ret = SDL.offsetsTemp;
+ ret.left = left;
+ ret.top = top;
+ return ret;
+ },
+
makeCEvent: function(event, ptr) {
if (typeof event === 'number') {
// This is a pointer to a native C event that was SDL_PushEvent'ed
@@ -523,8 +541,9 @@ var LibrarySDL = {
} else {
// Otherwise, calculate the movement based on the changes
// in the coordinates.
- var x = event.pageX - Module["canvas"].offsetLeft;
- var y = event.pageY - Module["canvas"].offsetTop;
+ var offsets = SDL.offsets(Module["canvas"]);
+ var x = event.pageX - offsets.left;
+ var y = event.pageY - offsets.top;
var movementX = x - SDL.mouseX;
var movementY = y - SDL.mouseY;
}
@@ -911,10 +930,11 @@ var LibrarySDL = {
SDL_WarpMouse: function(x, y) {
return; // TODO: implement this in a non-buggy way. Need to keep relative mouse movements correct after calling this
+ var offsets = SDL.offsets(Module["canvas"]);
SDL.events.push({
type: 'mousemove',
- pageX: x + Module['canvas'].offsetLeft,
- pageY: y + Module['canvas'].offsetTop
+ pageX: x + offsets.left,
+ pageY: y + offsets.top
});
},
@@ -1235,7 +1255,6 @@ var LibrarySDL = {
Mix_Init: function(flags) {
if (!flags) return 0;
- SDL.channelMinimumNumber = 0;
return 8; /* MIX_INIT_OGG */
},
Mix_Quit: function(){},
diff --git a/src/long.js b/src/long.js
index c3651bd9..6d0e873d 100644
--- a/src/long.js
+++ b/src/long.js
@@ -1530,13 +1530,6 @@ var i64Math = (function() { // Emscripten wrapper
// Emscripten wrapper
var Wrapper = {
- add: function(xl, xh, yl, yh) {
- var x = new goog.math.Long(xl, xh);
- var y = new goog.math.Long(yl, yh);
- var ret = x.add(y);
- HEAP32[tempDoublePtr>>2] = ret.low_;
- HEAP32[tempDoublePtr+4>>2] = ret.high_;
- },
subtract: function(xl, xh, yl, yh) {
var x = new goog.math.Long(xl, xh);
var y = new goog.math.Long(yl, yh);
diff --git a/src/modules.js b/src/modules.js
index 65b8d437..bda8a605 100644
--- a/src/modules.js
+++ b/src/modules.js
@@ -374,7 +374,7 @@ var LibraryManager = {
load: function() {
if (this.library) return;
- var libraries = ['library.js', 'library_browser.js', 'library_sdl.js', 'library_gl.js', 'library_glut.js', 'library_xlib.js', 'library_egl.js', 'library_gc.js', 'library_jansson.js'].concat(additionalLibraries);
+ var libraries = ['library.js', 'library_browser.js', 'library_sdl.js', 'library_gl.js', 'library_glut.js', 'library_xlib.js', 'library_egl.js', 'library_gc.js', 'library_jansson.js', 'library_openal.js'].concat(additionalLibraries);
for (var i = 0; i < libraries.length; i++) {
eval(processMacros(preprocess(read(libraries[i]))));
}
diff --git a/src/parseTools.js b/src/parseTools.js
index 48274cd5..2664baed 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -1724,13 +1724,14 @@ function makeLLVMStruct(values) {
}
}
-function makeStructuralReturn(values) {
+function makeStructuralReturn(values, inAsm) {
if (USE_TYPED_ARRAYS == 2) {
- var i = 0;
- return 'return (' + values.slice(1).map(function(value) {
- return ASM_JS ? 'asm.setTempRet' + (i++) + '(' + value + ')'
+ var i = -1;
+ return 'return ' + asmCoercion(values.slice(1).map(function(value) {
+ i++;
+ return ASM_JS ? (inAsm ? 'tempRet' + i + ' = ' + value : 'asm.setTempRet' + i + '(' + value + ')')
: 'tempRet' + (i++) + ' = ' + value;
- }).concat([values[0]]).join(',') + ')';
+ }).concat([values[0]]).join(','), 'i32');
} else {
var i = 0;
return 'return { ' + values.map(function(value) {
@@ -1971,6 +1972,10 @@ function processMathop(item) {
return finish(['(i64Math' + (ASM_JS ? '_' : '.') + type + '(' + asmCoercion(low1, 'i32') + ',' + asmCoercion(high1, 'i32') + ',' + asmCoercion(low2, 'i32') + ',' + asmCoercion(high2, 'i32') +
(lastArg ? ',' + asmCoercion(+lastArg, 'i32') : '') + '),' + makeGetValue('tempDoublePtr', 0, 'i32') + ')', makeGetValue('tempDoublePtr', Runtime.getNativeTypeSize('i32'), 'i32')]);
}
+ function i64PreciseLib(type) {
+ Types.preciseI64MathUsed = true;
+ return finish(['_i64' + type[0].toUpperCase() + type.substr(1) + '(' + low1 + ',' + high1 + ',' + low2 + ',' + high2 + ')', 'tempRet0']);
+ }
switch (op) {
// basic integer ops
case 'or': {
@@ -1985,43 +1990,7 @@ function processMathop(item) {
case 'shl':
case 'ashr':
case 'lshr': {
- if (!isNumber(idents[1])) {
- return '(Runtime' + (ASM_JS ? '_' : '.') + 'bitshift64(' + idents[0] + '[0], ' + idents[0] + '[1],' + Runtime['BITSHIFT64_' + op.toUpperCase()] + ',' + stripCorrections(idents[1]) + '[0]|0),' +
- '[' + makeGetTempDouble(0, 'i32') + ',' + makeGetTempDouble(1, 'i32') + '])';
- }
- bits = parseInt(idents[1]);
- var ander = Math.pow(2, bits)-1;
- if (bits < 32) {
- switch (op) {
- case 'shl':
- return '[' + idents[0] + '[0] << ' + idents[1] + ', ' +
- '('+idents[0] + '[1] << ' + idents[1] + ') | ((' + idents[0] + '[0]&(' + ander + '<<' + (32 - bits) + ')) >>> (32-' + idents[1] + '))]';
- case 'ashr':
- return '[((('+idents[0] + '[0] >>> ' + idents[1] + ') | ((' + idents[0] + '[1]&' + ander + ')<<' + (32 - bits) + ')) >> 0) >>> 0,' +
- '(' + idents[0] + '[1] >> ' + idents[1] + ') >>> 0]';
- case 'lshr':
- return '[(('+idents[0] + '[0] >>> ' + idents[1] + ') | ((' + idents[0] + '[1]&' + ander + ')<<' + (32 - bits) + ')) >>> 0,' +
- idents[0] + '[1] >>> ' + idents[1] + ']';
- }
- } else if (bits == 32) {
- switch (op) {
- case 'shl':
- return '[0, ' + idents[0] + '[0]]';
- case 'ashr':
- return '[' + idents[0] + '[1], (' + idents[0] + '[1]|0) < 0 ? ' + ander + ' : 0]';
- case 'lshr':
- return '[' + idents[0] + '[1], 0]';
- }
- } else { // bits > 32
- switch (op) {
- case 'shl':
- return '[0, ' + idents[0] + '[0] << ' + (bits - 32) + ']';
- case 'ashr':
- return '[(' + idents[0] + '[1] >> ' + (bits - 32) + ') >>> 0, (' + idents[0] + '[1]|0) < 0 ? ' + ander + ' : 0]';
- case 'lshr':
- return '[' + idents[0] + '[1] >>> ' + (bits - 32) + ', 0]';
- }
- }
+ throw 'shifts should have been legalized!';
}
case 'uitofp': case 'sitofp': return RuntimeGenerator.makeBigInt(low1, high1, op[0] == 'u');
case 'fptoui': case 'fptosi': return finish(splitI64(idents[0], true));
@@ -2059,7 +2028,7 @@ function processMathop(item) {
// Dangerous, rounded operations. TODO: Fully emulate
case 'add': {
if (PRECISE_I64_MATH) {
- return i64PreciseOp('add');
+ return i64PreciseLib('add');
} else {
warnI64_1();
return finish(splitI64(mergeI64(idents[0]) + '+' + mergeI64(idents[1]), true));
@@ -2350,3 +2319,7 @@ function getImplementationType(varInfo) {
return varInfo.type;
}
+function charCode(char) {
+ return char.charCodeAt(0);
+}
+
diff --git a/src/preamble.js b/src/preamble.js
index 7538b19c..2cff440c 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -503,34 +503,47 @@ function allocate(slab, types, allocator, ptr) {
Module['allocate'] = allocate;
function Pointer_stringify(ptr, /* optional */ length) {
- var utf8 = new Runtime.UTF8Processor();
- var nullTerminated = typeof(length) == "undefined";
- var ret = "";
- var i = 0;
+ // Find the length, and check for UTF while doing so
+ var hasUtf = false;
var t;
+ var i = 0;
while (1) {
+ t = {{{ makeGetValue('ptr', 'i', 'i8', 0, 1) }}};
+ if (t >= 128) hasUtf = true;
+ else if (t == 0 && !length) break;
+ i++;
+ if (length && i == length) break;
+ }
+ if (!length) length = i;
+
+ var ret = '';
+
+#if USE_TYPED_ARRAYS == 2
+ if (!hasUtf) {
+ var MAX_CHUNK = 1024; // split up into chunks, because .apply on a huge string can overflow the stack
+ var curr;
+ while (length > 0) {
+ curr = String.fromCharCode.apply(String, HEAPU8.subarray(ptr, ptr + Math.min(length, MAX_CHUNK)));
+ ret = ret ? ret + curr : curr;
+ ptr += MAX_CHUNK;
+ length -= MAX_CHUNK;
+ }
+ return ret;
+ }
+#endif
+
+ var utf8 = new Runtime.UTF8Processor();
+ for (i = 0; i < length; i++) {
#if ASSERTIONS
- assert(i < TOTAL_MEMORY);
+ assert(ptr + i < TOTAL_MEMORY);
#endif
t = {{{ makeGetValue('ptr', 'i', 'i8', 0, 1) }}};
- if (nullTerminated && t == 0) break;
ret += utf8.processCChar(t);
- i += 1;
- if (!nullTerminated && i == length) break;
}
return ret;
}
Module['Pointer_stringify'] = Pointer_stringify;
-function Array_stringify(array) {
- var ret = "";
- for (var i = 0; i < array.length; i++) {
- ret += String.fromCharCode(array[i]);
- }
- return ret;
-}
-Module['Array_stringify'] = Array_stringify;
-
// Memory management
var PAGE_SIZE = 4096;
@@ -557,7 +570,7 @@ function enlargeMemory() {
#if ASM_JS == 0
abort('Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value, (2) compile with ALLOW_MEMORY_GROWTH which adjusts the size at runtime but prevents some optimizations, or (3) set Module.TOTAL_MEMORY before the program runs.');
#else
- abort('Cannot enlarge memory arrays in asm.js. Compile with -s TOTAL_MEMORY=X with X higher than the current value.');
+ abort('Cannot enlarge memory arrays in asm.js. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value, or (2) set Module.TOTAL_MEMORY before the program runs.');
#endif
#else
// TOTAL_MEMORY is the current size of the actual array, and STATICTOP is the new top.
diff --git a/src/runtime.js b/src/runtime.js
index d5c0fabc..2a26db28 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -122,57 +122,6 @@ var Runtime = {
INT_TYPES: set('i1', 'i8', 'i16', 'i32', 'i64'),
FLOAT_TYPES: set('float', 'double'),
- // Mirrors processMathop's treatment of constants (which we optimize directly)
- BITSHIFT64_SHL: 0,
- BITSHIFT64_ASHR: 1,
- BITSHIFT64_LSHR: 2,
- bitshift64: function(low, high, op, bits) {
- var ret;
- var ander = Math.pow(2, bits)-1;
- if (bits < 32) {
- switch (op) {
- case Runtime.BITSHIFT64_SHL:
- ret = [low << bits, (high << bits) | ((low&(ander << (32 - bits))) >>> (32 - bits))];
- break;
- case Runtime.BITSHIFT64_ASHR:
- ret = [(((low >>> bits ) | ((high&ander) << (32 - bits))) >> 0) >>> 0, (high >> bits) >>> 0];
- break;
- case Runtime.BITSHIFT64_LSHR:
- ret = [((low >>> bits) | ((high&ander) << (32 - bits))) >>> 0, high >>> bits];
- break;
- }
- } else if (bits == 32) {
- switch (op) {
- case Runtime.BITSHIFT64_SHL:
- ret = [0, low];
- break;
- case Runtime.BITSHIFT64_ASHR:
- ret = [high, (high|0) < 0 ? ander : 0];
- break;
- case Runtime.BITSHIFT64_LSHR:
- ret = [high, 0];
- break;
- }
- } else { // bits > 32
- switch (op) {
- case Runtime.BITSHIFT64_SHL:
- ret = [0, low << (bits - 32)];
- break;
- case Runtime.BITSHIFT64_ASHR:
- ret = [(high >> (bits - 32)) >>> 0, (high|0) < 0 ? ander : 0];
- break;
- case Runtime.BITSHIFT64_LSHR:
- ret = [high >>> (bits - 32) , 0];
- break;
- }
- }
-#if ASSERTIONS
- assert(ret);
-#endif
- HEAP32[tempDoublePtr>>2] = ret[0]; // cannot use utility functions since we are in runtime itself
- HEAP32[tempDoublePtr+4>>2] = ret[1];
- },
-
// Imprecise bitops utilities
or64: function(x, y) {
var l = (x | 0) | (y | 0);
diff --git a/src/settings.js b/src/settings.js
index 101c403c..97963ac5 100644
--- a/src/settings.js
+++ b/src/settings.js
@@ -163,6 +163,8 @@ var LIBRARY_DEBUG = 0; // Print out when we enter a library call (library*.js).
// emscripten_run_script("Runtime.debug = ...;");
var SOCKET_DEBUG = 0; // Log out socket/network data transfer.
+var OPENAL_DEBUG = 0; // Print out debugging information from our OpenAL implementation.
+
var GL_DEBUG = 0; // Print out all calls into WebGL. As with LIBRARY_DEBUG, you can set a runtime
// option, in this case GL.debug.
var GL_TESTING = 0; // When enabled, sets preserveDrawingBuffer in the context, to allow tests to work (but adds overhead)
@@ -224,19 +226,22 @@ var NAMED_GLOBALS = 0; // If 1, we use global variables for globals. Otherwise
// they are referred to by a base plus an offset (called an indexed global),
// saving global variables but adding runtime overhead.
-var EXPORT_ALL = 0; // If true, we export all the symbols
var EXPORTED_FUNCTIONS = ['_main']; // Functions that are explicitly exported. These functions are kept alive
// through LLVM dead code elimination, and also made accessible outside of
// the generated code even after running closure compiler (on "Module").
// Note the necessary prefix of "_".
+var EXPORT_ALL = 0; // If true, we export all the symbols
+var EXPORT_BINDINGS = 0; // Export all bindings generator functions (prefixed with emscripten_bind_). This
+ // is necessary to use the bindings generator with asm.js
-var DEFAULT_LIBRARY_FUNCS_TO_INCLUDE = ['memcpy', 'memset', 'malloc', 'free', '$Browser']; // JS library functions (C functions implemented in JS)
- // that we include by default. If you want to make sure
- // something is included by the JS compiler, add it here.
- // For example, if you do not use some emscripten_*
- // C API call from C, but you want to call it from JS,
- // add it here (and in EXPORTED FUNCTIONS with prefix
- // "_", for closure).
+// JS library functions (C functions implemented in JS)
+// that we include by default. If you want to make sure
+// something is included by the JS compiler, add it here.
+// For example, if you do not use some emscripten_*
+// C API call from C, but you want to call it from JS,
+// add it here (and in EXPORTED FUNCTIONS with prefix
+// "_", for closure).
+var DEFAULT_LIBRARY_FUNCS_TO_INCLUDE = ['memcpy', 'memset', 'malloc', 'free', 'strlen', '$Browser'];
var LIBRARY_DEPS_TO_AUTOEXPORT = ['memcpy']; // This list is also used to determine
// auto-exporting of library dependencies (i.e., functions that
@@ -337,8 +342,14 @@ var PGO = 0; // Enables profile-guided optimization in the form of runtime check
// can pass to DEAD_FUNCTIONS (you can also emit the list manually by
// calling PGOMonitor.dump());
var DEAD_FUNCTIONS = []; // A list of functions that no code will be emitted for, and
- // a runtime abort will happen if they are called
+ // a runtime abort will happen if they are called. If
+ // such a function is an unresolved reference, that is not
+ // considered an error.
// TODO: options to lazily load such functions
+var UNRESOLVED_AS_DEAD = 0; // Handle all unresolved functions as if they were in the
+ // list of dead functions. This is a quick way to turn
+ // all unresolved references into runtime aborts (and not
+ // get compile-time warnings or errors on them).
var EXPLICIT_ZEXT = 0; // If 1, generate an explicit conversion of zext i1 to i32, using ?:
diff --git a/src/utility.js b/src/utility.js
index 8db37c61..19444675 100644
--- a/src/utility.js
+++ b/src/utility.js
@@ -267,6 +267,15 @@ function set() {
}
var unset = keys;
+function numberedSet() {
+ var args = typeof arguments[0] === 'object' ? arguments[0] : arguments;
+ var ret = {};
+ for (var i = 0; i < args.length; i++) {
+ ret[args[i]] = i;
+ }
+ return ret;
+}
+
function setSub(x, y) {
var ret = set(keys(x));
for (yy in y) {
diff --git a/system/include/AL/al.h b/system/include/AL/al.h
new file mode 100644
index 00000000..d7234e32
--- /dev/null
+++ b/system/include/AL/al.h
@@ -0,0 +1,172 @@
+#ifndef OPENAL_AL_H__
+#define OPENAL_AL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define AL_BITS 0x2002
+#define AL_BUFFER 0x1009
+#define AL_BUFFERS_PROCESSED 0x1016
+#define AL_BUFFERS_QUEUED 0x1015
+#define AL_BYTE_OFFSET 0x1026
+#define AL_CHANNELS 0x2003
+#define AL_CONE_INNER_ANGLE 0x1001
+#define AL_CONE_OUTER_ANGLE 0x1002
+#define AL_CONE_OUTER_GAIN 0x1022
+#define AL_DIRECTION 0x1005
+#define AL_DISTANCE_MODEL 0xD000
+#define AL_DOPPLER_FACTOR 0xC000
+#define AL_DOPPLER_VELOCITY 0xC001
+#define AL_EXPONENT_DISTANCE 0xD005
+#define AL_EXPONENT_DISTANCE_CLAMPED 0xD006
+#define AL_EXTENSIONS 0xB004
+#define AL_FALSE 0
+#define AL_FORMAT_MONO16 0x1101
+#define AL_FORMAT_MONO8 0x1100
+#define AL_FORMAT_STEREO16 0x1103
+#define AL_FORMAT_STEREO8 0x1102
+#define AL_FREQUENCY 0x2001
+#define AL_GAIN 0x100A
+#define AL_ILLEGAL_COMMAND AL_INVALID_OPERATION
+#define AL_ILLEGAL_ENUM AL_INVALID_ENUM
+#define AL_INITIAL 0x1011
+#define AL_INVALID (-1)
+#define AL_INVALID_ENUM 0xA002
+#define AL_INVALID_NAME 0xA001
+#define AL_INVALID_OPERATION 0xA004
+#define AL_INVALID_VALUE 0xA003
+#define AL_INVERSE_DISTANCE 0xD001
+#define AL_INVERSE_DISTANCE_CLAMPED 0xD002
+#define AL_LINEAR_DISTANCE 0xD003
+#define AL_LINEAR_DISTANCE_CLAMPED 0xD004
+#define AL_LOOPING 0x1007
+#define AL_MAX_DISTANCE 0x1023
+#define AL_MAX_GAIN 0x100E
+#define AL_MIN_GAIN 0x100D
+#define AL_NONE 0
+#define AL_NO_ERROR 0
+#define AL_ORIENTATION 0x100F
+#define AL_OUT_OF_MEMORY 0xA005
+#define AL_PAUSED 0x1013
+#define AL_PENDING 0x2011
+#define AL_PITCH 0x1003
+#define AL_PLAYING 0x1012
+#define AL_POSITION 0x1004
+#define AL_PROCESSED 0x2012
+#define AL_REFERENCE_DISTANCE 0x1020
+#define AL_RENDERER 0xB003
+#define AL_ROLLOFF_FACTOR 0x1021
+#define AL_SAMPLE_OFFSET 0x1025
+#define AL_SEC_OFFSET 0x1024
+#define AL_SIZE 0x2004
+#define AL_SOURCE_RELATIVE 0x202
+#define AL_SOURCE_STATE 0x1010
+#define AL_SOURCE_TYPE 0x1027
+#define AL_SPEED_OF_SOUND 0xC003
+#define AL_STATIC 0x1028
+#define AL_STOPPED 0x1014
+#define AL_STREAMING 0x1029
+#define AL_TRUE 1
+#define AL_UNDETERMINED 0x1030
+#define AL_UNUSED 0x2010
+#define AL_VELOCITY 0x1006
+#define AL_VENDOR 0xB001
+#define AL_VERSION 0xB002
+#define AL_VERSION_1_0
+#define AL_VERSION_1_1
+#define OPENAL
+
+typedef char ALboolean;
+typedef char ALchar;
+typedef double ALdouble;
+typedef float ALfloat;
+typedef int ALenum;
+typedef int ALint;
+typedef int ALsizei;
+typedef short ALshort;
+typedef signed char ALbyte;
+typedef unsigned char ALubyte;
+typedef unsigned int ALuint;
+typedef unsigned short ALushort;
+typedef void ALvoid;
+
+extern ALboolean alGetBoolean(ALenum param);
+extern ALboolean alIsBuffer(ALuint buffer);
+extern ALboolean alIsEnabled(ALenum capability);
+extern ALboolean alIsExtensionPresent(const ALchar *extname);
+extern ALboolean alIsSource(ALuint source);
+extern ALdouble alGetDouble(ALenum param);
+extern ALenum alGetEnumValue(const ALchar *ename);
+extern ALenum alGetError();
+extern ALfloat alGetFloat(ALenum param);
+extern ALint alGetInteger(ALenum param);
+extern const ALchar *alGetString(ALenum param);
+extern void *alGetProcAddress(const ALchar *fname);
+extern void alBuffer3f(ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3);
+extern void alBuffer3i(ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3);
+extern void alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq);
+extern void alBufferf(ALuint buffer, ALenum param, ALfloat value);
+extern void alBufferfv(ALuint buffer, ALenum param, const ALfloat *values);
+extern void alBufferi(ALuint buffer, ALenum param, ALint value);
+extern void alBufferiv(ALuint buffer, ALenum param, const ALint *values);
+extern void alDeleteBuffers(ALsizei n, const ALuint *buffers);
+extern void alDeleteSources(ALsizei n, const ALuint *sources);
+extern void alDisable(ALenum capability);
+extern void alDistanceModel(ALenum distanceModel);
+extern void alDopplerFactor(ALfloat value);
+extern void alDopplerVelocity(ALfloat value);
+extern void alEnable(ALenum capability);
+extern void alGenBuffers(ALsizei n, ALuint *buffers);
+extern void alGenSources(ALsizei n, ALuint *sources);
+extern void alGetBooleanv(ALenum param, ALboolean *values);
+extern void alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3);
+extern void alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3);
+extern void alGetBufferf(ALuint buffer, ALenum param, ALfloat *value);
+extern void alGetBufferfv(ALuint buffer, ALenum param, ALfloat *values);
+extern void alGetBufferi(ALuint buffer, ALenum param, ALint *value);
+extern void alGetBufferiv(ALuint buffer, ALenum param, ALint *values);
+extern void alGetDoublev(ALenum param, ALdouble *values);
+extern void alGetFloatv(ALenum param, ALfloat *values);
+extern void alGetIntegerv(ALenum param, ALint *values);
+extern void alGetListener3f(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3);
+extern void alGetListener3i(ALenum param, ALint *value1, ALint *value2, ALint *value3);
+extern void alGetListenerf(ALenum param, ALfloat *value);
+extern void alGetListenerfv(ALenum param, ALfloat *values);
+extern void alGetListeneri(ALenum param, ALint *value);
+extern void alGetListeneriv(ALenum param, ALint *values);
+extern void alGetSource3f(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3);
+extern void alGetSource3i(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3);
+extern void alGetSourcef(ALuint source, ALenum param, ALfloat *value);
+extern void alGetSourcefv(ALuint source, ALenum param, ALfloat *values);
+extern void alGetSourcei(ALuint source, ALenum param, ALint *value);
+extern void alGetSourceiv(ALuint source, ALenum param, ALint *values);
+extern void alListener3f(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3);
+extern void alListener3i(ALenum param, ALint value1, ALint value2, ALint value3);
+extern void alListenerf(ALenum param, ALfloat value);
+extern void alListenerfv(ALenum param, const ALfloat *values);
+extern void alListeneri(ALenum param, ALint value);
+extern void alListeneriv(ALenum param, const ALint *values);
+extern void alSource3f(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3);
+extern void alSource3i(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3);
+extern void alSourcePause(ALuint source);
+extern void alSourcePausev(ALsizei n, const ALuint *sources);
+extern void alSourcePlay(ALuint source);
+extern void alSourcePlayv(ALsizei n, const ALuint *sources);
+extern void alSourceQueueBuffers(ALuint source, ALsizei nb, const ALuint *buffers);
+extern void alSourceRewind(ALuint source);
+extern void alSourceRewindv(ALsizei n, const ALuint *sources);
+extern void alSourceStop(ALuint source);
+extern void alSourceStopv(ALsizei n, const ALuint *sources);
+extern void alSourceUnqueueBuffers(ALuint source, ALsizei nb, ALuint *buffers);
+extern void alSourcef(ALuint source, ALenum param, ALfloat value);
+extern void alSourcefv(ALuint source, ALenum param, const ALfloat *values);
+extern void alSourcei(ALuint source, ALenum param, ALint value);
+extern void alSourceiv(ALuint source, ALenum param, const ALint *values);
+extern void alSpeedOfSound(ALfloat value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/system/include/AL/alc.h b/system/include/AL/alc.h
new file mode 100644
index 00000000..6ff7cb9b
--- /dev/null
+++ b/system/include/AL/alc.h
@@ -0,0 +1,84 @@
+#ifndef OPENAL_ALC_H__
+#define OPENAL_ALC_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ALCAPI ALC_API
+#define ALCAPIENTRY ALC_APIENTRY
+#define ALC_ALL_ATTRIBUTES 0x1003
+#define ALC_ALL_DEVICES_SPECIFIER 0x1013
+#define ALC_ATTRIBUTES_SIZE 0x1002
+#define ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER 0x311
+#define ALC_CAPTURE_DEVICE_SPECIFIER 0x310
+#define ALC_CAPTURE_SAMPLES 0x312
+#define ALC_DEFAULT_ALL_DEVICES_SPECIFIER 0x1012
+#define ALC_DEFAULT_DEVICE_SPECIFIER 0x1004
+#define ALC_DEVICE_SPECIFIER 0x1005
+#define ALC_ENUMERATE_ALL_EXT 1
+#define ALC_EXTENSIONS 0x1006
+#define ALC_EXT_CAPTURE 1
+#define ALC_FALSE 0
+#define ALC_FREQUENCY 0x1007
+#define ALC_INVALID 0
+#define ALC_INVALID_CONTEXT 0xA002
+#define ALC_INVALID_DEVICE 0xA001
+#define ALC_INVALID_ENUM 0xA003
+#define ALC_INVALID_VALUE 0xA004
+#define ALC_MAJOR_VERSION 0x1000
+#define ALC_MINOR_VERSION 0x1001
+#define ALC_MONO_SOURCES 0x1010
+#define ALC_NO_ERROR 0
+#define ALC_OUT_OF_MEMORY 0xA005
+#define ALC_REFRESH 0x1008
+#define ALC_STEREO_SOURCES 0x1011
+#define ALC_SYNC 0x1009
+#define ALC_TRUE 1
+#define ALC_VERSION_0_1 1
+#define AL_ALC_H
+
+struct ALCcontext_struct;
+struct ALCdevice_struct;
+typedef char ALCboolean;
+typedef char ALCchar;
+typedef double ALCdouble;
+typedef float ALCfloat;
+typedef int ALCenum;
+typedef int ALCint;
+typedef int ALCsizei;
+typedef short ALCshort;
+typedef signed char ALCbyte;
+typedef struct ALCcontext_struct ALCcontext;
+typedef struct ALCdevice_struct ALCdevice;
+typedef unsigned char ALCubyte;
+typedef unsigned int ALCuint;
+typedef unsigned short ALCushort;
+typedef void ALCvoid;
+
+extern ALCboolean alcCaptureCloseDevice(ALCdevice *device);
+extern ALCboolean alcCloseDevice(ALCdevice *device);
+extern ALCboolean alcIsExtensionPresent(ALCdevice *device, const ALCchar *extname);
+extern ALCboolean alcMakeContextCurrent(ALCcontext *context);
+extern ALCcontext *alcCreateContext(ALCdevice *device, const ALCint *attrlist);
+extern ALCcontext *alcGetCurrentContext();
+extern ALCdevice *alcCaptureOpenDevice(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize);
+extern ALCdevice *alcGetContextsDevice(ALCcontext *context);
+extern ALCdevice *alcOpenDevice(const ALCchar *devicename);
+extern ALCenum alcGetEnumValue(ALCdevice *device, const ALCchar *enumname);
+extern ALCenum alcGetError(ALCdevice *device);
+extern const ALCchar *alcGetString(ALCdevice *device, ALCenum param);
+extern void *alcGetProcAddress(ALCdevice *device, const ALCchar *funcname);
+extern void alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples);
+extern void alcCaptureStart(ALCdevice *device);
+extern void alcCaptureStop(ALCdevice *device);
+extern void alcDestroyContext(ALCcontext *context);
+extern void alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values);
+extern void alcProcessContext(ALCcontext *context);
+extern void alcSuspendContext(ALCcontext *context);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/system/include/libc/ctype.h b/system/include/libc/ctype.h
index 26d3c6ce..383a8db1 100644
--- a/system/include/libc/ctype.h
+++ b/system/include/libc/ctype.h
@@ -72,11 +72,14 @@ _CONST
#define isgraph(__c) (__ctype_lookup(__c)&(CTYPE__P|CTYPE__U|CTYPE__L|CTYPE__N))
#define iscntrl(__c) (__ctype_lookup(__c)&CTYPE__C)
+/* XXX: EMSCRIPTEN: We alter the names of __typeof__ declarations to
+ reduce the chance of them conflicting when expanded */
+
#if defined(__GNUC__) && \
(!defined(__STRICT_ANSI__) || __STDC_VERSION__ >= 199901L)
#define isblank(__c) \
- __extension__ ({ __typeof__ (__c) __x = (__c); \
- (__ctype_lookup(__x)&_B) || (int) (__x) == '\t';})
+ __extension__ ({ __typeof__ (__c) __ctb_x = (__c); \
+ (__ctype_lookup(__ctb_x)&_B) || (int) (__ctb_x) == '\t';})
#endif
@@ -86,20 +89,20 @@ _CONST
# if defined(__GNUC__)
# if !defined (_MB_EXTENDED_CHARSETS_ISO) && !defined (_MB_EXTENDED_CHARSETS_WINDOWS)
# define toupper(__c) \
- __extension__ ({ __typeof__ (__c) __x = (__c); \
- islower (__x) ? (int) __x - 'a' + 'A' : (int) __x;})
+ __extension__ ({ __typeof__ (__c) __cttu_x = (__c); \
+ islower (__cttu_x) ? (int) __cttu_x - 'a' + 'A' : (int) __cttu_x;})
# define tolower(__c) \
- __extension__ ({ __typeof__ (__c) __x = (__c); \
- isupper (__x) ? (int) __x - 'A' + 'a' : (int) __x;})
+ __extension__ ({ __typeof__ (__c) __cttl_x = (__c); \
+ isupper (__cttl_x) ? (int) __cttl_x - 'A' + 'a' : (int) __cttl_x;})
# else /* _MB_EXTENDED_CHARSETS* */
/* Allow a gcc warning if the user passed 'char', but defer to the
function. */
# define toupper(__c) \
- __extension__ ({ __typeof__ (__c) __x = (__c); \
- (void) __ctype_ptr__[__x]; (toupper) (__x);})
+ __extension__ ({ __typeof__ (__c) __cttu_x = (__c); \
+ (void) __ctype_ptr__[__cttu_x]; (toupper) (__cttu_x);})
# define tolower(__c) \
- __extension__ ({ __typeof__ (__c) __x = (__c); \
- (void) __ctype_ptr__[__x]; (tolower) (__x);})
+ __extension__ ({ __typeof__ (__c) __cttl_x = (__c); \
+ (void) __ctype_ptr__[__cttl_x]; (tolower) (__cttl_x);})
# endif /* _MB_EXTENDED_CHARSETS* */
# endif /* __GNUC__ */
#endif /* !__cplusplus */
diff --git a/system/include/libc/math.h b/system/include/libc/math.h
index d963c6c8..e2f8cdef 100644
--- a/system/include/libc/math.h
+++ b/system/include/libc/math.h
@@ -210,25 +210,28 @@ extern int __signbitd (double x);
((sizeof(__x) == sizeof(float)) ? __signbitf(__x) : \
__signbitd(__x))
+/* XXX: EMSCRIPTEN: We alter the names of __typeof__ declarations to
+ reduce the chance of them conflicting when expanded */
+
#define isgreater(x,y) \
- (__extension__ ({__typeof__(x) __x = (x); __typeof__(y) __y = (y); \
- !isunordered(__x,__y) && (__x > __y);}))
+ (__extension__ ({__typeof__(x) __isg_x = (x); __typeof__(y) __isg_y = (y); \
+ !isunordered(__isg_x,__isg_y) && (__isg_x > __isg_y);}))
#define isgreaterequal(x,y) \
- (__extension__ ({__typeof__(x) __x = (x); __typeof__(y) __y = (y); \
- !isunordered(__x,__y) && (__x >= __y);}))
+ (__extension__ ({__typeof__(x) __isge_x = (x); __typeof__(y) __isge_y = (y); \
+ !isunordered(__isge_x,__isge_y) && (__isge_x >= __isge_y);}))
#define isless(x,y) \
- (__extension__ ({__typeof__(x) __x = (x); __typeof__(y) __y = (y); \
- !isunordered(__x,__y) && (__x < __y);}))
+ (__extension__ ({__typeof__(x) __isl_x = (x); __typeof__(y) __isl_y = (y); \
+ !isunordered(__isl_x,__isl_y) && (__isl_x < __isl_y);}))
#define islessequal(x,y) \
- (__extension__ ({__typeof__(x) __x = (x); __typeof__(y) __y = (y); \
- !isunordered(__x,__y) && (__x <= __y);}))
+ (__extension__ ({__typeof__(x) __isle_x = (x); __typeof__(y) __isle_y = (y); \
+ !isunordered(__isle_x,__isle_y) && (__isle_x <= __isle_y);}))
#define islessgreater(x,y) \
- (__extension__ ({__typeof__(x) __x = (x); __typeof__(y) __y = (y); \
- !isunordered(__x,__y) && (__x < __y || __x > __y);}))
+ (__extension__ ({__typeof__(x) __islg_x = (x); __typeof__(y) __islg_y = (y); \
+ !isunordered(__islg_x,__islg_y) && (__islg_x < __islg_y || __islg_x > __islg_y);}))
#define isunordered(a,b) \
- (__extension__ ({__typeof__(a) __a = (a); __typeof__(b) __b = (b); \
- fpclassify(__a) == FP_NAN || fpclassify(__b) == FP_NAN;}))
+ (__extension__ ({__typeof__(a) __isu_a = (a); __typeof__(b) __isu_b = (b); \
+ fpclassify(__isu_a) == FP_NAN || fpclassify(__isu_b) == FP_NAN;}))
/* Non ANSI double precision functions. */
diff --git a/tests/cases/alignedunaligned.ll b/tests/cases/alignedunaligned.ll
index 9faa87ef..f4e0535a 100644
--- a/tests/cases/alignedunaligned.ll
+++ b/tests/cases/alignedunaligned.ll
@@ -15,9 +15,7 @@ entry:
%saved_stack = alloca i8* ; [#uses=2 type=i8**]
%cleanup.dest.slot = alloca i32 ; [#uses=1 type=i32*]
store i32 0, i32* %retval
- call void @llvm.dbg.declare(metadata !{i8** %str}, metadata !12), !dbg !16 ; [debug line = 6:19] [debug variable = str]
store i8* getelementptr inbounds ([13 x i8]* @.str, i32 0, i32 0), i8** %str, align 4, !dbg !17 ; [debug line = 6:39]
- call void @llvm.dbg.declare(metadata !{i32* %len}, metadata !18), !dbg !19 ; [debug line = 7:17] [debug variable = len]
%0 = load i8** %str, align 4, !dbg !20 ; [#uses=1 type=i8*] [debug line = 7:23]
%call = call i32 @strlen(i8* %0), !dbg !20 ; [#uses=1 type=i32] [debug line = 7:23]
store i32 %call, i32* %len, align 4, !dbg !20 ; [debug line = 7:23]
@@ -26,7 +24,6 @@ entry:
%2 = call i8* @llvm.stacksave(), !dbg !21 ; [#uses=1 type=i8*] [debug line = 8:29]
store i8* %2, i8** %saved_stack, !dbg !21 ; [debug line = 8:29]
%vla = alloca i8, i32 %add, align 1, !dbg !21 ; [#uses=93 type=i8*] [debug line = 8:29]
- call void @llvm.dbg.declare(metadata !{i8* %vla}, metadata !22), !dbg !26 ; [debug line = 8:18] [debug variable = curr]
%3 = load i32* %len, align 4, !dbg !27 ; [#uses=1 type=i32] [debug line = 13:13]
call void @llvm.memset.p0i8.i32(i8* %vla, i8 46, i32 %3, i32 4, i1 false), !dbg !27 ; [debug line = 13:13]
%4 = load i32* %len, align 4, !dbg !27 ; [#uses=1 type=i32] [debug line = 13:13]
@@ -210,9 +207,6 @@ entry:
ret i32 %63, !dbg !122 ; [debug line = 40:11]
}
-; [#uses=3]
-declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone
-
; [#uses=1]
declare i32 @strlen(i8*)
diff --git a/tests/cases/breakinthemiddle3.ll b/tests/cases/breakinthemiddle3.ll
new file mode 100644
index 00000000..e9173965
--- /dev/null
+++ b/tests/cases/breakinthemiddle3.ll
@@ -0,0 +1,26 @@
+@.str = private constant [15 x i8] c"hello, world!\0A\00", align 1 ; [#uses=1]
+
+define linkonce_odr i32 @main() align 2 {
+ %333 = call i32 @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0)) ; [#uses=0]
+ %199 = trunc i8 1 to i1 ; [#uses=1]
+ switch i32 %333, label %label999 [
+ i32 1000, label %label995
+ ] ; switch should ignore all code after it in the block
+ ; No predecessors!
+ %a472 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
+ cleanup
+ %a473 = extractvalue { i8*, i32 } %a472, 0
+ %a474 = extractvalue { i8*, i32 } %a472, 1
+ br label %label999
+
+label995:
+ %333b = call i32 @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0)) ; [#uses=0]
+ br label %label999
+
+label999: ; preds = %555
+ ret i32 0
+}
+
+declare i32 @printf(i8*)
+declare i32 @__gxx_personality_v0(...)
+
diff --git a/tests/cases/callundef.ll b/tests/cases/callundef.ll
new file mode 100644
index 00000000..a540a08c
--- /dev/null
+++ b/tests/cases/callundef.ll
@@ -0,0 +1,18 @@
+; ModuleID = 'tests/hello_world.bc'
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128"
+target triple = "i386-pc-linux-gnu"
+
+@.str = private unnamed_addr constant [15 x i8] c"hello, world!\0A\00", align 1 ; [#uses=1 type=[15 x i8]*]
+
+; [#uses=0]
+define i32 @main() {
+entry:
+ %retval = alloca i32, align 4 ; [#uses=1 type=i32*]
+ store i32 0, i32* %retval
+ %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0)) ; [#uses=0 type=i32]
+ call void undef(i32 55)
+ ret i32 1
+}
+
+; [#uses=1]
+declare i32 @printf(i8*, ...)
diff --git a/tests/cases/phicubed.ll b/tests/cases/phicubed.ll
index 4f0611ec..a0799997 100644
--- a/tests/cases/phicubed.ll
+++ b/tests/cases/phicubed.ll
@@ -12,25 +12,16 @@ entry:
%a = alloca %struct.worker_args, align 4 ; [#uses=3 type=%struct.worker_args*]
%b = alloca %struct.worker_args, align 4 ; [#uses=4 type=%struct.worker_args*]
%chunk = alloca [10 x %struct.worker_args], align 4 ; [#uses=30 type=[10 x %struct.worker_args]*]
- call void @llvm.dbg.declare(metadata !{%struct.worker_args* %a}, metadata !12), !dbg !23 ; [debug line = 9:25] [debug variable = a]
- call void @llvm.dbg.declare(metadata !{%struct.worker_args* %b}, metadata !24), !dbg !25 ; [debug line = 10:25] [debug variable = b]
%value = getelementptr inbounds %struct.worker_args* %a, i32 0, i32 0, !dbg !26 ; [#uses=1 type=i32*] [debug line = 11:13]
store i32 60, i32* %value, align 4, !dbg !26 ; [debug line = 11:13]
call void @emscripten_autodebug_i32(i32 16, i32 60)
%next = getelementptr inbounds %struct.worker_args* %a, i32 0, i32 1, !dbg !27 ; [#uses=1 type=%struct.worker_args**] [debug line = 12:13]
- call void @llvm.dbg.value(metadata !{%struct.worker_args* %b}, i64 0, metadata !24), !dbg !27 ; [debug line = 12:13] [debug variable = b]
- call void @llvm.dbg.value(metadata !{%struct.worker_args* %b}, i64 0, metadata !24), !dbg !27 ; [debug line = 12:13] [debug variable = b]
- call void @llvm.dbg.value(metadata !{%struct.worker_args* %b}, i64 0, metadata !24), !dbg !27 ; [debug line = 12:13] [debug variable = b]
- call void @llvm.dbg.value(metadata !{%struct.worker_args* %b}, i64 0, metadata !24), !dbg !27 ; [debug line = 12:13] [debug variable = b]
- call void @llvm.dbg.value(metadata !{%struct.worker_args* %b}, i64 0, metadata !24), !dbg !27 ; [debug line = 12:13] [debug variable = b]
store %struct.worker_args* %b, %struct.worker_args** %next, align 4, !dbg !27 ; [debug line = 12:13]
%value1 = getelementptr inbounds %struct.worker_args* %b, i32 0, i32 0, !dbg !28 ; [#uses=1 type=i32*] [debug line = 13:13]
store i32 900, i32* %value1, align 4, !dbg !28 ; [debug line = 13:13]
call void @emscripten_autodebug_i32(i32 26, i32 900)
%next2 = getelementptr inbounds %struct.worker_args* %b, i32 0, i32 1, !dbg !29 ; [#uses=1 type=%struct.worker_args**] [debug line = 14:13]
store %struct.worker_args* null, %struct.worker_args** %next2, align 4, !dbg !29 ; [debug line = 14:13]
- call void @llvm.dbg.value(metadata !{%struct.worker_args* %a}, i64 0, metadata !30), !dbg !31 ; [debug line = 15:32] [debug variable = c]
- call void @llvm.dbg.value(metadata !2, i64 0, metadata !32), !dbg !33 ; [debug line = 16:26] [debug variable = total]
br label %while.body, !dbg !34 ; [debug line = 17:13]
for.cond.preheader: ; preds = %while.body
@@ -40,70 +31,60 @@ for.cond.preheader: ; preds = %while.body
%arrayidx7 = getelementptr inbounds [10 x %struct.worker_args]* %chunk, i32 0, i32 1, !dbg !38 ; [#uses=1 type=%struct.worker_args*] [debug line = 26:15]
%next9 = getelementptr inbounds [10 x %struct.worker_args]* %chunk, i32 0, i32 0, i32 1, !dbg !38 ; [#uses=1 type=%struct.worker_args**] [debug line = 26:15]
store %struct.worker_args* %arrayidx7, %struct.worker_args** %next9, align 4, !dbg !38 ; [debug line = 26:15]
- call void @llvm.dbg.value(metadata !39, i64 0, metadata !40), !dbg !41 ; [debug line = 24:36] [debug variable = i]
%value5.1 = getelementptr inbounds [10 x %struct.worker_args]* %chunk, i32 0, i32 1, i32 0, !dbg !35 ; [#uses=1 type=i32*] [debug line = 25:15]
store i32 10, i32* %value5.1, align 4, !dbg !35 ; [debug line = 25:15]
call void @emscripten_autodebug_i32(i32 43, i32 10)
%arrayidx7.1 = getelementptr inbounds [10 x %struct.worker_args]* %chunk, i32 0, i32 2, !dbg !38 ; [#uses=1 type=%struct.worker_args*] [debug line = 26:15]
%next9.1 = getelementptr inbounds [10 x %struct.worker_args]* %chunk, i32 0, i32 1, i32 1, !dbg !38 ; [#uses=1 type=%struct.worker_args**] [debug line = 26:15]
store %struct.worker_args* %arrayidx7.1, %struct.worker_args** %next9.1, align 4, !dbg !38 ; [debug line = 26:15]
- call void @llvm.dbg.value(metadata !39, i64 0, metadata !40), !dbg !41 ; [debug line = 24:36] [debug variable = i]
%value5.2 = getelementptr inbounds [10 x %struct.worker_args]* %chunk, i32 0, i32 2, i32 0, !dbg !35 ; [#uses=1 type=i32*] [debug line = 25:15]
store i32 20, i32* %value5.2, align 4, !dbg !35 ; [debug line = 25:15]
call void @emscripten_autodebug_i32(i32 50, i32 20)
%arrayidx7.2 = getelementptr inbounds [10 x %struct.worker_args]* %chunk, i32 0, i32 3, !dbg !38 ; [#uses=1 type=%struct.worker_args*] [debug line = 26:15]
%next9.2 = getelementptr inbounds [10 x %struct.worker_args]* %chunk, i32 0, i32 2, i32 1, !dbg !38 ; [#uses=1 type=%struct.worker_args**] [debug line = 26:15]
store %struct.worker_args* %arrayidx7.2, %struct.worker_args** %next9.2, align 4, !dbg !38 ; [debug line = 26:15]
- call void @llvm.dbg.value(metadata !39, i64 0, metadata !40), !dbg !41 ; [debug line = 24:36] [debug variable = i]
%value5.3 = getelementptr inbounds [10 x %struct.worker_args]* %chunk, i32 0, i32 3, i32 0, !dbg !35 ; [#uses=1 type=i32*] [debug line = 25:15]
store i32 30, i32* %value5.3, align 4, !dbg !35 ; [debug line = 25:15]
call void @emscripten_autodebug_i32(i32 57, i32 30)
%arrayidx7.3 = getelementptr inbounds [10 x %struct.worker_args]* %chunk, i32 0, i32 4, !dbg !38 ; [#uses=1 type=%struct.worker_args*] [debug line = 26:15]
%next9.3 = getelementptr inbounds [10 x %struct.worker_args]* %chunk, i32 0, i32 3, i32 1, !dbg !38 ; [#uses=1 type=%struct.worker_args**] [debug line = 26:15]
store %struct.worker_args* %arrayidx7.3, %struct.worker_args** %next9.3, align 4, !dbg !38 ; [debug line = 26:15]
- call void @llvm.dbg.value(metadata !39, i64 0, metadata !40), !dbg !41 ; [debug line = 24:36] [debug variable = i]
%value5.4 = getelementptr inbounds [10 x %struct.worker_args]* %chunk, i32 0, i32 4, i32 0, !dbg !35 ; [#uses=1 type=i32*] [debug line = 25:15]
store i32 40, i32* %value5.4, align 4, !dbg !35 ; [debug line = 25:15]
call void @emscripten_autodebug_i32(i32 64, i32 40)
%arrayidx7.4 = getelementptr inbounds [10 x %struct.worker_args]* %chunk, i32 0, i32 5, !dbg !38 ; [#uses=1 type=%struct.worker_args*] [debug line = 26:15]
%next9.4 = getelementptr inbounds [10 x %struct.worker_args]* %chunk, i32 0, i32 4, i32 1, !dbg !38 ; [#uses=1 type=%struct.worker_args**] [debug line = 26:15]
store %struct.worker_args* %arrayidx7.4, %struct.worker_args** %next9.4, align 4, !dbg !38 ; [debug line = 26:15]
- call void @llvm.dbg.value(metadata !39, i64 0, metadata !40), !dbg !41 ; [debug line = 24:36] [debug variable = i]
%value5.5 = getelementptr inbounds [10 x %struct.worker_args]* %chunk, i32 0, i32 5, i32 0, !dbg !35 ; [#uses=1 type=i32*] [debug line = 25:15]
store i32 50, i32* %value5.5, align 4, !dbg !35 ; [debug line = 25:15]
call void @emscripten_autodebug_i32(i32 71, i32 50)
%arrayidx7.5 = getelementptr inbounds [10 x %struct.worker_args]* %chunk, i32 0, i32 6, !dbg !38 ; [#uses=1 type=%struct.worker_args*] [debug line = 26:15]
%next9.5 = getelementptr inbounds [10 x %struct.worker_args]* %chunk, i32 0, i32 5, i32 1, !dbg !38 ; [#uses=1 type=%struct.worker_args**] [debug line = 26:15]
store %struct.worker_args* %arrayidx7.5, %struct.worker_args** %next9.5, align 4, !dbg !38 ; [debug line = 26:15]
- call void @llvm.dbg.value(metadata !39, i64 0, metadata !40), !dbg !41 ; [debug line = 24:36] [debug variable = i]
%value5.6 = getelementptr inbounds [10 x %struct.worker_args]* %chunk, i32 0, i32 6, i32 0, !dbg !35 ; [#uses=1 type=i32*] [debug line = 25:15]
store i32 60, i32* %value5.6, align 4, !dbg !35 ; [debug line = 25:15]
call void @emscripten_autodebug_i32(i32 78, i32 60)
%arrayidx7.6 = getelementptr inbounds [10 x %struct.worker_args]* %chunk, i32 0, i32 7, !dbg !38 ; [#uses=1 type=%struct.worker_args*] [debug line = 26:15]
%next9.6 = getelementptr inbounds [10 x %struct.worker_args]* %chunk, i32 0, i32 6, i32 1, !dbg !38 ; [#uses=1 type=%struct.worker_args**] [debug line = 26:15]
store %struct.worker_args* %arrayidx7.6, %struct.worker_args** %next9.6, align 4, !dbg !38 ; [debug line = 26:15]
- call void @llvm.dbg.value(metadata !39, i64 0, metadata !40), !dbg !41 ; [debug line = 24:36] [debug variable = i]
%value5.7 = getelementptr inbounds [10 x %struct.worker_args]* %chunk, i32 0, i32 7, i32 0, !dbg !35 ; [#uses=1 type=i32*] [debug line = 25:15]
store i32 70, i32* %value5.7, align 4, !dbg !35 ; [debug line = 25:15]
call void @emscripten_autodebug_i32(i32 85, i32 70)
%arrayidx7.7 = getelementptr inbounds [10 x %struct.worker_args]* %chunk, i32 0, i32 8, !dbg !38 ; [#uses=1 type=%struct.worker_args*] [debug line = 26:15]
%next9.7 = getelementptr inbounds [10 x %struct.worker_args]* %chunk, i32 0, i32 7, i32 1, !dbg !38 ; [#uses=1 type=%struct.worker_args**] [debug line = 26:15]
store %struct.worker_args* %arrayidx7.7, %struct.worker_args** %next9.7, align 4, !dbg !38 ; [debug line = 26:15]
- call void @llvm.dbg.value(metadata !39, i64 0, metadata !40), !dbg !41 ; [debug line = 24:36] [debug variable = i]
%value5.8 = getelementptr inbounds [10 x %struct.worker_args]* %chunk, i32 0, i32 8, i32 0, !dbg !35 ; [#uses=1 type=i32*] [debug line = 25:15]
store i32 80, i32* %value5.8, align 4, !dbg !35 ; [debug line = 25:15]
call void @emscripten_autodebug_i32(i32 92, i32 80)
%arrayidx7.8 = getelementptr inbounds [10 x %struct.worker_args]* %chunk, i32 0, i32 9, !dbg !38 ; [#uses=1 type=%struct.worker_args*] [debug line = 26:15]
%next9.8 = getelementptr inbounds [10 x %struct.worker_args]* %chunk, i32 0, i32 8, i32 1, !dbg !38 ; [#uses=1 type=%struct.worker_args**] [debug line = 26:15]
store %struct.worker_args* %arrayidx7.8, %struct.worker_args** %next9.8, align 4, !dbg !38 ; [debug line = 26:15]
- call void @llvm.dbg.value(metadata !39, i64 0, metadata !40), !dbg !41 ; [debug line = 24:36] [debug variable = i]
%value11 = getelementptr inbounds [10 x %struct.worker_args]* %chunk, i32 0, i32 9, i32 0, !dbg !42 ; [#uses=1 type=i32*] [debug line = 28:13]
store i32 90, i32* %value11, align 4, !dbg !42 ; [debug line = 28:13]
call void @emscripten_autodebug_i32(i32 99, i32 90)
%arrayidx12 = getelementptr inbounds [10 x %struct.worker_args]* %chunk, i32 0, i32 0, !dbg !43 ; [#uses=3 type=%struct.worker_args*] [debug line = 29:13]
%next14 = getelementptr inbounds [10 x %struct.worker_args]* %chunk, i32 0, i32 9, i32 1, !dbg !43 ; [#uses=1 type=%struct.worker_args**] [debug line = 29:13]
store %struct.worker_args* %arrayidx12, %struct.worker_args** %next14, align 4, !dbg !43 ; [debug line = 29:13]
- call void @llvm.dbg.value(metadata !{%struct.worker_args* %arrayidx12}, i64 0, metadata !30), !dbg !44 ; [debug line = 31:13] [debug variable = c]
br label %do.body, !dbg !45 ; [debug line = 32:13]
while.body: ; preds = %while.body.while.body_crit_edge, %entry
@@ -114,8 +95,6 @@ while.body: ; preds = %while.body.while.bo
%1 = load i32* %value3, align 4, !dbg !46 ; [#uses=2 type=i32] [debug line = 18:15]
call void @emscripten_autodebug_i32(i32 112, i32 %1)
%add = add nsw i32 %1, %total.02, !dbg !46 ; [#uses=2 type=i32] [debug line = 18:15]
- call void @llvm.dbg.value(metadata !{i32 %add}, i64 0, metadata !32), !dbg !46 ; [debug line = 18:15] [debug variable = total]
- call void @llvm.dbg.value(metadata !{%struct.worker_args* %0}, i64 0, metadata !30), !dbg !48 ; [debug line = 19:15] [debug variable = c]
%tobool = icmp eq %struct.worker_args* %0, null, !dbg !34 ; [#uses=1 type=i1] [debug line = 17:13]
br i1 %tobool, label %for.cond.preheader, label %while.body.while.body_crit_edge, !dbg !34 ; [debug line = 17:13]
@@ -131,10 +110,8 @@ do.body: ; preds = %do.body, %for.cond.
%2 = load i32* %value15, align 4, !dbg !49 ; [#uses=2 type=i32] [debug line = 33:15]
call void @emscripten_autodebug_i32(i32 129, i32 %2)
%add16 = add nsw i32 %2, %total.1, !dbg !49 ; [#uses=2 type=i32] [debug line = 33:15]
- call void @llvm.dbg.value(metadata !{i32 %add16}, i64 0, metadata !32), !dbg !49 ; [debug line = 33:15] [debug variable = total]
%next17 = getelementptr inbounds %struct.worker_args* %c.1, i32 0, i32 1, !dbg !51 ; [#uses=1 type=%struct.worker_args**] [debug line = 34:15]
%3 = load %struct.worker_args** %next17, align 4, !dbg !51 ; [#uses=2 type=%struct.worker_args*] [debug line = 34:15]
- call void @llvm.dbg.value(metadata !{%struct.worker_args* %3}, i64 0, metadata !30), !dbg !51 ; [debug line = 34:15] [debug variable = c]
%cmp19 = icmp eq %struct.worker_args* %3, %arrayidx12, !dbg !52 ; [#uses=1 type=i1] [debug line = 35:13]
br i1 %cmp19, label %do.end, label %do.body, !dbg !52 ; [debug line = 35:13]
@@ -143,15 +120,9 @@ do.end: ; preds = %do.body
ret i32 0, !dbg !54 ; [debug line = 40:13]
}
-; [#uses=2]
-declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone
-
; [#uses=7]
declare i32 @printf(i8* nocapture, ...) nounwind
-; [#uses=21]
-declare void @llvm.dbg.value(metadata, i64, metadata) nounwind readnone
-
; [#uses=0]
define void @emscripten_autodebug_i64(i32 %line, i64 %value) {
entry:
diff --git a/tests/cases/storestruct.ll b/tests/cases/storestruct.ll
index 5bd9224e..a5b7483b 100644
--- a/tests/cases/storestruct.ll
+++ b/tests/cases/storestruct.ll
@@ -15,8 +15,6 @@ entry:
%x = alloca %struct.X, align 4 ; [#uses=2]
%y = alloca %struct.X, align 4 ; [#uses=2]
store i32 0, i32* %retval
- call void @llvm.dbg.declare(metadata !{%struct.X* %x}, metadata !6), !dbg !13
- call void @llvm.dbg.declare(metadata !{%struct.X* %y}, metadata !14), !dbg !15
%a = getelementptr inbounds %struct.X* %x, i32 0, i32 0, !dbg !16 ; [#uses=1]
store i32 5, i32* %a, align 4, !dbg !16
%b = getelementptr inbounds %struct.X* %x, i32 0, i32 1, !dbg !17 ; [#uses=1]
@@ -54,9 +52,6 @@ entry:
ret i32 0, !dbg !19
}
-; [#uses=2]
-declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone
-
; [#uses=1]
declare i32 @printf(i8*, ...)
diff --git a/tests/cases/unannotated.ll b/tests/cases/unannotated__noasm.ll
index d87b2e54..d87b2e54 100644
--- a/tests/cases/unannotated.ll
+++ b/tests/cases/unannotated__noasm.ll
diff --git a/tests/cases/unannotated.txt b/tests/cases/unannotated__noasm.txt
index 9daeafb9..9daeafb9 100644
--- a/tests/cases/unannotated.txt
+++ b/tests/cases/unannotated__noasm.txt
diff --git a/tests/gl_ps_strides.c b/tests/gl_ps_strides.c
new file mode 100644
index 00000000..d88f5d0b
--- /dev/null
+++ b/tests/gl_ps_strides.c
@@ -0,0 +1,241 @@
+/*******************************************************************
+ * *
+ * Using SDL With OpenGL *
+ * *
+ * Tutorial by Kyle Foley (sdw) *
+ * *
+ * http://gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL *
+ * *
+ *******************************************************************/
+
+/*
+THIS WORK, INCLUDING THE SOURCE CODE, DOCUMENTATION
+AND RELATED MEDIA AND DATA, IS PLACED INTO THE PUBLIC DOMAIN.
+
+THE ORIGINAL AUTHOR IS KYLE FOLEY.
+
+THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+RESULTING FROM THE USE, MODIFICATION, OR
+REDISTRIBUTION OF THIS SOFTWARE.
+*/
+
+#if !EMSCRIPTEN
+#define USE_GLEW 1
+#endif
+
+#if USE_GLEW
+#include "GL/glew.h"
+#endif
+
+#include "SDL/SDL.h"
+#include "SDL/SDL_image.h"
+#if !USE_GLEW
+#include "SDL/SDL_opengl.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+void shaders() {
+#if USE_GLEW
+ glewInit();
+#endif
+
+ GLint ok;
+
+ const char *vertexShader = "void main(void) \n"
+ "{ \n"
+ " gl_Position = ftransform(); \n"
+ " gl_TexCoord[0] = gl_MultiTexCoord0; \n"
+ " gl_FrontColor = gl_Color; \n"
+ "} \n";
+ const char *fragmentShader = "uniform sampler2D tex0; \n"
+ "void main(void) \n"
+ "{ \n"
+ " gl_FragColor = gl_Color * texture2D(tex0, gl_TexCoord[0].xy); \n"
+ "} \n";
+
+ GLuint vs = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vs, 1, &vertexShader, NULL);
+ glCompileShader(vs);
+ glGetShaderiv(vs, GL_COMPILE_STATUS, &ok);
+ assert(ok);
+
+ GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(fs, 1, &fragmentShader, NULL);
+ glCompileShader(fs);
+ glGetShaderiv(fs, GL_COMPILE_STATUS, &ok);
+ assert(ok);
+
+ GLuint program = glCreateProgram();
+
+ glAttachShader(program, vs);
+ glAttachShader(program, fs);
+ glLinkProgram(program);
+ glGetProgramiv(program, GL_LINK_STATUS, &ok);
+ assert(ok);
+ assert(glIsProgram(program));
+ assert(!glIsProgram(0));
+ assert(!glIsProgram(program+1)); // a number that can't be a real shader
+
+ glUseProgram(program);
+
+ {
+ // Also, check getting the error log
+ const char *fakeVertexShader = "atbute ve4 blarg; ### AAA\n";
+ GLuint vs = glCreateShader(GL_VERTEX_SHADER);
+ glShaderSource(vs, 1, &fakeVertexShader, NULL);
+ glCompileShader(vs);
+ glGetShaderiv(vs, GL_COMPILE_STATUS, &ok);
+ assert(!ok);
+ GLint infoLen = 0;
+ glGetShaderiv(vs, GL_INFO_LOG_LENGTH, &infoLen);
+ assert(infoLen > 1);
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ SDL_Surface *screen;
+
+ // Slightly different SDL initialization
+ if ( SDL_Init(SDL_INIT_VIDEO) != 0 ) {
+ printf("Unable to initialize SDL: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); // *new*
+
+ screen = SDL_SetVideoMode( 640, 480, 16, SDL_OPENGL ); // *changed*
+ if ( !screen ) {
+ printf("Unable to set video mode: %s\n", SDL_GetError());
+ return 1;
+ }
+
+ // Set the OpenGL state after creating the context with SDL_SetVideoMode
+
+ glClearColor( 0, 0, 0, 0 );
+
+#if !EMSCRIPTEN
+ glEnable( GL_TEXTURE_2D ); // Need this to display a texture XXX unnecessary in OpenGL ES 2.0/WebGL
+#endif
+
+ glViewport( 0, 0, 640, 480 );
+
+ glMatrixMode( GL_PROJECTION );
+ GLfloat matrixData[] = { 2.0/640, 0, 0, 0,
+ 0, -2.0/480, 0, 0,
+ 0, 0, -1, 0,
+ -1, 1, 0, 1 };
+ glLoadMatrixf(matrixData); // test loadmatrix
+
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+
+ // Load the OpenGL texture
+
+ GLuint texture; // Texture object handle
+ SDL_Surface *surface; // Gives us the information to make the texture
+
+ if ( (surface = IMG_Load("screenshot.png")) ) {
+
+ // Check that the image's width is a power of 2
+ if ( (surface->w & (surface->w - 1)) != 0 ) {
+ printf("warning: image.bmp's width is not a power of 2\n");
+ }
+
+ // Also check if the height is a power of 2
+ if ( (surface->h & (surface->h - 1)) != 0 ) {
+ printf("warning: image.bmp's height is not a power of 2\n");
+ }
+
+ // Have OpenGL generate a texture object handle for us
+ glGenTextures( 1, &texture );
+
+ // Bind the texture object
+ glBindTexture( GL_TEXTURE_2D, texture );
+
+ // Set the texture's stretching properties
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+
+ //SDL_LockSurface(surface);
+
+ // Add some greyness
+ memset(surface->pixels, 0x66, surface->w*surface->h);
+
+ // Edit the texture object's image data using the information SDL_Surface gives us
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels );
+
+ //SDL_UnlockSurface(surface);
+ }
+ else {
+ printf("SDL could not load image.bmp: %s\n", SDL_GetError());
+ SDL_Quit();
+ return 1;
+ }
+
+ // Free the SDL_Surface only if it was successfully created
+ if ( surface ) {
+ SDL_FreeSurface( surface );
+ }
+
+ // Clear the screen before drawing
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ shaders();
+
+ // Bind the texture to which subsequent calls refer to
+ glBindTexture( GL_TEXTURE_2D, texture );
+
+ // Use clientside vertex pointers to render two items
+ GLfloat vertexData[] = { 0, 0, 10, 10, // texture2, position2
+ 1, 0, 300, 10,
+ 1, 1, 300, 128,
+ 0, 1, 10, 128,
+ 0, 0.5, 410, 10,
+ 1, 0.5, 600, 10,
+ 1, 1, 630, 200,
+ 0.5, 1, 310, 250,
+ 0, 0, 100, 300,
+ 1, 0, 300, 300,
+ 1, 1, 300, 400,
+ 0, 1, 100, 400 };
+
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_FLOAT, 4*4, &vertexData[0]);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(2, GL_FLOAT, 4*4, &vertexData[2]);
+
+ glDrawArrays(GL_QUADS, 0, 4);
+
+ glTexCoordPointer(2, GL_FLOAT, 4*4*2, &vertexData[0]); // and now with a different stride
+ glVertexPointer(2, GL_FLOAT, 4*4*2, &vertexData[2]);
+ glDrawArrays(GL_QUADS, 4, 4);
+
+ glTexCoordPointer(2, GL_FLOAT, 4*4, &vertexData[0]); // and back
+ glVertexPointer(2, GL_FLOAT, 4*4, &vertexData[2]);
+ glDrawArrays(GL_QUADS, 8, 4);
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_VERTEX_ARRAY);
+
+ SDL_GL_SwapBuffers();
+
+#if !EMSCRIPTEN
+ // Wait for 3 seconds to give us a chance to see the image
+ SDL_Delay(3000);
+#endif
+
+ // Now we can delete the OpenGL texture and close down SDL
+ glDeleteTextures( 1, &texture );
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/tests/gl_ps_strides.png b/tests/gl_ps_strides.png
new file mode 100644
index 00000000..5b49af36
--- /dev/null
+++ b/tests/gl_ps_strides.png
Binary files differ
diff --git a/tests/openal_playback.cpp b/tests/openal_playback.cpp
new file mode 100644
index 00000000..13d619e6
--- /dev/null
+++ b/tests/openal_playback.cpp
@@ -0,0 +1,115 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <AL/al.h>
+#include <AL/alc.h>
+#include <assert.h>
+#include <emscripten.h>
+
+void playSource(void* arg)
+{
+ ALuint source = reinterpret_cast<ALuint>(arg);
+ ALint state;
+ alGetSourcei(source, AL_SOURCE_STATE, &state);
+ assert(state == AL_PLAYING);
+ alSourcePause(source);
+ alGetSourcei(source, AL_SOURCE_STATE, &state);
+ assert(state == AL_PAUSED);
+ alSourcePlay(source);
+ alGetSourcei(source, AL_SOURCE_STATE, &state);
+ assert(state == AL_PLAYING);
+ alSourceStop(source);
+ alGetSourcei(source, AL_SOURCE_STATE, &state);
+ assert(state == AL_STOPPED);
+
+ int result = 1;
+ REPORT_RESULT();
+}
+
+int main() {
+ ALCdevice* device = alcOpenDevice(NULL);
+ ALCcontext* context = alcCreateContext(device, NULL);
+ alcMakeContextCurrent(context);
+
+ 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};
+
+ alListenerfv(AL_POSITION, listenerPos);
+ alListenerfv(AL_VELOCITY, listenerVel);
+ alListenerfv(AL_ORIENTATION, listenerOri);
+
+ ALuint buffers[1];
+
+ alGenBuffers(1, buffers);
+
+ FILE* source = fopen("audio.wav", "rb");
+ fseek(source, 0, SEEK_END);
+ int size = ftell(source);
+ fseek(source, 0, SEEK_SET);
+
+ unsigned char* buffer = (unsigned char*) malloc(size);
+ fread(buffer, size, 1, source);
+
+ unsigned offset = 12; // ignore the RIFF header
+ offset += 8; // ignore the fmt header
+ offset += 2; // ignore the format type
+
+ unsigned channels = buffer[offset + 1] << 8;
+ channels |= buffer[offset];
+ offset += 2;
+ printf("Channels: %u\n", channels);
+
+ unsigned frequency = buffer[offset + 3] << 24;
+ frequency |= buffer[offset + 2] << 16;
+ frequency |= buffer[offset + 1] << 8;
+ frequency |= buffer[offset];
+ offset += 4;
+ printf("Frequency: %u\n", frequency);
+
+ offset += 6; // ignore block size and bps
+
+ unsigned bits = buffer[offset + 1] << 8;
+ bits |= buffer[offset];
+ offset += 2;
+ printf("Bits: %u\n", bits);
+
+ ALenum format = 0;
+ if(bits == 8)
+ {
+ if(channels == 1)
+ format = AL_FORMAT_MONO8;
+ else if(channels == 2)
+ format = AL_FORMAT_STEREO8;
+ }
+ else if(bits == 16)
+ {
+ if(channels == 1)
+ format = AL_FORMAT_MONO16;
+ else if(channels == 2)
+ format = AL_FORMAT_STEREO16;
+ }
+
+ offset += 8; // ignore the data chunk
+
+ printf("Start offset: %d\n", offset);
+
+ alBufferData(buffers[0], format, &buffer[offset], size - offset, frequency);
+
+ ALuint sources[1];
+ alGenSources(1, sources);
+
+ alSourcei(sources[0], AL_BUFFER, buffers[0]);
+
+ ALint state;
+ alGetSourcei(sources[0], AL_SOURCE_STATE, &state);
+ assert(state == AL_INITIAL);
+
+ alSourcePlay(sources[0]);
+
+ alGetSourcei(sources[0], AL_SOURCE_STATE, &state);
+ assert(state == AL_PLAYING);
+
+ emscripten_async_call(playSource, reinterpret_cast<void*>(sources[0]), 700);
+
+ return 0;
+}
diff --git a/tests/runner.py b/tests/runner.py
index 99c536e3..529dcc48 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -829,11 +829,14 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv) and 'brows
int add_low = add;
int add_high = add >> 32;
printf("*%lld,%lld,%u,%u*\n", mul, add, add_low, add_high);
+ int64 x = sec + (usec << 25);
+ x >>= argc*3;
+ printf("*%llu*\n", x);
return 0;
}
'''
- self.do_run(src, '*1329409676000000,1329412005509675,3663280683,309527*\n')
+ self.do_run(src, '*1329409676000000,1329412005509675,3663280683,309527*\n*9770671914067409*\n')
def test_i64_cmp(self):
if Settings.USE_TYPED_ARRAYS != 2: return self.skip('full i64 stuff only in ta2')
@@ -1003,12 +1006,6 @@ m_divisor is 1091269979
'''
self.do_run(src, open(path_from_root('tests', 'i64_precise.txt')).read())
- # Verify that without precision, we do not include the precision code
- Settings.PRECISE_I64_MATH = 0
- self.do_run(src, 'unsigned')
- code = open(os.path.join(self.get_dir(), 'src.cpp.o.js')).read()
- assert 'goog.math.Long' not in code, 'i64 precise math should not have been included if not asked for'
-
# Verify that even if we ask for precision, if it is not needed it is not included
Settings.PRECISE_I64_MATH = 1
src = '''
@@ -1890,13 +1887,34 @@ Succeeded!
printf("%s\\n", strdup_val);
free(strdup_val);
+ {
+ char *one = "one 1 ONE !";
+ char *two = "two 2 TWO ?";
+ char three[1024];
+ memset(three, '.', 1024);
+ three[50] = 0;
+ strncpy(three + argc, one + (argc/2), argc+1);
+ strncpy(three + argc*3, two + (argc/3), argc+2);
+ printf("waka %s\\n", three);
+ }
+
+ {
+ char *one = "string number one top notch";
+ char *two = "fa la sa ho fi FI FO FUM WHEN WHERE WHY HOW WHO";
+ char three[1000];
+ strcpy(three, &one[argc*2]);
+ strcat(three, &two[argc*3]);
+ printf("cat |%s|\\n", three);
+ }
+
return 0;
}
'''
for named in (0, 1):
print named
Settings.NAMED_GLOBALS = named
- self.do_run(src, '4:10,177,543,def\n4\nwowie\ntoo\n76\n5\n(null)\n/* a comment */\n// another\ntest\n', ['wowie', 'too', '74'])
+ self.do_run(src, '''4:10,177,543,def\n4\nwowie\ntoo\n76\n5\n(null)\n/* a comment */\n// another\ntest\nwaka ....e 1 O...wo 2 T................................
+cat |umber one top notchfi FI FO FUM WHEN WHERE WHY HOW WHO|''', ['wowie', 'too', '74'])
if self.emcc_args == []:
gen = open(self.in_dir('src.cpp.o.js')).read()
assert ('var __str1;' in gen) == named
@@ -4117,10 +4135,12 @@ The current type of b is: 9
#define CONSTRLEN 32
+ char * (*func)(char *, const char *) = NULL;
+
void conoutfv(const char *fmt)
{
static char buf[CONSTRLEN];
- strcpy(buf, fmt);
+ func(buf, fmt); // call by function pointer to make sure we test strcpy here
puts(buf);
}
@@ -4142,6 +4162,7 @@ The current type of b is: 9
};
int main() {
+ func = &strcpy;
conoutfv("*staticccz*");
printf("*%.2f,%.2f,%.2f*\\n", S::getIdentity().x, S::getIdentity().y, S::getIdentity().z);
return 0;
@@ -5232,6 +5253,62 @@ at function.:blag
'''
self.do_run(src, re.sub('(^|\n)\s+', '\\1', expected))
+ def test_vsnprintf(self):
+ if self.emcc_args is None: return self.skip('needs i64 math')
+
+ src = r'''
+ #include <stdio.h>
+ #include <stdarg.h>
+ #include <stdint.h>
+
+ void printy(const char *f, ...)
+ {
+ char buffer[256];
+ va_list args;
+ va_start(args, f);
+ vsnprintf(buffer, 256, f, args);
+ puts(buffer);
+ va_end(args);
+ }
+
+ int main(int argc, char **argv) {
+ int64_t x = argc - 1;
+ int64_t y = argc - 1 + 0x400000;
+ if (x % 3 == 2) y *= 2;
+
+ printy("0x%llx_0x%llx", x, y);
+ printy("0x%llx_0x%llx", x, x);
+ printy("0x%llx_0x%llx", y, x);
+ printy("0x%llx_0x%llx", y, y);
+
+ {
+ uint64_t A = 0x800000;
+ uint64_t B = 0x800000000000ULL;
+ printy("0x%llx_0x%llx", A, B);
+ }
+ {
+ uint64_t A = 0x800;
+ uint64_t B = 0x12340000000000ULL;
+ printy("0x%llx_0x%llx", A, B);
+ }
+ {
+ uint64_t A = 0x000009182746756;
+ uint64_t B = 0x192837465631ACBDULL;
+ printy("0x%llx_0x%llx", A, B);
+ }
+
+ return 0;
+ }
+ '''
+ self.do_run(src, '''0x0_0x400000
+0x0_0x0
+0x400000_0x0
+0x400000_0x400000
+0x800000_0x800000000000
+0x800_0x12340000000000
+0x9182746756_0x192837465631acbd
+''')
+
def test_printf_more(self):
src = r'''
#include <stdio.h>
@@ -6497,6 +6574,90 @@ PORT: 3979
expected = open(path_from_root('tests', 'ctype', 'output.txt'), 'r').read()
self.do_run(src, expected)
+ def test_strcasecmp(self):
+ src = r'''
+ #include <stdio.h>
+ #include <strings.h>
+ int sign(int x) {
+ if (x < 0) return -1;
+ if (x > 0) return 1;
+ return 0;
+ }
+ int main() {
+ printf("*\n");
+
+ printf("%d\n", sign(strcasecmp("hello", "hello")));
+ printf("%d\n", sign(strcasecmp("hello1", "hello")));
+ printf("%d\n", sign(strcasecmp("hello", "hello1")));
+ printf("%d\n", sign(strcasecmp("hello1", "hello1")));
+ printf("%d\n", sign(strcasecmp("iello", "hello")));
+ printf("%d\n", sign(strcasecmp("hello", "iello")));
+ printf("%d\n", sign(strcasecmp("A", "hello")));
+ printf("%d\n", sign(strcasecmp("Z", "hello")));
+ printf("%d\n", sign(strcasecmp("a", "hello")));
+ printf("%d\n", sign(strcasecmp("z", "hello")));
+ printf("%d\n", sign(strcasecmp("hello", "a")));
+ printf("%d\n", sign(strcasecmp("hello", "z")));
+
+ printf("%d\n", sign(strcasecmp("Hello", "hello")));
+ printf("%d\n", sign(strcasecmp("Hello1", "hello")));
+ printf("%d\n", sign(strcasecmp("Hello", "hello1")));
+ printf("%d\n", sign(strcasecmp("Hello1", "hello1")));
+ printf("%d\n", sign(strcasecmp("Iello", "hello")));
+ printf("%d\n", sign(strcasecmp("Hello", "iello")));
+ printf("%d\n", sign(strcasecmp("A", "hello")));
+ printf("%d\n", sign(strcasecmp("Z", "hello")));
+ printf("%d\n", sign(strcasecmp("a", "hello")));
+ printf("%d\n", sign(strcasecmp("z", "hello")));
+ printf("%d\n", sign(strcasecmp("Hello", "a")));
+ printf("%d\n", sign(strcasecmp("Hello", "z")));
+
+ printf("%d\n", sign(strcasecmp("hello", "Hello")));
+ printf("%d\n", sign(strcasecmp("hello1", "Hello")));
+ printf("%d\n", sign(strcasecmp("hello", "Hello1")));
+ printf("%d\n", sign(strcasecmp("hello1", "Hello1")));
+ printf("%d\n", sign(strcasecmp("iello", "Hello")));
+ printf("%d\n", sign(strcasecmp("hello", "Iello")));
+ printf("%d\n", sign(strcasecmp("A", "Hello")));
+ printf("%d\n", sign(strcasecmp("Z", "Hello")));
+ printf("%d\n", sign(strcasecmp("a", "Hello")));
+ printf("%d\n", sign(strcasecmp("z", "Hello")));
+ printf("%d\n", sign(strcasecmp("hello", "a")));
+ printf("%d\n", sign(strcasecmp("hello", "z")));
+
+ printf("%d\n", sign(strcasecmp("Hello", "Hello")));
+ printf("%d\n", sign(strcasecmp("Hello1", "Hello")));
+ printf("%d\n", sign(strcasecmp("Hello", "Hello1")));
+ printf("%d\n", sign(strcasecmp("Hello1", "Hello1")));
+ printf("%d\n", sign(strcasecmp("Iello", "Hello")));
+ printf("%d\n", sign(strcasecmp("Hello", "Iello")));
+ printf("%d\n", sign(strcasecmp("A", "Hello")));
+ printf("%d\n", sign(strcasecmp("Z", "Hello")));
+ printf("%d\n", sign(strcasecmp("a", "Hello")));
+ printf("%d\n", sign(strcasecmp("z", "Hello")));
+ printf("%d\n", sign(strcasecmp("Hello", "a")));
+ printf("%d\n", sign(strcasecmp("Hello", "z")));
+
+ printf("%d\n", sign(strncasecmp("hello", "hello", 3)));
+ printf("%d\n", sign(strncasecmp("hello1", "hello", 3)));
+ printf("%d\n", sign(strncasecmp("hello", "hello1", 3)));
+ printf("%d\n", sign(strncasecmp("hello1", "hello1", 3)));
+ printf("%d\n", sign(strncasecmp("iello", "hello", 3)));
+ printf("%d\n", sign(strncasecmp("hello", "iello", 3)));
+ printf("%d\n", sign(strncasecmp("A", "hello", 3)));
+ printf("%d\n", sign(strncasecmp("Z", "hello", 3)));
+ printf("%d\n", sign(strncasecmp("a", "hello", 3)));
+ printf("%d\n", sign(strncasecmp("z", "hello", 3)));
+ printf("%d\n", sign(strncasecmp("hello", "a", 3)));
+ printf("%d\n", sign(strncasecmp("hello", "z", 3)));
+
+ printf("*\n");
+
+ return 0;
+ }
+ '''
+ self.do_run(src, '''*\n0\n1\n-1\n0\n1\n-1\n-1\n1\n-1\n1\n1\n-1\n0\n1\n-1\n0\n1\n-1\n-1\n1\n-1\n1\n1\n-1\n0\n1\n-1\n0\n1\n-1\n-1\n1\n-1\n1\n1\n-1\n0\n1\n-1\n0\n1\n-1\n-1\n1\n-1\n1\n1\n-1\n0\n0\n0\n0\n1\n-1\n-1\n1\n-1\n1\n1\n-1\n*\n''')
+
def test_atomic(self):
src = '''
#include <stdio.h>
@@ -7202,6 +7363,8 @@ def process(filename):
if self.emcc_args is None: return self.skip('requires emcc')
if Building.LLVM_OPTS and self.emcc_args is None: Settings.SAFE_HEAP = 0 # Optimizations make it so we do not have debug info on the line we need to ignore
+ Settings.DEAD_FUNCTIONS = ['__ZSt9terminatev']
+
# Note: this is also a good test of per-file and per-line changes (since we have multiple files, and correct specific lines)
if Settings.SAFE_HEAP:
# Ignore bitfield warnings
@@ -7782,20 +7945,32 @@ def process(filename):
self.emcc_args = map(lambda x: 'ASM_JS=1' if x == 'ASM_JS=0' else x, self.emcc_args)
shutil.move(self.in_dir('src.cpp.o.js'), self.in_dir('pgo.js'))
- pgo_output = run_js(self.in_dir('pgo.js'))
+ pgo_output = run_js(self.in_dir('pgo.js')).split('\n')[1]
+ open('pgo_data', 'w').write(pgo_output)
+
+ # with response file
- open('pgo_data', 'w').write(pgo_output.split('\n')[1])
self.emcc_args += ['@pgo_data']
self.do_run(src, output)
+ self.emcc_args.pop()
shutil.move(self.in_dir('src.cpp.o.js'), self.in_dir('pgoed.js'))
before = len(open('normal.js').read())
after = len(open('pgoed.js').read())
assert after < 0.66 * before, [before, after] # expect a big size reduction
+ # with response in settings element itself
+
+ open('dead_funcs', 'w').write(pgo_output[pgo_output.find('['):-1])
+ self.emcc_args += ['-s', 'DEAD_FUNCTIONS=@' + self.in_dir('dead_funcs')]
+ self.do_run(src, output)
+ shutil.move(self.in_dir('src.cpp.o.js'), self.in_dir('pgoed2.js'))
+ assert open('pgoed.js').read() == open('pgoed2.js').read()
+
def test_scriptaclass(self):
if self.emcc_args is None: return self.skip('requires emcc')
- if Settings.ASM_JS: return self.skip('asm does not bindings generator yet')
+
+ Settings.EXPORT_BINDINGS = 1
header_filename = os.path.join(self.get_dir(), 'header.h')
header = '''
@@ -7970,6 +8145,7 @@ def process(filename):
Module.Child2.prototype.runVirtualFunc(c2);
c2.virtualFunc2();
+''' + ('' if Settings.ASM_JS else '''
// extend the class from JS
var c3 = new Module.Child2;
Module.customizeVTable(c3, [{
@@ -7990,6 +8166,7 @@ def process(filename):
c2.virtualFunc(); // original should remain the same
Module.Child2.prototype.runVirtualFunc(c2);
c2.virtualFunc2();
+''') + '''
Module.print('*ok*');
\'\'\'
@@ -8028,7 +8205,7 @@ Child2:9
*static*
*virtualf*
*virtualf*
-*virtualf2*
+*virtualf2*''' + ('' if Settings.ASM_JS else '''
Parent:9
Child2:9
*js virtualf replacement*
@@ -8036,13 +8213,14 @@ Child2:9
*js virtualf2 replacement*
*virtualf*
*virtualf*
-*virtualf2*
+*virtualf2*''') + '''
*ok*
''', post_build=[post2, post3])
def test_scriptaclass_2(self):
if self.emcc_args is None: return self.skip('requires emcc')
- if Settings.ASM_JS: return self.skip('asm does not bindings generator yet')
+
+ Settings.EXPORT_BINDINGS = 1
header_filename = os.path.join(self.get_dir(), 'header.h')
header = '''
@@ -9196,7 +9374,7 @@ f.close()
filename = self.in_dir('src.cpp')
open(filename, 'w').write(src)
out, err = Popen([PYTHON, EMCC, filename, '-s', 'ASM_JS=1', '-O2'], stderr=PIPE).communicate()
- assert 'Warning: Unresolved symbol' in err, 'always warn on undefs in asm, since it breaks validation'
+ assert 'Unresolved symbol' in err, 'always warn on undefs in asm, since it breaks validation: ' + err
def test_redundant_link(self):
lib = "int mult() { return 1; }"
@@ -9841,11 +10019,11 @@ f.close()
try:
os.environ['EMCC_DEBUG'] = '1'
for asm, linkable, chunks, js_chunks in [
- (0, 0, 3, 2), (0, 1, 3, 4),
- (1, 0, 3, 2), (1, 1, 3, 4)
+ (0, 0, 3, 2), (0, 1, 4, 4),
+ (1, 0, 3, 2), (1, 1, 4, 5)
]:
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], 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, '-s', 'UNRESOLVED_AS_DEAD=1'], stdout=PIPE, stderr=PIPE).communicate()
assert 'phase 2 working on %d chunks' %chunks in err, err
assert 'splitting up js optimization into %d chunks' % js_chunks in err, err
finally:
@@ -10892,6 +11070,13 @@ elif 'browser' in str(sys.argv):
Popen([PYTHON, EMCC, path_from_root('tests', 'sdl_fog_linear.c'), '-o', 'something.html', '--pre-js', 'reftest.js', '--preload-file', 'screenshot.png', '-s', 'GL_TESTING=1']).communicate()
self.run_browser('something.html', 'You should see an image with fog.', '/report_result?0')
+ def test_openal_playback(self):
+ shutil.copyfile(path_from_root('tests', 'sounds', 'audio.wav'), os.path.join(self.get_dir(), 'audio.wav'))
+ open(os.path.join(self.get_dir(), 'openal_playback.cpp'), 'w').write(self.with_report_result(open(path_from_root('tests', 'openal_playback.cpp')).read()))
+
+ Popen([PYTHON, EMCC, '-O2', os.path.join(self.get_dir(), 'openal_playback.cpp'), '--preload-file', 'audio.wav', '-o', 'page.html']).communicate()
+ self.run_browser('page.html', '', '/report_result?1')
+
def test_worker(self):
# Test running in a web worker
output = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_worker.cpp'), '-o', 'worker.js'], stdout=PIPE, stderr=PIPE).communicate()
@@ -11178,6 +11363,10 @@ elif 'browser' in str(sys.argv):
shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png'))
self.btest('gl_ps_workaround2.c', reference='gl_ps.png', args=['--preload-file', 'screenshot.png'])
+ def test_gl_ps_strides(self):
+ shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png'))
+ self.btest('gl_ps_strides.c', reference='gl_ps_strides.png', args=['--preload-file', 'screenshot.png'])
+
def test_matrix_identity(self):
self.btest('gl_matrix_identity.c', expected=['-1882984448', '460451840'])
@@ -11639,7 +11828,8 @@ elif 'benchmark' in str(sys.argv):
start = time.time()
js_output = run_js(final_filename, engine=JS_ENGINE, args=args, stderr=PIPE, full_output=True)
if i == 0 and 'Successfully compiled asm.js code' in js_output:
- print "[%s was asm.js'ified]" % name
+ if 'asm.js link error' not in js_output:
+ print "[%s was asm.js'ified]" % name
curr = time.time()-start
times.append(curr)
total_times[tests_done] += curr
@@ -11907,7 +12097,8 @@ ok.
native=True)
emcc_args = js_lib + ['-I' + path_from_root('tests', 'bullet', 'src'),
- '-I' + path_from_root('tests', 'bullet', 'Demos', 'Benchmarks')]
+ '-I' + path_from_root('tests', 'bullet', 'Demos', 'Benchmarks'),
+ '-s', 'DEAD_FUNCTIONS=["__ZSt9terminatev"]']
native_args = native_lib + ['-I' + path_from_root('tests', 'bullet', 'src'),
'-I' + path_from_root('tests', 'bullet', 'Demos', 'Benchmarks')]
@@ -12306,9 +12497,9 @@ fi
assert ('bootstrapping relooper succeeded' in output) == (i == 2), 'only bootstrap on first O2: ' + output
assert os.path.exists(RELOOPER) == (i >= 2), 'have relooper on O2: ' + output
src = open('a.out.js').read()
- main = src.split('function _main() {')[1].split('\n}\n')[0]
- assert ('while (1) {' in main) == (i >= 2), 'reloop code on O2: ' + src
- assert ('switch' not in main) == (i >= 2), 'reloop code on O2: ' + src
+ main = src.split('function _main()')[1].split('\n}\n')[0]
+ assert ('while (1) {' in main or 'while(1){' in main) == (i >= 2), 'reloop code on O2: ' + main
+ assert ('switch' not in main) == (i >= 2), 'reloop code on O2: ' + main
def test_jcache(self):
PRE_LOAD_MSG = 'loading pre from jcache'
diff --git a/tests/sdl_audio_mix.c b/tests/sdl_audio_mix.c
index e3431e0c..f72f9c43 100644
--- a/tests/sdl_audio_mix.c
+++ b/tests/sdl_audio_mix.c
@@ -49,6 +49,8 @@ void one_iter() {
case 120:
Mix_HaltChannel(soundChannel);
Mix_HaltMusic();
+ int result = 1;
+ REPORT_RESULT();
break;
};
}
diff --git a/tests/sounds/audio.wav b/tests/sounds/audio.wav
new file mode 100644
index 00000000..dd1b8057
--- /dev/null
+++ b/tests/sounds/audio.wav
Binary files differ
diff --git a/tools/bindings_generator.py b/tools/bindings_generator.py
index d2c165a2..d610ab54 100755
--- a/tools/bindings_generator.py
+++ b/tools/bindings_generator.py
@@ -62,6 +62,10 @@ Notes:
string on the *stack*. The C string will live for the current
function call. If you need it for longer, you need to create a copy
in your C++ code.
+
+ * You should compile with -s EXPORT_BINDINGS=1 in order for the
+ autogenerated bindings functions to be exported. This is necessary
+ when compiling in asm.js mode.
'''
import os, sys, glob, re
@@ -464,6 +468,7 @@ Module['getClass'] = getClass;
function customizeVTable(object, replacementPairs) {
// Does not handle multiple inheritance
+ // Does not work with asm.js
// Find out vtable size
var vTable = getValue(object.ptr, 'void*');
diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py
index 87fd0660..1f1c1354 100644
--- a/tools/js_optimizer.py
+++ b/tools/js_optimizer.py
@@ -154,7 +154,7 @@ def run_on_js(filename, passes, js_engine, jcache):
class Finals:
buf = []
def process(line):
- if len(line) > 0 and (line.startswith('Module[') or line.endswith('["X"]=1;')):
+ if len(line) > 0 and (line.startswith(('Module[', 'if (globalScope)')) or line.endswith('["X"]=1;')):
Finals.buf.append(line)
return False
return True
diff --git a/tools/settings_template_readonly.py b/tools/settings_template_readonly.py
index f689e205..7ab89b48 100644
--- a/tools/settings_template_readonly.py
+++ b/tools/settings_template_readonly.py
@@ -11,8 +11,7 @@ PYTHON = os.path.expanduser(os.getenv('PYTHON') or '{{{ PYTHON }}}') # executabl
# See below for notes on which JS engine(s) you need
NODE_JS = os.path.expanduser(os.getenv('NODE') or '{{{ NODE }}}') # executable
-SPIDERMONKEY_ENGINE = [
- os.path.expanduser(os.getenv('SPIDERMONKEY') or 'js'), '-m', '-n'] # executable
+SPIDERMONKEY_ENGINE = [os.path.expanduser(os.getenv('SPIDERMONKEY') or 'js')] # executable
V8_ENGINE = os.path.expanduser(os.getenv('V8') or 'd8') # executable
JAVA = 'java' # executable
diff --git a/tools/shared.py b/tools/shared.py
index 34ed9b3d..3d0f90b9 100644
--- a/tools/shared.py
+++ b/tools/shared.py
@@ -181,7 +181,7 @@ def check_node_version():
# 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.3.0'
+EMSCRIPTEN_VERSION = '1.3.1'
def check_sanity(force=False):
try:
@@ -1141,6 +1141,9 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e
print >> sys.stderr, 'bootstrapping relooper...'
os.chdir(path_from_root('src'))
+ emcc_debug = os.environ.get('EMCC_DEBUG')
+ if emcc_debug: del os.environ['EMCC_DEBUG']
+
def make(opt_level):
raw = relooper + '.raw.js'
Building.emcc(os.path.join('relooper', 'Relooper.cpp'), ['-I' + os.path.join('relooper'), '--post-js',
@@ -1169,6 +1172,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e
ok = True
finally:
os.chdir(curr)
+ if emcc_debug: os.environ['EMCC_DEBUG'] = emcc_debug
if not ok:
print >> sys.stderr, 'bootstrapping relooper failed. You may need to manually create relooper.js by compiling it, see src/relooper/emscripten'
1/0