From 9b8e3eb8f76a7debacf35f9d5c3dcfb509ea6fc3 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 29 Aug 2023 15:07:14 +0000 Subject: [PATCH 1/4] Move around constants' `Stable` impls a bit --- compiler/rustc_smir/src/rustc_smir/mod.rs | 35 +++++++++++++---------- compiler/rustc_smir/src/stable_mir/ty.rs | 20 ++++++------- 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 7877c91c2cf1a..b3f3f6d01d780 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -1083,8 +1083,21 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> { type T = stable_mir::ty::Const; fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { - let cnst = ConstantKind::from_const(*self, tables.tcx); - stable_mir::ty::Const { literal: cnst.stable(tables) } + stable_mir::ty::Const { + literal: match self.kind() { + ty::Value(val) => { + let const_val = tables.tcx.valtree_to_const_val((self.ty(), val)); + stable_mir::ty::ConstantKind::Allocated(new_allocation( + self.ty(), + const_val, + tables, + )) + } + ty::ParamCt(param) => stable_mir::ty::ConstantKind::ParamCt(opaque(¶m)), + ty::ErrorCt(_) => unreachable!(), + _ => unimplemented!(), + }, + } } } @@ -1155,26 +1168,18 @@ impl<'tcx> Stable<'tcx> for rustc_middle::mir::ConstantKind<'tcx> { type T = stable_mir::ty::ConstantKind; fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { - match self { - ConstantKind::Ty(c) => match c.kind() { - ty::Value(val) => { - let const_val = tables.tcx.valtree_to_const_val((c.ty(), val)); - stable_mir::ty::ConstantKind::Allocated(new_allocation(self, const_val, tables)) - } - ty::ParamCt(param) => stable_mir::ty::ConstantKind::ParamCt(opaque(¶m)), - ty::ErrorCt(_) => unreachable!(), - _ => unimplemented!(), - }, + match *self { + ConstantKind::Ty(c) => c.stable(tables).literal, ConstantKind::Unevaluated(unev_const, ty) => { stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst { - ty: tables.intern_ty(*ty), + ty: tables.intern_ty(ty), def: tables.const_def(unev_const.def), args: unev_const.args.stable(tables), promoted: unev_const.promoted.map(|u| u.as_u32()), }) } - ConstantKind::Val(val, _) => { - stable_mir::ty::ConstantKind::Allocated(new_allocation(self, *val, tables)) + ConstantKind::Val(val, ty) => { + stable_mir::ty::ConstantKind::Allocated(new_allocation(ty, val, tables)) } } } diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index fce5375f848f8..804d532b7b59f 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -301,8 +301,9 @@ impl Allocation { // We need this method instead of a Stable implementation // because we need to get `Ty` of the const we are trying to create, to do that // we need to have access to `ConstantKind` but we can't access that inside Stable impl. +#[allow(rustc::usage_of_qualified_ty)] pub fn new_allocation<'tcx>( - const_kind: &rustc_middle::mir::ConstantKind<'tcx>, + ty: rustc_middle::ty::Ty<'tcx>, const_value: ConstValue<'tcx>, tables: &mut Tables<'tcx>, ) -> Allocation { @@ -311,7 +312,7 @@ pub fn new_allocation<'tcx>( let size = scalar.size(); let align = tables .tcx - .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(const_kind.ty())) + .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(ty)) .unwrap() .align; let mut allocation = rustc_middle::mir::interpret::Allocation::uninit(size, align.abi); @@ -321,11 +322,8 @@ pub fn new_allocation<'tcx>( allocation.stable(tables) } ConstValue::ZeroSized => { - let align = tables - .tcx - .layout_of(rustc_middle::ty::ParamEnv::empty().and(const_kind.ty())) - .unwrap() - .align; + let align = + tables.tcx.layout_of(rustc_middle::ty::ParamEnv::empty().and(ty)).unwrap().align; Allocation::new_empty_allocation(align.abi) } ConstValue::Slice { data, start, end } => { @@ -336,10 +334,8 @@ pub fn new_allocation<'tcx>( (end - start) as u64, &tables.tcx, ); - let layout = tables - .tcx - .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(const_kind.ty())) - .unwrap(); + let layout = + tables.tcx.layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(ty)).unwrap(); let mut allocation = rustc_middle::mir::interpret::Allocation::uninit(layout.size, layout.align.abi); allocation @@ -361,7 +357,7 @@ pub fn new_allocation<'tcx>( ConstValue::ByRef { alloc, offset } => { let ty_size = tables .tcx - .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(const_kind.ty())) + .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(ty)) .unwrap() .size; allocation_filter(&alloc.0, alloc_range(offset, ty_size), tables) From 3a736a747dbb569da4eac27ecf6c25fed8c479c6 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 29 Aug 2023 15:11:51 +0000 Subject: [PATCH 2/4] Exhaustively match on `ty::Const::kind` --- compiler/rustc_smir/src/rustc_smir/mod.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index b3f3f6d01d780..316affa2c65d8 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -1095,7 +1095,18 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> { } ty::ParamCt(param) => stable_mir::ty::ConstantKind::ParamCt(opaque(¶m)), ty::ErrorCt(_) => unreachable!(), - _ => unimplemented!(), + ty::InferCt(_) => unreachable!(), + ty::BoundCt(_, _) => unimplemented!(), + ty::PlaceholderCt(_) => unimplemented!(), + ty::Unevaluated(uv) => { + stable_mir::ty::ConstantKind::Unevaluated(stable_mir::ty::UnevaluatedConst { + ty: tables.intern_ty(self.ty()), + def: tables.const_def(uv.def), + args: uv.args.stable(tables), + promoted: None, + }) + } + ty::ExprCt(_) => unimplemented!(), }, } } From 03b03f9feecb98c16784635a7819e1c548baf2e9 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 29 Aug 2023 15:12:20 +0000 Subject: [PATCH 3/4] Reuse the `ty::Const: Stable` impl --- compiler/rustc_smir/src/rustc_smir/mod.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 316affa2c65d8..529e71688e92a 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -10,7 +10,7 @@ use crate::rustc_internal::{self, opaque}; use crate::stable_mir::mir::{CopyNonOverlapping, UserTypeProjection, VariantIdx}; use crate::stable_mir::ty::{ - allocation_filter, new_allocation, Const, FloatTy, GenericParamDef, IntTy, Movability, RigidTy, + allocation_filter, new_allocation, FloatTy, GenericParamDef, IntTy, Movability, RigidTy, TyKind, UintTy, }; use crate::stable_mir::{self, Context}; @@ -205,8 +205,7 @@ impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> { match self { Use(op) => stable_mir::mir::Rvalue::Use(op.stable(tables)), Repeat(op, len) => { - let cnst = ConstantKind::from_const(*len, tables.tcx); - let len = Const { literal: cnst.stable(tables) }; + let len = len.stable(tables); stable_mir::mir::Rvalue::Repeat(op.stable(tables), len) } Ref(region, kind, place) => stable_mir::mir::Rvalue::Ref( @@ -394,8 +393,7 @@ impl<'tcx> Stable<'tcx> for ty::TermKind<'tcx> { match self { ty::TermKind::Ty(ty) => TermKind::Type(tables.intern_ty(*ty)), ty::TermKind::Const(cnst) => { - let cnst = ConstantKind::from_const(*cnst, tables.tcx); - let cnst = Const { literal: cnst.stable(tables) }; + let cnst = cnst.stable(tables); TermKind::Const(cnst) } } From 92cfd209f15a015b3269e1f350e08f837d1bd0df Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 29 Aug 2023 15:17:16 +0000 Subject: [PATCH 4/4] Move some logic using rustc datastructures to the `rustc_smir` module --- compiler/rustc_smir/src/rustc_smir/alloc.rs | 124 +++++++++++++++++++ compiler/rustc_smir/src/rustc_smir/mod.rs | 17 +-- compiler/rustc_smir/src/stable_mir/ty.rs | 125 +------------------- 3 files changed, 135 insertions(+), 131 deletions(-) create mode 100644 compiler/rustc_smir/src/rustc_smir/alloc.rs diff --git a/compiler/rustc_smir/src/rustc_smir/alloc.rs b/compiler/rustc_smir/src/rustc_smir/alloc.rs new file mode 100644 index 0000000000000..33c75250adcd6 --- /dev/null +++ b/compiler/rustc_smir/src/rustc_smir/alloc.rs @@ -0,0 +1,124 @@ +use rustc_middle::mir::interpret::{alloc_range, AllocRange, ConstValue, Pointer}; + +use crate::{ + rustc_internal::opaque, + rustc_smir::{Stable, Tables}, + stable_mir::mir::Mutability, + stable_mir::ty::{Allocation, ProvenanceMap}, +}; + +/// Creates new empty `Allocation` from given `Align`. +fn new_empty_allocation(align: rustc_target::abi::Align) -> Allocation { + Allocation { + bytes: Vec::new(), + provenance: ProvenanceMap { ptrs: Vec::new() }, + align: align.bytes(), + mutability: Mutability::Not, + } +} + +// We need this method instead of a Stable implementation +// because we need to get `Ty` of the const we are trying to create, to do that +// we need to have access to `ConstantKind` but we can't access that inside Stable impl. +#[allow(rustc::usage_of_qualified_ty)] +pub fn new_allocation<'tcx>( + ty: rustc_middle::ty::Ty<'tcx>, + const_value: ConstValue<'tcx>, + tables: &mut Tables<'tcx>, +) -> Allocation { + match const_value { + ConstValue::Scalar(scalar) => { + let size = scalar.size(); + let align = tables + .tcx + .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(ty)) + .unwrap() + .align; + let mut allocation = rustc_middle::mir::interpret::Allocation::uninit(size, align.abi); + allocation + .write_scalar(&tables.tcx, alloc_range(rustc_target::abi::Size::ZERO, size), scalar) + .unwrap(); + allocation.stable(tables) + } + ConstValue::ZeroSized => { + let align = + tables.tcx.layout_of(rustc_middle::ty::ParamEnv::empty().and(ty)).unwrap().align; + new_empty_allocation(align.abi) + } + ConstValue::Slice { data, start, end } => { + let alloc_id = tables.tcx.create_memory_alloc(data); + let ptr = Pointer::new(alloc_id, rustc_target::abi::Size::from_bytes(start)); + let scalar_ptr = rustc_middle::mir::interpret::Scalar::from_pointer(ptr, &tables.tcx); + let scalar_len = rustc_middle::mir::interpret::Scalar::from_target_usize( + (end - start) as u64, + &tables.tcx, + ); + let layout = + tables.tcx.layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(ty)).unwrap(); + let mut allocation = + rustc_middle::mir::interpret::Allocation::uninit(layout.size, layout.align.abi); + allocation + .write_scalar( + &tables.tcx, + alloc_range(rustc_target::abi::Size::ZERO, tables.tcx.data_layout.pointer_size), + scalar_ptr, + ) + .unwrap(); + allocation + .write_scalar( + &tables.tcx, + alloc_range(tables.tcx.data_layout.pointer_size, scalar_len.size()), + scalar_len, + ) + .unwrap(); + allocation.stable(tables) + } + ConstValue::ByRef { alloc, offset } => { + let ty_size = tables + .tcx + .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(ty)) + .unwrap() + .size; + allocation_filter(&alloc.0, alloc_range(offset, ty_size), tables) + } + } +} + +/// Creates an `Allocation` only from information within the `AllocRange`. +pub(super) fn allocation_filter<'tcx>( + alloc: &rustc_middle::mir::interpret::Allocation, + alloc_range: AllocRange, + tables: &mut Tables<'tcx>, +) -> Allocation { + let mut bytes: Vec> = alloc + .inspect_with_uninit_and_ptr_outside_interpreter( + alloc_range.start.bytes_usize()..alloc_range.end().bytes_usize(), + ) + .iter() + .copied() + .map(Some) + .collect(); + for (i, b) in bytes.iter_mut().enumerate() { + if !alloc + .init_mask() + .get(rustc_target::abi::Size::from_bytes(i + alloc_range.start.bytes_usize())) + { + *b = None; + } + } + let mut ptrs = Vec::new(); + for (offset, prov) in alloc + .provenance() + .ptrs() + .iter() + .filter(|a| a.0 >= alloc_range.start && a.0 <= alloc_range.end()) + { + ptrs.push((offset.bytes_usize() - alloc_range.start.bytes_usize(), opaque(prov))); + } + Allocation { + bytes: bytes, + provenance: ProvenanceMap { ptrs }, + align: alloc.align.bytes(), + mutability: alloc.mutability.stable(tables), + } +} diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 529e71688e92a..d36835d37f54b 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -9,10 +9,7 @@ use crate::rustc_internal::{self, opaque}; use crate::stable_mir::mir::{CopyNonOverlapping, UserTypeProjection, VariantIdx}; -use crate::stable_mir::ty::{ - allocation_filter, new_allocation, FloatTy, GenericParamDef, IntTy, Movability, RigidTy, - TyKind, UintTy, -}; +use crate::stable_mir::ty::{FloatTy, GenericParamDef, IntTy, Movability, RigidTy, TyKind, UintTy}; use crate::stable_mir::{self, Context}; use rustc_hir as hir; use rustc_middle::mir::interpret::alloc_range; @@ -22,6 +19,8 @@ use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc_target::abi::FieldIdx; use tracing::debug; +mod alloc; + impl<'tcx> Context for Tables<'tcx> { fn local_crate(&self) -> stable_mir::Crate { smir_crate(self.tcx, LOCAL_CRATE) @@ -1085,7 +1084,7 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> { literal: match self.kind() { ty::Value(val) => { let const_val = tables.tcx.valtree_to_const_val((self.ty(), val)); - stable_mir::ty::ConstantKind::Allocated(new_allocation( + stable_mir::ty::ConstantKind::Allocated(alloc::new_allocation( self.ty(), const_val, tables, @@ -1130,7 +1129,11 @@ impl<'tcx> Stable<'tcx> for mir::interpret::Allocation { type T = stable_mir::ty::Allocation; fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { - allocation_filter(self, alloc_range(rustc_target::abi::Size::ZERO, self.size()), tables) + alloc::allocation_filter( + self, + alloc_range(rustc_target::abi::Size::ZERO, self.size()), + tables, + ) } } @@ -1188,7 +1191,7 @@ impl<'tcx> Stable<'tcx> for rustc_middle::mir::ConstantKind<'tcx> { }) } ConstantKind::Val(val, ty) => { - stable_mir::ty::ConstantKind::Allocated(new_allocation(ty, val, tables)) + stable_mir::ty::ConstantKind::Allocated(alloc::new_allocation(ty, val, tables)) } } } diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index 804d532b7b59f..d49f3243777ff 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -1,10 +1,5 @@ -use rustc_middle::mir::interpret::{alloc_range, AllocRange, ConstValue, Pointer}; - use super::{mir::Mutability, mir::Safety, with, DefId}; -use crate::{ - rustc_internal::{opaque, Opaque}, - rustc_smir::{Stable, Tables}, -}; +use crate::rustc_internal::Opaque; #[derive(Copy, Clone, Debug)] pub struct Ty(pub usize); @@ -286,124 +281,6 @@ pub struct Allocation { pub mutability: Mutability, } -impl Allocation { - /// Creates new empty `Allocation` from given `Align`. - fn new_empty_allocation(align: rustc_target::abi::Align) -> Allocation { - Allocation { - bytes: Vec::new(), - provenance: ProvenanceMap { ptrs: Vec::new() }, - align: align.bytes(), - mutability: Mutability::Not, - } - } -} - -// We need this method instead of a Stable implementation -// because we need to get `Ty` of the const we are trying to create, to do that -// we need to have access to `ConstantKind` but we can't access that inside Stable impl. -#[allow(rustc::usage_of_qualified_ty)] -pub fn new_allocation<'tcx>( - ty: rustc_middle::ty::Ty<'tcx>, - const_value: ConstValue<'tcx>, - tables: &mut Tables<'tcx>, -) -> Allocation { - match const_value { - ConstValue::Scalar(scalar) => { - let size = scalar.size(); - let align = tables - .tcx - .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(ty)) - .unwrap() - .align; - let mut allocation = rustc_middle::mir::interpret::Allocation::uninit(size, align.abi); - allocation - .write_scalar(&tables.tcx, alloc_range(rustc_target::abi::Size::ZERO, size), scalar) - .unwrap(); - allocation.stable(tables) - } - ConstValue::ZeroSized => { - let align = - tables.tcx.layout_of(rustc_middle::ty::ParamEnv::empty().and(ty)).unwrap().align; - Allocation::new_empty_allocation(align.abi) - } - ConstValue::Slice { data, start, end } => { - let alloc_id = tables.tcx.create_memory_alloc(data); - let ptr = Pointer::new(alloc_id, rustc_target::abi::Size::from_bytes(start)); - let scalar_ptr = rustc_middle::mir::interpret::Scalar::from_pointer(ptr, &tables.tcx); - let scalar_len = rustc_middle::mir::interpret::Scalar::from_target_usize( - (end - start) as u64, - &tables.tcx, - ); - let layout = - tables.tcx.layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(ty)).unwrap(); - let mut allocation = - rustc_middle::mir::interpret::Allocation::uninit(layout.size, layout.align.abi); - allocation - .write_scalar( - &tables.tcx, - alloc_range(rustc_target::abi::Size::ZERO, tables.tcx.data_layout.pointer_size), - scalar_ptr, - ) - .unwrap(); - allocation - .write_scalar( - &tables.tcx, - alloc_range(tables.tcx.data_layout.pointer_size, scalar_len.size()), - scalar_len, - ) - .unwrap(); - allocation.stable(tables) - } - ConstValue::ByRef { alloc, offset } => { - let ty_size = tables - .tcx - .layout_of(rustc_middle::ty::ParamEnv::reveal_all().and(ty)) - .unwrap() - .size; - allocation_filter(&alloc.0, alloc_range(offset, ty_size), tables) - } - } -} - -/// Creates an `Allocation` only from information within the `AllocRange`. -pub fn allocation_filter<'tcx>( - alloc: &rustc_middle::mir::interpret::Allocation, - alloc_range: AllocRange, - tables: &mut Tables<'tcx>, -) -> Allocation { - let mut bytes: Vec> = alloc - .inspect_with_uninit_and_ptr_outside_interpreter( - alloc_range.start.bytes_usize()..alloc_range.end().bytes_usize(), - ) - .iter() - .copied() - .map(Some) - .collect(); - for (i, b) in bytes.iter_mut().enumerate() { - if !alloc - .init_mask() - .get(rustc_target::abi::Size::from_bytes(i + alloc_range.start.bytes_usize())) - { - *b = None; - } - } - let mut ptrs = Vec::new(); - for (offset, prov) in alloc - .provenance() - .ptrs() - .iter() - .filter(|a| a.0 >= alloc_range.start && a.0 <= alloc_range.end()) - { - ptrs.push((offset.bytes_usize() - alloc_range.start.bytes_usize(), opaque(prov))); - } - Allocation { - bytes: bytes, - provenance: ProvenanceMap { ptrs }, - align: alloc.align.bytes(), - mutability: alloc.mutability.stable(tables), - } -} - #[derive(Clone, Debug)] pub enum ConstantKind { Allocated(Allocation),