Skip to content

Commit 95ffdf8

Browse files
committed
Target modifiers (special marked options) are recorded in metainfo and compared to be equal in different crates
1 parent f005c74 commit 95ffdf8

File tree

15 files changed

+409
-20
lines changed

15 files changed

+409
-20
lines changed

compiler/rustc_driver_impl/src/lib.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -1170,11 +1170,12 @@ fn describe_codegen_flags() {
11701170

11711171
fn print_flag_list<T>(
11721172
cmdline_opt: &str,
1173-
flag_list: &[(&'static str, T, &'static str, &'static str)],
1173+
flag_list: &[(&'static str, T, &'static str, &'static str, bool)],
11741174
) {
1175-
let max_len = flag_list.iter().map(|&(name, _, _, _)| name.chars().count()).max().unwrap_or(0);
1175+
let max_len =
1176+
flag_list.iter().map(|&(name, _, _, _, _)| name.chars().count()).max().unwrap_or(0);
11761177

1177-
for &(name, _, _, desc) in flag_list {
1178+
for &(name, _, _, desc, _) in flag_list {
11781179
safe_println!(
11791180
" {} {:>width$}=val -- {}",
11801181
cmdline_opt,

compiler/rustc_interface/src/passes.rs

+1
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ fn configure_and_expand(
270270

271271
resolver.resolve_crate(&krate);
272272

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

compiler/rustc_metadata/messages.ftl

+7
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,13 @@ 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
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 = `{$flag_name_prefixed}` 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 = alternatively, 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}`
116123
metadata_incompatible_wasm_link =
117124
`wasm_import_module` is incompatible with other arguments in `#[link]` attributes
118125

compiler/rustc_metadata/src/creader.rs

+111-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ use rustc_hir::definitions::Definitions;
2222
use rustc_index::IndexVec;
2323
use rustc_middle::bug;
2424
use rustc_middle::ty::{TyCtxt, TyCtxtFeed};
25-
use rustc_session::config::{self, CrateType, ExternLocation};
25+
use rustc_session::config::{
26+
self, CrateType, ExtendedTargetModifierInfo, ExternLocation, TargetModifier,
27+
};
2628
use rustc_session::cstore::{CrateDepKind, CrateSource, ExternCrate, ExternCrateSource};
2729
use rustc_session::lint::{self, BuiltinLintDiag};
2830
use rustc_session::output::validate_crate_name;
@@ -35,7 +37,9 @@ use tracing::{debug, info, trace};
3537

3638
use crate::errors;
3739
use crate::locator::{CrateError, CrateLocator, CratePaths};
38-
use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob};
40+
use crate::rmeta::{
41+
CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob, TargetModifiers,
42+
};
3943

4044
/// The backend's way to give the crate store access to the metadata in a library.
4145
/// Note that it returns the raw metadata bytes stored in the library file, whether
@@ -290,6 +294,90 @@ impl CStore {
290294
}
291295
}
292296

297+
pub fn report_incompatible_target_modifiers(&self, tcx: TyCtxt<'_>, krate: &Crate) {
298+
if tcx.crate_types().contains(&CrateType::ProcMacro) {
299+
return;
300+
}
301+
let sess = tcx.sess;
302+
let allowed_flag_mismatches = &sess.opts.cg.unsafe_allow_abi_mismatch;
303+
let span = krate.spans.inner_span.shrink_to_lo();
304+
let tmod_extender = |tmod: &TargetModifier| {
305+
(
306+
sess.opts
307+
.target_modifier_info_by_hash(tmod.name_hash, &tmod.value_name)
308+
.expect("Target modifier not found by name hash"),
309+
tmod.clone(),
310+
)
311+
};
312+
313+
let name = tcx.crate_name(LOCAL_CRATE);
314+
let mods = sess.opts.gather_target_modifiers();
315+
for (_cnum, data) in self.iter_crate_data() {
316+
if data.is_proc_macro_crate() {
317+
continue;
318+
}
319+
let report_diff = |prefix: &String,
320+
opt_name: &String,
321+
flag_local_value: &String,
322+
flag_extern_value: &String| {
323+
if allowed_flag_mismatches.contains(&opt_name) {
324+
return;
325+
}
326+
tcx.dcx().emit_err(errors::IncompatibleTargetModifiers {
327+
span,
328+
extern_crate: data.name(),
329+
local_crate: name,
330+
flag_name: opt_name.clone(),
331+
flag_name_prefixed: format!("-{}{}", prefix, opt_name),
332+
flag_local_value: flag_local_value.to_string(),
333+
flag_extern_value: flag_extern_value.to_string(),
334+
});
335+
};
336+
let mut it1 = mods.iter().map(tmod_extender);
337+
let mut it2 = data.target_modifiers().map(tmod_extender);
338+
let mut left_name_val: Option<(ExtendedTargetModifierInfo, TargetModifier)> = None;
339+
let mut right_name_val: Option<(ExtendedTargetModifierInfo, TargetModifier)> = None;
340+
let no_val = "*".to_string();
341+
loop {
342+
left_name_val = left_name_val.or_else(|| it1.next());
343+
right_name_val = right_name_val.or_else(|| it2.next());
344+
match (&left_name_val, &right_name_val) {
345+
(Some(l), Some(r)) => match l.1.name_hash.cmp(&r.1.name_hash) {
346+
cmp::Ordering::Equal => {
347+
if l.0.tech_value != r.0.tech_value {
348+
report_diff(
349+
&l.0.prefix,
350+
&l.0.name,
351+
&l.1.value_name,
352+
&r.1.value_name,
353+
);
354+
}
355+
left_name_val = None;
356+
right_name_val = None;
357+
}
358+
cmp::Ordering::Greater => {
359+
report_diff(&r.0.prefix, &r.0.name, &no_val, &r.1.value_name);
360+
right_name_val = None;
361+
}
362+
cmp::Ordering::Less => {
363+
report_diff(&l.0.prefix, &l.0.name, &l.1.value_name, &no_val);
364+
left_name_val = None;
365+
}
366+
},
367+
(Some(l), None) => {
368+
report_diff(&l.0.prefix, &l.0.name, &l.1.value_name, &no_val);
369+
left_name_val = None;
370+
}
371+
(None, Some(r)) => {
372+
report_diff(&r.0.prefix, &r.0.name, &no_val, &r.1.value_name);
373+
right_name_val = None;
374+
}
375+
(None, None) => break,
376+
}
377+
}
378+
}
379+
}
380+
293381
pub fn new(metadata_loader: Box<MetadataLoaderDyn>) -> CStore {
294382
CStore {
295383
metadata_loader,
@@ -432,6 +520,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
432520
};
433521

434522
let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, dep_kind)?;
523+
let target_modifiers = self.resolve_target_modifiers(&crate_root, &metadata, cnum)?;
435524

436525
let raw_proc_macros = if crate_root.is_proc_macro_crate() {
437526
let temp_root;
@@ -456,6 +545,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
456545
raw_proc_macros,
457546
cnum,
458547
cnum_map,
548+
target_modifiers,
459549
dep_kind,
460550
source,
461551
private_dep,
@@ -694,6 +784,25 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
694784
Ok(crate_num_map)
695785
}
696786

787+
fn resolve_target_modifiers(
788+
&mut self,
789+
crate_root: &CrateRoot,
790+
metadata: &MetadataBlob,
791+
krate: CrateNum,
792+
) -> Result<TargetModifiers, CrateError> {
793+
debug!("resolving target modifiers of external crate");
794+
if crate_root.is_proc_macro_crate() {
795+
return Ok(TargetModifiers::new());
796+
}
797+
let mods = crate_root.decode_target_modifiers(metadata);
798+
let mut target_modifiers = TargetModifiers::with_capacity(mods.len());
799+
for modifier in mods {
800+
target_modifiers.push(modifier);
801+
}
802+
debug!("resolve_target_modifiers: target mods for {:?} is {:?}", krate, target_modifiers);
803+
Ok(target_modifiers)
804+
}
805+
697806
fn dlsym_proc_macros(
698807
&self,
699808
path: &Path,

compiler/rustc_metadata/src/errors.rs

+17
Original file line numberDiff line numberDiff line change
@@ -732,3 +732,20 @@ 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+
}

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::symbol::kw;
@@ -74,6 +75,9 @@ impl MetadataBlob {
7475
/// own crate numbers.
7576
pub(crate) type CrateNumMap = IndexVec<CrateNum, CrateNum>;
7677

78+
/// Target modifiers - abi / vulnerability-resist affecting flags
79+
pub(crate) type TargetModifiers = Vec<TargetModifier>;
80+
7781
pub(crate) struct CrateMetadata {
7882
/// The primary crate data - binary metadata blob.
7983
blob: MetadataBlob,
@@ -111,6 +115,8 @@ pub(crate) struct CrateMetadata {
111115
cnum_map: CrateNumMap,
112116
/// Same ID set as `cnum_map` plus maybe some injected crates like panic runtime.
113117
dependencies: Vec<CrateNum>,
118+
/// Target modifiers - abi and vulnerability-resist affecting flags the crate was compiled with
119+
target_modifiers: TargetModifiers,
114120
/// How to link (or not link) this crate to the currently compiled crate.
115121
dep_kind: CrateDepKind,
116122
/// 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> {
@@ -1818,6 +1831,7 @@ impl CrateMetadata {
18181831
raw_proc_macros: Option<&'static [ProcMacro]>,
18191832
cnum: CrateNum,
18201833
cnum_map: CrateNumMap,
1834+
target_modifiers: TargetModifiers,
18211835
dep_kind: CrateDepKind,
18221836
source: CrateSource,
18231837
private_dep: bool,
@@ -1849,6 +1863,7 @@ impl CrateMetadata {
18491863
cnum,
18501864
cnum_map,
18511865
dependencies,
1866+
target_modifiers,
18521867
dep_kind,
18531868
source: Lrc::new(source),
18541869
private_dep,
@@ -1878,6 +1893,10 @@ impl CrateMetadata {
18781893
self.dependencies.push(cnum);
18791894
}
18801895

1896+
pub(crate) fn target_modifiers(&self) -> impl Iterator<Item = &TargetModifier> + '_ {
1897+
self.target_modifiers.iter()
1898+
}
1899+
18811900
pub(crate) fn update_extern_crate(&mut self, new_extern_crate: ExternCrate) -> bool {
18821901
let update =
18831902
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::symbol::sym;
3131
use rustc_span::{
@@ -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();
@@ -732,6 +733,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
732733
native_libraries,
733734
foreign_modules,
734735
source_map,
736+
target_modifiers,
735737
traits,
736738
impls,
737739
incoherent_impls,
@@ -1988,6 +1990,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
19881990
self.lazy_array(deps.iter().map(|(_, dep)| dep))
19891991
}
19901992

1993+
fn encode_target_modifiers(&mut self) -> LazyArray<TargetModifier> {
1994+
empty_proc_macro!(self);
1995+
let tcx = self.tcx;
1996+
self.lazy_array(tcx.sess.opts.gather_target_modifiers())
1997+
}
1998+
19911999
fn encode_lib_features(&mut self) -> LazyArray<(Symbol, FeatureStability)> {
19922000
empty_proc_macro!(self);
19932001
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};
@@ -283,6 +283,7 @@ pub(crate) struct CrateRoot {
283283
def_path_hash_map: LazyValue<DefPathHashMapRef<'static>>,
284284

285285
source_map: LazyTable<u32, Option<LazyValue<rustc_span::SourceFile>>>,
286+
target_modifiers: LazyArray<TargetModifier>,
286287

287288
compiler_builtins: bool,
288289
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
@@ -1190,6 +1190,7 @@ impl Default for Options {
11901190
color: ColorConfig::Auto,
11911191
logical_env: FxIndexMap::default(),
11921192
verbose: false,
1193+
target_modifiers: BTreeMap::default(),
11931194
}
11941195
}
11951196
}
@@ -2333,14 +2334,16 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
23332334
let crate_types = parse_crate_types_from_list(unparsed_crate_types)
23342335
.unwrap_or_else(|e| early_dcx.early_fatal(e));
23352336

2336-
let mut unstable_opts = UnstableOptions::build(early_dcx, matches);
2337+
let mut target_modifiers = BTreeMap::<String, String>::new();
2338+
2339+
let mut unstable_opts = UnstableOptions::build(early_dcx, matches, &mut target_modifiers);
23372340
let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(early_dcx, matches);
23382341

23392342
check_error_format_stability(early_dcx, &unstable_opts, error_format);
23402343

23412344
let output_types = parse_output_types(early_dcx, &unstable_opts, matches);
23422345

2343-
let mut cg = CodegenOptions::build(early_dcx, matches);
2346+
let mut cg = CodegenOptions::build(early_dcx, matches, &mut target_modifiers);
23442347
let (disable_local_thinlto, codegen_units) = should_override_cgus_and_disable_thinlto(
23452348
early_dcx,
23462349
&output_types,
@@ -2611,6 +2614,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
26112614
color,
26122615
logical_env,
26132616
verbose,
2617+
target_modifiers,
26142618
}
26152619
}
26162620

0 commit comments

Comments
 (0)