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
12 changes: 10 additions & 2 deletions compiler/rustc_codegen_llvm/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ use rustc_target::spec::HasTargetSpec;
use smallvec::SmallVec;
use tracing::debug;

use crate::attributes;
use crate::builder::Builder;
use crate::common::Funclet;
use crate::context::CodegenCx;
use crate::llvm::{self, ToLlvmBool, Type, Value};
use crate::type_of::LayoutLlvmExt;
use crate::{attributes, llvm_util};

impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
fn codegen_inline_asm(
Expand Down Expand Up @@ -499,7 +499,15 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
template_str.push_str("\n.att_syntax\n");
}

llvm::append_module_inline_asm(self.llmod, template_str.as_bytes());
let target_features = self.tcx.global_backend_features(()).join(",");
let target_cpu = llvm_util::target_cpu(self.tcx.sess);

llvm::append_module_inline_asm(
self.llmod,
template_str.as_bytes(),
&target_features,
target_cpu,
);
}

fn mangled_name(&self, instance: Instance<'tcx>) -> String {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_llvm/src/back/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1303,9 +1303,9 @@ fn embed_bitcode(
// We need custom section flags, so emit module-level inline assembly.
let section_flags = if cgcx.is_pe_coff { "n" } else { "e" };
let asm = create_section_with_flags_asm(".llvmbc", section_flags, bitcode);
llvm::append_module_inline_asm(llmod, &asm);
llvm::append_module_inline_asm(llmod, &asm, "", "");
let asm = create_section_with_flags_asm(".llvmcmd", section_flags, &[]);
llvm::append_module_inline_asm(llmod, &asm);
llvm::append_module_inline_asm(llmod, &asm, "", "");

@folkertdev folkertdev Aug 5, 2026

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 believe we just embed bytes here, so the target features and cpu don't seem relevant.

View changes since the review

}
}

Expand Down
18 changes: 11 additions & 7 deletions compiler/rustc_codegen_llvm/src/llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -907,13 +907,6 @@ unsafe extern "C" {
pub(crate) fn LLVMGetDataLayoutStr(M: &Module) -> *const c_char;
pub(crate) fn LLVMSetDataLayout(M: &Module, Triple: *const c_char);

/// Append inline assembly to a module. See `Module::appendModuleInlineAsm`.
pub(crate) fn LLVMAppendModuleInlineAsm(
M: &Module,
Asm: *const c_uchar, // See "PTR_LEN_STR".
Len: size_t,
);

/// Create the specified uniqued inline asm string. See `InlineAsm::get()`.
pub(crate) fn LLVMGetInlineAsm<'ll>(
Ty: &'ll Type,
Expand Down Expand Up @@ -2119,6 +2112,17 @@ unsafe extern "C" {
ConstraintsLen: size_t,
) -> bool;

/// Append inline assembly to a module. See `Module::appendModuleInlineAsm`.
pub(crate) fn LLVMRustAppendModuleInlineAsm(
M: &Module,
Asm: *const c_uchar, // See "PTR_LEN_STR".
AsmLen: size_t,
TargetFeatures: *const c_uchar, // See "PTR_LEN_STR".
TargetFeaturesLen: size_t,
TargetCpu: *const c_uchar, // See "PTR_LEN_STR".
TargetCpuLen: size_t,
);

/// A list of pointer-length strings is passed as two pointer-length slices,
/// one slice containing pointers and one slice containing their corresponding
/// lengths. The implementation will check that both slices have the same length.
Expand Down
19 changes: 16 additions & 3 deletions compiler/rustc_codegen_llvm/src/llvm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,11 +474,24 @@ pub(crate) fn set_dso_local<'ll>(v: &'ll Value) {
}
}

