Skip to content

Commit 3b9d09d

Browse files
moved the C compilation commands into a struct for easier handling
1 parent d395e9c commit 3b9d09d

File tree

3 files changed

+194
-56
lines changed

3 files changed

+194
-56
lines changed

crates/intrinsic-test/src/arm/functions.rs

Lines changed: 52 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use super::config::{AARCH_CONFIGURATIONS, POLY128_OSTREAM_DEF, build_notices};
22
use super::intrinsic::ArmIntrinsicType;
33
use crate::arm::constraint::Constraint;
44
use crate::common::argument::Argument;
5+
use crate::common::compile_c::CompilationCommandBuilder;
56
use crate::common::format::Indentation;
67
use crate::common::gen_c::{compile_c, create_c_filenames, generate_c_program};
78
use crate::common::gen_rust::{compile_rust, create_rust_filenames, generate_rust_program};
@@ -161,72 +162,67 @@ fn generate_rust_program_arm(
161162

162163
fn compile_c_arm(
163164
intrinsics_name_list: &Vec<String>,
164-
filename_mapping: BTreeMap<&String, String>,
165+
_filename_mapping: BTreeMap<&String, String>,
165166
compiler: &str,
166167
target: &str,
167168
cxx_toolchain_dir: Option<&str>,
168169
) -> bool {
169-
let compiler_commands = intrinsics_name_list.iter().map(|intrinsic_name| {
170-
let c_filename = filename_mapping.get(intrinsic_name).unwrap();
171-
let flags = std::env::var("CPPFLAGS").unwrap_or("".into());
172-
let arch_flags = if target.contains("v7") {
173-
"-march=armv8.6-a+crypto+crc+dotprod+fp16"
174-
} else {
175-
"-march=armv8.6-a+crypto+sha3+crc+dotprod+fp16+faminmax+lut"
176-
};
177-
178-
let compiler_command = if target == "aarch64_be-unknown-linux-gnu" {
179-
let Some(cxx_toolchain_dir) = cxx_toolchain_dir else {
180-
panic!(
181-
"When setting `--target aarch64_be-unknown-linux-gnu` the C++ compilers toolchain directory must be set with `--cxx-toolchain-dir <dest>`"
182-
);
170+
let compiler_commands = intrinsics_name_list
171+
.iter()
172+
.map(|intrinsic_name| {
173+
let mut command = CompilationCommandBuilder::new();
174+
if target.contains("v7") {
175+
command.set_arch_flags(vec!["armv8.6-a", "crypto", "crc", "dotprod", "fp16"])
176+
} else {
177+
command.set_arch_flags(vec![
178+
"armv8.6-a",
179+
"crypto",
180+
"crc",
181+
"dotprod",
182+
"fp16",
183+
"sha3",
184+
"faminmax",
185+
"lut"
186+
])
183187
};
184188

185-
/* clang++ cannot link an aarch64_be object file, so we invoke
186-
* aarch64_be-unknown-linux-gnu's C++ linker. This ensures that we
187-
* are testing the intrinsics against LLVM.
188-
*
189-
* Note: setting `--sysroot=<...>` which is the obvious thing to do
190-
* does not work as it gets caught up with `#include_next <stdlib.h>`
191-
* not existing... */
192-
format!(
193-
"{compiler} {flags} {arch_flags} \
194-
-ffp-contract=off \
195-
-Wno-narrowing \
196-
-O2 \
197-
--target=aarch64_be-unknown-linux-gnu \
198-
-I{cxx_toolchain_dir}/include \
199-
-I{cxx_toolchain_dir}/aarch64_be-none-linux-gnu/include \
200-
-I{cxx_toolchain_dir}/aarch64_be-none-linux-gnu/include/c++/14.2.1 \
201-
-I{cxx_toolchain_dir}/aarch64_be-none-linux-gnu/include/c++/14.2.1/aarch64_be-none-linux-gnu \
202-
-I{cxx_toolchain_dir}/aarch64_be-none-linux-gnu/include/c++/14.2.1/backward \
203-
-I{cxx_toolchain_dir}/aarch64_be-none-linux-gnu/libc/usr/include \
204-
-c {c_filename} \
205-
-o c_programs/{intrinsic_name}.o && \
206-
{cxx_toolchain_dir}/bin/aarch64_be-none-linux-gnu-g++ c_programs/{intrinsic_name}.o -o c_programs/{intrinsic_name} && \
207-
rm c_programs/{intrinsic_name}.o",
208-
)
209-
} else {
210-
// -ffp-contract=off emulates Rust's approach of not fusing separate mul-add operations
211-
let base_compiler_command = format!(
212-
"{compiler} {flags} {arch_flags} -o c_programs/{intrinsic_name} {c_filename} -ffp-contract=off -Wno-narrowing -O2"
213-
);
189+
command = command
190+
.set_compiler(compiler)
191+
.set_output_name(intrinsic_name)
192+
.set_target(target)
193+
.set_opt_level("2")
194+
.set_cxx_toolchain_dir(cxx_toolchain_dir)
195+
.set_project_root("c_programs")
196+
.set_input_name(intrinsic_name)
197+
.add_extra_flags(vec!["-ffp-contract=off", "-Wno-narrowing"]);
214198

215-
/* `-target` can be passed to some c++ compilers, however if we want to
216-
* use a c++ compiler does not support this flag we do not want to pass
217-
* the flag. */
218-
if compiler.contains("clang") {
219-
format!("{base_compiler_command} -target {target}")
199+
command = if target == "aarch64_be-unknown-linux-gnu" {
200+
command
201+
.set_linker(
202+
cxx_toolchain_dir.unwrap_or("").to_string()
203+
+ "/bin/aarch64_be-none-linux-gnu-g++",
204+
)
205+
.set_include_paths(vec![
206+
"/include",
207+
"/aarch64_be-none-linux-gnu/include",
208+
"/aarch64_be-none-linux-gnu/include/c++/14.2.1",
209+
"/aarch64_be-none-linux-gnu/include/c++/14.2.1/aarch64_be-none-linux-gnu",
210+
"/aarch64_be-none-linux-gnu/include/c++/14.2.1/backward",
211+
"/aarch64_be-none-linux-gnu/libc/usr/include"
212+
])
220213
} else {
221-
format!("{base_compiler_command} -flax-vector-conversions")
222-
}
223-
};
214+
if compiler.contains("clang") {
215+
command.add_extra_flag(format!("-target {target}").as_str())
216+
} else {
217+
command.add_extra_flag("-flax-vector-conversions")
218+
}
219+
};
224220

225-
compiler_command
226-
})
227-
.collect::<Vec<_>>();
221+
command.as_str()
222+
})
223+
.collect::<Vec<_>>();
228224

229-
compile_c(&compiler_commands)
225+
compile_c(&compiler_commands)
230226
}
231227

232228
pub fn build_c(
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
pub struct CompilationCommandBuilder {
2+
compiler: String,
3+
target: Option<String>,
4+
cxx_toolchain_dir: Option<String>,
5+
arch_flags: Vec<String>,
6+
optimization: String,
7+
include_paths: Vec<String>,
8+
project_root: Option<String>,
9+
output: String,
10+
input: String,
11+
linker: Option<String>,
12+
extra_flags: Vec<String>,
13+
}
14+
15+
impl CompilationCommandBuilder {
16+
pub fn new() -> Self {
17+
Self {
18+
compiler: String::new(),
19+
target: None,
20+
cxx_toolchain_dir: None,
21+
arch_flags: Vec::new(),
22+
optimization: "2".to_string(),
23+
include_paths: Vec::new(),
24+
project_root: None,
25+
output: String::new(),
26+
input: String::new(),
27+
linker: None,
28+
extra_flags: Vec::new(),
29+
}
30+
}
31+
32+
pub fn set_compiler(mut self, compiler: &str) -> Self {
33+
self.compiler = compiler.to_string();
34+
self
35+
}
36+
37+
pub fn set_target(mut self, target: &str) -> Self {
38+
self.target = Some(target.to_string());
39+
self
40+
}
41+
42+
pub fn set_cxx_toolchain_dir(mut self, path: Option<&str>) -> Self {
43+
self.cxx_toolchain_dir = path.map(|p| p.to_string());
44+
self
45+
}
46+
47+
pub fn set_arch_flags(&mut self, flags: Vec<&str>) {
48+
self.arch_flags = flags.iter().map(|v| v.to_string()).collect();
49+
}
50+
51+
pub fn set_opt_level(mut self, optimization: &str) -> Self {
52+
self.optimization = optimization.to_string();
53+
self
54+
}
55+
56+
pub fn set_include_paths(mut self, paths: Vec<&str>) -> Self {
57+
self.include_paths = paths.into_iter().map(|path| path.to_string()).collect();
58+
self
59+
}
60+
61+
pub fn set_project_root(mut self, path: &str) -> Self {
62+
self.project_root = Some(path.to_string());
63+
self
64+
}
65+
66+
pub fn set_output_name(mut self, path: &str) -> Self {
67+
self.output = path.to_string();
68+
self
69+
}
70+
71+
pub fn set_input_name(mut self, path: &str) -> Self {
72+
self.input = path.to_string();
73+
self
74+
}
75+
76+
pub fn set_linker(mut self, linker: String) -> Self {
77+
self.linker = Some(linker);
78+
self.output += ".o";
79+
self
80+
}
81+
82+
pub fn add_extra_flags(mut self, flags: Vec<&str>) -> Self {
83+
let mut flags: Vec<String> = flags.into_iter().map(|f| f.to_string()).collect();
84+
self.extra_flags.append(&mut flags);
85+
self
86+
}
87+
88+
pub fn add_extra_flag(self, flag: &str) -> Self {
89+
self.add_extra_flags(vec![flag])
90+
}
91+
}
92+
93+
impl CompilationCommandBuilder {
94+
pub fn as_str(self) -> String {
95+
let arch_flags = self.arch_flags.join("+");
96+
let flags = std::env::var("CPPFLAGS").unwrap_or("".into());
97+
let project_root = self.project_root.unwrap_or(String::new());
98+
let project_root_str = project_root.as_str();
99+
let mut command = format!(
100+
"{} {flags} -march={arch_flags} \
101+
-O{} \
102+
-o {project_root}/{} \
103+
{project_root}/{}.cpp",
104+
self.compiler, self.optimization, self.output, self.input,
105+
);
106+
107+
command = command + " " + self.extra_flags.join(" ").as_str();
108+
109+
if let (Some(linker), Some(cxx_toolchain_dir)) = (&self.linker, &self.cxx_toolchain_dir) {
110+
if let Some(target) = &self.target {
111+
command = command + " --target=" + target;
112+
}
113+
114+
let include_args = self
115+
.include_paths
116+
.iter()
117+
.map(|path| "--include-directory=".to_string() + cxx_toolchain_dir + path)
118+
.collect::<Vec<_>>()
119+
.join(" ");
120+
121+
command = command
122+
+ " -c "
123+
+ include_args.as_str()
124+
+ " && "
125+
+ linker
126+
+ project_root_str
127+
+ "/"
128+
+ self.output.as_str()
129+
+ " -o "
130+
+ project_root_str
131+
+ "/"
132+
+ self.output.strip_suffix(".o").unwrap()
133+
+ " && rm "
134+
+ project_root_str
135+
+ "/"
136+
+ self.output.as_str();
137+
}
138+
139+
command
140+
}
141+
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::io::Write;
44

55
pub mod argument;
66
pub mod compare;
7+
pub mod compile_c;
78
pub mod format;
89
pub mod gen_c;
910
pub mod gen_rust;

0 commit comments

Comments
 (0)