]> git.lizzy.rs Git - rust.git/blob - src/libcore/sys.rs
core: Turn off the local heap in newsched in stage0 to work around windows bustage
[rust.git] / src / libcore / sys.rs
1 // Copyright 2012 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 //! Misc low level stuff
12
13 use option::{Some, None};
14 use cast;
15 use cmp::{Eq, Ord};
16 use gc;
17 use io;
18 use libc;
19 use libc::{c_void, c_char, size_t};
20 use repr;
21 use str;
22
23 pub type FreeGlue<'self> = &'self fn(*TypeDesc, *c_void);
24
25 // Corresponds to runtime type_desc type
26 pub struct TypeDesc {
27     size: uint,
28     align: uint,
29     take_glue: uint,
30     drop_glue: uint,
31     free_glue: uint
32     // Remaining fields not listed
33 }
34
35 /// The representation of a Rust closure
36 pub struct Closure {
37     code: *(),
38     env: *(),
39 }
40
41 pub mod rusti {
42     #[abi = "rust-intrinsic"]
43     pub extern "rust-intrinsic" {
44         fn get_tydesc<T>() -> *();
45         fn size_of<T>() -> uint;
46         fn pref_align_of<T>() -> uint;
47         fn min_align_of<T>() -> uint;
48     }
49 }
50
51 pub mod rustrt {
52     use libc::{c_char, size_t};
53
54     pub extern {
55         #[rust_stack]
56         unsafe fn rust_upcall_fail(expr: *c_char,
57                                    file: *c_char,
58                                    line: size_t);
59     }
60 }
61
62 /// Compares contents of two pointers using the default method.
63 /// Equivalent to `*x1 == *x2`.  Useful for hashtables.
64 pub fn shape_eq<T:Eq>(x1: &T, x2: &T) -> bool {
65     *x1 == *x2
66 }
67
68 pub fn shape_lt<T:Ord>(x1: &T, x2: &T) -> bool {
69     *x1 < *x2
70 }
71
72 pub fn shape_le<T:Ord>(x1: &T, x2: &T) -> bool {
73     *x1 <= *x2
74 }
75
76 /**
77  * Returns a pointer to a type descriptor.
78  *
79  * Useful for calling certain function in the Rust runtime or otherwise
80  * performing dark magick.
81  */
82 #[inline(always)]
83 pub fn get_type_desc<T>() -> *TypeDesc {
84     unsafe { rusti::get_tydesc::<T>() as *TypeDesc }
85 }
86
87 /// Returns a pointer to a type descriptor.
88 #[inline(always)]
89 pub fn get_type_desc_val<T>(_val: &T) -> *TypeDesc {
90     get_type_desc::<T>()
91 }
92
93 /// Returns the size of a type
94 #[inline(always)]
95 pub fn size_of<T>() -> uint {
96     unsafe { rusti::size_of::<T>() }
97 }
98
99 /// Returns the size of the type that `_val` points to
100 #[inline(always)]
101 pub fn size_of_val<T>(_val: &T) -> uint {
102     size_of::<T>()
103 }
104
105 /**
106  * Returns the size of a type, or 1 if the actual size is zero.
107  *
108  * Useful for building structures containing variable-length arrays.
109  */
110 #[inline(always)]
111 pub fn nonzero_size_of<T>() -> uint {
112     let s = size_of::<T>();
113     if s == 0 { 1 } else { s }
114 }
115
116 /// Returns the size of the type of the value that `_val` points to
117 #[inline(always)]
118 pub fn nonzero_size_of_val<T>(_val: &T) -> uint {
119     nonzero_size_of::<T>()
120 }
121
122
123 /**
124  * Returns the ABI-required minimum alignment of a type
125  *
126  * This is the alignment used for struct fields. It may be smaller
127  * than the preferred alignment.
128  */
129 #[inline(always)]
130 pub fn min_align_of<T>() -> uint {
131     unsafe { rusti::min_align_of::<T>() }
132 }
133
134 /// Returns the ABI-required minimum alignment of the type of the value that
135 /// `_val` points to
136 #[inline(always)]
137 pub fn min_align_of_val<T>(_val: &T) -> uint {
138     min_align_of::<T>()
139 }
140
141 /// Returns the preferred alignment of a type
142 #[inline(always)]
143 pub fn pref_align_of<T>() -> uint {
144     unsafe { rusti::pref_align_of::<T>() }
145 }
146
147 /// Returns the preferred alignment of the type of the value that
148 /// `_val` points to
149 #[inline(always)]
150 pub fn pref_align_of_val<T>(_val: &T) -> uint {
151     pref_align_of::<T>()
152 }
153
154 /// Returns the refcount of a shared box (as just before calling this)
155 #[inline(always)]
156 pub fn refcount<T>(t: @T) -> uint {
157     unsafe {
158         let ref_ptr: *uint = cast::reinterpret_cast(&t);
159         *ref_ptr - 1
160     }
161 }
162
163 pub fn log_str<T>(t: &T) -> ~str {
164     do io::with_str_writer |wr| {
165         repr::write_repr(wr, t)
166     }
167 }
168
169 /** Initiate task failure */
170 pub fn begin_unwind(msg: ~str, file: ~str, line: uint) -> ! {
171
172     use rt::{context, OldTaskContext};
173     use rt::local_services::unsafe_borrow_local_services;
174
175     match context() {
176         OldTaskContext => {
177             do str::as_buf(msg) |msg_buf, _msg_len| {
178                 do str::as_buf(file) |file_buf, _file_len| {
179                     unsafe {
180                         let msg_buf = cast::transmute(msg_buf);
181                         let file_buf = cast::transmute(file_buf);
182                         begin_unwind_(msg_buf, file_buf, line as libc::size_t)
183                     }
184                 }
185             }
186         }
187         _ => {
188             gc::cleanup_stack_for_failure();
189             unsafe {
190                 let local_services = unsafe_borrow_local_services();
191                 match local_services.unwinder {
192                     Some(ref mut unwinder) => unwinder.begin_unwind(),
193                     None => abort!("failure without unwinder. aborting process")
194                 }
195             }
196         }
197     }
198 }
199
200 // FIXME #4427: Temporary until rt::rt_fail_ goes away
201 pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! {
202     unsafe {
203         gc::cleanup_stack_for_failure();
204         rustrt::rust_upcall_fail(msg, file, line);
205         cast::transmute(())
206     }
207 }
208
209 pub fn fail_assert(msg: &str, file: &str, line: uint) -> ! {
210     let (msg, file) = (msg.to_owned(), file.to_owned());
211     begin_unwind(~"assertion failed: " + msg, file, line)
212 }
213
214 #[cfg(test)]
215 mod tests {
216     use cast;
217     use sys::*;
218
219     #[test]
220     fn size_of_basic() {
221         assert!(size_of::<u8>() == 1u);
222         assert!(size_of::<u16>() == 2u);
223         assert!(size_of::<u32>() == 4u);
224         assert!(size_of::<u64>() == 8u);
225     }
226
227     #[test]
228     #[cfg(target_arch = "x86")]
229     #[cfg(target_arch = "arm")]
230     #[cfg(target_arch = "mips")]
231     fn size_of_32() {
232         assert!(size_of::<uint>() == 4u);
233         assert!(size_of::<*uint>() == 4u);
234     }
235
236     #[test]
237     #[cfg(target_arch = "x86_64")]
238     fn size_of_64() {
239         assert!(size_of::<uint>() == 8u);
240         assert!(size_of::<*uint>() == 8u);
241     }
242
243     #[test]
244     fn size_of_val_basic() {
245         assert_eq!(size_of_val(&1u8), 1);
246         assert_eq!(size_of_val(&1u16), 2);
247         assert_eq!(size_of_val(&1u32), 4);
248         assert_eq!(size_of_val(&1u64), 8);
249     }
250
251     #[test]
252     fn nonzero_size_of_basic() {
253         type Z = [i8, ..0];
254         assert!(size_of::<Z>() == 0u);
255         assert!(nonzero_size_of::<Z>() == 1u);
256         assert!(nonzero_size_of::<uint>() == size_of::<uint>());
257     }
258
259     #[test]
260     fn nonzero_size_of_val_basic() {
261         let z = [0u8, ..0];
262         assert_eq!(size_of_val(&z), 0u);
263         assert_eq!(nonzero_size_of_val(&z), 1u);
264         assert_eq!(nonzero_size_of_val(&1u), size_of_val(&1u));
265     }
266
267     #[test]
268     fn align_of_basic() {
269         assert!(pref_align_of::<u8>() == 1u);
270         assert!(pref_align_of::<u16>() == 2u);
271         assert!(pref_align_of::<u32>() == 4u);
272     }
273
274     #[test]
275     #[cfg(target_arch = "x86")]
276     #[cfg(target_arch = "arm")]
277     #[cfg(target_arch = "mips")]
278     fn align_of_32() {
279         assert!(pref_align_of::<uint>() == 4u);
280         assert!(pref_align_of::<*uint>() == 4u);
281     }
282
283     #[test]
284     #[cfg(target_arch = "x86_64")]
285     fn align_of_64() {
286         assert!(pref_align_of::<uint>() == 8u);
287         assert!(pref_align_of::<*uint>() == 8u);
288     }
289
290     #[test]
291     fn align_of_val_basic() {
292         assert_eq!(pref_align_of_val(&1u8), 1u);
293         assert_eq!(pref_align_of_val(&1u16), 2u);
294         assert_eq!(pref_align_of_val(&1u32), 4u);
295     }
296
297     #[test]
298     fn synthesize_closure() {
299         unsafe {
300             let x = 10;
301             let f: &fn(int) -> int = |y| x + y;
302
303             assert!(f(20) == 30);
304
305             let original_closure: Closure = cast::transmute(f);
306
307             let actual_function_pointer = original_closure.code;
308             let environment = original_closure.env;
309
310             let new_closure = Closure {
311                 code: actual_function_pointer,
312                 env: environment
313             };
314
315             let new_f: &fn(int) -> int = cast::transmute(new_closure);
316             assert!(new_f(20) == 30);
317         }
318     }
319 }
320
321 // Local Variables:
322 // mode: rust;
323 // fill-column: 78;
324 // indent-tabs-mode: nil
325 // c-basic-offset: 4
326 // buffer-file-coding-system: utf-8-unix
327 // End: