diff options
author | Alon Zakai <alonzakai@gmail.com> | 2011-06-09 15:53:55 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2011-06-09 15:53:55 -0700 |
commit | e9e7efa370ee972dc34dd86f1e4e114588e63840 (patch) | |
tree | 3590b8d9ec266d1c60d16f1b02993afa219126b9 /src/parseTools.js | |
parent | fa4c3a7de17c36d80977d1ba0b1bb868f7531dc7 (diff) |
sign analyzer for ta==2
Diffstat (limited to 'src/parseTools.js')
-rw-r--r-- | src/parseTools.js | 54 |
1 files changed, 42 insertions, 12 deletions
diff --git a/src/parseTools.js b/src/parseTools.js index 1311f8d3..ad6f288f 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -672,12 +672,12 @@ function getHeapOffset(offset, type) { } // See makeSetValue -function makeGetValue(ptr, pos, type, noNeedFirst) { +function makeGetValue(ptr, pos, type, noNeedFirst, unsigned) { if (isStructType(type)) { var typeData = Types.types[type]; var ret = []; for (var i = 0; i < typeData.fields.length; i++) { - ret.push('f' + i + ': ' + makeGetValue(ptr, pos + typeData.flatIndexes[i], typeData.fields[i], noNeedFirst)); + ret.push('f' + i + ': ' + makeGetValue(ptr, pos + typeData.flatIndexes[i], typeData.fields[i], noNeedFirst, unsigned)); } return '{ ' + ret.join(', ') + ' }'; } @@ -686,9 +686,9 @@ function makeGetValue(ptr, pos, type, noNeedFirst) { if (SAFE_HEAP) { if (type !== 'null' && type[0] !== '#') type = '"' + safeQuote(type) + '"'; if (type[0] === '#') type = type.substr(1); - return 'SAFE_HEAP_LOAD(' + offset + ', ' + type + ', ' + !checkSafeHeap() + ')'; + return 'SAFE_HEAP_LOAD(' + offset + ', ' + type + ', ' + (!!unsigned+0) + ', ' + (!checkSafeHeap()+0) + ')'; } else { - return makeGetSlabs(ptr, type)[0] + '[' + getHeapOffset(offset, type) + ']'; + return makeGetSlabs(ptr, type, false, unsigned)[0] + '[' + getHeapOffset(offset, type) + ']'; } } @@ -860,7 +860,7 @@ function makePointer(slab, pos, allocator, type) { ')'; } -function makeGetSlabs(ptr, type, allowMultiple) { +function makeGetSlabs(ptr, type, allowMultiple, unsigned) { assert(type); if (!USE_TYPED_ARRAYS) { return ['HEAP']; @@ -883,12 +883,11 @@ function makeGetSlabs(ptr, type, allowMultiple) { } } switch(type) { - case 'i1': return ['HEAP8']; break; - case 'i8': return ['HEAP8']; break; - case 'i16': return ['HEAP16']; break; - case 'i32': return ['HEAP32']; break; + case 'i1': case 'i8': return [unsigned ? 'HEAPU8' : 'HEAP8']; break; + case 'i16': return [unsigned ? 'HEAPU16' : 'HEAP16']; break; + case 'i64': warn64(); + case 'i32': return [unsigned ? 'HEAPU32' : 'HEAP32']; break; case 'float': return ['HEAPF32']; break; - case 'i64': warn64(); return ['HEAP32']; break; case 'double': warn64(); return ['HEAPF32']; break; default: { throw 'what, exactly, can we do for unknown types in TA2?! ' + new Error().stack; @@ -1048,6 +1047,14 @@ function makeRounding(value, bits, signed) { return 'Math.floor(' + value + ')'; } +function isUnsignedOp(op, variant) { + return op in set('udiv', 'urem', 'uitofp', 'zext', 'lshr') || (variant && variant[0] == 'u'); +} + +function isSignedOp(op, variant) { + return op in set('sdiv', 'srem', 'sitofp', 'sext', 'ashr') || (variant && variant[0] == 's'); +} + function processMathop(item) { with(item) { for (var i = 1; i <= 4; i++) { if (item['param'+i]) { @@ -1059,10 +1066,10 @@ function processMathop(item) { with(item) { item['ident'+i] = null; // just so it exists for purposes of reading ident2 etc. later on, and no exception is thrown } } - if (op in set('udiv', 'urem', 'uitofp', 'zext', 'lshr') || (variant && variant[0] == 'u')) { + if (isUnsignedOp(op, variant)) { ident1 = makeSignOp(ident1, type, 'un'); ident2 = makeSignOp(ident2, type, 'un'); - } else if (op in set('sdiv', 'srem', 'sitofp', 'sext', 'ashr') || (variant && variant[0] == 's')) { + } else if (isSignedOp(op, variant)) { ident1 = makeSignOp(ident1, type, 're'); ident2 = makeSignOp(ident2, type, 're'); } @@ -1200,3 +1207,26 @@ function processMathop(item) { with(item) { } } } +// Walks through some intertype data, calling a function at every item. If +// the function returns true, will stop the walk. +// TODO: Use this in analyzer, possibly also in jsifier +function walkInterdata(item, pre, post, obj) { + if (!item || !item.intertype) return false; +//print(' walk: ' + [item.lineNum, item.intertype]); +//if (item.intertype === 'value') print(dump(item)); + if (pre(item, obj)) return true; + var originalObj = obj; + if (obj.replaceWith) obj = obj.replaceWith; // allow pre to replace the object we pass to all its children + if (item.value && walkInterdata(item.value, pre, post, obj)) return true; + var i; + for (i = 1; i <= 4; i++) { + if (item['param'+i] && walkInterdata(item['param'+i], pre, post, obj)) return true; + } + if (item.params) { + for (i = 0; i <= item.params.length; i++) { + if (walkInterdata(item.params[i], pre, post, obj)) return true; + } + } + return post(item, originalObj, obj); +} + |