//! clang_cxx23_26_x86 — C++23 and C++26 feature implementation for Clang on X86.
//!
//! This module provides complete C++23 and preview C++26 language and library
//! feature support, specialized for the X86 architecture family (IA-32, X86-64).
//! Clean-room behavioral reconstruction from ISO/IEC 14882:2024 (C++23) working
//! drafts, WG21 papers, and published Clang documentation.
//!
//! # Architecture
//!
//! - `X86CXX23_26` — Master struct coordinating all C++23/26 X86 support
//! - C++23 features — Full parsing, semantic analysis, and codegen implementations
//! - C++26 features — Preview/experimental implementations
//! - `X86CXX23Features` — Feature detection and test macros
//! - `X86CXX23CodeGen` — C++23-specific X86 code generation lowering
//!
//! # C++23 Features Covered (Full)
//!
//! - Literal suffixes `uz`, `z` for `std::size_t`, `std::ptrdiff_t` (P0330R8)
//! - `if consteval` compile-time conditional (P1938R3)
//! - Deducing `this` / explicit object parameters (P0847R7)
//! - Multidimensional subscript operator (P2128R6)
//! - `static operator()` (P1169R4)
//! - `auto(x)` / `auto{x}` decay-copy prvalue (P0849R8)
//! - `#elifdef`, `#elifndef` preprocessor directives (P2334R1)
//! - `#warning` standard directive (P2437R1)
//! - Attributes on lambdas
//! - Simpler implicit move in return statements (P2266R3)
//! - Monadic operations for `std::optional`: `and_then`, `transform`, `or_else` (P0798R8)
//! - `std::expected<T, E>` error handling type (P0323R12)
//! - `std::mdspan` multidimensional span (P0009R18)
//! - `std::flat_map`, `std::flat_set` sorted vector containers (P0429R9)
//! - `std::print`, `std::println` formatted output (P2093R14)
//! - `std::generator<T>` coroutine generator (P2502R2)
//! - Range views: `zip`, `zip_transform`, `adjacent`, `adjacent_transform`,
//! `slide`, `chunk`, `chunk_by`, `stride`, `cartesian_product`, `join_with`,
//! `repeat`, `enumerate`, `as_rvalue`, `as_const`
//! - `std::ranges::to<T>` range conversion (P1206R7)
//! - Range algorithm improvements: `find_last`, `contains`, `starts_with`, `ends_with`
//! - DR20: Parenthesized aggregate initialization (P0960R3)
//!
//! # C++26 Features Covered (Preview)
//!
//! - Pack indexing: `args...[0]` (P2662R3)
//! - Placeholder variables with no name: `auto _ = f();` (P2169R4)
//! - `constexpr` placement new (P2747R2)
//! - User-generated `static_assert` messages (P2741R3)
//! - Deleting pointer to incomplete type — ill-formed diagnostic
//! - `std::inplace_vector<T, N>` fixed-capacity vector (P0843R8)
//! - `std::hive<T>` bucket array container (P0447R18)
//! - `std::is_virtual_base_of` type trait (P2985R0)
//! - Read-copy update (RCU) / hazard pointers
//! - Contracts: `pre`, `post`, `assert` (P0542R5)
//! - Reflection: `^` operator, `[: :]` splicer, `meta::info` (P2996R3)
//! - Senders/Receivers: `std::execution` (P2300R7)
//! - Pattern matching: `inspect` expression (P1371R3)
//! - `std::simd<T, N>` with X86 SIMD lowering (P1928R3)
use std::collections::{BTreeMap, HashMap, HashSet};
use std::fmt;
// ═══════════════════════════════════════════════════════════════════════════════
// 1. X86CXX23_26 — Master coordinator for C++23/26 X86 Clang support
// ═══════════════════════════════════════════════════════════════════════════════
/// Architecture variant for X86 C++23/26 code generation.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CXX23X86Arch {
/// IA-32 (32-bit protected mode).
X86_32,
/// X86-64 (AMD64/Intel 64).
X86_64,
}
impl fmt::Display for CXX23X86Arch {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::X86_32 => write!(f, "i386"),
Self::X86_64 => write!(f, "x86_64"),
}
}
}
/// SIMD capability level on the X86 target for C++23/26 features.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum CXX23SimdLevel {
/// No SIMD (baseline scalar).
None,
/// SSE (128-bit).
SSE,
/// SSE2 (128-bit — baseline for x86_64).
SSE2,
/// SSE3 + SSSE3.
SSSE3,
/// SSE4.1 + SSE4.2.
SSE4,
/// AVX (256-bit).
AVX,
/// AVX2 (256-bit integer).
AVX2,
/// AVX-512 Foundation (512-bit).
AVX512F,
/// AVX-512 with all sub-extensions.
AVX512Full,
}
impl CXX23SimdLevel {
/// Determine SIMD level from X86 feature flags.
pub fn from_features(has_avx512f: bool, has_avx2: bool, has_avx: bool, has_sse2: bool) -> Self {
if has_avx512f {
Self::AVX512F
} else if has_avx2 {
Self::AVX2
} else if has_avx {
Self::AVX
} else if has_sse2 {
Self::SSE2
} else {
Self::None
}
}
/// Returns the vector width in bits for this SIMD level.
pub fn vector_width_bits(&self) -> u32 {
match self {
Self::None => 0,
Self::SSE | Self::SSE2 | Self::SSSE3 | Self::SSE4 => 128,
Self::AVX | Self::AVX2 => 256,
Self::AVX512F | Self::AVX512Full => 512,
}
}
/// Returns true if this SIMD level supports integer vector operations.
pub fn supports_integer_vectors(&self) -> bool {
matches!(
self,
Self::SSE2 | Self::SSSE3 | Self::SSE4 | Self::AVX2 | Self::AVX512F | Self::AVX512Full
)
}
}
impl fmt::Display for CXX23SimdLevel {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::None => write!(f, "none"),
Self::SSE => write!(f, "sse"),
Self::SSE2 => write!(f, "sse2"),
Self::SSSE3 => write!(f, "ssse3"),
Self::SSE4 => write!(f, "sse4"),
Self::AVX => write!(f, "avx"),
Self::AVX2 => write!(f, "avx2"),
Self::AVX512F => write!(f, "avx512f"),
Self::AVX512Full => write!(f, "avx512full"),
}
}
}
/// Master coordinator for C++23 and C++26 feature support on X86 Clang.
///
/// Integrates feature detection, parsing, semantic analysis, and code generation
/// for all C++23 and C++26 language/library features with X86-specific lowering.
#[derive(Debug, Clone)]
pub struct X86CXX23_26 {
/// Target architecture variant.
pub arch: CXX23X86Arch,
/// SIMD capability level on target.
pub simd_level: CXX23SimdLevel,
/// C++ standard version being targeted (e.g., C++23, C++26).
pub standard: X86CXXStandard,
/// Feature detection and registration.
pub features: X86CXX23Features,
/// Code generation engine.
pub codegen: X86CXX23CodeGen,
/// Whether contracts are enabled (C++26 preview).
pub contracts_enabled: bool,
/// Whether reflection is enabled (C++26 preview).
pub reflection_enabled: bool,
/// Whether pattern matching is enabled (C++26 preview).
pub pattern_matching_enabled: bool,
/// Whether senders/receivers (std::execution) is enabled (C++26 preview).
pub senders_receivers_enabled: bool,
/// Whether pack indexing is enabled (C++26 preview).
pub pack_indexing_enabled: bool,
/// Whether constexpr placement new is enabled (C++26 preview).
pub constexpr_placement_new_enabled: bool,
/// Whether SIMD library is enabled (requires SSE/AVX).
pub simd_enabled: bool,
/// Debug logging verbosity.
pub verbose: bool,
}
impl X86CXX23_26 {
/// Create a new instance for X86-64 with C++23 standard.
pub fn new_x86_64_cxx23() -> Self {
let arch = CXX23X86Arch::X86_64;
let simd_level = CXX23SimdLevel::SSE2;
let standard = X86CXXStandard::CXX23;
Self {
arch,
simd_level,
standard,
features: X86CXX23Features::new_x86_64(standard),
codegen: X86CXX23CodeGen::new(arch, simd_level, standard),
contracts_enabled: false,
reflection_enabled: false,
pattern_matching_enabled: false,
senders_receivers_enabled: false,
pack_indexing_enabled: false,
constexpr_placement_new_enabled: false,
simd_enabled: true,
verbose: false,
}
}
/// Create a new instance for X86-64 with C++26 preview standard.
pub fn new_x86_64_cxx26() -> Self {
let arch = CXX23X86Arch::X86_64;
let simd_level = CXX23SimdLevel::SSE2;
let standard = X86CXXStandard::CXX26;
Self {
arch,
simd_level,
standard,
features: X86CXX23Features::new_x86_64(standard),
codegen: X86CXX23CodeGen::new(arch, simd_level, standard),
contracts_enabled: true,
reflection_enabled: true,
pattern_matching_enabled: true,
senders_receivers_enabled: true,
pack_indexing_enabled: true,
constexpr_placement_new_enabled: true,
simd_enabled: true,
verbose: false,
}
}
/// Create a new instance for IA-32 with C++23 standard.
pub fn new_x86_32_cxx23() -> Self {
let arch = CXX23X86Arch::X86_32;
let simd_level = CXX23SimdLevel::None;
let standard = X86CXXStandard::CXX23;
Self {
arch,
simd_level,
standard,
features: X86CXX23Features::new_x86_32(standard),
codegen: X86CXX23CodeGen::new(arch, simd_level, standard),
contracts_enabled: false,
reflection_enabled: false,
pattern_matching_enabled: false,
senders_receivers_enabled: false,
pack_indexing_enabled: false,
constexpr_placement_new_enabled: false,
simd_enabled: false,
verbose: false,
}
}
/// Enable all C++26 preview features.
pub fn enable_cxx26_preview(&mut self) {
self.contracts_enabled = true;
self.reflection_enabled = true;
self.pattern_matching_enabled = true;
self.senders_receivers_enabled = true;
self.pack_indexing_enabled = true;
self.constexpr_placement_new_enabled = true;
}
/// Enable SIMD features at a specific level.
pub fn enable_simd(&mut self, level: CXX23SimdLevel) {
self.simd_level = level;
self.simd_enabled = level > CXX23SimdLevel::None;
}
/// Return the size of `size_t` in bytes for the target architecture.
pub fn size_t_bytes(&self) -> u8 {
match self.arch {
CXX23X86Arch::X86_32 => 4,
CXX23X86Arch::X86_64 => 8,
}
}
/// Return the alignment of fundamental types for the target.
pub fn max_fundamental_alignment(&self) -> u32 {
match self.arch {
CXX23X86Arch::X86_32 => 8,
CXX23X86Arch::X86_64 => 16,
}
}
/// Check if a specific C++23/26 feature is enabled.
pub fn is_feature_enabled(&self, feature: &X86CXXFeature) -> bool {
self.features.is_enabled(feature)
}
/// Get a summary of all enabled features.
pub fn enabled_summary(&self) -> String {
let mut summary = format!(
"X86 C++{}/{} features on {} (SIMD: {})\n",
if self.standard >= X86CXXStandard::CXX23 {
"23"
} else {
"20"
},
if self.standard >= X86CXXStandard::CXX26 {
"26"
} else if self.standard >= X86CXXStandard::CXX23 {
"23"
} else {
"20"
},
self.arch,
self.simd_level,
);
let enabled = self.features.enabled_features();
summary.push_str(&format!(" Enabled: {}\n", enabled.len()));
for f in &enabled {
summary.push_str(&format!(" - {}\n", f.name()));
}
summary
}
}
impl Default for X86CXX23_26 {
fn default() -> Self {
Self::new_x86_64_cxx23()
}
}
// ═══════════════════════════════════════════════════════════════════════════════
// 2. X86CXXStandard — C++ standard version with X86-specific extensions
// ═══════════════════════════════════════════════════════════════════════════════
/// C++ standard version for X86 Clang.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum X86CXXStandard {
/// C++17 (ISO/IEC 14882:2017).
CXX17 = 201703,
/// C++20 (ISO/IEC 14882:2020).
CXX20 = 202002,
/// C++23 (ISO/IEC 14882:2024).
CXX23 = 202302,
/// C++26 (WG21 working draft preview).
CXX26 = 202602,
}
impl X86CXXStandard {
/// Parse from a standard string like "c++23", "c++2b", "c++26".
pub fn from_str(s: &str) -> Option<Self> {
match s {
"c++17" | "c++1z" | "cxx17" => Some(Self::CXX17),
"c++20" | "c++2a" | "cxx20" => Some(Self::CXX20),
"c++23" | "c++2b" | "cxx23" => Some(Self::CXX23),
"c++26" | "c++2c" | "cxx26" => Some(Self::CXX26),
_ => None,
}
}
/// Return the standard as a string.
pub fn as_str(&self) -> &'static str {
match self {
Self::CXX17 => "c++17",
Self::CXX20 => "c++20",
Self::CXX23 => "c++23",
Self::CXX26 => "c++26",
}
}
/// Return the standard value (year + month).
pub fn value(&self) -> u32 {
*self as u32
}
/// Check if this standard is at least the given version.
pub fn is_at_least(&self, other: Self) -> bool {
*self >= other
}
}
impl fmt::Display for X86CXXStandard {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.as_str())
}
}
// ═══════════════════════════════════════════════════════════════════════════════
// 3. C++23 Features — Full Implementations
// ═══════════════════════════════════════════════════════════════════════════════
// ── 3.1 Literal Suffixes for size_t and ptrdiff_t (uz / z) ── P0330R8 ──
/// Literal suffix kind for `size_t` and `ptrdiff_t`.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86SizeTLiteralSuffix {
/// `uz` — unsigned, yields `std::size_t`.
Uz,
/// `z` — signed, yields `std::ptrdiff_t` (signed counterpart).
Z,
}
impl X86SizeTLiteralSuffix {
/// Parse from a suffix string.
pub fn from_suffix(s: &str) -> Option<Self> {
match s {
"uz" | "uZ" | "Uz" | "UZ" => Some(Self::Uz),
"z" | "Z" => Some(Self::Z),
_ => None,
}
}
/// Return the suffix as a C++ literal string.
pub fn as_str(&self) -> &'static str {
match self {
Self::Uz => "uz",
Self::Z => "z",
}
}
/// Whether this suffix is signed.
pub fn is_signed(&self) -> bool {
matches!(self, Self::Z)
}
/// The type name this suffix resolves to.
pub fn type_name(&self) -> &'static str {
match self {
Self::Uz => "std::size_t",
Self::Z => "std::ptrdiff_t",
}
}
/// The width of this type in bytes on X86-64.
pub fn width_bytes_x86_64(&self) -> u8 {
match self {
Self::Uz => 8,
Self::Z => 8,
}
}
/// The width of this type in bytes on IA-32.
pub fn width_bytes_x86_32(&self) -> u8 {
match self {
Self::Uz => 4,
Self::Z => 4,
}
}
}
/// A parsed `size_t` or `ptrdiff_t` literal.
#[derive(Debug, Clone)]
pub struct X86SizeTLiteral {
/// The numeric value as a string.
pub value: String,
/// Which suffix was used.
pub suffix: X86SizeTLiteralSuffix,
}
impl X86SizeTLiteral {
pub fn new(value: String, suffix: X86SizeTLiteralSuffix) -> Self {
Self { value, suffix }
}
/// Reconstruct the literal as C++ source code.
pub fn to_source(&self) -> String {
format!("{}{}", self.value, self.suffix.as_str())
}
/// Get the corresponding LLVM integer type for the X86 target.
pub fn llvm_type(&self, arch: CXX23X86Arch) -> String {
let bits = match arch {
CXX23X86Arch::X86_32 => 32,
CXX23X86Arch::X86_64 => 64,
};
format!("i{}", bits)
}
}
/// Parser for `size_t` literal suffixes.
#[derive(Debug, Clone, Default)]
pub struct X86SizeTLiteralParser {
/// Whether `uz`/`z` suffixes are enabled.
pub enabled: bool,
}
impl X86SizeTLiteralParser {
pub fn new(enabled: bool) -> Self {
Self { enabled }
}
/// Try to parse a `uz`/`z` suffix from a numeric literal token text.
pub fn try_parse(&self, literal_text: &str) -> Option<X86SizeTLiteral> {
if !self.enabled {
return None;
}
let (num_part, suffix_part) = if let Some(idx) = literal_text.find(|c: char| !c.is_ascii_digit() && c != '\'') {
literal_text.split_at(idx)
} else {
return None;
};
let suffix = X86SizeTLiteralSuffix::from_suffix(suffix_part)?;
Some(X86SizeTLiteral::new(num_part.to_string(), suffix))
}
}
// ── 3.2 if consteval — P1938R3 ──
/// Result of evaluating whether we are in an immediate (consteval) context.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86IfConstevalResult {
/// The code is executing in an immediate function context.
ImmediateContext,
/// The code is not executing in an immediate function context.
NonImmediateContext,
}
/// A stack-based tracking of `consteval` contexts.
#[derive(Debug, Clone)]
pub struct X86ConstevalContext {
/// Depth of consteval nesting: > 0 means we are in a consteval context.
depth: u32,
/// Stack of function names to track nesting.
stack: Vec<String>,
}
impl X86ConstevalContext {
pub fn new() -> Self {
Self {
depth: 0,
stack: Vec::new(),
}
}
/// Enter a consteval context (e.g., inside a `consteval` function).
pub fn enter(&mut self, function_name: &str) {
self.depth += 1;
self.stack.push(function_name.to_string());
}
/// Leave a consteval context.
pub fn leave(&mut self) -> Option<String> {
if self.depth > 0 {
self.depth -= 1;
}
self.stack.pop()
}
/// Check whether we are currently in a consteval context.
pub fn is_consteval(&self) -> bool {
self.depth > 0
}
/// Evaluate an `if consteval` expression — return which branch to take.
pub fn evaluate_if_consteval(&self) -> X86IfConstevalResult {
if self.is_consteval() {
X86IfConstevalResult::ImmediateContext
} else {
X86IfConstevalResult::NonImmediateContext
}
}
/// Return the current nesting depth.
pub fn nesting_depth(&self) -> u32 {
self.depth
}
}
impl Default for X86ConstevalContext {
fn default() -> Self {
Self::new()
}
}
/// Parser/handler for `if consteval` statements.
#[derive(Debug, Clone)]
pub struct X86IfConstevalParser {
/// Whether `if consteval` is enabled.
pub enabled: bool,
/// The consteval tracking context.
pub contexts: X86ConstevalContext,
}
impl X86IfConstevalParser {
pub fn new(enabled: bool) -> Self {
Self {
enabled,
contexts: X86ConstevalContext::new(),
}
}
/// Detect whether we are in a position to use `if consteval`.
pub fn detect_consteval(&self) -> bool {
self.enabled && self.contexts.is_consteval()
}
/// Parse an `if consteval` body, returning the appropriate branch.
pub fn parse_body<'a>(&self, immediate_body: &'a str, non_immediate_body: &'a str) -> &'a str {
match self.contexts.evaluate_if_consteval() {
X86IfConstevalResult::ImmediateContext => immediate_body,
X86IfConstevalResult::NonImmediateContext => non_immediate_body,
}
}
}
// ── 3.3 Deducing This (Explicit Object Parameters) — P0847R7 ──
/// The kind of explicit object parameter.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86ExplicitObjectKind {
/// `this auto&& self` — deduced forwarding reference.
DeducedRef,
/// `this auto& self` — deduced lvalue reference.
DeducedLvalueRef,
/// `this auto self` — deduced by value.
DeducedByValue,
/// `this auto const& self` — deduced const lvalue reference.
DeducedConstLvalueRef,
}
impl X86ExplicitObjectKind {
/// Parse the kind from the explicit parameter string.
pub fn from_param_str(param: &str) -> Option<Self> {
if param.contains("auto&&") {
Some(Self::DeducedRef)
} else if param.contains("auto const&") || param.contains("const auto&") {
Some(Self::DeducedConstLvalueRef)
} else if param.contains("auto&") {
Some(Self::DeducedLvalueRef)
} else if param.contains("auto") {
Some(Self::DeducedByValue)
} else {
None
}
}
/// Whether this kind is a reference.
pub fn is_reference(&self) -> bool {
matches!(self, Self::DeducedRef | Self::DeducedLvalueRef | Self::DeducedConstLvalueRef)
}
/// Whether this kind is const.
pub fn is_const(&self) -> bool {
matches!(self, Self::DeducedConstLvalueRef)
}
}
/// A function declared with an explicit object parameter (`this auto&& self`).
#[derive(Debug, Clone)]
pub struct X86ExplicitObjectFunction {
/// Function name.
pub name: String,
/// The explicit object parameter text (e.g., `this auto&& self`).
pub explicit_param: String,
/// The parameter name (e.g., `self`).
pub param_name: String,
/// The kind of deduction for the explicit object parameter.
pub kind: X86ExplicitObjectKind,
/// Regular (non-explicit) parameters.
pub regular_params: Vec<X86FunctionParam>,
/// Return type string.
pub return_type: String,
/// Whether this is a member function.
pub is_member: bool,
/// Whether this function is constexpr.
pub is_constexpr: bool,
/// The enclosing class name (if member).
pub class_name: Option<String>,
/// Whether this is a static member function equivalent.
pub is_static: bool,
}
/// A regular function parameter descriptor.
#[derive(Debug, Clone)]
pub struct X86FunctionParam {
/// Parameter name.
pub name: String,
/// Parameter type description.
pub type_desc: String,
/// Optional default value.
pub default_value: Option<String>,
}
impl X86ExplicitObjectFunction {
pub fn new(
name: String,
explicit_param: String,
regular_params: Vec<X86FunctionParam>,
return_type: String,
is_member: bool,
class_name: Option<String>,
) -> Self {
let param_name = explicit_param
.split_whitespace()
.last()
.unwrap_or("self")
.to_string();
let kind = X86ExplicitObjectKind::from_param_str(&explicit_param)
.unwrap_or(X86ExplicitObjectKind::DeducedRef);
Self {
name,
explicit_param,
param_name,
kind,
regular_params,
return_type,
is_member,
is_constexpr: false,
class_name,
is_static: false,
}
}
/// Generate the function signature as C++ source.
pub fn signature(&self) -> String {
let mut sig = String::new();
if self.is_constexpr {
sig.push_str("constexpr ");
}
sig.push_str(&format!("auto {}(", self.name));
sig.push_str(&self.explicit_param);
for p in &self.regular_params {
sig.push_str(&format!(", {} {}", p.type_desc, p.name));
}
sig.push_str(")");
if !self.return_type.is_empty() && self.return_type != "auto" {
sig.push_str(&format!(" -> {}", self.return_type));
}
sig
}
/// Whether this function can bind an lvalue argument.
pub fn can_bind_lvalue(&self) -> bool {
self.kind.is_reference() && !self.kind.is_const()
}
/// Whether this function can bind an rvalue argument.
pub fn can_bind_rvalue(&self) -> bool {
matches!(self.kind, X86ExplicitObjectKind::DeducedRef | X86ExplicitObjectKind::DeducedByValue)
}
}
/// Parser for explicit object parameter declarations.
#[derive(Debug, Clone)]
pub struct X86DeducingThisParser {
/// Whether deducing this is enabled.
pub enabled: bool,
/// Collected diagnostics.
pub diagnostics: Vec<X86DeducingThisDiag>,
}
/// A diagnostic generated during deducing-this parsing.
#[derive(Debug, Clone)]
pub struct X86DeducingThisDiag {
/// The diagnostic message.
pub message: String,
/// Whether this is an error (true) or warning (false).
pub is_error: bool,
}
impl X86DeducingThisParser {
pub fn new(enabled: bool) -> Self {
Self {
enabled,
diagnostics: Vec::new(),
}
}
/// Try to parse an explicit object parameter from the given text.
pub fn parse_param(&self, param_text: &str) -> Option<X86ExplicitObjectKind> {
if !self.enabled {
return None;
}
X86ExplicitObjectKind::from_param_str(param_text)
}
/// Validate that a function with an explicit object parameter is well-formed.
pub fn validate(&mut self, func: &X86ExplicitObjectFunction) -> bool {
if !self.enabled {
return false;
}
let mut valid = true;
// Cannot be a constructor, destructor, or have cv/ref qualifiers.
if func.name == func.class_name.as_deref().unwrap_or("") {
self.diagnostics.push(X86DeducingThisDiag {
message: "explicit object parameter cannot be used in a constructor".into(),
is_error: true,
});
valid = false;
}
// The explicit object parameter must be the first parameter.
// (This is structurally guaranteed by the AST at this level.)
if valid {
self.diagnostics.push(X86DeducingThisDiag {
message: format!("valid explicit object parameter function '{}'", func.name),
is_error: false,
});
}
valid
}
/// Deduce the `this` type from a call expression.
pub fn deduce_this_type(&self, func: &X86ExplicitObjectFunction, arg_is_lvalue: bool, arg_is_const: bool) -> String {
match func.kind {
X86ExplicitObjectKind::DeducedRef => {
if arg_is_const {
format!("{} const&", func.class_name.as_deref().unwrap_or("auto"))
} else if arg_is_lvalue {
format!("{}&", func.class_name.as_deref().unwrap_or("auto"))
} else {
format!("{}&&", func.class_name.as_deref().unwrap_or("auto"))
}
}
X86ExplicitObjectKind::DeducedLvalueRef => {
format!("{}&", func.class_name.as_deref().unwrap_or("auto"))
}
X86ExplicitObjectKind::DeducedByValue => {
func.class_name.as_deref().unwrap_or("auto").to_string()
}
X86ExplicitObjectKind::DeducedConstLvalueRef => {
format!("{} const&", func.class_name.as_deref().unwrap_or("auto"))
}
}
}
}
impl Default for X86DeducingThisParser {
fn default() -> Self {
Self::new(true)
}
}
// ── 3.4 Multidimensional Subscript Operator — P2128R6 ──
/// A multidimensional subscript operator declaration: `operator[](size_t i, size_t j)`.
#[derive(Debug, Clone)]
pub struct X86MultiDimSubscript {
/// Number of index parameters.
pub index_count: usize,
/// Types of the index parameters.
pub index_types: Vec<String>,
/// The return type of the subscript.
pub return_type: String,
/// Whether the operator is const-qualified.
pub is_const: bool,
/// Source line for diagnostics.
pub source_line: u32,
}
impl X86MultiDimSubscript {
pub fn new(index_types: Vec<String>, return_type: String, is_const: bool) -> Self {
let index_count = index_types.len();
Self {
index_count,
index_types,
return_type,
is_const,
source_line: 0,
}
}
/// Validate that this subscript operator is well-formed.
pub fn validate(&self) -> Result<(), String> {
if self.index_count == 0 {
return Err("multidimensional subscript requires at least one index parameter".into());
}
if self.index_count > 32 {
return Err("multidimensional subscript limited to 32 index parameters".into());
}
Ok(())
}
/// Generate the C++ call syntax for this subscript.
pub fn call_syntax(&self, object: &str, args: &[String]) -> String {
let indices = args.join(", ");
format!("{}[{indices}]", object, indices = indices)
}
/// Lower the multidimensional subscript to a regular function call.
pub fn lower_subscript(&self, object: &str, args: &[String]) -> String {
let indices = args.join(", ");
format!("{}.operator[]({indices})", object, indices = indices)
}
}
// ── 3.5 static operator() — P1169R4 ──
/// The kind of call operator.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86CallOperatorKind {
/// Non-const mutable call operator.
Mutable,
/// Const call operator.
Const,
/// Static call operator (P1169R4).
Static,
/// Call operator with explicit object parameter.
ExplicitObject,
}
impl fmt::Display for X86CallOperatorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Mutable => write!(f, "operator()"),
Self::Const => write!(f, "operator() const"),
Self::Static => write!(f, "static operator()"),
Self::ExplicitObject => write!(f, "operator(this auto&&)"),
}
}
}
/// A static `operator()` declaration.
#[derive(Debug, Clone)]
pub struct X86StaticOperatorCall {
/// The enclosing class name.
pub class_name: String,
/// The parameters.
pub params: Vec<X86FunctionParam>,
/// The return type.
pub return_type: String,
/// Whether this is a lambda.
pub is_lambda: bool,
/// Whether the lambda has captures.
pub has_captures: bool,
/// The kind of call operator.
pub kind: X86CallOperatorKind,
}
impl X86StaticOperatorCall {
pub fn new(
class_name: String,
params: Vec<X86FunctionParam>,
return_type: String,
is_lambda: bool,
has_captures: bool,
kind: X86CallOperatorKind,
) -> Self {
Self {
class_name,
params,
return_type,
is_lambda,
has_captures,
kind,
}
}
/// Validate the static operator() declaration.
pub fn validate(&self) -> Result<(), String> {
if self.kind == X86CallOperatorKind::Static && self.has_captures {
return Err("static operator() cannot have captures".into());
}
if self.kind == X86CallOperatorKind::Static && self.is_lambda && self.has_captures {
return Err("lambda with captures cannot have a static operator()".into());
}
Ok(())
}
/// Generate the mangled name for this operator.
pub fn mangled_name(&self) -> String {
match self.kind {
X86CallOperatorKind::Static => format!("_ZN{}clEv", self.class_name.len()),
X86CallOperatorKind::Const => format!("_ZNK{}clEv", self.class_name.len()),
_ => format!("_ZN{}clEv", self.class_name.len()),
}
}
}
// ── 3.6 auto(x) / auto{x} Decay Copy — P0849R8 ──
/// The kind of decay-copy expression.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86DecayCopyKind {
/// `auto(x)` — parenthesized decay-copy.
DecayCopyParen,
/// `auto{x}` — braced decay-copy.
DecayCopyBrace,
}
impl fmt::Display for X86DecayCopyKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::DecayCopyParen => write!(f, "auto()"),
Self::DecayCopyBrace => write!(f, "auto{{}}"),
}
}
}
/// A decay-copy expression: `auto(x)` or `auto{x}`.
#[derive(Debug, Clone)]
pub struct X86DecayCopyExpr {
/// Whether this is parenthesized or braced.
pub kind: X86DecayCopyKind,
/// The inner expression being decay-copied.
pub inner_expr: String,
/// The deduced type after decay.
pub deduced_type: String,
/// Whether the result is a prvalue.
pub is_prvalue: bool,
}
impl X86DecayCopyExpr {
pub fn new(kind: X86DecayCopyKind, inner_expr: String) -> Self {
Self {
kind,
inner_expr,
deduced_type: String::new(),
is_prvalue: true,
}
}
/// Emit the decay-copy as C++ source.
pub fn emit(&self) -> String {
match self.kind {
X86DecayCopyKind::DecayCopyParen => format!("auto({})", self.inner_expr),
X86DecayCopyKind::DecayCopyBrace => format!("auto{{{}}}", self.inner_expr),
}
}
/// Apply C++ decay rules to determine the resulting type.
pub fn apply_decay(&mut self, original_type: &str) {
self.deduced_type = if original_type.contains('&') {
// Reference types strip the reference and become prvalues
original_type.trim_end_matches('&')
.trim_end_matches("const ")
.trim_end_matches("volatile ")
.to_string()
} else if original_type.contains('[') {
// Array types decay to pointers
let base = original_type.split('[').next().unwrap_or(original_type);
format!("{}*", base.trim())
} else if original_type.ends_with("const") || original_type.ends_with("volatile") {
// Top-level cv-qualifiers are stripped
original_type
.trim_end_matches(" const")
.trim_end_matches(" volatile")
.to_string()
} else {
original_type.to_string()
};
}
}
/// Parser for `auto(x)` / `auto{x}` expressions.
#[derive(Debug, Clone, Default)]
pub struct X86DecayCopyParser {
/// Whether decay-copy is enabled.
pub enabled: bool,
}
impl X86DecayCopyParser {
pub fn new(enabled: bool) -> Self {
Self { enabled }
}
/// Try to parse a decay-copy expression. Returns `None` if not applicable.
pub fn try_parse(&self, source: &str) -> Option<X86DecayCopyExpr> {
if !self.enabled {
return None;
}
let trimmed = source.trim();
if let Some(inner) = trimmed.strip_prefix("auto(").and_then(|s| s.strip_suffix(')')) {
Some(X86DecayCopyExpr::new(X86DecayCopyKind::DecayCopyParen, inner.to_string()))
} else if let Some(inner) = trimmed.strip_prefix("auto{").and_then(|s| s.strip_suffix('}')) {
Some(X86DecayCopyExpr::new(X86DecayCopyKind::DecayCopyBrace, inner.to_string()))
} else {
None
}
}
}
// ── 3.7 #elifdef / #elifndef — P2334R1 ──
/// Conditional preprocessor directives including `#elifdef` and `#elifndef`.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86ElifConditional {
/// `#elif`
Elif,
/// `#elifdef MACRO`
Elifdef,
/// `#elifndef MACRO`
Elifndef,
}
impl X86ElifConditional {
/// Parse from a directive string.
pub fn from_directive(s: &str) -> Option<Self> {
match s {
"elif" | "#elif" => Some(Self::Elif),
"elifdef" | "#elifdef" => Some(Self::Elifdef),
"elifndef" | "#elifndef" => Some(Self::Elifndef),
_ => None,
}
}
/// Return the directive as a string.
pub fn as_str(&self) -> &'static str {
match self {
Self::Elif => "#elif",
Self::Elifdef => "#elifdef",
Self::Elifndef => "#elifndef",
}
}
}
/// A block in a conditional chain.
#[derive(Debug, Clone)]
pub struct X86ConditionalBlock {
/// The condition expression (macro name for `ifdef`/`elifdef`).
pub condition: String,
/// The type of conditional that started this block.
pub conditional_type: X86ElifConditional,
/// The body text of this block.
pub body: String,
/// Whether this branch was taken.
pub was_taken: bool,
}
/// A chain of conditional preprocessor blocks: `#if`, `#elif`, `#elifdef`, `#elifndef`, `#else`.
#[derive(Debug, Clone)]
pub struct X86ConditionalChain {
/// All blocks in the chain.
pub blocks: Vec<X86ConditionalBlock>,
/// Whether any branch was taken.
pub branch_taken: bool,
/// Whether we warned about a missing `#endif`.
pub warned_missing_endif: bool,
/// Whether `#elifdef`/`#elifndef` are enabled.
pub elifdef_enabled: bool,
}
impl X86ConditionalChain {
pub fn new(elifdef_enabled: bool) -> Self {
Self {
blocks: Vec::new(),
branch_taken: false,
warned_missing_endif: false,
elifdef_enabled,
}
}
/// Handle an `#ifdef MACRO` directive.
pub fn handle_ifdef(&mut self, macro_name: &str, is_defined: bool) {
let taken = is_defined && !self.branch_taken;
if taken {
self.branch_taken = true;
}
self.blocks.push(X86ConditionalBlock {
condition: macro_name.to_string(),
conditional_type: X86ElifConditional::Elif,
body: String::new(),
was_taken: taken,
});
}
/// Handle an `#ifndef MACRO` directive.
pub fn handle_ifndef(&mut self, macro_name: &str, is_defined: bool) {
let taken = !is_defined && !self.branch_taken;
if taken {
self.branch_taken = true;
}
self.blocks.push(X86ConditionalBlock {
condition: macro_name.to_string(),
conditional_type: X86ElifConditional::Elif,
body: String::new(),
was_taken: taken,
});
}
/// Handle an `#elifdef MACRO` directive.
pub fn handle_elifdef(&mut self, macro_name: &str, is_defined: bool) {
if !self.elifdef_enabled {
return;
}
let taken = is_defined && !self.branch_taken;
if taken {
self.branch_taken = true;
}
self.blocks.push(X86ConditionalBlock {
condition: macro_name.to_string(),
conditional_type: X86ElifConditional::Elifdef,
body: String::new(),
was_taken: taken,
});
}
/// Handle an `#elifndef MACRO` directive.
pub fn handle_elifndef(&mut self, macro_name: &str, is_defined: bool) {
if !self.elifdef_enabled {
return;
}
let taken = !is_defined && !self.branch_taken;
if taken {
self.branch_taken = true;
}
self.blocks.push(X86ConditionalBlock {
condition: macro_name.to_string(),
conditional_type: X86ElifConditional::Elifndef,
body: String::new(),
was_taken: taken,
});
}
/// Handle an `#else` directive.
pub fn handle_else(&mut self) {
let taken = !self.branch_taken;
if taken {
self.branch_taken = true;
}
self.blocks.push(X86ConditionalBlock {
condition: String::new(),
conditional_type: X86ElifConditional::Elif,
body: String::new(),
was_taken: taken,
});
}
/// Reset the chain for a new conditional block.
pub fn reset(&mut self) {
self.blocks.clear();
self.branch_taken = false;
self.warned_missing_endif = false;
}
}
impl Default for X86ConditionalChain {
fn default() -> Self {
Self::new(true)
}
}
// ── 3.8 #warning Directive — P2437R1 ──
/// A `#warning` preprocessor directive.
#[derive(Debug, Clone)]
pub struct X86WarningDirective {
/// The warning message.
pub message: String,
/// Source line number.
pub line: u32,
/// Source file name.
pub file: String,
}
impl X86WarningDirective {
pub fn new(message: String, line: u32, file: String) -> Self {
Self { message, line, file }
}
/// Format as a diagnostic message.
pub fn format_diagnostic(&self) -> String {
format!("{}:{}: warning: {}", self.file, self.line, self.message)
}
}
/// Handler for `#warning` directives.
#[derive(Debug, Clone)]
pub struct X86WarningDirectiveHandler {
/// Collected warnings.
pub warnings: Vec<X86WarningDirective>,
/// Whether to treat warnings as errors (`-Werror`).
pub treat_warnings_as_errors: bool,
/// Whether `#warning` is enabled as a standard directive.
pub enabled: bool,
}
impl X86WarningDirectiveHandler {
pub fn new(treat_warnings_as_errors: bool, enabled: bool) -> Self {
Self {
warnings: Vec::new(),
treat_warnings_as_errors,
enabled,
}
}
/// Handle a `#warning` directive. Returns `Err` if warnings are errors.
pub fn handle(&mut self, warning: X86WarningDirective) -> Result<(), String> {
if !self.enabled {
return Ok(());
}
let diag = warning.format_diagnostic();
self.warnings.push(warning);
if self.treat_warnings_as_errors {
Err(diag)
} else {
Ok(())
}
}
/// Whether any warnings were emitted.
pub fn has_warnings(&self) -> bool {
!self.warnings.is_empty()
}
}
impl Default for X86WarningDirectiveHandler {
fn default() -> Self {
Self::new(false, true)
}
}
// ── 3.9 Simpler Implicit Move — P2266R3 ──
/// Return statement that may trigger implicit move.
#[derive(Debug, Clone)]
pub struct X86ImplicitMoveReturn {
/// Whether implicit move is enabled (C++23).
pub enabled: bool,
/// The expression being returned.
pub return_expr: String,
/// The type of the returned expression.
pub return_type: String,
/// Whether the expression is eligible for implicit move.
pub eligible_for_move: bool,
}
impl X86ImplicitMoveReturn {
pub fn new(return_expr: String, return_type: String) -> Self {
Self {
enabled: true,
return_expr,
return_type,
eligible_for_move: false,
}
}
/// Determine whether implicit move applies.
///
/// In C++23, a `return expr;` where `expr` is an id-expression naming a
/// local variable or parameter of non-volatile automatic storage duration
/// triggers an implicit move.
pub fn apply_implicit_move(&mut self, local_var_names: &HashSet<String>) -> bool {
if !self.enabled {
return false;
}
// Check if the return expression is a simple variable name.
let trimmed = self.return_expr.trim();
let is_local = local_var_names.contains(trimmed);
let is_non_volatile = !self.return_type.contains("volatile");
if is_local && is_non_volatile {
self.eligible_for_move = true;
}
self.eligible_for_move
}
/// Generate the LLVM IR instruction for the implicit move.
pub fn generate_implicit_move(&self) -> String {
if self.eligible_for_move {
format!("%result = call i8* @llvm.move(i8* %{})", self.return_expr)
} else {
format!("%result = load {}, {}", self.return_type, self.return_expr)
}
}
}
// ── 3.10 Monadic Operations for std::optional — P0798R8 ──
/// Monadic operation kinds for `std::optional`.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86OptionalMonadicOp {
/// `opt.and_then(f)` — chain operations, returning optional.
AndThen,
/// `opt.or_else(f)` — provide fallback, returning optional.
OrElse,
/// `opt.transform(f)` — map the value, wrapping in optional.
Transform,
}
impl fmt::Display for X86OptionalMonadicOp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::AndThen => write!(f, "and_then"),
Self::OrElse => write!(f, "or_else"),
Self::Transform => write!(f, "transform"),
}
}
}
/// Monadic operations support for `std::optional<T>`.
#[derive(Debug, Clone)]
pub struct X86OptionalMonadic<T: Clone + fmt::Debug> {
/// The contained value type.
pub value_type: String,
/// Whether monadic operations are enabled (C++23).
pub monadic_enabled: bool,
_phantom: std::marker::PhantomData<T>,
}
impl<T: Clone + fmt::Debug> X86OptionalMonadic<T> {
pub fn new(value_type: String) -> Self {
Self {
value_type,
monadic_enabled: true,
_phantom: std::marker::PhantomData,
}
}
/// Return type for `and_then(f)`: `std::optional<U>` where `f: T -> std::optional<U>`.
pub fn and_then_return_type(&self, result_type: &str) -> String {
format!("std::optional<{}>", result_type)
}
/// Return type for `transform(f)`: `std::optional<U>` where `f: T -> U`.
pub fn transform_return_type(&self, result_type: &str) -> String {
format!("std::optional<{}>", result_type)
}
/// Return type for `or_else(f)`: `std::optional<T>`.
pub fn or_else_return_type(&self) -> String {
format!("std::optional<{}>", self.value_type)
}
/// Generate code for `opt.and_then(f)`.
pub fn codegen_and_then(&self, opt_var: &str, func_call: &str, _result_type: &str) -> String {
format!(
"if ({opt_var}.has_value()) {{ return {func_call}; }} else {{ return std::nullopt; }}",
opt_var = opt_var,
func_call = func_call
)
}
/// Generate code for `opt.or_else(f)`.
pub fn codegen_or_else(&self, opt_var: &str, func_call: &str) -> String {
format!(
"if ({opt_var}.has_value()) {{ return {opt_var}; }} else {{ return {func_call}; }}",
opt_var = opt_var,
func_call = func_call
)
}
/// Generate code for `opt.transform(f)`.
pub fn codegen_transform(&self, opt_var: &str, func_call: &str, result_type: &str) -> String {
format!(
"if ({opt_var}.has_value()) {{ return std::optional<{result_type}>({func_call}); }} else {{ return std::nullopt; }}",
opt_var = opt_var,
result_type = result_type,
func_call = func_call,
)
}
}
// ── 3.11 std::expected<T, E> — P0323R12 ──
/// Discriminant for the expected value/error union.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86ExpectedDiscriminant {
/// Holds a value.
HasValue,
/// Holds an error.
HasError,
}
/// Monadic operation kinds for `std::expected`.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86ExpectedMonadicOp {
/// Chain on success.
AndThen,
/// Fallback on error.
OrElse,
/// Map the value.
Transform,
/// Map the error.
TransformError,
}
impl fmt::Display for X86ExpectedMonadicOp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::AndThen => write!(f, "and_then"),
Self::OrElse => write!(f, "or_else"),
Self::Transform => write!(f, "transform"),
Self::TransformError => write!(f, "transform_error"),
}
}
}
/// Representation of `std::expected<T, E>` for code generation.
#[derive(Debug, Clone)]
pub struct X86ExpectedType {
/// The value type `T`.
pub value_type: String,
/// The error type `E`.
pub error_type: String,
/// Whether monadic operations are enabled (C++23).
pub monadic_enabled: bool,
/// Whether `void` is allowed as either T or E.
pub allow_void: bool,
}
impl X86ExpectedType {
pub fn new(value_type: String, error_type: String) -> Self {
Self {
value_type,
error_type,
monadic_enabled: true,
allow_void: true,
}
}
/// Validate the expected type parameters.
pub fn validate(&self) -> Result<(), String> {
if self.error_type == "void" && !self.allow_void {
return Err("std::expected<T, void> is ill-formed".into());
}
if self.error_type.is_empty() {
return Err("std::expected requires a non-empty error type".into());
}
Ok(())
}
/// Return type for `and_then(f)`: `std::expected<U, E>`.
pub fn and_then_return_type(&self, result_value_type: &str) -> String {
format!("std::expected<{}, {}>", result_value_type, self.error_type)
}
/// Return type for `transform(f)`: `std::expected<U, E>`.
pub fn transform_return_type(&self, result_value_type: &str) -> String {
format!("std::expected<{}, {}>", result_value_type, self.error_type)
}
/// Return type for `transform_error(f)`: `std::expected<T, NewE>`.
pub fn transform_error_return_type(&self, result_error_type: &str) -> String {
format!("std::expected<{}, {}>", self.value_type, result_error_type)
}
/// Return type for `or_else(f)`: `std::expected<T, E>`.
pub fn or_else_return_type(&self) -> String {
format!("std::expected<{}, {}>", self.value_type, self.error_type)
}
/// Union-based codegen: `union { T value; E error; }; bool has_value;`
pub fn union_layout(&self) -> String {
format!(
"union {{ {} value; {} error; }}; bool has_value;",
self.value_type, self.error_type
)
}
}
/// An `std::expected` value, either Ok or Err.
#[derive(Debug, Clone)]
pub enum X86ExpectedValue<T: Clone, E: Clone> {
Ok(T),
Err(E),
}
impl<T: Clone, E: Clone> X86ExpectedValue<T, E> {
pub fn is_ok(&self) -> bool {
matches!(self, Self::Ok(_))
}
pub fn is_err(&self) -> bool {
matches!(self, Self::Err(_))
}
pub fn map<U: Clone>(&self, f: impl FnOnce(&T) -> U) -> X86ExpectedValue<U, E> {
match self {
Self::Ok(v) => X86ExpectedValue::Ok(f(v)),
Self::Err(e) => X86ExpectedValue::Err(e.clone()),
}
}
pub fn and_then<U: Clone>(&self, f: impl FnOnce(&T) -> X86ExpectedValue<U, E>) -> X86ExpectedValue<U, E> {
match self {
Self::Ok(v) => f(v),
Self::Err(e) => X86ExpectedValue::Err(e.clone()),
}
}
pub fn or_else(&self, f: impl FnOnce(&E) -> X86ExpectedValue<T, E>) -> X86ExpectedValue<T, E> {
match self {
Self::Ok(v) => X86ExpectedValue::Ok(v.clone()),
Self::Err(e) => f(e),
}
}
}
// ── 3.12 std::mdspan — P0009R18 ──
/// Layout policy for `std::mdspan`.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86MdspanLayout {
/// Row-major layout: rightmost extent is stride-1.
LayoutRight,
/// Column-major layout: leftmost extent is stride-1.
LayoutLeft,
/// Custom strided layout.
LayoutStride,
}
impl X86MdspanLayout {
pub fn to_cpp(&self) -> &'static str {
match self {
Self::LayoutRight => "std::layout_right",
Self::LayoutLeft => "std::layout_left",
Self::LayoutStride => "std::layout_stride",
}
}
pub fn is_strided(&self) -> bool {
matches!(self, Self::LayoutStride)
}
}
/// Accessor policy for `std::mdspan`.
#[derive(Debug, Clone)]
pub enum X86MdspanAccessor {
/// Default accessor.
DefaultAccessor,
/// Custom accessor name.
Custom(String),
}
impl X86MdspanAccessor {
pub fn to_cpp(&self) -> String {
match self {
Self::DefaultAccessor => "std::default_accessor".to_string(),
Self::Custom(name) => name.clone(),
}
}
}
/// A multidimensional span descriptor.
#[derive(Debug, Clone)]
pub struct X86Mdspan {
/// Element type.
pub element_type: String,
/// Rank (number of dimensions).
pub rank: usize,
/// Extents (static or dynamic).
pub extents: Vec<X86MdspanExtent>,
/// Layout policy.
pub layout: X86MdspanLayout,
/// Accessor policy.
pub accessor: X86MdspanAccessor,
/// Pointer to data.
pub data_ptr: String,
}
/// An extent for an mdspan dimension.
#[derive(Debug, Clone)]
pub enum X86MdspanExtent {
/// Static extent known at compile time.
Static(usize),
/// Dynamic extent determined at runtime.
Dynamic,
}
impl X86MdspanExtent {
pub fn to_cpp(&self) -> String {
match self {
Self::Static(n) => n.to_string(),
Self::Dynamic => "std::dynamic_extent".to_string(),
}
}
}
impl X86Mdspan {
pub fn new(element_type: String, extents: Vec<X86MdspanExtent>) -> Self {
let rank = extents.len();
Self {
element_type,
rank,
extents,
layout: X86MdspanLayout::LayoutRight,
accessor: X86MdspanAccessor::DefaultAccessor,
data_ptr: String::new(),
}
}
/// Set the layout policy.
pub fn with_layout(mut self, layout: X86MdspanLayout) -> Self {
self.layout = layout;
self
}
/// Set the accessor policy.
pub fn with_accessor(mut self, accessor: X86MdspanAccessor) -> Self {
self.accessor = accessor;
self
}
/// Generate the C++ type for this mdspan.
pub fn type_decl(&self) -> String {
let extents_str: Vec<String> = self.extents.iter().map(|e| e.to_cpp()).collect();
format!(
"std::mdspan<{}, std::extents<{}>, {}, {}>",
self.element_type,
extents_str.join(", "),
self.layout.to_cpp(),
self.accessor.to_cpp()
)
}
/// Generate the IR for element access with X86 lowering.
pub fn lower_element_access(&self, indices: &[usize]) -> String {
let strides = self.compute_strides();
let offset: usize = indices.iter().zip(strides.iter()).map(|(i, s)| i * s).sum();
format!(
"getelementptr inbounds {}, {}* {}, i64 {}",
self.element_type, self.element_type, self.data_ptr, offset
)
}
/// Compute strides for the current layout.
pub fn compute_strides(&self) -> Vec<usize> {
match self.layout {
X86MdspanLayout::LayoutRight => {
// Row-major: stride[i] = product of extents[i+1..]
let mut strides = vec![1usize; self.rank];
for i in (0..self.rank - 1).rev() {
let next_extent = match &self.extents[i + 1] {
X86MdspanExtent::Static(n) => *n,
X86MdspanExtent::Dynamic => 1, // Placeholder for dynamic
};
strides[i] = strides[i + 1] * next_extent;
}
strides
}
X86MdspanLayout::LayoutLeft => {
// Column-major: stride[i] = product of extents[0..i]
let mut strides = vec![1usize; self.rank];
for i in 1..self.rank {
let prev_extent = match &self.extents[i - 1] {
X86MdspanExtent::Static(n) => *n,
X86MdspanExtent::Dynamic => 1,
};
strides[i] = strides[i - 1] * prev_extent;
}
strides
}
X86MdspanLayout::LayoutStride => {
// For layout_stride, strides are explicitly provided; return 1 as placeholder.
vec![1usize; self.rank]
}
}
}
}
// ── 3.13 std::flat_map / std::flat_set — P0429R9 ──
/// Configuration for a `std::flat_map` container.
#[derive(Debug, Clone)]
pub struct X86FlatMap {
/// Key type.
pub key_type: String,
/// Value type.
pub value_type: String,
/// Key comparison function type.
pub compare: String,
/// The underlying container type (usually `std::vector`).
pub container_type: String,
}
impl X86FlatMap {
pub fn new(key_type: String, value_type: String) -> Self {
Self {
key_type,
value_type,
compare: "std::less".to_string(),
container_type: "std::vector".to_string(),
}
}
/// Generate the C++ type declaration.
pub fn type_decl(&self) -> String {
format!(
"std::flat_map<{}, {}, std::less<{}>, {}<std::pair<const {}, {}>{}>",
self.key_type,
self.value_type,
self.key_type,
self.container_type,
self.key_type,
self.value_type,
if self.container_type == "std::vector" { "" } else { "" },
)
}
/// The sorted vector representation: key-value pairs sorted by key.
pub fn underlying_layout(&self) -> String {
format!(
"{}<std::pair<{}, {}>>",
self.container_type, self.key_type, self.value_type
)
}
}
/// Configuration for `std::flat_set`.
#[derive(Debug, Clone)]
pub struct X86FlatSet {
/// Element type.
pub element_type: String,
/// Comparison function type.
pub compare: String,
/// The underlying container type.
pub container_type: String,
}
impl X86FlatSet {
pub fn new(element_type: String) -> Self {
Self {
element_type,
compare: "std::less".to_string(),
container_type: "std::vector".to_string(),
}
}
/// Generate the C++ type declaration.
pub fn type_decl(&self) -> String {
format!(
"std::flat_set<{}, std::less<{}>, {}<{}>>",
self.element_type,
self.element_type,
self.container_type,
self.element_type,
)
}
}
// ── 3.14 std::print / std::println — P2093R14 ──
/// Formatted output support modeled after `fmt::print`.
#[derive(Debug, Clone)]
pub struct X86FormattedPrint {
/// Whether `std::print`/`std::println` is available.
pub enabled: bool,
/// Whether to use Unicode-aware output.
pub unicode: bool,
/// Target output stream.
pub output: X86PrintOutput,
}
/// Print output destination.
#[derive(Debug, Clone)]
pub enum X86PrintOutput {
/// Standard output.
Stdout,
/// Standard error.
Stderr,
/// Custom FILE* stream.
File(String),
}
impl X86FormattedPrint {
pub fn new(enabled: bool) -> Self {
Self {
enabled,
unicode: true,
output: X86PrintOutput::Stdout,
}
}
/// Generate the call to `std::print`.
pub fn generate_print(&self, format_str: &str, args: &[String]) -> String {
if !self.enabled {
return format!("printf({:?}, {});", format_str, args.join(", "));
}
let file_arg = match &self.output {
X86PrintOutput::Stdout => "stdout".to_string(),
X86PrintOutput::Stderr => "stderr".to_string(),
X86PrintOutput::File(f) => f.clone(),
};
format!(
"std::print({file}, {:?}{});",
format_str,
if args.is_empty() {
String::new()
} else {
format!(", {}", args.join(", "))
},
file = file_arg
)
}
/// Generate the call to `std::println`.
pub fn generate_println(&self, format_str: &str, args: &[String]) -> String {
if !self.enabled {
return format!("printf({:?}\\n, {});", format_str, args.join(", "));
}
let file_arg = match &self.output {
X86PrintOutput::Stdout => "stdout".to_string(),
X86PrintOutput::Stderr => "stderr".to_string(),
X86PrintOutput::File(f) => f.clone(),
};
format!(
"std::println({file}, {:?}{});",
format_str,
if args.is_empty() {
String::new()
} else {
format!(", {}", args.join(", "))
},
file = file_arg,
)
}
}
// ── 3.15 std::generator<T> — P2502R2 ──
/// Coroutine generator `std::generator<T>`.
#[derive(Debug, Clone)]
pub struct X86Generator {
/// The yielded value type.
pub value_type: String,
/// The coroutine frame layout.
pub frame: X86CoroutineFrame,
/// Promise type descriptor.
pub promise: X86PromiseType,
}
/// Coroutine frame layout for X86.
#[derive(Debug, Clone)]
pub struct X86CoroutineFrame {
/// Frame size in bytes.
pub frame_size: usize,
/// Frame alignment.
pub alignment: usize,
/// Resume point index.
pub resume_index: usize,
/// Destroy point index.
pub destroy_index: usize,
/// Whether frame is allocated on the heap.
pub heap_allocated: bool,
/// Number of local variables stored in the frame.
pub local_count: usize,
}
/// Promise type descriptor for coroutines.
#[derive(Debug, Clone)]
pub struct X86PromiseType {
/// Promise type name.
pub type_name: String,
/// Whether `yield_value` is defined.
pub has_yield_value: bool,
/// Whether `return_void` is used.
pub return_void: bool,
/// Whether `unhandled_exception` is defined.
pub has_unhandled_exception: bool,
}
impl X86Generator {
pub fn new(value_type: String) -> Self {
let promise_type_name = format!("std::generator<{}>::promise_type", value_type);
Self {
value_type,
frame: X86CoroutineFrame {
frame_size: 64,
alignment: 16,
resume_index: 0,
destroy_index: 1,
heap_allocated: true,
local_count: 0,
},
promise: X86PromiseType {
type_name: promise_type_name,
has_yield_value: true,
return_void: true,
has_unhandled_exception: true,
},
}
}
/// Generate the C++ type declaration for the generator.
pub fn type_decl(&self) -> String {
format!("std::generator<{}>", self.value_type)
}
/// Generate the coroutine frame type for LLVM IR.
pub fn frame_type_decl(&self) -> String {
format!(
"%generator.frame.{}.{} = type {{ i32, i32, i8*, {} }}",
self.value_type,
self.frame.frame_size,
self.promise.type_name,
)
}
/// Lower `co_yield val` to IR.
pub fn lower_co_yield(&self, value_var: &str) -> String {
format!(
"call void @llvm.coro.yield({} %{}, i1 false)",
self.value_type, value_var
)
}
}
// ── 3.16 std::views — Range adaptors (C++23) ──
/// All C++23 range view adaptor kinds.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum X86RangeViewAdaptor {
/// `std::views::zip(r1, r2, ...)` — zip multiple ranges.
Zip,
/// `std::views::zip_transform(f, r1, r2, ...)` — zip with transform.
ZipTransform,
/// `std::views::adjacent<N>(r)` — sliding window of N elements.
Adjacent,
/// `std::views::adjacent_transform<N>(f, r)` — adjacent with transform.
AdjacentTransform,
/// `std::views::cartesian_product(r1, r2, ...)` — Cartesian product.
CartesianProduct,
/// `std::views::enumerate(r)` — attach indices.
Enumerate,
/// `std::views::as_const(r)` — view elements as const.
AsConst,
/// `std::views::as_rvalue(r)` — view elements as rvalue references.
AsRvalue,
/// `std::views::repeat(v, n?)` — repeat a value.
Repeat,
/// `std::views::stride(r, n)` — take every n-th element.
Stride,
/// `std::views::slide(r, n)` — sliding window of n elements.
Slide,
/// `std::views::chunk(r, n)` — chunk into subranges of n elements.
Chunk,
/// `std::views::chunk_by(r, pred)` — chunk by predicate.
ChunkBy,
/// `std::views::join_with(r, delim)` — join with delimiter.
JoinWith,
/// `std::views::iota(start, end?)` — incremental range.
Iota,
}
impl X86RangeViewAdaptor {
/// Return the C++ name of the view adaptor.
pub fn name(&self) -> &'static str {
match self {
Self::Zip => "zip",
Self::ZipTransform => "zip_transform",
Self::Adjacent => "adjacent",
Self::AdjacentTransform => "adjacent_transform",
Self::CartesianProduct => "cartesian_product",
Self::Enumerate => "enumerate",
Self::AsConst => "as_const",
Self::AsRvalue => "as_rvalue",
Self::Repeat => "repeat",
Self::Stride => "stride",
Self::Slide => "slide",
Self::Chunk => "chunk",
Self::ChunkBy => "chunk_by",
Self::JoinWith => "join_with",
Self::Iota => "iota",
}
}
/// Return the `<ranges>` header needed for this adaptor.
pub fn header(&self) -> &'static str {
"<ranges>"
}
}
/// Configuration for a specific range view.
#[derive(Debug, Clone)]
pub struct X86RangeViewConfig {
/// The adaptor being used.
pub adaptor: X86RangeViewAdaptor,
/// The element type of the resulting view.
pub element_type: String,
/// Whether the view is const-iterable.
pub is_const: bool,
/// Whether the view is sized.
pub is_sized: bool,
/// Whether the view is borrowed (iterators don't dangle).
pub is_borrowed: bool,
/// Whether the view is common (begin == end type).
pub is_common: bool,
}
impl X86RangeViewConfig {
pub fn new(adaptor: X86RangeViewAdaptor, element_type: String) -> Self {
let (is_sized, is_borrowed, is_common) = match adaptor {
X86RangeViewAdaptor::Zip => (false, false, true),
X86RangeViewAdaptor::ZipTransform => (false, false, false),
X86RangeViewAdaptor::Adjacent => (true, false, true),
X86RangeViewAdaptor::AdjacentTransform => (true, false, true),
X86RangeViewAdaptor::CartesianProduct => (false, false, true),
X86RangeViewAdaptor::Enumerate => (true, false, true),
X86RangeViewAdaptor::AsConst => (true, true, true),
X86RangeViewAdaptor::AsRvalue => (true, true, true),
X86RangeViewAdaptor::Repeat => (false, true, true),
X86RangeViewAdaptor::Stride => (true, false, true),
X86RangeViewAdaptor::Slide => (true, false, true),
X86RangeViewAdaptor::Chunk => (false, false, false),
X86RangeViewAdaptor::ChunkBy => (false, false, false),
X86RangeViewAdaptor::JoinWith => (false, false, true),
X86RangeViewAdaptor::Iota => (true, false, true),
};
Self {
adaptor,
element_type,
is_const: false,
is_sized,
is_borrowed,
is_common,
}
}
}
/// Iterator for a zip view.
#[derive(Debug, Clone)]
pub struct X86ZipIterator {
/// Number of ranges being zipped.
pub ranges_count: usize,
/// Value types of the ranges.
pub value_types: Vec<String>,
}
impl X86ZipIterator {
pub fn new(ranges_count: usize, value_types: Vec<String>) -> Self {
Self {
ranges_count,
value_types,
}
}
/// The dereference type: a tuple of references.
pub fn deref_type(&self) -> String {
let refs: Vec<String> = self.value_types.iter().map(|t| format!("{}&", t)).collect();
format!("std::tuple<{}>", refs.join(", "))
}
}
/// Iterator for an enumerated view.
#[derive(Debug, Clone)]
pub struct X86EnumerateIterator {
/// Value type of the underlying range.
pub value_type: String,
/// Index type (typically `std::size_t`).
pub index_type: String,
}
impl X86EnumerateIterator {
pub fn new(value_type: String) -> Self {
Self {
value_type,
index_type: "std::size_t".to_string(),
}
}
/// The element type: a pair of (index, value).
pub fn element_type(&self) -> String {
format!("std::tuple<{}, {}&>", self.index_type, self.value_type)
}
}
/// View for chunking a range.
#[derive(Debug, Clone)]
pub struct X86ChunkView {
/// The chunk size.
pub chunk_size: usize,
/// The element type of the underlying range.
pub element_type: String,
}
impl X86ChunkView {
pub fn new(chunk_size: usize, element_type: String) -> Self {
Self {
chunk_size,
element_type,
}
}
/// The inner range type of each chunk.
pub fn inner_range_type(&self) -> String {
format!("std::ranges::take_view<std::ranges::ref_view<{}>>", self.element_type)
}
}
/// View for Cartesian product.
#[derive(Debug, Clone)]
pub struct X86CartesianProductView {
/// First range element type.
pub first_type: String,
/// Second range element type.
pub second_type: String,
}
impl X86CartesianProductView {
pub fn new(first_type: String, second_type: String) -> Self {
Self {
first_type,
second_type,
}
}
/// The element type: a tuple of both types.
pub fn element_type(&self) -> String {
format!("std::tuple<{}, {}>", self.first_type, self.second_type)
}
}
/// Registry of all X86 range view adaptors.
#[derive(Debug, Clone)]
pub struct X86RangesAdaptorRegistry {
/// Registered adaptors.
pub adaptors: HashMap<X86RangeViewAdaptor, String>,
}
impl X86RangesAdaptorRegistry {
pub fn new() -> Self {
let mut adaptors = HashMap::new();
for a in &[
X86RangeViewAdaptor::Zip,
X86RangeViewAdaptor::ZipTransform,
X86RangeViewAdaptor::Adjacent,
X86RangeViewAdaptor::AdjacentTransform,
X86RangeViewAdaptor::CartesianProduct,
X86RangeViewAdaptor::Enumerate,
X86RangeViewAdaptor::AsConst,
X86RangeViewAdaptor::AsRvalue,
X86RangeViewAdaptor::Repeat,
X86RangeViewAdaptor::Stride,
X86RangeViewAdaptor::Slide,
X86RangeViewAdaptor::Chunk,
X86RangeViewAdaptor::ChunkBy,
X86RangeViewAdaptor::JoinWith,
X86RangeViewAdaptor::Iota,
] {
adaptors.insert(*a, a.name().to_string());
}
Self { adaptors }
}
/// Look up an adaptor.
pub fn lookup(&self, name: &str) -> Option<X86RangeViewAdaptor> {
self.adaptors.iter().find_map(|(k, v)| if v == name { Some(*k) } else { None })
}
/// Check if a given name is an adaptor.
pub fn is_adaptor(&self, name: &str) -> bool {
self.adaptors.values().any(|v| v == name)
}
/// Return all adaptor names.
pub fn adaptor_names(&self) -> Vec<&String> {
self.adaptors.values().collect()
}
/// Number of registered adaptors.
pub fn count(&self) -> usize {
self.adaptors.len()
}
}
impl Default for X86RangesAdaptorRegistry {
fn default() -> Self {
Self::new()
}
}
// ── 3.17 std::ranges::to<T> — P1206R7 ──
/// Range conversion via `std::ranges::to<T>()`.
#[derive(Debug, Clone)]
pub struct X86RangesTo {
/// Whether `ranges::to` is enabled.
pub enabled: bool,
/// The target container type.
pub target_type: String,
/// The source range type.
pub source_type: String,
}
impl X86RangesTo {
pub fn new(target_type: String, source_type: String) -> Self {
Self {
enabled: true,
target_type,
source_type,
}
}
/// Generate the conversion call.
pub fn generate(&self) -> String {
format!(
"std::ranges::to<{}>({})",
self.target_type, self.source_type
)
}
}
// ── 3.18 Range algorithm improvements (C++23) ──
/// C++23 range algorithm enhancements.
#[derive(Debug, Clone)]
pub struct X86RangeAlgorithms {
/// Whether C++23 range algorithms are enabled.
pub enabled: bool,
}
impl X86RangeAlgorithms {
pub fn new() -> Self {
Self { enabled: true }
}
/// `std::ranges::contains(r, val)`.
pub fn contains(&self, range: &str, value: &str) -> String {
format!("std::ranges::contains({}, {})", range, value)
}
/// `std::ranges::starts_with(r, prefix)`.
pub fn starts_with(&self, range: &str, prefix: &str) -> String {
format!("std::ranges::starts_with({}, {})", range, prefix)
}
/// `std::ranges::ends_with(r, suffix)`.
pub fn ends_with(&self, range: &str, suffix: &str) -> String {
format!("std::ranges::ends_with({}, {})", range, suffix)
}
/// `std::ranges::find_last(r, val)`.
pub fn find_last(&self, range: &str, value: &str) -> String {
format!("std::ranges::find_last({}, {})", range, value)
}
/// `std::ranges::iota(r, start)` — fill with incremental values.
pub fn iota(&self, range: &str, start: &str) -> String {
format!("std::ranges::iota({}, {})", range, start)
}
}
impl Default for X86RangeAlgorithms {
fn default() -> Self {
Self::new()
}
}
// ── 3.19 DR20: Parenthesized Aggregate Initialization — P0960R3 ──
/// Support for parenthesized aggregate initialization: `T t(a, b, c)`.
#[derive(Debug, Clone)]
pub struct X86ParenAggregateInit {
/// Whether parenthesized aggregate init is enabled.
pub enabled: bool,
/// The aggregate type.
pub aggregate_type: String,
/// The initializer arguments.
pub args: Vec<String>,
}
impl X86ParenAggregateInit {
pub fn new(aggregate_type: String, args: Vec<String>) -> Self {
Self {
enabled: true,
aggregate_type,
args,
}
}
/// Generate the parenthesized aggregate initialization.
pub fn generate(&self) -> String {
let args_str = self.args.join(", ");
format!("{} t({args_str})", self.aggregate_type, args_str = args_str)
}
/// Validate that the aggregate can be initialized this way.
pub fn validate(&self, member_count: usize) -> Result<(), String> {
if self.args.len() > member_count {
return Err(format!(
"too many initializers for aggregate '{}': expected {} but got {}",
self.aggregate_type,
member_count,
self.args.len()
));
}
Ok(())
}
}
// ═══════════════════════════════════════════════════════════════════════════════
// 4. C++26 Features — Preview Implementations
// ═══════════════════════════════════════════════════════════════════════════════
// ── 4.1 Pack Indexing — P2662R3 ──
/// Pack indexing support: `args...[0]` to access parameter pack elements.
#[derive(Debug, Clone)]
pub struct X86PackIndexing {
/// Whether pack indexing is enabled.
pub enabled: bool,
/// The pack name.
pub pack_name: String,
/// The element type of the pack.
pub element_type: String,
/// The pack size (if known at compile time).
pub size: Option<usize>,
}
impl X86PackIndexing {
pub fn new(pack_name: String, element_type: String) -> Self {
Self {
enabled: true,
pack_name,
element_type,
size: None,
}
}
/// Generate a pack indexing expression: `args...[i]`.
pub fn generate_index(&self, index: usize) -> String {
format!("{}...[{}]", self.pack_name, index)
}
/// Generate a pack slice: `args...[0..N]`.
pub fn generate_slice(&self, start: usize, end: usize) -> String {
format!("{}...[{}..{}]", self.pack_name, start, end)
}
/// Validate that an index is within bounds.
pub fn validate_index(&self, index: usize) -> Result<(), String> {
if let Some(size) = self.size {
if index >= size {
return Err(format!(
"pack index {} out of bounds for pack '{}' of size {}",
index, self.pack_name, size
));
}
}
Ok(())
}
}
// ── 4.2 Placeholder Variables (Unnamed) — P2169R4 ──
/// Support for unnamed placeholder variables: `auto _ = f();`.
#[derive(Debug, Clone)]
pub struct X86UnnamedPlaceholder {
/// Whether unnamed placeholders are enabled.
pub enabled: bool,
/// The current count of unnamed placeholders in scope.
pub count: u32,
}
impl X86UnnamedPlaceholder {
pub fn new(enabled: bool) -> Self {
Self { enabled, count: 0 }
}
/// Generate a unique internal name for the unnamed placeholder.
pub fn generate_name(&mut self) -> String {
self.count += 1;
format!("__unnamed_placeholder_{}", self.count)
}
/// Whether an identifier `_` should be treated as an unnamed placeholder.
pub fn is_placeholder(&self, name: &str) -> bool {
self.enabled && name == "_"
}
}
impl Default for X86UnnamedPlaceholder {
fn default() -> Self {
Self::new(true)
}
}
// ── 4.3 constexpr Placement New — P2747R2 ──
/// Compile-time dynamic allocation via placement new.
#[derive(Debug, Clone)]
pub struct X86ConstexprPlacementNew {
/// Whether constexpr placement new is enabled.
pub enabled: bool,
/// Compile-time allocator tracking.
pub allocator: X86ConstexprAllocator,
}
/// A compile-time allocation record.
#[derive(Debug, Clone)]
pub struct X86ConstexprAllocation {
/// Virtual address of the allocation (for tracking purposes).
pub address: usize,
/// Size of the allocation in bytes.
pub size: usize,
/// Alignment of the allocation.
pub alignment: usize,
/// Whether the allocation has been deallocated.
pub deallocated: bool,
/// The type constructed at this address.
pub constructed_type: String,
}
impl X86ConstexprAllocation {
pub fn new(address: usize, size: usize, alignment: usize) -> Self {
Self {
address,
size,
alignment,
deallocated: false,
constructed_type: String::new(),
}
}
/// Whether the allocation is properly aligned.
pub fn is_aligned(&self) -> bool {
self.address % self.alignment == 0
}
/// Mark as deallocated.
pub fn deallocate(&mut self) {
self.deallocated = true;
}
/// Generate a placement new expression.
pub fn generate_placement_new(&self, type_name: &str) -> String {
format!(
"new (reinterpret_cast<void*>({})) {}(...);",
self.address, type_name
)
}
}
/// Compile-time allocator for `constexpr` dynamic memory.
#[derive(Debug, Clone)]
pub struct X86ConstexprAllocator {
/// Active allocations.
pub allocations: Vec<X86ConstexprAllocation>,
/// Total bytes allocated so far.
pub total_allocated: usize,
/// Total bytes deallocated so far.
pub total_deallocated: usize,
/// Whether any leaks were detected.
pub leak_detected: bool,
/// Next virtual address to assign.
next_address: usize,
}
impl X86ConstexprAllocator {
pub fn new() -> Self {
Self {
allocations: Vec::new(),
total_allocated: 0,
total_deallocated: 0,
leak_detected: false,
next_address: 0x1000,
}
}
/// Allocate memory at compile time.
pub fn allocate(&mut self, size: usize, alignment: usize) -> X86ConstexprAllocation {
// Align the address.
let addr = (self.next_address + alignment - 1) & !(alignment - 1);
self.next_address = addr + size;
self.total_allocated += size;
let alloc = X86ConstexprAllocation::new(addr, size, alignment);
self.allocations.push(alloc.clone());
alloc
}
/// Deallocate memory at compile time.
pub fn deallocate(&mut self, address: usize) -> Result<(), String> {
for alloc in &mut self.allocations {
if alloc.address == address && !alloc.deallocated {
alloc.deallocate();
self.total_deallocated += alloc.size;
return Ok(());
}
}
Err(format!(
"constexpr deallocation error: no active allocation at address {:#x}",
address
))
}
/// Check for memory leaks.
pub fn check_leaks(&self) -> bool {
self.allocations.iter().any(|a| !a.deallocated)
}
/// Whether the allocator is sound (no leaks, all alignments correct).
pub fn is_sound(&self) -> bool {
!self.leak_detected
&& !self.check_leaks()
&& self.allocations.iter().all(|a| a.is_aligned())
&& self.total_allocated == self.total_deallocated
}
/// Return the current number of active allocations.
pub fn currently_allocated(&self) -> usize {
self.allocations.iter().filter(|a| !a.deallocated).count()
}
}
impl Default for X86ConstexprAllocator {
fn default() -> Self {
Self::new()
}
}
impl X86ConstexprPlacementNew {
pub fn new(enabled: bool) -> Self {
Self {
enabled,
allocator: X86ConstexprAllocator::new(),
}
}
}
// ── 4.4 User-Generated static_assert Messages — P2741R3 ──
/// User-generated `static_assert` with `string_view` messages.
#[derive(Debug, Clone)]
pub struct X86UserStaticAssert {
/// Whether user-generated messages are enabled.
pub enabled: bool,
/// The condition expression.
pub condition: String,
/// The message (can be a `string_view`).
pub message: String,
/// Whether the message is a compile-time string.
pub is_ct_string: bool,
}
impl X86UserStaticAssert {
pub fn new(condition: String, message: String) -> Self {
Self {
enabled: true,
condition,
message,
is_ct_string: true,
}
}
/// Generate the `static_assert` declaration.
pub fn generate(&self) -> String {
if self.is_ct_string {
format!(
"static_assert({}, std::string_view{{\"{}\"}});",
self.condition, self.message
)
} else {
format!("static_assert({}, \"{}\");", self.condition, self.message)
}
}
}
// ── 4.5 Deleting pointer to incomplete type — diagnostic ──
/// Diagnostic check for deleting a pointer to an incomplete type.
#[derive(Debug, Clone)]
pub struct X86IncompleteDeleteCheck {
/// Whether the diagnostic is enabled.
pub enabled: bool,
}
impl X86IncompleteDeleteCheck {
pub fn new() -> Self {
Self { enabled: true }
}
/// Check whether `delete p` where `p` points to an incomplete type is well-formed.
/// Returns an error if the type is incomplete.
pub fn check(&self, type_name: &str, is_complete: bool) -> Result<(), String> {
if !is_complete && self.enabled {
return Err(format!(
"cannot delete pointer to incomplete type '{}'",
type_name
));
}
Ok(())
}
}
impl Default for X86IncompleteDeleteCheck {
fn default() -> Self {
Self::new()
}
}
// ── 4.6 std::inplace_vector<T, N> — P0843R8 ──
/// A fixed-capacity, stack-allocated vector.
#[derive(Debug, Clone)]
pub struct X86InplaceVector<T: Clone + fmt::Debug> {
/// Fixed capacity.
pub capacity: usize,
/// Current size.
pub size: usize,
/// Elements stored inline.
pub elements: Vec<Option<T>>,
}
impl<T: Clone + fmt::Debug> X86InplaceVector<T> {
pub fn new(capacity: usize) -> Self {
Self {
capacity,
size: 0,
elements: vec![None; capacity],
}
}
/// Push an element to the back. Returns `Err` if full.
pub fn push_back(&mut self, value: T) -> Result<(), String> {
if self.size >= self.capacity {
return Err("inplace_vector is full".into());
}
self.elements[self.size] = Some(value);
self.size += 1;
Ok(())
}
/// Pop an element from the back. Returns `None` if empty.
pub fn pop_back(&mut self) -> Option<T> {
if self.size == 0 {
return None;
}
self.size -= 1;
self.elements[self.size].take()
}
/// Get a reference to an element at `index`.
pub fn get(&self, index: usize) -> Option<&T> {
self.elements.get(index).and_then(|opt| opt.as_ref())
}
/// Get a mutable reference to an element at `index`.
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
self.elements.get_mut(index).and_then(|opt| opt.as_mut())
}
/// Clear all elements.
pub fn clear(&mut self) {
for i in 0..self.size {
self.elements[i] = None;
}
self.size = 0;
}
/// Whether the vector is empty.
pub fn is_empty(&self) -> bool {
self.size == 0
}
/// Whether the vector is full.
pub fn is_full(&self) -> bool {
self.size >= self.capacity
}
/// Insert an element at `index`. Shifts subsequent elements right.
pub fn insert(&mut self, index: usize, value: T) -> Result<(), String> {
if self.size >= self.capacity {
return Err("inplace_vector is full".into());
}
if index > self.size {
return Err("insert index out of bounds".into());
}
for i in (index..self.size).rev() {
self.elements[i + 1] = self.elements[i].take();
}
self.elements[index] = Some(value);
self.size += 1;
Ok(())
}
/// Erase an element at `index`. Shifts subsequent elements left.
pub fn erase(&mut self, index: usize) -> Result<T, String> {
if index >= self.size {
return Err("erase index out of bounds".into());
}
let removed = self.elements[index].take();
for i in index..self.size - 1 {
self.elements[i] = self.elements[i + 1].take();
}
self.elements[self.size - 1] = None;
self.size -= 1;
removed.ok_or_else(|| "internal error: element was None".into())
}
/// Try to emplace an element at the back.
pub fn try_emplace_back(&mut self, value: T) -> Result<(), String> {
self.push_back(value)
}
/// Reserve capacity (no-op since fixed).
pub fn reserve(&mut self, _new_cap: usize) {
// Fixed capacity; nothing to do.
}
/// Resize the vector (truncate or default-construct to fill).
pub fn resize(&mut self, new_size: usize, fill: T) -> Result<(), String> {
if new_size > self.capacity {
return Err("inplace_vector resize exceeds capacity".into());
}
while self.size < new_size {
self.push_back(fill.clone())?;
}
while self.size > new_size {
self.pop_back();
}
Ok(())
}
/// Iterator over elements.
pub fn iter(&self) -> impl Iterator<Item = &T> {
self.elements[..self.size].iter().filter_map(|opt| opt.as_ref())
}
}
impl<T: Clone + fmt::Debug> Default for X86InplaceVector<T> {
fn default() -> Self {
Self::new(16)
}
}
// ── 4.7 std::hive<T> — P0447R18 ──
/// A single element in a hive bucket.
#[derive(Debug, Clone)]
pub struct X86HiveElement<T: Clone + fmt::Debug> {
/// The stored value.
pub value: Option<T>,
/// Whether this slot is active.
pub is_active: bool,
/// Index of the next free slot (free list).
pub next_free: Option<usize>,
}
/// A bucket in a hive.
#[derive(Debug, Clone)]
pub struct X86HiveBucket<T: Clone + fmt::Debug> {
/// Elements stored in this bucket.
pub elements: Vec<X86HiveElement<T>>,
/// Total capacity of this bucket.
pub capacity: usize,
/// Number of active elements.
pub active_count: usize,
}
impl<T: Clone + fmt::Debug> X86HiveBucket<T> {
pub fn new(capacity: usize) -> Self {
let mut elements = Vec::with_capacity(capacity);
for _ in 0..capacity {
elements.push(X86HiveElement {
value: None,
is_active: false,
next_free: None,
});
}
Self {
elements,
capacity,
active_count: 0,
}
}
/// Insert a value into this bucket. Returns the slot index.
pub fn insert(&mut self, value: T) -> Result<usize, String> {
for i in 0..self.capacity {
if !self.elements[i].is_active {
self.elements[i].value = Some(value);
self.elements[i].is_active = true;
self.active_count += 1;
return Ok(i);
}
}
Err("bucket is full".into())
}
/// Erase an element from this bucket by slot index.
pub fn erase(&mut self, index: usize) -> Result<(), String> {
if index >= self.capacity || !self.elements[index].is_active {
return Err("erase on empty slot".into());
}
self.elements[index].value = None;
self.elements[index].is_active = false;
self.active_count -= 1;
Ok(())
}
/// Whether this bucket is full.
pub fn is_full(&self) -> bool {
self.active_count >= self.capacity
}
/// Whether this bucket is empty.
pub fn is_empty(&self) -> bool {
self.active_count == 0
}
}
/// A bucket array container with O(1) erase and stable iterators.
#[derive(Debug, Clone)]
pub struct X86Hive<T: Clone + fmt::Debug> {
/// Buckets for element storage.
pub buckets: Vec<X86HiveBucket<T>>,
/// Fixed capacity per bucket.
pub bucket_capacity: usize,
/// Total number of active elements.
pub total_elements: usize,
}
impl<T: Clone + fmt::Debug> X86Hive<T> {
pub fn new(bucket_capacity: usize) -> Self {
Self {
buckets: Vec::new(),
bucket_capacity,
total_elements: 0,
}
}
/// Insert an element into the hive.
pub fn insert(&mut self, value: T) -> (usize, usize) {
// Find first non-full bucket.
for (bi, bucket) in self.buckets.iter_mut().enumerate() {
if !bucket.is_full() {
let slot = bucket.insert(value).expect("bucket is not full");
self.total_elements += 1;
return (bi, slot);
}
}
// No non-full bucket found; create a new one.
let mut new_bucket = X86HiveBucket::new(self.bucket_capacity);
let slot = new_bucket.insert(value).expect("new bucket should have space");
self.buckets.push(new_bucket);
self.total_elements += 1;
(self.buckets.len() - 1, slot)
}
/// Erase an element by (bucket_idx, slot_idx).
pub fn erase(&mut self, bucket_idx: usize, slot_idx: usize) -> Result<(), String> {
if bucket_idx >= self.buckets.len() {
return Err("bucket index out of bounds".into());
}
self.buckets[bucket_idx].erase(slot_idx)?;
self.total_elements -= 1;
Ok(())
}
/// Total number of active elements.
pub fn size(&self) -> usize {
self.total_elements
}
/// Whether the hive is empty.
pub fn is_empty(&self) -> bool {
self.total_elements == 0
}
/// Number of buckets.
pub fn bucket_count(&self) -> usize {
self.buckets.len()
}
/// Total capacity across all buckets.
pub fn capacity(&self) -> usize {
self.buckets.iter().map(|b| b.capacity).sum()
}
/// Compact: remove fully empty buckets and re-pack.
pub fn compact(&mut self) {
self.buckets.retain(|b| !b.is_empty());
}
/// Convert to a `Vec`.
pub fn to_vec(&self) -> Vec<T> {
let mut result = Vec::with_capacity(self.total_elements);
for bucket in &self.buckets {
for elem in &bucket.elements {
if elem.is_active {
if let Some(ref v) = elem.value {
result.push(v.clone());
}
}
}
}
result
}
}
// ── 4.8 std::is_virtual_base_of — P2985R0 ──
/// Type trait: whether a class is a virtual base of another.
#[derive(Debug, Clone)]
pub struct X86IsVirtualBaseOf {
/// Whether this trait is enabled.
pub enabled: bool,
}
impl X86IsVirtualBaseOf {
pub fn new() -> Self {
Self { enabled: true }
}
/// Evaluate `std::is_virtual_base_of<Base, Derived>::value`.
pub fn evaluate(&self, _base: &str, _derived: &str, is_virtual_base: bool) -> bool {
is_virtual_base
}
/// Generate the type trait expression.
pub fn generate_expr(&self, base: &str, derived: &str) -> String {
format!("std::is_virtual_base_of_v<{}, {}>", base, derived)
}
}
impl Default for X86IsVirtualBaseOf {
fn default() -> Self {
Self::new()
}
}
// ── 4.9 Read-Copy Update (RCU) and Hazard Pointers ──
/// A hazard pointer for lock-free memory reclamation.
#[derive(Debug, Clone)]
pub struct X86HazardPointer {
/// Index within the domain.
pub index: usize,
/// The protected memory address.
pub protected_address: Option<usize>,
/// Whether this hazard pointer is active.
pub is_active: bool,
}
impl X86HazardPointer {
pub fn new(index: usize) -> Self {
Self {
index,
protected_address: None,
is_active: false,
}
}
/// Protect a memory address.
pub fn protect(&mut self, address: usize) {
self.protected_address = Some(address);
self.is_active = true;
// On x86, use a store with release semantics.
}
/// Reset the protection.
pub fn reset(&mut self) {
self.protected_address = None;
self.is_active = false;
}
/// Whether this pointer is actively protecting an address.
pub fn is_protecting(&self) -> bool {
self.is_active
}
/// The protected address, if any.
pub fn address(&self) -> Option<usize> {
self.protected_address
}
}
/// A domain managing multiple hazard pointers.
#[derive(Debug, Clone)]
pub struct X86HazardPointerDomain {
/// Hazard pointers in this domain.
pub pointers: Vec<X86HazardPointer>,
/// Maximum number of hazard pointers per thread.
pub max_pointers: usize,
/// List of retired objects pending reclamation.
pub retired_list: Vec<X86RetiredObject>,
}
/// A retired object waiting for reclamation.
#[derive(Debug, Clone)]
pub struct X86RetiredObject {
/// The address of the retired object.
pub address: usize,
/// The "time" it was retired (sequence number).
pub retire_time: u64,
/// Function to call for reclamation.
pub reclaim_fn: String,
}
impl X86HazardPointerDomain {
pub fn new(max_pointers: usize) -> Self {
let mut pointers = Vec::with_capacity(max_pointers);
for i in 0..max_pointers {
pointers.push(X86HazardPointer::new(i));
}
Self {
pointers,
max_pointers,
retired_list: Vec::new(),
}
}
/// Acquire a hazard pointer.
pub fn acquire(&mut self) -> Option<usize> {
for hp in &mut self.pointers {
if !hp.is_active {
hp.is_active = true;
return Some(hp.index);
}
}
None
}
/// Release a hazard pointer.
pub fn release(&mut self, index: usize) {
if let Some(hp) = self.pointers.get_mut(index) {
hp.reset();
}
}
/// Retire an object — it will be reclaimed when safe.
pub fn retire(&mut self, address: usize, reclaim_fn: String) {
self.retired_list.push(X86RetiredObject {
address,
retire_time: 0,
reclaim_fn,
});
}
/// Attempt to reclaim retired objects that are no longer protected.
pub fn reclaim(&mut self) -> usize {
let protected: HashSet<usize> = self
.pointers
.iter()
.filter_map(|hp| hp.address())
.collect();
let mut reclaimed = 0;
self.retired_list.retain(|obj| {
if protected.contains(&obj.address) {
true // Still protected, keep it.
} else {
reclaimed += 1;
false // Safe to reclaim.
}
});
reclaimed
}
/// Number of active hazard pointers.
pub fn active_count(&self) -> usize {
self.pointers.iter().filter(|hp| hp.is_active).count()
}
/// Number of retired objects awaiting reclamation.
pub fn retired_count(&self) -> usize {
self.retired_list.len()
}
}
/// Registry of hazard pointer domains.
#[derive(Debug, Clone)]
pub struct X86HazardPointerRegistry {
/// Available domains.
pub domains: Vec<X86HazardPointerDomain>,
/// Max pointers per domain.
pub max_per_domain: usize,
}
impl X86HazardPointerRegistry {
pub fn new(domain_count: usize, max_per_domain: usize) -> Self {
let mut domains = Vec::with_capacity(domain_count);
for _ in 0..domain_count {
domains.push(X86HazardPointerDomain::new(max_per_domain));
}
Self {
domains,
max_per_domain,
}
}
/// Get a domain by index.
pub fn domain_for(&self, index: usize) -> Option<&X86HazardPointerDomain> {
self.domains.get(index)
}
/// Total number of active hazard pointers across all domains.
pub fn total_active(&self) -> usize {
self.domains.iter().map(|d| d.active_count()).sum()
}
}
/// RCU (Read-Copy Update) domain.
#[derive(Debug, Clone)]
pub struct X86RcuDomain {
/// Domain identifier.
pub id: usize,
/// Current generation for grace period tracking.
pub generation: u64,
/// Pending callbacks.
pub callbacks: Vec<X86RcuCallback>,
/// Whether a grace period is currently active.
pub grace_period_active: bool,
}
/// An RCU callback waiting for a grace period.
#[derive(Debug, Clone)]
pub struct X86RcuCallback {
/// Callback identifier.
pub id: u64,
/// Address of the data to reclaim.
pub data_address: usize,
/// The function to call for reclamation.
pub callback_fn: String,
/// The generation when this callback was registered.
pub registered_generation: u64,
}
impl X86RcuDomain {
pub fn new(id: usize) -> Self {
Self {
id,
generation: 0,
callbacks: Vec::new(),
grace_period_active: false,
}
}
/// Enter an RCU read-side critical section.
pub fn rcu_read_lock(&self) -> X86RcuReadGuard {
X86RcuReadGuard {
domain_id: self.id,
generation: self.generation,
}
}
/// Synchronize: wait for a grace period to elapse.
pub fn synchronize_rcu(&mut self) {
self.grace_period_active = true;
self.generation += 1;
// In a real implementation, wait for all readers to finish.
self.grace_period_active = false;
self.process_callbacks();
}
/// Schedule a callback to be invoked after a grace period.
pub fn call_rcu(&mut self, data_address: usize, callback_fn: String) {
let id = self.callbacks.len() as u64;
self.callbacks.push(X86RcuCallback {
id,
data_address,
callback_fn,
registered_generation: self.generation,
});
}
/// Process callbacks for which a grace period has elapsed.
pub fn process_callbacks(&mut self) -> usize {
let current_gen = self.generation;
let mut processed = 0;
self.callbacks.retain(|cb| {
if cb.registered_generation < current_gen {
processed += 1;
false
} else {
true
}
});
processed
}
/// Whether a reader is currently active.
pub fn is_reader_active(&self) -> bool {
self.grace_period_active
}
}
/// A guard for an RCU read-side critical section.
#[derive(Debug, Clone)]
pub struct X86RcuReadGuard {
/// Domain identifier.
pub domain_id: usize,
/// The generation at time of entering.
pub generation: u64,
}
impl X86RcuReadGuard {
/// The generation at the time this guard was created.
pub fn generation(&self) -> u64 {
self.generation
}
}
/// RCU-protected data.
#[derive(Debug, Clone)]
pub struct X86RcuProtected<T: Clone + fmt::Debug> {
/// The protected data.
pub data: T,
/// Domain identifier.
pub domain: usize,
/// Whether an update is pending.
pub update_pending: bool,
}
impl<T: Clone + fmt::Debug> X86RcuProtected<T> {
pub fn new(data: T, domain: usize) -> Self {
Self {
data,
domain,
update_pending: false,
}
}
/// Read the data (RCU read-side critical section).
pub fn read(&self) -> &T {
&self.data
}
/// Update the data (copy then replace).
pub fn update(&mut self, new_data: T) {
self.data = new_data;
self.update_pending = true;
}
}
// ── 4.10 Contracts — P0542R5 ──
/// Contract assertion kind.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum X86ContractKind {
/// Precondition on function entry.
Precondition,
/// Postcondition on function return.
Postcondition,
/// Inline assertion.
Assert,
/// Audited precondition (only checked in audit builds).
PreconditionAudit,
/// Audited postcondition (only checked in audit builds).
PostconditionAudit,
/// Audited assertion (only checked in audit builds).
AssertAudit,
}
impl X86ContractKind {
/// Whether this is an audit-level contract.
pub fn is_audit(&self) -> bool {
matches!(
self,
Self::PreconditionAudit | Self::PostconditionAudit | Self::AssertAudit
)
}
/// Whether this is a precondition.
pub fn is_precondition(&self) -> bool {
matches!(self, Self::Precondition | Self::PreconditionAudit)
}
/// Whether this is a postcondition.
pub fn is_postcondition(&self) -> bool {
matches!(self, Self::Postcondition | Self::PostconditionAudit)
}
/// Whether this is an inline assertion.
pub fn is_assert(&self) -> bool {
matches!(self, Self::Assert | Self::AssertAudit)
}
}
impl fmt::Display for X86ContractKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Precondition => write!(f, "pre"),
Self::Postcondition => write!(f, "post"),
Self::Assert => write!(f, "assert"),
Self::PreconditionAudit => write!(f, "pre audit"),
Self::PostconditionAudit => write!(f, "post audit"),
Self::AssertAudit => write!(f, "assert audit"),
}
}
}
/// Contract build level.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86ContractBuildLevel {
/// No contracts evaluated.
Off,
/// Only default (non-audit) contracts.
Default,
/// All contracts including audit.
Audit,
}
/// Continuation mode after a contract violation.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86ContractContinuationMode {
/// Never continue after violation.
NeverContinue,
/// May continue depending on handler.
MaybeContinue,
/// Always continue (for testing).
AlwaysContinue,
}
impl fmt::Display for X86ContractContinuationMode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NeverContinue => write!(f, "never"),
Self::MaybeContinue => write!(f, "maybe"),
Self::AlwaysContinue => write!(f, "always"),
}
}
}
/// A single contract annotation.
#[derive(Debug, Clone)]
pub struct X86ContractAnnotation {
/// The kind of contract.
pub kind: X86ContractKind,
/// The predicate expression.
pub predicate: String,
/// Identifier for the return value (postconditions).
pub result_identifier: Option<String>,
/// Source location for diagnostics.
pub location: (String, u32, u32),
/// Continuation mode.
pub continuation: X86ContractContinuationMode,
}
/// A collection of contracts for a function.
#[derive(Debug, Clone)]
pub struct X86FunctionContracts {
/// Function name.
pub function_name: String,
/// Preconditions.
pub preconditions: Vec<X86ContractAnnotation>,
/// Postconditions.
pub postconditions: Vec<X86ContractAnnotation>,
/// Assertions.
pub assertions: Vec<X86ContractAnnotation>,
/// Build configuration.
pub build_level: X86ContractBuildLevel,
}
impl X86FunctionContracts {
pub fn new(function_name: String, build_level: X86ContractBuildLevel) -> Self {
Self {
function_name,
preconditions: Vec::new(),
postconditions: Vec::new(),
assertions: Vec::new(),
build_level,
}
}
/// Add a precondition.
pub fn add_precondition(&mut self, predicate: String, result: Option<String>, location: (String, u32, u32), audit: bool) {
self.preconditions.push(X86ContractAnnotation {
kind: if audit {
X86ContractKind::PreconditionAudit
} else {
X86ContractKind::Precondition
},
predicate,
result_identifier: result,
location,
continuation: X86ContractContinuationMode::NeverContinue,
});
}
/// Add a postcondition.
pub fn add_postcondition(&mut self, predicate: String, result: Option<String>, location: (String, u32, u32), audit: bool) {
self.postconditions.push(X86ContractAnnotation {
kind: if audit {
X86ContractKind::PostconditionAudit
} else {
X86ContractKind::Postcondition
},
predicate,
result_identifier: result,
location,
continuation: X86ContractContinuationMode::NeverContinue,
});
}
/// Add an assertion.
pub fn add_assertion(&mut self, predicate: String, location: (String, u32, u32), audit: bool) {
self.assertions.push(X86ContractAnnotation {
kind: if audit {
X86ContractKind::AssertAudit
} else {
X86ContractKind::Assert
},
predicate,
result_identifier: None,
location,
continuation: X86ContractContinuationMode::NeverContinue,
});
}
/// Total number of contracts.
pub fn total_count(&self) -> usize {
self.preconditions.len() + self.postconditions.len() + self.assertions.len()
}
/// Whether all contracts are audit-level.
pub fn all_audit(&self) -> bool {
self.preconditions.iter().all(|c| c.kind.is_audit())
&& self.postconditions.iter().all(|c| c.kind.is_audit())
&& self.assertions.iter().all(|c| c.kind.is_audit())
}
}
/// Build configuration for contracts.
#[derive(Debug, Clone)]
pub struct X86ContractBuildConfig {
/// The build level.
pub level: X86ContractBuildLevel,
/// Default continuation mode.
pub default_continuation: X86ContractContinuationMode,
}
impl X86ContractBuildConfig {
/// Whether a given contract should be evaluated under this config.
pub fn should_evaluate(&self, kind: X86ContractKind) -> bool {
match self.level {
X86ContractBuildLevel::Off => false,
X86ContractBuildLevel::Default => !kind.is_audit(),
X86ContractBuildLevel::Audit => true,
}
}
}
impl Default for X86ContractBuildConfig {
fn default() -> Self {
Self {
level: X86ContractBuildLevel::Default,
default_continuation: X86ContractContinuationMode::NeverContinue,
}
}
}
// ── 4.11 Reflection — P2996R3 ──
/// Handle to a reflected entity.
#[derive(Debug, Clone)]
pub struct X86MetaInfo {
/// Opaque handle for the reflected entity.
pub handle: u64,
/// The kind of entity reflected.
pub entity_kind: X86MetaEntityKind,
/// Source location of the entity.
pub source_location: String,
/// Display name of the entity.
pub display_name: String,
}
/// Kinds of entities that can be reflected.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum X86MetaEntityKind {
/// A type (class, struct, union, enum, fundamental type).
Type,
/// A variable.
Variable,
/// A free function.
Function,
/// A member function.
MemberFunction,
/// A namespace.
Namespace,
/// A template.
Template,
/// A concept.
Concept,
/// An expression.
Expression,
/// A statement.
Statement,
/// An enumeration.
Enum,
/// An enumerator value.
EnumValue,
/// A class.
Class,
/// A struct.
Struct,
/// A union.
Union,
/// A base class.
BaseClass,
/// A data member.
DataMember,
/// A function parameter.
Parameter,
/// A lambda expression.
Lambda,
/// A type alias.
Alias,
}
impl fmt::Display for X86MetaEntityKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Type => write!(f, "type"),
Self::Variable => write!(f, "variable"),
Self::Function => write!(f, "function"),
Self::MemberFunction => write!(f, "member_function"),
Self::Namespace => write!(f, "namespace"),
Self::Template => write!(f, "template"),
Self::Concept => write!(f, "concept"),
Self::Expression => write!(f, "expression"),
Self::Statement => write!(f, "statement"),
Self::Enum => write!(f, "enum"),
Self::EnumValue => write!(f, "enum_value"),
Self::Class => write!(f, "class"),
Self::Struct => write!(f, "struct"),
Self::Union => write!(f, "union"),
Self::BaseClass => write!(f, "base_class"),
Self::DataMember => write!(f, "data_member"),
Self::Parameter => write!(f, "parameter"),
Self::Lambda => write!(f, "lambda"),
Self::Alias => write!(f, "alias"),
}
}
}
/// Reflection operator: `^entity` produces a `meta::info`.
#[derive(Debug, Clone)]
pub struct X86ReflectionOperator {
/// The entity being reflected.
pub entity: String,
/// The resulting meta::info handle.
pub info: X86MetaInfo,
}
impl X86ReflectionOperator {
/// Reflect a type.
pub fn reflect_type(type_name: &str) -> Self {
Self {
entity: type_name.to_string(),
info: X86MetaInfo {
handle: 0,
entity_kind: X86MetaEntityKind::Type,
source_location: String::new(),
display_name: type_name.to_string(),
},
}
}
/// Reflect a class.
pub fn reflect_class(class_name: &str) -> Self {
Self {
entity: class_name.to_string(),
info: X86MetaInfo {
handle: 0,
entity_kind: X86MetaEntityKind::Class,
source_location: String::new(),
display_name: class_name.to_string(),
},
}
}
/// Reflect a function.
pub fn reflect_function(func_name: &str) -> Self {
Self {
entity: func_name.to_string(),
info: X86MetaInfo {
handle: 0,
entity_kind: X86MetaEntityKind::Function,
source_location: String::new(),
display_name: func_name.to_string(),
},
}
}
/// Generate the reflection expression: `^{entity}`.
pub fn generate_expression(&self) -> String {
format!("^{}", self.entity)
}
}
/// Splicer: `[: rexpr :]` splices a reflected expression back into code.
#[derive(Debug, Clone)]
pub struct X86Splicer {
/// The spliced expression.
pub expression: String,
/// The reflection info being spliced.
pub reflected_info: X86MetaInfo,
/// The result type.
pub result_type: String,
}
impl X86Splicer {
pub fn new(expression: String, info: X86MetaInfo) -> Self {
Self {
expression,
reflected_info: info,
result_type: String::new(),
}
}
/// Splicer producing a type.
pub fn type_splicer(expression: String, info: X86MetaInfo) -> Self {
Self {
expression: format!("typename([:{expression}:])", expression = expression),
reflected_info: info,
result_type: String::new(),
}
}
/// Splicer producing a value.
pub fn value_splicer(expression: String, info: X86MetaInfo) -> Self {
Self {
expression: format!("[:{expression}:]", expression = expression),
reflected_info: info,
result_type: String::new(),
}
}
/// Generate the splicer expression.
pub fn generate(&self) -> String {
self.expression.clone()
}
}
/// Meta query operations on reflected entities.
#[derive(Debug, Clone)]
pub enum X86MetaQuery {
/// Get the name of an entity.
NameOf,
/// Get the type of an entity.
TypeOf,
/// Get the members of a reflected type.
MembersOf,
/// Get the base classes of a reflected type.
BasesOf,
/// Get the parameters of a function.
ParametersOf,
/// Check access (public/protected/private).
AccessCheck,
/// Check if a base is virtual.
IsVirtual,
/// Check if constexpr.
IsConstexpr,
/// Check if noexcept.
IsNoexcept,
/// Get the size of a reflected type.
SizeOfReflected,
/// Get the alignment of a reflected type.
AlignOfReflected,
/// Custom query.
Custom(String),
}
impl X86MetaQuery {
/// Generate the query expression.
pub fn generate(&self, info: &X86MetaInfo) -> String {
match self {
Self::NameOf => format!("meta::name_of({:?})", info),
Self::TypeOf => format!("meta::type_of({:?})", info),
Self::MembersOf => format!("meta::members_of({:?})", info),
Self::BasesOf => format!("meta::bases_of({:?})", info),
Self::ParametersOf => format!("meta::parameters_of({:?})", info),
Self::AccessCheck => format!("meta::is_public({:?})", info),
Self::IsVirtual => format!("meta::is_virtual({:?})", info),
Self::IsConstexpr => format!("meta::is_constexpr({:?})", info),
Self::IsNoexcept => format!("meta::is_noexcept({:?})", info),
Self::SizeOfReflected => format!("meta::size_of({:?})", info),
Self::AlignOfReflected => format!("meta::align_of({:?})", info),
Self::Custom(s) => s.clone(),
}
}
}
/// Context for reflection operations, tracking nesting depth.
#[derive(Debug, Clone)]
pub struct X86ReflectionContext {
/// Active reflection operations.
pub operations: Vec<X86MetaQuery>,
/// Active splicers.
pub splicers: Vec<X86Splicer>,
/// Generated code fragments.
pub generated_code: Vec<String>,
/// Nesting depth for inline reflection blocks.
pub nesting_depth: u32,
}
impl X86ReflectionContext {
pub fn new() -> Self {
Self {
operations: Vec::new(),
splicers: Vec::new(),
generated_code: Vec::new(),
nesting_depth: 0,
}
}
/// Add a meta query.
pub fn add_query(&mut self, query: X86MetaQuery) {
self.operations.push(query);
}
/// Add a splicer.
pub fn add_splicer(&mut self, splicer: X86Splicer) {
self.splicers.push(splicer);
}
/// Generate an enum-to-string converter using reflection.
pub fn generate_enum_to_string(&mut self, enum_name: &str, enumerators: &[(&str, i64)]) -> Vec<String> {
let mut code = Vec::new();
code.push(format!("const char* to_string({} e) {{", enum_name));
code.push(" switch (e) {".to_string());
for (name, _) in enumerators {
code.push(format!(" case {}::{}: return \"{}\";", enum_name, name, name));
}
code.push(" default: return \"unknown\";".to_string());
code.push(" }".to_string());
code.push("}".to_string());
self.generated_code.extend(code.clone());
code
}
/// Generate a struct-to-tuple converter using reflection.
pub fn generate_struct_to_tuple(&mut self, struct_name: &str, member_count: usize) -> String {
let result = format!(
"auto to_tuple(const {}& s) {{ return std::tie({}); }}",
struct_name,
(0..member_count)
.map(|i| format!("s.member_{}", i))
.collect::<Vec<_>>()
.join(", ")
);
self.generated_code.push(result.clone());
result
}
}
impl Default for X86ReflectionContext {
fn default() -> Self {
Self::new()
}
}
// ── 4.12 Senders/Receivers — P2300R7 ──
/// Completion signals for senders/receivers.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum X86CompletionSignal {
/// Value was set (success).
SetValue,
/// Error occurred.
SetError,
/// Operation was stopped.
SetStopped,
}
impl fmt::Display for X86CompletionSignal {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::SetValue => write!(f, "set_value"),
Self::SetError => write!(f, "set_error"),
Self::SetStopped => write!(f, "set_stopped"),
}
}
}
/// A sender descriptor.
#[derive(Debug, Clone)]
pub struct X86SenderDescriptor {
/// The sender type name.
pub sender_type: String,
/// Value types that this sender can produce.
pub value_types: Vec<String>,
/// Error type.
pub error_type: String,
/// Whether this sender always completes.
pub always_completes: bool,
}
impl X86SenderDescriptor {
/// Create a `just` sender that produces a single value.
pub fn just(value_type: String) -> Self {
Self {
sender_type: format!("just_t<{}>", value_type),
value_types: vec![value_type],
error_type: "std::exception_ptr".to_string(),
always_completes: true,
}
}
/// Create a `schedule` sender from a scheduler.
pub fn schedule(scheduler_type: String) -> Self {
Self {
sender_type: format!("schedule_t<{}>", scheduler_type),
value_types: Vec::new(),
error_type: "std::exception_ptr".to_string(),
always_completes: true,
}
}
}
/// Sender adaptors (algorithms).
#[derive(Debug, Clone)]
pub enum X86SenderAdaptor {
/// Chain: `then(sender, f)`.
Then {
function: String,
input_type: String,
output_type: String,
},
/// Error handler: `upon_error(sender, f)`.
UponError {
function: String,
error_type: String,
},
/// Stopped handler: `upon_stopped(sender, f)`.
UponStopped {
function: String,
},
/// `let_value(sender, f)`.
LetValue {
function: String,
input_type: String,
},
/// `let_error(sender, f)`.
LetError {
function: String,
error_type: String,
},
/// `let_stopped(sender, f)`.
LetStopped {
function: String,
},
/// `bulk(sender, n, f)`.
Bulk {
count: usize,
function: String,
},
/// `split(sender)`.
Split,
/// `when_all(s1, s2, ...)`.
WhenAll {
sender_count: usize,
},
/// `transfer(sender, scheduler)`.
Transfer {
scheduler: String,
},
/// `transfer_just(scheduler, values...)`.
TransferJust {
scheduler: String,
values: Vec<String>,
},
/// `start_on(scheduler, sender)`.
StartOn {
scheduler: String,
},
/// `on(scheduler, sender, f)`.
On {
scheduler: String,
function: String,
},
/// `into_variant(sender)`.
IntoVariant,
/// `ensure_started(sender)`.
EnsureStarted,
}
impl X86SenderAdaptor {
/// The type name of this adaptor.
pub fn type_name(&self) -> &'static str {
match self {
Self::Then { .. } => "then_t",
Self::UponError { .. } => "upon_error_t",
Self::UponStopped { .. } => "upon_stopped_t",
Self::LetValue { .. } => "let_value_t",
Self::LetError { .. } => "let_error_t",
Self::LetStopped { .. } => "let_stopped_t",
Self::Bulk { .. } => "bulk_t",
Self::Split => "split_t",
Self::WhenAll { .. } => "when_all_t",
Self::Transfer { .. } => "transfer_t",
Self::TransferJust { .. } => "transfer_just_t",
Self::StartOn { .. } => "start_on_t",
Self::On { .. } => "on_t",
Self::IntoVariant => "into_variant_t",
Self::EnsureStarted => "ensure_started_t",
}
}
/// Input arity for the adaptor.
pub fn input_arity(&self) -> usize {
match self {
Self::WhenAll { sender_count } => *sender_count,
Self::Bulk { count, .. } => *count,
_ => 1,
}
}
}
/// Execution context for senders/receivers.
#[derive(Debug, Clone)]
pub struct X86ExecutionContext {
/// The scheduler in use.
pub scheduler: String,
/// Active sender chains.
pub active_senders: Vec<X86SenderDescriptor>,
/// Adaptors in the chain.
pub adaptors: Vec<X86SenderAdaptor>,
}
impl X86ExecutionContext {
pub fn new(scheduler: String) -> Self {
Self {
scheduler,
active_senders: Vec::new(),
adaptors: Vec::new(),
}
}
/// Apply `then` to the execution context.
pub fn then(&mut self, function: String, input_type: String, output_type: String) {
self.adaptors.push(X86SenderAdaptor::Then {
function,
input_type,
output_type,
});
}
/// Apply `upon_error` to the execution context.
pub fn upon_error(&mut self, function: String, error_type: String) {
self.adaptors.push(X86SenderAdaptor::UponError {
function,
error_type,
});
}
/// Generate the linear sender chain.
pub fn generate_chain(&self) -> String {
let mut chain = format!("auto __sender = schedule({});\n", self.scheduler);
for adaptor in &self.adaptors {
match adaptor {
X86SenderAdaptor::Then { function, input_type: _, output_type: _ } => {
chain.push_str(&format!(
"auto __sender2 = then(__sender, {});\n", function
));
chain.push_str("__sender = __sender2;\n");
}
X86SenderAdaptor::UponError { function, error_type: _ } => {
chain.push_str(&format!(
"auto __sender2 = upon_error(__sender, {});\n", function
));
chain.push_str("__sender = __sender2;\n");
}
_ => {
chain.push_str(&format!(
"// adaptor: {}\n", adaptor.type_name()
));
}
}
}
chain
}
}
// ── 4.13 Pattern Matching — P1371R3 ──
/// A pattern in an `inspect` expression.
#[derive(Debug, Clone)]
pub enum X86MatchPattern {
/// `_` — wildcard, matches anything.
Wildcard,
/// `let x` — binding that captures the matched value.
Binding(String),
/// Integer literal.
IntegerLiteral(i64),
/// Float literal.
FloatLiteral(f64),
/// Boolean literal.
BooleanLiteral(bool),
/// String literal.
StringLiteral(String),
/// Destructuring: `(pattern1, pattern2, ...)`.
Destructure(Vec<X86MatchPattern>),
/// Alternative: `pattern1 | pattern2`.
Alternative(Vec<X86MatchPattern>),
/// Guarded pattern: `pattern if condition`.
Guard {
pattern: Box<X86MatchPattern>,
condition: String,
},
/// Type pattern: `:TypeName x`.
TypePattern {
type_name: String,
binding: Option<String>,
},
}
/// Helper to convert a pattern to a display string.
impl fmt::Display for X86MatchPattern {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Wildcard => write!(f, "_"),
Self::Binding(name) => write!(f, "{}", name),
Self::IntegerLiteral(n) => write!(f, "{}", n),
Self::FloatLiteral(n) => write!(f, "{}", n),
Self::BooleanLiteral(b) => write!(f, "{}", b),
Self::StringLiteral(s) => write!(f, "\"{}\"", s),
Self::Destructure(patterns) => {
let inner: Vec<String> = patterns.iter().map(|p| p.to_string()).collect();
write!(f, "({})", inner.join(", "))
}
Self::Alternative(patterns) => {
let inner: Vec<String> = patterns.iter().map(|p| p.to_string()).collect();
write!(f, "{}", inner.join(" | "))
}
Self::Guard { pattern, condition } => {
write!(f, "{} if {}", pattern, condition)
}
Self::TypePattern { type_name, binding } => {
if let Some(b) = binding {
write!(f, ":{} {}", type_name, b)
} else {
write!(f, ":{}", type_name)
}
}
}
}
}
/// A case in an `inspect` expression.
#[derive(Debug, Clone)]
pub struct X86InspectCase {
/// The pattern to match.
pub pattern: X86MatchPattern,
/// The action/body to execute if matched.
pub action: String,
}
/// An `inspect` expression.
#[derive(Debug, Clone)]
pub struct X86InspectExpression {
/// The scrutinee expression being inspected.
pub scrutinee: String,
/// The type of the scrutinee.
pub scrutinee_type: String,
/// The cases.
pub cases: Vec<X86InspectCase>,
/// The result type (common type of all actions).
pub result_type: String,
/// Whether the match is exhaustive.
pub exhaustive: bool,
}
impl X86InspectExpression {
pub fn new(scrutinee: String, scrutinee_type: String) -> Self {
Self {
scrutinee,
scrutinee_type,
cases: Vec::new(),
result_type: String::new(),
exhaustive: false,
}
}
/// Add a case to the inspect expression.
pub fn add_case(&mut self, pattern: X86MatchPattern, action: String) {
self.cases.push(X86InspectCase { pattern, action });
}
/// Generate the `inspect` expression as C++ source.
pub fn generate(&self) -> String {
let mut result = format!(
"inspect ({}) {{\n",
self.scrutinee
);
for case in &self.cases {
result.push_str(&format!(" {} => {};\n", case.pattern, case.action));
}
result.push('}');
result
}
/// Check whether the pattern set is exhaustive.
pub fn check_exhaustiveness(&self) -> bool {
self.cases.iter().any(|c| matches!(c.pattern, X86MatchPattern::Wildcard))
}
}
// ── 4.14 SIMD Library — P1928R3 with X86 Lowering ──
/// A SIMD type descriptor.
#[derive(Debug, Clone)]
pub struct X86SimdType {
/// The scalar element type.
pub scalar_type: String,
/// Number of elements in the vector.
pub size: usize,
/// ABI tag for the SIMD type.
pub abi_tag: String,
}
impl X86SimdType {
pub fn new(scalar_type: String, size: usize) -> Self {
let abi_tag = match scalar_type.as_str() {
"float" | "double" | "long double" => "native".to_string(),
_ => "compatible".to_string(),
};
Self {
scalar_type,
size,
abi_tag,
}
}
/// The C++ type name: `std::simd<float, 4>`.
pub fn type_name(&self) -> String {
format!("std::simd<{}, {}>", self.scalar_type, self.size)
}
/// The corresponding mask type.
pub fn mask_type(&self) -> String {
format!("std::simd_mask<{}, {}>", self.scalar_type, self.size)
}
/// The LLVM vector type for this SIMD.
pub fn llvm_vector_type(&self, vector_width: u32) -> String {
let elem_size = self.scalar_size_bytes();
let total_bits = elem_size * 8 * self.size as u32;
if total_bits <= vector_width {
format!("<{} x {}>", self.size, self.llvm_scalar_type())
} else {
// Need to split into sub-vectors.
format!("<{} x {}>", vector_width / (elem_size * 8), self.llvm_scalar_type())
}
}
/// Size of the scalar type in bytes.
fn scalar_size_bytes(&self) -> u32 {
match self.scalar_type.as_str() {
"float" => 4,
"double" => 8,
"int" | "unsigned int" => 4,
"short" | "unsigned short" => 2,
"char" | "unsigned char" | "signed char" => 1,
"long" | "unsigned long" => 8,
"long long" | "unsigned long long" => 8,
_ => 4,
}
}
/// The LLVM scalar type.
fn llvm_scalar_type(&self) -> &'static str {
match self.scalar_type.as_str() {
"float" => "float",
"double" => "double",
"int" | "unsigned int" => "i32",
"short" | "unsigned short" => "i16",
"char" | "unsigned char" | "signed char" => "i8",
"long" | "unsigned long" | "long long" | "unsigned long long" => "i64",
_ => "i32",
}
}
}
/// SIMD math operations.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum X86SimdMathOp {
Frexp,
Ldexp,
Logb,
Modf,
Remquo,
Sin,
Cos,
Tan,
Asin,
Acos,
Atan,
Atan2,
Sqrt,
Cbrt,
Exp,
Exp2,
Expm1,
Log,
Log2,
Log10,
Log1p,
Pow,
Ceil,
Floor,
Trunc,
Round,
Abs,
Fma,
Hypot,
}
impl X86SimdMathOp {
/// The C function name for this operation.
pub fn function_name(&self) -> &'static str {
match self {
Self::Frexp => "frexp",
Self::Ldexp => "ldexp",
Self::Logb => "logb",
Self::Modf => "modf",
Self::Remquo => "remquo",
Self::Sin => "sin",
Self::Cos => "cos",
Self::Tan => "tan",
Self::Asin => "asin",
Self::Acos => "acos",
Self::Atan => "atan",
Self::Atan2 => "atan2",
Self::Sqrt => "sqrt",
Self::Cbrt => "cbrt",
Self::Exp => "exp",
Self::Exp2 => "exp2",
Self::Expm1 => "expm1",
Self::Log => "log",
Self::Log2 => "log2",
Self::Log10 => "log10",
Self::Log1p => "log1p",
Self::Pow => "pow",
Self::Ceil => "ceil",
Self::Floor => "floor",
Self::Trunc => "trunc",
Self::Round => "round",
Self::Abs => "abs",
Self::Fma => "fma",
Self::Hypot => "hypot",
}
}
/// Arity of the operation.
pub fn arity(&self) -> usize {
match self {
Self::Atan2 | Self::Pow | Self::Ldexp | Self::Remquo | Self::Fma | Self::Hypot => 2,
_ => 1,
}
}
/// Whether this operation is available for integer SIMD types.
pub fn available_for_integer(&self) -> bool {
matches!(self, Self::Abs)
}
/// Generate X86 SIMD intrinsic call for this operation.
pub fn generate_x86_intrinsic(&self, _simd: &X86SimdType, simd_level: CXX23SimdLevel) -> String {
let prefix = match simd_level {
CXX23SimdLevel::SSE | CXX23SimdLevel::SSE2 | CXX23SimdLevel::SSSE3 | CXX23SimdLevel::SSE4 => "mm",
CXX23SimdLevel::AVX | CXX23SimdLevel::AVX2 => "mm256",
CXX23SimdLevel::AVX512F | CXX23SimdLevel::AVX512Full => "mm512",
_ => "mm",
};
match self {
Self::Sqrt => format!("_{prefix}_sqrt_pd", prefix = prefix),
Self::Abs => format!("_{prefix}_abs_pd", prefix = prefix),
Self::Ceil => format!("_{prefix}_ceil_pd", prefix = prefix),
Self::Floor => format!("_{prefix}_floor_pd", prefix = prefix),
Self::Fma => format!("_{prefix}_fmadd_pd", prefix = prefix),
_ => format!("_{prefix}_{}_pd", self.function_name(), prefix = prefix),
}
}
}
/// Registry of available SIMD math operations.
#[derive(Debug, Clone)]
pub struct X86SimdMathRegistry {
/// Supported operations.
pub supported_ops: Vec<X86SimdMathOp>,
/// The SIMD type this registry is for.
pub simd_type: X86SimdType,
/// Whether float operations are supported.
pub has_float_support: bool,
/// Whether integer operations are supported.
pub has_integer_support: bool,
/// SIMD capability level.
pub simd_level: CXX23SimdLevel,
}
impl X86SimdMathRegistry {
pub fn new(simd_type: X86SimdType, simd_level: CXX23SimdLevel) -> Self {
let has_float = matches!(
simd_type.scalar_type.as_str(),
"float" | "double" | "long double"
);
let has_int = matches!(
simd_type.scalar_type.as_str(),
"int" | "unsigned int" | "short" | "unsigned short" | "char" | "unsigned char"
| "long" | "unsigned long" | "long long" | "unsigned long long"
);
let mut supported_ops = Vec::new();
if has_float {
supported_ops.extend_from_slice(&[
X86SimdMathOp::Sin, X86SimdMathOp::Cos, X86SimdMathOp::Tan,
X86SimdMathOp::Asin, X86SimdMathOp::Acos, X86SimdMathOp::Atan,
X86SimdMathOp::Atan2, X86SimdMathOp::Sqrt, X86SimdMathOp::Cbrt,
X86SimdMathOp::Exp, X86SimdMathOp::Exp2, X86SimdMathOp::Expm1,
X86SimdMathOp::Log, X86SimdMathOp::Log2, X86SimdMathOp::Log10,
X86SimdMathOp::Log1p, X86SimdMathOp::Pow, X86SimdMathOp::Ceil,
X86SimdMathOp::Floor, X86SimdMathOp::Trunc, X86SimdMathOp::Round,
X86SimdMathOp::Fma, X86SimdMathOp::Hypot,
]);
} else if has_int && simd_level.supports_integer_vectors() {
supported_ops.push(X86SimdMathOp::Abs);
}
Self {
supported_ops,
simd_type,
has_float_support: has_float,
has_integer_support: has_int && simd_level.supports_integer_vectors(),
simd_level,
}
}
/// List available operations.
pub fn available_ops(&self) -> &[X86SimdMathOp] {
&self.supported_ops
}
/// Whether a specific operation is supported.
pub fn supports(&self, op: X86SimdMathOp) -> bool {
self.supported_ops.contains(&op)
}
/// Number of supported operations.
pub fn op_count(&self) -> usize {
self.supported_ops.len()
}
}
// ═══════════════════════════════════════════════════════════════════════════════
// 5. X86CXX23Features — Feature Detection and Test Macros
// ═══════════════════════════════════════════════════════════════════════════════
/// An individual C++ feature for detection.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum X86CXXFeature {
// C++23 Language
DeducingThis,
IfConsteval,
StaticOperatorCall,
MultiDimSubscript,
DecayCopy,
WarningDirective,
ElifdefElifndef,
SizeTLiteral,
ImplicitMoveReturn,
ParenAggregateInit,
// C++23 Library
OptionalMonadic,
Expected,
Mdspan,
FlatMap,
FlatSet,
FormattedPrint,
Generator,
ZipView,
ZipTransformView,
EnumerateView,
AdjacentView,
CartesianProductView,
AsConstView,
AsRvalueView,
RepeatView,
StrideView,
SlideView,
ChunkView,
ChunkByView,
JoinWithView,
IotaView,
RangesTo,
RangesContains,
RangesFindLast,
RangesStartsWith,
RangesEndsWith,
// C++26 Language (Preview)
PackIndexing,
UnnamedPlaceholder,
ConstexprPlacementNew,
UserStaticAssert,
IncompleteDeleteCheck,
Contracts,
Reflection,
PatternMatching,
// C++26 Library (Preview)
InplaceVector,
Hive,
IsVirtualBaseOf,
HazardPointers,
Rcu,
SendersReceivers,
SimdExtensions,
}
impl X86CXXFeature {
/// Human-readable name of the feature.
pub fn name(&self) -> &'static str {
match self {
Self::DeducingThis => "Deducing this (P0847R7)",
Self::IfConsteval => "if consteval (P1938R3)",
Self::StaticOperatorCall => "static operator() (P1169R4)",
Self::MultiDimSubscript => "Multidimensional subscript (P2128R6)",
Self::DecayCopy => "auto(x)/auto{x} decay-copy (P0849R8)",
Self::WarningDirective => "#warning directive (P2437R1)",
Self::ElifdefElifndef => "#elifdef/#elifndef (P2334R1)",
Self::SizeTLiteral => "Literal suffix for size_t (P0330R8)",
Self::ImplicitMoveReturn => "Simpler implicit move (P2266R3)",
Self::ParenAggregateInit => "Parenthesized aggregate init (P0960R3)",
Self::OptionalMonadic => "std::optional monadic ops (P0798R8)",
Self::Expected => "std::expected (P0323R12)",
Self::Mdspan => "std::mdspan (P0009R18)",
Self::FlatMap => "std::flat_map (P0429R9)",
Self::FlatSet => "std::flat_set (P0429R9)",
Self::FormattedPrint => "std::print/println (P2093R14)",
Self::Generator => "std::generator (P2502R2)",
Self::ZipView => "std::views::zip (P2321R2)",
Self::ZipTransformView => "std::views::zip_transform",
Self::EnumerateView => "std::views::enumerate (P2164R4)",
Self::AdjacentView => "std::views::adjacent (P2321R2)",
Self::CartesianProductView => "std::views::cartesian_product (P2374R4)",
Self::AsConstView => "std::views::as_const (P2278R2)",
Self::AsRvalueView => "std::views::as_rvalue (P2446R2)",
Self::RepeatView => "std::views::repeat (P2474R2)",
Self::StrideView => "std::views::stride (P1899R3)",
Self::SlideView => "std::views::slide (P2442R1)",
Self::ChunkView => "std::views::chunk (P2442R1)",
Self::ChunkByView => "std::views::chunk_by (P2443R1)",
Self::JoinWithView => "std::views::join_with (P2441R1)",
Self::IotaView => "std::views::iota with value (P2440R1)",
Self::RangesTo => "std::ranges::to (P1206R7)",
Self::RangesContains => "std::ranges::contains (P2302R4)",
Self::RangesFindLast => "std::ranges::find_last (P1223R5)",
Self::RangesStartsWith => "std::ranges::starts_with (P1659R3)",
Self::RangesEndsWith => "std::ranges::ends_with (P1659R3)",
Self::PackIndexing => "Pack indexing (P2662R3)",
Self::UnnamedPlaceholder => "Unnamed placeholder (P2169R4)",
Self::ConstexprPlacementNew => "constexpr placement new (P2747R2)",
Self::UserStaticAssert => "User static_assert messages (P2741R3)",
Self::IncompleteDeleteCheck => "Delete incomplete type diagnostic",
Self::Contracts => "Contracts (P0542R5)",
Self::Reflection => "Reflection (P2996R3)",
Self::PatternMatching => "Pattern matching (P1371R3)",
Self::InplaceVector => "std::inplace_vector (P0843R8)",
Self::Hive => "std::hive (P0447R18)",
Self::IsVirtualBaseOf => "std::is_virtual_base_of (P2985R0)",
Self::HazardPointers => "Hazard pointers",
Self::Rcu => "RCU",
Self::SendersReceivers => "Senders/Receivers (P2300R7)",
Self::SimdExtensions => "std::simd library (P1928R3)",
}
}
/// The WG21 paper number for this feature.
pub fn paper_number(&self) -> &'static str {
match self {
Self::DeducingThis => "P0847R7",
Self::IfConsteval => "P1938R3",
Self::StaticOperatorCall => "P1169R4",
Self::MultiDimSubscript => "P2128R6",
Self::DecayCopy => "P0849R8",
Self::WarningDirective => "P2437R1",
Self::ElifdefElifndef => "P2334R1",
Self::SizeTLiteral => "P0330R8",
Self::ImplicitMoveReturn => "P2266R3",
Self::ParenAggregateInit => "P0960R3",
Self::OptionalMonadic => "P0798R8",
Self::Expected => "P0323R12",
Self::Mdspan => "P0009R18",
Self::FlatMap => "P0429R9",
Self::FlatSet => "P0429R9",
Self::FormattedPrint => "P2093R14",
Self::Generator => "P2502R2",
Self::ZipView => "P2321R2",
Self::ZipTransformView => "P2321R2",
Self::EnumerateView => "P2164R4",
Self::AdjacentView => "P2321R2",
Self::CartesianProductView => "P2374R4",
Self::AsConstView => "P2278R2",
Self::AsRvalueView => "P2446R2",
Self::RepeatView => "P2474R2",
Self::StrideView => "P1899R3",
Self::SlideView => "P2442R1",
Self::ChunkView => "P2442R1",
Self::ChunkByView => "P2443R1",
Self::JoinWithView => "P2441R1",
Self::IotaView => "P2440R1",
Self::RangesTo => "P1206R7",
Self::RangesContains => "P2302R4",
Self::RangesFindLast => "P1223R5",
Self::RangesStartsWith => "P1659R3",
Self::RangesEndsWith => "P1659R3",
Self::PackIndexing => "P2662R3",
Self::UnnamedPlaceholder => "P2169R4",
Self::ConstexprPlacementNew => "P2747R2",
Self::UserStaticAssert => "P2741R3",
Self::IncompleteDeleteCheck => "N/A",
Self::Contracts => "P0542R5",
Self::Reflection => "P2996R3",
Self::PatternMatching => "P1371R3",
Self::InplaceVector => "P0843R8",
Self::Hive => "P0447R18",
Self::IsVirtualBaseOf => "P2985R0",
Self::HazardPointers => "P2530R3",
Self::Rcu => "P2545R4",
Self::SendersReceivers => "P2300R7",
Self::SimdExtensions => "P1928R3",
}
}
/// The feature-test macro name for this feature (`__cpp_*`).
pub fn feature_test_macro(&self) -> &'static str {
match self {
Self::DeducingThis => "__cpp_explicit_this_parameter",
Self::IfConsteval => "__cpp_if_consteval",
Self::StaticOperatorCall => "__cpp_static_call_operator",
Self::MultiDimSubscript => "__cpp_multidimensional_subscript",
Self::DecayCopy => "__cpp_auto_decay_copy",
Self::WarningDirective => "__cpp_warning_directive",
Self::ElifdefElifndef => "__cpp_elifdef_elifndef",
Self::SizeTLiteral => "__cpp_size_t_suffix",
Self::ImplicitMoveReturn => "__cpp_implicit_move",
Self::ParenAggregateInit => "__cpp_aggregate_paren_init",
Self::OptionalMonadic => "__cpp_lib_optional_monadic",
Self::Expected => "__cpp_lib_expected",
Self::Mdspan => "__cpp_lib_mdspan",
Self::FlatMap => "__cpp_lib_flat_map",
Self::FlatSet => "__cpp_lib_flat_set",
Self::FormattedPrint => "__cpp_lib_print",
Self::Generator => "__cpp_lib_generator",
Self::ZipView => "__cpp_lib_ranges_zip",
Self::ZipTransformView => "__cpp_lib_ranges_zip_transform",
Self::EnumerateView => "__cpp_lib_ranges_enumerate",
Self::AdjacentView => "__cpp_lib_ranges_adjacent",
Self::CartesianProductView => "__cpp_lib_ranges_cartesian_product",
Self::AsConstView => "__cpp_lib_ranges_as_const",
Self::AsRvalueView => "__cpp_lib_ranges_as_rvalue",
Self::RepeatView => "__cpp_lib_ranges_repeat",
Self::StrideView => "__cpp_lib_ranges_stride",
Self::SlideView => "__cpp_lib_ranges_slide",
Self::ChunkView => "__cpp_lib_ranges_chunk",
Self::ChunkByView => "__cpp_lib_ranges_chunk_by",
Self::JoinWithView => "__cpp_lib_ranges_join_with",
Self::IotaView => "__cpp_lib_ranges_iota",
Self::RangesTo => "__cpp_lib_ranges_to_container",
Self::RangesContains => "__cpp_lib_ranges_contains",
Self::RangesFindLast => "__cpp_lib_ranges_find_last",
Self::RangesStartsWith => "__cpp_lib_ranges_starts_ends_with",
Self::RangesEndsWith => "__cpp_lib_ranges_starts_ends_with",
Self::PackIndexing => "__cpp_pack_indexing",
Self::UnnamedPlaceholder => "__cpp_placeholder_variables",
Self::ConstexprPlacementNew => "__cpp_constexpr_placement_new",
Self::UserStaticAssert => "__cpp_static_assert",
Self::IncompleteDeleteCheck => "__cpp_delete_incomplete",
Self::Contracts => "__cpp_contracts",
Self::Reflection => "__cpp_reflection",
Self::PatternMatching => "__cpp_pattern_matching",
Self::InplaceVector => "__cpp_lib_inplace_vector",
Self::Hive => "__cpp_lib_hive",
Self::IsVirtualBaseOf => "__cpp_lib_is_virtual_base_of",
Self::HazardPointers => "__cpp_lib_hazard_pointer",
Self::Rcu => "__cpp_lib_rcu",
Self::SendersReceivers => "__cpp_lib_execution",
Self::SimdExtensions => "__cpp_lib_simd",
}
}
/// The value of the feature-test macro.
pub fn feature_test_value(&self) -> u32 {
match self {
Self::DeducingThis => 202110,
Self::IfConsteval => 202106,
Self::StaticOperatorCall => 202207,
Self::MultiDimSubscript => 202211,
Self::DecayCopy => 202302,
Self::WarningDirective => 202211,
Self::ElifdefElifndef => 202302,
Self::SizeTLiteral => 202011,
Self::ImplicitMoveReturn => 202207,
Self::ParenAggregateInit => 202306,
Self::OptionalMonadic => 202110,
Self::Expected => 202211,
Self::Mdspan => 202207,
Self::FlatMap => 202207,
Self::FlatSet => 202207,
Self::FormattedPrint => 202212,
Self::Generator => 202302,
Self::ZipView => 202110,
Self::ZipTransformView => 202110,
Self::EnumerateView => 202302,
Self::AdjacentView => 202302,
Self::CartesianProductView => 202207,
Self::AsConstView => 202302,
Self::AsRvalueView => 202302,
Self::RepeatView => 202302,
Self::StrideView => 202302,
Self::SlideView => 202302,
Self::ChunkView => 202302,
Self::ChunkByView => 202302,
Self::JoinWithView => 202302,
Self::IotaView => 202302,
Self::RangesTo => 202302,
Self::RangesContains => 202302,
Self::RangesFindLast => 202302,
Self::RangesStartsWith => 202302,
Self::RangesEndsWith => 202302,
Self::PackIndexing => 202602,
Self::UnnamedPlaceholder => 202602,
Self::ConstexprPlacementNew => 202602,
Self::UserStaticAssert => 202602,
Self::IncompleteDeleteCheck => 202602,
Self::Contracts => 202602,
Self::Reflection => 202602,
Self::PatternMatching => 202602,
Self::InplaceVector => 202602,
Self::Hive => 202602,
Self::IsVirtualBaseOf => 202602,
Self::HazardPointers => 202602,
Self::Rcu => 202602,
Self::SendersReceivers => 202602,
Self::SimdExtensions => 202602,
}
}
/// The minimum C++ standard version required for this feature.
pub fn min_standard(&self) -> X86CXXStandard {
match self {
Self::DeducingThis | Self::IfConsteval | Self::StaticOperatorCall
| Self::MultiDimSubscript | Self::DecayCopy | Self::WarningDirective
| Self::ElifdefElifndef | Self::SizeTLiteral | Self::ImplicitMoveReturn
| Self::ParenAggregateInit | Self::OptionalMonadic | Self::Expected
| Self::Mdspan | Self::FlatMap | Self::FlatSet | Self::FormattedPrint
| Self::Generator | Self::ZipView | Self::ZipTransformView
| Self::EnumerateView | Self::AdjacentView | Self::CartesianProductView
| Self::AsConstView | Self::AsRvalueView | Self::RepeatView
| Self::StrideView | Self::SlideView | Self::ChunkView
| Self::ChunkByView | Self::JoinWithView | Self::IotaView
| Self::RangesTo | Self::RangesContains | Self::RangesFindLast
| Self::RangesStartsWith | Self::RangesEndsWith => X86CXXStandard::CXX23,
_ => X86CXXStandard::CXX26,
}
}
/// Whether this feature requires X86 SIMD (SSE/AVX).
pub fn requires_simd(&self) -> bool {
matches!(self, Self::SimdExtensions)
}
/// Whether this feature is a C++26 preview feature.
pub fn is_cxx26_preview(&self) -> bool {
self.min_standard() == X86CXXStandard::CXX26
}
}
/// Feature detection and registration for C++23/26 on X86.
#[derive(Debug, Clone)]
pub struct X86CXX23Features {
/// All features with their enabled status.
pub features: HashMap<X86CXXFeature, bool>,
/// The target C++ standard version.
pub standard: X86CXXStandard,
/// The target architecture.
pub arch: CXX23X86Arch,
/// The SIMD capability level.
pub simd_level: CXX23SimdLevel,
/// Generated feature-test macro definitions.
pub feature_test_macros: BTreeMap<String, u32>,
}
impl X86CXX23Features {
/// Create a new feature registry for X86-64.
pub fn new_x86_64(standard: X86CXXStandard) -> Self {
Self::new(standard, CXX23X86Arch::X86_64, CXX23SimdLevel::SSE2)
}
/// Create a new feature registry for IA-32.
pub fn new_x86_32(standard: X86CXXStandard) -> Self {
Self::new(standard, CXX23X86Arch::X86_32, CXX23SimdLevel::None)
}
fn new(standard: X86CXXStandard, arch: CXX23X86Arch, simd_level: CXX23SimdLevel) -> Self {
let mut features = HashMap::new();
let mut macros = BTreeMap::new();
// C++23 features are enabled for C++23 and C++26
let cxx23_enabled = standard >= X86CXXStandard::CXX23;
let cxx26_enabled = standard >= X86CXXStandard::CXX26;
// Language features
features.insert(X86CXXFeature::DeducingThis, cxx23_enabled);
features.insert(X86CXXFeature::IfConsteval, cxx23_enabled);
features.insert(X86CXXFeature::StaticOperatorCall, cxx23_enabled);
features.insert(X86CXXFeature::MultiDimSubscript, cxx23_enabled);
features.insert(X86CXXFeature::DecayCopy, cxx23_enabled);
features.insert(X86CXXFeature::WarningDirective, cxx23_enabled);
features.insert(X86CXXFeature::ElifdefElifndef, cxx23_enabled);
features.insert(X86CXXFeature::SizeTLiteral, cxx23_enabled);
features.insert(X86CXXFeature::ImplicitMoveReturn, cxx23_enabled);
features.insert(X86CXXFeature::ParenAggregateInit, cxx23_enabled);
// Library features
features.insert(X86CXXFeature::OptionalMonadic, cxx23_enabled);
features.insert(X86CXXFeature::Expected, cxx23_enabled);
features.insert(X86CXXFeature::Mdspan, cxx23_enabled);
features.insert(X86CXXFeature::FlatMap, cxx23_enabled);
features.insert(X86CXXFeature::FlatSet, cxx23_enabled);
features.insert(X86CXXFeature::FormattedPrint, cxx23_enabled);
features.insert(X86CXXFeature::Generator, cxx23_enabled);
features.insert(X86CXXFeature::ZipView, cxx23_enabled);
features.insert(X86CXXFeature::ZipTransformView, cxx23_enabled);
features.insert(X86CXXFeature::EnumerateView, cxx23_enabled);
features.insert(X86CXXFeature::AdjacentView, cxx23_enabled);
features.insert(X86CXXFeature::CartesianProductView, cxx23_enabled);
features.insert(X86CXXFeature::AsConstView, cxx23_enabled);
features.insert(X86CXXFeature::AsRvalueView, cxx23_enabled);
features.insert(X86CXXFeature::RepeatView, cxx23_enabled);
features.insert(X86CXXFeature::StrideView, cxx23_enabled);
features.insert(X86CXXFeature::SlideView, cxx23_enabled);
features.insert(X86CXXFeature::ChunkView, cxx23_enabled);
features.insert(X86CXXFeature::ChunkByView, cxx23_enabled);
features.insert(X86CXXFeature::JoinWithView, cxx23_enabled);
features.insert(X86CXXFeature::IotaView, cxx23_enabled);
features.insert(X86CXXFeature::RangesTo, cxx23_enabled);
features.insert(X86CXXFeature::RangesContains, cxx23_enabled);
features.insert(X86CXXFeature::RangesFindLast, cxx23_enabled);
features.insert(X86CXXFeature::RangesStartsWith, cxx23_enabled);
features.insert(X86CXXFeature::RangesEndsWith, cxx23_enabled);
// C++26 preview features
let simd_available = simd_level > CXX23SimdLevel::None;
features.insert(X86CXXFeature::PackIndexing, cxx26_enabled);
features.insert(X86CXXFeature::UnnamedPlaceholder, cxx26_enabled);
features.insert(X86CXXFeature::ConstexprPlacementNew, cxx26_enabled);
features.insert(X86CXXFeature::UserStaticAssert, cxx26_enabled);
features.insert(X86CXXFeature::IncompleteDeleteCheck, cxx26_enabled);
features.insert(X86CXXFeature::Contracts, cxx26_enabled);
features.insert(X86CXXFeature::Reflection, cxx26_enabled);
features.insert(X86CXXFeature::PatternMatching, cxx26_enabled);
features.insert(X86CXXFeature::InplaceVector, cxx26_enabled);
features.insert(X86CXXFeature::Hive, cxx26_enabled);
features.insert(X86CXXFeature::IsVirtualBaseOf, cxx26_enabled);
features.insert(X86CXXFeature::HazardPointers, cxx26_enabled);
features.insert(X86CXXFeature::Rcu, cxx26_enabled);
features.insert(X86CXXFeature::SendersReceivers, cxx26_enabled);
features.insert(X86CXXFeature::SimdExtensions, cxx26_enabled && simd_available);
// Build feature-test macros
for feature in features.keys() {
if features[feature] {
macros.insert(
feature.feature_test_macro().to_string(),
feature.feature_test_value(),
);
}
}
Self {
features,
standard,
arch,
simd_level,
feature_test_macros: macros,
}
}
/// Check if a feature is enabled.
pub fn is_enabled(&self, feature: &X86CXXFeature) -> bool {
self.features.get(feature).copied().unwrap_or(false)
}
/// Enable a specific feature.
pub fn enable(&mut self, feature: X86CXXFeature) {
self.features.insert(feature, true);
self.feature_test_macros.insert(
feature.feature_test_macro().to_string(),
feature.feature_test_value(),
);
}
/// Disable a specific feature.
pub fn disable(&mut self, feature: X86CXXFeature) {
self.features.insert(feature, false);
self.feature_test_macros.remove(feature.feature_test_macro());
}
/// Get the target standard.
pub fn standard(&self) -> X86CXXStandard {
self.standard
}
/// Returns all enabled features.
pub fn enabled_features(&self) -> Vec<X86CXXFeature> {
self.features
.iter()
.filter(|&(_, &enabled)| enabled)
.map(|(&f, _)| f)
.collect()
}
/// Returns all C++23 enabled features.
pub fn cxx23_enabled_features(&self) -> Vec<X86CXXFeature> {
self.features
.iter()
.filter(|&(&f, &enabled)| enabled && f.min_standard() == X86CXXStandard::CXX23)
.map(|(&f, _)| f)
.collect()
}
/// Returns all C++26 preview enabled features.
pub fn cxx26_enabled_features(&self) -> Vec<X86CXXFeature> {
self.features
.iter()
.filter(|&(&f, &enabled)| enabled && f.is_cxx26_preview())
.map(|(&f, _)| f)
.collect()
}
/// Total number of features.
pub fn feature_count(&self) -> usize {
self.features.len()
}
/// Number of enabled features.
pub fn enabled_count(&self) -> usize {
self.features.values().filter(|&&e| e).count()
}
/// Generate the complete `#define` block for feature-test macros.
pub fn generate_feature_test_macros_source(&self) -> String {
let mut source = String::new();
source.push_str("// C++23/26 Feature-test macros for X86 Clang\n");
source.push_str(&format!("// Target standard: {}\n", self.standard));
source.push_str(&format!("// Architecture: {}\n", self.arch));
source.push_str("\n");
// Group by standard
source.push_str("// ── C++23 Language Features ──\n");
for feature in &self.cxx23_enabled_features() {
match feature {
f if matches!(f, X86CXXFeature::OptionalMonadic | X86CXXFeature::Expected | X86CXXFeature::Mdspan | X86CXXFeature::FlatMap | X86CXXFeature::FlatSet | X86CXXFeature::FormattedPrint | X86CXXFeature::Generator | X86CXXFeature::ZipView | X86CXXFeature::ZipTransformView | X86CXXFeature::EnumerateView | X86CXXFeature::AdjacentView | X86CXXFeature::CartesianProductView | X86CXXFeature::AsConstView | X86CXXFeature::AsRvalueView | X86CXXFeature::RepeatView | X86CXXFeature::StrideView | X86CXXFeature::SlideView | X86CXXFeature::ChunkView | X86CXXFeature::ChunkByView | X86CXXFeature::JoinWithView | X86CXXFeature::IotaView | X86CXXFeature::RangesTo | X86CXXFeature::RangesContains | X86CXXFeature::RangesFindLast | X86CXXFeature::RangesStartsWith | X86CXXFeature::RangesEndsWith) => continue,
_ => {}
}
source.push_str(&format!(
"#define {} {}\n",
feature.feature_test_macro(),
feature.feature_test_value()
));
}
source.push_str("\n// ── C++23 Library Features ──\n");
for feature in &self.cxx23_enabled_features() {
match feature {
f if matches!(f, X86CXXFeature::OptionalMonadic | X86CXXFeature::Expected | X86CXXFeature::Mdspan | X86CXXFeature::FlatMap | X86CXXFeature::FlatSet | X86CXXFeature::FormattedPrint | X86CXXFeature::Generator | X86CXXFeature::ZipView | X86CXXFeature::ZipTransformView | X86CXXFeature::EnumerateView | X86CXXFeature::AdjacentView | X86CXXFeature::CartesianProductView | X86CXXFeature::AsConstView | X86CXXFeature::AsRvalueView | X86CXXFeature::RepeatView | X86CXXFeature::StrideView | X86CXXFeature::SlideView | X86CXXFeature::ChunkView | X86CXXFeature::ChunkByView | X86CXXFeature::JoinWithView | X86CXXFeature::IotaView | X86CXXFeature::RangesTo | X86CXXFeature::RangesContains | X86CXXFeature::RangesFindLast | X86CXXFeature::RangesStartsWith | X86CXXFeature::RangesEndsWith) => {}
_ => continue,
}
source.push_str(&format!(
"#define {} {}\n",
feature.feature_test_macro(),
feature.feature_test_value()
));
}
if !self.cxx26_enabled_features().is_empty() {
source.push_str("\n// ── C++26 Preview Features ──\n");
for feature in &self.cxx26_enabled_features() {
source.push_str(&format!(
"#define {} {}\n",
feature.feature_test_macro(),
feature.feature_test_value()
));
}
}
source
}
}
// ═══════════════════════════════════════════════════════════════════════════════
// 6. X86CXX23CodeGen — C++23-Specific X86 Code Generation
// ═══════════════════════════════════════════════════════════════════════════════
/// Code generation strategy for C++23 features on X86.
#[derive(Debug, Clone)]
pub struct X86CXX23CodeGen {
/// Target architecture.
pub arch: CXX23X86Arch,
/// SIMD capability level.
pub simd_level: CXX23SimdLevel,
/// Target C++ standard.
pub standard: X86CXXStandard,
/// Whether deducing-this lowering is enabled.
pub deducing_this_codegen: bool,
/// Whether multidimensional subscript lowering is enabled.
pub multi_dim_subscript_codegen: bool,
/// Whether coroutine generator codegen is enabled.
pub generator_codegen: bool,
/// Whether expected<T,E> union-based codegen is enabled.
pub expected_codegen: bool,
/// Whether mdspan accessor+layout lowering is enabled.
pub mdspan_codegen: bool,
/// X86 pointer size in bytes.
pub pointer_size: u8,
/// X86 size_t size in bytes.
pub size_t_size: u8,
}
impl X86CXX23CodeGen {
pub fn new(arch: CXX23X86Arch, simd_level: CXX23SimdLevel, standard: X86CXXStandard) -> Self {
let (pointer_size, size_t_size) = match arch {
CXX23X86Arch::X86_32 => (4, 4),
CXX23X86Arch::X86_64 => (8, 8),
};
Self {
arch,
simd_level,
standard,
deducing_this_codegen: true,
multi_dim_subscript_codegen: true,
generator_codegen: true,
expected_codegen: true,
mdspan_codegen: true,
pointer_size,
size_t_size,
}
}
// ── 6.1 Deducing This Lowering ──
/// Lower an explicit object parameter call to an implicit-this call.
///
/// Transforms: `obj.function(args...)` where `f` has explicit object param
/// into a direct call with the object as the first argument.
pub fn lower_deducing_this(
&self,
func: &X86ExplicitObjectFunction,
object_type: &str,
call_args: &[String],
) -> String {
if !self.deducing_this_codegen {
return format!("{}({})", func.name, call_args.join(", "));
}
// Reconstruct the call as if it were a free function.
let mut args = vec![format!("{}", call_args.first().cloned().unwrap_or_default())];
for a in &call_args[1..] {
args.push(a.clone());
}
// Generate the mangled name.
let mangled = format!(
"_Z{}{}({})",
func.name.len(),
func.name,
args.join(", ")
);
// For the implicit this pointer on X86-64: pass via %rdi (first integer arg register).
let arg_reg = if self.arch == CXX23X86Arch::X86_64 {
"%rdi"
} else {
"%ecx"
};
format!(
"; deducing-this lowering for {}\n mov {}, {}*\n call {}",
func.name,
arg_reg,
object_type,
mangled,
)
}
// ── 6.2 Multidimensional Subscript Lowering ──
/// Lower a multidimensional subscript to individual element accesses.
///
/// `arr[i][j][k]` → address computation with product-of-extents.
pub fn lower_multi_dim_subscript(
&self,
base_ptr: &str,
element_type: &str,
indices: &[usize],
extents: &[usize],
) -> String {
if !self.multi_dim_subscript_codegen || indices.len() <= 1 {
return format!("{}[{}]", base_ptr, indices.first().copied().unwrap_or(0));
}
// Compute flat offset: i*dim1*dim2 + j*dim2 + k
let mut flat_offset: usize = 0;
let mut stride: usize = 1;
for i in (0..indices.len()).rev() {
flat_offset += indices[i] * stride;
if i < extents.len() {
stride *= extents[i];
}
}
format!(
"getelementptr inbounds {}, {}* {}, i64 {}",
element_type, element_type, base_ptr, flat_offset
)
}
// ── 6.3 std::generator Coroutine Codegen ──
/// Generate the coroutine frame lowering for `std::generator<T>` on X86.
pub fn lower_generator_frame(&self, generator: &X86Generator) -> String {
let mut ir = String::new();
// Coroutine frame type.
ir.push_str(&format!(
"%generator.frame.{} = type {{ \n",
generator.value_type
));
ir.push_str(" i32, ; resume index\n");
ir.push_str(" i32, ; destroy index\n");
ir.push_str(" i8*, ; promise pointer\n");
ir.push_str(&format!(
" {}, ; value storage\n",
generator.value_type
));
ir.push_str("}\n\n");
// Allocate frame on heap.
ir.push_str(&format!(
"%frame = call i8* @malloc(i64 {})\n",
generator.frame.frame_size
));
ir.push_str(&format!(
"%typed_frame = bitcast i8* %frame to %generator.frame.{}*\n",
generator.value_type
));
// Initialize promise.
ir.push_str("call void @llvm.coro.init(i8* %frame)\n");
ir.push_str("call void @llvm.coro.begin(i8* %frame)\n");
ir
}
/// Generate the yield-point IR for a generator.
pub fn lower_generator_yield(&self, generator: &X86Generator, value_slot: &str) -> String {
format!(
" store {} %{}, {}* %typed_frame.value_storage\n \
call void @llvm.coro.suspend(i8* %frame)\n",
generator.value_type, value_slot, generator.value_type,
)
}
// ── 6.4 std::expected<T,E> Union-Based Codegen ──
/// Generate the layout for `std::expected<T, E>` as a tagged union.
pub fn lower_expected_layout(&self, expected: &X86ExpectedType) -> String {
if !self.expected_codegen {
return String::new();
}
// On X86-64, the expected type is lowered as:
// { bool, union { T, E } }
// The bool discriminant tells us which union member is active.
let layout = format!(
"%expected.{t}.{e} = type {{\n\
i8, ; bool has_value discriminant (0=error, 1=value)\n\
[7 x i8], ; padding to align union\n\
union {{\n\
{t}, ; value storage\n\
{e} ; error storage\n\
}}\n\
}}",
t = expected.value_type,
e = expected.error_type,
);
layout
}
/// Lower an `std::expected` value access with branch on discriminant.
pub fn lower_expected_access(&self, expected: &X86ExpectedType, ptr: &str) -> String {
format!(
"; std::expected<{}, {}> access\n\
%has_value = load i8, i8* getelementptr inbounds ({}.expected.layout, {}* {}, i32 0, i32 0)\n\
%is_valid = icmp ne i8 %has_value, 0\n\
br i1 %is_valid, label %value_block, label %error_block\n",
expected.value_type, expected.error_type,
expected.value_type, expected.value_type, ptr,
)
}
// ── 6.5 std::mdspan Accessor + Layout Lowering ──
/// Lower an mdspan element access to a GEP instruction with stride computation.
pub fn lower_mdspan_access(
&self,
mdspan: &X86Mdspan,
indices: &[usize],
) -> String {
if !self.mdspan_codegen {
return String::new();
}
let strides = mdspan.compute_strides();
let _flat_offset: usize = indices.iter().zip(strides.iter())
.map(|(idx, stride)| idx * stride)
.sum();
let mut ir = String::new();
ir.push_str(&format!(
"; mdspan<{}, {}> element access (layout: {})\n",
mdspan.element_type, mdspan.rank, mdspan.layout.to_cpp()
));
// Compute strides in IR
for (dim, stride) in strides.iter().enumerate() {
ir.push_str(&format!(
" %stride_{dim} = mul i64 %index_{dim}, {stride}\n",
dim = dim,
stride = stride
));
}
// Sum strides
ir.push_str(" %flat_offset = add i64 ");
let terms: Vec<String> = (0..strides.len())
.map(|d| format!("%stride_{}", d))
.collect();
ir.push_str(&terms.join(", "));
ir.push_str("\n");
// GEP
ir.push_str(&format!(
" %element_ptr = getelementptr inbounds {}, {}* {}, i64 %flat_offset\n",
mdspan.element_type, mdspan.element_type, mdspan.data_ptr,
));
ir.push_str(&format!(
" %value = load {}, {}* %element_ptr\n",
mdspan.element_type, mdspan.element_type,
));
ir
}
// ── 6.6 Flat Map / Flat Set Lowering ──
/// Generate X86 IR for flat_map insertion (binary search in sorted vector).
pub fn lower_flat_map_insert(
&self,
key_type: &str,
value_type: &str,
key: &str,
value: &str,
) -> String {
format!(
"; flat_map<{}, {}>::insert\n\
%pos = call i64 @std_lower_bound({}*, {}, i64 0, i64 %size)\n\
call void @std_vector_insert({}*, i64 %pos, {} %key, {} %value)\n",
key_type, value_type, key_type, key, key_type, key, value,
)
}
// ── 6.7 Aggregate Parenthesized Init Lowering ──
/// Lower parenthesized aggregate init to member-wise initialization.
pub fn lower_paren_aggregate_init(
&self,
aggregate_type: &str,
member_types: &[String],
args: &[String],
) -> String {
let mut ir = String::new();
ir.push_str(&format!("; Parenthesized aggregate init for {}\n", aggregate_type));
ir.push_str(&format!(
"%agg = alloca {}, align {}\n",
aggregate_type,
if self.arch == CXX23X86Arch::X86_64 { 8 } else { 4 }
));
for (i, (member_type, arg)) in member_types.iter().zip(args.iter()).enumerate() {
ir.push_str(&format!(
" %member_{i} = getelementptr inbounds {}, {}* %agg, i32 0, i32 {i}\n\
store {} %{}, {}* %member_{i}\n",
aggregate_type, aggregate_type, member_type, arg, member_type,
i = i,
));
}
ir
}
/// Get the target triple for the current architecture.
pub fn target_triple(&self) -> &'static str {
match self.arch {
CXX23X86Arch::X86_32 => "i386-unknown-linux-gnu",
CXX23X86Arch::X86_64 => "x86_64-unknown-linux-gnu",
}
}
/// Get the data layout string for the current architecture.
pub fn data_layout(&self) -> &'static str {
match self.arch {
CXX23X86Arch::X86_32 => "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:32-n8:16:32-S128",
CXX23X86Arch::X86_64 => "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128",
}
}
}
// ═══════════════════════════════════════════════════════════════════════════════
// 7. Tests
// ═══════════════════════════════════════════════════════════════════════════════
#[cfg(test)]
mod tests {
use super::*;
// ── 7.1 X86CXX23_26 Tests ──
#[test]
fn test_x86_cxx23_26_new_x86_64_cxx23() {
let framework = X86CXX23_26::new_x86_64_cxx23();
assert_eq!(framework.arch, CXX23X86Arch::X86_64);
assert_eq!(framework.simd_level, CXX23SimdLevel::SSE2);
assert_eq!(framework.standard, X86CXXStandard::CXX23);
assert!(!framework.contracts_enabled);
assert!(!framework.reflection_enabled);
assert!(!framework.pattern_matching_enabled);
assert!(!framework.senders_receivers_enabled);
assert!(framework.simd_enabled);
}
#[test]
fn test_x86_cxx23_26_new_x86_64_cxx26() {
let framework = X86CXX23_26::new_x86_64_cxx26();
assert_eq!(framework.arch, CXX23X86Arch::X86_64);
assert_eq!(framework.standard, X86CXXStandard::CXX26);
assert!(framework.contracts_enabled);
assert!(framework.reflection_enabled);
assert!(framework.pattern_matching_enabled);
assert!(framework.senders_receivers_enabled);
assert!(framework.pack_indexing_enabled);
assert!(framework.constexpr_placement_new_enabled);
}
#[test]
fn test_x86_cxx23_26_new_x86_32() {
let framework = X86CXX23_26::new_x86_32_cxx23();
assert_eq!(framework.arch, CXX23X86Arch::X86_32);
assert_eq!(framework.simd_level, CXX23SimdLevel::None);
assert!(!framework.simd_enabled);
}
#[test]
fn test_x86_cxx23_26_size_t_bytes() {
let f64 = X86CXX23_26::new_x86_64_cxx23();
let f32 = X86CXX23_26::new_x86_32_cxx23();
assert_eq!(f64.size_t_bytes(), 8);
assert_eq!(f32.size_t_bytes(), 4);
}
#[test]
fn test_x86_cxx23_26_max_alignment() {
let f64 = X86CXX23_26::new_x86_64_cxx23();
let f32 = X86CXX23_26::new_x86_32_cxx23();
assert_eq!(f64.max_fundamental_alignment(), 16);
assert_eq!(f32.max_fundamental_alignment(), 8);
}
#[test]
fn test_x86_cxx23_26_enable_cxx26_preview() {
let mut framework = X86CXX23_26::new_x86_64_cxx23();
assert!(!framework.contracts_enabled);
framework.enable_cxx26_preview();
assert!(framework.contracts_enabled);
assert!(framework.reflection_enabled);
assert!(framework.pattern_matching_enabled);
assert!(framework.senders_receivers_enabled);
}
#[test]
fn test_x86_cxx23_26_enable_simd() {
let mut framework = X86CXX23_26::new_x86_64_cxx23();
framework.enable_simd(CXX23SimdLevel::AVX2);
assert_eq!(framework.simd_level, CXX23SimdLevel::AVX2);
assert!(framework.simd_enabled);
}
#[test]
fn test_x86_cxx23_26_default() {
let framework = X86CXX23_26::default();
assert_eq!(framework.arch, CXX23X86Arch::X86_64);
assert_eq!(framework.standard, X86CXXStandard::CXX23);
}
#[test]
fn test_enabled_summary() {
let framework = X86CXX23_26::new_x86_64_cxx23();
let summary = framework.enabled_summary();
assert!(summary.contains("X86 C++23"));
assert!(summary.contains("x86_64"));
}
// ── 7.2 SimdLevel Tests ──
#[test]
fn test_simd_level_from_features() {
assert_eq!(
CXX23SimdLevel::from_features(true, true, true, true),
CXX23SimdLevel::AVX512F
);
assert_eq!(
CXX23SimdLevel::from_features(false, true, true, true),
CXX23SimdLevel::AVX2
);
assert_eq!(
CXX23SimdLevel::from_features(false, false, true, true),
CXX23SimdLevel::AVX
);
assert_eq!(
CXX23SimdLevel::from_features(false, false, false, true),
CXX23SimdLevel::SSE2
);
assert_eq!(
CXX23SimdLevel::from_features(false, false, false, false),
CXX23SimdLevel::None
);
}
#[test]
fn test_simd_level_vector_width() {
assert_eq!(CXX23SimdLevel::None.vector_width_bits(), 0);
assert_eq!(CXX23SimdLevel::SSE.vector_width_bits(), 128);
assert_eq!(CXX23SimdLevel::SSE2.vector_width_bits(), 128);
assert_eq!(CXX23SimdLevel::AVX.vector_width_bits(), 256);
assert_eq!(CXX23SimdLevel::AVX2.vector_width_bits(), 256);
assert_eq!(CXX23SimdLevel::AVX512F.vector_width_bits(), 512);
}
#[test]
fn test_simd_level_supports_integer_vectors() {
assert!(!CXX23SimdLevel::None.supports_integer_vectors());
assert!(!CXX23SimdLevel::SSE.supports_integer_vectors());
assert!(CXX23SimdLevel::SSE2.supports_integer_vectors());
assert!(CXX23SimdLevel::AVX2.supports_integer_vectors());
assert!(CXX23SimdLevel::AVX512F.supports_integer_vectors());
}
#[test]
fn test_simd_level_display() {
assert_eq!(format!("{}", CXX23SimdLevel::None), "none");
assert_eq!(format!("{}", CXX23SimdLevel::SSE2), "sse2");
assert_eq!(format!("{}", CXX23SimdLevel::AVX512F), "avx512f");
}
// ── 7.3 CXXStandard Tests ──
#[test]
fn test_cxx_standard_from_str() {
assert_eq!(
X86CXXStandard::from_str("c++23"),
Some(X86CXXStandard::CXX23)
);
assert_eq!(
X86CXXStandard::from_str("c++2b"),
Some(X86CXXStandard::CXX23)
);
assert_eq!(
X86CXXStandard::from_str("c++26"),
Some(X86CXXStandard::CXX26)
);
assert_eq!(
X86CXXStandard::from_str("c++20"),
Some(X86CXXStandard::CXX20)
);
assert_eq!(X86CXXStandard::from_str("invalid"), None);
}
#[test]
fn test_cxx_standard_as_str() {
assert_eq!(X86CXXStandard::CXX17.as_str(), "c++17");
assert_eq!(X86CXXStandard::CXX20.as_str(), "c++20");
assert_eq!(X86CXXStandard::CXX23.as_str(), "c++23");
assert_eq!(X86CXXStandard::CXX26.as_str(), "c++26");
}
#[test]
fn test_cxx_standard_is_at_least() {
assert!(X86CXXStandard::CXX26.is_at_least(X86CXXStandard::CXX23));
assert!(X86CXXStandard::CXX23.is_at_least(X86CXXStandard::CXX23));
assert!(!X86CXXStandard::CXX20.is_at_least(X86CXXStandard::CXX23));
}
// ── 7.4 SizeT Literal Suffix Tests ──
#[test]
fn test_size_t_literal_suffix_from_suffix() {
assert_eq!(
X86SizeTLiteralSuffix::from_suffix("uz"),
Some(X86SizeTLiteralSuffix::Uz)
);
assert_eq!(
X86SizeTLiteralSuffix::from_suffix("z"),
Some(X86SizeTLiteralSuffix::Z)
);
assert_eq!(
X86SizeTLiteralSuffix::from_suffix("UZ"),
Some(X86SizeTLiteralSuffix::Uz)
);
assert_eq!(X86SizeTLiteralSuffix::from_suffix("ul"), None);
}
#[test]
fn test_size_t_literal_suffix_properties() {
assert!(!X86SizeTLiteralSuffix::Uz.is_signed());
assert!(X86SizeTLiteralSuffix::Z.is_signed());
assert_eq!(X86SizeTLiteralSuffix::Uz.type_name(), "std::size_t");
assert_eq!(X86SizeTLiteralSuffix::Z.type_name(), "std::ptrdiff_t");
assert_eq!(X86SizeTLiteralSuffix::Uz.width_bytes_x86_64(), 8);
assert_eq!(X86SizeTLiteralSuffix::Uz.width_bytes_x86_32(), 4);
}
#[test]
fn test_size_t_literal_parser_enabled() {
let parser = X86SizeTLiteralParser::new(true);
let result = parser.try_parse("42uz");
assert!(result.is_some());
let lit = result.unwrap();
assert_eq!(lit.value, "42");
assert_eq!(lit.suffix, X86SizeTLiteralSuffix::Uz);
assert_eq!(lit.to_source(), "42uz");
}
#[test]
fn test_size_t_literal_parser_disabled() {
let parser = X86SizeTLiteralParser::new(false);
assert!(parser.try_parse("42uz").is_none());
}
#[test]
fn test_size_t_literal_parser_z_suffix() {
let parser = X86SizeTLiteralParser::new(true);
let result = parser.try_parse("100z");
assert!(result.is_some());
let lit = result.unwrap();
assert_eq!(lit.suffix, X86SizeTLiteralSuffix::Z);
assert_eq!(lit.to_source(), "100z");
}
#[test]
fn test_size_t_literal_parser_non_literal() {
let parser = X86SizeTLiteralParser::new(true);
assert!(parser.try_parse("not_a_literal").is_none());
assert!(parser.try_parse("42").is_none());
}
#[test]
fn test_size_t_literal_llvm_type() {
let lit = X86SizeTLiteral::new("42".into(), X86SizeTLiteralSuffix::Uz);
assert_eq!(lit.llvm_type(CXX23X86Arch::X86_64), "i64");
assert_eq!(lit.llvm_type(CXX23X86Arch::X86_32), "i32");
}
// ── 7.5 If Consteval Tests ──
#[test]
fn test_consteval_context_enter_leave() {
let mut ctx = X86ConstevalContext::new();
assert!(!ctx.is_consteval());
ctx.enter("test_func");
assert!(ctx.is_consteval());
assert_eq!(ctx.nesting_depth(), 1);
let exited = ctx.leave();
assert_eq!(exited, Some("test_func".to_string()));
assert!(!ctx.is_consteval());
}
#[test]
fn test_consteval_context_nested() {
let mut ctx = X86ConstevalContext::new();
ctx.enter("outer");
ctx.enter("inner");
assert!(ctx.is_consteval());
assert_eq!(ctx.nesting_depth(), 2);
ctx.leave();
assert_eq!(ctx.nesting_depth(), 1);
ctx.leave();
assert_eq!(ctx.nesting_depth(), 0);
}
#[test]
fn test_evaluate_if_consteval() {
let mut ctx = X86ConstevalContext::new();
assert_eq!(
ctx.evaluate_if_consteval(),
X86IfConstevalResult::NonImmediateContext
);
ctx.enter("consteval_func");
assert_eq!(
ctx.evaluate_if_consteval(),
X86IfConstevalResult::ImmediateContext
);
}
#[test]
fn test_if_consteval_parser_detect() {
let parser = X86IfConstevalParser::new(true);
assert!(!parser.detect_consteval());
}
#[test]
fn test_if_consteval_parser_parse_body() {
let mut parser = X86IfConstevalParser::new(true);
parser.contexts.enter("test");
let result = parser.parse_body("immediate", "non_immediate");
assert_eq!(result, "immediate");
parser.contexts.leave();
let result2 = parser.parse_body("immediate", "non_immediate");
assert_eq!(result2, "non_immediate");
}
// ── 7.6 Deducing This Tests ──
#[test]
fn test_explicit_object_kind_from_param_str() {
assert_eq!(
X86ExplicitObjectKind::from_param_str("this auto&& self"),
Some(X86ExplicitObjectKind::DeducedRef)
);
assert_eq!(
X86ExplicitObjectKind::from_param_str("this auto& self"),
Some(X86ExplicitObjectKind::DeducedLvalueRef)
);
assert_eq!(
X86ExplicitObjectKind::from_param_str("this auto self"),
Some(X86ExplicitObjectKind::DeducedByValue)
);
assert_eq!(
X86ExplicitObjectKind::from_param_str("this auto const& self"),
Some(X86ExplicitObjectKind::DeducedConstLvalueRef)
);
assert_eq!(
X86ExplicitObjectKind::from_param_str("int x"),
None
);
}
#[test]
fn test_explicit_object_kind_properties() {
assert!(X86ExplicitObjectKind::DeducedRef.is_reference());
assert!(!X86ExplicitObjectKind::DeducedRef.is_const());
assert!(!X86ExplicitObjectKind::DeducedByValue.is_reference());
assert!(X86ExplicitObjectKind::DeducedConstLvalueRef.is_const());
}
#[test]
fn test_explicit_object_function_creation() {
let func = X86ExplicitObjectFunction::new(
"foo".into(),
"this auto&& self".into(),
vec![X86FunctionParam {
name: "x".into(),
type_desc: "int".into(),
default_value: None,
}],
"int".into(),
true,
Some("MyClass".into()),
);
assert_eq!(func.name, "foo");
assert_eq!(func.param_name, "self");
assert_eq!(func.kind, X86ExplicitObjectKind::DeducedRef);
assert!(func.can_bind_lvalue());
assert!(func.can_bind_rvalue());
}
#[test]
fn test_explicit_object_function_signature() {
let func = X86ExplicitObjectFunction::new(
"foo".into(),
"this auto&& self".into(),
vec![],
"int".into(),
false,
None,
);
let sig = func.signature();
assert!(sig.contains("auto foo"));
assert!(sig.contains("this auto&& self"));
assert!(sig.contains("-> int"));
}
#[test]
fn test_deducing_this_parser_validate() {
let mut parser = X86DeducingThisParser::new(true);
let func = X86ExplicitObjectFunction::new(
"foo".into(),
"this auto&& self".into(),
vec![],
"int".into(),
true,
Some("MyClass".into()),
);
assert!(parser.validate(&func));
assert!(!parser.diagnostics.is_empty());
}
#[test]
fn test_deducing_this_parser_deduce_this_type() {
let parser = X86DeducingThisParser::new(true);
let func = X86ExplicitObjectFunction::new(
"foo".into(),
"this auto&& self".into(),
vec![],
"int".into(),
true,
Some("MyClass".into()),
);
let deduced = parser.deduce_this_type(&func, true, false);
assert_eq!(deduced, "MyClass&");
}
#[test]
fn test_deducing_this_parser_deduce_const_lvalue() {
let parser = X86DeducingThisParser::new(true);
let func = X86ExplicitObjectFunction::new(
"foo".into(),
"this auto const& self".into(),
vec![],
"int".into(),
true,
Some("MyClass".into()),
);
let deduced = parser.deduce_this_type(&func, true, true);
assert_eq!(deduced, "MyClass const&");
}
// ── 7.7 MultiDim Subscript Tests ──
#[test]
fn test_multi_dim_subscript_new() {
let sub = X86MultiDimSubscript::new(
vec!["size_t".into(), "size_t".into()],
"double&".into(),
false,
);
assert_eq!(sub.index_count, 2);
assert!(sub.validate().is_ok());
}
#[test]
fn test_multi_dim_subscript_validate_empty() {
let sub = X86MultiDimSubscript::new(vec![], "int".into(), false);
assert!(sub.validate().is_err());
}
#[test]
fn test_multi_dim_subscript_call_syntax() {
let sub = X86MultiDimSubscript::new(
vec!["int".into(), "int".into()],
"double".into(),
false,
);
let call = sub.call_syntax("mat", &["1".into(), "2".into()]);
assert_eq!(call, "mat[1, 2]");
}
#[test]
fn test_multi_dim_subscript_lower() {
let sub = X86MultiDimSubscript::new(
vec!["int".into(), "int".into()],
"double".into(),
false,
);
let lowered = sub.lower_subscript("mat", &["1".into(), "2".into()]);
assert_eq!(lowered, "mat.operator[](1, 2)");
}
// ── 7.8 Static Operator Call Tests ──
#[test]
fn test_static_operator_call_validation() {
let op = X86StaticOperatorCall::new(
"MyLambda".into(),
vec![],
"int".into(),
true,
false,
X86CallOperatorKind::Static,
);
assert!(op.validate().is_ok());
}
#[test]
fn test_static_operator_call_validation_with_captures_fails() {
let op = X86StaticOperatorCall::new(
"MyLambda".into(),
vec![],
"int".into(),
true,
true, // has captures
X86CallOperatorKind::Static,
);
assert!(op.validate().is_err());
}
#[test]
fn test_call_operator_kind_display() {
assert_eq!(format!("{}", X86CallOperatorKind::Mutable), "operator()");
assert_eq!(format!("{}", X86CallOperatorKind::Const), "operator() const");
assert_eq!(format!("{}", X86CallOperatorKind::Static), "static operator()");
}
#[test]
fn test_static_operator_call_mangled_name() {
let op = X86StaticOperatorCall::new(
"MyClass".into(),
vec![],
"void".into(),
false,
false,
X86CallOperatorKind::Static,
);
assert!(op.mangled_name().contains("clEv"));
}
// ── 7.9 Decay Copy Tests ──
#[test]
fn test_decay_copy_parser_paren() {
let parser = X86DecayCopyParser::new(true);
let result = parser.try_parse("auto(x)");
assert!(result.is_some());
let expr = result.unwrap();
assert_eq!(expr.kind, X86DecayCopyKind::DecayCopyParen);
assert_eq!(expr.inner_expr, "x");
}
#[test]
fn test_decay_copy_parser_brace() {
let parser = X86DecayCopyParser::new(true);
let result = parser.try_parse("auto{x}");
assert!(result.is_some());
let expr = result.unwrap();
assert_eq!(expr.kind, X86DecayCopyKind::DecayCopyBrace);
assert_eq!(expr.inner_expr, "x");
}
#[test]
fn test_decay_copy_parser_not_decay() {
let parser = X86DecayCopyParser::new(true);
assert!(parser.try_parse("int(x)").is_none());
assert!(parser.try_parse("auto").is_none());
}
#[test]
fn test_decay_copy_parser_disabled() {
let parser = X86DecayCopyParser::new(false);
assert!(parser.try_parse("auto(x)").is_none());
}
#[test]
fn test_decay_copy_apply_decay_ref() {
let mut expr = X86DecayCopyExpr::new(X86DecayCopyKind::DecayCopyParen, "x".into());
expr.apply_decay("int&");
assert_eq!(expr.deduced_type, "int");
}
#[test]
fn test_decay_copy_apply_decay_array() {
let mut expr = X86DecayCopyExpr::new(X86DecayCopyKind::DecayCopyParen, "x".into());
expr.apply_decay("int[10]");
assert_eq!(expr.deduced_type, "int*");
}
#[test]
fn test_decay_copy_emit() {
let expr = X86DecayCopyExpr::new(X86DecayCopyKind::DecayCopyParen, "x".into());
assert_eq!(expr.emit(), "auto(x)");
}
// ── 7.10 #elifdef/#elifndef Tests ──
#[test]
fn test_elif_conditional_from_directive() {
assert_eq!(
X86ElifConditional::from_directive("elifdef"),
Some(X86ElifConditional::Elifdef)
);
assert_eq!(
X86ElifConditional::from_directive("#elifndef"),
Some(X86ElifConditional::Elifndef)
);
assert_eq!(
X86ElifConditional::from_directive("#elif"),
Some(X86ElifConditional::Elif)
);
assert_eq!(X86ElifConditional::from_directive("if"), None);
}
#[test]
fn test_elif_conditional_as_str() {
assert_eq!(X86ElifConditional::Elifdef.as_str(), "#elifdef");
assert_eq!(X86ElifConditional::Elifndef.as_str(), "#elifndef");
}
#[test]
fn test_conditional_chain_ifdef() {
let mut chain = X86ConditionalChain::new(true);
chain.handle_ifdef("FEATURE_X", true);
assert_eq!(chain.blocks.len(), 1);
assert!(chain.branch_taken);
assert!(chain.blocks[0].was_taken);
}
#[test]
fn test_conditional_chain_elifdef() {
let mut chain = X86ConditionalChain::new(true);
chain.handle_ifdef("FEATURE_X", false);
assert!(!chain.branch_taken);
chain.handle_elifdef("FEATURE_Y", true);
assert!(chain.branch_taken);
assert_eq!(chain.blocks.len(), 2);
}
#[test]
fn test_conditional_chain_elifndef() {
let mut chain = X86ConditionalChain::new(true);
chain.handle_ifndef("FEATURE_X", true);
assert!(!chain.branch_taken);
chain.handle_elifndef("FEATURE_Y", false);
assert!(chain.branch_taken);
}
#[test]
fn test_conditional_chain_else() {
let mut chain = X86ConditionalChain::new(true);
chain.handle_ifdef("FEATURE_X", false);
assert!(!chain.branch_taken);
chain.handle_else();
assert!(chain.branch_taken);
}
#[test]
fn test_conditional_chain_reset() {
let mut chain = X86ConditionalChain::new(true);
chain.handle_ifdef("X", true);
assert!(chain.branch_taken);
chain.reset();
assert!(!chain.branch_taken);
assert!(chain.blocks.is_empty());
}
// ── 7.11 #warning Directive Tests ──
#[test]
fn test_warning_directive_format() {
let w = X86WarningDirective::new("deprecated header".into(), 42, "test.h".into());
assert!(w.format_diagnostic().contains("test.h:42"));
assert!(w.format_diagnostic().contains("deprecated header"));
}
#[test]
fn test_warning_handler() {
let mut handler = X86WarningDirectiveHandler::new(false, true);
let warn = X86WarningDirective::new("test warning".into(), 1, "test.cpp".into());
assert!(handler.handle(warn).is_ok());
assert!(handler.has_warnings());
}
#[test]
fn test_warning_handler_werror() {
let mut handler = X86WarningDirectiveHandler::new(true, true);
let warn = X86WarningDirective::new("test warning".into(), 1, "test.cpp".into());
assert!(handler.handle(warn).is_err());
}
#[test]
fn test_warning_handler_disabled() {
let mut handler = X86WarningDirectiveHandler::new(false, false);
let warn = X86WarningDirective::new("test warning".into(), 1, "test.cpp".into());
assert!(handler.handle(warn).is_ok());
assert!(!handler.has_warnings());
}
// ── 7.12 Implicit Move Tests ──
#[test]
fn test_implicit_move_applies() {
let mut ret = X86ImplicitMoveReturn::new("x".into(), "int".into());
let mut locals = HashSet::new();
locals.insert("x".to_string());
assert!(ret.apply_implicit_move(&locals));
assert!(ret.eligible_for_move);
}
#[test]
fn test_implicit_move_not_local() {
let mut ret = X86ImplicitMoveReturn::new("g.x".into(), "int".into());
let locals = HashSet::new();
assert!(!ret.apply_implicit_move(&locals));
}
#[test]
fn test_implicit_move_disabled() {
let mut ret = X86ImplicitMoveReturn::new("x".into(), "int".into());
ret.enabled = false;
let mut locals = HashSet::new();
locals.insert("x".to_string());
assert!(!ret.apply_implicit_move(&locals));
}
// ── 7.13 Optional Monadic Tests ──
#[test]
fn test_optional_monadic_and_then_return() {
let monadic: X86OptionalMonadic<String> = X86OptionalMonadic::new("int".into());
assert_eq!(
monadic.and_then_return_type("float"),
"std::optional<float>"
);
}
#[test]
fn test_optional_monadic_transform_return() {
let monadic: X86OptionalMonadic<String> = X86OptionalMonadic::new("int".into());
assert_eq!(
monadic.transform_return_type("double"),
"std::optional<double>"
);
}
#[test]
fn test_optional_monadic_codegen_and_then() {
let monadic: X86OptionalMonadic<String> = X86OptionalMonadic::new("int".into());
let code = monadic.codegen_and_then("opt", "f(*opt)", "float");
assert!(code.contains("has_value"));
assert!(code.contains("f(*opt)"));
}
#[test]
fn test_optional_monadic_codegen_transform() {
let monadic: X86OptionalMonadic<String> = X86OptionalMonadic::new("int".into());
let code = monadic.codegen_transform("opt", "g(*opt)", "double");
assert!(code.contains("std::optional<double>"));
}
#[test]
fn test_optional_monadic_op_display() {
assert_eq!(format!("{}", X86OptionalMonadicOp::AndThen), "and_then");
assert_eq!(format!("{}", X86OptionalMonadicOp::Transform), "transform");
assert_eq!(format!("{}", X86OptionalMonadicOp::OrElse), "or_else");
}
// ── 7.14 std::expected Tests ──
#[test]
fn test_expected_type_validation() {
let exp = X86ExpectedType::new("int".into(), "std::error_code".into());
assert!(exp.validate().is_ok());
}
#[test]
fn test_expected_type_validation_error_empty() {
let exp = X86ExpectedType::new("int".into(), "".into());
assert!(exp.validate().is_err());
}
#[test]
fn test_expected_and_then_return() {
let exp = X86ExpectedType::new("int".into(), "error".into());
assert_eq!(
exp.and_then_return_type("float"),
"std::expected<float, error>"
);
}
#[test]
fn test_expected_transform_error_return() {
let exp = X86ExpectedType::new("int".into(), "error".into());
assert_eq!(
exp.transform_error_return_type("new_error"),
"std::expected<int, new_error>"
);
}
#[test]
fn test_expected_union_layout() {
let exp = X86ExpectedType::new("int".into(), "std::string".into());
let layout = exp.union_layout();
assert!(layout.contains("union"));
assert!(layout.contains("int value"));
assert!(layout.contains("has_value"));
}
#[test]
fn test_expected_value_is_ok() {
let val: X86ExpectedValue<i32, String> = X86ExpectedValue::Ok(42);
assert!(val.is_ok());
assert!(!val.is_err());
}
#[test]
fn test_expected_value_is_err() {
let val: X86ExpectedValue<i32, String> = X86ExpectedValue::Err("oh no".into());
assert!(val.is_err());
assert!(!val.is_ok());
}
#[test]
fn test_expected_value_map() {
let val: X86ExpectedValue<i32, String> = X86ExpectedValue::Ok(10);
let mapped = val.map(|v| v * 2);
match mapped {
X86ExpectedValue::Ok(v) => assert_eq!(v, 20),
_ => panic!("expected Ok"),
}
}
#[test]
fn test_expected_value_and_then() {
let val: X86ExpectedValue<i32, String> = X86ExpectedValue::Ok(5);
let chained = val.and_then(|v| X86ExpectedValue::Ok(v * 10));
match chained {
X86ExpectedValue::Ok(v) => assert_eq!(v, 50),
_ => panic!("expected Ok"),
}
}
#[test]
fn test_expected_value_or_else() {
let val: X86ExpectedValue<i32, String> = X86ExpectedValue::Err("fail".into());
let recovered = val.or_else(|_| X86ExpectedValue::Ok(0));
assert!(recovered.is_ok());
}
// ── 7.15 Mdspan Tests ──
#[test]
fn test_mdspan_new() {
let md = X86Mdspan::new(
"double".into(),
vec![
X86MdspanExtent::Dynamic,
X86MdspanExtent::Static(3),
X86MdspanExtent::Static(4),
],
);
assert_eq!(md.rank, 3);
assert_eq!(md.element_type, "double");
}
#[test]
fn test_mdspan_with_layout() {
let md = X86Mdspan::new(
"float".into(),
vec![X86MdspanExtent::Static(4), X86MdspanExtent::Static(4)],
).with_layout(X86MdspanLayout::LayoutLeft);
assert_eq!(md.layout, X86MdspanLayout::LayoutLeft);
}
#[test]
fn test_mdspan_compute_strides_right() {
let md = X86Mdspan::new(
"float".into(),
vec![
X86MdspanExtent::Static(2),
X86MdspanExtent::Static(3),
X86MdspanExtent::Static(4),
],
);
let strides = md.compute_strides();
assert_eq!(strides, vec![12, 4, 1]);
}
#[test]
fn test_mdspan_compute_strides_left() {
let md = X86Mdspan::new(
"float".into(),
vec![
X86MdspanExtent::Static(2),
X86MdspanExtent::Static(3),
X86MdspanExtent::Static(4),
],
).with_layout(X86MdspanLayout::LayoutLeft);
let strides = md.compute_strides();
assert_eq!(strides, vec![1, 2, 6]);
}
#[test]
fn test_mdspan_type_decl() {
let md = X86Mdspan::new(
"double".into(),
vec![
X86MdspanExtent::Dynamic,
X86MdspanExtent::Static(4),
],
);
let decl = md.type_decl();
assert!(decl.contains("std::mdspan"));
assert!(decl.contains("double"));
assert!(decl.contains("std::dynamic_extent"));
}
#[test]
fn test_mdspan_extent_to_cpp() {
assert_eq!(X86MdspanExtent::Static(5).to_cpp(), "5");
assert_eq!(X86MdspanExtent::Dynamic.to_cpp(), "std::dynamic_extent");
}
#[test]
fn test_mdspan_layout_properties() {
assert!(!X86MdspanLayout::LayoutRight.is_strided());
assert!(X86MdspanLayout::LayoutStride.is_strided());
}
// ── 7.16 Flat Map / Flat Set Tests ──
#[test]
fn test_flat_map_type_decl() {
let fm = X86FlatMap::new("int".into(), "std::string".into());
let decl = fm.type_decl();
assert!(decl.contains("std::flat_map"));
assert!(decl.contains("int"));
assert!(decl.contains("std::string"));
}
#[test]
fn test_flat_map_underlying_layout() {
let fm = X86FlatMap::new("int".into(), "double".into());
let layout = fm.underlying_layout();
assert!(layout.contains("std::vector"));
assert!(layout.contains("std::pair"));
}
#[test]
fn test_flat_set_type_decl() {
let fs = X86FlatSet::new("int".into());
let decl = fs.type_decl();
assert!(decl.contains("std::flat_set"));
assert!(decl.contains("int"));
}
// ── 7.17 Formatted Print Tests ──
#[test]
fn test_formatted_print_generate() {
let printer = X86FormattedPrint::new(true);
let call = printer.generate_print("Hello {}!", &["name".into()]);
assert!(call.contains("std::print"));
assert!(call.contains("Hello {}!"));
}
#[test]
fn test_formatted_print_generate_disabled() {
let printer = X86FormattedPrint::new(false);
let call = printer.generate_print("Hello {}!", &["name".into()]);
assert!(call.contains("printf"));
}
#[test]
fn test_formatted_println_generate() {
let printer = X86FormattedPrint::new(true);
let call = printer.generate_println("Value: {}", &["42".into()]);
assert!(call.contains("std::println"));
}
// ── 7.18 Generator Tests ──
#[test]
fn test_generator_new() {
let r#gen = X86Generator::new("int".into());
assert_eq!(r#gen.value_type, "int");
assert!(r#gen.promise.has_yield_value);
assert!(r#gen.promise.return_void);
}
#[test]
fn test_generator_type_decl() {
let r#gen = X86Generator::new("double".into());
assert_eq!(r#gen.type_decl(), "std::generator<double>");
}
#[test]
fn test_generator_frame_type_decl() {
let r#gen = X86Generator::new("int".into());
let frame_type = r#gen.frame_type_decl();
assert!(frame_type.contains("generator.frame.int"));
}
#[test]
fn test_generator_lower_co_yield() {
let r#gen = X86Generator::new("int".into());
let ir = r#gen.lower_co_yield("%val");
assert!(ir.contains("llvm.coro.yield"));
}
// ── 7.19 Range Views Tests ──
#[test]
fn test_range_view_adaptor_names() {
assert_eq!(X86RangeViewAdaptor::Zip.name(), "zip");
assert_eq!(X86RangeViewAdaptor::Enumerate.name(), "enumerate");
assert_eq!(X86RangeViewAdaptor::Chunk.name(), "chunk");
assert_eq!(X86RangeViewAdaptor::Iota.name(), "iota");
}
#[test]
fn test_range_view_config_zip() {
let config = X86RangeViewConfig::new(
X86RangeViewAdaptor::Zip,
"int".into(),
);
assert!(!config.is_sized);
assert!(!config.is_borrowed);
assert!(config.is_common);
}
#[test]
fn test_range_view_config_enumerate() {
let config = X86RangeViewConfig::new(
X86RangeViewAdaptor::Enumerate,
"double".into(),
);
assert!(config.is_sized);
assert!(!config.is_borrowed);
}
#[test]
fn test_zip_iterator_deref_type() {
let iter = X86ZipIterator::new(2, vec!["int".into(), "float".into()]);
let dtype = iter.deref_type();
assert!(dtype.contains("std::tuple"));
assert!(dtype.contains("int&"));
assert!(dtype.contains("float&"));
}
#[test]
fn test_enumerate_iterator_element_type() {
let iter = X86EnumerateIterator::new("double".into());
let etype = iter.element_type();
assert!(etype.contains("std::tuple"));
assert!(etype.contains("std::size_t"));
assert!(etype.contains("double&"));
}
#[test]
fn test_ranges_adaptor_registry_new() {
let registry = X86RangesAdaptorRegistry::new();
assert_eq!(registry.count(), 15);
assert!(registry.is_adaptor("zip"));
assert!(registry.is_adaptor("enumerate"));
assert!(!registry.is_adaptor("unknown"));
}
#[test]
fn test_ranges_adaptor_registry_lookup() {
let registry = X86RangesAdaptorRegistry::new();
assert_eq!(registry.lookup("zip"), Some(X86RangeViewAdaptor::Zip));
assert_eq!(registry.lookup("unknown"), None);
}
#[test]
fn test_ranges_to_generate() {
let rt = X86RangesTo::new("std::vector<int>".into(), "my_range".into());
let call = rt.generate();
assert!(call.contains("std::ranges::to"));
assert!(call.contains("std::vector<int>"));
}
#[test]
fn test_range_algorithms_contains() {
let alg = X86RangeAlgorithms::new();
let call = alg.contains("vec", "42");
assert!(call.contains("std::ranges::contains"));
}
#[test]
fn test_range_algorithms_find_last() {
let alg = X86RangeAlgorithms::new();
let call = alg.find_last("vec", "x");
assert!(call.contains("std::ranges::find_last"));
}
// ── 7.20 Paren Aggregate Init Tests ──
#[test]
fn test_paren_aggregate_init_generate() {
let pai = X86ParenAggregateInit::new(
"Point".into(),
vec!["1".into(), "2".into(), "3".into()],
);
let r#gen = pai.generate();
assert_eq!(r#gen, "Point t(1, 2, 3)");
}
#[test]
fn test_paren_aggregate_init_validate_ok() {
let pai = X86ParenAggregateInit::new(
"Point".into(),
vec!["1".into(), "2".into()],
);
assert!(pai.validate(3).is_ok()); // 2 args ≤ 3 members
}
#[test]
fn test_paren_aggregate_init_validate_too_many() {
let pai = X86ParenAggregateInit::new(
"Point".into(),
vec!["1".into(), "2".into(), "3".into(), "4".into()],
);
assert!(pai.validate(2).is_err());
}
// ── 7.21 Pack Indexing Tests ──
#[test]
fn test_pack_indexing_new() {
let pi = X86PackIndexing::new("args".into(), "int".into());
assert_eq!(pi.pack_name, "args");
assert!(pi.enabled);
}
#[test]
fn test_pack_indexing_generate_index() {
let pi = X86PackIndexing::new("args".into(), "int".into());
assert_eq!(pi.generate_index(0), "args...[0]");
assert_eq!(pi.generate_index(2), "args...[2]");
}
#[test]
fn test_pack_indexing_generate_slice() {
let pi = X86PackIndexing::new("args".into(), "int".into());
assert_eq!(pi.generate_slice(0, 3), "args...[0..3]");
}
#[test]
fn test_pack_indexing_validate_in_bounds() {
let mut pi = X86PackIndexing::new("args".into(), "int".into());
pi.size = Some(5);
assert!(pi.validate_index(3).is_ok());
}
#[test]
fn test_pack_indexing_validate_out_of_bounds() {
let mut pi = X86PackIndexing::new("args".into(), "int".into());
pi.size = Some(3);
assert!(pi.validate_index(5).is_err());
}
// ── 7.22 Unnamed Placeholder Tests ──
#[test]
fn test_unnamed_placeholder_is_placeholder() {
let up = X86UnnamedPlaceholder::new(true);
assert!(up.is_placeholder("_"));
assert!(!up.is_placeholder("x"));
}
#[test]
fn test_unnamed_placeholder_generate_name() {
let mut up = X86UnnamedPlaceholder::new(true);
let name1 = up.generate_name();
let name2 = up.generate_name();
assert!(name1.contains("__unnamed_placeholder_"));
assert_ne!(name1, name2);
}
#[test]
fn test_unnamed_placeholder_disabled() {
let up = X86UnnamedPlaceholder::new(false);
assert!(!up.is_placeholder("_"));
}
// ── 7.23 Constexpr Placement New Tests ──
#[test]
fn test_constexpr_allocation_new() {
let alloc = X86ConstexprAllocation::new(0x1000, 64, 16);
assert_eq!(alloc.size, 64);
assert!(alloc.is_aligned());
assert!(!alloc.deallocated);
}
#[test]
fn test_constexpr_allocation_deallocate() {
let mut alloc = X86ConstexprAllocation::new(0x1000, 64, 16);
alloc.deallocate();
assert!(alloc.deallocated);
}
#[test]
fn test_constexpr_allocator_new() {
let allocator = X86ConstexprAllocator::new();
assert_eq!(allocator.total_allocated, 0);
assert!(!allocator.check_leaks());
}
#[test]
fn test_constexpr_allocator_allocate_deallocate() {
let mut allocator = X86ConstexprAllocator::new();
let alloc = allocator.allocate(128, 16);
assert_eq!(allocator.total_allocated, 128);
assert_eq!(allocator.currently_allocated(), 1);
allocator.deallocate(alloc.address).unwrap();
assert_eq!(allocator.currently_allocated(), 0);
}
#[test]
fn test_constexpr_allocator_check_leaks() {
let mut allocator = X86ConstexprAllocator::new();
let alloc = allocator.allocate(64, 8);
assert_eq!(allocator.currently_allocated(), 1);
assert!(!allocator.is_sound());
allocator.deallocate(alloc.address).unwrap();
assert!(allocator.is_sound());
}
#[test]
fn test_constexpr_placement_new_new() {
let cp = X86ConstexprPlacementNew::new(true);
assert!(cp.enabled);
assert_eq!(cp.allocator.total_allocated, 0);
}
// ── 7.24 User Static Assert Tests ──
#[test]
fn test_user_static_assert_generate() {
let sa = X86UserStaticAssert::new(
"sizeof(T) == 4".into(),
"Type T must be 4 bytes".into(),
);
let r#gen = sa.generate();
assert!(r#gen.contains("static_assert"));
assert!(r#gen.contains("sizeof(T) == 4"));
assert!(r#gen.contains("std::string_view"));
}
// ── 7.25 Incomplete Delete Check Tests ──
#[test]
fn test_incomplete_delete_check_ok() {
let checker = X86IncompleteDeleteCheck::new();
assert!(checker.check("MyClass", true).is_ok());
}
#[test]
fn test_incomplete_delete_check_fails() {
let checker = X86IncompleteDeleteCheck::new();
assert!(checker.check("ForwardDeclared", false).is_err());
}
// ── 7.26 InplaceVector Tests ──
#[test]
fn test_inplace_vector_new() {
let v: X86InplaceVector<i32> = X86InplaceVector::new(4);
assert_eq!(v.capacity, 4);
assert!(v.is_empty());
}
#[test]
fn test_inplace_vector_push_pop() {
let mut v: X86InplaceVector<i32> = X86InplaceVector::new(4);
assert!(v.push_back(10).is_ok());
assert_eq!(v.size, 1);
assert_eq!(v.pop_back(), Some(10));
assert!(v.is_empty());
}
#[test]
fn test_inplace_vector_push_until_full() {
let mut v: X86InplaceVector<i32> = X86InplaceVector::new(3);
assert!(v.push_back(1).is_ok());
assert!(v.push_back(2).is_ok());
assert!(v.push_back(3).is_ok());
assert!(v.is_full());
assert!(v.push_back(4).is_err());
}
#[test]
fn test_inplace_vector_get() {
let mut v: X86InplaceVector<i32> = X86InplaceVector::new(4);
v.push_back(42).unwrap();
assert_eq!(v.get(0), Some(&42));
assert_eq!(v.get(1), None);
}
#[test]
fn test_inplace_vector_get_mut() {
let mut v: X86InplaceVector<i32> = X86InplaceVector::new(4);
v.push_back(42).unwrap();
if let Some(val) = v.get_mut(0) {
*val = 99;
}
assert_eq!(v.get(0), Some(&99));
}
#[test]
fn test_inplace_vector_insert() {
let mut v: X86InplaceVector<i32> = X86InplaceVector::new(4);
v.push_back(1).unwrap();
v.push_back(3).unwrap();
v.insert(1, 2).unwrap();
assert_eq!(v.get(0), Some(&1));
assert_eq!(v.get(1), Some(&2));
assert_eq!(v.get(2), Some(&3));
}
#[test]
fn test_inplace_vector_erase() {
let mut v: X86InplaceVector<i32> = X86InplaceVector::new(4);
v.push_back(1).unwrap();
v.push_back(2).unwrap();
v.push_back(3).unwrap();
let removed = v.erase(1).unwrap();
assert_eq!(removed, 2);
assert_eq!(v.size, 2);
assert_eq!(v.get(0), Some(&1));
assert_eq!(v.get(1), Some(&3));
}
#[test]
fn test_inplace_vector_resize() {
let mut v: X86InplaceVector<i32> = X86InplaceVector::new(8);
v.push_back(1).unwrap();
v.resize(3, 0).unwrap();
assert_eq!(v.size, 3);
v.resize(1, 0).unwrap();
assert_eq!(v.size, 1);
}
#[test]
fn test_inplace_vector_clear() {
let mut v: X86InplaceVector<i32> = X86InplaceVector::new(4);
v.push_back(1).unwrap();
v.push_back(2).unwrap();
v.clear();
assert!(v.is_empty());
assert_eq!(v.size, 0);
}
// ── 7.27 Hive Tests ──
#[test]
fn test_hive_new() {
let hive: X86Hive<i32> = X86Hive::new(16);
assert!(hive.is_empty());
assert_eq!(hive.bucket_count(), 0);
}
#[test]
fn test_hive_insert() {
let mut hive: X86Hive<i32> = X86Hive::new(4);
let (bi, si) = hive.insert(42);
assert_eq!(hive.size(), 1);
assert_eq!(hive.bucket_count(), 1);
assert_eq!(bi, 0);
assert_eq!(si, 0);
}
#[test]
fn test_hive_multiple_inserts() {
let mut hive: X86Hive<i32> = X86Hive::new(2);
hive.insert(1);
hive.insert(2);
hive.insert(3); // Should overflow to a new bucket.
assert_eq!(hive.size(), 3);
assert_eq!(hive.bucket_count(), 2);
}
#[test]
fn test_hive_erase() {
let mut hive: X86Hive<i32> = X86Hive::new(4);
let (bi, si) = hive.insert(42);
assert!(hive.erase(bi, si).is_ok());
assert_eq!(hive.size(), 0);
}
#[test]
fn test_hive_erase_invalid() {
let mut hive: X86Hive<i32> = X86Hive::new(4);
assert!(hive.erase(0, 0).is_err());
}
#[test]
fn test_hive_compact() {
let mut hive: X86Hive<i32> = X86Hive::new(2);
hive.insert(1);
hive.insert(2);
let (bi, _) = hive.insert(3); // new bucket
hive.erase(bi, 0).unwrap(); // empty the second bucket
hive.compact();
assert_eq!(hive.bucket_count(), 1);
}
#[test]
fn test_hive_to_vec() {
let mut hive: X86Hive<i32> = X86Hive::new(4);
hive.insert(1);
hive.insert(2);
hive.insert(3);
let vec = hive.to_vec();
assert_eq!(vec.len(), 3);
assert!(vec.contains(&1));
assert!(vec.contains(&2));
assert!(vec.contains(&3));
}
#[test]
fn test_hive_capacity() {
let mut hive: X86Hive<i32> = X86Hive::new(4);
hive.insert(1);
hive.insert(2);
assert_eq!(hive.capacity(), 4);
hive.insert(3);
hive.insert(4);
hive.insert(5); // new bucket
assert_eq!(hive.capacity(), 8);
}
// ── 7.28 IsVirtualBaseOf Tests ──
#[test]
fn test_is_virtual_base_of_new() {
let trait_ = X86IsVirtualBaseOf::new();
assert!(trait_.enabled);
}
#[test]
fn test_is_virtual_base_of_evaluate() {
let trait_ = X86IsVirtualBaseOf::new();
assert!(trait_.evaluate("Base", "Derived", true));
assert!(!trait_.evaluate("Base", "Derived", false));
}
#[test]
fn test_is_virtual_base_of_generate_expr() {
let trait_ = X86IsVirtualBaseOf::new();
let expr = trait_.generate_expr("Base", "Derived");
assert_eq!(expr, "std::is_virtual_base_of_v<Base, Derived>");
}
// ── 7.29 Hazard Pointer & RCU Tests ──
#[test]
fn test_hazard_pointer_new() {
let hp = X86HazardPointer::new(0);
assert!(!hp.is_active);
assert_eq!(hp.address(), None);
}
#[test]
fn test_hazard_pointer_protect() {
let mut hp = X86HazardPointer::new(0);
hp.protect(0xDEADBEEF);
assert!(hp.is_active);
assert_eq!(hp.address(), Some(0xDEADBEEF));
}
#[test]
fn test_hazard_pointer_reset() {
let mut hp = X86HazardPointer::new(0);
hp.protect(0x1000);
hp.reset();
assert!(!hp.is_active);
assert_eq!(hp.address(), None);
}
#[test]
fn test_hazard_pointer_domain_new() {
let domain = X86HazardPointerDomain::new(4);
assert_eq!(domain.max_pointers, 4);
assert_eq!(domain.pointers.len(), 4);
}
#[test]
fn test_hazard_pointer_domain_acquire_release() {
let mut domain = X86HazardPointerDomain::new(2);
let idx = domain.acquire().unwrap();
assert_eq!(domain.active_count(), 1);
domain.release(idx);
assert_eq!(domain.active_count(), 0);
}
#[test]
fn test_hazard_pointer_domain_retire_reclaim() {
let mut domain = X86HazardPointerDomain::new(2);
domain.retire(0x1000, "free".into());
assert_eq!(domain.retired_count(), 1);
let reclaimed = domain.reclaim();
assert_eq!(reclaimed, 1);
assert_eq!(domain.retired_count(), 0);
}
#[test]
fn test_hazard_pointer_registry_new() {
let registry = X86HazardPointerRegistry::new(3, 4);
assert_eq!(registry.domains.len(), 3);
assert!(registry.domain_for(0).is_some());
assert!(registry.domain_for(3).is_none());
}
#[test]
fn test_rcu_domain_new() {
let domain = X86RcuDomain::new(0);
assert!(!domain.is_reader_active());
}
#[test]
fn test_rcu_read_lock() {
let domain = X86RcuDomain::new(0);
let guard = domain.rcu_read_lock();
assert_eq!(guard.domain_id, 0);
}
#[test]
fn test_rcu_synchronize() {
let mut domain = X86RcuDomain::new(0);
domain.synchronize_rcu();
// Should not panic
}
#[test]
fn test_rcu_call_rcu_and_process() {
let mut domain = X86RcuDomain::new(0);
domain.call_rcu(0x2000, "custom_delete".into());
assert_eq!(domain.callbacks.len(), 1);
domain.synchronize_rcu();
// Callbacks from generation 0 should be processed after synchronize.
}
#[test]
fn test_rcu_protected_read_update() {
let mut protected = X86RcuProtected::new(vec![1, 2, 3], 0);
assert_eq!(protected.read().len(), 3);
protected.update(vec![4, 5, 6]);
assert!(protected.update_pending);
}
// ── 7.30 Contracts Tests ──
#[test]
fn test_contract_kind_is_audit() {
assert!(X86ContractKind::PreconditionAudit.is_audit());
assert!(!X86ContractKind::Precondition.is_audit());
}
#[test]
fn test_contract_kind_is_precondition() {
assert!(X86ContractKind::Precondition.is_precondition());
assert!(X86ContractKind::PreconditionAudit.is_precondition());
assert!(!X86ContractKind::Assert.is_precondition());
}
#[test]
fn test_contract_kind_display() {
assert_eq!(format!("{}", X86ContractKind::Precondition), "pre");
assert_eq!(format!("{}", X86ContractKind::Assert), "assert");
}
#[test]
fn test_function_contracts_new() {
let fc = X86FunctionContracts::new("my_func".into(), X86ContractBuildLevel::Default);
assert_eq!(fc.function_name, "my_func");
assert_eq!(fc.total_count(), 0);
}
#[test]
fn test_function_contracts_add_precondition() {
let mut fc = X86FunctionContracts::new("f".into(), X86ContractBuildLevel::Default);
fc.add_precondition("x > 0".into(), None, ("test.cpp".into(), 1, 1), false);
assert_eq!(fc.total_count(), 1);
}
#[test]
fn test_function_contracts_add_postcondition() {
let mut fc = X86FunctionContracts::new("f".into(), X86ContractBuildLevel::Default);
fc.add_postcondition("ret >= 0".into(), Some("ret".into()), ("test.cpp".into(), 10, 1), false);
assert_eq!(fc.total_count(), 1);
}
#[test]
fn test_contract_build_config_should_evaluate() {
let config = X86ContractBuildConfig::default();
assert!(config.should_evaluate(X86ContractKind::Precondition));
assert!(!config.should_evaluate(X86ContractKind::PreconditionAudit));
let audit_config = X86ContractBuildConfig {
level: X86ContractBuildLevel::Audit,
default_continuation: X86ContractContinuationMode::NeverContinue,
};
assert!(audit_config.should_evaluate(X86ContractKind::PreconditionAudit));
let off_config = X86ContractBuildConfig {
level: X86ContractBuildLevel::Off,
default_continuation: X86ContractContinuationMode::NeverContinue,
};
assert!(!off_config.should_evaluate(X86ContractKind::Precondition));
}
#[test]
fn test_contract_continuation_mode_display() {
assert_eq!(
format!("{}", X86ContractContinuationMode::NeverContinue),
"never"
);
assert_eq!(
format!("{}", X86ContractContinuationMode::AlwaysContinue),
"always"
);
}
// ── 7.31 Reflection Tests ──
#[test]
fn test_reflection_operator_reflect_type() {
let op = X86ReflectionOperator::reflect_type("int");
assert_eq!(op.entity, "int");
assert_eq!(op.info.entity_kind, X86MetaEntityKind::Type);
}
#[test]
fn test_reflection_operator_reflect_class() {
let op = X86ReflectionOperator::reflect_class("MyClass");
assert_eq!(op.info.entity_kind, X86MetaEntityKind::Class);
}
#[test]
fn test_splicer_new() {
let info = X86MetaInfo {
handle: 1,
entity_kind: X86MetaEntityKind::Type,
source_location: "test.cpp:10".into(),
display_name: "int".into(),
};
let splicer = X86Splicer::new("expr".into(), info);
assert_eq!(splicer.expression, "expr");
}
#[test]
fn test_splicer_type_splicer() {
let info = X86MetaInfo {
handle: 1,
entity_kind: X86MetaEntityKind::Type,
source_location: String::new(),
display_name: "T".into(),
};
let splicer = X86Splicer::type_splicer("meta_type".into(), info);
assert!(splicer.expression.contains("typename"));
}
#[test]
fn test_reflection_context_new() {
let ctx = X86ReflectionContext::new();
assert_eq!(ctx.nesting_depth, 0);
assert!(ctx.operations.is_empty());
}
#[test]
fn test_reflection_context_enum_to_string() {
let mut ctx = X86ReflectionContext::new();
let code = ctx.generate_enum_to_string(
"Color",
&[("Red", 0), ("Green", 1), ("Blue", 2)],
);
assert_eq!(code.len(), 8); // function signature + switch + 3 cases + default + 2 closing braces
assert!(code.join("\n").contains("to_string"));
}
#[test]
fn test_meta_entity_kind_display() {
assert_eq!(format!("{}", X86MetaEntityKind::Type), "type");
assert_eq!(format!("{}", X86MetaEntityKind::Class), "class");
assert_eq!(format!("{}", X86MetaEntityKind::Lambda), "lambda");
}
// ── 7.32 Pattern Matching Tests ──
#[test]
fn test_inspect_expression_new() {
let ie = X86InspectExpression::new("value".into(), "int".into());
assert_eq!(ie.scrutinee, "value");
assert!(!ie.exhaustive);
}
#[test]
fn test_inspect_expression_add_case() {
let mut ie = X86InspectExpression::new("v".into(), "int".into());
ie.add_case(X86MatchPattern::IntegerLiteral(0), "return 0;".into());
assert_eq!(ie.cases.len(), 1);
}
#[test]
fn test_inspect_expression_generate() {
let mut ie = X86InspectExpression::new("v".into(), "int".into());
ie.add_case(X86MatchPattern::IntegerLiteral(1), "handle_one();".into());
ie.add_case(X86MatchPattern::Wildcard, "handle_other();".into());
let code = ie.generate();
assert!(code.contains("inspect"));
assert!(code.contains("1 =>"));
assert!(code.contains("_ =>"));
}
#[test]
fn test_inspect_expression_exhaustiveness() {
let mut ie = X86InspectExpression::new("v".into(), "int".into());
ie.add_case(X86MatchPattern::IntegerLiteral(1), "a".into());
assert!(!ie.check_exhaustiveness());
ie.add_case(X86MatchPattern::Wildcard, "b".into());
assert!(ie.check_exhaustiveness());
}
#[test]
fn test_match_pattern_display() {
assert_eq!(format!("{}", X86MatchPattern::Wildcard), "_");
assert_eq!(format!("{}", X86MatchPattern::IntegerLiteral(42)), "42");
assert_eq!(format!("{}", X86MatchPattern::Binding("x".into())), "x");
}
// ── 7.33 Senders/Receivers Tests ──
#[test]
fn test_sender_descriptor_just() {
let sd = X86SenderDescriptor::just("int".into());
assert_eq!(sd.value_types, vec!["int"]);
assert!(sd.always_completes);
}
#[test]
fn test_sender_adaptor_type_name() {
let adaptor = X86SenderAdaptor::Then {
function: "f".into(),
input_type: "int".into(),
output_type: "double".into(),
};
assert_eq!(adaptor.type_name(), "then_t");
}
#[test]
fn test_sender_adaptor_input_arity() {
let adaptor = X86SenderAdaptor::WhenAll { sender_count: 3 };
assert_eq!(adaptor.input_arity(), 3);
}
#[test]
fn test_execution_context_then_chain() {
let mut ctx = X86ExecutionContext::new("thread_pool".into());
ctx.then("func1".into(), "int".into(), "float".into());
let chain = ctx.generate_chain();
assert!(chain.contains("thread_pool"));
assert!(chain.contains("func1"));
}
// ── 7.34 SIMD Tests ──
#[test]
fn test_simd_type_new() {
let simd = X86SimdType::new("float".into(), 4);
assert_eq!(simd.scalar_type, "float");
assert_eq!(simd.size, 4);
}
#[test]
fn test_simd_type_type_name() {
let simd = X86SimdType::new("double".into(), 4);
assert_eq!(simd.type_name(), "std::simd<double, 4>");
}
#[test]
fn test_simd_type_mask_type() {
let simd = X86SimdType::new("float".into(), 8);
assert_eq!(simd.mask_type(), "std::simd_mask<float, 8>");
}
#[test]
fn test_simd_math_op_function_name() {
assert_eq!(X86SimdMathOp::Sqrt.function_name(), "sqrt");
assert_eq!(X86SimdMathOp::Sin.function_name(), "sin");
assert_eq!(X86SimdMathOp::Fma.function_name(), "fma");
}
#[test]
fn test_simd_math_op_arity() {
assert_eq!(X86SimdMathOp::Sqrt.arity(), 1);
assert_eq!(X86SimdMathOp::Atan2.arity(), 2);
assert_eq!(X86SimdMathOp::Fma.arity(), 2);
}
#[test]
fn test_simd_math_op_generate_x86_intrinsic() {
let simd = X86SimdType::new("double".into(), 4);
let intrinsic = X86SimdMathOp::Sqrt.generate_x86_intrinsic(&simd, CXX23SimdLevel::SSE2);
assert!(intrinsic.contains("sqrt"));
}
#[test]
fn test_simd_math_registry_new_float() {
let simd = X86SimdType::new("float".into(), 4);
let registry = X86SimdMathRegistry::new(simd, CXX23SimdLevel::SSE2);
assert!(registry.has_float_support);
assert!(!registry.has_integer_support);
assert!(registry.op_count() > 0);
}
#[test]
fn test_simd_math_registry_new_int() {
let simd = X86SimdType::new("int".into(), 4);
let registry = X86SimdMathRegistry::new(simd, CXX23SimdLevel::SSE2);
assert!(!registry.has_float_support);
assert!(registry.has_integer_support);
assert!(registry.supports(X86SimdMathOp::Abs));
assert!(!registry.supports(X86SimdMathOp::Sin));
}
// ── 7.35 Feature Detection Tests ──
#[test]
fn test_x86_cxx_feature_name() {
assert!(X86CXXFeature::DeducingThis.name().contains("P0847R7"));
assert!(X86CXXFeature::IfConsteval.name().contains("P1938R3"));
}
#[test]
fn test_x86_cxx_feature_paper_number() {
assert_eq!(X86CXXFeature::DeducingThis.paper_number(), "P0847R7");
assert_eq!(X86CXXFeature::Mdspan.paper_number(), "P0009R18");
assert_eq!(X86CXXFeature::PackIndexing.paper_number(), "P2662R3");
}
#[test]
fn test_x86_cxx_feature_feature_test_macro() {
assert_eq!(
X86CXXFeature::OptionalMonadic.feature_test_macro(),
"__cpp_lib_optional_monadic"
);
assert_eq!(
X86CXXFeature::ZipView.feature_test_macro(),
"__cpp_lib_ranges_zip"
);
}
#[test]
fn test_x86_cxx_feature_feature_test_value() {
assert_eq!(X86CXXFeature::DeducingThis.feature_test_value(), 202110);
assert_eq!(X86CXXFeature::PackIndexing.feature_test_value(), 202602);
}
#[test]
fn test_x86_cxx_feature_min_standard() {
assert_eq!(
X86CXXFeature::DeducingThis.min_standard(),
X86CXXStandard::CXX23
);
assert_eq!(
X86CXXFeature::Contracts.min_standard(),
X86CXXStandard::CXX26
);
}
#[test]
fn test_x86_cxx_feature_requires_simd() {
assert!(X86CXXFeature::SimdExtensions.requires_simd());
assert!(!X86CXXFeature::DeducingThis.requires_simd());
}
#[test]
fn test_x86_cxx_feature_is_cxx26_preview() {
assert!(!X86CXXFeature::DeducingThis.is_cxx26_preview());
assert!(X86CXXFeature::PackIndexing.is_cxx26_preview());
}
#[test]
fn test_features_new_x86_64_cxx23() {
let features = X86CXX23Features::new_x86_64(X86CXXStandard::CXX23);
assert_eq!(features.standard(), X86CXXStandard::CXX23);
assert!(features.is_enabled(&X86CXXFeature::DeducingThis));
assert!(!features.is_enabled(&X86CXXFeature::Contracts));
assert!(features.enabled_count() > 0);
}
#[test]
fn test_features_new_x86_64_cxx26() {
let features = X86CXX23Features::new_x86_64(X86CXXStandard::CXX26);
assert!(features.is_enabled(&X86CXXFeature::Contracts));
assert!(features.is_enabled(&X86CXXFeature::SimdExtensions)); // SSE2 available
}
#[test]
fn test_features_new_x86_32() {
let features = X86CXX23Features::new_x86_32(X86CXXStandard::CXX26);
assert!(!features.is_enabled(&X86CXXFeature::SimdExtensions)); // No SIMD on x86_32
}
#[test]
fn test_features_enable_disable() {
let mut features = X86CXX23Features::new_x86_64(X86CXXStandard::CXX23);
assert!(features.is_enabled(&X86CXXFeature::DeducingThis));
features.disable(X86CXXFeature::DeducingThis);
assert!(!features.is_enabled(&X86CXXFeature::DeducingThis));
features.enable(X86CXXFeature::DeducingThis);
assert!(features.is_enabled(&X86CXXFeature::DeducingThis));
}
#[test]
fn test_features_enabled_lists() {
let features = X86CXX23Features::new_x86_64(X86CXXStandard::CXX23);
let cxx23 = features.cxx23_enabled_features();
assert!(!cxx23.is_empty());
let cxx26 = features.cxx26_enabled_features();
assert!(cxx26.is_empty());
}
#[test]
fn test_features_generate_macros() {
let features = X86CXX23Features::new_x86_64(X86CXXStandard::CXX23);
let source = features.generate_feature_test_macros_source();
assert!(source.contains("#define"));
assert!(source.contains("__cpp_explicit_this_parameter"));
assert!(source.contains("202110"));
}
#[test]
fn test_features_feature_count() {
let features = X86CXX23Features::new_x86_64(X86CXXStandard::CXX23);
assert_eq!(features.feature_count(), X86CXXFeature::SimdExtensions as usize + 1);
}
// ── 7.36 CodeGen Tests ──
#[test]
fn test_codegen_new_x86_64() {
let cg = X86CXX23CodeGen::new(
CXX23X86Arch::X86_64,
CXX23SimdLevel::SSE2,
X86CXXStandard::CXX23,
);
assert_eq!(cg.pointer_size, 8);
assert_eq!(cg.size_t_size, 8);
assert!(cg.deducing_this_codegen);
assert!(cg.multi_dim_subscript_codegen);
}
#[test]
fn test_codegen_new_x86_32() {
let cg = X86CXX23CodeGen::new(
CXX23X86Arch::X86_32,
CXX23SimdLevel::None,
X86CXXStandard::CXX23,
);
assert_eq!(cg.pointer_size, 4);
assert_eq!(cg.size_t_size, 4);
}
#[test]
fn test_codegen_lower_deducing_this() {
let cg = X86CXX23CodeGen::new(
CXX23X86Arch::X86_64,
CXX23SimdLevel::SSE2,
X86CXXStandard::CXX23,
);
let func = X86ExplicitObjectFunction::new(
"print".into(),
"this auto&& self".into(),
vec![],
"void".into(),
true,
Some("Printer".into()),
);
let ir = cg.lower_deducing_this(&func, "Printer", &["obj".into()]);
assert!(ir.contains("deducing-this lowering"));
assert!(ir.contains("call"));
}
#[test]
fn test_codegen_lower_multi_dim_subscript() {
let cg = X86CXX23CodeGen::new(
CXX23X86Arch::X86_64,
CXX23SimdLevel::SSE2,
X86CXXStandard::CXX23,
);
let ir = cg.lower_multi_dim_subscript(
"%mat",
"double",
&[1, 2],
&[3, 4],
);
assert!(ir.contains("getelementptr"));
}
#[test]
fn test_codegen_lower_generator_frame() {
let cg = X86CXX23CodeGen::new(
CXX23X86Arch::X86_64,
CXX23SimdLevel::SSE2,
X86CXXStandard::CXX23,
);
let r#gen = X86Generator::new("int".into());
let ir = cg.lower_generator_frame(&r#gen);
assert!(ir.contains("generator.frame"));
assert!(ir.contains("llvm.coro.init"));
}
#[test]
fn test_codegen_lower_generator_yield() {
let cg = X86CXX23CodeGen::new(
CXX23X86Arch::X86_64,
CXX23SimdLevel::SSE2,
X86CXXStandard::CXX23,
);
let r#gen = X86Generator::new("double".into());
let ir = cg.lower_generator_yield(&r#gen, "%val42");
assert!(ir.contains("llvm.coro.suspend"));
}
#[test]
fn test_codegen_lower_expected_layout() {
let cg = X86CXX23CodeGen::new(
CXX23X86Arch::X86_64,
CXX23SimdLevel::SSE2,
X86CXXStandard::CXX23,
);
let exp = X86ExpectedType::new("int".into(), "std::string".into());
let layout = cg.lower_expected_layout(&exp);
assert!(layout.contains("has_value"));
assert!(layout.contains("union"));
}
#[test]
fn test_codegen_lower_expected_access() {
let cg = X86CXX23CodeGen::new(
CXX23X86Arch::X86_64,
CXX23SimdLevel::SSE2,
X86CXXStandard::CXX23,
);
let exp = X86ExpectedType::new("int".into(), "error".into());
let ir = cg.lower_expected_access(&exp, "%ptr");
assert!(ir.contains("icmp ne"));
assert!(ir.contains("value_block"));
assert!(ir.contains("error_block"));
}
#[test]
fn test_codegen_lower_mdspan_access() {
let cg = X86CXX23CodeGen::new(
CXX23X86Arch::X86_64,
CXX23SimdLevel::SSE2,
X86CXXStandard::CXX23,
);
let mut md = X86Mdspan::new(
"float".into(),
vec![X86MdspanExtent::Static(3), X86MdspanExtent::Static(4)],
);
md.data_ptr = "%data".into();
let ir = cg.lower_mdspan_access(&md, &[1, 2]);
assert!(ir.contains("getelementptr"));
assert!(ir.contains("load"));
assert!(ir.contains("float"));
}
#[test]
fn test_codegen_lower_flat_map_insert() {
let cg = X86CXX23CodeGen::new(
CXX23X86Arch::X86_64,
CXX23SimdLevel::SSE2,
X86CXXStandard::CXX23,
);
let ir = cg.lower_flat_map_insert("int", "double", "%key", "%val");
assert!(ir.contains("flat_map"));
assert!(ir.contains("lower_bound"));
}
#[test]
fn test_codegen_lower_paren_aggregate_init() {
let cg = X86CXX23CodeGen::new(
CXX23X86Arch::X86_64,
CXX23SimdLevel::SSE2,
X86CXXStandard::CXX23,
);
let ir = cg.lower_paren_aggregate_init(
"Point",
&["float".into(), "float".into()],
&["%x".into(), "%y".into()],
);
assert!(ir.contains("aggregate init"));
assert!(ir.contains("alloca"));
assert!(ir.contains("getelementptr"));
}
#[test]
fn test_codegen_target_triple() {
let cg64 = X86CXX23CodeGen::new(
CXX23X86Arch::X86_64,
CXX23SimdLevel::SSE2,
X86CXXStandard::CXX23,
);
let cg32 = X86CXX23CodeGen::new(
CXX23X86Arch::X86_32,
CXX23SimdLevel::None,
X86CXXStandard::CXX23,
);
assert_eq!(cg64.target_triple(), "x86_64-unknown-linux-gnu");
assert_eq!(cg32.target_triple(), "i386-unknown-linux-gnu");
}
#[test]
fn test_codegen_data_layout() {
let cg64 = X86CXX23CodeGen::new(
CXX23X86Arch::X86_64,
CXX23SimdLevel::SSE2,
X86CXXStandard::CXX23,
);
let dl = cg64.data_layout();
assert!(dl.contains("e-m:e-p"));
assert!(dl.contains("S128"));
}
// ── 7.37 Edge Case and Integration Tests ──
#[test]
fn test_cxx23_26_full_pipeline_instantiation() {
let mut framework = X86CXX23_26::new_x86_64_cxx23();
framework.enable_simd(CXX23SimdLevel::AVX2);
assert_eq!(framework.simd_level, CXX23SimdLevel::AVX2);
let enabled = framework.features.enabled_features();
assert!(!enabled.is_empty());
// Check that C++23 core features are enabled
assert!(framework.is_feature_enabled(&X86CXXFeature::DeducingThis));
assert!(framework.is_feature_enabled(&X86CXXFeature::IfConsteval));
assert!(framework.is_feature_enabled(&X86CXXFeature::StaticOperatorCall));
assert!(framework.is_feature_enabled(&X86CXXFeature::OptionalMonadic));
assert!(framework.is_feature_enabled(&X86CXXFeature::Expected));
assert!(framework.is_feature_enabled(&X86CXXFeature::ZipView));
}
#[test]
fn test_cxx26_full_pipeline_instantiation() {
let framework = X86CXX23_26::new_x86_64_cxx26();
// All C++26 preview features should be enabled
assert!(framework.is_feature_enabled(&X86CXXFeature::Contracts));
assert!(framework.is_feature_enabled(&X86CXXFeature::Reflection));
assert!(framework.is_feature_enabled(&X86CXXFeature::PatternMatching));
assert!(framework.is_feature_enabled(&X86CXXFeature::SendersReceivers));
assert!(framework.is_feature_enabled(&X86CXXFeature::PackIndexing));
assert!(framework.is_feature_enabled(&X86CXXFeature::ConstexprPlacementNew));
assert!(framework.is_feature_enabled(&X86CXXFeature::InplaceVector));
assert!(framework.is_feature_enabled(&X86CXXFeature::Hive));
assert!(framework.is_feature_enabled(&X86CXXFeature::IsVirtualBaseOf));
assert!(framework.is_feature_enabled(&X86CXXFeature::HazardPointers));
assert!(framework.is_feature_enabled(&X86CXXFeature::Rcu));
assert!(framework.is_feature_enabled(&X86CXXFeature::SimdExtensions));
}
#[test]
fn test_rcu_read_guard_generation() {
let guard = X86RcuReadGuard {
domain_id: 1,
generation: 5,
};
assert_eq!(guard.generation(), 5);
assert_eq!(guard.domain_id, 1);
}
#[test]
fn test_arch_display() {
assert_eq!(format!("{}", CXX23X86Arch::X86_64), "x86_64");
assert_eq!(format!("{}", CXX23X86Arch::X86_32), "i386");
}
#[test]
fn test_cxx_standard_display() {
assert_eq!(format!("{}", X86CXXStandard::CXX23), "c++23");
assert_eq!(format!("{}", X86CXXStandard::CXX26), "c++26");
}
#[test]
fn test_expected_monadic_op_display() {
assert_eq!(format!("{}", X86ExpectedMonadicOp::AndThen), "and_then");
assert_eq!(format!("{}", X86ExpectedMonadicOp::OrElse), "or_else");
assert_eq!(format!("{}", X86ExpectedMonadicOp::Transform), "transform");
assert_eq!(format!("{}", X86ExpectedMonadicOp::TransformError), "transform_error");
}
#[test]
fn test_simd_level_ordering() {
assert!(CXX23SimdLevel::AVX512F > CXX23SimdLevel::AVX2);
assert!(CXX23SimdLevel::AVX2 > CXX23SimdLevel::AVX);
assert!(CXX23SimdLevel::AVX > CXX23SimdLevel::SSE2);
assert!(CXX23SimdLevel::SSE2 > CXX23SimdLevel::None);
}
#[test]
fn test_completion_signal_display() {
assert_eq!(format!("{}", X86CompletionSignal::SetValue), "set_value");
assert_eq!(format!("{}", X86CompletionSignal::SetError), "set_error");
assert_eq!(format!("{}", X86CompletionSignal::SetStopped), "set_stopped");
}
}