Skip to content

Commit 76fa5f2

Browse files
authored
Rollup merge of #78950 - khyperia:spirv-asm, r=Amanieu
Add asm register information for SPIR-V As discussed in [zulip](https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/Defining.20asm!.20for.20new.20architecture), we at [rust-gpu](https://github.com/EmbarkStudios/rust-gpu) would like to support `asm!` for our SPIR-V backend. However, we cannot do so purely without frontend support: [this match](https://github.com/rust-lang/rust/blob/d4ea0b3e46a0303d5802b632e88ba1ba84d9d16f/compiler/rustc_target/src/asm/mod.rs#L185) fails and so `asm!` is not supported ([error reported here](https://github.com/rust-lang/rust/blob/d4ea0b3e46a0303d5802b632e88ba1ba84d9d16f/compiler/rustc_ast_lowering/src/expr.rs#L1095)). To resolve this, we need to stub out register information for SPIR-V to support getting the `asm!` content all the way to [`AsmBuilderMethods::codegen_inline_asm`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/traits/trait.AsmBuilderMethods.html#tymethod.codegen_inline_asm), at which point the rust-gpu backend can do all the parsing and codegen that is needed. This is a pretty weird PR - adding support for a backend that isn't in-tree feels pretty gross to me, but I don't see an easy way around this. ``@Amanieu`` said I should submit it anyway, so, here we are! Let me know if this needs to go through a more formal process (MCP?) and what I should do to help this along. I based this off the [wasm asm PR](#78684), which unfortunately this PR conflicts with that one quite a bit, sorry for any merge conflict pain :( --- Some open questions: - What do we call the register class? Some context, SPIR-V is an SSA-based IR, there are "instructions" that create IDs (referred to as `<id>` in the spec), which can be referenced by other instructions. So, `reg` isn't exactly accurate, they're SSA IDs, not re-assignable registers. - What happens when a SPIR-V register gets to the LLVM backend? Right now it's a `bug!`, but should that be a `sess.fatal()`? I'm not sure if it's even possible to reach that point, maybe there's a check that prevents the `spirv` target from even reaching that codepath.
2 parents 4088981 + 0e34b73 commit 76fa5f2

File tree

3 files changed

+78
-1
lines changed

3 files changed

+78
-1
lines changed

compiler/rustc_codegen_llvm/src/asm.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ use rustc_codegen_ssa::mir::place::PlaceRef;
1212
use rustc_codegen_ssa::traits::*;
1313
use rustc_data_structures::fx::FxHashMap;
1414
use rustc_hir as hir;
15-
use rustc_middle::span_bug;
1615
use rustc_middle::ty::layout::TyAndLayout;
16+
use rustc_middle::{bug, span_bug};
1717
use rustc_span::{Pos, Span};
1818
use rustc_target::abi::*;
1919
use rustc_target::asm::*;
@@ -260,6 +260,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
260260
InlineAsmArch::Nvptx64 => {}
261261
InlineAsmArch::Hexagon => {}
262262
InlineAsmArch::Mips | InlineAsmArch::Mips64 => {}
263+
InlineAsmArch::SpirV => {}
263264
}
264265
}
265266
if !options.contains(InlineAsmOptions::NOMEM) {
@@ -518,6 +519,9 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>)
518519
| InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) => "x",
519520
InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v",
520521
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => "^Yk",
522+
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
523+
bug!("LLVM backend does not support SPIR-V")
524+
}
521525
}
522526
.to_string(),
523527
}
@@ -580,6 +584,9 @@ fn modifier_to_llvm(
580584
_ => unreachable!(),
581585
},
582586
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => None,
587+
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
588+
bug!("LLVM backend does not support SPIR-V")
589+
}
583590
}
584591
}
585592

@@ -619,6 +626,9 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll
619626
| InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg)
620627
| InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => cx.type_f32(),
621628
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => cx.type_i16(),
629+
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
630+
bug!("LLVM backend does not support SPIR-V")
631+
}
622632
}
623633
}
624634

compiler/rustc_target/src/asm/mod.rs

+21
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ mod hexagon;
155155
mod mips;
156156
mod nvptx;
157157
mod riscv;
158+
mod spirv;
158159
mod x86;
159160

160161
pub use aarch64::{AArch64InlineAsmReg, AArch64InlineAsmRegClass};
@@ -163,6 +164,7 @@ pub use hexagon::{HexagonInlineAsmReg, HexagonInlineAsmRegClass};
163164
pub use mips::{MipsInlineAsmReg, MipsInlineAsmRegClass};
164165
pub use nvptx::{NvptxInlineAsmReg, NvptxInlineAsmRegClass};
165166
pub use riscv::{RiscVInlineAsmReg, RiscVInlineAsmRegClass};
167+
pub use spirv::{SpirVInlineAsmReg, SpirVInlineAsmRegClass};
166168
pub use x86::{X86InlineAsmReg, X86InlineAsmRegClass};
167169

168170
#[derive(Copy, Clone, Encodable, Decodable, Debug, Eq, PartialEq, Hash)]
@@ -177,6 +179,7 @@ pub enum InlineAsmArch {
177179
Hexagon,
178180
Mips,
179181
Mips64,
182+
SpirV,
180183
}
181184

