Fix codegen with explicit allocation byte access
This commit is contained in:
parent
7b941e368f
commit
df58fcffbc
1 changed files with 48 additions and 7 deletions
|
@ -35,11 +35,21 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll
|
||||||
assert_eq!(offset as usize as u64, offset);
|
assert_eq!(offset as usize as u64, offset);
|
||||||
let offset = offset as usize;
|
let offset = offset as usize;
|
||||||
if offset > next_offset {
|
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(
|
let ptr_offset = read_target_uint(
|
||||||
dl.endian,
|
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;
|
).expect("const_alloc_to_llvm: could not read relocation pointer") as u64;
|
||||||
llvals.push(cx.scalar_to_backend(
|
llvals.push(cx.scalar_to_backend(
|
||||||
Pointer::new(alloc_id, Size::from_bytes(ptr_offset)).into(),
|
Pointer::new(alloc_id, Size::from_bytes(ptr_offset)).into(),
|
||||||
|
@ -51,8 +61,16 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll
|
||||||
));
|
));
|
||||||
next_offset = offset + pointer_size;
|
next_offset = offset + pointer_size;
|
||||||
}
|
}
|
||||||
if alloc.bytes.len() >= next_offset {
|
if alloc.len() >= next_offset {
|
||||||
llvals.push(cx.const_bytes(&alloc.bytes[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)
|
cx.const_struct(&llvals, true)
|
||||||
|
@ -437,7 +455,23 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> {
|
||||||
//
|
//
|
||||||
// We could remove this hack whenever we decide to drop macOS 10.10 support.
|
// We could remove this hack whenever we decide to drop macOS 10.10 support.
|
||||||
if self.tcx.sess.target.target.options.is_like_osx {
|
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")
|
CStr::from_bytes_with_nul_unchecked(b"__DATA,__thread_bss\0")
|
||||||
} else {
|
} else {
|
||||||
CStr::from_bytes_with_nul_unchecked(b"__DATA,__thread_data\0")
|
CStr::from_bytes_with_nul_unchecked(b"__DATA,__thread_data\0")
|
||||||
|
@ -456,10 +490,17 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> {
|
||||||
section.as_str().as_ptr() as *const _,
|
section.as_str().as_ptr() as *const _,
|
||||||
section.as_str().len() as c_uint,
|
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(
|
let alloc = llvm::LLVMMDStringInContext(
|
||||||
self.llcx,
|
self.llcx,
|
||||||
alloc.bytes.as_ptr() as *const _,
|
bytes.as_ptr() as *const _,
|
||||||
alloc.bytes.len() as c_uint,
|
bytes.len() as c_uint,
|
||||||
);
|
);
|
||||||
let data = [section, alloc];
|
let data = [section, alloc];
|
||||||
let meta = llvm::LLVMMDNodeInContext(self.llcx, data.as_ptr(), 2);
|
let meta = llvm::LLVMMDNodeInContext(self.llcx, data.as_ptr(), 2);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue