aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2012-12-05 16:14:36 -0800
committerAlon Zakai <alonzakai@gmail.com>2012-12-07 14:23:23 -0800
commitb6466081c6023181cdbfc3421c78966edfdf7c44 (patch)
tree152fc0e133b974d032201f7719a170ecd6a0a768
parentcfc6b10be7b2742949b78f0c41371ceaff5978ce (diff)
start to legalize structural types
-rw-r--r--src/analyzer.js46
-rw-r--r--src/parseTools.js9
-rw-r--r--tests/cases/structparam.ll1
3 files changed, 50 insertions, 6 deletions
diff --git a/src/analyzer.js b/src/analyzer.js
index bef810b7..751c0970 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -19,7 +19,7 @@ function recomputeLines(func) {
var BRANCH_INVOKE = set('branch', 'invoke');
var SIDE_EFFECT_CAUSERS = set('call', 'invoke', 'atomic');
-var UNUNFOLDABLE = set('value', 'type', 'phiparam');
+var UNUNFOLDABLE = set('value', 'structvalue', 'type', 'phiparam');
// Analyzer
@@ -142,6 +142,9 @@ function analyzer(data, sidePass) {
}
return ret;
}
+ function getLegalStructuralParts(value) {
+ return value.params.slice(0);
+ }
// Uses the right factor to multiply line numbers by so that they fit in between
// the line[i] and the line after it
function interpLines(lines, i, toAdd) {
@@ -191,6 +194,7 @@ function analyzer(data, sidePass) {
// Legalize lines in labels
var tempId = 0;
func.labels.forEach(function(label) {
+ if (dcheck('legalizer')) dprint('zz legalizing: \n' + dump(label.lines));
var i = 0, bits;
while (i < label.lines.length) {
var item = label.lines[i];
@@ -222,7 +226,7 @@ function analyzer(data, sidePass) {
if (subItem != item && (!(subItem.intertype in UNUNFOLDABLE) ||
(subItem.intertype == 'value' && isNumber(subItem.ident) && isIllegalType(subItem.type)))) {
if (item.intertype == 'phi') {
- assert(subItem.intertype == 'value', 'We can only unfold illegal constants in phis');
+ assert(subItem.intertype == 'value' || subItem.intertype == 'structvalue', 'We can only unfold illegal constants in phis');
// we must handle this in the phi itself, if we unfold normally it will not be pushed back with the phi
} else {
var tempIdent = '$$etemp$' + (tempId++);
@@ -341,6 +345,21 @@ function analyzer(data, sidePass) {
i += removeAndAdd(label.lines, i, toAdd);
continue;
}
+ case 'structvalue': {
+ bits = getBits(value.type);
+ var elements = getLegalVars(item.assignTo, bits);
+ var toAdd = [];
+ for (var j = 0; j < item.params.length; j++) {
+ toAdd[j] = {
+ intertype: 'value',
+ assignTo: elements[j].ident,
+ type: 'i32',
+ ident: item.params[j].ident
+ };
+ }
+ i += removeAndAdd(label.lines, i, toAdd);
+ continue;
+ }
case 'load': {
bits = getBits(value.valueType);
var elements = getLegalVars(item.assignTo, bits);
@@ -382,13 +401,21 @@ function analyzer(data, sidePass) {
var toAdd = [];
var elements = getLegalVars(item.assignTo, bits);
var j = 0;
- var literalValues = {}; // special handling of literals - we cannot unfold them normally
- value.params.map(function(param) {
+ var values = value.params.map(function(param) {
if (isNumber(param.value.ident)) {
- literalValues[param.value.ident] = getLegalLiterals(param.value.ident, bits);
+ return getLegalLiterals(param.value.ident, bits);
+ } else if (param.value.intertype == 'structvalue') {
+ return getLegalStructuralParts(param.value);
+ } else if (param.value.ident == 'zeroinitializer') {
+ return getStructuralTypeParts(param.value.type).map(function(part) {
+ return { ident: 0, type: 'i32' };
+ });
+ } else {
+ return getLegalVars(param.value.ident, bits);
}
});
elements.forEach(function(element) {
+ var k = 0;
toAdd.push({
intertype: 'phi',
assignTo: element.ident,
@@ -399,7 +426,7 @@ function analyzer(data, sidePass) {
label: param.label,
value: {
intertype: 'value',
- ident: (param.value.ident in literalValues) ? literalValues[param.value.ident][j].ident : (param.value.ident + '$' + j),
+ ident: values[k++][j].ident,
type: 'i' + element.bits,
}
};
@@ -414,6 +441,13 @@ function analyzer(data, sidePass) {
i++;
continue; // special case, handled in makeComparison
}
+ case 'extractvalue': {
+ item.intertype = 'value';
+ item.ident = item.ident + '$' + item.indexes[0][0].text;
+ item.type = 'i32'; // XXX we assume they are all i32-compatible
+ i++;
+ continue;
+ }
case 'bitcast': {
var inType = item.type2;
var outType = item.type;
diff --git a/src/parseTools.js b/src/parseTools.js
index 5cae53b4..a7a45f09 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -128,12 +128,21 @@ function isStructType(type) {
return type[0] == '%';
}
+function isStructuralType(type) {
+ return /^{ ?[^}]* ?}$/.test(type); // { i32, i8 } etc. - anonymous struct types
+}
+
+function getStructuralTypeParts(type) { // split { i32, i8 } etc. into parts
+ return type.replace(/[ {}]/g, '').split(',');
+}
+
function isIntImplemented(type) {
return type[0] == 'i' || isPointerType(type);
}
// Note: works for iX types, not pointers (even though they are implemented as ints)
function getBits(type) {
+ if (isStructuralType(type)) return getStructuralTypeParts(type).length*32; // 32 bits per part in { i32, i1, i8, i32 } etc
if (!type || type[0] != 'i') return 0;
var left = type.substr(1);
if (!isNumber(left)) return 0;
diff --git a/tests/cases/structparam.ll b/tests/cases/structparam.ll
index b9ecd770..c59ad600 100644
--- a/tests/cases/structparam.ll
+++ b/tests/cases/structparam.ll
@@ -15,6 +15,7 @@ define i32 @doit(i32 %x, { i32, i32 } %y) {
define i32 @main() {
entry:
%retval = alloca i32, align 4 ; [#uses=1 type=i32*]
+ %myi64 = alloca i64, align 4
%comp = alloca { i32, i32 }, align 4 ; [#uses=1]
store i32 0, i32* %retval
br label %cond.end