aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2012-01-28 09:28:44 -0800
committerAlon Zakai <alonzakai@gmail.com>2012-01-28 09:28:44 -0800
commitbbab542ca777f91cae76244dc8455c800de58ce7 (patch)
tree1470abc99ffce2b94c18d86438dcf9977bdb099c
parentf8d4a502913713757355a700bda4ddf7270121ed (diff)
legalize lshr
-rw-r--r--src/analyzer.js53
-rw-r--r--src/jsifier.js3
-rw-r--r--src/parseTools.js2
3 files changed, 57 insertions, 1 deletions
diff --git a/src/analyzer.js b/src/analyzer.js
index 4839134f..2eb6f8d5 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -254,7 +254,7 @@ function analyzer(data, sidePass) {
}
}
case 'mathop': {
- if (isIllegalType(value.valueType)) {
+ if (isIllegalType(value.type)) {
dprint('legalizer', 'Legalizing mathop at line ' + item.lineNum);
bits = getBits(value.type);
var targetElements = getLegalVars(item.ident, bits);
@@ -263,6 +263,57 @@ function analyzer(data, sidePass) {
label.lines.splice(i, 1);
switch (value.op) {
case 'lshr': {
+ assert(value.param2.intertype == 'value', 'TODO: unfolding');
+ var shifts = parseInt(value.param2.ident);
+ assert(isNumber(shifts), 'TODO: handle nonconstant shifts');
+ // Shift right makes values smaller. Towards the 0 index of the elements
+ var whole = Math.floor(shifts/32);
+ var fraction = shifts % 32;
+ var toAdd = [];
+ for (var j = 0; j < targetElements.length; j++) {
+ var result = {
+ intertype: 'value',
+ ident: (j + whole) < sourceElements.length ? sourceElements[j + whole].ident : '0',
+ type: 'i32',
+ };
+ if (fraction > 0) {
+ var other = {
+ intertype: 'value',
+ ident: (j + 1 + whole) < sourceElements.length ? sourceElements[j + 1 + whole].ident : '0',
+ type: 'i32',
+ };
+ other = {
+ intertype: 'mathop',
+ op: 'shl',
+ type: 'i32',
+ param1: other,
+ param2: { intertype: 'value', ident: (32 - fraction).toString(), type: 'i32' }
+ };
+ result = {
+ intertype: 'mathop',
+ op: 'lshr',
+ type: 'i32',
+ param1: result,
+ param2: { intertype: 'value', ident: fraction.toString(), type: 'i32' }
+ };
+ result = {
+ intertype: 'mathop',
+ op: 'or',
+ type: 'i32',
+ param1: result,
+ param2: other
+ }
+ }
+ toAdd.push({
+ intertype: 'assign',
+ ident: targetElements[j].ident,
+ value: result,
+ lineNum: item.lineNum + (j/100)
+ });
+ }
+ Array.prototype.splice.apply(label.lines, [i, 0].concat(toAdd));
+ i += toAdd.length;
+ continue;
}
default: throw 'Invalid mathop for legalization: ' + [value.op, item.lineNum];
}
diff --git a/src/jsifier.js b/src/jsifier.js
index d7d161d3..62cab3d5 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -719,6 +719,9 @@ function JSify(data, functionsOnly, givenFunctions) {
}
});
}
+ makeFuncLineActor('value', function(item) {
+ return item.ident;
+ });
makeFuncLineActor('noop', function(item) {
return ';';
});
diff --git a/src/parseTools.js b/src/parseTools.js
index 45cee958..635fa411 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -1464,6 +1464,8 @@ function finalizeLLVMParameter(param, noIndexizeFunctions) {
return finalizeBlockAddress(param);
} else if (param.intertype === 'type') {
return param.ident; // we don't really want the type here
+ } else if (param.intertype == 'mathop') {
+ return processMathop(param);
} else {
throw 'invalid llvm parameter: ' + param.intertype;
}