llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.87k stars 11.92k forks source link

[WebAssembly] Cannot handle irreducible CFGs caused by unwind edges #49292

Open aheejin opened 3 years ago

aheejin commented 3 years ago
Bugzilla Link 49948
Version trunk
OS All
CC @dschuff

Extended Description

Currently irreducible CFGs are fixed by WebAssemblyFixIrreducibleControlFlow pass, but irreducible CFGs caused by unwind edges are not handled by that pass. For example,

test.cpp:

void maythrow();

void test() {
  int x = 1;
lab:
  try {
    if (x) {
      maythrow();
    }
    maythrow();
  } catch (...) {
    x = 0;
    goto lab;
  }
}
$ clang++ --target=wasm32-unknown-unknown -fwasm-exceptions -O1 -c -S -emit-llvm test.cpp -o test.ll

test.ll:

target triple = "wasm32-unknown-unknown"

define void @test() personality ptr @__gxx_wasm_personality_v0 {
entry:
  invoke void @maythrow()
          to label %if.end unwind label %catch.dispatch

if.end:                                           ; preds = %catch.start, %entry
  invoke void @maythrow()
          to label %try.cont unwind label %catch.dispatch

catch.dispatch:                                   ; preds = %if.end, %entry
  %0 = catchswitch within none [label %catch.start] unwind to caller

catch.start:                                      ; preds = %catch.dispatch
  %1 = catchpad within %0 [ptr null]
  %2 = call ptr @llvm.wasm.get.exception(token %1)
  %3 = call i32 @llvm.wasm.get.ehselector(token %1)
  %4 = call ptr @__cxa_begin_catch(ptr %2) #0 [ "funclet"(token %1) ]
  call void @__cxa_end_catch() [ "funclet"(token %1) ]
  catchret from %1 to label %if.end

try.cont:                                         ; preds = %if.end
  ret void
}

declare void @maythrow()
declare i32 @__gxx_wasm_personality_v0(...)
; Function Attrs: nounwind
declare ptr @llvm.wasm.get.exception(token) #0
; Function Attrs: nounwind
declare i32 @llvm.wasm.get.ehselector(token) #0
declare ptr @__cxa_begin_catch(ptr)
declare void @__cxa_end_catch()

attributes #0 = { nounwind }

This CFG cannot be handled by the wasm backend.

$ llc -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling -verify-machineinstrs test.ll

crashes with this error message:

*** Bad machine code: MBB has unexpected successors which are not branch targets, fallthrough, EHPads, or inlineasm_br targets. ***
- function:    test
- basic block: %bb.0 entry (0x1793360)

*** Bad machine code: MBB has unexpected successors which are not branch targets, fallthrough, EHPads, or inlineasm_br targets. ***
- function:    test
- basic block: %bb.2 if.end (0x1793448)
LLVM ERROR: Found 2 machine code errors.
xgupta commented 2 years ago

This is now giving a good error message -

LLVM ERROR: -exception-model=wasm only allowed with at least one of -wasm-enable-eh or -wasm-enable-sjj

Edit - After adding -wasm-enable-eh option it is still the same error message.

aheejin commented 2 years ago

Sorry, the attached ll file was not correct. It was supposed to crash but it compiled without a problem. But you can reproduce the error if you compile the cpp file directly. I think I pasted an incorrect ll file; I'll fix that.

The error message you saw is for a different reason. A while ago we changed the necessary flags to turn on Wasm EH in llc, so now it additionally requires -wasm-enable-eh. If you use clang or emscripten that flag is supplied by them so you don't need to manually add it, but to test llc separately you need it. I'll update the original post with the correct ll file and the correct command line to reproduce the bug. By the way this bug has not been fixed yet.

fhahn commented 2 years ago

Reproduces: https://llvm.godbolt.org/z/rdPMeKr1Y