Skip to content

Commit ac7071e

Browse files
feat: add C testfile compilation mechanism to loongarch
1 parent 1a488a9 commit ac7071e

File tree

3 files changed

+105
-2
lines changed

3 files changed

+105
-2
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
use crate::common::cli::ProcessedCli;
2+
use crate::common::compile_c::{CompilationCommandBuilder, CppCompilation};
3+
4+
pub fn build_cpp_compilation(config: &ProcessedCli) -> Option<CppCompilation> {
5+
let cpp_compiler = config.cpp_compiler.as_ref()?;
6+
7+
// -ffp-contract=off emulates Rust's approach of not fusing separate mul-add operations
8+
let mut command = CompilationCommandBuilder::new()
9+
.set_compiler(cpp_compiler)
10+
.set_target(&config.target)
11+
.set_opt_level("2")
12+
.set_cxx_toolchain_dir(config.cxx_toolchain_dir.as_deref())
13+
.set_project_root("c_programs")
14+
.add_extra_flags(vec![
15+
"-ffp-contract=off",
16+
"-Wno-narrowing",
17+
"-mlasx",
18+
"-mlsx",
19+
"-mfrecipe",
20+
]);
21+
22+
if !cpp_compiler.contains("clang") {
23+
command = command.add_extra_flag("-flax-vector-conversions");
24+
}
25+
26+
let cpp_compiler = command.into_cpp_compilation();
27+
28+
Some(cpp_compiler)
29+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
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 `stdarch-gen-loongarch/lsx.spec` and `stdarch-gen-loongarch/lasx.spec`,
6+
{line_prefix}published under the same license as the `intrinsic-test` crate.\n
7+
"
8+
)
9+
}

crates/intrinsic-test/src/loongarch/mod.rs

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
mod compile;
2+
mod config;
13
mod intrinsic;
24
mod parser;
35
mod types;
@@ -6,12 +8,14 @@ use std::fs::{self, File};
68

79
use rayon::prelude::*;
810

9-
use crate::common::SupportedArchitectureTest;
1011
use crate::common::cli::ProcessedCli;
1112
use crate::common::compare::compare_outputs;
13+
use crate::common::gen_c::{write_main_cpp, write_mod_cpp};
1214
use crate::common::intrinsic_helpers::TypeKind;
15+
use crate::common::{SupportedArchitectureTest, chunk_info};
1316

1417
use crate::common::intrinsic::Intrinsic;
18+
use crate::loongarch::config::build_notices;
1519
use crate::loongarch::parser::get_loongson_intrinsics;
1620
use intrinsic::LoongArchIntrinsicType;
1721

@@ -42,7 +46,68 @@ impl SupportedArchitectureTest for LoongArchArchitectureTest {
4246
}
4347

4448
fn build_c_file(&self) -> bool {
45-
unimplemented!("build_c_file of LoongArchIntrinsicType is not defined!")
49+
let c_target = "loongarch";
50+
let platform_headers = &["lasxintrin.h", "lsxintrin.h"];
51+
52+
let (chunk_size, chunk_count) = chunk_info(self.intrinsics.len());
53+
54+
let cpp_compiler_wrapped = compile::build_cpp_compilation(&self.cli_options);
55+
56+
let notice = &build_notices("// ");
57+
fs::create_dir_all("c_programs").unwrap();
58+
self.intrinsics
59+
.par_chunks(chunk_size)
60+
.enumerate()
61+
.map(|(i, chunk)| {
62+
let c_filename = format!("c_programs/mod_{i}.cpp");
63+
let mut file = File::create(&c_filename).unwrap();
64+
write_mod_cpp(&mut file, notice, c_target, platform_headers, chunk).unwrap();
65+
66+
// compile this cpp file into a .o file.
67+
//
68+
// This is done because `cpp_compiler_wrapped` is None when
69+
// the --generate-only flag is passed
70+
if let Some(cpp_compiler) = cpp_compiler_wrapped.as_ref() {
71+
let output = cpp_compiler
72+
.compile_object_file(&format!("mod_{i}.cpp"), &format!("mod_{i}.o"))?;
73+
assert!(output.status.success(), "{output:?}");
74+
}
75+
76+
Ok(())
77+
})
78+
.collect::<Result<(), std::io::Error>>()
79+
.unwrap();
80+
81+
let mut file = File::create("c_programs/main.cpp").unwrap();
82+
write_main_cpp(
83+
&mut file,
84+
c_target,
85+
"\n",
86+
self.intrinsics.iter().map(|i| i.name.as_str()),
87+
)
88+
.unwrap();
89+
90+
// This is done because `cpp_compiler_wrapped` is None when
91+
// the --generate-only flag is passed
92+
if let Some(cpp_compiler) = cpp_compiler_wrapped.as_ref() {
93+
// compile this cpp file into a .o file
94+
info!("compiling main.cpp");
95+
let output = cpp_compiler
96+
.compile_object_file("main.cpp", "intrinsic-test-programs.o")
97+
.unwrap();
98+
assert!(output.status.success(), "{output:?}");
99+
100+
let object_files = (0..chunk_count)
101+
.map(|i| format!("mod_{i}.o"))
102+
.chain(["intrinsic-test-programs.o".to_owned()]);
103+
104+
let output = cpp_compiler
105+
.link_executable(object_files, "intrinsic-test-programs")
106+
.unwrap();
107+
assert!(output.status.success(), "{output:?}");
108+
}
109+
110+
true
46111
}
47112

48113
fn build_rust_file(&self) -> bool {

0 commit comments

Comments
 (0)