Skip to content

Commit 49b19d3

Browse files
committed
Auto merge of #157404 - jhpratt:rollup-npYd5Y2, r=jhpratt
Rollup of 3 pull requests Successful merges: - #156210 (Emit retags in codegen to support BorrowSanitizer (part 2)) - #157317 (Fix ICE when wrong intra-doc link on type alias) - #157391 (Reorganize `tests/ui/issues` [4/N])
2 parents 76dfce2 + aa15473 commit 49b19d3

35 files changed

Lines changed: 309 additions & 101 deletions

compiler/rustc_codegen_ssa/src/mir/block.rs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,12 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
264264
bx.lifetime_end(tmp, size);
265265
}
266266
fx.store_return(bx, ret_dest, &fn_abi.ret, invokeret);
267+
268+
// If the return value was retagged as it was stored,
269+
// then we might be in a different basic block now.
270+
// Update the cached block for `target` to point to this new
271+
// block, where codegen will continue.
272+
fx.cached_llbbs[target] = CachedLlbb::Some(bx.llbb());
267273
}
268274
MergingSucc::False
269275
} else {
@@ -2186,19 +2192,27 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
21862192
llval: Bx::Value,
21872193
) {
21882194
use self::ReturnDest::*;
2189-
2195+
let retags_enabled = bx.tcx().sess.opts.unstable_opts.codegen_emit_retag.is_some();
21902196
match dest {
21912197
Nothing => (),
2192-
Store(dst) => bx.store_arg(ret_abi, llval, dst),
2198+
Store(dst) => {
2199+
bx.store_arg(ret_abi, llval, dst);
2200+
if retags_enabled {
2201+
self.codegen_retag_place(bx, dst, false);
2202+
}
2203+
}
21932204
IndirectOperand(tmp, index) => {
2194-
let op = bx.load_operand(tmp);
2205+
let mut op = bx.load_operand(tmp);
21952206
tmp.storage_dead(bx);
2207+
if retags_enabled {
2208+
op = self.codegen_retag_operand(bx, op, false);
2209+
}
21962210
self.overwrite_local(index, LocalRef::Operand(op));
21972211
self.debug_introduce_local(bx, index);
21982212
}
21992213
DirectOperand(index) => {
22002214
// If there is a cast, we have to store and reload.
2201-
let op = if let PassMode::Cast { .. } = ret_abi.mode {
2215+
let mut op = if let PassMode::Cast { .. } = ret_abi.mode {
22022216
let tmp = PlaceRef::alloca(bx, ret_abi.layout);
22032217
tmp.storage_live(bx);
22042218
bx.store_arg(ret_abi, llval, tmp);
@@ -2208,6 +2222,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
22082222
} else {
22092223
OperandRef::from_immediate_or_packed_pair(bx, llval, ret_abi.layout)
22102224
};
2225+
if retags_enabled {
2226+
op = self.codegen_retag_operand(bx, op, false);
2227+
}
22112228
self.overwrite_local(index, LocalRef::Operand(op));
22122229
self.debug_introduce_local(bx, index);
22132230
}

compiler/rustc_codegen_ssa/src/mir/mod.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ mod locals;
2424
pub mod naked_asm;
2525
pub mod operand;
2626
pub mod place;
27+
mod retag;
2728
mod rvalue;
2829
mod statement;
2930

@@ -425,7 +426,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
425426
return vec![];
426427
}
427428

428-
let args = mir
429+
let mut args = mir
429430
.args_iter()
430431
.enumerate()
431432
.map(|(arg_index, local)| {
@@ -562,6 +563,32 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
562563
}
563564
})
564565
.collect::<Vec<_>>();
566+
if bx.tcx().sess.opts.unstable_opts.codegen_emit_retag.is_some() {
567+
args = args
568+
.iter()
569+
.map(|arg| match arg {
570+
&LocalRef::Place(place_ref) => {
571+
fx.codegen_retag_place(bx, place_ref, true);
572+
LocalRef::Place(place_ref)
573+
}
574+
&LocalRef::UnsizedPlace(place_ref) => {
575+
let operand = bx.load_operand(place_ref);
576+
let retagged = fx.codegen_retag_operand(bx, operand, true);
577+
assert!(matches!(retagged.val, OperandValue::Pair(_, _)));
578+
retagged.val.store(bx, place_ref);
579+
LocalRef::UnsizedPlace(place_ref)
580+
}
581+
&LocalRef::Operand(operand_ref) => {
582+
let retagged = fx.codegen_retag_operand(bx, operand_ref, true);
583+
LocalRef::Operand(retagged)
584+
}
585+
LocalRef::PendingOperand => LocalRef::PendingOperand,
586+
})
587+
.collect::<Vec<_>>();
588+
// If we branched during retagging, then we need to update the
589+
// start block to the new location.
590+
fx.cached_llbbs[mir::START_BLOCK] = CachedLlbb::Some(bx.llbb());
591+
}
565592

566593
if fx.instance.def.requires_caller_location(bx.tcx()) {
567594
let mir_args = if let Some(num_untupled) = num_untupled {
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//! Experimental support for emitting retags as function calls in generated code.
2+
3+
use rustc_middle::mir::{Rvalue, WithRetag};
4+
5+
use crate::mir::FunctionCx;
6+
use crate::mir::operand::OperandRef;
7+
use crate::mir::place::PlaceRef;
8+
use crate::traits::BuilderMethods;
9+
10+
pub(crate) fn rvalue_needs_retag(rvalue: &Rvalue<'_>) -> bool {
11+
// `Ref` has its own internal retagging
12+
!matches!(rvalue, Rvalue::Ref(..)) && !matches!(rvalue, Rvalue::Use(.., WithRetag::No))
13+
}
14+
15+
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
16+
/// Retags the pointers within an [`OperandRef`].
17+
pub(crate) fn codegen_retag_operand(
18+
&mut self,
19+
_bx: &mut Bx,
20+
operand: OperandRef<'tcx, Bx::Value>,
21+
_is_fn_entry: bool,
22+
) -> OperandRef<'tcx, Bx::Value> {
23+
operand
24+
}
25+
26+
/// Retags the pointers within a [`PlaceRef`].
27+
pub(crate) fn codegen_retag_place(
28+
&mut self,
29+
_bx: &mut Bx,
30+
_place_ref: PlaceRef<'tcx, Bx::Value>,
31+
_is_fn_entry: bool,
32+
) {
33+
}
34+
}

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
522522
let mk_ref = move |tcx: TyCtxt<'tcx>, ty: Ty<'tcx>| {
523523
Ty::new_ref(tcx, tcx.lifetimes.re_erased, ty, bk.to_mutbl_lossy())
524524
};
525-
self.codegen_place_to_pointer(bx, place, mk_ref)
525+
let op = self.codegen_place_to_pointer(bx, place, mk_ref);
526+
if self.cx.tcx().sess.opts.unstable_opts.codegen_emit_retag.is_some() {
527+
self.codegen_retag_operand(bx, op, false)
528+
} else {
529+
op
530+
}
526531
}
527532

