aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/analyzer.js5
-rw-r--r--src/fastLong.js12
-rw-r--r--src/intertyper.js43
-rw-r--r--src/jsifier.js216
-rw-r--r--src/library.js138
-rw-r--r--src/library_fs.js14
-rw-r--r--src/modules.js18
-rw-r--r--src/parseTools.js124
-rw-r--r--src/preamble.js20
-rw-r--r--src/runtime.js19
-rw-r--r--src/settings.js13
11 files changed, 395 insertions, 227 deletions
diff --git a/src/analyzer.js b/src/analyzer.js
index 3fb20253..17ad26ad 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -783,13 +783,14 @@ function analyzer(data, sidePass) {
assert(PRECISE_I64_MATH, 'Must have precise i64 math for non-constant 64-bit shifts');
Types.preciseI64MathUsed = 1;
value.intertype = 'value';
- value.ident = 'var ' + value.assignTo + '$0 = ' +
+ value.ident = makeVarDef(value.assignTo) + '$0=' +
asmCoercion('_bitshift64' + value.op[0].toUpperCase() + value.op.substr(1) + '(' +
asmCoercion(sourceElements[0].ident, 'i32') + ',' +
asmCoercion(sourceElements[1].ident, 'i32') + ',' +
asmCoercion(value.params[1].ident + '$0', 'i32') + ')', 'i32'
) + ';' +
- 'var ' + value.assignTo + '$1 = tempRet0;';
+ makeVarDef(value.assignTo) + '$1=tempRet0;';
+ value.vars = [[value.assignTo + '$0', 'i32'], [value.assignTo + '$1', 'i32']];
value.assignTo = null;
i++;
continue;
diff --git a/src/fastLong.js b/src/fastLong.js
index 4f6efd9f..2b70b2fb 100644
--- a/src/fastLong.js
+++ b/src/fastLong.js
@@ -5,12 +5,12 @@ function ___muldsi3($a, $b) {
var $1 = 0, $2 = 0, $3 = 0, $6 = 0, $8 = 0, $11 = 0, $12 = 0;
$1 = $a & 65535;
$2 = $b & 65535;
- $3 = Math.imul($2, $1) | 0;
+ $3 = Math_imul($2, $1) | 0;
$6 = $a >>> 16;
- $8 = ($3 >>> 16) + (Math.imul($2, $6) | 0) | 0;
+ $8 = ($3 >>> 16) + (Math_imul($2, $6) | 0) | 0;
$11 = $b >>> 16;
- $12 = Math.imul($11, $1) | 0;
- return (tempRet0 = (($8 >>> 16) + (Math.imul($11, $6) | 0) | 0) + ((($8 & 65535) + $12 | 0) >>> 16) | 0, 0 | ($8 + $12 << 16 | $3 & 65535)) | 0;
+ $12 = Math_imul($11, $1) | 0;
+ return (tempRet0 = (($8 >>> 16) + (Math_imul($11, $6) | 0) | 0) + ((($8 & 65535) + $12 | 0) >>> 16) | 0, 0 | ($8 + $12 << 16 | $3 & 65535)) | 0;
}
function ___divdi3($a$0, $a$1, $b$0, $b$1) {
$a$0 = $a$0 | 0;
@@ -63,8 +63,8 @@ function ___muldi3($a$0, $a$1, $b$0, $b$1) {
$y_sroa_0_0_extract_trunc = $b$0;
$1$0 = ___muldsi3($x_sroa_0_0_extract_trunc, $y_sroa_0_0_extract_trunc) | 0;
$1$1 = tempRet0;
- $2 = Math.imul($a$1, $y_sroa_0_0_extract_trunc) | 0;
- return (tempRet0 = ((Math.imul($b$1, $x_sroa_0_0_extract_trunc) | 0) + $2 | 0) + $1$1 | $1$1 & 0, 0 | $1$0 & -1) | 0;
+ $2 = Math_imul($a$1, $y_sroa_0_0_extract_trunc) | 0;
+ return (tempRet0 = ((Math_imul($b$1, $x_sroa_0_0_extract_trunc) | 0) + $2 | 0) + $1$1 | $1$1 & 0, 0 | $1$0 & -1) | 0;
}
function ___udivdi3($a$0, $a$1, $b$0, $b$1) {
$a$0 = $a$0 | 0;
diff --git a/src/intertyper.js b/src/intertyper.js
index 07f2020c..09bdaa33 100644
--- a/src/intertyper.js
+++ b/src/intertyper.js
@@ -850,6 +850,7 @@ function intertyper(lines, sidePass, baseLineNums) {
// TODO: also remove 2nd param?
} else if (item.op in LLVM.COMPS) {
item.type = 'i1';
+ if (item.params[1].intertype === 'type') item.params[1].intertype = 'value'; // parsed as type, but comparisons have just values there
}
if (USE_TYPED_ARRAYS == 2) {
// Some specific corrections, since 'i64' is special
@@ -1013,7 +1014,8 @@ function intertyper(lines, sidePass, baseLineNums) {
noteGlobalVariable(ret);
}
} else if (phase === 'funcs') {
- if (m = /^ (%[\w\d\._]+) = (getelementptr|load) ([%\w\d\._ ,\*\-@]+)$/.exec(line.lineText)) {
+ // TODO: (void)call, store
+ if (m = /^ (%[\w\d\._]+) = (getelementptr|load|icmp) ([%\w\d\._ ,\*\-@]+)$/.exec(line.lineText)) {
var assignTo = m[1];
var intertype = m[2];
var args = m[3];
@@ -1067,14 +1069,36 @@ function intertyper(lines, sidePass, baseLineNums) {
}
break;
}
+ case 'icmp': {
+ var parts = args.split(' ');
+ assert(parts.length === 4);
+ ret = {
+ intertype: 'mathop',
+ op: 'icmp',
+ variant: parts[0],
+ lineNum: line.lineNum,
+ assignTo: toNiceIdent(assignTo),
+ params: [{
+ intertype: 'value',
+ ident: toNiceIdent(parts[2].substr(0, parts[2].length-1)),
+ type: parts[1]
+ }, {
+ intertype: 'value',
+ ident: toNiceIdent(parts[3]),
+ type: parts[1]
+ }],
+ type: 'i1',
+ };
+ break;
+ }
default: throw 'unexpected fast path type ' + intertype;
}
- //else if (line.lineText.indexOf(' = load ') > 0) printErr('close: ' + JSON.stringify(line.lineText));
}
+ //else if (line.lineText.indexOf(' = icmp ') > 0) printErr('close: ' + JSON.stringify(line.lineText));
}
if (ret) {
if (COMPILER_ASSERTIONS) {
- //printErr(['\n', JSON.stringify(ret), '\n', JSON.stringify(triager(tokenizer(line)))]);
+ //printErr(['\n', dump(ret), '\n', dump(triager(tokenizer(line)))]);
var normal = triager(tokenizer(line));
delete normal.tokens;
delete normal.indent;
@@ -1087,11 +1111,14 @@ function intertyper(lines, sidePass, baseLineNums) {
// Input
lineSplitter().forEach(function(line) {
- var item = tryFastPaths(line);
- if (item) {
- finalResults.push(item);
- fastPaths++;
- return;
+ var item;
+ if (COMPILER_FASTPATHS) {
+ item = tryFastPaths(line);
+ if (item) {
+ finalResults.push(item);
+ fastPaths++;
+ return;
+ }
}
slowPaths++;
diff --git a/src/jsifier.js b/src/jsifier.js
index 96cb8d9a..0e5f8ef3 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -347,7 +347,7 @@ function JSify(data, functionsOnly, givenFunctions) {
js += 'if (globalScope) { assert(!globalScope["' + item.ident + '"]); globalScope["' + item.ident + '"] = ' + item.ident + ' }';
}
if (item.external && !NAMED_GLOBALS) {
- js = 'var ' + item.ident + ' = ' + js; // force an explicit naming, even if unnamed globals, for asm forwarding
+ js = 'var ' + item.ident + '=' + js; // force an explicit naming, even if unnamed globals, for asm forwarding
}
itemsDict.GlobalVariableStub.push({
intertype: 'GlobalVariable',
@@ -418,7 +418,7 @@ function JSify(data, functionsOnly, givenFunctions) {
}
// In asm, we need to know about library functions. If there is a target, though, then no
// need to consider this a library function - we will call directly to it anyhow
- if (ASM_JS && !redirectedIdent && (typeof target == 'function' || /Math\.\w+/.exec(snippet))) {
+ if (ASM_JS && !redirectedIdent && (typeof target == 'function' || /Math_\w+/.exec(snippet))) {
Functions.libraryFunctions[ident] = 1;
}
} else if (typeof snippet === 'object') {
@@ -537,6 +537,7 @@ function JSify(data, functionsOnly, givenFunctions) {
default: throw 'what is this line? ' + dump(line);
}
assert(line.JS);
+ //if (ASM_JS) assert(line.JS.indexOf('var ') < 0, dump(line));
if (line.assignTo) makeAssign(line);
Framework.currItem = null;
});
@@ -584,7 +585,7 @@ function JSify(data, functionsOnly, givenFunctions) {
if (DLOPEN_SUPPORT) Functions.getIndex(func.ident);
- func.JS += 'function ' + func.ident + '(' + paramIdents.join(', ') + ') {\n';
+ func.JS += 'function ' + func.ident + '(' + paramIdents.join(',') + '){\n';
if (PGO) {
func.JS += INDENTATION + 'PGOMonitor.called["' + func.ident + '"] = 1;\n';
@@ -593,13 +594,23 @@ function JSify(data, functionsOnly, givenFunctions) {
if (ASM_JS) {
// spell out argument types
func.params.forEach(function(param) {
- func.JS += INDENTATION + param.ident + ' = ' + asmCoercion(param.ident, param.type) + ';\n';
+ func.JS += INDENTATION + param.ident + '=' + deParen(asmCoercion(param.ident, param.type)) + ';\n';
});
+ addVariable('label', 'i32', func);
+
+ if (func.setjmpTable) {
+ addVariable('setjmpLabel', 'i32', func);
+ addVariable('setjmpTable', 'i32', func);
+ }
+
// spell out local variables
- var vars = values(func.variables).filter(function(v) { return v.origin != 'funcparam' });
+ var vars = values(func.variables).filter(function(v) {
+ return v.origin !== 'funcparam' &&
+ (!isIllegalType(getImplementationType(v)) || v.ident.indexOf('$', 1) > 0); // not illegal, or a broken up illegal (we have illegal chunks explicitly anyhow)
+ });
if (vars.length > 0) {
- var chunkSize = 8;
+ var chunkSize = 20;
var chunks = [];
var i = 0;
while (i < vars.length) {
@@ -608,22 +619,15 @@ function JSify(data, functionsOnly, givenFunctions) {
}
for (i = 0; i < chunks.length; i++) {
func.JS += INDENTATION + 'var ' + chunks[i].map(function(v) {
- var type = getImplementationType(v);
- if (!isIllegalType(type) || v.ident.indexOf('$', 1) > 0) { // not illegal, or a broken up illegal
- return v.ident + ' = ' + asmInitializer(type); //, func.variables[v.ident].impl);
- } else {
- return range(Math.ceil(getBits(type)/32)).map(function(i) {
- return v.ident + '$' + i + '= 0';
- }).join(',');
- }
- }).join(', ') + ';\n';
+ return v.ident + '=' + asmInitializer(getImplementationType(v)); //, func.variables[v.ident].impl);
+ }).join(',') + ';\n';
}
}
}
- if (true) { // TODO: optimize away when not needed
- if (CLOSURE_ANNOTATIONS) func.JS += '/** @type {number} */';
- func.JS += INDENTATION + 'var label = 0;\n';
+ if (CLOSURE_ANNOTATIONS) func.JS += '/** @type {number} */';
+ if (!ASM_JS) {
+ func.JS += INDENTATION + 'var label=0;\n';
}
if (ASM_JS) {
@@ -632,12 +636,12 @@ function JSify(data, functionsOnly, givenFunctions) {
hasByVal = hasByVal || param.byVal;
});
if (hasByVal) {
- func.JS += INDENTATION + 'var tempParam = 0;\n';
+ func.JS += INDENTATION + 'var tempParam=0;\n';
}
}
if (func.hasVarArgsCall) {
- func.JS += INDENTATION + 'var tempVarArgs = 0;\n';
+ func.JS += INDENTATION + 'var tempVarArgs=0;\n';
}
// Prepare the stack, if we need one. If we have other stack allocations, force the stack to be set up.
@@ -654,7 +658,7 @@ function JSify(data, functionsOnly, givenFunctions) {
if (param.byVal) {
var type = removePointing(param.type);
var typeInfo = Types.types[type];
- func.JS += INDENTATION + (ASM_JS ? '' : 'var ') + 'tempParam = ' + param.ident + '; ' + param.ident + ' = ' + RuntimeGenerator.stackAlloc(typeInfo.flatSize) + ';' +
+ func.JS += INDENTATION + (ASM_JS ? '' : 'var ') + 'tempParam = ' + param.ident + '; ' + param.ident + '=' + RuntimeGenerator.stackAlloc(typeInfo.flatSize) + ';' +
makeCopyValues(param.ident, 'tempParam', typeInfo.flatSize, 'null', null, param.byVal) + ';\n';
}
});
@@ -665,14 +669,14 @@ function JSify(data, functionsOnly, givenFunctions) {
function walkBlock(block, indent) {
if (!block) return '';
dprint('relooping', 'walking block: ' + block.type + ',' + block.entries + ' : ' + block.labels.length);
- function getLabelLines(label, indent, relooping) {
+ function getLabelLines(label, relooping) {
if (!label) return '';
var ret = '';
if ((LABEL_DEBUG >= 2) && functionNameFilterTest(func.ident)) {
- ret += indent + "Module.print(INDENT + '" + func.ident + ":" + label.ident + "');\n";
+ ret += INDENTATION + "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';
+ ret += INDENTATION + 'if (Date.now() - START_TIME >= ' + (EXECUTION_TIMEOUT*1000) + ') throw "Timed out!" + (new Error().stack);\n';
}
if (PRINT_SPLIT_FILE_MARKER && Debugging.on && Debugging.getAssociatedSourceFile(label.lines[label.lines.length-1].lineNum)) {
@@ -685,6 +689,7 @@ function JSify(data, functionsOnly, givenFunctions) {
var i = 0;
return ret + label.lines.map(function(line) {
var JS = line.JS;
+ if (!relooping) JS = INDENTATION + JS;
if (relooping && i == label.lines.length-1) {
if (line.intertype == 'branch' || line.intertype == 'switch') {
JS = ''; // just branching operations - done in the relooper, so nothing need be done here
@@ -695,12 +700,10 @@ function JSify(data, functionsOnly, givenFunctions) {
i++;
// invoke instructions span two lines, and the debug info is located
// on the second line, hence the +1
- return JS + (Debugging.on ? Debugging.getComment(line.lineNum + (line.intertype === 'invoke' ? 1 : 0)) : '');
- })
- .join('\n')
- .split('\n') // some lines include line breaks
- .map(function(line) { return indent + line })
- .join('\n');
+ if (Debugging.on) JS += Debugging.getComment(line.lineNum + (line.intertype === 'invoke' ? 1 : 0));
+ //assert(JS.indexOf('\n') < 0, JS);
+ return JS;
+ }).join('\n');
}
var ret = '';
if (!RELOOP || func.forceEmulated) { // TODO: also if just 1 label?
@@ -719,19 +722,19 @@ function JSify(data, functionsOnly, givenFunctions) {
ret += 'dummy: 0';
ret += '};\n';
} else {
- ret += 'var setjmpLabel = 0;\n';
- ret += 'var setjmpTable = ' + RuntimeGenerator.stackAlloc(4 * (MAX_SETJMPS + 1) * 2) + ';\n';
+ ret += makeVarDef('setjmpLabel') + '=0;\n';
+ ret += makeVarDef('setjmpTable') + '=' + RuntimeGenerator.stackAlloc(4 * (MAX_SETJMPS + 1) * 2) + ';\n';
ret += makeSetValue('setjmpTable', '0', '0', 'i32') + ';'; // initialize first entry to 0
}
}
- ret += indent + 'while(1) ';
+ ret += indent + 'while(1)';
if (func.setjmpTable && !ASM_JS) {
ret += 'try { ';
}
- ret += 'switch(' + asmCoercion('label', 'i32') + ') {\n';
+ ret += 'switch(' + asmCoercion('label', 'i32') + '){\n';
ret += block.labels.map(function(label) {
- return indent + INDENTATION + 'case ' + getLabelId(label.ident) + ': ' + (SHOW_LABELS ? '// ' + getOriginalLabelId(label.ident) : '') + '\n'
- + getLabelLines(label, indent + INDENTATION + INDENTATION);
+ return INDENTATION + 'case ' + getLabelId(label.ident) + ': ' + (SHOW_LABELS ? '// ' + getOriginalLabelId(label.ident) : '') + '\n'
+ + getLabelLines(label);
}).join('\n') + '\n';
if (func.setjmpTable && ASM_JS) {
// emit a label in which we write to the proper local variable, before jumping to the actual label
@@ -748,8 +751,16 @@ function JSify(data, functionsOnly, givenFunctions) {
if (func.setjmpTable && !ASM_JS) {
ret += ' } catch(e) { if (!e.longjmp || !(e.id in mySetjmpIds)) throw(e); setjmpTable[setjmpLabels[e.id]](e.value) }';
}
+ if (ASM_JS && func.returnType !== 'void') {
+ // Add a return
+ if (func.returnType in Runtime.FLOAT_TYPES) {
+ ret += ' return +0;\n';
+ } else {
+ ret += ' return 0;\n';
+ }
+ }
} else {
- ret += (SHOW_LABELS ? indent + '/* ' + block.entries[0] + ' */' : '') + '\n' + getLabelLines(block.labels[0], indent);
+ ret += (SHOW_LABELS ? indent + '/* ' + block.entries[0] + ' */' : '') + '\n' + getLabelLines(block.labels[0]);
}
ret += '\n';
} else {
@@ -764,7 +775,7 @@ function JSify(data, functionsOnly, givenFunctions) {
// add blocks
for (var i = 0; i < block.labels.length; i++) {
var label = block.labels[i];
- var content = getLabelLines(label, '', true);
+ var content = getLabelLines(label, true);
//printErr(func.ident + ' : ' + label.ident + ' : ' + content + '\n');
var last = label.lines[label.lines.length-1];
if (!last.signedIdent) {
@@ -810,9 +821,17 @@ function JSify(data, functionsOnly, givenFunctions) {
// Finalize function
if (LABEL_DEBUG && functionNameFilterTest(func.ident)) func.JS += " INDENT = INDENT.substr(0, INDENT.length-2);\n";
// Ensure a return in a function with a type that returns, even if it lacks a return (e.g., if it aborts())
- if (RELOOP && func.lines.length > 0 && func.returnType != 'void') {
- var returns = func.labels.filter(function(label) { return label.lines[label.lines.length-1].intertype == 'return' }).length;
- if (returns == 0) func.JS += INDENTATION + 'return ' + asmCoercion('0', func.returnType);
+ if (RELOOP && ASM_JS && func.lines.length > 0 && func.returnType != 'void') {
+ var lastCurly = func.JS.lastIndexOf('}');
+ var lastReturn = func.JS.lastIndexOf('return ');
+ if ((lastCurly < 0 && lastReturn < 0) || // no control flow, no return
+ (lastCurly >= 0 && lastReturn < lastCurly)) { // control flow, no return past last join
+ if (func.returnType in Runtime.FLOAT_TYPES) {
+ func.JS += ' return +0;\n';
+ } else {
+ func.JS += ' return 0;\n';
+ }
+ }
}
func.JS += '}\n';
@@ -898,6 +917,11 @@ function JSify(data, functionsOnly, givenFunctions) {
// Function lines
function valueHandler(item) {
+ if (item.vars) {
+ item.vars.forEach(function(v) {
+ addVariable(v[0], v[1]);
+ });
+ }
return item.ident;
}
function noopHandler(item) {
@@ -959,7 +983,7 @@ function JSify(data, functionsOnly, givenFunctions) {
var parts = label.split('|');
var trueLabel = parts[1] || '';
var oldLabel = parts[2] || '';
- var labelSetting = oldLabel ? 'label = ' + getLabelId(oldLabel) + ';' +
+ var labelSetting = oldLabel ? 'label=' + getLabelId(oldLabel) + ';' +
(SHOW_LABELS ? ' /* to: ' + getOriginalLabelId(cleanLabel(oldLabel)) + ' */' : '') : ''; // TODO: optimize away the setting
if (label[1] == 'R') {
if (label[2] == 'N') { // BRNOL: break, no label setting
@@ -980,7 +1004,7 @@ function JSify(data, functionsOnly, givenFunctions) {
}
} else {
if (!labelIsVariable) label = getLabelId(label);
- return pre + 'label = ' + label + ';' + (SHOW_LABELS ? ' /* to: ' + getOriginalLabelId(cleanLabel(label)) + ' */' : '') + ' break;';
+ return pre + 'label=' + label + ';' + (SHOW_LABELS ? ' /* to: ' + getOriginalLabelId(cleanLabel(label)) + ' */' : '') + 'break;';
}
}
@@ -1002,14 +1026,14 @@ function JSify(data, functionsOnly, givenFunctions) {
var labelSets = phiSets[label];
// FIXME: Many of the |var |s here are not needed, but without them we get slowdowns with closure compiler. TODO: remove this workaround.
if (labelSets.length == 1) {
- return (ASM_JS ? '' : 'var ') + labelSets[0].ident + ' = ' + labelSets[0].valueJS + ';';
+ return (ASM_JS ? '' : 'var ') + labelSets[0].ident + '=' + labelSets[0].valueJS + ';';
}
// TODO: eliminate unneeded sets (to undefined etc.)
var deps = {}; // for each ident we will set, which others it depends on
- var valueJSes = {};
+ var map = {};
labelSets.forEach(function(labelSet) {
deps[labelSet.ident] = {};
- valueJSes[labelSet.ident] = labelSet.valueJS;
+ map[labelSet.ident] = labelSet;
});
labelSets.forEach(function(labelSet) {
walkInterdata(labelSet.value, function mark(item) {
@@ -1028,14 +1052,18 @@ function JSify(data, functionsOnly, givenFunctions) {
}
for (var i = 0; i < idents.length; i++) {
if (keys(deps[idents[i]]).length == 0) {
- post = 'var ' + idents[i] + ' = ' + valueJSes[idents[i]] + ';' + post;
+ post = idents[i] + '=' + map[idents[i]].valueJS + ';' + post;
+ if (!ASM_JS) post = 'var ' + post;
+ else addVariable(idents[i], map[idents[i]].value.type);
remove(idents[i]);
continue mainLoop;
}
}
// If we got here, we have circular dependencies, and must break at least one.
- pre += 'var ' + idents[0] + '$phi = ' + valueJSes[idents[0]] + ';';
- post += 'var ' + idents[0] + ' = ' + idents[0] + '$phi;';
+ pre += makeVarDef(idents[0]) + '$phi=' + map[idents[0]].valueJS + ';';
+ post += makeVarDef(idents[0]) + '=' + idents[0] + '$phi;';
+ addVariable(idents[0] + '$phi', map[idents[0]].value.type);
+ addVariable(idents[0], map[idents[0]].value.type);
remove(idents[0]);
}
return pre + post;
@@ -1062,10 +1090,10 @@ function JSify(data, functionsOnly, givenFunctions) {
var labelTrue = (item.labelTrueJS = getPhiSetsForLabel(phiSets, item.labelTrue)) + makeBranch(item.labelTrue, item.currLabelId);
var labelFalse = (item.labelFalseJS = getPhiSetsForLabel(phiSets, item.labelFalse)) + makeBranch(item.labelFalse, item.currLabelId);
if (labelTrue == ';' && labelFalse == ';') return ';';
- var head = 'if (' + condition + ') { ';
- var head2 = 'if (!(' + condition + ')) { ';
- var else_ = ' } else { ';
- var tail = ' }';
+ var head = 'if(' + condition + '){';
+ var head2 = 'if(!(' + condition + ')){';
+ var else_ = '}else{';
+ var tail = '}';
if (labelTrue == ';') {
return head2 + labelFalse + tail;
} else if (labelFalse == ';') {
@@ -1112,7 +1140,7 @@ function JSify(data, functionsOnly, givenFunctions) {
item.groupedLabels = [];
}
if (!useIfs) {
- ret += 'switch(' + signedIdent + ') {\n';
+ ret += 'switch(' + signedIdent + '){';
}
// process target labels, sorting them so output is consistently ordered
keys(targetLabels).sort().forEach(function(targetLabel) {
@@ -1125,17 +1153,17 @@ function JSify(data, functionsOnly, givenFunctions) {
if (useIfs) {
value = targetLabels[targetLabel].map(function(value) {
return makeComparison(signedIdent, '==', makeSignOp(value, item.type, 're'), item.type)
- }).join(' | ');
- ret += 'if (' + value + ') {\n';
+ }).join('|');
+ ret += 'if(' + value + '){';
} else {
value = targetLabels[targetLabel].map(function(value) {
return 'case ' + makeSignOp(value, item.type, 're') + ':';
- }).join(' ');
- ret += value + '{\n';
+ }).join('');
+ ret += value + '{';
}
var phiSet = getPhiSetsForLabel(phiSets, targetLabel);
- ret += INDENTATION + '' + phiSet + makeBranch(targetLabel, item.currLabelId || null) + '\n';
- ret += '}\n';
+ ret += INDENTATION + '' + phiSet + makeBranch(targetLabel, item.currLabelId || null);
+ ret += '}';
if (RELOOP) {
item.groupedLabels.push({
label: targetLabel,
@@ -1146,15 +1174,15 @@ function JSify(data, functionsOnly, givenFunctions) {
});
var phiSet = item.defaultLabelJS = getPhiSetsForLabel(phiSets, item.defaultLabel);
if (useIfs) {
- if (item.switchLabels.length > 0) ret += 'else {\n';
- ret += phiSet + makeBranch(item.defaultLabel, item.currLabelId) + '\n';
- if (item.switchLabels.length > 0) ret += '}\n';
+ if (item.switchLabels.length > 0) ret += 'else{';
+ ret += phiSet + makeBranch(item.defaultLabel, item.currLabelId) + '';
+ if (item.switchLabels.length > 0) ret += '}';
} else {
- ret += 'default: {\n';
- ret += phiSet + makeBranch(item.defaultLabel, item.currLabelId) + '\n';
- ret += '}\n';
+ ret += 'default:{';
+ ret += phiSet + makeBranch(item.defaultLabel, item.currLabelId) + '';
+ ret += '}';
- ret += '} break; \n'; // finish switch and break, to move control flow properly (breaks from makeBranch just broke out of the switch)
+ ret += '}break;'; // finish switch and break, to move control flow properly (breaks from makeBranch just broke out of the switch)
}
if (item.value) {
ret += ' ' + toNiceIdent(item.value);
@@ -1162,10 +1190,11 @@ function JSify(data, functionsOnly, givenFunctions) {
return ret;
}
function returnHandler(item) {
- var ret = RuntimeGenerator.stackExit(item.funcData.initialStack, item.funcData.otherStackAllocations) + ';\n';
+ var ret = RuntimeGenerator.stackExit(item.funcData.initialStack, item.funcData.otherStackAllocations);
+ if (ret.length > 0) ret += ';';
if (LABEL_DEBUG && functionNameFilterTest(item.funcData.ident)) {
- ret += "Module.print(INDENT + 'Exiting: " + item.funcData.ident + "');\n"
- + "INDENT = INDENT.substr(0, INDENT.length-2);\n";
+ ret += "Module.print(INDENT + 'Exiting: " + item.funcData.ident + "');"
+ + "INDENT = INDENT.substr(0, INDENT.length-2);";
}
ret += 'return';
var value = item.value ? finalizeLLVMParameter(item.value) : null;
@@ -1191,7 +1220,7 @@ function JSify(data, functionsOnly, givenFunctions) {
// in an assignment
var disabled = DISABLE_EXCEPTION_CATCHING == 2 && !(item.funcData.ident in EXCEPTION_CATCHING_WHITELIST);
var phiSets = calcPhiSets(item);
- var call_ = makeFunctionCall(item.ident, item.params, item.funcData, item.type, ASM_JS && !disabled, !!item.assignTo || !item.standalone, true);
+ var call_ = makeFunctionCall(item, item.params, item.funcData, item.type, ASM_JS && !disabled, !!item.assignTo || !item.standalone, true);
var ret;
@@ -1217,11 +1246,16 @@ function JSify(data, functionsOnly, givenFunctions) {
ret = makeVarArgsCleanup(ret);
if (item.assignTo) {
- ret = 'var ' + item.assignTo + ' = ' + ret;
- if (USE_TYPED_ARRAYS == 2 && isIllegalType(item.type)) {
+ var illegal = USE_TYPED_ARRAYS == 2 && isIllegalType(item.type);
+ var assignTo = illegal ? item.assignTo + '$r' : item.assignTo;
+ ret = makeVarDef(assignTo) + '=' + ret;
+ if (ASM_JS) addVariable(assignTo, item.type);
+ if (illegal) {
var bits = getBits(item.type);
for (var i = 0; i < bits/32; i++) {
- ret += 'var ' + item.assignTo + '$' + i + ' = ' + (i == 0 ? item.assignTo : 'tempRet' + (i-1)) + ';'
+ var v = item.assignTo + '$' + i;
+ ret += makeVarDef(v) + '=' + (i == 0 ? assignTo : 'tempRet' + (i-1)) + ';'
+ if (ASM_JS) addVariable(v, 'i32');
}
}
item.assignTo = null;
@@ -1252,8 +1286,12 @@ function JSify(data, functionsOnly, givenFunctions) {
}
}
function landingpadHandler(item) {
+ if (ASM_JS) {
+ addVariable(item.assignTo + '$0', 'i32');
+ addVariable(item.assignTo + '$1', 'i32');
+ }
if (DISABLE_EXCEPTION_CATCHING && !(item.funcData.ident in EXCEPTION_CATCHING_WHITELIST) && USE_TYPED_ARRAYS == 2) {
- ret = makeVarDef(item.assignTo) + '$0 = 0; ' + item.assignTo + '$1 = 0;';
+ ret = makeVarDef(item.assignTo) + '$0 = 0; ' + makeVarDef(item.assignTo) + '$1 = 0;';
item.assignTo = null;
if (VERBOSE) warnOnce('landingpad, but exceptions are disabled!');
return ret;
@@ -1261,7 +1299,7 @@ function JSify(data, functionsOnly, givenFunctions) {
var catchTypeArray = item.catchables.map(finalizeLLVMParameter).map(function(element) { return asmCoercion(element, 'i32') }).join(',');
var ret = asmCoercion('___cxa_find_matching_catch(-1, -1' + (catchTypeArray.length > 0 ? ',' + catchTypeArray : '') +')', 'i32');
if (USE_TYPED_ARRAYS == 2) {
- ret = makeVarDef(item.assignTo) + '$0 = ' + ret + '; ' + item.assignTo + '$1 = tempRet0;';
+ ret = makeVarDef(item.assignTo) + '$0 = ' + ret + '; ' + makeVarDef(item.assignTo) + '$1 = tempRet0;';
item.assignTo = null;
}
return ret;
@@ -1307,13 +1345,14 @@ function JSify(data, functionsOnly, givenFunctions) {
item.ident = 'tempValue';
ret += item.ident + ' = [' + makeEmptyStruct(item.type) + '], ';
}
- return ret + item.ident + '.f' + item.indexes[0][0].text + ' = ' + finalizeLLVMParameter(item.value) + ', ' + item.ident + ')';
+ return ret + item.ident + '.f' + item.indexes[0][0].text + '=' + finalizeLLVMParameter(item.value) + ', ' + item.ident + ')';
}
function indirectbrHandler(item) {
var phiSets = calcPhiSets(item);
- var js = 'var ibr = ' + finalizeLLVMParameter(item.value) + ';\n';
+ var js = makeVarDef('ibr') + '=' + finalizeLLVMParameter(item.value) + ';';
+ if (ASM_JS) addVariable('ibr', 'i32');
for (var targetLabel in phiSets) {
- js += 'if (' + makeComparison('ibr', '==', targetLabel, 'i32') + ') { ' + getPhiSetsForLabel(phiSets, targetLabel) + ' }\n';
+ js += 'if(' + makeComparison('ibr', '==', targetLabel, 'i32') + '){' + getPhiSetsForLabel(phiSets, targetLabel) + '}';
}
return js + makeBranch('ibr', item.currLabelId, true);
}
@@ -1349,7 +1388,9 @@ function JSify(data, functionsOnly, givenFunctions) {
return ret;
}
- function makeFunctionCall(ident, params, funcData, type, forceByPointer, hasReturn, invoke) {
+ function makeFunctionCall(item, params, funcData, type, forceByPointer, hasReturn, invoke) {
+ var ident = item.ident;
+
// We cannot compile assembly. See comment in intertyper.js:'Call'
assert(ident != 'asm', 'Inline assembly cannot be compiled to JavaScript!');
@@ -1368,7 +1409,7 @@ function JSify(data, functionsOnly, givenFunctions) {
var callIdent = LibraryManager.getRootIdent(simpleIdent);
if (callIdent) {
simpleIdent = callIdent; // ident may not be in library, if all there is is ident__inline, but in this case it is
- if (callIdent.indexOf('.') < 0) {
+ if (callIdent.indexOf('Math_') !== 0) {
callIdent = '_' + callIdent; // Not Math.*, so add the normal prefix
}
} else {
@@ -1499,6 +1540,9 @@ function JSify(data, functionsOnly, givenFunctions) {
if (trueType !== returnType && !isIdenticallyImplemented(trueType, returnType)) {
if (VERBOSE) warnOnce('Fixing function call based on return type from signature, on ' + [callIdent, returnType, trueType]);
returnType = trueType;
+ if (trueType === 'void') {
+ item.assignTo = null;
+ }
}
}
}
@@ -1526,7 +1570,7 @@ function JSify(data, functionsOnly, givenFunctions) {
if (!ASM_JS || functionTableCall) callIdent = Functions.getTable(sig) + '[' + callIdent + ']';
}
- var ret = callIdent + '(' + args.join(', ') + ')';
+ var ret = callIdent + '(' + args.join(',') + ')';
if (ASM_JS) { // TODO: do only when needed (library functions and Math.*?) XXX && simpleIdent in Functions.libraryFunctions) {
ret = asmCoercion(ret, returnType);
if (simpleIdent == 'abort' && funcData.returnType != 'void') {
@@ -1537,7 +1581,7 @@ function JSify(data, functionsOnly, givenFunctions) {
if (ASM_JS && funcData.setjmpTable) {
// check if a longjmp was done. If a setjmp happened, check if ours. If ours, go to a special label to handle it.
// otherwise, just return - the call to us must also have been an invoke, so the setjmp propagates that way
- ret += '; if (((__THREW__|0) != 0) & ((threwValue|0) != 0)) { setjmpLabel = ' + asmCoercion('_testSetjmp(' + makeGetValue('__THREW__', 0, 'i32') + ', setjmpTable)', 'i32') + '; if ((setjmpLabel|0) > 0) { label = ' + SETJMP_LABEL + '; break } else return ' + (funcData.returnType != 'void' ? asmCoercion('0', funcData.returnType) : '') + ' } __THREW__ = threwValue = 0;\n';
+ ret += '; if (((__THREW__|0) != 0) & ((threwValue|0) != 0)) { setjmpLabel = ' + asmCoercion('_testSetjmp(' + makeGetValue('__THREW__', 0, 'i32') + ', setjmpTable)', 'i32') + '; if ((setjmpLabel|0) > 0) { label = ' + SETJMP_LABEL + '; break } else return ' + (funcData.returnType != 'void' ? asmCoercion('0', funcData.returnType) : '') + ' } __THREW__ = threwValue = 0;';
}
return ret;
@@ -1558,7 +1602,7 @@ function JSify(data, functionsOnly, givenFunctions) {
function getelementptrHandler(item) { return finalizeLLVMFunctionCall(item) }
function callHandler(item) {
if (item.standalone && LibraryManager.isStubFunction(item.ident)) return ';';
- var ret = makeFunctionCall(item.ident, item.params, item.funcData, item.type, false, !!item.assignTo || !item.standalone) + (item.standalone ? ';' : '');
+ var ret = makeFunctionCall(item, item.params, item.funcData, item.type, false, !!item.assignTo || !item.standalone) + (item.standalone ? ';' : '');
return makeVarArgsCleanup(ret);
}
@@ -1805,14 +1849,14 @@ function JSify(data, functionsOnly, givenFunctions) {
var shellParts = read(shellFile).split('{{BODY}}');
print(processMacros(preprocess(shellParts[1])));
// Print out some useful metadata
- if (EMIT_GENERATED_FUNCTIONS || PGO) {
+ if (RUNNING_JS_OPTS || PGO) {
var generatedFunctions = JSON.stringify(keys(Functions.implementedFunctions).filter(function(func) {
return IGNORED_FUNCTIONS.indexOf(func.ident) < 0;
}));
if (PGO) {
print('PGOMonitor.allGenerated = ' + generatedFunctions + ';\nremoveRunDependency("pgo");\n');
}
- if (EMIT_GENERATED_FUNCTIONS) {
+ if (RUNNING_JS_OPTS) {
print('// EMSCRIPTEN_GENERATED_FUNCTIONS: ' + generatedFunctions + '\n');
}
}
diff --git a/src/library.js b/src/library.js
index 02981a80..5e71b087 100644
--- a/src/library.js
+++ b/src/library.js
@@ -459,14 +459,17 @@ LibraryManager.library = {
// http://pubs.opengroup.org/onlinepubs/009695399/functions/creat.html
return _open(path, {{{ cDefine('O_WRONLY') }}} | {{{ cDefine('O_CREAT') }}} | {{{ cDefine('O_TRUNC') }}}, allocate([mode, 0, 0, 0], 'i32', ALLOC_STACK));
},
- mkstemp__deps: ['creat'],
- mkstemp: function(template) {
- if (!_mkstemp.counter) _mkstemp.counter = 0;
- var c = (_mkstemp.counter++).toString();
+ mktemp: function(template) {
+ if (!_mktemp.counter) _mktemp.counter = 0;
+ var c = (_mktemp.counter++).toString();
var rep = 'XXXXXX';
while (c.length < rep.length) c = '0' + c;
writeArrayToMemory(intArrayFromString(c), template + Pointer_stringify(template).indexOf(rep));
- return _creat(template, 0600);
+ return template;
+ },
+ mkstemp__deps: ['creat', 'mktemp'],
+ mkstemp: function(template) {
+ return _creat(_mktemp(template), 0600);
},
fcntl__deps: ['$FS', '__setErrNo', '$ERRNO_CODES'],
fcntl: function(fildes, cmd, varargs, dup2) {
@@ -3005,8 +3008,8 @@ LibraryManager.library = {
return ret;
},
- abs: 'Math.abs',
- labs: 'Math.abs',
+ abs: 'Math_abs',
+ labs: 'Math_abs',
#if USE_TYPED_ARRAYS == 2
llabs__deps: [function() { Types.preciseI64MathUsed = 1 }],
llabs: function(lo, hi) {
@@ -3799,8 +3802,8 @@ LibraryManager.library = {
p1 = p1|0; p2 = p2|0; num = num|0;
var i = 0, v1 = 0, v2 = 0;
while ((i|0) < (num|0)) {
- var v1 = {{{ makeGetValueAsm('p1', 'i', 'i8', true) }}};
- var v2 = {{{ makeGetValueAsm('p2', 'i', 'i8', true) }}};
+ v1 = {{{ makeGetValueAsm('p1', 'i', 'i8', true) }}};
+ v2 = {{{ makeGetValueAsm('p2', 'i', 'i8', true) }}};
if ((v1|0) != (v2|0)) return ((v1|0) > (v2|0) ? 1 : -1)|0;
i = (i+1)|0;
}
@@ -4224,9 +4227,9 @@ LibraryManager.library = {
var ret = 0;
ret = {{{ makeGetValueAsm('ctlz_i8', 'x >>> 24', 'i8') }}};
if ((ret|0) < 8) return ret|0;
- var ret = {{{ makeGetValueAsm('ctlz_i8', '(x >> 16)&0xff', 'i8') }}};
+ ret = {{{ makeGetValueAsm('ctlz_i8', '(x >> 16)&0xff', 'i8') }}};
if ((ret|0) < 8) return (ret + 8)|0;
- var ret = {{{ makeGetValueAsm('ctlz_i8', '(x >> 8)&0xff', 'i8') }}};
+ ret = {{{ makeGetValueAsm('ctlz_i8', '(x >> 8)&0xff', 'i8') }}};
if ((ret|0) < 8) return (ret + 16)|0;
return ({{{ makeGetValueAsm('ctlz_i8', 'x&0xff', 'i8') }}} + 24)|0;
},
@@ -4260,9 +4263,9 @@ LibraryManager.library = {
var ret = 0;
ret = {{{ makeGetValueAsm('cttz_i8', 'x & 0xff', 'i8') }}};
if ((ret|0) < 8) return ret|0;
- var ret = {{{ makeGetValueAsm('cttz_i8', '(x >> 8)&0xff', 'i8') }}};
+ ret = {{{ makeGetValueAsm('cttz_i8', '(x >> 8)&0xff', 'i8') }}};
if ((ret|0) < 8) return (ret + 8)|0;
- var ret = {{{ makeGetValueAsm('cttz_i8', '(x >> 16)&0xff', 'i8') }}};
+ ret = {{{ makeGetValueAsm('cttz_i8', '(x >> 16)&0xff', 'i8') }}};
if ((ret|0) < 8) return (ret + 16)|0;
return ({{{ makeGetValueAsm('cttz_i8', 'x >>> 24', 'i8') }}} + 24)|0;
},
@@ -4699,30 +4702,30 @@ LibraryManager.library = {
// math.h