项目文件夹

文件
2026-07-13 12:47:05 +08:00

2990 行
129 KiB
CMake

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
# ============================================================================
#
# 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()