Skip to content
Permalink
Browse files

[AVR] Teach Rust about 16-bit pointers

Rust is now be able to handle 16-bit pointers.
  • Loading branch information...
Dylan McKay
Dylan McKay committed Aug 11, 2015
1 parent f9d262e commit 1b1343706d26bac4553fb01d1a1e75e1a1b0b66b
@@ -438,16 +438,16 @@ impl<T> Drop for RawVec<T> {
// * We don't overflow `usize::MAX` and actually allocate too little
//
// On 64-bit we just need to check for overflow since trying to allocate
// `> isize::MAX` bytes will surely fail. On 32-bit we need to add an extra
// guard for this in case we're running on a platform which can use all 4GB in
// user-space. e.g. PAE or x32
// `> isize::MAX` bytes will surely fail. On 32-bit and 16-bit we need to add
// an extra guard for this in case we're running on a platform which can use
// all 4GB in user-space. e.g. PAE or x32

#[inline]
#[cfg(target_pointer_width = "64")]
fn alloc_guard(_alloc_size: usize) { }

#[inline]
#[cfg(target_pointer_width = "32")]
#[cfg(any(target_pointer_width = "32", target_pointer_width = "16"))]
fn alloc_guard(alloc_size: usize) {
assert!(alloc_size <= ::core::isize::MAX as usize, "capacity overflow");
}
@@ -1341,7 +1341,9 @@ impl<T> Pointer for *const T {

if let None = f.width {
// The formats need two extra bytes, for the 0x
if cfg!(target_pointer_width = "32") {
if cfg!(target_pointer_width = "16") {
f.width = Some(5);

This comment has been minimized.

@eefriedman

eefriedman Aug 11, 2015

The correct formula here is (core::usize::BITS/4)+2 (== 6 on a 16-bit target).

This comment has been minimized.

@dylanmckay

dylanmckay Aug 12, 2015

Member

Fixed in 353ae16, thanks!

} else if cfg!(target_pointer_width = "32") {
f.width = Some(10);
} else {
f.width = Some(18);
@@ -27,6 +27,7 @@ trait Int: Zero + PartialEq + PartialOrd + Div<Output=Self> + Rem<Output=Self> +
Sub<Output=Self> + Copy {
fn from_u8(u: u8) -> Self;
fn to_u8(&self) -> u8;
fn to_u16(&self) -> u16;
fn to_u32(&self) -> u32;
fn to_u64(&self) -> u64;
}
@@ -35,6 +36,7 @@ macro_rules! doit {
($($t:ident)*) => ($(impl Int for $t {
fn from_u8(u: u8) -> $t { u as $t }
fn to_u8(&self) -> u8 { *self as u8 }
fn to_u16(&self) -> u16 { *self as u16 }
fn to_u32(&self) -> u32 { *self as u32 }
fn to_u64(&self) -> u64 { *self as u64 }
})*)
@@ -312,6 +314,8 @@ macro_rules! impl_Display {

impl_Display!(i8, u8, i16, u16, i32, u32: to_u32);
impl_Display!(i64, u64: to_u64);
#[cfg(target_pointer_width = "16")]
impl_Display!(isize, usize: to_u16);
#[cfg(target_pointer_width = "32")]
impl_Display!(isize, usize: to_u32);
#[cfg(target_pointer_width = "64")]
@@ -136,7 +136,9 @@ pub trait Hasher {
#[inline]
#[stable(feature = "hasher_write", since = "1.3.0")]
fn write_usize(&mut self, i: usize) {
if cfg!(target_pointer_width = "32") {
if cfg!(target_pointer_width = "16") {
self.write_u16(i as u16);
} else if cfg!(target_pointer_width = "32") {
self.write_u32(i as u32)
} else {
self.write_u64(i as u64)
@@ -2725,6 +2725,8 @@ step_impl_unsigned!(u64);
step_impl_signed!(i64);
#[cfg(target_pointer_width = "32")]
step_impl_no_between!(u64 i64);
#[cfg(target_pointer_width = "16")]
step_impl_no_between!(u64 i64);

/// An adapter for stepping range iterators by a custom amount.
///
@@ -490,6 +490,10 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
#[stable(feature = "rust1", since = "1.0.0")]
pub fn drop<T>(_x: T) { }

macro_rules! repeat_u8_as_u16 {
($name:expr) => { (($name as u16) << 8 |
($name as u16)) }
}
macro_rules! repeat_u8_as_u32 {
($name:expr) => { (($name as u32) << 24 |
($name as u32) << 16 |
@@ -515,11 +519,18 @@ macro_rules! repeat_u8_as_u64 {
pub const POST_DROP_U8: u8 = 0x1d;
#[unstable(feature = "filling_drop")]
#[allow(missing_docs)]
pub const POST_DROP_U16: u16 = repeat_u8_as_u16!(POST_DROP_U8);
#[unstable(feature = "filling_drop")]
#[allow(missing_docs)]
pub const POST_DROP_U32: u32 = repeat_u8_as_u32!(POST_DROP_U8);
#[unstable(feature = "filling_drop")]
#[allow(missing_docs)]
pub const POST_DROP_U64: u64 = repeat_u8_as_u64!(POST_DROP_U8);

#[cfg(target_pointer_width = "16")]
#[unstable(feature = "filling_drop")]
#[allow(missing_docs)]
pub const POST_DROP_USIZE: usize = POST_DROP_U16 as usize;
#[cfg(target_pointer_width = "32")]
#[unstable(feature = "filling_drop")]
#[allow(missing_docs)]
@@ -12,6 +12,8 @@

#![stable(feature = "rust1", since = "1.0.0")]

#[cfg(target_pointer_width = "16")]
int_module! { isize, 16 }
#[cfg(target_pointer_width = "32")]
int_module! { isize, 32 }
#[cfg(target_pointer_width = "64")]
@@ -639,6 +639,15 @@ impl i64 {
intrinsics::i64_mul_with_overflow }
}

#[cfg(target_pointer_width = "16")]
#[lang = "isize"]
impl isize {
int_impl! { i16, u16, 16,
intrinsics::i16_add_with_overflow,
intrinsics::i16_sub_with_overflow,
intrinsics::i16_mul_with_overflow }
}

#[cfg(target_pointer_width = "32")]
#[lang = "isize"]
impl isize {
@@ -1209,6 +1218,18 @@ impl u64 {
intrinsics::u64_mul_with_overflow }
}

#[cfg(target_pointer_width = "16")]
#[lang = "usize"]
impl usize {
uint_impl! { u16, 16,
intrinsics::ctpop16,
intrinsics::ctlz16,
intrinsics::cttz16,
intrinsics::bswap16,
intrinsics::u16_add_with_overflow,
intrinsics::u16_sub_with_overflow,
intrinsics::u16_mul_with_overflow }
}
#[cfg(target_pointer_width = "32")]
#[lang = "usize"]
impl usize {
@@ -402,6 +402,56 @@ impl OverflowingOps for usize {
}
}

#[cfg(target_pointer_width = "16")]
impl OverflowingOps for usize {
#[inline(always)]
fn overflowing_add(self, rhs: usize) -> (usize, bool) {
unsafe {
let res = u16_add_with_overflow(self as u16, rhs as u16);
(res.0 as usize, res.1)
}
}
#[inline(always)]
fn overflowing_sub(self, rhs: usize) -> (usize, bool) {
unsafe {
let res = u16_sub_with_overflow(self as u16, rhs as u16);
(res.0 as usize, res.1)
}
}
#[inline(always)]
fn overflowing_mul(self, rhs: usize) -> (usize, bool) {
unsafe {
let res = u16_mul_with_overflow(self as u16, rhs as u16);
(res.0 as usize, res.1)
}
}
#[inline(always)]
fn overflowing_div(self, rhs: usize) -> (usize, bool) {
let (r, f) = (self as u16).overflowing_div(rhs as u16);
(r as usize, f)
}
#[inline(always)]
fn overflowing_rem(self, rhs: usize) -> (usize, bool) {
let (r, f) = (self as u16).overflowing_rem(rhs as u16);
(r as usize, f)
}
#[inline(always)]
fn overflowing_neg(self) -> (usize, bool) {
let (r, f) = (self as u16).overflowing_neg();
(r as usize, f)
}
#[inline(always)]
fn overflowing_shl(self, rhs: u32) -> (usize, bool) {
let (r, f) = (self as u16).overflowing_shl(rhs);
(r as usize, f)
}
#[inline(always)]
fn overflowing_shr(self, rhs: u32) -> (usize, bool) {
let (r, f) = (self as u16).overflowing_shr(rhs);
(r as usize, f)
}
}

#[cfg(target_pointer_width = "64")]
impl OverflowingOps for isize {
#[inline(always)]
@@ -501,3 +551,53 @@ impl OverflowingOps for isize {
(r as isize, f)
}
}

#[cfg(target_pointer_width = "16")]
impl OverflowingOps for isize {
#[inline(always)]
fn overflowing_add(self, rhs: isize) -> (isize, bool) {
unsafe {
let res = i16_add_with_overflow(self as i16, rhs as i16);
(res.0 as isize, res.1)
}
}
#[inline(always)]
fn overflowing_sub(self, rhs: isize) -> (isize, bool) {
unsafe {
let res = i16_sub_with_overflow(self as i16, rhs as i16);
(res.0 as isize, res.1)
}
}
#[inline(always)]
fn overflowing_mul(self, rhs: isize) -> (isize, bool) {
unsafe {
let res = i16_mul_with_overflow(self as i16, rhs as i16);
(res.0 as isize, res.1)
}
}
#[inline(always)]
fn overflowing_div(self, rhs: isize) -> (isize, bool) {
let (r, f) = (self as i16).overflowing_div(rhs as i16);
(r as isize, f)
}
#[inline(always)]
fn overflowing_rem(self, rhs: isize) -> (isize, bool) {
let (r, f) = (self as i16).overflowing_rem(rhs as i16);
(r as isize, f)
}
#[inline(always)]
fn overflowing_neg(self) -> (isize, bool) {
let (r, f) = (self as i16).overflowing_neg();
(r as isize, f)
}
#[inline(always)]
fn overflowing_shl(self, rhs: u32) -> (isize, bool) {
let (r, f) = (self as i16).overflowing_shl(rhs);
(r as isize, f)
}
#[inline(always)]
fn overflowing_shr(self, rhs: u32) -> (isize, bool) {
let (r, f) = (self as i16).overflowing_shr(rhs);
(r as isize, f)
}
}
@@ -18,6 +18,13 @@ fn size_of_basic() {
assert_eq!(size_of::<u64>(), 8);
}

#[test]
#[cfg(target_pointer_width = "16")]
fn size_of_16() {
assert_eq!(size_of::<usize>(), 2);
assert_eq!(size_of::<*const usize>(), 2);
}

#[test]
#[cfg(target_pointer_width = "32")]
fn size_of_32() {
@@ -47,6 +54,13 @@ fn align_of_basic() {
assert_eq!(align_of::<u32>(), 4);
}

#[test]
#[cfg(target_pointer_width = "16")]
fn align_of_16() {
assert_eq!(align_of::<usize>(), 2);
assert_eq!(align_of::<*const usize>(), 2);
}

#[test]
#[cfg(target_pointer_width = "32")]
fn align_of_32() {
@@ -177,6 +177,10 @@ pub fn represent_type<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
repr
}

macro_rules! repeat_u8_as_u16 {
($name:expr) => { (($name as u16) << 8 |
($name as u16)) }
}
macro_rules! repeat_u8_as_u32 {
($name:expr) => { (($name as u32) << 24 |
($name as u32) << 16 |
@@ -203,23 +207,27 @@ pub const DTOR_NEEDED_HINT: u8 = 0x3d;
pub const DTOR_MOVED_HINT: u8 = 0x2d;

pub const DTOR_NEEDED: u8 = 0xd4;
pub const DTOR_NEEDED_U16: u16 = repeat_u8_as_u16!(DTOR_NEEDED);
pub const DTOR_NEEDED_U32: u32 = repeat_u8_as_u32!(DTOR_NEEDED);
pub const DTOR_NEEDED_U64: u64 = repeat_u8_as_u64!(DTOR_NEEDED);
#[allow(dead_code)]
pub fn dtor_needed_usize(ccx: &CrateContext) -> usize {
match &ccx.tcx().sess.target.target.target_pointer_width[..] {
"16" => DTOR_NEEDED_U16 as usize,
"32" => DTOR_NEEDED_U32 as usize,
"64" => DTOR_NEEDED_U64 as usize,
tws => panic!("Unsupported target word size for int: {}", tws),
}
}

pub const DTOR_DONE: u8 = 0x1d;
pub const DTOR_DONE_U16: u16 = repeat_u8_as_u16!(DTOR_DONE);
pub const DTOR_DONE_U32: u32 = repeat_u8_as_u32!(DTOR_DONE);
pub const DTOR_DONE_U64: u64 = repeat_u8_as_u64!(DTOR_DONE);
#[allow(dead_code)]
pub fn dtor_done_usize(ccx: &CrateContext) -> usize {
match &ccx.tcx().sess.target.target.target_pointer_width[..] {
"16" => DTOR_DONE_U16 as usize,
"32" => DTOR_DONE_U32 as usize,
"64" => DTOR_DONE_U64 as usize,
tws => panic!("Unsupported target word size for int: {}", tws),
@@ -935,6 +935,7 @@ pub fn call_memcpy(cx: Block, dst: ValueRef, src: ValueRef, n_bytes: ValueRef, a
let _icx = push_ctxt("call_memcpy");
let ccx = cx.ccx();
let key = match &ccx.sess().target.target.target_pointer_width[..] {
"16" => "llvm.memcpy.p0i8.p0i8.i16",
"32" => "llvm.memcpy.p0i8.p0i8.i32",
"64" => "llvm.memcpy.p0i8.p0i8.i64",
tws => panic!("Unsupported target word size for memcpy: {}", tws),
@@ -989,6 +990,7 @@ fn memfill<'a, 'tcx>(b: &Builder<'a, 'tcx>, llptr: ValueRef, ty: Ty<'tcx>, byte:
let llty = type_of::type_of(ccx, ty);

let intrinsic_key = match &ccx.sess().target.target.target_pointer_width[..] {
"16" => "llvm.memset.p0i8.i16",
"32" => "llvm.memset.p0i8.i32",
"64" => "llvm.memset.p0i8.i64",
tws => panic!("Unsupported target word size for memset: {}", tws),
@@ -834,6 +834,7 @@ pub fn C_int<I: AsI64>(ccx: &CrateContext, i: I) -> ValueRef {
let v = i.as_i64();

match machine::llbitsize_of_real(ccx, ccx.int_type()) {
16 => assert!(v < (1<<15) && v >= -(1<<15)),
32 => assert!(v < (1<<31) && v >= -(1<<31)),
64 => {},
n => panic!("unsupported target size: {}", n)
@@ -846,6 +847,7 @@ pub fn C_uint<I: AsU64>(ccx: &CrateContext, i: I) -> ValueRef {
let v = i.as_u64();

match machine::llbitsize_of_real(ccx, ccx.int_type()) {
16 => assert!(v < (1<<16)),
32 => assert!(v < (1<<32)),
64 => {},
n => panic!("unsupported target size: {}", n)
@@ -767,6 +767,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
/// address space on 64-bit ARMv8 and x86_64.
pub fn obj_size_bound(&self) -> u64 {
match &self.sess().target.target.target_pointer_width[..] {
"16" => 1 << 15,
"32" => 1 << 31,
"64" => 1 << 47,
_ => unreachable!() // error handled by config::build_target_config
@@ -829,10 +830,13 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef
let t_f32 = Type::f32(ccx);
let t_f64 = Type::f64(ccx);

ifn!("llvm.memcpy.p0i8.p0i8.i16", fn(i8p, i8p, t_i16, t_i32, i1) -> void);
ifn!("llvm.memcpy.p0i8.p0i8.i32", fn(i8p, i8p, t_i32, t_i32, i1) -> void);
ifn!("llvm.memcpy.p0i8.p0i8.i64", fn(i8p, i8p, t_i64, t_i32, i1) -> void);
ifn!("llvm.memmove.p0i8.p0i8.i16", fn(i8p, i8p, t_i16, t_i32, i1) -> void);
ifn!("llvm.memmove.p0i8.p0i8.i32", fn(i8p, i8p, t_i32, t_i32, i1) -> void);
ifn!("llvm.memmove.p0i8.p0i8.i64", fn(i8p, i8p, t_i64, t_i32, i1) -> void);
ifn!("llvm.memset.p0i8.i16", fn(i8p, t_i8, t_i16, t_i32, i1) -> void);
ifn!("llvm.memset.p0i8.i32", fn(i8p, t_i8, t_i32, t_i32, i1) -> void);
ifn!("llvm.memset.p0i8.i64", fn(i8p, t_i8, t_i64, t_i32, i1) -> void);

@@ -2312,11 +2312,13 @@ impl OverflowOpViaIntrinsic {

let new_sty = match ty.sty {
TyInt(TyIs) => match &tcx.sess.target.target.target_pointer_width[..] {
"16" => TyInt(TyI16),
"32" => TyInt(TyI32),
"64" => TyInt(TyI64),
_ => panic!("unsupported target word size")
},
TyUint(TyUs) => match &tcx.sess.target.target.target_pointer_width[..] {
"16" => TyUint(TyU16),
"32" => TyUint(TyU32),
"64" => TyUint(TyU64),
_ => panic!("unsupported target word size")
Oops, something went wrong.

0 comments on commit 1b13437

Please sign in to comment.
You can’t perform that action at this time.