-
Notifications
You must be signed in to change notification settings - Fork 32
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
Test failure: gfortran.dg/c_kind_params.f90 #73
Comments
hmm .. here I am not sure why we would be using varargs anyway - the prototypes are explicit. This seems to say that we are making a mistake with packing of args on the stack - but I'm not sure why that would change with optimisation (unless some inlining or something). darwin c-chars are signed in any event - so if you need a specific test - it would be the unsigned case. time to look at the asm generated :) |
Signed or unsigned makes no difference, I've tried. I know this case doesn't have varargs, but thought somehow an issue might have slipped into the handling of args packing at the same time. |
OK I think I've reduced to its bare minimum. Take this pure C example:
It works, as it should. Now, I replace the "param_test" function with Fortran, and boom:
The Fortran and C versions of param_test should be absolutely identical and lead to the same codegen. But:
There are more differences in the codegen at |
OK, we probably ought to be able to reduce the number of initial ints... probably
Is what I expect. edit - I'd expect the same result if you dropped i .. u from the arguments (unless the bug is dependent on the args count, of course) |
JFTR, clang and GCC agree on the position of w in C ( so, at least, we're ABI-compliant in this case :) ) |
The asm difference remains with args i to u removed. The Fortran tree dump for that version is:
Notice that In fact, that Fortran version should be equivalent to having for
but the codegen shows that it is different. Hum… why are these types treated differently? |
character(kind=1) v, so it seems integer(kind=1) is being treated the same as integer(kind=4) |
I guess Fortran either does not know (or maybe has no provision for) that the default char type is signed [there are relatively few targets with default signed char, so it might not show much except on Darwin which is probably the only one using Fortran aggressively] |
this port has already picked up a bunch of problems with the function interfaces, so it's doing useful service for improving the compiler :) |
That's not 100% convincing (although it is plausible too); the first value appears at the start of a slot (so that has sufficient alignment for either a char (1) or an int (4) .. and, yes, if the character kind=1 is being promoted to int, then that would be 4 bytes which would push the second char to 4 bytes offest. OTOH, if the second char is promoted to int, then that would need 4 bytes of alignment which would also push it to a higher offset. (we cannot tell which is in effect without seeing what the "c-style" function signature is)
No, but it's a potential source of other bugs - so we ought to file something on BZ about that. |
oops I meant to reply to your post, not edit it. |
I'd like to be able to hack into the middle-end and dump that function type, but I don't know how. I mean I remember I have to set up a breakpoint in a suitable place and call |
Hey looking at the tree dump that
I mean, how could a scalar variable be writable? But I suppose this does not affect your argument layout, it is only used at middle-end level to optimise stuff. Am I right? |
I was looking at debug-wise I suppose the answer is to break on expand_call or expand_function and then look at the actual function types list passed... |
So the tree dump for arg
and that of
So I guess the problem is that the |
well there's been quite a bit of fixing up of the fn-specs in this cycle (some of which is the result of problems with this port - but seems there's more to do)
Layout would only be affected by the passed-as type (so if it's a char being passed as an int, that would break things) - although that is not how C rules are being interpreted by either GCC or clang (they both agree in this case) |
Yikes - that supports the "w" attribute, I guess.. but not exactly an efficient way to pass a single char ;)
seems likely and likely affects all platforms - but this is the only one that's going to show it. |
so two possible PRs:
|
I wonder, in passing why w is not producing this effect - and why changing the signed-ness of v makes no difference. |
I suppose the key is character c.f. int - perhaps character is always represented as an array? (speculation). |
In the Fortran front-end, character variables are always arrays. We never actually have character scalars, only strings, represented as arrays. When we emit a call to a C function, with a signature that expects a scalar char value, the front-end actually builds the from the existing types. And apparently, it can fail (although why this has never mattered on other targets, I don't know.) |
This is the first target (or at least the only one in the current set) to pack entities on the stack, so most targets will start a new PARM_BOUNDARY (most likely 8bytes on most machines) for each stack var and you would never see it on a LE machine. You might see it on a BE machine tho. Perhaps I'll experiment with powerpc-darwin9 when it frees up from this week's test cycle. |
I'm not very familiar with |
I did not deduce it from your debug_tree () output - but from the output from fdump-rtl-expand which seems to show
edit - in fairness that does not prove that it is being treated as an array - only that it is being passed as a 32b chunk (which is what's messing things up). |
Reported to bugzilla: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103828 |
Hum, I might have a one-line fix for it:
It makes the tree for that argument now be:
which is looking good. It fixes the reduced testcase, but not the original one (with more arguments). On the full testcase, I still get a failure. I'm tired and need to sleep, I won't make more progress on this :( |
OK, I'm diving back in. The testcase is still:
Now, with my patch, the trees being used for the types of the last three arguments are:
All three are Yet, compiling with
which I think is wrong: it seems to treat |
Yes, that looks equally wrong to the previous version despite that the type is now right. I assume that the offset is still wrong in the asm too.
c.f.
Where, in the gimple pipeline are you looking at the arg types? |
I set a breakpoint on expand_function_start and stepped through the parms:
So something in the middle end has decided that this needs to be passed as an int |
I don't know how to look at the gimple in the middle-end (at least, outside of the But I looked further down the front-end, and found this, which gave me a “oh shit” moment.
and then this:
And if I print this
|
So the front-end is emitting code for that argument with a |
hmm.. well the comment about what C would do does not appear to agree with what either GCC or clang's C compilers actually implement - perhaps there's some misinterpretation of promotion rules that would be applied to an un-prototyped function (where things are indeed promoted)? and indeed - there is the SI arg-type - so it's not a ME thing |
OK, removing that stupid line works, and makes the test pass. I'll follow up with the Fortran maintainers. I'm wondering why it's allowed to have a type with |
Yes, totally legal - it corresponds to the situation in which a type cannot be passed naturally and has to be passed as something different according to ABI. I guess it might be necessary to read the C std on promotion rules (I am only going from [possibly faulty] memory that the C-(rather than ABI) promotions happen when the destination type is unknown [so for unprototyped and maybe K&R style functions]) |
@iains my memory is the same, and what I've found in 5 minutes of reading confirms that. Thanks a lot for your help, and sorry that it wasn't a target bug after all… |
“Funnily” enough, the original PR that introduced this feature was https://gcc.gnu.org/bugzilla/show_bug.cgi?id=32732 |
well, I suppose that one could add Tobias to the BZ and/or just post the patch if there are no regressions on darwin / linux (it is possible to test Solaris on the cfarm - gcc211 is what I use). |
I've just finished a clean patch for Fortran, with a couple more testcases as well (for those delicate targets…). Regtesting right now on aarch64-apple-darwin. But it seemed to pass on solaris before, so maybe it's delicate in a different way |
I suppose a BE target (e.g. gcc110) would be wise - that could very well show progressions if the ABI mismatches by placing the char at [SP+3] instead of [SP] (which would be the consequence of promoting to int on a BW machine) |
Closing the report, it's moved to bugzilla, and I'll submit a patch later today. |
Regarding signedness, I've concluded that there is no actual wrong caused by the current implementation. The Fortran standard, in its C interoperability section, actually makes some interesting notes on how Fortran does not really care about signedness and can interoperate with all of char, unsigned char and signed char in the same way. We only ever pass or return arguments, by value or by address. But internally, we can use whatever we want (and most Fortran operations on character values outside the ASCII range are noted to be implementation-defined anyway). |
And… patch posted: https://gcc.gnu.org/pipermail/fortran/2021-December/057226.html |
Yeah, from my Fortran days (f77 ;) ) I recall that it does not really have the concept of unsigned integers. So I suppose that any juggling needs to be done in the C bindings. |
gfortran.dg/c_kind_params.f90
is failing, and has been for some time. I hoped that with the new version of varargs it would be fixed, but it's not. Somewhat reduced:where it is clear that the last argument is passed with wrong value. It is a sensitive test, the value displayed (instead of
0
) can change if you compile with-O1
or remove some of the unused local variables.A shorter version, showing a non-zero value passed (which makes the original test pass, but not the reduced testcase) is:
The text was updated successfully, but these errors were encountered: