Introduce NullOp::AlignOf

This commit is contained in:
Gary Guo 2021-09-07 16:06:07 +01:00
parent b69fe57261
commit 1c3409f333
13 changed files with 54 additions and 33 deletions

View file

@ -726,15 +726,20 @@ fn codegen_stmt<'tcx>(
let ptr = fx.bcx.inst_results(call)[0]; let ptr = fx.bcx.inst_results(call)[0];
lval.write_cvalue(fx, CValue::by_val(ptr, box_layout)); lval.write_cvalue(fx, CValue::by_val(ptr, box_layout));
} }
Rvalue::NullaryOp(NullOp::SizeOf, ty) => { Rvalue::NullaryOp(null_op, ty) => {
assert!( assert!(
lval.layout() lval.layout()
.ty .ty
.is_sized(fx.tcx.at(stmt.source_info.span), ParamEnv::reveal_all()) .is_sized(fx.tcx.at(stmt.source_info.span), ParamEnv::reveal_all())
); );
let ty_size = fx.layout_of(fx.monomorphize(ty)).size.bytes(); let layout = fx.layout_of(fx.monomorphize(ty));
let val = match null_op {
NullOp::SizeOf => layout.size.bytes(),
NullOp::AlignOf => layout.align.abi.bytes(),
NullOp::Box => unreachable!(),
};
let val = let val =
CValue::const_val(fx, fx.layout_of(fx.tcx.types.usize), ty_size.into()); CValue::const_val(fx, fx.layout_of(fx.tcx.types.usize), val.into());
lval.write_cvalue(fx, val); lval.write_cvalue(fx, val);
} }
Rvalue::Aggregate(ref kind, ref operands) => match kind.as_ref() { Rvalue::Aggregate(ref kind, ref operands) => match kind.as_ref() {

View file

@ -823,7 +823,7 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
dest.write_cvalue(fx, val); dest.write_cvalue(fx, val);
}; };
pref_align_of | min_align_of | needs_drop | type_id | type_name | variant_count, () { pref_align_of | needs_drop | type_id | type_name | variant_count, () {
let const_val = let const_val =
fx.tcx.const_eval_instance(ParamEnv::reveal_all(), instance, None).unwrap(); fx.tcx.const_eval_instance(ParamEnv::reveal_all(), instance, None).unwrap();
let val = crate::constant::codegen_const_value( let val = crate::constant::codegen_const_value(

View file

@ -104,7 +104,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
} }
} }
sym::pref_align_of sym::pref_align_of
| sym::min_align_of
| sym::needs_drop | sym::needs_drop
| sym::type_id | sym::type_id
| sym::type_name | sym::type_name

View file

