Skip to content

Commit d4be92c

Browse files
committed
Merge LoongArch and RISC-V AOT calculation of FpStructInRegistersInfo because they were identical. Move it to Common\Internal/Runtime because it's no longer exposed in JIT interface.
1 parent f064eb6 commit d4be92c

File tree

8 files changed

+99
-288
lines changed

8 files changed

+99
-288
lines changed

src/coreclr/tools/Common/JitInterface/LoongArch64PassStructInRegister.cs renamed to src/coreclr/tools/Common/Internal/Runtime/RiscVLoongArch64FpStruct.cs

Lines changed: 87 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,90 @@
99

1010
namespace Internal.JitInterface
1111
{
12-
internal static class LoongArch64PassStructInRegister
12+
// StructFloatFieldInfoFlags: used on LoongArch64 and RISC-V architecture as a legacy representation of
13+
// FpStructInRegistersInfo, returned by FpStructInRegistersInfo.ToOldFlags()
14+
//
15+
// `STRUCT_NO_FLOAT_FIELD` means structs are not passed using the float register(s).
16+
//
17+
// Otherwise, and only for structs with no more than two fields and a total struct size no larger
18+
// than two pointers:
19+
//
20+
// The lowest four bits denote the floating-point info:
21+
// bit 0: `1` means there is only one float or double field within the struct.
22+
// bit 1: `1` means only the first field is floating-point type.
23+
// bit 2: `1` means only the second field is floating-point type.
24+
// bit 3: `1` means the two fields are both floating-point type.
25+
// The bits[5:4] denoting whether the field size is 8-bytes:
26+
// bit 4: `1` means the first field's size is 8.
27+
// bit 5: `1` means the second field's size is 8.
28+
//
29+
// Note that bit 0 and 3 cannot both be set.
30+
[Flags]
31+
public enum StructFloatFieldInfoFlags
32+
{
33+
STRUCT_NO_FLOAT_FIELD = 0x0,
34+
STRUCT_FLOAT_FIELD_ONLY_ONE = 0x1,
35+
STRUCT_FLOAT_FIELD_ONLY_TWO = 0x8,
36+
STRUCT_FLOAT_FIELD_FIRST = 0x2,
37+
STRUCT_FLOAT_FIELD_SECOND = 0x4,
38+
STRUCT_FIRST_FIELD_SIZE_IS8 = 0x10,
39+
STRUCT_SECOND_FIELD_SIZE_IS8 = 0x20,
40+
};
41+
42+
43+
// Bitfields for FpStructInRegistersInfo.flags
44+
[Flags]
45+
public enum FpStruct
46+
{
47+
// Positions of flags and bitfields
48+
PosOnlyOne = 0,
49+
PosBothFloat = 1,
50+
PosFloatInt = 2,
51+
PosIntFloat = 3,
52+
PosSizeShift1st = 4, // 2 bits
53+
PosSizeShift2nd = 6, // 2 bits
54+
55+
UseIntCallConv = 0, // struct is passed according to integer calling convention
56+
57+
// The flags and bitfields
58+
OnlyOne = 1 << PosOnlyOne, // has only one field, which is floating-point
59+
BothFloat = 1 << PosBothFloat, // has two fields, both are floating-point
60+
FloatInt = 1 << PosFloatInt, // has two fields, 1st is floating and 2nd is integer
61+
IntFloat = 1 << PosIntFloat, // has two fields, 2nd is floating and 1st is integer
62+
SizeShift1stMask = 0b11 << PosSizeShift1st, // log2(size) of 1st field
63+
SizeShift2ndMask = 0b11 << PosSizeShift2nd, // log2(size) of 2nd field
64+
// Note: flags OnlyOne, BothFloat, FloatInt, and IntFloat are mutually exclusive
65+
}
66+
67+
// On RISC-V and LoongArch a struct with up to two non-empty fields, at least one of them floating-point,
68+
// can be passed in registers according to hardware FP calling convention. FpStructInRegistersInfo represents
69+
// passing information for such parameters.
70+
public struct FpStructInRegistersInfo
71+
{
72+
public FpStruct flags;
73+
public uint offset1st;
74+
public uint offset2nd;
75+
76+
public uint SizeShift1st() { return (uint)((int)flags >> (int)FpStruct.PosSizeShift1st) & 0b11; }
77+
78+
public uint SizeShift2nd() { return (uint)((int)flags >> (int)FpStruct.PosSizeShift2nd) & 0b11; }
79+
80+
public uint Size1st() { return 1u << (int)SizeShift1st(); }
81+
public uint Size2nd() { return 1u << (int)SizeShift2nd(); }
82+
83+
public StructFloatFieldInfoFlags ToOldFlags()
84+
{
85+
return
86+
((flags & FpStruct.OnlyOne) != 0 ? StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_ONLY_ONE : 0) |
87+
((flags & FpStruct.BothFloat) != 0 ? StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_ONLY_TWO : 0) |
88+
((flags & FpStruct.FloatInt) != 0 ? StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_FIRST : 0) |
89+
((flags & FpStruct.IntFloat) != 0 ? StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_SECOND : 0) |
90+
((SizeShift1st() == 3) ? StructFloatFieldInfoFlags.STRUCT_FIRST_FIELD_SIZE_IS8 : 0) |
91+
((SizeShift2nd() == 3) ? StructFloatFieldInfoFlags.STRUCT_SECOND_FIELD_SIZE_IS8 : 0);
92+
}
93+
}
94+
95+
internal static class RiscVLoongArch64FpStruct
1396
{
1497
private const int
1598
ENREGISTERED_PARAMTYPE_MAXSIZE = 16,
@@ -125,8 +208,10 @@ private static bool FlattenFields(TypeDesc td, uint offset, ref FpStructInRegist
125208

126209
private static bool IsAligned(uint val, uint alignment) => 0 == (val & (alignment - 1));
127210

128-
public static FpStructInRegistersInfo GetLoongArch64PassFpStructInRegistersInfo(TypeDesc td)
211+
public static FpStructInRegistersInfo GetFpStructInRegistersInfo(TypeDesc td, TargetArchitecture arch)
129212
{
213+
Debug.Assert(arch is TargetArchitecture.RiscV64 or TargetArchitecture.LoongArch64);
214+
130215
if (td.GetElementSize().AsInt > ENREGISTERED_PARAMTYPE_MAXSIZE)
131216
return new FpStructInRegistersInfo{};
132217

src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3456,23 +3456,8 @@ private void getSwiftLowering(CORINFO_CLASS_STRUCT_* structHnd, ref CORINFO_SWIF
34563456

34573457
private void getFpStructLowering(CORINFO_CLASS_STRUCT_* structHnd, ref CORINFO_FPSTRUCT_LOWERING lowering)
34583458
{
3459-
TypeDesc typeDesc = HandleToObject(structHnd);
3460-
var target = _compilation.TypeSystemContext.Target;
3461-
FpStructInRegistersInfo info;
3462-
if (target.Architecture is TargetArchitecture.RiscV64)
3463-
{
3464-
info = RiscV64PassFpStructInRegisters.GetRiscV64PassFpStructInRegistersInfo(typeDesc);
3465-
}
3466-
else if (target.Architecture is TargetArchitecture.LoongArch64)
3467-
{
3468-
info = LoongArch64PassStructInRegister.GetLoongArch64PassFpStructInRegistersInfo(typeDesc);
3469-
}
3470-
else
3471-
{
3472-
Debug.Assert(false, "Unsupported architecture for getFpStructInRegistersInfo");
3473-
return;
3474-
}
3475-
3459+
FpStructInRegistersInfo info = RiscVLoongArch64FpStruct.GetFpStructInRegistersInfo(
3460+
HandleToObject(structHnd), _compilation.TypeSystemContext.Target.Architecture);
34763461
if (info.flags != FpStruct.UseIntCallConv)
34773462
{
34783463
lowering = new CORINFO_FPSTRUCT_LOWERING {

src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs

Lines changed: 0 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,89 +1221,6 @@ public struct SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR
12211221
public byte eightByteOffsets1;
12221222
};
12231223

1224-
// StructFloatFieldInfoFlags: used on LoongArch64 and RISC-V architecture as a legacy representation of
1225-
// FpStructInRegistersInfo, returned by FpStructInRegistersInfo.ToOldFlags()
1226-
//
1227-
// `STRUCT_NO_FLOAT_FIELD` means structs are not passed using the float register(s).
1228-
//
1229-
// Otherwise, and only for structs with no more than two fields and a total struct size no larger
1230-
// than two pointers:
1231-
//
1232-
// The lowest four bits denote the floating-point info:
1233-
// bit 0: `1` means there is only one float or double field within the struct.
1234-
// bit 1: `1` means only the first field is floating-point type.
1235-
// bit 2: `1` means only the second field is floating-point type.
1236-
// bit 3: `1` means the two fields are both floating-point type.
1237-
// The bits[5:4] denoting whether the field size is 8-bytes:
1238-
// bit 4: `1` means the first field's size is 8.
1239-
// bit 5: `1` means the second field's size is 8.
1240-
//
1241-
// Note that bit 0 and 3 cannot both be set.
1242-
[Flags]
1243-
public enum StructFloatFieldInfoFlags
1244-
{
1245-
STRUCT_NO_FLOAT_FIELD = 0x0,
1246-
STRUCT_FLOAT_FIELD_ONLY_ONE = 0x1,
1247-
STRUCT_FLOAT_FIELD_ONLY_TWO = 0x8,
1248-
STRUCT_FLOAT_FIELD_FIRST = 0x2,
1249-
STRUCT_FLOAT_FIELD_SECOND = 0x4,
1250-
STRUCT_FIRST_FIELD_SIZE_IS8 = 0x10,
1251-
STRUCT_SECOND_FIELD_SIZE_IS8 = 0x20,
1252-
};
1253-
1254-
1255-
// Bitfields for FpStructInRegistersInfo.flags
1256-
[Flags]
1257-
public enum FpStruct
1258-
{
1259-
// Positions of flags and bitfields
1260-
PosOnlyOne = 0,
1261-
PosBothFloat = 1,
1262-
PosFloatInt = 2,
1263-
PosIntFloat = 3,
1264-
PosSizeShift1st = 4, // 2 bits
1265-
PosSizeShift2nd = 6, // 2 bits
1266-
1267-
UseIntCallConv = 0, // struct is passed according to integer calling convention
1268-
1269-
// The flags and bitfields
1270-
OnlyOne = 1 << PosOnlyOne, // has only one field, which is floating-point
1271-
BothFloat = 1 << PosBothFloat, // has two fields, both are floating-point
1272-
FloatInt = 1 << PosFloatInt, // has two fields, 1st is floating and 2nd is integer
1273-
IntFloat = 1 << PosIntFloat, // has two fields, 2nd is floating and 1st is integer
1274-
SizeShift1stMask = 0b11 << PosSizeShift1st, // log2(size) of 1st field
1275-
SizeShift2ndMask = 0b11 << PosSizeShift2nd, // log2(size) of 2nd field
1276-
// Note: flags OnlyOne, BothFloat, FloatInt, and IntFloat are mutually exclusive
1277-
}
1278-
1279-
// On RISC-V and LoongArch a struct with up to two non-empty fields, at least one of them floating-point,
1280-
// can be passed in registers according to hardware FP calling convention. FpStructInRegistersInfo represents
1281-
// passing information for such parameters.
1282-
public struct FpStructInRegistersInfo
1283-
{
1284-
public FpStruct flags;
1285-
public uint offset1st;
1286-
public uint offset2nd;
1287-
1288-
public uint SizeShift1st() { return (uint)((int)flags >> (int)FpStruct.PosSizeShift1st) & 0b11; }
1289-
1290-
public uint SizeShift2nd() { return (uint)((int)flags >> (int)FpStruct.PosSizeShift2nd) & 0b11; }
1291-
1292-
public uint Size1st() { return 1u << (int)SizeShift1st(); }
1293-
public uint Size2nd() { return 1u << (int)SizeShift2nd(); }
1294-
1295-
public StructFloatFieldInfoFlags ToOldFlags()
1296-
{
1297-
return
1298-
((flags & FpStruct.OnlyOne) != 0 ? StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_ONLY_ONE : 0) |
1299-
((flags & FpStruct.BothFloat) != 0 ? StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_ONLY_TWO : 0) |
1300-
((flags & FpStruct.FloatInt) != 0 ? StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_FIRST : 0) |
1301-
((flags & FpStruct.IntFloat) != 0 ? StructFloatFieldInfoFlags.STRUCT_FLOAT_FIELD_SECOND : 0) |
1302-
((SizeShift1st() == 3) ? StructFloatFieldInfoFlags.STRUCT_FIRST_FIELD_SIZE_IS8 : 0) |
1303-
((SizeShift2nd() == 3) ? StructFloatFieldInfoFlags.STRUCT_SECOND_FIELD_SIZE_IS8 : 0);
1304-
}
1305-
}
1306-
13071224
// DEBUGGER DATA
13081225
public enum MappingTypes
13091226
{

src/coreclr/tools/Common/JitInterface/RiscV64PassFpStructInRegisters.cs

Lines changed: 0 additions & 172 deletions
This file was deleted.

0 commit comments

Comments
 (0)