@@ -780,7 +780,7 @@ fn x86_64_sysv64_va_arg_from_memory<'ll, 'tcx>(
780780 mem_addr
781781}
782782
783- fn emit_hexagon_va_arg < ' ll , ' tcx > (
783+ fn emit_hexagon_va_arg_musl < ' ll , ' tcx > (
784784 bx : & mut Builder < ' _ , ' ll , ' tcx > ,
785785 list : OperandRef < ' tcx , & ' ll Value > ,
786786 target_ty : Ty < ' tcx > ,
@@ -865,6 +865,57 @@ fn emit_hexagon_va_arg<'ll, 'tcx>(
865865 bx. load ( layout. llvm_type ( bx) , value_addr, layout. align . abi )
866866}
867867
868+ fn emit_hexagon_va_arg_bare_metal < ' ll , ' tcx > (
869+ bx : & mut Builder < ' _ , ' ll , ' tcx > ,
870+ list : OperandRef < ' tcx , & ' ll Value > ,
871+ target_ty : Ty < ' tcx > ,
872+ ) -> & ' ll Value {
873+ // Implementation of va_arg for Hexagon bare-metal (non-musl) targets.
874+ // Based on LLVM's EmitVAArgForHexagon implementation.
875+ //
876+ // va_list is a simple pointer (char *)
877+ let va_list_addr = list. immediate ( ) ;
878+ let layout = bx. cx . layout_of ( target_ty) ;
879+ let ptr_align_abi = bx. tcx ( ) . data_layout . pointer_align ( ) . abi ;
880+
881+ // Load current pointer from va_list
882+ let current_ptr = bx. load ( bx. type_ptr ( ) , va_list_addr, ptr_align_abi) ;
883+
884+ // Handle address alignment for types with alignment > 4 bytes
885+ let ty_align = layout. align . abi ;
886+ let aligned_ptr = if ty_align. bytes ( ) > 4 {
887+ // Ensure alignment is a power of 2
888+ debug_assert ! ( ty_align. bytes( ) . is_power_of_two( ) , "Alignment is not power of 2!" ) ;
889+ round_pointer_up_to_alignment ( bx, current_ptr, ty_align, bx. type_ptr ( ) )
890+ } else {
891+ current_ptr
892+ } ;
893+
894+ // Calculate offset: round up type size to 4-byte boundary (minimum stack slot size)
895+ let type_size = layout. size . bytes ( ) ;
896+ let offset = ( ( type_size + 3 ) / 4 ) * 4 ; // align to 4 bytes
897+
898+ // Update va_list to point to next argument
899+ let next_ptr = bx. inbounds_ptradd ( aligned_ptr, bx. const_usize ( offset) ) ;
900+ bx. store ( next_ptr, va_list_addr, ptr_align_abi) ;
901+
902+ // Load and return the argument value
903+ bx. load ( layout. llvm_type ( bx) , aligned_ptr, layout. align . abi )
904+ }
905+
906+ fn emit_hexagon_va_arg < ' ll , ' tcx > (
907+ bx : & mut Builder < ' _ , ' ll , ' tcx > ,
908+ list : OperandRef < ' tcx , & ' ll Value > ,
909+ target_ty : Ty < ' tcx > ,
910+ is_musl : bool ,
911+ ) -> & ' ll Value {
912+ if is_musl {
913+ emit_hexagon_va_arg_musl ( bx, list, target_ty)
914+ } else {
915+ emit_hexagon_va_arg_bare_metal ( bx, list, target_ty)
916+ }
917+ }
918+
868919fn emit_xtensa_va_arg < ' ll , ' tcx > (
869920 bx : & mut Builder < ' _ , ' ll , ' tcx > ,
870921 list : OperandRef < ' tcx , & ' ll Value > ,
@@ -1049,7 +1100,7 @@ pub(super) fn emit_va_arg<'ll, 'tcx>(
10491100 // This includes `target.is_like_darwin`, which on x86_64 targets is like sysv64.
10501101 Arch :: X86_64 => emit_x86_64_sysv64_va_arg ( bx, addr, target_ty) ,
10511102 Arch :: Xtensa => emit_xtensa_va_arg ( bx, addr, target_ty) ,
1052- Arch :: Hexagon if target . env == Env :: Musl = > emit_hexagon_va_arg ( bx, addr, target_ty) ,
1103+ Arch :: Hexagon = > emit_hexagon_va_arg ( bx, addr, target_ty, target . env == Env :: Musl ) ,
10531104 // For all other architecture/OS combinations fall back to using
10541105 // the LLVM va_arg instruction.
10551106 // https://llvm.org/docs/LangRef.html#va-arg-instruction
0 commit comments