Last active
August 29, 2015 14:03
-
-
Save bgamari/d3e3a7a6b83c1bfaa00e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![feature(unsafe_destructor)] | |
use std::ty::Unsafe; | |
use std::kinds::marker::InvariantType; | |
struct AReg1 { | |
value: Unsafe<u32> | |
} | |
struct AReg1Value { | |
value: u32, | |
} | |
impl AReg1Value { | |
pub fn new<'a>(reg: &'a AReg1) -> AReg1Value { | |
unsafe { | |
AReg1Value {value: *reg.value.get()} | |
} | |
} | |
pub fn get_field1(&self) -> bool { | |
(self.value >> 0) & 1 != 0 | |
} | |
pub fn get_field2(&self) -> u32 { | |
(self.value >> 1) & 7 | |
} | |
pub fn get_field3(&self) -> bool { | |
(self.value >> 5) & 1 != 0 | |
} | |
} | |
/// This represents the value of a particular register named AReg1 and | |
/// can be used to manipulate the fields of this register atomically | |
struct AReg1Updater<'a> { | |
value: u32, | |
mask: u32, | |
// this may need to turn into a raw pointer due to unsafe destructors | |
reg: &'a AReg1, | |
} | |
impl<'a> AReg1Updater<'a> { | |
pub fn new(reg: &'a AReg1) -> AReg1Updater<'a> { | |
AReg1Updater {value: 0, mask: 0, reg: reg} | |
} | |
/// bit 0 | |
pub fn set_field1<'b>(&'b mut self, value: bool) -> &'b mut AReg1Updater<'a> { | |
self.value = (!(1<<0) & self.value) | ((value as u32 & 1) << 0); | |
self.mask = self.mask | 1; | |
self | |
} | |
/// bits 1..4 | |
pub fn set_field2<'b>(&'b mut self, value: u32) -> &'b mut AReg1Updater<'a> { | |
self.value = (!(7<<1) & self.value) | ((value as u32 & 0x7) << 1); | |
self.mask = self.mask | (7<<1); | |
self | |
} | |
/// bit 5: a write-to-clear flag | |
pub fn clear_field3<'b>(&'b mut self) -> &'b mut AReg1Updater<'a> { | |
self.value = self.value | (1<<5); | |
self.mask = self.mask | (1<<5); | |
self | |
} | |
} | |
#[unsafe_destructor] | |
impl<'a> Drop for AReg1Updater<'a> { | |
fn drop(&mut self) { | |
let clear_mask: u32 = 1 << 5; | |
if self.mask != 0 { | |
unsafe { | |
let old_value: u32 = *self.reg.value.get() & !clear_mask & !self.mask; | |
*self.reg.value.get() = self.value | old_value; | |
} | |
} | |
} | |
} | |
impl AReg1 { | |
fn get<'a>(&'a self) -> AReg1Value { | |
AReg1Value::new(self) | |
} | |
fn set_field1<'a>(&'a self, value: bool) -> AReg1Updater<'a> { | |
let mut a = AReg1Updater::new(self); | |
a.set_field1(value); | |
a | |
} | |
//fn get_field1<'a>(&'a self) -> u32 { ... } | |
//fn set_field2<'a>(&'a self, value: u32) -> AReg1Updater<'a> { ... } | |
//fn get_field2<'a>(&'a self) -> u32 { ... } | |
//fn set_field3<'a>(&'a self, value: bool) -> AReg1Updater<'a> { ... } | |
//fn get_field3<'a>(&'a self) -> bool { ... } | |
} | |
static mut areg1: AReg1 = | |
AReg1 { value: Unsafe {value: 0, | |
marker1: InvariantType }}; | |
fn main() { | |
unsafe { | |
areg1 | |
.set_field1(true) | |
.set_field2(5) | |
.clear_field3(); | |
println!("field1 = {}", areg1.get().get_field1()); | |
println!("field2 = {}", areg1.get().get_field2()); | |
} | |
} |
Author
bgamari
commented
Jul 9, 2014
$ rustc test.rs
error: internal compiler error: unexpected failure
note: the compiler hit an unexpected failure path. this is a bug.
note: we would appreciate a bug report: http://doc.rust-lang.org/complement-bugreport.html
note: run with `RUST_BACKTRACE=1` for a backtrace
task 'rustc' failed at 'index out of bounds: the len is 0 but the index is 0', /opt/exp/rust/src/librustc/middle/subst.rs:405
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment