Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
d560d3a
Add test for async Send inference with PhantomData<*mut ()> + unsafe …
sandersaares Mar 26, 2026
2f10fd2
autodiff: stop always needing an alloca
scottmcm May 31, 2026
ca10995
export symbols: support macos/windows(32/64)
cezarbbb May 30, 2026
cfc4211
codegen_ssa: multiply scalable vec size by `vscale`
davidtwco Jun 22, 2026
b9d55eb
move typetree logic into a new file
ZuseZ4 Jun 22, 2026
2262b8e
Fix bug when rustdoc "go to only result" setting is not working as ex…
GuillaumeGomez Jun 23, 2026
d9038db
simplify call chains, fix assertions
ZuseZ4 Jun 23, 2026
c247067
doc(unstable-book): fix typo "earier" -> "earlier" in default-visibil…
Dodothereal Jun 23, 2026
8949cf2
Make normalization in a test case resilient to dist compilation
steffahn Jun 23, 2026
6f9f78c
move batch
zedddie Jun 24, 2026
19f2cef
bless batch
zedddie Jun 24, 2026
f8973b7
Include `Item::const_stability` info in rustdoc JSON.
obi1kenobi Jun 24, 2026
b75fb84
Update panicking.rs
joboet Jun 24, 2026
4594bcf
disallow tail calling extern "rust-call" functions
WaffleLapkin Jun 24, 2026
0083485
Revert "rebuild LLVM when `bootstrap.toml` config changes"
folkertdev Jun 24, 2026
4eb7436
Use `transmute_neo` in `assume_init`
scottmcm Jun 24, 2026
915b021
Fix: auto trait, const trait bound
Jamesbarford Jun 25, 2026
749740f
Rollup merge of #155535 - cezarbbb:cstyle-export-symbols, r=bjorn3
JonathanBrouwer Jun 25, 2026
e20298b
Rollup merge of #158253 - davidtwco:scalable-vector-memcpy-vscale, r=…
JonathanBrouwer Jun 25, 2026
0b5b960
Rollup merge of #158308 - GuillaumeGomez:fix-only-result-bug, r=notri…
JonathanBrouwer Jun 25, 2026
512c162
Rollup merge of #158345 - scottmcm:assume-init-no-read, r=RalfJung
JonathanBrouwer Jun 25, 2026
6f9fb4f
Rollup merge of #158369 - joboet:resume_unwind_in_hook, r=Amanieu
JonathanBrouwer Jun 25, 2026
005f989
Rollup merge of #158374 - WaffleLapkin:no-tail-rust-call, r=folkertdev
JonathanBrouwer Jun 25, 2026
759d8ea
Rollup merge of #158380 - folkertdev:revert-rebuild-llvm-on-bootstrap…
JonathanBrouwer Jun 25, 2026
88f124b
Rollup merge of #154398 - sandersaares:higher-ranked-auto-trait-test-…
JonathanBrouwer Jun 25, 2026
08c8c34
Rollup merge of #157181 - scottmcm:no-autodiff-alloca, r=ZuseZ4
JonathanBrouwer Jun 25, 2026
d6acc46
Rollup merge of #158278 - ZuseZ4:typetrees-for-enzyme2, r=oli-obk
JonathanBrouwer Jun 25, 2026
024f6a7
Rollup merge of #158311 - Dodothereal:fix/unstable-book-default-visib…
JonathanBrouwer Jun 25, 2026
675d478
Rollup merge of #158318 - steffahn:fix-ice-confusion, r=camelid
JonathanBrouwer Jun 25, 2026
e2bd72e
Rollup merge of #158338 - zedddie:gsoc-batch-14-meow, r=Kivooeo
JonathanBrouwer Jun 25, 2026
914c18e
Rollup merge of #158343 - obi1kenobi:pg/item-const-stability, r=Guill…
JonathanBrouwer Jun 25, 2026
65153e0
Rollup merge of #158390 - Jamesbarford:fix/trait-solver-const-bounds,…
JonathanBrouwer Jun 25, 2026
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
8 changes: 7 additions & 1 deletion compiler/rustc_abi/src/extern_abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,10 +343,16 @@ impl ExternAbi {
// This ABI does not support calls at all (except via assembly).
false
}
Self::RustCall => {
// Argument untupling requires additional support for tail calls to be possible,
// see <https://github.com/rust-lang/rust/pull/158248>. There is no real uses of
// tail calling `extern "rust-call"` functions
false
}

Self::C { .. }
| Self::System { .. }
| Self::Rust
| Self::RustCall
| Self::RustCold
| Self::RustInvalid
| Self::Unadjusted
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_codegen_gcc/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1459,6 +1459,10 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
);
}

fn vscale(&mut self, _: Self::Type) -> Self::Value {
unimplemented!("`rustc_codegen_gcc` doesn't support scalable vectors yet")
}

fn select(
&mut self,
cond: RValue<'gcc>,
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_codegen_llvm/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1226,6 +1226,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
}
}

fn vscale(&mut self, ty: &'ll Type) -> &'ll Value {
unsafe { llvm::LLVMRustBuildVScale(self.llbuilder, ty) }
}

fn select(
&mut self,
cond: &'ll Value,
Expand Down
21 changes: 16 additions & 5 deletions compiler/rustc_codegen_llvm/src/builder/autodiff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ use std::ptr;
use rustc_ast::expand::autodiff_attrs::{DiffActivity, DiffMode};
use rustc_ast::expand::typetree::FncTree;
use rustc_codegen_ssa::common::TypeKind;
use rustc_codegen_ssa::mir::IntrinsicResult;
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
use rustc_codegen_ssa::mir::place::PlaceValue;
use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods};
use rustc_data_structures::thin_vec::ThinVec;
use rustc_hir::attrs::RustcAutodiff;
Expand All @@ -11,7 +14,7 @@ use rustc_middle::{bug, ty};
use rustc_target::callconv::PassMode;
use tracing::debug;

use crate::builder::{Builder, PlaceRef, UNNAMED};
use crate::builder::{Builder, UNNAMED};
use crate::context::SimpleCx;
use crate::declare::declare_simple_fn;
use crate::llvm::{self, TRUE, Type, Value};
Expand Down Expand Up @@ -296,9 +299,10 @@ pub(crate) fn generate_enzyme_call<'ll, 'tcx>(
ret_ty: &'ll Type,
fn_args: &[&'ll Value],
attrs: &RustcAutodiff,
dest: PlaceRef<'tcx, &'ll Value>,
dest_layout: ty::layout::TyAndLayout<'tcx>,
dest_place: Option<PlaceValue<&'ll Value>>,
fnc_tree: FncTree,
) {
) -> IntrinsicResult<'tcx, &'ll Value> {
// We have to pick the name depending on whether we want forward or reverse mode autodiff.
let mut ad_name: String = match attrs.mode {
DiffMode::Forward => "__enzyme_fwddiff",
Expand Down Expand Up @@ -381,11 +385,18 @@ pub(crate) fn generate_enzyme_call<'ll, 'tcx>(
let call = builder.call(enzyme_ty, None, None, ad_fn, &args, None, None);

let fn_ret_ty = builder.cx.val_ty(call);
if fn_ret_ty != builder.cx.type_void() && fn_ret_ty != builder.cx.type_struct(&[], false) {
if fn_ret_ty == builder.cx.type_void() || fn_ret_ty == builder.cx.type_struct(&[], false) {
// If we return void or an empty struct, then our caller (due to how we generated it)
// does not expect a return value. As such, we have no pointer (or place) into which
// we could store our value, and would store into an undef, which would cause UB.
// As such, we just ignore the return value in those cases.
builder.store_to_place(call, dest.val);
IntrinsicResult::Operand(OperandValue::ZeroSized)
} else if let Some(dest_place) = dest_place {
builder.store_to_place(call, dest_place);
IntrinsicResult::WroteIntoPlace
} else {
IntrinsicResult::Operand(
OperandRef::from_immediate_or_packed_pair(builder, call, dest_layout).val,
)
}
}
5 changes: 1 addition & 4 deletions compiler/rustc_codegen_llvm/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -978,10 +978,7 @@ impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
}

fn intrinsic_call_expects_place_always(&self, name: Symbol) -> bool {
matches!(
name,
sym::autodiff | sym::volatile_load | sym::unaligned_volatile_load | sym::black_box
)
matches!(name, sym::volatile_load | sym::unaligned_volatile_load | sym::black_box)
}
}

Expand Down
24 changes: 11 additions & 13 deletions compiler/rustc_codegen_llvm/src/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ use crate::errors::{
AutoDiffWithoutEnable, AutoDiffWithoutLto, IntrinsicSignatureMismatch, IntrinsicWrongArch,
OffloadWithoutEnable, OffloadWithoutFatLTO, UnknownIntrinsic,
};
use crate::intrinsic::ty::typetree::fnc_typetrees;
use crate::llvm::{self, Type, Value};
use crate::type_of::LayoutLlvmExt;
use crate::va_arg::emit_va_arg;
Expand Down Expand Up @@ -223,12 +224,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
)
}
sym::autodiff => {
let result = PlaceRef {
val: result_place.unwrap(),
layout: result_layout,
};
codegen_autodiff(self, tcx, instance, args, result);
return IntrinsicResult::WroteIntoPlace;
return codegen_autodiff(self, tcx, instance, args, result_layout, result_place);
}
sym::offload => {
if tcx.sess.opts.unstable_opts.offload.is_empty() {
Expand Down Expand Up @@ -1728,8 +1724,9 @@ fn codegen_autodiff<'ll, 'tcx>(
tcx: TyCtxt<'tcx>,
instance: ty::Instance<'tcx>,
args: &[OperandRef<'tcx, &'ll Value>],
result: PlaceRef<'tcx, &'ll Value>,
) {
result_layout: ty::layout::TyAndLayout<'tcx>,
result_place: Option<PlaceValue<&'ll Value>>,
) -> IntrinsicResult<'tcx, &'ll Value> {
if !tcx.sess.opts.unstable_opts.autodiff.contains(&rustc_session::config::AutoDiff::Enable) {
let _ = tcx.dcx().emit_almost_fatal(AutoDiffWithoutEnable);
}
Expand Down Expand Up @@ -1769,9 +1766,9 @@ fn codegen_autodiff<'ll, 'tcx>(
diff_id,
diff_args
),
Err(_) => {
Err(err) => {
// An error has already been emitted
return;
return IntrinsicResult::Err(err);
}
};

Expand All @@ -1791,7 +1788,7 @@ fn codegen_autodiff<'ll, 'tcx>(
&mut diff_attrs.input_activity,
);

let fnc_tree = rustc_middle::ty::fnc_typetrees(tcx, source_fn_ptr_ty);
let fnc_tree = fnc_typetrees(tcx, source_fn_ptr_ty);

// Build body
generate_enzyme_call(
Expand All @@ -1802,9 +1799,10 @@ fn codegen_autodiff<'ll, 'tcx>(
llret_ty,
&val_arr,
&diff_attrs,
result,
result_layout,
result_place,
fnc_tree,
);
)
}

// Generates the LLVM code to offload a Rust function to a target device (e.g., GPU).
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_codegen_llvm/src/llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2139,6 +2139,8 @@ unsafe extern "C" {
IsVolatile: bool,
) -> &'a Value;

pub(crate) fn LLVMRustBuildVScale<'a>(B: &Builder<'a>, Ty: &'a Type) -> &'a Value;

pub(crate) fn LLVMRustTimeTraceProfilerInitialize();

pub(crate) fn LLVMRustTimeTraceProfilerFinishThread();
Expand Down
81 changes: 76 additions & 5 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ use rustc_session::{Session, filesearch};
use rustc_span::Symbol;
use rustc_target::spec::crt_objects::CrtObjects;
use rustc_target::spec::{
BinaryFormat, Cc, CfgAbi, Env, LinkOutputKind, LinkSelfContainedComponents,
Arch, BinaryFormat, Cc, CfgAbi, Env, LinkOutputKind, LinkSelfContainedComponents,
LinkSelfContainedDefault, LinkerFeatures, LinkerFlavor, LinkerFlavorCli, Lld, Os, RelocModel,
RelroLevel, SanitizerSet, SplitDebuginfo,
};
Expand Down Expand Up @@ -2413,6 +2413,69 @@ fn add_rpath_args(
}
}

fn strip_numeric_suffix<'a>(base: &'a str, suffix: impl AsRef<str>, fallback: &'a str) -> &'a str {
if suffix.as_ref().parse::<u32>().is_ok() { base } else { fallback }
}

fn undecorate_c_symbol<'a>(
name: &'a str,
sess: &Session,
kind: SymbolExportKind,
) -> Option<&'a str> {
match sess.target.binary_format {
BinaryFormat::MachO => {
// Mach-O: strip the leading underscore that all external symbols have.
// The Darwin linker's export_symbols will add it back.
name.strip_prefix('_')
}
BinaryFormat::Coff => {
// MSVC C++ mangled names start with '?' and use a completely different
// decorating scheme that includes '@@' as structural delimiters.
// They must not be subjected to C calling-convention undecoration.
if name.starts_with('?') {
return Some(name);
}
Some(match sess.target.arch {
Arch::X86 => {
// COFF 32-bit: strip calling-convention decorations.
if let Some(rest) = name.strip_prefix('@') {
// fastcall: @foo@N -> foo
rest.rsplit_once('@')
.map(|(base, suffix)| strip_numeric_suffix(base, suffix, name))
.unwrap_or(name)
} else if let Some(stripped) = name.strip_prefix('_') {
if let Some((base, suffix)) = stripped.rsplit_once('@') {
// stdcall: _foo@N -> foo
strip_numeric_suffix(base, suffix, stripped)
} else {
// cdecl: _foo -> foo
stripped
}
} else {
// vectorcall: foo@@N -> foo
name.rsplit_once("@@")
.map(|(base, suffix)| strip_numeric_suffix(base, suffix, name))
.unwrap_or(name)
}
}
Arch::X86_64 => {
// COFF 64-bit: vectorcall mangling (foo@@N -> foo) also applies on x86_64.
name.rsplit_once("@@")
.map(|(base, suffix)| strip_numeric_suffix(base, suffix, name))
.unwrap_or(name)
}
Arch::Arm64EC if kind == SymbolExportKind::Text => {
// Arm64EC: `#` prefix distinguishes ARM64EC text symbols from x64 thunks.
name.strip_prefix('#').unwrap_or(name)
}
_ => name,
})
}
// ELF: no decoration
_ => Some(name),
}
}

