Why do backend pass definitions call a seperate function just to call the constructor?

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.