fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
layout: TyLayout<'tcx>,
- defer: &mut Option<(Type, TyLayout<'tcx>)>)
- -> Type {
+ defer: &mut Option<(&'a Type, TyLayout<'tcx>)>)
+ -> &'a Type {
match layout.abi {
layout::Abi::Scalar(_) => bug!("handled elsewhere"),
layout::Abi::Vector { ref element, count } => {
return Type::x86_mmx(cx)
} else {
let element = layout.scalar_llvm_type_at(cx, element, Size::ZERO);
- return Type::vector(&element, count);
+ return Type::vector(element, count);
}
}
layout::Abi::ScalarPair(..) => {
return Type::struct_(cx, &[
- layout.scalar_pair_element_llvm_type(cx, 0),
- layout.scalar_pair_element_llvm_type(cx, 1),
+ layout.scalar_pair_element_llvm_type(cx, 0, false),
+ layout.scalar_pair_element_llvm_type(cx, 1, false),
], false);
}
layout::Abi::Uninhabited |
}
}
layout::FieldPlacement::Array { count, .. } => {
- Type::array(&layout.field(cx, 0).llvm_type(cx), count)
+ Type::array(layout.field(cx, 0).llvm_type(cx), count)
}
layout::FieldPlacement::Arbitrary { .. } => {
match name {
fn struct_llfields<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
layout: TyLayout<'tcx>)
- -> (Vec<Type>, bool) {
+ -> (Vec<&'a Type>, bool) {
debug!("struct_llfields: {:#?}", layout);
let field_count = layout.fields.count();
let mut packed = false;
let mut offset = Size::ZERO;
let mut prev_align = layout.align;
- let mut result: Vec<Type> = Vec::with_capacity(1 + field_count * 2);
+ let mut result: Vec<_> = Vec::with_capacity(1 + field_count * 2);
for i in layout.fields.index_by_increasing_offset() {
let field = layout.field(cx, i);
packed |= layout.align.abi() < field.align.abi();
pub trait LayoutLlvmExt<'tcx> {
fn is_llvm_immediate(&self) -> bool;
fn is_llvm_scalar_pair<'a>(&self) -> bool;
- fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type;
- fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type;
+ fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type;
+ fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type;
fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
- scalar: &layout::Scalar, offset: Size) -> Type;
+ scalar: &layout::Scalar, offset: Size) -> &'a Type;
fn scalar_pair_element_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
- index: usize) -> Type;
+ index: usize, immediate: bool) -> &'a Type;
fn llvm_field_index(&self, index: usize) -> u64;
fn pointee_info_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, offset: Size)
-> Option<PointeeInfo>;
/// with the inner-most trailing unsized field using the "minimal unit"
/// of that field's type - this is useful for taking the address of
/// that field and ensuring the struct has the right alignment.
- fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
+ fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
if let layout::Abi::Scalar(ref scalar) = self.abi {
// Use a different cache for scalars because pointers to DSTs
// can be either fat or thin (data pointers of fat pointers).
cx.lltypes.borrow_mut().insert((self.ty, variant_index), llty);
- if let Some((mut llty, layout)) = defer {
+ if let Some((llty, layout)) = defer {
let (llfields, packed) = struct_llfields(cx, layout);
llty.set_struct_body(&llfields, packed)
}
llty
}
- fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
+ fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
if let layout::Abi::Scalar(ref scalar) = self.abi {
if scalar.is_bool() {
return Type::i1(cx);
}
fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
- scalar: &layout::Scalar, offset: Size) -> Type {
+ scalar: &layout::Scalar, offset: Size) -> &'a Type {
match scalar.value {
layout::Int(i, _) => Type::from_integer(cx, i),
layout::Float(FloatTy::F32) => Type::f32(cx),
}
fn scalar_pair_element_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
- index: usize) -> Type {
+ index: usize, immediate: bool) -> &'a Type {
// HACK(eddyb) special-case fat pointers until LLVM removes
// pointee types, to avoid bitcasting every `OperandRef::deref`.
match self.ty.sty {
}
ty::TyAdt(def, _) if def.is_box() => {
let ptr_ty = cx.tcx.mk_mut_ptr(self.ty.boxed_ty());
- return cx.layout_of(ptr_ty).scalar_pair_element_llvm_type(cx, index);
+ return cx.layout_of(ptr_ty).scalar_pair_element_llvm_type(cx, index, immediate);
}
_ => {}
}
};
let scalar = [a, b][index];
- // Make sure to return the same type `immediate_llvm_type` would,
- // to avoid dealing with two types and the associated conversions.
- // This means that `(bool, bool)` is represented as `{i1, i1}`,
- // both in memory and as an immediate, while `bool` is typically
- // `i8` in memory and only `i1` when immediate. While we need to
- // load/store `bool` as `i8` to avoid crippling LLVM optimizations,
- // `i1` in a LLVM aggregate is valid and mostly equivalent to `i8`.
- if scalar.is_bool() {
+ // Make sure to return the same type `immediate_llvm_type` would when
+ // dealing with an immediate pair. This means that `(bool, bool)` is
+ // effectively represented as `{i8, i8}` in memory and two `i1`s as an
+ // immediate, just like `bool` is typically `i8` in memory and only `i1`
+ // when immediate. We need to load/store `bool` as `i8` to avoid
+ // crippling LLVM optimizations or triggering other LLVM bugs with `i1`.
+ if immediate && scalar.is_bool() {
return Type::i1(cx);
}