@@ -94,6 +94,8 @@ pub struct Linearizer<'a> {
9494 current_func_name : String ,
9595 /// Counter for generating unique static local names
9696 static_local_counter : u32 ,
97+ /// Counter for generating unique compound literal names (for file-scope compound literals)
98+ compound_literal_counter : u32 ,
9799 /// Static local variables (local name -> static local info)
98100 /// This is persistent across function calls (not cleared per function)
99101 static_locals : HashMap < String , StaticLocalInfo > ,
@@ -135,6 +137,7 @@ impl<'a> Linearizer<'a> {
135137 struct_return_size : 0 ,
136138 current_func_name : String :: new ( ) ,
137139 static_local_counter : 0 ,
140+ compound_literal_counter : 0 ,
138141 static_locals : HashMap :: new ( ) ,
139142 current_pos : None ,
140143 target,
@@ -518,7 +521,8 @@ impl<'a> Linearizer<'a> {
518521 /// - Struct initializers with designated and positional fields
519522 /// - Address-of expressions (&symbol)
520523 /// - Nested initializers
521- fn ast_init_to_ir ( & self , expr : & Expr , typ : TypeId ) -> Initializer {
524+ /// - Compound literals (C99 6.5.2.5)
525+ fn ast_init_to_ir ( & mut self , expr : & Expr , typ : TypeId ) -> Initializer {
522526 match & expr. kind {
523527 ExprKind :: IntLit ( v) => Initializer :: Int ( * v) ,
524528 ExprKind :: FloatLit ( v) => Initializer :: Float ( * v) ,
@@ -573,6 +577,33 @@ impl<'a> Linearizer<'a> {
573577 // Initializer list for arrays/structs
574578 ExprKind :: InitList { elements } => self . ast_init_list_to_ir ( elements, typ) ,
575579
580+ // Compound literal in initializer context (C99 6.5.2.5)
581+ ExprKind :: CompoundLiteral {
582+ typ : cl_type,
583+ elements,
584+ } => {
585+ // Check if compound literal type matches target type
586+ if * cl_type == typ {
587+ // Direct value - treat like InitList
588+ self . ast_init_list_to_ir ( elements, typ)
589+ } else if self . types . kind ( typ) == TypeKind :: Pointer {
590+ // Pointer initialization - create anonymous static global
591+ // and return its address
592+ let anon_name = format ! ( ".CL{}" , self . compound_literal_counter) ;
593+ self . compound_literal_counter += 1 ;
594+
595+ // Create the anonymous global
596+ let init = self . ast_init_list_to_ir ( elements, * cl_type) ;
597+ self . module . add_global ( & anon_name, * cl_type, init) ;
598+
599+ // Return address of the anonymous global
600+ Initializer :: SymAddr ( anon_name)
601+ } else {
602+ // Type mismatch - try to use the initializer list directly
603+ self . ast_init_list_to_ir ( elements, typ)
604+ }
605+ }
606+
576607 // Identifier - for constant addresses (function pointers, array decay, etc.)
577608 // or enum constants
578609 ExprKind :: Ident { name } => {
@@ -603,7 +634,7 @@ impl<'a> Linearizer<'a> {
603634 }
604635
605636 /// Convert an AST initializer list to an IR Initializer
606- fn ast_init_list_to_ir ( & self , elements : & [ InitElement ] , typ : TypeId ) -> Initializer {
637+ fn ast_init_list_to_ir ( & mut self , elements : & [ InitElement ] , typ : TypeId ) -> Initializer {
607638 let type_kind = self . types . kind ( typ) ;
608639 let total_size = ( self . types . size_bits ( typ) / 8 ) as usize ;
609640
@@ -2147,6 +2178,28 @@ impl<'a> Linearizer<'a> {
21472178 ) ) ;
21482179 addr
21492180 }
2181+ ExprKind :: CompoundLiteral { typ, elements } => {
2182+ // Compound literal as lvalue: create it and return its address
2183+ // This is used for &(struct S){...}
2184+ let sym_id = self . alloc_pseudo ( ) ;
2185+ let unique_name = format ! ( ".compound_literal#{}" , sym_id. 0 ) ;
2186+ let sym = Pseudo :: sym ( sym_id, unique_name. clone ( ) ) ;
2187+ if let Some ( func) = & mut self . current_func {
2188+ func. add_pseudo ( sym) ;
2189+ func. add_local ( & unique_name, sym_id, * typ, false , self . current_bb ) ;
2190+ }
2191+ self . linearize_init_list ( sym_id, * typ, elements) ;
2192+
2193+ // Return address of the compound literal
2194+ let result = self . alloc_pseudo ( ) ;
2195+ let pseudo = Pseudo :: reg ( result, result. 0 ) ;
2196+ if let Some ( func) = & mut self . current_func {
2197+ func. add_pseudo ( pseudo) ;
2198+ }
2199+ let ptr_type = self . types . pointer_to ( * typ) ;
2200+ self . emit ( Instruction :: sym_addr ( result, sym_id, ptr_type) ) ;
2201+ result
2202+ }
21502203 _ => {
21512204 // Fallback: just evaluate the expression (shouldn't happen for valid lvalues)
21522205 self . linearize_expr ( expr)
@@ -3249,6 +3302,44 @@ impl<'a> Linearizer<'a> {
32493302 panic ! ( "InitList should be handled in declaration context, not as standalone expression" )
32503303 }
32513304
3305+ ExprKind :: CompoundLiteral { typ, elements } => {
3306+ // Compound literals have automatic storage at block scope
3307+ // Create an anonymous local variable, similar to how local variables work
3308+
3309+ // Create a symbol pseudo for the compound literal (its address)
3310+ let sym_id = self . alloc_pseudo ( ) ;
3311+ let unique_name = format ! ( ".compound_literal#{}" , sym_id. 0 ) ;
3312+ let sym = Pseudo :: sym ( sym_id, unique_name. clone ( ) ) ;
3313+ if let Some ( func) = & mut self . current_func {
3314+ func. add_pseudo ( sym) ;
3315+ // Register as local for proper stack allocation
3316+ func. add_local ( & unique_name, sym_id, * typ, false , self . current_bb ) ;
3317+ }
3318+
3319+ // Initialize using existing init list machinery
3320+ self . linearize_init_list ( sym_id, * typ, elements) ;
3321+
3322+ // For arrays: return pointer (array-to-pointer decay)
3323+ // For structs/scalars: load and return the value
3324+ let result = self . alloc_pseudo ( ) ;
3325+ let pseudo = Pseudo :: reg ( result, result. 0 ) ;
3326+ if let Some ( func) = & mut self . current_func {
3327+ func. add_pseudo ( pseudo) ;
3328+ }
3329+
3330+ if self . types . kind ( * typ) == TypeKind :: Array {
3331+ // Array compound literal - decay to pointer to first element
3332+ let elem_type = self . types . base_type ( * typ) . unwrap_or ( self . types . int_id ) ;
3333+ let ptr_type = self . types . pointer_to ( elem_type) ;
3334+ self . emit ( Instruction :: sym_addr ( result, sym_id, ptr_type) ) ;
3335+ } else {
3336+ // Struct/scalar compound literal - load the value
3337+ let size = self . types . size_bits ( * typ) ;
3338+ self . emit ( Instruction :: load ( result, sym_id, 0 , * typ, size) ) ;
3339+ }
3340+ result
3341+ }
3342+
32523343 // ================================================================
32533344 // Variadic function support (va_* builtins)
32543345 // ================================================================
0 commit comments