assert_eq!(offset as usize as u64, offset);
let offset = offset as usize;
if offset > next_offset {
- llvals.push(cx.const_bytes(&alloc.bytes[next_offset..offset]));
+ // This `inspect` is okay since we have check that it is not within a relocation, it is
+ // within the bounds of the allocation, and it doesn't affect interpreter execution (we
+ // inspect the result after interpreter execution). Any undef byte is replaced with
+ // some arbitrary byte value.
+ //
+ // FIXME: relay undef bytes to codegen as undef const bytes
+ let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter(next_offset..offset);
+ llvals.push(cx.const_bytes(bytes));
}
let ptr_offset = read_target_uint(
dl.endian,
- &alloc.bytes[offset..(offset + 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_undef_and_ptr_outside_interpreter(offset..(offset + pointer_size)),
).expect("const_alloc_to_llvm: could not read relocation pointer") as u64;
llvals.push(cx.scalar_to_backend(
Pointer::new(alloc_id, Size::from_bytes(ptr_offset)).into(),
));
next_offset = offset + pointer_size;
}
- if alloc.bytes.len() >= next_offset {
- llvals.push(cx.const_bytes(&alloc.bytes[next_offset ..]));
+ if alloc.len() >= next_offset {
+ let range = next_offset..alloc.len();
+ // This `inspect` is okay since we have check that it is after all relocations, it is
+ // within the bounds of the allocation, and it doesn't affect interpreter execution (we
+ // inspect the result after interpreter execution). Any undef byte is replaced with some
+ // arbitrary byte value.
+ //
+ // FIXME: relay undef bytes to codegen as undef const bytes
+ let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter(range);
+ llvals.push(cx.const_bytes(bytes));
}
cx.const_struct(&llvals, true)
//
// We could remove this hack whenever we decide to drop macOS 10.10 support.
if self.tcx.sess.target.target.options.is_like_osx {
- let sect_name = if alloc.bytes.iter().all(|b| *b == 0) {
+ assert_eq!(alloc.relocations.len(), 0);
+
+ let is_zeroed = {
+ // Treats undefined bytes as if they were defined with the byte value that
+ // happens to be currently assigned in mir. This is valid since reading
+ // undef bytes may yield arbitrary values.
+ //
+ // FIXME: ignore undef bytes even with representation `!= 0`.
+ //
+ // The `inspect` method is okay here because we checked relocations, and
+ // because we are doing this access to inspect the final interpreter state
+ // (not as part of the interpreter execution).
+ alloc.inspect_with_undef_and_ptr_outside_interpreter(0..alloc.len())
+ .iter()
+ .all(|b| *b == 0)
+ };
+ let sect_name = if is_zeroed {
CStr::from_bytes_with_nul_unchecked(b"__DATA,__thread_bss\0")
} else {
CStr::from_bytes_with_nul_unchecked(b"__DATA,__thread_data\0")
section.as_str().as_ptr() as *const _,
section.as_str().len() as c_uint,
);
+ assert!(alloc.relocations.is_empty());
+
+ // The `inspect` method is okay here because we checked relocations, and
+ // because we are doing this access to inspect the final interpreter state (not
+ // as part of the interpreter execution).
+ let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter(
+ 0..alloc.len());
let alloc = llvm::LLVMMDStringInContext(
self.llcx,
- alloc.bytes.as_ptr() as *const _,
- alloc.bytes.len() as c_uint,
+ bytes.as_ptr() as *const _,
+ bytes.len() as c_uint,
);
let data = [section, alloc];
let meta = llvm::LLVMMDNodeInContext(self.llcx, data.as_ptr(), 2);