1 //! Generate sources with type info.
2 //!
3 //! This generates a `types.rs` file which is included in
4 //! `cranelift-codegen/ir/types.rs`. The file provides constant definitions for the
5 //! most commonly used types, including all of the scalar types.
6 //!
7 //! This ensures that the metaprogram and the generated program see the same
8 //! type numbering.
9 
10 use crate::cdsl::types as cdsl_types;
11 use cranelift_srcgen::{Formatter, Language, error, fmtln};
12 
13 /// Emit a constant definition of a single value type.
emit_type(ty: &cdsl_types::ValueType, fmt: &mut Formatter)14 fn emit_type(ty: &cdsl_types::ValueType, fmt: &mut Formatter) {
15     let name = ty.to_string().to_uppercase();
16     let number = ty.number();
17 
18     fmt.doc_comment(&ty.doc());
19     fmtln!(fmt, "pub const {}: Type = Type({:#x});\n", name, number);
20 }
21 
22 /// Emit definition for all vector types with `bits` total size.
emit_vectors(bits: u64, fmt: &mut Formatter)23 fn emit_vectors(bits: u64, fmt: &mut Formatter) {
24     let vec_size: u64 = bits / 8;
25     for vec in cdsl_types::ValueType::all_lane_types()
26         .map(|ty| (ty, cdsl_types::ValueType::from(ty).membytes()))
27         .filter(|&(_, lane_size)| lane_size != 0 && lane_size < vec_size)
28         .map(|(ty, lane_size)| (ty, vec_size / lane_size))
29         .map(|(ty, lanes)| cdsl_types::VectorType::new(ty, lanes))
30     {
31         emit_type(&cdsl_types::ValueType::from(vec), fmt);
32     }
33 }
34 
35 /// Emit definition for all dynamic vector types with `bits` total size.
emit_dynamic_vectors(bits: u64, fmt: &mut Formatter)36 fn emit_dynamic_vectors(bits: u64, fmt: &mut Formatter) {
37     let vec_size: u64 = bits / 8;
38     for vec in cdsl_types::ValueType::all_lane_types()
39         .map(|ty| (ty, cdsl_types::ValueType::from(ty).membytes()))
40         .filter(|&(_, lane_size)| lane_size != 0 && lane_size < vec_size)
41         .map(|(ty, lane_size)| (ty, vec_size / lane_size))
42         .map(|(ty, lanes)| cdsl_types::DynamicVectorType::new(ty, lanes))
43     {
44         emit_type(&cdsl_types::ValueType::from(vec), fmt);
45     }
46 }
47 
48 /// Emit types using the given formatter object.
emit_types(fmt: &mut Formatter)49 fn emit_types(fmt: &mut Formatter) {
50     // Emit all of the lane types, such integers, floats, and booleans.
51     for ty in cdsl_types::ValueType::all_lane_types().map(cdsl_types::ValueType::from) {
52         emit_type(&ty, fmt);
53     }
54 
55     // Emit vector definitions for common SIMD sizes.
56     // Emit dynamic vector definitions.
57     for vec_size in &[16_u64, 32, 64, 128, 256, 512] {
58         emit_vectors(*vec_size, fmt);
59         emit_dynamic_vectors(*vec_size, fmt);
60     }
61 }
62 
63 /// Generate the types file.
generate(filename: &str, out_dir: &std::path::Path) -> Result<(), error::Error>64 pub(crate) fn generate(filename: &str, out_dir: &std::path::Path) -> Result<(), error::Error> {
65     let mut fmt = Formatter::new(Language::Rust);
66     emit_types(&mut fmt);
67     fmt.write(filename, out_dir)?;
68     Ok(())
69 }
70