mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Store field remapping information together with the LLVM type in a new TypeLowering struct instead of an extra cache.
This commit is contained in:
parent
7dbc568325
commit
4a4e9e3cf8
@ -74,15 +74,15 @@ pub struct CodegenCx<'ll, 'tcx> {
|
|||||||
/// See <https://llvm.org/docs/LangRef.html#the-llvm-used-global-variable> for details
|
/// See <https://llvm.org/docs/LangRef.html#the-llvm-used-global-variable> for details
|
||||||
pub used_statics: RefCell<Vec<&'ll Value>>,
|
pub used_statics: RefCell<Vec<&'ll Value>>,
|
||||||
|
|
||||||
pub lltypes: RefCell<FxHashMap<(Ty<'tcx>, Option<VariantIdx>), &'ll Type>>,
|
/// Mapping of non-scalar types to llvm types and field remapping if needed.
|
||||||
|
pub type_lowering: RefCell<FxHashMap<(Ty<'tcx>, Option<VariantIdx>), TypeLowering<'ll>>>,
|
||||||
|
|
||||||
|
/// Mapping of scalar types to llvm types.
|
||||||
pub scalar_lltypes: RefCell<FxHashMap<Ty<'tcx>, &'ll Type>>,
|
pub scalar_lltypes: RefCell<FxHashMap<Ty<'tcx>, &'ll Type>>,
|
||||||
|
|
||||||
pub pointee_infos: RefCell<FxHashMap<(Ty<'tcx>, Size), Option<PointeeInfo>>>,
|
pub pointee_infos: RefCell<FxHashMap<(Ty<'tcx>, Size), Option<PointeeInfo>>>,
|
||||||
pub isize_ty: &'ll Type,
|
pub isize_ty: &'ll Type,
|
||||||
|
|
||||||
/// Cache for the mapping from source index to llvm index for struct fields,
|
|
||||||
/// only present if synthetic fields are inserted for padding.
|
|
||||||
pub field_projection_cache: RefCell<FxHashMap<TyAndLayout<'tcx>, Vec<u32>>>,
|
|
||||||
|
|
||||||
pub coverage_cx: Option<coverageinfo::CrateCoverageContext<'ll, 'tcx>>,
|
pub coverage_cx: Option<coverageinfo::CrateCoverageContext<'ll, 'tcx>>,
|
||||||
pub dbg_cx: Option<debuginfo::CrateDebugContext<'ll, 'tcx>>,
|
pub dbg_cx: Option<debuginfo::CrateDebugContext<'ll, 'tcx>>,
|
||||||
|
|
||||||
@ -96,6 +96,15 @@ pub struct CodegenCx<'ll, 'tcx> {
|
|||||||
local_gen_sym_counter: Cell<usize>,
|
local_gen_sym_counter: Cell<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct TypeLowering<'ll> {
|
||||||
|
/// Associated LLVM type
|
||||||
|
pub lltype: &'ll Type,
|
||||||
|
|
||||||
|
/// If padding is used the slice maps fields from source order
|
||||||
|
/// to llvm order.
|
||||||
|
pub field_remapping: Option<Box<[u32]>>,
|
||||||
|
}
|
||||||
|
|
||||||
fn to_llvm_tls_model(tls_model: TlsModel) -> llvm::ThreadLocalMode {
|
fn to_llvm_tls_model(tls_model: TlsModel) -> llvm::ThreadLocalMode {
|
||||||
match tls_model {
|
match tls_model {
|
||||||
TlsModel::GeneralDynamic => llvm::ThreadLocalMode::GeneralDynamic,
|
TlsModel::GeneralDynamic => llvm::ThreadLocalMode::GeneralDynamic,
|
||||||
@ -308,11 +317,10 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
|||||||
const_globals: Default::default(),
|
const_globals: Default::default(),
|
||||||
statics_to_rauw: RefCell::new(Vec::new()),
|
statics_to_rauw: RefCell::new(Vec::new()),
|
||||||
used_statics: RefCell::new(Vec::new()),
|
used_statics: RefCell::new(Vec::new()),
|
||||||
lltypes: Default::default(),
|
type_lowering: Default::default(),
|
||||||
scalar_lltypes: Default::default(),
|
scalar_lltypes: Default::default(),
|
||||||
pointee_infos: Default::default(),
|
pointee_infos: Default::default(),
|
||||||
isize_ty,
|
isize_ty,
|
||||||
field_projection_cache: Default::default(),
|
|
||||||
coverage_cx,
|
coverage_cx,
|
||||||
dbg_cx,
|
dbg_cx,
|
||||||
eh_personality: Cell::new(None),
|
eh_personality: Cell::new(None),
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use crate::abi::FnAbi;
|
use crate::abi::FnAbi;
|
||||||
use crate::common::*;
|
use crate::common::*;
|
||||||
|
use crate::context::TypeLowering;
|
||||||
use crate::type_::Type;
|
use crate::type_::Type;
|
||||||
use rustc_codegen_ssa::traits::*;
|
use rustc_codegen_ssa::traits::*;
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
@ -17,6 +18,7 @@ fn uncached_llvm_type<'a, 'tcx>(
|
|||||||
cx: &CodegenCx<'a, 'tcx>,
|
cx: &CodegenCx<'a, 'tcx>,
|
||||||
layout: TyAndLayout<'tcx>,
|
layout: TyAndLayout<'tcx>,
|
||||||
defer: &mut Option<(&'a Type, TyAndLayout<'tcx>)>,
|
defer: &mut Option<(&'a Type, TyAndLayout<'tcx>)>,
|
||||||
|
field_remapping: &mut Option<Box<[u32]>>,
|
||||||
) -> &'a Type {
|
) -> &'a Type {
|
||||||
match layout.abi {
|
match layout.abi {
|
||||||
Abi::Scalar(_) => bug!("handled elsewhere"),
|
Abi::Scalar(_) => bug!("handled elsewhere"),
|
||||||
@ -75,7 +77,8 @@ fn uncached_llvm_type<'a, 'tcx>(
|
|||||||
FieldsShape::Array { count, .. } => cx.type_array(layout.field(cx, 0).llvm_type(cx), count),
|
FieldsShape::Array { count, .. } => cx.type_array(layout.field(cx, 0).llvm_type(cx), count),
|
||||||
FieldsShape::Arbitrary { .. } => match name {
|
FieldsShape::Arbitrary { .. } => match name {
|
||||||
None => {
|
None => {
|
||||||
let (llfields, packed) = struct_llfields(cx, layout);
|
let (llfields, packed, new_field_remapping) = struct_llfields(cx, layout);
|
||||||
|
*field_remapping = new_field_remapping;
|
||||||
cx.type_struct(&llfields, packed)
|
cx.type_struct(&llfields, packed)
|
||||||
}
|
}
|
||||||
Some(ref name) => {
|
Some(ref name) => {
|
||||||
@ -90,7 +93,7 @@ fn uncached_llvm_type<'a, 'tcx>(
|
|||||||
fn struct_llfields<'a, 'tcx>(
|
fn struct_llfields<'a, 'tcx>(
|
||||||
cx: &CodegenCx<'a, 'tcx>,
|
cx: &CodegenCx<'a, 'tcx>,
|
||||||
layout: TyAndLayout<'tcx>,
|
layout: TyAndLayout<'tcx>,
|
||||||
) -> (Vec<&'a Type>, bool) {
|
) -> (Vec<&'a Type>, bool, Option<Box<[u32]>>) {
|
||||||
debug!("struct_llfields: {:#?}", layout);
|
debug!("struct_llfields: {:#?}", layout);
|
||||||
let field_count = layout.fields.count();
|
let field_count = layout.fields.count();
|
||||||
|
|
||||||
@ -147,11 +150,8 @@ fn struct_llfields<'a, 'tcx>(
|
|||||||
} else {
|
} else {
|
||||||
debug!("struct_llfields: offset: {:?} stride: {:?}", offset, layout.size);
|
debug!("struct_llfields: offset: {:?} stride: {:?}", offset, layout.size);
|
||||||
}
|
}
|
||||||
if padding_used {
|
|
||||||
cx.field_projection_cache.borrow_mut().insert(layout, projection);
|
|
||||||
}
|
|
||||||
|
|
||||||
(result, packed)
|
(result, packed, padding_used.then_some(projection.into_boxed_slice()))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> CodegenCx<'a, 'tcx> {
|
impl<'a, 'tcx> CodegenCx<'a, 'tcx> {
|
||||||
@ -243,8 +243,8 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
|
|||||||
Variants::Single { index } => Some(index),
|
Variants::Single { index } => Some(index),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
if let Some(&llty) = cx.lltypes.borrow().get(&(self.ty, variant_index)) {
|
if let Some(ref llty) = cx.type_lowering.borrow().get(&(self.ty, variant_index)) {
|
||||||
return llty;
|
return llty.lltype;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("llvm_type({:#?})", self);
|
debug!("llvm_type({:#?})", self);
|
||||||
@ -256,6 +256,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
|
|||||||
let normal_ty = cx.tcx.erase_regions(self.ty);
|
let normal_ty = cx.tcx.erase_regions(self.ty);
|
||||||
|
|
||||||
let mut defer = None;
|
let mut defer = None;
|
||||||
|
let mut field_remapping = None;
|
||||||
let llty = if self.ty != normal_ty {
|
let llty = if self.ty != normal_ty {
|
||||||
let mut layout = cx.layout_of(normal_ty);
|
let mut layout = cx.layout_of(normal_ty);
|
||||||
if let Some(v) = variant_index {
|
if let Some(v) = variant_index {
|
||||||
@ -263,17 +264,21 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
|
|||||||
}
|
}
|
||||||
layout.llvm_type(cx)
|
layout.llvm_type(cx)
|
||||||
} else {
|
} else {
|
||||||
uncached_llvm_type(cx, *self, &mut defer)
|
uncached_llvm_type(cx, *self, &mut defer, &mut field_remapping)
|
||||||
};
|
};
|
||||||
debug!("--> mapped {:#?} to llty={:?}", self, llty);
|
debug!("--> mapped {:#?} to llty={:?}", self, llty);
|
||||||
|
|
||||||
cx.lltypes.borrow_mut().insert((self.ty, variant_index), llty);
|
cx.type_lowering
|
||||||
|
.borrow_mut()
|
||||||
|
.insert((self.ty, variant_index), TypeLowering { lltype: llty, field_remapping: None });
|
||||||
|
|
||||||
if let Some((llty, layout)) = defer {
|
if let Some((llty, layout)) = defer {
|
||||||
let (llfields, packed) = struct_llfields(cx, layout);
|
let (llfields, packed, new_field_remapping) = struct_llfields(cx, layout);
|
||||||
cx.set_struct_body(llty, &llfields, packed)
|
cx.set_struct_body(llty, &llfields, packed);
|
||||||
|
field_remapping = new_field_remapping;
|
||||||
}
|
}
|
||||||
|
cx.type_lowering.borrow_mut().get_mut(&(self.ty, variant_index)).unwrap().field_remapping =
|
||||||
|
field_remapping;
|
||||||
llty
|
llty
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -363,12 +368,23 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
|
|||||||
|
|
||||||
FieldsShape::Array { .. } => index as u64,
|
FieldsShape::Array { .. } => index as u64,
|
||||||
|
|
||||||
// Look up llvm field index in projection cache if present. If no projection cache
|
FieldsShape::Arbitrary { .. } => {
|
||||||
// is present no padding is used and the llvm field index matches the memory index.
|
let variant_index = match self.variants {
|
||||||
FieldsShape::Arbitrary { .. } => match cx.field_projection_cache.borrow().get(self) {
|
Variants::Single { index } => Some(index),
|
||||||
Some(projection) => projection[index] as u64,
|
_ => None,
|
||||||
None => self.fields.memory_index(index) as u64,
|
};
|
||||||
},
|
|
||||||
|
// Look up llvm field if indexes do not match memory order due to padding. If
|
||||||
|
// `field_remapping` is `None` no padding was used and the llvm field index
|
||||||
|
// matches the memory index.
|
||||||
|
match cx.type_lowering.borrow().get(&(self.ty, variant_index)) {
|
||||||
|
Some(TypeLowering { field_remapping: Some(ref prj), .. }) => prj[index] as u64,
|
||||||
|
Some(_) => self.fields.memory_index(index) as u64,
|
||||||
|
None => {
|
||||||
|
bug!("TyAndLayout::llvm_field_index({:?}): type info not found", self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user