John Emmas via llvm-dev
2021-Dec-03 16:21 UTC
[llvm-dev] [UPDATE] Disabling inline compilation (Clang with VS2019)
Just an update to a long gone thread.... Back in September I flagged up some problematic code which was building fine with MSVC but failing to link when built with Visual Studio and Clang. In the end, it turned out to be a typo at my end but along the way we discovered a difference in the way that MSVC and Clang will each treat functions declared using '__declspec(dllimport) ' Basically, Clang was sometimes trying to inline them when MSVC wasn't (I've added the relevant part of the discussion below...) The devs here said they'd be happy to make Clang's behaviour match MSVC but that it was traditionally hard to find out what Visual Studio's 'rules' are. So I posted a question on the VS developer forum - and 3 months later, Microsoft's own devs have finally replied:- https://developercommunity.visualstudio.com/t/__declspecdllimport-and-inline-abili/1537756#T-ND1602459 I know it's ancient history now but given that the situation's been clarified at last, I figured I might as well feed it back here. Basically, although the rules can change over time, currently (for dllimport functions) MSVC carries out 2 simple tests when deciding whether or not they can be candidates for inlining:- 1) the MSVC optimizer won't inline a candidate if that candidate calls some other function - and/or 2) the MSVC optimizer won't inline a candidate if that candidate accesses a global variable For class variables, a static member is treated as being a global variable. Like I said, I know it's all a long gone problem but I figured Microsoft's reply would be worth flagging up. Hope it all helps, John On 22/09/2021 13:53, Eric Astor wrote:> I've transferred John's example into Compiler Explorer, which will > hopefully be a useful demonstration. Both clang and MSVC handle the > dllexport case identically... but they do differ in the dllimport > case: https://godbolt.org/z/vTrEevY8o > > Just as John suggested, disassembling the output shows that clang is > inlining this function, even at -O1, where MSVC doesn't, even at /O3. > > I'd agree that this isn't a great match, though it *is* a point of > ambiguity in the handling of __declspec(dllimport). > > > On 22/09/2021 13:22, John Emmas wrote: >> Hi there - I first asked this question over on clang-users but I >> got advised to ask it here (sorry about the length...) >> >> I'm a VS2019 user and I've been trying to switch it here to use >> Clang as the compiler, rather than MSVC. But I seem to have hit a >> common problem. Consider the following code:- >> >> #if defined (BUILDING_DLL) >> #define DLL_API __declspec(dllexport) >> #else >> #define DLL_API __declspec(dllimport) >> #endif >> >> namespace Gtkmm2ext { >> >> class DLL_API Keyboard >> { >> public: >> Keyboard (); >> ~Keyboard (); >> >> static Keyboard& get_keyboard() { return *_the_keyboard; } >> >> protected: >> static Keyboard* _the_keyboard; >> }; >> >> } /* namespace */ >> >> The above code is from a DLL which gets used by an exe. The DLL >> compiles and links just fine and the exe compiles. But when I >> try to link the exe, Clang's linker complains that it can't find >> '_the_keyboard' >> >> But here's the thing... '_the_keyboard' is an internal variable >> that's private to the DLL. It should never need to get accessed >> by the exe. If I change 'get_keyboard()' to be just a >> declaration (and then implement it in a DLL source file) Clang is >> then happy - but unfortunately, this is one of several hundred >> similar linker errors. >> >> So I'm wondering if (maybe) the compiler implemented its call to >> 'get_keyboard()' as inline code, rather than importing it from >> the DLL? Maybe for very simple code like this, Clang is trying >> to be clever and implement stuff inline if it can? >> >> VS2019 can disable inline code via a compiler option called >> "/Ob0" - and typing "clang-cl /?" indicates that "/Ob0" is >> supported. But I still see the error, even if I specify "/Ob0" >> during compilation. >> >> So will "/Ob0" disable all inline compilation for Clang? Or does >> it only take effect where there's an actual 'inline' keyword? >> Hope that all makes sense... >> >> John >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20211203/2ee31dab/attachment.html>
Reid Kleckner via llvm-dev
2021-Dec-06 18:37 UTC
[llvm-dev] [UPDATE] Disabling inline compilation (Clang with VS2019)
Thanks for asking about the rules. I think, at the moment, we should leave clang's dllimport+inline heuristics alone, but we should at least document our behavior, perhaps in AttributeReference.html <https://clang.llvm.org/docs/AttributeReference.html>. On Fri, Dec 3, 2021 at 8:21 AM John Emmas via llvm-dev < llvm-dev at lists.llvm.org> wrote:> Just an update to a long gone thread.... > > Back in September I flagged up some problematic code which was building > fine with MSVC but failing to link when built with Visual Studio and Clang. > In the end, it turned out to be a typo at my end but along the way we > discovered a difference in the way that MSVC and Clang will each treat > functions declared using '__declspec(dllimport) ' Basically, Clang was > sometimes trying to inline them when MSVC wasn't (I've added the relevant > part of the discussion below...) > > The devs here said they'd be happy to make Clang's behaviour match MSVC > but that it was traditionally hard to find out what Visual Studio's 'rules' > are. So I posted a question on the VS developer forum - and 3 months > later, Microsoft's own devs have finally replied:- > > > https://developercommunity.visualstudio.com/t/__declspecdllimport-and-inline-abili/1537756#T-ND1602459 > > I know it's ancient history now but given that the situation's been > clarified at last, I figured I might as well feed it back here. Basically, > although the rules can change over time, currently (for dllimport > functions) MSVC carries out 2 simple tests when deciding whether or not > they can be candidates for inlining:- > > 1) the MSVC optimizer won't inline a candidate if that candidate calls > some other function - and/or > > 2) the MSVC optimizer won't inline a candidate if that candidate > accesses a global variable > > For class variables, a static member is treated as being a global variable. > > Like I said, I know it's all a long gone problem but I figured Microsoft's > reply would be worth flagging up. Hope it all helps, > > John > > > On 22/09/2021 13:53, Eric Astor wrote: > > I've transferred John's example into Compiler Explorer, which will > hopefully be a useful demonstration. Both clang and MSVC handle the > dllexport case identically... but they do differ in the dllimport case: > https://godbolt.org/z/vTrEevY8o > > Just as John suggested, disassembling the output shows that clang is > inlining this function, even at -O1, where MSVC doesn't, even at /O3. > > I'd agree that this isn't a great match, though it *is* a point of > ambiguity in the handling of __declspec(dllimport). > > > On 22/09/2021 13:22, John Emmas wrote: >> >> Hi there - I first asked this question over on clang-users but I got >> advised to ask it here (sorry about the length...) >> >> I'm a VS2019 user and I've been trying to switch it here to use Clang as >> the compiler, rather than MSVC. But I seem to have hit a common problem. >> Consider the following code:- >> >> #if defined (BUILDING_DLL) >> #define DLL_API __declspec(dllexport) >> #else >> #define DLL_API __declspec(dllimport) >> #endif >> >> namespace Gtkmm2ext { >> >> class DLL_API Keyboard >> { >> public: >> Keyboard (); >> ~Keyboard (); >> >> static Keyboard& get_keyboard() { return *_the_keyboard; } >> >> protected: >> static Keyboard* _the_keyboard; >> }; >> >> } /* namespace */ >> >> The above code is from a DLL which gets used by an exe. The DLL compiles >> and links just fine and the exe compiles. But when I try to link the exe, >> Clang's linker complains that it can't find '_the_keyboard' >> >> But here's the thing... '_the_keyboard' is an internal variable that's >> private to the DLL. It should never need to get accessed by the exe. If I >> change 'get_keyboard()' to be just a declaration (and then implement it in >> a DLL source file) Clang is then happy - but unfortunately, this is one of >> several hundred similar linker errors. >> >> So I'm wondering if (maybe) the compiler implemented its call to >> 'get_keyboard()' as inline code, rather than importing it from the DLL? >> Maybe for very simple code like this, Clang is trying to be clever and >> implement stuff inline if it can? >> >> VS2019 can disable inline code via a compiler option called "/Ob0" - and >> typing "clang-cl /?" indicates that "/Ob0" is supported. But I still see >> the error, even if I specify "/Ob0" during compilation. >> >> So will "/Ob0" disable all inline compilation for Clang? Or does it only >> take effect where there's an actual 'inline' keyword? Hope that all makes >> sense... >> >> John >> >> >> > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20211206/b7119314/attachment-0001.html>