Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
};
Comment on lines +144 to +151
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this really matters but we may as well match LLVM


// In particular, `.arm` can also be written `.code 32` and `.thumb` as `.code 16`.
let (arch_prefix, arch_suffix) = if is_arm {
Expand Down Expand Up @@ -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();
Comment on lines -270 to +284
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This just got moved up so that .def comes before the .pushsection.

writeln!(begin, "{asm_name}:").unwrap();

writeln!(end).unwrap();
writeln!(end, ".Lfunc_end_{asm_name}:").unwrap();
writeln!(end, ".popsection").unwrap();
Comment on lines -281 to -282
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LLVM does not emit these, so then we should not need to either

if !arch_suffix.is_empty() {
writeln!(end, "{}", arch_suffix).unwrap();
}
Expand Down
49 changes: 49 additions & 0 deletions tests/assembly-llvm/naked-functions/link-section-windows.rs
Original file line number Diff line number Diff line change
@@ -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
}
12 changes: 6 additions & 6 deletions tests/codegen-llvm/naked-fn/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -52,7 +52,7 @@ impl Invert for i64 {
}
}

// CHECK: .balign 4
// CHECK: .balign
// CHECK-LABEL: generic_function:
// CHECK: call
// CHECK: ret
Expand All @@ -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

Expand All @@ -83,7 +83,7 @@ impl Foo {
}
}

// CHECK: .balign 4
// CHECK: .balign
// CHECK-LABEL: trait_method:
// CHECK: mov rax, rdi

Expand All @@ -99,7 +99,7 @@ impl Bar for Foo {
}
}

// CHECK: .balign 4
// CHECK: .balign
// CHECK-LABEL: naked_with_args_and_return:
// CHECK: lea rax, [rdi + rsi]

Expand Down
34 changes: 23 additions & 11 deletions tests/codegen-llvm/naked-fn/naked-functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,11 @@ use minicore::*;
//
// 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
Expand All @@ -44,16 +42,24 @@ use minicore::*;
// 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
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You probably meant i686 and x86 here.

// thumb: bx lr
//
// CHECK: .popsection
// linux,macos,thumb: .popsection
//
// thumb: .thumb
//
Expand All @@ -76,13 +82,11 @@ pub extern "C" fn naked_empty() {
//
// 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
Expand All @@ -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
Expand All @@ -110,7 +122,7 @@ pub extern "C" fn naked_empty() {
// linux,macos,win: ret
// thumb: bx lr
//
// CHECK: .popsection
// linux,macos,thumb: .popsection
//
// thumb: .thumb
//
Expand Down
Loading