about summary refs log tree commit diff
path: root/compiler/rustc_codegen_ssa
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2023-12-02 12:25:01 +0100
committerRalf Jung <post@ralfj.de>2023-12-12 08:15:17 +0100
commitb1613ebc432ae495ecfcfa822548390c250849a8 (patch)
tree827aba1a66de751ceef46c6dc45a06d9a60a6548 /compiler/rustc_codegen_ssa
parent8b1ba11cb1176cd7b8a0f4b55d1c97ee9fd3662d (diff)
downloadrust-b1613ebc432ae495ecfcfa822548390c250849a8.tar.gz
rust-b1613ebc432ae495ecfcfa822548390c250849a8.zip
codegen: panic when trying to compute size/align of extern type
Diffstat (limited to 'compiler/rustc_codegen_ssa')
-rw-r--r--compiler/rustc_codegen_ssa/src/lib.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/intrinsic.rs22
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/operand.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/place.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/size_of_val.rs (renamed from compiler/rustc_codegen_ssa/src/glue.rs)36
5 files changed, 46 insertions, 24 deletions
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index cd5eb77e06e..9b60f0844a0 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -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;
 
diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
index 136d06d561a..a5bffc33d39 100644
--- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
@@ -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();
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index feee3ac03d0..e8c58f6b6f8 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -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);
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index 83425dee1a8..a3fb3b9d783 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -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()
diff --git a/compiler/rustc_codegen_ssa/src/glue.rs b/compiler/rustc_codegen_ssa/src/size_of_val.rs
index c34f1dbf856..b8a4949d59f 100644
--- a/compiler/rustc_codegen_ssa/src/glue.rs
+++ b/compiler/rustc_codegen_ssa/src/size_of_val.rs
@@ -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"),
     }
 }