diff options
-rw-r--r-- | docs/paper.tex | 8 | ||||
-rwxr-xr-x | emcc | 39 | ||||
-rw-r--r-- | src/library.js | 39 | ||||
-rw-r--r-- | src/library_egl.js | 31 | ||||
-rw-r--r-- | src/library_gl.js | 8 | ||||
-rw-r--r-- | src/preamble.js | 6 | ||||
-rw-r--r-- | tests/cube_explosion.c | 7 | ||||
-rw-r--r-- | tools/shared.py | 4 |
8 files changed, 85 insertions, 57 deletions
diff --git a/docs/paper.tex b/docs/paper.tex index 4ad795b8..3b8da618 100644 --- a/docs/paper.tex +++ b/docs/paper.tex @@ -114,7 +114,7 @@ main ones of which are Clang and LLVM-GCC) into the LLVM intermediary representation (which can be machine-readable bitcode, or human-readable assembly), and then passes it through a \emph{backend} which generates actual machine code for a particular -architecure. Emscripten plays the role of a backend which targets JavaScript. +architecture. Emscripten plays the role of a backend which targets JavaScript. By using Emscripten, potentially many languages can be run on the web, using one of the following methods: @@ -138,7 +138,7 @@ run on the web, using one of the following methods: From a technical standpoint, one challenge in designing and implementing Emscripten is that it compiles a low-level language -- LLVM assembly -- into -a high-level one -- JavaScript. This is somethat the reverse of the usual +a high-level one -- JavaScript. This is somewhat the reverse of the usual situation one is in when building a compiler, and leads to some unique difficulties. For example, to get good performance in JavaScript one must use natural JavaScript code flow structures, like loops and ifs, but @@ -475,7 +475,7 @@ a compilation option, SAFE\_HEAP, which generates code that checks that LSC hold doesn't. It also warns about other memory-related issues like reading from memory before a value was written (somewhat similarly to tools like Valgrind\footnote{\url{http://valgrind.org/}}). When such problems are detected, possible solutions are to ignore the issue (if it has no actual -consqeuences), or alter the source code. +consequences), or alter the source code. Note that it is somewhat wasteful to allocate 4 memory locations for a 32-bit integer, and use only one of them. It is possible to change @@ -737,7 +737,7 @@ surprisingly easy to implement. For example, C++ exceptions are represented in LLVM by \emph{invoke} and \emph{unwind}, where \emph{invoke} is a call to a function that will potentially trigger an \emph{unwind}, and \emph{unwind} returns to the earliest invoke. If one were to implement those -in a typical compiler, doing so would require careful work. In Emscripen, however, +in a typical compiler, doing so would require careful work. In Emscripten, however, it is possible to do so using JavaScript exceptions in a straightforward manner: \emph{invoke} becomes a function call wrapped in a \emph{try} block, and \emph{unwind} becomes \emph{throw}. This is a case where compiling to a high-level language turns @@ -248,6 +248,15 @@ Options that are modified or new in %s include: are compiling to. To run your code, you will need both the .html and the .data. + emcc runs tools/file_packager.py to do the + actual packaging of embedded and preloaded + files. You can run the file packager yourself + if you want, see docs inside that file. You + should then put the output of the file packager + in an emcc --pre-js, so that it executes before + your main compiled code (or run it before in + some other way). + --compression <codec> Compress both the compiled code and embedded/ preloaded files. <codec> should be a triple, @@ -1089,36 +1098,6 @@ try: shared.Building.llvm_opt(in_temp(target_basename + '.bc'), link_opts) if DEBUG: save_intermediate('linktime', 'bc') - # Optimization and lto can add new intrinsics like memcpy that were not present before. We - # are now *after* linking in libc, so we missed our chance to get memcpy - check and add it now - # if necessary - final_symbols = shared.Building.llvm_nm(final) - need_memcpy = False - for symbol in final_symbols.undefs: - if symbol in MEMCPY_ALIASES: - need_memcpy = True - break - has_memcpy = False - for symbol in final_symbols.defs: - if symbol in MEMCPY_ALIASES: - has_memcpy = True - break - if need_memcpy and not has_memcpy: - if DEBUG: print >> sys.stderr, 'memcpy intrinsic added in optimizations, linking in optimized memcpy' - memcpy = in_temp('memcpy.bc') - force_cxx = os.environ.get('EMMAKEN_CXX') - if force_cxx is not None: del os.environ['EMMAKEN_CXX'] # memcpy must be compiled as C - execute([shared.PYTHON, shared.EMCC, shared.path_from_root('system', 'lib', 'libc', 'musl', 'memcpy.c'), '-o', memcpy], stdout=stdout, stderr=stderr) - if force_cxx is not None: os.environ['EMMAKEN_CXX'] = force_cxx - shared.Building.llvm_opt(memcpy, llvm_opts) # optimize it just like normal code; no point in lto though - next = final + '.postrinsics.bc' - shared.Building.link([final, memcpy], next) - final = next - if shared.Settings.ASM_JS: # export it so other library functions etc. can use it - if '_memcpy' not in shared.Settings.EXPORTED_FUNCTIONS: - shared.Settings.EXPORTED_FUNCTIONS.append('_memcpy') - if DEBUG: save_intermediate('postrinsics', 'bc') - # Prepare .ll for Emscripten if not LEAVE_INPUTS_RAW: final = shared.Building.llvm_dis(final, final + '.ll') diff --git a/src/library.js b/src/library.js index 53fc8617..5071552a 100644 --- a/src/library.js +++ b/src/library.js @@ -4217,16 +4217,31 @@ LibraryManager.library = { return ret; }, + memcpy__asm: 'true', + memcpy__sig: 'iiii', memcpy: function (dest, src, num) { - // simple version, in general it should not be used - we should pull it in from libc - if (!_memcpy.shown) { - _memcpy.shown = true; - Module.printErr('warning: library.js memcpy should not be running, it is only for testing!'); + dest = dest|0; src = src|0; num = num|0; + if ((dest&3) == (src&3)) { + while (dest & 3 & num) { + {{{ makeSetValueAsm('dest', 0, makeGetValueAsm('src', 0, 'i8'), 'i8') }}}; + dest = (dest+1)|0; + src = (src+1)|0; + num = (num-1)|0; + } + while ((num|0) >= 4) { + {{{ makeSetValueAsm('dest', 0, makeGetValueAsm('src', 0, 'i32'), 'i32') }}}; + dest = (dest+4)|0; + src = (src+4)|0; + num = (num-4)|0; + } } -#endif - while (num--) { - HEAP8[dest++] = HEAP8[src++]; + while ((num|0) > 0) { + {{{ makeSetValueAsm('dest', 0, makeGetValueAsm('src', 0, 'i8'), 'i8') }}}; + dest = (dest+1)|0; + src = (src+1)|0; + num = (num-1)|0; } + return dest|0; }, wmemcpy: function() { throw 'wmemcpy not implemented' }, @@ -5601,11 +5616,11 @@ LibraryManager.library = { // ========================================================================== __utsname_struct_layout: Runtime.generateStructInfo([ - 'sysname', - 'nodename', - 'release', - 'version', - 'machine'], '%struct.utsname'), + 'sysname', + 'nodename', + 'release', + 'version', + 'machine'], '%struct.utsname'), uname__deps: ['__utsname_struct_layout'], uname: function(name) { // int uname(struct utsname *name); diff --git a/src/library_egl.js b/src/library_egl.js index 1c35ddf4..a9eb37dd 100644 --- a/src/library_egl.js +++ b/src/library_egl.js @@ -71,6 +71,17 @@ var LibraryEGL = { return 0; } }, + + // EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy); + eglTerminate: function(display) { + if (display != 62000 /* Magic ID for Emscripten 'default display' */) { + EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */); + return 0; + } + // TODO: Tear down EGL here. Currently a no-op since we don't need to actually do anything here for the browser. + EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); + return 1; + }, // EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config); eglGetConfigs: function(display, configs, config_size, numConfigs) { @@ -228,6 +239,22 @@ var LibraryEGL = { return 62004; // Magic ID for Emscripten EGLContext }, + // EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx); + eglDestroyContext: function(display, context) { + if (display != 62000 /* Magic ID for Emscripten 'default display' */) { + EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */); + return 0; + } + + if (context != 62004 /* Magic ID for Emscripten EGLContext */) { + EGL.setErrorCode(0x3006 /* EGL_BAD_CONTEXT */); + return 0; + } + + EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); + return 1; + }, + // EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value); eglQuerySurface: function(display, surface, attribute, value) { if (display != 62000 /* Magic ID for Emscripten 'default display' */) { @@ -336,6 +363,7 @@ var LibraryEGL = { return EGL.eglErrorCode; }, + // EGLAPI const char * EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name); eglQueryString: function(display, name) { if (display != 62000 /* Magic ID for Emscripten 'default display' */) { EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */); @@ -412,7 +440,8 @@ var LibraryEGL = { EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); return 1; }, - + + // EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface); eglSwapBuffers: function() { EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); }, diff --git a/src/library_gl.js b/src/library_gl.js index 0566b3a0..f7966dab 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -424,11 +424,9 @@ var LibraryGL = { }, glIsTexture: function(texture) { - var fb = GL.textures[texture]; - if (typeof(fb) == 'undefined') { - return 0; - } - return Module.ctx.isTexture(fb); + var texture = GL.textures[texture]; + if (!texture) return 0; + return Module.ctx.isTexture(texture); }, glGenBuffers__sig: 'vii', diff --git a/src/preamble.js b/src/preamble.js index 8a68736e..aab50e9a 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -35,8 +35,8 @@ function SAFE_HEAP_ACCESS(dest, type, store, ignore) { // When using typed arrays, reads over the top of TOTAL_MEMORY will fail silently, so we must // correct that by growing TOTAL_MEMORY as needed. Without typed arrays, memory is a normal // JS array so it will work (potentially slowly, depending on the engine). - assert(dest < STATICTOP); - assert(STATICTOP <= TOTAL_MEMORY); + assert(ignore || dest < STATICTOP); + assert(ignore || STATICTOP <= TOTAL_MEMORY); #endif #if USE_TYPED_ARRAYS == 2 @@ -482,7 +482,7 @@ Module['ALLOC_NONE'] = ALLOC_NONE; var _memset = function(ptr, value, num) { var stop = ptr + num; while (ptr < stop) { - {{{ makeSetValueAsm('ptr++', 0, 'value', 'i8', null, null, null, true) }}}; + {{{ makeSetValue('ptr++', 0, 'value', 'i8', null, true) }}}; } } diff --git a/tests/cube_explosion.c b/tests/cube_explosion.c index ee990a57..3f55b3c6 100644 --- a/tests/cube_explosion.c +++ b/tests/cube_explosion.c @@ -64,8 +64,11 @@ int main(int argc, char *argv[]) // Create a texture GLuint texture; + assert(!glIsTexture(1)); // not a texture glGenTextures( 1, &texture ); + assert(!glIsTexture(texture)); // not a texture until glBindTexture glBindTexture( GL_TEXTURE_2D, texture ); + assert(glIsTexture(texture)); // NOW it is a texture glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); GLubyte textureData[16*16*4]; @@ -223,6 +226,10 @@ int main(int argc, char *argv[]) SDL_GL_SwapBuffers(); + assert(glIsTexture(texture)); // still a texture + glDeleteTextures(1, &texture); + assert(!glIsTexture(texture)); // but not anymore + verify(); #if !EMSCRIPTEN diff --git a/tools/shared.py b/tools/shared.py index e41d7c5c..b55e60dc 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -1081,7 +1081,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e Building._is_ar_cache[filename] = sigcheck return sigcheck except Exception, e: - print >> sys.stderr, 'shared.Building.is_ar failed to test whether file \'%s\' is a llvm archive file! Failed on exception: %s' % (filename, e) + if DEBUG: print >> sys.stderr, 'shared.Building.is_ar failed to test whether file \'%s\' is a llvm archive file! Failed on exception: %s' % (filename, e) return False @staticmethod @@ -1101,7 +1101,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e assert os.path.exists(test_ll) try_delete(test_ll) except Exception, e: - print >> sys.stderr, 'shared.Building.is_bitcode failed to test whether file \'%s\' is a llvm bitcode file! Failed on exception: %s' % (filename, e) + if DEBUG: print >> sys.stderr, 'shared.Building.is_bitcode failed to test whether file \'%s\' is a llvm bitcode file! Failed on exception: %s' % (filename, e) return False # look for magic signature |