2019-02-26 11:29:59 +08:00
|
|
|
; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -exception-model=wasm -mattr=+exception-handling | FileCheck %s
|
2019-03-27 01:15:55 +08:00
|
|
|
; RUN: llc < %s -O0 -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -verify-machineinstrs -exception-model=wasm -mattr=+exception-handling | FileCheck %s --check-prefix=NOOPT
|
2019-03-30 19:04:48 +08:00
|
|
|
; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -exception-model=wasm -mattr=+exception-handling -wasm-disable-ehpad-sort | FileCheck %s --check-prefix=NOSORT
|
2018-08-08 04:19:23 +08:00
|
|
|
|
|
|
|
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
|
|
|
|
target triple = "wasm32-unknown-unknown"
|
|
|
|
|
|
|
|
@_ZTIi = external constant i8*
|
|
|
|
@_ZTId = external constant i8*
|
|
|
|
|
|
|
|
; Simple test case with two catch clauses
|
2019-02-26 11:29:59 +08:00
|
|
|
;
|
|
|
|
; void foo();
|
[WebAssembly] Exception handling: Switch to the new proposal
Summary:
This switches the EH implementation to the new proposal:
https://github.com/WebAssembly/exception-handling/blob/master/proposals/Exceptions.md
(The previous proposal was
https://github.com/WebAssembly/exception-handling/blob/master/proposals/old/Exceptions.md)
- Instruction changes
- Now we have one single `catch` instruction that returns a except_ref
value
- `throw` now can take variable number of operations
- `rethrow` does not have 'depth' argument anymore
- `br_on_exn` queries an except_ref to see if it matches the tag and
branches to the given label if true.
- `extract_exception` is a pseudo instruction that simulates popping
values from wasm stack. This is to make `br_on_exn`, a very special
instruction, work: `br_on_exn` puts values onto the stack only if it
is taken, and the # of values can vay depending on the tag.
- Now there's only one `catch` per `try`, this patch removes all special
handling for terminate pad with a call to `__clang_call_terminate`.
Before it was the only case there are two catch clauses (a normal
`catch` and `catch_all` per `try`).
- Make `rethrow` act as a terminator like `throw`. This splits BB after
`rethrow` in WasmEHPrepare, and deletes an unnecessary `unreachable`
after `rethrow` in LateEHPrepare.
- Now we stop at all catchpads (because we add wasm `catch` instruction
that catches all exceptions), this creates new
`findWasmUnwindDestinations` function in SelectionDAGBuilder.
- Now we use `br_on_exn` instrution to figure out if an except_ref
matches the current tag or not, LateEHPrepare generates this sequence
for catch pads:
```
catch
block i32
br_on_exn $__cpp_exception
end_block
extract_exception
```
- Branch analysis for `br_on_exn` in WebAssemblyInstrInfo
- Other various misc. changes to switch to the new proposal.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D57134
llvm-svn: 352598
2019-01-30 11:21:57 +08:00
|
|
|
; void test0() {
|
|
|
|
; try {
|
|
|
|
; foo();
|
2019-02-26 11:29:59 +08:00
|
|
|
; } catch (int) {
|
|
|
|
; } catch (double) {
|
[WebAssembly] Exception handling: Switch to the new proposal
Summary:
This switches the EH implementation to the new proposal:
https://github.com/WebAssembly/exception-handling/blob/master/proposals/Exceptions.md
(The previous proposal was
https://github.com/WebAssembly/exception-handling/blob/master/proposals/old/Exceptions.md)
- Instruction changes
- Now we have one single `catch` instruction that returns a except_ref
value
- `throw` now can take variable number of operations
- `rethrow` does not have 'depth' argument anymore
- `br_on_exn` queries an except_ref to see if it matches the tag and
branches to the given label if true.
- `extract_exception` is a pseudo instruction that simulates popping
values from wasm stack. This is to make `br_on_exn`, a very special
instruction, work: `br_on_exn` puts values onto the stack only if it
is taken, and the # of values can vay depending on the tag.
- Now there's only one `catch` per `try`, this patch removes all special
handling for terminate pad with a call to `__clang_call_terminate`.
Before it was the only case there are two catch clauses (a normal
`catch` and `catch_all` per `try`).
- Make `rethrow` act as a terminator like `throw`. This splits BB after
`rethrow` in WasmEHPrepare, and deletes an unnecessary `unreachable`
after `rethrow` in LateEHPrepare.
- Now we stop at all catchpads (because we add wasm `catch` instruction
that catches all exceptions), this creates new
`findWasmUnwindDestinations` function in SelectionDAGBuilder.
- Now we use `br_on_exn` instrution to figure out if an except_ref
matches the current tag or not, LateEHPrepare generates this sequence
for catch pads:
```
catch
block i32
br_on_exn $__cpp_exception
end_block
extract_exception
```
- Branch analysis for `br_on_exn` in WebAssemblyInstrInfo
- Other various misc. changes to switch to the new proposal.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D57134
llvm-svn: 352598
2019-01-30 11:21:57 +08:00
|
|
|
; }
|
|
|
|
; }
|
2018-08-08 04:19:23 +08:00
|
|
|
|
|
|
|
; CHECK-LABEL: test0
|
2019-02-27 08:50:53 +08:00
|
|
|
; CHECK: try
|
|
|
|
; CHECK: call foo
|
|
|
|
; CHECK: catch
|
|
|
|
; CHECK: block
|
|
|
|
; CHECK: br_if 0, {{.*}} # 0: down to label2
|
|
|
|
; CHECK: i32.call $drop=, __cxa_begin_catch
|
|
|
|
; CHECK: call __cxa_end_catch
|
|
|
|
; CHECK: br 1 # 1: down to label0
|
|
|
|
; CHECK: end_block # label2:
|
|
|
|
; CHECK: block
|
|
|
|
; CHECK: br_if 0, {{.*}} # 0: down to label3
|
|
|
|
; CHECK: i32.call $drop=, __cxa_begin_catch
|
|
|
|
; CHECK: call __cxa_end_catch
|
|
|
|
; CHECK: br 1 # 1: down to label0
|
|
|
|
; CHECK: end_block # label3:
|
[WebAssembly] Make rethrow take an except_ref type argument
Summary:
In the new wasm EH proposal, `rethrow` takes an `except_ref` argument.
This change was missing in r352598.
This patch adds `llvm.wasm.rethrow.in.catch` intrinsic. This is an
intrinsic that's gonna eventually be lowered to wasm `rethrow`
instruction, but this intrinsic can appear only within a catchpad or a
cleanuppad scope. Also this intrinsic needs to be invokable - otherwise
EH pad successor for it will not be correctly generated in clang.
This also adds lowering logic for this intrinsic in
`SelectionDAGBuilder::visitInvoke`. This routine is basically a
specialized and simplified version of
`SelectionDAGBuilder::visitTargetIntrinsic`, but we can't use it
because if is only for `CallInst`s.
This deletes the previous `llvm.wasm.rethrow` intrinsic and related
tests, which was meant to be used within a `__cxa_rethrow` library
function. Turned out this needs some more logic, so the intrinsic for
this purpose will be added later.
LateEHPrepare takes a result value of `catch` and inserts it into
matching `rethrow` as an argument.
`RETHROW_IN_CATCH` is a pseudo instruction that serves as a link between
`llvm.wasm.rethrow.in.catch` and the real wasm `rethrow` instruction. To
generate a `rethrow` instruction, we need an `except_ref` argument,
which is generated from `catch` instruction. But `catch` instrutions are
added in LateEHPrepare pass, so we use `RETHROW_IN_CATCH`, which takes
no argument, until we are able to correctly lower it to `rethrow` in
LateEHPrepare.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D59352
llvm-svn: 356316
2019-03-16 13:38:57 +08:00
|
|
|
; CHECK: rethrow {{.*}} # to caller
|
2019-02-27 08:50:53 +08:00
|
|
|
; CHECK: end_try # label0:
|
2018-08-08 04:19:23 +08:00
|
|
|
define void @test0() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
|
|
|
|
entry:
|
|
|
|
invoke void @foo()
|
|
|
|
to label %try.cont unwind label %catch.dispatch
|
|
|
|
|
|
|
|
catch.dispatch: ; preds = %entry
|
|
|
|
%0 = catchswitch within none [label %catch.start] unwind to caller
|
|
|
|
|
|
|
|
catch.start: ; preds = %catch.dispatch
|
|
|
|
%1 = catchpad within %0 [i8* bitcast (i8** @_ZTIi to i8*), i8* bitcast (i8** @_ZTId to i8*)]
|
|
|
|
%2 = call i8* @llvm.wasm.get.exception(token %1)
|
|
|
|
%3 = call i32 @llvm.wasm.get.ehselector(token %1)
|
|
|
|
%4 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
|
|
|
|
%matches = icmp eq i32 %3, %4
|
|
|
|
br i1 %matches, label %catch2, label %catch.fallthrough
|
|
|
|
|
|
|
|
catch2: ; preds = %catch.start
|
|
|
|
%5 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
|
|
|
|
call void @__cxa_end_catch() [ "funclet"(token %1) ]
|
|
|
|
catchret from %1 to label %try.cont
|
|
|
|
|
|
|
|
catch.fallthrough: ; preds = %catch.start
|
2019-02-26 11:29:59 +08:00
|
|
|
%6 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTId to i8*))
|
|
|
|
%matches1 = icmp eq i32 %3, %6
|
2018-08-08 04:19:23 +08:00
|
|
|
br i1 %matches1, label %catch, label %rethrow
|
|
|
|
|
|
|
|
catch: ; preds = %catch.fallthrough
|
2019-02-26 11:29:59 +08:00
|
|
|
%7 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
|
2018-08-08 04:19:23 +08:00
|
|
|
call void @__cxa_end_catch() [ "funclet"(token %1) ]
|
|
|
|
catchret from %1 to label %try.cont
|
|
|
|
|
|
|
|
rethrow: ; preds = %catch.fallthrough
|
[WebAssembly] Make rethrow take an except_ref type argument
Summary:
In the new wasm EH proposal, `rethrow` takes an `except_ref` argument.
This change was missing in r352598.
This patch adds `llvm.wasm.rethrow.in.catch` intrinsic. This is an
intrinsic that's gonna eventually be lowered to wasm `rethrow`
instruction, but this intrinsic can appear only within a catchpad or a
cleanuppad scope. Also this intrinsic needs to be invokable - otherwise
EH pad successor for it will not be correctly generated in clang.
This also adds lowering logic for this intrinsic in
`SelectionDAGBuilder::visitInvoke`. This routine is basically a
specialized and simplified version of
`SelectionDAGBuilder::visitTargetIntrinsic`, but we can't use it
because if is only for `CallInst`s.
This deletes the previous `llvm.wasm.rethrow` intrinsic and related
tests, which was meant to be used within a `__cxa_rethrow` library
function. Turned out this needs some more logic, so the intrinsic for
this purpose will be added later.
LateEHPrepare takes a result value of `catch` and inserts it into
matching `rethrow` as an argument.
`RETHROW_IN_CATCH` is a pseudo instruction that serves as a link between
`llvm.wasm.rethrow.in.catch` and the real wasm `rethrow` instruction. To
generate a `rethrow` instruction, we need an `except_ref` argument,
which is generated from `catch` instruction. But `catch` instrutions are
added in LateEHPrepare pass, so we use `RETHROW_IN_CATCH`, which takes
no argument, until we are able to correctly lower it to `rethrow` in
LateEHPrepare.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D59352
llvm-svn: 356316
2019-03-16 13:38:57 +08:00
|
|
|
call void @llvm.wasm.rethrow.in.catch() [ "funclet"(token %1) ]
|
2018-08-08 04:19:23 +08:00
|
|
|
unreachable
|
|
|
|
|
2019-03-27 01:15:55 +08:00
|
|
|
try.cont: ; preds = %catch, %catch2, %entry
|
2018-08-08 04:19:23 +08:00
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
; Nested try-catches within a catch
|
[WebAssembly] Exception handling: Switch to the new proposal
Summary:
This switches the EH implementation to the new proposal:
https://github.com/WebAssembly/exception-handling/blob/master/proposals/Exceptions.md
(The previous proposal was
https://github.com/WebAssembly/exception-handling/blob/master/proposals/old/Exceptions.md)
- Instruction changes
- Now we have one single `catch` instruction that returns a except_ref
value
- `throw` now can take variable number of operations
- `rethrow` does not have 'depth' argument anymore
- `br_on_exn` queries an except_ref to see if it matches the tag and
branches to the given label if true.
- `extract_exception` is a pseudo instruction that simulates popping
values from wasm stack. This is to make `br_on_exn`, a very special
instruction, work: `br_on_exn` puts values onto the stack only if it
is taken, and the # of values can vay depending on the tag.
- Now there's only one `catch` per `try`, this patch removes all special
handling for terminate pad with a call to `__clang_call_terminate`.
Before it was the only case there are two catch clauses (a normal
`catch` and `catch_all` per `try`).
- Make `rethrow` act as a terminator like `throw`. This splits BB after
`rethrow` in WasmEHPrepare, and deletes an unnecessary `unreachable`
after `rethrow` in LateEHPrepare.
- Now we stop at all catchpads (because we add wasm `catch` instruction
that catches all exceptions), this creates new
`findWasmUnwindDestinations` function in SelectionDAGBuilder.
- Now we use `br_on_exn` instrution to figure out if an except_ref
matches the current tag or not, LateEHPrepare generates this sequence
for catch pads:
```
catch
block i32
br_on_exn $__cpp_exception
end_block
extract_exception
```
- Branch analysis for `br_on_exn` in WebAssemblyInstrInfo
- Other various misc. changes to switch to the new proposal.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D57134
llvm-svn: 352598
2019-01-30 11:21:57 +08:00
|
|
|
; void test1() {
|
|
|
|
; try {
|
|
|
|
; foo();
|
2019-02-26 11:29:59 +08:00
|
|
|
; } catch (int) {
|
[WebAssembly] Exception handling: Switch to the new proposal
Summary:
This switches the EH implementation to the new proposal:
https://github.com/WebAssembly/exception-handling/blob/master/proposals/Exceptions.md
(The previous proposal was
https://github.com/WebAssembly/exception-handling/blob/master/proposals/old/Exceptions.md)
- Instruction changes
- Now we have one single `catch` instruction that returns a except_ref
value
- `throw` now can take variable number of operations
- `rethrow` does not have 'depth' argument anymore
- `br_on_exn` queries an except_ref to see if it matches the tag and
branches to the given label if true.
- `extract_exception` is a pseudo instruction that simulates popping
values from wasm stack. This is to make `br_on_exn`, a very special
instruction, work: `br_on_exn` puts values onto the stack only if it
is taken, and the # of values can vay depending on the tag.
- Now there's only one `catch` per `try`, this patch removes all special
handling for terminate pad with a call to `__clang_call_terminate`.
Before it was the only case there are two catch clauses (a normal
`catch` and `catch_all` per `try`).
- Make `rethrow` act as a terminator like `throw`. This splits BB after
`rethrow` in WasmEHPrepare, and deletes an unnecessary `unreachable`
after `rethrow` in LateEHPrepare.
- Now we stop at all catchpads (because we add wasm `catch` instruction
that catches all exceptions), this creates new
`findWasmUnwindDestinations` function in SelectionDAGBuilder.
- Now we use `br_on_exn` instrution to figure out if an except_ref
matches the current tag or not, LateEHPrepare generates this sequence
for catch pads:
```
catch
block i32
br_on_exn $__cpp_exception
end_block
extract_exception
```
- Branch analysis for `br_on_exn` in WebAssemblyInstrInfo
- Other various misc. changes to switch to the new proposal.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D57134
llvm-svn: 352598
2019-01-30 11:21:57 +08:00
|
|
|
; try {
|
|
|
|
; foo();
|
2019-02-26 11:29:59 +08:00
|
|
|
; } catch (int) {
|
[WebAssembly] Exception handling: Switch to the new proposal
Summary:
This switches the EH implementation to the new proposal:
https://github.com/WebAssembly/exception-handling/blob/master/proposals/Exceptions.md
(The previous proposal was
https://github.com/WebAssembly/exception-handling/blob/master/proposals/old/Exceptions.md)
- Instruction changes
- Now we have one single `catch` instruction that returns a except_ref
value
- `throw` now can take variable number of operations
- `rethrow` does not have 'depth' argument anymore
- `br_on_exn` queries an except_ref to see if it matches the tag and
branches to the given label if true.
- `extract_exception` is a pseudo instruction that simulates popping
values from wasm stack. This is to make `br_on_exn`, a very special
instruction, work: `br_on_exn` puts values onto the stack only if it
is taken, and the # of values can vay depending on the tag.
- Now there's only one `catch` per `try`, this patch removes all special
handling for terminate pad with a call to `__clang_call_terminate`.
Before it was the only case there are two catch clauses (a normal
`catch` and `catch_all` per `try`).
- Make `rethrow` act as a terminator like `throw`. This splits BB after
`rethrow` in WasmEHPrepare, and deletes an unnecessary `unreachable`
after `rethrow` in LateEHPrepare.
- Now we stop at all catchpads (because we add wasm `catch` instruction
that catches all exceptions), this creates new
`findWasmUnwindDestinations` function in SelectionDAGBuilder.
- Now we use `br_on_exn` instrution to figure out if an except_ref
matches the current tag or not, LateEHPrepare generates this sequence
for catch pads:
```
catch
block i32
br_on_exn $__cpp_exception
end_block
extract_exception
```
- Branch analysis for `br_on_exn` in WebAssemblyInstrInfo
- Other various misc. changes to switch to the new proposal.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D57134
llvm-svn: 352598
2019-01-30 11:21:57 +08:00
|
|
|
; foo();
|
|
|
|
; }
|
|
|
|
; }
|
|
|
|
; }
|
2018-08-08 04:19:23 +08:00
|
|
|
|
|
|
|
; CHECK-LABEL: test1
|
2019-02-27 09:35:14 +08:00
|
|
|
; CHECK: try
|
|
|
|
; CHECK: call foo
|
|
|
|
; CHECK: catch
|
|
|
|
; CHECK: block
|
|
|
|
; CHECK: block
|
|
|
|
; CHECK: br_if 0, {{.*}} # 0: down to label7
|
|
|
|
; CHECK: i32.call $drop=, __cxa_begin_catch
|
|
|
|
; CHECK: try
|
|
|
|
; CHECK: call foo
|
|
|
|
; CHECK: br 2 # 2: down to label6
|
|
|
|
; CHECK: catch
|
|
|
|
; CHECK: try
|
|
|
|
; CHECK: block
|
|
|
|
; CHECK: br_if 0, {{.*}} # 0: down to label11
|
|
|
|
; CHECK: i32.call $drop=, __cxa_begin_catch
|
|
|
|
; CHECK: try
|
|
|
|
; CHECK: call foo
|
[WebAssembly] Delete ThrowUnwindDest map from WasmEHFuncInfo
Summary:
Before when we implemented the first EH proposal, 'catch <tag>'
instruction may not catch an exception so there were multiple EH pads an
exception can unwind to. That means a BB could have multiple EH pad
successors.
Now after we switched to the new proposal, every 'catch' instruction
catches an exception, and there is only one catchpad per catchswitch, so
we at most have one EH pad successor, making `ThrowUnwindDest` map in
`WasmEHInfo` unnecessary.
Keeping `ThrowUnwindDest` map in `WasmEHInfo` has its own problems,
because other optimization passes can split a BB that contains possibly
throwing calls (previously invokes), and we have to update the map every
time that happens, which is not easy for common CodeGen passes.
This also correctly updates successor info in LateEHPrepare when we add
a rethrow instruction.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D58486
llvm-svn: 355296
2019-03-04 06:35:56 +08:00
|
|
|
; CHECK: br 2 # 2: down to label9
|
2019-02-27 09:35:14 +08:00
|
|
|
; CHECK: catch
|
|
|
|
; CHECK: call __cxa_end_catch
|
[WebAssembly] Make rethrow take an except_ref type argument
Summary:
In the new wasm EH proposal, `rethrow` takes an `except_ref` argument.
This change was missing in r352598.
This patch adds `llvm.wasm.rethrow.in.catch` intrinsic. This is an
intrinsic that's gonna eventually be lowered to wasm `rethrow`
instruction, but this intrinsic can appear only within a catchpad or a
cleanuppad scope. Also this intrinsic needs to be invokable - otherwise
EH pad successor for it will not be correctly generated in clang.
This also adds lowering logic for this intrinsic in
`SelectionDAGBuilder::visitInvoke`. This routine is basically a
specialized and simplified version of
`SelectionDAGBuilder::visitTargetIntrinsic`, but we can't use it
because if is only for `CallInst`s.
This deletes the previous `llvm.wasm.rethrow` intrinsic and related
tests, which was meant to be used within a `__cxa_rethrow` library
function. Turned out this needs some more logic, so the intrinsic for
this purpose will be added later.
LateEHPrepare takes a result value of `catch` and inserts it into
matching `rethrow` as an argument.
`RETHROW_IN_CATCH` is a pseudo instruction that serves as a link between
`llvm.wasm.rethrow.in.catch` and the real wasm `rethrow` instruction. To
generate a `rethrow` instruction, we need an `except_ref` argument,
which is generated from `catch` instruction. But `catch` instrutions are
added in LateEHPrepare pass, so we use `RETHROW_IN_CATCH`, which takes
no argument, until we are able to correctly lower it to `rethrow` in
LateEHPrepare.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D59352
llvm-svn: 356316
2019-03-16 13:38:57 +08:00
|
|
|
; CHECK: rethrow {{.*}} # down to catch3
|
2019-02-27 09:35:14 +08:00
|
|
|
; CHECK: end_try
|
|
|
|
; CHECK: end_block # label11:
|
[WebAssembly] Make rethrow take an except_ref type argument
Summary:
In the new wasm EH proposal, `rethrow` takes an `except_ref` argument.
This change was missing in r352598.
This patch adds `llvm.wasm.rethrow.in.catch` intrinsic. This is an
intrinsic that's gonna eventually be lowered to wasm `rethrow`
instruction, but this intrinsic can appear only within a catchpad or a
cleanuppad scope. Also this intrinsic needs to be invokable - otherwise
EH pad successor for it will not be correctly generated in clang.
This also adds lowering logic for this intrinsic in
`SelectionDAGBuilder::visitInvoke`. This routine is basically a
specialized and simplified version of
`SelectionDAGBuilder::visitTargetIntrinsic`, but we can't use it
because if is only for `CallInst`s.
This deletes the previous `llvm.wasm.rethrow` intrinsic and related
tests, which was meant to be used within a `__cxa_rethrow` library
function. Turned out this needs some more logic, so the intrinsic for
this purpose will be added later.
LateEHPrepare takes a result value of `catch` and inserts it into
matching `rethrow` as an argument.
`RETHROW_IN_CATCH` is a pseudo instruction that serves as a link between
`llvm.wasm.rethrow.in.catch` and the real wasm `rethrow` instruction. To
generate a `rethrow` instruction, we need an `except_ref` argument,
which is generated from `catch` instruction. But `catch` instrutions are
added in LateEHPrepare pass, so we use `RETHROW_IN_CATCH`, which takes
no argument, until we are able to correctly lower it to `rethrow` in
LateEHPrepare.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D59352
llvm-svn: 356316
2019-03-16 13:38:57 +08:00
|
|
|
; CHECK: rethrow {{.*}} # down to catch3
|
2019-02-27 09:35:14 +08:00
|
|
|
; CHECK: catch {{.*}} # catch3:
|
|
|
|
; CHECK: call __cxa_end_catch
|
[WebAssembly] Make rethrow take an except_ref type argument
Summary:
In the new wasm EH proposal, `rethrow` takes an `except_ref` argument.
This change was missing in r352598.
This patch adds `llvm.wasm.rethrow.in.catch` intrinsic. This is an
intrinsic that's gonna eventually be lowered to wasm `rethrow`
instruction, but this intrinsic can appear only within a catchpad or a
cleanuppad scope. Also this intrinsic needs to be invokable - otherwise
EH pad successor for it will not be correctly generated in clang.
This also adds lowering logic for this intrinsic in
`SelectionDAGBuilder::visitInvoke`. This routine is basically a
specialized and simplified version of
`SelectionDAGBuilder::visitTargetIntrinsic`, but we can't use it
because if is only for `CallInst`s.
This deletes the previous `llvm.wasm.rethrow` intrinsic and related
tests, which was meant to be used within a `__cxa_rethrow` library
function. Turned out this needs some more logic, so the intrinsic for
this purpose will be added later.
LateEHPrepare takes a result value of `catch` and inserts it into
matching `rethrow` as an argument.
`RETHROW_IN_CATCH` is a pseudo instruction that serves as a link between
`llvm.wasm.rethrow.in.catch` and the real wasm `rethrow` instruction. To
generate a `rethrow` instruction, we need an `except_ref` argument,
which is generated from `catch` instruction. But `catch` instrutions are
added in LateEHPrepare pass, so we use `RETHROW_IN_CATCH`, which takes
no argument, until we are able to correctly lower it to `rethrow` in
LateEHPrepare.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D59352
llvm-svn: 356316
2019-03-16 13:38:57 +08:00
|
|
|
; CHECK: rethrow {{.*}} # to caller
|
[WebAssembly] Delete ThrowUnwindDest map from WasmEHFuncInfo
Summary:
Before when we implemented the first EH proposal, 'catch <tag>'
instruction may not catch an exception so there were multiple EH pads an
exception can unwind to. That means a BB could have multiple EH pad
successors.
Now after we switched to the new proposal, every 'catch' instruction
catches an exception, and there is only one catchpad per catchswitch, so
we at most have one EH pad successor, making `ThrowUnwindDest` map in
`WasmEHInfo` unnecessary.
Keeping `ThrowUnwindDest` map in `WasmEHInfo` has its own problems,
because other optimization passes can split a BB that contains possibly
throwing calls (previously invokes), and we have to update the map every
time that happens, which is not easy for common CodeGen passes.
This also correctly updates successor info in LateEHPrepare when we add
a rethrow instruction.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D58486
llvm-svn: 355296
2019-03-04 06:35:56 +08:00
|
|
|
; CHECK: end_try # label9:
|
2019-02-27 09:35:14 +08:00
|
|
|
; CHECK: call __cxa_end_catch
|
|
|
|
; CHECK: br 2 # 2: down to label6
|
|
|
|
; CHECK: end_try
|
|
|
|
; CHECK: end_block # label7:
|
[WebAssembly] Make rethrow take an except_ref type argument
Summary:
In the new wasm EH proposal, `rethrow` takes an `except_ref` argument.
This change was missing in r352598.
This patch adds `llvm.wasm.rethrow.in.catch` intrinsic. This is an
intrinsic that's gonna eventually be lowered to wasm `rethrow`
instruction, but this intrinsic can appear only within a catchpad or a
cleanuppad scope. Also this intrinsic needs to be invokable - otherwise
EH pad successor for it will not be correctly generated in clang.
This also adds lowering logic for this intrinsic in
`SelectionDAGBuilder::visitInvoke`. This routine is basically a
specialized and simplified version of
`SelectionDAGBuilder::visitTargetIntrinsic`, but we can't use it
because if is only for `CallInst`s.
This deletes the previous `llvm.wasm.rethrow` intrinsic and related
tests, which was meant to be used within a `__cxa_rethrow` library
function. Turned out this needs some more logic, so the intrinsic for
this purpose will be added later.
LateEHPrepare takes a result value of `catch` and inserts it into
matching `rethrow` as an argument.
`RETHROW_IN_CATCH` is a pseudo instruction that serves as a link between
`llvm.wasm.rethrow.in.catch` and the real wasm `rethrow` instruction. To
generate a `rethrow` instruction, we need an `except_ref` argument,
which is generated from `catch` instruction. But `catch` instrutions are
added in LateEHPrepare pass, so we use `RETHROW_IN_CATCH`, which takes
no argument, until we are able to correctly lower it to `rethrow` in
LateEHPrepare.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D59352
llvm-svn: 356316
2019-03-16 13:38:57 +08:00
|
|
|
; CHECK: rethrow {{.*}} # to caller
|
2019-02-27 09:35:14 +08:00
|
|
|
; CHECK: end_block # label6:
|
|
|
|
; CHECK: call __cxa_end_catch
|
|
|
|
; CHECK: end_try
|
[WebAssembly] Exception handling: Switch to the new proposal
Summary:
This switches the EH implementation to the new proposal:
https://github.com/WebAssembly/exception-handling/blob/master/proposals/Exceptions.md
(The previous proposal was
https://github.com/WebAssembly/exception-handling/blob/master/proposals/old/Exceptions.md)
- Instruction changes
- Now we have one single `catch` instruction that returns a except_ref
value
- `throw` now can take variable number of operations
- `rethrow` does not have 'depth' argument anymore
- `br_on_exn` queries an except_ref to see if it matches the tag and
branches to the given label if true.
- `extract_exception` is a pseudo instruction that simulates popping
values from wasm stack. This is to make `br_on_exn`, a very special
instruction, work: `br_on_exn` puts values onto the stack only if it
is taken, and the # of values can vay depending on the tag.
- Now there's only one `catch` per `try`, this patch removes all special
handling for terminate pad with a call to `__clang_call_terminate`.
Before it was the only case there are two catch clauses (a normal
`catch` and `catch_all` per `try`).
- Make `rethrow` act as a terminator like `throw`. This splits BB after
`rethrow` in WasmEHPrepare, and deletes an unnecessary `unreachable`
after `rethrow` in LateEHPrepare.
- Now we stop at all catchpads (because we add wasm `catch` instruction
that catches all exceptions), this creates new
`findWasmUnwindDestinations` function in SelectionDAGBuilder.
- Now we use `br_on_exn` instrution to figure out if an except_ref
matches the current tag or not, LateEHPrepare generates this sequence
for catch pads:
```
catch
block i32
br_on_exn $__cpp_exception
end_block
extract_exception
```
- Branch analysis for `br_on_exn` in WebAssemblyInstrInfo
- Other various misc. changes to switch to the new proposal.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D57134
llvm-svn: 352598
2019-01-30 11:21:57 +08:00
|
|
|
define void @test1() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
|
2018-08-08 04:19:23 +08:00
|
|
|
entry:
|
|
|
|
invoke void @foo()
|
|
|
|
to label %try.cont11 unwind label %catch.dispatch
|
|
|
|
|
|
|
|
catch.dispatch: ; preds = %entry
|
|
|
|
%0 = catchswitch within none [label %catch.start] unwind to caller
|
|
|
|
|
|
|
|
catch.start: ; preds = %catch.dispatch
|
|
|
|
%1 = catchpad within %0 [i8* bitcast (i8** @_ZTIi to i8*)]
|
|
|
|
%2 = call i8* @llvm.wasm.get.exception(token %1)
|
|
|
|
%3 = call i32 @llvm.wasm.get.ehselector(token %1)
|
|
|
|
%4 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
|
|
|
|
%matches = icmp eq i32 %3, %4
|
|
|
|
br i1 %matches, label %catch, label %rethrow
|
|
|
|
|
|
|
|
catch: ; preds = %catch.start
|
|
|
|
%5 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
|
|
|
|
%6 = bitcast i8* %5 to i32*
|
|
|
|
%7 = load i32, i32* %6, align 4
|
|
|
|
invoke void @foo() [ "funclet"(token %1) ]
|
|
|
|
to label %try.cont unwind label %catch.dispatch2
|
|
|
|
|
|
|
|
catch.dispatch2: ; preds = %catch
|
|
|
|
%8 = catchswitch within %1 [label %catch.start3] unwind label %ehcleanup9
|
|
|
|
|
|
|
|
catch.start3: ; preds = %catch.dispatch2
|
|
|
|
%9 = catchpad within %8 [i8* bitcast (i8** @_ZTIi to i8*)]
|
|
|
|
%10 = call i8* @llvm.wasm.get.exception(token %9)
|
|
|
|
%11 = call i32 @llvm.wasm.get.ehselector(token %9)
|
|
|
|
%12 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
|
|
|
|
%matches4 = icmp eq i32 %11, %12
|
|
|
|
br i1 %matches4, label %catch6, label %rethrow5
|
|
|
|
|
|
|
|
catch6: ; preds = %catch.start3
|
|
|
|
%13 = call i8* @__cxa_begin_catch(i8* %10) [ "funclet"(token %9) ]
|
|
|
|
%14 = bitcast i8* %13 to i32*
|
|
|
|
%15 = load i32, i32* %14, align 4
|
|
|
|
invoke void @foo() [ "funclet"(token %9) ]
|
|
|
|
to label %invoke.cont8 unwind label %ehcleanup
|
|
|
|
|
|
|
|
invoke.cont8: ; preds = %catch6
|
|
|
|
call void @__cxa_end_catch() [ "funclet"(token %9) ]
|
|
|
|
catchret from %9 to label %try.cont
|
|
|
|
|
|
|
|
rethrow5: ; preds = %catch.start3
|
[WebAssembly] Make rethrow take an except_ref type argument
Summary:
In the new wasm EH proposal, `rethrow` takes an `except_ref` argument.
This change was missing in r352598.
This patch adds `llvm.wasm.rethrow.in.catch` intrinsic. This is an
intrinsic that's gonna eventually be lowered to wasm `rethrow`
instruction, but this intrinsic can appear only within a catchpad or a
cleanuppad scope. Also this intrinsic needs to be invokable - otherwise
EH pad successor for it will not be correctly generated in clang.
This also adds lowering logic for this intrinsic in
`SelectionDAGBuilder::visitInvoke`. This routine is basically a
specialized and simplified version of
`SelectionDAGBuilder::visitTargetIntrinsic`, but we can't use it
because if is only for `CallInst`s.
This deletes the previous `llvm.wasm.rethrow` intrinsic and related
tests, which was meant to be used within a `__cxa_rethrow` library
function. Turned out this needs some more logic, so the intrinsic for
this purpose will be added later.
LateEHPrepare takes a result value of `catch` and inserts it into
matching `rethrow` as an argument.
`RETHROW_IN_CATCH` is a pseudo instruction that serves as a link between
`llvm.wasm.rethrow.in.catch` and the real wasm `rethrow` instruction. To
generate a `rethrow` instruction, we need an `except_ref` argument,
which is generated from `catch` instruction. But `catch` instrutions are
added in LateEHPrepare pass, so we use `RETHROW_IN_CATCH`, which takes
no argument, until we are able to correctly lower it to `rethrow` in
LateEHPrepare.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D59352
llvm-svn: 356316
2019-03-16 13:38:57 +08:00
|
|
|
invoke void @llvm.wasm.rethrow.in.catch() [ "funclet"(token %9) ]
|
2018-08-08 04:19:23 +08:00
|
|
|
to label %unreachable unwind label %ehcleanup9
|
|
|
|
|
2019-03-27 01:15:55 +08:00
|
|
|
try.cont: ; preds = %invoke.cont8, %catch
|
2018-08-08 04:19:23 +08:00
|
|
|
call void @__cxa_end_catch() [ "funclet"(token %1) ]
|
|
|
|
catchret from %1 to label %try.cont11
|
|
|
|
|
|
|
|
rethrow: ; preds = %catch.start
|
[WebAssembly] Make rethrow take an except_ref type argument
Summary:
In the new wasm EH proposal, `rethrow` takes an `except_ref` argument.
This change was missing in r352598.
This patch adds `llvm.wasm.rethrow.in.catch` intrinsic. This is an
intrinsic that's gonna eventually be lowered to wasm `rethrow`
instruction, but this intrinsic can appear only within a catchpad or a
cleanuppad scope. Also this intrinsic needs to be invokable - otherwise
EH pad successor for it will not be correctly generated in clang.
This also adds lowering logic for this intrinsic in
`SelectionDAGBuilder::visitInvoke`. This routine is basically a
specialized and simplified version of
`SelectionDAGBuilder::visitTargetIntrinsic`, but we can't use it
because if is only for `CallInst`s.
This deletes the previous `llvm.wasm.rethrow` intrinsic and related
tests, which was meant to be used within a `__cxa_rethrow` library
function. Turned out this needs some more logic, so the intrinsic for
this purpose will be added later.
LateEHPrepare takes a result value of `catch` and inserts it into
matching `rethrow` as an argument.
`RETHROW_IN_CATCH` is a pseudo instruction that serves as a link between
`llvm.wasm.rethrow.in.catch` and the real wasm `rethrow` instruction. To
generate a `rethrow` instruction, we need an `except_ref` argument,
which is generated from `catch` instruction. But `catch` instrutions are
added in LateEHPrepare pass, so we use `RETHROW_IN_CATCH`, which takes
no argument, until we are able to correctly lower it to `rethrow` in
LateEHPrepare.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D59352
llvm-svn: 356316
2019-03-16 13:38:57 +08:00
|
|
|
call void @llvm.wasm.rethrow.in.catch() [ "funclet"(token %1) ]
|
2018-08-08 04:19:23 +08:00
|
|
|
unreachable
|
|
|
|
|
2019-03-27 01:15:55 +08:00
|
|
|
try.cont11: ; preds = %try.cont, %entry
|
2018-08-08 04:19:23 +08:00
|
|
|
ret void
|
|
|
|
|
|
|
|
ehcleanup: ; preds = %catch6
|
|
|
|
%16 = cleanuppad within %9 []
|
|
|
|
call void @__cxa_end_catch() [ "funclet"(token %16) ]
|
|
|
|
cleanupret from %16 unwind label %ehcleanup9
|
|
|
|
|
|
|
|
ehcleanup9: ; preds = %ehcleanup, %rethrow5, %catch.dispatch2
|
|
|
|
%17 = cleanuppad within %1 []
|
|
|
|
call void @__cxa_end_catch() [ "funclet"(token %17) ]
|
|
|
|
cleanupret from %17 unwind to caller
|
|
|
|
|
|
|
|
unreachable: ; preds = %rethrow5
|
|
|
|
unreachable
|
|
|
|
}
|
|
|
|
|
|
|
|
; Nested loop within a catch clause
|
[WebAssembly] Exception handling: Switch to the new proposal
Summary:
This switches the EH implementation to the new proposal:
https://github.com/WebAssembly/exception-handling/blob/master/proposals/Exceptions.md
(The previous proposal was
https://github.com/WebAssembly/exception-handling/blob/master/proposals/old/Exceptions.md)
- Instruction changes
- Now we have one single `catch` instruction that returns a except_ref
value
- `throw` now can take variable number of operations
- `rethrow` does not have 'depth' argument anymore
- `br_on_exn` queries an except_ref to see if it matches the tag and
branches to the given label if true.
- `extract_exception` is a pseudo instruction that simulates popping
values from wasm stack. This is to make `br_on_exn`, a very special
instruction, work: `br_on_exn` puts values onto the stack only if it
is taken, and the # of values can vay depending on the tag.
- Now there's only one `catch` per `try`, this patch removes all special
handling for terminate pad with a call to `__clang_call_terminate`.
Before it was the only case there are two catch clauses (a normal
`catch` and `catch_all` per `try`).
- Make `rethrow` act as a terminator like `throw`. This splits BB after
`rethrow` in WasmEHPrepare, and deletes an unnecessary `unreachable`
after `rethrow` in LateEHPrepare.
- Now we stop at all catchpads (because we add wasm `catch` instruction
that catches all exceptions), this creates new
`findWasmUnwindDestinations` function in SelectionDAGBuilder.
- Now we use `br_on_exn` instrution to figure out if an except_ref
matches the current tag or not, LateEHPrepare generates this sequence
for catch pads:
```
catch
block i32
br_on_exn $__cpp_exception
end_block
extract_exception
```
- Branch analysis for `br_on_exn` in WebAssemblyInstrInfo
- Other various misc. changes to switch to the new proposal.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D57134
llvm-svn: 352598
2019-01-30 11:21:57 +08:00
|
|
|
; void test2() {
|
|
|
|
; try {
|
|
|
|
; foo();
|
|
|
|
; } catch (...) {
|
|
|
|
; for (int i = 0; i < 50; i++)
|
|
|
|
; foo();
|
|
|
|
; }
|
|
|
|
; }
|
2018-08-08 04:19:23 +08:00
|
|
|
|
|
|
|
; CHECK-LABEL: test2
|
2019-02-27 08:50:53 +08:00
|
|
|
; CHECK: try
|
|
|
|
; CHECK: call foo
|
|
|
|
; CHECK: catch
|
|
|
|
; CHECK: i32.call $drop=, __cxa_begin_catch
|
|
|
|
; CHECK: loop # label15:
|
|
|
|
; CHECK: block
|
2019-02-26 11:29:59 +08:00
|
|
|
; CHECK: block
|
2019-02-27 08:50:53 +08:00
|
|
|
; CHECK: br_if 0, {{.*}} # 0: down to label17
|
|
|
|
; CHECK: try
|
|
|
|
; CHECK: call foo
|
|
|
|
; CHECK: br 2 # 2: down to label16
|
|
|
|
; CHECK: catch
|
2019-02-26 11:29:59 +08:00
|
|
|
; CHECK: try
|
2019-02-27 08:50:53 +08:00
|
|
|
; CHECK: call __cxa_end_catch
|
2019-02-26 11:29:59 +08:00
|
|
|
; CHECK: catch
|
2019-02-27 08:50:53 +08:00
|
|
|
; CHECK: call __clang_call_terminate
|
|
|
|
; CHECK: unreachable
|
2019-02-26 11:29:59 +08:00
|
|
|
; CHECK: end_try
|
[WebAssembly] Make rethrow take an except_ref type argument
Summary:
In the new wasm EH proposal, `rethrow` takes an `except_ref` argument.
This change was missing in r352598.
This patch adds `llvm.wasm.rethrow.in.catch` intrinsic. This is an
intrinsic that's gonna eventually be lowered to wasm `rethrow`
instruction, but this intrinsic can appear only within a catchpad or a
cleanuppad scope. Also this intrinsic needs to be invokable - otherwise
EH pad successor for it will not be correctly generated in clang.
This also adds lowering logic for this intrinsic in
`SelectionDAGBuilder::visitInvoke`. This routine is basically a
specialized and simplified version of
`SelectionDAGBuilder::visitTargetIntrinsic`, but we can't use it
because if is only for `CallInst`s.
This deletes the previous `llvm.wasm.rethrow` intrinsic and related
tests, which was meant to be used within a `__cxa_rethrow` library
function. Turned out this needs some more logic, so the intrinsic for
this purpose will be added later.
LateEHPrepare takes a result value of `catch` and inserts it into
matching `rethrow` as an argument.
`RETHROW_IN_CATCH` is a pseudo instruction that serves as a link between
`llvm.wasm.rethrow.in.catch` and the real wasm `rethrow` instruction. To
generate a `rethrow` instruction, we need an `except_ref` argument,
which is generated from `catch` instruction. But `catch` instrutions are
added in LateEHPrepare pass, so we use `RETHROW_IN_CATCH`, which takes
no argument, until we are able to correctly lower it to `rethrow` in
LateEHPrepare.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D59352
llvm-svn: 356316
2019-03-16 13:38:57 +08:00
|
|
|
; CHECK: rethrow {{.*}} # to caller
|
2019-02-27 08:50:53 +08:00
|
|
|
; CHECK: end_try
|
|
|
|
; CHECK: end_block # label17:
|
|
|
|
; CHECK: call __cxa_end_catch
|
|
|
|
; CHECK: br 2 # 2: down to label13
|
|
|
|
; CHECK: end_block # label16:
|
|
|
|
; CHECK: br 0 # 0: up to label15
|
|
|
|
; CHECK: end_loop
|
|
|
|
; CHECK: end_try # label13:
|
2018-08-08 04:19:23 +08:00
|
|
|
define void @test2() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
|
|
|
|
entry:
|
|
|
|
invoke void @foo()
|
|
|
|
to label %try.cont unwind label %catch.dispatch
|
|
|
|
|
|
|
|
catch.dispatch: ; preds = %entry
|
|
|
|
%0 = catchswitch within none [label %catch.start] unwind to caller
|
|
|
|
|
|
|
|
catch.start: ; preds = %catch.dispatch
|
|
|
|
%1 = catchpad within %0 [i8* null]
|
|
|
|
%2 = call i8* @llvm.wasm.get.exception(token %1)
|
|
|
|
%3 = call i32 @llvm.wasm.get.ehselector(token %1)
|
|
|
|
%4 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
|
|
|
|
br label %for.cond
|
|
|
|
|
|
|
|
for.cond: ; preds = %for.inc, %catch.start
|
|
|
|
%i.0 = phi i32 [ 0, %catch.start ], [ %inc, %for.inc ]
|
|
|
|
%cmp = icmp slt i32 %i.0, 50
|
|
|
|
br i1 %cmp, label %for.body, label %for.end
|
|
|
|
|
|
|
|
for.body: ; preds = %for.cond
|
|
|
|
invoke void @foo() [ "funclet"(token %1) ]
|
|
|
|
to label %for.inc unwind label %ehcleanup
|
|
|
|
|
|
|
|
for.inc: ; preds = %for.body
|
|
|
|
%inc = add nsw i32 %i.0, 1
|
|
|
|
br label %for.cond
|
|
|
|
|
|
|
|
for.end: ; preds = %for.cond
|
|
|
|
call void @__cxa_end_catch() [ "funclet"(token %1) ]
|
|
|
|
catchret from %1 to label %try.cont
|
|
|
|
|
|
|
|
try.cont: ; preds = %for.end, %entry
|
|
|
|
ret void
|
|
|
|
|
|
|
|
ehcleanup: ; preds = %for.body
|
|
|
|
%5 = cleanuppad within %1 []
|
|
|
|
invoke void @__cxa_end_catch() [ "funclet"(token %5) ]
|
|
|
|
to label %invoke.cont2 unwind label %terminate
|
|
|
|
|
|
|
|
invoke.cont2: ; preds = %ehcleanup
|
|
|
|
cleanupret from %5 unwind to caller
|
|
|
|
|
|
|
|
terminate: ; preds = %ehcleanup
|
|
|
|
%6 = cleanuppad within %5 []
|
|
|
|
%7 = call i8* @llvm.wasm.get.exception(token %6)
|
|
|
|
call void @__clang_call_terminate(i8* %7) [ "funclet"(token %6) ]
|
|
|
|
unreachable
|
|
|
|
}
|
|
|
|
|
2019-03-27 01:15:55 +08:00
|
|
|
; Tests if block and try markers are correctly placed. Even if two predecessors
|
|
|
|
; of the EH pad are bb2 and bb3 and their nearest common dominator is bb1, the
|
|
|
|
; TRY marker should be placed at bb0 because there's a branch from bb0 to bb2,
|
|
|
|
; and scopes cannot be interleaved.
|
|
|
|
|
|
|
|
; NOOPT-LABEL: test3
|
|
|
|
; NOOPT: try
|
|
|
|
; NOOPT: block
|
|
|
|
; NOOPT: block
|
|
|
|
; NOOPT: block
|
|
|
|
; NOOPT: end_block
|
|
|
|
; NOOPT: end_block
|
|
|
|
; NOOPT: call foo
|
|
|
|
; NOOPT: end_block
|
|
|
|
; NOOPT: call bar
|
|
|
|
; NOOPT: catch {{.*}}
|
|
|
|
; NOOPT: end_try
|
|
|
|
define void @test3() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
|
|
|
|
bb0:
|
|
|
|
br i1 undef, label %bb1, label %bb2
|
|
|
|
|
|
|
|
bb1: ; preds = %bb0
|
|
|
|
br i1 undef, label %bb3, label %bb4
|
|
|
|
|
|
|
|
bb2: ; preds = %bb0
|
|
|
|
br label %try.cont
|
|
|
|
|
|
|
|
bb3: ; preds = %bb1
|
|
|
|
invoke void @foo()
|
|
|
|
to label %try.cont unwind label %catch.dispatch
|
|
|
|
|
|
|
|
bb4: ; preds = %bb1
|
|
|
|
invoke void @bar()
|
|
|
|
to label %try.cont unwind label %catch.dispatch
|
|
|
|
|
|
|
|
catch.dispatch: ; preds = %bb4, %bb3
|
|
|
|
%0 = catchswitch within none [label %catch.start] unwind to caller
|
|
|
|
|
|
|
|
catch.start: ; preds = %catch.dispatch
|
|
|
|
%1 = catchpad within %0 [i8* null]
|
|
|
|
%2 = call i8* @llvm.wasm.get.exception(token %1)
|
|
|
|
%3 = call i32 @llvm.wasm.get.ehselector(token %1)
|
|
|
|
catchret from %1 to label %try.cont
|
|
|
|
|
|
|
|
try.cont: ; preds = %catch.start, %bb4, %bb3, %bb2
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
2019-03-27 01:29:55 +08:00
|
|
|
; Tests if try/end_try markers are placed correctly wrt loop/end_loop markers,
|
|
|
|
; when try and loop markers are in the same BB and end_try and end_loop are in
|
|
|
|
; another BB.
|
|
|
|
; CHECK: loop
|
|
|
|
; CHECK: try
|
|
|
|
; CHECK: call foo
|
|
|
|
; CHECK: catch
|
|
|
|
; CHECK: end_try
|
|
|
|
; CHECK: end_loop
|
|
|
|
define void @test4(i32* %p) personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
|
|
|
|
entry:
|
|
|
|
store volatile i32 0, i32* %p
|
|
|
|
br label %loop
|
|
|
|
|
|
|
|
loop: ; preds = %try.cont, %entry
|
|
|
|
store volatile i32 1, i32* %p
|
|
|
|
invoke void @foo()
|
|
|
|
to label %try.cont unwind label %catch.dispatch
|
|
|
|
|
|
|
|
catch.dispatch: ; preds = %loop
|
|
|
|
%0 = catchswitch within none [label %catch.start] unwind to caller
|
|
|
|
|
|
|
|
catch.start: ; preds = %catch.dispatch
|
|
|
|
%1 = catchpad within %0 [i8* null]
|
|
|
|
%2 = call i8* @llvm.wasm.get.exception(token %1)
|
|
|
|
%3 = call i32 @llvm.wasm.get.ehselector(token %1)
|
|
|
|
catchret from %1 to label %try.cont
|
|
|
|
|
|
|
|
try.cont: ; preds = %catch.start, %loop
|
|
|
|
br label %loop
|
|
|
|
}
|
|
|
|
|
2019-03-30 19:04:48 +08:00
|
|
|
; Some of test cases below are hand-tweaked by deleting some library calls to
|
|
|
|
; simplify tests and changing the order of basic blocks to cause unwind
|
|
|
|
; destination mismatches. And we use -wasm-disable-ehpad-sort to create maximum
|
|
|
|
; number of mismatches in several tests below.
|
|
|
|
|
|
|
|
; 'call bar''s original unwind destination was 'catch14', but after control flow
|
|
|
|
; linearization, its unwind destination incorrectly becomes 'catch15'. We fix
|
|
|
|
; this by wrapping the call with a nested try/catch/end_try and branching to the
|
|
|
|
; right destination (label32).
|
|
|
|
|
|
|
|
; NOSORT-LABEL: test5
|
|
|
|
; NOSORT: block
|
|
|
|
; NOSORT: try
|
|
|
|
; NOSORT: try
|
|
|
|
; NOSORT: call foo
|
|
|
|
; --- Nested try/catch/end_try starts
|
|
|
|
; NOSORT: try
|
|
|
|
; NOSORT: call bar
|
|
|
|
; NOSORT: catch $drop=
|
|
|
|
; NOSORT: br 2 # 2: down to label32
|
|
|
|
; NOSORT: end_try
|
|
|
|
; --- Nested try/catch/end_try ends
|
|
|
|
; NOSORT: br 2 # 2: down to label31
|
|
|
|
; NOSORT: catch $drop= # catch15:
|
|
|
|
; NOSORT: br 2 # 2: down to label31
|
|
|
|
; NOSORT: end_try
|
|
|
|
; NOSORT: catch $drop= # catch14:
|
|
|
|
; NOSORT: end_try # label32:
|
|
|
|
; NOSORT: end_block # label31:
|
|
|
|
; NOSORT: return
|
|
|
|
|
|
|
|
define void @test5() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
|
|
|
|
bb0:
|
|
|
|
invoke void @foo()
|
|
|
|
to label %bb1 unwind label %catch.dispatch0
|
|
|
|
|
|
|
|
bb1: ; preds = %bb0
|
|
|
|
invoke void @bar()
|
|
|
|
to label %try.cont unwind label %catch.dispatch1
|
|
|
|
|
|
|
|
catch.dispatch0: ; preds = %bb0
|
|
|
|
%0 = catchswitch within none [label %catch.start0] unwind to caller
|
|
|
|
|
|
|
|
catch.start0: ; preds = %catch.dispatch0
|
|
|
|
%1 = catchpad within %0 [i8* null]
|
|
|
|
%2 = call i8* @llvm.wasm.get.exception(token %1)
|
|
|
|
%3 = call i32 @llvm.wasm.get.ehselector(token %1)
|
|
|
|
catchret from %1 to label %try.cont
|
|
|
|
|
|
|
|
catch.dispatch1: ; preds = %bb1
|
|
|
|
%4 = catchswitch within none [label %catch.start1] unwind to caller
|
|
|
|
|
|
|
|
catch.start1: ; preds = %catch.dispatch1
|
|
|
|
%5 = catchpad within %4 [i8* null]
|
|
|
|
%6 = call i8* @llvm.wasm.get.exception(token %5)
|
|
|
|
%7 = call i32 @llvm.wasm.get.ehselector(token %5)
|
|
|
|
catchret from %5 to label %try.cont
|
|
|
|
|
|
|
|
try.cont: ; preds = %catch.start1, %catch.start0, %bb1
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
; Two 'call bar''s original unwind destination was the caller, but after control
|
|
|
|
; flow linearization, their unwind destination incorrectly becomes 'catch17'. We
|
|
|
|
; fix this by wrapping the call with a nested try/catch/end_try and branching to
|
|
|
|
; the right destination (label4), from which we rethrow the exception to the
|
|
|
|
; caller.
|
|
|
|
|
|
|
|
; NOSORT-LABEL: test6
|
|
|
|
; NOSORT: try
|
|
|
|
; NOSORT: call foo
|
|
|
|
; --- Nested try/catch/end_try starts
|
|
|
|
; NOSORT: try
|
|
|
|
; NOSORT: call bar
|
|
|
|
; NOSORT: call bar
|
|
|
|
; NOSORT: catch $[[REG:[0-9]+]]=
|
|
|
|
; NOSORT: br 1 # 1: down to label35
|
|
|
|
; NOSORT: end_try
|
|
|
|
; --- Nested try/catch/end_try ends
|
|
|
|
; NOSORT: return
|
|
|
|
; NOSORT: catch $drop= # catch17:
|
|
|
|
; NOSORT: return
|
|
|
|
; NOSORT: end_try # label35:
|
|
|
|
; NOSORT: rethrow $[[REG]] # to caller
|
|
|
|
|
|
|
|
define void @test6() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
|
|
|
|
bb0:
|
|
|
|
invoke void @foo()
|
|
|
|
to label %bb1 unwind label %catch.dispatch0
|
|
|
|
|
|
|
|
bb1: ; preds = %bb0
|
|
|
|
call void @bar()
|
|
|
|
call void @bar()
|
|
|
|
ret void
|
|
|
|
|
|
|
|
catch.dispatch0: ; preds = %bb0
|
|
|
|
%0 = catchswitch within none [label %catch.start0] unwind to caller
|
|
|
|
|
|
|
|
catch.start0: ; preds = %catch.dispatch0
|
|
|
|
%1 = catchpad within %0 [i8* null]
|
|
|
|
%2 = call i8* @llvm.wasm.get.exception(token %1)
|
|
|
|
%3 = call i32 @llvm.wasm.get.ehselector(token %1)
|
|
|
|
catchret from %1 to label %try.cont
|
|
|
|
|
|
|
|
try.cont: ; preds = %catch.start0
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
|
|
|
; If not for the unwind destination mismatch, the LOOP marker here would have an
|
|
|
|
; i32 signature. But because we add a rethrow instruction at the end of the
|
|
|
|
; appendix block, now the LOOP marker does not have a signature (= has a void
|
|
|
|
; signature). Here the two calls two 'bar' are supposed to throw up to the
|
|
|
|
; caller, but incorrectly unwind to 'catch19' after linearizing the CFG.
|
|
|
|
|
|
|
|
; NOSORT-LABEL: test7
|
|
|
|
; NOSORT: block
|
|
|
|
; NOSORT-NOT: loop i32
|
|
|
|
; NOSORT: loop # label38:
|
|
|
|
; NOSORT: try
|
|
|
|
; NOSORT: call foo
|
|
|
|
; --- Nested try/catch/end_try starts
|
|
|
|
; NOSORT: try
|
|
|
|
; NOSORT: call bar
|
|
|
|
; NOSORT: call bar
|
|
|
|
; NOSORT: catch $[[REG:[0-9]+]]=
|
|
|
|
; NOSORT: br 1 # 1: down to label39
|
|
|
|
; NOSORT: end_try
|
|
|
|
; --- Nested try/catch/end_try ends
|
|
|
|
; NOSORT: return {{.*}}
|
|
|
|
; NOSORT: catch $drop= # catch19:
|
|
|
|
; NOSORT: br 1 # 1: up to label38
|
|
|
|
; NOSORT: end_try # label39:
|
|
|
|
; NOSORT: end_loop
|
|
|
|
; NOSORT: end_block
|
|
|
|
; NOSORT: rethrow $[[REG]] # to caller
|
|
|
|
|
|
|
|
define i32 @test7(i32* %p) personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
|
|
|
|
entry:
|
|
|
|
store volatile i32 0, i32* %p
|
|
|
|
br label %loop
|
|
|
|
|
|
|
|
loop: ; preds = %try.cont, %entry
|
|
|
|
store volatile i32 1, i32* %p
|
|
|
|
invoke void @foo()
|
|
|
|
to label %bb unwind label %catch.dispatch
|
|
|
|
|
|
|
|
bb: ; preds = %loop
|
|
|
|
call void @bar()
|
|
|
|
call void @bar()
|
|
|
|
ret i32 0
|
|
|
|
|
|
|
|
catch.dispatch: ; preds = %loop
|
|
|
|
%0 = catchswitch within none [label %catch.start] unwind to caller
|
|
|
|
|
|
|
|
catch.start: ; preds = %catch.dispatch
|
|
|
|
%1 = catchpad within %0 [i8* null]
|
|
|
|
%2 = call i8* @llvm.wasm.get.exception(token %1)
|
|
|
|
%3 = call i32 @llvm.wasm.get.ehselector(token %1)
|
|
|
|
catchret from %1 to label %try.cont
|
|
|
|
|
|
|
|
try.cont: ; preds = %catch.start
|
|
|
|
br label %loop
|
|
|
|
}
|
|
|
|
|
|
|
|
; When we have both kinds of EH pad unwind mismatches:
|
|
|
|
; - A may-throw instruction unwinds to an incorrect EH pad after linearizing the
|
|
|
|
; CFG, when it is supposed to unwind to another EH pad.
|
|
|
|
; - A may-throw instruction unwinds to an incorrect EH pad after linearizing the
|
|
|
|
; CFG, when it is supposed to unwind to the caller.
|
|
|
|
|
|
|
|
; NOSORT-LABEL: test8
|
|
|
|
; NOSORT: block
|
|
|
|
; NOSORT: block
|
|
|
|
; NOSORT: try
|
|
|
|
; NOSORT: try
|
|
|
|
; NOSORT: call foo
|
|
|
|
; --- Nested try/catch/end_try starts
|
|
|
|
; NOSORT: try
|
|
|
|
; NOSORT: call bar
|
|
|
|
; NOSORT: catch $[[REG0:[0-9]+]]=
|
|
|
|
; NOSORT: br 2 # 2: down to label43
|
|
|
|
; NOSORT: end_try
|
|
|
|
; --- Nested try/catch/end_try ends
|
|
|
|
; NOSORT: br 2 # 2: down to label42
|
|
|
|
; NOSORT: catch {{.*}}
|
|
|
|
; NOSORT: block i32
|
|
|
|
; NOSORT: br_on_exn 0, {{.*}} # 0: down to label46
|
|
|
|
; --- Nested try/catch/end_try starts
|
|
|
|
; NOSORT: try
|
|
|
|
; NOSORT: rethrow {{.*}} # down to catch24
|
|
|
|
; NOSORT: catch $[[REG1:[0-9]+]]= # catch24:
|
|
|
|
; NOSORT: br 5 # 5: down to label41
|
|
|
|
; NOSORT: end_try
|
|
|
|
; --- Nested try/catch/end_try ends
|
|
|
|
; NOSORT: end_block # label46:
|
|
|
|
; NOSORT: i32.call $drop=, __cxa_begin_catch
|
|
|
|
; --- Nested try/catch/end_try starts
|
|
|
|
; NOSORT: try
|
|
|
|
; NOSORT: call __cxa_end_catch
|
|
|
|
; NOSORT: catch $[[REG1]]=
|
|
|
|
; NOSORT: br 4 # 4: down to label41
|
|
|
|
; NOSORT: end_try
|
|
|
|
; --- Nested try/catch/end_try ends
|
|
|
|
; NOSORT: br 2 # 2: down to label42
|
|
|
|
; NOSORT: end_try
|
|
|
|
; NOSORT: catch $[[REG0]]=
|
|
|
|
; NOSORT: end_try # label43:
|
|
|
|
; NOSORT: i32.call $drop=, __cxa_begin_catch
|
|
|
|
; NOSORT: call __cxa_end_catch
|
|
|
|
; NOSORT: end_block # label42:
|
|
|
|
; NOSORT: return
|
|
|
|
; NOSORT: end_block # label41:
|
|
|
|
; NOSORT: rethrow $[[REG1]] # to caller
|
|
|
|
define void @test8() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
|
|
|
|
bb0:
|
|
|
|
invoke void @foo()
|
|
|
|
to label %bb1 unwind label %catch.dispatch0
|
|
|
|
|
|
|
|
bb1: ; preds = %bb0
|
|
|
|
invoke void @bar()
|
|
|
|
to label %try.cont unwind label %catch.dispatch1
|
|
|
|
|
|
|
|
catch.dispatch0: ; preds = %bb0
|
|
|
|
%0 = catchswitch within none [label %catch.start0] unwind to caller
|
|
|
|
|
|
|
|
catch.start0: ; preds = %catch.dispatch0
|
|
|
|
%1 = catchpad within %0 [i8* null]
|
|
|
|
%2 = call i8* @llvm.wasm.get.exception(token %1)
|
|
|
|
%3 = call i32 @llvm.wasm.get.ehselector(token %1)
|
|
|
|
%4 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
|
|
|
|
call void @__cxa_end_catch() [ "funclet"(token %1) ]
|
|
|
|
catchret from %1 to label %try.cont
|
|
|
|
|
|
|
|
catch.dispatch1: ; preds = %bb1
|
|
|
|
%5 = catchswitch within none [label %catch.start1] unwind to caller
|
|
|
|
|
|
|
|
catch.start1: ; preds = %catch.dispatch1
|
|
|
|
%6 = catchpad within %5 [i8* null]
|
|
|
|
%7 = call i8* @llvm.wasm.get.exception(token %6)
|
|
|
|
%8 = call i32 @llvm.wasm.get.ehselector(token %6)
|
|
|
|
%9 = call i8* @__cxa_begin_catch(i8* %7) [ "funclet"(token %6) ]
|
|
|
|
call void @__cxa_end_catch() [ "funclet"(token %6) ]
|
|
|
|
catchret from %6 to label %try.cont
|
|
|
|
|
|
|
|
try.cont: ; preds = %catch.start1, %catch.start0, %bb1
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
2018-08-08 04:19:23 +08:00
|
|
|
declare void @foo()
|
|
|
|
declare void @bar()
|
|
|
|
declare i32 @__gxx_wasm_personality_v0(...)
|
|
|
|
declare i8* @llvm.wasm.get.exception(token)
|
|
|
|
declare i32 @llvm.wasm.get.ehselector(token)
|
[WebAssembly] Make rethrow take an except_ref type argument
Summary:
In the new wasm EH proposal, `rethrow` takes an `except_ref` argument.
This change was missing in r352598.
This patch adds `llvm.wasm.rethrow.in.catch` intrinsic. This is an
intrinsic that's gonna eventually be lowered to wasm `rethrow`
instruction, but this intrinsic can appear only within a catchpad or a
cleanuppad scope. Also this intrinsic needs to be invokable - otherwise
EH pad successor for it will not be correctly generated in clang.
This also adds lowering logic for this intrinsic in
`SelectionDAGBuilder::visitInvoke`. This routine is basically a
specialized and simplified version of
`SelectionDAGBuilder::visitTargetIntrinsic`, but we can't use it
because if is only for `CallInst`s.
This deletes the previous `llvm.wasm.rethrow` intrinsic and related
tests, which was meant to be used within a `__cxa_rethrow` library
function. Turned out this needs some more logic, so the intrinsic for
this purpose will be added later.
LateEHPrepare takes a result value of `catch` and inserts it into
matching `rethrow` as an argument.
`RETHROW_IN_CATCH` is a pseudo instruction that serves as a link between
`llvm.wasm.rethrow.in.catch` and the real wasm `rethrow` instruction. To
generate a `rethrow` instruction, we need an `except_ref` argument,
which is generated from `catch` instruction. But `catch` instrutions are
added in LateEHPrepare pass, so we use `RETHROW_IN_CATCH`, which takes
no argument, until we are able to correctly lower it to `rethrow` in
LateEHPrepare.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D59352
llvm-svn: 356316
2019-03-16 13:38:57 +08:00
|
|
|
declare void @llvm.wasm.rethrow.in.catch()
|
2018-08-08 04:19:23 +08:00
|
|
|
declare i32 @llvm.eh.typeid.for(i8*)
|
|
|
|
declare i8* @__cxa_begin_catch(i8*)
|
|
|
|
declare void @__cxa_end_catch()
|
|
|
|
declare void @__clang_call_terminate(i8*)
|
|
|
|
declare void @_ZSt9terminatev()
|