fn add_c_staticlib_symbols(
sess: &Session,
lib: &NativeLib,
Expand Down Expand Up @@ -2454,7 +2517,14 @@ fn add_c_staticlib_symbols(
}

for symbol in object.symbols() {
if symbol.scope() != object::SymbolScope::Dynamic {
// The `object` crate returns `Dynamic` for ELF/Mach-O global symbols,
// but always returns `Linkage` for COFF external symbols.
// Accept both for COFF (Windows and UEFI).
let scope = symbol.scope();
if scope != object::SymbolScope::Dynamic
&& !(sess.target.binary_format == BinaryFormat::Coff
&& scope == object::SymbolScope::Linkage)
{
continue;
}

Expand All @@ -2469,9 +2539,10 @@ fn add_c_staticlib_symbols(
_ => continue,
};

// FIXME:The symbol mangle rules are slightly different in Windows(32-bit) and Apple.
// Need to be resolved.
out.push((name.to_string(), export_kind));
let Some(undecorated) = undecorate_c_symbol(name, sess, export_kind) else {
continue;
};
out.push((undecorated.to_string(), export_kind));
}
}

Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_codegen_ssa/src/traits/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,11 @@ pub trait BuilderMethods<'a, 'tcx>:
flags: MemFlags,
);

// Produce a value from calling the `vscale` intrinsic (containing the `vscale` multiplier that
// a scalable vector's element size and count can be multiplied by to get the real size of the
// vector)
fn vscale(&mut self, ty: Self::Type) -> Self::Value;

/// *Typed* copy for non-overlapping places.
///
/// Has a default implementation in terms of `memcpy`, but specific backends
Expand Down Expand Up @@ -513,6 +518,12 @@ pub trait BuilderMethods<'a, 'tcx>:
temp.val.store_with_flags(self, dst.with_type(layout), flags);
} else if !layout.is_zst() {
let bytes = self.const_usize(layout.size.bytes());
let bytes = if layout.peel_transparent_wrappers(self).ty.is_scalable_vector() {
let vscale = self.vscale(self.type_i64());
self.mul(vscale, bytes)
} else {
bytes
};
self.memcpy(dst.llval, dst.align, src.llval, src.align, bytes, flags, None);
}
}
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1497,6 +1497,10 @@ LLVMRustBuildMemMove(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign,
unwrap(Size), IsVolatile));
}

extern "C" LLVMValueRef LLVMRustBuildVScale(LLVMBuilderRef B, LLVMTypeRef Ty) {
return wrap(unwrap(B)->CreateVScale(unwrap(Ty)));
}

extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B, LLVMValueRef Dst,
unsigned DstAlign, LLVMValueRef Val,
LLVMValueRef Size,
Expand Down
Loading
Loading