@@ -46,6 +46,74 @@ impl<'tcx> DropValue<'tcx> {
46
46
fn trans < ' a > ( & self , funclet : Option < & ' a Funclet > , bcx : & BlockAndBuilder < ' a , ' tcx > ) {
47
47
glue:: call_drop_glue ( bcx, self . val , self . ty , self . skip_dtor , funclet)
48
48
}
49
+
50
+ /// Creates a landing pad for the top scope. The landing pad will perform all cleanups necessary
51
+ /// for an unwind and then `resume` to continue error propagation:
52
+ ///
53
+ /// landing_pad -> ... cleanups ... -> [resume]
54
+ ///
55
+ /// This should only be called once per function, as it creates an alloca for the landingpad.
56
+ fn get_landing_pad < ' a > ( & self , fcx : & FunctionContext < ' a , ' tcx > ) -> BasicBlockRef {
57
+ debug ! ( "get_landing_pad" ) ;
58
+
59
+ let mut pad_bcx = fcx. build_new_block ( "unwind_custom_" ) ;
60
+
61
+ let llpersonality = pad_bcx. fcx ( ) . eh_personality ( ) ;
62
+
63
+ let resume_bcx = fcx. build_new_block ( "resume" ) ;
64
+ let val = if base:: wants_msvc_seh ( fcx. ccx . sess ( ) ) {
65
+ // A cleanup pad requires a personality function to be specified, so
66
+ // we do that here explicitly (happens implicitly below through
67
+ // creation of the landingpad instruction). We then create a
68
+ // cleanuppad instruction which has no filters to run cleanup on all
69
+ // exceptions.
70
+ pad_bcx. set_personality_fn ( llpersonality) ;
71
+ let llretval = pad_bcx. cleanup_pad ( None , & [ ] ) ;
72
+ resume_bcx. cleanup_ret ( resume_bcx. cleanup_pad ( None , & [ ] ) , None ) ;
73
+ UnwindKind :: CleanupPad ( llretval)
74
+ } else {
75
+ // The landing pad return type (the type being propagated). Not sure
76
+ // what this represents but it's determined by the personality
77
+ // function and this is what the EH proposal example uses.
78
+ let llretty = Type :: struct_ ( fcx. ccx , & [ Type :: i8p ( fcx. ccx ) , Type :: i32 ( fcx. ccx ) ] , false ) ;
79
+
80
+ // The only landing pad clause will be 'cleanup'
81
+ let llretval = pad_bcx. landing_pad ( llretty, llpersonality, 1 , pad_bcx. fcx ( ) . llfn ) ;
82
+
83
+ // The landing pad block is a cleanup
84
+ pad_bcx. set_cleanup ( llretval) ;
85
+
86
+ let addr = pad_bcx. fcx ( ) . alloca ( common:: val_ty ( llretval) , "" ) ;
87
+ Lifetime :: Start . call ( & pad_bcx, addr) ;
88
+ pad_bcx. store ( llretval, addr) ;
89
+ let lp = resume_bcx. load ( addr) ;
90
+ Lifetime :: End . call ( & resume_bcx, addr) ;
91
+ if !resume_bcx. sess ( ) . target . target . options . custom_unwind_resume {
92
+ resume_bcx. resume ( lp) ;
93
+ } else {
94
+ let exc_ptr = resume_bcx. extract_value ( lp, 0 ) ;
95
+ resume_bcx. call ( fcx. eh_unwind_resume ( ) . reify ( fcx. ccx ) , & [ exc_ptr] , None ) ;
96
+ }
97
+ UnwindKind :: LandingPad
98
+ } ;
99
+
100
+ let mut cleanup = fcx. build_new_block ( "clean_custom_" ) ;
101
+
102
+ // Insert cleanup instructions into the cleanup block
103
+ let funclet = match val {
104
+ UnwindKind :: CleanupPad ( _) => Some ( Funclet :: new ( cleanup. cleanup_pad ( None , & [ ] ) ) ) ,
105
+ UnwindKind :: LandingPad => None ,
106
+ } ;
107
+ self . trans ( funclet. as_ref ( ) , & cleanup) ;
108
+
109
+ // Insert instruction into cleanup block to branch to the exit
110
+ val. branch ( & mut cleanup, resume_bcx. llbb ( ) ) ;
111
+
112
+ // Branch into the cleanup block
113
+ val. branch ( & mut pad_bcx, cleanup. llbb ( ) ) ;
114
+
115
+ pad_bcx. llbb ( )
116
+ }
49
117
}
50
118
51
119
#[ derive( Copy , Clone , Debug ) ]
@@ -73,16 +141,6 @@ impl UnwindKind {
73
141
}
74
142
}
75
143
76
- impl PartialEq for UnwindKind {
77
- fn eq ( & self , label : & UnwindKind ) -> bool {
78
- match ( * self , * label) {
79
- ( UnwindKind :: LandingPad , UnwindKind :: LandingPad ) |
80
- ( UnwindKind :: CleanupPad ( ..) , UnwindKind :: CleanupPad ( ..) ) => true ,
81
- _ => false ,
82
- }
83
- }
84
- }
85
-
86
144
impl < ' a , ' tcx > FunctionContext < ' a , ' tcx > {
87
145
/// Schedules a (deep) drop of `val`, which is a pointer to an instance of `ty`
88
146
pub fn schedule_drop_mem ( & self , val : ValueRef , ty : Ty < ' tcx > ) -> CleanupScope < ' tcx > {
@@ -126,7 +184,7 @@ impl<'tcx> CleanupScope<'tcx> {
126
184
CleanupScope {
127
185
cleanup : Some ( drop_val) ,
128
186
landing_pad : if !fcx. ccx . sess ( ) . no_landing_pads ( ) {
129
- Some ( CleanupScope :: get_landing_pad ( fcx, & drop_val ) )
187
+ Some ( drop_val . get_landing_pad ( fcx) )
130
188
} else {
131
189
None
132
190
} ,
@@ -145,73 +203,4 @@ impl<'tcx> CleanupScope<'tcx> {
145
203
cleanup. trans ( None , & bcx) ;
146
204
}
147
205
}
148
-
149
- /// Creates a landing pad for the top scope. The landing pad will perform all cleanups necessary
150
- /// for an unwind and then `resume` to continue error propagation:
151
- ///
152
- /// landing_pad -> ... cleanups ... -> [resume]
153
- ///
154
- /// This should only be called once per function, as it creates an alloca for the landingpad.
155
- fn get_landing_pad < ' a > ( fcx : & FunctionContext < ' a , ' tcx > , drop_val : & DropValue < ' tcx > )
156
- -> BasicBlockRef {
157
- debug ! ( "get_landing_pad" ) ;
158
-
159
- let mut pad_bcx = fcx. build_new_block ( "unwind_custom_" ) ;
160
-
161
- let llpersonality = pad_bcx. fcx ( ) . eh_personality ( ) ;
162
-
163
- let resume_bcx = fcx. build_new_block ( "resume" ) ;
164
- let val = if base:: wants_msvc_seh ( fcx. ccx . sess ( ) ) {
165
- // A cleanup pad requires a personality function to be specified, so
166
- // we do that here explicitly (happens implicitly below through
167
- // creation of the landingpad instruction). We then create a
168
- // cleanuppad instruction which has no filters to run cleanup on all
169
- // exceptions.
170
- pad_bcx. set_personality_fn ( llpersonality) ;
171
- let llretval = pad_bcx. cleanup_pad ( None , & [ ] ) ;
172
- resume_bcx. cleanup_ret ( resume_bcx. cleanup_pad ( None , & [ ] ) , None ) ;
173
- UnwindKind :: CleanupPad ( llretval)
174
- } else {
175
- // The landing pad return type (the type being propagated). Not sure
176
- // what this represents but it's determined by the personality
177
- // function and this is what the EH proposal example uses.
178
- let llretty = Type :: struct_ ( fcx. ccx , & [ Type :: i8p ( fcx. ccx ) , Type :: i32 ( fcx. ccx ) ] , false ) ;
179
-
180
- // The only landing pad clause will be 'cleanup'
181
- let llretval = pad_bcx. landing_pad ( llretty, llpersonality, 1 , pad_bcx. fcx ( ) . llfn ) ;
182
-
183
- // The landing pad block is a cleanup
184
- pad_bcx. set_cleanup ( llretval) ;
185
-
186
- let addr = pad_bcx. fcx ( ) . alloca ( common:: val_ty ( llretval) , "" ) ;
187
- Lifetime :: Start . call ( & pad_bcx, addr) ;
188
- pad_bcx. store ( llretval, addr) ;
189
- let lp = resume_bcx. load ( addr) ;
190
- Lifetime :: End . call ( & resume_bcx, addr) ;
191
- if !resume_bcx. sess ( ) . target . target . options . custom_unwind_resume {
192
- resume_bcx. resume ( lp) ;
193
- } else {
194
- let exc_ptr = resume_bcx. extract_value ( lp, 0 ) ;
195
- resume_bcx. call ( fcx. eh_unwind_resume ( ) . reify ( fcx. ccx ) , & [ exc_ptr] , None ) ;
196
- }
197
- UnwindKind :: LandingPad
198
- } ;
199
-
200
- let mut cleanup = fcx. build_new_block ( "clean_custom_" ) ;
201
-
202
- // Insert cleanup instructions into the cleanup block
203
- let funclet = match val {
204
- UnwindKind :: CleanupPad ( _) => Some ( Funclet :: new ( cleanup. cleanup_pad ( None , & [ ] ) ) ) ,
205
- UnwindKind :: LandingPad => None ,
206
- } ;
207
- drop_val. trans ( funclet. as_ref ( ) , & cleanup) ;
208
-
209
- // Insert instruction into cleanup block to branch to the exit
210
- val. branch ( & mut cleanup, resume_bcx. llbb ( ) ) ;
211
-
212
- // Branch into the cleanup block
213
- val. branch ( & mut pad_bcx, cleanup. llbb ( ) ) ;
214
-
215
- return pad_bcx. llbb ( ) ;
216
- }
217
206
}
0 commit comments