]>
Commit | Line | Data |
---|---|---|
f035d41b | 1 | use crate::spec::Target; |
5e7ed085 | 2 | use crate::{abi::Size, spec::RelocModel}; |
f9f354fc XL |
3 | use rustc_data_structures::fx::{FxHashMap, FxHashSet}; |
4 | use rustc_macros::HashStable_Generic; | |
5 | use rustc_span::Symbol; | |
6 | use std::fmt; | |
7 | use std::str::FromStr; | |
8 | ||
f9f354fc XL |
9 | macro_rules! def_reg_class { |
10 | ($arch:ident $arch_regclass:ident { | |
11 | $( | |
12 | $class:ident, | |
13 | )* | |
14 | }) => { | |
6a06907d | 15 | #[derive(Copy, Clone, Encodable, Decodable, Debug, Eq, PartialEq, PartialOrd, Hash, HashStable_Generic)] |
f9f354fc XL |
16 | #[allow(non_camel_case_types)] |
17 | pub enum $arch_regclass { | |
18 | $($class,)* | |
19 | } | |
20 | ||
21 | impl $arch_regclass { | |
fc512014 | 22 | pub fn name(self) -> rustc_span::Symbol { |
f9f354fc | 23 | match self { |
fc512014 | 24 | $(Self::$class => rustc_span::symbol::sym::$class,)* |
f9f354fc XL |
25 | } |
26 | } | |
27 | ||
5e7ed085 | 28 | pub fn parse(name: rustc_span::Symbol) -> Result<Self, &'static str> { |
f9f354fc XL |
29 | match name { |
30 | $( | |
fc512014 | 31 | rustc_span::sym::$class => Ok(Self::$class), |
f9f354fc XL |
32 | )* |
33 | _ => Err("unknown register class"), | |
34 | } | |
35 | } | |
36 | } | |
37 | ||
38 | pub(super) fn regclass_map() -> rustc_data_structures::fx::FxHashMap< | |
39 | super::InlineAsmRegClass, | |
40 | rustc_data_structures::fx::FxHashSet<super::InlineAsmReg>, | |
41 | > { | |
42 | use rustc_data_structures::fx::{FxHashMap, FxHashSet}; | |
43 | use super::InlineAsmRegClass; | |
44 | let mut map = FxHashMap::default(); | |
45 | $( | |
46 | map.insert(InlineAsmRegClass::$arch($arch_regclass::$class), FxHashSet::default()); | |
47 | )* | |
48 | map | |
49 | } | |
50 | } | |
51 | } | |
52 | ||
f9f354fc XL |
53 | macro_rules! def_regs { |
54 | ($arch:ident $arch_reg:ident $arch_regclass:ident { | |
55 | $( | |
56 | $reg:ident: $class:ident $(, $extra_class:ident)* = [$reg_name:literal $(, $alias:literal)*] $(% $filter:ident)?, | |
57 | )* | |
58 | $( | |
59 | #error = [$($bad_reg:literal),+] => $error:literal, | |
60 | )* | |
61 | }) => { | |
62 | #[allow(unreachable_code)] | |
6a06907d | 63 | #[derive(Copy, Clone, Encodable, Decodable, Debug, Eq, PartialEq, PartialOrd, Hash, HashStable_Generic)] |
f9f354fc XL |
64 | #[allow(non_camel_case_types)] |
65 | pub enum $arch_reg { | |
66 | $($reg,)* | |
67 | } | |
68 | ||
69 | impl $arch_reg { | |
70 | pub fn name(self) -> &'static str { | |
71 | match self { | |
72 | $(Self::$reg => $reg_name,)* | |
73 | } | |
74 | } | |
75 | ||
76 | pub fn reg_class(self) -> $arch_regclass { | |
77 | match self { | |
78 | $(Self::$reg => $arch_regclass::$class,)* | |
79 | } | |
80 | } | |
81 | ||
5e7ed085 | 82 | pub fn parse(name: &str) -> Result<Self, &'static str> { |
f9f354fc XL |
83 | match name { |
84 | $( | |
5e7ed085 | 85 | $($alias)|* | $reg_name => Ok(Self::$reg), |
f9f354fc XL |
86 | )* |
87 | $( | |
88 | $($bad_reg)|* => Err($error), | |
89 | )* | |
90 | _ => Err("unknown register"), | |
91 | } | |
92 | } | |
5e7ed085 FG |
93 | |
94 | pub fn validate(self, | |
95 | _arch: super::InlineAsmArch, | |
96 | _reloc_model: crate::spec::RelocModel, | |
97 | _target_features: &rustc_data_structures::fx::FxHashSet<Symbol>, | |
98 | _target: &crate::spec::Target, | |
99 | _is_clobber: bool, | |
100 | ) -> Result<(), &'static str> { | |
101 | match self { | |
102 | $( | |
103 | Self::$reg => { | |
104 | $($filter( | |
105 | _arch, | |
106 | _reloc_model, | |
107 | _target_features, | |
108 | _target, | |
109 | _is_clobber | |
110 | )?;)? | |
111 | Ok(()) | |
112 | } | |
113 | )* | |
114 | } | |
115 | } | |
f9f354fc XL |
116 | } |
117 | ||
118 | pub(super) fn fill_reg_map( | |
119 | _arch: super::InlineAsmArch, | |
5e7ed085 | 120 | _reloc_model: crate::spec::RelocModel, |
5099ac24 | 121 | _target_features: &rustc_data_structures::fx::FxHashSet<Symbol>, |
f035d41b | 122 | _target: &crate::spec::Target, |
f9f354fc XL |
123 | _map: &mut rustc_data_structures::fx::FxHashMap< |
124 | super::InlineAsmRegClass, | |
125 | rustc_data_structures::fx::FxHashSet<super::InlineAsmReg>, | |
126 | >, | |
127 | ) { | |
128 | #[allow(unused_imports)] | |
129 | use super::{InlineAsmReg, InlineAsmRegClass}; | |
130 | $( | |
5e7ed085 | 131 | if $($filter(_arch, _reloc_model, _target_features, _target, false).is_ok() &&)? true { |
f9f354fc XL |
132 | if let Some(set) = _map.get_mut(&InlineAsmRegClass::$arch($arch_regclass::$class)) { |
133 | set.insert(InlineAsmReg::$arch($arch_reg::$reg)); | |
134 | } | |
135 | $( | |
136 | if let Some(set) = _map.get_mut(&InlineAsmRegClass::$arch($arch_regclass::$extra_class)) { | |
137 | set.insert(InlineAsmReg::$arch($arch_reg::$reg)); | |
138 | } | |
139 | )* | |
140 | } | |
141 | )* | |
142 | } | |
143 | } | |
144 | } | |
145 | ||
f9f354fc XL |
146 | macro_rules! types { |
147 | ( | |
148 | $(_ : $($ty:expr),+;)? | |
5099ac24 | 149 | $($feature:ident: $($ty2:expr),+;)* |
f9f354fc XL |
150 | ) => { |
151 | { | |
152 | use super::InlineAsmType::*; | |
153 | &[ | |
154 | $($( | |
155 | ($ty, None), | |
156 | )*)? | |
157 | $($( | |
5099ac24 | 158 | ($ty2, Some(rustc_span::sym::$feature)), |
f9f354fc XL |
159 | )*)* |
160 | ] | |
161 | } | |
162 | }; | |
163 | } | |
164 | ||
165 | mod aarch64; | |
166 | mod arm; | |
a2a8927a | 167 | mod avr; |
17df50a5 | 168 | mod bpf; |
f035d41b | 169 | mod hexagon; |
1b1a35ee | 170 | mod mips; |
5099ac24 | 171 | mod msp430; |
f9f354fc | 172 | mod nvptx; |
17df50a5 | 173 | mod powerpc; |
f9f354fc | 174 | mod riscv; |
94222f64 | 175 | mod s390x; |
29967ef6 | 176 | mod spirv; |
fc512014 | 177 | mod wasm; |
f9f354fc XL |
178 | mod x86; |
179 | ||
180 | pub use aarch64::{AArch64InlineAsmReg, AArch64InlineAsmRegClass}; | |
181 | pub use arm::{ArmInlineAsmReg, ArmInlineAsmRegClass}; | |
a2a8927a | 182 | pub use avr::{AvrInlineAsmReg, AvrInlineAsmRegClass}; |
17df50a5 | 183 | pub use bpf::{BpfInlineAsmReg, BpfInlineAsmRegClass}; |
f035d41b | 184 | pub use hexagon::{HexagonInlineAsmReg, HexagonInlineAsmRegClass}; |
1b1a35ee | 185 | pub use mips::{MipsInlineAsmReg, MipsInlineAsmRegClass}; |
5099ac24 | 186 | pub use msp430::{Msp430InlineAsmReg, Msp430InlineAsmRegClass}; |
f9f354fc | 187 | pub use nvptx::{NvptxInlineAsmReg, NvptxInlineAsmRegClass}; |
17df50a5 | 188 | pub use powerpc::{PowerPCInlineAsmReg, PowerPCInlineAsmRegClass}; |
f9f354fc | 189 | pub use riscv::{RiscVInlineAsmReg, RiscVInlineAsmRegClass}; |
94222f64 | 190 | pub use s390x::{S390xInlineAsmReg, S390xInlineAsmRegClass}; |
29967ef6 | 191 | pub use spirv::{SpirVInlineAsmReg, SpirVInlineAsmRegClass}; |
fc512014 | 192 | pub use wasm::{WasmInlineAsmReg, WasmInlineAsmRegClass}; |
f9f354fc XL |
193 | pub use x86::{X86InlineAsmReg, X86InlineAsmRegClass}; |
194 | ||
3dfed10e | 195 | #[derive(Copy, Clone, Encodable, Decodable, Debug, Eq, PartialEq, Hash)] |
f9f354fc XL |
196 | pub enum InlineAsmArch { |
197 | X86, | |
198 | X86_64, | |
199 | Arm, | |
200 | AArch64, | |
201 | RiscV32, | |
202 | RiscV64, | |
203 | Nvptx64, | |
f035d41b | 204 | Hexagon, |
1b1a35ee | 205 | Mips, |
29967ef6 | 206 | Mips64, |
17df50a5 XL |
207 | PowerPC, |
208 | PowerPC64, | |
94222f64 | 209 | S390x, |
29967ef6 | 210 | SpirV, |
fc512014 | 211 | Wasm32, |
3c0e092e | 212 | Wasm64, |
17df50a5 | 213 | Bpf, |
a2a8927a | 214 | Avr, |
5099ac24 | 215 | Msp430, |
f9f354fc XL |
216 | } |
217 | ||
218 | impl FromStr for InlineAsmArch { | |
219 | type Err = (); | |
220 | ||
221 | fn from_str(s: &str) -> Result<InlineAsmArch, ()> { | |
222 | match s { | |
223 | "x86" => Ok(Self::X86), | |
224 | "x86_64" => Ok(Self::X86_64), | |
225 | "arm" => Ok(Self::Arm), | |
226 | "aarch64" => Ok(Self::AArch64), | |
227 | "riscv32" => Ok(Self::RiscV32), | |
228 | "riscv64" => Ok(Self::RiscV64), | |
229 | "nvptx64" => Ok(Self::Nvptx64), | |
17df50a5 XL |
230 | "powerpc" => Ok(Self::PowerPC), |
231 | "powerpc64" => Ok(Self::PowerPC64), | |
f035d41b | 232 | "hexagon" => Ok(Self::Hexagon), |
1b1a35ee | 233 | "mips" => Ok(Self::Mips), |
29967ef6 | 234 | "mips64" => Ok(Self::Mips64), |
94222f64 | 235 | "s390x" => Ok(Self::S390x), |
29967ef6 | 236 | "spirv" => Ok(Self::SpirV), |
fc512014 | 237 | "wasm32" => Ok(Self::Wasm32), |
3c0e092e | 238 | "wasm64" => Ok(Self::Wasm64), |
17df50a5 | 239 | "bpf" => Ok(Self::Bpf), |
a2a8927a | 240 | "avr" => Ok(Self::Avr), |
5099ac24 | 241 | "msp430" => Ok(Self::Msp430), |
f9f354fc XL |
242 | _ => Err(()), |
243 | } | |
244 | } | |
245 | } | |
246 | ||
6a06907d XL |
247 | #[derive( |
248 | Copy, | |
249 | Clone, | |
250 | Encodable, | |
251 | Decodable, | |
252 | Debug, | |
253 | Eq, | |
254 | PartialEq, | |
255 | PartialOrd, | |
256 | Hash, | |
257 | HashStable_Generic | |
258 | )] | |
f9f354fc XL |
259 | pub enum InlineAsmReg { |
260 | X86(X86InlineAsmReg), | |
261 | Arm(ArmInlineAsmReg), | |
262 | AArch64(AArch64InlineAsmReg), | |
263 | RiscV(RiscVInlineAsmReg), | |
264 | Nvptx(NvptxInlineAsmReg), | |
17df50a5 | 265 | PowerPC(PowerPCInlineAsmReg), |
f035d41b | 266 | Hexagon(HexagonInlineAsmReg), |
1b1a35ee | 267 | Mips(MipsInlineAsmReg), |
94222f64 | 268 | S390x(S390xInlineAsmReg), |
29967ef6 | 269 | SpirV(SpirVInlineAsmReg), |
fc512014 | 270 | Wasm(WasmInlineAsmReg), |
17df50a5 | 271 | Bpf(BpfInlineAsmReg), |
a2a8927a | 272 | Avr(AvrInlineAsmReg), |
5099ac24 | 273 | Msp430(Msp430InlineAsmReg), |
6a06907d XL |
274 | // Placeholder for invalid register constraints for the current target |
275 | Err, | |
f9f354fc XL |
276 | } |
277 | ||
278 | impl InlineAsmReg { | |
279 | pub fn name(self) -> &'static str { | |
280 | match self { | |
281 | Self::X86(r) => r.name(), | |
282 | Self::Arm(r) => r.name(), | |
283 | Self::AArch64(r) => r.name(), | |
284 | Self::RiscV(r) => r.name(), | |
17df50a5 | 285 | Self::PowerPC(r) => r.name(), |
f035d41b | 286 | Self::Hexagon(r) => r.name(), |
1b1a35ee | 287 | Self::Mips(r) => r.name(), |
94222f64 | 288 | Self::S390x(r) => r.name(), |
17df50a5 | 289 | Self::Bpf(r) => r.name(), |
a2a8927a | 290 | Self::Avr(r) => r.name(), |
5099ac24 | 291 | Self::Msp430(r) => r.name(), |
6a06907d | 292 | Self::Err => "<reg>", |
f9f354fc XL |
293 | } |
294 | } | |
295 | ||
296 | pub fn reg_class(self) -> InlineAsmRegClass { | |
297 | match self { | |
298 | Self::X86(r) => InlineAsmRegClass::X86(r.reg_class()), | |
299 | Self::Arm(r) => InlineAsmRegClass::Arm(r.reg_class()), | |
300 | Self::AArch64(r) => InlineAsmRegClass::AArch64(r.reg_class()), | |
301 | Self::RiscV(r) => InlineAsmRegClass::RiscV(r.reg_class()), | |
17df50a5 | 302 | Self::PowerPC(r) => InlineAsmRegClass::PowerPC(r.reg_class()), |
f035d41b | 303 | Self::Hexagon(r) => InlineAsmRegClass::Hexagon(r.reg_class()), |
1b1a35ee | 304 | Self::Mips(r) => InlineAsmRegClass::Mips(r.reg_class()), |
94222f64 | 305 | Self::S390x(r) => InlineAsmRegClass::S390x(r.reg_class()), |
17df50a5 | 306 | Self::Bpf(r) => InlineAsmRegClass::Bpf(r.reg_class()), |
a2a8927a | 307 | Self::Avr(r) => InlineAsmRegClass::Avr(r.reg_class()), |
5099ac24 | 308 | Self::Msp430(r) => InlineAsmRegClass::Msp430(r.reg_class()), |
6a06907d | 309 | Self::Err => InlineAsmRegClass::Err, |
f9f354fc XL |
310 | } |
311 | } | |
312 | ||
5e7ed085 | 313 | pub fn parse(arch: InlineAsmArch, name: Symbol) -> Result<Self, &'static str> { |
f9f354fc XL |
314 | // FIXME: use direct symbol comparison for register names |
315 | // Use `Symbol::as_str` instead of `Symbol::with` here because `has_feature` may access `Symbol`. | |
316 | let name = name.as_str(); | |
317 | Ok(match arch { | |
5e7ed085 FG |
318 | InlineAsmArch::X86 | InlineAsmArch::X86_64 => Self::X86(X86InlineAsmReg::parse(name)?), |
319 | InlineAsmArch::Arm => Self::Arm(ArmInlineAsmReg::parse(name)?), | |
320 | InlineAsmArch::AArch64 => Self::AArch64(AArch64InlineAsmReg::parse(name)?), | |
321 | InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => { | |
322 | Self::RiscV(RiscVInlineAsmReg::parse(name)?) | |
f035d41b | 323 | } |
5e7ed085 FG |
324 | InlineAsmArch::Nvptx64 => Self::Nvptx(NvptxInlineAsmReg::parse(name)?), |
325 | InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => { | |
326 | Self::PowerPC(PowerPCInlineAsmReg::parse(name)?) | |
fc512014 | 327 | } |
5e7ed085 FG |
328 | InlineAsmArch::Hexagon => Self::Hexagon(HexagonInlineAsmReg::parse(name)?), |
329 | InlineAsmArch::Mips | InlineAsmArch::Mips64 => { | |
330 | Self::Mips(MipsInlineAsmReg::parse(name)?) | |
a2a8927a | 331 | } |
5e7ed085 FG |
332 | InlineAsmArch::S390x => Self::S390x(S390xInlineAsmReg::parse(name)?), |
333 | InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmReg::parse(name)?), | |
334 | InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => { | |
335 | Self::Wasm(WasmInlineAsmReg::parse(name)?) | |
17df50a5 | 336 | } |
5e7ed085 FG |
337 | InlineAsmArch::Bpf => Self::Bpf(BpfInlineAsmReg::parse(name)?), |
338 | InlineAsmArch::Avr => Self::Avr(AvrInlineAsmReg::parse(name)?), | |
339 | InlineAsmArch::Msp430 => Self::Msp430(Msp430InlineAsmReg::parse(name)?), | |
f9f354fc XL |
340 | }) |
341 | } | |
342 | ||
5e7ed085 FG |
343 | pub fn validate( |
344 | self, | |
345 | arch: InlineAsmArch, | |
346 | reloc_model: RelocModel, | |
347 | target_features: &FxHashSet<Symbol>, | |
348 | target: &Target, | |
349 | is_clobber: bool, | |
350 | ) -> Result<(), &'static str> { | |
351 | match self { | |
352 | Self::X86(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), | |
353 | Self::Arm(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), | |
354 | Self::AArch64(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), | |
355 | Self::RiscV(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), | |
356 | Self::PowerPC(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), | |
357 | Self::Hexagon(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), | |
358 | Self::Mips(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), | |
359 | Self::S390x(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), | |
360 | Self::Bpf(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), | |
361 | Self::Avr(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), | |
362 | Self::Msp430(r) => r.validate(arch, reloc_model, target_features, target, is_clobber), | |
363 | Self::Err => unreachable!(), | |
364 | } | |
365 | } | |
366 | ||
f9f354fc XL |
367 | // NOTE: This function isn't used at the moment, but is needed to support |
368 | // falling back to an external assembler. | |
369 | pub fn emit( | |
370 | self, | |
371 | out: &mut dyn fmt::Write, | |
372 | arch: InlineAsmArch, | |
373 | modifier: Option<char>, | |
374 | ) -> fmt::Result { | |
375 | match self { | |
376 | Self::X86(r) => r.emit(out, arch, modifier), | |
377 | Self::Arm(r) => r.emit(out, arch, modifier), | |
378 | Self::AArch64(r) => r.emit(out, arch, modifier), | |
379 | Self::RiscV(r) => r.emit(out, arch, modifier), | |
17df50a5 | 380 | Self::PowerPC(r) => r.emit(out, arch, modifier), |
f035d41b | 381 | Self::Hexagon(r) => r.emit(out, arch, modifier), |
1b1a35ee | 382 | Self::Mips(r) => r.emit(out, arch, modifier), |
94222f64 | 383 | Self::S390x(r) => r.emit(out, arch, modifier), |
17df50a5 | 384 | Self::Bpf(r) => r.emit(out, arch, modifier), |
a2a8927a | 385 | Self::Avr(r) => r.emit(out, arch, modifier), |
5099ac24 | 386 | Self::Msp430(r) => r.emit(out, arch, modifier), |
6a06907d | 387 | Self::Err => unreachable!("Use of InlineAsmReg::Err"), |
f9f354fc XL |
388 | } |
389 | } | |
390 | ||
391 | pub fn overlapping_regs(self, mut cb: impl FnMut(InlineAsmReg)) { | |
392 | match self { | |
393 | Self::X86(r) => r.overlapping_regs(|r| cb(Self::X86(r))), | |
394 | Self::Arm(r) => r.overlapping_regs(|r| cb(Self::Arm(r))), | |
395 | Self::AArch64(_) => cb(self), | |
396 | Self::RiscV(_) => cb(self), | |
94222f64 | 397 | Self::PowerPC(r) => r.overlapping_regs(|r| cb(Self::PowerPC(r))), |
f035d41b | 398 | Self::Hexagon(r) => r.overlapping_regs(|r| cb(Self::Hexagon(r))), |
1b1a35ee | 399 | Self::Mips(_) => cb(self), |
94222f64 | 400 | Self::S390x(_) => cb(self), |
17df50a5 | 401 | Self::Bpf(r) => r.overlapping_regs(|r| cb(Self::Bpf(r))), |
a2a8927a | 402 | Self::Avr(r) => r.overlapping_regs(|r| cb(Self::Avr(r))), |
5099ac24 | 403 | Self::Msp430(_) => cb(self), |
6a06907d | 404 | Self::Err => unreachable!("Use of InlineAsmReg::Err"), |
f9f354fc XL |
405 | } |
406 | } | |
407 | } | |
408 | ||
6a06907d XL |
409 | #[derive( |
410 | Copy, | |
411 | Clone, | |
412 | Encodable, | |
413 | Decodable, | |
414 | Debug, | |
415 | Eq, | |
416 | PartialEq, | |
417 | PartialOrd, | |
418 | Hash, | |
419 | HashStable_Generic | |
420 | )] | |
f9f354fc XL |
421 | pub enum InlineAsmRegClass { |
422 | X86(X86InlineAsmRegClass), | |
423 | Arm(ArmInlineAsmRegClass), | |
424 | AArch64(AArch64InlineAsmRegClass), | |
425 | RiscV(RiscVInlineAsmRegClass), | |
426 | Nvptx(NvptxInlineAsmRegClass), | |
17df50a5 | 427 | PowerPC(PowerPCInlineAsmRegClass), |
f035d41b | 428 | Hexagon(HexagonInlineAsmRegClass), |
1b1a35ee | 429 | Mips(MipsInlineAsmRegClass), |
94222f64 | 430 | S390x(S390xInlineAsmRegClass), |
29967ef6 | 431 | SpirV(SpirVInlineAsmRegClass), |
fc512014 | 432 | Wasm(WasmInlineAsmRegClass), |
17df50a5 | 433 | Bpf(BpfInlineAsmRegClass), |
a2a8927a | 434 | Avr(AvrInlineAsmRegClass), |
5099ac24 | 435 | Msp430(Msp430InlineAsmRegClass), |
6a06907d XL |
436 | // Placeholder for invalid register constraints for the current target |
437 | Err, | |
f9f354fc XL |
438 | } |
439 | ||
440 | impl InlineAsmRegClass { | |
fc512014 | 441 | pub fn name(self) -> Symbol { |
f9f354fc XL |
442 | match self { |
443 | Self::X86(r) => r.name(), | |
444 | Self::Arm(r) => r.name(), | |
445 | Self::AArch64(r) => r.name(), | |
446 | Self::RiscV(r) => r.name(), | |
447 | Self::Nvptx(r) => r.name(), | |
17df50a5 | 448 | Self::PowerPC(r) => r.name(), |
f035d41b | 449 | Self::Hexagon(r) => r.name(), |
1b1a35ee | 450 | Self::Mips(r) => r.name(), |
94222f64 | 451 | Self::S390x(r) => r.name(), |
29967ef6 | 452 | Self::SpirV(r) => r.name(), |
fc512014 | 453 | Self::Wasm(r) => r.name(), |
17df50a5 | 454 | Self::Bpf(r) => r.name(), |
a2a8927a | 455 | Self::Avr(r) => r.name(), |
5099ac24 | 456 | Self::Msp430(r) => r.name(), |
6a06907d | 457 | Self::Err => rustc_span::symbol::sym::reg, |
f9f354fc XL |
458 | } |
459 | } | |
460 | ||
461 | /// Returns a suggested register class to use for this type. This is called | |
5099ac24 | 462 | /// when `supported_types` fails to give a better error |
f9f354fc XL |
463 | /// message to the user. |
464 | pub fn suggest_class(self, arch: InlineAsmArch, ty: InlineAsmType) -> Option<Self> { | |
465 | match self { | |
466 | Self::X86(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::X86), | |
467 | Self::Arm(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Arm), | |
468 | Self::AArch64(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::AArch64), | |
469 | Self::RiscV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::RiscV), | |
470 | Self::Nvptx(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Nvptx), | |
17df50a5 | 471 | Self::PowerPC(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::PowerPC), |
f035d41b | 472 | Self::Hexagon(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Hexagon), |
1b1a35ee | 473 | Self::Mips(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Mips), |
94222f64 | 474 | Self::S390x(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::S390x), |
29967ef6 | 475 | Self::SpirV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::SpirV), |
fc512014 | 476 | Self::Wasm(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Wasm), |
17df50a5 | 477 | Self::Bpf(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Bpf), |
a2a8927a | 478 | Self::Avr(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Avr), |
5099ac24 | 479 | Self::Msp430(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Msp430), |
6a06907d | 480 | Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), |
f9f354fc XL |
481 | } |
482 | } | |
483 | ||
484 | /// Returns a suggested template modifier to use for this type and an | |
485 | /// example of a register named formatted with it. | |
486 | /// | |
487 | /// Such suggestions are useful if a type smaller than the full register | |
488 | /// size is used and a modifier can be used to point to the subregister of | |
489 | /// the correct size. | |
490 | pub fn suggest_modifier( | |
491 | self, | |
492 | arch: InlineAsmArch, | |
493 | ty: InlineAsmType, | |
494 | ) -> Option<(char, &'static str)> { | |
495 | match self { | |
496 | Self::X86(r) => r.suggest_modifier(arch, ty), | |
497 | Self::Arm(r) => r.suggest_modifier(arch, ty), | |
498 | Self::AArch64(r) => r.suggest_modifier(arch, ty), | |
499 | Self::RiscV(r) => r.suggest_modifier(arch, ty), | |
500 | Self::Nvptx(r) => r.suggest_modifier(arch, ty), | |
17df50a5 | 501 | Self::PowerPC(r) => r.suggest_modifier(arch, ty), |
f035d41b | 502 | Self::Hexagon(r) => r.suggest_modifier(arch, ty), |
1b1a35ee | 503 | Self::Mips(r) => r.suggest_modifier(arch, ty), |
94222f64 | 504 | Self::S390x(r) => r.suggest_modifier(arch, ty), |
29967ef6 | 505 | Self::SpirV(r) => r.suggest_modifier(arch, ty), |
fc512014 | 506 | Self::Wasm(r) => r.suggest_modifier(arch, ty), |
17df50a5 | 507 | Self::Bpf(r) => r.suggest_modifier(arch, ty), |
a2a8927a | 508 | Self::Avr(r) => r.suggest_modifier(arch, ty), |
5099ac24 | 509 | Self::Msp430(r) => r.suggest_modifier(arch, ty), |
6a06907d | 510 | Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), |
f9f354fc XL |
511 | } |
512 | } | |
513 | ||
514 | /// Returns the default modifier for this register and an example of a | |
515 | /// register named formatted with it. | |
516 | /// | |
517 | /// This is only needed when the register class can suggest a modifier, so | |
518 | /// that the user can be shown how to get the default behavior without a | |
519 | /// warning. | |
520 | pub fn default_modifier(self, arch: InlineAsmArch) -> Option<(char, &'static str)> { | |
521 | match self { | |
522 | Self::X86(r) => r.default_modifier(arch), | |
523 | Self::Arm(r) => r.default_modifier(arch), | |
524 | Self::AArch64(r) => r.default_modifier(arch), | |
525 | Self::RiscV(r) => r.default_modifier(arch), | |
526 | Self::Nvptx(r) => r.default_modifier(arch), | |
17df50a5 | 527 | Self::PowerPC(r) => r.default_modifier(arch), |
f035d41b | 528 | Self::Hexagon(r) => r.default_modifier(arch), |
1b1a35ee | 529 | Self::Mips(r) => r.default_modifier(arch), |
94222f64 | 530 | Self::S390x(r) => r.default_modifier(arch), |
29967ef6 | 531 | Self::SpirV(r) => r.default_modifier(arch), |
fc512014 | 532 | Self::Wasm(r) => r.default_modifier(arch), |
17df50a5 | 533 | Self::Bpf(r) => r.default_modifier(arch), |
a2a8927a | 534 | Self::Avr(r) => r.default_modifier(arch), |
5099ac24 | 535 | Self::Msp430(r) => r.default_modifier(arch), |
6a06907d | 536 | Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), |
f9f354fc XL |
537 | } |
538 | } | |
539 | ||
94222f64 | 540 | /// Returns a list of supported types for this register class, each with an |
f9f354fc XL |
541 | /// options target feature required to use this type. |
542 | pub fn supported_types( | |
543 | self, | |
544 | arch: InlineAsmArch, | |
5099ac24 | 545 | ) -> &'static [(InlineAsmType, Option<Symbol>)] { |
f9f354fc XL |
546 | match self { |
547 | Self::X86(r) => r.supported_types(arch), | |
548 | Self::Arm(r) => r.supported_types(arch), | |
549 | Self::AArch64(r) => r.supported_types(arch), | |
550 | Self::RiscV(r) => r.supported_types(arch), | |
551 | Self::Nvptx(r) => r.supported_types(arch), | |
17df50a5 | 552 | Self::PowerPC(r) => r.supported_types(arch), |
f035d41b | 553 | Self::Hexagon(r) => r.supported_types(arch), |
1b1a35ee | 554 | Self::Mips(r) => r.supported_types(arch), |
94222f64 | 555 | Self::S390x(r) => r.supported_types(arch), |
29967ef6 | 556 | Self::SpirV(r) => r.supported_types(arch), |
fc512014 | 557 | Self::Wasm(r) => r.supported_types(arch), |
17df50a5 | 558 | Self::Bpf(r) => r.supported_types(arch), |
a2a8927a | 559 | Self::Avr(r) => r.supported_types(arch), |
5099ac24 | 560 | Self::Msp430(r) => r.supported_types(arch), |
6a06907d | 561 | Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), |
f9f354fc XL |
562 | } |
563 | } | |
564 | ||
565 | pub fn parse(arch: InlineAsmArch, name: Symbol) -> Result<Self, &'static str> { | |
fc512014 XL |
566 | Ok(match arch { |
567 | InlineAsmArch::X86 | InlineAsmArch::X86_64 => { | |
5e7ed085 | 568 | Self::X86(X86InlineAsmRegClass::parse(name)?) |
fc512014 | 569 | } |
5e7ed085 FG |
570 | InlineAsmArch::Arm => Self::Arm(ArmInlineAsmRegClass::parse(name)?), |
571 | InlineAsmArch::AArch64 => Self::AArch64(AArch64InlineAsmRegClass::parse(name)?), | |
fc512014 | 572 | InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => { |
5e7ed085 | 573 | Self::RiscV(RiscVInlineAsmRegClass::parse(name)?) |
fc512014 | 574 | } |
5e7ed085 | 575 | InlineAsmArch::Nvptx64 => Self::Nvptx(NvptxInlineAsmRegClass::parse(name)?), |
17df50a5 | 576 | InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => { |
5e7ed085 | 577 | Self::PowerPC(PowerPCInlineAsmRegClass::parse(name)?) |
17df50a5 | 578 | } |
5e7ed085 | 579 | InlineAsmArch::Hexagon => Self::Hexagon(HexagonInlineAsmRegClass::parse(name)?), |
fc512014 | 580 | InlineAsmArch::Mips | InlineAsmArch::Mips64 => { |
5e7ed085 | 581 | Self::Mips(MipsInlineAsmRegClass::parse(name)?) |
fc512014 | 582 | } |
5e7ed085 FG |
583 | InlineAsmArch::S390x => Self::S390x(S390xInlineAsmRegClass::parse(name)?), |
584 | InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmRegClass::parse(name)?), | |
3c0e092e | 585 | InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => { |
5e7ed085 | 586 | Self::Wasm(WasmInlineAsmRegClass::parse(name)?) |
3c0e092e | 587 | } |
5e7ed085 FG |
588 | InlineAsmArch::Bpf => Self::Bpf(BpfInlineAsmRegClass::parse(name)?), |
589 | InlineAsmArch::Avr => Self::Avr(AvrInlineAsmRegClass::parse(name)?), | |
590 | InlineAsmArch::Msp430 => Self::Msp430(Msp430InlineAsmRegClass::parse(name)?), | |
f9f354fc XL |
591 | }) |
592 | } | |
593 | ||
594 | /// Returns the list of template modifiers that can be used with this | |
595 | /// register class. | |
596 | pub fn valid_modifiers(self, arch: InlineAsmArch) -> &'static [char] { | |
597 | match self { | |
598 | Self::X86(r) => r.valid_modifiers(arch), | |
599 | Self::Arm(r) => r.valid_modifiers(arch), | |
600 | Self::AArch64(r) => r.valid_modifiers(arch), | |
601 | Self::RiscV(r) => r.valid_modifiers(arch), | |
602 | Self::Nvptx(r) => r.valid_modifiers(arch), | |
17df50a5 | 603 | Self::PowerPC(r) => r.valid_modifiers(arch), |
f035d41b | 604 | Self::Hexagon(r) => r.valid_modifiers(arch), |
1b1a35ee | 605 | Self::Mips(r) => r.valid_modifiers(arch), |
94222f64 | 606 | Self::S390x(r) => r.valid_modifiers(arch), |
29967ef6 | 607 | Self::SpirV(r) => r.valid_modifiers(arch), |
fc512014 | 608 | Self::Wasm(r) => r.valid_modifiers(arch), |
17df50a5 | 609 | Self::Bpf(r) => r.valid_modifiers(arch), |
a2a8927a | 610 | Self::Avr(r) => r.valid_modifiers(arch), |
5099ac24 | 611 | Self::Msp430(r) => r.valid_modifiers(arch), |
6a06907d | 612 | Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), |
f9f354fc XL |
613 | } |
614 | } | |
136023e0 XL |
615 | |
616 | /// Returns whether registers in this class can only be used as clobbers | |
617 | /// and not as inputs/outputs. | |
618 | pub fn is_clobber_only(self, arch: InlineAsmArch) -> bool { | |
619 | self.supported_types(arch).is_empty() | |
620 | } | |
f9f354fc XL |
621 | } |
622 | ||
6a06907d XL |
623 | #[derive( |
624 | Copy, | |
625 | Clone, | |
626 | Encodable, | |
627 | Decodable, | |
628 | Debug, | |
629 | Eq, | |
630 | PartialEq, | |
631 | PartialOrd, | |
632 | Hash, | |
633 | HashStable_Generic | |
634 | )] | |
f9f354fc XL |
635 | pub enum InlineAsmRegOrRegClass { |
636 | Reg(InlineAsmReg), | |
637 | RegClass(InlineAsmRegClass), | |
638 | } | |
639 | ||
640 | impl InlineAsmRegOrRegClass { | |
641 | pub fn reg_class(self) -> InlineAsmRegClass { | |
642 | match self { | |
643 | Self::Reg(r) => r.reg_class(), | |
644 | Self::RegClass(r) => r, | |
645 | } | |
646 | } | |
647 | } | |
648 | ||
649 | impl fmt::Display for InlineAsmRegOrRegClass { | |
650 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
651 | match self { | |
652 | Self::Reg(r) => write!(f, "\"{}\"", r.name()), | |
fc512014 | 653 | Self::RegClass(r) => write!(f, "{}", r.name()), |
f9f354fc XL |
654 | } |
655 | } | |
656 | } | |
657 | ||
658 | /// Set of types which can be used with a particular register class. | |
659 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] | |
660 | pub enum InlineAsmType { | |
661 | I8, | |
662 | I16, | |
663 | I32, | |
664 | I64, | |
665 | I128, | |
666 | F32, | |
667 | F64, | |
668 | VecI8(u64), | |
669 | VecI16(u64), | |
670 | VecI32(u64), | |
671 | VecI64(u64), | |
672 | VecI128(u64), | |
673 | VecF32(u64), | |
674 | VecF64(u64), | |
675 | } | |
676 | ||
677 | impl InlineAsmType { | |
678 | pub fn is_integer(self) -> bool { | |
29967ef6 | 679 | matches!(self, Self::I8 | Self::I16 | Self::I32 | Self::I64 | Self::I128) |
f9f354fc XL |
680 | } |
681 | ||
682 | pub fn size(self) -> Size { | |
683 | Size::from_bytes(match self { | |
684 | Self::I8 => 1, | |
685 | Self::I16 => 2, | |
686 | Self::I32 => 4, | |
687 | Self::I64 => 8, | |
688 | Self::I128 => 16, | |
689 | Self::F32 => 4, | |
690 | Self::F64 => 8, | |
691 | Self::VecI8(n) => n * 1, | |
692 | Self::VecI16(n) => n * 2, | |
693 | Self::VecI32(n) => n * 4, | |
694 | Self::VecI64(n) => n * 8, | |
695 | Self::VecI128(n) => n * 16, | |
696 | Self::VecF32(n) => n * 4, | |
697 | Self::VecF64(n) => n * 8, | |
698 | }) | |
699 | } | |
700 | } | |
701 | ||
702 | impl fmt::Display for InlineAsmType { | |
703 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
704 | match *self { | |
705 | Self::I8 => f.write_str("i8"), | |
706 | Self::I16 => f.write_str("i16"), | |
707 | Self::I32 => f.write_str("i32"), | |
708 | Self::I64 => f.write_str("i64"), | |
709 | Self::I128 => f.write_str("i128"), | |
710 | Self::F32 => f.write_str("f32"), | |
711 | Self::F64 => f.write_str("f64"), | |
712 | Self::VecI8(n) => write!(f, "i8x{}", n), | |
713 | Self::VecI16(n) => write!(f, "i16x{}", n), | |
714 | Self::VecI32(n) => write!(f, "i32x{}", n), | |
715 | Self::VecI64(n) => write!(f, "i64x{}", n), | |
716 | Self::VecI128(n) => write!(f, "i128x{}", n), | |
717 | Self::VecF32(n) => write!(f, "f32x{}", n), | |
718 | Self::VecF64(n) => write!(f, "f64x{}", n), | |
719 | } | |
720 | } | |
721 | } | |
722 | ||
723 | /// Returns the full set of allocatable registers for a given architecture. | |
724 | /// | |
725 | /// The registers are structured as a map containing the set of allocatable | |
726 | /// registers in each register class. A particular register may be allocatable | |
727 | /// from multiple register classes, in which case it will appear multiple times | |
728 | /// in the map. | |
729 | // NOTE: This function isn't used at the moment, but is needed to support | |
730 | // falling back to an external assembler. | |
731 | pub fn allocatable_registers( | |
732 | arch: InlineAsmArch, | |
5e7ed085 | 733 | reloc_model: RelocModel, |
5099ac24 | 734 | target_features: &FxHashSet<Symbol>, |
f035d41b | 735 | target: &crate::spec::Target, |
f9f354fc XL |
736 | ) -> FxHashMap<InlineAsmRegClass, FxHashSet<InlineAsmReg>> { |
737 | match arch { | |
738 | InlineAsmArch::X86 | InlineAsmArch::X86_64 => { | |
739 | let mut map = x86::regclass_map(); | |
5e7ed085 | 740 | x86::fill_reg_map(arch, reloc_model, target_features, target, &mut map); |
f9f354fc XL |
741 | map |
742 | } | |
743 | InlineAsmArch::Arm => { | |
744 | let mut map = arm::regclass_map(); | |
5e7ed085 | 745 | arm::fill_reg_map(arch, reloc_model, target_features, target, &mut map); |
f9f354fc XL |
746 | map |
747 | } | |
748 | InlineAsmArch::AArch64 => { | |
749 | let mut map = aarch64::regclass_map(); | |
5e7ed085 | 750 | aarch64::fill_reg_map(arch, reloc_model, target_features, target, &mut map); |
f9f354fc XL |
751 | map |
752 | } | |
753 | InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => { | |
754 | let mut map = riscv::regclass_map(); | |
5e7ed085 | 755 | riscv::fill_reg_map(arch, reloc_model, target_features, target, &mut map); |
f9f354fc XL |
756 | map |
757 | } | |
758 | InlineAsmArch::Nvptx64 => { | |
759 | let mut map = nvptx::regclass_map(); | |
5e7ed085 | 760 | nvptx::fill_reg_map(arch, reloc_model, target_features, target, &mut map); |
f035d41b XL |
761 | map |
762 | } | |
17df50a5 XL |
763 | InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => { |
764 | let mut map = powerpc::regclass_map(); | |
5e7ed085 | 765 | powerpc::fill_reg_map(arch, reloc_model, target_features, target, &mut map); |
17df50a5 XL |
766 | map |
767 | } | |
f035d41b XL |
768 | InlineAsmArch::Hexagon => { |
769 | let mut map = hexagon::regclass_map(); | |
5e7ed085 | 770 | hexagon::fill_reg_map(arch, reloc_model, target_features, target, &mut map); |
f9f354fc XL |
771 | map |
772 | } | |
29967ef6 | 773 | InlineAsmArch::Mips | InlineAsmArch::Mips64 => { |
1b1a35ee | 774 | let mut map = mips::regclass_map(); |
5e7ed085 | 775 | mips::fill_reg_map(arch, reloc_model, target_features, target, &mut map); |
1b1a35ee XL |
776 | map |
777 | } | |
94222f64 XL |
778 | InlineAsmArch::S390x => { |
779 | let mut map = s390x::regclass_map(); | |
5e7ed085 | 780 | s390x::fill_reg_map(arch, reloc_model, target_features, target, &mut map); |
94222f64 XL |
781 | map |
782 | } | |
29967ef6 XL |
783 | InlineAsmArch::SpirV => { |
784 | let mut map = spirv::regclass_map(); | |
5e7ed085 | 785 | spirv::fill_reg_map(arch, reloc_model, target_features, target, &mut map); |
29967ef6 XL |
786 | map |
787 | } | |
3c0e092e | 788 | InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => { |
fc512014 | 789 | let mut map = wasm::regclass_map(); |
5e7ed085 | 790 | wasm::fill_reg_map(arch, reloc_model, target_features, target, &mut map); |
fc512014 XL |
791 | map |
792 | } | |
17df50a5 XL |
793 | InlineAsmArch::Bpf => { |
794 | let mut map = bpf::regclass_map(); | |
5e7ed085 | 795 | bpf::fill_reg_map(arch, reloc_model, target_features, target, &mut map); |
17df50a5 XL |
796 | map |
797 | } | |
a2a8927a XL |
798 | InlineAsmArch::Avr => { |
799 | let mut map = avr::regclass_map(); | |
5e7ed085 | 800 | avr::fill_reg_map(arch, reloc_model, target_features, target, &mut map); |
5099ac24 FG |
801 | map |
802 | } | |
803 | InlineAsmArch::Msp430 => { | |
804 | let mut map = msp430::regclass_map(); | |
5e7ed085 | 805 | msp430::fill_reg_map(arch, reloc_model, target_features, target, &mut map); |
a2a8927a XL |
806 | map |
807 | } | |
f9f354fc XL |
808 | } |
809 | } | |
94222f64 XL |
810 | |
811 | #[derive( | |
812 | Copy, | |
813 | Clone, | |
814 | Encodable, | |
815 | Decodable, | |
816 | Debug, | |
817 | Eq, | |
818 | PartialEq, | |
819 | PartialOrd, | |
820 | Hash, | |
821 | HashStable_Generic | |
822 | )] | |
823 | pub enum InlineAsmClobberAbi { | |
824 | X86, | |
825 | X86_64Win, | |
826 | X86_64SysV, | |
827 | Arm, | |
828 | AArch64, | |
a2a8927a | 829 | AArch64NoX18, |
94222f64 XL |
830 | RiscV, |
831 | } | |
832 | ||
833 | impl InlineAsmClobberAbi { | |
834 | /// Parses a clobber ABI for the given target, or returns a list of supported | |
835 | /// clobber ABIs for the target. | |
836 | pub fn parse( | |
837 | arch: InlineAsmArch, | |
838 | target: &Target, | |
839 | name: Symbol, | |
840 | ) -> Result<Self, &'static [&'static str]> { | |
a2a8927a | 841 | let name = name.as_str(); |
94222f64 XL |
842 | match arch { |
843 | InlineAsmArch::X86 => match name { | |
844 | "C" | "system" | "efiapi" | "cdecl" | "stdcall" | "fastcall" => { | |
845 | Ok(InlineAsmClobberAbi::X86) | |
846 | } | |
847 | _ => Err(&["C", "system", "efiapi", "cdecl", "stdcall", "fastcall"]), | |
848 | }, | |
849 | InlineAsmArch::X86_64 => match name { | |
850 | "C" | "system" if !target.is_like_windows => Ok(InlineAsmClobberAbi::X86_64SysV), | |
851 | "C" | "system" if target.is_like_windows => Ok(InlineAsmClobberAbi::X86_64Win), | |
852 | "win64" | "efiapi" => Ok(InlineAsmClobberAbi::X86_64Win), | |
853 | "sysv64" => Ok(InlineAsmClobberAbi::X86_64SysV), | |
854 | _ => Err(&["C", "system", "efiapi", "win64", "sysv64"]), | |
855 | }, | |
856 | InlineAsmArch::Arm => match name { | |
857 | "C" | "system" | "efiapi" | "aapcs" => Ok(InlineAsmClobberAbi::Arm), | |
858 | _ => Err(&["C", "system", "efiapi", "aapcs"]), | |
859 | }, | |
860 | InlineAsmArch::AArch64 => match name { | |
5e7ed085 FG |
861 | "C" | "system" | "efiapi" => Ok(if aarch64::target_reserves_x18(target) { |
862 | InlineAsmClobberAbi::AArch64NoX18 | |
863 | } else { | |
864 | InlineAsmClobberAbi::AArch64 | |
865 | }), | |
94222f64 XL |
866 | _ => Err(&["C", "system", "efiapi"]), |
867 | }, | |
868 | InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => match name { | |
869 | "C" | "system" | "efiapi" => Ok(InlineAsmClobberAbi::RiscV), | |
870 | _ => Err(&["C", "system", "efiapi"]), | |
871 | }, | |
872 | _ => Err(&[]), | |
873 | } | |
874 | } | |
875 | ||
876 | /// Returns the set of registers which are clobbered by this ABI. | |
877 | pub fn clobbered_regs(self) -> &'static [InlineAsmReg] { | |
878 | macro_rules! clobbered_regs { | |
879 | ($arch:ident $arch_reg:ident { | |
880 | $( | |
881 | $reg:ident, | |
882 | )* | |
883 | }) => { | |
884 | &[ | |
885 | $(InlineAsmReg::$arch($arch_reg::$reg),)* | |
886 | ] | |
887 | }; | |
888 | } | |
889 | match self { | |
890 | InlineAsmClobberAbi::X86 => clobbered_regs! { | |
891 | X86 X86InlineAsmReg { | |
892 | ax, cx, dx, | |
893 | ||
894 | xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, | |
895 | ||
04454e1e | 896 | k0, k1, k2, k3, k4, k5, k6, k7, |
94222f64 XL |
897 | |
898 | mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7, | |
899 | st0, st1, st2, st3, st4, st5, st6, st7, | |
900 | } | |
901 | }, | |
902 | InlineAsmClobberAbi::X86_64SysV => clobbered_regs! { | |
903 | X86 X86InlineAsmReg { | |
904 | ax, cx, dx, si, di, r8, r9, r10, r11, | |
905 | ||
906 | xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, | |
907 | xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, | |
908 | zmm16, zmm17, zmm18, zmm19, zmm20, zmm21, zmm22, zmm23, | |
909 | zmm24, zmm25, zmm26, zmm27, zmm28, zmm29, zmm30, zmm31, | |
910 | ||
04454e1e | 911 | k0, k1, k2, k3, k4, k5, k6, k7, |
94222f64 XL |
912 | |
913 | mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7, | |
914 | st0, st1, st2, st3, st4, st5, st6, st7, | |
923072b8 | 915 | tmm0, tmm1, tmm2, tmm3, tmm4, tmm5, tmm6, tmm7, |
94222f64 XL |
916 | } |
917 | }, | |
918 | InlineAsmClobberAbi::X86_64Win => clobbered_regs! { | |
919 | X86 X86InlineAsmReg { | |
920 | // rdi and rsi are callee-saved on windows | |
921 | ax, cx, dx, r8, r9, r10, r11, | |
922 | ||
923 | // xmm6-xmm15 are callee-saved on windows, but we need to | |
924 | // mark them as clobbered anyways because the upper portions | |
925 | // of ymm6-ymm15 are volatile. | |
926 | xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, | |
927 | xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15, | |
928 | zmm16, zmm17, zmm18, zmm19, zmm20, zmm21, zmm22, zmm23, | |
929 | zmm24, zmm25, zmm26, zmm27, zmm28, zmm29, zmm30, zmm31, | |
930 | ||
04454e1e | 931 | k0, k1, k2, k3, k4, k5, k6, k7, |
94222f64 XL |
932 | |
933 | mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7, | |
934 | st0, st1, st2, st3, st4, st5, st6, st7, | |
923072b8 | 935 | tmm0, tmm1, tmm2, tmm3, tmm4, tmm5, tmm6, tmm7, |
94222f64 XL |
936 | } |
937 | }, | |
938 | InlineAsmClobberAbi::AArch64 => clobbered_regs! { | |
939 | AArch64 AArch64InlineAsmReg { | |
940 | x0, x1, x2, x3, x4, x5, x6, x7, | |
941 | x8, x9, x10, x11, x12, x13, x14, x15, | |
a2a8927a XL |
942 | x16, x17, x18, x30, |
943 | ||
944 | // Technically the low 64 bits of v8-v15 are preserved, but | |
945 | // we have no way of expressing this using clobbers. | |
946 | v0, v1, v2, v3, v4, v5, v6, v7, | |
947 | v8, v9, v10, v11, v12, v13, v14, v15, | |
948 | v16, v17, v18, v19, v20, v21, v22, v23, | |
949 | v24, v25, v26, v27, v28, v29, v30, v31, | |
950 | ||
951 | p0, p1, p2, p3, p4, p5, p6, p7, | |
952 | p8, p9, p10, p11, p12, p13, p14, p15, | |
953 | ffr, | |
954 | ||
955 | } | |
956 | }, | |
957 | InlineAsmClobberAbi::AArch64NoX18 => clobbered_regs! { | |
958 | AArch64 AArch64InlineAsmReg { | |
959 | x0, x1, x2, x3, x4, x5, x6, x7, | |
960 | x8, x9, x10, x11, x12, x13, x14, x15, | |
94222f64 XL |
961 | x16, x17, x30, |
962 | ||
963 | // Technically the low 64 bits of v8-v15 are preserved, but | |
964 | // we have no way of expressing this using clobbers. | |
965 | v0, v1, v2, v3, v4, v5, v6, v7, | |
966 | v8, v9, v10, v11, v12, v13, v14, v15, | |
967 | v16, v17, v18, v19, v20, v21, v22, v23, | |
968 | v24, v25, v26, v27, v28, v29, v30, v31, | |
969 | ||
970 | p0, p1, p2, p3, p4, p5, p6, p7, | |
971 | p8, p9, p10, p11, p12, p13, p14, p15, | |
972 | ffr, | |
973 | ||
974 | } | |
975 | }, | |
976 | InlineAsmClobberAbi::Arm => clobbered_regs! { | |
977 | Arm ArmInlineAsmReg { | |
a2a8927a XL |
978 | // r9 is either platform-reserved or callee-saved. Either |
979 | // way we don't need to clobber it. | |
94222f64 XL |
980 | r0, r1, r2, r3, r12, r14, |
981 | ||
982 | // The finest-grained register variant is used here so that | |
983 | // partial uses of larger registers are properly handled. | |
984 | s0, s1, s2, s3, s4, s5, s6, s7, | |
985 | s8, s9, s10, s11, s12, s13, s14, s15, | |
986 | // s16-s31 are callee-saved | |
987 | d16, d17, d18, d19, d20, d21, d22, d23, | |
988 | d24, d25, d26, d27, d28, d29, d30, d31, | |
989 | } | |
990 | }, | |
991 | InlineAsmClobberAbi::RiscV => clobbered_regs! { | |
992 | RiscV RiscVInlineAsmReg { | |
993 | // ra | |
994 | x1, | |
995 | // t0-t2 | |
996 | x5, x6, x7, | |
997 | // a0-a7 | |
998 | x10, x11, x12, x13, x14, x15, x16, x17, | |
999 | // t3-t6 | |
1000 | x28, x29, x30, x31, | |
1001 | // ft0-ft7 | |
1002 | f0, f1, f2, f3, f4, f5, f6, f7, | |
1003 | // fa0-fa7 | |
1004 | f10, f11, f12, f13, f14, f15, f16, f17, | |
1005 | // ft8-ft11 | |
1006 | f28, f29, f30, f31, | |
1007 | ||
1008 | v0, v1, v2, v3, v4, v5, v6, v7, | |
1009 | v8, v9, v10, v11, v12, v13, v14, v15, | |
1010 | v16, v17, v18, v19, v20, v21, v22, v23, | |
1011 | v24, v25, v26, v27, v28, v29, v30, v31, | |
1012 | } | |
1013 | }, | |
1014 | } | |
1015 | } | |
1016 | } |