@no_wasm('uses function tables in an asm.js specific way')
@needs_dlfcn
def test_dylink_asmjs_funcpointers(self):
    self.dylink_test(main='\n      #include "header.h"\n      #include <emscripten.h>\n      void left1() { printf("left1\\n"); }\n      void left2() { printf("left2\\n"); }\n      voidfunc getleft1() { return left1; }\n      voidfunc getleft2() { return left2; }\n      int main(int argc, char **argv) {\n        printf("main\\n");\n        EM_ASM({\n          // make the function table sizes a non-power-of-two\n          var newSize = alignFunctionTables();\n          //out(\'old size of function tables: \' + newSize);\n          while ((newSize & 3) !== 3) {\n            Module[\'FUNCTION_TABLE_v\'].push(0);\n            newSize = alignFunctionTables();\n          }\n          //out(\'new size of function tables: \' + newSize);\n          // when masked, the two function pointers 1 and 2 should not happen to fall back to the right place\n          assert(((newSize+1) & 3) !== 1 || ((newSize+2) & 3) !== 2);\n          loadDynamicLibrary(\'liblib.so\');\n        });\n        volatilevoidfunc f;\n        f = (volatilevoidfunc)left1;\n        f();\n        f = (volatilevoidfunc)left2;\n        f();\n        f = (volatilevoidfunc)getright1();\n        f();\n        f = (volatilevoidfunc)getright2();\n        f();\n        second();\n        return 0;\n      }\n      ', side='\n      #include "header.h"\n      void right1() { printf("right1\\n"); }\n      void right2() { printf("right2\\n"); }\n      voidfunc getright1() { return right1; }\n      voidfunc getright2() { return right2; }\n      void second() {\n        printf("second\\n");\n        volatilevoidfunc f;\n        f = (volatilevoidfunc)getleft1();\n        f();\n        f = (volatilevoidfunc)getleft2();\n        f();\n        f = (volatilevoidfunc)right1;\n        f();\n        f = (volatilevoidfunc)right2;\n        f();\n      }\n      ', expected='main\nleft1\nleft2\nright1\nright2\nsecond\nleft1\nleft2\nright1\nright2\n', header='\n      #include <stdio.h>\n      typedef void (*voidfunc)();\n      typedef volatile voidfunc volatilevoidfunc;\n      voidfunc getleft1();\n      voidfunc getleft2();\n      voidfunc getright1();\n      voidfunc getright2();\n      void second();\n      ', need_reverse=False, auto_load=False)
@no_wasm('uses function tables in an asm.js specific way')
@needs_dlfcn
def test_dylink_asmjs_funcpointers(self):
    self.dylink_test(main='\n      #include "header.h"\n      #include <emscripten.h>\n      void left1() { printf("left1\\n"); }\n      void left2() { printf("left2\\n"); }\n      voidfunc getleft1() { return left1; }\n      voidfunc getleft2() { return left2; }\n      int main(int argc, char **argv) {\n        printf("main\\n");\n        EM_ASM({\n          // make the function table sizes a non-power-of-two\n          var newSize = alignFunctionTables();\n          //out(\'old size of function tables: \' + newSize);\n          while ((newSize & 3) !== 3) {\n            Module[\'FUNCTION_TABLE_v\'].push(0);\n            newSize = alignFunctionTables();\n          }\n          //out(\'new size of function tables: \' + newSize);\n          // when masked, the two function pointers 1 and 2 should not happen to fall back to the right place\n          assert(((newSize+1) & 3) !== 1 || ((newSize+2) & 3) !== 2);\n          loadDynamicLibrary(\'liblib.so\');\n        });\n        volatilevoidfunc f;\n        f = (volatilevoidfunc)left1;\n        f();\n        f = (volatilevoidfunc)left2;\n        f();\n        f = (volatilevoidfunc)getright1();\n        f();\n        f = (volatilevoidfunc)getright2();\n        f();\n        second();\n        return 0;\n      }\n      ', side='\n      #include "header.h"\n      void right1() { printf("right1\\n"); }\n      void right2() { printf("right2\\n"); }\n      voidfunc getright1() { return right1; }\n      voidfunc getright2() { return right2; }\n      void second() {\n        printf("second\\n");\n        volatilevoidfunc f;\n        f = (volatilevoidfunc)getleft1();\n        f();\n        f = (volatilevoidfunc)getleft2();\n        f();\n        f = (volatilevoidfunc)right1;\n        f();\n        f = (volatilevoidfunc)right2;\n        f();\n      }\n      ', expected='main\nleft1\nleft2\nright1\nright2\nsecond\nleft1\nleft2\nright1\nright2\n', header='\n      #include <stdio.h>\n      typedef void (*voidfunc)();\n      typedef volatile voidfunc volatilevoidfunc;\n      voidfunc getleft1();\n      voidfunc getleft2();\n      voidfunc getright1();\n      voidfunc getright2();\n      void second();\n      ', need_reverse=False, auto_load=False)