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>
Hans Wennborg via llvm-dev
2021-Dec-07 16:12 UTC
[llvm-dev] [UPDATE] Disabling inline compilation (Clang with VS2019)
Adding a note here: https://reviews.llvm.org/D115252 On Mon, Dec 6, 2021 at 7:38 PM Reid Kleckner via llvm-dev <llvm-dev at lists.llvm.org> wrote:> > 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. > > 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 > > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev