Skip to content

Commit fdcf56c

Browse files
committed
Panic for size_of_val and align_of_val of extern type
cc rust-lang/rust#118534
1 parent b1c925b commit fdcf56c

File tree

4 files changed

+85
-58
lines changed

4 files changed

+85
-58
lines changed

src/base.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
353353
fx,
354354
rustc_hir::LangItem::PanicBoundsCheck,
355355
&[index, len, location],
356-
source_info.span,
356+
Some(source_info.span),
357357
);
358358
}
359359
AssertKind::MisalignedPointerDereference { ref required, ref found } => {
@@ -365,7 +365,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
365365
fx,
366366
rustc_hir::LangItem::PanicMisalignedPointerDereference,
367367
&[required, found, location],
368-
source_info.span,
368+
Some(source_info.span),
369369
);
370370
}
371371
_ => {
@@ -945,19 +945,19 @@ pub(crate) fn codegen_panic<'tcx>(
945945
let msg_len = fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(msg_str.len()).unwrap());
946946
let args = [msg_ptr, msg_len, location];
947947

948-
codegen_panic_inner(fx, rustc_hir::LangItem::Panic, &args, source_info.span);
948+
codegen_panic_inner(fx, rustc_hir::LangItem::Panic, &args, Some(source_info.span));
949949
}
950950

951951
pub(crate) fn codegen_panic_nounwind<'tcx>(
952952
fx: &mut FunctionCx<'_, '_, 'tcx>,
953953
msg_str: &str,
954-
source_info: mir::SourceInfo,
954+
span: Option<Span>,
955955
) {
956956
let msg_ptr = fx.anonymous_str(msg_str);
957957
let msg_len = fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(msg_str.len()).unwrap());
958958
let args = [msg_ptr, msg_len];
959959

960-
codegen_panic_inner(fx, rustc_hir::LangItem::PanicNounwind, &args, source_info.span);
960+
codegen_panic_inner(fx, rustc_hir::LangItem::PanicNounwind, &args, span);
961961
}
962962

963963
pub(crate) fn codegen_unwind_terminate<'tcx>(
@@ -967,16 +967,16 @@ pub(crate) fn codegen_unwind_terminate<'tcx>(
967967
) {
968968
let args = [];
969969

970-
codegen_panic_inner(fx, reason.lang_item(), &args, source_info.span);
970+
codegen_panic_inner(fx, reason.lang_item(), &args, Some(source_info.span));
971971
}
972972

973973
fn codegen_panic_inner<'tcx>(
974974
fx: &mut FunctionCx<'_, '_, 'tcx>,
975975
lang_item: rustc_hir::LangItem,
976976
args: &[Value],
977-
span: Span,
977+
span: Option<Span>,
978978
) {
979-
let def_id = fx.tcx.require_lang_item(lang_item, Some(span));
979+
let def_id = fx.tcx.require_lang_item(lang_item, span);
980980

981981
let instance = Instance::mono(fx.tcx, def_id).polymorphize(fx.tcx);
982982
let symbol_name = fx.tcx.symbol_name(instance).name;

src/intrinsics/mod.rs

+9-11
Original file line numberDiff line numberDiff line change
@@ -487,13 +487,12 @@ fn codegen_regular_intrinsic_call<'tcx>(
487487
let layout = fx.layout_of(generic_args.type_at(0));
488488
// Note: Can't use is_unsized here as truly unsized types need to take the fixed size
489489
// branch
490-
let size = if let Abi::ScalarPair(_, _) = ptr.layout().abi {
491-
let (_ptr, info) = ptr.load_scalar_pair(fx);
492-
let (size, _align) = crate::unsize::size_and_align_of_dst(fx, layout, info);
493-
size
490+
let meta = if let Abi::ScalarPair(_, _) = ptr.layout().abi {
491+
Some(ptr.load_scalar_pair(fx).1)
494492
} else {
495-
fx.bcx.ins().iconst(fx.pointer_type, layout.size.bytes() as i64)
493+
None
496494
};
495+
let (size, _align) = crate::unsize::size_and_align_of(fx, layout, meta);
497496
ret.write_cvalue(fx, CValue::by_val(size, usize_layout));
498497
}
499498
sym::min_align_of_val => {
@@ -502,13 +501,12 @@ fn codegen_regular_intrinsic_call<'tcx>(
502501
let layout = fx.layout_of(generic_args.type_at(0));
503502
// Note: Can't use is_unsized here as truly unsized types need to take the fixed size
504503
// branch
505-
let align = if let Abi::ScalarPair(_, _) = ptr.layout().abi {
506-
let (_ptr, info) = ptr.load_scalar_pair(fx);
507-
let (_size, align) = crate::unsize::size_and_align_of_dst(fx, layout, info);
508-
align
504+
let meta = if let Abi::ScalarPair(_, _) = ptr.layout().abi {
505+
Some(ptr.load_scalar_pair(fx).1)
509506
} else {
510-
fx.bcx.ins().iconst(fx.pointer_type, layout.align.abi.bytes() as i64)
507+
None
511508
};
509+
let (_size, align) = crate::unsize::size_and_align_of(fx, layout, meta);
512510
ret.write_cvalue(fx, CValue::by_val(align, usize_layout));
513511
}
514512

@@ -688,7 +686,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
688686
}
689687
})
690688
});
691-
crate::base::codegen_panic_nounwind(fx, &msg_str, source_info);
689+
crate::base::codegen_panic_nounwind(fx, &msg_str, Some(source_info.span));
692690
return;
693691
}
694692
}

