Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
3e6a43d
allow `Allocator`s to be used as `#[global_allocator]`s
joboet May 29, 2026
46939fa
std: implement `GlobalAllocator` for `System`
joboet May 29, 2026
6c2e9d5
bless UI tests
joboet May 31, 2026
5042010
core: allow zero-size checks to be optimized out for `GlobalAllocator`
joboet Jun 21, 2026
e3e20ed
Rename HAS_CT_PROJECTION to HAS_CONST_ALIASES
Shourya742 Jun 27, 2026
4d1093d
Do not inherit `ConstArgHasType` predicates when it is applied to con…
aerooneqq Jul 3, 2026
cc71d5c
simplify `Option::into_flat_iter` signature
WaffleLapkin Jul 3, 2026
b66097b
Move DuplicateEiiImpls to rustc_middle
qaijuang May 11, 2026
0c82287
Reject linked dylib EII default overrides
qaijuang May 11, 2026
53897bb
address a few nits
qaijuang May 28, 2026
f6ce3ba
preserve EII rlib-only aux builds
qaijuang May 28, 2026
eef7f2e
Add library support for `aarch64-unknown-linux-pauthtest`
jchlanda May 4, 2026
1a7135c
Use target_env = "musl" & target_abi = "pauthtest" instead of env
jchlanda May 11, 2026
d0b4c46
Update landing pad to use addr()
jchlanda Jun 3, 2026
038cb8d
Use rust_force_inline on sign_lpad function
jchlanda Jul 3, 2026
b749630
Set correct cfg_select for sign_lpad
jchlanda Jul 6, 2026
017255b
Add new PGO config section to bootstrap
Kobzol Jul 7, 2026
33da2c8
Port LLVM PGO to the new PGO config section
Kobzol Jul 7, 2026
b576701
Use the new bootstrap PGO options in `opt-dist`
Kobzol Jul 7, 2026
5d96f17
Do not build the compiler when invoking `x perf compare`
Kobzol Jul 7, 2026
d2ee4ca
rustdoc: Represent `--output-format=json` coverage and ir differently
aDotInTheVoid Mar 27, 2026
f4db0a9
Emit the emscripten entry point as `__main_argc_argv`
guybedford Jul 8, 2026
1f6b1d5
Fix bootstrap example TOML
Kobzol Jul 7, 2026
08d5ee3
codegen_ssa: pack small const aggregates into immediate stores
ChuanqiXu9 Jun 24, 2026
fc267a6
Improve generic parameters handling for #[diagnostic::on_const]
rperier Jun 21, 2026
abc324c
Move `std::io::default_write_vectored` to `core::io`
bushrat011899 May 21, 2026
55585ea
Move `std::io::cursor`internals to `core::io`
bushrat011899 May 22, 2026
66f79f1
Move `WriteThroughCursor` internals to `alloc::io`
bushrat011899 Jul 3, 2026
ec0534f
Move `std::io::Write` to `core::io`
bushrat011899 Jul 3, 2026
4ecb0cd
Fix documentation links to `Write`
bushrat011899 May 22, 2026
53727e6
Add documentation to `core::io` internal methods
bushrat011899 Jul 7, 2026
0e61812
Reduce visibility of `core::io::write::default_write_fmt`
bushrat011899 Jul 7, 2026
cb09bff
Add `Vec::try_extend_from_slice_of_bytes`
bushrat011899 Jul 7, 2026
8118399
Attempt to run parallel frontend CI
heinwol Jul 8, 2026
3378897
address suggestions
qaijuang Jul 8, 2026
41bdaed
address follow up nits
qaijuang Jul 8, 2026
15f9829
update comments
guybedford Jul 8, 2026
7b28740
Rollup merge of #157690 - ChuanqiXu9:PaddingZero, r=dianqk
JonathanBrouwer Jul 8, 2026
481da76
Rollup merge of #158541 - bushrat011899:core_io_write, r=clarfonthey
JonathanBrouwer Jul 8, 2026
4f87cdb
Rollup merge of #154445 - aDotInTheVoid:better-enum, r=Urgau
JonathanBrouwer Jul 8, 2026
9959d40
Rollup merge of #156370 - qaijuang:eii-dylib-default-override, r=bjorn3
JonathanBrouwer Jul 8, 2026
d68cfaa
Rollup merge of #157153 - joboet:global_allocator, r=nia-e
JonathanBrouwer Jul 8, 2026
fef0144
Rollup merge of #158495 - Shourya742:2026-06-27-rename-tflag, r=BoxyU…
JonathanBrouwer Jul 8, 2026
e23904c
Rollup merge of #158912 - Kobzol:bootstrap-pgo-config, r=jieyouxu
JonathanBrouwer Jul 8, 2026
74d268c
Rollup merge of #158932 - Kobzol:x-compare-dont-build-rustc, r=clubby789
JonathanBrouwer Jul 8, 2026
f90a5b5
Rollup merge of #158937 - guybedford:emscripten-pthread-main, r=bjorn3
JonathanBrouwer Jul 8, 2026
9a1a245
Rollup merge of #156548 - jchlanda:jakub/pac_lib, r=davidtwco
JonathanBrouwer Jul 8, 2026
0504996
Rollup merge of #158307 - heinwol:parallel-frontend-CI, r=jieyouxu
JonathanBrouwer Jul 8, 2026
6ab1c00
Rollup merge of #158347 - rperier:diagnostic_on_const_format_argument…
JonathanBrouwer Jul 8, 2026
16c65d7
Rollup merge of #158722 - aerooneqq:delegation-const-predicates-ice, …
JonathanBrouwer Jul 8, 2026
0a5274b
Rollup merge of #158741 - WaffleLapkin:into_flat_iter_noa, r=hanna-kr…
JonathanBrouwer Jul 8, 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
18 changes: 18 additions & 0 deletions bootstrap.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -973,6 +973,24 @@
#dist.vendor = if "is a tarball source" || "is a git repository" { true } else { false }


# =============================================================================
# Profile-guided optimization options
#
# Configure the PGO profile to be used for compilation, or a path where the
# profile will be written by an instrumented binary, for individual components
# =============================================================================

# Use the following profile to PGO optimize the Rust compiler.
#pgo.rustc.use = "/tmp/profiles/foo.profraw"
# Instrument the Rust compiler, so that when executed, it will gather profiles
# to this path.
#pgo.rustc.generate = "/tmp/profiles/foo.profraw"
# Use the following profile to PGO optimize LLVM.
#pgo.llvm.use = "/tmp/profiles/foo.profraw"
# Instrument LLVM, so that when executed, it will gather profiles
# Note: for LLVM specifically, this should be a directory, not a file path.
#pgo.llvm.generate = "/tmp/profiles"

# =============================================================================
# Options for specific targets
#
Expand Down
67 changes: 67 additions & 0 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use rustc_metadata::{
walk_native_lib_search_dirs,
};
use rustc_middle::bug;
use rustc_middle::error::DuplicateEiiImpls;
use rustc_middle::lint::emit_lint_base;
use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
use rustc_middle::middle::dependency_format::Linkage;
Expand Down Expand Up @@ -76,6 +77,64 @@ pub fn ensure_removed(dcx: DiagCtxtHandle<'_>, path: &Path) {
}
}

fn eii_impl_crate_name(crate_info: &CrateInfo, cnum: CrateNum) -> Symbol {
if cnum == LOCAL_CRATE { crate_info.local_crate_name } else { crate_info.crate_name[&cnum] }
}

fn check_externally_implementable_item_linkage(sess: &Session, crate_info: &CrateInfo) {
if crate_info.eii_linkage.is_empty() {
return;
}

// A crate can request multiple linked outputs with overlapping dependency
// formats, so report each underlying conflict once.
let mut emitted = FxHashSet::default();

// This needs the dependency formats selected for the final artifact. The
// earlier EII pass still handles missing impls and duplicate explicit impls.
for dependency_formats in crate_info.dependency_formats.values() {
for (eii_index, eii) in crate_info.eii_linkage.iter().enumerate() {
let Some(explicit_impl) = eii.impls.first() else {
continue;
};
// If the explicit impl is already coming from a dylib, that dylib
// has already resolved the default-vs-explicit choice.
if matches!(
dependency_formats.get(explicit_impl.impl_crate),
Some(Linkage::Dynamic | Linkage::IncludedFromDylib)
) {
continue;
}

let Some(default_impl) = &eii.default_impl else {
continue;
};
if !matches!(
dependency_formats.get(default_impl.impl_crate),
Some(Linkage::Dynamic | Linkage::IncludedFromDylib)
) {
continue;
}

if !emitted.insert(eii_index) {
continue;
}

sess.dcx().emit_err(DuplicateEiiImpls {
name: eii.name,
first_span: explicit_impl.span,
first_crate: eii_impl_crate_name(crate_info, explicit_impl.impl_crate),
second_span: default_impl.span,
second_crate: eii_impl_crate_name(crate_info, default_impl.impl_crate),
help: (),
additional_crates: None,
num_additional_crates: 0,
additional_crate_names: String::new(),
});
}
}
}

