aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/library.js19
-rw-r--r--src/library_browser.js54
-rw-r--r--src/library_openal.js100
-rw-r--r--src/library_sdl.js38
-rw-r--r--src/parseTools.js4
-rw-r--r--src/shell.html8
-rw-r--r--system/include/libc/ctype.h44
-rwxr-xr-xtests/runner.py72
-rw-r--r--tools/js-optimizer.js11
9 files changed, 220 insertions, 130 deletions
diff --git a/src/library.js b/src/library.js
index d5f11cf3..aebad63b 100644
--- a/src/library.js
+++ b/src/library.js
@@ -382,7 +382,7 @@ LibraryManager.library = {
// do preloading for the Image/Audio part, as if the typed array were the
// result of an XHR that you did manually.
createPreloadedFile: function(parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile) {
- Browser.ensureObjects();
+ Browser.init();
var fullname = FS.joinPath([parent, name], true);
function processData(byteArray) {
function finish(byteArray) {
@@ -2642,7 +2642,7 @@ LibraryManager.library = {
// 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.
- _formatString__deps: ['strlen'],
+ _formatString__deps: ['strlen', '_reallyNegative'],
_formatString: function(format, varargs) {
var textIndex = format;
var argIndex = 0;
@@ -2897,7 +2897,6 @@ LibraryManager.library = {
// Float.
var currArg = getNextArg('double');
var argText;
-
if (isNaN(currArg)) {
argText = 'nan';
flagZeroPad = false;
@@ -2932,6 +2931,9 @@ LibraryManager.library = {
}
} else if (next == {{{ charCode('f') }}} || next == {{{ charCode('F') }}}) {
argText = currArg.toFixed(effectivePrecision);
+ if (currArg === 0 && __reallyNegative(currArg)) {
+ argText = '-' + argText;
+ }
}
var parts = argText.split('e');
@@ -4950,7 +4952,7 @@ LibraryManager.library = {
var ret = 0;
while (x) {
if (x&1) ret++;
- x >>= 1;
+ x >>>= 1;
}
return ret;
},
@@ -5478,9 +5480,14 @@ LibraryManager.library = {
return isNaN(x);
},
__isnan: 'isnan',
+
+ _reallyNegative: function(x) {
+ return x < 0 || (x === 0 && (1/x) === -Infinity);
+ },
+
+ copysign__deps: ['_reallyNegative'],
copysign: function(a, b) {
- if (a < 0 === b < 0) return a;
- return -a;
+ return __reallyNegative(a) === __reallyNegative(b) ? a : -a;
},
copysignf: 'copysign',
__signbit__deps: ['copysign'],
diff --git a/src/library_browser.js b/src/library_browser.js
index bdd94bac..e61f84b5 100644
--- a/src/library_browser.js
+++ b/src/library_browser.js
@@ -45,9 +45,9 @@ mergeInto(LibraryManager.library, {
moduleContextCreatedCallbacks: [],
workers: [],
- ensureObjects: function() {
- if (Browser.ensured) return;
- Browser.ensured = true;
+ init: function() {
+ if (Browser.initted) return;
+ Browser.initted = true;
try {
new Blob();
Browser.hasBlobConstructor = true;
@@ -193,6 +193,36 @@ mergeInto(LibraryManager.library, {
}
};
Module['preloadPlugins'].push(audioPlugin);
+
+ // Canvas event setup
+
+ var canvas = Module['canvas'];
+ canvas.requestPointerLock = canvas['requestPointerLock'] ||
+ canvas['mozRequestPointerLock'] ||
+ canvas['webkitRequestPointerLock'];
+ canvas.exitPointerLock = document['exitPointerLock'] ||
+ document['mozExitPointerLock'] ||
+ document['webkitExitPointerLock'];
+ canvas.exitPointerLock = canvas.exitPointerLock.bind(document);
+
+ function pointerLockChange() {
+ Browser.pointerLock = document['pointerLockElement'] === canvas ||
+ document['mozPointerLockElement'] === canvas ||
+ document['webkitPointerLockElement'] === canvas;
+ }
+
+ document.addEventListener('pointerlockchange', pointerLockChange, false);
+ document.addEventListener('mozpointerlockchange', pointerLockChange, false);
+ document.addEventListener('webkitpointerlockchange', pointerLockChange, false);
+
+ if (Module['elementPointerLock']) {
+ canvas.addEventListener("click", function(ev) {
+ if (!Browser.pointerLock && canvas.requestPointerLock) {
+ canvas.requestPointerLock();
+ ev.preventDefault();
+ }
+ }, false);
+ }
},
createContext: function(canvas, useWebGL, setInModule) {
@@ -271,6 +301,7 @@ mergeInto(LibraryManager.library, {
Module.ctx = ctx;
Module.useWebGL = useWebGL;
Browser.moduleContextCreatedCallbacks.forEach(function(callback) { callback() });
+ Browser.init();
}
return ctx;
},
@@ -292,13 +323,6 @@ mergeInto(LibraryManager.library, {
if ((document['webkitFullScreenElement'] || document['webkitFullscreenElement'] ||
document['mozFullScreenElement'] || document['mozFullscreenElement'] ||
document['fullScreenElement'] || document['fullscreenElement']) === canvas) {
- canvas.requestPointerLock = canvas['requestPointerLock'] ||
- canvas['mozRequestPointerLock'] ||
- canvas['webkitRequestPointerLock'];
- canvas.exitPointerLock = document['exitPointerLock'] ||
- document['mozExitPointerLock'] ||
- document['webkitExitPointerLock'];
- canvas.exitPointerLock = canvas.exitPointerLock.bind(document);
canvas.cancelFullScreen = document['cancelFullScreen'] ||
document['mozCancelFullScreen'] ||
document['webkitCancelFullScreen'];
@@ -312,21 +336,11 @@ mergeInto(LibraryManager.library, {
if (Module['onFullScreen']) Module['onFullScreen'](Browser.isFullScreen);
}
- function pointerLockChange() {
- Browser.pointerLock = document['pointerLockElement'] === canvas ||
- document['mozPointerLockElement'] === canvas ||
- document['webkitPointerLockElement'] === canvas;
- }
-
if (!this.fullScreenHandlersInstalled) {
this.fullScreenHandlersInstalled = true;
document.addEventListener('fullscreenchange', fullScreenChange, false);
document.addEventListener('mozfullscreenchange', fullScreenChange, false);
document.addEventListener('webkitfullscreenchange', fullScreenChange, false);
-
- document.addEventListener('pointerlockchange', pointerLockChange, false);
- document.addEventListener('mozpointerlockchange', pointerLockChange, false);
- document.addEventListener('webkitpointerlockchange', pointerLockChange, false);
}
canvas.requestFullScreen = canvas['requestFullScreen'] ||
diff --git a/src/library_openal.js b/src/library_openal.js
index 6bd0f6b0..b785a89f 100644
--- a/src/library_openal.js
+++ b/src/library_openal.js
@@ -57,6 +57,7 @@ var LibraryOpenAL = {
}
if (ctx) {
+ ctx.listener.panningModel = "equalpower";
AL.contexts.push({ctx: ctx, err: 0, src: [], buf: []});
return AL.contexts.length;
} else {
@@ -72,6 +73,12 @@ var LibraryOpenAL = {
}
},
+ alcGetError__deps: ['alGetError'],
+ alcGetError: function(device) {
+ // We have only one audio device, so just return alGetError.
+ return _alGetError();
+ },
+
alDeleteSources: function(count, sources)
{
if (!AL.currentContext) {
@@ -81,7 +88,7 @@ var LibraryOpenAL = {
return;
}
for (var i = 0; i < count; ++i) {
- var sourceIdx = {{{ makeGetValue('sources', 'i', 'i32') }}} - 1;
+ var sourceIdx = {{{ makeGetValue('sources', 'i*4', 'i32') }}} - 1;
delete AL.currentContext.src[sourceIdx];
}
},
@@ -96,14 +103,8 @@ var LibraryOpenAL = {
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)
+ gain.connect(panner);
+ panner.connect(AL.currentContext.ctx.destination);
AL.currentContext.src.push({
loop: false,
buffer: null,
@@ -113,7 +114,7 @@ var LibraryOpenAL = {
playTime: -1,
pausedTime: 0
});
- {{{ makeSetValue('sources', 'i', 'AL.currentContext.src.length', 'i32') }}};
+ {{{ makeSetValue('sources', 'i*4', 'AL.currentContext.src.length', 'i32') }}};
}
},
@@ -196,15 +197,15 @@ var LibraryOpenAL = {
case 0x1004 /* AL_POSITION */:
AL.currentContext.src[source - 1].panner.setPosition(
{{{ makeGetValue('value', '0', 'float') }}},
- {{{ makeGetValue('value', '1', 'float') }}},
- {{{ makeGetValue('value', '2', 'float') }}}
+ {{{ makeGetValue('value', '4', 'float') }}},
+ {{{ makeGetValue('value', '8', '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') }}}
+ {{{ makeGetValue('value', '4', 'float') }}},
+ {{{ makeGetValue('value', '8', 'float') }}}
);
break;
default:
@@ -235,7 +236,7 @@ var LibraryOpenAL = {
return;
}
for (var i = 0; i < count; ++i) {
- var buffer = {{{ makeGetValue('buffers', 'i', 'i32') }}};
+ var buffer = {{{ makeGetValue('buffers', 'i*4', 'i32') }}};
if (buffer > AL.currentContext.buf.length) {
#if OPENAL_DEBUG
console.error("alSourceQueueBuffers called with an invalid buffer");
@@ -270,7 +271,7 @@ var LibraryOpenAL = {
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') }}};
+ {{{ makeSetValue('buffers', 'i*4', 'j+1', 'i32') }}};
AL.currentContext.src[source - 1].buffer = null;
break;
}
@@ -287,7 +288,7 @@ var LibraryOpenAL = {
return;
}
for (var i = 0; i < count; ++i) {
- var bufferIdx = {{{ makeGetValue('buffers', 'i', 'i32') }}} - 1;
+ var bufferIdx = {{{ makeGetValue('buffers', 'i*4', '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) {
@@ -308,7 +309,7 @@ var LibraryOpenAL = {
}
for (var i = 0; i < count; ++i) {
AL.currentContext.buf.push({buf: null});
- {{{ makeSetValue('buffers', 'i', 'AL.currentContext.buf.length', 'i32') }}};
+ {{{ makeSetValue('buffers', 'i*4', 'AL.currentContext.buf.length', 'i32') }}};
}
},
@@ -385,22 +386,25 @@ var LibraryOpenAL = {
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;
+ if ("src" in AL.currentContext.src[source - 1] &&
+ AL.currentContext.src[source - 1]["src"].buffer ==
+ AL.currentContext.src[source - 1].buffer) {
+ 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;
+ } else {
+ // 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);
+ }
}
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].playTime = AL.currentContext.ctx.currentTime;
AL.currentContext.src[source - 1].paused = false;
AL.currentContext.src[source - 1]['src'] = src;
},
@@ -440,8 +444,7 @@ var LibraryOpenAL = {
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].pausedTime = AL.currentContext.ctx.currentTime;
AL.currentContext.src[source - 1]["src"].stop(0);
delete AL.currentContext.src[source - 1].src;
}
@@ -513,9 +516,43 @@ var LibraryOpenAL = {
},
alListenerfv: function(param, values) {
+ if (!AL.currentContext) {
+#if OPENAL_DEBUG
+ console.error("alListenerfv called without a valid context");
+#endif
+ return;
+ }
+ switch (param) {
+ case 0x1004 /* AL_POSITION */:
+ AL.currentContext.ctx.listener.setPosition(
+ {{{ makeGetValue('values', '0', 'float') }}},
+ {{{ makeGetValue('values', '4', 'float') }}},
+ {{{ makeGetValue('values', '8', 'float') }}}
+ );
+ break;
+ case 0x1006 /* AL_VELOCITY */:
+ AL.currentContext.ctx.listener.setVelocity(
+ {{{ makeGetValue('values', '0', 'float') }}},
+ {{{ makeGetValue('values', '4', 'float') }}},
+ {{{ makeGetValue('values', '8', 'float') }}}
+ );
+ break;
+ case 0x100F /* AL_ORIENTATION */:
+ AL.currentContext.ctx.listener.setOrientation(
+ {{{ makeGetValue('values', '0', 'float') }}},
+ {{{ makeGetValue('values', '4', 'float') }}},
+ {{{ makeGetValue('values', '8', 'float') }}},
+ {{{ makeGetValue('values', '12', 'float') }}},
+ {{{ makeGetValue('values', '16', 'float') }}},
+ {{{ makeGetValue('values', '20', 'float') }}}
+ );
+ break;
+ default:
#if OPENAL_DEBUG
- console.log("alListenerfv is not supported yet");
+ console.log("alListenerfv with param " + param + " not implemented yet");
#endif
+ break;
+ }
},
alIsExtensionPresent: function(extName) {
@@ -533,7 +570,6 @@ var LibraryOpenAL = {
alcGetProcAddress: function(device, fname) {
return 0;
},
-
};
autoAddDeps(LibraryOpenAL, '$AL');
diff --git a/src/library_sdl.js b/src/library_sdl.js
index 77305609..42207f23 100644
--- a/src/library_sdl.js
+++ b/src/library_sdl.js
@@ -443,23 +443,6 @@ 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
@@ -541,9 +524,18 @@ var LibrarySDL = {
} else {
// Otherwise, calculate the movement based on the changes
// in the coordinates.
- var offsets = SDL.offsets(Module["canvas"]);
- var x = event.pageX - offsets.left;
- var y = event.pageY - offsets.top;
+ var rect = Module["canvas"].getBoundingClientRect();
+ var x = event.pageX - (window.scrollX + rect.left);
+ var y = event.pageY - (window.scrollY + rect.top);
+
+ // the canvas might be CSS-scaled compared to its backbuffer;
+ // SDL-using content will want mouse coordinates in terms
+ // of backbuffer units.
+ var cw = Module["canvas"].width;
+ var ch = Module["canvas"].height;
+ x = x * (cw / rect.width);
+ y = y * (ch / rect.height);
+
var movementX = x - SDL.mouseX;
var movementY = y - SDL.mouseY;
}
@@ -930,11 +922,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"]);
+ var rect = Module["canvas"].getBoundingClientRect();
SDL.events.push({
type: 'mousemove',
- pageX: x + offsets.left,
- pageY: y + offsets.top
+ pageX: x + (window.scrollX + rect.left),
+ pageY: y + (window.scrollY + rect.top)
});
},
diff --git a/src/parseTools.js b/src/parseTools.js
index 2664baed..9fddacbb 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -818,7 +818,9 @@ function parseNumerical(value, type) {
return '0';
}
if (isNumber(value)) {
- return parseFloat(value).toString(); // will change e.g. 5.000000e+01 to 50
+ var ret = parseFloat(value); // will change e.g. 5.000000e+01 to 50
+ if (type in Runtime.FLOAT_TYPES && value[0] == '-' && ret === 0) return '-0'; // fix negative 0, toString makes it 0
+ return ret.toString();
} else {
return value;
}
diff --git a/src/shell.html b/src/shell.html
index 8743d403..f7eb9e1f 100644
--- a/src/shell.html
+++ b/src/shell.html
@@ -6,9 +6,11 @@
<title>Emscripten-Generated Code</title>
<style>
.emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
- canvas.emscripten { border: 1px solid black; }
textarea.emscripten { font-family: monospace; width: 80%; }
div.emscripten { text-align: center; }
+ div.emscripten_border { border: 1px solid black; }
+ /* the canvas *must not* have any border or padding, or mouse coords will be wrong */
+ canvas.emscripten { border: 0px none; }
</style>
</head>
<body>
@@ -17,7 +19,9 @@
<div class="emscripten">
<progress value="0" max="100" id="progress" hidden=1></progress>
</div>
- <canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
+ <div class="emscripten_border">
+ <canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
+ </div>
<hr/>
<div class="emscripten">
<input type="checkbox" id="resize">Resize canvas
diff --git a/system/include/libc/ctype.h b/system/include/libc/ctype.h
index 383a8db1..666c4d7c 100644
--- a/system/include/libc/ctype.h
+++ b/system/include/libc/ctype.h
@@ -117,20 +117,6 @@ extern __IMPORT _CONST char _ctype_[];
_END_STD_C
-
-
-
-
-
-
-
-
-
-
-
-
-
-
/*
* Copyright (c) 2000, 2005, 2008 Apple Inc. All rights reserved.
*
@@ -196,25 +182,15 @@ _END_STD_C
* @(#)ctype.h 8.4 (Berkeley) 1/21/94
*/
-#define _CTYPE_A 0x00000100L /* Alpha */
-#define _CTYPE_C 0x00000200L /* Control */
-#define _CTYPE_D 0x00000400L /* Digit */
-#define _CTYPE_G 0x00000800L /* Graph */
-#define _CTYPE_L 0x00001000L /* Lower */
-#define _CTYPE_P 0x00002000L /* Punct */
-#define _CTYPE_S 0x00004000L /* Space */
-#define _CTYPE_U 0x00008000L /* Upper */
-#define _CTYPE_X 0x00010000L /* X digit */
-#define _CTYPE_B 0x00020000L /* Blank */
-#define _CTYPE_R 0x00040000L /* Print */
-#define _CTYPE_I 0x00080000L /* Ideogram */
-#define _CTYPE_T 0x00100000L /* Special */
-#define _CTYPE_Q 0x00200000L /* Phonogram */
-#define _CTYPE_SW0 0x20000000L /* 0 width character */
-#define _CTYPE_SW1 0x40000000L /* 1 width character */
-#define _CTYPE_SW2 0x80000000L /* 2 width character */
-#define _CTYPE_SW3 0xc0000000L /* 3 width character */
-#define _CTYPE_SWM 0xe0000000L /* Mask for screen width data */
-#define _CTYPE_SWS 30 /* Bits to shift to get width */
+#define _CTYPE_A 0x00000400 /* Alpha */
+#define _CTYPE_C 0x00000002 /* Control */
+#define _CTYPE_D 0x00000800 /* Digit */
+#define _CTYPE_L 0x00000200 /* Lower */
+#define _CTYPE_P 0x00000004 /* Punct */
+#define _CTYPE_S 0x00002000 /* Space */
+#define _CTYPE_U 0x00000100 /* Upper */
+#define _CTYPE_X 0x00001000 /* X digit */
+#define _CTYPE_B 0x00000001 /* Blank */
+#define _CTYPE_R 0x00004000 /* Print */
#endif /* _CTYPE_H_ */
diff --git a/tests/runner.py b/tests/runner.py
index 529dcc48..168567d2 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -1234,6 +1234,59 @@ m_divisor is 1091269979
'''
self.do_run(src, ',0,,2,C!,0,C!,0,,65535,C!,0,')
+ def test_negative_zero(self):
+ src = r'''
+ #include <stdio.h>
+ #include <math.h>
+
+ int main() {
+ #define TEST(x, y) \
+ printf("%.2f, %.2f ==> %.2f\n", x, y, copysign(x, y));
+ TEST( 5.0f, 5.0f);
+ TEST( 5.0f, -5.0f);
+ TEST(-5.0f, 5.0f);
+ TEST(-5.0f, -5.0f);
+ TEST( 5.0f, 4.0f);
+ TEST( 5.0f, -4.0f);
+ TEST(-5.0f, 4.0f);
+ TEST(-5.0f, -4.0f);
+ TEST( 0.0f, 5.0f);
+ TEST( 0.0f, -5.0f);
+ TEST(-0.0f, 5.0f);
+ TEST(-0.0f, -5.0f);
+ TEST( 5.0f, 0.0f);
+ TEST( 5.0f, -0.0f);
+ TEST(-5.0f, 0.0f);
+ TEST(-5.0f, -0.0f);
+ TEST( 0.0f, 0.0f);
+ TEST( 0.0f, -0.0f);
+ TEST(-0.0f, 0.0f);
+ TEST(-0.0f, -0.0f);
+ return 0;
+ }
+ '''
+ self.do_run(src, '''5.00, 5.00 ==> 5.00
+5.00, -5.00 ==> -5.00
+-5.00, 5.00 ==> 5.00
+-5.00, -5.00 ==> -5.00
+5.00, 4.00 ==> 5.00
+5.00, -4.00 ==> -5.00
+-5.00, 4.00 ==> 5.00
+-5.00, -4.00 ==> -5.00
+0.00, 5.00 ==> 0.00
+0.00, -5.00 ==> -0.00
+-0.00, 5.00 ==> 0.00
+-0.00, -5.00 ==> -0.00
+5.00, 0.00 ==> 5.00
+5.00, -0.00 ==> -5.00
+-5.00, 0.00 ==> 5.00
+-5.00, -0.00 ==> -5.00
+0.00, 0.00 ==> 0.00
+0.00, -0.00 ==> -0.00
+-0.00, 0.00 ==> 0.00
+-0.00, -0.00 ==> -0.00
+''')
+
def test_llvm_intrinsics(self):
if self.emcc_args == None: return self.skip('needs ta2')
@@ -1269,6 +1322,7 @@ m_divisor is 1091269979
printf("%d,%d\n", (int)llvm_ctlz_i64(((int64_t)1) << 40), llvm_ctlz_i32(1<<10));
printf("%d,%d\n", (int)llvm_cttz_i64(((int64_t)1) << 40), llvm_cttz_i32(1<<10));
printf("%d,%d\n", (int)llvm_ctpop_i64((0x3101ULL << 32) | 1), llvm_ctpop_i32(0x3101));
+ printf("%d\n", (int)llvm_ctpop_i32(-594093059));
printf("%d\n", llvm_expect_i32(x % 27, 3));
@@ -1286,6 +1340,7 @@ c5,de,15,8a
23,21
40,10
5,4
+22
13
72057594037927936
''')
@@ -5095,7 +5150,7 @@ def process(filename):
0
0
0
- 0
+ -0
1
1
1
@@ -10003,6 +10058,7 @@ f.close()
(path_from_root('tools', 'test-js-optimizer-asm-last.js'), open(path_from_root('tools', 'test-js-optimizer-asm-last-output.js')).read(),
['asm', 'last']),
]:
+ print input
output = Popen(listify(NODE_JS) + [path_from_root('tools', 'js-optimizer.js'), input] + passes, stdin=PIPE, stdout=PIPE).communicate()[0]
self.assertIdentical(expected, output.replace('\r\n', '\n').replace('\n\n', '\n'))
@@ -10019,13 +10075,19 @@ f.close()
try:
os.environ['EMCC_DEBUG'] = '1'
for asm, linkable, chunks, js_chunks in [
- (0, 0, 3, 2), (0, 1, 4, 4),
- (1, 0, 3, 2), (1, 1, 4, 5)
+ (0, 0, 3, 2), (0, 1, 3, 4),
+ (1, 0, 3, 2), (1, 1, 3, 4)
]:
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, '-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
+ ok = False
+ for c in range(chunks, chunks+2):
+ ok = ok or ('phase 2 working on %d chunks' % c in err)
+ assert ok, err
+ ok = False
+ for c in range(js_chunks, js_chunks+2):
+ ok = ok or ('splitting up js optimization into %d chunks' % c in err)
+ assert ok, err
finally:
del os.environ['EMCC_DEBUG']
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js
index 48ab5a1f..5ede0ce8 100644
--- a/tools/js-optimizer.js
+++ b/tools/js-optimizer.js
@@ -2287,19 +2287,16 @@ function minifyGlobals(ast) {
function prepDotZero(ast) {
traverse(ast, function(node, type) {
if (type == 'unary-prefix' && node[1] == '+') {
- if (node[2][0] == 'num') {
+ if (node[2][0] == 'num' ||
+ (node[2][0] == 'unary-prefix' && node[2][1] == '-' && node[2][2][0] == 'num')) {
return ['call', ['name', 'DOT$ZERO'], [node[2]]];
- } else if (node[2][0] == 'unary-prefix' && node[2][1] == '-' && node[2][2][0] == 'num') {
- node[2][2][1] = -node[2][2][1];
- return ['call', ['name', 'DOT$ZERO'], [node[2][2]]];
}
}
});
}
function fixDotZero(js) {
- return js.replace(/DOT\$ZERO\(((0x)?[-+]?[0-9a-f]*\.?[0-9]+([eE][-+]?[0-9]+)?)\)/g, function(m, num) {
- if (num.substr(0, 2) == '0x') {
- if (num[2] == '-') num = '-0x' + num.substr(3); // uglify generates 0x-8000 for some reason
+ return js.replace(/DOT\$ZERO\(([-+]?(0x)?[0-9a-f]*\.?[0-9]+([eE][-+]?[0-9]+)?)\)/g, function(m, num) {
+ if (num.substr(0, 2) == '0x' || num.substr(0, 3) == '-0x') {
return eval(num) + '.0';
}
if (num.indexOf('.') >= 0) return num;