From 58fdc43e03bd77c575bc1c62b18b784f71ab4bf2 Mon Sep 17 00:00:00 2001 From: Michal Sudwoj Date: Thu, 21 May 2020 23:01:22 +0200 Subject: [PATCH 01/10] NVPTX support for new asm! --- src/librustc_codegen_llvm/asm.rs | 12 +++ src/librustc_target/asm/mod.rs | 27 +++++++ src/librustc_target/asm/nvptx.rs | 90 ++++++++++++++++++++++ src/test/assembly/asm/nvptx-types.rs | 109 +++++++++++++++++++++++++++ 4 files changed, 238 insertions(+) create mode 100644 src/librustc_target/asm/nvptx.rs create mode 100644 src/test/assembly/asm/nvptx-types.rs diff --git a/src/librustc_codegen_llvm/asm.rs b/src/librustc_codegen_llvm/asm.rs index 8986ab322c07f..fe4cd16c1f5e5 100644 --- a/src/librustc_codegen_llvm/asm.rs +++ b/src/librustc_codegen_llvm/asm.rs @@ -254,6 +254,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { ]); } InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {} + InlineAsmArch::Nvptx64 => {} } } if !options.contains(InlineAsmOptions::NOMEM) { @@ -410,6 +411,11 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass) -> String { | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4) => "x", InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg) | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg) => "w", + InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => "h", + InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => "r", + InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => "l", + InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::freg32) => "f", + InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::freg64) => "d", InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r", InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => "f", InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) => "r", @@ -452,6 +458,7 @@ fn modifier_to_llvm( modifier } } + InlineAsmRegClass::Nvptx(_) => None, InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) | InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => None, InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) @@ -502,6 +509,11 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4) => { cx.type_vector(cx.type_i64(), 2) } + InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => cx.type_i16(), + InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => cx.type_i32(), + InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => cx.type_i64(), + InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::freg32) => cx.type_f32(), + InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::freg64) => cx.type_f64(), InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => cx.type_f32(), InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) diff --git a/src/librustc_target/asm/mod.rs b/src/librustc_target/asm/mod.rs index 774146a679ab8..ffca742e9ab8d 100644 --- a/src/librustc_target/asm/mod.rs +++ b/src/librustc_target/asm/mod.rs @@ -146,11 +146,13 @@ macro_rules! types { mod aarch64; mod arm; +mod nvptx; mod riscv; mod x86; pub use aarch64::{AArch64InlineAsmReg, AArch64InlineAsmRegClass}; pub use arm::{ArmInlineAsmReg, ArmInlineAsmRegClass}; +pub use nvptx::{NvptxInlineAsmReg, NvptxInlineAsmRegClass}; pub use riscv::{RiscVInlineAsmReg, RiscVInlineAsmRegClass}; pub use x86::{X86InlineAsmReg, X86InlineAsmRegClass}; @@ -162,6 +164,7 @@ pub enum InlineAsmArch { AArch64, RiscV32, RiscV64, + Nvptx64, } impl FromStr for InlineAsmArch { @@ -175,6 +178,7 @@ impl FromStr for InlineAsmArch { "aarch64" => Ok(Self::AArch64), "riscv32" => Ok(Self::RiscV32), "riscv64" => Ok(Self::RiscV64), + "nvptx64" => Ok(Self::Nvptx64), _ => Err(()), } } @@ -196,6 +200,7 @@ pub enum InlineAsmReg { Arm(ArmInlineAsmReg), AArch64(AArch64InlineAsmReg), RiscV(RiscVInlineAsmReg), + Nvptx(NvptxInlineAsmReg), } impl InlineAsmReg { @@ -205,6 +210,7 @@ impl InlineAsmReg { Self::Arm(r) => r.name(), Self::AArch64(r) => r.name(), Self::RiscV(r) => r.name(), + Self::Nvptx(r) => r.name(), } } @@ -214,6 +220,7 @@ impl InlineAsmReg { Self::Arm(r) => InlineAsmRegClass::Arm(r.reg_class()), Self::AArch64(r) => InlineAsmRegClass::AArch64(r.reg_class()), Self::RiscV(r) => InlineAsmRegClass::RiscV(r.reg_class()), + Self::Nvptx(r) => InlineAsmRegClass::Nvptx(r.reg_class()), } } @@ -236,6 +243,9 @@ impl InlineAsmReg { InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => { Self::RiscV(RiscVInlineAsmReg::parse(arch, has_feature, &name)?) } + InlineAsmArch::Nvptx64 => { + Self::Nvptx(NvptxInlineAsmReg::parse(arch, has_feature, &name)?) + } }) } @@ -252,6 +262,7 @@ impl InlineAsmReg { Self::Arm(r) => r.emit(out, arch, modifier), Self::AArch64(r) => r.emit(out, arch, modifier), Self::RiscV(r) => r.emit(out, arch, modifier), + Self::Nvptx(r) => r.emit(out, arch, modifier), } } @@ -261,6 +272,7 @@ impl InlineAsmReg { Self::Arm(r) => r.overlapping_regs(|r| cb(Self::Arm(r))), Self::AArch64(_) => cb(self), Self::RiscV(_) => cb(self), + Self::Nvptx(_) => cb(self), } } } @@ -281,6 +293,7 @@ pub enum InlineAsmRegClass { Arm(ArmInlineAsmRegClass), AArch64(AArch64InlineAsmRegClass), RiscV(RiscVInlineAsmRegClass), + Nvptx(NvptxInlineAsmRegClass), } impl InlineAsmRegClass { @@ -290,6 +303,7 @@ impl InlineAsmRegClass { Self::Arm(r) => r.name(), Self::AArch64(r) => r.name(), Self::RiscV(r) => r.name(), + Self::Nvptx(r) => r.name(), } } @@ -302,6 +316,7 @@ impl InlineAsmRegClass { Self::Arm(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Arm), Self::AArch64(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::AArch64), Self::RiscV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::RiscV), + Self::Nvptx(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Nvptx), } } @@ -321,6 +336,7 @@ impl InlineAsmRegClass { Self::Arm(r) => r.suggest_modifier(arch, ty), Self::AArch64(r) => r.suggest_modifier(arch, ty), Self::RiscV(r) => r.suggest_modifier(arch, ty), + Self::Nvptx(r) => r.suggest_modifier(arch, ty), } } @@ -336,6 +352,7 @@ impl InlineAsmRegClass { Self::Arm(r) => r.default_modifier(arch), Self::AArch64(r) => r.default_modifier(arch), Self::RiscV(r) => r.default_modifier(arch), + Self::Nvptx(r) => r.default_modifier(arch), } } @@ -350,6 +367,7 @@ impl InlineAsmRegClass { Self::Arm(r) => r.supported_types(arch), Self::AArch64(r) => r.supported_types(arch), Self::RiscV(r) => r.supported_types(arch), + Self::Nvptx(r) => r.supported_types(arch), } } @@ -367,6 +385,9 @@ impl InlineAsmRegClass { InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => { Self::RiscV(RiscVInlineAsmRegClass::parse(arch, name)?) } + InlineAsmArch::Nvptx64 => { + Self::Nvptx(NvptxInlineAsmRegClass::parse(arch, name)?) + } }) }) } @@ -379,6 +400,7 @@ impl InlineAsmRegClass { Self::Arm(r) => r.valid_modifiers(arch), Self::AArch64(r) => r.valid_modifiers(arch), Self::RiscV(r) => r.valid_modifiers(arch), + Self::Nvptx(r) => r.valid_modifiers(arch), } } } @@ -518,5 +540,10 @@ pub fn allocatable_registers( riscv::fill_reg_map(arch, has_feature, &mut map); map } + InlineAsmArch::Nvptx64 => { + let mut map = nvptx::regclass_map(); + nvptx::fill_reg_map(arch, has_feature, &mut map); + map + } } } diff --git a/src/librustc_target/asm/nvptx.rs b/src/librustc_target/asm/nvptx.rs new file mode 100644 index 0000000000000..b574e921718ad --- /dev/null +++ b/src/librustc_target/asm/nvptx.rs @@ -0,0 +1,90 @@ +use super::{InlineAsmArch, InlineAsmType}; +use rustc_macros::HashStable_Generic; +use std::fmt; + +def_reg_class! { + Nvptx NvptxInlineAsmRegClass { + reg16, + reg32, + reg64, + freg32, + freg64, + } +} + +impl NvptxInlineAsmRegClass { + pub fn valid_modifiers(self, _arch: InlineAsmArch) -> &'static [char] { + &[] + } + + pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option { + None + } + + pub fn suggest_modifier( + self, + _arch: InlineAsmArch, + _ty: InlineAsmType, + ) -> Option<(char, &'static str)> { + None + } + + pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> { + None + } + + pub fn supported_types( + self, + _arch: InlineAsmArch, + ) -> &'static [(InlineAsmType, Option<&'static str>)] { + match self { + Self::reg16 => types! { _: I8, I16; }, + Self::reg32 => types! { _: I8, I16, I32; }, + Self::reg64 => types! { _: I8, I16, I32, I64; }, + Self::freg32 => types! { _: F32; }, + Self::freg64 => types! { _: F32, F64; }, + } + } +} + +def_regs! { + Nvptx NvptxInlineAsmReg NvptxInlineAsmRegClass { + // We have to define a register, otherwise we get warnings/errors about unused imports and + // unreachable code. Do what clang does and define r0. + r0: reg32 = ["r0"], + #error = ["tid", "tid.x", "tid.y", "tid.z"] => "tid not supported for inline asm", + #error = ["ntid", "ntid.x", "ntid.y", "ntid.z"] => "ntid not supported for inline asm", + #error = ["laneid"] => "laneid not supported for inline asm", + #error = ["warpid"] => "warpid not supported for inline asm", + #error = ["nwarpid"] => "nwarpid not supported for inline asm", + #error = ["ctaid", "ctaid.x", "ctaid.y", "ctaid.z"] => "ctaid not supported for inline asm", + #error = ["nctaid", "nctaid.x", "nctaid.y", "nctaid.z"] => "nctaid not supported for inline asm", + #error = ["smid"] => "smid not supported for inline asm", + #error = ["nsmid"] => "nsmid not supported for inline asm", + #error = ["gridid"] => "gridid not supported for inline asm", + #error = ["lanemask_eq"] => "lanemask_eq not supported for inline asm", + #error = ["lanemask_le"] => "lanemask_le not supported for inline asm", + #error = ["lanemask_lt"] => "lanemask_lt not supported for inline asm", + #error = ["lanemask_ge"] => "lanemask_ge not supported for inline asm", + #error = ["lanemask_gt"] => "lanemask_gt not supported for inline asm", + #error = ["clock", "clock_hi"] => "clock not supported for inline asm", + #error = ["clock64"] => "clock64 not supported for inline asm", + #error = ["pm0", "pm1", "pm2", "pm3", "pm4", "pm5", "pm6", "pm7"] => "pm not supported for inline asm", + #error = ["pm0_64", "pm1_64", "pm2_64", "pm3_64", "pm4_64", "pm5_64", "pm6_64", "pm7_64"] => "pm_64 not supported for inline asm", + #error = ["envreg0", "envreg1", "envreg2", "envreg3", "envreg4", "envreg5", "envreg6", "envreg7", "envreg8", "envreg9", "envreg10", "envreg11", "envreg12", "envreg13", "envreg14", "envreg15", "envreg16", "envreg17", "envreg18", "envreg19", "envreg20", "envreg21", "envreg22", "envreg23", "envreg24", "envreg25", "envreg26", "envreg27", "envreg28", "envreg29", "envreg30", "envreg31"] => "envreg not supported for inline asm", + #error = ["globaltimer", "globaltimer_lo", "globaltimer_hi"] => "globaltimer not supported for inline asm", + #error = ["total_mem_size"] => "total_mem_size not supported for inline asm", + #error = ["dynamic_mem_size"] => "dynamic_mem_size not supported for inline asm", + } +} + +impl NvptxInlineAsmReg { + pub fn emit( + self, + out: &mut dyn fmt::Write, + _arch: InlineAsmArch, + _modifier: Option, + ) -> fmt::Result { + out.write_str(self.name()) + } +} diff --git a/src/test/assembly/asm/nvptx-types.rs b/src/test/assembly/asm/nvptx-types.rs new file mode 100644 index 0000000000000..cfaab23512458 --- /dev/null +++ b/src/test/assembly/asm/nvptx-types.rs @@ -0,0 +1,109 @@ +// no-system-llvm +// assembly-output: emit-asm +// compile-flags: --target --nvptx64-nvidia-cuda +// only-nvptx64 +// ignore-nvptx64 + +#![feature(no_core, lang_items, rustc_attrs)] +#![crate_type = "rlib"] +#![no_core] +#![allow(asm_sub_register, non_camel_case_types)] + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} +#[rustc_builtin_macro] +macro_rules! concat { + () => {}; +} +#[rustc_builtin_macro] +macro_rules! stringify { + () => {}; +} + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +type ptr = *mut u8; + +impl Copy for i8 {} +impl Copy for i16 {} +impl Copy for i32 {} +impl Copy for f32 {} +impl Copy for i64 {} +impl Copy for f64 {} +impl Copy for ptr {} + +#[no_mangle] +fn extern_func(); + +// CHECK-LABEL: sym_fn +// CHECK: #APP +// CHECK call extern_func; +// CHECK: #NO_APP +#[no_mangle] +pub unsafe fn sym_fn() { + asm!("call {}", sym extern_func); +} + +macro_rules! check { + ($func:ident $ty:ident, $class:ident $mov:literal) => { + #[no_mangle] + pub unsafe fn $func(x: $ty) -> $ty { + // Hack to avoid function merging + extern "Rust" { + fn dont_merge(s: &str); + } + dont_merge(stringify!($func)); + + let y; + asm!(concat!($mov, " {}, {};"), out($class) y, in($class) x); + y + } + }; +} + +// CHECK-LABEL: reg_i8 +// CHECK: #APP +// CHECK: mov.i16 {{[a-z0-9]+}}, {{[a-z0-9]+}}; +// CHECK: #NO_APP +check!(reg_i8 i8 reg16 "mov.i16"); + +// CHECK-LABEL: reg_i16 +// CHECK: #APP +// CHECK: mov.i16 {{[a-z0-9]+}}, {{[a-z0-9]+}}; +// CHECK: #NO_APP +check!(reg_i16 i16 reg16 "mov.i16"); + +// CHECK-LABEL: reg_i32 +// CHECK: #APP +// CHECK: mov.i32 {{[a-z0-9]+}}, {{[a-z0-9]+}}; +// CHECK: #NO_APP +check!(reg_i32 i32 reg32 "mov.i32"); + +// CHECK-LABEL: reg_f32 +// CHECK: #APP +// CHECK: mov.f32 {{[a-z0-9]+}}, {{[a-z0-9]+}}; +// CHECK: #NO_APP +check!(reg_f32 f32 freg32 "mov.f32"); + +// CHECK-LABEL: reg_i54 +// CHECK: #APP +// CHECK: mov.i64 {{[a-z0-9]+}}, {{[a-z0-9]+}}; +// CHECK: #NO_APP +check!(reg_i64 i64 reg64 "mov.i64"); + +// CHECK-LABEL: reg_f64 +// CHECK: #APP +// CHECK: mov.f64 {{[a-z0-9]+}}, {{[a-z0-9]+}}; +// CHECK: #NO_APP +check!(reg_f64 f64 freg64 "mov.f64"); + +// CHECK-LABEL: reg_ptr +// CHECK: #APP +// CHECK: mov.i64 {{[a-z0-9]+}}, {{[a-z0-9]+}}; +// CHECK: #NO_APP +check!(reg_ptr ptr reg64 "mov.i64"); From d77f73e8818453afd513f96e98cf7e0c889cdbd9 Mon Sep 17 00:00:00 2001 From: Michal Sudwoj Date: Fri, 22 May 2020 00:31:50 +0200 Subject: [PATCH 02/10] Formatted correctly --- src/librustc_target/asm/mod.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/librustc_target/asm/mod.rs b/src/librustc_target/asm/mod.rs index ffca742e9ab8d..99061d1fdeb8b 100644 --- a/src/librustc_target/asm/mod.rs +++ b/src/librustc_target/asm/mod.rs @@ -385,9 +385,7 @@ impl InlineAsmRegClass { InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => { Self::RiscV(RiscVInlineAsmRegClass::parse(arch, name)?) } - InlineAsmArch::Nvptx64 => { - Self::Nvptx(NvptxInlineAsmRegClass::parse(arch, name)?) - } + InlineAsmArch::Nvptx64 => Self::Nvptx(NvptxInlineAsmRegClass::parse(arch, name)?), }) }) } From baa801a92900d1a44ab5efb005b4bbb0353af206 Mon Sep 17 00:00:00 2001 From: Michal Sudwoj Date: Fri, 22 May 2020 14:38:46 +0200 Subject: [PATCH 03/10] Minor fixes, as requested in PR review --- src/librustc_codegen_llvm/asm.rs | 4 -- src/librustc_target/asm/mod.rs | 28 +++++++++-- src/librustc_target/asm/nvptx.rs | 49 ++---------------- src/test/assembly/asm/nvptx-types.rs | 75 ++++++++++++++++++++-------- 4 files changed, 80 insertions(+), 76 deletions(-) diff --git a/src/librustc_codegen_llvm/asm.rs b/src/librustc_codegen_llvm/asm.rs index fe4cd16c1f5e5..f3b46dd322a39 100644 --- a/src/librustc_codegen_llvm/asm.rs +++ b/src/librustc_codegen_llvm/asm.rs @@ -414,8 +414,6 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass) -> String { InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => "h", InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => "r", InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => "l", - InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::freg32) => "f", - InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::freg64) => "d", InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r", InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => "f", InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) => "r", @@ -512,8 +510,6 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => cx.type_i16(), InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => cx.type_i32(), InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => cx.type_i64(), - InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::freg32) => cx.type_f32(), - InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::freg64) => cx.type_f64(), InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => cx.type_f32(), InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) diff --git a/src/librustc_target/asm/mod.rs b/src/librustc_target/asm/mod.rs index 99061d1fdeb8b..1bbaa4c4c002e 100644 --- a/src/librustc_target/asm/mod.rs +++ b/src/librustc_target/asm/mod.rs @@ -52,6 +52,30 @@ macro_rules! def_reg_class { #[macro_use] macro_rules! def_regs { + ($arch:ident $arch_reg:ident $arch_regclass:ident {}) => { + #[allow(unreachable_code)] + #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, Eq, PartialEq, Hash, HashStable_Generic)] + pub enum $arch_reg {} + + impl $arch_reg { + pub fn parse( + _arch: super::InlineAsmArch, + mut _has_feature: impl FnMut(&str) -> bool, + _name: &str, + ) -> Result { + Err("unknown register") + } + } + + pub(super) fn fill_reg_map( + _arch: super::InlineAsmArch, + mut _has_feature: impl FnMut(&str) -> bool, + _map: &mut rustc_data_structures::fx::FxHashMap< + super::InlineAsmRegClass, + rustc_data_structures::fx::FxHashSet, + >, + ) {} + }; ($arch:ident $arch_reg:ident $arch_regclass:ident { $( $reg:ident: $class:ident $(, $extra_class:ident)* = [$reg_name:literal $(, $alias:literal)*] $(% $filter:ident)?, @@ -210,7 +234,6 @@ impl InlineAsmReg { Self::Arm(r) => r.name(), Self::AArch64(r) => r.name(), Self::RiscV(r) => r.name(), - Self::Nvptx(r) => r.name(), } } @@ -220,7 +243,6 @@ impl InlineAsmReg { Self::Arm(r) => InlineAsmRegClass::Arm(r.reg_class()), Self::AArch64(r) => InlineAsmRegClass::AArch64(r.reg_class()), Self::RiscV(r) => InlineAsmRegClass::RiscV(r.reg_class()), - Self::Nvptx(r) => InlineAsmRegClass::Nvptx(r.reg_class()), } } @@ -262,7 +284,6 @@ impl InlineAsmReg { Self::Arm(r) => r.emit(out, arch, modifier), Self::AArch64(r) => r.emit(out, arch, modifier), Self::RiscV(r) => r.emit(out, arch, modifier), - Self::Nvptx(r) => r.emit(out, arch, modifier), } } @@ -272,7 +293,6 @@ impl InlineAsmReg { Self::Arm(r) => r.overlapping_regs(|r| cb(Self::Arm(r))), Self::AArch64(_) => cb(self), Self::RiscV(_) => cb(self), - Self::Nvptx(_) => cb(self), } } } diff --git a/src/librustc_target/asm/nvptx.rs b/src/librustc_target/asm/nvptx.rs index b574e921718ad..cba069cd0542c 100644 --- a/src/librustc_target/asm/nvptx.rs +++ b/src/librustc_target/asm/nvptx.rs @@ -1,14 +1,11 @@ use super::{InlineAsmArch, InlineAsmType}; use rustc_macros::HashStable_Generic; -use std::fmt; def_reg_class! { Nvptx NvptxInlineAsmRegClass { reg16, reg32, reg64, - freg32, - freg64, } } @@ -39,52 +36,12 @@ impl NvptxInlineAsmRegClass { ) -> &'static [(InlineAsmType, Option<&'static str>)] { match self { Self::reg16 => types! { _: I8, I16; }, - Self::reg32 => types! { _: I8, I16, I32; }, - Self::reg64 => types! { _: I8, I16, I32, I64; }, - Self::freg32 => types! { _: F32; }, - Self::freg64 => types! { _: F32, F64; }, + Self::reg32 => types! { _: I8, I16, I32, F32; }, + Self::reg64 => types! { _: I8, I16, I32, F32, I64, F64; }, } } } def_regs! { - Nvptx NvptxInlineAsmReg NvptxInlineAsmRegClass { - // We have to define a register, otherwise we get warnings/errors about unused imports and - // unreachable code. Do what clang does and define r0. - r0: reg32 = ["r0"], - #error = ["tid", "tid.x", "tid.y", "tid.z"] => "tid not supported for inline asm", - #error = ["ntid", "ntid.x", "ntid.y", "ntid.z"] => "ntid not supported for inline asm", - #error = ["laneid"] => "laneid not supported for inline asm", - #error = ["warpid"] => "warpid not supported for inline asm", - #error = ["nwarpid"] => "nwarpid not supported for inline asm", - #error = ["ctaid", "ctaid.x", "ctaid.y", "ctaid.z"] => "ctaid not supported for inline asm", - #error = ["nctaid", "nctaid.x", "nctaid.y", "nctaid.z"] => "nctaid not supported for inline asm", - #error = ["smid"] => "smid not supported for inline asm", - #error = ["nsmid"] => "nsmid not supported for inline asm", - #error = ["gridid"] => "gridid not supported for inline asm", - #error = ["lanemask_eq"] => "lanemask_eq not supported for inline asm", - #error = ["lanemask_le"] => "lanemask_le not supported for inline asm", - #error = ["lanemask_lt"] => "lanemask_lt not supported for inline asm", - #error = ["lanemask_ge"] => "lanemask_ge not supported for inline asm", - #error = ["lanemask_gt"] => "lanemask_gt not supported for inline asm", - #error = ["clock", "clock_hi"] => "clock not supported for inline asm", - #error = ["clock64"] => "clock64 not supported for inline asm", - #error = ["pm0", "pm1", "pm2", "pm3", "pm4", "pm5", "pm6", "pm7"] => "pm not supported for inline asm", - #error = ["pm0_64", "pm1_64", "pm2_64", "pm3_64", "pm4_64", "pm5_64", "pm6_64", "pm7_64"] => "pm_64 not supported for inline asm", - #error = ["envreg0", "envreg1", "envreg2", "envreg3", "envreg4", "envreg5", "envreg6", "envreg7", "envreg8", "envreg9", "envreg10", "envreg11", "envreg12", "envreg13", "envreg14", "envreg15", "envreg16", "envreg17", "envreg18", "envreg19", "envreg20", "envreg21", "envreg22", "envreg23", "envreg24", "envreg25", "envreg26", "envreg27", "envreg28", "envreg29", "envreg30", "envreg31"] => "envreg not supported for inline asm", - #error = ["globaltimer", "globaltimer_lo", "globaltimer_hi"] => "globaltimer not supported for inline asm", - #error = ["total_mem_size"] => "total_mem_size not supported for inline asm", - #error = ["dynamic_mem_size"] => "dynamic_mem_size not supported for inline asm", - } -} - -impl NvptxInlineAsmReg { - pub fn emit( - self, - out: &mut dyn fmt::Write, - _arch: InlineAsmArch, - _modifier: Option, - ) -> fmt::Result { - out.write_str(self.name()) - } + Nvptx NvptxInlineAsmReg NvptxInlineAsmRegClass {} } diff --git a/src/test/assembly/asm/nvptx-types.rs b/src/test/assembly/asm/nvptx-types.rs index cfaab23512458..5faf4082f327c 100644 --- a/src/test/assembly/asm/nvptx-types.rs +++ b/src/test/assembly/asm/nvptx-types.rs @@ -1,6 +1,7 @@ // no-system-llvm // assembly-output: emit-asm // compile-flags: --target --nvptx64-nvidia-cuda +// compile-flags: -Z merge-functions=disabled // only-nvptx64 // ignore-nvptx64 @@ -53,12 +54,6 @@ macro_rules! check { ($func:ident $ty:ident, $class:ident $mov:literal) => { #[no_mangle] pub unsafe fn $func(x: $ty) -> $ty { - // Hack to avoid function merging - extern "Rust" { - fn dont_merge(s: &str); - } - dont_merge(stringify!($func)); - let y; asm!(concat!($mov, " {}, {};"), out($class) y, in($class) x); y @@ -66,44 +61,80 @@ macro_rules! check { }; } -// CHECK-LABEL: reg_i8 +// CHECK-LABEL: reg16_i8 // CHECK: #APP // CHECK: mov.i16 {{[a-z0-9]+}}, {{[a-z0-9]+}}; // CHECK: #NO_APP -check!(reg_i8 i8 reg16 "mov.i16"); +check!(reg16_i8 i8 reg16 "mov.i16"); -// CHECK-LABEL: reg_i16 +// CHECK-LABEL: reg16_i16 // CHECK: #APP // CHECK: mov.i16 {{[a-z0-9]+}}, {{[a-z0-9]+}}; // CHECK: #NO_APP -check!(reg_i16 i16 reg16 "mov.i16"); +check!(reg16_i16 i16 reg16 "mov.i16"); + +// CHECK-LABEL: reg32_i8 +// CHECK: #APP +// CHECK: mov.i32 {{[a-z0-9]+}}, {{[a-z0-9]+}}; +// CHECK: #NO_APP +check!(reg32_i8 i8 reg32 "mov.i32"); + +// CHECK-LABEL: reg32_i16 +// CHECK: #APP +// CHECK: mov.i32 {{[a-z0-9]+}}, {{[a-z0-9]+}}; +// CHECK: #NO_APP +check!(reg32_i16 i16 reg32 "mov.i32"); -// CHECK-LABEL: reg_i32 +// CHECK-LABEL: reg32_i32 // CHECK: #APP // CHECK: mov.i32 {{[a-z0-9]+}}, {{[a-z0-9]+}}; // CHECK: #NO_APP -check!(reg_i32 i32 reg32 "mov.i32"); +check!(reg32_i32 i32 reg32 "mov.i32"); -// CHECK-LABEL: reg_f32 +// CHECK-LABEL: reg32_f32 // CHECK: #APP -// CHECK: mov.f32 {{[a-z0-9]+}}, {{[a-z0-9]+}}; +// CHECK: mov.i32 {{[a-z0-9]+}}, {{[a-z0-9]+}}; +// CHECK: #NO_APP +check!(reg32_f32 f32 reg32 "mov.i32"); + +// CHECK-LABEL: reg64_i8 +// CHECK: #APP +// CHECK: mov.i64 {{[a-z0-9]+}}, {{[a-z0-9]+}}; // CHECK: #NO_APP -check!(reg_f32 f32 freg32 "mov.f32"); +check!(reg64_i8 i8 reg64 "mov.i64"); -// CHECK-LABEL: reg_i54 +// CHECK-LABEL: reg64_i16 // CHECK: #APP // CHECK: mov.i64 {{[a-z0-9]+}}, {{[a-z0-9]+}}; // CHECK: #NO_APP -check!(reg_i64 i64 reg64 "mov.i64"); +check!(reg64_i16 i16 reg64 "mov.i64"); -// CHECK-LABEL: reg_f64 +// CHECK-LABEL: reg64_i32 // CHECK: #APP -// CHECK: mov.f64 {{[a-z0-9]+}}, {{[a-z0-9]+}}; +// CHECK: mov.i64 {{[a-z0-9]+}}, {{[a-z0-9]+}}; +// CHECK: #NO_APP +check!(reg64_i32 i32 reg64 "mov.i64"); + +// CHECK-LABEL: reg64_f32 +// CHECK: #APP +// CHECK: mov.i64 {{[a-z0-9]+}}, {{[a-z0-9]+}}; +// CHECK: #NO_APP +check!(reg64_f32 f32 reg64 "mov.i64"); + +// CHECK-LABEL: reg64_i64 +// CHECK: #APP +// CHECK: mov.i64 {{[a-z0-9]+}}, {{[a-z0-9]+}}; +// CHECK: #NO_APP +check!(reg64_i64 i64 reg64 "mov.i64"); + +// CHECK-LABEL: reg64_f64 +// CHECK: #APP +// CHECK: mov.i64 {{[a-z0-9]+}}, {{[a-z0-9]+}}; // CHECK: #NO_APP -check!(reg_f64 f64 freg64 "mov.f64"); +check!(reg64_f64 f64 reg64 "mov.i64"); -// CHECK-LABEL: reg_ptr +// CHECK-LABEL: reg64_ptr // CHECK: #APP // CHECK: mov.i64 {{[a-z0-9]+}}, {{[a-z0-9]+}}; // CHECK: #NO_APP -check!(reg_ptr ptr reg64 "mov.i64"); +check!(reg64_ptr ptr reg64 "mov.i64"); From 1070f08aaba30cfe2aba587a911fcbdf35f6cdbc Mon Sep 17 00:00:00 2001 From: Michal Sudwoj Date: Fri, 22 May 2020 18:16:26 +0200 Subject: [PATCH 04/10] Deduplicated macro code --- src/librustc_target/asm/mod.rs | 32 +++++--------------------------- 1 file changed, 5 insertions(+), 27 deletions(-) diff --git a/src/librustc_target/asm/mod.rs b/src/librustc_target/asm/mod.rs index 1bbaa4c4c002e..a18a4dbd3e214 100644 --- a/src/librustc_target/asm/mod.rs +++ b/src/librustc_target/asm/mod.rs @@ -52,30 +52,6 @@ macro_rules! def_reg_class { #[macro_use] macro_rules! def_regs { - ($arch:ident $arch_reg:ident $arch_regclass:ident {}) => { - #[allow(unreachable_code)] - #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, Eq, PartialEq, Hash, HashStable_Generic)] - pub enum $arch_reg {} - - impl $arch_reg { - pub fn parse( - _arch: super::InlineAsmArch, - mut _has_feature: impl FnMut(&str) -> bool, - _name: &str, - ) -> Result { - Err("unknown register") - } - } - - pub(super) fn fill_reg_map( - _arch: super::InlineAsmArch, - mut _has_feature: impl FnMut(&str) -> bool, - _map: &mut rustc_data_structures::fx::FxHashMap< - super::InlineAsmRegClass, - rustc_data_structures::fx::FxHashSet, - >, - ) {} - }; ($arch:ident $arch_reg:ident $arch_regclass:ident { $( $reg:ident: $class:ident $(, $extra_class:ident)* = [$reg_name:literal $(, $alias:literal)*] $(% $filter:ident)?, @@ -84,6 +60,7 @@ macro_rules! def_regs { #error = [$($bad_reg:literal),+] => $error:literal, )* }) => { + #[allow(unreachable_code)] #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, Eq, PartialEq, Hash, HashStable_Generic)] #[allow(non_camel_case_types)] pub enum $arch_reg { @@ -126,19 +103,20 @@ macro_rules! def_regs { pub(super) fn fill_reg_map( _arch: super::InlineAsmArch, mut _has_feature: impl FnMut(&str) -> bool, - map: &mut rustc_data_structures::fx::FxHashMap< + _map: &mut rustc_data_structures::fx::FxHashMap< super::InlineAsmRegClass, rustc_data_structures::fx::FxHashSet, >, ) { + #[allow(unused_imports)] use super::{InlineAsmReg, InlineAsmRegClass}; $( if $($filter(_arch, &mut _has_feature, true).is_ok() &&)? true { - if let Some(set) = map.get_mut(&InlineAsmRegClass::$arch($arch_regclass::$class)) { + if let Some(set) = _map.get_mut(&InlineAsmRegClass::$arch($arch_regclass::$class)) { set.insert(InlineAsmReg::$arch($arch_reg::$reg)); } $( - if let Some(set) = map.get_mut(&InlineAsmRegClass::$arch($arch_regclass::$extra_class)) { + if let Some(set) = _map.get_mut(&InlineAsmRegClass::$arch($arch_regclass::$extra_class)) { set.insert(InlineAsmReg::$arch($arch_reg::$reg)); } )* From 6d74e096d868385441874346c0eab93bc405ebef Mon Sep 17 00:00:00 2001 From: Michal Sudwoj Date: Fri, 22 May 2020 18:16:57 +0200 Subject: [PATCH 05/10] Added comment on there being no predefined registers --- src/librustc_target/asm/nvptx.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/librustc_target/asm/nvptx.rs b/src/librustc_target/asm/nvptx.rs index cba069cd0542c..43d16ae0f5d10 100644 --- a/src/librustc_target/asm/nvptx.rs +++ b/src/librustc_target/asm/nvptx.rs @@ -43,5 +43,7 @@ impl NvptxInlineAsmRegClass { } def_regs! { + // Registers in PTX are declared in the assembly. + // There are no predefined registers that one can use. Nvptx NvptxInlineAsmReg NvptxInlineAsmRegClass {} } From 5ec6b5eaeed5cddcb224cdec7bda148b3c8631f4 Mon Sep 17 00:00:00 2001 From: Michal Sudwoj Date: Fri, 22 May 2020 18:17:22 +0200 Subject: [PATCH 06/10] Fixed tests --- src/test/assembly/asm/nvptx-types.rs | 130 +++++++++++++-------------- 1 file changed, 61 insertions(+), 69 deletions(-) diff --git a/src/test/assembly/asm/nvptx-types.rs b/src/test/assembly/asm/nvptx-types.rs index 5faf4082f327c..b36efe16c64a1 100644 --- a/src/test/assembly/asm/nvptx-types.rs +++ b/src/test/assembly/asm/nvptx-types.rs @@ -1,14 +1,10 @@ // no-system-llvm // assembly-output: emit-asm -// compile-flags: --target --nvptx64-nvidia-cuda -// compile-flags: -Z merge-functions=disabled -// only-nvptx64 -// ignore-nvptx64 +// compile-flags: --target nvptx64-nvidia-cuda +// compile-flags: --crate-type cdylib #![feature(no_core, lang_items, rustc_attrs)] -#![crate_type = "rlib"] #![no_core] -#![allow(asm_sub_register, non_camel_case_types)] #[rustc_builtin_macro] macro_rules! asm { @@ -18,10 +14,6 @@ macro_rules! asm { macro_rules! concat { () => {}; } -#[rustc_builtin_macro] -macro_rules! stringify { - () => {}; -} #[lang = "sized"] trait Sized {} @@ -39,19 +31,19 @@ impl Copy for f64 {} impl Copy for ptr {} #[no_mangle] -fn extern_func(); +fn extern_func() {} -// CHECK-LABEL: sym_fn -// CHECK: #APP -// CHECK call extern_func; -// CHECK: #NO_APP +// CHECK-LABEL: .visible .func sym_fn() +// CHECK: // begin inline asm +// CHECK: call extern_func; +// CHECK: // end inline asm #[no_mangle] pub unsafe fn sym_fn() { - asm!("call {}", sym extern_func); + asm!("call {};", sym extern_func); } macro_rules! check { - ($func:ident $ty:ident, $class:ident $mov:literal) => { + ($func:ident $ty:ident $class:ident $mov:literal) => { #[no_mangle] pub unsafe fn $func(x: $ty) -> $ty { let y; @@ -61,80 +53,80 @@ macro_rules! check { }; } -// CHECK-LABEL: reg16_i8 -// CHECK: #APP -// CHECK: mov.i16 {{[a-z0-9]+}}, {{[a-z0-9]+}}; -// CHECK: #NO_APP +// CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg16_i8 +// CHECK: // begin inline asm +// CHECK: mov.i16 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; +// CHECK: // end inline asm check!(reg16_i8 i8 reg16 "mov.i16"); -// CHECK-LABEL: reg16_i16 -// CHECK: #APP -// CHECK: mov.i16 {{[a-z0-9]+}}, {{[a-z0-9]+}}; -// CHECK: #NO_APP +// CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg16_i16 +// CHECK: // begin inline asm +// CHECK: mov.i16 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; +// CHECK: // end inline asm check!(reg16_i16 i16 reg16 "mov.i16"); -// CHECK-LABEL: reg32_i8 -// CHECK: #APP -// CHECK: mov.i32 {{[a-z0-9]+}}, {{[a-z0-9]+}}; -// CHECK: #NO_APP +// CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg32_i8 +// CHECK: // begin inline asm +// CHECK: mov.i32 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; +// CHECK: // end inline asm check!(reg32_i8 i8 reg32 "mov.i32"); -// CHECK-LABEL: reg32_i16 -// CHECK: #APP -// CHECK: mov.i32 {{[a-z0-9]+}}, {{[a-z0-9]+}}; -// CHECK: #NO_APP +// CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg32_i16 +// CHECK: // begin inline asm +// CHECK: mov.i32 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; +// CHECK: // end inline asm check!(reg32_i16 i16 reg32 "mov.i32"); -// CHECK-LABEL: reg32_i32 -// CHECK: #APP -// CHECK: mov.i32 {{[a-z0-9]+}}, {{[a-z0-9]+}}; -// CHECK: #NO_APP +// CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg32_i32 +// CHECK: // begin inline asm +// CHECK: mov.i32 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; +// CHECK: // end inline asm check!(reg32_i32 i32 reg32 "mov.i32"); -// CHECK-LABEL: reg32_f32 -// CHECK: #APP -// CHECK: mov.i32 {{[a-z0-9]+}}, {{[a-z0-9]+}}; -// CHECK: #NO_APP +// CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg32_f32 +// CHECK: // begin inline asm +// CHECK: mov.i32 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; +// CHECK: // end inline asm check!(reg32_f32 f32 reg32 "mov.i32"); -// CHECK-LABEL: reg64_i8 -// CHECK: #APP -// CHECK: mov.i64 {{[a-z0-9]+}}, {{[a-z0-9]+}}; -// CHECK: #NO_APP +// CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg64_i8 +// CHECK: // begin inline asm +// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; +// CHECK: // end inline asm check!(reg64_i8 i8 reg64 "mov.i64"); -// CHECK-LABEL: reg64_i16 -// CHECK: #APP -// CHECK: mov.i64 {{[a-z0-9]+}}, {{[a-z0-9]+}}; -// CHECK: #NO_APP +// CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg64_i16 +// CHECK: // begin inline asm +// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; +// CHECK: // end inline asm check!(reg64_i16 i16 reg64 "mov.i64"); -// CHECK-LABEL: reg64_i32 -// CHECK: #APP -// CHECK: mov.i64 {{[a-z0-9]+}}, {{[a-z0-9]+}}; -// CHECK: #NO_APP +// CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg64_i32 +// CHECK: // begin inline asm +// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; +// CHECK: // end inline asm check!(reg64_i32 i32 reg64 "mov.i64"); -// CHECK-LABEL: reg64_f32 -// CHECK: #APP -// CHECK: mov.i64 {{[a-z0-9]+}}, {{[a-z0-9]+}}; -// CHECK: #NO_APP +// CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg64_f32 +// CHECK: // begin inline asm +// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; +// CHECK: // end inline asm check!(reg64_f32 f32 reg64 "mov.i64"); -// CHECK-LABEL: reg64_i64 -// CHECK: #APP -// CHECK: mov.i64 {{[a-z0-9]+}}, {{[a-z0-9]+}}; -// CHECK: #NO_APP +// CHECK-LABEL: .visible .func (.param .b64 func_retval0) reg64_i64 +// CHECK: // begin inline asm +// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; +// CHECK: // end inline asm check!(reg64_i64 i64 reg64 "mov.i64"); -// CHECK-LABEL: reg64_f64 -// CHECK: #APP -// CHECK: mov.i64 {{[a-z0-9]+}}, {{[a-z0-9]+}}; -// CHECK: #NO_APP +// CHECK-LABEL: .visible .func (.param .b64 func_retval0) reg64_f64 +// CHECK: // begin inline asm +// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; +// CHECK: // end inline asm check!(reg64_f64 f64 reg64 "mov.i64"); -// CHECK-LABEL: reg64_ptr -// CHECK: #APP -// CHECK: mov.i64 {{[a-z0-9]+}}, {{[a-z0-9]+}}; -// CHECK: #NO_APP +// CHECK-LABEL: .visible .func (.param .b64 func_retval0) reg64_ptr +// CHECK: // begin inline asm +// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; +// CHECK: // end inline asm check!(reg64_ptr ptr reg64 "mov.i64"); From ed559b3770d11f1047f0f4df3036beccb1b6dc47 Mon Sep 17 00:00:00 2001 From: Michal Sudwoj Date: Sat, 23 May 2020 00:25:20 +0200 Subject: [PATCH 07/10] Updated documentation --- src/doc/unstable-book/src/library-features/asm.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/doc/unstable-book/src/library-features/asm.md b/src/doc/unstable-book/src/library-features/asm.md index 0b68991fce2a1..c34a2931bc06b 100644 --- a/src/doc/unstable-book/src/library-features/asm.md +++ b/src/doc/unstable-book/src/library-features/asm.md @@ -468,12 +468,17 @@ Here is the list of currently supported register classes: | ARM | `qreg` | `q[0-15]` | `w` | | ARM | `qreg_low8` | `q[0-7]` | `t` | | ARM | `qreg_low4` | `q[0-3]` | `x` | +| NVPTX | `reg16` | None\* | `h` | +| NVPTX | `reg32` | None\* | `r` | +| NVPTX | `reg64` | None\* | `l` | | RISC-V | `reg` | `x1`, `x[5-7]`, `x[9-15]`, `x[16-31]` (non-RV32E) | `r` | | RISC-V | `freg` | `f[0-31]` | `f` | > **Note**: On x86 we treat `reg_byte` differently from `reg` because the compiler can allocate `al` and `ah` separately whereas `reg` reserves the whole register. > > Note #2: On x86-64 the high byte registers (e.g. `ah`) are only available when used as an explicit register. Specifying the `reg_byte` register class for an operand will always allocate a low byte register. +> +> Note #3: On NVPTX, register names are not supported. Additional register classes may be added in the future based on demand (e.g. MMX, x87, etc). @@ -495,6 +500,9 @@ Each register class has constraints on which value types they can be used with. | ARM | `sreg` | `vfp2` | `i32`, `f32` | | ARM | `dreg` | `vfp2` | `i64`, `f64`, `i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2` | | ARM | `qreg` | `neon` | `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4` | +| NVPTX | `reg16` | None | `i8`, `i16` | +| NVPTX | `reg32` | None | `i8`, `i16`, `i32`, `f32` | +| NVPTX | `reg64` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` | | RISC-V32 | `reg` | None | `i8`, `i16`, `i32`, `f32` | | RISC-V64 | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` | | RISC-V | `freg` | `f` | `f32` | @@ -502,7 +510,7 @@ Each register class has constraints on which value types they can be used with. > **Note**: For the purposes of the above table pointers, function pointers and `isize`/`usize` are treated as the equivalent integer type (`i16`/`i32`/`i64` depending on the target). -If a value is of a smaller size than the register it is allocated in then the upper bits of that register will have an undefined value for inputs and will be ignored for outputs. The only exception is the `freg` register class on RISC-V where `f32` values are NaN-boxed in a `f64` as required by the RISC-V architecture. +If a value is of a smaller size than the register it is allocated in then the upper bits of that register will have an undefined value for inputs and will be ignored for outputs. The only exceptions are the `freg` register class on RISC-V where `f32` values are NaN-boxed in a `f64` as required by the RISC-V architecture, and the register classes on NVPTX where values are zero-extended. When separate input and output expressions are specified for an `inout` operand, both expressions must have the same type. The only exception is if both operands are pointers or integers, in which case they are only required to have the same size. This restriction exists because the register allocators in LLVM and GCC sometimes cannot handle tied operands with different types. @@ -610,6 +618,9 @@ The supported modifiers are a subset of LLVM's (and GCC's) [asm template argumen | ARM | `dreg` | None | `d0` | `P` | | ARM | `qreg` | None | `q0` | `q` | | ARM | `qreg` | `e` / `f` | `d0` / `d1` | `e` / `f` | +| NVPTX | `reg16` | None | `rs0` | None | +| NVPTX | `reg32` | None | `r0` | None | +| NVPTX | `reg64` | None | `rd0` | None | | RISC-V | `reg` | None | `x1` | None | | RISC-V | `freg` | None | `f0` | None | From 70cd375c57bc35db9c9a3eff37abdb900e45f910 Mon Sep 17 00:00:00 2001 From: Michal Sudwoj Date: Sat, 23 May 2020 03:48:40 +0200 Subject: [PATCH 08/10] Corrected statement about zero-extension in docs. --- src/doc/unstable-book/src/library-features/asm.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/unstable-book/src/library-features/asm.md b/src/doc/unstable-book/src/library-features/asm.md index c34a2931bc06b..50121b2c0fca4 100644 --- a/src/doc/unstable-book/src/library-features/asm.md +++ b/src/doc/unstable-book/src/library-features/asm.md @@ -510,7 +510,7 @@ Each register class has constraints on which value types they can be used with. > **Note**: For the purposes of the above table pointers, function pointers and `isize`/`usize` are treated as the equivalent integer type (`i16`/`i32`/`i64` depending on the target). -If a value is of a smaller size than the register it is allocated in then the upper bits of that register will have an undefined value for inputs and will be ignored for outputs. The only exceptions are the `freg` register class on RISC-V where `f32` values are NaN-boxed in a `f64` as required by the RISC-V architecture, and the register classes on NVPTX where values are zero-extended. +If a value is of a smaller size than the register it is allocated in then the upper bits of that register will have an undefined value for inputs and will be ignored for outputs. The only exception is the `freg` register class on RISC-V where `f32` values are NaN-boxed in a `f64` as required by the RISC-V architecture. When separate input and output expressions are specified for an `inout` operand, both expressions must have the same type. The only exception is if both operands are pointers or integers, in which case they are only required to have the same size. This restriction exists because the register allocators in LLVM and GCC sometimes cannot handle tied operands with different types. From 83a5cdf0aec1a998fed98565829ee7b732b95134 Mon Sep 17 00:00:00 2001 From: Michal Sudwoj Date: Sat, 23 May 2020 03:55:34 +0200 Subject: [PATCH 09/10] Update src/doc/unstable-book/src/library-features/asm.md Co-authored-by: Amanieu d'Antras --- src/doc/unstable-book/src/library-features/asm.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/unstable-book/src/library-features/asm.md b/src/doc/unstable-book/src/library-features/asm.md index 50121b2c0fca4..ea560a6d70915 100644 --- a/src/doc/unstable-book/src/library-features/asm.md +++ b/src/doc/unstable-book/src/library-features/asm.md @@ -478,7 +478,7 @@ Here is the list of currently supported register classes: > > Note #2: On x86-64 the high byte registers (e.g. `ah`) are only available when used as an explicit register. Specifying the `reg_byte` register class for an operand will always allocate a low byte register. > -> Note #3: On NVPTX, register names are not supported. +> Note #3: NVPTX doesn't have a fixed register set, so named registers are not supported. Additional register classes may be added in the future based on demand (e.g. MMX, x87, etc). From e18054d5c07c2303380b47c3ea21f5bd7cccddc9 Mon Sep 17 00:00:00 2001 From: Michal Sudwoj Date: Sat, 23 May 2020 13:13:17 +0200 Subject: [PATCH 10/10] Added comment about static variables --- src/test/assembly/asm/nvptx-types.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/assembly/asm/nvptx-types.rs b/src/test/assembly/asm/nvptx-types.rs index b36efe16c64a1..4ee79d1bcc839 100644 --- a/src/test/assembly/asm/nvptx-types.rs +++ b/src/test/assembly/asm/nvptx-types.rs @@ -30,6 +30,7 @@ impl Copy for i64 {} impl Copy for f64 {} impl Copy for ptr {} +// NVPTX does not support static variables #[no_mangle] fn extern_func() {}