aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2012-12-06 12:02:03 -0800
committerAlon Zakai <alonzakai@gmail.com>2012-12-07 14:23:24 -0800
commitd1d33362df70a31e7248e2fda0eb4bad0fe58390 (patch)
treed0973fc4d737043a7c19d9fa5fdd3edcf026e445
parent32635a86097de499d7ee84bd9fb6967bd96e6169 (diff)
legalize illegal parts of structural types
-rw-r--r--src/analyzer.js67
-rw-r--r--src/jsifier.js2
-rw-r--r--src/parseTools.js18
-rw-r--r--tests/cases/uadd_overflow.ll12
-rw-r--r--tests/cases/uadd_overflow.txt1
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*