//"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 MATHOPS = set(['add', 'sub', 'sdiv', 'udiv', 'mul', 'icmp', 'zext', 'urem', 'srem', 'fadd', 'fsub', 'fmul', 'fdiv', 'fcmp', 'uitofp', 'sitofp', 'fpext', 'fptrunc', 'fptoui', 'fptosi', 'trunc', 'sext', 'select', 'shl', 'shr', 'ashl', 'ashr', 'lshr', 'lshl', 'xor', 'or', 'and', 'ptrtoint', 'inttoptr']);
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);
if (mainPass) {
if (LLVM_STYLE === null) {
// new = clang on 2.8, old = llvm-gcc anywhere or clang on 2.7
LLVM_STYLE = (data.indexOf('<label>') == -1 && data.indexOf('entry:') != -1) ? 'old' : 'new';
//dprint('LLVM_STYLE: ' + LLVM_STYLE);
}
}
// 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];
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 testType = /[@%\w\d\.\" ]+ = type .*/.exec(line);
if (!testType) {
var global = /([@%\w\d\.\" ]+) = .*/.exec(line);
var globalIdent = toNiceIdent(global[1]);
var testAlias = /[@%\w\d\.\" ]+ = alias .*/.exec(line);
var testString = /^[^"]+c\"[^"]+"/.exec(line);
Variables.globals[globalIdent] = {
name: globalIdent,
alias: !!testAlias,
impl: VAR_EMULATED,
isString : !!testString
};
unparsedGlobals.lines.push(line);
} else {
unparsedTypes.lines.push(line);
}
continue;
}
if (mainPass && /^define .*/.test(line