aboutsummaryrefslogtreecommitdiff
path: root/src/jsifier.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/jsifier.js')
-rw-r--r--src/jsifier.js75
1 files changed, 55 insertions, 20 deletions
diff --git a/src/jsifier.js b/src/jsifier.js
index b830fc7c..5ad1573b 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -66,7 +66,7 @@ function JSify(data, functionsOnly, givenFunctions) {
assert(!BUILD_AS_SHARED_LIB, 'Cannot have both INCLUDE_FULL_LIBRARY and BUILD_AS_SHARED_LIB set.')
libFuncsToInclude = [];
for (var key in LibraryManager.library) {
- if (!key.match(/__(deps|postset)$/)) {
+ if (!key.match(/__(deps|postset|inline)$/)) {
libFuncsToInclude.push(key);
}
}
@@ -167,7 +167,7 @@ function JSify(data, functionsOnly, givenFunctions) {
}
// Add current value(s)
var currValue = flatten(values[i]);
- if (I64_MODE == 1 && typeData.fields[i] == 'i64') {
+ if (USE_TYPED_ARRAYS == 2 && typeData.fields[i] == 'i64') {
// 'flatten' out the 64-bit value into two 32-bit halves
ret[index++] = currValue>>>0;
ret[index++] = 0;
@@ -229,7 +229,7 @@ function JSify(data, functionsOnly, givenFunctions) {
return makeEmptyStruct(type);
} else if (value.intertype === 'string') {
return JSON.stringify(parseLLVMString(value.text)) +
- ' /* ' + value.text.substr(0, 20).replace(/\*/g, '_') + ' */'; // make string safe for inclusion in comment
+ ' /* ' + value.text.substr(0, 20).replace(/[*<>]/g, '_') + ' */'; // make string safe for inclusion in comment
} else {
return alignStruct(handleSegments(value.contents), type);
}
@@ -574,14 +574,30 @@ function JSify(data, functionsOnly, givenFunctions) {
if (block.type == 'emulated') {
if (block.labels.length > 1) {
if (block.entries.length == 1) {
- ret += indent + '__label__ = ' + getLabelId(block.entries[0]) + '; ' + (SHOW_LABELS ? '/* ' + block.entries[0] + ' */' : '') + '\n';
+ ret += indent + '__label__ = ' + getLabelId(block.entries[0]) + '; ' + (SHOW_LABELS ? '/* ' + getOriginalLabelId(block.entries[0]) + ' */' : '') + '\n';
} // otherwise, should have been set before!
- ret += indent + 'while(1) switch(__label__) {\n';
+ if (func.setjmpTable) {
+ var setjmpTable = {};
+ ret += indent + 'var setjmpTable = {';
+ func.setjmpTable.forEach(function(triple) { // original label, label we created for right after the setjmp, variable setjmp result goes into
+ ret += '"' + getLabelId(triple[0]) + '": ' + 'function(value) { __label__ = ' + getLabelId(triple[1]) + '; ' + triple[2] + ' = value },';
+ });
+ ret += 'dummy: 0';
+ ret += '};\n';
+ }
+ ret += indent + 'while(1) ';
+ if (func.setjmpTable) {
+ ret += 'try { ';
+ }
+ ret += 'switch(__label__) {\n';
ret += block.labels.map(function(label) {
- return indent + ' case ' + getLabelId(label.ident) + ': // ' + label.ident + '\n'
+ return indent + ' case ' + getLabelId(label.ident) + ': ' + (SHOW_LABELS ? '// ' + getOriginalLabelId(label.ident) : '') + '\n'
+ getLabelLines(label, indent + ' ');
}).join('\n');
ret += '\n' + indent + ' default: assert(0, "bad label: " + __label__);\n' + indent + '}';
+ if (func.setjmpTable) {
+ ret += ' } catch(e) { if (!e.longjmp) throw(e); setjmpTable[e.label](e.value) }';
+ }
} else {
ret += (SHOW_LABELS ? indent + '/* ' + block.entries[0] + ' */' : '') + '\n' + getLabelLines(block.labels[0], indent);
}
@@ -754,11 +770,14 @@ function JSify(data, functionsOnly, givenFunctions) {
makeFuncLineActor('deleted', function(item) { return ';' });
- function getLabelId(label) {
+ function getOriginalLabelId(label) {
var funcData = Framework.currItem.funcData;
- var labelIds = funcData.labelIds;
- if (labelIds[label] !== undefined) return labelIds[label];
- return labelIds[label] = funcData.labelIdCounter++;
+ var labelIdsInverse = funcData.labelIdsInverse;
+ return labelIdsInverse[label];
+ }
+
+ function getLabelId(label) {
+ return label;
}
function makeBranch(label, lastLabel, labelIsVariable) {
@@ -772,7 +791,7 @@ function JSify(data, functionsOnly, givenFunctions) {
var trueLabel = parts[1] || '';
var oldLabel = parts[2] || '';
var labelSetting = oldLabel ? '__label__ = ' + getLabelId(oldLabel) + ';' +
- (SHOW_LABELS ? ' /* to: ' + cleanLabel(oldLabel) + ' */' : '') : ''; // TODO: optimize away the setting
+ (SHOW_LABELS ? ' /* to: ' + getOriginalLabelId(cleanLabel(oldLabel)) + ' */' : '') : ''; // TODO: optimize away the setting
if (label[1] == 'R') {
if (label[2] == 'N') { // BRNOL: break, no label setting
labelSetting = '';
@@ -792,7 +811,7 @@ function JSify(data, functionsOnly, givenFunctions) {
}
} else {
if (!labelIsVariable) label = getLabelId(label);
- return pre + '__label__ = ' + label + ';' + (SHOW_LABELS ? ' /* to: ' + cleanLabel(label) + ' */' : '') + ' break;';
+ return pre + '__label__ = ' + label + ';' + (SHOW_LABELS ? ' /* to: ' + getOriginalLabelId(cleanLabel(label)) + ' */' : '') + ' break;';
}
}
@@ -902,13 +921,16 @@ function JSify(data, functionsOnly, givenFunctions) {
});
var ret = '';
var first = true;
+ var signedIdent = makeSignOp(item.ident, item.type, 're'); // we need to standardize for purpose of comparison
for (var targetLabel in targetLabels) {
if (!first) {
ret += 'else ';
} else {
first = false;
}
- ret += 'if (' + targetLabels[targetLabel].map(function(value) { return item.ident + ' == ' + value }).join(' || ') + ') {\n';
+ ret += 'if (' + targetLabels[targetLabel].map(function(value) {
+ return makeComparison(signedIdent, makeSignOp(value, item.type, 're'), item.type)
+ }).join(' || ') + ') {\n';
ret += ' ' + getPhiSetsForLabel(phiSets, targetLabel) + makeBranch(targetLabel, item.currLabelId || null) + '\n';
ret += '}\n';
}
@@ -953,7 +975,16 @@ function JSify(data, functionsOnly, givenFunctions) {
+ 'if (typeof e != "number") throw e; '
+ 'if (ABORT) throw e; __THREW__ = true; '
+ (EXCEPTION_DEBUG ? 'print("Exception: " + e + ", currently at: " + (new Error().stack)); ' : '')
- + 'return null } })(); if (!__THREW__) { ' + getPhiSetsForLabel(phiSets, item.toLabel) + makeBranch(item.toLabel, item.currLabelId)
+ + 'return null } })();';
+ if (item.assignTo) {
+ ret = 'var ' + item.assignTo + ' = ' + ret;
+ if (isIllegalType(item.type)) {
+ assert(item.type == 'i64', 'Can only handle i64 invoke among illegal invokes');
+ ret += 'var ' + item.assignTo + '$0 = ' + item.assignTo + '[0], ' + item.assignTo + '$1 = ' + item.assignTo + '[1];';
+ }
+ item.assignTo = null;
+ }
+ ret += 'if (!__THREW__) { ' + getPhiSetsForLabel(phiSets, item.toLabel) + makeBranch(item.toLabel, item.currLabelId)
+ ' } else { ' + getPhiSetsForLabel(phiSets, item.unwindLabel) + makeBranch(item.unwindLabel, item.currLabelId) + ' }';
return ret;
});
@@ -963,6 +994,7 @@ function JSify(data, functionsOnly, givenFunctions) {
var param2 = finalizeLLVMParameter(item.params[1]);
switch (item.op) {
case 'add': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, 'tempValue+' + param2, type) + ',tempValue)';
+ case 'sub': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, 'tempValue-' + param2, type) + ',tempValue)';
case 'xchg': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, param2, type) + ',tempValue)';
case 'cmpxchg': {
var param3 = finalizeLLVMParameter(item.params[2]);
@@ -972,9 +1004,8 @@ function JSify(data, functionsOnly, givenFunctions) {
}
});
makeFuncLineActor('landingpad', function(item) {
- // Just a stub
- return '{ f0: ' + makeGetValue('_llvm_eh_exception.buf', '0', 'void*') +
- ', f1:' + makeGetValue('_llvm_eh_exception.buf', QUANTUM_SIZE, 'void*') + ' }';
+ var catchTypeArray = item.catchables.map(finalizeLLVMParameter).join(',');
+ return '___cxa_find_matching_catch('+ makeGetValue('_llvm_eh_exception.buf', '0', 'void*') +',' + makeGetValue('_llvm_eh_exception.buf', QUANTUM_SIZE, 'void*') + ',[' + catchTypeArray +'])';
});
makeFuncLineActor('load', function(item) {
var value = finalizeLLVMParameter(item.pointer);
@@ -1030,10 +1061,14 @@ function JSify(data, functionsOnly, givenFunctions) {
makeFuncLineActor('mathop', processMathop);
makeFuncLineActor('bitcast', function(item) {
- return processMathop({
+ var temp = {
op: 'bitcast', variant: null, type: item.type,
- param1: item.params[0]
- });
+ assignTo: item.assignTo,
+ params: [item.params[0]] // XXX
+ };
+ var ret = processMathop(temp);
+ if (!temp.assignTo) item.assignTo = null; // If the assign was stolen, propagate that
+ return ret;
});
function makeFunctionCall(ident, params, funcData, type) {