// Various tools for parsing LLVM. Utilities of various sorts, that are
// specific to Emscripten (and hence not in utility.js).
// Does simple 'macro' substitution, using Django-like syntax,
// {{{ code }}} will be replaced with |eval(code)|.
function processMacros(text) {
return text.replace(/{{{[^}]+}}}/g, function(str) {
str = str.substr(3, str.length-6);
return eval(str).toString();
});
}
// Simple #if/else/endif preprocessing for a file. Checks if the
// ident checked is true in our global. Also replaces some constants.
function preprocess(text, constants) {
for (constant in constants) {
text = text.replace(eval('/' + constant + '/g'), constants[constant]);
}
var lines = text.split('\n');
var ret = '';
var showStack = [];
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
if (!line[0] || line[0] != '#') {
if (showStack.indexOf(false) == -1) {
ret += line + '\n';
}
} else {
if (line[1] && line[1] == 'i') { // if
var ident = line.substr(4);
showStack.push(!!this[ident] && this[ident] > 0);
} else if (line[2] && line[2] == 'l') { // else
showStack.push(!showStack.pop());
} else if (line[2] && line[2] == 'n') { // endif
showStack.pop();
} else {
throw "Unclear preprocessor command: " + line;
}
}
}
assert(showStack.length == 0);
return ret;
}
function addPointing(type) { return type + '*' }
function removePointing(type, num) {
if (num === 0) return type;
return type.substr(0, type.length-(num ? num : 1));
}
function pointingLevels(type) {
if (!type) return 0;
var ret = 0;
var len1 = type.length - 1;
while (type[len1-ret] && type[len1-ret] === '*') {
ret ++;
}
return ret;
}
function removeAllPointing(type) {
return removePointing(type, pointingLevels(type));
}
function toNiceIdent(ident) {
assert(ident);
if (parseFloat(ident) == ident) return ident;
if (ident == 'null') return '0'; // see parseNumerical
return ident.replace('%', '$').replace(/["&\\ \.@:<>,\*\[\]-]/g, '_');
}
// Kind of a hack. In some cases we have strings that we do not want
// to |toNiceIdent|, as they are the output of previous processing. We
// should refactor everything into an object, with an explicit flag
// saying what has been |toNiceIdent|ed. Until then, this will detect
// simple idents that are in need of |toNiceIdent|ation. Or, we should
// ensure that processed strings never start with %,@, e.g. by always
// enclosing them in ().
function toNiceIdentCarefully(ident) {
if (ident[0] == '%' || ident[0] == '@') ident = toNiceIdent(ident);
return ident;
}
function isStructPointerType(type) {
// This test is necessary for clang - in llvm-gcc, we
// could check for %struct. The downside is that %1 can
// be either a variable or a structure, and we guess it is
// a struct, which can lead to |call i32 %5()| having
// |%5()| as a function call (like |i32 (i8*)| etc.). So
// we must check later on, in call(), where we have more
// context, to differentiate such cases.
// A similar thing happns in isStructType()
return !Runtime.isNumberType(type) && type[0] == '%';
}
function isStructType(type) {
if (isPointerType(type)) return false;
if (new RegExp(/^\[\d+\ x\ (.*)\]/g).test(type)) return true; // [15 x ?] blocks. Like structs
// See comment in isStructPointerType()
return !Runtime.isNumberType(type) && type[0