diff options
author | Alon Zakai <alonzakai@gmail.com> | 2012-03-03 12:03:48 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2012-03-03 12:03:48 -0800 |
commit | d6cff2177ec065aa14f228ab547abc29ef37b248 (patch) | |
tree | 285c3d737500e8a3ed6be56dcaf9357ffd5c7cd9 /src | |
parent | dfd9488e0094a6b5433b406517338e0f757c1e27 (diff) | |
parent | 6f57ea8f0eeb220fc81726b4e3a3c02f4232b667 (diff) |
Merge branch 'master' into llvmsvn
Diffstat (limited to 'src')
-rw-r--r-- | src/analyzer.js | 212 | ||||
-rw-r--r-- | src/compiler.js | 22 | ||||
-rw-r--r-- | src/intertyper.js | 38 | ||||
-rw-r--r-- | src/jsifier.js | 52 | ||||
-rw-r--r-- | src/library.js | 161 | ||||
-rw-r--r-- | src/modules.js | 2 | ||||
-rw-r--r-- | src/parseTools.js | 292 | ||||
-rw-r--r-- | src/preamble.js | 43 | ||||
-rw-r--r-- | src/settings.js | 6 | ||||
-rw-r--r-- | src/shell.js | 19 |
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() {}, |