Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 7 pull requests #95913

Closed
wants to merge 22 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
ad430f5
rename compiler-flags to compile-flags
compiler-errors Feb 22, 2022
52dd0b6
reject compiler-flags as a compiletest attribute
compiler-errors Feb 22, 2022
a867b8d
Add a test for issue 47384
nbdd0121 Feb 9, 2022
aa8413c
Add `SymbolExportInfo`
nbdd0121 Apr 2, 2022
08b7029
Make `#[used]` considered reachable
nbdd0121 Apr 2, 2022
fefc69a
Synthesis object file for `#[used]` and exported symbols
nbdd0121 Apr 2, 2022
3730fe3
Ignore paths in temporary dir in reproducible build test
nbdd0121 Apr 2, 2022
77f610e
Note that CI tests Windows 10
ChrisDenton Apr 9, 2022
bf3ef0d
Switch to the 'normal' basic block for writing asm outputs if needed.
luqmana Apr 9, 2022
0b2f360
Update asm-may_unwind test to handle use of asm with outputs.
luqmana Apr 9, 2022
460054c
Add a note to reachable.rs about `#[used]`
nbdd0121 Apr 9, 2022
98cd818
Refactor exported_symbols and linked_symbols for code reuse
nbdd0121 Apr 10, 2022
80152ed
use `to_string` instead of `format!`
TaKO8Ki Apr 10, 2022
386ca6a
Allow usage of sudo while not accessing root
Apr 10, 2022
dfe13db
only suggest removing semicolon when expr implements trait
compiler-errors Apr 7, 2022
d10673b
Rollup merge of #94243 - compiler-errors:compiler-flags-typo, r=Mark-…
Dylan-DPC Apr 11, 2022
f138648
Rollup merge of #95604 - nbdd0121:used2, r=petrochenkov
Dylan-DPC Apr 11, 2022
365cc2f
Rollup merge of #95671 - gimbles:master, r=Mark-Simulacrum
Dylan-DPC Apr 11, 2022
16461fd
Rollup merge of #95758 - compiler-errors:issue-54771, r=estebank
Dylan-DPC Apr 11, 2022
de7adb4
Rollup merge of #95861 - ChrisDenton:windows7-support, r=Dylan-DPC
Dylan-DPC Apr 11, 2022
5470c2c
Rollup merge of #95864 - luqmana:inline-asm-unwind-store-miscompile, …
Dylan-DPC Apr 11, 2022
1664dcf
Rollup merge of #95881 - TaKO8Ki:use-to-string-instead-of-format, r=c…
Dylan-DPC Apr 11, 2022
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
5 changes: 5 additions & 0 deletions compiler/rustc_codegen_llvm/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,11 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
}
attributes::apply_to_callsite(result, llvm::AttributePlace::Function, &{ attrs });

// Switch to the 'normal' basic block if we did an `invoke` instead of a `call`
if let Some((dest, _, _)) = dest_catch_funclet {
self.switch_to_block(dest);
}

// Write results to outputs
for (idx, op) in operands.iter().enumerate() {
if let InlineAsmOperandRef::Out { reg, place: Some(place), .. }
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_codegen_llvm/src/back/lto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use rustc_errors::{FatalError, Handler};
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_middle::bug;
use rustc_middle::dep_graph::WorkProduct;
use rustc_middle::middle::exported_symbols::SymbolExportLevel;
use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel};
use rustc_session::cgu_reuse_tracker::CguReuse;
use rustc_session::config::{self, CrateType, Lto};
use tracing::{debug, info};
Expand Down Expand Up @@ -55,8 +55,8 @@ fn prepare_lto(
Lto::No => panic!("didn't request LTO but we're doing LTO"),
};

let symbol_filter = &|&(ref name, level): &(String, SymbolExportLevel)| {
if level.is_below_threshold(export_threshold) {
let symbol_filter = &|&(ref name, info): &(String, SymbolExportInfo)| {
if info.level.is_below_threshold(export_threshold) {
Some(CString::new(name.as_str()).unwrap())
} else {
None
Expand Down
69 changes: 69 additions & 0 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use rustc_errors::{ErrorGuaranteed, Handler};
use rustc_fs_util::fix_windows_verbatim_for_gcc;
use rustc_hir::def_id::CrateNum;
use rustc_middle::middle::dependency_format::Linkage;
use rustc_middle::middle::exported_symbols::SymbolExportKind;
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip};
use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, SplitDwarfKind};
use rustc_session::cstore::DllImport;
Expand Down Expand Up @@ -1655,6 +1656,67 @@ 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.
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;
};

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(e) = result {
sess.fatal(&format!("failed to write {}: {}", path.display(), e));
}
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 @@ -1798,6 +1860,13 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
// Sanitizer libraries.
add_sanitizer_libraries(sess, crate_type, cmd);

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

// Object code from the current crate.
// Take careful note of the ordering of the arguments we pass to the linker
// here. Linkers will assume that things on the left depend on things to the
Expand Down
72 changes: 50 additions & 22 deletions compiler/rustc_codegen_ssa/src/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use std::{env, mem, str};

use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
use rustc_middle::middle::dependency_format::Linkage;
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo, SymbolExportKind};
use rustc_middle::ty::TyCtxt;
use rustc_serialize::{json, Encoder};
use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel, Strip};
Expand Down Expand Up @@ -1518,6 +1519,29 @@ impl<'a> L4Bender<'a> {
}
}

fn for_each_exported_symbols_include_dep<'tcx>(
tcx: TyCtxt<'tcx>,
crate_type: CrateType,
mut callback: impl FnMut(ExportedSymbol<'tcx>, SymbolExportInfo, CrateNum),
) {
for &(symbol, info) in tcx.exported_symbols(LOCAL_CRATE).iter() {
callback(symbol, info, LOCAL_CRATE);
}

let formats = tcx.dependency_formats(());
let deps = formats.iter().find_map(|(t, list)| (*t == crate_type).then_some(list)).unwrap();

for (index, dep_format) in deps.iter().enumerate() {
let cnum = CrateNum::new(index + 1);
// For each dependency that we are linking to statically ...
if *dep_format == Linkage::Static {
for &(symbol, info) in tcx.exported_symbols(cnum).iter() {
callback(symbol, info, cnum);
}
}
}
}

pub(crate) fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> {
if let Some(ref exports) = tcx.sess.target.override_export_symbols {
return exports.iter().map(ToString::to_string).collect();
Expand All @@ -1526,34 +1550,38 @@ pub(crate) fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<St
let mut symbols = Vec::new();

let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);
for &(symbol, level) in tcx.exported_symbols(LOCAL_CRATE).iter() {
if level.is_below_threshold(export_threshold) {
symbols.push(symbol_export::symbol_name_for_instance_in_crate(
tcx,
symbol,
LOCAL_CRATE,
));
for_each_exported_symbols_include_dep(tcx, crate_type, |symbol, info, cnum| {
if info.level.is_below_threshold(export_threshold) {
symbols.push(symbol_export::symbol_name_for_instance_in_crate(tcx, symbol, cnum));
}
}
});

let formats = tcx.dependency_formats(());
let deps = formats.iter().find_map(|(t, list)| (*t == crate_type).then_some(list)).unwrap();

for (index, dep_format) in deps.iter().enumerate() {
let cnum = CrateNum::new(index + 1);
// For each dependency that we are linking to statically ...
if *dep_format == Linkage::Static {
// ... we add its symbol list to our export list.
for &(symbol, level) in tcx.exported_symbols(cnum).iter() {
if !level.is_below_threshold(export_threshold) {
continue;
}
symbols
}

symbols.push(symbol_export::symbol_name_for_instance_in_crate(tcx, symbol, cnum));
}
pub(crate) fn linked_symbols(
tcx: TyCtxt<'_>,
crate_type: CrateType,
) -> Vec<(String, SymbolExportKind)> {
match crate_type {
CrateType::Executable | CrateType::Cdylib => (),
CrateType::Staticlib | CrateType::ProcMacro | CrateType::Rlib | CrateType::Dylib => {
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::symbol_name_for_instance_in_crate(tcx, symbol, cnum),
info.kind,
));
}
});

symbols
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_ssa/src/back/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ fn search_for_metadata<'a>(
.map_err(|e| format!("failed to read {} section in '{}': {}", section, path.display(), e))
}

fn create_object_file(sess: &Session) -> Option<write::Object<'static>> {
pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static>> {
let endianness = match sess.target.options.endian {
Endian::Little => Endianness::Little,
Endian::Big => Endianness::Big,
Expand Down
Loading