Skip to content

Commit b151600

Browse files
committed
compute_100 target
1 parent 7285e16 commit b151600

8 files changed

Lines changed: 156 additions & 18 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ book
33
**/.vscode
44
.devcontainer
55
.codex
6+
rustc-ice-*.txt
7+
.nix-driver-libs

crates/nvvm/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,14 @@ impl NvvmArch {
448448
self.capability_value() % 10
449449
}
450450

451+
/// Whether this target uses NVVM's modern IR dialect rather than the legacy LLVM 7 dialect.
452+
///
453+
/// CUDA 13.2 documents the modern dialect as Blackwell-and-later only, which begins at
454+
/// `compute_100`.
455+
pub fn uses_modern_ir_dialect(&self) -> bool {
456+
self.capability_value() >= 100
457+
}
458+
451459
/// Get the target feature string (e.g., "compute_50" for `Compute50`, "compute_90a" for
452460
/// `Compute90a`).
453461
pub fn target_feature(&self) -> &'static str {

crates/rustc_codegen_nvvm/rustc_llvm_wrapper/RustWrapper.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,11 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind)
284284
case SExt:
285285
return Attribute::SExt;
286286
case StructRet:
287+
#if LLVM_VERSION_MAJOR >= 19
288+
report_fatal_error("StructRet not supported without a type on LLVM 19+");
289+
#else
287290
return Attribute::StructRet;
291+
#endif
288292
case UWTable:
289293
return Attribute::UWTable;
290294
case ZExt:
@@ -422,6 +426,41 @@ extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn, unsigned Index,
422426
#endif
423427
}
424428

429+
extern "C" void LLVMRustAddFunctionAttributeWithType(LLVMValueRef Fn, unsigned Index,
430+
LLVMRustAttribute RustAttr,
431+
LLVMTypeRef Ty)
432+
{
433+
#if LLVM_VERSION_MAJOR >= 19
434+
Function *A = unwrap<Function>(Fn);
435+
LLVMContext &Ctx = A->getContext();
436+
AttrBuilder B(Ctx);
437+
if (RustAttr == StructRet) {
438+
B.addStructRetAttr(unwrap(Ty));
439+
} else if (RustAttr == ByVal) {
440+
B.addByValAttr(unwrap(Ty));
441+
} else {
442+
B.addAttribute(Attribute::get(Ctx, fromRust(RustAttr)));
443+
}
444+
A->setAttributes(A->getAttributes().addAttributesAtIndex(Ctx, Index, B));
445+
#else
446+
Function *A = unwrap<Function>(Fn);
447+
Attribute Attr;
448+
if (RustAttr == StructRet) {
449+
Attr = Attribute::getWithStructRetType(A->getContext(), unwrap(Ty));
450+
} else if (RustAttr == ByVal) {
451+
Attr = Attribute::getWithByValType(A->getContext(), unwrap(Ty));
452+
} else {
453+
Attr = Attribute::get(A->getContext(), fromRust(RustAttr));
454+
}
455+
AttrBuilder B(Attr);
456+
#if LLVM_VERSION_GE(5, 0)
457+
A->addAttributes(Index, B);
458+
#else
459+
A->addAttributes(Index, AttributeSet::get(A->getContext(), Index, B));
460+
#endif
461+
#endif
462+
}
463+
425464
extern "C" void LLVMRustAddAlignmentAttr(LLVMValueRef Fn,
426465
unsigned Index,
427466
uint32_t Bytes)

crates/rustc_codegen_nvvm/src/abi.rs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,9 @@ impl ArgAttributesExt for ArgAttributes {
144144
llvm::LLVMRustAddDereferenceableOrNullAttr(llfn, idx.as_uint(), deref);
145145
}
146146
regular -= ArgAttribute::NonNull;
147-
}
148-
if let Some(align) = self.pointee_align {
149-
llvm::LLVMRustAddAlignmentAttr(llfn, idx.as_uint(), align.bytes() as u32);
147+
if let Some(align) = self.pointee_align {
148+
llvm::LLVMRustAddAlignmentAttr(llfn, idx.as_uint(), align.bytes() as u32);
149+
}
150150
}
151151
regular.for_each_kind(|attr| attr.apply_llfn(idx, llfn));
152152
// TODO(RDambrosio016): Apply mutable noalias once we upgrade to LLVM 13
@@ -182,13 +182,13 @@ impl ArgAttributesExt for ArgAttributes {
182182
);
183183
}
184184
regular -= ArgAttribute::NonNull;
185-
}
186-
if let Some(align) = self.pointee_align {
187-
llvm::LLVMRustAddAlignmentCallSiteAttr(
188-
callsite,
189-
idx.as_uint(),
190-
align.bytes() as u32,
191-
);
185+
if let Some(align) = self.pointee_align {
186+
llvm::LLVMRustAddAlignmentCallSiteAttr(
187+
callsite,
188+
idx.as_uint(),
189+
align.bytes() as u32,
190+
);
191+
}
192192
}
193193
regular.for_each_kind(|attr| attr.apply_callsite(idx, callsite));
194194
match self.arg_ext {
@@ -443,6 +443,13 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
443443
} => {
444444
assert!(!on_stack);
445445
let i = apply(attrs);
446+
#[cfg(feature = "llvm19")]
447+
llvm::Attribute::StructRet.apply_llfn_with_type(
448+
llvm::AttributePlace::Argument(i),
449+
llfn,
450+
self.ret.memory_ty(cx),
451+
);
452+
#[cfg(not(feature = "llvm19"))]
446453
llvm::Attribute::StructRet.apply_llfn(llvm::AttributePlace::Argument(i), llfn);
447454
}
448455
_ => {}

crates/rustc_codegen_nvvm/src/llvm.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ impl Attribute {
9797
unsafe { LLVMRustAddFunctionAttribute(llfn, idx.as_uint(), *self) }
9898
}
9999

