diff options
-rwxr-xr-x | emcc | 2 | ||||
-rw-r--r-- | src/jsifier.js | 2 | ||||
-rw-r--r-- | src/library.js | 6 | ||||
-rw-r--r-- | src/parseTools.js | 36 | ||||
-rw-r--r-- | src/postamble.js | 4 | ||||
-rw-r--r-- | src/shell.html | 5 | ||||
-rw-r--r-- | tests/hello_world_sdl.cpp | 3 | ||||
-rwxr-xr-x | tests/runner.py | 69 | ||||
-rw-r--r-- | tools/scons/site_scons/site_tools/emscripten/__init__.py | 3 | ||||
-rw-r--r-- | tools/scons/site_scons/site_tools/emscripten/emscripten.py | 44 |
10 files changed, 148 insertions, 26 deletions
@@ -216,7 +216,7 @@ be generated: <name>.js JavaScript (default) <name>.html HTML with embedded JavaScript <name>.bc LLVM bitcode - <name>.o LLVM bitcode + <name>.o LLVM bitcode (same as .bc) The -c option (which tells gcc not to run the linker) will cause LLVM bitcode to be generated, as %s only generates diff --git a/src/jsifier.js b/src/jsifier.js index d4d57fc6..b54aace3 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -229,7 +229,7 @@ function JSify(data, functionsOnly, givenFunctions) { return makeEmptyStruct(type); } else if (value.intertype === 'string') { return JSON.stringify(parseLLVMString(value.text)) + - ' /* ' + value.text.substr(0, 20).replace(/\*/g, '_') + ' */'; // make string safe for inclusion in comment + ' /* ' + value.text.substr(0, 20).replace(/[*<>]/g, '_') + ' */'; // make string safe for inclusion in comment } else { return alignStruct(handleSegments(value.contents), type); } diff --git a/src/library.js b/src/library.js index 817f87e2..74a8a0ac 100644 --- a/src/library.js +++ b/src/library.js @@ -5183,7 +5183,7 @@ LibraryManager.library = { var dst = Number(start.getTimezoneOffset() != date.getTimezoneOffset()); {{{ makeSetValue('tmPtr', 'offsets.tm_isdst', 'dst', 'i32') }}} - var timezone = date.toString().match(/\(([A-Z]+)\)/)[1]; + var timezone = 'GMT'; // XXX do not rely on browser timezone info, it is very unpredictable | date.toString().match(/\(([A-Z]+)\)/)[1]; if (!(timezone in ___tm_timezones)) { ___tm_timezones[timezone] = allocate(intArrayFromString(timezone), 'i8', ALLOC_NORMAL); } @@ -5245,8 +5245,8 @@ LibraryManager.library = { var summer = new Date(2000, 6, 1); {{{ makeSetValue('__daylight', '0', 'Number(winter.getTimezoneOffset() != summer.getTimezoneOffset())', 'i32') }}} - var winterName = winter.toString().match(/\(([A-Z]+)\)/)[1]; - var summerName = summer.toString().match(/\(([A-Z]+)\)/)[1]; + var winterName = 'GMT'; // XXX do not rely on browser timezone info, it is very unpredictable | winter.toString().match(/\(([A-Z]+)\)/)[1]; + var summerName = 'GMT'; // XXX do not rely on browser timezone info, it is very unpredictable | summer.toString().match(/\(([A-Z]+)\)/)[1]; var winterNamePtr = allocate(intArrayFromString(winterName), 'i8', ALLOC_NORMAL); var summerNamePtr = allocate(intArrayFromString(summerName), 'i8', ALLOC_NORMAL); __tzname = _malloc(2 * {{{ Runtime.QUANTUM_SIZE }}}); // glibc does not need the double __ diff --git a/src/parseTools.js b/src/parseTools.js index ff578c0a..520d278e 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -559,12 +559,12 @@ function splitI64(value) { return makeInlineCalculation(makeI64('VALUE>>>0', 'Math.min(Math.floor(VALUE/4294967296), 4294967295)'), value, 'tempBigIntP'); } } -function mergeI64(value) { +function mergeI64(value, unsigned) { assert(USE_TYPED_ARRAYS == 2); if (legalizedI64s) { - return RuntimeGenerator.makeBigInt(value + '$0', value + '$1'); + return RuntimeGenerator.makeBigInt(value + '$0', value + '$1', unsigned); } else { - return makeInlineCalculation(RuntimeGenerator.makeBigInt('VALUE[0]', 'VALUE[1]'), value, 'tempI64'); + return makeInlineCalculation(RuntimeGenerator.makeBigInt('VALUE[0]', 'VALUE[1]', unsigned), value, 'tempI64'); } } @@ -1672,22 +1672,22 @@ function processMathop(item) { case 'fptoui': case 'fptosi': return finish(splitI64(idents[0])); case 'icmp': { switch (variant) { - case 'uge': return high1 + ' >= ' + high2 + ' && (' + high1 + ' > ' + high2 + ' || ' + - low1 + ' >= ' + low2 + ')'; + case 'uge': return '(' + high1 + '>>>0) >= (' + high2 + '>>>0) && ((' + high1 + '>>>0) > (' + high2 + '>>>0) || ' + + '(' + low1 + '>>>0) >= (' + low2 + '>>>0))'; case 'sge': return '(' + high1 + '|0) >= (' + high2 + '|0) && ((' + high1 + '|0) > (' + high2 + '|0) || ' + - '(' + low1 + '|0) >= (' + low2 + '|0))'; - case 'ule': return high1 + ' <= ' + high2 + ' && (' + high1 + ' < ' + high2 + ' || ' + - low1 + ' <= ' + low2 + ')'; + '(' + low1 + '>>>0) >= (' + low2 + '>>>0))'; + case 'ule': return '(' + high1 + '>>>0) <= (' + high2 + '>>>0) && ((' + high1 + '>>>0) < (' + high2 + '>>>0) || ' + + '(' + low1 + '>>>0) <= (' + low2 + '>>>0))'; case 'sle': return '(' + high1 + '|0) <= (' + high2 + '|0) && ((' + high1 + '|0) < (' + high2 + '|0) || ' + - '(' + low1 + '|0) <= (' + low2 + '|0))'; - case 'ugt': return high1 + ' > ' + high2 + ' || (' + high1 + ' == ' + high2 + ' && ' + - low1 + ' > ' + low2 + ')'; + '(' + low1 + '>>>0) <= (' + low2 + '>>>0))'; + case 'ugt': return '(' + high1 + '>>>0) > (' + high2 + '>>>0) || ((' + high1 + '>>>0) == (' + high2 + '>>>0) && ' + + '(' + low1 + '>>>0) > (' + low2 + '>>>0))'; case 'sgt': return '(' + high1 + '|0) > (' + high2 + '|0) || ((' + high1 + '|0) == (' + high2 + '|0) && ' + - '(' + low1 + '|0) > (' + low2 + '|0))'; - case 'ult': return high1 + ' < ' + high2 + ' || (' + high1 + ' == ' + high2 + ' && ' + - low1 + ' < ' + low2 + ')'; + '(' + low1 + '>>>0) > (' + low2 + '>>>0))'; + case 'ult': return '(' + high1 + '>>>0) < (' + high2 + '>>>0) || ((' + high1 + '>>>0) == (' + high2 + '>>>0) && ' + + '(' + low1 + '>>>0) < (' + low2 + '>>>0))'; case 'slt': return '(' + high1 + '|0) < (' + high2 + '|0) || ((' + high1 + '|0) == (' + high2 + '|0) && ' + - '(' + low1 + '|0) < (' + low2 + '|0))'; + '(' + low1 + '>>>0) < (' + low2 + '>>>0))'; case 'ne': return low1 + ' != ' + low2 + ' || ' + high1 + ' != ' + high2 + ''; case 'eq': return low1 + ' == ' + low2 + ' && ' + high1 + ' == ' + high2 + ''; default: throw 'Unknown icmp variant: ' + variant; @@ -1704,9 +1704,9 @@ function processMathop(item) { // Dangerous, rounded operations. TODO: Fully emulate case 'add': warnI64_1(); return finish(splitI64(mergeI64(idents[0]) + '+' + mergeI64(idents[1]))); case 'sub': warnI64_1(); return finish(splitI64(mergeI64(idents[0]) + '-' + mergeI64(idents[1]))); - case 'sdiv': case 'udiv': warnI64_1(); return finish(splitI64(makeRounding(mergeI64(idents[0]) + '/' + mergeI64(idents[1]), bits, op[0] === 's'))); - case 'mul': warnI64_1(); return finish(splitI64(mergeI64(idents[0]) + '*' + mergeI64(idents[1]))); - case 'urem': case 'srem': warnI64_1(); return finish(splitI64(mergeI64(idents[0]) + '%' + mergeI64(idents[1]))); + case 'sdiv': case 'udiv': warnI64_1(); return finish(splitI64(makeRounding(mergeI64(idents[0], op[0] === 'u') + '/' + mergeI64(idents[1], op[0] === 'u'), bits, op[0] === 's'))); + case 'mul': warnI64_1(); return finish(splitI64(mergeI64(idents[0], op[0] === 'u') + '*' + mergeI64(idents[1], op[0] === 'u'))); + case 'urem': case 'srem': warnI64_1(); return finish(splitI64(mergeI64(idents[0], op[0] === 'u') + '%' + mergeI64(idents[1], op[0] === 'u'))); case 'bitcast': { // Pointers are not 64-bit, so there is really only one possible type of bitcast here, int to float or vice versa assert(USE_TYPED_ARRAYS == 2, 'Can only bitcast ints <-> floats with typed arrays mode 2'); diff --git a/src/postamble.js b/src/postamble.js index 390f9f27..56f0aee1 100644 --- a/src/postamble.js +++ b/src/postamble.js @@ -37,7 +37,9 @@ function run(args) { var ret = null; if (Module['_main']) { ret = Module.callMain(args); - exitRuntime(); + if (!Module['noExitRuntime']) { + exitRuntime(); + } } return ret; } diff --git a/src/shell.html b/src/shell.html index 69217b18..a41086b9 100644 --- a/src/shell.html +++ b/src/shell.html @@ -19,7 +19,10 @@ print: (function() { var element = document.getElementById('output'); return function(text) { - element.innerHTML += text.replace('\n', '<br>', 'g') + '<br>'; + text = text.replace(/</g, "<"); + text = text.replace(/>/g, ">"); + text = text.replace('\n', '<br>', 'g'); + element.innerHTML += text + '<br>'; }; })(), canvas: document.getElementById('canvas') diff --git a/tests/hello_world_sdl.cpp b/tests/hello_world_sdl.cpp index df69b055..35aec303 100644 --- a/tests/hello_world_sdl.cpp +++ b/tests/hello_world_sdl.cpp @@ -20,7 +20,8 @@ int main() { if (SDL_MUSTLOCK(screen)) SDL_UnlockSurface(screen); SDL_Flip(screen); - printf("you should see a colored cube."); + printf("you should see a colored cube.\n"); + printf("and here is some text that should be HTML-friendly: amp: |&| double-quote: |\"| quote: |'| less-than, greater-than, html-like tags: |<cheez></cheez>|\nanother line.\n"); SDL_Quit(); diff --git a/tests/runner.py b/tests/runner.py index 3e31127b..e8bcb72e 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -689,6 +689,51 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv): self.do_run(src, '*1,1,0,0,1,0*\n') + def test_i64_cmp2(self): + if Settings.USE_TYPED_ARRAYS != 2: return self.skip('full i64 stuff only in ta2') + src = r''' + #include <inttypes.h> + #include <stdio.h> + + typedef int32_t INT32; + typedef int64_t INT64; + typedef uint8_t UINT8; + + void interface_clock_changed() + { + UINT8 m_divshift; + INT32 m_divisor; + + //INT64 attos = m_attoseconds_per_cycle; + INT64 attos = 279365114840; + m_divshift = 0; + while (attos >= (1UL << 31)) + { + m_divshift++; + printf("m_divshift is %i, on %Ld >?= %lu\n", m_divshift, attos, 1UL << 31); + attos >>= 1; + } + m_divisor = attos; + + printf("m_divisor is %i\n",m_divisor); + } + + int main() { + interface_clock_changed(); + return 0; + } + ''' + self.do_run(src, '''m_divshift is 1, on 279365114840 >?= 2147483648 +m_divshift is 2, on 139682557420 >?= 2147483648 +m_divshift is 3, on 69841278710 >?= 2147483648 +m_divshift is 4, on 34920639355 >?= 2147483648 +m_divshift is 5, on 17460319677 >?= 2147483648 +m_divshift is 6, on 8730159838 >?= 2147483648 +m_divshift is 7, on 4365079919 >?= 2147483648 +m_divshift is 8, on 2182539959 >?= 2147483648 +m_divisor is 1091269979 +''') + def test_i64_double(self): if Settings.USE_TYPED_ARRAYS != 2: return self.skip('full i64 stuff only in ta2') src = r''' @@ -731,6 +776,30 @@ if 'benchmark' not in str(sys.argv) and 'sanity' not in str(sys.argv): ''' self.do_run(src, '*0,0,0,0*\n*1,1,0,0*\n') # same as gcc + def test_i64_umul(self): + if Settings.USE_TYPED_ARRAYS != 2: return self.skip('full i64 stuff only in ta2') + src = r''' + #include <inttypes.h> + #include <stdio.h> + + typedef uint32_t UINT32; + typedef uint64_t UINT64; + + int main() { + volatile UINT32 testu32a = 2375724032U; + UINT32 bigu32 = 0xffffffffU; + volatile UINT64 testu64a = 14746250828952703000U; + + while ((UINT64)testu32a * (UINT64)bigu32 < testu64a) { + printf("testu64a is %llu\n", testu64a); + testu64a /= 2; + } + + return 0; + } + ''' + self.do_run(src, 'testu64a is 14746250828952703000\n') + def test_unaligned(self): if Settings.QUANTUM_SIZE == 1: return self.skip('No meaning to unaligned addresses in q1') diff --git a/tools/scons/site_scons/site_tools/emscripten/__init__.py b/tools/scons/site_scons/site_tools/emscripten/__init__.py new file mode 100644 index 00000000..8ae2288e --- /dev/null +++ b/tools/scons/site_scons/site_tools/emscripten/__init__.py @@ -0,0 +1,3 @@ +#!/usr/bin/env python + +from emscripten import exists, generate diff --git a/tools/scons/site_scons/site_tools/emscripten/emscripten.py b/tools/scons/site_scons/site_tools/emscripten/emscripten.py new file mode 100644 index 00000000..cb14b58e --- /dev/null +++ b/tools/scons/site_scons/site_tools/emscripten/emscripten.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python + +import os + +def generate(env, emscripten_path=None, **kw): + """ SCons tool entry point """ + + if emscripten_path is None: + # Try to find emscripten + # Use same method as Emscripten's shared.py + EM_CONFIG = os.environ.get('EM_CONFIG') + if not EM_CONFIG: + EM_CONFIG = '~/.emscripten' + + CONFIG_FILE = os.path.expanduser(EM_CONFIG) + try: + exec(open(CONFIG_FILE, 'r').read()) + except Exception, e: + print >> sys.stderr, 'Error in evaluating %s (at %s): %s' % (EM_CONFIG, CONFIG_FILE, str(e)) + sys.exit(1) + + emscripten_path = EMSCRIPTEN_ROOT + + try: + emscPath = emscripten_path.abspath + except: + emscPath = emscripten_path + + env.Replace(CC = os.path.join(emscPath, "emcc" )) + env.Replace(CXX = os.path.join(emscPath, "em++" )) + env.Replace(LINK = os.path.join(emscPath, "emld" )) + # SHLINK and LDMODULE should use LINK so no + # need to change them here + + env.Replace(AR = os.path.join(emscPath, "emar" )) + env.Replace(RANLIB = os.path.join(emscPath, "emranlib")) + + env.Replace(OBJSUFFIX = [".js", ".bc", ".o"][2]) + env.Replace(LIBSUFFIX = [".js", ".bc", ".o"][2]) + env.Replace(PROGSUFFIX = [".html", ".js" ][1]) + +def exists(env): + """ NOOP method required by SCons """ + return 1 |