Skip to content
Closed
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
1 change: 0 additions & 1 deletion compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use libc::{c_char, c_uint};
use super::ffi::{BasicBlock, Metadata, Module, Type, Value};
use crate::llvm::Bool;

#[link(name = "llvm-wrapper", kind = "static")]
unsafe extern "C" {
// Enzyme
pub(crate) fn LLVMRustHasMetadata(I: &Value, KindID: c_uint) -> bool;
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_codegen_llvm/src/llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1774,7 +1774,6 @@ unsafe extern "C" {
) -> &'ll Metadata;
}

#[link(name = "llvm-wrapper", kind = "static")]
unsafe extern "C" {
pub(crate) fn LLVMRustInstallErrorHandlers();
pub(crate) fn LLVMRustDisableSystemDialogsOnCrash();
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_codegen_ssa/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,6 @@ codegen_ssa_extract_bundled_libs_write_file = failed to write file '{$rlib}': {$

codegen_ssa_failed_to_get_layout = failed to get layout for {$ty}: {$err}

codegen_ssa_failed_to_write = failed to write {$path}: {$error}

codegen_ssa_field_associated_value_expected = associated value expected for `{$name}`

codegen_ssa_forbidden_target_feature_attr =
Expand Down
92 changes: 3 additions & 89 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ use rustc_middle::bug;
use rustc_middle::lint::lint_level;
use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
use rustc_middle::middle::dependency_format::Linkage;
use rustc_middle::middle::exported_symbols::SymbolExportKind;
use rustc_session::config::{
self, CFGuard, CrateType, DebugInfo, LinkerFeaturesCli, OutFileName, OutputFilenames,
OutputType, PrintKind, SplitDwarfKind, Strip,
Expand Down Expand Up @@ -2054,84 +2053,6 @@ fn add_post_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor
}
}

/// Add a synthetic object file that contains reference to all symbols that we want to expose to
/// the linker.
///
/// Background: we implement rlibs as static library (archives). Linkers treat archives
/// differently from object files: all object files participate in linking, while archives will
/// only participate in linking if they can satisfy at least one undefined reference (version
/// scripts doesn't count). This causes `#[no_mangle]` or `#[used]` items to be ignored by the
/// linker, and since they never participate in the linking, using `KEEP` in the linker scripts
/// can't keep them either. This causes #47384.
///
/// To keep them around, we could use `--whole-archive` and equivalents to force rlib to
/// participate in linking like object files, but this proves to be expensive (#93791). Therefore
/// we instead just introduce an undefined reference to them. This could be done by `-u` command
/// line option to the linker or `EXTERN(...)` in linker scripts, however they does not only
/// introduce an undefined reference, but also make them the GC roots, preventing `--gc-sections`
/// from removing them, and this is especially problematic for embedded programming where every
/// byte counts.
///
/// This method creates a synthetic object file, which contains undefined references to all symbols
/// that are necessary for the linking. They are only present in symbol table but not actually
/// used in any sections, so the linker will therefore pick relevant rlibs for linking, but
/// unused `#[no_mangle]` or `#[used]` can still be discard by GC sections.
///
/// There's a few internal crates in the standard library (aka libcore and
/// libstd) which actually have a circular dependence upon one another. This
/// currently arises through "weak lang items" where libcore requires things
/// like `rust_begin_unwind` but libstd ends up defining it. To get this
/// circular dependence to work correctly we declare some of these things
/// in this synthetic object.
fn add_linked_symbol_object(
cmd: &mut dyn Linker,
sess: &Session,
tmpdir: &Path,
symbols: &[(String, SymbolExportKind)],
) {
if symbols.is_empty() {
return;
}

let Some(mut file) = super::metadata::create_object_file(sess) else {
return;
};

if file.format() == object::BinaryFormat::Coff {
// NOTE(nbdd0121): MSVC will hang if the input object file contains no sections,
// so add an empty section.
file.add_section(Vec::new(), ".text".into(), object::SectionKind::Text);

// We handle the name decoration of COFF targets in `symbol_export.rs`, so disable the
// default mangler in `object` crate.
file.set_mangling(object::write::Mangling::None);
}

for (sym, kind) in symbols.iter() {
file.add_symbol(object::write::Symbol {
name: sym.clone().into(),
value: 0,
size: 0,
kind: match kind {
SymbolExportKind::Text => object::SymbolKind::Text,
SymbolExportKind::Data => object::SymbolKind::Data,
SymbolExportKind::Tls => object::SymbolKind::Tls,
},
scope: object::SymbolScope::Unknown,
weak: false,
section: object::write::SymbolSection::Undefined,
flags: object::SymbolFlags::None,
});
}

let path = tmpdir.join("symbols.o");
let result = std::fs::write(&path, file.write().unwrap());
if let Err(error) = result {
sess.dcx().emit_fatal(errors::FailedToWrite { path, error });
}
cmd.add_object(&path);
}

/// Add object files containing code from the current crate.
fn add_local_crate_regular_objects(cmd: &mut dyn Linker, codegen_results: &CodegenResults) {
for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) {
Expand Down Expand Up @@ -2289,13 +2210,6 @@ fn linker_with_args(
// Pre-link CRT objects.
add_pre_link_objects(cmd, sess, flavor, link_output_kind, self_contained_crt_objects);

add_linked_symbol_object(
cmd,
sess,
tmpdir,
&codegen_results.crate_info.linked_symbols[&crate_type],
);

// Sanitizer libraries.
add_sanitizer_libraries(sess, flavor, crate_type, cmd);

Expand Down Expand Up @@ -2684,7 +2598,7 @@ fn add_native_libs_from_crate(
NativeLibKind::Static { bundle, whole_archive } => {
if link_static {
let bundle = bundle.unwrap_or(true);
let whole_archive = whole_archive == Some(true);
let whole_archive = whole_archive.unwrap_or(link_output_kind.is_dylib());
if bundle && cnum != LOCAL_CRATE {
if let Some(filename) = lib.filename {
// If rlib contains native libs as archives, they are unpacked to tmpdir.
Expand All @@ -2706,7 +2620,7 @@ fn add_native_libs_from_crate(
// link kind is unspecified.
if !link_output_kind.can_link_dylib() && !sess.target.crt_static_allows_dylibs {
if link_static {
cmd.link_staticlib_by_name(name, verbatim, false);
cmd.link_staticlib_by_name(name, verbatim, link_output_kind.is_dylib());
}
} else if link_dynamic {
cmd.link_dylib_by_name(name, verbatim, true);
Expand Down Expand Up @@ -2956,7 +2870,7 @@ fn add_static_crate(
let cratepath = &src.rlib.as_ref().unwrap().0;

let mut link_upstream =
|path: &Path| cmd.link_staticlib_by_path(&rehome_lib_path(sess, path), false);
|path: &Path| cmd.link_staticlib_by_path(&rehome_lib_path(sess, path), true);

if !are_upstream_rust_objects_already_included(sess)
|| ignored_for_lto(sess, &codegen_results.crate_info, cnum)
Expand Down
28 changes: 1 addition & 27 deletions compiler/rustc_codegen_ssa/src/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use rustc_metadata::{
use rustc_middle::bug;
use rustc_middle::middle::dependency_format::Linkage;
use rustc_middle::middle::exported_symbols;
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo, SymbolExportKind};
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel, Strip};
Expand Down Expand Up @@ -1808,32 +1808,6 @@ fn exported_symbols_for_proc_macro_crate(tcx: TyCtxt<'_>) -> Vec<String> {
vec![proc_macro_decls_name, metadata_symbol_name]
}

pub(crate) fn linked_symbols(
tcx: TyCtxt<'_>,
crate_type: CrateType,
) -> Vec<(String, SymbolExportKind)> {
match crate_type {
CrateType::Executable | CrateType::Cdylib | CrateType::Dylib => (),
CrateType::Staticlib | CrateType::ProcMacro | CrateType::Rlib => {
return Vec::new();
}
}

let mut symbols = Vec::new();

let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);
for_each_exported_symbols_include_dep(tcx, crate_type, |symbol, info, cnum| {
if info.level.is_below_threshold(export_threshold) || info.used {
symbols.push((
symbol_export::linking_symbol_name_for_instance_in_crate(tcx, symbol, cnum),
info.kind,
));
}
});

symbols
}

/// Much simplified and explicit CLI for the NVPTX linker. The linker operates
/// with bitcode and uses LLVM backend to generate a PTX assembly.
struct PtxLinker<'a> {
Expand Down
54 changes: 0 additions & 54 deletions compiler/rustc_codegen_ssa/src/back/symbol_export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -621,60 +621,6 @@ fn calling_convention_for_symbol<'tcx>(
.unwrap_or((Conv::Rust, &[]))
}

/// This is the symbol name of the given instance as seen by the linker.
///
/// On 32-bit Windows symbols are decorated according to their calling conventions.
pub(crate) fn linking_symbol_name_for_instance_in_crate<'tcx>(
tcx: TyCtxt<'tcx>,
symbol: ExportedSymbol<'tcx>,
instantiating_crate: CrateNum,
) -> String {
let mut undecorated = symbol_name_for_instance_in_crate(tcx, symbol, instantiating_crate);

// thread local will not be a function call,
// so it is safe to return before windows symbol decoration check.
if let Some(name) = maybe_emutls_symbol_name(tcx, symbol, &undecorated) {
return name;
}

let target = &tcx.sess.target;
if !target.is_like_windows {
// Mach-O has a global "_" suffix and `object` crate will handle it.
// ELF does not have any symbol decorations.
return undecorated;
}

let prefix = match &target.arch[..] {
"x86" => Some('_'),
"x86_64" => None,
"arm64ec" => Some('#'),
// Only x86/64 use symbol decorations.
_ => return undecorated,
};

let (conv, args) = calling_convention_for_symbol(tcx, symbol);

// Decorate symbols with prefixes, suffixes and total number of bytes of arguments.
// Reference: https://docs.microsoft.com/en-us/cpp/build/reference/decorated-names?view=msvc-170
let (prefix, suffix) = match conv {
Conv::X86Fastcall => ("@", "@"),
Conv::X86Stdcall => ("_", "@"),
Conv::X86VectorCall => ("", "@@"),
_ => {
if let Some(prefix) = prefix {
undecorated.insert(0, prefix);
}
return undecorated;
}
};

let args_in_bytes: u64 = args
.iter()
.map(|abi| abi.layout.size.bytes().next_multiple_of(target.pointer_width as u64 / 8))
.sum();
format!("{prefix}{undecorated}{suffix}{args_in_bytes}")
}

pub(crate) fn exporting_symbol_name_for_instance_in_crate<'tcx>(
tcx: TyCtxt<'tcx>,
symbol: ExportedSymbol<'tcx>,
Expand Down
62 changes: 4 additions & 58 deletions compiler/rustc_codegen_ssa/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use std::time::{Duration, Instant};

use itertools::Itertools;
use rustc_abi::FIRST_VARIANT;
use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, AllocatorKind, global_fn_name};
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
use rustc_ast::expand::allocator::AllocatorKind;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
use rustc_data_structures::sync::par_map;
use rustc_data_structures::unord::UnordMap;
Expand All @@ -16,23 +16,21 @@ use rustc_metadata::EncodedMetadata;
use rustc_middle::bug;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::middle::debugger_visualizer::{DebuggerVisualizerFile, DebuggerVisualizerType};
use rustc_middle::middle::exported_symbols::SymbolExportKind;
use rustc_middle::middle::{exported_symbols, lang_items};
use rustc_middle::middle::exported_symbols;
use rustc_middle::mir::BinOp;
use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem, MonoItemPartitions};
use rustc_middle::query::Providers;
use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout};
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
use rustc_session::Session;
use rustc_session::config::{self, CrateType, EntryFnType, OutputType};
use rustc_span::{DUMMY_SP, Symbol, sym};
use rustc_span::{DUMMY_SP, sym};
use rustc_trait_selection::infer::{BoundRegionConversionTime, TyCtxtInferExt};
use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
use tracing::{debug, info};
use {rustc_ast as ast, rustc_attr_parsing as attr};

use crate::assert_module_sources::CguReuse;
use crate::back::link::are_upstream_rust_objects_already_included;
use crate::back::metadata::create_compressed_metadata_file;
use crate::back::write::{
ComputedLtoType, OngoingCodegen, compute_per_cgu_lto_type, start_async_codegen,
Expand Down Expand Up @@ -872,8 +870,6 @@ impl CrateInfo {
.iter()
.map(|&c| (c, crate::back::linker::exported_symbols(tcx, c)))
.collect();
let linked_symbols =
crate_types.iter().map(|&c| (c, crate::back::linker::linked_symbols(tcx, c))).collect();
let local_crate_name = tcx.crate_name(LOCAL_CRATE);
let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
let subsystem =
Expand Down Expand Up @@ -918,7 +914,6 @@ impl CrateInfo {
target_features: tcx.global_backend_features(()).clone(),
crate_types,
exported_symbols,
linked_symbols,
local_crate_name,
compiler_builtins,
profiler_runtime: None,
Expand Down Expand Up @@ -960,55 +955,6 @@ impl CrateInfo {
// and we assume that they cannot define weak lang items. This is not currently enforced
// by the compiler, but that's ok because all this stuff is unstable anyway.
let target = &tcx.sess.target;
if !are_upstream_rust_objects_already_included(tcx.sess) {
let missing_weak_lang_items: FxIndexSet<Symbol> = info
.used_crates
.iter()
.flat_map(|&cnum| tcx.missing_lang_items(cnum))
.filter(|l| l.is_weak())
.filter_map(|&l| {
let name = l.link_name()?;
lang_items::required(tcx, l).then_some(name)
})
.collect();
let prefix = match (target.is_like_windows, target.arch.as_ref()) {
(true, "x86") => "_",
(true, "arm64ec") => "#",
_ => "",
};

// This loop only adds new items to values of the hash map, so the order in which we
// iterate over the values is not important.
#[allow(rustc::potential_query_instability)]
info.linked_symbols
.iter_mut()
.filter(|(crate_type, _)| {
!matches!(crate_type, CrateType::Rlib | CrateType::Staticlib)
})
.for_each(|(_, linked_symbols)| {
let mut symbols = missing_weak_lang_items
.iter()
.map(|item| (format!("{prefix}{item}"), SymbolExportKind::Text))
.collect::<Vec<_>>();
symbols.sort_unstable_by(|a, b| a.0.cmp(&b.0));
linked_symbols.extend(symbols);
if tcx.allocator_kind(()).is_some() {
// At least one crate needs a global allocator. This crate may be placed
// after the crate that defines it in the linker order, in which case some
// linkers return an error. By adding the global allocator shim methods to
// the linked_symbols list, linking the generated symbols.o will ensure that
// circular dependencies involving the global allocator don't lead to linker
// errors.
linked_symbols.extend(ALLOCATOR_METHODS.iter().map(|method| {
(
format!("{prefix}{}", global_fn_name(method.name).as_str()),
SymbolExportKind::Text,
)
}));
}
});
}

let embed_visualizers = tcx.crate_types().iter().any(|&crate_type| match crate_type {
CrateType::Executable | CrateType::Dylib | CrateType::Cdylib => {
// These are crate types for which we invoke the linker and can embed
Expand Down
7 changes: 0 additions & 7 deletions compiler/rustc_codegen_ssa/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -586,13 +586,6 @@ pub(crate) struct LinkScriptWriteFailure {
pub error: Error,
}

#[derive(Diagnostic)]
#[diag(codegen_ssa_failed_to_write)]
pub(crate) struct FailedToWrite {
pub path: PathBuf,
pub error: Error,
}

#[derive(Diagnostic)]
#[diag(codegen_ssa_unable_to_write_debugger_visualizer)]
pub(crate) struct UnableToWriteDebuggerVisualizer {
Expand Down
Loading
Loading