-
Notifications
You must be signed in to change notification settings - Fork 5k
[RISC-V][LoongArch64] Handle reversed fields in lowered structs #115933
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch |
if (nFields == 2 && info.offset1st > info.offset2nd) | ||
{ | ||
LOG((LF_JIT, LL_EVERYTHING, "FpStructInRegistersInfo: struct %s (%u bytes): swap fields to match memory order\n", | ||
(!th.IsTypeDesc() ? th.AsMethodTable() : th.AsNativeValueType())->GetDebugClassName(), th.GetSize())); | ||
info.flags = FpStruct::Flags( | ||
((info.flags & FloatInt) << (PosIntFloat - PosFloatInt)) | | ||
((info.flags & IntFloat) >> (PosIntFloat - PosFloatInt)) | | ||
((info.flags & SizeShift1stMask) << (PosSizeShift2nd - PosSizeShift1st)) | | ||
((info.flags & SizeShift2ndMask) >> (PosSizeShift2nd - PosSizeShift1st)) | ||
); | ||
std::swap(info.offset1st, info.offset2nd); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The order matters for two floats and the calling convention wasn't clear. The only precedent I could find was GCC/gnat compiling Ada of all places, I made a proposal following it: riscv-non-isa/riscv-elf-psabi-doc#463, LoongArch gnat also behaves this way.
For int-float structs it doesn't matter but I'm ordering the fields as they come in memory anyway for consistency.
if (nFields == 2 && info.offset1st > info.offset2nd) | ||
{ | ||
// swap fields to match memory order | ||
info.flags = (FpStruct)( | ||
((uint)(info.flags & FloatInt) << (PosIntFloat - PosFloatInt)) | | ||
((uint)(info.flags & IntFloat) >> (PosIntFloat - PosFloatInt)) | | ||
((uint)(info.flags & SizeShift1stMask) << (PosSizeShift2nd - PosSizeShift1st)) | | ||
((uint)(info.flags & SizeShift2ndMask) >> (PosSizeShift2nd - PosSizeShift1st)) | ||
); | ||
(info.offset2nd, info.offset1st) = (info.offset1st, info.offset2nd); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is nFields == 2
the only case that needs to be handled? What about e.g. 8 byte fields and a double field? Can that combination not be passed in an integer + float register?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is nFields == 2 the only case that needs to be handled?
Yes
What about e.g. 8 byte fields and a double field? Can that combination not be passed in an integer + float register?
Only structs with one or two primitive fields (at least one of them FP) are lowered, structs with more fields are passed in integer registers and/or on the stack as they are laid out in memory.
RISC-V Release-CLR-QEMU: 9075 / 9105 (99.67%)
report.xml, report.md, failures.xml, testclr_details.tar.zst RISC-V Release-CLR-VF2: 9076 / 9106 (99.67%)
report.xml, report.md, failures.xml, testclr_details.tar.zst RISC-V Release-FX-QEMU: 282588 / 283649 (99.63%)
report.xml, report.md, failures.xml, testclr_details.tar.zst RISC-V Release-FX-VF2: 308940 / 310658 (99.45%)
report.xml, report.md, failures.xml, testclr_details.tar.zst Build information and commandsGIT: |
/ba-g Failure is #115955 |
Part of #84834, cc @dotnet/samsung @LuckyXu-HF @shushanhf