Auto merge of #69171 - Amanieu:new-asm, r=nagisa,nikomatsakis
Implement new asm! syntax from RFC 2850 This PR implements the new `asm!` syntax proposed in https://github.com/rust-lang/rfcs/pull/2850. # Design A large part of this PR revolves around taking an `asm!` macro invocation and plumbing it through all of the compiler layers down to LLVM codegen. Throughout the various stages, an `InlineAsm` generally consists of 3 components: - The template string, which is stored as an array of `InlineAsmTemplatePiece`. Each piece represents either a literal or a placeholder for an operand (just like format strings). ```rust pub enum InlineAsmTemplatePiece { String(String), Placeholder { operand_idx: usize, modifier: Option<char>, span: Span }, } ``` - The list of operands to the `asm!` (`in`, `[late]out`, `in[late]out`, `sym`, `const`). These are represented differently at each stage of lowering, but follow a common pattern: - `in`, `out` and `inout` all have an associated register class (`reg`) or explicit register (`"eax"`). - `inout` has 2 forms: one with a single expression that is both read from and written to, and one with two separate expressions for the input and output parts. - `out` and `inout` have a `late` flag (`lateout` / `inlateout`) to indicate that the register allocator is allowed to reuse an input register for this output. - `out` and the split variant of `inout` allow `_` to be specified for an output, which means that the output is discarded. This is used to allocate scratch registers for assembly code. - `sym` is a bit special since it only accepts a path expression, which must point to a `static` or a `fn`. - The options set at the end of the `asm!` macro. The only one that is particularly of interest to rustc is `NORETURN` which makes `asm!` return `!` instead of `()`. ```rust bitflags::bitflags! { pub struct InlineAsmOptions: u8 { const PURE = 1 << 0; const NOMEM = 1 << 1; const READONLY = 1 << 2; const PRESERVES_FLAGS = 1 << 3; const NORETURN = 1 << 4; const NOSTACK = 1 << 5; } } ``` ## AST `InlineAsm` is represented as an expression in the AST: ```rust pub struct InlineAsm { pub template: Vec<InlineAsmTemplatePiece>, pub operands: Vec<(InlineAsmOperand, Span)>, pub options: InlineAsmOptions, } pub enum InlineAsmRegOrRegClass { Reg(Symbol), RegClass(Symbol), } pub enum InlineAsmOperand { In { reg: InlineAsmRegOrRegClass, expr: P<Expr>, }, Out { reg: InlineAsmRegOrRegClass, late: bool, expr: Option<P<Expr>>, }, InOut { reg: InlineAsmRegOrRegClass, late: bool, expr: P<Expr>, }, SplitInOut { reg: InlineAsmRegOrRegClass, late: bool, in_expr: P<Expr>, out_expr: Option<P<Expr>>, }, Const { expr: P<Expr>, }, Sym { expr: P<Expr>, }, } ``` The `asm!` macro is implemented in librustc_builtin_macros and outputs an `InlineAsm` AST node. The template string is parsed using libfmt_macros, positional and named operands are resolved to explicit operand indicies. Since target information is not available to macro invocations, validation of the registers and register classes is deferred to AST lowering. ## HIR `InlineAsm` is represented as an expression in the HIR: ```rust pub struct InlineAsm<'hir> { pub template: &'hir [InlineAsmTemplatePiece], pub operands: &'hir [InlineAsmOperand<'hir>], pub options: InlineAsmOptions, } pub enum InlineAsmRegOrRegClass { Reg(InlineAsmReg), RegClass(InlineAsmRegClass), } pub enum InlineAsmOperand<'hir> { In { reg: InlineAsmRegOrRegClass, expr: Expr<'hir>, }, Out { reg: InlineAsmRegOrRegClass, late: bool, expr: Option<Expr<'hir>>, }, InOut { reg: InlineAsmRegOrRegClass, late: bool, expr: Expr<'hir>, }, SplitInOut { reg: InlineAsmRegOrRegClass, late: bool, in_expr: Expr<'hir>, out_expr: Option<Expr<'hir>>, }, Const { expr: Expr<'hir>, }, Sym { expr: Expr<'hir>, }, } ``` AST lowering is where `InlineAsmRegOrRegClass` is converted from `Symbol`s to an actual register or register class. If any modifiers are specified for a template string placeholder, these are validated against the set allowed for that operand type. Finally, explicit registers for inputs and outputs are checked for conflicts (same register used for different operands). ## Type checking Each register class has a whitelist of types that it may be used with. After the types of all operands have been determined, the `intrinsicck` pass will check that these types are in the whitelist. It also checks that split `inout` operands have compatible types and that `const` operands are integers or floats. Suggestions are emitted where needed if a template modifier should be used for an operand based on the type that was passed into it. ## HAIR `InlineAsm` is represented as an expression in the HAIR: ```rust crate enum ExprKind<'tcx> { // [..] InlineAsm { template: &'tcx [InlineAsmTemplatePiece], operands: Vec<InlineAsmOperand<'tcx>>, options: InlineAsmOptions, }, } crate enum InlineAsmOperand<'tcx> { In { reg: InlineAsmRegOrRegClass, expr: ExprRef<'tcx>, }, Out { reg: InlineAsmRegOrRegClass, late: bool, expr: Option<ExprRef<'tcx>>, }, InOut { reg: InlineAsmRegOrRegClass, late: bool, expr: ExprRef<'tcx>, }, SplitInOut { reg: InlineAsmRegOrRegClass, late: bool, in_expr: ExprRef<'tcx>, out_expr: Option<ExprRef<'tcx>>, }, Const { expr: ExprRef<'tcx>, }, SymFn { expr: ExprRef<'tcx>, }, SymStatic { expr: ExprRef<'tcx>, }, } ``` The only significant change compared to HIR is that `Sym` has been lowered to either a `SymFn` whose `expr` is a `Literal` ZST of the `fn`, or a `SymStatic` whose `expr` is a `StaticRef`. ## MIR `InlineAsm` is represented as a `Terminator` in the MIR: ```rust pub enum TerminatorKind<'tcx> { // [..] /// Block ends with an inline assembly block. This is a terminator since /// inline assembly is allowed to diverge. InlineAsm { /// The template for the inline assembly, with placeholders. template: &'tcx [InlineAsmTemplatePiece], /// The operands for the inline assembly, as `Operand`s or `Place`s. operands: Vec<InlineAsmOperand<'tcx>>, /// Miscellaneous options for the inline assembly. options: InlineAsmOptions, /// Destination block after the inline assembly returns, unless it is /// diverging (InlineAsmOptions::NORETURN). destination: Option<BasicBlock>, }, } pub enum InlineAsmOperand<'tcx> { In { reg: InlineAsmRegOrRegClass, value: Operand<'tcx>, }, Out { reg: InlineAsmRegOrRegClass, late: bool, place: Option<Place<'tcx>>, }, InOut { reg: InlineAsmRegOrRegClass, late: bool, in_value: Operand<'tcx>, out_place: Option<Place<'tcx>>, }, Const { value: Operand<'tcx>, }, SymFn { value: Box<Constant<'tcx>>, }, SymStatic { value: Box<Constant<'tcx>>, }, } ``` As part of HAIR lowering, `InOut` and `SplitInOut` operands are lowered to a split form with a separate `in_value` and `out_place`. Semantically, the `InlineAsm` terminator is similar to the `Call` terminator except that it has multiple output places where a `Call` only has a single return place output. The constant promotion pass is used to ensure that `const` operands are actually constants (using the same logic as `#[rustc_args_required_const]`). ## Codegen Operands are lowered one more time before being passed to LLVM codegen: ```rust pub enum InlineAsmOperandRef<'tcx, B: BackendTypes + ?Sized> { In { reg: InlineAsmRegOrRegClass, value: OperandRef<'tcx, B::Value>, }, Out { reg: InlineAsmRegOrRegClass, late: bool, place: Option<PlaceRef<'tcx, B::Value>>, }, InOut { reg: InlineAsmRegOrRegClass, late: bool, in_value: OperandRef<'tcx, B::Value>, out_place: Option<PlaceRef<'tcx, B::Value>>, }, Const { string: String, }, SymFn { instance: Instance<'tcx>, }, SymStatic { def_id: DefId, }, } ``` The operands are lowered to LLVM operands and constraint codes as follow: - `out` and the output part of `inout` operands are added first, as required by LLVM. Late output operands have a `=` prefix added to their constraint code, non-late output operands have a `=&` prefix added to their constraint code. - `in` operands are added normally. - `inout` operands are tied to the matching output operand. - `sym` operands are passed as function pointers or pointers, using the `"s"` constraint. - `const` operands are formatted to a string and directly inserted in the template string. The template string is converted to LLVM form: - `$` characters are escaped as `$$`. - `const` operands are converted to strings and inserted directly. - Placeholders are formatted as `${X:M}` where `X` is the operand index and `M` is the modifier character. Modifiers are converted from the Rust form to the LLVM form. The various options are converted to clobber constraints or LLVM attributes, refer to the [RFC](https://github.com/Amanieu/rfcs/blob/inline-asm/text/0000-inline-asm.md#mapping-to-llvm-ir) for more details. Note that LLVM is sometimes rather picky about what types it accepts for certain constraint codes so we sometimes need to insert conversions to/from a supported type. See the target-specific ISelLowering.cpp files in LLVM for details. # Adding support for new architectures Adding inline assembly support to an architecture is mostly a matter of defining the registers and register classes for that architecture. All the definitions for register classes are located in `src/librustc_target/asm/`. Additionally you will need to implement lowering of these register classes to LLVM constraint codes in `src/librustc_codegen_llvm/asm.rs`.
This commit is contained in:
commit
3a7dfda40a
140 changed files with 9285 additions and 279 deletions
18
src/test/ui/asm/bad-options.rs
Normal file
18
src/test/ui/asm/bad-options.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
// only-x86_64
|
||||
|
||||
#![feature(asm)]
|
||||
|
||||
fn main() {
|
||||
let mut foo = 0;
|
||||
unsafe {
|
||||
asm!("", options(nomem, readonly));
|
||||
//~^ ERROR the `nomem` and `readonly` options are mutually exclusive
|
||||
asm!("", options(pure, nomem, noreturn));
|
||||
//~^ ERROR the `pure` and `noreturn` options are mutually exclusive
|
||||
//~^^ ERROR asm with `pure` option must have at least one output
|
||||
asm!("{}", in(reg) foo, options(pure, nomem));
|
||||
//~^ ERROR asm with `pure` option must have at least one output
|
||||
asm!("{}", out(reg) foo, options(noreturn));
|
||||
//~^ ERROR asm outputs are not allowed with the `noreturn` option
|
||||
}
|
||||
}
|
||||
32
src/test/ui/asm/bad-options.stderr
Normal file
32
src/test/ui/asm/bad-options.stderr
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
error: the `nomem` and `readonly` options are mutually exclusive
|
||||
--> $DIR/bad-options.rs:8:18
|
||||
|
|
||||
LL | asm!("", options(nomem, readonly));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: the `pure` and `noreturn` options are mutually exclusive
|
||||
--> $DIR/bad-options.rs:10:18
|
||||
|
|
||||
LL | asm!("", options(pure, nomem, noreturn));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: asm with `pure` option must have at least one output
|
||||
--> $DIR/bad-options.rs:10:18
|
||||
|
|
||||
LL | asm!("", options(pure, nomem, noreturn));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: asm with `pure` option must have at least one output
|
||||
--> $DIR/bad-options.rs:13:33
|
||||
|
|
||||
LL | asm!("{}", in(reg) foo, options(pure, nomem));
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: asm outputs are not allowed with the `noreturn` option
|
||||
--> $DIR/bad-options.rs:15:20
|
||||
|
|
||||
LL | asm!("{}", out(reg) foo, options(noreturn));
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
55
src/test/ui/asm/bad-reg.rs
Normal file
55
src/test/ui/asm/bad-reg.rs
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
// only-x86_64
|
||||
// compile-flags: -C target-feature=+avx2
|
||||
|
||||
#![feature(asm)]
|
||||
|
||||
fn main() {
|
||||
let mut foo = 0;
|
||||
let mut bar = 0;
|
||||
unsafe {
|
||||
// Bad register/register class
|
||||
|
||||
asm!("{}", in(foo) foo);
|
||||
//~^ ERROR invalid register class `foo`: unknown register class
|
||||
asm!("", in("foo") foo);
|
||||
//~^ ERROR invalid register `foo`: unknown register
|
||||
asm!("{:z}", in(reg) foo);
|
||||
//~^ ERROR invalid asm template modifier for this register class
|
||||
asm!("{:r}", in(xmm_reg) foo);
|
||||
//~^ ERROR invalid asm template modifier for this register class
|
||||
asm!("{:a}", const 0);
|
||||
//~^ ERROR asm template modifiers are not allowed for `const` arguments
|
||||
asm!("{:a}", sym main);
|
||||
//~^ ERROR asm template modifiers are not allowed for `sym` arguments
|
||||
asm!("{}", in(zmm_reg) foo);
|
||||
//~^ ERROR register class `zmm_reg` requires the `avx512f` target feature
|
||||
asm!("", in("zmm0") foo);
|
||||
//~^ ERROR register class `zmm_reg` requires the `avx512f` target feature
|
||||
asm!("", in("ebp") foo);
|
||||
//~^ ERROR invalid register `ebp`: the frame pointer cannot be used as an operand
|
||||
asm!("", in("rsp") foo);
|
||||
//~^ ERROR invalid register `rsp`: the stack pointer cannot be used as an operand
|
||||
asm!("", in("ip") foo);
|
||||
//~^ ERROR invalid register `ip`: the instruction pointer cannot be used as an operand
|
||||
asm!("", in("st(2)") foo);
|
||||
//~^ ERROR invalid register `st(2)`: x87 registers are not currently supported as operands
|
||||
asm!("", in("mm0") foo);
|
||||
//~^ ERROR invalid register `mm0`: MMX registers are not currently supported as operands
|
||||
asm!("", in("k0") foo);
|
||||
//~^ ERROR invalid register `k0`: the k0 AVX mask register cannot be used as an operand
|
||||
|
||||
// Explicit register conflicts
|
||||
// (except in/lateout which don't conflict)
|
||||
|
||||
asm!("", in("eax") foo, in("al") bar);
|
||||
//~^ ERROR register `al` conflicts with register `ax`
|
||||
asm!("", in("rax") foo, out("rax") bar);
|
||||
//~^ ERROR register `ax` conflicts with register `ax`
|
||||
asm!("", in("al") foo, lateout("al") bar);
|
||||
asm!("", in("xmm0") foo, in("ymm0") bar);
|
||||
//~^ ERROR register `ymm0` conflicts with register `xmm0`
|
||||
asm!("", in("xmm0") foo, out("ymm0") bar);
|
||||
//~^ ERROR register `ymm0` conflicts with register `xmm0`
|
||||
asm!("", in("xmm0") foo, lateout("ymm0") bar);
|
||||
}
|
||||
}
|
||||
142
src/test/ui/asm/bad-reg.stderr
Normal file
142
src/test/ui/asm/bad-reg.stderr
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
error: invalid register class `foo`: unknown register class
|
||||
--> $DIR/bad-reg.rs:12:20
|
||||
|
|
||||
LL | asm!("{}", in(foo) foo);
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: invalid register `foo`: unknown register
|
||||
--> $DIR/bad-reg.rs:14:18
|
||||
|
|
||||
LL | asm!("", in("foo") foo);
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: invalid asm template modifier for this register class
|
||||
--> $DIR/bad-reg.rs:16:15
|
||||
|
|
||||
LL | asm!("{:z}", in(reg) foo);
|
||||
| ^^^^ ----------- argument
|
||||
| |
|
||||
| template modifier
|
||||
|
|
||||
= 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
|
||||
|
|
||||
LL | asm!("{:r}", in(xmm_reg) foo);
|
||||
| ^^^^ --------------- argument
|
||||
| |
|
||||
| template modifier
|
||||
|
|
||||
= 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
|
||||
|
|
||||
LL | asm!("{:a}", const 0);
|
||||
| ^^^^ ------- argument
|
||||
| |
|
||||
| template modifier
|
||||
|
||||
error: asm template modifiers are not allowed for `sym` arguments
|
||||
--> $DIR/bad-reg.rs:22:15
|
||||
|
|
||||
LL | asm!("{:a}", sym main);
|
||||
| ^^^^ -------- argument
|
||||
| |
|
||||
| template modifier
|
||||
|
||||
error: register class `zmm_reg` requires the `avx512f` target feature
|
||||
--> $DIR/bad-reg.rs:24:20
|
||||
|
|
||||
LL | asm!("{}", in(zmm_reg) foo);
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: register class `zmm_reg` requires the `avx512f` target feature
|
||||
--> $DIR/bad-reg.rs:26:18
|
||||
|
|
||||
LL | asm!("", in("zmm0") foo);
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: invalid register `ebp`: the frame pointer cannot be used as an operand for inline asm
|
||||
--> $DIR/bad-reg.rs:28: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:30: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:32:18
|
||||
|
|
||||
LL | asm!("", in("ip") foo);
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: invalid register `st(2)`: x87 registers are not currently supported as operands for inline asm
|
||||
--> $DIR/bad-reg.rs:34:18
|
||||
|
|
||||
LL | asm!("", in("st(2)") foo);
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: invalid register `mm0`: MMX registers are not currently supported as operands for inline asm
|
||||
--> $DIR/bad-reg.rs:36:18
|
||||
|
|
||||
LL | asm!("", in("mm0") foo);
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: invalid register `k0`: the k0 AVX mask register cannot be used as an operand for inline asm
|
||||
--> $DIR/bad-reg.rs:38:18
|
||||
|
|
||||
LL | asm!("", in("k0") foo);
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: register `al` conflicts with register `ax`
|
||||
--> $DIR/bad-reg.rs:44:33
|
||||
|
|
||||
LL | asm!("", in("eax") foo, in("al") bar);
|
||||
| ------------- ^^^^^^^^^^^^ register `al`
|
||||
| |
|
||||
| register `ax`
|
||||
|
||||
error: register `ax` conflicts with register `ax`
|
||||
--> $DIR/bad-reg.rs:46:33
|
||||
|
|
||||
LL | asm!("", in("rax") foo, out("rax") bar);
|
||||
| ------------- ^^^^^^^^^^^^^^ register `ax`
|
||||
| |
|
||||
| register `ax`
|
||||
|
|
||||
help: use `lateout` instead of `out` to avoid conflict
|
||||
--> $DIR/bad-reg.rs:46:18
|
||||
|
|
||||
LL | asm!("", in("rax") foo, out("rax") bar);
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: register `ymm0` conflicts with register `xmm0`
|
||||
--> $DIR/bad-reg.rs:49:34
|
||||
|
|
||||
LL | asm!("", in("xmm0") foo, in("ymm0") bar);
|
||||
| -------------- ^^^^^^^^^^^^^^ register `ymm0`
|
||||
| |
|
||||
| register `xmm0`
|
||||
|
||||
error: register `ymm0` conflicts with register `xmm0`
|
||||
--> $DIR/bad-reg.rs:51:34
|
||||
|
|
||||
LL | asm!("", in("xmm0") foo, out("ymm0") bar);
|
||||
| -------------- ^^^^^^^^^^^^^^^ register `ymm0`
|
||||
| |
|
||||
| register `xmm0`
|
||||
|
|
||||
help: use `lateout` instead of `out` to avoid conflict
|
||||
--> $DIR/bad-reg.rs:51:18
|
||||
|
|
||||
LL | asm!("", in("xmm0") foo, out("ymm0") bar);
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 18 previous errors
|
||||
|
||||
26
src/test/ui/asm/bad-template.rs
Normal file
26
src/test/ui/asm/bad-template.rs
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// only-x86_64
|
||||
|
||||
#![feature(asm)]
|
||||
|
||||
fn main() {
|
||||
let mut foo = 0;
|
||||
unsafe {
|
||||
asm!("{}");
|
||||
//~^ ERROR invalid reference to argument at index 0
|
||||
asm!("{1}", in(reg) foo);
|
||||
//~^ ERROR invalid reference to argument at index 1
|
||||
//~^^ ERROR argument never used
|
||||
asm!("{a}");
|
||||
//~^ ERROR there is no argument named `a`
|
||||
asm!("{}", a = in(reg) foo);
|
||||
//~^ ERROR invalid reference to argument at index 0
|
||||
//~^^ ERROR argument never used
|
||||
asm!("{1}", a = in(reg) foo);
|
||||
//~^ ERROR invalid reference to argument at index 1
|
||||
//~^^ ERROR named argument never used
|
||||
asm!("{}", in("eax") foo);
|
||||
//~^ ERROR invalid reference to argument at index 0
|
||||
asm!("{:foo}", in(reg) foo);
|
||||
//~^ ERROR asm template modifier must be a single character
|
||||
}
|
||||
}
|
||||
86
src/test/ui/asm/bad-template.stderr
Normal file
86
src/test/ui/asm/bad-template.stderr
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
error: invalid reference to argument at index 0
|
||||
--> $DIR/bad-template.rs:8:15
|
||||
|
|
||||
LL | asm!("{}");
|
||||
| ^^ from here
|
||||
|
|
||||
= note: no arguments were given
|
||||
|
||||
error: invalid reference to argument at index 1
|
||||
--> $DIR/bad-template.rs:10:15
|
||||
|
|
||||
LL | asm!("{1}", in(reg) foo);
|
||||
| ^^^ from here
|
||||
|
|
||||
= note: there is 1 argument
|
||||
|
||||
error: argument never used
|
||||
--> $DIR/bad-template.rs:10:21
|
||||
|
|
||||
LL | asm!("{1}", in(reg) foo);
|
||||
| ^^^^^^^^^^^ argument never used
|
||||
|
||||
error: there is no argument named `a`
|
||||
--> $DIR/bad-template.rs:13:15
|
||||
|
|
||||
LL | asm!("{a}");
|
||||
| ^^^
|
||||
|
||||
error: invalid reference to argument at index 0
|
||||
--> $DIR/bad-template.rs:15:15
|
||||
|
|
||||
LL | asm!("{}", a = in(reg) foo);
|
||||
| ^^ --------------- named argument
|
||||
| |
|
||||
| from here
|
||||
|
|
||||
= note: no positional arguments were given
|
||||
note: named arguments cannot be referenced by position
|
||||
--> $DIR/bad-template.rs:15:20
|
||||
|
|
||||
LL | asm!("{}", a = in(reg) foo);
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
error: named argument never used
|
||||
--> $DIR/bad-template.rs:15:20
|
||||
|
|
||||
LL | asm!("{}", a = in(reg) foo);
|
||||
| ^^^^^^^^^^^^^^^ named argument never used
|
||||
|
||||
error: invalid reference to argument at index 1
|
||||
--> $DIR/bad-template.rs:18:15
|
||||
|
|
||||
LL | asm!("{1}", a = in(reg) foo);
|
||||
| ^^^ from here
|
||||
|
|
||||
= note: no positional arguments were given
|
||||
|
||||
error: named argument never used
|
||||
--> $DIR/bad-template.rs:18:21
|
||||
|
|
||||
LL | asm!("{1}", a = in(reg) foo);
|
||||
| ^^^^^^^^^^^^^^^ named argument never used
|
||||
|
||||
error: invalid reference to argument at index 0
|
||||
--> $DIR/bad-template.rs:21:15
|
||||
|
|
||||
LL | asm!("{}", in("eax") foo);
|
||||
| ^^ ------------- explicit register argument
|
||||
| |
|
||||
| from here
|
||||
|
|
||||
= note: no positional arguments were given
|
||||
note: explicit register arguments cannot be used in the asm template
|
||||
--> $DIR/bad-template.rs:21:20
|
||||
|
|
||||
LL | asm!("{}", in("eax") foo);
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: asm template modifier must be a single character
|
||||
--> $DIR/bad-template.rs:23:17
|
||||
|
|
||||
LL | asm!("{:foo}", in(reg) foo);
|
||||
| ^^^
|
||||
|
||||
error: aborting due to 10 previous errors
|
||||
|
||||
56
src/test/ui/asm/const.rs
Normal file
56
src/test/ui/asm/const.rs
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
// no-system-llvm
|
||||
// only-x86_64
|
||||
// run-pass
|
||||
|
||||
#![feature(asm)]
|
||||
|
||||
use std::mem::size_of;
|
||||
|
||||
trait Proj {
|
||||
const C: usize;
|
||||
}
|
||||
impl Proj for i8 {
|
||||
const C: usize = 8;
|
||||
}
|
||||
impl Proj for i16 {
|
||||
const C: usize = 16;
|
||||
}
|
||||
|
||||
const fn constfn(x: usize) -> usize {
|
||||
x
|
||||
}
|
||||
|
||||
fn generic<T: Proj>() {
|
||||
unsafe {
|
||||
let a: usize;
|
||||
asm!("mov {}, {}", out(reg) a, const size_of::<T>());
|
||||
assert_eq!(a, size_of::<T>());
|
||||
|
||||
let b: usize;
|
||||
asm!("mov {}, {}", out(reg) b, const size_of::<T>() + constfn(5));
|
||||
assert_eq!(b, size_of::<T>() + 5);
|
||||
|
||||
let c: usize;
|
||||
asm!("mov {}, {}", out(reg) c, const T::C);
|
||||
assert_eq!(c, T::C);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let a: usize;
|
||||
asm!("mov {}, {}", out(reg) a, const 5);
|
||||
assert_eq!(a, 5);
|
||||
|
||||
let b: usize;
|
||||
asm!("mov {}, {}", out(reg) b, const constfn(5));
|
||||
assert_eq!(b, 5);
|
||||
|
||||
let c: usize;
|
||||
asm!("mov {}, {}", out(reg) c, const constfn(5) + constfn(5));
|
||||
assert_eq!(c, 10);
|
||||
}
|
||||
|
||||
generic::<i8>();
|
||||
generic::<i16>();
|
||||
}
|
||||
17
src/test/ui/asm/noreturn.rs
Normal file
17
src/test/ui/asm/noreturn.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
// only-x86_64
|
||||
// check-pass
|
||||
|
||||
#![feature(asm, never_type)]
|
||||
#![crate_type = "rlib"]
|
||||
|
||||
pub unsafe fn asm1() {
|
||||
let _: () = asm!("");
|
||||
}
|
||||
|
||||
pub unsafe fn asm2() {
|
||||
let _: ! = asm!("", options(noreturn));
|
||||
}
|
||||
|
||||
pub unsafe fn asm3() -> ! {
|
||||
asm!("", options(noreturn));
|
||||
}
|
||||
56
src/test/ui/asm/parse-error.rs
Normal file
56
src/test/ui/asm/parse-error.rs
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
// only-x86_64
|
||||
|
||||
#![feature(asm)]
|
||||
|
||||
fn main() {
|
||||
let mut foo = 0;
|
||||
let mut bar = 0;
|
||||
unsafe {
|
||||
asm!();
|
||||
//~^ ERROR requires at least a template string argument
|
||||
asm!(foo);
|
||||
//~^ ERROR asm template must be a string literal
|
||||
asm!("{}" foo);
|
||||
//~^ ERROR expected token: `,`
|
||||
asm!("{}", foo);
|
||||
//~^ ERROR expected one of
|
||||
asm!("{}", in foo);
|
||||
//~^ ERROR expected `(`, found `foo`
|
||||
asm!("{}", in(reg foo));
|
||||
//~^ ERROR expected `)`, found `foo`
|
||||
asm!("{}", in(reg));
|
||||
//~^ ERROR expected expression, found end of macro arguments
|
||||
asm!("{}", inout(=) foo => bar);
|
||||
//~^ ERROR expected register class or explicit register
|
||||
asm!("{}", inout(reg) foo =>);
|
||||
//~^ ERROR expected expression, found end of macro arguments
|
||||
asm!("{}", in(reg) foo => bar);
|
||||
//~^ ERROR expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>`
|
||||
asm!("{}", sym foo + bar);
|
||||
//~^ ERROR argument to `sym` must be a path expression
|
||||
asm!("", options(foo));
|
||||
//~^ ERROR expected one of
|
||||
asm!("", options(nomem foo));
|
||||
//~^ ERROR expected one of
|
||||
asm!("", options(nomem, foo));
|
||||
//~^ ERROR expected one of
|
||||
asm!("", options(), options());
|
||||
//~^ ERROR asm options cannot be specified multiple times
|
||||
asm!("", options(), options(), options());
|
||||
//~^ ERROR asm options cannot be specified multiple times
|
||||
//~^^ ERROR asm options cannot be specified multiple times
|
||||
asm!("{}", options(), const foo);
|
||||
//~^ ERROR arguments are not allowed after options
|
||||
asm!("{a}", a = const foo, a = const bar);
|
||||
//~^ ERROR duplicate argument named `a`
|
||||
//~^^ ERROR argument never used
|
||||
asm!("", a = in("eax") foo);
|
||||
//~^ ERROR explicit register arguments cannot have names
|
||||
asm!("{a}", in("eax") foo, a = const bar);
|
||||
//~^ ERROR named arguments cannot follow explicit register arguments
|
||||
asm!("{a}", in("eax") foo, a = const bar);
|
||||
//~^ ERROR named arguments cannot follow explicit register arguments
|
||||
asm!("{1}", in("eax") foo, const bar);
|
||||
//~^ ERROR positional arguments cannot follow named arguments or explicit register arguments
|
||||
}
|
||||
}
|
||||
162
src/test/ui/asm/parse-error.stderr
Normal file
162
src/test/ui/asm/parse-error.stderr
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
error: requires at least a template string argument
|
||||
--> $DIR/parse-error.rs:9:9
|
||||
|
|
||||
LL | asm!();
|
||||
| ^^^^^^^
|
||||
|
||||
error: asm template must be a string literal
|
||||
--> $DIR/parse-error.rs:11:14
|
||||
|
|
||||
LL | asm!(foo);
|
||||
| ^^^
|
||||
|
||||
error: expected token: `,`
|
||||
--> $DIR/parse-error.rs:13:19
|
||||
|
|
||||
LL | asm!("{}" foo);
|
||||
| ^^^ expected `,`
|
||||
|
||||
error: expected one of `const`, `in`, `inlateout`, `inout`, `lateout`, `options`, `out`, or `sym`, found `foo`
|
||||
--> $DIR/parse-error.rs:15:20
|
||||
|
|
||||
LL | asm!("{}", foo);
|
||||
| ^^^ expected one of 8 possible tokens
|
||||
|
||||
error: expected `(`, found `foo`
|
||||
--> $DIR/parse-error.rs:17:23
|
||||
|
|
||||
LL | asm!("{}", in foo);
|
||||
| ^^^ expected `(`
|
||||
|
||||
error: expected `)`, found `foo`
|
||||
--> $DIR/parse-error.rs:19:27
|
||||
|
|
||||
LL | asm!("{}", in(reg foo));
|
||||
| ^^^ expected `)`
|
||||
|
||||
error: expected expression, found end of macro arguments
|
||||
--> $DIR/parse-error.rs:21:27
|
||||
|
|
||||
LL | asm!("{}", in(reg));
|
||||
| ^ expected expression
|
||||
|
||||
error: expected register class or explicit register
|
||||
--> $DIR/parse-error.rs:23:26
|
||||
|
|
||||
LL | asm!("{}", inout(=) foo => bar);
|
||||
| ^
|
||||
|
||||
error: expected expression, found end of macro arguments
|
||||
--> $DIR/parse-error.rs:25:37
|
||||
|
|
||||
LL | asm!("{}", inout(reg) foo =>);
|
||||
| ^ expected expression
|
||||
|
||||
error: expected one of `!`, `,`, `.`, `::`, `?`, `{`, or an operator, found `=>`
|
||||
--> $DIR/parse-error.rs:27: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
|
||||
|
|
||||
LL | asm!("{}", sym foo + bar);
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: expected one of `)`, `att_syntax`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, or `readonly`, found `foo`
|
||||
--> $DIR/parse-error.rs:31:26
|
||||
|
|
||||
LL | asm!("", options(foo));
|
||||
| ^^^ expected one of 8 possible tokens
|
||||
|
||||
error: expected one of `)` or `,`, found `foo`
|
||||
--> $DIR/parse-error.rs:33:32
|
||||
|
|
||||
LL | asm!("", options(nomem foo));
|
||||
| ^^^ expected one of `)` or `,`
|
||||
|
||||
error: expected one of `)`, `att_syntax`, `nomem`, `noreturn`, `nostack`, `preserves_flags`, `pure`, or `readonly`, found `foo`
|
||||
--> $DIR/parse-error.rs:35:33
|
||||
|
|
||||
LL | asm!("", options(nomem, foo));
|
||||
| ^^^ expected one of 8 possible tokens
|
||||
|
||||
error: asm options cannot be specified multiple times
|
||||
--> $DIR/parse-error.rs:37:29
|
||||
|
|
||||
LL | asm!("", options(), options());
|
||||
| --------- ^^^^^^^^^ duplicate options
|
||||
| |
|
||||
| previously here
|
||||
|
||||
error: asm options cannot be specified multiple times
|
||||
--> $DIR/parse-error.rs:39:29
|
||||
|
|
||||
LL | asm!("", options(), options(), options());
|
||||
| --------- ^^^^^^^^^ duplicate options
|
||||
| |
|
||||
| previously here
|
||||
|
||||
error: asm options cannot be specified multiple times
|
||||
--> $DIR/parse-error.rs:39:40
|
||||
|
|
||||
LL | asm!("", options(), options(), options());
|
||||
| --------- ^^^^^^^^^ duplicate options
|
||||
| |
|
||||
| previously here
|
||||
|
||||
error: arguments are not allowed after options
|
||||
--> $DIR/parse-error.rs:42:31
|
||||
|
|
||||
LL | asm!("{}", options(), const foo);
|
||||
| --------- ^^^^^^^^^ argument
|
||||
| |
|
||||
| previous options
|
||||
|
||||
error: duplicate argument named `a`
|
||||
--> $DIR/parse-error.rs:44:36
|
||||
|
|
||||
LL | asm!("{a}", a = const foo, a = const bar);
|
||||
| ------------- ^^^^^^^^^^^^^ duplicate argument
|
||||
| |
|
||||
| previously here
|
||||
|
||||
error: argument never used
|
||||
--> $DIR/parse-error.rs:44:36
|
||||
|
|
||||
LL | asm!("{a}", a = const foo, a = const bar);
|
||||
| ^^^^^^^^^^^^^ argument never used
|
||||
|
||||
error: explicit register arguments cannot have names
|
||||
--> $DIR/parse-error.rs:47:18
|
||||
|
|
||||
LL | asm!("", a = in("eax") foo);
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: named arguments cannot follow explicit register arguments
|
||||
--> $DIR/parse-error.rs:49:36
|
||||
|
|
||||
LL | asm!("{a}", in("eax") foo, a = const bar);
|
||||
| ------------- ^^^^^^^^^^^^^ named argument
|
||||
| |
|
||||
| explicit register argument
|
||||
|
||||
error: named arguments cannot follow explicit register arguments
|
||||
--> $DIR/parse-error.rs:51:36
|
||||
|
|
||||
LL | asm!("{a}", in("eax") foo, a = const bar);
|
||||
| ------------- ^^^^^^^^^^^^^ named argument
|
||||
| |
|
||||
| explicit register argument
|
||||
|
||||
error: positional arguments cannot follow named arguments or explicit register arguments
|
||||
--> $DIR/parse-error.rs:53:36
|
||||
|
|
||||
LL | asm!("{1}", in("eax") foo, const bar);
|
||||
| ------------- ^^^^^^^^^ positional argument
|
||||
| |
|
||||
| explicit register argument
|
||||
|
||||
error: aborting due to 24 previous errors
|
||||
|
||||
16
src/test/ui/asm/rustfix-asm.fixed
Normal file
16
src/test/ui/asm/rustfix-asm.fixed
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
// run-rustfix
|
||||
// only-x86_64
|
||||
|
||||
#![feature(asm, llvm_asm)]
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let x = 1;
|
||||
let y: i32;
|
||||
llvm_asm!("" :: "r" (x));
|
||||
//~^ ERROR legacy asm! syntax is no longer supported
|
||||
llvm_asm!("" : "=r" (y));
|
||||
//~^ ERROR legacy asm! syntax is no longer supported
|
||||
let _ = y;
|
||||
}
|
||||
}
|
||||
16
src/test/ui/asm/rustfix-asm.rs
Normal file
16
src/test/ui/asm/rustfix-asm.rs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
// run-rustfix
|
||||
// only-x86_64
|
||||
|
||||
#![feature(asm, llvm_asm)]
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let x = 1;
|
||||
let y: i32;
|
||||
asm!("" :: "r" (x));
|
||||
//~^ ERROR legacy asm! syntax is no longer supported
|
||||
asm!("" : "=r" (y));
|
||||
//~^ ERROR legacy asm! syntax is no longer supported
|
||||
let _ = y;
|
||||
}
|
||||
}
|
||||
18
src/test/ui/asm/rustfix-asm.stderr
Normal file
18
src/test/ui/asm/rustfix-asm.stderr
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
error: legacy asm! syntax is no longer supported
|
||||
--> $DIR/rustfix-asm.rs:10:9
|
||||
|
|
||||
LL | asm!("" :: "r" (x));
|
||||
| ----^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| help: replace with: `llvm_asm!`
|
||||
|
||||
error: legacy asm! syntax is no longer supported
|
||||
--> $DIR/rustfix-asm.rs:12:9
|
||||
|
|
||||
LL | asm!("" : "=r" (y));
|
||||
| ----^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| help: replace with: `llvm_asm!`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
25
src/test/ui/asm/type-check-1.rs
Normal file
25
src/test/ui/asm/type-check-1.rs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
// only-x86_64
|
||||
|
||||
#![feature(asm)]
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
// Outputs must be place expressions
|
||||
|
||||
asm!("{}", in(reg) 1 + 2);
|
||||
asm!("{}", out(reg) 1 + 2);
|
||||
//~^ ERROR invalid asm output
|
||||
asm!("{}", inout(reg) 1 + 2);
|
||||
//~^ ERROR invalid asm output
|
||||
|
||||
// Operands must be sized
|
||||
|
||||
let v: [u64; 3] = [0, 1, 2];
|
||||
asm!("{}", in(reg) v[..]);
|
||||
//~^ ERROR the size for values of type `[u64]` cannot be known at compilation time
|
||||
asm!("{}", out(reg) v[..]);
|
||||
//~^ ERROR the size for values of type `[u64]` cannot be known at compilation time
|
||||
asm!("{}", inout(reg) v[..]);
|
||||
//~^ ERROR the size for values of type `[u64]` cannot be known at compilation time
|
||||
}
|
||||
}
|
||||
45
src/test/ui/asm/type-check-1.stderr
Normal file
45
src/test/ui/asm/type-check-1.stderr
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
error: invalid asm output
|
||||
--> $DIR/type-check-1.rs:10:29
|
||||
|
|
||||
LL | asm!("{}", out(reg) 1 + 2);
|
||||
| ^^^^^ cannot assign to this expression
|
||||
|
||||
error: invalid asm output
|
||||
--> $DIR/type-check-1.rs:12: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:18:28
|
||||
|
|
||||
LL | asm!("{}", in(reg) v[..]);
|
||||
| ^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `[u64]`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= 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:20:29
|
||||
|
|
||||
LL | asm!("{}", out(reg) v[..]);
|
||||
| ^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `[u64]`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= 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:22:31
|
||||
|
|
||||
LL | asm!("{}", inout(reg) v[..]);
|
||||
| ^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `[u64]`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= note: all inline asm arguments must have a statically known size
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
104
src/test/ui/asm/type-check-2.rs
Normal file
104
src/test/ui/asm/type-check-2.rs
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
// only-x86_64
|
||||
|
||||
#![feature(asm, repr_simd, never_type)]
|
||||
|
||||
#[repr(simd)]
|
||||
struct SimdNonCopy(f32, f32, f32, f32);
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
// Inputs must be initialized
|
||||
|
||||
let x: u64;
|
||||
asm!("{}", in(reg) x);
|
||||
//~^ ERROR use of possibly-uninitialized variable: `x`
|
||||
let mut y: u64;
|
||||
asm!("{}", inout(reg) y);
|
||||
//~^ ERROR use of possibly-uninitialized variable: `y`
|
||||
let _ = y;
|
||||
|
||||
// Outputs require mutable places
|
||||
|
||||
let v: Vec<u64> = vec![0, 1, 2];
|
||||
asm!("{}", in(reg) v[0]);
|
||||
asm!("{}", out(reg) v[0]);
|
||||
//~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
|
||||
asm!("{}", inout(reg) v[0]);
|
||||
//~^ ERROR cannot borrow `v` as mutable, as it is not declared as mutable
|
||||
|
||||
// Const operands must be integer or floats, and must be constants.
|
||||
|
||||
let x = 0;
|
||||
const C: i32 = 0;
|
||||
const fn const_foo(x: i32) -> i32 {
|
||||
x
|
||||
}
|
||||
const fn const_bar<T>(x: T) -> T {
|
||||
x
|
||||
}
|
||||
asm!("{}", const 0i32);
|
||||
asm!("{}", const 0f32);
|
||||
asm!("{}", const 0 as *mut u8);
|
||||
//~^ ERROR asm `const` arguments must be integer or floating-point values
|
||||
asm!("{}", const &0);
|
||||
//~^ ERROR asm `const` arguments must be integer or floating-point values
|
||||
asm!("{}", const x);
|
||||
//~^ ERROR argument 1 is required to be a constant
|
||||
asm!("{}", const const_foo(0));
|
||||
asm!("{}", const const_foo(x));
|
||||
//~^ ERROR argument 1 is required to be a constant
|
||||
asm!("{}", const const_bar(0));
|
||||
asm!("{}", const const_bar(x));
|
||||
//~^ ERROR argument 1 is required to be a constant
|
||||
|
||||
// Sym operands must point to a function or static
|
||||
|
||||
static S: i32 = 0;
|
||||
asm!("{}", sym S);
|
||||
asm!("{}", sym main);
|
||||
asm!("{}", sym C);
|
||||
//~^ ERROR asm `sym` operand must point to a fn or static
|
||||
asm!("{}", sym x);
|
||||
//~^ ERROR asm `sym` operand must point to a fn or static
|
||||
|
||||
// Register operands must be Copy
|
||||
|
||||
asm!("{}", in(xmm_reg) SimdNonCopy(0.0, 0.0, 0.0, 0.0));
|
||||
//~^ ERROR arguments for inline assembly must be copyable
|
||||
|
||||
// Register operands must be integers, floats, SIMD vectors, pointers or
|
||||
// function pointers.
|
||||
|
||||
asm!("{}", in(reg) 0i64);
|
||||
asm!("{}", in(reg) 0f64);
|
||||
asm!("{}", in(xmm_reg) std::arch::x86_64::_mm_setzero_ps());
|
||||
asm!("{}", in(reg) 0 as *const u8);
|
||||
asm!("{}", in(reg) 0 as *mut u8);
|
||||
asm!("{}", in(reg) main as fn());
|
||||
asm!("{}", in(reg) |x: i32| x);
|
||||
//~^ ERROR cannot use value of type
|
||||
asm!("{}", in(reg) vec![0]);
|
||||
//~^ ERROR cannot use value of type `std::vec::Vec<i32>` for inline assembly
|
||||
asm!("{}", in(reg) (1, 2, 3));
|
||||
//~^ ERROR cannot use value of type `(i32, i32, i32)` for inline assembly
|
||||
asm!("{}", in(reg) [1, 2, 3]);
|
||||
//~^ ERROR cannot use value of type `[i32; 3]` for inline assembly
|
||||
|
||||
// Register inputs (but not outputs) allow references and function types
|
||||
|
||||
let mut f = main;
|
||||
let mut r = &mut 0;
|
||||
asm!("{}", in(reg) f);
|
||||
asm!("{}", inout(reg) f);
|
||||
//~^ ERROR cannot use value of type `fn() {main}` for inline assembly
|
||||
asm!("{}", in(reg) r);
|
||||
asm!("{}", inout(reg) r);
|
||||
//~^ ERROR cannot use value of type `&mut i32` for inline assembly
|
||||
let _ = (f, r);
|
||||
|
||||
// Type checks ignore never type
|
||||
|
||||
let u: ! = unreachable!();
|
||||
asm!("{}", in(reg) u);
|
||||
}
|
||||
}
|
||||
133
src/test/ui/asm/type-check-2.stderr
Normal file
133
src/test/ui/asm/type-check-2.stderr
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
error: asm `const` arguments must be integer or floating-point values
|
||||
--> $DIR/type-check-2.rs:41:26
|
||||
|
|
||||
LL | asm!("{}", const 0 as *mut u8);
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: asm `const` arguments must be integer or floating-point values
|
||||
--> $DIR/type-check-2.rs:43:26
|
||||
|
|
||||
LL | asm!("{}", const &0);
|
||||
| ^^
|
||||
|
||||
error: arguments for inline assembly must be copyable
|
||||
--> $DIR/type-check-2.rs:66: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:78:28: 78:38]` for inline assembly
|
||||
--> $DIR/type-check-2.rs:78:28
|
||||
|
|
||||
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 `std::vec::Vec<i32>` for inline assembly
|
||||
--> $DIR/type-check-2.rs:80:28
|
||||
|
|
||||
LL | asm!("{}", in(reg) vec![0]);
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
|
||||
= note: this error originates in a macro (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:82:28
|
||||
|
|
||||
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:84:28
|
||||
|
|
||||
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:92:31
|
||||
|
|
||||
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:95: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:59:24
|
||||
|
|
||||
LL | asm!("{}", sym C);
|
||||
| ^
|
||||
|
||||
error: asm `sym` operand must point to a fn or static
|
||||
--> $DIR/type-check-2.rs:61:24
|
||||
|
|
||||
LL | asm!("{}", sym x);
|
||||
| ^
|
||||
|
||||
error: argument 1 is required to be a constant
|
||||
--> $DIR/type-check-2.rs:45:9
|
||||
|
|
||||
LL | asm!("{}", const x);
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: argument 1 is required to be a constant
|
||||
--> $DIR/type-check-2.rs:48:9
|
||||
|
|
||||
LL | asm!("{}", const const_foo(x));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: argument 1 is required to be a constant
|
||||
--> $DIR/type-check-2.rs:51:9
|
||||
|
|
||||
LL | asm!("{}", const const_bar(x));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0381]: use of possibly-uninitialized variable: `x`
|
||||
--> $DIR/type-check-2.rs:13: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
|
||||
|
|
||||
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
|
||||
|
|
||||
LL | let v: Vec<u64> = vec![0, 1, 2];
|
||||
| - help: consider changing this to be mutable: `mut v`
|
||||
LL | asm!("{}", in(reg) v[0]);
|
||||
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
|
||||
|
|
||||
LL | let v: Vec<u64> = vec![0, 1, 2];
|
||||
| - help: consider changing this to be mutable: `mut v`
|
||||
...
|
||||
LL | asm!("{}", inout(reg) v[0]);
|
||||
| ^ cannot borrow as mutable
|
||||
|
||||
error: aborting due to 18 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0381, E0596.
|
||||
For more information about an error, try `rustc --explain E0381`.
|
||||
71
src/test/ui/asm/type-check-3.rs
Normal file
71
src/test/ui/asm/type-check-3.rs
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
// only-x86_64
|
||||
// compile-flags: -C target-feature=+avx512f
|
||||
|
||||
#![feature(asm)]
|
||||
|
||||
use std::arch::x86_64::{_mm256_setzero_ps, _mm_setzero_ps};
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
// Types must be in the whitelist for the register class
|
||||
|
||||
asm!("{}", in(reg) 0i128);
|
||||
//~^ ERROR type `i128` cannot be used with this register class
|
||||
asm!("{}", in(reg) _mm_setzero_ps());
|
||||
//~^ ERROR type `std::arch::x86_64::__m128` cannot be used with this register class
|
||||
asm!("{}", in(reg) _mm256_setzero_ps());
|
||||
//~^ ERROR type `std::arch::x86_64::__m256` cannot be used with this register class
|
||||
asm!("{}", in(xmm_reg) 0u8);
|
||||
//~^ ERROR type `u8` cannot be used with this register class
|
||||
asm!("{:e}", in(reg) 0i32);
|
||||
asm!("{}", in(xmm_reg) 0i32);
|
||||
asm!("{:e}", in(reg) 0f32);
|
||||
asm!("{}", in(xmm_reg) 0f32);
|
||||
asm!("{}", in(xmm_reg) _mm_setzero_ps());
|
||||
asm!("{:x}", in(ymm_reg) _mm_setzero_ps());
|
||||
asm!("{}", in(kreg) 0u16);
|
||||
asm!("{}", in(kreg) 0u64);
|
||||
//~^ ERROR `avx512bw` target feature is not enabled
|
||||
|
||||
// Template modifier suggestions for sub-registers
|
||||
|
||||
asm!("{0} {0}", in(reg) 0i16);
|
||||
//~^ WARN formatting may not be suitable for sub-register argument
|
||||
asm!("{0} {0:x}", in(reg) 0i16);
|
||||
//~^ WARN formatting may not be suitable for sub-register argument
|
||||
asm!("{}", in(reg) 0i32);
|
||||
//~^ WARN formatting may not be suitable for sub-register argument
|
||||
asm!("{}", in(reg) 0i64);
|
||||
asm!("{}", in(ymm_reg) 0i64);
|
||||
//~^ WARN formatting may not be suitable for sub-register argument
|
||||
asm!("{}", in(ymm_reg) _mm256_setzero_ps());
|
||||
asm!("{:l}", in(reg) 0i16);
|
||||
asm!("{:l}", in(reg) 0i32);
|
||||
asm!("{:l}", in(reg) 0i64);
|
||||
asm!("{:x}", in(ymm_reg) 0i64);
|
||||
asm!("{:x}", in(ymm_reg) _mm256_setzero_ps());
|
||||
|
||||
// Suggest different register class for type
|
||||
|
||||
asm!("{}", in(reg) 0i8);
|
||||
//~^ ERROR type `i8` cannot be used with this register class
|
||||
asm!("{}", in(reg_byte) 0i8);
|
||||
|
||||
// Split inout operands must have compatible types
|
||||
|
||||
let mut val_i16: i16;
|
||||
let mut val_f32: f32;
|
||||
let mut val_u32: u32;
|
||||
let mut val_u64: u64;
|
||||
let mut val_ptr: *mut u8;
|
||||
asm!("{:r}", inout(reg) 0u16 => val_i16);
|
||||
asm!("{:r}", inout(reg) 0u32 => val_f32);
|
||||
//~^ ERROR incompatible types for asm inout argument
|
||||
asm!("{:r}", inout(reg) 0u32 => val_ptr);
|
||||
//~^ ERROR incompatible types for asm inout argument
|
||||
asm!("{:r}", inout(reg) main => val_u32);
|
||||
//~^ ERROR incompatible types for asm inout argument
|
||||
asm!("{:r}", inout(reg) 0u64 => val_ptr);
|
||||
asm!("{:r}", inout(reg) main => val_u64);
|
||||
}
|
||||
}
|
||||
118
src/test/ui/asm/type-check-3.stderr
Normal file
118
src/test/ui/asm/type-check-3.stderr
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
error: type `i128` cannot be used with this register class
|
||||
--> $DIR/type-check-3.rs:12:28
|
||||
|
|
||||
LL | asm!("{}", in(reg) 0i128);
|
||||
| ^^^^^
|
||||
|
|
||||
= note: register class `reg` supports these types: i16, i32, i64, f32, f64
|
||||
|
||||
error: type `std::arch::x86_64::__m128` cannot be used with this register class
|
||||
--> $DIR/type-check-3.rs:14:28
|
||||
|
|
||||
LL | asm!("{}", in(reg) _mm_setzero_ps());
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: register class `reg` supports these types: i16, i32, i64, f32, f64
|
||||
|
||||
error: type `std::arch::x86_64::__m256` cannot be used with this register class
|
||||
--> $DIR/type-check-3.rs:16:28
|
||||
|
|
||||
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
|
||||
|
|
||||
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
|
||||
|
|
||||
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
|
||||
|
|
||||
LL | asm!("{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`
|
||||
|
||||
warning: formatting may not be suitable for sub-register argument
|
||||
--> $DIR/type-check-3.rs:34:15
|
||||
|
|
||||
LL | asm!("{0} {0:x}", in(reg) 0i16);
|
||||
| ^^^ ---- for this argument
|
||||
|
|
||||
= 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`
|
||||
|
||||
warning: formatting may not be suitable for sub-register argument
|
||||
--> $DIR/type-check-3.rs:36:15
|
||||
|
|
||||
LL | asm!("{}", in(reg) 0i32);
|
||||
| ^^ ---- for this argument
|
||||
|
|
||||
= help: use the `e` modifier to have the register formatted as `eax`
|
||||
= 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
|
||||
|
|
||||
LL | asm!("{}", in(ymm_reg) 0i64);
|
||||
| ^^ ---- for this argument
|
||||
|
|
||||
= help: use the `x` modifier to have the register formatted as `xmm0`
|
||||
= 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
|
||||
|
|
||||
LL | asm!("{}", in(reg) 0i8);
|
||||
| ^^^
|
||||
|
|
||||
= note: register class `reg` supports these types: i16, i32, i64, f32, f64
|
||||
= help: consider using the `reg_byte` register class instead
|
||||
|
||||
error: incompatible types for asm inout argument
|
||||
--> $DIR/type-check-3.rs:62:33
|
||||
|
|
||||
LL | asm!("{:r}", inout(reg) 0u32 => val_f32);
|
||||
| ^^^^ ^^^^^^^ type `f32`
|
||||
| |
|
||||
| type `u32`
|
||||
|
|
||||
= 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
|
||||
|
|
||||
LL | asm!("{:r}", inout(reg) 0u32 => val_ptr);
|
||||
| ^^^^ ^^^^^^^ type `*mut u8`
|
||||
| |
|
||||
| type `u32`
|
||||
|
|
||||
= 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
|
||||
|
|
||||
LL | asm!("{:r}", inout(reg) main => val_u32);
|
||||
| ^^^^ ^^^^^^^ type `u32`
|
||||
| |
|
||||
| type `fn()`
|
||||
|
|
||||
= note: asm inout arguments must have the same type, unless they are both pointers or integers of the same size
|
||||
|
||||
error: aborting due to 9 previous errors; 4 warnings emitted
|
||||
|
||||
23
src/test/ui/asm/type-check-4.rs
Normal file
23
src/test/ui/asm/type-check-4.rs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// only-x86_64
|
||||
|
||||
#![feature(asm)]
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
// Can't output to borrowed values.
|
||||
|
||||
let mut a = 0isize;
|
||||
let p = &a;
|
||||
asm!("{}", out(reg) a);
|
||||
//~^ cannot assign to `a` because it is borrowed
|
||||
println!("{}", p);
|
||||
|
||||
// Can't read from mutable borrowed values.
|
||||
|
||||
let mut a = 0isize;
|
||||
let p = &mut a;
|
||||
asm!("{}", in(reg) a);
|
||||
//~^ cannot use `a` because it was mutably borrowed
|
||||
println!("{}", p);
|
||||
}
|
||||
}
|
||||
26
src/test/ui/asm/type-check-4.stderr
Normal file
26
src/test/ui/asm/type-check-4.stderr
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
error[E0506]: cannot assign to `a` because it is borrowed
|
||||
--> $DIR/type-check-4.rs:11:9
|
||||
|
|
||||
LL | let p = &a;
|
||||
| -- borrow of `a` occurs here
|
||||
LL | asm!("{}", out(reg) a);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `a` occurs here
|
||||
LL |
|
||||
LL | println!("{}", p);
|
||||
| - borrow later used here
|
||||
|
||||
error[E0503]: cannot use `a` because it was mutably borrowed
|
||||
--> $DIR/type-check-4.rs:19:28
|
||||
|
|
||||
LL | let p = &mut a;
|
||||
| ------ borrow of `a` occurs here
|
||||
LL | asm!("{}", in(reg) a);
|
||||
| ^ use of borrowed `a`
|
||||
LL |
|
||||
LL | println!("{}", p);
|
||||
| - borrow later used here
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0503, E0506.
|
||||
For more information about an error, try `rustc --explain E0503`.
|
||||
|
|
@ -2,8 +2,9 @@
|
|||
|
||||
fn main() {
|
||||
unsafe {
|
||||
asm!(""); //~ ERROR inline assembly is not stable enough
|
||||
//~^ WARN use of deprecated item 'asm'
|
||||
llvm_asm!(""); //~ ERROR inline assembly is not stable enough
|
||||
asm!("");
|
||||
//~^ ERROR inline assembly is not stable enough
|
||||
llvm_asm!("");
|
||||
//~^ ERROR LLVM-style inline assembly will never be stabilized
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@ error[E0658]: use of unstable library feature 'asm': inline assembly is not stab
|
|||
LL | asm!("");
|
||||
| ^^^
|
||||
|
|
||||
= note: see issue #70173 <https://github.com/rust-lang/rust/issues/70173> for more information
|
||||
= note: see issue #72016 <https://github.com/rust-lang/rust/issues/72016> for more information
|
||||
= help: add `#![feature(asm)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: use of unstable library feature 'llvm_asm': inline assembly is not stable enough for use and is subject to change
|
||||
error[E0658]: use of unstable library feature 'llvm_asm': LLVM-style inline assembly will never be stabilized, prefer using asm! instead
|
||||
--> $DIR/feature-gate-asm.rs:7:9
|
||||
|
|
||||
LL | llvm_asm!("");
|
||||
|
|
@ -16,14 +16,6 @@ LL | llvm_asm!("");
|
|||
= note: see issue #70173 <https://github.com/rust-lang/rust/issues/70173> for more information
|
||||
= help: add `#![feature(llvm_asm)]` to the crate attributes to enable
|
||||
|
||||
warning: use of deprecated item 'asm': the syntax of asm! will change soon, use llvm_asm! to avoid breakage
|
||||
--> $DIR/feature-gate-asm.rs:5:9
|
||||
|
|
||||
LL | asm!("");
|
||||
| ^^^ help: replace the use of the deprecated item: `llvm_asm`
|
||||
|
|
||||
= note: `#[warn(deprecated)]` on by default
|
||||
|
||||
error: aborting due to 2 previous errors; 1 warning emitted
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
|
|||
|
|
@ -2,8 +2,9 @@
|
|||
|
||||
fn main() {
|
||||
unsafe {
|
||||
println!("{:?}", asm!("")); //~ ERROR inline assembly is not stable
|
||||
//~^ WARN use of deprecated item 'asm'
|
||||
println!("{:?}", llvm_asm!("")); //~ ERROR inline assembly is not stable
|
||||
println!("{:?}", asm!(""));
|
||||
//~^ ERROR inline assembly is not stable enough
|
||||
println!("{:?}", llvm_asm!(""));
|
||||
//~^ ERROR LLVM-style inline assembly will never be stabilized
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@ error[E0658]: use of unstable library feature 'asm': inline assembly is not stab
|
|||
LL | println!("{:?}", asm!(""));
|
||||
| ^^^
|
||||
|
|
||||
= note: see issue #70173 <https://github.com/rust-lang/rust/issues/70173> for more information
|
||||
= note: see issue #72016 <https://github.com/rust-lang/rust/issues/72016> for more information
|
||||
= help: add `#![feature(asm)]` to the crate attributes to enable
|
||||
|
||||
error[E0658]: use of unstable library feature 'llvm_asm': inline assembly is not stable enough for use and is subject to change
|
||||
error[E0658]: use of unstable library feature 'llvm_asm': LLVM-style inline assembly will never be stabilized, prefer using asm! instead
|
||||
--> $DIR/feature-gate-asm2.rs:7:26
|
||||
|
|
||||
LL | println!("{:?}", llvm_asm!(""));
|
||||
|
|
@ -16,14 +16,6 @@ LL | println!("{:?}", llvm_asm!(""));
|
|||
= note: see issue #70173 <https://github.com/rust-lang/rust/issues/70173> for more information
|
||||
= help: add `#![feature(llvm_asm)]` to the crate attributes to enable
|
||||
|
||||
warning: use of deprecated item 'asm': the syntax of asm! will change soon, use llvm_asm! to avoid breakage
|
||||
--> $DIR/feature-gate-asm2.rs:5:26
|
||||
|
|
||||
LL | println!("{:?}", asm!(""));
|
||||
| ^^^ help: replace the use of the deprecated item: `llvm_asm`
|
||||
|
|
||||
= note: `#[warn(deprecated)]` on by default
|
||||
|
||||
error: aborting due to 2 previous errors; 1 warning emitted
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
|
|||
|
|
@ -5,5 +5,5 @@ macro_rules! m {
|
|||
}
|
||||
|
||||
macro_rules! n {
|
||||
() => { unsafe { llvm_asm!(include_str!("file.txt")); } }
|
||||
() => { unsafe { asm!(include_str!("file.txt")); } }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// ignore-emscripten no llvm_asm! support
|
||||
// build-pass (FIXME(62277): could be check-pass?)
|
||||
#![feature(llvm_asm)]
|
||||
#![feature(asm)]
|
||||
#![allow(unused)]
|
||||
|
||||
#[macro_use]
|
||||
|
|
|
|||
|
|
@ -3,13 +3,14 @@
|
|||
// test that errors in a (selection) of macros don't kill compilation
|
||||
// immediately, so that we get more errors listed at a time.
|
||||
|
||||
#![feature(llvm_asm)]
|
||||
#![feature(asm, llvm_asm)]
|
||||
#![feature(trace_macros, concat_idents)]
|
||||
|
||||
#[derive(Default)] //~ ERROR
|
||||
enum OrDeriveThis {}
|
||||
|
||||
fn main() {
|
||||
asm!(invalid); //~ ERROR
|
||||
llvm_asm!(invalid); //~ ERROR
|
||||
|
||||
concat_idents!("not", "idents"); //~ ERROR
|
||||
|
|
|
|||
|
|
@ -6,44 +6,50 @@ LL | #[derive(Default)]
|
|||
|
|
||||
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: asm template must be a string literal
|
||||
--> $DIR/macros-nonfatal-errors.rs:13:10
|
||||
|
|
||||
LL | asm!(invalid);
|
||||
| ^^^^^^^
|
||||
|
||||
error: inline assembly must be a string literal
|
||||
--> $DIR/macros-nonfatal-errors.rs:13:15
|
||||
--> $DIR/macros-nonfatal-errors.rs:14:15
|
||||
|
|
||||
LL | llvm_asm!(invalid);
|
||||
| ^^^^^^^
|
||||
|
||||
error: concat_idents! requires ident args.
|
||||
--> $DIR/macros-nonfatal-errors.rs:15:5
|
||||
--> $DIR/macros-nonfatal-errors.rs:16:5
|
||||
|
|
||||
LL | concat_idents!("not", "idents");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: argument must be a string literal
|
||||
--> $DIR/macros-nonfatal-errors.rs:17:17
|
||||
--> $DIR/macros-nonfatal-errors.rs:18:17
|
||||
|
|
||||
LL | option_env!(invalid);
|
||||
| ^^^^^^^
|
||||
|
||||
error: expected string literal
|
||||
--> $DIR/macros-nonfatal-errors.rs:18:10
|
||||
--> $DIR/macros-nonfatal-errors.rs:19:10
|
||||
|
|
||||
LL | env!(invalid);
|
||||
| ^^^^^^^
|
||||
|
||||
error: expected string literal
|
||||
--> $DIR/macros-nonfatal-errors.rs:19:10
|
||||
--> $DIR/macros-nonfatal-errors.rs:20:10
|
||||
|
|
||||
LL | env!(foo, abr, baz);
|
||||
| ^^^
|
||||
|
||||
error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined
|
||||
--> $DIR/macros-nonfatal-errors.rs:20:5
|
||||
--> $DIR/macros-nonfatal-errors.rs:21:5
|
||||
|
|
||||
LL | env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: format argument must be a string literal
|
||||
--> $DIR/macros-nonfatal-errors.rs:22:13
|
||||
--> $DIR/macros-nonfatal-errors.rs:23:13
|
||||
|
|
||||
LL | format!(invalid);
|
||||
| ^^^^^^^
|
||||
|
|
@ -54,19 +60,19 @@ LL | format!("{}", invalid);
|
|||
| ^^^^^
|
||||
|
||||
error: argument must be a string literal
|
||||
--> $DIR/macros-nonfatal-errors.rs:24:14
|
||||
--> $DIR/macros-nonfatal-errors.rs:25:14
|
||||
|
|
||||
LL | include!(invalid);
|
||||
| ^^^^^^^
|
||||
|
||||
error: argument must be a string literal
|
||||
--> $DIR/macros-nonfatal-errors.rs:26:18
|
||||
--> $DIR/macros-nonfatal-errors.rs:27:18
|
||||
|
|
||||
LL | include_str!(invalid);
|
||||
| ^^^^^^^
|
||||
|
||||
error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2)
|
||||
--> $DIR/macros-nonfatal-errors.rs:27:5
|
||||
--> $DIR/macros-nonfatal-errors.rs:28:5
|
||||
|
|
||||
LL | include_str!("i'd be quite surprised if a file with this name existed");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -74,13 +80,13 @@ LL | include_str!("i'd be quite surprised if a file with this name existed")
|
|||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: argument must be a string literal
|
||||
--> $DIR/macros-nonfatal-errors.rs:28:20
|
||||
--> $DIR/macros-nonfatal-errors.rs:29:20
|
||||
|
|
||||
LL | include_bytes!(invalid);
|
||||
| ^^^^^^^
|
||||
|
||||
error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: $FILE_NOT_FOUND_MSG (os error 2)
|
||||
--> $DIR/macros-nonfatal-errors.rs:29:5
|
||||
--> $DIR/macros-nonfatal-errors.rs:30:5
|
||||
|
|
||||
LL | include_bytes!("i'd be quite surprised if a file with this name existed");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -88,11 +94,11 @@ LL | include_bytes!("i'd be quite surprised if a file with this name existed
|
|||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: trace_macros! accepts only `true` or `false`
|
||||
--> $DIR/macros-nonfatal-errors.rs:31:5
|
||||
--> $DIR/macros-nonfatal-errors.rs:32:5
|
||||
|
|
||||
LL | trace_macros!(invalid);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 14 previous errors
|
||||
error: aborting due to 15 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0665`.
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
// gate-test-movbe_target_feature
|
||||
// gate-test-rtm_target_feature
|
||||
// gate-test-f16c_target_feature
|
||||
// gate-test-riscv_target_feature
|
||||
|
||||
#[target_feature(enable = "avx512bw")]
|
||||
//~^ ERROR: currently unstable
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error[E0658]: the target feature `avx512bw` is currently unstable
|
||||
--> $DIR/gate.rs:29:18
|
||||
--> $DIR/gate.rs:30:18
|
||||
|
|
||||
LL | #[target_feature(enable = "avx512bw")]
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue