aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2012-02-08 18:51:43 -0800
committerAlon Zakai <alonzakai@gmail.com>2012-02-11 14:54:27 -0800
commitee70b710083e7659f1391b239eb6365e4120d2d3 (patch)
treeaad86f73ffe6ee47ecc82a789f280e2f15a37074
parentc74dd0de9db344599dc8bbee311a05b1123370e3 (diff)
completely general unfolder
-rw-r--r--src/analyzer.js544
-rw-r--r--src/parseTools.js32
2 files changed, 305 insertions, 271 deletions
diff --git a/src/analyzer.js b/src/analyzer.js
index 729d4607..c007452b 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -22,6 +22,7 @@ function cleanFunc(func) {
var BRANCH_INVOKE = set('branch', 'invoke');
var SIDE_EFFECT_CAUSERS = set('call', 'invoke', 'atomic');
+var UNFOLDABLE = set('value', 'type', 'phiparam');
// Analyzer
@@ -128,7 +129,8 @@ function analyzer(data, sidePass) {
// Legalization
if (USE_TYPED_ARRAYS == 2) {
function isIllegalType(type) {
- return getBits(type) > 64;
+ var bits = getBits(type);
+ return bits > 0 && (bits > 64 || !isPowerOfTwo(bits));
}
function getLegalVars(base, bits) {
if (isNumber(base)) {
@@ -154,311 +156,315 @@ function analyzer(data, sidePass) {
}
return ret;
}
- // Unfolds internal inline llvmfunc calls, for example x = load (bitcast y)
- // will become temp = y \n x = load temp
- // @return The index of the original line, after the unfolding. In the example
- // above, the index returned will be the new index of the line with `load',
- // that is, i+1.
- function unfold(lines, i, item, slot) {
- if (item[slot].intertype == 'value') return i;
- // TODO: unfold multiple slots at once
- var tempIdent = '$$emscripten$temp$' + i;
- item[slot].assignTo = tempIdent;
- item[slot].lineNum = lines[i].lineNum - 0.5;
- lines.splice(i, 0, item[slot]);
- item[slot] = { intertype: 'value', ident: tempIdent, type: item[slot].type };
- return i+1;
+ // Uses the right factor to multiply line numbers by so that they fit in between
+ // the line[i] and the line after it
+ function interpLines(lines, i, toAdd) {
+ var prev = i >= 0 ? lines[i].lineNum : -1;
+ var next = (i < lines.length-1) ? lines[i+1].lineNum : (lines[i].lineNum + 0.5);
+ var factor = (next - prev)/(4*toAdd.length+3);
+ for (var k = 0; k < toAdd.length; k++) {
+ toAdd[k].lineNum = prev + ((k+1)*factor);
+ }
}
function removeAndAdd(lines, i, toAdd) {
var item = lines[i];
- var interp = getInterp(lines, i, toAdd.length);
- for (var k = 0; k < toAdd.length; k++) {
- toAdd[k].lineNum = item.lineNum + (k*interp);
- }
+ interpLines(lines, i, toAdd);
Array.prototype.splice.apply(lines, [i, 1].concat(toAdd));
return toAdd.length;
}
- // Assuming we will replace the item at line i, with num items, returns
- // the right factor to multiply line numbers by so that they fit in between
- // the removed line and the line after it
- function getInterp(lines, i, num) {
- var next = (i < lines.length-1) ? lines[i+1].lineNum : (lines[i].lineNum + 0.5);
- return (next - lines[i].lineNum)/(3*num+2);
- }
data.functions.forEach(function(func) {
+ var tempId = 0;
func.labels.forEach(function(label) {
var i = 0, bits;
while (i < label.lines.length) {
var item = label.lines[i];
+ // Check if we need to legalize here
+ var isIllegal = false;
+ walkInterdata(item, function(item) {
+ if (isIllegalType(item.valueType) || isIllegalType(item.type)) {
+ isIllegal = true;
+ }
+ });
+ if (!isIllegal) {
+ i++;
+ continue;
+ }
+ // Unfold this line. If we unfolded, we need to return and process the lines we just
+ // generated - they may need legalization too
+ var unfolded = [];
+ walkAndModifyInterdata(item, function(subItem) {
+ if (subItem != item && !(subItem.intertype in UNFOLDABLE)) {
+ var tempIdent = '$$emscripten$temp$' + (tempId++);
+ subItem.assignTo = tempIdent;
+ unfolded.unshift(subItem);
+ return { intertype: 'value', ident: tempIdent, type: subItem.type };
+ }
+ });
+ if (unfolded.length > 0) {
+ interpLines(label.lines, i-1, unfolded);
+ Array.prototype.splice.apply(label.lines, [i, 0].concat(unfolded));
+ continue; // remain at this index, to unfold newly generated lines
+ }
+ // This is an illegal-containing line, and it is unfolded. Legalize it now
if (item.intertype == 'store') {
- if (isIllegalType(item.valueType)) {
- dprint('legalizer', 'Legalizing store at line ' + item.lineNum);
- var toAdd = [];
- bits = getBits(item.valueType);
- i = unfold(label.lines, i, item, 'value');
- var elements;
- elements = getLegalVars(item.value.ident, bits);
- var j = 0;
- elements.forEach(function(element) {
- var tempVar = '$st$' + i + '$' + j;
- toAdd.push({
- intertype: 'getelementptr',
- assignTo: tempVar,
- ident: item.pointer.ident,
- type: '[0 x i32]*',
- params: [
- { intertype: 'value', ident: item.pointer.ident, type: '[0 x i32]*' }, // technically a bitcase is needed in llvm, but not for us
- { intertype: 'value', ident: '0', type: 'i32' },
- { intertype: 'value', ident: j.toString(), type: 'i32' }
- ],
- });
- var actualSizeType = 'i' + element.bits; // The last one may be smaller than 32 bits
- toAdd.push({
- intertype: 'store',
- valueType: actualSizeType,
- value: { intertype: 'value', ident: element.ident, type: actualSizeType },
- pointer: { intertype: 'value', ident: tempVar, type: actualSizeType + '*' },
- ident: tempVar,
- pointerType: actualSizeType + '*',
- align: item.align,
- });
- j++;
+ dprint('legalizer', 'Legalizing store at line ' + item.lineNum);
+ var toAdd = [];
+ bits = getBits(item.valueType);
+ var elements;
+ elements = getLegalVars(item.value.ident, bits);
+ var j = 0;
+ elements.forEach(function(element) {
+ var tempVar = '$st$' + i + '$' + j;
+ toAdd.push({
+ intertype: 'getelementptr',
+ assignTo: tempVar,
+ ident: item.pointer.ident,
+ type: '[0 x i32]*',
+ params: [
+ { intertype: 'value', ident: item.pointer.ident, type: '[0 x i32]*' }, // technically a bitcase is needed in llvm, but not for us
+ { intertype: 'value', ident: '0', type: 'i32' },
+ { intertype: 'value', ident: j.toString(), type: 'i32' }
+ ],
});
- Types.needAnalysis['[0 x i32]'] = 0;
- i += removeAndAdd(label.lines, i, toAdd);
- continue;
- }
+ var actualSizeType = 'i' + element.bits; // The last one may be smaller than 32 bits
+ toAdd.push({
+ intertype: 'store',
+ valueType: actualSizeType,
+ value: { intertype: 'value', ident: element.ident, type: actualSizeType },
+ pointer: { intertype: 'value', ident: tempVar, type: actualSizeType + '*' },
+ ident: tempVar,
+ pointerType: actualSizeType + '*',
+ align: item.align,
+ });
+ j++;
+ });
+ Types.needAnalysis['[0 x i32]'] = 0;
+ i += removeAndAdd(label.lines, i, toAdd);
+ continue;
} else if (item.assignTo) {
var value = item;
switch (value.intertype) {
case 'load': {
- if (isIllegalType(value.valueType)) {
- dprint('legalizer', 'Legalizing load at line ' + item.lineNum);
- bits = getBits(value.valueType);
- i = unfold(label.lines, i, value, 'pointer');
- var interp = getInterp(label.lines, i, Math.ceil(bits/32));
- label.lines.splice(i, 1);
- var elements = getLegalVars(item.assignTo, bits);
- var j = 0;
- elements.forEach(function(element) {
- var tempVar = '$st$' + i + '$' + j;
- label.lines.splice(i+j*2, 0, {
- intertype: 'getelementptr',
- assignTo: tempVar,
- ident: value.pointer.ident,
- type: '[0 x i32]*',
- params: [
- { intertype: 'value', ident: value.pointer.ident, type: '[0 x i32]*' }, // technically bitcast is needed in llvm, but not for us
- { intertype: 'value', ident: '0', type: 'i32' },
- { intertype: 'value', ident: j.toString(), type: 'i32' }
- ],
- lineNum: item.lineNum + (j*interp)
- });
- var actualSizeType = 'i' + element.bits; // The last one may be smaller than 32 bits
- label.lines.splice(i+j*2+1, 0, {
- intertype: 'load',
- assignTo: element.ident,
- pointerType: actualSizeType + '*',
- valueType: actualSizeType,
- type: actualSizeType, // XXX why is this missing from intertyper?
- pointer: { intertype: 'value', ident: tempVar, type: actualSizeType + '*' },
- ident: tempVar,
- pointerType: actualSizeType + '*',
- align: value.align,
- lineNum: item.lineNum + ((j+0.5)*interp)
- });
- j++;
+ dprint('legalizer', 'Legalizing load at line ' + item.lineNum);
+ bits = getBits(value.valueType);
+ var elements = getLegalVars(item.assignTo, bits);
+ var j = 0;
+ var toAdd = [];
+ elements.forEach(function(element) {
+ var tempVar = '$st$' + i + '$' + j;
+ toAdd.push({
+ intertype: 'getelementptr',
+ assignTo: tempVar,
+ ident: value.pointer.ident,
+ type: '[0 x i32]*',
+ params: [
+ { intertype: 'value', ident: value.pointer.ident, type: '[0 x i32]*' }, // technically bitcast is needed in llvm, but not for us
+ { intertype: 'value', ident: '0', type: 'i32' },
+ { intertype: 'value', ident: j.toString(), type: 'i32' }
+ ]
});
- Types.needAnalysis['[0 x i32]'] = 0;
- i += j*2;
- continue;
- }
- break;
+ var actualSizeType = 'i' + element.bits; // The last one may be smaller than 32 bits
+ toAdd.push({
+ intertype: 'load',
+ assignTo: element.ident,
+ pointerType: actualSizeType + '*',
+ valueType: actualSizeType,
+ type: actualSizeType, // XXX why is this missing from intertyper?
+ pointer: { intertype: 'value', ident: tempVar, type: actualSizeType + '*' },
+ ident: tempVar,
+ pointerType: actualSizeType + '*',
+ align: value.align
+ });
+ j++;
+ });
+ Types.needAnalysis['[0 x i32]'] = 0;
+ i += removeAndAdd(label.lines, i, toAdd);
+ continue;
}
case 'phi': {
- if (isIllegalType(value.type)) {
- dprint('legalizer', 'Legalizing phi at line ' + item.lineNum);
- bits = getBits(value.type);
- var toAdd = [];
- var elements = getLegalVars(item.assignTo, bits);
- var j = 0;
- elements.forEach(function(element) {
- toAdd.push({
- intertype: 'phi',
- assignTo: element.ident,
- type: 'i' + element.bits,
- params: value.params.map(function(param) {
- return {
- intertype: 'phiparam',
- label: param.label,
- value: { // TODO: unfolding
- intertype: 'value',
- ident: param.value.ident + '$' + j,
- type: 'i' + element.bits,
- }
- };
- })
- });
- j++;
+ dprint('legalizer', 'Legalizing phi at line ' + item.lineNum);
+ bits = getBits(value.type);
+ var toAdd = [];
+ var elements = getLegalVars(item.assignTo, bits);
+ var j = 0;
+ elements.forEach(function(element) {
+ toAdd.push({
+ intertype: 'phi',
+ assignTo: element.ident,
+ type: 'i' + element.bits,
+ params: value.params.map(function(param) {
+ return {
+ intertype: 'phiparam',
+ label: param.label,
+ value: {
+ intertype: 'value',
+ ident: param.value.ident + '$' + j,
+ type: 'i' + element.bits,
+ }
+ };
+ })
});
- i += removeAndAdd(label.lines, i, toAdd);
- continue;
- }
- break;
+ j++;
+ });
+ i += removeAndAdd(label.lines, i, toAdd);
+ continue;
+ }
+ case 'bitcast': {
+ value = {
+ op: 'bitcast',
+ param1: item.params[0]
+ };
+ // fall through
}
case 'mathop': {
- if (isIllegalType(value.type)) {
- dprint('legalizer', 'Legalizing mathop at line ' + item.lineNum);
- var toAdd = [];
- assert(value.param1.intertype == 'value', 'TODO: unfolding');
- var sourceBits = getBits(value.param1.type);
- var sourceElements;
- if (sourceBits <= 64) {
- // The input is a legal type
- if (sourceBits <= 32) {
- sourceElements = [{ ident: value.param1.ident, bits: sourceBits }];
- } else if (sourceBits == 64 && I64_MODE == 1) {
- sourceElements = [{ ident: value.param1.ident + '[0]', bits: 32 },
- { ident: value.param1.ident + '[1]', bits: 32 }];
- // Add the source element as a param so that it is not eliminated as unneeded (the idents are not a simple ident here)
- toAdd.push({
- intertype: 'value', ident: ';', type: 'rawJS',
- params: [{ intertype: 'value', ident: value.param1.ident, type: 'i32' }]
- });
- } else {
- throw 'Invalid legal type as source of legalization ' + sourceBits;
- }
+ dprint('legalizer', 'Legalizing mathop at line ' + item.lineNum);
+ var toAdd = [];
+ var sourceBits = getBits(value.param1.type);
+ var sourceElements;
+ if (sourceBits <= 64) {
+ // The input is a legal type
+ if (sourceBits <= 32) {
+ sourceElements = [{ ident: value.param1.ident, bits: sourceBits }];
+ } else if (sourceBits == 64 && I64_MODE == 1) {
+ sourceElements = [{ ident: value.param1.ident + '[0]', bits: 32 },
+ { ident: value.param1.ident + '[1]', bits: 32 }];
+ // Add the source element as a param so that it is not eliminated as unneeded (the idents are not a simple ident here)
+ toAdd.push({
+ intertype: 'value', ident: ';', type: 'rawJS',
+ params: [{ intertype: 'value', ident: value.param1.ident, type: 'i32' }]
+ });
} else {
- sourceElements = getLegalVars(value.param1.ident, sourceBits);
+ throw 'Invalid legal type as source of legalization ' + sourceBits;
}
- // All mathops can be parametrized by how many shifts we do, and how big the source is
- var shifts = 0;
- var targetBits;
- var processor = null;
- switch (value.op) {
- case 'lshr': {
- assert(value.param2.intertype == 'value', 'TODO: unfolding');
- shifts = parseInt(value.param2.ident);
- targetBits = sourceBits;
- break;
- }
- case 'shl': {
- assert(value.param2.intertype == 'value', 'TODO: unfolding');
- shifts = -parseInt(value.param2.ident);
- targetBits = sourceBits;
- break;
- }
- case 'trunc': case 'zext': {
- assert(value.param2.intertype == 'type' || value.param2.intertype == 'value', 'TODO: unfolding');
- targetBits = getBits(value.param2.ident);
- break;
- }
- case 'or': case 'and': case 'xor': {
- targetBits = sourceBits;
- var otherElements = getLegalVars(value.param2.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 }
- };
- };
- break;
- }
- default: throw 'Invalid mathop for legalization: ' + [value.op, item.lineNum, dump(item)];
+ } else {
+ sourceElements = getLegalVars(value.param1.ident, sourceBits);
+ }
+ // All mathops can be parametrized by how many shifts we do, and how big the source is
+ var shifts = 0;
+ var targetBits;
+ var processor = null;
+ switch (value.op) {
+ case 'lshr': {
+ shifts = parseInt(value.param2.ident);
+ targetBits = sourceBits;
+ break;
+ }
+ case 'shl': {
+ shifts = -parseInt(value.param2.ident);
+ targetBits = sourceBits;
+ break;
+ }
+ case 'trunc': case 'zext': {
+ targetBits = getBits(value.param2.ident);
+ break;
+ }
+ case 'bitcast': {
+ targetBits = sourceBits;
+ break;
+ }
+ case 'or': case 'and': case 'xor': {
+ targetBits = sourceBits;
+ var otherElements = getLegalVars(value.param2.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 }
+ };
+ };
+ break;
}
- // Do the legalization
- assert(isNumber(shifts), 'TODO: handle nonconstant shifts');
- var targetElements = getLegalVars(item.assignTo, targetBits);
- var sign = shifts >= 0 ? 1 : -1;
- var shiftOp = shifts >= 0 ? 'shl' : 'lshr';
- var shiftOpReverse = shifts >= 0 ? 'lshr' : 'shl';
- var whole = shifts >= 0 ? Math.floor(shifts/32) : Math.ceil(shifts/32);
- var fraction = Math.abs(shifts % 32);
- for (var j = 0; j < targetElements.length; j++) {
- var result = {
+ default: throw 'Invalid mathop for legalization: ' + [value.op, item.lineNum, dump(item)];
+ }
+ // Do the legalization
+ assert(isNumber(shifts), 'TODO: handle nonconstant shifts');
+ var targetElements = getLegalVars(item.assignTo, targetBits);
+ var sign = shifts >= 0 ? 1 : -1;
+ var shiftOp = shifts >= 0 ? 'shl' : 'lshr';
+ var shiftOpReverse = shifts >= 0 ? 'lshr' : 'shl';
+ var whole = shifts >= 0 ? Math.floor(shifts/32) : Math.ceil(shifts/32);
+ var fraction = Math.abs(shifts % 32);
+ for (var j = 0; j < targetElements.length; j++) {
+ var result = {
+ intertype: 'value',
+ ident: (j + whole >= 0 && j + whole < sourceElements.length) ? sourceElements[j + whole].ident : '0',
+ type: 'i32',
+ };
+ if (fraction != 0) {
+ var other = {
intertype: 'value',
- ident: (j + whole >= 0 && j + whole < sourceElements.length) ? sourceElements[j + whole].ident : '0',
+ ident: (j + sign + whole >= 0 && j + sign + whole < sourceElements.length) ? sourceElements[j + sign + whole].ident : '0',
type: 'i32',
};
- if (fraction != 0) {
- var other = {
- intertype: 'value',
- ident: (j + sign + whole >= 0 && j + sign + whole < sourceElements.length) ? sourceElements[j + sign + whole].ident : '0',
- type: 'i32',
- };
- other = {
- intertype: 'mathop',
- op: shiftOp,
- type: 'i32',
- param1: other,
- param2: { intertype: 'value', ident: (32 - fraction).toString(), type: 'i32' }
- };
- result = {
- intertype: 'mathop',
- op: shiftOpReverse,
- type: 'i32',
- param1: result,
- param2: { intertype: 'value', ident: fraction.toString(), type: 'i32' }
- };
- result = {
- intertype: 'mathop',
- op: 'or',
- type: 'i32',
- param1: result,
- param2: other
- }
- }
- if (targetElements[j].bits < 32 && shifts < 0) {
- // truncate bits that fall off the end. This is not needed in most cases, can probably be optimized out
- result = {
- intertype: 'mathop',
- op: 'and',
- type: 'i32',
- param1: result,
- param2: { intertype: 'value', ident: (Math.pow(2, targetElements[j].bits)-1).toString(), type: 'i32' }
- }
- }
- if (processor) {
- result = processor(result, j);
+ other = {
+ intertype: 'mathop',
+ op: shiftOp,
+ type: 'i32',
+ param1: other,
+ param2: { intertype: 'value', ident: (32 - fraction).toString(), type: 'i32' }
+ };
+ result = {
+ intertype: 'mathop',
+ op: shiftOpReverse,
+ type: 'i32',
+ param1: result,
+ param2: { intertype: 'value', ident: fraction.toString(), type: 'i32' }
+ };
+ result = {
+ intertype: 'mathop',
+ op: 'or',
+ type: 'i32',
+ param1: result,
+ param2: other
}
- result.assignTo = targetElements[j].ident;
- toAdd.push(result);
}
- if (targetBits <= 64) {
- // We are generating a normal legal type here
- var legalValue;
- if (targetBits == 64 && I64_MODE == 1) {
- // Generate an i64-1 [low,high]. This will be unnecessary when we legalize i64s
- legalValue = {
- intertype: 'value',
- ident: '[' + targetElements[0].ident + ',' + targetElements[1].ident + ']',
- type: 'rawJS',
- // Add the target elements as params so that they are not eliminated as unneeded (the ident is not a simple ident here)
- params: targetElements.map(function(element) {
- return { intertype: 'value', ident: element.ident, type: 'i32' };
- })
- };
- } else if (targetBits <= 32) {
- legalValue = { intertype: 'value', ident: targetElements[0].ident, type: 'rawJS' };
- // truncation to smaller than 32 bits has already been done, if necessary
- } else {
- throw 'Invalid legal type as target of legalization ' + targetBits;
+ if (targetElements[j].bits < 32 && shifts < 0) {
+ // truncate bits that fall off the end. This is not needed in most cases, can probably be optimized out
+ result = {
+ intertype: 'mathop',
+ op: 'and',
+ type: 'i32',
+ param1: result,
+ param2: { intertype: 'value', ident: (Math.pow(2, targetElements[j].bits)-1).toString(), type: 'i32' }
}
- legalValue.assignTo = item.assignTo;
- toAdd.push(legalValue);
}
- i += removeAndAdd(label.lines, i, toAdd);
- continue;
+ if (processor) {
+ result = processor(result, j);
+ }
+ result.assignTo = targetElements[j].ident;
+ toAdd.push(result);
}
- break;
+ if (targetBits <= 64) {
+ // We are generating a normal legal type here
+ var legalValue;
+ if (targetBits == 64 && I64_MODE == 1) {
+ // Generate an i64-1 [low,high]. This will be unnecessary when we legalize i64s
+ legalValue = {
+ intertype: 'value',
+ ident: '[' + targetElements[0].ident + ',' + targetElements[1].ident + ']',
+ type: 'rawJS',
+ // Add the target elements as params so that they are not eliminated as unneeded (the ident is not a simple ident here)
+ params: targetElements.map(function(element) {
+ return { intertype: 'value', ident: element.ident, type: 'i32' };
+ })
+ };
+ } else if (targetBits <= 32) {
+ legalValue = { intertype: 'value', ident: targetElements[0].ident, type: 'rawJS' };
+ // truncation to smaller than 32 bits has already been done, if necessary
+ } else {
+ throw 'Invalid legal type as target of legalization ' + targetBits;
+ }
+ legalValue.assignTo = item.assignTo;
+ toAdd.push(legalValue);
+ }
+ i += removeAndAdd(label.lines, i, toAdd);
+ continue;
}
}
}
- i++;
- continue;
+ assert(0, 'Could not legalize illegal line: ' + [item.lineNum, dump(item)]);
}
});
});
diff --git a/src/parseTools.js b/src/parseTools.js
index 3cc17cc4..fcb85281 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -129,9 +129,12 @@ function isIntImplemented(type) {
return type[0] == 'i' || isPointerType(type);
}
+// Note: works for iX types, not pointers (even though they are implemented as ints)
function getBits(type) {
if (!type || type[0] != 'i') return 0;
- return parseInt(type.substr(1));
+ var left = type.substr(1);
+ if (!isNumber(left)) return 0;
+ return parseInt(left);
}
function isVoidType(type) {
@@ -966,7 +969,8 @@ function makeSetValue(ptr, pos, value, type, noNeedFirst, ignore, align, noSafe,
makeSetValue(ptr, getFastValue(pos, '+', Runtime.getNativeTypeSize('i32')), 'tempDoubleI32[1]', 'i32', noNeedFirst, ignore, align, noSafe, ',') + ')';
}
- var needSplitting = isIntImplemented(type) && !isPowerOfTwo(getBits(type)); // an unnatural type like i24
+ var bits = getBits(type);
+ var needSplitting = bits > 0 && !isPowerOfTwo(bits); // an unnatural type like i24
if (USE_TYPED_ARRAYS == 2 && (align || needSplitting)) {
// Alignment is important here, or we need to split this up for other reasons.
var bytes = Runtime.getNativeTypeSize(type);
@@ -1831,6 +1835,7 @@ function walkInterdata(item, pre, post, obj) {
var originalObj = obj;
if (obj && obj.replaceWith) obj = obj.replaceWith; // allow pre to replace the object we pass to all its children
if (item.value && walkInterdata(item.value, pre, post, obj)) return true;
+ // TODO if (item.pointer && walkInterdata(item.pointer, pre, post, obj)) return true;
if (item.dependent && walkInterdata(item.dependent, pre, post, obj)) return true;
var i;
for (i = 1; i <= 4; i++) {
@@ -1851,6 +1856,29 @@ function walkInterdata(item, pre, post, obj) {
return post && post(item, originalObj, obj);
}
+// Separate from walkInterdata so that the former is as fast as possible
+// If the callback returns a value, we replace the current item with that
+// value, and do *not* walk the children.
+function walkAndModifyInterdata(item, pre) {
+ if (!item || !item.intertype) return false;
+ var ret = pre(item);
+ if (ret) return ret;
+ var repl;
+ if (item.value && (repl = walkAndModifyInterdata(item.value, pre))) item.value = repl;
+ if (item.pointer && (repl = walkAndModifyInterdata(item.pointer, pre))) item.pointer = repl;
+ if (item.dependent && (repl = walkAndModifyInterdata(item.dependent, pre))) item.dependent = repl;
+ var i;
+ for (i = 1; i <= 4; i++) {
+ if (item['param'+i] && (repl = walkAndModifyInterdata(item['param'+i], pre))) item['param'+i] = repl;
+ }
+ if (item.params) {
+ for (i = 0; i <= item.params.length; i++) {
+ if (repl = walkAndModifyInterdata(item.params[i], pre)) item.params[i] = repl;
+ }
+ }
+ // Ignore possibleVars because we can't replace them anyhow
+}
+
function parseBlockAddress(segment) {
return { intertype: 'blockaddress', func: toNiceIdent(segment[2].item.tokens[0].text), label: toNiceIdent(segment[2].item.tokens[2].text), type: 'i32' };
}