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