@ -487,20 +487,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
) )
} }
mir::Rvalue::NullaryOp(mir::NullOp::SizeOf, ty) => {
let ty = self.monomorphize(ty);
assert!(bx.cx().type_is_sized(ty));
let val = bx.cx().const_usize(bx.cx().layout_of(ty).size.bytes());
let tcx = self.cx.tcx();
(
bx,
OperandRef {
val: OperandValue::Immediate(val),
layout: self.cx.layout_of(tcx.types.usize),
},
)
}
mir::Rvalue::NullaryOp(mir::NullOp::Box, content_ty) => { mir::Rvalue::NullaryOp(mir::NullOp::Box, content_ty) => {
let content_ty = self.monomorphize(content_ty); let content_ty = self.monomorphize(content_ty);
let content_layout = bx.cx().layout_of(content_ty); let content_layout = bx.cx().layout_of(content_ty);
@ -525,6 +511,27 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let operand = OperandRef { val: OperandValue::Immediate(val), layout: box_layout }; let operand = OperandRef { val: OperandValue::Immediate(val), layout: box_layout };
(bx, operand) (bx, operand)
} }
mir::Rvalue::NullaryOp(null_op, ty) => {
let ty = self.monomorphize(ty);
assert!(bx.cx().type_is_sized(ty));
let layout = bx.cx().layout_of(ty);
let val = match null_op {
mir::NullOp::SizeOf => layout.size.bytes(),
mir::NullOp::AlignOf => layout.align.abi.bytes(),
mir::NullOp::Box => unreachable!(),
};
let val = bx.cx().const_usize(val);
let tcx = self.cx.tcx();
(
bx,
OperandRef {
val: OperandValue::Immediate(val),
layout: self.cx.layout_of(tcx.types.usize),
},
)
}
mir::Rvalue::ThreadLocalRef(def_id) => { mir::Rvalue::ThreadLocalRef(def_id) => {
assert!(bx.cx().tcx().is_static(def_id)); assert!(bx.cx().tcx().is_static(def_id));
let static_ = bx.get_static(def_id); let static_ = bx.get_static(def_id);

View file

@ -160,17 +160,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
self.write_scalar(Scalar::from_machine_usize(result, self), dest)?; self.write_scalar(Scalar::from_machine_usize(result, self), dest)?;
} }
sym::min_align_of sym::pref_align_of
| sym::pref_align_of
| sym::needs_drop | sym::needs_drop
| sym::type_id | sym::type_id
| sym::type_name | sym::type_name
| sym::variant_count => { | sym::variant_count => {
let gid = GlobalId { instance, promoted: None }; let gid = GlobalId { instance, promoted: None };
let ty = match intrinsic_name { let ty = match intrinsic_name {
sym::min_align_of | sym::pref_align_of | sym::variant_count => { sym::pref_align_of | sym::variant_count => self.tcx.types.usize,
self.tcx.types.usize
}
sym::needs_drop => self.tcx.types.bool, sym::needs_drop => self.tcx.types.bool,
sym::type_id => self.tcx.types.u64, sym::type_id => self.tcx.types.u64,
sym::type_name => self.tcx.mk_static_str(), sym::type_name => self.tcx.mk_static_str(),

View file

@ -270,18 +270,23 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
M::box_alloc(self, &dest)?; M::box_alloc(self, &dest)?;
} }
NullaryOp(mir::NullOp::SizeOf, ty) => { NullaryOp(null_op, ty) => {
let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty); let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty);
let layout = self.layout_of(ty)?; let layout = self.layout_of(ty)?;
if layout.is_unsized() { if layout.is_unsized() {
// FIXME: This should be a span_bug (#80742) // FIXME: This should be a span_bug (#80742)
self.tcx.sess.delay_span_bug( self.tcx.sess.delay_span_bug(
self.frame().current_span(), self.frame().current_span(),
&format!("SizeOf nullary MIR operator called for unsized type {}", ty), &format!("Nullary MIR operator called for unsized type {}", ty),
); );
throw_inval!(SizeOfUnsizedType(ty)); throw_inval!(SizeOfUnsizedType(ty));
} }
self.write_scalar(Scalar::from_machine_usize(layout.size.bytes(), self), &dest)?; let val = match null_op {
mir::NullOp::SizeOf => layout.size.bytes(),
mir::NullOp::AlignOf => layout.align.abi.bytes(),
mir::NullOp::Box => unreachable!(),
};
self.write_scalar(Scalar::from_machine_usize(val, self), &dest)?;
} }
Cast(cast_kind, ref operand, cast_ty) => { Cast(cast_kind, ref operand, cast_ty) => {

View file

@ -648,7 +648,7 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> {
} }
} }
Rvalue::NullaryOp(NullOp::SizeOf, _) => {} Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {}
Rvalue::NullaryOp(NullOp::Box, _) => self.check_op(ops::HeapAllocation), Rvalue::NullaryOp(NullOp::Box, _) => self.check_op(ops::HeapAllocation),
Rvalue::UnaryOp(_, ref operand) => { Rvalue::UnaryOp(_, ref operand) => {

View file

@ -520,6 +520,7 @@ impl<'tcx> Validator<'_, 'tcx> {
Rvalue::NullaryOp(op, _) => match op { Rvalue::NullaryOp(op, _) => match op {
NullOp::Box => return Err(Unpromotable), NullOp::Box => return Err(Unpromotable),
NullOp::SizeOf => {} NullOp::SizeOf => {}
NullOp::AlignOf => {}
}, },
Rvalue::UnaryOp(op, operand) => { Rvalue::UnaryOp(op, operand) => {

View file

@ -2278,6 +2278,8 @@ impl BinOp {
pub enum NullOp { pub enum NullOp {
/// Returns the size of a value of that type /// Returns the size of a value of that type
SizeOf, SizeOf,
/// Returns the minimum alignment of a type
AlignOf,
/// Creates a new uninitialized box for a value of that type /// Creates a new uninitialized box for a value of that type
Box, Box,
} }

View file

@ -196,7 +196,7 @@ impl<'tcx> Rvalue<'tcx> {
Rvalue::UnaryOp(UnOp::Not | UnOp::Neg, ref operand) => operand.ty(local_decls, tcx), Rvalue::UnaryOp(UnOp::Not | UnOp::Neg, ref operand) => operand.ty(local_decls, tcx),
Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx), Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx),
Rvalue::NullaryOp(NullOp::Box, t) => tcx.mk_box(t), Rvalue::NullaryOp(NullOp::Box, t) => tcx.mk_box(t),
Rvalue::NullaryOp(NullOp::SizeOf, _) => tcx.types.usize, Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => tcx.types.usize,
Rvalue::Aggregate(ref ak, ref ops) => match **ak { Rvalue::Aggregate(ref ak, ref ops) => match **ak {
AggregateKind::Array(ty) => tcx.mk_array(ty, ops.len() as u64), AggregateKind::Array(ty) => tcx.mk_array(ty, ops.len() as u64),
AggregateKind::Tuple => tcx.mk_tup(ops.iter().map(|op| op.ty(local_decls, tcx))), AggregateKind::Tuple => tcx.mk_tup(ops.iter().map(|op| op.ty(local_decls, tcx))),

View file

@ -342,7 +342,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
| Rvalue::AddressOf(..) | Rvalue::AddressOf(..)
| Rvalue::Discriminant(..) | Rvalue::Discriminant(..)
| Rvalue::Len(..) | Rvalue::Len(..)
| Rvalue::NullaryOp(NullOp::SizeOf, _) | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _)
| Rvalue::NullaryOp(NullOp::Box, _) => { | Rvalue::NullaryOp(NullOp::Box, _) => {
// This returns an rvalue with uninitialized contents. We can't // This returns an rvalue with uninitialized contents. We can't
// move out of it here because it is an rvalue - assignments always // move out of it here because it is an rvalue - assignments always

View file

@ -92,14 +92,19 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
// since their semantics depend on the value of overflow-checks flag used // since their semantics depend on the value of overflow-checks flag used
// during codegen. Issue #35310. // during codegen. Issue #35310.
} }
sym::size_of => { sym::size_of | sym::min_align_of => {
if let Some((destination, target)) = *destination { if let Some((destination, target)) = *destination {
let tp_ty = substs.type_at(0); let tp_ty = substs.type_at(0);
let null_op = match intrinsic_name {
sym::size_of => NullOp::SizeOf,
sym::min_align_of => NullOp::AlignOf,
_ => bug!("unexpected intrinsic"),
};
block.statements.push(Statement { block.statements.push(Statement {
source_info: terminator.source_info, source_info: terminator.source_info,
kind: StatementKind::Assign(Box::new(( kind: StatementKind::Assign(Box::new((
destination, destination,
Rvalue::NullaryOp(NullOp::SizeOf, tp_ty), Rvalue::NullaryOp(null_op, tp_ty),
))), ))),
}); });
terminator.kind = TerminatorKind::Goto { target }; terminator.kind = TerminatorKind::Goto { target };

View file

@ -192,7 +192,7 @@ fn check_rvalue(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, def_id: DefId, rvalue: &Rv
)) ))
} }
}, },
Rvalue::NullaryOp(NullOp::SizeOf, _) => Ok(()), Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => Ok(()),
Rvalue::NullaryOp(NullOp::Box, _) => Err((span, "heap allocations are not allowed in const fn".into())), Rvalue::NullaryOp(NullOp::Box, _) => Err((span, "heap allocations are not allowed in const fn".into())),
Rvalue::UnaryOp(_, operand) => { Rvalue::UnaryOp(_, operand) => {
let ty = operand.ty(body, tcx); let ty = operand.ty(body, tcx);