diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index fcd41c844659d..1a2a6ea2fe6c0 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_errors::ErrorReported; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::interpret::{ - read_target_uint, AllocId, Allocation, ConstValue, ErrorHandled, GlobalAlloc, Pointer, Scalar, + read_target_ptr, AllocId, Allocation, ConstValue, ErrorHandled, GlobalAlloc, Pointer, Scalar, }; use rustc_middle::ty::ConstKind; @@ -379,11 +379,11 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant let addend = { let endianness = tcx.data_layout.endian; let offset = offset.bytes() as usize; - let ptr_size = tcx.data_layout.pointer_size; + let ptr_size = tcx.data_layout.pointer_size.bytes() as usize; let bytes = &alloc.inspect_with_uninit_and_ptr_outside_interpreter( - offset..offset + ptr_size.bytes() as usize, + offset..offset + ptr_size ); - read_target_uint(endianness, bytes).unwrap() + read_target_ptr(endianness, ptr_size, bytes) }; let reloc_target_alloc = tcx.get_global_alloc(reloc).unwrap(); diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index 27fc2abedc7e9..459d775e7a17b 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -83,6 +83,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( let indexes = { use rustc_middle::mir::interpret::*; + use rustc_target::abi::Endian; + let idx_const = crate::constant::mir_operand_get_const_val(fx, idx).expect("simd_shuffle* idx not const"); let idx_bytes = match idx_const { @@ -96,10 +98,11 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( (0..ret_lane_count).map(|i| { let i = usize::try_from(i).unwrap(); - let idx = rustc_middle::mir::interpret::read_target_uint( - fx.tcx.data_layout.endian, - &idx_bytes[4*i.. 4*i + 4], - ).expect("read_target_uint"); + let idx = match (fx.tcx.data_layout.endian, &idx_bytes[4*i.. 4*i + 4]) { + (Endian::Little, &[a, b, c, d]) => u32::from_le_bytes([a, b, c, d]), + (Endian::Big, &[a, b, c, d]) => u32::from_be_bytes([a, b, c, d]), + (_, _) => unreachable!(), + }; u16::try_from(idx).expect("try_from u32") }).collect::>() }; diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 99046839973d5..0ccaab2762bf0 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -11,7 +11,7 @@ use rustc_codegen_ssa::traits::*; use rustc_hir::def_id::DefId; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::mir::interpret::{ - read_target_uint, Allocation, ErrorHandled, GlobalAlloc, Pointer, + read_target_ptr, Allocation, ErrorHandled, GlobalAlloc, Pointer, }; use rustc_middle::mir::mono::MonoItem; use rustc_middle::ty::{self, Instance, Ty}; @@ -22,6 +22,7 @@ use tracing::debug; pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll Value { let mut llvals = Vec::with_capacity(alloc.relocations().len() + 1); let dl = cx.data_layout(); + let endian = dl.endian; let pointer_size = dl.pointer_size.bytes() as usize; let mut next_offset = 0; @@ -39,16 +40,15 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(next_offset..offset); llvals.push(cx.const_bytes(bytes)); } - let ptr_offset = read_target_uint( - dl.endian, + + let ptr_offset = read_target_ptr( + endian, + pointer_size, // This `inspect` is okay since it is within the bounds of the allocation, it doesn't // affect interpreter execution (we inspect the result after interpreter execution), // and we properly interpret the relocation as a relocation pointer offset. alloc.inspect_with_uninit_and_ptr_outside_interpreter(offset..(offset + pointer_size)), - ) - .expect("const_alloc_to_llvm: could not read relocation pointer") - as u64; - + ); let address_space = match cx.tcx.global_alloc(alloc_id) { GlobalAlloc::Function(..) => cx.data_layout().instruction_address_space, GlobalAlloc::Static(..) | GlobalAlloc::Memory(..) => AddressSpace::DATA, diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 55fe5f971e718..69baf889c212f 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -555,12 +555,12 @@ impl<'tcx> TyCtxt<'tcx> { //////////////////////////////////////////////////////////////////////////////// #[inline] -pub fn write_target_uint( +fn write_target_uint( endianness: Endian, mut target: &mut [u8], data: u128, ) -> Result<(), io::Error> { - // This u128 holds an "any-size uint" (since smaller uints can fits in it) + // This u128 holds an "any-size uint" (since smaller uints can fit in it) // So we do not write all bytes of the u128, just the "payload". match endianness { Endian::Little => target.write(&data.to_le_bytes())?, @@ -571,7 +571,7 @@ pub fn write_target_uint( } #[inline] -pub fn read_target_uint(endianness: Endian, mut source: &[u8]) -> Result { +fn read_target_uint(endianness: Endian, mut source: &[u8]) -> Result { // This u128 holds an "any-size uint" (since smaller uints can fits in it) let mut buf = [0u8; std::mem::size_of::()]; // So we do not read exactly 16 bytes into the u128, just the "payload". @@ -588,3 +588,20 @@ pub fn read_target_uint(endianness: Endian, mut source: &[u8]) -> Result u64 { + use core::convert::TryInto; + match (ptr_size, endian) { + (2, Endian::Little) => u16::from_le_bytes(bytes.try_into().unwrap()) as u64, + (2, Endian::Big) => u16::from_be_bytes(bytes.try_into().unwrap()) as u64, + (4, Endian::Little) => u32::from_le_bytes(bytes.try_into().unwrap()) as u64, + (4, Endian::Big) => u32::from_be_bytes(bytes.try_into().unwrap()) as u64, + (8, Endian::Little) => u64::from_le_bytes(bytes.try_into().unwrap()), + (8, Endian::Big) => u64::from_be_bytes(bytes.try_into().unwrap()), + (_, _) => panic!("unknown pointer size and endianness combination"), + } +} diff --git a/compiler/rustc_mir/src/util/pretty.rs b/compiler/rustc_mir/src/util/pretty.rs index 3b88aec16b26a..9141360a7309b 100644 --- a/compiler/rustc_mir/src/util/pretty.rs +++ b/compiler/rustc_mir/src/util/pretty.rs @@ -13,7 +13,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_index::vec::Idx; use rustc_middle::mir::interpret::{ - read_target_uint, AllocId, Allocation, ConstValue, GlobalAlloc, Pointer, + read_target_ptr, AllocId, Allocation, ConstValue, GlobalAlloc, Pointer, }; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; @@ -833,6 +833,7 @@ fn write_allocation_bytes( let mut line_start = Size::ZERO; let ptr_size = tcx.data_layout.pointer_size; + let ptr_bytesize = ptr_size.bytes_usize(); let mut ascii = String::new(); @@ -852,9 +853,8 @@ fn write_allocation_bytes( if let Some(&(tag, target_id)) = alloc.relocations().get(&i) { // Memory with a relocation must be defined let j = i.bytes_usize(); - let offset = alloc - .inspect_with_uninit_and_ptr_outside_interpreter(j..j + ptr_size.bytes_usize()); - let offset = read_target_uint(tcx.data_layout.endian, offset).unwrap(); + let offset = alloc.inspect_with_uninit_and_ptr_outside_interpreter(j..j + ptr_bytesize); + let offset = read_target_ptr(tcx.data_layout.endian, ptr_bytesize, offset); let offset = Size::from_bytes(offset); let relocation_width = |bytes| bytes * 3; let ptr = Pointer::new_with_tag(target_id, offset, tag);