Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 026563a

Browse files
committedFeb 13, 2025
[wip] Add intrinsic for shared memory
TODO - Docs for the intrinsic - Allow only for amdgpu and nvptx - Re-use the same global in a module - Add tests
1 parent 4fad2e7 commit 026563a

File tree

8 files changed

+89
-6
lines changed

8 files changed

+89
-6
lines changed
 

‎compiler/rustc_abi/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1394,6 +1394,8 @@ pub struct AddressSpace(pub u32);
13941394
impl AddressSpace {
13951395
/// The default address space, corresponding to data space.
13961396
pub const DATA: Self = AddressSpace(0);
1397+
/// The address space for shared memory on nvptx and amdgpu.
1398+
pub const SHARED: Self = AddressSpace(3);
13971399
}
13981400

13991401
/// The way we represent values to the backend

‎compiler/rustc_codegen_llvm/src/declare.rs

+23
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
//! * When in doubt, define.
1313
1414
use itertools::Itertools;
15+
use rustc_abi::AddressSpace;
1516
use rustc_codegen_ssa::traits::TypeMembershipCodegenMethods;
1617
use rustc_data_structures::fx::FxIndexSet;
1718
use rustc_middle::ty::{Instance, Ty};
@@ -90,6 +91,28 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
9091
unsafe { llvm::LLVMRustGetOrInsertGlobal(self.llmod, name.as_c_char_ptr(), name.len(), ty) }
9192
}
9293

94+
/// Declare a global value in a specific address space.
95+
///
96+
/// If there’s a value with the same name already declared, the function will
97+
/// return its Value instead.
98+
pub(crate) fn declare_global_in_addrspace(
99+
&self,
100+
name: &str,
101+
ty: &'ll Type,
102+
addr_space: AddressSpace,
103+
) -> &'ll Value {
104+
debug!("declare_global(name={name:?}, addrspace={addr_space:?})");
105+
unsafe {
106+
llvm::LLVMRustGetOrInsertGlobalInAddrspace(
107+
self.llmod,
108+
name.as_c_char_ptr(),
109+
name.len(),
110+
ty,
111+
addr_space.0,
112+
)
113+
}
114+
}
115+
93116
/// Declare a C ABI function.
94117
///
95118
/// Only use this for foreign function ABIs and glue. For Rust functions use

‎compiler/rustc_codegen_llvm/src/intrinsic.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::assert_matches::assert_matches;
22
use std::cmp::Ordering;
33

4-
use rustc_abi::{self as abi, Align, Float, HasDataLayout, Primitive, Size};
4+
use rustc_abi::{self as abi, AddressSpace, Align, Float, HasDataLayout, Primitive, Size};
55
use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh, wants_wasm_eh};
66
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
77
use rustc_codegen_ssa::errors::{ExpectedPointerMutability, InvalidMonomorphization};
@@ -551,6 +551,25 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
551551
return Ok(());
552552
}
553553

554+
sym::dynamic_shared_memory => {
555+
// TODO Allow only on nvptx and amdgpu
556+
// TODO create only one global per module, take the maximum alignment of all calls
557+
let global = self.declare_global_in_addrspace(
558+
"",
559+
self.type_array(self.type_i8(), 0),
560+
AddressSpace::SHARED,
561+
);
562+
// TODO Set alignment
563+
let ty::RawPtr(inner_ty, _) = ret_ty.kind() else { unreachable!() };
564+
let alignment = self.align_of(*inner_ty).bytes() as u32;
565+
unsafe {
566+
if alignment > llvm::LLVMGetAlignment(global) {
567+
llvm::LLVMSetAlignment(global, alignment);
568+
}
569+
}
570+
self.cx().const_pointercast(global, self.type_ptr())
571+
}
572+
554573
_ if name.as_str().starts_with("simd_") => {
555574
// Unpack non-power-of-2 #[repr(packed, simd)] arguments.
556575
// This gives them the expected layout of a regular #[repr(simd)] vector.

‎compiler/rustc_codegen_llvm/src/llvm/ffi.rs

+7
Original file line numberDiff line numberDiff line change
@@ -1777,6 +1777,13 @@ unsafe extern "C" {
17771777
NameLen: size_t,
17781778
T: &'a Type,
17791779
) -> &'a Value;
1780+
pub fn LLVMRustGetOrInsertGlobalInAddrspace<'a>(
1781+
M: &'a Module,
1782+
Name: *const c_char,
1783+
NameLen: size_t,
1784+
T: &'a Type,
1785+
AddressSpace: c_uint,
1786+
) -> &'a Value;
17801787
pub fn LLVMRustInsertPrivateGlobal<'a>(M: &'a Module, T: &'a Type) -> &'a Value;
17811788
pub fn LLVMRustGetNamedValue(
17821789
M: &Module,

‎compiler/rustc_hir_analysis/src/check/intrinsic.rs

+2
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -
9292
| sym::min_align_of
9393
| sym::needs_drop
9494
| sym::caller_location
95+
| sym::dynamic_shared_memory
9596
| sym::add_with_overflow
9697
| sym::sub_with_overflow
9798
| sym::mul_with_overflow
@@ -251,6 +252,7 @@ pub fn check_intrinsic_type(
251252
}
252253
sym::rustc_peek => (1, 0, vec![param(0)], param(0)),
253254
sym::caller_location => (0, 0, vec![], tcx.caller_location_ty()),
255+
sym::dynamic_shared_memory => (1, 0, vec![], Ty::new_mut_ptr(tcx, param(0))),
254256
sym::assert_inhabited
255257
| sym::assert_zero_valid
256258
| sym::assert_mem_uninitialized_valid => (1, 0, vec![], tcx.types.unit),

‎compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp

+16-5
Original file line numberDiff line numberDiff line change
@@ -205,10 +205,11 @@ extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M,
205205
.getCallee());
206206
}
207207

208-
extern "C" LLVMValueRef LLVMRustGetOrInsertGlobal(LLVMModuleRef M,
209-
const char *Name,
210-
size_t NameLen,
211-
LLVMTypeRef Ty) {
208+
extern "C" LLVMValueRef LLVMRustGetOrInsertGlobalInAddrspace(LLVMModuleRef M,
209+
const char *Name,
210+
size_t NameLen,
211+
LLVMTypeRef Ty,
212+
unsigned AddressSpace) {
212213
Module *Mod = unwrap(M);
213214
auto NameRef = StringRef(Name, NameLen);
214215

@@ -219,10 +220,20 @@ extern "C" LLVMValueRef LLVMRustGetOrInsertGlobal(LLVMModuleRef M,
219220
GlobalVariable *GV = Mod->getGlobalVariable(NameRef, true);
220221
if (!GV)
221222
GV = new GlobalVariable(*Mod, unwrap(Ty), false,
222-
GlobalValue::ExternalLinkage, nullptr, NameRef);
223+
GlobalValue::ExternalLinkage, nullptr, NameRef,
224+
nullptr, GlobalValue::NotThreadLocal, AddressSpace);
223225
return wrap(GV);
224226
}
225227

228+
extern "C" LLVMValueRef LLVMRustGetOrInsertGlobal(LLVMModuleRef M,
229+
const char *Name,
230+
size_t NameLen,
231+
LLVMTypeRef Ty) {
232+
Module *Mod = unwrap(M);
233+
unsigned AddressSpace = Mod->getDataLayout().getDefaultGlobalsAddressSpace();
234+
return LLVMRustGetOrInsertGlobalInAddrspace(M, Name, NameLen, Ty, AddressSpace);
235+
}
236+
226237
extern "C" LLVMValueRef LLVMRustInsertPrivateGlobal(LLVMModuleRef M,
227238
LLVMTypeRef Ty) {
228239
return wrap(new GlobalVariable(*unwrap(M), unwrap(Ty), false,

‎compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -825,6 +825,7 @@ symbols! {
825825
dyn_star,
826826
dyn_trait,
827827
dynamic_no_pic: "dynamic-no-pic",
828+
dynamic_shared_memory,
828829
e,
829830
edition_panic,
830831
effects,

‎library/core/src/intrinsics/mod.rs

+18
Original file line numberDiff line numberDiff line change
@@ -4234,6 +4234,24 @@ pub const unsafe fn min_align_of_val<T: ?Sized>(_ptr: *const T) -> usize {
42344234
unreachable!()
42354235
}
42364236

4237+
/// Returns a pointer to dynamic shared memory
4238+
/// The return pointer is aligned by properly.
4239+
/// All pointers returned by `dynamic_shared_memory` point to the same address,
4240+
/// so alias the same memory.
4241+
///
4242+
/// # Other APIs
4243+
///
4244+
/// CUDA and HIP call this shared memory.
4245+
/// OpenCL and SYCL call this local memory.
4246+
#[cfg(not(bootstrap))]
4247+
#[rustc_nounwind]
4248+
#[unstable(feature = "dynamic_shared_memory", issue = "135513")]
4249+
#[rustc_intrinsic]
4250+
#[rustc_intrinsic_must_be_overridden]
4251+
pub fn dynamic_shared_memory<T: ?Sized>() -> *mut T {
4252+
unreachable!()
4253+
}
4254+
42374255
/// Gets a static string slice containing the name of a type.
42384256
///
42394257
/// Note that, unlike most intrinsics, this is safe to call;

0 commit comments

Comments
 (0)
Failed to load comments.