File: generics.rs

package info (click to toggle)
rustc 1.87.0%2Bdfsg1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 925,564 kB
  • sloc: xml: 158,127; python: 36,039; javascript: 19,761; sh: 19,737; cpp: 18,981; ansic: 13,133; asm: 4,376; makefile: 710; perl: 29; lisp: 28; ruby: 19; sql: 11
file content (116 lines) | stat: -rw-r--r-- 2,170 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
//@ compile-flags: -Copt-level=3
//@ only-x86_64

#![crate_type = "lib"]
#![feature(naked_functions, asm_const)]

use std::arch::naked_asm;

#[no_mangle]
fn test(x: u64) {
    // just making sure these symbols get used
    using_const_generics::<1>(x);
    using_const_generics::<2>(x);

    generic_function::<i64>(x as i64);

    let foo = Foo(x);

    foo.method();
    foo.trait_method();
}

// CHECK: .balign 4
// CHECK: add rax, 2
// CHECK: add rax, 42

// CHECK: .balign 4
// CHECK: add rax, 1
// CHECK: add rax, 42

#[naked]
pub extern "C" fn using_const_generics<const N: u64>(x: u64) -> u64 {
    const M: u64 = 42;

    unsafe {
        naked_asm!(
            "xor rax, rax",
            "add rax, rdi",
            "add rax, {}",
            "add rax, {}",
            "ret",
            const N,
            const M,
        )
    }
}

trait Invert {
    fn invert(self) -> Self;
}

impl Invert for i64 {
    fn invert(self) -> Self {
        -1 * self
    }
}

// CHECK: .balign 4
// CHECK-LABEL: generic_function:
// CHECK: call
// CHECK: ret

#[naked]
#[no_mangle]
pub extern "C" fn generic_function<T: Invert>(x: i64) -> i64 {
    unsafe {
        naked_asm!(
            "call {}",
            "ret",
            sym <T as Invert>::invert,
        )
    }
}

#[derive(Copy, Clone)]
#[repr(transparent)]
struct Foo(u64);

// CHECK: .balign 4
// CHECK-LABEL: method:
// CHECK: mov rax, rdi

impl Foo {
    #[naked]
    #[no_mangle]
    extern "C" fn method(self) -> u64 {
        unsafe { naked_asm!("mov rax, rdi", "ret") }
    }
}

// CHECK: .balign 4
// CHECK-LABEL: trait_method:
// CHECK: mov rax, rdi

trait Bar {
    extern "C" fn trait_method(self) -> u64;
}

impl Bar for Foo {
    #[naked]
    #[no_mangle]
    extern "C" fn trait_method(self) -> u64 {
        unsafe { naked_asm!("mov rax, rdi", "ret") }
    }
}

// CHECK: .balign 4
// CHECK-LABEL: naked_with_args_and_return:
// CHECK: lea rax, [rdi + rsi]

// this previously ICE'd, see https://github.com/rust-lang/rust/issues/124375
#[naked]
#[no_mangle]
pub unsafe extern "C" fn naked_with_args_and_return(a: isize, b: isize) -> isize {
    naked_asm!("lea rax, [rdi + rsi]", "ret");
}