Skip to content

Commit b185a33

Browse files
committed
[cc] linearize: clean up magic numbers
1 parent baf46d2 commit b185a33

File tree

2 files changed

+19
-14
lines changed

2 files changed

+19
-14
lines changed

cc/arch/aarch64/codegen.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use crate::arch::aarch64::lir::{Aarch64Inst, CallTarget, Cond, GpOperand, MemAdd
2121
use crate::arch::codegen::CodeGenerator;
2222
use crate::arch::lir::{Directive, FpSize, Label, OperandSize, Symbol};
2323
use crate::ir::{Function, Initializer, Instruction, Module, Opcode, Pseudo, PseudoId, PseudoKind};
24+
use crate::linearize::MAX_REGISTER_AGGREGATE_BITS;
2425
use crate::target::Target;
2526
use crate::types::{Type, TypeModifiers};
2627
use std::collections::HashMap;
@@ -2928,12 +2929,11 @@ impl Aarch64CodeGen {
29282929
let mut fp_arg_idx = 0;
29292930
let mut stack_args = 0;
29302931

2931-
// Check if this call returns a large struct (> 8 bytes)
2932+
// Check if this call returns a large struct
29322933
// If so, the first argument is the sret pointer and goes in X8 (not X0)
2933-
// Note: Must match linearizer threshold of > 64 bits
29342934
let returns_large_struct = insn.typ.as_ref().is_some_and(|t| {
29352935
(t.kind == crate::types::TypeKind::Struct || t.kind == crate::types::TypeKind::Union)
2936-
&& t.size_bits() > 64
2936+
&& t.size_bits() > MAX_REGISTER_AGGREGATE_BITS
29372937
});
29382938

29392939
// Also check if return type is a pointer to a large struct (linearizer wraps it)
@@ -2942,7 +2942,7 @@ impl Aarch64CodeGen {
29422942
if let Some(pointee) = t.get_base() {
29432943
(pointee.kind == crate::types::TypeKind::Struct
29442944
|| pointee.kind == crate::types::TypeKind::Union)
2945-
&& pointee.size_bits() > 64
2945+
&& pointee.size_bits() > MAX_REGISTER_AGGREGATE_BITS
29462946
} else {
29472947
false
29482948
}

cc/linearize.rs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ use crate::symbol::SymbolTable;
2323
use crate::types::{MemberInfo, Type, TypeKind, TypeModifiers};
2424
use 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)]
2833
struct 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

Comments
 (0)