[PATCH] include: Use __cdecl calling convention for wine_dbg_log().

Zebediah Figura z.figura12 at gmail.com
Sat Sep 19 10:39:39 CDT 2020


On 9/18/20 11:52 AM, Rémi Bernon wrote:
> On 2020-09-10 22:30, Rémi Bernon wrote:
>> On 2020-09-10 21:38, Matteo Bruni wrote:
>>> The practical consequence is that registers are saved / restored
>>> inside wine_dbg_log() instead of in the caller, which means not
>>> incurring in the overhead when debug channels are disabled.
>>>
>>> Signed-off-by: Matteo Bruni <mbruni at codeweavers.com>
>>> ---
>>> This came up from hacking around yesterday with Paul and Rémi. I
>>> haven't tested the patch extensively but it seems to do the
>>> trick. wine_dbg_log() in practice is never inlined for me and that's
>>> the reason why this is enough. It's not possible to remove the inline
>>> keyword from the definition because that makes it trigger the "unused
>>> static function" warning all over Wine.
>>>
>>> Worth mentioning that this patch makes sure that wine_dbg_log() has
>>> the same calling convention as __wine_dbg_header() and the other
>>> debug functions in ntdll.
>>> ---
>>>   include/wine/debug.h | 12 ++++++------
>>>   1 file changed, 6 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/include/wine/debug.h b/include/wine/debug.h
>>> index 912d61a90af0..462a43e22e20 100644
>>> --- a/include/wine/debug.h
>>> +++ b/include/wine/debug.h
>>> @@ -193,12 +193,12 @@ static inline int __wine_dbg_cdecl 
>>> wine_dbg_printf( const char *format, ... )
>>>       return __wine_dbg_output( buffer );
>>>   }
>>> -static int __wine_dbg_cdecl wine_dbg_log( enum __wine_debug_class cls,
>>> -                                          struct __wine_debug_channel 
>>> *channel, const char *func,
>>> -                                          const char *format, ... ) 
>>> __WINE_PRINTF_ATTR(4,5);
>>> -static inline int __wine_dbg_cdecl wine_dbg_log( enum 
>>> __wine_debug_class cls,
>>> -                                                 struct 
>>> __wine_debug_channel *channel,
>>> -                                                 const char 
>>> *function, const char *format, ... )
>>> +static int __cdecl wine_dbg_log( enum __wine_debug_class cls,
>>> +                                 struct __wine_debug_channel 
>>> *channel, const char *func,
>>> +                                 const char *format, ... ) 
>>> __WINE_PRINTF_ATTR(4,5);
>>> +static inline int __cdecl wine_dbg_log( enum __wine_debug_class cls,
>>> +                                        struct __wine_debug_channel 
>>> *channel,
>>> +                                        const char *function, const 
>>> char *format, ... )
>>>   {
>>>       char buffer[1024];
>>>       __wine_dbg_va_list args;
>>>
>>
>> Well, if we intend to make these functions __cdecl, probably they all 
>> should be, in this header, including the inline helpers, as we've seen 
>> that any missing attribute can make the spilling leak to its callers.
>>
>> Then, I didn't look very precisely either, but I believe there's 
>> actually a big issue that makes it not so simple after all (correct me 
>> if I'm wrong though, maybe it's all good):
>>
>> If we set "ms_abi" attribute to these vararg functions, then their 
>> calling convention will be as such. Thus, we cannot use anymore the sysv 
>> va_list in there, and we have instead to use the __ms_va_list (defined 
>> to __builtin_ms_va_list in this case).
>>
>> Now, doing so will break the vsnprintf call, when it goes to libc, as it 
>> expects a sysv va_list argument instead.
>>
>> One possible way that I see would be instead to have a 
>> __wine_dbg_vsnprintf export in ntdll, that either forward the call to 
>> msvcrt vsnprintf (which already expects a __ms_va_list argument), or to 
>> an ntdll.so implementation.
>>
>> The ntdll.so implementation will have to be here anyway, to support its 
>> own traces, as it cannot go back to msvcrt for that. It will have to 
>> handle the __ms_va_arg somehow, possibly translating it for libc (which 
>> actually may not be so hard, with snprintf and one argument at a time), 
>> or handle the formatting on its own.
>>
>> The latter could actually make the whole thing worth the effort, if we 
>> consider that TRACE messages could benefit from a specific printf 
>> implementation with some extensions. For instances, it could print 
>> strings and wstrings at the same time, in a safe way, without needing 
>> the debugstr_a/w anymore. Same for guids for instance.
> 
> 
> Hi!
> 
> 
> I actually pushed the idea a little bit further and implemented it, in 
> the attached patches, to illustrate a bit and because I think it could 
> possibly still be interesting.
> 
> 
> The SSE register spilling savings are actually a little bit 
> underwhelming. As we have seen, any ms_abi function that calls a 
> sysv_abi function (or a non specified, in an ELF builtin) will spill the 
> XMM registers to the stack and restore them after the call.
> 
> Marking the debug functions ms_abi mostly helps with the leaf functions 
> that do not call anything else, but for instance in wined3d, there's a 
> lot of unspecified helpers that will cause the same spilling to happen. 
> We will have to specify ms_abi on all of them to solve the issue.
> 
> Then, making all functions ms_abi pushes the spilling down the call 
> chain, and if there's a system function to call in the end, it will have 
> to spill the registers anyway. If that function is called much more 
> often than the Wine entry point, then it may also not be ideal to force 
> the register spilling there, and having it on the entry point would be 
> preferable.
> 
> Anyway, making debug functions ms_abi should not hurt in any case, they 
> are not supposed to be called often, they never go back from sysv_abi to 
> ms_abi, and keeping their own induced spilling internally is better 
> regardless of what the surrounding code does.
> 
> 
> Now, what I find the most useful, is what this implementation allows us 
> to do with debug TRACE messages. As it makes every debug formatting go 
> through ntdll.so, I think it has at least two interesting properties:
> 
> 1) We can control the formatting, and as I did in the patch, extend the 
> format specifiers as we like, and get rid of most of the static inline 
> debug helpers (I don't know if that's a good thing or not, but I 
> personally like to be able to do so).
> 
> 2) The actual value formatting is done consistently by glibc. There's no 
> value formatting difference between PE code and ELF code TRACE messages. 
> And thanks to 1) we can still support MSVC-specific format specifiers, 
> we just need to convert them to the glibc equivalents.
> 
> 

This is something I considered a while back, when I was having problems
with %l truncating 64-bit LONG_PTR values. The problem with it is that
if we introduce custom changes to the format string, we lose the ability
to use __attribute__((format(printf))), which I think is pretty valuable.

> Cheers,
> 

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://www.winehq.org/pipermail/wine-devel/attachments/20200919/f69b275c/attachment.sig>


More information about the wine-devel mailing list