528533
// Note: Exclusive reborrowing is always equal to a memcpy, as the types do not change.

compiler/rustc_codegen_ssa/src/mir/statement.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use rustc_middle::{bug, span_bug, ty};
33
use tracing::instrument;
44

55
use super::{FunctionCx, LocalRef};
6+
use crate::mir::retag;
67
use crate::traits::*;
78

89
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
@@ -12,9 +13,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1213
self.set_debug_loc(bx, statement.source_info);
1314
match statement.kind {
1415
mir::StatementKind::Assign((ref place, ref rvalue)) => {
16+
let needs_retag = bx.tcx().sess.opts.unstable_opts.codegen_emit_retag.is_some()
17+
&& retag::rvalue_needs_retag(rvalue);
18+
1519
if let Some(index) = place.as_local() {
1620
match self.locals[index] {
17-
LocalRef::Place(cg_dest) => self.codegen_rvalue(bx, cg_dest, rvalue),
21+
LocalRef::Place(cg_dest) => {
22+
self.codegen_rvalue(bx, cg_dest, rvalue);
23+
if needs_retag {
24+
self.codegen_retag_place(bx, cg_dest, false);
25+
}
26+
}
1827
LocalRef::UnsizedPlace(cg_indirect_dest) => {
1928
let ty = cg_indirect_dest.layout.ty;
2029
span_bug!(
@@ -24,7 +33,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
2433
);
2534
}
2635
LocalRef::PendingOperand => {
27-
let operand = self.codegen_rvalue_operand(bx, rvalue);
36+
let mut operand = self.codegen_rvalue_operand(bx, rvalue);
37+
if needs_retag {
38+
operand = self.codegen_retag_operand(bx, operand, false);
39+
}
2840
self.overwrite_local(index, LocalRef::Operand(operand));
2941
self.debug_introduce_local(bx, index);
3042
}
@@ -39,12 +51,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
3951

4052
// If the type is zero-sized, it's already been set here,
4153
// but we still need to make sure we codegen the operand
42-
self.codegen_rvalue_operand(bx, rvalue);
54+
// and emit a retag.
55+
let operand = self.codegen_rvalue_operand(bx, rvalue);
56+
if needs_retag {
57+
self.codegen_retag_operand(bx, operand, false);
58+
}
4359
}
4460
}
4561
} else {
4662
let cg_dest = self.codegen_place(bx, place.as_ref());
4763
self.codegen_rvalue(bx, cg_dest, rvalue);
64+
if needs_retag {
65+
self.codegen_retag_place(bx, cg_dest, false);
66+
}
4867
}
4968
}
5069
mir::StatementKind::SetDiscriminant { ref place, variant_index } => {

compiler/rustc_interface/src/tests.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ use rustc_errors::ColorConfig;
1010
use rustc_errors::emitter::HumanReadableErrorType;
1111
use rustc_hir::attrs::{CollapseMacroDebuginfo, NativeLibKind};
1212
use rustc_session::config::{
13-
AnnotateMoves, AutoDiff, BranchProtection, CFGuard, Cfg, CoverageLevel, CoverageOptions,
14-
DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation, Externs,
15-
FmtDebug, FunctionReturn, IncrementalStateAssertion, InliningThreshold, Input,
13+
AnnotateMoves, AutoDiff, BranchProtection, CFGuard, Cfg, CodegenRetagOptions, CoverageLevel,
14+
CoverageOptions, DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation,
15+
Externs, FmtDebug, FunctionReturn, IncrementalStateAssertion, InliningThreshold, Input,
1616
InstrumentCoverage, InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli,
1717
MirIncludeSpans, NextSolverConfig, Offload, Options, OutFileName, OutputType, OutputTypes,
1818
PAuthKey, PacRet, Passes, PatchableFunctionEntry, Polonius, ProcMacroExecutionStrategy, Strip,
@@ -772,6 +772,7 @@ fn test_unstable_options_tracking_hash() {
772772
})
773773
);
774774
tracked!(codegen_backend, Some("abc".to_string()));
775+
tracked!(codegen_emit_retag, Some(CodegenRetagOptions::default()));
775776
tracked!(
776777
coverage_options,
777778
CoverageOptions {

compiler/rustc_session/src/config.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,15 @@ pub enum Offload {
200200
Test,
201201
}
202202

203+
/// The different settings that the `-Z codegen-emit-retag` flag can have.
204+
#[derive(Copy, Clone, Debug, Default, PartialEq, Hash, Encodable, Decodable)]
205+
pub struct CodegenRetagOptions {
206+
/// Track interior mutable data on the level of references, instead of on the byte level.
207+
pub no_precise_im: bool,
208+
/// Track `UnsafePinned` data on the level of references, instead of on the byte level.
209+
pub no_precise_pin: bool,
210+
}
211+
203212
/// The different settings that the `-Z autodiff` flag can have.
204213
#[derive(Clone, PartialEq, Hash, Debug, Encodable, Decodable)]
205214
pub enum AutoDiff {
@@ -3045,12 +3054,13 @@ pub(crate) mod dep_tracking {
30453054
};
30463055

30473056
use super::{
3048-
AnnotateMoves, AutoDiff, BranchProtection, CFGuard, CFProtection, CoverageOptions,
3049-
CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FmtDebug, FunctionReturn,
3050-
InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail,
3051-
LtoCli, MirStripDebugInfo, NextSolverConfig, Offload, OptLevel, OutFileName, OutputType,
3052-
OutputTypes, PatchableFunctionEntry, Polonius, ResolveDocLinks, SourceFileHashAlgorithm,
3053-
SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
3057+
AnnotateMoves, AutoDiff, BranchProtection, CFGuard, CFProtection, CodegenRetagOptions,
3058+
CoverageOptions, CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FmtDebug,
3059+
FunctionReturn, InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto,
3060+
LocationDetail, LtoCli, MirStripDebugInfo, NextSolverConfig, Offload, OptLevel,
3061+
OutFileName, OutputType, OutputTypes, PatchableFunctionEntry, Polonius, ResolveDocLinks,
3062+
SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion,
3063+
WasiExecModel,
30543064
};
30553065
use crate::lint;
30563066
use crate::utils::NativeLib;
@@ -3154,6 +3164,7 @@ pub(crate) mod dep_tracking {
31543164
InliningThreshold,
31553165
FunctionReturn,
31563166
Align,
3167+
CodegenRetagOptions
31573168
);
31583169

31593170
impl<T1, T2> DepTrackingHash for (T1, T2)

compiler/rustc_session/src/options.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,6 +783,8 @@ mod desc {
783783
pub(crate) const parse_dump_mono_stats: &str = "`markdown` (default) or `json`";
784784
pub(crate) const parse_instrument_coverage: &str = parse_bool;
785785
pub(crate) const parse_coverage_options: &str = "`block` | `branch` | `condition`";
786+
pub(crate) const parse_codegen_retag_options: &str =
787+
"either no value or a comma-separated list of settings: `no-precise-im`, `no-precise-pin`";
786788
pub(crate) const parse_instrument_xray: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or a comma separated list of settings: `always` or `never` (mutually exclusive), `ignore-loops`, `instruction-threshold=N`, `skip-entry`, `skip-exit`";
787789
pub(crate) const parse_unpretty: &str = "`string` or `string=string`";
788790
pub(crate) const parse_treat_err_as_bug: &str = "either no value or a non-negative number";
@@ -1523,6 +1525,29 @@ pub mod parse {
15231525
true
15241526
}
15251527

1528+
pub(crate) fn parse_codegen_retag_options(
1529+
slot: &mut Option<CodegenRetagOptions>,
1530+
v: Option<&str>,
1531+
) -> bool {
1532+
let mut no_precise_im = false;
1533+
let mut no_precise_pin = false;
1534+
if let Some(opt_list) = v.map(|s| s.split(',')) {
1535+
for opt in opt_list {
1536+
match opt {
1537+
"no-precise-im" => {
1538+
no_precise_im = true;
1539+
}
1540+
"no-precise-pin" => {
1541+
no_precise_pin = true;
1542+
}
1543+
_ => return false,
1544+
}
1545+
}
1546+
}
1547+
*slot = Some(CodegenRetagOptions { no_precise_im, no_precise_pin });
1548+
true
1549+
}
1550+
15261551
pub(crate) fn parse_coverage_options(slot: &mut CoverageOptions, v: Option<&str>) -> bool {
15271552
let Some(v) = v else { return true };
15281553

@@ -2242,6 +2267,8 @@ options! {
22422267
"hash algorithm of source files used to check freshness in cargo (`blake3` or `sha256`)"),
22432268
codegen_backend: Option<String> = (None, parse_opt_string, [TRACKED],
22442269
"the backend to use"),
2270+
codegen_emit_retag: Option<CodegenRetagOptions> = (None, parse_codegen_retag_options, [TRACKED],
2271+
"emit retag function calls in generated code"),
22452272
codegen_source_order: bool = (false, parse_bool, [UNTRACKED],
22462273
"emit mono items in the order of spans in source files (default: no)"),
22472274
contract_checks: Option<bool> = (None, parse_opt_bool, [TRACKED],

compiler/rustc_session/src/session.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,8 @@ impl Session {
553553
// HWAddressSanitizer and KernelHWAddressSanitizer will use lifetimes to detect use after
554554
// scope bugs in the future.
555555
|| self.sanitizers().intersects(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS | SanitizerSet::MEMORY | SanitizerSet::HWADDRESS | SanitizerSet::KERNELHWADDRESS)
556+
// Lifetimes are necessary for retagging semantics.
557+
|| self.opts.unstable_opts.codegen_emit_retag.is_some()
556558
}
557559

558560
pub fn diagnostic_width(&self) -> usize {

src/librustdoc/passes/collect_intra_doc_links.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,12 @@ impl<'tcx> LinkCollector<'_, 'tcx> {
328328
})
329329
}
330330
}
331-
_ => unreachable!(),
331+
_ => Err(UnresolvedPath {
332+
item_id,
333+
module_id,
334+
partial_res: Some(Res::Def(DefKind::TyAlias, did)),
335+
unresolved: variant_name.to_string().into(),
336+
}),
332337
}
333338
}
334339
_ => Err(UnresolvedPath {

0 commit comments

Comments
 (0)