Initial
This commit is contained in:
2
avr-core/.gitignore
vendored
Normal file
2
avr-core/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
Cargo.lock
|
||||
target/
|
||||
6
avr-core/Cargo.toml
Normal file
6
avr-core/Cargo.toml
Normal file
@@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "avr-core"
|
||||
version = "0.1.0"
|
||||
authors = ["The Rust Project"]
|
||||
|
||||
[dependencies]
|
||||
84
avr-core/src/clone.rs
Normal file
84
avr-core/src/clone.rs
Normal file
@@ -0,0 +1,84 @@
|
||||
// Copyright 2012-2013 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.
|
||||
|
||||
//! The `Clone` trait for types that cannot be 'implicitly copied'
|
||||
//!
|
||||
//! In Rust, some simple types are "implicitly copyable" and when you
|
||||
//! assign them or pass them as arguments, the receiver will get a copy,
|
||||
//! leaving the original value in place. These types do not require
|
||||
//! allocation to copy and do not have finalizers (i.e. they do not
|
||||
//! contain owned boxes or implement `Drop`), so the compiler considers
|
||||
//! them cheap and safe to copy. For other types copies must be made
|
||||
//! explicitly, by convention implementing the `Clone` trait and calling
|
||||
//! the `clone` method.
|
||||
|
||||
|
||||
use marker::Sized;
|
||||
|
||||
/// A common trait for cloning an object.
|
||||
///
|
||||
/// This trait can be used with `#[derive]`.
|
||||
pub trait Clone : Sized {
|
||||
/// Returns a copy of the value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let hello = "Hello"; // &str implements Clone
|
||||
///
|
||||
/// assert_eq!("Hello", hello.clone());
|
||||
/// ```
|
||||
fn clone(&self) -> Self;
|
||||
|
||||
/// Performs copy-assignment from `source`.
|
||||
///
|
||||
/// `a.clone_from(&b)` is equivalent to `a = b.clone()` in functionality,
|
||||
/// but can be overridden to reuse the resources of `a` to avoid unnecessary
|
||||
/// allocations.
|
||||
#[inline(always)]
|
||||
fn clone_from(&mut self, source: &Self) {
|
||||
*self = source.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized> Clone for &'a T {
|
||||
/// Returns a shallow copy of the reference.
|
||||
#[inline]
|
||||
fn clone(&self) -> &'a T { *self }
|
||||
}
|
||||
|
||||
macro_rules! clone_impl {
|
||||
($t:ty) => {
|
||||
impl Clone for $t {
|
||||
/// Returns a deep copy of the value.
|
||||
#[inline]
|
||||
fn clone(&self) -> $t { *self }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clone_impl! { isize }
|
||||
clone_impl! { i8 }
|
||||
clone_impl! { i16 }
|
||||
clone_impl! { i32 }
|
||||
clone_impl! { i64 }
|
||||
|
||||
clone_impl! { usize }
|
||||
clone_impl! { u8 }
|
||||
clone_impl! { u16 }
|
||||
clone_impl! { u32 }
|
||||
clone_impl! { u64 }
|
||||
|
||||
clone_impl! { f32 }
|
||||
clone_impl! { f64 }
|
||||
|
||||
clone_impl! { () }
|
||||
clone_impl! { bool }
|
||||
clone_impl! { char }
|
||||
550
avr-core/src/cmp.rs
Normal file
550
avr-core/src/cmp.rs
Normal file
@@ -0,0 +1,550 @@
|
||||
// Copyright 2012-2014 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.
|
||||
|
||||
//! Functionality for ordering and comparison.
|
||||
//!
|
||||
//! This module defines both `PartialOrd` and `PartialEq` traits which are used
|
||||
//! by the compiler to implement comparison operators. Rust programs may
|
||||
//! implement `PartialOrd` to overload the `<`, `<=`, `>`, and `>=` operators,
|
||||
//! and may implement `PartialEq` to overload the `==` and `!=` operators.
|
||||
|
||||
|
||||
use self::Ordering::*;
|
||||
|
||||
use marker::Sized;
|
||||
use option::Option::{self, Some};
|
||||
|
||||
/// Trait for equality comparisons which are [partial equivalence
|
||||
/// relations](http://en.wikipedia.org/wiki/Partial_equivalence_relation).
|
||||
///
|
||||
/// This trait allows for partial equality, for types that do not have a full
|
||||
/// equivalence relation. For example, in floating point numbers `NaN != NaN`,
|
||||
/// so floating point types implement `PartialEq` but not `Eq`.
|
||||
///
|
||||
/// Formally, the equality must be (for all `a`, `b` and `c`):
|
||||
///
|
||||
/// - symmetric: `a == b` implies `b == a`; and
|
||||
/// - transitive: `a == b` and `b == c` implies `a == c`.
|
||||
///
|
||||
/// Note that these requirements mean that the trait itself must be implemented
|
||||
/// symmetrically and transitively: if `T: PartialEq<U>` and `U: PartialEq<V>`
|
||||
/// then `U: PartialEq<T>` and `T: PartialEq<V>`.
|
||||
///
|
||||
/// PartialEq only requires the `eq` method to be implemented; `ne` is defined
|
||||
/// in terms of it by default. Any manual implementation of `ne` *must* respect
|
||||
/// the rule that `eq` is a strict inverse of `ne`; that is, `!(a == b)` if and
|
||||
/// only if `a != b`.
|
||||
///
|
||||
/// This trait can be used with `#[derive]`.
|
||||
#[lang = "eq"]
|
||||
pub trait PartialEq<Rhs: ?Sized = Self> {
|
||||
/// This method tests for `self` and `other` values to be equal, and is used
|
||||
/// by `==`.
|
||||
fn eq(&self, other: &Rhs) -> bool;
|
||||
|
||||
/// This method tests for `!=`.
|
||||
#[inline]
|
||||
fn ne(&self, other: &Rhs) -> bool { !self.eq(other) }
|
||||
}
|
||||
|
||||
/// Trait for equality comparisons which are [equivalence relations](
|
||||
/// https://en.wikipedia.org/wiki/Equivalence_relation).
|
||||
///
|
||||
/// This means, that in addition to `a == b` and `a != b` being strict inverses, the equality must
|
||||
/// be (for all `a`, `b` and `c`):
|
||||
///
|
||||
/// - reflexive: `a == a`;
|
||||
/// - symmetric: `a == b` implies `b == a`; and
|
||||
/// - transitive: `a == b` and `b == c` implies `a == c`.
|
||||
///
|
||||
/// This property cannot be checked by the compiler, and therefore `Eq` implies
|
||||
/// `PartialEq`, and has no extra methods.
|
||||
///
|
||||
/// This trait can be used with `#[derive]`.
|
||||
pub trait Eq: PartialEq<Self> {
|
||||
// FIXME #13101: this method is used solely by #[deriving] to
|
||||
// assert that every component of a type implements #[deriving]
|
||||
// itself, the current deriving infrastructure means doing this
|
||||
// assertion without using a method on this trait is nearly
|
||||
// impossible.
|
||||
//
|
||||
// This should never be implemented by hand.
|
||||
#[doc(hidden)]
|
||||
#[inline(always)]
|
||||
fn assert_receiver_is_total_eq(&self) {}
|
||||
}
|
||||
|
||||
/// An `Ordering` is the result of a comparison between two values.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::cmp::Ordering;
|
||||
///
|
||||
/// let result = 1.cmp(&2);
|
||||
/// assert_eq!(Ordering::Less, result);
|
||||
///
|
||||
/// let result = 1.cmp(&1);
|
||||
/// assert_eq!(Ordering::Equal, result);
|
||||
///
|
||||
/// let result = 2.cmp(&1);
|
||||
/// assert_eq!(Ordering::Greater, result);
|
||||
/// ```
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub enum Ordering {
|
||||
/// An ordering where a compared value is less [than another].
|
||||
Less = -1,
|
||||
/// An ordering where a compared value is equal [to another].
|
||||
Equal = 0,
|
||||
/// An ordering where a compared value is greater [than another].
|
||||
Greater = 1,
|
||||
}
|
||||
|
||||
// impl Ordering {
|
||||
// unsafe fn from_i8_unchecked(v: i8) -> Ordering {
|
||||
// mem::transmute(v)
|
||||
// }
|
||||
|
||||
// /// Reverse the `Ordering`.
|
||||
// ///
|
||||
// /// * `Less` becomes `Greater`.
|
||||
// /// * `Greater` becomes `Less`.
|
||||
// /// * `Equal` becomes `Equal`.
|
||||
// ///
|
||||
// /// # Examples
|
||||
// ///
|
||||
// /// Basic behavior:
|
||||
// ///
|
||||
// /// ```
|
||||
// /// use std::cmp::Ordering;
|
||||
// ///
|
||||
// /// assert_eq!(Ordering::Less.reverse(), Ordering::Greater);
|
||||
// /// assert_eq!(Ordering::Equal.reverse(), Ordering::Equal);
|
||||
// /// assert_eq!(Ordering::Greater.reverse(), Ordering::Less);
|
||||
// /// ```
|
||||
// ///
|
||||
// /// This method can be used to reverse a comparison:
|
||||
// ///
|
||||
// /// ```
|
||||
// /// let mut data: &mut [_] = &mut [2, 10, 5, 8];
|
||||
// ///
|
||||
// /// // sort the array from largest to smallest.
|
||||
// /// data.sort_by(|a, b| a.cmp(b).reverse());
|
||||
// ///
|
||||
// /// let b: &mut [_] = &mut [10, 8, 5, 2];
|
||||
// /// assert!(data == b);
|
||||
// /// ```
|
||||
// #[inline]
|
||||
// pub fn reverse(self) -> Ordering {
|
||||
// unsafe {
|
||||
// // this compiles really nicely (to a single instruction);
|
||||
// // an explicit match has a pile of branches and
|
||||
// // comparisons.
|
||||
// //
|
||||
// // NB. it is safe because of the explicit discriminants
|
||||
// // given above.
|
||||
// Ordering::from_i8_unchecked(-(self as i8))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
/// Trait for types that form a [total order](https://en.wikipedia.org/wiki/Total_order).
|
||||
///
|
||||
/// An order is a total order if it is (for all `a`, `b` and `c`):
|
||||
///
|
||||
/// - total and antisymmetric: exactly one of `a < b`, `a == b` or `a > b` is true; and
|
||||
/// - transitive, `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
|
||||
///
|
||||
/// When this trait is `derive`d, it produces a lexicographic ordering.
|
||||
///
|
||||
/// This trait can be used with `#[derive]`.
|
||||
pub trait Ord: Eq + PartialOrd<Self> {
|
||||
/// This method returns an `Ordering` between `self` and `other`.
|
||||
///
|
||||
/// By convention, `self.cmp(&other)` returns the ordering matching the expression
|
||||
/// `self <operator> other` if true.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::cmp::Ordering;
|
||||
///
|
||||
/// assert_eq!(5.cmp(&10), Ordering::Less);
|
||||
/// assert_eq!(10.cmp(&5), Ordering::Greater);
|
||||
/// assert_eq!(5.cmp(&5), Ordering::Equal);
|
||||
/// ```
|
||||
fn cmp(&self, other: &Self) -> Ordering;
|
||||
}
|
||||
|
||||
impl Eq for Ordering {}
|
||||
|
||||
impl Ord for Ordering {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &Ordering) -> Ordering {
|
||||
(*self as i32).cmp(&(*other as i32))
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for Ordering {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &Ordering) -> Option<Ordering> {
|
||||
(*self as i32).partial_cmp(&(*other as i32))
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for values that can be compared for a sort-order.
|
||||
///
|
||||
/// The comparison must satisfy, for all `a`, `b` and `c`:
|
||||
///
|
||||
/// - antisymmetry: if `a < b` then `!(a > b)`, as well as `a > b` implying `!(a < b)`; and
|
||||
/// - transitivity: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
|
||||
///
|
||||
/// Note that these requirements mean that the trait itself must be implemented symmetrically and
|
||||
/// transitively: if `T: PartialOrd<U>` and `U: PartialOrd<V>` then `U: PartialOrd<T>` and `T:
|
||||
/// PartialOrd<V>`.
|
||||
///
|
||||
/// PartialOrd only requires implementation of the `partial_cmp` method, with the others generated
|
||||
/// from default implementations.
|
||||
///
|
||||
/// However it remains possible to implement the others separately for types which do not have a
|
||||
/// total order. For example, for floating point numbers, `NaN < 0 == false` and `NaN >= 0 ==
|
||||
/// false` (cf. IEEE 754-2008 section 5.11).
|
||||
///
|
||||
/// This trait can be used with `#[derive]`.
|
||||
#[lang = "ord"]
|
||||
pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
|
||||
/// This method returns an ordering between `self` and `other` values if one exists.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::cmp::Ordering;
|
||||
///
|
||||
/// let result = 1.0.partial_cmp(&2.0);
|
||||
/// assert_eq!(result, Some(Ordering::Less));
|
||||
///
|
||||
/// let result = 1.0.partial_cmp(&1.0);
|
||||
/// assert_eq!(result, Some(Ordering::Equal));
|
||||
///
|
||||
/// let result = 2.0.partial_cmp(&1.0);
|
||||
/// assert_eq!(result, Some(Ordering::Greater));
|
||||
/// ```
|
||||
///
|
||||
/// When comparison is impossible:
|
||||
///
|
||||
/// ```
|
||||
/// let result = std::f64::NAN.partial_cmp(&1.0);
|
||||
/// assert_eq!(result, None);
|
||||
/// ```
|
||||
fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;
|
||||
|
||||
/// This method tests less than (for `self` and `other`) and is used by the `<` operator.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let result = 1.0 < 2.0;
|
||||
/// assert_eq!(result, true);
|
||||
///
|
||||
/// let result = 2.0 < 1.0;
|
||||
/// assert_eq!(result, false);
|
||||
/// ```
|
||||
#[inline]
|
||||
fn lt(&self, other: &Rhs) -> bool {
|
||||
match self.partial_cmp(other) {
|
||||
Some(Less) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// This method tests less than or equal to (for `self` and `other`) and is used by the `<=`
|
||||
/// operator.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let result = 1.0 <= 2.0;
|
||||
/// assert_eq!(result, true);
|
||||
///
|
||||
/// let result = 2.0 <= 2.0;
|
||||
/// assert_eq!(result, true);
|
||||
/// ```
|
||||
#[inline]
|
||||
fn le(&self, other: &Rhs) -> bool {
|
||||
match self.partial_cmp(other) {
|
||||
Some(Less) | Some(Equal) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// This method tests greater than (for `self` and `other`) and is used by the `>` operator.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let result = 1.0 > 2.0;
|
||||
/// assert_eq!(result, false);
|
||||
///
|
||||
/// let result = 2.0 > 2.0;
|
||||
/// assert_eq!(result, false);
|
||||
/// ```
|
||||
#[inline]
|
||||
fn gt(&self, other: &Rhs) -> bool {
|
||||
match self.partial_cmp(other) {
|
||||
Some(Greater) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// This method tests greater than or equal to (for `self` and `other`) and is used by the `>=`
|
||||
/// operator.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let result = 2.0 >= 1.0;
|
||||
/// assert_eq!(result, true);
|
||||
///
|
||||
/// let result = 2.0 >= 2.0;
|
||||
/// assert_eq!(result, true);
|
||||
/// ```
|
||||
#[inline]
|
||||
fn ge(&self, other: &Rhs) -> bool {
|
||||
match self.partial_cmp(other) {
|
||||
Some(Greater) | Some(Equal) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Compare and return the minimum of two values.
|
||||
///
|
||||
/// Returns the first argument if the comparison determines them to be equal.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::cmp;
|
||||
///
|
||||
/// assert_eq!(1, cmp::min(1, 2));
|
||||
/// assert_eq!(2, cmp::min(2, 2));
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn min<T: Ord>(v1: T, v2: T) -> T {
|
||||
if v1 <= v2 { v1 } else { v2 }
|
||||
}
|
||||
|
||||
/// Compare and return the maximum of two values.
|
||||
///
|
||||
/// Returns the second argument if the comparison determines them to be equal.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::cmp;
|
||||
///
|
||||
/// assert_eq!(2, cmp::max(1, 2));
|
||||
/// assert_eq!(2, cmp::max(2, 2));
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn max<T: Ord>(v1: T, v2: T) -> T {
|
||||
if v2 >= v1 { v2 } else { v1 }
|
||||
}
|
||||
|
||||
// Implementation of PartialEq, Eq, PartialOrd and Ord for primitive types
|
||||
mod impls {
|
||||
use cmp::{PartialOrd, Ord, PartialEq, Eq, Ordering};
|
||||
use cmp::Ordering::{Less, Greater, Equal};
|
||||
use marker::Sized;
|
||||
use option::Option;
|
||||
use option::Option::{Some, None};
|
||||
|
||||
macro_rules! partial_eq_impl {
|
||||
($($t:ty)*) => ($(
|
||||
impl PartialEq for $t {
|
||||
#[inline]
|
||||
fn eq(&self, other: &$t) -> bool { (*self) == (*other) }
|
||||
#[inline]
|
||||
fn ne(&self, other: &$t) -> bool { (*self) != (*other) }
|
||||
}
|
||||
)*)
|
||||
}
|
||||
|
||||
impl PartialEq for () {
|
||||
#[inline]
|
||||
fn eq(&self, _other: &()) -> bool { true }
|
||||
#[inline]
|
||||
fn ne(&self, _other: &()) -> bool { false }
|
||||
}
|
||||
|
||||
partial_eq_impl! {
|
||||
bool char usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64
|
||||
}
|
||||
|
||||
macro_rules! eq_impl {
|
||||
($($t:ty)*) => ($(
|
||||
impl Eq for $t {}
|
||||
)*)
|
||||
}
|
||||
|
||||
eq_impl! { () bool char usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
|
||||
|
||||
macro_rules! partial_ord_impl {
|
||||
($($t:ty)*) => ($(
|
||||
impl PartialOrd for $t {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &$t) -> Option<Ordering> {
|
||||
match (self <= other, self >= other) {
|
||||
(false, false) => None,
|
||||
(false, true) => Some(Greater),
|
||||
(true, false) => Some(Less),
|
||||
(true, true) => Some(Equal),
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
fn lt(&self, other: &$t) -> bool { (*self) < (*other) }
|
||||
#[inline]
|
||||
fn le(&self, other: &$t) -> bool { (*self) <= (*other) }
|
||||
#[inline]
|
||||
fn ge(&self, other: &$t) -> bool { (*self) >= (*other) }
|
||||
#[inline]
|
||||
fn gt(&self, other: &$t) -> bool { (*self) > (*other) }
|
||||
}
|
||||
)*)
|
||||
}
|
||||
|
||||
impl PartialOrd for () {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, _: &()) -> Option<Ordering> {
|
||||
Some(Equal)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for bool {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &bool) -> Option<Ordering> {
|
||||
(*self as u8).partial_cmp(&(*other as u8))
|
||||
}
|
||||
}
|
||||
|
||||
partial_ord_impl! { f32 f64 }
|
||||
|
||||
macro_rules! ord_impl {
|
||||
($($t:ty)*) => ($(
|
||||
impl PartialOrd for $t {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &$t) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
#[inline]
|
||||
fn lt(&self, other: &$t) -> bool { (*self) < (*other) }
|
||||
#[inline]
|
||||
fn le(&self, other: &$t) -> bool { (*self) <= (*other) }
|
||||
#[inline]
|
||||
fn ge(&self, other: &$t) -> bool { (*self) >= (*other) }
|
||||
#[inline]
|
||||
fn gt(&self, other: &$t) -> bool { (*self) > (*other) }
|
||||
}
|
||||
|
||||
impl Ord for $t {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &$t) -> Ordering {
|
||||
if *self == *other { Equal }
|
||||
else if *self < *other { Less }
|
||||
else { Greater }
|
||||
}
|
||||
}
|
||||
)*)
|
||||
}
|
||||
|
||||
impl Ord for () {
|
||||
#[inline]
|
||||
fn cmp(&self, _other: &()) -> Ordering { Equal }
|
||||
}
|
||||
|
||||
impl Ord for bool {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &bool) -> Ordering {
|
||||
(*self as u8).cmp(&(*other as u8))
|
||||
}
|
||||
}
|
||||
|
||||
ord_impl! { char usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
|
||||
|
||||
// & pointers
|
||||
|
||||
impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b B> for &'a A where A: PartialEq<B> {
|
||||
#[inline]
|
||||
fn eq(&self, other: & &'b B) -> bool { PartialEq::eq(*self, *other) }
|
||||
#[inline]
|
||||
fn ne(&self, other: & &'b B) -> bool { PartialEq::ne(*self, *other) }
|
||||
}
|
||||
impl<'a, 'b, A: ?Sized, B: ?Sized> PartialOrd<&'b B> for &'a A where A: PartialOrd<B> {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &&'b B) -> Option<Ordering> {
|
||||
PartialOrd::partial_cmp(*self, *other)
|
||||
}
|
||||
#[inline]
|
||||
fn lt(&self, other: & &'b B) -> bool { PartialOrd::lt(*self, *other) }
|
||||
#[inline]
|
||||
fn le(&self, other: & &'b B) -> bool { PartialOrd::le(*self, *other) }
|
||||
#[inline]
|
||||
fn ge(&self, other: & &'b B) -> bool { PartialOrd::ge(*self, *other) }
|
||||
#[inline]
|
||||
fn gt(&self, other: & &'b B) -> bool { PartialOrd::gt(*self, *other) }
|
||||
}
|
||||
impl<'a, A: ?Sized> Ord for &'a A where A: Ord {
|
||||
#[inline]
|
||||
fn cmp(&self, other: & &'a A) -> Ordering { Ord::cmp(*self, *other) }
|
||||
}
|
||||
impl<'a, A: ?Sized> Eq for &'a A where A: Eq {}
|
||||
|
||||
// &mut pointers
|
||||
|
||||
impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b mut B> for &'a mut A where A: PartialEq<B> {
|
||||
#[inline]
|
||||
fn eq(&self, other: &&'b mut B) -> bool { PartialEq::eq(*self, *other) }
|
||||
#[inline]
|
||||
fn ne(&self, other: &&'b mut B) -> bool { PartialEq::ne(*self, *other) }
|
||||
}
|
||||
impl<'a, 'b, A: ?Sized, B: ?Sized> PartialOrd<&'b mut B> for &'a mut A where A: PartialOrd<B> {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &&'b mut B) -> Option<Ordering> {
|
||||
PartialOrd::partial_cmp(*self, *other)
|
||||
}
|
||||
#[inline]
|
||||
fn lt(&self, other: &&'b mut B) -> bool { PartialOrd::lt(*self, *other) }
|
||||
#[inline]
|
||||
fn le(&self, other: &&'b mut B) -> bool { PartialOrd::le(*self, *other) }
|
||||
#[inline]
|
||||
fn ge(&self, other: &&'b mut B) -> bool { PartialOrd::ge(*self, *other) }
|
||||
#[inline]
|
||||
fn gt(&self, other: &&'b mut B) -> bool { PartialOrd::gt(*self, *other) }
|
||||
}
|
||||
impl<'a, A: ?Sized> Ord for &'a mut A where A: Ord {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &&'a mut A) -> Ordering { Ord::cmp(*self, *other) }
|
||||
}
|
||||
impl<'a, A: ?Sized> Eq for &'a mut A where A: Eq {}
|
||||
|
||||
impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b mut B> for &'a A where A: PartialEq<B> {
|
||||
#[inline]
|
||||
fn eq(&self, other: &&'b mut B) -> bool { PartialEq::eq(*self, *other) }
|
||||
#[inline]
|
||||
fn ne(&self, other: &&'b mut B) -> bool { PartialEq::ne(*self, *other) }
|
||||
}
|
||||
|
||||
impl<'a, 'b, A: ?Sized, B: ?Sized> PartialEq<&'b B> for &'a mut A where A: PartialEq<B> {
|
||||
#[inline]
|
||||
fn eq(&self, other: &&'b B) -> bool { PartialEq::eq(*self, *other) }
|
||||
#[inline]
|
||||
fn ne(&self, other: &&'b B) -> bool { PartialEq::ne(*self, *other) }
|
||||
}
|
||||
}
|
||||
585
avr-core/src/intrinsics.rs
Normal file
585
avr-core/src/intrinsics.rs
Normal file
@@ -0,0 +1,585 @@
|
||||
// Copyright 2013 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.
|
||||
|
||||
//! rustc compiler intrinsics.
|
||||
//!
|
||||
//! The corresponding definitions are in librustc_trans/trans/intrinsic.rs.
|
||||
//!
|
||||
//! # Volatiles
|
||||
//!
|
||||
//! The volatile intrinsics provide operations intended to act on I/O
|
||||
//! memory, which are guaranteed to not be reordered by the compiler
|
||||
//! across other volatile intrinsics. See the LLVM documentation on
|
||||
//! [[volatile]].
|
||||
//!
|
||||
//! [volatile]: http://llvm.org/docs/LangRef.html#volatile-memory-accesses
|
||||
//!
|
||||
//! # Atomics
|
||||
//!
|
||||
//! The atomic intrinsics provide common atomic operations on machine
|
||||
//! words, with multiple possible memory orderings. They obey the same
|
||||
//! semantics as C++11. See the LLVM documentation on [[atomics]].
|
||||
//!
|
||||
//! [atomics]: http://llvm.org/docs/Atomics.html
|
||||
//!
|
||||
//! A quick refresher on memory ordering:
|
||||
//!
|
||||
//! * Acquire - a barrier for acquiring a lock. Subsequent reads and writes
|
||||
//! take place after the barrier.
|
||||
//! * Release - a barrier for releasing a lock. Preceding reads and writes
|
||||
//! take place before the barrier.
|
||||
//! * Sequentially consistent - sequentially consistent operations are
|
||||
//! guaranteed to happen in order. This is the standard mode for working
|
||||
//! with atomic types and is equivalent to Java's `volatile`.
|
||||
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use marker::Sized;
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
|
||||
// NB: These intrinsics take raw pointers because they mutate aliased
|
||||
// memory, which is not valid for either `&` or `&mut`.
|
||||
|
||||
pub fn atomic_cxchg<T>(dst: *mut T, old: T, src: T) -> (T, bool);
|
||||
pub fn atomic_cxchg_acq<T>(dst: *mut T, old: T, src: T) -> (T, bool);
|
||||
pub fn atomic_cxchg_rel<T>(dst: *mut T, old: T, src: T) -> (T, bool);
|
||||
pub fn atomic_cxchg_acqrel<T>(dst: *mut T, old: T, src: T) -> (T, bool);
|
||||
pub fn atomic_cxchg_relaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
|
||||
pub fn atomic_cxchg_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
|
||||
pub fn atomic_cxchg_failacq<T>(dst: *mut T, old: T, src: T) -> (T, bool);
|
||||
pub fn atomic_cxchg_acq_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
|
||||
pub fn atomic_cxchg_acqrel_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
|
||||
|
||||
pub fn atomic_cxchgweak<T>(dst: *mut T, old: T, src: T) -> (T, bool);
|
||||
pub fn atomic_cxchgweak_acq<T>(dst: *mut T, old: T, src: T) -> (T, bool);
|
||||
pub fn atomic_cxchgweak_rel<T>(dst: *mut T, old: T, src: T) -> (T, bool);
|
||||
pub fn atomic_cxchgweak_acqrel<T>(dst: *mut T, old: T, src: T) -> (T, bool);
|
||||
pub fn atomic_cxchgweak_relaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
|
||||
pub fn atomic_cxchgweak_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
|
||||
pub fn atomic_cxchgweak_failacq<T>(dst: *mut T, old: T, src: T) -> (T, bool);
|
||||
pub fn atomic_cxchgweak_acq_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
|
||||
pub fn atomic_cxchgweak_acqrel_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
|
||||
|
||||
pub fn atomic_load<T>(src: *const T) -> T;
|
||||
pub fn atomic_load_acq<T>(src: *const T) -> T;
|
||||
pub fn atomic_load_relaxed<T>(src: *const T) -> T;
|
||||
pub fn atomic_load_unordered<T>(src: *const T) -> T;
|
||||
|
||||
pub fn atomic_store<T>(dst: *mut T, val: T);
|
||||
pub fn atomic_store_rel<T>(dst: *mut T, val: T);
|
||||
pub fn atomic_store_relaxed<T>(dst: *mut T, val: T);
|
||||
pub fn atomic_store_unordered<T>(dst: *mut T, val: T);
|
||||
|
||||
pub fn atomic_xchg<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_xchg_acq<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_xchg_rel<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_xchg_acqrel<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_xchg_relaxed<T>(dst: *mut T, src: T) -> T;
|
||||
|
||||
pub fn atomic_xadd<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_xadd_acq<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_xadd_rel<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_xadd_acqrel<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_xadd_relaxed<T>(dst: *mut T, src: T) -> T;
|
||||
|
||||
pub fn atomic_xsub<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_xsub_acq<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_xsub_rel<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_xsub_acqrel<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_xsub_relaxed<T>(dst: *mut T, src: T) -> T;
|
||||
|
||||
pub fn atomic_and<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_and_acq<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_and_rel<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_and_acqrel<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_and_relaxed<T>(dst: *mut T, src: T) -> T;
|
||||
|
||||
pub fn atomic_nand<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_nand_acq<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_nand_rel<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_nand_acqrel<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_nand_relaxed<T>(dst: *mut T, src: T) -> T;
|
||||
|
||||
pub fn atomic_or<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_or_acq<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_or_rel<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_or_acqrel<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_or_relaxed<T>(dst: *mut T, src: T) -> T;
|
||||
|
||||
pub fn atomic_xor<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_xor_acq<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_xor_rel<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_xor_acqrel<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_xor_relaxed<T>(dst: *mut T, src: T) -> T;
|
||||
|
||||
pub fn atomic_max<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_max_acq<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_max_rel<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_max_acqrel<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_max_relaxed<T>(dst: *mut T, src: T) -> T;
|
||||
|
||||
pub fn atomic_min<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_min_acq<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_min_rel<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_min_acqrel<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_min_relaxed<T>(dst: *mut T, src: T) -> T;
|
||||
|
||||
pub fn atomic_umin<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_umin_acq<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_umin_rel<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_umin_acqrel<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_umin_relaxed<T>(dst: *mut T, src: T) -> T;
|
||||
|
||||
pub fn atomic_umax<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_umax_acq<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_umax_rel<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_umax_acqrel<T>(dst: *mut T, src: T) -> T;
|
||||
pub fn atomic_umax_relaxed<T>(dst: *mut T, src: T) -> T;
|
||||
}
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
|
||||
pub fn atomic_fence();
|
||||
pub fn atomic_fence_acq();
|
||||
pub fn atomic_fence_rel();
|
||||
pub fn atomic_fence_acqrel();
|
||||
|
||||
/// A compiler-only memory barrier.
|
||||
///
|
||||
/// Memory accesses will never be reordered across this barrier by the
|
||||
/// compiler, but no instructions will be emitted for it. This is
|
||||
/// appropriate for operations on the same thread that may be preempted,
|
||||
/// such as when interacting with signal handlers.
|
||||
pub fn atomic_singlethreadfence();
|
||||
pub fn atomic_singlethreadfence_acq();
|
||||
pub fn atomic_singlethreadfence_rel();
|
||||
pub fn atomic_singlethreadfence_acqrel();
|
||||
|
||||
/// Aborts the execution of the process.
|
||||
pub fn abort() -> !;
|
||||
|
||||
/// Tells LLVM that this point in the code is not reachable,
|
||||
/// enabling further optimizations.
|
||||
///
|
||||
/// NB: This is very different from the `unreachable!()` macro!
|
||||
pub fn unreachable() -> !;
|
||||
|
||||
/// Informs the optimizer that a condition is always true.
|
||||
/// If the condition is false, the behavior is undefined.
|
||||
///
|
||||
/// No code is generated for this intrinsic, but the optimizer will try
|
||||
/// to preserve it (and its condition) between passes, which may interfere
|
||||
/// with optimization of surrounding code and reduce performance. It should
|
||||
/// not be used if the invariant can be discovered by the optimizer on its
|
||||
/// own, or if it does not enable any significant optimizations.
|
||||
pub fn assume(b: bool);
|
||||
|
||||
/// Executes a breakpoint trap, for inspection by a debugger.
|
||||
pub fn breakpoint();
|
||||
|
||||
/// The size of a type in bytes.
|
||||
///
|
||||
/// More specifically, this is the offset in bytes between successive
|
||||
/// items of the same type, including alignment padding.
|
||||
pub fn size_of<T>() -> usize;
|
||||
|
||||
/// Moves a value to an uninitialized memory location.
|
||||
///
|
||||
/// Drop glue is not run on the destination.
|
||||
pub fn move_val_init<T>(dst: *mut T, src: T);
|
||||
|
||||
pub fn min_align_of<T>() -> usize;
|
||||
pub fn pref_align_of<T>() -> usize;
|
||||
|
||||
pub fn size_of_val<T: ?Sized>(_: &T) -> usize;
|
||||
pub fn min_align_of_val<T: ?Sized>(_: &T) -> usize;
|
||||
|
||||
/// Executes the destructor (if any) of the pointed-to value.
|
||||
///
|
||||
/// This has two use cases:
|
||||
///
|
||||
/// * It is *required* to use `drop_in_place` to drop unsized types like
|
||||
/// trait objects, because they can't be read out onto the stack and
|
||||
/// dropped normally.
|
||||
///
|
||||
/// * It is friendlier to the optimizer to do this over `ptr::read` when
|
||||
/// dropping manually allocated memory (e.g. when writing Box/Rc/Vec),
|
||||
/// as the compiler doesn't need to prove that it's sound to elide the
|
||||
/// copy.
|
||||
///
|
||||
/// # Undefined Behavior
|
||||
///
|
||||
/// This has all the same safety problems as `ptr::read` with respect to
|
||||
/// invalid pointers, types, and double drops.
|
||||
pub fn drop_in_place<T: ?Sized>(to_drop: *mut T);
|
||||
|
||||
/// Gets a static string slice containing the name of a type.
|
||||
pub fn type_name<T: ?Sized>() -> &'static str;
|
||||
|
||||
/// Gets an identifier which is globally unique to the specified type. This
|
||||
/// function will return the same value for a type regardless of whichever
|
||||
/// crate it is invoked in.
|
||||
pub fn type_id<T: ?Sized + 'static>() -> u64;
|
||||
|
||||
/// Creates a value initialized to so that its drop flag,
|
||||
/// if any, says that it has been dropped.
|
||||
///
|
||||
/// `init_dropped` is unsafe because it returns a datum with all
|
||||
/// of its bytes set to the drop flag, which generally does not
|
||||
/// correspond to a valid value.
|
||||
///
|
||||
/// This intrinsic is likely to be deprecated in the future when
|
||||
/// Rust moves to non-zeroing dynamic drop (and thus removes the
|
||||
/// embedded drop flags that are being established by this
|
||||
/// intrinsic).
|
||||
pub fn init_dropped<T>() -> T;
|
||||
|
||||
/// Creates a value initialized to zero.
|
||||
///
|
||||
/// `init` is unsafe because it returns a zeroed-out datum,
|
||||
/// which is unsafe unless T is `Copy`. Also, even if T is
|
||||
/// `Copy`, an all-zero value may not correspond to any legitimate
|
||||
/// state for the type in question.
|
||||
pub fn init<T>() -> T;
|
||||
|
||||
/// Creates an uninitialized value.
|
||||
///
|
||||
/// `uninit` is unsafe because there is no guarantee of what its
|
||||
/// contents are. In particular its drop-flag may be set to any
|
||||
/// state, which means it may claim either dropped or
|
||||
/// undropped. In the general case one must use `ptr::write` to
|
||||
/// initialize memory previous set to the result of `uninit`.
|
||||
pub fn uninit<T>() -> T;
|
||||
|
||||
/// Moves a value out of scope without running drop glue.
|
||||
pub fn forget<T>(_: T) -> ();
|
||||
|
||||
/// Unsafely transforms a value of one type into a value of another type.
|
||||
///
|
||||
/// Both types must have the same size.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::mem;
|
||||
///
|
||||
/// let array: &[u8] = unsafe { mem::transmute("Rust") };
|
||||
/// assert_eq!(array, [82, 117, 115, 116]);
|
||||
/// ```
|
||||
pub fn transmute<T, U>(e: T) -> U;
|
||||
|
||||
/// Gives the address for the return value of the enclosing function.
|
||||
///
|
||||
/// Using this intrinsic in a function that does not use an out pointer
|
||||
/// will trigger a compiler error.
|
||||
pub fn return_address() -> *const u8;
|
||||
|
||||
/// Returns `true` if the actual type given as `T` requires drop
|
||||
/// glue; returns `false` if the actual type provided for `T`
|
||||
/// implements `Copy`.
|
||||
///
|
||||
/// If the actual type neither requires drop glue nor implements
|
||||
/// `Copy`, then may return `true` or `false`.
|
||||
pub fn needs_drop<T>() -> bool;
|
||||
|
||||
/// Calculates the offset from a pointer.
|
||||
///
|
||||
/// This is implemented as an intrinsic to avoid converting to and from an
|
||||
/// integer, since the conversion would throw away aliasing information.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Both the starting and resulting pointer must be either in bounds or one
|
||||
/// byte past the end of an allocated object. If either pointer is out of
|
||||
/// bounds or arithmetic overflow occurs then any further use of the
|
||||
/// returned value will result in undefined behavior.
|
||||
pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
|
||||
|
||||
/// Calculates the offset from a pointer, potentially wrapping.
|
||||
///
|
||||
/// This is implemented as an intrinsic to avoid converting to and from an
|
||||
/// integer, since the conversion inhibits certain optimizations.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Unlike the `offset` intrinsic, this intrinsic does not restrict the
|
||||
/// resulting pointer to point into or one byte past the end of an allocated
|
||||
/// object, and it wraps with two's complement arithmetic. The resulting
|
||||
/// value is not necessarily valid to be used to actually access memory.
|
||||
pub fn arith_offset<T>(dst: *const T, offset: isize) -> *const T;
|
||||
|
||||
/// Copies `count * size_of<T>` bytes from `src` to `dst`. The source
|
||||
/// and destination may *not* overlap.
|
||||
///
|
||||
/// `copy_nonoverlapping` is semantically equivalent to C's `memcpy`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Beyond requiring that the program must be allowed to access both regions
|
||||
/// of memory, it is Undefined Behavior for source and destination to
|
||||
/// overlap. Care must also be taken with the ownership of `src` and
|
||||
/// `dst`. This method semantically moves the values of `src` into `dst`.
|
||||
/// However it does not drop the contents of `dst`, or prevent the contents
|
||||
/// of `src` from being dropped or used.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// A safe swap function:
|
||||
///
|
||||
/// ```
|
||||
/// use std::mem;
|
||||
/// use std::ptr;
|
||||
///
|
||||
/// # #[allow(dead_code)]
|
||||
/// fn swap<T>(x: &mut T, y: &mut T) {
|
||||
/// unsafe {
|
||||
/// // Give ourselves some scratch space to work with
|
||||
/// let mut t: T = mem::uninitialized();
|
||||
///
|
||||
/// // Perform the swap, `&mut` pointers never alias
|
||||
/// ptr::copy_nonoverlapping(x, &mut t, 1);
|
||||
/// ptr::copy_nonoverlapping(y, x, 1);
|
||||
/// ptr::copy_nonoverlapping(&t, y, 1);
|
||||
///
|
||||
/// // y and t now point to the same thing, but we need to completely forget `tmp`
|
||||
/// // because it's no longer relevant.
|
||||
/// mem::forget(t);
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
|
||||
|
||||
/// Copies `count * size_of<T>` bytes from `src` to `dst`. The source
|
||||
/// and destination may overlap.
|
||||
///
|
||||
/// `copy` is semantically equivalent to C's `memmove`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Care must be taken with the ownership of `src` and `dst`.
|
||||
/// This method semantically moves the values of `src` into `dst`.
|
||||
/// However it does not drop the contents of `dst`, or prevent the contents of `src`
|
||||
/// from being dropped or used.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Efficiently create a Rust vector from an unsafe buffer:
|
||||
///
|
||||
/// ```
|
||||
/// use std::ptr;
|
||||
///
|
||||
/// # #[allow(dead_code)]
|
||||
/// unsafe fn from_buf_raw<T>(ptr: *const T, elts: usize) -> Vec<T> {
|
||||
/// let mut dst = Vec::with_capacity(elts);
|
||||
/// dst.set_len(elts);
|
||||
/// ptr::copy(ptr, dst.as_mut_ptr(), elts);
|
||||
/// dst
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
pub fn copy<T>(src: *const T, dst: *mut T, count: usize);
|
||||
|
||||
/// Invokes memset on the specified pointer, setting `count * size_of::<T>()`
|
||||
/// bytes of memory starting at `dst` to `val`.
|
||||
pub fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
|
||||
|
||||
/// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with
|
||||
/// a size of `count` * `size_of::<T>()` and an alignment of
|
||||
/// `min_align_of::<T>()`
|
||||
///
|
||||
/// The volatile parameter is set to `true`, so it will not be optimized out.
|
||||
pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T,
|
||||
count: usize);
|
||||
/// Equivalent to the appropriate `llvm.memmove.p0i8.0i8.*` intrinsic, with
|
||||
/// a size of `count` * `size_of::<T>()` and an alignment of
|
||||
/// `min_align_of::<T>()`
|
||||
///
|
||||
/// The volatile parameter is set to `true`, so it will not be optimized out.
|
||||
pub fn volatile_copy_memory<T>(dst: *mut T, src: *const T, count: usize);
|
||||
/// Equivalent to the appropriate `llvm.memset.p0i8.*` intrinsic, with a
|
||||
/// size of `count` * `size_of::<T>()` and an alignment of
|
||||
/// `min_align_of::<T>()`.
|
||||
///
|
||||
/// The volatile parameter is set to `true`, so it will not be optimized out.
|
||||
pub fn volatile_set_memory<T>(dst: *mut T, val: u8, count: usize);
|
||||
|
||||
/// Perform a volatile load from the `src` pointer.
|
||||
pub fn volatile_load<T>(src: *const T) -> T;
|
||||
/// Perform a volatile store to the `dst` pointer.
|
||||
pub fn volatile_store<T>(dst: *mut T, val: T);
|
||||
|
||||
/// Returns the square root of an `f32`
|
||||
pub fn sqrtf32(x: f32) -> f32;
|
||||
/// Returns the square root of an `f64`
|
||||
pub fn sqrtf64(x: f64) -> f64;
|
||||
|
||||
/// Raises an `f32` to an integer power.
|
||||
pub fn powif32(a: f32, x: i32) -> f32;
|
||||
/// Raises an `f64` to an integer power.
|
||||
pub fn powif64(a: f64, x: i32) -> f64;
|
||||
|
||||
/// Returns the sine of an `f32`.
|
||||
pub fn sinf32(x: f32) -> f32;
|
||||
/// Returns the sine of an `f64`.
|
||||
pub fn sinf64(x: f64) -> f64;
|
||||
|
||||
/// Returns the cosine of an `f32`.
|
||||
pub fn cosf32(x: f32) -> f32;
|
||||
/// Returns the cosine of an `f64`.
|
||||
pub fn cosf64(x: f64) -> f64;
|
||||
|
||||
/// Raises an `f32` to an `f32` power.
|
||||
pub fn powf32(a: f32, x: f32) -> f32;
|
||||
/// Raises an `f64` to an `f64` power.
|
||||
pub fn powf64(a: f64, x: f64) -> f64;
|
||||
|
||||
/// Returns the exponential of an `f32`.
|
||||
pub fn expf32(x: f32) -> f32;
|
||||
/// Returns the exponential of an `f64`.
|
||||
pub fn expf64(x: f64) -> f64;
|
||||
|
||||
/// Returns 2 raised to the power of an `f32`.
|
||||
pub fn exp2f32(x: f32) -> f32;
|
||||
/// Returns 2 raised to the power of an `f64`.
|
||||
pub fn exp2f64(x: f64) -> f64;
|
||||
|
||||
/// Returns the natural logarithm of an `f32`.
|
||||
pub fn logf32(x: f32) -> f32;
|
||||
/// Returns the natural logarithm of an `f64`.
|
||||
pub fn logf64(x: f64) -> f64;
|
||||
|
||||
/// Returns the base 10 logarithm of an `f32`.
|
||||
pub fn log10f32(x: f32) -> f32;
|
||||
/// Returns the base 10 logarithm of an `f64`.
|
||||
pub fn log10f64(x: f64) -> f64;
|
||||
|
||||
/// Returns the base 2 logarithm of an `f32`.
|
||||
pub fn log2f32(x: f32) -> f32;
|
||||
/// Returns the base 2 logarithm of an `f64`.
|
||||
pub fn log2f64(x: f64) -> f64;
|
||||
|
||||
/// Returns `a * b + c` for `f32` values.
|
||||
pub fn fmaf32(a: f32, b: f32, c: f32) -> f32;
|
||||
/// Returns `a * b + c` for `f64` values.
|
||||
pub fn fmaf64(a: f64, b: f64, c: f64) -> f64;
|
||||
|
||||
/// Returns the absolute value of an `f32`.
|
||||
pub fn fabsf32(x: f32) -> f32;
|
||||
/// Returns the absolute value of an `f64`.
|
||||
pub fn fabsf64(x: f64) -> f64;
|
||||
|
||||
/// Copies the sign from `y` to `x` for `f32` values.
|
||||
pub fn copysignf32(x: f32, y: f32) -> f32;
|
||||
/// Copies the sign from `y` to `x` for `f64` values.
|
||||
pub fn copysignf64(x: f64, y: f64) -> f64;
|
||||
|
||||
/// Returns the largest integer less than or equal to an `f32`.
|
||||
pub fn floorf32(x: f32) -> f32;
|
||||
/// Returns the largest integer less than or equal to an `f64`.
|
||||
pub fn floorf64(x: f64) -> f64;
|
||||
|
||||
/// Returns the smallest integer greater than or equal to an `f32`.
|
||||
pub fn ceilf32(x: f32) -> f32;
|
||||
/// Returns the smallest integer greater than or equal to an `f64`.
|
||||
pub fn ceilf64(x: f64) -> f64;
|
||||
|
||||
/// Returns the integer part of an `f32`.
|
||||
pub fn truncf32(x: f32) -> f32;
|
||||
/// Returns the integer part of an `f64`.
|
||||
pub fn truncf64(x: f64) -> f64;
|
||||
|
||||
/// Returns the nearest integer to an `f32`. May raise an inexact floating-point exception
|
||||
/// if the argument is not an integer.
|
||||
pub fn rintf32(x: f32) -> f32;
|
||||
/// Returns the nearest integer to an `f64`. May raise an inexact floating-point exception
|
||||
/// if the argument is not an integer.
|
||||
pub fn rintf64(x: f64) -> f64;
|
||||
|
||||
/// Returns the nearest integer to an `f32`.
|
||||
pub fn nearbyintf32(x: f32) -> f32;
|
||||
/// Returns the nearest integer to an `f64`.
|
||||
pub fn nearbyintf64(x: f64) -> f64;
|
||||
|
||||
/// Returns the nearest integer to an `f32`. Rounds half-way cases away from zero.
|
||||
pub fn roundf32(x: f32) -> f32;
|
||||
/// Returns the nearest integer to an `f64`. Rounds half-way cases away from zero.
|
||||
pub fn roundf64(x: f64) -> f64;
|
||||
|
||||
/// Float addition that allows optimizations based on algebraic rules.
|
||||
/// May assume inputs are finite.
|
||||
pub fn fadd_fast<T>(a: T, b: T) -> T;
|
||||
|
||||
/// Float subtraction that allows optimizations based on algebraic rules.
|
||||
/// May assume inputs are finite.
|
||||
pub fn fsub_fast<T>(a: T, b: T) -> T;
|
||||
|
||||
/// Float multiplication that allows optimizations based on algebraic rules.
|
||||
/// May assume inputs are finite.
|
||||
pub fn fmul_fast<T>(a: T, b: T) -> T;
|
||||
|
||||
/// Float division that allows optimizations based on algebraic rules.
|
||||
/// May assume inputs are finite.
|
||||
pub fn fdiv_fast<T>(a: T, b: T) -> T;
|
||||
|
||||
/// Float remainder that allows optimizations based on algebraic rules.
|
||||
/// May assume inputs are finite.
|
||||
pub fn frem_fast<T>(a: T, b: T) -> T;
|
||||
|
||||
|
||||
/// Returns the number of bits set in an integer type `T`
|
||||
pub fn ctpop<T>(x: T) -> T;
|
||||
|
||||
/// Returns the number of leading bits unset in an integer type `T`
|
||||
pub fn ctlz<T>(x: T) -> T;
|
||||
|
||||
/// Returns the number of trailing bits unset in an integer type `T`
|
||||
pub fn cttz<T>(x: T) -> T;
|
||||
|
||||
/// Reverses the bytes in an integer type `T`.
|
||||
pub fn bswap<T>(x: T) -> T;
|
||||
|
||||
/// Performs checked integer addition.
|
||||
pub fn add_with_overflow<T>(x: T, y: T) -> (T, bool);
|
||||
|
||||
/// Performs checked integer subtraction
|
||||
pub fn sub_with_overflow<T>(x: T, y: T) -> (T, bool);
|
||||
|
||||
/// Performs checked integer multiplication
|
||||
pub fn mul_with_overflow<T>(x: T, y: T) -> (T, bool);
|
||||
|
||||
/// Performs an unchecked division, resulting in undefined behavior
|
||||
/// where y = 0 or x = `T::min_value()` and y = -1
|
||||
pub fn unchecked_div<T>(x: T, y: T) -> T;
|
||||
/// Returns the remainder of an unchecked division, resulting in
|
||||
/// undefined behavior where y = 0 or x = `T::min_value()` and y = -1
|
||||
pub fn unchecked_rem<T>(x: T, y: T) -> T;
|
||||
|
||||
/// Returns (a + b) mod 2^N, where N is the width of T in bits.
|
||||
pub fn overflowing_add<T>(a: T, b: T) -> T;
|
||||
/// Returns (a - b) mod 2^N, where N is the width of T in bits.
|
||||
pub fn overflowing_sub<T>(a: T, b: T) -> T;
|
||||
/// Returns (a * b) mod 2^N, where N is the width of T in bits.
|
||||
pub fn overflowing_mul<T>(a: T, b: T) -> T;
|
||||
|
||||
/// Returns the value of the discriminant for the variant in 'v',
|
||||
/// cast to a `u64`; if `T` has no discriminant, returns 0.
|
||||
pub fn discriminant_value<T>(v: &T) -> u64;
|
||||
|
||||
/// Rust's "try catch" construct which invokes the function pointer `f` with
|
||||
/// the data pointer `data`.
|
||||
///
|
||||
/// The third pointer is a target-specific data pointer which is filled in
|
||||
/// with the specifics of the exception that occurred. For examples on Unix
|
||||
/// platforms this is a `*mut *mut T` which is filled in by the compiler and
|
||||
/// on MSVC it's `*mut [usize; 2]`. For more information see the compiler's
|
||||
/// source as well as std's catch implementation.
|
||||
pub fn try(f: fn(*mut u8), data: *mut u8, local_ptr: *mut u8) -> i32;
|
||||
}
|
||||
32
avr-core/src/lib.rs
Normal file
32
avr-core/src/lib.rs
Normal file
@@ -0,0 +1,32 @@
|
||||
#![feature(no_core)]
|
||||
#![feature(lang_items)]
|
||||
#![feature(fundamental)]
|
||||
#![feature(intrinsics)]
|
||||
#![feature(on_unimplemented)]
|
||||
#![feature(optin_builtin_traits)]
|
||||
#![feature(reflect)]
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(associated_type_defaults)]
|
||||
|
||||
#![no_core]
|
||||
|
||||
pub mod prelude {
|
||||
pub use option::Option::*;
|
||||
pub use ops::*;
|
||||
}
|
||||
|
||||
#[lang = "eh_personality"]
|
||||
extern fn eh_personality() {}
|
||||
|
||||
#[lang = "panic"]
|
||||
pub fn panic(expr_file_line: &(&'static str, &'static str, u32)) -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
// All this is copied from libcore
|
||||
pub mod option;
|
||||
pub mod intrinsics;
|
||||
pub mod clone;
|
||||
pub mod cmp;
|
||||
pub mod marker;
|
||||
pub mod ops;
|
||||
434
avr-core/src/marker.rs
Normal file
434
avr-core/src/marker.rs
Normal file
@@ -0,0 +1,434 @@
|
||||
// Copyright 2012-2015 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.
|
||||
|
||||
//! Primitive traits and marker types representing basic 'kinds' of types.
|
||||
//!
|
||||
//! Rust types can be classified in various useful ways according to
|
||||
//! intrinsic properties of the type. These classifications, often called
|
||||
//! 'kinds', are represented as traits.
|
||||
|
||||
|
||||
use clone::Clone;
|
||||
use cmp;
|
||||
//use default::Default;
|
||||
use option::Option;
|
||||
// use hash::Hash;
|
||||
// use hash::Hasher;
|
||||
|
||||
/// Types that can be transferred across thread boundaries.
|
||||
///
|
||||
/// This trait is automatically derived when the compiler determines it's appropriate.
|
||||
#[lang = "send"]
|
||||
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
|
||||
pub unsafe trait Send {
|
||||
// empty.
|
||||
}
|
||||
|
||||
unsafe impl Send for .. { }
|
||||
|
||||
impl<T: ?Sized> !Send for *const T { }
|
||||
impl<T: ?Sized> !Send for *mut T { }
|
||||
|
||||
/// Types with a constant size known at compile-time.
|
||||
///
|
||||
/// All type parameters which can be bounded have an implicit bound of `Sized`. The special syntax
|
||||
/// `?Sized` can be used to remove this bound if it is not appropriate.
|
||||
///
|
||||
/// ```
|
||||
/// # #![allow(dead_code)]
|
||||
/// struct Foo<T>(T);
|
||||
/// struct Bar<T: ?Sized>(T);
|
||||
///
|
||||
/// // struct FooUse(Foo<[i32]>); // error: Sized is not implemented for [i32]
|
||||
/// struct BarUse(Bar<[i32]>); // OK
|
||||
/// ```
|
||||
#[lang = "sized"]
|
||||
#[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"]
|
||||
#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
|
||||
pub trait Sized {
|
||||
// Empty.
|
||||
}
|
||||
|
||||
/// Types that can be "unsized" to a dynamically sized type.
|
||||
#[lang="unsize"]
|
||||
pub trait Unsize<T: ?Sized> {
|
||||
// Empty.
|
||||
}
|
||||
|
||||
/// Types that can be copied by simply copying bits (i.e. `memcpy`).
|
||||
///
|
||||
/// By default, variable bindings have 'move semantics.' In other
|
||||
/// words:
|
||||
///
|
||||
/// ```
|
||||
/// #[derive(Debug)]
|
||||
/// struct Foo;
|
||||
///
|
||||
/// let x = Foo;
|
||||
///
|
||||
/// let y = x;
|
||||
///
|
||||
/// // `x` has moved into `y`, and so cannot be used
|
||||
///
|
||||
/// // println!("{:?}", x); // error: use of moved value
|
||||
/// ```
|
||||
///
|
||||
/// However, if a type implements `Copy`, it instead has 'copy semantics':
|
||||
///
|
||||
/// ```
|
||||
/// // we can just derive a `Copy` implementation
|
||||
/// #[derive(Debug, Copy, Clone)]
|
||||
/// struct Foo;
|
||||
///
|
||||
/// let x = Foo;
|
||||
///
|
||||
/// let y = x;
|
||||
///
|
||||
/// // `y` is a copy of `x`
|
||||
///
|
||||
/// println!("{:?}", x); // A-OK!
|
||||
/// ```
|
||||
///
|
||||
/// It's important to note that in these two examples, the only difference is if you are allowed to
|
||||
/// access `x` after the assignment: a move is also a bitwise copy under the hood.
|
||||
///
|
||||
/// ## When can my type be `Copy`?
|
||||
///
|
||||
/// A type can implement `Copy` if all of its components implement `Copy`. For example, this
|
||||
/// `struct` can be `Copy`:
|
||||
///
|
||||
/// ```
|
||||
/// # #[allow(dead_code)]
|
||||
/// struct Point {
|
||||
/// x: i32,
|
||||
/// y: i32,
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// A `struct` can be `Copy`, and `i32` is `Copy`, so therefore, `Point` is eligible to be `Copy`.
|
||||
///
|
||||
/// ```
|
||||
/// # #![allow(dead_code)]
|
||||
/// # struct Point;
|
||||
/// struct PointList {
|
||||
/// points: Vec<Point>,
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// The `PointList` `struct` cannot implement `Copy`, because `Vec<T>` is not `Copy`. If we
|
||||
/// attempt to derive a `Copy` implementation, we'll get an error:
|
||||
///
|
||||
/// ```text
|
||||
/// the trait `Copy` may not be implemented for this type; field `points` does not implement `Copy`
|
||||
/// ```
|
||||
///
|
||||
/// ## How can I implement `Copy`?
|
||||
///
|
||||
/// There are two ways to implement `Copy` on your type:
|
||||
///
|
||||
/// ```
|
||||
/// #[derive(Copy, Clone)]
|
||||
/// struct MyStruct;
|
||||
/// ```
|
||||
///
|
||||
/// and
|
||||
///
|
||||
/// ```
|
||||
/// struct MyStruct;
|
||||
/// impl Copy for MyStruct {}
|
||||
/// impl Clone for MyStruct { fn clone(&self) -> MyStruct { *self } }
|
||||
/// ```
|
||||
///
|
||||
/// There is a small difference between the two: the `derive` strategy will also place a `Copy`
|
||||
/// bound on type parameters, which isn't always desired.
|
||||
///
|
||||
/// ## When can my type _not_ be `Copy`?
|
||||
///
|
||||
/// Some types can't be copied safely. For example, copying `&mut T` would create an aliased
|
||||
/// mutable reference, and copying `String` would result in two attempts to free the same buffer.
|
||||
///
|
||||
/// Generalizing the latter case, any type implementing `Drop` can't be `Copy`, because it's
|
||||
/// managing some resource besides its own `size_of::<T>()` bytes.
|
||||
///
|
||||
/// ## When should my type be `Copy`?
|
||||
///
|
||||
/// Generally speaking, if your type _can_ implement `Copy`, it should. There's one important thing
|
||||
/// to consider though: if you think your type may _not_ be able to implement `Copy` in the future,
|
||||
/// then it might be prudent to not implement `Copy`. This is because removing `Copy` is a breaking
|
||||
/// change: that second example would fail to compile if we made `Foo` non-`Copy`.
|
||||
///
|
||||
/// # Derivable
|
||||
///
|
||||
/// This trait can be used with `#[derive]`.
|
||||
#[lang = "copy"]
|
||||
pub trait Copy : Clone {
|
||||
// Empty.
|
||||
}
|
||||
|
||||
/// Types that can be safely shared between threads when aliased.
|
||||
///
|
||||
/// The precise definition is: a type `T` is `Sync` if `&T` is
|
||||
/// thread-safe. In other words, there is no possibility of data races
|
||||
/// when passing `&T` references between threads.
|
||||
///
|
||||
/// As one would expect, primitive types like `u8` and `f64` are all
|
||||
/// `Sync`, and so are simple aggregate types containing them (like
|
||||
/// tuples, structs and enums). More instances of basic `Sync` types
|
||||
/// include "immutable" types like `&T` and those with simple
|
||||
/// inherited mutability, such as `Box<T>`, `Vec<T>` and most other
|
||||
/// collection types. (Generic parameters need to be `Sync` for their
|
||||
/// container to be `Sync`.)
|
||||
///
|
||||
/// A somewhat surprising consequence of the definition is `&mut T` is
|
||||
/// `Sync` (if `T` is `Sync`) even though it seems that it might
|
||||
/// provide unsynchronized mutation. The trick is a mutable reference
|
||||
/// stored in an aliasable reference (that is, `& &mut T`) becomes
|
||||
/// read-only, as if it were a `& &T`, hence there is no risk of a data
|
||||
/// race.
|
||||
///
|
||||
/// Types that are not `Sync` are those that have "interior
|
||||
/// mutability" in a non-thread-safe way, such as `Cell` and `RefCell`
|
||||
/// in `std::cell`. These types allow for mutation of their contents
|
||||
/// even when in an immutable, aliasable slot, e.g. the contents of
|
||||
/// `&Cell<T>` can be `.set`, and do not ensure data races are
|
||||
/// impossible, hence they cannot be `Sync`. A higher level example
|
||||
/// of a non-`Sync` type is the reference counted pointer
|
||||
/// `std::rc::Rc`, because any reference `&Rc<T>` can clone a new
|
||||
/// reference, which modifies the reference counts in a non-atomic
|
||||
/// way.
|
||||
///
|
||||
/// For cases when one does need thread-safe interior mutability,
|
||||
/// types like the atomics in `std::sync` and `Mutex` & `RWLock` in
|
||||
/// the `sync` crate do ensure that any mutation cannot cause data
|
||||
/// races. Hence these types are `Sync`.
|
||||
///
|
||||
/// Any types with interior mutability must also use the `std::cell::UnsafeCell`
|
||||
/// wrapper around the value(s) which can be mutated when behind a `&`
|
||||
/// reference; not doing this is undefined behavior (for example,
|
||||
/// `transmute`-ing from `&T` to `&mut T` is invalid).
|
||||
///
|
||||
/// This trait is automatically derived when the compiler determines it's appropriate.
|
||||
#[lang = "sync"]
|
||||
#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
|
||||
pub unsafe trait Sync {
|
||||
// Empty
|
||||
}
|
||||
|
||||
unsafe impl Sync for .. { }
|
||||
|
||||
impl<T: ?Sized> !Sync for *const T { }
|
||||
impl<T: ?Sized> !Sync for *mut T { }
|
||||
|
||||
macro_rules! impls{
|
||||
($t: ident) => (
|
||||
// impl<T:?Sized> Hash for $t<T> {
|
||||
// #[inline]
|
||||
// fn hash<H: Hasher>(&self, _: &mut H) {
|
||||
// }
|
||||
// }
|
||||
|
||||
impl<T:?Sized> cmp::PartialEq for $t<T> {
|
||||
fn eq(&self, _other: &$t<T>) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl<T:?Sized> cmp::Eq for $t<T> {
|
||||
}
|
||||
|
||||
impl<T:?Sized> cmp::PartialOrd for $t<T> {
|
||||
fn partial_cmp(&self, _other: &$t<T>) -> Option<cmp::Ordering> {
|
||||
Option::Some(cmp::Ordering::Equal)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T:?Sized> cmp::Ord for $t<T> {
|
||||
fn cmp(&self, _other: &$t<T>) -> cmp::Ordering {
|
||||
cmp::Ordering::Equal
|
||||
}
|
||||
}
|
||||
|
||||
impl<T:?Sized> Copy for $t<T> { }
|
||||
|
||||
impl<T:?Sized> Clone for $t<T> {
|
||||
fn clone(&self) -> $t<T> {
|
||||
$t
|
||||
}
|
||||
}
|
||||
|
||||
// impl<T:?Sized> Default for $t<T> {
|
||||
// fn default() -> $t<T> {
|
||||
// $t
|
||||
// }
|
||||
// }
|
||||
)
|
||||
}
|
||||
|
||||
/// `PhantomData<T>` allows you to describe that a type acts as if it stores a value of type `T`,
|
||||
/// even though it does not. This allows you to inform the compiler about certain safety properties
|
||||
/// of your code.
|
||||
///
|
||||
/// For a more in-depth explanation of how to use `PhantomData<T>`, please see [the Nomicon].
|
||||
///
|
||||
/// [the Nomicon]: ../../nomicon/phantom-data.html
|
||||
///
|
||||
/// # A ghastly note 👻👻👻
|
||||
///
|
||||
/// Though they both have scary names, `PhantomData<T>` and 'phantom types' are related, but not
|
||||
/// identical. Phantom types are a more general concept that don't require `PhantomData<T>` to
|
||||
/// implement, but `PhantomData<T>` is the most common way to implement them in a correct manner.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ## Unused lifetime parameter
|
||||
///
|
||||
/// Perhaps the most common time that `PhantomData` is required is
|
||||
/// with a struct that has an unused lifetime parameter, typically as
|
||||
/// part of some unsafe code. For example, here is a struct `Slice`
|
||||
/// that has two pointers of type `*const T`, presumably pointing into
|
||||
/// an array somewhere:
|
||||
///
|
||||
/// ```ignore
|
||||
/// struct Slice<'a, T> {
|
||||
/// start: *const T,
|
||||
/// end: *const T,
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// The intention is that the underlying data is only valid for the
|
||||
/// lifetime `'a`, so `Slice` should not outlive `'a`. However, this
|
||||
/// intent is not expressed in the code, since there are no uses of
|
||||
/// the lifetime `'a` and hence it is not clear what data it applies
|
||||
/// to. We can correct this by telling the compiler to act *as if* the
|
||||
/// `Slice` struct contained a borrowed reference `&'a T`:
|
||||
///
|
||||
/// ```
|
||||
/// use std::marker::PhantomData;
|
||||
///
|
||||
/// # #[allow(dead_code)]
|
||||
/// struct Slice<'a, T:'a> {
|
||||
/// start: *const T,
|
||||
/// end: *const T,
|
||||
/// phantom: PhantomData<&'a T>
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// This also in turn requires that we annotate `T:'a`, indicating
|
||||
/// that `T` is a type that can be borrowed for the lifetime `'a`.
|
||||
///
|
||||
/// ## Unused type parameters
|
||||
///
|
||||
/// It sometimes happens that there are unused type parameters that
|
||||
/// indicate what type of data a struct is "tied" to, even though that
|
||||
/// data is not actually found in the struct itself. Here is an
|
||||
/// example where this arises when handling external resources over a
|
||||
/// foreign function interface. `PhantomData<T>` can prevent
|
||||
/// mismatches by enforcing types in the method implementations:
|
||||
///
|
||||
/// ```
|
||||
/// # #![allow(dead_code)]
|
||||
/// # trait ResType { fn foo(&self); }
|
||||
/// # struct ParamType;
|
||||
/// # mod foreign_lib {
|
||||
/// # pub fn new(_: usize) -> *mut () { 42 as *mut () }
|
||||
/// # pub fn do_stuff(_: *mut (), _: usize) {}
|
||||
/// # }
|
||||
/// # fn convert_params(_: ParamType) -> usize { 42 }
|
||||
/// use std::marker::PhantomData;
|
||||
/// use std::mem;
|
||||
///
|
||||
/// struct ExternalResource<R> {
|
||||
/// resource_handle: *mut (),
|
||||
/// resource_type: PhantomData<R>,
|
||||
/// }
|
||||
///
|
||||
/// impl<R: ResType> ExternalResource<R> {
|
||||
/// fn new() -> ExternalResource<R> {
|
||||
/// let size_of_res = mem::size_of::<R>();
|
||||
/// ExternalResource {
|
||||
/// resource_handle: foreign_lib::new(size_of_res),
|
||||
/// resource_type: PhantomData,
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn do_stuff(&self, param: ParamType) {
|
||||
/// let foreign_params = convert_params(param);
|
||||
/// foreign_lib::do_stuff(self.resource_handle, foreign_params);
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ## Indicating ownership
|
||||
///
|
||||
/// Adding a field of type `PhantomData<T>` also indicates that your
|
||||
/// struct owns data of type `T`. This in turn implies that when your
|
||||
/// struct is dropped, it may in turn drop one or more instances of
|
||||
/// the type `T`, though that may not be apparent from the other
|
||||
/// structure of the type itself. This is commonly necessary if the
|
||||
/// structure is using a raw pointer like `*mut T` whose referent
|
||||
/// may be dropped when the type is dropped, as a `*mut T` is
|
||||
/// otherwise not treated as owned.
|
||||
///
|
||||
/// If your struct does not in fact *own* the data of type `T`, it is
|
||||
/// better to use a reference type, like `PhantomData<&'a T>`
|
||||
/// (ideally) or `PhantomData<*const T>` (if no lifetime applies), so
|
||||
/// as not to indicate ownership.
|
||||
#[lang = "phantom_data"]
|
||||
pub struct PhantomData<T:?Sized>;
|
||||
|
||||
impls! { PhantomData }
|
||||
|
||||
mod impls {
|
||||
use super::{Send, Sync, Sized};
|
||||
|
||||
unsafe impl<'a, T: Sync + ?Sized> Send for &'a T {}
|
||||
unsafe impl<'a, T: Send + ?Sized> Send for &'a mut T {}
|
||||
}
|
||||
|
||||
/// Types that can be reflected over.
|
||||
///
|
||||
/// This trait is implemented for all types. Its purpose is to ensure
|
||||
/// that when you write a generic function that will employ
|
||||
/// reflection, that must be reflected (no pun intended) in the
|
||||
/// generic bounds of that function. Here is an example:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(reflect_marker)]
|
||||
/// use std::marker::Reflect;
|
||||
/// use std::any::Any;
|
||||
///
|
||||
/// # #[allow(dead_code)]
|
||||
/// fn foo<T:Reflect+'static>(x: &T) {
|
||||
/// let any: &Any = x;
|
||||
/// if any.is::<u32>() { println!("u32"); }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Without the declaration `T:Reflect`, `foo` would not type check
|
||||
/// (note: as a matter of style, it would be preferable to write
|
||||
/// `T:Any`, because `T:Any` implies `T:Reflect` and `T:'static`, but
|
||||
/// we use `Reflect` here to show how it works). The `Reflect` bound
|
||||
/// thus serves to alert `foo`'s caller to the fact that `foo` may
|
||||
/// behave differently depending on whether `T=u32` or not. In
|
||||
/// particular, thanks to the `Reflect` bound, callers know that a
|
||||
/// function declared like `fn bar<T>(...)` will always act in
|
||||
/// precisely the same way no matter what type `T` is supplied,
|
||||
/// because there are no bounds declared on `T`. (The ability for a
|
||||
/// caller to reason about what a function may do based solely on what
|
||||
/// generic bounds are declared is often called the ["parametricity
|
||||
/// property"][1].)
|
||||
///
|
||||
/// [1]: http://en.wikipedia.org/wiki/Parametricity
|
||||
#[rustc_reflect_like]
|
||||
#[rustc_on_unimplemented = "`{Self}` does not implement `Any`; \
|
||||
ensure all type parameters are bounded by `Any`"]
|
||||
pub trait Reflect {}
|
||||
|
||||
impl Reflect for .. { }
|
||||
1724
avr-core/src/ops.rs
Normal file
1724
avr-core/src/ops.rs
Normal file
File diff suppressed because it is too large
Load Diff
7
avr-core/src/option.rs
Normal file
7
avr-core/src/option.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord)]
|
||||
pub enum Option<T> {
|
||||
/// No value
|
||||
None,
|
||||
/// Some value `T`
|
||||
Some(T)
|
||||
}
|
||||
2
blink/.gitignore
vendored
Normal file
2
blink/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
target/
|
||||
blink.hex
|
||||
11
blink/Cargo.lock
generated
Normal file
11
blink/Cargo.lock
generated
Normal file
@@ -0,0 +1,11 @@
|
||||
[root]
|
||||
name = "blink"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"avr-core 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "avr-core"
|
||||
version = "0.1.0"
|
||||
|
||||
7
blink/Cargo.toml
Normal file
7
blink/Cargo.toml
Normal file
@@ -0,0 +1,7 @@
|
||||
[package]
|
||||
name = "blink"
|
||||
version = "0.1.0"
|
||||
authors = ["Jake Goulding <jake.goulding@gmail.com>"]
|
||||
|
||||
[dependencies.avr-core]
|
||||
path = "../avr-core"
|
||||
17
blink/Makefile
Normal file
17
blink/Makefile
Normal file
@@ -0,0 +1,17 @@
|
||||
COMPILED:=target/arduino/release/blink.elf
|
||||
HEX:=blink.hex
|
||||
|
||||
all: ${HEX}
|
||||
|
||||
.PHONY: ${COMPILED}
|
||||
${COMPILED}:
|
||||
cargo build --release --target=./arduino.json
|
||||
|
||||
# Convert binary to an Intel HEX file for upload
|
||||
${HEX}: ${COMPILED}
|
||||
avr-objcopy -O ihex -R .eeprom $< $@
|
||||
|
||||
# Download the HEX to the board
|
||||
.PHONY: program
|
||||
program: ${HEX}
|
||||
avrdude -p atmega328p -c arduino -P /dev/cu.usbmodem1411 -U flash:w:$<:i
|
||||
19
blink/arduino.json
Normal file
19
blink/arduino.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"llvm-target": "avr-atmel-none",
|
||||
"target-endian": "little",
|
||||
"target-pointer-width": "16",
|
||||
"os": "none",
|
||||
"target-env": "gnu",
|
||||
"target-vendor": "unknown",
|
||||
"arch": "avr",
|
||||
"data-layout": "e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8-i64:8:8-f32:8:8-f64:8:8-n8",
|
||||
|
||||
"executables": true,
|
||||
|
||||
"linker": "avr-gcc",
|
||||
"pre-link-args": ["-mmcu=atmega328p", "-nostartfiles", "../interrupt_vector.S"],
|
||||
"exe-suffix": ".elf",
|
||||
"post-link-args": ["-Wl,--no-gc-sections"],
|
||||
|
||||
"no-compiler-rt": true
|
||||
}
|
||||
109
blink/src/main.rs
Normal file
109
blink/src/main.rs
Normal file
@@ -0,0 +1,109 @@
|
||||
#![feature(no_core)]
|
||||
#![feature(asm)]
|
||||
|
||||
#![no_core]
|
||||
#![no_main]
|
||||
|
||||
extern crate avr_core;
|
||||
|
||||
use avr_core::prelude::*;
|
||||
use avr_core::intrinsics::{volatile_load, volatile_store};
|
||||
use avr_core::marker::PhantomData;
|
||||
|
||||
pub mod avr {
|
||||
pub const DDRB: *mut u8 = 0x24 as *mut u8;
|
||||
pub const PORTB: *mut u8 = 0x25 as *mut u8;
|
||||
|
||||
pub const TCCR0A: *mut u8 = 0x44 as *mut u8;
|
||||
pub const TCCR0B: *mut u8 = 0x45 as *mut u8;
|
||||
pub const TCNT0: *mut u8 = 0x46 as *mut u8;
|
||||
pub const OCR0A: *mut u8 = 0x47 as *mut u8;
|
||||
pub const TIMSK0: *mut u8 = 0x6E as *mut u8;
|
||||
|
||||
pub const TCCR1A: *mut u8 = 0x80 as *mut u8;
|
||||
pub const TCCR1B: *mut u8 = 0x81 as *mut u8;
|
||||
pub const TCCR1L: *mut u8 = 0x84 as *mut u8;
|
||||
pub const TCCR1H: *mut u8 = 0x85 as *mut u8;
|
||||
pub const OCR1AL: *mut u8 = 0x88 as *mut u8;
|
||||
pub const OCR1AH: *mut u8 = 0x89 as *mut u8;
|
||||
|
||||
pub const TCNT1L: *mut u8 = 0x84 as *mut u8;
|
||||
pub const TCNT1H: *mut u8 = 0x85 as *mut u8;
|
||||
|
||||
pub const TIMSK1: *mut u8 = 0x6F as *mut u8;
|
||||
|
||||
// Should pins be represented in this way?
|
||||
pub const PINB5: u8 = 0b0010_0000;
|
||||
|
||||
pub const WGM12: u8 = 0b0000_1000;
|
||||
pub const CS12: u8 = 0b0000_0100;
|
||||
pub const CS10: u8 = 0b0000_0001;
|
||||
pub const OCIE1A: u8 = 0b0000_0010;
|
||||
}
|
||||
|
||||
use avr::*;
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "avr-interrupt" fn _ivr_timer1_compare_a() {
|
||||
let prev_value = volatile_load(PORTB);
|
||||
volatile_store(PORTB, prev_value ^ PINB5);
|
||||
}
|
||||
|
||||
struct DisableInterrupts(PhantomData<()>);
|
||||
|
||||
impl DisableInterrupts {
|
||||
fn new() -> DisableInterrupts {
|
||||
unsafe { asm!("CLI") }
|
||||
DisableInterrupts(PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for DisableInterrupts {
|
||||
fn drop(&mut self) {
|
||||
unsafe { asm!("SEI") }
|
||||
}
|
||||
}
|
||||
|
||||
fn without_interrupts<F, T>(f: F) -> T
|
||||
where F: FnOnce() -> T
|
||||
{
|
||||
let _disabled = DisableInterrupts::new();
|
||||
f()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn main() {
|
||||
unsafe {
|
||||
without_interrupts(|| {
|
||||
// Configure all Port B pins as outputs
|
||||
volatile_store(DDRB, 0xFF);
|
||||
// Turn on all Port B pins
|
||||
volatile_store(PORTB, 0xFF);
|
||||
|
||||
// Initialize timer settings
|
||||
volatile_store(TCCR1A, 0);
|
||||
volatile_store(TCCR1B, 0);
|
||||
|
||||
// Initialize timer counter
|
||||
volatile_store(TCNT1L, 0);
|
||||
volatile_store(TCNT1H, 0);
|
||||
|
||||
// Set compare match register for 1hz increments (must be <65536)
|
||||
// (16*10^6) / (1*1024) - 1 => 15624 => 0x3D08
|
||||
volatile_store(OCR1AH, 0x3D);
|
||||
volatile_store(OCR1AL, 0x08);
|
||||
|
||||
// Configure timer
|
||||
let ctc_mode = WGM12;
|
||||
let prescaler_1024x = CS12 | CS10;
|
||||
volatile_store(TCCR1B, ctc_mode | prescaler_1024x);
|
||||
|
||||
// Enable timer compare interrupt
|
||||
volatile_store(TIMSK1, OCIE1A);
|
||||
});
|
||||
|
||||
loop {
|
||||
// forever!
|
||||
}
|
||||
}
|
||||
}
|
||||
65
interrupt_vector.S
Normal file
65
interrupt_vector.S
Normal file
@@ -0,0 +1,65 @@
|
||||
ivr:
|
||||
jmp _ivr_reset
|
||||
jmp _ivr_irq0
|
||||
jmp _ivr_irq1
|
||||
jmp _ivr_pin_change_0
|
||||
jmp _ivr_pin_change_1
|
||||
jmp _ivr_pin_change_2
|
||||
jmp _ivr_watchdog_timer
|
||||
jmp _ivr_timer2_compare_a
|
||||
jmp _ivr_timer2_compare_b
|
||||
jmp _ivr_timer2_overflow
|
||||
jmp _ivr_timer1_capture
|
||||
jmp _ivr_timer1_compare_a
|
||||
jmp _ivr_timer1_compare_b
|
||||
jmp _ivr_timer1_overflow
|
||||
jmp _ivr_timer0_compare_a
|
||||
jmp _ivr_timer0_compare_b
|
||||
jmp _ivr_timer0_overflow
|
||||
jmp _ivr_spi_transfer_complete
|
||||
jmp _ivr_usart_rx_complete
|
||||
jmp _ivr_usart_udr_empty
|
||||
jmp _ivr_usart_tx_complete
|
||||
jmp _ivr_adc_conversion_complete
|
||||
jmp _ivr_eeprom_ready
|
||||
jmp _ivr_analog_comparator
|
||||
jmp _ivr_two_wire_serial_interface
|
||||
jmp _ivr_store_program_memory_ready
|
||||
|
||||
_ivr_undefined:
|
||||
reti
|
||||
|
||||
;;; By default, start all interrupt handlers as doing a no-op
|
||||
;;; return. Since these symbols are weakly linked, user code can
|
||||
;;; override each one on demand.
|
||||
.macro _ivr_default name target=_ivr_undefined
|
||||
.weak \name
|
||||
.set \name, \target
|
||||
.endm
|
||||
|
||||
_ivr_default _ivr_reset main ; Default to `main` here, no need for indirection
|
||||
_ivr_default _ivr_irq0
|
||||
_ivr_default _ivr_irq1
|
||||
_ivr_default _ivr_pin_change_0
|
||||
_ivr_default _ivr_pin_change_1
|
||||
_ivr_default _ivr_pin_change_2
|
||||
_ivr_default _ivr_watchdog_timer
|
||||
_ivr_default _ivr_timer2_compare_a
|
||||
_ivr_default _ivr_timer2_compare_b
|
||||
_ivr_default _ivr_timer2_overflow
|
||||
_ivr_default _ivr_timer1_capture
|
||||
_ivr_default _ivr_timer1_compare_a
|
||||
_ivr_default _ivr_timer1_compare_b
|
||||
_ivr_default _ivr_timer1_overflow
|
||||
_ivr_default _ivr_timer0_compare_a
|
||||
_ivr_default _ivr_timer0_compare_b
|
||||
_ivr_default _ivr_timer0_overflow
|
||||
_ivr_default _ivr_spi_transfer_complete
|
||||
_ivr_default _ivr_usart_rx_complete
|
||||
_ivr_default _ivr_usart_udr_empty
|
||||
_ivr_default _ivr_usart_tx_complete
|
||||
_ivr_default _ivr_adc_conversion_complete
|
||||
_ivr_default _ivr_eeprom_ready
|
||||
_ivr_default _ivr_analog_comparator
|
||||
_ivr_default _ivr_two_wire_serial_interface
|
||||
_ivr_default _ivr_store_program_memory_ready
|
||||
Reference in New Issue
Block a user