src/unsize.rs

+47-8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
//!
33
//! [`PointerCoercion::Unsize`]: `rustc_middle::ty::adjustment::PointerCoercion::Unsize`
44
5+
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
6+
7+
use crate::base::codegen_panic_nounwind;
58
use crate::prelude::*;
69

710
// Adapted from https://github.com/rust-lang/rust/blob/2a663555ddf36f6b041445894a8c175cd1bc718c/src/librustc_codegen_ssa/base.rs#L159-L307
@@ -187,27 +190,62 @@ pub(crate) fn coerce_dyn_star<'tcx>(
187190

188191
// Adapted from https://github.com/rust-lang/rust/blob/2a663555ddf36f6b041445894a8c175cd1bc718c/src/librustc_codegen_ssa/glue.rs
189192

190-
pub(crate) fn size_and_align_of_dst<'tcx>(
193+
pub(crate) fn size_and_align_of<'tcx>(
191194
fx: &mut FunctionCx<'_, '_, 'tcx>,
192195
layout: TyAndLayout<'tcx>,
193-
info: Value,
196+
info: Option<Value>,
194197
) -> (Value, Value) {
195-
assert!(layout.is_unsized() || layout.abi == Abi::Uninhabited);
196-
match layout.ty.kind() {
198+
if layout.is_sized() {
199+
return (
200+
fx.bcx.ins().iconst(fx.pointer_type, layout.size.bytes() as i64),
201+
fx.bcx.ins().iconst(fx.pointer_type, layout.align.abi.bytes() as i64),
202+
);
203+
}
204+
205+
let ty = layout.ty;
206+
match ty.kind() {
197207
ty::Dynamic(..) => {
198208
// load size/align from vtable
199-
(crate::vtable::size_of_obj(fx, info), crate::vtable::min_align_of_obj(fx, info))
209+
(
210+
crate::vtable::size_of_obj(fx, info.unwrap()),
211+
crate::vtable::min_align_of_obj(fx, info.unwrap()),
212+
)
200213
}
201214
ty::Slice(_) | ty::Str => {
202215
let unit = layout.field(fx, 0);
203216
// The info in this case is the length of the str, so the size is that
204217
// times the unit size.
205218
(
206-
fx.bcx.ins().imul_imm(info, unit.size.bytes() as i64),
219+
fx.bcx.ins().imul_imm(info.unwrap(), unit.size.bytes() as i64),
207220
fx.bcx.ins().iconst(fx.pointer_type, unit.align.abi.bytes() as i64),
208221
)
209222
}
210-
_ => {
223+
ty::Foreign(_) => {
224+
let trap_block = fx.bcx.create_block();
225+
let true_ = fx.bcx.ins().iconst(types::I8, 1);
226+
let next_block = fx.bcx.create_block();
227+
fx.bcx.ins().brif(true_, trap_block, &[], next_block, &[]);
228+
fx.bcx.seal_block(trap_block);
229+
fx.bcx.seal_block(next_block);
230+
fx.bcx.switch_to_block(trap_block);
231+
232+
// `extern` type. We cannot compute the size, so panic.
233+
let msg_str = with_no_visible_paths!({
234+
with_no_trimmed_paths!({
235+
format!("attempted to compute the size or alignment of extern type `{ty}`")
236+
})
237+
});
238+
239+
codegen_panic_nounwind(fx, &msg_str, None);
240+
241+
fx.bcx.switch_to_block(next_block);
242+
243+
// This function does not return so we can now return whatever we want.
244+
let size = fx.bcx.ins().iconst(fx.pointer_type, 42);
245+
let align = fx.bcx.ins().iconst(fx.pointer_type, 42);
246+
(size, align)
247+
}
248+
ty::Adt(..) | ty::Tuple(..) => {
211249
// First get the size of all statically known fields.
212250
// Don't use size_of because it also rounds up to alignment, which we
213251
// want to avoid, as the unsized field's alignment could be smaller.
@@ -221,7 +259,7 @@ pub(crate) fn size_and_align_of_dst<'tcx>(
221259
// Recurse to get the size of the dynamically sized field (must be
222260
// the last field).
223261
let field_layout = layout.field(fx, i);
224-
let (unsized_size, mut unsized_align) = size_and_align_of_dst(fx, field_layout, info);
262+
let (unsized_size, mut unsized_align) = size_and_align_of(fx, field_layout, info);
225263

226264
// FIXME (#26403, #27023): We should be adding padding
227265
// to `sized_size` (to accommodate the `unsized_align`
@@ -262,5 +300,6 @@ pub(crate) fn size_and_align_of_dst<'tcx>(
262300

263301
(size, align)
264302
}
303+
_ => bug!("size_and_align_of_dst: {ty} not supported"),
265304
}
266305
}

src/value_and_place.rs

+21-31
Original file line numberDiff line numberDiff line change
@@ -20,34 +20,29 @@ fn codegen_field<'tcx>(
2020
(base.offset_i64(fx, i64::try_from(field_offset.bytes()).unwrap()), field_layout)
2121
};
2222

23-
if let Some(extra) = extra {
24-
if field_layout.is_sized() {
25-
return simple(fx);
23+
if field_layout.is_sized() {
24+
return simple(fx);
25+
}
26+
match field_layout.ty.kind() {
27+
ty::Slice(..) | ty::Str => simple(fx),
28+
ty::Adt(def, _) if def.repr().packed() => {
29+
assert_eq!(layout.align.abi.bytes(), 1);
30+
simple(fx)
2631
}
27-
match field_layout.ty.kind() {
28-
ty::Slice(..) | ty::Str | ty::Foreign(..) => simple(fx),
29-
ty::Adt(def, _) if def.repr().packed() => {
30-
assert_eq!(layout.align.abi.bytes(), 1);
31-
simple(fx)
32-
}
33-
_ => {
34-
// We have to align the offset for DST's
35-
let unaligned_offset = field_offset.bytes();
36-
let (_, unsized_align) =
37-
crate::unsize::size_and_align_of_dst(fx, field_layout, extra);
32+
_ => {
33+
// We have to align the offset for DST's
34+
let unaligned_offset = field_offset.bytes();
35+
let (_, unsized_align) = crate::unsize::size_and_align_of(fx, field_layout, extra);
3836

39-
let one = fx.bcx.ins().iconst(fx.pointer_type, 1);
40-
let align_sub_1 = fx.bcx.ins().isub(unsized_align, one);
41-
let and_lhs = fx.bcx.ins().iadd_imm(align_sub_1, unaligned_offset as i64);
42-
let zero = fx.bcx.ins().iconst(fx.pointer_type, 0);
43-
let and_rhs = fx.bcx.ins().isub(zero, unsized_align);
44-
let offset = fx.bcx.ins().band(and_lhs, and_rhs);
37+
let one = fx.bcx.ins().iconst(fx.pointer_type, 1);
38+
let align_sub_1 = fx.bcx.ins().isub(unsized_align, one);
39+
let and_lhs = fx.bcx.ins().iadd_imm(align_sub_1, unaligned_offset as i64);
40+
let zero = fx.bcx.ins().iconst(fx.pointer_type, 0);
41+
let and_rhs = fx.bcx.ins().isub(zero, unsized_align);
42+
let offset = fx.bcx.ins().band(and_lhs, and_rhs);
4543

46-
(base.offset_value(fx, offset), field_layout)
47-
}
44+
(base.offset_value(fx, offset), field_layout)
4845
}
49-
} else {
50-
simple(fx)
5146
}
5247
}
5348

@@ -731,13 +726,8 @@ impl<'tcx> CPlace<'tcx> {
731726
};
732727

733728
let (field_ptr, field_layout) = codegen_field(fx, base, extra, layout, field);
734-
if field_layout.is_unsized() {
735-
if let ty::Foreign(_) = field_layout.ty.kind() {
736-
assert!(extra.is_none());
737-
CPlace::for_ptr(field_ptr, field_layout)
738-
} else {
739-
CPlace::for_ptr_with_extra(field_ptr, extra.unwrap(), field_layout)
740-
}
729+
if has_ptr_meta(fx.tcx, field_layout.ty) {
730+
CPlace::for_ptr_with_extra(field_ptr, extra.unwrap(), field_layout)
741731
} else {
742732
CPlace::for_ptr(field_ptr, field_layout)
743733
}

0 commit comments

Comments
 (0)