@@ -3,19 +3,22 @@ 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 , RtsanSetting , UsedBy } ;
6+ use rustc_hir:: attrs:: {
7+ AttributeKind , InlineAttr , InstructionSetAttr , Linkage , RtsanSetting , UsedBy ,
8+ } ;
79use rustc_hir:: def:: DefKind ;
810use rustc_hir:: def_id:: { DefId , LOCAL_CRATE , LocalDefId } ;
911use rustc_hir:: { self as hir, Attribute , LangItem , find_attr, lang_items} ;
1012use rustc_middle:: middle:: codegen_fn_attrs:: {
1113 CodegenFnAttrFlags , CodegenFnAttrs , PatchableFunctionEntry , SanitizerFnAttrs ,
1214} ;
15+ use rustc_middle:: mir:: mono:: Visibility ;
1316use rustc_middle:: query:: Providers ;
1417use rustc_middle:: span_bug;
15- use rustc_middle:: ty:: { self as ty, TyCtxt } ;
18+ use rustc_middle:: ty:: { self as ty, Instance , TyCtxt } ;
1619use rustc_session:: lint;
1720use rustc_session:: parse:: feature_err;
18- use rustc_span:: { Ident , Span , sym} ;
21+ use rustc_span:: { Ident , Span , Symbol , sym} ;
1922use rustc_target:: spec:: Os ;
2023
2124use crate :: errors;
@@ -310,6 +313,39 @@ fn process_builtin_attrs(
310313 AttributeKind :: ObjcSelector { methname, .. } => {
311314 codegen_fn_attrs. objc_selector = Some ( * methname) ;
312315 }
316+ AttributeKind :: EiiImpls ( impls) => {
317+ for i in impls {
318+ let extern_item = find_attr ! (
319+ tcx. get_all_attrs( i. eii_macro) ,
320+ AttributeKind :: EiiExternTarget ( target) => target. eii_extern_target
321+ )
322+ . expect ( "eii should have declaration macro with extern target attribute" ) ;
323+
324+ let symbol_name = tcx. symbol_name ( Instance :: mono ( tcx, extern_item) ) ;
325+
326+ // this is to prevent a bug where a single crate defines both the default and explicit implementation
327+ // for an EII. In that case, both of them may be part of the same final object file. I'm not 100% sure
328+ // what happens, either rustc deduplicates the symbol or llvm, or it's random/order-dependent.
329+ // However, the fact that the default one of has weak linkage isn't considered and you sometimes get that
330+ // the default implementation is used while an explicit implementation is given.
331+ if
332+ // if this is a default impl
333+ i. is_default
334+ // iterate over all implementations *in the current crate*
335+ // (this is ok since we generate codegen fn attrs in the local crate)
336+ // if any of them is *not default* then don't emit the alias.
337+ && tcx. externally_implementable_items ( LOCAL_CRATE ) . get ( & i. eii_macro ) . expect ( "at least one" ) . 1 . iter ( ) . any ( |( _, imp) | !imp. is_default )
338+ {
339+ continue ;
340+ }
341+
342+ codegen_fn_attrs. foreign_item_symbol_aliases . push ( (
343+ Symbol :: intern ( symbol_name. name ) ,
344+ if i. is_default { Linkage :: LinkOnceAny } else { Linkage :: External } ,
345+ Visibility :: Default ,
346+ ) ) ;
347+ }
348+ }
313349 _ => { }
314350 }
315351 }
0 commit comments