@@ -3,19 +3,20 @@ use std::str::FromStr;
33use rustc_abi:: { Align , ExternAbi } ;
44use rustc_ast:: expand:: autodiff_attrs:: { AutoDiffAttrs , DiffActivity , DiffMode } ;
55use 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 } ;
77use rustc_hir:: def:: DefKind ;
88use rustc_hir:: def_id:: { DefId , LOCAL_CRATE , LocalDefId } ;
99use rustc_hir:: { self as hir, Attribute , LangItem , find_attr, lang_items} ;
1010use rustc_middle:: middle:: codegen_fn_attrs:: {
1111 CodegenFnAttrFlags , CodegenFnAttrs , PatchableFunctionEntry ,
1212} ;
13+ use rustc_middle:: mir:: mono:: Visibility ;
1314use rustc_middle:: query:: Providers ;
1415use rustc_middle:: span_bug;
15- use rustc_middle:: ty:: { self as ty, TyCtxt } ;
16+ use rustc_middle:: ty:: { self as ty, Instance , TyCtxt } ;
1617use rustc_session:: lint;
1718use rustc_session:: parse:: feature_err;
18- use rustc_span:: { Ident , Span , sym} ;
19+ use rustc_span:: { Ident , Span , Symbol , sym} ;
1920use rustc_target:: spec:: SanitizerSet ;
2021
2122use crate :: errors;
@@ -296,6 +297,39 @@ fn process_builtin_attrs(
296297 AttributeKind :: Sanitize { span, .. } => {
297298 interesting_spans. sanitize = Some ( * span) ;
298299 }
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+ }
299333 _ => { }
300334 }
301335 }
0 commit comments