Skip to content

Commit 33b7fe2

Browse files
committed
Add Rvalue::AddressOf to MIR
This operator creates a raw pointer to a Place directly, without first creating a reference. See RFC rust-lang#2582 for motivation. The Rvalue is currently unused.
1 parent e1c6d00 commit 33b7fe2

File tree

17 files changed

+221
-89
lines changed

17 files changed

+221
-89
lines changed

src/librustc/ich/impls_mir.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,10 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for mir::Rvalue<'gcx> {
335335
borrow_kind.hash_stable(hcx, hasher);
336336
place.hash_stable(hcx, hasher);
337337
}
338+
mir::Rvalue::AddressOf(mutability, ref place) => {
339+
mutability.hash_stable(hcx, hasher);
340+
place.hash_stable(hcx, hasher);
341+
}
338342
mir::Rvalue::Len(ref place) => {
339343
place.hash_stable(hcx, hasher);
340344
}

src/librustc/mir/mod.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2182,6 +2182,11 @@ pub enum Rvalue<'tcx> {
21822182
/// &x or &mut x
21832183
Ref(Region<'tcx>, BorrowKind, Place<'tcx>),
21842184

2185+
/// Create a raw pointer to the given place
2186+
/// Can be generated by expressions like `&x as *const _`,
2187+
/// or when casting a reference to a raw pointer.
2188+
AddressOf(Mutability, Place<'tcx>),
2189+
21852190
/// length of a [X] or [X;n] value
21862191
Len(Place<'tcx>),
21872192

@@ -2354,6 +2359,15 @@ impl<'tcx> Debug for Rvalue<'tcx> {
23542359
write!(fmt, "&{}{}{:?}", region, kind_str, place)
23552360
}
23562361

2362+
AddressOf(mutability, ref place) => {
2363+
let kind_str = match mutability {
2364+
Mutability::Mut => "mut",
2365+
Mutability::Not => "const",
2366+
};
2367+
2368+
write!(fmt, "&{} raw {:?}", kind_str, place)
2369+
}
2370+
23572371
Aggregate(ref kind, ref places) => {
23582372
fn fmt_tuple(fmt: &mut Formatter<'_>, places: &[Operand<'_>]) -> fmt::Result {
23592373
let mut tuple_fmt = fmt.debug_tuple("");
@@ -3308,6 +3322,9 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
33083322
Ref(region, bk, ref place) => {
33093323
Ref(region.fold_with(folder), bk, place.fold_with(folder))
33103324
}
3325+
AddressOf(mutability, ref place) => {
3326+
AddressOf(mutability, place.fold_with(folder))
3327+
}
33113328
Len(ref place) => Len(place.fold_with(folder)),
33123329
Cast(kind, ref op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)),
33133330
BinaryOp(op, ref rhs, ref lhs) => {
@@ -3348,6 +3365,7 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
33483365
Use(ref op) => op.visit_with(visitor),
33493366
Repeat(ref op, _) => op.visit_with(visitor),
33503367
Ref(region, _, ref place) => region.visit_with(visitor) || place.visit_with(visitor),
3368+
AddressOf(_, ref place) => place.visit_with(visitor),
33513369
Len(ref place) => place.visit_with(visitor),
33523370
Cast(_, ref op, ty) => op.visit_with(visitor) || ty.visit_with(visitor),
33533371
BinaryOp(_, ref rhs, ref lhs) | CheckedBinaryOp(_, ref rhs, ref lhs) => {

src/librustc/mir/tcx.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,13 @@ impl<'tcx> Rvalue<'tcx> {
227227
}
228228
)
229229
}
230+
Rvalue::AddressOf(mutability, ref place) => {
231+
let place_ty = place.ty(local_decls, tcx).to_ty(tcx);
232+
tcx.mk_ptr(ty::TypeAndMut {
233+
ty: place_ty,
234+
mutbl: mutability.into(),
235+
})
236+
}
230237
Rvalue::Len(..) => tcx.types.usize,
231238
Rvalue::Cast(.., ty) => ty,
232239
Rvalue::BinaryOp(op, ref lhs, ref rhs) => {

src/librustc/mir/visit.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,18 @@ macro_rules! make_mir_visitor {
604604
self.visit_place(path, ctx, location);
605605
}
606606

607+
Rvalue::AddressOf(m, path) => {
608+
let ctx = match m {
609+
Mutability::Mut => PlaceContext::MutatingUse(
610+
MutatingUseContext::AddressOf
611+
),
612+
Mutability::Not => PlaceContext::NonMutatingUse(
613+
NonMutatingUseContext::AddressOf
614+
),
615+
};
616+
self.visit_place(path, ctx, location);
617+
}
618+
607619
Rvalue::Len(path) => {
608620
self.visit_place(
609621
path,
@@ -984,6 +996,8 @@ pub enum NonMutatingUseContext<'tcx> {
984996
ShallowBorrow(Region<'tcx>),
985997
/// Unique borrow.
986998
UniqueBorrow(Region<'tcx>),
999+
/// AddressOf for *const pointer
1000+
AddressOf,
9871001
/// Used as base for another place, e.g., `x` in `x.y`. Will not mutate the place.
9881002
/// For example, the projection `x.y` is not marked as a mutation in these cases:
9891003
///
@@ -1007,6 +1021,8 @@ pub enum MutatingUseContext<'tcx> {
10071021
Drop,
10081022
/// Mutable borrow.
10091023
Borrow(Region<'tcx>),
1024+
/// AddressOf for *mut pointer
1025+
AddressOf,
10101026
/// Used as base for another place, e.g., `x` in `x.y`. Could potentially mutate the place.
10111027
/// For example, the projection `x.y` is marked as a mutation in these cases:
10121028
///

src/librustc_codegen_ssa/mir/analyze.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,10 +236,12 @@ impl<'mir, 'a: 'mir, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
236236
PlaceContext::MutatingUse(MutatingUseContext::Store) |
237237
PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) |
238238
PlaceContext::MutatingUse(MutatingUseContext::Borrow(..)) |
239+
PlaceContext::MutatingUse(MutatingUseContext::AddressOf) |
239240
PlaceContext::MutatingUse(MutatingUseContext::Projection) |
240241
PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow(..)) |
241242
PlaceContext::NonMutatingUse(NonMutatingUseContext::UniqueBorrow(..)) |
242243
PlaceContext::NonMutatingUse(NonMutatingUseContext::ShallowBorrow(..)) |
244+
PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) |
243245
PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) => {
244246
self.not_ssa(local);
245247
}

src/librustc_codegen_ssa/mir/rvalue.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,25 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
397397
})
398398
}
399399

400+
mir::Rvalue::AddressOf(mutability, ref place) => {
401+
let cg_place = self.codegen_place(&mut bx, place);
402+
403+
let ty = cg_place.layout.ty;
404+
405+
let val = if !bx.cx().type_has_metadata(ty) {
406+
OperandValue::Immediate(cg_place.llval)
407+
} else {
408+
OperandValue::Pair(cg_place.llval, cg_place.llextra.unwrap())
409+
};
410+
411+
(bx, OperandRef {
412+
val,
413+
layout: self.cx.layout_of(self.cx.tcx().mk_ptr(
414+
ty::TypeAndMut { ty, mutbl: mutability.into() }
415+
)),
416+
})
417+
}
418+
400419
mir::Rvalue::Len(ref place) => {
401420
let size = self.evaluate_array_len(&mut bx, place);
402421
let operand = OperandRef {
@@ -710,6 +729,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
710729
pub fn rvalue_creates_operand(&self, rvalue: &mir::Rvalue<'tcx>) -> bool {
711730
match *rvalue {
712731
mir::Rvalue::Ref(..) |
732+
mir::Rvalue::AddressOf(..) |
713733
mir::Rvalue::Len(..) |
714734
mir::Rvalue::Cast(..) | // (*)
715735
mir::Rvalue::BinaryOp(..) |

src/librustc_mir/borrow_check/mod.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,6 +1171,31 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
11711171
);
11721172
}
11731173

1174+
1175+
Rvalue::AddressOf(mutability, ref place) => {
1176+
let access_kind = match mutability {
1177+
Mutability::Mut => (Deep, Write(WriteKind::MutableBorrow(BorrowKind::Mut {
1178+
allow_two_phase_borrow: false,
1179+
}))),
1180+
Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
1181+
};
1182+
1183+
self.access_place(
1184+
context,
1185+
(place, span),
1186+
access_kind,
1187+
LocalMutationIsAllowed::No,
1188+
flow_state,
1189+
);
1190+
1191+
self.check_if_path_or_subpath_is_moved(
1192+
context,
1193+
InitializationRequiringAction::Use,
1194+
(place, span),
1195+
flow_state,
1196+
);
1197+
}
1198+
11741199
Rvalue::Use(ref operand)
11751200
| Rvalue::Repeat(ref operand, _)
11761201
| Rvalue::UnaryOp(_ /*un_op*/, ref operand)

src/librustc_mir/borrow_check/nll/invalidation.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rustc::mir::visit::Visitor;
1515
use rustc::mir::{BasicBlock, Location, Mir, Place, Rvalue};
1616
use rustc::mir::{Statement, StatementKind};
1717
use rustc::mir::{Terminator, TerminatorKind};
18-
use rustc::mir::{Operand, BorrowKind};
18+
use rustc::mir::{Operand, BorrowKind, Mutability};
1919
use rustc_data_structures::graph::dominators::Dominators;
2020

2121
pub(super) fn generate_invalidates<'cx, 'gcx, 'tcx>(
@@ -346,6 +346,22 @@ impl<'cg, 'cx, 'tcx, 'gcx> InvalidationGenerator<'cx, 'tcx, 'gcx> {
346346
);
347347
}
348348

349+
Rvalue::AddressOf(mutability, ref place) => {
350+
let access_kind = match mutability {
351+
Mutability::Mut => (Deep, Write(WriteKind::MutableBorrow(BorrowKind::Mut {
352+
allow_two_phase_borrow: false,
353+
}))),
354+
Mutability::Not => (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))),
355+
};
356+
357+
self.access_place(
358+
context,
359+
place,
360+
access_kind,
361+
LocalMutationIsAllowed::No,
362+
);
363+
}
364+
349365
Rvalue::Use(ref operand)
350366
| Rvalue::Repeat(ref operand, _)
351367
| Rvalue::UnaryOp(_ /*un_op*/, ref operand)

