Skip to content
Merged
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
12 changes: 12 additions & 0 deletions src/tools/run-make-support/src/external_deps/llvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,12 @@ impl LlvmFilecheck {
self.cmd.arg(input_file.as_ref());
self
}

/// Set a single `--check-prefix`.
pub fn check_prefix<S: AsRef<str>>(&mut self, prefix: S) -> &mut Self {
self.cmd.arg(format!("--check-prefix={}", prefix.as_ref()));
self
}
}

impl LlvmObjdump {
Expand All @@ -324,6 +330,12 @@ impl LlvmObjdump {
self.cmd.arg("-d");
self
}

/// Demangle symbols.
pub fn demangle(&mut self) -> &mut Self {
self.cmd.arg("--demangle");
self
}
}

impl LlvmAr {
Expand Down
1 change: 1 addition & 0 deletions tests/run-make/thumb-interworking/link.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ENTRY(entry);
118 changes: 118 additions & 0 deletions tests/run-make/thumb-interworking/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
#![feature(no_core)]
#![no_core]
#![no_main]

extern crate minicore;
use minicore::*;

#[unsafe(no_mangle)]
fn entry() {
arm();
thumb();
}

#[unsafe(no_mangle)]
pub fn arm() {
// thumbv5te-LABEL: <arm>:
// thumbv5te: blx {{0x[0-9a-f]+}} <main::arm_normalfn>
// thumbv5te: blx {{0x[0-9a-f]+}} <arm_globalfn>
// thumbv5te: blx {{0x[0-9a-f]+}} <main::arm_nakedfn>

// thumbv4t-LABEL: <arm>:
// thumbv4t: bl {{0x[0-9a-f]+}} <__Thumbv4ABSLongBXThunk__{{.*}}arm_normalfn>
// thumbv4t: bl {{0x[0-9a-f]+}} <__Thumbv4ABSLongBXThunk_arm_globalfn>
// thumbv4t: bl {{0x[0-9a-f]+}} <__Thumbv4ABSLongBXThunk__{{.*}}arm_nakedfn>

// armv5te-LABEL: <arm>:
// armv5te: bl {{0x[0-9a-f]+}} <main::arm_normalfn>
// armv5te: bl {{0x[0-9a-f]+}} <arm_globalfn>
// armv5te: bl {{0x[0-9a-f]+}} <main::arm_nakedfn>

// armv4t-LABEL: <arm>:
// armv4t: bl {{0x[0-9a-f]+}} <main::arm_normalfn>
// armv4t: bl {{0x[0-9a-f]+}} <arm_globalfn>
// armv4t: bl {{0x[0-9a-f]+}} <main::arm_nakedfn>
arm_normalfn();
arm_globalfn();
arm_nakedfn();
}

#[unsafe(no_mangle)]
pub fn thumb() {
// thumbv5te-LABEL: <thumb>:
// thumbv5te: bl {{0x[0-9a-f]+}} <main::thumb_normalfn>
// thumbv5te: bl {{0x[0-9a-f]+}} <thumb_globalfn>
// thumbv5te: bl {{0x[0-9a-f]+}} <main::thumb_nakedfn>

// thumbv4t-LABEL: <thumb>:
// thumbv4t: bl {{0x[0-9a-f]+}} <main::thumb_normalfn>
// thumbv4t: bl {{0x[0-9a-f]+}} <thumb_globalfn>
// thumbv4t: bl {{0x[0-9a-f]+}} <main::thumb_nakedfn>

// armv5te-LABEL: <thumb>:
// armv5te: blx {{0x[0-9a-f]+}} <main::thumb_normalfn>
// armv5te: blx {{0x[0-9a-f]+}} <thumb_globalfn>
// armv5te: blx {{0x[0-9a-f]+}} <main::thumb_nakedfn>

// armv4t-LABEL: <thumb>:
// armv4t: bl {{0x[0-9a-f]+}} <__ARMv4ABSLongBXThunk__{{.*}}thumb_normalfn>
// armv4t: bl {{0x[0-9a-f]+}} <__ARMv4ABSLongBXThunk_thumb_globalfn>
// armv4t: bl {{0x[0-9a-f]+}} <__ARMv4ABSLongBXThunk__{{.*}}thumb_nakedfn>
thumb_normalfn();
thumb_globalfn();
thumb_nakedfn();
}

#[instruction_set(arm::t32)]
extern "C" fn thumb_normalfn() {
unsafe { asm!("nop") }
}

unsafe extern "C" {
safe fn thumb_globalfn();
}

global_asm!(
r#"
.thumb
.global thumb_globalfn
.type thumb_globalfn, %function
thumb_globalfn:
nop
bx lr
.size thumb_globalfn, . - thumb_globalfn
"#
);

#[unsafe(naked)]
#[instruction_set(arm::t32)]
extern "C" fn thumb_nakedfn() {
naked_asm!("nop", "bx lr",);
}

#[instruction_set(arm::a32)]
extern "C" fn arm_normalfn() {
unsafe { asm!("nop") }
}

unsafe extern "C" {
safe fn arm_globalfn();
}

global_asm!(
r#"
.arm
.global arm_globalfn
.type arm_globalfn, %function
arm_globalfn:
nop
bx lr
.size arm_globalfn, . - arm_globalfn
"#
);

#[unsafe(naked)]
#[instruction_set(arm::a32)]
extern "C" fn arm_nakedfn() {
naked_asm!("nop", "bx lr",);
}
52 changes: 52 additions & 0 deletions tests/run-make/thumb-interworking/rmake.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//@ needs-llvm-components: arm
//@ needs-rust-lld
use run_make_support::{llvm_filecheck, llvm_objdump, path, rfs, run, rustc, source_root};

// Test a thumb target calling arm functions. Doing so requires switching from thumb mode to arm
// mode, calling the arm code, then switching back to thumb mode. Depending on the thumb version,
// this happens using a special calling instruction, or by calling a generated thunk that performs
// the mode switching.
//
// In particular this tests that naked functions behave like normal functions. Before LLVM 22, a
// bug in LLVM caused thumb mode to be used unconditonally when symbols were .hidden, miscompiling
// calls to arm functions.
//
// - https://github.com/llvm/llvm-project/pull/181156
// - https://github.com/rust-lang/rust/issues/151946

fn main() {
// Thumb calling thumb and arm.
helper("thumbv5te", "thumbv5te-none-eabi");
helper("thumbv4t", "thumbv4t-none-eabi");

// Arm calling thumb and arm.
helper("armv5te", "armv5te-none-eabi");
helper("armv4t", "armv4t-none-eabi");
}

fn helper(prefix: &str, target: &str) {
rustc()
.input(source_root().join("tests/auxiliary/minicore.rs"))
.crate_name("minicore")
.crate_type("rlib")
.target(target)
.output("libminicore.rlib")
.run();
let minicore = path("libminicore.rlib");

rustc()
.input("main.rs")
.panic("abort")
.link_arg("-Tlink.ld")
.arg("--extern")
.arg(format!("minicore={}", minicore.display()))
.target(target)
.output(prefix)
.run();

let dump = llvm_objdump().disassemble().demangle().input(path(prefix)).run();

eprintln!("{}", str::from_utf8(&dump.stdout()).unwrap());

llvm_filecheck().patterns("main.rs").check_prefix(prefix).stdin_buf(dump.stdout()).run();
}
Loading