aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/analyzer.js59
-rw-r--r--[-rwxr-xr-x]src/embind/embind.js0
-rw-r--r--[-rwxr-xr-x]src/embind/emval.js0
-rw-r--r--src/library.js131
-rw-r--r--src/modules.js3
-rw-r--r--src/settings.js4
6 files changed, 143 insertions, 54 deletions
diff --git a/src/analyzer.js b/src/analyzer.js
index 03d44cb7..3f9025da 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -99,7 +99,66 @@ function analyzer(data, sidePass) {
}
}
delete item.items;
+ this.forwardItem(item, 'CastAway');
+ }
+ });
+
+ // CastAway - try to remove bitcasts of double to i64, which LLVM sometimes generates unnecessarily
+ // (load a double, convert to i64, use as i64).
+ // We optimize this by checking if the value is later converted to an i64. If so we create a shadow
+ // variable that is a load of an i64, and use that in those places. (As SSA, this is valid, and
+ // variable elimination later will remove the double load if it is no longer needed.)
+ //
+ substrate.addActor('CastAway', {
+ processItem: function(item) {
this.forwardItem(item, 'Legalizer');
+ if (USE_TYPED_ARRAYS != 2) return;
+
+ item.functions.forEach(function(func) {
+ var changed = false;
+ func.labels.forEach(function(label) {
+ var doubleVars = {};
+ var lines = label.lines;
+ var i = 0;
+ while (i < lines.length) {
+ var line = lines[i];
+ if (line.intertype == 'load' && line.type == 'double') {
+ doubleVars[line.assignTo] = i;
+ } else if (line.intertype == 'bitcast' && line.type == 'i64' && line.ident in doubleVars) {
+ // this is a bitcast of a loaded double into an i64. create shadow var
+ var shadow = line.ident + '$$i64doubleSHADOW';
+ var loadI = doubleVars[line.ident];
+ var load = lines[loadI];
+ if (load.pointer.intertype != 'value') { i++; continue } // TODO
+ // create shadow
+ lines.splice(loadI + 1, 0, { // this element will be legalized in the next phase
+ tokens: null,
+ indent: 2,
+ lineNum: load.lineNum + 0.5,
+ assignTo: shadow,
+ intertype: 'load',
+ pointerType: 'i64*',
+ type: 'i64',
+ valueType: 'i64',
+ pointer: {
+ intertype: 'value',
+ ident: load.pointer.ident,
+ type: 'i64*'
+ },
+ align: load.align,
+ ident: load.ident
+ });
+ // use shadow
+ line.params[0].ident = shadow;
+ line.params[0].type = 'i64';
+ line.type2 = 'i64';
+ // note: no need to update func.lines, it is generated in a later pass
+ i++;
+ }
+ i++;
+ }
+ });
+ });
}
});
diff --git a/src/embind/embind.js b/src/embind/embind.js
index cadee700..cadee700 100755..100644
--- a/src/embind/embind.js
+++ b/src/embind/embind.js
diff --git a/src/embind/emval.js b/src/embind/emval.js
index c02ffa92..c02ffa92 100755..100644
--- a/src/embind/emval.js
+++ b/src/embind/emval.js
diff --git a/src/library.js b/src/library.js
index cfe83c6e..6bfb49ef 100644
--- a/src/library.js
+++ b/src/library.js
@@ -296,74 +296,97 @@ LibraryManager.library = {
if (typeof XMLHttpRequest !== 'undefined') {
if (!ENVIRONMENT_IS_WORKER) throw 'Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc';
// Lazy chunked Uint8Array (implements get and length from Uint8Array). Actual getting is abstracted away for eventual reuse.
- var LazyUint8Array = function(chunkSize, length) {
- this.length = length;
- this.chunkSize = chunkSize;
+ var LazyUint8Array = function() {
+ this.lengthKnown = false;
this.chunks = []; // Loaded chunks. Index is the chunk number
}
LazyUint8Array.prototype.get = function(idx) {
if (idx > this.length-1 || idx < 0) {
return undefined;
}
- var chunkOffset = idx % chunkSize;
- var chunkNum = Math.floor(idx / chunkSize);
+ var chunkOffset = idx % this.chunkSize;
+ var chunkNum = Math.floor(idx / this.chunkSize);
return this.getter(chunkNum)[chunkOffset];
}
LazyUint8Array.prototype.setDataGetter = function(getter) {
this.getter = getter;
}
-
- // Find length
- var xhr = new XMLHttpRequest();
- xhr.open('HEAD', url, false);
- xhr.send(null);
- if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status);
- var datalength = Number(xhr.getResponseHeader("Content-length"));
- var header;
- var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes";
+
+ LazyUint8Array.prototype.cacheLength = function() {
+ // Find length
+ var xhr = new XMLHttpRequest();
+ xhr.open('HEAD', url, false);
+ xhr.send(null);
+ if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status);
+ var datalength = Number(xhr.getResponseHeader("Content-length"));
+ var header;
+ var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes";
#if SMALL_XHR_CHUNKS
- var chunkSize = 1024; // Chunk size in bytes
+ var chunkSize = 1024; // Chunk size in bytes
#else
- var chunkSize = 1024*1024; // Chunk size in bytes
+ var chunkSize = 1024*1024; // Chunk size in bytes
#endif
- if (!hasByteServing) chunkSize = datalength;
-
- // Function to get a range from the remote URL.
- var doXHR = (function(from, to) {
- if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!");
- if (to > datalength-1) throw new Error("only " + datalength + " bytes available! programmer error!");
-
- // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available.
- var xhr = new XMLHttpRequest();
- xhr.open('GET', url, false);
- if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to);
-
- // Some hints to the browser that we want binary data.
- if (typeof Uint8Array != 'undefined') xhr.responseType = 'arraybuffer';
- if (xhr.overrideMimeType) {
- xhr.overrideMimeType('text/plain; charset=x-user-defined');
- }
+ if (!hasByteServing) chunkSize = datalength;
+
+ // Function to get a range from the remote URL.
+ var doXHR = (function(from, to) {
+ if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!");
+ if (to > datalength-1) throw new Error("only " + datalength + " bytes available! programmer error!");
+
+ // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available.
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', url, false);
+ if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to);
+
+ // Some hints to the browser that we want binary data.
+ if (typeof Uint8Array != 'undefined') xhr.responseType = 'arraybuffer';
+ if (xhr.overrideMimeType) {
+ xhr.overrideMimeType('text/plain; charset=x-user-defined');
+ }
+
+ xhr.send(null);
+ if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status);
+ if (xhr.response !== undefined) {
+ return new Uint8Array(xhr.response || []);
+ } else {
+ return intArrayFromString(xhr.responseText || '', true);
+ }
+ });
+ var lazyArray = this;
+ lazyArray.setDataGetter(function(chunkNum) {
+ var start = chunkNum * chunkSize;
+ var end = (chunkNum+1) * chunkSize - 1; // including this byte
+ end = Math.min(end, datalength-1); // if datalength-1 is selected, this is the last block
+ if (typeof(lazyArray.chunks[chunkNum]) === "undefined") {
+ lazyArray.chunks[chunkNum] = doXHR(start, end);
+ }
+ if (typeof(lazyArray.chunks[chunkNum]) === "undefined") throw new Error("doXHR failed!");
+ return lazyArray.chunks[chunkNum];
+ });
+
+ this._length = datalength;
+ this._chunkSize = chunkSize;
+ this.lengthKnown = true;
+ }
- xhr.send(null);
- if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status);
- if (xhr.response !== undefined) {
- return new Uint8Array(xhr.response || []);
- } else {
- return intArrayFromString(xhr.responseText || '', true);
- }
+ var lazyArray = new LazyUint8Array();
+ Object.defineProperty(lazyArray, "length", {
+ get: function() {
+ if(!this.lengthKnown) {
+ this.cacheLength();
+ }
+ return this._length;
+ }
});
-
- var lazyArray = new LazyUint8Array(chunkSize, datalength);
- lazyArray.setDataGetter(function(chunkNum) {
- var start = chunkNum * lazyArray.chunkSize;
- var end = (chunkNum+1) * lazyArray.chunkSize - 1; // including this byte
- end = Math.min(end, datalength-1); // if datalength-1 is selected, this is the last block
- if (typeof(lazyArray.chunks[chunkNum]) === "undefined") {
- lazyArray.chunks[chunkNum] = doXHR(start, end);
- }
- if (typeof(lazyArray.chunks[chunkNum]) === "undefined") throw new Error("doXHR failed!");
- return lazyArray.chunks[chunkNum];
+ Object.defineProperty(lazyArray, "chunkSize", {
+ get: function() {
+ if(!this.lengthKnown) {
+ this.cacheLength();
+ }
+ return this._chunkSize;
+ }
});
+
var properties = { isDevice: false, contents: lazyArray };
} else {
var properties = { isDevice: false, url: url };
@@ -2465,9 +2488,15 @@ LibraryManager.library = {
__scanString.whiteSpace[{{{ charCode(' ') }}}] = 1;
__scanString.whiteSpace[{{{ charCode('\t') }}}] = 1;
__scanString.whiteSpace[{{{ charCode('\n') }}}] = 1;
+ __scanString.whiteSpace[{{{ charCode('\v') }}}] = 1;
+ __scanString.whiteSpace[{{{ charCode('\f') }}}] = 1;
+ __scanString.whiteSpace[{{{ charCode('\r') }}}] = 1;
__scanString.whiteSpace[' '] = 1;
__scanString.whiteSpace['\t'] = 1;
__scanString.whiteSpace['\n'] = 1;
+ __scanString.whiteSpace['\v'] = 1;
+ __scanString.whiteSpace['\f'] = 1;
+ __scanString.whiteSpace['\r'] = 1;
}
// Supports %x, %4x, %d.%d, %lld, %s, %f, %lf.
// TODO: Support all format specifiers.
diff --git a/src/modules.js b/src/modules.js
index 9cbe88aa..6b3c5ffb 100644
--- a/src/modules.js
+++ b/src/modules.js
@@ -259,7 +259,7 @@ var Functions = {
}
if (phase != 'post' && singlePhase) {
if (!doNotCreate) this.indexedFunctions[ident] = 0; // tell python we need this indexized
- return "'{{ FI_" + ident + " }}'"; // something python will replace later
+ return "'{{ FI_" + toNiceIdent(ident) + " }}'"; // something python will replace later
} else {
var ret = this.indexedFunctions[ident];
if (!ret) {
@@ -318,6 +318,7 @@ var Functions = {
if (ASM_JS) {
var curr = table[i];
if (curr && curr != '0' && !Functions.implementedFunctions[curr]) {
+ curr = toNiceIdent(curr); // fix Math.* to Math_*
// This is a library function, we can't just put it in the function table, need a wrapper
if (!wrapped[curr]) {
var args = '', arg_coercions = '', call = curr + '(', retPre = '', retPost = '';
diff --git a/src/settings.js b/src/settings.js
index ba1f6a83..d029598a 100644
--- a/src/settings.js
+++ b/src/settings.js
@@ -17,8 +17,8 @@ var QUANTUM_SIZE = 4; // This is the size of an individual field in a structure.
//
// Changing this from the default of 4 is deprecated.
-var TARGET_X86 = 1; // For le32-unknown-nacl
-var TARGET_LE32 = 0; // For i386-pc-linux-gnu
+var TARGET_X86 = 0; // For i386-pc-linux-gnu
+var TARGET_LE32 = 1; // For le32-unknown-nacl
var CORRECT_SIGNS = 1; // Whether we make sure to convert unsigned values to signed values.
// Decreases performance with additional runtime checks. Might not be