diff --git a/crates/cuda_builder/src/lib.rs b/crates/cuda_builder/src/lib.rs index e5b1e60..bc8677a 100644 --- a/crates/cuda_builder/src/lib.rs +++ b/crates/cuda_builder/src/lib.rs @@ -376,10 +376,12 @@ fn invoke_rustc(builder: &CudaBuilder) -> Result { let new_path = get_new_path_var(); - let mut rustflags = vec![format!( - "-Zcodegen-backend={}", - rustc_codegen_nvvm.display(), - )]; + let mut rustflags = vec![ + format!("-Zcodegen-backend={}", rustc_codegen_nvvm.display(),), + "-Zcrate-attr=feature(register_tool)".to_string(), + "-Zcrate-attr=register_tool(rust_cuda)".to_string(), + "-Zcrate-attr=no_std".to_string(), + ]; if let Some(emit) = &builder.emit { let string = match emit { diff --git a/crates/cuda_std/src/atomic/intrinsics.rs b/crates/cuda_std/src/atomic/intrinsics.rs index ba8565f..7a4fc2a 100644 --- a/crates/cuda_std/src/atomic/intrinsics.rs +++ b/crates/cuda_std/src/atomic/intrinsics.rs @@ -1,6 +1,7 @@ //! Raw CUDA-specific atomic functions that map to PTX instructions. use crate::gpu_only; +use core::arch::asm; use core::concat; use paste::paste; diff --git a/crates/cuda_std/src/lib.rs b/crates/cuda_std/src/lib.rs index 33e7b28..f08a604 100644 --- a/crates/cuda_std/src/lib.rs +++ b/crates/cuda_std/src/lib.rs @@ -23,15 +23,11 @@ #![cfg_attr( target_os = "cuda", - no_std, feature( - register_attr, alloc_error_handler, - asm, asm_experimental_arch, link_llvm_intrinsics ), - register_attr(nvvm_internal) )] extern crate alloc; @@ -49,7 +45,7 @@ pub mod cfg; pub mod ptr; pub mod shared; pub mod thread; -pub mod warp; +// pub mod warp; mod float_ext; diff --git a/crates/cuda_std/src/mem.rs b/crates/cuda_std/src/mem.rs index a3504ec..b41a3ae 100644 --- a/crates/cuda_std/src/mem.rs +++ b/crates/cuda_std/src/mem.rs @@ -1,8 +1,8 @@ //! Support for allocating memory and using `alloc` using CUDA memory allocation system-calls. - use crate::gpu_only; #[cfg(any(target_arch = "nvptx", target_arch = "nvptx64"))] use alloc::alloc::*; +use core::arch::asm; #[cfg(any(target_arch = "nvptx", target_arch = "nvptx64"))] use core::ffi::c_void; diff --git a/crates/cuda_std/src/misc.rs b/crates/cuda_std/src/misc.rs index 9314a3c..160ac24 100644 --- a/crates/cuda_std/src/misc.rs +++ b/crates/cuda_std/src/misc.rs @@ -1,6 +1,6 @@ //! Misc functions that do not exactly fit into other categories. - use crate::gpu_only; +use core::arch::asm; /// Suspends execution of the kernel, usually to pause at a specific point when debugging in a debugger. #[gpu_only] diff --git a/crates/cuda_std/src/ptr.rs b/crates/cuda_std/src/ptr.rs index 02dd876..9dbd36a 100644 --- a/crates/cuda_std/src/ptr.rs +++ b/crates/cuda_std/src/ptr.rs @@ -1,6 +1,6 @@ //! CUDA-specific pointer handling logic. - use crate::gpu_only; +use core::arch::asm; /// Special areas of GPU memory where a pointer could reside. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] diff --git a/crates/cuda_std/src/shared.rs b/crates/cuda_std/src/shared.rs index bbbefcf..021aee5 100644 --- a/crates/cuda_std/src/shared.rs +++ b/crates/cuda_std/src/shared.rs @@ -77,7 +77,7 @@ pub fn dynamic_shared_mem() -> *mut T { extern "C" { // need to use nvvm_internal and not address_space because address_space only parses // static definitions, not extern static definitions. - #[nvvm_internal(addrspace(3))] + #[rust_cuda::nvvm_internal(addrspace(3))] #[allow(improper_ctypes)] // mangle it a bit to make sure nobody makes the same thing #[link_name = "_Zcuda_std_dyn_shared"] diff --git a/crates/cuda_std/src/thread.rs b/crates/cuda_std/src/thread.rs index e32d1bb..22e14a6 100644 --- a/crates/cuda_std/src/thread.rs +++ b/crates/cuda_std/src/thread.rs @@ -17,7 +17,7 @@ //! The most important structure after threads, thread blocks arrange // TODO: write some docs about the terms used in this module. - +use core::arch::asm; use cuda_std_macros::gpu_only; use vek::{Vec2, Vec3}; diff --git a/crates/cuda_std/src/warp.rs b/crates/cuda_std/src/warp.rs index dae087d..b82808d 100644 --- a/crates/cuda_std/src/warp.rs +++ b/crates/cuda_std/src/warp.rs @@ -4,6 +4,7 @@ //! thread blocks and execute in SIMT fashion. use crate::gpu_only; +use core::arch::asm; use half::{bf16, f16}; /// Synchronizes all of the threads inside of this warp according to `mask`. diff --git a/crates/cuda_std_macros/src/lib.rs b/crates/cuda_std_macros/src/lib.rs index b813ee9..c255659 100644 --- a/crates/cuda_std_macros/src/lib.rs +++ b/crates/cuda_std_macros/src/lib.rs @@ -1,6 +1,6 @@ use proc_macro::TokenStream; -use proc_macro2::Span; -use quote::{quote_spanned, ToTokens}; +use proc_macro2::{Span, TokenTree, Delimiter, Group}; +use quote::{quote_spanned, ToTokens, quote}; use syn::{ parse::Parse, parse_macro_input, parse_quote, punctuated::Punctuated, spanned::Spanned, Error, FnArg, Ident, ItemFn, ReturnType, Stmt, Token, @@ -27,7 +27,7 @@ pub fn kernel(input: proc_macro::TokenStream, item: proc_macro::TokenStream) -> let mut item = parse_macro_input!(item as ItemFn); let no_mangle = parse_quote!(#[no_mangle]); item.attrs.push(no_mangle); - let internal = parse_quote!(#[cfg_attr(any(target_arch="nvptx", target_arch="nvptx64"), nvvm_internal(kernel(#input)))]); + let internal = parse_quote!(#[cfg_attr(any(target_arch="nvptx", target_arch="nvptx64"), rust_cuda::nvvm_internal(kernel(#input)))]); item.attrs.push(internal); // used to guarantee some things about how params are passed in the codegen. @@ -231,7 +231,7 @@ pub fn address_space(attr: proc_macro::TokenStream, item: proc_macro::TokenStrea }; let new_attr = - parse_quote!(#[cfg_attr(target_os = "cuda", nvvm_internal(addrspace(#addrspace_num)))]); + parse_quote!(#[cfg_attr(target_os = "cuda", rust_cuda::nvvm_internal(addrspace(#addrspace_num)))]); global.attrs.push(new_attr); global.into_token_stream().into() diff --git a/crates/cust/Cargo.toml b/crates/cust/Cargo.toml index 39eab9c..0a335f0 100644 --- a/crates/cust/Cargo.toml +++ b/crates/cust/Cargo.toml @@ -17,7 +17,7 @@ cust_core = { path = "../cust_core", version = "0.1.0"} cust_raw = { path = "../cust_raw", version = "0.11.2"} bitflags = "1.2" cust_derive = { path = "../cust_derive", version = "0.2" } -glam = { version = "0.20", features=["cuda"], optional = true } +glam = { version = "0.21", features=["cuda"], optional = true } mint = { version = "^0.5", optional = true } num-complex = { version = "0.4", optional = true } vek = { version = "0.15.1", optional = true, default-features = false } diff --git a/crates/cust_core/Cargo.toml b/crates/cust_core/Cargo.toml index 1eacca1..80bb7cb 100644 --- a/crates/cust_core/Cargo.toml +++ b/crates/cust_core/Cargo.toml @@ -9,7 +9,7 @@ readme = "../../README.md" [dependencies] vek = { version = "0.15.1", default-features=false, features=["libm"], optional = true } -glam = { version = "0.20", features=["cuda", "libm"], default-features=false, optional=true } +glam = { version = "0.21", features=["cuda", "libm"], default-features=false, optional=true } mint = { version = "^0.5", optional = true } half = { version = "1.8", optional = true } num-complex = { version = "0.4", optional = true } diff --git a/crates/cust_core/src/lib.rs b/crates/cust_core/src/lib.rs index ed4ddd3..0589534 100644 --- a/crates/cust_core/src/lib.rs +++ b/crates/cust_core/src/lib.rs @@ -172,7 +172,7 @@ pub mod _hidden { #[cfg(feature = "glam")] impl_device_copy! { - glam::Vec2, glam::Vec3, glam::Vec4, glam::IVec2, glam::IVec3, glam::IVec4, + glam::Vec2, glam::Vec3, glam::Vec4, glam::IVec2, glam::IVec3, glam::IVec4, glam::Mat3, glam::Mat4 } #[cfg(feature = "mint")] diff --git a/crates/optix/Cargo.toml b/crates/optix/Cargo.toml index 8fc7377..de4f031 100644 --- a/crates/optix/Cargo.toml +++ b/crates/optix/Cargo.toml @@ -20,7 +20,7 @@ cust = { version = "0.3", path = "../cust", features=["impl_mint"] } cust_raw = { version = "0.11.2", path = "../cust_raw" } cfg-if = "1.0.0" bitflags = "1.3.2" -glam = { version = "0.20", features=["cuda", "libm"], default-features=false, optional=true } +glam = { version = "0.21", features=["cuda", "libm"], default-features=false, optional=true } half = { version = "^1.8", optional = true } memoffset = "0.6.4" mint = "0.5.8" diff --git a/crates/optix/examples/ex02_pipeline/device/src/lib.rs b/crates/optix/examples/ex02_pipeline/device/src/lib.rs index 45cabfe..d1b18bc 100644 --- a/crates/optix/examples/ex02_pipeline/device/src/lib.rs +++ b/crates/optix/examples/ex02_pipeline/device/src/lib.rs @@ -1,9 +1,8 @@ -#![feature(asm)] #![cfg_attr( target_os = "cuda", no_std, - feature(register_attr), - register_attr(nvvm_internal) + feature(register_tool), + register_tool(nvvm_internal) )] // #![deny(warnings)] #![allow(clippy::missing_safety_doc)] diff --git a/crates/optix/examples/rust/ex04_mesh_gpu/src/lib.rs b/crates/optix/examples/rust/ex04_mesh_gpu/src/lib.rs index 3266975..7796897 100644 --- a/crates/optix/examples/rust/ex04_mesh_gpu/src/lib.rs +++ b/crates/optix/examples/rust/ex04_mesh_gpu/src/lib.rs @@ -1,8 +1,8 @@ #![cfg_attr( target_os = "cuda", no_std, - feature(register_attr), - register_attr(nvvm_internal) + feature(register_tool), + register_tool(nvvm_internal) )] #![allow(non_snake_case, clippy::missing_safety_doc)] diff --git a/crates/optix_device/Cargo.toml b/crates/optix_device/Cargo.toml index 92fb2db..536a8db 100644 --- a/crates/optix_device/Cargo.toml +++ b/crates/optix_device/Cargo.toml @@ -7,7 +7,7 @@ authors = ["Anders Langlands ", "Riccardo D'Ambrosio [dependencies] bitflags = "1.3.2" cuda_std = { version = "0.2", path = "../cuda_std" } -glam = { version = "0.20", features=["cuda", "libm"], default-features=false } +glam = { version = "0.21", features=["cuda", "libm"], default-features=false } paste = "1.0.6" seq-macro = "0.3.0" cust_core = { version = "0.1", path = "../cust_core" } diff --git a/crates/optix_device/src/lib.rs b/crates/optix_device/src/lib.rs index d75938b..c6d03fa 100644 --- a/crates/optix_device/src/lib.rs +++ b/crates/optix_device/src/lib.rs @@ -1,8 +1,8 @@ #![cfg_attr( target_arch = "nvptx64", no_std, - feature(register_attr, asm, asm_experimental_arch), - register_attr(nvvm_internal) + feature(register_tool, asm, asm_experimental_arch), + register_tool(nvvm_internal) )] extern crate alloc; diff --git a/crates/rustc_codegen_nvvm/Cargo.toml b/crates/rustc_codegen_nvvm/Cargo.toml index 01f7473..81c56fb 100644 --- a/crates/rustc_codegen_nvvm/Cargo.toml +++ b/crates/rustc_codegen_nvvm/Cargo.toml @@ -17,7 +17,9 @@ crate-type = ["dylib"] [dependencies] nvvm = { version = "0.1", path = "../nvvm" } rustc-demangle = "0.1.20" +cstr = "0.2" libc = "0.2.97" +libloading = "0.7" tar = "0.4.35" once_cell = "1.8.0" bitflags = "1.3.2" diff --git a/crates/rustc_codegen_nvvm/src/abi.rs b/crates/rustc_codegen_nvvm/src/abi.rs index f9adb1b..cc20f6b 100644 --- a/crates/rustc_codegen_nvvm/src/abi.rs +++ b/crates/rustc_codegen_nvvm/src/abi.rs @@ -18,6 +18,24 @@ use rustc_target::abi::{self, HasDataLayout, Int}; pub use rustc_target::spec::abi::Abi; use tracing::trace; +fn clone_pass_mode(original: &PassMode) -> PassMode { + match original { + PassMode::Ignore => PassMode::Ignore, + PassMode::Direct(attrs) => PassMode::Direct(*attrs), + PassMode::Pair(attrs1, attrs2) => PassMode::Pair(*attrs1, *attrs2), + PassMode::Cast(target, bool) => PassMode::Cast(target.clone(), *bool), + PassMode::Indirect { + attrs, + extra_attrs, + on_stack, + } => PassMode::Indirect { + attrs: *attrs, + extra_attrs: *extra_attrs, + on_stack: *on_stack, + }, + } +} + pub(crate) fn readjust_fn_abi<'tcx>( tcx: TyCtxt<'tcx>, fn_abi: &'tcx FnAbi<'tcx, Ty<'tcx>>, @@ -29,8 +47,7 @@ pub(crate) fn readjust_fn_abi<'tcx>( let readjust_arg_abi = |arg: &ArgAbi<'tcx, Ty<'tcx>>| { let mut arg = ArgAbi { layout: arg.layout, - mode: arg.mode, - pad: arg.pad, + mode: clone_pass_mode(&arg.mode), }; // ignore zsts @@ -265,7 +282,7 @@ pub(crate) trait FnAbiLlvmExt<'ll, 'tcx> { impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type { let args_capacity: usize = self.args.iter().map(|arg| - if arg.pad.is_some() { 1 } else { 0 } + + // if arg.pad.is_some() { 1 } else { 0 } + if let PassMode::Pair(_, _) = arg.mode { 2 } else { 1 } ).sum(); @@ -281,10 +298,10 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { } + args_capacity, ); - let mut llreturn_ty = match self.ret.mode { + let mut llreturn_ty = match &self.ret.mode { PassMode::Ignore => cx.type_void(), PassMode::Direct(_) | PassMode::Pair(..) => self.ret.layout.immediate_llvm_type(cx), - PassMode::Cast(cast) => cast.llvm_type(cx), + PassMode::Cast(cast, _) => cast.llvm_type(cx), PassMode::Indirect { .. } => { idx += 1; llargument_tys.push(cx.type_ptr_to(self.ret.memory_ty(cx))); @@ -302,13 +319,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { } for arg in self.args.iter() { - // add padding - if let Some(ty) = arg.pad { - idx += 1; - llargument_tys.push(ty.llvm_type(cx)); - } - - let llarg_ty = match arg.mode { + let llarg_ty = match &arg.mode { PassMode::Ignore => continue, PassMode::Direct(_) => arg.layout.immediate_llvm_type(cx), PassMode::Pair(..) => { @@ -329,7 +340,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { idx += 2; continue; } - PassMode::Cast(cast) => cast.llvm_type(cx), + PassMode::Cast(cast, _) => cast.llvm_type(cx), PassMode::Indirect { attrs: _, extra_attrs: None, @@ -398,10 +409,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { } _ => {} } - for arg in &self.args { - if arg.pad.is_some() { - apply(&ArgAttributes::new()); - } + for arg in self.args.iter() { match arg.mode { PassMode::Ignore => {} PassMode::Indirect { @@ -436,7 +444,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { apply(a); apply(b); } - PassMode::Cast(_) => { + PassMode::Cast(..) => { apply(&ArgAttributes::new()); } } @@ -476,16 +484,13 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { // If the value is a boolean, the range is 0..2 and that ultimately // become 0..0 when the type becomes i1, which would be rejected // by the LLVM verifier. - if let Int(..) = scalar.value { + if scalar.primitive().is_int() { if !scalar.is_bool() && !scalar.is_always_valid(bx) { - bx.range_metadata(callsite, scalar.valid_range); + bx.range_metadata(callsite, scalar.valid_range(bx)); } } } - for arg in &self.args { - if arg.pad.is_some() { - apply(bx.cx, &ArgAttributes::new()); - } + for arg in self.args.iter() { match arg.mode { PassMode::Ignore => {} PassMode::Indirect { @@ -515,7 +520,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { apply(bx.cx, a); apply(bx.cx, b); } - PassMode::Cast(_) => { + PassMode::Cast(..) => { apply(bx.cx, &ArgAttributes::new()); } } @@ -524,10 +529,6 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { } impl<'a, 'll, 'tcx> AbiBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { - fn apply_attrs_callsite(&mut self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, callsite: Self::Value) { - fn_abi.apply_attrs_callsite(self, callsite) - } - fn get_param(&mut self, index: usize) -> Self::Value { let val = llvm::get_param(self.llfn(), index as c_uint); trace!("Get param `{:?}`", val); @@ -588,7 +589,7 @@ impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { OperandValue::Ref(val, None, self.layout.align.abi).store(bx, dst) } else if self.is_unsized_indirect() { bug!("unsized `ArgAbi` must be handled through `store_fn_arg`"); - } else if let PassMode::Cast(cast) = self.mode { + } else if let PassMode::Cast(cast, _) = &self.mode { let can_store_through_cast_ptr = false; if can_store_through_cast_ptr { let cast_ptr_llty = bx.type_ptr_to(cast.llvm_type(bx)); @@ -647,7 +648,7 @@ impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { extra_attrs: None, on_stack: _, } - | PassMode::Cast(_) => { + | PassMode::Cast(..) => { let next_arg = next(); self.store(bx, next_arg, dst); } diff --git a/crates/rustc_codegen_nvvm/src/allocator.rs b/crates/rustc_codegen_nvvm/src/allocator.rs index c0090d7..1692a72 100644 --- a/crates/rustc_codegen_nvvm/src/allocator.rs +++ b/crates/rustc_codegen_nvvm/src/allocator.rs @@ -11,7 +11,7 @@ pub(crate) unsafe fn codegen( _tcx: TyCtxt<'_>, mods: &mut LlvmMod, kind: AllocatorKind, - has_alloc_error_handler: bool, + alloc_error_handler_kind: AllocatorKind, ) { let llcx = &*mods.llcx; let llmod = mods.llmod.as_ref().unwrap(); @@ -94,11 +94,7 @@ pub(crate) unsafe fn codegen( // -> ! DIFlagNoReturn llvm::Attribute::NoReturn.apply_llfn(llvm::AttributePlace::Function, llfn); - let kind = if has_alloc_error_handler { - AllocatorKind::Global - } else { - AllocatorKind::Default - }; + let kind = alloc_error_handler_kind; let callee = kind.fn_name(sym::oom); let callee = llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr().cast(), callee.len(), ty); diff --git a/crates/rustc_codegen_nvvm/src/asm.rs b/crates/rustc_codegen_nvvm/src/asm.rs index 1a1c79f..d1dcaac 100644 --- a/crates/rustc_codegen_nvvm/src/asm.rs +++ b/crates/rustc_codegen_nvvm/src/asm.rs @@ -1,10 +1,10 @@ use std::os::raw::{c_char, c_uint}; use crate::{ - llvm::{self, Value}, + llvm::{self, AsmDialect, Value}, ty::LayoutLlvmExt, }; -use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece, LlvmAsmDialect}; +use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_codegen_ssa::{ mir::{operand::OperandValue, place::PlaceRef}, traits::{ @@ -13,7 +13,6 @@ use rustc_codegen_ssa::{ }, }; use rustc_hash::FxHashMap; -use rustc_hir::LlvmInlineAsmInner; use rustc_middle::{span_bug, ty::Instance}; use rustc_span::{Pos, Span}; use rustc_target::asm::{InlineAsmRegClass, InlineAsmRegOrRegClass, NvptxInlineAsmRegClass}; @@ -21,97 +20,6 @@ use rustc_target::asm::{InlineAsmRegClass, InlineAsmRegOrRegClass, NvptxInlineAs use crate::{builder::Builder, context::CodegenCx}; impl<'a, 'll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { - // inline llvm ir is allowed, but the user needs to make sure it doesnt violate - // nvvm ir constraints - fn codegen_llvm_inline_asm( - &mut self, - ia: &LlvmInlineAsmInner, - outputs: Vec>, - mut inputs: Vec<&'ll Value>, - span: Span, - ) -> bool { - let mut ext_constraints = vec![]; - let mut output_types = vec![]; - - // Prepare the output operands - let mut indirect_outputs = vec![]; - for (i, (out, &place)) in ia.outputs.iter().zip(&outputs).enumerate() { - if out.is_rw { - let operand = self.load_operand(place); - if let OperandValue::Immediate(_) = operand.val { - inputs.push(operand.immediate()); - } - ext_constraints.push(i.to_string()); - } - if out.is_indirect { - let operand = self.load_operand(place); - if let OperandValue::Immediate(_) = operand.val { - indirect_outputs.push(operand.immediate()); - } - } else { - output_types.push(place.layout.llvm_type(self.cx)); - } - } - if !indirect_outputs.is_empty() { - indirect_outputs.extend_from_slice(&inputs); - inputs = indirect_outputs; - } - - let clobbers = ia.clobbers.iter().map(|s| format!("~{{{}}}", &s)); - - let all_constraints = ia - .outputs - .iter() - .map(|out| out.constraint.to_string()) - .chain(ia.inputs.iter().map(|s| s.to_string())) - .chain(ext_constraints) - .chain(clobbers) - .collect::>() - .join(","); - - // Depending on how many outputs we have, the return type is different - let num_outputs = output_types.len(); - let output_type = match num_outputs { - 0 => self.type_void(), - 1 => output_types[0], - _ => self.type_struct(&output_types, false), - }; - - let asm = ia.asm.as_str(); - let r = inline_asm_call( - self, - &asm, - &all_constraints, - &inputs, - output_type, - ia.volatile, - ia.alignstack, - ia.dialect, - &[span], - ); - if r.is_none() { - return false; - } - let r = r.unwrap(); - - // Again, based on how many outputs we have - let outputs = ia - .outputs - .iter() - .zip(&outputs) - .filter(|&(o, _)| !o.is_indirect); - for (i, (_, &place)) in outputs.enumerate() { - let v = if num_outputs == 1 { - r - } else { - self.extract_value(r, i as u64) - }; - OperandValue::Immediate(v).store(self, place); - } - - true - } - fn codegen_inline_asm( &mut self, template: &[InlineAsmTemplatePiece], @@ -119,6 +27,7 @@ impl<'a, 'll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { options: rustc_ast::InlineAsmOptions, line_spans: &[Span], _inst: Instance, + dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>, ) { // Collect the types of output operands let mut constraints = vec![]; @@ -260,7 +169,7 @@ impl<'a, 'll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { [ty] => ty, tys => self.type_struct(tys, false), }; - let dialect = LlvmAsmDialect::Att; + let dialect = AsmDialect::Att; let result = inline_asm_call( self, &template_str, @@ -303,7 +212,7 @@ impl<'a, 'll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { } } -impl<'ll, 'tcx> AsmMethods for CodegenCx<'ll, 'tcx> { +impl<'ll, 'tcx> AsmMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn codegen_global_asm( &self, template: &[InlineAsmTemplatePiece], @@ -328,6 +237,7 @@ impl<'ll, 'tcx> AsmMethods for CodegenCx<'ll, 'tcx> { // here unlike normal inline assembly. template_str.push_str(string); } + _ => todo!(), } } } @@ -367,7 +277,7 @@ pub(crate) fn inline_asm_call<'a, 'll, 'tcx>( output: &'ll llvm::Type, volatile: bool, alignstack: bool, - dia: LlvmAsmDialect, + dia: AsmDialect, line_spans: &[Span], ) -> Option<&'ll Value> { let volatile = if volatile { llvm::True } else { llvm::False }; @@ -388,9 +298,10 @@ pub(crate) fn inline_asm_call<'a, 'll, 'tcx>( cons.len(), volatile, alignstack, - llvm::AsmDialect::from_generic(dia), + // llvm::AsmDialect::from_generic(dia), + dia, ); - let call = bx.call(fty, v, inputs, None); + let call = bx.call(fty, None, v, inputs, None); // Store mark in a metadata node so we can map LLVM errors // back to source locations. See #17552. diff --git a/crates/rustc_codegen_nvvm/src/attributes.rs b/crates/rustc_codegen_nvvm/src/attributes.rs index 0652a0b..375b421 100644 --- a/crates/rustc_codegen_nvvm/src/attributes.rs +++ b/crates/rustc_codegen_nvvm/src/attributes.rs @@ -1,7 +1,7 @@ use crate::llvm::{self, AttributePlace::*, Value}; -use rustc_ast::{Attribute, Lit, LitKind}; +use rustc_ast::{ast::MetaItemLit, ast::NestedMetaItem, Attribute, LitKind, AttrKind}; use rustc_attr::{InlineAttr, OptimizeAttr}; -use rustc_middle::{middle::codegen_fn_attrs::CodegenFnAttrFlags, ty}; +use rustc_middle::{middle::codegen_fn_attrs::CodegenFnAttrFlags, ty, ty::Attributes}; use rustc_session::{config::OptLevel, Session}; use rustc_span::{sym, Symbol}; @@ -91,6 +91,7 @@ pub(crate) fn from_fn_attrs<'ll, 'tcx>( } pub struct Symbols { + pub rust_cuda: Symbol, pub nvvm_internal: Symbol, pub kernel: Symbol, pub addrspace: Symbol, @@ -108,32 +109,43 @@ impl NvvmAttributes { pub fn parse<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, attrs: &'tcx [Attribute]) -> Self { let mut nvvm_attrs = Self::default(); - for attr in attrs { - if attr.has_name(cx.symbols.nvvm_internal) { - let args = attr.meta_item_list().unwrap_or_default(); - if let Some(arg) = args.first() { - if arg.has_name(cx.symbols.kernel) { - nvvm_attrs.kernel = true; - } - if arg.has_name(sym::used) { - nvvm_attrs.used = true; - } - if arg.has_name(cx.symbols.addrspace) { - let args = arg.meta_item_list().unwrap_or_default(); - if let Some(arg) = args.first() { - let lit = arg.literal(); - if let Some(Lit { - kind: LitKind::Int(val, _), - .. - }) = lit - { - nvvm_attrs.addrspace = Some(*val as u8); - } else { - panic!(); + for attr in attrs.into_iter() { + match attr.kind { + AttrKind::Normal(ref normal) => { + let s = &normal.item.path.segments; + if s.len() > 1 && s[0].ident.name == cx.symbols.rust_cuda { + // #[rust_cuda ...] + if s.len() != 2 || s[1].ident.name != cx.symbols.nvvm_internal { + // #[rust_cuda::...] but not #[rust_cuda::nvvm_internal] + } + else if let Some(args) = attr.meta_item_list() { + if let Some(arg) = args.first() { + if arg.has_name(cx.symbols.kernel) { + nvvm_attrs.kernel = true; + } + if arg.has_name(sym::used) { + nvvm_attrs.used = true; + } + if arg.has_name(cx.symbols.addrspace) { + let args = arg.meta_item_list().unwrap_or_default(); + if let Some(arg) = args.first() { + let lit = arg.lit(); + if let Some(MetaItemLit { + kind: LitKind::Int(val, _), + .. + }) = lit + { + nvvm_attrs.addrspace = Some(*val as u8); + } else { + panic!(); + } + } + } } } } } + AttrKind::DocComment(..) => {}, // doccomment } } diff --git a/crates/rustc_codegen_nvvm/src/back.rs b/crates/rustc_codegen_nvvm/src/back.rs index 1759616..0b39f8e 100644 --- a/crates/rustc_codegen_nvvm/src/back.rs +++ b/crates/rustc_codegen_nvvm/src/back.rs @@ -1,6 +1,7 @@ use crate::llvm::{self}; use crate::override_fns::define_or_override_fn; use crate::{builder::Builder, context::CodegenCx, lto::ThinBuffer, LlvmMod, NvvmCodegenBackend}; +use cstr::cstr; use libc::{c_char, size_t}; use rustc_codegen_ssa::back::write::{TargetMachineFactoryConfig, TargetMachineFactoryFn}; use rustc_codegen_ssa::traits::{DebugInfoMethods, MiscMethods}; @@ -86,7 +87,7 @@ pub fn target_machine_factory( let ffunction_sections = sess .opts - .debugging_opts + .unstable_opts .function_sections .unwrap_or(sess.target.function_sections); let fdata_sections = ffunction_sections; @@ -98,7 +99,7 @@ pub fn target_machine_factory( let features = CString::new("").unwrap(); let trap_unreachable = sess .opts - .debugging_opts + .unstable_opts .trap_unreachable .unwrap_or(sess.target.trap_unreachable); @@ -285,11 +286,18 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol) -> (ModuleCodegen } // Create the llvm.used and llvm.compiler.used variables. - if !cx.used_statics().borrow().is_empty() { - cx.create_used_variable(); + if !cx.used_statics.borrow().is_empty() { + // cx.create_used_variable(); + cx.create_used_variable_impl( + cstr!("llvm.used").as_ptr(), + &*cx.used_statics.borrow(), + ); } - if !cx.compiler_used_statics().borrow().is_empty() { - cx.create_compiler_used_variable(); + if !cx.compiler_used_statics.borrow().is_empty() { + cx.create_used_variable_impl( + cstr!("llvm.compiler.used").as_ptr(), + &*cx.compiler_used_statics.borrow(), + ); } // Finalize debuginfo diff --git a/crates/rustc_codegen_nvvm/src/builder.rs b/crates/rustc_codegen_nvvm/src/builder.rs index fdb0c9c..0591e2b 100644 --- a/crates/rustc_codegen_nvvm/src/builder.rs +++ b/crates/rustc_codegen_nvvm/src/builder.rs @@ -8,6 +8,7 @@ use libc::{c_char, c_uint}; use rustc_codegen_ssa::common::{AtomicOrdering, IntPredicate, RealPredicate, TypeKind}; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::mir::place::PlaceRef; +use rustc_codegen_ssa::traits::BackendTypes; use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::MemFlags; use rustc_hir::def_id::DefId; @@ -186,10 +187,10 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { unsafe { llvm::LLVMGetInsertBlock(self.llbuilder) } } - fn build_sibling_block(&mut self, name: &str) -> Self { - let llbb = self.append_sibling_block(name); - Self::build(self.cx, llbb) - } + // fn build_sibling_block(&mut self, name: &str) -> Self { + // let llbb = self.append_sibling_block(name); + // Self::build(self.cx, llbb) + // } fn set_span(&mut self, _span: Span) {} @@ -257,9 +258,18 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } } + fn switch_to_block(&mut self, llbb: &'ll BasicBlock) { + *self = Self::build(self.cx, llbb) + } + + fn cleanup_landing_pad(&mut self, _: &'ll Type, _: &'ll Value) -> &'ll Value { + todo!() + } + fn invoke( &mut self, ty: &'ll Type, + fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, llfn: &'ll Value, args: &[&'ll Value], then: &'ll BasicBlock, @@ -267,7 +277,7 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { funclet: Option<&()>, ) -> &'ll Value { trace!("invoke"); - let call = self.call(ty, llfn, args, funclet); + let call = self.call(ty, None, llfn, args, funclet); // exceptions arent a thing, go directly to the `then` block unsafe { llvm::LLVMBuildBr(self.llbuilder, then) }; call @@ -426,7 +436,7 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { let intrinsic = self.get_intrinsic(name); // call actually ignores the ty param for now, we just need it for conformance with nightly api // so give it a dummy type - let res = self.call(self.type_i1(), intrinsic, &[lhs, rhs], None); + let res = self.call(self.type_i1(), None, intrinsic, &[lhs, rhs], None); (self.extract_value(res, 0), self.extract_value(res, 1)) } @@ -448,10 +458,7 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { trace!("Alloca `{:?}`", ty); let mut bx = Builder::with_cx(self.cx); bx.position_at_start(unsafe { llvm::LLVMGetFirstBasicBlock(self.llfn()) }); - bx.dynamic_alloca(ty, align) - } - - fn dynamic_alloca(&mut self, ty: &'ll Type, align: Align) -> &'ll Value { + // bx.dynamic_alloca(ty, align) trace!("Dynamic Alloca `{:?}`", ty); unsafe { let alloca = llvm::LLVMBuildAlloca(self.llbuilder, ty, unnamed()); @@ -460,9 +467,10 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } } - fn array_alloca(&mut self, ty: &'ll Type, len: &'ll Value, align: Align) -> &'ll Value { + fn byte_array_alloca(&mut self, len: Self::Value, align: Align) -> Self::Value { unsafe { - let alloca = llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len, unnamed()); + let alloca = + llvm::LLVMBuildArrayAlloca(self.llbuilder, self.cx().type_i8(), len, unnamed()); llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint); alloca } @@ -510,7 +518,7 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { // self.call(vprintf, &[formatlist, valist], None); let trap = self.get_intrinsic("llvm.trap"); - self.call(ty, trap, &[], None); + self.call(ty, None, trap, &[], None); unsafe { llvm::LLVMBuildLoad(self.llbuilder, ptr, unnamed()) } } @@ -527,13 +535,13 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { load: &'ll Value, scalar: &abi::Scalar, ) { - match scalar.value { + match scalar.primitive() { abi::Int(..) => { if !scalar.is_always_valid(bx) { - bx.range_metadata(load, scalar.valid_range); + bx.range_metadata(load, scalar.valid_range(bx)); } } - abi::Pointer if !scalar.valid_range.contains(0) => { + abi::Pointer if !scalar.valid_range(bx).contains(0) => { bx.nonnull_metadata(load); } _ => {} @@ -563,7 +571,7 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { OperandValue::Immediate(self.to_immediate(llval, place.layout)) } else if let abi::Abi::ScalarPair(ref a, ref b) = place.layout.abi { - let b_offset = a.value.size(self).align_to(b.value.align(self).abi); + let b_offset = a.size(self).align_to(b.align(self).abi); let pair_ty = place.layout.llvm_type(self); let mut load = |i, scalar: &abi::Scalar, align| { @@ -589,27 +597,30 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn write_operand_repeatedly( - mut self, + &mut self, cg_elem: OperandRef<'tcx, &'ll Value>, count: u64, dest: PlaceRef<'tcx, &'ll Value>, - ) -> Self { + ) { trace!("write operand repeatedly"); let zero = self.const_usize(0); let count = self.const_usize(count); - let start = dest.project_index(&mut self, zero).llval; - let end = dest.project_index(&mut self, count).llval; + let start = dest.project_index(self, zero).llval; + let end = dest.project_index(self, count).llval; + + let header_bb = self.append_sibling_block("repeat_loop_header"); + let body_bb = self.append_sibling_block("repeat_loop_body"); + let next_bb = self.append_sibling_block("repeat_loop_next"); - let mut header_bx = self.build_sibling_block("repeat_loop_header"); - let mut body_bx = self.build_sibling_block("repeat_loop_body"); - let next_bx = self.build_sibling_block("repeat_loop_next"); + self.br(header_bb); - self.br(header_bx.llbb()); + let mut header_bx = Self::build(self.cx, header_bb); let current = header_bx.phi(self.val_ty(start), &[start], &[self.llbb()]); let keep_going = header_bx.icmp(IntPredicate::IntNE, current, end); - header_bx.cond_br(keep_going, body_bx.llbb(), next_bx.llbb()); + header_bx.cond_br(keep_going, body_bb, next_bb); + let mut body_bx = Self::build(self.cx, body_bb); let align = dest .align .restrict_for_offset(dest.layout.field(self.cx(), 0).size); @@ -623,10 +634,10 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { current, &[self.const_usize(1)], ); - body_bx.br(header_bx.llbb()); - header_bx.add_incoming_to_phi(current, next, body_bx.llbb()); + body_bx.br(header_bb); + header_bx.add_incoming_to_phi(current, next, body_bb); - next_bx + *self = Self::build(self.cx, next_bb); } fn range_metadata(&mut self, load: &'ll Value, range: WrappingRange) { @@ -656,15 +667,6 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } } - fn type_metadata(&mut self, _function: &'ll Value, _typeid: String) { - // LLVM CFI doesnt make sense on the GPU - } - - fn typeid_metadata(&mut self, _typeid: String) -> Self::Value { - // LLVM CFI doesnt make sense on the GPU - self.const_i32(0) - } - fn store(&mut self, val: &'ll Value, ptr: &'ll Value, align: Align) -> &'ll Value { trace!("Store val `{:?}` into ptr `{:?}`", val, ptr); self.store_with_flags(val, ptr, align, MemFlags::empty()) @@ -773,18 +775,20 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { unsafe { llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty, unnamed()) } } - fn fptoui_sat(&mut self, _val: &'ll Value, _dest_ty: &'ll Type) -> Option<&'ll Value> { - None + fn fptoui_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { + trace!("fptoui_sat {:?} to {:?}", val, dest_ty); + // unsafe { llvm::LLVMBuildFPToUISat(self.llbuilder, val, dest_ty, unnamed()) } + // todo!(); + unsafe { llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty, unnamed()) } } - fn fptosi_sat(&mut self, _val: &'ll Value, _dest_ty: &'ll Type) -> Option<&'ll Value> { - None + fn fptosi_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { + // trace!("fptosi_sat {:?} to {:?}", val, dest_ty); + // unsafe { llvm::LLVMBuildFPToSISat(self.llbuilder, val, dest_ty, unnamed()) } + // todo!(); + unsafe { llvm::LLVMBuildFPToSI(self.llbuilder, val, dest_ty, unnamed()) } } - // fn fptosui_may_trap(&self, val: &'ll Value, dest_ty: &'ll Type) -> bool { - // false - // } - fn fptoui(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { trace!("fptoui {:?} to {:?}", val, dest_ty); unsafe { llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty, unnamed()) } @@ -990,26 +994,15 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } } - fn landing_pad( - &mut self, - _ty: &'ll Type, - _pers_fn: &'ll Value, - _num_clauses: usize, - ) -> &'ll Value { - todo!(); - } - - fn set_cleanup(&mut self, _landing_pad: &'ll Value) {} - - fn resume(&mut self, _exn: &'ll Value) -> &'ll Value { + fn resume(&mut self, _exn: &'ll Value) { self.unsupported("resumes"); } fn cleanup_pad(&mut self, _parent: Option<&'ll Value>, _args: &[&'ll Value]) {} - fn cleanup_ret(&mut self, _funclet: &(), _unwind: Option<&'ll BasicBlock>) -> &'ll Value { + fn cleanup_ret(&mut self, _funclet: &(), _unwind: Option<&'ll BasicBlock>) { // rustc doesnt actually use this value ;) - self.const_bool(false) + self.const_bool(false); } fn catch_pad(&mut self, _parent: &'ll Value, _args: &[&'ll Value]) {} @@ -1018,15 +1011,11 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { &mut self, _parent: Option<&'ll Value>, _unwind: Option<&'ll BasicBlock>, - _num_handlers: usize, + _handlers: &[&'ll BasicBlock], ) -> &'ll Value { self.unsupported("catch switches"); } - fn add_handler(&mut self, _catch_switch: &'ll Value, _handler: &'ll BasicBlock) { - todo!(); - } - fn set_personality_fn(&mut self, _personality: &'ll Value) {} // Atomic Operations @@ -1093,6 +1082,7 @@ impl<'ll, 'tcx, 'a> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { fn call( &mut self, _: &'ll Type, + _fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, llfn: &'ll Value, args: &[&'ll Value], _funclet: Option<&()>, @@ -1268,6 +1258,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { let ptr = self.pointercast(ptr, self.cx.type_i8p()); self.call( self.type_i1(), + None, lifetime_intrinsic, &[self.cx.const_u64(size), ptr], None, diff --git a/crates/rustc_codegen_nvvm/src/const_ty.rs b/crates/rustc_codegen_nvvm/src/const_ty.rs index 96d6dcb..b5977b7 100644 --- a/crates/rustc_codegen_nvvm/src/const_ty.rs +++ b/crates/rustc_codegen_nvvm/src/const_ty.rs @@ -7,7 +7,7 @@ use rustc_codegen_ssa::{ mir::place::PlaceRef, traits::{BaseTypeMethods, ConstMethods, DerivedTypeMethods, MiscMethods, StaticMethods}, }; -use rustc_middle::mir::interpret::{Allocation, GlobalAlloc, Scalar}; +use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar}; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{layout::TyAndLayout, ScalarInt}; use rustc_span::Symbol; @@ -15,8 +15,8 @@ use rustc_target::abi::{self, AddressSpace, HasDataLayout, Size}; use tracing::trace; impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { - fn const_data_from_alloc(&self, alloc: &Allocation) -> &'ll Value { - const_alloc_to_llvm(self, alloc) + fn const_data_from_alloc(&self, alloc: ConstAllocation<'tcx>) -> &'ll Value { + const_alloc_to_llvm(self, &alloc) } fn const_null(&self, t: &'ll Type) -> &'ll Value { @@ -46,6 +46,10 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { self.const_uint(self.type_i1(), val as u64) } + fn const_i16(&self, i: i16) -> &'ll Value { + self.const_int(self.type_i16(), i as i64) + } + fn const_i32(&self, i: i32) -> &'ll Value { self.const_int(self.type_i32(), i as i64) } @@ -70,11 +74,35 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { unsafe { llvm::LLVMConstReal(t, val) } } - fn const_str(&self, s: Symbol) -> (&'ll Value, &'ll Value) { - let len = s.as_str().len(); - let val = self.const_cstr(s, false); - let ty = self.type_ptr_to(self.layout_of(self.tcx.types.str_).llvm_type(self)); - let cs = unsafe { llvm::LLVMConstPointerCast(val, ty) }; + fn const_str(&self, s: &str) -> (&'ll Value, &'ll Value) { + let str_global = *self + .const_str_cache + .borrow_mut() + .raw_entry_mut() + .from_key(s) + .or_insert_with(|| { + let sc = self.const_bytes(s.as_bytes()); + let sym = self.generate_local_symbol_name("str"); + let g = self + .define_global(&sym, self.val_ty(sc), AddressSpace::DATA) + .unwrap(); + // TODO: What replacement is there now for bug!? + // .unwrap_or_else(|| { + // bug!("symbol `{}` is already defined", sym); + // }); + unsafe { + llvm::LLVMSetInitializer(g, sc); + llvm::LLVMSetGlobalConstant(g, True); + llvm::LLVMRustSetLinkage(g, llvm::Linkage::InternalLinkage); + } + (s.to_owned(), g) + }) + .1; + let len = s.len(); + let cs = self.const_ptrcast( + str_global, + self.type_ptr_to(self.layout_of(self.tcx.types.str_).llvm_type(self)), + ); (cs, self.const_usize(len as u64)) } @@ -113,17 +141,13 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { let bitsize = if layout.is_bool() { 1 } else { - layout.value.size(self).bits() + layout.size(self).bits() }; - let val = match cv { - Scalar::Int(ScalarInt::ZST) => { - assert_eq!(0, layout.value.size(self).bytes()); - self.const_undef(self.type_ix(0)) - } + match cv { Scalar::Int(int) => { - let data = int.assert_bits(layout.value.size(self)); + let data = int.assert_bits(layout.size(self)); let llval = self.const_uint_big(self.type_ix(bitsize), data); - if layout.value == Pointer { + if layout.primitive() == Pointer { unsafe { llvm::LLVMConstIntToPtr(llval, llty) } } else { self.const_bitcast(llval, llty) @@ -133,7 +157,8 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { let (alloc_id, offset) = ptr.into_parts(); let (base_addr, base_addr_space) = match self.tcx.global_alloc(alloc_id) { GlobalAlloc::Memory(alloc) => { - let init = const_alloc_to_llvm(self, alloc); + let init = const_alloc_to_llvm(self, &alloc); + let alloc = alloc.inner(); let value = match alloc.mutability { Mutability::Mut => self.static_addr_of_mut(init, alloc.align, None), _ => self.static_addr_of(init, alloc.align, None), @@ -147,14 +172,19 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { self.get_fn_addr(fn_instance.polymorphize(self.tcx)), self.data_layout().instruction_address_space, ), + GlobalAlloc::VTable(ty, trait_ref) => { + let alloc = self + .tcx + .global_alloc(self.tcx.vtable_allocation((ty, trait_ref))) + .unwrap_memory(); + let init = const_alloc_to_llvm(self, &alloc); + let value = self.static_addr_of(init, alloc.inner().align, None); + (value, AddressSpace::DATA) + } GlobalAlloc::Static(def_id) => { assert!(self.tcx.is_static(def_id)); assert!(!self.tcx.is_thread_local_static(def_id)); - let val = self.get_static(def_id); - let addrspace = unsafe { - llvm::LLVMGetPointerAddressSpace(llvm::LLVMRustGetValueType(val)) - }; - (self.get_static(def_id), AddressSpace(addrspace)) + (self.get_static(def_id), AddressSpace::DATA) } }; let llval = unsafe { @@ -164,41 +194,29 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { 1, ) }; - - if layout.value != Pointer { + if layout.primitive() != Pointer { unsafe { llvm::LLVMConstPtrToInt(llval, llty) } } else { - if base_addr_space != AddressSpace::DATA { - unsafe { - let element = llvm::LLVMGetElementType(llty); - llty = self.type_ptr_to_ext(element, base_addr_space); - } - } self.const_bitcast(llval, llty) } } - }; - - trace!("...Scalar to backend: `{:?}`", val); - trace!("{:?}", std::backtrace::Backtrace::force_capture()); - - val + } } fn from_const_alloc( &self, layout: TyAndLayout<'tcx>, - alloc: &Allocation, + alloc: ConstAllocation<'tcx>, offset: Size, ) -> PlaceRef<'tcx, &'ll Value> { - assert_eq!(alloc.align, layout.align.abi); + assert_eq!(alloc.0 .0.align, layout.align.abi); let llty = self.type_ptr_to(layout.llvm_type(self)); let llval = if layout.size == Size::ZERO { - let llval = self.const_usize(alloc.align.bytes()); + let llval = self.const_usize(alloc.0 .0.align.bytes()); unsafe { llvm::LLVMConstIntToPtr(llval, llty) } } else { - let init = const_alloc_to_llvm(self, alloc); - let base_addr = self.static_addr_of(init, alloc.align, None); + let init = const_alloc_to_llvm(self, &alloc); + let base_addr = self.static_addr_of(init, alloc.0 .0.align, None); let llval = unsafe { llvm::LLVMConstInBoundsGEP( diff --git a/crates/rustc_codegen_nvvm/src/consts.rs b/crates/rustc_codegen_nvvm/src/consts.rs index 82378af..bb6ceeb 100644 --- a/crates/rustc_codegen_nvvm/src/consts.rs +++ b/crates/rustc_codegen_nvvm/src/consts.rs @@ -13,7 +13,7 @@ use rustc_middle::mir::interpret::{ use rustc_middle::{ bug, middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}, - mir::interpret::{InitChunk, Scalar as InterpScalar}, + mir::interpret::{ConstAllocation, InitChunk, Scalar as InterpScalar}, mir::mono::{Linkage, MonoItem}, span_bug, ty::{self, layout::LayoutOf, Instance, Ty}, @@ -42,39 +42,42 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { bytes_in_context(self.llcx, bytes) } - pub(crate) fn const_cstr(&self, s: Symbol, null_terminated: bool) -> &'ll Value { - trace!("Const cstr for symbol `{:?}`", s); - unsafe { - if let Some(&llval) = self.const_cstr_cache.borrow().get(&s) { - return llval; - } - - let s_str = s.as_str(); - let sc = llvm::LLVMConstStringInContext( - self.llcx, - s_str.as_ptr() as *const c_char, - s_str.len() as c_uint, - !null_terminated as Bool, - ); - let sym = self.generate_local_symbol_name("str"); - let g = self - .define_global(&sym[..], self.val_ty(sc), AddressSpace::DATA) - .unwrap_or_else(|| { - bug!("symbol `{}` is already defined", sym); - }); - llvm::LLVMSetInitializer(g, sc); - llvm::LLVMSetGlobalConstant(g, True); - llvm::LLVMRustSetLinkage(g, llvm::Linkage::InternalLinkage); - - self.const_cstr_cache.borrow_mut().insert(s, g); - g - } - } + // pub(crate) fn const_cstr(&self, s_str: &str, null_terminated: bool) -> &'ll Value { + // trace!("Const cstr for symbol `{:?}`", s_str); + // unsafe { + // if let Some(&llval) = self.const_str_cache.borrow().get(&s) { + // return llval; + // } + + // let sc = llvm::LLVMConstStringInContext( + // self.llcx, + // s_str.as_ptr() as *const c_char, + // s_str.len() as c_uint, + // !null_terminated as Bool, + // ); + // let sym = self.generate_local_symbol_name("str"); + // let g = self + // .define_global(&sym[..], self.val_ty(sc), AddressSpace::DATA) + // .unwrap_or_else(|| { + // bug!("symbol `{}` is already defined", sym); + // }); + // llvm::LLVMSetInitializer(g, sc); + // llvm::LLVMSetGlobalConstant(g, True); + // llvm::LLVMRustSetLinkage(g, llvm::Linkage::InternalLinkage); + + // self.const_cstr_cache.borrow_mut().insert(s, g); + // g + // } + // } } -pub(crate) fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll Value { +pub(crate) fn const_alloc_to_llvm<'ll>( + cx: &CodegenCx<'ll, '_>, + alloc: &ConstAllocation<'_>, +) -> &'ll Value { trace!("Const alloc to llvm"); - let mut llvals = Vec::with_capacity(alloc.relocations().len() + 1); + let alloc = alloc.inner(); + let mut llvals = Vec::with_capacity(alloc.provenance().ptrs().len() + 1); let dl = cx.data_layout(); let pointer_size = dl.pointer_size.bytes() as usize; @@ -86,9 +89,7 @@ pub(crate) fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: &Allocati alloc: &'a Allocation, range: Range, ) { - let mut chunks = alloc - .init_mask() - .range_as_init_chunks(Size::from_bytes(range.start), Size::from_bytes(range.end)); + let chunks = alloc.init_mask().range_as_init_chunks(range.clone().into()); let chunk_to_llval = move |chunk| match chunk { InitChunk::Init(range) => { @@ -104,37 +105,22 @@ pub(crate) fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: &Allocati // Generating partially-uninit consts inhibits optimizations, so it is disabled by default. // See https://github.com/rust-lang/rust/issues/84565. - let allow_partially_uninit = match cx - .sess() - .opts - .debugging_opts - .partially_uninit_const_threshold - { - Some(max) => range.len() <= max, - None => false, - }; + let max = cx.sess().opts.unstable_opts.uninit_const_chunk_threshold; + + let allow_uninit_chunks = chunks.clone().take(max.saturating_add(1)).count() <= max; - if allow_partially_uninit { + if allow_uninit_chunks { llvals.extend(chunks.map(chunk_to_llval)); } else { - let llval = match (chunks.next(), chunks.next()) { - (Some(chunk), None) => { - // exactly one chunk, either fully init or fully uninit - chunk_to_llval(chunk) - } - _ => { - // partially uninit, codegen as if it was initialized - // (using some arbitrary value for uninit bytes) - let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(range); - cx.const_bytes(bytes) - } - }; - llvals.push(llval); + // If this allocation contains any uninit bytes, codegen as if it was initialized + // (using some arbitrary value for uninit bytes). + let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(range); + llvals.push(cx.const_bytes(bytes)); } } let mut next_offset = 0; - for &(offset, alloc_id) in alloc.relocations().iter() { + for &(offset, alloc_id) in alloc.provenance().ptrs().iter() { let offset = offset.bytes(); assert_eq!(offset as usize as u64, offset); let offset = offset as usize; @@ -156,7 +142,9 @@ pub(crate) fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: &Allocati let address_space = match cx.tcx.global_alloc(alloc_id) { GlobalAlloc::Function(..) => cx.data_layout().instruction_address_space, - GlobalAlloc::Static(..) | GlobalAlloc::Memory(..) => AddressSpace::DATA, + GlobalAlloc::Static(..) | GlobalAlloc::Memory(..) | GlobalAlloc::VTable(..) => { + AddressSpace::DATA + } }; llvals.push(cx.scalar_to_backend( @@ -164,9 +152,9 @@ pub(crate) fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: &Allocati Pointer::new(alloc_id, Size::from_bytes(ptr_offset)), &cx.tcx, ), - Scalar { + Scalar::Initialized { value: Primitive::Pointer, - valid_range: WrappingRange { start: 0, end: !0 }, + valid_range: WrappingRange::full(dl.pointer_size), }, cx.type_i8p_ext(address_space), )); @@ -186,9 +174,9 @@ pub(crate) fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: &Allocati pub(crate) fn codegen_static_initializer<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, def_id: DefId, -) -> Result<(&'ll Value, &'tcx Allocation), ErrorHandled> { +) -> Result<(&'ll Value, ConstAllocation<'tcx>), ErrorHandled> { let alloc = cx.tcx.eval_static_initializer(def_id)?; - Ok((const_alloc_to_llvm(cx, alloc), alloc)) + Ok((const_alloc_to_llvm(cx, &alloc), alloc)) } pub(crate) fn linkage_to_llvm(linkage: Linkage) -> llvm::Linkage { diff --git a/crates/rustc_codegen_nvvm/src/context.rs b/crates/rustc_codegen_nvvm/src/context.rs index 49ea650..28ef572 100644 --- a/crates/rustc_codegen_nvvm/src/context.rs +++ b/crates/rustc_codegen_nvvm/src/context.rs @@ -1,11 +1,12 @@ use crate::abi::FnAbiLlvmExt; use crate::attributes::{self, NvvmAttributes, Symbols}; use crate::debug_info::{self, compile_unit_metadata, CrateDebugContext}; +use crate::llvm::MetadataType::MD_kcfi_type; use crate::llvm::{self, BasicBlock, Type, Value}; use crate::{target, LlvmMod}; use nvvm::NvvmOption; use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeMethods, CoverageInfoMethods, MiscMethods}; -use rustc_codegen_ssa::traits::{ConstMethods, DerivedTypeMethods}; +use rustc_codegen_ssa::traits::{ConstMethods, DerivedTypeMethods, TypeMembershipMethods}; use rustc_data_structures::base_n; use rustc_hash::FxHashMap; use rustc_middle::dep_graph::DepContext; @@ -13,7 +14,7 @@ use rustc_middle::ty::layout::{ FnAbiError, FnAbiOf, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, TyAndLayout, }; use rustc_middle::ty::layout::{FnAbiOfHelpers, LayoutOfHelpers}; -use rustc_middle::ty::{Ty, TypeFoldable}; +use rustc_middle::ty::{Ty, TypeFoldable, TypeVisitable}; use rustc_middle::{bug, span_bug, ty}; use rustc_middle::{ mir::mono::CodegenUnit, @@ -31,6 +32,7 @@ use std::cell::{Cell, RefCell}; use std::ffi::CStr; use std::hash::BuildHasherDefault; use std::os::raw::c_char; +use std::os::raw::c_uint; use std::path::PathBuf; use std::ptr::null; use std::str::FromStr; @@ -49,7 +51,7 @@ pub(crate) struct CodegenCx<'ll, 'tcx> { /// A cache of the generated vtables for trait objects pub vtables: RefCell, Option>), &'ll Value>>, /// A cache of constant strings and their values - pub const_cstr_cache: RefCell>, + pub const_str_cache: RefCell>, /// A map of functions which have parameters at specific indices replaced with an int-remapped type. /// such as i128 --> <2 x i64> #[allow(clippy::type_complexity)] @@ -137,7 +139,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { codegen_unit, instances: Default::default(), vtables: Default::default(), - const_cstr_cache: Default::default(), + const_str_cache: Default::default(), remapped_integer_args: Default::default(), const_globals: Default::default(), statics_to_rauw: RefCell::new(Vec::new()), @@ -154,10 +156,11 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { BuildHasherDefault::default(), )), local_gen_sym_counter: Cell::new(0), - nvptx_data_layout: TargetDataLayout::parse(&target::target()).unwrap(), + nvptx_data_layout: target::target().parse_data_layout().unwrap_or_default(), nvptx_target: target::target(), eh_personality, symbols: Symbols { + rust_cuda: Symbol::intern("rust_cuda"), nvvm_internal: Symbol::intern("nvvm_internal"), kernel: Symbol::intern("kernel"), addrspace: Symbol::intern("addrspace"), @@ -179,7 +182,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { self.fatal(&format!("{} is unsupported", thing)) } - fn create_used_variable_impl(&self, name: *const c_char, values: &[&'ll Value]) { + pub fn create_used_variable_impl(&self, name: *const c_char, values: &[&'ll Value]) { let section = "llvm.metadata\0".as_ptr().cast(); let array = self.const_array(self.type_ptr_to(self.type_i8()), values); @@ -232,21 +235,6 @@ impl<'ll, 'tcx> MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { self.codegen_unit } - fn used_statics(&self) -> &RefCell> { - &self.used_statics - } - - fn create_used_variable(&self) { - self.create_used_variable_impl("llvm.used\0".as_ptr().cast(), &*self.used_statics.borrow()); - } - - fn create_compiler_used_variable(&self) { - self.create_used_variable_impl( - "llvm.compiler.used\0".as_ptr().cast(), - &*self.compiler_used_statics.borrow(), - ); - } - fn declare_c_main(&self, _fn_type: Self::Type) -> Option { // no point for gpu kernels None @@ -256,10 +244,6 @@ impl<'ll, 'tcx> MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { // no point if we are running on the gpu ;) } - fn compiler_used_statics(&self) -> &RefCell> { - &self.compiler_used_statics - } - fn set_frame_pointer_type(&self, _llfn: Self::Function) {} } @@ -268,8 +252,8 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { pub fn static_addrspace(&self, instance: Instance<'tcx>) -> AddressSpace { let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all()); let is_mutable = self.tcx().is_mutable_static(instance.def_id()); - let attrs = self.tcx.get_attrs(instance.def_id()); - let nvvm_attrs = NvvmAttributes::parse(self, attrs); + let attrs = self.tcx.get_attrs_unchecked(instance.def_id()); + let nvvm_attrs = NvvmAttributes::parse(self, &attrs); if let Some(addr) = nvvm_attrs.addrspace { return AddressSpace(addr as u32); @@ -658,3 +642,27 @@ impl<'ll, 'tcx> CoverageInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { todo!() } } + +impl<'ll, 'tcx> TypeMembershipMethods<'tcx> for CodegenCx<'ll, 'tcx> { + fn set_type_metadata(&self, function: &'ll Value, typeid: String) { + let typeid_metadata = self.typeid_metadata(typeid); + let v = [self.const_usize(0), typeid_metadata]; + unsafe { + llvm::LLVMSetMetadata( + function, + llvm::MetadataType::MD_type as c_uint, + llvm::LLVMMDNodeInContext(self.llcx, v.as_ptr(), v.len() as c_uint), + ) + } + } + + fn typeid_metadata(&self, typeid: String) -> &'ll Value { + unsafe { + llvm::LLVMMDStringInContext( + self.llcx, + typeid.as_ptr() as *const c_char, + typeid.len() as c_uint, + ) + } + } +} diff --git a/crates/rustc_codegen_nvvm/src/debug_info/create_scope_map.rs b/crates/rustc_codegen_nvvm/src/debug_info/create_scope_map.rs index 0477f32..d275106 100644 --- a/crates/rustc_codegen_nvvm/src/debug_info/create_scope_map.rs +++ b/crates/rustc_codegen_nvvm/src/debug_info/create_scope_map.rs @@ -16,23 +16,29 @@ use super::metadata::file_metadata; use super::util::DIB; /// Produces DIScope DIEs for each MIR Scope which has variables defined in it. +// FIXME(eddyb) almost all of this should be in `rustc_codegen_ssa::mir::debuginfo`. pub(crate) fn compute_mir_scopes<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>, mir: &Body<'tcx>, - fn_dbg_scope: &'ll DIScope, debug_context: &mut FunctionDebugContext<&'ll DIScope, &'ll DILocation>, ) { - // Find all the scopes with variables defined in them. - let mut has_variables = BitSet::new_empty(mir.source_scopes.len()); - - // Only consider variables when they're going to be emitted. - if cx.sess().opts.debuginfo == DebugInfo::Full { + // Find all scopes with variables defined in them. + let variables = if cx.sess().opts.debuginfo == DebugInfo::Full { + let mut vars = BitSet::new_empty(mir.source_scopes.len()); + // FIXME(eddyb) take into account that arguments always have debuginfo, + // irrespective of their name (assuming full debuginfo is enabled). + // NOTE(eddyb) actually, on second thought, those are always in the + // function scope, which always exists. for var_debug_info in &mir.var_debug_info { - has_variables.insert(var_debug_info.source_info.scope); + vars.insert(var_debug_info.source_info.scope); } - } - + Some(vars) + } else { + // Nothing to emit, of course. + None + }; + let mut instantiated = BitSet::new_empty(mir.source_scopes.len()); // Instantiate all scopes. for idx in 0..mir.source_scopes.len() { let scope = SourceScope::new(idx); @@ -40,24 +46,25 @@ pub(crate) fn compute_mir_scopes<'ll, 'tcx>( cx, instance, mir, - fn_dbg_scope, - &has_variables, + &variables, debug_context, + &mut instantiated, scope, ); } + assert!(instantiated.count() == mir.source_scopes.len()); } fn make_mir_scope<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>, mir: &Body<'tcx>, - fn_dbg_scope: &'ll DIScope, - has_variables: &BitSet, + variables: &Option>, debug_context: &mut FunctionDebugContext<&'ll DIScope, &'ll DILocation>, + instantiated: &mut BitSet, scope: SourceScope, ) { - if debug_context.scopes[scope].dbg_scope.is_some() { + if instantiated.contains(scope) { return; } @@ -67,9 +74,9 @@ fn make_mir_scope<'ll, 'tcx>( cx, instance, mir, - fn_dbg_scope, - has_variables, + variables, debug_context, + instantiated, parent, ); debug_context.scopes[parent] @@ -77,18 +84,19 @@ fn make_mir_scope<'ll, 'tcx>( // The root is the function itself. let loc = cx.lookup_debug_loc(mir.span.lo()); debug_context.scopes[scope] = DebugScope { - dbg_scope: Some(fn_dbg_scope), - inlined_at: None, file_start_pos: loc.file.start_pos, file_end_pos: loc.file.end_pos, + ..debug_context.scopes[scope] }; + instantiated.insert(scope); return; }; - if !has_variables.contains(scope) && scope_data.inlined.is_none() { + if let Some(vars) = variables && !vars.contains(scope) && scope_data.inlined.is_none() { // Do not create a DIScope if there are no variables defined in this // MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat. debug_context.scopes[scope] = parent_scope; + instantiated.insert(scope); return; } @@ -97,6 +105,8 @@ fn make_mir_scope<'ll, 'tcx>( let dbg_scope = match scope_data.inlined { Some((callee, _)) => { + // FIXME(eddyb) this would be `self.monomorphize(&callee)` + // if this is moved to `rustc_codegen_ssa::mir::debuginfo`. let callee = cx.tcx.subst_and_normalize_erasing_regions( instance.substs, ty::ParamEnv::reveal_all(), @@ -108,7 +118,7 @@ fn make_mir_scope<'ll, 'tcx>( None => unsafe { llvm::LLVMRustDIBuilderCreateLexicalBlock( DIB(cx), - parent_scope.dbg_scope.unwrap(), + parent_scope.dbg_scope, file_metadata, loc.line, loc.col, @@ -117,14 +127,17 @@ fn make_mir_scope<'ll, 'tcx>( }; let inlined_at = scope_data.inlined.map(|(_, callsite_span)| { + // FIXME(eddyb) this doesn't account for the macro-related + // `Span` fixups that `rustc_codegen_ssa::mir::debuginfo` does. let callsite_scope = parent_scope.adjust_dbg_scope_for_span(cx, callsite_span); cx.dbg_loc(callsite_scope, parent_scope.inlined_at, callsite_span) }); debug_context.scopes[scope] = DebugScope { - dbg_scope: Some(dbg_scope), + dbg_scope, inlined_at: inlined_at.or(parent_scope.inlined_at), file_start_pos: loc.file.start_pos, file_end_pos: loc.file.end_pos, }; + instantiated.insert(scope); } diff --git a/crates/rustc_codegen_nvvm/src/debug_info/metadata.rs b/crates/rustc_codegen_nvvm/src/debug_info/metadata.rs index 127946f..586aaf7 100644 --- a/crates/rustc_codegen_nvvm/src/debug_info/metadata.rs +++ b/crates/rustc_codegen_nvvm/src/debug_info/metadata.rs @@ -13,7 +13,6 @@ use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::Instance; use rustc_middle::ty::{self, AdtKind, GeneratorSubsts, ParamEnv, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; -use rustc_query_system::ich::NodeIdHashingMode; use rustc_session::config::{self, DebugInfo}; use rustc_span::symbol::Symbol; use rustc_span::{self, SourceFile, SourceFileHash, Span}; @@ -171,7 +170,7 @@ impl<'ll, 'tcx> TypeMap<'ll, 'tcx> { /// This function is used to remove the temporary metadata /// mapping after we've computed the actual metadata. fn remove_type(&mut self, type_: Ty<'tcx>) { - if self.type_to_metadata.remove(type_).is_none() { + if self.type_to_metadata.remove(&type_).is_none() { bug!("type metadata `Ty` '{}' is not in the `TypeMap`!", type_); } } @@ -226,11 +225,13 @@ impl<'ll, 'tcx> TypeMap<'ll, 'tcx> { // The hasher we are using to generate the UniqueTypeId. We want // something that provides more than the 64 bits of the DefaultHasher. let mut hasher = StableHasher::new(); - let mut hcx = cx.tcx.create_stable_hashing_context(); + let type_ = cx.tcx.erase_regions(type_); - hcx.while_hashing_spans(false, |hcx| { - hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { + cx.tcx.with_stable_hashing_context(|mut hcx| { + hcx.while_hashing_spans(false, |hcx| { + // hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { type_.hash_stable(hcx, &mut hasher); + // }); }); }); let unique_type_id = hasher.finish::().to_hex(); @@ -501,7 +502,7 @@ fn subroutine_type_metadata<'ll, 'tcx>( signature .inputs() .iter() - .map(|argument_type| Some(type_metadata(cx, argument_type, span))), + .map(|argument_type| Some(type_metadata(cx, *argument_type, span))), ) .collect(); @@ -537,7 +538,7 @@ fn trait_pointer_metadata<'ll, 'tcx>( let (containing_scope, trait_type_name) = match trait_object_type { Some(trait_object_type) => match trait_object_type.kind() { ty::Adt(def, _) => ( - Some(get_namespace_for_item(cx, def.did)), + Some(get_namespace_for_item(cx, def.did())), compute_debuginfo_type_name(cx.tcx, trait_object_type, false), ), ty::RawPtr(_) | ty::Ref(..) => ( @@ -789,12 +790,12 @@ pub(crate) fn type_metadata<'ll, 'tcx>( prepare_union_metadata(cx, t, unique_type_id, usage_site_span).finalize(cx) } AdtKind::Enum => { - prepare_enum_metadata(cx, t, def.did, unique_type_id, usage_site_span, vec![]) + prepare_enum_metadata(cx, t, def.did(), unique_type_id, usage_site_span, vec![]) .finalize(cx) } }, ty::Tuple(elements) => { - let tys: Vec<_> = elements.iter().map(|k| k.expect_ty()).collect(); + let tys: Vec<_> = elements.iter().collect(); prepare_tuple_metadata( cx, t, @@ -1136,10 +1137,10 @@ impl<'ll, 'tcx> StructMemberDescriptionFactory<'tcx> { .iter() .enumerate() .map(|(i, f)| { - let name = if self.variant.ctor_kind == CtorKind::Fn { + let name = if self.variant.ctor_kind() == Some(CtorKind::Fn) { format!("__{}", i) } else { - f.ident.to_string() + f.ident(cx.tcx).to_string() }; let field = layout.field(cx, i); MemberDescription { @@ -1166,7 +1167,7 @@ fn prepare_struct_metadata<'ll, 'tcx>( let struct_name = compute_debuginfo_type_name(cx.tcx, struct_type, false); let (struct_def_id, variant) = match struct_type.kind() { - ty::Adt(def, _) => (def.did, def.non_enum_variant()), + ty::Adt(def, _) => (def.did(), def.non_enum_variant()), _ => bug!("prepare_struct_metadata on a non-ADT"), }; @@ -1323,7 +1324,7 @@ impl<'tcx> UnionMemberDescriptionFactory<'tcx> { .map(|(i, f)| { let field = self.layout.field(cx, i); MemberDescription { - name: f.ident.to_string(), + name: f.ident(cx.tcx).to_string(), type_metadata: type_metadata(cx, field.ty, self.span), offset: Size::ZERO, size: field.size, @@ -1346,7 +1347,7 @@ fn prepare_union_metadata<'ll, 'tcx>( let union_name = compute_debuginfo_type_name(cx.tcx, union_type, false); let (union_def_id, variant) = match union_type.kind() { - ty::Adt(def, _) => (def.did, def.non_enum_variant()), + ty::Adt(def, _) => (def.did(), def.non_enum_variant()), _ => bug!("prepare_union_metadata on a non-ADT"), }; @@ -1445,7 +1446,7 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> { }; let variant_info_for = |index: VariantIdx| match *self.enum_type.kind() { - ty::Adt(adt, _) => VariantInfo::Adt(&adt.variants[index]), + ty::Adt(adt, _) => VariantInfo::Adt(&adt.variants()[index]), ty::Generator(def_id, _, _) => { let (generator_layout, generator_saved_local_names) = generator_variant_info_data.as_ref().unwrap(); @@ -1465,7 +1466,7 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> { match self.layout.variants { Variants::Single { index } => { if let ty::Adt(adt, _) = self.enum_type.kind() { - if adt.variants.is_empty() { + if adt.variants().is_empty() { return vec![]; } } @@ -1484,7 +1485,7 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> { Some(&self.common_members), ); vec![MemberDescription { - name: variant_info.variant_name(), + name: variant_info.variant_name(cx), type_metadata: variant_type_metadata, offset: Size::ZERO, size: self.layout.size, @@ -1517,7 +1518,7 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> { ); MemberDescription { - name: variant_info.variant_name(), + name: variant_info.variant_name(cx), type_metadata: variant_type_metadata, offset: Size::ZERO, size: self.layout.size, @@ -1539,20 +1540,21 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> { TagEncoding::Niche { ref niche_variants, niche_start, - dataful_variant, + untagged_variant, + .. }, ref tag, ref variants, .. } => { let calculate_niche_value = |i: VariantIdx| { - if i == dataful_variant { + if i == untagged_variant { None } else { let value = (i.as_u32() as u128) .wrapping_sub(niche_variants.start().as_u32() as u128) .wrapping_add(niche_start); - let value = tag.value.size(cx).truncate(value); + let value = tag.size(cx).truncate(value); // NOTE(eddyb) do *NOT* remove this assert, until // we pass the full 128-bit value to LLVM, otherwise // truncation will be silent and remain undetected. @@ -1588,7 +1590,7 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> { let niche_value = calculate_niche_value(i); MemberDescription { - name: variant_info.variant_name(), + name: variant_info.variant_name(cx), type_metadata: variant_type_metadata, offset: Size::ZERO, size: self.layout.size, @@ -1649,18 +1651,18 @@ enum VariantInfo<'a, 'tcx> { } impl<'tcx> VariantInfo<'_, 'tcx> { - fn map_struct_name(&self, f: impl FnOnce(&str) -> R) -> R { + fn map_struct_name(&self, f: impl FnOnce(&str) -> R, cx: &CodegenCx<'_, 'tcx>) -> R { match self { - VariantInfo::Adt(variant) => f(&variant.ident.as_str()), + VariantInfo::Adt(variant) => f(&variant.ident(cx.tcx).as_str()), VariantInfo::Generator { variant_index, .. } => { f(&GeneratorSubsts::variant_name(*variant_index)) } } } - fn variant_name(&self) -> String { + fn variant_name(&self, cx: &CodegenCx<'_, 'tcx>) -> String { match self { - VariantInfo::Adt(variant) => variant.ident.to_string(), + VariantInfo::Adt(variant) => variant.ident(cx.tcx).to_string(), VariantInfo::Generator { variant_index, .. } => { // Since GDB currently prints out the raw discriminant along // with every variant, make each variant name be just the value @@ -1671,10 +1673,10 @@ impl<'tcx> VariantInfo<'_, 'tcx> { } } - fn field_name(&self, i: usize) -> String { + fn field_name(&self, i: usize, cx: &CodegenCx<'_, 'tcx>) -> String { let field_name = match *self { - VariantInfo::Adt(variant) if variant.ctor_kind != CtorKind::Fn => { - Some(variant.fields[i].ident.name) + VariantInfo::Adt(variant) if variant.ctor_kind() != Some(CtorKind::Fn) => { + Some(variant.fields[i].ident(cx.tcx).name) } VariantInfo::Generator { generator_layout, @@ -1728,26 +1730,29 @@ fn describe_enum_variant<'ll, 'tcx>( containing_scope: &'ll DIScope, span: Span, ) -> (&'ll DICompositeType, MemberDescriptionFactory<'ll, 'tcx>) { - let metadata_stub = variant.map_struct_name(|variant_name| { - let unique_type_id = debug_context(cx) - .type_map - .borrow_mut() - .get_unique_type_id_of_enum_variant(cx, layout.ty, variant_name); - create_struct_stub( - cx, - layout.ty, - variant_name, - unique_type_id, - Some(containing_scope), - DIFlags::FlagZero, - ) - }); + let metadata_stub = variant.map_struct_name( + |variant_name| { + let unique_type_id = debug_context(cx) + .type_map + .borrow_mut() + .get_unique_type_id_of_enum_variant(cx, layout.ty, variant_name); + create_struct_stub( + cx, + layout.ty, + variant_name, + unique_type_id, + Some(containing_scope), + DIFlags::FlagZero, + ) + }, + cx, + ); let offsets = (0..layout.fields.count()) .map(|i| layout.fields.offset(i)) .collect(); let args = (0..layout.fields.count()) - .map(|i| (variant.field_name(i), layout.field(cx, i).ty)) + .map(|i| (variant.field_name(i, cx), layout.field(cx, i).ty)) .collect(); let member_description_factory = VariantMDF(VariantMemberDescriptionFactory { @@ -1778,9 +1783,9 @@ fn prepare_enum_metadata<'ll, 'tcx>( ty::Adt(def, _) => def .discriminants(tcx) .into_iter() - .zip(def.variants.iter()) + .zip(def.variants().iter()) .map(|((_, discr), v)| { - let name = CString::new(&*v.ident.as_str()).unwrap(); + let name = CString::new(&*v.ident(tcx).as_str()).unwrap(); unsafe { Some(llvm::LLVMRustDIBuilderCreateEnumerator( DIB(cx), @@ -1820,7 +1825,8 @@ fn prepare_enum_metadata<'ll, 'tcx>( let (discriminant_size, discriminant_align) = (discr.size(cx), discr.align(cx)); let discriminant_base_type_metadata = type_metadata(cx, discr.to_ty(cx.tcx), DUMMY_SP); - let discriminant_name = get_enum_discriminant_name(cx, enum_def_id).as_str(); + let name = get_enum_discriminant_name(cx, enum_def_id); + let discriminant_name = name.as_str(); let name = CString::new(discriminant_name.as_bytes()).unwrap(); let discriminant_type_metadata = unsafe { @@ -1858,7 +1864,7 @@ fn prepare_enum_metadata<'ll, 'tcx>( }, ) = (&layout.abi, &layout.variants) { - return FinalMetadata(discriminant_type_metadata(tag.value)); + return FinalMetadata(discriminant_type_metadata(tag.primitive())); } let discriminator_name = CString::new(match enum_type.kind() { @@ -1878,10 +1884,10 @@ fn prepare_enum_metadata<'ll, 'tcx>( .. } => { // Find the integer type of the correct size. - let size = tag.value.size(cx); - let align = tag.value.align(cx); + let size = tag.size(cx); + let align = tag.align(cx); - let tag_type = match tag.value { + let tag_type = match tag.primitive() { Int(t, _) => t, F32 => Integer::I32, F64 => Integer::I64, @@ -1912,7 +1918,7 @@ fn prepare_enum_metadata<'ll, 'tcx>( tag_field, .. } => { - let discr_type = tag.value.to_ty(cx.tcx); + let discr_type = tag.primitive().to_ty(cx.tcx); let (size, align) = cx.size_and_align_of(discr_type); let discr_metadata = basic_type_metadata(cx, discr_type); @@ -2113,7 +2119,7 @@ fn set_members_of_composite_type<'ll, 'tcx>( fn compute_type_parameters<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> &'ll DIArray { if let ty::Adt(def, substs) = *ty.kind() { if substs.types().next().is_some() { - let generics = cx.tcx.generics_of(def.did); + let generics = cx.tcx.generics_of(def.did()); let names = get_parameter_names(cx, generics); let template_params: Vec<_> = substs .into_iter() diff --git a/crates/rustc_codegen_nvvm/src/debug_info/mod.rs b/crates/rustc_codegen_nvvm/src/debug_info/mod.rs index 23e7f9a..9096156 100644 --- a/crates/rustc_codegen_nvvm/src/debug_info/mod.rs +++ b/crates/rustc_codegen_nvvm/src/debug_info/mod.rs @@ -1,10 +1,12 @@ use std::cell::RefCell; use std::ffi::CString; +use std::ops::Range; use libc::c_uint; use rustc_codegen_ssa::debuginfo::type_names; use rustc_codegen_ssa::mir::debuginfo::VariableKind::*; use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind}; +use rustc_codegen_ssa::traits::DebugInfoBuilderMethods; use rustc_codegen_ssa::traits::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; @@ -13,7 +15,10 @@ use rustc_index::vec::IndexVec; use rustc_middle::mir; use rustc_middle::ty::layout::HasTyCtxt; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; -use rustc_middle::ty::{self, Binder, ExistentialTraitRef, Instance, ParamEnv, Ty, TypeFoldable}; +use rustc_middle::ty::{ + self, Binder, ExistentialTraitRef, Instance, ParamEnv, PolyExistentialTraitRef, Ty, + TypeFoldable, TypeVisitable, +}; use rustc_session::config::{self, DebugInfo}; use rustc_span::symbol::Symbol; use rustc_span::{self, BytePos, Pos, SourceFile, SourceFileAndLine, Span}; @@ -106,6 +111,7 @@ impl<'a, 'll, 'tcx> DebugInfoBuilderMethods for Builder<'a, 'll, 'tcx> { variable_alloca: &'ll Value, direct_offset: Size, indirect_offsets: &[Size], + fragment: Option>, ) { let op_deref = || unsafe { llvm::LLVMRustDIBuilderCreateOpDeref() }; let op_plus_uconst = || unsafe { llvm::LLVMRustDIBuilderCreateOpPlusUconst() }; @@ -214,7 +220,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { // Initialize fn debug context (including scopes). let empty_scope = DebugScope { - dbg_scope: None, + dbg_scope: self.dbg_scope_fn(instance, fn_abi, Some(llfn)), inlined_at: None, file_start_pos: BytePos(0), file_end_pos: BytePos(0), @@ -224,17 +230,20 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { }; // Fill in all the scopes, with the information from the MIR body. - compute_mir_scopes( - self, - instance, - mir, - self.dbg_scope_fn(instance, fn_abi, Some(llfn)), - &mut fn_debug_context, - ); + compute_mir_scopes(self, instance, mir, &mut fn_debug_context); Some(fn_debug_context) } + fn create_vtable_debuginfo( + &self, + ty: Ty<'tcx>, + trait_ref: Option>, + vtable: &'ll Value, + ) { + // todo!(); + } + fn dbg_scope_fn( &self, instance: Instance<'tcx>, @@ -416,11 +425,11 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { ty::Adt(def, ..) if !def.is_box() => { // Again, only create type information if full debuginfo is enabled if cx.sess().opts.debuginfo == DebugInfo::Full - && !impl_self_ty.definitely_needs_subst(cx.tcx) + && !impl_self_ty.needs_subst() { Some(type_metadata(cx, impl_self_ty, rustc_span::DUMMY_SP)) } else { - Some(namespace::item_namespace(cx, def.did)) + Some(namespace::item_namespace(cx, def.did())) } } _ => None, @@ -459,14 +468,14 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { unsafe { llvm::LLVMRustDIBuilderCreateDebugLocation(line, col, scope, inlined_at) } } - fn create_vtable_metadata( - &self, - ty: Ty<'tcx>, - _: Option>>, - vtable: Self::Value, - ) { - metadata::create_vtable_metadata(self, ty, vtable) - } + // fn create_vtable_metadata( + // &self, + // ty: Ty<'tcx>, + // _: Option>>, + // vtable: Self::Value, + // ) { + // metadata::create_vtable_metadata(self, ty, vtable) + // } fn extend_scope_to_file( &self, diff --git a/crates/rustc_codegen_nvvm/src/debug_info/util.rs b/crates/rustc_codegen_nvvm/src/debug_info/util.rs index 10a742f..8cb0491 100644 --- a/crates/rustc_codegen_nvvm/src/debug_info/util.rs +++ b/crates/rustc_codegen_nvvm/src/debug_info/util.rs @@ -45,10 +45,5 @@ pub(crate) fn get_namespace_for_item<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, def_id: DefId, ) -> &'ll DIScope { - item_namespace( - cx, - cx.tcx - .parent(def_id) - .expect("get_namespace_for_item: missing parent?"), - ) + item_namespace(cx, cx.tcx.parent(def_id)) } diff --git a/crates/rustc_codegen_nvvm/src/init.rs b/crates/rustc_codegen_nvvm/src/init.rs index 2a4a346..d729c14 100644 --- a/crates/rustc_codegen_nvvm/src/init.rs +++ b/crates/rustc_codegen_nvvm/src/init.rs @@ -1,9 +1,10 @@ use libc::c_int; -use rustc_metadata::dynamic_lib::DynamicLibrary; +use libloading::Library; use rustc_middle::bug; use rustc_session::Session; use rustc_target::spec::MergeFunctions; use std::ffi::CString; +use tracing::debug; use std::mem; use std::path::Path; @@ -81,13 +82,13 @@ unsafe fn configure_llvm(sess: &Session) { if sess.print_llvm_passes() { add("-debug-pass=Structure", false); } - if !sess.opts.debugging_opts.no_generate_arange_section { + if !sess.opts.unstable_opts.no_generate_arange_section { add("-generate-arange-section", false); } match sess .opts - .debugging_opts + .unstable_opts .merge_functions .unwrap_or(sess.target.merge_functions) { @@ -114,14 +115,13 @@ unsafe fn configure_llvm(sess: &Session) { llvm::LLVMInitializePasses(); - for plugin in &sess.opts.debugging_opts.llvm_plugins { - let path = Path::new(plugin); - let res = DynamicLibrary::open(path); - match res { - Ok(_) => {} - Err(e) => bug!("couldn't load plugin: {}", e), - } - mem::forget(res); + for plugin in &sess.opts.unstable_opts.llvm_plugins { + let lib = Library::new(plugin).unwrap_or_else(|e| bug!("couldn't load plugin: {}", e)); + debug!("LLVM plugin loaded successfully {:?} ({})", lib, plugin); + + // Intentionally leak the dynamic library. We can't ever unload it + // since the library can make things that will live arbitrarily long. + mem::forget(lib); } llvm::LLVMInitializeNVPTXTarget(); diff --git a/crates/rustc_codegen_nvvm/src/intrinsic.rs b/crates/rustc_codegen_nvvm/src/intrinsic.rs index 4359f4b..beac855 100644 --- a/crates/rustc_codegen_nvvm/src/intrinsic.rs +++ b/crates/rustc_codegen_nvvm/src/intrinsic.rs @@ -1,4 +1,5 @@ use crate::abi::LlvmType; +use crate::llvm::TypeKind::Vector; use crate::llvm::{self, Value}; use crate::target; use crate::ty::LayoutLlvmExt; @@ -196,6 +197,7 @@ impl<'a, 'll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { let llval = match name { _ if simple.is_some() => self.call( self.type_i1(), + None, simple.unwrap(), &args.iter().map(|arg| arg.immediate()).collect::>(), None, @@ -204,6 +206,7 @@ impl<'a, 'll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { let expect = self.get_intrinsic("llvm.expect.i1"); self.call( self.type_i1(), + None, expect, &[args[0].immediate(), self.const_bool(true)], None, @@ -213,6 +216,7 @@ impl<'a, 'll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { let expect = self.get_intrinsic("llvm.expect.i1"); self.call( self.type_i1(), + None, expect, &[args[0].immediate(), self.const_bool(false)], None, @@ -222,7 +226,7 @@ impl<'a, 'll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { let try_func = args[0].immediate(); let data = args[1].immediate(); - self.call(self.type_i1(), try_func, &[data], None); + self.call(self.type_i1(), None, try_func, &[data], None); let ret_align = self.data_layout().i32_align.abi; self.store(self.const_i32(0), llresult, ret_align) } @@ -234,6 +238,7 @@ impl<'a, 'll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { let intrinsic = self.cx().get_intrinsic("llvm.va_copy"); self.call( self.type_i1(), + None, intrinsic, &[args[0].immediate(), args[1].immediate()], None, @@ -241,8 +246,8 @@ impl<'a, 'll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { } sym::va_arg => { match fn_abi.ret.layout.abi { - abi::Abi::Scalar(ref scalar) => { - match scalar.value { + abi::Abi::Scalar(abi::Scalar::Initialized { ref value, .. }) => { + match value { Primitive::Int(..) => { if self.cx().size_of(ret_ty).bytes() < 4 { // `va_arg` should not be called on a integer type @@ -275,7 +280,7 @@ impl<'a, 'll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { sym::volatile_load | sym::unaligned_volatile_load => { let tp_ty = substs.type_at(0); let mut ptr = args[0].immediate(); - if let PassMode::Cast(ty) = fn_abi.ret.mode { + if let PassMode::Cast(ty, _) = &fn_abi.ret.mode { ptr = self.pointercast(ptr, self.type_ptr_to(ty.llvm_type(self))); } let load = self.volatile_load(self.type_i1(), ptr); @@ -313,6 +318,7 @@ impl<'a, 'll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { }; self.call( self.type_i1(), + None, expect, &[ args[0].immediate(), @@ -364,16 +370,17 @@ impl<'a, 'll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { sym::ctlz | sym::cttz => { let y = self.const_bool(false); let llfn = self.get_intrinsic(&format!("llvm.{}.i{}", name, width)); - self.call(self.type_i1(), llfn, &[args[0].immediate(), y], None) + self.call(self.type_i1(), None, llfn, &[args[0].immediate(), y], None) } sym::ctlz_nonzero | sym::cttz_nonzero => { let y = self.const_bool(true); let llvm_name = &format!("llvm.{}.i{}", &name_str[..4], width); let llfn = self.get_intrinsic(llvm_name); - self.call(self.type_i1(), llfn, &[args[0].immediate(), y], None) + self.call(self.type_i1(), None, llfn, &[args[0].immediate(), y], None) } sym::ctpop => self.call( self.type_i1(), + None, self.get_intrinsic(&format!("llvm.ctpop.i{}", width)), &[args[0].immediate()], None, @@ -384,6 +391,7 @@ impl<'a, 'll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { } else { self.call( self.type_i1(), + None, self.get_intrinsic(&format!("llvm.bswap.i{}", width)), &[args[0].immediate()], None, @@ -392,6 +400,7 @@ impl<'a, 'll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { } sym::bitreverse => self.call( self.type_i1(), + None, self.get_intrinsic(&format!("llvm.bitreverse.i{}", width)), &[args[0].immediate()], None, @@ -404,7 +413,7 @@ impl<'a, 'll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { let llvm_name = &format!("llvm.fsh{}.i{}", if is_left { 'l' } else { 'r' }, width); let llfn = self.get_intrinsic(llvm_name); - self.call(self.type_i1(), llfn, &[val, val, raw_shift], None) + self.call(self.type_i1(), None, llfn, &[val, val, raw_shift], None) } sym::saturating_add | sym::saturating_sub => { let is_add = name == sym::saturating_add; @@ -417,7 +426,7 @@ impl<'a, 'll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { width ); let llfn = self.get_intrinsic(llvm_name); - self.call(self.type_i1(), llfn, &[lhs, rhs], None) + self.call(self.type_i1(), None, llfn, &[lhs, rhs], None) } _ => unreachable!(), } @@ -428,36 +437,36 @@ impl<'a, 'll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { use rustc_codegen_ssa::common::IntPredicate; let tp_ty = substs.type_at(0); let layout = self.layout_of(tp_ty).layout; - let use_integer_compare = match layout.abi { + let use_integer_compare = match layout.abi() { Scalar(_) | ScalarPair(_, _) => true, Uninhabited | Vector { .. } => false, Aggregate { .. } => { // For rusty ABIs, small aggregates are actually passed // as `RegKind::Integer` (see `FnAbi::adjust_for_abi`), // so we re-use that same threshold here. - layout.size <= self.data_layout().pointer_size * 2 + layout.size() <= self.data_layout().pointer_size * 2 } }; let a = args[0].immediate(); let b = args[1].immediate(); - if layout.size.bytes() == 0 { + if layout.size().bytes() == 0 { self.const_bool(true) } else if use_integer_compare { - let integer_ty = self.type_ix(layout.size.bits()); + let integer_ty = self.type_ix(layout.size().bits()); let ptr_ty = self.type_ptr_to(integer_ty); let a_ptr = self.bitcast(a, ptr_ty); - let a_val = self.load(integer_ty, a_ptr, layout.align.abi); + let a_val = self.load(integer_ty, a_ptr, layout.align().abi); let b_ptr = self.bitcast(b, ptr_ty); - let b_val = self.load(integer_ty, b_ptr, layout.align.abi); + let b_val = self.load(integer_ty, b_ptr, layout.align().abi); self.icmp(IntPredicate::IntEQ, a_val, b_val) } else { let i8p_ty = self.type_i8p(); let a_ptr = self.bitcast(a, i8p_ty); let b_ptr = self.bitcast(b, i8p_ty); - let n = self.const_usize(layout.size.bytes()); + let n = self.const_usize(layout.size().bytes()); let intrinsic = self.get_intrinsic("memcmp"); - let cmp = self.call(self.type_i1(), intrinsic, &[a_ptr, b_ptr, n], None); + let cmp = self.call(self.type_i1(), None, intrinsic, &[a_ptr, b_ptr, n], None); self.icmp(IntPredicate::IntEQ, cmp, self.const_i32(0)) } } @@ -467,7 +476,7 @@ impl<'a, 'll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { }; trace!("Finish intrinsic call: `{:?}`", llval); if !fn_abi.ret.is_ignore() { - if let PassMode::Cast(ty) = fn_abi.ret.mode { + if let PassMode::Cast(ty, _) = &fn_abi.ret.mode { let ptr_llty = self.type_ptr_to(ty.llvm_type(self)); let ptr = self.pointercast(result.llval, ptr_llty); self.store(llval, ptr, result.align); @@ -482,13 +491,13 @@ impl<'a, 'll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { fn abort(&mut self) { trace!("Generate abort call"); let fnname = self.get_intrinsic("llvm.trap"); - self.call(self.type_i1(), fnname, &[], None); + self.call(self.type_i1(), None, fnname, &[], None); } fn assume(&mut self, val: Self::Value) { trace!("Generate assume call with `{:?}`", val); let assume_intrinsic = self.get_intrinsic("llvm.assume"); - self.call(self.type_i1(), assume_intrinsic, &[val], None); + self.call(self.type_i1(), None, assume_intrinsic, &[val], None); } fn expect(&mut self, cond: Self::Value, expected: bool) -> Self::Value { @@ -496,6 +505,7 @@ impl<'a, 'll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { let expect = self.get_intrinsic("llvm.expect.i1"); self.call( self.type_i1(), + None, expect, &[cond, self.const_bool(expected)], None, @@ -507,15 +517,24 @@ impl<'a, 'll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { self.const_i32(0) } + fn type_checked_load( + &mut self, + llvtable: &'ll Value, + vtable_byte_offset: u64, + typeid: &'ll Value, + ) -> &'ll Value { + todo!() + } + fn va_start(&mut self, va_list: &'ll Value) -> Self::Value { trace!("Generate va_start `{:?}`", va_list); let intrinsic = self.cx().get_intrinsic("llvm.va_start"); - self.call(self.type_i1(), intrinsic, &[va_list], None) + self.call(self.type_i1(), None, intrinsic, &[va_list], None) } fn va_end(&mut self, va_list: &'ll Value) -> Self::Value { trace!("Generate va_end call `{:?}`", va_list); let intrinsic = self.cx().get_intrinsic("llvm.va_end"); - self.call(self.type_i1(), intrinsic, &[va_list], None) + self.call(self.type_i1(), None, intrinsic, &[va_list], None) } } diff --git a/crates/rustc_codegen_nvvm/src/lib.rs b/crates/rustc_codegen_nvvm/src/lib.rs index b224e84..0a044f9 100644 --- a/crates/rustc_codegen_nvvm/src/lib.rs +++ b/crates/rustc_codegen_nvvm/src/lib.rs @@ -3,7 +3,8 @@ // make our lives a lot easier for llvm ffi with this. And since rustc's core infra // relies on it its almost guaranteed to not be removed/broken #![feature(extern_types)] -#![feature(backtrace)] +#![feature(hash_raw_entry)] +#![feature(let_chains)] extern crate rustc_arena; extern crate rustc_ast; @@ -51,6 +52,7 @@ mod ty; use abi::readjust_fn_abi; use back::target_machine_factory; use lto::ThinBuffer; +use rustc_codegen_llvm::ModuleLlvm; use rustc_codegen_ssa::{ back::{ lto::{LtoModuleCodegen, SerializedModule, ThinModule}, @@ -59,7 +61,7 @@ use rustc_codegen_ssa::{ traits::{CodegenBackend, ExtraBackendMethods, WriteBackendMethods}, CodegenResults, CompiledModule, ModuleCodegen, }; -use rustc_errors::{ErrorReported, FatalError, Handler}; +use rustc_errors::{ErrorGuaranteed, FatalError, Handler}; use rustc_hash::FxHashMap; use rustc_metadata::EncodedMetadata; use rustc_middle::ty::query; @@ -67,7 +69,7 @@ use rustc_middle::{ dep_graph::{WorkProduct, WorkProductId}, ty::TyCtxt, }; -use rustc_session::{cstore::MetadataLoaderDyn, Session}; +use rustc_session::{config::OutputFilenames, cstore::MetadataLoaderDyn, Session}; use tracing::debug; use std::ffi::CString; @@ -109,6 +111,7 @@ impl CodegenBackend for NvvmCodegenBackend { let result = (rustc_interface::DEFAULT_QUERY_PROVIDERS.fn_abi_of_instance)(tcx, key); Ok(readjust_fn_abi(tcx, result?)) }; + providers.global_backend_features = |tcx, ()| vec![]; } fn provide_extern(&self, _providers: &mut query::ExternProviders) {} @@ -132,7 +135,8 @@ impl CodegenBackend for NvvmCodegenBackend { &self, ongoing_codegen: Box, sess: &Session, - ) -> Result<(CodegenResults, FxHashMap), ErrorReported> { + outputs: &OutputFilenames, + ) -> Result<(CodegenResults, FxHashMap), ErrorGuaranteed> { debug!("Join codegen"); let (codegen_results, work_products) = ongoing_codegen .downcast::>() @@ -149,7 +153,7 @@ impl CodegenBackend for NvvmCodegenBackend { sess: &rustc_session::Session, codegen_results: rustc_codegen_ssa::CodegenResults, outputs: &rustc_session::config::OutputFilenames, - ) -> Result<(), rustc_errors::ErrorReported> { + ) -> Result<(), rustc_errors::ErrorGuaranteed> { link::link( sess, &codegen_results, @@ -163,7 +167,6 @@ impl CodegenBackend for NvvmCodegenBackend { impl WriteBackendMethods for NvvmCodegenBackend { type Module = LlvmMod; type ModuleBuffer = lto::ModuleBuffer; - type Context = llvm::Context; type TargetMachine = &'static mut llvm::TargetMachine; type ThinData = (); type ThinBuffer = ThinBuffer; @@ -212,11 +215,18 @@ impl WriteBackendMethods for NvvmCodegenBackend { unsafe fn optimize_thin( cgcx: &CodegenContext, - thin_module: &mut ThinModule, + thin_module: ThinModule, ) -> Result, FatalError> { lto::optimize_thin(cgcx, thin_module) } + fn optimize_fat( + _: &CodegenContext, + _: &mut ModuleCodegen<::Module>, + ) -> Result<(), FatalError> { + todo!() + } + unsafe fn codegen( cgcx: &CodegenContext, diag_handler: &Handler, @@ -246,39 +256,40 @@ impl WriteBackendMethods for NvvmCodegenBackend { } } - fn run_lto_pass_manager( - _: &CodegenContext, - _: &ModuleCodegen, - _: &ModuleConfig, - _: bool, - ) -> Result<(), FatalError> { - todo!() - } + // fn run_lto_pass_manager( + // _: &CodegenContext, + // _: &ModuleCodegen, + // _: &ModuleConfig, + // _: bool, + // ) -> Result<(), FatalError> { + // todo!() + // } } impl ExtraBackendMethods for NvvmCodegenBackend { - fn new_metadata(&self, _sess: TyCtxt<'_>, mod_name: &str) -> Self::Module { - LlvmMod::new(mod_name) - } - - fn write_compressed_metadata<'tcx>( - &self, - _tcx: TyCtxt<'tcx>, - _metadata: &EncodedMetadata, - _llvm_module: &mut Self::Module, - ) { - todo!() - } + // fn new_metadata(&self, _sess: TyCtxt<'_>, mod_name: &str) -> Self::Module { + // LlvmMod::new(mod_name) + // } + + // fn write_compressed_metadata<'tcx>( + // &self, + // _tcx: TyCtxt<'tcx>, + // _metadata: &EncodedMetadata, + // _llvm_module: &mut Self::Module, + // ) { + // todo!() + // } fn codegen_allocator<'tcx>( &self, tcx: TyCtxt<'tcx>, - mods: &mut Self::Module, - _module_name: &str, + module_name: &str, kind: rustc_ast::expand::allocator::AllocatorKind, - has_alloc_error_handler: bool, - ) { - unsafe { allocator::codegen(tcx, mods, kind, has_alloc_error_handler) } + alloc_error_handler_kind: rustc_ast::expand::allocator::AllocatorKind, + ) -> LlvmMod { + let mut module_llvm = LlvmMod::new(module_name); + unsafe { allocator::codegen(tcx, &mut module_llvm, kind, alloc_error_handler_kind) } + module_llvm } fn compile_codegen_unit( @@ -293,17 +304,18 @@ impl ExtraBackendMethods for NvvmCodegenBackend { &self, sess: &Session, opt_level: rustc_session::config::OptLevel, + target_features: &[String], ) -> rustc_codegen_ssa::back::write::TargetMachineFactoryFn { target_machine_factory(sess, opt_level) } - fn target_cpu<'b>(&self, _sess: &'b Session) -> &'b str { - todo!() - } + // fn target_cpu<'b>(&self, _sess: &'b Session) -> &'b str { + // todo!() + // } - fn tune_cpu<'b>(&self, _sess: &'b Session) -> Option<&'b str> { - todo!() - } + // fn tune_cpu<'b>(&self, _sess: &'b Session) -> Option<&'b str> { + // todo!() + // } } /// Create the LLVM module for the rest of the compilation, this houses diff --git a/crates/rustc_codegen_nvvm/src/link.rs b/crates/rustc_codegen_nvvm/src/link.rs index 0d5e484..a24894f 100644 --- a/crates/rustc_codegen_nvvm/src/link.rs +++ b/crates/rustc_codegen_nvvm/src/link.rs @@ -26,6 +26,7 @@ use tracing::{debug, trace}; use crate::context::CodegenArgs; use crate::LlvmMod; +use rustc_ast::CRATE_NODE_ID; pub(crate) struct NvvmMetadataLoader; @@ -75,7 +76,7 @@ pub fn link<'tcx>( // largely inspired by rust-gpu let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata); for &crate_type in sess.crate_types().iter() { - if (sess.opts.debugging_opts.no_codegen || !sess.opts.output_types.should_codegen()) + if (sess.opts.unstable_opts.no_codegen || !sess.opts.output_types.should_codegen()) && !output_metadata && crate_type == CrateType::Executable { @@ -91,7 +92,12 @@ pub fn link<'tcx>( } if outputs.outputs.should_codegen() { - let out_filename = out_filename(sess, crate_type, outputs, crate_name); + let out_filename = out_filename( + sess, + crate_type, + outputs, + codegen_results.crate_info.local_crate_name, + ); match crate_type { CrateType::Rlib => { link_rlib(sess, codegen_results, &out_filename); @@ -136,6 +142,7 @@ fn link_rlib(sess: &Session, codegen_results: &CodegenResults, out_filename: &Pa | NativeLibKind::Dylib { .. } | NativeLibKind::Framework { .. } | NativeLibKind::RawDylib + | NativeLibKind::LinkArg | NativeLibKind::Unspecified => continue, } // native libraries in cuda doesnt make much sense, extern functions @@ -307,11 +314,11 @@ fn link_local_crate_native_libs_and_dependent_crate_libs<'a>( crate_type: CrateType, codegen_results: &CodegenResults, ) { - if sess.opts.debugging_opts.link_native_libraries { + if sess.opts.unstable_opts.link_native_libraries { add_local_native_libraries(sess, codegen_results); } add_upstream_rust_crates(sess, rlibs, codegen_results, crate_type); - if sess.opts.debugging_opts.link_native_libraries { + if sess.opts.unstable_opts.link_native_libraries { add_upstream_native_libraries(sess, codegen_results, crate_type); } } @@ -369,7 +376,7 @@ fn add_upstream_native_libraries( fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool { match lib.cfg { - Some(ref cfg) => rustc_attr::cfg_matches(cfg, &sess.parse_sess, None), + Some(ref cfg) => rustc_attr::cfg_matches(cfg, &sess.parse_sess, CRATE_NODE_ID, None), None => true, } } diff --git a/crates/rustc_codegen_nvvm/src/llvm.rs b/crates/rustc_codegen_nvvm/src/llvm.rs index fe3a4c9..599b768 100644 --- a/crates/rustc_codegen_nvvm/src/llvm.rs +++ b/crates/rustc_codegen_nvvm/src/llvm.rs @@ -335,6 +335,8 @@ pub(crate) enum MetadataType { MD_invariant_load = 6, MD_nontemporal = 9, MD_nonnull = 11, + MD_type = 19, + MD_kcfi_type = 36, } /// LLVMRustAsmDialect @@ -346,14 +348,14 @@ pub enum AsmDialect { Intel, } -impl AsmDialect { - pub fn from_generic(asm: rustc_ast::LlvmAsmDialect) -> Self { - match asm { - rustc_ast::LlvmAsmDialect::Att => AsmDialect::Att, - rustc_ast::LlvmAsmDialect::Intel => AsmDialect::Intel, - } - } -} +// impl AsmDialect { +// pub fn from_generic(asm: rustc_ast::LlvmAsmDialect) -> Self { +// match asm { +// rustc_ast::LlvmAsmDialect::Att => AsmDialect::Att, +// rustc_ast::LlvmAsmDialect::Intel => AsmDialect::Intel, +// } +// } +// } /// LLVMRustDiagnosticKind #[derive(Copy, Clone)] @@ -1585,6 +1587,18 @@ extern "C" { DestTy: &'a Type, Name: *const c_char, ) -> &'a Value; + // pub(crate) fn LLVMBuildFPToSISat<'a>( + // B: &Builder<'a>, + // Val: &'a Value, + // DestTy: &'a Type, + // Name: *const c_char, + // ) -> &'a Value; + // pub(crate) fn LLVMBuildFPToUISat<'a>( + // B: &Builder<'a>, + // Val: &'a Value, + // DestTy: &'a Type, + // Name: *const c_char, + // ) -> &'a Value; pub(crate) fn LLVMBuildUIToFP<'a>( B: &Builder<'a>, Val: &'a Value, diff --git a/crates/rustc_codegen_nvvm/src/lto.rs b/crates/rustc_codegen_nvvm/src/lto.rs index 74c51d6..5044971 100644 --- a/crates/rustc_codegen_nvvm/src/lto.rs +++ b/crates/rustc_codegen_nvvm/src/lto.rs @@ -148,7 +148,7 @@ pub(crate) fn run_thin( pub(crate) unsafe fn optimize_thin( cgcx: &CodegenContext, - thin_module: &mut ThinModule, + thin_module: ThinModule, ) -> Result, FatalError> { // essentially does nothing let diag_handler = cgcx.create_diag_handler(); diff --git a/crates/rustc_codegen_nvvm/src/mono_item.rs b/crates/rustc_codegen_nvvm/src/mono_item.rs index a84c757..2d195f2 100644 --- a/crates/rustc_codegen_nvvm/src/mono_item.rs +++ b/crates/rustc_codegen_nvvm/src/mono_item.rs @@ -11,7 +11,7 @@ pub use rustc_middle::mir::mono::MonoItem; use rustc_middle::mir::mono::{Linkage, Visibility}; use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::layout::LayoutOf; -use rustc_middle::ty::{self, Instance, TypeFoldable}; +use rustc_middle::ty::{self, Instance, TypeFoldable, TypeVisitable}; use tracing::trace; pub(crate) fn visibility_to_llvm(linkage: Visibility) -> llvm::Visibility { @@ -94,8 +94,8 @@ impl<'ll, 'tcx> PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> { attributes::from_fn_attrs(self, lldecl, instance); let def_id = instance.def_id(); - let attrs = self.tcx.get_attrs(def_id); - let nvvm_attrs = NvvmAttributes::parse(self, attrs); + let attrs = self.tcx.get_attrs_unchecked(def_id); + let nvvm_attrs = NvvmAttributes::parse(self, &attrs); unsafe { // if this function is marked as being a kernel, add it diff --git a/crates/rustc_codegen_nvvm/src/override_fns.rs b/crates/rustc_codegen_nvvm/src/override_fns.rs index 61a8ef3..bbe35e9 100644 --- a/crates/rustc_codegen_nvvm/src/override_fns.rs +++ b/crates/rustc_codegen_nvvm/src/override_fns.rs @@ -27,7 +27,8 @@ fn should_override<'ll, 'tcx>(func: Instance<'tcx>, cx: &CodegenCx<'ll, 'tcx>) - if !is_libm { return false; } - let name = cx.tcx.item_name(func.def_id()).as_str(); + let name_id = cx.tcx.item_name(func.def_id()); + let name = name_id.as_str(); let intrinsics = cx.intrinsics_map.borrow(); let is_known_intrinsic = intrinsics.contains_key(format!("__nv_{}", name).as_str()); @@ -48,7 +49,8 @@ fn is_unsupported_libdevice_fn(name: &str) -> bool { } fn override_libm_function<'ll, 'tcx>(func: Instance<'tcx>, cx: &CodegenCx<'ll, 'tcx>) { - let name = cx.tcx.item_name(func.def_id()).as_str(); + let name_id = cx.tcx.item_name(func.def_id()); + let name = name_id.as_str(); let nv_name = format!("__nv_{}", name); let intrinsic = cx.get_intrinsic(&nv_name); @@ -57,6 +59,6 @@ fn override_libm_function<'ll, 'tcx>(func: Instance<'tcx>, cx: &CodegenCx<'ll, ' let mut bx = Builder::build(cx, start); let params = llvm::get_params(llfn); - let llcall = bx.call(cx.type_i1(), intrinsic, ¶ms, None); + let llcall = bx.call(cx.type_i1(), None, intrinsic, ¶ms, None); bx.ret(llcall); } diff --git a/crates/rustc_codegen_nvvm/src/target.rs b/crates/rustc_codegen_nvvm/src/target.rs index dc01761..1958fab 100644 --- a/crates/rustc_codegen_nvvm/src/target.rs +++ b/crates/rustc_codegen_nvvm/src/target.rs @@ -11,45 +11,44 @@ pub(crate) unsafe fn usize_ty(llcx: &'_ llvm::Context) -> &'_ Type { } pub fn target() -> Target { - Target { - arch: "nvptx".to_string(), - data_layout: DATA_LAYOUT.to_string(), - llvm_target: "nvptx64-nvidia-cuda".to_string(), - pointer_width: 64, + let mut target_options = TargetOptions::default(); + target_options.os = "cuda".into(); + target_options.vendor = "nvidia".into(); + target_options.linker_flavor = LinkerFlavor::Ptx; + // nvvm does all the linking for us; but technically its not a linker + target_options.linker = None; - options: TargetOptions { - os: "cuda".to_string(), - vendor: "nvidia".to_string(), - linker_flavor: LinkerFlavor::PtxLinker, - // nvvm does all the linking for us, but technically its not a linker - linker: None, + target_options.cpu = "sm_30".into(); - cpu: "sm_30".to_string(), + target_options.max_atomic_width = Some(64); - max_atomic_width: Some(64), + // Unwinding on CUDA is neither feasible nor useful. + target_options.panic_strategy = PanicStrategy::Abort; - // Unwinding on CUDA is neither feasible nor useful. - panic_strategy: PanicStrategy::Abort, + // Needed to use `dylib` and `bin` crate types and the linker. + target_options.dynamic_linking = true; + target_options.executables = true; - // Needed to use `dylib` and `bin` crate types and the linker. - dynamic_linking: true, - executables: true, + target_options.only_cdylib = true; - only_cdylib: true, + // nvvm does all the work of turning the bitcode into ptx + target_options.obj_is_bitcode = true; - // nvvm does all the work of turning the bitcode into ptx - obj_is_bitcode: true, + target_options.dll_prefix = "".into(); + target_options.dll_suffix = ".ptx".into(); + target_options.exe_suffix = ".ptx".into(); - dll_prefix: "".to_string(), - dll_suffix: ".ptx".to_string(), - exe_suffix: ".ptx".to_string(), + // Disable MergeFunctions LLVM optimisation pass because it can + // produce kernel functions that call other kernel functions. + // This behavior is not supported by PTX ISA. + target_options.merge_functions = MergeFunctions::Disabled; - // Disable MergeFunctions LLVM optimisation pass because it can - // produce kernel functions that call other kernel functions. - // This behavior is not supported by PTX ISA. - merge_functions: MergeFunctions::Disabled, + Target { + arch: "nvptx".into(), + data_layout: DATA_LAYOUT.into(), + llvm_target: "nvptx64-nvidia-cuda".into(), + pointer_width: 64, - ..Default::default() - }, + options: target_options, } } diff --git a/crates/rustc_codegen_nvvm/src/ty.rs b/crates/rustc_codegen_nvvm/src/ty.rs index 55102db..c117d97 100644 --- a/crates/rustc_codegen_nvvm/src/ty.rs +++ b/crates/rustc_codegen_nvvm/src/ty.rs @@ -1,6 +1,7 @@ use crate::abi::{FnAbiLlvmExt, LlvmType}; use crate::context::CodegenCx; use crate::llvm::{self, Bool, False, True, Type, Value}; +use crate::rustc_middle::ty::TypeVisitable; use crate::rustc_target::abi::TyAbiInterface; use libc::c_uint; use rustc_codegen_ssa::common::TypeKind; @@ -222,6 +223,10 @@ impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn val_ty(&self, v: &'ll Value) -> &'ll Type { unsafe { llvm::LLVMTypeOf(v) } } + + fn type_array(&self, ty: &'ll Type, len: u64) -> &'ll Type { + unsafe { llvm::LLVMRustArrayType(ty, len) } + } } impl<'ll, 'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> { @@ -390,7 +395,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { scalar: &Scalar, offset: Size, ) -> &'a Type { - match scalar.value { + match scalar.primitive() { Int(i, _) => cx.type_from_integer(i), F32 => cx.type_f32(), F64 => cx.type_f64(), @@ -453,7 +458,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { let offset = if index == 0 { Size::ZERO } else { - a.value.size(cx).align_to(b.value.align(cx).abi) + a.size(cx).align_to(b.align(cx).abi) }; self.scalar_llvm_type_at(cx, scalar, offset) } @@ -519,12 +524,12 @@ fn uncached_llvm_type<'a, 'tcx>( // in problematically distinct types due to HRTB and subtyping (see #47638). // ty::Dynamic(..) | ty::Adt(..) | ty::Closure(..) | ty::Foreign(..) | ty::Generator(..) | ty::Str => { - let mut name = with_no_trimmed_paths(|| layout.ty.to_string()); + let mut name = with_no_trimmed_paths!(layout.ty.to_string()); if let (&ty::Adt(def, _), &Variants::Single { index }) = (layout.ty.kind(), &layout.variants) { - if def.is_enum() && !def.variants.is_empty() { - write!(&mut name, "::{}", def.variants[index].ident).unwrap(); + if def.is_enum() && !def.variants().is_empty() { + write!(&mut name, "::{}", def.variants()[index].ident(cx.tcx)).unwrap(); } } if let (&ty::Generator(_, _, _), &Variants::Single { index }) = @@ -543,8 +548,8 @@ fn uncached_llvm_type<'a, 'tcx>( let packed = false; match name { None => cx.type_struct(&[fill], packed), - Some(ref name) => { - let llty = cx.type_named_struct(name); + Some(name) => { + let llty = cx.type_named_struct(&name); cx.set_struct_body(llty, &[fill], packed); llty } diff --git a/examples/cuda/gpu/add_gpu/src/lib.rs b/examples/cuda/gpu/add_gpu/src/lib.rs index 92ac4e2..42f1481 100644 --- a/examples/cuda/gpu/add_gpu/src/lib.rs +++ b/examples/cuda/gpu/add_gpu/src/lib.rs @@ -1,10 +1,3 @@ -#![cfg_attr( - target_os = "cuda", - no_std, - feature(register_attr), - register_attr(nvvm_internal) -)] - use cuda_std::prelude::*; #[kernel] diff --git a/examples/cuda/gpu/path_tracer_gpu/src/lib.rs b/examples/cuda/gpu/path_tracer_gpu/src/lib.rs index 4ebd5d8..8c7cdbd 100644 --- a/examples/cuda/gpu/path_tracer_gpu/src/lib.rs +++ b/examples/cuda/gpu/path_tracer_gpu/src/lib.rs @@ -1,8 +1,8 @@ #![cfg_attr( target_os = "cuda", no_std, - feature(register_attr), - register_attr(nvvm_internal) + feature(register_tool), + register_tool(nvvm_internal) )] #![allow(clippy::missing_safety_doc)] diff --git a/guide/src/guide/getting_started.md b/guide/src/guide/getting_started.md index eb4ea1e..67d763b 100644 --- a/guide/src/guide/getting_started.md +++ b/guide/src/guide/getting_started.md @@ -62,8 +62,8 @@ Before we can write any GPU kernels, we must add a few directives to our `lib.rs #![cfg_attr( target_os = "cuda", no_std, - feature(register_attr), - register_attr(nvvm_internal) + feature(register_tool), + register_tool(nvvm_internal) )] use cuda_std::*; diff --git a/rust-toolchain b/rust-toolchain index ecef846..ac5fb7c 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -5,5 +5,5 @@ # to the user in the error, instead of "error: invalid channel name '[toolchain]'". [toolchain] -channel = "nightly-2021-12-04" -components = ["rust-src", "rustc-dev", "llvm-tools-preview"] \ No newline at end of file +channel = "nightly-2022-12-10" +components = ["rust-src", "rustc-dev", "llvm-tools-preview", "rust-analyzer"]