Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions compiler/rustc_codegen_gcc/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -687,9 +687,15 @@ fn reg_class_to_gcc(reg_class: InlineAsmRegClass) -> &'static str {
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w",
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg_pair) => "r",
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::preg) => {
unreachable!("clobber-only")
}
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::vreg) => "v",
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::vreg_pair) => "v",
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::qreg) => {
unreachable!("clobber-only")
}
InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => "f",
InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => "r",
Expand Down Expand Up @@ -779,9 +785,19 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl
cx.type_vector(cx.type_i64(), 2)
}
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => cx.type_i32(),
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg_pair) => cx.type_i64(),
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::preg) => {
unreachable!("clobber-only")
}
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::vreg) => {
cx.type_vector(cx.type_i32(), 16)
}
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::vreg_pair) => {
cx.type_vector(cx.type_i32(), 32)
}
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::qreg) => {
unreachable!("clobber-only")
}
InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => cx.type_i32(),
InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => cx.type_f32(),
InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(),
Expand Down
74 changes: 74 additions & 0 deletions compiler/rustc_codegen_llvm/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,52 @@ fn a64_vreg_index(reg: InlineAsmReg) -> Option<u32> {
}
}

/// If the register is a Hexagon register pair then return its LLVM double register index.
/// LLVM uses `d0`, `d1`, ... for Hexagon double registers in inline asm constraints,
/// not the assembly-printed `r1:0`, `r3:2`, ... format.
fn hexagon_reg_pair_index(reg: InlineAsmReg) -> Option<u32> {
match reg {
InlineAsmReg::Hexagon(HexagonInlineAsmReg::r1_0) => Some(0),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::r3_2) => Some(1),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::r5_4) => Some(2),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::r7_6) => Some(3),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::r9_8) => Some(4),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::r11_10) => Some(5),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::r13_12) => Some(6),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::r15_14) => Some(7),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::r17_16) => Some(8),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::r21_20) => Some(10),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::r23_22) => Some(11),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::r25_24) => Some(12),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::r27_26) => Some(13),
_ => None,
}
}

/// If the register is a Hexagon HVX vector pair then return its LLVM W-register index.
/// LLVM uses `w0`, `w1`, ... for Hexagon vector pair registers in inline asm constraints.
fn hexagon_vreg_pair_index(reg: InlineAsmReg) -> Option<u32> {
match reg {
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v1_0) => Some(0),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v3_2) => Some(1),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v5_4) => Some(2),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v7_6) => Some(3),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v9_8) => Some(4),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v11_10) => Some(5),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v13_12) => Some(6),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v15_14) => Some(7),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v17_16) => Some(8),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v19_18) => Some(9),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v21_20) => Some(10),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v23_22) => Some(11),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v25_24) => Some(12),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v27_26) => Some(13),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v29_28) => Some(14),
InlineAsmReg::Hexagon(HexagonInlineAsmReg::v31_30) => Some(15),
_ => None,
}
}