/// Performs the linkage portion of the compilation phase. This will generate all
/// of the requested outputs for this compilation session.
pub fn link_binary(
Expand All @@ -91,6 +150,14 @@ pub fn link_binary(
let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata);
let mut tempfiles_for_stdout_output: Vec<PathBuf> = Vec::new();
let mut rmeta_link_cache = RmetaLinkCache::default();

if outputs.outputs.should_link() {
sess.time("check_externally_implementable_item_linkage", || {
check_externally_implementable_item_linkage(sess, &crate_info);
});
sess.dcx().abort_if_errors();
}

for &crate_type in &crate_info.crate_types {
// Ignore executable crates if we have -Z no-codegen, as they will error.
if (sess.opts.unstable_opts.no_codegen || !sess.opts.output_types.should_codegen())
Expand Down
17 changes: 16 additions & 1 deletion compiler/rustc_codegen_ssa/src/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1286,9 +1286,24 @@ impl<'a> Linker for EmLinker<'a> {

self.cc_arg("-s");

// Emscripten exposes the program entry point under the JS name `_main`
// regardless of the underlying wasm symbol (which is `__main_argc_argv`
// per the wasm C ABI in the tool-conventions BasicCABI spec), bridging
// the two internally. So the entry symbol must be requested as `_main`
// here rather than as a `_`-prefixed form of its wasm name.
let entry_name = self.sess.target.entry_name.as_ref();
let mut arg = OsString::from("EXPORTED_FUNCTIONS=");
let encoded = serde_json::to_string(
&symbols.iter().map(|sym| "_".to_owned() + &sym.name).collect::<Vec<_>>(),
&symbols
.iter()
.map(|sym| {
if sym.name == entry_name {
"_main".to_owned()
} else {
"_".to_owned() + &sym.name
}
})
.collect::<Vec<_>>(),
)
.unwrap();
debug!("{encoded}");
Expand Down
87 changes: 80 additions & 7 deletions compiler/rustc_codegen_ssa/src/base.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
use std::cmp;
use std::collections::BTreeSet;
use std::sync::Arc;
use std::time::{Duration, Instant};
use std::{cmp, iter};

use itertools::Itertools;
use rustc_abi::FIRST_VARIANT;
use rustc_ast::expand::allocator::{
ALLOC_ERROR_HANDLER, ALLOCATOR_METHODS, AllocatorKind, AllocatorMethod, AllocatorMethodInput,
AllocatorTy,
};
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
use rustc_data_structures::sync::{IntoDynSyncSend, par_map};
use rustc_data_structures::unord::UnordMap;
use rustc_hir::attrs::{DebuggerVisualizerType, OptimizeAttr};
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_hir::attrs::{DebuggerVisualizerType, EiiDecl, EiiImpl, OptimizeAttr};
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc_hir::lang_items::LangItem;
use rustc_hir::{ItemId, Target, find_attr};
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
use rustc_middle::middle::dependency_format::Dependencies;
use rustc_middle::middle::dependency_format::{Dependencies, Linkage};
use rustc_middle::middle::exported_symbols::{self, SymbolExportKind};
use rustc_middle::middle::lang_items;
use rustc_middle::mir::BinOp;
Expand Down Expand Up @@ -50,7 +50,8 @@ use crate::mir::operand::OperandValue;
use crate::mir::place::PlaceRef;
use crate::traits::*;
use crate::{
CachedModuleCodegen, CodegenLintLevelSpecs, CrateInfo, ModuleCodegen, errors, meth, mir,
CachedModuleCodegen, CodegenLintLevelSpecs, CrateInfo, EiiLinkageImplInfo, EiiLinkageInfo,
ModuleCodegen, errors, meth, mir,
};

pub(crate) fn bin_op_to_icmp_predicate(op: BinOp, signed: bool) -> IntPredicate {
Expand Down Expand Up @@ -902,6 +903,71 @@ pub fn is_call_from_compiler_builtins_to_upstream_monomorphization<'tcx>(
&& !tcx.should_codegen_locally(instance)
}

fn collect_eii_linkage(tcx: TyCtxt<'_>) -> Vec<EiiLinkageInfo> {
#[derive(Debug)]
struct FoundImpl {
imp: EiiImpl,
impl_crate: CrateNum,
}

#[derive(Debug)]
struct FoundEii {
decl: EiiDecl,
impls: FxIndexMap<DefId, FoundImpl>,
}

let mut eiis = FxIndexMap::<DefId, FoundEii>::default();

for &cnum in tcx.crates(()).iter().chain(iter::once(&LOCAL_CRATE)) {
for (&did, &(decl, ref impls)) in tcx.externally_implementable_items(cnum) {
eiis.entry(did)
.or_insert_with(|| FoundEii { decl, impls: Default::default() })
.impls
.extend(
impls
.into_iter()
.map(|(&did, &imp)| (did, FoundImpl { imp, impl_crate: cnum })),
);
}
}

eiis.into_iter()
.filter_map(|(_, FoundEii { decl, impls })| {
let mut explicit_impls = Vec::new();
let mut default_impl = None;

for (impl_did, FoundImpl { imp, impl_crate }) in impls {
let impl_info = EiiLinkageImplInfo { span: tcx.def_span(impl_did), impl_crate };
if imp.is_default {
default_impl = Some(impl_info);
} else {
explicit_impls.push(impl_info);
}
}

// Link time check is only needed when there may be a default impl in a dylib.
// Other cases emit an error in `rustc_passes` already.
if let Some(default_impl) = default_impl {
Some(EiiLinkageInfo {
name: decl.name.name,
impls: explicit_impls,
default_impl: Some(default_impl),
})
} else {
None
}
})
.collect()
}

fn eii_linkage_needed(dependency_formats: &Dependencies) -> bool {
dependency_formats.values().any(|formats| {
formats
.iter()
.any(|&linkage| matches!(linkage, Linkage::Dynamic | Linkage::IncludedFromDylib))
})
}

impl CrateInfo {
pub fn new(tcx: TyCtxt<'_>, target_cpu: String) -> CrateInfo {
let crate_types = tcx.crate_types().to_vec();
Expand All @@ -913,6 +979,12 @@ impl CrateInfo {
crate_types.iter().map(|&c| (c, crate::back::linker::linked_symbols(tcx, c))).collect();
let local_crate_name = tcx.crate_name(LOCAL_CRATE);
let windows_subsystem = find_attr!(tcx, crate, WindowsSubsystem(kind) => *kind);
let dependency_formats = Arc::clone(tcx.dependency_formats(()));
let eii_linkage = if eii_linkage_needed(&dependency_formats) {
collect_eii_linkage(tcx)
} else {
Vec::new()
};

// This list is used when generating the command line to pass through to
// system linker. The linker expects undefined symbols on the left of the
Expand Down Expand Up @@ -957,7 +1029,8 @@ impl CrateInfo {
crate_name: UnordMap::with_capacity(n_crates),
used_crates,
used_crate_source: UnordMap::with_capacity(n_crates),
dependency_formats: Arc::clone(tcx.dependency_formats(())),
dependency_formats,
eii_linkage,
windows_subsystem,
natvis_debugger_visualizers: Default::default(),
lint_level_specs: CodegenLintLevelSpecs::from_tcx(tcx),
Expand Down
18 changes: 17 additions & 1 deletion compiler/rustc_codegen_ssa/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ use rustc_session::Session;
use rustc_session::config::{CrateType, OutputFilenames, OutputType};
use rustc_session::cstore::{self, CrateSource};
use rustc_session::lint::builtin::LINKER_MESSAGES;
use rustc_span::Symbol;
use rustc_span::{Span, Symbol};

pub mod assert_module_sources;
pub mod back;
Expand Down Expand Up @@ -256,6 +256,19 @@ impl SymbolExport {
}
}

#[derive(Clone, Debug, Encodable, Decodable)]
pub struct EiiLinkageImplInfo {
pub span: Span,
pub impl_crate: CrateNum,
}

#[derive(Clone, Debug, Encodable, Decodable)]
pub struct EiiLinkageInfo {
pub name: Symbol,
pub impls: Vec<EiiLinkageImplInfo>,
pub default_impl: Option<EiiLinkageImplInfo>,
}

/// Misc info we load from metadata to persist beyond the tcx.
///
/// Note: though `CrateNum` is only meaningful within the same tcx, information within `CrateInfo`
Expand All @@ -282,6 +295,9 @@ pub struct CrateInfo {
pub used_crate_source: UnordMap<CrateNum, Arc<CrateSource>>,
pub used_crates: Vec<CrateNum>,
pub dependency_formats: Arc<Dependencies>,
/// EII implementations used by the link-time duplicate check, so `-Zno-link` can serialize the data needed by a
/// later `-Zlink-only` invocation.
pub eii_linkage: Vec<EiiLinkageInfo>,
pub windows_subsystem: Option<WindowsSubsystemKind>,
pub natvis_debugger_visualizers: BTreeSet<DebuggerVisualizerFile>,
pub lint_level_specs: CodegenLintLevelSpecs,
Expand Down
63 changes: 63 additions & 0 deletions compiler/rustc_codegen_ssa/src/mir/rvalue.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use itertools::Itertools as _;
use rustc_abi::{self as abi, BackendRepr, FIRST_VARIANT};
use rustc_index::IndexVec;
use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout};
use rustc_middle::ty::{self, Instance, Mutability, Ty, TyCtxt};
Expand All @@ -15,6 +16,64 @@ use crate::traits::*;
use crate::{MemFlags, base};

impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
fn try_codegen_const_aggregate_as_immediate(
&mut self,
bx: &mut Bx,
dest: PlaceRef<'tcx, Bx::Value>,
kind: &mir::AggregateKind<'tcx>,
operands: &IndexVec<abi::FieldIdx, mir::Operand<'tcx>>,
) -> bool {
// Keep this allowlist limited to aggregate kinds with direct codegen coverage.
if !matches!(kind, mir::AggregateKind::Tuple | mir::AggregateKind::Adt(_, _, _, _, None)) {
return false;
}
if !matches!(dest.layout.fields, abi::FieldsShape::Arbitrary { .. }) {
return false;
}
if !matches!(dest.layout.variants, abi::Variants::Single { .. }) {
return false;
}
debug_assert_eq!(operands.len(), dest.layout.fields.count());

let size = dest.layout.size.bytes();
let llty = match size {
1 => bx.cx().type_i8(),
2 => bx.cx().type_i16(),
4 => bx.cx().type_i32(),
8 => bx.cx().type_i64(),
16 => bx.cx().type_i128(),
_ => return false,
};

let mut value = 0u128;
for (field_idx, operand) in operands.iter_enumerated() {
let field_layout = dest.layout.field(bx.cx(), field_idx.as_usize());
if field_layout.is_zst() {
continue;
}
let mir::Operand::Constant(constant) = operand else {
return false;
};
let Some(field_value) = self.eval_mir_constant(constant).try_to_bits(field_layout.size)
else {
return false;
};

let field_size = field_layout.size.bytes();
let field_offset = dest.layout.fields.offset(field_idx.as_usize()).bytes();
debug_assert!(field_offset + field_size <= size);
let shift = match bx.tcx().data_layout.endian {
abi::Endian::Little => field_offset * 8,
abi::Endian::Big => (size - field_offset - field_size) * 8,
};
value |= field_value << shift;
}

let value = bx.cx().const_uint_big(llty, value);
bx.store_to_place(value, dest.val);
true
}

#[instrument(level = "trace", skip(self, bx))]
pub(crate) fn codegen_rvalue(
&mut self,
Expand Down Expand Up @@ -179,6 +238,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
mir::Rvalue::Aggregate(ref kind, ref operands)
if !matches!(**kind, mir::AggregateKind::RawPtr(..)) =>
{
if self.try_codegen_const_aggregate_as_immediate(bx, dest, kind, operands) {
return;
}

let (variant_index, variant_dest, active_field_index) = match **kind {
mir::AggregateKind::Adt(_, variant_index, _, _, active_field_index) => {
let variant_dest = dest.project_downcast(bx, variant_index);
Expand Down
Loading
Loading