From d28123b40852c121ab6be587005cdb4565463825 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Thu, 7 Aug 2014 09:59:28 -0400 Subject: [PATCH 1/4] Allow registers to have non-'static lifetime --- ioreg/builder/accessors.rs | 16 +++++++-------- ioreg/builder/getter.rs | 2 +- ioreg/builder/setter.rs | 41 +++++++++++++++++++------------------- 3 files changed, 29 insertions(+), 30 deletions(-) diff --git a/ioreg/builder/accessors.rs b/ioreg/builder/accessors.rs index 6e0aa1f2..5791e440 100644 --- a/ioreg/builder/accessors.rs +++ b/ioreg/builder/accessors.rs @@ -82,7 +82,7 @@ fn build_field_accessors<'a>(cx: &'a ExtCtxt, path: &Vec, }, None => "no documentation".into_string() }; - let docstring = format!("*[{}]* Field `{}`: {}", + let docstring = format!("*[{}]* `{}` field: {}", access_tag, field.name.node, field_doc); @@ -111,7 +111,7 @@ fn build_get_fn<'a>(cx: &'a ExtCtxt, path: &Vec, reg: &node::Reg) impl $reg_ty { $doc_attr #[allow(dead_code)] - pub fn get(&'static self) -> $getter_ty { + pub fn get(&self) -> $getter_ty { $getter_ty::new(self) } } @@ -131,7 +131,7 @@ fn build_field_set_fn<'a>(cx: &'a ExtCtxt, path: &Vec, if field.count.node == 1 { quote_method!(cx, #[allow(dead_code, missing_doc)] - pub fn $fn_name(&'static self, new_value: $field_ty) -> $setter_ty { + pub fn $fn_name<'a>(&'a self, new_value: $field_ty) -> $setter_ty<'a> { let mut setter: $setter_ty = $setter_ty::new(self); setter.$fn_name(new_value); setter @@ -140,7 +140,7 @@ fn build_field_set_fn<'a>(cx: &'a ExtCtxt, path: &Vec, } else { quote_method!(cx, #[allow(dead_code, missing_doc)] - pub fn $fn_name(&'static self, idx: uint, new_value: $field_ty) -> $setter_ty { + pub fn $fn_name<'a>(&'a self, idx: uint, new_value: $field_ty) -> $setter_ty<'a> { let mut setter: $setter_ty = $setter_ty::new(self); setter.$fn_name(idx, new_value); setter @@ -160,14 +160,14 @@ fn build_field_get_fn<'a>(cx: &'a ExtCtxt, path: &Vec, if field.count.node == 1 { quote_method!(cx, #[allow(dead_code, missing_doc)] - pub fn $fn_name(&'static self) -> $field_ty { + pub fn $fn_name(&self) -> $field_ty { $getter_ty::new(self).$fn_name() } ) } else { quote_method!(cx, #[allow(dead_code, missing_doc)] - pub fn $fn_name(&'static self, idx: uint) -> $field_ty { + pub fn $fn_name(&self, idx: uint) -> $field_ty { $getter_ty::new(self).$fn_name(idx) } ) @@ -184,7 +184,7 @@ fn build_field_clear_fn<'a>(cx: &'a ExtCtxt, path: &Vec, if field.count.node == 1 { quote_method!(cx, #[allow(dead_code, missing_doc)] - pub fn $fn_name(&'static self) -> $setter_ty { + pub fn $fn_name<'a>(&'a self) -> $setter_ty<'a> { let mut setter: $setter_ty = $setter_ty::new(self); setter.$fn_name(); setter @@ -193,7 +193,7 @@ fn build_field_clear_fn<'a>(cx: &'a ExtCtxt, path: &Vec, } else { quote_method!(cx, #[allow(dead_code, missing_doc)] - pub fn $fn_name(&'static self, idx: uint) -> $setter_ty { + pub fn $fn_name<'a>(&'a self, idx: uint) -> $setter_ty<'a> { let mut setter: $setter_ty = $setter_ty::new(self); setter.$fn_name(idx); setter diff --git a/ioreg/builder/getter.rs b/ioreg/builder/getter.rs index ec6744aa..8dfe2cd9 100644 --- a/ioreg/builder/getter.rs +++ b/ioreg/builder/getter.rs @@ -83,7 +83,7 @@ fn build_new<'a>(cx: &'a ExtCtxt, path: &Vec) utils::getter_name(cx, path)); let item = quote_item!(cx, #[doc = "Create a getter reflecting the current value of the given register."] - pub fn new(reg: &'static $reg_ty) -> $getter_ty { + pub fn new(reg: & $reg_ty) -> $getter_ty { $getter_ty { value: reg.value.get(), } diff --git a/ioreg/builder/setter.rs b/ioreg/builder/setter.rs index 9068b8a7..ccc04e91 100644 --- a/ioreg/builder/setter.rs +++ b/ioreg/builder/setter.rs @@ -75,10 +75,10 @@ fn build_type<'a>(cx: &'a ExtCtxt, path: &Vec, let item = quote_item!(cx, $doc_attr #[allow(non_camel_case_types)] - pub struct $name { + pub struct $name<'a> { value: $packed_ty, mask: $packed_ty, - reg: &'static $reg_ty, + reg: &'a $reg_ty, } ); item.unwrap() @@ -92,7 +92,7 @@ fn build_new<'a>(cx: &'a ExtCtxt, path: &Vec) utils::setter_name(cx, path)); let item = quote_item!(cx, #[doc="Create a new updater"] - pub fn new(reg: &'static $reg_ty) -> $setter_ty { + pub fn new(reg: &'a $reg_ty) -> $setter_ty { $setter_ty { value: 0, mask: 0, @@ -125,7 +125,7 @@ fn build_drop<'a>(cx: &'a ExtCtxt, path: &Vec, let item = quote_item!(cx, #[unsafe_destructor] #[doc = "This performs the register update"] - impl Drop for $setter_ty { + impl<'a> Drop for $setter_ty<'a> { fn drop(&mut self) { let clear_mask: $unpacked_ty = $clear as $unpacked_ty; if self.mask != 0 { @@ -161,7 +161,7 @@ fn build_impl<'a>(cx: &'a ExtCtxt, path: &Vec, reg: &node::Reg, let done: P = build_done(cx); let impl_ = quote_item!(cx, #[allow(dead_code)] - impl $setter_ty { + impl<'a> $setter_ty<'a> { $new $methods $done @@ -206,8 +206,8 @@ fn build_field_set_fn<'a>(cx: &'a ExtCtxt, path: &Vec, reg: &node::Reg, let shift = utils::shift(cx, None, field); quote_method!(cx, $doc_attr - pub fn $fn_name<'a>(&'a mut self, new_value: $field_ty) - -> &'a mut $setter_ty { + pub fn $fn_name<'b>(&'b mut self, new_value: $field_ty) + -> &'b mut $setter_ty<'a> { self.value |= (self.value & ! $mask) | ((new_value as $unpacked_ty) & $mask) << $shift; self.mask |= $mask << $shift; self @@ -217,11 +217,11 @@ fn build_field_set_fn<'a>(cx: &'a ExtCtxt, path: &Vec, reg: &node::Reg, let shift = utils::shift(cx, Some(quote_expr!(cx, idx)), field); quote_method!(cx, $doc_attr - pub fn $fn_name<'a>(&'a mut self, idx: uint, new_value: $field_ty) - -> &'a mut $setter_ty { - self.value |= (self.value & ! $mask) | ((new_value as $unpacked_ty) & $mask) << $shift; - self.mask |= $mask << $shift; - self + pub fn $fn_name<'b>(&'b mut self, idx: uint, new_value: $field_ty) + -> &'b mut $setter_ty<'a> { + self.value |= (self.value & ! $mask) | ((new_value as $unpacked_ty) & $mask) << $shift; + self.mask |= $mask << $shift; + self } ) } @@ -248,21 +248,20 @@ fn build_field_clear_fn<'a>(cx: &'a ExtCtxt, path: &Vec, let shift = utils::shift(cx, None, field); quote_method!(cx, $doc_attr - pub fn $fn_name<'a>(&'a mut self) -> &'a mut $setter_ty { - self.value |= $mask << $shift; - self.mask |= $mask << $shift; - self + pub fn $fn_name<'b>(&'b mut self) -> &'b mut $setter_ty<'a> { + self.value |= $mask << $shift; + self.mask |= $mask << $shift; + self } ) } else { let shift = utils::shift(cx, Some(quote_expr!(cx, idx)), field); quote_method!(cx, $doc_attr - pub fn $fn_name<'a>(&'a mut self, idx: uint) - -> &'a mut $setter_ty { - self.value |= $mask << $shift; - self.mask |= $mask << $shift; - self + pub fn $fn_name<'b>(&'b mut self, idx: uint) -> &'b mut $setter_ty<'a> { + self.value |= $mask << $shift; + self.mask |= $mask << $shift; + self } ) } From 69a89a377d4e4099f408d34708926a9094596556 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Thu, 7 Aug 2014 11:01:42 -0400 Subject: [PATCH 2/4] ioreg: Remove 'static from documentation example --- ioreg/ioreg.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ioreg/ioreg.rs b/ioreg/ioreg.rs index 8d03886c..f508912d 100644 --- a/ioreg/ioreg.rs +++ b/ioreg/ioreg.rs @@ -208,18 +208,18 @@ look at `cr` in particular, ``` impl UART_cr { - pub fn get(&'static self) -> UART_cr_Get { ... } + pub fn get(&self) -> UART_cr_Get { ... } - pub fn set_rxe(&'static self, new_value: bool) -> UART_cr_Update { ... } - pub fn rxe(&'static self) -> bool { ... } + pub fn set_rxe(&self, new_value: bool) -> UART_cr_Update { ... } + pub fn rxe(&self) -> bool { ... } // similar methods for `txe`, `rxie`, `txie` - pub fn set_br(&'static self, new_value: u32) -> UART_cr_Update { ... } - pub fn br(&'static self) -> u32 { ... } + pub fn set_br(&self, new_value: u32) -> UART_cr_Update { ... } + pub fn br(&self) -> u32 { ... } - pub fn set_parity(&'static self, new_value: UART_cr_parity) -> UART_cr_Update { ... } - pub fn parity(&'static self) -> UART_cr_parity { ... } + pub fn set_parity(&self, new_value: UART_cr_parity) -> UART_cr_Update { ... } + pub fn parity(&self) -> UART_cr_parity { ... } } ``` @@ -264,7 +264,7 @@ method is instead produced. For instance, in the case of the `sr` register's `fe` flag, ``` -pub fn clear_fe(&'static self) -> UART_sr_Update { ... } +pub fn clear_fe(&self) -> UART_sr_Update { ... } ``` ### Informal grammar From 6dcbbd372a63d477631cc79e0591c450b8689fe6 Mon Sep 17 00:00:00 2001 From: Vladimir Pouzanov Date: Wed, 23 Jul 2014 08:12:21 +0100 Subject: [PATCH 3/4] Zinc now depends on shiny --- Rakefile | 11 ++++++++++- support/rake.rb | 4 ++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Rakefile b/Rakefile index de4d4f08..95cd6cce 100644 --- a/Rakefile +++ b/Rakefile @@ -7,6 +7,14 @@ Context.create(__FILE__, ENV['PLATFORM']) provide_stdlibs +# shiny +compile_rust :shiny_crate, { + source: 'thirdparty/shiny/src/lib.rs'.in_root, + produce: 'thirdparty/shiny/src/lib.rs'.in_root.as_rlib.in_build, + out_dir: true, + build_for: :host, +} + # tests desc "Run tests" task :test @@ -90,9 +98,10 @@ rust_tests :platformtree_test, { produce: 'platformtree_test'.in_build, } +# zinc test rust_tests :zinc_test, { source: 'main.rs'.in_source, - deps: [:core_crate, :macro_ioreg], + deps: [:core_crate, :macro_ioreg, :hamcrest_crate, :shiny_crate], produce: 'zinc_test'.in_build, recompile_on: [:platform], build_for: :host, diff --git a/support/rake.rb b/support/rake.rb index 47be5c84..cd2e2ecd 100644 --- a/support/rake.rb +++ b/support/rake.rb @@ -162,4 +162,8 @@ def provide_stdlibs Rake::FileTask.define_task 'thirdparty/hamcrest-rust'.in_root do |t| sh "git clone --single-branch --depth 1 https://github.com/carllerche/hamcrest-rust #{t.name}" end.invoke + + Rake::FileTask.define_task 'thirdparty/shiny'.in_root do |t| + sh "git clone --single-branch --depth 1 https://github.com/farcaller/shiny #{t.name}" + end.invoke end From 11b6e7acf4e85bc878c02322e69076f845d1bde7 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Thu, 7 Aug 2014 10:53:11 -0400 Subject: [PATCH 4/4] ioreg: Add simple testcases --- Rakefile | 6 +++ ioreg/test.rs | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 ioreg/test.rs diff --git a/Rakefile b/Rakefile index 95cd6cce..b386bb23 100644 --- a/Rakefile +++ b/Rakefile @@ -58,6 +58,12 @@ compile_rust :macro_ioreg, { build_for: :host, } +rust_tests :ioreg_test, { + source: 'ioreg/test.rs'.in_root, + deps: [:core_crate, :macro_ioreg, :shiny_crate], + produce: 'ioreg_test'.in_build, +} + # zinc crate compile_rust :zinc_crate, { source: 'main.rs'.in_source, diff --git a/ioreg/test.rs b/ioreg/test.rs new file mode 100644 index 00000000..069877cb --- /dev/null +++ b/ioreg/test.rs @@ -0,0 +1,133 @@ +// Zinc, the bare metal stack for rust. +// Copyright 2014 Ben Gamari +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Tests for ioreg! syntax extension + +#![feature(phase)] +#[phase(plugin)] extern crate macro_ioreg; +#[phase(plugin,link)] extern crate shiny; +extern crate core; + + +#[allow(dead_code)] +#[path="../src/lib/volatile_cell.rs"] mod volatile_cell; + +#[cfg(test)] +mod test { + use std::mem::{transmute, zeroed}; + use std::ptr::RawPtr; + use volatile_cell::VolatileCell; + + fn get_value<'a, T>(v: &'a T, offset: uint) -> u32 { + unsafe { + let ptr: *const u32 = transmute(v); + *(ptr.offset(offset as int)) + } + } + + fn zeroed_safe() -> T { + unsafe { + return zeroed(); + } + } + + ioregs!(BASIC_TEST = { + 0x0 => reg32 reg1 { + 0 => field1, + 1..3 => field2, + 16..24 => field3, + 25 => field4: set_to_clear, + } + 0x4 => reg32 reg2 { + 0 => field1, + } + }) + + describe!( + before_each { + let test: BASIC_TEST = zeroed_safe(); + } + + it "can round_trip simple field values (1)" { + test.reg1.set_field1(true); + assert_eq!(test.reg1.field1(), true) + assert_eq!(get_value(&test, 0), 1) + assert_eq!(get_value(&test, 1), 0) + } + + it "can round trip simple field values (2)" { + test.reg1.set_field3(0xde); + assert_eq!(test.reg1.field3(), 0xde) + assert_eq!(get_value(&test, 0), 0xde<<16) + } + + it "sets set_to_clear fields" { + test.reg1.clear_field4(); + assert_eq!(get_value(&test, 0), 1<<25) + } + ) + + ioregs!(GROUP_TEST = { + 0x0 => group regs[5] { + 0x0 => reg32 reg1 { + 0..31 => field1 + } + 0x4 => reg32 reg2 { + 0..31 => field2 + } + } + }) + + describe!( + before_each { + let test: GROUP_TEST = zeroed_safe(); + } + + it "sets groups correctly" { + test.regs[0].reg1.set_field1(0xdeadbeef); + assert_eq!(test.regs[0].reg1.field1(), 0xdeadbeef) + assert_eq!(get_value(&test, 0), 0xdeadbeef) + for i in range(1, 10) { + assert_eq!(get_value(&test, i), 0) + } + + test.regs[2].reg2.set_field2(0xfeedbeef); + assert_eq!(test.regs[2].reg2.field2(), 0xfeedbeef) + assert_eq!(get_value(&test, 5), 0xfeedbeef) + } + ) + + ioregs!(FIELD_ARRAY_TEST = { + 0x0 => reg32 reg1 { + 0..31 => field[16] + } + }) + + describe!( + before_each { + let test: FIELD_ARRAY_TEST = zeroed_safe(); + } + + it "sets field arrays correctly" { + test.reg1.set_field(0, 1); + assert_eq!(test.reg1.field(0), 1); + assert_eq!(get_value(&test, 0), 0x1) + + test.reg1.set_field(4, 3); + assert_eq!(test.reg1.field(4), 3); + assert_eq!(get_value(&test, 0), 0x1 | 0x3<<8) + } + ) +}