aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/analyzer.js4
-rw-r--r--src/library_browser.js10
-rw-r--r--src/library_sdl.js1
-rw-r--r--src/parseTools.js51
-rw-r--r--system/include/emscripten.h1
-rw-r--r--tests/emscripten_api_browser.cpp4
-rwxr-xr-xtests/runner.py23
7 files changed, 70 insertions, 24 deletions
diff --git a/src/analyzer.js b/src/analyzer.js
index 8ded86f1..1453b22c 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -544,6 +544,10 @@ function analyzer(data, sidePass) {
params: [(signed && j + whole > sourceElements.length) ? signedKeepAlive : null],
type: 'i32',
};
+ if (j == 0 && isUnsignedOp(value.op) && sourceBits < 32) {
+ // zext sign correction
+ result.ident = makeSignOp(result.ident, 'i' + sourceBits, 'un', 1, 1);
+ }
if (fraction != 0) {
var other = {
intertype: 'value',
diff --git a/src/library_browser.js b/src/library_browser.js
index 66aeeaf8..a37ef612 100644
--- a/src/library_browser.js
+++ b/src/library_browser.js
@@ -3,6 +3,16 @@
// Utilities for browser environments
mergeInto(LibraryManager.library, {
+ emscripten_async_run_script__deps: ['emscripten_run_script'],
+ emscripten_async_run_script: function(script, millis) {
+ Module['noExitRuntime'] = true;
+
+ // TODO: cache these to avoid generating garbage
+ setTimeout(function() {
+ _emscripten_run_script(script);
+ }, millis);
+ },
+
emscripten_set_main_loop: function(func, fps) {
Module['noExitRuntime'] = true;
diff --git a/src/library_sdl.js b/src/library_sdl.js
index e76a2a28..809ff658 100644
--- a/src/library_sdl.js
+++ b/src/library_sdl.js
@@ -611,6 +611,7 @@ var LibrarySDL = {
},
SDL_WarpMouse: function(x, y) {
+ return; // TODO: implement this in a non-buggy way. Need to keep relative mouse movements correct after calling this
SDL.events.push({
type: 'mousemove',
pageX: x + Module['canvas'].offsetLeft,
diff --git a/src/parseTools.js b/src/parseTools.js
index 92fb038a..21852c5d 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -1314,27 +1314,36 @@ function finalizeLLVMFunctionCall(item, noIndexizeFunctions) {
// Warn about some types of casts, then fall through to the handling code below
var oldType = item.params[0].type;
var newType = item.type;
- if (isPossiblyFunctionType(oldType) && isPossiblyFunctionType(newType) &&
- countNormalArgs(oldType) != countNormalArgs(newType)) {
- warnOnce('Casting a function pointer type to another with a different number of arguments. See more info in the source');
- // This may be dangerous as clang generates different code for C and C++ calling conventions. The only problem
- // case appears to be passing a structure by value, C will have (field1, field2) as function args, and the
- // function will internally create a structure with that data, while C++ will have (struct* byVal) and it
- // will create a copy before calling the function, then call it with a pointer to the copy. Mixing the two
- // first of all leads to two copies being made, so this is a bad idea even regardless of Emscripten. But,
- // what is a problem for Emscr ipten is that mixing these two calling conventions (say, calling a C one from
- // C++) will then assume that (struct* byVal) is actually the same as (field1, field2). In native code, this
- // is easily possible, you place the two fields on the stack and call the function (you know to place the
- // values since there is 'byVal'). In Emscripten, though, this means we would need to always do one or the
- // other of the two possibilities, for example, always passing by-value structs as (field1, field2). This
- // would slow down everything, just to handle this corner case. (Which, just to point out how much of a
- // corner case it is, does not appear to happen with nested structures!)
- //
- // The recommended solution for this problem is not to mix C and C++ calling conventions when passing structs
- // by value. Either always pass structs by value within C code or C++ code, but not mixing the two by
- // defining a function in one and calling it from the other (so, just changing .c to .cpp, or moving code
- // from one file to another, would be enough to fix this), or, do not pass structs by value (which in general
- // is inefficient, and worth avoiding if you can).
+ if (isPossiblyFunctionType(oldType) && isPossiblyFunctionType(newType)) {
+ var oldCount = countNormalArgs(oldType);
+ var newCount = countNormalArgs(newType);
+ if (oldCount != newCount && oldCount && newCount) {
+ if (!ASSERTIONS) {
+ warnOnce('Casting a function pointer type to another with a different number of arguments. See more info in the compiler source');
+ } else {
+ warn('Casting a function pointer type to another with a different number of arguments: ' + oldType + ' vs. ' + newType + ', on ' + item.params[0].ident);
+ }
+ // This may be dangerous as clang generates different code for C and C++ calling conventions. The only problem
+ // case appears to be passing a structure by value, C will have (field1, field2) as function args, and the
+ // function will internally create a structure with that data, while C++ will have (struct* byVal) and it
+ // will create a copy before calling the function, then call it with a pointer to the copy. Mixing the two
+ // first of all leads to two copies being made, so this is a bad idea even regardless of Emscripten. But,
+ // what is a problem for Emscr ipten is that mixing these two calling conventions (say, calling a C one from
+ // C++) will then assume that (struct* byVal) is actually the same as (field1, field2). In native code, this
+ // is easily possible, you place the two fields on the stack and call the function (you know to place the
+ // values since there is 'byVal'). In Emscripten, though, this means we would need to always do one or the
+ // other of the two possibilities, for example, always passing by-value structs as (field1, field2). This
+ // would slow down everything, just to handle this corner case. (Which, just to point out how much of a
+ // corner case it is, does not appear to happen with nested structures!)
+ //
+ // The recommended solution for this problem is not to mix C and C++ calling conventions when passing structs
+ // by value. Either always pass structs by value within C code or C++ code, but not mixing the two by
+ // defining a function in one and calling it from the other (so, just changing .c to .cpp, or moving code
+ // from one file to another, would be enough to fix this), or, do not pass structs by value (which in general
+ // is inefficient, and worth avoiding if you can).
+ //
+ // Note that removing all arguments is acceptable, as a vast to void ()*.
+ }
}
}
var temp = {
diff --git a/system/include/emscripten.h b/system/include/emscripten.h
index 7bb2ae8e..fa95645a 100644
--- a/system/include/emscripten.h
+++ b/system/include/emscripten.h
@@ -17,6 +17,7 @@ extern "C" {
*/
extern void emscripten_run_script(const char *script);
extern int emscripten_run_script_int(const char *script);
+extern void emscripten_async_run_script(const char *script, int millis);
/*
* Set a C function as the main event loop. The JS environment
diff --git a/tests/emscripten_api_browser.cpp b/tests/emscripten_api_browser.cpp
index 4d425120..0226eae5 100644
--- a/tests/emscripten_api_browser.cpp
+++ b/tests/emscripten_api_browser.cpp
@@ -9,7 +9,7 @@ int last = 0;
extern "C" {
-void third() {
+void __attribute__((used)) third() {
int now = SDL_GetTicks();
printf("thard! %d\n", now);
assert(fabs(now - last - 1000) < 500);
@@ -22,7 +22,7 @@ void second() {
printf("sacond! %d\n", now);
assert(fabs(now - last - 500) < 250);
last = now;
- emscripten_async_call(third, 1000);
+ emscripten_async_run_script("_third()", 1000);
}
}
diff --git a/tests/runner.py b/tests/runner.py
index 3a2b3537..ecda863e 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -909,6 +909,27 @@ m_divisor is 1091269979
code = open(os.path.join(self.get_dir(), 'src.cpp.o.js')).read()
assert 'goog.math.Long' not in code and 'jsbn' not in code, 'i64 precise math should not have been included if not actually used'
+ def test_i64_zextneg(self):
+ if Settings.USE_TYPED_ARRAYS != 2: return self.skip('full i64 stuff only in ta2')
+
+ src = r'''
+ #include <stdint.h>
+ #include <stdio.h>
+
+ int main(int argc, char *argv[])
+ {
+ uint8_t byte = 0x80;
+ uint16_t two = byte;
+ uint32_t four = byte;
+ uint64_t eight = byte;
+
+ printf("value: %d,%d,%d,%lld.\n", byte, two, four, eight);
+
+ return 0;
+ }
+ '''
+ self.do_run(src, 'value: 128,128,128,128.')
+
def test_cube2hash(self):
# A good test of i64 math
if Settings.USE_TYPED_ARRAYS != 2: return self.skip('requires ta2 C-style memory aliasing')
@@ -2702,7 +2723,7 @@ def process(filename):
output = Popen(['python', EMCC, all_name], stderr=PIPE).communicate()
# Check for warning in the generated code
generated = open(os.path.join(self.get_dir(), 'src.cpp.o.js')).read()
- assert 'Casting a function pointer type to another with a different number of arguments.' in output[1], 'Missing expected warning'
+ assert 'Casting a function pointer type to another with a different number of arguments' in output[1], 'Missing expected warning'
def test_stdlibs(self):
if Settings.USE_TYPED_ARRAYS == 2: