@@ -9,7 +9,7 @@ use rustc_codegen_ssa::traits::{
99use rustc_middle:: ty:: Ty ;
1010use rustc_middle:: ty:: layout:: { HasTyCtxt , LayoutOf , TyAndLayout } ;
1111use rustc_span:: bug;
12- use rustc_target:: spec:: { Arch , Env , LlvmAbi , RustcAbi } ;
12+ use rustc_target:: spec:: { Arch , Env , LlvmAbi , RustcAbi , Target } ;
1313
1414use crate :: builder:: Builder ;
1515use crate :: llvm:: Value ;
@@ -97,7 +97,13 @@ fn get_param_type_alignment<'ll, 'tcx>(
9797 Primitive :: Float ( float) => match float {
9898 Float :: F16 | Float :: F16B | Float :: F32 => unreachable ! ( ) ,
9999 Float :: F64 | Float :: F128 => { /* fall through */ }
100- Float :: PpcF128 => return Align :: EIGHT ,
100+ Float :: PpcF128 => {
101+ return if is_powerpc_softfloat_abi ( & bx. cx . tcx . sess . target ) {
102+ Align :: FOUR
103+ } else {
104+ Align :: EIGHT
105+ } ;
106+ }
101107 } ,
102108 Primitive :: Pointer ( _) => { /* fall through */ }
103109 } ,
@@ -222,7 +228,7 @@ fn emit_aapcs_va_arg<'ll, 'tcx>(
222228 let on_stack = bx. append_sibling_block ( "va_arg.on_stack" ) ;
223229 let end = bx. append_sibling_block ( "va_arg.end" ) ;
224230 let zero = bx. const_i32 ( 0 ) ;
225- let offset_align = Align :: from_bytes ( 4 ) . unwrap ( ) ;
231+ let offset_align = Align :: FOUR ;
226232
227233 let gr_type = layout. ty . is_any_ptr ( ) || layout. ty . is_integral ( ) ;
228234 let ( reg_off, reg_top, slot_size) = if gr_type {
@@ -291,6 +297,19 @@ fn emit_aapcs_va_arg<'ll, 'tcx>(
291297 val
292298}
293299
300+ fn is_powerpc_softfloat_abi ( target : & Target ) -> bool {
301+ if target. arch != Arch :: PowerPC {
302+ return false ;
303+ }
304+
305+ match target. rustc_abi {
306+ Some ( RustcAbi :: Softfloat ) => bug ! ( "there are currently no powerpc softfloat targets" ) ,
307+ Some ( RustcAbi :: PowerPcSpe ) => true , // SPE is like softfloat in terms of ABI
308+ None => false ,
309+ Some ( other) => bug ! ( "unexpected powerpc abi {other:?}" ) ,
310+ }
311+ }
312+
294313fn emit_powerpc_va_arg < ' ll , ' tcx > (
295314 bx : & mut Builder < ' _ , ' ll , ' tcx > ,
296315 list : OperandRef < ' tcx , & ' ll Value > ,
@@ -310,26 +329,19 @@ fn emit_powerpc_va_arg<'ll, 'tcx>(
310329 // Peel off any newtype wrappers.
311330 let layout = layout. peel_transparent_wrappers_from_non_1zst ( bx. cx ) ;
312331
313- // Rust does not currently support any powerpc softfloat targets.
314- // FIXME: however, the SPE targets are softfloat-like, and the current
315- // implementation doesn't handle them correctly.
316- let target = & bx. cx . tcx . sess . target ;
317- let is_soft_float_abi = target. rustc_abi == Some ( RustcAbi :: Softfloat ) ;
318- assert ! ( !is_soft_float_abi) ;
319-
320332 // All instances of VaArgSafe are passed directly.
321333 let is_indirect = false ;
322334
323- let ( is_i64 , is_int, is_f64 ) = match layout. layout . backend_repr ( ) {
335+ let is_int = match layout. layout . backend_repr ( ) {
324336 BackendRepr :: Scalar ( scalar) => match scalar. primitive ( ) {
325- rustc_abi:: Primitive :: Int ( integer, _) => ( integer. size ( ) . bits ( ) == 64 , true , false ) ,
326- rustc_abi:: Primitive :: Float ( float) => ( false , false , matches ! ( float, Float :: F64 ) ) ,
327- rustc_abi:: Primitive :: Pointer ( _) => ( false , true , false ) ,
337+ rustc_abi:: Primitive :: Int ( _, _) | rustc_abi:: Primitive :: Pointer ( _) => true ,
338+ rustc_abi:: Primitive :: Float ( _) => false ,
328339 } ,
329340 _ => unreachable ! ( "all instances of VaArgSafe are represented as scalars" ) ,
330341 } ;
331342
332- let is_passed_in_fprs = !( is_int || is_soft_float_abi) ;
343+ let is_passed_in_fprs = !( is_int || is_powerpc_softfloat_abi ( & bx. cx . tcx . sess . target ) ) ;
344+
333345 let num_regs_addr = if !is_passed_in_fprs {
334346 va_list_addr // gpr
335347 } else {
@@ -339,7 +351,7 @@ fn emit_powerpc_va_arg<'ll, 'tcx>(
339351 let mut num_regs = bx. load ( bx. type_i8 ( ) , num_regs_addr, dl. i8_align ) ;
340352
341353 // "Align" the register count when the type is passed as `i64`.
342- if is_i64 || ( is_f64 && is_soft_float_abi ) {
354+ if layout . size . bytes ( ) == 8 && !is_passed_in_fprs {
343355 num_regs = bx. add ( num_regs, bx. const_u8 ( 1 ) ) ;
344356 num_regs = bx. and ( num_regs, bx. const_u8 ( 0b1111_1110 ) ) ;
345357 }
@@ -388,7 +400,7 @@ fn emit_powerpc_va_arg<'ll, 'tcx>(
388400 bx. store ( bx. const_u8 ( max_regs) , num_regs_addr, dl. i8_align ) ;
389401
390402 // Everything in the overflow area is rounded up to a size of at least 4.
391- let overflow_area_align = Align :: from_bytes ( 4 ) . unwrap ( ) ;
403+ let overflow_area_align = Align :: FOUR ;
392404
393405 let size = if !is_indirect {
394406 layout. layout . size . align_to ( overflow_area_align)
@@ -625,8 +637,8 @@ fn emit_x86_64_sysv64_va_arg<'ll, 'tcx>(
625637 let gp_offset_ptr = va_list_addr;
626638 let fp_offset_ptr = bx. inbounds_ptradd ( va_list_addr, bx. cx . const_usize ( unsigned_int_offset) ) ;
627639
628- let gp_offset_v = bx. load ( bx. type_i32 ( ) , gp_offset_ptr, Align :: from_bytes ( 8 ) . unwrap ( ) ) ;
629- let fp_offset_v = bx. load ( bx. type_i32 ( ) , fp_offset_ptr, Align :: from_bytes ( 4 ) . unwrap ( ) ) ;
640+ let gp_offset_v = bx. load ( bx. type_i32 ( ) , gp_offset_ptr, Align :: EIGHT ) ;
641+ let fp_offset_v = bx. load ( bx. type_i32 ( ) , fp_offset_ptr, Align :: FOUR ) ;
630642
631643 let mut use_regs = bx. const_bool ( false ) ;
632644
@@ -759,7 +771,7 @@ fn emit_x86_64_sysv64_va_arg<'ll, 'tcx>(
759771 if num_fp_registers > 0 {
760772 let offset = bx. const_u32 ( num_fp_registers * 16 ) ;
761773 let sum = bx. add ( fp_offset_v, offset) ;
762- bx. store ( sum, fp_offset_ptr, Align :: from_bytes ( 4 ) . unwrap ( ) ) ;
774+ bx. store ( sum, fp_offset_ptr, Align :: FOUR ) ;
763775 }
764776
765777 bx. br ( end) ;
@@ -872,11 +884,7 @@ fn emit_hexagon_va_arg_musl<'ll, 'tcx>(
872884 // Align current pointer based on argument type size (following LLVM's implementation)
873885 // Arguments <= 32 bits (4 bytes) use 4-byte alignment, > 32 bits use 8-byte alignment
874886 let type_size_bits = layout. size . bits ( ) ;
875- let arg_align = if type_size_bits > 32 {
876- Align :: from_bytes ( 8 ) . unwrap ( )
877- } else {
878- Align :: from_bytes ( 4 ) . unwrap ( )
879- } ;
887+ let arg_align = if type_size_bits > 32 { Align :: EIGHT } else { Align :: FOUR } ;
880888 let aligned_current = round_pointer_up_to_alignment ( bx, current_ptr, arg_align) ;
881889
882890 // Calculate next pointer position (following LLVM's logic)
@@ -991,7 +999,7 @@ fn emit_xtensa_va_arg<'ll, 'tcx>(
991999 let offset = bx. load ( bx. type_i32 ( ) , offset_ptr, bx. tcx ( ) . data_layout . i32_align ) ;
9921000 let offset = round_up_to_alignment ( bx, offset, layout. align . abi ) ;
9931001
994- let slot_size = layout. size . align_to ( Align :: from_bytes ( 4 ) . unwrap ( ) ) . bytes ( ) as i32 ;
1002+ let slot_size = layout. size . align_to ( Align :: FOUR ) . bytes ( ) as i32 ;
9951003
9961004 // Update the offset in va_list, by adding the slot's size.
9971005 let offset_next = bx. add ( offset, bx. const_i32 ( slot_size) ) ;
0 commit comments