/// * if a layout `k` fits a memory block (denoted by `ptr`)
/// currently allocated via an allocator `a`, then it is legal to
/// use that layout to deallocate it, i.e. `a.dealloc(ptr, k);`.
+///
+/// # Unsafety
+///
+/// The `Alloc` trait is an `unsafe` trait for a number of reasons, and
+/// implementors must ensure that they adhere to these contracts:
+///
+/// * Pointers returned from allocation functions must point to valid memory and
+/// retain their validity until at least the instance of `Alloc` is dropped
+/// itself.
+///
+/// * It's undefined behavior if global allocators unwind. This restriction may
+/// be lifted in the future, but currently a panic from any of these
+/// functions may lead to memory unsafety. Note that as of the time of this
+/// writing allocators *not* intending to be global allocators can still panic
+/// in their implementation without violating memory safety.
+///
+/// * `Layout` queries and calculations in general must be correct. Callers of
+/// this trait are allowed to rely on the contracts defined on each method,
+/// and implementors must ensure such contracts remain true.
+///
+/// Note that this list may get tweaked over time as clarifications are made in
+/// the future. Additionally global allocators may gain unique requirements for
+/// how to safely implement one in the future as well.
pub unsafe trait Alloc {
// (Note: existing allocators have unspecified but well-defined
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,
new_size: usize,
new_align: usize,
err: *mut u8) -> *mut u8;
+ #[rustc_allocator_nounwind]
fn __rust_alloc_zeroed(size: usize, align: usize, err: *mut u8) -> *mut u8;
+ #[rustc_allocator_nounwind]
fn __rust_alloc_excess(size: usize,
align: usize,
excess: *mut usize,
err: *mut u8) -> *mut u8;
+ #[rustc_allocator_nounwind]
fn __rust_realloc_excess(ptr: *mut u8,
old_size: usize,
old_align: usize,
new_align: usize,
excess: *mut usize,
err: *mut u8) -> *mut u8;
+ #[rustc_allocator_nounwind]
fn __rust_grow_in_place(ptr: *mut u8,
old_size: usize,
old_align: usize,
new_size: usize,
new_align: usize) -> u8;
+ #[rustc_allocator_nounwind]
fn __rust_shrink_in_place(ptr: *mut u8,
old_size: usize,
old_align: usize,
#![feature(pattern)]
#![feature(placement_in_syntax)]
#![feature(placement_new_protocol)]
+#![feature(rustc_attrs)]
#![feature(shared)]
#![feature(slice_get_slice)]
#![feature(slice_patterns)]
llvm::AttributePlace::ReturnValue(), llfn);
} else if attr.check_name("unwind") {
unwind(llfn, true);
+ } else if attr.check_name("rustc_allocator_nounwind") {
+ unwind(llfn, false);
}
}
if !target_features.is_empty() {
--- /dev/null
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+//
+// no-system-llvm
+// compile-flags: -O
+
+#![crate_type="lib"]
+
+struct A;
+
+impl Drop for A {
+ fn drop(&mut self) {
+ extern { fn foo(); }
+ unsafe { foo(); }
+ }
+}
+
+#[no_mangle]
+pub fn a(a: Box<i32>) {
+ // CHECK-LABEL: define void @a
+ // CHECK: call void @__rust_dealloc
+ // CHECK-NEXT: call void @foo
+ let _a = A;
+ drop(a);
+}