use std::collections::HashMap;
use crate::clang::preprocessor::*;
use crate::clang::*;
use crate::x86::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum X86BuiltinHeader {
Stddef,
Stdint,
Stdbool,
Stdarg,
Limits,
Float,
Iso646,
Stdalign,
Stdnoreturn,
Stdatomic,
Tgmath,
Stdckdint,
X86Intrin,
Mmintrin,
Xmmintrin,
Emmintrin,
Pmmintrin,
Tmmintrin,
Smmintrin,
Nmmintrin,
Wmmintrin,
Immintrin,
Avxintrin,
Avx2intrin,
Avx512fintrin,
Avx512bwintrin,
Avx512dqintrin,
Avx512vlintrin,
Fmaintrin,
Bmiintrin,
Bmi2intrin,
Lzcntintrin,
Cpuid,
}
impl X86BuiltinHeader {
pub fn filename(&self) -> &'static str {
match self {
Self::Stddef => "stddef.h",
Self::Stdint => "stdint.h",
Self::Stdbool => "stdbool.h",
Self::Stdarg => "stdarg.h",
Self::Limits => "limits.h",
Self::Float => "float.h",
Self::Iso646 => "iso646.h",
Self::Stdalign => "stdalign.h",
Self::Stdnoreturn => "stdnoreturn.h",
Self::Stdatomic => "stdatomic.h",
Self::Tgmath => "tgmath.h",
Self::Stdckdint => "stdckdint.h",
Self::X86Intrin => "x86intrin.h",
Self::Mmintrin => "mmintrin.h",
Self::Xmmintrin => "xmmintrin.h",
Self::Emmintrin => "emmintrin.h",
Self::Pmmintrin => "pmmintrin.h",
Self::Tmmintrin => "tmmintrin.h",
Self::Smmintrin => "smmintrin.h",
Self::Nmmintrin => "nmmintrin.h",
Self::Wmmintrin => "wmmintrin.h",
Self::Immintrin => "immintrin.h",
Self::Avxintrin => "avxintrin.h",
Self::Avx2intrin => "avx2intrin.h",
Self::Avx512fintrin => "avx512fintrin.h",
Self::Avx512bwintrin => "avx512bwintrin.h",
Self::Avx512dqintrin => "avx512dqintrin.h",
Self::Avx512vlintrin => "avx512vlintrin.h",
Self::Fmaintrin => "fmaintrin.h",
Self::Bmiintrin => "bmiintrin.h",
Self::Bmi2intrin => "bmi2intrin.h",
Self::Lzcntintrin => "lzcntintrin.h",
Self::Cpuid => "cpuid.h",
}
}
pub fn is_standard_c(&self) -> bool {
matches!(
self,
Self::Stddef
| Self::Stdint
| Self::Stdbool
| Self::Stdarg
| Self::Limits
| Self::Float
| Self::Iso646
| Self::Stdalign
| Self::Stdnoreturn
| Self::Stdatomic
| Self::Tgmath
| Self::Stdckdint
)
}
pub fn is_x86_intrinsic(&self) -> bool {
matches!(
self,
Self::X86Intrin
| Self::Mmintrin
| Self::Xmmintrin
| Self::Emmintrin
| Self::Pmmintrin
| Self::Tmmintrin
| Self::Smmintrin
| Self::Nmmintrin
| Self::Wmmintrin
| Self::Immintrin
| Self::Avxintrin
| Self::Avx2intrin
| Self::Avx512fintrin
| Self::Avx512bwintrin
| Self::Avx512dqintrin
| Self::Avx512vlintrin
| Self::Fmaintrin
| Self::Bmiintrin
| Self::Bmi2intrin
| Self::Lzcntintrin
| Self::Cpuid
)
}
}
#[derive(Debug, Clone)]
pub struct X86TargetConfig {
pub pointer_width: u32,
pub long_width: u32,
pub long_long_width: u32,
pub wchar_width: u32,
pub little_endian: bool,
pub int_width: u32,
pub short_width: u32,
pub char_width: u32,
pub char_is_signed: bool,
pub max_alignment: u32,
pub has_int128: bool,
pub has_mmx: bool,
pub has_sse: bool,
pub has_sse2: bool,
pub has_sse3: bool,
pub has_ssse3: bool,
pub has_sse4_1: bool,
pub has_sse4_2: bool,
pub has_aes: bool,
pub has_avx: bool,
pub has_avx2: bool,
pub has_avx512f: bool,
pub has_avx512bw: bool,
pub has_avx512dq: bool,
pub has_avx512vl: bool,
pub has_fma: bool,
pub has_bmi: bool,
pub has_bmi2: bool,
pub has_lzcnt: bool,
}
impl Default for X86TargetConfig {
fn default() -> Self {
Self::new_x86_64_linux()
}
}
impl X86TargetConfig {
pub fn new_x86_64_linux() -> Self {
Self {
pointer_width: 64,
long_width: 64,
long_long_width: 64,
wchar_width: 32,
little_endian: true,
int_width: 32,
short_width: 16,
char_width: 8,
char_is_signed: true,
max_alignment: 16,
has_int128: true,
has_mmx: true,
has_sse: true,
has_sse2: true,
has_sse3: true,
has_ssse3: true,
has_sse4_1: true,
has_sse4_2: true,
has_aes: true,
has_avx: true,
has_avx2: true,
has_avx512f: false,
has_avx512bw: false,
has_avx512dq: false,
has_avx512vl: false,
has_fma: true,
has_bmi: true,
has_bmi2: true,
has_lzcnt: true,
}
}
pub fn new_x86_64_avx512() -> Self {
let mut cfg = Self::new_x86_64_linux();
cfg.has_avx512f = true;
cfg.has_avx512bw = true;
cfg.has_avx512dq = true;
cfg.has_avx512vl = true;
cfg.max_alignment = 64;
cfg
}
pub fn new_x86_32_linux() -> Self {
Self {
pointer_width: 32,
long_width: 32,
long_long_width: 64,
wchar_width: 32,
little_endian: true,
int_width: 32,
short_width: 16,
char_width: 8,
char_is_signed: true,
max_alignment: 16,
has_int128: false,
has_mmx: true,
has_sse: true,
has_sse2: true,
has_sse3: true,
has_ssse3: true,
has_sse4_1: true,
has_sse4_2: true,
has_aes: true,
has_avx: true,
has_avx2: true,
has_avx512f: false,
has_avx512bw: false,
has_avx512dq: false,
has_avx512vl: false,
has_fma: true,
has_bmi: true,
has_bmi2: true,
has_lzcnt: true,
}
}
}
#[derive(Debug, Clone)]
pub struct X86BuiltinHeaders {
pub config: X86TargetConfig,
}
impl X86BuiltinHeaders {
pub fn new(config: X86TargetConfig) -> Self {
Self { config }
}
pub fn new_x86_64() -> Self {
Self::new(X86TargetConfig::new_x86_64_linux())
}
pub fn new_x86_32() -> Self {
Self::new(X86TargetConfig::new_x86_32_linux())
}
pub fn generate(&self, header: X86BuiltinHeader) -> String {
match header {
X86BuiltinHeader::Stddef => self.generate_stddef(),
X86BuiltinHeader::Stdint => self.generate_stdint(),
X86BuiltinHeader::Stdbool => self.generate_stdbool(),
X86BuiltinHeader::Stdarg => self.generate_stdarg(),
X86BuiltinHeader::Limits => self.generate_limits(),
X86BuiltinHeader::Float => self.generate_float(),
X86BuiltinHeader::Iso646 => self.generate_iso646(),
X86BuiltinHeader::Stdalign => self.generate_stdalign(),
X86BuiltinHeader::Stdnoreturn => self.generate_stdnoreturn(),
X86BuiltinHeader::Stdatomic => self.generate_stdatomic(),
X86BuiltinHeader::Tgmath => self.generate_tgmath(),
X86BuiltinHeader::Stdckdint => self.generate_stdckdint(),
X86BuiltinHeader::X86Intrin => self.generate_x86intrin(),
X86BuiltinHeader::Mmintrin => self.generate_mmintrin(),
X86BuiltinHeader::Xmmintrin => self.generate_xmmintrin(),
X86BuiltinHeader::Emmintrin => self.generate_emmintrin(),
X86BuiltinHeader::Pmmintrin => self.generate_pmmintrin(),
X86BuiltinHeader::Tmmintrin => self.generate_tmmintrin(),
X86BuiltinHeader::Smmintrin => self.generate_smmintrin(),
X86BuiltinHeader::Nmmintrin => self.generate_nmmintrin(),
X86BuiltinHeader::Wmmintrin => self.generate_wmmintrin(),
X86BuiltinHeader::Immintrin => self.generate_immintrin(),
X86BuiltinHeader::Avxintrin => self.generate_avxintrin(),
X86BuiltinHeader::Avx2intrin => self.generate_avx2intrin(),
X86BuiltinHeader::Avx512fintrin => self.generate_avx512fintrin(),
X86BuiltinHeader::Avx512bwintrin => self.generate_avx512bwintrin(),
X86BuiltinHeader::Avx512dqintrin => self.generate_avx512dqintrin(),
X86BuiltinHeader::Avx512vlintrin => self.generate_avx512vlintrin(),
X86BuiltinHeader::Fmaintrin => self.generate_fmaintrin(),
X86BuiltinHeader::Bmiintrin => self.generate_bmiintrin(),
X86BuiltinHeader::Bmi2intrin => self.generate_bmi2intrin(),
X86BuiltinHeader::Lzcntintrin => self.generate_lzcntintrin(),
X86BuiltinHeader::Cpuid => self.generate_cpuid(),
}
}
pub fn generate_all(&self) -> HashMap<String, String> {
let all = self.all_headers();
let mut map = HashMap::new();
for h in &all {
map.insert(h.filename().to_string(), self.generate(*h));
}
map
}
pub fn all_headers(&self) -> Vec<X86BuiltinHeader> {
vec![
X86BuiltinHeader::Stddef,
X86BuiltinHeader::Stdint,
X86BuiltinHeader::Stdbool,
X86BuiltinHeader::Stdarg,
X86BuiltinHeader::Limits,
X86BuiltinHeader::Float,
X86BuiltinHeader::Iso646,
X86BuiltinHeader::Stdalign,
X86BuiltinHeader::Stdnoreturn,
X86BuiltinHeader::Stdatomic,
X86BuiltinHeader::Tgmath,
X86BuiltinHeader::Stdckdint,
X86BuiltinHeader::X86Intrin,
X86BuiltinHeader::Mmintrin,
X86BuiltinHeader::Xmmintrin,
X86BuiltinHeader::Emmintrin,
X86BuiltinHeader::Pmmintrin,
X86BuiltinHeader::Tmmintrin,
X86BuiltinHeader::Smmintrin,
X86BuiltinHeader::Nmmintrin,
X86BuiltinHeader::Wmmintrin,
X86BuiltinHeader::Immintrin,
X86BuiltinHeader::Avxintrin,
X86BuiltinHeader::Avx2intrin,
X86BuiltinHeader::Avx512fintrin,
X86BuiltinHeader::Avx512bwintrin,
X86BuiltinHeader::Avx512dqintrin,
X86BuiltinHeader::Avx512vlintrin,
X86BuiltinHeader::Fmaintrin,
X86BuiltinHeader::Bmiintrin,
X86BuiltinHeader::Bmi2intrin,
X86BuiltinHeader::Lzcntintrin,
X86BuiltinHeader::Cpuid,
]
}
fn generate_stddef(&self) -> String {
let mut s = String::new();
s.push_str("/*===---- stddef.h - Basic types and macros ---------------------===*/\n");
s.push_str("/* */\n");
s.push_str("/* ISO C standard: 7.19 Common definitions <stddef.h> */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __STDDEF_H\n");
s.push_str("#define __STDDEF_H\n\n");
s.push_str("#if !defined(__size_t_defined)\n");
s.push_str("#define __size_t_defined\n");
if self.config.pointer_width == 64 {
s.push_str("typedef __SIZE_TYPE__ size_t;\n");
s.push_str("/* typedef unsigned long size_t; */\n");
} else {
s.push_str("typedef __SIZE_TYPE__ size_t;\n");
s.push_str("/* typedef unsigned int size_t; */\n");
}
s.push_str("#endif\n\n");
s.push_str("#if !defined(__ptrdiff_t_defined)\n");
s.push_str("#define __ptrdiff_t_defined\n");
s.push_str("typedef __PTRDIFF_TYPE__ ptrdiff_t;\n");
s.push_str("#endif\n\n");
s.push_str("#if !defined(NULL)\n");
s.push_str("#if defined(__cplusplus)\n");
s.push_str("#if __cplusplus >= 201103L\n");
s.push_str("#define NULL nullptr\n");
s.push_str("#else\n");
s.push_str("#define NULL 0\n");
s.push_str("#endif\n");
s.push_str("#else /* C */\n");
s.push_str("#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L\n");
s.push_str("#define NULL nullptr\n");
s.push_str("#else\n");
s.push_str("#define NULL ((void*)0)\n");
s.push_str("#endif\n");
s.push_str("#endif\n");
s.push_str("#endif\n\n");
s.push_str("#if !defined(offsetof)\n");
s.push_str("#define offsetof(type, member) __builtin_offsetof(type, member)\n");
s.push_str("#endif\n\n");
s.push_str("#if !defined(__max_align_t_defined)\n");
s.push_str("#define __max_align_t_defined\n");
s.push_str("typedef struct {\n");
if self.config.max_alignment >= 16 {
s.push_str(" long long __clang_max_align_nonce1\n");
s.push_str(" __attribute__((__aligned__(__alignof__(long long))));\n");
s.push_str(" long double __clang_max_align_nonce2\n");
s.push_str(" __attribute__((__aligned__(__alignof__(long double))));\n");
} else if self.config.max_alignment >= 8 {
s.push_str(" long long __clang_max_align_nonce1\n");
s.push_str(" __attribute__((__aligned__(__alignof__(long long))));\n");
s.push_str(" double __clang_max_align_nonce2\n");
s.push_str(" __attribute__((__aligned__(__alignof__(double))));\n");
} else {
s.push_str(" long __clang_max_align_nonce1\n");
s.push_str(" __attribute__((__aligned__(__alignof__(long))));\n");
}
s.push_str("} max_align_t;\n");
s.push_str("#endif\n\n");
s.push_str("#if !defined(__wchar_t_defined)\n");
s.push_str("#define __wchar_t_defined\n");
s.push_str("#ifndef __cplusplus\n");
s.push_str("typedef __WCHAR_TYPE__ wchar_t;\n");
s.push_str("#endif\n");
s.push_str("#endif\n\n");
s.push_str(
"#if __STDC_VERSION__ >= 202311L || (defined(__cplusplus) && __cplusplus >= 201103L)\n",
);
s.push_str("#if !defined(__nullptr_t_defined)\n");
s.push_str("#define __nullptr_t_defined\n");
s.push_str("#ifdef __cplusplus\n");
s.push_str("typedef decltype(nullptr) nullptr_t;\n");
s.push_str("#else\n");
s.push_str("typedef typeof(nullptr) nullptr_t;\n");
s.push_str("#endif\n");
s.push_str("#endif\n");
s.push_str("#endif\n\n");
s.push_str("#if __STDC_VERSION__ >= 202311L\n");
s.push_str("#if !defined(unreachable)\n");
s.push_str("#define unreachable() __builtin_unreachable()\n");
s.push_str("#endif\n");
s.push_str("#endif\n\n");
s.push_str("#if __STDC_VERSION__ >= 202311L\n");
s.push_str("typedef unsigned char byte;\n");
s.push_str("#endif\n\n");
s.push_str("#if !defined(__rsize_t_defined)\n");
s.push_str("#define __rsize_t_defined\n");
s.push_str("typedef size_t rsize_t;\n");
s.push_str("#endif\n\n");
s.push_str("#endif /* __STDDEF_H */\n");
s
}
fn generate_stdarg(&self) -> String {
let mut s = String::new();
s.push_str("/*===---- stdarg.h - Variable argument lists ----------------------===*/\n");
s.push_str("/* */\n");
s.push_str("/* ISO C standard: 7.15 Variable arguments <stdarg.h> */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __STDARG_H\n");
s.push_str("#define __STDARG_H\n\n");
s.push_str("/*\n");
s.push_str(" * X86-64 System V AMD64 ABI va_list structure.\n");
s.push_str(" * The va_list type is an array of one element containing:\n");
s.push_str(" * - gp_offset: offset in bytes from reg_save_area to next GPR arg\n");
s.push_str(" * - fp_offset: offset in bytes from reg_save_area to next XMM arg\n");
s.push_str(" * - overflow_arg_area: pointer to stack arguments\n");
s.push_str(" * - reg_save_area: pointer to register save area\n");
s.push_str(" */\n\n");
s.push_str("typedef __builtin_va_list va_list;\n\n");
s.push_str("#define va_start(ap, param) __builtin_va_start(ap, param)\n");
s.push_str("#define va_end(ap) __builtin_va_end(ap)\n");
s.push_str("#define va_arg(ap, type) __builtin_va_arg(ap, type)\n");
s.push_str("#define va_copy(dest, src) __builtin_va_copy(dest, src)\n\n");
s.push_str("#ifndef __va_copy\n");
s.push_str("#define __va_copy(dest, src) __builtin_va_copy(dest, src)\n");
s.push_str("#endif\n\n");
s.push_str("/*\n");
s.push_str(" * When compiling with GCC, __builtin_va_list is defined as:\n");
s.push_str(" * typedef struct {\n");
s.push_str(" * unsigned int gp_offset;\n");
s.push_str(" * unsigned int fp_offset;\n");
s.push_str(" * void *overflow_arg_area;\n");
s.push_str(" * void *reg_save_area;\n");
s.push_str(" * } __va_list_tag[1];\n");
s.push_str(" */\n\n");
s.push_str("#endif /* __STDARG_H */\n");
s
}
fn generate_stdbool(&self) -> String {
let mut s = String::new();
s.push_str("/*===---- stdbool.h - Boolean type and values ----------------------===*/\n");
s.push_str("/* */\n");
s.push_str("/* ISO C standard: 7.18 Boolean type and values <stdbool.h> */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __STDBOOL_H\n");
s.push_str("#define __STDBOOL_H\n\n");
s.push_str("#ifndef __cplusplus\n\n");
s.push_str("#define bool _Bool\n");
s.push_str("#define true 1\n");
s.push_str("#define false 0\n\n");
s.push_str("#else /* __cplusplus */\n\n");
s.push_str("/*\n");
s.push_str(" * In C++, bool/true/false are keywords, but this header may still\n");
s.push_str(" * be included for compatibility. We define __bool_true_false_are_defined\n");
s.push_str(" * so that code can check for this header.\n");
s.push_str(" */\n\n");
s.push_str("#endif /* __cplusplus */\n\n");
s.push_str("#define __bool_true_false_are_defined 1\n\n");
s.push_str("#endif /* __STDBOOL_H */\n");
s
}
fn generate_stdint(&self) -> String {
let mut s = String::new();
s.push_str("/*===---- stdint.h - Integer types ---------------------------------===*/\n");
s.push_str("/* */\n");
s.push_str("/* ISO C standard: 7.20 Integer types <stdint.h> */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __STDINT_H\n");
s.push_str("#define __STDINT_H\n\n");
s.push_str("/* Exact-width integer types */\n");
s.push_str("typedef signed char int8_t;\n");
s.push_str("typedef short int16_t;\n");
s.push_str("typedef int int32_t;\n");
if self.config.pointer_width == 64 && self.config.long_width == 64 {
s.push_str("typedef long int64_t;\n");
} else {
s.push_str("typedef long long int64_t;\n");
}
s.push_str("\n");
s.push_str("typedef unsigned char uint8_t;\n");
s.push_str("typedef unsigned short uint16_t;\n");
s.push_str("typedef unsigned int uint32_t;\n");
if self.config.pointer_width == 64 && self.config.long_width == 64 {
s.push_str("typedef unsigned long uint64_t;\n");
} else {
s.push_str("typedef unsigned long long uint64_t;\n");
}
s.push_str("\n");
s.push_str("/* Minimum-width integer types */\n");
s.push_str("typedef int8_t int_least8_t;\n");
s.push_str("typedef int16_t int_least16_t;\n");
s.push_str("typedef int32_t int_least32_t;\n");
if self.config.long_width >= 64 {
s.push_str("typedef long int_least64_t;\n");
} else {
s.push_str("typedef long long int_least64_t;\n");
}
s.push_str("\n");
s.push_str("typedef uint8_t uint_least8_t;\n");
s.push_str("typedef uint16_t uint_least16_t;\n");
s.push_str("typedef uint32_t uint_least32_t;\n");
if self.config.long_width >= 64 {
s.push_str("typedef unsigned long uint_least64_t;\n");
} else {
s.push_str("typedef unsigned long long uint_least64_t;\n");
}
s.push_str("\n");
s.push_str("/* Fastest minimum-width integer types */\n");
s.push_str("typedef int8_t int_fast8_t;\n");
s.push_str("typedef int int_fast16_t;\n");
s.push_str("typedef int int_fast32_t;\n");
if self.config.pointer_width == 64 {
s.push_str("typedef long int_fast64_t;\n");
} else {
s.push_str("typedef long long int_fast64_t;\n");
}
s.push_str("\n");
s.push_str("typedef uint8_t uint_fast8_t;\n");
s.push_str("typedef unsigned int uint_fast16_t;\n");
s.push_str("typedef unsigned int uint_fast32_t;\n");
if self.config.pointer_width == 64 {
s.push_str("typedef unsigned long uint_fast64_t;\n");
} else {
s.push_str("typedef unsigned long long uint_fast64_t;\n");
}
s.push_str("\n");
s.push_str("/* Integer types capable of holding object pointers */\n");
if self.config.pointer_width == 64 {
s.push_str("typedef long intptr_t;\n");
s.push_str("typedef unsigned long uintptr_t;\n");
} else {
s.push_str("typedef int intptr_t;\n");
s.push_str("typedef unsigned int uintptr_t;\n");
}
s.push_str("\n");
s.push_str("/* Greatest-width integer types */\n");
if self.config.has_int128 && self.config.pointer_width == 64 {
s.push_str("#ifdef __SIZEOF_INT128__\n");
s.push_str("typedef __int128 intmax_t;\n");
s.push_str("typedef unsigned __int128 uintmax_t;\n");
s.push_str("#else\n");
s.push_str("typedef long long intmax_t;\n");
s.push_str("typedef unsigned long long uintmax_t;\n");
s.push_str("#endif\n");
} else {
s.push_str("typedef long long intmax_t;\n");
s.push_str("typedef unsigned long long uintmax_t;\n");
}
s.push_str("\n");
s.push_str("/* Limits of exact-width integer types */\n");
s.push_str("#define INT8_MIN (-128)\n");
s.push_str("#define INT8_MAX (127)\n");
s.push_str("#define UINT8_MAX (255U)\n\n");
s.push_str("#define INT16_MIN (-32767 - 1)\n");
s.push_str("#define INT16_MAX (32767)\n");
s.push_str("#define UINT16_MAX (65535U)\n\n");
s.push_str("#define INT32_MIN (-2147483647 - 1)\n");
s.push_str("#define INT32_MAX (2147483647)\n");
s.push_str("#define UINT32_MAX (4294967295U)\n\n");
if self.config.long_width >= 64 {
s.push_str("#define INT64_MIN (-9223372036854775807L - 1L)\n");
s.push_str("#define INT64_MAX (9223372036854775807L)\n");
s.push_str("#define UINT64_MAX (18446744073709551615UL)\n\n");
} else {
s.push_str("#define INT64_MIN (-9223372036854775807LL - 1LL)\n");
s.push_str("#define INT64_MAX (9223372036854775807LL)\n");
s.push_str("#define UINT64_MAX (18446744073709551615ULL)\n\n");
}
s.push_str("/* Limits of minimum-width integer types */\n");
s.push_str("#define INT_LEAST8_MIN INT8_MIN\n");
s.push_str("#define INT_LEAST8_MAX INT8_MAX\n");
s.push_str("#define UINT_LEAST8_MAX UINT8_MAX\n\n");
s.push_str("#define INT_LEAST16_MIN INT16_MIN\n");
s.push_str("#define INT_LEAST16_MAX INT16_MAX\n");
s.push_str("#define UINT_LEAST16_MAX UINT16_MAX\n\n");
s.push_str("#define INT_LEAST32_MIN INT32_MIN\n");
s.push_str("#define INT_LEAST32_MAX INT32_MAX\n");
s.push_str("#define UINT_LEAST32_MAX UINT32_MAX\n\n");
s.push_str("#define INT_LEAST64_MIN INT64_MIN\n");
s.push_str("#define INT_LEAST64_MAX INT64_MAX\n");
s.push_str("#define UINT_LEAST64_MAX UINT64_MAX\n\n");
s.push_str("/* Limits of fastest minimum-width integer types */\n");
s.push_str("#define INT_FAST8_MIN INT8_MIN\n");
s.push_str("#define INT_FAST8_MAX INT8_MAX\n");
s.push_str("#define UINT_FAST8_MAX UINT8_MAX\n\n");
s.push_str("#define INT_FAST16_MIN INT32_MIN\n");
s.push_str("#define INT_FAST16_MAX INT32_MAX\n");
s.push_str("#define UINT_FAST16_MAX UINT32_MAX\n\n");
s.push_str("#define INT_FAST32_MIN INT32_MIN\n");
s.push_str("#define INT_FAST32_MAX INT32_MAX\n");
s.push_str("#define UINT_FAST32_MAX UINT32_MAX\n\n");
s.push_str("#define INT_FAST64_MIN INT64_MIN\n");
s.push_str("#define INT_FAST64_MAX INT64_MAX\n");
s.push_str("#define UINT_FAST64_MAX UINT64_MAX\n\n");
s.push_str("/* Limits of pointer-sized integer types */\n");
if self.config.pointer_width == 64 {
s.push_str("#define INTPTR_MIN INT64_MIN\n");
s.push_str("#define INTPTR_MAX INT64_MAX\n");
s.push_str("#define UINTPTR_MAX UINT64_MAX\n\n");
s.push_str("#define PTRDIFF_MIN INT64_MIN\n");
s.push_str("#define PTRDIFF_MAX INT64_MAX\n\n");
s.push_str("#define SIZE_MAX UINT64_MAX\n\n");
} else {
s.push_str("#define INTPTR_MIN INT32_MIN\n");
s.push_str("#define INTPTR_MAX INT32_MAX\n");
s.push_str("#define UINTPTR_MAX UINT32_MAX\n\n");
s.push_str("#define PTRDIFF_MIN INT32_MIN\n");
s.push_str("#define PTRDIFF_MAX INT32_MAX\n\n");
s.push_str("#define SIZE_MAX UINT32_MAX\n\n");
}
s.push_str("/* Limits of greatest-width integer types */\n");
s.push_str("#define INTMAX_MIN INT64_MIN\n");
s.push_str("#define INTMAX_MAX INT64_MAX\n");
s.push_str("#define UINTMAX_MAX UINT64_MAX\n\n");
s.push_str("/* Limits of other integer types */\n");
s.push_str("#define WINT_MIN (-2147483647 - 1)\n");
s.push_str("#define WINT_MAX (2147483647)\n\n");
if self.config.wchar_width == 16 {
s.push_str("#define WCHAR_MIN (-32767 - 1)\n");
s.push_str("#define WCHAR_MAX (32767)\n\n");
} else {
s.push_str("#define WCHAR_MIN (-2147483647 - 1)\n");
s.push_str("#define WCHAR_MAX (2147483647)\n\n");
}
s.push_str("#define SIG_ATOMIC_MIN INT32_MIN\n");
s.push_str("#define SIG_ATOMIC_MAX INT32_MAX\n\n");
s.push_str("/* Macros for integer constant expressions */\n");
s.push_str("#define INT8_C(c) c\n");
s.push_str("#define INT16_C(c) c\n");
s.push_str("#define INT32_C(c) c\n");
if self.config.long_width >= 64 {
s.push_str("#define INT64_C(c) c ## L\n");
s.push_str("#define UINT64_C(c) c ## UL\n");
} else {
s.push_str("#define INT64_C(c) c ## LL\n");
s.push_str("#define UINT64_C(c) c ## ULL\n");
}
s.push_str("#define INTMAX_C(c) c ## LL\n\n");
s.push_str("#define UINT8_C(c) c ## U\n");
s.push_str("#define UINT16_C(c) c ## U\n");
s.push_str("#define UINT32_C(c) c ## U\n");
s.push_str("#define UINTMAX_C(c) c ## ULL\n\n");
s.push_str("#endif /* __STDINT_H */\n");
s
}
fn generate_limits(&self) -> String {
let mut s = String::new();
s.push_str("/*===---- limits.h - Implementation-defined integer limits ----------===*/\n");
s.push_str("/* */\n");
s.push_str("/* ISO C standard: 5.2.4.2.1 Sizes of integer types <limits.h> */\n");
s.push_str("/* */\n");
s.push_str("/* LP64 model for x86-64: */\n");
s.push_str("/* char=8 short=16 int=32 long=64 long long=64 pointer=64 */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __LIMITS_H\n");
s.push_str("#define __LIMITS_H\n\n");
s.push_str("/* Number of bits in a character */\n");
s.push_str("#define CHAR_BIT 8\n\n");
s.push_str("/* Minimum and maximum values a 'signed char' can hold */\n");
s.push_str("#define SCHAR_MIN (-128)\n");
s.push_str("#define SCHAR_MAX 127\n\n");
s.push_str("/* Maximum value an 'unsigned char' can hold */\n");
s.push_str("#define UCHAR_MAX 255\n\n");
s.push_str("/* Minimum and maximum values a 'char' can hold */\n");
if self.config.char_is_signed {
s.push_str("#define CHAR_MIN SCHAR_MIN\n");
s.push_str("#define CHAR_MAX SCHAR_MAX\n\n");
} else {
s.push_str("#define CHAR_MIN 0\n");
s.push_str("#define CHAR_MAX UCHAR_MAX\n\n");
}
s.push_str("/* Minimum and maximum values a 'short int' can hold */\n");
s.push_str("#define SHRT_MIN (-32767 - 1)\n");
s.push_str("#define SHRT_MAX 32767\n\n");
s.push_str("/* Maximum value an 'unsigned short int' can hold */\n");
s.push_str("#define USHRT_MAX 65535\n\n");
s.push_str("/* Minimum and maximum values an 'int' can hold */\n");
s.push_str("#define INT_MIN (-2147483647 - 1)\n");
s.push_str("#define INT_MAX 2147483647\n\n");
s.push_str("/* Maximum value an 'unsigned int' can hold */\n");
s.push_str("#define UINT_MAX 4294967295U\n\n");
s.push_str("/* Minimum and maximum values a 'long int' can hold */\n");
if self.config.long_width == 64 {
s.push_str("#define LONG_MIN (-9223372036854775807L - 1L)\n");
s.push_str("#define LONG_MAX 9223372036854775807L\n\n");
s.push_str("#define ULONG_MAX 18446744073709551615UL\n\n");
} else {
s.push_str("#define LONG_MIN (-2147483647L - 1L)\n");
s.push_str("#define LONG_MAX 2147483647L\n\n");
s.push_str("#define ULONG_MAX 4294967295UL\n\n");
}
s.push_str("/* Minimum and maximum values a 'long long int' can hold */\n");
s.push_str("#define LLONG_MIN (-9223372036854775807LL - 1LL)\n");
s.push_str("#define LLONG_MAX 9223372036854775807LL\n\n");
s.push_str("/* Maximum value an 'unsigned long long int' can hold */\n");
s.push_str("#define ULLONG_MAX 18446744073709551615ULL\n\n");
s.push_str("/* Maximum number of bytes in a multibyte character */\n");
s.push_str("#ifndef MB_LEN_MAX\n");
s.push_str("#define MB_LEN_MAX 16\n");
s.push_str("#endif\n\n");
s.push_str("/* POSIX extensions */\n");
s.push_str("#ifndef SSIZE_MAX\n");
if self.config.pointer_width == 64 {
s.push_str("#define SSIZE_MAX LONG_MAX\n");
} else {
s.push_str("#define SSIZE_MAX INT_MAX\n");
}
s.push_str("#endif\n\n");
s.push_str("/* GNU extensions */\n");
s.push_str("#ifndef LONG_LONG_MIN\n");
s.push_str("#define LONG_LONG_MIN LLONG_MIN\n");
s.push_str("#endif\n");
s.push_str("#ifndef LONG_LONG_MAX\n");
s.push_str("#define LONG_LONG_MAX LLONG_MAX\n");
s.push_str("#endif\n");
s.push_str("#ifndef ULONG_LONG_MAX\n");
s.push_str("#define ULONG_LONG_MAX ULLONG_MAX\n");
s.push_str("#endif\n\n");
s.push_str("#endif /* __LIMITS_H */\n");
s
}
fn generate_float(&self) -> String {
let mut s = String::new();
s.push_str("/*===---- float.h - Floating-point characteristics ------------------===*/\n");
s.push_str("/* */\n");
s.push_str("/* ISO C standard: 5.2.4.2.2 Characteristics of floating types */\n");
s.push_str("/* <float.h> */\n");
s.push_str("/* */\n");
s.push_str("/* x86 uses IEEE 754 binary32 for float, binary64 for double, */\n");
s.push_str("/* and 80-bit extended precision (x87) for long double. */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __FLOAT_H\n");
s.push_str("#define __FLOAT_H\n\n");
s.push_str("/* Radix of exponent representation */\n");
s.push_str("#define FLT_RADIX 2\n\n");
s.push_str("/* float (IEEE 754 binary32) */\n");
s.push_str("#define FLT_MANT_DIG 24\n");
s.push_str("#define FLT_DIG 6\n");
s.push_str("#define FLT_MIN_EXP (-125)\n");
s.push_str("#define FLT_MIN_10_EXP (-37)\n");
s.push_str("#define FLT_MAX_EXP 128\n");
s.push_str("#define FLT_MAX_10_EXP 38\n");
s.push_str("#define FLT_MIN 1.17549435082228750796873653722224568e-38F\n");
s.push_str("#define FLT_MAX 3.40282346638528859811704183484516925e+38F\n");
s.push_str("#define FLT_EPSILON 1.1920928955078125e-07F\n");
s.push_str("#define FLT_TRUE_MIN 1.40129846432481707092372958328991613e-45F\n");
s.push_str("#define FLT_HAS_SUBNORM 1\n");
s.push_str("#define FLT_DECIMAL_DIG 9\n\n");
s.push_str("/* double (IEEE 754 binary64) */\n");
s.push_str("#define DBL_MANT_DIG 53\n");
s.push_str("#define DBL_DIG 15\n");
s.push_str("#define DBL_MIN_EXP (-1021)\n");
s.push_str("#define DBL_MIN_10_EXP (-307)\n");
s.push_str("#define DBL_MAX_EXP 1024\n");
s.push_str("#define DBL_MAX_10_EXP 308\n");
s.push_str("#define DBL_MIN 2.22507385850720138309023271733240406e-308\n");
s.push_str("#define DBL_MAX 1.79769313486231570814527423731704357e+308\n");
s.push_str("#define DBL_EPSILON 2.22044604925031308084726333618164062e-16\n");
s.push_str("#define DBL_TRUE_MIN 4.94065645841246544176568792868221372e-324\n");
s.push_str("#define DBL_HAS_SUBNORM 1\n");
s.push_str("#define DBL_DECIMAL_DIG 17\n\n");
s.push_str("/* long double (80-bit x87 extended precision for x86-64) */\n");
s.push_str("#define LDBL_MANT_DIG 64\n");
s.push_str("#define LDBL_DIG 18\n");
s.push_str("#define LDBL_MIN_EXP (-16381)\n");
s.push_str("#define LDBL_MIN_10_EXP (-4931)\n");
s.push_str("#define LDBL_MAX_EXP 16384\n");
s.push_str("#define LDBL_MAX_10_EXP 4932\n");
s.push_str("#define LDBL_MIN 3.36210314311209350626267781732175260e-4932L\n");
s.push_str("#define LDBL_MAX 1.18973149535723176502126385303097021e+4932L\n");
s.push_str("#define LDBL_EPSILON 1.08420217248550443400745280086994171e-19L\n");
s.push_str("#define LDBL_TRUE_MIN 3.64519953188247460252840593361941982e-4951L\n");
s.push_str("#define LDBL_HAS_SUBNORM 1\n");
s.push_str("#define LDBL_DECIMAL_DIG 21\n\n");
s.push_str("/*\n");
s.push_str(" * FLT_EVAL_METHOD:\n");
s.push_str(" * 0 - all operations evaluated in the type's range and precision\n");
s.push_str(" * 1 - float operations promoted to double (legacy)\n");
s.push_str(" * 2 - all operations evaluated in long double (x87 default)\n");
s.push_str(" *\n");
s.push_str(" * x86 with SSE defaults to 0; x87 defaults to 2.\n");
s.push_str(" */\n");
s.push_str("#if defined(__SSE_MATH__) || defined(__SSE2_MATH__)\n");
s.push_str("#define FLT_EVAL_METHOD 0\n");
s.push_str("#else\n");
s.push_str("#define FLT_EVAL_METHOD 2\n");
s.push_str("#endif\n\n");
s.push_str("/* Number of decimal digits for long double */\n");
s.push_str("#ifndef DECIMAL_DIG\n");
s.push_str("#define DECIMAL_DIG LDBL_DECIMAL_DIG\n");
s.push_str("#endif\n\n");
s.push_str("#endif /* __FLOAT_H */\n");
s
}
fn generate_iso646(&self) -> String {
let mut s = String::new();
s.push_str("/*===---- iso646.h - Alternative operator spellings -----------------===*/\n");
s.push_str("/* */\n");
s.push_str("/* ISO C standard: 7.9 Alternative spellings <iso646.h> */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __ISO646_H\n");
s.push_str("#define __ISO646_H\n\n");
s.push_str("#ifndef __cplusplus\n\n");
s.push_str("/*\n");
s.push_str(" * Alternative spellings for operators using characters from the\n");
s.push_str(" * ISO 646 invariant character set, for systems that lack certain\n");
s.push_str(" * punctuation characters.\n");
s.push_str(" */\n\n");
s.push_str("#define and &&\n");
s.push_str("#define and_eq &=\n");
s.push_str("#define bitand &\n");
s.push_str("#define bitor |\n");
s.push_str("#define compl ~\n");
s.push_str("#define not !\n");
s.push_str("#define not_eq !=\n");
s.push_str("#define or ||\n");
s.push_str("#define or_eq |=\n");
s.push_str("#define xor ^\n");
s.push_str("#define xor_eq ^=\n\n");
s.push_str("#endif /* !__cplusplus */\n\n");
s.push_str("#endif /* __ISO646_H */\n");
s
}
fn generate_stdalign(&self) -> String {
let mut s = String::new();
s.push_str("/*===---- stdalign.h - Alignment macros -----------------------------===*/\n");
s.push_str("/* */\n");
s.push_str("/* ISO C standard: 7.15 Alignment <stdalign.h> */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __STDALIGN_H\n");
s.push_str("#define __STDALIGN_H\n\n");
s.push_str("#ifndef __cplusplus\n\n");
s.push_str("#define alignas _Alignas\n");
s.push_str("#define alignof _Alignof\n\n");
s.push_str("#define __alignas_is_defined 1\n");
s.push_str("#define __alignof_is_defined 1\n\n");
s.push_str("#endif /* !__cplusplus */\n\n");
s.push_str("#endif /* __STDALIGN_H */\n");
s
}
fn generate_stdnoreturn(&self) -> String {
let mut s = String::new();
s.push_str("/*===---- stdnoreturn.h - _Noreturn macro ---------------------------===*/\n");
s.push_str("/* */\n");
s.push_str("/* ISO C standard: 7.23 _Noreturn <stdnoreturn.h> */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __STDNORETURN_H\n");
s.push_str("#define __STDNORETURN_H\n\n");
s.push_str("#ifndef __cplusplus\n\n");
s.push_str("#define noreturn _Noreturn\n\n");
s.push_str("#endif /* !__cplusplus */\n\n");
s.push_str("#endif /* __STDNORETURN_H */\n");
s
}
fn generate_stdatomic(&self) -> String {
let mut s = String::new();
s.push_str("/*===---- stdatomic.h - Atomics -------------------------------------===*/\n");
s.push_str("/* */\n");
s.push_str("/* ISO C standard: 7.17 Atomics <stdatomic.h> */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __STDATOMIC_H\n");
s.push_str("#define __STDATOMIC_H\n\n");
s.push_str("#include <stddef.h>\n");
s.push_str("#include <stdint.h>\n\n");
s.push_str("typedef enum memory_order {\n");
s.push_str(" memory_order_relaxed = __ATOMIC_RELAXED,\n");
s.push_str(" memory_order_consume = __ATOMIC_CONSUME,\n");
s.push_str(" memory_order_acquire = __ATOMIC_ACQUIRE,\n");
s.push_str(" memory_order_release = __ATOMIC_RELEASE,\n");
s.push_str(" memory_order_acq_rel = __ATOMIC_ACQ_REL,\n");
s.push_str(" memory_order_seq_cst = __ATOMIC_SEQ_CST\n");
s.push_str("} memory_order;\n\n");
s.push_str("/* Lock-free property macros */\n");
s.push_str("#define ATOMIC_BOOL_LOCK_FREE __CLANG_ATOMIC_BOOL_LOCK_FREE\n");
s.push_str("#define ATOMIC_CHAR_LOCK_FREE __CLANG_ATOMIC_CHAR_LOCK_FREE\n");
s.push_str("#define ATOMIC_CHAR16_T_LOCK_FREE __CLANG_ATOMIC_CHAR16_T_LOCK_FREE\n");
s.push_str("#define ATOMIC_CHAR32_T_LOCK_FREE __CLANG_ATOMIC_CHAR32_T_LOCK_FREE\n");
s.push_str("#define ATOMIC_WCHAR_T_LOCK_FREE __CLANG_ATOMIC_WCHAR_T_LOCK_FREE\n");
s.push_str("#define ATOMIC_SHORT_LOCK_FREE __CLANG_ATOMIC_SHORT_LOCK_FREE\n");
s.push_str("#define ATOMIC_INT_LOCK_FREE __CLANG_ATOMIC_INT_LOCK_FREE\n");
s.push_str("#define ATOMIC_LONG_LOCK_FREE __CLANG_ATOMIC_LONG_LOCK_FREE\n");
s.push_str("#define ATOMIC_LLONG_LOCK_FREE __CLANG_ATOMIC_LLONG_LOCK_FREE\n");
s.push_str("#define ATOMIC_POINTER_LOCK_FREE __CLANG_ATOMIC_POINTER_LOCK_FREE\n\n");
s.push_str("/* Atomic type definitions */\n");
s.push_str("typedef _Atomic(_Bool) atomic_bool;\n");
s.push_str("typedef _Atomic(char) atomic_char;\n");
s.push_str("typedef _Atomic(signed char) atomic_schar;\n");
s.push_str("typedef _Atomic(unsigned char) atomic_uchar;\n");
s.push_str("typedef _Atomic(short) atomic_short;\n");
s.push_str("typedef _Atomic(unsigned short) atomic_ushort;\n");
s.push_str("typedef _Atomic(int) atomic_int;\n");
s.push_str("typedef _Atomic(unsigned int) atomic_uint;\n");
s.push_str("typedef _Atomic(long) atomic_long;\n");
s.push_str("typedef _Atomic(unsigned long) atomic_ulong;\n");
s.push_str("typedef _Atomic(long long) atomic_llong;\n");
s.push_str("typedef _Atomic(unsigned long long) atomic_ullong;\n");
s.push_str("typedef _Atomic(int_least8_t) atomic_int_least8_t;\n");
s.push_str("typedef _Atomic(uint_least8_t) atomic_uint_least8_t;\n");
s.push_str("typedef _Atomic(int_least16_t) atomic_int_least16_t;\n");
s.push_str("typedef _Atomic(uint_least16_t) atomic_uint_least16_t;\n");
s.push_str("typedef _Atomic(int_least32_t) atomic_int_least32_t;\n");
s.push_str("typedef _Atomic(uint_least32_t) atomic_uint_least32_t;\n");
s.push_str("typedef _Atomic(int_least64_t) atomic_int_least64_t;\n");
s.push_str("typedef _Atomic(uint_least64_t) atomic_uint_least64_t;\n");
s.push_str("typedef _Atomic(intptr_t) atomic_intptr_t;\n");
s.push_str("typedef _Atomic(uintptr_t) atomic_uintptr_t;\n");
s.push_str("typedef _Atomic(size_t) atomic_size_t;\n");
s.push_str("typedef _Atomic(ptrdiff_t) atomic_ptrdiff_t;\n");
s.push_str("typedef _Atomic(intmax_t) atomic_intmax_t;\n");
s.push_str("typedef _Atomic(uintmax_t) atomic_uintmax_t;\n\n");
s.push_str("/* Atomic flag type */\n");
s.push_str("typedef struct atomic_flag { _Atomic(_Bool) __flag; } atomic_flag;\n");
s.push_str("#define ATOMIC_FLAG_INIT { 0 }\n\n");
s.push_str("#define ATOMIC_VAR_INIT(value) (value)\n\n");
s.push_str("/* Generic atomic operations */\n");
s.push_str("#define atomic_init(obj, value) \\\n");
s.push_str(" __c11_atomic_init(obj, value)\n\n");
s.push_str("#define atomic_load(object) \\\n");
s.push_str(" __c11_atomic_load(object, memory_order_seq_cst)\n\n");
s.push_str("#define atomic_load_explicit(object, order) \\\n");
s.push_str(" __c11_atomic_load(object, order)\n\n");
s.push_str("#define atomic_store(object, desired) \\\n");
s.push_str(" __c11_atomic_store(object, desired, memory_order_seq_cst)\n\n");
s.push_str("#define atomic_store_explicit(object, desired, order) \\\n");
s.push_str(" __c11_atomic_store(object, desired, order)\n\n");
s.push_str("#define atomic_exchange(object, desired) \\\n");
s.push_str(" __c11_atomic_exchange(object, desired, memory_order_seq_cst)\n\n");
s.push_str("#define atomic_exchange_explicit(object, desired, order) \\\n");
s.push_str(" __c11_atomic_exchange(object, desired, order)\n\n");
s.push_str("#define atomic_compare_exchange_strong(object, expected, desired) \\\n");
s.push_str(" __c11_atomic_compare_exchange_strong(object, expected, desired, \\\n");
s.push_str(" memory_order_seq_cst, memory_order_seq_cst)\n\n");
s.push_str("#define atomic_compare_exchange_strong_explicit(object, expected, desired, succ, fail) \\\n");
s.push_str(
" __c11_atomic_compare_exchange_strong(object, expected, desired, succ, fail)\n\n",
);
s.push_str("#define atomic_compare_exchange_weak(object, expected, desired) \\\n");
s.push_str(" __c11_atomic_compare_exchange_weak(object, expected, desired, \\\n");
s.push_str(" memory_order_seq_cst, memory_order_seq_cst)\n\n");
s.push_str("#define atomic_compare_exchange_weak_explicit(object, expected, desired, succ, fail) \\\n");
s.push_str(
" __c11_atomic_compare_exchange_weak(object, expected, desired, succ, fail)\n\n",
);
s.push_str("#define atomic_fetch_add(object, operand) \\\n");
s.push_str(" __c11_atomic_fetch_add(object, operand, memory_order_seq_cst)\n\n");
s.push_str("#define atomic_fetch_add_explicit(object, operand, order) \\\n");
s.push_str(" __c11_atomic_fetch_add(object, operand, order)\n\n");
s.push_str("#define atomic_fetch_sub(object, operand) \\\n");
s.push_str(" __c11_atomic_fetch_sub(object, operand, memory_order_seq_cst)\n\n");
s.push_str("#define atomic_fetch_sub_explicit(object, operand, order) \\\n");
s.push_str(" __c11_atomic_fetch_sub(object, operand, order)\n\n");
s.push_str("#define atomic_fetch_or(object, operand) \\\n");
s.push_str(" __c11_atomic_fetch_or(object, operand, memory_order_seq_cst)\n\n");
s.push_str("#define atomic_fetch_or_explicit(object, operand, order) \\\n");
s.push_str(" __c11_atomic_fetch_or(object, operand, order)\n\n");
s.push_str("#define atomic_fetch_xor(object, operand) \\\n");
s.push_str(" __c11_atomic_fetch_xor(object, operand, memory_order_seq_cst)\n\n");
s.push_str("#define atomic_fetch_xor_explicit(object, operand, order) \\\n");
s.push_str(" __c11_atomic_fetch_xor(object, operand, order)\n\n");
s.push_str("#define atomic_fetch_and(object, operand) \\\n");
s.push_str(" __c11_atomic_fetch_and(object, operand, memory_order_seq_cst)\n\n");
s.push_str("#define atomic_fetch_and_explicit(object, operand, order) \\\n");
s.push_str(" __c11_atomic_fetch_and(object, operand, order)\n\n");
s.push_str("/* Fence operations */\n");
s.push_str("#define atomic_thread_fence(order) \\\n");
s.push_str(" __c11_atomic_thread_fence(order)\n\n");
s.push_str("#define atomic_signal_fence(order) \\\n");
s.push_str(" __c11_atomic_signal_fence(order)\n\n");
s.push_str("/* Flag operations */\n");
s.push_str("#define atomic_flag_test_and_set(object) \\\n");
s.push_str(" __c11_atomic_exchange(&(object)->__flag, 1, memory_order_seq_cst)\n\n");
s.push_str("#define atomic_flag_test_and_set_explicit(object, order) \\\n");
s.push_str(" __c11_atomic_exchange(&(object)->__flag, 1, order)\n\n");
s.push_str("#define atomic_flag_clear(object) \\\n");
s.push_str(" __c11_atomic_store(&(object)->__flag, 0, memory_order_seq_cst)\n\n");
s.push_str("#define atomic_flag_clear_explicit(object, order) \\\n");
s.push_str(" __c11_atomic_store(&(object)->__flag, 0, order)\n\n");
s.push_str("/* Kill dependency for memory_order_consume */\n");
s.push_str("#define atomic_thread_fence(order) \\\n");
s.push_str(" __c11_atomic_thread_fence(order)\n\n");
s.push_str("#define kill_dependency(y) (y)\n\n");
s.push_str("#endif /* __STDATOMIC_H */\n");
s
}
fn generate_tgmath(&self) -> String {
let mut s = String::new();
s.push_str("/*===---- tgmath.h - Type-generic math ------------------------------===*/\n");
s.push_str("/* */\n");
s.push_str("/* ISO C standard: 7.25 Type-generic math <tgmath.h> */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __TGMATH_H\n");
s.push_str("#define __TGMATH_H\n\n");
s.push_str("/*\n");
s.push_str(" * Type-generic math macros using __builtin_tgmath.\n");
s.push_str(" * Each macro dispatches to float/double/long double variants\n");
s.push_str(" * based on the argument types.\n");
s.push_str(" */\n\n");
s.push_str("/* Trigonometric functions */\n");
s.push_str("#define acos(x) __builtin_tgmath(acosf, acos, acosl, x)\n");
s.push_str("#define asin(x) __builtin_tgmath(asinf, asin, asinl, x)\n");
s.push_str("#define atan(x) __builtin_tgmath(atanf, atan, atanl, x)\n");
s.push_str("#define atan2(y,x) __builtin_tgmath(atan2f, atan2, atan2l, y, x)\n");
s.push_str("#define cos(x) __builtin_tgmath(cosf, cos, cosl, x)\n");
s.push_str("#define sin(x) __builtin_tgmath(sinf, sin, sinl, x)\n");
s.push_str("#define tan(x) __builtin_tgmath(tanf, tan, tanl, x)\n\n");
s.push_str("/* Hyperbolic functions */\n");
s.push_str("#define acosh(x) __builtin_tgmath(acoshf, acosh, acoshl, x)\n");
s.push_str("#define asinh(x) __builtin_tgmath(asinhf, asinh, asinhl, x)\n");
s.push_str("#define atanh(x) __builtin_tgmath(atanhf, atanh, atanhl, x)\n");
s.push_str("#define cosh(x) __builtin_tgmath(coshf, cosh, coshl, x)\n");
s.push_str("#define sinh(x) __builtin_tgmath(sinhf, sinh, sinhl, x)\n");
s.push_str("#define tanh(x) __builtin_tgmath(tanhf, tanh, tanhl, x)\n\n");
s.push_str("/* Exponential and logarithmic functions */\n");
s.push_str("#define exp(x) __builtin_tgmath(expf, exp, expl, x)\n");
s.push_str("#define exp2(x) __builtin_tgmath(exp2f, exp2, exp2l, x)\n");
s.push_str("#define expm1(x) __builtin_tgmath(expm1f, expm1, expm1l, x)\n");
s.push_str("#define frexp(v,p) __builtin_tgmath(frexpf, frexp, frexpl, v, p)\n");
s.push_str("#define ldexp(x,e) __builtin_tgmath(ldexpf, ldexp, ldexpl, x, e)\n");
s.push_str("#define log(x) __builtin_tgmath(logf, log, logl, x)\n");
s.push_str("#define log10(x) __builtin_tgmath(log10f, log10, log10l, x)\n");
s.push_str("#define log1p(x) __builtin_tgmath(log1pf, log1p, log1pl, x)\n");
s.push_str("#define log2(x) __builtin_tgmath(log2f, log2, log2l, x)\n");
s.push_str("#define logb(x) __builtin_tgmath(logbf, logb, logbl, x)\n");
s.push_str("#define modf(v,p) __builtin_tgmath(modff, modf, modfl, v, p)\n");
s.push_str("#define scalbn(x,n) __builtin_tgmath(scalbnf, scalbn, scalbnl, x, n)\n");
s.push_str("#define scalbln(x,n) __builtin_tgmath(scalblnf, scalbln, scalblnl, x, n)\n\n");
s.push_str("/* Power and absolute-value functions */\n");
s.push_str("#define cbrt(x) __builtin_tgmath(cbrtf, cbrt, cbrtl, x)\n");
s.push_str("#define fabs(x) __builtin_tgmath(fabsf, fabs, fabsl, x)\n");
s.push_str("#define hypot(x,y) __builtin_tgmath(hypotf, hypot, hypotl, x, y)\n");
s.push_str("#define pow(x,y) __builtin_tgmath(powf, pow, powl, x, y)\n");
s.push_str("#define sqrt(x) __builtin_tgmath(sqrtf, sqrt, sqrtl, x)\n\n");
s.push_str("/* Error and gamma functions */\n");
s.push_str("#define erf(x) __builtin_tgmath(erff, erf, erfl, x)\n");
s.push_str("#define erfc(x) __builtin_tgmath(erfcf, erfc, erfcl, x)\n");
s.push_str("#define lgamma(x) __builtin_tgmath(lgammaf, lgamma, lgammal, x)\n");
s.push_str("#define tgamma(x) __builtin_tgmath(tgammaf, tgamma, tgammal, x)\n\n");
s.push_str("/* Nearest integer functions */\n");
s.push_str("#define ceil(x) __builtin_tgmath(ceilf, ceil, ceill, x)\n");
s.push_str("#define floor(x) __builtin_tgmath(floorf, floor, floorl, x)\n");
s.push_str("#define nearbyint(x) __builtin_tgmath(nearbyintf, nearbyint, nearbyintl, x)\n");
s.push_str("#define rint(x) __builtin_tgmath(rintf, rint, rintl, x)\n");
s.push_str("#define lrint(x) __builtin_tgmath(lrintf, lrint, lrintl, x)\n");
s.push_str("#define llrint(x) __builtin_tgmath(llrintf, llrint, llrintl, x)\n");
s.push_str("#define round(x) __builtin_tgmath(roundf, round, roundl, x)\n");
s.push_str("#define lround(x) __builtin_tgmath(lroundf, lround, lroundl, x)\n");
s.push_str("#define llround(x) __builtin_tgmath(llroundf, llround, llroundl, x)\n");
s.push_str("#define trunc(x) __builtin_tgmath(truncf, trunc, truncl, x)\n\n");
s.push_str("/* Remainder functions */\n");
s.push_str("#define fmod(x,y) __builtin_tgmath(fmodf, fmod, fmodl, x, y)\n");
s.push_str(
"#define remainder(x,y) __builtin_tgmath(remainderf, remainder, remainderl, x, y)\n",
);
s.push_str("#define remquo(x,y,q) __builtin_tgmath(remquof, remquo, remquol, x, y, q)\n\n");
s.push_str("/* Manipulation functions */\n");
s.push_str(
"#define copysign(x,y) __builtin_tgmath(copysignf, copysign, copysignl, x, y)\n",
);
s.push_str("#define nan(s) __builtin_tgmath(nanf, nan, nanl, s)\n");
s.push_str(
"#define nextafter(x,y) __builtin_tgmath(nextafterf, nextafter, nextafterl, x, y)\n",
);
s.push_str("#define nexttoward(x,y) __builtin_tgmath(nexttowardf, nexttoward, nexttowardl, x, y)\n\n");
s.push_str("/* Minimum, maximum, difference functions */\n");
s.push_str("#define fdim(x,y) __builtin_tgmath(fdimf, fdim, fdiml, x, y)\n");
s.push_str("#define fmax(x,y) __builtin_tgmath(fmaxf, fmax, fmaxl, x, y)\n");
s.push_str("#define fmin(x,y) __builtin_tgmath(fminf, fmin, fminl, x, y)\n\n");
s.push_str("/* Other macros */\n");
s.push_str("#define fma(x,y,z) __builtin_tgmath(fmaf, fma, fmal, x, y, z)\n\n");
s.push_str("#endif /* __TGMATH_H */\n");
s
}
fn generate_stdckdint(&self) -> String {
let mut s = String::new();
s.push_str("/*===---- stdckdint.h - Checked integer arithmetic (C23) -------------===*/\n");
s.push_str("/* */\n");
s.push_str("/* ISO C standard: 7.20 Checked Integer Arithmetic <stdckdint.h> */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __STDCKDINT_H\n");
s.push_str("#define __STDCKDINT_H\n\n");
s.push_str("/*\n");
s.push_str(" * C23 checked integer arithmetic macros.\n");
s.push_str(" * Each macro returns false (0) if the operation succeeds (result stored\n");
s.push_str(" * in *result), or true (non-zero) on overflow.\n");
s.push_str(" */\n\n");
s.push_str("#define ckd_add(result, a, b) \\\n");
s.push_str(" __builtin_add_overflow((a), (b), (result))\n\n");
s.push_str("#define ckd_sub(result, a, b) \\\n");
s.push_str(" __builtin_sub_overflow((a), (b), (result))\n\n");
s.push_str("#define ckd_mul(result, a, b) \\\n");
s.push_str(" __builtin_mul_overflow((a), (b), (result))\n\n");
s.push_str("#endif /* __STDCKDINT_H */\n");
s
}
fn generate_x86intrin(&self) -> String {
let mut s = String::new();
s.push_str("/*===---- x86intrin.h - X86 intrinsic functions (umbrella header) ----===*/\n");
s.push_str("/* */\n");
s.push_str("/* This header includes all available x86 intrinsic headers based on */\n");
s.push_str("/* the target CPU features. */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __X86INTRIN_H\n");
s.push_str("#define __X86INTRIN_H\n\n");
s.push_str("#include <cpuid.h>\n\n");
s.push_str("/* SIMD intrinsic headers included based on target features */\n");
if self.config.has_mmx {
s.push_str("#include <mmintrin.h>\n");
}
if self.config.has_sse {
s.push_str("#include <xmmintrin.h>\n");
}
if self.config.has_sse2 {
s.push_str("#include <emmintrin.h>\n");
}
if self.config.has_sse3 {
s.push_str("#include <pmmintrin.h>\n");
}
if self.config.has_ssse3 {
s.push_str("#include <tmmintrin.h>\n");
}
if self.config.has_sse4_1 {
s.push_str("#include <smmintrin.h>\n");
}
if self.config.has_sse4_2 {
s.push_str("#include <nmmintrin.h>\n");
}
if self.config.has_aes {
s.push_str("#include <wmmintrin.h>\n");
}
if self.config.has_bmi {
s.push_str("#include <bmiintrin.h>\n");
}
if self.config.has_bmi2 {
s.push_str("#include <bmi2intrin.h>\n");
}
if self.config.has_lzcnt {
s.push_str("#include <lzcntintrin.h>\n");
}
if self.config.has_fma {
s.push_str("#include <fmaintrin.h>\n");
}
if self.config.has_avx {
s.push_str("#include <immintrin.h>\n");
s.push_str("#include <avxintrin.h>\n");
}
if self.config.has_avx2 {
s.push_str("#include <avx2intrin.h>\n");
}
if self.config.has_avx512f {
s.push_str("#include <avx512fintrin.h>\n");
}
if self.config.has_avx512bw {
s.push_str("#include <avx512bwintrin.h>\n");
}
if self.config.has_avx512dq {
s.push_str("#include <avx512dqintrin.h>\n");
}
if self.config.has_avx512vl {
s.push_str("#include <avx512vlintrin.h>\n");
}
s.push_str("\n#endif /* __X86INTRIN_H */\n");
s
}
fn generate_mmintrin(&self) -> String {
let mut s = String::new();
s.push_str("/*===---- mmintrin.h - MMX intrinsics --------------------------------===*/\n");
s.push_str("/* */\n");
s.push_str("/* Intel MMX (MultiMedia eXtensions) intrinsics. */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __MMINTRIN_H\n");
s.push_str("#define __MMINTRIN_H\n\n");
s.push_str("#if !defined(__MMX__)\n");
s.push_str("#error \"MMX instruction set not enabled\"\n");
s.push_str("#endif\n\n");
s.push_str("/* MMX 64-bit vector type */\n");
s.push_str("typedef int __m64 __attribute__((__vector_size__(8), __aligned__(8)));\n\n");
s.push_str("/* MMX integer vector type */\n");
s.push_str(
"typedef long long __m64i __attribute__((__vector_size__(8), __aligned__(8)));\n\n",
);
s.push_str("/* Construction */\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_setzero_si64(void)\n");
s.push_str("{\n");
s.push_str(" return (__m64)0LL;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_set_pi32(int __i1, int __i0)\n");
s.push_str("{\n");
s.push_str(" return (__m64)__builtin_ia32_vec_init_v2si(__i0, __i1);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_set_pi16(short __w3, short __w2, short __w1, short __w0)\n");
s.push_str("{\n");
s.push_str(" return (__m64)__builtin_ia32_vec_init_v4hi(__w0, __w1, __w2, __w3);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_set_pi8(char __b7, char __b6, char __b5, char __b4,\n");
s.push_str(" char __b3, char __b2, char __b1, char __b0)\n");
s.push_str("{\n");
s.push_str(" return (__m64)__builtin_ia32_vec_init_v8qi(__b0, __b1, __b2, __b3,\n");
s.push_str(" __b4, __b5, __b6, __b7);\n");
s.push_str("}\n\n");
s.push_str("/* Conversion */\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_cvtsi32_si64(int __i)\n");
s.push_str("{\n");
s.push_str(" return (__m64)__builtin_ia32_vec_init_v2si(__i, 0);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ int __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_cvtsi64_si32(__m64 __i)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_vec_ext_v2si((__v2si)__i, 0);\n");
s.push_str("}\n\n");
s.push_str("/* Packed addition */\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_add_pi8(__m64 __m1, __m64 __m2)\n");
s.push_str("{\n");
s.push_str(" return (__m64)((__v8qi)__m1 + (__v8qi)__m2);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_add_pi16(__m64 __m1, __m64 __m2)\n");
s.push_str("{\n");
s.push_str(" return (__m64)((__v4hi)__m1 + (__v4hi)__m2);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_add_pi32(__m64 __m1, __m64 __m2)\n");
s.push_str("{\n");
s.push_str(" return (__m64)((__v2si)__m1 + (__v2si)__m2);\n");
s.push_str("}\n\n");
s.push_str("/* Packed subtraction */\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_sub_pi8(__m64 __m1, __m64 __m2)\n");
s.push_str("{\n");
s.push_str(" return (__m64)((__v8qi)__m1 - (__v8qi)__m2);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_sub_pi16(__m64 __m1, __m64 __m2)\n");
s.push_str("{\n");
s.push_str(" return (__m64)((__v4hi)__m1 - (__v4hi)__m2);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_sub_pi32(__m64 __m1, __m64 __m2)\n");
s.push_str("{\n");
s.push_str(" return (__m64)((__v2si)__m1 - (__v2si)__m2);\n");
s.push_str("}\n\n");
s.push_str("/* Packed multiply (16-bit producing 32-bit) */\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_mullo_pi16(__m64 __m1, __m64 __m2)\n");
s.push_str("{\n");
s.push_str(" return (__m64)((__v4hi)__m1 * (__v4hi)__m2);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_madd_pi16(__m64 __m1, __m64 __m2)\n");
s.push_str("{\n");
s.push_str(" return (__m64)__builtin_ia32_pmaddwd((__v4hi)__m1, (__v4hi)__m2);\n");
s.push_str("}\n\n");
s.push_str("/* Packed shifts */\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_sll_pi16(__m64 __m, __m64 __count)\n");
s.push_str("{\n");
s.push_str(" return (__m64)__builtin_ia32_psllw((__v4hi)__m, (__v4hi)__count);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_sll_pi32(__m64 __m, __m64 __count)\n");
s.push_str("{\n");
s.push_str(" return (__m64)__builtin_ia32_pslld((__v2si)__m, (__v2si)__count);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_srl_pi16(__m64 __m, __m64 __count)\n");
s.push_str("{\n");
s.push_str(" return (__m64)__builtin_ia32_psrlw((__v4hi)__m, (__v4hi)__count);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_srl_pi32(__m64 __m, __m64 __count)\n");
s.push_str("{\n");
s.push_str(" return (__m64)__builtin_ia32_psrld((__v2si)__m, (__v2si)__count);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_sra_pi16(__m64 __m, __m64 __count)\n");
s.push_str("{\n");
s.push_str(" return (__m64)__builtin_ia32_psraw((__v4hi)__m, (__v4hi)__count);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_sra_pi32(__m64 __m, __m64 __count)\n");
s.push_str("{\n");
s.push_str(" return (__m64)__builtin_ia32_psrad((__v2si)__m, (__v2si)__count);\n");
s.push_str("}\n\n");
s.push_str("/* Bitwise operations */\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_and_si64(__m64 __m1, __m64 __m2)\n");
s.push_str("{\n");
s.push_str(" return __m1 & __m2;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_or_si64(__m64 __m1, __m64 __m2)\n");
s.push_str("{\n");
s.push_str(" return __m1 | __m2;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_xor_si64(__m64 __m1, __m64 __m2)\n");
s.push_str("{\n");
s.push_str(" return __m1 ^ __m2;\n");
s.push_str("}\n\n");
s.push_str("/* Packed comparison for equality */\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_cmpeq_pi8(__m64 __m1, __m64 __m2)\n");
s.push_str("{\n");
s.push_str(" return (__m64)((__v8qi)__m1 == (__v8qi)__m2);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_cmpeq_pi16(__m64 __m1, __m64 __m2)\n");
s.push_str("{\n");
s.push_str(" return (__m64)((__v4hi)__m1 == (__v4hi)__m2);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_cmpeq_pi32(__m64 __m1, __m64 __m2)\n");
s.push_str("{\n");
s.push_str(" return (__m64)((__v2si)__m1 == (__v2si)__m2);\n");
s.push_str("}\n\n");
s.push_str("/* Pack and unpack */\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_packs_pi16(__m64 __m1, __m64 __m2)\n");
s.push_str("{\n");
s.push_str(" return (__m64)__builtin_ia32_packsswb((__v4hi)__m1, (__v4hi)__m2);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_packs_pi32(__m64 __m1, __m64 __m2)\n");
s.push_str("{\n");
s.push_str(" return (__m64)__builtin_ia32_packssdw((__v2si)__m1, (__v2si)__m2);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_unpackhi_pi8(__m64 __m1, __m64 __m2)\n");
s.push_str("{\n");
s.push_str(" return (__m64)__builtin_shufflevector((__v8qi)__m1, (__v8qi)__m2,\n");
s.push_str(" 4, 12, 5, 13, 6, 14, 7, 15);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_unpacklo_pi8(__m64 __m1, __m64 __m2)\n");
s.push_str("{\n");
s.push_str(" return (__m64)__builtin_shufflevector((__v8qi)__m1, (__v8qi)__m2,\n");
s.push_str(" 0, 8, 1, 9, 2, 10, 3, 11);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ void __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_empty(void)\n");
s.push_str("{\n");
s.push_str(" __builtin_ia32_emms();\n");
s.push_str("}\n\n");
s.push_str("#endif /* __MMINTRIN_H */\n");
s
}
fn generate_xmmintrin(&self) -> String {
let mut s = String::new();
s.push_str("/*===---- xmmintrin.h - SSE intrinsics -------------------------------===*/\n");
s.push_str("/* */\n");
s.push_str("/* Intel SSE (Streaming SIMD Extensions) intrinsics. */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __XMMINTRIN_H\n");
s.push_str("#define __XMMINTRIN_H\n\n");
s.push_str("#if !defined(__SSE__)\n");
s.push_str("#error \"SSE instruction set not enabled\"\n");
s.push_str("#endif\n\n");
s.push_str("/* SSE 128-bit types */\n");
s.push_str("typedef float __m128 __attribute__((__vector_size__(16), __aligned__(16)));\n");
s.push_str(
"typedef int __m128i __attribute__((__vector_size__(16), __aligned__(16)));\n\n",
);
s.push_str("/* Construction and conversion */\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_setzero_ps(void)\n");
s.push_str("{\n");
s.push_str(" return __extension__ (__m128){ 0.0f, 0.0f, 0.0f, 0.0f };\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_set_ps(float __e3, float __e2, float __e1, float __e0)\n");
s.push_str("{\n");
s.push_str(" return __extension__ (__m128){ __e0, __e1, __e2, __e3 };\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_set1_ps(float __f)\n");
s.push_str("{\n");
s.push_str(" return __extension__ (__m128){ __f, __f, __f, __f };\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_set_ss(float __f)\n");
s.push_str("{\n");
s.push_str(" return __extension__ (__m128){ __f, 0.0f, 0.0f, 0.0f };\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_load_ps(float const *__p)\n");
s.push_str("{\n");
s.push_str(" return *(__m128 const *)__p;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_loadu_ps(float const *__p)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_loadups(__p);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_load_ss(float const *__p)\n");
s.push_str("{\n");
s.push_str(" return __extension__ (__m128){ *__p, 0.0f, 0.0f, 0.0f };\n");
s.push_str("}\n\n");
s.push_str("static __inline__ void __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_store_ps(float *__p, __m128 __a)\n");
s.push_str("{\n");
s.push_str(" *(__m128 *)__p = __a;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ void __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_storeu_ps(float *__p, __m128 __a)\n");
s.push_str("{\n");
s.push_str(" __builtin_ia32_storeups(__p, __a);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ void __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_store_ss(float *__p, __m128 __a)\n");
s.push_str("{\n");
s.push_str(" *__p = __a[0];\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_load1_ps(float const *__p)\n");
s.push_str("{\n");
s.push_str(" float __f = *__p;\n");
s.push_str(" return __extension__ (__m128){ __f, __f, __f, __f };\n");
s.push_str("}\n\n");
s.push_str("/* Arithmetic operations */\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_add_ps(__m128 __a, __m128 __b)\n");
s.push_str("{\n");
s.push_str(" return __a + __b;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_add_ss(__m128 __a, __m128 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_addss(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_sub_ps(__m128 __a, __m128 __b)\n");
s.push_str("{\n");
s.push_str(" return __a - __b;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_sub_ss(__m128 __a, __m128 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_subss(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_mul_ps(__m128 __a, __m128 __b)\n");
s.push_str("{\n");
s.push_str(" return __a * __b;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_mul_ss(__m128 __a, __m128 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_mulss(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_div_ps(__m128 __a, __m128 __b)\n");
s.push_str("{\n");
s.push_str(" return __a / __b;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_div_ss(__m128 __a, __m128 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_divss(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_sqrt_ps(__m128 __a)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_sqrtps(__a);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_sqrt_ss(__m128 __a)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_sqrtss(__a);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_rcp_ps(__m128 __a)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_rcpps(__a);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_rcp_ss(__m128 __a)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_rcpss(__a);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_rsqrt_ps(__m128 __a)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_rsqrtps(__a);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_rsqrt_ss(__m128 __a)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_rsqrtss(__a);\n");
s.push_str("}\n\n");
s.push_str("/* Minimum and maximum */\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_min_ps(__m128 __a, __m128 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_minps(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_max_ps(__m128 __a, __m128 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_maxps(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_min_ss(__m128 __a, __m128 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_minss(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_max_ss(__m128 __a, __m128 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_maxss(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("/* Comparison operations */\n");
s.push_str("#define _CMP_EQ_OQ 0x00 /* Equal (ordered, non-signaling) */\n");
s.push_str("#define _CMP_LT_OS 0x01 /* Less-than (ordered, signaling) */\n");
s.push_str("#define _CMP_LE_OS 0x02 /* Less-or-equal (ordered, signaling) */\n");
s.push_str("#define _CMP_UNORD_Q 0x03 /* Unordered (non-signaling) */\n");
s.push_str("#define _CMP_NEQ_UQ 0x04 /* Not-equal (unordered, non-signaling) */\n");
s.push_str("#define _CMP_NLT_US 0x05 /* Not-less-than (unordered, signaling) */\n");
s.push_str("#define _CMP_NLE_US 0x06 /* Not-less-or-equal (unordered, signaling) */\n");
s.push_str("#define _CMP_ORD_Q 0x07 /* Ordered (non-signaling) */\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_cmplt_ps(__m128 __a, __m128 __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128)(__a < __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_cmple_ps(__m128 __a, __m128 __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128)(__a <= __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_cmpgt_ps(__m128 __a, __m128 __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128)(__a > __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_cmpge_ps(__m128 __a, __m128 __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128)(__a >= __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_cmpeq_ps(__m128 __a, __m128 __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128)(__a == __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_cmpneq_ps(__m128 __a, __m128 __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128)(__a != __b);\n");
s.push_str("}\n\n");
s.push_str("/* Bitwise logical operations */\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_and_ps(__m128 __a, __m128 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_andps(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_or_ps(__m128 __a, __m128 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_orps(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_xor_ps(__m128 __a, __m128 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_xorps(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_andnot_ps(__m128 __a, __m128 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_andnps(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("/* Shuffle */\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_shuffle_ps(__m128 __a, __m128 __b, unsigned int __imm8)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_shufps(__a, __b, __imm8);\n");
s.push_str("}\n\n");
s.push_str(
"#define _MM_SHUFFLE(z, y, x, w) (((z) << 6) | ((y) << 4) | ((x) << 2) | (w))\n\n",
);
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_unpackhi_ps(__m128 __a, __m128 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_shufflevector(__a, __b, 2, 6, 3, 7);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_unpacklo_ps(__m128 __a, __m128 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_shufflevector(__a, __b, 0, 4, 1, 5);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_movehl_ps(__m128 __a, __m128 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_shufflevector(__a, __b, 6, 7, 2, 3);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_movelh_ps(__m128 __a, __m128 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_shufflevector(__a, __b, 0, 1, 4, 5);\n");
s.push_str("}\n\n");
s.push_str("/* Conversion */\n");
s.push_str("static __inline__ int __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_cvtss_si32(__m128 __a)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_cvtss2si(__a);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_cvtsi32_ss(__m128 __a, int __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_cvtsi2ss(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("/* Miscellaneous */\n");
s.push_str("static __inline__ int __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_movemask_ps(__m128 __a)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_movmskps(__a);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ void __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_prefetch(char const *__p, int __i)\n");
s.push_str("{\n");
s.push_str(" __builtin_prefetch(__p, (__i & 0x4) ? 1 : 0, __i & 0x3);\n");
s.push_str("}\n\n");
s.push_str("#define _MM_HINT_T0 3\n");
s.push_str("#define _MM_HINT_T1 2\n");
s.push_str("#define _MM_HINT_T2 1\n");
s.push_str("#define _MM_HINT_NTA 0\n");
s.push_str("#define _MM_HINT_ET0 7\n");
s.push_str("#define _MM_HINT_ET1 6\n\n");
s.push_str("static __inline__ void __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_sfence(void)\n");
s.push_str("{\n");
s.push_str(" __builtin_ia32_sfence();\n");
s.push_str("}\n\n");
s.push_str("#endif /* __XMMINTRIN_H */\n");
s
}
fn generate_emmintrin(&self) -> String {
let mut s = String::new();
s.push_str("/*===---- emmintrin.h - SSE2 intrinsics ------------------------------===*/\n");
s.push_str("/* */\n");
s.push_str("/* Intel SSE2 (Streaming SIMD Extensions 2) intrinsics. */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __EMMINTRIN_H\n");
s.push_str("#define __EMMINTRIN_H\n\n");
s.push_str("#if !defined(__SSE2__)\n");
s.push_str("#error \"SSE2 instruction set not enabled\"\n");
s.push_str("#endif\n\n");
s.push_str("#include <xmmintrin.h>\n\n");
s.push_str("/* SSE2 double-precision type */\n");
s.push_str(
"typedef double __m128d __attribute__((__vector_size__(16), __aligned__(16)));\n\n",
);
s.push_str("/* Construction and load/store */\n");
s.push_str("static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_setzero_pd(void)\n");
s.push_str("{\n");
s.push_str(" return __extension__ (__m128d){ 0.0, 0.0 };\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_set_pd(double __e1, double __e0)\n");
s.push_str("{\n");
s.push_str(" return __extension__ (__m128d){ __e0, __e1 };\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_set1_pd(double __d)\n");
s.push_str("{\n");
s.push_str(" return __extension__ (__m128d){ __d, __d };\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_load_pd(double const *__dp)\n");
s.push_str("{\n");
s.push_str(" return *(__m128d const *)__dp;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_loadu_pd(double const *__dp)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_loadupd(__dp);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ void __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_store_pd(double *__dp, __m128d __a)\n");
s.push_str("{\n");
s.push_str(" *(__m128d *)__dp = __a;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ void __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_storeu_pd(double *__dp, __m128d __a)\n");
s.push_str("{\n");
s.push_str(" __builtin_ia32_storeupd(__dp, __a);\n");
s.push_str("}\n\n");
s.push_str("/* Double-precision arithmetic */\n");
s.push_str("static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_add_pd(__m128d __a, __m128d __b)\n");
s.push_str("{\n");
s.push_str(" return __a + __b;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_sub_pd(__m128d __a, __m128d __b)\n");
s.push_str("{\n");
s.push_str(" return __a - __b;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_mul_pd(__m128d __a, __m128d __b)\n");
s.push_str("{\n");
s.push_str(" return __a * __b;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_div_pd(__m128d __a, __m128d __b)\n");
s.push_str("{\n");
s.push_str(" return __a / __b;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_sqrt_pd(__m128d __a)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_sqrtpd(__a);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_min_pd(__m128d __a, __m128d __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_minpd(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_max_pd(__m128d __a, __m128d __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_maxpd(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("/* 128-bit integer arithmetic */\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_add_epi8(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)((__v16qs)__a + (__v16qs)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_add_epi16(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)((__v8hi)__a + (__v8hi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_add_epi32(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)((__v4si)__a + (__v4si)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_add_epi64(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)((__v2di)__a + (__v2di)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_sub_epi8(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)((__v16qs)__a - (__v16qs)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_sub_epi16(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)((__v8hi)__a - (__v8hi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_sub_epi32(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)((__v4si)__a - (__v4si)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_sub_epi64(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)((__v2di)__a - (__v2di)__b);\n");
s.push_str("}\n\n");
s.push_str("/* Multiplication */\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_madd_epi16(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_pmaddwd128((__v8hi)__a, (__v8hi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_mul_epu32(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_pmuludq((__v4si)__a, (__v4si)__b);\n");
s.push_str("}\n\n");
s.push_str("/* Bitwise operations */\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_and_si128(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return __a & __b;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_or_si128(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return __a | __b;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_xor_si128(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return __a ^ __b;\n");
s.push_str("}\n\n");
s.push_str("/* Shift operations */\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_slli_epi16(__m128i __a, int __count)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_psllwi128((__v8hi)__a, __count);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_slli_epi32(__m128i __a, int __count)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_pslldi128((__v4si)__a, __count);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_slli_epi64(__m128i __a, int __count)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_psllqi128((__v2di)__a, __count);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_srli_epi16(__m128i __a, int __count)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_psrlwi128((__v8hi)__a, __count);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_srli_epi32(__m128i __a, int __count)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_psrldi128((__v4si)__a, __count);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_srli_epi64(__m128i __a, int __count)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_psrlqi128((__v2di)__a, __count);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_srai_epi16(__m128i __a, int __count)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_psrawi128((__v8hi)__a, __count);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_srai_epi32(__m128i __a, int __count)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_psradi128((__v4si)__a, __count);\n");
s.push_str("}\n\n");
s.push_str("/* Comparison */\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_cmpeq_epi8(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)((__v16qs)__a == (__v16qs)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_cmpeq_epi16(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)((__v8hi)__a == (__v8hi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_cmpeq_epi32(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)((__v4si)__a == (__v4si)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_cmpgt_epi8(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)((__v16qs)__a > (__v16qs)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_cmpgt_epi16(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)((__v8hi)__a > (__v8hi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_cmpgt_epi32(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)((__v4si)__a > (__v4si)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_cmplt_epi8(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)((__v16qs)__a < (__v16qs)__b);\n");
s.push_str("}\n\n");
s.push_str("/* Pack, unpack, and shuffle */\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_packs_epi16(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_packsswb128((__v8hi)__a, (__v8hi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_packs_epi32(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_packssdw128((__v4si)__a, (__v4si)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_unpackhi_epi8(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_shufflevector((__v16qs)__a, (__v16qs)__b,\n");
s.push_str(" 8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_unpacklo_epi8(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_shufflevector((__v16qs)__a, (__v16qs)__b,\n");
s.push_str(" 0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_unpackhi_epi16(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_shufflevector((__v8hi)__a, (__v8hi)__b,\n");
s.push_str(" 4, 12, 5, 13, 6, 14, 7, 15);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_unpacklo_epi16(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_shufflevector((__v8hi)__a, (__v8hi)__b,\n");
s.push_str(" 0, 8, 1, 9, 2, 10, 3, 11);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_unpackhi_epi32(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_shufflevector((__v4si)__a, (__v4si)__b,\n");
s.push_str(" 2, 6, 3, 7);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_unpacklo_epi32(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_shufflevector((__v4si)__a, (__v4si)__b,\n");
s.push_str(" 0, 4, 1, 5);\n");
s.push_str("}\n\n");
s.push_str("/* Conversion between float and double */\n");
s.push_str("static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_cvtps_pd(__m128 __a)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_cvtps2pd(__a);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_cvtpd_ps(__m128d __a)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_cvtpd2ps(__a);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ int __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_cvtsd_si32(__m128d __a)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_cvtsd2si(__a);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_cvtsi32_sd(__m128d __a, int __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_cvtsi2sd(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("/* Miscellaneous */\n");
s.push_str("static __inline__ int __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_movemask_pd(__m128d __a)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_movmskpd(__a);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_setzero_si128(void)\n");
s.push_str("{\n");
s.push_str(" return __extension__ (__m128i)(__v2di){ 0LL, 0LL };\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_move_epi64(__m128i __a)\n");
s.push_str("{\n");
s.push_str(" return __builtin_shufflevector(__a, (__m128i){0}, 0, 1);\n");
s.push_str("}\n\n");
s.push_str("#endif /* __EMMINTRIN_H */\n");
s
}
fn generate_pmmintrin(&self) -> String {
let mut s = String::new();
s.push_str("/*===---- pmmintrin.h - SSE3 intrinsics ------------------------------===*/\n");
s.push_str("/* */\n");
s.push_str("/* Intel SSE3 (Prescott New Instructions) intrinsics. */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __PMMINTRIN_H\n");
s.push_str("#define __PMMINTRIN_H\n\n");
s.push_str("#if !defined(__SSE3__)\n");
s.push_str("#error \"SSE3 instruction set not enabled\"\n");
s.push_str("#endif\n\n");
s.push_str("#include <emmintrin.h>\n\n");
s.push_str("/* Horizontal add/subtract */\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_addsub_ps(__m128 __a, __m128 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_addsubps(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_addsub_pd(__m128d __a, __m128d __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_addsubpd(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_hadd_ps(__m128 __a, __m128 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_haddps(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_hadd_pd(__m128d __a, __m128d __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_haddpd(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_hsub_ps(__m128 __a, __m128 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_hsubps(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_hsub_pd(__m128d __a, __m128d __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_hsubpd(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("/* Move operations */\n");
s.push_str("static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_movedup_pd(__m128d __a)\n");
s.push_str("{\n");
s.push_str(" return __builtin_shufflevector(__a, __a, 0, 0);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_movehdup_ps(__m128 __a)\n");
s.push_str("{\n");
s.push_str(" return __builtin_shufflevector(__a, __a, 1, 1, 3, 3);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_moveldup_ps(__m128 __a)\n");
s.push_str("{\n");
s.push_str(" return __builtin_shufflevector(__a, __a, 0, 0, 2, 2);\n");
s.push_str("}\n\n");
s.push_str("/* Load unaligned integer 128 */\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_lddqu_si128(__m128i const *__p)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_lddqu((char const *)__p);\n");
s.push_str("}\n\n");
s.push_str("#endif /* __PMMINTRIN_H */\n");
s
}
fn generate_tmmintrin(&self) -> String {
let mut s = String::new();
s.push_str("/*===---- tmmintrin.h - SSSE3 intrinsics -----------------------------===*/\n");
s.push_str("/* */\n");
s.push_str("/* Intel SSSE3 (Supplemental SSE3) intrinsics. */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __TMMINTRIN_H\n");
s.push_str("#define __TMMINTRIN_H\n\n");
s.push_str("#if !defined(__SSSE3__)\n");
s.push_str("#error \"SSSE3 instruction set not enabled\"\n");
s.push_str("#endif\n\n");
s.push_str("#include <pmmintrin.h>\n\n");
s.push_str("/* Absolute value */\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_abs_epi8(__m128i __a)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_pabsb128((__v16qs)__a);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_abs_epi16(__m128i __a)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_pabsw128((__v8hi)__a);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_abs_epi32(__m128i __a)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_pabsd128((__v4si)__a);\n");
s.push_str("}\n\n");
s.push_str("/* Horizontal add/subtract (integer) */\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_hadd_epi16(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_phaddw128((__v8hi)__a, (__v8hi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_hadd_epi32(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_phaddd128((__v4si)__a, (__v4si)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_hsub_epi16(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_phsubw128((__v8hi)__a, (__v8hi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_hsub_epi32(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_phsubd128((__v4si)__a, (__v4si)__b);\n");
s.push_str("}\n\n");
s.push_str("/* Sign operations */\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_sign_epi8(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_psignb128((__v16qs)__a, (__v16qs)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_sign_epi16(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_psignw128((__v8hi)__a, (__v8hi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_sign_epi32(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_psignd128((__v4si)__a, (__v4si)__b);\n");
s.push_str("}\n\n");
s.push_str("/* Shuffle bytes */\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_shuffle_epi8(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_pshufb128((__v16qs)__a, (__v16qs)__b);\n");
s.push_str("}\n\n");
s.push_str("/* Multiply and add */\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_maddubs_epi16(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_pmaddubsw128((__v16qs)__a, (__v16qs)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_mulhrs_epi16(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_pmulhrsw128((__v8hi)__a, (__v8hi)__b);\n");
s.push_str("}\n\n");
s.push_str("/* Byte alignment */\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_alignr_epi8(__m128i __a, __m128i __b, int __n)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_palignr128((__v2di)__a, (__v2di)__b, __n);\n");
s.push_str("}\n\n");
s.push_str("#endif /* __TMMINTRIN_H */\n");
s
}
fn generate_smmintrin(&self) -> String {
let mut s = String::new();
s.push_str("/*===---- smmintrin.h - SSE4.1 intrinsics ----------------------------===*/\n");
s.push_str("/* */\n");
s.push_str("/* Intel SSE4.1 intrinsics. */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __SMMINTRIN_H\n");
s.push_str("#define __SMMINTRIN_H\n\n");
s.push_str("#if !defined(__SSE4_1__)\n");
s.push_str("#error \"SSE4.1 instruction set not enabled\"\n");
s.push_str("#endif\n\n");
s.push_str("#include <tmmintrin.h>\n\n");
s.push_str("/* Blend */\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_blend_ps(__m128 __a, __m128 __b, const int __imm8)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_blendps(__a, __b, __imm8);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_blend_pd(__m128d __a, __m128d __b, const int __imm8)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_blendpd(__a, __b, __imm8);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_blend_epi16(__m128i __a, __m128i __b, const int __imm8)\n");
s.push_str("{\n");
s.push_str(
" return (__m128i)__builtin_ia32_pblendw128((__v8hi)__a, (__v8hi)__b, __imm8);\n",
);
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_blendv_ps(__m128 __a, __m128 __b, __m128 __mask)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_blendvps(__a, __b, __mask);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_blendv_pd(__m128d __a, __m128d __b, __m128d __mask)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_blendvpd(__a, __b, __mask);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_blendv_epi8(__m128i __a, __m128i __b, __m128i __mask)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_pblendvb128((__v16qs)__a, (__v16qs)__b, (__v16qs)__mask);\n");
s.push_str("}\n\n");
s.push_str("/* Dot product */\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_dp_ps(__m128 __a, __m128 __b, const int __imm8)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_dpps(__a, __b, __imm8);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_dp_pd(__m128d __a, __m128d __b, const int __imm8)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_dppd(__a, __b, __imm8);\n");
s.push_str("}\n\n");
s.push_str("/* Rounding */\n");
s.push_str("#define _MM_FROUND_TO_NEAREST_INT 0x00\n");
s.push_str("#define _MM_FROUND_TO_NEG_INF 0x01\n");
s.push_str("#define _MM_FROUND_TO_POS_INF 0x02\n");
s.push_str("#define _MM_FROUND_TO_ZERO 0x03\n");
s.push_str("#define _MM_FROUND_CUR_DIRECTION 0x04\n");
s.push_str("#define _MM_FROUND_RAISE_EXC 0x00\n");
s.push_str("#define _MM_FROUND_NO_EXC 0x08\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_round_ps(__m128 __a, int __rounding)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_roundps(__a, __rounding);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_round_pd(__m128d __a, int __rounding)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_roundpd(__a, __rounding);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_round_ss(__m128 __a, __m128 __b, int __rounding)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_roundss(__a, __b, __rounding);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_round_sd(__m128d __a, __m128d __b, int __rounding)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_roundsd(__a, __b, __rounding);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_floor_ps(__m128 __a)\n");
s.push_str("{\n");
s.push_str(" return _mm_round_ps(__a, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_ceil_ps(__m128 __a)\n");
s.push_str("{\n");
s.push_str(" return _mm_round_ps(__a, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC);\n");
s.push_str("}\n\n");
s.push_str("/* Integer multiplication */\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_mullo_epi32(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_pmulld128((__v4si)__a, (__v4si)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_mul_epi32(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_pmuldq128((__v4si)__a, (__v4si)__b);\n");
s.push_str("}\n\n");
s.push_str("/* Integer min/max */\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_min_epi8(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_pminsb128((__v16qs)__a, (__v16qs)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_max_epi8(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_pmaxsb128((__v16qs)__a, (__v16qs)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_min_epu16(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_pminuw128((__v8hi)__a, (__v8hi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_max_epu16(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_pmaxuw128((__v8hi)__a, (__v8hi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_min_epi32(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_pminsd128((__v4si)__a, (__v4si)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_max_epi32(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_pmaxsd128((__v4si)__a, (__v4si)__b);\n");
s.push_str("}\n\n");
s.push_str("/* Extract and insert */\n");
s.push_str("static __inline__ int __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_extract_ps(__m128 __a, const int __imm8)\n");
s.push_str("{\n");
s.push_str(" int __r;\n");
s.push_str(" __builtin_ia32_vec_ext_v4sf((__v4sf)__a, __imm8, &__r);\n");
s.push_str(" return __r;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_insert_ps(__m128 __a, __m128 __b, const int __imm8)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_insertps128(__a, __b, __imm8);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_packus_epi32(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_packusdw128((__v4si)__a, (__v4si)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_cmpeq_epi64(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)((__v2di)__a == (__v2di)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ int __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_testz_si128(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_ptestz128((__v2di)__a, (__v2di)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ int __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_testc_si128(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_ptestc128((__v2di)__a, (__v2di)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ int __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_testnzc_si128(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_ptestnzc128((__v2di)__a, (__v2di)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_stream_load_si128(__m128i *__p)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_movntdqa((__v2di *)__p);\n");
s.push_str("}\n\n");
s.push_str("#endif /* __SMMINTRIN_H */\n");
s
}
fn generate_nmmintrin(&self) -> String {
let mut s = String::new();
s.push_str("/*===---- nmmintrin.h - SSE4.2 intrinsics ----------------------------===*/\n");
s.push_str("/* */\n");
s.push_str("/* Intel SSE4.2 intrinsics. */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __NMMINTRIN_H\n");
s.push_str("#define __NMMINTRIN_H\n\n");
s.push_str("#if !defined(__SSE4_2__)\n");
s.push_str("#error \"SSE4.2 instruction set not enabled\"\n");
s.push_str("#endif\n\n");
s.push_str("#include <smmintrin.h>\n\n");
s.push_str("/* CRC-32 */\n");
s.push_str(
"static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))\n",
);
s.push_str("_mm_crc32_u8(unsigned int __crc, unsigned char __v)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_crc32qi(__crc, __v);\n");
s.push_str("}\n\n");
s.push_str(
"static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))\n",
);
s.push_str("_mm_crc32_u16(unsigned int __crc, unsigned short __v)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_crc32hi(__crc, __v);\n");
s.push_str("}\n\n");
s.push_str(
"static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))\n",
);
s.push_str("_mm_crc32_u32(unsigned int __crc, unsigned int __v)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_crc32si(__crc, __v);\n");
s.push_str("}\n\n");
if self.config.pointer_width == 64 {
s.push_str("static __inline__ unsigned long long __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_crc32_u64(unsigned long long __crc, unsigned long long __v)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_crc32di(__crc, __v);\n");
s.push_str("}\n\n");
}
s.push_str("/* Packed compare strings */\n");
s.push_str("static __inline__ int __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_cmpistri(__m128i __a, __m128i __b, const int __imm8)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_pcmpistri128((__v16qs)__a, (__v16qs)__b, __imm8);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ int __attribute__((__always_inline__, __nodebug__))\n");
s.push_str(
"_mm_cmpestri(__m128i __a, int __la, __m128i __b, int __lb, const int __imm8)\n",
);
s.push_str("{\n");
s.push_str(" return __builtin_ia32_pcmpestri128((__v16qs)__a, __la, (__v16qs)__b, __lb, __imm8);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_cmpistrm(__m128i __a, __m128i __b, const int __imm8)\n");
s.push_str("{\n");
s.push_str(
" return (__m128i)__builtin_ia32_pcmpistrm128((__v16qs)__a, (__v16qs)__b, __imm8);\n",
);
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str(
"_mm_cmpestrm(__m128i __a, int __la, __m128i __b, int __lb, const int __imm8)\n",
);
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_pcmpestrm128((__v16qs)__a, __la, (__v16qs)__b, __lb, __imm8);\n");
s.push_str("}\n\n");
s.push_str("#endif /* __NMMINTRIN_H */\n");
s
}
fn generate_wmmintrin(&self) -> String {
let mut s = String::new();
s.push_str("/*===---- wmmintrin.h - AES intrinsics -------------------------------===*/\n");
s.push_str("/* */\n");
s.push_str("/* Intel AES (Advanced Encryption Standard) New Instructions. */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __WMMINTRIN_H\n");
s.push_str("#define __WMMINTRIN_H\n\n");
s.push_str("#if !defined(__AES__)\n");
s.push_str("#error \"AES instruction set not enabled\"\n");
s.push_str("#endif\n\n");
s.push_str("#include <emmintrin.h>\n\n");
s.push_str("/* AES encryption round */\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_aesenc_si128(__m128i __a, __m128i __RoundKey)\n");
s.push_str("{\n");
s.push_str(
" return (__m128i)__builtin_ia32_aesenc128((__v2di)__a, (__v2di)__RoundKey);\n",
);
s.push_str("}\n\n");
s.push_str("/* AES last encryption round */\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_aesenclast_si128(__m128i __a, __m128i __RoundKey)\n");
s.push_str("{\n");
s.push_str(
" return (__m128i)__builtin_ia32_aesenclast128((__v2di)__a, (__v2di)__RoundKey);\n",
);
s.push_str("}\n\n");
s.push_str("/* AES decryption round */\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_aesdec_si128(__m128i __a, __m128i __RoundKey)\n");
s.push_str("{\n");
s.push_str(
" return (__m128i)__builtin_ia32_aesdec128((__v2di)__a, (__v2di)__RoundKey);\n",
);
s.push_str("}\n\n");
s.push_str("/* AES last decryption round */\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_aesdeclast_si128(__m128i __a, __m128i __RoundKey)\n");
s.push_str("{\n");
s.push_str(
" return (__m128i)__builtin_ia32_aesdeclast128((__v2di)__a, (__v2di)__RoundKey);\n",
);
s.push_str("}\n\n");
s.push_str("/* AES inverse MixColumns */\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_aesimc_si128(__m128i __a)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_aesimc128((__v2di)__a);\n");
s.push_str("}\n\n");
s.push_str("/* AES key generation assist */\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_aeskeygenassist_si128(__m128i __CipherKey, const int __Rcon)\n");
s.push_str("{\n");
s.push_str(
" return (__m128i)__builtin_ia32_aeskeygenassist128((__v2di)__CipherKey, __Rcon);\n",
);
s.push_str("}\n\n");
s.push_str("#endif /* __WMMINTRIN_H */\n");
s
}
fn generate_avxintrin(&self) -> String {
let mut s = String::new();
s.push_str("/*===---- avxintrin.h - AVX intrinsics -------------------------------===*/\n");
s.push_str("/* */\n");
s.push_str("/* Intel AVX (Advanced Vector Extensions) intrinsics — 256-bit. */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __AVXINTRIN_H\n");
s.push_str("#define __AVXINTRIN_H\n\n");
s.push_str("#if !defined(__AVX__)\n");
s.push_str("#error \"AVX instruction set not enabled\"\n");
s.push_str("#endif\n\n");
s.push_str("/* AVX 256-bit types */\n");
s.push_str("typedef float __m256 __attribute__((__vector_size__(32), __aligned__(32)));\n");
s.push_str(
"typedef double __m256d __attribute__((__vector_size__(32), __aligned__(32)));\n",
);
s.push_str(
"typedef int __m256i __attribute__((__vector_size__(32), __aligned__(32)));\n\n",
);
s.push_str("/* Construction */\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_setzero_ps(void)\n");
s.push_str("{\n");
s.push_str(
" return __extension__ (__m256){ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };\n",
);
s.push_str("}\n\n");
s.push_str("static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_setzero_pd(void)\n");
s.push_str("{\n");
s.push_str(" return __extension__ (__m256d){ 0.0, 0.0, 0.0, 0.0 };\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_setzero_si256(void)\n");
s.push_str("{\n");
s.push_str(" return __extension__ (__m256i){ 0LL, 0LL, 0LL, 0LL };\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_set1_ps(float __f)\n");
s.push_str("{\n");
s.push_str(" return __extension__ (__m256){ __f, __f, __f, __f, __f, __f, __f, __f };\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_set1_pd(double __d)\n");
s.push_str("{\n");
s.push_str(" return __extension__ (__m256d){ __d, __d, __d, __d };\n");
s.push_str("}\n\n");
s.push_str("/* Load and store */\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_load_ps(float const *__p)\n");
s.push_str("{\n");
s.push_str(" return *(__m256 const *)__p;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_load_pd(double const *__p)\n");
s.push_str("{\n");
s.push_str(" return *(__m256d const *)__p;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_loadu_ps(float const *__p)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_loadups256(__p);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_loadu_pd(double const *__p)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_loadupd256(__p);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ void __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_store_ps(float *__p, __m256 __a)\n");
s.push_str("{\n");
s.push_str(" *(__m256 *)__p = __a;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ void __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_store_pd(double *__p, __m256d __a)\n");
s.push_str("{\n");
s.push_str(" *(__m256d *)__p = __a;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ void __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_storeu_ps(float *__p, __m256 __a)\n");
s.push_str("{\n");
s.push_str(" __builtin_ia32_storeups256(__p, __a);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ void __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_storeu_pd(double *__p, __m256d __a)\n");
s.push_str("{\n");
s.push_str(" __builtin_ia32_storeupd256(__p, __a);\n");
s.push_str("}\n\n");
s.push_str("/* Arithmetic */\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_add_ps(__m256 __a, __m256 __b)\n");
s.push_str("{\n");
s.push_str(" return __a + __b;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_add_pd(__m256d __a, __m256d __b)\n");
s.push_str("{\n");
s.push_str(" return __a + __b;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_sub_ps(__m256 __a, __m256 __b)\n");
s.push_str("{\n");
s.push_str(" return __a - __b;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_sub_pd(__m256d __a, __m256d __b)\n");
s.push_str("{\n");
s.push_str(" return __a - __b;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_mul_ps(__m256 __a, __m256 __b)\n");
s.push_str("{\n");
s.push_str(" return __a * __b;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_mul_pd(__m256d __a, __m256d __b)\n");
s.push_str("{\n");
s.push_str(" return __a * __b;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_div_ps(__m256 __a, __m256 __b)\n");
s.push_str("{\n");
s.push_str(" return __a / __b;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_div_pd(__m256d __a, __m256d __b)\n");
s.push_str("{\n");
s.push_str(" return __a / __b;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_sqrt_ps(__m256 __a)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_sqrtps256(__a);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_sqrt_pd(__m256d __a)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_sqrtpd256(__a);\n");
s.push_str("}\n\n");
s.push_str("/* Min/Max */\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_min_ps(__m256 __a, __m256 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_minps256(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_max_ps(__m256 __a, __m256 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_maxps256(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("/* Bitwise operations */\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_and_ps(__m256 __a, __m256 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_andps256(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_or_ps(__m256 __a, __m256 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_orps256(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_xor_ps(__m256 __a, __m256 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_xorps256(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_andnot_ps(__m256 __a, __m256 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_andnps256(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("/* Comparison */\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_cmp_ps(__m256 __a, __m256 __b, const int __imm8)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_cmpps256(__a, __b, __imm8);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_cmp_pd(__m256d __a, __m256d __b, const int __imm8)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_cmppd256(__a, __b, __imm8);\n");
s.push_str("}\n\n");
s.push_str("/* Shuffle */\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_shuffle_ps(__m256 __a, __m256 __b, const int __imm8)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_shufps256(__a, __b, __imm8);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_shuffle_pd(__m256d __a, __m256d __b, const int __imm8)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_shufpd256(__a, __b, __imm8);\n");
s.push_str("}\n\n");
s.push_str("/* Unpack */\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_unpackhi_ps(__m256 __a, __m256 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_shufflevector(__a, __b, 2, 10, 3, 11, 6, 14, 7, 15);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_unpacklo_ps(__m256 __a, __m256 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_shufflevector(__a, __b, 0, 8, 1, 9, 4, 12, 5, 13);\n");
s.push_str("}\n\n");
s.push_str("/* Broadcast */\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_broadcast_ss(float const *__p)\n");
s.push_str("{\n");
s.push_str(" float __f = *__p;\n");
s.push_str(" return __extension__ (__m256){ __f, __f, __f, __f, __f, __f, __f, __f };\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_broadcast_ss(float const *__p)\n");
s.push_str("{\n");
s.push_str(" float __f = *__p;\n");
s.push_str(" return __extension__ (__m128){ __f, __f, __f, __f };\n");
s.push_str("}\n\n");
s.push_str("/* Convert */\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_cvtpd_ps(__m256d __a)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_cvtpd2ps256(__a);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_cvtps_pd(__m128 __a)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_cvtps2pd256(__a);\n");
s.push_str("}\n\n");
s.push_str("/* Move mask */\n");
s.push_str("static __inline__ int __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_movemask_ps(__m256 __a)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_movmskps256(__a);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ int __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_movemask_pd(__m256d __a)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_movmskpd256(__a);\n");
s.push_str("}\n\n");
s.push_str("/* Permute */\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_permute_ps(__m256 __a, const int __imm8)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_permps256(__a, __imm8);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_permute_pd(__m256d __a, const int __imm8)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_permpd256(__a, __imm8);\n");
s.push_str("}\n\n");
s.push_str("/* VZEROUPPER and VZEROALL */\n");
s.push_str("static __inline__ void __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_zeroupper(void)\n");
s.push_str("{\n");
s.push_str(" __builtin_ia32_vzeroupper();\n");
s.push_str("}\n\n");
s.push_str("#endif /* __AVXINTRIN_H */\n");
s
}
fn generate_immintrin(&self) -> String {
let mut s = String::new();
s.push_str(
"/*===---- immintrin.h - Intel intrinsics umbrella header --------------===*/\n",
);
s.push_str("/* */\n");
s.push_str("/* This header includes all Intel intrinsic headers. */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __IMMINTRIN_H\n");
s.push_str("#define __IMMINTRIN_H\n\n");
s.push_str("#if !defined(__MMX__) && !defined(__SSE__) && !defined(__AVX__)\n");
s.push_str("#error \"No SIMD instruction set enabled\"\n");
s.push_str("#endif\n\n");
s.push_str("/* 256-bit types (defined in avxintrin.h) */\n");
s.push_str("#ifdef __AVX__\n");
s.push_str("typedef float __m256 __attribute__((__vector_size__(32), __aligned__(32)));\n");
s.push_str(
"typedef double __m256d __attribute__((__vector_size__(32), __aligned__(32)));\n",
);
s.push_str("typedef int __m256i __attribute__((__vector_size__(32), __aligned__(32)));\n");
s.push_str("#endif\n\n");
s.push_str("/* Include feature-specific intrinsic headers */\n");
s.push_str("#include <mmintrin.h>\n");
s.push_str("#include <xmmintrin.h>\n");
s.push_str("#include <emmintrin.h>\n");
s.push_str("#include <pmmintrin.h>\n");
s.push_str("#include <tmmintrin.h>\n");
s.push_str("#include <smmintrin.h>\n");
s.push_str("#include <nmmintrin.h>\n");
s.push_str("#include <wmmintrin.h>\n");
s.push_str("#include <bmiintrin.h>\n");
s.push_str("#include <bmi2intrin.h>\n");
s.push_str("#include <lzcntintrin.h>\n");
if self.config.has_fma {
s.push_str("#include <fmaintrin.h>\n");
}
if self.config.has_avx {
s.push_str("#include <avxintrin.h>\n");
}
if self.config.has_avx2 {
s.push_str("#include <avx2intrin.h>\n");
}
if self.config.has_avx512f {
s.push_str("#include <avx512fintrin.h>\n");
}
if self.config.has_avx512bw {
s.push_str("#include <avx512bwintrin.h>\n");
}
if self.config.has_avx512dq {
s.push_str("#include <avx512dqintrin.h>\n");
}
if self.config.has_avx512vl {
s.push_str("#include <avx512vlintrin.h>\n");
}
s.push_str("\n#endif /* __IMMINTRIN_H */\n");
s
}
fn generate_avx2intrin(&self) -> String {
let mut s = String::new();
s.push_str("/*===---- avx2intrin.h - AVX2 intrinsics -----------------------------===*/\n");
s.push_str("/* */\n");
s.push_str("/* Intel AVX2 intrinsics — 256-bit integer operations. */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __AVX2INTRIN_H\n");
s.push_str("#define __AVX2INTRIN_H\n\n");
s.push_str("#if !defined(__AVX2__)\n");
s.push_str("#error \"AVX2 instruction set not enabled\"\n");
s.push_str("#endif\n\n");
s.push_str("#include <avxintrin.h>\n\n");
s.push_str("/* Integer arithmetic */\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_add_epi8(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)((__v32qs)__a + (__v32qs)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_add_epi16(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)((__v16hi)__a + (__v16hi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_add_epi32(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)((__v8si)__a + (__v8si)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_add_epi64(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)((__v4di)__a + (__v4di)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_sub_epi8(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)((__v32qs)__a - (__v32qs)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_sub_epi16(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)((__v16hi)__a - (__v16hi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_sub_epi32(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)((__v8si)__a - (__v8si)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_sub_epi64(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)((__v4di)__a - (__v4di)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_mul_epi32(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_pmuldq256((__v8si)__a, (__v8si)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_mullo_epi32(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_pmulld256((__v8si)__a, (__v8si)__b);\n");
s.push_str("}\n\n");
s.push_str("/* Shifts */\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_slli_epi16(__m256i __a, int __count)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_psllwi256((__v16hi)__a, __count);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_slli_epi32(__m256i __a, int __count)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_pslldi256((__v8si)__a, __count);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_slli_epi64(__m256i __a, int __count)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_psllqi256((__v4di)__a, __count);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_srli_epi16(__m256i __a, int __count)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_psrlwi256((__v16hi)__a, __count);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_srli_epi32(__m256i __a, int __count)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_psrldi256((__v8si)__a, __count);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_srli_epi64(__m256i __a, int __count)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_psrlqi256((__v4di)__a, __count);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_srai_epi16(__m256i __a, int __count)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_psrawi256((__v16hi)__a, __count);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_srai_epi32(__m256i __a, int __count)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_psradi256((__v8si)__a, __count);\n");
s.push_str("}\n\n");
s.push_str("/* Bitwise operations */\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_and_si256(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return __a & __b;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_or_si256(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return __a | __b;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_xor_si256(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return __a ^ __b;\n");
s.push_str("}\n\n");
s.push_str("/* Comparison */\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_cmpeq_epi8(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)((__v32qs)__a == (__v32qs)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_cmpeq_epi16(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)((__v16hi)__a == (__v16hi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_cmpeq_epi32(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)((__v8si)__a == (__v8si)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_cmpeq_epi64(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)((__v4di)__a == (__v4di)__b);\n");
s.push_str("}\n\n");
s.push_str("/* Gather */\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str(
"_mm256_i32gather_ps(float const *__base, __m256i __index, const int __scale)\n",
);
s.push_str("{\n");
s.push_str(" return __builtin_ia32_gathersiv8sf(__base, __index, __scale);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str(
"_mm256_i64gather_pd(double const *__base, __m256i __index, const int __scale)\n",
);
s.push_str("{\n");
s.push_str(" return __builtin_ia32_gatherdiv4df(__base, __index, __scale);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_alignr_epi8(__m256i __a, __m256i __b, const int __n)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_palignr256((__v4di)__a, (__v4di)__b, __n);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_permutevar8x32_epi32(__m256i __a, __m256i __idx)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_permvarsi256((__v8si)__a, (__v8si)__idx);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_blend_epi32(__m256i __a, __m256i __b, const int __imm8)\n");
s.push_str("{\n");
s.push_str(
" return (__m256i)__builtin_ia32_pblendd256((__v8si)__a, (__v8si)__b, __imm8);\n",
);
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_abs_epi8(__m256i __a)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_pabsb256((__v32qs)__a);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_abs_epi16(__m256i __a)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_pabsw256((__v16hi)__a);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_abs_epi32(__m256i __a)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_pabsd256((__v8si)__a);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_min_epi8(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_pminsb256((__v32qs)__a, (__v32qs)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_max_epi8(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_pmaxsb256((__v32qs)__a, (__v32qs)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_min_epi16(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_pminsw256((__v16hi)__a, (__v16hi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_max_epi16(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_pmaxsw256((__v16hi)__a, (__v16hi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_min_epi32(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_pminsd256((__v8si)__a, (__v8si)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_max_epi32(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_pmaxsd256((__v8si)__a, (__v8si)__b);\n");
s.push_str("}\n\n");
s.push_str("#endif /* __AVX2INTRIN_H */\n");
s
}
fn generate_avx512fintrin(&self) -> String {
let mut s = String::new();
s.push_str(
"/*===---- avx512fintrin.h - AVX-512 Foundation intrinsics -------------===*/\n",
);
s.push_str("/* */\n");
s.push_str("/* Intel AVX-512 Foundation (AVX-512F) intrinsics. */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __AVX512FINTRIN_H\n");
s.push_str("#define __AVX512FINTRIN_H\n\n");
s.push_str("#if !defined(__AVX512F__)\n");
s.push_str("#error \"AVX-512F instruction set not enabled\"\n");
s.push_str("#endif\n\n");
s.push_str("#include <avx2intrin.h>\n\n");
s.push_str("/* AVX-512 512-bit types */\n");
s.push_str("typedef float __m512 __attribute__((__vector_size__(64), __aligned__(64)));\n");
s.push_str(
"typedef double __m512d __attribute__((__vector_size__(64), __aligned__(64)));\n",
);
s.push_str(
"typedef int __m512i __attribute__((__vector_size__(64), __aligned__(64)));\n\n",
);
s.push_str("/* Mask types for AVX-512 */\n");
s.push_str("typedef unsigned short __mmask8;\n");
s.push_str("typedef unsigned short __mmask16;\n");
s.push_str("typedef unsigned int __mmask32;\n");
s.push_str("typedef unsigned long long __mmask64;\n\n");
s.push_str("/* Basic arithmetic */\n");
s.push_str("static __inline__ __m512 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm512_add_ps(__m512 __a, __m512 __b)\n");
s.push_str("{\n");
s.push_str(" return __a + __b;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m512d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm512_add_pd(__m512d __a, __m512d __b)\n");
s.push_str("{\n");
s.push_str(" return __a + __b;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m512 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm512_sub_ps(__m512 __a, __m512 __b)\n");
s.push_str("{\n");
s.push_str(" return __a - __b;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m512d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm512_sub_pd(__m512d __a, __m512d __b)\n");
s.push_str("{\n");
s.push_str(" return __a - __b;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m512 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm512_mul_ps(__m512 __a, __m512 __b)\n");
s.push_str("{\n");
s.push_str(" return __a * __b;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m512d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm512_mul_pd(__m512d __a, __m512d __b)\n");
s.push_str("{\n");
s.push_str(" return __a * __b;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m512 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm512_div_ps(__m512 __a, __m512 __b)\n");
s.push_str("{\n");
s.push_str(" return __a / __b;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m512d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm512_div_pd(__m512d __a, __m512d __b)\n");
s.push_str("{\n");
s.push_str(" return __a / __b;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m512 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm512_load_ps(void const *__p)\n");
s.push_str("{\n");
s.push_str(" return *(__m512 const *)__p;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ void __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm512_store_ps(void *__p, __m512 __a)\n");
s.push_str("{\n");
s.push_str(" *(__m512 *)__p = __a;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __mmask16 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm512_cmp_ps_mask(__m512 __a, __m512 __b, const int __imm8)\n");
s.push_str("{\n");
s.push_str(
" return (__mmask16)__builtin_ia32_cmpps512_mask(__a, __b, __imm8, (__mmask16)-1);\n",
);
s.push_str("}\n\n");
s.push_str("static __inline__ __m512 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm512_and_ps(__m512 __a, __m512 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_andps512(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m512 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm512_or_ps(__m512 __a, __m512 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_orps512(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m512 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm512_set1_ps(float __f)\n");
s.push_str("{\n");
s.push_str(" return (__m512)__builtin_ia32_vbroadcastss512((__m128){__f,__f,__f,__f});\n");
s.push_str("}\n\n");
s.push_str("#endif /* __AVX512FINTRIN_H */\n");
s
}
fn generate_avx512bwintrin(&self) -> String {
let mut s = String::new();
s.push_str("/*===---- avx512bwintrin.h - AVX-512BW intrinsics --------------------===*/\n");
s.push_str("/* */\n");
s.push_str("/* Intel AVX-512 Byte and Word (AVX-512BW) intrinsics. */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __AVX512BWINTRIN_H\n");
s.push_str("#define __AVX512BWINTRIN_H\n\n");
s.push_str("#if !defined(__AVX512BW__)\n");
s.push_str("#error \"AVX-512BW instruction set not enabled\"\n");
s.push_str("#endif\n\n");
s.push_str("#include <avx512fintrin.h>\n\n");
s.push_str("/* Byte/Word operations */\n");
s.push_str("static __inline__ __m512i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm512_add_epi8(__m512i __a, __m512i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m512i)((__v64qs)__a + (__v64qs)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m512i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm512_add_epi16(__m512i __a, __m512i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m512i)((__v32hi)__a + (__v32hi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m512i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm512_sub_epi8(__m512i __a, __m512i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m512i)((__v64qs)__a - (__v64qs)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m512i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm512_sub_epi16(__m512i __a, __m512i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m512i)((__v32hi)__a - (__v32hi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __mmask64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm512_cmpeq_epi8_mask(__m512i __a, __m512i __b)\n");
s.push_str("{\n");
s.push_str(" return (__mmask64)__builtin_ia32_pcmpeqb512_mask((__v64qi)__a, (__v64qi)__b, (__mmask64)-1);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __mmask32 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm512_cmpeq_epi16_mask(__m512i __a, __m512i __b)\n");
s.push_str("{\n");
s.push_str(" return (__mmask32)__builtin_ia32_pcmpeqw512_mask((__v32hi)__a, (__v32hi)__b, (__mmask32)-1);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m512i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm512_shuffle_epi8(__m512i __a, __m512i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m512i)__builtin_ia32_pshufb512((__v64qi)__a, (__v64qi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m512i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm512_alignr_epi8(__m512i __a, __m512i __b, const int __n)\n");
s.push_str("{\n");
s.push_str(" return (__m512i)__builtin_ia32_palignr512((__v8di)__a, (__v8di)__b, __n);\n");
s.push_str("}\n\n");
s.push_str("#endif /* __AVX512BWINTRIN_H */\n");
s
}
fn generate_avx512dqintrin(&self) -> String {
let mut s = String::new();
s.push_str("/*===---- avx512dqintrin.h - AVX-512DQ intrinsics --------------------===*/\n");
s.push_str("/* */\n");
s.push_str("/* Intel AVX-512 Doubleword and Quadword (AVX-512DQ) intrinsics. */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __AVX512DQINTRIN_H\n");
s.push_str("#define __AVX512DQINTRIN_H\n\n");
s.push_str("#if !defined(__AVX512DQ__)\n");
s.push_str("#error \"AVX-512DQ instruction set not enabled\"\n");
s.push_str("#endif\n\n");
s.push_str("#include <avx512fintrin.h>\n\n");
s.push_str("/* 32-bit and 64-bit operations */\n");
s.push_str("static __inline__ __m512i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm512_mullo_epi32(__m512i __a, __m512i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m512i)__builtin_ia32_pmulld512((__v16si)__a, (__v16si)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m512i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm512_mul_epi32(__m512i __a, __m512i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m512i)__builtin_ia32_pmuldq512((__v16si)__a, (__v16si)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m512d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm512_cvtpd_epi64(__m512d __a)\n");
s.push_str("{\n");
s.push_str(" return (__m512d)__builtin_ia32_cvtpd2qq512_mask(__a, _MM_FROUND_CUR_DIRECTION, (__mmask8)-1);\n");
s.push_str("}\n\n");
s.push_str("#endif /* __AVX512DQINTRIN_H */\n");
s
}
fn generate_avx512vlintrin(&self) -> String {
let mut s = String::new();
s.push_str("/*===---- avx512vlintrin.h - AVX-512VL intrinsics --------------------===*/\n");
s.push_str("/* */\n");
s.push_str("/* Intel AVX-512 Vector Length (AVX-512VL) intrinsics — extends */\n");
s.push_str("/* AVX-512F/BW/DQ operations to 128-bit and 256-bit vectors. */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __AVX512VLINTRIN_H\n");
s.push_str("#define __AVX512VLINTRIN_H\n\n");
s.push_str("#if !defined(__AVX512VL__)\n");
s.push_str("#error \"AVX-512VL instruction set not enabled\"\n");
s.push_str("#endif\n\n");
s.push_str("#include <avx512fintrin.h>\n");
if self.config.has_avx512bw {
s.push_str("#include <avx512bwintrin.h>\n");
}
if self.config.has_avx512dq {
s.push_str("#include <avx512dqintrin.h>\n");
}
s.push_str("\n/* 128-bit and 256-bit variants of AVX-512F operations */\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_mask_add_ps(__m256 __src, __mmask8 __k, __m256 __a, __m256 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_addps256_mask(__a, __b, __src, __k);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_mask_add_ps(__m128 __src, __mmask8 __k, __m128 __a, __m128 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_addps128_mask(__a, __b, __src, __k);\n");
s.push_str("}\n\n");
s.push_str("#endif /* __AVX512VLINTRIN_H */\n");
s
}
fn generate_fmaintrin(&self) -> String {
let mut s = String::new();
s.push_str("/*===---- fmaintrin.h - FMA intrinsics -------------------------------===*/\n");
s.push_str("/* */\n");
s.push_str("/* Intel FMA (Fused Multiply-Add) intrinsics. */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __FMAINTRIN_H\n");
s.push_str("#define __FMAINTRIN_H\n\n");
s.push_str("#if !defined(__FMA__)\n");
s.push_str("#error \"FMA instruction set not enabled\"\n");
s.push_str("#endif\n\n");
s.push_str("/* 128-bit FMA operations */\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_fmadd_ps(__m128 __a, __m128 __b, __m128 __c)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_vfmaddps(__a, __b, __c);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_fmadd_pd(__m128d __a, __m128d __b, __m128d __c)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_vfmaddpd(__a, __b, __c);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_fmsub_ps(__m128 __a, __m128 __b, __m128 __c)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_vfmsubps(__a, __b, __c);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_fmsub_pd(__m128d __a, __m128d __b, __m128d __c)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_vfmsubpd(__a, __b, __c);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_fnmadd_ps(__m128 __a, __m128 __b, __m128 __c)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_vfnmaddps(__a, __b, __c);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_fnmadd_pd(__m128d __a, __m128d __b, __m128d __c)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_vfnmaddpd(__a, __b, __c);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_fnmsub_ps(__m128 __a, __m128 __b, __m128 __c)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_vfnmsubps(__a, __b, __c);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_fnmsub_pd(__m128d __a, __m128d __b, __m128d __c)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_vfnmsubpd(__a, __b, __c);\n");
s.push_str("}\n\n");
s.push_str("/* Scalar FMA operations */\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_fmadd_ss(__m128 __a, __m128 __b, __m128 __c)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_vfmaddss(__a, __b, __c);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_fmadd_sd(__m128d __a, __m128d __b, __m128d __c)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_vfmaddsd(__a, __b, __c);\n");
s.push_str("}\n\n");
s.push_str("/* 256-bit FMA operations */\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_fmadd_ps(__m256 __a, __m256 __b, __m256 __c)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_vfmaddps256(__a, __b, __c);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_fmadd_pd(__m256d __a, __m256d __b, __m256d __c)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_vfmaddpd256(__a, __b, __c);\n");
s.push_str("}\n\n");
s.push_str("#endif /* __FMAINTRIN_H */\n");
s
}
fn generate_bmiintrin(&self) -> String {
let mut s = String::new();
s.push_str("/*===---- bmiintrin.h - BMI intrinsics -------------------------------===*/\n");
s.push_str("/* */\n");
s.push_str("/* Intel BMI (Bit Manipulation Instructions) intrinsics. */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __BMIINTRIN_H\n");
s.push_str("#define __BMIINTRIN_H\n\n");
s.push_str("#if !defined(__BMI__)\n");
s.push_str("#error \"BMI instruction set not enabled\"\n");
s.push_str("#endif\n\n");
s.push_str("/* ANDN: dest = ~src1 & src2 */\n");
s.push_str(
"static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))\n",
);
s.push_str("__andn_u32(unsigned int __a, unsigned int __b)\n");
s.push_str("{\n");
s.push_str(" return ~__a & __b;\n");
s.push_str("}\n\n");
s.push_str("/* BEXTR: extract contiguous bits */\n");
s.push_str(
"static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))\n",
);
s.push_str("__bextr_u32(unsigned int __a, unsigned int __start, unsigned int __len)\n");
s.push_str("{\n");
s.push_str(" unsigned int __mask = (1U << __len) - 1;\n");
s.push_str(" return (__a >> __start) & __mask;\n");
s.push_str("}\n\n");
s.push_str("/* BLSI: isolate lowest set bit */\n");
s.push_str(
"static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))\n",
);
s.push_str("__blsi_u32(unsigned int __a)\n");
s.push_str("{\n");
s.push_str(" return __a & -__a;\n");
s.push_str("}\n\n");
s.push_str("/* BLSMSK: mask up to lowest set bit */\n");
s.push_str(
"static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))\n",
);
s.push_str("__blsmsk_u32(unsigned int __a)\n");
s.push_str("{\n");
s.push_str(" return __a ^ (__a - 1);\n");
s.push_str("}\n\n");
s.push_str("/* BLSR: reset lowest set bit */\n");
s.push_str(
"static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))\n",
);
s.push_str("__blsr_u32(unsigned int __a)\n");
s.push_str("{\n");
s.push_str(" return __a & (__a - 1);\n");
s.push_str("}\n\n");
if self.config.pointer_width == 64 {
s.push_str("static __inline__ unsigned long long __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("__andn_u64(unsigned long long __a, unsigned long long __b)\n");
s.push_str("{\n");
s.push_str(" return ~__a & __b;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ unsigned long long __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("__blsi_u64(unsigned long long __a)\n");
s.push_str("{\n");
s.push_str(" return __a & -__a;\n");
s.push_str("}\n\n");
s.push_str("static __inline__ unsigned long long __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("__blsr_u64(unsigned long long __a)\n");
s.push_str("{\n");
s.push_str(" return __a & (__a - 1);\n");
s.push_str("}\n\n");
}
s.push_str("#endif /* __BMIINTRIN_H */\n");
s
}
fn generate_bmi2intrin(&self) -> String {
let mut s = String::new();
s.push_str("/*===---- bmi2intrin.h - BMI2 intrinsics -----------------------------===*/\n");
s.push_str("/* */\n");
s.push_str("/* Intel BMI2 (Bit Manipulation Instructions 2) intrinsics. */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __BMI2INTRIN_H\n");
s.push_str("#define __BMI2INTRIN_H\n\n");
s.push_str("#if !defined(__BMI2__)\n");
s.push_str("#error \"BMI2 instruction set not enabled\"\n");
s.push_str("#endif\n\n");
s.push_str("/* BZHI: zero high bits starting at specified position */\n");
s.push_str(
"static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))\n",
);
s.push_str("__bzhi_u32(unsigned int __a, unsigned int __index)\n");
s.push_str("{\n");
s.push_str(" if (__index >= 32) return __a;\n");
s.push_str(" return __a & ((1U << __index) - 1);\n");
s.push_str("}\n\n");
s.push_str("/* PDEP: parallel bits deposit */\n");
s.push_str(
"static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))\n",
);
s.push_str("_pdep_u32(unsigned int __a, unsigned int __mask)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_pdep_si(__a, __mask);\n");
s.push_str("}\n\n");
s.push_str("/* PEXT: parallel bits extract */\n");
s.push_str(
"static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))\n",
);
s.push_str("_pext_u32(unsigned int __a, unsigned int __mask)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_pext_si(__a, __mask);\n");
s.push_str("}\n\n");
s.push_str("/* MULX: unsigned multiply without affecting flags */\n");
s.push_str(
"static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))\n",
);
s.push_str("_mulx_u32(unsigned int __a, unsigned int __b, unsigned int *__hi)\n");
s.push_str("{\n");
s.push_str(" unsigned long long __res = (unsigned long long)__a * __b;\n");
s.push_str(" *__hi = (unsigned int)(__res >> 32);\n");
s.push_str(" return (unsigned int)__res;\n");
s.push_str("}\n\n");
if self.config.pointer_width == 64 {
s.push_str("static __inline__ unsigned long long __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_pdep_u64(unsigned long long __a, unsigned long long __mask)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_pdep_di(__a, __mask);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ unsigned long long __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_pext_u64(unsigned long long __a, unsigned long long __mask)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_pext_di(__a, __mask);\n");
s.push_str("}\n\n");
}
s.push_str("#endif /* __BMI2INTRIN_H */\n");
s
}
fn generate_lzcntintrin(&self) -> String {
let mut s = String::new();
s.push_str("/*===---- lzcntintrin.h - LZCNT intrinsics ---------------------------===*/\n");
s.push_str("/* */\n");
s.push_str("/* Intel LZCNT (Leading Zero Count) intrinsics. */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __LZCNTINTRIN_H\n");
s.push_str("#define __LZCNTINTRIN_H\n\n");
s.push_str("#if !defined(__LZCNT__)\n");
s.push_str("#error \"LZCNT instruction set not enabled\"\n");
s.push_str("#endif\n\n");
s.push_str("/* Count leading zeros */\n");
s.push_str(
"static __inline__ unsigned short __attribute__((__always_inline__, __nodebug__))\n",
);
s.push_str("__lzcnt16(unsigned short __x)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_lzcnt_u16(__x);\n");
s.push_str("}\n\n");
s.push_str(
"static __inline__ unsigned int __attribute__((__always_inline__, __nodebug__))\n",
);
s.push_str("__lzcnt32(unsigned int __x)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_lzcnt_u32(__x);\n");
s.push_str("}\n\n");
if self.config.pointer_width == 64 {
s.push_str("static __inline__ unsigned long long __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("__lzcnt64(unsigned long long __x)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_lzcnt_u64(__x);\n");
s.push_str("}\n\n");
}
s.push_str("#endif /* __LZCNTINTRIN_H */\n");
s
}
fn generate_cpuid(&self) -> String {
let mut s = String::new();
s.push_str("/*===---- cpuid.h - X86 CPUID intrinsics -----------------------------===*/\n");
s.push_str("/* */\n");
s.push_str("/* Provides access to the CPUID instruction for x86 processors. */\n");
s.push_str("/* This is a compiler-supplied header equivalent to GCC's cpuid.h. */\n");
s.push_str(
"/*===-----------------------------------------------------------------===*/\n\n",
);
s.push_str("#ifndef __CPUID_H\n");
s.push_str("#define __CPUID_H\n\n");
s.push_str("#if !(defined(__i386__) || defined(__x86_64__))\n");
s.push_str("#error \"cpuid.h is only supported on x86 targets\"\n");
s.push_str("#endif\n\n");
s.push_str("/*\n");
s.push_str(" * __cpuid — execute CPUID instruction with leaf in __eax.\n");
s.push_str(" * Results are stored in the array pointed to by __info:\n");
s.push_str(" * __info[0] = EAX, __info[1] = EBX, __info[2] = ECX, __info[3] = EDX\n");
s.push_str(" */\n");
s.push_str("static __inline__ void __attribute__((__always_inline__))\n");
s.push_str("__cpuid(unsigned int __info[4], unsigned int __eax)\n");
s.push_str("{\n");
s.push_str(" __asm__ volatile(\"cpuid\"\n");
s.push_str(
" : \"=a\"(__info[0]), \"=b\"(__info[1]), \"=c\"(__info[2]), \"=d\"(__info[3])\n",
);
s.push_str(" : \"a\"(__eax), \"c\"(0));\n");
s.push_str("}\n\n");
s.push_str("/*\n");
s.push_str(" * __cpuid_count — execute CPUID instruction with leaf in __eax and\n");
s.push_str(" * sub-leaf in __ecx.\n");
s.push_str(" */\n");
s.push_str("static __inline__ void __attribute__((__always_inline__))\n");
s.push_str(
"__cpuid_count(unsigned int __info[4], unsigned int __eax, unsigned int __ecx)\n",
);
s.push_str("{\n");
s.push_str(" __asm__ volatile(\"cpuid\"\n");
s.push_str(
" : \"=a\"(__info[0]), \"=b\"(__info[1]), \"=c\"(__info[2]), \"=d\"(__info[3])\n",
);
s.push_str(" : \"a\"(__eax), \"c\"(__ecx));\n");
s.push_str("}\n\n");
s.push_str("/*\n");
s.push_str(" * __get_cpuid_max — return the maximum supported CPUID leaf number\n");
s.push_str(" * and vendor information. Sets *__sig to the vendor signature.\n");
s.push_str(" */\n");
s.push_str("static __inline__ unsigned int __attribute__((__always_inline__))\n");
s.push_str("__get_cpuid_max(unsigned int __eax, unsigned int *__sig)\n");
s.push_str("{\n");
s.push_str(" unsigned int __info[4];\n");
s.push_str(" __cpuid(__info, __eax);\n");
s.push_str(" if (__sig)\n");
s.push_str(" *__sig = __info[1]; /* EBX contains the vendor info for leaf 0 */\n");
s.push_str(" return __info[0];\n");
s.push_str("}\n\n");
s.push_str("/*\n");
s.push_str(" * Convenience macros for vendor identification.\n");
s.push_str(" * Compare the result from __get_cpuid_max(0, &sig) with these.\n");
s.push_str(" */\n");
s.push_str("#define __cpuid_vendor_intel \\\n");
s.push_str(" (((unsigned int)'u' << 24) | ((unsigned int)'n' << 16) | \\\n");
s.push_str(" ((unsigned int)'e' << 8) | (unsigned int)'G')\n\n");
s.push_str("#define __cpuid_vendor_amd \\\n");
s.push_str(" (((unsigned int)'h' << 24) | ((unsigned int)'t' << 16) | \\\n");
s.push_str(" ((unsigned int)'u' << 8) | (unsigned int)'A')\n\n");
s.push_str("/*\n");
s.push_str(" * Feature bit positions in CPUID leaves for common checks.\n");
s.push_str(" */\n");
s.push_str("#define __cpuid_feature_SSE 25 /* EDX bit 25 in leaf 1 */\n");
s.push_str("#define __cpuid_feature_SSE2 26 /* EDX bit 26 in leaf 1 */\n");
s.push_str("#define __cpuid_feature_SSE3 0 /* ECX bit 0 in leaf 1 */\n");
s.push_str("#define __cpuid_feature_SSSE3 9 /* ECX bit 9 in leaf 1 */\n");
s.push_str("#define __cpuid_feature_SSE4_1 19 /* ECX bit 19 in leaf 1 */\n");
s.push_str("#define __cpuid_feature_SSE4_2 20 /* ECX bit 20 in leaf 1 */\n");
s.push_str("#define __cpuid_feature_AES 25 /* ECX bit 25 in leaf 1 */\n");
s.push_str("#define __cpuid_feature_AVX 28 /* ECX bit 28 in leaf 1 */\n");
s.push_str("#define __cpuid_feature_FMA 12 /* ECX bit 12 in leaf 1 */\n");
s.push_str("#define __cpuid_feature_AVX2 5 /* EBX bit 5 in leaf 7 */\n");
s.push_str("#define __cpuid_feature_BMI 3 /* EBX bit 3 in leaf 7 */\n");
s.push_str("#define __cpuid_feature_BMI2 8 /* EBX bit 8 in leaf 7 */\n");
s.push_str("#define __cpuid_feature_LZCNT 5 /* ECX bit 5 in leaf 0x80000001 */\n");
s.push_str("#define __cpuid_feature_AVX512F 16 /* EBX bit 16 in leaf 7 */\n");
s.push_str("#define __cpuid_feature_AVX512BW 30 /* EBX bit 30 in leaf 7 */\n");
s.push_str("#define __cpuid_feature_AVX512DQ 17 /* EBX bit 17 in leaf 7 */\n");
s.push_str("#define __cpuid_feature_AVX512VL 31 /* EBX bit 31 in leaf 7 */\n\n");
s.push_str("#endif /* __CPUID_H */\n");
s
}
}
#[derive(Debug, Clone)]
pub struct X86HeaderProvider {
generator: X86BuiltinHeaders,
cache: HashMap<String, Option<String>>,
}
impl X86HeaderProvider {
pub fn new(config: X86TargetConfig) -> Self {
Self {
generator: X86BuiltinHeaders::new(config),
cache: HashMap::new(),
}
}
pub fn new_x86_64() -> Self {
Self::new(X86TargetConfig::new_x86_64_linux())
}
pub fn new_x86_32() -> Self {
Self::new(X86TargetConfig::new_x86_32_linux())
}
pub fn config_mut(&mut self) -> &mut X86TargetConfig {
&mut self.generator.config
}
pub fn config(&self) -> &X86TargetConfig {
&self.generator.config
}
pub fn resolve(&mut self, header_name: &str) -> Option<String> {
let normalized = header_name
.trim_matches('"')
.trim_matches('<')
.trim_matches('>');
let normalized_owned = normalized.to_string();
{
let cached = self.cache.get(&normalized_owned);
if let Some(cached) = cached {
return cached.clone();
}
}
let header = self.lookup_by_name(normalized)?;
if !self.is_feature_available(header) {
self.cache.insert(normalized_owned, None);
return None;
}
let content = self.generator.generate(header);
self.cache.insert(normalized_owned.clone(), Some(content));
self.cache.get(&normalized_owned).cloned().flatten()
}
pub fn is_builtin_header(&self, header_name: &str) -> bool {
let normalized = header_name
.trim_matches('"')
.trim_matches('<')
.trim_matches('>');
self.lookup_by_name(normalized).is_some()
}
pub fn is_available(&mut self, header_name: &str) -> bool {
let normalized = header_name
.trim_matches('"')
.trim_matches('<')
.trim_matches('>');
if let Some(cached) = self.cache.get(normalized) {
return cached.is_some();
}
match self.lookup_by_name(normalized) {
Some(h) => self.is_feature_available(h),
None => false,
}
}
pub fn prewarm_cache(&mut self) {
for header in self.generator.all_headers() {
if self.is_feature_available(header) {
let name = header.filename().to_string();
if !self.cache.contains_key(&name) {
let content = self.generator.generate(header);
self.cache.insert(name, Some(content));
}
}
}
}
pub fn clear_cache(&mut self) {
self.cache.clear();
}
pub fn cache_size(&self) -> usize {
self.cache.len()
}
pub fn available_count(&self) -> usize {
self.cache.values().filter(|v| v.is_some()).count()
}
fn lookup_by_name(&self, name: &str) -> Option<X86BuiltinHeader> {
match name {
"stddef.h" => Some(X86BuiltinHeader::Stddef),
"stdint.h" => Some(X86BuiltinHeader::Stdint),
"stdbool.h" => Some(X86BuiltinHeader::Stdbool),
"stdarg.h" => Some(X86BuiltinHeader::Stdarg),
"limits.h" => Some(X86BuiltinHeader::Limits),
"float.h" => Some(X86BuiltinHeader::Float),
"iso646.h" => Some(X86BuiltinHeader::Iso646),
"stdalign.h" => Some(X86BuiltinHeader::Stdalign),
"stdnoreturn.h" => Some(X86BuiltinHeader::Stdnoreturn),
"stdatomic.h" => Some(X86BuiltinHeader::Stdatomic),
"tgmath.h" => Some(X86BuiltinHeader::Tgmath),
"stdckdint.h" => Some(X86BuiltinHeader::Stdckdint),
"x86intrin.h" => Some(X86BuiltinHeader::X86Intrin),
"mmintrin.h" => Some(X86BuiltinHeader::Mmintrin),
"xmmintrin.h" => Some(X86BuiltinHeader::Xmmintrin),
"emmintrin.h" => Some(X86BuiltinHeader::Emmintrin),
"pmmintrin.h" => Some(X86BuiltinHeader::Pmmintrin),
"tmmintrin.h" => Some(X86BuiltinHeader::Tmmintrin),
"smmintrin.h" => Some(X86BuiltinHeader::Smmintrin),
"nmmintrin.h" => Some(X86BuiltinHeader::Nmmintrin),
"wmmintrin.h" => Some(X86BuiltinHeader::Wmmintrin),
"immintrin.h" => Some(X86BuiltinHeader::Immintrin),
"avxintrin.h" => Some(X86BuiltinHeader::Avxintrin),
"avx2intrin.h" => Some(X86BuiltinHeader::Avx2intrin),
"avx512fintrin.h" => Some(X86BuiltinHeader::Avx512fintrin),
"avx512bwintrin.h" => Some(X86BuiltinHeader::Avx512bwintrin),
"avx512dqintrin.h" => Some(X86BuiltinHeader::Avx512dqintrin),
"avx512vlintrin.h" => Some(X86BuiltinHeader::Avx512vlintrin),
"fmaintrin.h" => Some(X86BuiltinHeader::Fmaintrin),
"bmiintrin.h" => Some(X86BuiltinHeader::Bmiintrin),
"bmi2intrin.h" => Some(X86BuiltinHeader::Bmi2intrin),
"lzcntintrin.h" => Some(X86BuiltinHeader::Lzcntintrin),
"cpuid.h" => Some(X86BuiltinHeader::Cpuid),
_ => None,
}
}
fn is_feature_available(&self, header: X86BuiltinHeader) -> bool {
let cfg = &self.generator.config;
match header {
X86BuiltinHeader::Stddef
| X86BuiltinHeader::Stdint
| X86BuiltinHeader::Stdbool
| X86BuiltinHeader::Stdarg
| X86BuiltinHeader::Limits
| X86BuiltinHeader::Float
| X86BuiltinHeader::Iso646
| X86BuiltinHeader::Stdalign
| X86BuiltinHeader::Stdnoreturn
| X86BuiltinHeader::Stdatomic
| X86BuiltinHeader::Tgmath
| X86BuiltinHeader::Stdckdint
| X86BuiltinHeader::Cpuid => true,
X86BuiltinHeader::X86Intrin => true, X86BuiltinHeader::Mmintrin => cfg.has_mmx,
X86BuiltinHeader::Xmmintrin => cfg.has_sse,
X86BuiltinHeader::Emmintrin => cfg.has_sse2,
X86BuiltinHeader::Pmmintrin => cfg.has_sse3,
X86BuiltinHeader::Tmmintrin => cfg.has_ssse3,
X86BuiltinHeader::Smmintrin => cfg.has_sse4_1,
X86BuiltinHeader::Nmmintrin => cfg.has_sse4_2,
X86BuiltinHeader::Wmmintrin => cfg.has_aes,
X86BuiltinHeader::Immintrin => cfg.has_avx || cfg.has_mmx,
X86BuiltinHeader::Avxintrin => cfg.has_avx,
X86BuiltinHeader::Avx2intrin => cfg.has_avx2,
X86BuiltinHeader::Avx512fintrin => cfg.has_avx512f,
X86BuiltinHeader::Avx512bwintrin => cfg.has_avx512bw,
X86BuiltinHeader::Avx512dqintrin => cfg.has_avx512dq,
X86BuiltinHeader::Avx512vlintrin => cfg.has_avx512vl,
X86BuiltinHeader::Fmaintrin => cfg.has_fma,
X86BuiltinHeader::Bmiintrin => cfg.has_bmi,
X86BuiltinHeader::Bmi2intrin => cfg.has_bmi2,
X86BuiltinHeader::Lzcntintrin => cfg.has_lzcnt,
}
}
}
impl Default for X86HeaderProvider {
fn default() -> Self {
Self::new_x86_64()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum X86Feature {
Mmx,
Sse,
Sse2,
Sse3,
Ssse3,
Sse41,
Sse42,
Aes,
Avx,
Avx2,
Avx512f,
Avx512bw,
Avx512dq,
Avx512vl,
Fma,
Bmi,
Bmi2,
Lzcnt,
}
impl X86Feature {
pub fn name(&self) -> &'static str {
match self {
Self::Mmx => "MMX",
Self::Sse => "SSE",
Self::Sse2 => "SSE2",
Self::Sse3 => "SSE3",
Self::Ssse3 => "SSSE3",
Self::Sse41 => "SSE4.1",
Self::Sse42 => "SSE4.2",
Self::Aes => "AES",
Self::Avx => "AVX",
Self::Avx2 => "AVX2",
Self::Avx512f => "AVX-512F",
Self::Avx512bw => "AVX-512BW",
Self::Avx512dq => "AVX-512DQ",
Self::Avx512vl => "AVX-512VL",
Self::Fma => "FMA",
Self::Bmi => "BMI",
Self::Bmi2 => "BMI2",
Self::Lzcnt => "LZCNT",
}
}
pub fn header(&self) -> Option<X86BuiltinHeader> {
match self {
Self::Mmx => Some(X86BuiltinHeader::Mmintrin),
Self::Sse => Some(X86BuiltinHeader::Xmmintrin),
Self::Sse2 => Some(X86BuiltinHeader::Emmintrin),
Self::Sse3 => Some(X86BuiltinHeader::Pmmintrin),
Self::Ssse3 => Some(X86BuiltinHeader::Tmmintrin),
Self::Sse41 => Some(X86BuiltinHeader::Smmintrin),
Self::Sse42 => Some(X86BuiltinHeader::Nmmintrin),
Self::Aes => Some(X86BuiltinHeader::Wmmintrin),
Self::Avx => Some(X86BuiltinHeader::Avxintrin),
Self::Avx2 => Some(X86BuiltinHeader::Avx2intrin),
Self::Avx512f => Some(X86BuiltinHeader::Avx512fintrin),
Self::Avx512bw => Some(X86BuiltinHeader::Avx512bwintrin),
Self::Avx512dq => Some(X86BuiltinHeader::Avx512dqintrin),
Self::Avx512vl => Some(X86BuiltinHeader::Avx512vlintrin),
Self::Fma => Some(X86BuiltinHeader::Fmaintrin),
Self::Bmi => Some(X86BuiltinHeader::Bmiintrin),
Self::Bmi2 => Some(X86BuiltinHeader::Bmi2intrin),
Self::Lzcnt => Some(X86BuiltinHeader::Lzcntintrin),
}
}
pub fn prerequisites(&self) -> &'static [X86Feature] {
match self {
Self::Mmx => &[],
Self::Sse => &[Self::Mmx],
Self::Sse2 => &[Self::Sse],
Self::Sse3 => &[Self::Sse2],
Self::Ssse3 => &[Self::Sse3],
Self::Sse41 => &[Self::Ssse3],
Self::Sse42 => &[Self::Sse41],
Self::Aes => &[Self::Sse2],
Self::Avx => &[Self::Sse42],
Self::Avx2 => &[Self::Avx],
Self::Avx512f => &[Self::Avx2],
Self::Avx512bw => &[Self::Avx512f],
Self::Avx512dq => &[Self::Avx512f],
Self::Avx512vl => &[Self::Avx512f],
Self::Fma => &[Self::Avx],
Self::Bmi => &[],
Self::Bmi2 => &[],
Self::Lzcnt => &[],
}
}
pub fn all() -> &'static [X86Feature] {
&[
Self::Mmx,
Self::Sse,
Self::Sse2,
Self::Sse3,
Self::Ssse3,
Self::Sse41,
Self::Sse42,
Self::Aes,
Self::Avx,
Self::Avx2,
Self::Avx512f,
Self::Avx512bw,
Self::Avx512dq,
Self::Avx512vl,
Self::Fma,
Self::Bmi,
Self::Bmi2,
Self::Lzcnt,
]
}
}
impl X86TargetConfig {
pub fn has_feature(&self, feature: X86Feature) -> bool {
match feature {
X86Feature::Mmx => self.has_mmx,
X86Feature::Sse => self.has_sse,
X86Feature::Sse2 => self.has_sse2,
X86Feature::Sse3 => self.has_sse3,
X86Feature::Ssse3 => self.has_ssse3,
X86Feature::Sse41 => self.has_sse4_1,
X86Feature::Sse42 => self.has_sse4_2,
X86Feature::Aes => self.has_aes,
X86Feature::Avx => self.has_avx,
X86Feature::Avx2 => self.has_avx2,
X86Feature::Avx512f => self.has_avx512f,
X86Feature::Avx512bw => self.has_avx512bw,
X86Feature::Avx512dq => self.has_avx512dq,
X86Feature::Avx512vl => self.has_avx512vl,
X86Feature::Fma => self.has_fma,
X86Feature::Bmi => self.has_bmi,
X86Feature::Bmi2 => self.has_bmi2,
X86Feature::Lzcnt => self.has_lzcnt,
}
}
pub fn enable_feature(&mut self, feature: X86Feature) {
for prereq in feature.prerequisites() {
self.enable_feature(*prereq);
}
match feature {
X86Feature::Mmx => self.has_mmx = true,
X86Feature::Sse => self.has_sse = true,
X86Feature::Sse2 => self.has_sse2 = true,
X86Feature::Sse3 => self.has_sse3 = true,
X86Feature::Ssse3 => self.has_ssse3 = true,
X86Feature::Sse41 => self.has_sse4_1 = true,
X86Feature::Sse42 => self.has_sse4_2 = true,
X86Feature::Aes => self.has_aes = true,
X86Feature::Avx => self.has_avx = true,
X86Feature::Avx2 => self.has_avx2 = true,
X86Feature::Avx512f => self.has_avx512f = true,
X86Feature::Avx512bw => self.has_avx512bw = true,
X86Feature::Avx512dq => self.has_avx512dq = true,
X86Feature::Avx512vl => self.has_avx512vl = true,
X86Feature::Fma => self.has_fma = true,
X86Feature::Bmi => self.has_bmi = true,
X86Feature::Bmi2 => self.has_bmi2 = true,
X86Feature::Lzcnt => self.has_lzcnt = true,
}
}
pub fn enabled_features(&self) -> Vec<X86Feature> {
X86Feature::all()
.iter()
.filter(|f| self.has_feature(**f))
.copied()
.collect()
}
pub fn new_minimal_x86_64() -> Self {
Self {
pointer_width: 64,
long_width: 64,
long_long_width: 64,
wchar_width: 32,
little_endian: true,
int_width: 32,
short_width: 16,
char_width: 8,
char_is_signed: true,
max_alignment: 8,
has_int128: false,
has_mmx: false,
has_sse: false,
has_sse2: false,
has_sse3: false,
has_ssse3: false,
has_sse4_1: false,
has_sse4_2: false,
has_aes: false,
has_avx: false,
has_avx2: false,
has_avx512f: false,
has_avx512bw: false,
has_avx512dq: false,
has_avx512vl: false,
has_fma: false,
has_bmi: false,
has_bmi2: false,
has_lzcnt: false,
}
}
}
pub struct HeaderContentValidator {
pub errors: Vec<String>,
pub warnings: Vec<String>,
}
impl HeaderContentValidator {
pub fn new() -> Self {
Self {
errors: Vec::new(),
warnings: Vec::new(),
}
}
pub fn validate_all(r#gen: &X86BuiltinHeaders) -> Vec<(X86BuiltinHeader, Vec<String>)> {
let mut results = Vec::new();
for header in r#gen.all_headers() {
let content = r#gen.generate(header);
let mut v = Self::new();
v.validate_content(header, &content);
if !v.errors.is_empty() {
results.push((header, v.errors.clone()));
}
}
results
}
pub fn validate_content(&mut self, header: X86BuiltinHeader, content: &str) {
let name = header.filename();
if !content.contains("#ifndef") {
self.errors
.push(format!("{}: missing #ifndef include guard", name));
}
if !content.contains("#define") {
self.errors
.push(format!("{}: missing #define guard macro", name));
}
if !content.contains("#endif") {
self.errors.push(format!("{}: missing #endif", name));
}
if !content.ends_with('\n') {
self.warnings
.push(format!("{}: missing trailing newline", name));
}
if content.trim().is_empty() {
self.errors
.push(format!("{}: header content is empty", name));
}
let ifdef_count = content.matches("#ifndef").count()
+ content.matches("#ifdef").count()
+ content.matches("#if ").count()
+ content.matches("#if(").count();
let endif_count = content.matches("#endif").count();
if ifdef_count > endif_count {
self.errors.push(format!(
"{}: unbalanced conditionals ({} opens, {} closes)",
name, ifdef_count, endif_count
));
}
if header.is_standard_c() && !content.is_ascii() {
self.errors
.push(format!("{}: standard C header contains non-ASCII", name));
}
}
pub fn is_valid(&self) -> bool {
self.errors.is_empty()
}
pub fn issue_count(&self) -> usize {
self.errors.len() + self.warnings.len()
}
}
impl Default for HeaderContentValidator {
fn default() -> Self {
Self::new()
}
}
impl X86BuiltinHeaders {
pub fn generate_mmx_extended(&self) -> String {
let mut s = String::new();
s.push_str("/* Extended MMX intrinsics */\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_adds_pi8(__m64 __m1, __m64 __m2)\n");
s.push_str("{\n");
s.push_str(" return (__m64)__builtin_ia32_paddsb((__v8qi)__m1, (__v8qi)__m2);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_adds_pu8(__m64 __m1, __m64 __m2)\n");
s.push_str("{\n");
s.push_str(" return (__m64)__builtin_ia32_paddusb((__v8qi)__m1, (__v8qi)__m2);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_adds_pi16(__m64 __m1, __m64 __m2)\n");
s.push_str("{\n");
s.push_str(" return (__m64)__builtin_ia32_paddsw((__v4hi)__m1, (__v4hi)__m2);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_subs_pi8(__m64 __m1, __m64 __m2)\n");
s.push_str("{\n");
s.push_str(" return (__m64)__builtin_ia32_psubsb((__v8qi)__m1, (__v8qi)__m2);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_subs_pi16(__m64 __m1, __m64 __m2)\n");
s.push_str("{\n");
s.push_str(" return (__m64)__builtin_ia32_psubsw((__v4hi)__m1, (__v4hi)__m2);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_mulhi_pi16(__m64 __m1, __m64 __m2)\n");
s.push_str("{\n");
s.push_str(" return (__m64)__builtin_ia32_pmulhw((__v4hi)__m1, (__v4hi)__m2);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_avg_pu8(__m64 __m1, __m64 __m2)\n");
s.push_str("{\n");
s.push_str(" return (__m64)__builtin_ia32_pavgb((__v8qi)__m1, (__v8qi)__m2);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_avg_pu16(__m64 __m1, __m64 __m2)\n");
s.push_str("{\n");
s.push_str(" return (__m64)__builtin_ia32_pavgw((__v4hi)__m1, (__v4hi)__m2);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_min_pi16(__m64 __m1, __m64 __m2)\n");
s.push_str("{\n");
s.push_str(" return (__m64)__builtin_ia32_pminsw((__v4hi)__m1, (__v4hi)__m2);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_max_pi16(__m64 __m1, __m64 __m2)\n");
s.push_str("{\n");
s.push_str(" return (__m64)__builtin_ia32_pmaxsw((__v4hi)__m1, (__v4hi)__m2);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ int __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_movemask_pi8(__m64 __m)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_pmovmskb((__v8qi)__m);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_insert_pi16(__m64 __m, int __i, int __n)\n");
s.push_str("{\n");
s.push_str(" return (__m64)__builtin_ia32_vec_set_v4hi((__v4hi)__m, __i, __n);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ int __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_extract_pi16(__m64 __m, int __n)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_vec_ext_v4hi((__v4hi)__m, __n);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_sad_pu8(__m64 __m1, __m64 __m2)\n");
s.push_str("{\n");
s.push_str(" return (__m64)__builtin_ia32_psadbw((__v8qi)__m1, (__v8qi)__m2);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m64 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_shuffle_pi16(__m64 __m, int __n)\n");
s.push_str("{\n");
s.push_str(" return (__m64)__builtin_ia32_pshufw((__v4hi)__m, __n);\n");
s.push_str("}\n\n");
s
}
pub fn generate_sse_extended(&self) -> String {
let mut s = String::new();
s.push_str("/* Extended SSE intrinsics */\n\n");
s.push_str("static __inline__ void __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_stream_ps(float *__p, __m128 __a)\n");
s.push_str("{\n");
s.push_str(" __builtin_ia32_movntps(__p, __a);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ void __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_stream_pi(__m64 *__p, __m64 __a)\n");
s.push_str("{\n");
s.push_str(" __builtin_ia32_movntq(__p, __a);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ void __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_pause(void)\n");
s.push_str("{\n");
s.push_str(" __builtin_ia32_pause();\n");
s.push_str("}\n\n");
s.push_str("#define _MM_TRANSPOSE4_PS(row0, row1, row2, row3) do { \\\n");
s.push_str(" __m128 __tmp0, __tmp1, __tmp2, __tmp3; \\\n");
s.push_str(" __tmp0 = _mm_unpacklo_ps((row0), (row1)); \\\n");
s.push_str(" __tmp1 = _mm_unpackhi_ps((row0), (row1)); \\\n");
s.push_str(" __tmp2 = _mm_unpacklo_ps((row2), (row3)); \\\n");
s.push_str(" __tmp3 = _mm_unpackhi_ps((row2), (row3)); \\\n");
s.push_str(" (row0) = _mm_movelh_ps(__tmp0, __tmp2); \\\n");
s.push_str(" (row1) = _mm_movehl_ps(__tmp2, __tmp0); \\\n");
s.push_str(" (row2) = _mm_movelh_ps(__tmp1, __tmp3); \\\n");
s.push_str(" (row3) = _mm_movehl_ps(__tmp3, __tmp1); \\\n");
s.push_str("} while (0)\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_loadh_pi(__m128 __a, __m64 const *__p)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_loadhps(__a, (__v2si *)__p);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_loadl_pi(__m128 __a, __m64 const *__p)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_loadlps(__a, (__v2si *)__p);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ void __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_storeh_pi(__m64 *__p, __m128 __a)\n");
s.push_str("{\n");
s.push_str(" __builtin_ia32_storehps((__v2si *)__p, __a);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ void __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_storel_pi(__m64 *__p, __m128 __a)\n");
s.push_str("{\n");
s.push_str(" __builtin_ia32_storelps((__v2si *)__p, __a);\n");
s.push_str("}\n\n");
s
}
pub fn generate_sse2_extended(&self) -> String {
let mut s = String::new();
s.push_str("/* Extended SSE2 intrinsics */\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_adds_epi8(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_paddsb128((__v16qi)__a, (__v16qi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_adds_epu8(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_paddusb128((__v16qi)__a, (__v16qi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_adds_epi16(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_paddsw128((__v8hi)__a, (__v8hi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_subs_epi8(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_psubsb128((__v16qi)__a, (__v16qi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_subs_epi16(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_psubsw128((__v8hi)__a, (__v8hi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_avg_epu8(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_pavgb128((__v16qi)__a, (__v16qi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_avg_epu16(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_pavgw128((__v8hi)__a, (__v8hi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_min_epu8(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_pminub128((__v16qi)__a, (__v16qi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_max_epu8(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_pmaxub128((__v16qi)__a, (__v16qi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_mulhi_epi16(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_pmulhw128((__v8hi)__a, (__v8hi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_mulhi_epu16(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_pmulhuw128((__v8hi)__a, (__v8hi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_sad_epu8(__m128i __a, __m128i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m128i)__builtin_ia32_psadbw128((__v16qi)__a, (__v16qi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ int __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_movemask_epi8(__m128i __a)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_pmovmskb128((__v16qi)__a);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ void __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_stream_si128(__m128i *__p, __m128i __a)\n");
s.push_str("{\n");
s.push_str(" __builtin_ia32_movntdq((__v2di *)__p, (__v2di)__a);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ void __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_stream_pd(double *__p, __m128d __a)\n");
s.push_str("{\n");
s.push_str(" __builtin_ia32_movntpd(__p, __a);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ void __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_maskmove_si64(__m64 __d, __m64 __n, char *__p)\n");
s.push_str("{\n");
s.push_str(" __builtin_ia32_maskmovq((__v8qi)__d, (__v8qi)__n, __p);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ void __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_clflush(void const *__p)\n");
s.push_str("{\n");
s.push_str(" __builtin_ia32_clflush(__p);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ void __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_lfence(void)\n");
s.push_str("{\n");
s.push_str(" __builtin_ia32_lfence();\n");
s.push_str("}\n\n");
s.push_str("static __inline__ void __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm_mfence(void)\n");
s.push_str("{\n");
s.push_str(" __builtin_ia32_mfence();\n");
s.push_str("}\n\n");
s
}
pub fn generate_avx_extended(&self) -> String {
let mut s = String::new();
s.push_str("/* Extended AVX intrinsics */\n\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_hadd_ps(__m256 __a, __m256 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_haddps256(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_hadd_pd(__m256d __a, __m256d __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_haddpd256(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_hsub_ps(__m256 __a, __m256 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_hsubps256(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_addsub_ps(__m256 __a, __m256 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_addsubps256(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_addsub_pd(__m256d __a, __m256d __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_addsubpd256(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_blend_ps(__m256 __a, __m256 __b, const int __imm8)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_blendps256(__a, __b, __imm8);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_blend_pd(__m256d __a, __m256d __b, const int __imm8)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_blendpd256(__a, __b, __imm8);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_blendv_ps(__m256 __a, __m256 __b, __m256 __mask)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_blendvps256(__a, __b, __mask);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_dp_ps(__m256 __a, __m256 __b, const int __imm8)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_dpps256(__a, __b, __imm8);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_round_ps(__m256 __a, int __rounding)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_roundps256(__a, __rounding);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256d __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_round_pd(__m256d __a, int __rounding)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_roundpd256(__a, __rounding);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_floor_ps(__m256 __a)\n");
s.push_str("{\n");
s.push_str(" return _mm256_round_ps(__a, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_ceil_ps(__m256 __a)\n");
s.push_str("{\n");
s.push_str(" return _mm256_round_ps(__a, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ int __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_testz_ps(__m256 __a, __m256 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_vtestzps256(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ int __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_testc_ps(__m256 __a, __m256 __b)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_vtestcps256(__a, __b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m128 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_extractf128_ps(__m256 __a, const int __imm8)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_vextractf128_ps256(__a, __imm8);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_insertf128_ps(__m256 __a, __m128 __b, const int __imm8)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_vinsertf128_ps256(__a, __b, __imm8);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ void __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_stream_ps(float *__p, __m256 __a)\n");
s.push_str("{\n");
s.push_str(" __builtin_ia32_movntps256(__p, __a);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ void __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_stream_pd(double *__p, __m256d __a)\n");
s.push_str("{\n");
s.push_str(" __builtin_ia32_movntpd256(__p, __a);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256 __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_maskload_ps(float const *__p, __m256i __mask)\n");
s.push_str("{\n");
s.push_str(" return __builtin_ia32_maskloadps256(__p, __mask);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ void __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_maskstore_ps(float *__p, __m256i __mask, __m256 __a)\n");
s.push_str("{\n");
s.push_str(" __builtin_ia32_maskstoreps256(__p, __mask, __a);\n");
s.push_str("}\n\n");
s
}
pub fn generate_avx2_extended(&self) -> String {
let mut s = String::new();
s.push_str("/* Extended AVX2 intrinsics */\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_sllv_epi32(__m256i __a, __m256i __count)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_psllv8si((__v8si)__a, (__v8si)__count);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_sllv_epi64(__m256i __a, __m256i __count)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_psllv4di((__v4di)__a, (__v4di)__count);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_srlv_epi32(__m256i __a, __m256i __count)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_psrlv8si((__v8si)__a, (__v8si)__count);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_srav_epi32(__m256i __a, __m256i __count)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_psrav8si((__v8si)__a, (__v8si)__count);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_adds_epi8(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_paddsb256((__v32qi)__a, (__v32qi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_adds_epi16(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_paddsw256((__v16hi)__a, (__v16hi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_subs_epi8(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_psubsb256((__v32qi)__a, (__v32qi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_subs_epi16(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_psubsw256((__v16hi)__a, (__v16hi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_mulhi_epi16(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_pmulhw256((__v16hi)__a, (__v16hi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_hadd_epi16(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_phaddw256((__v16hi)__a, (__v16hi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_hadd_epi32(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_phaddd256((__v8si)__a, (__v8si)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_shuffle_epi8(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_pshufb256((__v32qi)__a, (__v32qi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_packs_epi16(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_packsswb256((__v16hi)__a, (__v16hi)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_packs_epi32(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_packssdw256((__v8si)__a, (__v8si)__b);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_unpackhi_epi8(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_shufflevector((__v32qi)__a, (__v32qi)__b,\n");
s.push_str(" 8,40,9,41,10,42,11,43,12,44,13,45,14,46,15,47,\n");
s.push_str(" 24,56,25,57,26,58,27,59,28,60,29,61,30,62,31,63);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_unpacklo_epi8(__m256i __a, __m256i __b)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_shufflevector((__v32qi)__a, (__v32qi)__b,\n");
s.push_str(" 0,32,1,33,2,34,3,35,4,36,5,37,6,38,7,39,\n");
s.push_str(" 16,48,17,49,18,50,19,51,20,52,21,53,22,54,23,55);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_broadcastsi128_si256(__m128i const *__p)\n");
s.push_str("{\n");
s.push_str(" __m128i __v = *__p;\n");
s.push_str(" return (__m256i)__builtin_shufflevector(__v, __v, 0,1,2,3,0,1,2,3);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ __m256i __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_maskload_epi32(int const *__p, __m256i __mask)\n");
s.push_str("{\n");
s.push_str(" return (__m256i)__builtin_ia32_maskloadd256(__p, (__v8si)__mask);\n");
s.push_str("}\n\n");
s.push_str("static __inline__ void __attribute__((__always_inline__, __nodebug__))\n");
s.push_str("_mm256_maskstore_epi32(int *__p, __m256i __mask, __m256i __a)\n");
s.push_str("{\n");
s.push_str(" __builtin_ia32_maskstored256(__p, (__v8si)__mask, (__v8si)__a);\n");
s.push_str("}\n\n");
s
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_x86_builtin_header_filenames() {
assert_eq!(X86BuiltinHeader::Stddef.filename(), "stddef.h");
assert_eq!(X86BuiltinHeader::Stdint.filename(), "stdint.h");
assert_eq!(X86BuiltinHeader::Stdbool.filename(), "stdbool.h");
assert_eq!(X86BuiltinHeader::Stdarg.filename(), "stdarg.h");
assert_eq!(X86BuiltinHeader::Limits.filename(), "limits.h");
assert_eq!(X86BuiltinHeader::Float.filename(), "float.h");
assert_eq!(X86BuiltinHeader::Iso646.filename(), "iso646.h");
assert_eq!(X86BuiltinHeader::Stdalign.filename(), "stdalign.h");
assert_eq!(X86BuiltinHeader::Stdnoreturn.filename(), "stdnoreturn.h");
assert_eq!(X86BuiltinHeader::Stdatomic.filename(), "stdatomic.h");
assert_eq!(X86BuiltinHeader::Tgmath.filename(), "tgmath.h");
assert_eq!(X86BuiltinHeader::Stdckdint.filename(), "stdckdint.h");
assert_eq!(X86BuiltinHeader::X86Intrin.filename(), "x86intrin.h");
assert_eq!(X86BuiltinHeader::Mmintrin.filename(), "mmintrin.h");
assert_eq!(X86BuiltinHeader::Xmmintrin.filename(), "xmmintrin.h");
assert_eq!(X86BuiltinHeader::Emmintrin.filename(), "emmintrin.h");
assert_eq!(X86BuiltinHeader::Cpuid.filename(), "cpuid.h");
}
#[test]
fn test_is_standard_c() {
assert!(X86BuiltinHeader::Stddef.is_standard_c());
assert!(X86BuiltinHeader::Limits.is_standard_c());
assert!(!X86BuiltinHeader::Xmmintrin.is_standard_c());
assert!(!X86BuiltinHeader::Cpuid.is_standard_c());
}
#[test]
fn test_is_x86_intrinsic() {
assert!(X86BuiltinHeader::Xmmintrin.is_x86_intrinsic());
assert!(X86BuiltinHeader::Avx2intrin.is_x86_intrinsic());
assert!(X86BuiltinHeader::Cpuid.is_x86_intrinsic());
assert!(!X86BuiltinHeader::Stddef.is_x86_intrinsic());
}
#[test]
fn test_x86_target_config_default() {
let cfg = X86TargetConfig::default();
assert_eq!(cfg.pointer_width, 64);
assert_eq!(cfg.long_width, 64);
assert_eq!(cfg.int_width, 32);
assert!(cfg.has_sse);
assert!(cfg.has_sse2);
assert!(cfg.has_avx);
assert!(!cfg.has_avx512f);
}
#[test]
fn test_x86_target_config_avx512() {
let cfg = X86TargetConfig::new_x86_64_avx512();
assert!(cfg.has_avx512f);
assert!(cfg.has_avx512bw);
assert!(cfg.has_avx512dq);
assert!(cfg.has_avx512vl);
assert_eq!(cfg.max_alignment, 64);
}
#[test]
fn test_x86_target_config_32bit() {
let cfg = X86TargetConfig::new_x86_32_linux();
assert_eq!(cfg.pointer_width, 32);
assert_eq!(cfg.long_width, 32);
assert!(!cfg.has_int128);
assert!(cfg.has_sse2);
}
#[test]
fn test_generate_stddef_x86_64() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Stddef);
assert!(content.contains("__STDDEF_H"));
assert!(content.contains("size_t"));
assert!(content.contains("ptrdiff_t"));
assert!(content.contains("NULL"));
assert!(content.contains("offsetof"));
assert!(content.contains("max_align_t"));
assert!(content.contains("wchar_t"));
assert!(content.contains("nullptr_t"));
assert!(content.contains("unreachable"));
}
#[test]
fn test_generate_stddef_size_t_64bit() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Stddef);
assert!(content.contains("__SIZE_TYPE__"));
}
#[test]
fn test_generate_stdarg() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Stdarg);
assert!(content.contains("va_list"));
assert!(content.contains("va_start"));
assert!(content.contains("va_end"));
assert!(content.contains("va_arg"));
assert!(content.contains("va_copy"));
assert!(content.contains("__builtin_va_list"));
assert!(content.contains("X86-64 System V AMD64"));
}
#[test]
fn test_generate_stdbool() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Stdbool);
assert!(content.contains("bool"));
assert!(content.contains("true"));
assert!(content.contains("false"));
assert!(content.contains("__bool_true_false_are_defined"));
}
#[test]
fn test_generate_stdint_x86_64() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Stdint);
assert!(content.contains("int8_t"));
assert!(content.contains("int16_t"));
assert!(content.contains("int32_t"));
assert!(content.contains("int64_t"));
assert!(content.contains("uint8_t"));
assert!(content.contains("uintptr_t"));
assert!(content.contains("INT32_MIN"));
assert!(content.contains("INT64_MAX"));
assert!(content.contains("SIZE_MAX"));
assert!(content.contains("WINT_MIN"));
assert!(content.contains("WINT_MAX"));
assert!(content.contains("intptr_t"));
assert!(content.contains("long"));
}
#[test]
fn test_generate_stdint_32bit() {
let r#gen = X86BuiltinHeaders::new_x86_32();
let content = r#gen.generate(X86BuiltinHeader::Stdint);
assert!(content.contains("intptr_t"));
assert!(content.contains("UINT32_MAX"));
}
#[test]
fn test_generate_limits_x86_64_lp64() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Limits);
assert!(content.contains("CHAR_BIT 8"));
assert!(content.contains("SCHAR_MIN"));
assert!(content.contains("UCHAR_MAX"));
assert!(content.contains("CHAR_MIN"));
assert!(content.contains("SHRT_MIN"));
assert!(content.contains("SHRT_MAX"));
assert!(content.contains("INT_MIN"));
assert!(content.contains("INT_MAX"));
assert!(content.contains("UINT_MAX"));
assert!(content.contains("9223372036854775807"));
assert!(content.contains("LLONG_MAX"));
assert!(content.contains("ULLONG_MAX"));
assert!(content.contains("SSIZE_MAX"));
}
#[test]
fn test_generate_limits_32bit() {
let r#gen = X86BuiltinHeaders::new_x86_32();
let content = r#gen.generate(X86BuiltinHeader::Limits);
assert!(content.contains("2147483647L"));
}
#[test]
fn test_generate_float_x86_64_extended_precision() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Float);
assert!(content.contains("FLT_RADIX 2"));
assert!(content.contains("FLT_MANT_DIG"));
assert!(content.contains("DBL_MANT_DIG"));
assert!(content.contains("LDBL_MANT_DIG 64")); assert!(content.contains("FLT_MIN"));
assert!(content.contains("DBL_MAX"));
assert!(content.contains("LDBL_EPSILON"));
assert!(content.contains("FLT_EVAL_METHOD"));
assert!(content.contains("FLT_DIG"));
assert!(content.contains("DBL_DIG"));
assert!(content.contains("LDBL_DIG"));
}
#[test]
fn test_generate_float_has_subnorm() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Float);
assert!(content.contains("FLT_HAS_SUBNORM 1"));
assert!(content.contains("DBL_HAS_SUBNORM 1"));
assert!(content.contains("LDBL_HAS_SUBNORM 1"));
}
#[test]
fn test_generate_iso646() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Iso646);
assert!(content.contains("and"));
assert!(content.contains("or"));
assert!(content.contains("not"));
assert!(content.contains("xor"));
assert!(content.contains("bitand"));
assert!(content.contains("bitor"));
assert!(content.contains("compl"));
assert!(content.contains("and_eq"));
assert!(content.contains("or_eq"));
assert!(content.contains("xor_eq"));
assert!(content.contains("not_eq"));
}
#[test]
fn test_generate_stdalign() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Stdalign);
assert!(content.contains("alignas"));
assert!(content.contains("alignof"));
assert!(content.contains("__alignas_is_defined"));
assert!(content.contains("__alignof_is_defined"));
}
#[test]
fn test_generate_stdnoreturn() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Stdnoreturn);
assert!(content.contains("noreturn"));
assert!(content.contains("_Noreturn"));
}
#[test]
fn test_generate_stdatomic() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Stdatomic);
assert!(content.contains("memory_order_relaxed"));
assert!(content.contains("memory_order_acquire"));
assert!(content.contains("memory_order_release"));
assert!(content.contains("memory_order_seq_cst"));
assert!(content.contains("atomic_int"));
assert!(content.contains("atomic_long"));
assert!(content.contains("atomic_bool"));
assert!(content.contains("atomic_load"));
assert!(content.contains("atomic_store"));
assert!(content.contains("atomic_exchange"));
assert!(content.contains("atomic_compare_exchange_strong"));
assert!(content.contains("atomic_compare_exchange_weak"));
assert!(content.contains("atomic_fetch_add"));
assert!(content.contains("atomic_fetch_sub"));
assert!(content.contains("atomic_fetch_or"));
assert!(content.contains("atomic_fetch_xor"));
assert!(content.contains("atomic_fetch_and"));
assert!(content.contains("atomic_thread_fence"));
assert!(content.contains("atomic_signal_fence"));
assert!(content.contains("ATOMIC_FLAG_INIT"));
assert!(content.contains("ATOMIC_VAR_INIT"));
assert!(content.contains("atomic_flag"));
}
#[test]
fn test_generate_tgmath() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Tgmath);
assert!(content.contains("sin"));
assert!(content.contains("cos"));
assert!(content.contains("tan"));
assert!(content.contains("exp"));
assert!(content.contains("log"));
assert!(content.contains("sqrt"));
assert!(content.contains("pow"));
assert!(content.contains("fabs"));
assert!(content.contains("__builtin_tgmath"));
}
#[test]
fn test_generate_stdckdint() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Stdckdint);
assert!(content.contains("ckd_add"));
assert!(content.contains("ckd_sub"));
assert!(content.contains("ckd_mul"));
assert!(content.contains("__builtin_add_overflow"));
assert!(content.contains("__builtin_sub_overflow"));
assert!(content.contains("__builtin_mul_overflow"));
}
#[test]
fn test_generate_x86intrin_umbrella() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::X86Intrin);
assert!(content.contains("__X86INTRIN_H"));
assert!(content.contains("mmintrin.h"));
assert!(content.contains("xmmintrin.h"));
assert!(content.contains("emmintrin.h"));
assert!(content.contains("cpuid.h"));
}
#[test]
fn test_generate_mmintrin() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Mmintrin);
assert!(content.contains("__m64"));
assert!(content.contains("_mm_setzero_si64"));
assert!(content.contains("_mm_set_pi32"));
assert!(content.contains("_mm_add_pi16"));
assert!(content.contains("_mm_sub_pi32"));
assert!(content.contains("_mm_and_si64"));
assert!(content.contains("_mm_cmpeq_pi8"));
assert!(content.contains("_mm_packs_pi16"));
assert!(content.contains("_mm_empty"));
}
#[test]
fn test_generate_xmmintrin() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Xmmintrin);
assert!(content.contains("__m128"));
assert!(content.contains("_mm_setzero_ps"));
assert!(content.contains("_mm_add_ps"));
assert!(content.contains("_mm_mul_ps"));
assert!(content.contains("_mm_div_ps"));
assert!(content.contains("_mm_sqrt_ps"));
assert!(content.contains("_mm_min_ps"));
assert!(content.contains("_mm_max_ps"));
assert!(content.contains("_mm_shuffle_ps"));
assert!(content.contains("_MM_SHUFFLE"));
assert!(content.contains("_mm_prefetch"));
assert!(content.contains("_MM_HINT_T0"));
}
#[test]
fn test_generate_emmintrin() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Emmintrin);
assert!(content.contains("__m128d"));
assert!(content.contains("__m128i"));
assert!(content.contains("_mm_add_pd"));
assert!(content.contains("_mm_mul_pd"));
assert!(content.contains("_mm_add_epi32"));
assert!(content.contains("_mm_and_si128"));
assert!(content.contains("_mm_cmpeq_epi32"));
assert!(content.contains("_mm_packs_epi16"));
assert!(content.contains("_mm_setzero_si128"));
}
#[test]
fn test_generate_pmmintrin() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Pmmintrin);
assert!(content.contains("_mm_addsub_ps"));
assert!(content.contains("_mm_hadd_ps"));
assert!(content.contains("_mm_hsub_ps"));
assert!(content.contains("_mm_moveldup_ps"));
assert!(content.contains("_mm_movehdup_ps"));
assert!(content.contains("_mm_movedup_pd"));
assert!(content.contains("_mm_lddqu_si128"));
}
#[test]
fn test_generate_tmmintrin() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Tmmintrin);
assert!(content.contains("_mm_abs_epi8"));
assert!(content.contains("_mm_abs_epi32"));
assert!(content.contains("_mm_sign_epi16"));
assert!(content.contains("_mm_shuffle_epi8"));
assert!(content.contains("_mm_hadd_epi16"));
assert!(content.contains("_mm_alignr_epi8"));
assert!(content.contains("_mm_maddubs_epi16"));
}
#[test]
fn test_generate_smmintrin() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Smmintrin);
assert!(content.contains("_mm_blend_ps"));
assert!(content.contains("_mm_blendv_ps"));
assert!(content.contains("_mm_dp_ps"));
assert!(content.contains("_mm_round_ps"));
assert!(content.contains("_mm_mullo_epi32"));
assert!(content.contains("_mm_min_epi8"));
assert!(content.contains("_mm_max_epi32"));
assert!(content.contains("_mm_testz_si128"));
assert!(content.contains("_mm_stream_load_si128"));
}
#[test]
fn test_generate_nmmintrin() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Nmmintrin);
assert!(content.contains("_mm_crc32_u8"));
assert!(content.contains("_mm_crc32_u32"));
assert!(content.contains("_mm_crc32_u64"));
assert!(content.contains("_mm_cmpistri"));
assert!(content.contains("_mm_cmpestri"));
}
#[test]
fn test_generate_wmmintrin() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Wmmintrin);
assert!(content.contains("_mm_aesenc_si128"));
assert!(content.contains("_mm_aesdec_si128"));
assert!(content.contains("_mm_aesenclast_si128"));
assert!(content.contains("_mm_aesdeclast_si128"));
assert!(content.contains("_mm_aesimc_si128"));
assert!(content.contains("_mm_aeskeygenassist_si128"));
}
#[test]
fn test_generate_immintrin() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Immintrin);
assert!(content.contains("__m256"));
assert!(content.contains("__m256d"));
assert!(content.contains("__m256i"));
assert!(content.contains("mmintrin.h"));
assert!(content.contains("xmmintrin.h"));
assert!(content.contains("avxintrin.h"));
}
#[test]
fn test_generate_avxintrin() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Avxintrin);
assert!(content.contains("__m256"));
assert!(content.contains("__m256d"));
assert!(content.contains("_mm256_add_ps"));
assert!(content.contains("_mm256_mul_ps"));
assert!(content.contains("_mm256_load_ps"));
assert!(content.contains("_mm256_store_ps"));
assert!(content.contains("_mm256_broadcast_ss"));
assert!(content.contains("_mm256_zeroupper"));
}
#[test]
fn test_generate_avx2intrin() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Avx2intrin);
assert!(content.contains("_mm256_add_epi32"));
assert!(content.contains("_mm256_mul_epi32"));
assert!(content.contains("_mm256_and_si256"));
assert!(content.contains("_mm256_cmpeq_epi64"));
assert!(content.contains("_mm256_i32gather_ps"));
assert!(content.contains("_mm256_abs_epi32"));
assert!(content.contains("_mm256_min_epi32"));
}
#[test]
fn test_generate_avx512fintrin() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Avx512fintrin);
assert!(content.contains("__AVX512FINTRIN_H"));
assert!(content.contains("__m512"));
assert!(content.contains("__m512d"));
assert!(content.contains("__mmask16"));
assert!(content.contains("_mm512_add_ps"));
assert!(content.contains("_mm512_mul_pd"));
assert!(content.contains("_mm512_load_ps"));
}
#[test]
fn test_generate_avx512bwintrin() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Avx512bwintrin);
assert!(content.contains("_mm512_add_epi8"));
assert!(content.contains("_mm512_sub_epi16"));
assert!(content.contains("_mm512_shuffle_epi8"));
}
#[test]
fn test_generate_fmaintrin() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Fmaintrin);
assert!(content.contains("_mm_fmadd_ps"));
assert!(content.contains("_mm_fmsub_pd"));
assert!(content.contains("_mm_fnmadd_ps"));
assert!(content.contains("_mm_fnmsub_pd"));
assert!(content.contains("_mm256_fmadd_ps"));
}
#[test]
fn test_generate_bmiintrin() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Bmiintrin);
assert!(content.contains("__andn_u32"));
assert!(content.contains("__blsi_u32"));
assert!(content.contains("__blsr_u32"));
assert!(content.contains("__blsmsk_u32"));
assert!(content.contains("__bextr_u32"));
if r#gen.config.pointer_width == 64 {
assert!(content.contains("__andn_u64"));
}
}
#[test]
fn test_generate_bmi2intrin() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Bmi2intrin);
assert!(content.contains("_pdep_u32"));
assert!(content.contains("_pext_u32"));
assert!(content.contains("_mulx_u32"));
assert!(content.contains("__bzhi_u32"));
}
#[test]
fn test_generate_lzcntintrin() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Lzcntintrin);
assert!(content.contains("__lzcnt16"));
assert!(content.contains("__lzcnt32"));
assert!(content.contains("__lzcnt64"));
}
#[test]
fn test_generate_cpuid() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Cpuid);
assert!(content.contains("__cpuid"));
assert!(content.contains("__cpuid_count"));
assert!(content.contains("__get_cpuid_max"));
assert!(content.contains("cpuid"));
assert!(content.contains("GenuineIntel"));
assert!(content.contains("__cpuid_vendor_intel"));
assert!(content.contains("__cpuid_vendor_amd"));
assert!(content.contains("__cpuid_feature_SSE"));
assert!(content.contains("__cpuid_feature_AVX"));
assert!(content.contains("__cpuid_feature_AVX512F"));
}
#[test]
fn test_provider_resolve_stddef() {
let mut provider = X86HeaderProvider::new_x86_64();
let content = provider.resolve("stddef.h");
assert!(content.is_some());
assert!(content.unwrap().contains("size_t"));
}
#[test]
fn test_provider_resolve_with_brackets() {
let mut provider = X86HeaderProvider::new_x86_64();
assert!(provider.resolve("<stddef.h>").is_some());
assert!(provider.resolve("\"stddef.h\"").is_some());
}
#[test]
fn test_provider_is_builtin_header() {
let provider = X86HeaderProvider::new_x86_64();
assert!(provider.is_builtin_header("stddef.h"));
assert!(provider.is_builtin_header("xmmintrin.h"));
assert!(provider.is_builtin_header("cpuid.h"));
assert!(!provider.is_builtin_header("nonexistent.h"));
assert!(!provider.is_builtin_header("stdio.h"));
}
#[test]
fn test_provider_is_available() {
let mut provider = X86HeaderProvider::new_x86_64();
assert!(provider.is_available("stddef.h"));
assert!(provider.is_available("xmmintrin.h"));
assert!(!provider.is_available("nonexistent.h"));
}
#[test]
fn test_provider_feature_gating_avx512_disabled() {
let mut provider = X86HeaderProvider::new_x86_64();
assert!(!provider.is_available("avx512fintrin.h"));
let result = provider.resolve("avx512fintrin.h");
assert!(result.is_none());
}
#[test]
fn test_provider_feature_gating_avx512_enabled() {
let mut provider = X86HeaderProvider::new(X86TargetConfig::new_x86_64_avx512());
assert!(provider.is_available("avx512fintrin.h"));
let result = provider.resolve("avx512fintrin.h");
assert!(result.is_some());
assert!(result.unwrap().contains("_mm512_add_ps"));
}
#[test]
fn test_provider_caching() {
let mut provider = X86HeaderProvider::new_x86_64();
assert_eq!(provider.cache_size(), 0);
provider.resolve("stddef.h");
assert_eq!(provider.cache_size(), 1);
provider.resolve("stddef.h");
assert_eq!(provider.cache_size(), 1);
provider.resolve("stdint.h");
assert_eq!(provider.cache_size(), 2);
}
#[test]
fn test_provider_clear_cache() {
let mut provider = X86HeaderProvider::new_x86_64();
provider.resolve("stddef.h");
provider.resolve("stdint.h");
assert_eq!(provider.cache_size(), 2);
provider.clear_cache();
assert_eq!(provider.cache_size(), 0);
}
#[test]
fn test_provider_prewarm_cache() {
let mut provider = X86HeaderProvider::new_x86_64();
provider.prewarm_cache();
assert!(provider.cache_size() > 20); assert!(provider.available_count() > 20);
}
#[test]
fn test_provider_available_count() {
let mut provider = X86HeaderProvider::new_x86_64();
provider.prewarm_cache();
let available = provider.available_count();
let total = provider.cache_size();
assert!(available <= total);
}
#[test]
fn test_provider_config_mut() {
let mut provider = X86HeaderProvider::new_x86_64();
assert!(!provider.config().has_avx512f);
provider.config_mut().has_avx512f = true;
assert!(provider.config().has_avx512f);
provider.clear_cache();
assert!(provider.is_available("avx512fintrin.h"));
}
#[test]
fn test_provider_32bit() {
let mut provider = X86HeaderProvider::new_x86_32();
let content = provider.resolve("stdint.h").unwrap();
assert!(content.contains("UINT32_MAX"));
assert!(!content.contains("__int128"));
}
#[test]
fn test_generate_all_includes_all_standard_headers() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let all = r#gen.generate_all();
assert!(all.contains_key("stddef.h"));
assert!(all.contains_key("stdint.h"));
assert!(all.contains_key("stdbool.h"));
assert!(all.contains_key("stdarg.h"));
assert!(all.contains_key("limits.h"));
assert!(all.contains_key("float.h"));
assert!(all.contains_key("iso646.h"));
assert!(all.contains_key("stdalign.h"));
assert!(all.contains_key("stdnoreturn.h"));
assert!(all.contains_key("stdatomic.h"));
assert!(all.contains_key("tgmath.h"));
assert!(all.contains_key("stdckdint.h"));
}
#[test]
fn test_generate_all_includes_x86_headers() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let all = r#gen.generate_all();
assert!(all.contains_key("x86intrin.h"));
assert!(all.contains_key("mmintrin.h"));
assert!(all.contains_key("xmmintrin.h"));
assert!(all.contains_key("emmintrin.h"));
assert!(all.contains_key("cpuid.h"));
}
#[test]
fn test_all_headers_count() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let all = r#gen.all_headers();
assert_eq!(all.len(), 33);
}
#[test]
fn test_empty_cache_lookup() {
let mut provider = X86HeaderProvider::new_x86_64();
assert!(provider.resolve("nonexistent.h").is_none());
assert_eq!(provider.cache_size(), 0);
}
#[test]
fn test_feature_disabled_headers_cached_as_none() {
let mut provider = X86HeaderProvider::new_x86_64();
let result = provider.resolve("avx512fintrin.h");
assert!(result.is_none());
assert_eq!(provider.cache_size(), 1);
let result2 = provider.resolve("avx512fintrin.h");
assert!(result2.is_none());
}
#[test]
fn test_generate_stddef_contains_nullptr_c23() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Stddef);
assert!(content.contains("nullptr"));
assert!(content.contains("nullptr_t"));
}
#[test]
fn test_generate_float_eval_method_for_sse() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Float);
assert!(content.contains("__SSE_MATH__"));
assert!(content.contains("FLT_EVAL_METHOD"));
}
#[test]
fn test_mmintrin_all_functions() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Mmintrin);
assert!(content.contains("_mm_set_pi8"));
assert!(content.contains("_mm_set_pi16"));
assert!(content.contains("_mm_cvtsi32_si64"));
assert!(content.contains("_mm_cvtsi64_si32"));
assert!(content.contains("_mm_add_pi8"));
assert!(content.contains("_mm_sub_pi16"));
assert!(content.contains("_mm_mullo_pi16"));
assert!(content.contains("_mm_madd_pi16"));
assert!(content.contains("_mm_sll_pi16"));
assert!(content.contains("_mm_srl_pi32"));
assert!(content.contains("_mm_sra_pi16"));
assert!(content.contains("_mm_and_si64"));
assert!(content.contains("_mm_or_si64"));
assert!(content.contains("_mm_xor_si64"));
assert!(content.contains("_mm_cmpeq_pi8"));
assert!(content.contains("_mm_cmpeq_pi16"));
assert!(content.contains("_mm_cmpeq_pi32"));
assert!(content.contains("_mm_packs_pi16"));
assert!(content.contains("_mm_packs_pi32"));
assert!(content.contains("_mm_unpackhi_pi8"));
assert!(content.contains("_mm_unpacklo_pi8"));
assert!(content.contains("_mm_empty"));
}
#[test]
fn test_xmmintrin_full_coverage() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Xmmintrin);
assert!(content.contains("_mm_set_ps"));
assert!(content.contains("_mm_set1_ps"));
assert!(content.contains("_mm_set_ss"));
assert!(content.contains("_mm_load_ps"));
assert!(content.contains("_mm_loadu_ps"));
assert!(content.contains("_mm_load_ss"));
assert!(content.contains("_mm_store_ps"));
assert!(content.contains("_mm_storeu_ps"));
assert!(content.contains("_mm_store_ss"));
assert!(content.contains("_mm_load1_ps"));
assert!(content.contains("_mm_add_ss"));
assert!(content.contains("_mm_sub_ps"));
assert!(content.contains("_mm_sub_ss"));
assert!(content.contains("_mm_mul_ss"));
assert!(content.contains("_mm_div_ss"));
assert!(content.contains("_mm_sqrt_ss"));
assert!(content.contains("_mm_rcp_ps"));
assert!(content.contains("_mm_rcp_ss"));
assert!(content.contains("_mm_rsqrt_ps"));
assert!(content.contains("_mm_rsqrt_ss"));
assert!(content.contains("_mm_min_ss"));
assert!(content.contains("_mm_max_ss"));
assert!(content.contains("_mm_cmplt_ps"));
assert!(content.contains("_mm_cmple_ps"));
assert!(content.contains("_mm_cmpgt_ps"));
assert!(content.contains("_mm_cmpge_ps"));
assert!(content.contains("_mm_cmpneq_ps"));
assert!(content.contains("_mm_and_ps"));
assert!(content.contains("_mm_or_ps"));
assert!(content.contains("_mm_xor_ps"));
assert!(content.contains("_mm_andnot_ps"));
assert!(content.contains("_mm_unpackhi_ps"));
assert!(content.contains("_mm_unpacklo_ps"));
assert!(content.contains("_mm_movehl_ps"));
assert!(content.contains("_mm_movelh_ps"));
assert!(content.contains("_mm_cvtss_si32"));
assert!(content.contains("_mm_cvtsi32_ss"));
assert!(content.contains("_mm_movemask_ps"));
assert!(content.contains("_mm_sfence"));
assert!(content.contains("_MM_HINT_NTA"));
assert!(content.contains("_MM_HINT_ET1"));
}
#[test]
fn test_emmintrin_integer_ops() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Emmintrin);
assert!(content.contains("_mm_add_epi8"));
assert!(content.contains("_mm_add_epi16"));
assert!(content.contains("_mm_add_epi32"));
assert!(content.contains("_mm_add_epi64"));
assert!(content.contains("_mm_sub_epi8"));
assert!(content.contains("_mm_sub_epi16"));
assert!(content.contains("_mm_sub_epi32"));
assert!(content.contains("_mm_sub_epi64"));
assert!(content.contains("_mm_madd_epi16"));
assert!(content.contains("_mm_mul_epu32"));
assert!(content.contains("_mm_slli_epi16"));
assert!(content.contains("_mm_slli_epi32"));
assert!(content.contains("_mm_slli_epi64"));
assert!(content.contains("_mm_srli_epi16"));
assert!(content.contains("_mm_srli_epi32"));
assert!(content.contains("_mm_srli_epi64"));
assert!(content.contains("_mm_srai_epi16"));
assert!(content.contains("_mm_srai_epi32"));
assert!(content.contains("_mm_cmpeq_epi8"));
assert!(content.contains("_mm_cmpeq_epi16"));
assert!(content.contains("_mm_cmpeq_epi32"));
assert!(content.contains("_mm_cmpgt_epi8"));
assert!(content.contains("_mm_cmpgt_epi16"));
assert!(content.contains("_mm_cmpgt_epi32"));
assert!(content.contains("_mm_cmplt_epi8"));
assert!(content.contains("_mm_unpackhi_epi8"));
assert!(content.contains("_mm_unpacklo_epi8"));
assert!(content.contains("_mm_unpackhi_epi16"));
assert!(content.contains("_mm_unpacklo_epi16"));
assert!(content.contains("_mm_unpackhi_epi32"));
assert!(content.contains("_mm_unpacklo_epi32"));
assert!(content.contains("_mm_cvtps_pd"));
assert!(content.contains("_mm_cvtpd_ps"));
assert!(content.contains("_mm_cvtsd_si32"));
assert!(content.contains("_mm_cvtsi32_sd"));
assert!(content.contains("_mm_movemask_pd"));
assert!(content.contains("_mm_move_epi64"));
}
#[test]
fn test_nmmintrin_crc32_all_widths() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Nmmintrin);
assert!(content.contains("_mm_crc32_u8"));
assert!(content.contains("_mm_crc32_u16"));
assert!(content.contains("_mm_crc32_u32"));
assert!(content.contains("_mm_crc32_u64"));
}
#[test]
fn test_wmmintrin_aes_all_operations() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Wmmintrin);
assert!(content.contains("_mm_aesenc_si128"));
assert!(content.contains("_mm_aesenclast_si128"));
assert!(content.contains("_mm_aesdec_si128"));
assert!(content.contains("_mm_aesdeclast_si128"));
assert!(content.contains("_mm_aesimc_si128"));
assert!(content.contains("_mm_aeskeygenassist_si128"));
}
#[test]
fn test_fmaintrin_all_variants() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Fmaintrin);
assert!(content.contains("_mm_fmadd_ps"));
assert!(content.contains("_mm_fmadd_pd"));
assert!(content.contains("_mm_fmsub_ps"));
assert!(content.contains("_mm_fmsub_pd"));
assert!(content.contains("_mm_fnmadd_ps"));
assert!(content.contains("_mm_fnmadd_pd"));
assert!(content.contains("_mm_fnmsub_ps"));
assert!(content.contains("_mm_fnmsub_pd"));
assert!(content.contains("_mm_fmadd_ss"));
assert!(content.contains("_mm_fmadd_sd"));
assert!(content.contains("_mm256_fmadd_ps"));
assert!(content.contains("_mm256_fmadd_pd"));
}
#[test]
fn test_bmiintrin_all_32bit() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Bmiintrin);
assert!(content.contains("__andn_u32"));
assert!(content.contains("__bextr_u32"));
assert!(content.contains("__blsi_u32"));
assert!(content.contains("__blsmsk_u32"));
assert!(content.contains("__blsr_u32"));
}
#[test]
fn test_bmi2intrin_all_32bit() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Bmi2intrin);
assert!(content.contains("__bzhi_u32"));
assert!(content.contains("_pdep_u32"));
assert!(content.contains("_pext_u32"));
assert!(content.contains("_mulx_u32"));
}
#[test]
fn test_feature_matrix_all_combinations() {
let combos = vec![
("baseline_x86_64", X86TargetConfig::new_x86_64_linux()),
("avx512_full", X86TargetConfig::new_x86_64_avx512()),
("x86_32", X86TargetConfig::new_x86_32_linux()),
];
for (name, cfg) in &combos {
let provider = X86HeaderProvider::new(cfg.clone());
assert!(
provider.is_builtin_header("stddef.h"),
"{}: stddef missing",
name
);
assert!(
provider.is_builtin_header("limits.h"),
"{}: limits missing",
name
);
assert!(
provider.is_builtin_header("cpuid.h"),
"{}: cpuid missing",
name
);
}
}
#[test]
fn test_feature_introspection() {
let cfg = X86TargetConfig::new_x86_64_linux();
assert!(cfg.has_sse);
assert!(cfg.has_sse2);
assert!(cfg.has_sse3);
assert!(cfg.has_ssse3);
assert!(cfg.has_sse4_1);
assert!(cfg.has_sse4_2);
assert!(cfg.has_aes);
assert!(cfg.has_avx);
assert!(cfg.has_avx2);
assert!(cfg.has_fma);
assert!(cfg.has_bmi);
assert!(cfg.has_bmi2);
assert!(cfg.has_lzcnt);
assert!(cfg.has_mmx);
assert!(!cfg.has_avx512f);
assert!(!cfg.has_avx512bw);
assert!(!cfg.has_avx512dq);
assert!(!cfg.has_avx512vl);
}
#[test]
fn test_x86intrin_includes_correct_order() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::X86Intrin);
let cpuid_pos = content.find("cpuid.h").unwrap();
let mmintrin_pos = content.find("mmintrin.h").unwrap();
assert!(cpuid_pos < mmintrin_pos, "cpuid.h must precede mmintrin.h");
let xmm_pos = content.find("xmmintrin.h").unwrap();
assert!(
mmintrin_pos < xmm_pos,
"mmintrin.h must precede xmmintrin.h"
);
let emm_pos = content.find("emmintrin.h").unwrap();
assert!(xmm_pos < emm_pos, "xmmintrin.h must precede emmintrin.h");
}
#[test]
fn test_simd_header_includes_in_chain() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let sse2 = r#gen.generate(X86BuiltinHeader::Emmintrin);
assert!(
sse2.contains("xmmintrin.h"),
"emmintrin.h must include xmmintrin.h"
);
let sse3 = r#gen.generate(X86BuiltinHeader::Pmmintrin);
assert!(
sse3.contains("emmintrin.h"),
"pmmintrin.h must include emmintrin.h"
);
let ssse3 = r#gen.generate(X86BuiltinHeader::Tmmintrin);
assert!(
ssse3.contains("pmmintrin.h"),
"tmmintrin.h must include pmmintrin.h"
);
let sse41 = r#gen.generate(X86BuiltinHeader::Smmintrin);
assert!(
sse41.contains("tmmintrin.h"),
"smmintrin.h must include tmmintrin.h"
);
let sse42 = r#gen.generate(X86BuiltinHeader::Nmmintrin);
assert!(
sse42.contains("smmintrin.h"),
"nmmintrin.h must include smmintrin.h"
);
let avx2 = r#gen.generate(X86BuiltinHeader::Avx2intrin);
assert!(
avx2.contains("avxintrin.h"),
"avx2intrin.h must include avxintrin.h"
);
}
#[test]
fn test_all_headers_have_include_guards() {
let r#gen = X86BuiltinHeaders::new_x86_64();
for header in r#gen.all_headers() {
let content = r#gen.generate(header);
let name = header.filename();
assert!(
content.contains("#ifndef"),
"{} missing #ifndef guard",
name
);
assert!(
content.contains("#define"),
"{} missing #define guard",
name
);
assert!(content.contains("#endif"), "{} missing #endif guard", name);
}
}
#[test]
fn test_standard_headers_are_ascii() {
let r#gen = X86BuiltinHeaders::new_x86_64();
for header in r#gen.all_headers() {
if header.is_standard_c() {
let content = r#gen.generate(header);
assert!(
content.is_ascii(),
"{} contains non-ASCII characters",
header.filename()
);
}
}
}
#[test]
fn test_headers_end_with_newline() {
let r#gen = X86BuiltinHeaders::new_x86_64();
for header in r#gen.all_headers() {
let content = r#gen.generate(header);
assert!(
content.ends_with('\n'),
"{} does not end with newline",
header.filename()
);
}
}
#[test]
fn test_no_empty_headers() {
let r#gen = X86BuiltinHeaders::new_x86_64();
for header in r#gen.all_headers() {
let content = r#gen.generate(header);
assert!(!content.trim().is_empty(), "{} is empty", header.filename());
}
}
#[test]
fn test_header_content_is_deterministic() {
let r#gen = X86BuiltinHeaders::new_x86_64();
for header in r#gen.all_headers() {
let a = r#gen.generate(header);
let b = r#gen.generate(header);
assert_eq!(
a,
b,
"{} produces non-deterministic output",
header.filename()
);
}
}
#[test]
fn test_stddef_size_t_width_matches_pointer_width() {
let gen64 = X86BuiltinHeaders::new_x86_64();
let c64 = gen64.generate(X86BuiltinHeader::Stddef);
assert!(c64.contains("__SIZE_TYPE__"));
let gen32 = X86BuiltinHeaders::new_x86_32();
let c32 = gen32.generate(X86BuiltinHeader::Stddef);
assert!(c32.contains("__SIZE_TYPE__"));
}
#[test]
fn test_limits_long_width_matches_lp64() {
let gen64 = X86BuiltinHeaders::new_x86_64();
let c64 = gen64.generate(X86BuiltinHeader::Limits);
assert!(c64.contains("9223372036854775807L"));
assert!(c64.contains("18446744073709551615UL"));
let gen32 = X86BuiltinHeaders::new_x86_32();
let c32 = gen32.generate(X86BuiltinHeader::Limits);
assert!(c32.contains("2147483647L"));
}
#[test]
fn test_float_ldbl_mant_dig_is_64_for_x86() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Float);
assert!(content.contains("LDBL_MANT_DIG 64"));
assert!(content.contains("LDBL_DIG 18"));
}
#[test]
fn test_stdint_int64_uses_long_on_lp64() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Stdint);
let int64_line = content
.lines()
.find(|l| l.contains("int64_t") && l.contains("typedef"))
.unwrap();
assert!(
int64_line.contains("long"),
"int64_t should use 'long' on LP64: {}",
int64_line
);
}
#[test]
fn test_atomic_types_complete() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Stdatomic);
let required_types = [
"atomic_bool",
"atomic_char",
"atomic_schar",
"atomic_uchar",
"atomic_short",
"atomic_ushort",
"atomic_int",
"atomic_uint",
"atomic_long",
"atomic_ulong",
"atomic_llong",
"atomic_ullong",
"atomic_intptr_t",
"atomic_uintptr_t",
"atomic_size_t",
"atomic_ptrdiff_t",
"atomic_intmax_t",
"atomic_uintmax_t",
];
for t in &required_types {
assert!(content.contains(t), "Missing atomic type: {}", t);
}
}
#[test]
fn test_atomic_operations_complete() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Stdatomic);
let required_ops = [
"atomic_init",
"atomic_load",
"atomic_load_explicit",
"atomic_store",
"atomic_store_explicit",
"atomic_exchange",
"atomic_exchange_explicit",
"atomic_compare_exchange_strong",
"atomic_compare_exchange_strong_explicit",
"atomic_compare_exchange_weak",
"atomic_compare_exchange_weak_explicit",
"atomic_fetch_add",
"atomic_fetch_add_explicit",
"atomic_fetch_sub",
"atomic_fetch_sub_explicit",
"atomic_fetch_or",
"atomic_fetch_or_explicit",
"atomic_fetch_xor",
"atomic_fetch_xor_explicit",
"atomic_fetch_and",
"atomic_fetch_and_explicit",
"atomic_thread_fence",
"atomic_signal_fence",
"atomic_flag_test_and_set",
"atomic_flag_clear",
"kill_dependency",
];
for op in &required_ops {
assert!(content.contains(op), "Missing atomic operation: {}", op);
}
}
#[test]
fn test_tgmath_all_required_functions() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Tgmath);
let required = [
"acos",
"asin",
"atan",
"atan2",
"cos",
"sin",
"tan",
"acosh",
"asinh",
"atanh",
"cosh",
"sinh",
"tanh",
"exp",
"exp2",
"expm1",
"frexp",
"ldexp",
"log",
"log10",
"log1p",
"log2",
"logb",
"modf",
"scalbn",
"scalbln",
"cbrt",
"fabs",
"hypot",
"pow",
"sqrt",
"erf",
"erfc",
"lgamma",
"tgamma",
"ceil",
"floor",
"nearbyint",
"rint",
"lrint",
"llrint",
"round",
"lround",
"llround",
"trunc",
"fmod",
"remainder",
"remquo",
"copysign",
"nan",
"nextafter",
"nexttoward",
"fdim",
"fmax",
"fmin",
"fma",
];
for f in &required {
assert!(content.contains(f), "tgmath.h missing function: {}", f);
}
}
#[test]
fn test_provider_resolve_all_standard_headers() {
let mut provider = X86HeaderProvider::new_x86_64();
let headers = [
"stddef.h",
"stdint.h",
"stdbool.h",
"stdarg.h",
"limits.h",
"float.h",
"iso646.h",
"stdalign.h",
"stdnoreturn.h",
"stdatomic.h",
"tgmath.h",
"stdckdint.h",
];
for h in &headers {
assert!(provider.resolve(h).is_some(), "Failed to resolve: {}", h);
}
}
#[test]
fn test_provider_resolve_all_available_intrinsic_headers() {
let mut provider = X86HeaderProvider::new_x86_64();
let headers = [
"x86intrin.h",
"mmintrin.h",
"xmmintrin.h",
"emmintrin.h",
"pmmintrin.h",
"tmmintrin.h",
"smmintrin.h",
"nmmintrin.h",
"wmmintrin.h",
"immintrin.h",
"avxintrin.h",
"avx2intrin.h",
"fmaintrin.h",
"bmiintrin.h",
"bmi2intrin.h",
"lzcntintrin.h",
"cpuid.h",
];
for h in &headers {
let result = provider.resolve(h);
assert!(
result.is_some(),
"Failed to resolve intrinsic header: {}",
h
);
}
}
#[test]
fn test_large_scale_generation() {
let r#gen = X86BuiltinHeaders::new_x86_64();
for _ in 0..10 {
let all = r#gen.generate_all();
assert!(!all.is_empty());
}
}
#[test]
fn test_cache_integrity_after_clear() {
let mut provider = X86HeaderProvider::new_x86_64();
provider.prewarm_cache();
let before = provider.cache_size();
assert!(before > 0);
provider.clear_cache();
assert_eq!(provider.cache_size(), 0);
assert!(provider.resolve("stddef.h").is_some());
assert_eq!(provider.cache_size(), 1);
}
#[test]
fn test_config_change_and_cache_invalidation() {
let mut provider = X86HeaderProvider::new_x86_64();
assert!(!provider.is_available("avx512fintrin.h"));
provider.resolve("avx512fintrin.h");
provider.config_mut().has_avx512f = true;
provider.clear_cache();
assert!(provider.is_available("avx512fintrin.h"));
let content = provider.resolve("avx512fintrin.h").unwrap();
assert!(content.contains("_mm512_add_ps"));
}
#[test]
fn test_cpuid_header_contains_feature_bit_positions() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Cpuid);
assert!(content.contains("__cpuid_feature_SSE"));
assert!(content.contains("__cpuid_feature_SSE2"));
assert!(content.contains("__cpuid_feature_SSE3"));
assert!(content.contains("__cpuid_feature_SSSE3"));
assert!(content.contains("__cpuid_feature_SSE4_1"));
assert!(content.contains("__cpuid_feature_SSE4_2"));
assert!(content.contains("__cpuid_feature_AES"));
assert!(content.contains("__cpuid_feature_AVX"));
assert!(content.contains("__cpuid_feature_FMA"));
assert!(content.contains("__cpuid_feature_AVX2"));
assert!(content.contains("__cpuid_feature_BMI"));
assert!(content.contains("__cpuid_feature_BMI2"));
assert!(content.contains("__cpuid_feature_LZCNT"));
assert!(content.contains("__cpuid_feature_AVX512F"));
assert!(content.contains("__cpuid_feature_AVX512BW"));
assert!(content.contains("__cpuid_feature_AVX512DQ"));
assert!(content.contains("__cpuid_feature_AVX512VL"));
}
#[test]
fn test_cpuid_inline_assembly_syntax() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Cpuid);
assert!(content.contains("\"cpuid\""));
assert!(content.contains("\"=a\""));
assert!(content.contains("\"=b\""));
assert!(content.contains("\"=c\""));
assert!(content.contains("\"=d\""));
}
#[test]
fn test_generate_all_memory_bounded() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let all = r#gen.generate_all();
let total_bytes: usize = all.values().map(|s| s.len()).sum();
assert!(
total_bytes < 2_000_000,
"Total header size too large: {}",
total_bytes
);
assert!(
total_bytes > 10_000,
"Total header size too small: {}",
total_bytes
);
}
#[test]
fn test_individual_header_sizes() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let xmm = r#gen.generate(X86BuiltinHeader::Xmmintrin);
assert!(
xmm.len() > 2000,
"xmmintrin.h too small: {} bytes",
xmm.len()
);
let emm = r#gen.generate(X86BuiltinHeader::Emmintrin);
assert!(
emm.len() > 3000,
"emmintrin.h too small: {} bytes",
emm.len()
);
let avx = r#gen.generate(X86BuiltinHeader::Avxintrin);
assert!(
avx.len() > 2000,
"avxintrin.h too small: {} bytes",
avx.len()
);
let stddef = r#gen.generate(X86BuiltinHeader::Stddef);
assert!(
stddef.len() > 500,
"stddef.h too small: {} bytes",
stddef.len()
);
let stdatomic = r#gen.generate(X86BuiltinHeader::Stdatomic);
assert!(
stdatomic.len() > 2000,
"stdatomic.h too small: {} bytes",
stdatomic.len()
);
}
#[test]
fn test_provider_default_constructor() {
let provider = X86HeaderProvider::default();
assert_eq!(provider.config().pointer_width, 64);
assert!(provider.config().has_sse2);
}
#[test]
fn test_provider_config_accessors() {
let mut provider = X86HeaderProvider::new_x86_64();
assert_eq!(provider.config().pointer_width, 64);
provider.config_mut().pointer_width = 32;
assert_eq!(provider.config().pointer_width, 32);
}
#[test]
fn test_header_name_normalization() {
let mut provider = X86HeaderProvider::new_x86_64();
let a = provider.resolve("stddef.h").unwrap();
let b = provider.resolve("<stddef.h>").unwrap();
let c = provider.resolve("\"stddef.h\"").unwrap();
assert_eq!(a, b);
assert_eq!(b, c);
}
#[test]
fn test_generate_all_keys_match_filenames() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let all = r#gen.generate_all();
for header in r#gen.all_headers() {
assert!(
all.contains_key(header.filename()),
"generate_all missing: {}",
header.filename()
);
}
}
#[test]
fn test_provider_resolve_and_is_available_consistency() {
let mut provider = X86HeaderProvider::new_x86_64();
let all = provider.generator.all_headers();
for header in &all {
let name = header.filename();
let resolved = provider.resolve(name);
let available = provider.is_available(name);
assert_eq!(
resolved.is_some(),
available,
"Inconsistent resolve/available for: {}",
name
);
}
}
#[test]
fn test_generation_speed_estimate() {
use std::time::Instant;
let r#gen = X86BuiltinHeaders::new_x86_64();
let start = Instant::now();
let all = r#gen.generate_all();
let elapsed = start.elapsed();
assert!(
elapsed.as_millis() < 1000,
"Header generation too slow: {}ms",
elapsed.as_millis()
);
assert_eq!(all.len(), 33);
}
#[test]
fn test_provider_prewarm_speed() {
use std::time::Instant;
let mut provider = X86HeaderProvider::new_x86_64();
let start = Instant::now();
provider.prewarm_cache();
let elapsed = start.elapsed();
assert!(
elapsed.as_millis() < 2000,
"Prewarm too slow: {}ms",
elapsed.as_millis()
);
assert!(provider.cache_size() > 0);
}
#[test]
fn test_provider_handles_empty_string() {
let mut provider = X86HeaderProvider::new_x86_64();
assert!(provider.resolve("").is_none());
}
#[test]
fn test_provider_handles_whitespace_only() {
let mut provider = X86HeaderProvider::new_x86_64();
assert!(provider.resolve(" ").is_none());
}
#[test]
fn test_provider_handles_only_brackets() {
let mut provider = X86HeaderProvider::new_x86_64();
assert!(provider.resolve("<>").is_none());
assert!(provider.resolve("\"\"").is_none());
}
#[test]
fn test_provider_case_sensitivity() {
let mut provider = X86HeaderProvider::new_x86_64();
assert!(provider.is_builtin_header("stddef.h"));
assert!(!provider.is_builtin_header("STDDEF.H"));
assert!(!provider.is_builtin_header("StdDef.h"));
}
#[test]
fn test_all_header_filenames_are_lowercase() {
let r#gen = X86BuiltinHeaders::new_x86_64();
for header in r#gen.all_headers() {
let name = header.filename();
assert_eq!(
name,
name.to_lowercase(),
"Header filename not lowercase: {}",
name
);
}
}
#[test]
fn test_all_header_filenames_have_h_extension() {
let r#gen = X86BuiltinHeaders::new_x86_64();
for header in r#gen.all_headers() {
let name = header.filename();
assert!(
name.ends_with(".h"),
"Header filename missing .h extension: {}",
name
);
}
}
#[test]
fn test_sse_comparison_constants_defined() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Xmmintrin);
assert!(content.contains("_CMP_EQ_OQ"));
assert!(content.contains("_CMP_LT_OS"));
assert!(content.contains("_CMP_LE_OS"));
assert!(content.contains("_CMP_UNORD_Q"));
assert!(content.contains("_CMP_NEQ_UQ"));
assert!(content.contains("_CMP_NLT_US"));
assert!(content.contains("_CMP_NLE_US"));
assert!(content.contains("_CMP_ORD_Q"));
}
#[test]
fn test_sse4_1_rounding_constants() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Smmintrin);
assert!(content.contains("_MM_FROUND_TO_NEAREST_INT"));
assert!(content.contains("_MM_FROUND_TO_NEG_INF"));
assert!(content.contains("_MM_FROUND_TO_POS_INF"));
assert!(content.contains("_MM_FROUND_TO_ZERO"));
assert!(content.contains("_MM_FROUND_CUR_DIRECTION"));
assert!(content.contains("_MM_FROUND_NO_EXC"));
}
#[test]
fn test_avx512vl_includes_chain() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Avx512vlintrin);
assert!(content.contains("avx512fintrin.h"));
}
#[test]
fn test_avx512bw_includes_chain() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Avx512bwintrin);
assert!(content.contains("avx512fintrin.h"));
}
#[test]
fn test_immintrin_umbrella_includes_avx_conditionally() {
let mut cfg = X86TargetConfig::new_x86_64_linux();
cfg.has_avx = false;
cfg.has_avx2 = false;
let r#gen = X86BuiltinHeaders::new(cfg);
let content = r#gen.generate(X86BuiltinHeader::Immintrin);
assert!(content.contains("mmintrin.h"));
assert!(content.contains("xmmintrin.h"));
assert!(!content.contains("avxintrin.h"));
assert!(!content.contains("avx2intrin.h"));
}
#[test]
fn test_generate_stdarg_has_legacy_synonym() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Stdarg);
assert!(content.contains("__va_copy"));
}
#[test]
fn test_generate_unreachable_in_stddef() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Stddef);
assert!(content.contains("__builtin_unreachable"));
}
#[test]
fn test_lzcntintrin_has_16_32_64() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Lzcntintrin);
assert!(content.contains("__lzcnt16"));
assert!(content.contains("__lzcnt32"));
assert!(content.contains("__lzcnt64"));
}
#[test]
fn test_nmmintrin_crc64_only_on_64bit() {
let gen64 = X86BuiltinHeaders::new_x86_64();
let c64 = gen64.generate(X86BuiltinHeader::Nmmintrin);
assert!(c64.contains("_mm_crc32_u64"));
let gen32 = X86BuiltinHeaders::new_x86_32();
let c32 = gen32.generate(X86BuiltinHeader::Nmmintrin);
assert!(!c32.contains("_mm_crc32_u64"));
}
#[test]
fn test_bmiintrin_64bit_only_on_64bit() {
let gen64 = X86BuiltinHeaders::new_x86_64();
let c64 = gen64.generate(X86BuiltinHeader::Bmiintrin);
assert!(c64.contains("__andn_u64"));
let gen32 = X86BuiltinHeaders::new_x86_32();
let c32 = gen32.generate(X86BuiltinHeader::Bmiintrin);
assert!(!c32.contains("__andn_u64"));
}
#[test]
fn test_bmi2intrin_pdep_pext_64bit_only_on_64bit() {
let gen64 = X86BuiltinHeaders::new_x86_64();
let c64 = gen64.generate(X86BuiltinHeader::Bmi2intrin);
assert!(c64.contains("_pdep_u64"));
let gen32 = X86BuiltinHeaders::new_x86_32();
let c32 = gen32.generate(X86BuiltinHeader::Bmi2intrin);
assert!(!c32.contains("_pdep_u64"));
}
#[test]
fn test_avx512f_has_mask_types() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Avx512fintrin);
assert!(content.contains("__mmask8"));
assert!(content.contains("__mmask16"));
assert!(content.contains("__mmask32"));
assert!(content.contains("__mmask64"));
}
#[test]
fn test_avx512f_has_512bit_types() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Avx512fintrin);
assert!(content.contains("__m512"));
assert!(content.contains("__m512d"));
assert!(content.contains("__m512i"));
}
#[test]
fn test_avx512bw_has_byte_word_ops() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Avx512bwintrin);
assert!(content.contains("_mm512_add_epi8"));
assert!(content.contains("_mm512_add_epi16"));
assert!(content.contains("_mm512_cmpeq_epi8_mask"));
assert!(content.contains("_mm512_cmpeq_epi16_mask"));
}
#[test]
fn test_avx512vl_has_128_256_mask_variants() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Avx512vlintrin);
assert!(content.contains("_mm256_mask_add_ps"));
assert!(content.contains("_mm_mask_add_ps"));
}
#[test]
fn test_header_debug_trait() {
let h = X86BuiltinHeader::Stddef;
let _ = format!("{:?}", h);
let _ = format!("{:?}", X86TargetConfig::default());
let _ = format!("{:?}", X86BuiltinHeaders::new_x86_64());
let _ = format!("{:?}", X86HeaderProvider::default());
}
#[test]
fn test_header_clone_trait() {
let h = X86BuiltinHeader::Stddef;
let h2 = h;
assert_eq!(h, h2);
let cfg = X86TargetConfig::default();
let cfg2 = cfg.clone();
assert_eq!(cfg.pointer_width, cfg2.pointer_width);
let r#gen = X86BuiltinHeaders::new_x86_64();
let gen2 = r#gen.clone();
let c1 = r#gen.generate(X86BuiltinHeader::Stddef);
let c2 = gen2.generate(X86BuiltinHeader::Stddef);
assert_eq!(c1, c2);
}
#[test]
fn test_header_content_does_not_contain_preprocessor_errors() {
let r#gen = X86BuiltinHeaders::new_x86_64();
for header in r#gen.all_headers() {
let content = r#gen.generate(header);
let ifdefs = content.matches("#ifndef").count();
let defines = content.matches("#define ").count();
let endifs = content.matches("#endif").count();
assert!(ifdefs >= 1, "{}: missing #ifndef", header.filename());
assert!(endifs >= 1, "{}: missing #endif", header.filename());
assert!(defines >= 1, "{}: no #define", header.filename());
}
}
#[test]
fn test_all_headers_contain_comment_header() {
let r#gen = X86BuiltinHeaders::new_x86_64();
for header in r#gen.all_headers() {
let content = r#gen.generate(header);
let name = header.filename();
assert!(
content.contains("==="),
"{} missing header comment banner",
name
);
assert!(
content.contains(name),
"{} header comment doesn't mention its own name",
name
);
}
}
#[test]
fn test_header_size_distribution() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let mut sizes: Vec<(&str, usize)> = r#gen
.all_headers()
.iter()
.map(|h| (h.filename(), r#gen.generate(*h).len()))
.collect();
sizes.sort_by_key(|(_, s)| *s);
let smallest = sizes.first().unwrap();
assert!(
smallest.1 > 100,
"{} is suspiciously small: {} bytes",
smallest.0,
smallest.1
);
let largest = sizes.last().unwrap();
assert!(
largest.1 > 1000,
"{} is suspiciously small for being the largest: {} bytes",
largest.0,
largest.1
);
}
#[test]
fn test_x86_feature_names() {
assert_eq!(X86Feature::Sse.name(), "SSE");
assert_eq!(X86Feature::Avx2.name(), "AVX2");
assert_eq!(X86Feature::Avx512f.name(), "AVX-512F");
assert_eq!(X86Feature::Fma.name(), "FMA");
assert_eq!(X86Feature::Bmi.name(), "BMI");
assert_eq!(X86Feature::Lzcnt.name(), "LZCNT");
}
#[test]
fn test_x86_feature_headers() {
assert_eq!(X86Feature::Sse.header(), Some(X86BuiltinHeader::Xmmintrin));
assert_eq!(X86Feature::Sse2.header(), Some(X86BuiltinHeader::Emmintrin));
assert_eq!(X86Feature::Avx.header(), Some(X86BuiltinHeader::Avxintrin));
assert_eq!(
X86Feature::Avx2.header(),
Some(X86BuiltinHeader::Avx2intrin)
);
assert_eq!(
X86Feature::Avx512f.header(),
Some(X86BuiltinHeader::Avx512fintrin)
);
}
#[test]
fn test_x86_feature_prerequisites() {
assert!(X86Feature::Sse2.prerequisites().contains(&X86Feature::Sse));
assert!(X86Feature::Avx.prerequisites().contains(&X86Feature::Sse42));
assert!(X86Feature::Avx2.prerequisites().contains(&X86Feature::Avx));
assert!(X86Feature::Avx512f
.prerequisites()
.contains(&X86Feature::Avx2));
assert!(X86Feature::Bmi.prerequisites().is_empty());
assert!(X86Feature::Lzcnt.prerequisites().is_empty());
}
#[test]
fn test_x86_feature_all_count() {
assert_eq!(X86Feature::all().len(), 18);
}
#[test]
fn test_target_config_has_feature() {
let cfg = X86TargetConfig::new_x86_64_linux();
assert!(cfg.has_feature(X86Feature::Sse));
assert!(cfg.has_feature(X86Feature::Sse2));
assert!(cfg.has_feature(X86Feature::Avx));
assert!(cfg.has_feature(X86Feature::Avx2));
assert!(!cfg.has_feature(X86Feature::Avx512f));
assert!(!cfg.has_feature(X86Feature::Avx512bw));
}
#[test]
fn test_target_config_enable_feature() {
let mut cfg = X86TargetConfig::new_x86_64_linux();
assert!(!cfg.has_feature(X86Feature::Avx512f));
cfg.enable_feature(X86Feature::Avx512f);
assert!(cfg.has_feature(X86Feature::Avx512f));
assert!(cfg.has_feature(X86Feature::Avx2));
assert!(cfg.has_feature(X86Feature::Avx));
assert!(cfg.has_feature(X86Feature::Sse42));
}
#[test]
fn test_target_config_enabled_features() {
let cfg = X86TargetConfig::new_x86_64_linux();
let features = cfg.enabled_features();
assert!(features.contains(&X86Feature::Mmx));
assert!(features.contains(&X86Feature::Sse));
assert!(features.contains(&X86Feature::Sse2));
assert!(features.contains(&X86Feature::Avx));
assert!(features.contains(&X86Feature::Avx2));
assert!(!features.contains(&X86Feature::Avx512f));
}
#[test]
fn test_target_config_minimal() {
let cfg = X86TargetConfig::new_minimal_x86_64();
assert_eq!(cfg.pointer_width, 64);
assert!(cfg.enabled_features().is_empty());
assert!(!cfg.has_mmx);
assert!(!cfg.has_sse);
assert!(!cfg.has_sse2);
}
#[test]
fn test_validator_valid_header_passes() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Stddef);
let mut v = HeaderContentValidator::new();
v.validate_content(X86BuiltinHeader::Stddef, &content);
assert!(v.is_valid());
assert_eq!(v.errors.len(), 0);
}
#[test]
fn test_validator_all_standard_headers_pass() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let failures = HeaderContentValidator::validate_all(&r#gen);
for (header, errors) in &failures {
eprintln!("Validator failure in {}: {:?}", header.filename(), errors);
}
for (header, _) in &failures {
assert!(
!header.is_standard_c(),
"Standard header {} failed validation",
header.filename()
);
}
}
#[test]
fn test_validator_empty_content_fails() {
let mut v = HeaderContentValidator::new();
v.validate_content(X86BuiltinHeader::Stddef, "");
assert!(!v.is_valid());
}
#[test]
fn test_validator_default() {
let v = HeaderContentValidator::default();
assert!(v.errors.is_empty());
assert!(v.warnings.is_empty());
assert_eq!(v.issue_count(), 0);
}
#[test]
fn test_mmx_extended_saturated_ops() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate_mmx_extended();
assert!(content.contains("_mm_adds_pi8"));
assert!(content.contains("_mm_adds_pu8"));
assert!(content.contains("_mm_adds_pi16"));
assert!(content.contains("_mm_subs_pi8"));
assert!(content.contains("_mm_subs_pi16"));
}
#[test]
fn test_mmx_extended_average_min_max() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate_mmx_extended();
assert!(content.contains("_mm_avg_pu8"));
assert!(content.contains("_mm_avg_pu16"));
assert!(content.contains("_mm_min_pi16"));
assert!(content.contains("_mm_max_pi16"));
assert!(content.contains("_mm_sad_pu8"));
}
#[test]
fn test_mmx_extended_insert_extract() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate_mmx_extended();
assert!(content.contains("_mm_insert_pi16"));
assert!(content.contains("_mm_extract_pi16"));
assert!(content.contains("_mm_shuffle_pi16"));
assert!(content.contains("_mm_movemask_pi8"));
}
#[test]
fn test_mmx_extended_mulhi() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate_mmx_extended();
assert!(content.contains("_mm_mulhi_pi16"));
}
#[test]
fn test_sse_extended_streaming() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate_sse_extended();
assert!(content.contains("_mm_stream_ps"));
assert!(content.contains("_mm_stream_pi"));
assert!(content.contains("_mm_pause"));
}
#[test]
fn test_sse_extended_transpose_macro() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate_sse_extended();
assert!(content.contains("_MM_TRANSPOSE4_PS"));
assert!(content.contains("_mm_unpacklo_ps"));
assert!(content.contains("_mm_movelh_ps"));
}
#[test]
fn test_sse_extended_load_store_pi() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate_sse_extended();
assert!(content.contains("_mm_loadh_pi"));
assert!(content.contains("_mm_loadl_pi"));
assert!(content.contains("_mm_storeh_pi"));
assert!(content.contains("_mm_storel_pi"));
}
#[test]
fn test_sse2_extended_saturated_ops() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate_sse2_extended();
assert!(content.contains("_mm_adds_epi8"));
assert!(content.contains("_mm_adds_epu8"));
assert!(content.contains("_mm_adds_epi16"));
assert!(content.contains("_mm_subs_epi8"));
assert!(content.contains("_mm_subs_epi16"));
}
#[test]
fn test_sse2_extended_average_min_max() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate_sse2_extended();
assert!(content.contains("_mm_avg_epu8"));
assert!(content.contains("_mm_avg_epu16"));
assert!(content.contains("_mm_min_epu8"));
assert!(content.contains("_mm_max_epu8"));
assert!(content.contains("_mm_sad_epu8"));
}
#[test]
fn test_sse2_extended_mulhi() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate_sse2_extended();
assert!(content.contains("_mm_mulhi_epi16"));
assert!(content.contains("_mm_mulhi_epu16"));
}
#[test]
fn test_sse2_extended_streaming_and_fence() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate_sse2_extended();
assert!(content.contains("_mm_stream_si128"));
assert!(content.contains("_mm_stream_pd"));
assert!(content.contains("_mm_clflush"));
assert!(content.contains("_mm_lfence"));
assert!(content.contains("_mm_mfence"));
assert!(content.contains("_mm_maskmove_si64"));
assert!(content.contains("_mm_movemask_epi8"));
}
#[test]
fn test_avx_extended_hadd_hsub_addsub() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate_avx_extended();
assert!(content.contains("_mm256_hadd_ps"));
assert!(content.contains("_mm256_hadd_pd"));
assert!(content.contains("_mm256_hsub_ps"));
assert!(content.contains("_mm256_addsub_ps"));
assert!(content.contains("_mm256_addsub_pd"));
}
#[test]
fn test_avx_extended_blend_round_floor_ceil() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate_avx_extended();
assert!(content.contains("_mm256_blend_ps"));
assert!(content.contains("_mm256_blend_pd"));
assert!(content.contains("_mm256_blendv_ps"));
assert!(content.contains("_mm256_dp_ps"));
assert!(content.contains("_mm256_round_ps"));
assert!(content.contains("_mm256_round_pd"));
assert!(content.contains("_mm256_floor_ps"));
assert!(content.contains("_mm256_ceil_ps"));
}
#[test]
fn test_avx_extended_test_extract_insert() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate_avx_extended();
assert!(content.contains("_mm256_testz_ps"));
assert!(content.contains("_mm256_testc_ps"));
assert!(content.contains("_mm256_extractf128_ps"));
assert!(content.contains("_mm256_insertf128_ps"));
}
#[test]
fn test_avx_extended_stream_mask() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate_avx_extended();
assert!(content.contains("_mm256_stream_ps"));
assert!(content.contains("_mm256_stream_pd"));
assert!(content.contains("_mm256_maskload_ps"));
assert!(content.contains("_mm256_maskstore_ps"));
}
#[test]
fn test_avx2_extended_variable_shifts() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate_avx2_extended();
assert!(content.contains("_mm256_sllv_epi32"));
assert!(content.contains("_mm256_sllv_epi64"));
assert!(content.contains("_mm256_srlv_epi32"));
assert!(content.contains("_mm256_srav_epi32"));
}
#[test]
fn test_avx2_extended_saturated_ops() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate_avx2_extended();
assert!(content.contains("_mm256_adds_epi8"));
assert!(content.contains("_mm256_adds_epi16"));
assert!(content.contains("_mm256_subs_epi8"));
assert!(content.contains("_mm256_subs_epi16"));
}
#[test]
fn test_avx2_extended_hadd_shuffle_pack_unpack() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate_avx2_extended();
assert!(content.contains("_mm256_hadd_epi16"));
assert!(content.contains("_mm256_hadd_epi32"));
assert!(content.contains("_mm256_shuffle_epi8"));
assert!(content.contains("_mm256_packs_epi16"));
assert!(content.contains("_mm256_packs_epi32"));
assert!(content.contains("_mm256_unpackhi_epi8"));
assert!(content.contains("_mm256_unpacklo_epi8"));
}
#[test]
fn test_avx2_extended_broadcast_mask() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate_avx2_extended();
assert!(content.contains("_mm256_broadcastsi128_si256"));
assert!(content.contains("_mm256_maskload_epi32"));
assert!(content.contains("_mm256_maskstore_epi32"));
assert!(content.contains("_mm256_mulhi_epi16"));
}
#[test]
fn test_builtin_define_extraction_stdint() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Stdint);
let defines: Vec<&str> = content
.lines()
.filter(|l| l.trim().starts_with("#define"))
.collect();
assert!(defines.len() > 20, "Expected >20 define macros in stdint.h");
let define_names: Vec<&str> = defines
.iter()
.filter_map(|line| {
let parts: Vec<&str> = line.split_whitespace().collect();
if parts.len() >= 2 {
Some(parts[1])
} else {
None
}
})
.collect();
assert!(define_names.contains(&"INT8_MIN"));
assert!(define_names.contains(&"INT64_MAX"));
assert!(define_names.contains(&"SIZE_MAX"));
assert!(define_names.contains(&"WINT_MIN"));
assert!(define_names.contains(&"WINT_MAX"));
}
#[test]
fn test_builtin_define_extraction_limits() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Limits);
let define_names: Vec<&str> = content
.lines()
.filter(|l| l.trim().starts_with("#define"))
.filter_map(|line| {
let parts: Vec<&str> = line.split_whitespace().collect();
if parts.len() >= 2 {
Some(parts[1])
} else {
None
}
})
.collect();
assert!(define_names.contains(&"CHAR_BIT"));
assert!(define_names.contains(&"SCHAR_MIN"));
assert!(define_names.contains(&"UCHAR_MAX"));
assert!(define_names.contains(&"SHRT_MAX"));
assert!(define_names.contains(&"INT_MIN"));
assert!(define_names.contains(&"INT_MAX"));
assert!(define_names.contains(&"LONG_MIN"));
assert!(define_names.contains(&"LONG_MAX"));
assert!(define_names.contains(&"LLONG_MAX"));
assert!(define_names.contains(&"ULLONG_MAX"));
assert!(define_names.contains(&"SSIZE_MAX"));
}
#[test]
fn test_builtin_define_extraction_float() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Float);
let define_names: Vec<&str> = content
.lines()
.filter(|l| l.trim().starts_with("#define"))
.filter_map(|line| {
let parts: Vec<&str> = line.split_whitespace().collect();
if parts.len() >= 2 {
Some(parts[1])
} else {
None
}
})
.collect();
assert!(define_names.contains(&"FLT_RADIX"));
assert!(define_names.contains(&"FLT_MANT_DIG"));
assert!(define_names.contains(&"DBL_MANT_DIG"));
assert!(define_names.contains(&"LDBL_MANT_DIG"));
assert!(define_names.contains(&"FLT_MIN"));
assert!(define_names.contains(&"DBL_MAX"));
assert!(define_names.contains(&"FLT_EPSILON"));
}
#[test]
fn test_int_sizes_consistent_stdint_vs_limits() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let stdint = r#gen.generate(X86BuiltinHeader::Stdint);
let limits = r#gen.generate(X86BuiltinHeader::Limits);
let int32_max_stdint = extract_define_value(&stdint, "INT32_MAX");
let int_max_limits = extract_define_value(&limits, "INT_MAX");
if let (Some(a), Some(b)) = (int32_max_stdint, int_max_limits) {
assert_eq!(
a, b,
"INT32_MAX in stdint.h and INT_MAX in limits.h must match"
);
}
}
#[test]
fn test_size_t_consistent_stddef_vs_stdint() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let stddef = r#gen.generate(X86BuiltinHeader::Stddef);
let stdint = r#gen.generate(X86BuiltinHeader::Stdint);
assert!(stdint.contains("SIZE_MAX"));
assert!(stddef.contains("size_t"));
}
#[test]
fn test_unreachable_only_in_c23_context() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Stddef);
let unreachable_idx = content.find("unreachable").unwrap();
let version_guard = content[..unreachable_idx].rfind("202311L").unwrap();
assert!(version_guard < unreachable_idx);
}
#[test]
fn test_differential_x86_64_vs_x86_32() {
let gen64 = X86BuiltinHeaders::new_x86_64();
let gen32 = X86BuiltinHeaders::new_x86_32();
let stdint64 = gen64.generate(X86BuiltinHeader::Stdint);
let stdint32 = gen32.generate(X86BuiltinHeader::Stdint);
let size_max64 = extract_define_value(&stdint64, "SIZE_MAX");
let size_max32 = extract_define_value(&stdint32, "SIZE_MAX");
assert!(size_max64 != size_max32);
if let (Some(s64), Some(s32)) = (size_max64, size_max32) {
let v64 = s64
.replace("UL", "")
.replace("ULL", "")
.parse::<u64>()
.unwrap_or(0);
let v32 = s32
.replace("U", "")
.replace("UL", "")
.parse::<u64>()
.unwrap_or(0);
assert!(v64 > v32, "64-bit SIZE_MAX should exceed 32-bit SIZE_MAX");
}
}
#[test]
fn test_differential_avx512_enabled_vs_disabled() {
let mut provider = X86HeaderProvider::new_x86_64();
assert!(!provider.is_available("avx512fintrin.h"));
provider.config_mut().enable_feature(X86Feature::Avx512f);
provider.clear_cache();
assert!(provider.is_available("avx512fintrin.h"));
assert!(provider.is_available("avx512bwintrin.h"));
assert!(provider.is_available("avx512dqintrin.h"));
assert!(provider.is_available("avx512vlintrin.h"));
}
fn extract_define_value(content: &str, name: &str) -> Option<String> {
for line in content.lines() {
let trimmed = line.trim();
if trimmed.starts_with("#define") {
let parts: Vec<&str> = trimmed.split_whitespace().collect();
if parts.len() >= 3 && parts[1] == name {
return Some(parts[2..].join(" "));
}
}
}
None
}
#[test]
fn test_scenario_compile_c89_program() {
let mut provider = X86HeaderProvider::new_x86_64();
let needed = ["stddef.h", "stdarg.h", "limits.h", "float.h"];
for h in &needed {
assert!(provider.resolve(h).is_some(), "Missing C89 header: {}", h);
}
assert!(provider.is_builtin_header("stdint.h"));
assert!(provider.is_builtin_header("stdbool.h"));
}
#[test]
fn test_scenario_compile_simd_program() {
let mut provider = X86HeaderProvider::new_x86_64();
let needed = [
"stddef.h",
"stdint.h",
"x86intrin.h",
"xmmintrin.h",
"emmintrin.h",
"pmmintrin.h",
"tmmintrin.h",
"smmintrin.h",
];
for h in &needed {
let result = provider.resolve(h);
assert!(
result.is_some(),
"Missing SIMD header: {} (cache size: {})",
h,
provider.cache_size()
);
}
}
#[test]
fn test_scenario_compile_aes_program() {
let mut provider = X86HeaderProvider::new_x86_64();
assert!(provider.resolve("wmmintrin.h").is_some());
let content = provider.resolve("wmmintrin.h").unwrap();
assert!(content.contains("_mm_aesenc_si128"));
}
#[test]
fn test_scenario_compile_avx2_program() {
let mut provider = X86HeaderProvider::new_x86_64();
assert!(provider.resolve("immintrin.h").is_some());
assert!(provider.resolve("avxintrin.h").is_some());
assert!(provider.resolve("avx2intrin.h").is_some());
assert!(provider.resolve("fmaintrin.h").is_some());
}
#[test]
fn test_scenario_cpuid_detection() {
let mut provider = X86HeaderProvider::new_x86_64();
let content = provider.resolve("cpuid.h").unwrap();
assert!(content.contains("__cpuid"));
assert!(content.contains("__cpuid_count"));
assert!(content.contains("__get_cpuid_max"));
assert!(content.contains("GenuineIntel"));
}
#[test]
fn test_invariant_all_headers_are_unique_filenames() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let mut seen = std::collections::HashSet::new();
for header in r#gen.all_headers() {
assert!(
seen.insert(header.filename()),
"Duplicate filename: {}",
header.filename()
);
}
}
#[test]
fn test_invariant_include_guard_macro_is_related_to_header_name() {
let r#gen = X86BuiltinHeaders::new_x86_64();
for header in r#gen.all_headers() {
let content = r#gen.generate(header);
let guard_line = content
.lines()
.find(|l| l.starts_with("#define ") && l.contains('_'))
.unwrap();
let expected_macro = header.filename().to_uppercase().replace('.', "_");
assert!(
guard_line.contains("__"),
"{}: guard macro missing __ prefix: {}",
header.filename(),
guard_line
);
}
}
#[test]
fn test_invariant_no_tabs_in_header_content() {
let r#gen = X86BuiltinHeaders::new_x86_64();
for header in r#gen.all_headers() {
let content = r#gen.generate(header);
assert!(
!content.contains('\t'),
"{} contains tab characters (use spaces)",
header.filename()
);
}
}
#[test]
fn test_invariant_no_trailing_whitespace_on_lines() {
let r#gen = X86BuiltinHeaders::new_x86_64();
for header in r#gen.all_headers() {
let content = r#gen.generate(header);
for (i, line) in content.lines().enumerate() {
if !line.is_empty() {
assert!(
!line.ends_with(' ') && !line.ends_with('\t'),
"{}:{} trailing whitespace: '{}'",
header.filename(),
i + 1,
line
);
}
}
}
}
#[test]
fn test_invariant_generate_all_returns_all_headers() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let all = r#gen.generate_all();
assert_eq!(all.len(), r#gen.all_headers().len());
}
#[test]
fn test_roundtrip_header_name_to_enum() {
let mut provider = X86HeaderProvider::new_x86_64();
let header_names: Vec<&str> = provider
.generator
.all_headers()
.iter()
.map(|h| h.filename())
.collect();
for name in &header_names {
assert!(
provider.is_builtin_header(name),
"Header name '{}' not recognized",
name
);
}
}
#[test]
fn test_all_header_enums_have_filename_match() {
let r#gen = X86BuiltinHeaders::new_x86_64();
for header in r#gen.all_headers() {
let name = header.filename();
let content = r#gen.generate(header);
assert!(
content.contains(name),
"{} generated content doesn't mention its filename",
name
);
}
}
#[test]
fn test_avx512f_all_operations() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Avx512fintrin);
assert!(content.contains("_mm512_add_ps"));
assert!(content.contains("_mm512_add_pd"));
assert!(content.contains("_mm512_sub_ps"));
assert!(content.contains("_mm512_mul_ps"));
assert!(content.contains("_mm512_div_ps"));
assert!(content.contains("_mm512_cmp_ps_mask"));
assert!(content.contains("_mm512_and_ps"));
assert!(content.contains("_mm512_or_ps"));
assert!(content.contains("_mm512_load_ps"));
assert!(content.contains("_mm512_store_ps"));
assert!(content.contains("__mmask16"));
assert!(content.contains("__mmask64"));
}
#[test]
fn test_avx512_feature_enable_all() {
for feature in X86Feature::all() {
let mut cfg = X86TargetConfig::new_minimal_x86_64();
assert!(!cfg.has_feature(*feature));
cfg.enable_feature(*feature);
assert!(cfg.has_feature(*feature));
}
}
#[test]
fn test_feature_enable_all_at_once() {
let mut cfg = X86TargetConfig::new_minimal_x86_64();
assert_eq!(cfg.enabled_features().len(), 0);
for feature in X86Feature::all() {
cfg.enable_feature(*feature);
}
assert_eq!(cfg.enabled_features().len(), X86Feature::all().len());
}
#[test]
fn test_sse_dependency_chain() {
let mut cfg = X86TargetConfig::new_minimal_x86_64();
cfg.enable_feature(X86Feature::Sse42);
assert!(cfg.has_feature(X86Feature::Sse41));
assert!(cfg.has_feature(X86Feature::Ssse3));
assert!(cfg.has_feature(X86Feature::Sse3));
assert!(cfg.has_feature(X86Feature::Sse2));
assert!(cfg.has_feature(X86Feature::Sse));
assert!(cfg.has_feature(X86Feature::Mmx));
}
#[test]
fn test_provider_repeated_resolve_stable() {
let mut provider = X86HeaderProvider::new_x86_64();
let first = provider.resolve("stddef.h").unwrap().to_string();
for _ in 0..100 {
let again = provider.resolve("stddef.h").unwrap();
assert_eq!(first, again);
}
}
#[test]
fn test_provider_prewarm_then_resolve() {
let mut provider = X86HeaderProvider::new_x86_64();
provider.prewarm_cache();
let pre = provider.cache_size();
provider.resolve("stddef.h");
assert_eq!(provider.cache_size(), pre);
}
#[test]
fn test_stdint_all_required_types() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Stdint);
for t in &[
"int8_t", "int16_t", "int32_t", "int64_t", "uint8_t", "uint16_t", "uint32_t",
"uint64_t",
] {
assert!(content.contains(t), "Missing: {}", t);
}
for t in &[
"int_least8_t",
"int_least16_t",
"int_least32_t",
"int_least64_t",
] {
assert!(content.contains(t), "Missing: {}", t);
}
for t in &[
"int_fast8_t",
"int_fast16_t",
"int_fast32_t",
"int_fast64_t",
] {
assert!(content.contains(t), "Missing: {}", t);
}
assert!(content.contains("intptr_t"));
assert!(content.contains("uintptr_t"));
assert!(content.contains("intmax_t"));
assert!(content.contains("uintmax_t"));
}
#[test]
fn test_stdint_all_limit_macros() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Stdint);
for m in &[
"INT8_MIN",
"INT8_MAX",
"INT16_MIN",
"INT16_MAX",
"INT32_MIN",
"INT32_MAX",
"INT64_MIN",
"INT64_MAX",
"UINT8_MAX",
"UINT16_MAX",
"UINT32_MAX",
"UINT64_MAX",
] {
assert!(content.contains(m), "Missing: {}", m);
}
for m in &[
"INT8_C", "INT16_C", "INT32_C", "INT64_C", "UINT8_C", "UINT16_C", "UINT32_C",
"UINT64_C",
] {
assert!(content.contains(m), "Missing: {}", m);
}
}
#[test]
fn test_generate_all_idempotent() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let first = r#gen.generate_all();
let second = r#gen.generate_all();
assert_eq!(first.len(), second.len());
for (key, value) in &first {
assert_eq!(value, &second[key]);
}
}
#[test]
fn test_minimal_to_full_feature_progression() {
let mut provider = X86HeaderProvider::new(X86TargetConfig::new_minimal_x86_64());
assert!(provider.resolve("stddef.h").is_some());
assert!(provider.resolve("xmmintrin.h").is_none());
provider.config_mut().enable_feature(X86Feature::Sse);
provider.clear_cache();
assert!(provider.resolve("xmmintrin.h").is_some());
provider.config_mut().enable_feature(X86Feature::Avx);
provider.clear_cache();
assert!(provider.resolve("avxintrin.h").is_some());
}
#[test]
fn test_validator_all_standard_headers_pass_v2() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let failures = HeaderContentValidator::validate_all(&r#gen);
for (header, errors) in &failures {
if header.is_standard_c() {
panic!("Standard header {} failed: {:?}", header.filename(), errors);
}
}
}
#[test]
fn test_intrinsic_headers_contain_patterns() {
let r#gen = X86BuiltinHeaders::new_x86_64();
for header in r#gen.all_headers() {
if header.is_x86_intrinsic() && header != X86BuiltinHeader::Cpuid {
let content = r#gen.generate(header);
let ok = content.contains("__builtin_ia32")
|| content.contains("__builtin_shufflevector")
|| content.contains("__attribute__")
|| content.contains("__asm__");
assert!(ok, "{} missing implementation", header.filename());
}
}
}
#[test]
fn test_no_tabs_in_content() {
let r#gen = X86BuiltinHeaders::new_x86_64();
for header in r#gen.all_headers() {
let content = r#gen.generate(header);
assert!(!content.contains('\t'), "{} has tabs", header.filename());
}
}
#[test]
fn test_float_mant_dig_correct() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Float);
assert!(content.contains("FLT_MANT_DIG 24"));
assert!(content.contains("DBL_MANT_DIG 53"));
assert!(content.contains("LDBL_MANT_DIG 64"));
}
#[test]
fn test_float_decimal_dig_correct() {
let r#gen = X86BuiltinHeaders::new_x86_64();
let content = r#gen.generate(X86BuiltinHeader::Float);
assert!(content.contains("FLT_DECIMAL_DIG 9"));
assert!(content.contains("DBL_DECIMAL_DIG 17"));
assert!(content.contains("LDBL_DECIMAL_DIG 21"));
}
#[test]
fn test_differential_64_vs_32_size_max() {
let gen64 = X86BuiltinHeaders::new_x86_64();
let gen32 = X86BuiltinHeaders::new_x86_32();
let c64 = gen64.generate(X86BuiltinHeader::Stdint);
let c32 = gen32.generate(X86BuiltinHeader::Stdint);
let v64 = extract_define_value(&c64, "SIZE_MAX");
let v32 = extract_define_value(&c32, "SIZE_MAX");
assert!(v64 != v32);
}
#[test]
fn test_provider_trait_impls() {
let p = X86HeaderProvider::default();
assert_eq!(p.config().pointer_width, 64);
let p2 = X86HeaderProvider::new_x86_32();
assert_eq!(p2.config().pointer_width, 32);
let p3 = X86HeaderProvider::new(X86TargetConfig::new_x86_64_avx512());
assert!(p3.config().has_avx512f);
}
}