diff options
-rw-r--r-- | src/parseTools.js | 8 | ||||
-rw-r--r-- | src/settings.js | 4 | ||||
-rwxr-xr-x | tests/runner.py | 25 |
3 files changed, 29 insertions, 8 deletions
diff --git a/src/parseTools.js b/src/parseTools.js index 80ba269b..8e919d15 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -905,6 +905,7 @@ function getHeapOffset(offset, type) { // See makeSetValue function makeGetValue(ptr, pos, type, noNeedFirst, unsigned, ignore, align, noSafe) { + if (UNALIGNED_MEMORY) align = 1; if (isStructType(type)) { var typeData = Types.types[type]; var ret = []; @@ -930,7 +931,7 @@ function makeGetValue(ptr, pos, type, noNeedFirst, unsigned, ignore, align, noSa // Special case that we can optimize ret += makeGetValue(ptr, pos, 'i16', noNeedFirst, 2, ignore) + '+' + '(' + makeGetValue(ptr, getFastValue(pos, '+', 2), 'i16', noNeedFirst, 2, ignore) + '<<16)'; - } else if (bytes <= 4) { + } else { // XXX we cannot truly handle > 4... ret = ''; for (var i = 0; i < bytes; i++) { ret += '(' + makeGetValue(ptr, getFastValue(pos, '+', i), 'i8', noNeedFirst, 1, ignore) + (i > 0 ? '<<' + (8*i) : '') + ')'; @@ -983,7 +984,8 @@ function indexizeFunctions(value, type) { //! 'null' means, in the context of SAFE_HEAP, that we should accept all types; //! which means we should write to all slabs, ignore type differences if any on reads, etc. //! @param noNeedFirst Whether to ignore the offset in the pointer itself. -function makeSetValue(ptr, pos, value, type, noNeedFirst, ignore, align, noSafe, sep) { +function makeSetValue(ptr, pos, value, type, noNeedFirst, ignore, align, noSafe, sep, forcedAlign) { + if (UNALIGNED_MEMORY && !forcedAlign) align = 1; sep = sep || ';'; if (isStructType(type)) { var typeData = Types.types[type]; @@ -1026,7 +1028,7 @@ function makeSetValue(ptr, pos, value, type, noNeedFirst, ignore, align, noSafe, } } } else { - ret += makeSetValue('tempDoublePtr', 0, value, type, noNeedFirst, ignore, 8) + sep; + ret += makeSetValue('tempDoublePtr', 0, value, type, noNeedFirst, ignore, 8, null, null, true) + sep; ret += makeCopyValues(getFastValue(ptr, '+', pos), 'tempDoublePtr', Runtime.getNativeTypeSize(type), type, null, align, sep); } return ret; diff --git a/src/settings.js b/src/settings.js index 0b58a26f..5b1968b9 100644 --- a/src/settings.js +++ b/src/settings.js @@ -72,6 +72,10 @@ var DOUBLE_MODE = 1; // How to load and store 64-bit doubles. Without typed arra // then load it aligned, and that load-store will make JS engines alter it if it is being // stored to a typed array for security reasons. That will 'fix' the number from being a // NaN or an infinite number. +var UNALIGNED_MEMORY = 0; // If enabled, all memory accesses are assumed to be unaligned. (This only matters in + // typed arrays mode 2 where alignment is relevant.) In unaligned memory mode, you + // can run nonportable code that typically would break in JS (or on ARM for that + // matter, which also cannot do unaligned reads/writes), at the cost of slowness var PRECISE_I64_MATH = 1; // If enabled, i64 addition etc. is emulated - which is slow but precise. If disabled, // we use the 'double trick' which is fast but incurs rounding at high values. // Note that we do not catch 32-bit multiplication by default (which must be done in diff --git a/tests/runner.py b/tests/runner.py index de8acaef..db566c3f 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -1183,16 +1183,11 @@ c5,de,15,8a } ''' - Settings.EMULATE_UNALIGNED_ACCESSES = 0 - try: self.do_run(src, '*300:1*\n*515559*\n*42949672960*\n') except Exception, e: assert 'must be aligned' in str(e), e # expected to fail without emulation - # XXX TODO Settings.EMULATE_UNALIGNED_ACCESSES = 1 - #self.do_run(src, '*300:1*\n*515559*\n*42949672960*\n') # but succeeds with it - def test_unsigned(self): Settings.CORRECT_SIGNS = 1 # We test for exactly this sort of thing here Settings.CHECK_SIGNS = 0 @@ -7279,6 +7274,26 @@ f.close() Popen(['python', EMCC, os.path.join(self.get_dir(), 'test.cpp'), '-fcatch-undefined-behavior']).communicate() self.assertContained('hello, world!', run_js(os.path.join(self.get_dir(), 'a.out.js'))) + def test_unaligned_memory(self): + open(os.path.join(self.get_dir(), 'test.cpp'), 'w').write(r''' + #include <stdio.h> + + typedef unsigned char Bit8u; + typedef unsigned short Bit16u; + typedef unsigned int Bit32u; + + int main() + { + Bit8u data[4] = {0x01,0x23,0x45,0x67}; + + printf("data: %x\n", *(Bit32u*)data); + printf("data[0,1] 16bit: %x\n", *(Bit16u*)data); + printf("data[1,2] 16bit: %x\n", *(Bit16u*)(data+1)); + } + ''') + Popen(['python', EMCC, os.path.join(self.get_dir(), 'test.cpp'), '-s', 'UNALIGNED_MEMORY=1']).communicate() + self.assertContained('data: 67452301\ndata[0,1] 16bit: 2301\ndata[1,2] 16bit: 4523', run_js(os.path.join(self.get_dir(), 'a.out.js'))) + def test_l_link(self): # Linking with -lLIBNAME and -L/DIRNAME should work |