//"use strict";
// LLVM assembly => internal intermediate representation, which is ready
// to be processed by the later stages.
var tokenizer; // TODO: Clean this up/out
// XXX In particular, this closes over the substrate, which can keep stuff in memory, which is bad
function tokenize(text) {
return tokenizer.processItem({ lineText: text }, true);
}
// Handy sets
var ENCLOSER_STARTERS = set('[', '(', '<');
var ENCLOSER_ENDERS = {
'[': ']',
'(': ')',
'<': '>'
};
var ZEROINIT_UNDEF = set('zeroinitializer', 'undef');
var NSW_NUW = set('nsw', 'nuw');
// Intertyper
function intertyper(data, sidePass, baseLineNums) {
var mainPass = !sidePass;
baseLineNums = baseLineNums || [[0,0]]; // each pair [#0,#1] means "starting from line #0, the base line num is #1"
dprint('framework', 'Big picture: Starting intertyper, main pass=' + mainPass);
// Substrate
var substrate = new Substrate('Intertyper');
// Line splitter. We break off some bunches of lines into unparsedBundles, which are
// parsed in separate passes later. This helps to keep memory usage low - we can start
// from raw lines and end up with final JS for each function individually that way, instead
// of intertyping them all, then analyzing them all, etc.
substrate.addActor('LineSplitter', {
processItem: function _lineSplitter(item) {
var lines = item.llvmLines;
var ret = [];
var inContinual = false;
var inFunction = false;
var currFunctionLines;
var currFunctionLineNum;
var unparsedBundles = [];
var unparsedTypes, unparsedGlobals;
if (mainPass) {
unparsedTypes = {
intertype: 'unparsedTypes',
lines: []
};
unparsedBundles.push(unparsedTypes);
unparsedGlobals = {
intertype: 'unparsedGlobals',
lines: []
};
unparsedBundles.push(unparsedGlobals);
}
var baseLineNumPosition = 0;
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
if (singlePhase) lines[i] = null; // lines may be very very large. Allow GCing to occur in the loop by releasing refs here
while (baseLineNumPosition < baseLineNums.length-1 && i >= baseLineNums[baseLineNumPosition+1][0]) {
baseLineNumPosition++;
}
if (mainPass && (line[0] == '%' || line[0] == '@')) {
// If this isn't a type, it's a global variable, make a note of the information now, we will need it later
var parts = line.split(' = ');
assert(parts.length >= 2);
var left = parts[0], right = parts.slice(1).join(' = ');
var testType = /^type .*/.exec(right);
if (!testType) {
var globalIdent = toNiceIdent(left);
var testAlias = /^(hidden )?alias .*/.exec(right);
Variables.globals[globalIdent] = {
name: globalIdent,
alias: !!testAlias,
impl: VAR_EMULATED
};
unparsedGlobals.lines.push(line);
} else {
unparsedTypes.lines.push(line);
}
continue;
}
if (mainPass && /^define .*/.test(line)) {
inFunction = true;
currFunctionLines = [];
currFunctionLineNum = i + 1;
}
if (!inFunction || !mainPass) {
if (inContinual || /^\ +(to|catch |filter |cleanup).*/.test(line)) {
// to after invoke or landingpad second line
ret.slice(-1)[0].lineText += line;
if (/^\ +\]/.test(line)) { // end of llvm switch
inContinual = false;
}
} else {
ret.push({
lineText: line,
lineNum: i + 1 + baseLineNums[baseLineNumPosition][