diff options
author | Alon Zakai <alonzakai@gmail.com> | 2014-05-28 14:50:35 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2014-05-28 14:50:35 -0700 |
commit | 504b62384aba8da8258ed6f8ba0a455a1db7736a (patch) | |
tree | 310e8b2bba9c2ac4ea2c05133905515aa788677d | |
parent | 8abdafadfcd61cc9874b4e5ea6b43e3651f26070 (diff) |
add emscripten_align typedefs for #2378
-rw-r--r-- | system/include/emscripten/emscripten.h | 26 | ||||
-rw-r--r-- | tests/core/test_set_align.c | 50 | ||||
-rw-r--r-- | tests/core/test_set_align.out | 8 | ||||
-rw-r--r-- | tests/test_core.py | 9 |
4 files changed, 93 insertions, 0 deletions
diff --git a/system/include/emscripten/emscripten.h b/system/include/emscripten/emscripten.h index 66017a8d..8a08aabb 100644 --- a/system/include/emscripten/emscripten.h +++ b/system/include/emscripten/emscripten.h @@ -18,6 +18,32 @@ extern "C" { #include <SDL/SDL.h> /* for SDL_Delay in async_call */ #endif + +/* Typedefs */ + +/* + * Unaligned types, helpful to force LLVM to emit unaligned + * loads/stores in places in your code where SAFE_HEAP found + * an unaligned operation. (It's better to avoid unaligned + * operations, but if you are reading from a packed stream of + * bytes or such, these types may be useful.) + */ + +typedef short __attribute__((aligned(1))) emscripten_align1_short; + +typedef int __attribute__((aligned(2))) emscripten_align2_int; +typedef int __attribute__((aligned(1))) emscripten_align1_int; + +typedef float __attribute__((aligned(2))) emscripten_align2_float; +typedef float __attribute__((aligned(1))) emscripten_align1_float; + +typedef double __attribute__((aligned(4))) emscripten_align4_double; +typedef double __attribute__((aligned(2))) emscripten_align2_double; +typedef double __attribute__((aligned(1))) emscripten_align1_double; + + +/* Functions */ + /* * Convenient syntax for inline assembly/js. Allows stuff like * diff --git a/tests/core/test_set_align.c b/tests/core/test_set_align.c new file mode 100644 index 00000000..26158ef4 --- /dev/null +++ b/tests/core/test_set_align.c @@ -0,0 +1,50 @@ + +#include <stdio.h> +#include <emscripten.h> + +volatile char data[16]; + +__attribute__((noinline)) void *get_aligned(int align) +{ + char *ptr = (char*)(((int)(data + 7)) & ~7); // Make 8-byte aligned + ptr += align; // Now 'align' aligned + return (void*)ptr; +} + +int main() +{ + emscripten_align4_double *d4 = (emscripten_align4_double*)get_aligned(4); + *d4 = 17.0; + printf("addr: %d, value: %f\n", ((int)d4) % 8, *d4); + + emscripten_align2_double *d2 = (emscripten_align2_double*)get_aligned(2); + *d2 = 18.0; + printf("addr: %d, value: %f\n", ((int)d2) % 8, *d2); + + emscripten_align1_double *d1 = (emscripten_align1_double*)get_aligned(1); + *d1 = 19.0; + printf("addr: %d, value: %f\n", ((int)d1) % 8, *d1); + + emscripten_align2_float *f2 = (emscripten_align2_float*)get_aligned(2); + *f2 = 20.0; + printf("addr: %d, value: %f\n", ((int)f2) % 4, *f2); + + emscripten_align1_float *f1 = (emscripten_align1_float*)get_aligned(1); + *f1 = 21.0; + printf("addr: %d, value: %f\n", ((int)f1) % 4, *f1); + + emscripten_align2_int *i2 = (emscripten_align2_int*)get_aligned(2); + *i2 = 22; + printf("addr: %d, value: %d\n", ((int)i2) % 4, *i2); + + emscripten_align1_int *i1 = (emscripten_align1_int*)get_aligned(1); + *i1 = 23; + printf("addr: %d, value: %d\n", ((int)i1) % 4, *i1); + + emscripten_align1_short *s1 = (emscripten_align1_short*)get_aligned(1); + *s1 = 24; + printf("addr: %d, value: %d\n", ((int)s1) % 4, (int)*s1); + + return 0; +} + diff --git a/tests/core/test_set_align.out b/tests/core/test_set_align.out new file mode 100644 index 00000000..55e377b0 --- /dev/null +++ b/tests/core/test_set_align.out @@ -0,0 +1,8 @@ +addr: 4, value: 17.000000 +addr: 2, value: 18.000000 +addr: 1, value: 19.000000 +addr: 2, value: 20.000000 +addr: 1, value: 21.000000 +addr: 2, value: 22 +addr: 1, value: 23 +addr: 1, value: 24 diff --git a/tests/test_core.py b/tests/test_core.py index 62a061e2..505a051b 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -1980,6 +1980,15 @@ too many setjmps in a function call, build with a higher value for MAX_SETJMPS'' self.do_run_from_file(src, output) + def test_set_align(self): + if self.run_name == 'slow2asm': return self.skip('FIXME in slow2asm') + + Settings.SAFE_HEAP = 1 + + test_path = path_from_root('tests', 'core', 'test_set_align') + src, output = (test_path + s for s in ('.c', '.out')) + self.do_run_from_file(src, output) + def test_emscripten_api(self): #if Settings.MICRO_OPTS or Settings.RELOOP or Building.LLVM_OPTS: return self.skip('FIXME') |