Skip to content

Commit 41f33a6

Browse files
author
hyd-dev
committed
Implement calls to exported symbols
1 parent 71f4140 commit 41f33a6

39 files changed

+584
-90
lines changed

src/bin/miri.rs

Lines changed: 70 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,52 @@
1-
#![feature(rustc_private)]
1+
#![feature(rustc_private, bool_to_option, stmt_expr_attributes)]
22

33
extern crate rustc_driver;
44
extern crate rustc_errors;
55
extern crate rustc_hir;
66
extern crate rustc_interface;
7+
extern crate rustc_metadata;
78
extern crate rustc_middle;
89
extern crate rustc_session;
910

1011
use std::convert::TryFrom;
1112
use std::env;
13+
use std::path::PathBuf;
14+
use std::rc::Rc;
1215
use std::str::FromStr;
1316

1417
use hex::FromHexError;
1518
use log::debug;
1619

1720
use rustc_driver::Compilation;
1821
use rustc_errors::emitter::{ColorConfig, HumanReadableErrorType};
19-
use rustc_middle::ty::TyCtxt;
20-
use rustc_session::{config::ErrorOutputType, CtfeBacktrace};
22+
use rustc_hir::def_id::LOCAL_CRATE;
23+
use rustc_interface::interface::Config;
24+
use rustc_middle::{
25+
middle::exported_symbols::{ExportedSymbol, SymbolExportLevel},
26+
ty::{query::Providers, TyCtxt},
27+
};
28+
use rustc_session::{config::ErrorOutputType, search_paths::PathKind, CtfeBacktrace};
2129

2230
struct MiriCompilerCalls {
2331
miri_config: miri::MiriConfig,
2432
}
2533

2634
impl rustc_driver::Callbacks for MiriCompilerCalls {
35+
fn config(&mut self, config: &mut Config) {
36+
config.override_queries = Some(|_, _, external_providers| {
37+
external_providers.used_crate_source = |tcx, cnum| {
38+
let mut providers = Providers::default();
39+
rustc_metadata::provide_extern(&mut providers);
40+
let mut crate_source = (providers.used_crate_source)(tcx, cnum);
41+
// HACK: rustc will emit "crate ... required to be available in rlib format, but
42+
// was not found in this form" errors once we use `tcx.dependency_formats()` if
43+
// there's no rlib provided, so setting a dummy path here to workaround those errors.
44+
Rc::make_mut(&mut crate_source).rlib = Some((PathBuf::new(), PathKind::All));
45+
crate_source
46+
};
47+
});
48+
}
49+
2750
fn after_analysis<'tcx>(
2851
&mut self,
2952
compiler: &rustc_interface::interface::Compiler,
@@ -67,6 +90,39 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
6790
}
6891
}
6992

