22#
33# Core types (CGVal, CGCtx) and helper functions for Tile IR code generation.
44
5+ #= ============================================================================
6+ Type-safe shape wrappers: Julia (column-major) ↔ Tile IR (row-major)
7+ =============================================================================#
8+
9+ # Tile IR is natively row-major: shapes are stored with the slowest-varying dimension first.
10+ # Julia is column-major: shapes are stored with the fastest-varying dimension first.
11+ # Converting between them is a simple reversal. The Shape{O} wrapper ensures we don't
12+ # accidentally mix up conventions — IR operations accept only RowMajorShape, while
13+ # user-facing shapes from Julia are ColMajorShape.
14+
15+ abstract type StorageOrder end
16+ struct RowMajor <: StorageOrder end
17+ struct ColMajor <: StorageOrder end
18+
19+ struct Shape{O<: StorageOrder }
20+ dims:: Vector{Int}
21+ end
22+
23+ const RowMajorShape = Shape{RowMajor}
24+ const ColMajorShape = Shape{ColMajor}
25+
26+ # Conversion constructors
27+ RowMajorShape (s:: RowMajorShape ) = s
28+ RowMajorShape (s:: ColMajorShape ) = RowMajorShape (reverse (s. dims))
29+ RowMajorShape (t:: Tuple ) = RowMajorShape (ColMajorShape (collect (Int, t)))
30+
31+ ColMajorShape (s:: ColMajorShape ) = s
32+ ColMajorShape (s:: RowMajorShape ) = ColMajorShape (reverse (s. dims))
33+ ColMajorShape (t:: Tuple ) = ColMajorShape (collect (Int, t))
34+
35+ # Forward common operations to .dims
36+ Base. length (s:: Shape ) = length (s. dims)
37+ Base. isempty (s:: Shape ) = isempty (s. dims)
38+ Base. getindex (s:: Shape , i) = s. dims[i]
39+ Base. setindex! (s:: Shape , v, i) = (s. dims[i] = v; s)
40+ Base. copy (s:: Shape{O} ) where O = Shape {O} (copy (s. dims))
41+ Base.:(== )(a:: Shape{O} , b:: Shape{O} ) where O = a. dims == b. dims
42+ Base. iterate (s:: Shape , state... ) = iterate (s. dims, state... )
43+ Base. eachindex (s:: Shape ) = eachindex (s. dims)
44+ Base. collect (s:: Shape ) = s. dims
45+ TupleType (s:: Shape ) = Tuple{s. dims... }
46+
47+ # Scalar (0-D) shape — storage order is irrelevant for zero dimensions
48+ struct ScalarShape end
49+ Base. length (:: ScalarShape ) = 0
50+ Base. isempty (:: ScalarShape ) = true
51+ Base. collect (:: ScalarShape ) = Int[]
52+ TupleType (:: ScalarShape ) = Tuple{}
53+
54+ Base.:(== )(:: ScalarShape , :: ScalarShape ) = true
55+ Base.:(== )(:: ScalarShape , :: Shape ) = false
56+ Base.:(== )(:: Shape , :: ScalarShape ) = false
57+
58+ # Cross-type conversions (must be after ScalarShape definition)
59+ ColMajorShape (:: ScalarShape ) = ColMajorShape (Int[])
60+
61+ const TileShape = Union{RowMajorShape, ScalarShape}
62+
563#= ============================================================================
664 IRError: Exception type for IR compilation errors
765=============================================================================#
@@ -69,7 +127,7 @@ struct CGVal
69127 v:: Union{Value, Vector{Value}, Nothing} # Single value, multi-value, or nothing
70128 type_id:: Union{TypeId, Nothing} # Tile IR type (nothing for lazy refs or multi-value)
71129 jltype:: Any # Original Julia type
72- shape:: Vector{Int} # Tile shape (empty for scalars)
130+ shape:: TileShape # Tile shape (ScalarShape for scalars)
73131 # Lazy argument reference: (arg_idx, [field_indices...])
74132 # e.g., (1, [2, 1]) means "argument 1, field 2, sub-field 1"
75133 arg_ref:: Union{Tuple{Int, Vector{Int}}, Nothing}
79137
80138# Convenience constructors for concrete values
81139CGVal (v:: Value , type_id:: TypeId , @nospecialize (jltype)) =
82- CGVal (v, type_id, jltype, Int[] , nothing , nothing , nothing )
140+ CGVal (v, type_id, jltype, ScalarShape () , nothing , nothing , nothing )
83141
84- CGVal (v:: Value , type_id:: TypeId , @nospecialize (jltype), shape:: Vector{Int} ) =
142+ CGVal (v:: Value , type_id:: TypeId , @nospecialize (jltype), shape:: TileShape ) =
85143 CGVal (v, type_id, jltype, shape, nothing , nothing , nothing )
86144
87145# Constructor for multi-value results (from loops, ifs)
88146CGVal (v:: Vector{Value} , @nospecialize (jltype)) =
89- CGVal (v, nothing , jltype, Int[] , nothing , nothing , nothing )
147+ CGVal (v, nothing , jltype, ScalarShape () , nothing , nothing , nothing )
90148
91149# Constructor for lazy argument references
92150function arg_ref_value (arg_idx:: Int , chain:: Vector{Int} , @nospecialize (jltype))
93- CGVal (nothing , nothing , jltype, Int[] , (arg_idx, chain), nothing , nothing )
151+ CGVal (nothing , nothing , jltype, ScalarShape () , (arg_idx, chain), nothing , nothing )
94152end
95153
96154"""
99157Create a ghost value (zero-size singleton with no runtime representation).
100158Optionally stores a compile-time constant value.
101159"""
102- ghost_value (@nospecialize (jltype)) = CGVal (nothing , TypeId (- 1 ), jltype, Int[] , nothing , nothing , nothing )
103- ghost_value (@nospecialize (jltype), constant) = CGVal (nothing , TypeId (- 1 ), jltype, Int[] , nothing , Some (constant), nothing )
160+ ghost_value (@nospecialize (jltype)) = CGVal (nothing , TypeId (- 1 ), jltype, ScalarShape () , nothing , nothing , nothing )
161+ ghost_value (@nospecialize (jltype), constant) = CGVal (nothing , TypeId (- 1 ), jltype, ScalarShape () , nothing , Some (constant), nothing )
104162
105163"""
106164 tuple_value(jltype, component_refs, component_constants) -> CGVal
@@ -115,7 +173,7 @@ function tuple_value(@nospecialize(jltype), component_refs::Vector{Any}, compone
115173 else
116174 nothing
117175 end
118- CGVal (nothing , TypeId (- 1 ), jltype, Int[] , nothing , constant, component_refs)
176+ CGVal (nothing , TypeId (- 1 ), jltype, ScalarShape () , nothing , constant, component_refs)
119177end
120178
121179"""
@@ -382,27 +440,27 @@ function _tile_type_for_julia!(tt::TypeTable, @nospecialize(T::Type))
382440 throw (IRError (" Tile shape must be a tuple, got: $shape_param " ))
383441 end
384442 elem_dtype = julia_to_tile_dtype! (tt, eltype (T))
385- shape = collect (Int, shape_param)
386- return tile_type! (tt, elem_dtype, shape)
443+ shape = RowMajorShape ( shape_param)
444+ return tile_type! (tt, elem_dtype, collect ( shape) )
387445 end
388446
389447 return nothing
390448end
391449
392450"""
393- tile_type_and_shape_for_julia!(ctx, T) -> (TypeId, Vector{Int} )
451+ tile_type_and_shape_for_julia!(ctx, T) -> (TypeId, RowMajorShape )
394452
395453Get the Tile IR type and shape for a Julia type.
396454"""
397455function tile_type_and_shape_for_julia! (ctx:: CGCtx , @nospecialize (T))
398456 actual_type = CC. widenconst (T)
399457 type_id = tile_type_for_julia! (ctx, actual_type)
400458
401- # Extract shape from Tile types
459+ # Extract shape from Tile types (in Tile IR row-major order)
402460 shape = if actual_type <: Tile
403- collect (Int, size (actual_type))
461+ RowMajorShape ( size (actual_type))
404462 else
405- Int[]
463+ ScalarShape ()
406464 end
407465
408466 return (type_id, shape)
@@ -489,14 +547,15 @@ end
489547# -----------------------------------------------------------------------------
490548
491549"""
492- extract_tile_shape(T) -> Vector{Int}
550+ extract_tile_shape(T) -> RowMajorShape
493551
494- Extract shape from a Tile{T, Shape} type, returning Int[] if not a Tile type.
552+ Extract shape from a Tile{T, Shape} type in Tile IR (row-major) order.
553+ Returns empty shape if not a Tile type.
495554"""
496555function extract_tile_shape (@nospecialize (T))
497556 T = CC. widenconst (T)
498557 if T <: Tile
499- return collect (Int, size (T))
558+ return RowMajorShape ( size (T))
500559 end
501- Int[]
560+ ScalarShape ()
502561end
0 commit comments