diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/analyzer.js | 1 | ||||
-rw-r--r-- | src/jsifier.js | 43 | ||||
-rw-r--r-- | src/preamble.js | 19 | ||||
-rw-r--r-- | src/settings.js | 8 | ||||
-rw-r--r-- | src/utility.js | 2 |
5 files changed, 44 insertions, 29 deletions
diff --git a/src/analyzer.js b/src/analyzer.js index 936482a3..4aad192b 100644 --- a/src/analyzer.js +++ b/src/analyzer.js @@ -241,6 +241,7 @@ function analyzer(data, givenTypes) { // Normal variables func.lines.forEach(function(item) { if (item.intertype in set('assign', 'fastgetelementptrload')) { + if (!item.value.tokens.slice(-1)[0].item) throw 'Did you run llvm-dis with -show-annotations?'; func.variables[item.ident] = { ident: item.ident, type: item.value.type, diff --git a/src/jsifier.js b/src/jsifier.js index f4565bcc..1404e63f 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -156,7 +156,7 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions) { return [finalizeLLVMFunctionCall(value)]; } else if (Runtime.isNumberType(type) || pointingLevels(type) >= 1) { return indexizeFunctions(parseNumerical(toNiceIdent(value.text))); - } else if (value.text == 'zeroinitializer') { + } else if (value.text in set('zeroinitializer', 'undef')) { // undef doesn't really need initting, but why not return makeEmptyStruct(type); } else if (value.text && value.text[0] == '"') { value.text = value.text.substr(1, value.text.length-2); @@ -709,18 +709,24 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions) { ident2 = makeUnSign(ident2, type); } } + function checkOverflow(text) { + if (!CHECK_OVERFLOWS) return text; + if (item.type[0] !== 'i') return text; + var bits = item.type.substr(1); + return 'CHECK_OVERFLOW(' + text + ', ' + bits + ')'; + } switch (op) { - case 'add': return ident1 + ' + ' + ident2; - case 'sub': return ident1 + ' - ' + ident2; - case 'sdiv': case 'udiv': return 'Math.floor(' + ident1 + ' / ' + ident2 + ')'; - case 'mul': return ident1 + ' * ' + ident2; + case 'add': return checkOverflow(ident1 + ' + ' + ident2); + case 'sub': return checkOverflow(ident1 + ' - ' + ident2); + case 'sdiv': case 'udiv': return checkOverflow('Math.floor(' + ident1 + ' / ' + ident2 + ')'); + case 'mul': return checkOverflow(ident1 + ' * ' + ident2); case 'urem': case 'srem': return 'Math.floor(' + ident1 + ' % ' + ident2 + ')'; - case 'or': return ident1 + ' | ' + ident2; - case 'and': return ident1 + ' & ' + ident2; - case 'xor': return ident1 + ' ^ ' + ident2; - case 'shl': return ident1 + ' << ' + ident2; - case 'ashr': return ident1 + ' >> ' + ident2; - case 'lshr': return ident1 + ' >>> ' + ident2; + case 'or': return ident1 + ' | ' + ident2; // XXX this forces into a 32-bit int - add overflow-style checks? + case 'and': return ident1 + ' & ' + ident2; // XXX ^ + case 'xor': return ident1 + ' ^ ' + ident2; // XXX ^ + case 'shl': return ident1 + ' << ' + ident2; // XXX ^ + case 'ashr': return ident1 + ' >> ' + ident2; // XXX ^ + case 'lshr': return ident1 + ' >>> ' + ident2; // XXX ^ case 'fadd': return ident1 + ' + ' + ident2; case 'fsub': return ident1 + ' - ' + ident2; case 'fdiv': return ident1 + ' / ' + ident2; @@ -775,18 +781,6 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions) { default: throw 'Unknown mathcmp op: ' + item.op; } } }); -/* - return [{ - __result__: true, - intertype: 'mathop', - op: op, - variant: variant, - type: item.tokens[1].text, - ident: item.tokens[2].text, - value: item.tokens[4].text, - lineNum: item.lineNum, - }]; -*/ // Given two values and an operation, returns the result of that operation. // Tries to do as much as possible at compile time. @@ -881,7 +875,8 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions) { case 'icmp': case 'mul': case 'zext': // TODO: Other mathops var temp = { op: item.intertype, - variant: item.variant + variant: item.variant, + type: item.type }; for (var i = 1; i <= 4; i++) { if (item.params[i-1]) { diff --git a/src/preamble.js b/src/preamble.js index c895231f..a4e685d0 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -75,6 +75,14 @@ function __Z18UNPROTECT_HEAPADDRPv(dest) { //========================================== #endif +#if CHECK_OVERFLOWS +function CHECK_OVERFLOW(value, bits) { + assert(value !== Infinity && value !== -Infinity, 'Infinity!'); + assert(Math.abs(value) < Math.pow(2, bits-1), 'Overflow!'); + return value; +} +#endif + #if LABEL_DEBUG var INDENT = ''; #endif @@ -87,12 +95,15 @@ var ABORT = false; var undef = 0; +function abort(text) { + print(text + ':\n' + (new Error).stack); + ABORT = true; + throw "Assertion: " + text; +} + function assert(condition, text) { if (!condition) { - var text = "Assertion failed: " + text; - print(text + ':\n' + (new Error).stack); - ABORT = true; - throw "Assertion: " + text; + abort('Assertion failed: ' + text); } } diff --git a/src/settings.js b/src/settings.js index 04bfa79a..62143fa9 100644 --- a/src/settings.js +++ b/src/settings.js @@ -34,6 +34,14 @@ SAFE_HEAP = 0; // Check each write to the heap against a list of blocked address LABEL_DEBUG = 0; // Print out labels and functions as we enter them EXCEPTION_DEBUG = 0; // Print out exceptions in emscriptened code EXECUTION_TIMEOUT = -1; // Throw an exception after X seconds - useful to debug infinite loops +CHECK_OVERFLOWS = 0; // Add code that checks for overflows in integer math operations. + // There is currently not much to do to handle overflows if they occur. + // We can add code to simulate i32/i64 overflows in JS, but that would + // be very slow. It probably makes more sense to avoid overflows in + // C/C++ code. For example, if you have an int that you multiply by + // some factor, in order to get 'random' hash values - by taking + // that |value & hash_table_size| - then multiplying enough times will overflow. + // But instead, you can do |value = value & 30_BITS| in each iteration. // Compiler debugging options DEBUG_TAGS_SHOWING = []; diff --git a/src/utility.js b/src/utility.js index 8b014957..ec4bf99b 100644 --- a/src/utility.js +++ b/src/utility.js @@ -16,7 +16,7 @@ function dump(item) { return ret + '// ' + text; } try { - return lineify(JSON.stringify(item)); + return lineify(JSON.stringify(item).substr(0, 80*25)); } catch(e) { var ret = []; for (var i in item) { |