]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys.rs
Find the cratemap at runtime on windows.
[rust.git] / src / libstd / 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 #[allow(missing_doc)];
14
15 use c_str::ToCStr;
16 use cast;
17 use libc;
18 use libc::{c_char, size_t};
19 use repr;
20 use str;
21 use unstable::intrinsics;
22
23 /// Returns the size of a type
24 #[inline]
25 pub fn size_of<T>() -> uint {
26     unsafe { intrinsics::size_of::<T>() }
27 }
28
29 /// Returns the size of the type that `_val` points to
30 #[inline]
31 pub fn size_of_val<T>(_val: &T) -> uint {
32     size_of::<T>()
33 }
34
35 /**
36  * Returns the size of a type, or 1 if the actual size is zero.
37  *
38  * Useful for building structures containing variable-length arrays.
39  */
40 #[inline]
41 pub fn nonzero_size_of<T>() -> uint {
42     let s = size_of::<T>();
43     if s == 0 { 1 } else { s }
44 }
45
46 /// Returns the size of the type of the value that `_val` points to
47 #[inline]
48 pub fn nonzero_size_of_val<T>(_val: &T) -> uint {
49     nonzero_size_of::<T>()
50 }
51
52
53 /**
54  * Returns the ABI-required minimum alignment of a type
55  *
56  * This is the alignment used for struct fields. It may be smaller
57  * than the preferred alignment.
58  */
59 #[inline]
60 pub fn min_align_of<T>() -> uint {
61     unsafe { intrinsics::min_align_of::<T>() }
62 }
63
64 /// Returns the ABI-required minimum alignment of the type of the value that
65 /// `_val` points to
66 #[inline]
67 pub fn min_align_of_val<T>(_val: &T) -> uint {
68     min_align_of::<T>()
69 }
70
71 /// Returns the preferred alignment of a type
72 #[inline]
73 pub fn pref_align_of<T>() -> uint {
74     unsafe { intrinsics::pref_align_of::<T>() }
75 }
76
77 /// Returns the preferred alignment of the type of the value that
78 /// `_val` points to
79 #[inline]
80 pub fn pref_align_of_val<T>(_val: &T) -> uint {
81     pref_align_of::<T>()
82 }
83
84 /// Returns the refcount of a shared box (as just before calling this)
85 #[inline]
86 pub fn refcount<T>(t: @T) -> uint {
87     unsafe {
88         let ref_ptr: *uint = cast::transmute_copy(&t);
89         *ref_ptr - 1
90     }
91 }
92
93 pub fn log_str<T>(t: &T) -> ~str {
94     use rt::io;
95     use rt::io::Decorator;
96
97     let mut result = io::mem::MemWriter::new();
98     repr::write_repr(&mut result as &mut io::Writer, t);
99     str::from_utf8_owned(result.inner())
100 }
101
102 /// Trait for initiating task failure.
103 pub trait FailWithCause {
104     /// Fail the current task, taking ownership of `cause`
105     fn fail_with(cause: Self, file: &'static str, line: uint) -> !;
106 }
107
108 impl FailWithCause for ~str {
109     fn fail_with(cause: ~str, file: &'static str, line: uint) -> ! {
110         do cause.with_c_str |msg_buf| {
111             do file.with_c_str |file_buf| {
112                 begin_unwind_(msg_buf, file_buf, line as libc::size_t)
113             }
114         }
115     }
116 }
117
118 impl FailWithCause for &'static str {
119     fn fail_with(cause: &'static str, file: &'static str, line: uint) -> ! {
120         do cause.with_c_str |msg_buf| {
121             do file.with_c_str |file_buf| {
122                 begin_unwind_(msg_buf, file_buf, line as libc::size_t)
123             }
124         }
125     }
126 }
127
128 // FIXME #4427: Temporary until rt::rt_fail_ goes away
129 pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! {
130     use option::{Some, None};
131     use rt::in_green_task_context;
132     use rt::task::Task;
133     use rt::local::Local;
134     use rt::logging::Logger;
135     use send_str::SendStrOwned;
136     use str::Str;
137
138     unsafe {
139         // XXX: Bad re-allocations. fail! needs some refactoring
140         let msg = str::raw::from_c_str(msg);
141         let file = str::raw::from_c_str(file);
142
143         // XXX: Logging doesn't work correctly in non-task context because it
144         // invokes the local heap
145         if in_green_task_context() {
146             // XXX: Logging doesn't work here - the check to call the log
147             // function never passes - so calling the log function directly.
148             do Local::borrow |task: &mut Task| {
149                 let msg = match task.name {
150                     Some(ref name) =>
151                     fmt!("task '%s' failed at '%s', %s:%i",
152                          name.as_slice(), msg, file, line as int),
153                     None =>
154                     fmt!("task <unnamed> failed at '%s', %s:%i",
155                          msg, file, line as int)
156                 };
157
158                 task.logger.log(SendStrOwned(msg));
159             }
160         } else {
161             rterrln!("failed in non-task context at '%s', %s:%i",
162                      msg, file, line as int);
163         }
164
165         let task: *mut Task = Local::unsafe_borrow();
166         if (*task).unwinder.unwinding {
167             rtabort!("unwinding again");
168         }
169         (*task).unwinder.begin_unwind();
170     }
171 }
172
173 #[cfg(test)]
174 mod tests {
175     use cast;
176     use sys::*;
177
178     #[test]
179     fn size_of_basic() {
180         assert_eq!(size_of::<u8>(), 1u);
181         assert_eq!(size_of::<u16>(), 2u);
182         assert_eq!(size_of::<u32>(), 4u);
183         assert_eq!(size_of::<u64>(), 8u);
184     }
185
186     #[test]
187     #[cfg(target_arch = "x86")]
188     #[cfg(target_arch = "arm")]
189     #[cfg(target_arch = "mips")]
190     fn size_of_32() {
191         assert_eq!(size_of::<uint>(), 4u);
192         assert_eq!(size_of::<*uint>(), 4u);
193     }
194
195     #[test]
196     #[cfg(target_arch = "x86_64")]
197     fn size_of_64() {
198         assert_eq!(size_of::<uint>(), 8u);
199         assert_eq!(size_of::<*uint>(), 8u);
200     }
201
202     #[test]
203     fn size_of_val_basic() {
204         assert_eq!(size_of_val(&1u8), 1);
205         assert_eq!(size_of_val(&1u16), 2);
206         assert_eq!(size_of_val(&1u32), 4);
207         assert_eq!(size_of_val(&1u64), 8);
208     }
209
210     #[test]
211     fn nonzero_size_of_basic() {
212         type Z = [i8, ..0];
213         assert_eq!(size_of::<Z>(), 0u);
214         assert_eq!(nonzero_size_of::<Z>(), 1u);
215         assert_eq!(nonzero_size_of::<uint>(), size_of::<uint>());
216     }
217
218     #[test]
219     fn nonzero_size_of_val_basic() {
220         let z = [0u8, ..0];
221         assert_eq!(size_of_val(&z), 0u);
222         assert_eq!(nonzero_size_of_val(&z), 1u);
223         assert_eq!(nonzero_size_of_val(&1u), size_of_val(&1u));
224     }
225
226     #[test]
227     fn align_of_basic() {
228         assert_eq!(pref_align_of::<u8>(), 1u);
229         assert_eq!(pref_align_of::<u16>(), 2u);
230         assert_eq!(pref_align_of::<u32>(), 4u);
231     }
232
233     #[test]
234     #[cfg(target_arch = "x86")]
235     #[cfg(target_arch = "arm")]
236     #[cfg(target_arch = "mips")]
237     fn align_of_32() {
238         assert_eq!(pref_align_of::<uint>(), 4u);
239         assert_eq!(pref_align_of::<*uint>(), 4u);
240     }
241
242     #[test]
243     #[cfg(target_arch = "x86_64")]
244     fn align_of_64() {
245         assert_eq!(pref_align_of::<uint>(), 8u);
246         assert_eq!(pref_align_of::<*uint>(), 8u);
247     }
248
249     #[test]
250     fn align_of_val_basic() {
251         assert_eq!(pref_align_of_val(&1u8), 1u);
252         assert_eq!(pref_align_of_val(&1u16), 2u);
253         assert_eq!(pref_align_of_val(&1u32), 4u);
254     }
255
256     #[test]
257     fn synthesize_closure() {
258         use unstable::raw::Closure;
259         unsafe {
260             let x = 10;
261             let f: &fn(int) -> int = |y| x + y;
262
263             assert_eq!(f(20), 30);
264
265             let original_closure: Closure = cast::transmute(f);
266
267             let actual_function_pointer = original_closure.code;
268             let environment = original_closure.env;
269
270             let new_closure = Closure {
271                 code: actual_function_pointer,
272                 env: environment
273             };
274
275             let new_f: &fn(int) -> int = cast::transmute(new_closure);
276             assert_eq!(new_f(20), 30);
277         }
278     }
279
280     #[test]
281     #[should_fail]
282     fn fail_static() { FailWithCause::fail_with("cause", file!(), line!())  }
283
284     #[test]
285     #[should_fail]
286     fn fail_owned() { FailWithCause::fail_with(~"cause", file!(), line!())  }
287 }