Skip to content

Commit ea54566

Browse files
committed
Update rust-toolchain to nightly-2025-03-02.
Nvvm codegen compiles with latest nightly, and is able to codegen `core` and other essential crates. `libm` causes ICE and is next on the list to fix.
1 parent 1e45359 commit ea54566

File tree

25 files changed

+596
-394
lines changed

25 files changed

+596
-394
lines changed

crates/cuda_builder/src/lib.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -376,10 +376,13 @@ fn invoke_rustc(builder: &CudaBuilder) -> Result<PathBuf, CudaBuilderError> {
376376

377377
let new_path = get_new_path_var();
378378

379-
let mut rustflags = vec![format!(
380-
"-Zcodegen-backend={}",
381-
rustc_codegen_nvvm.display(),
382-
)];
379+
let mut rustflags = vec![
380+
format!("-Zcodegen-backend={}", rustc_codegen_nvvm.display()),
381+
"-Zcrate-attr=feature(register_tool)".into(),
382+
"-Zcrate-attr=register_tool(rust_cuda)".into(),
383+
"-Zcrate-attr=no_std".into(),
384+
"-Zsaturating_float_casts=false".into(),
385+
];
383386

384387
if let Some(emit) = &builder.emit {
385388
let string = match emit {

crates/rustc_codegen_nvvm/rustc_llvm_wrapper/RustWrapper.cpp

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,16 @@
99
// except according to those terms.
1010

1111
#include "rustllvm.h"
12+
#include "llvm/IR/CallSite.h"
13+
#include "llvm/IR/Constant.h"
1214
#include "llvm/IR/DebugInfoMetadata.h"
1315
#include "llvm/IR/DiagnosticInfo.h"
1416
#include "llvm/IR/DiagnosticPrinter.h"
1517
#include "llvm/IR/Instructions.h"
18+
#include "llvm/IR/Type.h"
1619
#include "llvm/Object/Archive.h"
1720
#include "llvm/Object/ObjectFile.h"
1821
#include "llvm/Bitcode/BitcodeWriterPass.h"
19-
#include "llvm/IR/CallSite.h"
2022
#include "llvm/Support/Casting.h"
2123

2224
#if LLVM_VERSION_GE(5, 0)
@@ -75,11 +77,6 @@ extern "C" LLVMTypeRef LLVMRustGetFunctionReturnType(LLVMValueRef V)
7577
return wrap(dyn_cast<llvm::Function>(unwrap<llvm::Value>(V))->getReturnType());
7678
}
7779

78-
extern "C" LLVMTypeRef LLVMRustGetValueType(LLVMValueRef V)
79-
{
80-
return wrap(unwrap<llvm::Value>(V)->getType());
81-
}
82-
8380
extern "C" LLVMValueRef
8481
LLVMRustInsertPrivateGlobal(LLVMModuleRef M, LLVMTypeRef Ty)
8582
{
@@ -1088,9 +1085,10 @@ extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
10881085

10891086
extern "C" LLVMMetadataRef
10901087
LLVMRustDIBuilderCreateEnumerator(LLVMRustDIBuilderRef Builder,
1091-
const char *Name, size_t NameLen, int64_t Val)
1088+
const char *Name, size_t NameLen, int64_t Val,
1089+
bool IsUnsigned)
10921090
{
1093-
return wrap(Builder->createEnumerator(StringRef(Name, NameLen), Val));
1091+
return wrap(Builder->createEnumerator(StringRef(Name, NameLen), Val, IsUnsigned));
10941092
}
10951093

10961094
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
@@ -1895,4 +1893,36 @@ extern "C" LLVMValueRef
18951893
{
18961894
return nullptr;
18971895
}
1896+
#endif
1897+
1898+
// Backport for LLVM < 8.0
1899+
#if LLVM_VERSION_LT(8, 0)
1900+
extern "C" LLVMValueRef LLVMConstInBoundsGEP2(LLVMTypeRef Ty,
1901+
LLVMValueRef ConstantVal,
1902+
LLVMValueRef *ConstantIndices,
1903+
unsigned NumIndices)
1904+
{
1905+
ArrayRef<Constant *> IdxList(unwrap<Constant>(ConstantIndices, NumIndices),
1906+
NumIndices);
1907+
Constant* Val = unwrap<Constant>(ConstantVal);
1908+
return wrap(ConstantExpr::getInBoundsGetElementPtr(unwrap(Ty), Val, IdxList));
1909+
}
1910+
1911+
extern "C" LLVMValueRef LLVMBuildGEP2(LLVMBuilderRef B, LLVMTypeRef Ty,
1912+
LLVMValueRef Pointer, LLVMValueRef *Indices,
1913+
unsigned NumIndices, const char *Name)
1914+
{
1915+
ArrayRef<Value *> IdxList(unwrap(Indices), NumIndices);
1916+
return wrap(unwrap(B)->CreateGEP(unwrap(Ty), unwrap(Pointer), IdxList, Name));
1917+
}
1918+
1919+
extern "C" LLVMValueRef LLVMBuildInBoundsGEP2(LLVMBuilderRef B, LLVMTypeRef Ty,
1920+
LLVMValueRef Pointer, LLVMValueRef *Indices,
1921+
unsigned NumIndices, const char *Name)
1922+
{
1923+
ArrayRef<Value *> IdxList(unwrap(Indices), NumIndices);
1924+
return wrap(
1925+
unwrap(B)->CreateInBoundsGEP(unwrap(Ty), unwrap(Pointer), IdxList, Name));
1926+
}
1927+
18981928
#endif

crates/rustc_codegen_nvvm/src/abi.rs

Lines changed: 71 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1+
use std::cmp;
2+
13
use libc::c_uint;
24
use rustc_abi::BackendRepr::Scalar;
5+
use rustc_abi::Size;
36
use rustc_abi::{HasDataLayout, Primitive, Reg, RegKind};
7+
use rustc_codegen_ssa::mir::operand::OperandRef;
48
use rustc_codegen_ssa::mir::operand::OperandValue;
59
use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue};
610
use rustc_codegen_ssa::{MemFlags, traits::*};
@@ -193,42 +197,39 @@ impl LlvmType for Reg {
193197
impl LlvmType for CastTarget {
194198
fn llvm_type<'ll>(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type {
195199
let rest_ll_unit = self.rest.unit.llvm_type(cx);
196-
let (rest_count, rem_bytes) = if self.rest.unit.size.bytes() == 0 {
197-
(0, 0)
200+
let rest_count = if self.rest.total == Size::ZERO {
201+
0
198202
} else {
199-
(
200-
self.rest.total.bytes() / self.rest.unit.size.bytes(),
201-
self.rest.total.bytes() % self.rest.unit.size.bytes(),
202-
)
203+
assert_ne!(
204+
self.rest.unit.size,
205+
Size::ZERO,
206+
"total size {:?} cannot be divided into units of zero size",
207+
self.rest.total
208+
);
209+
if self.rest.total.bytes() % self.rest.unit.size.bytes() != 0 {
210+
assert_eq!(self.rest.unit.kind, RegKind::Integer, "only int regs can be split");
211+
}
212+
self.rest.total.bytes().div_ceil(self.rest.unit.size.bytes())
203213
};
204214

215+
// Simplify to a single unit or an array if there's no prefix.
216+
// This produces the same layout, but using a simpler type.
205217
if self.prefix.iter().all(|x| x.is_none()) {
206-
// Simplify to a single unit when there is no prefix and size <= unit size
207-
if self.rest.total <= self.rest.unit.size {
218+
// We can't do this if is_consecutive is set and the unit would get
219+
// split on the target. Currently, this is only relevant for i128
220+
// registers.
221+
if rest_count == 1 && (!self.rest.is_consecutive || self.rest.unit != Reg::i128()) {
208222
return rest_ll_unit;
209223
}
210224

211-
// Simplify to array when all chunks are the same size and type
212-
if rem_bytes == 0 {
213-
return cx.type_array(rest_ll_unit, rest_count);
214-
}
215-
}
216-
217-
// Create list of fields in the main structure
218-
let mut args: Vec<_> = self
219-
.prefix
220-
.iter()
221-
.flat_map(|option_reg| option_reg.map(|reg| reg.llvm_type(cx)))
222-
.chain((0..rest_count).map(|_| rest_ll_unit))
223-
.collect();
224-
225-
// Append final integer
226-
if rem_bytes != 0 {
227-
// Only integers can be really split further.
228-
assert_eq!(self.rest.unit.kind, RegKind::Integer);
229-
args.push(cx.type_ix(rem_bytes * 8));
225+
return cx.type_array(rest_ll_unit, rest_count);
230226
}
231227

228+
// Generate a struct type with the prefix and the "rest" arguments.
229+
let prefix_args =
230+
self.prefix.iter().flat_map(|option_reg| option_reg.map(|reg| reg.llvm_type(cx)));
231+
let rest_args = (0..rest_count).map(|_| rest_ll_unit);
232+
let args: Vec<_> = prefix_args.chain(rest_args).collect();
232233
cx.type_struct(&args, false)
233234
}
234235
}
@@ -306,7 +307,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
306307
old_ret_ty = None;
307308
}
308309

309-
for arg in self.args.iter() {
310+
for arg in args {
310311
let llarg_ty = match &arg.mode {
311312
PassMode::Ignore => continue,
312313
PassMode::Direct(_) => arg.layout.immediate_llvm_type(cx),
@@ -356,6 +357,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
356357
cx.type_func(&llargument_tys, llreturn_ty)
357358
};
358359
if !transformed_types.is_empty() || old_ret_ty.is_some() {
360+
trace!("remapping args in {:?} to {:?}", ty, transformed_types);
359361
cx.remapped_integer_args
360362
.borrow_mut()
361363
.insert(ty, (old_ret_ty, transformed_types));
@@ -373,7 +375,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
373375
}
374376

375377
fn apply_attrs_llfn(&self, cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value) {
376-
if self.ret.layout.backend_repr.is_uninhabited() {
378+
if self.ret.layout.is_uninhabited() {
377379
llvm::Attribute::NoReturn.apply_llfn(llvm::AttributePlace::Function, llfn);
378380
}
379381

@@ -484,6 +486,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
484486
// by the LLVM verifier.
485487
if let Primitive::Int(..) = scalar.primitive() {
486488
if !scalar.is_bool() && !scalar.is_always_valid(bx) {
489+
trace!("apply_attrs_callsite -> range_metadata");
487490
bx.range_metadata(callsite, scalar.valid_range(bx));
488491
}
489492
}
@@ -532,9 +535,10 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
532535
impl<'a, 'll, 'tcx> AbiBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
533536
fn get_param(&mut self, index: usize) -> Self::Value {
534537
let val = llvm::get_param(self.llfn(), index as c_uint);
535-
trace!("Get param `{:?}`", val);
536-
unsafe {
538+
// trace!("Get param `{:?}`", val);
539+
let val = unsafe {
537540
let llfnty = LLVMRustGetFunctionType(self.llfn());
541+
trace!("llfnty: {:?}", llfnty);
538542
// destructure so rustc doesnt complain in the call to transmute_llval
539543
let Self { cx, llbuilder } = self;
540544
let map = cx.remapped_integer_args.borrow();
@@ -545,7 +549,9 @@ impl<'a, 'll, 'tcx> AbiBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
545549
}
546550
}
547551
val
548-
}
552+
};
553+
trace!("Get param `{:?}`", val);
554+
val
549555
}
550556
}
551557

@@ -591,7 +597,7 @@ impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
591597
on_stack: _,
592598
} => {
593599
let align = attrs.pointee_align.unwrap_or(self.layout.align.abi);
594-
OperandValue::Ref(PlaceValue::new_sized(val, self.layout.align.pref))
600+
OperandValue::Ref(PlaceValue::new_sized(val, align))
595601
.store(bx, dst);
596602
}
597603
// Unsized indirect arguments
@@ -603,35 +609,40 @@ impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
603609
bug!("unsized `ArgAbi` must be handled through `store_fn_arg`");
604610
}
605611
PassMode::Cast { pad_i32: _, cast } => {
606-
let can_store_through_cast_ptr = false;
607-
if can_store_through_cast_ptr {
608-
let cast_ptr_llty = bx.type_ptr_to(cast.llvm_type(bx));
609-
let cast_dst = bx.pointercast(dst.val.llval, cast_ptr_llty);
610-
bx.store(val, cast_dst, self.layout.align.abi);
611-
} else {
612-
let scratch_size = cast.size(bx);
613-
let scratch_align = cast.align(bx);
614-
let llscratch = bx.alloca(scratch_size, scratch_align);
615-
bx.lifetime_start(llscratch, scratch_size);
616-
617-
bx.store(val, llscratch, scratch_align);
618-
619-
bx.memcpy(
620-
dst.val.llval,
621-
self.layout.align.abi,
622-
llscratch,
623-
scratch_align,
624-
bx.const_usize(self.layout.size.bytes()),
625-
MemFlags::empty(),
626-
);
612+
trace!("store cast");
613+
// The ABI mandates that the value is passed as a different struct representation.
614+
// Spill and reload it from the stack to convert from the ABI representation to
615+
// the Rust representation.
616+
let scratch_size = cast.size(bx);
617+
let scratch_align = cast.align(bx);
618+
// Note that the ABI type may be either larger or smaller than the Rust type,
619+
// due to the presence or absence of trailing padding. For example:
620+
// - On some ABIs, the Rust layout { f64, f32, <f32 padding> } may omit padding
621+
// when passed by value, making it smaller.
622+
// - On some ABIs, the Rust layout { u16, u16, u16 } may be padded up to 8 bytes
623+
// when passed by value, making it larger.
624+
let copy_bytes =
625+
cmp::min(cast.unaligned_size(bx).bytes(), self.layout.size.bytes());
626+
// Allocate some scratch space...
627+
let llscratch = bx.alloca(scratch_size, scratch_align);
628+
bx.lifetime_start(llscratch, scratch_size);
629+
// ...store the value...
630+
bx.store(val, llscratch, scratch_align);
631+
// ... and then memcpy it to the intended destination.
632+
bx.memcpy(
633+
dst.val.llval,
634+
self.layout.align.abi,
635+
llscratch,
636+
scratch_align,
637+
bx.const_usize(copy_bytes),
638+
MemFlags::empty(),
639+
);
627640

628-
bx.lifetime_end(llscratch, scratch_size);
629-
bx.lifetime_end(llscratch, scratch_size);
630-
bx.lifetime_end(llscratch, scratch_size);
631-
}
641+
bx.lifetime_end(llscratch, scratch_size);
642+
trace!("store cast end");
632643
}
633644
_ => {
634-
OperandValue::Immediate(val).store(bx, dst);
645+
OperandRef::from_immediate_or_packed_pair(bx, val, self.layout).val.store(bx, dst);
635646
}
636647
}
637648
}
@@ -665,11 +676,7 @@ impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
665676
OperandValue::Ref(place_val).store(bx, dst);
666677
}
667678
PassMode::Direct(_)
668-
| PassMode::Indirect {
669-
attrs: _,
670-
meta_attrs: None,
671-
on_stack: _,
672-
}
679+
| PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _, }
673680
| PassMode::Cast { .. } => {
674681
let next_arg = next();
675682
self.store(bx, next_arg, dst);

0 commit comments

Comments
 (0)