182185
impl FromStr for InlineAsmArch {
@@ -194,6 +197,7 @@ impl FromStr for InlineAsmArch {
194197
"hexagon" => Ok(Self::Hexagon),
195198
"mips" => Ok(Self::Mips),
196199
"mips64" => Ok(Self::Mips64),
200+
"spirv" => Ok(Self::SpirV),
197201
_ => Err(()),
198202
}
199203
}
@@ -208,6 +212,7 @@ pub enum InlineAsmReg {
208212
Nvptx(NvptxInlineAsmReg),
209213
Hexagon(HexagonInlineAsmReg),
210214
Mips(MipsInlineAsmReg),
215+
SpirV(SpirVInlineAsmReg),
211216
}
212217

213218
impl InlineAsmReg {
@@ -264,6 +269,9 @@ impl InlineAsmReg {
264269
InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
265270
Self::Mips(MipsInlineAsmReg::parse(arch, has_feature, target, &name)?)
266271
}
272+
InlineAsmArch::SpirV => {
273+
Self::SpirV(SpirVInlineAsmReg::parse(arch, has_feature, target, &name)?)
274+
}
267275
})
268276
}
269277

@@ -306,6 +314,7 @@ pub enum InlineAsmRegClass {
306314
Nvptx(NvptxInlineAsmRegClass),
307315
Hexagon(HexagonInlineAsmRegClass),
308316
Mips(MipsInlineAsmRegClass),
317+
SpirV(SpirVInlineAsmRegClass),
309318
}
310319

311320
impl InlineAsmRegClass {
@@ -318,6 +327,7 @@ impl InlineAsmRegClass {
318327
Self::Nvptx(r) => r.name(),
319328
Self::Hexagon(r) => r.name(),
320329
Self::Mips(r) => r.name(),
330+
Self::SpirV(r) => r.name(),
321331
}
322332
}
323333

@@ -333,6 +343,7 @@ impl InlineAsmRegClass {
333343
Self::Nvptx(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Nvptx),
334344
Self::Hexagon(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Hexagon),
335345
Self::Mips(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Mips),
346+
Self::SpirV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::SpirV),
336347
}
337348
}
338349

@@ -355,6 +366,7 @@ impl InlineAsmRegClass {
355366
Self::Nvptx(r) => r.suggest_modifier(arch, ty),
356367
Self::Hexagon(r) => r.suggest_modifier(arch, ty),
357368
Self::Mips(r) => r.suggest_modifier(arch, ty),
369+
Self::SpirV(r) => r.suggest_modifier(arch, ty),
358370
}
359371
}
360372

@@ -373,6 +385,7 @@ impl InlineAsmRegClass {
373385
Self::Nvptx(r) => r.default_modifier(arch),
374386
Self::Hexagon(r) => r.default_modifier(arch),
375387
Self::Mips(r) => r.default_modifier(arch),
388+
Self::SpirV(r) => r.default_modifier(arch),
376389
}
377390
}
378391

@@ -390,6 +403,7 @@ impl InlineAsmRegClass {
390403
Self::Nvptx(r) => r.supported_types(arch),
391404
Self::Hexagon(r) => r.supported_types(arch),
392405
Self::Mips(r) => r.supported_types(arch),
406+
Self::SpirV(r) => r.supported_types(arch),
393407
}
394408
}
395409

@@ -414,6 +428,7 @@ impl InlineAsmRegClass {
414428
InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
415429
Self::Mips(MipsInlineAsmRegClass::parse(arch, name)?)
416430
}
431+
InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmRegClass::parse(arch, name)?),
417432
})
418433
})
419434
}
@@ -429,6 +444,7 @@ impl InlineAsmRegClass {
429444
Self::Nvptx(r) => r.valid_modifiers(arch),
430445
Self::Hexagon(r) => r.valid_modifiers(arch),
431446
Self::Mips(r) => r.valid_modifiers(arch),
447+
Self::SpirV(r) => r.valid_modifiers(arch),
432448
}
433449
}
434450
}
@@ -571,5 +587,10 @@ pub fn allocatable_registers(
571587
mips::fill_reg_map(arch, has_feature, target, &mut map);
572588
map
573589
}
590+
InlineAsmArch::SpirV => {
591+
let mut map = spirv::regclass_map();
592+
spirv::fill_reg_map(arch, has_feature, target, &mut map);
593+
map
594+
}
574595
}
575596
}
+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
use super::{InlineAsmArch, InlineAsmType};
2+
use rustc_macros::HashStable_Generic;
3+
4+
def_reg_class! {
5+
SpirV SpirVInlineAsmRegClass {
6+
reg,
7+
}
8+
}
9+
10+
impl SpirVInlineAsmRegClass {
11+
pub fn valid_modifiers(self, _arch: super::InlineAsmArch) -> &'static [char] {
12+
&[]
13+
}
14+
15+
pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option<Self> {
16+
None
17+
}
18+
19+
pub fn suggest_modifier(
20+
self,
21+
_arch: InlineAsmArch,
22+
_ty: InlineAsmType,
23+
) -> Option<(char, &'static str)> {
24+
None
25+
}
26+
27+
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> {
28+
None
29+
}
30+
31+
pub fn supported_types(
32+
self,
33+
_arch: InlineAsmArch,
34+
) -> &'static [(InlineAsmType, Option<&'static str>)] {
35+
match self {
36+
Self::reg => {
37+
types! { _: I8, I16, I32, I64, F32, F64; }
38+
}
39+
}
40+
}
41+
}
42+
43+
def_regs! {
44+
// SPIR-V is SSA-based, it does not have registers.
45+
SpirV SpirVInlineAsmReg SpirVInlineAsmRegClass {}
46+
}

0 commit comments

Comments
 (0)