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 debuginfo;
|
||||
pub mod errors;
|
||||
pub mod glue;
|
||||
pub mod meth;
|
||||
pub mod mir;
|
||||
pub mod mono_item;
|
||||
pub mod size_of_val;
|
||||
pub mod target_features;
|
||||
pub mod traits;
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ use super::FunctionCx;
|
|||
use crate::common::IntPredicate;
|
||||
use crate::errors;
|
||||
use crate::errors::InvalidMonomorphization;
|
||||
use crate::glue;
|
||||
use crate::meth;
|
||||
use crate::size_of_val;
|
||||
use crate::traits::*;
|
||||
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::size_of_val => {
|
||||
let tp_ty = fn_args.type_at(0);
|
||||
if let OperandValue::Pair(_, meta) = args[0].val {
|
||||
let (llsize, _) = glue::size_and_align_of_dst(bx, tp_ty, Some(meta));
|
||||
llsize
|
||||
} else {
|
||||
bx.const_usize(bx.layout_of(tp_ty).size.bytes())
|
||||
}
|
||||
let 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
|
||||
}
|
||||
sym::min_align_of_val => {
|
||||
let tp_ty = fn_args.type_at(0);
|
||||
if let OperandValue::Pair(_, meta) = args[0].val {
|
||||
let (_, llalign) = glue::size_and_align_of_dst(bx, tp_ty, Some(meta));
|
||||
llalign
|
||||
} else {
|
||||
bx.const_usize(bx.layout_of(tp_ty).align.abi.bytes())
|
||||
}
|
||||
let 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
|
||||
}
|
||||
sym::vtable_size | sym::vtable_align => {
|
||||
let vtable = args[0].immediate();
|
||||
|
|
|
@ -2,7 +2,7 @@ use super::place::PlaceRef;
|
|||
use super::{FunctionCx, LocalRef};
|
||||
|
||||
use crate::base;
|
||||
use crate::glue;
|
||||
use crate::size_of_val;
|
||||
use crate::traits::*;
|
||||
use crate::MemFlags;
|
||||
|
||||
|
@ -466,13 +466,13 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
|
|||
.ty;
|
||||
|
||||
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
|
||||
// doesn't support dynamic alignment, we allocate an extra align - 1 bytes, and align the
|
||||
// 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 align_minus_1 = bx.sub(align, one);
|
||||
let size_extra = bx.add(size, align_minus_1);
|
||||
|
|
|
@ -2,7 +2,7 @@ use super::operand::OperandValue;
|
|||
use super::{FunctionCx, LocalRef};
|
||||
|
||||
use crate::common::IntPredicate;
|
||||
use crate::glue;
|
||||
use crate::size_of_val;
|
||||
use crate::traits::*;
|
||||
|
||||
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());
|
||||
|
||||
// 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.
|
||||
if let ty::Adt(def, _) = self.layout.ty.kind()
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
//!
|
||||
//
|
||||
// Code relating to drop glue.
|
||||
//! Computing the size and alignment of a value.
|
||||
|
||||
use crate::common;
|
||||
use crate::common::IntPredicate;
|
||||
use crate::meth;
|
||||
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_target::abi::WrappingRange;
|
||||
|
||||
|
@ -14,7 +15,7 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
info: Option<Bx::Value>,
|
||||
) -> (Bx::Value, Bx::Value) {
|
||||
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() {
|
||||
let size = bx.const_usize(layout.size.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()),
|
||||
)
|
||||
}
|
||||
_ => {
|
||||
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.
|
||||
// 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.
|
||||
|
@ -122,5 +147,6 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
|
||||
(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)]
|
||||
|
||||
use std::mem::{align_of_val, size_of_val};
|
||||
|
@ -10,6 +12,7 @@ extern "C" {
|
|||
fn main() {
|
||||
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!(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