diff options
author | Alon Zakai <alonzakai@gmail.com> | 2012-02-08 18:51:43 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2012-02-11 14:54:27 -0800 |
commit | ee70b710083e7659f1391b239eb6365e4120d2d3 (patch) | |
tree | aad86f73ffe6ee47ecc82a789f280e2f15a37074 | |
parent | c74dd0de9db344599dc8bbee311a05b1123370e3 (diff) |
completely general unfolder
-rw-r--r-- | src/analyzer.js | 544 | ||||
-rw-r--r-- | src/parseTools.js | 32 |
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' }; } |