Skip to content

Commit dfd5add

Browse files
committed
Cast allocas to default address space
Pointers for variables all need to be in the same address space for correct compilation. Therefore ensure that even if an `alloca` is created in a different address space, it is casted to the default address space before its value is used. This is necessary for the amdgpu target and others where the default address space for `alloca`s is not 0. For example the following code compiles incorrectly when not casting the address space to the default one: ```rust fn f(p: *const i8 /* addrspace(0) */) -> *const i8 /* addrspace(0) */ { let local = 0i8; /* addrspace(5) */ let res = if cond { p } else { &raw const local }; res } ``` results in ```llvm %local = alloca addrspace(5) i8 %res = alloca addrspace(5) ptr if: ; Store 64-bit flat pointer store ptr %p, ptr addrspace(5) %res else: ; Store 32-bit scratch pointer store ptr addrspace(5) %local, ptr addrspace(5) %res ret: ; Load and return 64-bit flat pointer %res.load = load ptr, ptr addrspace(5) %res ret ptr %res.load ``` For amdgpu, `addrspace(0)` are 64-bit pointers, `addrspace(5)` are 32-bit pointers. The above code may store a 32-bit pointer and read it back as a 64-bit pointer, which is obviously wrong and cannot work. Instead, we need to `addrspacecast %local to ptr addrspace(0)`, then we store and load the correct type.
1 parent bf6f8a4 commit dfd5add

File tree

2 files changed

+26
-2
lines changed

2 files changed

+26
-2
lines changed

compiler/rustc_codegen_llvm/src/builder.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,8 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
421421
unsafe {
422422
let alloca = llvm::LLVMBuildAlloca(bx.llbuilder, ty, UNNAMED);
423423
llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint);
424-
alloca
424+
// Cast to default addrspace if necessary
425+
llvm::LLVMBuildPointerCast(bx.llbuilder, alloca, self.cx().type_ptr(), UNNAMED)
425426
}
426427
}
427428

@@ -430,7 +431,8 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
430431
let alloca =
431432
llvm::LLVMBuildArrayAlloca(self.llbuilder, self.cx().type_i8(), size, UNNAMED);
432433
llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint);
433-
alloca
434+
// Cast to default addrspace if necessary
435+
llvm::LLVMBuildPointerCast(self.llbuilder, alloca, self.cx().type_ptr(), UNNAMED)
434436
}
435437
}
436438

tests/codegen/amdgpu-addrspacecast.rs

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Check that pointers are casted to addrspace(0) before they are used
2+
3+
//@ compile-flags: --crate-type=rlib --target=amdgcn-amd-amdhsa -Ctarget-cpu=gfx900
4+
//@ needs-llvm-components: amdgpu
5+
#![feature(no_core, lang_items)]
6+
#![no_core]
7+
8+
#[lang = "sized"]
9+
trait Sized {}
10+
#[lang = "freeze"]
11+
trait Freeze {}
12+
#[lang = "copy"]
13+
trait Copy {}
14+
15+
// CHECK-LABEL: @ref_of_local
16+
// CHECK: [[alloca:%[0-9]]] = alloca
17+
// CHECK: %i = addrspacecast ptr addrspace(5) [[alloca]] to ptr
18+
#[no_mangle]
19+
pub fn ref_of_local(f: fn(&i32)) {
20+
let i = 0;
21+
f(&i);
22+
}

0 commit comments

Comments
 (0)