fix transmutes between pointers in different address spaces
This commit is contained in:
parent
c6fcdb6906
commit
6085d33033
@ -1810,15 +1810,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
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.primitive() == abi::Pointer)
|
||||
== (dst_scalar.primitive() == abi::Pointer)
|
||||
{
|
||||
let src_is_ptr = src_scalar.primitive() == abi::Pointer;
|
||||
let dst_is_ptr = dst_scalar.primitive() == abi::Pointer;
|
||||
if src_is_ptr == dst_is_ptr {
|
||||
assert_eq!(src.layout.size, dst.layout.size);
|
||||
|
||||
// NOTE(eddyb) the `from_immediate` and `to_immediate_scalar`
|
||||
// conversions allow handling `bool`s the same as `u8`s.
|
||||
let src = bx.from_immediate(src.immediate());
|
||||
let src_as_dst = bx.bitcast(src, bx.backend_type(dst.layout));
|
||||
// LLVM also doesn't like `bitcast`s between pointers in different address spaces.
|
||||
let src_as_dst = if src_is_ptr {
|
||||
bx.pointercast(src, bx.backend_type(dst.layout))
|
||||
} else {
|
||||
bx.bitcast(src, bx.backend_type(dst.layout))
|
||||
};
|
||||
Immediate(bx.to_immediate_scalar(src_as_dst, dst_scalar)).store(bx, dst);
|
||||
return;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
// It also validates that functions can be called through function pointers
|
||||
// through traits.
|
||||
|
||||
#![feature(no_core, lang_items, unboxed_closures, arbitrary_self_types)]
|
||||
#![feature(no_core, lang_items, intrinsics, unboxed_closures, arbitrary_self_types)]
|
||||
#![crate_type = "lib"]
|
||||
#![no_core]
|
||||
|
||||
@ -49,6 +49,10 @@ pub trait Fn<Args: Tuple>: FnOnce<Args> {
|
||||
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
|
||||
}
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
pub fn transmute<Src, Dst>(src: Src) -> Dst;
|
||||
}
|
||||
|
||||
pub static mut STORAGE_FOO: fn(&usize, &mut u32) -> Result<(), ()> = arbitrary_black_box;
|
||||
pub static mut STORAGE_BAR: u32 = 12;
|
||||
|
||||
@ -87,3 +91,21 @@ pub extern "C" fn test() {
|
||||
STORAGE_FOO(&1, &mut buf);
|
||||
}
|
||||
}
|
||||
|
||||
// Validate that we can codegen transmutes between data ptrs and fn ptrs.
|
||||
|
||||
// CHECK: define{{.+}}{{void \(\) addrspace\(1\)\*|ptr addrspace\(1\)}} @transmute_data_ptr_to_fn({{\{\}\*|ptr}}{{.*}} %x)
|
||||
#[no_mangle]
|
||||
pub unsafe fn transmute_data_ptr_to_fn(x: *const ()) -> fn() {
|
||||
// It doesn't matter precisely how this is codegenned (through memory or an addrspacecast),
|
||||
// as long as it doesn't cause a verifier error by using `bitcast`.
|
||||
transmute(x)
|
||||
}
|
||||
|
||||
// CHECK: define{{.+}}{{\{\}\*|ptr}} @transmute_fn_ptr_to_data({{void \(\) addrspace\(1\)\*|ptr addrspace\(1\)}}{{.*}} %x)
|
||||
#[no_mangle]
|
||||
pub unsafe fn transmute_fn_ptr_to_data(x: fn()) -> *const () {
|
||||
// It doesn't matter precisely how this is codegenned (through memory or an addrspacecast),
|
||||
// as long as it doesn't cause a verifier error by using `bitcast`.
|
||||
transmute(x)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user