@@ -181,6 +181,41 @@ fn get_or_create_closure_declaration<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
181
181
llfn
182
182
}
183
183
184
+ fn translating_closure_body_via_mir_will_fail ( ccx : & CrateContext ,
185
+ closure_def_id : DefId )
186
+ -> bool {
187
+ let default_to_mir = ccx. sess ( ) . opts . debugging_opts . orbit ;
188
+ let invert = if default_to_mir { "rustc_no_mir" } else { "rustc_mir" } ;
189
+ let use_mir = default_to_mir ^ ccx. tcx ( ) . has_attr ( closure_def_id, invert) ;
190
+
191
+ !use_mir
192
+ }
193
+
194
+ pub fn trans_closure_body_via_mir < ' a , ' tcx > ( ccx : & CrateContext < ' a , ' tcx > ,
195
+ closure_def_id : DefId ,
196
+ closure_substs : ty:: ClosureSubsts < ' tcx > ) {
197
+ use syntax:: ast:: DUMMY_NODE_ID ;
198
+ use syntax_pos:: DUMMY_SP ;
199
+ use syntax:: ptr:: P ;
200
+
201
+ trans_closure_expr ( Dest :: Ignore ( ccx) ,
202
+ & hir:: FnDecl {
203
+ inputs : P :: new ( ) ,
204
+ output : hir:: NoReturn ( DUMMY_SP ) ,
205
+ variadic : false
206
+ } ,
207
+ & hir:: Block {
208
+ stmts : P :: new ( ) ,
209
+ expr : None ,
210
+ id : DUMMY_NODE_ID ,
211
+ rules : hir:: DefaultBlock ,
212
+ span : DUMMY_SP
213
+ } ,
214
+ DUMMY_NODE_ID ,
215
+ closure_def_id,
216
+ closure_substs) ;
217
+ }
218
+
184
219
pub enum Dest < ' a , ' tcx : ' a > {
185
220
SaveIn ( Block < ' a , ' tcx > , ValueRef ) ,
186
221
Ignore ( & ' a CrateContext < ' a , ' tcx > )
@@ -213,8 +248,13 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
213
248
// If we have not done so yet, translate this closure's body
214
249
if !ccx. instances ( ) . borrow ( ) . contains_key ( & instance) {
215
250
let llfn = get_or_create_closure_declaration ( ccx, closure_def_id, closure_substs) ;
216
- llvm:: SetLinkage ( llfn, llvm:: WeakODRLinkage ) ;
217
- llvm:: SetUniqueComdat ( ccx. llmod ( ) , llfn) ;
251
+
252
+ if ccx. sess ( ) . target . target . options . allows_weak_linkage {
253
+ llvm:: SetLinkage ( llfn, llvm:: WeakODRLinkage ) ;
254
+ llvm:: SetUniqueComdat ( ccx. llmod ( ) , llfn) ;
255
+ } else {
256
+ llvm:: SetLinkage ( llfn, llvm:: InternalLinkage ) ;
257
+ }
218
258
219
259
// set an inline hint for all closures
220
260
attributes:: inline ( llfn, attributes:: InlineAttr :: Hint ) ;
@@ -296,6 +336,39 @@ pub fn trans_closure_method<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
296
336
// If this is a closure, redirect to it.
297
337
let llfn = get_or_create_closure_declaration ( ccx, closure_def_id, substs) ;
298
338
339
+ // If weak linkage is not allowed, we have to make sure that a local,
340
+ // private copy of the closure is available in this codegen unit
341
+ if !ccx. sess ( ) . target . target . options . allows_weak_linkage &&
342
+ !ccx. sess ( ) . opts . single_codegen_unit ( ) {
343
+
344
+ if let Some ( node_id) = ccx. tcx ( ) . map . as_local_node_id ( closure_def_id) {
345
+ // If the closure is defined in the local crate, we can always just
346
+ // translate it.
347
+ let ( decl, body) = match ccx. tcx ( ) . map . expect_expr ( node_id) . node {
348
+ hir:: ExprClosure ( _, ref decl, ref body, _) => ( decl, body) ,
349
+ _ => { unreachable ! ( ) }
350
+ } ;
351
+
352
+ trans_closure_expr ( Dest :: Ignore ( ccx) ,
353
+ decl,
354
+ body,
355
+ node_id,
356
+ closure_def_id,
357
+ substs) ;
358
+ } else {
359
+ // If the closure is defined in an upstream crate, we can only
360
+ // translate it if MIR-trans is active.
361
+
362
+ if translating_closure_body_via_mir_will_fail ( ccx, closure_def_id) {
363
+ ccx. sess ( ) . fatal ( "You have run into a known limitation of the \
364
+ MingW toolchain. Either compile with -Zorbit or \
365
+ with -Ccodegen-units=1 to work around it.") ;
366
+ }
367
+
368
+ trans_closure_body_via_mir ( ccx, closure_def_id, substs) ;
369
+ }
370
+ }
371
+
299
372
// If the closure is a Fn closure, but a FnOnce is needed (etc),
300
373
// then adapt the self type
301
374
let llfn_closure_kind = ccx. tcx ( ) . closure_kind ( closure_def_id) ;
0 commit comments