diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/analyzer.js | 33 | ||||
-rw-r--r-- | src/library.js | 44 | ||||
-rw-r--r-- | src/library_browser.js | 4 | ||||
-rw-r--r-- | src/library_sdl.js | 18 | ||||
-rw-r--r-- | src/preamble.js | 43 | ||||
-rw-r--r-- | src/runtime.js | 45 | ||||
-rw-r--r-- | src/settings.js | 2 |
7 files changed, 124 insertions, 65 deletions
diff --git a/src/analyzer.js b/src/analyzer.js index 4bf2255e..163ff4a8 100644 --- a/src/analyzer.js +++ b/src/analyzer.js @@ -253,6 +253,7 @@ function analyzer(data, sidePass) { } // This is an illegal-containing line, and it is unfolded. Legalize it now dprint('legalizer', 'Legalizing ' + item.intertype + ' at line ' + item.lineNum); + var finalizer = null; switch (item.intertype) { case 'store': { var toAdd = []; @@ -486,12 +487,13 @@ function analyzer(data, sidePass) { }; break; } - case 'or': case 'and': case 'xor': { + case 'or': case 'and': case 'xor': case 'icmp': { var otherElements = getLegalVars(value.params[1].ident, sourceBits); processor = function(result, j) { return { intertype: 'mathop', op: value.op, + variant: value.variant, type: 'i' + otherElements[j].bits, params: [ result, @@ -499,10 +501,35 @@ function analyzer(data, sidePass) { ] }; }; + if (value.op == 'icmp') { + if (sourceBits == 64) { // handle the i64 case in processMathOp, where we handle full i64 math + i++; + continue; + } + finalizer = function() { + var ident = ''; + for (var i = 0; i < targetElements.length; i++) { + if (i > 0) { + switch(value.variant) { + case 'eq': ident += '&&'; break; + case 'ne': ident += '||'; break; + default: throw 'unhandleable illegal icmp: ' + value.variant; + } + } + ident += targetElements[i].ident; + } + return { + intertype: 'value', + ident: ident, + type: 'rawJS', + assignTo: item.assignTo + }; + } + } break; } case 'add': case 'sub': case 'sdiv': case 'udiv': case 'mul': case 'urem': case 'srem': - case 'icmp':case 'uitofp': case 'sitofp': { + case 'uitofp': case 'sitofp': { // We cannot do these in parallel chunks of 32-bit operations. We will handle these in processMathop i++; continue; @@ -611,6 +638,8 @@ function analyzer(data, sidePass) { }; legalValue.assignTo = item.assignTo; toAdd.push(legalValue); + } else if (finalizer) { + toAdd.push(finalizer()); } i += removeAndAdd(label.lines, i, toAdd); continue; diff --git a/src/library.js b/src/library.js index bb73c48a..d1ede6bc 100644 --- a/src/library.js +++ b/src/library.js @@ -367,12 +367,13 @@ LibraryManager.library = { return input.cache.shift(); }; } + var utf8 = new Runtime.UTF8Processor(); function simpleOutput(val) { if (val === null || val === '\n'.charCodeAt(0)) { output.printer(output.buffer.join('')); output.buffer = []; } else { - output.buffer.push(String.fromCharCode(val)); + output.buffer.push(utf8.processCChar(val)); } } if (!output) { @@ -2281,6 +2282,14 @@ LibraryManager.library = { var fields = 0; var argIndex = 0; var next; + // remove initial whitespace + while (1) { + next = get(); + if (next == 0) return 0; + if (!(next in __scanString.whiteSpace)) break; + } + unget(next); + next = 1; for (var formatIndex = 0; formatIndex < format.length; formatIndex++) { if (next <= 0) return fields; var next = get(); @@ -2319,11 +2328,10 @@ LibraryManager.library = { } next = get(); } + unget(next); while (buffer.length > last) { - buffer.pop(); - unget(); + unget(buffer.pop().charCodeAt(0)); } - unget(); next = get(); } else { var first = true; @@ -2380,7 +2388,7 @@ LibraryManager.library = { next = get(); if (next <= 0) return fields; // End of input. } - unget(); + unget(next); } else { // Not a specifier. if (format[formatIndex].charCodeAt(0) !== next) { @@ -4519,33 +4527,11 @@ LibraryManager.library = { }, llvm_bswap_i16: function(x) { - x = unSign(x, 32); - var bytes = []; - bytes[0] = x & 255; - x >>= 8; - bytes[1] = x & 255; - x >>= 8; - var ret = 0; - ret <<= 8; - ret += bytes[0]; - ret <<= 8; - ret += bytes[1]; - return ret; + return ((x&0xff)<<8) | ((x>>8)&0xff); }, llvm_bswap_i32: function(x) { - x = unSign(x, 32); - var bytes = []; - for (var i = 0; i < 4; i++) { - bytes[i] = x & 255; - x >>= 8; - } - var ret = 0; - for (i = 0; i < 4; i++) { - ret <<= 8; - ret += bytes[i]; - } - return ret; + return ((x&0xff)<<24) | (((x>>8)&0xff)<<16) | (((x>>16)&0xff)<<8) | (x>>>24); }, llvm_ctlz_i32: function(x) { diff --git a/src/library_browser.js b/src/library_browser.js index 4c26037e..ce59dbdd 100644 --- a/src/library_browser.js +++ b/src/library_browser.js @@ -223,7 +223,8 @@ mergeInto(LibraryManager.library, { var wrapper = function() { if (Browser.mainLoop.queue.length > 0) { Browser.mainLoop.queue.shift()(); - Browser.mainLoop.scheduler(); + if (Browser.mainLoop.queue.length == 0 && Module['setStatus']) Module['setStatus'](''); + setTimeout(wrapper, 0); return; } if (Browser.mainLoop.shouldPause) { @@ -267,6 +268,7 @@ mergeInto(LibraryManager.library, { }, emscripten_push_main_loop_blocker: function(func) { + if (Module['setStatus']) Module['setStatus']('Please wait..'); Browser.mainLoop.queue.push(FUNCTION_TABLE[func]); }, diff --git a/src/library_sdl.js b/src/library_sdl.js index 48e45f27..662620d6 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -28,6 +28,9 @@ var LibrarySDL = { mixerNumChannels: 2, mixerChunkSize: 1024, + 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 + keyboardState: null, shiftKey: false, ctrlKey: false, @@ -263,6 +266,7 @@ var LibrarySDL = { // Decide if we want to use WebGL or not var useWebGL = (flags & 0x04000000) != 0; // SDL_OPENGL + SDL.GL = SDL.GL || useWebGL; var canvas; if (!usePageCanvas) { canvas = document.createElement('canvas'); @@ -695,6 +699,8 @@ var LibrarySDL = { // Copy data from the C++-accessible storage to the canvas backing SDL_UnlockSurface: function(surf) { + assert(!SDL.GL); // in GL mode we do not keep around 2D canvases and contexts + var surfData = SDL.surfaces[surf]; surfData.locked--; @@ -977,9 +983,13 @@ var LibrarySDL = { } var raw = Module["preloadedImages"][filename]; if (!raw) { + if (raw === null) Module.printErr('Trying to reuse preloaded image, but freePreloadedMediaOnUse is set!'); Runtime.warnOnce('Cannot find preloaded image ' + filename); return 0; } + if (Module['freePreloadedMediaOnUse']) { + Module["preloadedImages"][filename] = null; + } var surf = SDL.makeSurface(raw.width, raw.height, 0, false, 'load:' + filename); var surfData = SDL.surfaces[surf]; surfData.ctx.drawImage(raw, 0, 0, raw.width, raw.height, 0, 0, raw.width, raw.height); @@ -989,6 +999,10 @@ var LibrarySDL = { // are in fact available, so we retrieve it here. This does add overhead though. _SDL_LockSurface(surf); surfData.locked--; // The surface is not actually locked in this hack + if (SDL.GL) { + // After getting the pixel data, we can free the canvas and context if we do not need to do 2D canvas blitting + surfData.canvas = surfData.ctx = null; + } return surf; }, SDL_LoadBMP: 'IMG_Load', @@ -1110,9 +1124,13 @@ var LibrarySDL = { filename = FS.standardizePath(Pointer_stringify(filename)); var raw = Module["preloadedAudios"][filename]; if (!raw) { + if (raw === null) Module.printErr('Trying to reuse preloaded audio, but freePreloadedMediaOnUse is set!'); Runtime.warnOnce('Cannot find preloaded audio ' + filename); return 0; } + if (Module['freePreloadedMediaOnUse']) { + Module["preloadedAudios"][filename] = null; + } var id = SDL.audios.length; SDL.audios.push({ source: filename, diff --git a/src/preamble.js b/src/preamble.js index ae00b796..5c5e64fc 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -513,17 +513,17 @@ function allocate(slab, types, allocator) { Module['allocate'] = allocate; function Pointer_stringify(ptr, /* optional */ length) { + var utf8 = new Runtime.UTF8Processor(); var nullTerminated = typeof(length) == "undefined"; var ret = ""; var i = 0; var t; - var nullByte = String.fromCharCode(0); while (1) { - t = String.fromCharCode({{{ makeGetValue('ptr', 'i', 'i8', 0, 1) }}}); - if (nullTerminated && t == nullByte) { break; } else {} - ret += t; + t = {{{ makeGetValue('ptr', 'i', 'i8', 0, 1) }}}; + if (nullTerminated && t == 0) break; + ret += utf8.processCChar(t); i += 1; - if (!nullTerminated && i == length) { break; } + if (!nullTerminated && i == length) break; } return ret; } @@ -734,22 +734,9 @@ Module['String_len'] = String_len; // This processes a JS string into a C-line array of numbers, 0-terminated. // For LLVM-originating strings, see parser.js:parseLLVMString function function intArrayFromString(stringy, dontAddNull, length /* optional */) { - var ret = []; - var t; - var i = 0; - if (length === undefined) { - length = stringy.length; - } - while (i < length) { - var chr = stringy.charCodeAt(i); - if (chr > 0xFF) { -#if ASSERTIONS - assert(false, 'Character code ' + chr + ' (' + stringy[i] + ') at offset ' + i + ' not in 0x00-0xFF.'); -#endif - chr &= 0xFF; - } - ret.push(chr); - i = i + 1; + var ret = (new Runtime.UTF8Processor()).processJSString(stringy); + if (length) { + ret.length = length; } if (!dontAddNull) { ret.push(0); @@ -776,21 +763,13 @@ Module['intArrayToString'] = intArrayToString; // Write a Javascript array to somewhere in the heap function writeStringToMemory(string, buffer, dontAddNull) { + var array = intArrayFromString(string, dontAddNull); var i = 0; - while (i < string.length) { - var chr = string.charCodeAt(i); - if (chr > 0xFF) { -#if ASSERTIONS - assert(false, 'Character code ' + chr + ' (' + string[i] + ') at offset ' + i + ' not in 0x00-0xFF.'); -#endif - chr &= 0xFF; - } + while (i < array.length) { + var chr = array[i]; {{{ makeSetValue('buffer', 'i', 'chr', 'i8') }}} i = i + 1; } - if (!dontAddNull) { - {{{ makeSetValue('buffer', 'i', '0', 'i8') }}} - } } Module['writeStringToMemory'] = writeStringToMemory; diff --git a/src/runtime.js b/src/runtime.js index 1f8a618f..6defbb35 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -334,6 +334,51 @@ var Runtime = { return Runtime.funcWrappers[func]; }, + // Returns a processor of UTF. + // processCChar() receives characters from a C-like UTF representation and returns JS string fragments. + // processJSString() receives a JS string and returns a C-like UTF representation in an array + UTF8Processor: function() { + var buffer = []; + var needed = 0; + this.processCChar = function (code) { + code = code & 0xff; + if (needed) { + buffer.push(code); + needed--; + } + if (buffer.length == 0) { + if (code < 128) return String.fromCharCode(code); + buffer.push(code); + if (code > 191 && code < 224) { + needed = 1; + } else { + needed = 2; + } + return ''; + } + if (needed > 0) return ''; + var c1 = buffer[0]; + var c2 = buffer[1]; + var c3 = buffer[2]; + var ret; + if (c1 > 191 && c1 < 224) { + ret = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63)); + } else { + ret = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); + } + buffer.length = 0; + return ret; + } + this.processJSString = function(string) { + string = unescape(encodeURIComponent(string)); + var ret = []; + for (var i = 0; i < string.length; i++) { + ret.push(string.charCodeAt(i)); + } + return ret; + } + }, + #if RUNTIME_DEBUG debug: true, // Switch to false at runtime to disable logging at the right times diff --git a/src/settings.js b/src/settings.js index 2526081b..16c28529 100644 --- a/src/settings.js +++ b/src/settings.js @@ -639,7 +639,7 @@ var C_DEFINES = {'SI_MESGQ': '5', 'SING': '2', 'M_INVLN2': '1.44269504089', 'SDL_TIMERS_DISABLED': '1', - 'M_TWOPI': '3.14159265359', + 'M_TWOPI': '6.28318530718', '_PC_REC_XFER_ALIGN': '19', '_NL_TIME_DATE_FMT': '84', '_SC_REALTIME_SIGNALS': '29', |