2019-10-08 10:50:27 +08:00
|
|
|
; REQUIRES: asserts
|
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
|
2019-10-08 06:19:40 +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 -stats 2>&1 | FileCheck %s --check-prefix=NOSORT-STAT
|
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.
|
|
|
|
|
2019-10-01 14:21:53 +08:00
|
|
|
; And the return value of 'baz' should NOT be stackified because the BB is split
|
|
|
|
; during fixing unwind mismatches.
|
|
|
|
|
2019-03-30 19:04:48 +08:00
|
|
|
; NOSORT-LABEL: test6
|
|
|
|
; NOSORT: try
|
|
|
|
; NOSORT: call foo
|
|
|
|
; --- Nested try/catch/end_try starts
|
|
|
|
; NOSORT: try
|
|
|
|
; NOSORT: call bar
|
2019-10-01 14:21:53 +08:00
|
|
|
; NOSORT: i32.call ${{[0-9]+}}=, baz
|
|
|
|
; NOSORT-NOT: i32.call $push{{.*}}=, baz
|
2019-03-30 19:04:48 +08:00
|
|
|
; 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()
|
2019-10-01 14:21:53 +08:00
|
|
|
%call = call i32 @baz()
|
|
|
|
call void @nothrow(i32 %call) #0
|
2019-03-30 19:04:48 +08:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2019-10-01 14:53:28 +08:00
|
|
|
; In CFGSort, EH pads should be sorted as soon as it is available and
|
|
|
|
; 'Preferred' queue and should NOT be entered into 'Ready' queue unless we are
|
|
|
|
; in the middle of sorting another region that does not contain the EH pad. In
|
|
|
|
; this example, 'catch.start' should be sorted right after 'if.then' is sorted
|
|
|
|
; (before 'cont' is sorted) and there should not be any unwind destination
|
|
|
|
; mismatches in CFGStackify.
|
|
|
|
|
|
|
|
; NOOPT: block
|
|
|
|
; NOOPT: try
|
|
|
|
; NOOPT: call foo
|
|
|
|
; NOOPT: catch
|
|
|
|
; NOOPT: end_try
|
|
|
|
; NOOPT: call foo
|
|
|
|
; NOOPT: end_block
|
|
|
|
; NOOPT: return
|
|
|
|
define void @test9(i32 %arg) personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
|
|
|
|
entry:
|
|
|
|
%tobool = icmp ne i32 %arg, 0
|
|
|
|
br i1 %tobool, label %if.then, label %if.end
|
|
|
|
|
|
|
|
catch.dispatch: ; preds = %if.then
|
|
|
|
%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) ]
|
|
|
|
call void @__cxa_end_catch() [ "funclet"(token %1) ]
|
|
|
|
catchret from %1 to label %if.end
|
|
|
|
|
|
|
|
if.then: ; preds = %entry
|
|
|
|
invoke void @foo()
|
|
|
|
to label %cont unwind label %catch.dispatch
|
|
|
|
|
|
|
|
cont: ; preds = %if.then
|
|
|
|
call void @foo()
|
|
|
|
br label %if.end
|
|
|
|
|
|
|
|
if.end: ; preds = %cont, %catch.start, %entry
|
|
|
|
ret void
|
|
|
|
}
|
|
|
|
|
[WebAssembly] Add memory intrinsics handling to mayThrow()
Summary:
Previously, `WebAssembly::mayThrow()` assumed all inputs are global
addresses. But when intrinsics, such as `memcpy`, `memmove`, or `memset`
are lowered to external symbols in instruction selection and later
emitted as library calls. And these functions don't throw.
This patch adds handling to those memory intrinsics to `mayThrow`
function. But while most of libcalls don't throw, we can't guarantee all
of them don't throw, so currently we conservatively return true for all
other external symbols.
I think a better way to solve this problem is to embed 'nounwind' info
in `TargetLowering::CallLoweringInfo`, so that we can access the info
from the backend. This will also enable transferring 'nounwind'
properties of LLVM IR instructions. Currently we don't transfer that
info and we can only access properties of callee functions, if the
callees are within the module. Other targets don't need this info in the
backend because they do all the processing before isel, but it will help
us because that info will reduce code size increase in fixing unwind
destination mismatches in CFGStackify.
But for now we return false for these memory intrinsics and true for all
other libcalls conservatively.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, hiraditya, sunfish, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D68553
llvm-svn: 373967
2019-10-08 05:14:45 +08:00
|
|
|
%class.Object = type { i8 }
|
|
|
|
|
|
|
|
; Intrinsics like memcpy, memmove, and memset don't throw and are lowered into
|
|
|
|
; calls to external symbols (not global addresses) in instruction selection,
|
|
|
|
; which will be eventually lowered to library function calls.
|
|
|
|
; Because this test runs with -wasm-disable-ehpad-sort, these library calls in
|
|
|
|
; invoke.cont BB fall within try~end_try, but they shouldn't cause crashes or
|
|
|
|
; unwinding destination mismatches in CFGStackify.
|
|
|
|
|
|
|
|
; NOSORT-LABEL: test10
|
|
|
|
; NOSORT: try
|
|
|
|
; NOSORT: call foo
|
|
|
|
; NOSORT: i32.call {{.*}} memcpy
|
|
|
|
; NOSORT: i32.call {{.*}} memmove
|
|
|
|
; NOSORT: i32.call {{.*}} memset
|
|
|
|
; NOSORT: return
|
|
|
|
; NOSORT: catch
|
|
|
|
; NOSORT: rethrow
|
|
|
|
; NOSORT: end_try
|
|
|
|
define void @test10(i8* %a, i8* %b) personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
|
|
|
|
entry:
|
|
|
|
%o = alloca %class.Object, align 1
|
|
|
|
invoke void @foo()
|
|
|
|
to label %invoke.cont unwind label %ehcleanup
|
|
|
|
|
|
|
|
invoke.cont: ; preds = %entry
|
|
|
|
call void @llvm.memcpy.p0i8.p0i8.i32(i8* %a, i8* %b, i32 100, i1 false)
|
|
|
|
call void @llvm.memmove.p0i8.p0i8.i32(i8* %a, i8* %b, i32 100, i1 false)
|
|
|
|
call void @llvm.memset.p0i8.i32(i8* %a, i8 0, i32 100, i1 false)
|
|
|
|
%call = call %class.Object* @_ZN6ObjectD2Ev(%class.Object* %o) #1
|
|
|
|
ret void
|
|
|
|
|
|
|
|
ehcleanup: ; preds = %entry
|
|
|
|
%0 = cleanuppad within none []
|
|
|
|
%call2 = call %class.Object* @_ZN6ObjectD2Ev(%class.Object* %o) #1 [ "funclet"(token %0) ]
|
|
|
|
cleanupret from %0 unwind to caller
|
|
|
|
}
|
|
|
|
|
[WebAssembly] Fix a bug in 'try' placement
Summary:
When searching for local expression tree created by stackified
registers, for 'block' placement, we start the search from the previous
instruction of a BB's terminator. But in 'try''s case, we should start
from the previous instruction of a call that can throw, or a EH_LABEL
that precedes the call, because the return values of the call's previous
instructions can be stackified and consumed by the throwing call.
For example,
```
i32.call @foo
call @bar ; may throw
br $label0
```
In this case, if we start the search from the previous instruction of
the terminator (`br` here), we end up stopping at `call @bar` and place
a 'try' between `i32.call @foo` and `call @bar`, because `call @bar`
does not have a return value so it is not a local expression tree of
`br`.
But in this case, unlike when placing 'block's, we should start the
search from `call @bar`, because the return value of `i32.call @foo` is
stackified and used by `call @bar`.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, hiraditya, sunfish, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D68619
llvm-svn: 374073
2019-10-09 00:15:39 +08:00
|
|
|
; Tests if 'try' marker is placed correctly. In this test, 'try' should be
|
|
|
|
; placed before the call to 'nothrow_i32' and not between the call to
|
|
|
|
; 'nothrow_i32' and 'fun', because the return value of 'nothrow_i32' is
|
|
|
|
; stackified and pushed onto the stack to be consumed by the call to 'fun'.
|
|
|
|
|
|
|
|
; CHECK-LABEL: test11
|
|
|
|
; CHECK: try
|
|
|
|
; CHECK: i32.call $push{{.*}}=, nothrow_i32
|
|
|
|
; CHECK: call fun, $pop{{.*}}
|
|
|
|
define void @test11() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
|
|
|
|
entry:
|
|
|
|
%call = call i32 @nothrow_i32()
|
|
|
|
invoke void @fun(i32 %call)
|
|
|
|
to label %invoke.cont unwind label %terminate
|
|
|
|
|
|
|
|
invoke.cont: ; preds = %entry
|
|
|
|
ret void
|
|
|
|
|
|
|
|
terminate: ; preds = %entry
|
|
|
|
%0 = cleanuppad within none []
|
|
|
|
%1 = tail call i8* @llvm.wasm.get.exception(token %0)
|
|
|
|
call void @__clang_call_terminate(i8* %1) [ "funclet"(token %0) ]
|
|
|
|
unreachable
|
|
|
|
}
|
|
|
|
|
2019-10-08 06:19:40 +08:00
|
|
|
; Check if the unwind destination mismatch stats are correct
|
|
|
|
; NOSORT-STAT: 11 wasm-cfg-stackify - Number of EH pad unwind mismatches found
|
|
|
|
|
2018-08-08 04:19:23 +08:00
|
|
|
declare void @foo()
|
|
|
|
declare void @bar()
|
2019-10-01 14:21:53 +08:00
|
|
|
declare i32 @baz()
|
[WebAssembly] Fix a bug in 'try' placement
Summary:
When searching for local expression tree created by stackified
registers, for 'block' placement, we start the search from the previous
instruction of a BB's terminator. But in 'try''s case, we should start
from the previous instruction of a call that can throw, or a EH_LABEL
that precedes the call, because the return values of the call's previous
instructions can be stackified and consumed by the throwing call.
For example,
```
i32.call @foo
call @bar ; may throw
br $label0
```
In this case, if we start the search from the previous instruction of
the terminator (`br` here), we end up stopping at `call @bar` and place
a 'try' between `i32.call @foo` and `call @bar`, because `call @bar`
does not have a return value so it is not a local expression tree of
`br`.
But in this case, unlike when placing 'block's, we should start the
search from `call @bar`, because the return value of `i32.call @foo` is
stackified and used by `call @bar`.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, hiraditya, sunfish, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D68619
llvm-svn: 374073
2019-10-09 00:15:39 +08:00
|
|
|
declare void @fun(i32)
|
2019-10-01 14:21:53 +08:00
|
|
|
; Function Attrs: nounwind
|
|
|
|
declare void @nothrow(i32) #0
|
[WebAssembly] Fix a bug in 'try' placement
Summary:
When searching for local expression tree created by stackified
registers, for 'block' placement, we start the search from the previous
instruction of a BB's terminator. But in 'try''s case, we should start
from the previous instruction of a call that can throw, or a EH_LABEL
that precedes the call, because the return values of the call's previous
instructions can be stackified and consumed by the throwing call.
For example,
```
i32.call @foo
call @bar ; may throw
br $label0
```
In this case, if we start the search from the previous instruction of
the terminator (`br` here), we end up stopping at `call @bar` and place
a 'try' between `i32.call @foo` and `call @bar`, because `call @bar`
does not have a return value so it is not a local expression tree of
`br`.
But in this case, unlike when placing 'block's, we should start the
search from `call @bar`, because the return value of `i32.call @foo` is
stackified and used by `call @bar`.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, hiraditya, sunfish, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D68619
llvm-svn: 374073
2019-10-09 00:15:39 +08:00
|
|
|
declare i32 @nothrow_i32() #0
|
[WebAssembly] Add memory intrinsics handling to mayThrow()
Summary:
Previously, `WebAssembly::mayThrow()` assumed all inputs are global
addresses. But when intrinsics, such as `memcpy`, `memmove`, or `memset`
are lowered to external symbols in instruction selection and later
emitted as library calls. And these functions don't throw.
This patch adds handling to those memory intrinsics to `mayThrow`
function. But while most of libcalls don't throw, we can't guarantee all
of them don't throw, so currently we conservatively return true for all
other external symbols.
I think a better way to solve this problem is to embed 'nounwind' info
in `TargetLowering::CallLoweringInfo`, so that we can access the info
from the backend. This will also enable transferring 'nounwind'
properties of LLVM IR instructions. Currently we don't transfer that
info and we can only access properties of callee functions, if the
callees are within the module. Other targets don't need this info in the
backend because they do all the processing before isel, but it will help
us because that info will reduce code size increase in fixing unwind
destination mismatches in CFGStackify.
But for now we return false for these memory intrinsics and true for all
other libcalls conservatively.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, hiraditya, sunfish, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D68553
llvm-svn: 373967
2019-10-08 05:14:45 +08:00
|
|
|
; Function Attrs: nounwind
|
|
|
|
declare %class.Object* @_ZN6ObjectD2Ev(%class.Object* returned) #0
|
2018-08-08 04:19:23 +08:00
|
|
|
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()
|
[WebAssembly] Add memory intrinsics handling to mayThrow()
Summary:
Previously, `WebAssembly::mayThrow()` assumed all inputs are global
addresses. But when intrinsics, such as `memcpy`, `memmove`, or `memset`
are lowered to external symbols in instruction selection and later
emitted as library calls. And these functions don't throw.
This patch adds handling to those memory intrinsics to `mayThrow`
function. But while most of libcalls don't throw, we can't guarantee all
of them don't throw, so currently we conservatively return true for all
other external symbols.
I think a better way to solve this problem is to embed 'nounwind' info
in `TargetLowering::CallLoweringInfo`, so that we can access the info
from the backend. This will also enable transferring 'nounwind'
properties of LLVM IR instructions. Currently we don't transfer that
info and we can only access properties of callee functions, if the
callees are within the module. Other targets don't need this info in the
backend because they do all the processing before isel, but it will help
us because that info will reduce code size increase in fixing unwind
destination mismatches in CFGStackify.
But for now we return false for these memory intrinsics and true for all
other libcalls conservatively.
Reviewers: dschuff
Subscribers: sbc100, jgravelle-google, hiraditya, sunfish, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D68553
llvm-svn: 373967
2019-10-08 05:14:45 +08:00
|
|
|
; Function Attrs: nounwind
|
|
|
|
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i32, i1 immarg) #0
|
|
|
|
; Function Attrs: nounwind
|
|
|
|
declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i1 immarg) #0
|
|
|
|
; Function Attrs: nounwind
|
|
|
|
declare void @llvm.memset.p0i8.i32(i8* nocapture writeonly, i8, i32, i1 immarg) #0
|
2019-10-01 14:21:53 +08:00
|
|
|
|
|
|
|
attributes #0 = { nounwind }
|