diff options
-rw-r--r-- | src/analyzer.js | 60 | ||||
-rw-r--r-- | src/parseTools.js | 24 | ||||
-rw-r--r-- | src/runtime.js | 10 | ||||
-rw-r--r-- | src/utility.js | 2 | ||||
-rw-r--r-- | tests/cases/legalizer_ta2.ll | 15 | ||||
-rw-r--r-- | tests/cases/legalizer_ta2.txt | 1 | ||||
-rw-r--r-- | tests/cases/unaligneddouble.ll | 24 | ||||
-rwxr-xr-x | tests/runner.py | 47 | ||||
-rw-r--r-- | tools/shared.py | 15 |
9 files changed, 164 insertions, 34 deletions
diff --git a/src/analyzer.js b/src/analyzer.js index e1f2f6c1..729d4607 100644 --- a/src/analyzer.js +++ b/src/analyzer.js @@ -169,6 +169,15 @@ function analyzer(data, sidePass) { item[slot] = { intertype: 'value', ident: tempIdent, type: item[slot].type }; return i+1; } + function removeAndAdd(lines, i, toAdd) { + var item = lines[i]; + var interp = getInterp(lines, i, toAdd.length); + for (var k = 0; k < toAdd.length; k++) { + toAdd[k].lineNum = item.lineNum + (k*interp); + } + Array.prototype.splice.apply(lines, [i, 1].concat(toAdd)); + return toAdd.length; + } // Assuming we will replace the item at line i, with num items, returns // the right factor to multiply line numbers by so that they fit in between // the removed line and the line after it @@ -184,16 +193,15 @@ function analyzer(data, sidePass) { if (item.intertype == 'store') { if (isIllegalType(item.valueType)) { dprint('legalizer', 'Legalizing store at line ' + item.lineNum); + var toAdd = []; bits = getBits(item.valueType); i = unfold(label.lines, i, item, 'value'); - var interp = getInterp(label.lines, i, Math.ceil(bits/32)); - label.lines.splice(i, 1); var elements; elements = getLegalVars(item.value.ident, bits); var j = 0; elements.forEach(function(element) { var tempVar = '$st$' + i + '$' + j; - label.lines.splice(i+j*2, 0, { + toAdd.push({ intertype: 'getelementptr', assignTo: tempVar, ident: item.pointer.ident, @@ -203,10 +211,9 @@ function analyzer(data, sidePass) { { intertype: 'value', ident: '0', type: 'i32' }, { intertype: 'value', ident: j.toString(), type: 'i32' } ], - lineNum: item.lineNum + (j*interp) }); var actualSizeType = 'i' + element.bits; // The last one may be smaller than 32 bits - label.lines.splice(i+j*2+1, 0, { + toAdd.push({ intertype: 'store', valueType: actualSizeType, value: { intertype: 'value', ident: element.ident, type: actualSizeType }, @@ -214,12 +221,11 @@ function analyzer(data, sidePass) { ident: tempVar, pointerType: actualSizeType + '*', align: item.align, - lineNum: item.lineNum + ((j+0.5)*interp) }); j++; }); Types.needAnalysis['[0 x i32]'] = 0; - i += j*2; + i += removeAndAdd(label.lines, i, toAdd); continue; } } else if (item.assignTo) { @@ -267,6 +273,38 @@ function analyzer(data, sidePass) { i += j*2; continue; } + break; + } + case 'phi': { + if (isIllegalType(value.type)) { + dprint('legalizer', 'Legalizing phi at line ' + item.lineNum); + bits = getBits(value.type); + var toAdd = []; + var elements = getLegalVars(item.assignTo, bits); + var j = 0; + elements.forEach(function(element) { + toAdd.push({ + intertype: 'phi', + assignTo: element.ident, + type: 'i' + element.bits, + params: value.params.map(function(param) { + return { + intertype: 'phiparam', + label: param.label, + value: { // TODO: unfolding + intertype: 'value', + ident: param.value.ident + '$' + j, + type: 'i' + element.bits, + } + }; + }) + }); + j++; + }); + i += removeAndAdd(label.lines, i, toAdd); + continue; + } + break; } case 'mathop': { if (isIllegalType(value.type)) { @@ -412,14 +450,10 @@ function analyzer(data, sidePass) { legalValue.assignTo = item.assignTo; toAdd.push(legalValue); } - var interp = getInterp(label.lines, i, toAdd.length); - for (var k = 0; k < toAdd.length; k++) { - toAdd[k].lineNum = item.lineNum + (k*interp); - } - Array.prototype.splice.apply(label.lines, [i, 1].concat(toAdd)); - i += toAdd.length; + i += removeAndAdd(label.lines, i, toAdd); continue; } + break; } } } diff --git a/src/parseTools.js b/src/parseTools.js index a5752e67..3cc17cc4 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -962,32 +962,32 @@ function makeSetValue(ptr, pos, value, type, noNeedFirst, ignore, align, noSafe, if (DOUBLE_MODE == 1 && USE_TYPED_ARRAYS == 2 && type == 'double') { return '(tempDoubleF64[0]=' + value + ',' + - makeSetValue(ptr, pos, 'tempDoubleI32[0]', 'i32', noNeedFirst, ignore, align) + ',' + - makeSetValue(ptr, getFastValue(pos, '+', Runtime.getNativeTypeSize('i32')), 'tempDoubleI32[1]', 'i32', noNeedFirst, ignore, align) + ')'; + makeSetValue(ptr, pos, 'tempDoubleI32[0]', 'i32', noNeedFirst, ignore, align, noSafe, ',') + ',' + + makeSetValue(ptr, getFastValue(pos, '+', Runtime.getNativeTypeSize('i32')), 'tempDoubleI32[1]', 'i32', noNeedFirst, ignore, align, noSafe, ',') + ')'; } - if (USE_TYPED_ARRAYS == 2 && align) { - // Alignment is important here. May need to split this up + var needSplitting = isIntImplemented(type) && !isPowerOfTwo(getBits(type)); // an unnatural type like i24 + if (USE_TYPED_ARRAYS == 2 && (align || needSplitting)) { + // Alignment is important here, or we need to split this up for other reasons. var bytes = Runtime.getNativeTypeSize(type); - if (bytes > align) { + if (bytes > align || needSplitting) { var ret = ''; if (isIntImplemented(type)) { if (bytes == 4 && align == 2) { // Special case that we can optimize ret += 'tempBigInt=' + value + sep; ret += makeSetValue(ptr, pos, 'tempBigInt&0xffff', 'i16', noNeedFirst, ignore, 2) + sep; - ret += makeSetValue(ptr, getFastValue(pos, '+', 2), 'tempBigInt>>16', 'i16', noNeedFirst, ignore, 2) + sep; - } else if (bytes <= 4) { + ret += makeSetValue(ptr, getFastValue(pos, '+', 2), 'tempBigInt>>16', 'i16', noNeedFirst, ignore, 2); + } else if (bytes != 8) { ret += 'tempBigInt=' + value + sep; for (var i = 0; i < bytes; i++) { - ret += makeSetValue(ptr, getFastValue(pos, '+', i), 'tempBigInt&0xff', 'i8', noNeedFirst, ignore, 1) + sep; - if (i < bytes-1) ret += 'tempBigInt>>=8' + sep; + ret += makeSetValue(ptr, getFastValue(pos, '+', i), 'tempBigInt&0xff', 'i8', noNeedFirst, ignore, 1); + if (i < bytes-1) ret += sep + 'tempBigInt>>=8' + sep; } - } else { - assert(bytes == 8); + } else { // bytes == 8, specific optimization ret += 'tempPair=' + ensureI64_1(value) + sep; ret += makeSetValue(ptr, pos, 'tempPair[0]', 'i32', noNeedFirst, ignore, align) + sep; - ret += makeSetValue(ptr, getFastValue(pos, '+', Runtime.getNativeTypeSize('i32')), 'tempPair[1]', 'i32', noNeedFirst, ignore, align) + sep; + ret += makeSetValue(ptr, getFastValue(pos, '+', Runtime.getNativeTypeSize('i32')), 'tempPair[1]', 'i32', noNeedFirst, ignore, align); } } else { ret += makeSetValue('tempDoublePtr', 0, value, type, noNeedFirst, ignore, 8) + sep; diff --git a/src/runtime.js b/src/runtime.js index 190260e6..b5663045 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -185,8 +185,14 @@ var Runtime = { "%float": 4, "%double": 8 }['%'+type]; // add '%' since float and double confuse Closure compiler as keys, and also spidermonkey as a compiler will remove 's from '_i8' etc - if (!size && type[type.length-1] == '*') { - size = Runtime.QUANTUM_SIZE; // A pointer + if (!size) { + if (type[type.length-1] == '*') { + size = Runtime.QUANTUM_SIZE; // A pointer + } else if (type[0] == 'i') { + var bits = parseInt(type.substr(1)); + assert(bits % 8 == 0); + size = bits/8; + } } return size; }, diff --git a/src/utility.js b/src/utility.js index 5ddccfd4..31eff100 100644 --- a/src/utility.js +++ b/src/utility.js @@ -21,7 +21,7 @@ function dump(item) { ret.push(i + ': [?]'); } } - return lineify(ret.join(', ')); + return ret.join(',\n'); } } diff --git a/tests/cases/legalizer_ta2.ll b/tests/cases/legalizer_ta2.ll index a877c683..67cd9feb 100644 --- a/tests/cases/legalizer_ta2.ll +++ b/tests/cases/legalizer_ta2.ll @@ -101,6 +101,21 @@ entry: store i80 %loaded.short, i80* bitcast ([300 x i8]* @globaliz to i80*), align 4 call i32 (i8*)* @puts(i8* bitcast ([300 x i8]* @globaliz to i8*)) +; phi + %if = trunc i104 %ander to i1 + %first = trunc i104 %xored to i88 + br i1 %if, label %a17, label %a26 + +a17: + %second = trunc i104 %loaded to i88 + br label %a26 + +a26: + %a27 = phi i88 [ %first, %entry ], [ %second, %a17 ] + store i104 0, i104* %bundled, align 4 ; wipe it out + store i88 %a27, i88* bitcast ([300 x i8]* @globaliz to i88*), align 4 + call i32 (i8*)* @puts(i8* bitcast ([300 x i8]* @globaliz to i8*)) + ret i32 1 } diff --git a/tests/cases/legalizer_ta2.txt b/tests/cases/legalizer_ta2.txt index e05a4816..e25076e6 100644 --- a/tests/cases/legalizer_ta2.txt +++ b/tests/cases/legalizer_ta2.txt @@ -15,3 +15,4 @@ hellon worod hello, war`d hello, wor-d hello, wor +hello, worl diff --git a/tests/cases/unaligneddouble.ll b/tests/cases/unaligneddouble.ll new file mode 100644 index 00000000..22b92741 --- /dev/null +++ b/tests/cases/unaligneddouble.ll @@ -0,0 +1,24 @@ +; ModuleID = 'tests/hello_world.bc' +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128" +target triple = "i386-pc-linux-gnu" + +@.str = private unnamed_addr constant [15 x i8] c"hello, world!\0A\00", align 1 ; [#uses=1 type=[15 x i8]*] + +; [#uses=0] +define i32 @main() { +entry: + %retval = alloca i32, align 4 ; [#uses=1 type=i32*] + %doub = alloca double, align 4 + store i32 0, i32* %retval + %0 = bitcast double* %doub to i32 + %1 = uitofp i32 %0 to double + store double %1, double* %doub, align 1 + store double %1, double* %doub, align 2 + store double %1, double* %doub, align 4 + store double %1, double* %doub, align 8 + %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0)) ; [#uses=0 type=i32] + ret i32 1 +} + +; [#uses=1] +declare i32 @printf(i8*, ...) diff --git a/tests/runner.py b/tests/runner.py index 0dde33c0..d220dca7 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -3743,7 +3743,7 @@ def process(filename): ''' self.do_run(src, "some string constant") - def test_istream(self): + def zzztest_istream(self): if self.emcc_args is None: return self.skip('requires libcxx') src = ''' @@ -5807,7 +5807,7 @@ elif 'benchmark' in str(sys.argv): Building.COMPILER_TEST_OPTS = [] TEST_REPS = 10 - TOTAL_TESTS = 8 + TOTAL_TESTS = 9 tests_done = 0 total_times = map(lambda x: 0., range(TOTAL_TESTS)) @@ -5940,6 +5940,49 @@ elif 'benchmark' in str(sys.argv): ''' self.do_benchmark(src, [], 'final: 720.') + def test_files(self): + src = r''' + #include<stdio.h> + #include<stdlib.h> + #include<assert.h> + #include <unistd.h> + + int main() { + int N = 100; + int M = 1000; + int K = 1000; + unsigned char *k = (unsigned char*)malloc(K+1), *k2 = (unsigned char*)malloc(K+1); + for (int i = 0; i < K; i++) { + k[i] = (i % 250) + 1; + } + k[K] = 0; + char buf[100]; + for (int i = 0; i < N; i++) { + sprintf(buf, "/dev/shm/file-%d.dat", i); + FILE *f = fopen(buf, "w"); + for (int j = 0; j < M; j++) { + fwrite(k, 1, (j % K) + 1, f); + } + fclose(f); + } + for (int i = 0; i < N; i++) { + sprintf(buf, "/dev/shm/file-%d.dat", i); + FILE *f = fopen(buf, "r"); + for (int j = 0; j < M; j++) { + fread(k2, 1, (j % K) + 1, f); + } + fclose(f); + for (int j = 0; j < K; j++) { + assert(k[j] == k2[j]); + } + unlink(buf); + } + printf("ok"); + return 1; + } + ''' + self.do_benchmark(src, [], 'ok') + def test_copy(self): src = r''' #include<stdio.h> diff --git a/tools/shared.py b/tools/shared.py index 45400581..7f633318 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -367,13 +367,17 @@ class Building: return env @staticmethod - def handle_CMake_toolchain(args): + def handle_CMake_toolchain(args, env): CMakeToolchain = '''# the name of the target operating system SET(CMAKE_SYSTEM_NAME Linux) # which C and C++ compiler to use SET(CMAKE_C_COMPILER $EMSCRIPTEN_ROOT/emcc) SET(CMAKE_CXX_COMPILER $EMSCRIPTEN_ROOT/em++) +SET(CMAKE_AR $EMSCRIPTEN_ROOT/emar) +SET(CMAKE_RANLIB $EMSCRIPTEN_ROOT/emranlib) +SET(CMAKE_C_FLAGS $CFLAGS) +SET(CMAKE_CXX_FLAGS $CXXFLAGS) # here is the target environment located SET(CMAKE_FIND_ROOT_PATH $EMSCRIPTEN_ROOT/system/include ) @@ -384,7 +388,10 @@ SET(CMAKE_FIND_ROOT_PATH $EMSCRIPTEN_ROOT/system/include ) set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH) -set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)'''.replace('$EMSCRIPTEN_ROOT', path_from_root('')) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' \ + .replace('$EMSCRIPTEN_ROOT', path_from_root('')) \ + .replace('$CFLAGS', env['CFLAGS']) \ + .replace('$CXXFLAGS', env['CFLAGS']) toolchainFile = mkstemp(suffix='.txt')[1] open(toolchainFile, 'w').write(CMakeToolchain) args.append('-DCMAKE_TOOLCHAIN_FILE=%s' % os.path.abspath(toolchainFile)) @@ -395,8 +402,8 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)'''.replace('$EMSCRIPTEN_ROOT', path_ if env is None: env = Building.get_building_env() env['EMMAKEN_JUST_CONFIGURE'] = '1' - if 'cmake' in sys.argv[0]: - args = Building.handle_CMake_toolchain(args) + if 'cmake' in args[0]: + args = Building.handle_CMake_toolchain(args, env) Popen(args, stdout=stdout, stderr=stderr, env=env).communicate()[0] del env['EMMAKEN_JUST_CONFIGURE'] |