Stabilize asm! and global_asm!

They are also removed from the prelude as per the decision in
https://github.com/rust-lang/rust/issues/87228.

stdarch and compiler-builtins are updated to work with the new, stable
asm! and global_asm! macros.
This commit is contained in:
Amanieu d'Antras 2021-12-10 00:15:33 +00:00
parent b3a55371a7
commit 44a3a66ee8
123 changed files with 540 additions and 1636 deletions

View file

@ -680,9 +680,9 @@ dependencies = [
[[package]]
name = "compiler_builtins"
version = "0.1.55"
version = "0.1.65"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9ac60765140c97aaf531dae151a287646b0805ec725805da9e2a3ee31cd501c"
checksum = "ed37ea958309f2451e1cea7fd2b37aa56b1894c9a9fbdbbe6a194f7b78f0362d"
dependencies = [
"cc",
"rustc-std-workspace-core",

View file

@ -3,8 +3,6 @@
// Run-time:
// status: 0
#![feature(asm, global_asm)]
global_asm!("
.global add_asm
add_asm:

View file

@ -3147,7 +3147,8 @@ fn is_zero(expr: &hir::Expr<'_>) -> bool {
/// ### Example
///
/// ```rust,compile_fail
/// #![feature(asm)]
/// use std::arch::asm;
///
/// fn main() {
/// unsafe {
/// asm!("foo: bar");
@ -3164,10 +3165,7 @@ fn is_zero(expr: &hir::Expr<'_>) -> bool {
/// of this, GNU assembler [local labels] *must* be used instead of labels
/// with a name. Using named labels might cause assembler or linker errors.
///
/// See the [unstable book] for more details.
///
/// [local labels]: https://sourceware.org/binutils/docs/as/Symbol-Names.html#Local-Labels
/// [unstable book]: https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels
pub NAMED_ASM_LABELS,
Deny,
"named labels in inline assembly",

View file

@ -772,7 +772,7 @@ fn lookup_with_diagnostics(
}
BuiltinLintDiagnostics::NamedAsmLabel(help) => {
db.help(&help);
db.note("see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information");
//db.note("see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information");
}
}
// Rewrap `db`, and pass control to the user.

View file

@ -2419,8 +2419,8 @@
///
/// ### Example
///
/// ```rust,ignore (fails on system llvm)
/// #![feature(asm)]
/// ```rust
/// use std::arch::asm;
///
/// fn main() {
/// #[cfg(target_arch="x86_64")]
@ -2430,19 +2430,7 @@
/// }
/// ```
///
/// This will produce:
///
/// ```text
/// warning: formatting may not be suitable for sub-register argument
/// --> src/main.rs:6:19
/// |
/// 6 | asm!("mov {0}, {0}", in(reg) 0i16);
/// | ^^^ ^^^ ---- for this argument
/// |
/// = note: `#[warn(asm_sub_register)]` on by default
/// = help: use the `x` modifier to have the register formatted as `ax`
/// = help: or use the `r` modifier to keep the default formatting of `rax`
/// ```
/// {{produces}}
///
/// ### Explanation
///
@ -2455,10 +2443,6 @@
/// register size, to alert you of possibly using the incorrect width. To
/// fix this, add the suggested modifier to the template, or cast the
/// value to the correct size.
///
/// See [register template modifiers] for more details.
///
/// [register template modifiers]: https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#register-template-modifiers
pub ASM_SUB_REGISTER,
Warn,
"using only a subset of a register for inline asm inputs",
@ -2470,34 +2454,21 @@
///
/// ### Example
///
/// ```rust,ignore (fails on system llvm)
/// #![feature(asm)]
/// ```rust
/// use std::arch::asm;
///
/// fn main() {
/// #[cfg(target_arch="x86_64")]
/// unsafe {
/// asm!(
/// ".att_syntax",
/// "movl {0}, {0}", in(reg) 0usize
/// "movq %{0}, %{0}", in(reg) 0usize
/// );
/// }
/// }
/// ```
///
/// This will produce:
///
/// ```text
/// warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead
/// --> test.rs:7:14
/// |
/// 7 | ".att_syntax",
/// | ^^^^^^^^^^^
/// 8 | "movq {0}, {0}", out(reg) _,
/// 9 | );
/// | - help: add option: `, options(att_syntax)`
/// |
/// = note: `#[warn(bad_asm_style)]` on by default
/// ```
/// {{produces}}
///
/// ### Explanation
///
@ -2739,7 +2710,8 @@
///
/// ```rust
/// #![feature(naked_functions)]
/// #![feature(asm)]
///
/// use std::arch::asm;
///
/// #[naked]
/// pub fn default_abi() -> u32 {

View file

@ -152,7 +152,6 @@
#![feature(abi_unadjusted)]
#![feature(allow_internal_unsafe)]
#![feature(allow_internal_unstable)]
#![feature(asm)]
#![feature(associated_type_bounds)]
#![feature(auto_traits)]
#![feature(cfg_target_has_atomic)]
@ -372,26 +371,14 @@ pub mod arch {
pub use crate::core_arch::arch::*;
/// Inline assembly.
///
/// Read the [unstable book] for the usage.
///
/// [unstable book]: ../../unstable-book/library-features/asm.html
#[unstable(
feature = "asm",
issue = "72016",
reason = "inline assembly is not stable enough for use and is subject to change"
)]
#[stable(feature = "asm", since = "1.59.0")]
#[rustc_builtin_macro]
pub macro asm("assembly template", $(operands,)* $(options($(option),*))?) {
/* compiler built-in */
}
/// Module-level inline assembly.
#[unstable(
feature = "global_asm",
issue = "35119",
reason = "`global_asm!` is not stable enough for use and is subject to change"
)]
#[stable(feature = "global_asm", since = "1.59.0")]
#[rustc_builtin_macro]
pub macro global_asm("assembly template", $(operands,)* $(options($(option),*))?) {
/* compiler built-in */

View file

@ -10,6 +10,7 @@
// computations are performed in the desired precision.
#[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
mod fpu_precision {
use core::arch::asm;
use core::mem::size_of;
/// A structure used to preserve the original value of the FPU control word, so that it can be

View file

@ -69,22 +69,6 @@
#[doc(no_inline)]
pub use crate::concat_bytes;
#[unstable(
feature = "asm",
issue = "72016",
reason = "inline assembly is not stable enough for use and is subject to change"
)]
#[doc(no_inline)]
pub use crate::arch::asm;
#[unstable(
feature = "global_asm",
issue = "35119",
reason = "`global_asm!` is not stable enough for use and is subject to change"
)]
#[doc(no_inline)]
pub use crate::arch::global_asm;
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[allow(deprecated, deprecated_in_future)]
#[doc(no_inline)]

View file

@ -14,7 +14,6 @@
#![feature(std_internals)]
#![feature(staged_api)]
#![feature(rustc_attrs)]
#![feature(asm)]
#![feature(c_unwind)]
#[cfg(target_os = "android")]
@ -69,11 +68,11 @@ unsafe fn abort() -> ! {
const FAST_FAIL_FATAL_APP_EXIT: usize = 7;
cfg_if::cfg_if! {
if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
asm!("int $$0x29", in("ecx") FAST_FAIL_FATAL_APP_EXIT);
core::arch::asm!("int $$0x29", in("ecx") FAST_FAIL_FATAL_APP_EXIT);
} else if #[cfg(all(target_arch = "arm", target_feature = "thumb-mode"))] {
asm!(".inst 0xDEFB", in("r0") FAST_FAIL_FATAL_APP_EXIT);
core::arch::asm!(".inst 0xDEFB", in("r0") FAST_FAIL_FATAL_APP_EXIT);
} else if #[cfg(target_arch = "aarch64")] {
asm!("brk 0xF003", in("x0") FAST_FAIL_FATAL_APP_EXIT);
core::arch::asm!("brk 0xF003", in("x0") FAST_FAIL_FATAL_APP_EXIT);
} else {
core::intrinsics::abort();
}

View file

@ -16,7 +16,7 @@ panic_unwind = { path = "../panic_unwind", optional = true }
panic_abort = { path = "../panic_abort" }
core = { path = "../core" }
libc = { version = "0.2.108", default-features = false, features = ['rustc-dep-of-std'] }
compiler_builtins = { version = "0.1.55" }
compiler_builtins = { version = "0.1.65" }
profiler_builtins = { path = "../profiler_builtins", optional = true }
unwind = { path = "../unwind" }
hashbrown = { version = "0.11", default-features = false, features = ['rustc-dep-of-std'] }

View file

@ -233,7 +233,6 @@
#![feature(allow_internal_unstable)]
#![feature(arbitrary_self_types)]
#![feature(array_error_internals)]
#![feature(asm)]
#![feature(assert_matches)]
#![feature(associated_type_bounds)]
#![feature(async_stream)]
@ -288,7 +287,6 @@
#![feature(gen_future)]
#![feature(generator_trait)]
#![feature(get_mut_unchecked)]
#![feature(global_asm)]
#![feature(hashmap_internals)]
#![feature(int_error_internals)]
#![feature(integer_atomics)]

View file

@ -5,6 +5,7 @@
#![unstable(feature = "sgx_platform", issue = "56975")]
use crate::mem::MaybeUninit;
use core::arch::asm;
/// Wrapper struct to force 16-byte alignment.
#[repr(align(16))]

View file

@ -54,22 +54,6 @@
#[doc(no_inline)]
pub use core::prelude::v1::concat_bytes;
#[unstable(
feature = "asm",
issue = "72016",
reason = "inline assembly is not stable enough for use and is subject to change"
)]
#[doc(no_inline)]
pub use core::prelude::v1::asm;
#[unstable(
feature = "global_asm",
issue = "35119",
reason = "`global_asm!` is not stable enough for use and is subject to change"
)]
#[doc(no_inline)]
pub use core::prelude::v1::global_asm;
// FIXME: Attribute and internal derive macros are not documented because for them rustdoc generates
// dead links which fail link checker testing.
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]

View file

@ -1,3 +1,5 @@
use core::arch::asm;
// Do not remove inline: will result in relocation failure
#[inline(always)]
pub(crate) unsafe fn rel_ptr<T>(offset: u64) -> *const T {

View file

@ -1,6 +1,7 @@
#![cfg_attr(test, allow(unused))] // RT initialization logic is not compiled for test
use crate::io::Write;
use core::arch::global_asm;
use core::sync::atomic::{AtomicUsize, Ordering};
// runtime features

View file

@ -10,9 +10,9 @@ pub fn breakpoint_program_exited(tid: usize) {
match () {
// SOLID_BP_PROGRAM_EXITED = 15
#[cfg(target_arch = "arm")]
() => asm!("bkpt #15", in("r0") tid),
#[cfg(target_arch = "aarch64")]
() => asm!("hlt #15", in("x0") tid),
() => core::arch::asm!("bkpt #15", in("r0") tid),
#[cfg(core::arch::asm = "aarch64")]
() => core::arch::asm!("hlt #15", in("x0") tid),
}
}
}
@ -23,9 +23,9 @@ pub fn breakpoint_abort() {
match () {
// SOLID_BP_CSABORT = 16
#[cfg(target_arch = "arm")]
() => asm!("bkpt #16"),
() => core::arch::asm!("bkpt #16"),
#[cfg(target_arch = "aarch64")]
() => asm!("hlt #16"),
() => core::arch::asm!("hlt #16"),
}
}
}

View file

@ -288,13 +288,13 @@ pub fn abort_internal() -> ! {
unsafe {
cfg_if::cfg_if! {
if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
asm!("int $$0x29", in("ecx") FAST_FAIL_FATAL_APP_EXIT);
core::arch::asm!("int $$0x29", in("ecx") FAST_FAIL_FATAL_APP_EXIT);
crate::intrinsics::unreachable();
} else if #[cfg(all(target_arch = "arm", target_feature = "thumb-mode"))] {
asm!(".inst 0xDEFB", in("r0") FAST_FAIL_FATAL_APP_EXIT);
core::arch::asm!(".inst 0xDEFB", in("r0") FAST_FAIL_FATAL_APP_EXIT);
crate::intrinsics::unreachable();
} else if #[cfg(target_arch = "aarch64")] {
asm!("brk 0xF003", in("x0") FAST_FAIL_FATAL_APP_EXIT);
core::arch::asm!("brk 0xF003", in("x0") FAST_FAIL_FATAL_APP_EXIT);
crate::intrinsics::unreachable();
}
}

@ -1 +1 @@
Subproject commit b70ae88ef2a6c83acad0a1e83d5bd78f9655fd05
Subproject commit d219ad63c5075098fc224a57deb4852b9734327d

View file

