diff options
author | Alon Zakai <alonzakai@gmail.com> | 2012-12-06 12:02:03 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2012-12-07 14:23:24 -0800 |
commit | d1d33362df70a31e7248e2fda0eb4bad0fe58390 (patch) | |
tree | d0973fc4d737043a7c19d9fa5fdd3edcf026e445 | |
parent | 32635a86097de499d7ee84bd9fb6967bd96e6169 (diff) |
legalize illegal parts of structural types
-rw-r--r-- | src/analyzer.js | 67 | ||||
-rw-r--r-- | src/jsifier.js | 2 | ||||
-rw-r--r-- | src/parseTools.js | 18 | ||||
-rw-r--r-- | tests/cases/uadd_overflow.ll | 12 | ||||
-rw-r--r-- | tests/cases/uadd_overflow.txt | 1 |
5 files changed, 79 insertions, 21 deletions
diff --git a/src/analyzer.js b/src/analyzer.js index f917d149..32b42a75 100644 --- a/src/analyzer.js +++ b/src/analyzer.js @@ -120,7 +120,8 @@ function analyzer(data, sidePass) { processItem: function(data) { // Legalization if (USE_TYPED_ARRAYS == 2) { - function getLegalVars(base, bits) { + function getLegalVars(base, bits, allowLegal) { + if (allowLegal && bits <= 32) return [{ ident: base, bits: bits }]; if (isNumber(base)) return getLegalLiterals(base, bits); var ret = new Array(Math.ceil(bits/32)); var i = 0; @@ -155,10 +156,6 @@ function analyzer(data, sidePass) { return getLegalStructuralParts(value).map(function(part) { return { ident: part.ident, bits: part.type.substr(1) }; }); - //} else if (value.ident == 'zeroinitializer' || value.ident == 'undef') { - // return getStructuralTypeParts(value.type).map(function(part) { - // return { ident: 0, bits: 32 }; - // }); } else { return getLegalVars(value.ident, bits); } @@ -331,7 +328,7 @@ function analyzer(data, sidePass) { intertype: 'value', assignTo: element.ident, type: element.bits, - ident: 'tempRet' + (j++ - 1) + ident: 'tempRet' + (j - 1) }); assert(j<10); // TODO: dynamically create more than 10 tempRet-s } @@ -461,26 +458,58 @@ 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++; + case 'extractvalue': { // XXX we assume 32-bit alignment in extractvalue/insertvalue, + // but in theory they can run on packed structs too (see use getStructuralTypePartBits) + // potentially legalize the actual extracted value too if it is >32 bits, not just the extraction in general + var index = item.indexes[0][0].text; + var parts = getStructureTypeParts(item.type); + var indexedType = parts[index]; + var targetBits = getBits(indexedType); + var sourceBits = getBits(item.type); + var elements = getLegalVars(item.assignTo, targetBits, true); // possibly illegal + var sourceElements = getLegalVars(item.ident, sourceBits); // definitely illegal + var toAdd = []; + var sourceIndex = 0; + for (var partIndex = 0; partIndex < parts.length; partIndex++) { + if (partIndex == index) { + for (var j = 0; j < elements.length; j++) { + toAdd.push({ + intertype: 'value', + assignTo: elements[j].ident, + type: 'i' + elements[j].bits, + ident: sourceElements[sourceIndex+j].ident + }); + } + break; + } + sourceIndex += getStructuralTypePartBits(parts[partIndex])/32; + } + i += removeAndAdd(label.lines, i, toAdd); continue; } case 'insertvalue': { + var index = item.indexes[0][0].text; // the modified index + var parts = getStructureTypeParts(item.type); + var indexedType = parts[index]; + var indexBits = getBits(indexedType); + var bits = getBits(item.type); // source and target bits = getBits(value.type); var toAdd = []; var elements = getLegalVars(item.assignTo, bits); var sourceElements = getLegalVars(item.ident, bits); - var modifiedIndex = value.indexes[0][0].text; - for (var j = 0; j < elements.length; j++) { - toAdd.push({ - intertype: 'value', - assignTo: elements[j].ident, - type: 'i' + elements[j].bits, - ident: j == modifiedIndex ? item.value.ident : sourceElements[j].ident - }); + var indexElements = getLegalVars(item.value.ident, indexBits, true); // possibly legal + var sourceIndex = 0; + for (var partIndex = 0; partIndex < parts.length; partIndex++) { + var currNum = getStructuralTypePartBits(parts[partIndex])/32; + for (var j = 0; j < currNum; j++) { + toAdd.push({ + intertype: 'value', + assignTo: elements[sourceIndex+j].ident, + type: 'i' + elements[sourceIndex+j].bits, + ident: partIndex == index ? indexElements[j].ident : sourceElements[sourceIndex+j].ident + }); + } + sourceIndex += currNum; } i += removeAndAdd(label.lines, i, toAdd); continue; diff --git a/src/jsifier.js b/src/jsifier.js index 01bb989d..00c32277 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -830,7 +830,7 @@ function JSify(data, functionsOnly, givenFunctions) { return substrate.addActor('Intertype:' + intertype, { processItem: function(item) { item.JS = func(item); - if (!item.JS) throw "No JS generated for " + dump(item); + if (!item.JS) throw "No JS generated for " + dump((item.funcData=null,item)); if (item.assignTo) { makeAssign(item); if (!item.JS) throw "No assign JS generated for " + dump(item); diff --git a/src/parseTools.js b/src/parseTools.js index 49740c6d..19913949 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -136,6 +136,20 @@ function getStructuralTypeParts(type) { // split { i32, i8 } etc. into parts return type.replace(/[ {}]/g, '').split(','); } +function getStructureTypeParts(type) { + if (isStructuralType(type)) { + return type.replace(/[ {}]/g, '').split(','); + } else { + var typeData = Types.types[type]; + assert(typeData, type); + return typeData.fields; + } +} + +function getStructuralTypePartBits(part) { + return Math.ceil(getBits(part)/32)*32; // simple 32-bit alignment +} + function isIntImplemented(type) { return type[0] == 'i' || isPointerType(type); } @@ -148,7 +162,9 @@ function getBits(type) { if (!isNumber(left)) return 0; return parseInt(left); } - if (isStructuralType(type)) return getStructuralTypeParts(type).length*32; // 32 bits per part in { i32, i1, i8, i32 } etc + if (isStructuralType(type)) { + return sum(getStructuralTypeParts(type).map(getStructuralTypePartBits)); + } if (isStructType(type)) { var typeData = Types.types[type]; return typeData.flatSize*8; diff --git a/tests/cases/uadd_overflow.ll b/tests/cases/uadd_overflow.ll index dfbf199b..81a76bcd 100644 --- a/tests/cases/uadd_overflow.ll +++ b/tests/cases/uadd_overflow.ll @@ -15,6 +15,7 @@ entry: %a1 = extractvalue { i32, i1 } %uadd1, 1 %a2 = zext i1 %a1 to i32 call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([9 x i8]* @.str2, i32 0, i32 0), i32 %a0, i32 %a2) ; [#uses=0] + %buadd1prepre = tail call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %mul7, i32 %shl10) %buadd1pre = insertvalue { i32, i1 } %buadd1prepre, i1 0, 1 %buadd1 = insertvalue { i32, i1 } %buadd1pre, i32 5177, 0 @@ -22,6 +23,16 @@ entry: %ba1 = extractvalue { i32, i1 } %buadd1, 1 %ba2 = zext i1 %ba1 to i32 call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([9 x i8]* @.str2, i32 0, i32 0), i32 %ba0, i32 %ba2) ; [#uses=0] + + %64buadd1pre = tail call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 5000, i64 3000) + %64buadd1 = insertvalue { i64, i1 } %64buadd1pre, i64 9875, 0 + %64buadd2 = insertvalue { i64, i1 } %64buadd1, i1 1, 1 + %64ba0pre = extractvalue { i64, i1 } %64buadd2, 0 + %64ba0 = trunc i64 %64ba0pre to i32 + %64ba1 = extractvalue { i64, i1 } %64buadd2, 1 + %64ba2 = zext i1 %64ba1 to i32 + call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([9 x i8]* @.str2, i32 0, i32 0), i32 %64ba0, i32 %64ba2) ; [#uses=0] + ret i32 1 } @@ -29,4 +40,5 @@ entry: declare i32 @printf(i8*, ...) declare { i32, i1 } @llvm.uadd.with.overflow.i32(i32, i32) nounwind readnone +declare { i64, i1 } @llvm.uadd.with.overflow.i64(i64, i32) nounwind readnone diff --git a/tests/cases/uadd_overflow.txt b/tests/cases/uadd_overflow.txt index 6e65c896..bcd04599 100644 --- a/tests/cases/uadd_overflow.txt +++ b/tests/cases/uadd_overflow.txt @@ -1,2 +1,3 @@ *3319578,1* *5177,0* +*9875,1* |