Skip to content

Commit dcddb44

Browse files
authored
Merge pull request rust-lang#1914 from folkertdev/architecture-test
`intrinsic-test`: make `build_{c, rust}_file` generic
2 parents d5bed4b + 4b549a7 commit dcddb44

File tree

11 files changed

+484
-390
lines changed

11 files changed

+484
-390
lines changed

library/stdarch/Cargo.lock

Lines changed: 152 additions & 65 deletions
Large diffs are not rendered by default.

library/stdarch/crates/intrinsic-test/src/arm/config.rs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1-
pub fn build_notices(line_prefix: &str) -> String {
2-
format!(
3-
"\
4-
{line_prefix}This is a transient test file, not intended for distribution. Some aspects of the
5-
{line_prefix}test are derived from a JSON specification, published under the same license as the
6-
{line_prefix}`intrinsic-test` crate.\n
7-
"
8-
)
9-
}
1+
pub const NOTICE: &str = "\
2+
// This is a transient test file, not intended for distribution. Some aspects of the
3+
// test are derived from a JSON specification, published under the same license as the
4+
// `intrinsic-test` crate.\n";
5+
6+
pub const POLY128_OSTREAM_DECL: &str = r#"
7+
#ifdef __aarch64__
8+
std::ostream& operator<<(std::ostream& os, poly128_t value);
9+
#endif
10+
"#;
1011

11-
pub const POLY128_OSTREAM_DEF: &str = r#"std::ostream& operator<<(std::ostream& os, poly128_t value) {
12+
pub const POLY128_OSTREAM_DEF: &str = r#"
13+
#ifdef __aarch64__
14+
std::ostream& operator<<(std::ostream& os, poly128_t value) {
1215
std::stringstream temp;
1316
do {
1417
int n = value % 10;
@@ -19,7 +22,9 @@ pub const POLY128_OSTREAM_DEF: &str = r#"std::ostream& operator<<(std::ostream&
1922
std::string res(tempstr.rbegin(), tempstr.rend());
2023
os << res;
2124
return os;
22-
}"#;
25+
}
26+
#endif
27+
"#;
2328

2429
// Format f16 values (and vectors containing them) in a way that is consistent with C.
2530
pub const F16_FORMATTING_DEF: &str = r#"
@@ -118,4 +123,10 @@ pub const AARCH_CONFIGURATIONS: &str = r#"
118123
#![cfg_attr(any(target_arch = "aarch64", target_arch = "arm64ec"), feature(stdarch_neon_ftts))]
119124
#![feature(fmt_helpers_for_derive)]
120125
#![feature(stdarch_neon_f16)]
126+
127+
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))]
128+
use core::arch::aarch64::*;
129+
130+
#[cfg(target_arch = "arm")]
131+
use core::arch::arm::*;
121132
"#;
Lines changed: 1 addition & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
use crate::common::argument::ArgumentList;
2-
use crate::common::indentation::Indentation;
3-
use crate::common::intrinsic::{Intrinsic, IntrinsicDefinition};
4-
use crate::common::intrinsic_helpers::{IntrinsicType, IntrinsicTypeDefinition, Sign, TypeKind};
1+
use crate::common::intrinsic_helpers::IntrinsicType;
52
use std::ops::{Deref, DerefMut};
63