@ -199,7 +199,7 @@ LLVM CFI can be enabled with -Zsanitizer=cfi and requires LTO (i.e., -Clto).
## Example
```text
#![feature(asm, naked_functions)]
#![feature(naked_functions)]
use std::mem;

View file

@ -1,910 +0,0 @@
# `asm`
The tracking issue for this feature is: [#72016]
[#72016]: https://github.com/rust-lang/rust/issues/72016
------------------------
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.
# Guide-level explanation
[guide-level-explanation]: #guide-level-explanation
Rust provides support for inline assembly via the `asm!` macro.
It can be used to embed handwritten assembly in the assembly output generated by the compiler.
Generally this should not be necessary, but might be where the required performance or timing
cannot be otherwise achieved. Accessing low level hardware primitives, e.g. in kernel code, may also demand this functionality.
> **Note**: the examples here are given in x86/x86-64 assembly, but other architectures are also supported.
Inline assembly is currently supported on the following architectures:
- x86 and x86-64
- ARM
- AArch64
- RISC-V
- NVPTX
- PowerPC
- Hexagon
- MIPS32r2 and MIPS64r2
- wasm32
- BPF
- SPIR-V
- AVR
## Basic usage
Let us start with the simplest possible example:
```rust,allow_fail
#![feature(asm)]
unsafe {
asm!("nop");
}
```
This will insert a NOP (no operation) instruction into the assembly generated by the compiler.
Note that all `asm!` invocations have to be inside an `unsafe` block, as they could insert
arbitrary instructions and break various invariants. The instructions to be inserted are listed
in the first argument of the `asm!` macro as a string literal.
## Inputs and outputs
Now inserting an instruction that does nothing is rather boring. Let us do something that
actually acts on data:
```rust,allow_fail
#![feature(asm)]
let x: u64;
unsafe {
asm!("mov {}, 5", out(reg) x);
}
assert_eq!(x, 5);
```
This will write the value `5` into the `u64` variable `x`.
You can see that the string literal we use to specify instructions is actually a template string.
It is governed by the same rules as Rust [format strings][format-syntax].
The arguments that are inserted into the template however look a bit different than you may
be familiar with. First we need to specify if the variable is an input or an output of the
inline assembly. In this case it is an output. We declared this by writing `out`.
We also need to specify in what kind of register the assembly expects the variable.
In this case we put it in an arbitrary general purpose register by specifying `reg`.
The compiler will choose an appropriate register to insert into
the template and will read the variable from there after the inline assembly finishes executing.
Let us see another example that also uses an input:
```rust,allow_fail
#![feature(asm)]
let i: u64 = 3;
let o: u64;
unsafe {
asm!(
"mov {0}, {1}",
"add {0}, {number}",
out(reg) o,
in(reg) i,
number = const 5,
);
}
assert_eq!(o, 8);
```
This will add `5` to the input in variable `i` and write the result to variable `o`.
The particular way this assembly does this is first copying the value from `i` to the output,
and then adding `5` to it.
The example shows a few things:
First, we can see that `asm!` allows multiple template string arguments; each
one is treated as a separate line of assembly code, as if they were all joined
together with newlines between them. This makes it easy to format assembly
code.
Second, we can see that inputs are declared by writing `in` instead of `out`.
Third, one of our operands has a type we haven't seen yet, `const`.
This tells the compiler to expand this argument to a value directly inside the assembly template.
This is only possible for constants and literals.
Fourth, we can see that we can specify an argument number, or name as in any format string.
For inline assembly templates this is particularly useful as arguments are often used more than once.
For more complex inline assembly using this facility is generally recommended, as it improves
readability, and allows reordering instructions without changing the argument order.
We can further refine the above example to avoid the `mov` instruction:
```rust,allow_fail
#![feature(asm)]
let mut x: u64 = 3;
unsafe {
asm!("add {0}, {number}", inout(reg) x, number = const 5);
}
assert_eq!(x, 8);
```
We can see that `inout` is used to specify an argument that is both input and output.
This is different from specifying an input and output separately in that it is guaranteed to assign both to the same register.
It is also possible to specify different variables for the input and output parts of an `inout` operand:
```rust,allow_fail
#![feature(asm)]
let x: u64 = 3;
let y: u64;
unsafe {
asm!("add {0}, {number}", inout(reg) x => y, number = const 5);
}
assert_eq!(y, 8);
```
## Late output operands
The Rust compiler is conservative with its allocation of operands. It is assumed that an `out`
can be written at any time, and can therefore not share its location with any other argument.
However, to guarantee optimal performance it is important to use as few registers as possible,
so they won't have to be saved and reloaded around the inline assembly block.
To achieve this Rust provides a `lateout` specifier. This can be used on any output that is
written only after all inputs have been consumed.
There is also a `inlateout` variant of this specifier.
Here is an example where `inlateout` *cannot* be used:
```rust,allow_fail
#![feature(asm)]
let mut a: u64 = 4;
let b: u64 = 4;
let c: u64 = 4;
unsafe {
asm!(
"add {0}, {1}",
"add {0}, {2}",
inout(reg) a,
in(reg) b,
in(reg) c,
);
}
assert_eq!(a, 12);
```
Here the compiler is free to allocate the same register for inputs `b` and `c` since it knows they have the same value. However it must allocate a separate register for `a` since it uses `inout` and not `inlateout`. If `inlateout` was used, then `a` and `c` could be allocated to the same register, in which case the first instruction to overwrite the value of `c` and cause the assembly code to produce the wrong result.
However the following example can use `inlateout` since the output is only modified after all input registers have been read:
```rust,allow_fail
#![feature(asm)]
let mut a: u64 = 4;
let b: u64 = 4;
unsafe {
asm!("add {0}, {1}", inlateout(reg) a, in(reg) b);
}
assert_eq!(a, 8);
```
As you can see, this assembly fragment will still work correctly if `a` and `b` are assigned to the same register.
## Explicit register operands
Some instructions require that the operands be in a specific register.
Therefore, Rust inline assembly provides some more specific constraint specifiers.
While `reg` is generally available on any architecture, explicit registers are highly architecture specific. E.g. for x86 the general purpose registers `eax`, `ebx`, `ecx`, `edx`, `ebp`, `esi`, and `edi` among others can be addressed by their name.
```rust,allow_fail,no_run
#![feature(asm)]
let cmd = 0xd1;
unsafe {
asm!("out 0x64, eax", in("eax") cmd);
}
```
In this example we call the `out` instruction to output the content of the `cmd` variable to port `0x64`. Since the `out` instruction only accepts `eax` (and its sub registers) as operand we had to use the `eax` constraint specifier.
> **Note**: unlike other operand types, explicit register operands cannot be used in the template string: you can't use `{}` and should write the register name directly instead. Also, they must appear at the end of the operand list after all other operand types.
Consider this example which uses the x86 `mul` instruction:
```rust,allow_fail
#![feature(asm)]
fn mul(a: u64, b: u64) -> u128 {
let lo: u64;
let hi: u64;
unsafe {
asm!(
// The x86 mul instruction takes rax as an implicit input and writes
// the 128-bit result of the multiplication to rax:rdx.
"mul {}",
in(reg) a,
inlateout("rax") b => lo,
lateout("rdx") hi
);
}
((hi as u128) << 64) + lo as u128
}
```
This uses the `mul` instruction to multiply two 64-bit inputs with a 128-bit result.
The only explicit operand is a register, that we fill from the variable `a`.
The second operand is implicit, and must be the `rax` register, which we fill from the variable `b`.
The lower 64 bits of the result are stored in `rax` from which we fill the variable `lo`.
The higher 64 bits are stored in `rdx` from which we fill the variable `hi`.
## Clobbered registers
In many cases inline assembly will modify state that is not needed as an output.
Usually this is either because we have to use a scratch register in the assembly or because instructions modify state that we don't need to further examine.
This state is generally referred to as being "clobbered".
We need to tell the compiler about this since it may need to save and restore this state around the inline assembly block.
```rust,allow_fail
#![feature(asm)]
let ebx: u32;
let ecx: u32;
unsafe {
asm!(
"cpuid",
// EAX 4 selects the "Deterministic Cache Parameters" CPUID leaf
inout("eax") 4 => _,
// ECX 0 selects the L0 cache information.
inout("ecx") 0 => ecx,
lateout("ebx") ebx,
lateout("edx") _,
);
}
println!(
"L0 Cache: {}",
((ebx >> 22) + 1) * (((ebx >> 12) & 0x3ff) + 1) * ((ebx & 0xfff) + 1) * (ecx + 1)
);
```
In the example above we use the `cpuid` instruction to get the L1 cache size.
This instruction writes to `eax`, `ebx`, `ecx`, and `edx`, but for the cache size we only care about the contents of `ebx` and `ecx`.
However we still need to tell the compiler that `eax` and `edx` have been modified so that it can save any values that were in these registers before the asm. This is done by declaring these as outputs but with `_` instead of a variable name, which indicates that the output value is to be discarded.
This can also be used with a general register class (e.g. `reg`) to obtain a scratch register for use inside the asm code:
```rust,allow_fail
#![feature(asm)]
// Multiply x by 6 using shifts and adds
let mut x: u64 = 4;
unsafe {
asm!(
"mov {tmp}, {x}",
"shl {tmp}, 1",
"shl {x}, 2",
"add {x}, {tmp}",
x = inout(reg) x,
tmp = out(reg) _,
);
}
assert_eq!(x, 4 * 6);
```
## Symbol operands and ABI clobbers
A special operand type, `sym`, allows you to use the symbol name of a `fn` or `static` in inline assembly code.
This allows you to call a function or access a global variable without needing to keep its address in a register.
```rust,allow_fail
#![feature(asm)]
extern "C" fn foo(arg: i32) -> i32 {
println!("arg = {}", arg);
arg * 2
}
fn call_foo(arg: i32) -> i32 {
unsafe {
let result;
asm!(
"call {}",
sym foo,
// 1st argument in rdi
in("rdi") arg,
// Return value in rax
out("rax") result,
// Mark all registers which are not preserved by the "C" calling
// convention as clobbered.
clobber_abi("C"),
);
result
}
}
```
Note that the `fn` or `static` item does not need to be public or `#[no_mangle]`: the compiler will automatically insert the appropriate mangled symbol name into the assembly code.
By default, `asm!` assumes that any register not specified as an output will have its contents preserved by the assembly code. The [`clobber_abi`](#abi-clobbers) argument to `asm!` tells the compiler to automatically insert the necessary clobber operands according to the given calling convention ABI: any register which is not fully preserved in that ABI will be treated as clobbered. Multiple `clobber_abi` arguments may be provided and all clobbers from all specified ABIs will be inserted.
## Register template modifiers
In some cases, fine control is needed over the way a register name is formatted when inserted into the template string. This is needed when an architecture's assembly language has several names for the same register, each typically being a "view" over a subset of the register (e.g. the low 32 bits of a 64-bit register).
By default the compiler will always choose the name that refers to the full register size (e.g. `rax` on x86-64, `eax` on x86, etc).
This default can be overriden by using modifiers on the template string operands, just like you would with format strings:
```rust,allow_fail
#![feature(asm)]
let mut x: u16 = 0xab;
unsafe {
asm!("mov {0:h}, {0:l}", inout(reg_abcd) x);
}
assert_eq!(x, 0xabab);
```
In this example, we use the `reg_abcd` register class to restrict the register allocator to the 4 legacy x86 register (`ax`, `bx`, `cx`, `dx`) of which the first two bytes can be addressed independently.
Let us assume that the register allocator has chosen to allocate `x` in the `ax` register.
The `h` modifier will emit the register name for the high byte of that register and the `l` modifier will emit the register name for the low byte. The asm code will therefore be expanded as `mov ah, al` which copies the low byte of the value into the high byte.
If you use a smaller data type (e.g. `u16`) with an operand and forget the use template modifiers, the compiler will emit a warning and suggest the correct modifier to use.
## Memory address operands
Sometimes assembly instructions require operands passed via memory addresses/memory locations.
You have to manually use the memory address syntax specified by the target architecture.
For example, on x86/x86_64 using intel assembly syntax, you should wrap inputs/outputs in `[]` to indicate they are memory operands:
```rust,allow_fail
#![feature(asm, llvm_asm)]
# fn load_fpu_control_word(control: u16) {
unsafe {
asm!("fldcw [{}]", in(reg) &control, options(nostack));
// Previously this would have been written with the deprecated `llvm_asm!` like this
llvm_asm!("fldcw $0" :: "m" (control) :: "volatile");
}
# }
```
## Labels
Any reuse of a named label, local or otherwise, can result in a assembler or linker error or may cause other strange behavior. Reuse of a named label can happen in a variety of ways including:
- explicitly: using a label more than once in one `asm!` block, or multiple times across blocks
- implicitly via inlining: the compiler is allowed to instantiate multiple copies of an `asm!` block, for example when the function containing it is inlined in multiple places.
- implicitly via LTO: LTO can cause code from *other crates* to be placed in the same codegen unit, and so could bring in arbitrary labels
As a consequence, you should only use GNU assembler **numeric** [local labels] inside inline assembly code. Defining symbols in assembly code may lead to assembler and/or linker errors due to duplicate symbol definitions.
Moreover, on x86 when using the default intel syntax, due to [an llvm bug], you shouldn't use labels exclusively made of `0` and `1` digits, e.g. `0`, `11` or `101010`, as they may end up being interpreted as binary values. Using `options(att_syntax)` will avoid any ambiguity, but that affects the syntax of the _entire_ `asm!` block.
```rust,allow_fail
#![feature(asm)]
let mut a = 0;
unsafe {
asm!(
"mov {0}, 10",
"2:",
"sub {0}, 1",
"cmp {0}, 3",
"jle 2f",
"jmp 2b",
"2:",
"add {0}, 2",
out(reg) a
);
}
assert_eq!(a, 5);
```
This will decrement the `{0}` register value from 10 to 3, then add 2 and store it in `a`.
This example shows a few things:
First that the same number can be used as a label multiple times in the same inline block.
Second, that when a numeric label is used as a reference (as an instruction operand, for example), the suffixes b (“backward”) or f (“forward”) should be added to the numeric label. It will then refer to the nearest label defined by this number in this direction.
[local labels]: https://sourceware.org/binutils/docs/as/Symbol-Names.html#Local-Labels
[an llvm bug]: https://bugs.llvm.org/show_bug.cgi?id=36144
## Options
By default, an inline assembly block is treated the same way as an external FFI function call with a custom calling convention: it may read/write memory, have observable side effects, etc. However, in many cases it is desirable to give the compiler more information about what the assembly code is actually doing so that it can optimize better.
Let's take our previous example of an `add` instruction:
```rust,allow_fail
#![feature(asm)]
let mut a: u64 = 4;
let b: u64 = 4;
unsafe {
asm!(
"add {0}, {1}",
inlateout(reg) a, in(reg) b,
options(pure, nomem, nostack),
);
}
assert_eq!(a, 8);
```
Options can be provided as an optional final argument to the `asm!` macro. We specified three options here:
- `pure` means that the asm code has no observable side effects and that its output depends only on its inputs. This allows the compiler optimizer to call the inline asm fewer times or even eliminate it entirely.
- `nomem` means that the asm code does not read or write to memory. By default the compiler will assume that inline assembly can read or write any memory address that is accessible to it (e.g. through a pointer passed as an operand, or a global).
- `nostack` means that the asm code does not push any data onto the stack. This allows the compiler to use optimizations such as the stack red zone on x86-64 to avoid stack pointer adjustments.
These allow the compiler to better optimize code using `asm!`, for example by eliminating pure `asm!` blocks whose outputs are not needed.
See the reference for the full list of available options and their effects.
# Reference-level explanation
[reference-level-explanation]: #reference-level-explanation
Inline assembler is implemented as an unsafe macro `asm!()`.
The first argument to this macro is a template string literal used to build the final assembly.
The following arguments specify input and output operands.
When required, options are specified as the final argument.
The following ABNF specifies the general syntax:
```text
dir_spec := "in" / "out" / "lateout" / "inout" / "inlateout"
reg_spec := <register class> / "<explicit register>"
operand_expr := expr / "_" / expr "=>" expr / expr "=>" "_"
reg_operand := dir_spec "(" reg_spec ")" operand_expr
operand := reg_operand / "const" const_expr / "sym" path
clobber_abi := "clobber_abi(" <abi> *["," <abi>] [","] ")"
option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn" / "nostack" / "att_syntax" / "raw" / "may_unwind"
options := "options(" option *["," option] [","] ")"
asm := "asm!(" format_string *("," format_string) *("," [ident "="] operand) *("," clobber_abi) *("," options) [","] ")"
```
Inline assembly is currently supported on the following architectures:
- x86 and x86-64
- ARM
- AArch64
- RISC-V
- NVPTX
- PowerPC
- Hexagon
- MIPS32r2 and MIPS64r2
- wasm32
- BPF
- SPIR-V
- AVR
Support for more targets may be added in the future. The compiler will emit an error if `asm!` is used on an unsupported target.
[format-syntax]: https://doc.rust-lang.org/std/fmt/#syntax
## Template string arguments
The assembler template uses the same syntax as [format strings][format-syntax] (i.e. placeholders are specified by curly braces). The corresponding arguments are accessed in order, by index, or by name. However, implicit named arguments (introduced by [RFC #2795][rfc-2795]) are not supported.
An `asm!` invocation may have one or more template string arguments; an `asm!` with multiple template string arguments is treated as if all the strings were concatenated with a `\n` between them. The expected usage is for each template string argument to correspond to a line of assembly code. All template string arguments must appear before any other arguments.
As with format strings, named arguments must appear after positional arguments. Explicit register operands must appear at the end of the operand list, after named arguments if any.
Explicit register operands cannot be used by placeholders in the template string. All other named and positional operands must appear at least once in the template string, otherwise a compiler error is generated.
The exact assembly code syntax is target-specific and opaque to the compiler except for the way operands are substituted into the template string to form the code passed to the assembler.
The 5 targets specified in this RFC (x86, ARM, AArch64, RISC-V, Hexagon) all use the assembly code syntax of the GNU assembler (GAS). On x86, the `.intel_syntax noprefix` mode of GAS is used by default. On ARM, the `.syntax unified` mode is used. These targets impose an additional restriction on the assembly code: any assembler state (e.g. the current section which can be changed with `.section`) must be restored to its original value at the end of the asm string. Assembly code that does not conform to the GAS syntax will result in assembler-specific behavior.
[rfc-2795]: https://github.com/rust-lang/rfcs/pull/2795
## Operand type
Several types of operands are supported:
* `in(<reg>) <expr>`
- `<reg>` can refer to a register class or an explicit register. The allocated register name is substituted into the asm template string.
- The allocated register will contain the value of `<expr>` at the start of the asm code.
- The allocated register must contain the same value at the end of the asm code (except if a `lateout` is allocated to the same register).
* `out(<reg>) <expr>`
- `<reg>` can refer to a register class or an explicit register. The allocated register name is substituted into the asm template string.
- The allocated register will contain an undefined value at the start of the asm code.
- `<expr>` must be a (possibly uninitialized) place expression, to which the contents of the allocated register is written to at the end of the asm code.
- An underscore (`_`) may be specified instead of an expression, which will cause the contents of the register to be discarded at the end of the asm code (effectively acting as a clobber).
* `lateout(<reg>) <expr>`
- Identical to `out` except that the register allocator can reuse a register allocated to an `in`.
- You should only write to the register after all inputs are read, otherwise you may clobber an input.
* `inout(<reg>) <expr>`
- `<reg>` can refer to a register class or an explicit register. The allocated register name is substituted into the asm template string.
- The allocated register will contain the value of `<expr>` at the start of the asm code.
- `<expr>` must be a mutable initialized place expression, to which the contents of the allocated register is written to at the end of the asm code.
* `inout(<reg>) <in expr> => <out expr>`
- Same as `inout` except that the initial value of the register is taken from the value of `<in expr>`.
- `<out expr>` must be a (possibly uninitialized) place expression, to which the contents of the allocated register is written to at the end of the asm code.
- An underscore (`_`) may be specified instead of an expression for `<out expr>`, which will cause the contents of the register to be discarded at the end of the asm code (effectively acting as a clobber).
- `<in expr>` and `<out expr>` may have different types.
* `inlateout(<reg>) <expr>` / `inlateout(<reg>) <in expr> => <out expr>`
- Identical to `inout` except that the register allocator can reuse a register allocated to an `in` (this can happen if the compiler knows the `in` has the same initial value as the `inlateout`).
- You should only write to the register after all inputs are read, otherwise you may clobber an input.
* `const <expr>`
- `<expr>` must be an integer constant expression.
- The value of the expression is formatted as a string and substituted directly into the asm template string.
* `sym <path>`
- `<path>` must refer to a `fn` or `static`.
- A mangled symbol name referring to the item is substituted into the asm template string.
- The substituted string does not include any modifiers (e.g. GOT, PLT, relocations, etc).
- `<path>` is allowed to point to a `#[thread_local]` static, in which case the asm code can combine the symbol with relocations (e.g. `@plt`, `@TPOFF`) to read from thread-local data.
Operand expressions are evaluated from left to right, just like function call arguments. After the `asm!` has executed, outputs are written to in left to right order. This is significant if two outputs point to the same place: that place will contain the value of the rightmost output.
## Register operands
Input and output operands can be specified either as an explicit register or as a register class from which the register allocator can select a register. Explicit registers are specified as string literals (e.g. `"eax"`) while register classes are specified as identifiers (e.g. `reg`). Using string literals for register names enables support for architectures that use special characters in register names, such as MIPS (`$0`, `$1`, etc).
Note that explicit registers treat register aliases (e.g. `r14` vs `lr` on ARM) and smaller views of a register (e.g. `eax` vs `rax`) as equivalent to the base register. It is a compile-time error to use the same explicit register for two input operands or two output operands. Additionally, it is also a compile-time error to use overlapping registers (e.g. ARM VFP) in input operands or in output operands.
Only the following types are allowed as operands for inline assembly:
- Integers (signed and unsigned)
- Floating-point numbers
- Pointers (thin only)
- Function pointers
- SIMD vectors (structs defined with `#[repr(simd)]` and which implement `Copy`). This includes architecture-specific vector types defined in `std::arch` such as `__m128` (x86) or `int8x16_t` (ARM).
Here is the list of currently supported register classes:
| Architecture | Register class | Registers | LLVM constraint code |
| ------------ | -------------- | --------- | -------------------- |
| x86 | `reg` | `ax`, `bx`, `cx`, `dx`, `si`, `di`, `bp`, `r[8-15]` (x86-64 only) | `r` |
| x86 | `reg_abcd` | `ax`, `bx`, `cx`, `dx` | `Q` |
| x86-32 | `reg_byte` | `al`, `bl`, `cl`, `dl`, `ah`, `bh`, `ch`, `dh` | `q` |
| x86-64 | `reg_byte`\* | `al`, `bl`, `cl`, `dl`, `sil`, `dil`, `bpl`, `r[8-15]b` | `q` |
| x86 | `xmm_reg` | `xmm[0-7]` (x86) `xmm[0-15]` (x86-64) | `x` |
| x86 | `ymm_reg` | `ymm[0-7]` (x86) `ymm[0-15]` (x86-64) | `x` |
| x86 | `zmm_reg` | `zmm[0-7]` (x86) `zmm[0-31]` (x86-64) | `v` |
| x86 | `kreg` | `k[1-7]` | `Yk` |
| x86 | `x87_reg` | `st([0-7])` | Only clobbers |
| x86 | `mmx_reg` | `mm[0-7]` | Only clobbers |
| AArch64 | `reg` | `x[0-30]` | `r` |
| AArch64 | `vreg` | `v[0-31]` | `w` |
| AArch64 | `vreg_low16` | `v[0-15]` | `x` |
| AArch64 | `preg` | `p[0-15]`, `ffr` | Only clobbers |
| ARM (ARM/Thumb2) | `reg` | `r[0-12]`, `r14` | `r` |
| ARM (Thumb1) | `reg` | `r[0-7]` | `r` |
| ARM | `sreg` | `s[0-31]` | `t` |
| ARM | `sreg_low16` | `s[0-15]` | `x` |
| ARM | `dreg` | `d[0-31]` | `w` |
| ARM | `dreg_low16` | `d[0-15]` | `t` |
| ARM | `dreg_low8` | `d[0-8]` | `x` |
| ARM | `qreg` | `q[0-15]` | `w` |
| ARM | `qreg_low8` | `q[0-7]` | `t` |
| ARM | `qreg_low4` | `q[0-3]` | `x` |
| MIPS | `reg` | `$[2-25]` | `r` |
| MIPS | `freg` | `$f[0-31]` | `f` |
| NVPTX | `reg16` | None\* | `h` |
| NVPTX | `reg32` | None\* | `r` |
| NVPTX | `reg64` | None\* | `l` |
| RISC-V | `reg` | `x1`, `x[5-7]`, `x[9-15]`, `x[16-31]` (non-RV32E) | `r` |
| RISC-V | `freg` | `f[0-31]` | `f` |
| RISC-V | `vreg` | `v[0-31]` | Only clobbers |
| Hexagon | `reg` | `r[0-28]` | `r` |
| PowerPC | `reg` | `r[0-31]` | `r` |
| PowerPC | `reg_nonzero` | | `r[1-31]` | `b` |
| PowerPC | `freg` | `f[0-31]` | `f` |
| PowerPC | `cr` | `cr[0-7]`, `cr` | Only clobbers |
| PowerPC | `xer` | `xer` | Only clobbers |
| wasm32 | `local` | None\* | `r` |
| BPF | `reg` | `r[0-10]` | `r` |
| BPF | `wreg` | `w[0-10]` | `w` |
| AVR | `reg` | `r[2-25]`, `XH`, `XL`, `ZH`, `ZL` | `r` |
| AVR | `reg_upper` | `r[16-25]`, `XH`, `XL`, `ZH`, `ZL` | `d` |
| AVR | `reg_pair` | `r3r2` .. `r25r24`, `X`, `Z` | `r` |
| AVR | `reg_iw` | `r25r24`, `X`, `Z` | `w` |
| AVR | `reg_ptr` | `X`, `Z` | `e` |
> **Note**: On x86 we treat `reg_byte` differently from `reg` because the compiler can allocate `al` and `ah` separately whereas `reg` reserves the whole register.
>
> Note #2: On x86-64 the high byte registers (e.g. `ah`) are not available in the `reg_byte` register class.
>
> Note #3: NVPTX doesn't have a fixed register set, so named registers are not supported.
>
> Note #4: WebAssembly doesn't have registers, so named registers are not supported.
>
> Note #5: Some register classes are marked as "Only clobbers" which means that they cannot be used for inputs or outputs, only clobbers of the form `out("reg") _` or `lateout("reg") _`.
Additional register classes may be added in the future based on demand (e.g. MMX, x87, etc).
Each register class has constraints on which value types they can be used with. This is necessary because the way a value is loaded into a register depends on its type. For example, on big-endian systems, loading a `i32x4` and a `i8x16` into a SIMD register may result in different register contents even if the byte-wise memory representation of both values is identical. The availability of supported types for a particular register class may depend on what target features are currently enabled.
| Architecture | Register class | Target feature | Allowed types |
| ------------ | -------------- | -------------- | ------------- |
| x86-32 | `reg` | None | `i16`, `i32`, `f32` |
| x86-64 | `reg` | None | `i16`, `i32`, `f32`, `i64`, `f64` |
| x86 | `reg_byte` | None | `i8` |
| x86 | `xmm_reg` | `sse` | `i32`, `f32`, `i64`, `f64`, <br> `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` |
| x86 | `ymm_reg` | `avx` | `i32`, `f32`, `i64`, `f64`, <br> `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` <br> `i8x32`, `i16x16`, `i32x8`, `i64x4`, `f32x8`, `f64x4` |
| x86 | `zmm_reg` | `avx512f` | `i32`, `f32`, `i64`, `f64`, <br> `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` <br> `i8x32`, `i16x16`, `i32x8`, `i64x4`, `f32x8`, `f64x4` <br> `i8x64`, `i16x32`, `i32x16`, `i64x8`, `f32x16`, `f64x8` |
| x86 | `kreg` | `avx512f` | `i8`, `i16` |
| x86 | `kreg` | `avx512bw` | `i32`, `i64` |
| x86 | `mmx_reg` | N/A | Only clobbers |
| x86 | `x87_reg` | N/A | Only clobbers |
| AArch64 | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` |
| AArch64 | `vreg` | `fp` | `i8`, `i16`, `i32`, `f32`, `i64`, `f64`, <br> `i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2`, `f64x1`, <br> `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4`, `f64x2` |
| AArch64 | `preg` | N/A | Only clobbers |
| ARM | `reg` | None | `i8`, `i16`, `i32`, `f32` |
| ARM | `sreg` | `vfp2` | `i32`, `f32` |
| ARM | `dreg` | `vfp2` | `i64`, `f64`, `i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2` |
| ARM | `qreg` | `neon` | `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4` |
| MIPS32 | `reg` | None | `i8`, `i16`, `i32`, `f32` |
| MIPS32 | `freg` | None | `f32`, `f64` |
| MIPS64 | `reg` | None | `i8`, `i16`, `i32`, `i64`, `f32`, `f64` |
| MIPS64 | `freg` | None | `f32`, `f64` |
| NVPTX | `reg16` | None | `i8`, `i16` |
| NVPTX | `reg32` | None | `i8`, `i16`, `i32`, `f32` |
| NVPTX | `reg64` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` |
| RISC-V32 | `reg` | None | `i8`, `i16`, `i32`, `f32` |
| RISC-V64 | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` |
| RISC-V | `freg` | `f` | `f32` |
| RISC-V | `freg` | `d` | `f64` |
| RISC-V | `vreg` | N/A | Only clobbers |
| Hexagon | `reg` | None | `i8`, `i16`, `i32`, `f32` |
| PowerPC | `reg` | None | `i8`, `i16`, `i32` |
| PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32` |
| PowerPC | `freg` | None | `f32`, `f64` |
| PowerPC | `cr` | N/A | Only clobbers |
| PowerPC | `xer` | N/A | Only clobbers |
| wasm32 | `local` | None | `i8` `i16` `i32` `i64` `f32` `f64` |
| BPF | `reg` | None | `i8` `i16` `i32` `i64` |
| BPF | `wreg` | `alu32` | `i8` `i16` `i32` |
| AVR | `reg`, `reg_upper` | None | `i8` |
| AVR | `reg_pair`, `reg_iw`, `reg_ptr` | None | `i16` |
> **Note**: For the purposes of the above table pointers, function pointers and `isize`/`usize` are treated as the equivalent integer type (`i16`/`i32`/`i64` depending on the target).
If a value is of a smaller size than the register it is allocated in then the upper bits of that register will have an undefined value for inputs and will be ignored for outputs. The only exception is the `freg` register class on RISC-V where `f32` values are NaN-boxed in a `f64` as required by the RISC-V architecture.
When separate input and output expressions are specified for an `inout` operand, both expressions must have the same type. The only exception is if both operands are pointers or integers, in which case they are only required to have the same size. This restriction exists because the register allocators in LLVM and GCC sometimes cannot handle tied operands with different types.
## Register names
Some registers have multiple names. These are all treated by the compiler as identical to the base register name. Here is the list of all supported register aliases:
| Architecture | Base register | Aliases |
| ------------ | ------------- | ------- |
| x86 | `ax` | `eax`, `rax` |
| x86 | `bx` | `ebx`, `rbx` |
| x86 | `cx` | `ecx`, `rcx` |
| x86 | `dx` | `edx`, `rdx` |
| x86 | `si` | `esi`, `rsi` |
| x86 | `di` | `edi`, `rdi` |
| x86 | `bp` | `bpl`, `ebp`, `rbp` |
| x86 | `sp` | `spl`, `esp`, `rsp` |
| x86 | `ip` | `eip`, `rip` |
| x86 | `st(0)` | `st` |
| x86 | `r[8-15]` | `r[8-15]b`, `r[8-15]w`, `r[8-15]d` |
| x86 | `xmm[0-31]` | `ymm[0-31]`, `zmm[0-31]` |
| AArch64 | `x[0-30]` | `w[0-30]` |
| AArch64 | `x29` | `fp` |
| AArch64 | `x30` | `lr` |
| AArch64 | `sp` | `wsp` |
| AArch64 | `xzr` | `wzr` |
| AArch64 | `v[0-31]` | `b[0-31]`, `h[0-31]`, `s[0-31]`, `d[0-31]`, `q[0-31]` |
| ARM | `r[0-3]` | `a[1-4]` |
| ARM | `r[4-9]` | `v[1-6]` |
| ARM | `r9` | `rfp` |
| ARM | `r10` | `sl` |
| ARM | `r11` | `fp` |
| ARM | `r12` | `ip` |
| ARM | `r13` | `sp` |
| ARM | `r14` | `lr` |
| ARM | `r15` | `pc` |
| RISC-V | `x0` | `zero` |
| RISC-V | `x1` | `ra` |
| RISC-V | `x2` | `sp` |
| RISC-V | `x3` | `gp` |
| RISC-V | `x4` | `tp` |
| RISC-V | `x[5-7]` | `t[0-2]` |
| RISC-V | `x8` | `fp`, `s0` |
| RISC-V | `x9` | `s1` |
| RISC-V | `x[10-17]` | `a[0-7]` |
| RISC-V | `x[18-27]` | `s[2-11]` |
| RISC-V | `x[28-31]` | `t[3-6]` |
| RISC-V | `f[0-7]` | `ft[0-7]` |
| RISC-V | `f[8-9]` | `fs[0-1]` |
| RISC-V | `f[10-17]` | `fa[0-7]` |
| RISC-V | `f[18-27]` | `fs[2-11]` |
| RISC-V | `f[28-31]` | `ft[8-11]` |
| Hexagon | `r29` | `sp` |
| Hexagon | `r30` | `fr` |
| Hexagon | `r31` | `lr` |
| BPF | `r[0-10]` | `w[0-10]` |
| AVR | `XH` | `r27` |
| AVR | `XL` | `r26` |
| AVR | `ZH` | `r31` |
| AVR | `ZL` | `r30` |
Some registers cannot be used for input or output operands:
| Architecture | Unsupported register | Reason |
| ------------ | -------------------- | ------ |
| All | `sp` | The stack pointer must be restored to its original value at the end of an asm code block. |
| All | `bp` (x86), `x29` (AArch64), `x8` (RISC-V), `fr` (Hexagon), `$fp` (MIPS), `Y` (AVR) | The frame pointer cannot be used as an input or output. |
| ARM | `r7` or `r11` | On ARM the frame pointer can be either `r7` or `r11` depending on the target. The frame pointer cannot be used as an input or output. |
| All | `si` (x86-32), `bx` (x86-64), `r6` (ARM), `x19` (AArch64), `r19` (Hexagon), `x9` (RISC-V) | This is used internally by LLVM as a "base pointer" for functions with complex stack frames. |
| x86 | `k0` | This is a constant zero register which can't be modified. |
| x86 | `ip` | This is the program counter, not a real register. |
| x86 | `mm[0-7]` | MMX registers are not currently supported (but may be in the future). |
| x86 | `st([0-7])` | x87 registers are not currently supported (but may be in the future). |
| AArch64 | `xzr` | This is a constant zero register which can't be modified. |
| ARM | `pc` | This is the program counter, not a real register. |
| ARM | `r9` | This is a reserved register on some ARM targets. |
| MIPS | `$0` or `$zero` | This is a constant zero register which can't be modified. |
| MIPS | `$1` or `$at` | Reserved for assembler. |
| MIPS | `$26`/`$k0`, `$27`/`$k1` | OS-reserved registers. |
| MIPS | `$28`/`$gp` | Global pointer cannot be used as inputs or outputs. |
| MIPS | `$ra` | Return address cannot be used as inputs or outputs. |
| RISC-V | `x0` | This is a constant zero register which can't be modified. |
| RISC-V | `gp`, `tp` | These registers are reserved and cannot be used as inputs or outputs. |
| Hexagon | `lr` | This is the link register which cannot be used as an input or output. |
| AVR | `r0`, `r1`, `r1r0` | Due to an issue in LLVM, the `r0` and `r1` registers cannot be used as inputs or outputs. If modified, they must be restored to their original values before the end of the block. |
In some cases LLVM will allocate a "reserved register" for `reg` operands even though this register cannot be explicitly specified. Assembly code making use of reserved registers should be careful since `reg` operands may alias with those registers. Reserved registers are the frame pointer and base pointer
- The frame pointer and LLVM base pointer on all architectures.
- `r9` on ARM.
- `x18` on AArch64.
- `r0` and `r1` on AVR.
## Template modifiers
The placeholders can be augmented by modifiers which are specified after the `:` in the curly braces. These modifiers do not affect register allocation, but change the way operands are formatted when inserted into the template string. Only one modifier is allowed per template placeholder.
The supported modifiers are a subset of LLVM's (and GCC's) [asm template argument modifiers][llvm-argmod], but do not use the same letter codes.
| Architecture | Register class | Modifier | Example output | LLVM modifier |
| ------------ | -------------- | -------- | -------------- | ------------- |
| x86-32 | `reg` | None | `eax` | `k` |
| x86-64 | `reg` | None | `rax` | `q` |
| x86-32 | `reg_abcd` | `l` | `al` | `b` |
| x86-64 | `reg` | `l` | `al` | `b` |
| x86 | `reg_abcd` | `h` | `ah` | `h` |
| x86 | `reg` | `x` | `ax` | `w` |
| x86 | `reg` | `e` | `eax` | `k` |
| x86-64 | `reg` | `r` | `rax` | `q` |
| x86 | `reg_byte` | None | `al` / `ah` | None |
| x86 | `xmm_reg` | None | `xmm0` | `x` |
| x86 | `ymm_reg` | None | `ymm0` | `t` |
| x86 | `zmm_reg` | None | `zmm0` | `g` |
| x86 | `*mm_reg` | `x` | `xmm0` | `x` |
| x86 | `*mm_reg` | `y` | `ymm0` | `t` |
| x86 | `*mm_reg` | `z` | `zmm0` | `g` |
| x86 | `kreg` | None | `k1` | None |
| AArch64 | `reg` | None | `x0` | `x` |
| AArch64 | `reg` | `w` | `w0` | `w` |
| AArch64 | `reg` | `x` | `x0` | `x` |
| AArch64 | `vreg` | None | `v0` | None |
| AArch64 | `vreg` | `v` | `v0` | None |
| AArch64 | `vreg` | `b` | `b0` | `b` |
| AArch64 | `vreg` | `h` | `h0` | `h` |
| AArch64 | `vreg` | `s` | `s0` | `s` |
| AArch64 | `vreg` | `d` | `d0` | `d` |
| AArch64 | `vreg` | `q` | `q0` | `q` |
| ARM | `reg` | None | `r0` | None |
| ARM | `sreg` | None | `s0` | None |
| ARM | `dreg` | None | `d0` | `P` |
| ARM | `qreg` | None | `q0` | `q` |
| ARM | `qreg` | `e` / `f` | `d0` / `d1` | `e` / `f` |
| MIPS | `reg` | None | `$2` | None |
| MIPS | `freg` | None | `$f0` | None |
| NVPTX | `reg16` | None | `rs0` | None |
| NVPTX | `reg32` | None | `r0` | None |
| NVPTX | `reg64` | None | `rd0` | None |
| RISC-V | `reg` | None | `x1` | None |
| RISC-V | `freg` | None | `f0` | None |
| Hexagon | `reg` | None | `r0` | None |
| PowerPC | `reg` | None | `0` | None |
| PowerPC | `reg_nonzero` | None | `3` | `b` |
| PowerPC | `freg` | None | `0` | None |
> Notes:
> - on ARM `e` / `f`: this prints the low or high doubleword register name of a NEON quad (128-bit) register.
> - on x86: our behavior for `reg` with no modifiers differs from what GCC does. GCC will infer the modifier based on the operand value type, while we default to the full register size.
> - on x86 `xmm_reg`: the `x`, `t` and `g` LLVM modifiers are not yet implemented in LLVM (they are supported by GCC only), but this should be a simple change.
As stated in the previous section, passing an input value smaller than the register width will result in the upper bits of the register containing undefined values. This is not a problem if the inline asm only accesses the lower bits of the register, which can be done by using a template modifier to use a subregister name in the asm code (e.g. `ax` instead of `rax`). Since this an easy pitfall, the compiler will suggest a template modifier to use where appropriate given the input type. If all references to an operand already have modifiers then the warning is suppressed for that operand.
[llvm-argmod]: http://llvm.org/docs/LangRef.html#asm-template-argument-modifiers
## ABI clobbers
The `clobber_abi` keyword can be used to apply a default set of clobbers to an `asm` block. This will automatically insert the necessary clobber constraints as needed for calling a function with a particular calling convention: if the calling convention does not fully preserve the value of a register across a call then a `lateout("reg") _` is implicitly added to the operands list.
`clobber_abi` may be specified any number of times. It will insert a clobber for all unique registers in the union of all specified calling conventions.
Generic register class outputs are disallowed by the compiler when `clobber_abi` is used: all outputs must specify an explicit register. Explicit register outputs have precedence over the implicit clobbers inserted by `clobber_abi`: a clobber will only be inserted for a register if that register is not used as an output.
The following ABIs can be used with `clobber_abi`:
| Architecture | ABI name | Clobbered registers |
| ------------ | -------- | ------------------- |
| x86-32 | `"C"`, `"system"`, `"efiapi"`, `"cdecl"`, `"stdcall"`, `"fastcall"` | `ax`, `cx`, `dx`, `xmm[0-7]`, `mm[0-7]`, `k[1-7]`, `st([0-7])` |
| x86-64 | `"C"`, `"system"` (on Windows), `"efiapi"`, `"win64"` | `ax`, `cx`, `dx`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `k[1-7]`, `st([0-7])` |
| x86-64 | `"C"`, `"system"` (on non-Windows), `"sysv64"` | `ax`, `cx`, `dx`, `si`, `di`, `r[8-11]`, `xmm[0-31]`, `mm[0-7]`, `k[1-7]`, `st([0-7])` |
| AArch64 | `"C"`, `"system"`, `"efiapi"` | `x[0-17]`, `x30`, `v[0-31]`, `p[0-15]`, `ffr` |
| ARM | `"C"`, `"system"`, `"efiapi"`, `"aapcs"` | `r[0-3]`, `r12`, `r14`, `s[0-15]`, `d[0-7]`, `d[16-31]` |
| RISC-V | `"C"`, `"system"`, `"efiapi"` | `x1`, `x[5-7]`, `x[10-17]`, `x[28-31]`, `f[0-7]`, `f[10-17]`, `f[28-31]`, `v[0-31]` |
The list of clobbered registers for each ABI is updated in rustc as architectures gain new registers: this ensures that `asm` clobbers will continue to be correct when LLVM starts using these new registers in its generated code.
## Options
Flags are used to further influence the behavior of the inline assembly block.
Currently the following options are defined:
- `pure`: The `asm` block has no side effects, and its outputs depend only on its direct inputs (i.e. the values themselves, not what they point to) or values read from memory (unless the `nomem` options is also set). This allows the compiler to execute the `asm` block fewer times than specified in the program (e.g. by hoisting it out of a loop) or even eliminate it entirely if the outputs are not used.
- `nomem`: The `asm` blocks does not read or write to any memory. This allows the compiler to cache the values of modified global variables in registers across the `asm` block since it knows that they are not read or written to by the `asm`.
- `readonly`: The `asm` block does not write to any memory. This allows the compiler to cache the values of unmodified global variables in registers across the `asm` block since it knows that they are not written to by the `asm`.
- `preserves_flags`: The `asm` block does not modify the flags register (defined in the rules below). This allows the compiler to avoid recomputing the condition flags after the `asm` block.
- `noreturn`: The `asm` block never returns, and its return type is defined as `!` (never). Behavior is undefined if execution falls through past the end of the asm code. A `noreturn` asm block behaves just like a function which doesn't return; notably, local variables in scope are not dropped before it is invoked.
- `nostack`: The `asm` block does not push data to the stack, or write to the stack red-zone (if supported by the target). If this option is *not* used then the stack pointer is guaranteed to be suitably aligned (according to the target ABI) for a function call.
- `att_syntax`: This option is only valid on x86, and causes the assembler to use the `.att_syntax prefix` mode of the GNU assembler. Register operands are substituted in with a leading `%`.
- `may_unwind`: The `asm` block may unwind the stack and be part of the stack unwinding process (This option is only supported by the LLVM backend right now).
- `raw`: This causes the template string to be parsed as a raw assembly string, with no special handling for `{` and `}`. This is primarily useful when including raw assembly code from an external file using `include_str!`.
The compiler performs some additional checks on options:
- The `nomem` and `readonly` options are mutually exclusive: it is a compile-time error to specify both.
- The `pure` option must be combined with either the `nomem` or `readonly` options, otherwise a compile-time error is emitted.
- It is a compile-time error to specify `pure` on an asm block with no outputs or only discarded outputs (`_`).
- It is a compile-time error to specify `noreturn` on an asm block with outputs.
## Rules for inline assembly
- Any registers not specified as inputs will contain an undefined value on entry to the asm block.
- An "undefined value" in the context of inline assembly means that the register can (non-deterministically) have any one of the possible values allowed by the architecture. Notably it is not the same as an LLVM `undef` which can have a different value every time you read it (since such a concept does not exist in assembly code).
- Any registers not specified as outputs must have the same value upon exiting the asm block as they had on entry, otherwise behavior is undefined.
- This only applies to registers which can be specified as an input or output. Other registers follow target-specific rules.
- Note that a `lateout` may be allocated to the same register as an `in`, in which case this rule does not apply. Code should not rely on this however since it depends on the results of register allocation.
- Behavior is undefined if execution unwinds out of an asm block.
- This also applies if the assembly code calls a function which then unwinds.
- The set of memory locations that assembly code is allowed to read and write are the same as those allowed for an FFI function.
- Refer to the unsafe code guidelines for the exact rules.
- If the `readonly` option is set, then only memory reads are allowed.
- If the `nomem` option is set then no reads or writes to memory are allowed.
- These rules do not apply to memory which is private to the asm code, such as stack space allocated within the asm block.
- The compiler cannot assume that the instructions in the asm are the ones that will actually end up executed.
- This effectively means that the compiler must treat the `asm!` as a black box and only take the interface specification into account, not the instructions themselves.
- Runtime code patching is allowed, via target-specific mechanisms (outside the scope of this RFC).
- Unless the `nostack` option is set, asm code is allowed to use stack space below the stack pointer.
- On entry to the asm block the stack pointer is guaranteed to be suitably aligned (according to the target ABI) for a function call.
- You are responsible for making sure you don't overflow the stack (e.g. use stack probing to ensure you hit a guard page).
- You should adjust the stack pointer when allocating stack memory as required by the target ABI.
- The stack pointer must be restored to its original value before leaving the asm block.
- If the `noreturn` option is set then behavior is undefined if execution falls through to the end of the asm block.
- If the `pure` option is set then behavior is undefined if the `asm` has side-effects other than its direct outputs. Behavior is also undefined if two executions of the `asm` code with the same inputs result in different outputs.
- When used with the `nomem` option, "inputs" are just the direct inputs of the `asm!`.
- When used with the `readonly` option, "inputs" comprise the direct inputs of the `asm!` and any memory that the `asm!` block is allowed to read.
- These flags registers must be restored upon exiting the asm block if the `preserves_flags` option is set:
- x86
- Status flags in `EFLAGS` (CF, PF, AF, ZF, SF, OF).
- Floating-point status word (all).
- Floating-point exception flags in `MXCSR` (PE, UE, OE, ZE, DE, IE).
- ARM
- Condition flags in `CPSR` (N, Z, C, V)
- Saturation flag in `CPSR` (Q)
- Greater than or equal flags in `CPSR` (GE).
- Condition flags in `FPSCR` (N, Z, C, V)
- Saturation flag in `FPSCR` (QC)
- Floating-point exception flags in `FPSCR` (IDC, IXC, UFC, OFC, DZC, IOC).
- AArch64
- Condition flags (`NZCV` register).
- Floating-point status (`FPSR` register).
- RISC-V
- Floating-point exception flags in `fcsr` (`fflags`).
- Vector extension state (`vtype`, `vl`, `vcsr`).
- AVR
- The status register `SREG`.
- On x86, the direction flag (DF in `EFLAGS`) is clear on entry to an asm block and must be clear on exit.
- Behavior is undefined if the direction flag is set on exiting an asm block.
- The requirement of restoring the stack pointer and non-output registers to their original value only applies when exiting an `asm!` block.
- This means that `asm!` blocks that never return (even if not marked `noreturn`) don't need to preserve these registers.
- When returning to a different `asm!` block than you entered (e.g. for context switching), these registers must contain the value they had upon entering the `asm!` block that you are *exiting*.
- You cannot exit an `asm!` block that has not been entered. Neither can you exit an `asm!` block that has already been exited.
- You are responsible for switching any target-specific state (e.g. thread-local storage, stack bounds).
- The set of memory locations that you may access is the intersection of those allowed by the `asm!` blocks you entered and exited.
- You cannot assume that an `asm!` block will appear exactly once in the output binary. The compiler is allowed to instantiate multiple copies of the `asm!` block, for example when the function containing it is inlined in multiple places.
- On x86, inline assembly must not end with an instruction prefix (such as `LOCK`) that would apply to instructions generated by the compiler.
- The compiler is currently unable to detect this due to the way inline assembly is compiled, but may catch and reject this in the future.
> **Note**: As a general rule, the flags covered by `preserves_flags` are those which are *not* preserved when performing a function call.

View file

@ -1,113 +0,0 @@
# `global_asm`
The tracking issue for this feature is: [#35119]
[#35119]: https://github.com/rust-lang/rust/issues/35119
------------------------
The `global_asm!` macro allows the programmer to write arbitrary
assembly outside the scope of a function body, passing it through
`rustc` and `llvm` to the assembler. That is to say, `global_asm!` is
equivalent to assembling the asm with an external assembler and then
linking the resulting object file with the current crate.
`global_asm!` fills a role not currently satisfied by either `asm!`
or `#[naked]` functions. The programmer has _all_ features of the
assembler at their disposal. The linker will expect to resolve any
symbols defined in the inline assembly, modulo any symbols marked as
external. It also means syntax for directives and assembly follow the
conventions of the assembler in your toolchain.
A simple usage looks like this:
```rust,ignore (requires-external-file)
#![feature(global_asm)]
# // you also need relevant target_arch cfgs
global_asm!(include_str!("something_neato.s"));
```
And a more complicated usage looks like this:
```rust,no_run
#![feature(global_asm)]
# #[cfg(any(target_arch="x86", target_arch="x86_64"))]
# mod x86 {
pub mod sally {
global_asm!(
".global foo",
"foo:",
"jmp baz",
);
#[no_mangle]
pub unsafe extern "C" fn baz() {}
}
// the symbols `foo` and `bar` are global, no matter where
// `global_asm!` was used.
extern "C" {
fn foo();
fn bar();
}
pub mod harry {
global_asm!(
".global bar",
"bar:",
"jmp quux",
);
#[no_mangle]
pub unsafe extern "C" fn quux() {}
}
# }
```
You may use `global_asm!` multiple times, anywhere in your crate, in
whatever way suits you. However, you should not rely on assembler state
(e.g. assembler macros) defined in one `global_asm!` to be available in
another one. It is implementation-defined whether the multiple usages
are concatenated into one or assembled separately.
`global_asm!` also supports `const` operands like `asm!`, which allows
constants defined in Rust to be used in assembly code:
```rust,no_run
#![feature(global_asm, asm_const)]
# #[cfg(any(target_arch="x86", target_arch="x86_64"))]
# mod x86 {
const C: i32 = 1234;
global_asm!(
".global bar",
"bar: .word {c}",
c = const C,
);
# }
```
The syntax for passing operands is the same as `asm!` except that only
`const` operands are allowed. Refer to the [asm](asm.md) documentation
for more details.
On x86, the assembly code will use intel syntax by default. You can
override this by adding `options(att_syntax)` at the end of the macro
arguments list:
```rust,no_run
#![feature(global_asm, asm_const)]
# #[cfg(any(target_arch="x86", target_arch="x86_64"))]
# mod x86 {
global_asm!("movl ${}, %ecx", const 5, options(att_syntax));
// is equivalent to
global_asm!("mov ecx, {}", const 5);
# }
```
------------------------
If you don't need quite as much power and flexibility as
`global_asm!` provides, and you don't mind restricting your inline
assembly to `fn` bodies only, you might try the
[asm](asm.md) feature instead.

View file

@ -188,6 +188,3 @@ 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
`llvm_asm!`, check out [global_asm](global-asm.md).

View file

@ -2,9 +2,11 @@
// assembly-output: emit-asm
// compile-flags: -C llvm-args=--x86-asm-syntax=intel
#![feature(global_asm, asm_const)]
#![feature(asm_const)]
#![crate_type = "rlib"]
use std::arch::global_asm;
// CHECK: mov eax, eax
global_asm!("mov eax, eax");
// CHECK: mov ebx, 5

View file

@ -4,11 +4,11 @@
// compile-flags: --crate-type staticlib
// only-x86_64-fortanix-unknown-sgx
#![feature(asm)]
use std::arch::asm;
#[no_mangle]
pub extern fn get(ptr: *const u64) -> u64 {
let value : u64;
pub extern "C" fn get(ptr: *const u64) -> u64 {
let value: u64;
unsafe {
asm!(".start_inline_asm:",
"mov {}, [{}]",
@ -26,11 +26,13 @@
// CHECK-NEXT: .end_inline_asm
#[no_mangle]
pub extern fn myret() {
pub extern "C" fn myret() {
unsafe {
asm!(".start_myret_inline_asm:
asm!(
".start_myret_inline_asm:
ret
.end_myret_inline_asm:");
.end_myret_inline_asm:"
);
}
}

View file

@ -2,7 +2,8 @@
// only-x86_64
#![crate_type = "rlib"]
#![feature(asm)]
use std::arch::asm;
// CHECK-LABEL: @clobber_sysv64
// CHECK: ={ax},={cx},={dx},={si},={di},={r8},={r9},={r10},={r11},={xmm0},={xmm1},={xmm2},={xmm3},={xmm4},={xmm5},={xmm6},={xmm7},={xmm8},={xmm9},={xmm10},={xmm11},={xmm12},={xmm13},={xmm14},={xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{k1},~{k2},~{k3},~{k4},~{k5},~{k6},~{k7},~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)},~{dirflag},~{fpsr},~{flags},~{memory}

View file

@ -2,7 +2,8 @@
// only-x86_64
#![crate_type = "rlib"]
#![feature(asm)]
use std::arch::asm;
// CHECK-LABEL: @x87_clobber
// CHECK: ~{st},~{st(1)},~{st(2)},~{st(3)},~{st(4)},~{st(5)},~{st(6)},~{st(7)}

View file

@ -3,7 +3,9 @@
// only-x86_64
#![crate_type = "rlib"]
#![feature(asm, asm_unwind)]
#![feature(asm_unwind)]
use std::arch::asm;
#[no_mangle]
pub extern "C" fn panicky() {}

View file

@ -2,7 +2,8 @@
// only-x86_64
#![crate_type = "rlib"]
#![feature(asm)]
use std::arch::asm;
// CHECK-LABEL: @pure
// CHECK-NOT: asm

View file

@ -2,7 +2,8 @@
// only-x86_64
#![crate_type = "rlib"]
#![feature(asm)]
use std::arch::asm;
// CHECK-LABEL: @pure
// CHECK-NOT: asm

View file

@ -3,7 +3,8 @@
// [avx512]compile-flags: -C target-feature=+avx512f
#![crate_type = "rlib"]
#![feature(asm)]
use std::arch::asm;
// CHECK-LABEL: @avx512_clobber
// base: call void asm sideeffect inteldialect "", "~{xmm31}"()

View file

@ -39,18 +39,21 @@
// ignore-emscripten
// compile-flags: -C no-prepopulate-passes
#![feature(global_asm)]
#![crate_type = "lib"]
use std::arch::global_asm;
// CHECK-LABEL: foo
// CHECK: module asm
// this regex will capture the correct unconditional branch inst.
// CHECK: module asm "{{[[:space:]]+}}jmp baz"
global_asm!(r#"
global_asm!(
r#"
.global foo
foo:
jmp baz
"#);
"#
);
extern "C" {
fn foo();

View file

@ -39,9 +39,10 @@
// ignore-emscripten
// compile-flags: -C no-prepopulate-passes
#![feature(global_asm)]
#![crate_type = "lib"]
use std::arch::global_asm;
// CHECK-LABEL: foo
// CHECK: module asm
// CHECK: module asm "{{[[:space:]]+}}jmp baz"

View file

@ -39,9 +39,10 @@
// ignore-emscripten
// compile-flags: -C no-prepopulate-passes
#![feature(global_asm)]
#![crate_type = "lib"]
#[no_std]
#![no_std]
use core::arch::global_asm;
// CHECK-LABEL: foo
// CHECK: module asm
@ -49,11 +50,13 @@
// any other global_asm will be appended to this first block, so:
// CHECK-LABEL: bar
// CHECK: module asm "{{[[:space:]]+}}jmp quux"
global_asm!(r#"
global_asm!(
r#"
.global foo
foo:
jmp baz
"#);
"#
);
extern "C" {
fn foo();
@ -64,11 +67,13 @@
pub unsafe extern "C" fn baz() {}
// no checks here; this has been appended to the first occurrence
global_asm!(r#"
global_asm!(
r#"
.global bar
bar:
jmp quux
"#);
"#
);
extern "C" {
fn bar();

View file

@ -3,28 +3,29 @@
// needs-asm-support
// ignore-wasm32
#![crate_type = "lib"]
#![feature(asm)]
#![feature(naked_functions)]
use std::arch::asm;
#[inline(always)]
#[naked]
#[no_mangle]
pub unsafe extern "C" fn f() {
// Check that f has naked and noinline attributes.
//
// CHECK: define void @f() unnamed_addr [[ATTR:#[0-9]+]]
// CHECK-NEXT: start:
// CHECK-NEXT: call void asm
// Check that f has naked and noinline attributes.
//
// CHECK: define void @f() unnamed_addr [[ATTR:#[0-9]+]]
// CHECK-NEXT: start:
// CHECK-NEXT: call void asm
asm!("", options(noreturn));
}
#[no_mangle]
pub unsafe fn g() {
// Check that call to f is not inlined.
//
// CHECK-LABEL: define void @g()
// CHECK-NEXT: start:
// CHECK-NEXT: call void @f()
// Check that call to f is not inlined.
//
// CHECK-LABEL: define void @g()
// CHECK-NEXT: start:
// CHECK-NEXT: call void @f()
f();
}

View file

@ -4,13 +4,11 @@
// Checks that we don't ICE when switching to an invalid register
// and back again
#![feature(asm)]
use std::arch::asm;
#[cfg(any(rpass1, rpass3))]
fn main() {
unsafe {
asm!("nop")
}
unsafe { asm!("nop") }
}
#[cfg(cfail1)]

View file

@ -1,15 +1,15 @@
#![feature(prelude_import)]
#![no_std]
#![feature(asm)]
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
extern crate std;
// pretty-mode:expanded
// pp-exact:asm.pp
// only-x86_64
use std::arch::asm;
pub fn main() {
let a: i32;
let mut b = 4i32;

View file

@ -1,9 +1,9 @@
#![feature(asm)]
// pretty-mode:expanded
// pp-exact:asm.pp
// only-x86_64
use std::arch::asm;
pub fn main() {
let a: i32;
let mut b = 4i32;
@ -20,8 +20,10 @@ pub fn main() {
asm!("inst1 {}, 42", "inst2 {}, 24", in(reg) a, out(reg) b);
asm!("inst2 {1}, 24", "inst1 {0}, 42", in(reg) a, out(reg) b);
asm!("inst1 {}, 42", "inst2 {name}, 24", in(reg) a, name = out(reg) b);
asm!("inst1
inst2");
asm!(
"inst1
inst2"
);
asm!("inst1\ninst2");
asm!("inst1\n\tinst2");
asm!("inst1\ninst2", "inst3\ninst4");

View file

@ -1,6 +1,5 @@
#![feature(global_asm)]
global_asm!( r#"
std::arch::global_asm!(
r#"
.text
.global rust_plus_one_global_asm
.type rust_plus_one_global_asm, @function
@ -8,41 +7,43 @@
movl (%rdi), %eax
inc %eax
retq
"#, options(att_syntax));
"#,
options(att_syntax)
);
extern {
fn cc_plus_one_c(arg : &u32) -> u32;
fn cc_plus_one_c_asm(arg : &u32) -> u32;
fn cc_plus_one_cxx(arg : &u32) -> u32;
fn cc_plus_one_cxx_asm(arg : &u32) -> u32;
fn cc_plus_one_asm(arg : &u32) -> u32;
fn cmake_plus_one_c(arg : &u32) -> u32;
fn cmake_plus_one_c_asm(arg : &u32) -> u32;
fn cmake_plus_one_cxx(arg : &u32) -> u32;
fn cmake_plus_one_cxx_asm(arg : &u32) -> u32;
fn cmake_plus_one_c_global_asm(arg : &u32) -> u32;
fn cmake_plus_one_cxx_global_asm(arg : &u32) -> u32;
fn cmake_plus_one_asm(arg : &u32) -> u32;
fn rust_plus_one_global_asm(arg : &u32) -> u32;
extern "C" {
fn cc_plus_one_c(arg: &u32) -> u32;
fn cc_plus_one_c_asm(arg: &u32) -> u32;
fn cc_plus_one_cxx(arg: &u32) -> u32;
fn cc_plus_one_cxx_asm(arg: &u32) -> u32;
fn cc_plus_one_asm(arg: &u32) -> u32;
fn cmake_plus_one_c(arg: &u32) -> u32;
fn cmake_plus_one_c_asm(arg: &u32) -> u32;
fn cmake_plus_one_cxx(arg: &u32) -> u32;
fn cmake_plus_one_cxx_asm(arg: &u32) -> u32;
fn cmake_plus_one_c_global_asm(arg: &u32) -> u32;
fn cmake_plus_one_cxx_global_asm(arg: &u32) -> u32;
fn cmake_plus_one_asm(arg: &u32) -> u32;
fn rust_plus_one_global_asm(arg: &u32) -> u32;
}
fn main() {
let value : u32 = 41;
let value: u32 = 41;
let question = "Answer to the Ultimate Question of Life, the Universe, and Everything:";
unsafe{
println!("{}: {}!", question,rust_plus_one_global_asm(&value));
println!("{}: {}!", question,cc_plus_one_c(&value));
println!("{}: {}!", question,cc_plus_one_c_asm(&value));
println!("{}: {}!", question,cc_plus_one_cxx(&value));
println!("{}: {}!", question,cc_plus_one_cxx_asm(&value));
println!("{}: {}!", question,cc_plus_one_asm(&value));
println!("{}: {}!", question,cmake_plus_one_c(&value));
println!("{}: {}!", question,cmake_plus_one_c_asm(&value));
println!("{}: {}!", question,cmake_plus_one_cxx(&value));
println!("{}: {}!", question,cmake_plus_one_cxx_asm(&value));
println!("{}: {}!", question,cmake_plus_one_c_global_asm(&value));
println!("{}: {}!", question,cmake_plus_one_cxx_global_asm(&value));
println!("{}: {}!", question,cmake_plus_one_asm(&value));
unsafe {
println!("{}: {}!", question, rust_plus_one_global_asm(&value));
println!("{}: {}!", question, cc_plus_one_c(&value));
println!("{}: {}!", question, cc_plus_one_c_asm(&value));
println!("{}: {}!", question, cc_plus_one_cxx(&value));
println!("{}: {}!", question, cc_plus_one_cxx_asm(&value));
println!("{}: {}!", question, cc_plus_one_asm(&value));
println!("{}: {}!", question, cmake_plus_one_c(&value));
println!("{}: {}!", question, cmake_plus_one_c_asm(&value));
println!("{}: {}!", question, cmake_plus_one_cxx(&value));
println!("{}: {}!", question, cmake_plus_one_cxx_asm(&value));
println!("{}: {}!", question, cmake_plus_one_c_global_asm(&value));
println!("{}: {}!", question, cmake_plus_one_cxx_global_asm(&value));
println!("{}: {}!", question, cmake_plus_one_asm(&value));
}
}

View file

@ -1,6 +1,6 @@
// Make sure rustdoc accepts asm! for a foreign architecture.
#![feature(asm)]
use std::arch::asm;
// @has asm_foreign/fn.aarch64.html
pub unsafe fn aarch64(a: f64, b: f64) -> f64 {

View file

@ -1,7 +1,7 @@
// only-aarch64
// Make sure rustdoc accepts options(att_syntax) asm! on non-x86 targets.
#![feature(asm)]
use std::arch::asm;
// @has asm_foreign2/fn.x86.html
pub unsafe fn x86(x: i64) -> i64 {

View file

@ -1,6 +1,6 @@
// only-aarch64
#![feature(asm, global_asm)]
use std::arch::{asm, global_asm};
fn main() {
let mut foo = 0;

View file

@ -1,7 +1,9 @@
// only-aarch64
// compile-flags: -C target-feature=+fp
#![feature(asm, asm_const, asm_sym)]
#![feature(asm_const, asm_sym)]
use std::arch::asm;
fn main() {
let mut foo = 0;

View file

@ -3,7 +3,9 @@
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
#![feature(asm, global_asm, asm_const)]
#![feature(asm_const)]
use std::arch::{asm, global_asm};
fn const_generic<const X: usize>() -> usize {
unsafe {

View file

@ -1,8 +1,6 @@
// only-aarch64
// run-rustfix
#![feature(asm, global_asm)]
fn main() {
unsafe {
asm!("", options(nomem, ));

View file

@ -1,7 +1,7 @@
// only-aarch64
// run-rustfix
#![feature(asm, global_asm)]
use std::arch::asm;
fn main() {
unsafe {
@ -19,8 +19,8 @@ fn main() {
"",
options(nomem, noreturn),
options(preserves_flags, noreturn), //~ ERROR the `noreturn` option was already provided
options(nomem, nostack), //~ ERROR the `nomem` option was already provided
options(noreturn), //~ ERROR the `noreturn` option was already provided
options(nomem, nostack), //~ ERROR the `nomem` option was already provided
options(noreturn), //~ ERROR the `noreturn` option was already provided
);
}
}

View file

@ -1,6 +1,6 @@
// only-aarch64
#![feature(asm)]
use std::arch::asm;
macro_rules! m {
($in:ident $out:ident $lateout:ident $inout:ident $inlateout:ident $const:ident $sym:ident

View file

@ -3,8 +3,9 @@
// run-pass
// needs-asm-support
#![feature(asm, asm_sym, asm_unwind)]
#![feature(asm_sym, asm_unwind)]
use std::arch::asm;
use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe};
struct Foo<'a>(&'a mut bool);

View file

@ -1,6 +1,8 @@
// only-aarch64
#![feature(asm, global_asm, asm_const)]
#![feature(asm_const)]
use std::arch::{asm, global_asm};
fn main() {
let mut foo = 0;

View file

@ -1,7 +1,8 @@
// only-aarch64
// build-fail
// compile-flags: -Ccodegen-units=1
#![feature(asm)]
use std::arch::asm;
// Checks that inline asm errors are mapped to the correct line in the source code.

View file

@ -2,7 +2,9 @@
// only-linux
// run-pass
#![feature(asm, thread_local, asm_sym)]
#![feature(thread_local, asm_sym)]
use std::arch::asm;
extern "C" fn f1() -> i32 {
111

View file

@ -1,6 +1,8 @@
// only-aarch64
#![feature(asm, repr_simd, never_type, asm_sym)]
#![feature(repr_simd, never_type, asm_sym)]
use std::arch::asm;
#[repr(simd)]
#[derive(Clone, Copy)]

View file

@ -1,9 +1,10 @@
// only-aarch64
// compile-flags: -C target-feature=+neon
#![feature(asm, global_asm, repr_simd, stdsimd, asm_const)]
#![feature(repr_simd, stdsimd, asm_const)]
use std::arch::aarch64::float64x2_t;
use std::arch::{asm, global_asm};
#[repr(simd)]
#[derive(Copy, Clone)]

View file

@ -2,7 +2,7 @@
// needs-asm-support
// Also test for #72960
#![feature(asm)]
use std::arch::asm;
fn main() {
unsafe {

View file

@ -4,7 +4,7 @@
// ignore-wasm32
// Make sure rustc doesn't ICE on asm! when output type is !.
#![feature(asm)]
use std::arch::asm;
fn hmm() -> ! {
let x;

View file

@ -4,9 +4,10 @@
// check-pass
// needs-asm-support
#![feature(asm)]
#![warn(unused)]
use std::arch::asm;
fn main() {
unsafe {
let x: () = asm!("nop");

View file

@ -1,11 +1,11 @@
warning: unused variable: `x`
--> $DIR/issue-89305.rs:12:13
--> $DIR/issue-89305.rs:13:13
|
LL | let x: () = asm!("nop");
| ^ help: if this is intentional, prefix it with an underscore: `_x`
|
note: the lint level is defined here
--> $DIR/issue-89305.rs:8:9
--> $DIR/issue-89305.rs:7:9
|
LL | #![warn(unused)]
| ^^^^^^

View file

@ -2,7 +2,9 @@
// run-pass
// needs-asm-support
#![feature(asm, asm_unwind)]
#![feature(asm_unwind)]
use std::arch::asm;
fn main() {
unsafe { asm!("", options(may_unwind)) };

View file

@ -1,12 +1,15 @@
// check-pass
// needs-asm-support
#![feature(asm)]
#![feature(naked_functions)]
#![crate_type = "lib"]
use std::arch::asm;
#[naked]
pub extern "C" fn naked(p: char) -> u128 {
//~^ WARN uses type `char`
//~| WARN uses type `u128`
unsafe { asm!("", options(noreturn)); }
unsafe {
asm!("", options(noreturn));
}
}

View file

@ -1,5 +1,5 @@
warning: `extern` fn uses type `char`, which is not FFI-safe
--> $DIR/naked-functions-ffi.rs:8:28
--> $DIR/naked-functions-ffi.rs:9:28
|
LL | pub extern "C" fn naked(p: char) -> u128 {
| ^^^^ not FFI-safe
@ -9,7 +9,7 @@ LL | pub extern "C" fn naked(p: char) -> u128 {
= note: the `char` type has no C equivalent
warning: `extern` fn uses type `u128`, which is not FFI-safe
--> $DIR/naked-functions-ffi.rs:8:37
--> $DIR/naked-functions-ffi.rs:9:37
|
LL | pub extern "C" fn naked(p: char) -> u128 {
| ^^^^ not FFI-safe

View file

@ -2,7 +2,6 @@
//[x86_64] only-x86_64
//[aarch64] only-aarch64
#![deny(unused)]
#![feature(asm)]
#![feature(naked_functions)]
#![crate_type = "lib"]
@ -12,6 +11,8 @@ pub trait Trait {
}
pub mod normal {
use std::arch::asm;
pub extern "C" fn function(a: usize, b: usize) -> usize {
//~^ ERROR unused variable: `a`
//~| ERROR unused variable: `b`
@ -50,6 +51,8 @@ extern "C" fn trait_method(&self, a: usize, b: usize) -> usize {
}
pub mod naked {
use std::arch::asm;
#[naked]
pub extern "C" fn function(a: usize, b: usize) -> usize {
unsafe { asm!("", options(noreturn)); }

View file

@ -1,5 +1,5 @@
error: unused variable: `a`
--> $DIR/naked-functions-unused.rs:15:32
--> $DIR/naked-functions-unused.rs:16:32
|
LL | pub extern "C" fn function(a: usize, b: usize) -> usize {
| ^ help: if this is intentional, prefix it with an underscore: `_a`
@ -12,55 +12,55 @@ LL | #![deny(unused)]
= note: `#[deny(unused_variables)]` implied by `#[deny(unused)]`
error: unused variable: `b`
--> $DIR/naked-functions-unused.rs:15:42
--> $DIR/naked-functions-unused.rs:16:42
|
LL | pub extern "C" fn function(a: usize, b: usize) -> usize {
| ^ help: if this is intentional, prefix it with an underscore: `_b`
error: unused variable: `a`
--> $DIR/naked-functions-unused.rs:24:38
--> $DIR/naked-functions-unused.rs:25:38
|
LL | pub extern "C" fn associated(a: usize, b: usize) -> usize {
| ^ help: if this is intentional, prefix it with an underscore: `_a`
error: unused variable: `b`
--> $DIR/naked-functions-unused.rs:24:48
--> $DIR/naked-functions-unused.rs:25:48
|
LL | pub extern "C" fn associated(a: usize, b: usize) -> usize {
| ^ help: if this is intentional, prefix it with an underscore: `_b`
error: unused variable: `a`
--> $DIR/naked-functions-unused.rs:30:41
--> $DIR/naked-functions-unused.rs:31:41
|
LL | pub extern "C" fn method(&self, a: usize, b: usize) -> usize {
| ^ help: if this is intentional, prefix it with an underscore: `_a`
error: unused variable: `b`
--> $DIR/naked-functions-unused.rs:30:51
--> $DIR/naked-functions-unused.rs:31:51
|
LL | pub extern "C" fn method(&self, a: usize, b: usize) -> usize {
| ^ help: if this is intentional, prefix it with an underscore: `_b`
error: unused variable: `a`
--> $DIR/naked-functions-unused.rs:38:40
--> $DIR/naked-functions-unused.rs:39:40
|
LL | extern "C" fn trait_associated(a: usize, b: usize) -> usize {
| ^ help: if this is intentional, prefix it with an underscore: `_a`
error: unused variable: `b`
--> $DIR/naked-functions-unused.rs:38:50
--> $DIR/naked-functions-unused.rs:39:50
|
LL | extern "C" fn trait_associated(a: usize, b: usize) -> usize {
| ^ help: if this is intentional, prefix it with an underscore: `_b`
error: unused variable: `a`
--> $DIR/naked-functions-unused.rs:44:43
--> $DIR/naked-functions-unused.rs:45:43
|
LL | extern "C" fn trait_method(&self, a: usize, b: usize) -> usize {
| ^ help: if this is intentional, prefix it with an underscore: `_a`
error: unused variable: `b`
--> $DIR/naked-functions-unused.rs:44:53
--> $DIR/naked-functions-unused.rs:45:53
|
LL | extern "C" fn trait_method(&self, a: usize, b: usize) -> usize {
| ^ help: if this is intentional, prefix it with an underscore: `_b`

View file

@ -3,7 +3,6 @@
// ignore-spirv
// ignore-wasm32
#![feature(asm)]
#![feature(llvm_asm)]
#![feature(naked_functions)]
#![feature(or_patterns)]
@ -11,6 +10,8 @@
#![crate_type = "lib"]
#![allow(deprecated)] // llvm_asm!
use std::arch::asm;
#[repr(C)]
pub struct P {
x: u8,

View file

@ -1,35 +1,35 @@
error: asm with the `pure` option must have at least one output
--> $DIR/naked-functions.rs:135:14
--> $DIR/naked-functions.rs:136:14
|
LL | asm!("", options(readonly, nostack), options(pure));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^
error: patterns not allowed in naked function parameters
--> $DIR/naked-functions.rs:22:5
--> $DIR/naked-functions.rs:23:5
|
LL | mut a: u32,
| ^^^^^
error: patterns not allowed in naked function parameters
--> $DIR/naked-functions.rs:24:5
--> $DIR/naked-functions.rs:25:5
|
LL | &b: &i32,
| ^^
error: patterns not allowed in naked function parameters
--> $DIR/naked-functions.rs:26:6
--> $DIR/naked-functions.rs:27:6
|
LL | (None | Some(_)): Option<std::ptr::NonNull<u8>>,
| ^^^^^^^^^^^^^^
error: patterns not allowed in naked function parameters
--> $DIR/naked-functions.rs:28:5
--> $DIR/naked-functions.rs:29:5
|
LL | P { x, y }: P,
| ^^^^^^^^^^
error: referencing function parameters is not allowed in naked functions
--> $DIR/naked-functions.rs:38:5
--> $DIR/naked-functions.rs:39:5
|
LL | a + 1
| ^
@ -37,7 +37,7 @@ LL | a + 1
= help: follow the calling convention in asm block to use parameters
warning: naked functions must contain a single asm block
--> $DIR/naked-functions.rs:35:1
--> $DIR/naked-functions.rs:36:1
|
LL | / pub unsafe extern "C" fn inc(a: u32) -> u32 {
LL | |
@ -53,7 +53,7 @@ LL | | }
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
error: referencing function parameters is not allowed in naked functions
--> $DIR/naked-functions.rs:44:31
--> $DIR/naked-functions.rs:45:31
|
LL | asm!("/* {0} */", in(reg) a, options(noreturn));
| ^
@ -61,7 +61,7 @@ LL | asm!("/* {0} */", in(reg) a, options(noreturn));
= help: follow the calling convention in asm block to use parameters
warning: only `const` and `sym` operands are supported in naked functions
--> $DIR/naked-functions.rs:44:23
--> $DIR/naked-functions.rs:45:23
|
LL | asm!("/* {0} */", in(reg) a, options(noreturn));
| ^^^^^^^^^
@ -70,7 +70,7 @@ LL | asm!("/* {0} */", in(reg) a, options(noreturn));
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions must contain a single asm block
--> $DIR/naked-functions.rs:51:1
--> $DIR/naked-functions.rs:52:1
|
LL | / pub unsafe extern "C" fn inc_closure(a: u32) -> u32 {
LL | |
@ -84,7 +84,7 @@ LL | | }
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: only `const` and `sym` operands are supported in naked functions
--> $DIR/naked-functions.rs:71:10
--> $DIR/naked-functions.rs:72:10
|
LL | in(reg) a,
| ^^^^^^^^^
@ -102,7 +102,7 @@ LL | out(reg) e,
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: asm in naked functions must use `noreturn` option
--> $DIR/naked-functions.rs:68:5
--> $DIR/naked-functions.rs:69:5
|
LL | / asm!("/* {0} {1} {2} {3} {4} {5} {6} */",
LL | |
@ -117,7 +117,7 @@ LL | | );
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions must contain a single asm block
--> $DIR/naked-functions.rs:58:1
--> $DIR/naked-functions.rs:59:1
|
LL | / pub unsafe extern "C" fn unsupported_operands() {
LL | |
@ -141,7 +141,7 @@ LL | | }
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions must contain a single asm block
--> $DIR/naked-functions.rs:84:1
--> $DIR/naked-functions.rs:85:1
|
LL | / pub extern "C" fn missing_assembly() {
LL | |
@ -153,7 +153,7 @@ LL | | }
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: asm in naked functions must use `noreturn` option
--> $DIR/naked-functions.rs:93:5
--> $DIR/naked-functions.rs:94:5
|
LL | asm!("");
| ^^^^^^^^
@ -162,7 +162,7 @@ LL | asm!("");
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: asm in naked functions must use `noreturn` option
--> $DIR/naked-functions.rs:96:5
--> $DIR/naked-functions.rs:97:5
|
LL | asm!("");
| ^^^^^^^^
@ -171,7 +171,7 @@ LL | asm!("");
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: asm in naked functions must use `noreturn` option
--> $DIR/naked-functions.rs:99:5
--> $DIR/naked-functions.rs:100:5
|
LL | asm!("");
| ^^^^^^^^
@ -180,7 +180,7 @@ LL | asm!("");
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions must contain a single asm block
--> $DIR/naked-functions.rs:90:1
--> $DIR/naked-functions.rs:91:1
|
LL | / pub extern "C" fn too_many_asm_blocks() {
LL | |
@ -202,7 +202,7 @@ LL | | }
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
error: referencing function parameters is not allowed in naked functions
--> $DIR/naked-functions.rs:110:11
--> $DIR/naked-functions.rs:111:11
|
LL | *&y
| ^
@ -210,7 +210,7 @@ LL | *&y
= help: follow the calling convention in asm block to use parameters
warning: naked functions must contain a single asm block
--> $DIR/naked-functions.rs:107:5
--> $DIR/naked-functions.rs:108:5
|
LL | / pub extern "C" fn inner(y: usize) -> usize {
LL | |
@ -225,7 +225,7 @@ LL | | }
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: the LLVM-style inline assembly is unsupported in naked functions
--> $DIR/naked-functions.rs:120:5
--> $DIR/naked-functions.rs:121:5
|
LL | llvm_asm!("");
| ^^^^^^^^^^^^^
@ -236,7 +236,7 @@ LL | llvm_asm!("");
= note: this warning originates in the macro `llvm_asm` (in Nightly builds, run with -Z macro-backtrace for more info)
warning: naked functions must contain a single asm block
--> $DIR/naked-functions.rs:117:1
--> $DIR/naked-functions.rs:118:1
|
LL | / unsafe extern "C" fn llvm() -> ! {
LL | |
@ -252,7 +252,7 @@ LL | | }
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: asm options unsupported in naked functions: `nomem`, `preserves_flags`
--> $DIR/naked-functions.rs:128:5
--> $DIR/naked-functions.rs:129:5
|
LL | asm!("", options(nomem, preserves_flags, noreturn));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -261,7 +261,7 @@ LL | asm!("", options(nomem, preserves_flags, noreturn));
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: asm options unsupported in naked functions: `nostack`, `pure`, `readonly`
--> $DIR/naked-functions.rs:135:5
--> $DIR/naked-functions.rs:136:5
|
LL | asm!("", options(readonly, nostack), options(pure));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -270,7 +270,7 @@ LL | asm!("", options(readonly, nostack), options(pure));
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: asm in naked functions must use `noreturn` option
--> $DIR/naked-functions.rs:135:5
--> $DIR/naked-functions.rs:136:5
|
LL | asm!("", options(readonly, nostack), options(pure));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -279,7 +279,7 @@ LL | asm!("", options(readonly, nostack), options(pure));
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: Rust ABI is unsupported in naked functions
--> $DIR/naked-functions.rs:144:15
--> $DIR/naked-functions.rs:145:15
|
LL | pub unsafe fn default_abi() {
| ^^^^^^^^^^^
@ -287,13 +287,13 @@ LL | pub unsafe fn default_abi() {
= note: `#[warn(undefined_naked_function_abi)]` on by default
warning: Rust ABI is unsupported in naked functions
--> $DIR/naked-functions.rs:150:15
--> $DIR/naked-functions.rs:151:15
|
LL | pub unsafe fn rust_abi() {
| ^^^^^^^^
warning: naked functions cannot be inlined
--> $DIR/naked-functions.rs:190:1
--> $DIR/naked-functions.rs:191:1
|
LL | #[inline]
| ^^^^^^^^^
@ -302,7 +302,7 @@ LL | #[inline]
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions cannot be inlined
--> $DIR/naked-functions.rs:198:1
--> $DIR/naked-functions.rs:199:1
|
LL | #[inline(always)]
| ^^^^^^^^^^^^^^^^^
@ -311,7 +311,7 @@ LL | #[inline(always)]
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions cannot be inlined
--> $DIR/naked-functions.rs:206:1
--> $DIR/naked-functions.rs:207:1
|
LL | #[inline(never)]
| ^^^^^^^^^^^^^^^^
@ -320,7 +320,7 @@ LL | #[inline(never)]
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions cannot be inlined
--> $DIR/naked-functions.rs:214:1
--> $DIR/naked-functions.rs:215:1
|
LL | #[inline]
| ^^^^^^^^^
@ -329,7 +329,7 @@ LL | #[inline]
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions cannot be inlined
--> $DIR/naked-functions.rs:217:1
--> $DIR/naked-functions.rs:218:1
|
LL | #[inline(always)]
| ^^^^^^^^^^^^^^^^^
@ -338,7 +338,7 @@ LL | #[inline(always)]
= note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
warning: naked functions cannot be inlined
--> $DIR/naked-functions.rs:220:1
--> $DIR/naked-functions.rs:221:1
|
LL | #[inline(never)]
| ^^^^^^^^^^^^^^^^

View file

@ -1,10 +1,11 @@
// Checks that #[naked] attribute can be placed on function definitions only.
//
// needs-asm-support
#![feature(asm)]
#![feature(naked_functions)]
#![naked] //~ ERROR should be applied to a function definition
use std::arch::asm;
extern "C" {
#[naked] //~ ERROR should be applied to a function definition
fn f();

View file

@ -1,5 +1,5 @@
error: attribute should be applied to a function definition
--> $DIR/naked-invalid-attr.rs:13:1
--> $DIR/naked-invalid-attr.rs:14:1
|
LL | #[naked]
| ^^^^^^^^
@ -11,13 +11,13 @@ LL | | }
| |_- not a function definition
error: attribute should be applied to a function definition
--> $DIR/naked-invalid-attr.rs:50:5
--> $DIR/naked-invalid-attr.rs:51:5
|
LL | #[naked] || {};
| ^^^^^^^^ ----- not a function definition
error: attribute should be applied to a function definition
--> $DIR/naked-invalid-attr.rs:21:5
--> $DIR/naked-invalid-attr.rs:22:5
|
LL | #[naked]
| ^^^^^^^^
@ -25,7 +25,7 @@ LL | extern "C" fn invoke(&self);
| ---------------------------- not a function definition
error: attribute should be applied to a function definition
--> $DIR/naked-invalid-attr.rs:9:5
--> $DIR/naked-invalid-attr.rs:10:5
|
LL | #[naked]
| ^^^^^^^^
@ -33,7 +33,7 @@ LL | fn f();
| ------- not a function definition
error: attribute should be applied to a function definition
--> $DIR/naked-invalid-attr.rs:6:1
--> $DIR/naked-invalid-attr.rs:5:1
|
LL | #![naked]
| ^^^^^^^^^

View file

@ -11,7 +11,9 @@
// which causes less readable LLVM errors and in the worst cases causes ICEs
// or segfaults based on system dependent behavior and codegen flags.
#![feature(asm, global_asm, naked_functions, asm_const)]
#![feature(naked_functions, asm_const)]
use std::arch::{asm, global_asm};
#[no_mangle]
pub static FOO: usize = 42;

View file

@ -1,141 +1,126 @@
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:22:15
--> $DIR/named-asm-labels.rs:24:15
|
LL | asm!("bar: nop");
| ^^^
|
= note: `#[deny(named_asm_labels)]` on by default
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:25:15
--> $DIR/named-asm-labels.rs:27:15
|
LL | asm!("abcd:");
| ^^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:28:15
--> $DIR/named-asm-labels.rs:30:15
|
LL | asm!("foo: bar1: nop");
| ^^^ ^^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:32:15
--> $DIR/named-asm-labels.rs:34:15
|
LL | asm!("foo1: nop", "nop");
| ^^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:33:15
--> $DIR/named-asm-labels.rs:35:15
|
LL | asm!("foo2: foo3: nop", "nop");
| ^^^^ ^^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:35:22
--> $DIR/named-asm-labels.rs:37:22
|
LL | asm!("nop", "foo4: nop");
| ^^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:36:15
--> $DIR/named-asm-labels.rs:38:15
|
LL | asm!("foo5: nop", "foo6: nop");
| ^^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:36:28
--> $DIR/named-asm-labels.rs:38:28
|
LL | asm!("foo5: nop", "foo6: nop");
| ^^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:41:15
--> $DIR/named-asm-labels.rs:43:15
|
LL | asm!("foo7: nop; foo8: nop");
| ^^^^ ^^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:43:15
--> $DIR/named-asm-labels.rs:45:15
|
LL | asm!("foo9: nop; nop");
| ^^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:44:20
--> $DIR/named-asm-labels.rs:46:20
|
LL | asm!("nop; foo10: nop");
| ^^^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:47:15
--> $DIR/named-asm-labels.rs:49:15
|
LL | asm!("bar2: nop\n bar3: nop");
| ^^^^ ^^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:49:15
--> $DIR/named-asm-labels.rs:51:15
|
LL | asm!("bar4: nop\n nop");
| ^^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:50:21
--> $DIR/named-asm-labels.rs:52:21
|
LL | asm!("nop\n bar5: nop");
| ^^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:51:21
--> $DIR/named-asm-labels.rs:53:21
|
LL | asm!("nop\n bar6: bar7: nop");
| ^^^^ ^^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:57:13
--> $DIR/named-asm-labels.rs:59:13
|
LL | blah2: nop
| ^^^^^
@ -143,192 +128,171 @@ LL | blah3: nop
| ^^^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:66:19
--> $DIR/named-asm-labels.rs:68:19
|
LL | nop ; blah4: nop
| ^^^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:80:15
--> $DIR/named-asm-labels.rs:82:15
|
LL | asm!("blah1: 2bar: nop");
| ^^^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:83:15
--> $DIR/named-asm-labels.rs:85:15
|
LL | asm!("def: def: nop");
| ^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:84:15
--> $DIR/named-asm-labels.rs:86:15
|
LL | asm!("def: nop\ndef: nop");
| ^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:85:15
--> $DIR/named-asm-labels.rs:87:15
|
LL | asm!("def: nop; def: nop");
| ^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:93:15
--> $DIR/named-asm-labels.rs:95:15
|
LL | asm!("fooo\u{003A} nop");
| ^^^^^^^^^^^^^^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:94:15
--> $DIR/named-asm-labels.rs:96:15
|
LL | asm!("foooo\x3A nop");
| ^^^^^^^^^^^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:97:15
--> $DIR/named-asm-labels.rs:99:15
|
LL | asm!("fooooo:\u{000A} nop");
| ^^^^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:98:15
--> $DIR/named-asm-labels.rs:100:15
|
LL | asm!("foooooo:\x0A nop");
| ^^^^^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:102:14
--> $DIR/named-asm-labels.rs:104:14
|
LL | asm!("\x41\x42\x43\x3A\x20\x6E\x6F\x70");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:110:13
--> $DIR/named-asm-labels.rs:112:13
|
LL | ab: nop // ab: does foo
| ^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:122:14
--> $DIR/named-asm-labels.rs:124:14
|
LL | asm!(include_str!("named-asm-labels.s"));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
warning: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:132:19
--> $DIR/named-asm-labels.rs:134:19
|
LL | asm!("warned: nop");
| ^^^^^^
|
note: the lint level is defined here
--> $DIR/named-asm-labels.rs:130:16
--> $DIR/named-asm-labels.rs:132:16
|
LL | #[warn(named_asm_labels)]
| ^^^^^^^^^^^^^^^^
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:141:20
--> $DIR/named-asm-labels.rs:143:20
|
LL | unsafe { asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1, options(noreturn)) }
| ^^^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:147:20
--> $DIR/named-asm-labels.rs:149:20
|
LL | unsafe { asm!(".Lbar: mov rax, {}; ret;", "nop", const 1, options(noreturn)) }
| ^^^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:155:20
--> $DIR/named-asm-labels.rs:157:20
|
LL | unsafe { asm!(".Laaa: nop; ret;", options(noreturn)) }
| ^^^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:165:24
--> $DIR/named-asm-labels.rs:167:24
|
LL | unsafe { asm!(".Lbbb: nop; ret;", options(noreturn)) }
| ^^^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:174:15
--> $DIR/named-asm-labels.rs:176:15
|
LL | asm!("closure1: nop");
| ^^^^^^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:178:15
--> $DIR/named-asm-labels.rs:180:15
|
LL | asm!("closure2: nop");
| ^^^^^^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: avoid using named labels in inline assembly
--> $DIR/named-asm-labels.rs:188:19
--> $DIR/named-asm-labels.rs:190:19
|
LL | asm!("closure3: nop");
| ^^^^^^^^
|
= help: only local labels of the form `<number>:` should be used in inline asm
= note: see the asm section of the unstable book <https://doc.rust-lang.org/nightly/unstable-book/library-features/asm.html#labels> for more information
error: aborting due to 35 previous errors; 1 warning emitted

View file

@ -1,9 +1,11 @@
// needs-asm-support
// check-pass
#![feature(asm, never_type)]
#![feature(never_type)]
#![crate_type = "rlib"]
use std::arch::asm;
pub unsafe fn asm1() {
let _: () = asm!("");
}

View file

@ -3,7 +3,9 @@
// ignore-spirv
// ignore-wasm32
#![feature(asm, global_asm, asm_const)]
#![feature(asm_const)]
use std::arch::{asm, global_asm};
fn main() {
unsafe {

View file

@ -1,5 +1,5 @@
error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/type-check-1.rs:37:26
--> $DIR/type-check-1.rs:39:26
|
LL | let x = 0;
| ----- help: consider using `const` instead of `let`: `const x`
@ -8,7 +8,7 @@ LL | asm!("{}", const x);
| ^ non-constant value
error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/type-check-1.rs:40:36
--> $DIR/type-check-1.rs:42:36
|
LL | let x = 0;
| ----- help: consider using `const` instead of `let`: `const x`
@ -17,7 +17,7 @@ LL | asm!("{}", const const_foo(x));
| ^ non-constant value
error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/type-check-1.rs:43:36
--> $DIR/type-check-1.rs:45:36
|
LL | let x = 0;
| ----- help: consider using `const` instead of `let`: `const x`
@ -26,13 +26,13 @@ LL | asm!("{}", const const_bar(x));
| ^ non-constant value
error[E0308]: mismatched types
--> $DIR/type-check-1.rs:51:26
--> $DIR/type-check-1.rs:53:26
|
LL | asm!("{}", const 0f32);
| ^^^^ expected integer, found `f32`
error[E0308]: mismatched types
--> $DIR/type-check-1.rs:53:26
--> $DIR/type-check-1.rs:55:26
|
LL | asm!("{}", const 0 as *mut u8);
| ^^^^^^^^^^^^ expected integer, found *-ptr
@ -41,7 +41,7 @@ LL | asm!("{}", const 0 as *mut u8);
found raw pointer `*mut u8`
error[E0308]: mismatched types
--> $DIR/type-check-1.rs:55:26
--> $DIR/type-check-1.rs:57:26
|
LL | asm!("{}", const &0);
| ^^ expected integer, found `&{integer}`
@ -53,19 +53,19 @@ LL + asm!("{}", const 0);
|
error: invalid asm output
--> $DIR/type-check-1.rs:13:29
--> $DIR/type-check-1.rs:15:29
|
LL | asm!("{}", out(reg) 1 + 2);
| ^^^^^ cannot assign to this expression
error: invalid asm output
--> $DIR/type-check-1.rs:15:31
--> $DIR/type-check-1.rs:17:31
|
LL | asm!("{}", inout(reg) 1 + 2);
| ^^^^^ cannot assign to this expression
error[E0277]: the size for values of type `[u64]` cannot be known at compilation time
--> $DIR/type-check-1.rs:21:28
--> $DIR/type-check-1.rs:23:28
|
LL | asm!("{}", in(reg) v[..]);
| ^^^^^ doesn't have a size known at compile-time
@ -74,7 +74,7 @@ LL | asm!("{}", in(reg) v[..]);
= note: all inline asm arguments must have a statically known size
error[E0277]: the size for values of type `[u64]` cannot be known at compilation time
--> $DIR/type-check-1.rs:23:29
--> $DIR/type-check-1.rs:25:29
|
LL | asm!("{}", out(reg) v[..]);
| ^^^^^ doesn't have a size known at compile-time
@ -83,7 +83,7 @@ LL | asm!("{}", out(reg) v[..]);
= note: all inline asm arguments must have a statically known size
error[E0277]: the size for values of type `[u64]` cannot be known at compilation time
--> $DIR/type-check-1.rs:25:31
--> $DIR/type-check-1.rs:27:31
|
LL | asm!("{}", inout(reg) v[..]);
| ^^^^^ doesn't have a size known at compile-time
@ -92,13 +92,13 @@ LL | asm!("{}", inout(reg) v[..]);
= note: all inline asm arguments must have a statically known size
error[E0308]: mismatched types
--> $DIR/type-check-1.rs:65:25
--> $DIR/type-check-1.rs:67:25
|
LL | global_asm!("{}", const 0f32);
| ^^^^ expected integer, found `f32`
error[E0308]: mismatched types
--> $DIR/type-check-1.rs:67:25
--> $DIR/type-check-1.rs:69:25
|
LL | global_asm!("{}", const 0 as *mut u8);
| ^^^^^^^^^^^^ expected integer, found *-ptr

View file

@ -3,7 +3,7 @@
// ignore-spirv
// ignore-wasm32
#![feature(asm)]
use std::arch::asm;
fn main() {
unsafe {

View file

@ -1,9 +1,9 @@
// needs-asm-support
// only-x86_64
// checks various modes of failure for the `clobber_abi` argument (after parsing)
use std::arch::asm;
#![feature(asm)]
// checks various modes of failure for the `clobber_abi` argument (after parsing)
fn main() {
unsafe {

View file

@ -1,6 +1,6 @@
// only-x86_64
#![feature(asm, global_asm)]
use std::arch::{asm, global_asm};
fn main() {
let mut foo = 0;

View file

@ -1,7 +1,9 @@
// only-x86_64
// compile-flags: -C target-feature=+avx2
#![feature(asm, asm_const, asm_sym)]
#![feature(asm_const, asm_sym)]
use std::arch::asm;
fn main() {
let mut foo = 0;

View file

@ -1,17 +1,17 @@
error: invalid register class `foo`: unknown register class
--> $DIR/bad-reg.rs:12:20
--> $DIR/bad-reg.rs:14:20
|
LL | asm!("{}", in(foo) foo);
| ^^^^^^^^^^^
error: invalid register `foo`: unknown register
--> $DIR/bad-reg.rs:14:18
--> $DIR/bad-reg.rs:16:18
|
LL | asm!("", in("foo") foo);
| ^^^^^^^^^^^^^
error: invalid asm template modifier for this register class
--> $DIR/bad-reg.rs:16:15
--> $DIR/bad-reg.rs:18:15
|
LL | asm!("{:z}", in(reg) foo);
| ^^^^ ----------- argument
@ -21,7 +21,7 @@ LL | asm!("{:z}", in(reg) foo);
= note: the `reg` register class supports the following template modifiers: `l`, `x`, `e`, `r`
error: invalid asm template modifier for this register class
--> $DIR/bad-reg.rs:18:15
--> $DIR/bad-reg.rs:20:15
|
LL | asm!("{:r}", in(xmm_reg) foo);
| ^^^^ --------------- argument
@ -31,7 +31,7 @@ LL | asm!("{:r}", in(xmm_reg) foo);
= note: the `xmm_reg` register class supports the following template modifiers: `x`, `y`, `z`
error: asm template modifiers are not allowed for `const` arguments
--> $DIR/bad-reg.rs:20:15
--> $DIR/bad-reg.rs:22:15
|
LL | asm!("{:a}", const 0);
| ^^^^ ------- argument
@ -39,7 +39,7 @@ LL | asm!("{:a}", const 0);
| template modifier
error: asm template modifiers are not allowed for `sym` arguments
--> $DIR/bad-reg.rs:22:15
--> $DIR/bad-reg.rs:24:15
|
LL | asm!("{:a}", sym main);
| ^^^^ -------- argument
@ -47,73 +47,73 @@ LL | asm!("{:a}", sym main);
| template modifier
error: invalid register `ebp`: the frame pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:24:18
--> $DIR/bad-reg.rs:26:18
|
LL | asm!("", in("ebp") foo);
| ^^^^^^^^^^^^^
error: invalid register `rsp`: the stack pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:26:18
--> $DIR/bad-reg.rs:28:18
|
LL | asm!("", in("rsp") foo);
| ^^^^^^^^^^^^^
error: invalid register `ip`: the instruction pointer cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:28:18
--> $DIR/bad-reg.rs:30:18
|
LL | asm!("", in("ip") foo);
| ^^^^^^^^^^^^
error: invalid register `k0`: the k0 AVX mask register cannot be used as an operand for inline asm
--> $DIR/bad-reg.rs:30:18
--> $DIR/bad-reg.rs:32:18
|
LL | asm!("", in("k0") foo);
| ^^^^^^^^^^^^
error: invalid register `ah`: high byte registers cannot be used as an operand on x86_64
--> $DIR/bad-reg.rs:32:18
--> $DIR/bad-reg.rs:34:18
|
LL | asm!("", in("ah") foo);
| ^^^^^^^^^^^^
error: register class `x87_reg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:35:18
--> $DIR/bad-reg.rs:37:18
|
LL | asm!("", in("st(2)") foo);
| ^^^^^^^^^^^^^^^
error: register class `mmx_reg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:37:18
--> $DIR/bad-reg.rs:39:18
|
LL | asm!("", in("mm0") foo);
| ^^^^^^^^^^^^^
error: register class `x87_reg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:41:20
--> $DIR/bad-reg.rs:43:20
|
LL | asm!("{}", in(x87_reg) foo);
| ^^^^^^^^^^^^^^^
error: register class `mmx_reg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:43:20
--> $DIR/bad-reg.rs:45:20
|
LL | asm!("{}", in(mmx_reg) foo);
| ^^^^^^^^^^^^^^^
error: register class `x87_reg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:45:20
--> $DIR/bad-reg.rs:47:20
|
LL | asm!("{}", out(x87_reg) _);
| ^^^^^^^^^^^^^^
error: register class `mmx_reg` can only be used as a clobber, not as an input or output
--> $DIR/bad-reg.rs:47:20
--> $DIR/bad-reg.rs:49:20
|
LL | asm!("{}", out(mmx_reg) _);
| ^^^^^^^^^^^^^^
error: register `al` conflicts with register `ax`
--> $DIR/bad-reg.rs:53:33
--> $DIR/bad-reg.rs:55:33
|
LL | asm!("", in("eax") foo, in("al") bar);
| ------------- ^^^^^^^^^^^^ register `al`
@ -121,7 +121,7 @@ LL | asm!("", in("eax") foo, in("al") bar);
| register `ax`
error: register `ax` conflicts with register `ax`
--> $DIR/bad-reg.rs:55:33
--> $DIR/bad-reg.rs:57:33
|
LL | asm!("", in("rax") foo, out("rax") bar);
| ------------- ^^^^^^^^^^^^^^ register `ax`
@ -129,13 +129,13 @@ LL | asm!("", in("rax") foo, out("rax") bar);
| register `ax`
|
help: use `lateout` instead of `out` to avoid conflict
--> $DIR/bad-reg.rs:55:18
--> $DIR/bad-reg.rs:57:18
|
LL | asm!("", in("rax") foo, out("rax") bar);
| ^^^^^^^^^^^^^
error: register `ymm0` conflicts with register `xmm0`
--> $DIR/bad-reg.rs:58:34
--> $DIR/bad-reg.rs:60:34
|
LL | asm!("", in("xmm0") foo, in("ymm0") bar);
| -------------- ^^^^^^^^^^^^^^ register `ymm0`
@ -143,7 +143,7 @@ LL | asm!("", in("xmm0") foo, in("ymm0") bar);
| register `xmm0`
error: register `ymm0` conflicts with register `xmm0`
--> $DIR/bad-reg.rs:60:34
--> $DIR/bad-reg.rs:62:34
|
LL | asm!("", in("xmm0") foo, out("ymm0") bar);
| -------------- ^^^^^^^^^^^^^^^ register `ymm0`
@ -151,7 +151,7 @@ LL | asm!("", in("xmm0") foo, out("ymm0") bar);
| register `xmm0`
|
help: use `lateout` instead of `out` to avoid conflict
--> $DIR/bad-reg.rs:60:18
--> $DIR/bad-reg.rs:62:18
|
LL | asm!("", in("xmm0") foo, out("ymm0") bar);
| ^^^^^^^^^^^^^^

View file

@ -3,7 +3,9 @@
// revisions: mirunsafeck thirunsafeck
// [thirunsafeck]compile-flags: -Z thir-unsafeck
#![feature(asm, global_asm, asm_const)]
#![feature(asm_const)]
use std::arch::{asm, global_asm};
fn const_generic<const X: usize>() -> usize {
unsafe {

View file

@ -1,7 +1,7 @@
// only-x86_64
// run-rustfix
#![feature(asm, global_asm)]
use std::arch::{asm, global_asm};
fn main() {
unsafe {
@ -19,8 +19,8 @@ fn main() {
"",
options(nomem, noreturn),
options(att_syntax, ), //~ ERROR the `noreturn` option was already provided
options( nostack), //~ ERROR the `nomem` option was already provided
options(), //~ ERROR the `noreturn` option was already provided
options( nostack), //~ ERROR the `nomem` option was already provided
options(), //~ ERROR the `noreturn` option was already provided
);
}
}

View file

@ -1,7 +1,7 @@
// only-x86_64
// run-rustfix
#![feature(asm, global_asm)]
use std::arch::{asm, global_asm};
fn main() {
unsafe {
@ -19,8 +19,8 @@ fn main() {
"",
options(nomem, noreturn),
options(att_syntax, noreturn), //~ ERROR the `noreturn` option was already provided
options(nomem, nostack), //~ ERROR the `nomem` option was already provided
options(noreturn), //~ ERROR the `noreturn` option was already provided
options(nomem, nostack), //~ ERROR the `nomem` option was already provided
options(noreturn), //~ ERROR the `noreturn` option was already provided
);
}
}

View file

@ -1,6 +1,6 @@
// only-x86_64
#![feature(asm)]
use std::arch::asm;
macro_rules! m {
($in:ident $out:ident $lateout:ident $inout:ident $inlateout:ident $const:ident $sym:ident

View file

@ -1,9 +1,10 @@
// only-x86_64
// Make sure rustc doesn't ICE on asm! for a foreign architecture.
#![feature(asm)]
#![crate_type = "rlib"]
use std::arch::asm;
pub unsafe fn aarch64(a: f64, b: f64) -> f64 {
let c;
asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {

View file

@ -1,17 +1,17 @@
error: invalid register class `vreg`: unknown register class
--> $DIR/issue-82869.rs:9:32
--> $DIR/issue-82869.rs:10:32
|
LL | asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {
| ^^^^^^^^^^^
error: invalid register class `vreg`: unknown register class
--> $DIR/issue-82869.rs:9:45
--> $DIR/issue-82869.rs:10:45
|
LL | asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {
| ^^^^^^^^^^
error: invalid register `d0`: unknown register
--> $DIR/issue-82869.rs:9:57
--> $DIR/issue-82869.rs:10:57
|
LL | asm!("add {:d}, {:d}, d0", out(vreg) c, in(vreg) a, in("d0") {
| _________________________________________________________^

View file

@ -1,7 +1,9 @@
// build-pass
// only-x86_64
#![feature(asm, target_feature_11)]
#![feature(target_feature_11)]
use std::arch::asm;
#[target_feature(enable = "avx")]
fn main() {

View file

@ -3,8 +3,9 @@
// run-pass
// needs-asm-support
#![feature(asm, asm_sym, asm_unwind)]
#![feature(asm_sym, asm_unwind)]
use std::arch::asm;
use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe};
struct Foo<'a>(&'a mut bool);

View file

@ -4,7 +4,9 @@
// Checks that multiple clobber_abi options can be used
#![feature(asm, asm_sym)]
#![feature(asm_sym)]
use std::arch::asm;
extern "sysv64" fn foo(x: i32) -> i32 {
x + 16

View file

@ -1,6 +1,8 @@
// only-x86_64
#![feature(asm, global_asm, asm_const)]
#![feature(asm_const)]
use std::arch::{asm, global_asm};
fn main() {
let mut foo = 0;

View file

@ -1,89 +1,89 @@
error: requires at least a template string argument
--> $DIR/parse-error.rs:9:9
--> $DIR/parse-error.rs:11:9
|
LL | asm!();
| ^^^^^^
error: asm template must be a string literal
--> $DIR/parse-error.rs:11:14
--> $DIR/parse-error.rs:13:14
|
LL | asm!(foo);
| ^^^
error: expected token: `,`
--> $DIR/parse-error.rs:13:19
--> $DIR/parse-error.rs:15:19
|
LL | asm!("{}" foo);
| ^^^ expected `,`
error: expected operand, clobber_abi, options, or additional template string
--> $DIR/parse-error.rs:15:20
--> $DIR/parse-error.rs:17:20
|
LL | asm!("{}", foo);
| ^^^ expected operand, clobber_abi, options, or additional template string
error: expected `(`, found `foo`
--> $DIR/parse-error.rs:17:23
--> $DIR/parse-error.rs:19:23
|
LL | asm!("{}", in foo);
| ^^^ expected `(`
error: expected `)`, found `foo`
--> $DIR/parse-error.rs:19:27
--> $DIR/parse-error.rs:21:27
|
LL | asm!("{}", in(reg foo));
| ^^^ expected `)`
error: expected expression, found end of macro arguments
--> $DIR/parse-error.rs:21:27
--> $DIR/parse-error.rs:23:27
|
LL | asm!("{}", in(reg));
| ^ expected expression
error: expected register class or explicit register
--> $DIR/parse-error.rs:23:26
--> $DIR/parse-error.rs:25:26
|
LL | asm!("{}", inout(=) foo => bar);
| ^
error: expected expression, found end of macro arguments
--> $DIR/parse-error.rs:25:37
--> $DIR/parse-error.rs:27:37
|
LL | asm!("{}", inout(reg) foo =>);
| ^ expected expression
error: expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>`
--> $DIR/parse-error.rs:27:32
--> $DIR/parse-error.rs:29:32
|
LL | asm!("{}", in(reg) foo => bar);
| ^^ expected one of 7 possible tokens
error: argument to `sym` must be a path expression
--> $DIR/parse-error.rs:29:24
--> $DIR/parse-error.rs:31:24
|
LL | asm!("{}", sym foo + bar);
| ^^^^^^^^^
error: expected one of `)`, `att_syntax`, `may_unwind`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo`
--> $DIR/parse-error.rs:31:26
--> $DIR/parse-error.rs:33:26
|
LL | asm!("", options(foo));
| ^^^ expected one of 10 possible tokens
error: expected one of `)` or `,`, found `foo`
--> $DIR/parse-error.rs:33:32
--> $DIR/parse-error.rs:35:32
|
LL | asm!("", options(nomem foo));
| ^^^ expected one of `)` or `,`
error: expected one of `)`, `att_syntax`, `may_unwind`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, `raw`, or `readonly`, found `foo`
--> $DIR/parse-error.rs:35:33
--> $DIR/parse-error.rs:37:33
|
LL | asm!("", options(nomem, foo));
| ^^^ expected one of 10 possible tokens
error: arguments are not allowed after options
--> $DIR/parse-error.rs:37:31
--> $DIR/parse-error.rs:39:31
|
LL | asm!("{}", options(), const foo);
| --------- ^^^^^^^^^ argument
@ -91,31 +91,31 @@ LL | asm!("{}", options(), const foo);
| previous options
error: at least one abi must be provided as an argument to `clobber_abi`
--> $DIR/parse-error.rs:40:30
--> $DIR/parse-error.rs:42:30
|
LL | asm!("", clobber_abi());
| ^
error: expected string literal
--> $DIR/parse-error.rs:42:30
--> $DIR/parse-error.rs:44:30
|
LL | asm!("", clobber_abi(foo));
| ^^^ not a string literal
error: expected one of `)` or `,`, found `foo`
--> $DIR/parse-error.rs:44:34
--> $DIR/parse-error.rs:46:34
|
LL | asm!("", clobber_abi("C" foo));
| ^^^ expected one of `)` or `,`
error: expected string literal
--> $DIR/parse-error.rs:46:35
--> $DIR/parse-error.rs:48:35
|
LL | asm!("", clobber_abi("C", foo));
| ^^^ not a string literal
error: arguments are not allowed after clobber_abi
--> $DIR/parse-error.rs:48:38
--> $DIR/parse-error.rs:50:38
|
LL | asm!("{}", clobber_abi("C"), const foo);
| ---------------- ^^^^^^^^^ argument
@ -123,7 +123,7 @@ LL | asm!("{}", clobber_abi("C"), const foo);
| clobber_abi
error: clobber_abi is not allowed after options
--> $DIR/parse-error.rs:51:29
--> $DIR/parse-error.rs:53:29
|
LL | asm!("", options(), clobber_abi("C"));
| --------- ^^^^^^^^^^^^^^^^
@ -131,7 +131,7 @@ LL | asm!("", options(), clobber_abi("C"));
| options
error: clobber_abi is not allowed after options
--> $DIR/parse-error.rs:53:31
--> $DIR/parse-error.rs:55:31
|
LL | asm!("{}", options(), clobber_abi("C"), const foo);
| --------- ^^^^^^^^^^^^^^^^
@ -139,7 +139,7 @@ LL | asm!("{}", options(), clobber_abi("C"), const foo);
| options
error: duplicate argument named `a`
--> $DIR/parse-error.rs:55:36
--> $DIR/parse-error.rs:57:36
|
LL | asm!("{a}", a = const foo, a = const bar);
| ------------- ^^^^^^^^^^^^^ duplicate argument
@ -147,7 +147,7 @@ LL | asm!("{a}", a = const foo, a = const bar);
| previously here
error: argument never used
--> $DIR/parse-error.rs:55:36
--> $DIR/parse-error.rs:57:36
|
LL | asm!("{a}", a = const foo, a = const bar);
| ^^^^^^^^^^^^^ argument never used
@ -155,13 +155,13 @@ LL | asm!("{a}", a = const foo, a = const bar);
= help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"`
error: explicit register arguments cannot have names
--> $DIR/parse-error.rs:60:18
--> $DIR/parse-error.rs:62:18
|
LL | asm!("", a = in("eax") foo);
| ^^^^^^^^^^^^^^^^^
error: named arguments cannot follow explicit register arguments
--> $DIR/parse-error.rs:62:36
--> $DIR/parse-error.rs:64:36
|
LL | asm!("{a}", in("eax") foo, a = const bar);
| ------------- ^^^^^^^^^^^^^ named argument
@ -169,7 +169,7 @@ LL | asm!("{a}", in("eax") foo, a = const bar);
| explicit register argument
error: named arguments cannot follow explicit register arguments
--> $DIR/parse-error.rs:65:36
--> $DIR/parse-error.rs:67:36
|
LL | asm!("{a}", in("eax") foo, a = const bar);
| ------------- ^^^^^^^^^^^^^ named argument
@ -177,7 +177,7 @@ LL | asm!("{a}", in("eax") foo, a = const bar);
| explicit register argument
error: positional arguments cannot follow named arguments or explicit register arguments
--> $DIR/parse-error.rs:68:36
--> $DIR/parse-error.rs:70:36
|
LL | asm!("{1}", in("eax") foo, const bar);
| ------------- ^^^^^^^^^ positional argument
@ -185,19 +185,19 @@ LL | asm!("{1}", in("eax") foo, const bar);
| explicit register argument
error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `""`
--> $DIR/parse-error.rs:71:29
--> $DIR/parse-error.rs:73:29
|
LL | asm!("", options(), "");
| ^^ expected one of 9 possible tokens
error: expected one of `clobber_abi`, `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `"{}"`
--> $DIR/parse-error.rs:73:33
--> $DIR/parse-error.rs:75:33
|
LL | asm!("{}", in(reg) foo, "{}", out(reg) foo);
| ^^^^ expected one of 9 possible tokens
error: asm template must be a string literal
--> $DIR/parse-error.rs:75:14
--> $DIR/parse-error.rs:77:14
|
LL | asm!(format!("{{{}}}", 0), in(reg) foo);
| ^^^^^^^^^^^^^^^^^^^^
@ -205,7 +205,7 @@ LL | asm!(format!("{{{}}}", 0), in(reg) foo);
= note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
error: asm template must be a string literal
--> $DIR/parse-error.rs:77:21
--> $DIR/parse-error.rs:79:21
|
LL | asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar);
| ^^^^^^^^^^^^^^^^^^^^
@ -213,79 +213,79 @@ LL | asm!("{1}", format!("{{{}}}", 0), in(reg) foo, out(reg) bar);
= note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
error: _ cannot be used for input operands
--> $DIR/parse-error.rs:79:28
--> $DIR/parse-error.rs:81:28
|
LL | asm!("{}", in(reg) _);
| ^
error: _ cannot be used for input operands
--> $DIR/parse-error.rs:81:31
--> $DIR/parse-error.rs:83:31
|
LL | asm!("{}", inout(reg) _);
| ^
error: _ cannot be used for input operands
--> $DIR/parse-error.rs:83:35
--> $DIR/parse-error.rs:85:35
|
LL | asm!("{}", inlateout(reg) _);
| ^
error: requires at least a template string argument
--> $DIR/parse-error.rs:90:1
--> $DIR/parse-error.rs:92:1
|
LL | global_asm!();
| ^^^^^^^^^^^^^
error: asm template must be a string literal
--> $DIR/parse-error.rs:92:13
--> $DIR/parse-error.rs:94:13
|
LL | global_asm!(FOO);
| ^^^
error: expected token: `,`
--> $DIR/parse-error.rs:94:18
--> $DIR/parse-error.rs:96:18
|
LL | global_asm!("{}" FOO);
| ^^^ expected `,`
error: expected operand, options, or additional template string
--> $DIR/parse-error.rs:96:19
--> $DIR/parse-error.rs:98:19
|
LL | global_asm!("{}", FOO);
| ^^^ expected operand, options, or additional template string
error: expected expression, found end of macro arguments
--> $DIR/parse-error.rs:98:24
--> $DIR/parse-error.rs:100:24
|
LL | global_asm!("{}", const);
| ^ expected expression
error: expected one of `,`, `.`, `?`, or an operator, found `FOO`
--> $DIR/parse-error.rs:100:30
--> $DIR/parse-error.rs:102:30
|
LL | global_asm!("{}", const(reg) FOO);
| ^^^ expected one of `,`, `.`, `?`, or an operator
error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `FOO`
--> $DIR/parse-error.rs:102:25
--> $DIR/parse-error.rs:104:25
|
LL | global_asm!("", options(FOO));
| ^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw`
error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `nomem`
--> $DIR/parse-error.rs:104:25
--> $DIR/parse-error.rs:106:25
|
LL | global_asm!("", options(nomem FOO));
| ^^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw`
error: expected one of `)`, `att_syntax`, `may_unwind`, or `raw`, found `nomem`
--> $DIR/parse-error.rs:106:25
--> $DIR/parse-error.rs:108:25
|
LL | global_asm!("", options(nomem, FOO));
| ^^^^^ expected one of `)`, `att_syntax`, `may_unwind`, or `raw`
error: arguments are not allowed after options
--> $DIR/parse-error.rs:108:30
--> $DIR/parse-error.rs:110:30
|
LL | global_asm!("{}", options(), const FOO);
| --------- ^^^^^^^^^ argument
@ -293,25 +293,25 @@ LL | global_asm!("{}", options(), const FOO);
| previous options
error: expected string literal
--> $DIR/parse-error.rs:110:29
--> $DIR/parse-error.rs:112:29
|
LL | global_asm!("", clobber_abi(FOO));
| ^^^ not a string literal
error: expected one of `)` or `,`, found `FOO`
--> $DIR/parse-error.rs:112:33
--> $DIR/parse-error.rs:114:33
|
LL | global_asm!("", clobber_abi("C" FOO));
| ^^^ expected one of `)` or `,`
error: expected string literal
--> $DIR/parse-error.rs:114:34
--> $DIR/parse-error.rs:116:34
|
LL | global_asm!("", clobber_abi("C", FOO));
| ^^^ not a string literal
error: arguments are not allowed after clobber_abi
--> $DIR/parse-error.rs:116:37
--> $DIR/parse-error.rs:118:37
|
LL | global_asm!("{}", clobber_abi("C"), const FOO);
| ---------------- ^^^^^^^^^ argument
@ -319,13 +319,13 @@ LL | global_asm!("{}", clobber_abi("C"), const FOO);
| clobber_abi
error: `clobber_abi` cannot be used with `global_asm!`
--> $DIR/parse-error.rs:116:19
--> $DIR/parse-error.rs:118:19
|
LL | global_asm!("{}", clobber_abi("C"), const FOO);
| ^^^^^^^^^^^^^^^^
error: clobber_abi is not allowed after options
--> $DIR/parse-error.rs:119:28
--> $DIR/parse-error.rs:121:28
|
LL | global_asm!("", options(), clobber_abi("C"));
| --------- ^^^^^^^^^^^^^^^^
@ -333,7 +333,7 @@ LL | global_asm!("", options(), clobber_abi("C"));
| options
error: clobber_abi is not allowed after options
--> $DIR/parse-error.rs:121:30
--> $DIR/parse-error.rs:123:30
|
LL | global_asm!("{}", options(), clobber_abi("C"), const FOO);
| --------- ^^^^^^^^^^^^^^^^
@ -341,13 +341,13 @@ LL | global_asm!("{}", options(), clobber_abi("C"), const FOO);
| options
error: `clobber_abi` cannot be used with `global_asm!`
--> $DIR/parse-error.rs:123:17
--> $DIR/parse-error.rs:125:17
|
LL | global_asm!("", clobber_abi("C"), clobber_abi("C"));
| ^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
error: duplicate argument named `a`
--> $DIR/parse-error.rs:125:35
--> $DIR/parse-error.rs:127:35
|
LL | global_asm!("{a}", a = const FOO, a = const BAR);
| ------------- ^^^^^^^^^^^^^ duplicate argument
@ -355,7 +355,7 @@ LL | global_asm!("{a}", a = const FOO, a = const BAR);
| previously here
error: argument never used
--> $DIR/parse-error.rs:125:35
--> $DIR/parse-error.rs:127:35
|
LL | global_asm!("{a}", a = const FOO, a = const BAR);
| ^^^^^^^^^^^^^ argument never used
@ -363,19 +363,19 @@ LL | global_asm!("{a}", a = const FOO, a = const BAR);
= help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {1} */"`
error: expected one of `clobber_abi`, `const`, or `options`, found `""`
--> $DIR/parse-error.rs:128:28
--> $DIR/parse-error.rs:130:28
|
LL | global_asm!("", options(), "");
| ^^ expected one of `clobber_abi`, `const`, or `options`
error: expected one of `clobber_abi`, `const`, or `options`, found `"{}"`
--> $DIR/parse-error.rs:130:30
--> $DIR/parse-error.rs:132:30
|
LL | global_asm!("{}", const FOO, "{}", const FOO);
| ^^^^ expected one of `clobber_abi`, `const`, or `options`
error: asm template must be a string literal
--> $DIR/parse-error.rs:132:13
--> $DIR/parse-error.rs:134:13
|
LL | global_asm!(format!("{{{}}}", 0), const FOO);
| ^^^^^^^^^^^^^^^^^^^^
@ -383,7 +383,7 @@ LL | global_asm!(format!("{{{}}}", 0), const FOO);
= note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
error: asm template must be a string literal
--> $DIR/parse-error.rs:134:20
--> $DIR/parse-error.rs:136:20
|
LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR);
| ^^^^^^^^^^^^^^^^^^^^
@ -391,7 +391,7 @@ LL | global_asm!("{1}", format!("{{{}}}", 0), const FOO, const BAR);
= note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/parse-error.rs:37:37
--> $DIR/parse-error.rs:39:37
|
LL | let mut foo = 0;
| ---------- help: consider using `const` instead of `let`: `const foo`
@ -400,7 +400,7 @@ LL | asm!("{}", options(), const foo);
| ^^^ non-constant value
error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/parse-error.rs:48:44
--> $DIR/parse-error.rs:50:44
|
LL | let mut foo = 0;
| ---------- help: consider using `const` instead of `let`: `const foo`
@ -409,7 +409,7 @@ LL | asm!("{}", clobber_abi("C"), const foo);
| ^^^ non-constant value
error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/parse-error.rs:55:31
--> $DIR/parse-error.rs:57:31
|
LL | let mut foo = 0;
| ---------- help: consider using `const` instead of `let`: `const foo`
@ -418,7 +418,7 @@ LL | asm!("{a}", a = const foo, a = const bar);
| ^^^ non-constant value
error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/parse-error.rs:55:46
--> $DIR/parse-error.rs:57:46
|
LL | let mut bar = 0;
| ---------- help: consider using `const` instead of `let`: `const bar`
@ -427,7 +427,7 @@ LL | asm!("{a}", a = const foo, a = const bar);
| ^^^ non-constant value
error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/parse-error.rs:62:46
--> $DIR/parse-error.rs:64:46
|
LL | let mut bar = 0;
| ---------- help: consider using `const` instead of `let`: `const bar`
@ -436,7 +436,7 @@ LL | asm!("{a}", in("eax") foo, a = const bar);
| ^^^ non-constant value
error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/parse-error.rs:65:46
--> $DIR/parse-error.rs:67:46
|
LL | let mut bar = 0;
| ---------- help: consider using `const` instead of `let`: `const bar`
@ -445,7 +445,7 @@ LL | asm!("{a}", in("eax") foo, a = const bar);
| ^^^ non-constant value
error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/parse-error.rs:68:42
--> $DIR/parse-error.rs:70:42
|
LL | let mut bar = 0;
| ---------- help: consider using `const` instead of `let`: `const bar`

View file

@ -1,7 +1,8 @@
// only-x86_64
// build-fail
// compile-flags: -Ccodegen-units=1
#![feature(asm)]
use std::arch::asm;
// Checks that inline asm errors are mapped to the correct line in the source code.

View file

@ -1,5 +1,5 @@
error: invalid instruction mnemonic 'invalid_instruction'
--> $DIR/srcloc.rs:10:15
--> $DIR/srcloc.rs:11:15
|
LL | asm!("invalid_instruction");
| ^
@ -11,7 +11,7 @@ LL | invalid_instruction
| ^^^^^^^^^^^^^^^^^^^
error: invalid instruction mnemonic 'invalid_instruction'
--> $DIR/srcloc.rs:14:13
--> $DIR/srcloc.rs:15:13
|
LL | invalid_instruction
| ^
@ -23,7 +23,7 @@ LL | invalid_instruction
| ^^^^^^^^^^^^^^^^^^^
error: invalid instruction mnemonic 'invalid_instruction'
--> $DIR/srcloc.rs:19:13
--> $DIR/srcloc.rs:20:13
|
LL | invalid_instruction
| ^
@ -35,7 +35,7 @@ LL | invalid_instruction
| ^^^^^^^^^^^^^^^^^^^
error: invalid instruction mnemonic 'invalid_instruction'
--> $DIR/srcloc.rs:25:13
--> $DIR/srcloc.rs:26:13
|
LL | invalid_instruction
| ^
@ -47,7 +47,7 @@ LL | invalid_instruction
| ^^^^^^^^^^^^^^^^^^^
error: invalid instruction mnemonic 'invalid_instruction'
--> $DIR/srcloc.rs:32:13
--> $DIR/srcloc.rs:33:13
|
LL | invalid_instruction
| ^
@ -59,7 +59,7 @@ LL | invalid_instruction
| ^^^^^^^^^^^^^^^^^^^
error: invalid instruction mnemonic 'invalid_instruction'
--> $DIR/srcloc.rs:37:14
--> $DIR/srcloc.rs:38:14
|
LL | asm!(concat!("invalid", "_", "instruction"));
| ^
@ -71,7 +71,7 @@ LL | invalid_instruction
| ^^^^^^^^^^^^^^^^^^^
warning: scale factor without index register is ignored
--> $DIR/srcloc.rs:40:15
--> $DIR/srcloc.rs:41:15
|
LL | asm!("movaps %xmm3, (%esi, 2)", options(att_syntax));
| ^
@ -83,7 +83,7 @@ LL | movaps %xmm3, (%esi, 2)
| ^
error: invalid instruction mnemonic 'invalid_instruction'
--> $DIR/srcloc.rs:44:14
--> $DIR/srcloc.rs:45:14
|
LL | "invalid_instruction",
| ^
@ -95,7 +95,7 @@ LL | invalid_instruction
| ^^^^^^^^^^^^^^^^^^^
error: invalid instruction mnemonic 'invalid_instruction'
--> $DIR/srcloc.rs:50:14
--> $DIR/srcloc.rs:51:14
|
LL | "invalid_instruction",
| ^
@ -107,7 +107,7 @@ LL | invalid_instruction
| ^^^^^^^^^^^^^^^^^^^
error: invalid instruction mnemonic 'invalid_instruction'
--> $DIR/srcloc.rs:57:14
--> $DIR/srcloc.rs:58:14
|
LL | "invalid_instruction",
| ^
@ -119,7 +119,7 @@ LL | invalid_instruction
| ^^^^^^^^^^^^^^^^^^^
error: invalid instruction mnemonic 'invalid_instruction'
--> $DIR/srcloc.rs:64:13
--> $DIR/srcloc.rs:65:13
|
LL | concat!("invalid", "_", "instruction"),
| ^
@ -131,7 +131,7 @@ LL | invalid_instruction
| ^^^^^^^^^^^^^^^^^^^
error: invalid instruction mnemonic 'invalid_instruction'
--> $DIR/srcloc.rs:71:13
--> $DIR/srcloc.rs:72:13
|
LL | concat!("invalid", "_", "instruction"),
| ^
@ -143,7 +143,7 @@ LL | invalid_instruction
| ^^^^^^^^^^^^^^^^^^^
error: invalid instruction mnemonic 'invalid_instruction1'
--> $DIR/srcloc.rs:78:14
--> $DIR/srcloc.rs:79:14
|
LL | "invalid_instruction1",
| ^
@ -155,7 +155,7 @@ LL | invalid_instruction1
| ^^^^^^^^^^^^^^^^^^^^
error: invalid instruction mnemonic 'invalid_instruction2'
--> $DIR/srcloc.rs:79:14
--> $DIR/srcloc.rs:80:14
|
LL | "invalid_instruction2",
| ^
@ -167,7 +167,7 @@ LL | invalid_instruction2
| ^^^^^^^^^^^^^^^^^^^^
error: invalid instruction mnemonic 'invalid_instruction1'
--> $DIR/srcloc.rs:85:13
--> $DIR/srcloc.rs:86:13
|
LL | concat!(
| ^
@ -179,7 +179,7 @@ LL | invalid_instruction1
| ^^^^^^^^^^^^^^^^^^^^
error: invalid instruction mnemonic 'invalid_instruction2'
--> $DIR/srcloc.rs:85:13
--> $DIR/srcloc.rs:86:13
|
LL | concat!(
| ^
@ -191,7 +191,7 @@ LL | invalid_instruction2
| ^^^^^^^^^^^^^^^^^^^^
error: invalid instruction mnemonic 'invalid_instruction1'
--> $DIR/srcloc.rs:94:13
--> $DIR/srcloc.rs:95:13
|
LL | concat!(
| ^
@ -203,7 +203,7 @@ LL | invalid_instruction1
| ^^^^^^^^^^^^^^^^^^^^
error: invalid instruction mnemonic 'invalid_instruction2'
--> $DIR/srcloc.rs:94:13
--> $DIR/srcloc.rs:95:13
|
LL | concat!(
| ^
@ -215,7 +215,7 @@ LL | invalid_instruction2
| ^^^^^^^^^^^^^^^^^^^^
error: invalid instruction mnemonic 'invalid_instruction3'
--> $DIR/srcloc.rs:98:13
--> $DIR/srcloc.rs:99:13
|
LL | concat!(
| ^
@ -227,7 +227,7 @@ LL | invalid_instruction3
| ^^^^^^^^^^^^^^^^^^^^
error: invalid instruction mnemonic 'invalid_instruction4'
--> $DIR/srcloc.rs:98:13
--> $DIR/srcloc.rs:99:13
|
LL | concat!(
| ^
@ -239,7 +239,7 @@ LL | invalid_instruction4
| ^^^^^^^^^^^^^^^^^^^^
error: invalid instruction mnemonic 'invalid_instruction1'
--> $DIR/srcloc.rs:109:13
--> $DIR/srcloc.rs:110:13
|
LL | concat!(
| ^
@ -251,7 +251,7 @@ LL | invalid_instruction1
| ^^^^^^^^^^^^^^^^^^^^
error: invalid instruction mnemonic 'invalid_instruction2'
--> $DIR/srcloc.rs:109:13
--> $DIR/srcloc.rs:110:13
|
LL | concat!(
| ^
@ -263,7 +263,7 @@ LL | invalid_instruction2
| ^^^^^^^^^^^^^^^^^^^^
error: invalid instruction mnemonic 'invalid_instruction3'
--> $DIR/srcloc.rs:113:13
--> $DIR/srcloc.rs:114:13
|
LL | concat!(
| ^
@ -275,7 +275,7 @@ LL | invalid_instruction3
| ^^^^^^^^^^^^^^^^^^^^
error: invalid instruction mnemonic 'invalid_instruction4'
--> $DIR/srcloc.rs:113:13
--> $DIR/srcloc.rs:114:13
|
LL | concat!(
| ^

View file

@ -3,7 +3,9 @@
// only-linux
// run-pass
#![feature(asm, thread_local, asm_sym)]
#![feature(thread_local, asm_sym)]
use std::arch::asm;
extern "C" fn f1() -> i32 {
111

View file

@ -1,6 +1,8 @@
// only-x86_64
#![feature(asm, avx512_target_feature)]
#![feature(avx512_target_feature)]
use std::arch::asm;
#[target_feature(enable = "avx")]
unsafe fn foo() {

View file

@ -1,23 +1,23 @@
error: register class `ymm_reg` requires the `avx` target feature
--> $DIR/target-feature-attr.rs:16:40
--> $DIR/target-feature-attr.rs:18:40
|
LL | asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x);
| ^^^^^^^^^^^^^
error: register class `ymm_reg` requires the `avx` target feature
--> $DIR/target-feature-attr.rs:16:55
--> $DIR/target-feature-attr.rs:18:55
|
LL | asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x);
| ^^^^^^^^^^^^^
error: register class `ymm_reg` requires the `avx` target feature
--> $DIR/target-feature-attr.rs:16:70
--> $DIR/target-feature-attr.rs:18:70
|
LL | asm!("vaddps {2:y}, {0:y}, {1:y}", in(ymm_reg) x, in(ymm_reg) y, lateout(ymm_reg) x);
| ^^^^^^^^^^^^^^^^^^
error: register class `kreg` requires at least one of the following target features: avx512bw, avx512f
--> $DIR/target-feature-attr.rs:31:23
--> $DIR/target-feature-attr.rs:33:23
|
LL | asm!("/* {0} */", in(kreg) x);
| ^^^^^^^^^^

View file

@ -1,6 +1,8 @@
// only-x86_64
#![feature(asm, repr_simd, never_type, asm_sym)]
#![feature(repr_simd, never_type, asm_sym)]
use std::arch::asm;
#[repr(simd)]
struct SimdNonCopy(f32, f32, f32, f32);

View file

@ -1,13 +1,13 @@
error: arguments for inline assembly must be copyable
--> $DIR/type-check-2.rs:42:32
--> $DIR/type-check-2.rs:44:32
|
LL | asm!("{}", in(xmm_reg) SimdNonCopy(0.0, 0.0, 0.0, 0.0));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `SimdNonCopy` does not implement the Copy trait
error: cannot use value of type `[closure@$DIR/type-check-2.rs:54:28: 54:38]` for inline assembly
--> $DIR/type-check-2.rs:54:28
error: cannot use value of type `[closure@$DIR/type-check-2.rs:56:28: 56:38]` for inline assembly
--> $DIR/type-check-2.rs:56:28
|
LL | asm!("{}", in(reg) |x: i32| x);
| ^^^^^^^^^^
@ -15,7 +15,7 @@ LL | asm!("{}", in(reg) |x: i32| x);
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
error: cannot use value of type `Vec<i32>` for inline assembly
--> $DIR/type-check-2.rs:56:28
--> $DIR/type-check-2.rs:58:28
|
LL | asm!("{}", in(reg) vec![0]);
| ^^^^^^^
@ -24,7 +24,7 @@ LL | asm!("{}", in(reg) vec![0]);
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
error: cannot use value of type `(i32, i32, i32)` for inline assembly
--> $DIR/type-check-2.rs:58:28
--> $DIR/type-check-2.rs:60:28
|
LL | asm!("{}", in(reg) (1, 2, 3));
| ^^^^^^^^^
@ -32,7 +32,7 @@ LL | asm!("{}", in(reg) (1, 2, 3));
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
error: cannot use value of type `[i32; 3]` for inline assembly
--> $DIR/type-check-2.rs:60:28
--> $DIR/type-check-2.rs:62:28
|
LL | asm!("{}", in(reg) [1, 2, 3]);
| ^^^^^^^^^
@ -40,7 +40,7 @@ LL | asm!("{}", in(reg) [1, 2, 3]);
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
error: cannot use value of type `fn() {main}` for inline assembly
--> $DIR/type-check-2.rs:68:31
--> $DIR/type-check-2.rs:70:31
|
LL | asm!("{}", inout(reg) f);
| ^
@ -48,7 +48,7 @@ LL | asm!("{}", inout(reg) f);
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
error: cannot use value of type `&mut i32` for inline assembly
--> $DIR/type-check-2.rs:71:31
--> $DIR/type-check-2.rs:73:31
|
LL | asm!("{}", inout(reg) r);
| ^
@ -56,31 +56,31 @@ LL | asm!("{}", inout(reg) r);
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
error: asm `sym` operand must point to a fn or static
--> $DIR/type-check-2.rs:35:24
--> $DIR/type-check-2.rs:37:24
|
LL | asm!("{}", sym C);
| ^
error: asm `sym` operand must point to a fn or static
--> $DIR/type-check-2.rs:37:24
--> $DIR/type-check-2.rs:39:24
|
LL | asm!("{}", sym x);
| ^
error[E0381]: use of possibly-uninitialized variable: `x`
--> $DIR/type-check-2.rs:13:28
--> $DIR/type-check-2.rs:15:28
|
LL | asm!("{}", in(reg) x);
| ^ use of possibly-uninitialized `x`
error[E0381]: use of possibly-uninitialized variable: `y`
--> $DIR/type-check-2.rs:16:9
--> $DIR/type-check-2.rs:18:9
|
LL | asm!("{}", inout(reg) y);
| ^^^^^^^^^^^^^^^^^^^^^^^^ use of possibly-uninitialized `y`
error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
--> $DIR/type-check-2.rs:24:29
--> $DIR/type-check-2.rs:26:29
|
LL | let v: Vec<u64> = vec![0, 1, 2];
| - help: consider changing this to be mutable: `mut v`
@ -89,7 +89,7 @@ LL | asm!("{}", out(reg) v[0]);
| ^ cannot borrow as mutable
error[E0596]: cannot borrow `v` as mutable, as it is not declared as mutable
--> $DIR/type-check-2.rs:26:31
--> $DIR/type-check-2.rs:28:31
|
LL | let v: Vec<u64> = vec![0, 1, 2];
| - help: consider changing this to be mutable: `mut v`

View file

@ -1,7 +1,9 @@
// only-x86_64
// compile-flags: -C target-feature=+avx512f
#![feature(asm, global_asm, asm_const)]
#![feature(asm_const)]
use std::arch::{asm, global_asm};
use std::arch::x86_64::{_mm256_setzero_ps, _mm_setzero_ps};

View file

@ -1,5 +1,5 @@
error: type `i128` cannot be used with this register class
--> $DIR/type-check-3.rs:12:28
--> $DIR/type-check-3.rs:14:28
|
LL | asm!("{}", in(reg) 0i128);
| ^^^^^
@ -7,7 +7,7 @@ LL | asm!("{}", in(reg) 0i128);
= note: register class `reg` supports these types: i16, i32, i64, f32, f64
error: type `__m128` cannot be used with this register class
--> $DIR/type-check-3.rs:14:28
--> $DIR/type-check-3.rs:16:28
|
LL | asm!("{}", in(reg) _mm_setzero_ps());
| ^^^^^^^^^^^^^^^^
@ -15,7 +15,7 @@ LL | asm!("{}", in(reg) _mm_setzero_ps());
= note: register class `reg` supports these types: i16, i32, i64, f32, f64
error: type `__m256` cannot be used with this register class
--> $DIR/type-check-3.rs:16:28
--> $DIR/type-check-3.rs:18:28
|
LL | asm!("{}", in(reg) _mm256_setzero_ps());
| ^^^^^^^^^^^^^^^^^^^
@ -23,7 +23,7 @@ LL | asm!("{}", in(reg) _mm256_setzero_ps());
= note: register class `reg` supports these types: i16, i32, i64, f32, f64
error: type `u8` cannot be used with this register class
--> $DIR/type-check-3.rs:18:32
--> $DIR/type-check-3.rs:20:32
|
LL | asm!("{}", in(xmm_reg) 0u8);
| ^^^
@ -31,7 +31,7 @@ LL | asm!("{}", in(xmm_reg) 0u8);
= note: register class `xmm_reg` supports these types: i32, i64, f32, f64, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2
error: `avx512bw` target feature is not enabled
--> $DIR/type-check-3.rs:27:29
--> $DIR/type-check-3.rs:29:29
|
LL | asm!("{}", in(kreg) 0u64);
| ^^^^
@ -39,7 +39,7 @@ LL | asm!("{}", in(kreg) 0u64);
= note: this is required to use type `u64` with register class `kreg`
warning: formatting may not be suitable for sub-register argument
--> $DIR/type-check-3.rs:32:15
--> $DIR/type-check-3.rs:34:15
|
LL | asm!("{0} {0}", in(reg) 0i16);
| ^^^ ^^^ ---- for this argument
@ -49,7 +49,7 @@ LL | asm!("{0} {0}", in(reg) 0i16);
= help: or use the `r` modifier to keep the default formatting of `rax`
warning: formatting may not be suitable for sub-register argument
--> $DIR/type-check-3.rs:34:15
--> $DIR/type-check-3.rs:36:15
|
LL | asm!("{0} {0:x}", in(reg) 0i16);
| ^^^ ---- for this argument
@ -58,7 +58,7 @@ LL | asm!("{0} {0:x}", in(reg) 0i16);
= help: or use the `r` modifier to keep the default formatting of `rax`
warning: formatting may not be suitable for sub-register argument
--> $DIR/type-check-3.rs:36:15
--> $DIR/type-check-3.rs:38:15
|
LL | asm!("{}", in(reg) 0i32);
| ^^ ---- for this argument
@ -67,7 +67,7 @@ LL | asm!("{}", in(reg) 0i32);
= help: or use the `r` modifier to keep the default formatting of `rax`
warning: formatting may not be suitable for sub-register argument
--> $DIR/type-check-3.rs:39:15
--> $DIR/type-check-3.rs:41:15
|
LL | asm!("{}", in(ymm_reg) 0i64);
| ^^ ---- for this argument
@ -76,7 +76,7 @@ LL | asm!("{}", in(ymm_reg) 0i64);
= help: or use the `y` modifier to keep the default formatting of `ymm0`
error: type `i8` cannot be used with this register class
--> $DIR/type-check-3.rs:50:28
--> $DIR/type-check-3.rs:52:28
|
LL | asm!("{}", in(reg) 0i8);
| ^^^
@ -85,7 +85,7 @@ LL | asm!("{}", in(reg) 0i8);
= help: consider using the `reg_byte` register class instead
error: incompatible types for asm inout argument
--> $DIR/type-check-3.rs:62:33
--> $DIR/type-check-3.rs:64:33
|
LL | asm!("{:r}", inout(reg) 0u32 => val_f32);
| ^^^^ ^^^^^^^ type `f32`
@ -95,7 +95,7 @@ LL | asm!("{:r}", inout(reg) 0u32 => val_f32);
= note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size
error: incompatible types for asm inout argument
--> $DIR/type-check-3.rs:64:33
--> $DIR/type-check-3.rs:66:33
|
LL | asm!("{:r}", inout(reg) 0u32 => val_ptr);
| ^^^^ ^^^^^^^ type `*mut u8`
@ -105,7 +105,7 @@ LL | asm!("{:r}", inout(reg) 0u32 => val_ptr);
= note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size
error: incompatible types for asm inout argument
--> $DIR/type-check-3.rs:66:33
--> $DIR/type-check-3.rs:68:33
|
LL | asm!("{:r}", inout(reg) main => val_u32);
| ^^^^ ^^^^^^^ type `u32`
@ -115,7 +115,7 @@ LL | asm!("{:r}", inout(reg) main => val_u32);
= note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size
error[E0013]: constants cannot refer to statics
--> $DIR/type-check-3.rs:82:25
--> $DIR/type-check-3.rs:84:25
|
LL | global_asm!("{}", const S);
| ^
@ -123,7 +123,7 @@ LL | global_asm!("{}", const S);
= help: consider extracting the value of the `static` to a `const`, and referring to that
error[E0013]: constants cannot refer to statics
--> $DIR/type-check-3.rs:85:35
--> $DIR/type-check-3.rs:87:35
|
LL | global_asm!("{}", const const_foo(S));
| ^
@ -131,7 +131,7 @@ LL | global_asm!("{}", const const_foo(S));
= help: consider extracting the value of the `static` to a `const`, and referring to that
error[E0013]: constants cannot refer to statics
--> $DIR/type-check-3.rs:88:35
--> $DIR/type-check-3.rs:90:35
|
LL | global_asm!("{}", const const_bar(S));
| ^

View file

@ -1,6 +1,6 @@
// needs-asm-support
#![feature(asm)]
use std::arch::asm;
const _: () = unsafe { asm!("nop") };
//~^ ERROR inline assembly

View file

@ -1,9 +1,11 @@
// compile-flags: -Zunleash-the-miri-inside-of-you
// only-x86_64
#![feature(asm,llvm_asm)]
#![feature(llvm_asm)]
#![allow(const_err)]
#![allow(deprecated)] // llvm_asm!
use std::arch::asm;
fn main() {}
// Make sure we catch executing inline assembly.

View file

@ -1,5 +1,5 @@
error[E0080]: could not evaluate static initializer
--> $DIR/inline_asm.rs:11:14
--> $DIR/inline_asm.rs:13:14
|
LL | unsafe { llvm_asm!("xor %eax, %eax" ::: "eax"); }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ inline assembly is not supported
@ -7,7 +7,7 @@ LL | unsafe { llvm_asm!("xor %eax, %eax" ::: "eax"); }
= note: this error originates in the macro `llvm_asm` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0080]: could not evaluate static initializer
--> $DIR/inline_asm.rs:20:14
--> $DIR/inline_asm.rs:22:14
|
LL | unsafe { asm!("nop"); }
| ^^^^^^^^^^^ inline assembly is not supported
@ -15,12 +15,12 @@ LL | unsafe { asm!("nop"); }
warning: skipping const checks
|
help: skipping check that does not even have a feature gate
--> $DIR/inline_asm.rs:11:14
--> $DIR/inline_asm.rs:13:14
|
LL | unsafe { llvm_asm!("xor %eax, %eax" ::: "eax"); }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: skipping check that does not even have a feature gate
--> $DIR/inline_asm.rs:20:14
--> $DIR/inline_asm.rs:22:14
|
LL | unsafe { asm!("nop"); }
| ^^^^^^^^^^^

View file

@ -1,6 +1,6 @@
// run-pass
#![feature(global_asm)]
use std::arch::global_asm;
#[cfg(target_arch = "x86")]
global_asm!("");

View file

@ -4,8 +4,6 @@
fn main() {
unsafe {
asm!("");
//~^ ERROR inline assembly is not stable enough
llvm_asm!("");
//~^ ERROR prefer using the new asm! syntax instead
}

Some files were not shown because too many files have changed in this diff Show more