/// Safe wrapper for `LLVMAppendModuleInlineAsm`, which delegates to
/// Safe wrapper for `LLVMRustAppendModuleInlineAsm`, which delegates to
/// `Module::appendModuleInlineAsm`.
pub(crate) fn append_module_inline_asm<'ll>(llmod: &'ll Module, asm: &[u8]) {
pub(crate) fn append_module_inline_asm<'ll>(
llmod: &'ll Module,
asm: &[u8],
target_features: &str,
target_cpu: &str,
) {
unsafe {
LLVMAppendModuleInlineAsm(llmod, asm.as_ptr(), asm.len());
LLVMRustAppendModuleInlineAsm(
llmod,
asm.as_ptr(),
asm.len(),
target_features.as_ptr(),
target_features.len(),
target_cpu.as_ptr(),
target_cpu.len(),
);
}
}

Expand Down
14 changes: 14 additions & 0 deletions compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,20 @@ extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints,
unwrap<FunctionType>(Ty), StringRef(Constraints, ConstraintsLen)));
}

extern "C" void LLVMRustAppendModuleInlineAsm(
LLVMModuleRef M, const char *Asm, size_t AsmLen, const char *TargetFeatures,
size_t TargetFeaturesLen, const char *TargetCPU, size_t TargetCPULen) {
#if LLVM_VERSION_GE(23, 0)
Module::GlobalAsmProperties Props;
Props.TargetFeatures = std::string(TargetFeatures, TargetFeaturesLen);
Props.TargetCPU = std::string(TargetCPU, TargetCPULen);
unwrap(M)->appendModuleInlineAsm(
Module::GlobalAsmFragment(std::string(Asm, AsmLen), Props));
#else
unwrap(M)->appendModuleInlineAsm(StringRef(Asm, AsmLen));
#endif
}

template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) {
return (DIT *)(Ref ? unwrap<Metadata>(Ref) : nullptr);
}
Expand Down
49 changes: 49 additions & 0 deletions tests/ui/asm/global-target-feature.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//@ build-pass
//@ add-minicore
//@ min-llvm-version: 23
//@ ignore-backends: gcc
//
//@ revisions: riscv opt-0-bitcode-no opt-0 opt-s-bitcode-no
//
//@[riscv] compile-flags: --target riscv64gc-unknown-linux-gnu -Clto=thin
//@[riscv] needs-llvm-components: riscv
//
//@[opt-0-bitcode-no] compile-flags: --target armv7r-none-eabihf -Copt-level=0 -Cembed-bitcode=no
//@[opt-0-bitcode-no] needs-llvm-components: arm
//
//@[opt-0] compile-flags: --target armv7r-none-eabihf -Copt-level=0
//@[opt-0] needs-llvm-components: arm
//
//@[opt-s-bitcode-no] compile-flags: --target armv7r-none-eabihf -Copt-level=s -Cembed-bitcode=no
//@[opt-s-bitcode-no] needs-llvm-components: arm

// Regression test for
//
// - https://github.com/llvm/llvm-project/issues/61991
// - https://github.com/rust-lang/rust/issues/80608
// - https://github.com/rust-lang/rust/issues/127269
//
// Since LLVM 23 target features are taken into account for module-level assembly.

#![feature(no_core)]
#![no_core]
#![crate_type = "lib"]

extern crate minicore;
use minicore::*;

#[cfg(target_arch = "riscv64")]
global_asm!("fld f0, 0(sp)");

#[cfg(target_arch = "arm")]
global_asm!(
r#"
.section .text.startup
.global _start
.code 32
.align 0

_start:
vmsr fpexc, r0
"#
);
1 change: 1 addition & 0 deletions tests/ui/asm/inline-syntax.arm.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ note: instantiated into assembly here
|
LL | .intel_syntax noprefix
| ^
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: unknown directive
--> $DIR/inline-syntax.rs:21:15
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/asm/inline-syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
//@[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
//@[x86_64] check-pass
//@[x86_64] needs-llvm-components: x86
// LLVM 19+ has full support for 64-bit cookies.
//@[arm] compile-flags: --target armv7-unknown-linux-gnueabihf
//@[arm] build-fail
//@[arm] needs-llvm-components: arm
//@[arm] min-llvm-version: 23
//@ ignore-backends: gcc

#![feature(no_core)]
Expand Down
Loading