-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
[LoongArch64] Fix the wrong GCInfo when testing GCStress. #72572
Conversation
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch Issue DetailsThis is part of the issue #69705 to amend the LA's port. This PR fixs the wrong GCInfo when testing GCStress, adds split for LA and fixs some assert errors.
|
src/coreclr/jit/morph.cpp
Outdated
#ifndef TARGET_LOONGARCH64 | ||
// Make sure we loaded exactly the required amount of bytes. | ||
// But for LoongArch64's ABI, the struct {long a; float b;} may be passed | ||
// by Integer register and float register while must be considered the padding here. | ||
assert(structSize == (lastElem.Offset + genTypeSize(lastElem.Type))); | ||
#endif |
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.
This is not right, this path must always load the exact size, it means the logic for setting up elems
is not correct.
What does the elems
array look like for the cited struct?
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.
structSize=16; for struct {long a; float b;}
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.
3941 assert(structSize == (lastElem.Offset + genTypeSize(lastElem.Type))); (gdb) p structSize $1 = 16 (gdb) p lastElem $2 = (Compiler::ArgElem &) @0xfffffee970: {Type = TYP_FLOAT, Offset = 8} (gdb) p elems[0] $3 = {Type = TYP_LONG, Offset = 0} (gdb) p elems[1] $4 = {Type = TYP_FLOAT, Offset = 8}
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.
And the second element is 4 bytes in size, I see.
Only some subset of structs can pass 4 bytes only instead of the full 8 (i. e. with the padding). For example, with this struct:
[StructLayout(LayoutKind.Sequential, Size = 16)]
struct StructWithSignificantPadding
{
long L;
float F;
[padding: 4]
}
All 16 bytes must be passed (we assume the user could store something in the explicit padding).
It seems simpler to always pass all the bytes (this would also be consistent with Unix x64).
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.
Thanks very much for your reviewing and advices!
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.
thanks very much.
I will reply later, maybe tomorrow night.
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.
Only some subset of structs can pass 4 bytes only instead of the full 8 (i. e. with the padding). For example, with this struct:
[StructLayout(LayoutKind.Sequential, Size = 16)] struct StructWithSignificantPadding { long L; float F; [padding: 4] }All 16 bytes must be passed (we assume the user could store something in the explicit padding).
Or the struct
[StructLayout(LayoutKind.Sequential, Size = 16)]
struct StructWithSignificantPadding
{
double d;
int i;
[padding: 4]
}
- (1) all 16 bytes mus be passed.
For the CPUs liking the LA64 and MIPS64, the struct passed to the callee function, if the struct's field within the register which including the padding does't be stored on the stack within the prolog and directly as an operand for a operation, liking this,
### the register A1 containg the second field with padding
IG_01:
###prolog, and A1 not be stored to stack
IG_02:
###the 32bits operation liking add_w, compare_w and branch:
addi.w T0, A1, 0x4 ### the hight 32bits of the A1 must be sign extend, or the result is unpredictable.
### This is quite different with the AArch64 and AMD64.
- (2) I want to know the padding will be used at this case ?
For example, the register which including the padding will be passed to an instruction directly liking the previous example ? - (3) I want more detail info about the usage of the padding to amend the LA64's ABI implementation,
for example, adding more details info about the padding and specially treat it before using it directly, maybe store the padding first and then sign extend the hight 32bits.
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.
So essentially the question is how should the "custom ABI" for these structs look like. Not a simple problem.
One thing to consider is that we must retain compatibility with the native ABI for C/C++ PInvokes.
For example, the following struct:
[StructLayout(LayoutKind.Explicit)]
struct S
{
[FieldOffset(0)]
public long U1;
[FieldOffset(0)]
public long U2;
[FieldOffset(8)]
public int I;
}
Equivalent to this native one:
struct S
{
union
{
long long U1;
long long U2;
}
int I;
}
Would be classified as having "significant padding" in the managed world. So it would have to be passed one way to managed methods and another way to native ones.
For the CPUs liking the LA64 and MIPS64, the struct passed to the callee function, if the struct's field within the register which including the padding doesn't be stored on the stack
Structs with significant padding will not be promoted, and so the situation you cite ought not to arise (in the Jitted code at least).
The general question does still stand on how the padding should be treated though (with a "it is sequence of byte
fields"-like rule), so we can reason about it.
It looks like a significant decision to make, so I will ask @jkotas and @dotnet/jit-contrib for assistance here.
My personal thinking here is that we should make this as simple as possible, perhaps going as far as passing all structs with significant padding by reference. I suppose this also requires fixing #71711 first.
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.
I do not have an opinion on this one. LA64 ABI for passing structs is extremely complex. I do not have all details internalized.
One thing to consider is that we must retain compatibility with the native ABI for C/C++ PInvokes.
For example, the following struct:
Yes, native ABI compatibility is a good thing to shoot for. However, we do not have 100% interop for unions today. I believe that there are cases on existing platforms where it is not possible to define a struct with unions in a portable way in C#.
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.
Yes, native ABI compatibility is a good thing to shoot for.
Agree with you.
However, we do not have 100% interop for unions today. I believe that there are cases on existing platforms where it is not possible to define a struct with unions in a portable way in C#.
Yes, I think so that defining a struct with union is not a good way for keeping portable.
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.
Thanks @SingleAccretion for your review. Added few more things.
d2dcfd6
to
1e3252d
Compare
Hi, @kunalspathak @SingleAccretion |
It's very close to the net7.0 branch freezing. This PR may be held until the main branch is updated to net8.0. |
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 changes look good to me. I don't think we should block this change on resolving the issues with "structs with significant padding".
This is for loongarch only. @shushanhf - Is the loongarch port tied with .NET 7 release somehow or can we wait to take this in .NET 8? |
I think it's better to merge this within .NET7 and amending it after struct's padding is explicit. |
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.
Added some questions/comments.
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.
Some comments are still unclear and we need to fix that up before we merge.
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.
LGTM. Thank you!
This is part of the issue #69705 to amend the LA's port.
This PR fixs the wrong GCInfo when testing GCStress, adds split for LA and fixs some assert errors.