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
John Emmas via llvm-dev
2021-Dec-08 09:51 UTC
[llvm-dev] [UPDATE] Disabling inline compilation (Clang with VS2019)
On 07/12/2021 16:12, Hans Wennborg wrote:> Adding a note here:https://reviews.llvm.org/D115252 >Many thanks everyone, So if I'm understanding this correctly, the difference in my original example below must be that (for MSVC) a static class member variable gets categorized as if it was a global variable - whereas (for Clang) it doesn't? John On 22/09/2021 13:22, John Emmas wrote:> > #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; } // > <--- inlined by clang but not by msvc > > protected: > static Keyboard* _the_keyboard; > }; > > } /* namespace */ >