What does `swift -frontend -merge-modules` actually do?

Out of curiosity I was taking a look at the verbose output of swift build to see how the build process works, and I see that there's this merge modules step before my executable is generated. What's actually happening here, and why is it done?

Also, what exactly is the swift "frontend"? I see that referenced several times in the process, but it's not clear to me what it is.

The front end of the compiler is the part of the compiler that does lexical, syntax, and semantic analysis of your code. It starts with the source code, and converts it into an abstract syntax tree, which is passed to the backend which does optimization and machine language generation.

2 Likes

The frontend is the part of the Swift executable that actually compiles things. This is as opposed to the driver, which looks at the set of input files and figures out what work (including frontend jobs, but also linkers and other tools) is needed to build the project. There’s a project underway to port the driver to Swift.

A Swift “module” is basically a binary equivalent of a header file. In incremental mode, the frontend produces a “partial” module for each source file in the project, in much the same way that it produces a .o file for each source file. The merge modules phase merges the partial modules together into a single one representing all of the files combined, sort of like a linker for these module files.

3 Likes

Interesting, thanks. So what's the devision of responsibilities exactly? Does the frontend just create the AST, or does it get as far as LLVM IR?

Thanks for clarifying. So if I understand correctly, this is only required in incremental mode, and this is only merging partial modules into a top-level module, not, for instance, merging dependency modules into the output module, correct?

As far as I understand it, the front-end generates the AST. The SILGen pass takes the AST, performs various Swift-specific optimizations, and generates a Swift Intermediate Language (SIL) representation. The IRGen phase takes the SIL representations, does more optimizations, and generates LLVM IR. Then, that is passed off to the LLVM backend libraries for more low-level optimizations and machine code generation.

2 Likes

Right. In WMO mode, we spin off one or two frontend processes which produce an object file and swiftmodule file for the entire module in one shot. In incremental mode, we spin off one frontend process per source file, which each produce one object file and one swiftmodule file, then link together the object files and merge the module files.

1 Like