src/librustc_mir/borrow_check/nll/type_check/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1992,8 +1992,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
19921992
self.add_reborrow_constraint(location, region, borrowed_place);
19931993
}
19941994

1995-
// FIXME: These other cases have to be implemented in future PRs
1996-
Rvalue::Use(..)
1995+
Rvalue::AddressOf(..)
1996+
| Rvalue::Use(..)
19971997
| Rvalue::Len(..)
19981998
| Rvalue::BinaryOp(..)
19991999
| Rvalue::CheckedBinaryOp(..)
@@ -2010,6 +2010,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
20102010
Rvalue::Use(_)
20112011
| Rvalue::Repeat(..)
20122012
| Rvalue::Ref(..)
2013+
| Rvalue::AddressOf(..)
20132014
| Rvalue::Len(..)
20142015
| Rvalue::Cast(..)
20152016
| Rvalue::BinaryOp(..)

src/librustc_mir/dataflow/move_paths/builder.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
316316
}
317317
}
318318
Rvalue::Ref(..) |
319+
Rvalue::AddressOf(..) |
319320
Rvalue::Discriminant(..) |
320321
Rvalue::Len(..) |
321322
Rvalue::NullaryOp(NullOp::SizeOf, _) |

src/librustc_mir/interpret/step.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
237237
)?;
238238
}
239239

240-
Ref(_, _, ref place) => {
240+
AddressOf(_, ref place)
241+
| Ref(_, _, ref place) => {
241242
let src = self.eval_place(place)?;
242243
let val = self.force_allocation(src)?;
243244
self.write_immediate(val.to_ref(), dest)?;

src/librustc_mir/transform/add_retag.rs

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -155,22 +155,11 @@ impl MirPass for AddRetag {
155155
// iterate backwards using indices.
156156
for i in (0..block_data.statements.len()).rev() {
157157
let (retag_kind, place) = match block_data.statements[i].kind {
158-
// If we are casting *from* a reference, we may have to retag-as-raw.
159-
StatementKind::Assign(ref place, box Rvalue::Cast(
160-
CastKind::Misc,
161-
ref src,
162-
dest_ty,
163-
)) => {
164-
let src_ty = src.ty(&*local_decls, tcx);
165-
if src_ty.is_region_ptr() {
166-
// The only `Misc` casts on references are those creating raw pointers.
167-
assert!(dest_ty.is_unsafe_ptr());
168-
(RetagKind::Raw, place)
169-
} else {
170-
// Some other cast, no retag
171-
continue
172-
}
158+
// Retag-as-raw after escaping to a raw pointer.
159+
StatementKind::Assign(ref place, box Rvalue::AddressOf(..)) => {
160+
(RetagKind::Raw, place)
173161
}
162+
174163
// Assignments of reference or ptr type are the ones where we may have
175164
// to update tags. This includes `x = &[mut] ...` and hence
176165
// we also retag after taking a reference!

src/librustc_mir/transform/const_prop.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
327327
},
328328
Rvalue::Repeat(..) |
329329
Rvalue::Ref(..) |
330+
Rvalue::AddressOf(..) |
330331
Rvalue::Aggregate(..) |
331332
Rvalue::NullaryOp(NullOp::Box, _) |
332333
Rvalue::Discriminant(..) => None,

src/librustc_mir/transform/promote_consts.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,8 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
299299
Candidate::Ref(loc) => {
300300
let ref mut statement = blocks[loc.block].statements[loc.statement_index];
301301
match statement.kind {
302-
StatementKind::Assign(_, box Rvalue::Ref(_, _, ref mut place)) => {
302+
StatementKind::Assign(_, box Rvalue::Ref(_, _, ref mut place))
303+
| StatementKind::Assign(_, box Rvalue::AddressOf(_, ref mut place)) => {
303304
// Find the underlying local for this (necessarily interior) borrow.
304305
let mut place = place;
305306
while let Place::Projection(ref mut proj) = *place {

0 commit comments

Comments
 (0)