diff options
Diffstat (limited to 'src/parseTools.js')
-rw-r--r-- | src/parseTools.js | 67 |
1 files changed, 42 insertions, 25 deletions
diff --git a/src/parseTools.js b/src/parseTools.js index 955353b2..a5d8da56 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -53,6 +53,7 @@ function preprocess(text, constants) { function addPointing(type) { return type + '*' } function removePointing(type, num) { if (num === 0) return type; + assert(type.substr(type.length-(num ? num : 1)).replace(/\*/g, '') === ''); //, 'Error in removePointing with ' + [type, num, type.substr(type.length-(num ? num : 1))]); return type.substr(0, type.length-(num ? num : 1)); } @@ -114,6 +115,7 @@ function isStructPointerType(type) { function isStructType(type) { if (isPointerType(type)) return false; if (new RegExp(/^\[\d+\ x\ (.*)\]/g).test(type)) return true; // [15 x ?] blocks. Like structs + if (new RegExp(/<?{ [^}]* }>?/g).test(type)) return true; // { i32, i8 } etc. - anonymous struct types // See comment in isStructPointerType() return !Runtime.isNumberType(type) && type[0] == '%'; } @@ -148,7 +150,7 @@ function isFunctionType(type) { if (pointingLevels(type) !== 1) return false; var text = removeAllPointing(parts.slice(1).join(' ')); if (!text) return false; - return isType(parts[0]) && isFunctionDef({ text: text, item: tokenizer.processItem({ lineText: text.substr(1, text.length-2) }, true) }); + return isType(parts[0]) && isFunctionDef({ text: text, item: tokenize(text.substr(1, text.length-2), true) }); } function isType(type) { // TODO! @@ -465,15 +467,13 @@ function eatLLVMIdent(tokens) { return ret; } -function cleanOutTokens(filterOut, tokens, index) { - while (filterOut.indexOf(tokens[index].text) != -1) { - tokens.splice(index, 1); - } -} - -function cleanOutTokensSet(filterOut, tokens, index) { - while (tokens[index].text in filterOut) { - tokens.splice(index, 1); +function cleanOutTokens(filterOut, tokens, indexes) { + if (typeof indexes !== 'object') indexes = [indexes]; + for (var i = indexes.length-1; i >=0; i--) { + var index = indexes[i]; + while (tokens[index].text in filterOut) { + tokens.splice(index, 1); + } } } @@ -979,14 +979,14 @@ function makeGetSlabs(ptr, type, allowMultiple, unsigned) { return []; } -function finalizeLLVMFunctionCall(item) { +function finalizeLLVMFunctionCall(item, noIndexizeFunctions) { switch(item.intertype) { case 'getelementptr': // TODO finalizeLLVMParameter on the ident and the indexes? return makePointer(makeGetSlabs(item.ident, item.type)[0], getGetElementPtrIndexes(item), null, item.type); case 'bitcast': case 'inttoptr': case 'ptrtoint': - return finalizeLLVMParameter(item.params[0]); + return finalizeLLVMParameter(item.params[0], noIndexizeFunctions); case 'icmp': case 'mul': case 'zext': case 'add': case 'sub': case 'div': var temp = { op: item.intertype, @@ -1078,18 +1078,18 @@ function handleOverflow(text, bits) { } // From parseLLVMSegment -function finalizeLLVMParameter(param) { +function finalizeLLVMParameter(param, noIndexizeFunctions) { var ret; if (isNumber(param)) { return param; } else if (typeof param === 'string') { return toNiceIdentCarefully(param); } else if (param.intertype in PARSABLE_LLVM_FUNCTIONS) { - ret = finalizeLLVMFunctionCall(param); + ret = finalizeLLVMFunctionCall(param, noIndexizeFunctions); } else if (param.intertype == 'value') { ret = parseNumerical(param.ident); } else if (param.intertype == 'structvalue') { - ret = param.values.map(finalizeLLVMParameter); + ret = param.values.map(function(value) { return finalizeLLVMParameter(value, noIndexizeFunctions) }); } else if (param.intertype === 'blockaddress') { return finalizeBlockAddress(param); } else if (param.intertype === 'type') { @@ -1098,7 +1098,8 @@ function finalizeLLVMParameter(param) { throw 'invalid llvm parameter: ' + param.intertype; } assert(param.type || (typeof param === 'string' && param.substr(0, 6) === 'CHECK_'), 'Missing type for param: ' + dump(param)); - return indexizeFunctions(ret, param.type); + if (!noIndexizeFunctions) ret = indexizeFunctions(ret, param.type); + return ret; } function makeSignOp(value, type, op) { @@ -1117,12 +1118,20 @@ function makeSignOp(value, type, op) { } if (!correctSigns() && !CHECK_SIGNS) return value; if (type in Runtime.INT_TYPES) { - // shortcuts for 32-bit case - if (bits === 32 && !CHECK_SIGNS) { - if (op === 're') { - return '((' + value + ')|0)'; - } else { - return '((' + value + ')>>>0)'; + // shortcuts + if (!CHECK_SIGNS) { + if (bits === 32) { + if (op === 're') { + return '((' + value + ')|0)'; + } else { + return '((' + value + ')>>>0)'; + } + } else if (bits < 32) { + if (op === 'un') { + return '((' + value + ')&' + (Math.pow(2, bits)-1) + ')'; + } else { + return '(tempInt=(' + value + '),(tempInt>=' + Math.pow(2, bits-1) + '?tempInt-' + Math.pow(2, bits) + ':tempInt))'; + } } } return full; @@ -1161,6 +1170,8 @@ function processMathop(item) { with(item) { item['ident'+i] = null; // just so it exists for purposes of reading ident2 etc. later on, and no exception is thrown } } + var originalIdent1 = ident1; + var originalIdent2 = ident2; if (isUnsignedOp(op, variant)) { ident1 = makeSignOp(ident1, paramTypes[0], 'un'); ident2 = makeSignOp(ident2, paramTypes[1], 'un'); @@ -1174,6 +1185,10 @@ function processMathop(item) { with(item) { } var bitsLeft = ident2 ? ident2.substr(2, ident2.length-3) : null; // remove (i and ), to leave number. This value is important in float ops + function integerizeBignum(value) { + return '(tempBigInt=(' + value + '), tempBigInt-tempBigInt%1)'; + } + switch (op) { // basic integer ops case 'add': return handleOverflow(ident1 + ' + ' + ident2, bits); @@ -1217,15 +1232,17 @@ function processMathop(item) { with(item) { } } */ - if (bits > 32) return ident1 + '*Math.pow(2,' + ident2 + ')'; + if (bits > 32) return ident1 + '*Math.pow(2,' + ident2 + ')'; // TODO: calculate Math.pow at runtime for consts, and below too return ident1 + ' << ' + ident2; } case 'ashr': { - if (bits > 32) return ident1 + '/Math.pow(2,' + ident2 + ')'; + if (bits > 32) return integerizeBignum(ident1 + '/Math.pow(2,' + ident2 + ')'); + if (bits === 32) return originalIdent1 + ' >> ' + ident2; // No need to reSign in this case return ident1 + ' >> ' + ident2; } case 'lshr': { - if (bits > 32) return ident1 + '/Math.pow(2,' + ident2 + ')'; + if (bits > 32) return integerizeBignum(ident1 + '/Math.pow(2,' + ident2 + ')'); + if (bits === 32) return originalIdent1 + ' >>> ' + ident2; // No need to unSign in this case return ident1 + ' >>> ' + ident2; } // basic float ops |