test #[naked] with #[link_section = "..."] on windows

This commit is contained in:
Folkert de Vries
2026-03-30 18:03:19 +02:00
parent 5a0d572cd1
commit 72b6825828
4 changed files with 96 additions and 30 deletions
@@ -141,8 +141,14 @@ fn prefix_and_suffix<'tcx>(
let attrs = tcx.codegen_instance_attrs(instance.def);
let link_section = attrs.link_section.map(|symbol| symbol.as_str().to_string());
// If no alignment is specified, an alignment of 4 bytes is used.
let align_bytes = attrs.alignment.map(|a| a.bytes()).unwrap_or(4);
// Pick a default alignment when the alignment is not explicitly specified.
let align_bytes = match attrs.alignment {
Some(align) => align.bytes(),
None => match asm_binary_format {
BinaryFormat::Coff => 16,
_ => 4,
},
};
// In particular, `.arm` can also be written `.code 32` and `.thumb` as `.code 16`.
let (arch_prefix, arch_suffix) = if is_arm {
@@ -267,19 +273,18 @@ fn prefix_and_suffix<'tcx>(
}
}
BinaryFormat::Coff => {
let section = link_section.unwrap_or_else(|| format!(".text.{asm_name}"));
writeln!(begin, ".pushsection {},\"xr\"", section).unwrap();
writeln!(begin, ".balign {align_bytes}").unwrap();
write_linkage(&mut begin).unwrap();
writeln!(begin, ".def {asm_name}").unwrap();
writeln!(begin, ".scl 2").unwrap();
writeln!(begin, ".type 32").unwrap();
writeln!(begin, ".endef").unwrap();
let section = link_section.unwrap_or_else(|| format!(".text.{asm_name}"));
writeln!(begin, ".pushsection {},\"xr\"", section).unwrap();
write_linkage(&mut begin).unwrap();
writeln!(begin, ".balign {align_bytes}").unwrap();
writeln!(begin, "{asm_name}:").unwrap();
writeln!(end).unwrap();
writeln!(end, ".Lfunc_end_{asm_name}:").unwrap();
writeln!(end, ".popsection").unwrap();
if !arch_suffix.is_empty() {
writeln!(end, "{}", arch_suffix).unwrap();
}
@@ -0,0 +1,49 @@
//@ revisions: windows-x86-gnu windows-x86-msvc
//@ add-minicore
//@ assembly-output: emit-asm
//
//@[windows-x86-gnu] compile-flags: --target x86_64-pc-windows-gnu
//@[windows-x86-gnu] needs-llvm-components: x86
//
//@[windows-x86-msvc] compile-flags: --target x86_64-pc-windows-msvc
//@[windows-x86-msvc] needs-llvm-components: x86
#![crate_type = "lib"]
#![feature(no_core)]
#![no_core]
// Tests that naked and non-naked functions emit the same directives when the function uses
// `#[link_section = "..."]`.
extern crate minicore;
use minicore::*;
#[unsafe(naked)]
#[unsafe(no_mangle)]
#[unsafe(link_section = "naked")]
extern "C" fn naked_ret() {
// CHECK: .def naked_ret;
// CHECK-NEXT: .scl 2;
// CHECK-NEXT: .type 32;
// CHECK-NEXT: .endef
// CHECK-NEXT: .section naked,"xr"
// CHECK-NEXT: .globl naked_ret
// CHECK-NEXT: .p2align 4
// CHECK-NEXT: naked_ret:
// CHECK-NEXT: retq
naked_asm!("ret")
}
#[unsafe(no_mangle)]
#[unsafe(link_section = "regular")]
extern "C" fn regular_ret() {
// CHECK: .def regular_ret;
// CHECK-NEXT: .scl 2;
// CHECK-NEXT: .type 32;
// CHECK-NEXT: .endef
// CHECK-NEXT: .section regular,"xr"
// CHECK-NEXT: .globl regular_ret
// CHECK-NEXT: .p2align 4
// CHECK-NEXT: regular_ret:
// CHECK-NEXT: retq
}
+6 -6
View File
@@ -19,11 +19,11 @@ fn test(x: u64) {
foo.trait_method();
}
// CHECK: .balign 4
// CHECK: .balign
// CHECK: add rax, 1
// CHECK: add rax, 42
// CHECK: .balign 4
// CHECK: .balign
// CHECK: add rax, 2
// CHECK: add rax, 42
@@ -52,7 +52,7 @@ fn invert(self) -> Self {
}
}
// CHECK: .balign 4
// CHECK: .balign
// CHECK-LABEL: generic_function:
// CHECK: call
// CHECK: ret
@@ -71,7 +71,7 @@ pub extern "C" fn generic_function<T: Invert>(x: i64) -> i64 {
#[repr(transparent)]
struct Foo(u64);
// CHECK: .balign 4
// CHECK: .balign
// CHECK-LABEL: method:
// CHECK: mov rax, rdi
@@ -83,7 +83,7 @@ extern "C" fn method(self) -> u64 {
}
}
// CHECK: .balign 4
// CHECK: .balign
// CHECK-LABEL: trait_method:
// CHECK: mov rax, rdi
@@ -99,7 +99,7 @@ extern "C" fn trait_method(self) -> u64 {
}
}
// CHECK: .balign 4
// CHECK: .balign
// CHECK-LABEL: naked_with_args_and_return:
// CHECK: lea rax, [rdi + rsi]
+28 -16
View File
@@ -19,17 +19,15 @@
extern crate minicore;
use minicore::*;
// linux,win: .intel_syntax
// linux,win_x86,win_i686: .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
// thumb: .pushsection .text.naked_empty,\22ax\22, %progbits
//
// CHECK: .balign 4
// linux, macos, thumb: .balign 4
//
// linux,win,thumb: .globl naked_empty
// linux,thumb: .globl naked_empty
// macos: .globl _naked_empty
//
// CHECK-NOT: .private_extern
@@ -44,20 +42,28 @@
// win_x86,win_i686: .type 32
// win_x86,win_i686: .endef
//
// win_x86: .pushsection .text.naked_empty,\22xr\22
// win_i686: .pushsection .text._naked_empty,\22xr\22
//
// win_x86: .globl naked_empty
// win_i686: .globl _naked_empty
//
// win_x86,win_i686: .balign 16
//
// thumb: .type naked_empty, %function
// thumb: .thumb
// thumb: .thumb_func
//
// CHECK-LABEL: naked_empty:
//
// linux,macos,win: ret
// linux,macos,win_x86,win_x86: ret
// thumb: bx lr
//
// CHECK: .popsection
// linux,macos,thumb: .popsection
//
// thumb: .thumb
//
// linux,win: .att_syntax
// linux,win_x86,win_i686: .att_syntax
#[no_mangle]
#[unsafe(naked)]
@@ -72,17 +78,15 @@ pub extern "C" fn naked_empty() {
}
}
// linux,win: .intel_syntax
// linux,win_x86,win_i686: .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
// thumb: .pushsection .text.naked_with_args_and_return,\22ax\22, %progbits
//
// CHECK: .balign 4
// linux, macos, thumb: .balign 4
//
// linux,win,thumb: .globl naked_with_args_and_return
// linux,thumb: .globl naked_with_args_and_return
// macos: .globl _naked_with_args_and_return
//
// CHECK-NOT: .private_extern
@@ -97,6 +101,14 @@ pub extern "C" fn naked_empty() {
// win_x86,win_i686: .type 32
// win_x86,win_i686: .endef
//
// win_x86: .pushsection .text.naked_with_args_and_return,\22xr\22
// win_i686: .pushsection .text._naked_with_args_and_return,\22xr\22
//
// win_x86: .globl naked_with_args_and_return
// win_i686: .globl _naked_with_args_and_return
//
// win_x86,win_i686: .balign 16
//
// thumb: .type naked_with_args_and_return, %function
// thumb: .thumb
// thumb: .thumb_func
@@ -107,14 +119,14 @@ pub extern "C" fn naked_empty() {
// macos: add x0, x0, x1
// thumb: adds r0, r0, r1
//
// linux,macos,win: ret
// linux,macos,win_x86,win_i686: ret
// thumb: bx lr
//
// CHECK: .popsection
// linux,macos,thumb: .popsection
//
// thumb: .thumb
//
// linux,win: .att_syntax
// linux,win_x86,win_i686: .att_syntax
#[no_mangle]
#[unsafe(naked)]