2990 lines
129 KiB
CMake
2990 lines
129 KiB
CMake
# ============================================================================
|
||
#
|
||
# 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()
|