diff options
-rw-r--r-- | AUTHORS | 1 | ||||
-rwxr-xr-x | emcc | 21 | ||||
-rw-r--r-- | emscripten-version.txt | 2 | ||||
-rwxr-xr-x | emscripten.py | 1 | ||||
-rw-r--r-- | src/emscripten-source-map.min.js | 3 | ||||
-rw-r--r-- | src/library.js | 18 | ||||
-rw-r--r-- | src/library_gl.js | 47 | ||||
-rw-r--r-- | src/library_sdl.js | 2 | ||||
-rw-r--r-- | src/preamble.js | 9 | ||||
-rw-r--r-- | system/include/emscripten/emscripten.h | 26 | ||||
-rw-r--r-- | tests/cases/floatundefinvoke_fastcomp.ll | 30 | ||||
-rw-r--r-- | tests/cases/floatundefinvoke_fastcomp.txt | 3 | ||||
-rw-r--r-- | tests/core/test_exceptions_white_list_empty.out | 0 | ||||
-rw-r--r-- | tests/core/test_set_align.c | 50 | ||||
-rw-r--r-- | tests/core/test_set_align.out | 8 | ||||
-rw-r--r-- | tests/gl_teximage.c | 120 | ||||
-rw-r--r-- | tests/test_browser.py | 3 | ||||
-rw-r--r-- | tests/test_core.py | 95 | ||||
-rw-r--r-- | tests/test_other.py | 20 | ||||
-rw-r--r-- | tests/test_sanity.py | 2 | ||||
-rw-r--r-- | tools/js-optimizer.js | 21 | ||||
-rw-r--r-- | tools/js_optimizer.py | 28 | ||||
-rw-r--r-- | tools/shared.py | 2 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-pre-output.js | 14 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-pre.js | 13 |
25 files changed, 459 insertions, 80 deletions
@@ -141,4 +141,5 @@ a license to everyone to use it as detailed in LICENSE.) * Markus Henschel <markus.henschel@yager.de> * Ophir Lojkine <ophir.lojkine@eleves.ec-nantes.fr> * Ryan Sturgell <ryan.sturgell@gmail.com> (copyright owned by Google, Inc.) +* Jason Green <jason@transgaming.com> (copyright owned by TransGaming, Inc.) @@ -64,6 +64,7 @@ DYNAMICLIB_ENDINGS = ('.dylib', '.so', '.dll') STATICLIB_ENDINGS = ('.a',) ASSEMBLY_ENDINGS = ('.ll',) HEADER_ENDINGS = ('.h', '.hxx', '.hpp', '.hh', '.H', '.HXX', '.HPP', '.HH') +SUPPORTED_LINKER_FLAGS = ('--start-group', '-(', '--end-group', '-)') LIB_PREFIXES = ('', 'lib') @@ -1177,7 +1178,12 @@ try: # (4, a), (4.25, b), (4.5, c), (4.75, d) link_flags_to_add = arg.split(',')[1:] for flag_index, flag in enumerate(link_flags_to_add): - link_flags.append((i + float(flag_index) / len(link_flags_to_add), flag)) + # Only keep flags that shared.Building.link knows how to deal with. + # We currently can't handle flags with options (like + # -Wl,-rpath,/bin:/lib, where /bin:/lib is an option for the -rpath + # flag). + if flag in SUPPORTED_LINKER_FLAGS: + link_flags.append((i + float(flag_index) / len(link_flags_to_add), flag)) newargs[i] = '' original_input_files = input_files[:] @@ -1263,10 +1269,10 @@ try: assert shared.Settings.TARGET_ASMJS_UNKNOWN_EMSCRIPTEN == 1, 'fastcomp requires asmjs-unknown-emscripten' assert shared.Settings.USE_TYPED_ARRAYS == 2, 'fastcomp assumes ta2' assert not split_js_file, '--split-js is deprecated and not supported in fastcomp' - assert shared.Settings.MAX_SETJMPS == 20, 'changing MAX_SETJMPS is not supported in fastcomp yet' assert shared.Settings.INIT_HEAP == 0, 'HEAP_INIT is not supported in fastcomp (and should never be needed except for debugging)' assert not shared.Settings.RUNTIME_TYPE_INFO, 'RUNTIME_TYPE_INFO is not supported in fastcomp' assert not shared.Settings.CORRUPTION_CHECK, 'CORRUPTION_CHECK is not supported in asm.js mode, which is what fastcomp can emit (you can use non-asm.js mode in non-fastcomp)' + assert not shared.Settings.MAIN_MODULE and not shared.Settings.SIDE_MODULE, 'Linking modules is not supported in fastcomp' except Exception, e: logging.error('Compiler settings are incompatible with fastcomp. You can fall back to the older compiler core, although that is not recommended, see https://github.com/kripken/emscripten/wiki/LLVM-Backend') raise e @@ -1283,8 +1289,8 @@ try: fastcomp_opts += ['-pnacl-abi-simplify-preopt', '-pnacl-abi-simplify-postopt'] if shared.Settings.DISABLE_EXCEPTION_CATCHING != 1: fastcomp_opts += ['-enable-emscripten-cxx-exceptions'] - if len(shared.Settings.EXCEPTION_CATCHING_WHITELIST) > 0: - fastcomp_opts += ['-emscripten-cxx-exceptions-whitelist=' + ','.join(shared.Settings.EXCEPTION_CATCHING_WHITELIST)] + if shared.Settings.DISABLE_EXCEPTION_CATCHING == 2: + fastcomp_opts += ['-emscripten-cxx-exceptions-whitelist=' + ','.join(shared.Settings.EXCEPTION_CATCHING_WHITELIST or ['fake'])] if shared.Settings.ASM_JS: assert opt_level >= 1 or fastcomp, 'asm.js requires -O1 or above' @@ -1788,8 +1794,11 @@ try: if emit_symbol_map: js_optimizer_queue += ['symbolMap='+target+'.symbols'] if debug_level == 0: js_optimizer_queue += ['minifyWhitespace'] - if closure and shared.Settings.ASM_JS: - js_optimizer_queue += ['closure'] + if shared.Settings.ASM_JS: + if closure: + js_optimizer_queue += ['closure'] + elif debug_level <= 2 and not shared.Settings.MAIN_MODULE and not shared.Settings.SIDE_MODULE: + js_optimizer_queue += ['cleanup'] if not shared.Settings.SIDE_MODULE: js_optimizer_queue += ['last'] # side modules are not finalized until after relocation diff --git a/emscripten-version.txt b/emscripten-version.txt index 18abf253..ca3ca78e 100644 --- a/emscripten-version.txt +++ b/emscripten-version.txt @@ -1,2 +1,2 @@ -1.18.3 +1.18.4 diff --git a/emscripten.py b/emscripten.py index 9abaf60c..98877a8e 100755 --- a/emscripten.py +++ b/emscripten.py @@ -761,6 +761,7 @@ def emscript_fast(infile, settings, outfile, libraries=[], compiler_engine=None, if settings['ALIASING_FUNCTION_POINTERS'] == 0: backend_args += ['-emscripten-no-aliasing-function-pointers'] backend_args += ['-O' + str(settings['OPT_LEVEL'])] + backend_args += ['-emscripten-max-setjmps=%d' % settings['MAX_SETJMPS']] if DEBUG: logging.debug('emscript: llvm backend: ' + ' '.join(backend_args)) t = time.time() diff --git a/src/emscripten-source-map.min.js b/src/emscripten-source-map.min.js index 9151400f..44cb1d84 100644 --- a/src/emscripten-source-map.min.js +++ b/src/emscripten-source-map.min.js @@ -4,7 +4,7 @@ var emscripten_sourcemap_xmlHttp = undefined; function emscripten_sourceMapLoaded() { if (emscripten_sourcemap_xmlHttp.readyState === 4) { Module['removeRunDependency']('sourcemap'); - if (emscripten_sourcemap_xmlHttp.status === 200) { + if (emscripten_sourcemap_xmlHttp.status === 200 || emscripten_sourcemap_xmlHttp.status === 0) { emscripten_source_map = new window.sourceMap.SourceMapConsumer(emscripten_sourcemap_xmlHttp.responseText); console.log('Source map data loaded.'); } else { @@ -20,6 +20,7 @@ function emscripten_loadSourceMap() { emscripten_sourcemap_xmlHttp = new XMLHttpRequest(); emscripten_sourcemap_xmlHttp.onreadystatechange = emscripten_sourceMapLoaded; emscripten_sourcemap_xmlHttp.open("GET", url, true); + emscripten_sourcemap_xmlHttp.responseType = "text"; emscripten_sourcemap_xmlHttp.send(null); } diff --git a/src/library.js b/src/library.js index 9dd2aedc..fb1a8998 100644 --- a/src/library.js +++ b/src/library.js @@ -5923,15 +5923,15 @@ LibraryManager.library = { var i = 0; setjmpId = (setjmpId+1)|0; {{{ makeSetValueAsm('env', '0', 'setjmpId', 'i32') }}}; - while ((i|0) < {{{ 2*MAX_SETJMPS }}}) { - if ({{{ makeGetValueAsm('table', '(i<<2)', 'i32') }}} == 0) { - {{{ makeSetValueAsm('table', '(i<<2)', 'setjmpId', 'i32') }}}; - {{{ makeSetValueAsm('table', '(i<<2)+4', 'label', 'i32') }}}; + while ((i|0) < {{{ MAX_SETJMPS }}}) { + if ({{{ makeGetValueAsm('table', '(i<<3)', 'i32') }}} == 0) { + {{{ makeSetValueAsm('table', '(i<<3)', 'setjmpId', 'i32') }}}; + {{{ makeSetValueAsm('table', '(i<<3)+4', 'label', 'i32') }}}; // prepare next slot - {{{ makeSetValueAsm('table', '(i<<2)+8', '0', 'i32') }}}; + {{{ makeSetValueAsm('table', '(i<<3)+8', '0', 'i32') }}}; return 0; } - i = (i+2)|0; + i = i+1|0; } {{{ makePrintChars('too many setjmps in a function call, build with a higher value for MAX_SETJMPS') }}}; abort(0); @@ -5945,12 +5945,12 @@ LibraryManager.library = { table = table|0; var i = 0, curr = 0; while ((i|0) < {{{ MAX_SETJMPS }}}) { - curr = {{{ makeGetValueAsm('table', '(i<<2)', 'i32') }}}; + curr = {{{ makeGetValueAsm('table', '(i<<3)', 'i32') }}}; if ((curr|0) == 0) break; if ((curr|0) == (id|0)) { - return {{{ makeGetValueAsm('table', '(i<<2)+4', 'i32') }}}; + return {{{ makeGetValueAsm('table', '(i<<3)+4', 'i32') }}}; } - i = (i+2)|0; + i = i+1|0; } return 0; }, diff --git a/src/library_gl.js b/src/library_gl.js index 851b01b1..2659a9d9 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -431,21 +431,42 @@ var LibraryGL = { sizePerPixel = 2; break; default: - throw 'Invalid format (' + format + ')'; + GL.recordError(0x0500); // GL_INVALID_ENUM +#if GL_ASSERTIONS + Module.printErr('GL_INVALID_ENUM in glTex[Sub]Image, type: ' + type + ', format: ' + format); +#endif + return { + pixels: null, + internalFormat: 0x0 + }; } break; case 0x1403 /* GL_UNSIGNED_SHORT */: if (format == 0x1902 /* GL_DEPTH_COMPONENT */) { sizePerPixel = 2; } else { - throw 'Invalid format (' + format + ')'; + GL.recordError(0x0500); // GL_INVALID_ENUM +#if GL_ASSERTIONS + Module.printErr('GL_INVALID_ENUM in glTex[Sub]Image, type: ' + type + ', format: ' + format); +#endif + return { + pixels: null, + internalFormat: 0x0 + }; } break; case 0x1405 /* GL_UNSIGNED_INT */: if (format == 0x1902 /* GL_DEPTH_COMPONENT */) { sizePerPixel = 4; } else { - throw 'Invalid format (' + format + ')'; + GL.recordError(0x0500); // GL_INVALID_ENUM +#if GL_ASSERTIONS + Module.printErr('GL_INVALID_ENUM in glTex[Sub]Image, type: ' + type + ', format: ' + format); +#endif + return { + pixels: null, + internalFormat: 0x0 + }; } break; case 0x84FA /* UNSIGNED_INT_24_8_WEBGL */: @@ -468,12 +489,26 @@ var LibraryGL = { sizePerPixel = 4*4; break; default: - throw 'Invalid format (' + format + ')'; + GL.recordError(0x0500); // GL_INVALID_ENUM +#if GL_ASSERTIONS + Module.printErr('GL_INVALID_ENUM in glTex[Sub]Image, type: ' + type + ', format: ' + format); +#endif + return { + pixels: null, + internalFormat: 0x0 + }; } internalFormat = GLctx.RGBA; break; default: - throw 'Invalid type (' + type + ')'; + GL.recordError(0x0500); // GL_INVALID_ENUM +#if GL_ASSERTIONS + Module.printErr('GL_INVALID_ENUM in glTex[Sub]Image, type: ' + type + ', format: ' + format); +#endif + return { + pixels: null, + internalFormat: 0x0 + }; } var bytes = GL.computeImageSize(width, height, sizePerPixel, GL.unpackAlignment); if (type == 0x1401 /* GL_UNSIGNED_BYTE */) { @@ -488,7 +523,7 @@ var LibraryGL = { return { pixels: pixels, internalFormat: internalFormat - } + }; }, #if GL_FFP_ONLY diff --git a/src/library_sdl.js b/src/library_sdl.js index fd8c6860..a01b3c6c 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -2332,7 +2332,7 @@ var LibrarySDL = { return 0; } - var arrayBuffer = bytes.buffer || bytes; + var arrayBuffer = bytes ? bytes.buffer || bytes : bytes; // To allow user code to work around browser bugs with audio playback on <audio> elements an Web Audio, enable // the user code to hook in a callback to decide on a file basis whether each file should use Web Audio or <audio> for decoding and playback. diff --git a/src/preamble.js b/src/preamble.js index f46119c7..58b442ab 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -352,6 +352,13 @@ var cwrap, ccall; // C calling interface. A convenient way to call C functions (in C files, or // defined with extern "C"). // + // Note: ccall/cwrap use the C stack for temporary values. If you pass a string + // then it is only alive until the call is complete. If the code being + // called saves the pointer to be used later, it may point to invalid + // data. If you need a string to live forever, you can create it (and + // must later delete it manually!) using malloc and writeStringToMemory, + // for example. + // // Note: LLVM optimizations can inline and remove functions, after which you will not be // able to call them. Closure can also do so. To avoid that, add your function to // the exports using something like @@ -389,7 +396,7 @@ var cwrap, ccall; return ret; } - var sourceRegex = /^function \((.*)\)\s*{\s*([^]*?)[\s;]*(?:return\s*(.*?)[;\s]*)?}$/; + var sourceRegex = /^function\s\(([^)]*)\)\s*{\s*([^*]*?)[\s;]*(?:return\s*(.*?)[;\s]*)?}$/; function parseJSFunc(jsfunc) { // Match the body and the return value of a javascript function source var parsed = jsfunc.toString().match(sourceRegex).slice(1); diff --git a/system/include/emscripten/emscripten.h b/system/include/emscripten/emscripten.h index 66017a8d..8a08aabb 100644 --- a/system/include/emscripten/emscripten.h +++ b/system/include/emscripten/emscripten.h @@ -18,6 +18,32 @@ extern "C" { #include <SDL/SDL.h> /* for SDL_Delay in async_call */ #endif + +/* Typedefs */ + +/* + * Unaligned types, helpful to force LLVM to emit unaligned + * loads/stores in places in your code where SAFE_HEAP found + * an unaligned operation. (It's better to avoid unaligned + * operations, but if you are reading from a packed stream of + * bytes or such, these types may be useful.) + */ + +typedef short __attribute__((aligned(1))) emscripten_align1_short; + +typedef int __attribute__((aligned(2))) emscripten_align2_int; +typedef int __attribute__((aligned(1))) emscripten_align1_int; + +typedef float __attribute__((aligned(2))) emscripten_align2_float; +typedef float __attribute__((aligned(1))) emscripten_align1_float; + +typedef double __attribute__((aligned(4))) emscripten_align4_double; +typedef double __attribute__((aligned(2))) emscripten_align2_double; +typedef double __attribute__((aligned(1))) emscripten_align1_double; + + +/* Functions */ + /* * Convenient syntax for inline assembly/js. Allows stuff like * diff --git a/tests/cases/floatundefinvoke_fastcomp.ll b/tests/cases/floatundefinvoke_fastcomp.ll new file mode 100644 index 00000000..215506ef --- /dev/null +++ b/tests/cases/floatundefinvoke_fastcomp.ll @@ -0,0 +1,30 @@ +; ModuleID = 'a.o' +target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:128-n32-S128" +target triple = "asmjs-unknown-emscripten" + +@.str = private unnamed_addr constant [11 x i8] c"float: %f\0A\00", align 1 + +define void @_Z10printFloatf(float %f) #0 { +entry: + %conv = fpext float %f to double + %call = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([11 x i8]* @.str, i32 0, i32 0), double %conv) + ret void +} + +define i32 @main() #1 { +entry: + tail call void @_Z10printFloatf(float 1.000000e+00) + call void @emscripten_preinvoke() + call void @_Z10printFloatf(float undef) + %last = call i32 @emscripten_postinvoke() + %lastf = sitofp i32 %last to float + tail call void @_Z10printFloatf(float %lastf) + ret i32 1 +} + +declare void @emscripten_preinvoke() +declare i32 @emscripten_postinvoke() +declare i32 @printf(i8* nocapture, ...) #1 + +attributes #0 = { noinline nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } diff --git a/tests/cases/floatundefinvoke_fastcomp.txt b/tests/cases/floatundefinvoke_fastcomp.txt new file mode 100644 index 00000000..5e19391e --- /dev/null +++ b/tests/cases/floatundefinvoke_fastcomp.txt @@ -0,0 +1,3 @@ +float: 1.000000 +float: 0.000000 +float: 0.000000 diff --git a/tests/core/test_exceptions_white_list_empty.out b/tests/core/test_exceptions_white_list_empty.out new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/tests/core/test_exceptions_white_list_empty.out diff --git a/tests/core/test_set_align.c b/tests/core/test_set_align.c new file mode 100644 index 00000000..26158ef4 --- /dev/null +++ b/tests/core/test_set_align.c @@ -0,0 +1,50 @@ + +#include <stdio.h> +#include <emscripten.h> + +volatile char data[16]; + +__attribute__((noinline)) void *get_aligned(int align) +{ + char *ptr = (char*)(((int)(data + 7)) & ~7); // Make 8-byte aligned + ptr += align; // Now 'align' aligned + return (void*)ptr; +} + +int main() +{ + emscripten_align4_double *d4 = (emscripten_align4_double*)get_aligned(4); + *d4 = 17.0; + printf("addr: %d, value: %f\n", ((int)d4) % 8, *d4); + + emscripten_align2_double *d2 = (emscripten_align2_double*)get_aligned(2); + *d2 = 18.0; + printf("addr: %d, value: %f\n", ((int)d2) % 8, *d2); + + emscripten_align1_double *d1 = (emscripten_align1_double*)get_aligned(1); + *d1 = 19.0; + printf("addr: %d, value: %f\n", ((int)d1) % 8, *d1); + + emscripten_align2_float *f2 = (emscripten_align2_float*)get_aligned(2); + *f2 = 20.0; + printf("addr: %d, value: %f\n", ((int)f2) % 4, *f2); + + emscripten_align1_float *f1 = (emscripten_align1_float*)get_aligned(1); + *f1 = 21.0; + printf("addr: %d, value: %f\n", ((int)f1) % 4, *f1); + + emscripten_align2_int *i2 = (emscripten_align2_int*)get_aligned(2); + *i2 = 22; + printf("addr: %d, value: %d\n", ((int)i2) % 4, *i2); + + emscripten_align1_int *i1 = (emscripten_align1_int*)get_aligned(1); + *i1 = 23; + printf("addr: %d, value: %d\n", ((int)i1) % 4, *i1); + + emscripten_align1_short *s1 = (emscripten_align1_short*)get_aligned(1); + *s1 = 24; + printf("addr: %d, value: %d\n", ((int)s1) % 4, (int)*s1); + + return 0; +} + diff --git a/tests/core/test_set_align.out b/tests/core/test_set_align.out new file mode 100644 index 00000000..55e377b0 --- /dev/null +++ b/tests/core/test_set_align.out @@ -0,0 +1,8 @@ +addr: 4, value: 17.000000 +addr: 2, value: 18.000000 +addr: 1, value: 19.000000 +addr: 2, value: 20.000000 +addr: 1, value: 21.000000 +addr: 2, value: 22 +addr: 1, value: 23 +addr: 1, value: 24 diff --git a/tests/gl_teximage.c b/tests/gl_teximage.c new file mode 100644 index 00000000..9cafce9c --- /dev/null +++ b/tests/gl_teximage.c @@ -0,0 +1,120 @@ +/* + * GLES2 test for glTexImage2D parameters + * + * Original author: Jason Green <jason@transgaming.com> + * + */ +#include "GLES2/gl2.h" +#include "SDL/SDL.h" + +#include <stdio.h> +#include <stdlib.h> +#include <emscripten.h> +#include <unistd.h> + +typedef enum { + TEST_STATUS_SUCCESS = 0, + TEST_STATUS_FAILURE = 1 +} TestStatus; + +/* Report success or failure (1 or 0) to Emscripten's test harness. Also, exit + * with the given error code. */ +static void exit_with_status(TestStatus code) +{ +#ifdef REPORT_RESULT + int result = (code == TEST_STATUS_SUCCESS) ? 1 : 0; + REPORT_RESULT(); +#endif + + exit(code); +} + +/* Loop over all glGetError() results until GL reports GL_NO_ERROR */ +static void clear_gl_errors() +{ + GLenum err; + do { + err = glGetError(); + } while (err != GL_NO_ERROR); +} + +int main(int argc, char *argv[]) +{ + TestStatus passed = TEST_STATUS_SUCCESS; + SDL_Surface *screen; + + if (SDL_Init(SDL_INIT_VIDEO) != 0) { + printf("SDL_Init failed with %s\n", SDL_GetError()); + exit_with_status(TEST_STATUS_FAILURE); + } + + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + screen = SDL_SetVideoMode(640, 480, 16, SDL_OPENGL); + if (!screen) { + printf("SDL_SetVideoMode failed with %s\n", SDL_GetError()); + exit_with_status(TEST_STATUS_FAILURE); + } + + GLuint texture; + glGenTextures(1, &texture); + + glBindTexture(GL_TEXTURE_2D, texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // Allocate space for a 32x32 image with 4 bytes per pixel. + // No need to fill it with any useful information, as these tests are + // only designed to make sure glTexImage2D doesn't crash on unsupported + // formats. + void* pixels = malloc(4 * 32 * 32); + if (pixels == NULL) { + printf("Unable to allocate pixel data\n"); + exit_with_status(TEST_STATUS_FAILURE); + } + + // First, try 0xffff for the internal format - should fail + glTexImage2D(GL_TEXTURE_2D, 0, 0xffff, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + GLenum err = glGetError(); + if (err == GL_NO_ERROR) { + printf("internal format == 0xffff succeeded, but should have failed\n"); + passed = TEST_STATUS_FAILURE; + } + clear_gl_errors(); + + // Try 0xffff for the format - should fail + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, 0xffff, GL_UNSIGNED_BYTE, pixels); + err = glGetError(); + if (err == GL_NO_ERROR) { + printf("format == 0xffff succeeded, but should have failed\n"); + passed = TEST_STATUS_FAILURE; + } + clear_gl_errors(); + + // Try 0xffff for the type - should fail + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, 0xffff, pixels); + err = glGetError(); + if (err == GL_NO_ERROR) { + printf("type == 0xffff succeeded, but should have failed\n"); + passed = TEST_STATUS_FAILURE; + } + clear_gl_errors(); + + // Try GL_RGBA/GL_UNSIGNED_BYTE - should succeed + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); + err = glGetError(); + if (err != GL_NO_ERROR) { + printf("GL_RGBA/GL_UNSIGNED_BYTE failed with %x, but should have succeeded\n", err); + passed = TEST_STATUS_FAILURE; + } + clear_gl_errors(); + + // Clean up objects + glBindTexture(GL_TEXTURE_2D, 0); + glDeleteTextures(1, &texture); + free(pixels); + + // 'screen' is freed implicitly by SDL_Quit() + SDL_Quit(); + + exit_with_status(passed); +} diff --git a/tests/test_browser.py b/tests/test_browser.py index aedc926a..c8e07b25 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -1425,6 +1425,9 @@ keydown(100);keyup(100); // trigger the end def test_sdlglshader(self): self.btest('sdlglshader.c', reference='sdlglshader.png', args=['-O2', '--closure', '1', '-s', 'LEGACY_GL_EMULATION=1']) + def test_gl_glteximage(self): + self.btest('gl_teximage.c', '1') + def test_gl_ps(self): # pointers and a shader shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) diff --git a/tests/test_core.py b/tests/test_core.py index 7c317894..505a051b 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -1166,7 +1166,6 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co self.do_run_from_file(src, output) def test_longjmp_repeat(self): - if os.environ.get('EMCC_FAST_COMPILER') == '0': Settings.MAX_SETJMPS = 1 # todo: do this more strict thing in fastcomp too test_path = path_from_root('tests', 'core', 'test_longjmp_repeat') src, output = (test_path + s for s in ('.in', '.out')) self.do_run_from_file(src, output) @@ -1190,8 +1189,6 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co self.do_run_from_file(src, output) def test_setjmp_many(self): - if os.environ.get('EMCC_FAST_COMPILER') != '0': return self.skip('todo in fastcomp: make MAX_SETJMPS take effect') - src = r''' #include <stdio.h> #include <setjmp.h> @@ -1203,9 +1200,42 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co return 0; } ''' - for num in [Settings.MAX_SETJMPS, Settings.MAX_SETJMPS+1]: - print num - self.do_run(src.replace('NUM', str(num)), '0\n' * num if num <= Settings.MAX_SETJMPS or not Settings.ASM_JS else 'build with a higher value for MAX_SETJMPS') + for maxx in [Settings.MAX_SETJMPS/2, Settings.MAX_SETJMPS, 2*Settings.MAX_SETJMPS]: + Settings.MAX_SETJMPS = maxx + for num in [maxx, maxx+1]: + print maxx, num + self.do_run(src.replace('NUM', str(num)), '0\n' * num if num <= Settings.MAX_SETJMPS or not Settings.ASM_JS else 'build with a higher value for MAX_SETJMPS') + + def test_setjmp_many_2(self): + if os.environ.get('EMCC_FAST_COMPILER') == '0': return self.skip('non-fastcomp do not hit the limit.') + + src = r''' +#include <setjmp.h> +#include <stdio.h> + +jmp_buf env; + +void luaWork(int d){ + int x; + printf("d is at %d\n", d); + + longjmp(env, 1); +} + +int main() +{ + const int ITERATIONS=25; + for(int i = 0; i < ITERATIONS; i++){ + if(!setjmp(env)){ + luaWork(i); + } + } + return 0; +} +''' + + self.do_run(src, r'''d is at 19 +too many setjmps in a function call, build with a higher value for MAX_SETJMPS''') def test_exceptions(self): if Settings.QUANTUM_SIZE == 1: return self.skip("we don't support libcxx in q1") @@ -1317,6 +1347,33 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co test_path = path_from_root('tests', 'core', 'test_exceptions_white_list') src, output = (test_path + s for s in ('.in', '.out')) self.do_run_from_file(src, output) + size = len(open('src.cpp.o.js').read()) + shutil.copyfile('src.cpp.o.js', 'orig.js') + + if os.environ.get('EMCC_FAST_COMPILER') != '0': + # check that an empty whitelist works properly (as in, same as exceptions disabled) + empty_output = path_from_root('tests', 'core', 'test_exceptions_white_list_empty.out') + + Settings.EXCEPTION_CATCHING_WHITELIST = [] + self.do_run_from_file(src, empty_output) + empty_size = len(open('src.cpp.o.js').read()) + shutil.copyfile('src.cpp.o.js', 'empty.js') + + Settings.EXCEPTION_CATCHING_WHITELIST = ['fake'] + self.do_run_from_file(src, empty_output) + fake_size = len(open('src.cpp.o.js').read()) + shutil.copyfile('src.cpp.o.js', 'fake.js') + + Settings.DISABLE_EXCEPTION_CATCHING = 1 + self.do_run_from_file(src, empty_output) + disabled_size = len(open('src.cpp.o.js').read()) + shutil.copyfile('src.cpp.o.js', 'disabled.js') + + assert size - empty_size > 2000, [empty_size, size] # big change when we disable entirely + assert size - fake_size > 2000, [fake_size, size] + assert empty_size == fake_size, [empty_size, fake_size] + assert empty_size - disabled_size < 100, [empty_size, disabled_size] # full disable removes a tiny bit more + assert fake_size - disabled_size < 100, [disabled_size, fake_size] def test_exceptions_white_list_2(self): Settings.DISABLE_EXCEPTION_CATCHING = 2 @@ -1923,6 +1980,15 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co self.do_run_from_file(src, output) + def test_set_align(self): + if self.run_name == 'slow2asm': return self.skip('FIXME in slow2asm') + + Settings.SAFE_HEAP = 1 + + test_path = path_from_root('tests', 'core', 'test_set_align') + src, output = (test_path + s for s in ('.c', '.out')) + self.do_run_from_file(src, output) + def test_emscripten_api(self): #if Settings.MICRO_OPTS or Settings.RELOOP or Building.LLVM_OPTS: return self.skip('FIXME') @@ -2038,10 +2104,10 @@ def process(filename): if self.emcc_args and '-O2' in self.emcc_args: # Make sure ALLOW_MEMORY_GROWTH generates different code (should be less optimized) - code_start = 'var TOTAL_MEMORY = ' + code_start = 'var TOTAL_MEMORY' fail = fail[fail.find(code_start):] win = win[win.find(code_start):] - assert len(fail) < len(win), 'failing code - without memory growth on - is more optimized, and smaller' + assert len(fail) < len(win), 'failing code - without memory growth on - is more optimized, and smaller' + str([len(fail), len(win)]) def test_ssr(self): # struct self-ref src = ''' @@ -3214,7 +3280,7 @@ def process(filename): break else: raise Exception('Could not find symbol table!') - table = table[table.find('{'):table.rfind('}')+1] + table = table[table.find('{'):table.find('}')+1] # ensure there aren't too many globals; we don't want unnamed_addr assert table.count(',') <= 4 @@ -4664,8 +4730,7 @@ int main(void) { if self.emcc_args is None: self.emcc_args = [] # dlmalloc auto-inclusion is only done if we use emcc self.banned_js_engines = [NODE_JS] # slower, and fail on 64-bit - Settings.CORRECT_SIGNS = 2 - Settings.CORRECT_SIGNS_LINES = ['src.cpp:' + str(i+4) for i in [4816, 4191, 4246, 4199, 4205, 4235, 4227]] + Settings.CORRECT_SIGNS = 1 Settings.TOTAL_MEMORY = 128*1024*1024 # needed with typed arrays src = open(path_from_root('system', 'lib', 'dlmalloc.c'), 'r').read() + '\n\n\n' + open(path_from_root('tests', 'dlmalloc_test.c'), 'r').read() @@ -5424,9 +5489,6 @@ def process(filename): ### Integration tests def test_ccall(self): - if self.emcc_args is not None and '-O2' in self.emcc_args: - self.emcc_args += ['--closure', '1'] # Use closure here, to test we export things right - post = ''' def process(filename): src = \'\'\' @@ -5470,6 +5532,11 @@ def process(filename): self.do_run_from_file(src, output, post_build=post) + if self.emcc_args is not None and '-O2' in self.emcc_args: + print 'with closure' + self.emcc_args += ['--closure', '1'] + self.do_run_from_file(src, output, post_build=post) + def test_pgo(self): if Settings.ASM_JS: retu |