mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
Use the GlobalAlloc trait for #[global_allocator]
This commit is contained in:
parent
eb69593f73
commit
86753ce1cc
1
src/Cargo.lock
generated
1
src/Cargo.lock
generated
@ -19,7 +19,6 @@ dependencies = [
|
||||
name = "alloc_jemalloc"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"alloc_system 0.0.0",
|
||||
"build_helper 0.1.0",
|
||||
"cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"compiler_builtins 0.0.0",
|
||||
|
@ -29,16 +29,16 @@ looks like:
|
||||
```rust
|
||||
#![feature(global_allocator, allocator_api, heap_api)]
|
||||
|
||||
use std::heap::{Alloc, System, Layout, AllocErr};
|
||||
use std::alloc::{GlobalAlloc, System, Layout, Void};
|
||||
|
||||
struct MyAllocator;
|
||||
|
||||
unsafe impl<'a> Alloc for &'a MyAllocator {
|
||||
unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
|
||||
unsafe impl GlobalAlloc for MyAllocator {
|
||||
unsafe fn alloc(&self, layout: Layout) -> *mut Void {
|
||||
System.alloc(layout)
|
||||
}
|
||||
|
||||
unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) {
|
||||
unsafe fn dealloc(&self, ptr: *mut Void, layout: Layout) {
|
||||
System.dealloc(ptr, layout)
|
||||
}
|
||||
}
|
||||
|
@ -16,26 +16,19 @@
|
||||
issue = "32838")]
|
||||
|
||||
use core::intrinsics::{min_align_of_val, size_of_val};
|
||||
use core::mem;
|
||||
use core::usize;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use core::alloc::*;
|
||||
|
||||
#[cfg(stage0)]
|
||||
extern "Rust" {
|
||||
#[allocator]
|
||||
#[rustc_allocator_nounwind]
|
||||
fn __rust_alloc(size: usize, align: usize, err: *mut u8) -> *mut u8;
|
||||
#[cold]
|
||||
#[rustc_allocator_nounwind]
|
||||
fn __rust_oom(err: *const u8) -> !;
|
||||
#[rustc_allocator_nounwind]
|
||||
fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
|
||||
#[rustc_allocator_nounwind]
|
||||
fn __rust_usable_size(layout: *const u8,
|
||||
min: *mut usize,
|
||||
max: *mut usize);
|
||||
#[rustc_allocator_nounwind]
|
||||
fn __rust_realloc(ptr: *mut u8,
|
||||
old_size: usize,
|
||||
old_align: usize,
|
||||
@ -44,31 +37,22 @@ extern "Rust" {
|
||||
err: *mut u8) -> *mut u8;
|
||||
#[rustc_allocator_nounwind]
|
||||
fn __rust_alloc_zeroed(size: usize, align: usize, err: *mut u8) -> *mut u8;
|
||||
}
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
extern "Rust" {
|
||||
#[allocator]
|
||||
#[rustc_allocator_nounwind]
|
||||
fn __rust_alloc_excess(size: usize,
|
||||
align: usize,
|
||||
excess: *mut usize,
|
||||
err: *mut u8) -> *mut u8;
|
||||
fn __rust_alloc(size: usize, align: usize) -> *mut u8;
|
||||
#[rustc_allocator_nounwind]
|
||||
fn __rust_realloc_excess(ptr: *mut u8,
|
||||
old_size: usize,
|
||||
old_align: usize,
|
||||
new_size: usize,
|
||||
new_align: usize,
|
||||
excess: *mut usize,
|
||||
err: *mut u8) -> *mut u8;
|
||||
fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
|
||||
#[rustc_allocator_nounwind]
|
||||
fn __rust_grow_in_place(ptr: *mut u8,
|
||||
old_size: usize,
|
||||
old_align: usize,
|
||||
new_size: usize,
|
||||
new_align: usize) -> u8;
|
||||
fn __rust_realloc(ptr: *mut u8,
|
||||
old_size: usize,
|
||||
align: usize,
|
||||
new_size: usize) -> *mut u8;
|
||||
#[rustc_allocator_nounwind]
|
||||
fn __rust_shrink_in_place(ptr: *mut u8,
|
||||
old_size: usize,
|
||||
old_align: usize,
|
||||
new_size: usize,
|
||||
new_align: usize) -> u8;
|
||||
fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8;
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Default, Debug)]
|
||||
@ -86,22 +70,15 @@ pub const Heap: Global = Global;
|
||||
unsafe impl Alloc for Global {
|
||||
#[inline]
|
||||
unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
|
||||
let mut err = AllocErr;
|
||||
let ptr = __rust_alloc(layout.size(),
|
||||
layout.align(),
|
||||
&mut err as *mut AllocErr as *mut u8);
|
||||
if ptr.is_null() {
|
||||
Err(AllocErr)
|
||||
} else {
|
||||
Ok(ptr)
|
||||
}
|
||||
}
|
||||
#[cfg(not(stage0))]
|
||||
let ptr = __rust_alloc(layout.size(), layout.align());
|
||||
#[cfg(stage0)]
|
||||
let ptr = __rust_alloc(layout.size(), layout.align(), &mut 0);
|
||||
|
||||
#[inline]
|
||||
#[cold]
|
||||
fn oom(&mut self, err: AllocErr) -> ! {
|
||||
unsafe {
|
||||
__rust_oom(&err as *const AllocErr as *const u8)
|
||||
if !ptr.is_null() {
|
||||
Ok(ptr)
|
||||
} else {
|
||||
Err(AllocErr)
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,18 +87,6 @@ unsafe impl Alloc for Global {
|
||||
__rust_dealloc(ptr, layout.size(), layout.align())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn usable_size(&self, layout: &Layout) -> (usize, usize) {
|
||||
let mut min = 0;
|
||||
let mut max = 0;
|
||||
unsafe {
|
||||
__rust_usable_size(layout as *const Layout as *const u8,
|
||||
&mut min,
|
||||
&mut max);
|
||||
}
|
||||
(min, max)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn realloc(&mut self,
|
||||
ptr: *mut u8,
|
||||
@ -129,107 +94,34 @@ unsafe impl Alloc for Global {
|
||||
new_layout: Layout)
|
||||
-> Result<*mut u8, AllocErr>
|
||||
{
|
||||
let mut err = AllocErr;
|
||||
let ptr = __rust_realloc(ptr,
|
||||
layout.size(),
|
||||
layout.align(),
|
||||
new_layout.size(),
|
||||
new_layout.align(),
|
||||
&mut err as *mut AllocErr as *mut u8);
|
||||
if ptr.is_null() {
|
||||
Err(AllocErr)
|
||||
if layout.align() == new_layout.align() {
|
||||
#[cfg(not(stage0))]
|
||||
let ptr = __rust_realloc(ptr, layout.size(), layout.align(), new_layout.size());
|
||||
#[cfg(stage0)]
|
||||
let ptr = __rust_realloc(ptr, layout.size(), layout.align(),
|
||||
new_layout.size(), new_layout.align(), &mut 0);
|
||||
|
||||
if !ptr.is_null() {
|
||||
Ok(ptr)
|
||||
} else {
|
||||
Err(AllocErr)
|
||||
}
|
||||
} else {
|
||||
mem::forget(err);
|
||||
Ok(ptr)
|
||||
Err(AllocErr)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
|
||||
let mut err = AllocErr;
|
||||
let ptr = __rust_alloc_zeroed(layout.size(),
|
||||
layout.align(),
|
||||
&mut err as *mut AllocErr as *mut u8);
|
||||
if ptr.is_null() {
|
||||
Err(AllocErr)
|
||||
} else {
|
||||
#[cfg(not(stage0))]
|
||||
let ptr = __rust_alloc_zeroed(layout.size(), layout.align());
|
||||
#[cfg(stage0)]
|
||||
let ptr = __rust_alloc_zeroed(layout.size(), layout.align(), &mut 0);
|
||||
|
||||
if !ptr.is_null() {
|
||||
Ok(ptr)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn alloc_excess(&mut self, layout: Layout) -> Result<Excess, AllocErr> {
|
||||
let mut err = AllocErr;
|
||||
let mut size = 0;
|
||||
let ptr = __rust_alloc_excess(layout.size(),
|
||||
layout.align(),
|
||||
&mut size,
|
||||
&mut err as *mut AllocErr as *mut u8);
|
||||
if ptr.is_null() {
|
||||
} else {
|
||||
Err(AllocErr)
|
||||
} else {
|
||||
Ok(Excess(ptr, size))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn realloc_excess(&mut self,
|
||||
ptr: *mut u8,
|
||||
layout: Layout,
|
||||
new_layout: Layout) -> Result<Excess, AllocErr> {
|
||||
let mut err = AllocErr;
|
||||
let mut size = 0;
|
||||
let ptr = __rust_realloc_excess(ptr,
|
||||
layout.size(),
|
||||
layout.align(),
|
||||
new_layout.size(),
|
||||
new_layout.align(),
|
||||
&mut size,
|
||||
&mut err as *mut AllocErr as *mut u8);
|
||||
if ptr.is_null() {
|
||||
Err(AllocErr)
|
||||
} else {
|
||||
Ok(Excess(ptr, size))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn grow_in_place(&mut self,
|
||||
ptr: *mut u8,
|
||||
layout: Layout,
|
||||
new_layout: Layout)
|
||||
-> Result<(), CannotReallocInPlace>
|
||||
{
|
||||
debug_assert!(new_layout.size() >= layout.size());
|
||||
debug_assert!(new_layout.align() == layout.align());
|
||||
let ret = __rust_grow_in_place(ptr,
|
||||
layout.size(),
|
||||
layout.align(),
|
||||
new_layout.size(),
|
||||
new_layout.align());
|
||||
if ret != 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(CannotReallocInPlace)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn shrink_in_place(&mut self,
|
||||
ptr: *mut u8,
|
||||
layout: Layout,
|
||||
new_layout: Layout) -> Result<(), CannotReallocInPlace> {
|
||||
debug_assert!(new_layout.size() <= layout.size());
|
||||
debug_assert!(new_layout.align() == layout.align());
|
||||
let ret = __rust_shrink_in_place(ptr,
|
||||
layout.size(),
|
||||
layout.align(),
|
||||
new_layout.size(),
|
||||
new_layout.align());
|
||||
if ret != 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(CannotReallocInPlace)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,6 @@ test = false
|
||||
doc = false
|
||||
|
||||
[dependencies]
|
||||
alloc_system = { path = "../liballoc_system" }
|
||||
core = { path = "../libcore" }
|
||||
libc = { path = "../rustc/libc_shim" }
|
||||
compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
|
||||
|
@ -14,7 +14,6 @@
|
||||
reason = "this library is unlikely to be stabilized in its current \
|
||||
form or name",
|
||||
issue = "27783")]
|
||||
#![feature(alloc_system)]
|
||||
#![feature(libc)]
|
||||
#![feature(linkage)]
|
||||
#![feature(staged_api)]
|
||||
@ -23,15 +22,12 @@
|
||||
#![cfg_attr(not(dummy_jemalloc), feature(allocator_api))]
|
||||
#![rustc_alloc_kind = "exe"]
|
||||
|
||||
extern crate alloc_system;
|
||||
extern crate libc;
|
||||
|
||||
#[cfg(not(dummy_jemalloc))]
|
||||
pub use contents::*;
|
||||
#[cfg(not(dummy_jemalloc))]
|
||||
mod contents {
|
||||
use core::alloc::{Alloc, AllocErr, Layout};
|
||||
use alloc_system::System;
|
||||
use libc::{c_int, c_void, size_t};
|
||||
|
||||
// Note that the symbols here are prefixed by default on macOS and Windows (we
|
||||
@ -50,18 +46,10 @@ mod contents {
|
||||
target_os = "dragonfly", target_os = "windows", target_env = "musl"),
|
||||
link_name = "je_rallocx")]
|
||||
fn rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void;
|
||||
#[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
|
||||
target_os = "dragonfly", target_os = "windows", target_env = "musl"),
|
||||
link_name = "je_xallocx")]
|
||||
fn xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t;
|
||||
#[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
|
||||
target_os = "dragonfly", target_os = "windows", target_env = "musl"),
|
||||
link_name = "je_sdallocx")]
|
||||
fn sdallocx(ptr: *mut c_void, size: size_t, flags: c_int);
|
||||
#[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
|
||||
target_os = "dragonfly", target_os = "windows", target_env = "musl"),
|
||||
link_name = "je_nallocx")]
|
||||
fn nallocx(size: size_t, flags: c_int) -> size_t;
|
||||
}
|
||||
|
||||
const MALLOCX_ZERO: c_int = 0x40;
|
||||
@ -102,20 +90,12 @@ mod contents {
|
||||
|
||||
#[no_mangle]
|
||||
#[rustc_std_internal_symbol]
|
||||
pub unsafe extern fn __rde_alloc(size: usize,
|
||||
align: usize,
|
||||
_err: *mut u8) -> *mut u8 {
|
||||
pub unsafe extern fn __rde_alloc(size: usize, align: usize) -> *mut u8 {
|
||||
let flags = align_to_flags(align, size);
|
||||
let ptr = mallocx(size as size_t, flags) as *mut u8;
|
||||
ptr
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[rustc_std_internal_symbol]
|
||||
pub unsafe extern fn __rde_oom(err: *const u8) -> ! {
|
||||
System.oom((*(err as *const AllocErr)).clone())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[rustc_std_internal_symbol]
|
||||
pub unsafe extern fn __rde_dealloc(ptr: *mut u8,
|
||||
@ -125,44 +105,20 @@ mod contents {
|
||||
sdallocx(ptr as *mut c_void, size, flags);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[rustc_std_internal_symbol]
|
||||
pub unsafe extern fn __rde_usable_size(layout: *const u8,
|
||||
min: *mut usize,
|
||||
max: *mut usize) {
|
||||
let layout = &*(layout as *const Layout);
|
||||
let flags = align_to_flags(layout.align(), layout.size());
|
||||
let size = nallocx(layout.size(), flags) as usize;
|
||||
*min = layout.size();
|
||||
if size > 0 {
|
||||
*max = size;
|
||||
} else {
|
||||
*max = layout.size();
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[rustc_std_internal_symbol]
|
||||
pub unsafe extern fn __rde_realloc(ptr: *mut u8,
|
||||
_old_size: usize,
|
||||
old_align: usize,
|
||||
new_size: usize,
|
||||
new_align: usize,
|
||||
_err: *mut u8) -> *mut u8 {
|
||||
if new_align != old_align {
|
||||
return 0 as *mut u8
|
||||
}
|
||||
|
||||
let flags = align_to_flags(new_align, new_size);
|
||||
align: usize,
|
||||
new_size: usize) -> *mut u8 {
|
||||
let flags = align_to_flags(align, new_size);
|
||||
let ptr = rallocx(ptr as *mut c_void, new_size, flags) as *mut u8;
|
||||
ptr
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[rustc_std_internal_symbol]
|
||||
pub unsafe extern fn __rde_alloc_zeroed(size: usize,
|
||||
align: usize,
|
||||
_err: *mut u8) -> *mut u8 {
|
||||
pub unsafe extern fn __rde_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
|
||||
let ptr = if align <= MIN_ALIGN && align <= size {
|
||||
calloc(size as size_t, 1) as *mut u8
|
||||
} else {
|
||||
@ -171,60 +127,4 @@ mod contents {
|
||||
};
|
||||
ptr
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[rustc_std_internal_symbol]
|
||||
pub unsafe extern fn __rde_alloc_excess(size: usize,
|
||||
align: usize,
|
||||
excess: *mut usize,
|
||||
err: *mut u8) -> *mut u8 {
|
||||
let p = __rde_alloc(size, align, err);
|
||||
if !p.is_null() {
|
||||
let flags = align_to_flags(align, size);
|
||||
*excess = nallocx(size, flags) as usize;
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[rustc_std_internal_symbol]
|
||||
pub unsafe extern fn __rde_realloc_excess(ptr: *mut u8,
|
||||
old_size: usize,
|
||||
old_align: usize,
|
||||
new_size: usize,
|
||||
new_align: usize,
|
||||
excess: *mut usize,
|
||||
err: *mut u8) -> *mut u8 {
|
||||
let p = __rde_realloc(ptr, old_size, old_align, new_size, new_align, err);
|
||||
if !p.is_null() {
|
||||
let flags = align_to_flags(new_align, new_size);
|
||||
*excess = nallocx(new_size, flags) as usize;
|
||||
}
|
||||
p
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[rustc_std_internal_symbol]
|
||||
pub unsafe extern fn __rde_grow_in_place(ptr: *mut u8,
|
||||
old_size: usize,
|
||||
old_align: usize,
|
||||
new_size: usize,
|
||||
new_align: usize) -> u8 {
|
||||
__rde_shrink_in_place(ptr, old_size, old_align, new_size, new_align)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[rustc_std_internal_symbol]
|
||||
pub unsafe extern fn __rde_shrink_in_place(ptr: *mut u8,
|
||||
_old_size: usize,
|
||||
old_align: usize,
|
||||
new_size: usize,
|
||||
new_align: usize) -> u8 {
|
||||
if old_align == new_align {
|
||||
let flags = align_to_flags(new_align, new_size);
|
||||
(xallocx(ptr as *mut c_void, new_size, 0, flags) == new_size) as u8
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
use rustc::middle::allocator::AllocatorKind;
|
||||
use rustc_errors;
|
||||
use syntax::abi::Abi;
|
||||
use syntax::ast::{Crate, Attribute, LitKind, StrStyle, ExprKind};
|
||||
use syntax::ast::{Crate, Attribute, LitKind, StrStyle};
|
||||
use syntax::ast::{Unsafety, Constness, Generics, Mutability, Ty, Mac, Arg};
|
||||
use syntax::ast::{self, Ident, Item, ItemKind, TyKind, VisibilityKind, Expr};
|
||||
use syntax::attr;
|
||||
@ -88,7 +88,7 @@ impl<'a> Folder for ExpandAllocatorDirectives<'a> {
|
||||
span,
|
||||
kind: AllocatorKind::Global,
|
||||
global: item.ident,
|
||||
alloc: Ident::from_str("alloc"),
|
||||
core: Ident::from_str("core"),
|
||||
cx: ExtCtxt::new(self.sess, ecfg, self.resolver),
|
||||
};
|
||||
let super_path = f.cx.path(f.span, vec![
|
||||
@ -96,7 +96,7 @@ impl<'a> Folder for ExpandAllocatorDirectives<'a> {
|
||||
f.global,
|
||||
]);
|
||||
let mut items = vec![
|
||||
f.cx.item_extern_crate(f.span, f.alloc),
|
||||
f.cx.item_extern_crate(f.span, f.core),
|
||||
f.cx.item_use_simple(
|
||||
f.span,
|
||||
respan(f.span.shrink_to_lo(), VisibilityKind::Inherited),
|
||||
@ -126,7 +126,7 @@ struct AllocFnFactory<'a> {
|
||||
span: Span,
|
||||
kind: AllocatorKind,
|
||||
global: Ident,
|
||||
alloc: Ident,
|
||||
core: Ident,
|
||||
cx: ExtCtxt<'a>,
|
||||
}
|
||||
|
||||
@ -143,8 +143,7 @@ impl<'a> AllocFnFactory<'a> {
|
||||
self.arg_ty(ty, &mut abi_args, mk)
|
||||
}).collect();
|
||||
let result = self.call_allocator(method.name, args);
|
||||
let (output_ty, output_expr) =
|
||||
self.ret_ty(&method.output, &mut abi_args, mk, result);
|
||||
let (output_ty, output_expr) = self.ret_ty(&method.output, result);
|
||||
let kind = ItemKind::Fn(self.cx.fn_decl(abi_args, ast::FunctionRetTy::Ty(output_ty)),
|
||||
Unsafety::Unsafe,
|
||||
dummy_spanned(Constness::NotConst),
|
||||
@ -159,16 +158,15 @@ impl<'a> AllocFnFactory<'a> {
|
||||
|
||||
fn call_allocator(&self, method: &str, mut args: Vec<P<Expr>>) -> P<Expr> {
|
||||
let method = self.cx.path(self.span, vec![
|
||||
self.alloc,
|
||||
Ident::from_str("heap"),
|
||||
Ident::from_str("Alloc"),
|
||||
self.core,
|
||||
Ident::from_str("alloc"),
|
||||
Ident::from_str("GlobalAlloc"),
|
||||
Ident::from_str(method),
|
||||
]);
|
||||
let method = self.cx.expr_path(method);
|
||||
let allocator = self.cx.path_ident(self.span, self.global);
|
||||
let allocator = self.cx.expr_path(allocator);
|
||||
let allocator = self.cx.expr_addr_of(self.span, allocator);
|
||||
let allocator = self.cx.expr_mut_addr_of(self.span, allocator);
|
||||
args.insert(0, allocator);
|
||||
|
||||
self.cx.expr_call(self.span, method, args)
|
||||
@ -205,8 +203,8 @@ impl<'a> AllocFnFactory<'a> {
|
||||
args.push(self.cx.arg(self.span, align, ty_usize));
|
||||
|
||||
let layout_new = self.cx.path(self.span, vec![
|
||||
self.alloc,
|
||||
Ident::from_str("heap"),
|
||||
self.core,
|
||||
Ident::from_str("alloc"),
|
||||
Ident::from_str("Layout"),
|
||||
Ident::from_str("from_size_align_unchecked"),
|
||||
]);
|
||||
@ -219,286 +217,67 @@ impl<'a> AllocFnFactory<'a> {
|
||||
layout
|
||||
}
|
||||
|
||||
AllocatorTy::LayoutRef => {
|
||||
let ident = ident();
|
||||
args.push(self.cx.arg(self.span, ident, self.ptr_u8()));
|
||||
|
||||
// Convert our `arg: *const u8` via:
|
||||
//
|
||||
// &*(arg as *const Layout)
|
||||
let expr = self.cx.expr_ident(self.span, ident);
|
||||
let expr = self.cx.expr_cast(self.span, expr, self.layout_ptr());
|
||||
let expr = self.cx.expr_deref(self.span, expr);
|
||||
self.cx.expr_addr_of(self.span, expr)
|
||||
}
|
||||
|
||||
AllocatorTy::AllocErr => {
|
||||
// We're creating:
|
||||
//
|
||||
// (*(arg as *const AllocErr)).clone()
|
||||
let ident = ident();
|
||||
args.push(self.cx.arg(self.span, ident, self.ptr_u8()));
|
||||
let expr = self.cx.expr_ident(self.span, ident);
|
||||
let expr = self.cx.expr_cast(self.span, expr, self.alloc_err_ptr());
|
||||
let expr = self.cx.expr_deref(self.span, expr);
|
||||
self.cx.expr_method_call(
|
||||
self.span,
|
||||
expr,
|
||||
Ident::from_str("clone"),
|
||||
Vec::new()
|
||||
)
|
||||
}
|
||||
|
||||
AllocatorTy::Ptr => {
|
||||
let ident = ident();
|
||||
args.push(self.cx.arg(self.span, ident, self.ptr_u8()));
|
||||
let arg = self.cx.expr_ident(self.span, ident);
|
||||
self.cx.expr_cast(self.span, arg, self.ptr_void())
|
||||
}
|
||||
|
||||
AllocatorTy::Usize => {
|
||||
let ident = ident();
|
||||
args.push(self.cx.arg(self.span, ident, self.usize()));
|
||||
self.cx.expr_ident(self.span, ident)
|
||||
}
|
||||
|
||||
AllocatorTy::ResultPtr |
|
||||
AllocatorTy::ResultExcess |
|
||||
AllocatorTy::ResultUnit |
|
||||
AllocatorTy::Bang |
|
||||
AllocatorTy::UsizePair |
|
||||
AllocatorTy::Unit => {
|
||||
panic!("can't convert AllocatorTy to an argument")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn ret_ty(&self,
|
||||
ty: &AllocatorTy,
|
||||
args: &mut Vec<Arg>,
|
||||
ident: &mut FnMut() -> Ident,
|
||||
expr: P<Expr>) -> (P<Ty>, P<Expr>)
|
||||
{
|
||||
fn ret_ty(&self, ty: &AllocatorTy, expr: P<Expr>) -> (P<Ty>, P<Expr>) {
|
||||
match *ty {
|
||||
AllocatorTy::UsizePair => {
|
||||
// We're creating:
|
||||
//
|
||||
// let arg = #expr;
|
||||
// *min = arg.0;
|
||||
// *max = arg.1;
|
||||
|
||||
let min = ident();
|
||||
let max = ident();
|
||||
|
||||
args.push(self.cx.arg(self.span, min, self.ptr_usize()));
|
||||
args.push(self.cx.arg(self.span, max, self.ptr_usize()));
|
||||
|
||||
let ident = ident();
|
||||
let stmt = self.cx.stmt_let(self.span, false, ident, expr);
|
||||
let min = self.cx.expr_ident(self.span, min);
|
||||
let max = self.cx.expr_ident(self.span, max);
|
||||
let layout = self.cx.expr_ident(self.span, ident);
|
||||
let assign_min = self.cx.expr(self.span, ExprKind::Assign(
|
||||
self.cx.expr_deref(self.span, min),
|
||||
self.cx.expr_tup_field_access(self.span, layout.clone(), 0),
|
||||
));
|
||||
let assign_min = self.cx.stmt_semi(assign_min);
|
||||
let assign_max = self.cx.expr(self.span, ExprKind::Assign(
|
||||
self.cx.expr_deref(self.span, max),
|
||||
self.cx.expr_tup_field_access(self.span, layout.clone(), 1),
|
||||
));
|
||||
let assign_max = self.cx.stmt_semi(assign_max);
|
||||
|
||||
let stmts = vec![stmt, assign_min, assign_max];
|
||||
let block = self.cx.block(self.span, stmts);
|
||||
let ty_unit = self.cx.ty(self.span, TyKind::Tup(Vec::new()));
|
||||
(ty_unit, self.cx.expr_block(block))
|
||||
}
|
||||
|
||||
AllocatorTy::ResultExcess => {
|
||||
// We're creating:
|
||||
//
|
||||
// match #expr {
|
||||
// Ok(ptr) => {
|
||||
// *excess = ptr.1;
|
||||
// ptr.0
|
||||
// }
|
||||
// Err(e) => {
|
||||
// ptr::write(err_ptr, e);
|
||||
// 0 as *mut u8
|
||||
// }
|
||||
// }
|
||||
|
||||
let excess_ptr = ident();
|
||||
args.push(self.cx.arg(self.span, excess_ptr, self.ptr_usize()));
|
||||
let excess_ptr = self.cx.expr_ident(self.span, excess_ptr);
|
||||
|
||||
let err_ptr = ident();
|
||||
args.push(self.cx.arg(self.span, err_ptr, self.ptr_u8()));
|
||||
let err_ptr = self.cx.expr_ident(self.span, err_ptr);
|
||||
let err_ptr = self.cx.expr_cast(self.span,
|
||||
err_ptr,
|
||||
self.alloc_err_ptr());
|
||||
|
||||
let name = ident();
|
||||
let ok_expr = {
|
||||
let ptr = self.cx.expr_ident(self.span, name);
|
||||
let write = self.cx.expr(self.span, ExprKind::Assign(
|
||||
self.cx.expr_deref(self.span, excess_ptr),
|
||||
self.cx.expr_tup_field_access(self.span, ptr.clone(), 1),
|
||||
));
|
||||
let write = self.cx.stmt_semi(write);
|
||||
let ret = self.cx.expr_tup_field_access(self.span,
|
||||
ptr.clone(),
|
||||
0);
|
||||
let ret = self.cx.stmt_expr(ret);
|
||||
let block = self.cx.block(self.span, vec![write, ret]);
|
||||
self.cx.expr_block(block)
|
||||
};
|
||||
let pat = self.cx.pat_ident(self.span, name);
|
||||
let ok = self.cx.path_ident(self.span, Ident::from_str("Ok"));
|
||||
let ok = self.cx.pat_tuple_struct(self.span, ok, vec![pat]);
|
||||
let ok = self.cx.arm(self.span, vec![ok], ok_expr);
|
||||
|
||||
let name = ident();
|
||||
let err_expr = {
|
||||
let err = self.cx.expr_ident(self.span, name);
|
||||
let write = self.cx.path(self.span, vec![
|
||||
self.alloc,
|
||||
Ident::from_str("heap"),
|
||||
Ident::from_str("__core"),
|
||||
Ident::from_str("ptr"),
|
||||
Ident::from_str("write"),
|
||||
]);
|
||||
let write = self.cx.expr_path(write);
|
||||
let write = self.cx.expr_call(self.span, write,
|
||||
vec![err_ptr, err]);
|
||||
let write = self.cx.stmt_semi(write);
|
||||
let null = self.cx.expr_usize(self.span, 0);
|
||||
let null = self.cx.expr_cast(self.span, null, self.ptr_u8());
|
||||
let null = self.cx.stmt_expr(null);
|
||||
let block = self.cx.block(self.span, vec![write, null]);
|
||||
self.cx.expr_block(block)
|
||||
};
|
||||
let pat = self.cx.pat_ident(self.span, name);
|
||||
let err = self.cx.path_ident(self.span, Ident::from_str("Err"));
|
||||
let err = self.cx.pat_tuple_struct(self.span, err, vec![pat]);
|
||||
let err = self.cx.arm(self.span, vec![err], err_expr);
|
||||
|
||||
let expr = self.cx.expr_match(self.span, expr, vec![ok, err]);
|
||||
(self.ptr_u8(), expr)
|
||||
}
|
||||
|
||||
AllocatorTy::ResultPtr => {
|
||||
// We're creating:
|
||||
//
|
||||
// match #expr {
|
||||
// Ok(ptr) => ptr,
|
||||
// Err(e) => {
|
||||
// ptr::write(err_ptr, e);
|
||||
// 0 as *mut u8
|
||||
// }
|
||||
// }
|
||||
// #expr as *mut u8
|
||||
|
||||
let err_ptr = ident();
|
||||
args.push(self.cx.arg(self.span, err_ptr, self.ptr_u8()));
|
||||
let err_ptr = self.cx.expr_ident(self.span, err_ptr);
|
||||
let err_ptr = self.cx.expr_cast(self.span,
|
||||
err_ptr,
|
||||
self.alloc_err_ptr());
|
||||
|
||||
let name = ident();
|
||||
let ok_expr = self.cx.expr_ident(self.span, name);
|
||||
let pat = self.cx.pat_ident(self.span, name);
|
||||
let ok = self.cx.path_ident(self.span, Ident::from_str("Ok"));
|
||||
let ok = self.cx.pat_tuple_struct(self.span, ok, vec![pat]);
|
||||
let ok = self.cx.arm(self.span, vec![ok], ok_expr);
|
||||
|
||||
let name = ident();
|
||||
let err_expr = {
|
||||
let err = self.cx.expr_ident(self.span, name);
|
||||
let write = self.cx.path(self.span, vec![
|
||||
self.alloc,
|
||||
Ident::from_str("heap"),
|
||||
Ident::from_str("__core"),
|
||||
Ident::from_str("ptr"),
|
||||
Ident::from_str("write"),
|
||||
]);
|
||||
let write = self.cx.expr_path(write);
|
||||
let write = self.cx.expr_call(self.span, write,
|
||||
vec![err_ptr, err]);
|
||||
let write = self.cx.stmt_semi(write);
|
||||
let null = self.cx.expr_usize(self.span, 0);
|
||||
let null = self.cx.expr_cast(self.span, null, self.ptr_u8());
|
||||
let null = self.cx.stmt_expr(null);
|
||||
let block = self.cx.block(self.span, vec![write, null]);
|
||||
self.cx.expr_block(block)
|
||||
};
|
||||
let pat = self.cx.pat_ident(self.span, name);
|
||||
let err = self.cx.path_ident(self.span, Ident::from_str("Err"));
|
||||
let err = self.cx.pat_tuple_struct(self.span, err, vec![pat]);
|
||||
let err = self.cx.arm(self.span, vec![err], err_expr);
|
||||
|
||||
let expr = self.cx.expr_match(self.span, expr, vec![ok, err]);
|
||||
let expr = self.cx.expr_cast(self.span, expr, self.ptr_u8());
|
||||
(self.ptr_u8(), expr)
|
||||
}
|
||||
|
||||
AllocatorTy::ResultUnit => {
|
||||
// We're creating:
|
||||
//
|
||||
// #expr.is_ok() as u8
|
||||
|
||||
let cast = self.cx.expr_method_call(
|
||||
self.span,
|
||||
expr,
|
||||
Ident::from_str("is_ok"),
|
||||
Vec::new()
|
||||
);
|
||||
let u8 = self.cx.path_ident(self.span, Ident::from_str("u8"));
|
||||
let u8 = self.cx.ty_path(u8);
|
||||
let cast = self.cx.expr_cast(self.span, cast, u8.clone());
|
||||
(u8, cast)
|
||||
}
|
||||
|
||||
AllocatorTy::Bang => {
|
||||
(self.cx.ty(self.span, TyKind::Never), expr)
|
||||
}
|
||||
|
||||
AllocatorTy::Unit => {
|
||||
(self.cx.ty(self.span, TyKind::Tup(Vec::new())), expr)
|
||||
}
|
||||
|
||||
AllocatorTy::AllocErr |
|
||||
AllocatorTy::Layout |
|
||||
AllocatorTy::LayoutRef |
|
||||
AllocatorTy::Usize |
|
||||
AllocatorTy::Ptr => {
|
||||
panic!("can't convert AllocatorTy to an output")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn usize(&self) -> P<Ty> {
|
||||
let usize = self.cx.path_ident(self.span, Ident::from_str("usize"));
|
||||
self.cx.ty_path(usize)
|
||||
}
|
||||
|
||||
fn ptr_u8(&self) -> P<Ty> {
|
||||
let u8 = self.cx.path_ident(self.span, Ident::from_str("u8"));
|
||||
let ty_u8 = self.cx.ty_path(u8);
|
||||
self.cx.ty_ptr(self.span, ty_u8, Mutability::Mutable)
|
||||
}
|
||||
|
||||
fn ptr_usize(&self) -> P<Ty> {
|
||||
let usize = self.cx.path_ident(self.span, Ident::from_str("usize"));
|
||||
let ty_usize = self.cx.ty_path(usize);
|
||||
self.cx.ty_ptr(self.span, ty_usize, Mutability::Mutable)
|
||||
}
|
||||
|
||||
fn layout_ptr(&self) -> P<Ty> {
|
||||
let layout = self.cx.path(self.span, vec![
|
||||
self.alloc,
|
||||
Ident::from_str("heap"),
|
||||
Ident::from_str("Layout"),
|
||||
fn ptr_void(&self) -> P<Ty> {
|
||||
let void = self.cx.path(self.span, vec![
|
||||
self.core,
|
||||
Ident::from_str("alloc"),
|
||||
Ident::from_str("Void"),
|
||||
]);
|
||||
let layout = self.cx.ty_path(layout);
|
||||
self.cx.ty_ptr(self.span, layout, Mutability::Mutable)
|
||||
}
|
||||
|
||||
fn alloc_err_ptr(&self) -> P<Ty> {
|
||||
let err = self.cx.path(self.span, vec![
|
||||
self.alloc,
|
||||
Ident::from_str("heap"),
|
||||
Ident::from_str("AllocErr"),
|
||||
]);
|
||||
let err = self.cx.ty_path(err);
|
||||
self.cx.ty_ptr(self.span, err, Mutability::Mutable)
|
||||
let ty_void = self.cx.ty_path(void);
|
||||
self.cx.ty_ptr(self.span, ty_void, Mutability::Mutable)
|
||||
}
|
||||
}
|
||||
|
@ -23,24 +23,14 @@ pub static ALLOCATOR_METHODS: &[AllocatorMethod] = &[
|
||||
inputs: &[AllocatorTy::Layout],
|
||||
output: AllocatorTy::ResultPtr,
|
||||
},
|
||||
AllocatorMethod {
|
||||
name: "oom",
|
||||
inputs: &[AllocatorTy::AllocErr],
|
||||
output: AllocatorTy::Bang,
|
||||
},
|
||||
AllocatorMethod {
|
||||
name: "dealloc",
|
||||
inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout],
|
||||
output: AllocatorTy::Unit,
|
||||
},
|
||||
AllocatorMethod {
|
||||
name: "usable_size",
|
||||
inputs: &[AllocatorTy::LayoutRef],
|
||||
output: AllocatorTy::UsizePair,
|
||||
},
|
||||
AllocatorMethod {
|
||||
name: "realloc",
|
||||
inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Layout],
|
||||
inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Usize],
|
||||
output: AllocatorTy::ResultPtr,
|
||||
},
|
||||
AllocatorMethod {
|
||||
@ -48,26 +38,6 @@ pub static ALLOCATOR_METHODS: &[AllocatorMethod] = &[
|
||||
inputs: &[AllocatorTy::Layout],
|
||||
output: AllocatorTy::ResultPtr,
|
||||
},
|
||||
AllocatorMethod {
|
||||
name: "alloc_excess",
|
||||
inputs: &[AllocatorTy::Layout],
|
||||
output: AllocatorTy::ResultExcess,
|
||||
},
|
||||
AllocatorMethod {
|
||||
name: "realloc_excess",
|
||||
inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Layout],
|
||||
output: AllocatorTy::ResultExcess,
|
||||
},
|
||||
AllocatorMethod {
|
||||
name: "grow_in_place",
|
||||
inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Layout],
|
||||
output: AllocatorTy::ResultUnit,
|
||||
},
|
||||
AllocatorMethod {
|
||||
name: "shrink_in_place",
|
||||
inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Layout],
|
||||
output: AllocatorTy::ResultUnit,
|
||||
},
|
||||
];
|
||||
|
||||
pub struct AllocatorMethod {
|
||||
@ -77,14 +47,9 @@ pub struct AllocatorMethod {
|
||||
}
|
||||
|
||||
pub enum AllocatorTy {
|
||||
AllocErr,
|
||||
Bang,
|
||||
Layout,
|
||||
LayoutRef,
|
||||
Ptr,
|
||||
ResultExcess,
|
||||
ResultPtr,
|
||||
ResultUnit,
|
||||
Unit,
|
||||
UsizePair,
|
||||
Usize,
|
||||
}
|
||||
|
@ -30,7 +30,6 @@ pub(crate) unsafe fn trans(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind)
|
||||
};
|
||||
let i8 = llvm::LLVMInt8TypeInContext(llcx);
|
||||
let i8p = llvm::LLVMPointerType(i8, 0);
|
||||
let usizep = llvm::LLVMPointerType(usize, 0);
|
||||
let void = llvm::LLVMVoidTypeInContext(llcx);
|
||||
|
||||
for method in ALLOCATOR_METHODS {
|
||||
@ -41,40 +40,19 @@ pub(crate) unsafe fn trans(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind)
|
||||
args.push(usize); // size
|
||||
args.push(usize); // align
|
||||
}
|
||||
AllocatorTy::LayoutRef => args.push(i8p),
|
||||
AllocatorTy::Ptr => args.push(i8p),
|
||||
AllocatorTy::AllocErr => args.push(i8p),
|
||||
AllocatorTy::Usize => args.push(usize),
|
||||
|
||||
AllocatorTy::Bang |
|
||||
AllocatorTy::ResultExcess |
|
||||
AllocatorTy::ResultPtr |
|
||||
AllocatorTy::ResultUnit |
|
||||
AllocatorTy::UsizePair |
|
||||
AllocatorTy::Unit => panic!("invalid allocator arg"),
|
||||
}
|
||||
}
|
||||
let output = match method.output {
|
||||
AllocatorTy::UsizePair => {
|
||||
args.push(usizep); // min
|
||||
args.push(usizep); // max
|
||||
None
|
||||
}
|
||||
AllocatorTy::Bang => None,
|
||||
AllocatorTy::ResultExcess => {
|
||||
args.push(i8p); // excess_ptr
|
||||
args.push(i8p); // err_ptr
|
||||
Some(i8p)
|
||||
}
|
||||
AllocatorTy::ResultPtr => {
|
||||
args.push(i8p); // err_ptr
|
||||
Some(i8p)
|
||||
}
|
||||
AllocatorTy::ResultUnit => Some(i8),
|
||||
AllocatorTy::ResultPtr => Some(i8p),
|
||||
AllocatorTy::Unit => None,
|
||||
|
||||
AllocatorTy::AllocErr |
|
||||
AllocatorTy::Layout |
|
||||
AllocatorTy::LayoutRef |
|
||||
AllocatorTy::Usize |
|
||||
AllocatorTy::Ptr => panic!("invalid allocator output"),
|
||||
};
|
||||
let ty = llvm::LLVMFunctionType(output.unwrap_or(void),
|
||||
|
@ -21,7 +21,7 @@
|
||||
#[doc(hidden)]
|
||||
#[allow(unused_attributes)]
|
||||
pub mod __default_lib_allocator {
|
||||
use super::{System, Layout, Alloc, AllocErr, CannotReallocInPlace};
|
||||
use super::{System, Layout, GlobalAlloc, Void};
|
||||
// for symbol names src/librustc/middle/allocator.rs
|
||||
// for signatures src/librustc_allocator/lib.rs
|
||||
|
||||
@ -30,20 +30,9 @@ pub mod __default_lib_allocator {
|
||||
|
||||
#[no_mangle]
|
||||
#[rustc_std_internal_symbol]
|
||||
pub unsafe extern fn __rdl_alloc(size: usize,
|
||||
align: usize,
|
||||
_err: *mut u8) -> *mut u8 {
|
||||
pub unsafe extern fn __rdl_alloc(size: usize, align: usize) -> *mut u8 {
|
||||
let layout = Layout::from_size_align_unchecked(size, align);
|
||||
match System.alloc(layout) {
|
||||
Ok(p) => p,
|
||||
Err(AllocErr) => 0 as *mut u8,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[rustc_std_internal_symbol]
|
||||
pub unsafe extern fn __rdl_oom(err: *const u8) -> ! {
|
||||
System.oom((*(err as *const AllocErr)).clone())
|
||||
System.alloc(layout) as *mut u8
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@ -51,110 +40,76 @@ pub mod __default_lib_allocator {
|
||||
pub unsafe extern fn __rdl_dealloc(ptr: *mut u8,
|
||||
size: usize,
|
||||
align: usize) {
|
||||
System.dealloc(ptr, Layout::from_size_align_unchecked(size, align))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[rustc_std_internal_symbol]
|
||||
pub unsafe extern fn __rdl_usable_size(layout: *const u8,
|
||||
min: *mut usize,
|
||||
max: *mut usize) {
|
||||
let pair = System.usable_size(&*(layout as *const Layout));
|
||||
*min = pair.0;
|
||||
*max = pair.1;
|
||||
System.dealloc(ptr as *mut Void, Layout::from_size_align_unchecked(size, align))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[rustc_std_internal_symbol]
|
||||
pub unsafe extern fn __rdl_realloc(ptr: *mut u8,
|
||||
old_size: usize,
|
||||
old_align: usize,
|
||||
new_size: usize,
|
||||
new_align: usize,
|
||||
_err: *mut u8) -> *mut u8 {
|
||||
let old_layout = Layout::from_size_align_unchecked(old_size, old_align);
|
||||
let new_layout = Layout::from_size_align_unchecked(new_size, new_align);
|
||||
match System.realloc(ptr, old_layout, new_layout) {
|
||||
Ok(p) => p,
|
||||
Err(AllocErr) => 0 as *mut u8,
|
||||
}
|
||||
align: usize,
|
||||
new_size: usize) -> *mut u8 {
|
||||
let old_layout = Layout::from_size_align_unchecked(old_size, align);
|
||||
System.realloc(ptr as *mut Void, old_layout, new_size) as *mut u8
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[rustc_std_internal_symbol]
|
||||
pub unsafe extern fn __rdl_alloc_zeroed(size: usize,
|
||||
align: usize,
|
||||
_err: *mut u8) -> *mut u8 {
|
||||
pub unsafe extern fn __rdl_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
|
||||
let layout = Layout::from_size_align_unchecked(size, align);
|
||||
match System.alloc_zeroed(layout) {
|
||||
Ok(p) => p,
|
||||
Err(AllocErr) => 0 as *mut u8,
|
||||
}
|
||||
System.alloc_zeroed(layout) as *mut u8
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[rustc_std_internal_symbol]
|
||||
pub unsafe extern fn __rdl_alloc_excess(size: usize,
|
||||
align: usize,
|
||||
excess: *mut usize,
|
||||
_err: *mut u8) -> *mut u8 {
|
||||
let layout = Layout::from_size_align_unchecked(size, align);
|
||||
match System.alloc_excess(layout) {
|
||||
Ok(p) => {
|
||||
*excess = p.1;
|
||||
p.0
|
||||
}
|
||||
Err(AllocErr) => 0 as *mut u8,
|
||||
#[cfg(stage0)]
|
||||
pub mod stage0 {
|
||||
#[no_mangle]
|
||||
#[rustc_std_internal_symbol]
|
||||
pub unsafe extern fn __rdl_usable_size(_layout: *const u8,
|
||||
_min: *mut usize,
|
||||
_max: *mut usize) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[rustc_std_internal_symbol]
|
||||
pub unsafe extern fn __rdl_realloc_excess(ptr: *mut u8,
|
||||
old_size: usize,
|
||||
old_align: usize,
|
||||
new_size: usize,
|
||||
new_align: usize,
|
||||
excess: *mut usize,
|
||||
_err: *mut u8) -> *mut u8 {
|
||||
let old_layout = Layout::from_size_align_unchecked(old_size, old_align);
|
||||
let new_layout = Layout::from_size_align_unchecked(new_size, new_align);
|
||||
match System.realloc_excess(ptr, old_layout, new_layout) {
|
||||
Ok(p) => {
|
||||
*excess = p.1;
|
||||
p.0
|
||||
}
|
||||
Err(AllocErr) => 0 as *mut u8,
|
||||
#[no_mangle]
|
||||
#[rustc_std_internal_symbol]
|
||||
pub unsafe extern fn __rdl_alloc_excess(_size: usize,
|
||||
_align: usize,
|
||||
_excess: *mut usize,
|
||||
_err: *mut u8) -> *mut u8 {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[rustc_std_internal_symbol]
|
||||
pub unsafe extern fn __rdl_grow_in_place(ptr: *mut u8,
|
||||
old_size: usize,
|
||||
old_align: usize,
|
||||
new_size: usize,
|
||||
new_align: usize) -> u8 {
|
||||
let old_layout = Layout::from_size_align_unchecked(old_size, old_align);
|
||||
let new_layout = Layout::from_size_align_unchecked(new_size, new_align);
|
||||
match System.grow_in_place(ptr, old_layout, new_layout) {
|
||||
Ok(()) => 1,
|
||||
Err(CannotReallocInPlace) => 0,
|
||||
#[no_mangle]
|
||||
#[rustc_std_internal_symbol]
|
||||
pub unsafe extern fn __rdl_realloc_excess(_ptr: *mut u8,
|
||||
_old_size: usize,
|
||||
_old_align: usize,
|
||||
_new_size: usize,
|
||||
_new_align: usize,
|
||||
_excess: *mut usize,
|
||||
_err: *mut u8) -> *mut u8 {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[rustc_std_internal_symbol]
|
||||
pub unsafe extern fn __rdl_shrink_in_place(ptr: *mut u8,
|
||||
old_size: usize,
|
||||
old_align: usize,
|
||||
new_size: usize,
|
||||
new_align: usize) -> u8 {
|
||||
let old_layout = Layout::from_size_align_unchecked(old_size, old_align);
|
||||
let new_layout = Layout::from_size_align_unchecked(new_size, new_align);
|
||||
match System.shrink_in_place(ptr, old_layout, new_layout) {
|
||||
Ok(()) => 1,
|
||||
Err(CannotReallocInPlace) => 0,
|
||||
#[no_mangle]
|
||||
#[rustc_std_internal_symbol]
|
||||
pub unsafe extern fn __rdl_grow_in_place(_ptr: *mut u8,
|
||||
_old_size: usize,
|
||||
_old_align: usize,
|
||||
_new_size: usize,
|
||||
_new_align: usize) -> u8 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[rustc_std_internal_symbol]
|
||||
pub unsafe extern fn __rdl_shrink_in_place(_ptr: *mut u8,
|
||||
_old_size: usize,
|
||||
_old_align: usize,
|
||||
_new_size: usize,
|
||||
_new_align: usize) -> u8 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
2
src/llvm
2
src/llvm
@ -1 +1 @@
|
||||
Subproject commit 6ceaaa4b0176a200e4bbd347d6a991ab6c776ede
|
||||
Subproject commit 7243155b1c3da0a980c868a87adebf00e0b33989
|
@ -1,4 +1,4 @@
|
||||
# If this file is modified, then llvm will be (optionally) cleaned and then rebuilt.
|
||||
# The actual contents of this file do not matter, but to trigger a change on the
|
||||
# build bots then the contents should be changed so git updates the mtime.
|
||||
2018-03-10
|
||||
2018-04-05
|
||||
|
@ -12,15 +12,9 @@
|
||||
|
||||
#[global_allocator]
|
||||
static A: usize = 0;
|
||||
//~^ the trait bound `&usize:
|
||||
//~| the trait bound `&usize:
|
||||
//~| the trait bound `&usize:
|
||||
//~| the trait bound `&usize:
|
||||
//~| the trait bound `&usize:
|
||||
//~| the trait bound `&usize:
|
||||
//~| the trait bound `&usize:
|
||||
//~| the trait bound `&usize:
|
||||
//~| the trait bound `&usize:
|
||||
//~| the trait bound `&usize:
|
||||
//~^ the trait bound `usize:
|
||||
//~| the trait bound `usize:
|
||||
//~| the trait bound `usize:
|
||||
//~| the trait bound `usize:
|
||||
|
||||
fn main() {}
|
||||
|
@ -11,16 +11,16 @@
|
||||
#![feature(allocator_api)]
|
||||
#![crate_type = "rlib"]
|
||||
|
||||
use std::heap::*;
|
||||
use std::alloc::*;
|
||||
|
||||
pub struct A;
|
||||
|
||||
unsafe impl<'a> Alloc for &'a A {
|
||||
unsafe fn alloc(&mut self, _: Layout) -> Result<*mut u8, AllocErr> {
|
||||
unsafe impl GlobalAlloc for A {
|
||||
unsafe fn alloc(&self, _: Layout) -> *mut Void {
|
||||
loop {}
|
||||
}
|
||||
|
||||
unsafe fn dealloc(&mut self, _ptr: *mut u8, _: Layout) {
|
||||
unsafe fn dealloc(&self, _ptr: *mut Void, _: Layout) {
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
|
@ -13,18 +13,18 @@
|
||||
#![feature(heap_api, allocator_api)]
|
||||
#![crate_type = "rlib"]
|
||||
|
||||
use std::heap::{Alloc, System, AllocErr, Layout};
|
||||
use std::heap::{GlobalAlloc, System, Layout, Void};
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
pub struct A(pub AtomicUsize);
|
||||
|
||||
unsafe impl<'a> Alloc for &'a A {
|
||||
unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
|
||||
unsafe impl GlobalAlloc for A {
|
||||
unsafe fn alloc(&self, layout: Layout) -> *mut Void {
|
||||
self.0.fetch_add(1, Ordering::SeqCst);
|
||||
System.alloc(layout)
|
||||
}
|
||||
|
||||
unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) {
|
||||
unsafe fn dealloc(&self, ptr: *mut Void, layout: Layout) {
|
||||
self.0.fetch_add(1, Ordering::SeqCst);
|
||||
System.dealloc(ptr, layout)
|
||||
}
|
||||
|
@ -15,20 +15,20 @@
|
||||
|
||||
extern crate helper;
|
||||
|
||||
use std::heap::{Heap, Alloc, System, Layout, AllocErr};
|
||||
use std::alloc::{self, Global, Alloc, System, Layout, Void};
|
||||
use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
|
||||
|
||||
static HITS: AtomicUsize = ATOMIC_USIZE_INIT;
|
||||
|
||||
struct A;
|
||||
|
||||
unsafe impl<'a> Alloc for &'a A {
|
||||
unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
|
||||
unsafe impl alloc::GlobalAlloc for A {
|
||||
unsafe fn alloc(&self, layout: Layout) -> *mut Void {
|
||||
HITS.fetch_add(1, Ordering::SeqCst);
|
||||
System.alloc(layout)
|
||||
}
|
||||
|
||||
unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) {
|
||||
unsafe fn dealloc(&self, ptr: *mut Void, layout: Layout) {
|
||||
HITS.fetch_add(1, Ordering::SeqCst);
|
||||
System.dealloc(ptr, layout)
|
||||
}
|
||||
@ -45,10 +45,10 @@ fn main() {
|
||||
unsafe {
|
||||
let layout = Layout::from_size_align(4, 2).unwrap();
|
||||
|
||||
let ptr = Heap.alloc(layout.clone()).unwrap();
|
||||
let ptr = Global.alloc(layout.clone()).unwrap();
|
||||
helper::work_with(&ptr);
|
||||
assert_eq!(HITS.load(Ordering::SeqCst), n + 1);
|
||||
Heap.dealloc(ptr, layout.clone());
|
||||
Global.dealloc(ptr, layout.clone());
|
||||
assert_eq!(HITS.load(Ordering::SeqCst), n + 2);
|
||||
|
||||
let s = String::with_capacity(10);
|
||||
|
@ -17,7 +17,7 @@
|
||||
extern crate custom;
|
||||
extern crate helper;
|
||||
|
||||
use std::heap::{Heap, Alloc, System, Layout};
|
||||
use std::alloc::{Global, Alloc, System, Layout};
|
||||
use std::sync::atomic::{Ordering, ATOMIC_USIZE_INIT};
|
||||
|
||||
#[global_allocator]
|
||||
@ -28,10 +28,10 @@ fn main() {
|
||||
let n = GLOBAL.0.load(Ordering::SeqCst);
|
||||
let layout = Layout::from_size_align(4, 2).unwrap();
|
||||
|
||||
let ptr = Heap.alloc(layout.clone()).unwrap();
|
||||
let ptr = Global.alloc(layout.clone()).unwrap();
|
||||
helper::work_with(&ptr);
|
||||
assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 1);
|
||||
Heap.dealloc(ptr, layout.clone());
|
||||
Global.dealloc(ptr, layout.clone());
|
||||
assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2);
|
||||
|
||||
let ptr = System.alloc(layout.clone()).unwrap();
|
||||
|
@ -19,7 +19,7 @@ extern crate custom;
|
||||
extern crate custom_as_global;
|
||||
extern crate helper;
|
||||
|
||||
use std::heap::{Heap, Alloc, System, Layout};
|
||||
use std::alloc::{Global, Alloc, GlobalAlloc, System, Layout};
|
||||
use std::sync::atomic::{Ordering, ATOMIC_USIZE_INIT};
|
||||
|
||||
static GLOBAL: custom::A = custom::A(ATOMIC_USIZE_INIT);
|
||||
@ -30,25 +30,25 @@ fn main() {
|
||||
let layout = Layout::from_size_align(4, 2).unwrap();
|
||||
|
||||
// Global allocator routes to the `custom_as_global` global
|
||||
let ptr = Heap.alloc(layout.clone()).unwrap();
|
||||
let ptr = Global.alloc(layout.clone()).unwrap();
|
||||
helper::work_with(&ptr);
|
||||
assert_eq!(custom_as_global::get(), n + 1);
|
||||
Heap.dealloc(ptr, layout.clone());
|
||||
Global.dealloc(ptr, layout.clone());
|
||||
assert_eq!(custom_as_global::get(), n + 2);
|
||||
|
||||
// Usage of the system allocator avoids all globals
|
||||
let ptr = System.alloc(layout.clone()).unwrap();
|
||||
let ptr = System.alloc(layout.clone());
|
||||
helper::work_with(&ptr);
|
||||
assert_eq!(custom_as_global::get(), n + 2);
|
||||
System.dealloc(ptr, layout.clone());
|
||||
assert_eq!(custom_as_global::get(), n + 2);
|
||||
|
||||
// Usage of our personal allocator doesn't affect other instances
|
||||
let ptr = (&GLOBAL).alloc(layout.clone()).unwrap();
|
||||
let ptr = GLOBAL.alloc(layout.clone());
|
||||
helper::work_with(&ptr);
|
||||
assert_eq!(custom_as_global::get(), n + 2);
|
||||
assert_eq!(GLOBAL.0.load(Ordering::SeqCst), 1);
|
||||
(&GLOBAL).dealloc(ptr, layout);
|
||||
GLOBAL.dealloc(ptr, layout);
|
||||
assert_eq!(custom_as_global::get(), n + 2);
|
||||
assert_eq!(GLOBAL.0.load(Ordering::SeqCst), 2);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user