aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2011-11-10 11:08:48 -0800
committerAlon Zakai <alonzakai@gmail.com>2011-11-10 11:08:48 -0800
commit74ad2855886778cf5957a460179b290b928ac994 (patch)
tree68cf67380e0f12a812e6de5b31b6868cf25fe539
parent2e67d240b5255b24dc5423d7797ffe196527dab3 (diff)
i64 fixes, first part of test_i64 passes
-rw-r--r--src/jsifier.js30
-rw-r--r--src/library.js6
-rw-r--r--src/parseTools.js68
-rw-r--r--src/preamble.js4
4 files changed, 60 insertions, 48 deletions
diff --git a/src/jsifier.js b/src/jsifier.js
index 64fe5e4a..b362009d 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -841,23 +841,43 @@ function JSify(data, functionsOnly, givenFunctions, givenGlobalVariables) {
var argsTypes = [];
var varargs = [];
var varargsTypes = [];
+ var ignoreFunctionIndexizing = [];
var useJSArgs = (shortident + '__jsargs') in LibraryManager.library;
params.forEach(function(param, i) {
var val = finalizeParam(param);
if (!func || !func.hasVarArgs || i < func.numParams-1 || useJSArgs) {
+ if (param.type == 'i64' && I64_MODE == 1) {
+ val = makeI64Copy(val); // Must copy [low, high] i64s, so they don't end up modified in the caller
+ }
args.push(val);
argsTypes.push(param.type);
} else {
- varargs.push(val);
- varargs = varargs.concat(zeros(getNativeFieldSize(param.type)-1));
- varargsTypes.push(param.type);
- varargsTypes = varargsTypes.concat(zeros(getNativeFieldSize(param.type)-1));
+ if (!(param.type == 'i64' && I64_MODE == 1)) {
+ varargs.push(val);
+ varargs = varargs.concat(zeros(getNativeFieldSize(param.type)-1));
+ varargsTypes.push(param.type);
+ varargsTypes = varargsTypes.concat(zeros(getNativeFieldSize(param.type)-1));
+ } else {
+ // i64 mode 1. Write one i32 with type i64, and one i32 with type i32
+ varargs.push(val + '[0]');
+ varargs = varargs.concat(zeros(getNativeFieldSize('i32')-1));
+ ignoreFunctionIndexizing.push(varargs.length); // We will have a value there, but no type (the type is i64, but we write two i32s)
+ varargs.push(val + '[1]');
+ varargs = varargs.concat(zeros(getNativeFieldSize('i32')-1));
+ varargsTypes.push('i64');
+ varargsTypes = varargsTypes.concat(zeros(getNativeFieldSize('i32')-1));
+ varargsTypes.push('i32');
+ varargsTypes = varargsTypes.concat(zeros(getNativeFieldSize('i32')-1));
+ }
}
});
args = args.map(function(arg, i) { return indexizeFunctions(arg, argsTypes[i]) });
- varargs = varargs.map(function(vararg, i) { return vararg === 0 ? 0 : indexizeFunctions(vararg, varargsTypes[i]) });
+ varargs = varargs.map(function(vararg, i) {
+ if (ignoreFunctionIndexizing.indexOf(i) >= 0) return vararg;
+ return vararg === 0 ? 0 : indexizeFunctions(vararg, varargsTypes[i])
+ });
if (func && func.hasVarArgs && !useJSArgs) {
if (varargs.length === 0) {
diff --git a/src/library.js b/src/library.js
index cb6a2ea3..4bb74001 100644
--- a/src/library.js
+++ b/src/library.js
@@ -2205,6 +2205,12 @@ LibraryManager.library = {
var ret;
if (type === 'float' || type === 'double') {
ret = {{{ makeGetValue('varargs', 'argIndex', 'double', undefined, undefined, true) }}};
+#if I64_MODE == 1
+ } else if (type == 'i64') {
+ ret = [{{{ makeGetValue('varargs', 'argIndex', 'i32', undefined, undefined, true) }}},
+ {{{ makeGetValue('varargs', 'argIndex+4', 'i32', undefined, undefined, true) }}}];
+ ret = ret[0] + ret[1]*Math.pow(2, 32); // XXX - loss of precision
+#endif
} else {
ret = {{{ makeGetValue('varargs', 'argIndex', 'i32', undefined, undefined, true) }}};
}
diff --git a/src/parseTools.js b/src/parseTools.js
index 879c8537..b7ea28e1 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -526,6 +526,16 @@ function IEEEUnHex(stringy) {
return (absolute * (neg ? -1 : 1)).toString();
}
+// 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 makeCopyI64(value) {
assert(I64_MODE == 1);
@@ -774,16 +784,6 @@ 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) {
return offset;
@@ -1357,7 +1357,7 @@ function processMathop(item) { with(item) {
return '(tempBigInt=(' + value + '), tempBigInt-tempBigInt%1)';
}
- if (item.type == 'i64' && I64_MODE == 1) {
+ if ((paramTypes[0] == 'i64' || paramTypes[1] == 'i64') && I64_MODE == 1) {
switch (op) {
// basic integer ops
case 'or': {
@@ -1371,27 +1371,27 @@ function processMathop(item) { with(item) {
}
case 'shl': {
return '[' + ident1 + '[0] << ' + ident2 + ', ' +
- '('+ident1 + '[1] << ' + ident2 + ') | ((' + ident + '[0]&((Math.pow(2, ' + ident2 + ')-1)<<(32-' + ident2 + ') >> (32-' + ident2 + '))]';
+ '('+ident1 + '[1] << ' + ident2 + ') | (' + ident1 + '[0]&(Math.pow(2, ' + ident2 + ')-1)<<(32-' + ident2 + ') >> (32-' + ident2 + '))]';
}
case 'ashr': {
- return '[('+ident1 + '[0] >> ' + ident2 + ') | ((' + ident + '[1]&((Math.pow(2, ' + ident2 + ')-1)<<(32-' + ident2 + ') >> (32-' + ident2 + '))]';
- + ident1 + '[1] >> ' + ident2 + ']';
+ return '[('+ident1 + '[0] >> ' + ident2 + ') | (' + ident1 + '[1]&(Math.pow(2, ' + ident2 + ')-1)<<(32-' + ident2 + ') >> (32-' + ident2 + ')),' +
+ ident1 + '[1] >> ' + ident2 + ']';
}
case 'lshr': {
- return '[('+ident1 + '[0] >>> ' + ident2 + ') | ((' + ident + '[1]&((Math.pow(2, ' + ident2 + ')-1)<<(32-' + ident2 + ') >> (32-' + ident2 + '))]';
- + ident1 + '[1] >>> ' + ident2 + ']';
+ return '[('+ident1 + '[0] >>> ' + ident2 + ') | (' + ident1 + '[1]&(Math.pow(2, ' + ident2 + ')-1)<<(32-' + ident2 + ') >> (32-' + ident2 + ')),' +
+ ident1 + '[1] >>> ' + ident2 + ']';
}
-
+ case 'uitofp': case 'sitofp': return ident1 + '[0] + ' + ident1 + '[1]*4294967296';
case 'icmp': {
switch (variant) {
case 'uge': case 'sge': return ident1 + '[1] >= ' + ident2 + '[1] && (' + ident1 + '[1] > ' + ident2 + '[1] || ' +
- '(' + ident1 + '[0] >= ' + ident2 + '[0]');
+ ident1 + '[0] >= ' + ident2 + '[0])';
case 'ule': case 'sle': return ident1 + '[1] <= ' + ident2 + '[1] && (' + ident1 + '[1] < ' + ident2 + '[1] || ' +
- '(' + ident1 + '[0] <= ' + ident2 + '[0]');
+ ident1 + '[0] <= ' + ident2 + '[0])';
case 'ugt': case 'sgt': return ident1 + '[1] > ' + ident2 + '[1] || (' + ident1 + '[1] = ' + ident2 + '[1] && ' +
- '(' + ident1 + '[0] > ' + ident2 + '[0]');
+ ident1 + '[0] > ' + ident2 + '[0])';
case 'ult': case 'slt': return ident1 + '[1] < ' + ident2 + '[1] || (' + ident1 + '[1] = ' + ident2 + '[1] && ' +
- '(' + ident1 + '[0] < ' + ident2 + '[0]');
+ ident1 + '[0] < ' + ident2 + '[0])';
case 'ne': case 'eq': {
// We must sign them, so we do not compare -1 to 255 (could have unsigned them both too)
// since LLVM tells us if <=, >= etc. comparisons are signed, but not == and !=.
@@ -1406,30 +1406,12 @@ function processMathop(item) { with(item) {
default: throw 'Unknown icmp variant: ' + variant;
}
}
- case 'zext': case 'sext': return makeCopyI64(ident1);
+ case 'zext': case 'sext': return makeI64(ident1, 0);
case 'trunc': {
- // Unlike extending, which we just 'do' (by doing nothing),
- // truncating can change the number, e.g. by truncating to an i1
- // in order to get the first bit
- assert(ident2[1] == 'i');
- assert(bitsLeft <= 32, 'Cannot truncate to more than 32 bits, since we use a native & op');
- return '((' + ident1 + ') & ' + (Math.pow(2, bitsLeft)-1) + ')';
- }
- case 'select': return ident1 + ' ? ' + ident2 + ' : ' + ident3;
- case 'ptrtoint': case 'inttoptr': {
- var ret = '';
- if (QUANTUM_SIZE == 1) {
- if (!Debugging.shownPtrtointWarning) {
- dprint('WARNING: .ll contains ptrtoint and/or inttoptr. These may be dangerous in QUANTUM == 1.');
- dprint(' The safest thing is to investigate every appearance, and modify the source code to avoid this.');
- dprint(' Emscripten will print a list of the .ll lines, and also annotate the .js.');
- Debugging.shownPtrtointWarning = true;
- }
- dprint(' ' + op + ' on .ll line ' + item.lineNum);
- ret = ' /* Warning: ' + op + ', .ll line ' + item.lineNum + ' */';
- }
- return ident1 + ret;
+ return '((' + ident1 + '[0]) & ' + (Math.pow(2, bitsLeft)-1) + ')';
}
+ case 'select': return ident1 + ' ? ' + makeCopyI64(ident2) + ' : ' + makeCopyI64(ident3);
+ case 'ptrtoint': case 'inttoptr': throw 'Pointers cannot be 64-bit!';
default: throw 'Unsupported i64 mode 1 op: ' + item.op;
}
}
diff --git a/src/preamble.js b/src/preamble.js
index ec9e672e..51d100e1 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -474,6 +474,10 @@ function allocate(slab, types, allocator) {
assert(type, 'Must know what type to store in allocate!');
#endif
+#if I64_MODE == 1
+ if (type == 'i64') type = 'i32'; // special case: we have one i32 here, and one i32 later
+#endif
+
setValue(ret+i, curr, type);
i += Runtime.getNativeTypeSize(type);
}