diff options
author | Alon Zakai <alonzakai@gmail.com> | 2011-11-09 17:48:15 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2011-11-09 17:48:15 -0800 |
commit | 35ee8e8ec0e5583faec00ade5f1c2bd24c19672b (patch) | |
tree | 4ad27edc11a3866bcaed14f6390b88c0a3e6f044 /src | |
parent | c5e70d1abcaa7779c3a8692d77745b3d3da9e3b4 (diff) |
initial work on i64
Diffstat (limited to 'src')
-rw-r--r-- | src/analyzer.js | 2 | ||||
-rw-r--r-- | src/jsifier.js | 4 | ||||
-rw-r--r-- | src/library.js | 4 | ||||
-rw-r--r-- | src/parseTools.js | 76 | ||||
-rw-r--r-- | src/settings.js | 6 |
5 files changed, 86 insertions, 6 deletions
diff --git a/src/analyzer.js b/src/analyzer.js index d0510e6e..366e2e02 100644 --- a/src/analyzer.js +++ b/src/analyzer.js @@ -361,6 +361,8 @@ function analyzer(data) { variable.impl = VAR_EMULATED; } else if (variable.origin == 'funcparam') { variable.impl = VAR_EMULATED; + } else if (variable.type == 'i64*' && I64_MODE == 1) { + variable.impl = VAR_EMULATED; } else if (OPTIMIZE && variable.pointingLevels === 0 && !variable.hasAddrTaken) { // A simple int value, can be implemented as a native variable variable.impl = VAR_NATIVE; diff --git a/src/jsifier.js b/src/jsifier.js index 021572f3..64fe5e4a 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -645,9 +645,9 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) { break; case VAR_EMULATED: if (item.pointer.intertype == 'value') { - return makeSetValue(item.ident, 0, value, item.valueType); + return makeSetValue(item.ident, 0, value, item.valueType) + ';'; } else { - return makeSetValue(0, finalizeLLVMParameter(item.pointer), value, item.valueType); + return makeSetValue(0, finalizeLLVMParameter(item.pointer), value, item.valueType) + ';'; } break; default: diff --git a/src/library.js b/src/library.js index 73caa37c..cb6a2ea3 100644 --- a/src/library.js +++ b/src/library.js @@ -706,8 +706,8 @@ LibraryManager.library = { mode = obj.link === undefined ? 0x8000 : 0xA000; // S_IFREG, S_IFLNK. } } - {{{ makeSetValue('buf', 'offsets.st_dev', 'dev', 'i64') }}} - {{{ makeSetValue('buf', 'offsets.st_rdev', 'rdev', 'i64') }}} + {{{ makeSetValue('buf', 'offsets.st_dev', makeI64('dev'), 'i64') }}} + {{{ makeSetValue('buf', 'offsets.st_rdev', makeI64('rdev'), 'i64') }}} // NOTE: These two may be i64, depending on compilation options. {{{ makeSetValue('buf', 'offsets.st_size', 'size', 'i32') }}} {{{ makeSetValue('buf', 'offsets.st_blocks', 'blocks', 'i32') }}} diff --git a/src/parseTools.js b/src/parseTools.js index 567e0ce1..89aab8d9 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -526,11 +526,64 @@ function IEEEUnHex(stringy) { return (absolute * (neg ? -1 : 1)).toString(); } +function parseI64Constant(v) { + assert(I64_MODE == 1); + + if (!isNumber(v)) { + // This is a variable. Copy it, so we do not modify the original + return v + '.slice(0)'; + } + + function getDigit(i) { + return v.charCodeAt(i) - '0'.charCodeAt(0); + } + function setDigit(i, d) { + v = v.substr(0, i) + String.fromCharCode(d + '0'.charCodeAt(0)) + v.substr(i+1); + } + function divide2() { + for (var i = v.length-1; i >= 0; i--) { + var d = getDigit(i); + var r = d % 2; + d = Math.floor(d/2); + setDigit(i, d); + if (r) { + assert(i+1 < v.length); + var d2 = getDigit(i+1); + d2 += 5; + if (d2 >= 10) { + setDigit(i, d+1); + d2 -= 10; + } + setDigit(i+1, d2); + } + } + } + + var bits = []; + while (!v.match(/^0+$/)) { + bits.push((getDigit(v.length-1) % 2 != 0)+0); + setDigit(v.length-1, getDigit(v.length-1) & 0xfe); + divide2(); + } + + var low = 0, high = 0; + for (var i = 0; i < bits.length; i++) { + if (i <= 31) { + low += bits[i]*Math.pow(2, i); + } else { + high += bits[i]*Math.pow(2, i-32); + } + } + return '[' + low + ',' + high + ']'; +} + function parseNumerical(value, type) { if ((!type || type == 'double' || type == 'float') && (value.substr && value.substr(0,2) == '0x')) { // Hexadecimal double value, as the llvm docs say, // "The one non-intuitive notation for constants is the hexadecimal form of floating point constants." value = IEEEUnHex(value); + } else if (type == 'i64' && I64_MODE == 1) { + value = parseI64Constant(value); } else if (value == 'null') { // NULL *is* 0, in C/C++. No JS null! (null == 0 is false, etc.) value = '0'; @@ -715,6 +768,15 @@ function checkSafeHeap() { return SAFE_HEAP === 1 || checkSpecificSafeHeap(); } +// Makes a proper runtime value for a 64-bit value. Used in library. +function makeI64(low, high) { + if (I64_MODE == 1) { + return '[' + low + ',' + (high || '0') + ']'; + } else { + assert(!high); + return low; + } +} function getHeapOffset(offset, type) { if (USE_TYPED_ARRAYS !== 2) { @@ -743,6 +805,11 @@ function makeGetValue(ptr, pos, type, noNeedFirst, unsigned, ignore) { return '{ ' + ret.join(', ') + ' }'; } + if (type == 'i64' && I64_MODE == 1) { + return '[' + makeGetValue(ptr, pos, 'i32', noNeedFirst, unsigned, ignore) + ',' + + makeGetValue(ptr, getFastValue(pos, '+', getNativeTypeSize('i32')), 'i32', noNeedFirst, unsigned, ignore) + ']'; + } + var offset = calcFastOffset(ptr, pos, noNeedFirst); if (SAFE_HEAP) { if (type !== 'null' && type[0] !== '#') type = '"' + safeQuote(type) + '"'; @@ -791,14 +858,19 @@ function makeSetValue(ptr, pos, value, type, noNeedFirst, ignore) { return ret.join('; '); } + if (type == 'i64' && I64_MODE == 1) { + return '(' + makeSetValue(ptr, pos, value + '[0]', 'i32', noNeedFirst, ignore) + ',' + + makeSetValue(ptr, getFastValue(pos, '+', getNativeTypeSize('i32')), value + '[1]', 'i32', noNeedFirst, ignore) + ')'; + } + value = indexizeFunctions(value, type); var offset = calcFastOffset(ptr, pos, noNeedFirst); if (SAFE_HEAP) { if (type !== 'null' && type[0] !== '#') type = '"' + safeQuote(type) + '"'; if (type[0] === '#') type = type.substr(1); - return 'SAFE_HEAP_STORE(' + offset + ', ' + value + ', ' + type + ', ' + ((!checkSafeHeap() || ignore)|0) + ');'; + return 'SAFE_HEAP_STORE(' + offset + ', ' + value + ', ' + type + ', ' + ((!checkSafeHeap() || ignore)|0) + ')'; } else { - return makeGetSlabs(ptr, type, true).map(function(slab) { return slab + '[' + getHeapOffset(offset, type) + ']=' + value }).join('; ') + ';'; + return makeGetSlabs(ptr, type, true).map(function(slab) { return slab + '[' + getHeapOffset(offset, type) + ']=' + value }).join('; '); } } diff --git a/src/settings.js b/src/settings.js index 17f3f5e8..c5894b87 100644 --- a/src/settings.js +++ b/src/settings.js @@ -50,6 +50,12 @@ USE_TYPED_ARRAYS = 0; // Try to use typed arrays for the heap // TODO: require compiling with -malign-double, which does align doubles USE_FHEAP = 1; // Relevant in USE_TYPED_ARRAYS == 1. If this is disabled, only IHEAP will be used, and FHEAP // not generated at all. This is useful if your code is 100% ints without floats or doubles +I64_MODE = 0; // How to implement 64-bit integers: + // 0: As doubles. This will work up to about 53 bits. + // 1: As [low, high]. This will support all 64 bits for bit ops, etc., but not full math. + // TODO: reuse these arrays/escape analysis to avoid GC + // 2: Full bignum support. TODO + SKIP_STACK_IN_SMALL = 1; // When enabled, does not push/pop the stack at all in // functions that have no basic stack usage. But, they // may allocate stack later, and in a loop, this can be |