93+
struct MiriBeRustCompilerCalls {
94+
target_crate: bool,
95+
}
96+
97+
impl rustc_driver::Callbacks for MiriBeRustCompilerCalls {
98+
fn config(&mut self, config: &mut Config) {
99+
if config.opts.prints.is_empty() && self.target_crate {
100+
// Queries overriden here affects the data stored in `rmeta` files of dependencies,
101+
// which will be used later in non-`MIRI_BE_RUSTC` mode.
102+
config.override_queries = Some(|_, local_providers, _| {
103+
// `exported_symbols()` provided by rustc always returns empty result if
104+
// `tcx.sess.opts.output_types.should_codegen()` is false.
105+
local_providers.exported_symbols = |tcx, cnum| {
106+
assert_eq!(cnum, LOCAL_CRATE);
107+
tcx.arena.alloc_from_iter(
108+
// This is based on:
109+
// https://github.com/rust-lang/rust/blob/2962e7c0089d5c136f4e9600b7abccfbbde4973d/compiler/rustc_codegen_ssa/src/back/symbol_export.rs#L62-L63
110+
// https://github.com/rust-lang/rust/blob/2962e7c0089d5c136f4e9600b7abccfbbde4973d/compiler/rustc_codegen_ssa/src/back/symbol_export.rs#L174
111+
tcx.reachable_set(()).iter().filter_map(|&local_def_id| {
112+
tcx.codegen_fn_attrs(local_def_id)
113+
.contains_extern_indicator()
114+
.then_some((
115+
ExportedSymbol::NonGeneric(local_def_id.to_def_id()),
116+
SymbolExportLevel::C,
117+
))
118+
}),
119+
)
120+
}
121+
});
122+
}
123+
}
124+
}
125+
70126
fn init_early_loggers() {
71127
// Note that our `extern crate log` is *not* the same as rustc's; as a result, we have to
72128
// initialize them both, and we always initialize `miri`'s first.
@@ -179,11 +235,7 @@ fn main() {
179235
if let Some(crate_kind) = env::var_os("MIRI_BE_RUSTC") {
180236
rustc_driver::init_rustc_env_logger();
181237

182-
// Don't insert `MIRI_DEFAULT_ARGS`, in particular, `--cfg=miri`, if we are building a
183-
// "host" crate. That may cause procedural macros (and probably build scripts) to depend
184-
// on Miri-only symbols, such as `miri_resolve_frame`:
185-
// https://github.com/rust-lang/miri/issues/1760
186-
let insert_default_args = if crate_kind == "target" {
238+
let target_crate = if crate_kind == "target" {
187239
true
188240
} else if crate_kind == "host" {
189241
false
@@ -192,8 +244,16 @@ fn main() {
192244
};
193245

194246
// We cannot use `rustc_driver::main` as we need to adjust the CLI arguments.
195-
let mut callbacks = rustc_driver::TimePassesCallbacks::default();
196-
run_compiler(env::args().collect(), &mut callbacks, insert_default_args)
247+
run_compiler(
248+
env::args().collect(),
249+
&mut MiriBeRustCompilerCalls { target_crate },
250+
// Don't insert `MIRI_DEFAULT_ARGS`, in particular, `--cfg=miri`, if we are building
251+
// a "host" crate. That may cause procedural macros (and probably build scripts) to
252+
// depend on Miri-only symbols, such as `miri_resolve_frame`:
253+
// https://github.com/rust-lang/miri/issues/1760
254+
#[rustfmt::skip]
255+
/* insert_default_args: */ target_crate,
256+
)
197257
}
198258

199259
// Init loggers the Miri way.

src/diagnostics.rs

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::num::NonZeroU64;
55
use log::trace;
66

77
use rustc_middle::ty::{self, TyCtxt};
8-
use rustc_span::{source_map::DUMMY_SP, Span};
8+
use rustc_span::{source_map::DUMMY_SP, Span, SpanData, Symbol};
99

1010
use crate::*;
1111

@@ -14,8 +14,18 @@ pub enum TerminationInfo {
1414
Exit(i64),
1515
Abort(String),
1616
UnsupportedInIsolation(String),
17-
ExperimentalUb { msg: String, url: String },
17+
ExperimentalUb {
18+
msg: String,
19+
url: String,
20+
},
1821
Deadlock,
22+
MultipleSymbolDefinitions {
23+
link_name: Symbol,
24+
first: SpanData,
25+
first_crate: Symbol,
26+
second: SpanData,
27+
second_crate: Symbol,
28+
},
1929
}
2030

2131
impl fmt::Display for TerminationInfo {
@@ -27,6 +37,8 @@ impl fmt::Display for TerminationInfo {
2737
UnsupportedInIsolation(msg) => write!(f, "{}", msg),
2838
ExperimentalUb { msg, .. } => write!(f, "{}", msg),
2939
Deadlock => write!(f, "the evaluated program deadlocked"),
40+
MultipleSymbolDefinitions { link_name, .. } =>
41+
write!(f, "multiple definitions of symbol `{}`", link_name),
3042
}
3143
}
3244
}
@@ -55,19 +67,25 @@ pub fn report_error<'tcx, 'mir>(
5567
use TerminationInfo::*;
5668
let title = match info {
5769
Exit(code) => return Some(*code),
58-
Abort(_) => "abnormal termination",
59-
UnsupportedInIsolation(_) => "unsupported operation",
60-
ExperimentalUb { .. } => "Undefined Behavior",
61-
Deadlock => "deadlock",
70+
Abort(_) => Some("abnormal termination"),
71+
UnsupportedInIsolation(_) => Some("unsupported operation"),
72+
ExperimentalUb { .. } => Some("Undefined Behavior"),
73+
Deadlock => Some("deadlock"),
74+
MultipleSymbolDefinitions { .. } => None,
6275
};
6376
#[rustfmt::skip]
6477
let helps = match info {
6578
UnsupportedInIsolation(_) =>
66-
vec![format!("pass the flag `-Zmiri-disable-isolation` to disable isolation")],
79+
vec![(None, format!("pass the flag `-Zmiri-disable-isolation` to disable isolation"))],
6780
ExperimentalUb { url, .. } =>
6881
vec![
69-
format!("this indicates a potential bug in the program: it performed an invalid operation, but the rules it violated are still experimental"),
70-
format!("see {} for further information", url),
82+
(None, format!("this indicates a potential bug in the program: it performed an invalid operation, but the rules it violated are still experimental")),
83+
(None, format!("see {} for further information", url)),
84+
],
85+
MultipleSymbolDefinitions { first, first_crate, second, second_crate, .. } =>
86+
vec![
87+
(Some(*first), format!("it's first defined here, in crate `{}`", first_crate)),
88+
(Some(*second), format!("then it's defined here again, in crate `{}`", second_crate)),
7189
],
7290
_ => vec![],
7391
};
@@ -90,26 +108,26 @@ pub fn report_error<'tcx, 'mir>(
90108
#[rustfmt::skip]
91109
let helps = match e.kind() {
92110
Unsupported(UnsupportedOpInfo::NoMirFor(..)) =>
93-
vec![format!("make sure to use a Miri sysroot, which you can prepare with `cargo miri setup`")],
111+
vec![(None, format!("make sure to use a Miri sysroot, which you can prepare with `cargo miri setup`"))],
94112
Unsupported(UnsupportedOpInfo::ReadBytesAsPointer | UnsupportedOpInfo::ThreadLocalStatic(_) | UnsupportedOpInfo::ReadExternStatic(_)) =>
95113
panic!("Error should never be raised by Miri: {:?}", e.kind()),
96114
Unsupported(_) =>
97-
vec![format!("this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support")],
115+
vec![(None, format!("this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support"))],
98116
UndefinedBehavior(UndefinedBehaviorInfo::AlignmentCheckFailed { .. })
99117
if ecx.memory.extra.check_alignment == AlignmentCheck::Symbolic
100118
=>
101119
vec![
102-
format!("this usually indicates that your program performed an invalid operation and caused Undefined Behavior"),
103-
format!("but due to `-Zmiri-symbolic-alignment-check`, alignment errors can also be false positives"),
120+
(None, format!("this usually indicates that your program performed an invalid operation and caused Undefined Behavior")),
121+
(None, format!("but due to `-Zmiri-symbolic-alignment-check`, alignment errors can also be false positives")),
104122
],
105123
UndefinedBehavior(_) =>
106124
vec![
107-
format!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior"),
108-
format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information"),
125+
(None, format!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior")),
126+
(None, format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information")),
109127
],
110128
_ => vec![],
111129
};
112-
(title, helps)
130+
(Some(title), helps)
113131
}
114132
};
115133

@@ -118,7 +136,7 @@ pub fn report_error<'tcx, 'mir>(
118136
report_msg(
119137
*ecx.tcx,
120138
/*error*/ true,
121-
&format!("{}: {}", title, msg),
139+
&if let Some(title) = title { format!("{}: {}", title, msg) } else { msg.clone() },
122140
msg,
123141
helps,
124142
&ecx.generate_stacktrace(),
@@ -157,7 +175,7 @@ fn report_msg<'tcx>(
157175
error: bool,
158176
title: &str,
159177
span_msg: String,
160-
mut helps: Vec<String>,
178+
mut helps: Vec<(Option<SpanData>, String)>,
161179
stacktrace: &[FrameInfo<'tcx>],
162180
) {
163181
let span = stacktrace.first().map_or(DUMMY_SP, |fi| fi.span);
@@ -177,9 +195,13 @@ fn report_msg<'tcx>(
177195
// Show help messages.
178196
if !helps.is_empty() {
179197
// Add visual separator before backtrace.
180-
helps.last_mut().unwrap().push_str("\n");
181-
for help in helps {
182-
err.help(&help);
198+
helps.last_mut().unwrap().1.push_str("\n");
199+
for (span_data, help) in helps {
200+
if let Some(span_data) = span_data {
201+
err.span_help(span_data.span(), &help);
202+
} else {
203+
err.help(&help);
204+
}
183205
}
184206
}
185207
// Add backtrace

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#![feature(map_try_insert)]
44
#![feature(never_type)]
55
#![feature(try_blocks)]
6+
#![feature(bool_to_option)]
67
#![warn(rust_2018_idioms)]
78
#![allow(clippy::cast_lossless)]
89

@@ -14,6 +15,7 @@ extern crate rustc_data_structures;
1415
extern crate rustc_hir;
1516
extern crate rustc_index;
1617
extern crate rustc_mir;
18+
extern crate rustc_session;
1719
extern crate rustc_span;
1820
extern crate rustc_target;
1921

src/machine.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use rustc_middle::{
1717
ty::{
1818
self,
1919
layout::{LayoutCx, LayoutError, TyAndLayout},
20-
TyCtxt,
20+
Instance, TyCtxt,
2121
},
2222
};
2323
use rustc_span::def_id::DefId;
@@ -294,6 +294,9 @@ pub struct Evaluator<'mir, 'tcx> {
294294
/// Used with `profiler` to cache the `StringId`s for event names
295295
/// uesd with `measureme`.
296296
string_cache: FxHashMap<String, measureme::StringId>,
297+
298+
/// Cache of `Instance` exported under the given `Symbol` name.
299+
pub(crate) exported_symbols_cache: FxHashMap<Symbol, Instance<'tcx>>,
297300
}
298301

299302
impl<'mir, 'tcx> Evaluator<'mir, 'tcx> {
@@ -322,6 +325,7 @@ impl<'mir, 'tcx> Evaluator<'mir, 'tcx> {
322325
static_roots: Vec::new(),
323326
profiler,
324327
string_cache: Default::default(),
328+
exported_symbols_cache: FxHashMap::default(),
325329
}
326330
}
327331
}

0 commit comments

Comments
 (0)