@@ -20,14 +20,10 @@ use crate::parse::ast::{
2020} ;
2121use crate :: ssa:: ssa_convert;
2222use crate :: symbol:: SymbolTable ;
23+ use crate :: target:: Target ;
2324use crate :: types:: { MemberInfo , TypeId , TypeKind , TypeModifiers , TypeTable } ;
2425use std:: collections:: HashMap ;
2526
26- /// Maximum size (in bits) for aggregate types (struct/union) to be passed or
27- /// returned by value in registers. Aggregates larger than this require
28- /// indirect passing (pointer) or sret (struct return pointer).
29- pub const MAX_REGISTER_AGGREGATE_BITS : u32 = 64 ;
30-
3127/// Information about a local variable
3228#[ derive( Clone ) ]
3329struct LocalVarInfo {
@@ -91,11 +87,13 @@ pub struct Linearizer<'a> {
9187 static_locals : HashMap < String , StaticLocalInfo > ,
9288 /// Current source position for debug info
9389 current_pos : Option < Position > ,
90+ /// Target configuration (architecture, ABI details)
91+ target : & ' a Target ,
9492}
9593
9694impl < ' a > Linearizer < ' a > {
9795 /// Create a new linearizer
98- pub fn new ( symbols : & ' a SymbolTable , types : & ' a TypeTable ) -> Self {
96+ pub fn new ( symbols : & ' a SymbolTable , types : & ' a TypeTable , target : & ' a Target ) -> Self {
9997 Self {
10098 module : Module :: new ( ) ,
10199 current_func : None ,
@@ -116,15 +114,16 @@ impl<'a> Linearizer<'a> {
116114 static_local_counter : 0 ,
117115 static_locals : HashMap :: new ( ) ,
118116 current_pos : None ,
117+ target,
119118 }
120119 }
121120
122121 /// Create a linearizer with SSA conversion disabled (for testing)
123122 #[ cfg( test) ]
124- pub fn new_no_ssa ( symbols : & ' a SymbolTable , types : & ' a TypeTable ) -> Self {
123+ pub fn new_no_ssa ( symbols : & ' a SymbolTable , types : & ' a TypeTable , target : & ' a Target ) -> Self {
125124 Self {
126125 run_ssa : false ,
127- ..Self :: new ( symbols, types)
126+ ..Self :: new ( symbols, types, target )
128127 }
129128 }
130129
@@ -510,7 +509,7 @@ impl<'a> Linearizer<'a> {
510509 // Large structs are returned via a hidden first parameter (sret)
511510 // that points to caller-allocated space
512511 let returns_large_struct = ( ret_kind == TypeKind :: Struct || ret_kind == TypeKind :: Union )
513- && self . types . size_bits ( func. return_type ) > MAX_REGISTER_AGGREGATE_BITS ;
512+ && self . types . size_bits ( func. return_type ) > self . target . max_aggregate_register_bits ;
514513
515514 // Argument index offset: if returning large struct, first arg is hidden return pointer
516515 let arg_offset: u32 = if returns_large_struct { 1 } else { 0 } ;
@@ -570,7 +569,7 @@ impl<'a> Linearizer<'a> {
570569 let typ_size = self . types . size_bits ( typ) ;
571570 // For large structs, arg_pseudo is a pointer to the struct
572571 // We need to copy the data from that pointer to local storage
573- if typ_size > MAX_REGISTER_AGGREGATE_BITS {
572+ if typ_size > self . target . max_aggregate_register_bits {
574573 // arg_pseudo is a pointer - copy each 8-byte chunk
575574 let struct_size = typ_size / 8 ;
576575 let mut offset = 0i64 ;
@@ -2239,7 +2238,7 @@ impl<'a> Linearizer<'a> {
22392238 let typ_kind = self . types . kind ( typ) ;
22402239 let returns_large_struct = ( typ_kind == TypeKind :: Struct
22412240 || typ_kind == TypeKind :: Union )
2242- && self . types . size_bits ( typ) > MAX_REGISTER_AGGREGATE_BITS ;
2241+ && self . types . size_bits ( typ) > self . target . max_aggregate_register_bits ;
22432242
22442243 let ( result_sym, mut arg_vals, mut arg_types_vec) = if returns_large_struct {
22452244 // Allocate local storage for the return value
@@ -2282,7 +2281,7 @@ impl<'a> Linearizer<'a> {
22822281 let arg_type = self . expr_type ( a) ;
22832282 let arg_kind = self . types . kind ( arg_type) ;
22842283 let arg_val = if ( arg_kind == TypeKind :: Struct || arg_kind == TypeKind :: Union )
2285- && self . types . size_bits ( arg_type) > MAX_REGISTER_AGGREGATE_BITS
2284+ && self . types . size_bits ( arg_type) > self . target . max_aggregate_register_bits
22862285 {
22872286 // Large struct: pass address instead of value
22882287 // The argument type becomes a pointer
@@ -2313,6 +2312,7 @@ impl<'a> Linearizer<'a> {
23132312 64 , // pointers are 64-bit
23142313 ) ;
23152314 call_insn. variadic_arg_start = variadic_arg_start;
2315+ call_insn. is_sret_call = true ;
23162316 self . emit ( call_insn) ;
23172317 // Return the symbol (address) where struct is stored
23182318 result_sym
@@ -3688,19 +3688,25 @@ impl<'a> Linearizer<'a> {
36883688
36893689/// Linearize an AST to IR (convenience wrapper for tests)
36903690#[ cfg( test) ]
3691- pub fn linearize ( tu : & TranslationUnit , symbols : & SymbolTable , types : & TypeTable ) -> Module {
3692- linearize_with_debug ( tu, symbols, types, false , None )
3691+ pub fn linearize (
3692+ tu : & TranslationUnit ,
3693+ symbols : & SymbolTable ,
3694+ types : & TypeTable ,
3695+ target : & Target ,
3696+ ) -> Module {
3697+ linearize_with_debug ( tu, symbols, types, target, false , None )
36933698}
36943699
36953700/// Linearize an AST to IR with debug info support
36963701pub fn linearize_with_debug (
36973702 tu : & TranslationUnit ,
36983703 symbols : & SymbolTable ,
36993704 types : & TypeTable ,
3705+ target : & Target ,
37003706 debug : bool ,
37013707 source_file : Option < & str > ,
37023708) -> Module {
3703- let mut linearizer = Linearizer :: new ( symbols, types) ;
3709+ let mut linearizer = Linearizer :: new ( symbols, types, target ) ;
37043710 let mut module = linearizer. linearize ( tu) ;
37053711 module. debug = debug;
37063712 if let Some ( path) = source_file {
@@ -3732,7 +3738,8 @@ mod tests {
37323738
37333739 fn test_linearize ( tu : & TranslationUnit , types : & TypeTable ) -> Module {
37343740 let symbols = SymbolTable :: new ( ) ;
3735- linearize ( tu, & symbols, types)
3741+ let target = Target :: host ( ) ;
3742+ linearize ( tu, & symbols, types, & target)
37363743 }
37373744
37383745 fn make_simple_func ( name : & str , body : Stmt , types : & TypeTable ) -> FunctionDef {
@@ -4017,7 +4024,8 @@ mod tests {
40174024
40184025 // Create linearizer and test that expr_type reads from the expression
40194026 let symbols = SymbolTable :: new ( ) ;
4020- let linearizer = Linearizer :: new ( & symbols, & types) ;
4027+ let target = Target :: host ( ) ;
4028+ let linearizer = Linearizer :: new ( & symbols, & types, & target) ;
40214029 let typ = linearizer. expr_type ( & expr) ;
40224030 assert_eq ! ( types. kind( typ) , TypeKind :: Int ) ;
40234031
@@ -4037,7 +4045,8 @@ mod tests {
40374045 expr. typ = Some ( types. double_id ) ;
40384046
40394047 let symbols = SymbolTable :: new ( ) ;
4040- let linearizer = Linearizer :: new ( & symbols, & types) ;
4048+ let target = Target :: host ( ) ;
4049+ let linearizer = Linearizer :: new ( & symbols, & types, & target) ;
40414050 let typ = linearizer. expr_type ( & expr) ;
40424051 assert_eq ! ( types. kind( typ) , TypeKind :: Double ) ;
40434052 }
@@ -4049,7 +4058,8 @@ mod tests {
40494058 /// Helper to linearize without SSA conversion (for comparing before/after)
40504059 fn linearize_no_ssa ( tu : & TranslationUnit , types : & TypeTable ) -> Module {
40514060 let symbols = SymbolTable :: new ( ) ;
4052- let mut linearizer = Linearizer :: new_no_ssa ( & symbols, types) ;
4061+ let target = Target :: host ( ) ;
4062+ let mut linearizer = Linearizer :: new_no_ssa ( & symbols, types, & target) ;
40534063 linearizer. linearize ( tu)
40544064 }
40554065
0 commit comments