-
-
Notifications
You must be signed in to change notification settings - Fork 262
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
Win64 ABI fix: return non-POD structs via sret. #856
Conversation
And get rid of obsolete integer rewrites on Win64 and PPC.
Does experimental mean that you are still working on it? |
I wanted to check whether that introduces any regressions. Seems like it doesn't for VS 2015 (fixing at least one failing unit test in std.algorithm), so I guess it also doesn't for VS 2013. And apparently the more thorough typesAreEuivalent() check also works nicely for the System V ABI. PS: We're now down to 50 failing test modules for VS 2015. |
I.e., pass them explicitly ByVal and return them via sret.
Just like DMD. Inline assembly in druntime/phobos depends on this. Only relevant for MinGW-w64 as MSVC uses 64-bit real.
@redstar: This one's good to go unless you have a better name and/or location for the LLTypeMemoryLayout struct. |
|
||
// single element? then discard wrapping struct | ||
if (numElements == 1) | ||
return elements[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.
Maybe it is better to check for the one-element case first?
This is really a question - are there one member structs in Phobos and druntime?
Subjectively, I haven't noticed any significant slowdown, but I don't have any numbers (yet). It's not invoked for every struct function parameter; on Win64, only for structs of power-of-2 sizes <= 8 bytes, on PowerPC similar iirc, and for System V only structs which can be passed in registers, i.e., generally <= 16 bytes, so that the recursion depth isn't deep. But currently the results aren't cached for each already visited type, so this could be added if there's really a significant slowdown. Of course there are single-member structs - in upstream druntime, every associative array is a struct containing an opaque pointer, just to name a popular example. And besides druntime and phobos there's always user code too ;). The many unnecessary rewrites cluttering the LL code produced by LDC are the reason for this more thorough (and hence recursive) check. |
Alright, some numbers for a rough estimate:
Current merge-2.067 head + LLVM 3.5.2 in my Xubuntu x64 VM using 3 of my 4 physical cores:
With this PR:
|
Win64 ABI fix: return non-POD structs via sret.
@kinke With these changes, I can no longer build certain files in druntime and phobos. For example I am using MSVC 2013 and LLVM 3.6. If I revert the changes from this PR, the problem is gone. Part of the backtrace (line numbers from ldc-merge-2.067 branch):
Verbose compilation output right before the crash:
So it seems there is a problem with In
called from
I do not understand enough of the code to help you fix this :( |
@kinke Should we revert this PR? |
Reverting is OK, but I'd like to understand what is going on too :) |
Thanks Johan.
Heh me too. ;) I've never liked this repainting in case the types differ. In your example, the result (pointer to an array returned via sret) should obviously not be repainted at all, as the formal I guess the best course of action would be stripping the qualifiers transitively (i.e., recursively) for array types. |
@kinke Yep, I thought the same and had tried to figure out how to strip all qualifiers (recursively) but couldn't figure it out so quickly. |
@kinke Now the next error (probably related to this PR) is:
The error is generated in func->getFunctionType()->dump();
functype->dump(); gives { i64, i8* } (%object.TypeInfo*, i64)
void ({ i64, i8* }*, %object.TypeInfo*, i64) Thanks for any hints. |
I've come up with a +5 lines solution, yours is way more elegant. ;) Your function type mismatch appears to be related to sret. PS: I think LLVM 3.6 is particularly picky about proper forward declarations. I've fixed a couple runtime function signatures lately, but apparently |
@kinke OK, I'll look into this tomorrow. |
There's not a lot of diffs between D and C calling conventions, apart from the reversed parameter order (to be fixed sometime) and variadic functions. So on Win64, a 16-bytes struct (dynamic D array) is to be passed by ref and to be returned via sret, for both calling conventions. |
@kinke OK, I've fixed the function fwd decl, but again hitting on another LLVM assert. I'm starting to wonder if this ever actually worked on Win64! ;-) :'( |
@kinke In |
@JohanEngelen To be honest, I'm not sure whether I've properly tested the 2 last commits on Win64 (with LLVM 3.7) as they appeared pretty minuscule. I'll have to check that when I get home. |
@kinke I bet a bottle of whisky that it's not going to work with any version of LLVM ;) I agree it is good to follow the Win64 C calling convention, so I will try later. |
The work continues in #901 |
And get rid of obsolete integer rewrites on Win64 and PPC and some general rewrites on System V x86_64 platforms.