Clean up intrinsic-test literals.

- Ensure that C literals don't rely on undefined overflow behaviour.
- We don't need to use 'as' casts, so remove them.
- We weren't using allow(overflowing_literals), so remove it.
- Format FP bit values as hex.

This simplifies the test input initialisers in the generated files,
making them shorter and easier to debug.
This commit is contained in:
Jacob Bramley 2023-05-19 17:13:10 +01:00 committed by Amanieu d'Antras
parent 1970299926
commit 05afebca4d
3 changed files with 33 additions and 24 deletions

View File

@ -174,7 +174,6 @@ fn generate_rust_program(notices: &str, intrinsic: &Intrinsic, a32: bool) -> Str
#![cfg_attr(target_arch = "aarch64", feature(stdarch_neon_sha3))]
#![cfg_attr(target_arch = "aarch64", feature(stdarch_neon_sm4))]
#![cfg_attr(target_arch = "aarch64", feature(stdarch_neon_ftts))]
#![allow(overflowing_literals)]
#![allow(non_upper_case_globals)]
use core_arch::arch::{target_arch}::*;

View File

@ -305,23 +305,38 @@ impl IntrinsicType {
match self {
IntrinsicType::Ptr { child, .. } => child.populate_random(loads, language),
IntrinsicType::Type {
bit_len: Some(bit_len),
kind: TypeKind::Int | TypeKind::UInt | TypeKind::Poly,
bit_len: Some(bit_len @ (8 | 16 | 32 | 64)),
kind: kind @ (TypeKind::Int | TypeKind::UInt | TypeKind::Poly),
simd_len,
vec_len,
..
} => {
let (prefix, as_type, suffix) = match language {
&Language::Rust => ("[", format!(" as {}", self.rust_scalar_type()), "]"),
&Language::C => ("{", "".into(), "}"),
let (prefix, suffix) = match language {
&Language::Rust => ("[", "]"),
&Language::C => ("{", "}"),
};
format!(
"{prefix}{body}{suffix}",
body = (0..(simd_len.unwrap_or(1) * vec_len.unwrap_or(1) + loads - 1))
.format_with(", ", |i, fmt| fmt(&format_args!(
"{src}{as_type}",
src = value_for_array(*bit_len, i)
)))
.format_with(", ", |i, fmt| {
let src = value_for_array(*bit_len, i);
assert!(src == 0 || src.ilog2() < *bit_len);
if *kind == TypeKind::Int && (src >> (*bit_len - 1)) != 0 {
// `src` is a two's complement representation of a negative value.
let mask = !0u64 >> (64 - *bit_len);
let ones_compl = src ^ mask;
let twos_compl = ones_compl + 1;
if (twos_compl == src) && (language == &Language::C) {
// `src` is INT*_MIN. C requires `-0x7fffffff - 1` to avoid
// undefined literal overflow behaviour.
fmt(&format_args!("-{ones_compl:#x} - 1"))
} else {
fmt(&format_args!("-{twos_compl:#x}"))
}
} else {
fmt(&format_args!("{src:#x}"))
}
})
)
}
IntrinsicType::Type {
@ -342,7 +357,7 @@ impl IntrinsicType {
"{prefix}{body}{suffix}",
body = (0..(simd_len.unwrap_or(1) * vec_len.unwrap_or(1) + loads - 1))
.format_with(", ", |i, fmt| fmt(&format_args!(
"{cast_prefix}{src}{cast_suffix}",
"{cast_prefix}{src:#x}{cast_suffix}",
src = value_for_array(*bit_len, i)
)))
)

View File

@ -1,19 +1,14 @@
/// Gets a hex constant value for a single value in the argument values array in a determistic way
/// Get a single value for an argument values array in a determistic way.
/// * `bits`: The number of bits for the type, only 8, 16, 32, 64 are valid values
/// * `index`: The position in the array we are generating for
pub fn value_for_array(bits: u32, index: u32) -> String {
pub fn value_for_array(bits: u32, index: u32) -> u64 {
let index = index as usize;
if bits == 8 {
format!("{:#X}", VALUES_8[index % VALUES_8.len()])
} else if bits == 16 {
format!("{:#X}", VALUES_16[index % VALUES_16.len()])
} else if bits == 32 {
format!("{:#X}", VALUES_32[index % VALUES_32.len()])
} else if bits == 64 {
format!("{:#X}", VALUES_64[index % VALUES_64.len()])
} else {
panic!("Unknown size: {bits}");
match bits {
8 => VALUES_8[index % VALUES_8.len()].into(),
16 => VALUES_16[index % VALUES_16.len()].into(),
32 => VALUES_32[index % VALUES_32.len()].into(),
64 => VALUES_64[index % VALUES_64.len()].into(),
_ => unimplemented!("value_for_array(bits: {bits}, ..)"),
}
}