aboutsummaryrefslogtreecommitdiff
path: root/test/CodeGen/WinEH/cppeh-demote-liveout.ll
blob: 309952bfc94beb38ca360400070dfb18f940f0ea (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
; RUN: opt -mtriple=x86_64-pc-windows-msvc -winehprepare -S < %s | FileCheck %s

; Notionally based on this C++ source:
; int liveout_catch(int p) {
;   int val = p + 1;
;   try {
;     might_throw();
;   } catch (int) {
;     val++;
;   }
;   return val;
; }

declare void @llvm.eh.begincatch(i8*, i8*)
declare void @llvm.eh.endcatch()
declare void @might_throw()
declare i32 @__CxxFrameHandler3(...)
declare i32 @llvm.eh.typeid.for(i8*)

@typeinfo.int = external global i32

define i32 @liveout_catch(i32 %p) personality i32 (...)* @__CxxFrameHandler3 {
entry:
  %val.entry = add i32 %p, 1
  invoke void @might_throw()
      to label %ret unwind label %lpad

lpad:
  %ehvals = landingpad { i8*, i32 }
      cleanup
      catch i32* @typeinfo.int
  %ehptr = extractvalue { i8*, i32 } %ehvals, 0
  %sel = extractvalue { i8*, i32 } %ehvals, 1
  %int_sel = call i32 @llvm.eh.typeid.for(i8* bitcast (i32* @typeinfo.int to i8*))
  %match = icmp eq i32 %sel, %int_sel
  br i1 %match, label %catchit, label %resume

catchit:
  call void @llvm.eh.begincatch(i8* %ehptr, i8* null)
  %val.lpad = add i32 %val.entry, 1
  call void @llvm.eh.endcatch()
  br label %ret

ret:
  %rv = phi i32 [%val.entry, %entry], [%val.lpad, %catchit]
  ret i32 %rv

resume:
  resume {i8*, i32} %ehvals
}

; CHECK-LABEL: define i32 @liveout_catch(i32 %p)
; CHECK: %val.entry = add i32 %p, 1
; CHECK-NEXT: store i32 %val.entry, i32* %val.entry.reg2mem
; CHECK: invoke void @might_throw()
;
; CHECK: landingpad
; CHECK: indirectbr i8* {{.*}}, [label %catchit.split]
;
; CHECK: catchit.split:
; CHECK: load i32, i32* %val.lpad.reg2mem
; CHECK: br label %ret
;
; CHECK: ret:
; CHECK: %rv = phi i32 [ {{.*}}, %entry ], [ {{.*}}, %catchit.split ]
; CHECK: ret i32

; CHECK-LABEL: define internal i8* @liveout_catch.catch(i8*, i8*)
; CHECK: %[[val:[^ ]*]] = load i32, i32*
; CHECK-NEXT: %[[val_lpad:[^ ]*]] = add i32 %[[val]], 1
; CHECK-NEXT: store i32 %[[val_lpad]], i32*
; CHECK: ret i8* blockaddress(@liveout_catch, %catchit.split)