1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-22 04:22:57 +02:00
llvm-mirror/test/CodeGen/WebAssembly/cfg-stackify-eh.mir
Heejin Ahn 0b69bb0689 [WebAssembly] Fix immediate of rethrow when throwing to caller
Summary:
Currently when assigning depths 'rethrow' does not take the whole
control flow stack into accounts but only considers EH pad stacks. When
assigning depth immmediates to rethrows, in normal cases it is done
correctly but when a rethrow instruction throws up to a caller, i.e., we
convert a pseudo RETHROW_TO_CALLER instruction to a rethrow, it
mistakenly compute the whole stack depth.

Reviewers: dschuff

Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits

Differential Revision: https://reviews.llvm.org/D53619

llvm-svn: 345223
2018-10-24 23:31:24 +00:00

323 lines
13 KiB
YAML

# RUN: llc -mtriple=wasm32-unknown-unknown -exception-model=wasm -run-pass wasm-cfg-stackify %s -o - | FileCheck %s
--- |
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
target triple = "wasm32-unknown-unknown"
@__wasm_lpad_context = external global { i32, i8*, i32 }
declare void @may_throw()
; Function Attrs: nounwind
declare void @dont_throw() #0
declare i8* @__cxa_begin_catch(i8*)
declare void @__cxa_end_catch()
declare void @__cxa_rethrow()
; Function Attrs: nounwind
declare i32 @__gxx_wasm_personality_v0(...)
declare i32 @_Unwind_CallPersonality(i8*) #0
define void @test0() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
unreachable
}
define void @test1() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
unreachable
}
define void @test2() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
unreachable
}
define void @test3() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
unreachable
}
attributes #0 = { nounwind }
---
# Simplest try-catch
# try {
# may_throw();
# } catch (...) {
# }
name: test0
# CHECK-LABEL: name: test0
liveins:
- { reg: '$arguments', reg: '$value_stack' }
body: |
bb.0:
successors: %bb.2, %bb.1
CALL_VOID @may_throw, implicit-def dead $arguments, implicit $sp32, implicit $sp64
BR %bb.2, implicit-def $arguments
; CHECK-LABEL: bb.0:
; CHECK: TRY
; CHECK-NEXT: CALL_VOID @may_throw
bb.1 (landing-pad):
; predecessors: %bb.0
successors: %bb.2
%2:i32 = CATCH_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
%3:i32 = CALL_I32 @__cxa_begin_catch, %2:i32, implicit-def dead $arguments, implicit $sp32, implicit $sp64, implicit-def $value_stack, implicit $value_stack
DROP_I32 killed %3:i32, implicit-def $arguments
CALL_VOID @__cxa_end_catch, implicit-def dead $arguments, implicit $sp32, implicit $sp64
bb.2:
; predecessors: %bb.0, %bb.1
RETURN_VOID implicit-def dead $arguments
; CHECK-LABEL: bb.2:
; CHECK-NEXT: END_TRY
; CHECK: RETURN_VOID
...
---
# Nested try-catch inside another catch
# try {
# may_throw();
# } catch (int n) {
# try {
# may_throw();
# } catch (int n) {
# }
# }
name: test1
# CHECK-LABEL: name: test1
liveins:
- { reg: '$arguments', reg: '$value_stack' }
body: |
bb.0:
successors: %bb.9, %bb.1
CALL_VOID @may_throw, implicit-def dead $arguments, implicit $sp32, implicit $sp64
BR %bb.9, implicit-def $arguments
; CHECK-LABEL: bb.0:
; CHECK: TRY
; CHECK-NEXT: CALL_VOID @may_throw
bb.1 (landing-pad):
; predecessors: %bb.0
successors: %bb.2, %bb.7
%30:i32 = CATCH_I32 0, implicit-def dead $arguments
SET_LOCAL_I32 0, %30:i32, implicit-def $arguments
%16:i32 = CONST_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
%27:i32 = CONST_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
STORE_I32 2, @__wasm_lpad_context + 4, %16:i32, %27:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack :: (store 4 into `i8** getelementptr inbounds ({ i32, i8*, i32 }, { i32, i8*, i32 }* @__wasm_lpad_context, i32 0, i32 1)`)
%26:i32 = CONST_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
%25:i32 = CONST_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
STORE_I32 2, @__wasm_lpad_context, %26:i32, %25:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack :: (store 4 into `i32* getelementptr inbounds ({ i32, i8*, i32 }, { i32, i8*, i32 }* @__wasm_lpad_context, i32 0, i32 0)`)
%32:i32 = GET_LOCAL_I32 0, implicit-def $arguments
%31:i32 = CALL_I32 @_Unwind_CallPersonality, %32:i32, implicit-def dead $arguments, implicit $sp32, implicit $sp64
DROP_I32 killed %31:i32, implicit-def $arguments
%24:i32 = CONST_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
%17:i32 = LOAD_I32 2, @__wasm_lpad_context + 8, %24:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack :: (dereferenceable load 4 from `i32* getelementptr inbounds ({ i32, i8*, i32 }, { i32, i8*, i32 }* @__wasm_lpad_context, i32 0, i32 2)`)
%18:i32 = CONST_I32 1, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
%19:i32 = NE_I32 %17:i32, %18:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
BR_IF %bb.7, %19:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
bb.2:
; predecessors: %bb.1
successors: %bb.8, %bb.3, %bb.6
%34:i32 = GET_LOCAL_I32 0, implicit-def $arguments
%33:i32 = CALL_I32 @__cxa_begin_catch, %34:i32, implicit-def dead $arguments, implicit $sp32, implicit $sp64
DROP_I32 killed %33:i32, implicit-def $arguments
CALL_VOID @may_throw, implicit-def dead $arguments, implicit $sp32, implicit $sp64
BR %bb.8, implicit-def $arguments
; CHECK-LABEL: bb.2:
; CHECK: DROP_I32
; CHECK-NEXT: TRY
; CHECK-NEXT: TRY
; CHECK-NEXT: CALL_VOID @may_throw
bb.3 (landing-pad):
; predecessors: %bb.2
successors: %bb.4, %bb.5
%35:i32 = CATCH_I32 0, implicit-def dead $arguments
SET_LOCAL_I32 0, %35:i32, implicit-def $arguments
%21:i32 = CONST_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
%20:i32 = CONST_I32 1, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
STORE_I32 2, @__wasm_lpad_context, %21:i32, %20:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack :: (store 4 into `i32* getelementptr inbounds ({ i32, i8*, i32 }, { i32, i8*, i32 }* @__wasm_lpad_context, i32 0, i32 0)`)
%37:i32 = GET_LOCAL_I32 0, implicit-def $arguments
%36:i32 = CALL_I32 @_Unwind_CallPersonality, %37:i32, implicit-def dead $arguments, implicit $sp32, implicit $sp64
DROP_I32 killed %36:i32, implicit-def $arguments
%29:i32 = CONST_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
%22:i32 = LOAD_I32 2, @__wasm_lpad_context + 8, %29:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack :: (dereferenceable load 4 from `i32* getelementptr inbounds ({ i32, i8*, i32 }, { i32, i8*, i32 }* @__wasm_lpad_context, i32 0, i32 2)`)
%28:i32 = CONST_I32 1, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
%23:i32 = NE_I32 %22:i32, %28:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
BR_IF %bb.5, %23:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
bb.4:
; predecessors: %bb.3
successors: %bb.8
%39:i32 = GET_LOCAL_I32 0, implicit-def $arguments
%38:i32 = CALL_I32 @__cxa_begin_catch, %39:i32, implicit-def dead $arguments, implicit $sp32, implicit $sp64
DROP_I32 killed %38:i32, implicit-def $arguments
CALL_VOID @__cxa_end_catch, implicit-def dead $arguments, implicit $sp32, implicit $sp64
BR %bb.8, implicit-def $arguments
bb.5:
; predecessors: %bb.3
successors: %bb.6
CALL_VOID @__cxa_rethrow, implicit-def dead $arguments, implicit $sp32, implicit $sp64
RETHROW %bb.6, implicit-def $arguments
bb.6 (landing-pad):
; predecessors: %bb.2, %bb.5
CATCH_ALL implicit-def $arguments
CALL_VOID @__cxa_end_catch, implicit-def dead $arguments, implicit $sp32, implicit $sp64
RETHROW_TO_CALLER implicit-def $arguments
; CHECK-LABEL: bb.6 (landing-pad):
; CHECK-NEXT: END_TRY
bb.7:
; predecessors: %bb.1
CALL_VOID @__cxa_rethrow, implicit-def dead $arguments, implicit $sp32, implicit $sp64
RETHROW_TO_CALLER implicit-def $arguments
; CHECK-LABEL: bb.7:
; CHECK-NEXT: END_TRY
; CHECK: RETHROW 0
bb.8:
; predecessors: %bb.2, %bb.4
successors: %bb.9
CALL_VOID @__cxa_end_catch, implicit-def dead $arguments, implicit $sp32, implicit $sp64
bb.9:
; predecessors: %bb.0, %bb.8
RETURN_VOID implicit-def dead $arguments
; CHECK-LABEL: bb.9:
; CHECK-NEXT: END_TRY
...
---
# A loop within a try.
# try {
# for (int i = 0; i < n; ++i)
# may_throw();
# } catch (...) {
# }
name: test2
# CHECK-LABEL: name: test2
liveins:
- { reg: '$arguments', reg: '$value_stack' }
body: |
bb.0:
successors: %bb.1, %bb.4
%18:i32 = CONST_I32 0, implicit-def dead $arguments
SET_LOCAL_I32 1, %18:i32, implicit-def $arguments
%14:i32 = CONST_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
%19:i32 = GET_LOCAL_I32 0, implicit-def $arguments
%9:i32 = GE_S_I32 %14:i32, %19:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
BR_IF %bb.4, %9:i32, implicit-def $arguments
bb.1:
; predecessors: %bb.0, %bb.3
successors: %bb.3, %bb.2
CALL_VOID @may_throw, implicit-def dead $arguments, implicit $sp32, implicit $sp64
BR %bb.3, implicit-def $arguments
; CHECK-LABEL: bb.1:
; CHECK: LOOP
; CHECK: TRY
; CHECK-NEXT: CALL_VOID @may_throw
bb.2 (landing-pad):
; predecessors: %bb.1
successors: %bb.4
%11:i32 = CATCH_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
%22:i32 = CALL_I32 @__cxa_begin_catch, %11:i32, implicit-def dead $arguments, implicit $sp32, implicit $sp64, implicit-def $value_stack, implicit $value_stack
DROP_I32 killed %22:i32, implicit-def $arguments
CALL_VOID @__cxa_end_catch, implicit-def dead $arguments, implicit $sp32, implicit $sp64
BR %bb.4, implicit-def $arguments
bb.3:
; predecessors: %bb.1
successors: %bb.1, %bb.4
%20:i32 = GET_LOCAL_I32 1, implicit-def $arguments
%17:i32 = CONST_I32 1, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
%16:i32 = ADD_I32 %20:i32, %17:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
%15:i32 = TEE_LOCAL_I32 1, %16:i32, implicit-def $arguments
%21:i32 = GET_LOCAL_I32 0, implicit-def $arguments
%10:i32 = GE_S_I32 %15:i32, %21:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
BR_UNLESS %bb.1, %10:i32, implicit-def $arguments
; CHECK-LABEL: bb.3:
; CHECK: END_TRY
bb.4:
; predecessors: %bb.2, %bb.0, %bb.3
RETURN_VOID implicit-def dead $arguments
...
---
# A loop within a catch
# try {
# may_throw();
# } catch (...) {
# for (int i = 0; i < n; ++i)
# dont_throw();
# }
name: test3
# CHECK-LABEL: name: test3
liveins:
- { reg: '$arguments', reg: '$value_stack' }
body: |
bb.0:
successors: %bb.4, %bb.1
CALL_VOID @may_throw, implicit-def dead $arguments, implicit $sp32, implicit $sp64
BR %bb.4, implicit-def $arguments
; CHECK-LABEL: bb.0:
; CHECK: TRY
; CHECK-NEXT: CALL_VOID @may_throw
bb.1 (landing-pad):
; predecessors: %bb.0
successors: %bb.2, %bb.3
%9:i32 = CATCH_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
%18:i32 = CALL_I32 @__cxa_begin_catch, %9:i32, implicit-def dead $arguments, implicit $sp32, implicit $sp64, implicit-def $value_stack, implicit $value_stack
DROP_I32 killed %18:i32, implicit-def $arguments
%19:i32 = CONST_I32 0, implicit-def dead $arguments
SET_LOCAL_I32 1, %19:i32, implicit-def $arguments
%14:i32 = CONST_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
%20:i32 = GET_LOCAL_I32 0, implicit-def $arguments
%10:i32 = GE_S_I32 %14:i32, %20:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
BR_IF %bb.3, %10:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
bb.2:
; predecessors: %bb.1, %bb.2
successors: %bb.2, %bb.3
CALL_VOID @dont_throw, implicit-def dead $arguments, implicit $sp32, implicit $sp64
%21:i32 = GET_LOCAL_I32 1, implicit-def $arguments
%17:i32 = CONST_I32 1, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
%16:i32 = ADD_I32 %21:i32, %17:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
%15:i32 = TEE_LOCAL_I32 1, %16:i32, implicit-def $arguments
%22:i32 = GET_LOCAL_I32 0, implicit-def $arguments
%11:i32 = GE_S_I32 %15:i32, %22:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
BR_UNLESS %bb.2, %11:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
bb.3:
; predecessors: %bb.1, %bb.2
successors: %bb.4
CALL_VOID @__cxa_end_catch, implicit-def dead $arguments, implicit $sp32, implicit $sp64
bb.4:
; predecessors: %bb.0, %bb.3
RETURN_VOID implicit-def dead $arguments
; CHECK-LABEL: bb.4:
; CHECK: END_TRY