Support clang plugins on Windows

Description of the project: The Clang compiler is part of the LLVM compiler infrastructure and supports various languages such as C, C++, ObjC and ObjC++. The design of LLVM and Clang allows the compiler to be extended with plugins[1]. A plugin makes it possible to run extra user defined actions during a compilation. Plugins are supported on unix and darwin but not on windows due to some specifics on the windows platform.

The general work that needs to be done is to annotate all the public API surface with __declspec(dllexport) and similar if they are being built as a dynamically linked library (and nothing if being built statically). When the library is being consumed the attribute on the same declaration must be __declspec(dllimport) or the same spelling for the GNU version for ELF and MachO. Note that the attribute changes between the implementation and consumer and between static and dynamic linking. This is normally controlled by expansion to a macro.

Expected result: This project aims to allow make clang -fplugin=windows/plugin.dll work. The implementation approach should extend the working prototype [3] and extend the annotation tool [4]. The successful candidate should be prepared to attend a weekly meeting, make presentations and prepare blog posts upon request.

Further reading [1] https://clang.llvm.org/docs/ClangPlugins.html

[2] https://discourse.llvm.org/t/clang-plugins-on-windows

[3] https://github.com/llvm/llvm-project/pull/67502

[4] https://github.com/compnerd/ids

Project size:Either medium or large.

Difficulty: Medium

Confirmed Mentor: Vassil Vassilev, Saleem Abdulrasool

3 Likes

Hi @vvassilev,
what are the required skills for this project?
and what are the areas of LLVM that I will work on If I get accepted?

Thanks

Hi @Mohamed,

@compnerd would be probably better at answering that. I think one needs to know well windows, its linking model and to have experience with low-level tools. You will be working mostly on the llvm and clang codebases.

Best, Vassil

Hi @compnerd @vvassilev in order for a proposal to be credibile which specific parts of the codebase woud you want me to contribute to? Any tips youcould share with me would be great.
Thanks

Yes, definitely would be helpful to have an understanding of low-level tools, in particular, link, objdump, llvm-readobj, ar, as well as object file formats, at the very least ELF and COFF, MachO is likely a good thing. More than knowing Windows, I would say that an understanding of Unix is likely helpful too.

I would say that LLVM, clang, LLDB, and LLD codebases are the ones to expect to be involved in.

I would say at the very least, LLVM, but I wouldn’t be surprised if it crosses across clang, clang tools extras, and lldb.

@tstellar did you ever publish your changes to compnerd’s ids tool anywhere? and what was the issue you were having that you disabled LLVM_CLASS_ABI for windows?

I had to disable LLVM_CLASS_ABI due to a combination of these two issues:

I’ll try to publish those changes to ids somewhere.

So explicitly deleted copy constructor and assignment operators need to be generated for classes with non copyable data so dllexport doesn’t try to instantiate them?

I think that’s right. It’s a lot hard to do than it sounds, though. But I wouldn’t object if someone wanted to try.

Here is my fork of ids: GitHub - tstellar/ids at annotate-classes

And the script I used to run it:

for f in `find /home/fedora/llvm-project/clang/lib/ /home/fedora/llvm-project/llvm/tools/ /home/fedora/llvm-project/llvm/unittests/ /home/fedora/llvm-project/lld/ /home/fedora/llvm-project/lldb/ -iname '*.cpp' -o -iname '*.c'`; do \
  echo $f;
  ./build/bin/idt -p /home/fedora/llvm-project/abi-build/ $f  --extra-arg "-I/home/fedora/llvm-install/lib/clang/17/include/" --extra-arg '-DLLVM_ABI=__attribute__((__visibility__("default")))' --extra-arg '-fvisibility=hidden' --extra-arg '-DLLVM_FUNC_ABI=LLVM_ABI' --extra-arg '-DLLVM_CLASS_ABI=LLVM_ABI' --apply-fixits --inplace --export-macro=LLVM_ABI;
done

@tstellar Do you think the correct fix for compile errors from templated base class functions being instantiated by dllexport even though the function is not supported in particular context is to declare them with std::enable_if? Some example classes this happens with is iterator_facade_base for llvm::sys:path::const_iterator and ilist_node_impl::isSentinel for various IR types.
A common patten seems to be that the problematic functions have a static_assert on same condition that enable_if would use.

@fsfod You may want to look at this thread on Discord where we discussed various solutions, for example.

I’m not very knowledgeable about C++ so I can’t really offer much more insight.

I’ve given this problem a bit of work locally, and found that cmake provides WINDOWS_EXPORT_ALL_SYMBOLS. While it doesn’t cover global variables it will handle functions and classes, it reduces the diff size quite a lot. although I’m not sure if people would find it appropriate to export everything like this, especially with how many symbols llvm has and dlls hard limit of UINT16_MAX exported symbols.

That is how the existing python script works, but as you guessed it has to workaround the DLL exported symbol limit by trying to filter down the exports based on name mangling to only export some symbol types. But it seems to have issues with missing symbols and doesn’t work for importing data symbols based on some past mailing list threads.

I’ve been continuing to work on this for a while and have a few changesets. I feel it would be best to start by annotating libraries bottom up. with LLVMDemangle, LLVMSupport, and LLVMOption to keep changesets small. I’ve also been annotating variables and classes that should be kept internal to these libraries as hidden to reduce export table sizes, which would be valuable even if dynamic linking doesnt make it in.