]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_codegen_cranelift/example/alloc_system.rs
Auto merge of #2731 - RalfJung:rustup, r=RalfJung
[rust.git] / compiler / rustc_codegen_cranelift / example / alloc_system.rs
1 // Copyright 2015 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 #![no_std]
11
12 pub struct System;
13
14 #[cfg(any(windows, unix, target_os = "redox"))]
15 mod realloc_fallback {
16     use core::alloc::{GlobalAlloc, Layout};
17     use core::cmp;
18     use core::ptr;
19     impl super::System {
20         pub(crate) unsafe fn realloc_fallback(
21             &self,
22             ptr: *mut u8,
23             old_layout: Layout,
24             new_size: usize,
25         ) -> *mut u8 {
26             // Docs for GlobalAlloc::realloc require this to be valid:
27             let new_layout = Layout::from_size_align_unchecked(new_size, old_layout.align());
28             let new_ptr = GlobalAlloc::alloc(self, new_layout);
29             if !new_ptr.is_null() {
30                 let size = cmp::min(old_layout.size(), new_size);
31                 ptr::copy_nonoverlapping(ptr, new_ptr, size);
32                 GlobalAlloc::dealloc(self, ptr, old_layout);
33             }
34             new_ptr
35         }
36     }
37 }
38 #[cfg(any(unix, target_os = "redox"))]
39 mod platform {
40     use core::alloc::{GlobalAlloc, Layout};
41     use core::ffi::c_void;
42     use core::ptr;
43     use System;
44     extern "C" {
45         fn posix_memalign(memptr: *mut *mut c_void, align: usize, size: usize) -> i32;
46         fn free(p: *mut c_void);
47     }
48     unsafe impl GlobalAlloc for System {
49         #[inline]
50         unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
51             aligned_malloc(&layout)
52         }
53         #[inline]
54         unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
55             let ptr = self.alloc(layout.clone());
56             if !ptr.is_null() {
57                 ptr::write_bytes(ptr, 0, layout.size());
58             }
59             ptr
60         }
61         #[inline]
62         unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
63             free(ptr as *mut c_void)
64         }
65         #[inline]
66         unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
67             self.realloc_fallback(ptr, layout, new_size)
68         }
69     }
70     unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
71         let mut out = ptr::null_mut();
72         let ret = posix_memalign(&mut out, layout.align(), layout.size());
73         if ret != 0 { ptr::null_mut() } else { out as *mut u8 }
74     }
75 }
76 #[cfg(windows)]
77 #[allow(nonstandard_style)]
78 mod platform {
79     use core::alloc::{GlobalAlloc, Layout};
80     use System;
81     type LPVOID = *mut u8;
82     type HANDLE = LPVOID;
83     type SIZE_T = usize;
84     type DWORD = u32;
85     type BOOL = i32;
86     extern "system" {
87         fn GetProcessHeap() -> HANDLE;
88         fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID;
89         fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID, dwBytes: SIZE_T) -> LPVOID;
90         fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL;
91         fn GetLastError() -> DWORD;
92     }
93     #[repr(C)]
94     struct Header(*mut u8);
95     const HEAP_ZERO_MEMORY: DWORD = 0x00000008;
96     unsafe fn get_header<'a>(ptr: *mut u8) -> &'a mut Header {
97         &mut *(ptr as *mut Header).sub(1)
98     }
99     unsafe fn align_ptr(ptr: *mut u8, align: usize) -> *mut u8 {
100         let aligned = ptr.add(align - (ptr as usize & (align - 1)));
101         *get_header(aligned) = Header(ptr);
102         aligned
103     }
104     #[inline]
105     unsafe fn allocate_with_flags(layout: Layout, flags: DWORD) -> *mut u8 {
106         let size = layout.size() + layout.align();
107         let ptr = HeapAlloc(GetProcessHeap(), flags, size);
108         (if ptr.is_null() { ptr } else { align_ptr(ptr, layout.align()) }) as *mut u8
109     }
110     unsafe impl GlobalAlloc for System {
111         #[inline]
112         unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
113             allocate_with_flags(layout, 0)
114         }
115         #[inline]
116         unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
117             allocate_with_flags(layout, HEAP_ZERO_MEMORY)
118         }
119         #[inline]
120         unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
121             let header = get_header(ptr);
122             let err = HeapFree(GetProcessHeap(), 0, header.0 as LPVOID);
123             debug_assert!(err != 0, "Failed to free heap memory: {}", GetLastError());
124         }
125         #[inline]
126         unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
127             self.realloc_fallback(ptr, layout, new_size)
128         }
129     }
130 }