74
#[derive(Debug, Clone, PartialEq)]
@@ -23,83 +20,3 @@ impl DerefMut for ArmIntrinsicType {
2320
&mut self.data
2421
}
2522
}
26-
27-
impl IntrinsicDefinition<ArmIntrinsicType> for Intrinsic<ArmIntrinsicType> {
28-
fn arguments(&self) -> ArgumentList<ArmIntrinsicType> {
29-
self.arguments.clone()
30-
}
31-
32-
fn results(&self) -> ArmIntrinsicType {
33-
self.results.clone()
34-
}
35-
36-
fn name(&self) -> String {
37-
self.name.clone()
38-
}
39-
40-
/// Generates a std::cout for the intrinsics results that will match the
41-
/// rust debug output format for the return type. The generated line assumes
42-
/// there is an int i in scope which is the current pass number.
43-
fn print_result_c(&self, indentation: Indentation, additional: &str) -> String {
44-
let lanes = if self.results().num_vectors() > 1 {
45-
(0..self.results().num_vectors())
46-
.map(|vector| {
47-
format!(
48-
r#""{ty}(" << {lanes} << ")""#,
49-
ty = self.results().c_single_vector_type(),
50-
lanes = (0..self.results().num_lanes())
51-
.map(move |idx| -> std::string::String {
52-
format!(
53-
"{cast}{lane_fn}(__return_value.val[{vector}], {lane})",
54-
cast = self.results().c_promotion(),
55-
lane_fn = self.results().get_lane_function(),
56-
lane = idx,
57-
vector = vector,
58-
)
59-
})
60-
.collect::<Vec<_>>()
61-
.join(r#" << ", " << "#)
62-
)
63-
})
64-
.collect::<Vec<_>>()
65-
.join(r#" << ", " << "#)
66-
} else if self.results().num_lanes() > 1 {
67-
(0..self.results().num_lanes())
68-
.map(|idx| -> std::string::String {
69-
format!(
70-
"{cast}{lane_fn}(__return_value, {lane})",
71-
cast = self.results().c_promotion(),
72-
lane_fn = self.results().get_lane_function(),
73-
lane = idx
74-
)
75-
})
76-
.collect::<Vec<_>>()
77-
.join(r#" << ", " << "#)
78-
} else {
79-
format!(
80-
"{promote}cast<{cast}>(__return_value)",
81-
cast = match self.results.kind() {
82-
TypeKind::Float if self.results().inner_size() == 16 => "float16_t".to_string(),
83-
TypeKind::Float if self.results().inner_size() == 32 => "float".to_string(),
84-
TypeKind::Float if self.results().inner_size() == 64 => "double".to_string(),
85-
TypeKind::Int(Sign::Signed) => format!("int{}_t", self.results().inner_size()),
86-
TypeKind::Int(Sign::Unsigned) =>
87-
format!("uint{}_t", self.results().inner_size()),
88-
TypeKind::Poly => format!("poly{}_t", self.results().inner_size()),
89-
ty => todo!("print_result_c - Unknown type: {:#?}", ty),
90-
},
91-
promote = self.results().c_promotion(),
92-
)
93-
};
94-
95-
format!(
96-
r#"{indentation}std::cout << "Result {additional}-" << i+1 << ": {ty}" << std::fixed << std::setprecision(150) << {lanes} << "{close}" << std::endl;"#,
97-
ty = if self.results().is_simd() {
98-
format!("{}(", self.results().c_type())
99-
} else {
100-
String::from("")
101-
},
102-
close = if self.results.is_simd() { ")" } else { "" },
103-
)
104-
}
105-
}

library/stdarch/crates/intrinsic-test/src/arm/mod.rs

Lines changed: 27 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,11 @@ mod intrinsic;
55
mod json_parser;
66
mod types;
77

8-
use std::fs::{self, File};
9-
10-
use rayon::prelude::*;
11-
8+
use crate::common::SupportedArchitectureTest;
129
use crate::common::cli::ProcessedCli;
13-
use crate::common::compare::compare_outputs;
14-
use crate::common::gen_c::{write_main_cpp, write_mod_cpp};
15-
use crate::common::gen_rust::{
16-
compile_rust_programs, write_bin_cargo_toml, write_lib_cargo_toml, write_lib_rs, write_main_rs,
17-
};
10+
use crate::common::compile_c::CppCompilation;
1811
use crate::common::intrinsic::Intrinsic;
1912
use crate::common::intrinsic_helpers::TypeKind;
20-
use crate::common::{SupportedArchitectureTest, chunk_info};
21-
use config::{AARCH_CONFIGURATIONS, F16_FORMATTING_DEF, POLY128_OSTREAM_DEF, build_notices};
2213
use intrinsic::ArmIntrinsicType;
2314
use json_parser::get_neon_intrinsics;
2415

@@ -28,7 +19,30 @@ pub struct ArmArchitectureTest {
2819
}
2920

3021
impl SupportedArchitectureTest for ArmArchitectureTest {
31-
fn create(cli_options: ProcessedCli) -> Box<Self> {
22+
type IntrinsicImpl = ArmIntrinsicType;
23+
24+
fn cli_options(&self) -> &ProcessedCli {
25+
&self.cli_options
26+
}
27+
28+
fn intrinsics(&self) -> &[Intrinsic<ArmIntrinsicType>] {
29+
&self.intrinsics
30+
}
31+
32+
const NOTICE: &str = config::NOTICE;
33+
34+
const PLATFORM_C_HEADERS: &[&str] = &["arm_neon.h", "arm_acle.h", "arm_fp16.h"];
35+
const PLATFORM_C_DEFINITIONS: &str = config::POLY128_OSTREAM_DEF;
36+
const PLATFORM_C_FORWARD_DECLARATIONS: &str = config::POLY128_OSTREAM_DECL;
37+
38+
const PLATFORM_RUST_DEFINITIONS: &str = config::F16_FORMATTING_DEF;
39+
const PLATFORM_RUST_CFGS: &str = config::AARCH_CONFIGURATIONS;
40+
41+
fn cpp_compilation(&self) -> Option<CppCompilation> {
42+
compile::build_cpp_compilation(&self.cli_options)
43+
}
44+
45+
fn create(cli_options: ProcessedCli) -> Self {
3246
let a32 = cli_options.target.contains("v7");
3347
let mut intrinsics = get_neon_intrinsics(&cli_options.filename, &cli_options.target)
3448
.expect("Error parsing input file");
@@ -50,149 +64,9 @@ impl SupportedArchitectureTest for ArmArchitectureTest {
5064
.collect::<Vec<_>>();
5165
intrinsics.dedup();
5266

53-
Box::new(Self {
67+
Self {
5468
intrinsics,
5569
cli_options,
56-
})
57-
}
58-
59-
fn build_c_file(&self) -> bool {
60-
let c_target = "aarch64";
61-
let platform_headers = &["arm_neon.h", "arm_acle.h", "arm_fp16.h"];
62-
63-
let (chunk_size, chunk_count) = chunk_info(self.intrinsics.len());
64-
65-
let cpp_compiler_wrapped = compile::build_cpp_compilation(&self.cli_options);
66-
67-
let notice = &build_notices("// ");
68-
fs::create_dir_all("c_programs").unwrap();
69-
self.intrinsics
70-
.par_chunks(chunk_size)
71-
.enumerate()
72-
.map(|(i, chunk)| {
73-
let c_filename = format!("c_programs/mod_{i}.cpp");
74-
let mut file = File::create(&c_filename).unwrap();
75-
write_mod_cpp(&mut file, notice, c_target, platform_headers, chunk).unwrap();
76-
77-
// compile this cpp file into a .o file.
78-
//
79-
// This is done because `cpp_compiler_wrapped` is None when
80-
// the --generate-only flag is passed
81-
if let Some(cpp_compiler) = cpp_compiler_wrapped.as_ref() {
82-
let output = cpp_compiler
83-
.compile_object_file(&format!("mod_{i}.cpp"), &format!("mod_{i}.o"))?;
84-
assert!(output.status.success(), "{output:?}");
85-
}
86-
87-
Ok(())
88-
})
89-
.collect::<Result<(), std::io::Error>>()
90-
.unwrap();
91-
92-
let mut file = File::create("c_programs/main.cpp").unwrap();
93-
write_main_cpp(
94-
&mut file,
95-
c_target,
96-
POLY128_OSTREAM_DEF,
97-
self.intrinsics.iter().map(|i| i.name.as_str()),
98-
)
99-
.unwrap();
100-
101-
// This is done because `cpp_compiler_wrapped` is None when
102-
// the --generate-only flag is passed
103-
if let Some(cpp_compiler) = cpp_compiler_wrapped.as_ref() {
104-
// compile this cpp file into a .o file
105-
info!("compiling main.cpp");
106-
let output = cpp_compiler
107-
.compile_object_file("main.cpp", "intrinsic-test-programs.o")
108-
.unwrap();
109-
assert!(output.status.success(), "{output:?}");
110-
111-
let object_files = (0..chunk_count)
112-
.map(|i| format!("mod_{i}.o"))
113-
.chain(["intrinsic-test-programs.o".to_owned()]);
114-
115-
let output = cpp_compiler
116-
.link_executable(object_files, "intrinsic-test-programs")
117-
.unwrap();
118-
assert!(output.status.success(), "{output:?}");
119-
}
120-
121-
true
122-
}
123-
124-
fn build_rust_file(&self) -> bool {
125-
std::fs::create_dir_all("rust_programs/src").unwrap();
126-
127-
let architecture = if self.cli_options.target.contains("v7") {
128-
"arm"
129-
} else {
130-
"aarch64"
131-
};
132-
133-
let (chunk_size, chunk_count) = chunk_info(self.intrinsics.len());
134-
135-
let mut cargo = File::create("rust_programs/Cargo.toml").unwrap();
136-
write_bin_cargo_toml(&mut cargo, chunk_count).unwrap();
137-
138-
let mut main_rs = File::create("rust_programs/src/main.rs").unwrap();
139-
write_main_rs(
140-
&mut main_rs,
141-
chunk_count,
142-
AARCH_CONFIGURATIONS,
143-
"",
144-
self.intrinsics.iter().map(|i| i.name.as_str()),
145-
)
146-
.unwrap();
147-
148-
let target = &self.cli_options.target;
149-
let toolchain = self.cli_options.toolchain.as_deref();
150-
let linker = self.cli_options.linker.as_deref();
151-
152-
let notice = &build_notices("// ");
153-
self.intrinsics
154-
.par_chunks(chunk_size)
155-
.enumerate()
156-
.map(|(i, chunk)| {
157-
std::fs::create_dir_all(format!("rust_programs/mod_{i}/src"))?;
158-
159-
let rust_filename = format!("rust_programs/mod_{i}/src/lib.rs");
160-
trace!("generating `{rust_filename}`");
161-
let mut file = File::create(rust_filename)?;
162-
163-
let cfg = AARCH_CONFIGURATIONS;
164-
let definitions = F16_FORMATTING_DEF;
165-
write_lib_rs(&mut file, architecture, notice, cfg, definitions, chunk)?;
166-
167-
let toml_filename = format!("rust_programs/mod_{i}/Cargo.toml");
168-
trace!("generating `{toml_filename}`");
169-
let mut file = File::create(toml_filename).unwrap();
170-
171-
write_lib_cargo_toml(&mut file, &format!("mod_{i}"))?;
172-
173-
Ok(())
174-
})
175-
.collect::<Result<(), std::io::Error>>()
176-
.unwrap();
177-
178-
compile_rust_programs(toolchain, target, linker)
179-
}
180-
181-
fn compare_outputs(&self) -> bool {
182-
if self.cli_options.toolchain.is_some() {
183-
let intrinsics_name_list = self
184-
.intrinsics
185-
.iter()
186-
.map(|i| i.name.clone())
187-
.collect::<Vec<_>>();
188-
189-
compare_outputs(
190-
&intrinsics_name_list,
191-
&self.cli_options.runner,
192-
&self.cli_options.target,
193-
)
194-
} else {
195-
true
19670
}
19771
}
19872
}

0 commit comments

Comments
 (0)