Couple of codegen_fn_attrs improvements
As noted in https://github.com/rust-lang/rust/pull/144678#discussion_r2245060329 here is no need to keep link_name and export_name separate, which the third commit fixes by merging them. The second commit removes some dead code and the first commit merges two ifs with equivalent conditions. The last commit is an unrelated change which removes an unused `feature(autodiff)`.
Add `-Zindirect-branch-cs-prefix`
Cc: ``@azhogin`` ``@Darksonn``
This goes on top of https://github.com/rust-lang/rust/pull/135927, i.e. please skip the first commit here. Please feel free to inherit it there.
In fact, I am not sure if there is any use case for the flag without `-Zretpoline*`. GCC and Clang allow it, though.
There is a `FIXME` for two `ignore`s in the test that I took from another test I did in the past -- they may be needed or not here since I didn't run the full CI. Either way, it is not critical.
Tracking issue: https://github.com/rust-lang/rust/issues/116852.
MCP: https://github.com/rust-lang/compiler-team/issues/868.
Remove `LlvmArchiveBuilder` and supporting code/bindings
Switching over to the newer Rust-based `ArArchiveBuilder` happened in rust-lang/rust#128936, a year ago.
Per the comment in `new_archive_builder`, that seems like enough time to justify removing the older, unused `LlvmArchiveBuilder` implementation and its associated bindings.
Fixesrust-lang/rust#128955.
cg_llvm: Small cleanups to `owned_target_machine`
This PR contains a few tiny cleanups to the `owned_target_machine` code.
Each individual commit should be fairly straightforward.
cg_llvm: Use LLVM-C bindings for `LLVMSetTailCallKind`, `LLVMGetTypeKind`
This PR replaces two existing `LLVMRust` bindings with equivalent calls to the LLVM-C API.
For `LLVMGetTypeKind`, we avoid the UB hazard by declaring the foreign function to return `RawEnum<TypeKind>` (which is a wrapper around `u32`), and then perform checked conversion from `u32` to `TypeKind`.
Fix `-Zregparm` for LLVM builtins
This fixes the issue where `-Zregparm=N` was not working correctly when calling LLVM intrinsics
By default on `x86-32`, arguments are passed on the stack. The `-Zregparm=N` flag allows the first `N` arguments to be passed in registers instead.
When calling intrinsics like `memset`, LLVM still passes parameters on the stack, which prevents optimizations like tail calls.
As proposed by ````@tgross35,```` I fixed this by setting the `NumRegisterParameters` LLVM module flag to `N` when the `-Zregparm=N` is set.
```rust
// compiler/rust_codegen_llvm/src/context.rs#375-382
if let Some(regparm_count) = sess.opts.unstable_opts.regparm {
llvm::add_module_flag_u32(
llmod,
llvm::ModuleFlagMergeBehavior::Error,
"NumRegisterParameters",
regparm_count,
);
}
```
[Here](https://rust.godbolt.org/z/YMezreo48) is a before/after compiler explorer.
Here is the final result for the code snippet in the original issue:
```asm
entrypoint:
push esi
mov esi, eax
mov eax, ecx
mov ecx, esi
pop esi
jmp memset ; Tail call parameters in registers
```
Fixes: https://github.com/rust-lang/rust/issues/145271
As noted in the `ffi` module docs, passing pointer/length byte strings from
Rust to C++ is easier if we declare them as `*const c_uchar` on the Rust side,
but `const char *` (possibly signed) on the C++ side. This is allowed because
both pointer types are ABI-compatible, regardless of char signedness.
llvm: Accept new LLVM lifetime format
In llvm/llvm-project#150248 LLVM removed the size parameter from the lifetime format. Tolerate not having that size parameter.
set
* Enforce the `-Zregparm=N` flag by setting the NumRegisterParameters
LLVM module flag * Add assembly tests verifying that the parameters are
passed in registers for reparm values 1, 2, and 3, for both LLVM
intrinsics and non-builtin functions * Add c_void type to minicore
Set dead_on_return attribute for indirect arguments
Set the dead_on_return attribute (added in LLVM 21) for arguments that are passed indirectly, but not byval.
This indicates that the value of the argument on return does not matter, enabling additional dead store elimination.
From LangRef:
> This attribute indicates that the memory pointed to by the argument is dead upon function return, both upon normal return and if the calls unwinds, meaning that the caller will not depend on its contents. Stores that would be observable either on the return path or on the unwind path may be elided.
>
> Specifically, the behavior is as-if any memory written through the pointer during the execution of the function is overwritten with a poison value upon function return. The caller may access the memory, but any load not preceded by a store will return poison.
>
> This attribute does not imply aliasing properties. For pointer arguments that do not alias other memory locations, noalias attribute may be used in conjunction. Conversely, this attribute always implies dead_on_unwind.
>
> This attribute cannot be applied to return values.
This fixes parts of https://github.com/rust-lang/rust/issues/96497.
Set the dead_on_return attribute (added in LLVM 21) for arguments
that are passed indirectly, but not byval.
This indicates that the value of the argument on return does not
matter, enabling additional dead store elimination.
Enable f16 and f128 on targets that were fixed in LLVM21
LLVM21 fixed the new float types on a number of targets:
* SystemZ gained f16 support https://github.com/llvm/llvm-project/pull/109164
* Hexagon now uses soft f16 to avoid recursion bugs https://github.com/llvm/llvm-project/pull/130977
* Mips now correctly handles f128 (actually since LLVM20) https://github.com/llvm/llvm-project/pull/117525
* f128 is now correctly aligned when passing the stack on x86 https://github.com/llvm/llvm-project/pull/138092
Thus, enable the types on relevant targets for LLVM > 21.0.0.
NVPTX also gained handling of f128 as a storage type, but it lacks support for basic math operations so is still disabled here.
try-job: dist-i586-gnu-i586-i686-musl
try-job: dist-i686-linux
try-job: dist-i686-msvc
try-job: dist-s390x-linux
try-job: dist-various-1
try-job: dist-various-2
try-job: dist-x86_64-linux
try-job: i686-gnu-1
try-job: i686-gnu-2
try-job: i686-msvc-1
try-job: i686-msvc-2
try-job: test-various
atomicrmw on pointers: move integer-pointer cast hacks into backend
Conceptually, we want to have atomic operations on pointers of the form `fn atomic_add(ptr: *mut T, offset: usize, ...)`. However, LLVM does not directly support such operations (https://github.com/llvm/llvm-project/issues/120837), so we have to cast the `offset` to a pointer somewhere.
This PR moves that hack into the LLVM backend, so that the standard library, intrinsic, and Miri all work with the conceptual operation we actually want. Hopefully, one day LLVM will gain a way to represent these operations without integer-pointer casts, and then the hack will disappear entirely.
Cc ```@nikic``` -- this is the best we can do right now, right?
Fixes https://github.com/rust-lang/rust/issues/134617
It used to be necessary on Apple platforms to ship with the App Store,
but XCode 15 has stopped embedding LLVM bitcode and the App Store no
longer accepts apps with bitcode embedded.
coverage: Remove all unstable support for MC/DC instrumentation
Preliminary support for a partial implementation of “Modified Condition/Decision Coverage” instrumentation was added behind the unstable flag `-Zcoverage-options=mcdc` in 2024. These are the most substantial PRs involved:
- rust-lang/rust#123409
- rust-lang/rust#126733
At the time, I accepted these PRs with relatively modest scrutiny, because I did not want to stand in the way of independent work on MC/DC instrumentation. My hope was that ongoing work by interested contributors would lead to the code becoming clearer and more maintainable over time.
---
However, that MC/DC code has proven itself to be a major burden on overall maintenance of coverage instrumentation, and a major obstacle to other planned improvements, such as internal changes needed for proper support of macro expansion regions.
I have also become reluctant to accept any further MC/DC-related changes that would increase this burden.
That tension has resulted in an unhappy impasse. On one hand, the present MC/DC implementation is not yet complete, and shows little sign of being complete at an acceptable level of code quality in the foreseeable future. On the other hand, the continued existence of this partial MC/DC implementation is imposing serious maintenance burdens on every other aspect of coverage instrumentation, and is preventing some of the very improvements that would make it easier to accept expanded MC/DC support in the future.
While I know this will be disappointing to some, I think the healthy way forward is accept that I made the wrong call in accepting the current implementation, and to remove it entirely from the compiler.
The implementation of the linkage attribute inside extern blocks defines
symbols starting with _rust_extern_with_linkage_. If someone tries to
also define this symbol you will get a symbol conflict or even an ICE.
By adding an unpredictable component to the symbol name, this becomes
less of an issue.
Instead of collecting pretty printers transitively when building
executables/staticlibs/cdylibs, let the debugger find each crate's
pretty printers via its .debug_gdb_scripts section. This covers the case
where libraries defining custom pretty printers are loaded dynamically.