[llvm-dev] Why do backend pass definitions call a seperate function just to call the constructor?

David Chisnall via llvm-dev llvm-dev at lists.llvm.org
Wed Jan 17 04:20:21 PST 2018

On 16 Jan 2018, at 21:32, Tim Northover via llvm-dev <llvm-dev at lists.llvm.org> wrote:
> On 16 January 2018 at 20:40, Ahmed Samara via llvm-dev
> <llvm-dev at lists.llvm.org> wrote:
>> Things like this in `lib/Target/ARM/ARMExpandPseudoInsts.cpp`
>>> FunctionPass *llvm::createARMExpandPseudoPass() {
>>>  return new ARMExpandPseudo();
>>> }
>> And other functions have basically the same style.
>> What's the point of doing it this way instead of just calling `new
>> ARMExpandPseudo` in any place that you would have called this function?
> Mostly it's so that everything that relies on knowing the class
> definition and layout is restricted to a single file. The interface to
> the rest of LLVM is just a single "createXYZ" standalone function.
> That speeds up build times and is generally good for abstraction.

To give a little bit more detail:

Note, specifically, that the return type of these functions is something like Pass or FunctionPass.  This prevents any accidental leakage of implementation details of the pass outside of its implementation file.

If you look at the implementation of most passes, you will see that they are in the anonymous namespace.  The only way of interacting with them from any other compilation unit is to call these factory functions and then invoke methods via the vtable, overridden from a public superclass.

As Tim says, this speeds up build times because, LTO-aside, no other compilation unit changes if you modify a pass.  If you add a field to a pass and then rerun ninja, you will see that you recompile one file and then relink everything that it depends on, but nothing else.  In contrast, if you add a field to a class in one of the LLVM headers, then you will often recompile a few hundred files.

This also (again, as Tim says) gives loose coupling between the passes and the rest of LLVM.  Things running passes are never exposed to any of the implementation details of a pass, they know only about a standard set of interfaces.


More information about the llvm-dev mailing list