diff options
author | Alon Zakai <alonzakai@gmail.com> | 2013-11-01 18:26:58 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2013-11-01 18:26:58 -0700 |
commit | 3d48329892cd517b2e709ef94a00df8214169ddd (patch) | |
tree | 988d17b59d4fc2473a6d7a63df0f4117b711bcf4 /src | |
parent | 75af3c1ac8dba93b508b8b431bef9a35e6b054c3 (diff) | |
parent | 2c3d580bf9122ec4aef9ee8d462281d3fd810355 (diff) |
Merge branch 'incoming' into f32
Conflicts:
src/parseTools.js
Diffstat (limited to 'src')
-rw-r--r-- | src/analyzer.js | 2 | ||||
-rw-r--r-- | src/intertyper.js | 10 | ||||
-rw-r--r-- | src/jsifier.js | 24 | ||||
-rw-r--r-- | src/library.js | 24 | ||||
-rw-r--r-- | src/library_egl.js | 14 | ||||
-rw-r--r-- | src/library_fs.js | 172 | ||||
-rw-r--r-- | src/library_gl.js | 74 | ||||
-rw-r--r-- | src/library_glfw.js | 4 | ||||
-rw-r--r-- | src/library_glut.js | 4 | ||||
-rw-r--r-- | src/library_idbfs.js | 2 | ||||
-rw-r--r-- | src/library_memfs.js | 106 | ||||
-rw-r--r-- | src/library_nodefs.js | 12 | ||||
-rw-r--r-- | src/library_path.js | 22 | ||||
-rw-r--r-- | src/library_sdl.js | 48 | ||||
-rw-r--r-- | src/parseTools.js | 102 | ||||
-rw-r--r-- | src/preamble.js | 10 | ||||
-rw-r--r-- | src/runtime.js | 4 | ||||
-rw-r--r-- | src/shell.html | 5 |
18 files changed, 376 insertions, 263 deletions
diff --git a/src/analyzer.js b/src/analyzer.js index 2b74a83f..253c5505 100644 --- a/src/analyzer.js +++ b/src/analyzer.js @@ -418,7 +418,7 @@ function analyzer(data, sidePass) { toAdd.push({ intertype: 'value', assignTo: element.ident, - type: element.bits, + type: 'i' + element.bits, ident: 'tempRet' + (j - 1) }); assert(j<10); // TODO: dynamically create more than 10 tempRet-s diff --git a/src/intertyper.js b/src/intertyper.js index d3640889..fceeb38d 100644 --- a/src/intertyper.js +++ b/src/intertyper.js @@ -682,7 +682,7 @@ function intertyper(lines, sidePass, baseLineNums) { } if (item.assignTo) item.ident = 'return ' + item.ident; item.ident = '(function(' + params + ') { ' + item.ident + ' })(' + args + ');'; - return { forward: null, ret: item, item: item }; + return { ret: item, item: item }; } if (item.ident.substr(-2) == '()') { // See comment in isStructType() @@ -705,13 +705,12 @@ function intertyper(lines, sidePass, baseLineNums) { if (item.indent == 2) { // standalone call - not in assign item.standalone = true; - return { forward: null, ret: item, item: item }; + return { ret: item, item: item }; } - return { forward: item, ret: null, item: item }; + return { ret: null, item: item }; } function callHandler(item) { var result = makeCall.call(this, item, 'call'); - if (result.forward) this.forwardItem(result.forward, 'Reintegrator'); return result.ret; } function invokeHandler(item) { @@ -721,10 +720,9 @@ function intertyper(lines, sidePass, baseLineNums) { finalResults.push({ intertype: 'branch', label: result.item.toLabel, - lineNum: (result.forward ? item.parentLineNum : item.lineNum) + 0.5 + lineNum: item.lineNum + 0.5 }); } - if (result.forward) this.forwardItem(result.forward, 'Reintegrator'); return result.ret; } function atomicHandler(item) { diff --git a/src/jsifier.js b/src/jsifier.js index 669cec73..d5b87a77 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -937,11 +937,12 @@ function JSify(data, functionsOnly, givenFunctions) { } if (item.valueType[item.valueType.length-1] === '>') { // vector store TODO: move to makeSetValue? - var base = getVectorBaseType(item.valueType); - return '(' + makeSetValue(item.ident, 0, value + '.x', base, 0, 0, item.align) + ',' + - makeSetValue(item.ident, 4, value + '.y', base, 0, 0, item.align) + ',' + - makeSetValue(item.ident, 8, value + '.z', base, 0, 0, item.align) + ',' + - makeSetValue(item.ident, 12, value + '.w', base, 0, 0, item.align) + ')'; + var native = getVectorNativeType(item.valueType); + var base = getSIMDName(native); + return '(' + makeSetValue(item.ident, 0, value + '.x', native, 0, 0, item.align) + ',' + + makeSetValue(item.ident, 4, value + '.y', native, 0, 0, item.align) + ',' + + makeSetValue(item.ident, 8, value + '.z', native, 0, 0, item.align) + ',' + + makeSetValue(item.ident, 12, value + '.w', native, 0, 0, item.align) + ');'; } switch (impl) { case VAR_NATIVIZED: @@ -1312,11 +1313,12 @@ function JSify(data, functionsOnly, givenFunctions) { var value = finalizeLLVMParameter(item.pointer); if (item.valueType[item.valueType.length-1] === '>') { // vector load - var base = getVectorBaseType(item.valueType); - return base + '32x4(' + makeGetValue(value, 0, base, 0, item.unsigned, 0, item.align) + ',' + - makeGetValue(value, 4, base, 0, item.unsigned, 0, item.align) + ',' + - makeGetValue(value, 8, base, 0, item.unsigned, 0, item.align) + ',' + - makeGetValue(value, 12, base, 0, item.unsigned, 0, item.align) + ')'; + var native = getVectorNativeType(item.valueType); + var base = getSIMDName(native); + return base + '32x4(' + makeGetValue(value, 0, native, 0, item.unsigned, 0, item.align) + ',' + + makeGetValue(value, 4, native, 0, item.unsigned, 0, item.align) + ',' + + makeGetValue(value, 8, native, 0, item.unsigned, 0, item.align) + ',' + + makeGetValue(value, 12, native, 0, item.unsigned, 0, item.align) + ');'; } var impl = item.ident ? getVarImpl(item.funcData, item.ident) : VAR_EMULATED; switch (impl) { @@ -1478,7 +1480,7 @@ function JSify(data, functionsOnly, givenFunctions) { } params.forEach(function(param, i) { - var val = finalizeParam(param); + var val = finalizeLLVMParameter(param); if (!hasVarArgs || useJSArgs || i < normalArgs) { args.push(val); argsTypes.push(param.type); diff --git a/src/library.js b/src/library.js index 875d8bab..e3cdc7c3 100644 --- a/src/library.js +++ b/src/library.js @@ -1579,12 +1579,12 @@ LibraryManager.library = { // stdio.h // ========================================================================== - _isFloat: function(text) { - return !!(/^[+-]?[0-9]*\.?[0-9]+([eE][+-]?[0-9]+)?$/.exec(text)); + _getFloat: function(text) { + return /^[+-]?[0-9]*\.?[0-9]+([eE][+-]?[0-9]+)?/.exec(text); }, // TODO: Document. - _scanString__deps: ['_isFloat'], + _scanString__deps: ['_getFloat'], _scanString: function(format, get, unget, varargs) { if (!__scanString.whiteSpace) { __scanString.whiteSpace = {}; @@ -1743,15 +1743,13 @@ LibraryManager.library = { // Read characters according to the format. floats are trickier, they may be in an unfloat state in the middle, then be a valid float later if (type == 'f' || type == 'e' || type == 'g' || type == 'F' || type == 'E' || type == 'G') { - var last = 0; next = get(); - while (next > 0) { + while (next > 0 && (!(next in __scanString.whiteSpace))) { buffer.push(String.fromCharCode(next)); - if (__isFloat(buffer.join(''))) { - last = buffer.length; - } next = get(); } + var m = __getFloat(buffer.join('')); + var last = m ? m[0].length : 0; for (var i = 0; i < buffer.length - last + 1; i++) { unget(); } @@ -8580,7 +8578,7 @@ LibraryManager.library = { }, emscripten_run_script_string: function(ptr) { - var s = eval(Pointer_stringify(ptr)); + var s = eval(Pointer_stringify(ptr)) + ''; var me = _emscripten_run_script_string; if (!me.bufferSize || me.bufferSize < s.length+1) { if (me.bufferSize) _free(me.buffer); @@ -8623,6 +8621,14 @@ LibraryManager.library = { }, //============================ + // emscripten vector ops + //============================ + + emscripten_float32x4_signmask__inline: function(x) { + return x + '.signMask()'; + }, + + //============================ // i64 math //============================ diff --git a/src/library_egl.js b/src/library_egl.js index c25dc8ef..cc702fec 100644 --- a/src/library_egl.js +++ b/src/library_egl.js @@ -10,6 +10,8 @@ var LibraryEGL = { $EGL: { // This variable tracks the success status of the most recently invoked EGL function call. eglErrorCode: 0x3000 /* EGL_SUCCESS */, + + stringCache: {}, setErrorCode: function(code) { EGL.eglErrorCode = code; @@ -416,15 +418,19 @@ var LibraryEGL = { } //\todo An EGL_NOT_INITIALIZED error is generated if EGL is not initialized for dpy. EGL.setErrorCode(0x3000 /* EGL_SUCCESS */); + if (EGL.stringCache[name]) return EGL.stringCache[name]; + var ret; switch(name) { - case 0x3053 /* EGL_VENDOR */: return allocate(intArrayFromString("Emscripten"), 'i8', ALLOC_NORMAL); - case 0x3054 /* EGL_VERSION */: return allocate(intArrayFromString("1.4 Emscripten EGL"), 'i8', ALLOC_NORMAL); - case 0x3055 /* EGL_EXTENSIONS */: return allocate(intArrayFromString(""), 'i8', ALLOC_NORMAL); // Currently not supporting any EGL extensions. - case 0x308D /* EGL_CLIENT_APIS */: return allocate(intArrayFromString("OpenGL_ES"), 'i8', ALLOC_NORMAL); + case 0x3053 /* EGL_VENDOR */: ret = allocate(intArrayFromString("Emscripten"), 'i8', ALLOC_NORMAL); break; + case 0x3054 /* EGL_VERSION */: ret = allocate(intArrayFromString("1.4 Emscripten EGL"), 'i8', ALLOC_NORMAL); break; + case 0x3055 /* EGL_EXTENSIONS */: ret = allocate(intArrayFromString(""), 'i8', ALLOC_NORMAL); break; // Currently not supporting any EGL extensions. + case 0x308D /* EGL_CLIENT_APIS */: ret = allocate(intArrayFromString("OpenGL_ES"), 'i8', ALLOC_NORMAL); break; default: EGL.setErrorCode(0x300C /* EGL_BAD_PARAMETER */); return 0; } + EGL.stringCache[name] = ret; + return ret; }, // EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api); diff --git a/src/library_fs.js b/src/library_fs.js index bd1522a8..aece2664 100644 --- a/src/library_fs.js +++ b/src/library_fs.js @@ -28,6 +28,7 @@ mergeInto(LibraryManager.library, { ignorePermissions: true, ErrnoError: null, // set during init + genericErrors: {}, handleFSError: function(e) { if (!(e instanceof FS.ErrnoError)) throw e + ' : ' + stackTrace(); @@ -62,7 +63,7 @@ mergeInto(LibraryManager.library, { } current = FS.lookupNode(current, parts[i]); - current_path = PATH.join(current_path, parts[i]); + current_path = PATH.join2(current_path, parts[i]); // jump to the mount's root node if this is a mountpoint if (FS.isMountpoint(current)) { @@ -94,9 +95,11 @@ mergeInto(LibraryManager.library, { var path; while (true) { if (FS.isRoot(node)) { - return path ? PATH.join(node.mount.mountpoint, path) : node.mount.mountpoint; + var mount = node.mount.mountpoint; + if (!path) return mount; + return mount[mount.length-1] !== '/' ? mount + '/' + path : mount + path; } - path = path ? PATH.join(node.name, path) : node.name; + path = path ? node.name + '/' + path : node.name; node = node.parent; } }, @@ -158,44 +161,50 @@ mergeInto(LibraryManager.library, { return FS.lookup(parent, name); }, createNode: function(parent, name, mode, rdev) { - var node = { - id: FS.nextInode++, - name: name, - mode: mode, - node_ops: {}, - stream_ops: {}, - rdev: rdev, - parent: null, - mount: null - }; - if (!parent) { - parent = node; // root node sets parent to itself - } - node.parent = parent; - node.mount = parent.mount; - // compatibility - var readMode = {{{ cDefine('S_IRUGO') }}} | {{{ cDefine('S_IXUGO') }}}; - var writeMode = {{{ cDefine('S_IWUGO') }}}; - // NOTE we must use Object.defineProperties instead of individual calls to - // Object.defineProperty in order to make closure compiler happy - Object.defineProperties(node, { - read: { - get: function() { return (node.mode & readMode) === readMode; }, - set: function(val) { val ? node.mode |= readMode : node.mode &= ~readMode; } - }, - write: { - get: function() { return (node.mode & writeMode) === writeMode; }, - set: function(val) { val ? node.mode |= writeMode : node.mode &= ~writeMode; } - }, - isFolder: { - get: function() { return FS.isDir(node.mode); }, - }, - isDevice: { - get: function() { return FS.isChrdev(node.mode); }, - }, - }); - FS.hashAddNode(node); - return node; + if (!FS.FSNode) { + FS.FSNode = function(parent, name, mode, rdev) { + this.id = FS.nextInode++; + this.name = name; + this.mode = mode; + this.node_ops = {}; + this.stream_ops = {}; + this.rdev = rdev; + this.parent = null; + this.mount = null; + if (!parent) { + parent = this; // root node sets parent to itself + } + this.parent = parent; + this.mount = parent.mount; + FS.hashAddNode(this); + }; + + // compatibility + var readMode = {{{ cDefine('S_IRUGO') }}} | {{{ cDefine('S_IXUGO') }}}; + var writeMode = {{{ cDefine('S_IWUGO') }}}; + + FS.FSNode.prototype = {}; + + // NOTE we must use Object.defineProperties instead of individual calls to + // Object.defineProperty in order to make closure compiler happy + Object.defineProperties(FS.FSNode.prototype, { + read: { + get: function() { return (this.mode & readMode) === readMode; }, + set: function(val) { val ? this.mode |= readMode : this.mode &= ~readMode; } + }, + write: { + get: function() { return (this.mode & writeMode) === writeMode; }, + set: function(val) { val ? this.mode |= writeMode : this.mode &= ~writeMode; } + }, + isFolder: { + get: function() { return FS.isDir(this.mode); }, + }, + isDevice: { + get: function() { return FS.isChrdev(this.mode); }, + }, + }); + } + return new FS.FSNode(parent, name, mode, rdev); }, destroyNode: function(node) { FS.hashRemoveNode(node); @@ -351,24 +360,28 @@ mergeInto(LibraryManager.library, { // object isn't directly passed in. not possible until // SOCKFS is completed. createStream: function(stream, fd_start, fd_end) { + if (!FS.FSStream) { + FS.FSStream = {}; + // compatibility + Object.defineProperties(FS.FSStream, { + object: { + get: function() { return this.node; }, + set: function(val) { this.node = val; } + }, + isRead: { + get: function() { return (this.flags & {{{ cDefine('O_ACCMODE') }}}) !== {{{ cDefine('O_WRONLY') }}}; } + }, + isWrite: { + get: function() { return (this.flags & {{{ cDefine('O_ACCMODE') }}}) !== {{{ cDefine('O_RDONLY') }}}; } + }, + isAppend: { + get: function() { return (this.flags & {{{ cDefine('O_APPEND') }}}); } + } + }); + } + stream.prototype = FS.FSStream; var fd = FS.nextfd(fd_start, fd_end); stream.fd = fd; - // compatibility - Object.defineProperties(stream, { - object: { - get: function() { return stream.node; }, - set: function(val) { stream.node = val; } - }, - isRead: { - get: function() { return (stream.flags & {{{ cDefine('O_ACCMODE') }}}) !== {{{ cDefine('O_WRONLY') }}}; } - }, - isWrite: { - get: function() { return (stream.flags & {{{ cDefine('O_ACCMODE') }}}) !== {{{ cDefine('O_RDONLY') }}}; } - }, - isAppend: { - get: function() { return (stream.flags & {{{ cDefine('O_APPEND') }}}); } - } - }); FS.streams[fd] = stream; return stream; }, @@ -771,7 +784,6 @@ mergeInto(LibraryManager.library, { }); }, open: function(path, flags, mode, fd_start, fd_end) { - path = PATH.normalize(path); flags = typeof flags === 'string' ? FS.modeStringToFlags(flags) : flags; mode = typeof mode === 'undefined' ? 0666 : mode; if ((flags & {{{ cDefine('O_CREAT') }}})) { @@ -780,13 +792,18 @@ mergeInto(LibraryManager.library, { mode = 0; } var node; - try { - var lookup = FS.lookupPath(path, { - follow: !(flags & {{{ cDefine('O_NOFOLLOW') }}}) - }); - node = lookup.node; - } catch (e) { - // ignore + if (typeof path === 'object') { + node = path; + } else { + path = PATH.normalize(path); + try { + var lookup = FS.lookupPath(path, { + follow: !(flags & {{{ cDefine('O_NOFOLLOW') }}}) + }); + node = lookup.node; + } catch (e) { + // ignore + } } // perhaps we need to create the node if ((flags & {{{ cDefine('O_CREAT') }}})) { @@ -1079,6 +1096,11 @@ mergeInto(LibraryManager.library, { }; FS.ErrnoError.prototype = new Error(); FS.ErrnoError.prototype.constructor = FS.ErrnoError; + // Some errors may happen quite a bit, to avoid overhead we reuse them (and suffer a lack of stack info) + [ERRNO_CODES.ENOENT].forEach(function(code) { + FS.genericErrors[code] = new FS.ErrnoError(code); + FS.genericErrors[code].stack = '<generic error, no stack>'; + }); }, staticInit: function() { FS.ensureErrnoError(); @@ -1173,7 +1195,7 @@ mergeInto(LibraryManager.library, { return ret; }, createFolder: function(parent, name, canRead, canWrite) { - var path = PATH.join(typeof parent === 'string' ? parent : FS.getPath(parent), name); + var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name); var mode = FS.getMode(canRead, canWrite); return FS.mkdir(path, mode); }, @@ -1183,7 +1205,7 @@ mergeInto(LibraryManager.library, { while (parts.length) { var part = parts.pop(); if (!part) continue; - var current = PATH.join(parent, part); + var current = PATH.join2(parent, part); try { FS.mkdir(current); } catch (e) { @@ -1194,12 +1216,12 @@ mergeInto(LibraryManager.library, { return current; }, createFile: function(parent, name, properties, canRead, canWrite) { - var path = PATH.join(typeof parent === 'string' ? parent : FS.getPath(parent), name); + var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name); var mode = FS.getMode(canRead, canWrite); return FS.create(path, mode); }, createDataFile: function(parent, name, data, canRead, canWrite, canOwn) { - var path = name ? PATH.join(typeof parent === 'string' ? parent : FS.getPath(parent), name) : parent; + var path = name ? PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name) : parent; var mode = FS.getMode(canRead, canWrite); var node = FS.create(path, mode); if (data) { @@ -1209,16 +1231,16 @@ mergeInto(LibraryManager.library, { data = arr; } // make sure we can write to the file - FS.chmod(path, mode | {{{ cDefine('S_IWUGO') }}}); - var stream = FS.open(path, 'w'); + FS.chmod(node, mode | {{{ cDefine('S_IWUGO') }}}); + var stream = FS.open(node, 'w'); FS.write(stream, data, 0, data.length, 0, canOwn); FS.close(stream); - FS.chmod(path, mode); + FS.chmod(node, mode); } return node; }, createDevice: function(parent, name, input, output) { - var path = PATH.join(typeof parent === 'string' ? parent : FS.getPath(parent), name); + var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name); var mode = FS.getMode(!!input, !!output); if (!FS.createDevice.major) FS.createDevice.major = 64; var dev = FS.makedev(FS.createDevice.major++, 0); @@ -1272,7 +1294,7 @@ mergeInto(LibraryManager.library, { return FS.mkdev(path, mode, dev); }, createLink: function(parent, name, target, canRead, canWrite) { - var path = PATH.join(typeof parent === 'string' ? parent : FS.getPath(parent), name); + var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name); return FS.symlink(target, path); }, // Makes sure a file's contents are loaded. Returns whether the file has @@ -1462,7 +1484,7 @@ mergeInto(LibraryManager.library, { Browser.init(); // TODO we should allow people to just pass in a complete filename instead // of parent and name being that we just join them anyways - var fullname = name ? PATH.resolve(PATH.join(parent, name)) : parent; + var fullname = name ? PATH.resolve(PATH.join2(parent, name)) : parent; function processData(byteArray) { function finish(byteArray) { if (!dontCreateFile) { diff --git a/src/library_gl.js b/src/library_gl.js index 1ea8efc2..6ae20185 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -42,6 +42,8 @@ var LibraryGL = { uniformTable: {}, // name => uniform ID. the uID must be identical until relinking, cannot create a new uID each call to glGetUniformLocation + stringCache: {}, + packAlignment: 4, // default alignment is 4 bytes unpackAlignment: 4, // default alignment is 4 bytes @@ -240,7 +242,9 @@ var LibraryGL = { sizePerPixel = 2; break; case 0x1406 /* GL_FLOAT */: +#if ASSERTIONS assert(GL.floatExt, 'Must have OES_texture_float to use float textures'); +#endif switch (format) { case 0x1907 /* GL_RGB */: sizePerPixel = 3*4; @@ -497,11 +501,14 @@ var LibraryGL = { glGetString__sig: 'ii', glGetString: function(name_) { + if (GL.stringCache[name_]) return GL.stringCache[name_]; + var ret; switch(name_) { case 0x1F00 /* GL_VENDOR */: case 0x1F01 /* GL_RENDERER */: case 0x1F02 /* GL_VERSION */: - return allocate(intArrayFromString(Module.ctx.getParameter(name_)), 'i8', ALLOC_NORMAL); + ret = allocate(intArrayFromString(Module.ctx.getParameter(name_)), 'i8', ALLOC_NORMAL); + break; case 0x1F03 /* GL_EXTENSIONS */: var exts = Module.ctx.getSupportedExtensions(); var gl_exts = []; @@ -509,12 +516,16 @@ var LibraryGL = { gl_exts.push(exts[i]); gl_exts.push("GL_" + exts[i]); } - return allocate(intArrayFromString(gl_exts.join(' ')), 'i8', ALLOC_NORMAL); // XXX this leaks! TODO: Cache all results like this in library_gl.js to be clean and nice and avoid leaking. + ret = allocate(intArrayFromString(gl_exts.join(' ')), 'i8', ALLOC_NORMAL); + break; case 0x8B8C /* GL_SHADING_LANGUAGE_VERSION */: - return allocate(intArrayFromString('OpenGL ES GLSL 1.00 (WebGL)'), 'i8', ALLOC_NORMAL); + ret = allocate(intArrayFromString('OpenGL ES GLSL 1.00 (WebGL)'), 'i8', ALLOC_NORMAL); + break; default: throw 'Failure: Invalid glGetString value: ' + name_; } + GL.stringCache[name_] = ret; + return ret; }, glGetIntegerv__sig: 'vii', @@ -680,7 +691,9 @@ var LibraryGL = { glCompressedTexImage2D__sig: 'viiiiiiii', glCompressedTexImage2D: function(target, level, internalFormat, width, height, border, imageSize, data) { +#if ASSERTIONS assert(GL.compressionExt); +#endif if (data) { data = {{{ makeHEAPView('U8', 'data', 'data+imageSize') }}}; } else { @@ -691,7 +704,9 @@ var LibraryGL = { glCompressedTexSubImage2D__sig: 'viiiiiiiii', glCompressedTexSubImage2D: function(target, level, xoffset, yoffset, width, height, format, imageSize, data) { +#if ASSERTIONS assert(GL.compressionExt); +#endif if (data) { data = {{{ makeHEAPView('U8', 'data', 'data+imageSize') }}}; } else { @@ -725,7 +740,9 @@ var LibraryGL = { glReadPixels__sig: 'viiiiiii', glReadPixels: function(x, y, width, height, format, type, pixels) { +#if ASSERTIONS assert(type == 0x1401 /* GL_UNSIGNED_BYTE */); +#endif var sizePerPixel; switch (format) { case 0x1907 /* GL_RGB */: @@ -1357,7 +1374,9 @@ var LibraryGL = { {{{ makeSetValue('count', '0', 'len', 'i32') }}}; for (var i = 0; i < len; ++i) { var id = GL.shaders.indexOf(result[i]); +#if ASSERTIONS assert(id !== -1, 'shader not bound to local id'); +#endif {{{ makeSetValue('shaders', 'i*4', 'id', 'i32') }}}; } }, @@ -1774,17 +1793,17 @@ var LibraryGL = { return; } case 0x8088: { // GL_TEXTURE_COORD_ARRAY_SIZE - var attribute = GLImmediate.clientAttributes[GLImmediate.TEXTURE0]; + var attribute = GLImmediate.clientAttributes[GLImmediate.TEXTURE0 + GLImmediate.clientActiveTexture]; {{{ makeSetValue('params', '0', 'attribute ? attribute.size : 0', 'i32') }}}; return; } case 0x8089: { // GL_TEXTURE_COORD_ARRAY_TYPE - var attribute = GLImmediate.clientAttributes[GLImmediate.TEXTURE0]; + var attribute = GLImmediate.clientAttributes[GLImmediate.TEXTURE0 + GLImmediate.clientActiveTexture]; {{{ makeSetValue('params', '0', 'attribute ? attribute.type : 0', 'i32') }}}; return; } case 0x808A: { // GL_TEXTURE_COORD_ARRAY_STRIDE - var attribute = GLImmediate.clientAttributes[GLImmediate.TEXTURE0]; + var attribute = GLImmediate.clientAttributes[GLImmediate.TEXTURE0 + GLImmediate.clientActiveTexture]; {{{ makeSetValue('params', '0', 'attribute ? attribute.stride : 0', 'i32') }}}; return; } @@ -1794,13 +1813,16 @@ var LibraryGL = { var glGetString = _glGetString; _glGetString = function(name_) { + if (GL.stringCache[name_]) return GL.stringCache[name_]; switch(name_) { case 0x1F03 /* GL_EXTENSIONS */: // Add various extensions that we can support - return allocate(intArrayFromString(Module.ctx.getSupportedExtensions().join(' ') + + var ret = allocate(intArrayFromString(Module.ctx.getSupportedExtensions().join(' ') + ' GL_EXT_texture_env_combine GL_ARB_texture_env_crossbar GL_ATI_texture_env_combine3 GL_NV_texture_env_combine4 GL_EXT_texture_env_dot3 GL_ARB_multitexture GL_ARB_vertex_buffer_object GL_EXT_framebuffer_object GL_ARB_vertex_program GL_ARB_fragment_program GL_ARB_shading_language_100 GL_ARB_shader_objects GL_ARB_vertex_shader GL_ARB_fragment_shader GL_ARB_texture_cube_map GL_EXT_draw_range_elements' + (GL.compressionExt ? ' GL_ARB_texture_compression GL_EXT_texture_compression_s3tc' : '') + (GL.anisotropicExt ? ' GL_EXT_texture_filter_anisotropic' : '') ), 'i8', ALLOC_NORMAL); + GL.stringCache[name_] = ret; + return ret; } return glGetString(name_); }; @@ -2013,7 +2035,9 @@ var LibraryGL = { glBindBuffer(target, buffer); if (target == Module.ctx.ARRAY_BUFFER) { if (GLEmulation.currentVao) { +#if ASSERTIONS assert(GLEmulation.currentVao.arrayBuffer == buffer || GLEmulation.currentVao.arrayBuffer == 0 || buffer == 0, 'TODO: support for multiple array buffers in vao'); +#endif GLEmulation.currentVao.arrayBuffer = buffer; } } else if (target == Module.ctx.ELEMENT_ARRAY_BUFFER) { @@ -2153,7 +2177,9 @@ var LibraryGL = { glBindProgram__sig: 'vii', glBindProgram: function(type, id) { +#if ASSERTIONS assert(id == 0); +#endif }, glGetPointerv: function(name, p) { @@ -2164,7 +2190,7 @@ var LibraryGL = { case 0x8090: // GL_COLOR_ARRAY_POINTER attribute = GLImmediate.clientAttributes[GLImmediate.COLOR]; break; case 0x8092: // GL_TEXTURE_COORD_ARRAY_POINTER - attribute = GLImmediate.clientAttributes[GLImmediate.TEXTURE0]; break; + attribute = GLImmediate.clientAttributes[GLImmediate.TEXTURE0 + GLImmediate.clientActiveTexture]; break; default: throw 'TODO: glGetPointerv for ' + name; } {{{ makeSetValue('p', '0', 'attribute ? attribute.pointer : 0', 'i32') }}}; @@ -2832,9 +2858,9 @@ var LibraryGL = { } else if (gl) { maxTexUnits = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS); } - +#if ASSERTIONS assert(maxTexUnits > 0); - +#endif s_texUnits = []; for (var i = 0; i < maxTexUnits; i++) { s_texUnits.push(new CTexUnit()); @@ -2893,9 +2919,10 @@ var LibraryGL = { }, getTexUnitType: function(texUnitID) { +#if ASSERTIONS assert(texUnitID >= 0 && texUnitID < s_texUnits.length); - +#endif return s_texUnits[texUnitID].getTexType(); }, @@ -3198,9 +3225,13 @@ var LibraryGL = { if (!GL.immediate.enabledClientAttributes[texAttribName]) continue; +#if ASSERTIONS if (!useCurrProgram) { - assert(GL.immediate.TexEnvJIT.getTexUnitType(i) != 0, "GL_TEXTURE" + i + " coords are supplied, but that texture unit is disabled in the fixed-function pipeline."); + if (GL.immediate.TexEnvJIT.getTexUnitType(i) == 0) { + Runtime.warnOnce("GL_TEXTURE" + i + " coords are supplied, but that texture unit is disabled in the fixed-function pipeline."); + } } +#endif textureSizes[i] = GL.immediate.clientAttributes[texAttribName].size; textureTypes[i] = GL.immediate.clientAttributes[texAttribName].type; @@ -3417,7 +3448,9 @@ var LibraryGL = { if (!GL.currArrayBuffer) { var start = GL.immediate.firstVertex*GL.immediate.stride; var end = GL.immediate.lastVertex*GL.immediate.stride; +#if ASSERTIONS assert(end <= GL.MAX_TEMP_BUFFER_SIZE, 'too much vertex data'); +#endif arrayBuffer = GL.tempVertexBuffers[GL.tempBufferIndexLookup[end]]; // TODO: consider using the last buffer we bound, if it was larger. downside is larger buffer, but we might avoid rebinding and preparing } else { @@ -3586,10 +3619,10 @@ var LibraryGL = { Module.ctx.drawElements(mode, count, type, indices); return; } +#if ASSERTIONS if (!GL.currElementArrayBuffer) { assert(type == Module.ctx.UNSIGNED_SHORT); // We can only emulate buffers of this kind, for now } -#if ASSERTIONS console.log("DrawElements doesn't actually prepareClientAttributes properly."); #endif GL.immediate.prepareClientAttributes(count, false); @@ -3797,13 +3830,17 @@ var LibraryGL = { if (!attribute) break; attribute.offset = attribute.pointer - start; if (attribute.offset > bytes) { // ensure we start where we should +#if ASSERTIONS assert((attribute.offset - bytes)%4 == 0); // XXX assuming 4-alignment +#endif bytes += attribute.offset - bytes; } bytes += attribute.size * GL.byteSizeByType[attribute.type - GL.byteSizeByTypeRoot]; if (bytes % 4 != 0) bytes += 4 - (bytes % 4); // XXX assuming 4-alignment } +#if ASSERTIONS assert(beginEnd || bytes <= stride); // if not begin-end, explicit stride should make sense with total byte size +#endif if (bytes < stride) { // ensure the size is that of the stride bytes = stride; } @@ -3830,18 +3867,21 @@ var LibraryGL = { // Generate index data in a format suitable for GLES 2.0/WebGL var numVertexes = 4 * this.vertexCounter / GL.immediate.stride; +#if ASSERTIONS assert(numVertexes % 1 == 0, "`numVertexes` must be an integer."); - +#endif var emulatedElementArrayBuffer = false; var numIndexes = 0; if (numProvidedIndexes) { numIndexes = numProvidedIndexes; if (!GL.currArrayBuffer && GL.immediate.firstVertex > GL.immediate.lastVertex) { // Figure out the first and last vertex from the index data +#if ASSERTIONS assert(!GL.currElementArrayBuffer); // If we are going to upload array buffer data, we need to find which range to // upload based on the indices. If they are in a buffer on the GPU, that is very // inconvenient! So if you do not have an array buffer, you should also not have // an element array buffer. But best is to use both buffers! +#endif for (var i = 0; i < numProvidedIndexes; i++) { var currIndex = {{{ makeGetValue('ptr', 'i*2', 'i16', null, 1) }}}; GL.immediate.firstVertex = Math.min(GL.immediate.firstVertex, currIndex); @@ -3850,7 +3890,9 @@ var LibraryGL = { } if (!GL.currElementArrayBuffer) { // If no element array buffer is bound, then indices is a literal pointer to clientside data +#if ASSERTIONS assert(numProvidedIndexes << 1 <= GL.MAX_TEMP_BUFFER_SIZE, 'too many immediate mode indexes (a)'); +#endif var indexBuffer = GL.tempIndexBuffers[GL.tempBufferIndexLookup[numProvidedIndexes << 1]]; Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, indexBuffer); Module.ctx.bufferSubData(Module.ctx.ELEMENT_ARRAY_BUFFER, 0, {{{ makeHEAPView('U16', 'ptr', 'ptr + (numProvidedIndexes << 1)') }}}); @@ -3862,11 +3904,15 @@ var LibraryGL = { // GL.immediate.firstVertex is the first vertex we want. Quad indexes are in the pattern // 0 1 2, 0 2 3, 4 5 6, 4 6 7, so we need to look at index firstVertex * 1.5 to see it. // Then since indexes are 2 bytes each, that means 3 +#if ASSERTIONS assert(GL.immediate.firstVertex % 4 == 0); +#endif ptr = GL.immediate.firstVertex*3; var numQuads = numVertexes / 4; numIndexes = numQuads * 6; // 0 1 2, 0 2 3 pattern +#if ASSERTIONS assert(ptr + (numIndexes << 1) <= GL.MAX_TEMP_BUFFER_SIZE, 'too many immediate mode indexes (b)'); +#endif Module.ctx.bindBuffer(Module.ctx.ELEMENT_ARRAY_BUFFER, GL.tempQuadIndexBuffer); emulatedElementArrayBuffer = true; } diff --git a/src/library_glfw.js b/src/library_glfw.js index b0519e39..647d4bb6 100644 --- a/src/library_glfw.js +++ b/src/library_glfw.js @@ -355,7 +355,9 @@ var LibraryGLFW = { } var contextAttributes = { - antialias: (GLFW.params[0x00020013] > 1) //GLFW_FSAA_SAMPLES + antialias: (GLFW.params[0x00020013] > 1), //GLFW_FSAA_SAMPLES + depth: (GLFW.params[0x00020009] > 0), //GLFW_DEPTH_BITS + stencil: (GLFW.params[0x0002000A] > 0) //GLFW_STENCIL_BITS } Module.ctx = Browser.createContext(Module['canvas'], true, true, contextAttributes); return 1; //GL_TRUE diff --git a/src/library_glut.js b/src/library_glut.js index 722ea85c..fefe7bd3 100644 --- a/src/library_glut.js +++ b/src/library_glut.js @@ -427,7 +427,9 @@ var LibraryGLUT = { glutCreateWindow__deps: ['$Browser'], glutCreateWindow: function(name) { var contextAttributes = { - antialias: ((GLUT.initDisplayMode & 0x0080 /*GLUT_MULTISAMPLE*/) != 0) + antialias: ((GLUT.initDisplayMode & 0x0080 /*GLUT_MULTISAMPLE*/) != 0), + depth: ((GLUT.initDisplayMode & 0x0010 /*GLUT_DEPTH*/) != 0), + stencil: ((GLUT.initDisplayMode & 0x0020 /*GLUT_STENCIL*/) != 0) }; Module.ctx = Browser.createContext(Module['canvas'], true, true, contextAttributes); return Module.ctx ? 1 /* a new GLUT window ID for the created context */ : 0 /* failure */; diff --git a/src/library_idbfs.js b/src/library_idbfs.js index 9031bad8..ab55673f 100644 --- a/src/library_idbfs.js +++ b/src/library_idbfs.js @@ -130,7 +130,7 @@ mergeInto(LibraryManager.library, { }; var toAbsolute = function(root) { return function(p) { - return PATH.join(root, p); + return PATH.join2(root, p); } }; diff --git a/src/library_memfs.js b/src/library_memfs.js index 94fd767e..d3148d8b 100644 --- a/src/library_memfs.js +++ b/src/library_memfs.js @@ -1,6 +1,8 @@ mergeInto(LibraryManager.library, { $MEMFS__deps: ['$FS'], $MEMFS: { + ops_table: null, + // content modes CONTENT_OWNING: 1, // contains a subarray into the heap, and we own it, without copying (note: someone else needs to free() it, if that is necessary) CONTENT_FLEXIBLE: 2, // has been modified or never set to anything, and is a flexible js array that can grow/shrink @@ -13,51 +15,71 @@ mergeInto(LibraryManager.library, { // no supported throw new FS.ErrnoError(ERRNO_CODES.EPERM); } + if (!MEMFS.ops_table) { + MEMFS.ops_table = { + dir: { + node: { + getattr: MEMFS.node_ops.getattr, + setattr: MEMFS.node_ops.setattr, + lookup: MEMFS.node_ops.lookup, + mknod: MEMFS.node_ops.mknod, + mknod: MEMFS.node_ops.mknod, + rename: MEMFS.node_ops.rename, + unlink: MEMFS.node_ops.unlink, + rmdir: MEMFS.node_ops.rmdir, + readdir: MEMFS.node_ops.readdir, + symlink: MEMFS.node_ops.symlink + }, + stream: { + llseek: MEMFS.stream_ops.llseek + } + }, + file: { + node: { + getattr: MEMFS.node_ops.getattr, + setattr: MEMFS.node_ops.setattr + }, + stream: { + llseek: MEMFS.stream_ops.llseek, + read: MEMFS.stream_ops.read, + write: MEMFS.stream_ops.write, + allocate: MEMFS.stream_ops.allocate, + mmap: MEMFS.stream_ops.mmap + } + }, + link: { + node: { + getattr: MEMFS.node_ops.getattr, + setattr: MEMFS.node_ops.setattr, + readlink: MEMFS.node_ops.readlink + }, + stream: {} + }, + chrdev: { + node: { + getattr: MEMFS.node_ops.getattr, + setattr: MEMFS.node_ops.setattr + }, + stream: FS.chrdev_stream_ops + }, + }; + } var node = FS.createNode(parent, name, mode, dev); if (FS.isDir(node.mode)) { - node.node_ops = { - getattr: MEMFS.node_ops.getattr, - setattr: MEMFS.node_ops.setattr, - lookup: MEMFS.node_ops.lookup, - mknod: MEMFS.node_ops.mknod, - mknod: MEMFS.node_ops.mknod, - rename: MEMFS.node_ops.rename, - unlink: MEMFS.node_ops.unlink, - rmdir: MEMFS.node_ops.rmdir, - readdir: MEMFS.node_ops.readdir, - symlink: MEMFS.node_ops.symlink - }; - node.stream_ops = { - llseek: MEMFS.stream_ops.llseek - }; + node.node_ops = MEMFS.ops_table.dir.node; + node.stream_ops = MEMFS.ops_table.dir.stream; node.contents = {}; } else if (FS.isFile(node.mode)) { - node.node_ops = { - getattr: MEMFS.node_ops.getattr, - setattr: MEMFS.node_ops.setattr - }; - node.stream_ops = { - llseek: MEMFS.stream_ops.llseek, - read: MEMFS.stream_ops.read, - write: MEMFS.stream_ops.write, - allocate: MEMFS.stream_ops.allocate, - mmap: MEMFS.stream_ops.mmap - }; + node.node_ops = MEMFS.ops_table.file.node; + node.stream_ops = MEMFS.ops_table.file.stream; node.contents = []; node.contentMode = MEMFS.CONTENT_FLEXIBLE; } else if (FS.isLink(node.mode)) { - node.node_ops = { - getattr: MEMFS.node_ops.getattr, - setattr: MEMFS.node_ops.setattr, - readlink: MEMFS.node_ops.readlink - }; - node.stream_ops = {}; + node.node_ops = MEMFS.ops_table.link.node; + node.stream_ops = MEMFS.ops_table.link.stream; } else if (FS.isChrdev(node.mode)) { - node.node_ops = { - getattr: MEMFS.node_ops.getattr, - setattr: MEMFS.node_ops.setattr - }; - node.stream_ops = FS.chrdev_stream_ops; + node.node_ops = MEMFS.ops_table.chrdev.node; + node.stream_ops = MEMFS.ops_table.chrdev.stream; } node.timestamp = Date.now(); // add the new node to the parent @@ -117,7 +139,7 @@ mergeInto(LibraryManager.library, { } }, lookup: function(parent, name) { - throw new FS.ErrnoError(ERRNO_CODES.ENOENT); + throw FS.genericErrors[ERRNO_CODES.ENOENT]; }, mknod: function(parent, name, mode, dev) { return MEMFS.createNode(parent, name, mode, dev); @@ -200,10 +222,12 @@ mergeInto(LibraryManager.library, { #if USE_TYPED_ARRAYS == 2 if (length && contents.length === 0 && position === 0 && buffer.subarray) { // just replace it with the new data +#if ASSERTIONS assert(buffer.length); - if (canOwn && buffer.buffer === HEAP8.buffer && offset === 0) { - node.contents = buffer; // this is a subarray of the heap, and we can own it - node.contentMode = MEMFS.CONTENT_OWNING; +#endif + if (canOwn && offset === 0) { + node.contents = buffer; // this could be a subarray of Emscripten HEAP, or allocated from some other source. + node.contentMode = (buffer.buffer === HEAP8.buffer) ? MEMFS.CONTENT_OWNING : MEMFS.CONTENT_FIXED; } else { node.contents = new Uint8Array(buffer.subarray(offset, offset+length)); node.contentMode = MEMFS.CONTENT_FIXED; diff --git a/src/library_nodefs.js b/src/library_nodefs.js index 2be54076..7686f3f2 100644 --- a/src/library_nodefs.js +++ b/src/library_nodefs.js @@ -134,7 +134,7 @@ mergeInto(LibraryManager.library, { } }, lookup: function (parent, name) { - var path = PATH.join(NODEFS.realPath(parent), name); + var path = PATH.join2(NODEFS.realPath(parent), name); var mode = NODEFS.getMode(path); return NODEFS.createNode(parent, name, mode); }, @@ -156,7 +156,7 @@ mergeInto(LibraryManager.library, { }, rename: function (oldNode, newDir, newName) { var oldPath = NODEFS.realPath(oldNode); - var newPath = PATH.join(NODEFS.realPath(newDir), newName); + var newPath = PATH.join2(NODEFS.realPath(newDir), newName); try { fs.renameSync(oldPath, newPath); } catch (e) { @@ -165,7 +165,7 @@ mergeInto(LibraryManager.library, { } }, unlink: function(parent, name) { - var path = PATH.join(NODEFS.realPath(parent), name); + var path = PATH.join2(NODEFS.realPath(parent), name); try { fs.unlinkSync(path); } catch (e) { @@ -174,7 +174,7 @@ mergeInto(LibraryManager.library, { } }, rmdir: function(parent, name) { - var path = PATH.join(NODEFS.realPath(parent), name); + var path = PATH.join2(NODEFS.realPath(parent), name); try { fs.rmdirSync(path); } catch (e) { @@ -192,7 +192,7 @@ mergeInto(LibraryManager.library, { } }, symlink: function(parent, newName, oldPath) { - var newPath = PATH.join(NODEFS.realPath(parent), newName); + var newPath = PATH.join2(NODEFS.realPath(parent), newName); try { fs.symlinkSync(oldPath, newPath); } catch (e) { @@ -283,4 +283,4 @@ mergeInto(LibraryManager.library, { } } } -});
\ No newline at end of file +}); diff --git a/src/library_path.js b/src/library_path.js index 09808acd..f00a7586 100644 --- a/src/library_path.js +++ b/src/library_path.js @@ -59,26 +59,22 @@ mergeInto(LibraryManager.library, { } return root + dir; }, - basename: function(path, ext) { + basename: function(path) { // EMSCRIPTEN return '/'' for '/', not an empty string if (path === '/') return '/'; - var f = PATH.splitPath(path)[2]; - if (ext && f.substr(-1 * ext.length) === ext) { - f = f.substr(0, f.length - ext.length); - } - return f; + var lastSlash = path.lastIndexOf('/'); + if (lastSlash === -1) return path; + return path.substr(lastSlash+1); }, extname: function(path) { return PATH.splitPath(path)[3]; }, join: function() { var paths = Array.prototype.slice.call(arguments, 0); - return PATH.normalize(paths.filter(function(p, index) { - if (typeof p !== 'string') { - throw new TypeError('Arguments to path.join must be strings'); - } - return p; - }).join('/')); + return PATH.normalize(paths.join('/')); + }, + join2: function(l, r) { + return PATH.normalize(l + '/' + r); }, resolve: function() { var resolvedPath = '', @@ -134,4 +130,4 @@ mergeInto(LibraryManager.library, { return outputParts.join('/'); } } -});
\ No newline at end of file +}); diff --git a/src/library_sdl.js b/src/library_sdl.js index 857ab7d4..04a66351 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -153,24 +153,30 @@ var LibrarySDL = { 120: 27, 121: 28, 122: 29, // Z - 44: 54, // comma - 46: 55, // period - 47: 56, // slash - 49: 30, // 1 - 50: 31, - 51: 32, - 52: 33, - 53: 34, - 54: 35, - 55: 36, - 56: 37, - 57: 38, // 9 - 48: 39, // 0 - 13: 40, // return - 9: 43, // tab - 27: 41, // escape - 32: 44, // space - 92: 49, // backslash + 49: 30, // 1 + 50: 31, + 51: 32, + 52: 33, + 53: 34, + 54: 35, + 55: 36, + 56: 37, + 57: 38, // 9 + 48: 39, // 0 + 13: 40, // return + 27: 41, // escape + 8: 42, // backspace + 9: 43, // tab + 32: 44, // space + 61: 46, // equals + 91: 47, // left bracket + 93: 48, // right bracket + 92: 49, // backslash + 59: 51, // ; + 96: 52, // apostrophe + 44: 54, // comma + 46: 55, // period + 47: 56, // slash 305: 224, // ctrl 308: 226, // alt }, @@ -254,9 +260,13 @@ var LibrarySDL = { } var webGLContextAttributes = { - antialias: ((SDL.glAttributes[13 /*SDL_GL_MULTISAMPLEBUFFERS*/] != 0) && (SDL.glAttributes[14 /*SDL_GL_MULTISAMPLESAMPLES*/] > 1)) + antialias: ((SDL.glAttributes[13 /*SDL_GL_MULTISAMPLEBUFFERS*/] != 0) && (SDL.glAttributes[14 /*SDL_GL_MULTISAMPLESAMPLES*/] > 1)), + depth: (SDL.glAttributes[6 /*SDL_GL_DEPTH_SIZE*/] > 0), + stencil: (SDL.glAttributes[7 /*SDL_GL_STENCIL_SIZE*/] > 0) }; + var ctx = Browser.createContext(canvas, useWebGL, usePageCanvas, webGLContextAttributes); + SDL.surfaces[surf] = { width: width, height: height, diff --git a/src/parseTools.js b/src/parseTools.js index 4dbabbb0..6179e285 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -157,6 +157,10 @@ function isStructType(type) { return type[0] == '%'; } +function isVectorType(type) { + return type[type.length-1] === '>'; +} + function isStructuralType(type) { return /^{ ?[^}]* ?}$/.test(type); // { i32, i8 } etc. - anonymous struct types } @@ -215,8 +219,22 @@ function isIdenticallyImplemented(type1, type2) { } function isIllegalType(type) { - var bits = getBits(type); - return bits > 0 && (bits >= 64 || !isPowerOfTwo(bits)); + switch (type) { + case 'i1': + case 'i8': + case 'i16': + case 'i32': + case 'float': + case 'double': + case 'rawJS': + case '<2 x float>': + case '<4 x float>': + case '<2 x i32>': + case '<4 x i32>': + case 'void': return false; + } + if (!type || type[type.length-1] === '*') return false; + return true; } function isVoidType(type) { @@ -287,6 +305,9 @@ function getReturnType(type) { if (pointingLevels(type) > 1) return '*'; // the type of a call can be either the return value, or the entire function. ** or more means it is a return value var lastOpen = type.lastIndexOf('('); if (lastOpen > 0) { + // handle things like void (i32)* (i32, void (i32)*)* + var closeStar = type.indexOf(')*'); + if (closeStar > 0 && closeStar < type.length-2) lastOpen = closeStar+3; return type.substr(0, lastOpen-1); } return type; @@ -328,28 +349,29 @@ function getVectorSize(type) { return parseInt(type.substring(1, type.indexOf(' '))); } -function getVectorBaseType(type) { +function getVectorNativeType(type) { Types.usesSIMD = true; switch (type) { case '<2 x float>': case '<4 x float>': return 'float'; case '<2 x i32>': - case '<4 x i32>': return 'uint'; + case '<4 x i32>': return 'i32'; default: throw 'unknown vector type ' + type; } } -function getVectorNativeType(type) { - Types.usesSIMD = true; +function getSIMDName(type) { switch (type) { - case '<2 x float>': - case '<4 x float>': return 'float'; - case '<2 x i32>': - case '<4 x i32>': return 'i32'; - default: throw 'unknown vector type ' + type; + case 'i32': return 'uint'; + case 'float': return 'float'; + default: throw 'getSIMDName ' + type; } } +function getVectorBaseType(type) { + return getSIMDName(getVectorNativeType(type)); +} + function addIdent(token) { token.ident = token.text; return token; @@ -465,29 +487,13 @@ function parseParamTokens(params) { Types.needAnalysis[ret[ret.length-1].type] = 0; anonymousIndex ++; } - } else if (segment[1].text in PARSABLE_LLVM_FUNCTIONS) { - ret.push(parseLLVMFunctionCall(segment)); - } else if (segment[1].text === 'blockaddress') { - ret.push(parseBlockAddress(segment)); - } else if (segment[1].type && segment[1].type == '{') { - ret.push(parseLLVMSegment(segment)); } else { if (segment[2] && segment[2].text == 'to') { // part of bitcast params segment = segment.slice(0, 2); } - while (segment.length > 2) { - segment[0].text += segment[1].text; - segment.splice(1, 1); // TODO: merge tokens nicely - } - var num = isNumber(segment[1].text) || (segment[1].text[0] === '0'); // handle 0x... as well - var ident = parseNumerical(segment[1].text, segment[0].text); - if (!num) ident = toNiceIdent(ident); - ret.push({ - intertype: 'value', - type: segment[0].text, - ident: ident - }); - Types.needAnalysis[removeAllPointing(ret[ret.length-1].type)] = 0; + var parsed = parseLLVMSegment(segment); + if (parsed.intertype === 'value' && !isIllegalType(parsed.type)) parsed.ident = parseNumerical(parsed.ident, parsed.type); + ret.push(parsed); } ret[ret.length-1].byVal = byVal; } @@ -561,25 +567,6 @@ function sortGlobals(globals) { }); } -function finalizeParam(param) { - if (param.intertype in PARSABLE_LLVM_FUNCTIONS) { - return finalizeLLVMFunctionCall(param); - } else if (param.intertype === 'blockaddress') { - return finalizeBlockAddress(param); - } else if (param.intertype === 'jsvalue') { - return param.ident; - } else { - if (param.type == 'i64' && USE_TYPED_ARRAYS == 2) { - return parseI64Constant(param.ident); - } - var ret = param.ident; - if (ret in Variables.globals) { - ret = makeGlobalUse(ret); - } - return ret; - } -} - // Segment ==> Parameter function parseLLVMSegment(segment) { var type; @@ -1012,11 +999,9 @@ function getOldLabel(label) { } function calcAllocatedSize(type) { - if (pointingLevels(type) == 0 && isStructType(type)) { - return Types.types[type].flatSize; // makeEmptyStruct(item.allocatedType).length; - } else { - return Runtime.getNativeTypeSize(type); // We can really get away with '1', though, at least on the stack... - } + var ret = Runtime.getNativeTypeSize(type); + if (ret) return ret; + return Types.types[type].flatSize; // known type } // Generates the type signature for a structure, for each byte, the type that is there. @@ -1823,7 +1808,7 @@ function makeGetSlabs(ptr, type, allowMultiple, unsigned) { switch(type) { case 'i1': case 'i8': return [unsigned ? 'HEAPU8' : 'HEAP8']; break; case 'i16': return [unsigned ? 'HEAPU16' : 'HEAP16']; break; - case '<4 x i32>': case 'uint': + case '<4 x i32>': case 'i32': case 'i64': return [unsigned ? 'HEAPU32' : 'HEAP32']; break; case 'double': { if (TARGET_LE32) return ['HEAPF64']; // in le32, we do have the ability to assume 64-bit alignment @@ -2016,6 +2001,8 @@ function finalizeLLVMParameter(param, noIndexizeFunctions) { } else if (param.ident == 'zeroinitializer') { if (isStructType(param.type)) { return makeLLVMStruct(zeros(Types.types[param.type].fields.length)); + } else if (isVectorType(param.type)) { + return ensureVector(0, getVectorBaseType(param.type)); } else { return '0'; } @@ -2038,7 +2025,7 @@ function finalizeLLVMParameter(param, noIndexizeFunctions) { } else if (param.intertype == 'mathop') { return processMathop(param); } else if (param.intertype === 'vector') { - return 'float32x4(' + param.idents.join(',') + ')'; + return getVectorBaseType(param.type) + '32x4(' + param.idents.join(',') + ')'; } else { throw 'invalid llvm parameter: ' + param.intertype; } @@ -2398,6 +2385,9 @@ function processMathop(item) { return 'SIMD.uint32x4BitsToFloat32x4(' + idents[0] + ')'; } } + case 'and': return 'SIMD.and(' + idents[0] + ',' + idents[1] + ')'; + case 'or': return 'SIMD.or(' + idents[0] + ',' + idents[1] + ')'; + case 'xor': return 'SIMD.xor(' + idents[0] + ',' + idents[1] + ')'; default: throw 'vector op todo: ' + dump(item); } } diff --git a/src/preamble.js b/src/preamble.js index 8ab6d604..b1434deb 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -1110,19 +1110,21 @@ var Math_min = Math.min; // it happens right before run - run will be postponed until // the dependencies are met. var runDependencies = 0; -var runDependencyTracking = {}; var runDependencyWatcher = null; var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled +#if ASSERTIONS +var runDependencyTracking = {}; +#endif function addRunDependency(id) { runDependencies++; if (Module['monitorRunDependencies']) { Module['monitorRunDependencies'](runDependencies); } +#if ASSERTIONS if (id) { assert(!runDependencyTracking[id]); runDependencyTracking[id] = 1; -#if ASSERTIONS if (runDependencyWatcher === null && typeof setInterval !== 'undefined') { // Check for missing dependencies every few seconds runDependencyWatcher = setInterval(function() { @@ -1139,10 +1141,10 @@ function addRunDependency(id) { } }, 10000); } -#endif } else { Module.printErr('warning: run dependency added without ID'); } +#endif } Module['addRunDependency'] = addRunDependency; function removeRunDependency(id) { @@ -1150,12 +1152,14 @@ function removeRunDependency(id) { if (Module['monitorRunDependencies']) { Module['monitorRunDependencies'](runDependencies); } +#if ASSERTIONS if (id) { assert(runDependencyTracking[id]); delete runDependencyTracking[id]; } else { Module.printErr('warning: run dependency removed without ID'); } +#endif if (runDependencies == 0) { if (runDependencyWatcher !== null) { clearInterval(runDependencyWatcher); diff --git a/src/runtime.js b/src/runtime.js index ed624fbf..c2a85e8b 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -145,7 +145,7 @@ var Runtime = { //! @param type The type, by name. getNativeTypeSize: function(type) { #if QUANTUM_SIZE == 1 - return 1; + return 1; #else switch (type) { case 'i1': case 'i8': return 1; @@ -161,6 +161,8 @@ var Runtime = { var bits = parseInt(type.substr(1)); assert(bits % 8 === 0); return bits/8; + } else { + return 0; } } } diff --git a/src/shell.html b/src/shell.html index a33735d9..53a4fffb 100644 --- a/src/shell.html +++ b/src/shell.html @@ -63,8 +63,11 @@ }, canvas: document.getElementById('canvas'), setStatus: function(text) { - if (Module.setStatus.interval) clearInterval(Module.setStatus.interval); + if (!Module.setStatus.last) Module.setStatus.last = { time: Date.now(), text: '' }; + if (text === Module.setStatus.text) return; var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/); + var now = Date.now(); + if (m && now - Date.now() < 30) return; // if this is a progress update, skip it if too soon var statusElement = document.getElementById('status'); var progressElement = document.getElementById('progress'); if (m) { |