properly handle #[cfg] (conditional compilation) on tasks

This commit is contained in:
Jorge Aparicio 2018-12-16 19:10:36 +01:00
parent 4345c10596
commit 8e9a91d0b0
4 changed files with 72 additions and 20 deletions

View file

@ -73,7 +73,8 @@ pub fn app(app: &App) -> parse::Result<()> {
app.tasks app.tasks
.values() .values()
.flat_map(|t| t.args.schedule.iter().chain(&t.args.spawn)), .flat_map(|t| t.args.schedule.iter().chain(&t.args.spawn)),
) { )
{
if !app.tasks.contains_key(task) { if !app.tasks.contains_key(task) {
return Err(parse::Error::new( return Err(parse::Error::new(
task.span(), task.span(),

View file

@ -1210,7 +1210,6 @@ fn tasks(ctxt: &mut Context, app: &App, analysis: &Analysis) -> proc_macro2::Tok
// second pass to generate the actual task function // second pass to generate the actual task function
for (name, task) in &app.tasks { for (name, task) in &app.tasks {
let attrs = &task.attrs;
let inputs = &task.inputs; let inputs = &task.inputs;
let locals = mk_locals(&task.statics, false); let locals = mk_locals(&task.statics, false);
let stmts = &task.stmts; let stmts = &task.stmts;
@ -1245,6 +1244,8 @@ fn tasks(ctxt: &mut Context, app: &App, analysis: &Analysis) -> proc_macro2::Tok
app, app,
)); ));
let attrs = &task.attrs;
let cfgs = &task.cfgs;
let task_alias = &ctxt.tasks[name].alias; let task_alias = &ctxt.tasks[name].alias;
let baseline_arg = match () { let baseline_arg = match () {
#[cfg(feature = "timer-queue")] #[cfg(feature = "timer-queue")]
@ -1257,6 +1258,7 @@ fn tasks(ctxt: &mut Context, app: &App, analysis: &Analysis) -> proc_macro2::Tok
}; };
items.push(quote!( items.push(quote!(
#(#attrs)* #(#attrs)*
#(#cfgs)*
#unsafety fn #task_alias(#baseline_arg #(#inputs,)*) { #unsafety fn #task_alias(#baseline_arg #(#inputs,)*) {
#(#locals)* #(#locals)*
@ -1284,9 +1286,21 @@ fn dispatchers(
for (level, dispatcher) in &analysis.dispatchers { for (level, dispatcher) in &analysis.dispatchers {
let ready_alias = mk_ident(None); let ready_alias = mk_ident(None);
let enum_alias = mk_ident(None); let enum_alias = mk_ident(None);
let tasks = &dispatcher.tasks;
let capacity = mk_typenum_capacity(dispatcher.capacity, true); let capacity = mk_typenum_capacity(dispatcher.capacity, true);
let variants = dispatcher
.tasks
.iter()
.map(|task| {
let task_ = &app.tasks[task];
let cfgs = &task_.cfgs;
quote!(
#(#cfgs)*
#task
)
})
.collect::<Vec<_>>();
let symbol = format!("P{}::READY_QUEUE::{}", level, ready_alias); let symbol = format!("P{}::READY_QUEUE::{}", level, ready_alias);
let e = quote!(rtfm::export); let e = quote!(rtfm::export);
let ty = quote!(#e::ReadyQueue<#enum_alias, #capacity>); let ty = quote!(#e::ReadyQueue<#enum_alias, #capacity>);
@ -1304,7 +1318,7 @@ fn dispatchers(
data.push(quote!( data.push(quote!(
#[allow(dead_code)] #[allow(dead_code)]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
enum #enum_alias { #(#tasks,)* } enum #enum_alias { #(#variants,)* }
#[doc = #symbol] #[doc = #symbol]
static mut #ready_alias: #e::MaybeUninit<#ty> = #e::MaybeUninit::uninitialized(); static mut #ready_alias: #e::MaybeUninit<#ty> = #e::MaybeUninit::uninitialized();
@ -1319,9 +1333,12 @@ fn dispatchers(
let task_ = &ctxt.tasks[task]; let task_ = &ctxt.tasks[task];
let inputs = &task_.inputs; let inputs = &task_.inputs;
let free = &task_.free_queue; let free = &task_.free_queue;
let pats = tuple_pat(&app.tasks[task].inputs);
let alias = &task_.alias; let alias = &task_.alias;
let task__ = &app.tasks[task];
let pats = tuple_pat(&task__.inputs);
let cfgs = &task__.cfgs;
let baseline_let; let baseline_let;
let call; let call;
match () { match () {
@ -1341,13 +1358,16 @@ fn dispatchers(
} }
}; };
quote!(#enum_alias::#task => { quote!(
#baseline_let #(#cfgs)*
let input = ptr::read(#inputs.get_ref().get_unchecked(usize::from(index))); #enum_alias::#task => {
#free.get_mut().split().0.enqueue_unchecked(index); #baseline_let
let (#pats) = input; let input = ptr::read(#inputs.get_ref().get_unchecked(usize::from(index)));
#call #free.get_mut().split().0.enqueue_unchecked(index);
}) let (#pats) = input;
#call
}
)
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
@ -1397,6 +1417,7 @@ fn spawn(ctxt: &Context, app: &App, analysis: &Analysis) -> proc_macro2::TokenSt
for (name, task) in &ctxt.tasks { for (name, task) in &ctxt.tasks {
let alias = &task.spawn_fn; let alias = &task.spawn_fn;
let task_ = &app.tasks[name]; let task_ = &app.tasks[name];
let cfgs = &task_.cfgs;
let free = &task.free_queue; let free = &task.free_queue;
let level = task_.args.priority; let level = task_.args.priority;
let dispatcher = &ctxt.dispatchers[&level]; let dispatcher = &ctxt.dispatchers[&level];
@ -1432,6 +1453,7 @@ fn spawn(ctxt: &Context, app: &App, analysis: &Analysis) -> proc_macro2::TokenSt
items.push(quote!( items.push(quote!(
#[inline(always)] #[inline(always)]
#(#cfgs)*
unsafe fn #alias( unsafe fn #alias(
#baseline_arg #baseline_arg
#priority: &core::cell::Cell<u8>, #priority: &core::cell::Cell<u8>,
@ -1470,8 +1492,10 @@ fn spawn(ctxt: &Context, app: &App, analysis: &Analysis) -> proc_macro2::TokenSt
let mut methods = vec![]; let mut methods = vec![];
for task in spawn { for task in spawn {
let task_ = &app.tasks[task];
let alias = &ctxt.tasks[task].spawn_fn; let alias = &ctxt.tasks[task].spawn_fn;
let inputs = &app.tasks[task].inputs; let inputs = &task_.inputs;
let cfgs = &task_.cfgs;
let ty = tuple_ty(inputs); let ty = tuple_ty(inputs);
let pats = tuple_pat(inputs); let pats = tuple_pat(inputs);
@ -1490,6 +1514,7 @@ fn spawn(ctxt: &Context, app: &App, analysis: &Analysis) -> proc_macro2::TokenSt
methods.push(quote!( methods.push(quote!(
#[allow(unsafe_code)] #[allow(unsafe_code)]
#[inline] #[inline]
#(#cfgs)*
pub fn #task(&self, #(#inputs,)*) -> Result<(), #ty> { pub fn #task(&self, #(#inputs,)*) -> Result<(), #ty> {
unsafe { #alias(#instant &self.#priority, #pats) } unsafe { #alias(#instant &self.#priority, #pats) }
} }
@ -1519,12 +1544,15 @@ fn schedule(ctxt: &Context, app: &App) -> proc_macro2::TokenStream {
let enum_ = &ctxt.schedule_enum; let enum_ = &ctxt.schedule_enum;
let inputs = &task_.inputs; let inputs = &task_.inputs;
let scheduleds = &task_.scheduleds; let scheduleds = &task_.scheduleds;
let args = &app.tasks[task].inputs; let task__ = &app.tasks[task];
let args = &task__.inputs;
let cfgs = &task__.cfgs;
let ty = tuple_ty(args); let ty = tuple_ty(args);
let pats = tuple_pat(args); let pats = tuple_pat(args);
items.push(quote!( items.push(quote!(
#[inline(always)] #[inline(always)]
#(#cfgs)*
unsafe fn #alias( unsafe fn #alias(
#priority: &core::cell::Cell<u8>, #priority: &core::cell::Cell<u8>,
instant: rtfm::Instant, instant: rtfm::Instant,
@ -1568,12 +1596,15 @@ fn schedule(ctxt: &Context, app: &App) -> proc_macro2::TokenStream {
let mut methods = vec![]; let mut methods = vec![];
for task in schedule { for task in schedule {
let alias = &ctxt.schedule_fn[task]; let alias = &ctxt.schedule_fn[task];
let inputs = &app.tasks[task].inputs; let task_ = &app.tasks[task];
let inputs = &task_.inputs;
let cfgs = &task_.cfgs;
let ty = tuple_ty(inputs); let ty = tuple_ty(inputs);
let pats = tuple_pat(inputs); let pats = tuple_pat(inputs);
methods.push(quote!( methods.push(quote!(
#[inline] #[inline]
#(#cfgs)*
pub fn #task( pub fn #task(
&self, &self,
instant: rtfm::Instant, instant: rtfm::Instant,
@ -1603,12 +1634,22 @@ fn timer_queue(ctxt: &Context, app: &App, analysis: &Analysis) -> proc_macro2::T
let mut items = vec![]; let mut items = vec![];
let variants = tasks
.iter()
.map(|task| {
let cfgs = &app.tasks[task].cfgs;
quote!(
#(#cfgs)*
#task
)
})
.collect::<Vec<_>>();
let enum_ = &ctxt.schedule_enum; let enum_ = &ctxt.schedule_enum;
items.push(quote!( items.push(quote!(
#[allow(dead_code)] #[allow(dead_code)]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
enum #enum_ { #(#tasks,)* } enum #enum_ { #(#variants,)* }
)); ));
let cap = mk_typenum_capacity(analysis.timer_queue.capacity, false); let cap = mk_typenum_capacity(analysis.timer_queue.capacity, false);
@ -1637,13 +1678,16 @@ fn timer_queue(ctxt: &Context, app: &App, analysis: &Analysis) -> proc_macro2::T
let arms = tasks let arms = tasks
.iter() .iter()
.map(|task| { .map(|task| {
let level = app.tasks[task].args.priority; let task_ = &app.tasks[task];
let level = task_.args.priority;
let cfgs = &task_.cfgs;
let dispatcher_ = &ctxt.dispatchers[&level]; let dispatcher_ = &ctxt.dispatchers[&level];
let tenum = &dispatcher_.enum_; let tenum = &dispatcher_.enum_;
let ready = &dispatcher_.ready_queue; let ready = &dispatcher_.ready_queue;
let dispatcher = &analysis.dispatchers[&level].interrupt; let dispatcher = &analysis.dispatchers[&level].interrupt;
quote!( quote!(
#(#cfgs)*
#enum_::#task => { #enum_::#task => {
(#ready { #priority }).lock(|rq| { (#ready { #priority }).lock(|rq| {
rq.split().0.enqueue_unchecked((#tenum::#task, index)) rq.split().0.enqueue_unchecked((#tenum::#task, index))

View file

@ -1047,6 +1047,7 @@ impl Static {
pub struct Task { pub struct Task {
pub args: TaskArgs, pub args: TaskArgs,
pub cfgs: Vec<Attribute>,
pub attrs: Vec<Attribute>, pub attrs: Vec<Attribute>,
pub unsafety: Option<Token![unsafe]>, pub unsafety: Option<Token![unsafe]>,
pub inputs: Vec<ArgCaptured>, pub inputs: Vec<ArgCaptured>,
@ -1098,9 +1099,11 @@ impl Task {
_ => {} _ => {}
} }
let (cfgs, attrs) = extract_cfgs(item.attrs);
Ok(Task { Ok(Task {
args, args,
attrs: item.attrs, cfgs,
attrs,
unsafety: item.unsafety, unsafety: item.unsafety,
inputs, inputs,
statics: Static::parse(statics)?, statics: Static::parse(statics)?,

View file

@ -30,18 +30,22 @@ const APP: () = {
loop {} loop {}
} }
#[task(resources = [FOO])] #[task(resources = [FOO], schedule = [quux], spawn = [quux])]
fn foo() { fn foo() {
#[cfg(never)] #[cfg(never)]
static mut BAR: u32 = 0; static mut BAR: u32 = 0;
} }
#[task(priority = 3, resources = [FOO])] #[task(priority = 3, resources = [FOO], schedule = [quux], spawn = [quux])]
fn bar() { fn bar() {
#[cfg(never)] #[cfg(never)]
static mut BAR: u32 = 0; static mut BAR: u32 = 0;
} }
#[cfg(never)]
#[task]
fn quux() {}
extern "C" { extern "C" {
fn UART0(); fn UART0();
fn UART1(); fn UART1();