diff options
author | Alon Zakai <alonzakai@gmail.com> | 2012-12-05 16:14:36 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2012-12-07 14:23:23 -0800 |
commit | b6466081c6023181cdbfc3421c78966edfdf7c44 (patch) | |
tree | 152fc0e133b974d032201f7719a170ecd6a0a768 | |
parent | cfc6b10be7b2742949b78f0c41371ceaff5978ce (diff) |
start to legalize structural types
-rw-r--r-- | src/analyzer.js | 46 | ||||
-rw-r--r-- | src/parseTools.js | 9 | ||||
-rw-r--r-- | tests/cases/structparam.ll | 1 |
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 |