summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/analyzer.js6
-rw-r--r--src/headless.js (renamed from tools/reproduceriter_shell.js)14
-rw-r--r--src/jsifier.js31
-rw-r--r--src/library_gl.js3
-rw-r--r--src/library_sdl.js10
-rw-r--r--src/parseTools.js3
-rw-r--r--src/postamble.js2
-rw-r--r--src/settings.js8
-rw-r--r--system/include/SDL/SDL_rotozoom.h123
-rw-r--r--tests/cases/fp80.ll21
-rwxr-xr-xtests/runner.py90
-rw-r--r--tests/sdl_canvas.c2
-rw-r--r--tests/sdl_ogl_p.c6
-rw-r--r--tests/sdl_rotozoom.c48
-rw-r--r--tests/sdl_rotozoom.pngbin0 -> 338527 bytes
-rwxr-xr-xtools/reproduceriter.py2
16 files changed, 357 insertions, 12 deletions
diff --git a/src/analyzer.js b/src/analyzer.js
index fa8aee59..c09739e9 100644
--- a/src/analyzer.js
+++ b/src/analyzer.js
@@ -467,6 +467,12 @@ function analyzer(data, sidePass) {
break;
}
case 'bitcast': {
+ if (!sourceBits) {
+ // we can be asked to bitcast doubles or such to integers, handle that as best we can (if it's a double that
+ // was an x86_fp80, this code will likely break when called)
+ sourceBits = targetBits = Runtime.getNativeTypeSize(value.params[0].type);
+ warn('legalizing non-integer bitcast on ll #' + item.lineNum);
+ }
break;
}
case 'select': {
diff --git a/tools/reproduceriter_shell.js b/src/headless.js
index f425df82..a528e8af 100644
--- a/tools/reproduceriter_shell.js
+++ b/src/headless.js
@@ -1,4 +1,6 @@
+//== HEADLESS ==//
+
var window = {
location: {
toString: function() {
@@ -666,6 +668,11 @@ var document = {
data: new Uint8ClampedArray(w*h),
};
},
+ save: function(){},
+ restore: function(){},
+ fillRect: function(){},
+ measureText: function() { return 10 },
+ fillText: function(){},
};
}
default: throw 'canvas.getContext: ' + which;
@@ -869,3 +876,10 @@ var MozBlobBuilder = function() {
};
};
+// additional setup
+if (!Module['canvas']) {
+ Module['canvas'] = document.getElementById('canvas');
+}
+
+//== HEADLESS ==//
+
diff --git a/src/jsifier.js b/src/jsifier.js
index 9c022efb..fae92f70 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -1148,6 +1148,7 @@ function JSify(data, functionsOnly, givenFunctions) {
var argsTypes = [];
var varargs = [];
var varargsTypes = [];
+ var varargsByVals = {};
var ignoreFunctionIndexizing = [];
var useJSArgs = (shortident + '__jsargs') in LibraryManager.library;
var hasVarArgs = isVarArgsFunctionType(type);
@@ -1159,10 +1160,18 @@ function JSify(data, functionsOnly, givenFunctions) {
args.push(val);
argsTypes.push(param.type);
} else {
+ var size;
+ if (param.byVal) {
+ varargsByVals[varargs.length] = param.byVal;
+ size = calcAllocatedSize(removeAllPointing(param.type));
+ } else {
+ size = Runtime.getNativeFieldSize(param.type);
+ }
varargs.push(val);
- varargs = varargs.concat(zeros(Runtime.getNativeFieldSize(param.type)-1));
+ varargs = varargs.concat(zeros(size-1));
+ // TODO: replace concats like this with push
varargsTypes.push(param.type);
- varargsTypes = varargsTypes.concat(zeros(Runtime.getNativeFieldSize(param.type)-1));
+ varargsTypes = varargsTypes.concat(zeros(size-1));
}
});
@@ -1182,8 +1191,17 @@ function JSify(data, functionsOnly, givenFunctions) {
varargs.map(function(arg, i) {
var type = varargsTypes[i];
if (type == 0) return null;
- var ret = makeSetValue(getFastValue('tempInt', '+', offset), 0, arg, type, null, null, QUANTUM_SIZE, null, ',');
- offset += Runtime.getNativeFieldSize(type);
+ var ret;
+ if (!varargsByVals[i]) {
+ ret = makeSetValue(getFastValue('tempInt', '+', offset), 0, arg, type, null, null, QUANTUM_SIZE, null, ',');
+ offset += Runtime.getNativeFieldSize(type);
+ } else {
+ assert(offset % 4 == 0); // varargs must be aligned
+ var size = calcAllocatedSize(removeAllPointing(type));
+ assert(size % 4 == 0); // varargs must stay aligned
+ ret = makeCopyValues(getFastValue('tempInt', '+', offset), arg, size, null, null, varargsByVals[i], ',');
+ offset += size;
+ }
return ret;
}).filter(function(arg) {
return arg !== null;
@@ -1276,6 +1294,11 @@ function JSify(data, functionsOnly, givenFunctions) {
print('// Warning: printing of i64 values may be slightly rounded! No deep i64 math used, so precise i64 code not included');
print('var i64Math = null;');
}
+ if (HEADLESS) {
+ print('if (!ENVIRONMENT_IS_WEB) {');
+ print(read('headless.js').replace("'%s'", "'http://emscripten.org'").replace("'?%s'", "''").replace('%s,', 'null,').replace('%d', '0'));
+ print('}');
+ }
var generated = itemsDict.functionStub.concat(itemsDict.GlobalVariablePostSet);
generated.forEach(function(item) { print(indentify(item.JS || '', 2)); });
if (RUNTIME_TYPE_INFO) {
diff --git a/src/library_gl.js b/src/library_gl.js
index 99198196..4d83572e 100644
--- a/src/library_gl.js
+++ b/src/library_gl.js
@@ -2080,6 +2080,9 @@ var LibraryGL = {
glVertex3fv: function(p) {
_glVertex3f({{{ makeGetValue('p', '0', 'float') }}}, {{{ makeGetValue('p', '4', 'float') }}}, {{{ makeGetValue('p', '8', 'float') }}});
},
+ glVertex2fv: function(p) {
+ _glVertex2f({{{ makeGetValue('p', '0', 'float') }}}, {{{ makeGetValue('p', '4', 'float') }}});
+ },
glTexCoord2i: function(u, v) {
#if ASSERTIONS
diff --git a/src/library_sdl.js b/src/library_sdl.js
index 4cb4ca6f..0969f738 100644
--- a/src/library_sdl.js
+++ b/src/library_sdl.js
@@ -966,6 +966,16 @@ var LibrarySDL = {
return _SDL_UpperBlit(src, srcrect, dst, dstrect);
},
+ zoomSurface: function(src, x, y, smooth) {
+ var srcData = SDL.surfaces[src];
+ var w = srcData.width*x;
+ var h = srcData.height*y;
+ var ret = SDL.makeSurface(w, h, srcData.flags, false, 'zoomSurface');
+ var dstData = SDL.surfaces[ret];
+ dstData.ctx.drawImage(srcData.canvas, 0, 0, w, h);
+ return ret;
+ },
+
SDL_SetAlpha: function(surf, flag, alpha) {
SDL.surfaces[surf].alpha = alpha;
},
diff --git a/src/parseTools.js b/src/parseTools.js
index e76d23be..6a10176c 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -847,7 +847,6 @@ function indentify(text, indent) {
// Correction tools
function correctSpecificSign() {
- assert(!(CORRECT_SIGNS >= 2 && !Debugging.on), 'Need debugging for line-specific corrections');
if (!Framework.currItem) return false;
if (Framework.currItem.funcData.ident.indexOf('emscripten_autodebug') >= 0) return 1; // always correct in the autodebugger code!
return (CORRECT_SIGNS === 2 && Debugging.getIdentifier() in CORRECT_SIGNS_LINES) ||
@@ -858,7 +857,6 @@ function correctSigns() {
}
function correctSpecificOverflow() {
- assert(!(CORRECT_OVERFLOWS >= 2 && !Debugging.on), 'Need debugging for line-specific corrections');
if (!Framework.currItem) return false;
return (CORRECT_OVERFLOWS === 2 && Debugging.getIdentifier() in CORRECT_OVERFLOWS_LINES) ||
(CORRECT_OVERFLOWS === 3 && !(Debugging.getIdentifier() in CORRECT_OVERFLOWS_LINES));
@@ -868,7 +866,6 @@ function correctOverflows() {
}
function correctSpecificRounding() {
- assert(!(CORRECT_ROUNDINGS >= 2 && !Debugging.on), 'Need debugging for line-specific corrections');
if (!Framework.currItem) return false;
return (CORRECT_ROUNDINGS === 2 && Debugging.getIdentifier() in CORRECT_ROUNDINGS_LINES) ||
(CORRECT_ROUNDINGS === 3 && !(Debugging.getIdentifier() in CORRECT_ROUNDINGS_LINES));
diff --git a/src/postamble.js b/src/postamble.js
index a4c43018..144b5af9 100644
--- a/src/postamble.js
+++ b/src/postamble.js
@@ -82,7 +82,7 @@ function run(args) {
return doRun();
}
}
-Module['run'] = run;
+Module['run'] = Module.run = run;
// {{PRE_RUN_ADDITIONS}}
diff --git a/src/settings.js b/src/settings.js
index 5d4299a4..58635950 100644
--- a/src/settings.js
+++ b/src/settings.js
@@ -277,6 +277,14 @@ var SMALL_XHR_CHUNKS = 0; // Use small chunk size for binary synchronous XHR's i
// Used for testing.
// See test_chunked_synchronous_xhr in runner.py and library.js.
+var HEADLESS = 0; // If 1, will include shim code that tries to 'fake' a browser
+ // environment, in order to let you run a browser program (say,
+ // using SDL) in the shell. Obviously nothing is rendered, but
+ // this can be useful for benchmarking and debugging if actual
+ // rendering is not the issue. Note that the shim code is
+ // very partial - it is hard to fake a whole browser! - so
+ // keep your expectations low for this to work.
+
var NECESSARY_BLOCKADDRS = []; // List of (function, block) for all block addresses that are taken.
// Compiler debugging options
diff --git a/system/include/SDL/SDL_rotozoom.h b/system/include/SDL/SDL_rotozoom.h
new file mode 100644
index 00000000..65b914a9
--- /dev/null
+++ b/system/include/SDL/SDL_rotozoom.h
@@ -0,0 +1,123 @@
+/*
+
+SDL_rotozoom.c: rotozoomer, zoomer and shrinker for 32bit or 8bit surfaces
+
+Copyright (C) 2001-2011 Andreas Schiffler
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+ 3. This notice may not be removed or altered from any source
+ distribution.
+
+Andreas Schiffler -- aschiffler at ferzkopp dot net
+
+*/
+
+#ifndef _SDL_rotozoom_h
+#define _SDL_rotozoom_h
+
+#include <math.h>
+
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef M_PI
+#define M_PI 3.141592654
+#endif
+
+#include "SDL.h"
+
+ /* ---- Defines */
+
+ /*!
+ \brief Disable anti-aliasing (no smoothing).
+ */
+#define SMOOTHING_OFF 0
+
+ /*!
+ \brief Enable anti-aliasing (smoothing).
+ */
+#define SMOOTHING_ON 1
+
+ /* ---- Function Prototypes */
+
+#ifdef _MSC_VER
+# if defined(DLL_EXPORT) && !defined(LIBSDL_GFX_DLL_IMPORT)
+# define SDL_ROTOZOOM_SCOPE __declspec(dllexport)
+# else
+# ifdef LIBSDL_GFX_DLL_IMPORT
+# define SDL_ROTOZOOM_SCOPE __declspec(dllimport)
+# endif
+# endif
+#endif
+#ifndef SDL_ROTOZOOM_SCOPE
+# define SDL_ROTOZOOM_SCOPE extern
+#endif
+
+ /*
+
+ Rotozoom functions
+
+ */
+
+ SDL_ROTOZOOM_SCOPE SDL_Surface *rotozoomSurface(SDL_Surface * src, double angle, double zoom, int smooth);
+
+ SDL_ROTOZOOM_SCOPE SDL_Surface *rotozoomSurfaceXY
+ (SDL_Surface * src, double angle, double zoomx, double zoomy, int smooth);
+
+
+ SDL_ROTOZOOM_SCOPE void rotozoomSurfaceSize(int width, int height, double angle, double zoom, int *dstwidth,
+ int *dstheight);
+
+ SDL_ROTOZOOM_SCOPE void rotozoomSurfaceSizeXY
+ (int width, int height, double angle, double zoomx, double zoomy,
+ int *dstwidth, int *dstheight);
+
+ /*
+
+ Zooming functions
+
+ */
+
+ SDL_ROTOZOOM_SCOPE SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth);
+
+ SDL_ROTOZOOM_SCOPE void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight);
+
+ /*
+
+ Shrinking functions
+
+ */
+
+ SDL_ROTOZOOM_SCOPE SDL_Surface *shrinkSurface(SDL_Surface * src, int factorx, int factory);
+
+ /*
+
+ Specialized rotation functions
+
+ */
+
+ SDL_ROTOZOOM_SCOPE SDL_Surface* rotateSurface90Degrees(SDL_Surface* src, int numClockwiseTurns);
+
+ /* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SDL_rotozoom_h */
diff --git a/tests/cases/fp80.ll b/tests/cases/fp80.ll
new file mode 100644
index 00000000..7fc0db4a
--- /dev/null
+++ b/tests/cases/fp80.ll
@@ -0,0 +1,21 @@
+; ModuleID = 'src.cpp.o'
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
+target triple = "i386-pc-linux-gnu"
+
+@.str = private unnamed_addr constant [15 x i8] c"hello, world!\0A\00" ; [#uses=1]
+
+; [#uses=0]
+define i32 @main() {
+entry:
+ %x = zext i32 0 to x86_fp80
+ %1 = bitcast x86_fp80 %x to i80
+ %2 = trunc i80 %1 to i32
+ %retval = alloca i32, align 4 ; [#uses=1]
+ store i32 0, i32* %retval
+ %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0)) ; [#uses=0]
+ ret i32 0
+}
+
+; [#uses=1]
+declare i32 @printf(i8*, ...)
+
diff --git a/tests/runner.py b/tests/runner.py
index 17bc7d2c..dfe435a7 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -3012,6 +3012,78 @@ def process(filename):
'''
self.do_run(src, '*cheez: 0+24*\n*cheez: 0+24*\n*albeit*\n*albeit*\nQ85*\nmaxxi:21*\nmaxxD:22.10*\n*vfp:22,199*\n*vfp:22,199*\n')
+ def test_varargs_byval(self):
+ if Settings.USE_TYPED_ARRAYS != 2: return self.skip('FIXME: Add support for this')
+
+ src = r'''
+ #include <stdio.h>
+ #include <stdarg.h>
+
+ typedef struct type_a {
+ union {
+ double f;
+ void *p;
+ int i;
+ short sym;
+ } value;
+ } type_a;
+
+ enum mrb_vtype {
+ MRB_TT_FALSE = 0, /* 0 */
+ MRB_TT_CLASS = 9 /* 9 */
+ };
+
+ typedef struct type_b {
+ enum mrb_vtype tt:8;
+ } type_b;
+
+ void print_type_a(int argc, ...);
+ void print_type_b(int argc, ...);
+
+ int main(int argc, char *argv[])
+ {
+ type_a a;
+ type_b b;
+ a.value.p = (void*) 0x12345678;
+ b.tt = MRB_TT_CLASS;
+
+ printf("The original address of a is: %p\n", a.value.p);
+ printf("The original type of b is: %d\n", b.tt);
+
+ print_type_a(1, a);
+ print_type_b(1, b);
+
+ return 0;
+ }
+
+ void print_type_a(int argc, ...) {
+ va_list ap;
+ type_a a;
+
+ va_start(ap, argc);
+ a = va_arg(ap, type_a);
+ va_end(ap);
+
+ printf("The current address of a is: %p\n", a.value.p);
+ }
+
+ void print_type_b(int argc, ...) {
+ va_list ap;
+ type_b b;
+
+ va_start(ap, argc);
+ b = va_arg(ap, type_b);
+ va_end(ap);
+
+ printf("The current type of b is: %d\n", b.tt);
+ }
+ '''
+ self.do_run(src, '''The original address of a is: 0x12345678
+The original type of b is: 9
+The current address of a is: 0x12345678
+The current type of b is: 9
+''')
+
def test_structbyval(self):
# part 1: make sure that normally, passing structs by value works
@@ -8306,6 +8378,20 @@ fscanfed: 10 - hello
Popen(['python', FILE_PACKAGER, 'test.data', '--pre-run', '--crunch=32', '--preload', 'ship.dds'], stdout=open('pre.js', 'w')).communicate()
assert crunch_time < os.stat('ship.crn').st_mtime, 'Crunch was changed'
+ def test_headless(self):
+ if SPIDERMONKEY_ENGINE not in JS_ENGINES: return self.skip('cannot run without spidermonkey due to node limitations (Uint8ClampedArray etc.)')
+
+ shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'example.png'))
+ Popen(['python', EMCC, path_from_root('tests', 'sdl_canvas.c'), '-s', 'HEADLESS=1']).communicate()
+ output = run_js('a.out.js', engine=SPIDERMONKEY_ENGINE, stderr=PIPE)
+ assert '''Init: 0
+Font: 0x1
+Sum: 0
+you should see two lines of text in different colors and a blue rectangle
+SDL_Quit called (and ignored)
+done.
+''' in output, output
+
elif 'browser' in str(sys.argv):
# Browser tests.
@@ -9316,6 +9402,10 @@ elif 'browser' in str(sys.argv):
def test_sdl_maprgba(self):
self.btest('sdl_maprgba.c', reference='sdl_maprgba.png', reference_slack=3)
+ def test_sdl_rotozoom(self):
+ shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'example.png'))
+ self.btest('sdl_rotozoom.c', reference='sdl_rotozoom.png', args=['--preload-file', 'example.png'])
+
def zzztest_sdl_canvas_palette_2(self): # XXX disabled until we have proper automation
open(os.path.join(self.get_dir(), 'sdl_canvas_palette_2.c'), 'w').write(self.with_report_result(open(path_from_root('tests', 'sdl_canvas_palette_2.c')).read()))
open(os.path.join(self.get_dir(), 'pre.js'), 'w').write('Module[\'preRun\'] = function() { SDL.defaults.copyOnLock = false }')
diff --git a/tests/sdl_canvas.c b/tests/sdl_canvas.c
index 5d1c849c..7dcfa043 100644
--- a/tests/sdl_canvas.c
+++ b/tests/sdl_canvas.c
@@ -53,6 +53,8 @@ int main(int argc, char **argv) {
SDL_Quit();
+ printf("done.\n");
+
int result = sum > 3000 && sum < 5000; // varies a little on different browsers, font differences?
REPORT_RESULT();
diff --git a/tests/sdl_ogl_p.c b/tests/sdl_ogl_p.c
index 949aaa44..fcc53a40 100644
--- a/tests/sdl_ogl_p.c
+++ b/tests/sdl_ogl_p.c
@@ -145,9 +145,9 @@ int main(int argc, char *argv[])
// Render the last item using oldschool glBegin etc
glBegin( GL_TRIANGLE_STRIP );
glTexCoord2i( 0, 0 ); glVertex3f( 100, 300, 0 );
- glTexCoord2i( 1, 0 ); glVertex3f( 300, 300, 0 );
- glTexCoord2i( 1, 1 ); glVertex3f( 300, 400, 0 );
- glTexCoord2i( 0, 1 ); glVertex3f( 500, 410, 0 );
+ glTexCoord2i( 1, 0 ); glVertex2f( 300, 300 );
+ glTexCoord2i( 1, 1 ); { float vals[3] = { 300, 400, 0 }; glVertex3fv(vals); }
+ glTexCoord2i( 0, 1 ); { float vals[2] = { 500, 410 }; glVertex2fv(vals); }
glEnd();
SDL_GL_SwapBuffers();
diff --git a/tests/sdl_rotozoom.c b/tests/sdl_rotozoom.c
new file mode 100644
index 00000000..cb6295cc
--- /dev/null
+++ b/tests/sdl_rotozoom.c
@@ -0,0 +1,48 @@
+#include "SDL/SDL.h"
+#include "SDL/SDL_image.h"
+#include "SDL/SDL_rotozoom.h"
+
+#ifdef EMSCRIPTEN
+#include "emscripten.h"
+#endif
+
+SDL_Surface *screen;
+SDL_Surface *sprite[4];
+
+void mainloop() {
+ int i;
+ SDL_Rect rect = { 0, 0, 100, 100 };
+ for (i = 0; i < 4; i++) {
+ rect.x = i & 1 ? 200 : 0;
+ rect.y = i & 2 ? 200 : 0;
+ SDL_BlitSurface(sprite[i], 0, screen, &rect);
+ SDL_UpdateRect(screen, 0, 0, 0, 0);
+ }
+}
+
+int main(int argc, char **argv) {
+ SDL_Init(SDL_INIT_VIDEO);
+
+ screen = SDL_SetVideoMode(400, 400, 32, SDL_SWSURFACE);
+
+ sprite[0] = IMG_Load("example.png");
+ sprite[1] = SDL_CreateRGBSurface(SDL_SWSURFACE, 100, 100, 32, 0xFF000000, 0xFF0000, 0xFF00, 0xFF);
+ SDL_FillRect(sprite[1], 0, 0xA0A0A0A0);
+ sprite[2] = zoomSurface(sprite[0], 0.5, 0.5, SMOOTHING_ON);
+ sprite[3] = zoomSurface(sprite[1], 0.5, 0.5, SMOOTHING_ON);
+
+ mainloop();
+
+#ifndef EMSCRIPTEN
+ SDL_Event evt;
+ while (1) {
+ if (SDL_PollEvent(&evt) != 0 && evt.type == SDL_QUIT) break;
+ //mainloop();
+ SDL_Delay(33);
+ }
+#endif
+
+ SDL_Quit();
+
+ return 1;
+}
diff --git a/tests/sdl_rotozoom.png b/tests/sdl_rotozoom.png
new file mode 100644
index 00000000..83ec0589
--- /dev/null
+++ b/tests/sdl_rotozoom.png
Binary files differ
diff --git a/tools/reproduceriter.py b/tools/reproduceriter.py
index a1912396..058eeecf 100755
--- a/tools/reproduceriter.py
+++ b/tools/reproduceriter.py
@@ -149,7 +149,7 @@ for parent, dirs, files in os.walk(out_dir):
print 'add boilerplate...'
open(os.path.join(out_dir, first_js), 'w').write(
- (open(os.path.join(os.path.dirname(__file__), 'reproduceriter_shell.js')).read() % (
+ (open(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'src', 'headless.js')).read() % (
window_location, window_location.split('?')[-1], on_idle or 'null', dirs_to_drop
) if shell else '') +
open(os.path.join(os.path.dirname(__file__), 'reproduceriter.js')).read() +