Rollup merge of #115240 - RalfJung:llvm-no-type, r=bjorn3
codegen_llvm/llvm_type: avoid matching on the Rust type This `match` is highly suspicious. Looking at `scalar_llvm_type_at` I think it makes no difference. But if it were to make a difference that would be a huge problem, since it doesn't look through `repr(transparent)`! Cc `@eddyb` `@bjorn3`
This commit is contained in:
commit
a5b7504f41
4 changed files with 25 additions and 67 deletions
|
@ -125,8 +125,8 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
||||||
PassMode::Ignore => continue,
|
PassMode::Ignore => continue,
|
||||||
PassMode::Direct(_) => arg.layout.immediate_gcc_type(cx),
|
PassMode::Direct(_) => arg.layout.immediate_gcc_type(cx),
|
||||||
PassMode::Pair(..) => {
|
PassMode::Pair(..) => {
|
||||||
argument_tys.push(arg.layout.scalar_pair_element_gcc_type(cx, 0, true));
|
argument_tys.push(arg.layout.scalar_pair_element_gcc_type(cx, 0));
|
||||||
argument_tys.push(arg.layout.scalar_pair_element_gcc_type(cx, 1, true));
|
argument_tys.push(arg.layout.scalar_pair_element_gcc_type(cx, 1));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
PassMode::Indirect { extra_attrs: Some(_), .. } => {
|
PassMode::Indirect { extra_attrs: Some(_), .. } => {
|
||||||
|
|
|
@ -821,7 +821,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||||
|
|
||||||
let mut load = |i, scalar: &abi::Scalar, align| {
|
let mut load = |i, scalar: &abi::Scalar, align| {
|
||||||
let llptr = self.struct_gep(pair_type, place.llval, i as u64);
|
let llptr = self.struct_gep(pair_type, place.llval, i as u64);
|
||||||
let llty = place.layout.scalar_pair_element_gcc_type(self, i, false);
|
let llty = place.layout.scalar_pair_element_gcc_type(self, i);
|
||||||
let load = self.load(llty, llptr, align);
|
let load = self.load(llty, llptr, align);
|
||||||
scalar_load_metadata(self, load, scalar);
|
scalar_load_metadata(self, load, scalar);
|
||||||
if scalar.is_bool() { self.trunc(load, self.type_i1()) } else { load }
|
if scalar.is_bool() { self.trunc(load, self.type_i1()) } else { load }
|
||||||
|
|
|
@ -4,7 +4,7 @@ use gccjit::{Struct, Type};
|
||||||
use crate::rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods, LayoutTypeMethods};
|
use crate::rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods, LayoutTypeMethods};
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
|
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
|
||||||
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
|
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
|
||||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||||
use rustc_target::abi::{self, Abi, Align, F32, F64, FieldsShape, Int, Integer, Pointer, PointeeInfo, Size, TyAbiInterface, Variants};
|
use rustc_target::abi::{self, Abi, Align, F32, F64, FieldsShape, Int, Integer, Pointer, PointeeInfo, Size, TyAbiInterface, Variants};
|
||||||
use rustc_target::abi::call::{CastTarget, FnAbi, Reg};
|
use rustc_target::abi::call::{CastTarget, FnAbi, Reg};
|
||||||
|
@ -74,8 +74,8 @@ fn uncached_gcc_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLayout
|
||||||
Abi::ScalarPair(..) => {
|
Abi::ScalarPair(..) => {
|
||||||
return cx.type_struct(
|
return cx.type_struct(
|
||||||
&[
|
&[
|
||||||
layout.scalar_pair_element_gcc_type(cx, 0, false),
|
layout.scalar_pair_element_gcc_type(cx, 0),
|
||||||
layout.scalar_pair_element_gcc_type(cx, 1, false),
|
layout.scalar_pair_element_gcc_type(cx, 1),
|
||||||
],
|
],
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
@ -150,7 +150,7 @@ pub trait LayoutGccExt<'tcx> {
|
||||||
fn gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>;
|
fn gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>;
|
||||||
fn immediate_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>;
|
fn immediate_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>;
|
||||||
fn scalar_gcc_type_at<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, scalar: &abi::Scalar, offset: Size) -> Type<'gcc>;
|
fn scalar_gcc_type_at<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, scalar: &abi::Scalar, offset: Size) -> Type<'gcc>;
|
||||||
fn scalar_pair_element_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, index: usize, immediate: bool) -> Type<'gcc>;
|
fn scalar_pair_element_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, index: usize) -> Type<'gcc>;
|
||||||
fn gcc_field_index(&self, index: usize) -> u64;
|
fn gcc_field_index(&self, index: usize) -> u64;
|
||||||
fn pointee_info_at<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, offset: Size) -> Option<PointeeInfo>;
|
fn pointee_info_at<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, offset: Size) -> Option<PointeeInfo>;
|
||||||
}
|
}
|
||||||
|
@ -182,23 +182,16 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
|
||||||
/// of that field's type - this is useful for taking the address of
|
/// of that field's type - this is useful for taking the address of
|
||||||
/// that field and ensuring the struct has the right alignment.
|
/// that field and ensuring the struct has the right alignment.
|
||||||
fn gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> {
|
fn gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> {
|
||||||
|
// This must produce the same result for `repr(transparent)` wrappers as for the inner type!
|
||||||
|
// In other words, this should generally not look at the type at all, but only at the
|
||||||
|
// layout.
|
||||||
if let Abi::Scalar(ref scalar) = self.abi {
|
if let Abi::Scalar(ref scalar) = self.abi {
|
||||||
// Use a different cache for scalars because pointers to DSTs
|
// Use a different cache for scalars because pointers to DSTs
|
||||||
// can be either fat or thin (data pointers of fat pointers).
|
// can be either fat or thin (data pointers of fat pointers).
|
||||||
if let Some(&ty) = cx.scalar_types.borrow().get(&self.ty) {
|
if let Some(&ty) = cx.scalar_types.borrow().get(&self.ty) {
|
||||||
return ty;
|
return ty;
|
||||||
}
|
}
|
||||||
let ty =
|
let ty = self.scalar_gcc_type_at(cx, scalar, Size::ZERO);
|
||||||
match *self.ty.kind() {
|
|
||||||
ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => {
|
|
||||||
cx.type_ptr_to(cx.layout_of(ty).gcc_type(cx))
|
|
||||||
}
|
|
||||||
ty::Adt(def, _) if def.is_box() => {
|
|
||||||
cx.type_ptr_to(cx.layout_of(self.ty.boxed_ty()).gcc_type(cx))
|
|
||||||
}
|
|
||||||
ty::FnPtr(sig) => cx.fn_ptr_backend_type(&cx.fn_abi_of_fn_ptr(sig, ty::List::empty())),
|
|
||||||
_ => self.scalar_gcc_type_at(cx, scalar, Size::ZERO),
|
|
||||||
};
|
|
||||||
cx.scalar_types.borrow_mut().insert(self.ty, ty);
|
cx.scalar_types.borrow_mut().insert(self.ty, ty);
|
||||||
return ty;
|
return ty;
|
||||||
}
|
}
|
||||||
|
@ -272,23 +265,10 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scalar_pair_element_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, index: usize, immediate: bool) -> Type<'gcc> {
|
fn scalar_pair_element_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, index: usize) -> Type<'gcc> {
|
||||||
// TODO(antoyo): remove llvm hack:
|
// This must produce the same result for `repr(transparent)` wrappers as for the inner type!
|
||||||
// HACK(eddyb) special-case fat pointers until LLVM removes
|
// In other words, this should generally not look at the type at all, but only at the
|
||||||
// pointee types, to avoid bitcasting every `OperandRef::deref`.
|
// layout.
|
||||||
match self.ty.kind() {
|
|
||||||
ty::Ref(..) | ty::RawPtr(_) => {
|
|
||||||
return self.field(cx, index).gcc_type(cx);
|
|
||||||
}
|
|
||||||
// only wide pointer boxes are handled as pointers
|
|
||||||
// thin pointer boxes with scalar allocators are handled by the general logic below
|
|
||||||
ty::Adt(def, args) if def.is_box() && cx.layout_of(args.type_at(1)).is_zst() => {
|
|
||||||
let ptr_ty = Ty::new_mut_ptr(cx.tcx,self.ty.boxed_ty());
|
|
||||||
return cx.layout_of(ptr_ty).scalar_pair_element_gcc_type(cx, index, immediate);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
let (a, b) = match self.abi {
|
let (a, b) = match self.abi {
|
||||||
Abi::ScalarPair(ref a, ref b) => (a, b),
|
Abi::ScalarPair(ref a, ref b) => (a, b),
|
||||||
_ => bug!("TyAndLayout::scalar_pair_element_llty({:?}): not applicable", self),
|
_ => bug!("TyAndLayout::scalar_pair_element_llty({:?}): not applicable", self),
|
||||||
|
@ -367,8 +347,8 @@ impl<'gcc, 'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||||
layout.gcc_field_index(index)
|
layout.gcc_field_index(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scalar_pair_element_backend_type(&self, layout: TyAndLayout<'tcx>, index: usize, immediate: bool) -> Type<'gcc> {
|
fn scalar_pair_element_backend_type(&self, layout: TyAndLayout<'tcx>, index: usize, _immediate: bool) -> Type<'gcc> {
|
||||||
layout.scalar_pair_element_gcc_type(self, index, immediate)
|
layout.scalar_pair_element_gcc_type(self, index)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cast_backend_type(&self, ty: &CastTarget) -> Type<'gcc> {
|
fn cast_backend_type(&self, ty: &CastTarget) -> Type<'gcc> {
|
||||||
|
|
|
@ -3,7 +3,7 @@ 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;
|
||||||
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
|
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
|
||||||
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
|
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
|
||||||
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
|
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
|
||||||
use rustc_target::abi::HasDataLayout;
|
use rustc_target::abi::HasDataLayout;
|
||||||
|
@ -215,20 +215,16 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
|
||||||
/// of that field's type - this is useful for taking the address of
|
/// of that field's type - this is useful for taking the address of
|
||||||
/// that field and ensuring the struct has the right alignment.
|
/// that field and ensuring the struct has the right alignment.
|
||||||
fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
|
fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
|
||||||
|
// This must produce the same result for `repr(transparent)` wrappers as for the inner type!
|
||||||
|
// In other words, this should generally not look at the type at all, but only at the
|
||||||
|
// layout.
|
||||||
if let Abi::Scalar(scalar) = self.abi {
|
if let Abi::Scalar(scalar) = self.abi {
|
||||||
// Use a different cache for scalars because pointers to DSTs
|
// Use a different cache for scalars because pointers to DSTs
|
||||||
// can be either fat or thin (data pointers of fat pointers).
|
// can be either fat or thin (data pointers of fat pointers).
|
||||||
if let Some(&llty) = cx.scalar_lltypes.borrow().get(&self.ty) {
|
if let Some(&llty) = cx.scalar_lltypes.borrow().get(&self.ty) {
|
||||||
return llty;
|
return llty;
|
||||||
}
|
}
|
||||||
let llty = match *self.ty.kind() {
|
let llty = self.scalar_llvm_type_at(cx, scalar);
|
||||||
ty::Ref(..) | ty::RawPtr(_) => cx.type_ptr(),
|
|
||||||
ty::Adt(def, _) if def.is_box() => cx.type_ptr(),
|
|
||||||
ty::FnPtr(sig) => {
|
|
||||||
cx.fn_ptr_backend_type(cx.fn_abi_of_fn_ptr(sig, ty::List::empty()))
|
|
||||||
}
|
|
||||||
_ => self.scalar_llvm_type_at(cx, scalar),
|
|
||||||
};
|
|
||||||
cx.scalar_lltypes.borrow_mut().insert(self.ty, llty);
|
cx.scalar_lltypes.borrow_mut().insert(self.ty, llty);
|
||||||
return llty;
|
return llty;
|
||||||
}
|
}
|
||||||
|
@ -303,27 +299,9 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
|
||||||
index: usize,
|
index: usize,
|
||||||
immediate: bool,
|
immediate: bool,
|
||||||
) -> &'a Type {
|
) -> &'a Type {
|
||||||
// HACK(eddyb) special-case fat pointers until LLVM removes
|
// This must produce the same result for `repr(transparent)` wrappers as for the inner type!
|
||||||
// pointee types, to avoid bitcasting every `OperandRef::deref`.
|
// In other words, this should generally not look at the type at all, but only at the
|
||||||
match *self.ty.kind() {
|
// layout.
|
||||||
ty::Ref(..) | ty::RawPtr(_) => {
|
|
||||||
return self.field(cx, index).llvm_type(cx);
|
|
||||||
}
|
|
||||||
// only wide pointer boxes are handled as pointers
|
|
||||||
// thin pointer boxes with scalar allocators are handled by the general logic below
|
|
||||||
ty::Adt(def, args) if def.is_box() && cx.layout_of(args.type_at(1)).is_zst() => {
|
|
||||||
let ptr_ty = Ty::new_mut_ptr(cx.tcx, self.ty.boxed_ty());
|
|
||||||
return cx.layout_of(ptr_ty).scalar_pair_element_llvm_type(cx, index, immediate);
|
|
||||||
}
|
|
||||||
// `dyn* Trait` has the same ABI as `*mut dyn Trait`
|
|
||||||
ty::Dynamic(bounds, region, ty::DynStar) => {
|
|
||||||
let ptr_ty =
|
|
||||||
Ty::new_mut_ptr(cx.tcx, Ty::new_dynamic(cx.tcx, bounds, region, ty::Dyn));
|
|
||||||
return cx.layout_of(ptr_ty).scalar_pair_element_llvm_type(cx, index, immediate);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
let Abi::ScalarPair(a, b) = self.abi else {
|
let Abi::ScalarPair(a, b) = self.abi else {
|
||||||
bug!("TyAndLayout::scalar_pair_element_llty({:?}): not applicable", self);
|
bug!("TyAndLayout::scalar_pair_element_llty({:?}): not applicable", self);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue