aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/analyzer.js97
-rw-r--r--src/compiler.js11
-rw-r--r--src/intertyper.js25
-rw-r--r--src/jsifier.js2
-rw-r--r--src/library_browser.js1
-rw-r--r--src/modules.js6
-rw-r--r--src/parseTools.js14
-rw-r--r--src/postamble.js1
8 files changed, 107 insertions, 50 deletions
diff --git a/src/analyzer.js b/src/analyzer.js
index 17ad26ad..23bc81b4 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -802,27 +802,65 @@ function analyzer(data, sidePass) {
var whole = shifts >= 0 ? Math.floor(shifts/32) : Math.ceil(shifts/32);
var fraction = Math.abs(shifts % 32);
if (signed) {
- var signedFill = '(' + makeSignOp(sourceElements[sourceElements.length-1].ident, 'i' + sourceElements[sourceElements.length-1].bits, 're', 1, 1) + ' < 0 ? -1 : 0)';
- var signedKeepAlive = { intertype: 'value', ident: sourceElements[sourceElements.length-1].ident, type: 'i32' };
- }
- for (var j = 0; j < targetElements.length; j++) {
- var result = {
- intertype: 'value',
- ident: (j + whole >= 0 && j + whole < sourceElements.length) ? sourceElements[j + whole].ident : (signed ? signedFill : '0'),
- params: [(signed && j + whole > sourceElements.length) ? signedKeepAlive : null],
+ var signedFill = {
+ intertype: 'mathop',
+ op: 'select',
+ variant: 's',
type: 'i32',
+ params: [{
+ intertype: 'mathop',
+ op: 'icmp',
+ variant: 'slt',
+ type: 'i32',
+ params: [
+ { intertype: 'value', ident: sourceElements[sourceElements.length-1].ident, type: 'i' + Math.min(sourceBits, 32) },
+ { intertype: 'value', ident: '0', type: 'i32' }
+ ]
+ },
+ { intertype: 'value', ident: '-1', type: 'i32' },
+ { intertype: 'value', ident: '0', type: 'i32' },
+ ]
};
- if (j == 0 && sourceBits < 32) {
- // zext sign correction
- result.ident = makeSignOp(result.ident, 'i' + sourceBits, isUnsignedOp(value.op) ? 'un' : 're', 1, 1);
- }
- if (fraction != 0) {
- var other = {
+ }
+ for (var j = 0; j < targetElements.length; j++) {
+ var inBounds = j + whole >= 0 && j + whole < sourceElements.length;
+ var result;
+ if (inBounds || !signed) {
+ result = {
intertype: 'value',
- ident: (j + sign + whole >= 0 && j + sign + whole < sourceElements.length) ? sourceElements[j + sign + whole].ident : (signed ? signedFill : '0'),
- params: [(signed && j + sign + whole > sourceElements.length) ? signedKeepAlive : null],
- type: 'i32',
+ ident: inBounds ? sourceElements[j + whole].ident : '0',
+ type: 'i' + Math.min(sourceBits, 32),
};
+ if (j == 0 && sourceBits < 32) {
+ // zext sign correction
+ var result2 = {
+ intertype: 'mathop',
+ op: isUnsignedOp(value.op) ? 'zext' : 'sext',
+ params: [result, {
+ intertype: 'type',
+ ident: 'i32',
+ type: 'i' + sourceBits
+ }],
+ type: 'i32'
+ };
+ result = result2;
+ }
+ } else {
+ // out of bounds and signed
+ result = copy(signedFill);
+ }
+ if (fraction != 0) {
+ var other;
+ var otherInBounds = j + sign + whole >= 0 && j + sign + whole < sourceElements.length;
+ if (otherInBounds || !signed) {
+ other = {
+ intertype: 'value',
+ ident: otherInBounds ? sourceElements[j + sign + whole].ident : '0',
+ type: 'i32',
+ };
+ } else {
+ other = copy(signedFill);
+ }
other = {
intertype: 'mathop',
op: shiftOp,
@@ -872,10 +910,17 @@ function analyzer(data, sidePass) {
}
if (targetBits <= 32) {
// We are generating a normal legal type here
- legalValue = {
- intertype: 'value',
- ident: targetElements[0].ident + (targetBits < 32 ? '&' + (Math.pow(2, targetBits)-1) : ''),
- type: 'rawJS'
+ legalValue = { intertype: 'value', ident: targetElements[0].ident, type: 'i32' };
+ if (targetBits < 32) {
+ legalValue = {
+ intertype: 'mathop',
+ op: 'and',
+ type: 'i32',
+ params: [
+ legalValue,
+ { intertype: 'value', ident: (Math.pow(2, targetBits)-1).toString(), type: 'i32' }
+ ]
+ }
};
legalValue.assignTo = item.assignTo;
toAdd.push(legalValue);
@@ -1117,7 +1162,7 @@ function analyzer(data, sidePass) {
rawLinesIndex: i
};
if (variable.origin === 'alloca') {
- variable.allocatedNum = item.allocatedNum;
+ variable.allocatedNum = item.ident;
}
if (variable.origin === 'call') {
variable.type = getReturnType(variable.type);
@@ -1608,9 +1653,9 @@ function analyzer(data, sidePass) {
var lines = func.labels[0].lines;
for (var i = 0; i < lines.length; i++) {
var item = lines[i];
- if (!item.assignTo || item.intertype != 'alloca' || !isNumber(item.allocatedNum)) break;
+ if (!item.assignTo || item.intertype != 'alloca' || !isNumber(item.ident)) break;
item.allocatedSize = func.variables[item.assignTo].impl === VAR_EMULATED ?
- calcAllocatedSize(item.allocatedType)*item.allocatedNum: 0;
+ calcAllocatedSize(item.allocatedType)*item.ident: 0;
if (USE_TYPED_ARRAYS === 2) {
// We need to keep the stack aligned
item.allocatedSize = Runtime.forceAlign(item.allocatedSize, Runtime.STACK_ALIGN);
@@ -1619,7 +1664,7 @@ function analyzer(data, sidePass) {
var index = 0;
for (var i = 0; i < lines.length; i++) {
var item = lines[i];
- if (!item.assignTo || item.intertype != 'alloca' || !isNumber(item.allocatedNum)) break;
+ if (!item.assignTo || item.intertype != 'alloca' || !isNumber(item.ident)) break;
item.allocatedIndex = index;
index += item.allocatedSize;
delete item.allocatedSize;
@@ -1647,7 +1692,7 @@ function analyzer(data, sidePass) {
for (var i = 0; i < lines.length; i++) {
var item = lines[i];
- if (!finishedInitial && (!item.assignTo || item.intertype != 'alloca' || !isNumber(item.allocatedNum))) {
+ if (!finishedInitial && (!item.assignTo || item.intertype != 'alloca' || !isNumber(item.ident))) {
finishedInitial = true;
}
if (item.intertype == 'alloca' && finishedInitial) {
diff --git a/src/compiler.js b/src/compiler.js
index 90060837..d490f454 100644
--- a/src/compiler.js
+++ b/src/compiler.js
@@ -185,7 +185,6 @@ if (SAFE_HEAP) USE_BSS = 0; // must initialize heap for safe heap
assert(!(USE_TYPED_ARRAYS === 2 && QUANTUM_SIZE !== 4), 'For USE_TYPED_ARRAYS == 2, must have normal QUANTUM_SIZE of 4');
if (ASM_JS) {
assert(!ALLOW_MEMORY_GROWTH, 'Cannot grow asm.js heap');
- assert((TOTAL_MEMORY&(TOTAL_MEMORY-1)) == 0, 'asm.js heap must be power of 2');
}
assert(!(!NAMED_GLOBALS && BUILD_AS_SHARED_LIB), 'shared libraries must have named globals');
@@ -207,7 +206,12 @@ if (phase == 'pre') {
if (VERBOSE) printErr('VERBOSE is on, this generates a lot of output and can slow down compilation');
// Load struct and define information.
-var temp = JSON.parse(read(STRUCT_INFO));
+try {
+ var temp = JSON.parse(read(STRUCT_INFO));
+} catch(e) {
+ printErr('cannot load struct info at ' + STRUCT_INFO + ' : ' + e + ', trying in current dir');
+ temp = JSON.parse(read('struct_info.compiled.json'));
+}
C_STRUCTS = temp.structs;
C_DEFINES = temp.defines;
@@ -312,3 +316,6 @@ 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)));
+
diff --git a/src/intertyper.js b/src/intertyper.js
index 09bdaa33..ac9a365f 100644
--- a/src/intertyper.js
+++ b/src/intertyper.js
@@ -5,6 +5,11 @@
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 } });
+
+//var tokenCacheMisses = {};
+
// Line tokenizer
function tokenizer(item, inner) {
//assert(item.lineNum != 40000);
@@ -12,7 +17,6 @@ function tokenizer(item, inner) {
var tokens = [];
var quotes = 0;
var lastToken = null;
- var CHUNKSIZE = 64; // How much forward to peek forward. Too much means too many string segments copied
// Note: '{' is not an encloser, as its use in functions is split over many lines
var enclosers = {
'[': 0,
@@ -31,6 +35,15 @@ function tokenizer(item, inner) {
return;
}
+ var cached = tokenCache[text];
+ if (cached) {
+ //assert(cached.text === text);
+ tokens.push(cached);
+ lastToken = cached;
+ return;
+ }
+ //tokenCacheMisses[text] = (misses[text] || 0) + 1;
+
var token = {
text: text
};
@@ -42,6 +55,10 @@ function tokenizer(item, inner) {
}
// merge certain tokens
if (lastToken && isType(lastToken.text) && isFunctionDef(token)) {
+ if (lastToken.text in tokenCache) {
+ // create a copy of the cached value
+ lastToken = tokens[tokens.length-1] = { text: lastToken.text };
+ }
lastToken.text += ' ' + text;
} else if (lastToken && text[0] == '}') { // }, }*, etc.
var openBrace = tokens.length-1;
@@ -766,15 +783,13 @@ function intertyper(lines, sidePass, baseLineNums) {
return item;
}
// 'alloca'
- var allocaPossibleVars = ['allocatedNum'];
function allocaHandler(item) {
item.intertype = 'alloca';
item.allocatedType = item.tokens[1].text;
if (item.tokens.length > 3 && Runtime.isNumberType(item.tokens[3].text)) {
- item.allocatedNum = toNiceIdent(item.tokens[4].text);
- item.possibleVars = allocaPossibleVars;
+ item.ident = toNiceIdent(item.tokens[4].text);
} else {
- item.allocatedNum = 1;
+ item.ident = 1;
}
item.type = addPointing(item.tokens[1].text); // type of pointer we will get
Types.needAnalysis[item.type] = 0;
diff --git a/src/jsifier.js b/src/jsifier.js
index 0e5f8ef3..e7cc3683 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -1361,7 +1361,7 @@ function JSify(data, functionsOnly, givenFunctions) {
if (item.allocatedSize === 0) return ''; // This will not actually be shown - it's nativized
return asmCoercion(getFastValue('sp', '+', item.allocatedIndex.toString()), 'i32');
} else {
- return RuntimeGenerator.stackAlloc(getFastValue(calcAllocatedSize(item.allocatedType), '*', item.allocatedNum));
+ return RuntimeGenerator.stackAlloc(getFastValue(calcAllocatedSize(item.allocatedType), '*', item.ident));
}
}
function va_argHandler(item) {
diff --git a/src/library_browser.js b/src/library_browser.js
index cba8ecdf..dd60a581 100644
--- a/src/library_browser.js
+++ b/src/library_browser.js
@@ -749,6 +749,7 @@ mergeInto(LibraryManager.library, {
if (e instanceof ExitStatus) {
return;
} else {
+ if (e && typeof e === 'object' && e.stack) Module.printErr('exception thrown: ' + [e, e.stack]);
throw e;
}
}
diff --git a/src/modules.js b/src/modules.js
index cc9ca549..76e5db11 100644
--- a/src/modules.js
+++ b/src/modules.js
@@ -285,11 +285,7 @@ var Functions = {
} else {
if (!singlePhase) return 'NO_INDEX'; // Should not index functions in post
ret = this.indexedFunctions[ident];
- if (!ret) {
- ret = this.nextIndex;
- this.nextIndex += FUNCTION_POINTER_ALIGNMENT;
- this.indexedFunctions[ident] = ret;
- }
+ assert(ret);
ret = ret.toString();
}
if (SIDE_MODULE && sig) { // sig can be undefined for the GL library functions
diff --git a/src/parseTools.js b/src/parseTools.js
index addf0f21..1f875584 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -914,13 +914,13 @@ function parseI64Constant(str, legalized) {
}
function parseNumerical(value, type) {
- if ((!type || type == 'double' || type == 'float') && (value.substr && value.substr(0,2) == '0x')) {
+ if ((!type || type === 'double' || type === 'float') && /^0x/.test(value)) {
// Hexadecimal double value, as the llvm docs say,
// "The one non-intuitive notation for constants is the hexadecimal form of floating point constants."
value = IEEEUnHex(value);
} else if (USE_TYPED_ARRAYS == 2 && isIllegalType(type)) {
return value; // do not parseFloat etc., that can lead to loss of precision
- } else if (value == 'null') {
+ } else if (value === 'null') {
// NULL *is* 0, in C/C++. No JS null! (null == 0 is false, etc.)
value = '0';
} else if (value === 'true') {
@@ -930,7 +930,7 @@ function parseNumerical(value, type) {
}
if (isNumber(value)) {
var ret = parseFloat(value); // will change e.g. 5.000000e+01 to 50
- if (type in Runtime.FLOAT_TYPES) {
+ if (type === 'double' || type === 'float') {
if (value[0] === '-' && ret === 0) return '-.0'; // fix negative 0, toString makes it 0
if (!RUNNING_JS_OPTS) ret = asmEnsureFloat(ret, type);
}
@@ -2474,13 +2474,6 @@ function walkInterdata(item, pre, post, obj) {
if (walkInterdata(item.params[i], pre, post, obj)) return true;
}
}
- if (item.possibleVars) { // other attributes that might contain interesting data; here, variables
- var box = { intertype: 'value', ident: '' };
- for (i = 0; i <= item.possibleVars.length; i++) {
- box.ident = item[item.possibleVars[i]];
- if (walkInterdata(box, pre, post, obj)) return true;
- }
- }
return post && post(item, originalObj, obj);
}
@@ -2500,7 +2493,6 @@ function walkAndModifyInterdata(item, pre) {
if (repl = walkAndModifyInterdata(item.params[i], pre)) item.params[i] = repl;
}
}
- // Ignore possibleVars because we can't replace them anyhow
}
function parseBlockAddress(segment) {
diff --git a/src/postamble.js b/src/postamble.js
index cd892733..62edeeb6 100644
--- a/src/postamble.js
+++ b/src/postamble.js
@@ -96,6 +96,7 @@ Module['callMain'] = Module.callMain = function callMain(args) {
Module['noExitRuntime'] = true;
return;
} else {
+ if (e && typeof e === 'object' && e.stack) Module.printErr('exception thrown: ' + [e, e.stack]);
throw e;
}
} finally {