From 1d07fb1a8e2303238b3f5e15edb667b3ba274707 Mon Sep 17 00:00:00 2001 From: Andy Sadler Date: Tue, 24 Nov 2020 16:37:36 -0600 Subject: [PATCH] Migrate llvm_asm! macro calls to new asm! macro Fixes #904 --- crates/core_arch/src/acle/barrier/cp15.rs | 15 ++++- crates/core_arch/src/acle/hints.rs | 9 ++- crates/core_arch/src/acle/registers/mod.rs | 8 +-- crates/core_arch/src/arm/armclang.rs | 14 ++-- crates/core_arch/src/lib.rs | 2 +- crates/core_arch/src/x86/bt.rs | 36 ++++++----- crates/core_arch/src/x86/cpuid.rs | 75 ++++++++++++---------- crates/core_arch/src/x86/eflags.rs | 8 +-- crates/core_arch/src/x86_64/bt.rs | 36 ++++++----- crates/std_detect/src/detect/os/aarch64.rs | 6 +- 10 files changed, 120 insertions(+), 89 deletions(-) diff --git a/crates/core_arch/src/acle/barrier/cp15.rs b/crates/core_arch/src/acle/barrier/cp15.rs index a4d101ad82..ca61c23491 100644 --- a/crates/core_arch/src/acle/barrier/cp15.rs +++ b/crates/core_arch/src/acle/barrier/cp15.rs @@ -8,20 +8,29 @@ pub struct SY; impl super::super::sealed::Dmb for SY { #[inline(always)] unsafe fn __dmb(&self) { - llvm_asm!("mcr p15, 0, r0, c7, c10, 5" : : : "memory" : "volatile") + asm!( + "mcr p15, 0, r0, c7, c10, 5", + options(nostack, preserves_flags) + ); } } impl super::super::sealed::Dsb for SY { #[inline(always)] unsafe fn __dsb(&self) { - llvm_asm!("mcr p15, 0, r0, c7, c10, 4" : : : "memory" : "volatile") + asm!( + "mcr p15, 0, r0, c7, c10, 4", + options(nostack, preserves_flags) + ); } } impl super::super::sealed::Isb for SY { #[inline(always)] unsafe fn __isb(&self) { - llvm_asm!("mcr p15, 0, r0, c7, c5, 4" : : : "memory" : "volatile") + asm!( + "mcr p15, 0, r0, c7, c5, 4", + options(nostack, preserves_flags) + ); } } diff --git a/crates/core_arch/src/acle/hints.rs b/crates/core_arch/src/acle/hints.rs index 892d4f517f..b5be929975 100644 --- a/crates/core_arch/src/acle/hints.rs +++ b/crates/core_arch/src/acle/hints.rs @@ -85,8 +85,11 @@ pub unsafe fn __yield() { pub unsafe fn __dbg(imm4: u32) { macro_rules! call { ($imm4:expr) => { - llvm_asm!(concat!("DBG ", stringify!($imm4)) : : : : "volatile") - } + asm!( + concat!("DBG ", stringify!($imm4)), + options(nostack, nomem, preserves_flags) + ); + }; } match imm4 & 0b1111 { @@ -117,7 +120,7 @@ pub unsafe fn __dbg(imm4: u32) { /// will increase execution time. #[inline(always)] pub unsafe fn __nop() { - llvm_asm!("NOP" : : : : "volatile") + asm!("NOP", options(nostack, nomem, preserves_flags)); } extern "C" { diff --git a/crates/core_arch/src/acle/registers/mod.rs b/crates/core_arch/src/acle/registers/mod.rs index 391a5f0824..17353cf1ca 100644 --- a/crates/core_arch/src/acle/registers/mod.rs +++ b/crates/core_arch/src/acle/registers/mod.rs @@ -4,7 +4,7 @@ macro_rules! rsr { impl super::super::sealed::Rsr for $R { unsafe fn __rsr(&self) -> u32 { let r: u32; - llvm_asm!(concat!("mrs $0,", stringify!($R)) : "=r"(r) : : : "volatile"); + asm!(concat!("mrs {},", stringify!($R)), out(reg) r, options(nostack, nomem, preserves_flags)); r } } @@ -17,7 +17,7 @@ macro_rules! rsrp { impl super::super::sealed::Rsrp for $R { unsafe fn __rsrp(&self) -> *const u8 { let r: *const u8; - llvm_asm!(concat!("mrs $0,", stringify!($R)) : "=r"(r) : : : "volatile"); + asm!(concat!("mrs {},", stringify!($R)), out(reg) r, options(nostack, nomem, preserves_flags)); r } } @@ -29,7 +29,7 @@ macro_rules! wsr { ($R:ident) => { impl super::super::sealed::Wsr for $R { unsafe fn __wsr(&self, value: u32) { - llvm_asm!(concat!("msr ", stringify!($R), ",$0") : : "r"(value) : : "volatile"); + asm!(concat!("msr ", stringify!($R), ",{}"), in(reg) value, options(nostack, nomem, preserves_flags)); } } }; @@ -40,7 +40,7 @@ macro_rules! wsrp { ($R:ident) => { impl super::super::sealed::Wsrp for $R { unsafe fn __wsrp(&self, value: *const u8) { - llvm_asm!(concat!("msr ", stringify!($R), ",$0") : : "r"(value) : : "volatile"); + asm!(concat!("msr ", stringify!($R), ",{}"), in(reg) value, options(nostack, nomem, preserves_flags)); } } }; diff --git a/crates/core_arch/src/arm/armclang.rs b/crates/core_arch/src/arm/armclang.rs index 2604727984..98a6a3c6e8 100644 --- a/crates/core_arch/src/arm/armclang.rs +++ b/crates/core_arch/src/arm/armclang.rs @@ -51,15 +51,21 @@ pub unsafe fn __breakpoint(val: i32) { #[cfg(target_arch = "arm")] macro_rules! call { ($imm8:expr) => { - llvm_asm!(concat!("BKPT ", stringify!($imm8)) : : : : "volatile") - } + asm!( + concat!("BKPT ", stringify!($imm8)), + options(nostack, nomem, preserves_flags) + ); + }; } #[cfg(target_arch = "aarch64")] macro_rules! call { ($imm8:expr) => { - llvm_asm!(concat!("BRK ", stringify!($imm8)) : : : : "volatile") - } + asm!( + concat!("BRK ", stringify!($imm8)), + options(nostack, nomem, preserves_flags) + ); + }; } // We can't `panic!` inside this intrinsic, so we can't really validate the diff --git a/crates/core_arch/src/lib.rs b/crates/core_arch/src/lib.rs index 2c744c2ffb..14c59768d3 100644 --- a/crates/core_arch/src/lib.rs +++ b/crates/core_arch/src/lib.rs @@ -13,7 +13,7 @@ platform_intrinsics, repr_simd, simd_ffi, - llvm_asm, + asm, proc_macro_hygiene, stmt_expr_attributes, core_intrinsics, diff --git a/crates/core_arch/src/x86/bt.rs b/crates/core_arch/src/x86/bt.rs index dc172f6f38..1d162d990d 100644 --- a/crates/core_arch/src/x86/bt.rs +++ b/crates/core_arch/src/x86/bt.rs @@ -7,10 +7,11 @@ use stdarch_test::assert_instr; #[unstable(feature = "simd_x86_bittest", issue = "59414")] pub unsafe fn _bittest(p: *const i32, b: i32) -> u8 { let r: u8; - llvm_asm!("btl $2, $1\n\tsetc ${0:b}" - : "=r"(r) - : "*m"(p), "r"(b) - : "cc", "memory"); + asm!("btl {b:e}, ({p}); setc {r}", + b = in(reg) b, + p = in(reg) p, + r = lateout(reg_byte) r, + options(att_syntax, nostack, readonly)); r } @@ -20,10 +21,11 @@ pub unsafe fn _bittest(p: *const i32, b: i32) -> u8 { #[unstable(feature = "simd_x86_bittest", issue = "59414")] pub unsafe fn _bittestandset(p: *mut i32, b: i32) -> u8 { let r: u8; - llvm_asm!("btsl $2, $1\n\tsetc ${0:b}" - : "=r"(r), "+*m"(p) - : "r"(b) - : "cc", "memory"); + asm!("btsl {b:e}, ({p}); setc {r}", + b = in(reg) b, + p = in(reg) p, + r = lateout(reg_byte) r, + options(att_syntax, nostack)); r } @@ -33,10 +35,11 @@ pub unsafe fn _bittestandset(p: *mut i32, b: i32) -> u8 { #[unstable(feature = "simd_x86_bittest", issue = "59414")] pub unsafe fn _bittestandreset(p: *mut i32, b: i32) -> u8 { let r: u8; - llvm_asm!("btrl $2, $1\n\tsetc ${0:b}" - : "=r"(r), "+*m"(p) - : "r"(b) - : "cc", "memory"); + asm!("btrl {b:e}, ({p}); setc {r}", + b = in(reg) b, + p = in(reg) p, + r = lateout(reg_byte) r, + options(att_syntax, nostack)); r } @@ -46,10 +49,11 @@ pub unsafe fn _bittestandreset(p: *mut i32, b: i32) -> u8 { #[unstable(feature = "simd_x86_bittest", issue = "59414")] pub unsafe fn _bittestandcomplement(p: *mut i32, b: i32) -> u8 { let r: u8; - llvm_asm!("btcl $2, $1\n\tsetc ${0:b}" - : "=r"(r), "+*m"(p) - : "r"(b) - : "cc", "memory"); + asm!("btcl {b:e}, ({p}); setc {r}", + b = in(reg) b, + p = in(reg) p, + r = lateout(reg_byte) r, + options(att_syntax, nostack)); r } diff --git a/crates/core_arch/src/x86/cpuid.rs b/crates/core_arch/src/x86/cpuid.rs index f292ae7b54..939ef33ca7 100644 --- a/crates/core_arch/src/x86/cpuid.rs +++ b/crates/core_arch/src/x86/cpuid.rs @@ -57,24 +57,27 @@ pub unsafe fn __cpuid_count(leaf: u32, sub_leaf: u32) -> CpuidResult { let edx; #[cfg(target_arch = "x86")] { - llvm_asm!("cpuid" - : "={eax}"(eax), "={ebx}"(ebx), "={ecx}"(ecx), "={edx}"(edx) - : "{eax}"(leaf), "{ecx}"(sub_leaf) - : :); + asm!("cpuid", + inlateout("eax") leaf => eax, + lateout("ebx") ebx, + inlateout("ecx") sub_leaf => ecx, + lateout("edx") edx, + options(nostack, nomem, att_syntax, preserves_flags, pure)); } #[cfg(target_arch = "x86_64")] { // x86-64 uses %rbx as the base register, so preserve it. // This works around a bug in LLVM with ASAN enabled: // https://bugs.llvm.org/show_bug.cgi?id=17907 - llvm_asm!(r#" - mov %rbx, %rsi - cpuid - xchg %rbx, %rsi - "# - : "={eax}"(eax), "={esi}"(ebx), "={ecx}"(ecx), "={edx}"(edx) - : "{eax}"(leaf), "{ecx}"(sub_leaf) - : :); + asm!( + "mov %rbx, %rsi", + "cpuid", + "xchg %rbx, %rsi", + inlateout("eax") leaf => eax, + lateout("esi") ebx, + inlateout("ecx") sub_leaf => ecx, + lateout("edx") edx, + options(nostack, nomem, att_syntax, preserves_flags, pure)); } CpuidResult { eax, ebx, ecx, edx } } @@ -119,29 +122,31 @@ pub fn has_cpuid() -> bool { // If it is, then `cpuid` is available. let result: u32; let _temp: u32; - llvm_asm!(r#" - # Read eflags into $0 and copy it into $1: - pushfd - pop $0 - mov $1, $0 - # Flip 21st bit of $0. - xor $0, 0x200000 - # Set eflags to the value of $0 - # - # Bit 21st can only be modified if cpuid is available - push $0 - popfd # A - # Read eflags into $0: - pushfd # B - pop $0 - # xor with the original eflags sets the bits that - # have been modified: - xor $0, $1 - "# - : "=r"(result), "=r"(_temp) - : - : "cc", "memory" - : "intel"); + asm!(r#" + # Read eflags into res and copy it into tmp: + pushfl + popl {res} + movl {res}, {tmp} + # Flip 21st bit of res. + xorl {mask}, {res} + # Set eflags to the value of res + # + # Bit 21st can only be modified if cpuid is available + pushl {res} + popfl # A + # Read eflags into res: + pushfl # B + popl {res} + # xor with the original eflags sets the bits that + # have been modified: + xorl {tmp}, {res} + "#, + res = out(reg) result, + tmp = out(reg) _, + mask = const 0x200000, + // we're not overwriting any of the status flags, so we can + // enable the preserves_flags option + options(nomem, att_syntax)); // There is a race between popfd (A) and pushfd (B) // where other bits beyond 21st may have been modified due to // interrupts, a debugger stepping through the asm, etc. diff --git a/crates/core_arch/src/x86/eflags.rs b/crates/core_arch/src/x86/eflags.rs index acb77bc3ec..beb7b9b5d7 100644 --- a/crates/core_arch/src/x86/eflags.rs +++ b/crates/core_arch/src/x86/eflags.rs @@ -13,7 +13,7 @@ #[doc(hidden)] pub unsafe fn __readeflags() -> u32 { let eflags: u32; - llvm_asm!("pushfd; popl $0" : "=r"(eflags) : : : "volatile"); + asm!("pushfd; popl {}", out(reg) eflags, options(att_syntax, preserves_flags, nomem, pure)); eflags } @@ -30,7 +30,7 @@ pub unsafe fn __readeflags() -> u32 { #[doc(hidden)] pub unsafe fn __readeflags() -> u64 { let eflags: u64; - llvm_asm!("pushfq; popq $0" : "=r"(eflags) : : : "volatile"); + asm!("pushfq; popq {}", out(reg) eflags, options(att_syntax, preserves_flags, nomem, pure)); eflags } @@ -46,7 +46,7 @@ pub unsafe fn __readeflags() -> u64 { )] #[doc(hidden)] pub unsafe fn __writeeflags(eflags: u32) { - llvm_asm!("pushl $0; popfd" : : "r"(eflags) : "cc", "flags" : "volatile"); + asm!("pushl {}; popfd", in(reg) eflags, options(att_syntax, nomem)); } /// Write EFLAGS. @@ -61,7 +61,7 @@ pub unsafe fn __writeeflags(eflags: u32) { )] #[doc(hidden)] pub unsafe fn __writeeflags(eflags: u64) { - llvm_asm!("pushq $0; popfq" : : "r"(eflags) : "cc", "flags" : "volatile"); + asm!("pushq {}; popfq", in(reg) eflags, options(att_syntax, nomem)); } #[cfg(test)] diff --git a/crates/core_arch/src/x86_64/bt.rs b/crates/core_arch/src/x86_64/bt.rs index f0b16baab6..69e67bebe0 100644 --- a/crates/core_arch/src/x86_64/bt.rs +++ b/crates/core_arch/src/x86_64/bt.rs @@ -7,10 +7,11 @@ use stdarch_test::assert_instr; #[unstable(feature = "simd_x86_bittest", issue = "59414")] pub unsafe fn _bittest64(p: *const i64, b: i64) -> u8 { let r: u8; - llvm_asm!("btq $2, $1\n\tsetc ${0:b}" - : "=r"(r) - : "*m"(p), "r"(b) - : "cc", "memory"); + asm!("btq {b}, ({p}); setc {r}", + p = in(reg) p, + b = in(reg) b, + r = lateout(reg_byte) r, + options(att_syntax, nostack, readonly)); r } @@ -20,10 +21,11 @@ pub unsafe fn _bittest64(p: *const i64, b: i64) -> u8 { #[unstable(feature = "simd_x86_bittest", issue = "59414")] pub unsafe fn _bittestandset64(p: *mut i64, b: i64) -> u8 { let r: u8; - llvm_asm!("btsq $2, $1\n\tsetc ${0:b}" - : "=r"(r), "+*m"(p) - : "r"(b) - : "cc", "memory"); + asm!("btsq {b}, ({p}); setc {r}", + b = in(reg) b, + p = in(reg) p, + r = lateout(reg_byte) r, + options(att_syntax, nostack)); r } @@ -33,10 +35,11 @@ pub unsafe fn _bittestandset64(p: *mut i64, b: i64) -> u8 { #[unstable(feature = "simd_x86_bittest", issue = "59414")] pub unsafe fn _bittestandreset64(p: *mut i64, b: i64) -> u8 { let r: u8; - llvm_asm!("btrq $2, $1\n\tsetc ${0:b}" - : "=r"(r), "+*m"(p) - : "r"(b) - : "cc", "memory"); + asm!("btrq {b}, ({p}); setc {r}", + b = in(reg) b, + p = in(reg) p, + r = lateout(reg_byte) r, + options(att_syntax, nostack)); r } @@ -46,10 +49,11 @@ pub unsafe fn _bittestandreset64(p: *mut i64, b: i64) -> u8 { #[unstable(feature = "simd_x86_bittest", issue = "59414")] pub unsafe fn _bittestandcomplement64(p: *mut i64, b: i64) -> u8 { let r: u8; - llvm_asm!("btcq $2, $1\n\tsetc ${0:b}" - : "=r"(r), "+*m"(p) - : "r"(b) - : "cc", "memory"); + asm!("btcq {b}, ({p}); setc {r}", + b = in(reg) b, + p = in(reg) p, + r = lateout(reg_byte) r, + options(att_syntax, nostack)); r } diff --git a/crates/std_detect/src/detect/os/aarch64.rs b/crates/std_detect/src/detect/os/aarch64.rs index c95b688970..52b7101c29 100644 --- a/crates/std_detect/src/detect/os/aarch64.rs +++ b/crates/std_detect/src/detect/os/aarch64.rs @@ -34,7 +34,7 @@ pub(crate) fn detect_features() -> cache::Initializer { // ID_AA64ISAR0_EL1 - Instruction Set Attribute Register 0 let aa64isar0: u64; unsafe { - llvm_asm!("mrs $0, ID_AA64ISAR0_EL1" : "=r"(aa64isar0)); + asm!("mrs {}, ID_AA64ISAR0_EL1", out(reg) aa64isar0); } let aes = bits_shift(aa64isar0, 7, 4) >= 1; @@ -51,7 +51,7 @@ pub(crate) fn detect_features() -> cache::Initializer { // ID_AA64PFR0_EL1 - Processor Feature Register 0 let aa64pfr0: u64; unsafe { - llvm_asm!("mrs $0, ID_AA64PFR0_EL1" : "=r"(aa64pfr0)); + asm!("mrs {}, ID_AA64PFR0_EL1", out(reg) aa64pfr0); } let fp = bits_shift(aa64pfr0, 19, 16) < 0xF; @@ -74,7 +74,7 @@ pub(crate) fn detect_features() -> cache::Initializer { // ID_AA64ISAR1_EL1 - Instruction Set Attribute Register 1 let aa64isar1: u64; unsafe { - llvm_asm!("mrs $0, ID_AA64ISAR1_EL1" : "=r"(aa64isar1)); + asm!("mrs {}, ID_AA64ISAR1_EL1", out(reg) aa64isar1); } enable_feature(Feature::rcpc, bits_shift(aa64isar1, 23, 20) >= 1);