]>
Commit | Line | Data |
---|---|---|
c620b35d | 1 | use crate::format::Indentation; |
c295e0f8 XL |
2 | use crate::types::{IntrinsicType, TypeKind}; |
3 | ||
4 | use super::argument::ArgumentList; | |
c295e0f8 XL |
5 | |
6 | /// An intrinsic | |
3c0e092e | 7 | #[derive(Debug, PartialEq, Clone)] |
c295e0f8 | 8 | pub struct Intrinsic { |
c295e0f8 XL |
9 | /// The function name of this intrinsic. |
10 | pub name: String, | |
11 | ||
a2a8927a | 12 | /// Any arguments for this intrinsic. |
c295e0f8 XL |
13 | pub arguments: ArgumentList, |
14 | ||
15 | /// The return type of this intrinsic. | |
c295e0f8 | 16 | pub results: IntrinsicType, |
a2a8927a XL |
17 | |
18 | /// Whether this intrinsic is only available on A64. | |
19 | pub a64_only: bool, | |
c295e0f8 XL |
20 | } |
21 | ||
22 | impl Intrinsic { | |
23 | /// Generates a std::cout for the intrinsics results that will match the | |
f2b60f7d FG |
24 | /// rust debug output format for the return type. The generated line assumes |
25 | /// there is an int i in scope which is the current pass number. | |
c620b35d | 26 | pub fn print_result_c(&self, indentation: Indentation, additional: &str) -> String { |
3c0e092e XL |
27 | let lanes = if self.results.num_vectors() > 1 { |
28 | (0..self.results.num_vectors()) | |
29 | .map(|vector| { | |
30 | format!( | |
31 | r#""{ty}(" << {lanes} << ")""#, | |
32 | ty = self.results.c_single_vector_type(), | |
33 | lanes = (0..self.results.num_lanes()) | |
34 | .map(move |idx| -> std::string::String { | |
35 | format!( | |
36 | "{cast}{lane_fn}(__return_value.val[{vector}], {lane})", | |
37 | cast = self.results.c_promotion(), | |
38 | lane_fn = self.results.get_lane_function(), | |
39 | lane = idx, | |
40 | vector = vector, | |
41 | ) | |
42 | }) | |
43 | .collect::<Vec<_>>() | |
44 | .join(r#" << ", " << "#) | |
45 | ) | |
46 | }) | |
47 | .collect::<Vec<_>>() | |
48 | .join(r#" << ", " << "#) | |
49 | } else if self.results.num_lanes() > 1 { | |
c295e0f8 XL |
50 | (0..self.results.num_lanes()) |
51 | .map(|idx| -> std::string::String { | |
52 | format!( | |
53 | "{cast}{lane_fn}(__return_value, {lane})", | |
54 | cast = self.results.c_promotion(), | |
55 | lane_fn = self.results.get_lane_function(), | |
56 | lane = idx | |
57 | ) | |
58 | }) | |
59 | .collect::<Vec<_>>() | |
60 | .join(r#" << ", " << "#) | |
61 | } else { | |
62 | format!( | |
63 | "{promote}cast<{cast}>(__return_value)", | |
64 | cast = match self.results.kind() { | |
65 | TypeKind::Float if self.results.inner_size() == 32 => "float".to_string(), | |
66 | TypeKind::Float if self.results.inner_size() == 64 => "double".to_string(), | |
67 | TypeKind::Int => format!("int{}_t", self.results.inner_size()), | |
68 | TypeKind::UInt => format!("uint{}_t", self.results.inner_size()), | |
69 | TypeKind::Poly => format!("poly{}_t", self.results.inner_size()), | |
70 | ty => todo!("print_result_c - Unknown type: {:#?}", ty), | |
71 | }, | |
72 | promote = self.results.c_promotion(), | |
73 | ) | |
74 | }; | |
75 | ||
76 | format!( | |
c620b35d | 77 | r#"{indentation}std::cout << "Result {additional}-" << i+1 << ": {ty}" << std::fixed << std::setprecision(150) << {lanes} << "{close}" << std::endl;"#, |
c295e0f8 XL |
78 | ty = if self.results.is_simd() { |
79 | format!("{}(", self.results.c_type()) | |
80 | } else { | |
81 | String::from("") | |
82 | }, | |
83 | close = if self.results.is_simd() { ")" } else { "" }, | |
84 | lanes = lanes, | |
3c0e092e | 85 | additional = additional, |
c295e0f8 XL |
86 | ) |
87 | } | |
88 | ||
f2b60f7d FG |
89 | pub fn generate_loop_c( |
90 | &self, | |
c620b35d | 91 | indentation: Indentation, |
f2b60f7d FG |
92 | additional: &str, |
93 | passes: u32, | |
94 | p64_armv7_workaround: bool, | |
95 | ) -> String { | |
c620b35d | 96 | let body_indentation = indentation.nested(); |
f2b60f7d | 97 | format!( |
c620b35d FG |
98 | "{indentation}for (int i=0; i<{passes}; i++) {{\n\ |
99 | {loaded_args}\ | |
100 | {body_indentation}auto __return_value = {intrinsic_call}({args});\n\ | |
101 | {print_result}\n\ | |
102 | {indentation}}}", | |
103 | loaded_args = self | |
104 | .arguments | |
105 | .load_values_c(body_indentation, p64_armv7_workaround), | |
f2b60f7d FG |
106 | intrinsic_call = self.name, |
107 | args = self.arguments.as_call_param_c(), | |
c620b35d | 108 | print_result = self.print_result_c(body_indentation, additional) |
f2b60f7d FG |
109 | ) |
110 | } | |
111 | ||
c620b35d FG |
112 | pub fn generate_loop_rust( |
113 | &self, | |
114 | indentation: Indentation, | |
115 | additional: &str, | |
116 | passes: u32, | |
117 | ) -> String { | |
3c0e092e XL |
118 | let constraints = self.arguments.as_constraint_parameters_rust(); |
119 | let constraints = if !constraints.is_empty() { | |
9ffffee4 | 120 | format!("::<{constraints}>") |
3c0e092e XL |
121 | } else { |
122 | constraints | |
123 | }; | |
124 | ||
c620b35d FG |
125 | let indentation2 = indentation.nested(); |
126 | let indentation3 = indentation2.nested(); | |
c295e0f8 | 127 | format!( |
c620b35d FG |
128 | "{indentation}for i in 0..{passes} {{\n\ |
129 | {indentation2}unsafe {{\n\ | |
130 | {loaded_args}\ | |
131 | {indentation3}let __return_value = {intrinsic_call}{const}({args});\n\ | |
132 | {indentation3}println!(\"Result {additional}-{{}}: {{:.150?}}\", i + 1, __return_value);\n\ | |
133 | {indentation2}}}\n\ | |
134 | {indentation}}}", | |
135 | loaded_args = self.arguments.load_values_rust(indentation3), | |
c295e0f8 | 136 | intrinsic_call = self.name, |
f2b60f7d FG |
137 | const = constraints, |
138 | args = self.arguments.as_call_param_rust(), | |
139 | additional = additional, | |
c295e0f8 XL |
140 | ) |
141 | } | |
142 | } |