This commit is contained in:
Jake Goulding
2016-05-19 14:22:50 -04:00
commit b365552c82
16 changed files with 3654 additions and 0 deletions

2
avr-core/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
Cargo.lock
target/

6
avr-core/Cargo.toml Normal file
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

7
avr-core/src/option.rs Normal file
View 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
View File

@@ -0,0 +1,2 @@
target/
blink.hex

11
blink/Cargo.lock generated Normal file
View 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
View 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
View 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
View 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
View 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
View 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