Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 2a544ab

Browse files
committedJan 22, 2025
Target modifiers (special marked options) are recorded in metainfo and compared to be equal in different crates
1 parent 341f603 commit 2a544ab

22 files changed

+656
-24
lines changed
 

‎compiler/rustc_interface/src/passes.rs

+1
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ fn configure_and_expand(
269269

270270
resolver.resolve_crate(&krate);
271271

272+
CStore::from_tcx(tcx).report_incompatible_target_modifiers(tcx, &krate);
272273
krate
273274
}
274275

‎compiler/rustc_metadata/messages.ftl

+10
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,14 @@ metadata_incompatible_rustc =
113113
found crate `{$crate_name}` compiled by an incompatible version of rustc{$add_info}
114114
.help = please recompile that crate using this compiler ({$rustc_version}) (consider running `cargo clean` first)
115115
116+
metadata_incompatible_target_modifiers =
117+
mixing `{$flag_name_prefixed}` will cause an ABI mismatch in crate `{$local_crate}`
118+
.note = `{$flag_name_prefixed}={$flag_local_value}` in this crate is incompatible with `{$flag_name_prefixed}={$flag_extern_value}` in dependency `{$extern_crate}`
119+
.help = the `{$flag_name_prefixed}` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely
120+
121+
metadata_incompatible_target_modifiers_help_allow = if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch={$flag_name}` to silence this error
122+
metadata_incompatible_target_modifiers_help_fix = set `{$flag_name_prefixed}={$flag_extern_value}` in this crate or `{$flag_name_prefixed}={$flag_local_value}` in `{$extern_crate}`
123+
116124
metadata_incompatible_wasm_link =
117125
`wasm_import_module` is incompatible with other arguments in `#[link]` attributes
118126
@@ -284,6 +292,8 @@ metadata_unknown_link_kind =
284292
metadata_unknown_link_modifier =
285293
unknown linking modifier `{$modifier}`, expected one of: bundle, verbatim, whole-archive, as-needed
286294
295+
metadata_unknown_target_modifier_unsafe_allowed = unknown target modifier `{$flag_name}`, requested by `-Cunsafe-allow-abi-mismatch={$flag_name}`
296+
287297
metadata_unsupported_abi =
288298
ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture
289299

‎compiler/rustc_metadata/src/creader.rs

+118-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ use rustc_hir::definitions::Definitions;
2323
use rustc_index::IndexVec;
2424
use rustc_middle::bug;
2525
use rustc_middle::ty::{TyCtxt, TyCtxtFeed};
26-
use rustc_session::config::{self, CrateType, ExternLocation};
26+
use rustc_session::config::{
27+
self, CrateType, ExtendedTargetModifierInfo, ExternLocation, OptionsTargetModifiers,
28+
TargetModifier,
29+
};
2730
use rustc_session::cstore::{CrateDepKind, CrateSource, ExternCrate, ExternCrateSource};
2831
use rustc_session::lint::{self, BuiltinLintDiag};
2932
use rustc_session::output::validate_crate_name;
@@ -35,7 +38,9 @@ use tracing::{debug, info, trace};
3538

3639
use crate::errors;
3740
use crate::locator::{CrateError, CrateLocator, CratePaths};
38-
use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob};
41+
use crate::rmeta::{
42+
CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob, TargetModifiers,
43+
};
3944

4045
/// The backend's way to give the crate store access to the metadata in a library.
4146
/// Note that it returns the raw metadata bytes stored in the library file, whether
@@ -296,6 +301,96 @@ impl CStore {
296301
}
297302
}
298303

