Skip to content

Commit 4eb8d93

Browse files
committed
Disallow z0-z15 in Arm64EC inline assembly
1 parent 45c2d1b commit 4eb8d93

File tree

6 files changed

+288
-109
lines changed

6 files changed

+288
-109
lines changed

compiler/rustc_codegen_llvm/src/asm.rs

+94-40
Original file line numberDiff line numberDiff line change
@@ -542,59 +542,107 @@ fn xmm_reg_index(reg: InlineAsmReg) -> Option<u32> {
542542

543543
/// If the register is an AArch64 integer register then return its index.
544544
fn a64_reg_index(reg: InlineAsmReg) -> Option<u32> {
545-
use AArch64InlineAsmReg::*;
546545
// Unlike `a64_vreg_index`, we can't subtract `x0` to get the u32 because
547546
// `x19` and `x29` are missing and the integer constants for the
548547
// `x0`..`x30` enum variants don't all match the register number. E.g. the
549548
// integer constant for `x18` is 18, but the constant for `x20` is 19.
550549
Some(match reg {
551-
InlineAsmReg::AArch64(r) => match r {
552-
x0 => 0,
553-
x1 => 1,
554-
x2 => 2,
555-
x3 => 3,
556-
x4 => 4,
557-
x5 => 5,
558-
x6 => 6,
559-
x7 => 7,
560-
x8 => 8,
561-
x9 => 9,
562-
x10 => 10,
563-
x11 => 11,
564-
x12 => 12,
565-
x13 => 13,
566-
x14 => 14,
567-
x15 => 15,
568-
x16 => 16,
569-
x17 => 17,
570-
x18 => 18,
571-
// x19 is reserved
572-
x20 => 20,
573-
x21 => 21,
574-
x22 => 22,
575-
x23 => 23,
576-
x24 => 24,
577-
x25 => 25,
578-
x26 => 26,
579-
x27 => 27,
580-
x28 => 28,
581-
// x29 is reserved
582-
x30 => 30,
583-
_ => return None,
584-
},
550+
InlineAsmReg::AArch64(r) => {
551+
use AArch64InlineAsmReg::*;
552+
match r {
553+
x0 => 0,
554+
x1 => 1,
555+
x2 => 2,
556+
x3 => 3,
557+
x4 => 4,
558+
x5 => 5,
559+
x6 => 6,
560+
x7 => 7,
561+
x8 => 8,
562+
x9 => 9,
563+
x10 => 10,
564+
x11 => 11,
565+
x12 => 12,
566+
x13 => 13,
567+
x14 => 14,
568+
x15 => 15,
569+
x16 => 16,
570+
x17 => 17,
571+
x18 => 18,
572+
// x19 is reserved
573+
x20 => 20,
574+
x21 => 21,
575+
x22 => 22,
576+
x23 => 23,
577+
x24 => 24,
578+
x25 => 25,
579+
x26 => 26,
580+
x27 => 27,
581+
x28 => 28,
582+
// x29 is reserved
583+
x30 => 30,
584+
_ => return None,
585+
}
586+
}
587+
InlineAsmReg::Arm64EC(r) => {
588+
use Arm64ECInlineAsmReg::*;
589+
match r {
590+
x0 => 0,
591+
x1 => 1,
592+
x2 => 2,
593+
x3 => 3,
594+
x4 => 4,
595+
x5 => 5,
596+
x6 => 6,
597+
x7 => 7,
598+
x8 => 8,
599+
x9 => 9,
600+
x10 => 10,
601+
x11 => 11,
602+
x12 => 12,
603+
// x13 is reserved
604+
// x14 is reserved
605+
x15 => 15,
606+
x16 => 16,
607+
x17 => 17,
608+
// x18 is reserved
609+
// x19 is reserved
610+
x20 => 20,
611+
x21 => 21,
612+
x22 => 22,
613+
// x23 is reserved
614+
// x24 is reserved
615+
x25 => 25,
616+
x26 => 26,
617+
x27 => 27,
618+
// x28 is reserved
619+
// x29 is reserved
620+
x30 => 30,
621+
_ => return None,
622+
}
623+
}
585624
_ => return None,
586625
})
587626
}
588627

589628
/// If the register is an AArch64 vector register then return its index.
590629
fn a64_vreg_index(reg: InlineAsmReg) -> Option<u32> {
591-
use AArch64InlineAsmReg::*;
592630
match reg {
593-
InlineAsmReg::AArch64(reg) if reg as u32 >= v0 as u32 && reg as u32 <= v31 as u32 => {
594-
Some(reg as u32 - v0 as u32)
631+
InlineAsmReg::AArch64(reg) => {
632+
use AArch64InlineAsmReg::*;
633+
if reg as u32 >= v0 as u32 && reg as u32 <= v31 as u32 {
634+
return Some(reg as u32 - v0 as u32);
635+
}
595636
}
596-
_ => None,
637+
InlineAsmReg::Arm64EC(reg) => {
638+
use Arm64ECInlineAsmReg::*;
639+
if reg as u32 >= v0 as u32 && reg as u32 <= v15 as u32 {
640+
return Some(reg as u32 - v0 as u32);
641+
}
642+
}
643+
_ => {}
597644
}
645+
None
598646
}
599647

600648
/// Converts a register class to an LLVM constraint code.
@@ -625,7 +673,13 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) ->
625673
// We use i32 as the type for discarded outputs
626674
'w'
627675
};
628-
if class == 'x' && reg == InlineAsmReg::AArch64(AArch64InlineAsmReg::x30) {
676+
if class == 'x'
677+
&& matches!(
678+
reg,
679+
InlineAsmReg::AArch64(AArch64InlineAsmReg::x30)
680+
| InlineAsmReg::Arm64EC(Arm64ECInlineAsmReg::x30)
681+
)
682+
{
629683
// LLVM doesn't recognize x30. use lr instead.
630684
"{lr}".to_string()
631685
} else {

compiler/rustc_target/src/asm/aarch64.rs

+38-53
Original file line numberDiff line numberDiff line change
@@ -88,20 +88,6 @@ fn reserved_x18(
8888
}
8989
}
9090

91-
fn restricted_for_arm64ec(
92-
arch: InlineAsmArch,
93-
_reloc_model: RelocModel,
94-
_target_features: &FxIndexSet<Symbol>,
95-
_target: &Target,
96-
_is_clobber: bool,
97-
) -> Result<(), &'static str> {
98-
if arch == InlineAsmArch::Arm64EC {
99-
Err("x13, x14, x23, x24, x28, v16-v31, z*, p*, ffr cannot be used for Arm64EC")
100-
} else {
101-
Ok(())
102-
}
103-
}
104-
10591
def_regs! {
10692
AArch64 AArch64InlineAsmReg AArch64InlineAsmRegClass {
10793
x0: reg = ["x0", "w0"],
@@ -117,23 +103,22 @@ def_regs! {
117103
x10: reg = ["x10", "w10"],
118104
x11: reg = ["x11", "w11"],
119105
x12: reg = ["x12", "w12"],
120-
x13: reg = ["x13", "w13"] % restricted_for_arm64ec,
121-
x14: reg = ["x14", "w14"] % restricted_for_arm64ec,
106+
x13: reg = ["x13", "w13"],
107+
x14: reg = ["x14", "w14"],
122108
x15: reg = ["x15", "w15"],
123109
x16: reg = ["x16", "w16"],
124110
x17: reg = ["x17", "w17"],
125111
x18: reg = ["x18", "w18"] % reserved_x18,
126112
x20: reg = ["x20", "w20"],
127113
x21: reg = ["x21", "w21"],
128114
x22: reg = ["x22", "w22"],
129-
x23: reg = ["x23", "w23"] % restricted_for_arm64ec,
130-
x24: reg = ["x24", "w24"] % restricted_for_arm64ec,
115+
x23: reg = ["x23", "w23"],
116+
x24: reg = ["x24", "w24"],
131117
x25: reg = ["x25", "w25"],
132118
x26: reg = ["x26", "w26"],
133119
x27: reg = ["x27", "w27"],
134-
x28: reg = ["x28", "w28"] % restricted_for_arm64ec,
120+
x28: reg = ["x28", "w28"],
135121
x30: reg = ["x30", "w30", "lr", "wlr"],
136-
// FIXME: z* cannot be used for Arm64EC
137122
v0: vreg, vreg_low16 = ["v0", "b0", "h0", "s0", "d0", "q0", "z0"],
138123
v1: vreg, vreg_low16 = ["v1", "b1", "h1", "s1", "d1", "q1", "z1"],
139124
v2: vreg, vreg_low16 = ["v2", "b2", "h2", "s2", "d2", "q2", "z2"],
@@ -150,39 +135,39 @@ def_regs! {
150135
v13: vreg, vreg_low16 = ["v13", "b13", "h13", "s13", "d13", "q13", "z13"],
151136
v14: vreg, vreg_low16 = ["v14", "b14", "h14", "s14", "d14", "q14", "z14"],
152137
v15: vreg, vreg_low16 = ["v15", "b15", "h15", "s15", "d15", "q15", "z15"],
153-
v16: vreg = ["v16", "b16", "h16", "s16", "d16", "q16", "z16"] % restricted_for_arm64ec,
154-
v17: vreg = ["v17", "b17", "h17", "s17", "d17", "q17", "z17"] % restricted_for_arm64ec,
155-
v18: vreg = ["v18", "b18", "h18", "s18", "d18", "q18", "z18"] % restricted_for_arm64ec,
156-
v19: vreg = ["v19", "b19", "h19", "s19", "d19", "q19", "z19"] % restricted_for_arm64ec,
157-
v20: vreg = ["v20", "b20", "h20", "s20", "d20", "q20", "z20"] % restricted_for_arm64ec,
158-
v21: vreg = ["v21", "b21", "h21", "s21", "d21", "q21", "z21"] % restricted_for_arm64ec,
159-
v22: vreg = ["v22", "b22", "h22", "s22", "d22", "q22", "z22"] % restricted_for_arm64ec,
160-
v23: vreg = ["v23", "b23", "h23", "s23", "d23", "q23", "z23"] % restricted_for_arm64ec,
161-
v24: vreg = ["v24", "b24", "h24", "s24", "d24", "q24", "z24"] % restricted_for_arm64ec,
162-
v25: vreg = ["v25", "b25", "h25", "s25", "d25", "q25", "z25"] % restricted_for_arm64ec,
163-
v26: vreg = ["v26", "b26", "h26", "s26", "d26", "q26", "z26"] % restricted_for_arm64ec,
164-
v27: vreg = ["v27", "b27", "h27", "s27", "d27", "q27", "z27"] % restricted_for_arm64ec,
165-
v28: vreg = ["v28", "b28", "h28", "s28", "d28", "q28", "z28"] % restricted_for_arm64ec,
166-
v29: vreg = ["v29", "b29", "h29", "s29", "d29", "q29", "z29"] % restricted_for_arm64ec,
167-
v30: vreg = ["v30", "b30", "h30", "s30", "d30", "q30", "z30"] % restricted_for_arm64ec,
168-
v31: vreg = ["v31", "b31", "h31", "s31", "d31", "q31", "z31"] % restricted_for_arm64ec,
169-
p0: preg = ["p0"] % restricted_for_arm64ec,
170-
p1: preg = ["p1"] % restricted_for_arm64ec,
171-
p2: preg = ["p2"] % restricted_for_arm64ec,
172-
p3: preg = ["p3"] % restricted_for_arm64ec,
173-
p4: preg = ["p4"] % restricted_for_arm64ec,
174-
p5: preg = ["p5"] % restricted_for_arm64ec,
175-
p6: preg = ["p6"] % restricted_for_arm64ec,
176-
p7: preg = ["p7"] % restricted_for_arm64ec,
177-
p8: preg = ["p8"] % restricted_for_arm64ec,
178-
p9: preg = ["p9"] % restricted_for_arm64ec,
179-
p10: preg = ["p10"] % restricted_for_arm64ec,
180-
p11: preg = ["p11"] % restricted_for_arm64ec,
181-
p12: preg = ["p12"] % restricted_for_arm64ec,
182-
p13: preg = ["p13"] % restricted_for_arm64ec,
183-
p14: preg = ["p14"] % restricted_for_arm64ec,
184-
p15: preg = ["p15"] % restricted_for_arm64ec,
185-
ffr: preg = ["ffr"] % restricted_for_arm64ec,
138+
v16: vreg = ["v16", "b16", "h16", "s16", "d16", "q16", "z16"],
139+
v17: vreg = ["v17", "b17", "h17", "s17", "d17", "q17", "z17"],
140+
v18: vreg = ["v18", "b18", "h18", "s18", "d18", "q18", "z18"],
141+
v19: vreg = ["v19", "b19", "h19", "s19", "d19", "q19", "z19"],
142+
v20: vreg = ["v20", "b20", "h20", "s20", "d20", "q20", "z20"],
143+
v21: vreg = ["v21", "b21", "h21", "s21", "d21", "q21", "z21"],
144+
v22: vreg = ["v22", "b22", "h22", "s22", "d22", "q22", "z22"],
145+
v23: vreg = ["v23", "b23", "h23", "s23", "d23", "q23", "z23"],
146+
v24: vreg = ["v24", "b24", "h24", "s24", "d24", "q24", "z24"],
147+
v25: vreg = ["v25", "b25", "h25", "s25", "d25", "q25", "z25"],
148+
v26: vreg = ["v26", "b26", "h26", "s26", "d26", "q26", "z26"],
149+
v27: vreg = ["v27", "b27", "h27", "s27", "d27", "q27", "z27"],
150+
v28: vreg = ["v28", "b28", "h28", "s28", "d28", "q28", "z28"],
151+
v29: vreg = ["v29", "b29", "h29", "s29", "d29", "q29", "z29"],
152+
v30: vreg = ["v30", "b30", "h30", "s30", "d30", "q30", "z30"],
153+
v31: vreg = ["v31", "b31", "h31", "s31", "d31", "q31", "z31"],
154+
p0: preg = ["p0"],
155+
p1: preg = ["p1"],
156+
p2: preg = ["p2"],
157+
p3: preg = ["p3"],
158+
p4: preg = ["p4"],
159+
p5: preg = ["p5"],
160+
p6: preg = ["p6"],
161+
p7: preg = ["p7"],
162+
p8: preg = ["p8"],
163+
p9: preg = ["p9"],
164+
p10: preg = ["p10"],
165+
p11: preg = ["p11"],
166+
p12: preg = ["p12"],
167+
p13: preg = ["p13"],
168+
p14: preg = ["p14"],
169+
p15: preg = ["p15"],
170+
ffr: preg = ["ffr"],
186171
#error = ["x19", "w19"] =>
187172
"x19 is used internally by LLVM and cannot be used as an operand for inline asm",
188173
#error = ["x29", "w29", "fp", "wfp"] =>
+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
use std::fmt;
2+
3+
use rustc_span::Symbol;
4+
5+
use super::{AArch64InlineAsmRegClass, InlineAsmArch};
6+
7+
def_regs! {
8+
Arm64EC Arm64ECInlineAsmReg AArch64 AArch64InlineAsmRegClass {
9+
x0: reg = ["x0", "w0"],
10+
x1: reg = ["x1", "w1"],
11+
x2: reg = ["x2", "w2"],
12+
x3: reg = ["x3", "w3"],
13+
x4: reg = ["x4", "w4"],
14+
x5: reg = ["x5", "w5"],
15+
x6: reg = ["x6", "w6"],
16+
x7: reg = ["x7", "w7"],
17+
x8: reg = ["x8", "w8"],
18+
x9: reg = ["x9", "w9"],
19+
x10: reg = ["x10", "w10"],
20+
x11: reg = ["x11", "w11"],
21+
x12: reg = ["x12", "w12"],
22+
x15: reg = ["x15", "w15"],
23+
x16: reg = ["x16", "w16"],
24+
x17: reg = ["x17", "w17"],
25+
x20: reg = ["x20", "w20"],
26+
x21: reg = ["x21", "w21"],
27+
x22: reg = ["x22", "w22"],
28+
x25: reg = ["x25", "w25"],
29+
x26: reg = ["x26", "w26"],
30+
x27: reg = ["x27", "w27"],
31+
x30: reg = ["x30", "w30", "lr", "wlr"],
32+
v0: vreg, vreg_low16 = ["v0", "b0", "h0", "s0", "d0", "q0"],
33+
v1: vreg, vreg_low16 = ["v1", "b1", "h1", "s1", "d1", "q1"],
34+
v2: vreg, vreg_low16 = ["v2", "b2", "h2", "s2", "d2", "q2"],
35+
v3: vreg, vreg_low16 = ["v3", "b3", "h3", "s3", "d3", "q3"],
36+
v4: vreg, vreg_low16 = ["v4", "b4", "h4", "s4", "d4", "q4"],
37+
v5: vreg, vreg_low16 = ["v5", "b5", "h5", "s5", "d5", "q5"],
38+
v6: vreg, vreg_low16 = ["v6", "b6", "h6", "s6", "d6", "q6"],
39+
v7: vreg, vreg_low16 = ["v7", "b7", "h7", "s7", "d7", "q7"],
40+
v8: vreg, vreg_low16 = ["v8", "b8", "h8", "s8", "d8", "q8"],
41+
v9: vreg, vreg_low16 = ["v9", "b9", "h9", "s9", "d9", "q9"],
42+
v10: vreg, vreg_low16 = ["v10", "b10", "h10", "s10", "d10", "q10"],
43+
v11: vreg, vreg_low16 = ["v11", "b11", "h11", "s11", "d11", "q11"],
44+
v12: vreg, vreg_low16 = ["v12", "b12", "h12", "s12", "d12", "q12"],
45+
v13: vreg, vreg_low16 = ["v13", "b13", "h13", "s13", "d13", "q13"],
46+
v14: vreg, vreg_low16 = ["v14", "b14", "h14", "s14", "d14", "q14"],
47+
v15: vreg, vreg_low16 = ["v15", "b15", "h15", "s15", "d15", "q15"],
48+
#error = ["x18", "w18"] =>
49+
"x18 is a reserved register on this target",
50+
#error = ["x19", "w19"] =>
51+
"x19 is used internally by LLVM and cannot be used as an operand for inline asm",
52+
#error = ["x29", "w29", "fp", "wfp"] =>
53+
"the frame pointer cannot be used as an operand for inline asm",
54+
#error = ["sp", "wsp"] =>
55+
"the stack pointer cannot be used as an operand for inline asm",
56+
#error = ["xzr", "wzr"] =>
57+
"the zero register cannot be used as an operand for inline asm",
58+
#error = [
59+
"x13", "w13",
60+
"x14", "w14",
61+
"x23", "w23",
62+
"x24", "w24",
63+
"x28", "w28",
64+
"v16", "b16", "h16", "s16", "d16", "q16",
65+
"v17", "b17", "h17", "s17", "d17", "q17",
66+
"v18", "b18", "h18", "s18", "d18", "q18",
67+
"v19", "b19", "h19", "s19", "d19", "q19",
68+
"v20", "b20", "h20", "s20", "d20", "q20",
69+
"v21", "b21", "h21", "s21", "d21", "q21",
70+
"v22", "b22", "h22", "s22", "d22", "q22",
71+
"v23", "b23", "h23", "s23", "d23", "q23",
72+
"v24", "b24", "h24", "s24", "d24", "q24",
73+
"v25", "b25", "h25", "s25", "d25", "q25",
74+
"v26", "b26", "h26", "s26", "d26", "q26",
75+
"v27", "b27", "h27", "s27", "d27", "q27",
76+
"v28", "b28", "h28", "s28", "d28", "q28",
77+
"v29", "b29", "h29", "s29", "d29", "q29",
78+
"v30", "b30", "h30", "s30", "d30", "q30",
79+
"v31", "b31", "h31", "s31", "d31", "q31"
80+
] =>
81+
"x13, x14, x23, x24, x28, v16-v31 cannot be used for Arm64EC",
82+
#error = [
83+
"z0", "z1", "z2", "z3", "z4", "z5", "z6", "z7", "z8", "z9",
84+
"z10", "z11", "z12", "z13", "z14", "z15", "z16", "z17", "z18", "z19",
85+
"z20", "z21", "z22", "z23", "z24", "z25", "z26", "z27", "z28", "z29",
86+
"z30", "z31",
87+
"p0", "p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8", "p9",
88+
"p10", "p11", "p12", "p13", "p14", "p15",
89+
"ffr"
90+
] =>
91+
"SVE cannot be used for Arm64EC",
92+
}
93+
}
94+
95+
impl Arm64ECInlineAsmReg {
96+
pub fn emit(
97+
self,
98+
out: &mut dyn fmt::Write,
99+
_arch: InlineAsmArch,
100+
modifier: Option<char>,
101+
) -> fmt::Result {
102+
let (prefix, index) = if (self as u32) < Self::v0 as u32 {
103+
(modifier.unwrap_or('x'), self as u32 - Self::x0 as u32)
104+
} else {
105+
(modifier.unwrap_or('v'), self as u32 - Self::v0 as u32)
106+
};
107+
assert!(index < 32);
108+
write!(out, "{prefix}{index}")
109+
}
110+
}

0 commit comments

Comments
 (0)