@@ -754,6 +754,102 @@ typedef DPTR(SystemVStructRegisterPassingHelper) SystemVStructRegisterPassingHel
754
754
755
755
#endif // UNIX_AMD64_ABI_ITF
756
756
757
+ #if defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64)
758
+ // StructFloatFieldInfoFlags: used on LoongArch64 and RISC-V architecture as a legacy representation of
759
+ // FpStructInRegistersInfo, returned by FpStructInRegistersInfo::ToOldFlags()
760
+ //
761
+ // `STRUCT_NO_FLOAT_FIELD` means structs are not passed using the float register(s).
762
+ //
763
+ // Otherwise, and only for structs with no more than two fields and a total struct size no larger
764
+ // than two pointers:
765
+ //
766
+ // The lowest four bits denote the floating-point info:
767
+ // bit 0: `1` means there is only one float or double field within the struct.
768
+ // bit 1: `1` means only the first field is floating-point type.
769
+ // bit 2: `1` means only the second field is floating-point type.
770
+ // bit 3: `1` means the two fields are both floating-point type.
771
+ // The bits[5:4] denoting whether the field size is 8-bytes:
772
+ // bit 4: `1` means the first field's size is 8.
773
+ // bit 5: `1` means the second field's size is 8.
774
+ //
775
+ // Note that bit 0 and 3 cannot both be set.
776
+ enum StructFloatFieldInfoFlags
777
+ {
778
+ STRUCT_NO_FLOAT_FIELD = 0x0 ,
779
+ STRUCT_FLOAT_FIELD_ONLY_ONE = 0x1 ,
780
+ STRUCT_FLOAT_FIELD_ONLY_TWO = 0x8 ,
781
+ STRUCT_FLOAT_FIELD_FIRST = 0x2 ,
782
+ STRUCT_FLOAT_FIELD_SECOND = 0x4 ,
783
+ STRUCT_FIRST_FIELD_SIZE_IS8 = 0x10 ,
784
+ STRUCT_SECOND_FIELD_SIZE_IS8 = 0x20 ,
785
+ };
786
+
787
+ // Bitfields for FpStructInRegistersInfo::flags
788
+ namespace FpStruct
789
+ {
790
+ enum Flags
791
+ {
792
+ // Positions of flags and bitfields
793
+ PosOnlyOne = 0 ,
794
+ PosBothFloat = 1 ,
795
+ PosFloatInt = 2 ,
796
+ PosIntFloat = 3 ,
797
+ PosSizeShift1st = 4 , // 2 bits
798
+ PosSizeShift2nd = 6 , // 2 bits
799
+
800
+ UseIntCallConv = 0 , // struct is passed according to integer calling convention
801
+
802
+ // The flags and bitfields
803
+ OnlyOne = 1 << PosOnlyOne, // has only one field, which is floating-point
804
+ BothFloat = 1 << PosBothFloat, // has two fields, both are floating-point
805
+ FloatInt = 1 << PosFloatInt, // has two fields, 1st is floating and 2nd is integer
806
+ IntFloat = 1 << PosIntFloat, // has two fields, 2nd is floating and 1st is integer
807
+ SizeShift1stMask = 0b11 << PosSizeShift1st, // log2(size) of 1st field
808
+ SizeShift2ndMask = 0b11 << PosSizeShift2nd, // log2(size) of 2nd field
809
+ // Note: flags OnlyOne, BothFloat, FloatInt, and IntFloat are mutually exclusive
810
+ };
811
+ }
812
+
813
+ // On RISC-V and LoongArch a struct with up to two non-empty fields, at least one of them floating-point,
814
+ // can be passed in registers according to hardware FP calling convention. FpStructInRegistersInfo represents
815
+ // passing information for such parameters.
816
+ struct FpStructInRegistersInfo
817
+ {
818
+ FpStruct::Flags flags;
819
+ uint32_t offset1st;
820
+ uint32_t offset2nd;
821
+
822
+ unsigned SizeShift1st () const { return (flags >> FpStruct::PosSizeShift1st) & 0b11 ; }
823
+ unsigned SizeShift2nd () const { return (flags >> FpStruct::PosSizeShift2nd) & 0b11 ; }
824
+
825
+ unsigned Size1st () const { return 1u << SizeShift1st (); }
826
+ unsigned Size2nd () const { return 1u << SizeShift2nd (); }
827
+
828
+ const char * FlagName () const
829
+ {
830
+ switch (flags & (FpStruct::OnlyOne | FpStruct::BothFloat | FpStruct::FloatInt | FpStruct::IntFloat))
831
+ {
832
+ case FpStruct::OnlyOne: return " OnlyOne" ;
833
+ case FpStruct::BothFloat: return " BothFloat" ;
834
+ case FpStruct::FloatInt: return " FloatInt" ;
835
+ case FpStruct::IntFloat: return " IntFloat" ;
836
+ default : return " ?" ;
837
+ }
838
+ }
839
+
840
+ StructFloatFieldInfoFlags ToOldFlags () const
841
+ {
842
+ return StructFloatFieldInfoFlags (
843
+ ((flags & FpStruct::OnlyOne) ? STRUCT_FLOAT_FIELD_ONLY_ONE : 0 ) |
844
+ ((flags & FpStruct::BothFloat) ? STRUCT_FLOAT_FIELD_ONLY_TWO : 0 ) |
845
+ ((flags & FpStruct::FloatInt) ? STRUCT_FLOAT_FIELD_FIRST : 0 ) |
846
+ ((flags & FpStruct::IntFloat) ? STRUCT_FLOAT_FIELD_SECOND : 0 ) |
847
+ ((SizeShift1st () == 3 ) ? STRUCT_FIRST_FIELD_SIZE_IS8 : 0 ) |
848
+ ((SizeShift2nd () == 3 ) ? STRUCT_SECOND_FIELD_SIZE_IS8 : 0 ));
849
+ }
850
+ };
851
+ #endif // defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64)
852
+
757
853
// ===============================================================================================
758
854
//
759
855
// GC data appears before the beginning of the MethodTable
0 commit comments