Skip to content

Commit

Permalink
Auto merge of #68404 - Amanieu:llvm-asm, r=estebank
Browse files Browse the repository at this point in the history
Rename asm! to llvm_asm!

As per rust-lang/rfcs#2843, this PR renames `asm!` to `llvm_asm!`. It also renames the compiler's internal `InlineAsm` data structures to `LlvmInlineAsm` in preparation for the new `asm!` functionality specified in rust-lang/rfcs#2850.

This PR doesn't actually deprecate `asm!` yet, it just makes it redirect to `llvm_asm!`. This is necessary because we first need to update the submodules (in particular stdarch) to use `llvm_asm!`.
  • Loading branch information
bors committed Mar 27, 2020
2 parents 7b73d14 + 1cc521e commit 6c19a10
Show file tree
Hide file tree
Showing 136 changed files with 634 additions and 588 deletions.
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
# `asm`
# `llvm_asm`

The tracking issue for this feature is: [#29722]
The tracking issue for this feature is: [#70173]

[#29722]: https://github.com/rust-lang/rust/issues/29722
[#70173]: https://github.com/rust-lang/rust/issues/70173

------------------------

For extremely low-level manipulations and performance reasons, one
might wish to control the CPU directly. Rust supports using inline
assembly to do this via the `asm!` macro.
assembly to do this via the `llvm_asm!` macro.

```rust,ignore
asm!(assembly template
llvm_asm!(assembly template
: output operands
: input operands
: clobbers
: options
);
```

Any use of `asm` is feature gated (requires `#![feature(asm)]` on the
Any use of `llvm_asm` is feature gated (requires `#![feature(llvm_asm)]` on the
crate to allow) and of course requires an `unsafe` block.

> **Note**: the examples here are given in x86/x86-64 assembly, but
Expand All @@ -31,12 +31,12 @@ The `assembly template` is the only required parameter and must be a
literal string (i.e. `""`)

```rust
#![feature(asm)]
#![feature(llvm_asm)]

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
fn foo() {
unsafe {
asm!("NOP");
llvm_asm!("NOP");
}
}

Expand All @@ -51,16 +51,16 @@ fn main() {
}
```

(The `feature(asm)` and `#[cfg]`s are omitted from now on.)
(The `feature(llvm_asm)` and `#[cfg]`s are omitted from now on.)

Output operands, input operands, clobbers and options are all optional
but you must add the right number of `:` if you skip them:

```rust
# #![feature(asm)]
# #![feature(llvm_asm)]
# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
# fn main() { unsafe {
asm!("xor %eax, %eax"
llvm_asm!("xor %eax, %eax"
:
:
: "eax"
Expand All @@ -73,10 +73,10 @@ asm!("xor %eax, %eax"
Whitespace also doesn't matter:

```rust
# #![feature(asm)]
# #![feature(llvm_asm)]
# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
# fn main() { unsafe {
asm!("xor %eax, %eax" ::: "eax");
llvm_asm!("xor %eax, %eax" ::: "eax");
# } }
# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
# fn main() {}
Expand All @@ -89,12 +89,12 @@ Input and output operands follow the same format: `:
expressions must be mutable lvalues, or not yet assigned:

```rust
# #![feature(asm)]
# #![feature(llvm_asm)]
# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
fn add(a: i32, b: i32) -> i32 {
let c: i32;
unsafe {
asm!("add $2, $0"
llvm_asm!("add $2, $0"
: "=r"(c)
: "0"(a), "r"(b)
);
Expand All @@ -116,11 +116,11 @@ operand. This is useful for very low level programming, where
which register you use is important:

```rust
# #![feature(asm)]
# #![feature(llvm_asm)]
# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
# unsafe fn read_byte_in(port: u16) -> u8 {
let result: u8;
asm!("in %dx, %al" : "={al}"(result) : "{dx}"(port));
llvm_asm!("in %dx, %al" : "={al}"(result) : "{dx}"(port));
result
# }
```
Expand All @@ -133,11 +133,11 @@ compiler not to assume any values loaded into those registers will
stay valid.

```rust
# #![feature(asm)]
# #![feature(llvm_asm)]
# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
# fn main() { unsafe {
// Put the value 0x200 in eax:
asm!("mov $$0x200, %eax" : /* no outputs */ : /* no inputs */ : "eax");
llvm_asm!("mov $$0x200, %eax" : /* no outputs */ : /* no inputs */ : "eax");
# } }
# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
# fn main() {}
Expand Down Expand Up @@ -167,12 +167,12 @@ Current valid options are:
3. *intel* - use intel syntax instead of the default AT&T.

```rust
# #![feature(asm)]
# #![feature(llvm_asm)]
# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
# fn main() {
let result: i32;
unsafe {
asm!("mov eax, 2" : "={eax}"(result) : : : "intel")
llvm_asm!("mov eax, 2" : "={eax}"(result) : : : "intel")
}
println!("eax is currently {}", result);
# }
Expand All @@ -182,12 +182,12 @@ println!("eax is currently {}", result);

## More Information

The current implementation of the `asm!` macro is a direct binding to [LLVM's
The current implementation of the `llvm_asm!` macro is a direct binding to [LLVM's
inline assembler expressions][llvm-docs], so be sure to check out [their
documentation as well][llvm-docs] for more information about clobbers,
constraints, etc.

[llvm-docs]: http://llvm.org/docs/LangRef.html#inline-assembler-expressions

If you need more power and don't mind losing some of the niceties of
`asm!`, check out [global_asm](global-asm.md).
`llvm_asm!`, check out [global_asm](global-asm.md).
2 changes: 1 addition & 1 deletion src/libcore/hint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ pub fn black_box<T>(dummy: T) -> T {
// box. This isn't the greatest implementation since it probably deoptimizes
// more than we want, but it's so far good enough.
unsafe {
asm!("" : : "r"(&dummy));
llvm_asm!("" : : "r"(&dummy));
dummy
}
}
1 change: 1 addition & 0 deletions src/libcore/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
#![feature(is_sorted)]
#![feature(lang_items)]
#![feature(link_llvm_intrinsics)]
#![feature(llvm_asm)]
#![cfg_attr(not(bootstrap), feature(negative_impls))]
#![feature(never_type)]
#![feature(nll)]
Expand Down
43 changes: 42 additions & 1 deletion src/libcore/macros/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1307,7 +1307,7 @@ pub(crate) mod builtin {
/// [unstable book]: ../unstable-book/library-features/asm.html
#[unstable(
feature = "asm",
issue = "29722",
issue = "70173",
reason = "inline assembly is not stable enough for use and is subject to change"
)]
#[rustc_builtin_macro]
Expand All @@ -1322,6 +1322,47 @@ pub(crate) mod builtin {
};
}

/// Inline assembly.
///
/// Read the [unstable book] for the usage.
///
/// [unstable book]: ../unstable-book/library-features/asm.html
#[cfg(bootstrap)]
#[unstable(
feature = "llvm_asm",
issue = "70173",
reason = "inline assembly is not stable enough for use and is subject to change"
)]
#[macro_export]
#[allow_internal_unstable(asm)]
macro_rules! llvm_asm {
// Redirect to asm! for stage0
($($arg:tt)*) => { $crate::asm!($($arg)*) }
}

/// Inline assembly.
///
/// Read the [unstable book] for the usage.
///
/// [unstable book]: ../unstable-book/library-features/asm.html
#[cfg(not(bootstrap))]
#[unstable(
feature = "llvm_asm",
issue = "70173",
reason = "inline assembly is not stable enough for use and is subject to change"
)]
#[rustc_builtin_macro]
#[macro_export]
macro_rules! llvm_asm {
("assembly template"
: $("output"(operand),)*
: $("input"(operand),)*
: $("clobbers",)*
: $("options",)*) => {
/* compiler built-in */
};
}

/// Module-level inline assembly.
#[unstable(
feature = "global_asm",
Expand Down
4 changes: 2 additions & 2 deletions src/libcore/num/dec2flt/algorithm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ mod fpu_precision {
fn set_cw(cw: u16) {
// SAFETY: the `fldcw` instruction has been audited to be able to work correctly with
// any `u16`
unsafe { asm!("fldcw $0" :: "m" (cw) :: "volatile") }
unsafe { llvm_asm!("fldcw $0" :: "m" (cw) :: "volatile") }
}

/// Sets the precision field of the FPU to `T` and returns a `FPUControlWord`.
Expand All @@ -78,7 +78,7 @@ mod fpu_precision {
// `FPUControlWord` structure is dropped
// SAFETY: the `fnstcw` instruction has been audited to be able to work correctly with
// any `u16`
unsafe { asm!("fnstcw $0" : "=*m" (&cw) ::: "volatile") }
unsafe { llvm_asm!("fnstcw $0" : "=*m" (&cw) ::: "volatile") }

// Set the control word to the desired precision. This is achieved by masking away the old
// precision (bits 8 and 9, 0x300) and replacing it with the precision flag computed above.
Expand Down
4 changes: 2 additions & 2 deletions src/libcore/prelude/v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ pub use crate::hash::macros::Hash;
#[doc(no_inline)]
pub use crate::{
asm, assert, cfg, column, compile_error, concat, concat_idents, env, file, format_args,
format_args_nl, global_asm, include, include_bytes, include_str, line, log_syntax, module_path,
option_env, stringify, trace_macros,
format_args_nl, global_asm, include, include_bytes, include_str, line, llvm_asm, log_syntax,
module_path, option_env, stringify, trace_macros,
};

#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
Expand Down
10 changes: 5 additions & 5 deletions src/librustc/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1584,7 +1584,7 @@ pub enum StatementKind<'tcx> {

/// Executes a piece of inline Assembly. Stored in a Box to keep the size
/// of `StatementKind` low.
InlineAsm(Box<InlineAsm<'tcx>>),
LlvmInlineAsm(Box<LlvmInlineAsm<'tcx>>),

/// Retag references in the given place, ensuring they got fresh tags. This is
/// part of the Stacked Borrows model. These statements are currently only interpreted
Expand Down Expand Up @@ -1668,8 +1668,8 @@ pub enum FakeReadCause {
}

#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
pub struct InlineAsm<'tcx> {
pub asm: hir::InlineAsmInner,
pub struct LlvmInlineAsm<'tcx> {
pub asm: hir::LlvmInlineAsmInner,
pub outputs: Box<[Place<'tcx>]>,
pub inputs: Box<[(Span, Operand<'tcx>)]>,
}
Expand All @@ -1696,8 +1696,8 @@ impl Debug for Statement<'_> {
SetDiscriminant { ref place, variant_index } => {
write!(fmt, "discriminant({:?}) = {:?}", place, variant_index)
}
InlineAsm(ref asm) => {
write!(fmt, "asm!({:?} : {:?} : {:?})", asm.asm, asm.outputs, asm.inputs)
LlvmInlineAsm(ref asm) => {
write!(fmt, "llvm_asm!({:?} : {:?} : {:?})", asm.asm, asm.outputs, asm.inputs)
}
AscribeUserType(box (ref place, ref c_ty), ref variance) => {
write!(fmt, "AscribeUserType({:?}, {:?}, {:?})", place, variance, c_ty)
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ macro_rules! make_mir_visitor {
location
);
}
StatementKind::InlineAsm(asm) => {
StatementKind::LlvmInlineAsm(asm) => {
for output in & $($mutability)? asm.outputs[..] {
self.visit_place(
output,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ CloneTypeFoldableAndLiftImpls! {
::rustc_span::symbol::Symbol,
::rustc_hir::def::Res,
::rustc_hir::def_id::DefId,
::rustc_hir::InlineAsmInner,
::rustc_hir::LlvmInlineAsmInner,
::rustc_hir::MatchSource,
::rustc_hir::Mutability,
::rustc_hir::Unsafety,
Expand Down
26 changes: 13 additions & 13 deletions src/librustc_ast/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1114,7 +1114,7 @@ impl Expr {
ExprKind::Break(..) => ExprPrecedence::Break,
ExprKind::Continue(..) => ExprPrecedence::Continue,
ExprKind::Ret(..) => ExprPrecedence::Ret,
ExprKind::InlineAsm(..) => ExprPrecedence::InlineAsm,
ExprKind::LlvmInlineAsm(..) => ExprPrecedence::InlineAsm,
ExprKind::MacCall(..) => ExprPrecedence::Mac,
ExprKind::Struct(..) => ExprPrecedence::Struct,
ExprKind::Repeat(..) => ExprPrecedence::Repeat,
Expand Down Expand Up @@ -1243,8 +1243,8 @@ pub enum ExprKind {
/// A `return`, with an optional value to be returned.
Ret(Option<P<Expr>>),

/// Output of the `asm!()` macro.
InlineAsm(P<InlineAsm>),
/// Output of the `llvm_asm!()` macro.
LlvmInlineAsm(P<LlvmInlineAsm>),

/// A macro invocation; pre-expansion.
MacCall(MacCall),
Expand Down Expand Up @@ -1860,37 +1860,37 @@ pub enum TraitObjectSyntax {

/// Inline assembly dialect.
///
/// E.g., `"intel"` as in `asm!("mov eax, 2" : "={eax}"(result) : : : "intel")`.
/// E.g., `"intel"` as in `llvm_asm!("mov eax, 2" : "={eax}"(result) : : : "intel")`.
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, HashStable_Generic)]
pub enum AsmDialect {
pub enum LlvmAsmDialect {
Att,
Intel,
}

/// Inline assembly.
/// LLVM-style inline assembly.
///
/// E.g., `"={eax}"(result)` as in `asm!("mov eax, 2" : "={eax}"(result) : : : "intel")`.
/// E.g., `"={eax}"(result)` as in `llvm_asm!("mov eax, 2" : "={eax}"(result) : : : "intel")`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct InlineAsmOutput {
pub struct LlvmInlineAsmOutput {
pub constraint: Symbol,
pub expr: P<Expr>,
pub is_rw: bool,
pub is_indirect: bool,
}

/// Inline assembly.
/// LLVM-style inline assembly.
///
/// E.g., `asm!("NOP");`.
/// E.g., `llvm_asm!("NOP");`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct InlineAsm {
pub struct LlvmInlineAsm {
pub asm: Symbol,
pub asm_str_style: StrStyle,
pub outputs: Vec<InlineAsmOutput>,
pub outputs: Vec<LlvmInlineAsmOutput>,
pub inputs: Vec<(Symbol, P<Expr>)>,
pub clobbers: Vec<Symbol>,
pub volatile: bool,
pub alignstack: bool,
pub dialect: AsmDialect,
pub dialect: LlvmAsmDialect,
}

/// A parameter in a function header.
Expand Down
6 changes: 3 additions & 3 deletions src/librustc_ast/mut_visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1202,8 +1202,8 @@ pub fn noop_visit_expr<T: MutVisitor>(Expr { kind, id, span, attrs }: &mut Expr,
ExprKind::Ret(expr) => {
visit_opt(expr, |expr| vis.visit_expr(expr));
}
ExprKind::InlineAsm(asm) => {
let InlineAsm {
ExprKind::LlvmInlineAsm(asm) => {
let LlvmInlineAsm {
asm: _,
asm_str_style: _,
outputs,
Expand All @@ -1214,7 +1214,7 @@ pub fn noop_visit_expr<T: MutVisitor>(Expr { kind, id, span, attrs }: &mut Expr,
dialect: _,
} = asm.deref_mut();
for out in outputs {
let InlineAsmOutput { constraint: _, expr, is_rw: _, is_indirect: _ } = out;
let LlvmInlineAsmOutput { constraint: _, expr, is_rw: _, is_indirect: _ } = out;
vis.visit_expr(expr);
}
visit_vec(inputs, |(_c, expr)| vis.visit_expr(expr));
Expand Down
Loading

0 comments on commit 6c19a10

Please sign in to comment.