@@ -3,19 +3,20 @@ use std::str::FromStr;
3
3
use rustc_abi:: { Align , ExternAbi } ;
4
4
use rustc_ast:: expand:: autodiff_attrs:: { AutoDiffAttrs , DiffActivity , DiffMode } ;
5
5
use rustc_ast:: { LitKind , MetaItem , MetaItemInner , attr} ;
6
- use rustc_hir:: attrs:: { AttributeKind , InlineAttr , InstructionSetAttr , UsedBy } ;
6
+ use rustc_hir:: attrs:: { AttributeKind , InlineAttr , InstructionSetAttr , Linkage , UsedBy } ;
7
7
use rustc_hir:: def:: DefKind ;
8
8
use rustc_hir:: def_id:: { DefId , LOCAL_CRATE , LocalDefId } ;
9
9
use rustc_hir:: { self as hir, Attribute , LangItem , find_attr, lang_items} ;
10
10
use rustc_middle:: middle:: codegen_fn_attrs:: {
11
11
CodegenFnAttrFlags , CodegenFnAttrs , PatchableFunctionEntry ,
12
12
} ;
13
+ use rustc_middle:: mir:: mono:: Visibility ;
13
14
use rustc_middle:: query:: Providers ;
14
15
use rustc_middle:: span_bug;
15
- use rustc_middle:: ty:: { self as ty, TyCtxt } ;
16
+ use rustc_middle:: ty:: { self as ty, Instance , TyCtxt } ;
16
17
use rustc_session:: lint;
17
18
use rustc_session:: parse:: feature_err;
18
- use rustc_span:: { Ident , Span , sym} ;
19
+ use rustc_span:: { Ident , Span , Symbol , sym} ;
19
20
use rustc_target:: spec:: SanitizerSet ;
20
21
21
22
use crate :: errors;
@@ -296,6 +297,39 @@ fn process_builtin_attrs(
296
297
AttributeKind :: Sanitize { span, .. } => {
297
298
interesting_spans. sanitize = Some ( * span) ;
298
299
}
300
+ AttributeKind :: EiiImpls ( impls) => {
301
+ for i in impls {
302
+ let extern_item = find_attr ! (
303
+ tcx. get_all_attrs( i. eii_macro) ,
304
+ AttributeKind :: EiiExternTarget ( target) => target. eii_extern_target
305
+ )
306
+ . expect ( "eii should have declaration macro with extern target attribute" ) ;
307
+
308
+ let symbol_name = tcx. symbol_name ( Instance :: mono ( tcx, extern_item) ) ;
309
+
310
+ // this is to prevent a bug where a single crate defines both the default and explicit implementation
311
+ // for an EII. In that case, both of them may be part of the same final object file. I'm not 100% sure
312
+ // what happens, either rustc deduplicates the symbol or llvm, or it's random/order-dependent.
313
+ // However, the fact that the default one of has weak linkage isn't considered and you sometimes get that
314
+ // the default implementation is used while an explicit implementation is given.
315
+ if
316
+ // if this is a default impl
317
+ i. is_default
318
+ // iterate over all implementations *in the current crate*
319
+ // (this is ok since we generate codegen fn attrs in the local crate)
320
+ // if any of them is *not default* then don't emit the alias.
321
+ && tcx. externally_implementable_items ( LOCAL_CRATE ) . get ( & i. eii_macro ) . expect ( "at least one" ) . 1 . iter ( ) . any ( |( _, imp) | !imp. is_default )
322
+ {
323
+ continue ;
324
+ }
325
+
326
+ codegen_fn_attrs. foreign_item_symbol_aliases . push ( (
327
+ Symbol :: intern ( symbol_name. name ) ,
328
+ if i. is_default { Linkage :: LinkOnceAny } else { Linkage :: External } ,
329
+ Visibility :: Default ,
330
+ ) ) ;
331
+ }
332
+ }
299
333
_ => { }
300
334
}
301
335
}
0 commit comments