Skip to content

Commit 0b6f079

Browse files
committed
Auto merge of rust-lang#91224 - couchand:2021-11/avr-asm, r=Amanieu
Support AVR for inline asm! A first pass at support for the AVR platform in inline `asm!`. Passes the initial compiler tests, have not yet done more complete verification. In particular, the register classes could use a lot more fleshing out, this draft PR so far only includes the most basic. cc `@Amanieu` `@dylanmckay`
2 parents c5c9494 + c6e8ae1 commit 0b6f079

File tree

8 files changed

+549
-1
lines changed

8 files changed

+549
-1
lines changed

compiler/rustc_codegen_gcc/src/asm.rs

+3
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,7 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
577577
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4) => unimplemented!(),
578578
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg)
579579
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg) => unimplemented!(),
580+
InlineAsmRegClass::Avr(_) => unimplemented!(),
580581
InlineAsmRegClass::Bpf(_) => unimplemented!(),
581582
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => unimplemented!(),
582583
InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => unimplemented!(),
@@ -639,6 +640,7 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl
639640
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4) => {
640641
unimplemented!()
641642
}
643+
InlineAsmRegClass::Avr(_) => unimplemented!(),
642644
InlineAsmRegClass::Bpf(_) => unimplemented!(),
643645
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => cx.type_i32(),
644646
InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(),
@@ -747,6 +749,7 @@ fn modifier_to_gcc(arch: InlineAsmArch, reg: InlineAsmRegClass, modifier: Option
747749
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4) => {
748750
unimplemented!()
749751
}
752+
InlineAsmRegClass::Avr(_) => unimplemented!(),
750753
InlineAsmRegClass::Bpf(_) => unimplemented!(),
751754
InlineAsmRegClass::Hexagon(_) => unimplemented!(),
752755
InlineAsmRegClass::Mips(_) => unimplemented!(),

compiler/rustc_codegen_llvm/src/asm.rs

+21
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,9 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
319319
"~{vxrm}".to_string(),
320320
]);
321321
}
322+
InlineAsmArch::Avr => {
323+
constraints.push("~{sreg}".to_string());
324+
}
322325
InlineAsmArch::Nvptx64 => {}
323326
InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {}
324327
InlineAsmArch::Hexagon => {}
@@ -669,6 +672,11 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>)
669672
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r",
670673
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r",
671674
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w",
675+
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg) => "r",
676+
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_upper) => "d",
677+
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_pair) => "r",
678+
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_iw) => "w",
679+
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_ptr) => "e",
672680
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => "r",
673681
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => "f",
674682
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
@@ -749,6 +757,14 @@ fn modifier_to_llvm(
749757
}
750758
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => None,
751759
InlineAsmRegClass::Bpf(_) => None,
760+
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_pair)
761+
| InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_iw)
762+
| InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_ptr) => match modifier {
763+
Some('h') => Some('B'),
764+
Some('l') => Some('A'),
765+
_ => None,
766+
},
767+
InlineAsmRegClass::Avr(_) => None,
752768
InlineAsmRegClass::S390x(_) => None,
753769
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
754770
bug!("LLVM backend does not support SPIR-V")
@@ -812,6 +828,11 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll
812828
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(),
813829
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => cx.type_i64(),
814830
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => cx.type_i32(),
831+
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg) => cx.type_i8(),
832+
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_upper) => cx.type_i8(),
833+
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_pair) => cx.type_i16(),
834+
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_iw) => cx.type_i16(),
835+
InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_ptr) => cx.type_i16(),
815836
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => cx.type_i32(),
816837
InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => cx.type_f64(),
817838
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {

compiler/rustc_span/src/symbol.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1053,8 +1053,12 @@ symbols! {
10531053
reg64,
10541054
reg_abcd,
10551055
reg_byte,
1056+
reg_iw,
10561057
reg_nonzero,
1058+
reg_pair,
1059+
reg_ptr,
10571060
reg_thumb,
1061+
reg_upper,
10581062
register_attr,
10591063
register_tool,
10601064
relaxed_adts,

compiler/rustc_target/src/asm/avr.rs

+196
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
use super::{InlineAsmArch, InlineAsmType};
2+
use rustc_macros::HashStable_Generic;
3+
use std::fmt;
4+
5+
def_reg_class! {
6+
Avr AvrInlineAsmRegClass {
7+
reg,
8+
reg_upper,
9+
reg_pair,
10+
reg_iw,
11+
reg_ptr,
12+
}
13+
}
14+
15+
impl AvrInlineAsmRegClass {
16+
pub fn valid_modifiers(self, _arch: InlineAsmArch) -> &'static [char] {
17+
match self {
18+
Self::reg_pair | Self::reg_iw | Self::reg_ptr => &['h', 'l'],
19+
_ => &[],
20+
}
21+
}
22+
23+
pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option<Self> {
24+
None
25+
}
26+
27+
pub fn suggest_modifier(
28+
self,
29+
_arch: InlineAsmArch,
30+
_ty: InlineAsmType,
31+
) -> Option<(char, &'static str)> {
32+
None
33+
}
34+
35+
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> {
36+
None
37+
}
38+
39+
pub fn supported_types(
40+
self,
41+
_arch: InlineAsmArch,
42+
) -> &'static [(InlineAsmType, Option<&'static str>)] {
43+
match self {
44+
Self::reg => types! { _: I8; },
45+
Self::reg_upper => types! { _: I8; },
46+
Self::reg_pair => types! { _: I16; },
47+
Self::reg_iw => types! { _: I16; },
48+
Self::reg_ptr => types! { _: I16; },
49+
}
50+
}
51+
}
52+
53+
def_regs! {
54+
Avr AvrInlineAsmReg AvrInlineAsmRegClass {
55+
r2: reg = ["r2"],
56+
r3: reg = ["r3"],
57+
r4: reg = ["r4"],
58+
r5: reg = ["r5"],
59+
r6: reg = ["r6"],
60+
r7: reg = ["r7"],
61+
r8: reg = ["r8"],
62+
r9: reg = ["r9"],
63+
r10: reg = ["r10"],
64+
r11: reg = ["r11"],
65+
r12: reg = ["r12"],
66+
r13: reg = ["r13"],
67+
r14: reg = ["r14"],
68+
r15: reg = ["r15"],
69+
r16: reg, reg_upper = ["r16"],
70+
r17: reg, reg_upper = ["r17"],
71+
r18: reg, reg_upper = ["r18"],
72+
r19: reg, reg_upper = ["r19"],
73+
r20: reg, reg_upper = ["r20"],
74+
r21: reg, reg_upper = ["r21"],
75+
r22: reg, reg_upper = ["r22"],
76+
r23: reg, reg_upper = ["r23"],
77+
r24: reg, reg_upper = ["r24"],
78+
r25: reg, reg_upper = ["r25"],
79+
r26: reg, reg_upper = ["r26", "XL"],
80+
r27: reg, reg_upper = ["r27", "XH"],
81+
r30: reg, reg_upper = ["r30", "ZL"],
82+
r31: reg, reg_upper = ["r31", "ZH"],
83+
84+
r3r2: reg_pair = ["r3r2"],
85+
r5r4: reg_pair = ["r5r4"],
86+
r7r6: reg_pair = ["r7r6"],
87+
r9r8: reg_pair = ["r9r8"],
88+
r11r10: reg_pair = ["r11r10"],
89+
r13r12: reg_pair = ["r13r12"],
90+
r15r14: reg_pair = ["r15r14"],
91+
r17r16: reg_pair = ["r17r16"],
92+
r19r18: reg_pair = ["r19r18"],
93+
r21r20: reg_pair = ["r21r20"],
94+
r23r22: reg_pair = ["r23r22"],
95+
96+
r25r24: reg_iw, reg_pair = ["r25r24"],
97+
98+
X: reg_ptr, reg_iw, reg_pair = ["r27r26", "X"],
99+
Z: reg_ptr, reg_iw, reg_pair = ["r31r30", "Z"],
100+
101+
#error = ["Y", "YL", "YH"] =>
102+
"the frame pointer cannot be used as an operand for inline asm",
103+
#error = ["SP", "SPL", "SPH"] =>
104+
"the stack pointer cannot be used as an operand for inline asm",
105+
#error = ["r0", "r1", "r1r0"] =>
106+
"r0 and r1 are not available due to an issue in LLVM",
107+
}
108+
}
109+
110+
macro_rules! emit_pairs {
111+
(
112+
$self:ident $modifier:ident,
113+
$($pair:ident $name:literal $hi:literal $lo:literal,)*
114+
) => {
115+
match ($self, $modifier) {
116+
$(
117+
(AvrInlineAsmReg::$pair, Some('h')) => $hi,
118+
(AvrInlineAsmReg::$pair, Some('l')) => $lo,
119+
(AvrInlineAsmReg::$pair, _) => $name,
120+
)*
121+
_ => $self.name(),
122+
}
123+
};
124+
}
125+
126+
impl AvrInlineAsmReg {
127+
pub fn emit(
128+
self,
129+
out: &mut dyn fmt::Write,
130+
_arch: InlineAsmArch,
131+
modifier: Option<char>,
132+
) -> fmt::Result {
133+
let name = emit_pairs! {
134+
self modifier,
135+
Z "Z" "ZH" "ZL",
136+
X "X" "XH" "XL",
137+
r25r24 "r25:r24" "r25" "r24",
138+
r23r22 "r23:r22" "r23" "r22",
139+
r21r20 "r21:r20" "r21" "r20",
140+
r19r18 "r19:r18" "r19" "r18",
141+
r17r16 "r17:r16" "r17" "r16",
142+
r15r14 "r15:r14" "r15" "r14",
143+
r13r12 "r13:r12" "r13" "r12",
144+
r11r10 "r11:r10" "r11" "r10",
145+
r9r8 "r9:r8" "r9" "r8",
146+
r7r6 "r7:r6" "r7" "r6",
147+
r5r4 "r5:r4" "r5" "r4",
148+
r3r2 "r3:r2" "r3" "r2",
149+
};
150+
out.write_str(name)
151+
}
152+
153+
pub fn overlapping_regs(self, mut cb: impl FnMut(AvrInlineAsmReg)) {
154+
cb(self);
155+
156+
macro_rules! reg_conflicts {
157+
(
158+
$(
159+
$pair:ident : $hi:ident $lo:ident,
160+
)*
161+
) => {
162+
match self {
163+
$(
164+
Self::$pair => {
165+
cb(Self::$hi);
166+
cb(Self::$lo);
167+
}
168+
Self::$hi => {
169+
cb(Self::$pair);
170+
}
171+
Self::$lo => {
172+
cb(Self::$pair);
173+
}
174+
)*
175+
}
176+
};
177+
}
178+
179+
reg_conflicts! {
180+
Z : r31 r30,
181+
X : r27 r26,
182+
r25r24 : r25 r24,
183+
r23r22 : r23 r22,
184+
r21r20 : r21 r20,
185+
r19r18 : r19 r18,
186+
r17r16 : r17 r16,
187+
r15r14 : r15 r14,
188+
r13r12 : r13 r12,
189+
r11r10 : r11 r10,
190+
r9r8 : r9 r8,
191+
r7r6 : r7 r6,
192+
r5r4 : r5 r4,
193+
r3r2 : r3 r2,
194+
}
195+
}
196+
}

0 commit comments

Comments
 (0)