-
Notifications
You must be signed in to change notification settings - Fork 13
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
Variadic functions improvements / unformatted functions #46
Variadic functions improvements / unformatted functions #46
Conversation
… function split, useful for languages with default arg support Added --generateexplodedvarargsfunctions option to generate variants of variadic functions with up to a number of explicit args, useful for languages without variadic function support Added --generateunformattedfunctions option to generate unformatted variants of format string supporting functions
…ns and to build workflow
Just a very quick note to say thanks for the PR, and that I'm afraid it'll likely be the weekend before I get a chance to look at it properly, but as soon as I get a chance I'll give it a go! |
I've spent a while playing with this and unfortunately I don't think the varargs mechanism works reliably in all situations. I think there are probably multiple situations in which this can go wrong - the most immediately obvious being that calling conventions generally expect floats/doubles to go into FPU registers. The x64 calling convention docs state that floating-point values go into XMM0 and so on whilst everything else goes into RCX/etc. I wrote a little bit of code to test this out: ImGui_Text("Float %f, %f", 1.0f, 2.0f);
ImGuiPrintableVarArg testArg;
testArg.val_double = 1.0f;
ImGuiPrintableVarArg testArgB;
testArgB.val_double = 2.0f;
ImGui_TextVA_2("Float test %f, %f", testArg, testArgB);
testArg.val_int32 = 123;
testArgB.val_int32 = 456;
ImGui_TextVA_2("Int test %d, %d", testArg, testArgB); Interestingly, on MSVC/Windows/x64 this actually works correctly: It appears that this is because of a compatibility feature - the calling convention notes say:
...and it seems that in this case Looking at the code, the first case (calling
Whilst the relevant part of
...and is therefore only loading the integer registers, not the SSE ones. On Clang/OSX/x64, on the other hand, printf() clearly uses the floating-point registers, because the same code gives this result: It looks like this is possibly a Clang/LLVM vs MSVC difference, as you can see in this compiler explorer test - MSVC clearly generates code to set both sets of registers:
...whilst Clang is happy to just set XMM1 and XMM2 and be on its way:
So as it stands it doesn't look like this will work in the general case, I'm afraid. I'm actually having a hard time coming up with plausible workarounds right now, too - even if the thunk code in I'll keep pondering it in case something comes to mind, but any ideas on your side? |
That's extremely unfortunate, but in hindsight, pretty expected, since we are completely in undefined behavior land. I can't think of any other reasonable approach, though... Unless, maybe generating a thunk for every possible permutations isn't that terrible of an idea? If we limit ourselves to just
4+ arguments would be impractical for sure. Other than that, I guess we can always abandon the idea of supporting varargs and rely solely on the unformatted variant, with the formatting done by the caller. There really isn't that much of a need for varargs, it was more of a nice to have. The unformatted variants effectively achieve similar results. |
limiting the argument to 3 is not a great approach IMO since now user have to remember to use 1 method if arguments are less than 4 and another if they are equal or above 4. Also, argument type won’t match so that would be another issue user have to deal with. At this point in time wouldn’t “generateunformattedfunctions” be enough? |
Yeah, as I said, the unformatted variants are enough. Varargs support for languages without varargs would have been a nice option, but it's not worth the effort or the ugliness. I'll remove it. |
Yeah, sadly I think that's the only practical way forward... I've been thinking about this more today but the only other "solution" I could come up with was basically to reimplement sprintf() in the wrapper layer, which would be both annoying to do and likely lead to all sorts of weird discrepancies in behaviour between the versions. |
…to make it portable
18fc295
to
a5d85ce
Compare
Removed varargs supports... Seems like changes are pretty minimal now. |
Yeah, this looks pretty good to me now. |
Yup, feel free to merge! |
Ah, one thing that just popped into my mind - what about |
On that front, though, I suspect that it's likely to be mostly orthogonal to the stuff in this PR - my understanding is that there are relatively few situations in which C-style format strings and |
I've merged this in to mainline - thanks! |
For the unformatted functions though, it does makes sense to have string slicing support though, same as for any other non format string supporting function. It would sure be useful for C#!
Of course! |
Added--generateexplodedvarargsfunctions
option to generate variants of variadic functions with up to a number of explicit args, useful for languages without variadic function support (No way to call variadic functions / functions with va_list from some languages #45)--generateunformattedfunctions
option to generate unformatted variants of format string supporting functions (fixed No way to call variadic functions / functions with va_list from some languages #45)--nogeneratedefaultargfunctions
option to disable the non-Ex/Ex function split, useful for languages with default arg support (fixed Add support for imgui_internal.h #9 (comment))The required changes were quite unintrusive, and the new output seems to resolve all the issues I had.
Remaining things to do: