aboutsummaryrefslogtreecommitdiff
path: root/src/jsifier.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/jsifier.js')
-rw-r--r--src/jsifier.js93
1 files changed, 52 insertions, 41 deletions
diff --git a/src/jsifier.js b/src/jsifier.js
index 5ad1573b..01ecd7d3 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -71,7 +71,7 @@ function JSify(data, functionsOnly, givenFunctions) {
}
}
} else {
- libFuncsToInclude = ['memcpy', 'memset', 'malloc', 'free'];
+ libFuncsToInclude = ['memcpy', 'memset', 'malloc', 'free', '$Browser'];
}
libFuncsToInclude.forEach(function(ident) {
data.functionStubs.push({
@@ -166,23 +166,27 @@ function JSify(data, functionsOnly, givenFunctions) {
ret[index++] = 0;
}
// Add current value(s)
- var currValue = flatten(values[i]);
+ var currValue = values[i];
if (USE_TYPED_ARRAYS == 2 && typeData.fields[i] == 'i64') {
// 'flatten' out the 64-bit value into two 32-bit halves
- ret[index++] = currValue>>>0;
+ var parts = parseI64Constant(currValue, true);
+ ret[index++] = parts[0];
ret[index++] = 0;
ret[index++] = 0;
ret[index++] = 0;
- ret[index++] = Math.floor(currValue/4294967296);
+ ret[index++] = parts[1];
ret[index++] = 0;
ret[index++] = 0;
ret[index++] = 0;
- } else if (typeof currValue == 'object') {
- for (var j = 0; j < currValue.length; j++) {
- ret[index++] = currValue[j];
- }
} else {
- ret[index++] = currValue;
+ currValue = flatten(currValue);
+ if (typeof currValue == 'object') {
+ for (var j = 0; j < currValue.length; j++) {
+ ret[index++] = currValue[j];
+ }
+ } else {
+ ret[index++] = currValue;
+ }
}
i += 1;
}
@@ -279,7 +283,7 @@ function JSify(data, functionsOnly, givenFunctions) {
var val = LibraryManager.library[shortident];
var padding;
if (Runtime.isNumberType(item.type) || isPointerType(item.type)) {
- padding = [item.type].concat(zeros(Runtime.getNativeFieldSize(item.type)));
+ padding = [item.type].concat(zeros(Runtime.getNativeFieldSize(item.type)-1));
} else {
padding = makeEmptyStruct(item.type);
}
@@ -371,11 +375,15 @@ function JSify(data, functionsOnly, givenFunctions) {
processItem: function(item) {
function addFromLibrary(ident) {
if (ident in addedLibraryItems) return '';
+ addedLibraryItems[ident] = true;
+
+ // dependencies can be JS functions, which we just run
+ if (typeof ident == 'function') return ident();
+
// Don't replace implemented functions with library ones (which can happen when we add dependencies).
// Note: We don't return the dependencies here. Be careful not to end up where this matters
if (('_' + ident) in Functions.implementedFunctions) return '';
- addedLibraryItems[ident] = true;
var snippet = LibraryManager.library[ident];
var redirectedIdent = null;
var deps = LibraryManager.library[ident + '__deps'] || [];
@@ -400,7 +408,8 @@ function JSify(data, functionsOnly, givenFunctions) {
// name the function; overwrite if it's already named
snippet = snippet.replace(/function(?:\s+([^(]+))?\s*\(/, 'function _' + ident + '(');
if (LIBRARY_DEBUG) {
- snippet = snippet.replace('{', '{ print("[library call:' + ident + ']"); ');
+ snippet = snippet.replace('{', '{ var ret = (function() { if (Runtime.debug) Module.printErr("[library call:' + ident + ': " + Array.prototype.slice.call(arguments).map(Runtime.prettyPrint) + "]"); ');
+ snippet = snippet.substr(0, snippet.length-1) + '}).apply(this, arguments); if (Runtime.debug && typeof ret !== "undefined") Module.printErr(" [ return:" + Runtime.prettyPrint(ret)); return ret; }';
}
}
@@ -423,7 +432,7 @@ function JSify(data, functionsOnly, givenFunctions) {
} else {
ident = '_' + ident;
}
- var text = (deps ? '\n' + deps.map(addFromLibrary).join('\n') : '');
+ var text = (deps ? '\n' + deps.map(addFromLibrary).filter(function(x) { return x != '' }).join('\n') : '');
text += isFunction ? snippet : 'var ' + ident + '=' + snippet + ';';
if (ident in EXPORTED_FUNCTIONS) {
text += '\nModule["' + ident + '"] = ' + ident + ';';
@@ -441,6 +450,9 @@ function JSify(data, functionsOnly, givenFunctions) {
item.JS = addFromLibrary(shortident);
} else {
item.JS = 'var ' + item.ident + '; // stub for ' + item.ident;
+ if (WARN_ON_UNDEFINED_SYMBOLS) {
+ warn('Unresolved symbol: ' + item.ident);
+ }
}
return ret;
}
@@ -540,15 +552,12 @@ function JSify(data, functionsOnly, givenFunctions) {
}
});
- if (LABEL_DEBUG) func.JS += " print(INDENT + ' Entering: " + func.ident + "'); INDENT += ' ';\n";
+ if (LABEL_DEBUG) func.JS += " Module.print(INDENT + ' Entering: " + func.ident + "'); INDENT += ' ';\n";
if (true) { // TODO: optimize away when not needed
if (CLOSURE_ANNOTATIONS) func.JS += '/** @type {number} */';
func.JS += ' var __label__;\n';
}
- if (func.needsLastLabel) {
- func.JS += ' var __lastLabel__ = null;\n';
- }
// Walk function blocks and generate JS
function walkBlock(block, indent) {
@@ -558,7 +567,7 @@ function JSify(data, functionsOnly, givenFunctions) {
if (!label) return '';
var ret = '';
if (LABEL_DEBUG) {
- ret += indent + "print(INDENT + '" + func.ident + ":" + label.ident + "');\n";
+ ret += indent + "Module.print(INDENT + '" + func.ident + ":" + label.ident + "');\n";
}
if (EXECUTION_TIMEOUT > 0) {
ret += indent + 'if (Date.now() - START_TIME >= ' + (EXECUTION_TIMEOUT*1000) + ') throw "Timed out!" + (new Error().stack);\n';
@@ -739,7 +748,7 @@ function JSify(data, functionsOnly, givenFunctions) {
makeFuncLineActor('noop', function(item) {
return ';';
});
- makeFuncLineActor('var', function(item) { // assigns into phis become simple vars when MICRO_OPTS
+ makeFuncLineActor('var', function(item) { // assigns into phis become simple vars
return 'var ' + item.ident + ';';
});
makeFuncLineActor('store', function(item) {
@@ -753,6 +762,10 @@ function JSify(data, functionsOnly, givenFunctions) {
}
switch (impl) {
case VAR_NATIVIZED:
+ if (isNumber(item.ident)) {
+ // Direct write to a memory address; this may be an intentional segfault, if not, it is a bug in the source
+ return 'throw "fault on write to ' + item.ident + '";';
+ }
return item.ident + '=' + value + ';'; // We have the actual value here
break;
case VAR_EMULATED:
@@ -780,11 +793,8 @@ function JSify(data, functionsOnly, givenFunctions) {
return label;
}
- function makeBranch(label, lastLabel, labelIsVariable) {
+ function makeBranch(label, lastLabel, labelIsVariable) { // lastLabel is deprecated
var pre = '';
- if (!MICRO_OPTS && lastLabel) {
- pre = '__lastLabel__ = ' + getLabelId(lastLabel) + '; ';
- }
if (label[0] == 'B') {
assert(!labelIsVariable, 'Cannot handle branches to variables with special branching options');
var parts = label.split('|');
@@ -951,7 +961,7 @@ function JSify(data, functionsOnly, givenFunctions) {
+ '}\n';
}
if (LABEL_DEBUG) {
- ret += "print(INDENT + 'Exiting: " + item.funcData.ident + "');\n"
+ ret += "Module.print(INDENT + 'Exiting: " + item.funcData.ident + "');\n"
+ "INDENT = INDENT.substr(0, INDENT.length-2);\n";
}
ret += 'return';
@@ -961,7 +971,7 @@ function JSify(data, functionsOnly, givenFunctions) {
return ret + ';';
});
makeFuncLineActor('resume', function(item) {
- return (EXCEPTION_DEBUG ? 'print("Resuming exception");' : '') +
+ return (EXCEPTION_DEBUG ? 'Module.print("Resuming exception");' : '') +
'throw ' + makeGetValue('_llvm_eh_exception.buf', '0', 'void*') + ';';
});
makeFuncLineActor('invoke', function(item) {
@@ -974,7 +984,7 @@ function JSify(data, functionsOnly, givenFunctions) {
+ '} catch(e) { '
+ 'if (typeof e != "number") throw e; '
+ 'if (ABORT) throw e; __THREW__ = true; '
- + (EXCEPTION_DEBUG ? 'print("Exception: " + e + ", currently at: " + (new Error().stack)); ' : '')
+ + (EXCEPTION_DEBUG ? 'Module.print("Exception: " + e + ", currently at: " + (new Error().stack)); ' : '')
+ 'return null } })();';
if (item.assignTo) {
ret = 'var ' + item.assignTo + ' = ' + ret;
@@ -1021,7 +1031,16 @@ function JSify(data, functionsOnly, givenFunctions) {
makeFuncLineActor('extractvalue', function(item) {
assert(item.indexes.length == 1); // TODO: use getelementptr parsing stuff, for depth. For now, we assume that LLVM aggregates are flat,
// and we emulate them using simple JS objects { f1: , f2: , } etc., for speed
- return item.ident + '.f' + item.indexes[0][0].text;
+ var index = item.indexes[0][0].text;
+ var valueType = Types.types[item.type].fields[index];
+ if (USE_TYPED_ARRAYS != 2 || valueType != 'i64') {
+ return item.ident + '.f' + index;
+ } else {
+ var assignTo = item.assignTo;
+ item.assignTo = null;
+ return 'var ' + assignTo + '$0 = ' + item.ident + '.f' + index + '[0];' +
+ 'var ' + assignTo + '$1 = ' + item.ident + '.f' + index + '[1];';
+ }
});
makeFuncLineActor('insertvalue', function(item) {
assert(item.indexes.length == 1); // TODO: see extractvalue
@@ -1043,20 +1062,6 @@ function JSify(data, functionsOnly, givenFunctions) {
return RuntimeGenerator.stackAlloc(getFastValue(calcAllocatedSize(item.allocatedType), '*', item.allocatedNum));
}
});
- makeFuncLineActor('phi', function(item) {
- var params = item.params;
- assert(!MICRO_OPTS);
- function makeOne(i) {
- if (i === params.length-1) {
- return finalizeLLVMParameter(params[i].value);
- }
- return '__lastLabel__ == ' + getLabelId(params[i].label) + ' ? ' +
- finalizeLLVMParameter(params[i].value) + ' : (' + makeOne(i+1) + ')';
- }
- var ret = makeOne(0);
- if (item.postSet) ret += item.postSet;
- return ret;
- });
makeFuncLineActor('mathop', processMathop);
@@ -1195,6 +1200,12 @@ function JSify(data, functionsOnly, givenFunctions) {
// This is the main pass. Print out the generated code that we have here, together with the
// rest of the output that we started to print out earlier (see comment on the
// "Final shape that will be created").
+ if (PRECISE_I64_MATH && preciseI64MathUsed) {
+ print(read('long.js'));
+ } else {
+ print('// Warning: printing of i64 values may be slightly rounded! No deep i64 math used, so precise i64 code not included');
+ print('var i64Math = null;');
+ }
var generated = itemsDict.functionStub.concat(itemsDict.GlobalVariablePostSet);
generated.forEach(function(item) { print(indentify(item.JS || '', 2)); });
if (RUNTIME_TYPE_INFO) {