aboutsummaryrefslogtreecommitdiff
path: root/src/parseTools.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/parseTools.js')
-rw-r--r--src/parseTools.js314
1 files changed, 199 insertions, 115 deletions
diff --git a/src/parseTools.js b/src/parseTools.js
index c55c895d..addf0f21 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -5,11 +5,12 @@
// Does simple 'macro' substitution, using Django-like syntax,
// {{{ code }}} will be replaced with |eval(code)|.
+// NOTE: Be careful with that ret check. If ret is |0|, |ret ? ret.toString() : ''| would result in ''!
function processMacros(text) {
return text.replace(/{{{([^}]|}(?!}))+}}}/g, function(str) {
str = str.substr(3, str.length-6);
var ret = eval(str);
- return ret ? ret.toString() : '';
+ return ret !== null ? ret.toString() : '';
});
}
@@ -110,12 +111,22 @@ function isNiceIdent(ident, loose) {
}
function isJSVar(ident) {
- return /^\(?[$_]?[\w$_\d ]*\)+$/.test(ident);
-
+ if (ident[0] === '(') {
+ if (ident[ident.length-1] !== ')') return false;
+ ident = ident.substr(1, ident.length-2);
+ }
+ return /^[$_]?[\w$_\d]* *$/.test(ident);
}
function isLocalVar(ident) {
- return ident[0] == '$';
+ return ident[0] === '$';
+}
+
+// Simple variables or numbers, or things already quoted, do not need to be quoted
+function needsQuoting(ident) {
+ if (/^[-+]?[$_]?[\w$_\d]*$/.test(ident)) return false; // number or variable
+ if (ident[0] === '(' && ident[ident.length-1] === ')' && ident.indexOf('(', 1) < 0) return false; // already fully quoted
+ return true;
}
function isStructPointerType(type) {
@@ -752,10 +763,10 @@ function splitI64(value, floatConversion) {
if (floatConversion && ASM_JS) lowInput = asmFloatToInt(lowInput);
var low = lowInput + '>>>0';
var high = makeInlineCalculation(
- asmCoercion('Math.abs(VALUE)', 'double') + ' >= ' + asmEnsureFloat('1', 'double') + ' ? ' +
+ asmCoercion('Math_abs(VALUE)', 'double') + ' >= ' + asmEnsureFloat('1', 'double') + ' ? ' +
'(VALUE > ' + asmEnsureFloat('0', 'double') + ' ? ' +
- asmCoercion('Math.min(' + asmCoercion('Math.floor((VALUE)/' + asmEnsureFloat(4294967296, 'float') + ')', 'double') + ', ' + asmEnsureFloat(4294967295, 'float') + ')', 'i32') + '>>>0' +
- ' : ' + asmFloatToInt(asmCoercion('Math.ceil((VALUE - +((' + asmFloatToInt('VALUE') + ')>>>0))/' + asmEnsureFloat(4294967296, 'float') + ')', 'double')) + '>>>0' +
+ asmCoercion('Math_min(' + asmCoercion('Math_floor((VALUE)/' + asmEnsureFloat(4294967296, 'float') + ')', 'double') + ', ' + asmEnsureFloat(4294967295, 'float') + ')', 'i32') + '>>>0' +
+ ' : ' + asmFloatToInt(asmCoercion('Math_ceil((VALUE - +((' + asmFloatToInt('VALUE') + ')>>>0))/' + asmEnsureFloat(4294967296, 'float') + ')', 'double')) + '>>>0' +
')' +
' : 0',
value,
@@ -919,7 +930,10 @@ function parseNumerical(value, type) {
}
if (isNumber(value)) {
var ret = parseFloat(value); // will change e.g. 5.000000e+01 to 50
- if (type in Runtime.FLOAT_TYPES && value[0] == '-' && ret === 0) return '-0'; // fix negative 0, toString makes it 0
+ if (type in Runtime.FLOAT_TYPES) {
+ if (value[0] === '-' && ret === 0) return '-.0'; // fix negative 0, toString makes it 0
+ if (!RUNNING_JS_OPTS) ret = asmEnsureFloat(ret, type);
+ }
return ret.toString();
} else {
return value;
@@ -932,12 +946,12 @@ function parseLLVMString(str) {
var ret = [];
var i = 0;
while (i < str.length) {
- var chr = str[i];
- if (chr != '\\') {
- ret.push(chr.charCodeAt(0));
+ var chr = str.charCodeAt(i);
+ if (chr !== 92) { // 92 === '//'.charCodeAt(0)
+ ret.push(chr);
i++;
} else {
- ret.push(eval('0x' + str[i+1]+str[i+2]));
+ ret.push(parseInt(str[i+1]+str[i+2], '16'));
i += 3;
}
}
@@ -1125,7 +1139,16 @@ function asmEnsureFloat(value, type) { // ensures that a float type has either 5
if (!ASM_JS) return value;
// coerce if missing a '.', or if smaller than 1, so could be 1e-5 which has no .
if (type in Runtime.FLOAT_TYPES && isNumber(value) && (value.toString().indexOf('.') < 0 || Math.abs(value) < 1)) {
- return '(+(' + value + '))';
+ if (RUNNING_JS_OPTS) {
+ return '(+' + value + ')'; // JS optimizer will run, we must do +x, and it will be corrected later
+ } else {
+ // ensure a .
+ value = value.toString();
+ if (value.indexOf('.') >= 0 || /[IN]/.test(value)) return value; // if already dotted, or Infinity or NaN, nothing to do here
+ var e = value.indexOf('e');
+ if (e < 0) return value + '.0';
+ return value.substr(0, e) + '.0' + value.substr(e);
+ }
} else {
return value;
}
@@ -1133,7 +1156,11 @@ function asmEnsureFloat(value, type) { // ensures that a float type has either 5
function asmInitializer(type, impl) {
if (type in Runtime.FLOAT_TYPES) {
- return '+0';
+ if (RUNNING_JS_OPTS) {
+ return '+0';
+ } else {
+ return '.0';
+ }
} else {
return '0';
}
@@ -1348,6 +1375,7 @@ function makeSetValue(ptr, pos, value, type, noNeedFirst, ignore, align, noSafe,
value = indexizeFunctions(value, type);
var offset = calcFastOffset(ptr, pos, noNeedFirst);
+ if (phase === 'pre' && isNumber(offset)) offset += ' '; // avoid pure numeric strings, seem to be perf issues with overly-aggressive interning or slt in pre processing of heap inits
if (SAFE_HEAP && !noSafe) {
var printType = type;
if (printType !== 'null' && printType[0] !== '#') printType = '"' + safeQuote(printType) + '"';
@@ -1464,77 +1492,97 @@ function makeHEAPView(which, start, end) {
return 'HEAP' + which + '.subarray((' + start + ')' + mod + ',(' + end + ')' + mod + ')';
}
-var PLUS_MUL = set('+', '*');
-var MUL_DIV = set('*', '/');
-var PLUS_MINUS = set('+', '-');
var TWO_TWENTY = Math.pow(2, 20);
// Given two values and an operation, returns the result of that operation.
// Tries to do as much as possible at compile time.
// Leaves overflows etc. unhandled, *except* for integer multiply, in order to be efficient with Math.imul
function getFastValue(a, op, b, type) {
- a = a.toString();
- b = b.toString();
- a = a == 'true' ? '1' : (a == 'false' ? '0' : a);
- b = b == 'true' ? '1' : (b == 'false' ? '0' : b);
- if (isNumber(a) && isNumber(b)) {
- if (op == 'pow') {
- return Math.pow(a, b).toString();
- } else {
- var value = eval(a + op + '(' + b + ')'); // parens protect us from "5 - -12" being seen as "5--12" which is "(5--)12"
- if (op == '/' && type in Runtime.INT_TYPES) value = value|0; // avoid emitting floats
- return value.toString();
+ a = a === 'true' ? '1' : (a === 'false' ? '0' : a);
+ b = b === 'true' ? '1' : (b === 'false' ? '0' : b);
+
+ var aNumber = null, bNumber = null;
+ if (typeof a === 'number') {
+ aNumber = a;
+ a = a.toString();
+ } else if (isNumber(a)) aNumber = parseFloat(a);
+ if (typeof b === 'number') {
+ bNumber = b;
+ b = b.toString();
+ } else if (isNumber(b)) bNumber = parseFloat(b);
+
+ if (aNumber !== null && bNumber !== null) {
+ switch (op) {
+ case '+': return (aNumber + bNumber).toString();
+ case '-': return (aNumber - bNumber).toString();
+ case '*': return (aNumber * bNumber).toString();
+ case '/': {
+ if (type[0] === 'i') {
+ return ((aNumber / bNumber)|0).toString();
+ } else {
+ return (aNumber / bNumber).toString();
+ }
+ }
+ case '%': return (aNumber % bNumber).toString();
+ case '|': return (aNumber | bNumber).toString();
+ case '>>>': return (aNumber >>> bNumber).toString();
+ case '&': return (aNumber & bNumber).toString();
+ case 'pow': return Math.pow(aNumber, bNumber).toString();
+ default: throw 'need to implement getFastValue pn ' + op;
}
}
- if (op == 'pow') {
- if (a == '2' && isIntImplemented(type)) {
+ if (op === 'pow') {
+ if (a === '2' && isIntImplemented(type)) {
return '(1 << (' + b + '))';
}
- return 'Math.pow(' + a + ', ' + b + ')';
+ return 'Math_pow(' + a + ', ' + b + ')';
}
- if (op in PLUS_MUL && isNumber(a)) { // if one of them is a number, keep it last
+ if ((op === '+' || op === '*') && aNumber !== null) { // if one of them is a number, keep it last
var c = b;
b = a;
a = c;
- }
- if (op in MUL_DIV) {
- if (op == '*') {
- if (a == 0 || b == 0) {
- return '0';
- } else if (a == 1) {
- return b;
- } else if (b == 1) {
- return a;
- } else if (isNumber(b) && type && isIntImplemented(type) && Runtime.getNativeTypeSize(type) <= 32) {
- var shifts = Math.log(parseFloat(b))/Math.LN2;
- if (shifts % 1 == 0) {
- return '(' + a + '<<' + shifts + ')';
- }
+ var cNumber = bNumber;
+ bNumber = aNumber;
+ aNumber = cNumber;
+ }
+ if (op === '*') {
+ // We can't eliminate where a or b are 0 as that would break things for creating
+ // a negative 0.
+ if ((aNumber === 0 || bNumber === 0) && !(type in Runtime.FLOAT_TYPES)) {
+ return '0';
+ } else if (aNumber === 1) {
+ return b;
+ } else if (bNumber === 1) {
+ return a;
+ } else if (bNumber !== null && type && isIntImplemented(type) && Runtime.getNativeTypeSize(type) <= 32) {
+ var shifts = Math.log(bNumber)/Math.LN2;
+ if (shifts % 1 === 0) {
+ return '(' + a + '<<' + shifts + ')';
}
- if (!(type in Runtime.FLOAT_TYPES)) {
- // if guaranteed small enough to not overflow into a double, do a normal multiply
- var bits = getBits(type) || 32; // default is 32-bit multiply for things like getelementptr indexes
- // Note that we can emit simple multiple in non-asm.js mode, but asm.js will not parse "16-bit" multiple, so must do imul there
- if ((isNumber(a) && Math.abs(a) < TWO_TWENTY) || (isNumber(b) && Math.abs(b) < TWO_TWENTY) || (bits < 32 && !ASM_JS)) {
- return '(((' + a + ')*(' + b + '))&' + ((Math.pow(2, bits)-1)|0) + ')'; // keep a non-eliminatable coercion directly on this
- }
- return '(Math.imul(' + a + ',' + b + ')|0)';
+ }
+ if (!(type in Runtime.FLOAT_TYPES)) {
+ // if guaranteed small enough to not overflow into a double, do a normal multiply
+ var bits = getBits(type) || 32; // default is 32-bit multiply for things like getelementptr indexes
+ // Note that we can emit simple multiple in non-asm.js mode, but asm.js will not parse "16-bit" multiple, so must do imul there
+ if ((aNumber !== null && Math.abs(a) < TWO_TWENTY) || (bNumber !== null && Math.abs(b) < TWO_TWENTY) || (bits < 32 && !ASM_JS)) {
+ return '(((' + a + ')*(' + b + '))&' + ((Math.pow(2, bits)-1)|0) + ')'; // keep a non-eliminatable coercion directly on this
}
- } else {
- if (a == '0') {
- return '0';
- } else if (b == 1) {
- return a;
- } // Doing shifts for division is problematic, as getting the rounding right on negatives is tricky
- }
- } else if (op in PLUS_MINUS) {
- if (b[0] == '-') {
- op = op == '+' ? '-' : '+';
+ return '(Math_imul(' + a + ',' + b + ')|0)';
+ }
+ } else if (op === '/') {
+ if (a === '0' && !(type in Runtime.FLOAT_TYPES)) { // careful on floats, since 0*NaN is not 0
+ return '0';
+ } else if (b === 1) {
+ return a;
+ } // Doing shifts for division is problematic, as getting the rounding right on negatives is tricky
+ } else if (op === '+' || op === '-') {
+ if (b[0] === '-') {
+ op = op === '+' ? '-' : '+';
b = b.substr(1);
}
- if (a == 0) {
- return op == '+' ? b : '(-' + b + ')';
- } else if (b == 0) {
+ if (aNumber === 0) {
+ return op === '+' ? b : '(-' + b + ')';
+ } else if (bNumber === 0) {
return a;
}
}
@@ -1563,12 +1611,8 @@ function getFastValues(list, op, type) {
}
function calcFastOffset(ptr, pos, noNeedFirst) {
- var offset = noNeedFirst ? '0' : makeGetPos(ptr);
- return getFastValue(offset, '+', pos, 'i32');
-}
-
-function makeGetPos(ptr) {
- return ptr;
+ assert(!noNeedFirst);
+ return getFastValue(ptr, '+', pos, 'i32');
}
var IHEAP_FHEAP = set('IHEAP', 'IHEAPU', 'FHEAP');
@@ -1758,7 +1802,7 @@ function checkBitcast(item) {
} else {
warnOnce('Casting a function pointer type to a potentially incompatible one (use -s VERBOSE=1 to see more)');
}
- warnOnce('See https://github.com/kripken/emscripten/wiki/CodeGuidlinesAndLimitations#function-pointer-issues for more information on dangerous function pointer casts');
+ warnOnce('See https://github.com/kripken/emscripten/wiki/CodeGuidelinesAndLimitations#function-pointer-issues for more information on dangerous function pointer casts');
if (ASM_JS) warnOnce('Incompatible function pointer casts are very dangerous with ASM_JS=1, you should investigate and correct these');
}
if (oldCount != newCount && oldCount && newCount) showWarning();
@@ -1805,7 +1849,7 @@ function getGetElementPtrIndexes(item) {
// struct, and possibly further substructures, all embedded
// can also be to 'blocks': [8 x i32]*, not just structs
type = removePointing(type);
- var indexes = [makeGetPos(ident)];
+ var indexes = [ident];
var offset = item.params[1];
if (offset != 0) {
if (isStructType(type)) {
@@ -1860,8 +1904,10 @@ function handleOverflow(text, bits) {
if (CHECK_OVERFLOWS) return 'CHECK_OVERFLOW(' + text + ', ' + bits + ', ' + Math.floor(correctSpecificOverflow()) + ')';
if (!correct) return text;
if (bits == 32) {
+ if (isNumber(text)) return text | 0;
return '((' + text + ')|0)';
} else if (bits < 32) {
+ if (isNumber(text)) return text & (Math.pow(2, bits) - 1);
return '((' + text + ')&' + (Math.pow(2, bits) - 1) + ')';
} else {
return text; // We warned about this earlier
@@ -1951,7 +1997,7 @@ function makeComparison(a, op, b, type) {
return asmCoercion(a, type) + op + asmCoercion(b, type);
} else {
assert(type == 'i64');
- return asmCoercion(a + '$0', 'i32') + op + asmCoercion(b + '$0', 'i32') + ' & ' +
+ return asmCoercion(a + '$0', 'i32') + op + asmCoercion(b + '$0', 'i32') + '&' +
asmCoercion(a + '$1', 'i32') + op + asmCoercion(b + '$1', 'i32');
}
}
@@ -1960,13 +2006,12 @@ function makeSignOp(value, type, op, force, ignore) {
if (USE_TYPED_ARRAYS == 2 && type == 'i64') {
return value; // these are always assumed to be two 32-bit unsigneds.
}
-
if (isPointerType(type)) type = 'i32'; // Pointers are treated as 32-bit ints
if (!value) return value;
var bits, full;
if (type in Runtime.INT_TYPES) {
bits = parseInt(type.substr(1));
- full = op + 'Sign(' + value + ', ' + bits + ', ' + Math.floor(ignore || (correctSpecificSign())) + ')';
+ full = op + 'Sign(' + value + ', ' + bits + ', ' + Math.floor(ignore || correctSpecificSign()) + ')';
// Always sign/unsign constants at compile time, regardless of CHECK/CORRECT
if (isNumber(value)) {
return eval(full).toString();
@@ -1974,23 +2019,25 @@ function makeSignOp(value, type, op, force, ignore) {
}
if ((ignore || !correctSigns()) && !CHECK_SIGNS && !force) return value;
if (type in Runtime.INT_TYPES) {
+ // this is an integer, but not a number (or we would have already handled it)
// shortcuts
if (!CHECK_SIGNS || ignore) {
+ if (value === 'true') {
+ value = '1';
+ } else if (value === 'false') {
+ value = '0';
+ } else if (needsQuoting(value)) value = '(' + value + ')';
if (bits === 32) {
if (op === 're') {
- return '(' + getFastValue(value, '|', '0') + ')';
+ return '(' + value + '|0)';
} else {
-
- return '(' + getFastValue(value, '>>>', '0') + ')';
- // Alternatively, we can consider the lengthier
- // return makeInlineCalculation('VALUE >= 0 ? VALUE : ' + Math.pow(2, bits) + ' + VALUE', value, 'tempBigInt');
- // which does not always turn us into a 32-bit *un*signed value
+ return '(' + value + '>>>0)';
}
} else if (bits < 32) {
if (op === 're') {
- return makeInlineCalculation('(VALUE << ' + (32-bits) + ') >> ' + (32-bits), value, 'tempInt');
+ return '((' + value + '<<' + (32-bits) + ')>>' + (32-bits) + ')';
} else {
- return '(' + getFastValue(value, '&', Math.pow(2, bits)-1) + ')';
+ return '(' + value + '&' + (Math.pow(2, bits)-1) + ')';
}
} else { // bits > 32
if (op === 're') {
@@ -2018,12 +2065,12 @@ function makeRounding(value, bits, signed, floatConversion) {
// as |0, but &-1 hints to the js optimizer that this is a rounding correction
// Do Math.floor, which is reasonably fast, if we either don't care, or if we can be sure
// the value is non-negative
- if (!correctRoundings() || (!signed && !floatConversion)) return 'Math.floor(' + value + ')';
+ if (!correctRoundings() || (!signed && !floatConversion)) return 'Math_floor(' + value + ')';
// We are left with >32 bits signed, or a float conversion. Check and correct inline
// Note that if converting a float, we may have the wrong sign at this point! But, we have
// been rounded properly regardless, and we will be sign-corrected later when actually used, if
// necessary.
- return makeInlineCalculation(makeComparison('VALUE', '>=', '0', 'float') + ' ? Math.floor(VALUE) : Math.ceil(VALUE)', value, 'tempBigIntR');
+ return makeInlineCalculation(makeComparison('VALUE', '>=', '0', 'float') + ' ? Math_floor(VALUE) : Math_ceil(VALUE)', value, 'tempBigIntR');
} else {
// asm.js mode, cleaner refactoring of this function as well. TODO: use in non-asm case, most of this
if (floatConversion && bits <= 32) {
@@ -2038,9 +2085,9 @@ function makeRounding(value, bits, signed, floatConversion) {
}
}
// Math.floor is reasonably fast if we don't care about corrections (and even correct if unsigned)
- if (!correctRoundings() || !signed) return 'Math.floor(' + value + ')';
+ if (!correctRoundings() || !signed) return 'Math_floor(' + value + ')';
// We are left with >32 bits
- return makeInlineCalculation(makeComparison('VALUE', '>=', '0', 'float') + ' ? Math.floor(VALUE) : Math.ceil(VALUE)', value, 'tempBigIntR');
+ return makeInlineCalculation(makeComparison('VALUE', '>=', '0', 'float') + ' ? Math_floor(VALUE) : Math_ceil(VALUE)', value, 'tempBigIntR');
}
}
@@ -2051,7 +2098,7 @@ function makeIsNaN(value) {
function makeFloat(value, type) {
if (TO_FLOAT32 && type == 'float') {
- return 'Math.toFloat32(' + value + ')';
+ return 'Math_toFloat32(' + value + ')';
}
return value;
}
@@ -2080,7 +2127,7 @@ function processMathop(item) {
if (item.params[i]) {
paramTypes[i] = item.params[i].type || type;
idents[i] = finalizeLLVMParameter(item.params[i]);
- if (!isNumber(idents[i]) && !isNiceIdent(idents[i])) {
+ if (needsQuoting(idents[i])) {
idents[i] = '(' + idents[i] + ')'; // we may have nested expressions. So enforce the order of operations we want
}
} else {
@@ -2127,7 +2174,13 @@ function processMathop(item) {
// If this is in legalization mode, steal the assign and assign into two vars
if (legalizedI64s) {
assert(item.assignTo);
- var ret = 'var ' + item.assignTo + '$0 = ' + result[0] + '; var ' + item.assignTo + '$1 = ' + result[1] + ';';
+ if (ASM_JS) {
+ var ret = item.assignTo + '$0=' + result[0] + ';' + item.assignTo + '$1=' + result[1] + ';';
+ addVariable(item.assignTo + '$0', 'i32');
+ addVariable(item.assignTo + '$1', 'i32');
+ } else {
+ var ret = 'var ' + item.assignTo + '$0=' + result[0] + ';var ' + item.assignTo + '$1=' + result[1] + ';';
+ }
item.assignTo = null;
return ret;
} else {
@@ -2278,7 +2331,7 @@ function processMathop(item) {
dprint('Warning: 64 bit OR - precision limit may be hit on llvm line ' + item.lineNum);
return 'Runtime.or64(' + idents[0] + ', ' + idents[1] + ')';
}
- return idents[0] + ' | ' + idents[1];
+ return idents[0] + '|' + idents[1];
}
case 'and': {
if (bits > 32) {
@@ -2286,7 +2339,7 @@ function processMathop(item) {
dprint('Warning: 64 bit AND - precision limit may be hit on llvm line ' + item.lineNum);
return 'Runtime.and64(' + idents[0] + ', ' + idents[1] + ')';
}
- return idents[0] + ' & ' + idents[1];
+ return idents[0] + '&' + idents[1];
}
case 'xor': {
if (bits > 32) {
@@ -2294,21 +2347,21 @@ function processMathop(item) {
dprint('Warning: 64 bit XOR - precision limit may be hit on llvm line ' + item.lineNum);
return 'Runtime.xor64(' + idents[0] + ', ' + idents[1] + ')';
}
- return idents[0] + ' ^ ' + idents[1];
+ return idents[0] + '^' + idents[1];
}
case 'shl': {
if (bits > 32) return idents[0] + '*' + getFastValue(2, 'pow', idents[1]);
- return idents[0] + ' << ' + idents[1];
+ return idents[0] + '<<' + idents[1];
}
case 'ashr': {
if (bits > 32) return integerizeBignum(idents[0] + '/' + getFastValue(2, 'pow', idents[1]));
- if (bits === 32) return originalIdents[0] + ' >> ' + idents[1]; // No need to reSign in this case
- return idents[0] + ' >> ' + idents[1];
+ if (bits === 32) return originalIdents[0] + '>>' + idents[1]; // No need to reSign in this case
+ return idents[0] + '>>' + idents[1];
}
case 'lshr': {
if (bits > 32) return integerizeBignum(idents[0] + '/' + getFastValue(2, 'pow', idents[1]));
- if (bits === 32) return originalIdents[0] + ' >>> ' + idents[1]; // No need to unSign in this case
- return idents[0] + ' >>> ' + idents[1];
+ if (bits === 32) return originalIdents[0] + '>>>' + idents[1]; // No need to unSign in this case
+ return idents[0] + '>>>' + idents[1];
}
// basic float ops
case 'fadd': return makeFloat(getFastValue(idents[0], '+', idents[1], item.type), item.type);
@@ -2323,10 +2376,10 @@ function processMathop(item) {
// Note that with typed arrays, these become 0 when written. So that is a potential difference with non-typed array runs.
case 'icmp': {
switch (variant) {
- case 'uge': case 'sge': return idents[0] + ' >= ' + idents[1];
- case 'ule': case 'sle': return idents[0] + ' <= ' + idents[1];
- case 'ugt': case 'sgt': return idents[0] + ' > ' + idents[1];
- case 'ult': case 'slt': return idents[0] + ' < ' + idents[1];
+ case 'uge': case 'sge': return idents[0] + '>=' + idents[1];
+ case 'ule': case 'sle': return idents[0] + '<=' + idents[1];
+ case 'ugt': case 'sgt': return idents[0] + '>' + idents[1];
+ case 'ult': case 'slt': return idents[0] + '<' + idents[1];
// We use loose comparisons, which allows false == 0 to be true, etc. Ditto in fcmp
case 'ne': case 'eq': {
// We must sign them, so we do not compare -1 to 255 (could have unsigned them both too)
@@ -2342,14 +2395,14 @@ function processMathop(item) {
switch (variant) {
// TODO 'o' ones should be 'ordered (no NaN) and',
// 'u' ones should be 'unordered or'.
- case 'uge': case 'oge': return idents[0] + ' >= ' + idents[1];
- case 'ule': case 'ole': return idents[0] + ' <= ' + idents[1];
- case 'ugt': case 'ogt': return idents[0] + ' > ' + idents[1];
- case 'ult': case 'olt': return idents[0] + ' < ' + idents[1];
- case 'une': case 'one': return idents[0] + ' != ' + idents[1];
- case 'ueq': case 'oeq': return idents[0] + ' == ' + idents[1];
- case 'ord': return '!' + makeIsNaN(idents[0]) + ' & !' + makeIsNaN(idents[1]);
- case 'uno': return makeIsNaN(idents[0]) + ' | ' + makeIsNaN(idents[1]);
+ case 'uge': case 'oge': return idents[0] + '>=' + idents[1];
+ case 'ule': case 'ole': return idents[0] + '<=' + idents[1];
+ case 'ugt': case 'ogt': return idents[0] + '>' + idents[1];
+ case 'ult': case 'olt': return idents[0] + '<' + idents[1];
+ case 'une': case 'one': return idents[0] + '!=' + idents[1];
+ case 'ueq': case 'oeq': return idents[0] + '==' + idents[1];
+ case 'ord': return '!' + makeIsNaN(idents[0]) + '&!' + makeIsNaN(idents[1]);
+ case 'uno': return makeIsNaN(idents[0]) + '|' + makeIsNaN(idents[1]);
case 'true': return '1';
default: throw 'Unknown fcmp variant: ' + variant;
}
@@ -2365,7 +2418,7 @@ function processMathop(item) {
}
case 'fpext': case 'sext': return idents[0];
case 'fptrunc': return idents[0];
- case 'select': return idents[0] + ' ? ' + asmEnsureFloat(idents[1], item.type) + ' : ' + asmEnsureFloat(idents[2], item.type);
+ case 'select': return idents[0] + '?' + asmEnsureFloat(idents[1], item.type) + ':' + asmEnsureFloat(idents[2], item.type);
case 'ptrtoint': case 'inttoptr': {
var ret = '';
if (QUANTUM_SIZE == 1) {
@@ -2383,7 +2436,7 @@ function processMathop(item) {
// truncating can change the number, e.g. by truncating to an i1
// in order to get the first bit
assert(bitsLeft <= 32, 'Cannot truncate to more than 32 bits, since we use a native & op');
- return '((' + idents[0] + ') & ' + (Math.pow(2, bitsLeft)-1) + ')';
+ return '((' + idents[0] + ')&' + (Math.pow(2, bitsLeft)-1) + ')';
}
case 'bitcast': {
// Most bitcasts are no-ops for us. However, the exception is int to float and float to int
@@ -2519,3 +2572,34 @@ function makePrintChars(s, sep) {
return ret;
}
+function parseAlign(text) { // parse ", align \d+"
+ if (!text) return QUANTUM_SIZE;
+ return parseInt(text.substr(8));
+}
+
+function deParen(text) {
+ if (text[0] === '(') return text.substr(1, text.length-2);
+ return text;
+}
+
+function addVariable(ident, type, funcData) {
+ funcData = funcData || Framework.currItem.funcData;
+ assert(type);
+ var old = funcData.variables[ident];
+ if (old) {
+ assert(old.type === type);
+ } else {
+ funcData.variables[ident] = {
+ ident: ident,
+ type: type,
+ origin: 'added',
+ lineNum: 0,
+ rawLinesIndex: 0,
+ hasValueTaken: false,
+ pointingLevels: 0,
+ uses: 0,
+ impl: VAR_EMULATED
+ };
+ }
+}
+