Check and pass the ACLE licence on to generated tests.

The generated tests are transient, and aren't committed, so this is
primarily a safety check.
This commit is contained in:
Jacob Bramley 2022-10-31 12:27:04 +00:00 committed by Amanieu d'Antras
parent 4407146bb8
commit 6e5b949ee7
3 changed files with 86 additions and 15 deletions

View file

@ -1,4 +1,4 @@
Copyright (c) 2021-2022 The Rust Project Developers
Copyright (c) 2021-2023 The Rust Project Developers
Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated

View file

@ -6,9 +6,53 @@ use crate::argument::{Argument, ArgumentList, Constraint};
use crate::intrinsic::Intrinsic;
use crate::types::{IntrinsicType, TypeKind};
pub fn get_acle_intrinsics(filename: &str) -> Vec<Intrinsic> {
pub struct CsvMetadata {
notices: String,
spdx_lic: String,
}
impl CsvMetadata {
fn new<'a>(header: impl Iterator<Item = &'a str>) -> Self {
lazy_static! {
static ref SPDX_LICENSE_IDENTIFIER: Regex =
Regex::new(r#"SPDX-License-Identifier:(.*)"#).unwrap();
}
let notices = header.map(|line| format!("{line}\n")).collect::<String>();
let spdx_lic = match SPDX_LICENSE_IDENTIFIER
.captures_iter(&notices)
.exactly_one()
{
Ok(caps) => {
let cap = caps.get(1).unwrap().as_str().trim();
// Ensure that (unlikely) ACLE licence changes don't go unnoticed.
assert_eq!(cap, "Apache-2.0");
cap.to_string()
}
Err(caps_iter) => panic!(
"Expected exactly one SPDX-License-Identifier, found {}.",
caps_iter.count()
),
};
Self { notices, spdx_lic }
}
pub fn spdx_license_identifier(&self) -> &str {
self.spdx_lic.as_str()
}
pub fn notices_lines(&self) -> impl Iterator<Item = &str> {
self.notices.lines()
}
}
pub fn get_acle_intrinsics(filename: &str) -> (CsvMetadata, Vec<Intrinsic>) {
let data = std::fs::read_to_string(filename).expect("Failed to open ACLE intrinsics file");
let comment_header = data.lines().map_while(|l| l.strip_prefix("<COMMENT>\t"));
let meta = CsvMetadata::new(comment_header);
let data = data
.lines()
.filter_map(|l| {
@ -51,7 +95,7 @@ pub fn get_acle_intrinsics(filename: &str) -> Vec<Intrinsic> {
}
}
intrinsics.to_vec()
(meta, intrinsics.to_vec())
}
impl Into<Intrinsic> for ACLEIntrinsicLine {

View file

@ -14,7 +14,7 @@ use itertools::Itertools;
use rayon::prelude::*;
use types::TypeKind;
use crate::acle_csv_parser::get_acle_intrinsics;
use crate::acle_csv_parser::{get_acle_intrinsics, CsvMetadata};
use crate::argument::Argument;
mod acle_csv_parser;
@ -70,6 +70,7 @@ fn gen_code_c(
}
fn generate_c_program(
notices: &str,
header_files: &[&str],
intrinsic: &Intrinsic,
p64_armv7_workaround: bool,
@ -81,7 +82,7 @@ fn generate_c_program(
.collect_vec();
format!(
r#"{header_files}
r#"{notices}{header_files}
#include <iostream>
#include <cstring>
#include <iomanip>
@ -157,7 +158,7 @@ fn gen_code_rust(intrinsic: &Intrinsic, constraints: &[&Argument], name: String)
}
}
fn generate_rust_program(intrinsic: &Intrinsic, a32: bool) -> String {
fn generate_rust_program(notices: &str, intrinsic: &Intrinsic, a32: bool) -> String {
let constraints = intrinsic
.arguments
.iter()
@ -165,7 +166,7 @@ fn generate_rust_program(intrinsic: &Intrinsic, a32: bool) -> String {
.collect_vec();
format!(
r#"#![feature(simd_ffi)]
r#"{notices}#![feature(simd_ffi)]
#![feature(link_llvm_intrinsics)]
#![feature(stdsimd)]
#![allow(overflowing_literals)]
@ -217,7 +218,23 @@ fn compile_c(c_filename: &str, intrinsic: &Intrinsic, compiler: &str, a32: bool)
}
}
fn build_c(intrinsics: &Vec<Intrinsic>, compiler: &str, a32: bool) -> bool {
fn build_notices(csv_metadata: &CsvMetadata, line_prefix: &str) -> String {
let mut notices = format!(
"\
{line_prefix}This is a transient test file, not intended for distribution. Some aspects of the
{line_prefix}test are derived from a CSV specification, published with the following notices:
{line_prefix}
"
);
let lines = csv_metadata
.notices_lines()
.map(|line| format!("{line_prefix} {line}\n"));
notices.extend(lines);
notices.push_str("\n");
notices
}
fn build_c(notices: &str, intrinsics: &Vec<Intrinsic>, compiler: &str, a32: bool) -> bool {
let _ = std::fs::create_dir("c_programs");
intrinsics
.par_iter()
@ -225,7 +242,7 @@ fn build_c(intrinsics: &Vec<Intrinsic>, compiler: &str, a32: bool) -> bool {
let c_filename = format!(r#"c_programs/{}.cpp"#, i.name);
let mut file = File::create(&c_filename).unwrap();
let c_code = generate_c_program(&["arm_neon.h", "arm_acle.h"], &i, a32);
let c_code = generate_c_program(notices, &["arm_neon.h", "arm_acle.h"], &i, a32);
file.write_all(c_code.into_bytes().as_slice()).unwrap();
compile_c(&c_filename, &i, compiler, a32)
})
@ -233,14 +250,20 @@ fn build_c(intrinsics: &Vec<Intrinsic>, compiler: &str, a32: bool) -> bool {
.is_none()
}
fn build_rust(intrinsics: &Vec<Intrinsic>, toolchain: &str, a32: bool) -> bool {
fn build_rust(
notices: &str,
spdx_lic: &str,
intrinsics: &Vec<Intrinsic>,
toolchain: &str,
a32: bool,
) -> bool {
intrinsics.iter().for_each(|i| {
let rust_dir = format!(r#"rust_programs/{}"#, i.name);
let _ = std::fs::create_dir_all(&rust_dir);
let rust_filename = format!(r#"{rust_dir}/main.rs"#);
let mut file = File::create(&rust_filename).unwrap();
let c_code = generate_rust_program(&i, a32);
let c_code = generate_rust_program(notices, &i, a32);
file.write_all(c_code.into_bytes().as_slice()).unwrap();
});
@ -249,9 +272,10 @@ fn build_rust(intrinsics: &Vec<Intrinsic>, toolchain: &str, a32: bool) -> bool {
.write_all(
format!(
r#"[package]
name = "intrinsic-test"
name = "intrinsic-test-programs"
version = "{version}"
authors = ["{authors}"]
license = "{spdx_lic}"
edition = "2018"
[workspace]
[dependencies]
@ -371,7 +395,7 @@ fn main() {
};
let a32 = matches.is_present("A32");
let intrinsics = get_acle_intrinsics(filename);
let (csv_metadata, intrinsics) = get_acle_intrinsics(filename);
let mut intrinsics = intrinsics
.into_iter()
@ -394,11 +418,14 @@ fn main() {
.collect::<Vec<_>>();
intrinsics.dedup();
if !build_c(&intrinsics, cpp_compiler, a32) {
let notices = build_notices(&csv_metadata, "// ");
let spdx_lic = csv_metadata.spdx_license_identifier();
if !build_c(&notices, &intrinsics, cpp_compiler, a32) {
std::process::exit(2);
}
if !build_rust(&intrinsics, &toolchain, a32) {
if !build_rust(&notices, spdx_lic, &intrinsics, &toolchain, a32) {
std::process::exit(3);
}