Skip to content

Commit 51bfc43

Browse files
jacobbramleyAmanieu
authored andcommitted
Improve intrinsic-test output formatting.
This change is simple, but makes the generated tests much easier to follow (and debug).
1 parent 1754ded commit 51bfc43

File tree

5 files changed

+132
-63
lines changed

5 files changed

+132
-63
lines changed

stdarch/crates/intrinsic-test/src/argument.rs

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::ops::Range;
22

3+
use crate::format::Indentation;
34
use crate::json_parser::ArgPrep;
45
use crate::types::{IntrinsicType, TypeKind};
56
use crate::Language;
@@ -169,15 +170,15 @@ impl ArgumentList {
169170
/// Creates a line for each argument that initializes an array for C from which `loads` argument
170171
/// values can be loaded as a sliding window.
171172
/// e.g `const int32x2_t a_vals = {0x3effffff, 0x3effffff, 0x3f7fffff}`, if loads=2.
172-
pub fn gen_arglists_c(&self, loads: u32) -> String {
173+
pub fn gen_arglists_c(&self, indentation: Indentation, loads: u32) -> String {
173174
self.iter()
174175
.filter_map(|arg| {
175176
(!arg.has_constraint()).then(|| {
176177
format!(
177-
"const {ty} {name}_vals[] = {values};",
178+
"{indentation}const {ty} {name}_vals[] = {values};",
178179
ty = arg.ty.c_scalar_type(),
179180
name = arg.name,
180-
values = arg.ty.populate_random(loads, &Language::C)
181+
values = arg.ty.populate_random(indentation, loads, &Language::C)
181182
)
182183
})
183184
})
@@ -187,17 +188,17 @@ impl ArgumentList {
187188

188189
/// Creates a line for each argument that initializes an array for Rust from which `loads` argument
189190
/// values can be loaded as a sliding window, e.g `const A_VALS: [u32; 20] = [...];`
190-
pub fn gen_arglists_rust(&self, loads: u32) -> String {
191+
pub fn gen_arglists_rust(&self, indentation: Indentation, loads: u32) -> String {
191192
self.iter()
192193
.filter_map(|arg| {
193194
(!arg.has_constraint()).then(|| {
194195
format!(
195-
"{bind} {name}: [{ty}; {load_size}] = {values};",
196+
"{indentation}{bind} {name}: [{ty}; {load_size}] = {values};",
196197
bind = arg.rust_vals_array_binding(),
197198
name = arg.rust_vals_array_name(),
198199
ty = arg.ty.rust_scalar_type(),
199200
load_size = arg.ty.num_lanes() * arg.ty.num_vectors() + loads - 1,
200-
values = arg.ty.populate_random(loads, &Language::Rust)
201+
values = arg.ty.populate_random(indentation, loads, &Language::Rust)
201202
)
202203
})
203204
})
@@ -208,7 +209,7 @@ impl ArgumentList {
208209
/// Creates a line for each argument that initializes the argument from an array `[arg]_vals` at
209210
/// an offset `i` using a load intrinsic, in C.
210211
/// e.g `uint8x8_t a = vld1_u8(&a_vals[i]);`
211-
pub fn load_values_c(&self, p64_armv7_workaround: bool) -> String {
212+
pub fn load_values_c(&self, indentation: Indentation, p64_armv7_workaround: bool) -> String {
212213
self.iter()
213214
.filter_map(|arg| {
214215
// The ACLE doesn't support 64-bit polynomial loads on Armv7
@@ -221,7 +222,7 @@ impl ArgumentList {
221222

222223
(!arg.has_constraint()).then(|| {
223224
format!(
224-
"{ty} {name} = {open_cast}{load}(&{name}_vals[i]){close_cast};",
225+
"{indentation}{ty} {name} = {open_cast}{load}(&{name}_vals[i]){close_cast};\n",
225226
ty = arg.to_c_type(),
226227
name = arg.name,
227228
load = if arg.is_simd() {
@@ -242,19 +243,18 @@ impl ArgumentList {
242243
)
243244
})
244245
})
245-
.collect::<Vec<_>>()
246-
.join("\n ")
246+
.collect()
247247
}
248248

249249
/// Creates a line for each argument that initializes the argument from array `[ARG]_VALS` at
250250
/// an offset `i` using a load intrinsic, in Rust.
251251
/// e.g `let a = vld1_u8(A_VALS.as_ptr().offset(i));`
252-
pub fn load_values_rust(&self) -> String {
252+
pub fn load_values_rust(&self, indentation: Indentation) -> String {
253253
self.iter()
254254
.filter_map(|arg| {
255255
(!arg.has_constraint()).then(|| {
256256
format!(
257-
"let {name} = {load}({vals_name}.as_ptr().offset(i));",
257+
"{indentation}let {name} = {load}({vals_name}.as_ptr().offset(i));\n",
258258
name = arg.name,
259259
vals_name = arg.rust_vals_array_name(),
260260
load = if arg.is_simd() {
@@ -265,8 +265,7 @@ impl ArgumentList {
265265
)
266266
})
267267
})
268-
.collect::<Vec<_>>()
269-
.join("\n ")
268+
.collect()
270269
}
271270

272271
pub fn iter(&self) -> std::slice::Iter<'_, Argument> {
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//! Basic code formatting tools.
2+
//!
3+
//! We don't need perfect formatting for the generated tests, but simple indentation can make
4+
//! debugging a lot easier.
5+
6+
#[derive(Copy, Clone, Debug)]
7+
pub struct Indentation(u32);
8+
9+
impl std::default::Default for Indentation {
10+
fn default() -> Self {
11+
Self(0)
12+
}
13+
}
14+
15+
impl Indentation {
16+
pub fn nested(self) -> Self {
17+
Self(self.0 + 1)
18+
}
19+
}
20+
21+
impl std::fmt::Display for Indentation {
22+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
23+
for _ in 0..self.0 {
24+
write!(f, " ")?;
25+
}
26+
Ok(())
27+
}
28+
}

stdarch/crates/intrinsic-test/src/intrinsic.rs

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::format::Indentation;
12
use crate::types::{IntrinsicType, TypeKind};
23

34
use super::argument::ArgumentList;
@@ -22,7 +23,7 @@ impl Intrinsic {
2223
/// Generates a std::cout for the intrinsics results that will match the
2324
/// rust debug output format for the return type. The generated line assumes
2425
/// there is an int i in scope which is the current pass number.
25-
pub fn print_result_c(&self, additional: &str) -> String {
26+
pub fn print_result_c(&self, indentation: Indentation, additional: &str) -> String {
2627
let lanes = if self.results.num_vectors() > 1 {
2728
(0..self.results.num_vectors())
2829
.map(|vector| {
@@ -73,7 +74,7 @@ impl Intrinsic {
7374
};
7475

7576
format!(
76-
r#"std::cout << "Result {additional}-" << i+1 << ": {ty}" << std::fixed << std::setprecision(150) << {lanes} << "{close}" << std::endl;"#,
77+
r#"{indentation}std::cout << "Result {additional}-" << i+1 << ": {ty}" << std::fixed << std::setprecision(150) << {lanes} << "{close}" << std::endl;"#,
7778
ty = if self.results.is_simd() {
7879
format!("{}(", self.results.c_type())
7980
} else {
@@ -87,44 +88,51 @@ impl Intrinsic {
8788

8889
pub fn generate_loop_c(
8990
&self,
91+
indentation: Indentation,
9092
additional: &str,
9193
passes: u32,
9294
p64_armv7_workaround: bool,
9395
) -> String {
96+
let body_indentation = indentation.nested();
9497
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),
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),
103106
intrinsic_call = self.name,
104107
args = self.arguments.as_call_param_c(),
105-
print_result = self.print_result_c(additional)
108+
print_result = self.print_result_c(body_indentation, additional)
106109
)
107110
}
108111

109-
pub fn generate_loop_rust(&self, additional: &str, passes: u32) -> String {
112+
pub fn generate_loop_rust(
113+
&self,
114+
indentation: Indentation,
115+
additional: &str,
116+
passes: u32,
117+
) -> String {
110118
let constraints = self.arguments.as_constraint_parameters_rust();
111119
let constraints = if !constraints.is_empty() {
112120
format!("::<{constraints}>")
113121
} else {
114122
constraints
115123
};
116124

125+
let indentation2 = indentation.nested();
126+
let indentation3 = indentation2.nested();
117127
format!(
118-
r#" {{
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-
}}
126-
}}"#,
127-
loaded_args = self.arguments.load_values_rust(),
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),
128136
intrinsic_call = self.name,
129137
const = constraints,
130138
args = self.arguments.as_call_param_rust(),

stdarch/crates/intrinsic-test/src/main.rs

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ use rayon::prelude::*;
1313
use types::TypeKind;
1414

1515
use crate::argument::Argument;
16+
use crate::format::Indentation;
1617
use crate::json_parser::get_neon_intrinsics;
1718

1819
mod argument;
20+
mod format;
1921
mod intrinsic;
2022
mod json_parser;
2123
mod types;
@@ -31,6 +33,7 @@ pub enum Language {
3133
}
3234

3335
fn gen_code_c(
36+
indentation: Indentation,
3437
intrinsic: &Intrinsic,
3538
constraints: &[&Argument],
3639
name: String,
@@ -43,27 +46,29 @@ fn gen_code_c(
4346
.map(|c| c.to_range())
4447
.flat_map(|r| r.into_iter());
4548

49+
let body_indentation = indentation.nested();
4650
range
4751
.map(|i| {
4852
format!(
49-
r#" {{
50-
{ty} {name} = {val};
51-
{pass}
52-
}}"#,
53+
"{indentation}{{\n\
54+
{body_indentation}{ty} {name} = {val};\n\
55+
{pass}\n\
56+
{indentation}}}",
5357
name = current.name,
5458
ty = current.ty.c_type(),
5559
val = i,
5660
pass = gen_code_c(
61+
body_indentation,
5762
intrinsic,
5863
constraints,
5964
format!("{name}-{i}"),
6065
p64_armv7_workaround
6166
)
6267
)
6368
})
64-
.collect()
69+
.join("\n")
6570
} else {
66-
intrinsic.generate_loop_c(&name, PASSES, p64_armv7_workaround)
71+
intrinsic.generate_loop_c(indentation, &name, PASSES, p64_armv7_workaround)
6772
}
6873
}
6974

@@ -79,6 +84,7 @@ fn generate_c_program(
7984
.filter(|i| i.has_constraint())
8085
.collect_vec();
8186

87+
let indentation = Indentation::default();
8288
format!(
8389
r#"{notices}{header_files}
8490
#include <iostream>
@@ -119,8 +125,9 @@ int main(int argc, char **argv) {{
119125
.map(|header| format!("#include <{header}>"))
120126
.collect::<Vec<_>>()
121127
.join("\n"),
122-
arglists = intrinsic.arguments.gen_arglists_c(PASSES),
128+
arglists = intrinsic.arguments.gen_arglists_c(indentation, PASSES),
123129
passes = gen_code_c(
130+
indentation.nested(),
124131
intrinsic,
125132
constraints.as_slice(),
126133
Default::default(),
@@ -129,30 +136,41 @@ int main(int argc, char **argv) {{
129136
)
130137
}
131138

132-
fn gen_code_rust(intrinsic: &Intrinsic, constraints: &[&Argument], name: String) -> String {
139+
fn gen_code_rust(
140+
indentation: Indentation,
141+
intrinsic: &Intrinsic,
142+
constraints: &[&Argument],
143+
name: String,
144+
) -> String {
133145
if let Some((current, constraints)) = constraints.split_last() {
134146
let range = current
135147
.constraints
136148
.iter()
137149
.map(|c| c.to_range())
138150
.flat_map(|r| r.into_iter());
139151

152+
let body_indentation = indentation.nested();
140153
range
141154
.map(|i| {
142155
format!(
143-
r#" {{
144-
const {name}: {ty} = {val};
145-
{pass}
146-
}}"#,
156+
"{indentation}{{\n\
157+
{body_indentation}const {name}: {ty} = {val};\n\
158+
{pass}\n\
159+
{indentation}}}",
147160
name = current.name,
148161
ty = current.ty.rust_type(),
149162
val = i,
150-
pass = gen_code_rust(intrinsic, constraints, format!("{name}-{i}"))
163+
pass = gen_code_rust(
164+
body_indentation,
165+
intrinsic,
166+
constraints,
167+
format!("{name}-{i}")
168+
)
151169
)
152170
})
153-
.collect()
171+
.join("\n")
154172
} else {
155-
intrinsic.generate_loop_rust(&name, PASSES)
173+
intrinsic.generate_loop_rust(indentation, &name, PASSES)
156174
}
157175
}
158176

@@ -163,6 +181,7 @@ fn generate_rust_program(notices: &str, intrinsic: &Intrinsic, a32: bool) -> Str
163181
.filter(|i| i.has_constraint())
164182
.collect_vec();
165183

184+
let indentation = Indentation::default();
166185
format!(
167186
r#"{notices}#![feature(simd_ffi)]
168187
#![feature(link_llvm_intrinsics)]
@@ -183,8 +202,15 @@ fn main() {{
183202
}}
184203
"#,
185204
target_arch = if a32 { "arm" } else { "aarch64" },
186-
arglists = intrinsic.arguments.gen_arglists_rust(PASSES),
187-
passes = gen_code_rust(intrinsic, &constraints, Default::default())
205+
arglists = intrinsic
206+
.arguments
207+
.gen_arglists_rust(indentation.nested(), PASSES),
208+
passes = gen_code_rust(
209+
indentation.nested(),
210+
intrinsic,
211+
&constraints,
212+
Default::default()
213+
)
188214
)
189215
}
190216

0 commit comments

Comments
 (0)