aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS1
-rwxr-xr-xemcc21
-rw-r--r--emscripten-version.txt2
-rwxr-xr-xemscripten.py1
-rw-r--r--src/emscripten-source-map.min.js3
-rw-r--r--src/library.js18
-rw-r--r--src/library_gl.js47
-rw-r--r--src/library_sdl.js2
-rw-r--r--src/preamble.js9
-rw-r--r--system/include/emscripten/emscripten.h26
-rw-r--r--tests/cases/floatundefinvoke_fastcomp.ll30
-rw-r--r--tests/cases/floatundefinvoke_fastcomp.txt3
-rw-r--r--tests/core/test_exceptions_white_list_empty.out0
-rw-r--r--tests/core/test_set_align.c50
-rw-r--r--tests/core/test_set_align.out8
-rw-r--r--tests/gl_teximage.c120
-rw-r--r--tests/test_browser.py3
-rw-r--r--tests/test_core.py95
-rw-r--r--tests/test_other.py20
-rw-r--r--tests/test_sanity.py2
-rw-r--r--tools/js-optimizer.js21
-rw-r--r--tools/js_optimizer.py28
-rw-r--r--tools/shared.py2
-rw-r--r--tools/test-js-optimizer-asm-pre-output.js14
-rw-r--r--tools/test-js-optimizer-asm-pre.js13
25 files changed, 459 insertions, 80 deletions
diff --git a/AUTHORS b/AUTHORS
index dc848d34..2ff3bd94 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -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.)
diff --git a/emcc b/emcc
index 1a645965..e55990df 100755
--- a/emcc
+++ b/emcc
@@ -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