1 //! Generate feature-related Rust code. 2 3 use super::{Formatter, fmtln}; 4 use crate::dsl; 5 6 impl dsl::Feature { 7 /// `macro_rules! for_each_feature { ... }` 8 /// 9 /// This function generates a macro to allow generating code for each CPU 10 /// feature. generate_macro(f: &mut Formatter)11 pub(crate) fn generate_macro(f: &mut Formatter) { 12 fmtln!(f, "#[doc(hidden)]"); 13 fmtln!(f, "#[macro_export]"); 14 f.add_block("macro_rules! for_each_feature", |f| { 15 f.add_block("($m:ident) =>", |f| { 16 f.add_block("$m!", |f| { 17 for feature in dsl::ALL_FEATURES { 18 fmtln!(f, "{feature}"); 19 } 20 }); 21 }); 22 }); 23 } 24 } 25 26 impl dsl::Features { 27 /// E.g., `features.is_sse2() && features.is_64b()` 28 /// 29 /// Generate a boolean expression that checks if the features are available. generate_boolean_expr(&self, name: &str) -> String30 pub(crate) fn generate_boolean_expr(&self, name: &str) -> String { 31 use dsl::Features::*; 32 match self { 33 And(lhs, rhs) => { 34 let lhs = lhs.generate_inner_boolean_expr(name); 35 let rhs = rhs.generate_inner_boolean_expr(name); 36 format!("{lhs} && {rhs}") 37 } 38 Or(lhs, rhs) => { 39 let lhs = lhs.generate_inner_boolean_expr(name); 40 let rhs = rhs.generate_inner_boolean_expr(name); 41 format!("{lhs} || {rhs}") 42 } 43 Feature(feature) => { 44 format!("{name}.{feature}()") 45 } 46 } 47 } 48 49 // This adds parentheses for inner terms. generate_inner_boolean_expr(&self, name: &str) -> String50 fn generate_inner_boolean_expr(&self, name: &str) -> String { 51 use dsl::Features::*; 52 match self { 53 And(lhs, rhs) => { 54 let lhs = lhs.generate_inner_boolean_expr(name); 55 let rhs = rhs.generate_inner_boolean_expr(name); 56 format!("({lhs} && {rhs})") 57 } 58 Or(lhs, rhs) => { 59 let lhs = lhs.generate_inner_boolean_expr(name); 60 let rhs = rhs.generate_inner_boolean_expr(name); 61 format!("({lhs} || {rhs})") 62 } 63 Feature(feature) => format!("{name}.{feature}()"), 64 } 65 } 66 67 /// E.g., `Features::Or(Features::Feature(compat), Features::Feature(64b))` 68 /// 69 /// Generate a Rust constructor expression that contains the feature 70 /// boolean term. generate_constructor_expr(&self, f: &mut Formatter)71 pub(crate) fn generate_constructor_expr(&self, f: &mut Formatter) { 72 let mut index = 0; 73 let name = self.generate_inner_constructor_expr(f, &mut index); 74 fmtln!(f, "{name}"); 75 } 76 generate_inner_constructor_expr(&self, f: &mut Formatter, index: &mut u32) -> String77 fn generate_inner_constructor_expr(&self, f: &mut Formatter, index: &mut u32) -> String { 78 use dsl::Features::*; 79 80 let name = format!("F{index}"); 81 *index += 1; 82 83 let const_expr = format!("const {name}: &'static Features"); 84 match self { 85 And(lhs, rhs) => { 86 let lhs = lhs.generate_inner_constructor_expr(f, index); 87 let rhs = rhs.generate_inner_constructor_expr(f, index); 88 fmtln!(f, "{const_expr} = &Features::And({lhs}, {rhs});"); 89 } 90 Or(lhs, rhs) => { 91 let lhs = lhs.generate_inner_constructor_expr(f, index); 92 let rhs = rhs.generate_inner_constructor_expr(f, index); 93 fmtln!(f, "{const_expr} = &Features::Or({lhs}, {rhs});"); 94 } 95 Feature(feature) => { 96 fmtln!(f, "{const_expr} = &Features::Feature(Feature::{feature});"); 97 } 98 } 99 name 100 } 101 } 102