diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler.js | 1 | ||||
-rw-r--r-- | src/intertyper.js | 147 | ||||
-rw-r--r-- | src/jsifier.js | 5 | ||||
-rw-r--r-- | src/library_fs.js | 34 | ||||
-rw-r--r-- | src/library_gl.js | 6 | ||||
-rw-r--r-- | src/library_glut.js | 37 | ||||
-rw-r--r-- | src/library_sdl.js | 2 | ||||
-rw-r--r-- | src/preamble.js | 25 | ||||
-rw-r--r-- | src/proxyClient.js | 10 |
9 files changed, 169 insertions, 98 deletions
diff --git a/src/compiler.js b/src/compiler.js index d490f454..ac1b0ec8 100644 --- a/src/compiler.js +++ b/src/compiler.js @@ -318,4 +318,5 @@ if (ll_file) { //var M = keys(tokenCacheMisses).map(function(m) { return [m, misses[m]] }).sort(function(a, b) { return a[1] - b[1] }); //printErr(dump(M.slice(M.length-10))); +//printErr('hits: ' + hits); diff --git a/src/intertyper.js b/src/intertyper.js index 781c8187..9414a1d4 100644 --- a/src/intertyper.js +++ b/src/intertyper.js @@ -6,12 +6,12 @@ var fastPaths = 0, slowPaths = 0; var tokenCache = {}; -['=', 'i32', 'label', ';', '4', '0', '1', '2', '255', 'align', 'i8*', 'i8', 'i16', 'getelementptr', 'inbounds', 'unnamed_addr', 'x', 'load', 'preds', 'br', 'i32*', 'i1', 'store', '<label>', 'constant', 'c', 'private', 'null', 'internal', 'to', 'bitcast', 'define', 'nounwind', 'nocapture', '%this', 'call', '...'].forEach(function(text) { tokenCache[text] = { text: text } }); +[',', 'i32', 'label', ';', '4', '0', '1', '2', '255', 'align', 'i8*', 'i8', 'i16', 'getelementptr', 'inbounds', 'unnamed_addr', 'x', 'load', 'preds', 'br', 'i32*', 'i1', 'store', '<label>', 'constant', 'c', 'private', 'null', 'internal', 'to', 'bitcast', 'define', 'nounwind', 'nocapture', '%this', 'call', '...'].forEach(function(text) { tokenCache[text] = { text: text } }); //var tokenCacheMisses = {}; // Line tokenizer -function tokenize(text, lineNum) { +function tokenize(text, lineNum, indent) { var tokens = []; var quotes = 0; var lastToken = null; @@ -63,12 +63,7 @@ function tokenize(text, lineNum) { tokens.splice(openBrace, tokens.length-openBrace+1); tokens.push(token); token.type = '{'; - token.text = '{ ' + token.text + ' }'; - var pointingLevelsToAdd = pointingLevels(text) - pointingLevels(token.text); - while (pointingLevelsToAdd > 0) { - token.text += '*'; - pointingLevelsToAdd--; - } + token.text = '{ ' + token.text + ' ' + text; lastToken = token; } else { tokens.push(token); @@ -82,78 +77,67 @@ function tokenize(text, lineNum) { segments.pop(); var len = segments.length; var i = -1; - var curr = ''; + var start = 0; var segment, letter; for (var s = 0; s < len; s++) { segment = segments[s]; i += segment.length + 1; letter = lineText[i]; - curr += segment; switch (letter) { case ' ': if (totalEnclosing == 0 && quotes == 0) { - makeToken(curr); - curr = ''; + makeToken(lineText.substring(start, i)); + start = i+1; } else { - curr += ' '; } break; case '"': if (totalEnclosing == 0) { if (quotes == 0) { - if (curr == '@' || curr == '%') { - curr += '"'; + if (start === i-1 && (lineText[start] == '@' || lineText[start] == '%')) { } else { - makeToken(curr); - curr = '"'; + makeToken(lineText.substring(start, i)); + start = i; } } else { - makeToken(curr + '"'); - curr = ''; + makeToken(lineText.substring(start, i+1)); + start = i+1; } - } else { - curr += '"'; } quotes = 1-quotes; break; case ',': if (totalEnclosing == 0 && quotes == 0) { - makeToken(curr); - curr = ''; - tokens.push({ text: ',' }); - } else { - curr += ','; + makeToken(lineText.substring(start, i)); + start = i+1; + tokens.push(tokenCache[',']); } break; default: assert(letter in enclosers); if (quotes) { - curr += letter; break; } if (letter in ENCLOSER_STARTERS) { if (totalEnclosing == 0) { - makeToken(curr); - curr = ''; + makeToken(lineText.substring(start, i)); + start = i; } - curr += letter; enclosers[letter]++; totalEnclosing++; } else { enclosers[enclosers[letter]]--; totalEnclosing--; if (totalEnclosing == 0) { - makeToken(curr + letter); - curr = ''; - } else { - curr += letter; + makeToken(lineText.substring(start, i+1)); + start = i+1; } } } } var newItem = { tokens: tokens, - indent: lineText.search(/[^ ]/), + indent: indent || lineText.search(/[^ ]/), lineNum: lineNum || 0 }; return newItem; @@ -291,10 +275,6 @@ function intertyper(lines, sidePass, baseLineNums) { function triager(item) { assert(!item.intertype); - if (item.indent == 2 && (eq = findTokenText(item, '=')) >= 0) { - item.assignTo = toNiceIdent(combineTokens(item.tokens.slice(0, eq)).text); - item.tokens = item.tokens.slice(eq+1); - } var token0Text = item.tokens[0].text; var token1Text = item.tokens[1] ? item.tokens[1].text : null; var tokensLength = item.tokens.length; @@ -345,7 +325,7 @@ function intertyper(lines, sidePass, baseLineNums) { return labelHandler(item); if (tokensLength >= 4 && token0Text == 'declare') return externalHandler(item); - if (tokensLength >= 3 && token1Text == '=') + if (item.assignTo) return globalHandler(item); if (tokensLength >= 4 && token0Text == 'define' && item.tokens.slice(-1)[0].text == '{') @@ -458,15 +438,15 @@ function intertyper(lines, sidePass, baseLineNums) { } } - cleanOutTokens(LLVM.VISIBILITIES, item.tokens, 2); - if (item.tokens[2].text == 'alias') { - cleanOutTokens(LLVM.LINKAGES, item.tokens, 3); - cleanOutTokens(LLVM.VISIBILITIES, item.tokens, 3); + cleanOutTokens(LLVM.VISIBILITIES, item.tokens, 0); + if (item.tokens[0].text == 'alias') { + cleanOutTokens(LLVM.LINKAGES, item.tokens, 1); + cleanOutTokens(LLVM.VISIBILITIES, item.tokens, 1); var last = getTokenIndexByText(item.tokens, ';'); var ret = { intertype: 'alias', - ident: toNiceIdent(item.tokens[0].text), - value: parseLLVMSegment(item.tokens.slice(3, last)), + ident: item.assignTo, + value: parseLLVMSegment(item.tokens.slice(1, last)), lineNum: item.lineNum }; ret.type = ret.value.type; @@ -476,18 +456,18 @@ function intertyper(lines, sidePass, baseLineNums) { } return ret; } - if (item.tokens[2].text == 'type') { + if (item.tokens[0].text == 'type') { var fields = []; var packed = false; - if (Runtime.isNumberType(item.tokens[3].text)) { + if (Runtime.isNumberType(item.tokens[1].text)) { // Clang sometimes has |= i32| instead of |= { i32 }| - fields = [item.tokens[3].text]; - } else if (item.tokens[3].text != 'opaque') { - if (item.tokens[3].type == '<') { + fields = [item.tokens[1].text]; + } else if (item.tokens[1].text != 'opaque') { + if (item.tokens[1].type == '<') { packed = true; - item.tokens[3] = item.tokens[3].item.tokens[0]; + item.tokens[1] = item.tokens[1].item.tokens[0]; } - var subTokens = item.tokens[3].tokens; + var subTokens = item.tokens[1].tokens; if (subTokens) { subTokens.push({text:','}); while (subTokens[0]) { @@ -500,38 +480,40 @@ function intertyper(lines, sidePass, baseLineNums) { } return { intertype: 'type', - name_: item.tokens[0].text, + name_: item.assignTo, fields: fields, packed: packed, lineNum: item.lineNum }; } else { // variable - var ident = item.tokens[0].text; + var ident = item.assignTo; var private_ = findTokenText(item, 'private') >= 0 || findTokenText(item, 'internal') >= 0; var named = findTokenText(item, 'unnamed_addr') < 0; - cleanOutTokens(LLVM.GLOBAL_MODIFIERS, item.tokens, [2, 3]); + cleanOutTokens(LLVM.GLOBAL_MODIFIERS, item.tokens, [0, 1]); var external = false; - if (item.tokens[2].text === 'external') { + if (item.tokens[0].text === 'external') { external = true; - item.tokens.splice(2, 1); + item.tokens.splice(0, 1); } var ret = { intertype: 'globalVariable', - ident: toNiceIdent(ident), - type: item.tokens[2].text, + ident: ident, + type: item.tokens[0].text, external: external, private_: private_, named: named, lineNum: item.lineNum }; noteGlobalVariable(ret); - if (ident == '@llvm.global_ctors') { + if (ident == '_llvm_global_ctors') { ret.ctors = []; - if (item.tokens[3].item) { - var subTokens = item.tokens[3].item.tokens; + if (item.tokens[1].item) { + var subTokens = item.tokens[1].item.tokens; splitTokenList(subTokens).forEach(function(segment) { - var ctor = toNiceIdent(segment[1].tokens.slice(-1)[0].text); + var parsed = parseLLVMSegment(segment); + assert(parsed.intertype === 'structvalue'); + var ctor = toNiceIdent(parsed.params[1].ident); ret.ctors.push(ctor); if (ASM_JS) { // must export the global constructors from asm.js module, so mark as implemented and exported Functions.implementedFunctions[ctor] = 'v'; @@ -540,14 +522,14 @@ function intertyper(lines, sidePass, baseLineNums) { }); } } else if (!external) { - if (item.tokens[3] && item.tokens[3].text != ';') { - if (item.tokens[3].text == 'c') { - item.tokens.splice(3, 1); + if (item.tokens[1] && item.tokens[1].text != ';') { + if (item.tokens[1].text == 'c') { + item.tokens.splice(1, 1); } - if (item.tokens[3].text in PARSABLE_LLVM_FUNCTIONS) { - ret.value = parseLLVMFunctionCall(item.tokens.slice(2)); + if (item.tokens[1].text in PARSABLE_LLVM_FUNCTIONS) { + ret.value = parseLLVMFunctionCall(item.tokens); } else { - ret.value = scanConst(item.tokens[3], ret.type); + ret.value = scanConst(item.tokens[1], ret.type); } } else { ret.value = { intertype: 'value', ident: '0', value: '0', type: ret.type }; @@ -1131,7 +1113,27 @@ function intertyper(lines, sidePass, baseLineNums) { //var time = Date.now(); - var t = tokenize(line.lineText, line.lineNum); + // parse out the assignment + var indent = 0, assignTo = null; + if (phase === 'pre') { + var m = /^([%@\w\d\._\-]+|[%@]"[^"]+") = (.*)/.exec(line.lineText); + if (m) { + assignTo = m[1]; + line.lineText = m[2]; + } + } else if (phase === 'funcs') { + var m = /^ ([%@\w\d\._\-]+|[%@]"[^"]+") = (.*)/.exec(line.lineText); + if (m) { + indent = 2; + assignTo = m[1]; + line.lineText = m[2]; + } + } + + var t = tokenize(line.lineText, line.lineNum, indent); + if (assignTo) { + t.assignTo = t.tokens[0].text !== 'type' ? toNiceIdent(assignTo) : assignTo; + } item = triager(t); /* @@ -1148,7 +1150,7 @@ function intertyper(lines, sidePass, baseLineNums) { return finalResults; } -// intertyper profiler +// intertyper profiling /* var interProf = {}; @@ -1156,4 +1158,5 @@ function dumpInterProf() { printErr('\nintertyper/' + phase + ' (ms | n): ' + JSON.stringify(keys(interProf).sort(function(x, y) { return interProf[y].ms - interProf[x].ms }).map(function(x) { return x + ' : ' + interProf[x].ms + ' | ' + interProf[x].n }), null, ' ') + '\n'); } */ +//var hits = 0; diff --git a/src/jsifier.js b/src/jsifier.js index a126994b..e84de3ee 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -407,6 +407,9 @@ function JSify(data, functionsOnly, givenFunctions) { var snippet = LibraryManager.library[ident]; var redirectedIdent = null; var deps = LibraryManager.library[ident + '__deps'] || []; + deps.forEach(function(dep) { + if (typeof snippet === 'string' && !(dep in LibraryManager.library)) warn('missing library dependency ' + dep + ', make sure you are compiling with the right options (see #ifdefs in src/library*.js)'); + }); var isFunction = false; if (typeof snippet === 'string') { @@ -1372,7 +1375,7 @@ function JSify(data, functionsOnly, givenFunctions) { // store current list offset in tempInt, advance list offset by STACK_ALIGN, return list entry stored at tempInt return '(tempInt=' + makeGetValue(ident, Runtime.QUANTUM_SIZE, '*') + ',' + - makeSetValue(ident, Runtime.QUANTUM_SIZE, 'tempInt + ' + move, '*') + ',' + + makeSetValue(ident, Runtime.QUANTUM_SIZE, 'tempInt + ' + move, '*', null, null, null, null, ',') + ',' + makeGetValue(makeGetValue(ident, 0, '*'), 'tempInt', item.type) + ')'; } diff --git a/src/library_fs.js b/src/library_fs.js index 5adbe6b7..bd1522a8 100644 --- a/src/library_fs.js +++ b/src/library_fs.js @@ -1,5 +1,5 @@ mergeInto(LibraryManager.library, { - $FS__deps: ['$ERRNO_CODES', '$ERRNO_MESSAGES', '__setErrNo', '$VFS', '$PATH', '$TTY', '$MEMFS', '$IDBFS', '$NODEFS', 'stdin', 'stdout', 'stderr', 'fflush'], + $FS__deps: ['$ERRNO_CODES', '$ERRNO_MESSAGES', '__setErrNo', '$PATH', '$TTY', '$MEMFS', '$IDBFS', '$NODEFS', 'stdin', 'stdout', 'stderr', 'fflush'], $FS__postset: 'FS.staticInit();' + '__ATINIT__.unshift({ func: function() { if (!Module["noFSInit"] && !FS.init.initialized) FS.init() } });' + '__ATMAIN__.push({ func: function() { FS.ignorePermissions = false } });' + @@ -1064,19 +1064,8 @@ mergeInto(LibraryManager.library, { {{{ makeSetValue(makeGlobalUse('_stderr'), 0, 'stderr.fd', 'void*') }}}; assert(stderr.fd === 3, 'invalid handle for stderr (' + stderr.fd + ')'); }, - staticInit: function() { - FS.nameTable = new Array(4096); - - FS.root = FS.createNode(null, '/', {{{ cDefine('S_IFDIR') }}} | 0777, 0); - FS.mount(MEMFS, {}, '/'); - - FS.createDefaultDirectories(); - FS.createDefaultDevices(); - }, - init: function(input, output, error) { - assert(!FS.init.initialized, 'FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)'); - FS.init.initialized = true; - + ensureErrnoError: function() { + if (FS.ErrnoError) return; FS.ErrnoError = function ErrnoError(errno) { this.errno = errno; for (var key in ERRNO_CODES) { @@ -1090,6 +1079,23 @@ mergeInto(LibraryManager.library, { }; FS.ErrnoError.prototype = new Error(); FS.ErrnoError.prototype.constructor = FS.ErrnoError; + }, + staticInit: function() { + FS.ensureErrnoError(); + + FS.nameTable = new Array(4096); + + FS.root = FS.createNode(null, '/', {{{ cDefine('S_IFDIR') }}} | 0777, 0); + FS.mount(MEMFS, {}, '/'); + + FS.createDefaultDirectories(); + FS.createDefaultDevices(); + }, + init: function(input, output, error) { + assert(!FS.init.initialized, 'FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)'); + FS.init.initialized = true; + + FS.ensureErrnoError(); // Allow Module.stdin etc. to provide defaults, if none explicitly passed to us here Module['stdin'] = input || Module['stdin']; diff --git a/src/library_gl.js b/src/library_gl.js index 6e0e04dc..1ea8efc2 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -4047,7 +4047,10 @@ var LibraryGL = { _glColor4f({{{ makeGetValue('p', '0', 'float') }}}, {{{ makeGetValue('p', '4', 'float') }}}, {{{ makeGetValue('p', '8', 'float') }}}, {{{ makeGetValue('p', '12', 'float') }}}); }, - glColor4ubv: function() { throw 'glColor4ubv not implemented' }, + glColor4ubv__deps: ['glColor4ub'], + glColor4ubv: function(p) { + _glColor4ub({{{ makeGetValue('p', '0', 'i8') }}}, {{{ makeGetValue('p', '1', 'i8') }}}, {{{ makeGetValue('p', '2', 'i8') }}}, {{{ makeGetValue('p', '3', 'i8') }}}); + }, glFogf: function(pname, param) { // partial support, TODO switch(pname) { @@ -4470,6 +4473,7 @@ var LibraryGL = { return 1 /* GL_TRUE */; }, + gluOrtho2D__deps: ['glOrtho'], gluOrtho2D: function(left, right, bottom, top) { _glOrtho(left, right, bottom, top, -1, 1); }, diff --git a/src/library_glut.js b/src/library_glut.js index 79c586c6..722ea85c 100644 --- a/src/library_glut.js +++ b/src/library_glut.js @@ -190,12 +190,12 @@ var LibraryGLUT = { } }, - onMouseButtonDown: function(event){ + onMouseButtonDown: function(event) { Browser.calculateMouseEvent(event); GLUT.buttons |= (1 << event['button']); - if(event.target == Module["canvas"] && GLUT.mouseFunc){ + if (event.target == Module["canvas"] && GLUT.mouseFunc) { try { event.target.setCapture(); } catch (e) {} @@ -205,21 +205,40 @@ var LibraryGLUT = { } }, - onMouseButtonUp: function(event){ + onMouseButtonUp: function(event) { Browser.calculateMouseEvent(event); GLUT.buttons &= ~(1 << event['button']); - if(GLUT.mouseFunc) { + if (GLUT.mouseFunc) { event.preventDefault(); GLUT.saveModifiers(event); Runtime.dynCall('viiii', GLUT.mouseFunc, [event['button'], 1/*GLUT_UP*/, Browser.mouseX, Browser.mouseY]); } }, + onMouseWheel: function(event) { + Browser.calculateMouseEvent(event); + + // cross-browser wheel delta + var e = window.event || event; // old IE support + var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail))); + + var button = 3; // wheel up + if (delta < 0) { + button = 4; // wheel down + } + + if (GLUT.mouseFunc) { + event.preventDefault(); + GLUT.saveModifiers(event); + Runtime.dynCall('viiii', GLUT.mouseFunc, [button, 0/*GLUT_DOWN*/, Browser.mouseX, Browser.mouseY]); + } + }, + // TODO add fullscreen API ala: // http://johndyer.name/native-fullscreen-javascript-api-plus-jquery-plugin/ - onFullScreenEventChange: function(event){ + onFullScreenEventChange: function(event) { var width; var height; if (document["fullScreen"] || document["mozFullScreen"] || document["webkitIsFullScreen"]) { @@ -280,6 +299,10 @@ var LibraryGLUT = { window.addEventListener("mousemove", GLUT.onMousemove, true); window.addEventListener("mousedown", GLUT.onMouseButtonDown, true); window.addEventListener("mouseup", GLUT.onMouseButtonUp, true); + // IE9, Chrome, Safari, Opera + window.addEventListener("mousewheel", GLUT.onMouseWheel, true); + // Firefox + window.addEventListener("DOMMouseScroll", GLUT.onMouseWheel, true); } Browser.resizeListeners.push(function(width, height) { @@ -299,6 +322,10 @@ var LibraryGLUT = { window.removeEventListener("mousemove", GLUT.onMousemove, true); window.removeEventListener("mousedown", GLUT.onMouseButtonDown, true); window.removeEventListener("mouseup", GLUT.onMouseButtonUp, true); + // IE9, Chrome, Safari, Opera + window.removeEventListener("mousewheel", GLUT.onMouseWheel, true); + // Firefox + window.removeEventListener("DOMMouseScroll", GLUT.onMouseWheel, true); } Module["canvas"].width = Module["canvas"].height = 1; } }); diff --git a/src/library_sdl.js b/src/library_sdl.js index bb7e9264..a0689343 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -1149,7 +1149,7 @@ var LibrarySDL = { var ret = SDL.makeSurface(diagonal, diagonal, srcData.flags, false, 'rotozoomSurface'); var dstData = SDL.surfaces[ret]; dstData.ctx.translate(diagonal / 2, diagonal / 2); - dstData.ctx.rotate(angle * Math.PI / 180); + dstData.ctx.rotate(-angle * Math.PI / 180); dstData.ctx.drawImage(srcData.canvas, -w / 2, -h / 2, w, h); return ret; }, diff --git a/src/preamble.js b/src/preamble.js index 33e80217..ee273f6a 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -656,7 +656,16 @@ function demangle(func) { 'i': 'int', 'l': 'long', 'f': 'float', - 'd': 'double' + 'd': 'double', + 'w': 'wchar_t', + 'a': 'signed char', + 'h': 'unsigned char', + 't': 'unsigned short', + 'j': 'unsigned int', + 'm': 'unsigned long', + 'x': 'long long', + 'y': 'unsigned long long', + 'z': '...' }; function dump(x) { //return; @@ -729,6 +738,7 @@ function demangle(func) { } else { switch (c) { case 'P': list.push(parse(true, 1, true)[0] + '*'); break; // pointer + case 'R': list.push(parse(true, 1, true)[0] + '&'); break; // reference case 'L': { // literal i++; // skip basic type var end = func.indexOf('E', i); @@ -737,6 +747,14 @@ function demangle(func) { i += size + 2; // size + 'EE' break; } + case 'A': { // array + var size = parseInt(func.substr(i)); + i += size.toString().length; + if (func[i] !== '_') throw '?'; + i++; // skip _ + list.push(parse(true, 1, true)[0] + ' [' + size + ']'); + break; + } case 'E': break paramLoop; default: ret += '?' + c; break paramLoop; } @@ -752,11 +770,12 @@ function demangle(func) { } function demangleAll(text) { - return text.replace(/__Z[\w\d_]+/, function(x) { var y = demangle(x); return x === y ? x : (x + ' (' + y + ')') }); + return text.replace(/__Z[\w\d_]+/g, function(x) { var y = demangle(x); return x === y ? x : (x + ' [' + y + ']') }); } function stackTrace() { - return demangleAll(new Error().stack); + var stack = new Error().stack; + return stack ? demangleAll(stack) : '(no stack trace available)'; // Stack trace is not available at least on IE10 and Safari 6. } // Memory management diff --git a/src/proxyClient.js b/src/proxyClient.js index 04f7ed11..38ea5771 100644 --- a/src/proxyClient.js +++ b/src/proxyClient.js @@ -30,7 +30,15 @@ worker.onmessage = function(event) { break; } case 'render': { - Module.canvasData.data.set(data.image.data); + var src = data.image.data; + var dst = Module.canvasData.data; + if (dst.set) { + dst.set(src); + } else { + for (var i = 0; i < src.length; i++) { + dst[i] = src[i]; + } + } Module.ctx.putImageData(Module.canvasData, 0, 0); break; } |