mirror of https://github.com/rust-lang/rust.git
codegen: panic when trying to compute size/align of extern type
This commit is contained in:
parent
8b1ba11cb1
commit
b1613ebc43
|
@ -51,10 +51,10 @@ pub mod codegen_attrs;
|
||||||
pub mod common;
|
pub mod common;
|
||||||
pub mod debuginfo;
|
pub mod debuginfo;
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
pub mod glue;
|
|
||||||
pub mod meth;
|
pub mod meth;
|
||||||
pub mod mir;
|
pub mod mir;
|
||||||
pub mod mono_item;
|
pub mod mono_item;
|
||||||
|
pub mod size_of_val;
|
||||||
pub mod target_features;
|
pub mod target_features;
|
||||||
pub mod traits;
|
pub mod traits;
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,8 @@ use super::FunctionCx;
|
||||||
use crate::common::IntPredicate;
|
use crate::common::IntPredicate;
|
||||||
use crate::errors;
|
use crate::errors;
|
||||||
use crate::errors::InvalidMonomorphization;
|
use crate::errors::InvalidMonomorphization;
|
||||||
use crate::glue;
|
|
||||||
use crate::meth;
|
use crate::meth;
|
||||||
|
use crate::size_of_val;
|
||||||
use crate::traits::*;
|
use crate::traits::*;
|
||||||
use crate::MemFlags;
|
use crate::MemFlags;
|
||||||
|
|
||||||
|
@ -88,21 +88,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
sym::va_end => bx.va_end(args[0].immediate()),
|
sym::va_end => bx.va_end(args[0].immediate()),
|
||||||
sym::size_of_val => {
|
sym::size_of_val => {
|
||||||
let tp_ty = fn_args.type_at(0);
|
let tp_ty = fn_args.type_at(0);
|
||||||
if let OperandValue::Pair(_, meta) = args[0].val {
|
let meta =
|
||||||
let (llsize, _) = glue::size_and_align_of_dst(bx, tp_ty, Some(meta));
|
if let OperandValue::Pair(_, meta) = args[0].val { Some(meta) } else { None };
|
||||||
|
let (llsize, _) = size_of_val::size_and_align_of_dst(bx, tp_ty, meta);
|
||||||
llsize
|
llsize
|
||||||
} else {
|
|
||||||
bx.const_usize(bx.layout_of(tp_ty).size.bytes())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
sym::min_align_of_val => {
|
sym::min_align_of_val => {
|
||||||
let tp_ty = fn_args.type_at(0);
|
let tp_ty = fn_args.type_at(0);
|
||||||
if let OperandValue::Pair(_, meta) = args[0].val {
|
let meta =
|
||||||
let (_, llalign) = glue::size_and_align_of_dst(bx, tp_ty, Some(meta));
|
if let OperandValue::Pair(_, meta) = args[0].val { Some(meta) } else { None };
|
||||||
|
let (_, llalign) = size_of_val::size_and_align_of_dst(bx, tp_ty, meta);
|
||||||
llalign
|
llalign
|
||||||
} else {
|
|
||||||
bx.const_usize(bx.layout_of(tp_ty).align.abi.bytes())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
sym::vtable_size | sym::vtable_align => {
|
sym::vtable_size | sym::vtable_align => {
|
||||||
let vtable = args[0].immediate();
|
let vtable = args[0].immediate();
|
||||||
|
|
|
@ -2,7 +2,7 @@ use super::place::PlaceRef;
|
||||||
use super::{FunctionCx, LocalRef};
|
use super::{FunctionCx, LocalRef};
|
||||||
|
|
||||||
use crate::base;
|
use crate::base;
|
||||||
use crate::glue;
|
use crate::size_of_val;
|
||||||
use crate::traits::*;
|
use crate::traits::*;
|
||||||
use crate::MemFlags;
|
use crate::MemFlags;
|
||||||
|
|
||||||
|
@ -466,13 +466,13 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
|
||||||
.ty;
|
.ty;
|
||||||
|
|
||||||
let OperandValue::Ref(llptr, Some(llextra), _) = self else {
|
let OperandValue::Ref(llptr, Some(llextra), _) = self else {
|
||||||
bug!("store_unsized called with a sized value")
|
bug!("store_unsized called with a sized value (or with an extern type)")
|
||||||
};
|
};
|
||||||
|
|
||||||
// Allocate an appropriate region on the stack, and copy the value into it. Since alloca
|
// Allocate an appropriate region on the stack, and copy the value into it. Since alloca
|
||||||
// doesn't support dynamic alignment, we allocate an extra align - 1 bytes, and align the
|
// doesn't support dynamic alignment, we allocate an extra align - 1 bytes, and align the
|
||||||
// pointer manually.
|
// pointer manually.
|
||||||
let (size, align) = glue::size_and_align_of_dst(bx, unsized_ty, Some(llextra));
|
let (size, align) = size_of_val::size_and_align_of_dst(bx, unsized_ty, Some(llextra));
|
||||||
let one = bx.const_usize(1);
|
let one = bx.const_usize(1);
|
||||||
let align_minus_1 = bx.sub(align, one);
|
let align_minus_1 = bx.sub(align, one);
|
||||||
let size_extra = bx.add(size, align_minus_1);
|
let size_extra = bx.add(size, align_minus_1);
|
||||||
|
|
|
@ -2,7 +2,7 @@ use super::operand::OperandValue;
|
||||||
use super::{FunctionCx, LocalRef};
|
use super::{FunctionCx, LocalRef};
|
||||||
|
|
||||||
use crate::common::IntPredicate;
|
use crate::common::IntPredicate;
|
||||||
use crate::glue;
|
use crate::size_of_val;
|
||||||
use crate::traits::*;
|
use crate::traits::*;
|
||||||
|
|
||||||
use rustc_middle::mir;
|
use rustc_middle::mir;
|
||||||
|
@ -179,7 +179,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
|
||||||
let unaligned_offset = bx.cx().const_usize(offset.bytes());
|
let unaligned_offset = bx.cx().const_usize(offset.bytes());
|
||||||
|
|
||||||
// Get the alignment of the field
|
// Get the alignment of the field
|
||||||
let (_, mut unsized_align) = glue::size_and_align_of_dst(bx, field.ty, meta);
|
let (_, mut unsized_align) = size_of_val::size_and_align_of_dst(bx, field.ty, meta);
|
||||||
|
|
||||||
// For packed types, we need to cap alignment.
|
// For packed types, we need to cap alignment.
|
||||||
if let ty::Adt(def, _) = self.layout.ty.kind()
|
if let ty::Adt(def, _) = self.layout.ty.kind()
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
//!
|
//! Computing the size and alignment of a value.
|
||||||
//
|
|
||||||
// Code relating to drop glue.
|
|
||||||
|
|
||||||
|
use crate::common;
|
||||||
use crate::common::IntPredicate;
|
use crate::common::IntPredicate;
|
||||||
use crate::meth;
|
use crate::meth;
|
||||||
use crate::traits::*;
|
use crate::traits::*;
|
||||||
|
use rustc_hir::LangItem;
|
||||||
|
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
|
||||||
use rustc_middle::ty::{self, Ty};
|
use rustc_middle::ty::{self, Ty};
|
||||||
use rustc_target::abi::WrappingRange;
|
use rustc_target::abi::WrappingRange;
|
||||||
|
|
||||||
|
@ -14,7 +15,7 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||||
info: Option<Bx::Value>,
|
info: Option<Bx::Value>,
|
||||||
) -> (Bx::Value, Bx::Value) {
|
) -> (Bx::Value, Bx::Value) {
|
||||||
let layout = bx.layout_of(t);
|
let layout = bx.layout_of(t);
|
||||||
debug!("size_and_align_of_dst(ty={}, info={:?}): layout: {:?}", t, info, layout);
|
trace!("size_and_align_of_dst(ty={}, info={:?}): layout: {:?}", t, info, layout);
|
||||||
if layout.is_sized() {
|
if layout.is_sized() {
|
||||||
let size = bx.const_usize(layout.size.bytes());
|
let size = bx.const_usize(layout.size.bytes());
|
||||||
let align = bx.const_usize(layout.align.abi.bytes());
|
let align = bx.const_usize(layout.align.abi.bytes());
|
||||||
|
@ -51,7 +52,31 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||||
bx.const_usize(unit.align.abi.bytes()),
|
bx.const_usize(unit.align.abi.bytes()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_ => {
|
ty::Foreign(_) => {
|
||||||
|
// `extern` type. We cannot compute the size, so panic.
|
||||||
|
let msg_str = with_no_visible_paths!({
|
||||||
|
with_no_trimmed_paths!({
|
||||||
|
format!("attempted to compute the size or alignment of extern type `{t}`")
|
||||||
|
})
|
||||||
|
});
|
||||||
|
let msg = bx.const_str(&msg_str);
|
||||||
|
|
||||||
|
// Obtain the panic entry point.
|
||||||
|
let (fn_abi, llfn) = common::build_langcall(bx, None, LangItem::PanicNounwind);
|
||||||
|
|
||||||
|
// Generate the call.
|
||||||
|
// Cannot use `do_call` since we don't have a MIR terminator so we can't create a `TerminationCodegenHelper`.
|
||||||
|
// (But we are in good company, this code is duplicated plenty of times.)
|
||||||
|
let fn_ty = bx.fn_decl_backend_type(fn_abi);
|
||||||
|
|
||||||
|
bx.call(fn_ty, /* fn_attrs */ None, Some(fn_abi), llfn, &[msg.0, msg.1], None);
|
||||||
|
|
||||||
|
// This function does not return so we can now return whatever we want.
|
||||||
|
let size = bx.const_usize(layout.size.bytes());
|
||||||
|
let align = bx.const_usize(layout.align.abi.bytes());
|
||||||
|
(size, align)
|
||||||
|
}
|
||||||
|
ty::Adt(..) | ty::Tuple(..) => {
|
||||||
// First get the size of all statically known fields.
|
// First get the size of all statically known fields.
|
||||||
// Don't use size_of because it also rounds up to alignment, which we
|
// Don't use size_of because it also rounds up to alignment, which we
|
||||||
// want to avoid, as the unsized field's alignment could be smaller.
|
// want to avoid, as the unsized field's alignment could be smaller.
|
||||||
|
@ -122,5 +147,6 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||||
|
|
||||||
(size, align)
|
(size, align)
|
||||||
}
|
}
|
||||||
|
_ => bug!("size_and_align_of_dst: {t} not supported"),
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,6 @@
|
||||||
// run-pass
|
// run-fail
|
||||||
|
// check-run-results
|
||||||
|
// normalize-stderr-test "panicking\.rs:\d+:\d+:" -> "panicking.rs:"
|
||||||
#![feature(extern_types)]
|
#![feature(extern_types)]
|
||||||
|
|
||||||
use std::mem::{align_of_val, size_of_val};
|
use std::mem::{align_of_val, size_of_val};
|
||||||
|
@ -10,6 +12,7 @@ extern "C" {
|
||||||
fn main() {
|
fn main() {
|
||||||
let x: &A = unsafe { &*(1usize as *const A) };
|
let x: &A = unsafe { &*(1usize as *const A) };
|
||||||
|
|
||||||
|
// These don't have a dynamic size, so this should panic.
|
||||||
assert_eq!(size_of_val(x), 0);
|
assert_eq!(size_of_val(x), 0);
|
||||||
assert_eq!(align_of_val(x), 1);
|
assert_eq!(align_of_val(x), 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
thread 'main' panicked at library/core/src/panicking.rs:
|
||||||
|
attempted to compute the size or alignment of extern type `A`
|
||||||
|
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
|
||||||
|
thread caused non-unwinding panic. aborting.
|
Loading…
Reference in New Issue