summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS4
-rwxr-xr-xemcc21
-rw-r--r--src/compiler.js1
-rw-r--r--src/intertyper.js147
-rw-r--r--src/jsifier.js5
-rw-r--r--src/library_fs.js34
-rw-r--r--src/library_gl.js6
-rw-r--r--src/library_glut.js37
-rw-r--r--src/library_sdl.js2
-rw-r--r--src/preamble.js25
-rw-r--r--src/proxyClient.js10
-rw-r--r--tests/cases/ctors_cast.ll49
-rw-r--r--tests/cases/ctors_cast.txt3
-rw-r--r--tests/glut_wheelevents.c68
-rw-r--r--tests/sdl_rotozoom.c2
-rw-r--r--tests/sdl_rotozoom.pngbin431168 -> 711242 bytes
-rw-r--r--tests/test_browser.py5
-rw-r--r--tests/test_core.py10
-rw-r--r--tests/test_other.py27
-rw-r--r--tools/autodebugger.py4
20 files changed, 347 insertions, 113 deletions
diff --git a/AUTHORS b/AUTHORS
index 22eb7d67..9db6c77b 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -99,4 +99,8 @@ a license to everyone to use it as detailed in LICENSE.)
* Tobias Vrinssen <tobias@vrinssen.de>
* Patrick R. Martin <patrick.martin.r@gmail.com>
* Richard Quirk <richard.quirk@gmail.com>
+* Marcos Scriven <marcos@scriven.org>
+* Antoine Lambert <antoine.lambert33@gmail.com>
+* Daniel Aquino <mr.danielaquino@gmail.com>
* Remi Papillie <remi.papillie@gmail.com>
+
diff --git a/emcc b/emcc
index f8d7319e..cfec5534 100755
--- a/emcc
+++ b/emcc
@@ -127,7 +127,11 @@ Most normal gcc/g++ options will work, for example:
--version Display compiler version information
Options that are modified or new in %s include:
- -O0 No optimizations (default)
+
+ -O0 No optimizations (default). This is the recommended
+ setting for starting to port a project, as it
+ includes various assertions.
+
-O1 Simple optimizations, including asm.js, LLVM -O1
optimizations, relooping, and no runtime assertions
or C++ exception catching (to re-enable
@@ -136,11 +140,20 @@ Options that are modified or new in %s include:
-s ALIASING_FUNCTION_POINTERS=1
- (For details on the affects of different
+ This is the recommended setting when you want a
+ reasonably optimized build that is generated as
+ quickly as possible (it is much faster than -O2).
+
+ (Note: for details on the affects of different
opt levels, see apply_opt_level() in
tools/shared.py and also src/settings.js.)
+
-O2 As -O1, plus various js-level optimizations and
- LLVM -O3 optimizations
+ LLVM -O3 optimizations. This is the recommended
+ setting for a release build: slower compilation
+ time in return for the smallest and fastest
+ output.
+
-O3 As -O2, plus dangerous optimizations that may
break the generated code! This adds
@@ -1231,7 +1244,7 @@ try:
file_suffix = filename_type_suffix(input_file)
if file_suffix.endswith(SOURCE_SUFFIXES):
temp_file = temp_files[i]
- logging.debug('optimizing %s with -O%d' % (input_file, llvm_opts))
+ logging.debug('optimizing %s with -O%s' % (input_file, llvm_opts))
shared.Building.llvm_opt(temp_file, llvm_opts)
# If we were just asked to generate bitcode, stop there
diff --git a/src/compiler.js b/src/compiler.js
index d490f454..ac1b0ec8 100644
--- a/src/compiler.js
+++ b/src/compiler.js
@@ -318,4 +318,5 @@ if (ll_file) {
//var M = keys(tokenCacheMisses).map(function(m) { return [m, misses[m]] }).sort(function(a, b) { return a[1] - b[1] });
//printErr(dump(M.slice(M.length-10)));
+//printErr('hits: ' + hits);
diff --git a/src/intertyper.js b/src/intertyper.js
index 781c8187..9414a1d4 100644
--- a/src/intertyper.js
+++ b/src/intertyper.js
@@ -6,12 +6,12 @@
var fastPaths = 0, slowPaths = 0;
var tokenCache = {};
-['=', 'i32', 'label', ';', '4', '0', '1', '2', '255', 'align', 'i8*', 'i8', 'i16', 'getelementptr', 'inbounds', 'unnamed_addr', 'x', 'load', 'preds', 'br', 'i32*', 'i1', 'store', '<label>', 'constant', 'c', 'private', 'null', 'internal', 'to', 'bitcast', 'define', 'nounwind', 'nocapture', '%this', 'call', '...'].forEach(function(text) { tokenCache[text] = { text: text } });
+[',', 'i32', 'label', ';', '4', '0', '1', '2', '255', 'align', 'i8*', 'i8', 'i16', 'getelementptr', 'inbounds', 'unnamed_addr', 'x', 'load', 'preds', 'br', 'i32*', 'i1', 'store', '<label>', 'constant', 'c', 'private', 'null', 'internal', 'to', 'bitcast', 'define', 'nounwind', 'nocapture', '%this', 'call', '...'].forEach(function(text) { tokenCache[text] = { text: text } });
//var tokenCacheMisses = {};
// Line tokenizer
-function tokenize(text, lineNum) {
+function tokenize(text, lineNum, indent) {
var tokens = [];
var quotes = 0;
var lastToken = null;
@@ -63,12 +63,7 @@ function tokenize(text, lineNum) {
tokens.splice(openBrace, tokens.length-openBrace+1);
tokens.push(token);
token.type = '{';
- token.text = '{ ' + token.text + ' }';
- var pointingLevelsToAdd = pointingLevels(text) - pointingLevels(token.text);
- while (pointingLevelsToAdd > 0) {
- token.text += '*';
- pointingLevelsToAdd--;
- }
+ token.text = '{ ' + token.text + ' ' + text;
lastToken = token;
} else {
tokens.push(token);
@@ -82,78 +77,67 @@ function tokenize(text, lineNum) {
segments.pop();
var len = segments.length;
var i = -1;
- var curr = '';
+ var start = 0;
var segment, letter;
for (var s = 0; s < len; s++) {
segment = segments[s];
i += segment.length + 1;
letter = lineText[i];
- curr += segment;
switch (letter) {
case ' ':
if (totalEnclosing == 0 && quotes == 0) {
- makeToken(curr);
- curr = '';
+ makeToken(lineText.substring(start, i));
+ start = i+1;
} else {
- curr += ' ';
}
break;
case '"':
if (totalEnclosing == 0) {
if (quotes == 0) {
- if (curr == '@' || curr == '%') {
- curr += '"';
+ if (start === i-1 && (lineText[start] == '@' || lineText[start] == '%')) {
} else {
- makeToken(curr);
- curr = '"';
+ makeToken(lineText.substring(start, i));
+ start = i;
}
} else {
- makeToken(curr + '"');
- curr = '';
+ makeToken(lineText.substring(start, i+1));
+ start = i+1;
}
- } else {
- curr += '"';
}
quotes = 1-quotes;
break;
case ',':
if (totalEnclosing == 0 && quotes == 0) {
- makeToken(curr);
- curr = '';
- tokens.push({ text: ',' });
- } else {
- curr += ',';
+ makeToken(lineText.substring(start, i));
+ start = i+1;
+ tokens.push(tokenCache[',']);
}
break;
default:
assert(letter in enclosers);
if (quotes) {
- curr += letter;
break;
}
if (letter in ENCLOSER_STARTERS) {
if (totalEnclosing == 0) {
- makeToken(curr);
- curr = '';
+ makeToken(lineText.substring(start, i));
+ start = i;
}
- curr += letter;
enclosers[letter]++;
totalEnclosing++;
} else {
enclosers[enclosers[letter]]--;
totalEnclosing--;
if (totalEnclosing == 0) {
- makeToken(curr + letter);
- curr = '';
- } else {
- curr += letter;
+ makeToken(lineText.substring(start, i+1));
+ start = i+1;
}
}
}
}
var newItem = {
tokens: tokens,
- indent: lineText.search(/[^ ]/),
+ indent: indent || lineText.search(/[^ ]/),
lineNum: lineNum || 0
};
return newItem;
@@ -291,10 +275,6 @@ function intertyper(lines, sidePass, baseLineNums) {
function triager(item) {
assert(!item.intertype);
- if (item.indent == 2 && (eq = findTokenText(item, '=')) >= 0) {
- item.assignTo = toNiceIdent(combineTokens(item.tokens.slice(0, eq)).text);
- item.tokens = item.tokens.slice(eq+1);
- }
var token0Text = item.tokens[0].text;
var token1Text = item.tokens[1] ? item.tokens[1].text : null;
var tokensLength = item.tokens.length;
@@ -345,7 +325,7 @@ function intertyper(lines, sidePass, baseLineNums) {
return labelHandler(item);
if (tokensLength >= 4 && token0Text == 'declare')
return externalHandler(item);
- if (tokensLength >= 3 && token1Text == '=')
+ if (item.assignTo)
return globalHandler(item);
if (tokensLength >= 4 && token0Text == 'define' &&
item.tokens.slice(-1)[0].text == '{')
@@ -458,15 +438,15 @@ function intertyper(lines, sidePass, baseLineNums) {
}
}
- cleanOutTokens(LLVM.VISIBILITIES, item.tokens, 2);
- if (item.tokens[2].text == 'alias') {
- cleanOutTokens(LLVM.LINKAGES, item.tokens, 3);
- cleanOutTokens(LLVM.VISIBILITIES, item.tokens, 3);
+ cleanOutTokens(LLVM.VISIBILITIES, item.tokens, 0);
+ if (item.tokens[0].text == 'alias') {
+ cleanOutTokens(LLVM.LINKAGES, item.tokens, 1);
+ cleanOutTokens(LLVM.VISIBILITIES, item.tokens, 1);
var last = getTokenIndexByText(item.tokens, ';');
var ret = {
intertype: 'alias',
- ident: toNiceIdent(item.tokens[0].text),
- value: parseLLVMSegment(item.tokens.slice(3, last)),
+ ident: item.assignTo,
+ value: parseLLVMSegment(item.tokens.slice(1, last)),
lineNum: item.lineNum
};
ret.type = ret.value.type;
@@ -476,18 +456,18 @@ function intertyper(lines, sidePass, baseLineNums) {
}
return ret;
}
- if (item.tokens[2].text == 'type') {
+ if (item.tokens[0].text == 'type') {
var fields = [];
var packed = false;
- if (Runtime.isNumberType(item.tokens[3].text)) {
+ if (Runtime.isNumberType(item.tokens[1].text)) {
// Clang sometimes has |= i32| instead of |= { i32 }|
- fields = [item.tokens[3].text];
- } else if (item.tokens[3].text != 'opaque') {
- if (item.tokens[3].type == '<') {
+ fields = [item.tokens[1].text];
+ } else if (item.tokens[1].text != 'opaque') {
+ if (item.tokens[1].type == '<') {
packed = true;
- item.tokens[3] = item.tokens[3].item.tokens[0];
+ item.tokens[1] = item.tokens[1].item.tokens[0];
}
- var subTokens = item.tokens[3].tokens;
+ var subTokens = item.tokens[1].tokens;
if (subTokens) {
subTokens.push({text:','});
while (subTokens[0]) {
@@ -500,38 +480,40 @@ function intertyper(lines, sidePass, baseLineNums) {
}
return {
intertype: 'type',
- name_: item.tokens[0].text,
+ name_: item.assignTo,
fields: fields,
packed: packed,
lineNum: item.lineNum
};
} else {
// variable
- var ident = item.tokens[0].text;
+ var ident = item.assignTo;
var private_ = findTokenText(item, 'private') >= 0 || findTokenText(item, 'internal') >= 0;
var named = findTokenText(item, 'unnamed_addr') < 0;
- cleanOutTokens(LLVM.GLOBAL_MODIFIERS, item.tokens, [2, 3]);
+ cleanOutTokens(LLVM.GLOBAL_MODIFIERS, item.tokens, [0, 1]);
var external = false;
- if (item.tokens[2].text === 'external') {
+ if (item.tokens[0].text === 'external') {
external = true;
- item.tokens.splice(2, 1);
+ item.tokens.splice(0, 1);
}
var ret = {
intertype: 'globalVariable',
- ident: toNiceIdent(ident),
- type: item.tokens[2].text,
+ ident: ident,
+ type: item.tokens[0].text,
external: external,
private_: private_,
named: named,
lineNum: item.lineNum
};
noteGlobalVariable(ret);
- if (ident == '@llvm.global_ctors') {
+ if (ident == '_llvm_global_ctors') {
ret.ctors = [];
- if (item.tokens[3].item) {
- var subTokens = item.tokens[3].item.tokens;
+ if (item.tokens[1].item) {
+ var subTokens = item.tokens[1].item.tokens;
splitTokenList(subTokens).forEach(function(segment) {
- var ctor = toNiceIdent(segment[1].tokens.slice(-1)[0].text);
+ var parsed = parseLLVMSegment(segment);
+ assert(parsed.intertype === 'structvalue');
+ var ctor = toNiceIdent(parsed.params[1].ident);
ret.ctors.push(ctor);
if (ASM_JS) { // must export the global constructors from asm.js module, so mark as implemented and exported
Functions.implementedFunctions[ctor] = 'v';
@@ -540,14 +522,14 @@ function intertyper(lines, sidePass, baseLineNums) {
});
}
} else if (!external) {
- if (item.tokens[3] && item.tokens[3].text != ';') {
- if (item.tokens[3].text == 'c') {
- item.tokens.splice(3, 1);
+ if (item.tokens[1] && item.tokens[1].text != ';') {
+ if (item.tokens[1].text == 'c') {
+ item.tokens.splice(1, 1);
}
- if (item.tokens[3].text in PARSABLE_LLVM_FUNCTIONS) {
- ret.value = parseLLVMFunctionCall(item.tokens.slice(2));
+ if (item.tokens[1].text in PARSABLE_LLVM_FUNCTIONS) {
+ ret.value = parseLLVMFunctionCall(item.tokens);
} else {
- ret.value = scanConst(item.tokens[3], ret.type);
+ ret.value = scanConst(item.tokens[1], ret.type);
}
} else {
ret.value = { intertype: 'value', ident: '0', value: '0', type: ret.type };
@@ -1131,7 +1113,27 @@ function intertyper(lines, sidePass, baseLineNums) {
//var time = Date.now();
- var t = tokenize(line.lineText, line.lineNum);
+ // parse out the assignment
+ var indent = 0, assignTo = null;
+ if (phase === 'pre') {
+ var m = /^([%@\w\d\._\-]+|[%@]"[^"]+") = (.*)/.exec(line.lineText);
+ if (m) {
+ assignTo = m[1];
+ line.lineText = m[2];
+ }
+ } else if (phase === 'funcs') {
+ var m = /^ ([%@\w\d\._\-]+|[%@]"[^"]+") = (.*)/.exec(line.lineText);
+ if (m) {
+ indent = 2;
+ assignTo = m[1];
+ line.lineText = m[2];
+ }
+ }
+
+ var t = tokenize(line.lineText, line.lineNum, indent);
+ if (assignTo) {
+ t.assignTo = t.tokens[0].text !== 'type' ? toNiceIdent(assignTo) : assignTo;
+ }
item = triager(t);
/*
@@ -1148,7 +1150,7 @@ function intertyper(lines, sidePass, baseLineNums) {
return finalResults;
}
-// intertyper profiler
+// intertyper profiling
/*
var interProf = {};
@@ -1156,4 +1158,5 @@ function dumpInterProf() {
printErr('\nintertyper/' + phase + ' (ms | n): ' + JSON.stringify(keys(interProf).sort(function(x, y) { return interProf[y].ms - interProf[x].ms }).map(function(x) { return x + ' : ' + interProf[x].ms + ' | ' + interProf[x].n }), null, ' ') + '\n');
}
*/
+//var hits = 0;
diff --git a/src/jsifier.js b/src/jsifier.js
index a126994b..e84de3ee 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -407,6 +407,9 @@ function JSify(data, functionsOnly, givenFunctions) {
var snippet = LibraryManager.library[ident];
var redirectedIdent = null;
var deps = LibraryManager.library[ident + '__deps'] || [];
+ deps.forEach(function(dep) {
+ if (typeof snippet === 'string' && !(dep in LibraryManager.library)) warn('missing library dependency ' + dep + ', make sure you are compiling with the right options (see #ifdefs in src/library*.js)');
+ });
var isFunction = false;
if (typeof snippet === 'string') {
@@ -1372,7 +1375,7 @@ function JSify(data, functionsOnly, givenFunctions) {
// store current list offset in tempInt, advance list offset by STACK_ALIGN, return list entry stored at tempInt
return '(tempInt=' + makeGetValue(ident, Runtime.QUANTUM_SIZE, '*') + ',' +
- makeSetValue(ident, Runtime.QUANTUM_SIZE, 'tempInt + ' + move, '*') + ',' +
+ makeSetValue(ident, Runtime.QUANTUM_SIZE, 'tempInt + ' + move, '*', null, null, null, null, ',') + ',' +
makeGetValue(makeGetValue(ident, 0, '*'), 'tempInt', item.type) + ')';
}
diff --git a/src/library_fs.js b/src/library_fs.js
index 5adbe6b7..bd1522a8 100644
--- a/src/library_fs.js
+++ b/src/library_fs.js
@@ -1,5 +1,5 @@
mergeInto(LibraryManager.library, {
- $FS__deps: ['$ERRNO_CODES', '$ERRNO_MESSAGES', '__setErrNo', '$VFS', '$PATH', '$TTY', '$MEMFS', '$IDBFS', '$NODEFS', 'stdin', 'stdout', 'stderr', 'fflush'],
+ $FS__deps: ['$ERRNO_CODES', '$ERRNO_MESSAGES', '__setErrNo', '$PATH', '$TTY', '$MEMFS', '$IDBFS', '$NODEFS', 'stdin', 'stdout', 'stderr', 'fflush'],
$FS__postset: 'FS.staticInit();' +
'__ATINIT__.unshift({ func: function() { if (!Module["noFSInit"] && !FS.init.initialized) FS.init() } });' +
'__ATMAIN__.push({ func: function() { FS.ignorePermissions = false } });' +
@@ -1064,19 +1064,8 @@ mergeInto(LibraryManager.library, {
{{{ makeSetValue(makeGlobalUse('_stderr'), 0, 'stderr.fd', 'void*') }}};
assert(stderr.fd === 3, 'invalid handle for stderr (' + stderr.fd + ')');
},
- staticInit: function() {
- FS.nameTable = new Array(4096);
-
- FS.root = FS.createNode(null, '/', {{{ cDefine('S_IFDIR') }}} | 0777, 0);
- FS.mount(MEMFS, {}, '/');
-
- FS.createDefaultDirectories();
- FS.createDefaultDevices();
- },
- init: function(input, output, error) {
- assert(!FS.init.initialized, 'FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)');
- FS.init.initialized = true;
-
+ ensureErrnoError: function() {
+ if (FS.ErrnoError) return;
FS.ErrnoError = function ErrnoError(errno) {
this.errno = errno;
for (var key in ERRNO_CODES) {
@@ -1090,6 +1079,23 @@ mergeInto(LibraryManager.library, {
};
FS.ErrnoError.prototype = new Error();
FS.ErrnoError.prototype.constructor = FS.ErrnoError;
+ },
+ staticInit: function() {
+ FS.ensureErrnoError();
+
+ FS.nameTable = new Array(4096);
+
+ FS.root = FS.createNode(null, '/', {{{ cDefine('S_IFDIR') }}} | 0777, 0);
+ FS.mount(MEMFS, {}, '/');
+
+ FS.createDefaultDirectories();
+ FS.createDefaultDevices();
+ },
+ init: function(input, output, error) {
+ assert(!FS.init.initialized, 'FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)');
+ FS.init.initialized = true;
+
+ FS.ensureErrnoError();
// Allow Module.stdin etc. to provide defaults, if none explicitly passed to us here
Module['stdin'] = input || Module['stdin'];
diff --git a/src/library_gl.js b/src/library_gl.js
index 6e0e04dc..1ea8efc2 100644
--- a/src/library_gl.js
+++ b/src/library_gl.js
@@ -4047,7 +4047,10 @@ var LibraryGL = {
_glColor4f({{{ makeGetValue('p', '0', 'float') }}}, {{{ makeGetValue('p', '4', 'float') }}}, {{{ makeGetValue('p', '8', 'float') }}}, {{{ makeGetValue('p', '12', 'float') }}});
},
- glColor4ubv: function() { throw 'glColor4ubv not implemented' },
+ glColor4ubv__deps: ['glColor4ub'],
+ glColor4ubv: function(p) {
+ _glColor4ub({{{ makeGetValue('p', '0', 'i8') }}}, {{{ makeGetValue('p', '1', 'i8') }}}, {{{ makeGetValue('p', '2', 'i8') }}}, {{{ makeGetValue('p', '3', 'i8') }}});
+ },
glFogf: function(pname, param) { // partial support, TODO
switch(pname) {
@@ -4470,6 +4473,7 @@ var LibraryGL = {
return 1 /* GL_TRUE */;
},
+ gluOrtho2D__deps: ['glOrtho'],
gluOrtho2D: function(left, right, bottom, top) {
_glOrtho(left, right, bottom, top, -1, 1);
},
diff --git a/src/library_glut.js b/src/library_glut.js
index 79c586c6..722ea85c 100644
--- a/src/library_glut.js
+++ b/src/library_glut.js
@@ -190,12 +190,12 @@ var LibraryGLUT = {
}
},
- onMouseButtonDown: function(event){
+ onMouseButtonDown: function(event) {
Browser.calculateMouseEvent(event);
GLUT.buttons |= (1 << event['button']);
- if(event.target == Module["canvas"] && GLUT.mouseFunc){
+ if (event.target == Module["canvas"] && GLUT.mouseFunc) {
try {
event.target.setCapture();
} catch (e) {}
@@ -205,21 +205,40 @@ var LibraryGLUT = {
}
},
- onMouseButtonUp: function(event){
+ onMouseButtonUp: function(event) {
Browser.calculateMouseEvent(event);
GLUT.buttons &= ~(1 << event['button']);
- if(GLUT.mouseFunc) {
+ if (GLUT.mouseFunc) {
event.preventDefault();
GLUT.saveModifiers(event);
Runtime.dynCall('viiii', GLUT.mouseFunc, [event['button'], 1/*GLUT_UP*/, Browser.mouseX, Browser.mouseY]);
}
},
+ onMouseWheel: function(event) {
+ Browser.calculateMouseEvent(event);
+
+ // cross-browser wheel delta
+ var e = window.event || event; // old IE support
+ var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));
+
+ var button = 3; // wheel up
+ if (delta < 0) {
+ button = 4; // wheel down
+ }
+
+ if (GLUT.mouseFunc) {
+ event.preventDefault();
+ GLUT.saveModifiers(event);
+ Runtime.dynCall('viiii', GLUT.mouseFunc, [button, 0/*GLUT_DOWN*/, Browser.mouseX, Browser.mouseY]);
+ }
+ },
+
// TODO add fullscreen API ala:
// http://johndyer.name/native-fullscreen-javascript-api-plus-jquery-plugin/
- onFullScreenEventChange: function(event){
+ onFullScreenEventChange: function(event) {
var width;
var height;
if (document["fullScreen"] || document["mozFullScreen"] || document["webkitIsFullScreen"]) {
@@ -280,6 +299,10 @@ var LibraryGLUT = {
window.addEventListener("mousemove", GLUT.onMousemove, true);
window.addEventListener("mousedown", GLUT.onMouseButtonDown, true);
window.addEventListener("mouseup", GLUT.onMouseButtonUp, true);
+ // IE9, Chrome, Safari, Opera
+ window.addEventListener("mousewheel", GLUT.onMouseWheel, true);
+ // Firefox
+ window.addEventListener("DOMMouseScroll", GLUT.onMouseWheel, true);
}
Browser.resizeListeners.push(function(width, height) {
@@ -299,6 +322,10 @@ var LibraryGLUT = {
window.removeEventListener("mousemove", GLUT.onMousemove, true);
window.removeEventListener("mousedown", GLUT.onMouseButtonDown, true);
window.removeEventListener("mouseup", GLUT.onMouseButtonUp, true);
+ // IE9, Chrome, Safari, Opera
+ window.removeEventListener("mousewheel", GLUT.onMouseWheel, true);
+ // Firefox
+ window.removeEventListener("DOMMouseScroll", GLUT.onMouseWheel, true);
}
Module["canvas"].width = Module["canvas"].height = 1;
} });
diff --git a/src/library_sdl.js b/src/library_sdl.js
index bb7e9264..a0689343 100644
--- a/src/library_sdl.js
+++ b/src/library_sdl.js
@@ -1149,7 +1149,7 @@ var LibrarySDL = {
var ret = SDL.makeSurface(diagonal, diagonal, srcData.flags, false, 'rotozoomSurface');
var dstData = SDL.surfaces[ret];
dstData.ctx.translate(diagonal / 2, diagonal / 2);
- dstData.ctx.rotate(angle * Math.PI / 180);
+ dstData.ctx.rotate(-angle * Math.PI / 180);
dstData.ctx.drawImage(srcData.canvas, -w / 2, -h / 2, w, h);
return ret;
},
diff --git a/src/preamble.js b/src/preamble.js
index 33e80217..ee273f6a 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -656,7 +656,16 @@ function demangle(func) {
'i': 'int',
'l': 'long',
'f': 'float',
- 'd': 'double'
+ 'd': 'double',
+ 'w': 'wchar_t',
+ 'a': 'signed char',
+ 'h': 'unsigned char',
+ 't': 'unsigned short',
+ 'j': 'unsigned int',
+ 'm': 'unsigned long',
+ 'x': 'long long',
+ 'y': 'unsigned long long',
+ 'z': '...'
};
function dump(x) {
//return;
@@ -729,6 +738,7 @@ function demangle(func) {
} else {
switch (c) {
case 'P': list.push(parse(true, 1, true)[0] + '*'); break; // pointer
+ case 'R': list.push(parse(true, 1, true)[0] + '&'); break; // reference
case 'L': { // literal
i++; // skip basic type
var end = func.indexOf('E', i);
@@ -737,6 +747,14 @@ function demangle(func) {
i += size + 2; // size + 'EE'
break;
}
+ case 'A': { // array
+ var size = parseInt(func.substr(i));
+ i += size.toString().length;
+ if (func[i] !== '_') throw '?';
+ i++; // skip _
+ list.push(parse(true, 1, true)[0] + ' [' + size + ']');
+ break;
+ }
case 'E': break paramLoop;
default: ret += '?' + c; break paramLoop;
}
@@ -752,11 +770,12 @@ function demangle(func) {
}
function demangleAll(text) {
- return text.replace(/__Z[\w\d_]+/, function(x) { var y = demangle(x); return x === y ? x : (x + ' (' + y + ')') });
+ return text.replace(/__Z[\w\d_]+/g, function(x) { var y = demangle(x); return x === y ? x : (x + ' [' + y + ']') });
}
function stackTrace() {
- return demangleAll(new Error().stack);
+ var stack = new Error().stack;
+ return stack ? demangleAll(stack) : '(no stack trace available)'; // Stack trace is not available at least on IE10 and Safari 6.
}
// Memory management
diff --git a/src/proxyClient.js b/src/proxyClient.js
index 04f7ed11..38ea5771 100644
--- a/src/proxyClient.js
+++ b/src/proxyClient.js
@@ -30,7 +30,15 @@ worker.onmessage = function(event) {
break;
}
case 'render': {
- Module.canvasData.data.set(data.image.data);
+ var src = data.image.data;
+ var dst = Module.canvasData.data;
+ if (dst.set) {
+ dst.set(src);
+ } else {
+ for (var i = 0; i < src.length; i++) {
+ dst[i] = src[i];
+ }
+ }
Module.ctx.putImageData(Module.canvasData, 0, 0);
break;
}
diff --git a/tests/cases/ctors_cast.ll b/tests/cases/ctors_cast.ll
new file mode 100644
index 00000000..d94b1d63
--- /dev/null
+++ b/tests/cases/ctors_cast.ll
@@ -0,0 +1,49 @@
+; ModuleID = '/tmp/tmpHcVUBJ/a.out.bc'
+target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:32"
+target triple = "le32-unknown-nacl"
+
+%struct.Other = type { i8 }
+
+@.str = private unnamed_addr constant [17 x i8] c"autorun called!\0A\00", align 1
+@other = internal global %struct.Other zeroinitializer, align 1
+@.str1 = private unnamed_addr constant [14 x i8] c"main called!\0A\00", align 1
+@.str2 = private unnamed_addr constant [7 x i8] c"Other\0A\00", align 1
+@llvm.global_ctors = appending global [2 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* bitcast (i32 ()* @_Z7autorunv to void ()*) }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }]
+
+define internal i32 @_Z7autorunv() {
+ %1 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([17 x i8]* @.str, i32 0, i32 0))
+ ret i32 0
+}
+
+declare i32 @printf(i8*, ...)
+
+define internal void @__cxx_global_var_init() {
+ call void @_ZN5OtherC1Ev(%struct.Other* @other)
+ ret void
+}
+
+define internal void @_ZN5OtherC1Ev(%struct.Other* %this) unnamed_addr align 2 {
+ %1 = alloca %struct.Other*, align 4
+ store %struct.Other* %this, %struct.Other** %1, align 4
+ %2 = load %struct.Other** %1
+ call void @_ZN5OtherC2Ev(%struct.Other* %2)
+ ret void
+}
+
+define i32 @main() {
+ %1 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([14 x i8]* @.str1, i32 0, i32 0))
+ ret i32 0
+}
+
+define internal void @_ZN5OtherC2Ev(%struct.Other* %this) unnamed_addr align 2 {
+ %1 = alloca %struct.Other*, align 4
+ store %struct.Other* %this, %struct.Other** %1, align 4
+ %2 = load %struct.Other** %1
+ %3 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([7 x i8]* @.str2, i32 0, i32 0))
+ ret void
+}
+
+define internal void @_GLOBAL__I_a() {
+ call void @__cxx_global_var_init()
+ ret void
+}
diff --git a/tests/cases/ctors_cast.txt b/tests/cases/ctors_cast.txt
new file mode 100644
index 00000000..8a3f62a7
--- /dev/null
+++ b/tests/cases/ctors_cast.txt
@@ -0,0 +1,3 @@
+autorun called!
+Other
+main called!
diff --git a/tests/glut_wheelevents.c b/tests/glut_wheelevents.c
new file mode 100644
index 00000000..7be01636
--- /dev/null
+++ b/tests/glut_wheelevents.c
@@ -0,0 +1,68 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <GL/glut.h>
+#include <EGL/egl.h>
+#include <emscripten.h>
+
+#define MULTILINE(...) #__VA_ARGS__
+
+int wheel_up = 0;
+int wheel_down = 0;
+
+int result = 0;
+
+void mouseCB(int button, int state, int x, int y)
+{
+ if(button == 3)
+ {
+ wheel_up = 1;
+ }
+ else if (button == 4)
+ {
+ wheel_down = 1;
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ emscripten_run_script(MULTILINE(
+ Module.injectWheelEvent = function(x, y, delta) {
+ var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
+ var event = document.createEvent("MouseEvents");
+ if (!isFirefox) {
+ // mouse wheel event for IE9, Chrome, Safari, Opera
+ event.initMouseEvent('mousewheel', true, true, window,
+ 0, Module['canvas'].offsetLeft + x, Module['canvas'].offsetTop + y, Module['canvas'].offsetLeft + x, Module['canvas'].offsetTop + y,
+ 0, 0, 0, 0, 0, null);
+ event.wheelDelta = delta;
+ } else {
+ // mouse wheel event for Firefox, the delta sign is inversed for that browser and is stored in the detail property of the mouse event
+ event.initMouseEvent('DOMMouseScroll', true, true, window,
+ -delta, Module['canvas'].offsetLeft + x, Module['canvas'].offsetTop + y, Module['canvas'].offsetLeft + x, Module['canvas'].offsetTop + y,
+ 0, 0, 0, 0, 0, null);
+ }
+ Module['canvas'].dispatchEvent(event);
+ }
+ ));
+
+
+ glutInit(&argc, argv);
+
+ glutMouseFunc(&mouseCB);
+
+ // inject wheel up event (delta > 0)
+ emscripten_run_script("Module.injectWheelEvent(100, 100, 1)");
+ if (wheel_up) {
+ printf("%s\n", "mouse wheel up event received");
+ }
+ // inject wheel down event (delta < 0)
+ emscripten_run_script("Module.injectWheelEvent(100, 100, -1)");
+ if (wheel_down) {
+ printf("%s\n", "mouse wheel down event received");
+ }
+
+ result = wheel_up && wheel_down;
+
+ REPORT_RESULT();
+ return 0;
+}
diff --git a/tests/sdl_rotozoom.c b/tests/sdl_rotozoom.c
index cdbdcc6f..2c0d35df 100644
--- a/tests/sdl_rotozoom.c
+++ b/tests/sdl_rotozoom.c
@@ -38,7 +38,7 @@ int main(int argc, char **argv) {
sprite[2] = zoomSurface(sprite[0], 0.5, 0.5, SMOOTHING_ON);
sprite[3] = zoomSurface(sprite[1], 0.5, 0.5, SMOOTHING_ON);
sprite[4] = rotozoomSurface(sprite[0], -20, 0.3, SMOOTHING_ON);
- sprite[5] = rotozoomSurface(sprite[1], 45, 0.5, SMOOTHING_ON);
+ sprite[5] = rotozoomSurface(sprite[1], 20, 1, SMOOTHING_ON);
sprite[6] = zoomSurface(sprite[0], -0.5, 0.5, SMOOTHING_ON);
sprite[7] = zoomSurface(sprite[0], -0.5, -0.5, SMOOTHING_ON);
sprite[8] = rotozoomSurface(sprite[1], 0, 0.5, SMOOTHING_ON);
diff --git a/tests/sdl_rotozoom.png b/tests/sdl_rotozoom.png
index 5933754f..ebde79f2 100644
--- a/tests/sdl_rotozoom.png
+++ b/tests/sdl_rotozoom.png
Binary files differ
diff --git a/tests/test_browser.py b/tests/test_browser.py
index 24113511..ecd331fd 100644
--- a/tests/test_browser.py
+++ b/tests/test_browser.py
@@ -866,6 +866,9 @@ keydown(100);keyup(100); // trigger the end
def test_glut_touchevents(self):
self.btest('glut_touchevents.c', '1')
+ def test_glut_wheelevents(self):
+ self.btest('glut_wheelevents.c', '1')
+
def test_emscripten_get_now(self):
self.btest('emscripten_get_now.cpp', '1')
@@ -1389,7 +1392,7 @@ keydown(100);keyup(100); // trigger the end
def test_sdl_rotozoom(self):
shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png'))
- self.btest('sdl_rotozoom.c', reference='sdl_rotozoom.png', args=['--preload-file', 'screenshot.png'], reference_slack=5)
+ self.btest('sdl_rotozoom.c', reference='sdl_rotozoom.png', args=['--preload-file', 'screenshot.png'])
def test_sdl_gfx_primitives(self):
self.btest('sdl_gfx_primitives.c', reference='sdl_gfx_primitives.png', reference_slack=1)
diff --git a/tests/test_core.py b/tests/test_core.py
index 87925082..8ba9295a 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -7274,6 +7274,7 @@ date: 18.07.2013w; day 18, month 7, year 2013, extra: 201, 3
self.do_run(src, expected, extra_emscripten_args=['-H', 'libc/langinfo.h'])
def test_files(self):
+ self.banned_js_engines = [SPIDERMONKEY_ENGINE] # closure can generate variables called 'gc', which pick up js shell stuff
if self.emcc_args is not None and '-O2' in self.emcc_args:
self.emcc_args += ['--closure', '1'] # Use closure here, to test we don't break FS stuff
self.emcc_args = filter(lambda x: x != '-g', self.emcc_args) # ensure we test --closure 1 --memory-init-file 1 (-g would disable closure)
@@ -7826,6 +7827,7 @@ def process(filename):
self.do_run(src, expected)
def test_unistd_unlink(self):
+ self.clear()
if self.emcc_args is None: return self.skip('requires emcc')
if not self.is_le32(): return self.skip('le32 needed for inline js')
for fs in ['MEMFS', 'NODEFS']:
@@ -7834,6 +7836,7 @@ def process(filename):
self.do_run(src, 'success', force_c=True, js_engines=[NODE_JS])
def test_unistd_links(self):
+ self.clear()
if not self.is_le32(): return self.skip('le32 needed for inline js')
for fs in ['MEMFS', 'NODEFS']:
src = open(path_from_root('tests', 'unistd', 'links.c'), 'r').read()
@@ -7847,6 +7850,7 @@ def process(filename):
self.do_run(src, expected)
def test_unistd_io(self):
+ self.clear()
if not self.is_le32(): return self.skip('le32 needed for inline js')
if self.run_name == 'o2': return self.skip('non-asm optimized builds can fail with inline js')
if self.emcc_args is None: return self.skip('requires emcc')
@@ -8091,11 +8095,7 @@ int main(int argc, char **argv) {
def test_iostream(self):
if Settings.QUANTUM_SIZE == 1: return self.skip("we don't support libcxx in q1")
-
- if self.emcc_args is None:
- if Building.LLVM_OPTS: return self.skip('optimizing bitcode before emcc can confuse libcxx inclusion')
- self.emcc_args = [] # libc++ auto-inclusion is only done if we use emcc
- Settings.SAFE_HEAP = 0 # Some spurious warnings from libc++ internals
+ if self.emcc_args is None: return self.skip('needs ta2 and emcc')
src = '''
#include <iostream>
diff --git a/tests/test_other.py b/tests/test_other.py
index 2d3dde3f..c8b6d4b1 100644
--- a/tests/test_other.py
+++ b/tests/test_other.py
@@ -31,8 +31,8 @@ Most normal gcc/g++ options will work, for example:
--version Display compiler version information
Options that are modified or new in %s include:
- -O0 No optimizations (default)
-''' % (shortcompiler, shortcompiler), output[0].replace('\r', ''), output[1].replace('\r', ''))
+
+ -O0 No optimizations (default)''' % (shortcompiler, shortcompiler), output[0].replace('\r', ''), output[1].replace('\r', ''))
# emcc src.cpp ==> writes a.out.js
self.clear()
@@ -388,6 +388,7 @@ f.close()
def test_unaligned_memory(self):
open(os.path.join(self.get_dir(), 'test.cpp'), 'w').write(r'''
#include <stdio.h>
+ #include <stdarg.h>
typedef unsigned char Bit8u;
typedef unsigned short Bit16u;
@@ -395,6 +396,9 @@ f.close()
int main()
{
+ va_list argp;
+ va_arg(argp, char *); // check for compilation error, #1705
+
Bit8u data[4] = {0x01,0x23,0x45,0x67};
printf("data: %x\n", *(Bit32u*)data);
@@ -1910,6 +1914,12 @@ done.
open('src.cpp', 'w').write('''
#include <stdio.h>
#include <emscripten.h>
+ void two(char c) {
+ EM_ASM(Module.print(stackTrace()));
+ }
+ void one(int x) {
+ two(x % 17);
+ }
int main() {
EM_ASM(Module.print(demangle('__Znwj'))); // check for no aborts
EM_ASM(Module.print(demangle('_main')));
@@ -1922,11 +1932,16 @@ done.
EM_ASM(Module.print(demangle('__Z3FooIidEvi')));
EM_ASM(Module.print(demangle('__ZN3Foo3BarILi5EEEvv')));
EM_ASM(Module.print(demangle('__ZNK10__cxxabiv120__si_class_type_info16search_below_dstEPNS_19__dynamic_cast_infoEPKvib')));
+ EM_ASM(Module.print(demangle('__Z9parsewordRPKciRi')));
+ EM_ASM(Module.print(demangle('__Z5multiwahtjmxyz')));
+ EM_ASM(Module.print(demangle('__Z1aA32_iPA5_c')));
+ one(17);
return 0;
}
''')
Popen([PYTHON, EMCC, 'src.cpp', '-s', 'LINKABLE=1']).communicate()
+ output = run_js('a.out.js')
self.assertContained('''main
f2()
abcdabcdabcd(int)
@@ -1937,5 +1952,11 @@ void Foo<int>()
void Foo<int, double>(int)
void Foo::Bar<5>()
__cxxabiv1::__si_class_type_info::search_below_dst(__cxxabiv1::__dynamic_cast_info*, void*, int, bool)
-''', run_js('a.out.js'))
+parseword(char*&, int, int&)
+multi(wchar_t, signed char, unsigned char, unsigned short, unsigned int, unsigned long, long long, unsigned long long, ...)
+a(int [32], char [5]*)
+''', output)
+ # test for multiple functions in one stack trace
+ assert 'one(int)' in output
+ assert 'two(char)' in output
diff --git a/tools/autodebugger.py b/tools/autodebugger.py
index c74e56d2..df9594b3 100644
--- a/tools/autodebugger.py
+++ b/tools/autodebugger.py
@@ -282,7 +282,9 @@ for i in range(len(lines)):
lines_added += 1
f = open(ofilename, 'w')
-f.write('\n'.join(lines) + '\n' + POSTAMBLE + '\n')
+ll = '\n'.join(lines)
+meta_start = ll.find('\n!')
+f.write(ll[:meta_start] + '\n' + POSTAMBLE + '\n' + ll[meta_start:])
f.close()
print 'Success.'