wasm-opt -fwasm-exceptions & asyncify

31 views
Skip to first unread message

Александр Гурьянов

unread,
Jan 27, 2023, 4:31:02 AM1/27/23
to emscripte...@googlegroups.com
Hi, I trying to add asyncify into project that uses exceptions (dosbox-x). I know that asyncify currently does not support exceptions. My idea is asyncify only "top level" functions that does not have exceptions code. My current asyncify call stack is:

js -> $runJsdos (asyncify) -> $jsdos_main (asyncify) -> $loopNoThrow -> $loop -> ...

$loop can throw exception, so  I impelemtned loopNoThrow like this:

int loopThrownNum = -1;
int loopNoThrow() {
    try {
        return (*loop)();
    } catch (int x) {
        loopThrownNum = x;
        return 0;
    } catch (...) {
        printf("throwing out loopNoThrow is not supported by asyncify\n");
        abort();
    }
}

I turning the exception into ret val, and the $jsdos_main is last asyncify function:

while (true) {
  sleep(0);
  int ret = loopNoThrow();
  // rest logic
}

To be sure that I don't use exceptions in async function, I mark them as noexcept, and compile with -fno-exceptions.

However, at link stage wasm-opt fail on assertion "unexpected expression type", because in function $runJsdos there are exception handling code.

The code of $runJsdos before wasm-opt:

(func $runJsdos (param $0 i32) (result i32)
  (drop
   (call $jsdos_main\28Config*\29
    (local.get $0)
   )
  )
  (call $jsdos::destroyAsyncify\28\29)
  (block $label$1
   (br_if $label$1
    (i32.eqz
     (local.get $0)
    )
   )
   (drop
    (call $Config::~Config\28\29
     (local.get $0)
    )
   )
  )
  (call $operator\20delete\28void*\29
   (local.get $0)
  )
  (unreachable)
 )

As you can see there is nothing related to exceptions, but AsyncifyFlow reports that $runJsdos have following code:
(try
 (do
  (local.set $3
   (i32.load $0
    (i32.const 1889704)
   )
  )
  (nop)
  (local.set $3
   (call_indirect $0 (type $none_=>_i32)
    (local.get $3)
   )
  )
 )
 (catch $tag$0
  (local.set $0
   (pop i32)
  )
  (nop)
  (nop)
  (nop)
  (global.set $__stack_pointer
   (local.get $2)
  )
  (i32.store $0
   (i32.const 40043732)
   (i32.const 1052)
  )
  (i32.store $0
   (i32.const 40043728)
   (i32.const 0)
  )
  (nop)
  (call $_Unwind_CallPersonality
   (local.get $0)
  )
  (nop)
  (local.set $1
   (i32.load $0
    (i32.const 40043736)
   )
  )
  (nop)
  (nop)
  (local.set $0
   (call $__cxa_begin_catch
    (local.get $0)
   )
  )
  (nop)
  (local.set $1
   (i32.eq
    (local.get $1)
    (i32.const 2)
   )
  )
  (if
   (local.get $1)
   (block
    (nop)
    (local.set $0
     (i32.load $0
      (local.get $0)
     )
    )
    (i32.store $0
     (i32.const 1149424)
     (local.get $0)
    )
    (call $__cxa_end_catch)
    (unreachable)
   )
  )
  (call $puts
   (i32.const 5497)
  )
  (try $label$938
   (do
    (call $abort)
   )
   (catch_all
    (nop)
    (global.set $__stack_pointer
     (local.get $2)
    )
    (try
     (do
      (call $__cxa_end_catch)
     )
     (catch_all
      (nop)
      (global.set $__stack_pointer
       (local.get $2)
      )
      (call $std::terminate\28\29)
      (unreachable)
     )
    )
    (rethrow $label$938)
   )
  )
  (unreachable)
 )
)

Probably this happens because of some inlining, I compile with -Oz, but I am not sure. How I can avoid injection of exception handling code into this functions?

Thank you!

Александр Гурьянов

unread,
Jan 27, 2023, 5:01:46 AM1/27/23
to emscripte...@googlegroups.com
Checked other optimization flags, defenitly this happens befcause of -Oz.
-O0, -O1 - works fine, I even can run Windows 95 that hardly uses exceptions code 🥳🥳🥳
-Oz, -O2 - not working (assertion "unexpected expression type")

So I need somehow exclude this two functions from optimization and then I will have optimized code with exceptiosn that works fine with asyncify. How I can do this?



пт, 27 янв. 2023 г. в 12:30, Александр Гурьянов <caii...@gmail.com>:

Alon Zakai

unread,
Jan 31, 2023, 3:49:20 PM1/31/23
to emscripte...@googlegroups.com
Are you saying LLVM optimizations cause try-catch to appear? That seems odd to me. Unless it really is simply because of inlining - in that case [[noinline]] can help.

Otherwise I think try-catch like those, which are really just to call std::terminate() on an exception, are added by clang in some cases, see details here:


If nothing else works, the Binaryen pass mentioned there might be modified to manually remove try-catches perhaps.

--
You received this message because you are subscribed to the Google Groups "emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-disc...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/emscripten-discuss/CAKOm%3DVH9DWG4WvMnrddZRJAgbBM-PU5poaoPeN7CopTE0xKi9w%40mail.gmail.com.

Александр Гурьянов

unread,
Feb 2, 2023, 2:00:00 AM2/2/23
to emscripte...@googlegroups.com
I think this is inlining, anyway I implemented better and more general solution:


вт, 31 янв. 2023 г. в 23:49, Alon Zakai <alon...@gmail.com>:
Reply all
Reply to author
Forward
0 new messages