mirror of
				https://github.com/rust-lang/rust.git
				synced 2025-11-03 22:49:17 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			235 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			235 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
//@ needs-asm-support
 | 
						|
//@ ignore-nvptx64
 | 
						|
//@ ignore-spirv
 | 
						|
 | 
						|
// Tests that the use of named labels in the `asm!` macro are linted against
 | 
						|
// except for in `#[naked]` fns.
 | 
						|
// Using a named label is incorrect as per the RFC because for most cases
 | 
						|
// the compiler cannot ensure that inline asm is emitted exactly once per
 | 
						|
// codegen unit (except for naked fns) and so the label could be duplicated
 | 
						|
// which causes less readable LLVM errors and in the worst cases causes ICEs
 | 
						|
// or segfaults based on system dependent behavior and codegen flags.
 | 
						|
 | 
						|
#![feature(naked_functions)]
 | 
						|
 | 
						|
use std::arch::{asm, global_asm, naked_asm};
 | 
						|
 | 
						|
#[no_mangle]
 | 
						|
pub static FOO: usize = 42;
 | 
						|
 | 
						|
fn main() {
 | 
						|
    unsafe {
 | 
						|
        // Basic usage
 | 
						|
        asm!("bar: nop"); //~ ERROR avoid using named labels
 | 
						|
 | 
						|
        // No following asm
 | 
						|
        asm!("abcd:"); //~ ERROR avoid using named labels
 | 
						|
 | 
						|
        // Multiple labels on one line
 | 
						|
        asm!("foo: bar1: nop");
 | 
						|
        //~^ ERROR avoid using named labels
 | 
						|
        //~^^ ERROR avoid using named labels
 | 
						|
 | 
						|
        // Multiple lines
 | 
						|
        asm!("foo1: nop", "nop"); //~ ERROR avoid using named labels
 | 
						|
        asm!("foo2: foo3: nop", "nop");
 | 
						|
        //~^ ERROR avoid using named labels
 | 
						|
        //~^^ ERROR avoid using named labels
 | 
						|
        asm!("nop", "foo4: nop"); //~ ERROR avoid using named labels
 | 
						|
        asm!("foo5: nop", "foo6: nop");
 | 
						|
        //~^ ERROR avoid using named labels
 | 
						|
        //~| ERROR avoid using named labels
 | 
						|
 | 
						|
        // Statement separator
 | 
						|
        asm!("foo7: nop; foo8: nop");
 | 
						|
        //~^ ERROR avoid using named labels
 | 
						|
        //~^^ ERROR avoid using named labels
 | 
						|
        asm!("foo9: nop; nop"); //~ ERROR avoid using named labels
 | 
						|
        asm!("nop; foo10: nop"); //~ ERROR avoid using named labels
 | 
						|
 | 
						|
        // Escaped newline
 | 
						|
        asm!("bar2: nop\n bar3: nop");
 | 
						|
        //~^ ERROR avoid using named labels
 | 
						|
        //~^^ ERROR avoid using named labels
 | 
						|
        asm!("bar4: nop\n nop"); //~ ERROR avoid using named labels
 | 
						|
        asm!("nop\n bar5: nop"); //~ ERROR avoid using named labels
 | 
						|
        asm!("nop\n bar6: bar7: nop");
 | 
						|
        //~^ ERROR avoid using named labels
 | 
						|
        //~^^ ERROR avoid using named labels
 | 
						|
 | 
						|
        // Raw strings
 | 
						|
        asm!(
 | 
						|
            r"
 | 
						|
            blah2: nop
 | 
						|
            blah3: nop
 | 
						|
            "
 | 
						|
        );
 | 
						|
        //~^^^^ ERROR avoid using named labels
 | 
						|
        //~^^^^ ERROR avoid using named labels
 | 
						|
 | 
						|
        asm!(
 | 
						|
            r###"
 | 
						|
            nop
 | 
						|
            nop ; blah4: nop
 | 
						|
            "###
 | 
						|
        );
 | 
						|
        //~^^^ ERROR avoid using named labels
 | 
						|
 | 
						|
        // Non-labels
 | 
						|
        // should not trigger lint, but may be invalid asm
 | 
						|
        asm!("ab cd: nop");
 | 
						|
 | 
						|
        // `blah:` does not trigger because labels need to be at the start
 | 
						|
        // of the statement, and there was already a non-label
 | 
						|
        asm!("1bar: blah: nop");
 | 
						|
 | 
						|
        // Only `blah1:` should trigger
 | 
						|
        asm!("blah1: 2bar: nop"); //~ ERROR avoid using named labels
 | 
						|
 | 
						|
        // Duplicate labels
 | 
						|
        asm!("def: def: nop");
 | 
						|
        //~^ ERROR avoid using named labels
 | 
						|
        //~^^ ERROR avoid using named labels
 | 
						|
        asm!("def: nop\ndef: nop");
 | 
						|
        //~^ ERROR avoid using named labels
 | 
						|
        //~^^ ERROR avoid using named labels
 | 
						|
        asm!("def: nop; def: nop");
 | 
						|
        //~^ ERROR avoid using named labels
 | 
						|
        //~^^ ERROR avoid using named labels
 | 
						|
 | 
						|
        // Trying to break parsing
 | 
						|
        asm!(":");
 | 
						|
        asm!("\n:\n");
 | 
						|
        asm!("::::");
 | 
						|
 | 
						|
        // 0x3A is a ':'
 | 
						|
        asm!("fooo\u{003A} nop"); //~ ERROR avoid using named labels
 | 
						|
        asm!("foooo\x3A nop"); //~ ERROR avoid using named labels
 | 
						|
 | 
						|
        // 0x0A is a newline
 | 
						|
        asm!("fooooo:\u{000A} nop"); //~ ERROR avoid using named labels
 | 
						|
        asm!("foooooo:\x0A nop"); //~ ERROR avoid using named labels
 | 
						|
 | 
						|
        // Intentionally breaking span finding
 | 
						|
        // equivalent to "ABC: nop"
 | 
						|
        asm!("\x41\x42\x43\x3A\x20\x6E\x6F\x70"); //~ ERROR avoid using named labels
 | 
						|
 | 
						|
        // Non-label colons - should pass
 | 
						|
        asm!("mov rax, qword ptr fs:[0]");
 | 
						|
 | 
						|
        // Comments
 | 
						|
        asm!(
 | 
						|
            r"
 | 
						|
            ab: nop // ab: does foo
 | 
						|
            // cd: nop
 | 
						|
            "
 | 
						|
        );
 | 
						|
        //~^^^^ ERROR avoid using named labels
 | 
						|
 | 
						|
        // Tests usage of colons in non-label positions
 | 
						|
        asm!(":lo12:FOO"); // this is apparently valid aarch64
 | 
						|
 | 
						|
        // is there an example that is valid x86 for this test?
 | 
						|
        asm!(":bbb nop");
 | 
						|
 | 
						|
        // non-ascii characters are not allowed in labels, so should not trigger the lint
 | 
						|
        asm!("Ù: nop");
 | 
						|
        asm!("testÙ: nop");
 | 
						|
        asm!("_Ù_: nop");
 | 
						|
 | 
						|
        // Format arguments should be conservatively assumed to be valid characters in labels
 | 
						|
        // Would emit `test_rax:` or similar
 | 
						|
        #[allow(asm_sub_register)]
 | 
						|
        {
 | 
						|
            asm!("test_{}: nop", in(reg) 10); //~ ERROR avoid using named labels
 | 
						|
        }
 | 
						|
        asm!("test_{}: nop", const 10); //~ ERROR avoid using named labels
 | 
						|
        asm!("test_{}: nop", sym main); //~ ERROR avoid using named labels
 | 
						|
        asm!("{}_test: nop", const 10); //~ ERROR avoid using named labels
 | 
						|
        asm!("test_{}_test: nop", const 10); //~ ERROR avoid using named labels
 | 
						|
        asm!("{}: nop", const 10); //~ ERROR avoid using named labels
 | 
						|
 | 
						|
        asm!("{uwu}: nop", uwu = const 10); //~ ERROR avoid using named labels
 | 
						|
        asm!("{0}: nop", const 10); //~ ERROR avoid using named labels
 | 
						|
        asm!("{1}: nop", "/* {0} */", const 10, const 20); //~ ERROR avoid using named labels
 | 
						|
 | 
						|
        // Test include_str in asm
 | 
						|
        asm!(include_str!("named-asm-labels.s"));
 | 
						|
        //~^ ERROR avoid using named labels
 | 
						|
        //~^^ ERROR avoid using named labels
 | 
						|
        //~^^^ ERROR avoid using named labels
 | 
						|
        //~^^^^ ERROR avoid using named labels
 | 
						|
 | 
						|
        // Test allowing or warning on the lint instead
 | 
						|
        #[allow(named_asm_labels)]
 | 
						|
        {
 | 
						|
            asm!("allowed: nop"); // Should not emit anything
 | 
						|
        }
 | 
						|
 | 
						|
        #[warn(named_asm_labels)]
 | 
						|
        {
 | 
						|
            asm!("warned: nop"); //~ WARNING avoid using named labels
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
// Trigger on naked fns too, even though they can't be inlined, reusing a
 | 
						|
// label or LTO can cause labels to break
 | 
						|
#[naked]
 | 
						|
pub extern "C" fn foo() -> i32 {
 | 
						|
    unsafe { naked_asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1) }
 | 
						|
    //~^ ERROR avoid using named labels
 | 
						|
}
 | 
						|
 | 
						|
// Make sure that non-naked attributes *do* still let the lint happen
 | 
						|
#[no_mangle]
 | 
						|
pub extern "C" fn bar() {
 | 
						|
    unsafe { asm!(".Lbar: mov rax, {}; ret;", "nop", const 1, options(noreturn)) }
 | 
						|
    //~^ ERROR avoid using named labels
 | 
						|
}
 | 
						|
 | 
						|
#[naked]
 | 
						|
pub extern "C" fn aaa() {
 | 
						|
    fn _local() {}
 | 
						|
 | 
						|
    unsafe { naked_asm!(".Laaa: nop; ret;") } //~ ERROR avoid using named labels
 | 
						|
}
 | 
						|
 | 
						|
pub fn normal() {
 | 
						|
    fn _local1() {}
 | 
						|
 | 
						|
    #[naked]
 | 
						|
    pub extern "C" fn bbb() {
 | 
						|
        fn _very_local() {}
 | 
						|
 | 
						|
        unsafe { naked_asm!(".Lbbb: nop; ret;") } //~ ERROR avoid using named labels
 | 
						|
    }
 | 
						|
 | 
						|
    fn _local2() {}
 | 
						|
}
 | 
						|
 | 
						|
// Make sure that the lint happens within closures
 | 
						|
fn closures() {
 | 
						|
    || unsafe {
 | 
						|
        asm!("closure1: nop"); //~ ERROR avoid using named labels
 | 
						|
    };
 | 
						|
 | 
						|
    move || unsafe {
 | 
						|
        asm!("closure2: nop"); //~ ERROR avoid using named labels
 | 
						|
    };
 | 
						|
 | 
						|
    || {
 | 
						|
        #[naked]
 | 
						|
        unsafe extern "C" fn _nested() {
 | 
						|
            naked_asm!("ret;");
 | 
						|
        }
 | 
						|
 | 
						|
        unsafe {
 | 
						|
            asm!("closure3: nop"); //~ ERROR avoid using named labels
 | 
						|
        }
 | 
						|
    };
 | 
						|
}
 | 
						|
 | 
						|
// Don't trigger on global asm
 | 
						|
global_asm!("aaaaaaaa: nop");
 |