about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-04-11 07:15:04 +0000
committerbors <bors@rust-lang.org>2024-04-11 07:15:04 +0000
commit05ccc49a4412a23a7afa1226804bb44558fb15b0 (patch)
tree4dd58cd390b531d8ff71d70d79d29e1febebc271 /compiler
parentf13f37fd7bbbc34c663311739176fe114ef51085 (diff)
parent2e44d29460bd4e8b94d3a0f491b04b9580506811 (diff)
Auto merge of #123507 - dpaoliello:arm64ecasm, r=Amanieu
Add support for Arm64EC inline assembly (as unstable)

Compiler support for Arm64EC assembly mostly reuses the existing AArch64 support, except that it needs to block registers that are not permitted: <https://learn.microsoft.com/en-us/windows/arm/arm64ec-abi#register-mapping-and-blocked-registers>

For assembly authors there are several caveats and differences that need to be considered, I've provided documentation for this as part of the "Standard Library Support" PR: <https://github.com/rust-lang/rust/pull/123144/files#diff-6b08532480943c8b82f5dbda7ee1521afa74c9f626466aeb308dfa6956397edd>

r? rust-lang/compiler
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_codegen_llvm/src/asm.rs2
-rw-r--r--compiler/rustc_target/src/asm/aarch64.rs56
-rw-r--r--compiler/rustc_target/src/asm/mod.rs16
3 files changed, 49 insertions, 25 deletions
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index 500904ce188..e09869cf425 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -220,7 +220,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
         constraints.append(&mut clobbers);
         if !options.contains(InlineAsmOptions::PRESERVES_FLAGS) {
             match asm_arch {
-                InlineAsmArch::AArch64 | InlineAsmArch::Arm => {
+                InlineAsmArch::AArch64 | InlineAsmArch::Arm64EC | InlineAsmArch::Arm => {
                     constraints.push("~{cc}".to_string());
                 }
                 InlineAsmArch::X86 | InlineAsmArch::X86_64 => {
diff --git a/compiler/rustc_target/src/asm/aarch64.rs b/compiler/rustc_target/src/asm/aarch64.rs
index 70528c1222c..5ae9a2e2058 100644
--- a/compiler/rustc_target/src/asm/aarch64.rs
+++ b/compiler/rustc_target/src/asm/aarch64.rs
@@ -87,6 +87,20 @@ fn reserved_x18(
     }
 }
 
+fn restricted_for_arm64ec(
+    arch: InlineAsmArch,
+    _reloc_model: RelocModel,
+    _target_features: &FxIndexSet<Symbol>,
+    _target: &Target,
+    _is_clobber: bool,
+) -> Result<(), &'static str> {
+    if arch == InlineAsmArch::Arm64EC {
+        Err("x13, x14, x23, x24, x28, v16-v31 cannot be used for Arm64EC")
+    } else {
+        Ok(())
+    }
+}
+
 def_regs! {
     AArch64 AArch64InlineAsmReg AArch64InlineAsmRegClass {
         x0: reg = ["x0", "w0"],
@@ -102,8 +116,8 @@ def_regs! {
         x10: reg = ["x10", "w10"],
         x11: reg = ["x11", "w11"],
         x12: reg = ["x12", "w12"],
-        x13: reg = ["x13", "w13"],
-        x14: reg = ["x14", "w14"],
+        x13: reg = ["x13", "w13"] % restricted_for_arm64ec,
+        x14: reg = ["x14", "w14"] % restricted_for_arm64ec,
         x15: reg = ["x15", "w15"],
         x16: reg = ["x16", "w16"],
         x17: reg = ["x17", "w17"],
@@ -111,12 +125,12 @@ def_regs! {
         x20: reg = ["x20", "w20"],
         x21: reg = ["x21", "w21"],
         x22: reg = ["x22", "w22"],
-        x23: reg = ["x23", "w23"],
-        x24: reg = ["x24", "w24"],
+        x23: reg = ["x23", "w23"] % restricted_for_arm64ec,
+        x24: reg = ["x24", "w24"] % restricted_for_arm64ec,
         x25: reg = ["x25", "w25"],
         x26: reg = ["x26", "w26"],
         x27: reg = ["x27", "w27"],
-        x28: reg = ["x28", "w28"],
+        x28: reg = ["x28", "w28"] % restricted_for_arm64ec,
         x30: reg = ["x30", "w30", "lr", "wlr"],
         v0: vreg, vreg_low16 = ["v0", "b0", "h0", "s0", "d0", "q0", "z0"],
         v1: vreg, vreg_low16 = ["v1", "b1", "h1", "s1", "d1", "q1", "z1"],
@@ -134,22 +148,22 @@ def_regs! {
         v13: vreg, vreg_low16 = ["v13", "b13", "h13", "s13", "d13", "q13", "z13"],
         v14: vreg, vreg_low16 = ["v14", "b14", "h14", "s14", "d14", "q14", "z14"],
         v15: vreg, vreg_low16 = ["v15", "b15", "h15", "s15", "d15", "q15", "z15"],
-        v16: vreg = ["v16", "b16", "h16", "s16", "d16", "q16", "z16"],
-        v17: vreg = ["v17", "b17", "h17", "s17", "d17", "q17", "z17"],
-        v18: vreg = ["v18", "b18", "h18", "s18", "d18", "q18", "z18"],
-        v19: vreg = ["v19", "b19", "h19", "s19", "d19", "q19", "z19"],
-        v20: vreg = ["v20", "b20", "h20", "s20", "d20", "q20", "z20"],
-        v21: vreg = ["v21", "b21", "h21", "s21", "d21", "q21", "z21"],
-        v22: vreg = ["v22", "b22", "h22", "s22", "d22", "q22", "z22"],
-        v23: vreg = ["v23", "b23", "h23", "s23", "d23", "q23", "z23"],
-        v24: vreg = ["v24", "b24", "h24", "s24", "d24", "q24", "z24"],
-        v25: vreg = ["v25", "b25", "h25", "s25", "d25", "q25", "z25"],
-        v26: vreg = ["v26", "b26", "h26", "s26", "d26", "q26", "z26"],
-        v27: vreg = ["v27", "b27", "h27", "s27", "d27", "q27", "z27"],
-        v28: vreg = ["v28", "b28", "h28", "s28", "d28", "q28", "z28"],
-        v29: vreg = ["v29", "b29", "h29", "s29", "d29", "q29", "z29"],
-        v30: vreg = ["v30", "b30", "h30", "s30", "d30", "q30", "z30"],
-        v31: vreg = ["v31", "b31", "h31", "s31", "d31", "q31", "z31"],
+        v16: vreg = ["v16", "b16", "h16", "s16", "d16", "q16", "z16"] % restricted_for_arm64ec,
+        v17: vreg = ["v17", "b17", "h17", "s17", "d17", "q17", "z17"] % restricted_for_arm64ec,
+        v18: vreg = ["v18", "b18", "h18", "s18", "d18", "q18", "z18"] % restricted_for_arm64ec,
+        v19: vreg = ["v19", "b19", "h19", "s19", "d19", "q19", "z19"] % restricted_for_arm64ec,
+        v20: vreg = ["v20", "b20", "h20", "s20", "d20", "q20", "z20"] % restricted_for_arm64ec,
+        v21: vreg = ["v21", "b21", "h21", "s21", "d21", "q21", "z21"] % restricted_for_arm64ec,
+        v22: vreg = ["v22", "b22", "h22", "s22", "d22", "q22", "z22"] % restricted_for_arm64ec,
+        v23: vreg = ["v23", "b23", "h23", "s23", "d23", "q23", "z23"] % restricted_for_arm64ec,
+        v24: vreg = ["v24", "b24", "h24", "s24", "d24", "q24", "z24"] % restricted_for_arm64ec,
+        v25: vreg = ["v25", "b25", "h25", "s25", "d25", "q25", "z25"] % restricted_for_arm64ec,
+        v26: vreg = ["v26", "b26", "h26", "s26", "d26", "q26", "z26"] % restricted_for_arm64ec,
+        v27: vreg = ["v27", "b27", "h27", "s27", "d27", "q27", "z27"] % restricted_for_arm64ec,
+        v28: vreg = ["v28", "b28", "h28", "s28", "d28", "q28", "z28"] % restricted_for_arm64ec,
+        v29: vreg = ["v29", "b29", "h29", "s29", "d29", "q29", "z29"] % restricted_for_arm64ec,
+        v30: vreg = ["v30", "b30", "h30", "s30", "d30", "q30", "z30"] % restricted_for_arm64ec,
+        v31: vreg = ["v31", "b31", "h31", "s31", "d31", "q31", "z31"] % restricted_for_arm64ec,
         p0: preg = ["p0"],
         p1: preg = ["p1"],
         p2: preg = ["p2"],
diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs
index 2e04dca98c5..d6bbf4f36cf 100644
--- a/compiler/rustc_target/src/asm/mod.rs
+++ b/compiler/rustc_target/src/asm/mod.rs
@@ -217,6 +217,7 @@ pub enum InlineAsmArch {
     X86_64,
     Arm,
     AArch64,
+    Arm64EC,
     RiscV32,
     RiscV64,
     Nvptx64,
@@ -246,6 +247,7 @@ impl FromStr for InlineAsmArch {
             "x86_64" => Ok(Self::X86_64),
             "arm" => Ok(Self::Arm),
             "aarch64" => Ok(Self::AArch64),
+            "arm64ec" => Ok(Self::Arm64EC),
             "riscv32" => Ok(Self::RiscV32),
             "riscv64" => Ok(Self::RiscV64),
             "nvptx64" => Ok(Self::Nvptx64),
@@ -341,7 +343,9 @@ impl InlineAsmReg {
         Ok(match arch {
             InlineAsmArch::X86 | InlineAsmArch::X86_64 => Self::X86(X86InlineAsmReg::parse(name)?),
             InlineAsmArch::Arm => Self::Arm(ArmInlineAsmReg::parse(name)?),
-            InlineAsmArch::AArch64 => Self::AArch64(AArch64InlineAsmReg::parse(name)?),
+            InlineAsmArch::AArch64 | InlineAsmArch::Arm64EC => {
+                Self::AArch64(AArch64InlineAsmReg::parse(name)?)
+            }
             InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
                 Self::RiscV(RiscVInlineAsmReg::parse(name)?)
             }
@@ -610,7 +614,9 @@ impl InlineAsmRegClass {
                 Self::X86(X86InlineAsmRegClass::parse(name)?)
             }
             InlineAsmArch::Arm => Self::Arm(ArmInlineAsmRegClass::parse(name)?),
-            InlineAsmArch::AArch64 => Self::AArch64(AArch64InlineAsmRegClass::parse(name)?),
+            InlineAsmArch::AArch64 | InlineAsmArch::Arm64EC => {
+                Self::AArch64(AArch64InlineAsmRegClass::parse(name)?)
+            }
             InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
                 Self::RiscV(RiscVInlineAsmRegClass::parse(name)?)
             }
@@ -783,7 +789,7 @@ pub fn allocatable_registers(
             arm::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
             map
         }
-        InlineAsmArch::AArch64 => {
+        InlineAsmArch::AArch64 | InlineAsmArch::Arm64EC => {
             let mut map = aarch64::regclass_map();
             aarch64::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
             map
@@ -909,6 +915,10 @@ impl InlineAsmClobberAbi {
                 }),
                 _ => Err(&["C", "system", "efiapi"]),
             },
+            InlineAsmArch::Arm64EC => match name {
+                "C" | "system" => Ok(InlineAsmClobberAbi::AArch64NoX18),
+                _ => Err(&["C", "system"]),
+            },
             InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => match name {
                 "C" | "system" | "efiapi" => Ok(InlineAsmClobberAbi::RiscV),
                 _ => Err(&["C", "system", "efiapi"]),