rustc_target/asm/
riscv.rs

1use std::fmt;
2
3use rustc_data_structures::fx::FxIndexSet;
4use rustc_span::{Symbol, sym};
5
6use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
7use crate::spec::{RelocModel, Target};
8
9def_reg_class! {
10    RiscV RiscVInlineAsmRegClass {
11        reg,
12        freg,
13        vreg,
14    }
15}
16
17impl RiscVInlineAsmRegClass {
18    pub fn valid_modifiers(self, _arch: super::InlineAsmArch) -> &'static [char] {
19        &[]
20    }
21
22    pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option<Self> {
23        None
24    }
25
26    pub fn suggest_modifier(
27        self,
28        _arch: InlineAsmArch,
29        _ty: InlineAsmType,
30    ) -> Option<ModifierInfo> {
31        None
32    }
33
34    pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<ModifierInfo> {
35        None
36    }
37
38    pub fn supported_types(
39        self,
40        arch: InlineAsmArch,
41    ) -> &'static [(InlineAsmType, Option<Symbol>)] {
42        match self {
43            Self::reg => {
44                if arch == InlineAsmArch::RiscV64 {
45                    types! { _: I8, I16, I32, I64, F16, F32, F64; }
46                } else {
47                    types! { _: I8, I16, I32, F16, F32; }
48                }
49            }
50            // FIXME(f16_f128): Add `q: F128;` once LLVM support the `Q` extension.
51            Self::freg => types! { f: F16, F32; d: F64; },
52            Self::vreg => &[],
53        }
54    }
55}
56
57pub(crate) fn is_e(target_features: &FxIndexSet<Symbol>) -> bool {
58    target_features.contains(&sym::e)
59}
60
61fn not_e(
62    _arch: InlineAsmArch,
63    _reloc_model: RelocModel,
64    target_features: &FxIndexSet<Symbol>,
65    _target: &Target,
66    _is_clobber: bool,
67) -> Result<(), &'static str> {
68    if is_e(target_features) {
69        Err("register can't be used with the `e` target feature")
70    } else {
71        Ok(())
72    }
73}
74
75def_regs! {
76    RiscV RiscVInlineAsmReg RiscVInlineAsmRegClass {
77        x1: reg = ["x1", "ra"],
78        x5: reg = ["x5", "t0"],
79        x6: reg = ["x6", "t1"],
80        x7: reg = ["x7", "t2"],
81        x10: reg = ["x10", "a0"],
82        x11: reg = ["x11", "a1"],
83        x12: reg = ["x12", "a2"],
84        x13: reg = ["x13", "a3"],
85        x14: reg = ["x14", "a4"],
86        x15: reg = ["x15", "a5"],
87        x16: reg = ["x16", "a6"] % not_e,
88        x17: reg = ["x17", "a7"] % not_e,
89        x18: reg = ["x18", "s2"] % not_e,
90        x19: reg = ["x19", "s3"] % not_e,
91        x20: reg = ["x20", "s4"] % not_e,
92        x21: reg = ["x21", "s5"] % not_e,
93        x22: reg = ["x22", "s6"] % not_e,
94        x23: reg = ["x23", "s7"] % not_e,
95        x24: reg = ["x24", "s8"] % not_e,
96        x25: reg = ["x25", "s9"] % not_e,
97        x26: reg = ["x26", "s10"] % not_e,
98        x27: reg = ["x27", "s11"] % not_e,
99        x28: reg = ["x28", "t3"] % not_e,
100        x29: reg = ["x29", "t4"] % not_e,
101        x30: reg = ["x30", "t5"] % not_e,
102        x31: reg = ["x31", "t6"] % not_e,
103        f0: freg = ["f0", "ft0"],
104        f1: freg = ["f1", "ft1"],
105        f2: freg = ["f2", "ft2"],
106        f3: freg = ["f3", "ft3"],
107        f4: freg = ["f4", "ft4"],
108        f5: freg = ["f5", "ft5"],
109        f6: freg = ["f6", "ft6"],
110        f7: freg = ["f7", "ft7"],
111        f8: freg = ["f8", "fs0"],
112        f9: freg = ["f9", "fs1"],
113        f10: freg = ["f10", "fa0"],
114        f11: freg = ["f11", "fa1"],
115        f12: freg = ["f12", "fa2"],
116        f13: freg = ["f13", "fa3"],
117        f14: freg = ["f14", "fa4"],
118        f15: freg = ["f15", "fa5"],
119        f16: freg = ["f16", "fa6"],
120        f17: freg = ["f17", "fa7"],
121        f18: freg = ["f18", "fs2"],
122        f19: freg = ["f19", "fs3"],
123        f20: freg = ["f20", "fs4"],
124        f21: freg = ["f21", "fs5"],
125        f22: freg = ["f22", "fs6"],
126        f23: freg = ["f23", "fs7"],
127        f24: freg = ["f24", "fs8"],
128        f25: freg = ["f25", "fs9"],
129        f26: freg = ["f26", "fs10"],
130        f27: freg = ["f27", "fs11"],
131        f28: freg = ["f28", "ft8"],
132        f29: freg = ["f29", "ft9"],
133        f30: freg = ["f30", "ft10"],
134        f31: freg = ["f31", "ft11"],
135        v0: vreg = ["v0"],
136        v1: vreg = ["v1"],
137        v2: vreg = ["v2"],
138        v3: vreg = ["v3"],
139        v4: vreg = ["v4"],
140        v5: vreg = ["v5"],
141        v6: vreg = ["v6"],
142        v7: vreg = ["v7"],
143        v8: vreg = ["v8"],
144        v9: vreg = ["v9"],
145        v10: vreg = ["v10"],
146        v11: vreg = ["v11"],
147        v12: vreg = ["v12"],
148        v13: vreg = ["v13"],
149        v14: vreg = ["v14"],
150        v15: vreg = ["v15"],
151        v16: vreg = ["v16"],
152        v17: vreg = ["v17"],
153        v18: vreg = ["v18"],
154        v19: vreg = ["v19"],
155        v20: vreg = ["v20"],
156        v21: vreg = ["v21"],
157        v22: vreg = ["v22"],
158        v23: vreg = ["v23"],
159        v24: vreg = ["v24"],
160        v25: vreg = ["v25"],
161        v26: vreg = ["v26"],
162        v27: vreg = ["v27"],
163        v28: vreg = ["v28"],
164        v29: vreg = ["v29"],
165        v30: vreg = ["v30"],
166        v31: vreg = ["v31"],
167        #error = ["x9", "s1"] =>
168            "s1 is used internally by LLVM and cannot be used as an operand for inline asm",
169        #error = ["x8", "s0", "fp"] =>
170            "the frame pointer cannot be used as an operand for inline asm",
171        #error = ["x2", "sp"] =>
172            "the stack pointer cannot be used as an operand for inline asm",
173        #error = ["x3", "gp"] =>
174            "the global pointer cannot be used as an operand for inline asm",
175        #error = ["x4", "tp"] =>
176            "the thread pointer cannot be used as an operand for inline asm" ,
177        #error = ["x0", "zero"] =>
178            "the zero register cannot be used as an operand for inline asm",
179    }
180}
181
182impl RiscVInlineAsmReg {
183    pub fn emit(
184        self,
185        out: &mut dyn fmt::Write,
186        _arch: InlineAsmArch,
187        _modifier: Option<char>,
188    ) -> fmt::Result {
189        out.write_str(self.name())
190    }
191}