moved more code generation functionality to common
This commit is contained in:
parent
c01c6ceb87
commit
2a5e678a84
7 changed files with 301 additions and 286 deletions
64
library/stdarch/crates/intrinsic-test/src/arm/compile.rs
Normal file
64
library/stdarch/crates/intrinsic-test/src/arm/compile.rs
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
use crate::common::compile_c::CompilationCommandBuilder;
|
||||
use crate::common::gen_c::compile_c;
|
||||
|
||||
pub fn compile_c_arm(
|
||||
intrinsics_name_list: &Vec<String>,
|
||||
compiler: &str,
|
||||
target: &str,
|
||||
cxx_toolchain_dir: Option<&str>,
|
||||
) -> bool {
|
||||
// -ffp-contract=off emulates Rust's approach of not fusing separate mul-add operations
|
||||
let mut command = CompilationCommandBuilder::new()
|
||||
.add_arch_flags(vec!["armv8.6-a", "crypto", "crc", "dotprod", "fp16"])
|
||||
.set_compiler(compiler)
|
||||
.set_target(target)
|
||||
.set_opt_level("2")
|
||||
.set_cxx_toolchain_dir(cxx_toolchain_dir)
|
||||
.set_project_root("c_programs")
|
||||
.add_extra_flags(vec!["-ffp-contract=off", "-Wno-narrowing"]);
|
||||
|
||||
if !target.contains("v7") {
|
||||
command = command.add_arch_flags(vec!["faminmax", "lut", "sha3"]);
|
||||
}
|
||||
|
||||
/*
|
||||
* clang++ cannot link an aarch64_be object file, so we invoke
|
||||
* aarch64_be-unknown-linux-gnu's C++ linker. This ensures that we
|
||||
* are testing the intrinsics against LLVM.
|
||||
*
|
||||
* Note: setting `--sysroot=<...>` which is the obvious thing to do
|
||||
* does not work as it gets caught up with `#include_next <stdlib.h>`
|
||||
* not existing...
|
||||
*/
|
||||
if target.contains("aarch64_be") {
|
||||
command = command
|
||||
.set_linker(
|
||||
cxx_toolchain_dir.unwrap_or("").to_string() + "/bin/aarch64_be-none-linux-gnu-g++",
|
||||
)
|
||||
.set_include_paths(vec![
|
||||
"/include",
|
||||
"/aarch64_be-none-linux-gnu/include",
|
||||
"/aarch64_be-none-linux-gnu/include/c++/14.2.1",
|
||||
"/aarch64_be-none-linux-gnu/include/c++/14.2.1/aarch64_be-none-linux-gnu",
|
||||
"/aarch64_be-none-linux-gnu/include/c++/14.2.1/backward",
|
||||
"/aarch64_be-none-linux-gnu/libc/usr/include",
|
||||
]);
|
||||
}
|
||||
|
||||
if !compiler.contains("clang") {
|
||||
command = command.add_extra_flag("-flax-vector-conversions");
|
||||
}
|
||||
|
||||
let compiler_commands = intrinsics_name_list
|
||||
.iter()
|
||||
.map(|intrinsic_name| {
|
||||
command
|
||||
.clone()
|
||||
.set_input_name(intrinsic_name)
|
||||
.set_output_name(intrinsic_name)
|
||||
.to_string()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
compile_c(&compiler_commands)
|
||||
}
|
||||
|
|
@ -1,270 +0,0 @@
|
|||
use super::config::{AARCH_CONFIGURATIONS, POLY128_OSTREAM_DEF, build_notices};
|
||||
use super::intrinsic::ArmIntrinsicType;
|
||||
use crate::common::argument::Argument;
|
||||
use crate::common::compile_c::CompilationCommandBuilder;
|
||||
use crate::common::gen_c::{compile_c, create_c_filenames, generate_c_program};
|
||||
use crate::common::gen_rust::{compile_rust, create_rust_filenames, generate_rust_program};
|
||||
use crate::common::indentation::Indentation;
|
||||
use crate::common::intrinsic::{Intrinsic, IntrinsicDefinition};
|
||||
use crate::common::intrinsic_helpers::IntrinsicTypeDefinition;
|
||||
use crate::common::write_file;
|
||||
use itertools::Itertools;
|
||||
use rayon::prelude::*;
|
||||
|
||||
// The number of times each intrinsic will be called.
|
||||
const PASSES: u32 = 20;
|
||||
|
||||
fn gen_code_c(
|
||||
indentation: Indentation,
|
||||
intrinsic: &Intrinsic<ArmIntrinsicType>,
|
||||
constraints: &[&Argument<ArmIntrinsicType>],
|
||||
name: String,
|
||||
target: &str,
|
||||
) -> String {
|
||||
if let Some((current, constraints)) = constraints.split_last() {
|
||||
let range = current
|
||||
.constraint
|
||||
.iter()
|
||||
.map(|c| c.to_range())
|
||||
.flat_map(|r| r.into_iter());
|
||||
|
||||
let body_indentation = indentation.nested();
|
||||
range
|
||||
.map(|i| {
|
||||
format!(
|
||||
"{indentation}{{\n\
|
||||
{body_indentation}{ty} {name} = {val};\n\
|
||||
{pass}\n\
|
||||
{indentation}}}",
|
||||
name = current.name,
|
||||
ty = current.ty.c_type(),
|
||||
val = i,
|
||||
pass = gen_code_c(
|
||||
body_indentation,
|
||||
intrinsic,
|
||||
constraints,
|
||||
format!("{name}-{i}"),
|
||||
target,
|
||||
)
|
||||
)
|
||||
})
|
||||
.join("\n")
|
||||
} else {
|
||||
intrinsic.generate_loop_c(indentation, &name, PASSES, target)
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_c_program_arm(
|
||||
header_files: &[&str],
|
||||
intrinsic: &Intrinsic<ArmIntrinsicType>,
|
||||
target: &str,
|
||||
) -> String {
|
||||
let constraints = intrinsic
|
||||
.arguments
|
||||
.iter()
|
||||
.filter(|&i| i.has_constraint())
|
||||
.collect_vec();
|
||||
|
||||
let indentation = Indentation::default();
|
||||
generate_c_program(
|
||||
build_notices("// ").as_str(),
|
||||
header_files,
|
||||
"aarch64",
|
||||
&[POLY128_OSTREAM_DEF],
|
||||
intrinsic
|
||||
.arguments
|
||||
.gen_arglists_c(indentation, PASSES)
|
||||
.as_str(),
|
||||
gen_code_c(
|
||||
indentation.nested(),
|
||||
intrinsic,
|
||||
constraints.as_slice(),
|
||||
Default::default(),
|
||||
target,
|
||||
)
|
||||
.as_str(),
|
||||
)
|
||||
}
|
||||
|
||||
fn gen_code_rust(
|
||||
indentation: Indentation,
|
||||
intrinsic: &Intrinsic<ArmIntrinsicType>,
|
||||
constraints: &[&Argument<ArmIntrinsicType>],
|
||||
name: String,
|
||||
) -> String {
|
||||
println!("{}", name);
|
||||
if let Some((current, constraints)) = constraints.split_last() {
|
||||
let range = current
|
||||
.constraint
|
||||
.iter()
|
||||
.map(|c| c.to_range())
|
||||
.flat_map(|r| r.into_iter());
|
||||
|
||||
let body_indentation = indentation.nested();
|
||||
range
|
||||
.map(|i| {
|
||||
format!(
|
||||
"{indentation}{{\n\
|
||||
{body_indentation}const {name}: {ty} = {val};\n\
|
||||
{pass}\n\
|
||||
{indentation}}}",
|
||||
name = current.name,
|
||||
ty = current.ty.rust_type(),
|
||||
val = i,
|
||||
pass = gen_code_rust(
|
||||
body_indentation,
|
||||
intrinsic,
|
||||
constraints,
|
||||
format!("{name}-{i}")
|
||||
)
|
||||
)
|
||||
})
|
||||
.join("\n")
|
||||
} else {
|
||||
intrinsic.generate_loop_rust(indentation, &name, PASSES)
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_rust_program_arm(intrinsic: &Intrinsic<ArmIntrinsicType>, target: &str) -> String {
|
||||
let constraints = intrinsic
|
||||
.arguments
|
||||
.iter()
|
||||
.filter(|i| i.has_constraint())
|
||||
.collect_vec();
|
||||
|
||||
let indentation = Indentation::default();
|
||||
let final_target = if target.contains("v7") {
|
||||
"arm"
|
||||
} else {
|
||||
"aarch64"
|
||||
};
|
||||
generate_rust_program(
|
||||
build_notices("// ").as_str(),
|
||||
AARCH_CONFIGURATIONS,
|
||||
final_target,
|
||||
intrinsic
|
||||
.arguments
|
||||
.gen_arglists_rust(indentation.nested(), PASSES)
|
||||
.as_str(),
|
||||
gen_code_rust(
|
||||
indentation.nested(),
|
||||
intrinsic,
|
||||
&constraints,
|
||||
Default::default(),
|
||||
)
|
||||
.as_str(),
|
||||
)
|
||||
}
|
||||
|
||||
fn compile_c_arm(
|
||||
intrinsics_name_list: &Vec<String>,
|
||||
compiler: &str,
|
||||
target: &str,
|
||||
cxx_toolchain_dir: Option<&str>,
|
||||
) -> bool {
|
||||
// -ffp-contract=off emulates Rust's approach of not fusing separate mul-add operations
|
||||
let mut command = CompilationCommandBuilder::new()
|
||||
.add_arch_flags(vec!["armv8.6-a", "crypto", "crc", "dotprod", "fp16"])
|
||||
.set_compiler(compiler)
|
||||
.set_target(target)
|
||||
.set_opt_level("2")
|
||||
.set_cxx_toolchain_dir(cxx_toolchain_dir)
|
||||
.set_project_root("c_programs")
|
||||
.add_extra_flags(vec!["-ffp-contract=off", "-Wno-narrowing"]);
|
||||
|
||||
if !target.contains("v7") {
|
||||
command = command.add_arch_flags(vec!["faminmax", "lut", "sha3"]);
|
||||
}
|
||||
|
||||
/*
|
||||
* clang++ cannot link an aarch64_be object file, so we invoke
|
||||
* aarch64_be-unknown-linux-gnu's C++ linker. This ensures that we
|
||||
* are testing the intrinsics against LLVM.
|
||||
*
|
||||
* Note: setting `--sysroot=<...>` which is the obvious thing to do
|
||||
* does not work as it gets caught up with `#include_next <stdlib.h>`
|
||||
* not existing...
|
||||
*/
|
||||
if target.contains("aarch64_be") {
|
||||
command = command
|
||||
.set_linker(
|
||||
cxx_toolchain_dir.unwrap_or("").to_string() + "/bin/aarch64_be-none-linux-gnu-g++",
|
||||
)
|
||||
.set_include_paths(vec![
|
||||
"/include",
|
||||
"/aarch64_be-none-linux-gnu/include",
|
||||
"/aarch64_be-none-linux-gnu/include/c++/14.2.1",
|
||||
"/aarch64_be-none-linux-gnu/include/c++/14.2.1/aarch64_be-none-linux-gnu",
|
||||
"/aarch64_be-none-linux-gnu/include/c++/14.2.1/backward",
|
||||
"/aarch64_be-none-linux-gnu/libc/usr/include",
|
||||
]);
|
||||
}
|
||||
|
||||
if !compiler.contains("clang") {
|
||||
command = command.add_extra_flag("-flax-vector-conversions");
|
||||
}
|
||||
|
||||
let compiler_commands = intrinsics_name_list
|
||||
.iter()
|
||||
.map(|intrinsic_name| {
|
||||
command
|
||||
.clone()
|
||||
.set_input_name(intrinsic_name)
|
||||
.set_output_name(intrinsic_name)
|
||||
.to_string()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
compile_c(&compiler_commands)
|
||||
}
|
||||
|
||||
pub fn build_c(
|
||||
intrinsics: &Vec<Intrinsic<ArmIntrinsicType>>,
|
||||
compiler: Option<&str>,
|
||||
target: &str,
|
||||
cxx_toolchain_dir: Option<&str>,
|
||||
) -> bool {
|
||||
let intrinsics_name_list = intrinsics
|
||||
.par_iter()
|
||||
.map(|i| i.name.clone())
|
||||
.collect::<Vec<_>>();
|
||||
let filename_mapping = create_c_filenames(&intrinsics_name_list);
|
||||
|
||||
intrinsics.par_iter().for_each(|i| {
|
||||
let c_code = generate_c_program_arm(&["arm_neon.h", "arm_acle.h", "arm_fp16.h"], i, target);
|
||||
match filename_mapping.get(&i.name) {
|
||||
Some(filename) => write_file(filename, c_code),
|
||||
None => {}
|
||||
};
|
||||
});
|
||||
|
||||
match compiler {
|
||||
None => true,
|
||||
Some(compiler) => compile_c_arm(&intrinsics_name_list, compiler, target, cxx_toolchain_dir),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_rust(
|
||||
intrinsics: &[Intrinsic<ArmIntrinsicType>],
|
||||
toolchain: Option<&str>,
|
||||
target: &str,
|
||||
linker: Option<&str>,
|
||||
) -> bool {
|
||||
let intrinsics_name_list = intrinsics
|
||||
.par_iter()
|
||||
.map(|i| i.name.clone())
|
||||
.collect::<Vec<_>>();
|
||||
let filename_mapping = create_rust_filenames(&intrinsics_name_list);
|
||||
|
||||
intrinsics.par_iter().for_each(|i| {
|
||||
let rust_code = generate_rust_program_arm(i, target);
|
||||
match filename_mapping.get(&i.name) {
|
||||
Some(filename) => write_file(filename, rust_code),
|
||||
None => {}
|
||||
}
|
||||
});
|
||||
|
||||
let intrinsics_name_list = intrinsics.iter().map(|i| i.name.as_str()).collect_vec();
|
||||
|
||||
compile_rust(&intrinsics_name_list, toolchain, target, linker)
|
||||
}
|
||||
|
|
@ -1,16 +1,19 @@
|
|||
mod compile;
|
||||
mod config;
|
||||
mod functions;
|
||||
mod intrinsic;
|
||||
mod json_parser;
|
||||
mod types;
|
||||
|
||||
use crate::arm::compile::compile_c_arm;
|
||||
use crate::arm::intrinsic::ArmIntrinsicType;
|
||||
use crate::common::SupportedArchitectureTest;
|
||||
use crate::common::cli::ProcessedCli;
|
||||
use crate::common::compare::compare_outputs;
|
||||
use crate::common::intrinsic::Intrinsic;
|
||||
use crate::common::gen_rust::compile_rust;
|
||||
use crate::common::intrinsic::{Intrinsic, IntrinsicDefinition};
|
||||
use crate::common::intrinsic_helpers::{BaseIntrinsicTypeDefinition, TypeKind};
|
||||
use functions::{build_c, build_rust};
|
||||
use crate::common::write_file::{write_c_testfiles, write_rust_testfiles};
|
||||
use config::{AARCH_CONFIGURATIONS, POLY128_OSTREAM_DEF, build_notices};
|
||||
use json_parser::get_neon_intrinsics;
|
||||
|
||||
pub struct ArmArchitectureTest {
|
||||
|
|
@ -48,21 +51,50 @@ impl SupportedArchitectureTest for ArmArchitectureTest {
|
|||
}
|
||||
|
||||
fn build_c_file(&self) -> bool {
|
||||
build_c(
|
||||
&self.intrinsics,
|
||||
self.cli_options.cpp_compiler.as_deref(),
|
||||
&self.cli_options.target,
|
||||
self.cli_options.cxx_toolchain_dir.as_deref(),
|
||||
)
|
||||
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 intrinsics_name_list = write_c_testfiles(
|
||||
&self
|
||||
.intrinsics
|
||||
.iter()
|
||||
.map(|i| i as &dyn IntrinsicDefinition<_>)
|
||||
.collect::<Vec<_>>(),
|
||||
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, compiler, target, cxx_toolchain_dir)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn build_rust_file(&self) -> bool {
|
||||
build_rust(
|
||||
&self.intrinsics,
|
||||
self.cli_options.toolchain.as_deref(),
|
||||
&self.cli_options.target,
|
||||
self.cli_options.linker.as_deref(),
|
||||
)
|
||||
let final_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<_>>(),
|
||||
final_target,
|
||||
&build_notices("// "),
|
||||
AARCH_CONFIGURATIONS,
|
||||
);
|
||||
|
||||
compile_rust(intrinsics_name_list, toolchain, target, linker)
|
||||
}
|
||||
|
||||
fn compare_outputs(&self) -> bool {
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ fn main() {{
|
|||
}
|
||||
|
||||
pub fn compile_rust(
|
||||
binaries: &[&str],
|
||||
binaries: Vec<String>,
|
||||
toolchain: Option<&str>,
|
||||
target: &str,
|
||||
linker: Option<&str>,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,14 @@
|
|||
use crate::common::argument::ArgumentList;
|
||||
use crate::common::indentation::Indentation;
|
||||
use crate::common::intrinsic_helpers::IntrinsicTypeDefinition;
|
||||
use itertools::Itertools;
|
||||
|
||||
use super::argument::Argument;
|
||||
use super::gen_c::generate_c_program;
|
||||
use super::gen_rust::generate_rust_program;
|
||||
|
||||
// The number of times each intrinsic will be called.
|
||||
const PASSES: u32 = 20;
|
||||
|
||||
/// An intrinsic
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
|
|
@ -85,4 +93,132 @@ where
|
|||
args = self.arguments().as_call_param_rust(),
|
||||
)
|
||||
}
|
||||
|
||||
fn gen_code_c(
|
||||
&self,
|
||||
indentation: Indentation,
|
||||
constraints: &[&Argument<T>],
|
||||
name: String,
|
||||
target: &str,
|
||||
) -> String {
|
||||
if let Some((current, constraints)) = constraints.split_last() {
|
||||
let range = current
|
||||
.constraint
|
||||
.iter()
|
||||
.map(|c| c.to_range())
|
||||
.flat_map(|r| r.into_iter());
|
||||
|
||||
let body_indentation = indentation.nested();
|
||||
range
|
||||
.map(|i| {
|
||||
format!(
|
||||
"{indentation}{{\n\
|
||||
{body_indentation}{ty} {name} = {val};\n\
|
||||
{pass}\n\
|
||||
{indentation}}}",
|
||||
name = current.name,
|
||||
ty = current.ty.c_type(),
|
||||
val = i,
|
||||
pass = self.gen_code_c(
|
||||
body_indentation,
|
||||
constraints,
|
||||
format!("{name}-{i}"),
|
||||
target,
|
||||
)
|
||||
)
|
||||
})
|
||||
.join("\n")
|
||||
} else {
|
||||
self.generate_loop_c(indentation, &name, PASSES, target)
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_c_program(
|
||||
&self,
|
||||
header_files: &[&str],
|
||||
target: &str,
|
||||
notices: &str,
|
||||
arch_specific_definitions: &[&str],
|
||||
) -> String {
|
||||
let arguments = self.arguments();
|
||||
let constraints = arguments
|
||||
.iter()
|
||||
.filter(|&i| i.has_constraint())
|
||||
.collect_vec();
|
||||
|
||||
let indentation = Indentation::default();
|
||||
generate_c_program(
|
||||
notices,
|
||||
header_files,
|
||||
"aarch64",
|
||||
arch_specific_definitions,
|
||||
self.arguments()
|
||||
.gen_arglists_c(indentation, PASSES)
|
||||
.as_str(),
|
||||
self.gen_code_c(
|
||||
indentation.nested(),
|
||||
constraints.as_slice(),
|
||||
Default::default(),
|
||||
target,
|
||||
)
|
||||
.as_str(),
|
||||
)
|
||||
}
|
||||
|
||||
fn gen_code_rust(
|
||||
&self,
|
||||
indentation: Indentation,
|
||||
constraints: &[&Argument<T>],
|
||||
name: String,
|
||||
) -> String {
|
||||
if let Some((current, constraints)) = constraints.split_last() {
|
||||
let range = current
|
||||
.constraint
|
||||
.iter()
|
||||
.map(|c| c.to_range())
|
||||
.flat_map(|r| r.into_iter());
|
||||
|
||||
let body_indentation = indentation.nested();
|
||||
range
|
||||
.map(|i| {
|
||||
format!(
|
||||
"{indentation}{{\n\
|
||||
{body_indentation}const {name}: {ty} = {val};\n\
|
||||
{pass}\n\
|
||||
{indentation}}}",
|
||||
name = current.name,
|
||||
ty = current.ty.rust_type(),
|
||||
val = i,
|
||||
pass = self.gen_code_rust(
|
||||
body_indentation,
|
||||
constraints,
|
||||
format!("{name}-{i}")
|
||||
)
|
||||
)
|
||||
})
|
||||
.join("\n")
|
||||
} else {
|
||||
self.generate_loop_rust(indentation, &name, PASSES)
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_rust_program(&self, target: &str, notice: &str, cfg: &str) -> String {
|
||||
let arguments = self.arguments();
|
||||
let constraints = arguments
|
||||
.iter()
|
||||
.filter(|i| i.has_constraint())
|
||||
.collect_vec();
|
||||
|
||||
let indentation = Indentation::default();
|
||||
generate_rust_program(
|
||||
notice,
|
||||
cfg,
|
||||
target,
|
||||
self.arguments()
|
||||
.gen_arglists_rust(indentation.nested(), PASSES)
|
||||
.as_str(),
|
||||
self.gen_code_rust(indentation.nested(), &constraints, Default::default())
|
||||
.as_str(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ pub mod indentation;
|
|||
pub mod intrinsic;
|
||||
pub mod intrinsic_helpers;
|
||||
pub mod values;
|
||||
pub mod write_file;
|
||||
|
||||
/// Architectures must support this trait
|
||||
/// to be successfully tested.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
use super::intrinsic_helpers::IntrinsicTypeDefinition;
|
||||
use crate::common::gen_c::create_c_filenames;
|
||||
use crate::common::gen_rust::create_rust_filenames;
|
||||
use crate::common::intrinsic::IntrinsicDefinition;
|
||||
use crate::common::write_file;
|
||||
|
||||
pub fn write_c_testfiles<T: IntrinsicTypeDefinition + Sized>(
|
||||
intrinsics: &Vec<&dyn IntrinsicDefinition<T>>,
|
||||
target: &str,
|
||||
headers: &[&str],
|
||||
notice: &str,
|
||||
arch_specific_definitions: &[&str],
|
||||
) -> Vec<String> {
|
||||
let intrinsics_name_list = intrinsics
|
||||
.iter()
|
||||
.map(|i| i.name().clone())
|
||||
.collect::<Vec<_>>();
|
||||
let filename_mapping = create_c_filenames(&intrinsics_name_list);
|
||||
|
||||
intrinsics.iter().for_each(|i| {
|
||||
let c_code = i.generate_c_program(headers, target, notice, arch_specific_definitions);
|
||||
match filename_mapping.get(&i.name()) {
|
||||
Some(filename) => write_file(filename, c_code),
|
||||
None => {}
|
||||
};
|
||||
});
|
||||
|
||||
intrinsics_name_list
|
||||
}
|
||||
|
||||
pub fn write_rust_testfiles<T: IntrinsicTypeDefinition>(
|
||||
intrinsics: Vec<&dyn IntrinsicDefinition<T>>,
|
||||
rust_target: &str,
|
||||
notice: &str,
|
||||
cfg: &str,
|
||||
) -> Vec<String> {
|
||||
let intrinsics_name_list = intrinsics
|
||||
.iter()
|
||||
.map(|i| i.name().clone())
|
||||
.collect::<Vec<_>>();
|
||||
let filename_mapping = create_rust_filenames(&intrinsics_name_list);
|
||||
|
||||
intrinsics.iter().for_each(|i| {
|
||||
let rust_code = i.generate_rust_program(rust_target, notice, cfg);
|
||||
match filename_mapping.get(&i.name()) {
|
||||
Some(filename) => write_file(filename, rust_code),
|
||||
None => {}
|
||||
}
|
||||
});
|
||||
|
||||
intrinsics_name_list
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue