Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 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
e4bb0e1
Limit splat AST and FnDecl to 255 args
teor2345 Jun 22, 2026
ade9fa3
Impl HIR FnSig for #[splat]
teor2345 Jun 10, 2026
cfd9e33
Impl HIR typeck for #[splat]
teor2345 Jun 10, 2026
ad77eda
Remove a leftover direct call to fn_ctxt.label_generic_mismatches
teor2345 Jun 5, 2026
ac47723
Fix ICE in `label_fn_like` when splatted arg index is out of bounds
Ajay-singh1 Jun 3, 2026
c29f2db
Impl MIR lowering side-tables for #[splat]
teor2345 Jun 12, 2026
4cb4e0c
Impl actual MIR lowering for #[splat]
teor2345 Jun 12, 2026
6c7c69c
Impl TypeInfo for splat
teor2345 Mar 11, 2026
c3593c1
Add UI tests for `#[splat]` unhappy path, generics, fn colors
Ajay-singh1 Jun 3, 2026
28b3d02
Add failing test for #[splat] with dyn AsRef<T> where T: Tuple
Ajay-singh1 Jun 22, 2026
b23bbed
Add splat UI tests for 255 splatted arg limit
teor2345 Jun 22, 2026
9b44c23
UI test arg diffs greater than u8::MAX
teor2345 Jun 23, 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
2625886
fixup the refactoring errors in 156246
jdonszelmann 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
58fe8e0
Rollup merge of #153697 - teor2345:fn-arg-splat-experiment, r=oli-obk
JonathanBrouwer Jun 25, 2026
aeb8c90
Rollup merge of #155535 - cezarbbb:cstyle-export-symbols, r=bjorn3
JonathanBrouwer Jun 25, 2026
8152132
Rollup merge of #158253 - davidtwco:scalable-vector-memcpy-vscale, r=…
JonathanBrouwer Jun 25, 2026
1ffafac
Rollup merge of #158308 - GuillaumeGomez:fix-only-result-bug, r=notri…
JonathanBrouwer Jun 25, 2026
58ca572
Rollup merge of #158345 - scottmcm:assume-init-no-read, r=RalfJung
JonathanBrouwer Jun 25, 2026
cd7d007
Rollup merge of #158369 - joboet:resume_unwind_in_hook, r=Amanieu
JonathanBrouwer Jun 25, 2026
6247a2e
Rollup merge of #158374 - WaffleLapkin:no-tail-rust-call, r=folkertdev
JonathanBrouwer Jun 25, 2026
f273f5b
Rollup merge of #158380 - folkertdev:revert-rebuild-llvm-on-bootstrap…
JonathanBrouwer Jun 25, 2026
9b8dc70
Rollup merge of #154398 - sandersaares:higher-ranked-auto-trait-test-…
JonathanBrouwer Jun 25, 2026
f05d8a9
Rollup merge of #157181 - scottmcm:no-autodiff-alloca, r=ZuseZ4
JonathanBrouwer Jun 25, 2026
2cf5eff
Rollup merge of #158278 - ZuseZ4:typetrees-for-enzyme2, r=oli-obk
JonathanBrouwer Jun 25, 2026
939c53a
Rollup merge of #158311 - Dodothereal:fix/unstable-book-default-visib…
JonathanBrouwer Jun 25, 2026
c01c933
Rollup merge of #158318 - steffahn:fix-ice-confusion, r=camelid
JonathanBrouwer Jun 25, 2026
843d94f
Rollup merge of #158338 - zedddie:gsoc-batch-14-meow, r=Kivooeo
JonathanBrouwer Jun 25, 2026
f9c9828
Rollup merge of #158343 - obi1kenobi:pg/item-const-stability, r=Guill…
JonathanBrouwer Jun 25, 2026
60ba47e
Rollup merge of #158355 - jdonszelmann:fixuop, r=lcnr
JonathanBrouwer Jun 25, 2026
24c190c
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
10 changes: 6 additions & 4 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3059,21 +3059,23 @@ impl FnDecl {
}

/// The marker index for "no splatted arguments".
/// Higher values are also not supported, for performance reasons.
///
/// Must have the same value as `FnSigKind::NO_SPLATTED_ARG_INDEX` and `FnDeclFlags::NO_SPLATTED_ARG_INDEX`.
pub const NO_SPLATTED_ARG_INDEX: u16 = u16::MAX;
pub const NO_SPLATTED_ARG_INDEX: u8 = u8::MAX;

/// Returns a splatted argument index, if any are present.
pub fn splatted(&self) -> Option<u16> {
pub fn splatted(&self) -> Option<u8> {
self.inputs.iter().enumerate().find_map(|(index, arg)| {
if index == Self::NO_SPLATTED_ARG_INDEX as usize {
if index >= usize::from(Self::NO_SPLATTED_ARG_INDEX) {
// AST validation has already checked the splatted argument index is valid, so just
// ignore invalid indexes here.
None
} else {
arg.attrs
.iter()
.any(|attr| attr.has_name(sym::splat))
.then_some(u16::try_from(index).unwrap())
.then_some(u8::try_from(index).unwrap())
}
})
}
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_ast_lowering/src/delegation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ struct ParamInfo {
pub c_variadic: bool,

/// The index of the splatted parameter, if any.
pub splatted: Option<u16>,
pub splatted: Option<u8>,
}

const PARENT_ID: hir::ItemLocalId = hir::ItemLocalId::ZERO;
Expand Down Expand Up @@ -364,11 +364,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn param_info(&self, def_id: DefId) -> ParamInfo {
let sig = self.tcx.fn_sig(def_id).skip_binder().skip_binder();

// FIXME(splat): use `sig.splatted()` once FnSig has it
ParamInfo {
param_count: sig.inputs().len() + usize::from(sig.c_variadic()),
c_variadic: sig.c_variadic(),
splatted: None,
splatted: sig.splatted(),
}
}

Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -412,11 +412,11 @@ impl<'a> AstValidator<'a> {
})
.unzip();

// A splatted argument at the "no splatted" marker index is not supported (this is an
// unlikely edge case).
// A splatted argument greater than or equal to the "no splatted" marker index is not
// supported.
if let (Some(&splatted_arg_index), Some(&splatted_span)) =
(splatted_arg_indexes.last(), splatted_spans.last())
&& splatted_arg_index == FnDecl::NO_SPLATTED_ARG_INDEX
&& splatted_arg_index >= u16::from(FnDecl::NO_SPLATTED_ARG_INDEX)
{
self.dcx().emit_err(diagnostics::InvalidSplattedArg {
splatted_arg_index,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_cranelift/src/abi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_
.map(|local| {
let arg_ty = fx.monomorphize(fx.mir.local_decls[local].ty);

// FIXME(splat): un-tuple splatted arguments in codegen, for performance
// Adapted from https://github.com/rust-lang/rust/blob/145155dc96757002c7b2e9de8489416e2fdbbd57/src/librustc_codegen_llvm/mir/mod.rs#L442-L482
if Some(local) == fx.mir.spread_arg {
// This argument (e.g. the last argument in the "rust-call" ABI)
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
1 change: 1 addition & 0 deletions compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,7 @@ fn push_debuginfo_type_name<'tcx>(
output.push_str("fn(");
}

// FIXME(splat): should debuginfo be de-tupled in the callee (and caller)?
if !sig.inputs().is_empty() {
for &parameter_type in sig.inputs() {
push_debuginfo_type_name(tcx, parameter_type, true, output, visited);
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_ssa/src/mir/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1185,6 +1185,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
};

// Split the rust-call tupled arguments off.
// FIXME(splat): un-tuple splatted arguments in codegen, for performance
let (first_args, untuple) = if sig.abi() == ExternAbi::RustCall
&& let Some((tup, args)) = args.split_last()
{
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_ssa/src/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
let arg_decl = &mir.local_decls[local];
let arg_ty = fx.monomorphize(arg_decl.ty);

// FIXME(splat): re-tuple splatted arguments that were un-tupled in the ABI
if Some(local) == mir.spread_arg {
// This argument (e.g., the last argument in the "rust-call" ABI)
// is a tuple that was spread at the ABI level and now we have
Expand Down
Loading
Loading