Add the no-builtins attribute to functions when no_builtins is applied at the crate level.

When `no_builtins` is applied at the crate level, we should add the
`no-builtins` attribute to each function to ensure it takes effect in LTO.
This commit is contained in:
DianQK 2023-07-18 22:15:47 +08:00
parent f0580df0d5
commit cc08749df2
No known key found for this signature in database
GPG Key ID: 46BDB1AC96C48912
8 changed files with 68 additions and 1 deletions

View File

@ -335,6 +335,10 @@ pub fn from_fn_attrs<'ll, 'tcx>(
to_add.extend(probestack_attr(cx));
to_add.extend(stackprotector_attr(cx));
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_BUILTINS) {
to_add.push(llvm::CreateAttrString(cx.llcx, "no-builtins"));
}
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) {
to_add.push(AttributeKind::Cold.create_attr(cx.llcx));
}

View File

@ -1,4 +1,4 @@
use rustc_ast::{ast, MetaItemKind, NestedMetaItem};
use rustc_ast::{ast, attr, MetaItemKind, NestedMetaItem};
use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
use rustc_errors::struct_span_err;
use rustc_hir as hir;
@ -60,6 +60,14 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
}
// When `no_builtins` is applied at the crate level, we should add the
// `no-builtins` attribute to each function to ensure it takes effect in LTO.
let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
let no_builtins = attr::contains_name(crate_attrs, sym::no_builtins);
if no_builtins {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_BUILTINS;
}
let supported_target_features = tcx.supported_target_features(LOCAL_CRATE);
let mut inline_span = None;

View File

@ -100,6 +100,8 @@ bitflags! {
const REALLOCATOR = 1 << 18;
/// `#[rustc_allocator_zeroed]`: a hint to LLVM that the function only allocates zeroed memory.
const ALLOCATOR_ZEROED = 1 << 19;
/// `#[no_builtins]`: indicates that disable implicit builtin knowledge of functions for the function.
const NO_BUILTINS = 1 << 20;
}
}

View File

@ -0,0 +1,24 @@
// compile-flags: -C opt-level=1
#![no_builtins]
#![crate_type = "lib"]
// CHECK: define
// CHECK-SAME: @__aeabi_memcpy
// CHECK-SAME: #0
#[no_mangle]
pub unsafe extern "C" fn __aeabi_memcpy(dest: *mut u8, src: *const u8, size: usize) {
// CHECK: call
// CHECK-SAME: @memcpy(
memcpy(dest, src, size);
}
// CHECK: declare
// CHECK-SAME: @memcpy
// CHECK-SAME: #0
extern "C" {
pub fn memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8;
}
// CHECK: attributes #0
// CHECK-SAME: "no-builtins"

View File

@ -0,0 +1,9 @@
include ../tools.mk
# We want to check if `no-builtins` is also added to the function declarations in the used crate.
all:
$(RUSTC) no_builtins.rs --emit=link
$(RUSTC) main.rs --emit=llvm-ir
cat "$(TMPDIR)"/main.ll | "$(LLVM_FILECHECK)" filecheck.main.txt

View File

@ -0,0 +1,5 @@
CHECK: declare void @foo()
CHECK-SAME: #[[ATTR_3:[0-9]+]]
CHECK: attributes #[[ATTR_3]]
CHECK-SAME: no-builtins

View File

@ -0,0 +1,10 @@
extern crate no_builtins;
#[no_mangle]
fn call_foo() {
no_builtins::foo();
}
fn main() {
call_foo();
}

View File

@ -0,0 +1,5 @@
#![crate_type = "lib"]
#![no_builtins]
#[no_mangle]
pub fn foo() {}