@@ -23,6 +23,11 @@ use crate::symbol::SymbolTable;
2323use crate :: types:: { MemberInfo , Type , TypeKind , TypeModifiers } ;
2424use std:: collections:: HashMap ;
2525
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+
2631/// Information about a local variable
2732#[ derive( Clone ) ]
2833struct LocalVarInfo {
@@ -490,12 +495,12 @@ impl<'a> Linearizer<'a> {
490495 let mut ir_func = Function :: new ( & func. name , func. return_type . clone ( ) ) ;
491496 ir_func. is_static = is_static;
492497
493- // Check if function returns a large struct (> 8 bytes)
494- // According to System V AMD64 ABI, large structs are returned via a hidden
495- // first parameter that points to caller-allocated space
498+ // Check if function returns a large struct
499+ // Large structs are returned via a hidden first parameter (sret)
500+ // that points to caller-allocated space
496501 let returns_large_struct = ( func. return_type . kind == TypeKind :: Struct
497502 || func. return_type . kind == TypeKind :: Union )
498- && func. return_type . size_bits ( ) > 64 ;
503+ && func. return_type . size_bits ( ) > MAX_REGISTER_AGGREGATE_BITS ;
499504
500505 // Argument index offset: if returning large struct, first arg is hidden return pointer
501506 let arg_offset: u32 = if returns_large_struct { 1 } else { 0 } ;
@@ -551,9 +556,9 @@ impl<'a> Linearizer<'a> {
551556 func. add_local ( & name, local_sym, typ. clone ( ) , is_volatile, None ) ;
552557 }
553558
554- // For large structs (> 8 bytes) , arg_pseudo is a pointer to the struct
559+ // For large structs, arg_pseudo is a pointer to the struct
555560 // We need to copy the data from that pointer to local storage
556- if typ. size_bits ( ) > 64 {
561+ if typ. size_bits ( ) > MAX_REGISTER_AGGREGATE_BITS {
557562 // arg_pseudo is a pointer - copy each 8-byte chunk
558563 let struct_size = typ. size_bits ( ) / 8 ;
559564 let mut offset = 0i64 ;
@@ -2231,11 +2236,11 @@ impl<'a> Linearizer<'a> {
22312236 None // No type info, assume non-variadic
22322237 } ;
22332238
2234- // Check if function returns a large struct (> 8 bytes)
2239+ // Check if function returns a large struct
22352240 // If so, allocate space and pass address as hidden first argument
22362241 let returns_large_struct = ( typ. kind == TypeKind :: Struct
22372242 || typ. kind == TypeKind :: Union )
2238- && typ. size_bits ( ) > 64 ;
2243+ && typ. size_bits ( ) > MAX_REGISTER_AGGREGATE_BITS ;
22392244
22402245 let ( result_sym, mut arg_vals, mut arg_types_vec) = if returns_large_struct {
22412246 // Allocate local storage for the return value
@@ -2273,12 +2278,12 @@ impl<'a> Linearizer<'a> {
22732278 } ;
22742279
22752280 // Linearize regular arguments
2276- // For structs > 8 bytes , pass by reference (address) instead of by value
2281+ // For large structs , pass by reference (address) instead of by value
22772282 for a in args. iter ( ) {
22782283 let arg_type = self . expr_type ( a) ;
22792284 let arg_val = if ( arg_type. kind == TypeKind :: Struct
22802285 || arg_type. kind == TypeKind :: Union )
2281- && arg_type. size_bits ( ) > 64
2286+ && arg_type. size_bits ( ) > MAX_REGISTER_AGGREGATE_BITS
22822287 {
22832288 // Large struct: pass address instead of value
22842289 // The argument type becomes a pointer
0 commit comments