Files
2026-07-13 12:47:05 +08:00

2990 lines
129 KiB
CMake
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ============================================================================
#
# Optimized version with debug profiles removed for production builds.
# Conditional diagnostics only when explicitly enabled via SD_ENABLE_DIAGNOSTICS.
# ============================================================================
# Include the reporting functions
include(SelectiveRenderingReports)
# ============================================================================
# HELPER FUNCTION: Write file only if content changed (preserves mtime for PCH)
# ============================================================================
function(_srcore_write_if_different filepath content)
set(should_write TRUE)
# Check if file already exists
if(EXISTS "${filepath}")
# Read existing content
file(READ "${filepath}" existing_content)
# Compare content
if("${existing_content}" STREQUAL "${content}")
set(should_write FALSE)
endif()
endif()
# Only write if content changed or file doesn't exist
if(should_write)
file(WRITE "${filepath}" "${content}")
endif()
endfunction()
# Export type validation results for use by SelectiveRenderingCore
function(export_validated_types_for_selective_rendering)
if(SD_TYPES_LIST_COUNT GREATER 0)
set(SRCORE_USE_SELECTIVE_TYPES TRUE PARENT_SCOPE)
set(SRCORE_VALIDATED_TYPES "${SD_TYPES_LIST}" PARENT_SCOPE)
if(SD_ENABLE_DIAGNOSTICS)
message(STATUS "Exporting SELECTIVE types for SelectiveRenderingCore: ${SD_TYPES_LIST}")
endif()
else()
set(SRCORE_USE_SELECTIVE_TYPES FALSE PARENT_SCOPE)
set(SRCORE_VALIDATED_TYPES "" PARENT_SCOPE)
if(SD_ENABLE_DIAGNOSTICS)
message(STATUS "Exporting ALL_TYPES mode for SelectiveRenderingCore")
endif()
endif()
endfunction()
# ============================================================================
# SECTION 1: SEMANTIC FILTERING LOGIC (Optimized)
# ============================================================================
function(_internal_srcore_is_type_numeric type_name output_var)
# Include all numeric types
set(numeric_types "BOOL;INT8;UINT8;INT16;UINT16;INT32;UINT32;INT64;UINT64;FLOAT32;DOUBLE;HALF;BFLOAT16")
list(FIND numeric_types "${type_name}" found_index)
if(found_index GREATER_EQUAL 0)
set(${output_var} TRUE PARENT_SCOPE)
else()
set(${output_var} FALSE PARENT_SCOPE)
endif()
endfunction()
function(_internal_srcore_is_type_floating type_name output_var)
set(floating_types "DOUBLE;FLOAT32;HALF;BFLOAT16")
list(FIND floating_types "${type_name}" found_index)
if(found_index GREATER_EQUAL 0)
set(${output_var} TRUE PARENT_SCOPE)
else()
set(${output_var} FALSE PARENT_SCOPE)
endif()
endfunction()
function(_internal_srcore_is_type_integer type_name output_var)
# Include both signed and unsigned integer types
set(integer_types "INT8;UINT8;INT16;UINT16;INT32;UINT32;INT64;UINT64;BOOL")
list(FIND integer_types "${type_name}" found_index)
if(found_index GREATER_EQUAL 0)
set(${output_var} TRUE PARENT_SCOPE)
else()
set(${output_var} FALSE PARENT_SCOPE)
endif()
endfunction()
function(_internal_srcore_get_type_priority type_name output_var)
# Proper priority ordering: higher precision = higher priority
if(type_name STREQUAL "DOUBLE")
set(${output_var} 10 PARENT_SCOPE)
elseif(type_name STREQUAL "INT64")
set(${output_var} 9 PARENT_SCOPE)
elseif(type_name STREQUAL "UINT64")
set(${output_var} 8 PARENT_SCOPE)
elseif(type_name STREQUAL "FLOAT32")
set(${output_var} 7 PARENT_SCOPE)
elseif(type_name STREQUAL "INT32")
set(${output_var} 6 PARENT_SCOPE)
elseif(type_name STREQUAL "UINT32")
set(${output_var} 5 PARENT_SCOPE)
elseif(type_name STREQUAL "BFLOAT16")
set(${output_var} 4 PARENT_SCOPE)
elseif(type_name STREQUAL "HALF")
set(${output_var} 4 PARENT_SCOPE)
elseif(type_name STREQUAL "INT16")
set(${output_var} 3 PARENT_SCOPE)
elseif(type_name STREQUAL "UINT16")
set(${output_var} 3 PARENT_SCOPE)
elseif(type_name STREQUAL "INT8")
set(${output_var} 2 PARENT_SCOPE)
elseif(type_name STREQUAL "UINT8")
set(${output_var} 2 PARENT_SCOPE)
elseif(type_name STREQUAL "BOOL")
set(${output_var} 1 PARENT_SCOPE)
else()
set(${output_var} 0 PARENT_SCOPE)
endif()
endfunction()
# SelectiveRenderingCore.cmake - Validation Functions
function(_internal_srcore_is_valid_pair type1 type2 output_var)
# 2-TYPE COMBINATION FILTERING FOR FUNCTRACE BUILDS
#
# Background: Functrace builds create ~3.3GB binaries (vs ~200MB normal) due to
# instrumentation overhead on every template instantiation. With 196 2-type
# combinations (14×14 with no filtering), the binary exceeds 2GB relocation limit.
#
# Solution: Filter rare/exotic type conversions while preserving commonly used ones.
# This reduces binary size without impacting model execution.
#
# Filtering Strategy:
# 1. KEEP: Same-type operations (X→X)
# 2. KEEP: Common numeric conversions (float↔double, int32↔int64)
# 3. KEEP: Numeric↔bool conversions (for comparisons)
# 4. FILTER: Rare integer cross-conversions (uint16↔uint32, int16↔uint64)
# 5. FILTER: Exotic combinations (bool↔float16, uint8↔bfloat16)
# 6. FILTER: String type conversions (rarely used in hot paths)
# Rule 1: Same-type operations always valid
if(type1 STREQUAL type2)
set(${output_var} TRUE PARENT_SCOPE)
return()
endif()
# Get type categories
_internal_srcore_is_type_floating("${type1}" t1_is_float)
_internal_srcore_is_type_floating("${type2}" t2_is_float)
_internal_srcore_is_type_integer("${type1}" t1_is_int)
_internal_srcore_is_type_integer("${type2}" t2_is_int)
set(t1_is_bool FALSE)
set(t2_is_bool FALSE)
if(type1 STREQUAL "BOOL")
set(t1_is_bool TRUE)
endif()
if(type2 STREQUAL "BOOL")
set(t2_is_bool TRUE)
endif()
# Check if types are "rare" (uint16, uint32, uint64, int16)
set(rare_types "UINT16;UINT32;UINT64;INT16")
list(FIND rare_types "${type1}" t1_rare_idx)
list(FIND rare_types "${type2}" t2_rare_idx)
set(t1_is_rare FALSE)
set(t2_is_rare FALSE)
if(t1_rare_idx GREATER_EQUAL 0)
set(t1_is_rare TRUE)
endif()
if(t2_rare_idx GREATER_EQUAL 0)
set(t2_is_rare TRUE)
endif()
# Check if types are exotic floats (float16, bfloat16)
set(exotic_float_types "HALF;BFLOAT16")
list(FIND exotic_float_types "${type1}" t1_exotic_idx)
list(FIND exotic_float_types "${type2}" t2_exotic_idx)
set(t1_is_exotic FALSE)
set(t2_is_exotic FALSE)
if(t1_exotic_idx GREATER_EQUAL 0)
set(t1_is_exotic TRUE)
endif()
if(t2_exotic_idx GREATER_EQUAL 0)
set(t2_is_exotic TRUE)
endif()
# Rule 2: Filter string type conversions (rarely used)
if(type1 MATCHES "UTF8" OR type2 MATCHES "UTF8")
set(${output_var} FALSE PARENT_SCOPE)
return()
endif()
# Rule 3: Filter rare×rare cross-type conversions
# Examples: uint16↔uint32, int16↔uint64
# These are rarely used in ML workloads
if(t1_is_rare AND t2_is_rare)
# Both are rare types and already filtered out same-type by Rule 1
set(${output_var} FALSE PARENT_SCOPE)
return()
endif()
# Rule 4: DISABLED - bool↔exotic float conversions ARE needed
# Examples that failed linking: ScalarTransform<bfloat16, float16, bool>
# if((t1_is_bool AND t2_is_exotic) OR (t1_is_exotic AND t2_is_bool))
# set(${output_var} FALSE PARENT_SCOPE)
# return()
# endif()
# Rule 5: DISABLED - exotic float×rare integer combinations ARE needed
# Examples that failed linking: PairWiseTransform<bfloat16, *, short/uint16/uint64>
# if((t1_is_exotic AND t2_is_rare) OR (t1_is_rare AND t2_is_exotic))
# set(${output_var} FALSE PARENT_SCOPE)
# return()
# endif()
# Rule 6: DISABLED - exotic float cross-conversions ARE needed
# Examples that failed linking: PairWiseTransform<bfloat16, *, float16>
# if(t1_is_exotic AND t2_is_exotic)
# # Both exotic and different types (same-type filtered by Rule 1)
# set(${output_var} FALSE PARENT_SCOPE)
# return()
# endif()
# All other combinations are valid:
# - Common numeric conversions (float↔double, int32↔int64)
# - Numeric↔bool (comparisons and masks)
# - Integer promotions (int8→int32, uint8→uint32)
# - Rare types with common types (uint16↔int32, int16↔float)
# - Exotic floats with common types (float16↔float, bfloat16↔double)
set(${output_var} TRUE PARENT_SCOPE)
endfunction()
# SelectiveRenderingCore.cmake - Triple Validation Function
function(_internal_srcore_is_valid_triple type1 type2 type3 output_var)
# SEMANTIC FILTERING: Filter invalid type combinations while preserving all valid ones
#
# Previous approach (accept ALL) generated 2,197 combinations including many invalid ones:
# - bool × bool → float (arithmetic on bools producing floats doesn't make sense)
# - Excessive uint16/32/64 combinations (59% of combinations, rarely used)
#
# Filtering strategy (incremental):
# - Phase 1: Filter bool × bool → numeric (13 combinations)
# - Phase 2: Filter rare × rare → rare (cross-type) (64 combinations)
#
# Valid combination patterns:
# 1. Same-type operations: (X, X, X)
# 2. Type promotion within category: (smaller, larger, larger)
# 3. Comparison operations: (any, any, bool)
# 4. Type conversion/casting: (any, any, any) with restrictions
# 5. Bool masking: (bool, numeric, numeric)
# 6. Rare types with common types: (rare, common, any) and (common, rare, any)
# Get type categories
_internal_srcore_is_type_floating("${type1}" t1_is_float)
_internal_srcore_is_type_floating("${type2}" t2_is_float)
_internal_srcore_is_type_floating("${type3}" t3_is_float)
_internal_srcore_is_type_integer("${type1}" t1_is_int)
_internal_srcore_is_type_integer("${type2}" t2_is_int)
_internal_srcore_is_type_integer("${type3}" t3_is_int)
set(t1_is_bool FALSE)
set(t2_is_bool FALSE)
set(t3_is_bool FALSE)
if(type1 STREQUAL "BOOL")
set(t1_is_bool TRUE)
endif()
if(type2 STREQUAL "BOOL")
set(t2_is_bool TRUE)
endif()
if(type3 STREQUAL "BOOL")
set(t3_is_bool TRUE)
endif()
# Check if types are rare types (rarely used in ML workloads)
# Rare types: UINT16, UINT32, UINT64, INT16
set(rare_types "UINT16;UINT32;UINT64;INT16")
set(t1_is_rare FALSE)
set(t2_is_rare FALSE)
set(t3_is_rare FALSE)
list(FIND rare_types "${type1}" t1_rare_idx)
if(t1_rare_idx GREATER_EQUAL 0)
set(t1_is_rare TRUE)
endif()
list(FIND rare_types "${type2}" t2_rare_idx)
if(t2_rare_idx GREATER_EQUAL 0)
set(t2_is_rare TRUE)
endif()
list(FIND rare_types "${type3}" t3_rare_idx)
if(t3_rare_idx GREATER_EQUAL 0)
set(t3_is_rare TRUE)
endif()
# Rule 1: Same-type operations are always valid (X, X, X)
if(type1 STREQUAL type2 AND type2 STREQUAL type3)
set(${output_var} TRUE PARENT_SCOPE)
return()
endif()
# Rule 2: Comparison operations (any, any, bool) are usually valid
# This covers ==, !=, <, >, <=, >= operations
# However, filter cross-rare-type comparisons (both inputs different rare types)
if(t3_is_bool)
# If comparing two different rare types, filter it
# Examples: (UINT16, UINT32, bool), (INT16, UINT64, bool)
# These cross-rare-type comparisons are genuinely rare in practice
if(t1_is_rare AND t2_is_rare AND NOT type1 STREQUAL type2)
set(${output_var} FALSE PARENT_SCOPE)
return()
endif()
# All other comparisons are valid
set(${output_var} TRUE PARENT_SCOPE)
return()
endif()
# Rule 3: Filter INVALID bool arithmetic combinations
# bool × bool → numeric doesn't make semantic sense (what is bool + bool → float?)
if(t1_is_bool AND t2_is_bool AND NOT t3_is_bool)
set(${output_var} FALSE PARENT_SCOPE)
return()
endif()
# Rule 4: Filter RARE × RARE cross-type combinations
# Strategy 4: Conservative rare-type filtering (Phase 3 optimization)
#
# Rare types (UINT16, UINT32, UINT64, INT16) are rarely used in ML workloads:
# - Actual code usage: ~88 lines across entire codebase
# - UINT32/UINT64 not in test suite
# - 54% of instantiations use these types, but <1% of operations code
#
# Filter combinations where INPUTS are different rare types:
# - uint32 × int16 → int32 (different rare inputs)
# - uint16 × uint32 → float32 (different rare inputs)
# - int16 × uint64 → bool (different rare inputs, even though output is bool)
#
# Preserve:
# - Same-type rare operations: uint32 × uint32 → uint32 (already handled by Rule 1)
# - Same rare inputs: uint32 × uint32 → int32 (same rare inputs, different output OK)
# - Rare with common types: uint32 × int32 → any (one input is common)
# - Common with rare: int32 × uint16 → any (one input is common)
#
# This filtering eliminates ~180 additional combinations with no semantic meaning,
# saving ~2.7GB total and achieving ~7% reduction with minimal risk.
#
# to prevent them from accepting these cross-rare-type combinations.
# Check if both inputs are rare types
if(t1_is_rare AND t2_is_rare)
# Both inputs are rare types
# Only allow if they're the SAME rare type (regardless of output)
if(NOT type1 STREQUAL type2)
# Different rare types in inputs - filter this combination
# Examples: uint32 × int16 → any, uint16 × uint32 → any
set(${output_var} FALSE PARENT_SCOPE)
return()
endif()
# Strategy 5: Filter rare×rare→rare (same inputs, rare output)
# Even when inputs are the same rare type, outputting another rare type is uncommon
# This typically indicates unnecessary type conversions
# Examples to filter:
# - uint32 × uint32 → uint16 (rare inputs → rare output)
# - uint32 × uint32 → uint64 (rare inputs → rare output)
# - int16 × int16 → int8 (rare inputs → rare output)
# Examples to KEEP:
# - uint32 × uint32 → uint32 (same type operation - handled by Rule 1)
# - uint32 × uint32 → int32 (rare → common output)
# - uint32 × uint32 → float32 (rare → common output)
# - uint32 × uint32 → bool (comparison - handled by Rule 2)
if(t3_is_rare AND NOT type1 STREQUAL type3)
# Rare inputs, different rare output - filter
# Keep only if output equals input type (Rule 1 handles this)
set(${output_var} FALSE PARENT_SCOPE)
return()
endif()
# If type1 == type2 == type3 (all same), Rule 1 already allowed it
# If type1 == type2 and type3 is common, continue to other rules
endif()
# Rule 4b: Filter float-rare type mixing (except comparisons which output bool)
# Float arrays combined with rare integer types are uncommon in ML workloads
# This rule filters combinations like:
# - (float, uint16, uint16) - float with rare int, rare int output
# - (uint16, float, uint16) - rare int with float, rare int output
# - (double, int16, int16) - float with rare int, rare int output
# But preserves:
# - (float, uint16, bool) - comparison operations (already handled by Rule 2)
# - (float, uint16, float) - output matches float input (handled by Rule 7)
#
# This eliminates ~50-80 combinations with semantically unusual patterns
if(NOT t3_is_bool)
if((t1_is_float AND t2_is_rare) OR (t1_is_rare AND t2_is_float))
# One input is float, other is rare int, output is NOT bool
# Check if output is the rare type - this pattern is semantically unusual
if((t1_is_rare AND type1 STREQUAL type3) OR (t2_is_rare AND type2 STREQUAL type3))
# Output matches the rare type - filter this unusual pattern
# Examples: (float, uint16, uint16), (uint16, double, uint16)
set(${output_var} FALSE PARENT_SCOPE)
return()
endif()
# If output matches float input, allow it (will be caught by Rule 7)
endif()
endif()
# Rule 5: Bool masking operations - RESTRICTED to same-type masking
# These support operations like: bool_mask ? float_x : float_y -> float_result
# AGGRESSIVE FILTER: Only allow when output type matches the numeric input type
# - Allow: (bool, float, float) - mask ? float : float -> float
# - Allow: (float, bool, float) - float ? mask : float -> float
# - Filter: (bool, int8, float) - nonsensical cross-type masking
# - Filter: (bool, float, double) - unnecessary precision change
if(t1_is_bool AND NOT t2_is_bool AND NOT t3_is_bool)
# (bool, numeric, output) - only allow if output matches numeric
if(type2 STREQUAL type3)
set(${output_var} TRUE PARENT_SCOPE)
return()
else()
# Cross-type bool masking - filter it
set(${output_var} FALSE PARENT_SCOPE)
return()
endif()
endif()
if(NOT t1_is_bool AND t2_is_bool AND NOT t3_is_bool)
# (numeric, bool, output) - only allow if output matches numeric
if(type1 STREQUAL type3)
set(${output_var} TRUE PARENT_SCOPE)
return()
else()
# Cross-type bool masking - filter it
set(${output_var} FALSE PARENT_SCOPE)
return()
endif()
endif()
# Rule 6: Type promotion - inputs match, output different (X, X, Y)
# Examples: float+float→double (accumulation), int32+int32→int64 (overflow protection)
if(type1 STREQUAL type2 AND NOT type2 STREQUAL type3)
# Both inputs same type, output different
# This is valid for type promotion operations
set(${output_var} TRUE PARENT_SCOPE)
return()
endif()
# Rule 7: Output matches one input (preserves type)
# Examples: float+int→float, int+float→float, float+double→double
if(type1 STREQUAL type3 OR type2 STREQUAL type3)
# Output matches at least one input
# This is valid for operations that preserve one input's type
set(${output_var} TRUE PARENT_SCOPE)
return()
endif()
# Rule 8: Filter ALL other three-way type mixing
# If we reach here, all three types are different AND none of the above rules matched
# Examples of what we filter:
# - (bfloat16, double, float) - three different float precisions
# - (int8, float, int32) - completely unrelated types
# - (float16, int32, double) - random type mixing
#
# Combined filtering summary:
# - Rule 8 base: ~912 combinations (51.3%)
# - Rule 2 refinement: ~20-30 cross-rare-type comparisons (~1-2%)
# - Rule 4b float-rare filtering: ~50-80 combinations (~2-3%)
# Total: ~980-1,020 combinations filtered (~55-58% reduction)
set(${output_var} FALSE PARENT_SCOPE)
endfunction()
# Scalar-specific validation function
# ScalarTransform<ArrayType, ScalarType, OutputType>
# Semantics: array op scalar -> output
function(_internal_srcore_is_valid_scalar_triple array_type scalar_type output_type output_var)
# Get type categories for array
_internal_srcore_is_type_floating("${array_type}" arr_is_float)
_internal_srcore_is_type_integer("${array_type}" arr_is_int)
set(arr_is_bool FALSE)
if(array_type STREQUAL "BOOL")
set(arr_is_bool TRUE)
endif()
# Get type categories for scalar
_internal_srcore_is_type_floating("${scalar_type}" scal_is_float)
_internal_srcore_is_type_integer("${scalar_type}" scal_is_int)
set(scal_is_bool FALSE)
if(scalar_type STREQUAL "BOOL")
set(scal_is_bool TRUE)
endif()
# Get type categories for output
_internal_srcore_is_type_floating("${output_type}" out_is_float)
_internal_srcore_is_type_integer("${output_type}" out_is_int)
set(out_is_bool FALSE)
if(output_type STREQUAL "BOOL")
set(out_is_bool TRUE)
endif()
# Rule 1: Same type throughout (X, X, X) - always valid
if(array_type STREQUAL scalar_type AND scalar_type STREQUAL output_type)
set(${output_var} TRUE PARENT_SCOPE)
return()
endif()
# Rule 2: Comparison operations (X, Y, bool) - always valid
if(out_is_bool)
set(${output_var} TRUE PARENT_SCOPE)
return()
endif()
# Rule 3: Scalar type promotion (X, Y, Y) - output matches scalar type
# Common pattern: float_array + double_scalar -> double_output
if(scalar_type STREQUAL output_type)
set(${output_var} TRUE PARENT_SCOPE)
return()
endif()
# Rule 4: Array type preservation (X, Y, X) - output matches array type
# Less common but valid: double_array + float_scalar -> double_output
if(array_type STREQUAL output_type)
set(${output_var} TRUE PARENT_SCOPE)
return()
endif()
# Rule 4b: Bitwise operations with integer types
# Pattern: (IntType, IntType, DifferentIntType) where array and scalar match
# Common for bit manipulation: rotate/shift operations that may produce different size outputs
# Example: (UINT64, UINT64, UINT32) for rotate operations
if(arr_is_int AND scal_is_int AND out_is_int AND array_type STREQUAL scalar_type)
set(${output_var} TRUE PARENT_SCOPE)
return()
endif()
# Rule 4c: Float type conversion operations
# Pattern: (FloatX, FloatX, FloatY) where array and scalar match but output is different float type
# Common for type conversions: (float, float, double), (bfloat16, bfloat16, float), etc.
# Example: ScalarTransform<float, float, double> for accumulation with higher precision
if(arr_is_float AND scal_is_float AND out_is_float AND array_type STREQUAL scalar_type)
set(${output_var} TRUE PARENT_SCOPE)
return()
endif()
# Rule 4d: Float-to-integer type casting operations
# Pattern: (FloatX, FloatX, IntY) where array and scalar match (both float) but output is integer
# Common for casting operations: (float, float, int32), (double, double, int64), etc.
# Example: ScalarTransform<bfloat16, bfloat16, Int32Type> for cast-to-int operations
if(arr_is_float AND scal_is_float AND out_is_int AND array_type STREQUAL scalar_type)
set(${output_var} TRUE PARENT_SCOPE)
return()
endif()
# Rule 4e: Integer-to-float type casting operations
# Pattern: (IntX, IntX, FloatY) where array and scalar match (both integer) but output is float
# Common for casting operations: (int32, int32, float), (int64, int64, double), etc.
# Example: ScalarTransform<Int32Type, Int32Type, float> for cast-to-float operations
if(arr_is_int AND scal_is_int AND out_is_float AND array_type STREQUAL scalar_type)
set(${output_var} TRUE PARENT_SCOPE)
return()
endif()
# Rule 5: Filter ALL other 3-way type mixing
# Examples of what we filter:
# - (float, uint32, int8) - completely nonsensical
# - (double, bfloat16, float16) - random type conversions
# - (int32, float, int8) - none of the types match
#
# This eliminates ~1,200 nonsensical combinations (67% reduction)
# Note: After adding Rules 4d and 4e, the reduction is lower (~60%) due to allowing cross-type casting
set(${output_var} FALSE PARENT_SCOPE)
endfunction()
# Broadcast-specific validation function
# Broadcast<Array1Type, Array2Type, OutputType>
# Semantics: array1 op array2 -> output
function(_internal_srcore_is_valid_broadcast_triple array1_type array2_type output_type output_var)
# Get type categories for array1
_internal_srcore_is_type_floating("${array1_type}" arr1_is_float)
_internal_srcore_is_type_integer("${array1_type}" arr1_is_int)
set(arr1_is_bool FALSE)
if(array1_type STREQUAL "BOOL")
set(arr1_is_bool TRUE)
endif()
# Get type categories for array2
_internal_srcore_is_type_floating("${array2_type}" arr2_is_float)
_internal_srcore_is_type_integer("${array2_type}" arr2_is_int)
set(arr2_is_bool FALSE)
if(array2_type STREQUAL "BOOL")
set(arr2_is_bool TRUE)
endif()
# Get type categories for output
_internal_srcore_is_type_floating("${output_type}" out_is_float)
_internal_srcore_is_type_integer("${output_type}" out_is_int)
set(out_is_bool FALSE)
if(output_type STREQUAL "BOOL")
set(out_is_bool TRUE)
endif()
# Rule 1: Same type throughout (X, X, X) - always valid
if(array1_type STREQUAL array2_type AND array2_type STREQUAL output_type)
set(${output_var} TRUE PARENT_SCOPE)
return()
endif()
# Rule 2: Comparison operations (X, Y, bool) - always valid
if(out_is_bool)
set(${output_var} TRUE PARENT_SCOPE)
return()
endif()
# Rule 2b: Bool masking operations - RESTRICTED to same-type masking
# These support operations like: bool_array ? numeric_x : numeric_y -> numeric_result
# AGGRESSIVE FILTER: Only allow when output type matches the numeric input type
# - Allow: (bool, float, float) - bool_mask broadcast numeric -> numeric
# - Allow: (float, bool, float) - numeric broadcast bool_mask -> numeric
# - Filter: (bool, int8, float) - nonsensical cross-type masking
# - Filter: (bool, float, double) - unnecessary precision change
if(arr1_is_bool AND NOT arr2_is_bool AND NOT out_is_bool)
# (bool, numeric, output) - only allow if output matches numeric array
if(array2_type STREQUAL output_type)
set(${output_var} TRUE PARENT_SCOPE)
return()
else()
# Cross-type bool masking - filter it
set(${output_var} FALSE PARENT_SCOPE)
return()
endif()
endif()
if(NOT arr1_is_bool AND arr2_is_bool AND NOT out_is_bool)
# (numeric, bool, output) - only allow if output matches numeric array
if(array1_type STREQUAL output_type)
set(${output_var} TRUE PARENT_SCOPE)
return()
else()
# Cross-type bool masking - filter it
set(${output_var} FALSE PARENT_SCOPE)
return()
endif()
endif()
# Rule 3: Type promotion (X, X, Y) - both inputs same, output is promoted type
# Common pattern: int32_array + int32_array -> int64_output
if(array1_type STREQUAL array2_type)
set(${output_var} TRUE PARENT_SCOPE)
return()
endif()
# Rule 4: Output matches first input (X, Y, X)
# Common in broadcasts: keep first array's type
if(array1_type STREQUAL output_type)
set(${output_var} TRUE PARENT_SCOPE)
return()
endif()
# Rule 5: Output matches second input (X, Y, Y)
# Common in broadcasts: keep second array's type
if(array2_type STREQUAL output_type)
set(${output_var} TRUE PARENT_SCOPE)
return()
endif()
# Rule 6: Filter ALL other 3-way type mixing
# Examples of what we filter:
# - (float, uint32, int8) - all three different, completely nonsensical
# - (double, bfloat16, float16) - random type conversions
# - (int32, float, int64) - none of the types match
#
# Combined with Rule 2b bool masking restrictions:
# This eliminates ~1,300-1,350 nonsensical combinations (~73-76% reduction)
set(${output_var} FALSE PARENT_SCOPE)
endfunction()
# ============================================================================
# REDUCE3 VALIDATION (Distance/Similarity Operations)
# ============================================================================
# Reduce3<InputType, OutputType> - operations like cosine similarity, euclidean distance
# InputType: the array elements being compared/measured
# OutputType: the result type (typically float for precision)
#
# Semantic rules:
# - Output should be same type as input OR a float type (for precision)
# - Float input → int output is nonsensical (losing precision on distance)
# - Cross-type int combinations rarely make sense (e.g., int8 → uint32)
function(_internal_srcore_is_valid_reduce3_pair input_type output_type output_var)
# Get type categories
_internal_srcore_is_type_floating("${input_type}" input_is_float)
_internal_srcore_is_type_floating("${output_type}" output_is_float)
_internal_srcore_is_type_integer("${input_type}" input_is_int)
_internal_srcore_is_type_integer("${output_type}" output_is_int)
# Rule 1: Same type is always valid (preserves precision)
if(input_type STREQUAL output_type)
set(${output_var} TRUE PARENT_SCOPE)
return()
endif()
# Rule 2: Integer input → float output is valid (precision preserved)
if(input_is_int AND output_is_float)
set(${output_var} TRUE PARENT_SCOPE)
return()
endif()
# Rule 3: Float input → float output is valid (allow ALL float-to-float conversions)
# Changed from precision-preserving only to support all cross-type float operations
# Needed for operations like: Reduce3<double, float>, Reduce3<float, bfloat16>, etc.
if(input_is_float AND output_is_float)
# Allow all float-to-float type pairs (including precision loss)
# The operation semantics may require flexibility in output type
set(${output_var} TRUE PARENT_SCOPE)
return()
endif()
# Rule 4: Filter all other combinations
# - Float → int (losing precision on distance measure)
# - Cross-type int combinations (e.g., int8 → uint32)
# - Lower precision float output (e.g., double → float16)
set(${output_var} FALSE PARENT_SCOPE)
endfunction()
# ============================================================================
# INDEXREDUCE VALIDATION (ArgMax/ArgMin Operations)
# ============================================================================
# IndexReduce<InputType, IndexType> - find indices of max/min values
# InputType: the array elements being searched
# IndexType: MUST be int64_t (indices are always 64-bit)
#
# Semantic rules:
# - IndexType should ALWAYS be INT64 (sd::LongType)
# - Any other index type is nonsensical (indices must be 64-bit signed)
function(_internal_srcore_is_valid_indexreduce_pair input_type index_type output_var)
# IndexType MUST be INT64
if(index_type STREQUAL "INT64")
set(${output_var} TRUE PARENT_SCOPE)
else()
# Filter all non-INT64 index types
set(${output_var} FALSE PARENT_SCOPE)
endif()
endfunction()
# ============================================================================
# REDUCE_FLOAT VALIDATION (Reductions with Float Output)
# ============================================================================
# ReduceFloatFunction<InputType, OutputType> - sum, mean, variance, std
# InputType: any numeric type
# OutputType: MUST be float type (for precision)
#
# Semantic rules:
# - Output must be float type (already enforced in TemplateProcessing.cmake)
# - Output precision should be >= input precision
# - Float → lower precision float is nonsensical (e.g., double → float16)
function(_internal_srcore_is_valid_reduce_float_pair input_type output_type output_var)
# Get type categories
_internal_srcore_is_type_floating("${input_type}" input_is_float)
_internal_srcore_is_type_floating("${output_type}" output_is_float)
_internal_srcore_is_type_integer("${input_type}" input_is_int)
# Output MUST be float (already checked in TemplateProcessing.cmake, but double-check)
if(NOT output_is_float)
set(${output_var} FALSE PARENT_SCOPE)
return()
endif()
# Rule 1: Same type is always valid
if(input_type STREQUAL output_type)
set(${output_var} TRUE PARENT_SCOPE)
return()
endif()
# Rule 2: Integer input → any float output is valid
if(input_is_int)
set(${output_var} TRUE PARENT_SCOPE)
return()
endif()
# Rule 3: Float input → any float output (including precision changes)
# for operations that explicitly request different output precision.
# Examples: ReduceFloatFunction<double, float>, <float, double>, etc.
if(input_is_float)
# Allow ALL float-to-float combinations (upcast, downcast, or same)
# The operation implementation handles precision conversion correctly
set(${output_var} TRUE PARENT_SCOPE)
return()
endif()
# Filter all other combinations
set(${output_var} FALSE PARENT_SCOPE)
endfunction()
# Helper function for integer promotion validation
function(_internal_is_valid_int_promotion from_type to_type result_var)
set(int_hierarchy "INT8;UINT8;INT16;UINT16;INT32;UINT32;INT64;UINT64")
list(FIND int_hierarchy "${from_type}" from_idx)
list(FIND int_hierarchy "${to_type}" to_idx)
if(from_idx LESS 0 OR to_idx LESS 0)
set(${result_var} FALSE PARENT_SCOPE)
return()
endif()
# Allow promotion to same or larger type
if(to_idx GREATER_EQUAL from_idx)
set(${result_var} TRUE PARENT_SCOPE)
else()
set(${result_var} FALSE PARENT_SCOPE)
endif()
endfunction()
# ============================================================================
# SECTION 2: OPTIMIZED COMBINATION GENERATION
# ============================================================================
function(_internal_srcore_generate_combinations active_indices type_names profile result_2_var result_3_var)
list(LENGTH active_indices type_count)
if(type_count EQUAL 0)
message(FATAL_ERROR "No active types for combination generation")
endif()
set(combinations_2 "")
set(combinations_3 "")
math(EXPR max_index "${type_count} - 1")
# Calculate theoretical maximums
math(EXPR max_possible_2 "${type_count} * ${type_count}")
math(EXPR max_possible_3 "${type_count} * ${type_count} * ${type_count}")
# Generate 2-type combinations with filtering
foreach(i RANGE ${max_index})
list(GET type_names ${i} type_i)
foreach(j RANGE ${max_index})
list(GET type_names ${j} type_j)
_internal_srcore_is_valid_pair("${type_i}" "${type_j}" is_valid)
if(is_valid)
list(APPEND combinations_2 "${i},${j}")
endif()
endforeach()
endforeach()
# Generate 3-type combinations with strict filtering
foreach(i RANGE ${max_index})
list(GET type_names ${i} type_i)
foreach(j RANGE ${max_index})
list(GET type_names ${j} type_j)
foreach(k RANGE ${max_index})
list(GET type_names ${k} type_k)
_internal_srcore_is_valid_triple("${type_i}" "${type_j}" "${type_k}" is_valid)
if(is_valid)
list(APPEND combinations_3 "${i},${j},${k}")
endif()
endforeach()
endforeach()
endforeach()
# Get counts before profile filtering
list(LENGTH combinations_2 accepted_2)
list(LENGTH combinations_3 accepted_3_before_profile)
# MODIFIED: Profile-based limiting DISABLED for full matrix generation
# Previous code limited combinations to 50-500 based on profile, causing
# runtime undefined symbol errors. Now generating ALL combinations.
#
# if(DEFINED profile AND NOT profile STREQUAL "")
# ... profile limiting code disabled ...
# endif()
# Get final count
list(LENGTH combinations_3 accepted_3)
# Calculate reduction percentages correctly
if(max_possible_2 GREATER 0)
math(EXPR reduction_2 "100 - (100 * ${accepted_2} / ${max_possible_2})")
else()
set(reduction_2 0)
endif()
if(max_possible_3 GREATER 0)
math(EXPR reduction_3 "100 - (100 * ${accepted_3} / ${max_possible_3})")
else()
set(reduction_3 0)
endif()
# Report statistics
message(STATUS "🎯 Selective Rendering Results:")
message(STATUS " - Active types: ${type_count}")
message(STATUS " - 2-type combinations: ${accepted_2}/${max_possible_2} (${reduction_2}% reduction)")
message(STATUS " - 3-type combinations: ${accepted_3}/${max_possible_3} (${reduction_3}% reduction)")
set(${result_2_var} "${combinations_2}" PARENT_SCOPE)
set(${result_3_var} "${combinations_3}" PARENT_SCOPE)
endfunction()
# Helper function to convert enum name to integer value
function(enum_to_int_value enum_name out_var)
# Map enum names to their integer values
if(enum_name STREQUAL "BOOL")
set(${out_var} 1 PARENT_SCOPE)
elseif(enum_name STREQUAL "FLOAT8")
set(${out_var} 2 PARENT_SCOPE)
elseif(enum_name STREQUAL "HALF" OR enum_name STREQUAL "FLOAT16")
set(${out_var} 3 PARENT_SCOPE)
elseif(enum_name STREQUAL "HALF2")
set(${out_var} 4 PARENT_SCOPE)
elseif(enum_name STREQUAL "FLOAT32")
set(${out_var} 5 PARENT_SCOPE)
elseif(enum_name STREQUAL "DOUBLE" OR enum_name STREQUAL "FLOAT64")
set(${out_var} 6 PARENT_SCOPE)
elseif(enum_name STREQUAL "INT8")
set(${out_var} 7 PARENT_SCOPE)
elseif(enum_name STREQUAL "INT16")
set(${out_var} 8 PARENT_SCOPE)
elseif(enum_name STREQUAL "INT32")
set(${out_var} 9 PARENT_SCOPE)
elseif(enum_name STREQUAL "INT64" OR enum_name STREQUAL "LONG")
set(${out_var} 10 PARENT_SCOPE)
elseif(enum_name STREQUAL "UINT8")
set(${out_var} 11 PARENT_SCOPE)
elseif(enum_name STREQUAL "UINT16")
set(${out_var} 12 PARENT_SCOPE)
elseif(enum_name STREQUAL "UINT32")
set(${out_var} 13 PARENT_SCOPE)
elseif(enum_name STREQUAL "UINT64" OR enum_name STREQUAL "ULONG")
set(${out_var} 14 PARENT_SCOPE)
elseif(enum_name STREQUAL "QINT8")
set(${out_var} 15 PARENT_SCOPE)
elseif(enum_name STREQUAL "QINT16")
set(${out_var} 16 PARENT_SCOPE)
elseif(enum_name STREQUAL "BFLOAT16")
set(${out_var} 17 PARENT_SCOPE)
elseif(enum_name STREQUAL "UTF8")
set(${out_var} 50 PARENT_SCOPE)
elseif(enum_name STREQUAL "UTF16")
set(${out_var} 51 PARENT_SCOPE)
elseif(enum_name STREQUAL "UTF32")
set(${out_var} 52 PARENT_SCOPE)
else()
message(WARNING "Unknown enum name: ${enum_name}")
set(${out_var} 0 PARENT_SCOPE)
endif()
endfunction()
function(report_template_statistics combinations_2 combinations_3 type_count)
list(LENGTH combinations_2 num_2)
list(LENGTH combinations_3 num_3)
# Calculate theoretical maximum
math(EXPR max_3 "${type_count} * ${type_count} * ${type_count}")
if(max_3 GREATER 0)
math(EXPR reduction_percent "100 - (100 * ${num_3} / ${max_3})")
else()
set(reduction_percent 0)
endif()
message(STATUS "🎯 Template Generation Statistics:")
message(STATUS " - 2-type combinations: ${num_2}")
message(STATUS " - 3-type combinations: ${num_3}")
message(STATUS " - Template instantiation reduction: ${reduction_percent}%")
endfunction()
# ============================================================================
# SECTION 3: CORE HELPER FUNCTIONS (Optimized)
# ============================================================================
function(srcore_normalize_type input_type output_var)
set(normalized_type "${input_type}")
# Handle all common type aliases
if(normalized_type STREQUAL "float32")
set(normalized_type "float")
elseif(normalized_type STREQUAL "float64")
set(normalized_type "double")
elseif(normalized_type STREQUAL "half")
set(normalized_type "float16")
elseif(normalized_type STREQUAL "long")
set(normalized_type "int64_t")
elseif(normalized_type STREQUAL "LongType")
set(normalized_type "int64_t")
elseif(normalized_type STREQUAL "int")
set(normalized_type "int32_t")
elseif(normalized_type STREQUAL "SignedChar")
set(normalized_type "int8_t")
elseif(normalized_type STREQUAL "UnsignedChar")
set(normalized_type "uint8_t")
elseif(normalized_type STREQUAL "Int16Type")
set(normalized_type "int16_t")
elseif(normalized_type STREQUAL "UInt16Type")
set(normalized_type "uint16_t")
elseif(normalized_type STREQUAL "Int32Type")
set(normalized_type "int32_t")
elseif(normalized_type STREQUAL "UInt32Type")
set(normalized_type "uint32_t")
elseif(normalized_type STREQUAL "bfloat")
set(normalized_type "bfloat16")
elseif(normalized_type STREQUAL "qint8")
set(normalized_type "int8_t")
elseif(normalized_type STREQUAL "quint8")
set(normalized_type "uint8_t")
elseif(normalized_type STREQUAL "qint16")
set(normalized_type "int16_t")
elseif(normalized_type STREQUAL "quint16")
set(normalized_type "uint16_t")
elseif(normalized_type STREQUAL "UnsignedLong")
set(normalized_type "uint64_t")
elseif(normalized_type STREQUAL "utf8")
set(normalized_type "std::string")
elseif(normalized_type STREQUAL "utf16")
set(normalized_type "std::u16string")
elseif(normalized_type STREQUAL "utf32")
set(normalized_type "std::u32string")
endif()
set(${output_var} "${normalized_type}" PARENT_SCOPE)
endfunction()
function(is_semantically_valid_combination type1 type2 type3 mode result_var)
# Normalize types first
srcore_normalize_type("${type1}" norm_t1)
srcore_normalize_type("${type2}" norm_t2)
srcore_normalize_type("${type3}" norm_t3)
# Rule 1: Same type combinations are ALWAYS valid
if(norm_t1 STREQUAL norm_t2 AND norm_t2 STREQUAL norm_t3)
set(${result_var} TRUE PARENT_SCOPE)
return()
endif()
# Rule 2: Quantization patterns
if((norm_t1 STREQUAL "int8_t" OR norm_t1 STREQUAL "uint8_t") AND
(norm_t2 STREQUAL "int8_t" OR norm_t2 STREQUAL "uint8_t"))
# INT8 accumulation or dequantization
if(norm_t3 STREQUAL "int32_t" OR norm_t3 STREQUAL "float")
set(${result_var} TRUE PARENT_SCOPE)
return()
endif()
# Block INT8 to half precision (bad pattern)
if(norm_t3 MATCHES "float16|bfloat16")
set(${result_var} FALSE PARENT_SCOPE)
return()
endif()
endif()
# Rule 3: Mixed precision training
if((norm_t1 STREQUAL "float16" OR norm_t1 STREQUAL "bfloat16") AND
(norm_t2 STREQUAL "float16" OR norm_t2 STREQUAL "bfloat16") AND
norm_t3 STREQUAL "float")
set(${result_var} TRUE PARENT_SCOPE)
return()
endif()
# Rule 4: Embedding lookups
if((norm_t1 STREQUAL "int32_t" OR norm_t1 STREQUAL "int64_t") AND
norm_t2 STREQUAL "float" AND norm_t3 STREQUAL "float")
set(${result_var} TRUE PARENT_SCOPE)
return()
endif()
# Rule 5: Comparisons producing bool
if(norm_t3 STREQUAL "bool")
# Any same-type comparison is valid
if(norm_t1 STREQUAL norm_t2)
set(${result_var} TRUE PARENT_SCOPE)
return()
endif()
endif()
# Rule 6: Masking operations
if(norm_t2 STREQUAL "bool" AND norm_t1 STREQUAL norm_t3)
set(${result_var} TRUE PARENT_SCOPE)
return()
endif()
# Rule 7: Block nonsensical patterns
# Integer operations producing half precision
if(norm_t1 MATCHES "int" AND norm_t2 MATCHES "int" AND
norm_t3 MATCHES "float16|bfloat16")
set(${result_var} FALSE PARENT_SCOPE)
return()
endif()
# Double to half precision (extreme downcast)
if(norm_t1 STREQUAL "double" AND norm_t3 MATCHES "float16|bfloat16")
set(${result_var} FALSE PARENT_SCOPE)
return()
endif()
# Rule 8: Standard promotions
if(norm_t1 STREQUAL norm_t2)
# Integer to float promotion
if(norm_t1 MATCHES "int" AND norm_t3 MATCHES "float|double")
set(${result_var} TRUE PARENT_SCOPE)
return()
endif()
# Float to double promotion
if(norm_t1 STREQUAL "float" AND norm_t3 STREQUAL "double")
set(${result_var} TRUE PARENT_SCOPE)
return()
endif()
endif()
# Default: invalid
set(${result_var} FALSE PARENT_SCOPE)
endfunction()
function(get_all_types result_var)
set(all_types
"bool" "float8" "float16" "half2" "float32" "double"
"int8" "int16" "int32" "int64" "uint8" "uint16" "uint32" "uint64"
"qint8" "qint16" "bfloat16" "utf8" "utf16" "utf32"
)
set(${result_var} "${all_types}" PARENT_SCOPE)
endfunction()
function(_internal_srcore_discover_types result_indices_var result_names_var result_enums_var result_cpp_types_var)
if(NOT DEFINED SRCORE_USE_SELECTIVE_TYPES)
get_property(cache_selective CACHE SRCORE_USE_SELECTIVE_TYPES PROPERTY VALUE)
get_property(cache_types CACHE SRCORE_VALIDATED_TYPES PROPERTY VALUE)
if(DEFINED cache_selective)
set(SRCORE_USE_SELECTIVE_TYPES "${cache_selective}")
set(SRCORE_VALIDATED_TYPES "${cache_types}")
else()
set(SRCORE_USE_SELECTIVE_TYPES FALSE)
set(SRCORE_VALIDATED_TYPES "")
endif()
endif()
if(SRCORE_USE_SELECTIVE_TYPES AND DEFINED SRCORE_VALIDATED_TYPES AND NOT SRCORE_VALIDATED_TYPES STREQUAL "")
_internal_srcore_discover_selective_types("${SRCORE_VALIDATED_TYPES}" discovered_indices discovered_names discovered_enums discovered_cpp_types)
else()
_internal_srcore_discover_all_types(discovered_indices discovered_names discovered_enums discovered_cpp_types)
endif()
set(${result_indices_var} "${discovered_indices}" PARENT_SCOPE)
set(${result_names_var} "${discovered_names}" PARENT_SCOPE)
set(${result_enums_var} "${discovered_enums}" PARENT_SCOPE)
set(${result_cpp_types_var} "${discovered_cpp_types}" PARENT_SCOPE)
endfunction()
# Replace the entire _internal_srcore_discover_selective_types function with this:
function(_internal_srcore_discover_selective_types validated_types_list result_indices_var result_names_var result_enums_var result_cpp_types_var)
# types.h is always at include/types/types.h
set(types_header "${CMAKE_CURRENT_SOURCE_DIR}/include/types/types.h")
if(NOT EXISTS "${types_header}")
message(FATAL_ERROR "Could not find types.h at expected location: ${types_header}")
endif()
file(READ "${types_header}" types_content)
# The profile should only be used by _internal_srcore_discover_all_types()
# This function is called when SRCORE_USE_SELECTIVE_TYPES=TRUE, meaning the
# user explicitly provided a type list (e.g., via -Dlibnd4j.datatypes=...).
# Using the profile here would override the user's explicit choice!
set(types_to_discover "${validated_types_list}")
# Enhanced type mapping to handle C++ type names to enum names
# Include ALL possible long type variations
set(type_mapping_float32 "FLOAT32")
set(type_mapping_float "FLOAT32")
set(type_mapping_double "DOUBLE")
set(type_mapping_int32 "INT32")
set(type_mapping_int32_t "INT32")
set(type_mapping_int "INT32")
set(type_mapping_Int32Type "INT32")
set(type_mapping_sd__Int32Type "INT32")
set(type_mapping_signed "INT32")
set(type_mapping_signed_int "INT32")
# Critical INT64 mappings - include ALL variations
set(type_mapping_int64 "INT64")
set(type_mapping_int64_t "INT64")
set(type_mapping_long_long "INT64")
set(type_mapping_long_long_int "INT64")
set(type_mapping_long "INT64")
set(type_mapping_long_int "INT64")
set(type_mapping_signed_long "INT64")
set(type_mapping_signed_long_long "INT64")
set(type_mapping_signed_long_int "INT64")
set(type_mapping_LongType "INT64")
set(type_mapping_sd__LongType "INT64")
# UINT64 mappings
set(type_mapping_uint64 "UINT64")
set(type_mapping_uint64_t "UINT64")
set(type_mapping_unsigned_long_long "UINT64")
set(type_mapping_unsigned_long_long_int "UINT64")
set(type_mapping_unsigned_long "UINT64")
set(type_mapping_unsigned_long_int "UINT64")
set(type_mapping_UnsignedLong "UINT64")
set(type_mapping_sd__UnsignedLong "UINT64")
set(type_mapping_size_t "UINT64")
set(type_mapping_bool "BOOL")
set(type_mapping_float16 "HALF")
set(type_mapping_half "HALF")
set(type_mapping_bfloat16 "BFLOAT16")
set(type_mapping_bfloat "BFLOAT16")
set(type_mapping_int8 "INT8")
set(type_mapping_int8_t "INT8")
set(type_mapping_signed_char "INT8")
set(type_mapping_char "INT8")
set(type_mapping_uint8 "UINT8")
set(type_mapping_uint8_t "UINT8")
set(type_mapping_unsigned_char "UINT8")
set(type_mapping_int16 "INT16")
set(type_mapping_int16_t "INT16")
set(type_mapping_Int16Type "INT16")
set(type_mapping_short "INT16")
set(type_mapping_short_int "INT16")
set(type_mapping_signed_short "INT16")
set(type_mapping_uint16 "UINT16")
set(type_mapping_uint16_t "UINT16")
set(type_mapping_unsigned_short "UINT16")
set(type_mapping_unsigned_short_int "UINT16")
set(type_mapping_uint32 "UINT32")
set(type_mapping_uint32_t "UINT32")
set(type_mapping_unsigned_int "UINT32")
set(type_mapping_unsigned "UINT32")
set(discovered_types "")
set(discovered_indices "")
set(discovered_enums "")
set(discovered_cpp_types "")
set(type_index 0)
foreach(user_type ${types_to_discover})
string(STRIP "${user_type}" user_type)
# Map C++ type name to enum name
set(type_key "")
string(REPLACE " " "_" user_type_clean "${user_type}")
string(REPLACE "::" "__" user_type_clean "${user_type_clean}")
if(DEFINED type_mapping_${user_type_clean})
set(type_key "${type_mapping_${user_type_clean}}")
else()
string(TOUPPER "${user_type}" upper_type)
set(type_key "${upper_type}")
endif()
if(NOT type_key)
continue()
endif()
# Find the type definition in types.h
string(REGEX MATCH "#define[ \t]+TTYPE_${type_key}[ \t]*,[ \t]*\\(([^)]+)\\)" type_match "${types_content}")
if(type_match)
list(APPEND discovered_types "${type_key}")
list(APPEND discovered_indices ${type_index})
string(REGEX MATCH "\\(([^)]+)\\)" tuple_match "${type_match}")
string(SUBSTRING "${tuple_match}" 1 -1 type_tuple)
string(REGEX REPLACE "^([^,]+),[ \t]*(.+)$" "\\1;\\2" tuple_parts "${type_tuple}")
list(GET tuple_parts 0 enum_part)
list(GET tuple_parts 1 cpp_part)
string(STRIP "${enum_part}" enum_part)
string(STRIP "${cpp_part}" cpp_part)
string(REGEX REPLACE "\\)$" "" cpp_part "${cpp_part}")
list(APPEND discovered_enums "${enum_part}")
list(APPEND discovered_cpp_types "${cpp_part}")
math(EXPR type_index "${type_index} + 1")
endif()
endforeach()
if(type_index EQUAL 0)
message(FATAL_ERROR "No valid types discovered from profile types: ${types_to_discover}")
endif()
set(${result_indices_var} "${discovered_indices}" PARENT_SCOPE)
set(${result_names_var} "${discovered_types}" PARENT_SCOPE)
set(${result_enums_var} "${discovered_enums}" PARENT_SCOPE)
set(${result_cpp_types_var} "${discovered_cpp_types}" PARENT_SCOPE)
endfunction()
function(_internal_srcore_discover_all_types result_indices_var result_names_var result_enums_var result_cpp_types_var)
# types.h is always at include/types/types.h
set(types_header "${CMAKE_CURRENT_SOURCE_DIR}/include/types/types.h")
if(NOT EXISTS "${types_header}")
message(FATAL_ERROR "Could not find types.h at expected location: ${types_header}")
endif()
file(READ "${types_header}" types_content)
# FORCE usage of profile types - DO NOT discover extra types!
if(DEFINED SD_TYPE_PROFILE AND NOT SD_TYPE_PROFILE STREQUAL "")
# Get the types from the profile - these are C++ type names
if(COMMAND get_profile_type_combinations)
get_profile_type_combinations("${SD_TYPE_PROFILE}" profile_types)
else()
message(FATAL_ERROR "get_profile_type_combinations function not found!")
endif()
message(STATUS "FORCING profile '${SD_TYPE_PROFILE}' types: ${profile_types}")
# Convert C++ type names to enum names for discovery
set(all_types "")
foreach(cpp_type ${profile_types})
# Map C++ types to enum names
if(cpp_type STREQUAL "bool")
list(APPEND all_types "BOOL")
elseif(cpp_type STREQUAL "int8_t")
list(APPEND all_types "INT8")
elseif(cpp_type STREQUAL "uint8_t")
list(APPEND all_types "UINT8")
elseif(cpp_type STREQUAL "int16_t")
list(APPEND all_types "INT16")
elseif(cpp_type STREQUAL "uint16_t")
list(APPEND all_types "UINT16")
elseif(cpp_type STREQUAL "int32_t")
list(APPEND all_types "INT32")
elseif(cpp_type STREQUAL "uint32_t")
list(APPEND all_types "UINT32")
elseif(cpp_type STREQUAL "int64_t")
list(APPEND all_types "INT64")
elseif(cpp_type STREQUAL "uint64_t")
list(APPEND all_types "UINT64")
elseif(cpp_type STREQUAL "float16")
list(APPEND all_types "HALF")
elseif(cpp_type STREQUAL "bfloat16")
list(APPEND all_types "BFLOAT16")
elseif(cpp_type STREQUAL "float")
list(APPEND all_types "FLOAT32")
elseif(cpp_type STREQUAL "double")
list(APPEND all_types "DOUBLE")
elseif(cpp_type STREQUAL "std::string")
list(APPEND all_types "UTF8")
elseif(cpp_type STREQUAL "std::u16string")
list(APPEND all_types "UTF16")
elseif(cpp_type STREQUAL "std::u32string")
list(APPEND all_types "UTF32")
else()
message(WARNING "Unknown C++ type in profile: ${cpp_type}")
endif()
endforeach()
list(LENGTH all_types mapped_count)
list(LENGTH profile_types original_count)
message(STATUS "Profile specified ${original_count} types, mapped to ${mapped_count} enum types")
if(mapped_count EQUAL 0)
message(FATAL_ERROR "No valid type mappings found for profile '${SD_TYPE_PROFILE}'")
endif()
else()
# No profile - this should not happen if STANDARD_ALL_TYPES is set
message(FATAL_ERROR "No SD_TYPE_PROFILE defined! Set SD_TYPE_PROFILE to use specific types.")
endif()
# Now discover ONLY the types that are in the profile
set(discovered_types "")
set(discovered_indices "")
set(discovered_enums "")
set(discovered_cpp_types "")
set(type_index 0)
foreach(type_key ${all_types})
string(REGEX MATCH "#define[ \t]+TTYPE_${type_key}[ \t]*,[ \t]*\\(([^)]+)\\)" type_match "${types_content}")
if(type_match)
list(APPEND discovered_types "${type_key}")
list(APPEND discovered_indices ${type_index})
string(REGEX MATCH "\\(([^)]+)\\)" tuple_match "${type_match}")
string(SUBSTRING "${tuple_match}" 1 -1 type_tuple)
string(REGEX REPLACE "^([^,]+),[ \t]*(.+)$" "\\1;\\2" tuple_parts "${type_tuple}")
list(GET tuple_parts 0 enum_part)
list(GET tuple_parts 1 cpp_part)
string(STRIP "${enum_part}" enum_part)
string(STRIP "${cpp_part}" cpp_part)
string(REGEX REPLACE "\\)$" "" cpp_part "${cpp_part}")
list(APPEND discovered_enums "${enum_part}")
list(APPEND discovered_cpp_types "${cpp_part}")
math(EXPR type_index "${type_index} + 1")
else()
message(WARNING "Type '${type_key}' specified in profile but not found in types.h")
endif()
endforeach()
if(type_index EQUAL 0)
message(FATAL_ERROR "No types discovered from types.h using profile '${SD_TYPE_PROFILE}'")
endif()
# Verify we got the expected number
list(LENGTH all_types expected_count)
if(NOT type_index EQUAL expected_count)
message(WARNING "Profile specifies ${expected_count} types but only ${type_index} were found in types.h")
endif()
message(STATUS "✅ Discovered ${type_index} types from profile '${SD_TYPE_PROFILE}'")
message(STATUS "Types: ${discovered_types}")
set(${result_indices_var} "${discovered_indices}" PARENT_SCOPE)
set(${result_names_var} "${discovered_types}" PARENT_SCOPE)
set(${result_enums_var} "${discovered_enums}" PARENT_SCOPE)
set(${result_cpp_types_var} "${discovered_cpp_types}" PARENT_SCOPE)
endfunction()
# ============================================================================
# SECTION 4: PUBLIC API FUNCTIONS
# ============================================================================
function(srcore_discover_active_types result_var result_enums_var result_cpp_types_var)
_internal_srcore_discover_types(active_indices active_names discovered_enums discovered_cpp_types)
set(SRCORE_ACTIVE_TYPES "${active_names}" PARENT_SCOPE)
list(LENGTH active_indices type_count)
set(SRCORE_ACTIVE_TYPE_COUNT ${type_count} PARENT_SCOPE)
# Store type mappings for later use
set(type_index 0)
foreach(type_enum IN LISTS discovered_enums)
set(SRCORE_TYPE_ENUM_${type_index} "${type_enum}" PARENT_SCOPE)
math(EXPR type_index "${type_index} + 1")
endforeach()
set(type_index 0)
foreach(type_cpp IN LISTS discovered_cpp_types)
set(SRCORE_TYPE_CPP_${type_index} "${type_cpp}" PARENT_SCOPE)
math(EXPR type_index "${type_index} + 1")
endforeach()
set(type_index 0)
foreach(type_name IN LISTS active_names)
set(SRCORE_TYPE_NAME_${type_index} "${type_name}" PARENT_SCOPE)
math(EXPR type_index "${type_index} + 1")
endforeach()
set(${result_var} "${active_indices}" PARENT_SCOPE)
set(${result_enums_var} "${discovered_enums}" PARENT_SCOPE)
set(${result_cpp_types_var} "${discovered_cpp_types}" PARENT_SCOPE)
endfunction()
function(srcore_generate_combinations active_indices profile result_2_var result_3_var)
_internal_srcore_generate_combinations("${active_indices}" "${SRCORE_ACTIVE_TYPES}" "${profile}" combinations_2 combinations_3)
set(SRCORE_COMBINATIONS_2 "${combinations_2}" PARENT_SCOPE)
set(SRCORE_COMBINATIONS_3 "${combinations_3}" PARENT_SCOPE)
set(${result_2_var} "${combinations_2}" PARENT_SCOPE)
set(${result_3_var} "${combinations_3}" PARENT_SCOPE)
endfunction()
function(srcore_generate_javacpp_header combinations_2 combinations_3 output_dir type_cpp_types active_indices)
# Generate JavaCPP-compatible header that declares only valid template instantiations
# This ensures JavaCPP generates JNI bindings ONLY for combinations that CMake builds
set(javacpp_header_file "${output_dir}/javacpp_instantiations.h")
set(javacpp_content "")
string(APPEND javacpp_content "/* AUTOMATICALLY GENERATED - JavaCPP Template Instantiation Declarations */\n")
string(APPEND javacpp_content "/* This header limits JavaCPP to generate JNI bindings only for valid type combinations */\n")
string(APPEND javacpp_content "/* Generated by SelectiveRenderingCore.cmake */\n\n")
string(APPEND javacpp_content "#ifndef SD_JAVACPP_INSTANTIATIONS_H\n")
string(APPEND javacpp_content "#define SD_JAVACPP_INSTANTIATIONS_H\n\n")
# Include all transform headers
string(APPEND javacpp_content "// Transform headers\n")
string(APPEND javacpp_content "#include <loops/scalar_transform.h>\n")
string(APPEND javacpp_content "#include <loops/scalar_bool.h>\n")
string(APPEND javacpp_content "#include <loops/scalar_int.h>\n")
string(APPEND javacpp_content "#include <loops/pairwise_transform.h>\n")
string(APPEND javacpp_content "#include <loops/pairwise_bool.h>\n")
string(APPEND javacpp_content "#include <loops/pairwise_int.h>\n")
string(APPEND javacpp_content "#include <loops/broadcasting.h>\n")
string(APPEND javacpp_content "#include <loops/broadcasting_bool.h>\n")
string(APPEND javacpp_content "#include <loops/broadcasting_int.h>\n")
string(APPEND javacpp_content "#include <loops/transform_any.h>\n")
string(APPEND javacpp_content "#include <loops/transform_bool.h>\n")
string(APPEND javacpp_content "#include <loops/transform_float.h>\n")
string(APPEND javacpp_content "#include <loops/transform_same.h>\n")
string(APPEND javacpp_content "#include <loops/transform_strict.h>\n")
string(APPEND javacpp_content "#include <loops/reduce_float.h>\n")
string(APPEND javacpp_content "#include <loops/reduce_same.h>\n")
string(APPEND javacpp_content "#include <loops/reduce_bool.h>\n")
string(APPEND javacpp_content "#include <loops/reduce_long.h>\n")
string(APPEND javacpp_content "#include <loops/reduce3.h>\n")
string(APPEND javacpp_content "#include <loops/indexreduce.h>\n")
string(APPEND javacpp_content "#include <loops/summarystatsreduce.h>\n\n")
string(APPEND javacpp_content "// Forward declarations of valid template instantiations\n")
string(APPEND javacpp_content "// JavaCPP will only generate JNI bindings for these combinations\n\n")
string(APPEND javacpp_content "namespace functions {\n\n")
# Triple-type transforms (X,Y,Z)
string(APPEND javacpp_content "// ===== TRIPLE-TYPE TRANSFORMS (X,Y,Z) =====\n\n")
# ScalarTransform
string(APPEND javacpp_content "namespace scalar {\n")
foreach(triple IN LISTS combinations_3)
string(REPLACE "," ";" triple_list "${triple}")
list(GET triple_list 0 t1)
list(GET triple_list 1 t2)
list(GET triple_list 2 t3)
list(GET type_cpp_types ${t1} cpp_type1)
list(GET type_cpp_types ${t2} cpp_type2)
list(GET type_cpp_types ${t3} cpp_type3)
string(APPEND javacpp_content "template class ScalarTransform<${cpp_type1}, ${cpp_type2}, ${cpp_type3}>;\n")
endforeach()
string(APPEND javacpp_content "} // namespace scalar\n\n")
# ScalarBoolTransform
string(APPEND javacpp_content "namespace scalar {\n")
foreach(triple IN LISTS combinations_3)
string(REPLACE "," ";" triple_list "${triple}")
list(GET triple_list 0 t1)
list(GET triple_list 1 t2)
list(GET triple_list 2 t3)
list(GET type_cpp_types ${t1} cpp_type1)
list(GET type_cpp_types ${t2} cpp_type2)
list(GET type_cpp_types ${t3} cpp_type3)
string(APPEND javacpp_content "template class ScalarBoolTransform<${cpp_type1}, ${cpp_type2}, ${cpp_type3}>;\n")
endforeach()
string(APPEND javacpp_content "} // namespace scalar\n\n")
# ScalarIntTransform
string(APPEND javacpp_content "namespace scalar {\n")
foreach(triple IN LISTS combinations_3)
string(REPLACE "," ";" triple_list "${triple}")
list(GET triple_list 0 t1)
list(GET triple_list 1 t2)
list(GET triple_list 2 t3)
list(GET type_cpp_types ${t1} cpp_type1)
list(GET type_cpp_types ${t2} cpp_type2)
list(GET type_cpp_types ${t3} cpp_type3)
string(APPEND javacpp_content "template class ScalarIntTransform<${cpp_type1}, ${cpp_type2}, ${cpp_type3}>;\n")
endforeach()
string(APPEND javacpp_content "} // namespace scalar\n\n")
# PairWiseTransform
string(APPEND javacpp_content "namespace pairwise_transforms {\n")
foreach(triple IN LISTS combinations_3)
string(REPLACE "," ";" triple_list "${triple}")
list(GET triple_list 0 t1)
list(GET triple_list 1 t2)
list(GET triple_list 2 t3)
list(GET type_cpp_types ${t1} cpp_type1)
list(GET type_cpp_types ${t2} cpp_type2)
list(GET type_cpp_types ${t3} cpp_type3)
string(APPEND javacpp_content "template class PairWiseTransform<${cpp_type1}, ${cpp_type2}, ${cpp_type3}>;\n")
endforeach()
string(APPEND javacpp_content "} // namespace pairwise_transforms\n\n")
# PairWiseBoolTransform
string(APPEND javacpp_content "namespace pairwise_transforms {\n")
foreach(triple IN LISTS combinations_3)
string(REPLACE "," ";" triple_list "${triple}")
list(GET triple_list 0 t1)
list(GET triple_list 1 t2)
list(GET triple_list 2 t3)
list(GET type_cpp_types ${t1} cpp_type1)
list(GET type_cpp_types ${t2} cpp_type2)
list(GET type_cpp_types ${t3} cpp_type3)
string(APPEND javacpp_content "template class PairWiseBoolTransform<${cpp_type1}, ${cpp_type2}, ${cpp_type3}>;\n")
endforeach()
string(APPEND javacpp_content "} // namespace pairwise_transforms\n\n")
# PairWiseIntTransform
string(APPEND javacpp_content "namespace pairwise_transforms {\n")
foreach(triple IN LISTS combinations_3)
string(REPLACE "," ";" triple_list "${triple}")
list(GET triple_list 0 t1)
list(GET triple_list 1 t2)
list(GET triple_list 2 t3)
list(GET type_cpp_types ${t1} cpp_type1)
list(GET type_cpp_types ${t2} cpp_type2)
list(GET type_cpp_types ${t3} cpp_type3)
string(APPEND javacpp_content "template class PairWiseIntTransform<${cpp_type1}, ${cpp_type2}, ${cpp_type3}>;\n")
endforeach()
string(APPEND javacpp_content "} // namespace pairwise_transforms\n\n")
# Broadcast
string(APPEND javacpp_content "namespace broadcast {\n")
foreach(triple IN LISTS combinations_3)
string(REPLACE "," ";" triple_list "${triple}")
list(GET triple_list 0 t1)
list(GET triple_list 1 t2)
list(GET triple_list 2 t3)
list(GET type_cpp_types ${t1} cpp_type1)
list(GET type_cpp_types ${t2} cpp_type2)
list(GET type_cpp_types ${t3} cpp_type3)
string(APPEND javacpp_content "template class Broadcast<${cpp_type1}, ${cpp_type2}, ${cpp_type3}>;\n")
endforeach()
string(APPEND javacpp_content "} // namespace broadcast\n\n")
# BroadcastBool
string(APPEND javacpp_content "namespace broadcast {\n")
foreach(triple IN LISTS combinations_3)
string(REPLACE "," ";" triple_list "${triple}")
list(GET triple_list 0 t1)
list(GET triple_list 1 t2)
list(GET triple_list 2 t3)
list(GET type_cpp_types ${t1} cpp_type1)
list(GET type_cpp_types ${t2} cpp_type2)
list(GET type_cpp_types ${t3} cpp_type3)
string(APPEND javacpp_content "template class BroadcastBool<${cpp_type1}, ${cpp_type2}, ${cpp_type3}>;\n")
endforeach()
string(APPEND javacpp_content "} // namespace broadcast\n\n")
# BroadcastInt
string(APPEND javacpp_content "namespace broadcast {\n")
foreach(triple IN LISTS combinations_3)
string(REPLACE "," ";" triple_list "${triple}")
list(GET triple_list 0 t1)
list(GET triple_list 1 t2)
list(GET triple_list 2 t3)
list(GET type_cpp_types ${t1} cpp_type1)
list(GET type_cpp_types ${t2} cpp_type2)
list(GET type_cpp_types ${t3} cpp_type3)
string(APPEND javacpp_content "template class BroadcastInt<${cpp_type1}, ${cpp_type2}, ${cpp_type3}>;\n")
endforeach()
string(APPEND javacpp_content "} // namespace broadcast\n\n")
# Pair-type transforms (X,Z)
string(APPEND javacpp_content "// ===== PAIR-TYPE TRANSFORMS (X,Z) =====\n\n")
foreach(pair IN LISTS combinations_2)
string(REPLACE "," ";" pair_list "${pair}")
list(GET pair_list 0 t1)
list(GET pair_list 1 t2)
list(GET type_cpp_types ${t1} cpp_type1)
list(GET type_cpp_types ${t2} cpp_type2)
string(APPEND javacpp_content "namespace transform {\n")
string(APPEND javacpp_content "template class TransformAny<${cpp_type1}, ${cpp_type2}>;\n")
string(APPEND javacpp_content "template class TransformBool<${cpp_type1}, ${cpp_type2}>;\n")
string(APPEND javacpp_content "template class TransformFloat<${cpp_type1}, ${cpp_type2}>;\n")
string(APPEND javacpp_content "template class TransformSame<${cpp_type1}, ${cpp_type2}>;\n")
string(APPEND javacpp_content "template class TransformStrict<${cpp_type1}, ${cpp_type2}>;\n")
string(APPEND javacpp_content "} // namespace transform\n\n")
endforeach()
# Reduce operations (X,Z)
string(APPEND javacpp_content "// ===== REDUCE OPERATIONS (X,Z) =====\n\n")
foreach(pair IN LISTS combinations_2)
string(REPLACE "," ";" pair_list "${pair}")
list(GET pair_list 0 t1)
list(GET pair_list 1 t2)
list(GET type_cpp_types ${t1} cpp_type1)
list(GET type_cpp_types ${t2} cpp_type2)
string(APPEND javacpp_content "namespace reduce {\n")
string(APPEND javacpp_content "template class ReduceFloatFunction<${cpp_type1}, ${cpp_type2}>;\n")
string(APPEND javacpp_content "template class ReduceSameFunction<${cpp_type1}, ${cpp_type2}>;\n")
string(APPEND javacpp_content "template class ReduceBoolFunction<${cpp_type1}, ${cpp_type2}>;\n")
string(APPEND javacpp_content "template class ReduceLongFunction<${cpp_type1}, ${cpp_type2}>;\n")
string(APPEND javacpp_content "} // namespace reduce\n\n")
endforeach()
# Reduce3 (X,Z)
string(APPEND javacpp_content "namespace reduce {\n")
foreach(pair IN LISTS combinations_2)
string(REPLACE "," ";" pair_list "${pair}")
list(GET pair_list 0 t1)
list(GET pair_list 1 t2)
list(GET type_cpp_types ${t1} cpp_type1)
list(GET type_cpp_types ${t2} cpp_type2)
string(APPEND javacpp_content "template class Reduce3<${cpp_type1}, ${cpp_type2}>;\n")
endforeach()
string(APPEND javacpp_content "} // namespace reduce\n\n")
# IndexReduce (X,Z)
string(APPEND javacpp_content "namespace indexreduce {\n")
foreach(pair IN LISTS combinations_2)
string(REPLACE "," ";" pair_list "${pair}")
list(GET pair_list 0 t1)
list(GET pair_list 1 t2)
list(GET type_cpp_types ${t1} cpp_type1)
list(GET type_cpp_types ${t2} cpp_type2)
string(APPEND javacpp_content "template class IndexReduce<${cpp_type1}, ${cpp_type2}>;\n")
endforeach()
string(APPEND javacpp_content "} // namespace indexreduce\n\n")
# SummaryStatsReduce (X,Z)
string(APPEND javacpp_content "namespace summarystats {\n")
foreach(pair IN LISTS combinations_2)
string(REPLACE "," ";" pair_list "${pair}")
list(GET pair_list 0 t1)
list(GET pair_list 1 t2)
list(GET type_cpp_types ${t1} cpp_type1)
list(GET type_cpp_types ${t2} cpp_type2)
string(APPEND javacpp_content "template class SummaryStatsReduce<${cpp_type1}, ${cpp_type2}>;\n")
endforeach()
string(APPEND javacpp_content "} // namespace summarystats\n\n")
# Single-type transforms (X)
string(APPEND javacpp_content "// ===== SINGLE-TYPE OPERATIONS (X) =====\n\n")
foreach(idx IN LISTS active_indices)
list(GET type_cpp_types ${idx} cpp_type)
string(APPEND javacpp_content "namespace random {\n")
string(APPEND javacpp_content "template class RandomFunction<${cpp_type}>;\n")
string(APPEND javacpp_content "} // namespace random\n\n")
endforeach()
string(APPEND javacpp_content "} // namespace functions\n\n")
string(APPEND javacpp_content "#endif // SD_JAVACPP_INSTANTIATIONS_H\n")
file(WRITE "${javacpp_header_file}" "${javacpp_content}")
list(LENGTH combinations_2 total_pairs)
list(LENGTH combinations_3 total_triples)
list(LENGTH active_indices total_singles)
message(STATUS "Generated JavaCPP instantiations header:")
message(STATUS " - File: ${javacpp_header_file}")
message(STATUS " - Single-type combinations: ${total_singles}")
message(STATUS " - Pair combinations: ${total_pairs}")
message(STATUS " - Triple combinations: ${total_triples}")
message(STATUS " - This ensures JavaCPP only generates JNI bindings for valid combinations")
endfunction()
function(srcore_generate_headers active_indices combinations_2 combinations_3 output_dir type_enums type_cpp_types)
# Generate the base validity header
_internal_srcore_generate_validity_header("${active_indices}" "${type_enums}" "${type_cpp_types}" "${combinations_2}" "${combinations_3}" "${output_dir}")
message(STATUS "Generated BUILD_ macro overrides: ${override_header_file}")
# Also enhance the main selective_rendering.h with runtime dispatch
srcore_generate_enhanced_header("${active_indices}" "${combinations_2}" "${combinations_3}" "${output_dir}" "${type_enums}" "${type_cpp_types}")
# Generate JavaCPP compatibility header with ALL transform types
srcore_generate_javacpp_header("${combinations_2}" "${combinations_3}" "${output_dir}" "${type_cpp_types}" "${active_indices}")
endfunction()
function(srcore_validate_output active_indices combinations_2 combinations_3)
list(LENGTH active_indices type_count)
list(LENGTH combinations_2 combo_2_count)
list(LENGTH combinations_3 combo_3_count)
if(type_count EQUAL 0)
message(FATAL_ERROR "No active types found")
endif()
if(combo_2_count EQUAL 0)
message(FATAL_ERROR "No 2-type combinations generated")
endif()
if(combo_3_count EQUAL 0)
message(FATAL_ERROR "No 3-type combinations generated")
endif()
endfunction()
function(srcore_emergency_fallback)
set(UNIFIED_ACTIVE_TYPES "float;double;int32_t;bool" PARENT_SCOPE)
set(UNIFIED_COMBINATIONS_2 "0,0;0,1;1,0;1,1;2,2;3,3" PARENT_SCOPE)
set(UNIFIED_COMBINATIONS_3 "0,0,0;1,1,1;2,2,2;3,3,3" PARENT_SCOPE)
set(UNIFIED_TYPE_COUNT 4 PARENT_SCOPE)
message(WARNING "Using emergency fallback type configuration")
endfunction()
function(srcore_auto_setup)
if(NOT DEFINED UNIFIED_COMBINATIONS_3 OR NOT UNIFIED_COMBINATIONS_3)
setup_selective_rendering_unified_safe()
endif()
endfunction()
function(_internal_srcore_generate_validity_header active_indices type_enums type_cpp_types combinations_2 combinations_3 output_dir)
file(MAKE_DIRECTORY "${output_dir}/system")
set(header_file "${output_dir}/system/selective_rendering.h")
# Helper function to convert enum value to integer
function(enum_to_int_value enum_value output_var)
string(REGEX REPLACE ".*::" "" datatype_name "${enum_value}")
# Match exact DataType enum values from the provided header
if(datatype_name STREQUAL "INHERIT")
set(int_value "0")
elseif(datatype_name STREQUAL "BOOL")
set(int_value "1")
elseif(datatype_name STREQUAL "FLOAT8")
set(int_value "2")
elseif(datatype_name STREQUAL "HALF")
set(int_value "3")
elseif(datatype_name STREQUAL "HALF2")
set(int_value "4")
elseif(datatype_name STREQUAL "FLOAT32")
set(int_value "5")
elseif(datatype_name STREQUAL "DOUBLE")
set(int_value "6")
elseif(datatype_name STREQUAL "INT8")
set(int_value "7")
elseif(datatype_name STREQUAL "INT16")
set(int_value "8")
elseif(datatype_name STREQUAL "INT32")
set(int_value "9")
elseif(datatype_name STREQUAL "INT64")
set(int_value "10")
elseif(datatype_name STREQUAL "UINT8")
set(int_value "11")
elseif(datatype_name STREQUAL "UINT16")
set(int_value "12")
elseif(datatype_name STREQUAL "UINT32")
set(int_value "13")
elseif(datatype_name STREQUAL "UINT64")
set(int_value "14")
elseif(datatype_name STREQUAL "QINT8")
set(int_value "15")
elseif(datatype_name STREQUAL "QINT16")
set(int_value "16")
elseif(datatype_name STREQUAL "BFLOAT16")
set(int_value "17")
elseif(datatype_name STREQUAL "UTF8")
set(int_value "50")
elseif(datatype_name STREQUAL "UTF16")
set(int_value "51")
elseif(datatype_name STREQUAL "UTF32")
set(int_value "52")
elseif(datatype_name STREQUAL "ANY")
set(int_value "100")
elseif(datatype_name STREQUAL "AUTO")
set(int_value "200")
elseif(datatype_name STREQUAL "UNKNOWN")
set(int_value "255")
else()
set(int_value "255") # Default to UNKNOWN
message(WARNING "Unknown DataType enum value: ${datatype_name}")
endif()
set(${output_var} "${int_value}" PARENT_SCOPE)
endfunction()
# Define type categories for partitioning
set(bool_types "1")
set(float_types "3;4;5;6") # HALF, HALF2, FLOAT32, DOUBLE
set(bfloat_types "17")
set(int_types "7;8;9;10") # INT8, INT16, INT32, INT64
set(uint_types "11;12;13;14") # UINT8, UINT16, UINT32, UINT64
set(string_types "50;51;52") # UTF8, UTF16, UTF32
# Helper function to determine which category a type belongs to
function(get_type_category type_num output_var)
list(FIND bool_types "${type_num}" idx)
if(idx GREATER_EQUAL 0)
set(${output_var} "bool" PARENT_SCOPE)
return()
endif()
list(FIND float_types "${type_num}" idx)
if(idx GREATER_EQUAL 0)
set(${output_var} "float" PARENT_SCOPE)
return()
endif()
list(FIND bfloat_types "${type_num}" idx)
if(idx GREATER_EQUAL 0)
set(${output_var} "bfloat" PARENT_SCOPE)
return()
endif()
list(FIND int_types "${type_num}" idx)
if(idx GREATER_EQUAL 0)
set(${output_var} "int" PARENT_SCOPE)
return()
endif()
list(FIND uint_types "${type_num}" idx)
if(idx GREATER_EQUAL 0)
set(${output_var} "uint" PARENT_SCOPE)
return()
endif()
list(FIND string_types "${type_num}" idx)
if(idx GREATER_EQUAL 0)
set(${output_var} "string" PARENT_SCOPE)
return()
endif()
set(${output_var} "other" PARENT_SCOPE)
endfunction()
# Initialize separate content for each category
set(core_content "")
set(bool_content "")
set(float_content "")
set(bfloat_content "")
set(int_content "")
set(uint_content "")
set(string_content "")
# Start building core mappings header (always included)
string(APPEND core_content "/* AUTOMATICALLY GENERATED - Core Type Mappings */\n")
string(APPEND core_content "/* Generated by SelectiveRenderingCore.cmake */\n")
string(APPEND core_content "#ifndef SD_SELECTIVE_RENDERING_CORE_H\n")
string(APPEND core_content "#define SD_SELECTIVE_RENDERING_CORE_H\n")
string(APPEND core_content "// Also define master guard so types.h recognizes selective rendering is active\n")
string(APPEND core_content "#define SD_SELECTIVE_RENDERING_H\n\n")
# Initialize category headers
string(APPEND bool_content "/* BOOL type flags */\n#ifndef SD_BOOL_TYPES_H\n#define SD_BOOL_TYPES_H\n\n")
string(APPEND float_content "/* FLOAT type flags */\n#ifndef SD_FLOAT_TYPES_H\n#define SD_FLOAT_TYPES_H\n\n")
string(APPEND bfloat_content "/* BFLOAT type flags */\n#ifndef SD_BFLOAT_TYPES_H\n#define SD_BFLOAT_TYPES_H\n\n")
string(APPEND int_content "/* INT type flags */\n#ifndef SD_INT_TYPES_H\n#define SD_INT_TYPES_H\n\n")
string(APPEND uint_content "/* UINT type flags */\n#ifndef SD_UINT_TYPES_H\n#define SD_UINT_TYPES_H\n\n")
string(APPEND string_content "/* STRING type flags */\n#ifndef SD_STRING_TYPES_H\n#define SD_STRING_TYPES_H\n\n")
# Start building the master header content
set(header_content "/* AUTOMATICALLY GENERATED - Selective Rendering Header */\n")
string(APPEND header_content "/* Generated by SelectiveRenderingCore.cmake */\n")
string(APPEND header_content "#ifndef SD_SELECTIVE_RENDERING_H\n")
string(APPEND header_content "#define SD_SELECTIVE_RENDERING_H\n\n")
string(APPEND header_content "// Include all type category headers\n")
string(APPEND header_content "#include \"selective_rendering/core.h\"\n")
string(APPEND header_content "#include \"selective_rendering/bool_types.h\"\n")
string(APPEND header_content "#include \"selective_rendering/float_types.h\"\n")
string(APPEND header_content "#include \"selective_rendering/bfloat_types.h\"\n")
string(APPEND header_content "#include \"selective_rendering/int_types.h\"\n")
string(APPEND header_content "#include \"selective_rendering/uint_types.h\"\n")
string(APPEND header_content "#include \"selective_rendering/string_types.h\"\n\n")
# ============================================================================
# SECTION 1: RAW COMPILATION FLAGS
# ============================================================================
string(APPEND header_content "// ============================================================================\n")
string(APPEND header_content "// SECTION 1: RAW COMPILATION FLAGS\n")
string(APPEND header_content "// ============================================================================\n\n")
# Collect all compiled type numbers from ACTUAL combinations, not from type_enums
# This ensures SD_*_COMPILED flags match what was actually instantiated
list(LENGTH type_enums num_types)
set(compiled_type_numbers "")
# Extract types from combinations_2
foreach(combo IN LISTS combinations_2)
string(REPLACE "," ";" parts "${combo}")
list(GET parts 0 i)
list(GET parts 1 j)
if(i LESS ${num_types})
list(GET type_enums ${i} enum_i)
enum_to_int_value("${enum_i}" int_i)
list(FIND compiled_type_numbers "${int_i}" found_idx)
if(found_idx EQUAL -1)
list(APPEND compiled_type_numbers "${int_i}")
endif()
endif()
if(j LESS ${num_types})
list(GET type_enums ${j} enum_j)
enum_to_int_value("${enum_j}" int_j)
list(FIND compiled_type_numbers "${int_j}" found_idx)
if(found_idx EQUAL -1)
list(APPEND compiled_type_numbers "${int_j}")
endif()
endif()
endforeach()
# Extract types from combinations_3
foreach(combo IN LISTS combinations_3)
string(REPLACE "," ";" parts "${combo}")
list(GET parts 0 i)
list(GET parts 1 j)
list(GET parts 2 k)
if(i LESS ${num_types})
list(GET type_enums ${i} enum_i)
enum_to_int_value("${enum_i}" int_i)
list(FIND compiled_type_numbers "${int_i}" found_idx)
if(found_idx EQUAL -1)
list(APPEND compiled_type_numbers "${int_i}")
endif()
endif()
if(j LESS ${num_types})
list(GET type_enums ${j} enum_j)
enum_to_int_value("${enum_j}" int_j)
list(FIND compiled_type_numbers "${int_j}" found_idx)
if(found_idx EQUAL -1)
list(APPEND compiled_type_numbers "${int_j}")
endif()
endif()
if(k LESS ${num_types})
list(GET type_enums ${k} enum_k)
enum_to_int_value("${enum_k}" int_k)
list(FIND compiled_type_numbers "${int_k}" found_idx)
if(found_idx EQUAL -1)
list(APPEND compiled_type_numbers "${int_k}")
endif()
endif()
endforeach()
# Generate single type compilation flags for ALL possible types
# Append to appropriate category files
set(all_possible_types "0;1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16;17;50;51;52;100;200;255")
foreach(type_num IN LISTS all_possible_types)
list(FIND compiled_type_numbers "${type_num}" found_idx)
set(flag_value "0")
if(found_idx GREATER_EQUAL 0)
set(flag_value "1")
endif()
# Determine which category this type belongs to
get_type_category("${type_num}" category)
# Append to appropriate category content
if(category STREQUAL "bool")
string(APPEND bool_content "#define SD_SINGLE_TYPE_${type_num}_COMPILED ${flag_value}\n")
elseif(category STREQUAL "float")
string(APPEND float_content "#define SD_SINGLE_TYPE_${type_num}_COMPILED ${flag_value}\n")
elseif(category STREQUAL "bfloat")
string(APPEND bfloat_content "#define SD_SINGLE_TYPE_${type_num}_COMPILED ${flag_value}\n")
elseif(category STREQUAL "int")
string(APPEND int_content "#define SD_SINGLE_TYPE_${type_num}_COMPILED ${flag_value}\n")
elseif(category STREQUAL "uint")
string(APPEND uint_content "#define SD_SINGLE_TYPE_${type_num}_COMPILED ${flag_value}\n")
elseif(category STREQUAL "string")
string(APPEND string_content "#define SD_SINGLE_TYPE_${type_num}_COMPILED ${flag_value}\n")
endif()
endforeach()
# Generate pair type compilation flags
string(APPEND header_content "// Pair type compilation flags\n")
set(all_pair_keys "")
# Collect all valid pairs from combinations_2
foreach(combo IN LISTS combinations_2)
string(REPLACE "," ";" parts "${combo}")
list(GET parts 0 i)
list(GET parts 1 j)
if(i LESS ${num_types} AND j LESS ${num_types})
list(GET type_enums ${i} enum_i)
list(GET type_enums ${j} enum_j)
enum_to_int_value("${enum_i}" int_i)
enum_to_int_value("${enum_j}" int_j)
set(pair_key "${int_i}_${int_j}")
list(FIND all_pair_keys "${pair_key}" found_idx)
if(found_idx EQUAL -1)
list(APPEND all_pair_keys "${pair_key}")
endif()
endif()
endforeach()
# Generate all pair combinations
# Append to category files based on which types are involved
foreach(type1 IN LISTS all_possible_types)
foreach(type2 IN LISTS all_possible_types)
set(pair_key "${type1}_${type2}")
list(FIND all_pair_keys "${pair_key}" found_idx)
set(flag_value "0")
if(found_idx GREATER_EQUAL 0)
set(flag_value "1")
endif()
# Get category for first type only - assign pair to exactly one file
# This prevents duplicate definitions when multiple headers are included
get_type_category("${type1}" cat1)
# Append to only the category file for the first type
if(cat1 STREQUAL "bool")
string(APPEND bool_content "#define SD_PAIR_TYPE_${type1}_${type2}_COMPILED ${flag_value}\n")
elseif(cat1 STREQUAL "float")
string(APPEND float_content "#define SD_PAIR_TYPE_${type1}_${type2}_COMPILED ${flag_value}\n")
elseif(cat1 STREQUAL "bfloat")
string(APPEND bfloat_content "#define SD_PAIR_TYPE_${type1}_${type2}_COMPILED ${flag_value}\n")
elseif(cat1 STREQUAL "int")
string(APPEND int_content "#define SD_PAIR_TYPE_${type1}_${type2}_COMPILED ${flag_value}\n")
elseif(cat1 STREQUAL "uint")
string(APPEND uint_content "#define SD_PAIR_TYPE_${type1}_${type2}_COMPILED ${flag_value}\n")
elseif(cat1 STREQUAL "string")
string(APPEND string_content "#define SD_PAIR_TYPE_${type1}_${type2}_COMPILED ${flag_value}\n")
else()
# For "other" types, put in core.h
string(APPEND core_content "#define SD_PAIR_TYPE_${type1}_${type2}_COMPILED ${flag_value}\n")
endif()
endforeach()
endforeach()
# Generate triple type compilation flags - append to category files
string(APPEND bool_content "\n// Triple type compilation flags (bool-related)\n")
string(APPEND float_content "\n// Triple type compilation flags (float-related)\n")
string(APPEND bfloat_content "\n// Triple type compilation flags (bfloat-related)\n")
string(APPEND int_content "\n// Triple type compilation flags (int-related)\n")
string(APPEND uint_content "\n// Triple type compilation flags (uint-related)\n")
string(APPEND string_content "\n// Triple type compilation flags (string-related)\n")
set(all_triple_keys "")
# Collect all valid triples from combinations_3
foreach(combo IN LISTS combinations_3)
string(REPLACE "," ";" parts "${combo}")
list(GET parts 0 i)
list(GET parts 1 j)
list(GET parts 2 k)
if(i LESS ${num_types} AND j LESS ${num_types} AND k LESS ${num_types})
list(GET type_enums ${i} enum_i)
list(GET type_enums ${j} enum_j)
list(GET type_enums ${k} enum_k)
enum_to_int_value("${enum_i}" int_i)
enum_to_int_value("${enum_j}" int_j)
enum_to_int_value("${enum_k}" int_k)
set(triple_key "${int_i}_${int_j}_${int_k}")
list(FIND all_triple_keys "${triple_key}" found_idx)
if(found_idx EQUAL -1)
list(APPEND all_triple_keys "${triple_key}")
endif()
endif()
endforeach()
# Generate all triple combinations - route to appropriate category files
foreach(type1 IN LISTS all_possible_types)
foreach(type2 IN LISTS all_possible_types)
foreach(type3 IN LISTS all_possible_types)
set(triple_key "${type1}_${type2}_${type3}")
list(FIND all_triple_keys "${triple_key}" found_idx)
if(found_idx GREATER_EQUAL 0)
set(flag_value "1")
else()
set(flag_value "0")
endif()
# Get category for first type only - assign triple to exactly one file
# This prevents duplicate definitions when multiple headers are included
get_type_category("${type1}" cat1)
# Append to only the category file for the first type
if(cat1 STREQUAL "bool")
string(APPEND bool_content "#define SD_TRIPLE_TYPE_${type1}_${type2}_${type3}_COMPILED ${flag_value}\n")
elseif(cat1 STREQUAL "float")
string(APPEND float_content "#define SD_TRIPLE_TYPE_${type1}_${type2}_${type3}_COMPILED ${flag_value}\n")
elseif(cat1 STREQUAL "bfloat")
string(APPEND bfloat_content "#define SD_TRIPLE_TYPE_${type1}_${type2}_${type3}_COMPILED ${flag_value}\n")
elseif(cat1 STREQUAL "int")
string(APPEND int_content "#define SD_TRIPLE_TYPE_${type1}_${type2}_${type3}_COMPILED ${flag_value}\n")
elseif(cat1 STREQUAL "uint")
string(APPEND uint_content "#define SD_TRIPLE_TYPE_${type1}_${type2}_${type3}_COMPILED ${flag_value}\n")
elseif(cat1 STREQUAL "string")
string(APPEND string_content "#define SD_TRIPLE_TYPE_${type1}_${type2}_${type3}_COMPILED ${flag_value}\n")
else()
# For "other" types, put in core.h
string(APPEND core_content "#define SD_TRIPLE_TYPE_${type1}_${type2}_${type3}_COMPILED ${flag_value}\n")
endif()
endforeach()
endforeach()
endforeach()
# ============================================================================
# SECTION 2: MAPPING TABLES - COMPLETE VERSION
# These go into core.h which is always included
# ============================================================================
string(APPEND core_content "// ============================================================================\n")
string(APPEND core_content "// SECTION 2: MAPPING TABLES\n")
string(APPEND core_content "// ============================================================================\n\n")
# Generate enum to number mappings - Complete DataType enum coverage
string(APPEND core_content "// DataType enum to number mappings (with namespace handling)\n")
string(APPEND core_content "#define SD_ENUM_TO_NUM_INHERIT 0\n")
string(APPEND core_content "#define SD_ENUM_TO_NUM_BOOL 1\n")
string(APPEND core_content "#define SD_ENUM_TO_NUM_FLOAT8 2\n")
string(APPEND core_content "#define SD_ENUM_TO_NUM_HALF 3\n")
string(APPEND core_content "#define SD_ENUM_TO_NUM_HALF2 4\n")
string(APPEND core_content "#define SD_ENUM_TO_NUM_FLOAT32 5\n")
string(APPEND core_content "#define SD_ENUM_TO_NUM_DOUBLE 6\n")
string(APPEND core_content "#define SD_ENUM_TO_NUM_INT8 7\n")
string(APPEND core_content "#define SD_ENUM_TO_NUM_INT16 8\n")
string(APPEND core_content "#define SD_ENUM_TO_NUM_INT32 9\n")
string(APPEND core_content "#define SD_ENUM_TO_NUM_INT64 10\n")
string(APPEND core_content "#define SD_ENUM_TO_NUM_UINT8 11\n")
string(APPEND core_content "#define SD_ENUM_TO_NUM_UINT16 12\n")
string(APPEND core_content "#define SD_ENUM_TO_NUM_UINT32 13\n")
string(APPEND core_content "#define SD_ENUM_TO_NUM_UINT64 14\n")
string(APPEND core_content "#define SD_ENUM_TO_NUM_QINT8 15\n")
string(APPEND core_content "#define SD_ENUM_TO_NUM_QINT16 16\n")
string(APPEND core_content "#define SD_ENUM_TO_NUM_BFLOAT16 17\n")
string(APPEND core_content "#define SD_ENUM_TO_NUM_UTF8 50\n")
string(APPEND core_content "#define SD_ENUM_TO_NUM_UTF16 51\n")
string(APPEND core_content "#define SD_ENUM_TO_NUM_UTF32 52\n")
string(APPEND core_content "#define SD_ENUM_TO_NUM_ANY 100\n")
string(APPEND core_content "#define SD_ENUM_TO_NUM_AUTO 200\n")
string(APPEND core_content "#define SD_ENUM_TO_NUM_UNKNOWN 255\n")
string(APPEND core_content "\n")
# Generate alias to number mappings
string(APPEND core_content "// Constexpr alias to number mappings\n")
string(APPEND core_content "#define SD_ALIAS_TO_NUM_INHERIT 0\n")
string(APPEND core_content "#define SD_ALIAS_TO_NUM_BOOL 1\n")
string(APPEND core_content "#define SD_ALIAS_TO_NUM_FLOAT8 2\n")
string(APPEND core_content "#define SD_ALIAS_TO_NUM_HALF 3\n")
string(APPEND core_content "#define SD_ALIAS_TO_NUM_HALF2 4\n")
string(APPEND core_content "#define SD_ALIAS_TO_NUM_FLOAT32 5\n")
string(APPEND core_content "#define SD_ALIAS_TO_NUM_DOUBLE 6\n")
string(APPEND core_content "#define SD_ALIAS_TO_NUM_INT8 7\n")
string(APPEND core_content "#define SD_ALIAS_TO_NUM_INT16 8\n")
string(APPEND core_content "#define SD_ALIAS_TO_NUM_INT32 9\n")
string(APPEND core_content "#define SD_ALIAS_TO_NUM_INT64 10\n")
string(APPEND core_content "#define SD_ALIAS_TO_NUM_UINT8 11\n")
string(APPEND core_content "#define SD_ALIAS_TO_NUM_UINT16 12\n")
string(APPEND core_content "#define SD_ALIAS_TO_NUM_UINT32 13\n")
string(APPEND core_content "#define SD_ALIAS_TO_NUM_UINT64 14\n")
string(APPEND core_content "#define SD_ALIAS_TO_NUM_QINT8 15\n")
string(APPEND core_content "#define SD_ALIAS_TO_NUM_QINT16 16\n")
string(APPEND core_content "#define SD_ALIAS_TO_NUM_BFLOAT16 17\n")
string(APPEND core_content "#define SD_ALIAS_TO_NUM_UTF8 50\n")
string(APPEND core_content "#define SD_ALIAS_TO_NUM_UTF16 51\n")
string(APPEND core_content "#define SD_ALIAS_TO_NUM_UTF32 52\n")
string(APPEND core_content "#define SD_ALIAS_TO_NUM_ANY 100\n")
string(APPEND core_content "#define SD_ALIAS_TO_NUM_AUTO 200\n")
string(APPEND core_content "#define SD_ALIAS_TO_NUM_UNKNOWN 255\n")
string(APPEND core_content "\n")
# Generate C++ type to number mappings - COMPREHENSIVE LIST
string(APPEND core_content "// C++ type name to number mappings\n")
# Build a comprehensive type mapping dictionary
set(type_mappings "")
list(APPEND type_mappings "bool:1")
list(APPEND type_mappings "float16:3")
list(APPEND type_mappings "half:3")
list(APPEND type_mappings "float:5")
list(APPEND type_mappings "float32:5")
list(APPEND type_mappings "double:6")
list(APPEND type_mappings "int8_t:7")
list(APPEND type_mappings "int16_t:8")
list(APPEND type_mappings "Int16Type:8")
list(APPEND type_mappings "int32_t:9")
list(APPEND type_mappings "Int32Type:9")
list(APPEND type_mappings "int:9")
list(APPEND type_mappings "int64_t:10")
list(APPEND type_mappings "LongType:10")
list(APPEND type_mappings "long:10")
list(APPEND type_mappings "long_long:10")
list(APPEND type_mappings "uint8_t:11")
list(APPEND type_mappings "unsigned_char:11")
list(APPEND type_mappings "uint16_t:12")
list(APPEND type_mappings "UInt16Type:12")
list(APPEND type_mappings "unsigned_short:12")
list(APPEND type_mappings "uint32_t:13")
list(APPEND type_mappings "UInt32Type:13")
list(APPEND type_mappings "unsigned_int:13")
list(APPEND type_mappings "uint64_t:14")
list(APPEND type_mappings "UInt64Type:14")
list(APPEND type_mappings "UnsignedLong:14")
list(APPEND type_mappings "unsigned_long:14")
list(APPEND type_mappings "bfloat16:17")
list(APPEND type_mappings "bfloat:17")
list(APPEND type_mappings "stdstring:50")
list(APPEND type_mappings "SignedChar:7")
list(APPEND type_mappings "UnsignedChar:11")
list(APPEND type_mappings "signed_char:7")
list(APPEND type_mappings "unsigned_char:11")
list(APPEND type_mappings "schar:7")
list(APPEND type_mappings "uchar:11")
list(APPEND type_mappings "int8:7")
list(APPEND type_mappings "uint8:11")
list(APPEND type_mappings "int16:8")
list(APPEND type_mappings "uint16:12")
list(APPEND type_mappings "int32:9")
list(APPEND type_mappings "uint32:13")
list(APPEND type_mappings "int64:10")
list(APPEND type_mappings "uint64:14")
list(APPEND type_mappings "short:8")
list(APPEND type_mappings "ushort:12")
list(APPEND type_mappings "uint:13")
list(APPEND type_mappings "longlong:10")
list(APPEND type_mappings "ulonglong:14")
list(APPEND type_mappings "ulong:14")
list(APPEND type_mappings "char:7")
# Generate all type to number mappings (both SD_TYPE_TO_NUM and SD_ALIAS_TO_NUM for compatibility)
foreach(mapping IN LISTS type_mappings)
string(REPLACE ":" ";" mapping_parts "${mapping}")
list(GET mapping_parts 0 type_name)
list(GET mapping_parts 1 type_num)
string(APPEND core_content "#define SD_TYPE_TO_NUM_${type_name} ${type_num}\n")
string(APPEND core_content "#define SD_ALIAS_TO_NUM_${type_name} ${type_num}\n")
endforeach()
string(APPEND core_content "\n")
# ============================================================================
# SECTION 2.5: HAS_* FEATURE DETECTION MACROS
# ============================================================================
string(APPEND core_content "// HAS_* macros for DataTypeUtils.h scalarTypesForNDarray trait\n")
string(APPEND core_content "// These indicate which types are compiled in selective rendering mode\n")
# Map type names to HAS_* macro names
set(HAS_MACRO_MAPPINGS "")
list(APPEND HAS_MACRO_MAPPINGS "bool:BOOL")
list(APPEND HAS_MACRO_MAPPINGS "float16:FLOAT16")
list(APPEND HAS_MACRO_MAPPINGS "bfloat16:BFLOAT16")
list(APPEND HAS_MACRO_MAPPINGS "float32:FLOAT32")
list(APPEND HAS_MACRO_MAPPINGS "double:DOUBLE")
list(APPEND HAS_MACRO_MAPPINGS "int8:INT8")
list(APPEND HAS_MACRO_MAPPINGS "int16:INT16")
list(APPEND HAS_MACRO_MAPPINGS "int32:INT32")
list(APPEND HAS_MACRO_MAPPINGS "int64:INT64")
list(APPEND HAS_MACRO_MAPPINGS "uint8:UINT8")
list(APPEND HAS_MACRO_MAPPINGS "uint16:UINT16")
list(APPEND HAS_MACRO_MAPPINGS "uint32:UINT32")
list(APPEND HAS_MACRO_MAPPINGS "uint64:UNSIGNEDLONG")
list(APPEND HAS_MACRO_MAPPINGS "utf8:UTF8")
list(APPEND HAS_MACRO_MAPPINGS "utf16:UTF16")
list(APPEND HAS_MACRO_MAPPINGS "utf32:UTF32")
# Generate HAS_* macros for enabled types
foreach(type_name IN LISTS SD_TYPES_LIST)
# Convert type name to lowercase for matching
string(TOLOWER "${type_name}" type_lower)
# Find matching HAS_* macro name
foreach(mapping IN LISTS HAS_MACRO_MAPPINGS)
string(REPLACE ":" ";" mapping_parts "${mapping}")
list(GET mapping_parts 0 map_type)
list(GET mapping_parts 1 map_macro)
if("${type_lower}" STREQUAL "${map_type}")
string(APPEND core_content "#define HAS_${map_macro} 1\n")
break()
endif()
endforeach()
endforeach()
string(APPEND core_content "\n")
# ============================================================================
# SECTION 3: CONDITIONAL COMPILATION MACROS
# ============================================================================
# ============================================================================
# SECTION 3: REMOVED - SD_IF_* CONDITIONAL COMPILATION MACROS
# ============================================================================
#
# REASON: These macros consumed 19,344 lines (~96% of selective_rendering.h),
# causing Clang 20.1.6 to exceed its source location limit ("ran out of source
# locations") when compiling large translation units like NativeOpExecutioner.cpp.
#
# IMPACT: None. Analysis showed these macros were never used in the codebase.
# The code directly checks SD_*_TYPE_*_COMPILED flags via preprocessor conditionals.
#
# RESULT: selective_rendering.h reduced from 20,152 lines to ~800 lines (96% reduction),
# allowing compilation with Clang while maintaining full 14-type support.
#
# Helper macros (SD_BUILD_*_IF_VALID) are appended separately by
# _internal_srcore_append_runtime_dispatch_to_header() around line 2171.
# ============================================================================
# Write partitioned header files
# ============================================================================
# Create selective_rendering subdirectory
get_filename_component(header_dir "${header_file}" DIRECTORY)
set(sr_dir "${header_dir}/selective_rendering")
file(MAKE_DIRECTORY "${sr_dir}")
# Close and write core.h (type mappings - always needed)
string(APPEND core_content "\n#endif // SD_SELECTIVE_RENDERING_CORE_H\n")
_srcore_write_if_different("${sr_dir}/core.h" "${core_content}")
# Close and write bool_types.h
string(APPEND bool_content "\n#endif // SD_SELECTIVE_RENDERING_BOOL_TYPES_H\n")
_srcore_write_if_different("${sr_dir}/bool_types.h" "${bool_content}")
# Close and write float_types.h
string(APPEND float_content "\n#endif // SD_SELECTIVE_RENDERING_FLOAT_TYPES_H\n")
_srcore_write_if_different("${sr_dir}/float_types.h" "${float_content}")
# Close and write bfloat_types.h
string(APPEND bfloat_content "\n#endif // SD_SELECTIVE_RENDERING_BFLOAT_TYPES_H\n")
_srcore_write_if_different("${sr_dir}/bfloat_types.h" "${bfloat_content}")
# Close and write int_types.h
string(APPEND int_content "\n#endif // SD_SELECTIVE_RENDERING_INT_TYPES_H\n")
_srcore_write_if_different("${sr_dir}/int_types.h" "${int_content}")
# Close and write uint_types.h
string(APPEND uint_content "\n#endif // SD_SELECTIVE_RENDERING_UINT_TYPES_H\n")
_srcore_write_if_different("${sr_dir}/uint_types.h" "${uint_content}")
# Close and write string_types.h
string(APPEND string_content "\n#endif // SD_SELECTIVE_RENDERING_STRING_TYPES_H\n")
_srcore_write_if_different("${sr_dir}/string_types.h" "${string_content}")
# Replace header_content with includes to all category headers
set(header_content "")
string(APPEND header_content "#ifndef SD_SELECTIVE_RENDERING_H\n")
string(APPEND header_content "#define SD_SELECTIVE_RENDERING_H\n\n")
string(APPEND header_content "// ============================================================================\n")
string(APPEND header_content "// Selective Rendering Type System - Partitioned Headers\n")
string(APPEND header_content "// ============================================================================\n")
string(APPEND header_content "// This master header includes all type category headers.\n")
string(APPEND header_content "// Large translation units can include only the specific category headers\n")
string(APPEND header_content "// they need to avoid Clang source location limits.\n")
string(APPEND header_content "// ============================================================================\n\n")
string(APPEND header_content "// Core type mappings (always required)\n")
string(APPEND header_content "#include \"selective_rendering/core.h\"\n\n")
string(APPEND header_content "// Type category headers\n")
string(APPEND header_content "#include \"selective_rendering/bool_types.h\"\n")
string(APPEND header_content "#include \"selective_rendering/float_types.h\"\n")
string(APPEND header_content "#include \"selective_rendering/bfloat_types.h\"\n")
string(APPEND header_content "#include \"selective_rendering/int_types.h\"\n")
string(APPEND header_content "#include \"selective_rendering/uint_types.h\"\n")
string(APPEND header_content "#include \"selective_rendering/string_types.h\"\n\n")
# Close the header guard
string(APPEND header_content "#endif // SD_SELECTIVE_RENDERING_H\n")
# Write the master header file
_srcore_write_if_different("${header_file}" "${header_content}")
# Report generation results
list(LENGTH all_triple_keys total_triple_combinations)
list(LENGTH all_pair_keys total_pair_combinations)
list(LENGTH compiled_type_numbers total_single_types)
message(STATUS "Generated selective_rendering.h (partitioned):")
message(STATUS " - Master header: ${header_file}")
message(STATUS " - Partitioned headers directory: ${sr_dir}/")
message(STATUS " * core.h (type mappings)")
message(STATUS " * bool_types.h, float_types.h, bfloat_types.h")
message(STATUS " * int_types.h, uint_types.h, string_types.h")
message(STATUS " - Single types: ${total_single_types}")
message(STATUS " - Pair combinations: ${total_pair_combinations}")
message(STATUS " - Triple combinations: ${total_triple_combinations}")
endfunction()
# ============================================================================
# NEW FUNCTION: Verify Type Compilation Status
# ============================================================================
function(verify_type_compilation_status)
message(STATUS "")
message(STATUS "=== Type Compilation Status ===")
# Check active types count
if(DEFINED UNIFIED_ACTIVE_TYPES)
list(LENGTH UNIFIED_ACTIVE_TYPES active_count)
message(STATUS "Active types count: ${active_count}")
message(STATUS "Active types: ${UNIFIED_ACTIVE_TYPES}")
else()
message(WARNING "UNIFIED_ACTIVE_TYPES not defined!")
endif()
# Check combinations count
if(DEFINED UNIFIED_COMBINATIONS_2)
list(LENGTH UNIFIED_COMBINATIONS_2 combo2_count)
message(STATUS "2-type combinations: ${combo2_count}")
endif()
if(DEFINED UNIFIED_COMBINATIONS_3)
list(LENGTH UNIFIED_COMBINATIONS_3 combo3_count)
message(STATUS "3-type combinations: ${combo3_count}")
endif()
# Check generated header file exists and has content
if(EXISTS "${CMAKE_BINARY_DIR}/include/system/selective_rendering.h")
file(READ "${CMAKE_BINARY_DIR}/include/system/selective_rendering.h" header_content)
string(LENGTH "${header_content}" header_size)
message(STATUS "Generated header size: ${header_size} bytes")
# Count how many types are actually compiled (have _COMPILED 1)
string(REGEX MATCHALL "#define SD_SINGLE_TYPE_[0-9]+_COMPILED 1" compiled_singles "${header_content}")
list(LENGTH compiled_singles compiled_count)
message(STATUS "Compiled single types: ${compiled_count}")
else()
message(WARNING "selective_rendering.h not found at expected location!")
endif()
message(STATUS "==============================")
message(STATUS "")
endfunction()
# ============================================================================
# SECTION 5: MAIN ORCHESTRATOR FUNCTIONS
# ============================================================================
function(setup_selective_rendering_unified)
set(options "")
set(one_value_args TYPE_PROFILE OUTPUT_DIR)
set(multi_value_args "")
cmake_parse_arguments(SRCORE "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN})
if(NOT SRCORE_TYPE_PROFILE)
set(SRCORE_TYPE_PROFILE "${SD_TYPE_PROFILE}")
endif()
if(NOT SRCORE_OUTPUT_DIR)
set(SRCORE_OUTPUT_DIR "${CMAKE_BINARY_DIR}/include")
endif()
srcore_discover_active_types(active_types_indices discovered_enums discovered_cpp_types)
list(LENGTH active_types_indices type_count)
if(type_count EQUAL 0)
message(FATAL_ERROR "No active types discovered!")
endif()
srcore_generate_combinations("${active_types_indices}" "${SRCORE_TYPE_PROFILE}" combinations_2 combinations_3)
srcore_generate_headers("${active_types_indices}" "${combinations_2}" "${combinations_3}" "${SRCORE_OUTPUT_DIR}" "${discovered_enums}" "${discovered_cpp_types}")
set(UNIFIED_COMBINATIONS_2 "${combinations_2}" PARENT_SCOPE)
set(UNIFIED_COMBINATIONS_3 "${combinations_3}" PARENT_SCOPE)
set(UNIFIED_ACTIVE_TYPES "${SRCORE_ACTIVE_TYPES}" PARENT_SCOPE)
set(UNIFIED_TYPE_COUNT ${type_count} PARENT_SCOPE)
set(UNIFIED_COMBINATIONS_2 "${combinations_2}" CACHE INTERNAL "Unified 2-type combinations")
set(UNIFIED_COMBINATIONS_3 "${combinations_3}" CACHE INTERNAL "Unified 3-type combinations")
set(UNIFIED_ACTIVE_TYPES "${SRCORE_ACTIVE_TYPES}" CACHE INTERNAL "Active types for build")
set(UNIFIED_TYPE_COUNT ${type_count} CACHE INTERNAL "Unified active type count")
_internal_ensure_diagnostics_output()
report_selective_rendering_statistics()
endfunction()
function(setup_selective_rendering_unified_safe)
if(NOT CMAKE_CROSSCOMPILING AND NOT ANDROID)
setup_selective_rendering_unified(${ARGN})
srcore_map_to_legacy_variables()
srcore_generate_diagnostic_report()
_internal_ensure_diagnostics_output()
else()
setup_selective_rendering_unified(${ARGN})
srcore_map_to_legacy_variables()
_internal_ensure_diagnostics_output()
endif()
# Propagate variables to parent scope
if(DEFINED UNIFIED_COMBINATIONS_3)
set(UNIFIED_COMBINATIONS_3 "${UNIFIED_COMBINATIONS_3}" PARENT_SCOPE)
endif()
if(DEFINED UNIFIED_COMBINATIONS_2)
set(UNIFIED_COMBINATIONS_2 "${UNIFIED_COMBINATIONS_2}" PARENT_SCOPE)
endif()
if(DEFINED UNIFIED_ACTIVE_TYPES)
set(UNIFIED_ACTIVE_TYPES "${UNIFIED_ACTIVE_TYPES}" PARENT_SCOPE)
endif()
if(DEFINED UNIFIED_TYPE_COUNT)
set(UNIFIED_TYPE_COUNT "${UNIFIED_TYPE_COUNT}" PARENT_SCOPE)
endif()
# Final verification
if(NOT DEFINED UNIFIED_COMBINATIONS_3 OR NOT UNIFIED_COMBINATIONS_3)
srcore_emergency_fallback()
srcore_map_to_legacy_variables()
# FIX: Ensure diagnostics even for fallback
_internal_ensure_diagnostics_output()
if(DEFINED UNIFIED_COMBINATIONS_3)
set(UNIFIED_COMBINATIONS_3 "${UNIFIED_COMBINATIONS_3}" PARENT_SCOPE)
endif()
if(DEFINED UNIFIED_COMBINATIONS_2)
set(UNIFIED_COMBINATIONS_2 "${UNIFIED_COMBINATIONS_2}" PARENT_SCOPE)
endif()
if(DEFINED UNIFIED_ACTIVE_TYPES)
set(UNIFIED_ACTIVE_TYPES "${UNIFIED_ACTIVE_TYPES}" PARENT_SCOPE)
endif()
if(DEFINED UNIFIED_TYPE_COUNT)
set(UNIFIED_TYPE_COUNT "${UNIFIED_TYPE_COUNT}" PARENT_SCOPE)
endif()
endif()
if(NOT DEFINED UNIFIED_COMBINATIONS_3 OR NOT UNIFIED_COMBINATIONS_3)
message(FATAL_ERROR "Unable to establish UNIFIED_COMBINATIONS_3 even with emergency fallback!")
endif()
# FIX: Add final check for diagnostics status
check_diagnostics_status()
endfunction()
function(_internal_ensure_diagnostics_output)
# Always create the diagnostics output directory
set(COMBINATION_REPORT_DIR "${CMAKE_BINARY_DIR}/type_combinations")
file(MAKE_DIRECTORY "${COMBINATION_REPORT_DIR}")
# Set as cache variable for other functions to use
set(SD_DIAGNOSTICS_DIR "${COMBINATION_REPORT_DIR}" CACHE INTERNAL "Type combinations diagnostics directory")
# Create a timestamp file to mark when the directory was created
string(TIMESTAMP creation_time "%Y-%m-%d %H:%M:%S")
file(WRITE "${COMBINATION_REPORT_DIR}/.created" "Directory created: ${creation_time}\n")
# FIX: Add explicit message about creating directory
message(STATUS "Creating type combinations diagnostics directory: ${COMBINATION_REPORT_DIR}")
# Automatically dump combinations if they exist
if(DEFINED UNIFIED_COMBINATIONS_2 OR DEFINED UNIFIED_COMBINATIONS_3)
# Silently dump combinations to disk without console output
_internal_quiet_dump_combinations("${COMBINATION_REPORT_DIR}")
# FIX: Also call the main dump function for full reports
dump_type_combinations_to_disk("${COMBINATION_REPORT_DIR}")
message(STATUS "Type combination reports written to: ${COMBINATION_REPORT_DIR}")
else()
message(STATUS "No combinations available yet for diagnostic output")
endif()
endfunction()
function(generate_selective_rendering_reports)
message(STATUS "")
message(STATUS "=== Generating Selective Rendering Reports ===")
# Ensure diagnostics directory exists
set(COMBINATION_REPORT_DIR "${CMAKE_BINARY_DIR}/type_combinations")
file(MAKE_DIRECTORY "${COMBINATION_REPORT_DIR}")
# Check if we have the necessary data
if(NOT DEFINED UNIFIED_COMBINATIONS_2 AND NOT DEFINED UNIFIED_COMBINATIONS_3)
message(WARNING "No type combinations available. Run setup_selective_rendering_unified_safe() first.")
return()
endif()
# Generate all reports
dump_type_combinations_to_disk("${COMBINATION_REPORT_DIR}")
report_selective_rendering_statistics()
# Verify files were created
file(GLOB report_files "${COMBINATION_REPORT_DIR}/*")
list(LENGTH report_files num_files)
if(num_files GREATER 0)
message(STATUS "Successfully generated ${num_files} report files in: ${COMBINATION_REPORT_DIR}")
# List the files
foreach(report_file ${report_files})
get_filename_component(filename "${report_file}" NAME)
message(STATUS " - ${filename}")
endforeach()
else()
message(WARNING "No report files were generated!")
endif()
message(STATUS "===============================================")
message(STATUS "")
endfunction()
function(srcore_map_to_legacy_variables)
if(DEFINED UNIFIED_COMBINATIONS_2)
set(COMBINATIONS_2 "${UNIFIED_COMBINATIONS_2}" PARENT_SCOPE)
set(COMBINATIONS_2 "${UNIFIED_COMBINATIONS_2}" CACHE INTERNAL "Legacy 2-type combinations")
endif()
if(DEFINED UNIFIED_COMBINATIONS_3)
set(COMBINATIONS_3 "${UNIFIED_COMBINATIONS_3}" PARENT_SCOPE)
set(COMBINATIONS_3 "${UNIFIED_COMBINATIONS_3}" CACHE INTERNAL "Legacy 3-type combinations")
endif()
if(DEFINED UNIFIED_ACTIVE_TYPES)
set(ACTIVE_TYPES "${UNIFIED_ACTIVE_TYPES}" PARENT_SCOPE)
set(ACTIVE_TYPES "${UNIFIED_ACTIVE_TYPES}" CACHE INTERNAL "Legacy active types")
list(LENGTH UNIFIED_ACTIVE_TYPES legacy_count)
set(SD_COMMON_TYPES_COUNT ${legacy_count} PARENT_SCOPE)
set(SD_COMMON_TYPES_COUNT ${legacy_count} CACHE INTERNAL "Legacy type count")
set(type_index 0)
foreach(type_name ${UNIFIED_ACTIVE_TYPES})
set(TYPE_NAME_${type_index} "${type_name}" PARENT_SCOPE)
set(TYPE_NAME_${type_index} "${type_name}" CACHE INTERNAL "Legacy reverse type lookup")
math(EXPR type_index "${type_index} + 1")
endforeach()
endif()
endfunction()
function(srcore_generate_diagnostic_report)
if(NOT SD_ENABLE_DIAGNOSTICS)
return()
endif()
set(report_file "${CMAKE_BINARY_DIR}/selective_rendering_diagnostic_report.txt")
set(report_content "")
string(TIMESTAMP current_time "%Y-%m-%d %H:%M:%S")
string(APPEND report_content "SelectiveRenderingCore Diagnostic Report\n")
string(APPEND report_content "Generated: ${current_time}\n")
string(APPEND report_content "========================================\n\n")
string(APPEND report_content "Configuration:\n")
string(APPEND report_content "- SD_ENABLE_SEMANTIC_FILTERING: ${SD_ENABLE_SEMANTIC_FILTERING}\n")
string(APPEND report_content "- SD_TYPE_PROFILE: ${SD_TYPE_PROFILE}\n")
string(APPEND report_content "- SD_SELECTIVE_TYPES: ${SD_SELECTIVE_TYPES}\n")
string(APPEND report_content "\n")
# Active types
if(DEFINED SRCORE_ACTIVE_TYPES)
list(LENGTH SRCORE_ACTIVE_TYPES type_count)
string(APPEND report_content "Active Types (${type_count}):\n")
set(index 0)
foreach(type_name ${SRCORE_ACTIVE_TYPES})
string(APPEND report_content " [${index}] ${type_name}\n")
math(EXPR index "${index} + 1")
endforeach()
string(APPEND report_content "\n")
endif()
# Combination statistics
if(DEFINED SRCORE_COMBINATIONS_2 AND DEFINED SRCORE_COMBINATIONS_3)
list(LENGTH SRCORE_COMBINATIONS_2 count_2)
list(LENGTH SRCORE_COMBINATIONS_3 count_3)
string(APPEND report_content "Combination Statistics:\n")
string(APPEND report_content "- 2-type combinations: ${count_2}\n")
string(APPEND report_content "- 3-type combinations: ${count_3}\n")
if(DEFINED SRCORE_ACTIVE_TYPE_COUNT)
math(EXPR total_possible "${SRCORE_ACTIVE_TYPE_COUNT} * ${SRCORE_ACTIVE_TYPE_COUNT} * ${SRCORE_ACTIVE_TYPE_COUNT}")
if(total_possible GREATER 0)
math(EXPR usage_percent "100 * ${count_3} / ${total_possible}")
math(EXPR savings_percent "100 - ${usage_percent}")
string(APPEND report_content "- Template usage: ${usage_percent}% (${savings_percent}% saved)\n")
endif()
endif()
string(APPEND report_content "\n")
endif()
# Sample combinations with type names
if(DEFINED SRCORE_COMBINATIONS_2)
string(APPEND report_content "Sample 2-type combinations (first 10):\n")
set(sample_count 0)
foreach(combo ${SRCORE_COMBINATIONS_2})
if(sample_count GREATER_EQUAL 10)
break()
endif()
string(REPLACE "," ";" combo_parts "${combo}")
list(GET combo_parts 0 i)
list(GET combo_parts 1 j)
if(DEFINED SRCORE_TYPE_NAME_${i} AND DEFINED SRCORE_TYPE_NAME_${j})
string(APPEND report_content " (${SRCORE_TYPE_NAME_${i}}, ${SRCORE_TYPE_NAME_${j}}) -> (${i},${j})\n")
else()
string(APPEND report_content " (${i},${j})\n")
endif()
math(EXPR sample_count "${sample_count} + 1")
endforeach()
string(APPEND report_content "\n")
endif()
if(DEFINED SRCORE_COMBINATIONS_3)
string(APPEND report_content "Sample 3-type combinations (first 10):\n")
set(sample_count 0)
foreach(combo ${SRCORE_COMBINATIONS_3})
if(sample_count GREATER_EQUAL 10)
break()
endif()
string(REPLACE "," ";" combo_parts "${combo}")
list(GET combo_parts 0 i)
list(GET combo_parts 1 j)
list(GET combo_parts 2 k)
if(DEFINED SRCORE_TYPE_NAME_${i} AND DEFINED SRCORE_TYPE_NAME_${j} AND DEFINED SRCORE_TYPE_NAME_${k})
string(APPEND report_content " (${SRCORE_TYPE_NAME_${i}}, ${SRCORE_TYPE_NAME_${j}}, ${SRCORE_TYPE_NAME_${k}}) -> (${i},${j},${k})\n")
else()
string(APPEND report_content " (${i},${j},${k})\n")
endif()
math(EXPR sample_count "${sample_count} + 1")
endforeach()
string(APPEND report_content "\n")
endif()
# Write validation rules summary
string(APPEND report_content "Validation Rules Applied:\n")
string(APPEND report_content "- Numeric type pairings allowed\n")
string(APPEND report_content "- Bool can pair with any numeric type\n")
string(APPEND report_content "- Float types can pair together\n")
string(APPEND report_content "- Integer types can pair together\n")
string(APPEND report_content "- Specific int-to-float promotions allowed\n")
string(APPEND report_content "- Triple output type must be >= input types (except bool)\n")
string(APPEND report_content "\n")
file(WRITE "${report_file}" "${report_content}")
message(STATUS "Diagnostic report written to: ${report_file}")
endfunction()
# ============================================================================
# OPTIMIZED WRAPPER FUNCTIONS (Production Ready)
# ============================================================================
# Main wrapper for existing code
function(setup_selective_rendering)
setup_selective_rendering_unified_safe()
if(DEFINED UNIFIED_COMBINATIONS_2)
set(COMBINATIONS_2 "${UNIFIED_COMBINATIONS_2}" PARENT_SCOPE)
endif()
if(DEFINED UNIFIED_COMBINATIONS_3)
set(COMBINATIONS_3 "${UNIFIED_COMBINATIONS_3}" PARENT_SCOPE)
endif()
if(DEFINED UNIFIED_ACTIVE_TYPES)
set(ACTIVE_TYPES "${UNIFIED_ACTIVE_TYPES}" PARENT_SCOPE)
endif()
endfunction()
# Legacy wrapper functions (now no-ops for performance)
function(track_combination_states active_types combinations_3)
# Handled internally - no action needed
endfunction()
function(generate_selective_rendering_header)
# Handled internally - no action needed
endfunction()
function(generate_selective_wrapper_header)
# Handled internally - no action needed
endfunction()
function(setup_definitive_semantic_filtering_with_selective_rendering)
set(SD_ENABLE_SEMANTIC_FILTERING TRUE PARENT_SCOPE)
set(SD_ENABLE_SELECTIVE_RENDERING TRUE PARENT_SCOPE)
setup_selective_rendering_unified_safe()
if(DEFINED UNIFIED_COMBINATIONS_2)
set(COMBINATIONS_2 "${UNIFIED_COMBINATIONS_2}" PARENT_SCOPE)
endif()
if(DEFINED UNIFIED_COMBINATIONS_3)
set(COMBINATIONS_3 "${UNIFIED_COMBINATIONS_3}" PARENT_SCOPE)
endif()
endfunction()
function(enhanced_semantic_filtering_setup)
setup_definitive_semantic_filtering_with_selective_rendering()
endfunction()
function(setup_definitive_semantic_filtering)
set(SD_ENABLE_SEMANTIC_FILTERING TRUE PARENT_SCOPE)
setup_selective_rendering_unified_safe(TYPE_PROFILE "${SD_TYPE_PROFILE}")
if(DEFINED UNIFIED_COMBINATIONS_2)
set(COMBINATIONS_2 "${UNIFIED_COMBINATIONS_2}" PARENT_SCOPE)
set(COMBINATIONS_2 "${UNIFIED_COMBINATIONS_2}" CACHE INTERNAL "2-type combinations" FORCE)
endif()
if(DEFINED UNIFIED_COMBINATIONS_3)
set(COMBINATIONS_3 "${UNIFIED_COMBINATIONS_3}" PARENT_SCOPE)
set(COMBINATIONS_3 "${UNIFIED_COMBINATIONS_3}" CACHE INTERNAL "3-type combinations" FORCE)
endif()
if(DEFINED UNIFIED_ACTIVE_TYPES)
set(ACTIVE_TYPES "${UNIFIED_ACTIVE_TYPES}" PARENT_SCOPE)
set(ACTIVE_TYPES "${UNIFIED_ACTIVE_TYPES}" CACHE INTERNAL "Active type list" FORCE)
endif()
endfunction()
function(initialize_definitive_combinations)
setup_definitive_semantic_filtering()
endfunction()
function(extract_definitive_types result_var)
if(DEFINED UNIFIED_ACTIVE_TYPES)
set(${result_var} "${UNIFIED_ACTIVE_TYPES}" PARENT_SCOPE)
else()
srcore_auto_setup()
set(${result_var} "${UNIFIED_ACTIVE_TYPES}" PARENT_SCOPE)
endif()
endfunction()
function(generate_definitive_combinations active_types result_2_var result_3_var)
if(DEFINED UNIFIED_COMBINATIONS_2 AND DEFINED UNIFIED_COMBINATIONS_3)
set(${result_2_var} "${UNIFIED_COMBINATIONS_2}" PARENT_SCOPE)
set(${result_3_var} "${UNIFIED_COMBINATIONS_3}" PARENT_SCOPE)
else()
srcore_auto_setup()
set(${result_2_var} "${UNIFIED_COMBINATIONS_2}" PARENT_SCOPE)
set(${result_3_var} "${UNIFIED_COMBINATIONS_3}" PARENT_SCOPE)
endif()
endfunction()
function(validate_critical_types_coverage active_types combinations_3)
# Handled internally - no action needed
endfunction()
# ============================================================================
# PRODUCTION-OPTIMIZED SEMANTIC ENGINE INTEGRATION
# ============================================================================
# Simplified version without debug overhead
function(setup_enhanced_semantic_validation)
# Core validation logic without debug output
if(SD_ENABLE_SEMANTIC_FILTERING)
if(NOT SD_TYPE_PROFILE OR SD_TYPE_PROFILE STREQUAL "")
if(SD_TYPES_LIST_COUNT GREATER 0)
set(detected_profile "")
if("int8_t" IN_LIST SD_TYPES_LIST AND "uint8_t" IN_LIST SD_TYPES_LIST)
set(detected_profile "quantization")
elseif("float16" IN_LIST SD_TYPES_LIST OR "bfloat16" IN_LIST SD_TYPES_LIST)
set(detected_profile "training")
elseif(SD_TYPES_LIST MATCHES ".*string.*")
set(detected_profile "nlp")
endif()
if(NOT detected_profile STREQUAL "")
set(SD_TYPE_PROFILE "${detected_profile}" PARENT_SCOPE)
else()
set(SD_TYPE_PROFILE "inference" PARENT_SCOPE)
endif()
else()
set(SD_TYPE_PROFILE "inference" PARENT_SCOPE)
endif()
endif()
endif()
endfunction()
# Remove debug function calls to avoid GCC function tracing overhead
macro(print_status_colored level message)
# Only output if diagnostics are explicitly enabled
message(STATUS "${message}")
endmacro()
function(_internal_srcore_generate_helper_macros output_var)
set(helper_content "")
string(APPEND helper_content "#define SD_BUILD_TRIPLE_IF_VALID(t1, t2, t3, build_macro) \\\n")
string(APPEND helper_content " do { \\\n")
string(APPEND helper_content " if (SD_IS_TRIPLE_TYPE_COMPILED(t1, t2, t3)) { \\\n")
string(APPEND helper_content " SD_DISPATCH_TRIPLE_RUNTIME(t1, t2, t3, build_macro); \\\n")
string(APPEND helper_content " } \\\n")
string(APPEND helper_content " } while(0)\n\n")
string(APPEND helper_content "#define SD_BUILD_PAIR_IF_VALID(t1, t2, build_macro) \\\n")
string(APPEND helper_content " do { \\\n")
string(APPEND helper_content " if (SD_IS_PAIR_TYPE_COMPILED(t1, t2)) { \\\n")
string(APPEND helper_content " SD_DISPATCH_PAIR_RUNTIME(t1, t2, build_macro); \\\n")
string(APPEND helper_content " } \\\n")
string(APPEND helper_content " } while(0)\n\n")
string(APPEND helper_content "#define SD_BUILD_SINGLE_IF_VALID(t1, build_macro) \\\n")
string(APPEND helper_content " do { \\\n")
string(APPEND helper_content " if (SD_IS_SINGLE_TYPE_COMPILED(t1)) { \\\n")
string(APPEND helper_content " SD_DISPATCH_SINGLE_RUNTIME(t1, build_macro); \\\n")
string(APPEND helper_content " } \\\n")
string(APPEND helper_content " } while(0)\n\n")
set(${output_var} "${helper_content}" PARENT_SCOPE)
endfunction()
function(srcore_generate_enhanced_header active_indices combinations_2 combinations_3 output_dir type_enums type_cpp_types)
_internal_srcore_generate_validity_header("${active_indices}" "${type_enums}" "${type_cpp_types}" "${combinations_2}" "${combinations_3}" "${output_dir}")
_internal_srcore_append_runtime_dispatch_to_header("${active_indices}" "${type_enums}" "${type_cpp_types}" "${combinations_2}" "${combinations_3}" "${output_dir}")
endfunction()
function(_internal_srcore_append_runtime_dispatch_to_header active_indices type_enums type_cpp_types combinations_2 combinations_3 output_dir)
set(header_file "${output_dir}/system/selective_rendering.h")
_internal_srcore_generate_helper_macros(helper_macros)
if(EXISTS "${header_file}")
file(READ "${header_file}" existing_content)
string(REGEX REPLACE "\n#endif // SD_SELECTIVE_RENDERING_H\n?$" "" content_without_endif "${existing_content}")
set(new_content "${content_without_endif}")
string(APPEND new_content "\n${dispatch_macros}")
string(APPEND new_content "${helper_macros}")
string(APPEND new_content "#endif // SD_SELECTIVE_RENDERING_H\n")
file(WRITE "${header_file}" "${new_content}")
list(LENGTH combinations_3 total_triple_combinations)
list(LENGTH combinations_2 total_pair_combinations)
message(STATUS "Enhanced selective_rendering.h with runtime dispatch - ${total_pair_combinations} pair dispatches, ${total_triple_combinations} triple dispatches")
else()
message(FATAL_ERROR "Cannot append runtime dispatch - header file does not exist: ${header_file}")
endif()
endfunction()
# ADD this new function to automatically create diagnostics during setup
function(_internal_ensure_diagnostics_output)
# Always create the diagnostics output directory
set(COMBINATION_REPORT_DIR "${CMAKE_BINARY_DIR}/type_combinations")
file(MAKE_DIRECTORY "${COMBINATION_REPORT_DIR}")
# Set as cache variable for other functions to use
set(SD_DIAGNOSTICS_DIR "${COMBINATION_REPORT_DIR}" CACHE INTERNAL "Type combinations diagnostics directory")
# Create a timestamp file to mark when the directory was created
string(TIMESTAMP creation_time "%Y-%m-%d %H:%M:%S")
file(WRITE "${COMBINATION_REPORT_DIR}/.created" "Directory created: ${creation_time}\n")
# Automatically dump combinations if they exist
if(DEFINED UNIFIED_COMBINATIONS_2 OR DEFINED UNIFIED_COMBINATIONS_3)
# Silently dump combinations to disk without console output
_internal_quiet_dump_combinations("${COMBINATION_REPORT_DIR}")
endif()
endfunction()
function(check_diagnostics_status)
if(EXISTS "${CMAKE_BINARY_DIR}/type_combinations")
file(GLOB diagnostic_files "${CMAKE_BINARY_DIR}/type_combinations/*")
list(LENGTH diagnostic_files num_files)
if(num_files GREATER 0)
message(STATUS "Type combination diagnostics available: ${CMAKE_BINARY_DIR}/type_combinations (${num_files} files)")
return()
endif()
endif()
message(STATUS "Type combination diagnostics not yet generated")
endfunction()
function(srcore_enable_runtime_dispatch)
set(SD_ENABLE_RUNTIME_DISPATCH TRUE PARENT_SCOPE)
set(SD_ENABLE_RUNTIME_DISPATCH TRUE CACHE BOOL "Enable runtime dispatch macro generation")
message(STATUS "Runtime dispatch enabled - will generate SD_DISPATCH_*_RUNTIME macros")
endfunction()