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: 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, "", "");
}
}

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 @@ -909,13 +909,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 @@ -2121,6 +2114,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
2 changes: 2 additions & 0 deletions library/alloc/src/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,8 @@
pub use core::fmt::Alignment;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::fmt::Error;
#[stable(feature = "fmt_numbuffer", since = "1.99.0")]
pub use core::fmt::NumBuffer;
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::fmt::{Arguments, write};
#[stable(feature = "rust1", since = "1.0.0")]
Expand Down
49 changes: 49 additions & 0 deletions library/compiler-builtins/builtins-test-intrinsics/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#![feature(f128)]
#![feature(f16)]
#![feature(lang_items)]
#![feature(optimize_attribute)]
#![no_std]
#![no_main]

Expand Down Expand Up @@ -389,6 +390,47 @@ mod intrinsics {
a % b
}

/* Unaligned memory access */

// LLVM only emits calls to `__aeabi_uread*` and `__aeabi_uwrite*` for functions optimized
// for minimum size on AEABI targets without unaligned access support.

/// # Safety
///
/// `p` must be valid for reading four bytes.
#[optimize(size)]
pub unsafe fn aeabi_uread4(p: *const u8) -> u32 {
// SAFETY: guaranteed by the caller.
unsafe { p.cast::<u32>().read_unaligned() }
}

/// # Safety
///
/// `p` must be valid for reading eight bytes.
#[optimize(size)]
pub unsafe fn aeabi_uread8(p: *const u8) -> u64 {
// SAFETY: guaranteed by the caller.
unsafe { p.cast::<u64>().read_unaligned() }
}

/// # Safety
///
/// `p` must be valid for writing four bytes.
#[optimize(size)]
pub unsafe fn aeabi_uwrite4(x: u32, p: *mut u8) {
// SAFETY: guaranteed by the caller.
unsafe { p.cast::<u32>().write_unaligned(x) }
}

/// # Safety
///
/// `p` must be valid for writing eight bytes.
#[optimize(size)]
pub unsafe fn aeabi_uwrite8(x: u64, p: *mut u8) {
// SAFETY: guaranteed by the caller.
unsafe { p.cast::<u64>().write_unaligned(x) }
}

/* u64 operations */

// floatundisf
Expand Down Expand Up @@ -500,6 +542,13 @@ fn run() {
bb(aeabi_ui2f(bb(2)));
bb(aeabi_uidiv(bb(2), bb(3)));
bb(aeabi_uidivmod(bb(2), bb(3)));
// SAFETY: the pointers point to buffers large enough for the access.
unsafe {
bb(aeabi_uread4(bb([0u8; 4].as_ptr())));
bb(aeabi_uread8(bb([0u8; 8].as_ptr())));
bb(aeabi_uwrite4(bb(2), bb([0u8; 4].as_mut_ptr())));
bb(aeabi_uwrite8(bb(2), bb([0u8; 8].as_mut_ptr())));
}
bb(aeabi_ul2d(bb(2)));
bb(aeabi_ul2f(bb(2)));
bb(aeabi_uldivmod(bb(2), bb(3)));
Expand Down
62 changes: 62 additions & 0 deletions library/compiler-builtins/builtins-test/tests/mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,3 +284,65 @@ fn memset_backward_aligned() {
assert_eq!(arr.0, reference.0);
}
}

#[cfg(all(
target_arch = "arm",
not(any(target_vendor = "apple", target_env = "msvc"))
))]
mod aeabi_unaligned {
use compiler_builtins::arm::__aeabi_uread4::__aeabi_uread4;
use compiler_builtins::arm::__aeabi_uread8::__aeabi_uread8;
use compiler_builtins::arm::__aeabi_uwrite4::__aeabi_uwrite4;
use compiler_builtins::arm::__aeabi_uwrite8::__aeabi_uwrite8;

/// A buffer with distinct bytes so that any mixup in byte order or offset is detected.
const PATTERN: [u8; 16] = [
0x11, 0x48, 0x7f, 0xb6, 0xed, 0x24, 0x5b, 0x92, 0xc9, 0x00, 0x37, 0x6e, 0xa5, 0xdc, 0x13,
0x4a,
];

#[test]
fn uread() {
let buf = PATTERN;
for offset in 0..8 {
let b = &buf[offset..];
let expected4 = u32::from_ne_bytes(*b.first_chunk::<4>().unwrap());
let expected8 = u64::from_ne_bytes(*b.first_chunk::<8>().unwrap());
unsafe {
assert_eq!(__aeabi_uread4(b.as_ptr()), expected4, "offset {offset}");
assert_eq!(__aeabi_uread8(b.as_ptr()), expected8, "offset {offset}");
}
}
}

#[test]
fn uwrite() {
let value4 = 0x8765_4321_u32;
let value8 = 0x0f1e_2d3c_4b5a_6978_u64;
for offset in 0..8 {
let mut buf = PATTERN;
let mut expected = PATTERN;
expected[offset..offset + 4].copy_from_slice(&value4.to_ne_bytes());
unsafe {
assert_eq!(
__aeabi_uwrite4(value4, buf.as_mut_ptr().add(offset)),
value4,
"offset {offset}"
);
}
assert_eq!(buf, expected, "offset {offset}");

let mut buf = PATTERN;
let mut expected = PATTERN;
expected[offset..offset + 8].copy_from_slice(&value8.to_ne_bytes());
unsafe {
assert_eq!(
__aeabi_uwrite8(value8, buf.as_mut_ptr().add(offset)),
value8,
"offset {offset}"
);
}
assert_eq!(buf, expected, "offset {offset}");
}
}
}
4 changes: 4 additions & 0 deletions library/compiler-builtins/compiler-builtins/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md).
- [x] arm/aeabi_memset.S
- [x] arm/aeabi_uidivmod.S
- [x] arm/aeabi_uldivmod.S
- [x] arm/aeabi_uread4.S
- [x] arm/aeabi_uread8.S
- [x] arm/aeabi_uwrite4.S
- [x] arm/aeabi_uwrite8.S
- [ ] arm/chkstk.S
- [ ] arm/divmodsi4.S (generic version is done)
- [ ] arm/divsi3.S (generic version is done)
Expand Down
4 changes: 0 additions & 4 deletions library/compiler-builtins/compiler-builtins/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,10 +362,6 @@ mod c {
("__aeabi_div0", "arm/aeabi_div0.c"),
("__aeabi_drsub", "arm/aeabi_drsub.c"),
("__aeabi_frsub", "arm/aeabi_frsub.c"),
("__aeabi_uread4", "arm/aeabi_uread4.S"),
("__aeabi_uread8", "arm/aeabi_uread8.S"),
("__aeabi_uwrite4", "arm/aeabi_uwrite4.S"),
("__aeabi_uwrite8", "arm/aeabi_uwrite8.S"),
("__bswapdi2", "arm/bswapdi2.S"),
("__bswapsi2", "arm/bswapsi2.S"),
("__divmodsi4", "arm/divmodsi4.S"),
Expand Down
Loading
Loading