diff options
Diffstat (limited to 'src/parseTools.js')
-rw-r--r-- | src/parseTools.js | 154 |
1 files changed, 81 insertions, 73 deletions
diff --git a/src/parseTools.js b/src/parseTools.js index 08cf9b60..bad080b7 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -16,6 +16,7 @@ function processMacros(text) { // Simple #if/else/endif preprocessing for a file. Checks if the // ident checked is true in our global. +// Also handles #include x.js (similar to C #include <file>) function preprocess(text) { var lines = text.split('\n'); var ret = ''; @@ -30,25 +31,34 @@ function preprocess(text) { ret += line + '\n'; } } else { - if (line[1] && line[1] == 'i') { // if - var parts = line.split(' '); - var ident = parts[1]; - var op = parts[2]; - var value = parts[3]; - if (op) { - if (op === '==') { - showStack.push(ident in this && this[ident] == value); - } else if (op === '!=') { - showStack.push(!(ident in this && this[ident] == value)); + if (line[1] == 'i') { + if (line[2] == 'f') { // if + var parts = line.split(' '); + var ident = parts[1]; + var op = parts[2]; + var value = parts[3]; + if (op) { + if (op === '==') { + showStack.push(ident in this && this[ident] == value); + } else if (op === '!=') { + showStack.push(!(ident in this && this[ident] == value)); + } else { + error('unsupported preprecessor op ' + op); + } } else { - error('unsupported preprecessor op ' + op); + if (ident[0] === '!') { + showStack.push(!(this[ident.substr(1)] > 0)); + } else { + showStack.push(ident in this && this[ident] > 0); + } } - } else { - showStack.push(ident in this && this[ident] > 0); + } else if (line[2] == 'n') { // include + var included = read(line.substr(line.indexOf(' ')+1)); + ret += '\n' + preprocess(included) + '\n' } - } else if (line[2] && line[2] == 'l') { // else + } else if (line[2] == 'l') { // else showStack.push(!showStack.pop()); - } else if (line[2] && line[2] == 'n') { // endif + } else if (line[2] == 'n') { // endif showStack.pop(); } else { throw "Unclear preprocessor command: " + line; @@ -362,7 +372,7 @@ function getVectorNativeType(type) { function getSIMDName(type) { switch (type) { - case 'i32': return 'uint'; + case 'i32': return 'int'; case 'float': return 'float'; default: throw 'getSIMDName ' + type; } @@ -457,7 +467,7 @@ function parseParamTokens(params) { // handle 'byval' and 'byval align X'. We store the alignment in 'byVal' byVal = QUANTUM_SIZE; segment.splice(1, 1); - if (segment[1] && segment[1].text === 'nocapture') { + if (segment[1] && (segment[1].text === 'nocapture' || segment[1].text === 'readonly')) { segment.splice(1, 1); } if (segment[1] && segment[1].text === 'align') { @@ -466,7 +476,7 @@ function parseParamTokens(params) { segment.splice(1, 2); } } - if (segment[1] && segment[1].text === 'nocapture') { + if (segment[1] && (segment[1].text === 'nocapture' || segment[1].text === 'readonly')) { segment.splice(1, 1); } if (segment.length == 1) { @@ -603,10 +613,11 @@ function parseLLVMSegment(segment) { type = segment[0].text; if (type[type.length-1] === '>' && segment[1].text[0] === '<') { // vector literal + var nativeType = getVectorNativeType(type); return { intertype: 'vector', idents: splitTokenList(segment[1].tokens).map(function(pair) { - return pair[1].text; + return parseNumerical(pair[1].text, nativeType); }), type: type }; @@ -621,7 +632,7 @@ function parseLLVMSegment(segment) { } function cleanSegment(segment) { - while (segment.length >= 2 && ['noalias', 'sret', 'nocapture', 'nest', 'zeroext', 'signext'].indexOf(segment[1].text) != -1) { + while (segment.length >= 2 && ['noalias', 'sret', 'nocapture', 'nest', 'zeroext', 'signext', 'readnone'].indexOf(segment[1].text) != -1) { segment.splice(1, 1); } return segment; @@ -955,8 +966,13 @@ function parseNumerical(value, type) { } if (isNumber(value)) { var ret = parseFloat(value); // will change e.g. 5.000000e+01 to 50 + // type may be undefined here, like when this is called from makeConst with a single argument. + // but if it is a number, then we can safely assume that this should handle negative zeros + // correctly. + if (type === undefined || type === 'double' || type === 'float') { + if (value[0] === '-' && ret === 0) { return '-.0'; } // fix negative 0, toString makes it 0 + } if (type === 'double' || type === 'float') { - if (value[0] === '-' && ret === 0) return '-.0'; // fix negative 0, toString makes it 0 if (!RUNNING_JS_OPTS) ret = asmEnsureFloat(ret, type); } return ret.toString(); @@ -1315,18 +1331,22 @@ function makeGetValue(ptr, pos, type, noNeedFirst, unsigned, ignore, align, noSa var printType = type; if (printType !== 'null' && printType[0] !== '#') printType = '"' + safeQuote(printType) + '"'; if (printType[0] === '#') printType = printType.substr(1); - return asmCoercion('SAFE_HEAP_LOAD(' + asmCoercion(offset, 'i32') + ', ' + (ASM_JS ? 0 : printType) + ', ' + (!!unsigned+0) + ', ' + ((!checkSafeHeap() || ignore)|0) + ')', type); - } else { - var ret = makeGetSlabs(ptr, type, false, unsigned)[0] + '[' + getHeapOffset(offset, type, forceAsm) + ']'; - if (ASM_JS && (phase == 'funcs' || forceAsm)) { - ret = asmCoercion(ret, type); - } - if (ASM_HEAP_LOG) { - ret = makeInlineCalculation('(asmPrint' + (type in Runtime.FLOAT_TYPES ? 'Float' : 'Int') + '(' + (asmPrintCounter++) + ',' + asmCoercion('VALUE', type) + '), VALUE)', ret, - 'temp' + (type in Runtime.FLOAT_TYPES ? 'Double' : 'Int')); + if (ASM_JS) { + if (!ignore && phase !== 'funcs') return asmCoercion('SAFE_HEAP_LOAD(' + asmCoercion(offset, 'i32') + ', ' + Runtime.getNativeTypeSize(type) + ', ' + ((type in Runtime.FLOAT_TYPES)|0) + ', ' + (!!unsigned+0) + ')', type); + // else fall through + } else { + return asmCoercion('SAFE_HEAP_LOAD(' + offset + ', ' + (ASM_JS ? 0 : printType) + ', ' + (!!unsigned+0) + ', ' + ((!checkSafeHeap() || ignore)|0) + ')', type); } - return ret; } + var ret = makeGetSlabs(ptr, type, false, unsigned)[0] + '[' + getHeapOffset(offset, type, forceAsm) + ']'; + if (ASM_JS && (phase == 'funcs' || forceAsm)) { + ret = asmCoercion(ret, type); + } + if (ASM_HEAP_LOG) { + ret = makeInlineCalculation('(asmPrint' + (type in Runtime.FLOAT_TYPES ? 'Float' : 'Int') + '(' + (asmPrintCounter++) + ',' + asmCoercion('VALUE', type) + '), VALUE)', ret, + 'temp' + (type in Runtime.FLOAT_TYPES ? 'Double' : 'Int')); + } + return ret; } function makeGetValueAsm(ptr, pos, type, unsigned) { @@ -1423,10 +1443,14 @@ function makeSetValue(ptr, pos, value, type, noNeedFirst, ignore, align, noSafe, var printType = type; if (printType !== 'null' && printType[0] !== '#') printType = '"' + safeQuote(printType) + '"'; if (printType[0] === '#') printType = printType.substr(1); - return 'SAFE_HEAP_STORE(' + asmCoercion(offset, 'i32') + ', ' + asmCoercion(value, type) + ', ' + (ASM_JS ? 0 : printType) + ', ' + ((!checkSafeHeap() || ignore)|0) + ')'; - } else { - return makeGetSlabs(ptr, type, true).map(function(slab) { return slab + '[' + getHeapOffset(offset, type, forceAsm) + ']=' + value }).join(sep); + if (ASM_JS) { + if (!ignore && phase !== 'funcs') return asmCoercion('SAFE_HEAP_STORE(' + asmCoercion(offset, 'i32') + ', ' + asmCoercion(value, type) + ', ' + Runtime.getNativeTypeSize(type) + ', ' + ((type in Runtime.FLOAT_TYPES)|0) + ')', type); + // else fall through + } else { + return 'SAFE_HEAP_STORE(' + offset + ', ' + value + ', ' + (ASM_JS ? 0 : printType) + ', ' + ((!checkSafeHeap() || ignore)|0) + ')'; + } } + return makeGetSlabs(ptr, type, true).map(function(slab) { return slab + '[' + getHeapOffset(offset, type, forceAsm) + ']=' + value }).join(sep); } function makeSetValueAsm(ptr, pos, value, type, noNeedFirst, ignore, align, noSafe, sep, forcedAlign) { @@ -1453,7 +1477,7 @@ function makeSetValues(ptr, pos, value, type, num, align) { // If we don't know how to handle this at compile-time, or handling it is best done in a large amount of code, call memset // TODO: optimize the case of numeric num but non-numeric value if (!isNumber(num) || !isNumber(value) || (parseInt(num)/align >= UNROLL_LOOP_MAX)) { - return '_memset(' + asmCoercion(getFastValue(ptr, '+', pos), 'i32') + ', ' + asmCoercion(value, 'i32') + ', ' + asmCoercion(num, 'i32') + ')'; + return '_memset(' + asmCoercion(getFastValue(ptr, '+', pos), 'i32') + ', ' + asmCoercion(value, 'i32') + ', ' + asmCoercion(num, 'i32') + ')|0'; } num = parseInt(num); value = parseInt(value); @@ -1633,7 +1657,10 @@ function getFastValue(a, op, b, type) { } function getFastValues(list, op, type) { - assert(op == '+'); + assert(op === '+' && type === 'i32'); + for (var i = 0; i < list.length; i++) { + if (isNumber(list[i])) list[i] = (list[i]|0) + ''; + } var changed = true; while (changed) { changed = false; @@ -1641,6 +1668,7 @@ function getFastValues(list, op, type) { var fast = getFastValue(list[i], op, list[i+1], type); var raw = list[i] + op + list[i+1]; if (fast.length < raw.length || fast.indexOf(op) < 0) { + if (isNumber(fast)) fast = (fast|0) + ''; list[i] = fast; list.splice(i+1, 1); i--; @@ -1765,31 +1793,12 @@ function makePointer(slab, pos, allocator, type, ptr, finalMemoryInitialization) types = 'i8'; } - // JS engines sometimes say array initializers are too large. Work around that by chunking and calling concat to combine at runtime - var chunkSize = JS_CHUNK_SIZE; - function chunkify(array) { - // break very large slabs into parts - var ret = ''; - var index = 0; - while (index < array.length) { - ret = (ret ? ret + '.concat(' : '') + '[' + array.slice(index, index + chunkSize).map(JSON.stringify) + ']' + (ret ? ')\n' : ''); - index += chunkSize; - } - return ret; - } - if (typeof slab == 'object' && slab.length > chunkSize) { - slab = chunkify(slab); - } if (typeof types == 'object') { while (types.length < slab.length) types.push(0); } - if (typeof types != 'string' && types.length > chunkSize) { - types = chunkify(types); - } else { - types = JSON.stringify(types); - } + types = JSON.stringify(types); if (typeof slab == 'object') slab = '[' + slab.join(',') + ']'; - return 'allocate(' + slab + ', ' + types + (allocator ? ', ' + allocator : '') + (allocator == 'ALLOC_NONE' ? ', ' + ptr : '') + ')'; + return 'allocate(' + slab + ', ' + types + (allocator ? ', ' + allocator : '') + (allocator == 'ALLOC_NONE' ? ', ' + ptr : '') + ');'; } function makeGetSlabs(ptr, type, allowMultiple, unsigned) { @@ -2134,9 +2143,9 @@ function makeRounding(value, bits, signed, floatConversion) { } } // Math.floor is reasonably fast if we don't care about corrections (and even correct if unsigned) - if (!correctRoundings() || !signed) return 'Math_floor(' + value + ')'; + if (!correctRoundings() || !signed) return '(+Math_floor(' + value + '))'; // We are left with >32 bits - return makeInlineCalculation(makeComparison('VALUE', '>=', '0', 'float') + ' ? Math_floor(VALUE) : Math_ceil(VALUE)', value, 'tempBigIntR'); + return makeInlineCalculation(makeComparison('VALUE', '>=', '0', 'float') + ' ? +Math_floor(VALUE) : +Math_ceil(VALUE)', value, 'tempBigIntR'); } } @@ -2371,29 +2380,28 @@ function processMathop(item) { // vector/SIMD operation Types.usesSIMD = true; switch (op) { - case 'fadd': return 'SIMD.add(' + idents[0] + ',' + idents[1] + ')'; - case 'fsub': return 'SIMD.sub(' + idents[0] + ',' + idents[1] + ')'; - case 'fmul': return 'SIMD.mul(' + idents[0] + ',' + idents[1] + ')'; - case 'fdiv': return 'SIMD.div(' + idents[0] + ',' + idents[1] + ')'; - case 'add' : return 'SIMD.addu32(' + idents[0] + ',' + idents[1] + ')'; - case 'sub' : return 'SIMD.subu32(' + idents[0] + ',' + idents[1] + ')'; - case 'mul' : return 'SIMD.mulu32(' + idents[0] + ',' + idents[1] + ')'; - case 'udiv': return 'SIMD.divu32(' + idents[0] + ',' + idents[1] + ')'; + case 'fadd': return 'SIMD.float32x4.add(' + idents[0] + ',' + idents[1] + ')'; + case 'fsub': return 'SIMD.float32x4.sub(' + idents[0] + ',' + idents[1] + ')'; + case 'fmul': return 'SIMD.float32x4.mul(' + idents[0] + ',' + idents[1] + ')'; + case 'fdiv': return 'SIMD.float32x4.div(' + idents[0] + ',' + idents[1] + ')'; + case 'add' : return 'SIMD.int32x4.add(' + idents[0] + ',' + idents[1] + ')'; + case 'sub' : return 'SIMD.int32x4.sub(' + idents[0] + ',' + idents[1] + ')'; + case 'mul' : return 'SIMD.int32x4.mul(' + idents[0] + ',' + idents[1] + ')'; case 'bitcast': { var inType = item.params[0].type; var outType = item.type; if (inType === '<4 x float>') { assert(outType === '<4 x i32>'); - return 'SIMD.float32x4BitsToUint32x4(' + idents[0] + ')'; + return 'SIMD.float32x4.bitsToInt32x4(' + idents[0] + ')'; } else { assert(inType === '<4 x i32>'); assert(outType === '<4 x float>'); - return 'SIMD.uint32x4BitsToFloat32x4(' + idents[0] + ')'; + return 'SIMD.int32x4.bitsToFloat32x4(' + idents[0] + ')'; } } - case 'and': return 'SIMD.and(' + idents[0] + ',' + idents[1] + ')'; - case 'or': return 'SIMD.or(' + idents[0] + ',' + idents[1] + ')'; - case 'xor': return 'SIMD.xor(' + idents[0] + ',' + idents[1] + ')'; + case 'and': return 'SIMD.int32x4.and(' + idents[0] + ',' + idents[1] + ')'; + case 'or': return 'SIMD.int32x4.or(' + idents[0] + ',' + idents[1] + ')'; + case 'xor': return 'SIMD.int32x4.xor(' + idents[0] + ',' + idents[1] + ')'; default: throw 'vector op todo: ' + dump(item); } } @@ -2697,7 +2705,7 @@ var simdLane = ['x', 'y', 'z', 'w']; function ensureVector(ident, base) { Types.usesSIMD = true; - return ident == 0 ? base + '32x4.zero()' : ident; + return ident == 0 ? base + '32x4.splat(0)' : ident; } function ensureValidFFIType(type) { |