// Analyze intertype data
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 = new Substrate('Analyzer');
// Sorter
substrate.addZyme('Sorter', {
processItem: function(item) {
item.items.sort(function (a, b) { return a.lineNum - b.lineNum });
this.forwardItem(item, 'Gatherer');
},
});
// Gatherer
substrate.addZyme('Gatherer', {
processItem: function(item) {
// Single-liners
['globalVariable', 'functionStub', 'type'].forEach(function(intertype) {
var temp = splitter(item.items, function(item) { return item.intertype == intertype });
item[intertype + 's'] = temp.splitOut;
item.items = temp.leftIn;
});
// Functions & labels
item.functions = []
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 = [];
} else if (item.functions.slice(-1)[0].endLineNum === null) {
// Internal line
item.functions.slice(-1)[0].lines.push(subItem);
item.functions.slice(-1)[0].labels.slice(-1)[0].lines.push(subItem);
} else {
print("ERROR: what is this? " + JSON.stringify(subItem));
}
}
delete item.items;
this.forwardItem(item, 'Identinicer');
},
});
// IdentiNicer
substrate.addZyme('Identinicer', {
processItem: function(output) {
walkJSON(output, function(item) {
['', '2', '3', '4', '5'].forEach(function(ext) {
if (item && item['ident' + ext])
item['ident' + ext] = toNiceIdent(item['ident' + ext]);
});
});
this.forwardItem(output, 'Typevestigator');
}
});
function addType(type, data) {
if (type.length == 1) return;
if (data.types[type]) return;
if (['internal', '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 && !data.types[nonPointing]) {
var num = parseInt(check[1]);
num = Math.max(num, 1); // [0 x something] is used not for allocations and such of course, but
// for indexing - for an |array of unknown length|, basically. So we
// define the 'type' as having a single field. TODO: Ensure as a sanity
// check that we never allocate with this (either as a child structure
// in the analyzer, or in calcSize in alloca).
var subType = check[2];
data.types[nonPointing] = {
name_: nonPointing,
fields: range(num).map(function() { return subType }),
lineNum: '?',
};
return;
}
if (isPointerType(type)) return;
if (['['].indexOf(type) != -1) return;
data.types