aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xemcc2
-rw-r--r--src/jsifier.js2
-rw-r--r--src/library.js6
-rw-r--r--src/parseTools.js36
-rw-r--r--src/postamble.js4
-rw-r--r--src/shell.html5
-rw-r--r--tests/hello_world_sdl.cpp3
-rwxr-xr-xtests/runner.py69
-rw-r--r--tools/scons/site_scons/site_tools/emscripten/__init__.py3
-rw-r--r--tools/scons/site_scons/site_tools/emscripten/emscripten.py44
10 files changed, 148 insertions, 26 deletions
diff --git a/emcc b/emcc
index 630c2504..8af40562 100755
--- a/emcc
+++ b/emcc
@@ -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, "&lt;");
+ text = text.replace(/>/g, "&gt;");
+ 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