@@ -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;
@@ -310,6 +311,39 @@ fn process_builtin_attrs(
310311 AttributeKind :: ObjcSelector { methname, .. } => {
311312 codegen_fn_attrs. objc_selector = Some ( * methname) ;
312313 }
314+ AttributeKind :: EiiImpls ( impls) => {
315+ for i in impls {
316+ let extern_item = find_attr ! (
317+ tcx. get_all_attrs( i. eii_macro) ,
318+ AttributeKind :: EiiExternTarget ( target) => target. eii_extern_target
319+ )
320+ . expect ( "eii should have declaration macro with extern target attribute" ) ;
321+
322+ let symbol_name = tcx. symbol_name ( Instance :: mono ( tcx, extern_item) ) ;
323+
324+ // this is to prevent a bug where a single crate defines both the default and explicit implementation
325+ // for an EII. In that case, both of them may be part of the same final object file. I'm not 100% sure
326+ // what happens, either rustc deduplicates the symbol or llvm, or it's random/order-dependent.
327+ // However, the fact that the default one of has weak linkage isn't considered and you sometimes get that
328+ // the default implementation is used while an explicit implementation is given.
329+ if
330+ // if this is a default impl
331+ i. is_default
332+ // iterate over all implementations *in the current crate*
333+ // (this is ok since we generate codegen fn attrs in the local crate)
334+ // if any of them is *not default* then don't emit the alias.
335+ && tcx. externally_implementable_items ( LOCAL_CRATE ) . get ( & i. eii_macro ) . expect ( "at least one" ) . 1 . iter ( ) . any ( |( _, imp) | !imp. is_default )
336+ {
337+ continue ;
338+ }
339+
340+ codegen_fn_attrs. foreign_item_symbol_aliases . push ( (
341+ Symbol :: intern ( symbol_name. name ) ,
342+ if i. is_default { Linkage :: LinkOnceAny } else { Linkage :: External } ,
343+ Visibility :: Default ,
344+ ) ) ;
345+ }
346+ }
313347 _ => { }
314348 }
315349 }
0 commit comments