diff options
-rw-r--r-- | src/analyzer.js | 6 | ||||
-rw-r--r-- | src/headless.js (renamed from tools/reproduceriter_shell.js) | 14 | ||||
-rw-r--r-- | src/jsifier.js | 31 | ||||
-rw-r--r-- | src/library_gl.js | 3 | ||||
-rw-r--r-- | src/library_sdl.js | 10 | ||||
-rw-r--r-- | src/parseTools.js | 3 | ||||
-rw-r--r-- | src/postamble.js | 2 | ||||
-rw-r--r-- | src/settings.js | 8 | ||||
-rw-r--r-- | system/include/SDL/SDL_rotozoom.h | 123 | ||||
-rw-r--r-- | tests/cases/fp80.ll | 21 | ||||
-rwxr-xr-x | tests/runner.py | 90 | ||||
-rw-r--r-- | tests/sdl_canvas.c | 2 | ||||
-rw-r--r-- | tests/sdl_ogl_p.c | 6 | ||||
-rw-r--r-- | tests/sdl_rotozoom.c | 48 | ||||
-rw-r--r-- | tests/sdl_rotozoom.png | bin | 0 -> 338527 bytes | |||
-rwxr-xr-x | tools/reproduceriter.py | 2 |
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 Binary files differnew file mode 100644 index 00000000..83ec0589 --- /dev/null +++ b/tests/sdl_rotozoom.png 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() + |