304+
fn report_target_modifiers_extended(
305+
tcx: TyCtxt<'_>,
306+
krate: &Crate,
307+
mods: &Vec<TargetModifier>,
308+
data: &CrateMetadata,
309+
) {
310+
let span = krate.spans.inner_span.shrink_to_lo();
311+
let allowed_flag_mismatches = &tcx.sess.opts.cg.unsafe_allow_abi_mismatch;
312+
let name = tcx.crate_name(LOCAL_CRATE);
313+
let tmod_extender = |tmod: &TargetModifier| (tmod.extend(), tmod.clone());
314+
let report_diff = |prefix: &String,
315+
opt_name: &String,
316+
flag_local_value: &String,
317+
flag_extern_value: &String| {
318+
if allowed_flag_mismatches.contains(&opt_name) {
319+
return;
320+
}
321+
tcx.dcx().emit_err(errors::IncompatibleTargetModifiers {
322+
span,
323+
extern_crate: data.name(),
324+
local_crate: name,
325+
flag_name: opt_name.clone(),
326+
flag_name_prefixed: format!("-{}{}", prefix, opt_name),
327+
flag_local_value: flag_local_value.to_string(),
328+
flag_extern_value: flag_extern_value.to_string(),
329+
});
330+
};
331+
let mut it1 = mods.iter().map(tmod_extender);
332+
let mut it2 = data.target_modifiers().iter().map(tmod_extender);
333+
let mut left_name_val: Option<(ExtendedTargetModifierInfo, TargetModifier)> = None;
334+
let mut right_name_val: Option<(ExtendedTargetModifierInfo, TargetModifier)> = None;
335+
let no_val = "*".to_string();
336+
loop {
337+
left_name_val = left_name_val.or_else(|| it1.next());
338+
right_name_val = right_name_val.or_else(|| it2.next());
339+
match (&left_name_val, &right_name_val) {
340+
(Some(l), Some(r)) => match l.1.opt.cmp(&r.1.opt) {
341+
cmp::Ordering::Equal => {
342+
if l.0.tech_value != r.0.tech_value {
343+
report_diff(&l.0.prefix, &l.0.name, &l.1.value_name, &r.1.value_name);
344+
}
345+
left_name_val = None;
346+
right_name_val = None;
347+
}
348+
cmp::Ordering::Greater => {
349+
report_diff(&r.0.prefix, &r.0.name, &no_val, &r.1.value_name);
350+
right_name_val = None;
351+
}
352+
cmp::Ordering::Less => {
353+
report_diff(&l.0.prefix, &l.0.name, &l.1.value_name, &no_val);
354+
left_name_val = None;
355+
}
356+
},
357+
(Some(l), None) => {
358+
report_diff(&l.0.prefix, &l.0.name, &l.1.value_name, &no_val);
359+
left_name_val = None;
360+
}
361+
(None, Some(r)) => {
362+
report_diff(&r.0.prefix, &r.0.name, &no_val, &r.1.value_name);
363+
right_name_val = None;
364+
}
365+
(None, None) => break,
366+
}
367+
}
368+
}
369+
370+
pub fn report_incompatible_target_modifiers(&self, tcx: TyCtxt<'_>, krate: &Crate) {
371+
for flag_name in &tcx.sess.opts.cg.unsafe_allow_abi_mismatch {
372+
if !OptionsTargetModifiers::is_target_modifier(flag_name) {
373+
tcx.dcx().emit_err(errors::UnknownTargetModifierUnsafeAllowed {
374+
span: krate.spans.inner_span.shrink_to_lo(),
375+
flag_name: flag_name.clone(),
376+
});
377+
}
378+
}
379+
380+
if tcx.crate_types().contains(&CrateType::ProcMacro) {
381+
return;
382+
}
383+
let mods = tcx.sess.opts.gather_target_modifiers();
384+
for (_cnum, data) in self.iter_crate_data() {
385+
if data.is_proc_macro_crate() {
386+
continue;
387+
}
388+
if mods != *data.target_modifiers() {
389+
Self::report_target_modifiers_extended(tcx, krate, &mods, data);
390+
}
391+
}
392+
}
393+
299394
pub fn new(metadata_loader: Box<MetadataLoaderDyn>) -> CStore {
300395
CStore {
301396
metadata_loader,
@@ -470,6 +565,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
470565
};
471566

472567
let cnum_map = self.resolve_crate_deps(dep_root, &crate_root, &metadata, cnum, dep_kind)?;
568+
let target_modifiers = self.resolve_target_modifiers(&crate_root, &metadata, cnum)?;
473569

474570
let raw_proc_macros = if crate_root.is_proc_macro_crate() {
475571
let temp_root;
@@ -494,6 +590,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
494590
raw_proc_macros,
495591
cnum,
496592
cnum_map,
593+
target_modifiers,
497594
dep_kind,
498595
source,
499596
private_dep,
@@ -737,6 +834,25 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
737834
Ok(crate_num_map)
738835
}
739836

837+
fn resolve_target_modifiers(
838+
&mut self,
839+
crate_root: &CrateRoot,
840+
metadata: &MetadataBlob,
841+
krate: CrateNum,
842+
) -> Result<TargetModifiers, CrateError> {
843+
debug!("resolving target modifiers of external crate");
844+
if crate_root.is_proc_macro_crate() {
845+
return Ok(TargetModifiers::new());
846+
}
847+
let mods = crate_root.decode_target_modifiers(metadata);
848+
let mut target_modifiers = TargetModifiers::with_capacity(mods.len());
849+
for modifier in mods {
850+
target_modifiers.push(modifier);
851+
}
852+
debug!("resolve_target_modifiers: target mods for {:?} is {:?}", krate, target_modifiers);
853+
Ok(target_modifiers)
854+
}
855+
740856
fn dlsym_proc_macros(
741857
&self,
742858
path: &Path,

‎compiler/rustc_metadata/src/errors.rs

+25
Original file line numberDiff line numberDiff line change
@@ -732,3 +732,28 @@ pub struct ImportNameTypeRaw {
732732
#[primary_span]
733733
pub span: Span,
734734
}
735+
736+
#[derive(Diagnostic)]
737+
#[diag(metadata_incompatible_target_modifiers)]
738+
#[help]
739+
#[note]
740+
#[help(metadata_incompatible_target_modifiers_help_fix)]
741+
#[help(metadata_incompatible_target_modifiers_help_allow)]
742+
pub struct IncompatibleTargetModifiers {
743+
#[primary_span]
744+
pub span: Span,
745+
pub extern_crate: Symbol,
746+
pub local_crate: Symbol,
747+
pub flag_name: String,
748+
pub flag_name_prefixed: String,
749+
pub flag_local_value: String,
750+
pub flag_extern_value: String,
751+
}
752+
753+
#[derive(Diagnostic)]
754+
#[diag(metadata_unknown_target_modifier_unsafe_allowed)]
755+
pub struct UnknownTargetModifierUnsafeAllowed {
756+
#[primary_span]
757+
pub span: Span,
758+
pub flag_name: String,
759+
}

‎compiler/rustc_metadata/src/rmeta/decoder.rs

+19
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use rustc_middle::{bug, implement_ty_decoder};
2929
use rustc_serialize::opaque::MemDecoder;
3030
use rustc_serialize::{Decodable, Decoder};
3131
use rustc_session::Session;
32+
use rustc_session::config::TargetModifier;
3233
use rustc_session::cstore::{CrateSource, ExternCrate};
3334
use rustc_span::hygiene::HygieneDecodeContext;
3435
use rustc_span::{BytePos, DUMMY_SP, Pos, SpanData, SpanDecoder, SyntaxContext, kw};
@@ -73,6 +74,9 @@ impl MetadataBlob {
7374
/// own crate numbers.
7475
pub(crate) type CrateNumMap = IndexVec<CrateNum, CrateNum>;
7576

77+
/// Target modifiers - abi or exploit mitigations flags
78+
pub(crate) type TargetModifiers = Vec<TargetModifier>;
79+
7680
pub(crate) struct CrateMetadata {
7781
/// The primary crate data - binary metadata blob.
7882
blob: MetadataBlob,
@@ -110,6 +114,8 @@ pub(crate) struct CrateMetadata {
110114
cnum_map: CrateNumMap,
111115
/// Same ID set as `cnum_map` plus maybe some injected crates like panic runtime.
112116
dependencies: Vec<CrateNum>,
117+
/// Target modifiers - abi and exploit mitigation flags the crate was compiled with
118+
target_modifiers: TargetModifiers,
113119
/// How to link (or not link) this crate to the currently compiled crate.
114120
dep_kind: CrateDepKind,
115121
/// Filesystem location of this crate.
@@ -961,6 +967,13 @@ impl CrateRoot {
961967
) -> impl ExactSizeIterator<Item = CrateDep> + Captures<'a> {
962968
self.crate_deps.decode(metadata)
963969
}
970+
971+
pub(crate) fn decode_target_modifiers<'a>(
972+
&self,
973+
metadata: &'a MetadataBlob,
974+
) -> impl ExactSizeIterator<Item = TargetModifier> + Captures<'a> {
975+
self.target_modifiers.decode(metadata)
976+
}
964977
}
965978

966979
impl<'a> CrateMetadataRef<'a> {
@@ -1823,6 +1836,7 @@ impl CrateMetadata {
18231836
raw_proc_macros: Option<&'static [ProcMacro]>,
18241837
cnum: CrateNum,
18251838
cnum_map: CrateNumMap,
1839+
target_modifiers: TargetModifiers,
18261840
dep_kind: CrateDepKind,
18271841
source: CrateSource,
18281842
private_dep: bool,
@@ -1854,6 +1868,7 @@ impl CrateMetadata {
18541868
cnum,
18551869
cnum_map,
18561870
dependencies,
1871+
target_modifiers,
18571872
dep_kind,
18581873
source: Lrc::new(source),
18591874
private_dep,
@@ -1883,6 +1898,10 @@ impl CrateMetadata {
18831898
self.dependencies.push(cnum);
18841899
}
18851900

1901+
pub(crate) fn target_modifiers(&self) -> &TargetModifiers {
1902+
&self.target_modifiers
1903+
}
1904+
18861905
pub(crate) fn update_extern_crate(&mut self, new_extern_crate: ExternCrate) -> bool {
18871906
let update =
18881907
Some(new_extern_crate.rank()) > self.extern_crate.as_ref().map(ExternCrate::rank);

‎compiler/rustc_metadata/src/rmeta/encoder.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use rustc_middle::ty::{AssocItemContainer, SymbolName};
2525
use rustc_middle::util::common::to_readable_str;
2626
use rustc_middle::{bug, span_bug};
2727
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, opaque};
28-
use rustc_session::config::{CrateType, OptLevel};
28+
use rustc_session::config::{CrateType, OptLevel, TargetModifier};
2929
use rustc_span::hygiene::HygieneEncodeContext;
3030
use rustc_span::{
3131
ExternalSource, FileName, SourceFile, SpanData, SpanEncoder, StableSourceFileId, SyntaxContext,
@@ -692,6 +692,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
692692
// Encode source_map. This needs to be done last, because encoding `Span`s tells us which
693693
// `SourceFiles` we actually need to encode.
694694
let source_map = stat!("source-map", || self.encode_source_map());
695+
let target_modifiers = stat!("target-modifiers", || self.encode_target_modifiers());
695696

696697
let root = stat!("final", || {
697698
let attrs = tcx.hir().krate_attrs();
@@ -735,6 +736,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
735736
native_libraries,
736737
foreign_modules,
737738
source_map,
739+
target_modifiers,
738740
traits,
739741
impls,
740742
incoherent_impls,
@@ -2009,6 +2011,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
20092011
self.lazy_array(deps.iter().map(|(_, dep)| dep))
20102012
}
20112013

2014+
fn encode_target_modifiers(&mut self) -> LazyArray<TargetModifier> {
2015+
empty_proc_macro!(self);
2016+
let tcx = self.tcx;
2017+
self.lazy_array(tcx.sess.opts.gather_target_modifiers())
2018+
}
2019+
20122020
fn encode_lib_features(&mut self) -> LazyArray<(Symbol, FeatureStability)> {
20132021
empty_proc_macro!(self);
20142022
let tcx = self.tcx;

‎compiler/rustc_metadata/src/rmeta/mod.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::marker::PhantomData;
22
use std::num::NonZero;
33

4-
pub(crate) use decoder::{CrateMetadata, CrateNumMap, MetadataBlob};
4+
pub(crate) use decoder::{CrateMetadata, CrateNumMap, MetadataBlob, TargetModifiers};
55
use decoder::{DecodeContext, Metadata};
66
use def_path_hash_map::DefPathHashMapRef;
77
use encoder::EncodeContext;
@@ -32,7 +32,7 @@ use rustc_middle::ty::{
3232
use rustc_middle::util::Providers;
3333
use rustc_middle::{mir, trivially_parameterized_over_tcx};
3434
use rustc_serialize::opaque::FileEncoder;
35-
use rustc_session::config::SymbolManglingVersion;
35+
use rustc_session::config::{SymbolManglingVersion, TargetModifier};
3636
use rustc_session::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib};
3737
use rustc_span::edition::Edition;
3838
use rustc_span::hygiene::{ExpnIndex, MacroKind, SyntaxContextData};
@@ -282,6 +282,7 @@ pub(crate) struct CrateRoot {
282282
def_path_hash_map: LazyValue<DefPathHashMapRef<'static>>,
283283

284284
source_map: LazyTable<u32, Option<LazyValue<rustc_span::SourceFile>>>,
285+
target_modifiers: LazyArray<TargetModifier>,
285286

286287
compiler_builtins: bool,
287288
needs_allocator: bool,

‎compiler/rustc_middle/src/ty/parameterized.rs

+1
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ trivially_parameterized_over_tcx! {
101101
rustc_session::cstore::ForeignModule,
102102
rustc_session::cstore::LinkagePreference,
103103
rustc_session::cstore::NativeLib,
104+
rustc_session::config::TargetModifier,
104105
rustc_span::ExpnData,
105106
rustc_span::ExpnHash,
106107
rustc_span::ExpnId,

‎compiler/rustc_session/src/config.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -1198,6 +1198,7 @@ impl Default for Options {
11981198
color: ColorConfig::Auto,
11991199
logical_env: FxIndexMap::default(),
12001200
verbose: false,
1201+
target_modifiers: BTreeMap::default(),
12011202
}
12021203
}
12031204
}
@@ -2341,14 +2342,16 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
23412342
let crate_types = parse_crate_types_from_list(unparsed_crate_types)
23422343
.unwrap_or_else(|e| early_dcx.early_fatal(e));
23432344

2344-
let mut unstable_opts = UnstableOptions::build(early_dcx, matches);
2345+
let mut target_modifiers = BTreeMap::<OptionsTargetModifiers, String>::new();
2346+
2347+
let mut unstable_opts = UnstableOptions::build(early_dcx, matches, &mut target_modifiers);
23452348
let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(early_dcx, matches);
23462349

23472350
check_error_format_stability(early_dcx, &unstable_opts, error_format);
23482351

23492352
let output_types = parse_output_types(early_dcx, &unstable_opts, matches);
23502353

2351-
let mut cg = CodegenOptions::build(early_dcx, matches);
2354+
let mut cg = CodegenOptions::build(early_dcx, matches, &mut target_modifiers);
23522355
let (disable_local_thinlto, codegen_units) = should_override_cgus_and_disable_thinlto(
23532356
early_dcx,
23542357
&output_types,
@@ -2619,6 +2622,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
26192622
color,
26202623
logical_env,
26212624
verbose,
2625+
target_modifiers,
26222626
}
26232627
}
26242628

There was a problem loading the remainder of the diff.

0 commit comments

Comments
 (0)
Failed to load comments.