@@ -14,8 +14,8 @@ use crate::context::CodegenCx;
14
14
use crate :: errors:: { MissingFeatures , SanitizerMemtagRequiresMte , TargetFeatureDisableOrEnable } ;
15
15
use crate :: llvm:: AttributePlace :: Function ;
16
16
use crate :: llvm:: { self , AllocKindFlags , Attribute , AttributeKind , AttributePlace , MemoryEffects } ;
17
+ use crate :: llvm_util;
17
18
use crate :: value:: Value ;
18
- use crate :: { attributes, llvm_util} ;
19
19
20
20
pub ( crate ) fn apply_to_llfn ( llfn : & Value , idx : AttributePlace , attrs : & [ & Attribute ] ) {
21
21
if !attrs. is_empty ( ) {
@@ -324,13 +324,18 @@ fn create_alloc_family_attr(llcx: &llvm::Context) -> &llvm::Attribute {
324
324
llvm:: CreateAttrStringValue ( llcx, "alloc-family" , "__rust_alloc" )
325
325
}
326
326
327
- /// Helper for `FnAbi::apply_attrs_llfn `:
327
+ /// Helper for `FnAbi::apply_attrs_* `:
328
328
/// Composite function which sets LLVM attributes for function depending on its AST (`#[attribute]`)
329
329
/// attributes.
330
+ ///
331
+ /// `apply_attrs` is called to apply the attributes, so this can be used both for declarations and
332
+ /// calls. However, some things are not represented as attributes and can only be set on
333
+ /// declarations, so `declare_llfn` should be `Some` if this is a declaration.
330
334
pub ( crate ) fn llfn_attrs_from_instance < ' ll , ' tcx > (
331
335
cx : & CodegenCx < ' ll , ' tcx > ,
332
- llfn : & ' ll Value ,
333
336
instance : ty:: Instance < ' tcx > ,
337
+ declare_llfn : Option < & ' ll Value > ,
338
+ apply_attrs : impl Fn ( AttributePlace , & [ & Attribute ] ) ,
334
339
) {
335
340
let codegen_fn_attrs = cx. tcx . codegen_fn_attrs ( instance. def_id ( ) ) ;
336
341
@@ -440,7 +445,7 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
440
445
to_add. push ( create_alloc_family_attr ( cx. llcx ) ) ;
441
446
// apply to argument place instead of function
442
447
let alloc_align = AttributeKind :: AllocAlign . create_attr ( cx. llcx ) ;
443
- attributes :: apply_to_llfn ( llfn , AttributePlace :: Argument ( 1 ) , & [ alloc_align] ) ;
448
+ apply_attrs ( AttributePlace :: Argument ( 1 ) , & [ alloc_align] ) ;
444
449
to_add. push ( llvm:: CreateAllocSizeAttr ( cx. llcx , 0 ) ) ;
445
450
let mut flags = AllocKindFlags :: Alloc | AllocKindFlags :: Aligned ;
446
451
if codegen_fn_attrs. flags . contains ( CodegenFnAttrFlags :: ALLOCATOR ) {
@@ -451,7 +456,7 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
451
456
to_add. push ( llvm:: CreateAllocKindAttr ( cx. llcx , flags) ) ;
452
457
// apply to return place instead of function (unlike all other attributes applied in this function)
453
458
let no_alias = AttributeKind :: NoAlias . create_attr ( cx. llcx ) ;
454
- attributes :: apply_to_llfn ( llfn , AttributePlace :: ReturnValue , & [ no_alias] ) ;
459
+ apply_attrs ( AttributePlace :: ReturnValue , & [ no_alias] ) ;
455
460
}
456
461
if codegen_fn_attrs. flags . contains ( CodegenFnAttrFlags :: REALLOCATOR ) {
457
462
to_add. push ( create_alloc_family_attr ( cx. llcx ) ) ;
@@ -461,26 +466,28 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
461
466
) ) ;
462
467
// applies to argument place instead of function place
463
468
let allocated_pointer = AttributeKind :: AllocatedPointer . create_attr ( cx. llcx ) ;
464
- attributes :: apply_to_llfn ( llfn , AttributePlace :: Argument ( 0 ) , & [ allocated_pointer] ) ;
469
+ apply_attrs ( AttributePlace :: Argument ( 0 ) , & [ allocated_pointer] ) ;
465
470
// apply to argument place instead of function
466
471
let alloc_align = AttributeKind :: AllocAlign . create_attr ( cx. llcx ) ;
467
- attributes :: apply_to_llfn ( llfn , AttributePlace :: Argument ( 2 ) , & [ alloc_align] ) ;
472
+ apply_attrs ( AttributePlace :: Argument ( 2 ) , & [ alloc_align] ) ;
468
473
to_add. push ( llvm:: CreateAllocSizeAttr ( cx. llcx , 3 ) ) ;
469
474
let no_alias = AttributeKind :: NoAlias . create_attr ( cx. llcx ) ;
470
- attributes :: apply_to_llfn ( llfn , AttributePlace :: ReturnValue , & [ no_alias] ) ;
475
+ apply_attrs ( AttributePlace :: ReturnValue , & [ no_alias] ) ;
471
476
}
472
477
if codegen_fn_attrs. flags . contains ( CodegenFnAttrFlags :: DEALLOCATOR ) {
473
478
to_add. push ( create_alloc_family_attr ( cx. llcx ) ) ;
474
479
to_add. push ( llvm:: CreateAllocKindAttr ( cx. llcx , AllocKindFlags :: Free ) ) ;
475
480
// applies to argument place instead of function place
476
481
let allocated_pointer = AttributeKind :: AllocatedPointer . create_attr ( cx. llcx ) ;
477
- attributes :: apply_to_llfn ( llfn , AttributePlace :: Argument ( 0 ) , & [ allocated_pointer] ) ;
482
+ apply_attrs ( AttributePlace :: Argument ( 0 ) , & [ allocated_pointer] ) ;
478
483
}
479
484
if codegen_fn_attrs. flags . contains ( CodegenFnAttrFlags :: CMSE_NONSECURE_ENTRY ) {
480
485
to_add. push ( llvm:: CreateAttrString ( cx. llcx , "cmse_nonsecure_entry" ) ) ;
481
486
}
482
487
if let Some ( align) = codegen_fn_attrs. alignment {
483
- llvm:: set_alignment ( llfn, align) ;
488
+ if let Some ( llfn) = declare_llfn {
489
+ llvm:: set_alignment ( llfn, align) ;
490
+ }
484
491
}
485
492
if let Some ( backchain) = backchain_attr ( cx) {
486
493
to_add. push ( backchain) ;
@@ -499,24 +506,27 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
499
506
let function_features =
500
507
codegen_fn_attrs. target_features . iter ( ) . map ( |f| f. name . as_str ( ) ) . collect :: < Vec < & str > > ( ) ;
501
508
502
- if let Some ( f) = llvm_util:: check_tied_features (
503
- cx. tcx . sess ,
504
- & function_features. iter ( ) . map ( |f| ( * f, true ) ) . collect ( ) ,
505
- ) {
506
- let span = cx
507
- . tcx
508
- . get_attrs ( instance. def_id ( ) , sym:: target_feature)
509
- . next ( )
510
- . map_or_else ( || cx. tcx . def_span ( instance. def_id ( ) ) , |a| a. span ) ;
511
- cx. tcx
512
- . dcx ( )
513
- . create_err ( TargetFeatureDisableOrEnable {
514
- features : f,
515
- span : Some ( span) ,
516
- missing_features : Some ( MissingFeatures ) ,
517
- } )
518
- . emit ( ) ;
519
- return ;
509
+ // HACK: Avoid emitting the lint twice.
510
+ if declare_llfn. is_some ( ) {
511
+ if let Some ( f) = llvm_util:: check_tied_features (
512
+ cx. tcx . sess ,
513
+ & function_features. iter ( ) . map ( |f| ( * f, true ) ) . collect ( ) ,
514
+ ) {
515
+ let span = cx
516
+ . tcx
517
+ . get_attrs ( instance. def_id ( ) , sym:: target_feature)
518
+ . next ( )
519
+ . map_or_else ( || cx. tcx . def_span ( instance. def_id ( ) ) , |a| a. span ) ;
520
+ cx. tcx
521
+ . dcx ( )
522
+ . create_err ( TargetFeatureDisableOrEnable {
523
+ features : f,
524
+ span : Some ( span) ,
525
+ missing_features : Some ( MissingFeatures ) ,
526
+ } )
527
+ . emit ( ) ;
528
+ return ;
529
+ }
520
530
}
521
531
522
532
let function_features = function_features
@@ -558,7 +568,7 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
558
568
to_add. push ( llvm:: CreateAttrStringValue ( cx. llcx , "target-features" , & target_features) ) ;
559
569
}
560
570
561
- attributes :: apply_to_llfn ( llfn , Function , & to_add) ;
571
+ apply_attrs ( Function , & to_add) ;
562
572
}
563
573
564
574
fn wasm_import_module ( tcx : TyCtxt < ' _ > , id : DefId ) -> Option < & String > {
0 commit comments