diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs index e7239ebfecf63..a01ced20d0c90 100644 --- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs +++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs @@ -127,6 +127,8 @@ fn prefix_and_suffix<'tcx>( let is_arm = tcx.sess.target.arch == "arm"; let is_thumb = tcx.sess.unstable_target_features.contains(&sym::thumb_mode); + let function_sections = + tcx.sess.opts.unstable_opts.function_sections.unwrap_or(tcx.sess.target.function_sections); let attrs = tcx.codegen_instance_attrs(instance.def); let link_section = attrs.link_section.map(|symbol| symbol.as_str().to_string()); @@ -201,8 +203,6 @@ fn prefix_and_suffix<'tcx>( let mut end = String::new(); match asm_binary_format { BinaryFormat::Elf => { - let section = link_section.unwrap_or_else(|| format!(".text.{asm_name}")); - let progbits = match is_arm { true => "%progbits", false => "@progbits", @@ -213,7 +213,11 @@ fn prefix_and_suffix<'tcx>( false => "@function", }; - writeln!(begin, ".pushsection {section},\"ax\", {progbits}").unwrap(); + if let Some(section) = &link_section { + writeln!(begin, ".pushsection {section},\"ax\", {progbits}").unwrap(); + } else if function_sections { + writeln!(begin, ".pushsection .text.{asm_name},\"ax\", {progbits}").unwrap(); + } writeln!(begin, ".balign {align_bytes}").unwrap(); write_linkage(&mut begin).unwrap(); match item_data.visibility { @@ -232,14 +236,18 @@ fn prefix_and_suffix<'tcx>( // pattern match on assembly generated by LLVM. writeln!(end, ".Lfunc_end_{asm_name}:").unwrap(); writeln!(end, ".size {asm_name}, . - {asm_name}").unwrap(); - writeln!(end, ".popsection").unwrap(); + if link_section.is_some() || function_sections { + writeln!(end, ".popsection").unwrap(); + } if !arch_suffix.is_empty() { writeln!(end, "{}", arch_suffix).unwrap(); } } BinaryFormat::MachO => { - let section = link_section.unwrap_or_else(|| "__TEXT,__text".to_string()); - writeln!(begin, ".pushsection {},regular,pure_instructions", section).unwrap(); + // NOTE: LLVM ignores `-Zfunction-sections` on macos. + if let Some(section) = &link_section { + writeln!(begin, ".pushsection {section},regular,pure_instructions").unwrap(); + } writeln!(begin, ".balign {align_bytes}").unwrap(); write_linkage(&mut begin).unwrap(); match item_data.visibility { @@ -250,14 +258,19 @@ fn prefix_and_suffix<'tcx>( writeln!(end).unwrap(); writeln!(end, ".Lfunc_end_{asm_name}:").unwrap(); - writeln!(end, ".popsection").unwrap(); + if link_section.is_some() { + writeln!(end, ".popsection").unwrap(); + } if !arch_suffix.is_empty() { writeln!(end, "{}", arch_suffix).unwrap(); } } BinaryFormat::Coff => { - let section = link_section.unwrap_or_else(|| format!(".text.{asm_name}")); - writeln!(begin, ".pushsection {},\"xr\"", section).unwrap(); + if let Some(section) = &link_section { + writeln!(begin, ".pushsection {section},\"xr\"").unwrap() + } else if function_sections { + writeln!(begin, ".pushsection .text${asm_name},\"xr\"").unwrap() + } writeln!(begin, ".balign {align_bytes}").unwrap(); write_linkage(&mut begin).unwrap(); writeln!(begin, ".def {asm_name}").unwrap(); @@ -268,7 +281,9 @@ fn prefix_and_suffix<'tcx>( writeln!(end).unwrap(); writeln!(end, ".Lfunc_end_{asm_name}:").unwrap(); - writeln!(end, ".popsection").unwrap(); + if link_section.is_some() || function_sections { + writeln!(end, ".popsection").unwrap(); + } if !arch_suffix.is_empty() { writeln!(end, "{}", arch_suffix).unwrap(); } diff --git a/tests/codegen-llvm/naked-fn/naked-functions.rs b/tests/codegen-llvm/naked-fn/naked-functions.rs index 8a7ee4b4de563..6d0691bfbf969 100644 --- a/tests/codegen-llvm/naked-fn/naked-functions.rs +++ b/tests/codegen-llvm/naked-fn/naked-functions.rs @@ -1,12 +1,14 @@ //@ add-core-stubs -//@ revisions: linux win_x86 win_i686 macos thumb +//@ revisions: linux win_x86_msvc win_x86_gnu win_i686_gnu macos thumb // //@[linux] compile-flags: --target x86_64-unknown-linux-gnu //@[linux] needs-llvm-components: x86 -//@[win_x86] compile-flags: --target x86_64-pc-windows-gnu -//@[win_x86] needs-llvm-components: x86 -//@[win_i686] compile-flags: --target i686-pc-windows-gnu -//@[win_i686] needs-llvm-components: x86 +//@[win_x86_gnu] compile-flags: --target x86_64-pc-windows-gnu +//@[win_x86_gnu] needs-llvm-components: x86 +//@[win_x86_msvc] compile-flags: --target x86_64-pc-windows-msvc +//@[win_x86_msvc] needs-llvm-components: x86 +//@[win_i686_gnu] compile-flags: --target i686-pc-windows-gnu +//@[win_i686_gnu] needs-llvm-components: x86 //@[macos] compile-flags: --target aarch64-apple-darwin //@[macos] needs-llvm-components: aarch64 //@[thumb] compile-flags: --target thumbv7em-none-eabi @@ -22,9 +24,10 @@ use minicore::*; // linux,win: .intel_syntax // // linux: .pushsection .text.naked_empty,\22ax\22, @progbits -// macos: .pushsection __TEXT,__text,regular,pure_instructions -// win_x86: .pushsection .text.naked_empty,\22xr\22 -// win_i686: .pushsection .text._naked_empty,\22xr\22 +// macos-NOT: .pushsection +// win_x86_msvc: .pushsection .text$naked_empty,\22xr\22 +// win_x86_gnu-NOT: .pushsection +// win_i686_gnu-NOT: .pushsection // thumb: .pushsection .text.naked_empty,\22ax\22, %progbits // // CHECK: .balign 4 @@ -37,12 +40,12 @@ use minicore::*; // // linux: .type naked_empty, @function // -// win_x86: .def naked_empty -// win_i686: .def _naked_empty +// win_x86_msvc,win_x86_gnu: .def naked_empty +// win_i686_gnu: .def _naked_empty // -// win_x86,win_i686: .scl 2 -// win_x86,win_i686: .type 32 -// win_x86,win_i686: .endef +// win_x86_msvc,win_x86_gnu,win_i686_gnu: .scl 2 +// win_x86_msvc,win_x86_gnu,win_i686_gnu: .type 32 +// win_x86_msvc,win_x86_gnu,win_i686_gnu: .endef // // thumb: .type naked_empty, %function // thumb: .thumb @@ -53,7 +56,8 @@ use minicore::*; // linux,macos,win: ret // thumb: bx lr // -// CHECK: .popsection +// linux,windows,win_x86_msvc,thumb: .popsection +// win_x86_gnu-NOT,win_i686_gnu-NOT: .popsection // // thumb: .thumb // @@ -72,9 +76,10 @@ pub extern "C" fn naked_empty() { // linux,win: .intel_syntax // // linux: .pushsection .text.naked_with_args_and_return,\22ax\22, @progbits -// macos: .pushsection __TEXT,__text,regular,pure_instructions -// win_x86: .pushsection .text.naked_with_args_and_return,\22xr\22 -// win_i686: .pushsection .text._naked_with_args_and_return,\22xr\22 +// macos-NOT: .pushsection +// win_x86_msvc: .pushsection .text$naked_with_args_and_return,\22xr\22 +// win_x86_gnu-NOT: .pushsection +// win_i686_gnu-NOT: .pushsection // thumb: .pushsection .text.naked_with_args_and_return,\22ax\22, %progbits // // CHECK: .balign 4 @@ -87,12 +92,12 @@ pub extern "C" fn naked_empty() { // // linux: .type naked_with_args_and_return, @function // -// win_x86: .def naked_with_args_and_return -// win_i686: .def _naked_with_args_and_return +// win_x86_msvc,win_x86_gnu: .def naked_with_args_and_return +// win_i686_gnu: .def _naked_with_args_and_return // -// win_x86,win_i686: .scl 2 -// win_x86,win_i686: .type 32 -// win_x86,win_i686: .endef +// win_x86_msvc,win_x86_gnu,win_i686_gnu: .scl 2 +// win_x86_msvc,win_x86_gnu,win_i686_gnu: .type 32 +// win_x86_msvc,win_x86_gnu,win_i686_gnu: .endef // // thumb: .type naked_with_args_and_return, %function // thumb: .thumb @@ -100,14 +105,15 @@ pub extern "C" fn naked_empty() { // // CHECK-LABEL: naked_with_args_and_return: // -// linux, win_x86,win_i686: lea rax, [rdi + rsi] +// linux,win_x86_msvc,win_x86_gnu,win_i686_gnu: lea rax, [rdi + rsi] // macos: add x0, x0, x1 // thumb: adds r0, r0, r1 // // linux,macos,win: ret // thumb: bx lr // -// CHECK: .popsection +// linux,windows,win_x86_msvc,thumb: .popsection +// win_x86_gnu-NOT,win_i686_gnu-NOT: .popsection // // thumb: .thumb // @@ -134,7 +140,7 @@ pub extern "C" fn naked_with_args_and_return(a: isize, b: isize) -> isize { // linux: .pushsection .text.some_different_name,\22ax\22, @progbits // macos: .pushsection .text.some_different_name,regular,pure_instructions -// win_x86,win_i686: .pushsection .text.some_different_name,\22xr\22 +// win_x86_msvc,win_x86_gnu,win_i686_gnu: .pushsection .text.some_different_name,\22xr\22 // thumb: .pushsection .text.some_different_name,\22ax\22, %progbits // CHECK-LABEL: test_link_section: #[no_mangle] @@ -148,15 +154,15 @@ pub extern "C" fn test_link_section() { naked_asm!("bx lr"); } -// win_x86: .def fastcall_cc -// win_i686: .def @fastcall_cc@4 +// win_x86_msvc,win_x86_gnu: .def fastcall_cc +// win_i686_gnu: .def @fastcall_cc@4 // -// win_x86,win_i686: .scl 2 -// win_x86,win_i686: .type 32 -// win_x86,win_i686: .endef +// win_x86_msvc,win_x86_gnu,win_i686_gnu: .scl 2 +// win_x86_msvc,win_x86_gnu,win_i686_gnu: .type 32 +// win_x86_msvc,win_x86_gnu,win_i686_gnu: .endef // -// win_x86-LABEL: fastcall_cc: -// win_i686-LABEL: @fastcall_cc@4: +// win_x86_msvc-LABEL,win_x86_gnu-LABEL: fastcall_cc: +// win_i686_gnu-LABEL: @fastcall_cc@4: #[cfg(target_os = "windows")] #[no_mangle] #[unsafe(naked)] diff --git a/tests/run-make/naked-dead-code-elimination/main.rs b/tests/run-make/naked-dead-code-elimination/main.rs new file mode 100644 index 0000000000000..8f64acd5f00fa --- /dev/null +++ b/tests/run-make/naked-dead-code-elimination/main.rs @@ -0,0 +1,24 @@ +use std::arch::naked_asm; + +#[unsafe(naked)] +#[no_mangle] +extern "C" fn used() { + naked_asm!("ret") +} + +#[unsafe(naked)] +#[no_mangle] +extern "C" fn unused() { + naked_asm!("ret") +} + +#[unsafe(naked)] +#[link_section = "foobar"] +#[no_mangle] +extern "C" fn unused_link_section() { + naked_asm!("ret") +} + +fn main() { + used(); +} diff --git a/tests/run-make/naked-dead-code-elimination/rmake.rs b/tests/run-make/naked-dead-code-elimination/rmake.rs new file mode 100644 index 0000000000000..1e1256f55b0fa --- /dev/null +++ b/tests/run-make/naked-dead-code-elimination/rmake.rs @@ -0,0 +1,10 @@ +//@ needs-asm-support + +use run_make_support::symbols::object_contains_any_symbol; +use run_make_support::{bin_name, rustc}; + +fn main() { + rustc().input("main.rs").opt().run(); + let mut unused = vec!["unused", "unused_link_section"]; + assert!(!object_contains_any_symbol(bin_name("main"), &unused)); +}