aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2012-03-03 12:03:48 -0800
committerAlon Zakai <alonzakai@gmail.com>2012-03-03 12:03:48 -0800
commitd6cff2177ec065aa14f228ab547abc29ef37b248 (patch)
tree285c3d737500e8a3ed6be56dcaf9357ffd5c7cd9 /src
parentdfd9488e0094a6b5433b406517338e0f757c1e27 (diff)
parent6f57ea8f0eeb220fc81726b4e3a3c02f4232b667 (diff)
Merge branch 'master' into llvmsvn
Diffstat (limited to 'src')
-rw-r--r--src/analyzer.js212
-rw-r--r--src/compiler.js22
-rw-r--r--src/intertyper.js38
-rw-r--r--src/jsifier.js52
-rw-r--r--src/library.js161
-rw-r--r--src/modules.js2
-rw-r--r--src/parseTools.js292
-rw-r--r--src/preamble.js43
-rw-r--r--src/settings.js6
-rw-r--r--src/shell.js19
10 files changed, 539 insertions, 308 deletions
diff --git a/src/analyzer.js b/src/analyzer.js
index 14a4f7de..8ded86f1 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -120,10 +120,6 @@ function analyzer(data, sidePass) {
processItem: function(data) {
// Legalization
if (USE_TYPED_ARRAYS == 2) {
- function isIllegalType(type) {
- var bits = getBits(type);
- return bits > 0 && (bits >= 64 || !isPowerOfTwo(bits));
- }
function getLegalVars(base, bits) {
assert(!isNumber(base));
var ret = new Array(Math.ceil(bits/32));
@@ -140,7 +136,7 @@ function analyzer(data, sidePass) {
var ret = new Array(Math.ceil(bits/32));
var i = 0;
while (bits > 0) {
- ret[i] = { ident: parsed[i].toString(), bits: Math.min(32, bits) };
+ ret[i] = { ident: (parsed[i]|0).toString(), bits: Math.min(32, bits) }; // resign all values
bits -= 32;
i++;
}
@@ -182,6 +178,13 @@ function analyzer(data, sidePass) {
i++;
}
}
+ function fixUnfolded(item) {
+ // Unfolded items may need some correction to work properly in the global scope
+ if (item.intertype in MATHOPS) {
+ item.op = item.intertype;
+ item.intertype = 'mathop';
+ }
+ }
data.functions.forEach(function(func) {
// Legalize function params
legalizeFunctionParameters(func.params);
@@ -218,10 +221,29 @@ function analyzer(data, sidePass) {
// accessible through ident$x, and not constants we need to parse then and there)
if (subItem != item && (!(subItem.intertype in UNUNFOLDABLE) ||
(subItem.intertype == 'value' && isNumber(subItem.ident) && isIllegalType(subItem.type)))) {
- var tempIdent = '$$emscripten$temp$' + (tempId++);
- subItem.assignTo = tempIdent;
- unfolded.unshift(subItem);
- return { intertype: 'value', ident: tempIdent, type: subItem.type };
+ if (item.intertype == 'phi') {
+ assert(subItem.intertype == 'value', 'We can only unfold illegal constants in phis');
+ // we must handle this in the phi itself, if we unfold normally it will not be pushed back with the phi
+ } else {
+ var tempIdent = '$$emscripten$temp$' + (tempId++);
+ subItem.assignTo = tempIdent;
+ unfolded.unshift(subItem);
+ fixUnfolded(subItem);
+ return { intertype: 'value', ident: tempIdent, type: subItem.type };
+ }
+ } else if (subItem.intertype == 'switch' && isIllegalType(subItem.type)) {
+ subItem.switchLabels.forEach(function(switchLabel) {
+ if (switchLabel.value[0] != '$') {
+ var tempIdent = '$$emscripten$temp$' + (tempId++);
+ unfolded.unshift({
+ assignTo: tempIdent,
+ intertype: 'value',
+ ident: switchLabel.value,
+ type: subItem.type
+ });
+ switchLabel.value = tempIdent;
+ }
+ });
}
});
if (unfolded.length > 0) {
@@ -268,7 +290,7 @@ function analyzer(data, sidePass) {
continue;
}
// call, return: Return value is in an unlegalized array literal. Not fully optimal.
- case 'call': case 'invoke': {
+ case 'call': {
bits = getBits(value.type);
var elements = getLegalVars(item.assignTo, bits);
var toAdd = [value];
@@ -296,6 +318,12 @@ function analyzer(data, sidePass) {
i++;
continue;
}
+ case 'invoke': {
+ legalizeFunctionParameters(value.params);
+ // We can't add lines after this, since invoke already modifies control flow. So we handle the return in invoke
+ i++;
+ continue;
+ }
case 'value': {
bits = getBits(value.type);
var elements = getLegalVars(item.assignTo, bits);
@@ -353,6 +381,12 @@ function analyzer(data, sidePass) {
var toAdd = [];
var elements = getLegalVars(item.assignTo, bits);
var j = 0;
+ var literalValues = {}; // special handling of literals - we cannot unfold them normally
+ value.params.map(function(param) {
+ if (isNumber(param.value.ident)) {
+ literalValues[param.value.ident] = getLegalLiterals(param.value.ident, bits);
+ }
+ });
elements.forEach(function(element) {
toAdd.push({
intertype: 'phi',
@@ -364,7 +398,7 @@ function analyzer(data, sidePass) {
label: param.label,
value: {
intertype: 'value',
- ident: param.value.ident + '$' + j,
+ ident: (param.value.ident in literalValues) ? literalValues[param.value.ident][j].ident : (param.value.ident + '$' + j),
type: 'i' + element.bits,
}
};
@@ -375,6 +409,10 @@ function analyzer(data, sidePass) {
i += removeAndAdd(label.lines, i, toAdd);
continue;
}
+ case 'switch': {
+ i++;
+ continue; // special case, handled in makeComparison
+ }
case 'bitcast': {
var inType = item.type2;
var outType = item.type;
@@ -385,16 +423,18 @@ function analyzer(data, sidePass) {
}
// fall through
}
- case 'inttoptr': case 'ptrtoint': {
+ case 'inttoptr': case 'ptrtoint': case 'zext': case 'sext': case 'trunc': case 'ashr': case 'lshr': case 'shl': case 'or': case 'and': case 'xor': {
value = {
op: item.intertype,
- param1: item.params[0]
+ variant: item.variant,
+ type: item.type,
+ params: item.params
};
// fall through
}
case 'mathop': {
var toAdd = [];
- var sourceBits = getBits(value.param1.type);
+ var sourceBits = getBits(value.params[0].type);
// All mathops can be parametrized by how many shifts we do, and how big the source is
var shifts = 0;
var targetBits = sourceBits;
@@ -406,11 +446,11 @@ function analyzer(data, sidePass) {
// fall through
}
case 'lshr': {
- shifts = parseInt(value.param2.ident);
+ shifts = parseInt(value.params[1].ident);
break;
}
case 'shl': {
- shifts = -parseInt(value.param2.ident);
+ shifts = -parseInt(value.params[1].ident);
break;
}
case 'sext': {
@@ -418,7 +458,7 @@ function analyzer(data, sidePass) {
// fall through
}
case 'trunc': case 'zext': case 'ptrtoint': {
- targetBits = getBits(value.param2.ident);
+ targetBits = getBits(value.params[1] ? value.params[1].ident : value.type);
break;
}
case 'inttoptr': {
@@ -429,31 +469,35 @@ function analyzer(data, sidePass) {
break;
}
case 'select': {
- sourceBits = targetBits = getBits(value.param2.type);
- var otherElementsA = getLegalVars(value.param2.ident, sourceBits);
- var otherElementsB = getLegalVars(value.param3.ident, sourceBits);
+ sourceBits = targetBits = getBits(value.params[1].type);
+ var otherElementsA = getLegalVars(value.params[1].ident, sourceBits);
+ var otherElementsB = getLegalVars(value.params[2].ident, sourceBits);
processor = function(result, j) {
return {
intertype: 'mathop',
op: 'select',
type: 'i' + otherElementsA[j].bits,
- param1: value.param1,
- param2: { intertype: 'value', ident: otherElementsA[j].ident, type: 'i' + otherElementsA[j].bits },
- param3: { intertype: 'value', ident: otherElementsB[j].ident, type: 'i' + otherElementsB[j].bits }
+ params: [
+ value.params[0],
+ { intertype: 'value', ident: otherElementsA[j].ident, type: 'i' + otherElementsA[j].bits },
+ { intertype: 'value', ident: otherElementsB[j].ident, type: 'i' + otherElementsB[j].bits }
+ ]
};
};
break;
}
case 'or': case 'and': case 'xor': {
- var otherElements = getLegalVars(value.param2.ident, sourceBits);
+ var otherElements = getLegalVars(value.params[1].ident, sourceBits);
processor = function(result, j) {
return {
intertype: 'mathop',
op: value.op,
type: 'i' + otherElements[j].bits,
- param1: result,
- param2: { intertype: 'value', ident: otherElements[j].ident, type: 'i' + otherElements[j].bits }
- };
+ params: [
+ result,
+ { intertype: 'value', ident: otherElements[j].ident, type: 'i' + otherElements[j].bits }
+ ]
+ };
};
break;
}
@@ -469,16 +513,16 @@ function analyzer(data, sidePass) {
var sourceElements;
if (sourceBits <= 32) {
// The input is a legal type
- sourceElements = [{ ident: value.param1.ident, bits: sourceBits }];
+ sourceElements = [{ ident: value.params[0].ident, bits: sourceBits }];
} else {
- sourceElements = getLegalVars(value.param1.ident, sourceBits);
+ sourceElements = getLegalVars(value.params[0].ident, sourceBits);
}
if (!isNumber(shifts)) {
// We can't statically legalize this, do the operation at runtime TODO: optimize
assert(sourceBits == 64, 'TODO: handle nonconstant shifts on != 64 bits');
value.intertype = 'value';
value.ident = 'Runtime.bitshift64(' + sourceElements[0].ident + ', ' +
- sourceElements[1].ident + ',"' + value.op + '",' + value.param2.ident + '$0);' +
+ sourceElements[1].ident + ',"' + value.op + '",' + value.params[1].ident + '$0);' +
'var ' + value.assignTo + '$0 = ' + value.assignTo + '[0], ' + value.assignTo + '$1 = ' + value.assignTo + '[1];';
i++;
continue;
@@ -497,37 +541,43 @@ function analyzer(data, sidePass) {
var result = {
intertype: 'value',
ident: (j + whole >= 0 && j + whole < sourceElements.length) ? sourceElements[j + whole].ident : (signed ? signedFill : '0'),
- param1: (signed && j + whole > sourceElements.length) ? signedKeepAlive : null,
+ params: [(signed && j + whole > sourceElements.length) ? signedKeepAlive : null],
type: 'i32',
};
if (fraction != 0) {
var other = {
intertype: 'value',
ident: (j + sign + whole >= 0 && j + sign + whole < sourceElements.length) ? sourceElements[j + sign + whole].ident : (signed ? signedFill : '0'),
- param1: (signed && j + sign + whole > sourceElements.length) ? signedKeepAlive : null,
+ params: [(signed && j + sign + whole > sourceElements.length) ? signedKeepAlive : null],
type: 'i32',
};
other = {
intertype: 'mathop',
op: shiftOp,
type: 'i32',
- param1: other,
- param2: { intertype: 'value', ident: (32 - fraction).toString(), type: 'i32' }
+ params: [
+ other,
+ { intertype: 'value', ident: (32 - fraction).toString(), type: 'i32' }
+ ]
};
result = {
intertype: 'mathop',
// shifting in 1s from the top is a special case
op: (signed && shifts >= 0 && j + sign + whole >= sourceElements.length) ? 'ashr' : shiftOpReverse,
type: 'i32',
- param1: result,
- param2: { intertype: 'value', ident: fraction.toString(), type: 'i32' }
+ params: [
+ result,
+ { intertype: 'value', ident: fraction.toString(), type: 'i32' }
+ ]
};
result = {
intertype: 'mathop',
op: 'or',
type: 'i32',
- param1: result,
- param2: other
+ params: [
+ result,
+ other
+ ]
}
}
if (targetElements[j].bits < 32 && shifts < 0) {
@@ -536,8 +586,10 @@ function analyzer(data, sidePass) {
intertype: 'mathop',
op: 'and',
type: 'i32',
- param1: result,
- param2: { intertype: 'value', ident: (Math.pow(2, targetElements[j].bits)-1).toString(), type: 'i32' }
+ params: [
+ result,
+ { intertype: 'value', ident: (Math.pow(2, targetElements[j].bits)-1).toString(), type: 'i32' }
+ ]
}
}
if (processor) {
@@ -548,8 +600,11 @@ function analyzer(data, sidePass) {
}
if (targetBits <= 32) {
// We are generating a normal legal type here
- legalValue = { intertype: 'value', ident: targetElements[0].ident, type: 'rawJS' };
- // truncation to smaller than 32 bits has already been done, if necessary
+ legalValue = {
+ intertype: 'value',
+ ident: targetElements[0].ident + (targetBits < 32 ? '&' + (Math.pow(2, targetBits)-1) : ''),
+ type: 'rawJS'
+ };
legalValue.assignTo = item.assignTo;
toAdd.push(legalValue);
}
@@ -855,7 +910,7 @@ function analyzer(data, sidePass) {
variable.impl = VAR_EMULATED;
} else if (variable.origin == 'funcparam') {
variable.impl = VAR_EMULATED;
- } else if (variable.type == 'i64*' && I64_MODE == 1) {
+ } else if (variable.type == 'i64*' && USE_TYPED_ARRAYS == 2) {
variable.impl = VAR_EMULATED;
} else if (MICRO_OPTS && variable.pointingLevels === 0) {
// A simple int value, can be implemented as a native variable
@@ -1096,18 +1151,61 @@ function analyzer(data, sidePass) {
}
});
+ function operateOnLabels(line, func) {
+ function process(item, id) {
+ ['label', 'labelTrue', 'labelFalse', 'toLabel', 'unwindLabel', 'defaultLabel'].forEach(function(id) {
+ if (item[id]) {
+ func(item, id);
+ }
+ });
+ }
+ if (line.intertype in BRANCH_INVOKE) {
+ process(line);
+ } else if (line.intertype == 'switch') {
+ process(line);
+ line.switchLabels.forEach(process);
+ }
+ }
+
// Label analyzer
substrate.addActor('LabelAnalyzer', {
processItem: function(item) {
item.functions.forEach(function(func) {
func.labelsDict = {};
func.labelIds = {};
- func.labelIdCounter = 0;
+ func.labelIdsInverse = {};
+ func.labelIds[toNiceIdent('%0')] = 0;
+ func.labelIdsInverse[0] = toNiceIdent('%0');
+ func.labelIdCounter = 1;
func.labels.forEach(function(label) {
- func.labelsDict[label.ident] = label;
func.labelIds[label.ident] = func.labelIdCounter++;
+ func.labelIdsInverse[func.labelIdCounter-1] = label.ident;
+ });
+
+ // Minify label ids to numeric ids.
+ func.labels.forEach(function(label) {
+ label.ident = func.labelIds[label.ident];
+ label.lines.forEach(function(line) {
+ operateOnLabels(line, function(item, id) {
+ item[id] = func.labelIds[item[id]].toString(); // strings, because we will append as we process
+ });
+ });
+ });
+
+ func.labels.forEach(function(label) {
+ func.labelsDict[label.ident] = label;
+ });
+
+ // Correct phis
+ func.labels.forEach(function(label) {
+ label.lines.forEach(function(phi) {
+ if (phi.intertype == 'phi') {
+ for (var i = 0; i < phi.params.length; i++) {
+ phi.params[i].label = func.labelIds[phi.params[i].label];
+ }
+ }
+ });
});
- func.labelIds[toNiceIdent('%0')] = -1; // entry is always -1
func.lines.forEach(function(line) {
if (line.intertype == 'indirectbr') {
@@ -1136,7 +1234,7 @@ function analyzer(data, sidePass) {
if (line.intertype == 'call' && line.ident == setjmp) {
// Add a new label
var oldIdent = label.ident;
- var newIdent = oldIdent + '$$' + i;
+ var newIdent = func.labelIdCounter++;
if (!func.setjmpTable) func.setjmpTable = [];
func.setjmpTable.push([oldIdent, newIdent, line.assignTo]);
func.labels.splice(i+1, 0, {
@@ -1330,22 +1428,6 @@ function analyzer(data, sidePass) {
}
});
- function operateOnLabels(line, func) {
- function process(item, id) {
- ['label', 'labelTrue', 'labelFalse', 'toLabel', 'unwindLabel', 'defaultLabel'].forEach(function(id) {
- if (item[id]) {
- func(item, id);
- }
- });
- }
- if (line.intertype in BRANCH_INVOKE) {
- process(line);
- } else if (line.intertype == 'switch') {
- process(line);
- line.switchLabels.forEach(process);
- }
- }
-
//! @param toLabelId If false, just a dry run - useful to search for labels
function replaceLabels(line, labelIds, toLabelId) {
var ret = [];
@@ -1436,7 +1518,7 @@ function analyzer(data, sidePass) {
label.allOutLabels = [];
});
- // First, find allInLabels
+ // First, find allInLabels. TODO: use typed arrays here to optimize this for memory and speed
var more = true, nextModified, modified = set(getLabelIds(labels));
while (more) {
more = false;
@@ -1487,7 +1569,7 @@ function analyzer(data, sidePass) {
var idCounter = 0;
function makeBlockId(entries) {
idCounter++;
- return entries.join('$') + '$' + idCounter;
+ return '$_$' + idCounter;
}
// There are X main kinds of blocks:
diff --git a/src/compiler.js b/src/compiler.js
index d37bc68b..134ac5bd 100644
--- a/src/compiler.js
+++ b/src/compiler.js
@@ -19,6 +19,7 @@ var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIR
if (ENVIRONMENT_IS_NODE) {
// Expose functionality in the same simple way that the shells work
+ // Note that we pollute the global namespace here, otherwise we break in node
print = function(x) {
process['stdout'].write(x + '\n');
};
@@ -37,12 +38,16 @@ if (ENVIRONMENT_IS_NODE) {
return ret;
};
+ load = function(f) {
+ globalEval(read(f));
+ };
+
arguments_ = process['argv'].slice(2);
} else if (ENVIRONMENT_IS_SHELL) {
// Polyfill over SpiderMonkey/V8 differences
if (!this['read']) {
- read = function(f) { snarf(f) };
+ this['read'] = function(f) { snarf(f) };
}
if (!this['arguments']) {
@@ -52,11 +57,11 @@ if (ENVIRONMENT_IS_NODE) {
}
} else if (ENVIRONMENT_IS_WEB) {
- print = printErr = function(x) {
+ this['print'] = printErr = function(x) {
console.log(x);
};
- read = function(url) {
+ this['read'] = function(url) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, false);
xhr.send(null);
@@ -69,7 +74,7 @@ if (ENVIRONMENT_IS_NODE) {
} else if (ENVIRONMENT_IS_WORKER) {
// We can do very little here...
- load = importScripts;
+ this['load'] = importScripts;
} else {
throw 'Unknown runtime environment. Where are we?';
@@ -80,17 +85,17 @@ function globalEval(x) {
}
if (typeof load == 'undefined' && typeof read != 'undefined') {
- load = function(f) {
+ this['load'] = function(f) {
globalEval(read(f));
};
}
if (typeof printErr === 'undefined') {
- printErr = function(){};
+ this['printErr'] = function(){};
}
if (typeof print === 'undefined') {
- print = printErr;
+ this['print'] = printErr;
}
// *** Environment setup code ***
@@ -138,7 +143,6 @@ EXPORTED_GLOBALS = set(EXPORTED_GLOBALS);
// Settings sanity checks
assert(!(USE_TYPED_ARRAYS === 2 && QUANTUM_SIZE !== 4), 'For USE_TYPED_ARRAYS == 2, must have normal QUANTUM_SIZE of 4');
-assert(!(USE_TYPED_ARRAYS !== 2 && I64_MODE === 1), 'i64 mode 1 is only supported with typed arrays mode 2');
// Output some info and warnings based on settings
@@ -149,7 +153,7 @@ if (!MICRO_OPTS || !RELOOP || ASSERTIONS || CHECK_SIGNS || CHECK_OVERFLOWS || IN
print('// Note: For maximum-speed code, see "Optimizing Code" on the Emscripten wiki, https://github.com/kripken/emscripten/wiki/Optimizing-Code');
}
-if (DOUBLE_MODE || I64_MODE || CORRECT_SIGNS || CORRECT_OVERFLOWS || CORRECT_ROUNDINGS) {
+if (DOUBLE_MODE || CORRECT_SIGNS || CORRECT_OVERFLOWS || CORRECT_ROUNDINGS) {
print('// Note: Some Emscripten settings may limit the speed of the generated code.');
}
diff --git a/src/intertyper.js b/src/intertyper.js
index 91ad15eb..bd7b70f9 100644
--- a/src/intertyper.js
+++ b/src/intertyper.js
@@ -728,11 +728,22 @@ function intertyper(data, sidePass, baseLineNums) {
this.forwardItem(item, 'Reintegrator');
}
});
- // 'landingpad' - just a stub implementation
+ // 'landingpad'
substrate.addActor('Landingpad', {
processItem: function(item) {
item.intertype = 'landingpad';
item.type = item.tokens[1].text;
+ item.catchables = [];
+ var catchIdx = findTokenText(item, "catch");
+ if (catchIdx != -1) {
+ do {
+ var nextCatchIdx = findTokenTextAfter(item, "catch", catchIdx+1);
+ if (nextCatchIdx == -1)
+ nextCatchIdx = item.tokens.length;
+ item.catchables.push(parseLLVMSegment(item.tokens.slice(catchIdx+2, nextCatchIdx)));
+ catchIdx = nextCatchIdx;
+ } while (catchIdx != item.tokens.length);
+ }
Types.needAnalysis[item.type] = 0;
this.forwardItem(item, 'Reintegrator');
}
@@ -789,38 +800,39 @@ function intertyper(data, sidePass, baseLineNums) {
}
if (item.tokens[1].text == 'exact') item.tokens.splice(1, 1); // TODO: Implement trap values
var segments = splitTokenList(item.tokens.slice(1));
+ item.params = [];
for (var i = 1; i <= 4; i++) {
if (segments[i-1]) {
if (i > 1 && segments[i-1].length == 1 && segments[0].length > 1 && !isType(segments[i-1][0].text)) {
segments[i-1].unshift(segments[0][0]); // Add the type from the first segment, they are all alike
}
- item['param'+i] = parseLLVMSegment(segments[i-1]);
+ item.params[i-1] = parseLLVMSegment(segments[i-1]);
}
}
if (item.op === 'select') {
- assert(item.param2.type === item.param3.type);
- item.type = item.param2.type;
+ assert(item.params[1].type === item.params[2].type);
+ item.type = item.params[1].type;
} else if (item.op === 'inttoptr' || item.op === 'ptrtoint') {
- item.type = item.param2.type;
+ item.type = item.params[1].type;
} else {
- item.type = item.param1.type;
+ item.type = item.params[0].type;
}
if (item.op != 'ptrtoint') {
- for (var i = 1; i <= 4; i++) {
- if (item['param'+i]) item['param'+i].type = item.type; // All params have the same type, normally
+ for (var i = 0; i < 4; i++) {
+ if (item.params[i]) item.params[i].type = item.type; // All params have the same type, normally
}
}
if (item.op in LLVM.EXTENDS) {
- item.type = item.param2.ident;
- item.param1.type = item.param2.type;
+ item.type = item.params[1].ident;
+ item.params[0].type = item.params[1].type;
// TODO: also remove 2nd param?
}
- if (I64_MODE == 1) {
+ if (USE_TYPED_ARRAYS == 2) {
// Some specific corrections, since 'i64' is special
if (item.op in LLVM.SHIFTS) {
- item.param2.type = 'i32';
+ item.params[1].type = 'i32';
} else if (item.op == 'select') {
- item.param1.type = 'i1';
+ item.params[0].type = 'i1';
}
}
Types.needAnalysis[item.type] = 0;
diff --git a/src/jsifier.js b/src/jsifier.js
index 567520db..d4d57fc6 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -167,7 +167,7 @@ function JSify(data, functionsOnly, givenFunctions) {
}
// Add current value(s)
var currValue = flatten(values[i]);
- if (I64_MODE == 1 && typeData.fields[i] == 'i64') {
+ if (USE_TYPED_ARRAYS == 2 && typeData.fields[i] == 'i64') {
// 'flatten' out the 64-bit value into two 32-bit halves
ret[index++] = currValue>>>0;
ret[index++] = 0;
@@ -574,13 +574,13 @@ function JSify(data, functionsOnly, givenFunctions) {
if (block.type == 'emulated') {
if (block.labels.length > 1) {
if (block.entries.length == 1) {
- ret += indent + '__label__ = ' + getLabelId(block.entries[0]) + '; ' + (SHOW_LABELS ? '/* ' + block.entries[0] + ' */' : '') + '\n';
+ ret += indent + '__label__ = ' + getLabelId(block.entries[0]) + '; ' + (SHOW_LABELS ? '/* ' + getOriginalLabelId(block.entries[0]) + ' */' : '') + '\n';
} // otherwise, should have been set before!
if (func.setjmpTable) {
var setjmpTable = {};
ret += indent + 'var setjmpTable = {';
func.setjmpTable.forEach(function(triple) { // original label, label we created for right after the setjmp, variable setjmp result goes into
- ret += getLabelId(triple[0])+ ': ' + 'function(value) { __label__ = ' + getLabelId(triple[1]) + '; ' + triple[2] + ' = value },';
+ ret += '"' + getLabelId(triple[0]) + '": ' + 'function(value) { __label__ = ' + getLabelId(triple[1]) + '; ' + triple[2] + ' = value },';
});
ret += 'dummy: 0';
ret += '};\n';
@@ -591,7 +591,7 @@ function JSify(data, functionsOnly, givenFunctions) {
}
ret += 'switch(__label__) {\n';
ret += block.labels.map(function(label) {
- return indent + ' case ' + getLabelId(label.ident) + ': // ' + label.ident + '\n'
+ return indent + ' case ' + getLabelId(label.ident) + ': ' + (SHOW_LABELS ? '// ' + getOriginalLabelId(label.ident) : '') + '\n'
+ getLabelLines(label, indent + ' ');
}).join('\n');
ret += '\n' + indent + ' default: assert(0, "bad label: " + __label__);\n' + indent + '}';
@@ -770,11 +770,14 @@ function JSify(data, functionsOnly, givenFunctions) {
makeFuncLineActor('deleted', function(item) { return ';' });
- function getLabelId(label) {
+ function getOriginalLabelId(label) {
var funcData = Framework.currItem.funcData;
- var labelIds = funcData.labelIds;
- if (labelIds[label] !== undefined) return labelIds[label];
- return labelIds[label] = funcData.labelIdCounter++;
+ var labelIdsInverse = funcData.labelIdsInverse;
+ return labelIdsInverse[label];
+ }
+
+ function getLabelId(label) {
+ return label;
}
function makeBranch(label, lastLabel, labelIsVariable) {
@@ -788,7 +791,7 @@ function JSify(data, functionsOnly, givenFunctions) {
var trueLabel = parts[1] || '';
var oldLabel = parts[2] || '';
var labelSetting = oldLabel ? '__label__ = ' + getLabelId(oldLabel) + ';' +
- (SHOW_LABELS ? ' /* to: ' + cleanLabel(oldLabel) + ' */' : '') : ''; // TODO: optimize away the setting
+ (SHOW_LABELS ? ' /* to: ' + getOriginalLabelId(cleanLabel(oldLabel)) + ' */' : '') : ''; // TODO: optimize away the setting
if (label[1] == 'R') {
if (label[2] == 'N') { // BRNOL: break, no label setting
labelSetting = '';
@@ -808,7 +811,7 @@ function JSify(data, functionsOnly, givenFunctions) {
}
} else {
if (!labelIsVariable) label = getLabelId(label);
- return pre + '__label__ = ' + label + ';' + (SHOW_LABELS ? ' /* to: ' + cleanLabel(label) + ' */' : '') + ' break;';
+ return pre + '__label__ = ' + label + ';' + (SHOW_LABELS ? ' /* to: ' + getOriginalLabelId(cleanLabel(label)) + ' */' : '') + ' break;';
}
}
@@ -924,7 +927,7 @@ function JSify(data, functionsOnly, givenFunctions) {
} else {
first = false;
}
- ret += 'if (' + targetLabels[targetLabel].map(function(value) { return item.ident + ' == ' + value }).join(' || ') + ') {\n';
+ ret += 'if (' + targetLabels[targetLabel].map(function(value) { return makeComparison(item.ident, value, item.type) }).join(' || ') + ') {\n';
ret += ' ' + getPhiSetsForLabel(phiSets, targetLabel) + makeBranch(targetLabel, item.currLabelId || null) + '\n';
ret += '}\n';
}
@@ -969,7 +972,16 @@ function JSify(data, functionsOnly, givenFunctions) {
+ 'if (typeof e != "number") throw e; '
+ 'if (ABORT) throw e; __THREW__ = true; '
+ (EXCEPTION_DEBUG ? 'print("Exception: " + e + ", currently at: " + (new Error().stack)); ' : '')
- + 'return null } })(); if (!__THREW__) { ' + getPhiSetsForLabel(phiSets, item.toLabel) + makeBranch(item.toLabel, item.currLabelId)
+ + 'return null } })();';
+ if (item.assignTo) {
+ ret = 'var ' + item.assignTo + ' = ' + ret;
+ if (isIllegalType(item.type)) {
+ assert(item.type == 'i64', 'Can only handle i64 invoke among illegal invokes');
+ ret += 'var ' + item.assignTo + '$0 = ' + item.assignTo + '[0], ' + item.assignTo + '$1 = ' + item.assignTo + '[1];';
+ }
+ item.assignTo = null;
+ }
+ ret += 'if (!__THREW__) { ' + getPhiSetsForLabel(phiSets, item.toLabel) + makeBranch(item.toLabel, item.currLabelId)
+ ' } else { ' + getPhiSetsForLabel(phiSets, item.unwindLabel) + makeBranch(item.unwindLabel, item.currLabelId) + ' }';
return ret;
});
@@ -979,6 +991,7 @@ function JSify(data, functionsOnly, givenFunctions) {
var param2 = finalizeLLVMParameter(item.params[1]);
switch (item.op) {
case 'add': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, 'tempValue+' + param2, type) + ',tempValue)';
+ case 'sub': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, 'tempValue-' + param2, type) + ',tempValue)';
case 'xchg': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, param2, type) + ',tempValue)';
case 'cmpxchg': {
var param3 = finalizeLLVMParameter(item.params[2]);
@@ -988,9 +1001,8 @@ function JSify(data, functionsOnly, givenFunctions) {
}
});
makeFuncLineActor('landingpad', function(item) {
- // Just a stub
- return '{ f0: ' + makeGetValue('_llvm_eh_exception.buf', '0', 'void*') +
- ', f1:' + makeGetValue('_llvm_eh_exception.buf', QUANTUM_SIZE, 'void*') + ' }';
+ var catchTypeArray = item.catchables.map(finalizeLLVMParameter).join(',');
+ return '___cxa_find_matching_catch('+ makeGetValue('_llvm_eh_exception.buf', '0', 'void*') +',' + makeGetValue('_llvm_eh_exception.buf', QUANTUM_SIZE, 'void*') + ',[' + catchTypeArray +'])';
});
makeFuncLineActor('load', function(item) {
var value = finalizeLLVMParameter(item.pointer);
@@ -1046,10 +1058,14 @@ function JSify(data, functionsOnly, givenFunctions) {
makeFuncLineActor('mathop', processMathop);
makeFuncLineActor('bitcast', function(item) {
- return processMathop({
+ var temp = {
op: 'bitcast', variant: null, type: item.type,
- param1: item.params[0]
- });
+ assignTo: item.assignTo,
+ params: [item.params[0]] // XXX
+ };
+ var ret = processMathop(temp);
+ if (!temp.assignTo) item.assignTo = null; // If the assign was stolen, propagate that
+ return ret;
});
function makeFunctionCall(ident, params, funcData, type) {
diff --git a/src/library.js b/src/library.js
index 0d756608..817f87e2 100644
--- a/src/library.js
+++ b/src/library.js
@@ -2298,7 +2298,7 @@ LibraryManager.library = {
var ret;
if (type === 'double') {
ret = {{{ makeGetValue('varargs', 'argIndex', 'double', undefined, undefined, true) }}};
-#if I64_MODE == 1
+#if USE_TYPED_ARRAYS == 2
} else if (type == 'i64') {
ret = [{{{ makeGetValue('varargs', 'argIndex', 'i32', undefined, undefined, true) }}},
{{{ makeGetValue('varargs', 'argIndex+4', 'i32', undefined, undefined, true) }}}];
@@ -2433,7 +2433,7 @@ LibraryManager.library = {
var signed = next == 'd'.charCodeAt(0) || next == 'i'.charCodeAt(0);
argSize = argSize || 4;
var currArg = getNextArg('i' + (argSize * 8));
-#if I64_MODE == 1
+#if USE_TYPED_ARRAYS == 2
// Flatten i64-1 [low, high] into a (slightly rounded) double
if (argSize == 8) {
currArg = Runtime.makeBigInt(currArg[0], currArg[1], next == 'u'.charCodeAt(0));
@@ -3485,12 +3485,6 @@ LibraryManager.library = {
if (bits == 64) {
ret = [{{{ splitI64('ret') }}}];
}
-#else
-#if I64_MODE == 1
- if (bits == 64) {
- ret = {{{ splitI64('ret') }}};
- }
-#endif
#endif
return ret;
@@ -4374,27 +4368,10 @@ LibraryManager.library = {
__cxa_guard_release: function() {},