blob: 6aaa49ff97f9bc1ebfbf099969b74d993bb5c200 [file] [log] [blame]
mod compile;
mod config;
mod intrinsic;
mod json_parser;
mod types;
use crate::common::SupportedArchitectureTest;
use crate::common::cli::ProcessedCli;
use crate::common::compare::compare_outputs;
use crate::common::gen_rust::compile_rust_programs;
use crate::common::intrinsic::{Intrinsic, IntrinsicDefinition};
use crate::common::intrinsic_helpers::TypeKind;
use crate::common::write_file::{write_c_testfiles, write_rust_testfiles};
use compile::compile_c_arm;
use config::{AARCH_CONFIGURATIONS, F16_FORMATTING_DEF, POLY128_OSTREAM_DEF, build_notices};
use intrinsic::ArmIntrinsicType;
use json_parser::get_neon_intrinsics;
pub struct ArmArchitectureTest {
intrinsics: Vec<Intrinsic<ArmIntrinsicType>>,
cli_options: ProcessedCli,
}
impl SupportedArchitectureTest for ArmArchitectureTest {
fn create(cli_options: ProcessedCli) -> Box<Self> {
let a32 = cli_options.target.contains("v7");
let mut intrinsics = get_neon_intrinsics(&cli_options.filename, &cli_options.target)
.expect("Error parsing input file");
intrinsics.sort_by(|a, b| a.name.cmp(&b.name));
let mut intrinsics = intrinsics
.into_iter()
// Not sure how we would compare intrinsic that returns void.
.filter(|i| i.results.kind() != TypeKind::Void)
.filter(|i| i.results.kind() != TypeKind::BFloat)
.filter(|i| !i.arguments.iter().any(|a| a.ty.kind() == TypeKind::BFloat))
// Skip pointers for now, we would probably need to look at the return
// type to work out how many elements we need to point to.
.filter(|i| !i.arguments.iter().any(|a| a.is_ptr()))
.filter(|i| !i.arguments.iter().any(|a| a.ty.inner_size() == 128))
.filter(|i| !cli_options.skip.contains(&i.name))
.filter(|i| !(a32 && i.arch_tags == vec!["A64".to_string()]))
.collect::<Vec<_>>();
intrinsics.dedup();
Box::new(Self {
intrinsics,
cli_options,
})
}
fn build_c_file(&self) -> bool {
let compiler = self.cli_options.cpp_compiler.as_deref();
let target = &self.cli_options.target;
let cxx_toolchain_dir = self.cli_options.cxx_toolchain_dir.as_deref();
let c_target = "aarch64";
let intrinsics_name_list = write_c_testfiles(
&self
.intrinsics
.iter()
.map(|i| i as &dyn IntrinsicDefinition<_>)
.collect::<Vec<_>>(),
target,
c_target,
&["arm_neon.h", "arm_acle.h", "arm_fp16.h"],
&build_notices("// "),
&[POLY128_OSTREAM_DEF],
);
match compiler {
None => true,
Some(compiler) => compile_c_arm(
intrinsics_name_list.as_slice(),
compiler,
target,
cxx_toolchain_dir,
),
}
}
fn build_rust_file(&self) -> bool {
let rust_target = if self.cli_options.target.contains("v7") {
"arm"
} else {
"aarch64"
};
let target = &self.cli_options.target;
let toolchain = self.cli_options.toolchain.as_deref();
let linker = self.cli_options.linker.as_deref();
let intrinsics_name_list = write_rust_testfiles(
self.intrinsics
.iter()
.map(|i| i as &dyn IntrinsicDefinition<_>)
.collect::<Vec<_>>(),
rust_target,
&build_notices("// "),
F16_FORMATTING_DEF,
AARCH_CONFIGURATIONS,
);
compile_rust_programs(intrinsics_name_list, toolchain, target, linker)
}
fn compare_outputs(&self) -> bool {
if let Some(ref toolchain) = self.cli_options.toolchain {
let intrinsics_name_list = self
.intrinsics
.iter()
.map(|i| i.name.clone())
.collect::<Vec<_>>();
compare_outputs(
&intrinsics_name_list,
toolchain,
&self.cli_options.c_runner,
&self.cli_options.target,
)
} else {
true
}
}
}