100+
#[cfg(feature = "llvm19")]
101+
pub fn apply_llfn_with_type(&self, idx: AttributePlace, llfn: &Value, ty: &Type) {
102+
unsafe { LLVMRustAddFunctionAttributeWithType(llfn, idx.as_uint(), *self, ty) }
103+
}
104+
100105
pub fn apply_callsite(&self, idx: AttributePlace, callsite: &Value) {
101106
unsafe { LLVMRustAddCallSiteAttribute(callsite, idx.as_uint(), *self) }
102107
}
@@ -1624,6 +1629,13 @@ unsafe extern "C" {
16241629
pub(crate) fn LLVMSetFunctionCallConv(Fn: &Value, CC: c_uint);
16251630
pub(crate) fn LLVMRustAddAlignmentAttr(Fn: &Value, index: c_uint, bytes: u32);
16261631
pub(crate) fn LLVMRustAddFunctionAttribute(Fn: &Value, index: c_uint, attr: Attribute);
1632+
#[cfg(feature = "llvm19")]
1633+
pub(crate) fn LLVMRustAddFunctionAttributeWithType(
1634+
Fn: &Value,
1635+
index: c_uint,
1636+
attr: Attribute,
1637+
ty: &Type,
1638+
);
16271639
pub(crate) fn LLVMRustAddFunctionAttrStringValue(
16281640
Fn: &Value,
16291641
index: c_uint,

crates/rustc_codegen_nvvm/src/nvvm.rs

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,23 @@ impl Display for CodegenErr {
4343
}
4444
}
4545

46+
#[cfg(feature = "llvm19")]
47+
fn is_known_nvvm_verify_false_negative(log: &str) -> bool {
48+
log.contains("Producer: 'LLVM19")
49+
&& log.contains("Reader: 'LLVM 7.0.1'")
50+
&& log.contains("parse Invalid value")
51+
}
52+
53+
fn selected_arch(args: &CodegenArgs) -> NvvmArch {
54+
args.nvvm_options
55+
.iter()
56+
.find_map(|opt| match opt {
57+
NvvmOption::Arch(arch) => Some(*arch),
58+
_ => None,
59+
})
60+
.unwrap_or_default()
61+
}
62+
4663
/// Take a list of bitcode module bytes and their names and codegen it
4764
/// into PTX bytes. The final PTX *should* be utf8, but just to be on the safe side
4865
/// it returns a vector of bytes.
@@ -56,6 +73,12 @@ pub fn codegen_bitcode_modules(
5673
llcx: &Context,
5774
) -> Result<Vec<u8>, CodegenErr> {
5875
debug!("Codegenning bitcode to PTX");
76+
let target_arch = selected_arch(args);
77+
debug!(
78+
"selected NVVM target arch: {} (modern dialect: {})",
79+
target_arch,
80+
target_arch.uses_modern_ir_dialect()
81+
);
5982

6083
// Make sure the nvvm version is high enough so users don't get confusing compilation errors.
6184
let (major, minor) = nvvm::ir_version();
@@ -116,19 +139,32 @@ pub fn codegen_bitcode_modules(
116139
let verification_res = prog.verify();
117140
if verification_res.is_err() {
118141
let log = prog.compiler_log().unwrap().unwrap_or_default();
119-
let footer = "If you plan to submit a bug report please re-run the codegen with `RUSTFLAGS=\"--emit=llvm-ir\" and include the .ll file corresponding to the .o file mentioned in the log";
120-
panic!(
121-
"Malformed NVVM IR program rejected by libnvvm, dumping verifier log:\n\n{log}\n\n{footer}"
122-
);
142+
#[cfg(feature = "llvm19")]
143+
if target_arch.uses_modern_ir_dialect() && is_known_nvvm_verify_false_negative(&log) {
144+
sess.dcx().warn(
145+
"libnvvm verification rejected LLVM 19 bitcode with the known legacy-reader message; proceeding to compilation anyway on the llvm19 path"
146+
);
147+
} else {
148+
let footer = "If you plan to submit a bug report please re-run the codegen with `RUSTFLAGS=\"--emit=llvm-ir\" and include the .ll file corresponding to the .o file mentioned in the log";
149+
panic!(
150+
"Malformed NVVM IR program rejected by libnvvm, dumping verifier log:\n\n{log}\n\n{footer}"
151+
);
152+
}
153+
#[cfg(not(feature = "llvm19"))]
154+
{
155+
let footer = "If you plan to submit a bug report please re-run the codegen with `RUSTFLAGS=\"--emit=llvm-ir\" and include the .ll file corresponding to the .o file mentioned in the log";
156+
panic!(
157+
"Malformed NVVM IR program rejected by libnvvm, dumping verifier log:\n\n{log}\n\n{footer}"
158+
);
159+
}
123160
}
124161

125162
let res = match prog.compile(&args.nvvm_options) {
126163
Ok(b) => b,
127164
Err(error) => {
128165
let log = prog.compiler_log().unwrap().unwrap_or_default();
129-
// this should never happen, if it does, something went really bad or its a bug on libnvvm's end
130166
panic!(
131-
"libnvvm returned an error that was not previously caught by the verifier: {error:?} {log:?}"
167+
"libnvvm compilation failed: {error:?}\n\n{log}"
132168
);
133169
}
134170
};

examples/vecadd/build.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
11
use std::env;
22
use std::path;
3+
use std::str::FromStr;
34

4-
use cuda_builder::CudaBuilder;
5+
use cuda_builder::{CudaBuilder, NvvmArch};
6+
7+
fn selected_arch() -> NvvmArch {
8+
match env::var("RUST_CUDA_TARGET_ARCH") {
9+
Ok(value) => NvvmArch::from_str(&value)
10+
.unwrap_or_else(|_| panic!("unknown RUST_CUDA_TARGET_ARCH value: {value}")),
11+
Err(_) if env::var_os("LLVM_CONFIG_19").is_some() => NvvmArch::Compute100,
12+
Err(_) => NvvmArch::default(),
13+
}
14+
}
515

616
fn main() {
717
// On Windows, nanorand's entropy uses SystemFunction036 (RtlGenRandom) from advapi32.
@@ -14,15 +24,30 @@ fn main() {
1424
println!("cargo::rerun-if-changed=kernels");
1525
println!("cargo::rerun-if-env-changed=RUST_CUDA_DUMP_FINAL_MODULE");
1626
println!("cargo::rerun-if-env-changed=RUST_CUDA_EMIT_LLVM_IR");
27+
println!("cargo::rerun-if-env-changed=RUST_CUDA_TARGET_ARCH");
28+
println!("cargo::rerun-if-env-changed=LLVM_CONFIG_19");
1729

1830
let out_path = path::PathBuf::from(env::var("OUT_DIR").unwrap());
1931
let manifest_dir = path::PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
2032

2133
let dump_final_module = env::var_os("RUST_CUDA_DUMP_FINAL_MODULE").is_some();
2234
let emit_llvm_ir = env::var_os("RUST_CUDA_EMIT_LLVM_IR").is_some();
35+
let arch = selected_arch();
36+
37+
println!("cargo:warning=vecadd target arch: {}", arch.target_feature());
38+
if arch.uses_modern_ir_dialect() {
39+
println!(
40+
"cargo:warning=vecadd expects the modern NVVM IR dialect on this target; use this path for LLVM 19 validation"
41+
);
42+
} else {
43+
println!(
44+
"cargo:warning=vecadd expects the legacy LLVM 7 NVVM dialect on this target, even if LLVM_CONFIG_19 is set"
45+
);
46+
}
2347

2448
let mut builder = CudaBuilder::new(manifest_dir.join("kernels"));
2549
builder = builder.copy_to(out_path.join("kernels.ptx"));
50+
builder = builder.arch(arch);
2651

2752
if dump_final_module {
2853
builder = builder.final_module_path(out_path.join("final-module.ll"));

flake.nix

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
};
1515
lib = pkgs.lib;
1616
cudaRoot = "/usr/local/cuda-13.2";
17+
driverLibDir = "/usr/lib/x86_64-linux-gnu";
18+
driverLibPath = "${driverLibDir}/libcuda.so.1";
1719
llvm19 = pkgs.llvmPackages_19;
1820
llvm19Bin = lib.getBin llvm19.llvm;
1921
llvm19Dev = lib.getDev llvm19.llvm;
@@ -69,12 +71,19 @@
6971
LIBCLANG_PATH = "${lib.getLib llvm19.libclang}/lib";
7072

7173
shellHook = ''
74+
driver_shim_dir="$PWD/.nix-driver-libs"
75+
mkdir -p "$driver_shim_dir"
76+
if [ -e "${driverLibPath}" ]; then
77+
ln -sf "${driverLibPath}" "$driver_shim_dir/libcuda.so.1"
78+
fi
79+
7280
export PATH="${llvm19CompatTools}/bin:${llvm19Bin}/bin:${llvm19Dev}/bin:${cudaRoot}/bin:${cudaRoot}/nvvm/bin:$PATH"
73-
export LD_LIBRARY_PATH="${cudaRoot}/nvvm/lib64:${cudaRoot}/lib64:${pkgs.ncurses.out}/lib:${pkgs.libxml2.out}/lib:${pkgs.zlib.out}/lib:${pkgs.stdenv.cc.cc.lib}/lib''${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
81+
export LD_LIBRARY_PATH="$driver_shim_dir:${cudaRoot}/nvvm/lib64:${cudaRoot}/lib64:${pkgs.ncurses.out}/lib:${pkgs.libxml2.out}/lib:${pkgs.zlib.out}/lib:${pkgs.stdenv.cc.cc.lib}/lib''${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
7482
7583
echo "rust-cuda llvm19 shell"
7684
echo " CUDA_HOME=$CUDA_HOME"
7785
echo " LLVM_CONFIG_19=$LLVM_CONFIG_19"
86+
echo " NVIDIA_DRIVER_LIB=$driver_shim_dir/libcuda.so.1"
7887
'';
7988
};
8089
};

0 commit comments

Comments
 (0)