// Analyze intertype data. Calculates things that are necessary in order
// to do the final conversion into JavaScript later, for example,
// properties of variables, loop structures of functions, etc.
VAR_NATIVE = 'native';
VAR_NATIVIZED = 'nativized';
VAR_EMULATED = 'emulated';
function cleanFunc(func) {
func.lines = func.lines.filter(function(line) { return line.intertype !== null });
func.labels.forEach(function(label) {
label.lines = label.lines.filter(function(line) { return line.intertype !== null });
});
}
function analyzer(data) {
// Substrate
substrate = new Substrate('Analyzer');
// Sorter
substrate.addActor('Sorter', {
processItem: function(item) {
item.items.sort(function (a, b) { return a.lineNum - b.lineNum });
this.forwardItem(item, 'Gatherer');
}
});
// Gatherer
substrate.addActor('Gatherer', {
processItem: function(item) {
// Single-liners
['globalVariable', 'functionStub', 'unparsedFunction'].forEach(function(intertype) {
var temp = splitter(item.items, function(item) { return item.intertype == intertype });
item.items = temp.leftIn;
item[intertype + 's'] = temp.splitOut;
});
var temp = splitter(item.items, function(item) { return item.intertype == 'type' });
item.items = temp.leftIn;
temp.splitOut.forEach(function(type) {
Types.types[type.name_] = type;
});
// Functions & labels
item.functions = [];
var currLabelFinished; // Sometimes LLVM puts a branch in the middle of a label. We need to ignore all lines after that.
for (var i = 0; i < item.items.length; i++) {
var subItem = item.items[i];
if (subItem.intertype == 'function') {
item.functions.push(subItem);
subItem.endLineNum = null;
subItem.lines = [];
subItem.labels = [];
// no explicit 'entry' label in clang on LLVM 2.8 - most of the time, but not all the time! - so we add one if necessary
if (LLVM_STYLE == 'new' && item.items[i+1].intertype !== 'label') {
item.items.splice(i+1, 0, {
intertype: 'label',
ident: '_entry',
lineNum: subItem.lineNum + '.5'
});
}
} else if (subItem.intertype == 'functionEnd') {
item.functions.slice(-1)[0].endLineNum = subItem.lineNum;
} else if (subItem.intertype == 'label') {
item.functions.slice(-1)[0].labels.push(subItem);
subItem.lines = [];
currLabelFinished = false;
} else if (item.functions.length > 0 && item.functions.slice(-1)[0].endLineNum === null) {
// Internal line
if (!currLabelFinished) {
item.functions.slice(-1)[0].lines.push(subItem);
item.functions.slice(-1)[0].labels.slice(-1)[0].lines.push(subItem); // If this line fails, perhaps missing a label? LLVM_STYLE related?
if (subItem.intertype === 'branch') {
currLabelFinished = true;
}
} else {
print('// WARNING: content after a branch in a label, line: ' + subItem.lineNum);
}
} else {
print("ERROR: what is this? " + JSON.stringify(subItem));
}
}
delete item.items;
this.forwardItem(item, 'Typevestigator');
}
});
function addType(type, data) {
if (type.length == 1) return;
if (Types.types[type]) return;
if (['internal', 'hidden', 'inbounds', 'void'].indexOf(type) != -1) return;
if (Runtime.isNumberType(type)) return;
// 'blocks': [14 x %struct.X] etc. If this is a pointer, we need
// to look at the underlying type - it was not defined explicitly
// anywhere else.
var nonPointing = removeAllPointing(type);
var check = new RegExp(/^\[(\d+)\ x\ (.*)\]$/g).exec(nonPointing);
if (check && !Types.types[nonPointing]) {
var