/// Converts a register class to an LLVM constraint code.
fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> String {
use InlineAsmRegClass::*;
Expand Down Expand Up @@ -624,6 +670,12 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) ->
'q'
};
format!("{{{}{}}}", class, idx)
} else if let Some(idx) = hexagon_reg_pair_index(reg) {
// LLVM uses `dN` for Hexagon double registers, not the `rN+1:N` asm syntax.
format!("{{d{}}}", idx)
} else if let Some(idx) = hexagon_vreg_pair_index(reg) {
// LLVM uses `wN` for Hexagon HVX vector pair registers.
format!("{{w{}}}", idx)
} else if reg == InlineAsmReg::Arm(ArmInlineAsmReg::r14) {
// LLVM doesn't recognize r14
"{lr}".to_string()
Expand All @@ -647,7 +699,11 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) ->
| Arm(ArmInlineAsmRegClass::qreg_low4) => "x",
Arm(ArmInlineAsmRegClass::dreg) | Arm(ArmInlineAsmRegClass::qreg) => "w",
Hexagon(HexagonInlineAsmRegClass::reg) => "r",
Hexagon(HexagonInlineAsmRegClass::reg_pair) => "r",
Hexagon(HexagonInlineAsmRegClass::preg) => unreachable!("clobber-only"),
Hexagon(HexagonInlineAsmRegClass::vreg) => "v",
Hexagon(HexagonInlineAsmRegClass::vreg_pair) => "v",
Hexagon(HexagonInlineAsmRegClass::qreg) => unreachable!("clobber-only"),
LoongArch(LoongArchInlineAsmRegClass::reg) => "r",
LoongArch(LoongArchInlineAsmRegClass::freg) => "f",
Mips(MipsInlineAsmRegClass::reg) => "r",
Expand Down Expand Up @@ -828,7 +884,25 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &'
| Arm(ArmInlineAsmRegClass::qreg_low8)
| Arm(ArmInlineAsmRegClass::qreg_low4) => cx.type_vector(cx.type_i64(), 2),
Hexagon(HexagonInlineAsmRegClass::reg) => cx.type_i32(),
Hexagon(HexagonInlineAsmRegClass::reg_pair) => cx.type_i64(),
Hexagon(HexagonInlineAsmRegClass::preg) => unreachable!("clobber-only"),
Hexagon(HexagonInlineAsmRegClass::vreg) => {
// HVX vector register size depends on the HVX mode.
// LLVM's "v" constraint requires the exact vector width.
if cx.tcx.sess.unstable_target_features.contains(&sym::hvx_length128b) {
cx.type_vector(cx.type_i32(), 32) // 1024-bit for 128B mode
} else {
cx.type_vector(cx.type_i32(), 16) // 512-bit for 64B mode
}
}
Hexagon(HexagonInlineAsmRegClass::vreg_pair) => {
if cx.tcx.sess.unstable_target_features.contains(&sym::hvx_length128b) {
cx.type_vector(cx.type_i32(), 64) // 2048-bit for 128B mode
} else {
cx.type_vector(cx.type_i32(), 32) // 1024-bit for 64B mode
}
}
Hexagon(HexagonInlineAsmRegClass::qreg) => unreachable!("clobber-only"),
LoongArch(LoongArchInlineAsmRegClass::reg) => cx.type_i32(),
LoongArch(LoongArchInlineAsmRegClass::freg) => cx.type_f32(),
Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(),
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1042,6 +1042,9 @@ symbols! {
html_no_source,
html_playground_url,
html_root_url,
hvx,
hvx_length64b: "hvx-length64b",
hvx_length128b: "hvx-length128b",
hwaddress,
i8,
i16,
Expand Down Expand Up @@ -2215,6 +2218,7 @@ symbols! {
volatile_store,
vreg,
vreg_low16,
vreg_pair,
vsreg,
vsx,
vtable_align,
Expand Down
150 changes: 149 additions & 1 deletion compiler/rustc_target/src/asm/hexagon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
def_reg_class! {
Hexagon HexagonInlineAsmRegClass {
reg,
reg_pair,
preg,
vreg,
vreg_pair,
qreg,
}
}

Expand Down Expand Up @@ -38,7 +42,17 @@ impl HexagonInlineAsmRegClass {
) -> &'static [(InlineAsmType, Option<Symbol>)] {
match self {
Self::reg => types! { _: I8, I16, I32, F32; },
Self::reg_pair => types! { _: I64, F64; },
Self::preg => &[],
Self::vreg => types! {
hvx_length64b: VecI32(16);
hvx_length128b: VecI32(32);
},
Self::vreg_pair => types! {
hvx_length64b: VecI32(32);
hvx_length128b: VecI32(64);
},
Self::qreg => &[],
}
}
}
Expand Down Expand Up @@ -73,18 +87,89 @@ def_regs! {
r26: reg = ["r26"],
r27: reg = ["r27"],
r28: reg = ["r28"],
r1_0: reg_pair = ["r1:0"],
r3_2: reg_pair = ["r3:2"],
r5_4: reg_pair = ["r5:4"],
r7_6: reg_pair = ["r7:6"],
r9_8: reg_pair = ["r9:8"],
r11_10: reg_pair = ["r11:10"],
r13_12: reg_pair = ["r13:12"],
r15_14: reg_pair = ["r15:14"],
r17_16: reg_pair = ["r17:16"],
r21_20: reg_pair = ["r21:20"],
r23_22: reg_pair = ["r23:22"],
r25_24: reg_pair = ["r25:24"],
r27_26: reg_pair = ["r27:26"],
p0: preg = ["p0"],
p1: preg = ["p1"],
p2: preg = ["p2"],
p3: preg = ["p3"],
v0: vreg = ["v0"],
v1: vreg = ["v1"],
v2: vreg = ["v2"],
v3: vreg = ["v3"],
v4: vreg = ["v4"],
v5: vreg = ["v5"],
v6: vreg = ["v6"],
v7: vreg = ["v7"],
v8: vreg = ["v8"],
v9: vreg = ["v9"],
v10: vreg = ["v10"],
v11: vreg = ["v11"],
v12: vreg = ["v12"],
v13: vreg = ["v13"],
v14: vreg = ["v14"],
v15: vreg = ["v15"],
v16: vreg = ["v16"],
v17: vreg = ["v17"],
v18: vreg = ["v18"],
v19: vreg = ["v19"],
v20: vreg = ["v20"],
v21: vreg = ["v21"],
v22: vreg = ["v22"],
v23: vreg = ["v23"],
v24: vreg = ["v24"],
v25: vreg = ["v25"],
v26: vreg = ["v26"],
v27: vreg = ["v27"],
v28: vreg = ["v28"],
v29: vreg = ["v29"],
v30: vreg = ["v30"],
v31: vreg = ["v31"],
v1_0: vreg_pair = ["v1:0"],
v3_2: vreg_pair = ["v3:2"],
v5_4: vreg_pair = ["v5:4"],
v7_6: vreg_pair = ["v7:6"],
v9_8: vreg_pair = ["v9:8"],
v11_10: vreg_pair = ["v11:10"],
v13_12: vreg_pair = ["v13:12"],
v15_14: vreg_pair = ["v15:14"],
v17_16: vreg_pair = ["v17:16"],
v19_18: vreg_pair = ["v19:18"],
v21_20: vreg_pair = ["v21:20"],
v23_22: vreg_pair = ["v23:22"],
v25_24: vreg_pair = ["v25:24"],
v27_26: vreg_pair = ["v27:26"],
v29_28: vreg_pair = ["v29:28"],
v31_30: vreg_pair = ["v31:30"],
q0: qreg = ["q0"],
q1: qreg = ["q1"],
q2: qreg = ["q2"],
q3: qreg = ["q3"],
#error = ["r19"] =>
"r19 is used internally by LLVM and cannot be used as an operand for inline asm",
#error = ["r19:18"] =>
"r19 is used internally by LLVM and cannot be used as an operand for inline asm",
#error = ["r29", "sp"] =>
"the stack pointer cannot be used as an operand for inline asm",
#error = ["r29:28"] =>
"the stack pointer cannot be used as an operand for inline asm",
#error = ["r30", "fr"] =>
"the frame register cannot be used as an operand for inline asm",
#error = ["r31", "lr"] =>
"the link register cannot be used as an operand for inline asm",
#error = ["r31:30"] =>
"the frame register and link register cannot be used as an operand for inline asm",
}
}

Expand All @@ -98,5 +183,68 @@ impl HexagonInlineAsmReg {
out.write_str(self.name())
}

pub fn overlapping_regs(self, mut _cb: impl FnMut(HexagonInlineAsmReg)) {}
pub fn overlapping_regs(self, mut cb: impl FnMut(HexagonInlineAsmReg)) {
cb(self);

macro_rules! reg_pair_conflicts {
(
$(
$pair:ident : $hi:ident $lo:ident,
)*
) => {
match self {
$(
Self::$pair => {
cb(Self::$hi);
cb(Self::$lo);
}
Self::$hi => {
cb(Self::$pair);
}
Self::$lo => {
cb(Self::$pair);
}
)*
_ => {}
}
};
}

// GPR pair ↔ single GPR conflicts
reg_pair_conflicts! {
r1_0 : r1 r0,
r3_2 : r3 r2,
r5_4 : r5 r4,
r7_6 : r7 r6,
r9_8 : r9 r8,
r11_10 : r11 r10,
r13_12 : r13 r12,
r15_14 : r15 r14,
r17_16 : r17 r16,
r21_20 : r21 r20,
r23_22 : r23 r22,
r25_24 : r25 r24,
r27_26 : r27 r26,
}

// HVX vector pair ↔ single vector conflicts
reg_pair_conflicts! {
v1_0 : v1 v0,
v3_2 : v3 v2,
v5_4 : v5 v4,
v7_6 : v7 v6,
v9_8 : v9 v8,
v11_10 : v11 v10,
v13_12 : v13 v12,
v15_14 : v15 v14,
v17_16 : v17 v16,
v19_18 : v19 v18,
v21_20 : v21 v20,
v23_22 : v23 v22,
v25_24 : v25 v24,
v27_26 : v27 v26,
v29_28 : v29 v28,
v31_30 : v31 v30,
}
}
}
Loading
Loading