1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 10:42:39 +01:00

[WebAssembly] Fix fixEndsAtEndOfFunction for delegate

Background:
CFGStackify's [[ 398f253400/llvm/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp (L1481-L1540) | fixEndsAtEndOfFunction ]] fixes block/loop/try's return
type when the end of function is unreachable and the function return
type is not void. So if a function returns i32 and `block`-`end` wraps the
whole function, i.e., the `block`'s `end` is the last instruction of the
function, the `block`'s return type should be i32 too:
```
block i32
  ...
end
end_function
```

If there are consecutive `end`s, this signature has to be propagate to
those blocks too, like:
```
block i32
  ...
  block i32
    ...
  end
end
end_function
```

This applies to `try`-`end` too:
```
try i32
  ...
catch
  ...
end
end_function
```

In case of `try`, we not only follow consecutive `end`s but also follow
`catch`, because for the type of the whole `try` to be i32, both `try`
and `catch` parts have to be i32:
```
try i32
  ...
  block i32
    ...
  end
catch
  ...
  block i32
    ...
  end
end
end_function
```

---

Previously we only handled consecutive `end`s or `end` before a `catch`.
But now we have `delegate`, which serves like `end` for
`try`-`delegate`. So we have to follow `delegate` too and mark its
corresponding `try` as i32 (the function's return type):
```
try i32
  ...
catch
  ...
  try i32    ;; Here
    ...
  delegate N
end
end_function
```

Reviewed By: tlively

Differential Revision: https://reviews.llvm.org/D101036
This commit is contained in:
Heejin Ahn 2021-04-22 02:00:57 -07:00
parent 4405bf5794
commit 5217fbac0b
2 changed files with 63 additions and 1 deletions

View File

@ -1524,6 +1524,7 @@ void WebAssemblyCFGStackify::fixEndsAtEndOfFunction(MachineFunction &MF) {
}
case WebAssembly::END_BLOCK:
case WebAssembly::END_LOOP:
case WebAssembly::DELEGATE:
EndToBegin[&MI]->getOperand(0).setImm(int32_t(RetType));
continue;
default:

View File

@ -9,6 +9,9 @@
define void @rethrow_arg_test() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
ret void
}
define i32 @fix_end_function_test() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
ret i32 0
}
...
---
@ -43,7 +46,7 @@ body: |
; CHECK: bb.2 (landing-pad):
; CHECK: CATCH
; CHECK: RETHROW 0
EH_LABEL <mcsymbol .Ltmp5>
EH_LABEL <mcsymbol .Ltmp3>
%1:i32 = CATCH &__cpp_exception, implicit-def dead $arguments
RETHROW 0, implicit-def dead $arguments
@ -53,3 +56,61 @@ body: |
; CHECK: END_TRY
RETURN implicit-def dead $arguments
...
---
# This function has i32 return type and the end of the function is unreachable,
# so CFGStackify's fixEndsAtEndOfFunction() propagates the return type while
# they encounter 'end' or 'delegate'. This is a regression test for a bug that
# we only handled 'end' but not 'delegate'.
# CHECK-LABEL: name: fix_end_function_test
name: fix_end_function_test
liveins:
- { reg: '$arguments' }
machineFunctionInfo:
params: [ ]
results: [ i32 ]
wasmEHFuncInfo:
3: 4
body: |
; CHECK: TRY 127
; CHECK: TRY 127
; CHECK: CALL @foo
; CHECK: TRY 64
; CHECK: CALL @foo
; CHECK: DELEGATE
; CHECK: RETURN
; CHECK: CATCH
;; This TRY should have the return type i32 (127)
; CHECK: TRY 127
; CHECK: RETHROW
; CHECK: DELEGATE
; CHECK: END_TRY
; CHECK: CATCH
; CHECK: RETHROW
; CHECK: END_TRY
bb.0:
successors: %bb.1, %bb.3
EH_LABEL <mcsymbol .Ltmp0>
CALL @foo, implicit-def dead $arguments, implicit $sp32, implicit $sp64
EH_LABEL <mcsymbol .Ltmp1>
bb.1:
successors: %bb.2, %bb.4
EH_LABEL <mcsymbol .Ltmp2>
CALL @foo, implicit-def dead $arguments, implicit $sp32, implicit $sp64
EH_LABEL <mcsymbol .Ltmp3>
bb.2:
%0:i32 = CONST_I32 3, implicit-def dead $arguments
RETURN %0:i32, implicit-def dead $arguments
bb.3 (landing-pad):
EH_LABEL <mcsymbol .Ltmp4>
%0:i32 = CATCH &__cpp_exception, implicit-def dead $arguments
RETHROW 0, implicit-def dead $arguments
bb.4 (landing-pad):
EH_LABEL <mcsymbol .Ltmp5>
%1:i32 = CATCH &__cpp_exception, implicit-def dead $arguments
RETHROW 0, implicit-def dead $arguments
...