Mark scalar layout unions so that backends that do not support partially initialized scalars can special case them.
This commit is contained in:
parent
2ed6786404
commit
d32ce37a17
@ -21,7 +21,7 @@ pub(crate) fn pointer_ty(tcx: TyCtxt<'_>) -> types::Type {
|
||||
}
|
||||
|
||||
pub(crate) fn scalar_to_clif_type(tcx: TyCtxt<'_>, scalar: Scalar) -> Type {
|
||||
match scalar.value {
|
||||
match scalar.primitive() {
|
||||
Primitive::Int(int, _sign) => match int {
|
||||
Integer::I8 => types::I8,
|
||||
Integer::I16 => types::I16,
|
||||
|
@ -105,7 +105,7 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
|
||||
// Decode the discriminant (specifically if it's niche-encoded).
|
||||
match *tag_encoding {
|
||||
TagEncoding::Direct => {
|
||||
let signed = match tag_scalar.value {
|
||||
let signed = match tag_scalar.primitive() {
|
||||
Int(_, signed) => signed,
|
||||
_ => false,
|
||||
};
|
||||
|
@ -50,7 +50,7 @@ fn codegen_field<'tcx>(
|
||||
}
|
||||
|
||||
fn scalar_pair_calculate_b_offset(tcx: TyCtxt<'_>, a_scalar: Scalar, b_scalar: Scalar) -> Offset32 {
|
||||
let b_offset = a_scalar.value.size(&tcx).align_to(b_scalar.value.align(&tcx).abi);
|
||||
let b_offset = a_scalar.size(&tcx).align_to(b_scalar.align(&tcx).abi);
|
||||
Offset32::new(b_offset.bytes().try_into().unwrap())
|
||||
}
|
||||
|
||||
|
@ -694,11 +694,11 @@ fn load_operand(&mut self, place: PlaceRef<'tcx, RValue<'gcc>>) -> OperandRef<'t
|
||||
}
|
||||
|
||||
fn scalar_load_metadata<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, load: RValue<'gcc>, scalar: &abi::Scalar) {
|
||||
let vr = scalar.valid_range.clone();
|
||||
match scalar.value {
|
||||
let vr = scalar.valid_range(bx);
|
||||
match scalar.primitive() {
|
||||
abi::Int(..) => {
|
||||
if !scalar.is_always_valid(bx) {
|
||||
bx.range_metadata(load, scalar.valid_range);
|
||||
bx.range_metadata(load, vr);
|
||||
}
|
||||
}
|
||||
abi::Pointer if vr.start < vr.end && !vr.contains(0) => {
|
||||
@ -720,7 +720,7 @@ fn scalar_load_metadata<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, load:
|
||||
OperandValue::Immediate(self.to_immediate(load, place.layout))
|
||||
}
|
||||
else if let abi::Abi::ScalarPair(ref a, ref b) = place.layout.abi {
|
||||
let b_offset = a.value.size(self).align_to(b.value.align(self).abi);
|
||||
let b_offset = a.size(self).align_to(b.align(self).abi);
|
||||
let pair_type = place.layout.gcc_type(self, false);
|
||||
|
||||
let mut load = |i, scalar: &abi::Scalar, align| {
|
||||
|
@ -158,14 +158,14 @@ fn const_to_opt_u128(&self, _v: RValue<'gcc>, _sign_ext: bool) -> Option<u128> {
|
||||
}
|
||||
|
||||
fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, ty: Type<'gcc>) -> RValue<'gcc> {
|
||||
let bitsize = if layout.is_bool() { 1 } else { layout.value.size(self).bits() };
|
||||
let bitsize = if layout.is_bool() { 1 } else { layout.size(self).bits() };
|
||||
match cv {
|
||||
Scalar::Int(ScalarInt::ZST) => {
|
||||
assert_eq!(0, layout.value.size(self).bytes());
|
||||
assert_eq!(0, layout.size(self).bytes());
|
||||
self.const_undef(self.type_ix(0))
|
||||
}
|
||||
Scalar::Int(int) => {
|
||||
let data = int.assert_bits(layout.value.size(self));
|
||||
let data = int.assert_bits(layout.size(self));
|
||||
|
||||
// FIXME(antoyo): there's some issues with using the u128 code that follows, so hard-code
|
||||
// the paths for floating-point values.
|
||||
@ -209,7 +209,7 @@ fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, ty: Type<'gcc>) ->
|
||||
let base_addr = self.const_bitcast(base_addr, self.usize_type);
|
||||
let offset = self.context.new_rvalue_from_long(self.usize_type, offset.bytes() as i64);
|
||||
let ptr = self.const_bitcast(base_addr + offset, ptr_type);
|
||||
if layout.value != Pointer {
|
||||
if layout.primitive() != Pointer {
|
||||
self.const_bitcast(ptr.dereference(None).to_rvalue(), ty)
|
||||
}
|
||||
else {
|
||||
|
@ -328,7 +328,7 @@ pub fn const_alloc_to_gcc<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, alloc: ConstAl
|
||||
interpret::Pointer::new(alloc_id, Size::from_bytes(ptr_offset)),
|
||||
&cx.tcx,
|
||||
),
|
||||
abi::Scalar { value: Primitive::Pointer, valid_range: WrappingRange { start: 0, end: !0 } },
|
||||
abi::Scalar::Initialized { value: Primitive::Pointer, valid_range: WrappingRange { start: 0, end: !0 } },
|
||||
cx.type_i8p(),
|
||||
));
|
||||
next_offset = offset + pointer_size;
|
||||
|
@ -224,7 +224,7 @@ 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> {
|
||||
match scalar.value {
|
||||
match scalar.primitive() {
|
||||
Int(i, true) => cx.type_from_integer(i),
|
||||
Int(i, false) => cx.type_from_unsigned_integer(i),
|
||||
F32 => cx.type_f32(),
|
||||
@ -282,7 +282,7 @@ fn scalar_pair_element_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, index:
|
||||
Size::ZERO
|
||||
}
|
||||
else {
|
||||
a.value.size(cx).align_to(b.value.align(cx).abi)
|
||||
a.size(cx).align_to(b.align(cx).abi)
|
||||
};
|
||||
self.scalar_gcc_type_at(cx, scalar, offset)
|
||||
}
|
||||
|
@ -510,9 +510,9 @@ fn apply_attrs_callsite(&self, bx: &mut Builder<'_, 'll, 'tcx>, callsite: &'ll V
|
||||
// If the value is a boolean, the range is 0..2 and that ultimately
|
||||
// become 0..0 when the type becomes i1, which would be rejected
|
||||
// by the LLVM verifier.
|
||||
if let Int(..) = scalar.value {
|
||||
if let Int(..) = scalar.primitive() {
|
||||
if !scalar.is_bool() && !scalar.is_always_valid(bx) {
|
||||
bx.range_metadata(callsite, scalar.valid_range);
|
||||
bx.range_metadata(callsite, scalar.valid_range(bx));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -753,7 +753,7 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &'
|
||||
/// Helper function to get the LLVM type for a Scalar. Pointers are returned as
|
||||
/// the equivalent integer type.
|
||||
fn llvm_asm_scalar_type<'ll>(cx: &CodegenCx<'ll, '_>, scalar: Scalar) -> &'ll Type {
|
||||
match scalar.value {
|
||||
match scalar.primitive() {
|
||||
Primitive::Int(Integer::I8, _) => cx.type_i8(),
|
||||
Primitive::Int(Integer::I16, _) => cx.type_i16(),
|
||||
Primitive::Int(Integer::I32, _) => cx.type_i32(),
|
||||
@ -774,7 +774,7 @@ fn llvm_fixup_input<'ll, 'tcx>(
|
||||
) -> &'ll Value {
|
||||
match (reg, layout.abi) {
|
||||
(InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => {
|
||||
if let Primitive::Int(Integer::I8, _) = s.value {
|
||||
if let Primitive::Int(Integer::I8, _) = s.primitive() {
|
||||
let vec_ty = bx.cx.type_vector(bx.cx.type_i8(), 8);
|
||||
bx.insert_element(bx.const_undef(vec_ty), value, bx.const_i32(0))
|
||||
} else {
|
||||
@ -785,7 +785,7 @@ fn llvm_fixup_input<'ll, 'tcx>(
|
||||
let elem_ty = llvm_asm_scalar_type(bx.cx, s);
|
||||
let count = 16 / layout.size.bytes();
|
||||
let vec_ty = bx.cx.type_vector(elem_ty, count);
|
||||
if let Primitive::Pointer = s.value {
|
||||
if let Primitive::Pointer = s.primitive() {
|
||||
value = bx.ptrtoint(value, bx.cx.type_isize());
|
||||
}
|
||||
bx.insert_element(bx.const_undef(vec_ty), value, bx.const_i32(0))
|
||||
@ -800,7 +800,7 @@ fn llvm_fixup_input<'ll, 'tcx>(
|
||||
bx.shuffle_vector(value, bx.const_undef(vec_ty), bx.const_vector(&indices))
|
||||
}
|
||||
(InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s))
|
||||
if s.value == Primitive::F64 =>
|
||||
if s.primitive() == Primitive::F64 =>
|
||||
{
|
||||
bx.bitcast(value, bx.cx.type_i64())
|
||||
}
|
||||
@ -812,7 +812,7 @@ fn llvm_fixup_input<'ll, 'tcx>(
|
||||
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg | ArmInlineAsmRegClass::sreg_low16),
|
||||
Abi::Scalar(s),
|
||||
) => {
|
||||
if let Primitive::Int(Integer::I32, _) = s.value {
|
||||
if let Primitive::Int(Integer::I32, _) = s.primitive() {
|
||||
bx.bitcast(value, bx.cx.type_f32())
|
||||
} else {
|
||||
value
|
||||
@ -826,19 +826,21 @@ fn llvm_fixup_input<'ll, 'tcx>(
|
||||
),
|
||||
Abi::Scalar(s),
|
||||
) => {
|
||||
if let Primitive::Int(Integer::I64, _) = s.value {
|
||||
if let Primitive::Int(Integer::I64, _) = s.primitive() {
|
||||
bx.bitcast(value, bx.cx.type_f64())
|
||||
} else {
|
||||
value
|
||||
}
|
||||
}
|
||||
(InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => match s.value {
|
||||
// MIPS only supports register-length arithmetics.
|
||||
Primitive::Int(Integer::I8 | Integer::I16, _) => bx.zext(value, bx.cx.type_i32()),
|
||||
Primitive::F32 => bx.bitcast(value, bx.cx.type_i32()),
|
||||
Primitive::F64 => bx.bitcast(value, bx.cx.type_i64()),
|
||||
_ => value,
|
||||
},
|
||||
(InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => {
|
||||
match s.primitive() {
|
||||
// MIPS only supports register-length arithmetics.
|
||||
Primitive::Int(Integer::I8 | Integer::I16, _) => bx.zext(value, bx.cx.type_i32()),
|
||||
Primitive::F32 => bx.bitcast(value, bx.cx.type_i32()),
|
||||
Primitive::F64 => bx.bitcast(value, bx.cx.type_i64()),
|
||||
_ => value,
|
||||
}
|
||||
}
|
||||
_ => value,
|
||||
}
|
||||
}
|
||||
@ -852,7 +854,7 @@ fn llvm_fixup_output<'ll, 'tcx>(
|
||||
) -> &'ll Value {
|
||||
match (reg, layout.abi) {
|
||||
(InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => {
|
||||
if let Primitive::Int(Integer::I8, _) = s.value {
|
||||
if let Primitive::Int(Integer::I8, _) = s.primitive() {
|
||||
bx.extract_element(value, bx.const_i32(0))
|
||||
} else {
|
||||
value
|
||||
@ -860,7 +862,7 @@ fn llvm_fixup_output<'ll, 'tcx>(
|
||||
}
|
||||
(InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16), Abi::Scalar(s)) => {
|
||||
value = bx.extract_element(value, bx.const_i32(0));
|
||||
if let Primitive::Pointer = s.value {
|
||||
if let Primitive::Pointer = s.primitive() {
|
||||
value = bx.inttoptr(value, layout.llvm_type(bx.cx));
|
||||
}
|
||||
value
|
||||
@ -875,7 +877,7 @@ fn llvm_fixup_output<'ll, 'tcx>(
|
||||
bx.shuffle_vector(value, bx.const_undef(vec_ty), bx.const_vector(&indices))
|
||||
}
|
||||
(InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s))
|
||||
if s.value == Primitive::F64 =>
|
||||
if s.primitive() == Primitive::F64 =>
|
||||
{
|
||||
bx.bitcast(value, bx.cx.type_f64())
|
||||
}
|
||||
@ -887,7 +889,7 @@ fn llvm_fixup_output<'ll, 'tcx>(
|
||||
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg | ArmInlineAsmRegClass::sreg_low16),
|
||||
Abi::Scalar(s),
|
||||
) => {
|
||||
if let Primitive::Int(Integer::I32, _) = s.value {
|
||||
if let Primitive::Int(Integer::I32, _) = s.primitive() {
|
||||
bx.bitcast(value, bx.cx.type_i32())
|
||||
} else {
|
||||
value
|
||||
@ -901,20 +903,22 @@ fn llvm_fixup_output<'ll, 'tcx>(
|
||||
),
|
||||
Abi::Scalar(s),
|
||||
) => {
|
||||
if let Primitive::Int(Integer::I64, _) = s.value {
|
||||
if let Primitive::Int(Integer::I64, _) = s.primitive() {
|
||||
bx.bitcast(value, bx.cx.type_i64())
|
||||
} else {
|
||||
value
|
||||
}
|
||||
}
|
||||
(InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => match s.value {
|
||||
// MIPS only supports register-length arithmetics.
|
||||
Primitive::Int(Integer::I8, _) => bx.trunc(value, bx.cx.type_i8()),
|
||||
Primitive::Int(Integer::I16, _) => bx.trunc(value, bx.cx.type_i16()),
|
||||
Primitive::F32 => bx.bitcast(value, bx.cx.type_f32()),
|
||||
Primitive::F64 => bx.bitcast(value, bx.cx.type_f64()),
|
||||
_ => value,
|
||||
},
|
||||
(InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => {
|
||||
match s.primitive() {
|
||||
// MIPS only supports register-length arithmetics.
|
||||
Primitive::Int(Integer::I8, _) => bx.trunc(value, bx.cx.type_i8()),
|
||||
Primitive::Int(Integer::I16, _) => bx.trunc(value, bx.cx.type_i16()),
|
||||
Primitive::F32 => bx.bitcast(value, bx.cx.type_f32()),
|
||||
Primitive::F64 => bx.bitcast(value, bx.cx.type_f64()),
|
||||
_ => value,
|
||||
}
|
||||
}
|
||||
_ => value,
|
||||
}
|
||||
}
|
||||
@ -927,7 +931,7 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
|
||||
) -> &'ll Type {
|
||||
match (reg, layout.abi) {
|
||||
(InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => {
|
||||
if let Primitive::Int(Integer::I8, _) = s.value {
|
||||
if let Primitive::Int(Integer::I8, _) = s.primitive() {
|
||||
cx.type_vector(cx.type_i8(), 8)
|
||||
} else {
|
||||
layout.llvm_type(cx)
|
||||
@ -946,7 +950,7 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
|
||||
cx.type_vector(elem_ty, count * 2)
|
||||
}
|
||||
(InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s))
|
||||
if s.value == Primitive::F64 =>
|
||||
if s.primitive() == Primitive::F64 =>
|
||||
{
|
||||
cx.type_i64()
|
||||
}
|
||||
@ -958,7 +962,7 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
|
||||
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg | ArmInlineAsmRegClass::sreg_low16),
|
||||
Abi::Scalar(s),
|
||||
) => {
|
||||
if let Primitive::Int(Integer::I32, _) = s.value {
|
||||
if let Primitive::Int(Integer::I32, _) = s.primitive() {
|
||||
cx.type_f32()
|
||||
} else {
|
||||
layout.llvm_type(cx)
|
||||
@ -972,19 +976,21 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
|
||||
),
|
||||
Abi::Scalar(s),
|
||||
) => {
|
||||
if let Primitive::Int(Integer::I64, _) = s.value {
|
||||
if let Primitive::Int(Integer::I64, _) = s.primitive() {
|
||||
cx.type_f64()
|
||||
} else {
|
||||
layout.llvm_type(cx)
|
||||
}
|
||||
}
|
||||
(InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => match s.value {
|
||||
// MIPS only supports register-length arithmetics.
|
||||
Primitive::Int(Integer::I8 | Integer::I16, _) => cx.type_i32(),
|
||||
Primitive::F32 => cx.type_i32(),
|
||||
Primitive::F64 => cx.type_i64(),
|
||||
_ => layout.llvm_type(cx),
|
||||
},
|
||||
(InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => {
|
||||
match s.primitive() {
|
||||
// MIPS only supports register-length arithmetics.
|
||||
Primitive::Int(Integer::I8 | Integer::I16, _) => cx.type_i32(),
|
||||
Primitive::F32 => cx.type_i32(),
|
||||
Primitive::F64 => cx.type_i64(),
|
||||
_ => layout.llvm_type(cx),
|
||||
}
|
||||
}
|
||||
_ => layout.llvm_type(cx),
|
||||
}
|
||||
}
|
||||
|
@ -484,14 +484,14 @@ fn scalar_load_metadata<'a, 'll, 'tcx>(
|
||||
bx.noundef_metadata(load);
|
||||
}
|
||||
|
||||
match scalar.value {
|
||||
match scalar.primitive() {
|
||||
abi::Int(..) => {
|
||||
if !scalar.is_always_valid(bx) {
|
||||
bx.range_metadata(load, scalar.valid_range);
|
||||
bx.range_metadata(load, scalar.valid_range(bx));
|
||||
}
|
||||
}
|
||||
abi::Pointer => {
|
||||
if !scalar.valid_range.contains(0) {
|
||||
if !scalar.valid_range(bx).contains(0) {
|
||||
bx.nonnull_metadata(load);
|
||||
}
|
||||
|
||||
@ -525,7 +525,7 @@ fn scalar_load_metadata<'a, 'll, 'tcx>(
|
||||
});
|
||||
OperandValue::Immediate(self.to_immediate(llval, place.layout))
|
||||
} else if let abi::Abi::ScalarPair(a, b) = place.layout.abi {
|
||||
let b_offset = a.value.size(self).align_to(b.value.align(self).abi);
|
||||
let b_offset = a.size(self).align_to(b.align(self).abi);
|
||||
let pair_ty = place.layout.llvm_type(self);
|
||||
|
||||
let mut load = |i, scalar: abi::Scalar, layout, align, offset| {
|
||||
|
@ -221,16 +221,16 @@ fn const_to_opt_u128(&self, v: &'ll Value, sign_ext: bool) -> Option<u128> {
|
||||
}
|
||||
|
||||
fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, llty: &'ll Type) -> &'ll Value {
|
||||
let bitsize = if layout.is_bool() { 1 } else { layout.value.size(self).bits() };
|
||||
let bitsize = if layout.is_bool() { 1 } else { layout.size(self).bits() };
|
||||
match cv {
|
||||
Scalar::Int(ScalarInt::ZST) => {
|
||||
assert_eq!(0, layout.value.size(self).bytes());
|
||||
assert_eq!(0, layout.size(self).bytes());
|
||||
self.const_undef(self.type_ix(0))
|
||||
}
|
||||
Scalar::Int(int) => {
|
||||
let data = int.assert_bits(layout.value.size(self));
|
||||
let data = int.assert_bits(layout.size(self));
|
||||
let llval = self.const_uint_big(self.type_ix(bitsize), data);
|
||||
if layout.value == Pointer {
|
||||
if layout.primitive() == Pointer {
|
||||
unsafe { llvm::LLVMConstIntToPtr(llval, llty) }
|
||||
} else {
|
||||
self.const_bitcast(llval, llty)
|
||||
@ -269,7 +269,7 @@ fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, llty: &'ll Type) ->
|
||||
1,
|
||||
)
|
||||
};
|
||||
if layout.value != Pointer {
|
||||
if layout.primitive() != Pointer {
|
||||
unsafe { llvm::LLVMConstPtrToInt(llval, llty) }
|
||||
} else {
|
||||
self.const_bitcast(llval, llty)
|
||||
|
@ -109,7 +109,10 @@ fn append_chunks_of_init_and_uninit_bytes<'ll, 'a, 'b>(
|
||||
Pointer::new(alloc_id, Size::from_bytes(ptr_offset)),
|
||||
&cx.tcx,
|
||||
),
|
||||
Scalar { value: Primitive::Pointer, valid_range: WrappingRange { start: 0, end: !0 } },
|
||||
Scalar::Initialized {
|
||||
value: Primitive::Pointer,
|
||||
valid_range: WrappingRange { start: 0, end: !0 },
|
||||
},
|
||||
cx.type_i8p_ext(address_space),
|
||||
));
|
||||
next_offset = offset + pointer_size;
|
||||
|
@ -118,7 +118,7 @@ fn tag_base_type<'ll, 'tcx>(
|
||||
|
||||
Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, tag, .. } => {
|
||||
// Niche tags are always normalized to unsized integers of the correct size.
|
||||
match tag.value {
|
||||
match tag.primitive() {
|
||||
Primitive::Int(t, _) => t,
|
||||
Primitive::F32 => Integer::I32,
|
||||
Primitive::F64 => Integer::I64,
|
||||
@ -136,7 +136,7 @@ fn tag_base_type<'ll, 'tcx>(
|
||||
|
||||
Variants::Multiple { tag_encoding: TagEncoding::Direct, tag, .. } => {
|
||||
// Direct tags preserve the sign.
|
||||
tag.value.to_ty(cx.tcx)
|
||||
tag.primitive().to_ty(cx.tcx)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -425,7 +425,7 @@ fn compute_discriminant_value<'ll, 'tcx>(
|
||||
let value = (variant_index.as_u32() as u128)
|
||||
.wrapping_sub(niche_variants.start().as_u32() as u128)
|
||||
.wrapping_add(niche_start);
|
||||
let value = tag.value.size(cx).truncate(value);
|
||||
let value = tag.size(cx).truncate(value);
|
||||
// NOTE(eddyb) do *NOT* remove this assert, until
|
||||
// we pass the full 128-bit value to LLVM, otherwise
|
||||
// truncation will be silent and remain undetected.
|
||||
|
@ -134,7 +134,7 @@ fn codegen_intrinsic_call(
|
||||
sym::va_arg => {
|
||||
match fn_abi.ret.layout.abi {
|
||||
abi::Abi::Scalar(scalar) => {
|
||||
match scalar.value {
|
||||
match scalar.primitive() {
|
||||
Primitive::Int(..) => {
|
||||
if self.cx().size_of(ret_ty).bytes() < 4 {
|
||||
// `va_arg` should not be called on an integer type
|
||||
|
@ -309,7 +309,7 @@ fn scalar_llvm_type_at<'a>(
|
||||
scalar: Scalar,
|
||||
offset: Size,
|
||||
) -> &'a Type {
|
||||
match scalar.value {
|
||||
match scalar.primitive() {
|
||||
Int(i, _) => cx.type_from_integer(i),
|
||||
F32 => cx.type_f32(),
|
||||
F64 => cx.type_f64(),
|
||||
@ -362,8 +362,7 @@ fn scalar_pair_element_llvm_type<'a>(
|
||||
return cx.type_i1();
|
||||
}
|
||||
|
||||
let offset =
|
||||
if index == 0 { Size::ZERO } else { a.value.size(cx).align_to(b.value.align(cx).abi) };
|
||||
let offset = if index == 0 { Size::ZERO } else { a.size(cx).align_to(b.align(cx).abi) };
|
||||
self.scalar_llvm_type_at(cx, scalar, offset)
|
||||
}
|
||||
|
||||
|
@ -464,13 +464,13 @@ fn msvc_enum_fallback<'tcx>(
|
||||
|
||||
// calculate the range of values for the dataful variant
|
||||
let dataful_discriminant_range =
|
||||
dataful_variant_layout.largest_niche().unwrap().scalar.valid_range;
|
||||
dataful_variant_layout.largest_niche().unwrap().valid_range;
|
||||
|
||||
let min = dataful_discriminant_range.start;
|
||||
let min = tag.value.size(&tcx).truncate(min);
|
||||
let min = tag.size(&tcx).truncate(min);
|
||||
|
||||
let max = dataful_discriminant_range.end;
|
||||
let max = tag.value.size(&tcx).truncate(max);
|
||||
let max = tag.size(&tcx).truncate(max);
|
||||
|
||||
let dataful_variant_name = variant_name(*dataful_variant);
|
||||
write!(output, ", {}, {}, {}", min, max, dataful_variant_name).unwrap();
|
||||
|
@ -1572,7 +1572,9 @@ fn codegen_transmute_into(
|
||||
match (src.layout.abi, dst.layout.abi) {
|
||||
(abi::Abi::Scalar(src_scalar), abi::Abi::Scalar(dst_scalar)) => {
|
||||
// HACK(eddyb) LLVM doesn't like `bitcast`s between pointers and non-pointers.
|
||||
if (src_scalar.value == abi::Pointer) == (dst_scalar.value == abi::Pointer) {
|
||||
if (src_scalar.primitive() == abi::Pointer)
|
||||
== (dst_scalar.primitive() == abi::Pointer)
|
||||
{
|
||||
assert_eq!(src.layout.size, dst.layout.size);
|
||||
|
||||
// NOTE(eddyb) the `from_immediate` and `to_immediate_scalar`
|
||||
|
@ -207,11 +207,11 @@ pub fn extract_field<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
|
||||
// Extract a scalar component from a pair.
|
||||
(OperandValue::Pair(a_llval, b_llval), Abi::ScalarPair(a, b)) => {
|
||||
if offset.bytes() == 0 {
|
||||
assert_eq!(field.size, a.value.size(bx.cx()));
|
||||
assert_eq!(field.size, a.size(bx.cx()));
|
||||
OperandValue::Immediate(a_llval)
|
||||
} else {
|
||||
assert_eq!(offset, a.value.size(bx.cx()).align_to(b.value.align(bx.cx()).abi));
|
||||
assert_eq!(field.size, b.value.size(bx.cx()));
|
||||
assert_eq!(offset, a.size(bx.cx()).align_to(b.align(bx.cx()).abi));
|
||||
assert_eq!(field.size, b.size(bx.cx()));
|
||||
OperandValue::Immediate(b_llval)
|
||||
}
|
||||
}
|
||||
@ -316,7 +316,7 @@ fn store_with_flags<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
|
||||
bug!("store_with_flags: invalid ScalarPair layout: {:#?}", dest.layout);
|
||||
};
|
||||
let ty = bx.backend_type(dest.layout);
|
||||
let b_offset = a_scalar.value.size(bx).align_to(b_scalar.value.align(bx).abi);
|
||||
let b_offset = a_scalar.size(bx).align_to(b_scalar.align(bx).abi);
|
||||
|
||||
let llptr = bx.struct_gep(ty, dest.llval, 0);
|
||||
let val = bx.from_immediate(a);
|
||||
|
@ -100,7 +100,7 @@ pub fn project_field<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
|
||||
self.llval
|
||||
}
|
||||
Abi::ScalarPair(a, b)
|
||||
if offset == a.value.size(bx.cx()).align_to(b.value.align(bx.cx()).abi) =>
|
||||
if offset == a.size(bx.cx()).align_to(b.align(bx.cx()).abi) =>
|
||||
{
|
||||
// Offset matches second field.
|
||||
let ty = bx.backend_type(self.layout);
|
||||
@ -234,7 +234,7 @@ pub fn codegen_get_discr<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
|
||||
// Decode the discriminant (specifically if it's niche-encoded).
|
||||
match *tag_encoding {
|
||||
TagEncoding::Direct => {
|
||||
let signed = match tag_scalar.value {
|
||||
let signed = match tag_scalar.primitive() {
|
||||
// We use `i1` for bytes that are always `0` or `1`,
|
||||
// e.g., `#[repr(i8)] enum E { A, B }`, but we can't
|
||||
// let LLVM interpret the `i1` as signed, because
|
||||
|
@ -299,7 +299,7 @@ pub fn codegen_rvalue_operand(
|
||||
|
||||
let mut signed = false;
|
||||
if let Abi::Scalar(scalar) = operand.layout.abi {
|
||||
if let Int(_, s) = scalar.value {
|
||||
if let Int(_, s) = scalar.primitive() {
|
||||
// We use `i1` for bytes that are always `0` or `1`,
|
||||
// e.g., `#[repr(i8)] enum E { A, B }`, but we can't
|
||||
// let LLVM interpret the `i1` as signed, because
|
||||
@ -307,15 +307,17 @@ pub fn codegen_rvalue_operand(
|
||||
signed = !scalar.is_bool() && s;
|
||||
|
||||
if !scalar.is_always_valid(bx.cx())
|
||||
&& scalar.valid_range.end >= scalar.valid_range.start
|
||||
&& scalar.valid_range(bx.cx()).end
|
||||
>= scalar.valid_range(bx.cx()).start
|
||||
{
|
||||
// We want `table[e as usize ± k]` to not
|
||||
// have bound checks, and this is the most
|
||||
// convenient place to put the `assume`s.
|
||||
if scalar.valid_range.start > 0 {
|
||||
let enum_value_lower_bound = bx
|
||||
.cx()
|
||||
.const_uint_big(ll_t_in, scalar.valid_range.start);
|
||||
if scalar.valid_range(bx.cx()).start > 0 {
|
||||
let enum_value_lower_bound = bx.cx().const_uint_big(
|
||||
ll_t_in,
|
||||
scalar.valid_range(bx.cx()).start,
|
||||
);
|
||||
let cmp_start = bx.icmp(
|
||||
IntPredicate::IntUGE,
|
||||
llval,
|
||||
@ -324,8 +326,9 @@ pub fn codegen_rvalue_operand(
|
||||
bx.assume(cmp_start);
|
||||
}
|
||||
|
||||
let enum_value_upper_bound =
|
||||
bx.cx().const_uint_big(ll_t_in, scalar.valid_range.end);
|
||||
let enum_value_upper_bound = bx
|
||||
.cx()
|
||||
.const_uint_big(ll_t_in, scalar.valid_range(bx.cx()).end);
|
||||
let cmp_end = bx.icmp(
|
||||
IntPredicate::IntULE,
|
||||
llval,
|
||||
|
@ -188,7 +188,7 @@ pub fn emulate_intrinsic(
|
||||
let val = self.read_scalar(&args[0])?.check_init()?;
|
||||
let bits = val.to_bits(layout_of.size)?;
|
||||
let kind = match layout_of.abi {
|
||||
Abi::Scalar(scalar) => scalar.value,
|
||||
Abi::Scalar(scalar) => scalar.primitive(),
|
||||
_ => span_bug!(
|
||||
self.cur_span(),
|
||||
"{} called on invalid type {:?}",
|
||||
|
@ -265,6 +265,11 @@ fn try_read_immediate_from_mplace(
|
||||
}));
|
||||
};
|
||||
|
||||
// It may seem like all types with `Scalar` or `ScalarPair` ABI are fair game at this point.
|
||||
// However, `MaybeUninit<u64>` is considered a `Scalar` as far as its layout is concerned --
|
||||
// and yet cannot be represented by an interpreter `Scalar`, since we have to handle the
|
||||
// case where some of the bytes are initialized and others are not. So, we only permit
|
||||
// reads from `Scalar`s and `ScalarPair`s that cannot be uninitialized.
|
||||
match mplace.layout.abi {
|
||||
Abi::Scalar(..) => {
|
||||
let scalar = alloc.read_scalar(alloc_range(Size::ZERO, mplace.layout.size))?;
|
||||
@ -274,7 +279,6 @@ fn try_read_immediate_from_mplace(
|
||||
// We checked `ptr_align` above, so all fields will have the alignment they need.
|
||||
// We would anyway check against `ptr_align.restrict_for_offset(b_offset)`,
|
||||
// which `ptr.offset(b_offset)` cannot possibly fail to satisfy.
|
||||
let (a, b) = (a.value, b.value);
|
||||
let (a_size, b_size) = (a.size(self), b.size(self));
|
||||
let b_offset = a_size.align_to(b.align(self).abi);
|
||||
assert!(b_offset.bytes() > 0); // we later use the offset to tell apart the fields
|
||||
@ -676,7 +680,7 @@ pub fn read_discriminant(
|
||||
// may be a pointer. This is `tag_val.layout`; we just use it for sanity checks.
|
||||
|
||||
// Get layout for tag.
|
||||
let tag_layout = self.layout_of(tag_scalar_layout.value.to_int_ty(*self.tcx))?;
|
||||
let tag_layout = self.layout_of(tag_scalar_layout.primitive().to_int_ty(*self.tcx))?;
|
||||
|
||||
// Read tag and sanity-check `tag_layout`.
|
||||
let tag_val = self.read_immediate(&self.operand_field(op, tag_field)?)?;
|
||||
|
@ -772,13 +772,11 @@ fn write_immediate_to_mplace_no_validate(
|
||||
// We checked `ptr_align` above, so all fields will have the alignment they need.
|
||||
// We would anyway check against `ptr_align.restrict_for_offset(b_offset)`,
|
||||
// which `ptr.offset(b_offset)` cannot possibly fail to satisfy.
|
||||
let (a, b) = match dest.layout.abi {
|
||||
Abi::ScalarPair(a, b) => (a.value, b.value),
|
||||
_ => span_bug!(
|
||||
let Abi::ScalarPair(a, b) = dest.layout.abi else { span_bug!(
|
||||
self.cur_span(),
|
||||
"write_immediate_to_mplace: invalid ScalarPair layout: {:#?}",
|
||||
dest.layout
|
||||
),
|
||||
)
|
||||
};
|
||||
let (a_size, b_size) = (a.size(&tcx), b.size(&tcx));
|
||||
let b_offset = a_size.align_to(b.align(&tcx).abi);
|
||||
@ -1047,7 +1045,7 @@ pub fn write_discriminant(
|
||||
// raw discriminants for enums are isize or bigger during
|
||||
// their computation, but the in-memory tag is the smallest possible
|
||||
// representation
|
||||
let size = tag_layout.value.size(self);
|
||||
let size = tag_layout.size(self);
|
||||
let tag_val = size.truncate(discr_val);
|
||||
|
||||
let tag_dest = self.place_field(dest, tag_field)?;
|
||||
@ -1071,7 +1069,7 @@ pub fn write_discriminant(
|
||||
.expect("overflow computing relative variant idx");
|
||||
// We need to use machine arithmetic when taking into account `niche_start`:
|
||||
// tag_val = variant_index_relative + niche_start_val
|
||||
let tag_layout = self.layout_of(tag_layout.value.to_int_ty(*self.tcx))?;
|
||||
let tag_layout = self.layout_of(tag_layout.primitive().to_int_ty(*self.tcx))?;
|
||||
let niche_start_val = ImmTy::from_uint(niche_start, tag_layout);
|
||||
let variant_index_relative_val =
|
||||
ImmTy::from_uint(variant_index_relative, tag_layout);
|
||||
|
@ -189,12 +189,15 @@ fn check_argument_compat(
|
||||
// that will take care to make it UB to leave the range, just
|
||||
// like for transmute).
|
||||
(abi::Abi::Scalar(caller), abi::Abi::Scalar(callee)) => {
|
||||
caller.value == callee.value
|
||||
caller.primitive() == callee.primitive()
|
||||
}
|
||||
(
|
||||
abi::Abi::ScalarPair(caller1, caller2),
|
||||
abi::Abi::ScalarPair(callee1, callee2),
|
||||
) => caller1.value == callee1.value && caller2.value == callee2.value,
|
||||
) => {
|
||||
caller1.primitive() == callee1.primitive()
|
||||
&& caller2.primitive() == callee2.primitive()
|
||||
}
|
||||
// Be conservative
|
||||
_ => false,
|
||||
}
|
||||
|
@ -629,12 +629,12 @@ fn visit_scalar(
|
||||
op: &OpTy<'tcx, M::PointerTag>,
|
||||
scalar_layout: ScalarAbi,
|
||||
) -> InterpResult<'tcx> {
|
||||
if scalar_layout.valid_range.is_full_for(op.layout.size) {
|
||||
if scalar_layout.valid_range(self.ecx).is_full_for(op.layout.size) {
|
||||
// Nothing to check
|
||||
return Ok(());
|
||||
}
|
||||
// At least one value is excluded.
|
||||
let valid_range = scalar_layout.valid_range;
|
||||
let valid_range = scalar_layout.valid_range(self.ecx);
|
||||
let WrappingRange { start, end } = valid_range;
|
||||
let max_value = op.layout.size.unsigned_int_max();
|
||||
assert!(end <= max_value);
|
||||
|
@ -12,7 +12,7 @@
|
||||
use rustc_span::source_map;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::{Span, Symbol, DUMMY_SP};
|
||||
use rustc_target::abi::Abi;
|
||||
use rustc_target::abi::{Abi, WrappingRange};
|
||||
use rustc_target::abi::{Integer, TagEncoding, Variants};
|
||||
use rustc_target::spec::abi::Abi as SpecAbi;
|
||||
|
||||
@ -796,14 +796,18 @@ fn get_nullable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'t
|
||||
// Return the nullable type this Option-like enum can be safely represented with.
|
||||
let field_ty_abi = &cx.layout_of(field_ty).unwrap().abi;
|
||||
if let Abi::Scalar(field_ty_scalar) = field_ty_abi {
|
||||
match (field_ty_scalar.valid_range.start, field_ty_scalar.valid_range.end) {
|
||||
(0, x) if x == field_ty_scalar.value.size(&cx.tcx).unsigned_int_max() - 1 => {
|
||||
match field_ty_scalar.valid_range(cx) {
|
||||
WrappingRange { start: 0, end }
|
||||
if end == field_ty_scalar.size(&cx.tcx).unsigned_int_max() - 1 =>
|
||||
{
|
||||
return Some(get_nullable_type(cx, field_ty).unwrap());
|
||||
}
|
||||
(1, _) => {
|
||||
WrappingRange { start: 1, .. } => {
|
||||
return Some(get_nullable_type(cx, field_ty).unwrap());
|
||||
}
|
||||
(start, end) => unreachable!("Unhandled start and end range: ({}, {})", start, end),
|
||||
WrappingRange { start, end } => {
|
||||
unreachable!("Unhandled start and end range: ({}, {})", start, end)
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -1342,7 +1346,7 @@ fn check_item(&mut self, cx: &LateContext<'_>, it: &hir::Item<'_>) {
|
||||
return
|
||||
};
|
||||
|
||||
let tag_size = tag.value.size(&cx.tcx).bytes();
|
||||
let tag_size = tag.size(&cx.tcx).bytes();
|
||||
|
||||
debug!(
|
||||
"enum `{}` is {} bytes large with layout:\n{:#?}",
|
||||
|
@ -305,10 +305,10 @@ fn invert_mapping(map: &[u32]) -> Vec<u32> {
|
||||
impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
fn scalar_pair(&self, a: Scalar, b: Scalar) -> LayoutS<'tcx> {
|
||||
let dl = self.data_layout();
|
||||
let b_align = b.value.align(dl);
|
||||
let align = a.value.align(dl).max(b_align).max(dl.aggregate_align);
|
||||
let b_offset = a.value.size(dl).align_to(b_align.abi);
|
||||
let size = (b_offset + b.value.size(dl)).align_to(align.abi);
|
||||
let b_align = b.align(dl);
|
||||
let align = a.align(dl).max(b_align).max(dl.aggregate_align);
|
||||
let b_offset = a.size(dl).align_to(b_align.abi);
|
||||
let size = (b_offset + b.size(dl)).align_to(align.abi);
|
||||
|
||||
// HACK(nox): We iter on `b` and then `a` because `max_by_key`
|
||||
// returns the last maximum.
|
||||
@ -567,7 +567,10 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, LayoutError<'
|
||||
let scalar_unit = |value: Primitive| {
|
||||
let size = value.size(dl);
|
||||
assert!(size.bits() <= 128);
|
||||
Scalar { value, valid_range: WrappingRange { start: 0, end: size.unsigned_int_max() } }
|
||||
Scalar::Initialized {
|
||||
value,
|
||||
valid_range: WrappingRange { start: 0, end: size.unsigned_int_max() },
|
||||
}
|
||||
};
|
||||
let scalar =
|
||||
|value: Primitive| tcx.intern_layout(LayoutS::scalar(self, scalar_unit(value)));
|
||||
@ -581,11 +584,14 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, LayoutError<'
|
||||
// Basic scalars.
|
||||
ty::Bool => tcx.intern_layout(LayoutS::scalar(
|
||||
self,
|
||||
Scalar { value: Int(I8, false), valid_range: WrappingRange { start: 0, end: 1 } },
|
||||
Scalar::Initialized {
|
||||
value: Int(I8, false),
|
||||
valid_range: WrappingRange { start: 0, end: 1 },
|
||||
},
|
||||
)),
|
||||
ty::Char => tcx.intern_layout(LayoutS::scalar(
|
||||
self,
|
||||
Scalar {
|
||||
Scalar::Initialized {
|
||||
value: Int(I32, false),
|
||||
valid_range: WrappingRange { start: 0, end: 0x10FFFF },
|
||||
},
|
||||
@ -598,7 +604,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, LayoutError<'
|
||||
}),
|
||||
ty::FnPtr(_) => {
|
||||
let mut ptr = scalar_unit(Pointer);
|
||||
ptr.valid_range = ptr.valid_range.with_start(1);
|
||||
ptr.valid_range_mut().start = 1;
|
||||
tcx.intern_layout(LayoutS::scalar(self, ptr))
|
||||
}
|
||||
|
||||
@ -616,7 +622,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, LayoutError<'
|
||||
ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
|
||||
let mut data_ptr = scalar_unit(Pointer);
|
||||
if !ty.is_unsafe_ptr() {
|
||||
data_ptr.valid_range = data_ptr.valid_range.with_start(1);
|
||||
data_ptr.valid_range_mut().start = 1;
|
||||
}
|
||||
|
||||
let pointee = tcx.normalize_erasing_regions(param_env, pointee);
|
||||
@ -632,7 +638,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, LayoutError<'
|
||||
ty::Slice(_) | ty::Str => scalar_unit(Int(dl.ptr_sized_integer(), false)),
|
||||
ty::Dynamic(..) => {
|
||||
let mut vtable = scalar_unit(Pointer);
|
||||
vtable.valid_range = vtable.valid_range.with_start(1);
|
||||
vtable.valid_range_mut().start = 1;
|
||||
vtable
|
||||
}
|
||||
_ => return Err(LayoutError::Unknown(unsized_part)),
|
||||
@ -889,14 +895,14 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, LayoutError<'
|
||||
|
||||
// If all non-ZST fields have the same ABI, forward this ABI
|
||||
if optimize && !field.is_zst() {
|
||||
// Normalize scalar_unit to the maximal valid range
|
||||
// Discard valid range information and allow undef
|
||||
let field_abi = match field.abi {
|
||||
Abi::Scalar(x) => Abi::Scalar(scalar_unit(x.value)),
|
||||
Abi::Scalar(x) => Abi::Scalar(x.to_union()),
|
||||
Abi::ScalarPair(x, y) => {
|
||||
Abi::ScalarPair(scalar_unit(x.value), scalar_unit(y.value))
|
||||
Abi::ScalarPair(x.to_union(), y.to_union())
|
||||
}
|
||||
Abi::Vector { element: x, count } => {
|
||||
Abi::Vector { element: scalar_unit(x.value), count }
|
||||
Abi::Vector { element: x.to_union(), count }
|
||||
}
|
||||
Abi::Uninhabited | Abi::Aggregate { .. } => {
|
||||
Abi::Aggregate { sized: true }
|
||||
@ -1000,14 +1006,16 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, LayoutError<'
|
||||
if let Bound::Included(start) = start {
|
||||
// FIXME(eddyb) this might be incorrect - it doesn't
|
||||
// account for wrap-around (end < start) ranges.
|
||||
assert!(scalar.valid_range.start <= start);
|
||||
scalar.valid_range.start = start;
|
||||
let valid_range = scalar.valid_range_mut();
|
||||
assert!(valid_range.start <= start);
|
||||
valid_range.start = start;
|
||||
}
|
||||
if let Bound::Included(end) = end {
|
||||
// FIXME(eddyb) this might be incorrect - it doesn't
|
||||
// account for wrap-around (end < start) ranges.
|
||||
assert!(scalar.valid_range.end >= end);
|
||||
scalar.valid_range.end = end;
|
||||
let valid_range = scalar.valid_range_mut();
|
||||
assert!(valid_range.end >= end);
|
||||
valid_range.end = end;
|
||||
}
|
||||
|
||||
// Update `largest_niche` if we have introduced a larger niche.
|
||||
@ -1133,9 +1141,15 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, LayoutError<'
|
||||
// guaranteed to be initialised, not the
|
||||
// other primitive.
|
||||
if offset.bytes() == 0 {
|
||||
Abi::ScalarPair(niche_scalar, scalar_unit(second.value))
|
||||
Abi::ScalarPair(
|
||||
niche_scalar,
|
||||
scalar_unit(second.primitive()),
|
||||
)
|
||||
} else {
|
||||
Abi::ScalarPair(scalar_unit(first.value), niche_scalar)
|
||||
Abi::ScalarPair(
|
||||
scalar_unit(first.primitive()),
|
||||
niche_scalar,
|
||||
)
|
||||
}
|
||||
}
|
||||
_ => Abi::Aggregate { sized: true },
|
||||
@ -1314,7 +1328,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, LayoutError<'
|
||||
}
|
||||
|
||||
let tag_mask = ity.size().unsigned_int_max();
|
||||
let tag = Scalar {
|
||||
let tag = Scalar::Initialized {
|
||||
value: Int(ity, signed),
|
||||
valid_range: WrappingRange {
|
||||
start: (min as u128 & tag_mask),
|
||||
@ -1325,7 +1339,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, LayoutError<'
|
||||
|
||||
// Without latter check aligned enums with custom discriminant values
|
||||
// Would result in ICE see the issue #92464 for more info
|
||||
if tag.value.size(dl) == size || variants.iter().all(|layout| layout.is_empty()) {
|
||||
if tag.size(dl) == size || variants.iter().all(|layout| layout.is_empty()) {
|
||||
abi = Abi::Scalar(tag);
|
||||
} else {
|
||||
// Try to use a ScalarPair for all tagged enums.
|
||||
@ -1345,7 +1359,7 @@ fn layout_of_uncached(&self, ty: Ty<'tcx>) -> Result<Layout<'tcx>, LayoutError<'
|
||||
}
|
||||
};
|
||||
let prim = match field.abi {
|
||||
Abi::Scalar(scalar) => scalar.value,
|
||||
Abi::Scalar(scalar) => scalar.primitive(),
|
||||
_ => {
|
||||
common_prim = None;
|
||||
break;
|
||||
@ -1599,7 +1613,7 @@ fn generator_layout(
|
||||
let max_discr = (info.variant_fields.len() - 1) as u128;
|
||||
let discr_int = Integer::fit_unsigned(max_discr);
|
||||
let discr_int_ty = discr_int.to_ty(tcx, false);
|
||||
let tag = Scalar {
|
||||
let tag = Scalar::Initialized {
|
||||
value: Primitive::Int(discr_int, false),
|
||||
valid_range: WrappingRange { start: 0, end: max_discr },
|
||||
};
|
||||
@ -1898,7 +1912,7 @@ fn record_layout_for_printing_outlined(&self, layout: TyAndLayout<'tcx>) {
|
||||
adt_kind.into(),
|
||||
adt_packed,
|
||||
match tag_encoding {
|
||||
TagEncoding::Direct => Some(tag.value.size(self)),
|
||||
TagEncoding::Direct => Some(tag.size(self)),
|
||||
_ => None,
|
||||
},
|
||||
variant_infos,
|
||||
@ -2304,7 +2318,7 @@ fn field_ty_or_layout<'tcx>(
|
||||
let tag_layout = |tag: Scalar| -> TyAndLayout<'tcx> {
|
||||
TyAndLayout {
|
||||
layout: tcx.intern_layout(LayoutS::scalar(cx, tag)),
|
||||
ty: tag.value.to_ty(tcx),
|
||||
ty: tag.primitive().to_ty(tcx),
|
||||
}
|
||||
};
|
||||
|
||||
@ -3079,11 +3093,9 @@ fn fn_abi_new_uncached(
|
||||
}
|
||||
|
||||
// Only pointer types handled below.
|
||||
if scalar.value != Pointer {
|
||||
return;
|
||||
}
|
||||
let Scalar::Initialized { value: Pointer, valid_range} = scalar else { return };
|
||||
|
||||
if !scalar.valid_range.contains(0) {
|
||||
if !valid_range.contains(0) {
|
||||
attrs.set(ArgAttribute::NonNull);
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
fn extend_integer_width_mips<Ty>(arg: &mut ArgAbi<'_, Ty>, bits: u64) {
|
||||
// Always sign extend u32 values on 64-bit mips
|
||||
if let abi::Abi::Scalar(scalar) = arg.layout.abi {
|
||||
if let abi::Int(i, signed) = scalar.value {
|
||||
if let abi::Int(i, signed) = scalar.primitive() {
|
||||
if !signed && i.size().bits() == 32 {
|
||||
if let PassMode::Direct(ref mut attrs) = arg.mode {
|
||||
attrs.ext(ArgExtension::Sext);
|
||||
@ -25,7 +25,7 @@ fn float_reg<'a, Ty, C>(cx: &C, ret: &ArgAbi<'a, Ty>, i: usize) -> Option<Reg>
|
||||
C: HasDataLayout,
|
||||
{
|
||||
match ret.layout.field(cx, i).abi {
|
||||
abi::Abi::Scalar(scalar) => match scalar.value {
|
||||
abi::Abi::Scalar(scalar) => match scalar.primitive() {
|
||||
abi::F32 => Some(Reg::f32()),
|
||||
abi::F64 => Some(Reg::f64()),
|
||||
_ => None,
|
||||
@ -110,7 +110,7 @@ fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
|
||||
|
||||
// We only care about aligned doubles
|
||||
if let abi::Abi::Scalar(scalar) = field.abi {
|
||||
if let abi::F64 = scalar.value {
|
||||
if let abi::F64 = scalar.primitive() {
|
||||
if offset.is_aligned(dl.f64_align.abi) {
|
||||
// Insert enough integers to cover [last_offset, offset)
|
||||
assert!(last_offset.is_aligned(dl.f64_align.abi));
|
||||
|
@ -348,7 +348,7 @@ pub fn homogeneous_aggregate<C>(&self, cx: &C) -> Result<HomogeneousAggregate, H
|
||||
|
||||
// The primitive for this algorithm.
|
||||
Abi::Scalar(scalar) => {
|
||||
let kind = match scalar.value {
|
||||
let kind = match scalar.primitive() {
|
||||
abi::Int(..) | abi::Pointer => RegKind::Integer,
|
||||
abi::F32 | abi::F64 => RegKind::Float,
|
||||
};
|
||||
@ -482,7 +482,7 @@ pub fn new(
|
||||
Abi::Scalar(scalar) => PassMode::Direct(scalar_attrs(&layout, scalar, Size::ZERO)),
|
||||
Abi::ScalarPair(a, b) => PassMode::Pair(
|
||||
scalar_attrs(&layout, a, Size::ZERO),
|
||||
scalar_attrs(&layout, b, a.value.size(cx).align_to(b.value.align(cx).abi)),
|
||||
scalar_attrs(&layout, b, a.size(cx).align_to(b.align(cx).abi)),
|
||||
),
|
||||
Abi::Vector { .. } => PassMode::Direct(ArgAttributes::new()),
|
||||
Abi::Aggregate { .. } => PassMode::Direct(ArgAttributes::new()),
|
||||
@ -534,7 +534,7 @@ pub fn make_indirect_byval(&mut self) {
|
||||
pub fn extend_integer_width_to(&mut self, bits: u64) {
|
||||
// Only integers have signedness
|
||||
if let Abi::Scalar(scalar) = self.layout.abi {
|
||||
if let abi::Int(i, signed) = scalar.value {
|
||||
if let abi::Int(i, signed) = scalar.primitive() {
|
||||
if i.size().bits() < bits {
|
||||
if let PassMode::Direct(ref mut attrs) = self.mode {
|
||||
if signed {
|
||||
|
@ -44,7 +44,7 @@ fn should_use_fp_conv_helper<'a, Ty, C>(
|
||||
Ty: TyAbiInterface<'a, C> + Copy,
|
||||
{
|
||||
match arg_layout.abi {
|
||||
Abi::Scalar(scalar) => match scalar.value {
|
||||
Abi::Scalar(scalar) => match scalar.primitive() {
|
||||
abi::Int(..) | abi::Pointer => {
|
||||
if arg_layout.size.bits() > xlen {
|
||||
return Err(CannotUseFpConv);
|
||||
@ -298,7 +298,7 @@ fn classify_arg<'a, Ty, C>(
|
||||
|
||||
fn extend_integer_width<'a, Ty>(arg: &mut ArgAbi<'a, Ty>, xlen: u64) {
|
||||
if let Abi::Scalar(scalar) = arg.layout.abi {
|
||||
if let abi::Int(i, _) = scalar.value {
|
||||
if let abi::Int(i, _) = scalar.primitive() {
|
||||
// 32-bit integers are always sign-extended
|
||||
if i.size().bits() == 32 && xlen > 32 {
|
||||
if let PassMode::Direct(ref mut attrs) = arg.mode {
|
||||
|
@ -20,7 +20,7 @@ fn arg_scalar<C>(cx: &C, scalar: &Scalar, offset: Size, mut data: Sdata) -> Sdat
|
||||
{
|
||||
let dl = cx.data_layout();
|
||||
|
||||
if scalar.value != abi::F32 && scalar.value != abi::F64 {
|
||||
if !scalar.primitive().is_float() {
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ fn arg_scalar<C>(cx: &C, scalar: &Scalar, offset: Size, mut data: Sdata) -> Sdat
|
||||
return data;
|
||||
}
|
||||
|
||||
if scalar.value == abi::F32 {
|
||||
if scalar.primitive() == abi::F32 {
|
||||
data.arg_attribute = ArgAttribute::InReg;
|
||||
data.prefix[data.prefix_index] = Some(Reg::f32());
|
||||
data.last_offset = offset + Reg::f32().size;
|
||||
@ -79,17 +79,15 @@ fn arg_scalar_pair<C>(
|
||||
C: HasDataLayout,
|
||||
{
|
||||
data = arg_scalar(cx, &scalar1, offset, data);
|
||||
if scalar1.value == abi::F32 {
|
||||
offset += Reg::f32().size;
|
||||
} else if scalar2.value == abi::F64 {
|
||||
offset += Reg::f64().size;
|
||||
} else if let abi::Int(i, _signed) = scalar1.value {
|
||||
offset += i.size();
|
||||
} else if scalar1.value == abi::Pointer {
|
||||
offset = offset + Reg::i64().size;
|
||||
match (scalar1.primitive(), scalar2.primitive()) {
|
||||
(abi::F32, _) => offset += Reg::f32().size,
|
||||
(_, abi::F64) => offset += Reg::f64().size,
|
||||
(abi::Int(i, _signed), _) => offset += i.size(),
|
||||
(abi::Pointer, _) => offset += Reg::i64().size,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if (offset.raw % 4) != 0 && (scalar2.value == abi::F32 || scalar2.value == abi::F64) {
|
||||
if (offset.raw % 4) != 0 && scalar2.primitive().is_float() {
|
||||
offset.raw += 4 - (offset.raw % 4);
|
||||
}
|
||||
data = arg_scalar(cx, &scalar2, offset, data);
|
||||
|
@ -49,7 +49,7 @@ fn classify<'a, Ty, C>(
|
||||
let mut c = match layout.abi {
|
||||
Abi::Uninhabited => return Ok(()),
|
||||
|
||||
Abi::Scalar(scalar) => match scalar.value {
|
||||
Abi::Scalar(scalar) => match scalar.primitive() {
|
||||
abi::Int(..) | abi::Pointer => Class::Int,
|
||||
abi::F32 | abi::F64 => Class::Sse,
|
||||
},
|
||||
|
@ -752,6 +752,10 @@ pub struct WrappingRange {
|
||||
}
|
||||
|
||||
impl WrappingRange {
|
||||
pub fn full(size: Size) -> Self {
|
||||
Self { start: 0, end: size.unsigned_int_max() }
|
||||
}
|
||||
|
||||
/// Returns `true` if `v` is contained in the range.
|
||||
#[inline(always)]
|
||||
pub fn contains(&self, v: u128) -> bool {
|
||||
@ -799,13 +803,23 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// Information about one scalar component of a Rust type.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||
#[derive(HashStable_Generic)]
|
||||
pub struct Scalar {
|
||||
pub value: Primitive,
|
||||
pub enum Scalar {
|
||||
Initialized {
|
||||
value: Primitive,
|
||||
|
||||
// FIXME(eddyb) always use the shortest range, e.g., by finding
|
||||
// the largest space between two consecutive valid values and
|
||||
// taking everything else as the (shortest) valid range.
|
||||
pub valid_range: WrappingRange,
|
||||
// FIXME(eddyb) always use the shortest range, e.g., by finding
|
||||
// the largest space between two consecutive valid values and
|
||||
// taking everything else as the (shortest) valid range.
|
||||
valid_range: WrappingRange,
|
||||
},
|
||||
Union {
|
||||
/// Even for unions, we need to use the correct registers for the kind of
|
||||
/// values inside the union, so we keep the `Primitive` type around. We
|
||||
/// also use it to compute the size of the scalar.
|
||||
/// However, unions never have niches and even allow undef,
|
||||
/// so there is no `valid_range`.
|
||||
value: Primitive,
|
||||
},
|
||||
}
|
||||
|
||||
impl Scalar {
|
||||
@ -813,14 +827,58 @@ impl Scalar {
|
||||
pub fn is_bool(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
Scalar { value: Int(I8, false), valid_range: WrappingRange { start: 0, end: 1 } }
|
||||
Scalar::Initialized {
|
||||
value: Int(I8, false),
|
||||
valid_range: WrappingRange { start: 0, end: 1 }
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/// Get the primitive representation of this type, ignoring the valid range and whether the
|
||||
/// value is allowed to be undefined (due to being a union).
|
||||
pub fn primitive(&self) -> Primitive {
|
||||
match *self {
|
||||
Scalar::Initialized { value, .. } | Scalar::Union { value } => value,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn align(self, cx: &impl HasDataLayout) -> AbiAndPrefAlign {
|
||||
self.primitive().align(cx)
|
||||
}
|
||||
|
||||
pub fn size(self, cx: &impl HasDataLayout) -> Size {
|
||||
self.primitive().size(cx)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_union(&self) -> Self {
|
||||
Self::Union { value: self.primitive() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn valid_range(&self, cx: &impl HasDataLayout) -> WrappingRange {
|
||||
match *self {
|
||||
Scalar::Initialized { valid_range, .. } => valid_range,
|
||||
Scalar::Union { value } => WrappingRange::full(value.size(cx)),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Allows the caller to mutate the valid range. This operation will panic if attempted on a union.
|
||||
pub fn valid_range_mut(&mut self) -> &mut WrappingRange {
|
||||
match self {
|
||||
Scalar::Initialized { valid_range, .. } => valid_range,
|
||||
Scalar::Union { .. } => panic!("cannot change the valid range of a union"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if all possible numbers are valid, i.e `valid_range` covers the whole layout
|
||||
#[inline]
|
||||
pub fn is_always_valid<C: HasDataLayout>(&self, cx: &C) -> bool {
|
||||
self.valid_range.is_full_for(self.value.size(cx))
|
||||
match *self {
|
||||
Scalar::Initialized { valid_range, .. } => valid_range.is_full_for(self.size(cx)),
|
||||
Scalar::Union { .. } => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -988,7 +1046,7 @@ pub fn is_unsized(&self) -> bool {
|
||||
#[inline]
|
||||
pub fn is_signed(&self) -> bool {
|
||||
match self {
|
||||
Abi::Scalar(scal) => match scal.value {
|
||||
Abi::Scalar(scal) => match scal.primitive() {
|
||||
Primitive::Int(_, signed) => signed,
|
||||
_ => false,
|
||||
},
|
||||
@ -1060,17 +1118,19 @@ pub enum TagEncoding {
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
|
||||
pub struct Niche {
|
||||
pub offset: Size,
|
||||
pub scalar: Scalar,
|
||||
pub value: Primitive,
|
||||
pub valid_range: WrappingRange,
|
||||
}
|
||||
|
||||
impl Niche {
|
||||
pub fn from_scalar<C: HasDataLayout>(cx: &C, offset: Size, scalar: Scalar) -> Option<Self> {
|
||||
let niche = Niche { offset, scalar };
|
||||
let Scalar::Initialized { value, valid_range } = scalar else { return None };
|
||||
let niche = Niche { offset, value, valid_range };
|
||||
if niche.available(cx) > 0 { Some(niche) } else { None }
|
||||
}
|
||||
|
||||
pub fn available<C: HasDataLayout>(&self, cx: &C) -> u128 {
|
||||
let Scalar { value, valid_range: v } = self.scalar;
|
||||
let Self { value, valid_range: v, .. } = *self;
|
||||
let size = value.size(cx);
|
||||
assert!(size.bits() <= 128);
|
||||
let max_value = size.unsigned_int_max();
|
||||
@ -1083,7 +1143,7 @@ pub fn available<C: HasDataLayout>(&self, cx: &C) -> u128 {
|
||||
pub fn reserve<C: HasDataLayout>(&self, cx: &C, count: u128) -> Option<(u128, Scalar)> {
|
||||
assert!(count > 0);
|
||||
|
||||
let Scalar { value, valid_range: v } = self.scalar;
|
||||
let Self { value, valid_range: v, .. } = *self;
|
||||
let size = value.size(cx);
|
||||
assert!(size.bits() <= 128);
|
||||
let max_value = size.unsigned_int_max();
|
||||
@ -1107,12 +1167,12 @@ pub fn reserve<C: HasDataLayout>(&self, cx: &C, count: u128) -> Option<(u128, Sc
|
||||
// If niche zero is already reserved, the selection of bounds are of little interest.
|
||||
let move_start = |v: WrappingRange| {
|
||||
let start = v.start.wrapping_sub(count) & max_value;
|
||||
Some((start, Scalar { value, valid_range: v.with_start(start) }))
|
||||
Some((start, Scalar::Initialized { value, valid_range: v.with_start(start) }))
|
||||
};
|
||||
let move_end = |v: WrappingRange| {
|
||||
let start = v.end.wrapping_add(1) & max_value;
|
||||
let end = v.end.wrapping_add(count) & max_value;
|
||||
Some((start, Scalar { value, valid_range: v.with_end(end) }))
|
||||
Some((start, Scalar::Initialized { value, valid_range: v.with_end(end) }))
|
||||
};
|
||||
let distance_end_zero = max_value - v.end;
|
||||
if v.start > v.end {
|
||||
@ -1172,8 +1232,8 @@ pub struct LayoutS<'a> {
|
||||
impl<'a> LayoutS<'a> {
|
||||
pub fn scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self {
|
||||
let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar);
|
||||
let size = scalar.value.size(cx);
|
||||
let align = scalar.value.align(cx);
|
||||
let size = scalar.size(cx);
|
||||
let align = scalar.align(cx);
|
||||
LayoutS {
|
||||
variants: Variants::Single { index: VariantIdx::new(0) },
|
||||
fields: FieldsShape::Primitive,
|
||||
@ -1325,7 +1385,7 @@ pub fn is_single_fp_element<C>(self, cx: &C) -> bool
|
||||
C: HasDataLayout,
|
||||
{
|
||||
match self.abi {
|
||||
Abi::Scalar(scalar) => scalar.value.is_float(),
|
||||
Abi::Scalar(scalar) => scalar.primitive().is_float(),
|
||||
Abi::Aggregate { .. } => {
|
||||
if self.fields.count() == 1 && self.fields.offset(0).bytes() == 0 {
|
||||
self.field(cx, 0).is_single_fp_element(cx)
|
||||
@ -1371,7 +1431,7 @@ pub fn might_permit_raw_init<C>(self, cx: &C, zero: bool) -> bool
|
||||
let scalar_allows_raw_init = move |s: Scalar| -> bool {
|
||||
if zero {
|
||||
// The range must contain 0.
|
||||
s.valid_range.contains(0)
|
||||
s.valid_range(cx).contains(0)
|
||||
} else {
|
||||
// The range must include all values.
|
||||
s.is_always_valid(cx)
|
||||
|
@ -1769,7 +1769,7 @@ fn write_size_of_layout(w: &mut Buffer, layout: Layout<'_>, tag_size: u64) {
|
||||
|
||||
let tag_size = if let TagEncoding::Niche { .. } = tag_encoding {
|
||||
0
|
||||
} else if let Primitive::Int(i, _) = tag.value {
|
||||
} else if let Primitive::Int(i, _) = tag.primitive() {
|
||||
i.size().bytes()
|
||||
} else {
|
||||
span_bug!(tcx.def_span(ty_def_id), "tag is neither niche nor int")
|
||||
|
@ -10,7 +10,7 @@ error: layout_of(E) = Layout {
|
||||
],
|
||||
},
|
||||
variants: Multiple {
|
||||
tag: Scalar {
|
||||
tag: Initialized {
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
@ -86,13 +86,11 @@ error: layout_of(E) = Layout {
|
||||
offset: Size {
|
||||
raw: 0,
|
||||
},
|
||||
scalar: Scalar {
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
),
|
||||
valid_range: 0..=0,
|
||||
},
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
),
|
||||
valid_range: 0..=0,
|
||||
},
|
||||
),
|
||||
align: AbiAndPrefAlign {
|
||||
@ -133,14 +131,14 @@ error: layout_of(S) = Layout {
|
||||
index: 0,
|
||||
},
|
||||
abi: ScalarPair(
|
||||
Scalar {
|
||||
Initialized {
|
||||
value: Int(
|
||||
I32,
|
||||
true,
|
||||
),
|
||||
valid_range: 0..=4294967295,
|
||||
},
|
||||
Scalar {
|
||||
Initialized {
|
||||
value: Int(
|
||||
I32,
|
||||
true,
|
||||
@ -202,7 +200,7 @@ error: layout_of(std::result::Result<i32, i32>) = Layout {
|
||||
],
|
||||
},
|
||||
variants: Multiple {
|
||||
tag: Scalar {
|
||||
tag: Initialized {
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
@ -271,14 +269,14 @@ error: layout_of(std::result::Result<i32, i32>) = Layout {
|
||||
],
|
||||
},
|
||||
abi: ScalarPair(
|
||||
Scalar {
|
||||
Initialized {
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
),
|
||||
valid_range: 0..=1,
|
||||
},
|
||||
Scalar {
|
||||
Initialized {
|
||||
value: Int(
|
||||
I32,
|
||||
true,
|
||||
@ -291,13 +289,11 @@ error: layout_of(std::result::Result<i32, i32>) = Layout {
|
||||
offset: Size {
|
||||
raw: 0,
|
||||
},
|
||||
scalar: Scalar {
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
),
|
||||
valid_range: 0..=1,
|
||||
},
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
),
|
||||
valid_range: 0..=1,
|
||||
},
|
||||
),
|
||||
align: AbiAndPrefAlign {
|
||||
@ -321,7 +317,7 @@ error: layout_of(i32) = Layout {
|
||||
index: 0,
|
||||
},
|
||||
abi: Scalar(
|
||||
Scalar {
|
||||
Initialized {
|
||||
value: Int(
|
||||
I32,
|
||||
true,
|
||||
|
@ -10,7 +10,7 @@ error: layout_of(A) = Layout {
|
||||
],
|
||||
},
|
||||
variants: Multiple {
|
||||
tag: Scalar {
|
||||
tag: Initialized {
|
||||
value: Int(
|
||||
I8,
|
||||
false,
|
||||
@ -47,7 +47,7 @@ error: layout_of(A) = Layout {
|
||||
],
|
||||
},
|
||||
abi: Scalar(
|
||||
Scalar {
|
||||
Initialized {
|
||||
value: Int(
|
||||
I8,
|
||||
false,
|
||||
@ -60,13 +60,11 @@ error: layout_of(A) = Layout {
|
||||
offset: Size {
|
||||
raw: 0,
|
||||
},
|
||||
scalar: Scalar {
|
||||
value: Int(
|
||||
I8,
|
||||
false,
|
||||
),
|
||||
valid_range: 0..=0,
|
||||
},
|
||||
value: Int(
|
||||
I8,
|
||||
false,
|
||||
),
|
||||
valid_range: 0..=0,
|
||||
},
|
||||
),
|
||||
align: AbiAndPrefAlign {
|
||||
@ -98,7 +96,7 @@ error: layout_of(B) = Layout {
|
||||
],
|
||||
},
|
||||
variants: Multiple {
|
||||
tag: Scalar {
|
||||
tag: Initialized {
|
||||
value: Int(
|
||||
I8,
|
||||
false,
|
||||
@ -135,7 +133,7 @@ error: layout_of(B) = Layout {
|
||||
],
|
||||
},
|
||||
abi: Scalar(
|
||||
Scalar {
|
||||
Initialized {
|
||||
value: Int(
|
||||
I8,
|
||||
false,
|
||||
@ -148,13 +146,11 @@ error: layout_of(B) = Layout {
|
||||
offset: Size {
|
||||
raw: 0,
|
||||
},
|
||||
scalar: Scalar {
|
||||
value: Int(
|
||||
I8,
|
||||
false,
|
||||
),
|
||||
valid_range: 255..=255,
|
||||
},
|
||||
value: Int(
|
||||
I8,
|
||||
false,
|
||||
),
|
||||
valid_range: 255..=255,
|
||||
},
|
||||
),
|
||||
align: AbiAndPrefAlign {
|
||||
@ -186,7 +182,7 @@ error: layout_of(C) = Layout {
|
||||
],
|
||||
},
|
||||
variants: Multiple {
|
||||
tag: Scalar {
|
||||
tag: Initialized {
|
||||
value: Int(
|
||||
I16,
|
||||
false,
|
||||
@ -223,7 +219,7 @@ error: layout_of(C) = Layout {
|
||||
],
|
||||
},
|
||||
abi: Scalar(
|
||||
Scalar {
|
||||
Initialized {
|
||||
value: Int(
|
||||
I16,
|
||||
false,
|
||||
@ -236,13 +232,11 @@ error: layout_of(C) = Layout {
|
||||
offset: Size {
|
||||
raw: 0,
|
||||
},
|
||||
scalar: Scalar {
|
||||
value: Int(
|
||||
I16,
|
||||
false,
|
||||
),
|
||||
valid_range: 256..=256,
|
||||
},
|
||||
value: Int(
|
||||
I16,
|
||||
false,
|
||||
),
|
||||
valid_range: 256..=256,
|
||||
},
|
||||
),
|
||||
align: AbiAndPrefAlign {
|
||||
@ -274,7 +268,7 @@ error: layout_of(P) = Layout {
|
||||
],
|
||||
},
|
||||
variants: Multiple {
|
||||
tag: Scalar {
|
||||
tag: Initialized {
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
@ -311,7 +305,7 @@ error: layout_of(P) = Layout {
|
||||
],
|
||||
},
|
||||
abi: Scalar(
|
||||
Scalar {
|
||||
Initialized {
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
@ -324,13 +318,11 @@ error: layout_of(P) = Layout {
|
||||
offset: Size {
|
||||
raw: 0,
|
||||
},
|
||||
scalar: Scalar {
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
),
|
||||
valid_range: 268435456..=268435456,
|
||||
},
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
),
|
||||
valid_range: 268435456..=268435456,
|
||||
},
|
||||
),
|
||||
align: AbiAndPrefAlign {
|
||||
@ -362,7 +354,7 @@ error: layout_of(T) = Layout {
|
||||
],
|
||||
},
|
||||
variants: Multiple {
|
||||
tag: Scalar {
|
||||
tag: Initialized {
|
||||
value: Int(
|
||||
I32,
|
||||
true,
|
||||
@ -399,7 +391,7 @@ error: layout_of(T) = Layout {
|
||||
],
|
||||
},
|
||||
abi: Scalar(
|
||||
Scalar {
|
||||
Initialized {
|
||||
value: Int(
|
||||
I32,
|
||||
true,
|
||||
@ -412,13 +404,11 @@ error: layout_of(T) = Layout {
|
||||
offset: Size {
|
||||
raw: 0,
|
||||
},
|
||||
scalar: Scalar {
|
||||
value: Int(
|
||||
I32,
|
||||
true,
|
||||
),
|
||||
valid_range: 2164260864..=2164260864,
|
||||
},
|
||||
value: Int(
|
||||
I32,
|
||||
true,
|
||||
),
|
||||
valid_range: 2164260864..=2164260864,
|
||||
},
|
||||
),
|
||||
align: AbiAndPrefAlign {
|
||||
|
@ -10,7 +10,7 @@ error: layout_of(A) = Layout {
|
||||
],
|
||||
},
|
||||
variants: Multiple {
|
||||
tag: Scalar {
|
||||
tag: Initialized {
|
||||
value: Int(
|
||||
I8,
|
||||
false,
|
||||
@ -47,7 +47,7 @@ error: layout_of(A) = Layout {
|
||||
],
|
||||
},
|
||||
abi: Scalar(
|
||||
Scalar {
|
||||
Initialized {
|
||||
value: Int(
|
||||
I8,
|
||||
false,
|
||||
@ -60,13 +60,11 @@ error: layout_of(A) = Layout {
|
||||
offset: Size {
|
||||
raw: 0,
|
||||
},
|
||||
scalar: Scalar {
|
||||
value: Int(
|
||||
I8,
|
||||
false,
|
||||
),
|
||||
valid_range: 0..=0,
|
||||
},
|
||||
value: Int(
|
||||
I8,
|
||||
false,
|
||||
),
|
||||
valid_range: 0..=0,
|
||||
},
|
||||
),
|
||||
align: AbiAndPrefAlign {
|
||||
@ -98,7 +96,7 @@ error: layout_of(B) = Layout {
|
||||
],
|
||||
},
|
||||
variants: Multiple {
|
||||
tag: Scalar {
|
||||
tag: Initialized {
|
||||
value: Int(
|
||||
I8,
|
||||
false,
|
||||
@ -135,7 +133,7 @@ error: layout_of(B) = Layout {
|
||||
],
|
||||
},
|
||||
abi: Scalar(
|
||||
Scalar {
|
||||
Initialized {
|
||||
value: Int(
|
||||
I8,
|
||||
false,
|
||||
@ -148,13 +146,11 @@ error: layout_of(B) = Layout {
|
||||
offset: Size {
|
||||
raw: 0,
|
||||
},
|
||||
scalar: Scalar {
|
||||
value: Int(
|
||||
I8,
|
||||
false,
|
||||
),
|
||||
valid_range: 255..=255,
|
||||
},
|
||||
value: Int(
|
||||
I8,
|
||||
false,
|
||||
),
|
||||
valid_range: 255..=255,
|
||||
},
|
||||
),
|
||||
align: AbiAndPrefAlign {
|
||||
@ -186,7 +182,7 @@ error: layout_of(C) = Layout {
|
||||
],
|
||||
},
|
||||
variants: Multiple {
|
||||
tag: Scalar {
|
||||
tag: Initialized {
|
||||
value: Int(
|
||||
I16,
|
||||
false,
|
||||
@ -223,7 +219,7 @@ error: layout_of(C) = Layout {
|
||||
],
|
||||
},
|
||||
abi: Scalar(
|
||||
Scalar {
|
||||
Initialized {
|
||||
value: Int(
|
||||
I16,
|
||||
false,
|
||||
@ -236,13 +232,11 @@ error: layout_of(C) = Layout {
|
||||
offset: Size {
|
||||
raw: 0,
|
||||
},
|
||||
scalar: Scalar {
|
||||
value: Int(
|
||||
I16,
|
||||
false,
|
||||
),
|
||||
valid_range: 256..=256,
|
||||
},
|
||||
value: Int(
|
||||
I16,
|
||||
false,
|
||||
),
|
||||
valid_range: 256..=256,
|
||||
},
|
||||
),
|
||||
align: AbiAndPrefAlign {
|
||||
@ -274,7 +268,7 @@ error: layout_of(P) = Layout {
|
||||
],
|
||||
},
|
||||
variants: Multiple {
|
||||
tag: Scalar {
|
||||
tag: Initialized {
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
@ -311,7 +305,7 @@ error: layout_of(P) = Layout {
|
||||
],
|
||||
},
|
||||
abi: Scalar(
|
||||
Scalar {
|
||||
Initialized {
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
@ -324,13 +318,11 @@ error: layout_of(P) = Layout {
|
||||
offset: Size {
|
||||
raw: 0,
|
||||
},
|
||||
scalar: Scalar {
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
),
|
||||
valid_range: 268435456..=268435456,
|
||||
},
|
||||
value: Int(
|
||||
I32,
|
||||
false,
|
||||
),
|
||||
valid_range: 268435456..=268435456,
|
||||
},
|
||||
),
|
||||
align: AbiAndPrefAlign {
|
||||
@ -362,7 +354,7 @@ error: layout_of(T) = Layout {
|
||||
],
|
||||
},
|
||||
variants: Multiple {
|
||||
tag: Scalar {
|
||||
tag: Initialized {
|
||||
value: Int(
|
||||
I32,
|
||||
true,
|
||||
@ -399,7 +391,7 @@ error: layout_of(T) = Layout {
|
||||
],
|
||||
},
|
||||
abi: Scalar(
|
||||
Scalar {
|
||||
Initialized {
|
||||
value: Int(
|
||||
I32,
|
||||
true,
|
||||
@ -412,13 +404,11 @@ error: layout_of(T) = Layout {
|
||||
offset: Size {
|
||||
raw: 0,
|
||||
},
|
||||
scalar: Scalar {
|
||||
value: Int(
|
||||
I32,
|
||||
true,
|
||||
),
|
||||
valid_range: 2164260864..=2164260864,
|
||||
},
|
||||
value: Int(
|
||||
I32,
|
||||
true,
|
||||
),
|
||||
valid_range: 2164260864..=2164260864,
|
||||
},
|
||||
),
|
||||
align: AbiAndPrefAlign {
|
||||
|
Loading…
Reference in New Issue
Block a user