]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/sgx/abi/usercalls/raw.rs
Auto merge of #56584 - davidtwco:issue-53990, r=nikomatsakis
[rust.git] / src / libstd / sys / sgx / abi / usercalls / raw.rs
1 // Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 #![allow(unused)]
12
13 use fortanix_sgx_abi::*;
14
15 use ptr::NonNull;
16
17 #[repr(C)]
18 struct UsercallReturn(u64, u64);
19
20 extern "C" {
21     fn usercall(nr: u64, p1: u64, p2: u64, _ignore: u64, p3: u64, p4: u64) -> UsercallReturn;
22 }
23
24 unsafe fn do_usercall(nr: u64, p1: u64, p2: u64, p3: u64, p4: u64) -> (u64, u64) {
25     if nr==0 { panic!("Invalid usercall number {}",nr) }
26     let UsercallReturn(a, b) = usercall(nr,p1,p2,0,p3,p4);
27     (a, b)
28 }
29
30 type Register = u64;
31
32 trait RegisterArgument {
33     fn from_register(Register) -> Self;
34     fn into_register(self) -> Register;
35 }
36
37 trait ReturnValue {
38     fn from_registers(call: &'static str, regs: (Register, Register)) -> Self;
39 }
40
41 macro_rules! define_usercalls {
42     // Using `$r:tt` because `$r:ty` doesn't match ! in `clobber_diverging`
43     ($(fn $f:ident($($n:ident: $t:ty),*) $(-> $r:tt)*; )*) => {
44         #[repr(C)]
45         #[allow(non_camel_case_types)]
46         enum Usercalls {
47             __enclave_usercalls_invalid,
48             $($f,)*
49         }
50
51         $(enclave_usercalls_internal_define_usercalls!(def fn $f($($n: $t),*) $(-> $r)*);)*
52     };
53 }
54
55 macro_rules! define_usercalls_asm {
56     ($(fn $f:ident($($n:ident: $t:ty),*) $(-> $r:ty)*; )*) => {
57         macro_rules! usercalls_asm {
58             () => {
59                 concat!(
60                     ".equ usercall_nr_LAST, 0\n",
61                     $(
62                     ".equ usercall_nr_", stringify!($f), ", usercall_nr_LAST+1\n",
63                     ".equ usercall_nr_LAST, usercall_nr_", stringify!($f), "\n"
64                     ),*
65                 )
66             }
67         }
68     };
69 }
70
71 macro_rules! define_ra {
72     (< $i:ident > $t:ty) => {
73         impl<$i> RegisterArgument for $t {
74             fn from_register(a: Register) -> Self {
75                 a as _
76             }
77             fn into_register(self) -> Register {
78                 self as _
79             }
80         }
81     };
82     ($i:ty as $t:ty) => {
83         impl RegisterArgument for $t {
84             fn from_register(a: Register) -> Self {
85                 a as $i as _
86             }
87             fn into_register(self) -> Register {
88                 self as $i as _
89             }
90         }
91     };
92     ($t:ty) => {
93         impl RegisterArgument for $t {
94             fn from_register(a: Register) -> Self {
95                 a as _
96             }
97             fn into_register(self) -> Register {
98                 self as _
99             }
100         }
101     };
102 }
103
104 define_ra!(Register);
105 define_ra!(i64);
106 define_ra!(u32);
107 define_ra!(u32 as i32);
108 define_ra!(u16);
109 define_ra!(u16 as i16);
110 define_ra!(u8);
111 define_ra!(u8 as i8);
112 define_ra!(usize);
113 define_ra!(usize as isize);
114 define_ra!(<T> *const T);
115 define_ra!(<T> *mut T);
116
117 impl RegisterArgument for bool {
118     fn from_register(a: Register) -> bool {
119         if a != 0 {
120             true
121         } else {
122             false
123         }
124     }
125     fn into_register(self) -> Register {
126         self as _
127     }
128 }
129
130 impl<T: RegisterArgument> RegisterArgument for Option<NonNull<T>> {
131     fn from_register(a: Register) -> Option<NonNull<T>> {
132         NonNull::new(a as _)
133     }
134     fn into_register(self) -> Register {
135         self.map_or(0 as _, NonNull::as_ptr) as _
136     }
137 }
138
139 impl ReturnValue for ! {
140     fn from_registers(call: &'static str, _regs: (Register, Register)) -> Self {
141         panic!("Usercall {}: did not expect to be re-entered", call);
142     }
143 }
144
145 impl ReturnValue for () {
146     fn from_registers(call: &'static str, regs: (Register, Register)) -> Self {
147         assert_eq!(regs.0, 0, "Usercall {}: expected {} return value to be 0", call, "1st");
148         assert_eq!(regs.1, 0, "Usercall {}: expected {} return value to be 0", call, "2nd");
149         ()
150     }
151 }
152
153 impl<T: RegisterArgument> ReturnValue for T {
154     fn from_registers(call: &'static str, regs: (Register, Register)) -> Self {
155         assert_eq!(regs.1, 0, "Usercall {}: expected {} return value to be 0", call, "2nd");
156         T::from_register(regs.0)
157     }
158 }
159
160 impl<T: RegisterArgument, U: RegisterArgument> ReturnValue for (T, U) {
161     fn from_registers(_call: &'static str, regs: (Register, Register)) -> Self {
162         (
163             T::from_register(regs.0),
164             U::from_register(regs.1)
165         )
166     }
167 }
168
169 macro_rules! enclave_usercalls_internal_define_usercalls {
170     (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty,
171                      $n3:ident: $t3:ty, $n4:ident: $t4:ty) -> $r:ty) => (
172         #[inline(always)]
173         pub unsafe fn $f($n1: $t1, $n2: $t2, $n3: $t3, $n4: $t4) -> $r {
174             ReturnValue::from_registers(stringify!($f), do_usercall(
175                 Usercalls::$f as Register,
176                 RegisterArgument::into_register($n1),
177                 RegisterArgument::into_register($n2),
178                 RegisterArgument::into_register($n3),
179                 RegisterArgument::into_register($n4),
180             ))
181         }
182     );
183     (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty, $n3:ident: $t3:ty) -> $r:ty) => (
184         #[inline(always)]
185         pub unsafe fn $f($n1: $t1, $n2: $t2, $n3: $t3) -> $r {
186             ReturnValue::from_registers(stringify!($f), do_usercall(
187                 Usercalls::$f as Register,
188                 RegisterArgument::into_register($n1),
189                 RegisterArgument::into_register($n2),
190                 RegisterArgument::into_register($n3),
191                 0
192             ))
193         }
194     );
195     (def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty) -> $r:ty) => (
196         #[inline(always)]
197         pub unsafe fn $f($n1: $t1, $n2: $t2) -> $r {
198             ReturnValue::from_registers(stringify!($f), do_usercall(
199                 Usercalls::$f as Register,
200                 RegisterArgument::into_register($n1),
201                 RegisterArgument::into_register($n2),
202                 0,0
203             ))
204         }
205     );
206     (def fn $f:ident($n1:ident: $t1:ty) -> $r:ty) => (
207         #[inline(always)]
208         pub unsafe fn $f($n1: $t1) -> $r {
209             ReturnValue::from_registers(stringify!($f), do_usercall(
210                 Usercalls::$f as Register,
211                 RegisterArgument::into_register($n1),
212                 0,0,0
213             ))
214         }
215     );
216     (def fn $f:ident() -> $r:ty) => (
217         #[inline(always)]
218         pub unsafe fn $f() -> $r {
219             ReturnValue::from_registers(stringify!($f), do_usercall(
220                 Usercalls::$f as Register,
221                 0,0,0,0
222             ))
223         }
224     );
225     (def fn $f:ident($($n:ident: $t:ty),*)) => (
226         enclave_usercalls_internal_define_usercalls!(def fn $f($($n: $t),*) -> ());
227     );
228 }
229
230 invoke_with_usercalls!(define_usercalls);
231 invoke_with_usercalls!(define_usercalls_asm);