From 6b98f6ca9264b7733fa44cbb7651ca60876157a8 Mon Sep 17 00:00:00 2001 From: Bruce Mitchener Date: Mon, 29 Apr 2013 18:20:35 +0700 Subject: [PATCH 01/34] This header is , not --- tests/799.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/799.cpp b/tests/799.cpp index 560321339a903..6c4c9b184584c 100644 --- a/tests/799.cpp +++ b/tests/799.cpp @@ -7,7 +7,7 @@ #include #ifdef EMSCRIPTEN -#include +#include #endif #define uint16 uint16_t From 82a55f49df01104ae405969f894e17771399bb01 Mon Sep 17 00:00:00 2001 From: Bruce Mitchener Date: Mon, 29 Apr 2013 21:35:26 +0700 Subject: [PATCH 02/34] Use va_copy (C99) instead of __va_copy (GNU ext). musl libc headers don't have __va_copy as it is a GNU extension and hasn't been needed for over a decade. --- tests/runner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/runner.py b/tests/runner.py index 4092d3de753cf..f925720c444c3 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -4016,7 +4016,7 @@ def test_varargs(self): // Try it with copying va_list tempva; - __va_copy(tempva, v); + va_copy(tempva, v); vsnprintf(d, 20, s, tempva); puts(d); From 868ae0d8e5bed99d6fe44ee4f9cf288ef065a787 Mon Sep 17 00:00:00 2001 From: Bruce Mitchener Date: Mon, 29 Apr 2013 21:58:42 +0700 Subject: [PATCH 03/34] Include to use int64_t. --- tests/runner.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/runner.py b/tests/runner.py index 4092d3de753cf..c7e1042dae4f0 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -5931,6 +5931,7 @@ def test_sscanf_3(self): # i64 if not Settings.USE_TYPED_ARRAYS == 2: return self.skip('64-bit sscanf only supported in ta2') src = r''' + #include #include int main(){ @@ -5990,6 +5991,7 @@ def test_sscanf_skip(self): if Settings.USE_TYPED_ARRAYS != 2: return self.skip("need ta2 for full i64") src = r''' + #include #include int main(){ From b1426dcfab43b6a4a06948f7adc971ac6bd0cb4a Mon Sep 17 00:00:00 2001 From: Bruce Mitchener Date: Mon, 29 Apr 2013 22:22:16 +0700 Subject: [PATCH 04/34] Use the standard int64_t rather than __int64_t. --- tests/runner.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/runner.py b/tests/runner.py index 4092d3de753cf..426d864a2ce5a 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -1133,10 +1133,11 @@ def test_i64_i16(self): if Settings.USE_TYPED_ARRAYS != 2: return self.skip('full i64 stuff only in ta2') src = r''' + #include #include int main(int argc, char ** argv){ int y=-133; - __int64_t x= ((__int64_t)((short)(y)))*(100 + argc); + int64_t x= ((int64_t)((short)(y)))*(100 + argc); if(x>0) printf(">0\n"); else From f06f3dc1282e7f79a7d86b93c96c31ad43259e9c Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 29 Apr 2013 11:00:23 -0700 Subject: [PATCH 05/34] update benchmarks --- tests/box2d/Benchmark.cpp | 11 +++-- tests/bullet/Demos/Benchmarks/main.cpp | 11 +++-- tests/life.c | 11 +++-- tests/runner.py | 66 ++++++++++++++------------ tests/skinning_test_no_simd.cpp | 11 +++-- tests/zlib/benchmark.c | 11 +++-- 6 files changed, 66 insertions(+), 55 deletions(-) diff --git a/tests/box2d/Benchmark.cpp b/tests/box2d/Benchmark.cpp index 566826748a5d9..6853a3dcc8be5 100644 --- a/tests/box2d/Benchmark.cpp +++ b/tests/box2d/Benchmark.cpp @@ -53,13 +53,14 @@ result_t measure(clock_t times[FRAMES]) { } int main(int argc, char **argv) { - int arg = argc > 1 ? argv[1][0] - '0' : 2; + int arg = argc > 1 ? argv[1][0] - '0' : 3; switch(arg) { case 0: return 0; break; - case 1: WARMUP = 32; FRAMES = 161; break; - case 2: WARMUP = 64; FRAMES = 333; break; - case 3: WARMUP = 5*64; FRAMES = 7*333; break; - case 4: WARMUP = 10*64; FRAMES = 17*333; break; + case 1: WARMUP = 5; FRAMES = 35; break; + case 2: WARMUP = 32; FRAMES = 161; break; + case 3: WARMUP = 64; FRAMES = 333; break; + case 4: WARMUP = 5*64; FRAMES = 7*333; break; + case 5: WARMUP = 10*64; FRAMES = 17*333; break; default: printf("error: %d\\n", arg); return -1; } diff --git a/tests/bullet/Demos/Benchmarks/main.cpp b/tests/bullet/Demos/Benchmarks/main.cpp index b050308ac3356..5526a31a6b835 100644 --- a/tests/bullet/Demos/Benchmarks/main.cpp +++ b/tests/bullet/Demos/Benchmarks/main.cpp @@ -32,13 +32,14 @@ extern bool gDisableDeactivation; int main(int argc, char **argv) { int NUM_TESTS; - int arg = argc > 1 ? argv[1][0] - '0' : 2; + int arg = argc > 1 ? argv[1][0] - '0' : 3; switch(arg) { case 0: return 0; break; - case 1: NUM_TESTS = 7; break; - case 2: NUM_TESTS = 33; break; - case 3: NUM_TESTS = 5*33; break; - case 4: NUM_TESTS = 7*35; break; + case 1: NUM_TESTS = 0; break; + case 2: NUM_TESTS = 7; break; + case 3: NUM_TESTS = 33; break; + case 4: NUM_TESTS = 5*33; break; + case 5: NUM_TESTS = 7*35; break; default: printf("error: %d\\n", arg); return -1; } diff --git a/tests/life.c b/tests/life.c index 74f0c108e3fad..4ce8d3850ff69 100644 --- a/tests/life.c +++ b/tests/life.c @@ -77,13 +77,14 @@ void game(int w, int h, int i) int main(int argc, char **argv) { int w, h, i; - int arg = argc > 1 ? argv[1][0] - '0' : 2; + int arg = argc > 1 ? argv[1][0] - '0' : 3; switch(arg) { case 0: return 0; break; - case 1: w = h = 32; i = 13000; break; - case 2: w = h = 32; i = 24000; break; - case 3: w = h = 32; i = 5*24000; break; - case 4: w = h = 32; i = 10*24000; break; + case 1: w = h = 32; i = 2500; break; + case 2: w = h = 32; i = 13000; break; + case 3: w = h = 32; i = 24000; break; + case 4: w = h = 32; i = 5*24000; break; + case 5: w = h = 32; i = 10*24000; break; default: printf("error: %d\\n", arg); return -1; } diff --git a/tests/runner.py b/tests/runner.py index 4092d3de753cf..418133a09b4fe 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -3441,7 +3441,7 @@ def test_life(self): [] [][][] [] -------------------------------- -''', ['1'], force_c=True) +''', ['2'], force_c=True) def test_array2(self): src = ''' @@ -12435,13 +12435,14 @@ def test_primes(self): #include #include int main(int argc, char **argv) { - int arg = argc > 1 ? argv[1][0] - '0' : 2; + int arg = argc > 1 ? argv[1][0] - '0' : 3; switch(arg) { case 0: return 0; break; - case 1: arg = 130000; break; - case 2: arg = 220000; break; - case 3: arg = 610000; break; - case 4: arg = 1010000; break; + case 1: arg = 33000; break; + case 2: arg = 130000; break; + case 3: arg = 220000; break; + case 4: arg = 610000; break; + case 5: arg = 1010000; break; default: printf("error: %d\\n", arg); return -1; } @@ -12472,13 +12473,14 @@ def test_memops(self): #include int main(int argc, char **argv) { int N, M; - int arg = argc > 1 ? argv[1][0] - '0' : 2; + int arg = argc > 1 ? argv[1][0] - '0' : 3; switch(arg) { case 0: return 0; break; - case 1: N = 1024*1024; M = 400; break; - case 2: N = 1024*1024; M = 800; break; - case 3: N = 1024*1024; M = 4000; break; - case 4: N = 1024*1024; M = 8000; break; + case 1: N = 1024*1024; M = 55; break; + case 2: N = 1024*1024; M = 400; break; + case 3: N = 1024*1024; M = 800; break; + case 4: N = 1024*1024; M = 4000; break; + case 5: N = 1024*1024; M = 8000; break; default: printf("error: %d\\n", arg); return -1; } @@ -12561,13 +12563,14 @@ def test_copy(self): int sum() { return x + y + z + r + g + b; } }; int main(int argc, char **argv) { - int arg = argc > 1 ? argv[1][0] - '0' : 2; + int arg = argc > 1 ? argv[1][0] - '0' : 3; switch(arg) { case 0: return 0; break; - case 1: arg = 625; break; - case 2: arg = 1250; break; - case 3: arg = 5*1250; break; - case 4: arg = 10*1250; break; + case 1: arg = 75; break; + case 2: arg = 625; break; + case 3: arg = 1250; break; + case 4: arg = 5*1250; break; + case 5: arg = 10*1250; break; default: printf("error: %d\\n", arg); return -1; } @@ -12598,13 +12601,14 @@ def test_fannkuch(self): 'int n = argc > 1 ? atoi(argv[1]) : 0;', ''' int n; - int arg = argc > 1 ? argv[1][0] - '0' : 2; + int arg = argc > 1 ? argv[1][0] - '0' : 3; switch(arg) { case 0: return 0; break; - case 1: n = 10; break; - case 2: n = 11; break; + case 1: n = 9; break; + case 2: n = 10; break; case 3: n = 11; break; - case 4: n = 12; break; + case 4: n = 11; break; + case 5: n = 12; break; default: printf("error: %d\\n", arg); return -1; } ''' @@ -12618,13 +12622,14 @@ def test_corrections(self): #include int main(int argc, char **argv) { int N, M; - int arg = argc > 1 ? argv[1][0] - '0' : 2; + int arg = argc > 1 ? argv[1][0] - '0' : 3; switch(arg) { case 0: return 0; break; - case 1: N = 20000; M = 3500; break; - case 2: N = 20000; M = 7000; break; - case 3: N = 20000; M = 5*7000; break; - case 4: N = 20000; M = 10*7000; break; + case 1: N = 20000; M = 550; break; + case 2: N = 20000; M = 3500; break; + case 3: N = 20000; M = 7000; break; + case 4: N = 20000; M = 5*7000; break; + case 5: N = 20000; M = 10*7000; break; default: printf("error: %d\\n", arg); return -1; } @@ -12648,13 +12653,14 @@ def fasta(self, double_rep): src = open(path_from_root('tests', 'fasta.cpp'), 'r').read().replace('double', double_rep) src = src.replace(' const size_t n = ( argc > 1 ) ? atoi( argv[1] ) : 512;', ''' int n; - int arg = argc > 1 ? argv[1][0] - '0' : 2; + int arg = argc > 1 ? argv[1][0] - '0' : 3; switch(arg) { case 0: return 0; break; - case 1: n = 19000000/2; break; - case 2: n = 19000000; break; - case 3: n = 19000000*5; break; - case 4: n = 19000000*10; break; + case 1: n = 19000000/20; break; + case 2: n = 19000000/2; break; + case 3: n = 19000000; break; + case 4: n = 19000000*5; break; + case 5: n = 19000000*10; break; default: printf("error: %d\\n", arg); return -1; } ''') diff --git a/tests/skinning_test_no_simd.cpp b/tests/skinning_test_no_simd.cpp index 9c99f093a9872..b94f8f766fcdd 100644 --- a/tests/skinning_test_no_simd.cpp +++ b/tests/skinning_test_no_simd.cpp @@ -172,13 +172,14 @@ void calculateVerticesAndNormals_x87( int main (int argc, char*argv[]) { int N, M; - int arg = argc > 1 ? argv[1][0] - '0' : 2; + int arg = argc > 1 ? argv[1][0] - '0' : 3; switch(arg) { case 0: return 0; break; - case 1: N = 6600; M = 6500; break; - case 2: N = 9500; M = 10000; break; - case 3: N = 2*11000; M = 2*12000; break; - case 4: N = 3*10000; M = 3*10800; break; + case 1: N = 2000; M = 1700; break; + case 2: N = 6600; M = 6500; break; + case 3: N = 9500; M = 10000; break; + case 4: N = 2*11000; M = 2*12000; break; + case 5: N = 3*10000; M = 3*10800; break; default: printf("error: %d\\n", arg); return -1; } diff --git a/tests/zlib/benchmark.c b/tests/zlib/benchmark.c index 5fe4a903295f8..f8f072acf8100 100644 --- a/tests/zlib/benchmark.c +++ b/tests/zlib/benchmark.c @@ -27,13 +27,14 @@ void __attribute__ ((noinline)) doit(char *buffer, int size, int i) { int main(int argc, char **argv) { int size, iters; - int arg = argc > 1 ? argv[1][0] - '0' : 2; + int arg = argc > 1 ? argv[1][0] - '0' : 3; switch(arg) { case 0: return 0; break; - case 1: size = 100000; iters = 250; break; - case 2: size = 100000; iters = 500; break; - case 3: size = 100000; iters = 5*500; break; - case 4: size = 100000; iters = 10*500; break; + case 1: size = 100000; iters = 60; break; + case 2: size = 100000; iters = 250; break; + case 3: size = 100000; iters = 500; break; + case 4: size = 100000; iters = 5*500; break; + case 5: size = 100000; iters = 10*500; break; default: printf("error: %d\\n", arg); return -1; } From ed34c86a0bf695726985d4d6dff9573fdba0eee3 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 29 Apr 2013 12:04:37 -0700 Subject: [PATCH 06/34] only show landingpad warnings in VERBOSE mode --- src/jsifier.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jsifier.js b/src/jsifier.js index 32c224b74acec..045328f8bd33c 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -1224,7 +1224,7 @@ function JSify(data, functionsOnly, givenFunctions) { if (DISABLE_EXCEPTION_CATCHING && USE_TYPED_ARRAYS == 2) { ret = makeVarDef(item.assignTo) + '$0 = 0; ' + item.assignTo + '$1 = 0;'; item.assignTo = null; - if (ASSERTIONS) warnOnce('landingpad, but exceptions are disabled!'); + if (VERBOSE) warnOnce('landingpad, but exceptions are disabled!'); return ret; } var catchTypeArray = item.catchables.map(finalizeLLVMParameter).map(function(element) { return asmCoercion(element, 'i32') }).join(','); From 3a108dc9cdbe270b23f1ce5ef32ce56ae864ce45 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 29 Apr 2013 12:12:32 -0700 Subject: [PATCH 07/34] ERROR_ON_UNRESOLVED_SYMBOLS option --- src/jsifier.js | 1 + src/settings.js | 3 +++ tests/runner.py | 18 +++++++++++++++++- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/jsifier.js b/src/jsifier.js index 045328f8bd33c..5fcf6b18739d1 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -487,6 +487,7 @@ function JSify(data, functionsOnly, givenFunctions) { } else { // If this is not linkable, anything not in the library is definitely missing if (!LINKABLE && !LibraryManager.library.hasOwnProperty(shortident) && !LibraryManager.library.hasOwnProperty(shortident + '__inline')) { + if (ERROR_ON_UNDEFINED_SYMBOLS) error('unresolved symbol: ' + shortident); if (VERBOSE || WARN_ON_UNDEFINED_SYMBOLS) printErr('warning: unresolved symbol: ' + shortident); LibraryManager.library[shortident] = new Function("Module['printErr']('missing function: " + shortident + "'); abort(-1);"); } diff --git a/src/settings.js b/src/settings.js index c878be92630d0..48b0347e0715f 100644 --- a/src/settings.js +++ b/src/settings.js @@ -317,6 +317,9 @@ var WARN_ON_UNDEFINED_SYMBOLS = 0; // If set to 1, we will warn on any undefined // the existing buildsystem), and (2) functions might be // implemented later on, say in --pre-js +var ERROR_ON_UNDEFINED_SYMBOLS = 0; // If set to 1, we will give a compile-time error on any + // undefined symbols (see WARN_ON_UNDEFINED_SYMBOLS). + var SMALL_XHR_CHUNKS = 0; // Use small chunk size for binary synchronous XHR's in Web Workers. // Used for testing. // See test_chunked_synchronous_xhr in runner.py and library.js. diff --git a/tests/runner.py b/tests/runner.py index 418133a09b4fe..008a73f005c45 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -10230,13 +10230,29 @@ def test_warn_undefined(self): } ''') + def clear(): try_delete('a.out.js') + for args in [[], ['-O2']]: - print args + clear() + print 'warn', args output = Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'main.cpp'), '-s', 'WARN_ON_UNDEFINED_SYMBOLS=1'] + args, stderr=PIPE).communicate() self.assertContained('unresolved symbol: something', output[1]) + clear() + output = Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'main.cpp')] + args, stderr=PIPE).communicate() + self.assertNotContained('unresolved symbol: something\n', output[1]) + + for args in [[], ['-O2']]: + clear() + print 'error', args + output = Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'main.cpp'), '-s', 'ERROR_ON_UNDEFINED_SYMBOLS=1'] + args, stderr=PIPE).communicate() + self.assertContained('unresolved symbol: something', output[1]) + assert not os.path.exists('a.out.js') + + clear() output = Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'main.cpp')] + args, stderr=PIPE).communicate() self.assertNotContained('unresolved symbol: something\n', output[1]) + assert os.path.exists('a.out.js') def test_toobig(self): open(os.path.join(self.get_dir(), 'main.cpp'), 'w').write(r''' From 049753ab9202598e4c1287f7b16cb55d46a795c2 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 20 Apr 2013 20:38:44 -0700 Subject: [PATCH 08/34] use le32-unknown-nacl triple --- tools/shared.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/shared.py b/tools/shared.py index 0dbae1d0e9038..16da1ea303d85 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -402,7 +402,7 @@ def clean_temp(): COMPILER_OPTS = COMPILER_OPTS + ['-m32', '-U__i386__', '-U__i386', '-Ui386', '-U__SSE__', '-U__SSE_MATH__', '-U__SSE2__', '-U__SSE2_MATH__', '-U__MMX__', '-DEMSCRIPTEN', '-D__EMSCRIPTEN__', '-U__STRICT_ANSI__', - '-target', 'i386-pc-linux-gnu', '-D__IEEE_LITTLE_ENDIAN', '-fno-math-errno'] + '-target', 'le32-unknown-nacl', '-D__IEEE_LITTLE_ENDIAN', '-fno-math-errno'] USE_EMSDK = not os.environ.get('EMMAKEN_NO_SDK') From d5afbea4576cae55facb921e2b88e56cc0ecbace Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 20 Apr 2013 20:50:19 -0700 Subject: [PATCH 09/34] align i64s and doubles to 64-bit boundaries --- src/runtime.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/runtime.js b/src/runtime.js index 5269301cede1e..d0c22c6fb567c 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -187,10 +187,10 @@ var Runtime = { var size, alignSize; if (Runtime.isNumberType(field) || Runtime.isPointerType(field)) { size = Runtime.getNativeTypeSize(field); // pack char; char; in structs, also char[X]s. - alignSize = size; + alignSize = size; // we align i64s and doubles on 64-bit boundaries, unlike x86 } else if (Runtime.isStructType(field)) { size = Types.types[field].flatSize; - alignSize = Types.types[field].alignSize; + alignSize = Math.min(Types.types[field].alignSize, Runtime.QUANTUM_SIZE); } else if (field[0] == 'b') { // bN, large number field, like a [N x i8] size = field.substr(1)|0; @@ -198,7 +198,7 @@ var Runtime = { } else { throw 'Unclear type in struct: ' + field + ', in ' + type.name_ + ' :: ' + dump(Types.types[type.name_]); } - alignSize = type.packed ? 1 : Math.min(alignSize, Runtime.QUANTUM_SIZE); + if (type.packed) alignSize = 1; type.alignSize = Math.max(type.alignSize, alignSize); var curr = Runtime.alignMemory(type.flatSize, alignSize); // if necessary, place this on aligned memory type.flatSize = curr + size; From 0fedeaa62d955ce57e6751a57e263122420671c1 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 20 Apr 2013 21:09:05 -0700 Subject: [PATCH 10/34] refactor struct detection of alignment size --- src/runtime.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/runtime.js b/src/runtime.js index d0c22c6fb567c..ec39636f92cc7 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -175,6 +175,13 @@ var Runtime = { set: set, + // type can be a native type or a struct (or null, for structs we only look at size here) + getAlignSize: function(type, size) { + // we align i64s and doubles on 64-bit boundaries, unlike x86 + if (type == 'i64' || type == 'double') return 8; + return Math.min(size, Runtime.QUANTUM_SIZE); + }, + // Calculate aligned size, just like C structs should be. TODO: Consider // requesting that compilation be done with #pragma pack(push) /n #pragma pack(1), // which would remove much of the complexity here. @@ -187,10 +194,10 @@ var Runtime = { var size, alignSize; if (Runtime.isNumberType(field) || Runtime.isPointerType(field)) { size = Runtime.getNativeTypeSize(field); // pack char; char; in structs, also char[X]s. - alignSize = size; // we align i64s and doubles on 64-bit boundaries, unlike x86 + alignSize = Runtime.getAlignSize(field, size); } else if (Runtime.isStructType(field)) { size = Types.types[field].flatSize; - alignSize = Math.min(Types.types[field].alignSize, Runtime.QUANTUM_SIZE); + alignSize = Runtime.getAlignSize(null, Types.types[field].alignSize); } else if (field[0] == 'b') { // bN, large number field, like a [N x i8] size = field.substr(1)|0; From 17248eb417685f37a94bc8857d3d6e513364cc9d Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 21 Apr 2013 08:36:33 -0700 Subject: [PATCH 11/34] add target settings --- emcc | 3 +++ src/runtime.js | 2 ++ src/settings.js | 3 +++ 3 files changed, 8 insertions(+) diff --git a/emcc b/emcc index 079f6edc14671..ed6e916f84e94 100755 --- a/emcc +++ b/emcc @@ -1032,6 +1032,9 @@ try: if minify_whitespace is None: minify_whitespace = opt_level >= 2 and not keep_js_debug + if shared.Settings.TARGET_X86: assert 'i386-pc-linux-gnu' in shared.COMPILER_OPTS + if shared.Settings.TARGET_LE32: assert 'le32-unknown-nacl' in shared.COMPILER_OPTS + ## Compile source code to bitcode if DEBUG: print >> sys.stderr, 'emcc: compiling to bitcode' diff --git a/src/runtime.js b/src/runtime.js index ec39636f92cc7..b184b27523274 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -178,7 +178,9 @@ var Runtime = { // type can be a native type or a struct (or null, for structs we only look at size here) getAlignSize: function(type, size) { // we align i64s and doubles on 64-bit boundaries, unlike x86 +#if TARGET_LE32 if (type == 'i64' || type == 'double') return 8; +#endif return Math.min(size, Runtime.QUANTUM_SIZE); }, diff --git a/src/settings.js b/src/settings.js index 48b0347e0715f..82cb411bd312e 100644 --- a/src/settings.js +++ b/src/settings.js @@ -17,6 +17,9 @@ var QUANTUM_SIZE = 4; // This is the size of an individual field in a structure. // // Changing this from the default of 4 is deprecated. +var TARGET_X86 = 0; // For le32-unknown-nacl +var TARGET_LE32 = 1; // For i386-pc-linux-gnu + var CORRECT_SIGNS = 1; // Whether we make sure to convert unsigned values to signed values. // Decreases performance with additional runtime checks. Might not be // needed in some kinds of code. From ec9707170f4e6c8f016c2e2ea27a53abf1326410 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 21 Apr 2013 09:01:12 -0700 Subject: [PATCH 12/34] work towards le32 varargs --- src/intertyper.js | 12 ++++++++++++ src/jsifier.js | 3 +++ src/library.js | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/src/intertyper.js b/src/intertyper.js index 57e3011d04149..445c37f48d864 100644 --- a/src/intertyper.js +++ b/src/intertyper.js @@ -336,6 +336,8 @@ function intertyper(data, sidePass, baseLineNums) { return 'InsertValue'; if (tokensLength >= 3 && token0Text == 'phi') return 'Phi'; + if (tokensLength >= 3 && token0Text == 'va_arg') + return 'va_arg'; if (tokensLength >= 3 && token0Text == 'landingpad') return 'Landingpad'; if (token0Text == 'fence') @@ -817,6 +819,16 @@ function intertyper(data, sidePass, baseLineNums) { this.forwardItem(item, 'Reintegrator'); } }); + // 'phi' + substrate.addActor('va_arg', { + processItem: function(item) { + item.intertype = 'va_arg'; + var segments = splitTokenList(item.tokens.slice(1)); + item.type = segments[1][0].text; + item.value = parseLLVMSegment(segments[0]); + this.forwardItem(item, 'Reintegrator'); + } + }); // mathops substrate.addActor('Mathops', { processItem: function(item) { diff --git a/src/jsifier.js b/src/jsifier.js index 5fcf6b18739d1..a2ed7f923fbbc 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -1295,6 +1295,9 @@ function JSify(data, functionsOnly, givenFunctions) { return RuntimeGenerator.stackAlloc(getFastValue(calcAllocatedSize(item.allocatedType), '*', item.allocatedNum)); } }); + makeFuncLineActor('va_arg', function(item) { + return makeGetValue(item.value.ident, 0, item.type); + }); makeFuncLineActor('mathop', processMathop); diff --git a/src/library.js b/src/library.js index 9b63084f8371d..c62b6a05c50ea 100644 --- a/src/library.js +++ b/src/library.js @@ -3612,6 +3612,8 @@ LibraryManager.library = { asprintf: function(s, format, varargs) { return _sprintf(-s, format, varargs); }, + +#if TARGET_X86 vfprintf: 'fprintf', vsnprintf: 'snprintf', vprintf: 'printf', @@ -3620,6 +3622,44 @@ LibraryManager.library = { vscanf: 'scanf', vfscanf: 'fscanf', vsscanf: 'sscanf', +#endif + +#if TARGET_LE32 + vfprintf__deps: ['fprintf'], + vfprintf: function(s, f, varargs) { + return _fprintf(s, f, {{{ makeGetValue('varargs', 0, '*') }}}); + }, + vsnprintf__deps: ['snprintf'], + vsnprintf: function(s, n, format, varargs) { + return _snprintf(s, n, format, {{{ makeGetValue('varargs', 0, '*') }}}); + }, + vprintf__deps: ['printf'], + vprintf: function(format, varargs) { + return _printf(format, {{{ makeGetValue('varargs', 0, '*') }}}); + }, + vsprintf__deps: ['sprintf'], + vsprintf: function(s, format, varargs) { + return _sprintf(s, format, {{{ makeGetValue('varargs', 0, '*') }}}); + }, + vasprintf__deps: ['asprintf'], + vasprintf: function(s, format, varargs) { + return _asprintf(s, format, {{{ makeGetValue('varargs', 0, '*') }}}); + }, + vscanf__deps: ['scanf'], + vscanf: function(format, varargs) { + return _scanf(format, {{{ makeGetValue('varargs', 0, '*') }}}); + }, + vfscanf__deps: ['fscanf'], + vfscanf: function(s, format, varargs) { + return _fscanf(s, format, {{{ makeGetValue('varargs', 0, '*') }}}); + }, + vsscanf__deps: ['sscanf'], + vsscanf: function(s, format, varargs) { + return _sscanf(s, format, {{{ makeGetValue('varargs', 0, '*') }}}); + }, + // TODO: others +#endif + fopen64: 'fopen', __01fopen64_: 'fopen', __01freopen64_: 'freopen', From c2816fad68242e8e85a731d32527115673fb9422 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 21 Apr 2013 10:17:52 -0700 Subject: [PATCH 13/34] implement le32 varargs as a struct with two fields: a start and an offset --- src/jsifier.js | 7 ++++++- src/library.js | 6 ++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/jsifier.js b/src/jsifier.js index a2ed7f923fbbc..acb0332b548d1 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -1296,7 +1296,12 @@ function JSify(data, functionsOnly, givenFunctions) { } }); makeFuncLineActor('va_arg', function(item) { - return makeGetValue(item.value.ident, 0, item.type); + assert(TARGET_LE32); + var ident = item.value.ident; + var move = Runtime.getNativeTypeSize(item.type); + return '(tempInt=' + makeGetValue(ident, 4, '*') + ',' + + makeSetValue(ident, 4, 'tempInt + ' + move, '*') + ',' + + makeGetValue(makeGetValue(ident, 0, '*'), 'tempInt', item.type) + ')'; }); makeFuncLineActor('mathop', processMathop); diff --git a/src/library.js b/src/library.js index c62b6a05c50ea..1686fc70bbb55 100644 --- a/src/library.js +++ b/src/library.js @@ -4865,7 +4865,13 @@ LibraryManager.library = { llvm_va_start__inline: function(ptr) { // varargs - we received a pointer to the varargs as a final 'extra' parameter called 'varrp' +#if TARGET_X86 return makeSetValue(ptr, 0, 'varrp', 'void*'); +#endif +#if TARGET_LE32 + // 4-word structure: start, current offset + return makeSetValue(ptr, 0, 'varrp', 'void*') + ';' + makeSetValue(ptr, 4, 0, 'void*'); +#endif }, llvm_va_end: function() {}, From e3c27642a8431328dc2a823ae1ee96e80a9baae7 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 21 Apr 2013 10:57:24 -0700 Subject: [PATCH 14/34] update test_pystruct --- tests/runner.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/runner.py b/tests/runner.py index 92395e2532ead..e705dadafaa9d 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -3650,7 +3650,12 @@ def test_pystruct(self): # Compressed memory. Note that sizeof() does give the fat sizes, however! self.do_run(src, '*0,0,0,1,2,3,4,5*\n*1,0,0*\n*0*\n0:1,1\n1:1,1\n2:1,1\n*12,20,5*') else: - self.do_run(src, '*0,0,0,4,8,12,16,20*\n*1,0,0*\n*0*\n0:1,1\n1:1,1\n2:1,1\n*12,20,20*') + if 'le32-unknown-nacl' in COMPILER_OPTS: + self.do_run(src, '*0,0,0,4,8,16,20,24*\n*1,0,0*\n*0*\n0:1,1\n1:1,1\n2:1,1\n*16,24,24*') + elif 'i386-pc-linux-gnu' in COMPILER_OPTS: + self.do_run(src, '*0,0,0,4,8,12,16,20*\n*1,0,0*\n*0*\n0:1,1\n1:1,1\n2:1,1\n*12,20,20*') + else: + raise Exception('unknown arch') def test_ptrtoint(self): if self.emcc_args is None: return self.skip('requires emcc') From 47f1437453100dc2eb44cc7fa9222fc01e1175ef Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 21 Apr 2013 11:01:21 -0700 Subject: [PATCH 15/34] update test_unaligned --- tests/runner.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/runner.py b/tests/runner.py index e705dadafaa9d..cdd8f35087a66 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -1500,7 +1500,13 @@ def test_unaligned(self): ''' # TODO: A version of this with int64s as well - self.do_run(src, '*12 : 1 : 12\n328157500735811.0,23,416012775903557.0,99\n') + + if 'le32-unknown-nacl' in COMPILER_OPTS: + self.do_run(src, '*16 : 0 : 16\n328157500735811.0,23,416012775903557.0,99\n') + elif 'i386-pc-linux-gnu' in COMPILER_OPTS: + self.do_run(src, '*12 : 1 : 12\n328157500735811.0,23,416012775903557.0,99\n') + else: + raise Exception('unknown arch') return # TODO: continue to the next part here From f3ef63bc4a28aef0f338084c6a4e4a5955dd86e5 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 21 Apr 2013 11:04:47 -0700 Subject: [PATCH 16/34] update test_varargs_byval --- tests/runner.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/runner.py b/tests/runner.py index cdd8f35087a66..a315ef29ddb76 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -4084,6 +4084,7 @@ def test_varargs(self): def test_varargs_byval(self): if Settings.USE_TYPED_ARRAYS != 2: return self.skip('FIXME: Add support for this') + if 'le32-unknown-nacl' in COMPILER_OPTS: return self.skip('clang cannot compile this code with that target yet') src = r''' #include From 9270ab0773b8fedb0bb8c1d124aad75ae8aec10e Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 21 Apr 2013 11:07:34 -0700 Subject: [PATCH 17/34] update test_python --- tests/runner.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/runner.py b/tests/runner.py index a315ef29ddb76..1e6a663e63588 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -7923,6 +7923,7 @@ def clean(text): def test_python(self): if self.emcc_args is None: return self.skip('requires emcc') if Settings.QUANTUM_SIZE == 1: return self.skip('TODO: make this work') + if 'le32-unknown-nacl' in COMPILER_OPTS: return self.skip('cannot use our existing bitcode file which is of a different target') # Overflows in string_hash Settings.CORRECT_OVERFLOWS = 1 From 741365c7892957ef446b2da242cf509102273c66 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 21 Apr 2013 16:15:43 -0700 Subject: [PATCH 18/34] update test_structbyval --- tests/runner.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/runner.py b/tests/runner.py index 1e6a663e63588..e51f5c6bb2e7f 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -4259,7 +4259,10 @@ def test_structbyval(self): output = Popen([PYTHON, EMCC, all_name], stderr=PIPE).communicate() # Check for warning in the generated code generated = open(os.path.join(self.get_dir(), 'src.cpp.o.js')).read() - assert 'Casting a function pointer type to another with a different number of arguments' in output[1], 'Missing expected warning' + if 'i386-pc-linux-gnu' in COMPILER_OPTS: + assert 'Casting a function pointer type to another with a different number of arguments' in output[1], 'Missing expected warning' + else: + print >> sys.stderr, 'skipping C/C++ conventions warning check, since not i386-pc-linux-gnu' def test_stdlibs(self): if self.emcc_args is None: return self.skip('requires emcc') From 685eafedefa6f856037c9646ac200f5e22186f66 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 21 Apr 2013 16:44:03 -0700 Subject: [PATCH 19/34] legalize va_arg on i64/i32* --- src/analyzer.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/analyzer.js b/src/analyzer.js index 7fbdf24dea7f1..31422201a771f 100644 --- a/src/analyzer.js +++ b/src/analyzer.js @@ -469,6 +469,23 @@ function analyzer(data, sidePass) { i++; continue; // special case, handled in makeComparison } + case 'va_arg': { + assert(value.type == 'i64'); + assert(value.value.type == 'i32*', value.value.type); + i += removeAndAdd(label.lines, i, range(2).map(function(x) { + return { + intertype: 'va_arg', + assignTo: value.assignTo + '$' + x, + type: 'i32', + value: { + intertype: 'value', + ident: value.value.ident, // We read twice from the same i32* var, incrementing // + '$' + x, + type: 'i32*' + } + }; + })); + continue; + } 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 From 3b0fde942abc569ba4dfaefef127325b3bf9441b Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 21 Apr 2013 17:04:32 -0700 Subject: [PATCH 20/34] clarify what we do in le32 v*printf etc. functions --- src/library.js | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/src/library.js b/src/library.js index 1686fc70bbb55..067458fec2c45 100644 --- a/src/library.js +++ b/src/library.js @@ -3614,6 +3614,7 @@ LibraryManager.library = { }, #if TARGET_X86 + // va_arg is just like our varargs vfprintf: 'fprintf', vsnprintf: 'snprintf', vprintf: 'printf', @@ -3625,39 +3626,39 @@ LibraryManager.library = { #endif #if TARGET_LE32 + // convert va_arg into varargs vfprintf__deps: ['fprintf'], - vfprintf: function(s, f, varargs) { - return _fprintf(s, f, {{{ makeGetValue('varargs', 0, '*') }}}); + vfprintf: function(s, f, va_arg) { + return _fprintf(s, f, {{{ makeGetValue('va_arg', 0, '*') }}}); }, vsnprintf__deps: ['snprintf'], - vsnprintf: function(s, n, format, varargs) { - return _snprintf(s, n, format, {{{ makeGetValue('varargs', 0, '*') }}}); + vsnprintf: function(s, n, format, va_arg) { + return _snprintf(s, n, format, {{{ makeGetValue('va_arg', 0, '*') }}}); }, vprintf__deps: ['printf'], - vprintf: function(format, varargs) { - return _printf(format, {{{ makeGetValue('varargs', 0, '*') }}}); + vprintf: function(format, va_arg) { + return _printf(format, {{{ makeGetValue('va_arg', 0, '*') }}}); }, vsprintf__deps: ['sprintf'], - vsprintf: function(s, format, varargs) { - return _sprintf(s, format, {{{ makeGetValue('varargs', 0, '*') }}}); + vsprintf: function(s, format, va_arg) { + return _sprintf(s, format, {{{ makeGetValue('va_arg', 0, '*') }}}); }, vasprintf__deps: ['asprintf'], - vasprintf: function(s, format, varargs) { - return _asprintf(s, format, {{{ makeGetValue('varargs', 0, '*') }}}); + vasprintf: function(s, format, va_arg) { + return _asprintf(s, format, {{{ makeGetValue('va_arg', 0, '*') }}}); }, vscanf__deps: ['scanf'], - vscanf: function(format, varargs) { - return _scanf(format, {{{ makeGetValue('varargs', 0, '*') }}}); + vscanf: function(format, va_arg) { + return _scanf(format, {{{ makeGetValue('va_arg', 0, '*') }}}); }, vfscanf__deps: ['fscanf'], - vfscanf: function(s, format, varargs) { - return _fscanf(s, format, {{{ makeGetValue('varargs', 0, '*') }}}); + vfscanf: function(s, format, va_arg) { + return _fscanf(s, format, {{{ makeGetValue('va_arg', 0, '*') }}}); }, vsscanf__deps: ['sscanf'], - vsscanf: function(s, format, varargs) { - return _sscanf(s, format, {{{ makeGetValue('varargs', 0, '*') }}}); + vsscanf: function(s, format, va_arg) { + return _sscanf(s, format, {{{ makeGetValue('va_arg', 0, '*') }}}); }, - // TODO: others #endif fopen64: 'fopen', From df08074e4c2f8a1d9c581cf03486664d274e393d Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 21 Apr 2013 19:54:51 -0700 Subject: [PATCH 21/34] enable benchmark.test_fasta_double to test handling of doubles --- tests/runner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/runner.py b/tests/runner.py index e51f5c6bb2e7f..b00f10eca3b3b 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -12705,7 +12705,7 @@ def fasta(self, double_rep): def test_fasta_float(self): self.fasta('float') - def zzztest_fasta_double(self): + def test_fasta_double(self): self.fasta('double') def test_skinning(self): From 91db790951e4fffea68c632da176b4a8c139698c Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 21 Apr 2013 20:02:33 -0700 Subject: [PATCH 22/34] add benchmark.test_fasta_double_full, with DOUBLE_MODE=1 --- tests/runner.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/runner.py b/tests/runner.py index b00f10eca3b3b..1309548fca247 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -12684,7 +12684,7 @@ def test_corrections(self): ''' self.do_benchmark('corrections', src, [], 'final: 40006013:10225.', emcc_args=['-s', 'CORRECT_SIGNS=1', '-s', 'CORRECT_OVERFLOWS=1', '-s', 'CORRECT_ROUNDINGS=1']) - def fasta(self, double_rep): + def fasta(self, double_rep, emcc_args=[]): src = open(path_from_root('tests', 'fasta.cpp'), 'r').read().replace('double', double_rep) src = src.replace(' const size_t n = ( argc > 1 ) ? atoi( argv[1] ) : 512;', ''' int n; @@ -12708,6 +12708,9 @@ def test_fasta_float(self): def test_fasta_double(self): self.fasta('double') + def test_fasta_double_full(self): + self.fasta('double', emcc_args=['-s', 'DOUBLE_MODE=1']) + def test_skinning(self): src = open(path_from_root('tests', 'skinning_test_no_simd.cpp'), 'r').read() self.do_benchmark('skinning', src, [], 'blah=0.000000') From 9b8e4488d77bffe68c3d7fd0df5f5f807331a3d6 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 21 Apr 2013 20:09:52 -0700 Subject: [PATCH 23/34] use fasta names --- tests/runner.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/runner.py b/tests/runner.py index 1309548fca247..baa95127240cc 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -12684,7 +12684,7 @@ def test_corrections(self): ''' self.do_benchmark('corrections', src, [], 'final: 40006013:10225.', emcc_args=['-s', 'CORRECT_SIGNS=1', '-s', 'CORRECT_OVERFLOWS=1', '-s', 'CORRECT_ROUNDINGS=1']) - def fasta(self, double_rep, emcc_args=[]): + def fasta(self, name, double_rep, emcc_args=[]): src = open(path_from_root('tests', 'fasta.cpp'), 'r').read().replace('double', double_rep) src = src.replace(' const size_t n = ( argc > 1 ) ? atoi( argv[1] ) : 512;', ''' int n; @@ -12703,13 +12703,13 @@ def fasta(self, double_rep, emcc_args=[]): self.do_benchmark('fasta', src, [], '''GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGA\nTCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACT\nAAAAATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAG\nGCTGAGGCAGGAGAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCG\nCCACTGCACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAAGGCCGGGCGCGGT\nGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGATCACCTGAGGTCA\nGGAGTTCGAGACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAATACAAAAA\nTTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCAGCTACTCGGGAGGCTGAGGCAGGAG\nAATCGCTTGAACCCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCCA\nGCCTGGGCGA''') def test_fasta_float(self): - self.fasta('float') + self.fasta('fasta_float', 'float') def test_fasta_double(self): - self.fasta('double') + self.fasta('fasta_double', 'double') def test_fasta_double_full(self): - self.fasta('double', emcc_args=['-s', 'DOUBLE_MODE=1']) + self.fasta('fasta_double_full', 'double', emcc_args=['-s', 'DOUBLE_MODE=1']) def test_skinning(self): src = open(path_from_root('tests', 'skinning_test_no_simd.cpp'), 'r').read() From f2338f77c9bc16a8565243b242217ad95c23e375 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 21 Apr 2013 20:17:10 -0700 Subject: [PATCH 24/34] do not hope for 64-bit alignment with doubles in DOUBLE_MODE 0 since we will read only 32 bits anyhow --- src/parseTools.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/parseTools.js b/src/parseTools.js index 77ab979de92f3..192b58ef288cd 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -1130,6 +1130,7 @@ function makeGetValue(ptr, pos, type, noNeedFirst, unsigned, ignore, align, noSa if (USE_TYPED_ARRAYS == 2 && align) { // Alignment is important here. May need to split this up var bytes = Runtime.getNativeTypeSize(type); + if (DOUBLE_MODE == 0 && type == 'double') bytes = 4; // we will really only read 4 bytes here if (bytes > align) { var ret = '('; if (isIntImplemented(type)) { From fec03aca6d36b9df1d721744af9635155c88c294 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 21 Apr 2013 21:03:53 -0700 Subject: [PATCH 25/34] read/write 64-bit aligned doubles directly in le32, when aligned properly --- src/parseTools.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/parseTools.js b/src/parseTools.js index 192b58ef288cd..35ad014d0b3d8 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -1020,7 +1020,9 @@ function getHeapOffset(offset, type, forceAsm) { } if (Runtime.getNativeFieldSize(type) > 4) { - type = 'i32'; // XXX we emulate 64-bit values as 32 + if (type == 'i64' || TARGET_X86) { + type = 'i32'; // XXX we emulate 64-bit values as 32 in x86, and also in le32 but only i64, not double + } } var sz = Runtime.getNativeTypeSize(type); @@ -1121,7 +1123,7 @@ function makeGetValue(ptr, pos, type, noNeedFirst, unsigned, ignore, align, noSa return '{ ' + ret.join(', ') + ' }'; } - if (DOUBLE_MODE == 1 && USE_TYPED_ARRAYS == 2 && type == 'double') { + if (DOUBLE_MODE == 1 && USE_TYPED_ARRAYS == 2 && type == 'double' && TARGET_X86) { return '(' + makeSetTempDouble(0, 'i32', makeGetValue(ptr, pos, 'i32', noNeedFirst, unsigned, ignore, align)) + ',' + makeSetTempDouble(1, 'i32', makeGetValue(ptr, getFastValue(pos, '+', Runtime.getNativeTypeSize('i32')), 'i32', noNeedFirst, unsigned, ignore, align)) + ',' + makeGetTempDouble(0, 'double') + ')'; @@ -1638,7 +1640,11 @@ function makeGetSlabs(ptr, type, allowMultiple, unsigned) { case 'i1': case 'i8': return [unsigned ? 'HEAPU8' : 'HEAP8']; break; case 'i16': return [unsigned ? 'HEAPU16' : 'HEAP16']; break; case 'i32': case 'i64': return [unsigned ? 'HEAPU32' : 'HEAP32']; break; - case 'float': case 'double': return ['HEAPF32']; break; + case 'double': { + if (TARGET_LE32) return ['HEAPF64']; // in le32, we do have the ability to assume 64-bit alignment + // otherwise, fall through to float + } + case 'float': return ['HEAPF32']; default: { throw 'what, exactly, can we do for unknown types in TA2?! ' + new Error().stack; } From 6c137888aa150fe7ca292b969e4ffb6489230ac9 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 22 Apr 2013 09:17:49 -0700 Subject: [PATCH 26/34] tweak handling of unaligned doubles a little --- src/parseTools.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/parseTools.js b/src/parseTools.js index 35ad014d0b3d8..f46381cbfab6d 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -1123,7 +1123,9 @@ function makeGetValue(ptr, pos, type, noNeedFirst, unsigned, ignore, align, noSa return '{ ' + ret.join(', ') + ' }'; } - if (DOUBLE_MODE == 1 && USE_TYPED_ARRAYS == 2 && type == 'double' && TARGET_X86) { + // In double mode 1, in x86 we always assume unaligned because we can't trust that; otherwise in le32 + // we need this code path if we are not fully aligned. + if (DOUBLE_MODE == 1 && USE_TYPED_ARRAYS == 2 && type == 'double' && (TARGET_X86 || align < 8)) { return '(' + makeSetTempDouble(0, 'i32', makeGetValue(ptr, pos, 'i32', noNeedFirst, unsigned, ignore, align)) + ',' + makeSetTempDouble(1, 'i32', makeGetValue(ptr, getFastValue(pos, '+', Runtime.getNativeTypeSize('i32')), 'i32', noNeedFirst, unsigned, ignore, align)) + ',' + makeGetTempDouble(0, 'double') + ')'; @@ -1140,7 +1142,7 @@ function makeGetValue(ptr, pos, type, noNeedFirst, unsigned, ignore, align, noSa // Special case that we can optimize ret += makeGetValue(ptr, pos, 'i16', noNeedFirst, 2, ignore) + '|' + '(' + makeGetValue(ptr, getFastValue(pos, '+', 2), 'i16', noNeedFirst, 2, ignore) + '<<16)'; - } else { // XXX we cannot truly handle > 4... + } else { // XXX we cannot truly handle > 4... (in x86) ret = ''; for (var i = 0; i < bytes; i++) { ret += '(' + makeGetValue(ptr, getFastValue(pos, '+', i), 'i8', noNeedFirst, 1, ignore) + (i > 0 ? '<<' + (8*i) : '') + ')'; From c812fd650031ffbaae1ef272d1c50ce457ab0bff Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 22 Apr 2013 10:26:39 -0700 Subject: [PATCH 27/34] todo --- src/parseTools.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/parseTools.js b/src/parseTools.js index f46381cbfab6d..6b6196f0efd5c 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -1231,6 +1231,7 @@ function makeSetValue(ptr, pos, value, type, noNeedFirst, ignore, align, noSafe, return ret.join('; '); } + // TODO: optimize like get for le32 if (DOUBLE_MODE == 1 && USE_TYPED_ARRAYS == 2 && type == 'double') { return '(' + makeSetTempDouble(0, 'double', value) + ',' + makeSetValue(ptr, pos, makeGetTempDouble(0, 'i32'), 'i32', noNeedFirst, ignore, align, noSafe, ',') + ',' + From e997f18e445e5d1b323ef6ef830e8b38a96c42b2 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 22 Apr 2013 10:27:28 -0700 Subject: [PATCH 28/34] add heap alignment checks to asm1 --- tests/runner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/runner.py b/tests/runner.py index baa95127240cc..d96e68034710d 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -9236,7 +9236,7 @@ def setUp(self): exec('o2 = make_run("o2", compiler=CLANG, emcc_args=["-O2", "-s", "ASM_JS=0", "-s", "JS_CHUNK_SIZE=1024"])') # asm.js - exec('asm1 = make_run("asm1", compiler=CLANG, emcc_args=["-O1"])') + exec('asm1 = make_run("asm1", compiler=CLANG, emcc_args=["-O1", "-s", "CHECK_HEAP_ALIGN=1"])') exec('asm2 = make_run("asm2", compiler=CLANG, emcc_args=["-O2"])') exec('asm2g = make_run("asm2g", compiler=CLANG, emcc_args=["-O2", "-g", "-s", "ASSERTIONS=1", "--memory-init-file", "1"])') From b020ec673028c47fa16e32f46a7c3e5c1dbe3905 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 22 Apr 2013 10:34:35 -0700 Subject: [PATCH 29/34] allow size to be null in getAlignSize, for native types --- src/runtime.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime.js b/src/runtime.js index b184b27523274..b15f4152e30c6 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -181,7 +181,7 @@ var Runtime = { #if TARGET_LE32 if (type == 'i64' || type == 'double') return 8; #endif - return Math.min(size, Runtime.QUANTUM_SIZE); + return Math.min(size || Runtime.getNativeFieldSize(type), Runtime.QUANTUM_SIZE); }, // Calculate aligned size, just like C structs should be. TODO: Consider From ef67463a0d300d6bb5899632fc96e18726351613 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 22 Apr 2013 10:52:52 -0700 Subject: [PATCH 30/34] align the stack to 64 bits in le32 --- src/analyzer.js | 2 +- src/jsifier.js | 5 ++--- src/library.js | 8 ++++---- src/modules.js | 2 ++ src/runtime.js | 17 +++++++++-------- 5 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/analyzer.js b/src/analyzer.js index 31422201a771f..03d44cb7ad9b5 100644 --- a/src/analyzer.js +++ b/src/analyzer.js @@ -1509,7 +1509,7 @@ function analyzer(data, sidePass) { calcAllocatedSize(item.allocatedType)*item.allocatedNum: 0; if (USE_TYPED_ARRAYS === 2) { // We need to keep the stack aligned - item.allocatedSize = Runtime.forceAlign(item.allocatedSize, QUANTUM_SIZE); + item.allocatedSize = Runtime.forceAlign(item.allocatedSize, Runtime.STACK_ALIGN); } } var index = 0; diff --git a/src/jsifier.js b/src/jsifier.js index acb0332b548d1..2715ae3e1ef22 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -1403,11 +1403,10 @@ function JSify(data, functionsOnly, givenFunctions) { ret = makeSetValue(getFastValue('tempInt', '+', offset), 0, arg, type, null, null, QUANTUM_SIZE, null, ','); offset += Runtime.getNativeFieldSize(type); } else { - assert(offset % 4 == 0); // varargs must be aligned + assert(offset % Runtime.STACK_ALIGN == 0); // varargs must be aligned var size = calcAllocatedSize(removeAllPointing(type)); - assert(size % 4 == 0); // varargs must stay aligned ret = makeCopyValues(getFastValue('tempInt', '+', offset), arg, size, null, null, varargsByVals[i], ','); - offset += size; + offset += Runtime.forceAlign(size, Runtime.STACK_ALIGN); } return ret; }).filter(function(arg) { diff --git a/src/library.js b/src/library.js index 067458fec2c45..f9ff18ecc3a7a 100644 --- a/src/library.js +++ b/src/library.js @@ -2499,7 +2499,7 @@ LibraryManager.library = { for (var formatIndex = 0; formatIndex < format.length;) { if (format[formatIndex] === '%' && format[formatIndex+1] == 'n') { var argPtr = {{{ makeGetValue('varargs', 'argIndex', 'void*') }}}; - argIndex += Runtime.getNativeFieldSize('void*'); + argIndex += Runtime.getAlignSize('void*'); {{{ makeSetValue('argPtr', 0, 'soFar', 'i32') }}}; formatIndex += 2; continue; @@ -2508,7 +2508,7 @@ LibraryManager.library = { // TODO: Support strings like "%5c" etc. if (format[formatIndex] === '%' && format[formatIndex+1] == 'c') { var argPtr = {{{ makeGetValue('varargs', 'argIndex', 'void*') }}}; - argIndex += Runtime.getNativeFieldSize('void*'); + argIndex += Runtime.getAlignSize('void*'); fields++; next = get(); {{{ makeSetValue('argPtr', 0, 'next', 'i8') }}} @@ -2600,7 +2600,7 @@ LibraryManager.library = { var text = buffer.join(''); var argPtr = {{{ makeGetValue('varargs', 'argIndex', 'void*') }}}; - argIndex += Runtime.getNativeFieldSize('void*'); + argIndex += Runtime.getAlignSize('void*'); switch (type) { case 'd': case 'u': case 'i': if (half) { @@ -2679,7 +2679,7 @@ LibraryManager.library = { type = 'i32'; // varargs are always i32, i64, or double ret = {{{ makeGetValue('varargs', 'argIndex', 'i32', undefined, undefined, true) }}}; } - argIndex += Runtime.getNativeFieldSize(type); + argIndex += Runtime.getAlignSize(type); return ret; } diff --git a/src/modules.js b/src/modules.js index ce162ac162880..9cbe88aadddc2 100644 --- a/src/modules.js +++ b/src/modules.js @@ -2,6 +2,8 @@ // Various namespace-like modules +var STACK_ALIGN = TARGET_X86 ? 4 : 8; + var LLVM = { LINKAGES: set('private', 'linker_private', 'linker_private_weak', 'linker_private_weak_def_auto', 'internal', 'available_externally', 'linkonce', 'common', 'weak', 'appending', 'extern_weak', 'linkonce_odr', diff --git a/src/runtime.js b/src/runtime.js index b15f4152e30c6..0a991117e0e54 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -14,8 +14,8 @@ var RuntimeGenerator = { ret += sep + '_memset(' + type + 'TOP, 0, ' + size + ')'; } ret += sep + type + 'TOP = (' + type + 'TOP + ' + size + ')|0'; - if ({{{ QUANTUM_SIZE }}} > 1 && !ignoreAlign) { - ret += sep + RuntimeGenerator.alignMemory(type + 'TOP', {{{ QUANTUM_SIZE }}}); + if ({{{ STACK_ALIGN }}} > 1 && !ignoreAlign) { + ret += sep + RuntimeGenerator.alignMemory(type + 'TOP', {{{ STACK_ALIGN }}}); } return ret; }, @@ -23,9 +23,8 @@ var RuntimeGenerator = { // An allocation that lives as long as the current function call stackAlloc: function(size, sep) { sep = sep || ';'; - if (USE_TYPED_ARRAYS === 2) 'STACKTOP = (STACKTOP + STACKTOP|0 % ' + ({{{ QUANTUM_SIZE }}} - (isNumber(size) ? Math.min(size, {{{ QUANTUM_SIZE }}}) : {{{ QUANTUM_SIZE }}})) + ')' + sep; - // The stack is always QUANTUM SIZE aligned, so we may not need to force alignment here - var ret = RuntimeGenerator.alloc(size, 'STACK', false, sep, USE_TYPED_ARRAYS != 2 || (isNumber(size) && parseInt(size) % {{{ QUANTUM_SIZE }}} == 0)); + if (USE_TYPED_ARRAYS === 2) 'STACKTOP = (STACKTOP + STACKTOP|0 % ' + ({{{ STACK_ALIGN }}} - (isNumber(size) ? Math.min(size, {{{ STACK_ALIGN }}}) : {{{ STACK_ALIGN }}})) + ')' + sep; + var ret = RuntimeGenerator.alloc(size, 'STACK', false, sep, USE_TYPED_ARRAYS != 2 || (isNumber(size) && parseInt(size) % {{{ STACK_ALIGN }}} == 0)); if (ASSERTIONS) { ret += sep + 'assert(' + asmCoercion('(STACKTOP|0) < (STACK_MAX|0)', 'i32') + ')'; } @@ -37,8 +36,8 @@ var RuntimeGenerator = { var ret = 'var __stackBase__ = ' + (ASM_JS ? '0; __stackBase__ = ' : '') + 'STACKTOP'; if (initial > 0) ret += '; STACKTOP = (STACKTOP + ' + initial + ')|0'; if (USE_TYPED_ARRAYS == 2) { - assert(initial % QUANTUM_SIZE == 0); - if (ASSERTIONS && QUANTUM_SIZE == 4) { + assert(initial % Runtime.STACK_ALIGN == 0); + if (ASSERTIONS && Runtime.STACK_ALIGN == 4) { ret += '; assert(' + asmCoercion('!(STACKTOP&3)', 'i32') + ')'; } } @@ -70,7 +69,7 @@ var RuntimeGenerator = { alignMemory: function(target, quantum) { if (typeof quantum !== 'number') { - quantum = '(quantum ? quantum : {{{ QUANTUM_SIZE }}})'; + quantum = '(quantum ? quantum : {{{ STACK_ALIGN }}})'; } return target + ' = ' + Runtime.forceAlign(target, quantum); }, @@ -175,6 +174,8 @@ var Runtime = { set: set, + STACK_ALIGN: {{{ STACK_ALIGN }}}, + // type can be a native type or a struct (or null, for structs we only look at size here) getAlignSize: function(type, size) { // we align i64s and doubles on 64-bit boundaries, unlike x86 From 174fc66d0ade7f5922341d339f9c8f7262fd35a4 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 22 Apr 2013 11:11:09 -0700 Subject: [PATCH 31/34] remove unused line --- src/runtime.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/runtime.js b/src/runtime.js index 0a991117e0e54..5b12241e4a278 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -23,7 +23,6 @@ var RuntimeGenerator = { // An allocation that lives as long as the current function call stackAlloc: function(size, sep) { sep = sep || ';'; - if (USE_TYPED_ARRAYS === 2) 'STACKTOP = (STACKTOP + STACKTOP|0 % ' + ({{{ STACK_ALIGN }}} - (isNumber(size) ? Math.min(size, {{{ STACK_ALIGN }}}) : {{{ STACK_ALIGN }}})) + ')' + sep; var ret = RuntimeGenerator.alloc(size, 'STACK', false, sep, USE_TYPED_ARRAYS != 2 || (isNumber(size) && parseInt(size) % {{{ STACK_ALIGN }}} == 0)); if (ASSERTIONS) { ret += sep + 'assert(' + asmCoercion('(STACKTOP|0) < (STACK_MAX|0)', 'i32') + ')'; From 5eb7cf382f79086d9d6d62ee97e65cc7adc50a2b Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 22 Apr 2013 11:17:00 -0700 Subject: [PATCH 32/34] fully align varargs and formatString arguments all to 64-bit --- src/jsifier.js | 1 + src/library.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/jsifier.js b/src/jsifier.js index 2715ae3e1ef22..1cb6308d1cb3c 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -1366,6 +1366,7 @@ function JSify(data, functionsOnly, givenFunctions) { } else { size = Runtime.getNativeFieldSize(param.type); } + size = Runtime.alignMemory(size, Runtime.STACK_ALIGN); varargs.push(val); varargs = varargs.concat(zeros(size-1)); // TODO: replace concats like this with push diff --git a/src/library.js b/src/library.js index f9ff18ecc3a7a..ae997a71f7ee2 100644 --- a/src/library.js +++ b/src/library.js @@ -2679,7 +2679,7 @@ LibraryManager.library = { type = 'i32'; // varargs are always i32, i64, or double ret = {{{ makeGetValue('varargs', 'argIndex', 'i32', undefined, undefined, true) }}}; } - argIndex += Runtime.getAlignSize(type); + argIndex += {{{ STACK_ALIGN }}}; return ret; } From 049f78e0aaec83d9a0b5ec5bdf209d5c895b489a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 22 Apr 2013 13:41:34 -0700 Subject: [PATCH 33/34] fix varargs alignment in le32 --- src/jsifier.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jsifier.js b/src/jsifier.js index 1cb6308d1cb3c..c82d284a40967 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -1400,11 +1400,11 @@ function JSify(data, functionsOnly, givenFunctions) { var type = varargsTypes[i]; if (type == 0) return null; var ret; + assert(offset % Runtime.STACK_ALIGN == 0); // varargs must be aligned if (!varargsByVals[i]) { ret = makeSetValue(getFastValue('tempInt', '+', offset), 0, arg, type, null, null, QUANTUM_SIZE, null, ','); - offset += Runtime.getNativeFieldSize(type); + offset += Runtime.alignMemory(Runtime.getNativeFieldSize(type), Runtime.STACK_ALIGN); } else { - assert(offset % Runtime.STACK_ALIGN == 0); // varargs must be aligned var size = calcAllocatedSize(removeAllPointing(type)); ret = makeCopyValues(getFastValue('tempInt', '+', offset), arg, size, null, null, varargsByVals[i], ','); offset += Runtime.forceAlign(size, Runtime.STACK_ALIGN); From 0b6a6613bc43768668fe50fd94074382c3652efa Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 27 Apr 2013 18:23:16 -0700 Subject: [PATCH 34/34] bump version --- tools/shared.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/shared.py b/tools/shared.py index 16da1ea303d85..d29875f97603c 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -199,7 +199,7 @@ def check_node_version(): # we re-check sanity when the settings are changed) # We also re-check sanity and clear the cache when the version changes -EMSCRIPTEN_VERSION = '1.3.8' +EMSCRIPTEN_VERSION = '1.4.1' def check_sanity(force=False): try: