Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename asm! to llvm_asm! #68404

Merged
merged 2 commits into from
Mar 27, 2020
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
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