<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.2.0">Jekyll</generator><link href="https://modocache.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://modocache.io/" rel="alternate" type="text/html" /><updated>2023-02-04T22:49:57+00:00</updated><id>https://modocache.io/feed.xml</id><title type="html">modocache.io</title><subtitle>Articles written by Brian Gesiak, a software engineer specializing in programming languages and compilers.
</subtitle><entry><title type="html">How the Swift Compiler Emits Diagnostics, Part 2: Swift's Wrappers of LLVM Abstractions</title><link href="https://modocache.io/swift-compiler-diagnostics-part-2" rel="alternate" type="text/html" title="How the Swift Compiler Emits Diagnostics, Part 2: Swift's Wrappers of LLVM Abstractions" /><published>2018-06-01T18:00:00+00:00</published><updated>2018-06-01T18:00:00+00:00</updated><id>https://modocache.io/swift-compiler-diagnostics-part-2</id><content type="html" xml:base="https://modocache.io/swift-compiler-diagnostics-part-2">&lt;p&gt;In the last two articles in this series on Swift compiler development, I wrote about the abstractions provided by LLVM to emit diagnostics. &lt;a href=&quot;/swift-compiler-diagnostics-part-1&quot;&gt;How the Swift Compiler Emits Diagnostics, Part 1&lt;/a&gt; explained how the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;&lt;/code&gt; class prints diagnostic messages along with lines of source code in an &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt;. Then I wrote about the internals of that &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt; class in &lt;a href=&quot;/llvm-memory-buffer&quot;&gt;How Swift and Clang Use LLVM to Read Files into Memory&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this article, I explain how these abstractions come together in the Swift compiler. Specifically, I'll cover:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;How the Swift frontend reads source files in as &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt; instances.&lt;/li&gt;
  &lt;li&gt;How the Swift frontend registers those buffers with a &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceManager&lt;/span&gt;&lt;/code&gt;, a libswiftBasic wrapper around &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;How the Swift lexer records &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceLoc&lt;/span&gt;&lt;/code&gt; locations as attributes on the tokens it lexes. (&lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceLoc&lt;/span&gt;&lt;/code&gt; is defined in libswiftBasic, as a wrapper around &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt;&lt;/code&gt;.)&lt;/li&gt;
  &lt;li&gt;How the Swift parser instructs &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;DiagnosticEngine&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceManager&lt;/span&gt;&lt;/code&gt; to print a diagnostic in the event it has encountered a parse error.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It's these mechanisms above that result in the printing of the parser error I wrote about in the last article:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;uhoh.swift&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;1  &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;// uhoh.swift&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;3  &lt;/span&gt;&lt;span class=&quot;fs&quot;&gt;print&lt;/span&gt;((&lt;span class=&quot;s&quot;&gt;&quot;Yikes.&quot;&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;pre&gt;
&lt;span class=&quot;cmd&quot;&gt;swiftc&lt;/span&gt; uhoh.swift
&lt;span class=&quot;diag&quot;&gt;uhoh.swift:3:17: &lt;span class=&quot;de&quot;&gt;error:&lt;/span&gt; expected ')' in expression list&lt;/span&gt;
print((&quot;Yikes.&quot;)
                &lt;span class=&quot;dc&quot;&gt;^&lt;/span&gt;
&lt;span class=&quot;diag&quot;&gt;uhoh.swift:3:6: &lt;span class=&quot;dn&quot;&gt;note:&lt;/span&gt; to match this opening '('&lt;/span&gt;
print((&quot;Yikes.&quot;)
     &lt;span class=&quot;dc&quot;&gt;^&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;Finally, this article will write about how the Swift compiler defines its diagnostics strings – for example, the &lt;code&gt;&lt;span class=&quot;s&quot;&gt;&quot;expected ')' in expression list&quot;&lt;/span&gt;&lt;/code&gt; string above – by using macros. This is similar to the way token kinds are defined, as described in my article &lt;a href=&quot;/the-swift-frontend-lexing-and-parsing&quot;&gt;Getting Started with the Swift Frontend: Lexing &amp;amp; Parsing&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;step-1-creating-an-llvmmemorybuffer-for-each-input-source-file&quot;&gt;Step 1: Creating an &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt; for each input source file&lt;/h2&gt;

&lt;p&gt;My article &lt;a href=&quot;/introduction-to-the-swift-compiler-driver&quot;&gt;An Introduction to the Swift Compiler Driver&lt;/a&gt; explained how an invocation of &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt;&lt;/code&gt; is normally split up, by libswiftDriver, into a series of &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;cmd&quot;&gt;ld&lt;/span&gt;&lt;/code&gt; linker invocations. And in &lt;a href=&quot;/the-swift-frontend-lexing-and-parsing&quot;&gt;Getting Started with the Swift Frontend: Lexing &amp;amp; Parsing&lt;/a&gt;, I explained how an invocation of &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt; results in libswiftFrontendTool and libswiftFrontend instantiating a &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;CompilerInvocation&lt;/span&gt;&lt;/code&gt;, parsing command-line arguments via the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;CompilerInvocation&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseArgs&lt;/span&gt;&lt;/code&gt; member function, and then using those parsed arguments to instantiate a &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;&lt;/code&gt;. To recap, here's that code again:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/FrontendTool/FrontendTool.cpp#L1304-L1542&quot;&gt;swift/lib/FrontendTool/FrontendTool.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;1304  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::performFrontend(&lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;const char&lt;/span&gt; *&amp;gt; Args,
&lt;span class=&quot;ln&quot;&gt;1305  &lt;/span&gt;                           &lt;span class=&quot;k&quot;&gt;const char&lt;/span&gt; *Argv0, &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; *MainAddr,
&lt;span class=&quot;ln&quot;&gt;1306  &lt;/span&gt;                           &lt;span class=&quot;cl&quot;&gt;FrontendObserver&lt;/span&gt; *observer) {
&lt;span class=&quot;ln&quot;&gt;....  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1348  &lt;/span&gt;  &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;&amp;gt; Instance =
&lt;span class=&quot;ln&quot;&gt;1349  &lt;/span&gt;    &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;make_unique&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;&amp;gt;();
&lt;span class=&quot;ln&quot;&gt;....  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1371  &lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;CompilerInvocation&lt;/span&gt; Invocation;
&lt;span class=&quot;ln&quot;&gt;....  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1379  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// Parse arguments.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1380  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;vi&quot;&gt;Invocation&lt;/span&gt;.&lt;span class=&quot;f&quot;&gt;parseArgs&lt;/span&gt;(Args, Instance-&amp;gt;&lt;span class=&quot;f&quot;&gt;getDiags&lt;/span&gt;(), workingDirectory)) {
&lt;span class=&quot;ln&quot;&gt;1381  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;f&quot;&gt;finishDiagProcessing&lt;/span&gt;(&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;1382  &lt;/span&gt;  }
&lt;span class=&quot;ln&quot;&gt;....  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1464  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (Instance-&amp;gt;&lt;span class=&quot;f&quot;&gt;setup&lt;/span&gt;(Invocation)) {
&lt;span class=&quot;ln&quot;&gt;1465  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;f&quot;&gt;finishDiagProcessing&lt;/span&gt;(&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;1466  &lt;/span&gt;  }
&lt;span class=&quot;ln&quot;&gt;....  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1542  &lt;/span&gt;}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;In &lt;a href=&quot;/the-swift-frontend-lexing-and-parsing&quot;&gt;Getting Started with the Swift Frontend: Lexing &amp;amp; Parsing&lt;/a&gt;, I pointed out that the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;setup&lt;/span&gt;&lt;/code&gt; function instantiated a &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;ASTContext&lt;/span&gt;&lt;/code&gt; object (a crucially important object that represents the syntax tree of the Swift program being compiled). But it's also in this function that source files are read into &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt; objects. The &lt;code&gt;&lt;span class=&quot;f&quot;&gt;setup&lt;/span&gt;&lt;/code&gt; function calls through to &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;setUpInputs&lt;/span&gt;&lt;/code&gt;, which calls &lt;code&gt;&lt;span class=&quot;f&quot;&gt;setUpForInput&lt;/span&gt;&lt;/code&gt;, and so on, until eventually &lt;code&gt;&lt;span class=&quot;f&quot;&gt;getInputBufferAndModuleDocBufferIfPresent&lt;/span&gt;&lt;/code&gt; instantiates an &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt; via the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getFileOrSTDIN&lt;/span&gt;&lt;/code&gt; function (which I explained in detail in &lt;a href=&quot;/llvm-memory-buffer&quot;&gt;the last article&lt;/a&gt;):&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/1da70a01cc40958fa3cc64708d78d6bee71f32fa/lib/Frontend/Frontend.cpp#L135-L342&quot;&gt;swift/lib/Frontend/Frontend.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;135  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::setup(&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;CompilerInvocation&lt;/span&gt; &amp;amp;Invok) {
&lt;span class=&quot;ln&quot;&gt;136  &lt;/span&gt;  &lt;span class=&quot;vi&quot;&gt;Invocation&lt;/span&gt; = Invok;
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;164  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;f&quot;&gt;setUpInputs&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;165  &lt;/span&gt;}
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;238  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::setUpInputs() {
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;243  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;InputFile&lt;/span&gt; &amp;amp;input :
&lt;span class=&quot;ln&quot;&gt;244  &lt;/span&gt;       &lt;span class=&quot;vi&quot;&gt;Invocation&lt;/span&gt;.&lt;span class=&quot;f&quot;&gt;getFrontendOptions&lt;/span&gt;().&lt;span class=&quot;vi&quot;&gt;InputsAndOutputs&lt;/span&gt;.&lt;span class=&quot;f&quot;&gt;getAllInputs&lt;/span&gt;())
&lt;span class=&quot;ln&quot;&gt;245  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;f&quot;&gt;setUpForInput&lt;/span&gt;(input))
&lt;span class=&quot;ln&quot;&gt;246  &lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;260  &lt;/span&gt;}
&lt;span class=&quot;ln&quot;&gt;261  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;262  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::setUpForInput(&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;InputFile&lt;/span&gt; &amp;amp;input) {
&lt;span class=&quot;ln&quot;&gt;263  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; failed = &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;264  &lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;Optional&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt;&amp;gt; bufferID = &lt;span class=&quot;f&quot;&gt;getRecordedBufferID&lt;/span&gt;(input, failed);
&lt;span class=&quot;ln&quot;&gt;265  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (failed)
&lt;span class=&quot;ln&quot;&gt;266  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;280  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;281  &lt;/span&gt;}
&lt;span class=&quot;ln&quot;&gt;282  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;283  &lt;/span&gt;&lt;span class=&quot;cl&quot;&gt;Optional&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt;&amp;gt; &lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::getRecordedBufferID(&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;InputFile&lt;/span&gt; &amp;amp;input,
&lt;span class=&quot;ln&quot;&gt;284  &lt;/span&gt;                                                         &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; &amp;amp;failed) {
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;291  &lt;/span&gt;  &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;pair&lt;/span&gt;&amp;lt;&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&amp;gt;,
&lt;span class=&quot;ln&quot;&gt;292  &lt;/span&gt;            &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&amp;gt;&amp;gt;
&lt;span class=&quot;ln&quot;&gt;293  &lt;/span&gt;      buffers = &lt;span class=&quot;f&quot;&gt;getInputBufferAndModuleDocBufferIfPresent&lt;/span&gt;(input);
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;308  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// Transfer ownership of the MemoryBuffer to the SourceMgr.&lt;/span&gt;
&lt;div class=&quot;hi&quot;&gt;&lt;span class=&quot;ln&quot;&gt;309  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt; bufferID = &lt;span class=&quot;vi&quot;&gt;SourceMgr&lt;/span&gt;.&lt;span class=&quot;f&quot;&gt;addNewSourceBuffer&lt;/span&gt;(&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;move&lt;/span&gt;(buffers.&lt;span class=&quot;fs&quot;&gt;first&lt;/span&gt;));&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;313  &lt;/span&gt;}
&lt;span class=&quot;ln&quot;&gt;314  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;315  &lt;/span&gt;&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;pair&lt;/span&gt;&amp;lt;&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&amp;gt;,
&lt;span class=&quot;ln&quot;&gt;316  &lt;/span&gt;          &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&amp;gt;&amp;gt;
&lt;span class=&quot;ln&quot;&gt;317  &lt;/span&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::getInputBufferAndModuleDocBufferIfPresent(
&lt;span class=&quot;ln&quot;&gt;318  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;InputFile&lt;/span&gt; &amp;amp;input) {
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;326  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; FileOrError = &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;ErrorOr&lt;/span&gt;&amp;lt;&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&amp;gt;&amp;gt;;
&lt;div class=&quot;hi&quot;&gt;&lt;span class=&quot;ln&quot;&gt;327  &lt;/span&gt;  &lt;span class=&quot;t&quot;&gt;FileOrError&lt;/span&gt; inputFileOrErr = &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getFileOrSTDIN&lt;/span&gt;(input.&lt;span class=&quot;f&quot;&gt;file&lt;/span&gt;());&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt;328  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (!inputFileOrErr) {
&lt;span class=&quot;ln&quot;&gt;329  &lt;/span&gt;    &lt;span class=&quot;v&quot;&gt;Diagnostics&lt;/span&gt;.&lt;span class=&quot;f&quot;&gt;diagnose&lt;/span&gt;(&lt;span class=&quot;cl&quot;&gt;SourceLoc&lt;/span&gt;(), &lt;span class=&quot;t&quot;&gt;diag&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;error_open_input_file&lt;/span&gt;, input.&lt;span class=&quot;f&quot;&gt;file&lt;/span&gt;(),
&lt;span class=&quot;ln&quot;&gt;330  &lt;/span&gt;                         inputFileOrErr.&lt;span class=&quot;f&quot;&gt;getError&lt;/span&gt;().&lt;span class=&quot;f&quot;&gt;message&lt;/span&gt;());
&lt;span class=&quot;ln&quot;&gt;331  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;make_pair&lt;/span&gt;(&lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;, &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;332  &lt;/span&gt;  }
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;342  &lt;/span&gt;}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Notice above that, after calling &lt;code&gt;&lt;span class=&quot;f&quot;&gt;getInputBufferAndModuleDocBufferIfPresent&lt;/span&gt;&lt;/code&gt; to instantiate an &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt;, the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getRecordedBufferID&lt;/span&gt;&lt;/code&gt; function adds the buffer to the source manager.&lt;/p&gt;

&lt;h2 id=&quot;step-2-registering-the-llvmmemorybuffer-with-the-swiftsourcemanager&quot;&gt;Step 2: Registering the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt; with the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceManager&lt;/span&gt;&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;The Swift codebase defines a library named libswiftBasic. It's the Swift codebase's equivalent of libLLVMSupport: a grab-bag of helper classes and functions without much in common.&lt;/p&gt;

&lt;p&gt;Included in this helper library are the Swift classes &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceManager&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceLoc&lt;/span&gt;&lt;/code&gt;, which wrap &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt;&lt;/code&gt;. They even define a lot of the same member functions, and in their implementations simply forward these along to the internal LLVM class – for example, &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceManager&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;addNewSourceBuffer&lt;/span&gt;&lt;/code&gt; simply calls through to &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;AddNewSourceBuffer&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/1da70a01cc40958fa3cc64708d78d6bee71f32fa/include/swift/Basic/SourceManager.h#L22-L236&quot;&gt;swift/include/swift/Basic/SourceManager.h&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt; 22  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; swift {
&lt;span class=&quot;ln&quot;&gt; 23  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 24  &lt;/span&gt;&lt;span class=&quot;d&quot;&gt;/// &lt;span class=&quot;dk&quot;&gt;\brief&lt;/span&gt; This class manages and owns source buffers.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 25  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; SourceManager {
&lt;span class=&quot;ln&quot;&gt; 26  &lt;/span&gt;  &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt; LLVMSourceMgr;
&lt;span class=&quot;ln&quot;&gt; ..  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;103  &lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// Adds a memory buffer to the SourceManager, taking ownership of it.&lt;/span&gt;
&lt;div class=&quot;hi&quot;&gt;&lt;span class=&quot;ln&quot;&gt;104  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt; addNewSourceBuffer(&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&amp;gt; Buffer);&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;234  &lt;/span&gt;};
&lt;span class=&quot;ln&quot;&gt;235  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;236  &lt;/span&gt;} &lt;span class=&quot;c&quot;&gt;// end namespace swift&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/1da70a01cc40958fa3cc64708d78d6bee71f32fa/lib/Basic/SourceLoc.cpp#L22-L236&quot;&gt;swift/lib/Basic/SourceLoc.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;42  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;43  &lt;/span&gt;&lt;span class=&quot;cl&quot;&gt;SourceManager&lt;/span&gt;::addNewSourceBuffer(&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&amp;gt; Buffer) {
&lt;span class=&quot;ln&quot;&gt;..  &lt;/span&gt;
&lt;div class=&quot;hi&quot;&gt;&lt;span class=&quot;ln&quot;&gt;46  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; ID = &lt;span class=&quot;vi&quot;&gt;LLVMSourceMgr&lt;/span&gt;.&lt;span class=&quot;f&quot;&gt;AddNewSourceBuffer&lt;/span&gt;(&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;move&lt;/span&gt;(Buffer), &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt;());&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt;..  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;49  &lt;/span&gt;}
&lt;/pre&gt;
&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;libswiftBasic wraps these LLVM abstractions in order to expose only some of their functions to the rest of the Swift codebase, or to add convenience methods. For example &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceLoc&lt;/span&gt;&lt;/code&gt; is documented as being defined mainly to deter other parts of the Swift codebase from calling &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getFromPointer&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;

  &lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/1da70a01cc40958fa3cc64708d78d6bee71f32fa/include/swift/Basic/SourceLoc.h#L28-L80&quot;&gt;swift/include/swift/Basic/SourceLoc.h&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;28  &lt;/span&gt;&lt;span class=&quot;d&quot;&gt;/// SourceLoc in swift is just an SMLoc.  We define it as a different type&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;29  &lt;/span&gt;&lt;span class=&quot;d&quot;&gt;/// (instead of as a typedef) just to remove the &quot;getFromPointer&quot; methods and&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;30  &lt;/span&gt;&lt;span class=&quot;d&quot;&gt;/// enforce purity in the Swift codebase.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;31  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; SourceLoc {
&lt;span class=&quot;ln&quot;&gt;..  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;80  &lt;/span&gt;};
&lt;/pre&gt;
&lt;/div&gt;
&lt;/blockquote&gt;

&lt;p&gt;So in step one above, after instantiating an &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt; in the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getInputBufferAndModuleDocBufferIfPresent&lt;/span&gt;&lt;/code&gt; function, the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getRecordedBufferID&lt;/span&gt;&lt;/code&gt; function calls &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceManager&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;addNewSourceBuffer&lt;/span&gt;&lt;/code&gt;, a trivial wrapper around &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;AddNewSourceBuffer&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceManager&lt;/span&gt;&lt;/code&gt; is stored as a member variable on &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;&lt;/code&gt;, called &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;SourceMgr&lt;/span&gt;&lt;/code&gt; – which is confusing, since that's the same spelling as the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;&lt;/code&gt; class. But one is an member variable, the other is a class.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/1da70a01cc40958fa3cc64708d78d6bee71f32fa/lib/Frontend/Frontend.cpp#L283-L313&quot;&gt;swift/lib/Frontend/Frontend.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;283  &lt;/span&gt;&lt;span class=&quot;cl&quot;&gt;Optional&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt;&amp;gt; &lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::getRecordedBufferID(&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;InputFile&lt;/span&gt; &amp;amp;input,
&lt;span class=&quot;ln&quot;&gt;284  &lt;/span&gt;                                                         &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; &amp;amp;failed) {
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;291  &lt;/span&gt;  &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;pair&lt;/span&gt;&amp;lt;&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&amp;gt;,
&lt;span class=&quot;ln&quot;&gt;292  &lt;/span&gt;            &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&amp;gt;&amp;gt;
&lt;span class=&quot;ln&quot;&gt;293  &lt;/span&gt;      buffers = &lt;span class=&quot;f&quot;&gt;getInputBufferAndModuleDocBufferIfPresent&lt;/span&gt;(input);
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;308  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// Transfer ownership of the MemoryBuffer to the SourceMgr.&lt;/span&gt;
&lt;div class=&quot;hi&quot;&gt;&lt;span class=&quot;ln&quot;&gt;309  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt; bufferID = &lt;span class=&quot;vi&quot;&gt;SourceMgr&lt;/span&gt;.&lt;span class=&quot;f&quot;&gt;addNewSourceBuffer&lt;/span&gt;(&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;move&lt;/span&gt;(buffers.&lt;span class=&quot;fs&quot;&gt;first&lt;/span&gt;));&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;313  &lt;/span&gt;}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;I explained in &lt;a href=&quot;/swift-compiler-diagnostics-part-1&quot;&gt;How the Swift Compiler Emits Diagnostics, Part 1: LLVM Abstractions&lt;/a&gt; how &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;&lt;/code&gt; prints diagnostics at locations in an &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt;. The Swift lexer is responsible for recording those locations, by instantiating &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceLoc&lt;/span&gt;&lt;/code&gt; objects (wrappers for &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt;&lt;/code&gt;) as it lexes tokens.&lt;/p&gt;

&lt;h2 id=&quot;step-3-recording-the-locations-of-lexed-tokens&quot;&gt;Step 3: Recording the locations of lexed tokens&lt;/h2&gt;

&lt;p&gt;In &lt;a href=&quot;/the-swift-frontend-lexing-and-parsing&quot;&gt;Getting Started with the Swift Frontend: Lexing &amp;amp; Parsing&lt;/a&gt; I wrote about how libswiftFrontend eventually calls &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseIntoSourceFile&lt;/span&gt;&lt;/code&gt;, which instantiates a &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;&lt;/code&gt;. The &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;&lt;/code&gt; initializer instantiates a new &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;&lt;/code&gt;, passing in the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceManager&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/Parse/Parser.cpp#L101-L120&quot;&gt;swift/lib/Parse/Parser.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;329&lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::Parser(&lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt; BufferID, &lt;span class=&quot;cl&quot;&gt;SourceFile&lt;/span&gt; &amp;amp;SF, &lt;span class=&quot;cl&quot;&gt;SILParserTUStateBase&lt;/span&gt; *SIL,
&lt;span class=&quot;ln&quot;&gt;330&lt;/span&gt;                 &lt;span class=&quot;cl&quot;&gt;PersistentParserState&lt;/span&gt; *PersistentState)
&lt;span class=&quot;ln&quot;&gt;331&lt;/span&gt;      : &lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;(
&lt;span class=&quot;ln&quot;&gt;332&lt;/span&gt;            &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;&amp;gt;(&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;(
&lt;div class=&quot;hi&quot;&gt;&lt;span class=&quot;ln&quot;&gt;333&lt;/span&gt;                SF.&lt;span class=&quot;f&quot;&gt;getASTContext&lt;/span&gt;().&lt;span class=&quot;vi&quot;&gt;LangOpts&lt;/span&gt;, SF.&lt;span class=&quot;f&quot;&gt;getASTContext&lt;/span&gt;().&lt;span class=&quot;vi&quot;&gt;SourceMgr&lt;/span&gt;,&lt;/div&gt;
&lt;div class=&quot;hi&quot;&gt;&lt;span class=&quot;ln&quot;&gt;334&lt;/span&gt;                BufferID, &amp;amp;SF.&lt;span class=&quot;f&quot;&gt;getASTContext&lt;/span&gt;().&lt;span class=&quot;vi&quot;&gt;Diags&lt;/span&gt;,&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt;335&lt;/span&gt;                &lt;span class=&quot;c&quot;&gt;/*InSILMode=*/&lt;/span&gt;SIL != &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;336&lt;/span&gt;                SF.&lt;span class=&quot;f&quot;&gt;getASTContext&lt;/span&gt;().&lt;span class=&quot;vi&quot;&gt;LangOpts&lt;/span&gt;.&lt;span class=&quot;vi&quot;&gt;AttachCommentsToDecls&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;337&lt;/span&gt;                    ? &lt;span class=&quot;t&quot;&gt;CommentRetentionMode&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;AttachToNextToken&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;338&lt;/span&gt;                    : &lt;span class=&quot;t&quot;&gt;CommentRetentionMode&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;None&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;339&lt;/span&gt;                SF.&lt;span class=&quot;f&quot;&gt;shouldKeepSyntaxInfo&lt;/span&gt;()
&lt;span class=&quot;ln&quot;&gt;340&lt;/span&gt;                    ? &lt;span class=&quot;t&quot;&gt;TriviaRetentionMode&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;WithTrivia&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;341&lt;/span&gt;                    : &lt;span class=&quot;t&quot;&gt;TriviaRetentionMode&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;WithoutTrivia&lt;/span&gt;)),
&lt;span class=&quot;ln&quot;&gt;342&lt;/span&gt;            SF, SIL, PersistentState) {}
&lt;/pre&gt;
&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;Besides the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceManager&lt;/span&gt;&lt;/code&gt;, the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;&lt;/code&gt; also takes a &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;DiagnosticEngine&lt;/span&gt;&lt;/code&gt; as a parameter to its initializer. This class is used to actually print the diagnostics – I'll cover it more in step 4 of this article.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In &lt;a href=&quot;/the-swift-frontend-lexing-and-parsing&quot;&gt;that article&lt;/a&gt; I also wrote about how the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;&lt;/code&gt; iterates over each character in its input memory buffer in order to form tokens. For example, if it finds the character &lt;code&gt;&lt;span class=&quot;ch&quot;&gt;'p'&lt;/span&gt;&lt;/code&gt; in its buffer, it'll attempt to lex an identifier. To do so, it advances its pointer into the buffer as long as it finds characters that form valid identifiers (&lt;code&gt;&lt;span class=&quot;ch&quot;&gt;'0'&lt;/span&gt;&lt;/code&gt; through &lt;code&gt;&lt;span class=&quot;ch&quot;&gt;'9'&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;ch&quot;&gt;'a'&lt;/span&gt;&lt;/code&gt; through &lt;code&gt;&lt;span class=&quot;ch&quot;&gt;'Z'&lt;/span&gt;&lt;/code&gt;, underscores, etc.). Once it can advance no further, it calls &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;formToken&lt;/span&gt;&lt;/code&gt; in order to reset the current &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Token&lt;/span&gt;&lt;/code&gt; with the correct source location.&lt;/p&gt;

&lt;p&gt;Here's the code that lexes an identifier and forms a token based on a pointer to its text:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/Parse/Lexer.cpp#L591-L604&quot;&gt;swift/lib/Parse/Lexer.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;591&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// lexIdentifier - Match [a-zA-Z_][a-zA-Z_$0-9]*&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;592&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;::lexIdentifier() {
&lt;span class=&quot;ln&quot;&gt;593&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;const char&lt;/span&gt; *TokStart = &lt;span class=&quot;vi&quot;&gt;CurPtr&lt;/span&gt;-&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;594&lt;/span&gt;    &lt;span class=&quot;vi&quot;&gt;CurPtr&lt;/span&gt; = TokStart;
&lt;span class=&quot;ln&quot;&gt;595&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; didStart = &lt;span class=&quot;f&quot;&gt;advanceIfValidStartOfIdentifier&lt;/span&gt;(&lt;span class=&quot;vi&quot;&gt;CurPtr&lt;/span&gt;, &lt;span class=&quot;vi&quot;&gt;BufferEnd&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;599&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// Lex [a-zA-Z_$0-9[[:XID_Continue:]]]*&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;600&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; (&lt;span class=&quot;f&quot;&gt;advanceIfValidContinuationOfIdentifier&lt;/span&gt;(&lt;span class=&quot;vi&quot;&gt;CurPtr&lt;/span&gt;, &lt;span class=&quot;vi&quot;&gt;BufferEnd&lt;/span&gt;));
&lt;span class=&quot;ln&quot;&gt;601&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;602&lt;/span&gt;    &lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt; Kind = &lt;span class=&quot;f&quot;&gt;kindOfIdentifier&lt;/span&gt;(&lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt;(TokStart, &lt;span class=&quot;vi&quot;&gt;CurPtr&lt;/span&gt;-TokStart), &lt;span class=&quot;vi&quot;&gt;InSILMode&lt;/span&gt;);
&lt;div class=&quot;hi&quot;&gt;&lt;span class=&quot;ln&quot;&gt;603&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;f&quot;&gt;formToken&lt;/span&gt;(Kind, TokStart);&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt;604&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Token&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getLoc&lt;/span&gt;&lt;/code&gt; member function can then be used to instantiate an &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceLoc&lt;/span&gt;&lt;/code&gt; based on the buffer pointer:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/include/swift/Parse/Token.h#L34-L280&quot;&gt;swift/include/swift/Parse/Token.h&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt; 34  &lt;/span&gt;class Token {
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;221  &lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// getLoc - Return a source location identifier for the specified&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;222  &lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// offset in the current file.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;223  &lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;SourceLoc&lt;/span&gt; getLoc() &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; {
&lt;span class=&quot;ln&quot;&gt;224  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;SourceLoc&lt;/span&gt;(&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getFromPointer&lt;/span&gt;(&lt;span class=&quot;vi&quot;&gt;Text&lt;/span&gt;.&lt;span class=&quot;f&quot;&gt;begin&lt;/span&gt;()));
&lt;span class=&quot;ln&quot;&gt;225  &lt;/span&gt;  }
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;280  &lt;/span&gt;};
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;So that explains how the lexer constructs tokens and their locations, how the frontend instantiates memory buffers for each of the input files, and how those memory buffers are owned and managed by a &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceManager&lt;/span&gt;&lt;/code&gt;. Finally, the parser calls through to &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;PrintMessage&lt;/span&gt;&lt;/code&gt; in order to actually print the diagnostic – just as my sample program did in &lt;a href=&quot;/swift-compiler-diagnostics-part-1&quot;&gt;How the Swift Compiler Emits Diagnostics, Part 1&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But the Swift compiler uses several layers of indirection to do so: &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;DiagnosticEngine&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Diagnostic&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;InFlightDiagnostic&lt;/span&gt;&lt;/code&gt;, and more. The next and final step in this article writes about those classes in detail.&lt;/p&gt;

&lt;h2 id=&quot;step-4-printing-the-diagnostic&quot;&gt;Step 4: Printing the diagnostic&lt;/h2&gt;

&lt;p&gt;When the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;&lt;/code&gt; parses invalid Swift source code and determines it must print a diagnostic, it doesn't call &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;PrintMessage&lt;/span&gt;&lt;/code&gt; directly. As an example, let's take a closer look at the note diagnostic from the beginning of this article:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;diag&quot;&gt;uhoh.swift:3:6: &lt;span class=&quot;dn&quot;&gt;note:&lt;/span&gt; to match this opening '('&lt;/span&gt;
print((&quot;Yikes.&quot;)
     &lt;span class=&quot;dc&quot;&gt;^&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;This diagnostic is printed because the parser encounters the opening &lt;code&gt;&lt;span class=&quot;ch&quot;&gt;'('&lt;/span&gt;&lt;/code&gt; token, and its &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseMatchingToken&lt;/span&gt;&lt;/code&gt; function kicks off a loop that tries to parse an expression list and a closing &lt;code&gt;&lt;span class=&quot;ch&quot;&gt;')'&lt;/span&gt;&lt;/code&gt; token. If a closing &lt;code&gt;&lt;span class=&quot;ch&quot;&gt;')'&lt;/span&gt;&lt;/code&gt; token isn't found, it calls &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;diagnose&lt;/span&gt;&lt;/code&gt;, passing in two arguments: the location of the &lt;code&gt;&lt;span class=&quot;ch&quot;&gt;'('&lt;/span&gt;&lt;/code&gt; token, and the diagnostic to print:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/Parse/Parser.cpp#L858-L878&quot;&gt;swift/lib/Parse/Parser.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt; 858  &lt;/span&gt;&lt;span class=&quot;d&quot;&gt;/// parseMatchingToken - Parse the specified expected token and return its&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 859  &lt;/span&gt;&lt;span class=&quot;d&quot;&gt;/// location on success.  On failure, emit the specified error diagnostic, and a&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 860  &lt;/span&gt;&lt;span class=&quot;d&quot;&gt;/// note at the specified note location.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 861  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::parseMatchingToken(&lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt; K, &lt;span class=&quot;cl&quot;&gt;SourceLoc&lt;/span&gt; &amp;amp;TokLoc, &lt;span class=&quot;cl&quot;&gt;Diag&lt;/span&gt;&amp;lt;&amp;gt; ErrorDiag,
&lt;span class=&quot;ln&quot;&gt; 862  &lt;/span&gt;                                &lt;span class=&quot;cl&quot;&gt;SourceLoc&lt;/span&gt; OtherLoc) {
&lt;div class=&quot;hi&quot;&gt;&lt;span class=&quot;ln&quot;&gt; 863  &lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;Diag&lt;/span&gt;&amp;lt;&amp;gt; OtherNote;&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt; 864  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; (K) {
&lt;div class=&quot;hi&quot;&gt;&lt;span class=&quot;ln&quot;&gt; 865  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;r_paren&lt;/span&gt;:  OtherNote = &lt;span class=&quot;t&quot;&gt;diag&lt;/span&gt;::&lt;span class=&quot;vg&quot;&gt;opening_paren&lt;/span&gt;;    &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;;&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt; 866  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;r_square&lt;/span&gt;: OtherNote = &lt;span class=&quot;t&quot;&gt;diag&lt;/span&gt;::&lt;span class=&quot;vg&quot;&gt;opening_bracket&lt;/span&gt;;  &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt; 867  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;r_brace&lt;/span&gt;:  OtherNote = &lt;span class=&quot;t&quot;&gt;diag&lt;/span&gt;::&lt;span class=&quot;vg&quot;&gt;opening_brace&lt;/span&gt;;    &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt; 868  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;default:&lt;/span&gt;            &lt;span class=&quot;f&quot;&gt;llvm_unreachable&lt;/span&gt;(&lt;span class=&quot;s&quot;&gt;&quot;unknown matching token!&quot;&lt;/span&gt;); &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt; 869  &lt;/span&gt;  }
&lt;span class=&quot;ln&quot;&gt; 870  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;f&quot;&gt;parseToken&lt;/span&gt;(K, TokLoc, ErrorDiag)) {
&lt;div class=&quot;hi&quot;&gt;&lt;span class=&quot;ln&quot;&gt; 871  &lt;/span&gt;    &lt;span class=&quot;f&quot;&gt;diagnose&lt;/span&gt;(OtherLoc, OtherNote);&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt; 872  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 873  &lt;/span&gt;    TokLoc = PreviousLoc;
&lt;span class=&quot;ln&quot;&gt; 874  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt; 875  &lt;/span&gt;  }
&lt;span class=&quot;ln&quot;&gt; 876  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 877  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt; 878  &lt;/span&gt;}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Notice that the note diagnostic text isn't represented with a string, but instead with a type &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Diag&lt;/span&gt;&amp;lt;&amp;gt;&lt;/code&gt;, set to the value &lt;code&gt;&lt;span class=&quot;t&quot;&gt;diag&lt;/span&gt;::&lt;span class=&quot;gv&quot;&gt;opening_paren&lt;/span&gt;&lt;/code&gt;. This value is defined using macros:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/include/swift/AST/DiagnosticsParse.def#L34-L48&quot;&gt;swift/include/swift/AST/DiagnosticsParse.def&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;34  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#ifndef NOTE&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;35  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#  define NOTE(ID,Options,Text,Signature) \&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;36  &lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;DIAG(NOTE,ID,Options,Text,Signature)&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;37  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#endif&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;..  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;47  &lt;/span&gt;&lt;span class=&quot;m&quot;&gt;NOTE&lt;/span&gt;(opening_paren,none,
&lt;span class=&quot;ln&quot;&gt;48  &lt;/span&gt;     &lt;span class=&quot;s&quot;&gt;&quot;to match this opening '('&quot;&lt;/span&gt;, ())
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Another file defines the &lt;code&gt;&lt;span class=&quot;m&quot;&gt;DIAG&lt;/span&gt;&lt;/code&gt; macro and then includes this file, in order to define a new global variable, named &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;diag&lt;/span&gt;::&lt;span class=&quot;gv&quot;&gt;opening_paren&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/include/swift/AST/DiagnosticsParse.h#L23-L30&quot;&gt;swift/include/swift/AST/DiagnosticsParse.def&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;23  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; swift {
&lt;span class=&quot;ln&quot;&gt;24  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; diag {
&lt;span class=&quot;ln&quot;&gt;25  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// Declare common diagnostics objects with their appropriate types.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;26  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#define DIAG(KIND,ID,Options,Text,Signature) \&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;27  &lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;extern detail::DiagWithArguments&amp;lt;&lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; Signature&amp;gt;::type ID;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;28  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;DiagnosticsParse.def&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;29  &lt;/span&gt;  }
&lt;span class=&quot;ln&quot;&gt;30  &lt;/span&gt;}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The extern variable &lt;code&gt;&lt;span class=&quot;gv&quot;&gt;opening_paren&lt;/span&gt;&lt;/code&gt; is an instance of &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;detail&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;DiagWithArguments&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; ()&amp;gt;::&lt;span class=&quot;t&quot;&gt;type&lt;/span&gt;&lt;/code&gt;, which is a type alias for &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Diag&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; ()&amp;gt;&lt;/code&gt;. The template parameter &lt;code&gt;&lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; ()&lt;/code&gt; indicates that the diagnostic takes no arguments.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;There are other &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;diag&lt;/span&gt;&lt;/code&gt; kinds that &lt;em&gt;do&lt;/em&gt; take arguments, such as &lt;code&gt;&lt;span class=&quot;gv&quot;&gt;operator_static_in_protocol&lt;/span&gt;&lt;/code&gt;, which takes a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt;&lt;/code&gt; for the operator name:&lt;/p&gt;

  &lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/include/swift/AST/DiagnosticsParse.h#L23-L30&quot;&gt;swift/include/swift/AST/DiagnosticsParse.def&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;345  &lt;/span&gt;&lt;span class=&quot;m&quot;&gt;ERROR&lt;/span&gt;(operator_static_in_protocol,none,
&lt;span class=&quot;ln&quot;&gt;346  &lt;/span&gt;      &lt;span class=&quot;s&quot;&gt;&quot;operator '&lt;span class=&quot;si&quot;&gt;%0&lt;/span&gt;' declared in protocol must be 'static'&quot;&lt;/span&gt;,
&lt;div class=&quot;hi&quot;&gt;&lt;span class=&quot;ln&quot;&gt;347  &lt;/span&gt;      (&lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt;))&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt;348  &lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

  &lt;p&gt;In a future article, I'll cover how these arguments are used. For now, I'll focus on &lt;code&gt;&lt;span class=&quot;gv&quot;&gt;opening_paren&lt;/span&gt;&lt;/code&gt;, which takes no arguments.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As shown above, &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseMatchingToken&lt;/span&gt;&lt;/code&gt; calls &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;diagnose&lt;/span&gt;&lt;/code&gt; with the location of the opening parenthesis token and the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;diag&lt;/span&gt;::&lt;span class=&quot;gv&quot;&gt;opening_paren&lt;/span&gt;&lt;/code&gt;. This function instantiates a &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Diagnostic&lt;/span&gt;&lt;/code&gt; based on the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Diag&lt;/span&gt;&amp;lt;&amp;gt;&lt;/code&gt;, and calls through to &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;DiagnosticEngine&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;diagnose&lt;/span&gt;&lt;/code&gt; (recall above that the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;&lt;/code&gt; was instantiated with an instance of &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;DiagnosticEngine&lt;/span&gt;&lt;/code&gt;, a member of &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;ASTContext&lt;/span&gt;&lt;/code&gt;):&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/include/swift/Parse/Parser.h#L545-L550&quot;&gt;swift/include/swift/Parse/Parser.h&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;545  &lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;InFlightDiagnostic&lt;/span&gt; diagnose(&lt;span class=&quot;cl&quot;&gt;SourceLoc&lt;/span&gt; Loc, Diagnostic Diag) {
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;549  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;Diags&lt;/span&gt;.&lt;span class=&quot;f&quot;&gt;diagnose&lt;/span&gt;(Loc, Diag);
&lt;span class=&quot;ln&quot;&gt;550  &lt;/span&gt;  }
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;556  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;typename&lt;/span&gt; ...DiagArgTypes, &lt;span class=&quot;k&quot;&gt;typename&lt;/span&gt; ...ArgTypes&amp;gt;
&lt;span class=&quot;ln&quot;&gt;557  &lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;InFlightDiagnostic&lt;/span&gt; diagnose(&lt;span class=&quot;cl&quot;&gt;SourceLoc&lt;/span&gt; Loc, &lt;span class=&quot;cl&quot;&gt;Diag&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;DiagArgTypes&lt;/span&gt;...&amp;gt; DiagID,
&lt;span class=&quot;ln&quot;&gt;558  &lt;/span&gt;                              &lt;span class=&quot;t&quot;&gt;ArgTypes&lt;/span&gt; &amp;amp;&amp;amp;...Args) {
&lt;span class=&quot;ln&quot;&gt;559  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;f&quot;&gt;diagnose&lt;/span&gt;(Loc, &lt;span class=&quot;cl&quot;&gt;Diagnostic&lt;/span&gt;(DiagID, &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;forward&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;ArgTypes&lt;/span&gt;&amp;gt;(Args)...));
&lt;span class=&quot;ln&quot;&gt;560  &lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The Swift compiler defines several abstractions around diagnostics, and it can be hard to keep track of them all. So far I've covered &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Diag&lt;/span&gt;&amp;lt;&amp;gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;detail&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;DiagnosticWithArguments&lt;/span&gt;&amp;lt;&amp;gt;::&lt;span class=&quot;t&quot;&gt;type&lt;/span&gt;&lt;/code&gt;, which represent a single unique diagnostic. The code snippet above introduces &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Diagnostic&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;DiagnosticEngine&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;DiagnosticConsumer&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;DiagnosticInfo&lt;/span&gt;&lt;/code&gt;, and &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;InFlightDiagnostic&lt;/span&gt;&lt;/code&gt;. I'll introduce them each before stepping through the code:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Diagnostic&lt;/span&gt;&lt;/code&gt;: A diagnostic and all of the arguments it requires. For example, this is used to represent &lt;code&gt;&lt;span class=&quot;t&quot;&gt;diag&lt;/span&gt;::&lt;span class=&quot;gv&quot;&gt;opening_paren&lt;/span&gt;&lt;/code&gt; and its zero arguments. It's also used to represent &lt;code&gt;&lt;span class=&quot;t&quot;&gt;diag&lt;/span&gt;::&lt;span class=&quot;gv&quot;&gt;operator_static_in_protocol&lt;/span&gt;&lt;/code&gt; and store its one &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt;&lt;/code&gt; argument.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;DiagnosticEngine&lt;/span&gt;&lt;/code&gt;: This is an &quot;announcer&quot; class. It stores a list of &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;DiagnosticConsumer&lt;/span&gt;&lt;/code&gt; &quot;listeners&quot;, which it delegates to in order to print diagnostics text.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;DiagnosticInfo&lt;/span&gt;&lt;/code&gt;: Information about the diagnostic that is passed to &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;DiagnosticConsumer&lt;/span&gt;&lt;/code&gt; isntances.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;InFlightDiagnostic&lt;/span&gt;&lt;/code&gt;: This class is, confusingly, called a &quot;diagnostic&quot;, but it is actually used to represent state in the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;DiagnosticEngine&lt;/span&gt;&lt;/code&gt;. The &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;DiagnosticEngine&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;diagnose&lt;/span&gt;&lt;/code&gt; function creates an &quot;active&quot; diagnostic, and returns an instance of &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;InFlightDiagnostic&lt;/span&gt;&lt;/code&gt;. When this instance goes out of scope and its destructor &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~InFlightDiagnostic&lt;/code&gt; is called, it calls &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;DiagnosticEngine&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;flushActiveDiagnostic&lt;/span&gt;&lt;/code&gt;, which in turn notifies each &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;DiagnosticConsumer&lt;/span&gt;&lt;/code&gt; that it should emit the current active diagnostic.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's a lot of abstraction, but I found that after I followed the code, things became a little clearer. Recall that the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;diagnose&lt;/span&gt;&lt;/code&gt; function above instantiated a &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Diagnostic&lt;/span&gt;&lt;/code&gt; for &lt;code&gt;&lt;span class=&quot;t&quot;&gt;diag&lt;/span&gt;::&lt;span class=&quot;gv&quot;&gt;opening_paren&lt;/span&gt;&lt;/code&gt;, and then called &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;DiagnosticEngine&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;diagnose&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/include/swift/AST/DiagnosticEngine.h#L646-L660&quot;&gt;swift/include/swift/AST/DiagnosticEngine.h&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;646  &lt;/span&gt;    &lt;span class=&quot;d&quot;&gt;/// &lt;span class=&quot;dk&quot;&gt;\brief&lt;/span&gt; Emit an already-constructed diagnostic at the given location.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;647  &lt;/span&gt;    &lt;span class=&quot;d&quot;&gt;///&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;648  &lt;/span&gt;    &lt;span class=&quot;d&quot;&gt;/// &lt;span class=&quot;dk&quot;&gt;\param&lt;/span&gt; Loc The location to which the diagnostic refers in the source&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;649  &lt;/span&gt;    &lt;span class=&quot;d&quot;&gt;/// code.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;650  &lt;/span&gt;    &lt;span class=&quot;d&quot;&gt;///&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;651  &lt;/span&gt;    &lt;span class=&quot;d&quot;&gt;/// &lt;span class=&quot;dk&quot;&gt;\param&lt;/span&gt; D The diagnostic.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;652  &lt;/span&gt;    &lt;span class=&quot;d&quot;&gt;///&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;653  &lt;/span&gt;    &lt;span class=&quot;d&quot;&gt;/// &lt;span class=&quot;dk&quot;&gt;\returns&lt;/span&gt; An in-flight diagnostic, to which additional information can&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;654  &lt;/span&gt;    &lt;span class=&quot;d&quot;&gt;/// be attached.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;655  &lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;InFlightDiagnostic&lt;/span&gt; diagnose(&lt;span class=&quot;cl&quot;&gt;SourceLoc&lt;/span&gt; Loc, &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Diagnostic&lt;/span&gt; &amp;amp;D) {
&lt;span class=&quot;ln&quot;&gt;656  &lt;/span&gt;      &lt;span class=&quot;ms&quot;&gt;assert&lt;/span&gt;(!&lt;span class=&quot;vi&quot;&gt;ActiveDiagnostic&lt;/span&gt; &amp;amp;&amp;amp; &lt;span class=&quot;s&quot;&gt;&quot;Already have an active diagnostic&quot;&lt;/span&gt;);
&lt;div class=&quot;hi&quot;&gt;&lt;span class=&quot;ln&quot;&gt;657  &lt;/span&gt;      &lt;span class=&quot;vi&quot;&gt;ActiveDiagnostic&lt;/span&gt; = D;&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt;658  &lt;/span&gt;      &lt;span class=&quot;vi&quot;&gt;ActiveDiagnostic&lt;/span&gt;-&amp;gt;&lt;span class=&quot;f&quot;&gt;setLoc&lt;/span&gt;(Loc);
&lt;div class=&quot;hi&quot;&gt;&lt;span class=&quot;ln&quot;&gt;659  &lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;InFlightDiagnostic&lt;/span&gt;(*&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;);&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt;660  &lt;/span&gt;    }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Here the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;DiagnosticEngine&lt;/span&gt;&lt;/code&gt; sets its &lt;code&gt;&lt;span class=&quot;vi&quot;&gt;ActiveDiagnostic&lt;/span&gt;&lt;/code&gt; to the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Diagnostic&lt;/span&gt;&lt;/code&gt; that it was given. It then instantiates a &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;InFlightDiagnostic&lt;/span&gt;&lt;/code&gt; and returns it.&lt;/p&gt;

&lt;p&gt;Again, the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;InFlightDiagnostic&lt;/span&gt;&lt;/code&gt; being returned here isn't actually a &quot;diagnostic.&quot; It doesn't hold any information about what text should be printed out or at which location. Its only purpose is to be returned to the caller – the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseMatchingToken&lt;/span&gt;&lt;/code&gt; function – in case that caller wants to attach additional fix-its to the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;DiagnosticEngine&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;ActiveDiagnostic&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In this case, the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseMatchingToken&lt;/span&gt;&lt;/code&gt; function doesn't store the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;InFlightDiagnostic&lt;/span&gt;&lt;/code&gt; at all. So it immediately goes out of scope, and its destructor is called:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/Parse/Parser.cpp#L858-L878&quot;&gt;swift/lib/Parse/Parser.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;861  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::parseMatchingToken(&lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt; K, &lt;span class=&quot;cl&quot;&gt;SourceLoc&lt;/span&gt; &amp;amp;TokLoc, &lt;span class=&quot;cl&quot;&gt;Diag&lt;/span&gt;&amp;lt;&amp;gt; ErrorDiag,
&lt;span class=&quot;ln&quot;&gt;862  &lt;/span&gt;                                &lt;span class=&quot;cl&quot;&gt;SourceLoc&lt;/span&gt; OtherLoc) {
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;870  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;f&quot;&gt;parseToken&lt;/span&gt;(K, TokLoc, ErrorDiag)) {
&lt;div class=&quot;hi&quot;&gt;&lt;span class=&quot;ln&quot;&gt;871  &lt;/span&gt;    &lt;span class=&quot;f&quot;&gt;diagnose&lt;/span&gt;(OtherLoc, OtherNote);&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;878  &lt;/span&gt;}
&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/include/swift/AST/DiagnosticEngine.h#L646-L660&quot;&gt;swift/include/swift/AST/DiagnosticEngine.h&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;393  &lt;/span&gt;    ~InFlightDiagnostic() {
&lt;span class=&quot;ln&quot;&gt;394  &lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;vi&quot;&gt;IsActive&lt;/span&gt;)
&lt;div class=&quot;hi&quot;&gt;&lt;span class=&quot;ln&quot;&gt;395  &lt;/span&gt;        &lt;span class=&quot;f&quot;&gt;flush&lt;/span&gt;();&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt;396  &lt;/span&gt;    }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;InFlightDiagnostic&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;flush&lt;/span&gt;&lt;/code&gt; member function calls through to &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;DiagnosticEngine&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;flushActiveDiagnostic&lt;/span&gt;&lt;/code&gt;, which loops over each diagnostic consumer to call &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;DiagnosticConsumer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;handleDiagnostic&lt;/span&gt;&lt;/code&gt;, passing them a reference to the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceManager&lt;/span&gt;&lt;/code&gt;, along with a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;DiagnosticInfo&lt;/span&gt;&lt;/code&gt; instance:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/AST/DiagnosticEngine.cpp#L241-L248&quot;&gt;swift/lib/AST/DiagnosticEngine.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;241  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; InFlightDiagnostic::flush() {
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;247  &lt;/span&gt;    &lt;span class=&quot;vi&quot;&gt;Engine&lt;/span&gt;-&amp;gt;&lt;span class=&quot;f&quot;&gt;flushActiveDiagnostic&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;248  &lt;/span&gt;}
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;682  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; DiagnosticEngine::flushActiveDiagnostic() {
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;685  &lt;/span&gt;    &lt;span class=&quot;f&quot;&gt;emitDiagnostic&lt;/span&gt;(*&lt;span class=&quot;vi&quot;&gt;ActiveDiagnostic&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;690  &lt;/span&gt;}
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;699  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; DiagnosticEngine::emitDiagnostic(&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Diagnostic&lt;/span&gt; &amp;amp;diagnostic) {
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;705  &lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;SourceLoc&lt;/span&gt; loc = diagnostic.&lt;span class=&quot;f&quot;&gt;getLoc&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;818  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// Pass the diagnostic off to the consumer.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;819  &lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;DiagnosticInfo&lt;/span&gt; Info;
&lt;span class=&quot;ln&quot;&gt;820  &lt;/span&gt;  Info.&lt;span class=&quot;vi&quot;&gt;ID&lt;/span&gt; = diagnostic.&lt;span class=&quot;f&quot;&gt;getID&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;821  &lt;/span&gt;  Info.&lt;span class=&quot;vi&quot;&gt;Ranges&lt;/span&gt; = diagnostic.&lt;span class=&quot;f&quot;&gt;getRanges&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;822  &lt;/span&gt;  Info.&lt;span class=&quot;vi&quot;&gt;FixIts&lt;/span&gt; = diagnostic.&lt;span class=&quot;f&quot;&gt;getFixIts&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;823  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; &amp;amp;Consumer : &lt;span class=&quot;vi&quot;&gt;Consumers&lt;/span&gt;) {
&lt;span class=&quot;ln&quot;&gt;824  &lt;/span&gt;    Consumer-&amp;gt;&lt;span class=&quot;f&quot;&gt;handleDiagnostic&lt;/span&gt;(SourceMgr, loc, &lt;span class=&quot;f&quot;&gt;toDiagnosticKind&lt;/span&gt;(behavior),
&lt;span class=&quot;ln&quot;&gt;825  &lt;/span&gt;                               &lt;span class=&quot;f&quot;&gt;diagnosticStringFor&lt;/span&gt;(Info.&lt;span class=&quot;vi&quot;&gt;ID&lt;/span&gt;),
&lt;span class=&quot;ln&quot;&gt;826  &lt;/span&gt;                               diagnostic.&lt;span class=&quot;f&quot;&gt;getArgs&lt;/span&gt;(), Info);
&lt;span class=&quot;ln&quot;&gt;827  &lt;/span&gt;  }
&lt;span class=&quot;ln&quot;&gt;828  &lt;/span&gt;}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The announcer and listener pattern employed by &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;DiagnosticEngine&lt;/span&gt;&lt;/code&gt; and its &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;DiagnosticConumer&lt;/span&gt;&lt;/code&gt; instances allow the Swift compiler to handle diagnostics in different ways. For example, when I invoke &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-serialize-diagnostics&lt;/span&gt;&lt;/code&gt;, libswiftFrontendTool registers a &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SerializedDiagnosticConsumer&lt;/span&gt;&lt;/code&gt; instance, which writes diagnostics data to a file.&lt;/p&gt;

&lt;p&gt;By default, libswiftFrontendTool registers a &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;PrintingDiagnosticConsumer&lt;/span&gt;&lt;/code&gt;, in the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;performFrontend&lt;/span&gt;&lt;/code&gt; function:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/FrontendTool/FrontendTool.cpp#L1607-L1824&quot;&gt;swift/lib/FrontendTool/FrontendTool.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;1607  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::performFrontend(&lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; *&amp;gt; Args,
&lt;span class=&quot;ln&quot;&gt;1608  &lt;/span&gt;                           &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; *Argv0, &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; *MainAddr,
&lt;span class=&quot;ln&quot;&gt;1609  &lt;/span&gt;                           &lt;span class=&quot;cl&quot;&gt;FrontendObserver&lt;/span&gt; *observer) {
&lt;span class=&quot;ln&quot;&gt;....  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1612  &lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;PrintingDiagnosticConsumer&lt;/span&gt; PDC;
&lt;span class=&quot;ln&quot;&gt;....  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1648  &lt;/span&gt;  &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;&amp;gt; Instance =
&lt;span class=&quot;ln&quot;&gt;1649  &lt;/span&gt;    &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;make_unique&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;&amp;gt;();
&lt;span class=&quot;ln&quot;&gt;1650  &lt;/span&gt;  Instance-&amp;gt;&lt;span class=&quot;f&quot;&gt;addDiagnosticConsumer&lt;/span&gt;(&amp;amp;PDC);
&lt;span class=&quot;ln&quot;&gt;....  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1824  &lt;/span&gt;}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;When &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;DiagnosticEngine&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;emitDiagnostic&lt;/span&gt;&lt;/code&gt; invokes the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;PrintingDiagnosticConsumer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;handleDiagnostic&lt;/span&gt;&lt;/code&gt; function, the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;&lt;/code&gt; functions described in &lt;a href=&quot;/swift-compiler-diagnostics-part-1&quot;&gt;How the Swift Compiler Emits Diagnostics, Part 1&lt;/a&gt; are called. &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;GetMessage&lt;/span&gt;&lt;/code&gt; is used to get the text to print, and &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;PrimtMessage&lt;/span&gt;&lt;/code&gt; is used to output that text to the console:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/FrontendTool/FrontendTool.cpp#L1607-L1824&quot;&gt;swift/lib/FrontendTool/FrontendTool.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt; 66  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;PrintingDiagnosticConsumer&lt;/span&gt;::handleDiagnostic(
&lt;span class=&quot;ln&quot;&gt; 67  &lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;SourceManager&lt;/span&gt; &amp;amp;SM, &lt;span class=&quot;cl&quot;&gt;SourceLoc&lt;/span&gt; Loc, &lt;span class=&quot;t&quot;&gt;DiagnosticKind&lt;/span&gt; Kind,
&lt;span class=&quot;ln&quot;&gt; 68  &lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt; FormatString, &lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;DiagnosticArgument&lt;/span&gt;&amp;gt; FormatArgs,
&lt;span class=&quot;ln&quot;&gt; 69  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;DiagnosticInfo&lt;/span&gt; &amp;amp;Info) {
&lt;span class=&quot;ln&quot;&gt; 70  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// Determine what kind of diagnostic we're emitting.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 71  &lt;/span&gt;  &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;DiagKind&lt;/span&gt; SMKind;
&lt;span class=&quot;ln&quot;&gt; 72  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; (Kind) {
&lt;span class=&quot;ln&quot;&gt; 73  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;DiagnosticKind&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;Error&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt; 74  &lt;/span&gt;      SMKind = &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;DK_Error&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt; 75  &lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt; 76  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;DiagnosticKind&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;Warning&lt;/span&gt;: 
&lt;span class=&quot;ln&quot;&gt; 77  &lt;/span&gt;      SMKind = &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;DK_Warning&lt;/span&gt;; 
&lt;span class=&quot;ln&quot;&gt; 78  &lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt; 79  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 80  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;DiagnosticKind&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;Note&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt; 81  &lt;/span&gt;      SMKind = &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;DK_Note&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt; 82  &lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt; 83  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 84  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;DiagnosticKind&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;Remark&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt; 85  &lt;/span&gt;      SMKind = &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;DK_Remark&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt; 86  &lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt; 87  &lt;/span&gt;  }
&lt;span class=&quot;ln&quot;&gt; ..  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;106  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt; &amp;amp;rawSM = SM.&lt;span class=&quot;f&quot;&gt;getLLVMSourceMgr&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;107  &lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;108  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// Actually substitute the diagnostic arguments into the diagnostic text.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;109  &lt;/span&gt;  &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SmallString&lt;/span&gt;&amp;lt;&lt;span class=&quot;num&quot;&gt;256&lt;/span&gt;&amp;gt; Text;
&lt;span class=&quot;ln&quot;&gt;110  &lt;/span&gt;  {
&lt;span class=&quot;ln&quot;&gt;111  &lt;/span&gt;    &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;raw_svector_ostream&lt;/span&gt; Out(Text);
&lt;span class=&quot;ln&quot;&gt;112  &lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;DiagnosticEngine&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;formatDiagnosticText&lt;/span&gt;(Out, FormatString, FormatArgs);
&lt;span class=&quot;ln&quot;&gt;113  &lt;/span&gt;  }
&lt;span class=&quot;ln&quot;&gt;114  &lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;115  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; Msg = SM.&lt;span class=&quot;f&quot;&gt;GetMessage&lt;/span&gt;(Loc, SMKind, Text, Ranges, FixIts);
&lt;div class=&quot;hi&quot;&gt;&lt;span class=&quot;ln&quot;&gt;116  &lt;/span&gt;  rawSM.&lt;span class=&quot;f&quot;&gt;PrintMessage&lt;/span&gt;(out, Msg);&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt;117  &lt;/span&gt;}
&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;summarizing-the-last-three-articles&quot;&gt;Summarizing the last three articles&lt;/h2&gt;

&lt;p&gt;There's a lot of different machinery involved in printing diagnostics, spanning both the Swift and LLVM codebases:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The Swift frontend uses libLLVMOption to parse command-line arguments. The frontend instantiates an &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt; for each command-line argument that is determined to be an input file path. An &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt; either reads the entire file into memory, or it uses the operating system call &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;mmap&lt;/span&gt;&lt;/code&gt; to read chunks of it into memory as needed.&lt;/li&gt;
  &lt;li&gt;The Swift frontend registers each instantiated &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt; with a &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceManager&lt;/span&gt;&lt;/code&gt;. This is a libswiftBasic wrapper around &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;&lt;/code&gt;. libLLVMSupport implements &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;&lt;/code&gt;, which defines logic to print a line of source code from an &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt;, along with carets &lt;code&gt;&lt;span class=&quot;dc&quot;&gt;^&lt;/span&gt;&lt;/code&gt; or underlines &lt;code&gt;&lt;span class=&quot;dc&quot;&gt;~~~~~&lt;/span&gt;&lt;/code&gt; at specific locations or ranges, plus some arbitrary text.&lt;/li&gt;
  &lt;li&gt;The Swift lexer records &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceLoc&lt;/span&gt;&lt;/code&gt; locations as attributes on the tokens it lexes. &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceLoc&lt;/span&gt;&lt;/code&gt; is defined in libswiftBasic, as a wrapper around &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt;&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;The Swift parser is instantiated with a &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;DiagnosticEngine&lt;/span&gt;&lt;/code&gt;, which in turn holds a reference to the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceManager&lt;/span&gt;&lt;/code&gt; that owns the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt; objects. When the Swift parser encounters a series of tokens that don't fit Swift's grammar rules, it instructs its &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;DiagnosticEngine&lt;/span&gt;&lt;/code&gt; to print a diagnostic.&lt;/li&gt;
  &lt;li&gt;The &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;DiagnosticEngine&lt;/span&gt;&lt;/code&gt; uses an announcer &amp;amp; listener pattern to call &lt;code&gt;&lt;span class=&quot;f&quot;&gt;handleDiagnostic&lt;/span&gt;&lt;/code&gt; on each of its &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;DiagnosticConsumer&lt;/span&gt;&lt;/code&gt; instances, passing them a reference to the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceManager&lt;/span&gt;&lt;/code&gt; and some information about the diagnostic.&lt;/li&gt;
  &lt;li&gt;The default diagnostic consumer is &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;PrintingDiagnosticConsumer&lt;/span&gt;&lt;/code&gt;, which calls &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;PrintMessage&lt;/span&gt;&lt;/code&gt; in order to print the diagnostic text to the console.&lt;/li&gt;
&lt;/ol&gt;</content><author><name></name></author><category term="swiftc" /><summary type="html">In the last two articles in this series on Swift compiler development, I wrote about the abstractions provided by LLVM to emit diagnostics. How the Swift Compiler Emits Diagnostics, Part 1 explained how the llvm::SourceMgr class prints diagnostic messages along with lines of source code in an llvm::MemoryBuffer. Then I wrote about the internals of that llvm::MemoryBuffer class in How Swift and Clang Use LLVM to Read Files into Memory.</summary></entry><entry><title type="html">How Swift and Clang Use LLVM to Read Files into Memory</title><link href="https://modocache.io/llvm-memory-buffer" rel="alternate" type="text/html" title="How Swift and Clang Use LLVM to Read Files into Memory" /><published>2018-05-07T18:00:00+00:00</published><updated>2018-05-07T18:00:00+00:00</updated><id>https://modocache.io/llvm-memory-buffer</id><content type="html" xml:base="https://modocache.io/llvm-memory-buffer">&lt;p&gt;The &lt;a href=&quot;/swift-compiler-diagnostics-part-1&quot;&gt;prior article&lt;/a&gt; in this series explained how the Swift and Clang compilers used &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;&lt;/code&gt; to emit diagnostics for source locations in memory buffers, represented by the class &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt;. This article focuses on &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt;, the primary abstraction for reading files and streams into memory. Since it's used by Swift, Clang, and LLVM tools like &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;llvm-tblgen&lt;/span&gt;&lt;/code&gt;, I found it valuable to understand how it works.&lt;/p&gt;

&lt;h2 id=&quot;reading-a-file-into-memory-using-c&quot;&gt;Reading a file into memory using C++&lt;/h2&gt;

&lt;p&gt;The documentation for libLLVMSupport's &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt; class says it &quot;provides simple read-only access to a block of memory, and provides simple methods for reading files and standard input into a memory buffer.&quot; To better understand how it does that, I tried writing a simple C++ program, called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read.cpp&lt;/code&gt;, that reads a file – itself, in this case – into memory. For simplicity's sake my program is only meant to operate on Unix systems.&lt;/p&gt;

&lt;p&gt;My &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read.cpp&lt;/code&gt; program reads a file into memory by using various &lt;em&gt;system calls&lt;/em&gt;. These are requests made to the operating system for things like &quot;open a file and give me its file descriptor,&quot; or &quot;read 8 bytes from the file with this file descriptor.&quot; &lt;a href=&quot;https://twitter.com/b0rk&quot;&gt;Julia Evans&lt;/a&gt; has a wonderful &lt;a href=&quot;https://twitter.com/b0rk/status/989011990092963840/&quot;&gt;comic&lt;/a&gt; that explains them further:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://d3vv6lp55qjaqc.cloudfront.net/items/1V1802202Z0u07251U1t/DbmtKZpWkAAlra6.jpg-large-2.jpeg?X-CloudApp-Visitor-Id=543005&quot; alt=&quot;Your program doesn't know how to, for example, open a file on the filesystem, but the Linux operating system does. Your program can ask the operating system to do this via a &amp;quot;system call.&amp;quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;My &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read.cpp&lt;/code&gt; program uses four system calls:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;http://man7.org/linux/man-pages/man2/open.2.html&quot;&gt;&lt;code&gt;&lt;span class=&quot;fs&quot;&gt;open(2)&lt;/span&gt;&lt;/code&gt;&lt;/a&gt; to get a file descriptor for the file.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://man7.org/linux/man-pages/man2/stat.2.html&quot;&gt;&lt;code&gt;&lt;span class=&quot;fs&quot;&gt;fstat&lt;/span&gt;&lt;/code&gt;&lt;/a&gt;, which returns information about a file descriptor. Specifically, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read.cpp&lt;/code&gt; allocates memory based on the file's size.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://man7.org/linux/man-pages/man2/read.2.html&quot;&gt;&lt;code&gt;&lt;span class=&quot;fs&quot;&gt;read(2)&lt;/span&gt;&lt;/code&gt;&lt;/a&gt;, which reads a given number of bytes from a file into a pre-allocated block of memory.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://man7.org/linux/man-pages/man2/close.2.html&quot;&gt;&lt;code&gt;&lt;span class=&quot;fs&quot;&gt;close(2)&lt;/span&gt;&lt;/code&gt;&lt;/a&gt; to close a file descriptor once I'm done using it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read.cpp&lt;/code&gt; program allocates memory and reads its own source file into that memory, it increments the &lt;code&gt;&lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; *&lt;/code&gt; pointer into the memory and prints out the first line of the file:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;read.cpp&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt; 1  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;lt;cerrno&amp;gt;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 2  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 3  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;lt;system_error&amp;gt;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 4  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 5  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;lt;fcntl.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 6  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;lt;sys/stat.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 7  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 8  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 9  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; main() {
&lt;span class=&quot;ln&quot;&gt;10  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// I'll open this file itself and read it into memory.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;11  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; FileName = &lt;span class=&quot;ms&quot;&gt;__FILE__&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;12  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;13  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// The system call open(2) gets a file descriptor&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;14  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// representing the open file.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;15  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; OpenFlags = &lt;span class=&quot;cns&quot;&gt;O_RDONLY&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;16  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; FD = &lt;span class=&quot;fs&quot;&gt;open&lt;/span&gt;(FileName, OpenFlags);
&lt;span class=&quot;ln&quot;&gt;17  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;18  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// open(2) returns a -1 if the file could not be opened.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;19  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// In this case, print an error and return.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;20  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (FD &amp;lt; &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;) {
&lt;span class=&quot;ln&quot;&gt;21  &lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;error_code&lt;/span&gt; Err(&lt;span class=&quot;cns&quot;&gt;errno&lt;/span&gt;, &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;generic_category&lt;/span&gt;());
&lt;span class=&quot;ln&quot;&gt;22  &lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cns&quot;&gt;cerr&lt;/span&gt; &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot;[ERROR] Could not open file &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;23  &lt;/span&gt;              &amp;lt;&amp;lt; FileName &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;: &quot;&lt;/span&gt; &amp;lt;&amp;lt; Err.&lt;span class=&quot;fs&quot;&gt;message&lt;/span&gt;()
&lt;span class=&quot;ln&quot;&gt;24  &lt;/span&gt;              &amp;lt;&amp;lt; &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;endl&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;25  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;26  &lt;/span&gt;  }
&lt;span class=&quot;ln&quot;&gt;27  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;28  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// Syscall fstat populates the struct stat pointer&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;29  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// with information about the given file descriptor,&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;30  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// including the file's size in bytes.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;31  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;cls&quot;&gt;stat&lt;/span&gt; Stat;
&lt;span class=&quot;ln&quot;&gt;32  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;fs&quot;&gt;fstat&lt;/span&gt;(FD, &amp;amp;Stat) &amp;lt; &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;) {
&lt;span class=&quot;ln&quot;&gt;33  &lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;error_code&lt;/span&gt; Err(&lt;span class=&quot;cns&quot;&gt;errno&lt;/span&gt;, &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;generic_category&lt;/span&gt;());
&lt;span class=&quot;ln&quot;&gt;34  &lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cns&quot;&gt;cerr&lt;/span&gt; &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot;[ERROR] Could not acquire information &quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;35  &lt;/span&gt;              &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot;on file descriptor &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt; &amp;lt;&amp;lt; FD
&lt;span class=&quot;ln&quot;&gt;36  &lt;/span&gt;              &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;: &quot;&lt;/span&gt; &amp;lt;&amp;lt; Err.&lt;span class=&quot;fs&quot;&gt;message&lt;/span&gt;() &amp;lt;&amp;lt; &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;endl&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;37  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;38  &lt;/span&gt;  }
&lt;span class=&quot;ln&quot;&gt;39  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;40  &lt;/span&gt;  &lt;span class=&quot;ts&quot;&gt;off_t&lt;/span&gt; FileSize = Stat.&lt;span class=&quot;vs&quot;&gt;st_size&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;41  &lt;/span&gt;  &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;vs&quot;&gt;cout&lt;/span&gt; &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot;[NOTE] File size: &quot;&lt;/span&gt; &amp;lt;&amp;lt; FileSize &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot; bytes&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;42  &lt;/span&gt;            &amp;lt;&amp;lt; &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;endl&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;43  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;44  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// Allocate memory in size equal to the number of bytes&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;45  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// in the file.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;46  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; *Memory = &lt;span class=&quot;k&quot;&gt;static_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; *&amp;gt;(&lt;span class=&quot;k&quot;&gt;operator new&lt;/span&gt;(
&lt;span class=&quot;ln&quot;&gt;47  &lt;/span&gt;      FileSize + &lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;vs&quot;&gt;nothrow&lt;/span&gt;));
&lt;span class=&quot;ln&quot;&gt;48  &lt;/span&gt;  Memory[FileSize] = &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;49  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;50  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// Use syscall read(2) to read in bytes from the given&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;51  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// file descriptor, into the prepared buffer, 16 bytes&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;52  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// at a time.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;53  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;ssize_t&lt;/span&gt; ChunkSize = 16;
&lt;span class=&quot;ln&quot;&gt;54  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;ssize_t&lt;/span&gt; Offset = &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;55  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;ssize_t&lt;/span&gt; ReadBytes = &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;56  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; {
&lt;span class=&quot;ln&quot;&gt;57  &lt;/span&gt;    ReadBytes = &lt;span class=&quot;fs&quot;&gt;read&lt;/span&gt;(FD, Memory + Offset, ChunkSize);
&lt;span class=&quot;ln&quot;&gt;58  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (ReadBytes &amp;lt; &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;) {
&lt;span class=&quot;ln&quot;&gt;59  &lt;/span&gt;      &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;error_code&lt;/span&gt; Err(&lt;span class=&quot;cns&quot;&gt;errno&lt;/span&gt;, &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;generic_category&lt;/span&gt;());
&lt;span class=&quot;ln&quot;&gt;60  &lt;/span&gt;      &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cns&quot;&gt;cerr&lt;/span&gt; &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot;[ERROR] Could not read from file &quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;61  &lt;/span&gt;                   &lt;span class=&quot;s&quot;&gt;&quot;descriptor &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;62  &lt;/span&gt;                &amp;lt;&amp;lt; FD &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;: &quot;&lt;/span&gt; &amp;lt;&amp;lt; Err.&lt;span class=&quot;fs&quot;&gt;message&lt;/span&gt;()
&lt;span class=&quot;ln&quot;&gt;63  &lt;/span&gt;                &amp;lt;&amp;lt; &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;endl&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;64  &lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;delete&lt;/span&gt; Memory;
&lt;span class=&quot;ln&quot;&gt;65  &lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;66  &lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;67  &lt;/span&gt;    Offset += ReadBytes;
&lt;span class=&quot;ln&quot;&gt;68  &lt;/span&gt;  } &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; (ReadBytes != &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;69  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;70  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// I've now read the file into memory. To demonstrate:&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;71  &lt;/span&gt;  &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;vs&quot;&gt;cout&lt;/span&gt; &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot;[NOTE] Here's the first line &quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;72  &lt;/span&gt;            &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot;of the file: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;73  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; *Ptr = Memory;
&lt;span class=&quot;ln&quot;&gt;74  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; (*Ptr != &lt;span class=&quot;ch&quot;&gt;'\n'&lt;/span&gt; &amp;amp;&amp;amp; *Ptr != &lt;span class=&quot;ch&quot;&gt;'\0'&lt;/span&gt;) {
&lt;span class=&quot;ln&quot;&gt;75  &lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;vs&quot;&gt;cout&lt;/span&gt; &amp;lt;&amp;lt; *Ptr;
&lt;span class=&quot;ln&quot;&gt;76  &lt;/span&gt;    ++Ptr;
&lt;span class=&quot;ln&quot;&gt;77  &lt;/span&gt;  }
&lt;span class=&quot;ln&quot;&gt;78  &lt;/span&gt;  &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;vs&quot;&gt;cout&lt;/span&gt; &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt; &amp;lt;&amp;lt; &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;endl&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;79  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;80  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// Once I'm done with the file, I need to delete the&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;81  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// memory I allocated, otherwise this is a memory leak.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;82  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;delete&lt;/span&gt; Memory;
&lt;span class=&quot;ln&quot;&gt;83  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;84  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// Finally, I need to close the open file descriptor,&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;85  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// using the system call close(2).&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;86  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;fs&quot;&gt;close&lt;/span&gt;(FD) &amp;lt; &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;) {
&lt;span class=&quot;ln&quot;&gt;87  &lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;error_code&lt;/span&gt; Err(&lt;span class=&quot;cns&quot;&gt;errno&lt;/span&gt;, &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;generic_category&lt;/span&gt;());
&lt;span class=&quot;ln&quot;&gt;88  &lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cns&quot;&gt;cerr&lt;/span&gt; &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot;[ERROR] Could not close file &quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;89  &lt;/span&gt;              &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot;descriptor &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot; &amp;lt;&amp;lt; FD &amp;lt;&amp;lt; &quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;:&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;90  &lt;/span&gt;              &amp;lt;&amp;lt; Err.&lt;span class=&quot;fs&quot;&gt;message&lt;/span&gt;() &amp;lt;&amp;lt; &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;endl&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;91  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;92  &lt;/span&gt;  }
&lt;span class=&quot;ln&quot;&gt;93  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;94  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;95  &lt;/span&gt;}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;I can compile and run this program like so:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;cexec&quot;&gt;clang++&lt;/span&gt; read.cpp &lt;span class=&quot;copt&quot;&gt;-o&lt;/span&gt; my-read-example
&lt;span class=&quot;cexec&quot;&gt;./my-read-example&lt;/span&gt;
[NOTE] File size: 2820 bytes
[NOTE] Here's the first line of the file: &quot;#include &amp;lt;cerrno&amp;gt;&quot;
&lt;/pre&gt;

&lt;p&gt;This is a good initial implementation of reading a file into memory in C++. In fact, this is very similar to what the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getFile&lt;/span&gt;&lt;/code&gt; function does. However, there's room for improvement.&lt;/p&gt;

&lt;h2 id=&quot;reading-a-large-file-into-memory-using-mmap2&quot;&gt;Reading a large file into memory using &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;mmap(2)&lt;/span&gt;&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;Recall that we allocated memory on the heap using &lt;code&gt;&lt;span class=&quot;k&quot;&gt;operator new&lt;/span&gt;&lt;/code&gt;, and then used the syscall &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;read(2)&lt;/span&gt;&lt;/code&gt; to populate that memory with the contents of our file:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;read.cpp&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;46  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; *Memory = &lt;span class=&quot;k&quot;&gt;static_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; *&amp;gt;(&lt;span class=&quot;k&quot;&gt;operator new&lt;/span&gt;(
&lt;span class=&quot;ln&quot;&gt;47  &lt;/span&gt;      FileSize + &lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;vs&quot;&gt;nothrow&lt;/span&gt;));
&lt;span class=&quot;ln&quot;&gt;48  &lt;/span&gt;  Memory[FileSize] = &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;..  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;56  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; {
&lt;span class=&quot;ln&quot;&gt;57  &lt;/span&gt;    ReadBytes = &lt;span class=&quot;fs&quot;&gt;read&lt;/span&gt;(FD, Memory + Offset, ChunkSize);
&lt;span class=&quot;ln&quot;&gt;..  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;67  &lt;/span&gt;    Offset += ReadBytes;
&lt;span class=&quot;ln&quot;&gt;68  &lt;/span&gt;  } &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; (ReadBytes != &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;);
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This allocation would be problematic if we had a huge file to read into memory. A file with a size of 1 gigabyte would result in 1 gigabyte of memory being allocated – that's a lot of RAM!&lt;/p&gt;

&lt;p&gt;Thankfully, the syscall &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;mmap(2)&lt;/span&gt;&lt;/code&gt; allows us to read in bits of the file at a time. Once again, Julia Evans explains it best with another great &lt;a href=&quot;https://twitter.com/b0rk/status/988259255428972545/&quot;&gt;comic&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://d3vv6lp55qjaqc.cloudfront.net/items/3C0h0i2f3v3A1k1m0B1R/DbcAjhJW4AAI28b.jpg-large.jpeg?X-CloudApp-Visitor-Id=543005&quot; alt=&quot;The mmap(2) syscall lazily loads files into memory.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I can modify the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read.cpp&lt;/code&gt; program to use &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;mmap(2)&lt;/span&gt;&lt;/code&gt; when reading from large files:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;read.cpp&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;  5  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;lt;fcntl.h&amp;gt;&lt;/span&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt;  +  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;lt;sys/mman.h&amp;gt;&lt;/span&gt;&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt;  7  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;lt;sys/stat.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;  8  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;  9  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 10  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; main() {
&lt;span class=&quot;ln&quot;&gt; ..  &lt;/span&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt; ++  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// For &quot;large&quot; files over 1024 bytes in size, I'll use&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt; ++  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// syscall mmap(2).&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt; ++  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; *Memory = &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;;&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt; ++  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; UseMMap = (FileSize &amp;gt; &lt;span class=&quot;num&quot;&gt;1024&lt;/span&gt;);&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt; ++  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (UseMMap) {&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt; ++  &lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;vs&quot;&gt;cout&lt;/span&gt; &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot;[NOTE] Using mmap&quot;&lt;/span&gt; &amp;lt;&amp;lt; &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;endl&lt;/span&gt;;&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt; ++  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; ProtectedOptions = &lt;span class=&quot;cns&quot;&gt;PROT_READ&lt;/span&gt;;&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt; ++  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; Flags = &lt;span class=&quot;cns&quot;&gt;MAP_SHARED&lt;/span&gt;;&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt; ++  &lt;/span&gt;    Memory = &lt;span class=&quot;k&quot;&gt;static_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; *&amp;gt;(&lt;span class=&quot;fs&quot;&gt;mmap&lt;/span&gt;(&lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;, FileSize,&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt; ++  &lt;/span&gt;                                      ProtectedOptions,&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt; ++  &lt;/span&gt;                                      Flags, FD, &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;));&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt; ++  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (Memory == &lt;span class=&quot;cns&quot;&gt;MAP_FAILED&lt;/span&gt;) {&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt; ++  &lt;/span&gt;      &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;error_code&lt;/span&gt; Err(&lt;span class=&quot;cns&quot;&gt;errno&lt;/span&gt;, &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;generic_category&lt;/span&gt;());&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt; ++  &lt;/span&gt;      &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cns&quot;&gt;cerr&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt; ++  &lt;/span&gt;          &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot;[ERROR] Could not mmap file descriptor &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt; ++  &lt;/span&gt;          &amp;lt;&amp;lt; FD &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;: &quot;&lt;/span&gt; &amp;lt;&amp;lt; Err.&lt;span class=&quot;fs&quot;&gt;message&lt;/span&gt;() &amp;lt;&amp;lt; &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;endl&lt;/span&gt;;&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt; ++  &lt;/span&gt;    }&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt; ++  &lt;/span&gt;  } &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; {&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt; ..  &lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// ...use operator new as before.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 89  &lt;/span&gt;  }
&lt;span class=&quot;ln&quot;&gt; 90  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 91  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// I've now read the file into memory.&lt;/span&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt; ++  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// Note that this works exactly as before, we&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt; ++  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// don't have to worry about whether it's an mmap:&lt;/span&gt;&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt; 94  &lt;/span&gt;  &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;vs&quot;&gt;cout&lt;/span&gt; &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot;[NOTE] Here's the first line &quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 95  &lt;/span&gt;            &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot;of the file: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt; 96  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; *Ptr = Memory;
&lt;span class=&quot;ln&quot;&gt; 97  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; (*Ptr != &lt;span class=&quot;ch&quot;&gt;'\n'&lt;/span&gt; &amp;amp;&amp;amp; *Ptr != &lt;span class=&quot;ch&quot;&gt;'\0'&lt;/span&gt;) {
&lt;span class=&quot;ln&quot;&gt; 98  &lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;vs&quot;&gt;cout&lt;/span&gt; &amp;lt;&amp;lt; *Ptr;
&lt;span class=&quot;ln&quot;&gt; 99  &lt;/span&gt;    ++Ptr;
&lt;span class=&quot;ln&quot;&gt;100  &lt;/span&gt;  }
&lt;span class=&quot;ln&quot;&gt;101  &lt;/span&gt;  &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;vs&quot;&gt;cout&lt;/span&gt; &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt; &amp;lt;&amp;lt; &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;endl&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;102  &lt;/span&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt;+++  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (UseMMap) {&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt;+++  &lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// Once I'm done with the mmap'ed region, I need to&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt;+++  &lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// release it.&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt;+++  &lt;/span&gt;    &lt;span class=&quot;fs&quot;&gt;munmap&lt;/span&gt;(Memory, FileSize);&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt;+++  &lt;/span&gt;  } &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; {&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt;108  &lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// Once I'm done with the file, I need to delete the&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;109  &lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// memory I allocated, otherwise this is a memory leak.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;110  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;delete&lt;/span&gt; Memory;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt;+++  &lt;/span&gt;  }&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;123  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;124  &lt;/span&gt;}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Compiling and running this program produces the exact same results as before, with the important distinction that this program can open even very large files, without allocating a ton of memory.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;To experiment, you could try adding millions of lines of comments to the bottom of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read.cpp&lt;/code&gt;. Flip the &lt;code&gt;(FileSize &amp;gt; &lt;span class=&quot;num&quot;&gt;1024&lt;/span&gt;);&lt;/code&gt; conditional to &lt;code&gt;&amp;lt;&lt;/code&gt; in order to use &lt;code&gt;&lt;span class=&quot;k&quot;&gt;operator new&lt;/span&gt;&lt;/code&gt;, and you'll allocate hundreds of megabytes of memory up front. Then flip it back, to use &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;mmap(2)&lt;/span&gt;&lt;/code&gt;, and you'll allocate almost no memory.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For the most part, &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt; works exactly the same way as the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read.cpp&lt;/code&gt; program above. It has a few extra bells and whistles, too: it works on both Unix and Windows, it uses a more complex hueristic to decide whether to use &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;mmap(2)&lt;/span&gt;&lt;/code&gt; or not, and it uses some interesting syscalls and options on platforms that support them. I'll explain these as I write about it in detail below.&lt;/p&gt;

&lt;h2 id=&quot;the-llvm-implementation-of-readcpp-llvmmemorybuffergetfileorstdin&quot;&gt;The LLVM implementation of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read.cpp&lt;/code&gt;: &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getFileOrSTDIN&lt;/span&gt;&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;Swift and Clang both use the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getFileOrSTDIN&lt;/span&gt;&lt;/code&gt; static member function to open input file arguments passed to them on the command-line. For example, below is the code in libswiftFrontend converts the string filenames it was passed on the command-line into &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt; objects. The filename is a &lt;code&gt;&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;string&lt;/span&gt;&lt;/code&gt; stored as &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;InputFile&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;file&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/1da70a01cc40958fa3cc64708d78d6bee71f32fa/lib/Frontend/Frontend.cpp#L315-L342&quot;&gt;swift/lib/Frontend/Frontend.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;315  &lt;/span&gt;&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;pair&lt;/span&gt;&amp;lt;&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&amp;gt;,
&lt;span class=&quot;ln&quot;&gt;316  &lt;/span&gt;          &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&amp;gt;&amp;gt;
&lt;span class=&quot;ln&quot;&gt;317  &lt;/span&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::getInputBufferAndModuleDocBufferIfPresent(
&lt;span class=&quot;ln&quot;&gt;318  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;InputFile&lt;/span&gt; &amp;amp;input) {
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;326  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; FileOrError = &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;ErrorOr&lt;/span&gt;&amp;lt;&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&amp;gt;&amp;gt;;
&lt;span class=&quot;ln&quot;&gt;327  &lt;/span&gt;  &lt;span class=&quot;t&quot;&gt;FileOrError&lt;/span&gt; inputFileOrErr = &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getFileOrSTDIN&lt;/span&gt;(input.&lt;span class=&quot;f&quot;&gt;file&lt;/span&gt;());
&lt;span class=&quot;ln&quot;&gt;328  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (!inputFileOrErr) {
&lt;span class=&quot;ln&quot;&gt;329  &lt;/span&gt;    &lt;span class=&quot;v&quot;&gt;Diagnostics&lt;/span&gt;.&lt;span class=&quot;f&quot;&gt;diagnose&lt;/span&gt;(&lt;span class=&quot;cl&quot;&gt;SourceLoc&lt;/span&gt;(), &lt;span class=&quot;t&quot;&gt;diag&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;error_open_input_file&lt;/span&gt;, input.&lt;span class=&quot;f&quot;&gt;file&lt;/span&gt;(),
&lt;span class=&quot;ln&quot;&gt;330  &lt;/span&gt;                         inputFileOrErr.&lt;span class=&quot;f&quot;&gt;getError&lt;/span&gt;().&lt;span class=&quot;f&quot;&gt;message&lt;/span&gt;());
&lt;span class=&quot;ln&quot;&gt;331  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;make_pair&lt;/span&gt;(&lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;, &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;332  &lt;/span&gt;  }
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;342  &lt;/span&gt;}
&lt;/pre&gt;
&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;As I wrote in &lt;a href=&quot;/swift-compiler-diagnostics-part-1&quot;&gt;the previous article&lt;/a&gt;, these &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt; will then be passed over to the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;&lt;/code&gt;, which takes ownership of them. The &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;&lt;/code&gt; will then interact with &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;&lt;/code&gt; (or more precisely, a wrapper called &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceManager&lt;/span&gt;&lt;/code&gt;) in order to emit diagnostics at particular locations in the buffer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getFileOrSTDIN&lt;/span&gt;&lt;/code&gt; function returns either a &lt;code&gt;&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&lt;/code&gt; to an &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt; for the given file, or an error. This is represented by the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;ErrorOr&lt;/span&gt;&lt;/code&gt; type. (I'll write more about &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;ErrorOr&lt;/span&gt;&lt;/code&gt; in the future, but in the meantime you can &lt;a href=&quot;https://www.youtube.com/watch?v=Wq8fNK98WGw&quot;&gt;watch this 5-minute lightning talk from LLVM Developers Meeting 2016&lt;/a&gt; to learn more about them.)&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;f&quot;&gt;getFileOrSTDIN&lt;/span&gt;&lt;/code&gt; function just checks for a file name of &lt;code&gt;&lt;span class=&quot;s&quot;&gt;&quot;-&quot;&lt;/span&gt;&lt;/code&gt; and then delegates its logic to either &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getSTDIN&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class=&quot;f&quot;&gt;getFile&lt;/span&gt;&lt;/code&gt;. It may optionally be given an &lt;code&gt;&lt;span class=&quot;k&quot;&gt;int64_t&lt;/span&gt; FileSize&lt;/code&gt; argument, but if not the default value of &lt;code&gt;&lt;span class=&quot;num&quot;&gt;-1&lt;/span&gt;&lt;/code&gt; signals the function to find out on its own – just as my example &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read.cpp&lt;/code&gt; program above did, by using the &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;fstat&lt;/span&gt;&lt;/code&gt; system call.&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/llvm-mirror/llvm/blob/b5e2d41d5d1fac6bb58a3a2207995b11a42f6eba/include/llvm/Support/MemoryBuffer.h#L125-L129&quot;&gt;llvm/include/llvm/Support/MemoryBuffer.h&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;125  &lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// Open the specified file as a MemoryBuffer, or open stdin if the Filename&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;126  &lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// is &quot;-&quot;.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;127  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;ErrorOr&lt;/span&gt;&amp;lt;&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&amp;gt;&amp;gt;
&lt;span class=&quot;ln&quot;&gt;128  &lt;/span&gt;  getFileOrSTDIN(&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Twine&lt;/span&gt; &amp;amp;Filename, &lt;span class=&quot;k&quot;&gt;int64_t&lt;/span&gt; FileSize = &lt;span class=&quot;num&quot;&gt;-1&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;129  &lt;/span&gt;                 &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; RequiresNullTerminator = &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;);
&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/llvm-mirror/llvm/blob/b5e2d41d5d1fac6bb58a3a2207995b11a42f6eba/lib/Support/MemoryBuffer.cpp#L143-L152&quot;&gt;llvm/lib/Support/MemoryBuffer.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt; 143  &lt;/span&gt;&lt;span class=&quot;cl&quot;&gt;ErrorOr&lt;/span&gt;&amp;lt;&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&amp;gt;&amp;gt;
&lt;span class=&quot;ln&quot;&gt; 144  &lt;/span&gt;&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;::getFileOrSTDIN(&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Twine&lt;/span&gt; &amp;amp;Filename, &lt;span class=&quot;k&quot;&gt;int64_t&lt;/span&gt; FileSize,
&lt;span class=&quot;ln&quot;&gt; 145  &lt;/span&gt;                             &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; RequiresNullTerminator) {
&lt;span class=&quot;ln&quot;&gt; 146  &lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;SmallString&lt;/span&gt;&amp;lt;&lt;span class=&quot;num&quot;&gt;256&lt;/span&gt;&amp;gt; NameBuf;
&lt;span class=&quot;ln&quot;&gt; 147  &lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt; NameRef = Filename.&lt;span class=&quot;f&quot;&gt;toStringRef&lt;/span&gt;(NameBuf);
&lt;span class=&quot;ln&quot;&gt; 148  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 149  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (NameRef == &lt;span class=&quot;s&quot;&gt;&quot;-&quot;&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt; 150  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;f&quot;&gt;getSTDIN&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt; 151  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;f&quot;&gt;getFile&lt;/span&gt;(Filename, FileSize, RequiresNullTerminator);
&lt;span class=&quot;ln&quot;&gt; 152  &lt;/span&gt;}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;I'll focus on the &lt;code&gt;&lt;span class=&quot;f&quot;&gt;getFile&lt;/span&gt;&lt;/code&gt; case for now, which delegates in turn to a function called &lt;code&gt;&lt;span class=&quot;f&quot;&gt;getFileAux&lt;/span&gt;&lt;/code&gt;. The &lt;code&gt;&lt;span class=&quot;f&quot;&gt;getFileAux&lt;/span&gt;&lt;/code&gt; static function implements some of the logic I implemented in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read.cpp&lt;/code&gt; example above: it opens the file in order to obtain a file descriptor, it reads that file, and then it calls &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;close(2)&lt;/span&gt;&lt;/code&gt; in order to close the file descriptor:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/llvm-mirror/llvm/blob/b5e2d41d5d1fac6bb58a3a2207995b11a42f6eba/include/llvm/Support/MemoryBuffer.h#L73-L83&quot;&gt;llvm/include/llvm/Support/MemoryBuffer.h&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;73  &lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// Open the specified file as a MemoryBuffer, returning a new MemoryBuffer&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;74  &lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// if successful, otherwise returning null. If FileSize is specified, this&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;75  &lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// means that the client knows that the file exists and that it has the&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;76  &lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// specified size.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;77  &lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;///&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;78  &lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// &lt;span class=&quot;dk&quot;&gt;\param&lt;/span&gt; IsVolatile Set to true to indicate that the contents of the file&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;79  &lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// can change outside the user's control, e.g. when libclang tries to parse&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;80  &lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// while the user is editing/updating the file or if the file is on an NFS.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;81  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;ErrorOr&lt;/span&gt;&amp;lt;&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&amp;gt;&amp;gt;
&lt;span class=&quot;ln&quot;&gt;82  &lt;/span&gt;  &lt;span class=&quot;f&quot;&gt;getFile&lt;/span&gt;(&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Twine&lt;/span&gt; &amp;amp;Filename, &lt;span class=&quot;k&quot;&gt;int64_t&lt;/span&gt; FileSize = &lt;span class=&quot;num&quot;&gt;-1&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;83  &lt;/span&gt;          &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; RequiresNullTerminator = &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;, &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; IsVolatile = &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;);
&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/llvm-mirror/llvm/blob/b5e2d41d5d1fac6bb58a3a2207995b11a42f6eba/lib/Support/MemoryBuffer.cpp#L229-L256&quot;&gt;llvm/lib/Support/MemoryBuffer.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;229  &lt;/span&gt;&lt;span class=&quot;cl&quot;&gt;ErrorOr&lt;/span&gt;&amp;lt;&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&amp;gt;&amp;gt;
&lt;span class=&quot;ln&quot;&gt;230  &lt;/span&gt;&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;::getFile(&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Twine&lt;/span&gt; &amp;amp;Filename, &lt;span class=&quot;k&quot;&gt;int64_t&lt;/span&gt; FileSize,
&lt;span class=&quot;ln&quot;&gt;231  &lt;/span&gt;                      &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; RequiresNullTerminator, &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; IsVolatile) {
&lt;span class=&quot;ln&quot;&gt;232  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;f&quot;&gt;getFileAux&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&amp;gt;(Filename, FileSize, FileSize, &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;233  &lt;/span&gt;                                  RequiresNullTerminator, IsVolatile);
&lt;span class=&quot;ln&quot;&gt;234  &lt;/span&gt;}
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;242  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;template&lt;/span&gt; &amp;lt;&lt;span class=&quot;k&quot;&gt;typename&lt;/span&gt; MB&amp;gt;
&lt;span class=&quot;ln&quot;&gt;243  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;ErrorOr&lt;/span&gt;&amp;lt;&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;MB&lt;/span&gt;&amp;gt;&amp;gt;
&lt;span class=&quot;ln&quot;&gt;244  &lt;/span&gt;getFileAux(&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Twine&lt;/span&gt; &amp;amp;Filename, &lt;span class=&quot;k&quot;&gt;int64_t&lt;/span&gt; FileSize, &lt;span class=&quot;k&quot;&gt;uint64_t&lt;/span&gt; MapSize,
&lt;span class=&quot;ln&quot;&gt;245  &lt;/span&gt;           &lt;span class=&quot;k&quot;&gt;uint64_t&lt;/span&gt; Offset, &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; RequiresNullTerminator, &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; IsVolatile) {
&lt;span class=&quot;ln&quot;&gt;246  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; FD;
&lt;span class=&quot;ln&quot;&gt;247  &lt;/span&gt;  &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;error_code&lt;/span&gt; EC = &lt;span class=&quot;t&quot;&gt;sys&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;fs&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;openFileForRead&lt;/span&gt;(Filename, FD);
&lt;span class=&quot;ln&quot;&gt;248  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;249  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (EC)
&lt;span class=&quot;ln&quot;&gt;250  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; EC;
&lt;span class=&quot;ln&quot;&gt;251  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;252  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; Ret = &lt;span class=&quot;f&quot;&gt;getOpenFileImpl&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;MB&lt;/span&gt;&amp;gt;(FD, Filename, FileSize, MapSize, Offset,
&lt;span class=&quot;ln&quot;&gt;253  &lt;/span&gt;                                 RequiresNullTerminator, IsVolatile);
&lt;span class=&quot;ln&quot;&gt;254  &lt;/span&gt;  &lt;span class=&quot;fs&quot;&gt;close&lt;/span&gt;(FD);
&lt;span class=&quot;ln&quot;&gt;255  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; Ret;
&lt;span class=&quot;ln&quot;&gt;256  &lt;/span&gt;}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Unlike &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read.cpp&lt;/code&gt;, the &lt;code&gt;&lt;span class=&quot;f&quot;&gt;getFileAux&lt;/span&gt;&lt;/code&gt; function does not call the &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;open(2)&lt;/span&gt;&lt;/code&gt; system call directly in order to obtain an open file descriptor for given filename. Instead, it uses the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;sys&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;fs&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;openFileForRead&lt;/span&gt;&lt;/code&gt; function. This LLVM helper function, unlike &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;open(2)&lt;/span&gt;&lt;/code&gt;, works on both Windows and Unix platforms.&lt;/p&gt;

&lt;h2 id=&quot;per-platform-implementations-of-system-calls-in-llvm&quot;&gt;Per-platform implementations of system calls in LLVM&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;sys&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;fs&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;openFileForRead&lt;/span&gt;&lt;/code&gt; function has a single delcaration, in the header file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FileSystem.h&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/llvm-mirror/llvm/blob/b5e2d41d5d1fac6bb58a3a2207995b11a42f6eba/include/llvm/Support/FileSystem.h#L822-L823&quot;&gt;llvm/include/llvm/Support/FileSystem.h&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;&lt;span class=&quot;d&quot;&gt;/// &lt;span class=&quot;dk&quot;&gt;@brief&lt;/span&gt; Opens the file with the given name in a read-only mode, returning&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;&lt;span class=&quot;d&quot;&gt;/// its open file descriptor.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;///
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;&lt;span class=&quot;d&quot;&gt;/// &lt;span class=&quot;dk&quot;&gt;@param&lt;/span&gt; Name The name of the file to open.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;&lt;span class=&quot;d&quot;&gt;/// &lt;span class=&quot;dk&quot;&gt;@param&lt;/span&gt; ResultFD The location to store the descriptor for the opened file.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;&lt;span class=&quot;d&quot;&gt;/// &lt;span class=&quot;dk&quot;&gt;@param&lt;/span&gt; RealPath If nonnull, extra work is done to determine the real path&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;&lt;span class=&quot;d&quot;&gt;///                 of the opened file, and that path is stored in this&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;&lt;span class=&quot;d&quot;&gt;///                 location.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;&lt;span class=&quot;d&quot;&gt;/// &lt;span class=&quot;dk&quot;&gt;@returns&lt;/span&gt; errc::success if &lt;span class=&quot;dk&quot;&gt;\a&lt;/span&gt; Name has been opened, otherwise a&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;&lt;span class=&quot;d&quot;&gt;///          platform-specific error_code.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;822  &lt;/span&gt;&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;error_code&lt;/span&gt; openFileForRead(&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Twine&lt;/span&gt; &amp;amp;Name, &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; &amp;amp;ResultFD,
&lt;span class=&quot;ln&quot;&gt;823  &lt;/span&gt;                                &lt;span class=&quot;cl&quot;&gt;SmallVectorImpl&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;char&lt;/span&gt;&amp;gt; *RealPath = &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;);
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;But the LLVM codebase defines two separate implementations of this function: one that's used on Windows platforms, and another that's used on Unix. It accomplishes this using CMake.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I've found that a working knowledge of CMake is a gift that really keeps on giving when it comes to compiler development. If you haven't already, you can read about it more in my articles &lt;a href=&quot;/the-swift-compilers-build-system&quot;&gt;The Swift Compiler's Build System&lt;/a&gt; and &lt;a href=&quot;/reading-and-understanding-the-cmake-in-apple-swift&quot;&gt;Reading and Understanding the CMake in apple/swift&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;LLVM's root &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CMakeLists.txt&lt;/code&gt; file appends two directories to its modules path, and then includes one file from each of those directories: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;llvm/cmake/config-ix.cmake&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;llvm/cmake/modules/HandleLLVMOptions.cmake&lt;/code&gt;. Finally, it configures a header file named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;config.h.cmake&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/llvm-mirror/llvm/blob/b5e2d41d5d1fac6bb58a3a2207995b11a42f6eba/CMakeLists.txt#L184-L602&quot;&gt;llvm/CMakeLists.txt&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;184  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;set&lt;/span&gt;(&lt;span class=&quot;v&quot;&gt;CMAKE_MODULE_PATH&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;185  &lt;/span&gt;  &lt;span class=&quot;si&quot;&gt;${CMAKE_MODULE_PATH}&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;186  &lt;/span&gt;  &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${CMAKE_CURRENT_SOURCE_DIR}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/cmake&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;187  &lt;/span&gt;  &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${CMAKE_CURRENT_SOURCE_DIR}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/cmake/modules&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;188  &lt;/span&gt;  )
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;588  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;include&lt;/span&gt;(config-ix)
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;602  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;include&lt;/span&gt;(HandleLLVMOptions)
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;737  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;configure_file&lt;/span&gt;(
&lt;span class=&quot;ln&quot;&gt;738  &lt;/span&gt;  &lt;span class=&quot;si&quot;&gt;${LLVM_MAIN_INCLUDE_DIR}&lt;/span&gt;/llvm/Config/config.h.cmake
&lt;span class=&quot;ln&quot;&gt;739  &lt;/span&gt;  &lt;span class=&quot;si&quot;&gt;${LLVM_INCLUDE_DIR}&lt;/span&gt;/llvm/Config/config.h)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;config-ix.cmake&lt;/code&gt; file uses &lt;a href=&quot;https://cmake.org/cmake/help/latest/module/CheckSymbolExists.html&quot;&gt;the built-in CMake function &lt;code&gt;&lt;span class=&quot;ms&quot;&gt;check_symbol_exists&lt;/span&gt;&lt;/code&gt;&lt;/a&gt; in order to determine which system calls are available in the target build environment. For example, it checks whether &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;pread&lt;/span&gt;&lt;/code&gt; is available and, if it is, has CMake define a variable named &lt;code&gt;&lt;span class=&quot;v&quot;&gt;HAVE_PREAD&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/llvm-mirror/llvm/blob/b5e2d41d5d1fac6bb58a3a2207995b11a42f6eba/cmake/config-ix.cmake#L205&quot;&gt;llvm/cmake/config-ix.cmake&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;205  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;check_symbol_exists&lt;/span&gt;(pread unistd.h &lt;span class=&quot;v&quot;&gt;HAVE_PREAD&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Then, in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HandleLLVMOptions.cmake&lt;/code&gt;, it uses the built-in CMake platform variables, &lt;a href=&quot;https://cmake.org/cmake/help/latest/variable/WIN32.html&quot;&gt;&lt;code&gt;&lt;span class=&quot;vs&quot;&gt;WIN32&lt;/span&gt;&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://cmake.org/cmake/help/latest/variable/UNIX.html&quot;&gt;&lt;code&gt;&lt;span class=&quot;vs&quot;&gt;UNIX&lt;/span&gt;&lt;/code&gt;&lt;/a&gt;, to set the CMake variables &lt;code&gt;&lt;span class=&quot;v&quot;&gt;LLVM_ON_WIN32&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;v&quot;&gt;LLVM_ON_UNIX&lt;/span&gt;&lt;/code&gt; to &lt;code&gt;&lt;span class=&quot;k&quot;&gt;True&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class=&quot;k&quot;&gt;False&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/llvm-mirror/llvm/blob/b5e2d41d5d1fac6bb58a3a2207995b11a42f6eba/cmake/modules/HandleLLVMOptions.cmake#L108-L129&quot;&gt;llvm/cmake/modules/HandleLLVMOptions.cmake&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;108  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;if&lt;/span&gt;(&lt;span class=&quot;vs&quot;&gt;WIN32&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;114  &lt;/span&gt;    &lt;span class=&quot;ms&quot;&gt;set&lt;/span&gt;(LLVM_ON_WIN32 &lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt;115  &lt;/span&gt;    &lt;span class=&quot;ms&quot;&gt;set&lt;/span&gt;(LLVM_ON_UNIX &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;117  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;else&lt;/span&gt;(&lt;span class=&quot;vs&quot;&gt;WIN32&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt;118  &lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;if&lt;/span&gt;(&lt;span class=&quot;vs&quot;&gt;UNIX&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt;119  &lt;/span&gt;    &lt;span class=&quot;ms&quot;&gt;set&lt;/span&gt;(LLVM_ON_WIN32 &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt;120  &lt;/span&gt;    &lt;span class=&quot;ms&quot;&gt;set&lt;/span&gt;(LLVM_ON_UNIX &lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;129  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;endif&lt;/span&gt;(&lt;span class=&quot;vs&quot;&gt;WIN32&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;At this point, CMake variables like &lt;code&gt;&lt;span class=&quot;v&quot;&gt;HAVE_PREAD&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;v&quot;&gt;LLVM_ON_UNIX&lt;/span&gt;&lt;/code&gt; would only be visible from within CMake. To make their values visible in C++, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;config.h.cmake&lt;/code&gt; file is configured via a call to &lt;a href=&quot;https://cmake.org/cmake/help/latest/command/configure_file.html?highlight=cmakedefine&quot;&gt;the CMake built-in function &lt;code&gt;&lt;span class=&quot;ms&quot;&gt;configure_file&lt;/span&gt;&lt;/code&gt;&lt;/a&gt;, as shown in a code snippet above. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;config.h.cmake&lt;/code&gt; file is full of &lt;code&gt;&lt;span class=&quot;ms&quot;&gt;#cmakedefine&lt;/span&gt;&lt;/code&gt; directives, which &lt;code&gt;&lt;span class=&quot;ms&quot;&gt;configure_file&lt;/span&gt;&lt;/code&gt; transforms into &lt;code&gt;&lt;span class=&quot;ms&quot;&gt;#define&lt;/span&gt;&lt;/code&gt; statements for consumption in C++. For example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;config.h.cmake&lt;/code&gt; contains these &lt;code&gt;&lt;span class=&quot;ms&quot;&gt;#cmakedefine&lt;/span&gt;&lt;/code&gt; statements…&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/llvm-mirror/llvm/blob/b5e2d41d5d1fac6bb58a3a2207995b11a42f6eba/include/llvm/Config/config.h.cmake#L142-L315&quot;&gt;llvm/include/llvm/Config/config.h.cmake&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;142  &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;/* Define to 1 if you have the `pread' function. */&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;143  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#cmakedefine&lt;/span&gt; HAVE_PREAD &lt;span class=&quot;si&quot;&gt;${HAVE_PREAD}&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;311  &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;/* Define if this is Unixish platform */&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;312  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#cmakedefine&lt;/span&gt; LLVM_ON_UNIX &lt;span class=&quot;si&quot;&gt;${LLVM_ON_UNIX}&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;313  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;314  &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;/* Define if this is Win32ish platform */&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;315  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#cmakedefine&lt;/span&gt; LLVM_ON_WIN32 &lt;span class=&quot;si&quot;&gt;${LLVM_ON_WIN32}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;…which on a Unix-like platform, such as macOS, are transformed into these statements, placed in a file in the build directory named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;include/llvm/Config/config.h&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;build/include/llvm/Config/config.h&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;142  &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;/* Define to 1 if you have the `pread' function. */&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;143  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#define&lt;/span&gt; HAVE_PREAD &lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;311  &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;/* Define if this is Win32ish platform */&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;312  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#define&lt;/span&gt; LLVM_ON_UNIX &lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;And in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;llvm/lib/Support/Path.cpp&lt;/code&gt;, instead of finding an implementation of the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;sys&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;fs&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;openFileForRead&lt;/span&gt;&lt;/code&gt; function, instead there's a condiitonal include based on these definitions:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/llvm-mirror/llvm/blob/b5e2d41d5d1fac6bb58a3a2207995b11a42f6eba/lib/Support/Path.cpp#L1072-L1078&quot;&gt;llvm/lib/Support/Path.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;1072  &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;// Include the truly platform-specific parts.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1073  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#if defined(LLVM_ON_UNIX)&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1074  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Unix/Path.inc&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1075  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#endif&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1076  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#if defined(LLVM_ON_WIN32)&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1077  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Windows/Path.inc&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1078  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#endif&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;It's in the included &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;llvm/lib/Support/Unix/Path.inc&lt;/code&gt; file that I can find the actual implementation of &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;sys&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;fs&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;openFileForRead&lt;/span&gt;&lt;/code&gt; that's used on Unix platforms.&lt;/p&gt;

&lt;h2 id=&quot;opening-a-file-on-unix&quot;&gt;Opening a file on Unix&lt;/h2&gt;

&lt;p&gt;As in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read.cpp&lt;/code&gt; example at the beginning of this article, the Unix implementation of the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;sys&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;fs&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;openFileForRead&lt;/span&gt;&lt;/code&gt; function uses the system call &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;open(2)&lt;/span&gt;&lt;/code&gt; in order to open a file and get its file descriptor:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/llvm-mirror/llvm/blob/b5e2d41d5d1fac6bb58a3a2207995b11a42f6eba/lib/Support/Unix/Path.inc#L719-L759&quot;&gt;llvm/lib/Support/Unix/Path.inc&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;719  &lt;/span&gt;&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;error_code&lt;/span&gt; openFileForRead(&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Twine&lt;/span&gt; &amp;amp;Name, &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; &amp;amp;ResultFD,
&lt;span class=&quot;ln&quot;&gt;720  &lt;/span&gt;                                &lt;span class=&quot;cl&quot;&gt;SmallVectorImpl&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;char&lt;/span&gt;&amp;gt; *RealPath) {
&lt;span class=&quot;ln&quot;&gt;721  &lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;SmallString&lt;/span&gt;&amp;lt;&lt;span class=&quot;num&quot;&gt;128&lt;/span&gt;&amp;gt; Storage;
&lt;span class=&quot;ln&quot;&gt;722  &lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt; P = Name.toNullTerminatedStringRef(Storage);
&lt;span class=&quot;ln&quot;&gt;723  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; OpenFlags = &lt;span class=&quot;cns&quot;&gt;O_RDONLY&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;724  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#ifdef O_CLOEXEC&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;725  &lt;/span&gt;  OpenFlags |= &lt;span class=&quot;cns&quot;&gt;O_CLOEXEC&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;726  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#endif&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;727  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; ((ResultFD = &lt;span class=&quot;t&quot;&gt;sys&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;RetryAfterSignal&lt;/span&gt;(&lt;span class=&quot;num&quot;&gt;-1&lt;/span&gt;, &lt;span class=&quot;fs&quot;&gt;open&lt;/span&gt;, P.&lt;span class=&quot;f&quot;&gt;begin&lt;/span&gt;(), OpenFlags)) &amp;lt; &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt;728  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;error_code&lt;/span&gt;(&lt;span class=&quot;cns&quot;&gt;errno&lt;/span&gt;, &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;generic_category&lt;/span&gt;());
&lt;span class=&quot;ln&quot;&gt;729  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#ifndef O_CLOEXEC&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;730  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; r = &lt;span class=&quot;fs&quot;&gt;fcntl&lt;/span&gt;(ResultFD, &lt;span class=&quot;cns&quot;&gt;F_SETFD&lt;/span&gt;, &lt;span class=&quot;cns&quot;&gt;FD_CLOEXEC&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;731  &lt;/span&gt;  (&lt;span class=&quot;k&quot;&gt;void&lt;/span&gt;)r;
&lt;span class=&quot;ln&quot;&gt;732  &lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;assert&lt;/span&gt;(r == &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt; &amp;amp;&amp;amp; &lt;span class=&quot;s&quot;&gt;&quot;fcntl(F_SETFD, FD_CLOEXEC) failed&quot;&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;733  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#endif&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;758  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;error_code&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;759  &lt;/span&gt;}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The implementation above is long-winded because of two pieces of Unix trivia.&lt;/p&gt;

&lt;p&gt;First off, instead of calling &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;open(2)&lt;/span&gt;&lt;/code&gt; directly, it calls &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;sys&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;RetryAfterSignal&lt;/span&gt;&lt;/code&gt;, which invokes &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;open(2)&lt;/span&gt;&lt;/code&gt; in a &lt;code&gt;&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt;&lt;/code&gt; loop. This loop retries the &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;open(2)&lt;/span&gt;&lt;/code&gt; call if it fails with an &lt;code&gt;&lt;span class=&quot;cns&quot;&gt;EINTR&lt;/span&gt;&lt;/code&gt; error code:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/llvm-mirror/llvm/blob/b5e2d41d5d1fac6bb58a3a2207995b11a42f6eba/include/llvm/Support/Errno.h#L33-L41&quot;&gt;llvm/include/llvm/Support/Errno.h&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;33  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;template&lt;/span&gt; &amp;lt;&lt;span class=&quot;k&quot;&gt;typename&lt;/span&gt; FailT, &lt;span class=&quot;k&quot;&gt;typename&lt;/span&gt; Fun, &lt;span class=&quot;k&quot;&gt;typename&lt;/span&gt;... Args&amp;gt;
&lt;span class=&quot;ln&quot;&gt;34  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;inline&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; RetryAfterSignal(&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;FailT&lt;/span&gt; &amp;amp;Fail, &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;Fun&lt;/span&gt; &amp;amp;F,
&lt;span class=&quot;ln&quot;&gt;35  &lt;/span&gt;                             &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;Args&lt;/span&gt; &amp;amp;... As) -&amp;gt; &lt;span class=&quot;k&quot;&gt;decltype&lt;/span&gt;(F(As...)) {
&lt;span class=&quot;ln&quot;&gt;36  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;decltype&lt;/span&gt;(F(As...)) Res;
&lt;span class=&quot;ln&quot;&gt;37  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;38  &lt;/span&gt;    Res = F(As...);
&lt;span class=&quot;ln&quot;&gt;39  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; (Res == Fail &amp;amp;&amp;amp; &lt;span class=&quot;cns&quot;&gt;errno&lt;/span&gt; == &lt;span class=&quot;cns&quot;&gt;EINTR&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;40  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; Res;
&lt;span class=&quot;ln&quot;&gt;41  &lt;/span&gt;}
&lt;/pre&gt;
&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;I'm not a C++ expert. In case you aren't either, allow me to offer an explanation for the templates being used in the code above.&lt;/p&gt;

  &lt;p&gt;The &lt;code&gt;&lt;span class=&quot;f&quot;&gt;RetryAfterSignal&lt;/span&gt;&lt;/code&gt; function has three template parameters:&lt;/p&gt;
  &lt;ol&gt;
    &lt;li&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;FailT&lt;/span&gt; &amp;amp;Fail&lt;/code&gt;, representing a value returned when the function call fails.&lt;/li&gt;
    &lt;li&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;Fun&lt;/span&gt; &amp;amp;F&lt;/code&gt;, representing the callable function.&lt;/li&gt;
    &lt;li&gt;A template parameter pack &lt;code&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;Args&lt;/span&gt; &amp;amp;... As&lt;/code&gt;, representing the arguments passed to function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;F&lt;/code&gt;.&lt;/li&gt;
  &lt;/ol&gt;

  &lt;p&gt;&lt;code&gt;&lt;span class=&quot;f&quot;&gt;RetryAfterSignal&lt;/span&gt;&lt;/code&gt; uses the trailing return type syntax, of the form &lt;code&gt;&lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; &lt;i&gt;function&lt;/i&gt; -&amp;gt; &lt;i&gt;return_type&lt;/i&gt;&lt;/code&gt;. Its return type is specified as &lt;code&gt;&lt;span class=&quot;k&quot;&gt;decltype&lt;/span&gt;(F(As...))&lt;/code&gt;. In other words, the return type is the type returned by the expression &lt;code&gt;F(As...)&lt;/code&gt;.&lt;/p&gt;

  &lt;p&gt;To map this all to the concrete example we were looking at in &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;sys&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;fs&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;openFileForRead&lt;/span&gt;&lt;/code&gt;, recall that function had the expression &lt;code&gt;&lt;span class=&quot;t&quot;&gt;sys&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;RetryAfterSignal&lt;/span&gt;(&lt;span class=&quot;num&quot;&gt;-1&lt;/span&gt;, &lt;span class=&quot;fs&quot;&gt;open&lt;/span&gt;, P.&lt;span class=&quot;f&quot;&gt;begin&lt;/span&gt;(), OpenFlags)&lt;/code&gt;. Here &lt;code&gt;&lt;span class=&quot;num&quot;&gt;-1&lt;/span&gt;&lt;/code&gt; is the failure value &lt;code&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;FailT&lt;/span&gt; &amp;amp;Fail&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;open&lt;/span&gt;&lt;/code&gt; is the function value &lt;code&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;Fun&lt;/span&gt; &amp;amp;F&lt;/code&gt;, and &lt;code&gt;(P.&lt;span class=&quot;f&quot;&gt;begin&lt;/span&gt;(), OpenFlags)&lt;/code&gt; are the template parameter pack arguments passed into the &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;open&lt;/span&gt;&lt;/code&gt; function. The return type is the type returned by &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;open&lt;/span&gt;(P.&lt;span class=&quot;f&quot;&gt;begin&lt;/span&gt;(), OpenFlags)&lt;/code&gt;, which is &lt;code&gt;&lt;span class=&quot;k&quot;&gt;int&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;sys&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;RetryAfterSignal&lt;/span&gt;&lt;/code&gt; function ignores the &lt;code&gt;&lt;span class=&quot;cns&quot;&gt;EINTR&lt;/span&gt;&lt;/code&gt; and retries because &quot;blocking&quot; Unix functions like &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;open(2)&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;read(2)&lt;/span&gt;&lt;/code&gt; return &lt;code&gt;&lt;span class=&quot;cns&quot;&gt;EINTR&lt;/span&gt;&lt;/code&gt; whenever they are interrupted by a Unix signal. Interruptions like this can occur for all sorts of reasons, some of which you can read more about &lt;a href=&quot;http://250bpm.com/blog:12&quot;&gt;here&lt;/a&gt;. In these cases, LLVM will simply try again.&lt;/p&gt;

&lt;p&gt;The other quirk in the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;sys&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;fs&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;openFileForRead&lt;/span&gt;&lt;/code&gt; implementation is the check for &lt;code&gt;&lt;span class=&quot;cns&quot;&gt;O_CLOEXEC&lt;/span&gt;&lt;/code&gt;, an &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;open(2)&lt;/span&gt;&lt;/code&gt; flag that only exists on Linux 2.6.23 and above. This option has the OS automatically close the file descriptor if the process forks. If it's not available, the implementation uses the syscall &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;fcntl&lt;/span&gt;&lt;/code&gt; in order to set a similar flag.&lt;/p&gt;

&lt;h2 id=&quot;reading-the-file-into-an-llvmwritablememorybuffer&quot;&gt;Reading the file into an &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;WritableMemoryBuffer&lt;/span&gt;&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;sys&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;fs&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;openFileForRead&lt;/span&gt;&lt;/code&gt; function opens a file and returns its file descriptor. Then control is returned back to the &lt;code&gt;&lt;span class=&quot;f&quot;&gt;getFileAux&lt;/span&gt;&lt;/code&gt; function, which passes the open descriptor into the &lt;code&gt;&lt;span class=&quot;f&quot;&gt;getOpenFileImpl&lt;/span&gt;&lt;/code&gt; static function:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/llvm-mirror/llvm/blob/b5e2d41d5d1fac6bb58a3a2207995b11a42f6eba/lib/Support/MemoryBuffer.cpp#L242-L256&quot;&gt;llvm/lib/Support/MemoryBuffer.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;242  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;template&lt;/span&gt; &amp;lt;&lt;span class=&quot;k&quot;&gt;typename&lt;/span&gt; MB&amp;gt;
&lt;span class=&quot;ln&quot;&gt;243  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;ErrorOr&lt;/span&gt;&amp;lt;&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;MB&lt;/span&gt;&amp;gt;&amp;gt;
&lt;span class=&quot;ln&quot;&gt;244  &lt;/span&gt;getFileAux(&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Twine&lt;/span&gt; &amp;amp;Filename, &lt;span class=&quot;k&quot;&gt;int64_t&lt;/span&gt; FileSize, &lt;span class=&quot;k&quot;&gt;uint64_t&lt;/span&gt; MapSize,
&lt;span class=&quot;ln&quot;&gt;245  &lt;/span&gt;           &lt;span class=&quot;k&quot;&gt;uint64_t&lt;/span&gt; Offset, &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; RequiresNullTerminator, &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; IsVolatile) {
&lt;span class=&quot;ln&quot;&gt;246  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; FD;
&lt;span class=&quot;ln&quot;&gt;247  &lt;/span&gt;  &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;error_code&lt;/span&gt; EC = &lt;span class=&quot;t&quot;&gt;sys&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;fs&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;openFileForRead&lt;/span&gt;(Filename, FD);
&lt;span class=&quot;ln&quot;&gt;248  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;249  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (EC)
&lt;span class=&quot;ln&quot;&gt;250  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; EC;
&lt;span class=&quot;ln&quot;&gt;251  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;252  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; Ret = &lt;span class=&quot;f&quot;&gt;getOpenFileImpl&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;MB&lt;/span&gt;&amp;gt;(FD, Filename, FileSize, MapSize, Offset,
&lt;span class=&quot;ln&quot;&gt;253  &lt;/span&gt;                                 RequiresNullTerminator, IsVolatile);
&lt;span class=&quot;ln&quot;&gt;254  &lt;/span&gt;  &lt;span class=&quot;fs&quot;&gt;close&lt;/span&gt;(FD);
&lt;span class=&quot;ln&quot;&gt;255  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; Ret;
&lt;span class=&quot;ln&quot;&gt;256  &lt;/span&gt;}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;f&quot;&gt;getOpenFileImpl&lt;/span&gt;&lt;/code&gt; implements the same logic the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read.cpp&lt;/code&gt; example at the beginning of this article did. If the file's size was not provided, it finds out how large the file is by calling &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;sys&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;fs&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;status&lt;/span&gt;&lt;/code&gt;, which on Unix calls &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;fstat&lt;/span&gt;&lt;/code&gt;. It then makes a decision as to whether to use &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;mmap(2)&lt;/span&gt;&lt;/code&gt; or to allocate memory up front using &lt;code&gt;&lt;span class=&quot;k&quot;&gt;operator new&lt;/span&gt;&lt;/code&gt;. If it allocates memory, then it uses the system call &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;read(2)&lt;/span&gt;&lt;/code&gt; (or &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;pread&lt;/span&gt;&lt;/code&gt;, if &lt;code&gt;&lt;span class=&quot;v&quot;&gt;HAVE_PREAD&lt;/span&gt;&lt;/code&gt; is true) in order to read the bytes of the file into memory:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/llvm-mirror/llvm/blob/b5e2d41d5d1fac6bb58a3a2207995b11a42f6eba/lib/Support/MemoryBuffer.cpp#L229-L256&quot;&gt;llvm/lib/Support/MemoryBuffer.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;416  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;template&lt;/span&gt; &amp;lt;&lt;span class=&quot;k&quot;&gt;typename&lt;/span&gt; MB&amp;gt;
&lt;span class=&quot;ln&quot;&gt;417  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;ErrorOr&lt;/span&gt;&amp;lt;&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;MB&lt;/span&gt;&amp;gt;&amp;gt;
&lt;span class=&quot;ln&quot;&gt;418  &lt;/span&gt;getOpenFileImpl(&lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; FD, &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Twine&lt;/span&gt; &amp;amp;Filename, &lt;span class=&quot;k&quot;&gt;uint64_t&lt;/span&gt; FileSize,
&lt;span class=&quot;ln&quot;&gt;419  &lt;/span&gt;                &lt;span class=&quot;k&quot;&gt;uint64_t&lt;/span&gt; MapSize, &lt;span class=&quot;k&quot;&gt;int64_t&lt;/span&gt; Offset, &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; RequiresNullTerminator,
&lt;span class=&quot;ln&quot;&gt;420  &lt;/span&gt;                &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; IsVolatile) {
&lt;span class=&quot;ln&quot;&gt;421  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; PageSize = &lt;span class=&quot;t&quot;&gt;sys&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Process&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getPageSize&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;422  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;423  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// Default is to map the full file.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;424  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (MapSize == &lt;span class=&quot;k&quot;&gt;uint64_t&lt;/span&gt;(&lt;span class=&quot;num&quot;&gt;-1&lt;/span&gt;)) {
&lt;span class=&quot;ln&quot;&gt;425  &lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// If we don't know the file size, use fstat to find out.  fstat on an open&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;426  &lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// file descriptor is cheaper than stat on a random path.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;427  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (FileSize == &lt;span class=&quot;k&quot;&gt;uint64_t&lt;/span&gt;(&lt;span class=&quot;num&quot;&gt;-1&lt;/span&gt;)) {
&lt;span class=&quot;ln&quot;&gt;428  &lt;/span&gt;      &lt;span class=&quot;t&quot;&gt;sys&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;fs&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;file_status&lt;/span&gt; Status;
&lt;span class=&quot;ln&quot;&gt;429  &lt;/span&gt;      &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;error_code&lt;/span&gt; EC = &lt;span class=&quot;t&quot;&gt;sys&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;fs&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;status&lt;/span&gt;(FD, Status);
&lt;span class=&quot;ln&quot;&gt;430  &lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (EC)
&lt;span class=&quot;ln&quot;&gt;431  &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; EC;
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;441  &lt;/span&gt;      FileSize = Status.&lt;span class=&quot;f&quot;&gt;getSize&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;442  &lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;443  &lt;/span&gt;    MapSize = FileSize;
&lt;span class=&quot;ln&quot;&gt;444  &lt;/span&gt;  }
&lt;span class=&quot;ln&quot;&gt;445  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;446  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;f&quot;&gt;shouldUseMmap&lt;/span&gt;(FD, FileSize, MapSize, Offset, RequiresNullTerminator,
&lt;span class=&quot;ln&quot;&gt;447  &lt;/span&gt;                    PageSize, IsVolatile)) {
&lt;span class=&quot;ln&quot;&gt;448  &lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;error_code&lt;/span&gt; EC;
&lt;span class=&quot;ln&quot;&gt;449  &lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;MB&lt;/span&gt;&amp;gt; Result(
&lt;span class=&quot;ln&quot;&gt;450  &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; (&lt;span class=&quot;cl&quot;&gt;NamedBufferAlloc&lt;/span&gt;(Filename)) &lt;span class=&quot;cl&quot;&gt;MemoryBufferMMapFile&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;MB&lt;/span&gt;&amp;gt;(
&lt;span class=&quot;ln&quot;&gt;451  &lt;/span&gt;            RequiresNullTerminator, FD, MapSize, Offset, EC));
&lt;span class=&quot;ln&quot;&gt;452  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (!EC)
&lt;span class=&quot;ln&quot;&gt;453  &lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;move&lt;/span&gt;(Result);
&lt;span class=&quot;ln&quot;&gt;454  &lt;/span&gt;  }
&lt;span class=&quot;ln&quot;&gt;455  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;456  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; Buf = &lt;span class=&quot;cl&quot;&gt;WritableMemoryBuffer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getNewUninitMemBuffer&lt;/span&gt;(MapSize, Filename);
&lt;span class=&quot;ln&quot;&gt;457  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (!Buf) {
&lt;span class=&quot;ln&quot;&gt;458  &lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// Failed to create a buffer. The only way it can fail is if&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;459  &lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// new(std::nothrow) returns 0.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;460  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;f&quot;&gt;make_error_code&lt;/span&gt;(&lt;span class=&quot;ts&quot;&gt;errc&lt;/span&gt;::&lt;span class=&quot;cns&quot;&gt;not_enough_memory&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;461  &lt;/span&gt;  }
&lt;span class=&quot;ln&quot;&gt;462  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;463  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; *BufPtr = Buf.&lt;span class=&quot;f&quot;&gt;get&lt;/span&gt;()-&amp;gt;&lt;span class=&quot;f&quot;&gt;getBufferStart&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;464  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;465  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;size_t&lt;/span&gt; BytesLeft = MapSize;
&lt;span class=&quot;ln&quot;&gt;466  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#ifndef HAVE_PREAD&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;467  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (lseek(FD, Offset, SEEK_SET) == &lt;span class=&quot;num&quot;&gt;-1&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt;468  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;error_code&lt;/span&gt;(&lt;span class=&quot;cns&quot;&gt;errno&lt;/span&gt;, &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;generic_category&lt;/span&gt;());
&lt;span class=&quot;ln&quot;&gt;469  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#endif&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;470  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;471  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; (BytesLeft) {
&lt;span class=&quot;ln&quot;&gt;472  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#ifdef HAVE_PREAD&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;473  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;ssize_t&lt;/span&gt; NumRead = &lt;span class=&quot;t&quot;&gt;sys&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;RetryAfterSignal&lt;/span&gt;(&lt;span class=&quot;num&quot;&gt;-1&lt;/span&gt;, ::&lt;span class=&quot;fs&quot;&gt;pread&lt;/span&gt;, FD, BufPtr, BytesLeft,
&lt;span class=&quot;ln&quot;&gt;474  &lt;/span&gt;                                            MapSize - BytesLeft + Offset);
&lt;span class=&quot;ln&quot;&gt;475  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#else&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;476  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;ssize_t&lt;/span&gt; NumRead = &lt;span class=&quot;t&quot;&gt;sys&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;RetryAfterSignal&lt;/span&gt;(&lt;span class=&quot;num&quot;&gt;-1&lt;/span&gt;, ::&lt;span class=&quot;fs&quot;&gt;read&lt;/span&gt;, FD, BufPtr, BytesLeft);
&lt;span class=&quot;ln&quot;&gt;477  &lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;#endif&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;478  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (NumRead == &lt;span class=&quot;num&quot;&gt;-1&lt;/span&gt;) {
&lt;span class=&quot;ln&quot;&gt;479  &lt;/span&gt;      &lt;span class=&quot;c&quot;&gt;// Error while reading.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;480  &lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;error_code&lt;/span&gt;(&lt;span class=&quot;cns&quot;&gt;errno&lt;/span&gt;, &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;generic_category&lt;/span&gt;());
&lt;span class=&quot;ln&quot;&gt;481  &lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;482  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (NumRead == &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;) {
&lt;span class=&quot;ln&quot;&gt;483  &lt;/span&gt;      &lt;span class=&quot;fs&quot;&gt;memset&lt;/span&gt;(BufPtr, &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;, BytesLeft); &lt;span class=&quot;c&quot;&gt;// zero-initialize rest of the buffer.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;484  &lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;485  &lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;486  &lt;/span&gt;    BytesLeft -= NumRead;
&lt;span class=&quot;ln&quot;&gt;487  &lt;/span&gt;    BufPtr += NumRead;
&lt;span class=&quot;ln&quot;&gt;488  &lt;/span&gt;  }
&lt;span class=&quot;ln&quot;&gt;489  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;490  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;move&lt;/span&gt;(Buf);
&lt;span class=&quot;ln&quot;&gt;491  &lt;/span&gt;}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The functions &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;sys&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Process&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getPageSize&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;sys&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;fs&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;status&lt;/span&gt;&lt;/code&gt; above use the same CMake tricks as &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;sys&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;fs&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;openFileForRead&lt;/span&gt;&lt;/code&gt; did in order to include a platform-specific implementation: &lt;code&gt;&lt;span class=&quot;f&quot;&gt;getPageSize&lt;/span&gt;&lt;/code&gt; is implemented in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;llvm/lib/Support/Unix/Process.inc&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Windows/Process.inc&lt;/code&gt;, and &lt;code&gt;&lt;span class=&quot;f&quot;&gt;status&lt;/span&gt;&lt;/code&gt; is implemented in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Unix/Path.inc&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Windows/Path.inc&lt;/code&gt;. On Unix they use system calls &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;getpagesize&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;fstat&lt;/span&gt;&lt;/code&gt; in order to get the information they need from the operating system.&lt;/p&gt;

&lt;p&gt;The code above instantiates either an &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBufferMMapFile&lt;/span&gt;&lt;/code&gt; or an &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;WritableMemoryBuffer&lt;/span&gt;&lt;/code&gt; based on whether the helper function &lt;code&gt;&lt;span class=&quot;f&quot;&gt;shouldUseMMap&lt;/span&gt;&lt;/code&gt; returns &lt;code&gt;&lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;&lt;/code&gt;. As it was in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read.cpp&lt;/code&gt; example at the beginning of this article, one criteria for that decision is the size of the file – for example, if it's smaller than a page on the system, or smaller than 16 kilobytes, then &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;mmap(2)&lt;/span&gt;&lt;/code&gt; is not used:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/llvm-mirror/llvm/blob/b5e2d41d5d1fac6bb58a3a2207995b11a42f6eba/lib/Support/MemoryBuffer.cpp#L308-L361&quot;&gt;llvm/lib/Support/MemoryBuffer.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;308  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;f&quot;&gt;shouldUseMmap&lt;/span&gt;(&lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; FD,
&lt;span class=&quot;ln&quot;&gt;309  &lt;/span&gt;                          &lt;span class=&quot;k&quot;&gt;size_t&lt;/span&gt; FileSize,
&lt;span class=&quot;ln&quot;&gt;310  &lt;/span&gt;                          &lt;span class=&quot;k&quot;&gt;size_t&lt;/span&gt; MapSize,
&lt;span class=&quot;ln&quot;&gt;311  &lt;/span&gt;                          &lt;span class=&quot;ts&quot;&gt;off_t&lt;/span&gt; Offset,
&lt;span class=&quot;ln&quot;&gt;312  &lt;/span&gt;                          &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; RequiresNullTerminator,
&lt;span class=&quot;ln&quot;&gt;313  &lt;/span&gt;                          &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; PageSize,
&lt;span class=&quot;ln&quot;&gt;314  &lt;/span&gt;                          &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; IsVolatile) {
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;321  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// We don't use mmap for small files because this can severely fragment our&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;322  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// address space.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;323  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (MapSize &amp;lt; &lt;span class=&quot;num&quot;&gt;4&lt;/span&gt; * &lt;span class=&quot;num&quot;&gt;4096&lt;/span&gt; || MapSize &amp;lt; (&lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt;)PageSize)
&lt;span class=&quot;ln&quot;&gt;324  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;360  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;361  &lt;/span&gt;}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Assuming &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;mmap(2)&lt;/span&gt;&lt;/code&gt; is not used, then the &lt;code&gt;&lt;span class=&quot;f&quot;&gt;getOpenFileImpl&lt;/span&gt;&lt;/code&gt; function calls the static function &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;WritableMemoryBuffer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getNewUninitMemBuffer&lt;/span&gt;&lt;/code&gt;. This function allocates the buffer memory just as the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read.cpp&lt;/code&gt; example did, by using &lt;code&gt;&lt;span class=&quot;k&quot;&gt;operator new&lt;/span&gt;&lt;/code&gt;. Unlike the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read.cpp&lt;/code&gt; example program, however, this function not only allocates memory for a buffer to store the file's contents, it also allocates space for an instance of the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt; class, and for the name of the file:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/llvm-mirror/llvm/blob/b5e2d41d5d1fac6bb58a3a2207995b11a42f6eba/lib/Support/MemoryBuffer.cpp#L273-L297&quot;&gt;llvm/lib/Support/MemoryBuffer.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;273  &lt;/span&gt;&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;W&lt;span class=&quot;cl&quot;&gt;ritableMemoryBuffer&lt;/span&gt;&amp;gt;
&lt;span class=&quot;ln&quot;&gt;274  &lt;/span&gt;&lt;span class=&quot;cl&quot;&gt;WritableMemoryBuffer&lt;/span&gt;::getNewUninitMemBuffer(&lt;span class=&quot;k&quot;&gt;size_t&lt;/span&gt; Size, &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Twine&lt;/span&gt; &amp;amp;BufferName) {
&lt;span class=&quot;ln&quot;&gt;275  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; MemBuffer = &lt;span class=&quot;cl&quot;&gt;MemoryBufferMem&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;WritableMemoryBuffer&lt;/span&gt;&amp;gt;;
&lt;span class=&quot;ln&quot;&gt;276  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// Allocate space for the MemoryBuffer, the data and the name. It is important&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;277  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// that MemoryBuffer and data are aligned so PointerIntPair works with them.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;280  &lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;SmallString&lt;/span&gt;&amp;lt;&lt;span class=&quot;num&quot;&gt;256&lt;/span&gt;&amp;gt; NameBuf;
&lt;span class=&quot;ln&quot;&gt;281  &lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt; NameRef = BufferName.&lt;span class=&quot;f&quot;&gt;toStringRef&lt;/span&gt;(NameBuf);
&lt;span class=&quot;ln&quot;&gt;282  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;size_t&lt;/span&gt; AlignedStringLen = &lt;span class=&quot;f&quot;&gt;alignTo&lt;/span&gt;(&lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;(MemBuffer) + NameRef.&lt;span class=&quot;f&quot;&gt;size&lt;/span&gt;() + &lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;num&quot;&gt;16&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;283  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;size_t&lt;/span&gt; RealLen = AlignedStringLen + Size + &lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;284  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; *Mem = &lt;span class=&quot;k&quot;&gt;static_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;char&lt;/span&gt;*&amp;gt;(&lt;span class=&quot;k&quot;&gt;operator new&lt;/span&gt;(RealLen, &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;vs&quot;&gt;nothrow&lt;/span&gt;));
&lt;span class=&quot;ln&quot;&gt;285  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (!Mem)
&lt;span class=&quot;ln&quot;&gt;286  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;287  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;288  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// The name is stored after the class itself.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;289  &lt;/span&gt;  &lt;span class=&quot;f&quot;&gt;CopyStringRef&lt;/span&gt;(Mem + &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;(&lt;span class=&quot;t&quot;&gt;MemBuffer&lt;/span&gt;), NameRef);
&lt;span class=&quot;ln&quot;&gt;290  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;291  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// The buffer begins after the name and must be aligned.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;292  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; *Buf = Mem + AlignedStringLen;
&lt;span class=&quot;ln&quot;&gt;293  &lt;/span&gt;  Buf[Size] = &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;; &lt;span class=&quot;c&quot;&gt;// Null terminate buffer.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;294  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;295  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; *Ret = &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; (Mem) &lt;span class=&quot;t&quot;&gt;MemBuffer&lt;/span&gt;(&lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt;(Buf, Size), &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;296  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;WritableMemoryBuffer&lt;/span&gt;&amp;gt;(Ret);
&lt;span class=&quot;ln&quot;&gt;297  &lt;/span&gt;}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Based on the code above, I can see that the memory that's being allocated here is laid out in three distinct segments:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://d3vv6lp55qjaqc.cloudfront.net/items/1I3z1N1f2s1Z0l46353g/Screen%20Shot%202018-05-06%20at%205.12.06%20PM.png?X-CloudApp-Visitor-Id=543005&quot; alt=&quot;The memory for &amp;lt;code&amp;gt;&amp;lt;span class=&amp;quot;t&amp;quot;&amp;gt;llvm&amp;lt;/span&amp;gt;::&amp;lt;span class=&amp;quot;cl&amp;quot;&amp;gt;MemoryBuffer&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt; is laid out in three segments.&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The first segment of memory allocated is sized such that an instance of &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBufferMem&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;WritableMemoryBuffer&lt;/span&gt;&amp;gt;&lt;/code&gt; could fit within it. Note that the size is calculated using &lt;code&gt;&lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;(&lt;span class=&quot;t&quot;&gt;MemBuffer&lt;/span&gt;)&lt;/code&gt;, and then the memory buffer is instantiated by calling &lt;code&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; (Mem) &lt;span class=&quot;t&quot;&gt;MemBuffer&lt;/span&gt;(...)&lt;/code&gt;. As I mentioned in my article on &lt;a href=&quot;/the-swift-frontend-lexing-and-parsing&quot;&gt;Getting Started with the Swift Frontend: Lexing &amp;amp; Parsing&lt;/a&gt;, this is a &quot;placement&quot; &lt;code&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;/code&gt; operator call. It doesn't allocate any memory, and instead calls the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;MemBuffer&lt;/span&gt;&lt;/code&gt; constructor, and then places the constructed instance in the chunk of memory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Mem&lt;/code&gt;. (You can read more about &quot;placement new&quot; &lt;a href=&quot;http://en.cppreference.com/w/cpp/language/new#Placement_new&quot;&gt;here&lt;/a&gt;.)&lt;/li&gt;
  &lt;li&gt;The second segment of memory stores the name of the buffer. It's sized using the call to &lt;code&gt;NameRef.&lt;span class=&quot;f&quot;&gt;size&lt;/span&gt;()&lt;/code&gt; above, and then the name is copied by calling the static helper function &lt;code&gt;&lt;span class=&quot;f&quot;&gt;CopyStringRef&lt;/span&gt;&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Finally comes the rest of the buffer, which is the same size as the file being read into it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The memory buffer allocated and returned by the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;WritableMemoryBuffer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getNewUninitMemBuffer&lt;/span&gt;&lt;/code&gt; function is an &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBufferMem&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;WritableMemoryBuffer&lt;/span&gt;&amp;gt;&lt;/code&gt;. &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;MemoryBufferMem&lt;/span&gt;&amp;lt;T&amp;gt;&lt;/code&gt; is defined as a subclass of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T&lt;/code&gt;. In this case, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T&lt;/code&gt; is an &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;WritableMemoryBuffer&lt;/span&gt;&lt;/code&gt;, which in turn derives from &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt;. The constructor of &lt;span class=&quot;cl&quot;&gt;MemoryBufferMem&lt;/span&gt; calls through to &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;init&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/llvm-mirror/llvm/blob/b5e2d41d5d1fac6bb58a3a2207995b11a42f6eba/lib/Support/MemoryBuffer.cpp#L83-L104&quot;&gt;llvm/lib/Support/MemoryBuffer.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt; 83  &lt;/span&gt;&lt;span class=&quot;d&quot;&gt;/// MemoryBufferMem - Named MemoryBuffer pointing to a block of memory.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 84  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;typename&lt;/span&gt; MB&amp;gt;
&lt;span class=&quot;ln&quot;&gt; 85  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; MemoryBufferMem : &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;MB&lt;/span&gt; {
&lt;span class=&quot;ln&quot;&gt; 86  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;public:&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 87  &lt;/span&gt;  MemoryBufferMem(&lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt; InputData, &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; RequiresNullTerminator) {
&lt;span class=&quot;ln&quot;&gt; 88  &lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;init&lt;/span&gt;(InputData.&lt;span class=&quot;f&quot;&gt;begin&lt;/span&gt;(), InputData.&lt;span class=&quot;f&quot;&gt;end&lt;/span&gt;(),
&lt;span class=&quot;ln&quot;&gt; 89  &lt;/span&gt;                       RequiresNullTerminator);
&lt;span class=&quot;ln&quot;&gt; 90  &lt;/span&gt;  }
&lt;span class=&quot;ln&quot;&gt; 91  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 92  &lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// Disable sized deallocation for MemoryBufferMem, because it has&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 93  &lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// tail-allocated data.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 94  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;void operator&lt;/span&gt; delete(&lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; *p) { ::&lt;span class=&quot;k&quot;&gt;operator delete&lt;/span&gt;(p); }
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;104  &lt;/span&gt;};
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;And the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;init&lt;/span&gt;&lt;/code&gt; function simply sets private members pointing to the beginning and end of the buffer:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/llvm-mirror/llvm/blob/b5e2d41d5d1fac6bb58a3a2207995b11a42f6eba/include/llvm/Support/MemoryBuffer.h#L42-L154&quot;&gt;llvm/include/llvm/Support/MemoryBuffer.h&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;  42  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; MemoryBuffer {
&lt;span class=&quot;ln&quot;&gt;  43  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; *BufferStart; &lt;span class=&quot;c&quot;&gt;// Start of the buffer.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;  44  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; *BufferEnd;   &lt;span class=&quot;c&quot;&gt;// End of the buffer.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;  ..&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 154  &lt;/span&gt;};
&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/llvm-mirror/llvm/blob/b5e2d41d5d1fac6bb58a3a2207995b11a42f6eba/lib/Support/MemoryBuffer.cpp#L83-L104&quot;&gt;llvm/lib/Support/MemoryBuffer.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt; 44  &lt;/span&gt;&lt;span class=&quot;d&quot;&gt;/// init - Initialize this MemoryBuffer as a reference to externally allocated&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 45  &lt;/span&gt;&lt;span class=&quot;d&quot;&gt;/// memory, memory that we know is already null terminated.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 46  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;::init(&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; *BufStart, &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; *BufEnd,
&lt;span class=&quot;ln&quot;&gt; 47  &lt;/span&gt;                        &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; RequiresNullTerminator) {
&lt;span class=&quot;ln&quot;&gt; 48  &lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;assert&lt;/span&gt;((!RequiresNullTerminator || BufEnd[&lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;] == &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;) &amp;amp;&amp;amp;
&lt;span class=&quot;ln&quot;&gt; 49  &lt;/span&gt;         &lt;span class=&quot;s&quot;&gt;&quot;Buffer is not null terminated!&quot;&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt; 50  &lt;/span&gt;  &lt;span class=&quot;v&quot;&gt;BufferStart&lt;/span&gt; = BufStart;
&lt;span class=&quot;ln&quot;&gt; 51  &lt;/span&gt;  &lt;span class=&quot;v&quot;&gt;BufferEnd&lt;/span&gt; = BufEnd;
&lt;span class=&quot;ln&quot;&gt; 52  &lt;/span&gt;}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;In summary, on a Unix system:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getFileOrSTDIN&lt;/span&gt;&lt;/code&gt; static function checks whether its been given a filename of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;-&quot;&lt;/code&gt; and, if it has, calls &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getSTDIN&lt;/span&gt;&lt;/code&gt;. Otherwise, it calls &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getFile&lt;/span&gt;&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getFile&lt;/span&gt;&lt;/code&gt; calls through to &lt;code&gt;&lt;span class=&quot;f&quot;&gt;getFileAux&lt;/span&gt;&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;&lt;span class=&quot;f&quot;&gt;getFileAux&lt;/span&gt;&lt;/code&gt; gets an open file descriptor by calling &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;sys&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;fs&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;openFileForRead&lt;/span&gt;&lt;/code&gt;, then &lt;code&gt;&lt;span class=&quot;f&quot;&gt;getOpenFileImpl&lt;/span&gt;&lt;/code&gt; to instantiate a new &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt; and read in the contents of the file, and finally&lt;code&gt;&lt;span class=&quot;fs&quot;&gt;`close(2)&lt;/span&gt;&lt;/code&gt; in order to close the file descriptor.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;&lt;span class=&quot;f&quot;&gt;getOpenFileImpl&lt;/span&gt;&lt;/code&gt; checks the file size and determines whether to use &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;mmap(2)&lt;/span&gt;&lt;/code&gt;. If &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;mmap(2)&lt;/span&gt;&lt;/code&gt; is not used, then &lt;code&gt;&lt;span class=&quot;f&quot;&gt;getOpenFileImpl&lt;/span&gt;&lt;/code&gt; allocates memory for an &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt;, its name, and its contents. It then reads in the contents of the file using &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;read(2)&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;pread&lt;/span&gt;&lt;/code&gt;, depending on what's available on the operating system.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;mapping-the-file-into-an-llvmmemorybuffermmapfile&quot;&gt;Mapping the file into an &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBufferMMapFile&lt;/span&gt;&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;Recall that &lt;code&gt;&lt;span class=&quot;f&quot;&gt;getOpenFileImpl&lt;/span&gt;&lt;/code&gt; instantiates an &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBufferMMapFile&lt;/span&gt;&lt;/code&gt; if &lt;code&gt;&lt;span class=&quot;f&quot;&gt;shouldUseMMap&lt;/span&gt;&lt;/code&gt; returns &lt;code&gt;&lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/llvm-mirror/llvm/blob/b5e2d41d5d1fac6bb58a3a2207995b11a42f6eba/lib/Support/MemoryBuffer.cpp#L229-L256&quot;&gt;llvm/lib/Support/MemoryBuffer.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;416  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;template&lt;/span&gt; &amp;lt;&lt;span class=&quot;k&quot;&gt;typename&lt;/span&gt; MB&amp;gt;
&lt;span class=&quot;ln&quot;&gt;417  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;ErrorOr&lt;/span&gt;&amp;lt;&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;MB&lt;/span&gt;&amp;gt;&amp;gt;
&lt;span class=&quot;ln&quot;&gt;418  &lt;/span&gt;getOpenFileImpl(&lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; FD, &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Twine&lt;/span&gt; &amp;amp;Filename, &lt;span class=&quot;k&quot;&gt;uint64_t&lt;/span&gt; FileSize,
&lt;span class=&quot;ln&quot;&gt;419  &lt;/span&gt;                &lt;span class=&quot;k&quot;&gt;uint64_t&lt;/span&gt; MapSize, &lt;span class=&quot;k&quot;&gt;int64_t&lt;/span&gt; Offset, &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; RequiresNullTerminator,
&lt;span class=&quot;ln&quot;&gt;420  &lt;/span&gt;                &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; IsVolatile) {
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;446  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;f&quot;&gt;shouldUseMmap&lt;/span&gt;(FD, FileSize, MapSize, Offset, RequiresNullTerminator,
&lt;span class=&quot;ln&quot;&gt;447  &lt;/span&gt;                    PageSize, IsVolatile)) {
&lt;span class=&quot;ln&quot;&gt;448  &lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;error_code&lt;/span&gt; EC;
&lt;span class=&quot;ln&quot;&gt;449  &lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;MB&lt;/span&gt;&amp;gt; Result(
&lt;span class=&quot;ln&quot;&gt;450  &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; (&lt;span class=&quot;cl&quot;&gt;NamedBufferAlloc&lt;/span&gt;(Filename)) &lt;span class=&quot;cl&quot;&gt;MemoryBufferMMapFile&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;MB&lt;/span&gt;&amp;gt;(
&lt;span class=&quot;ln&quot;&gt;451  &lt;/span&gt;            RequiresNullTerminator, FD, MapSize, Offset, EC));
&lt;span class=&quot;ln&quot;&gt;452  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (!EC)
&lt;span class=&quot;ln&quot;&gt;453  &lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;move&lt;/span&gt;(Result);
&lt;span class=&quot;ln&quot;&gt;454  &lt;/span&gt;  }
&lt;span class=&quot;ln&quot;&gt;455  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;456  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; Buf = &lt;span class=&quot;cl&quot;&gt;WritableMemoryBuffer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getNewUninitMemBuffer&lt;/span&gt;(MapSize, Filename);
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;490  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;move&lt;/span&gt;(Buf);
&lt;span class=&quot;ln&quot;&gt;491  &lt;/span&gt;}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBufferMMapFile&lt;/span&gt;&lt;/code&gt; class makes use of the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;sys&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;fs&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;mapped_file_region&lt;/span&gt;&lt;/code&gt; class, a wrapper around the &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;mmap(2)&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;munmap&lt;/span&gt;&lt;/code&gt; system calls:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/llvm-mirror/llvm/blob/b5e2d41d5d1fac6bb58a3a2207995b11a42f6eba/lib/Support/MemoryBuffer.cpp#L166-L208&quot;&gt;llvm/lib/Support/MemoryBuffer.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;166  &lt;/span&gt;&lt;span class=&quot;d&quot;&gt;/// &lt;span class=&quot;dk&quot;&gt;\brief&lt;/span&gt; Memory maps a file descriptor using sys::fs::mapped_file_region.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;167  &lt;/span&gt;&lt;span class=&quot;d&quot;&gt;///&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;168  &lt;/span&gt;&lt;span class=&quot;d&quot;&gt;/// This handles converting the offset into a legal offset on the platform.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;169  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;template&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;typename&lt;/span&gt; MB&amp;gt;
&lt;span class=&quot;ln&quot;&gt;170  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; MemoryBufferMMapFile : &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;MB&lt;/span&gt; {
&lt;span class=&quot;ln&quot;&gt;171  &lt;/span&gt;  &lt;span class=&quot;t&quot;&gt;sys&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;fs&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;mapped_file_region&lt;/span&gt; MFR;
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;185  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;public:&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;186  &lt;/span&gt;  MemoryBufferMMapFile(&lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; RequiresNullTerminator, &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; FD, &lt;span class=&quot;k&quot;&gt;uint64_t&lt;/span&gt; Len,
&lt;span class=&quot;ln&quot;&gt;187  &lt;/span&gt;                       &lt;span class=&quot;k&quot;&gt;uint64_t&lt;/span&gt; Offset, &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;error_code&lt;/span&gt; &amp;amp;EC)
&lt;span class=&quot;ln&quot;&gt;188  &lt;/span&gt;      : &lt;span class=&quot;v&quot;&gt;MFR&lt;/span&gt;(FD, &lt;span class=&quot;t&quot;&gt;MB&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;Mapmode&lt;/span&gt;, &lt;span class=&quot;f&quot;&gt;getLegalMapSize&lt;/span&gt;(Len, Offset),
&lt;span class=&quot;ln&quot;&gt;189  &lt;/span&gt;            &lt;span class=&quot;f&quot;&gt;getLegalMapOffset&lt;/span&gt;(Offset), EC) {
&lt;span class=&quot;ln&quot;&gt;190  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (!EC) {
&lt;span class=&quot;ln&quot;&gt;191  &lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; *Start = &lt;span class=&quot;f&quot;&gt;getStart&lt;/span&gt;(Len, Offset);
&lt;span class=&quot;ln&quot;&gt;192  &lt;/span&gt;      &lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;init&lt;/span&gt;(Start, Start + Len, RequiresNullTerminator);
&lt;span class=&quot;ln&quot;&gt;193  &lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;194  &lt;/span&gt;  }
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;208  &lt;/span&gt;};
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;mapped_file_region&lt;/span&gt;&lt;/code&gt; constructor calls &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;mapped_file_region&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;init&lt;/span&gt;&lt;/code&gt;, which calls &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;mmap(2)&lt;/span&gt;&lt;/code&gt;. Its destructor calls &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;munmap&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/llvm-mirror/llvm/blob/b5e2d41d5d1fac6bb58a3a2207995b11a42f6eba/lib/Support/Unix/Path.inc#L597-L642&quot;&gt;llvm/lib/Support/Unix/Path.inc&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;597  &lt;/span&gt;&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;error_code&lt;/span&gt; mapped_file_region::init(&lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; FD, &lt;span class=&quot;k&quot;&gt;uint64_t&lt;/span&gt; Offset,
&lt;span class=&quot;ln&quot;&gt;598  &lt;/span&gt;                                         &lt;span class=&quot;t&quot;&gt;mapmode&lt;/span&gt; Mode) {
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;623  &lt;/span&gt;  Mapping = ::&lt;span class=&quot;fs&quot;&gt;mmap&lt;/span&gt;(&lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;, Size, prot, flags, FD, Offset);
&lt;span class=&quot;ln&quot;&gt;624  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (Mapping == &lt;span class=&quot;cns&quot;&gt;MAP_FAILED&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt;625  &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;error_code&lt;/span&gt;(&lt;span class=&quot;cns&quot;&gt;errno&lt;/span&gt;, &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;generic_category&lt;/span&gt;());
&lt;span class=&quot;ln&quot;&gt;626  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;error_code&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;627  &lt;/span&gt;}
&lt;span class=&quot;ln&quot;&gt;628  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;629  &lt;/span&gt;&lt;span class=&quot;cl&quot;&gt;mapped_file_region&lt;/span&gt;::mapped_file_region(&lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; fd, &lt;span class=&quot;t&quot;&gt;mapmode&lt;/span&gt; mode, &lt;span class=&quot;k&quot;&gt;size_t&lt;/span&gt; length,
&lt;span class=&quot;ln&quot;&gt;630  &lt;/span&gt;                                       &lt;span class=&quot;k&quot;&gt;uint64_t&lt;/span&gt; offset, &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;error_code&lt;/span&gt; &amp;amp;ec)
&lt;span class=&quot;ln&quot;&gt;631  &lt;/span&gt;    : &lt;span class=&quot;v&quot;&gt;Size&lt;/span&gt;(length), &lt;span class=&quot;v&quot;&gt;Mapping&lt;/span&gt;(), &lt;span class=&quot;v&quot;&gt;FD&lt;/span&gt;(fd), &lt;span class=&quot;v&quot;&gt;Mode&lt;/span&gt;(mode) {
&lt;span class=&quot;ln&quot;&gt;...  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;634  &lt;/span&gt;  ec = &lt;span class=&quot;f&quot;&gt;init&lt;/span&gt;(fd, offset, mode);
&lt;span class=&quot;ln&quot;&gt;635  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (ec)
&lt;span class=&quot;ln&quot;&gt;636  &lt;/span&gt;    Mapping = &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;637  &lt;/span&gt;}
&lt;span class=&quot;ln&quot;&gt;638  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;639  &lt;/span&gt;&lt;span class=&quot;cl&quot;&gt;mapped_file_region&lt;/span&gt;::~mapped_file_region() {
&lt;span class=&quot;ln&quot;&gt;640  &lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (Mapping)
&lt;span class=&quot;ln&quot;&gt;641  &lt;/span&gt;    ::&lt;span class=&quot;fs&quot;&gt;munmap&lt;/span&gt;(Mapping, Size);
&lt;span class=&quot;ln&quot;&gt;642  &lt;/span&gt;}
&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;what-i-learned&quot;&gt;What I learned&lt;/h2&gt;

&lt;p&gt;Looking into &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt; and how LLVM reads source files into memory taught me a lot:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;At build time LLVM's CMake code determines which platform it's being built for. Based on this, it includes Unix- or Windows-specific implementations, such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;llvm/lib/Support/Unix/Path.inc&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Windows/Path.inc&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Also at build time LLVM CMake determines which system calls are available on the target platform. For example, if &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;pread&lt;/span&gt;&lt;/code&gt; is available, then &lt;code&gt;&lt;span class=&quot;f&quot;&gt;getOpenFileImpl&lt;/span&gt;&lt;/code&gt; will use &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;pread&lt;/span&gt;&lt;/code&gt; to read the file into an &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;WritableMemoryBuffer&lt;/span&gt;&lt;/code&gt;, instead of&lt;code&gt;&lt;span class=&quot;fs&quot;&gt;`read(2)&lt;/span&gt;&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;I can use &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;mmap(2)&lt;/span&gt;&lt;/code&gt; to access the contents of a very large file without allocating a large amount of memory. LLVM's &lt;code&gt;&lt;span class=&quot;f&quot;&gt;shouldUseMMap&lt;/span&gt;&lt;/code&gt; function references the file size, among other characteristics, to determine whether to use pre-allocated memory with &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;WritableMemoryBuffer&lt;/span&gt;&lt;/code&gt;, or &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;mmap(2)&lt;/span&gt;&lt;/code&gt; with &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBufferMMapFile&lt;/span&gt;&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt; maintains a buffer for the contents of a source file as a &quot;trailing object&quot; – a block of memory that is allocated when the class is constructed, but is not a member of the class itself. LLVM uses this trailing object pattern extensively. (It even defines &lt;a href=&quot;http://llvm.org/doxygen/classllvm_1_1TrailingObjects.html&quot;&gt;an &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;TrailingObjects&lt;/span&gt;&lt;/code&gt; class template&lt;/a&gt;, which I plan on writing more about in the future.)&lt;/li&gt;
&lt;/ul&gt;</content><author><name></name></author><category term="swiftc" /><summary type="html">The prior article in this series explained how the Swift and Clang compilers used llvm::SourceMgr to emit diagnostics for source locations in memory buffers, represented by the class llvm::MemoryBuffer. This article focuses on llvm::MemoryBuffer, the primary abstraction for reading files and streams into memory. Since it's used by Swift, Clang, and LLVM tools like llvm-tblgen, I found it valuable to understand how it works.</summary></entry><entry><title type="html">How the Swift Compiler Emits Diagnostics, Part 1: LLVM Abstractions</title><link href="https://modocache.io/swift-compiler-diagnostics-part-1" rel="alternate" type="text/html" title="How the Swift Compiler Emits Diagnostics, Part 1: LLVM Abstractions" /><published>2018-04-16T18:00:00+00:00</published><updated>2018-04-16T18:00:00+00:00</updated><id>https://modocache.io/swift-compiler-diagnostics-part-1</id><content type="html" xml:base="https://modocache.io/swift-compiler-diagnostics-part-1">&lt;p&gt;The &lt;a href=&quot;/the-swift-frontend-lexing-and-parsing&quot;&gt;prior article in this series&lt;/a&gt; explained how the Swift compiler lexes and parses source code, by looking at this syntactically valid Swift program:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;hello.swift&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;1&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// hello.swift&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;3&lt;/span&gt;  &lt;span class=&quot;fs&quot;&gt;print&lt;/span&gt;(&lt;span class=&quot;s&quot;&gt;&quot;Hello, world!&quot;&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;In this and the next few articles, I'd like to take a look at this ill-formed Swift program (note the extra opening parenthesis):&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;uhoh.swift&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;1&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// uhoh.swift&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;3&lt;/span&gt;  &lt;span class=&quot;fs&quot;&gt;print&lt;/span&gt;((&lt;span class=&quot;s&quot;&gt;&quot;Yikes.&quot;&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Compiling this program results in two &lt;em&gt;diagnostics&lt;/em&gt;: one &lt;em&gt;error&lt;/em&gt; diagnostic, and one &lt;em&gt;note&lt;/em&gt; diagnostic:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;cmd&quot;&gt;swiftc&lt;/span&gt; uhoh.swift
&lt;span class=&quot;diag&quot;&gt;uhoh.swift:3:17: &lt;span class=&quot;de&quot;&gt;error:&lt;/span&gt; expected ')' in expression list&lt;/span&gt;
print((&quot;Yikes.&quot;)
                &lt;span class=&quot;dc&quot;&gt;^&lt;/span&gt;
&lt;span class=&quot;diag&quot;&gt;uhoh.swift:3:6: &lt;span class=&quot;dn&quot;&gt;note:&lt;/span&gt; to match this opening '('&lt;/span&gt;
print((&quot;Yikes.&quot;)
     &lt;span class=&quot;dc&quot;&gt;^&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;As I explained in the &lt;a href=&quot;/the-swift-frontend-lexing-and-parsing&quot;&gt;previous article&lt;/a&gt;, the Swift parser instructs its lexer to lex tokens in the source program. It inspects each token, and determines what tokens need to be lexed next in order for the program to be valid. This is what I imagine the parser is &quot;thinking&quot; when it parses the program above:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&quot;I instruct the lexer to lex the first token in the source code. The lexer returns to me that token, which is &lt;code&gt;&lt;span class=&quot;f&quot;&gt;print&lt;/span&gt;&lt;/code&gt;. I know that this is an identifier. I need to keep parsing to determine whether this identifier is being used as a variable, as part of a function call, or in some other way. To find out, I'll instruct the lexer to lex another token.&quot;&lt;/li&gt;
  &lt;li&gt;&quot;The lexer has lexed the token &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(&lt;/code&gt;, an opening parenthesis. I am probably parsing a function call, and as such I expect to find a list of zero or more expressions – the function arguments – followed by a closing parenthesis &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;)&lt;/code&gt;. I'll instruct the lexer to lex another token.&quot;&lt;/li&gt;
  &lt;li&gt;&quot;The lexer has lexed the token &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(&lt;/code&gt;, another opening parenthesis. OK, so maybe there's a tuple argument being passed in as a function argument, such as &lt;code&gt;&lt;span class=&quot;f&quot;&gt;print&lt;/span&gt;((&lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;, &lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;))&lt;/code&gt; or something.&quot; (Keep in mind that the parser doesn't know anything about whether the &lt;code&gt;&lt;span class=&quot;f&quot;&gt;print&lt;/span&gt;&lt;/code&gt; function provided by the Swift standard library can take a tuple as an argument – that's something for the Swift type-checker, in libswiftSema, to determine.) &quot;So now I need to parse another list of zero or more expressions to fit inside this tuple or whatever, and then find two closing parentheses: one for the &lt;code&gt;&lt;span class=&quot;f&quot;&gt;print&lt;/span&gt;(&lt;/code&gt;, and one for the &lt;code&gt;&lt;span class=&quot;f&quot;&gt;print&lt;/span&gt;((&lt;/code&gt;. I'll instruct the lexer to lex another token.&quot;&lt;/li&gt;
  &lt;li&gt;&quot;The lexer has lexed the string literal token &lt;code&gt;&lt;span class=&quot;s&quot;&gt;&quot;Yikes.&quot;&lt;/span&gt;&lt;/code&gt;. OK, I guess this is the first expression inside the tuple. Let's keep going: I instruct the lexer to lex another token.&quot;&lt;/li&gt;
  &lt;li&gt;&quot;The lexer has lexed the token &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;)&lt;/code&gt;, a closing parenthesis. Aha, so it looks like I've parsed a tuple: &lt;code&gt;(&lt;span class=&quot;s&quot;&gt;&quot;Yikes.&quot;&lt;/span&gt;)&lt;/code&gt;. OK, so that's the first expression in a list of expressions being passed as arguments to &lt;code&gt;&lt;span class=&quot;f&quot;&gt;print&lt;/span&gt;(&lt;/code&gt;. I need to keep parsing expressions in that list of arguments, and then find a closing parenthesis &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;)&lt;/code&gt; to end the list. I instruct the lexer to lex another token.&quot;&lt;/li&gt;
  &lt;li&gt;&quot;The lexer has lexed the token… &lt;code&gt;&lt;span class=&quot;cn&quot;&gt;eof&lt;/span&gt;&lt;/code&gt;?? End of file? What the heck? Where's the closing parenthesis for &lt;code&gt;&lt;span class=&quot;f&quot;&gt;print&lt;/span&gt;(&lt;/code&gt;? OK, this source code is messed up. I should let the user know by emitting a diagnostic.&quot;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I explained the mechanics of steps 1 through 5 above in the &lt;a href=&quot;/the-swift-frontend-lexing-and-parsing&quot;&gt;previous article&lt;/a&gt;. In this article, I'll skim over those steps and focus instead on the diagnostic output itself:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;cmd&quot;&gt;swiftc&lt;/span&gt; uhoh.swift
&lt;span class=&quot;diag&quot;&gt;uhoh.swift:3:17: &lt;span class=&quot;de&quot;&gt;error:&lt;/span&gt; expected ')' in expression list&lt;/span&gt;
print((&quot;Yikes.&quot;)
                &lt;span class=&quot;dc&quot;&gt;^&lt;/span&gt;
&lt;span class=&quot;diag&quot;&gt;uhoh.swift:3:6: &lt;span class=&quot;dn&quot;&gt;note:&lt;/span&gt; to match this opening '('&lt;/span&gt;
print((&quot;Yikes.&quot;)
     &lt;span class=&quot;dc&quot;&gt;^&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;How does the parser know where to place the &lt;code&gt;&lt;span class=&quot;dc&quot;&gt;^&lt;/span&gt;&lt;/code&gt; carets in the output above? How is the text actually printed? Where is that logic defined?&lt;/p&gt;

&lt;p&gt;It turns out the answer to these questions span both the Swift and LLVM codebases.&lt;/p&gt;

&lt;h2 id=&quot;representing-source-text-and-locations-and-emitting-diagnostics-using-libllvmsupport&quot;&gt;Representing source text and locations, and emitting diagnostics, using libLLVMSupport&lt;/h2&gt;

&lt;p&gt;You may recall from my article on &lt;a href=&quot;/option-parsing-in-the-swift-compiler&quot;&gt;Option Parsing in the Swift Compiler&lt;/a&gt; that the &lt;a href=&quot;https://github.com/apple/swift/&quot;&gt;apple/swift&lt;/a&gt; codebase makes use of LLVM libraries. Specifically, that article described how the actual logic of parsing command-line strings was handled in libLLVMOption.&lt;/p&gt;

&lt;p&gt;Likewise, the actual logic involved in storing source program text in memory, representing locations in that source text, and printing diagnostic messages, is handled in the LLVM library libLLVMSupport.&lt;/p&gt;

&lt;p&gt;Here's a small sample program that demonstrates how libLLVMSupport can be used to emit a diagnostic:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;libLLVMSupport-Example.cpp&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt; 1&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;llvm/Support/MemoryBuffer.h&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 2&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;llvm/Support/SourceMgr.h&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 3&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt; 4&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; main() {
&lt;span class=&quot;ln&quot;&gt; 5&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// This string will represent our source program.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 6&lt;/span&gt;    &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt; Input =
&lt;span class=&quot;ln&quot;&gt; 7&lt;/span&gt;      &lt;span class=&quot;s&quot;&gt;&quot;func foo() {\n&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 8&lt;/span&gt;      &lt;span class=&quot;s&quot;&gt;&quot;  print(\&quot;Hello!\&quot;)\n&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 9&lt;/span&gt;      &lt;span class=&quot;s&quot;&gt;&quot;}&quot;&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;10&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;11&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// The llvm::MemoryBuffer class is used to store&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;12&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// large strings, along with metadata such as a&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;13&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// buffer or file name. Here we instantiate a&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;14&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// llvm::MemoryBuffer to store the contents of&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;15&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// our source program.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;16&lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&amp;gt; InputBuffer =
&lt;span class=&quot;ln&quot;&gt;17&lt;/span&gt;      &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getMemBuffer&lt;/span&gt;(Input);
&lt;span class=&quot;ln&quot;&gt;18&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;19&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// The llvm::SourceMgr class is used to emit&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;20&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// diagnostics for one or more llvm::MemoryBuffer&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;21&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// instances. Here we instantiate a new&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;22&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// llvm::SourceMgr and transfer ownership of our&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;23&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// input buffer over to it.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;24&lt;/span&gt;    &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt; SourceManager;
&lt;span class=&quot;ln&quot;&gt;25&lt;/span&gt;    SourceManager.&lt;span class=&quot;f&quot;&gt;AddNewSourceBuffer&lt;/span&gt;(
&lt;span class=&quot;ln&quot;&gt;26&lt;/span&gt;        &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;move&lt;/span&gt;(InputBuffer),
&lt;span class=&quot;ln&quot;&gt;27&lt;/span&gt;        &lt;span class=&quot;c&quot;&gt;/*IncludeLoc*/&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt;());
&lt;span class=&quot;ln&quot;&gt;28&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;29&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// Here we grab a pointer into the buffer.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;30&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// Incrementing and decrementing this pointer&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;31&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// allows us to traverse the source program.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;32&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt; *SourceBuffer =
&lt;span class=&quot;ln&quot;&gt;33&lt;/span&gt;      SourceManager.&lt;span class=&quot;f&quot;&gt;getMemoryBuffer&lt;/span&gt;(&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;34&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; *CurrentCharacter =
&lt;span class=&quot;ln&quot;&gt;35&lt;/span&gt;      SourceBuffer-&amp;gt;&lt;span class=&quot;f&quot;&gt;getBufferStart&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;36&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;37&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// The llvm::SMLoc class is used to represent a&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;38&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// location in an llvm::MemoryBuffer that is managed&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;39&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// by llvm::SourceMgr. We instantiate an llvm::SMLoc&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;40&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// here, for the starting location.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;41&lt;/span&gt;    &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt; BufferStartLocation =
&lt;span class=&quot;ln&quot;&gt;42&lt;/span&gt;      &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getFromPointer&lt;/span&gt;(CurrentCharacter);
&lt;span class=&quot;ln&quot;&gt;43&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;44&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// The llvm::SourceMgr::PrintMessage function allows&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;45&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// us to print a caret ^ at a specific llvm::SMLoc&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;46&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// location.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;47&lt;/span&gt;    SourceManager.&lt;span class=&quot;f&quot;&gt;PrintMessage&lt;/span&gt;(
&lt;span class=&quot;ln&quot;&gt;48&lt;/span&gt;        BufferStartLocation,
&lt;span class=&quot;ln&quot;&gt;49&lt;/span&gt;        &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;DiagKind&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;DK_Remark&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;50&lt;/span&gt;        &lt;span class=&quot;s&quot;&gt;&quot;This is the very beginning of the &quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;51&lt;/span&gt;        &lt;span class=&quot;s&quot;&gt;&quot;source buffer.&quot;&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;..&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;96&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;97&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Running the above program results in the following output:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;diag&quot;&gt;&lt;span class=&quot;dr&quot;&gt;remark:&lt;/span&gt; This is the very beginning of the source buffer.&lt;/span&gt;
func foo() {
&lt;span class=&quot;dc&quot;&gt;^&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;By incrementing the buffer pointer, I can print diagnostics at other locations as well. In the expanded example below, I use &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMRange&lt;/span&gt;&lt;/code&gt; to print a warning that points to the string &lt;code&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hello!&quot;&lt;/span&gt;&lt;/code&gt; in the source program:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;libLLVMSupport-Example.cpp&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt; 1&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;llvm/Support/MemoryBuffer.h&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 2&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;llvm/Support/SourceMgr.h&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 3&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt; 4&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; main() {
&lt;span class=&quot;ln&quot;&gt;..&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;53&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// Let's increment our buffer pointer until we find&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;54&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// the first quotation mark character: the first &quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;55&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// in the source text line 'print(&quot;Hello!&quot;)'. Then&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;56&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// let's record that in an llvm::SMLoc location.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;57&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; (*CurrentCharacter != &lt;span class=&quot;ch&quot;&gt;'&quot;'&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt;58&lt;/span&gt;      ++CurrentCharacter;
&lt;span class=&quot;ln&quot;&gt;59&lt;/span&gt;    &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt; StartLocation =
&lt;span class=&quot;ln&quot;&gt;60&lt;/span&gt;      &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getFromPointer&lt;/span&gt;(CurrentCharacter);
&lt;span class=&quot;ln&quot;&gt;61&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;62&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// Next, let's get the llvm::SMLoc location&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;63&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// representing the end of the string &quot;Hello!&quot;,&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;64&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// by finding the first character past the last&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;65&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// quotation mark.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;66&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; (*CurrentCharacter != &lt;span class=&quot;ch&quot;&gt;')'&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt;67&lt;/span&gt;      ++CurrentCharacter;
&lt;span class=&quot;ln&quot;&gt;68&lt;/span&gt;    &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt; EndLocation =
&lt;span class=&quot;ln&quot;&gt;69&lt;/span&gt;      &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getFromPointer&lt;/span&gt;(CurrentCharacter);
&lt;span class=&quot;ln&quot;&gt;70&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;71&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// The llvm::SMRange class represents a range: a&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;72&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// beginning and an end llvm::SMLoc location.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;73&lt;/span&gt;    &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMRange&lt;/span&gt; Range = &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMRange&lt;/span&gt;(StartLocation,
&lt;span class=&quot;ln&quot;&gt;74&lt;/span&gt;                                        EndLocation);
&lt;span class=&quot;ln&quot;&gt;75&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;76&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// We can print a warning that points to this&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;77&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// llvm::SMRange range.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;78&lt;/span&gt;    SourceManager.&lt;span class=&quot;f&quot;&gt;PrintMessage&lt;/span&gt;(
&lt;span class=&quot;ln&quot;&gt;79&lt;/span&gt;        StartLocation,
&lt;span class=&quot;ln&quot;&gt;80&lt;/span&gt;        &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;DiagKind&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;DK_Warning&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;81&lt;/span&gt;        &lt;span class=&quot;s&quot;&gt;&quot;This is the range of source text in which &quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;82&lt;/span&gt;        &lt;span class=&quot;s&quot;&gt;&quot;a string literal appears.&quot;&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;83&lt;/span&gt;        Range);
&lt;span class=&quot;ln&quot;&gt;..&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;96&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;97&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Now running the program results in two diagnostics being emitted:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;diag&quot;&gt;&lt;span class=&quot;dr&quot;&gt;remark:&lt;/span&gt; This is the very beginning of the source buffer.&lt;/span&gt;
func foo() {
&lt;span class=&quot;dc&quot;&gt;^&lt;/span&gt;
&lt;span class=&quot;diag&quot;&gt;&lt;span class=&quot;dw&quot;&gt;warning:&lt;/span&gt; This is the range of source text in which a string literal appears.&lt;/span&gt;
  print(&quot;Hello!&quot;)
        &lt;span class=&quot;dc&quot;&gt;^~~~~~~~&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;And I can use &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMFixIt&lt;/span&gt;&lt;/code&gt; in order to display a suggestion for a string to replace &lt;code&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hello!&quot;&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;libLLVMSupport-Example.cpp&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt; 1&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;llvm/Support/MemoryBuffer.h&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 2&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;llvm/Support/SourceMgr.h&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 3&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt; 4&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; main() {
&lt;span class=&quot;ln&quot;&gt;..&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;78&lt;/span&gt;    SourceManager.&lt;span class=&quot;f&quot;&gt;PrintMessage&lt;/span&gt;(
&lt;span class=&quot;ln&quot;&gt;79&lt;/span&gt;        StartLocation,
&lt;span class=&quot;ln&quot;&gt;80&lt;/span&gt;        &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;DiagKind&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;DK_Warning&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;81&lt;/span&gt;        &lt;span class=&quot;s&quot;&gt;&quot;This is the range of source text in which &quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;82&lt;/span&gt;        &lt;span class=&quot;s&quot;&gt;&quot;a string literal appears.&quot;&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;83&lt;/span&gt;        Range);
&lt;span class=&quot;ln&quot;&gt;84&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;85&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// The llvm::SMFixIt class allows us to print&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;86&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// a replacement suggestion underneath the&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;87&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// caret ^ output.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;88&lt;/span&gt;    SourceManager.&lt;span class=&quot;f&quot;&gt;PrintMessage&lt;/span&gt;(
&lt;span class=&quot;ln&quot;&gt;89&lt;/span&gt;        StartLocation,
&lt;span class=&quot;ln&quot;&gt;90&lt;/span&gt;        &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;DiagKind&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;DK_Note&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;91&lt;/span&gt;        &lt;span class=&quot;s&quot;&gt;&quot;This is a fix-it that suggests an &quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;92&lt;/span&gt;        &lt;span class=&quot;s&quot;&gt;&quot;alternative string.&quot;&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;93&lt;/span&gt;        &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;None&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;94&lt;/span&gt;        &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMFixIt&lt;/span&gt;(Range, &lt;span class=&quot;s&quot;&gt;&quot;\&quot;Good-bye!\&quot;&quot;&lt;/span&gt;));
&lt;span class=&quot;ln&quot;&gt;95&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;96&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;97&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The text associated with the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMFixIt&lt;/span&gt;&lt;/code&gt; is displayed below the underline:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;diag&quot;&gt;&lt;span class=&quot;dr&quot;&gt;remark:&lt;/span&gt; This is the very beginning of the source buffer.&lt;/span&gt;
func foo() {
&lt;span class=&quot;dc&quot;&gt;^&lt;/span&gt;
&lt;span class=&quot;diag&quot;&gt;&lt;span class=&quot;dw&quot;&gt;warning:&lt;/span&gt; This is the range of source text in which a string literal appears.&lt;/span&gt;
  print(&quot;Hello!&quot;)
        &lt;span class=&quot;dc&quot;&gt;^~~~~~~~&lt;/span&gt;
&lt;span class=&quot;diag&quot;&gt;&lt;span class=&quot;dn&quot;&gt;note:&lt;/span&gt; This is a fix-it that suggests an alternative string.&lt;/span&gt;
  print(&quot;Hello!&quot;)
        &lt;span class=&quot;dc&quot;&gt;^~~~~~~~&lt;/span&gt;
        &quot;Good-bye!&quot;
&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;&lt;/code&gt; also has some rudimentary support for emitting diagnostics for files included by other files. For example, I can mark our source buffer as having been included by another buffer, like so:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;libLLVMSupport-Example.cpp&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;  1&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;llvm/Support/MemoryBuffer.h&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;  2&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;llvm/Support/SourceMgr.h&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;  3&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;  4&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; main() {
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt;  +&lt;/span&gt;   &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt; IncludeInput = &lt;span class=&quot;s&quot;&gt;&quot;import foo&quot;&lt;/span&gt;;&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt;  +&lt;/span&gt;   &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt; SourceManager;&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt;  +&lt;/span&gt;    SourceManager.&lt;span class=&quot;f&quot;&gt;AddNewSourceBuffer&lt;/span&gt;(&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt;  +&lt;/span&gt;        &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;move&lt;/span&gt;(&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt;  +&lt;/span&gt;          &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getMemBuffer&lt;/span&gt;(IncludeInput)),&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt; ++&lt;/span&gt;        &lt;span class=&quot;c&quot;&gt;/*IncludeLoc*/&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt;());&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt; ++&lt;/span&gt;    &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt; IncludeLocation =&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt; ++&lt;/span&gt;      &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getFromPointer&lt;/span&gt;(&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt; ++&lt;/span&gt;          SourceManager.&lt;span class=&quot;f&quot;&gt;getMemoryBuffer&lt;/span&gt;(&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;)-&amp;gt;&lt;span class=&quot;f&quot;&gt;getBufferStart&lt;/span&gt;());&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt; 14&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt; 15&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// This string will represent our source program.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 16&lt;/span&gt;    &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt; Input =
&lt;span class=&quot;ln&quot;&gt; 17&lt;/span&gt;      &lt;span class=&quot;s&quot;&gt;&quot;func foo() {\n&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 18&lt;/span&gt;      &lt;span class=&quot;s&quot;&gt;&quot;  print(\&quot;Hello!\&quot;)\n&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 19&lt;/span&gt;      &lt;span class=&quot;s&quot;&gt;&quot;}&quot;&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt; 20&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt; 21&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// The llvm::MemoryBuffer class is used to store&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 22&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// large strings, along with metadata such as a&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 23&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// buffer or file name. Here we instantiate a&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 24&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// llvm::MemoryBuffer to store the contents of&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 25&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// our source program.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 26&lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&amp;gt; InputBuffer =
&lt;span class=&quot;ln&quot;&gt; 27&lt;/span&gt;      &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getMemBuffer&lt;/span&gt;(Input);
&lt;span class=&quot;ln&quot;&gt; 28&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt; 29&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// The llvm::SourceMgr class is used to emit&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 30&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// diagnostics for one or more llvm::MemoryBuffer&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 31&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// instances. Here we instantiate a new&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 32&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// llvm::SourceMgr and transfer ownership of our&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 33&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// input buffer over to it.&lt;/span&gt;
&lt;div class=&quot;rm&quot;&gt;&lt;span class=&quot;ln&quot;&gt; --&lt;/span&gt;   &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt; SourceManager;&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt; 34&lt;/span&gt;    SourceManager.&lt;span class=&quot;f&quot;&gt;AddNewSourceBuffer&lt;/span&gt;(
&lt;span class=&quot;ln&quot;&gt; 35&lt;/span&gt;        &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;move&lt;/span&gt;(InputBuffer),
&lt;div class=&quot;rm&quot;&gt;&lt;span class=&quot;ln&quot;&gt; --&lt;/span&gt;       &lt;span class=&quot;c&quot;&gt;/*IncludeLoc*/&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt;());&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt; ++&lt;/span&gt;       &lt;span class=&quot;c&quot;&gt;/*IncludeLoc*/&lt;/span&gt; IncludeLocation);&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt; 37&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt; 38&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// Here we grab a pointer into the buffer.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 39&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// Incrementing and decrementing this pointer&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 40&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// allows us to traverse the source program.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 41&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt; *SourceBuffer =
&lt;div class=&quot;rm&quot;&gt;&lt;span class=&quot;ln&quot;&gt; --&lt;/span&gt;     SourceManager.&lt;span class=&quot;f&quot;&gt;getMemoryBuffer&lt;/span&gt;(&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;);&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt; ++&lt;/span&gt;     SourceManager.&lt;span class=&quot;f&quot;&gt;getMemoryBuffer&lt;/span&gt;(&lt;span class=&quot;num&quot;&gt;2&lt;/span&gt;);&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt; 43&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; *CurrentCharacter =
&lt;span class=&quot;ln&quot;&gt; 44&lt;/span&gt;      SourceBuffer-&amp;gt;&lt;span class=&quot;f&quot;&gt;getBufferStart&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;106&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Now the diagnostics emitted for each &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt;&lt;/code&gt; location also include a line indicating where those locations were &quot;included&quot; from:&lt;/p&gt;

&lt;pre&gt;
Included from :1:
&lt;span class=&quot;diag&quot;&gt;&lt;span class=&quot;dr&quot;&gt;remark:&lt;/span&gt; This is the very beginning of the source buffer.&lt;/span&gt;
func foo() {
&lt;span class=&quot;dc&quot;&gt;^&lt;/span&gt;
Included from :1:
&lt;span class=&quot;diag&quot;&gt;&lt;span class=&quot;dw&quot;&gt;warning:&lt;/span&gt; This is the range of source text in which a string literal appears.&lt;/span&gt;
  print(&quot;Hello!&quot;)
        &lt;span class=&quot;dc&quot;&gt;^~~~~~~~&lt;/span&gt;
Included from :1:
&lt;span class=&quot;diag&quot;&gt;&lt;span class=&quot;dn&quot;&gt;note:&lt;/span&gt; This is a fix-it that suggests an alternative string.&lt;/span&gt;
  print(&quot;Hello!&quot;)
        &lt;span class=&quot;dc&quot;&gt;^~~~~~~~&lt;/span&gt;
        &quot;Good-bye!&quot;
&lt;/pre&gt;

&lt;p&gt;Since our source buffers are not named, &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;&lt;/code&gt; just outputs the line on which the &quot;include&quot; occurs – in our case, the first line in the buffer, &lt;code&gt;&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;&lt;/code&gt; – and so the output is &quot;Included from :1:&quot;.&lt;/p&gt;

&lt;p&gt;Assigning identifers to the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt; improves the output:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;libLLVMSupport-Example.cpp&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;  4&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; main() {
&lt;span class=&quot;ln&quot;&gt;  5&lt;/span&gt;    &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt; IncludeInput = &quot;import foo&quot;;
&lt;span class=&quot;ln&quot;&gt;  6&lt;/span&gt;    &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt; SourceManager;
&lt;span class=&quot;ln&quot;&gt;  7&lt;/span&gt;    SourceManager.&lt;span class=&quot;f&quot;&gt;AddNewSourceBuffer&lt;/span&gt;(
&lt;span class=&quot;ln&quot;&gt;  8&lt;/span&gt;       &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;move&lt;/span&gt;(
&lt;div class=&quot;rm&quot;&gt;&lt;span class=&quot;ln&quot;&gt;  -&lt;/span&gt;         &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getMemBuffer&lt;/span&gt;(IncludeInput)),&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt;  +&lt;/span&gt;         &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getMemBuffer&lt;/span&gt;(IncludeInput,,&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt; ++&lt;/span&gt;                                          &quot;include.swift&quot;)),&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt; 11&lt;/span&gt;        &lt;span class=&quot;c&quot;&gt;/*IncludeLoc*/&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt;());
&lt;span class=&quot;ln&quot;&gt; ..&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 27&lt;/span&gt;     &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&amp;gt; InputBuffer =
&lt;div class=&quot;rm&quot;&gt;&lt;span class=&quot;ln&quot;&gt; --&lt;/span&gt;      &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getMemBuffer&lt;/span&gt;(Input);&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt; ++&lt;/span&gt;      &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getMemBuffer&lt;/span&gt;(Input, &quot;foo.swift&quot;);&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;107&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Now the output includes the file names:&lt;/p&gt;

&lt;pre&gt;
Included from include.swift:1:
&lt;span class=&quot;diag&quot;&gt;foo.swift:1:1: &lt;span class=&quot;dr&quot;&gt;remark:&lt;/span&gt; This is the very beginning of the source buffer.&lt;/span&gt;
func foo() {
&lt;span class=&quot;dc&quot;&gt;^&lt;/span&gt;
Included from include.swift:1:
&lt;span class=&quot;diag&quot;&gt;foo.swift:2:9: &lt;span class=&quot;dw&quot;&gt;warning:&lt;/span&gt; This is the range of source text in which a string literal appears.&lt;/span&gt;
  print(&quot;Hello!&quot;)
        &lt;span class=&quot;dc&quot;&gt;^~~~~~~~&lt;/span&gt;
Included from include.swift:1:
&lt;span class=&quot;diag&quot;&gt;foo.swift:2:9: &lt;span class=&quot;dn&quot;&gt;note:&lt;/span&gt; This is a fix-it that suggests an alternative string.&lt;/span&gt;
  print(&quot;Hello!&quot;)
        &lt;span class=&quot;dc&quot;&gt;^~~~~~~~&lt;/span&gt;
        &quot;Good-bye!&quot;
&lt;/pre&gt;

&lt;p&gt;The diagnostics are pretty much identical to Swift's (and Clang's, the C/C++/Objective-C compiler), because the &lt;a href=&quot;https://github.com/apple/swift/&quot;&gt;apple/swift&lt;/a&gt; codebase uses the same &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt; I used above in order to store source text in memory, and it uses the same &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt;&lt;/code&gt; to emit its diagnostics.&lt;/p&gt;

&lt;h3 id=&quot;how-exactly-do-llvmsourcemgr-and-llvmsmloc-work&quot;&gt;How exactly do &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt;&lt;/code&gt; work?&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;&lt;/code&gt; owns a vector of memory buffers – the ones added via calls to &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;AddNewSourceBuffer&lt;/span&gt;&lt;/code&gt;. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SourceMgr.h&lt;/code&gt; header file also includes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A declaration of the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;DiagKind&lt;/span&gt;&lt;/code&gt; enum I used above to indicate the diagnostic severity.&lt;/li&gt;
  &lt;li&gt;The definition of a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;SrcBuffer&lt;/span&gt;&lt;/code&gt; struct used to wrap both the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt; and its &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt;&lt;/code&gt; include location.&lt;/li&gt;
  &lt;li&gt;The implementation of the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;AddNewSourceBuffer&lt;/span&gt;&lt;/code&gt; member function. Note how simple it is: it just creates a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;SrcBuffer&lt;/span&gt;&lt;/code&gt; to wrap the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt; and its include location, and pushes that &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;SrcBuffer&lt;/span&gt;&lt;/code&gt; onto its vector of &lt;span class=&quot;vi&quot;&gt;buffers&lt;/span&gt;.&lt;/li&gt;
  &lt;li&gt;Implementations of some incredibly simple functions: &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;isValidBufferID&lt;/span&gt;&lt;/code&gt;, for example, simply checks whether the given buffer index is out of bounds of the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;vi&quot;&gt;Buffers&lt;/span&gt;&lt;/code&gt; vector. &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getMainFileID&lt;/span&gt;&lt;/code&gt;, in particular, makes me chuckle: it just returns &lt;code&gt;&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;&lt;/code&gt;! (When I first read the &lt;a href=&quot;https://github.com/apple/swift/&quot;&gt;apple/swift&lt;/a&gt; source code and saw references to a &quot;main buffer ID&quot;, I thought it was something more significant than just the first source buffer added to the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;&lt;/code&gt;.)&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;&lt;/code&gt; also stores a vector of &quot;include directories,&quot; but I'm not quite sure why yet. As far as I can tell, it's only used by one or two internal LLVM tools, like TableGen (remember &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;llvm-tblgen&lt;/span&gt;&lt;/code&gt;? I wrote about it in &lt;a href=&quot;/option-parsing-in-the-swift-compiler&quot;&gt;this article&lt;/a&gt;).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/llvm-mirror/llvm/blob/b5e9b6fb66a4245306cd51cae0abbd11b1f044df/include/llvm/Support/SourceMgr.h&quot;&gt;llvm/include/llvm/Support/SourceMgr.h&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt; 40&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// This owns the files read by a parser, handles include stacks,&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 41&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// and handles diagnostic wrangling.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 42&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; SourceMgr {
&lt;span class=&quot;ln&quot;&gt; 43&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;public:&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 44&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; DiagKind {
&lt;span class=&quot;ln&quot;&gt; 45&lt;/span&gt;      DK_Error,
&lt;span class=&quot;ln&quot;&gt; 46&lt;/span&gt;      DK_Warning,
&lt;span class=&quot;ln&quot;&gt; 47&lt;/span&gt;      DK_Remark,
&lt;span class=&quot;ln&quot;&gt; 48&lt;/span&gt;      DK_Note,
&lt;span class=&quot;ln&quot;&gt; 49&lt;/span&gt;    };
&lt;span class=&quot;ln&quot;&gt; ..&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt; 56&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;private:&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 57&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; SrcBuffer {
&lt;span class=&quot;ln&quot;&gt; 58&lt;/span&gt;      &lt;span class=&quot;d&quot;&gt;/// The memory buffer for the file.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 59&lt;/span&gt;      &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&amp;gt; Buffer;
&lt;span class=&quot;ln&quot;&gt; ..&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 85&lt;/span&gt;      &lt;span class=&quot;d&quot;&gt;/// This is the location of the parent include, or null if at the top level.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 86&lt;/span&gt;      &lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt; IncludeLoc;
&lt;span class=&quot;ln&quot;&gt; 87&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt; 88&lt;/span&gt;      SrcBuffer() = &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt; ..&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 93&lt;/span&gt;    };
&lt;span class=&quot;ln&quot;&gt; 94&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt; 95&lt;/span&gt;    &lt;span class=&quot;d&quot;&gt;/// This is all of the buffers that we are reading from.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 96&lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;vector&lt;/span&gt;&amp;lt;&lt;span class=&quot;cls&quot;&gt;SrcBuffer&lt;/span&gt;&amp;gt; Buffers;
&lt;span class=&quot;ln&quot;&gt; 97&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt; 98&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// This is the list of directories we should search for include files in.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 99&lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;vector&lt;/span&gt;&amp;lt;&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;string&lt;/span&gt;&amp;gt; IncludeDirectories;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;104&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; isValidBufferID(&lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt; i) &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; { &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; i &amp;amp;&amp;amp; i &amp;lt;= &lt;span class=&quot;vi&quot;&gt;Buffers&lt;/span&gt;.&lt;span class=&quot;f&quot;&gt;size&lt;/span&gt;(); }
&lt;span class=&quot;ln&quot;&gt;105&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;106&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;public:&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;107&lt;/span&gt;    SourceMgr() = &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;131&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt; *getMemoryBuffer(&lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt; i) &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; {
&lt;span class=&quot;ln&quot;&gt;132&lt;/span&gt;      &lt;span class=&quot;ms&quot;&gt;assert&lt;/span&gt;(&lt;span class=&quot;f&quot;&gt;isValidBufferID&lt;/span&gt;(i));
&lt;span class=&quot;ln&quot;&gt;133&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;Buffers&lt;/span&gt;[i - &lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;].&lt;span class=&quot;vi&quot;&gt;Buffer&lt;/span&gt;.&lt;span class=&quot;f&quot;&gt;get&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;134&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;135&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;136&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt; getNumBuffers() &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; {
&lt;span class=&quot;ln&quot;&gt;137&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;Buffers&lt;/span&gt;.&lt;span class=&quot;f&quot;&gt;size&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;138&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;139&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;140&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt; getMainFileID() &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; {
&lt;span class=&quot;ln&quot;&gt;141&lt;/span&gt;      &lt;span class=&quot;ms&quot;&gt;assert&lt;/span&gt;(&lt;span class=&quot;f&quot;&gt;getNumBuffers&lt;/span&gt;());
&lt;span class=&quot;ln&quot;&gt;142&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; 1;
&lt;span class=&quot;ln&quot;&gt;143&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;150&lt;/span&gt;    &lt;span class=&quot;d&quot;&gt;/// Add a new source buffer to this source manager. This takes ownership of&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;151&lt;/span&gt;    &lt;span class=&quot;d&quot;&gt;/// the memory buffer.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;152&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt; AddNewSourceBuffer(&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&amp;gt; F,
&lt;span class=&quot;ln&quot;&gt;153&lt;/span&gt;                                &lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt; IncludeLoc) {
&lt;span class=&quot;ln&quot;&gt;154&lt;/span&gt;      &lt;span class=&quot;cl&quot;&gt;SrcBuffer&lt;/span&gt; NB;
&lt;span class=&quot;ln&quot;&gt;155&lt;/span&gt;      NB.&lt;span class=&quot;vi&quot;&gt;Buffer&lt;/span&gt; = &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;move&lt;/span&gt;(F);
&lt;span class=&quot;ln&quot;&gt;156&lt;/span&gt;      NB.&lt;span class=&quot;vi&quot;&gt;IncludeLoc&lt;/span&gt; = IncludeLoc;
&lt;span class=&quot;ln&quot;&gt;157&lt;/span&gt;      &lt;span class=&quot;vi&quot;&gt;Buffers&lt;/span&gt;.&lt;span class=&quot;f&quot;&gt;push_back&lt;/span&gt;(&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;move&lt;/span&gt;(NB));
&lt;span class=&quot;ln&quot;&gt;158&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;Buffers&lt;/span&gt;.&lt;span class=&quot;f&quot;&gt;size&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;159&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;225&lt;/span&gt;  };
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;&lt;/code&gt; header file also declares the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;PrintMessage&lt;/span&gt;&lt;/code&gt; member function, which I used above to print diagnostics. This is a convenience function that creates an &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMDiagnostic&lt;/span&gt;&lt;/code&gt; instance, and then calls the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMDiagnostic&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;print&lt;/span&gt;&lt;/code&gt; function.&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/llvm-mirror/llvm/blob/b5e9b6fb66a4245306cd51cae0abbd11b1f044df/include/llvm/Support/SourceMgr.h&quot;&gt;llvm/include/llvm/Support/SourceMgr.h&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt; 42&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; SourceMgr {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;186&lt;/span&gt;    &lt;span class=&quot;d&quot;&gt;/// Emit a message about the specified location with the specified string.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;187&lt;/span&gt;    &lt;span class=&quot;d&quot;&gt;///&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;188&lt;/span&gt;    &lt;span class=&quot;d&quot;&gt;/// &lt;span class=&quot;dk&quot;&gt;\param&lt;/span&gt; ShowColors Display colored messages if output is a terminal and&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;189&lt;/span&gt;    &lt;span class=&quot;d&quot;&gt;/// the default error handler is used.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;190&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; PrintMessage(&lt;span class=&quot;cl&quot;&gt;raw_ostream&lt;/span&gt; &amp;amp;OS, &lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt; Loc, &lt;span class=&quot;t&quot;&gt;DiagKind&lt;/span&gt; Kind,
&lt;span class=&quot;ln&quot;&gt;191&lt;/span&gt;                      &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Twine&lt;/span&gt; &amp;amp;Msg,
&lt;span class=&quot;ln&quot;&gt;192&lt;/span&gt;                      &lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;SMRange&lt;/span&gt;&amp;gt; Ranges = &lt;span class=&quot;cn&quot;&gt;None&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;193&lt;/span&gt;                      &lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;SMFixIt&lt;/span&gt;&amp;gt; FixIts = &lt;span class=&quot;cn&quot;&gt;None&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;194&lt;/span&gt;                      &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; ShowColors = &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;) &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;195&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;196&lt;/span&gt;    &lt;span class=&quot;d&quot;&gt;/// Emits a diagnostic to llvm::errs().&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;197&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; PrintMessage(&lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt; Loc, &lt;span class=&quot;t&quot;&gt;DiagKind&lt;/span&gt; Kind, &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Twine&lt;/span&gt; &amp;amp;Msg,
&lt;span class=&quot;ln&quot;&gt;198&lt;/span&gt;                      &lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;SMRange&lt;/span&gt;&amp;gt; Ranges = &lt;span class=&quot;cn&quot;&gt;None&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;199&lt;/span&gt;                      &lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;SMFixIt&lt;/span&gt;&amp;gt; FixIts = &lt;span class=&quot;cn&quot;&gt;None&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;200&lt;/span&gt;                      &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; ShowColors = &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;) &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;201&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;202&lt;/span&gt;    &lt;span class=&quot;d&quot;&gt;/// Emits a manually-constructed diagnostic to the given output stream.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;203&lt;/span&gt;    &lt;span class=&quot;d&quot;&gt;///&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;204&lt;/span&gt;    &lt;span class=&quot;d&quot;&gt;/// &lt;span class=&quot;dk&quot;&gt;\param&lt;/span&gt; ShowColors Display colored messages if output is a terminal and&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;205&lt;/span&gt;    &lt;span class=&quot;d&quot;&gt;/// the default error handler is used.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;206&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; PrintMessage(&lt;span class=&quot;cl&quot;&gt;raw_ostream&lt;/span&gt; &amp;amp;OS, &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;SMDiagnostic&lt;/span&gt; &amp;amp;Diagnostic,
&lt;span class=&quot;ln&quot;&gt;207&lt;/span&gt;                      &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; ShowColors = &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;) &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;225&lt;/span&gt;  };
&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/llvm-mirror/llvm/blob/b5e9b6fb66a4245306cd51cae0abbd11b1f044df/lib/Support/SourceMgr.cpp&quot;&gt;llvm/lib/Support/SourceMgr.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;231&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::PrintMessage(&lt;span class=&quot;cl&quot;&gt;raw_ostream&lt;/span&gt; &amp;amp;OS, &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;SMDiagnostic&lt;/span&gt; &amp;amp;Diagnostic,
&lt;span class=&quot;ln&quot;&gt;232&lt;/span&gt;                               &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; ShowColors) &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;239&lt;/span&gt;    if (Diagnostic.&lt;span class=&quot;f&quot;&gt;getLoc&lt;/span&gt;().&lt;span class=&quot;f&quot;&gt;isValid&lt;/span&gt;()) {
&lt;span class=&quot;ln&quot;&gt;240&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt; CurBuf = &lt;span class=&quot;f&quot;&gt;FindBufferContainingLoc&lt;/span&gt;(Diagnostic.&lt;span class=&quot;f&quot;&gt;getLoc&lt;/span&gt;());
&lt;span class=&quot;ln&quot;&gt;241&lt;/span&gt;      &lt;span class=&quot;ms&quot;&gt;assert&lt;/span&gt;(&lt;span class=&quot;f&quot;&gt;CurBuf&lt;/span&gt; &amp;amp;&amp;amp; &lt;span class=&quot;s&quot;&gt;&quot;Invalid or unspecified location!&quot;&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;242&lt;/span&gt;      &lt;span class=&quot;f&quot;&gt;PrintIncludeStack&lt;/span&gt;(&lt;span class=&quot;f&quot;&gt;getBufferInfo&lt;/span&gt;(CurBuf).&lt;span class=&quot;vi&quot;&gt;IncludeLoc&lt;/span&gt;, OS);
&lt;span class=&quot;ln&quot;&gt;243&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;244&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;245&lt;/span&gt;    Diagnostic.&lt;span class=&quot;f&quot;&gt;print&lt;/span&gt;(&lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;, OS, ShowColors);
&lt;span class=&quot;ln&quot;&gt;246&lt;/span&gt;  }
&lt;span class=&quot;ln&quot;&gt;247&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;248&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::PrintMessage(&lt;span class=&quot;cl&quot;&gt;raw_ostream&lt;/span&gt; &amp;amp;OS, &lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt; Loc,
&lt;span class=&quot;ln&quot;&gt;249&lt;/span&gt;                               &lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;DiagKind&lt;/span&gt; Kind,
&lt;span class=&quot;ln&quot;&gt;250&lt;/span&gt;                               &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Twine&lt;/span&gt; &amp;amp;Msg, &lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;SMRange&lt;/span&gt;&amp;gt; Ranges,
&lt;span class=&quot;ln&quot;&gt;251&lt;/span&gt;                               &lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;SMFixIt&lt;/span&gt;&amp;gt; FixIts, &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; ShowColors) &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; {
&lt;span class=&quot;ln&quot;&gt;252&lt;/span&gt;    &lt;span class=&quot;f&quot;&gt;PrintMessage&lt;/span&gt;(OS, &lt;span class=&quot;f&quot;&gt;GetMessage&lt;/span&gt;(Loc, Kind, Msg, Ranges, FixIts), ShowColors);
&lt;span class=&quot;ln&quot;&gt;253&lt;/span&gt;  }
&lt;span class=&quot;ln&quot;&gt;254&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;255&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::PrintMessage(SMLoc Loc, &lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;DiagKind&lt;/span&gt; Kind,
&lt;span class=&quot;ln&quot;&gt;256&lt;/span&gt;                               &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Twine&lt;/span&gt; &amp;amp;Msg, &lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;SMRange&lt;/span&gt;&amp;gt; Ranges,
&lt;span class=&quot;ln&quot;&gt;257&lt;/span&gt;                               &lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;SMFixIt&lt;/span&gt;&amp;gt; FixIts, &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; ShowColors) &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; {
&lt;span class=&quot;ln&quot;&gt;258&lt;/span&gt;    &lt;span class=&quot;f&quot;&gt;PrintMessage&lt;/span&gt;(&lt;span class=&quot;f&quot;&gt;errs&lt;/span&gt;(), Loc, Kind, Msg, Ranges, FixIts, ShowColors);
&lt;span class=&quot;ln&quot;&gt;259&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMDiagnostic&lt;/span&gt;&lt;/code&gt; class is also declared in the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;&lt;/code&gt; header file. It simply stores the data necessary when printing a diagnostic, and it declares the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMDiagnostic&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;print&lt;/span&gt;&lt;/code&gt; member function. This header also declares &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMFixIt&lt;/span&gt;&lt;/code&gt;, which is also a simple bag of data:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/llvm-mirror/llvm/blob/b5e9b6fb66a4245306cd51cae0abbd11b1f044df/include/llvm/Support/SourceMgr.h&quot;&gt;llvm/include/llvm/Support/SourceMgr.h&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;227&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// Represents a single fixit, a replacement of one range of text with another.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;228&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; SMFixIt {
&lt;span class=&quot;ln&quot;&gt;229&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;SMRange&lt;/span&gt; Range;
&lt;span class=&quot;ln&quot;&gt;230&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;231&lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;string&lt;/span&gt; Text;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;256&lt;/span&gt;  };
&lt;span class=&quot;ln&quot;&gt;257&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;258&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// Instances of this class encapsulate one diagnostic report, allowing&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;259&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// printing to a &lt;span class=&quot;cl&quot;&gt;raw_ostream&lt;/span&gt; as a caret diagnostic.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;260&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;SMDiagnostic&lt;/span&gt; {
&lt;span class=&quot;ln&quot;&gt;261&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt; *SM = &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;262&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt; Loc;
&lt;span class=&quot;ln&quot;&gt;263&lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;string&lt;/span&gt; Filename;
&lt;span class=&quot;ln&quot;&gt;264&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; LineNo = &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;265&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; ColumnNo = &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;266&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;DiagKind&lt;/span&gt; Kind = &lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;DK_Error&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;267&lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;string&lt;/span&gt; Message, LineContents;
&lt;span class=&quot;ln&quot;&gt;268&lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;vector&lt;/span&gt;&amp;lt;&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;pair&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt;, &lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt;&amp;gt;&amp;gt; Ranges;
&lt;span class=&quot;ln&quot;&gt;269&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;SmallVector&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;SMFixIt&lt;/span&gt;, &lt;span class=&quot;num&quot;&gt;4&lt;/span&gt;&amp;gt; FixIts;
&lt;span class=&quot;ln&quot;&gt;270&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;271&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;public:&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;278&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// Diagnostic with a location.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;279&lt;/span&gt;    SMDiagnostic(&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt; &amp;amp;sm, &lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt; L, &lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt; FN,
&lt;span class=&quot;ln&quot;&gt;280&lt;/span&gt;                 &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; Line, &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; Col, &lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;DiagKind&lt;/span&gt; Kind,
&lt;span class=&quot;ln&quot;&gt;281&lt;/span&gt;                 &lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt; Msg, &lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt; LineStr,
&lt;span class=&quot;ln&quot;&gt;282&lt;/span&gt;                 &lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;pair&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt;,&lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt;&amp;gt;&amp;gt; Ranges,
&lt;span class=&quot;ln&quot;&gt;283&lt;/span&gt;                 &lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;SMFixIt&lt;/span&gt;&amp;gt; FixIts =&lt;span class=&quot;cn&quot;&gt; None&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;303&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; print(&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; *ProgName, &lt;span class=&quot;cl&quot;&gt;raw_ostream&lt;/span&gt; &amp;amp;S, &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; S&lt;span class=&quot;f&quot;&gt;howColors&lt;/span&gt; = &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;304&lt;/span&gt;               &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; ShowKindLabel = &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;) &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;305&lt;/span&gt;  };
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Note that &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMDiagnostic&lt;/span&gt;&lt;/code&gt; is initialized with not just the &lt;code&gt;&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;string&lt;/span&gt;&lt;/code&gt; message that will be printed, but also the &lt;code&gt;&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;string&lt;/span&gt;&lt;/code&gt; source line to print as well. The &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;GetMessage&lt;/span&gt;&lt;/code&gt; member function, which is called when &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;PrintMessage&lt;/span&gt;&lt;/code&gt; is used to emit a diagnostic, grabs the source line, called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LineStr&lt;/code&gt; below, by searching for newline characters in the source buffer.&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/llvm-mirror/llvm/blob/b5e9b6fb66a4245306cd51cae0abbd11b1f044df/lib/Support/SourceMgr.cpp&quot;&gt;llvm/lib/Support/SourceMgr.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;169&lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;SMDiagnostic&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::GetMessage(&lt;span class=&quot;cl&quot;&gt;SMLoc&lt;/span&gt; Loc, &lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;DiagKind&lt;/span&gt; Kind,
&lt;span class=&quot;ln&quot;&gt;170&lt;/span&gt;                                     &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Twine&lt;/span&gt; &amp;amp;Msg,
&lt;span class=&quot;ln&quot;&gt;171&lt;/span&gt;                                     &lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;SMRange&lt;/span&gt;&amp;gt; Ranges,
&lt;span class=&quot;ln&quot;&gt;172&lt;/span&gt;                                     &lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;SMFixIt&lt;/span&gt;&amp;gt; FixIts) &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;187&lt;/span&gt;      &lt;span class=&quot;c&quot;&gt;// Scan backward to find the start of the line.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;188&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;const char&lt;/span&gt; *LineStart = Loc.&lt;span class=&quot;f&quot;&gt;getPointer&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;189&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;const char&lt;/span&gt; *BufStart = CurMB-&amp;gt;&lt;span class=&quot;f&quot;&gt;getBufferStart&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;190&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; (LineStart != BufStart &amp;amp;&amp;amp; LineStart[-&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;] != &lt;span class=&quot;ch&quot;&gt;'\n'&lt;/span&gt; &amp;amp;&amp;amp;
&lt;span class=&quot;ln&quot;&gt;191&lt;/span&gt;             LineStart[-&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;] != &lt;span class=&quot;ch&quot;&gt;'\r'&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt;192&lt;/span&gt;        --LineStart;
&lt;span class=&quot;ln&quot;&gt;193&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;194&lt;/span&gt;      &lt;span class=&quot;c&quot;&gt;// Get the end of the line.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;195&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;const char&lt;/span&gt; *LineEnd = Loc.&lt;span class=&quot;f&quot;&gt;getPointer&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;196&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;const char&lt;/span&gt; *BufEnd = CurMB-&amp;gt;&lt;span class=&quot;f&quot;&gt;getBufferEnd&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;197&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; (LineEnd != BufEnd &amp;amp;&amp;amp; LineEnd[&lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;] != &lt;span class=&quot;ch&quot;&gt;'\n'&lt;/span&gt; &amp;amp;&amp;amp; LineEnd[&lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;] != &lt;span class=&quot;ch&quot;&gt;'\r'&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt;198&lt;/span&gt;        ++LineEnd;
&lt;span class=&quot;ln&quot;&gt;199&lt;/span&gt;      LineStr = &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;string&lt;/span&gt;(LineStart, LineEnd);
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;    
&lt;span class=&quot;ln&quot;&gt;226&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;SMDiagnostic&lt;/span&gt;(*&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;, Loc, BufferID, LineAndCol.&lt;span class=&quot;vi&quot;&gt;first&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;227&lt;/span&gt;                        LineAndCol.&lt;span class=&quot;vi&quot;&gt;second&lt;/span&gt;-&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;, Kind, Msg.&lt;span class=&quot;f&quot;&gt;str&lt;/span&gt;(),
&lt;span class=&quot;ln&quot;&gt;228&lt;/span&gt;                        LineStr, ColRanges, FixIts);
&lt;span class=&quot;ln&quot;&gt;229&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The implementation of the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMDiagnostic&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;print&lt;/span&gt;&lt;/code&gt; function is what actually prints textual output (by default to &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;errs&lt;/span&gt;&lt;/code&gt;, which is just &lt;code&gt;&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::cerr&lt;/code&gt;, also known as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;STDERR&lt;/code&gt;). It's a fairly simple function, composed mostly of &lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;/code&gt; and print statements:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/llvm-mirror/llvm/blob/b5e9b6fb66a4245306cd51cae0abbd11b1f044df/lib/Support/SourceMgr.cpp&quot;&gt;llvm/lib/Support/SourceMgr.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;368&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;SMDiagnostic&lt;/span&gt;::print(&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; *ProgName, &lt;span class=&quot;cl&quot;&gt;raw_ostream&lt;/span&gt; &amp;amp;S,&lt;span class=&quot;f&quot;&gt; &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt;&lt;/span&gt; ShowColors,
&lt;span class=&quot;ln&quot;&gt;369&lt;/span&gt;                           &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; ShowKindLabel) &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;376&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (ProgName &amp;amp;&amp;amp; ProgName[&lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;])
&lt;span class=&quot;ln&quot;&gt;377&lt;/span&gt;      S &amp;lt;&amp;lt; ProgName &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot;: &quot;&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;378&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;379&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (!Filename.&lt;span class=&quot;f&quot;&gt;empty&lt;/span&gt;()) {
&lt;span class=&quot;ln&quot;&gt;380&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (Filename == &lt;span class=&quot;s&quot;&gt;&quot;-&quot;&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt;381&lt;/span&gt;        S &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot;&amp;lt;stdin&amp;gt;&quot;&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;382&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;383&lt;/span&gt;        S &amp;lt;&amp;lt; Filename;
&lt;span class=&quot;ln&quot;&gt;384&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;385&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (LineNo != -&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;) {
&lt;span class=&quot;ln&quot;&gt;386&lt;/span&gt;        S &amp;lt;&amp;lt; &lt;span class=&quot;ch&quot;&gt;':'&lt;/span&gt; &amp;lt;&amp;lt; LineNo;
&lt;span class=&quot;ln&quot;&gt;387&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (ColumnNo != -&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt;388&lt;/span&gt;          S &amp;lt;&amp;lt; &lt;span class=&quot;ch&quot;&gt;':'&lt;/span&gt; &amp;lt;&amp;lt; (ColumnNo+&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;389&lt;/span&gt;      }
&lt;span class=&quot;ln&quot;&gt;390&lt;/span&gt;      S &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot;: &quot;&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;391&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;392&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;393&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (ShowKindLabel) {
&lt;span class=&quot;ln&quot;&gt;394&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; (Kind) {
&lt;span class=&quot;ln&quot;&gt;395&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;DK_Error&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;398&lt;/span&gt;        S &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot;error: &quot;&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;399&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;400&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;DK_Warning&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;403&lt;/span&gt;        S &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot;warning: &quot;&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;404&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;405&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;DK_Note&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;408&lt;/span&gt;        S &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot;note: &quot;&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;409&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;410&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;DK_Remark&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;413&lt;/span&gt;        S &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot;remark: &quot;&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;414&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;415&lt;/span&gt;      }
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;421&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;422&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;423&lt;/span&gt;    S &amp;lt;&amp;lt; Message &amp;lt;&amp;lt; &lt;span class=&quot;ch&quot;&gt;'\n'&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;442&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// Build the line with the caret and ranges.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;443&lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;string&lt;/span&gt; CaretLine(NumColumns+&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;ch&quot;&gt;' '&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;444&lt;/span&gt;    
&lt;span class=&quot;ln&quot;&gt;445&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// Expand any ranges.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;446&lt;/span&gt;    for (&lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt; r = &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;, e = Ranges.&lt;span class=&quot;f&quot;&gt;size&lt;/span&gt;(); r != e; ++r) {
&lt;span class=&quot;ln&quot;&gt;447&lt;/span&gt;      &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;pair&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt;, &lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt;&amp;gt; R = Ranges[r];
&lt;span class=&quot;ln&quot;&gt;448&lt;/span&gt;      std::fill(&amp;amp;CaretLine[R.&lt;span class=&quot;vi&quot;&gt;first&lt;/span&gt;],
&lt;span class=&quot;ln&quot;&gt;449&lt;/span&gt;                &amp;amp;CaretLine[&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;min&lt;/span&gt;((&lt;span class=&quot;k&quot;&gt;size_t&lt;/span&gt;)R.&lt;span class=&quot;vi&quot;&gt;second&lt;/span&gt;, CaretLine.&lt;span class=&quot;f&quot;&gt;size&lt;/span&gt;())],
&lt;span class=&quot;ln&quot;&gt;450&lt;/span&gt;                &lt;span class=&quot;ch&quot;&gt;'~'&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;451&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;452&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;453&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// Add any fix-its.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;455&lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;string&lt;/span&gt; FixItInsertionLine;
&lt;span class=&quot;ln&quot;&gt;456&lt;/span&gt;    &lt;span class=&quot;f&quot;&gt;buildFixItLine&lt;/span&gt;(CaretLine, FixItInsertionLine, FixIts,
&lt;span class=&quot;ln&quot;&gt;457&lt;/span&gt;                   &lt;span class=&quot;f&quot;&gt;makeArrayRef&lt;/span&gt;(Loc.&lt;span class=&quot;f&quot;&gt;getPointer&lt;/span&gt;() - ColumnNo,
&lt;span class=&quot;ln&quot;&gt;458&lt;/span&gt;                                LineContents.&lt;span class=&quot;f&quot;&gt;size&lt;/span&gt;()));
&lt;span class=&quot;ln&quot;&gt;459&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;460&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// Finally, plop on the caret.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;461&lt;/span&gt;    if (&lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt;(ColumnNo) &amp;lt;= NumColumns)
&lt;span class=&quot;ln&quot;&gt;462&lt;/span&gt;      CaretLine[ColumnNo] = &lt;span class=&quot;ch&quot;&gt;'^'&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;463&lt;/span&gt;    else 
&lt;span class=&quot;ln&quot;&gt;464&lt;/span&gt;      CaretLine[NumColumns] = &lt;span class=&quot;ch&quot;&gt;'^'&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;465&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;466&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// ... and remove trailing whitespace so the output doesn't wrap for it.  We&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;467&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// know that the line isn't completely empty because it has the caret in it at&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;468&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// least.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;469&lt;/span&gt;    CaretLine.&lt;span class=&quot;f&quot;&gt;erase&lt;/span&gt;(CaretLine.&lt;span class=&quot;f&quot;&gt;find_last_not_of&lt;/span&gt;(&lt;span class=&quot;ch&quot;&gt;' '&lt;/span&gt;)+&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;470&lt;/span&gt;    
&lt;span class=&quot;ln&quot;&gt;471&lt;/span&gt;    &lt;span class=&quot;f&quot;&gt;printSourceLine&lt;/span&gt;(S, LineContents);
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;519&lt;/span&gt;    S &amp;lt;&amp;lt; &lt;span class=&quot;ch&quot;&gt;'\n'&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;520&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;What I wrote about above represents pretty much everything libLLVMSupport provides in the way of emitting diagnostics. I enjoy reading code like this in libLLVMSupport because it demystifies things that I would otherwise take for granted. The functionality in &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SMDiagnostic&lt;/span&gt;&lt;/code&gt; really boils down to storing strings in memory and printing to the console, but for some reason as a compiler &lt;em&gt;user&lt;/em&gt; I had always assumed there was something more magical going on behind the scenes. Maybe you felt similarly after reading this article.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I did, however, leave out some details, such as the internals of &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt;, and some of the complex caching logic that speeds up functions like &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getLineAndColumn&lt;/span&gt;&lt;/code&gt;. The former is especially interesting and I hope to write about it more someday – take a look yourself if you have the chance, by reading through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;llvm/include/llvm/Support/MemoryBuffer.h&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;llvm/lib/Support/MemoryBuffer.cpp&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the next article, I'll explain more about how the &lt;a href=&quot;https://github.com/apple/swift/&quot;&gt;apple/swift&lt;/a&gt; codebase wraps &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceMgr&lt;/span&gt;&lt;/code&gt; with the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;SourceManager&lt;/span&gt;&lt;/code&gt; class, how &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;&lt;/code&gt; instantiates a &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;MemoryBuffer&lt;/span&gt;&lt;/code&gt; for each source file, and about other Swift-specific abstractions, such as &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;DiagnosticEngine&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;</content><author><name></name></author><category term="swiftc" /><summary type="html">The prior article in this series explained how the Swift compiler lexes and parses source code, by looking at this syntactically valid Swift program:</summary></entry><entry><title type="html">Getting Started with the Swift Frontend: Lexing &amp;amp; Parsing</title><link href="https://modocache.io/the-swift-frontend-lexing-and-parsing" rel="alternate" type="text/html" title="Getting Started with the Swift Frontend: Lexing &amp;amp; Parsing" /><published>2018-02-05T05:00:00+00:00</published><updated>2018-02-05T05:00:00+00:00</updated><id>https://modocache.io/the-swift-frontend-lexing-and-parsing</id><content type="html" xml:base="https://modocache.io/the-swift-frontend-lexing-and-parsing">&lt;p&gt;&lt;a href=&quot;/reading-and-understanding-the-swift-driver-source-code&quot;&gt;A previous article&lt;/a&gt; in this series explained two primary ways of invoking the &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt;&lt;/code&gt; compiler executable: &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;When invoking &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt;, the &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt;&lt;/code&gt; executable enters its &lt;code&gt;&lt;span class=&quot;f&quot;&gt;main&lt;/span&gt;&lt;/code&gt; entry point and, once it sees the &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt; option, it begins to do everything you and I think of when we think of compilers: it attempts to lex the source file it's given, parse that file into a syntax tree, type-check it, produce an object file, and so on.&lt;/li&gt;
  &lt;li&gt;When invoking just &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt;&lt;/code&gt;, without the &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt; option, the &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt;&lt;/code&gt; executable splits itself up into child invocations of &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt;. The logic that Swift uses to split itself up is in the libswiftDriver library.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href=&quot;/reading-and-understanding-the-swift-driver-source-code&quot;&gt;Reading and Understanding the Swift Driver Source Code&lt;/a&gt; explains the libswiftDriver code that is executed in the second case. This article focuses on the first case: the &quot;compiler-y&quot; parts of the &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt;&lt;/code&gt; compiler executable.&lt;/p&gt;

&lt;p&gt;In a nutshell, I aim to answer the question. &quot;what happens when I compile this simple Swift program, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.swift&lt;/code&gt;?&quot;&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;hello.swift&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;1&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// hello.swift&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;3&lt;/span&gt;  &lt;span class=&quot;fs&quot;&gt;print&lt;/span&gt;(&lt;span class=&quot;s&quot;&gt;&quot;Hello, world!&quot;&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;parsing-a-swift-source-file&quot;&gt;Parsing a Swift source file&lt;/h2&gt;

&lt;p&gt;First, I'll recap some details covered in previous articles. For example, I've explained that I can compile the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.swift&lt;/code&gt; program on the command line, by invoking &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt; hello.swift&lt;/code&gt;. Even this simple invocation of &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt;&lt;/code&gt;, because it does not include the &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt; option, is split up into child jobs by the code in libswiftDriver. I can see these child jobs by invoking &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt; hello.swift &lt;span class=&quot;copt&quot;&gt;-driver-print-jobs&lt;/span&gt;&lt;/code&gt;, which outputs something like the following:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt; \
    &lt;span class=&quot;copt&quot;&gt;-c&lt;/span&gt; hello.swift \
    &lt;span class=&quot;copt&quot;&gt;-o&lt;/span&gt; /tmp/hello.o
&lt;span class=&quot;cmd&quot;&gt;ld&lt;/span&gt; /tmp/hello.o \
    &lt;span class=&quot;copt&quot;&gt;-lSystem&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-arch&lt;/span&gt; x86_64 &lt;span class=&quot;copt&quot;&gt;-macosx_version_min&lt;/span&gt; 10.13.0 \
    &lt;span class=&quot;copt&quot;&gt;-L&lt;/span&gt; /Users/bgesiak/Source/apple/build/Ninja-ReleaseAssert+swift-DebugAssert/swift-macosx-x86_64/lib/swift/macosx \
    &lt;span class=&quot;copt&quot;&gt;-rpath&lt;/span&gt; /Users/bgesiak/Source/apple/build/Ninja-ReleaseAssert+swift-DebugAssert/swift-macosx-x86_64/lib/swift/macosx \
    &lt;span class=&quot;copt&quot;&gt;-o&lt;/span&gt; hello
&lt;/pre&gt;

&lt;p&gt;The first job invokes &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt; in order to produce an object file named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.o&lt;/code&gt;, and the second job invokes the linker &lt;code&gt;&lt;span class=&quot;cmd&quot;&gt;ld&lt;/span&gt;&lt;/code&gt; in order to link that object file into an executable named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The first invocation appears to be very short, but make no mistake: it executes a &lt;em&gt;lot&lt;/em&gt; of code, from a diverse set of libraries. These libraries include libswiftFrontend, libswiftParse, libswiftAST, libswiftSema, libswiftSIL, and more.&lt;/p&gt;

&lt;p&gt;Covering each of these libraries in a single article would be exhausting. Instead, this article focuses on the first few phases of &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-c&lt;/span&gt; hello.swift&lt;/code&gt;. It'll cover libswiftFrontendTool, libswiftFrontend, and libswiftParse. These three libraries are used, in conjunction with libswiftAST, to build a tree structure that represents the untyped syntax tree of the Swift source file.&lt;/p&gt;

&lt;p&gt;I can display the untyped syntax tree by invoking &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt; hello.swift &lt;span class=&quot;copt&quot;&gt;-dump-parse&lt;/span&gt;&lt;/code&gt;, which outputs the following:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;astp&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;aststmt&quot;&gt;source_file&lt;/span&gt;
  &lt;span class=&quot;astp&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;astdecl&quot;&gt;top_level_code_decl&lt;/span&gt;
    &lt;span class=&quot;astp&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;aststmt&quot;&gt;brace_stmt&lt;/span&gt;
      &lt;span class=&quot;astp&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;astexpr&quot;&gt;call_expr&lt;/span&gt; &lt;span class=&quot;asto&quot;&gt;type='&amp;lt;null&amp;gt;' arg_labels=_:&lt;/span&gt;
        &lt;span class=&quot;astp&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;astexpr&quot;&gt;unresolved_decl_ref_expr&lt;/span&gt; &lt;span class=&quot;asto&quot;&gt;type='&amp;lt;null&amp;gt;' name=print function_ref=unapplied)&lt;/span&gt;
        &lt;span class=&quot;astp&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;astexpr&quot;&gt;paren_expr&lt;/span&gt; &lt;span class=&quot;asto&quot;&gt;type='&amp;lt;null&amp;gt;'&lt;/span&gt;
          &lt;span class=&quot;astp&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;astexpr&quot;&gt;string_literal_expr&lt;/span&gt; &lt;span class=&quot;asto&quot;&gt;type='&amp;lt;null&amp;gt;' encoding=utf8 value=&quot;Hello, world!&quot; builtin_initializer=**NULL** initializer=**NULL**&lt;/span&gt;&lt;span class=&quot;astp&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;astp&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;astp&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;astp&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;astp&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;astp&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;

&lt;blockquote&gt;
  &lt;p&gt;Note the difference between the untyped tree above and the &lt;em&gt;typed&lt;/em&gt; syntax tree that &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-dump-ast&lt;/span&gt;&lt;/code&gt; produces:&lt;/p&gt;

  &lt;pre&gt;
&lt;span class=&quot;astp&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;aststmt&quot;&gt;source_file&lt;/span&gt;
  &lt;span class=&quot;astp&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;astdecl&quot;&gt;top_level_code_decl&lt;/span&gt;
    &lt;span class=&quot;astp&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;aststmt&quot;&gt;brace_stmt&lt;/span&gt;
      &lt;span class=&quot;astp&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;astexpr&quot;&gt;call_expr&lt;/span&gt; &lt;span class=&quot;asto&quot;&gt;type='()' location=hello.swift:3:1 range=[hello.swift:3:1 - line:3:22] nothrow arg_labels=_:&lt;/span&gt;
        &lt;span class=&quot;astp&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;astexpr&quot;&gt;declref_expr&lt;/span&gt; &lt;span class=&quot;asto&quot;&gt;type='(Any..., String, String) -&amp;gt; ()' location=hello.swift:3:1 range=[hello.swift:3:1 - line:3:1] decl=Swift.(file).print(_:separator:terminator:) function_ref=single)&lt;/span&gt;
        &lt;span class=&quot;astp&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;astexpr&quot;&gt;tuple_shuffle_expr&lt;/span&gt; &lt;span class=&quot;asto&quot;&gt;implicit type='(Any..., separator: String, terminator: String)' location=hello.swift:3:7 range=[hello.swift:3:6 - line:3:22] scalar_to_tuple elements=[-2, -1, -1] variadic_sources=[0] default_args_owner=Swift.(file).print(_:separator:terminator:)&lt;/span&gt;
          &lt;span class=&quot;astp&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;astexpr&quot;&gt;paren_expr&lt;/span&gt; &lt;span class=&quot;asto&quot;&gt;type='Any' location=hello.swift:3:7 range=[hello.swift:3:6 - line:3:22]&lt;/span&gt;
            &lt;span class=&quot;astp&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;astexpr&quot;&gt;erasure_expr&lt;/span&gt; &lt;span class=&quot;asto&quot;&gt;implicit type='Any' location=hello.swift:3:7 range=[hello.swift:3:7 - line:3:7]&lt;/span&gt;
              &lt;span class=&quot;astp&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;astexpr&quot;&gt;string_literal_expr&lt;/span&gt; &lt;span class=&quot;asto&quot;&gt;type='String' location=hello.swift:3:7 range=[hello.swift:3:7 - line:3:7] encoding=utf8 value=&quot;Hello, world!&quot; builtin_initializer=Swift.(file).String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) initializer=**NULL**&lt;/span&gt;&lt;span class=&quot;astp&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;astp&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;astp&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;astp&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;astp&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;astp&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;astp&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;astp&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;

  &lt;p&gt;Specifically, the untyped tree features nodes such as &lt;code&gt;&lt;span class=&quot;astexpr&quot;&gt;unresolved_decl_ref_expr&lt;/span&gt;&lt;/code&gt;, and many nodes also have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type='&amp;lt;null&amp;gt;'&lt;/code&gt; value. These are later filled in with type information as part of the type-checker, which is implemented in libswiftSema. I'll cover libswiftSema in a future article.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;the-first-six-stages-of-the-swift-frontend-lexing--parsing&quot;&gt;The first six stages of the Swift frontend: lexing &amp;amp; parsing&lt;/h2&gt;

&lt;p&gt;Just how does the &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt;&lt;/code&gt; executable read the text in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.swift&lt;/code&gt; file to construct an untyped syntax tree? How does it determine that &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;print&lt;/span&gt;(&lt;span class=&quot;s&quot;&gt;&quot;Hello, world!&quot;&lt;/span&gt;)&lt;/code&gt; is a &lt;code&gt;&lt;span class=&quot;astexpr&quot;&gt;call_expr&lt;/span&gt;&lt;/code&gt; that wraps a &lt;code&gt;&lt;span class=&quot;astexpr&quot;&gt;paren_expr&lt;/span&gt;&lt;/code&gt; that wraps a &lt;code&gt;&lt;span class=&quot;astexpr&quot;&gt;string_literal_expr&lt;/span&gt;&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;At a high level, the frontend completes parsing in about 6 stages:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The &lt;code&gt;&lt;span class=&quot;f&quot;&gt;main&lt;/span&gt;&lt;/code&gt; function in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/tools/driver/driver.cpp&lt;/code&gt; sees that the first argument it's been passed is &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt;, and so it invokes the libswiftFrontendTool library's &lt;code&gt;&lt;span class=&quot;f&quot;&gt;performFrontend&lt;/span&gt;&lt;/code&gt; function.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;&lt;span class=&quot;f&quot;&gt;performFrontend&lt;/span&gt;&lt;/code&gt; parses command-line arguments to determine the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;FrontendOptions&lt;/span&gt;::&lt;span class=&quot;vi&quot;&gt;RequestedAction&lt;/span&gt;&lt;/code&gt;, by using the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInvocation&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseArgs&lt;/span&gt;&lt;/code&gt; member function. It then instantiates &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;ASTContext&lt;/span&gt;&lt;/code&gt; objects based on those arguments. Finally, it calls the libswiftFrontendTool function &lt;code&gt;&lt;span class=&quot;f&quot;&gt;performCompile&lt;/span&gt;&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;&lt;span class=&quot;f&quot;&gt;performCompile&lt;/span&gt;&lt;/code&gt; uses the requested &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;FrontendOptions&lt;/span&gt;::&lt;span class=&quot;vi&quot;&gt;RequestedAction&lt;/span&gt;&lt;/code&gt; to determine whether to call &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;performParseOnly&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;performSema&lt;/span&gt;&lt;/code&gt;. Our invocation of &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-c&lt;/span&gt;&lt;/code&gt; results in a requested action of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ActionType::EmitObject&lt;/code&gt;, and so &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;performSema&lt;/span&gt;&lt;/code&gt; is called.&lt;/li&gt;
  &lt;li&gt;The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;performSema&lt;/span&gt;&lt;/code&gt; member function calls through to several other member functions. It opens a bitstream cursor into the standard library module &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Swift.swiftmodule&lt;/code&gt; (it'll use this cursor later, in order to determine the type of the parsed &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;print&lt;/span&gt;(...)&lt;/code&gt; expression). It adds a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;SourceFile&lt;/span&gt;&lt;/code&gt; node to the root of the AST. It also calls the &lt;code&gt;&lt;span class=&quot;f&quot;&gt;parseIntoSourceFile&lt;/span&gt;&lt;/code&gt; function, which instantiates a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;&lt;/code&gt; and calls the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseTopLevel&lt;/span&gt;&lt;/code&gt; member function. This member function begins the process of lexing and parsing the text in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.swift&lt;/code&gt; source file.&lt;/li&gt;
  &lt;li&gt;The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;&lt;/code&gt; works in tandem with a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;&lt;/code&gt;, which it creates and stores internally as part of the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;&lt;/code&gt; initializer. When the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseTopLevel&lt;/span&gt;&lt;/code&gt; member is called, that kicks off an endless loop that:
    &lt;ol&gt;
      &lt;li&gt;Lexes a &quot;token&quot;. A token is a series of characters in the source file that form a cohesive unit. For example, the first token lexed in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.swift&lt;/code&gt; is &lt;code&gt;&lt;span class=&quot;s&quot;&gt;&quot;print&quot;&lt;/span&gt;&lt;/code&gt;. That's because the lexer first sees a &lt;code&gt;&lt;span class=&quot;ch&quot;&gt;'p'&lt;/span&gt;&lt;/code&gt;, determines that it must be the start of an identifier (i.e.: an alphabetical character, followed by any number of alphanumeric characters or underscores), and so continues to read in characters until it sees a &lt;code&gt;&lt;span class=&quot;ch&quot;&gt;'('&lt;/span&gt;&lt;/code&gt;, at which point it stops.&lt;/li&gt;
      &lt;li&gt;The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;&lt;/code&gt; looks at the token that the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;&lt;/code&gt; has lexed, and determines what to &quot;parse.&quot; For example, when the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;&lt;/code&gt; sees that the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;&lt;/code&gt; has lexed an identifier token of &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;print&lt;/span&gt;&lt;/code&gt;, it asks the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;&lt;/code&gt; to lex the next token. Because that next token is a &lt;code&gt;&lt;span class=&quot;ch&quot;&gt;'('&lt;/span&gt;&lt;/code&gt;, it determines that it must be parsing a call expression. It asks the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;&lt;/code&gt; to lex the appropriate number of tokens in order to close the &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;print&lt;/span&gt;(...)&lt;/code&gt; expression. Once it has, the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;&lt;/code&gt; instantiates a new AST node: &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CallExpr&lt;/span&gt;&lt;/code&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;&lt;/code&gt; continue their endless loop, instantiating new AST nodes,  such as &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CallExpr&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;StringLiteralExpr&lt;/span&gt;&lt;/code&gt;, and adding them to the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;ASTContext&lt;/span&gt;&lt;/code&gt;. Eventually they reach the end of the source file. Normally at this point libswiftFrontend would continue by kicking off the type-checker for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.swift&lt;/code&gt;. However, that's beyond the scope of this article, so we'll stop here.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The rest of this article steps through the code behind these six steps, explaining them in more detail.&lt;/p&gt;

&lt;h2 id=&quot;stage-1-parsing-the--frontend-argument&quot;&gt;Stage 1: Parsing the &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt; argument&lt;/h2&gt;

&lt;p&gt;As explained in &lt;a href=&quot;/reading-and-understanding-the-swift-driver-source-code&quot;&gt;my libswiftDriver article&lt;/a&gt;, &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt;&lt;/code&gt; is just a C++ executable. Any invocation of a C++ executable begins in its &lt;code&gt;&lt;span class=&quot;f&quot;&gt;main&lt;/span&gt;&lt;/code&gt; function. The &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt;&lt;/code&gt; executable's &lt;code&gt;&lt;span class=&quot;f&quot;&gt;main&lt;/span&gt;&lt;/code&gt; function is defined in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/tools/driver/driver.cpp&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Recall that one of the first things the Swift compiler's &lt;code&gt;&lt;span class=&quot;f&quot;&gt;main&lt;/span&gt;&lt;/code&gt; function does is check for the first argument it's given. If that argument is &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt;, it calls the &lt;code&gt;&lt;span class=&quot;f&quot;&gt;performFrontend&lt;/span&gt;&lt;/code&gt; function:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/tools/driver/driver.cpp#L160-L164&quot;&gt;swift/tools/driver/driver.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;111&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; main(&lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; argc_, &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; **argv_) {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;158&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt; FirstArg(argv[&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;]);
&lt;span class=&quot;ln&quot;&gt;159&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (FirstArg == &lt;span class=&quot;s&quot;&gt;&quot;-frontend&quot;&lt;/span&gt;) {
&lt;span class=&quot;ln&quot;&gt;160&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;f&quot;&gt;performFrontend&lt;/span&gt;(&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;makeArrayRef&lt;/span&gt;(argv.&lt;span class=&quot;f&quot;&gt;data&lt;/span&gt;()+&lt;span class=&quot;num&quot;&gt;2&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;161&lt;/span&gt;                                                argv.&lt;span class=&quot;f&quot;&gt;data&lt;/span&gt;()+argv.&lt;span class=&quot;f&quot;&gt;size&lt;/span&gt;()),
&lt;span class=&quot;ln&quot;&gt;162&lt;/span&gt;                             argv[&lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;], (&lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; *)(&lt;span class=&quot;ts&quot;&gt;intptr_t&lt;/span&gt;)&lt;span class=&quot;f&quot;&gt;getExecutablePath&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;163&lt;/span&gt;    }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Note that &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt; &lt;em&gt;must&lt;/em&gt; be the first argument; invoking &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-c&lt;/span&gt; hello.swift &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt; is &lt;em&gt;not&lt;/em&gt; considered a frontend invocation, and the &lt;code&gt;&lt;span class=&quot;f&quot;&gt;performFrontend&lt;/span&gt;&lt;/code&gt; function will not be called. The machinery described in my previous article, &lt;a href=&quot;/option-parsing-in-the-swift-compiler&quot;&gt;Option Parsing in the Swift Compiler&lt;/a&gt;, hasn't been initialized yet, and so libswiftOption and libLLVMOption are not used here to check for &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;options&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;ID&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;OPT_frontend&lt;/span&gt;&lt;/code&gt;. Instead, this is a naive string comparison.&lt;/p&gt;

&lt;h2 id=&quot;stage-2-instantiating-a-compilerinstance-based-on-command-line-arguments&quot;&gt;Stage 2: Instantiating a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;&lt;/code&gt; based on command-line arguments&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;f&quot;&gt;performFrontend&lt;/span&gt;&lt;/code&gt; function is part of the libswiftFrontendTool library. libswiftFrontendTool is a tiny Swift compiler library whose single purpose is to drive the frontend compilation process.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The build code for libswiftFrontendTool – which determines the files that are included in the library, how it is built, and which libraries it depends on – is all defined in CMake. Check out the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/lib/FrontendTool/CMakeLists.txt&lt;/code&gt; file to learn more.&lt;/p&gt;

  &lt;p&gt;There's nothing particularly exciting about the libswiftFrontendTool CMake, so I won't cover it here. A previous article, &lt;a href=&quot;/reading-and-understanding-the-cmake-in-apple-swift&quot;&gt;Reading and Understanding the CMake in apple/swift&lt;/a&gt;, has tips on how to read the CMake yourself.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;f&quot;&gt;performFrontend&lt;/span&gt;&lt;/code&gt; function instantiates a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;&lt;/code&gt; and a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInvocation&lt;/span&gt;&lt;/code&gt;, and then performs argument parsing:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/FrontendTool/FrontendTool.cpp#L160-L164&quot;&gt;swift/lib/FrontendTool/FrontendTool.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;1304&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::performFrontend(&lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;const char&lt;/span&gt; *&amp;gt; Args,
&lt;span class=&quot;ln&quot;&gt;1305&lt;/span&gt;                             &lt;span class=&quot;k&quot;&gt;const char&lt;/span&gt; *Argv0, &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; *MainAddr,
&lt;span class=&quot;ln&quot;&gt;1306&lt;/span&gt;                             &lt;span class=&quot;cl&quot;&gt;FrontendObserver&lt;/span&gt; *observer) {
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;1348&lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;&amp;gt; Instance =
&lt;span class=&quot;ln&quot;&gt;1349&lt;/span&gt;      &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;make_unique&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;&amp;gt;();
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1371&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;CompilerInvocation&lt;/span&gt; Invocation;
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1379&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// Parse arguments.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1380&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (Invocation.&lt;span class=&quot;f&quot;&gt;parseArgs&lt;/span&gt;(Args, Instance-&amp;gt;&lt;span class=&quot;f&quot;&gt;getDiags&lt;/span&gt;(), workingDirectory)) {
&lt;span class=&quot;ln&quot;&gt;1381&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; finishDiagProcessing(&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;1382&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;1542&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;As I mentioned in &lt;a href=&quot;/reading-and-understanding-the-swift-driver-source-code&quot;&gt;previous articles&lt;/a&gt;, I'll elide source code that isn't relevant to understanding the topic at hand: how the Swift compiler parses Swift source code. Besdies what's shown above, the &lt;code&gt;&lt;span class=&quot;f&quot;&gt;performFrontend&lt;/span&gt;&lt;/code&gt; function also calls functions like &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;InitializeAllTargets&lt;/span&gt;&lt;/code&gt;. If it didn't, the Swift compiler would not be able to generate object files. But this article isn't about generating object files, so I won't include that code in these snippets.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;&lt;/code&gt; class is arguably one of the most important classes in the Swift codebase. It's defined as part of the libswiftFrontend library. It's significant because it holds unique, owning references of several important singletons. For example, it holds a unique pointer to the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;ASTContext&lt;/span&gt;&lt;/code&gt;, which is a singleton that stores all AST nodes that are created by the compiler.&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/include/swift/Frontend/Frontend.h#L304-L579&quot;&gt;swift/include/swift/Frontend/Frontend.h&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;304&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// A class which manages the state and execution of the compiler.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;305&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// This owns the primary compiler singletons, such as the ASTContext,&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;306&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// as well as various build products such as the SILModule.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;307&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;///&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;308&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// Before a CompilerInstance can be used, it must be configured by&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;309&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// calling &lt;span class=&quot;dk&quot;&gt;\a&lt;/span&gt; setup.  If successful, this will create an ASTContext&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;310&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// and set up the basic compiler invariants.  Calling &lt;span class=&quot;dk&quot;&gt;\a&lt;/span&gt; setup multiple&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;311&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// times on a single CompilerInstance is not permitted.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;312&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; CompilerInstance {
&lt;span class=&quot;ln&quot;&gt;313&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;CompilerInvocation&lt;/span&gt; Invocation;
&lt;span class=&quot;ln&quot;&gt;314&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;SourceManager&lt;/span&gt; SourceMgr;
&lt;span class=&quot;ln&quot;&gt;315&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;DiagnosticEngine&lt;/span&gt; Diagnostics{&lt;span class=&quot;vi&quot;&gt;SourceMgr&lt;/span&gt;};
&lt;span class=&quot;ln&quot;&gt;316&lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;ASTContext&lt;/span&gt;&amp;gt; Context;
&lt;span class=&quot;ln&quot;&gt;317&lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;SILModule&lt;/span&gt;&amp;gt; TheSILModule;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;578&lt;/span&gt;  };
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;f&quot;&gt;performFrontend&lt;/span&gt;&lt;/code&gt; function also instantiates a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInvocation&lt;/span&gt;&lt;/code&gt; object. Not to be confused with &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;&lt;/code&gt;, the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInvocation&lt;/span&gt;&lt;/code&gt; class is practically a glorified bag of options. It's responsible for parsing command-line arguments to &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt;, and storing their values in various &quot;options&quot; classes, like &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;FrontendOptions&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;LangOptions&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/include/swift/Frontend/Frontend.h#L53-L303&quot;&gt;swift/include/swift/Frontend/Frontend.h&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt; 53&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// The abstract configuration of the compiler, including:&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 54&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;///   - options for all stages of translation,&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 55&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;///   - information about the build environment,&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 56&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;///   - information about the job being performed, and&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 57&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;///   - lists of inputs.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 58&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;///&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 59&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// A CompilerInvocation can be built from a frontend command line&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 60&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// using parseArgs.  It can then be used to build a CompilerInstance,&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 61&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// which manages the actual compiler execution.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 62&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; CompilerInvocation {
&lt;span class=&quot;ln&quot;&gt; 63&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;LangOptions&lt;/span&gt; LangOpts;
&lt;span class=&quot;ln&quot;&gt; 64&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;FrontendOptions&lt;/span&gt; FrontendOpts;
&lt;span class=&quot;ln&quot;&gt; 65&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;ClangImporterOptions&lt;/span&gt; ClangImporterOpts;
&lt;span class=&quot;ln&quot;&gt; 66&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;SearchPathOptions&lt;/span&gt; SearchPathOpts;
&lt;span class=&quot;ln&quot;&gt; 67&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;DiagnosticOptions&lt;/span&gt; DiagnosticOpts;
&lt;span class=&quot;ln&quot;&gt; 68&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;MigratorOptions&lt;/span&gt; MigratorOpts;
&lt;span class=&quot;ln&quot;&gt; 69&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;SILOptions&lt;/span&gt; SILOpts;
&lt;span class=&quot;ln&quot;&gt; 70&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;IRGenOptions&lt;/span&gt; IRGenOpts;
&lt;span class=&quot;ln&quot;&gt; ..&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt; 80&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt; ..&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 83&lt;/span&gt;    &lt;span class=&quot;d&quot;&gt;/// Initializes the compiler invocation for the list of arguments.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; ..&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 92&lt;/span&gt;    &lt;span class=&quot;d&quot;&gt;/// &lt;span class=&quot;dk&quot;&gt;\returns&lt;/span&gt; true if there was an error, false on success.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 93&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; parseArgs(&lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;const char&lt;/span&gt; *&amp;gt; Args, &lt;span class=&quot;cl&quot;&gt;DiagnosticEngine&lt;/span&gt; &amp;amp;Diags,
&lt;span class=&quot;ln&quot;&gt; 94&lt;/span&gt;                   &lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt; workingDirectory = {});
&lt;span class=&quot;ln&quot;&gt; ..&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;302&lt;/span&gt;  };
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;A &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInvocation&lt;/span&gt;&lt;/code&gt; object, then, is basically just a collection of parameters that are used to initialize the all-important &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;&lt;/code&gt;. The command-line arguments to &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt; are translated into the appropriate settings on a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInvocation&lt;/span&gt;&lt;/code&gt; object, via its &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInvocation&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseArgs&lt;/span&gt;&lt;/code&gt; member function.&lt;/p&gt;

&lt;h3 id=&quot;21-parsing-frontend-command-line-arguments&quot;&gt;2.1: Parsing frontend command-line arguments&lt;/h3&gt;

&lt;p&gt;If you've read &lt;a href=&quot;/option-parsing-in-the-swift-compiler&quot;&gt;Option Parsing in the Swift Compiler&lt;/a&gt;, the body of the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInvocation&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseArgs&lt;/span&gt;&lt;/code&gt; member function should look very familiar to you. It parses arguments using the exact same libswiftOption and libLLVMOption abstractions as the Swift driver does: &lt;code&gt;&lt;span class=&quot;f&quot;&gt;createSwiftOptTable&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;opt&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;OptTable&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;ParseArgs&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/Frontend/CompilerInvocation.cpp#L962-L1032&quot;&gt;swift/lib/Frontend/CompilerInvocation.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt; 962&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;CompilerInvocation&lt;/span&gt;::parseArgs(&lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;const char&lt;/span&gt; *&amp;gt; Args,
&lt;span class=&quot;ln&quot;&gt; 963&lt;/span&gt;                                     &lt;span class=&quot;cl&quot;&gt;DiagnosticEngine&lt;/span&gt; &amp;amp;Diags,
&lt;span class=&quot;ln&quot;&gt; 964&lt;/span&gt;                                     &lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt; workingDirectory) {
&lt;span class=&quot;ln&quot;&gt; ...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 973&lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;opt&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;OptTable&lt;/span&gt;&amp;gt; Table = &lt;span class=&quot;f&quot;&gt;createSwiftOptTable&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt; 974&lt;/span&gt;    &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;opt&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;InputArgList&lt;/span&gt; ParsedArgs =
&lt;span class=&quot;ln&quot;&gt; 975&lt;/span&gt;        Table-&amp;gt;&lt;span class=&quot;f&quot;&gt;ParseArgs&lt;/span&gt;(Args, MissingIndex, MissingCount, &lt;span class=&quot;cn&quot;&gt;FrontendOption&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt; ...&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt; 990&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;f&quot;&gt;ParseFrontendArgs&lt;/span&gt;(&lt;span class=&quot;vi&quot;&gt;FrontendOpts&lt;/span&gt;, ParsedArgs, Diags)) {
&lt;span class=&quot;ln&quot;&gt; 991&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt; 992&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt; 993&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt; 994&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;f&quot;&gt;ParseLangArgs&lt;/span&gt;(&lt;span class=&quot;vi&quot;&gt;LangOpts&lt;/span&gt;, ParsedArgs, Diags, &lt;span class=&quot;vi&quot;&gt;FrontendOpts&lt;/span&gt;)) {
&lt;span class=&quot;ln&quot;&gt; 995&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt; 996&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt; ...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1030&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;1031&lt;/span&gt;  }
&lt;span class=&quot;ln&quot;&gt;1032&lt;/span&gt;  
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;After converting the command-line strings into an &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;opt&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;InputArgList&lt;/span&gt;&lt;/code&gt; via the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;opt&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;OptTable&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;ParseArgs&lt;/span&gt;&lt;/code&gt; member function, the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInvocation&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseArgs&lt;/span&gt;&lt;/code&gt; member function calls functions like &lt;code&gt;&lt;span class=&quot;f&quot;&gt;ParseFrontendArgs&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;f&quot;&gt;ParseLangArgs&lt;/span&gt;&lt;/code&gt;, and so on, in order to set values on members such as &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInvocation&lt;/span&gt;::&lt;span class=&quot;vi&quot;&gt;LangOpts&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example, &lt;code&gt;&lt;span class=&quot;f&quot;&gt;ParseLangArgs&lt;/span&gt;&lt;/code&gt; is responsible for translating the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;options&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;ID&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;OPT_swift_version&lt;/span&gt;&lt;/code&gt; stored on the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;opt&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;InputArgList&lt;/span&gt;&lt;/code&gt;, and using that to set &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInvocation&lt;/span&gt;::&lt;span class=&quot;vi&quot;&gt;LangOpts&lt;/span&gt;::&lt;span class=&quot;vi&quot;&gt;EffectiveLanguageVersion&lt;/span&gt;&lt;/code&gt;. If the version passed in is invalid, it emits an error diagnostic:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/Frontend/CompilerInvocation.cpp#L125-L355&quot;&gt;swift/lib/Frontend/CompilerInvocation.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;125&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; ParseLangArgs(&lt;span class=&quot;cl&quot;&gt;LangOptions&lt;/span&gt; &amp;amp;Opts, &lt;span class=&quot;cl&quot;&gt;ArgList&lt;/span&gt; &amp;amp;Args,
&lt;span class=&quot;ln&quot;&gt;126&lt;/span&gt;                            &lt;span class=&quot;cl&quot;&gt;DiagnosticEngine&lt;/span&gt; &amp;amp;Diags,
&lt;span class=&quot;ln&quot;&gt;127&lt;/span&gt;                            &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;FrontendOptions&lt;/span&gt; &amp;amp;FrontendOpts) {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;136&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; A = Args.&lt;span class=&quot;f&quot;&gt;getLastArg&lt;/span&gt;(&lt;span class=&quot;cn&quot;&gt;OPT_swift_version&lt;/span&gt;)) {
&lt;span class=&quot;ln&quot;&gt;137&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; vers = &lt;span class=&quot;t&quot;&gt;version&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Version&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseVersionString&lt;/span&gt;(
&lt;span class=&quot;ln&quot;&gt;138&lt;/span&gt;        A-&amp;gt;&lt;span class=&quot;f&quot;&gt;getValue&lt;/span&gt;(), &lt;span class=&quot;cl&quot;&gt;SourceLoc&lt;/span&gt;(), &amp;amp;Diags);
&lt;span class=&quot;ln&quot;&gt;139&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; isValid = &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;140&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (vers.&lt;span class=&quot;f&quot;&gt;hasValue&lt;/span&gt;()) {
&lt;span class=&quot;ln&quot;&gt;141&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; effectiveVers = vers.&lt;span class=&quot;f&quot;&gt;getValue&lt;/span&gt;().&lt;span class=&quot;f&quot;&gt;getEffectiveLanguageVersion&lt;/span&gt;()) {
&lt;span class=&quot;ln&quot;&gt;142&lt;/span&gt;          Opts.&lt;span class=&quot;vi&quot;&gt;EffectiveLanguageVersion&lt;/span&gt; = effectiveVers.&lt;span class=&quot;f&quot;&gt;getValue&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;143&lt;/span&gt;          isValid = &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;144&lt;/span&gt;        }
&lt;span class=&quot;ln&quot;&gt;145&lt;/span&gt;      }
&lt;span class=&quot;ln&quot;&gt;146&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (!isValid)
&lt;span class=&quot;ln&quot;&gt;147&lt;/span&gt;        &lt;span class=&quot;f&quot;&gt;diagnoseSwiftVersion&lt;/span&gt;(vers, A, Args, Diags);
&lt;span class=&quot;ln&quot;&gt;148&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;355&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;To test this out, we can try passing &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt; an invalid language version, such as &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-c&lt;/span&gt; hello.swift &lt;span class=&quot;copt&quot;&gt;-swift-version&lt;/span&gt; foo&lt;/code&gt;. This outputs:&lt;/p&gt;

  &lt;pre&gt;
&lt;span class=&quot;diag&quot;&gt;&amp;lt;unknown&amp;gt;:0: &lt;span class=&quot;de&quot;&gt;error:&lt;/span&gt; version component contains non-numeric characters&lt;/span&gt;
&lt;span class=&quot;diag&quot;&gt;&amp;lt;unknown&amp;gt;:0: &lt;span class=&quot;de&quot;&gt;error:&lt;/span&gt; invalid value 'foo' in '-swift-version foo'&lt;/span&gt;
&lt;span class=&quot;diag&quot;&gt;&amp;lt;unknown&amp;gt;:0: &lt;span class=&quot;dn&quot;&gt;note:&lt;/span&gt; valid arguments to '-swift-version' are '3', '4', '5'&lt;/span&gt;
&lt;/pre&gt;

  &lt;p&gt;If you're curious what other combinations of Swift language versions are valid, you can take a look at the libswiftBasic functions that the &lt;code&gt;&lt;span class=&quot;f&quot;&gt;ParseLangArgs&lt;/span&gt;&lt;/code&gt; function uses above: &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Version&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseVersionString&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Version&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getEffectiveLanguageVersion&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One of the most important parts of this argument parsing is done in the &lt;code&gt;&lt;span class=&quot;f&quot;&gt;ParseFrontendArgs&lt;/span&gt;&lt;/code&gt; function. This calls through to the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;ArgsToFrontendConverter&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;determineRequestedAction&lt;/span&gt;&lt;/code&gt; member function, in order to set the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInvocation&lt;/span&gt;&lt;/code&gt; object's &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;FrontendOptions&lt;/span&gt;::&lt;span class=&quot;vi&quot;&gt;RequestedAction&lt;/span&gt;&lt;/code&gt;, based on whether the frontend was invoked with &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-emit-object&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-emit-sil&lt;/span&gt;&lt;/code&gt;, or some other option. This &quot;requested action&quot; will determine what logic the frontend executes:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/Frontend/ArgsToFrontendOptionsConverter.cpp#L269-L331&quot;&gt;swift/lib/Frontend/ArgsToFrontendOptionsConverter.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;269&lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;FrontendOptions&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;ActionType&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;270&lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;ArgsToFrontendOptionsConverter&lt;/span&gt;::determineRequestedAction() &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; {
&lt;span class=&quot;ln&quot;&gt;271&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;using namespace&lt;/span&gt; options;
&lt;span class=&quot;ln&quot;&gt;272&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Arg&lt;/span&gt; *A = Args.&lt;span class=&quot;f&quot;&gt;getLastArg&lt;/span&gt;(&lt;span class=&quot;cn&quot;&gt;OPT_modes_Group&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;283&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;Option&lt;/span&gt; Opt = A-&amp;gt;&lt;span class=&quot;f&quot;&gt;getOption&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;284&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (Opt.&lt;span class=&quot;f&quot;&gt;matches&lt;/span&gt;(&lt;span class=&quot;cn&quot;&gt;OPT_emit_object&lt;/span&gt;))
&lt;span class=&quot;ln&quot;&gt;285&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;FrontendOptions&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;ActionType&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;EmitObject&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;286&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (Opt.&lt;span class=&quot;f&quot;&gt;matches&lt;/span&gt;(&lt;span class=&quot;cn&quot;&gt;OPT_emit_assembly&lt;/span&gt;))
&lt;span class=&quot;ln&quot;&gt;287&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;FrontendOptions&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;ActionType&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;EmitAssembly&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;288&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (Opt.&lt;span class=&quot;f&quot;&gt;matches&lt;/span&gt;(&lt;span class=&quot;cn&quot;&gt;OPT_emit_ir&lt;/span&gt;))
&lt;span class=&quot;ln&quot;&gt;289&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;FrontendOptions&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;ActionType&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;EmitIR&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;308&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (Opt.&lt;span class=&quot;f&quot;&gt;matches&lt;/span&gt;(&lt;span class=&quot;cn&quot;&gt;OPT_dump_parse&lt;/span&gt;))
&lt;span class=&quot;ln&quot;&gt;309&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;FrontendOptions&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;ActionType&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;DumpParse&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;310&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (Opt.&lt;span class=&quot;f&quot;&gt;matches&lt;/span&gt;(&lt;span class=&quot;cn&quot;&gt;OPT_dump_ast&lt;/span&gt;))
&lt;span class=&quot;ln&quot;&gt;311&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;FrontendOptions&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;ActionType&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;DumpAST&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;330&lt;/span&gt;    &lt;span class=&quot;m&quot;&gt;llvm_unreachable&lt;/span&gt;(&lt;span class=&quot;s&quot;&gt;&quot;Unhandled mode option&quot;&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;331&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;My invocation of &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-c&lt;/span&gt; hello.swift&lt;/code&gt; does not appear to include the argument &lt;code&gt;&lt;span class=&quot;cn&quot;&gt;OPT_emit_object&lt;/span&gt;&lt;/code&gt;. However, a quick peek at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Options.td&lt;/code&gt; (covered in depth in the article on &lt;a href=&quot;/option-parsing-in-the-swift-compiler&quot;&gt;Option Parsing in the Swift Compiler&lt;/a&gt;) reveals that &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-c&lt;/span&gt;&lt;/code&gt; is an alias for &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-emit-object&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/include/swift/Option/Options.td#L571-L572&quot;&gt;swift/include/swift/Option/Options.td&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;571&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; c : &lt;span class=&quot;f&quot;&gt;Flag&lt;/span&gt;&amp;lt;[&lt;span class=&quot;s&quot;&gt;&quot;-&quot;&lt;/span&gt;], &lt;span class=&quot;s&quot;&gt;&quot;c&quot;&lt;/span&gt;&amp;gt;, &lt;span class=&quot;f&quot;&gt;Alias&lt;/span&gt;&amp;lt;emit_object&amp;gt;,
&lt;span class=&quot;ln&quot;&gt;572&lt;/span&gt;    &lt;span class=&quot;f&quot;&gt;Flags&lt;/span&gt;&amp;lt;[&lt;span class=&quot;cn&quot;&gt;FrontendOption&lt;/span&gt;, &lt;span class=&quot;cn&quot;&gt;NoInteractiveOption&lt;/span&gt;]&amp;gt;, &lt;span class=&quot;cn&quot;&gt;ModeOpt&lt;/span&gt;;
&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;22-instantiating-the-astcontext-via-the-compilerinstancesetup-member-function&quot;&gt;2.2: Instantiating the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;ASTContext&lt;/span&gt;&lt;/code&gt; via the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;setup&lt;/span&gt;&lt;/code&gt; member function&lt;/h3&gt;

&lt;p&gt;After the arguments have been parsed, the &lt;code&gt;&lt;span class=&quot;f&quot;&gt;performFrontend&lt;/span&gt;&lt;/code&gt; function continues by finishing the initialization of the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;&lt;/code&gt;. To do so, it calls the member function &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;setup&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/FrontendTool/FrontendTool.cpp#L1304-L1542&quot;&gt;swift/lib/FrontendTool/FrontendTool.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;1304&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::performFrontend(&lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;const char&lt;/span&gt; *&amp;gt; Args,
&lt;span class=&quot;ln&quot;&gt;1305&lt;/span&gt;                             &lt;span class=&quot;k&quot;&gt;const char&lt;/span&gt; *Argv0, &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; *MainAddr,
&lt;span class=&quot;ln&quot;&gt;1306&lt;/span&gt;                             &lt;span class=&quot;cl&quot;&gt;FrontendObserver&lt;/span&gt; *observer) {
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;1348&lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;&amp;gt; Instance =
&lt;span class=&quot;ln&quot;&gt;1349&lt;/span&gt;      &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;make_unique&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;&amp;gt;();
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1371&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;CompilerInvocation&lt;/span&gt; Invocation;
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1379&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// Parse arguments.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1380&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (Invocation.&lt;span class=&quot;f&quot;&gt;parseArgs&lt;/span&gt;(Args, Instance-&amp;gt;&lt;span class=&quot;f&quot;&gt;getDiags&lt;/span&gt;(), workingDirectory)) {
&lt;span class=&quot;ln&quot;&gt;1381&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; finishDiagProcessing(&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;1382&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;1464&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (Instance-&amp;gt;setup(Invocation)) {
&lt;span class=&quot;ln&quot;&gt;1465&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; finishDiagProcessing(&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;1466&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1542&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;setup&lt;/span&gt;&lt;/code&gt; allocates a new &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;ASTContext&lt;/span&gt;&lt;/code&gt;. &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;ASTContext&lt;/span&gt;&lt;/code&gt; is responsible for creating, allocating memory for, and owning the nodes of the syntax tree.&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/Frontend/Frontend.cpp#L76-L106&quot;&gt;swift/lib/Frontend/Frontend.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt; 76&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::setup(&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;CompilerInvocation&lt;/span&gt; &amp;amp;Invok) {
&lt;span class=&quot;ln&quot;&gt; 77&lt;/span&gt;    &lt;span class=&quot;vi&quot;&gt;Invocation&lt;/span&gt; = Invok;
&lt;span class=&quot;ln&quot;&gt; ..&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt; 93&lt;/span&gt;    &lt;span class=&quot;vi&quot;&gt;Context&lt;/span&gt;.&lt;span class=&quot;f&quot;&gt;reset&lt;/span&gt;(&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;ASTContext&lt;/span&gt;(&lt;span class=&quot;vi&quot;&gt;Invocation&lt;/span&gt;.&lt;span class=&quot;f&quot;&gt;getLangOptions&lt;/span&gt;(),
&lt;span class=&quot;ln&quot;&gt; 94&lt;/span&gt;                                 &lt;span class=&quot;vi&quot;&gt;Invocation&lt;/span&gt;.&lt;span class=&quot;f&quot;&gt;getSearchPathOptions&lt;/span&gt;(), &lt;span class=&quot;vi&quot;&gt;SourceMgr&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt; 95&lt;/span&gt;                                 &lt;span class=&quot;vi&quot;&gt;Diagnostics&lt;/span&gt;));
&lt;span class=&quot;ln&quot;&gt; 96&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt; ..&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;106&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;There's no overstating the importance of the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;ASTContext&lt;/span&gt;&lt;/code&gt; class; if you do any work on the Swift compiler, you'll see this class used &lt;em&gt;everwhere&lt;/em&gt;.&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/include/swift/AST/ASTContext.h#L178-L190&quot;&gt;swift/include/swift/AST/ASTContext.h&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;178&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// ASTContext - This object creates and owns the AST objects.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;179&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// However, this class does more than just maintain context within an AST.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;180&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// It is the closest thing to thread-local or compile-local storage in this&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;181&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// code base. Why? SourceKit uses this code with multiple threads per Unix&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;182&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// process. Each thread processes a different source file. Each thread has its&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;183&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// own instance of ASTContext, and that instance persists for the duration of&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;184&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// the thread, throughout all phases of the compilation. (The name &quot;ASTContext&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;185&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// is a bit of a misnomer here.) Why not use thread-local storage? This code&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;186&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// may use DispatchQueues and pthread-style TLS won't work with code that uses&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;187&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// DispatchQueues. Summary: if you think you need a global or static variable,&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;188&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// you probably need to put it here instead.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;189&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;190&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; ASTContext {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;924&lt;/span&gt;  };
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;I'll write more on &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;ASTContext&lt;/span&gt;&lt;/code&gt; below. For now, let's &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; to &lt;code&gt;&lt;span class=&quot;f&quot;&gt;performFrontend&lt;/span&gt;&lt;/code&gt;. Having called &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;setup&lt;/span&gt;&lt;/code&gt;, it calls &lt;code&gt;&lt;span class=&quot;f&quot;&gt;performCompile&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/FrontendTool/FrontendTool.cpp#L1304-L1542&quot;&gt;swift/lib/FrontendTool/FrontendTool.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;1304&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::performFrontend(&lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;const char&lt;/span&gt; *&amp;gt; Args,
&lt;span class=&quot;ln&quot;&gt;1305&lt;/span&gt;                             &lt;span class=&quot;k&quot;&gt;const char&lt;/span&gt; *Argv0, &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; *MainAddr,
&lt;span class=&quot;ln&quot;&gt;1306&lt;/span&gt;                             &lt;span class=&quot;cl&quot;&gt;FrontendObserver&lt;/span&gt; *observer) {
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;1348&lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;&amp;gt; Instance =
&lt;span class=&quot;ln&quot;&gt;1349&lt;/span&gt;      &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;make_unique&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;&amp;gt;();
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1371&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;CompilerInvocation&lt;/span&gt; Invocation;
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1379&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// Parse arguments.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1380&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (Invocation.&lt;span class=&quot;f&quot;&gt;parseArgs&lt;/span&gt;(Args, Instance-&amp;gt;&lt;span class=&quot;f&quot;&gt;getDiags&lt;/span&gt;(), workingDirectory)) {
&lt;span class=&quot;ln&quot;&gt;1381&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; finishDiagProcessing(&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;1382&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;1464&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (Instance-&amp;gt;&lt;span class=&quot;f&quot;&gt;setup&lt;/span&gt;(Invocation)) {
&lt;span class=&quot;ln&quot;&gt;1465&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; finishDiagProcessing(&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;1466&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1508&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; ReturnValue = 0;
&lt;span class=&quot;ln&quot;&gt;1509&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; HadError =
&lt;span class=&quot;ln&quot;&gt;1510&lt;/span&gt;      &lt;span class=&quot;f&quot;&gt;performCompile&lt;/span&gt;(*Instance, Invocation, Args, ReturnValue, observer,
&lt;span class=&quot;ln&quot;&gt;1511&lt;/span&gt;                     StatsReporter.&lt;span class=&quot;f&quot;&gt;get&lt;/span&gt;());
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1542&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;stage-3-kicking-off-libswiftparse-and-libswiftsema&quot;&gt;Stage 3: Kicking off libswiftParse (and libswiftSema)&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;f&quot;&gt;performCompile&lt;/span&gt;&lt;/code&gt; function (also defined as part of the libswiftFrontendTool library) looks at the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;FrontendOptions&lt;/span&gt;::&lt;span class=&quot;vi&quot;&gt;RequestedAction&lt;/span&gt;&lt;/code&gt; (set in stage 2.1 above) and calls either &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;performParseOnly&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;performSema&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/FrontendTool/FrontendTool.cpp#L528-L857&quot;&gt;swift/lib/FrontendTool/FrontendTool.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;528&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; performCompile(&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt; &amp;amp;Instance,
&lt;span class=&quot;ln&quot;&gt;529&lt;/span&gt;                             &lt;span class=&quot;cl&quot;&gt;CompilerInvocation&lt;/span&gt; &amp;amp;Invocation,
&lt;span class=&quot;ln&quot;&gt;530&lt;/span&gt;                             &lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;const char&lt;/span&gt; *&amp;gt; Args,
&lt;span class=&quot;ln&quot;&gt;531&lt;/span&gt;                             &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; &amp;amp;ReturnValue,
&lt;span class=&quot;ln&quot;&gt;532&lt;/span&gt;                             &lt;span class=&quot;cl&quot;&gt;FrontendObserver&lt;/span&gt; *observer,
&lt;span class=&quot;ln&quot;&gt;533&lt;/span&gt;                             &lt;span class=&quot;cl&quot;&gt;UnifiedStatsReporter&lt;/span&gt; *Stats) {
&lt;span class=&quot;ln&quot;&gt;534&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;FrontendOptions&lt;/span&gt; opts = Invocation.&lt;span class=&quot;f&quot;&gt;getFrontendOptions&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;535&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;FrontendOptions&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;ActionType&lt;/span&gt; Action = opts.&lt;span class=&quot;vi&quot;&gt;RequestedAction&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;608&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (Action == &lt;span class=&quot;cl&quot;&gt;FrontendOptions&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;ActionType&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;Parse&lt;/span&gt; ||
&lt;span class=&quot;ln&quot;&gt;609&lt;/span&gt;        Action == &lt;span class=&quot;cl&quot;&gt;FrontendOptions&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;ActionType&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;DumpParse&lt;/span&gt; ||
&lt;span class=&quot;ln&quot;&gt;610&lt;/span&gt;        Action == &lt;span class=&quot;cl&quot;&gt;FrontendOptions&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;ActionType&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;EmitSyntax&lt;/span&gt; ||
&lt;span class=&quot;ln&quot;&gt;611&lt;/span&gt;        Action == &lt;span class=&quot;cl&quot;&gt;FrontendOptions&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;ActionType&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;DumpInterfaceHash&lt;/span&gt; ||
&lt;span class=&quot;ln&quot;&gt;612&lt;/span&gt;        Action == &lt;span class=&quot;cl&quot;&gt;FrontendOptions&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;ActionType&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;EmitImportedModules&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt;613&lt;/span&gt;      Instance.&lt;span class=&quot;f&quot;&gt;performParseOnly&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;614&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;615&lt;/span&gt;      Instance.&lt;span class=&quot;f&quot;&gt;performSema&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;857&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;As explained in stage 2.1 above, when I invoke &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-c&lt;/span&gt; hello.swift&lt;/code&gt;, it results in a request for &lt;code&gt;&lt;span class=&quot;t&quot;&gt;ActionType&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;EmitObject&lt;/span&gt;&lt;/code&gt;, so the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;performSema&lt;/span&gt;&lt;/code&gt; member function is called.&lt;/p&gt;

&lt;h2 id=&quot;stage-4-opening-a-swiftswiftmodule-bitstream-cursor-and-kicking-off-the-parsing-loop&quot;&gt;Stage 4: Opening a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Swift.swiftmodule&lt;/code&gt; bitstream cursor and kicking off the parsing loop&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;performSema&lt;/span&gt;&lt;/code&gt; member function loads the Swift standard library and then calls through to &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseAndCheckTypes&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/Frontend/Frontend.cpp#L369-L403&quot;&gt;swift/lib/Frontend/Frontend.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;369&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::performSema() {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;382&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (!&lt;span class=&quot;f&quot;&gt;loadStdlib&lt;/span&gt;())
&lt;span class=&quot;ln&quot;&gt;383&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;398&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;vi&quot;&gt;MainBufferID&lt;/span&gt; != &lt;span class=&quot;cn&quot;&gt;NO_SUCH_BUFFER&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt;399&lt;/span&gt;      &lt;span class=&quot;f&quot;&gt;addMainFileToModule&lt;/span&gt;(implicitImports);
&lt;span class=&quot;ln&quot;&gt;400&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;401&lt;/span&gt;    &lt;span class=&quot;f&quot;&gt;parseAndCheckTypes&lt;/span&gt;(implicitImports);
&lt;span class=&quot;ln&quot;&gt;402&lt;/span&gt;  }  
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;loadStdlib&lt;/span&gt;&lt;/code&gt; member function opens a cursor into the Swift standard library module file. Swift module files are Swift ASTs, serialized into a binary format called an LLVM bitstream. Later, when libswiftSema type-checks the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.swift&lt;/code&gt; file, it will lookup the &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;print&lt;/span&gt;&lt;/code&gt; function using the cursor created here.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;This article only covers parsing, not type-checking. I'll write more about the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;loadStdlib&lt;/span&gt;&lt;/code&gt; member function, as well as about Swift modules in general, in a future article, which I'll publish before writing about the Swift type-checker.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Next, &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;performSema&lt;/span&gt;&lt;/code&gt; calls &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;addFileToMainModule&lt;/span&gt;&lt;/code&gt;, which calls through to &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;createSourceFileForMainModule&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/Frontend/Frontend.cpp#L369-L403&quot;&gt;swift/lib/Frontend/Frontend.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;744&lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;SourceFile&lt;/span&gt; *&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::createSourceFileForMainModule(
&lt;span class=&quot;ln&quot;&gt;745&lt;/span&gt;      &lt;span class=&quot;cl&quot;&gt;SourceFileKind&lt;/span&gt; fileKind, &lt;span class=&quot;cl&quot;&gt;SourceFile&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;ImplicitModuleImportKind&lt;/span&gt; importKind,
&lt;span class=&quot;ln&quot;&gt;746&lt;/span&gt;      &lt;span class=&quot;cl&quot;&gt;Optional&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt;&amp;gt; bufferID) {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;749&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;SourceFile&lt;/span&gt; *inputFile = &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; (*&lt;span class=&quot;vi&quot;&gt;Context&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt;750&lt;/span&gt;        &lt;span class=&quot;cl&quot;&gt;SourceFile&lt;/span&gt;(*mainModule, fileKind, bufferID, importKind, keepSyntaxInfo);
&lt;span class=&quot;ln&quot;&gt;751&lt;/span&gt;    &lt;span class=&quot;vi&quot;&gt;MainModule&lt;/span&gt;-&amp;gt;&lt;span class=&quot;f&quot;&gt;addFile&lt;/span&gt;(*inputFile);
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;757&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; inputFile;
&lt;span class=&quot;ln&quot;&gt;758&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This creates the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;SourceFile&lt;/span&gt;&lt;/code&gt; node at the root of the AST that is printed out when invoking &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-dump-parse&lt;/span&gt; hello.swift&lt;/code&gt;. The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;SourceFile&lt;/span&gt;&lt;/code&gt; class derives from the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;DeclContext&lt;/span&gt;&lt;/code&gt; class, which is used in the AST code as a container for arbitrary declarations.&lt;/p&gt;

&lt;p&gt;Back in &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;performSema&lt;/span&gt;&lt;/code&gt;, a call to &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseAndCheckTypes&lt;/span&gt;&lt;/code&gt; is made, which then calls through to &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseAndTypeCheckMainFile&lt;/span&gt;&lt;/code&gt;. This calls the &lt;code&gt;&lt;span class=&quot;f&quot;&gt;parseIntoSourceFile&lt;/span&gt;&lt;/code&gt; function multiple times – as many times as that function continues to find Swift code at the top level of the file to parse, until it hits the end of the file.&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/FrontendTool/FrontendTool.cpp#L659-L713&quot;&gt;swift/lib/Frontend/Frontend.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;659&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::parseAndTypeCheckMainFile(
&lt;span class=&quot;ln&quot;&gt;660&lt;/span&gt;      &lt;span class=&quot;cl&quot;&gt;PersistentParserState&lt;/span&gt; &amp;amp;PersistentState,
&lt;span class=&quot;ln&quot;&gt;661&lt;/span&gt;      &lt;span class=&quot;cl&quot;&gt;DelayedParsingCallbacks&lt;/span&gt; *DelayedParseCB,
&lt;span class=&quot;ln&quot;&gt;662&lt;/span&gt;      &lt;span class=&quot;cl&quot;&gt;OptionSet&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;TypeCheckingFlags&lt;/span&gt;&amp;gt; TypeCheckOptions) {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;677&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; Done;
&lt;span class=&quot;ln&quot;&gt;678&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;683&lt;/span&gt;      &lt;span class=&quot;f&quot;&gt;parseIntoSourceFile&lt;/span&gt;(MainFile, MainFile.&lt;span class=&quot;f&quot;&gt;getBufferID&lt;/span&gt;().&lt;span class=&quot;f&quot;&gt;getValue&lt;/span&gt;(), &amp;amp;Done,
&lt;span class=&quot;ln&quot;&gt;684&lt;/span&gt;                          &lt;span class=&quot;vi&quot;&gt;TheSILModule&lt;/span&gt; ? &amp;amp;SILContext : &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;, &amp;amp;PersistentState,
&lt;span class=&quot;ln&quot;&gt;685&lt;/span&gt;                          DelayedParseCB);
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;695&lt;/span&gt;    } &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; (!Done);
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;713&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;f&quot;&gt;parseIntoSourceFile&lt;/span&gt;&lt;/code&gt; function is defined as part of a tiny compiler library named libswiftParseSIL (the function was &lt;a href=&quot;https://github.com/apple/swift/commit/b4759bc8e2d73303483878b28c6bdbd99cd0f665#diff-1c75bc124740fb7c04eba94c2b6980c0&quot;&gt;recently split out into its own library&lt;/a&gt; in order to break circular library dependencies in the compiler). It instantiates a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;&lt;/code&gt; and calls &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseTopLevel&lt;/span&gt;&lt;/code&gt;. Note that it sets the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Done&lt;/code&gt; pointer based on whether it's found the &lt;code&gt;&lt;span class=&quot;cn&quot;&gt;eof&lt;/span&gt;&lt;/code&gt; &quot;token&quot;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/ParseSIL/ParseSIL.cpp#L101-L120&quot;&gt;swift/lib/ParseSIL/ParseSIL.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;101&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseIntoSourceFile&lt;/span&gt;(&lt;span class=&quot;cl&quot;&gt;SourceFile&lt;/span&gt; &amp;amp;SF,
&lt;span class=&quot;ln&quot;&gt;102&lt;/span&gt;                                  &lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt; BufferID,
&lt;span class=&quot;ln&quot;&gt;103&lt;/span&gt;                                  &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; *Done,
&lt;span class=&quot;ln&quot;&gt;104&lt;/span&gt;                                  &lt;span class=&quot;cl&quot;&gt;SILParserState&lt;/span&gt; *SIL,
&lt;span class=&quot;ln&quot;&gt;105&lt;/span&gt;                                  &lt;span class=&quot;cl&quot;&gt;PersistentParserState&lt;/span&gt; *PersistentState,
&lt;span class=&quot;ln&quot;&gt;106&lt;/span&gt;                                  &lt;span class=&quot;cl&quot;&gt;DelayedParsingCallbacks&lt;/span&gt; *DelayedParseCB) {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;108&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt; P(BufferID, SF, SIL ? SIL-&amp;gt;&lt;span class=&quot;vi&quot;&gt;Impl&lt;/span&gt;.&lt;span class=&quot;f&quot;&gt;get&lt;/span&gt;() : &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;, PersistentState);
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;116&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; FoundSideEffects = P.&lt;span class=&quot;f&quot;&gt;parseTopLevel&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;117&lt;/span&gt;    *Done = P.&lt;span class=&quot;vi&quot;&gt;Tok&lt;/span&gt;.&lt;span class=&quot;f&quot;&gt;is&lt;/span&gt;(&lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;eof&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;118&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;119&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; FoundSideEffects;
&lt;span class=&quot;ln&quot;&gt;120&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;41-more-on-the-lexer-and-tokens&quot;&gt;4.1: More on the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;&lt;/code&gt; and tokens&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;&lt;/code&gt; initializer that's used in the &lt;code&gt;&lt;span class=&quot;f&quot;&gt;parseIntoSourceFile&lt;/span&gt;&lt;/code&gt; function creates a new &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;&lt;/code&gt; object:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/Parse/Parser.cpp#L101-L120&quot;&gt;swift/lib/Parse/Parser.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;329&lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::Parser(&lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt; BufferID, &lt;span class=&quot;cl&quot;&gt;SourceFile&lt;/span&gt; &amp;amp;SF, &lt;span class=&quot;cl&quot;&gt;SILParserTUStateBase&lt;/span&gt; *SIL,
&lt;span class=&quot;ln&quot;&gt;330&lt;/span&gt;                 &lt;span class=&quot;cl&quot;&gt;PersistentParserState&lt;/span&gt; *PersistentState)
&lt;span class=&quot;ln&quot;&gt;331&lt;/span&gt;      : &lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;(
&lt;span class=&quot;ln&quot;&gt;332&lt;/span&gt;            &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;&amp;gt;(&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;(
&lt;span class=&quot;ln&quot;&gt;333&lt;/span&gt;                SF.&lt;span class=&quot;f&quot;&gt;getASTContext&lt;/span&gt;().&lt;span class=&quot;vi&quot;&gt;LangOpts&lt;/span&gt;, SF.&lt;span class=&quot;f&quot;&gt;getASTContext&lt;/span&gt;().&lt;span class=&quot;vi&quot;&gt;SourceMgr&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;334&lt;/span&gt;                BufferID, &amp;amp;SF.&lt;span class=&quot;f&quot;&gt;getASTContext&lt;/span&gt;().&lt;span class=&quot;vi&quot;&gt;Diags&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;335&lt;/span&gt;                &lt;span class=&quot;c&quot;&gt;/*InSILMode=*/&lt;/span&gt;SIL != &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;336&lt;/span&gt;                SF.&lt;span class=&quot;f&quot;&gt;getASTContext&lt;/span&gt;().&lt;span class=&quot;vi&quot;&gt;LangOpts&lt;/span&gt;.&lt;span class=&quot;vi&quot;&gt;AttachCommentsToDecls&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;337&lt;/span&gt;                    ? &lt;span class=&quot;t&quot;&gt;CommentRetentionMode&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;AttachToNextToken&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;338&lt;/span&gt;                    : &lt;span class=&quot;t&quot;&gt;CommentRetentionMode&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;None&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;339&lt;/span&gt;                SF.&lt;span class=&quot;f&quot;&gt;shouldKeepSyntaxInfo&lt;/span&gt;()
&lt;span class=&quot;ln&quot;&gt;340&lt;/span&gt;                    ? &lt;span class=&quot;t&quot;&gt;TriviaRetentionMode&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;WithTrivia&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;341&lt;/span&gt;                    : &lt;span class=&quot;t&quot;&gt;TriviaRetentionMode&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;WithoutTrivia&lt;/span&gt;)),
&lt;span class=&quot;ln&quot;&gt;342&lt;/span&gt;            SF, SIL, PersistentState) {}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;A &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;&lt;/code&gt; is responsible for reading in the individual characters in a source file and forming logical chunks, called tokens.&lt;/p&gt;

&lt;p&gt;The Clang compiler, which compiles C, C++, and Objective-C source code, can print the tokens it lexes, using the &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-dump-tokens&lt;/span&gt;&lt;/code&gt; frontend option. For example, consider the following simple C program &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.c&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; main() {
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;;
}
&lt;/pre&gt;

&lt;p&gt;I can invoke the Clang frontend, &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;clang&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-cc1&lt;/span&gt;&lt;/code&gt;, to dump the tokens in this file (Clang has a driver and frontend system that is nearly identical to Swift's, except that Clang takes the argument &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-cc1&lt;/span&gt;&lt;/code&gt; instead of &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt;). &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;clang&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-cc1&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-dump-tokens&lt;/span&gt; hello.c&lt;/code&gt; outputs the following:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;cn&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'int'&lt;/span&gt;             &lt;span class=&quot;c&quot;&gt;Loc=&amp;lt;hello.c:1:1&amp;gt;  [StartOfLine]&lt;/span&gt;
&lt;span class=&quot;cn&quot;&gt;identifier&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'main'&lt;/span&gt;     &lt;span class=&quot;c&quot;&gt;Loc=&amp;lt;hello.c:1:5&amp;gt;  [LeadingSpace]&lt;/span&gt;
&lt;span class=&quot;cn&quot;&gt;l_paren&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'('&lt;/span&gt;           &lt;span class=&quot;c&quot;&gt;Loc=&amp;lt;hello.c:1:9&amp;gt;&lt;/span&gt;
&lt;span class=&quot;cn&quot;&gt;r_paren&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;')'&lt;/span&gt;           &lt;span class=&quot;c&quot;&gt;Loc=&amp;lt;hello.c:1:10&amp;gt;&lt;/span&gt;
&lt;span class=&quot;cn&quot;&gt;l_brace&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'{'&lt;/span&gt;           &lt;span class=&quot;c&quot;&gt;Loc=&amp;lt;hello.c:1:12&amp;gt; [LeadingSpace]&lt;/span&gt;
&lt;span class=&quot;cn&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'return'&lt;/span&gt;       &lt;span class=&quot;c&quot;&gt;Loc=&amp;lt;hello.c:2:3&amp;gt;  [StartOfLine] [LeadingSpace]&lt;/span&gt;
&lt;span class=&quot;cn&quot;&gt;numeric_constant&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'0'&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;Loc=&amp;lt;hello.c:2:10&amp;gt; [LeadingSpace]&lt;/span&gt;
&lt;span class=&quot;cn&quot;&gt;semi&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;';'&lt;/span&gt;              &lt;span class=&quot;c&quot;&gt;Loc=&amp;lt;hello.c:2:11&amp;gt;&lt;/span&gt;
&lt;span class=&quot;cn&quot;&gt;r_brace&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'}'&lt;/span&gt;           &lt;span class=&quot;c&quot;&gt;Loc=&amp;lt;hello.c:3:1&amp;gt;  [StartOfLine]&lt;/span&gt;
&lt;span class=&quot;cn&quot;&gt;eof&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;''&lt;/span&gt;                &lt;span class=&quot;c&quot;&gt;Loc=&amp;lt;hello.c:3:2&amp;gt;&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;The Swift compiler executable does not have an option to print the tokens in a file (although if any readers are interested in contributing, this would be a great feature to add!), but if it did, the tokens in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.swift&lt;/code&gt; would be output like this:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;cn&quot;&gt;identifier&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'print'&lt;/span&gt;                &lt;span class=&quot;c&quot;&gt;Loc=&amp;lt;hello.swift:3:1&amp;gt;  [StartOfLine]&lt;/span&gt;
&lt;span class=&quot;cn&quot;&gt;l_paren&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'('&lt;/span&gt;                       &lt;span class=&quot;c&quot;&gt;Loc=&amp;lt;hello.swift:3:6&amp;gt;&lt;/span&gt;
&lt;span class=&quot;cn&quot;&gt;string_literal&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'&quot;Hello, world!&quot;'&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;Loc=&amp;lt;hello.swift:3:7&amp;gt;&lt;/span&gt;
&lt;span class=&quot;cn&quot;&gt;r_paren&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;')'&lt;/span&gt;                       &lt;span class=&quot;c&quot;&gt;Loc=&amp;lt;hello.swift:3:22&amp;gt;&lt;/span&gt;
&lt;span class=&quot;cn&quot;&gt;eof&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;''&lt;/span&gt;                            &lt;span class=&quot;c&quot;&gt;Loc=&amp;lt;hello.swift:3:23&amp;gt;&lt;/span&gt;
&lt;/pre&gt;

&lt;blockquote&gt;
  &lt;p&gt;Note that the comment at the top of the file, &lt;code&gt;&lt;span class=&quot;c&quot;&gt;// hello.swift&lt;/span&gt;&lt;/code&gt;, and the empty line below that comment, are not represented as tokens. The Swift compiler can be invoked such that it creates tokens for comments and whitespace, but normally they are discarded entirely by the compiler.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The first column of the output above displays the token &quot;kind&quot;. Kinds of Swift tokens include &lt;code&gt;&lt;span class=&quot;cn&quot;&gt;identifier&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;cn&quot;&gt;l_paren&lt;/span&gt;&lt;/code&gt;, and &lt;code&gt;&lt;span class=&quot;cn&quot;&gt;eof&lt;/span&gt;&lt;/code&gt;. You can find a list of all the different Swift token kinds in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/include/swift/Syntax/TokenKinds.def&lt;/code&gt;. An enum of all the different token kinds is defined in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/include/swift/Syntax/TokenKinds.h&lt;/code&gt;, using a trick readers of my &lt;a href=&quot;/option-parsing-in-the-swift-compiler&quot;&gt;option parsing article&lt;/a&gt; should be familiar with: it defines the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;TOKEN&lt;/span&gt;&lt;/code&gt; macro, and then includes the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TokenKinds.def&lt;/code&gt; file, which contais a call to &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;TOKEN&lt;/span&gt;&lt;/code&gt; for each token kind.&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/include/swift/Syntax/TokenKinds.h#L21-L24&quot;&gt;swift/include/swift/Syntax/TokenKinds.h&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;21&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;enum class&lt;/span&gt; tok {
&lt;span class=&quot;ln&quot;&gt;22&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#define TOKEN(X) X,&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;23&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;swift/Syntax/TokenKinds.def&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;24&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;25&lt;/span&gt;    NUM_TOKENS
&lt;span class=&quot;ln&quot;&gt;26&lt;/span&gt;  };
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This creates an enum case for, for example, the &lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;/code&gt; keyword. In that case, the enum case is named &lt;code&gt;&lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;kw_if&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/include/swift/Syntax/TokenKinds.def#L39-L169&quot;&gt;swift/include/swift/Syntax/TokenKinds.def&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt; 39&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// KEYWORD(kw)&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 40&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;///   Expands by default for every Swift keyword and every SIL keyword, such as&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 41&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;///   'if', 'else', 'sil_global', etc. If you only want to use Swift keywords&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 42&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;///   see SWIFT_KEYWORD.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 43&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#ifndef&lt;/span&gt; KEYWORD
&lt;span class=&quot;ln&quot;&gt; 44&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#define&lt;/span&gt; KEYWORD(kw) &lt;span class=&quot;m&quot;&gt;TOKEN&lt;/span&gt;(&lt;span class=&quot;si&quot;&gt;kw_ ##&lt;/span&gt; kw)
&lt;span class=&quot;ln&quot;&gt; 45&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#endif&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 46&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt; 47&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// SWIFT_KEYWORD(kw)&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 48&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;///   Expands for every Swift keyword.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 49&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#ifndef&lt;/span&gt; SWIFT_KEYWORD
&lt;span class=&quot;ln&quot;&gt; 50&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#define&lt;/span&gt; SWIFT_KEYWORD(kw) &lt;span class=&quot;m&quot;&gt;KEYWORD&lt;/span&gt;(kw)
&lt;span class=&quot;ln&quot;&gt; 51&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#endif&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; ..&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt; 59&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// STMT_KEYWORD(kw)&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 60&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;///   Expands for every Swift keyword used in statement grammar.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 61&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#ifndef&lt;/span&gt; STMT_KEYWORD
&lt;span class=&quot;ln&quot;&gt; 62&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#define&lt;/span&gt; STMT_KEYWORD(kw) &lt;span class=&quot;m&quot;&gt;SWIFT_KEYWORD&lt;/span&gt;(kw)
&lt;span class=&quot;ln&quot;&gt; 63&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#endif&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;169&lt;/span&gt;  &lt;span class=&quot;m&quot;&gt;STMT_KEYWORD&lt;/span&gt;(if)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Token&lt;/span&gt;&lt;/code&gt; class stores information about a token: its kind and its text. It also defines member functions such as &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Token&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;is&lt;/span&gt;&lt;/code&gt;, so that other parts of the compiler can quickly check &quot;is this token an &lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;/code&gt; keyword?&quot;, by invoking &lt;code&gt;Tok.&lt;span class=&quot;f&quot;&gt;is&lt;/span&gt;(&lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;kw_if&lt;/span&gt;)&lt;/code&gt;. Or, to check simply that the token is a keyword, the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Token&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;isKeyword&lt;/span&gt;&lt;/code&gt; member function is implemented using a macro and an include:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/include/swift/Parse/Token.h#L33-L302&quot;&gt;swift/include/swift/Parse/Token.h&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt; 33&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; Token {
&lt;span class=&quot;ln&quot;&gt; 34&lt;/span&gt;    &lt;span class=&quot;d&quot;&gt;/// Kind - The actual flavor of token this is.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 35&lt;/span&gt;    &lt;span class=&quot;d&quot;&gt;///&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 36&lt;/span&gt;    &lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt; Kind;
&lt;span class=&quot;ln&quot;&gt; 51&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt; 52&lt;/span&gt;    &lt;span class=&quot;d&quot;&gt;/// Text - The actual string covered by the token in the source buffer.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 53&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt; Text;
&lt;span class=&quot;ln&quot;&gt; ..&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt; 61&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt; ..&lt;/span&gt;    
&lt;span class=&quot;ln&quot;&gt; 76&lt;/span&gt;    &lt;span class=&quot;d&quot;&gt;/// is/isNot - Predicates to check if this token is a specific kind, as in&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 77&lt;/span&gt;    &lt;span class=&quot;d&quot;&gt;/// &quot;if (Tok.is(tok::l_brace)) {...}&quot;.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 78&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; is(&lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt; K) &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; { &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;Kind&lt;/span&gt; == K; }
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;214&lt;/span&gt;    &lt;span class=&quot;d&quot;&gt;/// True if the token is any keyword.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;215&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; isKeyword() &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; {
&lt;span class=&quot;ln&quot;&gt;216&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; (&lt;span class=&quot;vi&quot;&gt;Kind&lt;/span&gt;) {
&lt;span class=&quot;ln&quot;&gt;217&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#define KEYWORD(X) case tok::kw_&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;##X&lt;/span&gt;&lt;span class=&quot;ms&quot;&gt;: return true;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;218&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;swift/Syntax/TokenKinds.def&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;219&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;220&lt;/span&gt;      }
&lt;span class=&quot;ln&quot;&gt;221&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;302&lt;/span&gt;  };
&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;42-priming-the-lexer-to-form-a-token-for-the-identifier-print&quot;&gt;4.2: Priming the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;&lt;/code&gt; to form a token for the identifier &lt;code&gt;&lt;span class=&quot;s&quot;&gt;&quot;print&quot;&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Normally the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;&lt;/code&gt; prompts the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;&lt;/code&gt; to lex the next token in a file. The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;&lt;/code&gt; also, when it's initialized, lexes the first token in the file by calling the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;primeLexer&lt;/span&gt;&lt;/code&gt; member function.&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/include/swift/Parse/Lexer.h#L64-L523&quot;&gt;swift/include/swift/Parse/Lexer.h&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt; 64&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; Lexer {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;169&lt;/span&gt;    Lexer(&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;LangOptions&lt;/span&gt; &amp;amp;Options,
&lt;span class=&quot;ln&quot;&gt;170&lt;/span&gt;          &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;SourceManager&lt;/span&gt; &amp;amp;SourceMgr, &lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt; BufferID,
&lt;span class=&quot;ln&quot;&gt;171&lt;/span&gt;          &lt;span class=&quot;cl&quot;&gt;DiagnosticEngine&lt;/span&gt; *Diags, &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; InSILMode,
&lt;span class=&quot;ln&quot;&gt;172&lt;/span&gt;          &lt;span class=&quot;t&quot;&gt;CommentRetentionMode&lt;/span&gt; RetainComments = &lt;span class=&quot;t&quot;&gt;CommentRetentionMode&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;None&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;173&lt;/span&gt;          &lt;span class=&quot;t&quot;&gt;TriviaRetentionMode&lt;/span&gt; TriviaRetention = &lt;span class=&quot;t&quot;&gt;TriviaRetentionMode&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;WithoutTrivia&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt;174&lt;/span&gt;        : &lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;(Options, SourceMgr, Diags, BufferID, InSILMode, RetainComments,
&lt;span class=&quot;ln&quot;&gt;175&lt;/span&gt;                TriviaRetention) {
&lt;span class=&quot;ln&quot;&gt;176&lt;/span&gt;      &lt;span class=&quot;f&quot;&gt;primeLexer&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;177&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;523&lt;/span&gt;  };
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;primeLexer&lt;/span&gt;&lt;/code&gt; calls through to &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;lexImpl&lt;/span&gt;&lt;/code&gt;. This member function implements the core of the lexing functionality in the Swift compiler; it is the method that, based on the first character in a series, determines whether to lex an identifier, a number literal, an operator, or some other token.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;&lt;/code&gt; keeps a pointer to the character it's currently lexing using a member &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;::&lt;span class=&quot;vi&quot;&gt;CurPtr&lt;/span&gt;&lt;/code&gt;. &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;lexImpl&lt;/span&gt;&lt;/code&gt; moves the pointer to the next character and then enters a &lt;code&gt;&lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt;&lt;/code&gt; statement based on the character's value. Here are the &lt;code&gt;&lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt;&lt;/code&gt; statement cases that are relevant to my source file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.swift&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/Parse/Lexer.cpp#L64-L523&quot;&gt;swift/lib/Parse/Lexer.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;2041&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;::lexImpl() {
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2068&lt;/span&gt;  Restart:
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2074&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; ((&lt;span class=&quot;k&quot;&gt;signed char&lt;/span&gt;)*&lt;span class=&quot;vi&quot;&gt;CurPtr&lt;/span&gt;++) {
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2150&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;' '&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;2151&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'\t&lt;/span&gt;':
&lt;span class=&quot;ln&quot;&gt;2152&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'\f&lt;/span&gt;':
&lt;span class=&quot;ln&quot;&gt;2153&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'\v&lt;/span&gt;':
&lt;span class=&quot;ln&quot;&gt;2154&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; Restart;  &lt;span class=&quot;c&quot;&gt;// Skip whitespace.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;2193&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'('&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;f&quot;&gt;formToken&lt;/span&gt;(&lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;l_paren&lt;/span&gt;, TokStart);
&lt;span class=&quot;ln&quot;&gt;2194&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'}'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;f&quot;&gt;formToken&lt;/span&gt;(&lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;r_brace&lt;/span&gt;, TokStart);
&lt;span class=&quot;ln&quot;&gt;2195&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;']'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;f&quot;&gt;formToken&lt;/span&gt;(&lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;r_square&lt;/span&gt;, TokStart);
&lt;span class=&quot;ln&quot;&gt;2196&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;')'&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;2197&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;f&quot;&gt;formToken&lt;/span&gt;(&lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;r_paren&lt;/span&gt;, TokStart);
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;2209&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'/'&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;2210&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;vi&quot;&gt;CurPtr&lt;/span&gt;[&lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;] == &lt;span class=&quot;ch&quot;&gt;'/'&lt;/span&gt;) {  &lt;span class=&quot;c&quot;&gt;// &quot;//&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2211&lt;/span&gt;        &lt;span class=&quot;f&quot;&gt;skipSlashSlashComment&lt;/span&gt;(&lt;span class=&quot;c&quot;&gt;/*EatNewline=*/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2215&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; Restart;
&lt;span class=&quot;ln&quot;&gt;2216&lt;/span&gt;      }
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2264&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'A'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'B'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'C'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'D'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'E'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'F'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'G'&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;2265&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'H'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'I'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'J'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'K'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'L'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'M'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'N'&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;2266&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'O'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'P'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'Q'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'R'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'S'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'T'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'U'&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;2267&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'V'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'W'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'X'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'Y'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'Z'&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;2268&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'a'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'b'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'c'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'d'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'e'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'f'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'g'&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;2269&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'h'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'i'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'j'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'k'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'l'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'m'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'n'&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;2270&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'o'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'p'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'q'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'r'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'s'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'t'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'u'&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;2271&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'v'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'w'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'x'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'y'&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'z'&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;2272&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'_'&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;2273&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;f&quot;&gt;lexIdentifier&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2282&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'&quot;'&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;2283&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;ch&quot;&gt;'\'&lt;/span&gt;':
&lt;span class=&quot;ln&quot;&gt;2284&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;f&quot;&gt;lexStringLiteral&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2289&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;When the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;&lt;/code&gt; is first initialized in the frontend when parsing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.swift&lt;/code&gt;, the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;primeLexer&lt;/span&gt;&lt;/code&gt; member function is called, which calls &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;lexImpl&lt;/span&gt;&lt;/code&gt;. This skips the &lt;code&gt;&lt;span class=&quot;c&quot;&gt;//&lt;/span&gt;&lt;/code&gt; comments and whitespace at the beginning of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.swift&lt;/code&gt;, until it reaches the &lt;code&gt;&lt;span class=&quot;ch&quot;&gt;'p'&lt;/span&gt;&lt;/code&gt; character in &lt;code&gt;&lt;span class=&quot;s&quot;&gt;&quot;print&quot;&lt;/span&gt;&lt;/code&gt;, and so it enters the case in which the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;lexIdentifier&lt;/span&gt;&lt;/code&gt; member function is called. This function consumes characters as long as they are valid identifier characters, and then creates a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Token&lt;/span&gt;&lt;/code&gt; with a token kind of either &lt;code&gt;&lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;identifier&lt;/span&gt;&lt;/code&gt;, or a keyword token kind like &lt;code&gt;&lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;kw_if&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/Parse/Lexer.cpp#L591-L604&quot;&gt;swift/lib/Parse/Lexer.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;591&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// lexIdentifier - Match [a-zA-Z_][a-zA-Z_$0-9]*&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;592&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;::lexIdentifier() {
&lt;span class=&quot;ln&quot;&gt;593&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;const char&lt;/span&gt; *TokStart = &lt;span class=&quot;vi&quot;&gt;CurPtr&lt;/span&gt;-&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;594&lt;/span&gt;    &lt;span class=&quot;vi&quot;&gt;CurPtr&lt;/span&gt; = TokStart;
&lt;span class=&quot;ln&quot;&gt;595&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; didStart = &lt;span class=&quot;f&quot;&gt;advanceIfValidStartOfIdentifier&lt;/span&gt;(&lt;span class=&quot;vi&quot;&gt;CurPtr&lt;/span&gt;, &lt;span class=&quot;vi&quot;&gt;BufferEnd&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;599&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// Lex [a-zA-Z_$0-9[[:XID_Continue:]]]*&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;600&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; (&lt;span class=&quot;f&quot;&gt;advanceIfValidContinuationOfIdentifier&lt;/span&gt;(&lt;span class=&quot;vi&quot;&gt;CurPtr&lt;/span&gt;, &lt;span class=&quot;vi&quot;&gt;BufferEnd&lt;/span&gt;));
&lt;span class=&quot;ln&quot;&gt;601&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;602&lt;/span&gt;    &lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt; Kind = &lt;span class=&quot;f&quot;&gt;kindOfIdentifier&lt;/span&gt;(&lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt;(TokStart, &lt;span class=&quot;vi&quot;&gt;CurPtr&lt;/span&gt;-TokStart), &lt;span class=&quot;vi&quot;&gt;InSILMode&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;603&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;f&quot;&gt;formToken&lt;/span&gt;(Kind, TokStart);
&lt;span class=&quot;ln&quot;&gt;604&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;In the case of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.swift&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;lexIdentifier&lt;/span&gt;&lt;/code&gt; would advance, from &lt;code&gt;&lt;span class=&quot;ch&quot;&gt;'p'&lt;/span&gt;&lt;/code&gt;, and end at &lt;code&gt;&lt;span class=&quot;s&quot;&gt;&quot;print&quot;&lt;/span&gt;&lt;/code&gt;, stopping when it saw the &lt;code&gt;&lt;span class=&quot;ch&quot;&gt;'('&lt;/span&gt;&lt;/code&gt; character immediately after &lt;code&gt;&lt;span class=&quot;s&quot;&gt;&quot;print&quot;&lt;/span&gt;&lt;/code&gt;. It would then call &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;kindOfIdentifier&lt;/span&gt;&lt;/code&gt;, to determine whether &lt;code&gt;&lt;span class=&quot;s&quot;&gt;&quot;print&quot;&lt;/span&gt;&lt;/code&gt; was a keyword. The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;kindOfIdentifier&lt;/span&gt;&lt;/code&gt; member function uses, sure enough, the macro and include trick:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/Parse/Lexer.cpp#L570-L589&quot;&gt;swift/lib/Parse/Lexer.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;570&lt;/span&gt;  &lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;::kindOfIdentifier(&lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt; Str, &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; InSILMode) {
&lt;span class=&quot;ln&quot;&gt;571&lt;/span&gt;    &lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt; Kind = &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;StringSwitch&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;&amp;gt;(Str)
&lt;span class=&quot;ln&quot;&gt;572&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#define KEYWORD(kw) \&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;573&lt;/span&gt;      &lt;span class=&quot;ms&quot;&gt;.Case(#kw, tok::kw_&lt;span class=&quot;si&quot;&gt;##kw&lt;/span&gt;)&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;574&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;swift/Syntax/TokenKinds.def&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;575&lt;/span&gt;      .&lt;span class=&quot;f&quot;&gt;Default&lt;/span&gt;(&lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;identifier&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;588&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; Kind;
&lt;span class=&quot;ln&quot;&gt;589&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;So, as soon as the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;&lt;/code&gt; is initialized, the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;primeLexer&lt;/span&gt;&lt;/code&gt; member function results in the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;::&lt;span class=&quot;vi&quot;&gt;NextToken&lt;/span&gt;&lt;/code&gt; member being set to a token with kind &lt;code&gt;&lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;identifier&lt;/span&gt;&lt;/code&gt;, and with the text &lt;code&gt;&lt;span class=&quot;s&quot;&gt;&quot;print&quot;&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The next time the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;&lt;/code&gt; requests a token from its &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;&lt;/code&gt;, the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;&lt;/code&gt; will immediately &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; to it this &lt;code&gt;&lt;span class=&quot;s&quot;&gt;&quot;print&quot;&lt;/span&gt;&lt;/code&gt; token and, if it is not at the end of the file, it'll prepare the next &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;::&lt;span class=&quot;vi&quot;&gt;NextToken&lt;/span&gt;&lt;/code&gt; in the same way, by calling &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;lexImpl&lt;/span&gt;&lt;/code&gt; again.&lt;/p&gt;

&lt;h2 id=&quot;stage-5-the-lex--parse-loop&quot;&gt;Stage 5: The lex &amp;amp; parse loop&lt;/h2&gt;

&lt;p&gt;To recap: the libswiftFrontendTool function &lt;code&gt;&lt;span class=&quot;f&quot;&gt;performFrontend&lt;/span&gt;&lt;/code&gt; parsed the arguments passed into our &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt; invocation and determined it would call the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;performSema&lt;/span&gt;&lt;/code&gt; member function. That eventually called the &lt;code&gt;&lt;span class=&quot;f&quot;&gt;parseIntoSourceFile&lt;/span&gt;&lt;/code&gt; function, which instantiated a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;&lt;/code&gt; and its internal &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;&lt;/code&gt; (which resulted in &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;&lt;/code&gt; being &quot;primed&quot; with the &lt;code&gt;&lt;span class=&quot;s&quot;&gt;&quot;print&quot;&lt;/span&gt;&lt;/code&gt; token). Finally, &lt;code&gt;&lt;span class=&quot;f&quot;&gt;parseIntoSourceFile&lt;/span&gt;&lt;/code&gt; calls &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseTopLevel&lt;/span&gt;&lt;/code&gt;, which kicks off the lexing and parsing loop that results in the full syntax tree being constructed for our file.&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/Parse/ParseDecl.cpp#L570-L589&quot;&gt;swift/lib/Parse/ParseDecl.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;189&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::parseTopLevel() {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;194&lt;/span&gt;      &lt;span class=&quot;f&quot;&gt;consumeTokenWithoutFeedingReceiver&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;234&lt;/span&gt;      &lt;span class=&quot;f&quot;&gt;parseBraceItems&lt;/span&gt;(Items,
&lt;span class=&quot;ln&quot;&gt;235&lt;/span&gt;                      &lt;span class=&quot;f&quot;&gt;allowTopLevelCode&lt;/span&gt;() ? &lt;span class=&quot;t&quot;&gt;BraceItemListKind&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;TopLevelCode&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;236&lt;/span&gt;                                          : &lt;span class=&quot;t&quot;&gt;BraceItemListKind&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;TopLevelLibrary&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;281&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseTopLevel&lt;/span&gt;&lt;/code&gt; member function first requests the next token from the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;&lt;/code&gt;, by calling &lt;code&gt;&lt;span class=&quot;f&quot;&gt;consumeTokenWithoutFeedingReceiver&lt;/span&gt;&lt;/code&gt;. This sets member &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;Tok&lt;/span&gt;&lt;/code&gt; to the token for &lt;code&gt;&lt;span class=&quot;s&quot;&gt;&quot;print&quot;&lt;/span&gt;&lt;/code&gt;, and has the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;&lt;/code&gt; ready the next token, which is an &lt;code&gt;&lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;l_paren&lt;/span&gt;&lt;/code&gt; &lt;code&gt;&lt;span class=&quot;ch&quot;&gt;'('&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It then calls &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseBraceItems&lt;/span&gt;&lt;/code&gt;. &quot;Brace items&quot; here refers to a sequence of expressions or statements that are contained with a pair of braces &lt;code&gt;{ ... }&lt;/code&gt;. Our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.swift&lt;/code&gt; file does not contain braces, but when parsing top-level code in a file the Swift parser pretends that there are a set of braces wrapping that top level code.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseBraceItems&lt;/span&gt;&lt;/code&gt; enters a while loop that continues to parse the file until it reaches the file's end. Within that loop, it creates AST nodes for expressions or statements that it finds, by calling &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseExprOrStmt&lt;/span&gt;&lt;/code&gt;. If it finds an expression or statement, it wraps it in a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;BraceStmt&lt;/span&gt;&lt;/code&gt; node:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/Parse/ParseStmt.cpp#L226-L427&quot;&gt;swift/lib/Parse/ParseStmt.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;226&lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;ParserStatus&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::parseBraceItems(&lt;span class=&quot;cl&quot;&gt;SmallVectorImpl&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;ASTNode&lt;/span&gt;&amp;gt; &amp;amp;Entries,
&lt;span class=&quot;ln&quot;&gt;227&lt;/span&gt;                                       &lt;span class=&quot;t&quot;&gt;BraceItemListKind&lt;/span&gt; Kind,
&lt;span class=&quot;ln&quot;&gt;228&lt;/span&gt;                                       &lt;span class=&quot;t&quot;&gt;BraceItemListKind&lt;/span&gt; ConditionalBlockKind) {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;250&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; ((IsTopLevel || &lt;span class=&quot;vi&quot;&gt;Tok&lt;/span&gt;.&lt;span class=&quot;f&quot;&gt;isNot&lt;/span&gt;(&lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;r_brace&lt;/span&gt;)) &amp;amp;&amp;amp;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;254&lt;/span&gt;           &lt;span class=&quot;vi&quot;&gt;Tok&lt;/span&gt;.&lt;span class=&quot;f&quot;&gt;isNot&lt;/span&gt;(&lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;eof&lt;/span&gt;) &amp;amp;&amp;amp;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;263&lt;/span&gt;            !&lt;span class=&quot;f&quot;&gt;isTerminatorForBraceItemListKind&lt;/span&gt;(Kind, Entries))) {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;345&lt;/span&gt;        &lt;span class=&quot;c&quot;&gt;// If this is a statement or expression at the top level of the module,&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;346&lt;/span&gt;        &lt;span class=&quot;c&quot;&gt;// Parse it as a child of a TopLevelCodeDecl.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;347&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; *TLCD = &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; (&lt;span class=&quot;vi&quot;&gt;Context&lt;/span&gt;) &lt;span class=&quot;cl&quot;&gt;TopLevelCodeDecl&lt;/span&gt;(&lt;span class=&quot;vi&quot;&gt;CurDeclContext&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;357&lt;/span&gt;        &lt;span class=&quot;cl&quot;&gt;ParserStatus&lt;/span&gt; Status = &lt;span class=&quot;f&quot;&gt;parseExprOrStmt&lt;/span&gt;(Result);
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;373&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (!Result.&lt;span class=&quot;f&quot;&gt;isNull&lt;/span&gt;()) {
&lt;span class=&quot;ln&quot;&gt;374&lt;/span&gt;          &lt;span class=&quot;c&quot;&gt;// NOTE: this is a 'virtual' brace statement which does not have&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;375&lt;/span&gt;          &lt;span class=&quot;c&quot;&gt;//       explicit '{' or '}', so the start and end locations should be&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;376&lt;/span&gt;          &lt;span class=&quot;c&quot;&gt;//       the same as those of the result node&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;377&lt;/span&gt;          &lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; Brace = &lt;span class=&quot;cl&quot;&gt;BraceStmt&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;create&lt;/span&gt;(&lt;span class=&quot;vi&quot;&gt;Context&lt;/span&gt;, Result.&lt;span class=&quot;f&quot;&gt;getStartLoc&lt;/span&gt;(),
&lt;span class=&quot;ln&quot;&gt;378&lt;/span&gt;                                         Result, Result.&lt;span class=&quot;f&quot;&gt;getEndLoc&lt;/span&gt;());
&lt;span class=&quot;ln&quot;&gt;379&lt;/span&gt;          TLCD-&amp;gt;&lt;span class=&quot;f&quot;&gt;setBody&lt;/span&gt;(Brace);
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;381&lt;/span&gt;        }
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;424&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;427&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;With the creation of a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;TopLevelCodeDecl&lt;/span&gt;&lt;/code&gt; and a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;BraceStmt&lt;/span&gt;&lt;/code&gt; to wrap the result of the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseExprOrStmt&lt;/span&gt;&lt;/code&gt; member function call, the AST for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.swift&lt;/code&gt; would look like this:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;astp&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;aststmt&quot;&gt;source_file&lt;/span&gt;
  &lt;span class=&quot;astp&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;astdecl&quot;&gt;top_level_code_decl&lt;/span&gt;
    &lt;span class=&quot;astp&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;aststmt&quot;&gt;brace_stmt&lt;/span&gt;
      &lt;span class=&quot;asto&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;astp&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;astp&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;astp&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;The actual expression &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;print&lt;/span&gt;(&lt;span class=&quot;s&quot;&gt;&quot;Hello, world!&quot;&lt;/span&gt;)&lt;/code&gt; will be parsed as part of the call to &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseExprOrStmt&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;51-a-quick-note-on-custom-allocators-in-c&quot;&gt;5.1: A quick note on custom allocators in C++&lt;/h3&gt;

&lt;p&gt;Before getting into the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseExprOrStmt&lt;/span&gt;&lt;/code&gt; member function, take a closer look at the instantiation of &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;TopLevelCodeDecl&lt;/span&gt;&lt;/code&gt;, which uses an interesting C++ feature:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/Parse/ParseStmt.cpp#L226-L427&quot;&gt;swift/lib/Parse/ParseStmt.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;226&lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;ParserStatus&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::parseBraceItems(&lt;span class=&quot;cl&quot;&gt;SmallVectorImpl&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;ASTNode&lt;/span&gt;&amp;gt; &amp;amp;Entries,
&lt;span class=&quot;ln&quot;&gt;227&lt;/span&gt;                                       &lt;span class=&quot;t&quot;&gt;BraceItemListKind&lt;/span&gt; Kind,
&lt;span class=&quot;ln&quot;&gt;228&lt;/span&gt;                                       &lt;span class=&quot;t&quot;&gt;BraceItemListKind&lt;/span&gt; ConditionalBlockKind) {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;347&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; *TLCD = &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; (&lt;span class=&quot;vi&quot;&gt;Context&lt;/span&gt;) &lt;span class=&quot;cl&quot;&gt;TopLevelCodeDecl&lt;/span&gt;(&lt;span class=&quot;vi&quot;&gt;CurDeclContext&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;427&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;I didn't have any experience writing C++ before I began working on Swift and Clang, so this call to &lt;code&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; (&lt;span class=&quot;vi&quot;&gt;Context&lt;/span&gt;) &lt;span class=&quot;cl&quot;&gt;TopLevelCodeDecl&lt;/span&gt;(&lt;span class=&quot;c&quot;&gt;...&lt;/span&gt;)&lt;/code&gt; confused me. I was familiar with expressions such as &lt;code&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Foo&lt;/span&gt;()&lt;/code&gt;, which allocate memory for an instance of &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Foo&lt;/span&gt;&lt;/code&gt;. But the expression &lt;code&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; (&lt;span class=&quot;vi&quot;&gt;Context&lt;/span&gt;) &lt;span class=&quot;cl&quot;&gt;TopLevelCodeDecl&lt;/span&gt;(&lt;span class=&quot;c&quot;&gt;...&lt;/span&gt;)&lt;/code&gt; seemed to have an extra element: what is &lt;code&gt;(&lt;span class=&quot;vi&quot;&gt;Context&lt;/span&gt;)&lt;/code&gt; here?&lt;/p&gt;

&lt;p&gt;It turns out that C++ allows you to provide overrides of the &lt;code&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;/code&gt; operator for specific classes, and those overrides can take additional parameters. The &lt;code&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;/code&gt; operator's first argument must be a &lt;code&gt;&lt;span class=&quot;ts&quot;&gt;size_t&lt;/span&gt;&lt;/code&gt; that indicates how many bytes should be allocated, but beyond that you can define an arbitrary list of parameters. Here, &lt;code&gt;&lt;span class=&quot;vi&quot;&gt;Context&lt;/span&gt;&lt;/code&gt; is an argument being passed to &lt;code&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Swift's &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Decl&lt;/span&gt;&lt;/code&gt; class not only defines a custom &lt;code&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;/code&gt; operator that takes an &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;ASTContext&lt;/span&gt;&lt;/code&gt; argument, it also deletes the default &lt;code&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;/code&gt; operator implementation:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/include/swift/AST/Decl.h#L235-L878&quot;&gt;swift/include/swift/AST/Decl.h&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;235&lt;/span&gt;  &lt;span class=&quot;d&quot;&gt;/// Decl - Base class for all declarations in Swift.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;236&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;alignas&lt;/span&gt;(&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt; &amp;lt;&amp;lt; DeclAlignInBits) Decl {
&lt;span class=&quot;ln&quot;&gt;237&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;protected&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;865&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;866&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// Make vanilla new/delete illegal for Decls.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;867&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; *&lt;span class=&quot;k&quot;&gt;operator&lt;/span&gt; new(&lt;span class=&quot;ts&quot;&gt;size_t&lt;/span&gt; Bytes) = &lt;span class=&quot;k&quot;&gt;delete&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;870&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// Only allow allocation of Decls using the allocator in ASTContext&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;871&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// or by doing a placement new.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;872&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; *&lt;span class=&quot;k&quot;&gt;operator&lt;/span&gt; new(&lt;span class=&quot;ts&quot;&gt;size_t&lt;/span&gt; Bytes, &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;ASTContext&lt;/span&gt; &amp;amp;C,
&lt;span class=&quot;ln&quot;&gt;873&lt;/span&gt;                       &lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt; Alignment = &lt;span class=&quot;k&quot;&gt;alignof&lt;/span&gt;(&lt;span class=&quot;cl&quot;&gt;Decl&lt;/span&gt;));
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;878&lt;/span&gt;  };
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This means that you &lt;em&gt;cannot&lt;/em&gt; allocate memory for a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Decl&lt;/span&gt;&lt;/code&gt; by calling &lt;code&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Decl&lt;/span&gt;()&lt;/code&gt; – you must call &lt;code&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; (&lt;span class=&quot;vi&quot;&gt;Context&lt;/span&gt;) &lt;span class=&quot;cl&quot;&gt;Decl&lt;/span&gt;()&lt;/code&gt;. Doing so calls the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;ASTContext&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;Allocate&lt;/span&gt;&lt;/code&gt; member function:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/AST/Decl.cpp#L97-L101&quot;&gt;swift/lib/AST/Decl.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;97&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// Only allow allocation of Decls using the allocator in ASTContext.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;98&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; *Decl::&lt;span class=&quot;k&quot;&gt;operator&lt;/span&gt; new(&lt;span class=&quot;ts&quot;&gt;size_t&lt;/span&gt; Bytes, &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;ASTContext&lt;/span&gt; &amp;amp;C,
&lt;span class=&quot;ln&quot;&gt;99&lt;/span&gt;                           &lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt; Alignment) {
&lt;span class=&quot;ln&quot;&gt;100&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; C.&lt;span class=&quot;f&quot;&gt;Allocate&lt;/span&gt;(Bytes, Alignment);
&lt;span class=&quot;ln&quot;&gt;101&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;You may also have noticed this syntax earlier in this article, when &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;performSema&lt;/span&gt;&lt;/code&gt; called through to a function that created the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;SourceFile&lt;/span&gt;&lt;/code&gt; root node in the AST. The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;SourceFile&lt;/span&gt;&lt;/code&gt; class inherits from &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;DeclContext&lt;/span&gt;&lt;/code&gt;, which declares its own overload of the &lt;code&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;/code&gt; operator:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/include/swift/AST/DeclContext.h#L554-L556&quot;&gt;swift/include/swift/AST/DeclContext.h&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;186&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;alignas&lt;/span&gt;(&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt; &amp;lt;&amp;lt; DeclContextAlignInBits) DeclContext {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;554&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// Only allow allocation of DeclContext using the allocator in ASTContext.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;555&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; *&lt;span class=&quot;k&quot;&gt;operator&lt;/span&gt; new(&lt;span class=&quot;ts&quot;&gt;size_t&lt;/span&gt; Bytes, &lt;span class=&quot;cl&quot;&gt;ASTContext&lt;/span&gt; &amp;amp;C,
&lt;span class=&quot;ln&quot;&gt;556&lt;/span&gt;                       &lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt; Alignment = &lt;span class=&quot;k&quot;&gt;alignof&lt;/span&gt;(&lt;span class=&quot;cl&quot;&gt;DeclContext&lt;/span&gt;));
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;560&lt;/span&gt;  };
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This also calls through to the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;ASTContext&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;Allocate&lt;/span&gt;&lt;/code&gt; function:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/AST/DeclContext.cpp#L38-L42&quot;&gt;swift/lib/AST/DeclContext.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;38&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;// Only allow allocation of DeclContext using the allocator in ASTContext.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;39&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; *DeclContext::&lt;span class=&quot;k&quot;&gt;operator&lt;/span&gt; new(&lt;span class=&quot;ts&quot;&gt;size_t&lt;/span&gt; Bytes, &lt;span class=&quot;cl&quot;&gt;ASTContext&lt;/span&gt; &amp;amp;C,
&lt;span class=&quot;ln&quot;&gt;40&lt;/span&gt;                                  &lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt; Alignment) {
&lt;span class=&quot;ln&quot;&gt;41&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; C.&lt;span class=&quot;f&quot;&gt;Allocate&lt;/span&gt;(Bytes, Alignment);
&lt;span class=&quot;ln&quot;&gt;42&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;ASTContext&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;Allocate&lt;/span&gt;&lt;/code&gt; member function is too interesting to explain in detail here. I'll write about it in a future article.&lt;/p&gt;

&lt;h2 id=&quot;52-parsing-the-print-expression&quot;&gt;5.2: Parsing the &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;print&lt;/span&gt;(...)&lt;/code&gt; expression&lt;/h2&gt;

&lt;p&gt;To parse the expression or statement at the top level of my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.swift&lt;/code&gt; file, the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;&lt;/code&gt; must first determine whether it's an expression or a statement. It makes use of a helper function &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;isStartOfStmt&lt;/span&gt;&lt;/code&gt; to do so. For the most part, this just checks for keywords that clearly demarcate a statement:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/Parse/ParseStmt.cpp#L37-L86&quot;&gt;swift/lib/Parse/ParseStmt.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;37&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::isStartOfStmt() {
&lt;span class=&quot;ln&quot;&gt;38&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; (&lt;span class=&quot;vi&quot;&gt;Tok&lt;/span&gt;.&lt;span class=&quot;f&quot;&gt;getKind&lt;/span&gt;()) {
&lt;span class=&quot;ln&quot;&gt;39&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt;: &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;40&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;kw_return&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;41&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;kw_throw&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;42&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;kw_defer&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;43&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;kw_if&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;44&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;kw_guard&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;45&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;kw_while&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;46&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;kw_do&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;47&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;kw_repeat&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;48&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;kw_for&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;49&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;kw_break&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;50&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;kw_continue&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;51&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;kw_fallthrough&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;52&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;kw_switch&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;53&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;kw_case&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;54&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;kw_default&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;55&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;pound_if&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;56&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;pound_sourceLocation&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;57&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;..&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;85&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;86&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Using this function, &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseExprOrStmt&lt;/span&gt;&lt;/code&gt; determines that &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;print&lt;/span&gt;(...)&lt;/code&gt; is an expression, and so it calls &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseExpr&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/Parse/ParseStmt.cpp#L88-L135&quot;&gt;swift/lib/Parse/ParseStmt.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt; 88&lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;ParserStatus&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::parseExprOrStmt(&lt;span class=&quot;cl&quot;&gt;ASTNode&lt;/span&gt; &amp;amp;Result) {
&lt;span class=&quot;ln&quot;&gt; ..&lt;/span&gt;    
&lt;span class=&quot;ln&quot;&gt; 96&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;f&quot;&gt;isStartOfStmt&lt;/span&gt;()) {
&lt;span class=&quot;ln&quot;&gt; 97&lt;/span&gt;      &lt;span class=&quot;cl&quot;&gt;ParserResult&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;Stmt&lt;/span&gt;&amp;gt; Res = &lt;span class=&quot;f&quot;&gt;parseStmt&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt; 98&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (Res.&lt;span class=&quot;f&quot;&gt;isNonNull&lt;/span&gt;())
&lt;span class=&quot;ln&quot;&gt; 99&lt;/span&gt;        Result = Res.&lt;span class=&quot;f&quot;&gt;get&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;100&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; Res;
&lt;span class=&quot;ln&quot;&gt;101&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;117&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;ParserResult&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;Expr&lt;/span&gt;&amp;gt; ResultExpr = &lt;span class=&quot;f&quot;&gt;parseExpr&lt;/span&gt;(&lt;span class=&quot;t&quot;&gt;diag&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;expected_expr&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;118&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (ResultExpr.&lt;span class=&quot;f&quot;&gt;isNonNull&lt;/span&gt;()) {
&lt;span class=&quot;ln&quot;&gt;119&lt;/span&gt;      Result = ResultExpr.&lt;span class=&quot;f&quot;&gt;get&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;120&lt;/span&gt;    } &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (!ResultExpr.&lt;span class=&quot;f&quot;&gt;hasCodeCompletion&lt;/span&gt;()) {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;127&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;133&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; ResultExpr;
&lt;span class=&quot;ln&quot;&gt;134&lt;/span&gt;  }
&lt;span class=&quot;ln&quot;&gt;135&lt;/span&gt;  
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Parsing an expression in Swift is complicated, because expressions can be composed of sequence of expressions of arbitrary length. For example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a &amp;amp;&amp;amp; (b || (c &amp;amp;&amp;amp; d))&lt;/code&gt; is an expression itself, but &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(c &amp;amp;&amp;amp; d)&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(b || (c &amp;amp;&amp;amp; d)&lt;/code&gt; are also expressions on their own.&lt;/p&gt;

&lt;p&gt;I'll skip over some of the complexity that this introduces in order to showcase just the path that the code takes when parsing our single element expression sequence &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;print&lt;/span&gt;(&lt;span class=&quot;s&quot;&gt;&quot;Hello, world!&quot;&lt;/span&gt;)&lt;/code&gt;. Suffice it to say that &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseExpr&lt;/span&gt;&lt;/code&gt; eventually calls &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseExprPostfixWithoutSuffix&lt;/span&gt;&lt;/code&gt;, a function that enters a large &lt;code&gt;&lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt;&lt;/code&gt; statement on the current token kind: for example, if the current token is a string literal, it calls &lt;code&gt;&lt;span class=&quot;f&quot;&gt;parseExprStringLiteral&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/Parse/ParseExpr.cpp#L1463-L1886&quot;&gt;swift/lib/Parse/ParseExpr.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;1463&lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;ParserResult&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;Expr&lt;/span&gt;&amp;gt;
&lt;span class=&quot;ln&quot;&gt;1464&lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::parseExprPostfixWithoutSuffix(&lt;span class=&quot;cl&quot;&gt;Diag&lt;/span&gt;&amp;lt;&amp;gt; ID, &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; isExprBasic) {
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1466&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;ParserResult&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;Expr&lt;/span&gt;&amp;gt; Result;
&lt;span class=&quot;ln&quot;&gt;1467&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; (&lt;span class=&quot;vi&quot;&gt;Tok&lt;/span&gt;.&lt;span class=&quot;f&quot;&gt;getKind&lt;/span&gt;()) {
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1498&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;string_literal&lt;/span&gt;:  &lt;span class=&quot;c&quot;&gt;// &quot;foo&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1499&lt;/span&gt;      Result = &lt;span class=&quot;f&quot;&gt;parseExprStringLiteral&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;1500&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;        
&lt;span class=&quot;ln&quot;&gt;1562&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;identifier&lt;/span&gt;:  &lt;span class=&quot;c&quot;&gt;// foo&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;1598&lt;/span&gt;      &lt;span class=&quot;m&quot;&gt;LLVM_FALLTHROUGH&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;1599&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;kw_self&lt;/span&gt;:     &lt;span class=&quot;c&quot;&gt;// self&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1600&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;kw_Self&lt;/span&gt;:     &lt;span class=&quot;c&quot;&gt;// Self&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1601&lt;/span&gt;      Result = &lt;span class=&quot;f&quot;&gt;makeParserResult&lt;/span&gt;(&lt;span class=&quot;f&quot;&gt;parseExprIdentifier&lt;/span&gt;());
&lt;span class=&quot;ln&quot;&gt;1602&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;1603&lt;/span&gt;      &lt;span class=&quot;c&quot;&gt;// If there is an expr-call-suffix, parse it and form a call.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1604&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;vi&quot;&gt;Tok&lt;/span&gt;.&lt;span class=&quot;f&quot;&gt;isFollowingLParen&lt;/span&gt;()) {
&lt;span class=&quot;ln&quot;&gt;1605&lt;/span&gt;        Result = &lt;span class=&quot;f&quot;&gt;parseExprCallSuffix&lt;/span&gt;(Result, isExprBasic);
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1607&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;1608&lt;/span&gt;      }
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1610&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt; 
&lt;span class=&quot;ln&quot;&gt;1883&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;1885&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; Result;
&lt;span class=&quot;ln&quot;&gt;1886&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;In the case of &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;print&lt;/span&gt;(...)&lt;/code&gt;, the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseExprPostfixWithoutSuffix&lt;/span&gt;&lt;/code&gt; function enters the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;identifier&lt;/span&gt;&lt;/code&gt; case. In this case, it falls through to the same case as for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;self&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Self&lt;/code&gt;, and so it parses the identifier with &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseExprIdentifier&lt;/span&gt;&lt;/code&gt;. Then, if the next token is a left parentheses &lt;code&gt;&lt;span class=&quot;ch&quot;&gt;'('&lt;/span&gt;&lt;/code&gt;, it parses a call expression by calling &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseExprCallSuffix&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseExprIdentifier&lt;/span&gt;&lt;/code&gt; member function attempts to lookup the identifer name in the current scope and, if it can't find a definition, it creates an &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;UnqualifiedDeclRefExpr&lt;/span&gt;&lt;/code&gt; node in the AST:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/Parse/ParseExpr.cpp#L1463-L1886&quot;&gt;swift/lib/Parse/ParseExpr.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;2218&lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;Expr&lt;/span&gt; *&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::parseExprIdentifier() {
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2249&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;ValueDecl&lt;/span&gt; *D = &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2251&lt;/span&gt;      D = &lt;span class=&quot;f&quot;&gt;lookupInScope&lt;/span&gt;(name);
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;    
&lt;span class=&quot;ln&quot;&gt;2278&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;Expr&lt;/span&gt; *E;
&lt;span class=&quot;ln&quot;&gt;2279&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (D == &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;) {
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2286&lt;/span&gt;      E = &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; (&lt;span class=&quot;vi&quot;&gt;Context&lt;/span&gt;) &lt;span class=&quot;cl&quot;&gt;UnresolvedDeclRefExpr&lt;/span&gt;(name, refKind, loc);
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;2307&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; E;
&lt;span class=&quot;ln&quot;&gt;2308&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;An &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;UnqualifiedDeclRefExpr&lt;/span&gt;&lt;/code&gt; is an expression that references an &quot;unqualified&quot; identifier. The identifier might not have been defined yet, or it may never be defined and so this code will fail during type-checking, or the identifier could have been defined in a different module.&lt;/p&gt;

&lt;p&gt;In this case, &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;print&lt;/span&gt;&lt;/code&gt; is defined in a different module: it's defined in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Swift.swiftmodule&lt;/code&gt;, the Swift standard library module. As a result, any references to &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;print&lt;/span&gt;&lt;/code&gt; will be treated as an &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;UnqualifiedDeclRefExpr&lt;/span&gt;&lt;/code&gt;, at least until the type-checker runs and the &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;print&lt;/span&gt;&lt;/code&gt; identifier is read from the Swift module.&lt;/p&gt;

&lt;p&gt;As explained above &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseExprPostfixWithoutSuffix&lt;/span&gt;&lt;/code&gt; parses the &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;print&lt;/span&gt;&lt;/code&gt; identifier, then checks for an opening parenthesis &lt;code&gt;&lt;span class=&quot;ch&quot;&gt;'('&lt;/span&gt;&lt;/code&gt;. If one exists, it calls &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseExprCallSuffix&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Just as with parsing expression sequences, parsing arguments to a call expression is complicated. Swift functions can take an arbitrary number of expressions as arguments, and each of those arguments can itself be a sequence of expressions. I won't go into the details here; the basic idea is that &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseExprList&lt;/span&gt;&lt;/code&gt; parses a list of expressions that are passed into a call to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CallExpr::create&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/Parse/ParseExpr.cpp#L1463-L1886&quot;&gt;swift/lib/Parse/ParseExpr.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;3223&lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;ParserResult&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;Expr&lt;/span&gt;&amp;gt;
&lt;span class=&quot;ln&quot;&gt;3224&lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::parseExprCallSuffix(&lt;span class=&quot;cl&quot;&gt;ParserResult&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;Expr&lt;/span&gt;&amp;gt; fn, &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; isExprBasic) {  
&lt;span class=&quot;ln&quot;&gt;3227&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;3256&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;ParserStatus&lt;/span&gt; status = &lt;span class=&quot;f&quot;&gt;parseExprList&lt;/span&gt;(&lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;l_paren&lt;/span&gt;, &lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;r_paren&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;3257&lt;/span&gt;                                        &lt;span class=&quot;c&quot;&gt;/*isPostfix=*/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;, isExprBasic,
&lt;span class=&quot;ln&quot;&gt;3258&lt;/span&gt;                                        lParenLoc, args, argLabels,
&lt;span class=&quot;ln&quot;&gt;3259&lt;/span&gt;                                        argLabelLocs,
&lt;span class=&quot;ln&quot;&gt;3260&lt;/span&gt;                                        rParenLoc,
&lt;span class=&quot;ln&quot;&gt;3261&lt;/span&gt;                                        trailingClosure,
&lt;span class=&quot;ln&quot;&gt;3262&lt;/span&gt;                                        &lt;span class=&quot;t&quot;&gt;SyntaxKind&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;FunctionCallArgumentList&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;3263&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;3265&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; Result = &lt;span class=&quot;f&quot;&gt;makeParserResult&lt;/span&gt;(status | fn, 
&lt;span class=&quot;ln&quot;&gt;3266&lt;/span&gt;                                   &lt;span class=&quot;cl&quot;&gt;CallExpr&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;create&lt;/span&gt;(&lt;span class=&quot;vi&quot;&gt;Context&lt;/span&gt;, fn.&lt;span class=&quot;f&quot;&gt;get&lt;/span&gt;(), lParenLoc,
&lt;span class=&quot;ln&quot;&gt;3267&lt;/span&gt;                                                    args, argLabels, argLabelLocs,
&lt;span class=&quot;ln&quot;&gt;3268&lt;/span&gt;                                                    rParenLoc, trailingClosure,
&lt;span class=&quot;ln&quot;&gt;3269&lt;/span&gt;                                                    &lt;span class=&quot;c&quot;&gt;/*implicit=*/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;));
&lt;span class=&quot;ln&quot;&gt;3278&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; Result;
&lt;span class=&quot;ln&quot;&gt;3279&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;In the case of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.swift&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseExprList&lt;/span&gt;&lt;/code&gt; only finds a single expression. It eventually calls through to the &lt;code&gt;&lt;span class=&quot;cn&quot;&gt;string_literal&lt;/span&gt;&lt;/code&gt; case in the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseExprPostfixWithoutSuffix&lt;/span&gt;&lt;/code&gt; function posted above, which results in a call to &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseExprStringLiteral&lt;/span&gt;&lt;/code&gt; and, in turn, the &lt;code&gt;&lt;span class=&quot;f&quot;&gt;createStringLiteralExprFromSegment&lt;/span&gt;&lt;/code&gt; function:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/Parse/ParseExpr.cpp#L1463-L1886&quot;&gt;swift/lib/Parse/ParseExpr.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;1888&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;StringLiteralExpr&lt;/span&gt; *
&lt;span class=&quot;ln&quot;&gt;1889&lt;/span&gt;  createStringLiteralExprFromSegment(&lt;span class=&quot;cl&quot;&gt;ASTContext&lt;/span&gt; &amp;amp;Ctx,
&lt;span class=&quot;ln&quot;&gt;1890&lt;/span&gt;                                     &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt; *L,
&lt;span class=&quot;ln&quot;&gt;1891&lt;/span&gt;                                     &lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;StringSegment&lt;/span&gt; &amp;amp;Segment,
&lt;span class=&quot;ln&quot;&gt;1892&lt;/span&gt;                                     &lt;span class=&quot;cl&quot;&gt;SourceLoc&lt;/span&gt; TokenLoc) {
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1902&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; (Ctx) &lt;span class=&quot;cl&quot;&gt;StringLiteralExpr&lt;/span&gt;(EncodedStr, TokenLoc);
&lt;span class=&quot;ln&quot;&gt;1903&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseExprList&lt;/span&gt;&lt;/code&gt; function allocates a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;ParenExpr&lt;/span&gt;&lt;/code&gt;. Whatever expresions it parses, such as the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;StringLiteralExpr&lt;/span&gt;&lt;/code&gt; above, are nested within the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;ParenExpr&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;All told, the call to &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseExprOrStmt&lt;/span&gt;&lt;/code&gt; results in the following nodes being added to the AST:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;astp&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;astexpr&quot;&gt;call_expr&lt;/span&gt; &lt;span class=&quot;asto&quot;&gt;type='&amp;lt;null&amp;gt;' arg_labels=_:&lt;/span&gt;
  &lt;span class=&quot;astp&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;astexpr&quot;&gt;unresolved_decl_ref_expr&lt;/span&gt; &lt;span class=&quot;asto&quot;&gt;type='&amp;lt;null&amp;gt;' name=print function_ref=unapplied)&lt;/span&gt;
  &lt;span class=&quot;astp&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;astexpr&quot;&gt;paren_expr&lt;/span&gt; &lt;span class=&quot;asto&quot;&gt;type='&amp;lt;null&amp;gt;'&lt;/span&gt;
  &lt;span class=&quot;astp&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;astexpr&quot;&gt;string_literal_expr&lt;/span&gt; &lt;span class=&quot;asto&quot;&gt;type='&amp;lt;null&amp;gt;' encoding=utf8 value=&quot;Hello, world!&quot; builtin_initializer=**NULL** initializer=**NULL**&lt;/span&gt;&lt;span class=&quot;astp&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;astp&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;astp&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;As shown above, the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CallExpr&lt;/span&gt;&lt;/code&gt; result is then nested within the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;BraceStmt&lt;/span&gt;&lt;/code&gt; that is created within the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseBraceItems&lt;/span&gt;&lt;/code&gt; member function. So, in sum, the AST looks like this:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;astp&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;aststmt&quot;&gt;source_file&lt;/span&gt;
  &lt;span class=&quot;astp&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;astdecl&quot;&gt;top_level_code_decl&lt;/span&gt;
    &lt;span class=&quot;astp&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;aststmt&quot;&gt;brace_stmt&lt;/span&gt;
      &lt;span class=&quot;astp&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;astexpr&quot;&gt;call_expr&lt;/span&gt; &lt;span class=&quot;asto&quot;&gt;type='&amp;lt;null&amp;gt;' arg_labels=_:&lt;/span&gt;
        &lt;span class=&quot;astp&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;astexpr&quot;&gt;unresolved_decl_ref_expr&lt;/span&gt; &lt;span class=&quot;asto&quot;&gt;type='&amp;lt;null&amp;gt;' name=print function_ref=unapplied)&lt;/span&gt;
        &lt;span class=&quot;astp&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;astexpr&quot;&gt;paren_expr&lt;/span&gt; &lt;span class=&quot;asto&quot;&gt;type='&amp;lt;null&amp;gt;'&lt;/span&gt;
          &lt;span class=&quot;astp&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;astexpr&quot;&gt;string_literal_expr&lt;/span&gt; &lt;span class=&quot;asto&quot;&gt;type='&amp;lt;null&amp;gt;' encoding=utf8 value=&quot;Hello, world!&quot; builtin_initializer=**NULL** initializer=**NULL**&lt;/span&gt;&lt;span class=&quot;astp&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;astp&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;astp&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;astp&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;astp&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;astp&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;

&lt;h2 id=&quot;stage-6-reaching-the-end-of-the-file&quot;&gt;Stage 6: Reaching the end of the file&lt;/h2&gt;

&lt;p&gt;When &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseExprList&lt;/span&gt;&lt;/code&gt; is called, the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;&lt;/code&gt; tasks the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;&lt;/code&gt; with consuming each token within the parentheses that come after &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;print&lt;/span&gt;&lt;/code&gt;. The parsing and lexing stops at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;')'&lt;/code&gt;, at which point the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;::&lt;span class=&quot;vi&quot;&gt;NextToken&lt;/span&gt;&lt;/code&gt; is set to &lt;code&gt;&lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;eof&lt;/span&gt;&lt;/code&gt; – the end of the file.&lt;/p&gt;

&lt;p&gt;Recall that all this parsing was occuring within a while loop in &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseBraceItems&lt;/span&gt;&lt;/code&gt;. One of the termination conditions for that while loop was encountering an EOF marker. Now that the end of the file has been reached, &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseBraceItems&lt;/span&gt;&lt;/code&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;s control back to &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseTopLevel&lt;/span&gt;&lt;/code&gt;, which &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;s control back to &lt;code&gt;&lt;span class=&quot;f&quot;&gt;parseIntoSourceFile&lt;/span&gt;&lt;/code&gt;, which &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;s back to &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseAndTypeCheckMainFile&lt;/span&gt;&lt;/code&gt;. The stage is now set for type-checking, which is done by calling the &lt;code&gt;&lt;span class=&quot;f&quot;&gt;performTypeChecking&lt;/span&gt;&lt;/code&gt; function:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/ce0c40e40b0c4aa50514a29f2c2b9401b30849a4/lib/Frontend/Frontend.cpp#L1463-L1886&quot;&gt;swift/lib/Frontend/Frontend.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;659&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::parseAndTypeCheckMainFile(
&lt;span class=&quot;ln&quot;&gt;660&lt;/span&gt;      &lt;span class=&quot;cl&quot;&gt;PersistentParserState&lt;/span&gt; &amp;amp;PersistentState,
&lt;span class=&quot;ln&quot;&gt;661&lt;/span&gt;      &lt;span class=&quot;cl&quot;&gt;DelayedParsingCallbacks&lt;/span&gt; *DelayedParseCB,
&lt;span class=&quot;ln&quot;&gt;662&lt;/span&gt;      &lt;span class=&quot;cl&quot;&gt;OptionSet&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;TypeCheckingFlags&lt;/span&gt;&amp;gt; TypeCheckOptions) {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;677&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; Done;
&lt;span class=&quot;ln&quot;&gt;678&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;683&lt;/span&gt;      &lt;span class=&quot;f&quot;&gt;parseIntoSourceFile&lt;/span&gt;(MainFile, MainFile.&lt;span class=&quot;f&quot;&gt;getBufferID&lt;/span&gt;().&lt;span class=&quot;f&quot;&gt;getValue&lt;/span&gt;(), &amp;amp;Done,
&lt;span class=&quot;ln&quot;&gt;684&lt;/span&gt;                          &lt;span class=&quot;vi&quot;&gt;TheSILModule&lt;/span&gt; ? &amp;amp;SILContext : &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;, &amp;amp;PersistentState,
&lt;span class=&quot;ln&quot;&gt;685&lt;/span&gt;                          DelayedParseCB);
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;688&lt;/span&gt;        &lt;span class=&quot;f&quot;&gt;performTypeChecking&lt;/span&gt;(MainFile, PersistentState.&lt;span class=&quot;f&quot;&gt;getTopLevelContext&lt;/span&gt;(),
&lt;span class=&quot;ln&quot;&gt;689&lt;/span&gt;                            TypeCheckOptions, CurTUElem,
&lt;span class=&quot;ln&quot;&gt;690&lt;/span&gt;                            options.&lt;span class=&quot;vi&quot;&gt;WarnLongFunctionBodies&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;691&lt;/span&gt;                            options.&lt;span class=&quot;vi&quot;&gt;WarnLongExpressionTypeChecking&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;692&lt;/span&gt;                            options.&lt;span class=&quot;vi&quot;&gt;SolverExpressionTimeThreshold&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;695&lt;/span&gt;    } &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; (!Done);
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;713&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;I'll cover type-checking in a future article.&lt;/p&gt;

&lt;h2 id=&quot;recap-lexing-and-parsing-in-the-swift-compiler&quot;&gt;Recap: lexing and parsing in the Swift compiler&lt;/h2&gt;

&lt;p&gt;This article covered a lot of ground:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;It explained that Swift's &lt;code&gt;&lt;span class=&quot;f&quot;&gt;main&lt;/span&gt;&lt;/code&gt; function determines whether to call &lt;code&gt;&lt;span class=&quot;f&quot;&gt;performFrontend&lt;/span&gt;&lt;/code&gt; by checking for the presence of the &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt; argument.&lt;/li&gt;
  &lt;li&gt;If the &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt; argument is provided, &lt;code&gt;&lt;span class=&quot;f&quot;&gt;performFrontend&lt;/span&gt;&lt;/code&gt; parses the other arguments passed into &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt;. It determines the requested action based on those arguments, and instantiates a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;ASTContext&lt;/span&gt;&lt;/code&gt; to carry out that action. If compilation is requested, it calls &lt;code&gt;&lt;span class=&quot;f&quot;&gt;performCompile&lt;/span&gt;&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;&lt;span class=&quot;f&quot;&gt;performCompile&lt;/span&gt;&lt;/code&gt; checks the requested action and decides whether to call &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;performSema&lt;/span&gt;&lt;/code&gt; (parsing and type-checking), or &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;performParseOnly&lt;/span&gt;&lt;/code&gt; (just parsing). Our invocation of &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-c&lt;/span&gt;&lt;/code&gt; results in a requested action of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ActionType::EmitObject&lt;/code&gt;, and so &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;performSema&lt;/span&gt;&lt;/code&gt; is called.&lt;/li&gt;
  &lt;li&gt;A &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;&lt;/code&gt; is initialized along with its &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;&lt;/code&gt;. A &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;&lt;/code&gt; reads characters and transforms strings of them into &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Token&lt;/span&gt;&lt;/code&gt; objects. A &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;&lt;/code&gt; drives the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;&lt;/code&gt;, based on the tokens its seeing and its knowledge of Swift syntax. The parsing process begins when &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseTopLevel&lt;/span&gt;&lt;/code&gt; is called.
&lt;code&gt;&lt;span class=&quot;cl&quot;&gt;UnresolvedDeclRefExpr&lt;/span&gt;&lt;/code&gt;. It sees an opening parenthesis immediately following the identifier, so it wraps the expression in a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CallExpr&lt;/span&gt;&lt;/code&gt;. The arguments to the call expression are parsed: a single &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;StringLiteralExpr&lt;/span&gt;&lt;/code&gt;, wrapped in a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;ParenExpr&lt;/span&gt;&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;The end of the file is reached, and so control goes back to &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompilerInstance&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;performSema&lt;/span&gt;&lt;/code&gt;. Next stop: the type-checker!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To add new pieces of Swift syntax, or to modify existing Swift syntax, it's helpful to understand the libswiftParse source code. For example:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/apple/swift/pull/8813&quot;&gt;The pull request that implemented mulitline string literals in Swift&lt;/a&gt; modified how the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Lexer&lt;/span&gt;&lt;/code&gt; formed string literal tokens.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/apple/swift/pull/14048&quot;&gt;The pull request that implemented &lt;code&gt;&lt;span class=&quot;ms&quot;&gt;#error&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;ms&quot;&gt;#warning&lt;/span&gt;&lt;/code&gt; in Swift&lt;/a&gt; added &lt;code&gt;&lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;pound_warning&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;pound_error&lt;/span&gt;&lt;/code&gt; to the list of token kinds in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TokenKinds.def&lt;/code&gt;. It then added the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseDeclPoundDiagnostic&lt;/span&gt;&lt;/code&gt; function. This function, unlike many of the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Parser&lt;/span&gt;&lt;/code&gt; functions we covered above, does not create new AST nodes. Instead, it simply emits a warning or error when it sees &lt;code&gt;&lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;pound_warning&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class=&quot;t&quot;&gt;tok&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;pound_error&lt;/span&gt;&lt;/code&gt;. Pretty clever, huh?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To learn more about how parsing works in the Swift compiler, try writing small programs and walking through the code in the compiler to see how they're parsed. A good way to do this is by attaching a debugger – read the instructions from the first article in this series, &lt;a href=&quot;/getting-started-with-swift-development&quot;&gt;Getting Started with Swift Compiler Development&lt;/a&gt;, to learn how to do so. There's still a lot left to learn that I didn't cover in this article. Here's just two examples of parser mechanics that this article didn't cover:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The parser is capable of &quot;backtracking&quot;. That is, it can begin parsing tokens assuming a certain kind of statement or expression and, if it determines it is not actually parsing an expression of that kind, it can &quot;undo&quot; and reset back to where it started.&lt;/li&gt;
  &lt;li&gt;The parser can conditionally parse portions of the program based on directives such as &lt;code&gt;&lt;span class=&quot;ms&quot;&gt;#if&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;ms&quot;&gt;#else&lt;/span&gt;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;</content><author><name></name></author><category term="swiftc" /><summary type="html">A previous article in this series explained two primary ways of invoking the swift compiler executable: swift and swift -frontend.</summary></entry><entry><title type="html">Option Parsing in the Swift Compiler</title><link href="https://modocache.io/option-parsing-in-the-swift-compiler" rel="alternate" type="text/html" title="Option Parsing in the Swift Compiler" /><published>2017-12-16T05:00:00+00:00</published><updated>2017-12-16T05:00:00+00:00</updated><id>https://modocache.io/option-parsing-in-the-swift-compiler</id><content type="html" xml:base="https://modocache.io/option-parsing-in-the-swift-compiler">&lt;p&gt;The &lt;a href=&quot;/reading-and-understanding-the-swift-driver-source-code&quot;&gt;last article&lt;/a&gt; in this series explained how &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libswiftDriver&lt;/code&gt; split up &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt;&lt;/code&gt; executable invocations into smaller sub-jobs. Parsing command-line arguments is a big part of that work, but I didn't go into much detail about it. This article will now explain command-line argument parsing in depth.&lt;/p&gt;

&lt;p&gt;Specifically, this article describes how:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Within the Swift build system, LLVM TableGen is used to transform the options specified in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/include/swift/Option/Options.td&lt;/code&gt;. The transformed output is written to a file named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Options.inc&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;A &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libswiftOption&lt;/code&gt; header includes the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Options.inc&lt;/code&gt; file in order to define an enum named &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;options&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;ID&lt;/span&gt;&lt;/code&gt;. By defining a macro before including &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Options.inc&lt;/code&gt; file, it's able to define an enum case for each option defined in the original &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Options.td&lt;/code&gt; file: &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;options&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;ID&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;OPT_driver_print_jobs&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;options&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;ID&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;OPT_driver_print_actions&lt;/span&gt;&lt;/code&gt;, and so on.&lt;/li&gt;
  &lt;li&gt;In its implementation, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libswiftOption&lt;/code&gt; defines a macro, then includes the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Options.inc&lt;/code&gt; file a second time, this time in order to initialize an &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;opt&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;OptTable&lt;/span&gt;&lt;/code&gt;. The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;OptTable&lt;/span&gt;&lt;/code&gt; class is defined in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libLLVMOption&lt;/code&gt; and provides argument parsing utilities.&lt;/li&gt;
  &lt;li&gt;In its &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;buildCompilation&lt;/span&gt;&lt;/code&gt; method, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libswiftDriver&lt;/code&gt; calls the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;opt&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;OptTable&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;ParseArgs&lt;/span&gt;&lt;/code&gt; method. This takes the array of strings passed into the &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt;&lt;/code&gt; compiler executable's &lt;code&gt;&lt;span class=&quot;f&quot;&gt;main&lt;/span&gt;&lt;/code&gt; function as an argument, and it returns an &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;opt&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;InputArgList&lt;/span&gt;&lt;/code&gt;. This class defines the methods used throughout the Swift compiler codebase. The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;InputArgList&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;hasArg&lt;/span&gt;&lt;/code&gt; method, which checks for the presence of an argument, is perhaps the most common.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Many contributions to the Swift compiler involve modifying or adding command-line options. Understanding how these options are parsed has helped me make such contributions.&lt;/p&gt;

&lt;h2 id=&quot;an-introduction-to-llvm-tablegen&quot;&gt;An introduction to LLVM TableGen&lt;/h2&gt;

&lt;p&gt;TableGen is a utility program for LLVM developers. An &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;llvm-tblgen&lt;/span&gt;&lt;/code&gt; executable is built as part of LLVM, and can be found in the LLVM build directory of a Swift build tree, in &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;/path/to/build/llvm-macosx-x86_64/bin/llvm-tblgen&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;TableGen is documented in detail &lt;a href=&quot;http://llvm.org/docs/TableGen/&quot;&gt;here&lt;/a&gt;, but for my purposes it's sufficient to understand it as a tool that transforms the syntax in Swift's option files – &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/include/swift/Option/Options.td&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/include/swift/Option/FrontendOptions.td&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/tools/SourceKit/tools/sourcekitd-test/Options.td&lt;/code&gt; – into a syntax that looks like C macro invocations.&lt;/p&gt;

&lt;p&gt;For example, the &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-driver-print-jobs&lt;/span&gt;&lt;/code&gt; compiler option, mentioned in &lt;a href=&quot;/introduction-to-the-swift-compiler-driver&quot;&gt;several&lt;/a&gt; &lt;a href=&quot;/reading-and-understanding-the-swift-driver-source-code&quot;&gt;past&lt;/a&gt; articles, is defined in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Options.td&lt;/code&gt; like so:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/2e6f878d099d9dc1f5ac1357df02e334c3c7b10f/include/swift/Option/Options.td#L82-L83&quot;&gt;swift/include/swift/Option/Options.td&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;18&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;llvm/Option/OptParser.td&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;..&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;82&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; driver_print_jobs : &lt;span class=&quot;f&quot;&gt;Flag&lt;/span&gt;&amp;lt;[&lt;span class=&quot;s&quot;&gt;&quot;-&quot;&lt;/span&gt;], &lt;span class=&quot;s&quot;&gt;&quot;driver-print-jobs&quot;&lt;/span&gt;&amp;gt;, &lt;span class=&quot;cn&quot;&gt;InternalDebugOpt&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;83&lt;/span&gt;    &lt;span class=&quot;f&quot;&gt;HelpText&lt;/span&gt;&amp;lt;&lt;span class=&quot;s&quot;&gt;&quot;Dump list of jobs to execute&quot;&lt;/span&gt;&amp;gt;;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;I can use &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;llvm-tblgen&lt;/span&gt;&lt;/code&gt; to transform the file in which it's defined:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;cexec&quot;&gt;/path/to/build/llvm-macosx-x86_64/bin/llvm-tblgen&lt;/span&gt; \
    &lt;span class=&quot;copt&quot;&gt;-I&lt;/span&gt; ~/local/Source/apple/llvm/include \
    &lt;span class=&quot;copt&quot;&gt;-I&lt;/span&gt; ~/local/Source/apple/swift/include/swift/Option \
    ~/local/Source/apple/swift/include/swift/Option/Options.td \
    &lt;span class=&quot;copt&quot;&gt;-gen-opt-parser-defs&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;This takes all of the options in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Options.td&lt;/code&gt;, and outputs them as calls to a C macro named &lt;code&gt;&lt;span class=&quot;m&quot;&gt;OPTION&lt;/span&gt;&lt;/code&gt;. For example, here's the output that corresponds to the &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-driver-print-jobs&lt;/span&gt;&lt;/code&gt; definition shown above:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;m&quot;&gt;OPTION&lt;/span&gt;(
  &lt;span class=&quot;v&quot;&gt;prefix_1&lt;/span&gt;,
  &lt;span class=&quot;s&quot;&gt;&quot;driver-print-jobs&quot;&lt;/span&gt;,
  &lt;span class=&quot;cn&quot;&gt;driver_print_jobs&lt;/span&gt;,
  &lt;span class=&quot;v&quot;&gt;Flag&lt;/span&gt;,
  &lt;span class=&quot;cn&quot;&gt;internal_debug_Group&lt;/span&gt;,
  &lt;span class=&quot;cn&quot;&gt;INVALID&lt;/span&gt;,
  &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;,
  &lt;span class=&quot;cn&quot;&gt;HelpHidden&lt;/span&gt; | &lt;span class=&quot;cn&quot;&gt;DoesNotAffectIncrementalBuild&lt;/span&gt;,
  &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;,
  &lt;span class=&quot;s&quot;&gt;&quot;Dump list of jobs to execute&quot;&lt;/span&gt;,
  &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;,
  &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;)
&lt;/pre&gt;

&lt;blockquote&gt;
  &lt;p&gt;The LLVM TableGen executable &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;llvm-tblgen&lt;/span&gt;&lt;/code&gt; can output many different formats. I instructed it to output calls to the &lt;code&gt;&lt;span class=&quot;m&quot;&gt;OPTION&lt;/span&gt;&lt;/code&gt; macro, by using the &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-gen-opt-parser-defs&lt;/span&gt;&lt;/code&gt; argument. Other arguments include &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-gen-ctags&lt;/span&gt;&lt;/code&gt;, which generates definitions and source locations for the popular source indexing utility &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ctags&lt;/code&gt;, and &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-print-records&lt;/span&gt;&lt;/code&gt;, which prints TableGen's internal representation of each entry.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With that prerequisite explanation of LLVM TableGen out of the way, we're ready to look at the four stages of how arguments are parsed in the Swift compiler.&lt;/p&gt;

&lt;h2 id=&quot;stage-1-swifts-cmake-instructs-tablegen-to-transform-optionstd-into-optionsinc&quot;&gt;Stage 1: Swift's CMake instructs TableGen to transform &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Options.td&lt;/code&gt; into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Options.inc&lt;/code&gt;&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;If you haven't already, try reading &lt;a href=&quot;/the-swift-compilers-build-system&quot;&gt;The Swift Compiler's Build System&lt;/a&gt; and &lt;a href=&quot;/reading-and-understanding-the-cmake-in-apple-swift&quot;&gt;Reading and Understanding the CMake in apple/swift&lt;/a&gt; before continuing – you'll need to know the basics of CMake in order to enjoy this section.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A &lt;code&gt;&lt;span class=&quot;cmd&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;grep&lt;/span&gt;&lt;/code&gt; for &lt;code&gt;&lt;span class=&quot;s&quot;&gt;&quot;driver-print-jobs&quot;&lt;/span&gt;&lt;/code&gt; reveals that this option is defined in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/include/swift/Option/Options.td&lt;/code&gt;. In fact, nearly every option supported by the Swift compiler is defined in this file. And in that same directory, a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CMakeLists.txt&lt;/code&gt; file defines how these options are transformed by TableGen:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/2e6f878d099d9dc1f5ac1357df02e334c3c7b10f/include/swift/Option/CMakeLists.txt#L1-L3&quot;&gt;swift/include/swift/Option/CMakeLists.txt&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;1&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;(&lt;span class=&quot;v&quot;&gt;LLVM_TARGET_DEFINITIONS&lt;/span&gt; Options.td)
&lt;span class=&quot;ln&quot;&gt;2&lt;/span&gt;  &lt;span class=&quot;m&quot;&gt;swift_tablegen&lt;/span&gt;(Options.inc &lt;span class=&quot;copt&quot;&gt;-gen-opt-parser-defs&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt;3&lt;/span&gt;  &lt;span class=&quot;m&quot;&gt;swift_add_public_tablegen_target&lt;/span&gt;(SwiftOptions)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Note that, unlike CMake functions that take their input files as arguments, the &lt;code&gt;&lt;span class=&quot;m&quot;&gt;swift_tablegen&lt;/span&gt;&lt;/code&gt; CMake macro requires its input files be specified using a global variable named &lt;code&gt;&lt;span class=&quot;v&quot;&gt;LLVM_TARGET_DEFINITIONS&lt;/span&gt;&lt;/code&gt;. The function also allows arbitrary options to be passed to the &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;llvm-tblgen&lt;/span&gt;&lt;/code&gt; executable. In this case, that's &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-gen-opt-parser-defs&lt;/span&gt;&lt;/code&gt; – the option that transforms TableGen definitions into &lt;code&gt;&lt;span class=&quot;m&quot;&gt;OPTION&lt;/span&gt;&lt;/code&gt; macro calls.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;span class=&quot;m&quot;&gt;swift_tablgen&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;m&quot;&gt;swift_add_public_tablegen_target&lt;/span&gt;&lt;/code&gt; are CMake macros defined in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/cmake/modules/AddSwiftTableGen.cmake&lt;/code&gt;. These two macros call through to LLVM CMake functions &lt;code&gt;&lt;span class=&quot;f&quot;&gt;tablegen&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;f&quot;&gt;add_public_tablegen_target&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The LLVM CMake function &lt;code&gt;&lt;span class=&quot;f&quot;&gt;tablegen&lt;/span&gt;&lt;/code&gt; instructs CMake on how to produce the specified output file (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Options.inc&lt;/code&gt;, in this case).&lt;/li&gt;
  &lt;li&gt;The LLVM CMake function &lt;code&gt;&lt;span class=&quot;f&quot;&gt;add_public_tablegen_target&lt;/span&gt;&lt;/code&gt; creates a public CMake target that depends on the production of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Options.inc&lt;/code&gt; file.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here's the &lt;code&gt;&lt;span class=&quot;f&quot;&gt;tablegen&lt;/span&gt;&lt;/code&gt; LLVM CMake function. It uses the built-in CMake function &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;add_custom_command&lt;/span&gt;&lt;/code&gt; to define how &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;llvm-tblgen&lt;/span&gt;&lt;/code&gt; should be run:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift-llvm/blob/fe49d8f2cac91ebc77aed94a14f3b2e74e6678ad/cmake/modules/TableGen.cmake#L11-L97&quot;&gt;llvm/cmake/modules/TableGen.cmake&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt; 11&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;(tablegen project ofn)
&lt;span class=&quot;ln&quot;&gt; ..&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 43&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;cma&quot;&gt;IS_ABSOLUTE&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;${LLVM_TARGET_DEFINITIONS})&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 44&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;(LLVM_TARGET_DEFINITIONS_ABSOLUTE &lt;span class=&quot;si&quot;&gt;${LLVM_TARGET_DEFINITIONS}&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt; 45&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;()
&lt;span class=&quot;ln&quot;&gt; 46&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;(LLVM_TARGET_DEFINITIONS_ABSOLUTE
&lt;span class=&quot;ln&quot;&gt; 47&lt;/span&gt;        &lt;span class=&quot;si&quot;&gt;${CMAKE_CURRENT_SOURCE_DIR}&lt;/span&gt;/&lt;span class=&quot;si&quot;&gt;${LLVM_TARGET_DEFINITIONS}&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt; 48&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;()
&lt;span class=&quot;ln&quot;&gt; ..&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 65&lt;/span&gt;    &lt;span class=&quot;fs&quot;&gt;add_custom_command&lt;/span&gt;(&lt;span class=&quot;cma&quot;&gt;OUTPUT&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;${CMAKE_CURRENT_BINARY_DIR}&lt;/span&gt;/&lt;span class=&quot;si&quot;&gt;${ofn}&lt;/span&gt;.tmp
&lt;span class=&quot;ln&quot;&gt; ..&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 67&lt;/span&gt;      &lt;span class=&quot;cma&quot;&gt;COMMAND&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;${${project}_TABLEGEN_EXE} ${ARGN}&lt;/span&gt; -I &lt;span class=&quot;si&quot;&gt;${CMAKE_CURRENT_SOURCE_DIR}&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 68&lt;/span&gt;      &lt;span class=&quot;si&quot;&gt;${LLVM_TABLEGEN_FLAGS}&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 69&lt;/span&gt;      &lt;span class=&quot;si&quot;&gt;${LLVM_TARGET_DEFINITIONS_ABSOLUTE}&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; ..&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 77&lt;/span&gt;      &lt;span class=&quot;cma&quot;&gt;COMMENT&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Building ${ofn}...&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 78&lt;/span&gt;      )
&lt;span class=&quot;ln&quot;&gt; 79&lt;/span&gt;    &lt;span class=&quot;fs&quot;&gt;add_custom_command&lt;/span&gt;(&lt;span class=&quot;cma&quot;&gt;OUTPUT&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;${CMAKE_CURRENT_BINARY_DIR}&lt;/span&gt;/&lt;span class=&quot;si&quot;&gt;${ofn}&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 80&lt;/span&gt;      &lt;span class=&quot;c&quot;&gt;# Only update the real output file if there are any differences.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 81&lt;/span&gt;      &lt;span class=&quot;c&quot;&gt;# This prevents recompilation of all the files depending on it if there&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 82&lt;/span&gt;      &lt;span class=&quot;c&quot;&gt;# aren't any.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 83&lt;/span&gt;      &lt;span class=&quot;cma&quot;&gt;COMMAND&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;${CMAKE_COMMAND}&lt;/span&gt; -E copy_if_different
&lt;span class=&quot;ln&quot;&gt; 84&lt;/span&gt;          &lt;span class=&quot;si&quot;&gt;${CMAKE_CURRENT_BINARY_DIR}&lt;/span&gt;/&lt;span class=&quot;si&quot;&gt;${ofn}&lt;/span&gt;.tmp
&lt;span class=&quot;ln&quot;&gt; 85&lt;/span&gt;          &lt;span class=&quot;si&quot;&gt;${CMAKE_CURRENT_BINARY_DIR}&lt;/span&gt;/&lt;span class=&quot;si&quot;&gt;${ofn}&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 86&lt;/span&gt;      &lt;span class=&quot;cma&quot;&gt;DEPENDS&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;${CMAKE_CURRENT_BINARY_DIR}&lt;/span&gt;/&lt;span class=&quot;si&quot;&gt;${ofn}&lt;/span&gt;.tmp
&lt;span class=&quot;ln&quot;&gt; 87&lt;/span&gt;      &lt;span class=&quot;cma&quot;&gt;COMMENT&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Updating &lt;span class=&quot;si&quot;&gt;${ofn}&lt;/span&gt;...&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 88&lt;/span&gt;      )
&lt;span class=&quot;ln&quot;&gt; ..&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 93&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt; 94&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt;(TABLEGEN_OUTPUT &lt;span class=&quot;si&quot;&gt;${TABLEGEN_OUTPUT} ${CMAKE_CURRENT_BINARY_DIR}&lt;/span&gt;/&lt;span class=&quot;si&quot;&gt;${ofn}&lt;/span&gt; &lt;span class=&quot;cma&quot;&gt;PARENT_SCOPE&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt; ..&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 97&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;()
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;And here's the &lt;code&gt;&lt;span class=&quot;f&quot;&gt;add_public_tablegen_target&lt;/span&gt;&lt;/code&gt; LLVM CMake function:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift-llvm/blob/fe49d8f2cac91ebc77aed94a14f3b2e74e6678ad/cmake/modules/TableGen.cmake#L100-L111&quot;&gt;llvm/cmake/modules/TableGen.cmake&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;100&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;(add_public_tablegen_target target)
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;104&lt;/span&gt;    &lt;span class=&quot;fs&quot;&gt;add_custom_target&lt;/span&gt;(&lt;span class=&quot;si&quot;&gt;${target}&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;105&lt;/span&gt;      &lt;span class=&quot;cma&quot;&gt;DEPENDS&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;${TABLEGEN_OUTPUT}&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;111&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;()
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;f&quot;&gt;add_public_tablegen_target&lt;/span&gt;&lt;/code&gt; calls the built-in CMake function &lt;code&gt;&lt;span class=&quot;fs&quot;&gt;add_custom_target&lt;/span&gt;&lt;/code&gt; in order to define a CMake target. In this case, the name of that target is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SwiftOptions&lt;/code&gt;. I can manually generate the TableGen for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SwiftOptions&lt;/code&gt; by invoking &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;cmake&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;--build&lt;/span&gt;&lt;/code&gt; on the command line, specifying &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SwiftOptions&lt;/code&gt; as the target I'd like to build:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;cexec&quot;&gt;cmake&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;--build&lt;/span&gt; \
    /path/to/build/swift-macosx-x86_64 \
    &lt;span class=&quot;copt&quot;&gt;--target&lt;/span&gt; SwiftOptions
&lt;/pre&gt;

&lt;p&gt;The above command does essentially the same thing as the manual &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;llvm-tblgen&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-gen-opt-parser-defs&lt;/span&gt;&lt;/code&gt; invocation shown earlier in this article.&lt;/p&gt;

&lt;p&gt;Instead of having users manually build the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SwiftOptions&lt;/code&gt; target, the CMake targets for several Swift compiler libraries, such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libswiftOption&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libswiftDriver&lt;/code&gt;, specify a dependency upon &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SwiftOptions&lt;/code&gt;. For example, here's &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libswiftOption&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/2e6f878d099d9dc1f5ac1357df02e334c3c7b10f/lib/Option/CMakeLists.txt#L1-L4&quot;&gt;swift/lib/Option/CMakeLists.txt&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;1&lt;/span&gt;  &lt;span class=&quot;f&quot;&gt;add_swift_library&lt;/span&gt;(swiftOption &lt;span class=&quot;cma&quot;&gt;STATIC&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;4&lt;/span&gt;    &lt;span class=&quot;cma&quot;&gt;DEPENDS&lt;/span&gt; SwiftOptions
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;As a result of this declared dependency, building &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libswiftOption&lt;/code&gt; results in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SwiftOptions&lt;/code&gt; being built first, which means &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;llvm-tblgen&lt;/span&gt;&lt;/code&gt; is run on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/include/swift/Option/Options.td&lt;/code&gt; in order to produce the file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/path/to/build/swift-macosx-x86_64/include/swift/Option/Options.inc&lt;/code&gt;. And again, because the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/include/swift/Option/CMakeLists.txt&lt;/code&gt; file specifies that &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;llvm-tblgen&lt;/span&gt;&lt;/code&gt; be invoked with the &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-gen-opt-parser-defs&lt;/span&gt;&lt;/code&gt; argument, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Options.inc&lt;/code&gt; file is populated with one call to an &lt;code&gt;&lt;span class=&quot;m&quot;&gt;OPTION&lt;/span&gt;&lt;/code&gt; macro for each option defined in the original &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Options.td&lt;/code&gt; file.&lt;/p&gt;

&lt;h2 id=&quot;stage-2-the-libswiftoption-headers-declare-an-enum-containing-a-case-for-each-of-the-options&quot;&gt;Stage 2: The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libswiftOption&lt;/code&gt; headers declare an enum containing a case for each of the options&lt;/h2&gt;

&lt;p&gt;In stage one, &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;llvm-tblgen&lt;/span&gt;&lt;/code&gt; transformed the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Options.td&lt;/code&gt; file into a file named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Options.inc&lt;/code&gt;. For each option defined in the original &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Options.td&lt;/code&gt;, the new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Options.inc&lt;/code&gt; file contains an invocation of a macro named &lt;code&gt;&lt;span class=&quot;m&quot;&gt;OPTION&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;m&quot;&gt;OPTION&lt;/span&gt;(
  &lt;span class=&quot;v&quot;&gt;prefix_1&lt;/span&gt;,
  &lt;span class=&quot;s&quot;&gt;&quot;driver-print-jobs&quot;&lt;/span&gt;,
  &lt;span class=&quot;cn&quot;&gt;driver_print_jobs&lt;/span&gt;,
  &lt;span class=&quot;v&quot;&gt;Flag&lt;/span&gt;,
  &lt;span class=&quot;cn&quot;&gt;internal_debug_Group&lt;/span&gt;,
  &lt;span class=&quot;cn&quot;&gt;INVALID&lt;/span&gt;,
  &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;,
  &lt;span class=&quot;cn&quot;&gt;HelpHidden&lt;/span&gt; | &lt;span class=&quot;cn&quot;&gt;DoesNotAffectIncrementalBuild&lt;/span&gt;,
  &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;,
  &lt;span class=&quot;s&quot;&gt;&quot;Dump list of jobs to execute&quot;&lt;/span&gt;,
  &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;,
  &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;)
&lt;/pre&gt;

&lt;p&gt;This is useful because I can define the &lt;code&gt;&lt;span class=&quot;m&quot;&gt;OPTION&lt;/span&gt;&lt;/code&gt; macro to do whatever I want, then &lt;code&gt;&lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Options.inc&quot;&lt;/span&gt;&lt;/code&gt; in order to have the macro invoked once for each option.&lt;/p&gt;

&lt;p&gt;This is exactly what the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libswiftOption&lt;/code&gt; header &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Options.h&lt;/code&gt; does in order to define the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;options&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;ID&lt;/span&gt;&lt;/code&gt; enum. That enum contains a case for each option defined in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Options.td&lt;/code&gt;. Without TableGen, that would mean manually listing each of these options out in the enum, like this:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; swift {
&lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; options {

&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; ID {
  OPT_driver_print_jobs,
  OPT_driver_print_actions,
  OPT_driver_skip_execution,
  OPT_driver_use_frontend_path,
  &lt;span class=&quot;c&quot;&gt;// ...182 more options.&lt;/span&gt;
};
&lt;/pre&gt;

&lt;p&gt;Every time a Swift compiler developer wanted to add or remove a Swift option, they'd have to manually add or remove it from that enum. That's not only tedious, it's also error-prone.&lt;/p&gt;

&lt;p&gt;Instead, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/include/Option/Options.h&lt;/code&gt; header defines the &lt;code&gt;&lt;span class=&quot;m&quot;&gt;OPTION&lt;/span&gt;&lt;/code&gt; macro such that it concatenates the tokens &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OPT_&amp;lt;option-identifier&amp;gt;&lt;/code&gt; for each definition in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Options.inc&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/2e6f878d099d9dc1f5ac1357df02e334c3c7b10f/include/swift/Option/Options.h#L24-L47&quot;&gt;swift/include/swift/Option/Options.h&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;24&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; swift {
&lt;span class=&quot;ln&quot;&gt;25&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; options {
&lt;span class=&quot;ln&quot;&gt;..&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;39&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; ID {
&lt;span class=&quot;ln&quot;&gt;40&lt;/span&gt;      OPT_INVALID = &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;41&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;42&lt;/span&gt;                 &lt;span class=&quot;ms&quot;&gt;HELPTEXT, METAVAR, VALUES)                                      \&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;43&lt;/span&gt;    &lt;span class=&quot;si&quot;&gt;OPT_##ID&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;44&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;swift/Option/Options.inc&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;45&lt;/span&gt;      LastOption
&lt;span class=&quot;ln&quot;&gt;46&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#undef OPTION&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;47&lt;/span&gt;    };
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This results in an enum with several hundred cases, one for each option defined in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Options.inc&lt;/code&gt;. Note that the macro definition of &lt;code&gt;&lt;span class=&quot;m&quot;&gt;OPTION&lt;/span&gt;&lt;/code&gt; above only uses the third argument passed into it, which it calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ID&lt;/code&gt;. For &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-driver-print-jobs&lt;/span&gt;&lt;/code&gt;, that third parameter is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;driver_print_jobs&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;m&quot;&gt;OPTION&lt;/span&gt;(
  &lt;span class=&quot;v&quot;&gt;prefix_1&lt;/span&gt;,
  &lt;span class=&quot;s&quot;&gt;&quot;driver-print-jobs&quot;&lt;/span&gt;,
  &lt;div class=&quot;hi&quot;&gt;&lt;span class=&quot;cn&quot;&gt;driver_print_jobs&lt;/span&gt;&lt;/div&gt;,
  &lt;span class=&quot;v&quot;&gt;Flag&lt;/span&gt;,
  &lt;span class=&quot;cn&quot;&gt;internal_debug_Group&lt;/span&gt;,
  &lt;span class=&quot;cn&quot;&gt;INVALID&lt;/span&gt;,
  &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;,
  &lt;span class=&quot;cn&quot;&gt;HelpHidden&lt;/span&gt; | &lt;span class=&quot;cn&quot;&gt;DoesNotAffectIncrementalBuild&lt;/span&gt;,
  &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;,
  &lt;span class=&quot;s&quot;&gt;&quot;Dump list of jobs to execute&quot;&lt;/span&gt;,
  &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;,
  &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;)
&lt;/pre&gt;

&lt;h2 id=&quot;stage-3-libswiftoption-instantiates-an-llvmoptopttable-with-an-llvmoptopttableinfo-element-for-each-of-the-options&quot;&gt;Stage 3: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libswiftOption&lt;/code&gt; instantiates an &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;opt&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;OptTable&lt;/span&gt;&lt;/code&gt;, with an &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;opt&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;OptTable&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Info&lt;/span&gt;&lt;/code&gt; element for each of the options&lt;/h2&gt;

&lt;p&gt;LLVM provides a library, named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libLLVMOption&lt;/code&gt;, that encapsulates common operations related to command-line argument parsing. For instance, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libLLVMOption&lt;/code&gt; defines the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;opt&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;OptTable&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;opt&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;InputArgList&lt;/span&gt;&lt;/code&gt; classes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;OptTable&lt;/span&gt;&lt;/code&gt; class is instantiated with a list of options to parse, and provides a method named &lt;code&gt;&lt;span class=&quot;f&quot;&gt;ParseArgs&lt;/span&gt;&lt;/code&gt;. This method takes the list of strings passed into an executable, compares them to the options the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;OptTable&lt;/span&gt;&lt;/code&gt; is supposed to parse, and returns an &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;InputArgList&lt;/span&gt;&lt;/code&gt; (as well as a list of arguments that could not be parsed).&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;&lt;span class=&quot;cl&quot;&gt;InputArgList&lt;/span&gt;&lt;/code&gt; defines a method named &lt;code&gt;&lt;span class=&quot;f&quot;&gt;hasArg&lt;/span&gt;&lt;/code&gt;. This method can be used to check whether an option was specified.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libswiftOption&lt;/code&gt; is responsible for instantiating an &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;opt&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;OptTable&lt;/span&gt;&lt;/code&gt; that's used to parse arguments passed to the &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt;&lt;/code&gt; executable. The &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;opt&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;OptTable&lt;/span&gt;&lt;/code&gt; initializer takes an array of options it's supposed to parse. These options are represented using the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;opt&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;OptTable&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Info&lt;/span&gt;&lt;/code&gt; struct:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift-llvm/blob/fe49d8f2cac91ebc77aed94a14f3b2e74e6678ad/include/llvm/Option/OptTable.h#L39-84&quot;&gt;llvm/include/llvm/Option/OptTable.h&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;39&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; OptTable {
&lt;span class=&quot;ln&quot;&gt;..&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;42&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; Info {
&lt;span class=&quot;ln&quot;&gt;..&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;45&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;const char&lt;/span&gt; *&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; *Prefixes;
&lt;span class=&quot;ln&quot;&gt;46&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;const char&lt;/span&gt; *Name;
&lt;span class=&quot;ln&quot;&gt;47&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;const char&lt;/span&gt; *HelpText;
&lt;span class=&quot;ln&quot;&gt;48&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;const char&lt;/span&gt; *MetaVar;
&lt;span class=&quot;ln&quot;&gt;49&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt; ID;
&lt;span class=&quot;ln&quot;&gt;50&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;unsigned char&lt;/span&gt; Kind;
&lt;span class=&quot;ln&quot;&gt;51&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;unsigned char&lt;/span&gt; Param;
&lt;span class=&quot;ln&quot;&gt;52&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;unsigned short&lt;/span&gt; Flags;
&lt;span class=&quot;ln&quot;&gt;53&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;unsigned short&lt;/span&gt; GroupID;
&lt;span class=&quot;ln&quot;&gt;54&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;unsigned short&lt;/span&gt; AliasID;
&lt;span class=&quot;ln&quot;&gt;55&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;const char&lt;/span&gt; *AliasArgs;
&lt;span class=&quot;ln&quot;&gt;56&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;const char&lt;/span&gt; *Values;
&lt;span class=&quot;ln&quot;&gt;57&lt;/span&gt;    };
&lt;span class=&quot;ln&quot;&gt;..&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;83&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;protected&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;84&lt;/span&gt;    OptTable(&lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;Info&lt;/span&gt;&amp;gt; OptionInfos, &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; IgnoreCase = &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;);
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;In order to create this array of options, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libswiftOption&lt;/code&gt; once again defines the &lt;code&gt;&lt;span class=&quot;m&quot;&gt;OPTION&lt;/span&gt;&lt;/code&gt; macro and includes the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Options.inc&lt;/code&gt; file. This time, it defines the &lt;code&gt;&lt;span class=&quot;m&quot;&gt;OPTION&lt;/span&gt;&lt;/code&gt; macro such that it &lt;a href=&quot;http://en.cppreference.com/w/cpp/language/list_initialization&quot;&gt;list-initializes&lt;/a&gt; an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OptTable::Info&lt;/code&gt; struct for each call, and it uses those to statically define an array named &lt;code&gt;&lt;span class=&quot;v&quot;&gt;InfoTable&lt;/span&gt;[]&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/2e6f878d099d9dc1f5ac1357df02e334c3c7b10f/lib/Option/Options.cpp#L13-L33&quot;&gt;swift/lib/Option/Options.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;13&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;swift/Option/Options.h&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;..&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;16&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;llvm/Option/OptTable.h&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;17&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;llvm/Option/Option.h&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;18&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;19&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;using namespace&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;options&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;20&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;using namespace&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;opt&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;..&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;26&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;static const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;OptTable&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Info&lt;/span&gt; InfoTable[] = {
&lt;span class=&quot;ln&quot;&gt;27&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;28&lt;/span&gt;                 &lt;span class=&quot;ms&quot;&gt;HELPTEXT, METAVAR, VALUES)                                      \&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;29&lt;/span&gt;    {PREFIX, NAME,  HELPTEXT,    METAVAR,     &lt;span class=&quot;si&quot;&gt;OPT_##ID&lt;/span&gt;,  &lt;span class=&quot;si&quot;&gt;Option::KIND##Class&lt;/span&gt;,    \
&lt;span class=&quot;ln&quot;&gt;30&lt;/span&gt;     PARAM,  FLAGS, &lt;span class=&quot;si&quot;&gt;OPT_##GROUP&lt;/span&gt;, &lt;span class=&quot;si&quot;&gt;OPT_##ALIAS&lt;/span&gt;, ALIASARGS, VALUES},
&lt;span class=&quot;ln&quot;&gt;31&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;swift/Option/Options.inc&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;32&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#undef OPTION&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;33&lt;/span&gt;  };
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;After pre-processing, the &lt;code&gt;&lt;span class=&quot;m&quot;&gt;OPTION&lt;/span&gt;&lt;/code&gt; macro calls are expanded such that the &lt;code&gt;&lt;span class=&quot;v&quot;&gt;InfoTable&lt;/span&gt;[]&lt;/code&gt; initializer above looks like this:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;k&quot;&gt;static const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;OptTable&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Info&lt;/span&gt; InfoTable[] = {
  {{&lt;span class=&quot;s&quot;&gt;&quot;-&quot;&lt;/span&gt;, &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;}, &lt;span class=&quot;s&quot;&gt;&quot;driver-print-jobs&quot;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&quot;Dump list of jobs to execute&quot;&lt;/span&gt;, &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;, &lt;span class=&quot;cn&quot;&gt;OPT_driver_print_jobs&lt;/span&gt;, &lt;span class=&quot;t&quot;&gt;Option&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;FlagClass&lt;/span&gt;, &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;cn&quot;&gt;HelpHidden&lt;/span&gt; | &lt;span class=&quot;cn&quot;&gt;DoesNotAffectIncrementalBuild&lt;/span&gt;, &lt;span class=&quot;cn&quot;&gt;OPT_internal_debug_Group&lt;/span&gt;, &lt;span class=&quot;cn&quot;&gt;OPT_INVALID&lt;/span&gt;, &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;, &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;},
  {{&lt;span class=&quot;s&quot;&gt;&quot;-&quot;&lt;/span&gt;, &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;}, &lt;span class=&quot;s&quot;&gt;&quot;driver-print-actions&quot;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&quot;Dump list of actions to perform&quot;&lt;/span&gt;, &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;, &lt;span class=&quot;cn&quot;&gt;OPT_driver_print_actions&lt;/span&gt;, &lt;span class=&quot;t&quot;&gt;Option&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;FlagClass&lt;/span&gt;, &lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;, &lt;span class=&quot;cn&quot;&gt;HelpHidden&lt;/span&gt; | &lt;span class=&quot;cn&quot;&gt;DoesNotAffectIncrementalBuild&lt;/span&gt;, &lt;span class=&quot;cn&quot;&gt;OPT_internal_debug_Group&lt;/span&gt;, &lt;span class=&quot;cn&quot;&gt;OPT_INVALID&lt;/span&gt;, &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;, &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;},
  &lt;span class=&quot;c&quot;&gt;// ...184 more options.&lt;/span&gt;
};
&lt;/pre&gt;

&lt;blockquote&gt;
  &lt;p&gt;Note that the enum values from stage two are used in these static option definitions: &lt;code&gt;&lt;span class=&quot;cn&quot;&gt;OPT_driver_print_jobs&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;cn&quot;&gt;OPT_driver_print_actions&lt;/span&gt;&lt;/code&gt;, and so on.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To allow other parts of the Swift compiler to have access to this table of options, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libswiftOption&lt;/code&gt; creates an &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;opt&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;OptTable&lt;/span&gt;&lt;/code&gt; subclass named &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;SwiftOptTable&lt;/span&gt;&lt;/code&gt;, and initializes it with the &lt;code&gt;&lt;span class=&quot;v&quot;&gt;InfoTable&lt;/span&gt;[]&lt;/code&gt; array from above:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/2e6f878d099d9dc1f5ac1357df02e334c3c7b10f/lib/Option/Options.cpp#L37-L40&quot;&gt;swift/lib/Option/Options.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;37&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; SwiftOptTable : &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;OptTable&lt;/span&gt; {
&lt;span class=&quot;ln&quot;&gt;38&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;39&lt;/span&gt;    SwiftOptTable() : &lt;span class=&quot;v&quot;&gt;OptTable&lt;/span&gt;(&lt;span class=&quot;v&quot;&gt;InfoTable&lt;/span&gt;) {}
&lt;span class=&quot;ln&quot;&gt;40&lt;/span&gt;  };
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;It also defines a function that allows other libraries to grab a reference to the option table:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/2e6f878d099d9dc1f5ac1357df02e334c3c7b10f/lib/Option/Options.cpp#L44-L46&quot;&gt;swift/lib/Option/Options.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;44&lt;/span&gt;  &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;OptTable&lt;/span&gt;&amp;gt; &lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::createSwiftOptTable() {
&lt;span class=&quot;ln&quot;&gt;45&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;OptTable&lt;/span&gt;&amp;gt;(&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;SwiftOptTable&lt;/span&gt;());
&lt;span class=&quot;ln&quot;&gt;46&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;stage-4-libswiftdriver-calls-the-llvmoptopttableparseargs-method&quot;&gt;Stage 4: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libswiftDriver&lt;/code&gt; calls the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;opt&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;OptTable&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;ParseArgs&lt;/span&gt;&lt;/code&gt; method&lt;/h2&gt;

&lt;p&gt;As I briefly mentioned in &lt;a href=&quot;/reading-and-understanding-the-swift-driver-source-code&quot;&gt;the previous article in this series&lt;/a&gt;, the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;&lt;/code&gt; initializer calls the &lt;code&gt;&lt;span class=&quot;f&quot;&gt;createSwiftOptTable&lt;/span&gt;&lt;/code&gt; function in order to get a reference to the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;opt&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;OptTable&lt;/span&gt;&lt;/code&gt; subclass &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;SwiftOptTable&lt;/span&gt;&lt;/code&gt;, storing it in an ivar named &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::&lt;span class=&quot;v&quot;&gt;Opts&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/2e6f878d099d9dc1f5ac1357df02e334c3c7b10f/lib/Driver/Driver.cpp#L64-L68&quot;&gt;swift/lib/Driver/Driver.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;64&lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::Driver(&lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt; DriverExecutable,
&lt;span class=&quot;ln&quot;&gt;65&lt;/span&gt;                 &lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt; Name,
&lt;span class=&quot;ln&quot;&gt;66&lt;/span&gt;                 &lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;const char&lt;/span&gt; *&amp;gt; Args,
&lt;span class=&quot;ln&quot;&gt;67&lt;/span&gt;                 &lt;span class=&quot;cl&quot;&gt;DiagnosticEngine&lt;/span&gt; &amp;amp;Diags)
&lt;span class=&quot;ln&quot;&gt;68&lt;/span&gt;    : &lt;span class=&quot;v&quot;&gt;Opts&lt;/span&gt;(&lt;span class=&quot;f&quot;&gt;createSwiftOptTable&lt;/span&gt;()), &lt;span class=&quot;v&quot;&gt;Diags&lt;/span&gt;(Diags),
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Then, the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;&lt;/code&gt; has the command-line arguments to the &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt;&lt;/code&gt; executable parsed, in order to create and configure an instance of &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt;&lt;/code&gt;. To parse the arguments, it calls the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;opt&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;OptTable&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;ParseArgs&lt;/span&gt;&lt;/code&gt; method:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/2e6f878d099d9dc1f5ac1357df02e334c3c7b10f/lib/Driver/Driver.cpp#L841-L889&quot;&gt;swift/lib/Driver/Driver.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt; 841&lt;/span&gt;  &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;InputArgList&lt;/span&gt;&amp;gt;
&lt;span class=&quot;ln&quot;&gt; 842&lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::parseArgStrings(&lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;const char&lt;/span&gt; *&amp;gt; Args) {
&lt;span class=&quot;ln&quot;&gt; ...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 854&lt;/span&gt;    ArgList = &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;make_unique&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;InputArgList&lt;/span&gt;&amp;gt;(
&lt;span class=&quot;ln&quot;&gt; 855&lt;/span&gt;        &lt;span class=&quot;f&quot;&gt;getOpts&lt;/span&gt;().&lt;span class=&quot;f&quot;&gt;ParseArgs&lt;/span&gt;(Args, MissingArgIndex, MissingArgCount,
&lt;span class=&quot;ln&quot;&gt; 856&lt;/span&gt;                            IncludedFlagsBitmask, ExcludedFlagsBitmask));
&lt;span class=&quot;ln&quot;&gt; ...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 888&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; ArgList;
&lt;span class=&quot;ln&quot;&gt; 889&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;InputArgList&lt;/span&gt;&lt;/code&gt; returned by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Driver::parseArgStrings&lt;/code&gt; method is used throughout &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libswiftDriver&lt;/code&gt;. For example, &lt;a href=&quot;/reading-and-understanding-the-swift-driver-source-code&quot;&gt;the previous article in this series&lt;/a&gt; showcased the following code, which produced a warning if the &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-incremental&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-whole-module-optimization&lt;/span&gt;&lt;/code&gt; arguments were used in the same invocation:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/2e6f878d099d9dc1f5ac1357df02e334c3c7b10f/lib/Driver/Driver.cpp#L841-L889&quot;&gt;swift/lib/Driver/Driver.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;529&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; Incremental = ArgList-&amp;gt;&lt;span class=&quot;f&quot;&gt;hasArg&lt;/span&gt;(&lt;span class=&quot;t&quot;&gt;options&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;OPT_incremental&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;530&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (ArgList-&amp;gt;&lt;span class=&quot;f&quot;&gt;hasArg&lt;/span&gt;(&lt;span class=&quot;t&quot;&gt;options&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;OPT_whole_module_optimization&lt;/span&gt;)) {
&lt;span class=&quot;ln&quot;&gt;531&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (Incremental &amp;amp;&amp;amp; ShowIncrementalBuildDecisions) {
&lt;span class=&quot;ln&quot;&gt;532&lt;/span&gt;      &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;outs&lt;/span&gt;() &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot;Incremental compilation has been disabled, because it &quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;533&lt;/span&gt;                   &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot;is not compatible with whole module optimization.&quot;&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;534&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;535&lt;/span&gt;    Incremental = &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;536&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The code above uses the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;opt&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;InputArgList&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;hasArg&lt;/span&gt;&lt;/code&gt; method to check for the &lt;code&gt;&lt;span class=&quot;cn&quot;&gt;OPT_incremental&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;cn&quot;&gt;OPT_whole_module_optimization&lt;/span&gt;&lt;/code&gt; arguments. Remember, these were cases that were added to the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;options&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;ID&lt;/span&gt;&lt;/code&gt; enum by including &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Options.inc&lt;/code&gt; in stage two above! It all comes toghether here.&lt;/p&gt;

&lt;p&gt;Besides checking for the existence of certain options, &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;InputArgList&lt;/span&gt;&lt;/code&gt; also has methods to grab the values specified by those methods. Here's how &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libswiftFrontend&lt;/code&gt; grabs the value from the popular &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-warn-long-function-bodies=&lt;/span&gt;&lt;/code&gt; command-line option, by using the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;opt&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;InputArgList&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getLastArg&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;opt&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Arg&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getValue&lt;/span&gt;&lt;/code&gt; methods:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/2e6f878d099d9dc1f5ac1357df02e334c3c7b10f/lib/Frontend/CompilerInvocation.cpp#L841-L889&quot;&gt;swift/lib/Frontend/CompilerInvocation.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt; 178&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Arg&lt;/span&gt; *A = Args.&lt;span class=&quot;f&quot;&gt;getLastArg&lt;/span&gt;(&lt;span class=&quot;cn&quot;&gt;OPT_warn_long_function_bodies&lt;/span&gt;)) {
&lt;span class=&quot;ln&quot;&gt; 179&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;unsigned&lt;/span&gt; attempt;
&lt;span class=&quot;ln&quot;&gt; 180&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt;(A-&amp;gt;&lt;span class=&quot;f&quot;&gt;getValue&lt;/span&gt;()).&lt;span class=&quot;f&quot;&gt;getAsInteger&lt;/span&gt;(&lt;span class=&quot;num&quot;&gt;10&lt;/span&gt;, attempt)) {
&lt;span class=&quot;ln&quot;&gt; 181&lt;/span&gt;      Diags.&lt;span class=&quot;f&quot;&gt;diagnose&lt;/span&gt;(&lt;span class=&quot;cl&quot;&gt;SourceLoc&lt;/span&gt;(), &lt;span class=&quot;t&quot;&gt;diag&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;error_invalid_arg_value&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt; 182&lt;/span&gt;                     A-&amp;gt;&lt;span class=&quot;f&quot;&gt;getAsString&lt;/span&gt;(Args), A-&amp;gt;&lt;span class=&quot;f&quot;&gt;getValue&lt;/span&gt;());
&lt;span class=&quot;ln&quot;&gt; 183&lt;/span&gt;    } &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; {
&lt;span class=&quot;ln&quot;&gt; 184&lt;/span&gt;      &lt;span class=&quot;v&quot;&gt;Opts&lt;/span&gt;.&lt;span class=&quot;v&quot;&gt;WarnLongFunctionBodies&lt;/span&gt; = attempt;
&lt;span class=&quot;ln&quot;&gt; 185&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt; 186&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;sorry-no-magic-here&quot;&gt;Sorry, no magic here&lt;/h2&gt;

&lt;p&gt;I enjoy looking into the details of the Swift compiler because – and maybe this sounds silly – it helps me better understand that it's &quot;just a program&quot;.&lt;/p&gt;

&lt;p&gt;Because I was unfamilar with the LLVM TableGen utility, and with the C/C++ macros that the Swift compiler uses to define its options, it seemed like magic to me that modifying the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Options.td&lt;/code&gt; file would result in changes to Swift's command-line options. But it's not magic – as this article described, it's a four-stage process in which:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Options.td&lt;/code&gt; file is transformed by TableGen.&lt;/li&gt;
  &lt;li&gt;The transformed file, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Options.inc&lt;/code&gt;, is included such that it defines a large enum with all the Swift options as values.&lt;/li&gt;
  &lt;li&gt;The transformed file is included again, this time to intiialize an LLVM &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;OptTable&lt;/span&gt;&lt;/code&gt;. This class is capable of searching command-line arguments for option values.&lt;/li&gt;
  &lt;li&gt;The rest of the Swift compiler codebase uses the LLVM &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;OptTable&lt;/span&gt;&lt;/code&gt; class to check for arguments as necessary.&lt;/li&gt;
&lt;/ol&gt;</content><author><name></name></author><category term="swiftc" /><summary type="html">The last article in this series explained how libswiftDriver split up swift executable invocations into smaller sub-jobs. Parsing command-line arguments is a big part of that work, but I didn't go into much detail about it. This article will now explain command-line argument parsing in depth.</summary></entry><entry><title type="html">Reading and Understanding the Swift Driver Source Code</title><link href="https://modocache.io/reading-and-understanding-the-swift-driver-source-code" rel="alternate" type="text/html" title="Reading and Understanding the Swift Driver Source Code" /><published>2017-11-25T05:00:00+00:00</published><updated>2017-11-25T05:00:00+00:00</updated><id>https://modocache.io/reading-and-understanding-the-swift-driver-source-code</id><content type="html" xml:base="https://modocache.io/reading-and-understanding-the-swift-driver-source-code">&lt;p&gt;In &lt;a href=&quot;/introduction-to-the-swift-compiler-driver&quot;&gt;the previous article&lt;/a&gt; of this running series on the Swift compiler, I introduced the Swift compiler driver. To recap: the driver is the executable that is run when users invoke &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt;&lt;/code&gt; on the command line. It's responsible for splitting up a single &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt;&lt;/code&gt; invocation into multiple child jobs. These jobs are command line invocations of &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;cmd&quot;&gt;ld&lt;/span&gt;&lt;/code&gt;, or other command-line utilities.&lt;/p&gt;

&lt;p&gt;This article explains the details of how the Swift driver executable and libswiftDriver accomplish this. Specifically, I'll explain the code that is executed when I run &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt; hello.swift&lt;/code&gt; on the command line.&lt;/p&gt;

&lt;p&gt;I've found that understanding this process has made it easier for me to fix &lt;a href=&quot;https://bugs.swift.org/issues/?jql=labels+%3D+Driver&quot;&gt;Swift JIRA bugs labeled &quot;Driver&quot;&lt;/a&gt;. Please let me know if this article helps you do the same!&lt;/p&gt;

&lt;h2 id=&quot;the-six-stages-of-the-swift-driver&quot;&gt;The six stages of the Swift driver&lt;/h2&gt;

&lt;p&gt;I think of the driver as having six main stages, in which it:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Checks whether it needs to be split up:&lt;/strong&gt; The driver checks whether the current invocation of &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt;&lt;/code&gt; should be split up into jobs, or whether it's currently being run as one of those jobs. In other words, it checks whether it's being run as &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt;&lt;/code&gt; (and needs to be split up), or as &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt; (and so has already been split up). In our case, &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt; hello.swift&lt;/code&gt; is not an invocation of &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt;, and so the driver will determine it needs to be split up.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Instantiates a &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;&lt;/code&gt;:&lt;/strong&gt; If the invocation needs to be split up into jobs by the driver, a &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;&lt;/code&gt; object is instantiated, and its intializer determines the &quot;driver mode&quot; (explained in the &lt;a href=&quot;/introduction-to-the-swift-compiler-driver&quot;&gt;previous article&lt;/a&gt;).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Instantiates a &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt;&lt;/code&gt;:&lt;/strong&gt; Assuming a driver mode of &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt;&lt;/code&gt;, the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;buildCompilation&lt;/span&gt;&lt;/code&gt; method is called. This parses command-line options to create a &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt;&lt;/code&gt; object, which encapsulates the information required to build out a set of jobs. One of the most important pieces of information stored at this point is a mapping of inputs to desired outputs.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Splits up the work of a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt;&lt;/code&gt; into a graph of &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Action&lt;/span&gt;&lt;/code&gt; objects:&lt;/strong&gt; The &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;buildActions&lt;/span&gt;&lt;/code&gt; method creates a graph of &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Action&lt;/span&gt;&lt;/code&gt; objects. These represent smaller unit of work, such as &quot;compile this Swift source file into an object&quot; and &quot;link these objects into an executable.&quot; The actions for any given &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt;&lt;/code&gt; invocation can be examined with the &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-driver-print-actions&lt;/span&gt;&lt;/code&gt; option.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Instantiates a list of &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Job&lt;/span&gt;&lt;/code&gt; based on those actions:&lt;/strong&gt; Actions contain all the information necessary for a &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt;&lt;/code&gt; to instantiate a &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Job&lt;/span&gt;&lt;/code&gt;, which represents the actual command-line invocation used to run a child job. To translate actions into jobs, the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;buildJobs&lt;/span&gt;&lt;/code&gt; method is invoked. As explained in &lt;a href=&quot;/introduction-to-the-swift-compiler-driver&quot;&gt;the previous article&lt;/a&gt;, the jobs for any given &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt;&lt;/code&gt; invocation can be exampled with the &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-driver-print-jobs&lt;/span&gt;&lt;/code&gt; option.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Executes each of the list of &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Job&lt;/span&gt;&lt;/code&gt;:&lt;/strong&gt; Finally, the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;petformJobs&lt;/span&gt;&lt;/code&gt; method is called. This method runs each of the jobs within a task queue.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
  &lt;p&gt;The &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; repository includes a document named &lt;a href=&quot;https://github.com/apple/swift/blob/f69bc0eb14694e550a2a716d2d5a2ea134202031/docs/DriverInternals.rst&quot;&gt;Driver Design &amp;amp; Internals&lt;/a&gt; that describes the Swift 2.0 driver as being composed of four stages. I prefer to think of it as six stages, because I like to break the stages down more granularly – my stages one through three correspond to that document's stage one.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;stage-1-checking-whether-the-current-swift-invocation-needs-to-be-split-up-by-the-driver&quot;&gt;Stage 1: Checking whether the current &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt;&lt;/code&gt; invocation needs to be split up by the driver&lt;/h2&gt;

&lt;p&gt;I'll begin where the &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt;&lt;/code&gt; executable (and every C-based program) begins: the &lt;code&gt;&lt;span class=&quot;f&quot;&gt;main&lt;/span&gt;&lt;/code&gt; function.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;It's important to note that I'll elide many lines of source code that aren't immediately relevant to the six stages of the driver. For example, the very first thing the driver does is call the &lt;code&gt;&lt;span class=&quot;m&quot;&gt;INITIALIZE_LLVM&lt;/span&gt;&lt;/code&gt; macro. The Swift compiler would not function without this line of code, but because it's not crucial to understanding the Swift driver, I won't go into that macro here.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;11-checking-if-the-invocation-is-trying-to-run-a-subcommand&quot;&gt;1.1: Checking if the invocation is trying to run a &quot;subcommand&quot;&lt;/h3&gt;

&lt;p&gt;One of the first things &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt;&lt;/code&gt; does in &lt;code&gt;&lt;span class=&quot;f&quot;&gt;main&lt;/span&gt;&lt;/code&gt; is check whether it's being run as a &quot;subcommand&quot;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/f69bc0eb14694e550a2a716d2d5a2ea134202031/tools/driver/driver.cpp#L111-L126&quot;&gt;swift/tools/driver/driver.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;111&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; main(&lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; argc_, &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; **argv_) {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;124&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt; ExecName = &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;sys&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;path&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;stem&lt;/span&gt;(argv[&lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;]);
&lt;span class=&quot;ln&quot;&gt;125&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;SmallString&lt;/span&gt;&amp;lt;&lt;span class=&quot;num&quot;&gt;256&lt;/span&gt;&amp;gt; SubcommandName;
&lt;span class=&quot;ln&quot;&gt;126&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;f&quot;&gt;shouldRunAsSubcommand&lt;/span&gt;(ExecName, SubcommandName, argv)) {
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&quot;Subcommands&quot; here to refer to commands like &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;build&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;test&lt;/span&gt;&lt;/code&gt;. The &lt;code&gt;&lt;span class=&quot;f&quot;&gt;shouldRunAsSubcommand&lt;/span&gt;&lt;/code&gt; function checks the first two command-line arguments and, if they fit a certain pattern, it returns an executable name based on them. For example, an invocation that begins with &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;build&lt;/span&gt;&lt;/code&gt; would result in this function returning &lt;code&gt;&lt;span class=&quot;s&quot;&gt;&quot;swift-build&quot;&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/f69bc0eb14694e550a2a716d2d5a2ea134202031/tools/driver/driver.cpp#L70-L107&quot;&gt;swift/tools/driver/driver.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt; 70&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; shouldRunAsSubcommand(&lt;span class=&quot;cl&quot;&gt;&lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt;&lt;/span&gt; ExecName,
&lt;span class=&quot;ln&quot;&gt; 71&lt;/span&gt;                                    &lt;span class=&quot;cl&quot;&gt;SmallString&lt;/span&gt;&amp;lt;&lt;span class=&quot;num&quot;&gt;256&lt;/span&gt;&amp;gt; &amp;amp;SubcommandName,
&lt;span class=&quot;ln&quot;&gt; 72&lt;/span&gt;                                    &lt;span class=&quot;cl&quot;&gt;SmallVectorImpl&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; *&amp;gt; &amp;amp;Args) {
&lt;span class=&quot;ln&quot;&gt; ..&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 78&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (ExecName != &lt;span class=&quot;s&quot;&gt;&quot;swift&quot;&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt; 79&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt; ..&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt; 87&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt; FirstArg(Args[&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;]);
&lt;span class=&quot;ln&quot;&gt; 88&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (FirstArg.&lt;span class=&quot;f&quot;&gt;startswith&lt;/span&gt;(&lt;span class=&quot;s&quot;&gt;&quot;-&quot;&lt;/span&gt;) || FirstArg.&lt;span class=&quot;f&quot;&gt;find&lt;/span&gt;(&lt;span class=&quot;ch&quot;&gt;'.'&lt;/span&gt;) != &lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;npos&lt;/span&gt; ||
&lt;span class=&quot;ln&quot;&gt; 89&lt;/span&gt;        FirstArg.&lt;span class=&quot;f&quot;&gt;find&lt;/span&gt;(&lt;span class=&quot;ch&quot;&gt;'/'&lt;/span&gt;) != &lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;npos&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt; 90&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;103&lt;/span&gt;    SubcommandName.&lt;span class=&quot;f&quot;&gt;assign&lt;/span&gt;(&lt;span class=&quot;s&quot;&gt;&quot;swift-&quot;&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;104&lt;/span&gt;    SubcommandName.&lt;span class=&quot;f&quot;&gt;append&lt;/span&gt;(Subcommand);
&lt;span class=&quot;ln&quot;&gt;105&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;106&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;107&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;There are two things to note here:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The Swift driver only considers invocations that begin with &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt;&lt;/code&gt; as potential subcommand invocations. So &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;build&lt;/span&gt;&lt;/code&gt; would not be considered a subcommand.&lt;/li&gt;
  &lt;li&gt;Invocations whose second argument contains a period, or that start with a dash, as not considered subcommands. So &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; hello.swift&amp;lt;/span&amp;gt;&lt;/code&gt; would not be evaluated as a subcommand.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If the driver determines that it is running a subcommand, such as &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;build&lt;/span&gt;&lt;/code&gt;, it finds an executable named &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift-build&lt;/span&gt;&lt;/code&gt; in the same directory as the &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt;&lt;/code&gt; executable currently being run, and it executes it and immediately exits the program by calling the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;ExecuteInPlace&lt;/span&gt;&lt;/code&gt; function:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/f69bc0eb14694e550a2a716d2d5a2ea134202031/tools/driver/driver.cpp#L126-L154&quot;&gt;swift/tools/driver/driver.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;111&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; main(&lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; argc_, &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; **argv_) {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;126&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;f&quot;&gt;shouldRunAsSubcommand&lt;/span&gt;(ExecName, SubcommandName, argv)) {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;129&lt;/span&gt;      &lt;span class=&quot;cl&quot;&gt;SmallString&lt;/span&gt;&amp;lt;&lt;span class=&quot;num&quot;&gt;256&lt;/span&gt;&amp;gt; SubcommandPath(
&lt;span class=&quot;ln&quot;&gt;130&lt;/span&gt;        &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;sys&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;path&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parent_path&lt;/span&gt;(&lt;span class=&quot;f&quot;&gt;getExecutablePath&lt;/span&gt;(argv[&lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;])));
&lt;span class=&quot;ln&quot;&gt;131&lt;/span&gt;      &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;sys&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;path&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;append&lt;/span&gt;(SubcommandPath, SubcommandName);
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;146&lt;/span&gt;      argv.&lt;span class=&quot;f&quot;&gt;push_back&lt;/span&gt;(&lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;147&lt;/span&gt;      &lt;span class=&quot;f&quot;&gt;ExecuteInPlace&lt;/span&gt;(SubcommandPath.&lt;span class=&quot;f&quot;&gt;c_str&lt;/span&gt;(), argv.&lt;span class=&quot;f&quot;&gt;data&lt;/span&gt;());
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;154&lt;/span&gt;    }
&lt;/pre&gt;
&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;This is a fun quirk about how the Swift compiler works: if you invoke it with &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;foo&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;hello&lt;/span&gt;&lt;/code&gt;, it'll interpret those as subcommand invocations. This means the driver will attempt to invoke an executable named &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift-foo&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift-hello&lt;/span&gt;&lt;/code&gt;. You can try this yourself by creating an executable named &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift-goodjob&lt;/span&gt;&lt;/code&gt; next to your built Swift executable:&lt;/p&gt;

  &lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;/path/to/your/swift-macosx-x86_64/bin/swift-goodjob&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;c&quot;&gt;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class=&quot;cmd&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Keep up the good work!&quot;&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

  &lt;p&gt;Make the file executable by running &lt;code&gt;&lt;span class=&quot;cmd&quot;&gt;chmod&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;a+x&lt;/span&gt; /path/to/your/swift-macosx-x86_64/bin/swift-goodjob&lt;/code&gt; on the command line, and you'll be able to invoke it as a Swift subcommand:&lt;/p&gt;

  &lt;pre&gt;
&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;goodjob&lt;/span&gt;
&lt;/pre&gt;

  &lt;p&gt;Invoking it results in a reaffirming message:&lt;/p&gt;

  &lt;pre&gt;
Keep up the good work!
&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;12-checking-if-the-invocation-is-for-integrated-tools-like-swift--frontend&quot;&gt;1.2: Checking if the invocation is for &quot;integrated tools&quot; like &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;When I invoke &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt; hello.swift&lt;/code&gt; on the command line, it's not evaluated as a subcommand for two reasons:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;I'm invoking &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt;&lt;/code&gt;, not &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt;&lt;/code&gt;. Only &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;&amp;lt;subcommand-name&amp;gt;&lt;/span&gt;&lt;/code&gt; invocations are considered potential subcommands.&lt;/li&gt;
  &lt;li&gt;The second argument, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.swift&lt;/code&gt;, contains a period. The code I listed above explicitly discounts invocations whose second command contains a period.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Since &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt; hello.swift&lt;/code&gt; isn't considered a subcommand, the driver would continue by checking whether &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt; hello.swift&lt;/code&gt; needs to be split up into child jobs. The only &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; in which this &lt;em&gt;isn't&lt;/em&gt; necessary is when &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt;&lt;/code&gt; is being invoked as &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-modulewrap&lt;/span&gt;&lt;/code&gt;, or &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-apinotes&lt;/span&gt;&lt;/code&gt;. Each of these are considered to have already been split up.&lt;/p&gt;

&lt;p&gt;Therefore one of the first things the Swift driver does, after checking whether it should execute a subcommand, is check whether it should execute the &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt; code path:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/f69bc0eb14694e550a2a716d2d5a2ea134202031/tools/driver/driver.cpp#L158-L172&quot;&gt;swift/tools/driver/driver.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;111&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; main(&lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; argc_, &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; **argv_) {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// ...checks whether to run a subcommand.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;158&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt; FirstArg(argv[&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;]);
&lt;span class=&quot;ln&quot;&gt;159&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (FirstArg == &lt;span class=&quot;s&quot;&gt;&quot;-frontend&quot;&lt;/span&gt;) {
&lt;span class=&quot;ln&quot;&gt;160&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;f&quot;&gt;performFrontend&lt;/span&gt;(&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;makeArrayRef&lt;/span&gt;(argv.&lt;span class=&quot;f&quot;&gt;data&lt;/span&gt;()+&lt;span class=&quot;num&quot;&gt;2&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;161&lt;/span&gt;                                                argv.&lt;span class=&quot;f&quot;&gt;data&lt;/span&gt;()+argv.&lt;span class=&quot;f&quot;&gt;size&lt;/span&gt;()),
&lt;span class=&quot;ln&quot;&gt;162&lt;/span&gt;                             argv[&lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;], (&lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; *)(&lt;span class=&quot;ts&quot;&gt;intptr_t&lt;/span&gt;)&lt;span class=&quot;f&quot;&gt;getExecutablePath&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;163&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;164&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (FirstArg == &lt;span class=&quot;s&quot;&gt;&quot;-modulewrap&quot;&lt;/span&gt;) {
&lt;span class=&quot;ln&quot;&gt;165&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;f&quot;&gt;modulewrap_main&lt;/span&gt;(&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;makeArrayRef&lt;/span&gt;(argv.&lt;span class=&quot;f&quot;&gt;data&lt;/span&gt;()+&lt;span class=&quot;num&quot;&gt;2&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;166&lt;/span&gt;                                                argv.&lt;span class=&quot;f&quot;&gt;data&lt;/span&gt;()+argv.&lt;span class=&quot;f&quot;&gt;size&lt;/span&gt;()),
&lt;span class=&quot;ln&quot;&gt;167&lt;/span&gt;                             argv[&lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;], (&lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; *)(&lt;span class=&quot;ts&quot;&gt;intptr_t&lt;/span&gt;)&lt;span class=&quot;f&quot;&gt;getExecutablePath&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;168&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;169&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (FirstArg == &lt;span class=&quot;s&quot;&gt;&quot;-apinotes&quot;&lt;/span&gt;) {
&lt;span class=&quot;ln&quot;&gt;170&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;f&quot;&gt;apinotes_main&lt;/span&gt;(&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;makeArrayRef&lt;/span&gt;(argv.&lt;span class=&quot;f&quot;&gt;data&lt;/span&gt;()+1,
&lt;span class=&quot;ln&quot;&gt;171&lt;/span&gt;                                              argv.&lt;span class=&quot;f&quot;&gt;data&lt;/span&gt;()+argv.&lt;span class=&quot;f&quot;&gt;size&lt;/span&gt;()));
&lt;span class=&quot;ln&quot;&gt;172&lt;/span&gt;    }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The first code path in the &lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;/code&gt; statement, for &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt;, calls the &lt;code&gt;&lt;span class=&quot;f&quot;&gt;performFrontend&lt;/span&gt;&lt;/code&gt; function. This kicks off everything I think of when I think of &quot;compiling Swift code&quot;: parsing the source code, building an abstract syntax tree, type checking, and so on.&lt;/p&gt;

&lt;p&gt;I'll cover the frontend in a future article. For now, the driver has determined that my &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt; hello.swift&lt;/code&gt; invocation probably needs to be split up, and so it continues to stage two.&lt;/p&gt;

&lt;h2 id=&quot;stage-2-instantiating-a-swiftdriver&quot;&gt;Stage 2: Instantiating a &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;The logic behind splitting up my &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt; hello.swift&lt;/code&gt; invocation is handled by an instance of &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;&lt;/code&gt;, which the code in &lt;code&gt;&lt;span class=&quot;f&quot;&gt;main&lt;/span&gt;&lt;/code&gt; proceeds to instantiate:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/f69bc0eb14694e550a2a716d2d5a2ea134202031/tools/driver/driver.cpp#L183&quot;&gt;swift/tools/driver/driver.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;111&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; main(&lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; argc_, &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; **argv_) {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// ...checks whether to run a subcommand,&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// or whether to execute the compiler frontend.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;182&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;183&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt; TheDriver(Path, ExecName, argv, Diags);
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;&lt;/code&gt; initializer does two things:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;It instantiates a table of Swift option flags. (In order to do the explanation justice, I'll describe option tables and option parsing in a future article.)&lt;/li&gt;
  &lt;li&gt;It determines the &quot;driver mode&quot; it's being run under. Recall that &lt;a href=&quot;/introduction-to-the-swift-compiler-driver&quot;&gt;the previous article&lt;/a&gt; explained how the name of the executable (and the &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;--driver-mode=&lt;/span&gt;&lt;/code&gt; option) is used to determine how the driver behaves.&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/f69bc0eb14694e550a2a716d2d5a2ea134202031/lib/Driver/Driver.cpp#L64-L75&quot;&gt;swift/lib/Driver/Driver.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;64&lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::Driver(&lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt; DriverExecutable,
&lt;span class=&quot;ln&quot;&gt;65&lt;/span&gt;                 &lt;span class=&quot;cl&quot;&gt;StringRef&lt;/span&gt; Name,
&lt;span class=&quot;ln&quot;&gt;66&lt;/span&gt;                 &lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; *&amp;gt; Args,
&lt;span class=&quot;ln&quot;&gt;67&lt;/span&gt;                 &lt;span class=&quot;cl&quot;&gt;DiagnosticEngine&lt;/span&gt; &amp;amp;Diags)
&lt;span class=&quot;ln&quot;&gt;68&lt;/span&gt;    : &lt;span class=&quot;v&quot;&gt;Opts&lt;/span&gt;(&lt;span class=&quot;f&quot;&gt;createSwiftOptTable&lt;/span&gt;()), &lt;span class=&quot;v&quot;&gt;Diags&lt;/span&gt;(Diags),
&lt;span class=&quot;ln&quot;&gt;69&lt;/span&gt;      &lt;span class=&quot;v&quot;&gt;Name&lt;/span&gt;(Name), &lt;span class=&quot;v&quot;&gt;DriverExecutable&lt;/span&gt;(DriverExecutable),
&lt;span class=&quot;ln&quot;&gt;70&lt;/span&gt;      &lt;span class=&quot;v&quot;&gt;DefaultTargetTriple&lt;/span&gt;(&lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;sys&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;getDefaultTargetTriple&lt;/span&gt;()) {
&lt;span class=&quot;ln&quot;&gt;..&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;74&lt;/span&gt;    &lt;span class=&quot;f&quot;&gt;parseDriverKind&lt;/span&gt;(Args.&lt;span class=&quot;f&quot;&gt;slice&lt;/span&gt;(&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;));
&lt;span class=&quot;ln&quot;&gt;75&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Once the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;&lt;/code&gt; is instantiated, the driver executable determines what to do based on its driver mode: a mode of &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift-format&lt;/span&gt;&lt;/code&gt; results in an early exit after calling &lt;code&gt;&lt;span class=&quot;f&quot;&gt;swift_format_main&lt;/span&gt;&lt;/code&gt;, for example.&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/f69bc0eb14694e550a2a716d2d5a2ea134202031/tools/driver/driver.cpp#L183-L195&quot;&gt;swift/tools/driver/driver.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;111&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; main(&lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; argc_, &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; **argv_) {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// ...checks whether to run a subcommand,&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// or whether to execute the compiler frontend.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;182&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;183&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt; TheDriver(Path, ExecName, argv, Diags);
&lt;span class=&quot;ln&quot;&gt;184&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; (TheDriver.&lt;span class=&quot;f&quot;&gt;getDriverKind&lt;/span&gt;()) {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;189&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;DriverKind&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;SwiftFormat&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;190&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;f&quot;&gt;swift_format_main&lt;/span&gt;(
&lt;span class=&quot;ln&quot;&gt;191&lt;/span&gt;        TheDriver.&lt;span class=&quot;f&quot;&gt;getArgsWithoutProgramNameAndDriverMode&lt;/span&gt;(argv),
&lt;span class=&quot;ln&quot;&gt;192&lt;/span&gt;        argv[&lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;], (&lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; *)(&lt;span class=&quot;ts&quot;&gt;intptr_t&lt;/span&gt;)&lt;span class=&quot;f&quot;&gt;getExecutablePath&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;193&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;194&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;195&lt;/span&gt;    }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;If you're interested in how &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift-format&lt;/span&gt;&lt;/code&gt; works, just follow the code in the &lt;code&gt;&lt;span class=&quot;f&quot;&gt;swift_format_main&lt;/span&gt;&lt;/code&gt; function to find out. &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt; hello.swift&lt;/code&gt;, on the other hand, results in a driver mode of &lt;code&gt;&lt;span class=&quot;t&quot;&gt;DriverKind&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;Batch&lt;/span&gt;&lt;/code&gt;, and so this early return isn't taken. Instead, the driver continues its work of splitting up my invocation. To do so, it'll create a &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt;&lt;/code&gt; object.&lt;/p&gt;

&lt;h2 id=&quot;stage-3-instantiating-a-swiftcompilation&quot;&gt;Stage 3: Instantiating a &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt;&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;The driver uses an instance of &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt;&lt;/code&gt; to build up and a store a list of jobs. To begin, it calls the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;buildCompilation&lt;/span&gt;&lt;/code&gt; method:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/f69bc0eb14694e550a2a716d2d5a2ea134202031/tools/driver/driver.cpp#L197&quot;&gt;swift/tools/driver/driver.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;111&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; main(&lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; argc_, &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; **argv_) {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// ...checks whether to run a subcommand,&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// or whether to execute the compiler frontend,&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// and then instantiates a Driver object and&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// checks whether to return early for swift-format.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;196&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;197&lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt;&amp;gt; C = TheDriver.&lt;span class=&quot;f&quot;&gt;buildCompilation&lt;/span&gt;(argv);
&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;31-parsing-and-validating-command-line-arguments&quot;&gt;3.1: Parsing and validating command-line arguments&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;buildCompilation&lt;/span&gt;&lt;/code&gt; method parses the command-line arguments passed into the original &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt;&lt;/code&gt; invocation, by calling the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;parseArgStrings&lt;/span&gt;&lt;/code&gt; method. It then validates those arguments. For example, the &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-incremental&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-whole-module-optimization&lt;/span&gt;&lt;/code&gt; options are mutually exclusive, so it prints a warning if they're used together:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/f69bc0eb14694e550a2a716d2d5a2ea134202031/lib/Driver/Driver.cpp#L504-L536&quot;&gt;swift/lib/Driver/Driver.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;504&lt;/span&gt;  &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt;&amp;gt; &lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::buildCompilation(
&lt;span class=&quot;ln&quot;&gt;505&lt;/span&gt;      &lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; *&amp;gt; Args) {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;510&lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;InputArgList&lt;/span&gt;&amp;gt; ArgList(&lt;span class=&quot;f&quot;&gt;parseArgStrings&lt;/span&gt;(Args.&lt;span class=&quot;f&quot;&gt;slice&lt;/span&gt;(&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;)));
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;529&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; Incremental = ArgList-&amp;gt;&lt;span class=&quot;f&quot;&gt;hasArg&lt;/span&gt;(&lt;span class=&quot;t&quot;&gt;options&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;OPT_incremental&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;530&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (ArgList-&amp;gt;&lt;span class=&quot;f&quot;&gt;hasArg&lt;/span&gt;(&lt;span class=&quot;t&quot;&gt;options&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;OPT_whole_module_optimization&lt;/span&gt;)) {
&lt;span class=&quot;ln&quot;&gt;531&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (Incremental &amp;amp;&amp;amp; ShowIncrementalBuildDecisions) {
&lt;span class=&quot;ln&quot;&gt;532&lt;/span&gt;        &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;outs&lt;/span&gt;() &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot;Incremental compilation has been disabled, because it &quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;533&lt;/span&gt;                     &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot;is not compatible with whole module optimization.&quot;&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;534&lt;/span&gt;      }
&lt;span class=&quot;ln&quot;&gt;535&lt;/span&gt;      Incremental = &lt;span class=&quot;k&quot;&gt;false&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;536&lt;/span&gt;    }
&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;32-instantiating-a-swifttoolchain&quot;&gt;3.2: Instantiating a &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;ToolChain&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Once the arguments have been validated, the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;buildCompilation&lt;/span&gt;&lt;/code&gt; method instantiates a &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;ToolChain&lt;/span&gt;&lt;/code&gt; object. A &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;ToolChain&lt;/span&gt;&lt;/code&gt; is an object that's capable of translating &quot;actions&quot; (&lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Action&lt;/span&gt;&lt;/code&gt;) into &quot;jobs&quot; (&lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Job&lt;/span&gt;&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;ToolChain&lt;/span&gt;&lt;/code&gt; itself is an abstract base class. Several subclasses exist to create jobs for specific targets. For example, the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;toolchains&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Darwin&lt;/span&gt;&lt;/code&gt; toolchain knows how to create jobs that would work when compiling for a macOS or iOS target. &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;toolchains&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Android&lt;/span&gt;&lt;/code&gt; knows how to create jobs for Android targets.&lt;/p&gt;

&lt;p&gt;An appropriate toolchain is instantiated from within the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;buildCompilation&lt;/span&gt;&lt;/code&gt; method, by calling the &lt;code&gt;&lt;span class=&quot;f&quot;&gt;makeToolChain&lt;/span&gt;&lt;/code&gt; function:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/f69bc0eb14694e550a2a716d2d5a2ea134202031/lib/Driver/Driver.cpp#L563-L564&quot;&gt;swift/lib/Driver/Driver.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;504&lt;/span&gt;  &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt;&amp;gt; &lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::buildCompilation(
&lt;span class=&quot;ln&quot;&gt;505&lt;/span&gt;      &lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; *&amp;gt; Args) {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// ...parses and validates arguments.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;562&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;563&lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;ToolChain&lt;/span&gt;&amp;gt; TC =
&lt;span class=&quot;ln&quot;&gt;564&lt;/span&gt;        &lt;span class=&quot;f&quot;&gt;makeToolChain&lt;/span&gt;(*&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;, &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Triple&lt;/span&gt;(&lt;span class=&quot;v&quot;&gt;DefaultTargetTriple&lt;/span&gt;));
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;f&quot;&gt;makeToolChain&lt;/span&gt;&lt;/code&gt; function determines which toolchain to instantiate based on the target triple:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/f69bc0eb14694e550a2a716d2d5a2ea134202031/lib/Driver/Driver.cpp#L204-L233&quot;&gt;swift/lib/Driver/Driver.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;204&lt;/span&gt;  static &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;ToolChain&lt;/span&gt;&amp;gt;
&lt;span class=&quot;ln&quot;&gt;205&lt;/span&gt;  makeToolChain(&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt; &amp;amp;driver, &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Triple&lt;/span&gt; &amp;amp;target) {
&lt;span class=&quot;ln&quot;&gt;206&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; (target.&lt;span class=&quot;f&quot;&gt;getOS&lt;/span&gt;()) {
&lt;span class=&quot;ln&quot;&gt;207&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Triple&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;Darwin&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;208&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Triple&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;MacOSX&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;209&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Triple&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;IOS&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;210&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Triple&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;TvOS&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;211&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Triple&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;WatchOS&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;212&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;make_unique&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;toolchains&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Darwin&lt;/span&gt;&amp;gt;(driver, target);
&lt;span class=&quot;ln&quot;&gt;213&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;214&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Triple&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;Linux&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;215&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (target.&lt;span class=&quot;f&quot;&gt;isAndroid&lt;/span&gt;()) {
&lt;span class=&quot;ln&quot;&gt;216&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;make_unique&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;toolchains&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Android&lt;/span&gt;&amp;gt;(driver, target);
&lt;span class=&quot;ln&quot;&gt;217&lt;/span&gt;      } else {
&lt;span class=&quot;ln&quot;&gt;218&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;make_unique&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;toolchains&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;GenericUnix&lt;/span&gt;&amp;gt;(driver, target);
&lt;span class=&quot;ln&quot;&gt;219&lt;/span&gt;      }
&lt;span class=&quot;ln&quot;&gt;220&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;232&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;233&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;33-determining-the-swiftdriveroutputinfo&quot;&gt;3.3: Determining the &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;driver&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;OutputInfo&lt;/span&gt;&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;The driver's freshly instantiated &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;ToolChain&lt;/span&gt;&lt;/code&gt; is capable of translating actions into jobs. But to determine which actions my &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt; hello.swift&lt;/code&gt; invocation is composed of, the driver needs to construct an &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;OutputInfo&lt;/span&gt;&lt;/code&gt; object:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/f69bc0eb14694e550a2a716d2d5a2ea134202031/lib/Driver/Driver.cpp#L583-L584&quot;&gt;swift/lib/Driver/Driver.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;504&lt;/span&gt;  &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt;&amp;gt; &lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::buildCompilation(
&lt;span class=&quot;ln&quot;&gt;505&lt;/span&gt;      &lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; *&amp;gt; Args) {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// ...parses arguments and instantiates a toolchain.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;583&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;OutputInfo&lt;/span&gt; OI;
&lt;span class=&quot;ln&quot;&gt;584&lt;/span&gt;    &lt;span class=&quot;f&quot;&gt;buildOutputInfo&lt;/span&gt;(*TC, *TranslatedArgList, Inputs, OI);
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;buildOutputInfo&lt;/span&gt;&lt;/code&gt; method sets properties on the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;OutputInfo&lt;/span&gt;&lt;/code&gt; object, based on the driver mode and the presence of driver arguments like &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-emit-executable&lt;/span&gt;&lt;/code&gt; or &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-emit-library&lt;/span&gt;&lt;/code&gt;. Among the most important of these is &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;OutputInfo&lt;/span&gt;::&lt;span class=&quot;v&quot;&gt;LinkAction&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;OutputInfo&lt;/span&gt;::&lt;span class=&quot;v&quot;&gt;CompilerOutputType&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/f69bc0eb14694e550a2a716d2d5a2ea134202031/lib/Driver/Driver.cpp#L1052-L1099&quot;&gt;swift/lib/Driver/Driver.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;1052&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::buildOutputInfo(&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;ToolChain&lt;/span&gt; &amp;amp;TC, &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; DerivedArgList &amp;amp;Args,
&lt;span class=&quot;ln&quot;&gt;1053&lt;/span&gt;                               &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; InputFileList &amp;amp;Inputs,
&lt;span class=&quot;ln&quot;&gt;1054&lt;/span&gt;                               &lt;span class=&quot;cl&quot;&gt;OutputInfo&lt;/span&gt; &amp;amp;OI) &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; {
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1090&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; (OutputModeArg-&amp;gt;&lt;span class=&quot;f&quot;&gt;getOption&lt;/span&gt;().&lt;span class=&quot;f&quot;&gt;getID&lt;/span&gt;()) {
&lt;span class=&quot;ln&quot;&gt;1091&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;options&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;OPT_emit_executable&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;1092&lt;/span&gt;        OI.&lt;span class=&quot;v&quot;&gt;LinkAction&lt;/span&gt; = &lt;span class=&quot;t&quot;&gt;LinkKind&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;Executable&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;1093&lt;/span&gt;        OI.&lt;span class=&quot;v&quot;&gt;CompilerOutputType&lt;/span&gt; = &lt;span class=&quot;t&quot;&gt;types&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;TY_Object&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;1094&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;1095&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;1096&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;options&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;OPT_emit_library&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;1097&lt;/span&gt;        OI.&lt;span class=&quot;v&quot;&gt;LinkAction&lt;/span&gt; = &lt;span class=&quot;t&quot;&gt;LinkKind&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;DynamicLibrary&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;1098&lt;/span&gt;        OI.&lt;span class=&quot;v&quot;&gt;CompilerOutputType&lt;/span&gt; = &lt;span class=&quot;t&quot;&gt;types&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;TY_Object&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;1099&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1334&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Finally, the driver is ready to build a list of actions, by instantiating a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt;&lt;/code&gt; object, and then calling the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;buildActions&lt;/span&gt;&lt;/code&gt; method:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/f69bc0eb14694e550a2a716d2d5a2ea134202031/lib/Driver/Driver.cpp#L689-L703&quot;&gt;swift/lib/Driver/Driver.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;504&lt;/span&gt;  &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt;&amp;gt; &lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::buildCompilation(
&lt;span class=&quot;ln&quot;&gt;505&lt;/span&gt;      &lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; *&amp;gt; Args) {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// ...parses arguments, instantiates a toolchain,&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// and builds output info.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;688&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;689&lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt;&amp;gt; C(&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt;(Diags, Level,
&lt;span class=&quot;ln&quot;&gt;690&lt;/span&gt;                                                   &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;move&lt;/span&gt;(ArgList),
&lt;span class=&quot;ln&quot;&gt;691&lt;/span&gt;                                                   &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;move&lt;/span&gt;(TranslatedArgList),
&lt;span class=&quot;ln&quot;&gt;692&lt;/span&gt;                                                   &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;move&lt;/span&gt;(Inputs),
&lt;span class=&quot;ln&quot;&gt;693&lt;/span&gt;                                                   ArgsHash, StartTime,
&lt;span class=&quot;ln&quot;&gt;694&lt;/span&gt;                                                   NumberOfParallelCommands,
&lt;span class=&quot;ln&quot;&gt;695&lt;/span&gt;                                                   Incremental,
&lt;span class=&quot;ln&quot;&gt;696&lt;/span&gt;                                                   DriverSkipExecution,
&lt;span class=&quot;ln&quot;&gt;697&lt;/span&gt;                                                   SaveTemps,
&lt;span class=&quot;ln&quot;&gt;698&lt;/span&gt;                                                   ShowDriverTimeCompilation,
&lt;span class=&quot;ln&quot;&gt;699&lt;/span&gt;                                                   &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;move&lt;/span&gt;(StatsReporter)));
&lt;span class=&quot;ln&quot;&gt;700&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// Construct the graph of Actions.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;701&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;SmallVector&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Action&lt;/span&gt; *, &lt;span class=&quot;num&quot;&gt;8&lt;/span&gt;&amp;gt; TopLevelActions;
&lt;span class=&quot;ln&quot;&gt;702&lt;/span&gt;    &lt;span class=&quot;f&quot;&gt;buildActions&lt;/span&gt;(TopLevelActions, *TC, OI, OFM.&lt;span class=&quot;fs&quot;&gt;get&lt;/span&gt;(),
&lt;span class=&quot;ln&quot;&gt;703&lt;/span&gt;                 rebuildEverything ? &lt;span class=&quot;k&quot;&gt;nullptr&lt;/span&gt; : &amp;amp;outOfDateMap, *C);
&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;stage-4-instantiating-a-graph-of-swiftaction&quot;&gt;Stage 4: Instantiating a graph of &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Action&lt;/span&gt;&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&lt;span class=&quot;cl&quot;&gt;ToolChain&lt;/span&gt;&lt;/code&gt; objects are capable of translating &quot;actions&quot; – high-level descriptions of the inputs and outputs of a Swift compilation – into concrete &quot;jobs&quot;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/introduction-to-the-swift-compiler-driver&quot;&gt;The previous article&lt;/a&gt; explained that invoking &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt; hello.swift &lt;span class=&quot;copt&quot;&gt;-driver-print-jobs&lt;/span&gt;&lt;/code&gt; prints these &quot;jobs&quot;, which are themselves command-line invocations:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;cexec&quot;&gt;/Users/bgesiak/Source/apple/build/Ninja-ReleaseAssert/swift-macosx-x86_64/bin/swift&lt;/span&gt; \
    &lt;span class=&quot;copt&quot;&gt;-frontend -c -primary-file&lt;/span&gt; hello.swift \
    &lt;span class=&quot;copt&quot;&gt;-target x86_64-apple-darwin16.7.0&lt;/span&gt; \
    &lt;span class=&quot;copt&quot;&gt;-enable-objc-interop -color-diagnostics -module-name hello&lt;/span&gt; \
    &lt;span class=&quot;copt&quot;&gt;-o&lt;/span&gt; /var/folders/ry/2ryfdsb56b30092626qprw6d3rb3ss/T/hello-6ab6fd.o

&lt;span class=&quot;cexec&quot;&gt;/usr/bin/ld&lt;/span&gt; \
    /var/folders/ry/2ryfdsb56b30092626qprw6d3rb3ss/T/hello-6ab6fd.o \
    &lt;span class=&quot;copt&quot;&gt;-lobjc -lSystem -arch x86_64 -L&lt;/span&gt; /Users/bgesiak/Source/apple/build/Ninja-ReleaseAssert/swift-macosx-x86_64/lib/swift/macosx \
    &lt;span class=&quot;copt&quot;&gt;-rpath&lt;/span&gt; /Users/bgesiak/Source/apple/build/Ninja-ReleaseAssert/swift-macosx-x86_64/lib/swift/macosx \
    &lt;span class=&quot;copt&quot;&gt;-macosx_version_min 10.12.0 -no_objc_category_merging&lt;/span&gt; \
    &lt;span class=&quot;copt&quot;&gt;-o&lt;/span&gt; hello
&lt;/pre&gt;

&lt;p&gt;Besides jobs, the driver is also capable of printing a list of actions. Invoking &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt; hello.swift &lt;span class=&quot;copt&quot;&gt;-driver-print-actions&lt;/span&gt;&lt;/code&gt; outputs:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;: input, &lt;span class=&quot;s&quot;&gt;&quot;hello.swift&quot;&lt;/span&gt;, swift
&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;: compile, {&lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;}, object
&lt;span class=&quot;num&quot;&gt;2&lt;/span&gt;: link, {&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;}, image
&lt;/pre&gt;

&lt;p&gt;This looks similar to the output of &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt; hello.swift &lt;span class=&quot;copt&quot;&gt;-driver-print-jobs&lt;/span&gt;&lt;/code&gt;, with a few key differences:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;There are three actions. These are &quot;translated,&quot; by a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;ToolChain&lt;/span&gt;&lt;/code&gt;, into two jobs.&lt;/li&gt;
  &lt;li&gt;The input file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.swift&lt;/code&gt; is represented as an action, but there is no equivalent representation of it as a job.&lt;/li&gt;
  &lt;li&gt;The actions are high-level descriptions of what needs to happen. For example, &lt;code&gt;&lt;span class=&quot;num&quot;&gt;1&lt;/span&gt;: compile, {&lt;span class=&quot;num&quot;&gt;0&lt;/span&gt;}, object&lt;/code&gt; means &quot;input file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.swift&lt;/code&gt; needs to be compiled into an object.&quot; The job that corresponds to that action is a &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-c&lt;/span&gt;&lt;/code&gt; invocation with tons of arguments. In other words, the job is the concrete way that the toolchain chose to fulfill the action.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The actions themselves are constructed from within the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;buildActions&lt;/span&gt;&lt;/code&gt; method. This is a long method that's responsible for creating a list of actions based on the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;OutputInfo&lt;/span&gt;&lt;/code&gt; instance, the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;&lt;/code&gt; object's &lt;code&gt;&lt;span class=&quot;t&quot;&gt;DriverKind&lt;/span&gt;&lt;/code&gt;, and in some cases the target platform. I'll skip over most of it to show just the parts that are relevant to my &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt; hello.swift&lt;/code&gt; invocation:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/f69bc0eb14694e550a2a716d2d5a2ea134202031/lib/Driver/Driver.cpp#L1336-L1574&quot;&gt;swift/lib/Driver/Driver.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;1336&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::buildActions(&lt;span class=&quot;cl&quot;&gt;SmallVectorImpl&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Action&lt;/span&gt; *&amp;gt; &amp;amp;TopLevelActions,
&lt;span class=&quot;ln&quot;&gt;1337&lt;/span&gt;                            &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;ToolChain&lt;/span&gt; &amp;amp;TC, &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;OutputInfo&lt;/span&gt; &amp;amp;OI,
&lt;span class=&quot;ln&quot;&gt;1338&lt;/span&gt;                            &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;OutputFileMap&lt;/span&gt; *OFM,
&lt;span class=&quot;ln&quot;&gt;1339&lt;/span&gt;                            &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;InputInfoMap&lt;/span&gt; *OutOfDateMap,
&lt;span class=&quot;ln&quot;&gt;1340&lt;/span&gt;                            &lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt; &amp;amp;C) &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; {
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1349&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;SmallVector&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Action&lt;/span&gt; *, &lt;span class=&quot;num&quot;&gt;2&lt;/span&gt;&amp;gt; AllModuleInputs;
&lt;span class=&quot;ln&quot;&gt;1350&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;SmallVector&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Action&lt;/span&gt; *, &lt;span class=&quot;num&quot;&gt;2&lt;/span&gt;&amp;gt; AllLinkerInputs;
&lt;span class=&quot;ln&quot;&gt;1351&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1352&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; (OI.&lt;span class=&quot;v&quot;&gt;CompilerMode&lt;/span&gt;) {
&lt;span class=&quot;ln&quot;&gt;1353&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;OutputInfo&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;Mode&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;StandardCompile&lt;/span&gt;: {
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;1378&lt;/span&gt;      for (&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;InputPair&lt;/span&gt; &amp;amp;Input : Inputs) {
&lt;span class=&quot;ln&quot;&gt;1379&lt;/span&gt;        &lt;span class=&quot;t&quot;&gt;types&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;ID&lt;/span&gt; InputType = Input.&lt;span class=&quot;v&quot;&gt;first&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;1380&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Arg&lt;/span&gt; *InputArg = Input.&lt;span class=&quot;v&quot;&gt;second&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;1381&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;1382&lt;/span&gt;        &lt;span class=&quot;cl&quot;&gt;Action&lt;/span&gt; *Current = C.&lt;span class=&quot;f&quot;&gt;createAction&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;InputAction&lt;/span&gt;&amp;gt;(*InputArg, InputType);
&lt;span class=&quot;ln&quot;&gt;1383&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; (InputType) {
&lt;span class=&quot;ln&quot;&gt;1384&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;types&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;TY_Swift&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;1385&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;types&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;TY_SIL&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;1386&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;types&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;TY_SIB&lt;/span&gt;: {
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1405&lt;/span&gt;            Current = C.&lt;span class=&quot;f&quot;&gt;createAction&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;CompileJobAction&lt;/span&gt;&amp;gt;(Current,
&lt;span class=&quot;ln&quot;&gt;1406&lt;/span&gt;                                                       OI.&lt;span class=&quot;v&quot;&gt;CompilerOutputType&lt;/span&gt;,
&lt;span class=&quot;ln&quot;&gt;1407&lt;/span&gt;                                                       previousBuildState);
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1410&lt;/span&gt;            AllModuleInputs.&lt;span class=&quot;f&quot;&gt;push_back&lt;/span&gt;(Current);
&lt;span class=&quot;ln&quot;&gt;1411&lt;/span&gt;          }
&lt;span class=&quot;ln&quot;&gt;1412&lt;/span&gt;          AllLinkerInputs.&lt;span class=&quot;f&quot;&gt;push_back&lt;/span&gt;(Current);
&lt;span class=&quot;ln&quot;&gt;1413&lt;/span&gt;          &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;1414&lt;/span&gt;        }
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;1572&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (OI.&lt;span class=&quot;f&quot;&gt;shouldLink&lt;/span&gt;() &amp;amp;&amp;amp; !AllLinkerInputs.&lt;span class=&quot;f&quot;&gt;empty&lt;/span&gt;()) {
&lt;span class=&quot;ln&quot;&gt;1573&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; *LinkAction = C.&lt;span class=&quot;f&quot;&gt;createAction&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;LinkJobAction&lt;/span&gt;&amp;gt;(AllLinkerInputs,
&lt;span class=&quot;ln&quot;&gt;1574&lt;/span&gt;                                                       OI.&lt;span class=&quot;v&quot;&gt;LinkAction&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1627&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;1628&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The gist of the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;buildActions&lt;/span&gt;&lt;/code&gt; method is that it:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Loops over each of the inputs (in my case, that's just &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.swift&lt;/code&gt;) and creates an &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;InputAction&lt;/span&gt;&lt;/code&gt; for each of them. The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt;&lt;/code&gt; object stores a list of its actions internally.&lt;/li&gt;
  &lt;li&gt;For source code inputs of type &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.swift&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.sil&lt;/code&gt;, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.sib&lt;/code&gt;, it creates a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompileJobAction&lt;/span&gt;&lt;/code&gt;, also stored internally to the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt;&lt;/code&gt; object. It also specifies that the result of a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompileJobAction&lt;/span&gt;&lt;/code&gt; should be treated as an input to a linker action.&lt;/li&gt;
  &lt;li&gt;If a link action has been requested, and if there are inputs to that link action, the driver creates a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;LinkJobAction&lt;/span&gt;&lt;/code&gt;. Not all &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt;&lt;/code&gt; invocations result in a linker invocation – for example, had I ran &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt; hello.swift &lt;span class=&quot;copt&quot;&gt;-emit-object&lt;/span&gt;&lt;/code&gt;, then the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;OutputInfo&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;shouldLink&lt;/span&gt;&lt;/code&gt; method would return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;, and no &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;LinkJobAction&lt;/span&gt;&lt;/code&gt; would have been created.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;stage-5-instantiating-a-list-of-swiftjob-based-on-those-actions&quot;&gt;Stage 5: Instantiating a list of &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Job&lt;/span&gt;&lt;/code&gt; based on those actions&lt;/h2&gt;

&lt;p&gt;After constructing the actions, the driver calls the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;buildJobs&lt;/span&gt;&lt;/code&gt; method to translate actions into jobs:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/f69bc0eb14694e550a2a716d2d5a2ea134202031/lib/Driver/Driver.cpp#L713&quot;&gt;swift/lib/Driver/Driver.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;504&lt;/span&gt;  &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt;&amp;gt; &lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::buildCompilation(
&lt;span class=&quot;ln&quot;&gt;505&lt;/span&gt;      &lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; *&amp;gt; Args) {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// ...parses arguments, instantiates a toolchain,&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// and builds output info, instantiates a Compilation,&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// and builds a graph of actions.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;713&lt;/span&gt;    &lt;span class=&quot;f&quot;&gt;buildJobs&lt;/span&gt;(TopLevelActions, OI, OFM.&lt;span class=&quot;fs&quot;&gt;get&lt;/span&gt;(), *TC, *C);
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;752&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; C;
&lt;span class=&quot;ln&quot;&gt;753&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;buildJobs&lt;/span&gt;&lt;/code&gt; method loops over each &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Action&lt;/span&gt;&lt;/code&gt; and passes any &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;JobAction&lt;/span&gt;&lt;/code&gt; objects to the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;buildJobsForAction&lt;/span&gt;&lt;/code&gt; method. This filters out inputs, which are represented as &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;InputAction&lt;/span&gt;&lt;/code&gt; and so are not instances of &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;JobAction&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/f69bc0eb14694e550a2a716d2d5a2ea134202031/lib/Driver/Driver.cpp#L204-L233&quot;&gt;swift/lib/Driver/Driver.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;1673&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::buildJobs(&lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Action&lt;/span&gt; *&amp;gt; TopLevelActions,
&lt;span class=&quot;ln&quot;&gt;1674&lt;/span&gt;                         &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;OutputInfo&lt;/span&gt; &amp;amp;OI, &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;OutputFileMap&lt;/span&gt; *OFM,
&lt;span class=&quot;ln&quot;&gt;1675&lt;/span&gt;                         &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;ToolChain&lt;/span&gt; &amp;amp;TC, &lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt; &amp;amp;C) &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; {
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1702&lt;/span&gt;    for (&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Action&lt;/span&gt; *A : TopLevelActions) {
&lt;span class=&quot;ln&quot;&gt;1703&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; *JA = &lt;span class=&quot;f&quot;&gt;dyn_cast&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;JobAction&lt;/span&gt;&amp;gt;(A)) {
&lt;span class=&quot;ln&quot;&gt;1704&lt;/span&gt;        (void)&lt;span class=&quot;f&quot;&gt;buildJobsForAction&lt;/span&gt;(C, JA, OI, OFM, TC, /*TopLevel*/true, JobCache);
&lt;span class=&quot;ln&quot;&gt;1705&lt;/span&gt;      }
&lt;span class=&quot;ln&quot;&gt;1706&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;1707&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;buildJobsForAction&lt;/span&gt;&lt;/code&gt; method does a lot. Among other things, it records dependencies between actions, in order to improve Swift's incremental compilation. That's a topic I'll need to write several articles about, so I won't attempt to cover it here.&lt;/p&gt;

&lt;p&gt;At its core, though, the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;buildJobsForAction&lt;/span&gt;&lt;/code&gt; method calls through to the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;ToolChain&lt;/span&gt;&lt;/code&gt; object that was instantiated in stage three above, in order to translate each &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Action&lt;/span&gt;&lt;/code&gt; into a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Job&lt;/span&gt;&lt;/code&gt;. It then adds that &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Job&lt;/span&gt;&lt;/code&gt; to a list stored within the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt;&lt;/code&gt; object:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/f69bc0eb14694e550a2a716d2d5a2ea134202031/lib/Driver/Driver.cpp#L2291-L2294&quot;&gt;swift/lib/Driver/Driver.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;1993&lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;Job&lt;/span&gt; *&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::buildJobsForAction(&lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt; &amp;amp;C, &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; Job&lt;span class=&quot;cl&quot;&gt;Action&lt;/span&gt; *JA,
&lt;span class=&quot;ln&quot;&gt;1994&lt;/span&gt;                                  &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;OutputInfo&lt;/span&gt; &amp;amp;OI,
&lt;span class=&quot;ln&quot;&gt;1995&lt;/span&gt;                                  &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;OutputFileMap&lt;/span&gt; *OFM,
&lt;span class=&quot;ln&quot;&gt;1996&lt;/span&gt;                                  &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;ToolChain&lt;/span&gt; &amp;amp;TC, &lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; AtTopLevel,
&lt;span class=&quot;ln&quot;&gt;1997&lt;/span&gt;                                  &lt;span class=&quot;cl&quot;&gt;JobCacheMap&lt;/span&gt; &amp;amp;JobCache) &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; {
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2291&lt;/span&gt;    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;Job&lt;/span&gt;&amp;gt; ownedJob = TC.&lt;span class=&quot;f&quot;&gt;constructJob&lt;/span&gt;(*JA, C,&lt;span class=&quot;ts&quot;&gt; std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;move&lt;/span&gt;(InputJobs),
&lt;span class=&quot;ln&quot;&gt;2292&lt;/span&gt;                                                    InputActions, 
&lt;span class=&quot;ln&quot;&gt;2293&lt;/span&gt;                                                    &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;move&lt;/span&gt;(Output), OI);
&lt;span class=&quot;ln&quot;&gt;2294&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;Job&lt;/span&gt; *J = C.&lt;span class=&quot;f&quot;&gt;addJob&lt;/span&gt;(&lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;move&lt;/span&gt;(ownedJob));
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;2371&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; J;
&lt;span class=&quot;ln&quot;&gt;2372&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;In order to translate an action into a job, the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;ToolChain&lt;/span&gt;&lt;/code&gt; base class uses a macro that calls the appropriate &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;ToolChain&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;constructInvocation&lt;/span&gt;&lt;/code&gt; method for each action class type. &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;ToolChain&lt;/span&gt;&lt;/code&gt; classes overload &lt;code&gt;&lt;span class=&quot;f&quot;&gt;constructInvocation&lt;/span&gt;&lt;/code&gt; in order to execute separate logic for, say, &lt;code&gt;&lt;span class=&quot;f&quot;&gt;constructInvocation&lt;/span&gt;(&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompileJobAction&lt;/span&gt; &amp;amp;, ...)&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;f&quot;&gt;constructInvocation&lt;/span&gt;(&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;LinkJobAction&lt;/span&gt; &amp;amp;, ...)&lt;/code&gt;:&lt;/code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/f69bc0eb14694e550a2a716d2d5a2ea134202031/lib/Driver/ToolChain.cpp#L66-L124&quot;&gt;swift/lib/Driver/ToolChain.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt; 66&lt;/span&gt;  &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;Job&lt;/span&gt;&amp;gt;
&lt;span class=&quot;ln&quot;&gt; 67&lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;ToolChain&lt;/span&gt;::constructJob(&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; JobAction &amp;amp;JA,
&lt;span class=&quot;ln&quot;&gt; 68&lt;/span&gt;                          &lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt; &amp;amp;C,
&lt;span class=&quot;ln&quot;&gt; 69&lt;/span&gt;                          &lt;span class=&quot;cl&quot;&gt;SmallVectorImpl&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Job&lt;/span&gt; *&amp;gt; &amp;amp;&amp;amp;inputs,
&lt;span class=&quot;ln&quot;&gt; 70&lt;/span&gt;                          &lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Action&lt;/span&gt; *&amp;gt; inputActions,
&lt;span class=&quot;ln&quot;&gt; 71&lt;/span&gt;                          &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;cls&quot;&gt;unique_ptr&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;CommandOutput&lt;/span&gt;&amp;gt; output,
&lt;span class=&quot;ln&quot;&gt; 72&lt;/span&gt;                          &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;OutputInfo&lt;/span&gt; &amp;amp;OI) &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; {
&lt;span class=&quot;ln&quot;&gt; ..&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 75&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;auto&lt;/span&gt; invocationInfo = [&amp;amp;]() -&amp;gt; &lt;span class=&quot;cl&quot;&gt;InvocationInfo&lt;/span&gt; {
&lt;span class=&quot;ln&quot;&gt; 76&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; (JA.&lt;span class=&quot;f&quot;&gt;getKind&lt;/span&gt;()) {
&lt;span class=&quot;ln&quot;&gt; 77&lt;/span&gt;    &lt;span class=&quot;ms&quot;&gt;#define CASE(K) case Action::K: \&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 78&lt;/span&gt;        &lt;span class=&quot;ms&quot;&gt;return constructInvocation(cast&amp;lt;K##Action&amp;gt;(JA), context);&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 79&lt;/span&gt;      &lt;span class=&quot;m&quot;&gt;CASE&lt;/span&gt;(&lt;span class=&quot;cl&quot;&gt;CompileJob&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt; 80&lt;/span&gt;      &lt;span class=&quot;m&quot;&gt;CASE&lt;/span&gt;(&lt;span class=&quot;cl&quot;&gt;InterpretJob&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt; 81&lt;/span&gt;      &lt;span class=&quot;m&quot;&gt;CASE&lt;/span&gt;(&lt;span class=&quot;cl&quot;&gt;BackendJob&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt; 82&lt;/span&gt;      &lt;span class=&quot;m&quot;&gt;CASE&lt;/span&gt;(&lt;span class=&quot;cl&quot;&gt;MergeModuleJob&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt; 83&lt;/span&gt;      &lt;span class=&quot;m&quot;&gt;CASE&lt;/span&gt;(&lt;span class=&quot;cl&quot;&gt;ModuleWrapJob&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt; 84&lt;/span&gt;      &lt;span class=&quot;m&quot;&gt;CASE&lt;/span&gt;(&lt;span class=&quot;cl&quot;&gt;LinkJob&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt; ..&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 97&lt;/span&gt;    }();
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;120&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;llvm&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;make_unique&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;Job&lt;/span&gt;&amp;gt;(JA,&lt;span class=&quot;ts&quot;&gt; std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;move&lt;/span&gt;(inputs), &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;move&lt;/span&gt;(output),
&lt;span class=&quot;ln&quot;&gt;121&lt;/span&gt;                                  executablePath,
&lt;span class=&quot;ln&quot;&gt;122&lt;/span&gt;                                  &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;move&lt;/span&gt;(invocationInfo.&lt;span class=&quot;v&quot;&gt;Arguments&lt;/span&gt;),
&lt;span class=&quot;ln&quot;&gt;123&lt;/span&gt;                                  &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;move&lt;/span&gt;(invocationInfo.&lt;span class=&quot;v&quot;&gt;ExtraEnvironment&lt;/span&gt;),
&lt;span class=&quot;ln&quot;&gt;124&lt;/span&gt;                                  &lt;span class=&quot;ts&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;fs&quot;&gt;move&lt;/span&gt;(invocationInfo.&lt;span class=&quot;v&quot;&gt;FilelistInfo&lt;/span&gt;));
&lt;span class=&quot;ln&quot;&gt;125&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Each subclass of toolchain – &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;toolchains&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Darwin&lt;/span&gt;&lt;/code&gt;, &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;toolchains&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Android&lt;/span&gt;&lt;/code&gt;, etc. – constructs platform-specific command-line invocations for each action. Some actions, however, are the same on each platform. One example of such an action is a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompileJobAction&lt;/span&gt;&lt;/code&gt; – jobs for these are invocations of &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt;, and these are pretty much the same on any platform. As a result, they're handled in the base &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;ToolChain&lt;/span&gt;&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;Here's how the base &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;ToolChain&lt;/span&gt;&lt;/code&gt; class transforms the compile action for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.swift&lt;/code&gt; into an invocation of &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-c&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/f69bc0eb14694e550a2a716d2d5a2ea134202031/lib/Driver/ToolChain.cpp#L200-L501&quot;&gt;swift/lib/Driver/ToolChain.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;200&lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;ToolChain&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;InvocationInfo&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;201&lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;ToolChain&lt;/span&gt;::constructInvocation(&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;CompileJobAction&lt;/span&gt; &amp;amp;job,
&lt;span class=&quot;ln&quot;&gt;202&lt;/span&gt;                                 &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;JobContext&lt;/span&gt; &amp;amp;context) &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; {
&lt;span class=&quot;ln&quot;&gt;203&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;InvocationInfo&lt;/span&gt; II{&lt;span class=&quot;m&quot;&gt;SWIFT_EXECUTABLE_NAME&lt;/span&gt;};
&lt;span class=&quot;ln&quot;&gt;204&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;ArgStringList&lt;/span&gt; &amp;amp;Arguments = II.&lt;span class=&quot;v&quot;&gt;Arguments&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;205&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;206&lt;/span&gt;    Arguments.&lt;span class=&quot;f&quot;&gt;push_back&lt;/span&gt;(&lt;span class=&quot;s&quot;&gt;&quot;-frontend&quot;&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;210&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; (context.&lt;span class=&quot;v&quot;&gt;OI&lt;/span&gt;.&lt;span class=&quot;v&quot;&gt;CompilerMode&lt;/span&gt;) {
&lt;span class=&quot;ln&quot;&gt;211&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;OutputInfo&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;Mode&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;StandardCompile&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;212&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;OutputInfo&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;Mode&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;SingleCompile&lt;/span&gt;: {
&lt;span class=&quot;ln&quot;&gt;213&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; (context.&lt;span class=&quot;v&quot;&gt;Output&lt;/span&gt;.&lt;span class=&quot;f&quot;&gt;getPrimaryOutputType&lt;/span&gt;()) {
&lt;span class=&quot;ln&quot;&gt;214&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;types&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;TY_Object&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;215&lt;/span&gt;        FrontendModeOption = &lt;span class=&quot;s&quot;&gt;&quot;-c&quot;&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;216&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;280&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;500&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; II;
&lt;span class=&quot;ln&quot;&gt;501&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Unlike compile actions, link actions differ greatly depending on the target platform. As a result, most &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;ToolChain&lt;/span&gt;&lt;/code&gt; subclasses override the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;ToolChain&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;constructInvocation&lt;/span&gt;(&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;LinkJobAction&lt;/span&gt; &amp;amp;, ...)&lt;/code&gt; method. Here's &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;toolchains&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Darwin&lt;/span&gt;&lt;/code&gt;, which adds object files as inputs, conditionally adds the &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-dylib&lt;/span&gt;&lt;/code&gt; option when linking a dynamic library, and specifies the output file with &lt;code&gt;&lt;span class=&quot;copt&quot;&gt;-o&lt;/span&gt;&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/f69bc0eb14694e550a2a716d2d5a2ea134202031/lib/Driver/ToolChain.cpp#L66-L126&quot;&gt;swift/lib/Driver/ToolChain.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;1211&lt;/span&gt;  &lt;span class=&quot;cl&quot;&gt;ToolChain&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;InvocationInfo&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1212&lt;/span&gt;  &lt;span class=&quot;t&quot;&gt;toolchains&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Darwin&lt;/span&gt;::constructInvocation(&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;LinkJobAction&lt;/span&gt; &amp;amp;job,
&lt;span class=&quot;ln&quot;&gt;1213&lt;/span&gt;                                          &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;JobContext&lt;/span&gt; &amp;amp;context) &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; {
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1228&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; *LD = &lt;span class=&quot;s&quot;&gt;&quot;ld&quot;&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;1238&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;InvocationInfo&lt;/span&gt; II = {LD};
&lt;span class=&quot;ln&quot;&gt;1239&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;ArgStringList&lt;/span&gt; &amp;amp;Arguments = II.&lt;span class=&quot;v&quot;&gt;Arguments&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;1250&lt;/span&gt;    &lt;span class=&quot;f&quot;&gt;addInputsOfType&lt;/span&gt;(Arguments, context.&lt;span class=&quot;v&quot;&gt;InputActions&lt;/span&gt;, &lt;span class=&quot;t&quot;&gt;types&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;TY_Object&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;1264&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; (job.&lt;span class=&quot;f&quot;&gt;getKind&lt;/span&gt;()) {
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1270&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;t&quot;&gt;LinkKind&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;DynamicLibrary&lt;/span&gt;:
&lt;span class=&quot;ln&quot;&gt;1271&lt;/span&gt;      Arguments.&lt;span class=&quot;f&quot;&gt;push_back&lt;/span&gt;(&lt;span class=&quot;s&quot;&gt;&quot;-dylib&quot;&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;1272&lt;/span&gt;      &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;;
&lt;span class=&quot;ln&quot;&gt;1273&lt;/span&gt;    }
&lt;span class=&quot;ln&quot;&gt;....&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1463&lt;/span&gt;    Arguments.&lt;span class=&quot;f&quot;&gt;push_back&lt;/span&gt;(&lt;span class=&quot;s&quot;&gt;&quot;-o&quot;&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;1464&lt;/span&gt;    Arguments.&lt;span class=&quot;f&quot;&gt;push_back&lt;/span&gt;(context.&lt;span class=&quot;v&quot;&gt;Output&lt;/span&gt;.&lt;span class=&quot;f&quot;&gt;getPrimaryOutputFilename&lt;/span&gt;().&lt;span class=&quot;f&quot;&gt;c_str&lt;/span&gt;());
&lt;span class=&quot;ln&quot;&gt;1465&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;1466&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; II;
&lt;span class=&quot;ln&quot;&gt;1467&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;stage-6-executing-each-of-the-list-of-swiftjob&quot;&gt;Stage 6: Executing each of the list of &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Job&lt;/span&gt;&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;Recall that this article began in the &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt;&lt;/code&gt; executable's &lt;code&gt;&lt;span class=&quot;f&quot;&gt;main&lt;/span&gt;&lt;/code&gt; function, the entry point of the compiler. That function eventually called the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;buildCompilation&lt;/span&gt;&lt;/code&gt; method, in stage three. The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;buildCompilation&lt;/span&gt;&lt;/code&gt; method called &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;buildActions&lt;/span&gt;&lt;/code&gt; in stage four, and then &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;buildJobs&lt;/span&gt;&lt;/code&gt; in stage five, before returning back to &lt;code&gt;&lt;span class=&quot;f&quot;&gt;main&lt;/span&gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now back in &lt;code&gt;&lt;span class=&quot;f&quot;&gt;main&lt;/span&gt;&lt;/code&gt;, the driver has a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt;&lt;/code&gt; object that has a complete list of the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Job&lt;/span&gt;&lt;/code&gt; objects it needs to execute. Finally, the driver calls the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;performJobs&lt;/span&gt;&lt;/code&gt; method, which kicks off the execution of those jobs:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/f69bc0eb14694e550a2a716d2d5a2ea134202031/tools/driver/driver.cpp#L111-L207&quot;&gt;swift/tools/driver/driver.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;111&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; main(&lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; argc_, &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;char&lt;/span&gt; **argv_) {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// ...checks whether to run a subcommand,&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// or whether to execute the compiler frontend,&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// and then instantiates a Driver object and&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// checks whether to return early for swift-format,&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;// and finally builds a Compilation object.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;203&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; C-&amp;gt;&lt;span class=&quot;f&quot;&gt;performJobs&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;207&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;performJobs&lt;/span&gt;&lt;/code&gt; method just calls through to the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt;::&lt;span class=&quot;f&quot;&gt;performJobsImpl&lt;/span&gt;&lt;/code&gt; method, which in turn schedules the jobs and executes them on a task queue:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/f69bc0eb14694e550a2a716d2d5a2ea134202031/lib/Driver/Compilation.cpp#L826-L844&quot;&gt;swift/lib/Driver/Compilation.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;826&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt;::performJobsImpl(&lt;span class=&quot;k&quot;&gt;bool&lt;/span&gt; &amp;amp;abnormalExit) {
&lt;span class=&quot;ln&quot;&gt;827&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;PerformJobsState&lt;/span&gt; State(*&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;828&lt;/span&gt;  
&lt;span class=&quot;ln&quot;&gt;829&lt;/span&gt;    State.&lt;span class=&quot;f&quot;&gt;scheduleInitialJobs&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;830&lt;/span&gt;    State.&lt;span class=&quot;f&quot;&gt;scheduleAdditionalJobs&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;831&lt;/span&gt;    State.&lt;span class=&quot;f&quot;&gt;runTaskQueueToCompletion&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;832&lt;/span&gt;    State.&lt;span class=&quot;f&quot;&gt;checkUnfinishedJobs&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;843&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; State.&lt;span class=&quot;f&quot;&gt;getResult&lt;/span&gt;();
&lt;span class=&quot;ln&quot;&gt;844&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The task queue itself is implemented in one of two ways, depending on whether the driver is running on a Darwin or on a Unix host:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/f69bc0eb14694e550a2a716d2d5a2ea134202031/lib/Basic/TaskQueue.cpp#L26-L30&quot;&gt;swift/lib/Basic/TaskQueue.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;26&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#if LLVM_ON_UNIX &amp;amp;&amp;amp; !defined(__CYGWIN__) &amp;amp;&amp;amp; !defined(__HAIKU__)&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;27&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Unix/TaskQueue.inc&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;28&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#else&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;29&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Default/TaskQueue.inc&quot;&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;30&lt;/span&gt;  &lt;span class=&quot;ms&quot;&gt;#endif&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;I won't go into the details of each of these implementations in this article. Suffice it to say that the child job invocations are each executed in order.&lt;/p&gt;

&lt;h2 id=&quot;putting-it-all-together-the-story-of-how-swiftc-helloswift-is-executed&quot;&gt;Putting it all together: the story of how &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt; hello.swift&lt;/code&gt; is executed&lt;/h2&gt;

&lt;p&gt;In summary, here's how an invocation of &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt; hello.swift&lt;/code&gt;, when run on my macOS host machine, goes through the six stages of the Swift driver:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The driver determines the invocation isn't a subcommand (those start with &lt;code&gt;&lt;span class=&quot;s&quot;&gt;&quot;swift&quot;&lt;/span&gt;&lt;/code&gt;), and it isn't a &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swift&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt;&lt;/code&gt; invocation, so it must need to be split up somehow.&lt;/li&gt;
  &lt;li&gt;The driver instantiates a &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;&lt;/code&gt; object in order to handle splitting up &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt; hello.swift&lt;/code&gt;. Because the name of the executable is &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt;&lt;/code&gt;, the driver infers that it's being run in &lt;code&gt;&lt;span class=&quot;t&quot;&gt;DriverKind&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;Batch&lt;/span&gt;&lt;/code&gt; mode.&lt;/li&gt;
  &lt;li&gt;The driver instantiates a &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Compilation&lt;/span&gt;&lt;/code&gt; object to store each of the actions and jobs that will be constructed. A &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;toolchains&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Darwin&lt;/span&gt;&lt;/code&gt; toolchain object is instantiated, so that it can be used later to translate actions into macOS-specific jobs. The &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt; hello.swift&lt;/code&gt; invocation arguments are parsed in order to construct a &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;t&quot;&gt;driver&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;OutputInfo&lt;/span&gt;&lt;/code&gt; object whose &lt;code&gt;&lt;span class=&quot;v&quot;&gt;LinkAction&lt;/span&gt;&lt;/code&gt; is &lt;code&gt;&lt;span class=&quot;t&quot;&gt;LinkKind&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;Executable&lt;/span&gt;&lt;/code&gt;, and whose &lt;code&gt;&lt;span class=&quot;v&quot;&gt;CompilerOutputType&lt;/span&gt;&lt;/code&gt; is &lt;code&gt;&lt;span class=&quot;t&quot;&gt;types&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;TY_Object&lt;/span&gt;&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;The driver constructs a graph of &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Action&lt;/span&gt;&lt;/code&gt; objects based on the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;OutputInfo&lt;/span&gt;&lt;/code&gt;. In the &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; of &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt; hello.swift&lt;/code&gt;, an &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;InputAction&lt;/span&gt;&lt;/code&gt; is created to represent &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.swift&lt;/code&gt;, a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompileJobAction&lt;/span&gt;&lt;/code&gt; is created based on an &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;OutputInfo&lt;/span&gt;::&lt;span class=&quot;v&quot;&gt;CompilerOutputType&lt;/span&gt;&lt;/code&gt; of &lt;code&gt;&lt;span class=&quot;cn&quot;&gt;TY_Object&lt;/span&gt;&lt;/code&gt;, and a &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;LinkJobAction&lt;/span&gt;&lt;/code&gt; is created because the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;OutputInfo&lt;/span&gt;::&lt;span class=&quot;v&quot;&gt;LinkAction&lt;/span&gt;&lt;/code&gt; was set to &lt;code&gt;&lt;span class=&quot;cn&quot;&gt;Executable&lt;/span&gt;&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;The driver invokes the toolchain in order to instantiate a &lt;code&gt;&lt;span class=&quot;t&quot;&gt;swift&lt;/span&gt;::&lt;span class=&quot;cl&quot;&gt;Job&lt;/span&gt;&lt;/code&gt; for each &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;JobAction&lt;/span&gt;&lt;/code&gt; – so that's the &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;CompileJobAction&lt;/span&gt;&lt;/code&gt; and &lt;code&gt;&lt;span class=&quot;cl&quot;&gt;LinkJobAction&lt;/span&gt;&lt;/code&gt; from the previous stage.&lt;/li&gt;
  &lt;li&gt;The driver executes these two jobs on a task queue, thereby compiling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.swift&lt;/code&gt; into an object named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.o&lt;/code&gt;, and linking &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.o&lt;/code&gt; into an executable named &lt;code&gt;&lt;span class=&quot;cexec&quot;&gt;hello&lt;/span&gt;&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I hope that sheds some light on how the Swift driver behaves. Despite the length of this article, there's lot I &lt;em&gt;didn't&lt;/em&gt; cover. For example, the Swift driver is also responsible for incremental compilation – if it determines that the result of a job is already available from a previous compilation, it won't run that job. I'll try to write more about how this works in a future article.&lt;/p&gt;</content><author><name></name></author><category term="swiftc" /><summary type="html">In the previous article of this running series on the Swift compiler, I introduced the Swift compiler driver. To recap: the driver is the executable that is run when users invoke swift or swiftc on the command line. It's responsible for splitting up a single swift or swiftc invocation into multiple child jobs. These jobs are command line invocations of swift -frontend, ld, or other command-line utilities.</summary></entry><entry><title type="html">An Introduction to the Swift Compiler Driver</title><link href="https://modocache.io/introduction-to-the-swift-compiler-driver" rel="alternate" type="text/html" title="An Introduction to the Swift Compiler Driver" /><published>2017-11-04T05:00:00+00:00</published><updated>2017-11-04T05:00:00+00:00</updated><id>https://modocache.io/introduction-to-the-swift-compiler-driver</id><content type="html" xml:base="https://modocache.io/introduction-to-the-swift-compiler-driver">&lt;blockquote&gt;
  &lt;p&gt;
    This article contains some content especially for patrons.
    Although it reads coherently as-is, to read the full article, please consider
    &lt;a href=&quot;https://www.patreon.com/bePatron?c=1078745&amp;amp;rid=1916581&amp;amp;redirect_uri=https%3A%2F%2Fpatreon.com%2Foauth2%2Fauthorize%3Fresponse_type%3Dcode%26client_id%3Dda17b80fc255ee4f968b73c71a9600612148822e1fb0a4c0565c823613a630ec%26redirect_uri%3Dhttps%3A%2F%2Fmodocache.io%2Fpatreon%2Foauth%26state%3D%2Fintroduction-to-the-swift-compiler-driver&quot;&gt;supporting me on Patreon,&lt;/a&gt; or
    &lt;a href=&quot;https://patreon.com/oauth2/authorize?response_type=code&amp;amp;client_id=da17b80fc255ee4f968b73c71a9600612148822e1fb0a4c0565c823613a630ec&amp;amp;redirect_uri=https://modocache.io/patreon/oauth&amp;amp;state=/introduction-to-the-swift-compiler-driver&quot;&gt;click here&lt;/a&gt; if you are already a
    patron. $10/month gives you access to all content I will ever write on
    this website.
  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href=&quot;/getting-started-with-swift-development&quot;&gt;The first article of this series&lt;/a&gt; on the Swift compiler explained that the compiler is just a command-line program, named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftc&lt;/code&gt;. This article explains what that command-line program does.&lt;/p&gt;

&lt;p&gt;Specifically, this article explains the Swift &quot;driver&quot;. This is the first bit of code that is executed when users invoke &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftc&lt;/code&gt; on the command line.&lt;/p&gt;

&lt;p&gt;Like any other C, C++, or Objective-C command-line program, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftc&lt;/code&gt; begin by executing an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int main()&lt;/code&gt; function:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/77282a3e8afd1c31ac8d154dd5691c399ee08623/tools/driver/driver.cpp#L111&quot;&gt;swift/tools/driver/driver.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;111&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; main(&lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; argc_, &lt;span class=&quot;k&quot;&gt;const char&lt;/span&gt; **argv_) {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;207&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main()&lt;/code&gt; function calls out to code in a Swift compiler library, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libswiftDriver&lt;/code&gt;, in order to break up a single invocation of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftc&lt;/code&gt; into smaller chunks of work. These smaller chunks are called &quot;jobs&quot;.&lt;/p&gt;

&lt;h2 id=&quot;swift-driver-jobs-by-example-compiling-swift-source-code-into-an-executable&quot;&gt;Swift driver jobs by example: compiling Swift source code into an executable&lt;/h2&gt;

&lt;p&gt;For example, let's say I wanted to compile the following Swift source file, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.swift&lt;/code&gt;, into an executable:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;hello.swift&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;fs&quot;&gt;print&lt;/span&gt;(&lt;span class=&quot;s&quot;&gt;&quot;Hello!&quot;&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;To produce an executable named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello&lt;/code&gt;, I'll invoke &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftc&lt;/code&gt; on the command line:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt; hello.swift &lt;span class=&quot;copt&quot;&gt;-o&lt;/span&gt; hello
&lt;/pre&gt;

&lt;p&gt;This produces an executable named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello&lt;/code&gt;, by first compiling the Swift code into a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.o&lt;/code&gt; object file, and then linking that file into an executable named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello&lt;/code&gt;. I can request to see the exact series of jobs that led to the final &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello&lt;/code&gt; executable by using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-driver-print-jobs&lt;/code&gt; option:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;cexec&quot;&gt;swiftc&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-driver-print-jobs&lt;/span&gt; hello.swift &lt;span class=&quot;copt&quot;&gt;-o&lt;/span&gt; hello
&lt;/pre&gt;

&lt;p&gt;This outputs two jobs:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The first is an invocation of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift -frontend&lt;/code&gt; that compiles the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.swift&lt;/code&gt; source code file into an object file named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello-6ab6fd.o&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;The second is an invocation of the linker, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ld&lt;/code&gt;, which links the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello-6ab6fd.o&lt;/code&gt; object file with the Swift and Objective-C runtimes in order to produce the executable I requested: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here's the full output:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;cexec&quot;&gt;/Users/bgesiak/Source/apple/build/Ninja-ReleaseAssert/swift-macosx-x86_64/bin/swift&lt;/span&gt; \
    &lt;span class=&quot;copt&quot;&gt;-frontend -c -primary-file&lt;/span&gt; hello.swift \
    &lt;span class=&quot;copt&quot;&gt;-target x86_64-apple-darwin16.7.0&lt;/span&gt; \
    &lt;span class=&quot;copt&quot;&gt;-enable-objc-interop -color-diagnostics -module-name hello&lt;/span&gt; \
    &lt;span class=&quot;copt&quot;&gt;-o&lt;/span&gt; /var/folders/ry/2ryfdsb56b30092626qprw6d3rb3ss/T/hello-6ab6fd.o

&lt;span class=&quot;cexec&quot;&gt;/usr/bin/ld&lt;/span&gt; \
    /var/folders/ry/2ryfdsb56b30092626qprw6d3rb3ss/T/hello-6ab6fd.o \
    &lt;span class=&quot;copt&quot;&gt;-lobjc -lSystem -arch x86_64 -L&lt;/span&gt; /Users/bgesiak/Source/apple/build/Ninja-ReleaseAssert/swift-macosx-x86_64/lib/swift/macosx \
    &lt;span class=&quot;copt&quot;&gt;-rpath&lt;/span&gt; /Users/bgesiak/Source/apple/build/Ninja-ReleaseAssert/swift-macosx-x86_64/lib/swift/macosx \
    &lt;span class=&quot;copt&quot;&gt;-macosx_version_min 10.12.0 -no_objc_category_merging&lt;/span&gt; \
    &lt;span class=&quot;copt&quot;&gt;-o&lt;/span&gt; hello
&lt;/pre&gt;

&lt;p&gt;It would be tedious if users of the Swift compiler had to invoke two commands, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift -frontend&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ld&lt;/code&gt;, every time they wanted to generate an executable from a Swift source code file. The Swift driver exists to make this more convenient: it translates a single invocation of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftc&lt;/code&gt; into a series of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift -frontend&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ld&lt;/code&gt; jobs that do what the user wants.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;My example above may have been too simple to demonstrate just how useful the Swift driver is – it only took two jobs to do what I wanted. However, compiling multiple Swift source files requires a separate &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift -frontend&lt;/code&gt; job for each one. Producing a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.swiftmodule&lt;/code&gt; from those source files requires invocations of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift -frontend -merge-modules&lt;/code&gt;, as well as other jobs. The Swift driver coordinates all of this work for me, translating a simple invocation such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftc -emit-module&lt;/code&gt; into what is sometimes dozens of jobs.&lt;/p&gt;

  &lt;p&gt;If that weren't enough, the Swift driver is also responsible for determining when jobs do not need to be run, because their output is already available and up-to-date. This is known as &quot;incremental building&quot;. If you're interested in helping reduce the amount of time it takes for your Swift source code project to compile, you'll want to understand how the driver accomplishes this. It's a topic I plan on writing about at length in future articles.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When I think of the Swift compiler, I think of a program that parses the Swift source code in a file, outputs warnings or errors if that source code isn't syntactically correct, and then translates that source code into binary 0's and 1's that my operating system knows how to execute as a program. However, it's important to make a distinction: &lt;strong&gt;it's invocations of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift -frontend&lt;/code&gt; that are responsible for all that good stuff.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Invocations of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftc&lt;/code&gt;, without the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-frontend&lt;/code&gt; argument, invoke the &lt;em&gt;driver&lt;/em&gt;, not the frontend. The Swift driver doesn't type-check Swift source code, it generates jobs that invoke &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift -frontend&lt;/code&gt;. Those invocations of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift -frontend&lt;/code&gt;, in turn, do all the cool compiler stuff I think of when I think of compilers, such as type-checking.&lt;/p&gt;

&lt;h2 id=&quot;a-birds-eye-view-of-the-code-in-the-swift-driver&quot;&gt;A bird's-eye view of the code in the Swift driver&lt;/h2&gt;

&lt;p&gt;The basic idea of the Swift driver is that it splits up invocations of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftc&lt;/code&gt; into other, more granular invocations of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift -frontend&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ld&lt;/code&gt;, and other programs. These child invocations are called &quot;jobs&quot;. So, how does it accomplish this? What does the source code in the Swift driver look like, at a high level?&lt;/p&gt;

&lt;p&gt;The driver source code exists in two primary components: the driver executable C++ code, and the C++ libswiftDriver library code. The driver executable calls into the libswiftDriver library code to perform most of its tasks. libswiftDriver's interfaces are declared in its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.h&lt;/code&gt; header files, in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/include/swift/Driver&lt;/code&gt;. The implementation of those interfaces is in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.cpp&lt;/code&gt; implementation files in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/lib/Driver&lt;/code&gt;. The driver executable is implemented in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.cpp&lt;/code&gt; files in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/tools/driver&lt;/code&gt;, primarily &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/tools/driver/driver.cpp&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://d3vv6lp55qjaqc.cloudfront.net/items/0X2s1L422n2b1s392g0B/swiftDriver%2BlibswiftDriver.png?X-CloudApp-Visitor-Id=543005&quot; alt=&quot;The Swift driver in swift/tools/driver calls the libswiftDriver library code from swift/include/swift/Driver and swift/lib/Driver.&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The above diagram isn't a complete graph of library dependencies for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftc&lt;/code&gt; executables. Both the driver executable and libswiftDriver make use of other apple/swift and LLVM libraries, such as libswiftOption (for parsing command-line arguments like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-frontend&lt;/code&gt;) and libLLVMSupport (which provides utility functions for reading and creating files, among other things). I'll cover these in more detail later.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;CMake files, specifically &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/tools/driver/CMakeLists.txt&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/lib/Driver/CMakeLists.txt&lt;/code&gt;, define how the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftc&lt;/code&gt; executables and how the libswiftDriver library are built.&lt;/p&gt;

&lt;h2 id=&quot;how-swift-swiftc-and-libswiftdriver-are-built-and-just-what-is-the-difference-between-swift-and-swiftc-anyway&quot;&gt;How &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftc&lt;/code&gt;, and libswiftDriver are built (and just what is the difference between &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftc&lt;/code&gt;, anyway?)&lt;/h2&gt;

&lt;p&gt;I explained the &lt;a href=&quot;/the-swift-compilers-build-system&quot;&gt;Swift build system&lt;/a&gt; and &lt;a href=&quot;/reading-and-understanding-the-cmake-in-apple-swift&quot;&gt;how the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; executable is built&lt;/a&gt; in previous articles. To summarize those articles:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; build system is defined primarily in CMake. The top-level &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/CMakeLists.txt&lt;/code&gt; file is executed by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake&lt;/code&gt; executable, and that file in turn calls the CMake built-in function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_subdirectory()&lt;/code&gt; in order to execute the nested &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CMakeLists.txt&lt;/code&gt; files in other directories.&lt;/li&gt;
  &lt;li&gt;To understand how a particular set of source files are built, it makes sense to first look at the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CMakeLists.txt&lt;/code&gt; file that exists within the same directory as the source files.&lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CMakeLists.txt&lt;/code&gt; file at the same level as the Swift driver executable source file, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/tools/driver/driver.cpp&lt;/code&gt;, is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/tools/driver/CMakeLists.txt&lt;/code&gt;. That &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CMakeLists.txt&lt;/code&gt; file calls the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_swift_host_tool()&lt;/code&gt; function, a custom CMake function defined in the &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; project, in order to define how the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; executable should be built.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/tools/driver/CMakeLists.txt&lt;/code&gt; file doesn't just define how the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; executable is built. It also defines a symlink, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftc&lt;/code&gt;, that points to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/77282a3e8afd1c31ac8d154dd5691c399ee08623/tools/driver/CMakeLists.txt#L34-L36&quot;&gt;swift/tools/driver/CMakeLists.txt&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt; 1&lt;/span&gt;  &lt;span class=&quot;f&quot;&gt;add_swift_host_tool&lt;/span&gt;(swift
&lt;span class=&quot;ln&quot;&gt; 2&lt;/span&gt;    api_notes.cpp
&lt;span class=&quot;ln&quot;&gt; 3&lt;/span&gt;    driver.cpp
&lt;span class=&quot;ln&quot;&gt; 4&lt;/span&gt;    autolink_extract_main.cpp
&lt;span class=&quot;ln&quot;&gt; 5&lt;/span&gt;    modulewrap_main.cpp
&lt;span class=&quot;ln&quot;&gt; 6&lt;/span&gt;    swift_format_main.cpp
&lt;span class=&quot;ln&quot;&gt; 7&lt;/span&gt;    &lt;span class=&quot;cma&quot;&gt;LINK_LIBRARIES&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 8&lt;/span&gt;      swiftDriver
&lt;span class=&quot;ln&quot;&gt; 9&lt;/span&gt;      swiftFrontendTool
&lt;span class=&quot;ln&quot;&gt;10&lt;/span&gt;    &lt;span class=&quot;cma&quot;&gt;LLVM_COMPONENT_DEPENDS&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;11&lt;/span&gt;      DebugInfoCodeView
&lt;span class=&quot;ln&quot;&gt;12&lt;/span&gt;    &lt;span class=&quot;cma&quot;&gt;SWIFT_COMPONENT&lt;/span&gt; compiler
&lt;span class=&quot;ln&quot;&gt;13&lt;/span&gt;  )
&lt;span class=&quot;ln&quot;&gt;..&lt;/span&gt;
&lt;div class=&quot;hi&quot;&gt;&lt;span class=&quot;ln&quot;&gt;34&lt;/span&gt;  &lt;span class=&quot;f&quot;&gt;add_swift_tool_symlink&lt;/span&gt;(swiftc swift compiler)&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt;35&lt;/span&gt;  &lt;span class=&quot;f&quot;&gt;add_swift_tool_symlink&lt;/span&gt;(swift-autolink-extract swift autolink-driver)
&lt;span class=&quot;ln&quot;&gt;36&lt;/span&gt;  &lt;span class=&quot;f&quot;&gt;add_swift_tool_symlink&lt;/span&gt;(swift-format swift editor-integration)
&lt;/pre&gt;
&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;The name of the function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_swift_tool_symlink()&lt;/code&gt; is fairly straightforward, and so I can guess that it creates a symlink named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftc&lt;/code&gt; that points to the executable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt;. To confirm this guess, I can use the techniques I described in &lt;a href=&quot;/reading-and-understanding-the-cmake-in-apple-swift&quot;&gt;Reading and Understanding the CMake in apple/swift&lt;/a&gt;. A &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git grep&lt;/code&gt; for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;function(add_swift_tool_symlink&lt;/code&gt; reveals the function's definition in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/cmake/modules/AddSwift.cmake&lt;/code&gt;. The function calls through to two LLVM CMake functions. Two more &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git grep&lt;/code&gt; invocations, this time in the LLVM repository, can point me to those functions' definitions, in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;llvm/cmake/modules/AddLLVM.cmake&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As the CMake confirms, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftc&lt;/code&gt; executable is really just a symlink to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; executable. But why create a symlink?&lt;/p&gt;

&lt;h2 id=&quot;swift-driver-modes-or-a-swift-by-any-other-name&quot;&gt;Swift &quot;driver modes&quot;, or: &quot;A &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; by any other name&quot;&lt;/h2&gt;

&lt;p&gt;You may have noticed, in the CMake snippet above, that not only does the &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; build system produce a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftc&lt;/code&gt; symlink, it also creates symlinks named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift-autolink-extract&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift-format&lt;/code&gt;. Each one of these represents a different &quot;driver mode&quot; or, as it's referenced in the libswiftDriver source code, a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift::driver::Driver::DriverKind&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/77282a3e8afd1c31ac8d154dd5691c399ee08623/include/swift/Driver/Driver.h#L120-L125&quot;&gt;swift/include/swift/Driver/Driver.h&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;120&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;enum class&lt;/span&gt; DriverKind {
&lt;span class=&quot;ln&quot;&gt;121&lt;/span&gt;      Interactive,     &lt;span class=&quot;c&quot;&gt;// swift&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;122&lt;/span&gt;      Batch,           &lt;span class=&quot;c&quot;&gt;// swiftc&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;123&lt;/span&gt;      AutolinkExtract, &lt;span class=&quot;c&quot;&gt;// swift-autolink-extract&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;124&lt;/span&gt;      SwiftFormat      &lt;span class=&quot;c&quot;&gt;// swift-format&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;125&lt;/span&gt;    };
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Each of these driver modes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Accepts a different set of arguments. For example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftc&lt;/code&gt; accepts the argument &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-dump-ast&lt;/code&gt;, but &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift -dump-ast&lt;/code&gt; is invalid.&lt;/li&gt;
  &lt;li&gt;Performs a different set of tasks. For example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift-format&lt;/code&gt; tidies up the whitespace and indentation in Swift source code files. It does not perform any of the compilation that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftc&lt;/code&gt; does.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &quot;driver mode&quot; is determined by libswiftDriver, which contains code that checks the name of the executable that is currently being run:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/77282a3e8afd1c31ac8d154dd5691c399ee08623/lib/Driver/Driver.cpp#L94-L100&quot;&gt;swift/lib/Driver/Driver.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt; 79&lt;/span&gt;  &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Driver&lt;/span&gt;::parseDriverKind(&lt;span class=&quot;cl&quot;&gt;ArrayRef&lt;/span&gt;&amp;lt;&lt;span class=&quot;k&quot;&gt;const char&lt;/span&gt; *&amp;gt; Args) {
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 94&lt;/span&gt;    &lt;span class=&quot;cl&quot;&gt;Optional&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;DriverKind&lt;/span&gt;&amp;gt; Kind =
&lt;span class=&quot;ln&quot;&gt; 95&lt;/span&gt;    llvm::&lt;span class=&quot;cl&quot;&gt;StringSwitch&lt;/span&gt;&amp;lt;&lt;span class=&quot;cl&quot;&gt;Optional&lt;/span&gt;&amp;lt;&lt;span class=&quot;t&quot;&gt;DriverKind&lt;/span&gt;&amp;gt;&amp;gt;(DriverName)
&lt;span class=&quot;ln&quot;&gt; 96&lt;/span&gt;    .&lt;span class=&quot;f&quot;&gt;Case&lt;/span&gt;(&lt;span class=&quot;s&quot;&gt;&quot;swift&quot;&lt;/span&gt;, &lt;span class=&quot;t&quot;&gt;DriverKind&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;Interactive&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt; 97&lt;/span&gt;    .&lt;span class=&quot;f&quot;&gt;Case&lt;/span&gt;(&lt;span class=&quot;s&quot;&gt;&quot;swiftc&quot;&lt;/span&gt;, &lt;span class=&quot;t&quot;&gt;DriverKind&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;Batch&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt; 98&lt;/span&gt;    .&lt;span class=&quot;f&quot;&gt;Case&lt;/span&gt;(&lt;span class=&quot;s&quot;&gt;&quot;swift-autolink-extract&quot;&lt;/span&gt;, &lt;span class=&quot;t&quot;&gt;DriverKind&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;AutolinkExtract&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt; 99&lt;/span&gt;    .&lt;span class=&quot;f&quot;&gt;Case&lt;/span&gt;(&lt;span class=&quot;s&quot;&gt;&quot;swift-format&quot;&lt;/span&gt;, &lt;span class=&quot;t&quot;&gt;DriverKind&lt;/span&gt;::&lt;span class=&quot;cn&quot;&gt;SwiftFormat&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt;100&lt;/span&gt;    .&lt;span class=&quot;f&quot;&gt;Default&lt;/span&gt;(&lt;span class=&quot;cn&quot;&gt;None&lt;/span&gt;);
&lt;span class=&quot;ln&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;106&lt;/span&gt;  }
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;That is, when I invoke &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; on the command line, that causes libswiftDriver to run in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DriverKind::Interactive&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftc&lt;/code&gt; results in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DriverKind::Batch&lt;/code&gt;. In other parts of libswiftDriver, the current &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DriverKind&lt;/code&gt; is referenced when deciding which command-line options to accept as valid, or which actions to perform.&lt;/p&gt;

&lt;p&gt;So while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftc&lt;/code&gt; executes the exact same driver code as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt;, the fact that it's named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftc&lt;/code&gt; causes libswiftDriver to behave differently.&lt;/p&gt;

&lt;p&gt;This is actually a fun quirk in how Swift works: you can't invoke &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; through a symlink the driver code isn't aware of. For example, I tried creating a symlink to my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; executable, like so:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;c&quot;&gt;# Change directories to where my 'swift' executable lives:&lt;/span&gt;
&lt;span class=&quot;cmd&quot;&gt;cd&lt;/span&gt; ~/local/Source/apple/build/Ninja-ReleaseAssert/swift-macosx-x86_64/bin/

&lt;span class=&quot;c&quot;&gt;# Create an alias: 'my-swift-alias' points to 'swift':&lt;/span&gt;
&lt;span class=&quot;cmd&quot;&gt;ln&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-s&lt;/span&gt; swift my-swift-alias

&lt;span class=&quot;c&quot;&gt;# Attempt to print the help text for 'swift', by invoking&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# my alias:&lt;/span&gt;
&lt;span class=&quot;cexec&quot;&gt;my-swift-alias&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-help&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;Sure enough, this results in an error. The Swift driver doesn't recognize the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;my-swift-alias&lt;/code&gt; driver mode:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;diag&quot;&gt;&amp;lt;unknown&amp;gt;:0: &lt;span class=&quot;de&quot;&gt;error:&lt;/span&gt; invalid value 'my-swift-alias' in '--driver-mode='&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;As the error message hints at, I can override the Swift driver behavior that infers the driver mode from the name of the executable by using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--driver-mode=&lt;/code&gt; command-line option:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;c&quot;&gt;# Print out help text as if I were invoking&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# the 'swift' executable:&lt;/span&gt;
&lt;span class=&quot;cexec&quot;&gt;my-swift-alias&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;--driver-mode=swift -help&lt;/span&gt;
&lt;/pre&gt;

&lt;h2 id=&quot;another-look-at-the-driver-executable-and-libswiftdriver-source-code-and-next-steps&quot;&gt;Another look at the driver executable and libswiftDriver source code, and next steps&lt;/h2&gt;

&lt;p&gt;To recap:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The CMake code for the driver executable not only defines an executable named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt;, it also defines symlinks pointing to that executable, such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftc&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift-format&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;The driver determines the mode in which it's being run in, in part based on the name of the executable or symlink its being run with, and then it parses its command-line options based on that driver mode.&lt;/li&gt;
  &lt;li&gt;Based on its mode and the arguments passed to it, the driver executable calls out to libswiftDriver to build a series of &quot;jobs&quot;. These jobs are invocations of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift -frontend&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ld&lt;/code&gt;, or other executables. It's &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift -frontend&lt;/code&gt; that performs the actual type-checking and compilation of Swift source code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Parsing command-line arguments and splitting up a driver invocation into child jobs involves a lot of different classes, most of which are defined in libswiftDriver. To name just a few, there's &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift::Driver&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift::Compilation&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift::driver::ToolChain&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift::Action&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift::JobAction&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift::Job&lt;/code&gt;, and more. I'll go over the interactions between these classes in more detail in the next article in this series, and then I'll start writing about incremental compilation and other advanced features in libswiftDriver.&lt;/p&gt;

&lt;p&gt;In the meantime, try exploring this treemap of the source code in the Swift driver. Each rectangle is sized proportional to the number of source lines of code it contains. Click or tap on a rectangle to view it in GitHub.&lt;/p&gt;

&lt;svg id=&quot;swift-driver-treemap&quot;&gt;&lt;/svg&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;/js/swift-driver-treemap.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;The majority of the source code we'll cover next time is in three files:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/7f8e0ec99dda6259d32dc3166f81583596086302/tools/driver/driver.cpp&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/tools/driver/driver.cpp&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/7f8e0ec99dda6259d32dc3166f81583596086302/lib/Driver/Driver.cpp&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/lib/Driver/Driver.cpp&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/7f8e0ec99dda6259d32dc3166f81583596086302/lib/Driver/ToolChains.cpp&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/lib/Driver/ToolChains.cpp&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</content><author><name></name></author><category term="swiftc" /><summary type="html">This article contains some content especially for patrons. Although it reads coherently as-is, to read the full article, please consider supporting me on Patreon, or click here if you are already a patron. $10/month gives you access to all content I will ever write on this website.</summary></entry><entry><title type="html">Reading and Understanding the CMake in apple/swift</title><link href="https://modocache.io/reading-and-understanding-the-cmake-in-apple-swift" rel="alternate" type="text/html" title="Reading and Understanding the CMake in apple/swift" /><published>2017-09-16T17:00:00+00:00</published><updated>2017-09-16T17:00:00+00:00</updated><id>https://modocache.io/reading-and-understanding-the-cmake-in-apple-swift</id><content type="html" xml:base="https://modocache.io/reading-and-understanding-the-cmake-in-apple-swift">&lt;p&gt;In &lt;a href=&quot;/the-swift-compilers-build-system&quot;&gt;my last post&lt;/a&gt;, I invoked &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake&lt;/code&gt; in order to build &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt;. When I invoked &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake&lt;/code&gt;, I gave it the path to a source code directory. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake&lt;/code&gt; then executes the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CMakeLists.txt&lt;/code&gt; file in that directory.&lt;/p&gt;

&lt;p&gt;In the case of &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt;, that means the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/CMakeLists.txt&lt;/code&gt; CMake script file is executed.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/CMakeLists.txt&lt;/code&gt;, in turn, calls the CMake function &lt;a href=&quot;https://cmake.org/cmake/help/latest/command/add_subdirectory.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_subdirectory()&lt;/code&gt;&lt;/a&gt; to include its child directories. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CMakeLists.txt&lt;/code&gt; files in those subdirectories then include their children, and so on:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;fsd&quot;&gt;~/local/Source/apple/swift/&lt;/span&gt;&lt;span class=&quot;fsf&quot;&gt;CMakeLists.txt&lt;/span&gt;
    &lt;span class=&quot;fsd&quot;&gt;lib/&lt;/span&gt;&lt;span class=&quot;fsf&quot;&gt;CMakeLists.txt&lt;/span&gt;
        &lt;span class=&quot;fsd&quot;&gt;Driver/&lt;/span&gt;&lt;span class=&quot;fsf&quot;&gt;CMakeLists.txt&lt;/span&gt;
            &lt;span class=&quot;fsf&quot;&gt;Action.cpp, Compilation.cpp, ...&lt;/span&gt;
        &lt;span class=&quot;fsd&quot;&gt;Frontend/&lt;/span&gt;&lt;span class=&quot;fsf&quot;&gt;CMakeLists.txt&lt;/span&gt;
            &lt;span class=&quot;fsf&quot;&gt;Frontend.cpp, FrontendOptions.cpp, ...&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;fsd&quot;&gt; tools/&lt;/span&gt;&lt;span class=&quot;fsf&quot;&gt;CMakeLists.txt&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;...&lt;/span&gt;
    &lt;span class=&quot;fsd&quot;&gt; test/&lt;/span&gt;&lt;span class=&quot;fsf&quot;&gt;CMakeLists.txt&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;...&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;&lt;a href=&quot;https://d3vv6lp55qjaqc.cloudfront.net/items/15120j042G3n032G2Z3o/recursive-make-swift-3.gif?X-CloudApp-Visitor-Id=543005&quot;&gt;Here's&lt;/a&gt;  an animated &quot;time-lapse&quot; of this process.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;This recursive execution of build system code is referred to as the &lt;a href=&quot;http://aegis.sourceforge.net/auug97.pdf&quot;&gt;recursive make&lt;/a&gt; pattern. The LLVM, Clang, and &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; projects all structure their CMake code following this pattern.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By convention, a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CMakeLists.txt&lt;/code&gt; file in a directory describes how the source code in that directory is built. For example, to understand how the source code in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/lib/Driver&lt;/code&gt; is compiled, I would first read the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/lib/Driver/CMakeLists.txt&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;In addition, &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; defines helper CMake functions in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/cmake/modules&lt;/code&gt; directory. The top-level &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/CMakeLists.txt&lt;/code&gt; file includes these CMake functions by first appending the directory to the CMake module path…&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/74183c401632907b3f0d9f4e880d531744ed98a1/CMakeLists.txt#L4-L5&quot;&gt;swift/CMakeLists.txt&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;4  &lt;/span&gt;&lt;span class=&quot;ofm&quot;&gt;list&lt;/span&gt;(&lt;span class=&quot;cma&quot;&gt;APPEND&lt;/span&gt; &lt;span class=&quot;cmv&quot;&gt;CMAKE_MODULE_PATH&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;5  &lt;/span&gt;    &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${CMAKE_CURRENT_SOURCE_DIR}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/cmake/modules&quot;&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;…and then including them by name by using the CMake &lt;a href=&quot;https://cmake.org/cmake/help/latest/command/include.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;include()&lt;/code&gt;&lt;/a&gt; function:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/74183c401632907b3f0d9f4e880d531744ed98a1/CMakeLists.txt#L15-L16&quot;&gt;swift/CMakeLists.txt&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;15  &lt;/span&gt;&lt;span class=&quot;fs&quot;&gt;include&lt;/span&gt;(SwiftUtils)        &lt;span class=&quot;c&quot;&gt;# Loads swift/cmake/modules/SwiftUtils.cmake.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;16  &lt;/span&gt;&lt;span class=&quot;fs&quot;&gt;include&lt;/span&gt;(CheckSymbolExists) &lt;span class=&quot;c&quot;&gt;# Loads swift/cmake/modules/CheckSymbolExists.cmake.&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Including the two files above makes functions defined therein available to all CMake scripts in the project. For example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/cmake/modules/SwiftUtils.cmake&lt;/code&gt; defines a function named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;precondition()&lt;/code&gt;, which halts CMake with an error at configuration time if a variable is not defined.&lt;/p&gt;

&lt;p&gt;I find reading the CMake in &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; to be straightforward, because the order in which the CMake is executed is clear. All I have to do is read from the top of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/CMakeLists.txt&lt;/code&gt; to the bottom, following any calls to &lt;a href=&quot;https://cmake.org/cmake/help/latest/command/include.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;include()&lt;/code&gt;&lt;/a&gt; or &lt;a href=&quot;https://cmake.org/cmake/help/latest/command/add_subdirectory.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_subdirectory()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;reading-appleswift-cmake-by-example-the-swift-executable&quot;&gt;Reading apple/swift CMake by example: the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; executable&lt;/h2&gt;

&lt;p&gt;The above description should be enough to determine how, for example, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; compiler executable is configured and built. Here's how I found out:&lt;/p&gt;

&lt;p&gt;First, I know that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; is, at its core, just a command-line C++ program, so it must have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main()&lt;/code&gt; function I can search for:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;cmd&quot;&gt;git&lt;/span&gt; \
    &lt;span class=&quot;copt&quot;&gt;-C&lt;/span&gt; ~/local/Source/apple/swift \
    &lt;span class=&quot;copt&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;int main(&quot;&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; project contains many C++ programs, and so this search returns several results. Looking at the returned file names and their contents, however, it soon becomes clear that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/tools/driver/driver.cpp&lt;/code&gt; is the file that defines the entry point to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; executable.&lt;/p&gt;

&lt;p&gt;As I mentioned above, I can usually find out how a source code file is compiled by looking for a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CMakeLists.txt&lt;/code&gt; file in the same directory. Here, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/tools/driver/CMakeLists.txt&lt;/code&gt; is in the same directory as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;driver.cpp&lt;/code&gt;. The first few lines of code in that CMake file are exactly what I'm looking for:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/74183c401632907b3f0d9f4e880d531744ed98a1/tools/driver/CMakeLists.txt#L1-L13&quot;&gt;swift/tools/driver/CMakeLists.txt&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt; 1  &lt;/span&gt;&lt;span class=&quot;f&quot;&gt;add_swift_host_tool&lt;/span&gt;(swift
&lt;span class=&quot;ln&quot;&gt; 2  &lt;/span&gt;  api_notes.cpp
&lt;span class=&quot;ln&quot;&gt; 3  &lt;/span&gt;  driver.cpp
&lt;span class=&quot;ln&quot;&gt; 4  &lt;/span&gt;  autolink_extract_main.cpp
&lt;span class=&quot;ln&quot;&gt; 5  &lt;/span&gt;  modulewrap_main.cpp
&lt;span class=&quot;ln&quot;&gt; 6  &lt;/span&gt;  swift_format_main.cpp
&lt;span class=&quot;ln&quot;&gt; 7  &lt;/span&gt;  &lt;span class=&quot;cma&quot;&gt;LINK_LIBRARIES&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt; 8  &lt;/span&gt;    swiftDriver
&lt;span class=&quot;ln&quot;&gt; 9  &lt;/span&gt;    swiftFrontendTool
&lt;span class=&quot;ln&quot;&gt;10  &lt;/span&gt;  &lt;span class=&quot;cma&quot;&gt;LLVM_COMPONENT_DEPENDS&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;11  &lt;/span&gt;    DebugInfoCodeView
&lt;span class=&quot;ln&quot;&gt;12  &lt;/span&gt;  &lt;span class=&quot;cma&quot;&gt;SWIFT_COMPONENT&lt;/span&gt; compiler
&lt;span class=&quot;ln&quot;&gt;13  &lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;It appears this &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_swift_host_tool()&lt;/code&gt; function takes the name of the executable to be built (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt;), a list of source files (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;api_notes.cpp driver.cpp ...&lt;/code&gt;), a list of libraries to link (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LINK_LIBRARIES swiftDriver ...&lt;/code&gt;), a list of LLVM dependencies, and something called a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SWIFT_COMPONENT&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Based on its name, I can guess that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_swift_host_tool()&lt;/code&gt; function is not built into CMake, so to understand exactly what it does, I can't consult the CMake documentation. Instead, I can &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git grep&lt;/code&gt; for its definition:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;cmd&quot;&gt;git&lt;/span&gt; \
    &lt;span class=&quot;copt&quot;&gt;-C&lt;/span&gt; ~/local/Source/apple/swift \
    &lt;span class=&quot;copt&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;--line-number&lt;/span&gt; \
    &lt;span class=&quot;s&quot;&gt;&quot;function(add_swift_host_tool&quot;&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;The above command outputs:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;gfn&quot;&gt;cmake/modules/AddSwift.cmake:2104:&lt;/span&gt;&lt;span class=&quot;gm&quot;&gt;function(add_swift_host_tool&lt;/span&gt; executable)
&lt;/pre&gt;

&lt;p&gt;So it looks like the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_swift_host_tool()&lt;/code&gt; function is defined in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/cmake/modules/AddSwift.cmake&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;For &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_swift_host_tool()&lt;/code&gt; to be called from within &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/tools/driver/CMakeLists.txt&lt;/code&gt;, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AddSwift.cmake&lt;/code&gt; module must have been included at some point. Sure enough, a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git grep&lt;/code&gt; for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;include(AddSwift)&quot;&lt;/code&gt; shows that it is included from within &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/CMakeLists.txt&lt;/code&gt;. No magic here!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here's the definition of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_swift_host_tool()&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/74183c401632907b3f0d9f4e880d531744ed98a1/cmake/modules/AddSwift.cmake#L2104-L2130&quot;&gt;swift/cmake/modules/AddSwift.cmake&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;2104  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;(add_swift_host_tool executable)
&lt;span class=&quot;ln&quot;&gt;2105  &lt;/span&gt;  &lt;span class=&quot;fs&quot;&gt;cmake_parse_arguments&lt;/span&gt;(
&lt;span class=&quot;ln&quot;&gt;2106  &lt;/span&gt;     ADDSWIFTHOSTTOOL &lt;span class=&quot;c&quot;&gt;# prefix&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2107  &lt;/span&gt;     &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# options&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2108  &lt;/span&gt;     &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# single-value args&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2109  &lt;/span&gt;     &lt;span class=&quot;s&quot;&gt;&quot;SWIFT_COMPONENT&quot;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# multi-value args&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2110  &lt;/span&gt;     &lt;span class=&quot;si&quot;&gt;${ARGN}&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt;2111  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2112  &lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;# Create the executable rule.&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2113  &lt;/span&gt;  &lt;span class=&quot;f&quot;&gt;add_swift_executable&lt;/span&gt;(&lt;span class=&quot;si&quot;&gt;${executable}&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;${ADDSWIFTHOSTTOOL_UNPARSED_ARGUMENTS}&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt;....  &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2130  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;()
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;First, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_swift_host_tool()&lt;/code&gt; function parses any arguments it has been invoked with, by using the CMake function &lt;a href=&quot;https://cmake.org/cmake/help/latest/command/cmake_parse_arguments.html#command:cmake_parse_arguments&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake_parse_arguments()&lt;/code&gt;&lt;/a&gt;. Then, it calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_swift_executable()&lt;/code&gt; with a subset of those arguments.&lt;/p&gt;

&lt;p&gt;Like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_swift_host_tool()&lt;/code&gt;, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_swift_executable()&lt;/code&gt; function is also defined within the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake/modules/AddSwift.cmake&lt;/code&gt; module. It's documented as &quot;add an executable for the host machine.&quot;&lt;/p&gt;

&lt;p&gt;The &quot;host machine&quot; part of the documentation above is important. &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; CMake is responsible for describing how to build not only executables like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt;, but also the Swift runtime and standard library. The Swift runtime could be used on the macOS machine I'm using to build &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt;, or it could be run on an iOS device, or a tvOS device, or even an Android device.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; CMake refers to the machine I'm using to configure and build &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; as the &lt;em&gt;host machine&lt;/em&gt;. It refers to the platform I'm building for as the &lt;em&gt;target&lt;/em&gt;. macOS, iOS, tvOS, and Android are all valid &lt;em&gt;targets&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_swift_executable()&lt;/code&gt; describes how to build an executable for the host machine. In my case, that's the macOS machine I'm using to configure and build &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/74183c401632907b3f0d9f4e880d531744ed98a1/cmake/modules/AddSwift.cmake#L2063-L2094&quot;&gt;swift/cmake/modules/AddSwift.cmake&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;2063   &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;(add_swift_executable name)
&lt;span class=&quot;ln&quot;&gt;....   &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2083   &lt;/span&gt;  &lt;span class=&quot;f&quot;&gt;_add_swift_executable_single&lt;/span&gt;(
&lt;span class=&quot;ln&quot;&gt;2084   &lt;/span&gt;      &lt;span class=&quot;si&quot;&gt;${name}&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2085   &lt;/span&gt;      &lt;span class=&quot;si&quot;&gt;${SWIFTEXE_SOURCES}&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2086   &lt;/span&gt;      &lt;span class=&quot;cma&quot;&gt;DEPENDS&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;${SWIFTEXE_DEPENDS}&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2087   &lt;/span&gt;      &lt;span class=&quot;cma&quot;&gt;LLVM_COMPONENT_DEPENDS&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;${SWIFTEXE_LLVM_COMPONENT_DEPENDS}&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2088   &lt;/span&gt;      &lt;span class=&quot;cma&quot;&gt;LINK_LIBRARIES&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;${SWIFTEXE_LINK_LIBRARIES}&lt;/span&gt;
&lt;div class=&quot;hi&quot;&gt;&lt;span class=&quot;ln&quot;&gt;2089   &lt;/span&gt;      &lt;span class=&quot;cma&quot;&gt;SDK&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;${SWIFT_HOST_VARIANT_SDK}&lt;/span&gt;&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt;2090   &lt;/span&gt;      &lt;span class=&quot;cma&quot;&gt;ARCHITECTURE&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;${SWIFT_HOST_VARIANT_ARCH}&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2091   &lt;/span&gt;      &lt;span class=&quot;si&quot;&gt;${SWIFTEXE_EXCLUDE_FROM_ALL_FLAG}&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2092   &lt;/span&gt;      &lt;span class=&quot;si&quot;&gt;${SWIFTEXE_DONT_STRIP_NON_MAIN_SYMBOLS_FLAG}&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2093   &lt;/span&gt;      &lt;span class=&quot;si&quot;&gt;${SWIFTEXE_DISABLE_ASLR_FLAG}&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt;2094   &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;()
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;All &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_swift_executable()&lt;/code&gt; does is parse arguments and call another function, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_add_swift_executable_single()&lt;/code&gt;. When it does so, it sends the argument &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SDK ${CMAKE_HOST_VARIANT_SDK}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The term &quot;SDK&quot; here is misleading; it means the target for which to build the executable. In this case, its being set as the value of the variable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CMAKE_HOST_VARIANT_SDK&lt;/code&gt;, which is set to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;OSX&quot;&lt;/code&gt; at a higher level of the recursive CMake.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;h3 id=&quot;how-can-i-be-sure-the-value-of-cmake_host_variant_sdk-is-being-set-to-osx&quot;&gt;How can I be sure the value of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CMAKE_HOST_VARIANT_SDK&lt;/code&gt; is being set to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;OSX&quot;&lt;/code&gt;?&lt;/h3&gt;

  &lt;p&gt;There are two ways to confirm the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CMAKE_HOST_VARIANT_SDK&lt;/code&gt; that's being passed as an argument to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_add_swift_executable_single()&lt;/code&gt;. The first is by using the CMake function &lt;a href=&quot;https://cmake.org/cmake/help/latest/command/message.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;message()&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;

  &lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/74183c401632907b3f0d9f4e880d531744ed98a1/cmake/modules/AddSwift.cmake#L2083-L2085&quot;&gt;cmake/modules/AddSwift.cmake&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt;++++   &lt;/span&gt;  &lt;span class=&quot;ofm&quot;&gt;message&lt;/span&gt;(&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt;++++   &lt;/span&gt;    &lt;span class=&quot;cma&quot;&gt;STATUS&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt;++++   &lt;/span&gt;    &lt;span class=&quot;s&quot;&gt;&quot;Adding Swift executable '&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${name}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;' for &quot;&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt;++++   &lt;/span&gt;    &lt;span class=&quot;s&quot;&gt;&quot;SDK '&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${SWIFT_HOST_VARIANT_SDK}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&quot;&lt;/span&gt;)&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt;2083   &lt;/span&gt;  _add_swift_executable_single(
&lt;span class=&quot;ln&quot;&gt;2084   &lt;/span&gt;        &lt;span class=&quot;si&quot;&gt;${name}&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;2085   &lt;/span&gt;        &lt;span class=&quot;si&quot;&gt;${SWIFTEXE_SOURCES}&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;....   &lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;

  &lt;p&gt;Adding the above results in the following output when I run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake&lt;/code&gt; to configure the project:&lt;/p&gt;

  &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;-- Adding Swift executable 'swift' for SDK 'OSX'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;/div&gt;

  &lt;p&gt;Another way is to run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake&lt;/code&gt; using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--trace-expand&lt;/code&gt; option. This prints to stderr every single line of CMake that is executed, along with the values of the variables on those lines. That's a ton of output, but I can use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt; to filter it for the specific line that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; is added:&lt;/p&gt;

  &lt;pre&gt;
&lt;span class=&quot;cmd&quot;&gt;cmake&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;--trace-expand&lt;/span&gt; \
    &lt;span class=&quot;c&quot;&gt;...&lt;/span&gt; 2&amp;gt;&amp;amp;1 | &lt;span class=&quot;cmd&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;_add_swift_executable_single(swift &quot;&lt;/span&gt;
&lt;/pre&gt;

  &lt;p&gt;That outputs the following:&lt;/p&gt;

  &lt;pre&gt;
&lt;span class=&quot;gfn&quot;&gt;/Users/bgesiak/local/Source/apple/standalone/swift/cmake/modules/AddSwift.cmake(2083):&lt;/span&gt;
  &lt;span class=&quot;gm&quot;&gt;_add_swift_executable_single(&lt;/span&gt;
  &lt;span class=&quot;gm&quot;&gt;    swift &lt;/span&gt;
      api_notes.cpp;driver.cpp;autolink_extract_main.cpp;modulewrap_main.cpp;swift_format_main.cpp
      DEPENDS
      LLVM_COMPONENT_DEPENDS DebugInfoCodeView
      LINK_LIBRARIES swiftDriver;swiftFrontendTool
      SDK OSX
      ARCHITECTURE x86_64
  )
&lt;/pre&gt;

  &lt;p&gt;I can see in both of the outputs above that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SDK OSX&lt;/code&gt; is set.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_add_swift_executable_single()&lt;/code&gt; function is the one that finally calls into the built-in CMake function &lt;a href=&quot;https://cmake.org/cmake/help/latest/command/add_executable.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_executable()&lt;/code&gt;&lt;/a&gt; in order to define the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; executable target:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/74183c401632907b3f0d9f4e880d531744ed98a1/cmake/modules/AddSwift.cmake#L1825-L1942&quot;&gt;swift/cmake/modules/AddSwift.cmake&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;1825   &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;(_add_swift_executable_single name)
&lt;span class=&quot;ln&quot;&gt;....   &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1907   &lt;/span&gt;  &lt;span class=&quot;ofm&quot;&gt;add_executable&lt;/span&gt;(&lt;span class=&quot;si&quot;&gt;${name}&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1907   &lt;/span&gt;      &lt;span class=&quot;si&quot;&gt;${SWIFTEXE_SINGLE_EXCLUDE_FROM_ALL_FLAG&lt;/span&gt;}
&lt;span class=&quot;ln&quot;&gt;1907   &lt;/span&gt;      &lt;span class=&quot;si&quot;&gt;${SWIFTEXE_SINGLE_SOURCES}&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1907   &lt;/span&gt;      &lt;span class=&quot;si&quot;&gt;${SWIFTEXE_SINGLE_EXTERNAL_SOURCES}&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt;....   &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1937   &lt;/span&gt;  &lt;span class=&quot;ofm&quot;&gt;target_link_libraries&lt;/span&gt;(&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${name}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;${SWIFTEXE_SINGLE_LINK_LIBRARIES}&lt;/span&gt; &lt;span class=&quot;si&quot;&gt;${SWIFTEXE_SINGLE_LINK_FAT_LIBRARIES}&lt;/span&gt;)
&lt;span class=&quot;ln&quot;&gt;....   &lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;1942   &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;endfunction&lt;/span&gt;()
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;You may recall that &lt;a href=&quot;https://cmake.org/cmake/help/latest/command/add_executable.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_executable()&lt;/code&gt;&lt;/a&gt; is the same function I used to describe the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello&lt;/code&gt; executable, in my toy CMake example from &lt;a href=&quot;/the-swift-compilers-build-system&quot;&gt;my last post&lt;/a&gt;. The function is how to describe, in CMake, that an executable is to be built.&lt;/p&gt;

&lt;p&gt;In addition, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_add_swift_executable_single()&lt;/code&gt; then calls &lt;a href=&quot;https://cmake.org/cmake/help/latest/command/target_link_libraries.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;target_link_libraries()&lt;/code&gt;&lt;/a&gt;. This is another built-in CMake function. It specifies that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; executable depends upon the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftDriver&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftFrontendTool&lt;/code&gt; libraries.&lt;/p&gt;

&lt;h3 id=&quot;a-recap-of-how-appleswift-cmake-describes-the-swift-executable&quot;&gt;A recap of how apple/swift CMake describes the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; executable&lt;/h3&gt;

&lt;p&gt;In summary, the story of how &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; CMake describes the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; executable is as follows:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;When &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake&lt;/code&gt; is run to configure the project, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/CMakeLists.txt&lt;/code&gt; is executed. It adds &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/cmake/modules&lt;/code&gt; to the CMake module path, and it includes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/cmake/modules/AddSwift.cmake&lt;/code&gt;, which defines the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_swift_host_tool()&lt;/code&gt; function.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/CMakeLists.txt&lt;/code&gt; then calls &lt;a href=&quot;https://cmake.org/cmake/help/latest/command/add_subdirectory.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_subdirectory()&lt;/code&gt;&lt;/a&gt; on each of its subdirectories, including &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/tools&lt;/code&gt;. Each of these subdirectories contains a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CMakeLists.txt&lt;/code&gt; file that includes their subdirectories in turn. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/tools/CMakeLists.txt&lt;/code&gt; is no exception, of course, and it calls &lt;a href=&quot;https://cmake.org/cmake/help/latest/command/add_subdirectory.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_subdirectory()&lt;/code&gt;&lt;/a&gt; on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/tools/driver&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/tools/driver/CMakeLists.txt&lt;/code&gt; contains the CMake code that describes how to build the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; executable. It invokes the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_swift_host_tool()&lt;/code&gt; function. This eventually calls CMake's built-in functions, &lt;a href=&quot;https://cmake.org/cmake/help/latest/command/add_executable.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_executable()&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://cmake.org/cmake/help/latest/command/target_link_libraries.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;target_link_libraries()&lt;/code&gt;&lt;/a&gt;, in order to describe a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; executable that is linked to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftDriver&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftFrontend&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;p&gt;The challenge for a contributor who hopes to improve Swift's CMake isn't that the CMake behaves in a magical way, or does unintuitive things. Rather, the challenge is simply that there is a lot of CMake code: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_add_swift_executable_single()&lt;/code&gt; alone is nearly 100 lines long.&lt;/p&gt;

&lt;p&gt;The entire &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; project has 189 CMake files, with over 8,000 significant lines of code. It also makes use of CMake functions defined in LLVM, which itself has 347 CMake files that contain over 10,000 significant lines!&lt;/p&gt;

&lt;p&gt;As a result, it's not practical for me to describe how every single component in &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; is configured. However, if you're interested in how, for example, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sil-opt&lt;/code&gt; executable is configured, this post has hopefully shown how you can find out for yourself.&lt;/p&gt;

&lt;p&gt;In an upcoming post, I'll use the methods above to learn and write about how some of the main components of the &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; project are configured:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The Swift compiler libraries that are used by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; executable. I'll explore how LLVM tools such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tablegen&lt;/code&gt; are used when, for example, defining &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; command-line options.&lt;/li&gt;
  &lt;li&gt;The Swift runtime and standard library. I'll write about the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;handle_swift_sources()&lt;/code&gt; function, which describes how Swift source files should be compiled and included in the finished library.&lt;/li&gt;
  &lt;li&gt;The Swift test suite. I'll explore how a Python script executes the unique set of tests used by the project.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Afterwards, I'll also write about specific CMake configurations that allow me to build just what I'm working on, in order to iterate quicker on Swift compiler development.&lt;/p&gt;</content><author><name></name></author><category term="swiftc" /><summary type="html">In my last post, I invoked cmake in order to build apple/swift. When I invoked cmake, I gave it the path to a source code directory. cmake then executes the CMakeLists.txt file in that directory.</summary></entry><entry><title type="html">The Swift Compiler's Build System</title><link href="https://modocache.io/the-swift-compilers-build-system" rel="alternate" type="text/html" title="The Swift Compiler's Build System" /><published>2017-09-10T17:00:00+00:00</published><updated>2017-09-10T17:00:00+00:00</updated><id>https://modocache.io/the-swift-compilers-build-system</id><content type="html" xml:base="https://modocache.io/the-swift-compilers-build-system">&lt;p&gt;&lt;a href=&quot;/getting-started-with-swift-development&quot;&gt;My last post&lt;/a&gt; explained that invoking &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script&lt;/code&gt; compiles the C++ source code in the &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; project and produces a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; compiler executable.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script&lt;/code&gt; is a Python script that invokes another script, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script-impl&lt;/code&gt;. That, in turn, invokes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake&lt;/code&gt;, in order to configure and then compile the source code in &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I'll refer to this process as the Swift &lt;em&gt;build system&lt;/em&gt;, and I'll explain it in detail below.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://d3vv6lp55qjaqc.cloudfront.net/items/0a1k412q0i103U1p2T1J/swift-build-system.png?X-CloudApp-Visitor-Id=543005&quot; alt=&quot;swift/utils/build-script invokes swift/utils/build-script-impl, which invokes cmake, which configures and builds apple/swift.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;There are many benefits to having a deep understanding of the build system:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;When making changes to the &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; project, I typically edit source code, then compile that code and run its tests. By understanding the various ways to invoke the build system, I'm able to compile and test the subset of the project that's related to my changes. It takes several minutes to run the entire Swift test suite, but only a fraction of a second to run just the tests I care about.&lt;/li&gt;
  &lt;li&gt;The build system has a great deal of room for improvement, so I found it to be a very easy place to start contributing to Swift. At the point that I received commit access to &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt;, over half of my pull requests had been related to the build system.&lt;/li&gt;
  &lt;li&gt;Improvements to the build system are impactful: a small change could result in faster builds of the Swift compiler, which in turn would speed up the work of the core team, other contributors, and CI. &lt;a href=&quot;https://reviews.llvm.org/rL312043&quot;&gt;This recent change to the LLVM build system&lt;/a&gt; is a good example: it reduced the number of actions performed by the build by several thousand actions, just by modifying seven lines of build system code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'll begin with the build system's core: CMake.&lt;/p&gt;

&lt;h2 id=&quot;using-cmake-an-example&quot;&gt;Using CMake: An example&lt;/h2&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake&lt;/code&gt; executable reads script files that describe how a software project builds. For example, here's how I'd use it to build a simple C++ program, composed of a single source file, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/tmp/src/hello.cpp&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;/tmp/class/hello.cpp&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;pps&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;int&lt;/span&gt; main() {
  &lt;span class=&quot;ot&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;oig&quot;&gt;cout&lt;/span&gt; &amp;lt;&amp;lt; &lt;span class=&quot;s&quot;&gt;&quot;Hello!&quot;&lt;/span&gt; &amp;lt;&amp;lt; &lt;span class=&quot;ot&quot;&gt;std&lt;/span&gt;::&lt;span class=&quot;ofm&quot;&gt;endl&lt;/span&gt;;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;;
}
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;I can describe how to build this program using the CMake language, in a file named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/CMakeLists.txt&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;/tmp/src/CMakeLists.txt&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;c&quot;&gt;# CMake version 3.2 or greater must&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# be used to configure this project.&lt;/span&gt;
&lt;span class=&quot;ofm&quot;&gt;cmake_minimum_required&lt;/span&gt;(&lt;span class=&quot;cma&quot;&gt;VERSION&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;3.2&lt;/span&gt;)

&lt;span class=&quot;c&quot;&gt;# The name of the project is 'Hello'.&lt;/span&gt;
&lt;span class=&quot;ofm&quot;&gt;project&lt;/span&gt;(Hello)

&lt;span class=&quot;c&quot;&gt;# When built, create an executable&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# named 'hello', by compiling the&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# source file 'hello.cpp'.&lt;/span&gt;
&lt;span class=&quot;ofm&quot;&gt;add_executable&lt;/span&gt;(hello
               hello.cpp)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake&lt;/code&gt; on the command line generates build files that are used to actually build the project:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;c&quot;&gt;# Read the CMakeLists.txt in the '/tmp/src' directory,&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# and generate build files at '/tmp/build'.&lt;/span&gt;
&lt;span class=&quot;cmd&quot;&gt;cmake&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-H&lt;/span&gt;/tmp/src &lt;span class=&quot;copt&quot;&gt;-B&lt;/span&gt;/tmp/build
&lt;/pre&gt;

&lt;p&gt;I can then compile the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello&lt;/code&gt; executable by executing the build files in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/tmp/build&lt;/code&gt;. By default, CMake generates a Makefile, which I can execute like so:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;cmd&quot;&gt;make&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-C&lt;/span&gt; /tmp/build
&lt;/pre&gt;

&lt;p&gt;Running the above command compiles and links the executable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/tmp/build/hello&lt;/code&gt;. Running that program outputs the expected text, &quot;Hello!&quot;.&lt;/p&gt;

&lt;p&gt;It's important to note that CMake itself doesn't compile and link the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello&lt;/code&gt; executable. CMake generates build files, and those build files compile and link &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello&lt;/code&gt;. I can instruct CMake to generate different kinds of build files, including an Xcode project:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;cmd&quot;&gt;cmake&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-H&lt;/span&gt;/tmp/src &lt;span class=&quot;copt&quot;&gt;-B&lt;/span&gt;/tmp/build-with-xcode &lt;span class=&quot;copt&quot;&gt;-G&lt;/span&gt; Xcode
&lt;/pre&gt;

&lt;p&gt;The above command generates &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/tmp/build-with-xcode/Hello.xcodeproj&lt;/code&gt;. I can open &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Hello.xcodeproj&lt;/code&gt; in Xcode and build hello by clicking the &quot;Run&quot; button:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://d3vv6lp55qjaqc.cloudfront.net/items/3D3O0B371i1L2B0J0w2y/Screen%20Shot%202017-09-05%20at%2011.17.29%20PM.png?X-CloudApp-Visitor-Id=543005&quot; class=&quot;image&quot;&gt;
  &lt;img src=&quot;https://d3vv6lp55qjaqc.cloudfront.net/items/3D3O0B371i1L2B0J0w2y/Screen%20Shot%202017-09-05%20at%2011.17.29%20PM.png?X-CloudApp-Visitor-Id=543005&quot; alt=&quot;Building the CMake project via the Xcode GUI.&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I can also build &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello&lt;/code&gt; via the command line, by invoking &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xcodebuild&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;cmd&quot;&gt;xcodebuild&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-project&lt;/span&gt; /tmp/build-with-xcode/Hello.xcodeproj
&lt;/pre&gt;

&lt;p&gt;Notice how, when I didn't specify a build file generator using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake -G&lt;/code&gt; argument, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake&lt;/code&gt; generated a Makefile, that I could build by invoking &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make&lt;/code&gt;. The Xcode project, on the other hand, was built by invoking &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xcodebuild&lt;/code&gt;. Remembering which invocation to use is tiresome, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake&lt;/code&gt; provides a convenient way to build using whichever files were generated:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;c&quot;&gt;# Build using the Makefile in the&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# /tmp/build directory.&lt;/span&gt;
&lt;span class=&quot;cmd&quot;&gt;cmake&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;--build&lt;/span&gt; /tmp/build

&lt;span class=&quot;c&quot;&gt;# Build using the .xcodeproj in the&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# /tmp/build-with-xcode directory.&lt;/span&gt;
&lt;span class=&quot;cmd&quot;&gt;cmake&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;--build&lt;/span&gt; /tmp/build-with-xcode
&lt;/pre&gt;

&lt;blockquote&gt;
  &lt;p&gt;CMake has many more features than just the three lines from my example above. I'll cover additional concepts below, as we encounter them in &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt;'s CMake code. To learn about CMake itself, try &lt;a href=&quot;https://llvm.org/docs/CMakePrimer.html&quot;&gt;LLVM's CMake primer&lt;/a&gt;, or &lt;a href=&quot;https://cmake.org/cmake/help/latest/manual/cmake-language.7.html&quot;&gt;the latest official CMake documentation&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;why-does-appleswift-use-cmake&quot;&gt;Why does &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; use CMake?&lt;/h2&gt;

&lt;p&gt;If you're an iOS developer, you've likely used Xcode project files to specify how your iOS application is built. So why couldn't the &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; project just use Xcode, too? The simple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello&lt;/code&gt; example above demonstrates several reasons why:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Xcode is a macOS application; it can't be used to build &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; on Linux machines. CMake, on the other hand, can generate one set of build files on Linux, or an Xcode project on macOS, or even a Visual Studio &quot;solution&quot; file on Windows. CMake's versatility allows it to generate the best build files for any platform.&lt;/li&gt;
  &lt;li&gt;Xcode project files are massive XML files that contain a large number of automatically generated ID strings. If you've worked on a small team of even two or three iOS developers, you know how hard it is to resolve multiple sets of changes to such files. Now just imagine resolving those conflicts across the 500+ contributors to &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt;! Because CMake uses a plain text scripting language, it's easy to read and modify.&lt;/li&gt;
  &lt;li&gt;Some of CMake's generators build projects faster than Xcode can. For example, try reconfiguring the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello&lt;/code&gt; example above to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake -G Ninja&lt;/code&gt;. This generates &lt;a href=&quot;https://ninja-build.org/&quot;&gt;Ninja&lt;/a&gt; build files, which are incredibly fast.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;building-appleswift-with-cmake&quot;&gt;Building &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; with CMake&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; project is essentially the same as my &quot;Hello&quot; project above. Yes, it is a larger project with more CMake code, but it can be configured and built in the same way &quot;Hello&quot; can. Doing so is a useful exercise in understanding the &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; build infrastructure.&lt;/p&gt;

&lt;p&gt;First, I'll clone the source code from the &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; project, as well as the three projects it depends upon:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt;-cmark: A Markdown parsing library, used by &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; when parsing Markdown documentation and comment blocks. This is Apple's fork of &lt;a href=&quot;https://github.com/commonmark/cmark&quot;&gt;commonmark/cmark&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt;-llvm: &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; uses LLVM in a variety of ways. The most prominent is as a &quot;backend&quot;: a library that generates the 0's and 1's that are capable of running on the target machine, whether that be an iOS armv7 device, a macOS x86_64 device, or even Android armv7. But &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; also uses LLVM utilities such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lit&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FileCheck&lt;/code&gt;, two tools used to run the &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; test suite.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt;-clang: &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; makes use of Clang, a C and C++ compiler, as part of its C and Objective-C interoperability.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I'll clone these projects into a directory named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/local/Source/apple/standalone&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;cmd&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;clone&lt;/span&gt; &lt;span class=&quot;u&quot;&gt;https://github.com/apple/swift-cmark.git&lt;/span&gt; \
    ~/local/Source/apple/standalone/swift-cmark

&lt;span class=&quot;cmd&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;clone&lt;/span&gt; &lt;span class=&quot;u&quot;&gt;https://github.com/apple/swift-llvm.git&lt;/span&gt; \
    ~/local/Source/apple/standalone/swift-llvm

&lt;span class=&quot;c&quot;&gt;# A bug in Swift's CMake requires this repository&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# to be named 'clang', not 'swift-clang'.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# https://bugs.swift.org/browse/SR-5778&lt;/span&gt;
&lt;span class=&quot;cmd&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;clone&lt;/span&gt; &lt;span class=&quot;u&quot;&gt;https://github.com/apple/swift-clang.git&lt;/span&gt; \
    ~/local/Source/apple/standalone/clang

&lt;span class=&quot;cmd&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;clone&lt;/span&gt; &lt;span class=&quot;u&quot;&gt;https://github.com/apple/swift.git&lt;/span&gt; \
    ~/local/Source/apple/standalone/swift
&lt;/pre&gt;

&lt;p&gt;Before I can configure and build &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt;, I need to build its dependencies. First is &lt;a href=&quot;https://github.com/apple/swift-cmark&quot;&gt;apple/swift-cmark&lt;/a&gt;. I'll generate Ninja build files because they're faster:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;c&quot;&gt;# First configure.&lt;/span&gt;
&lt;span class=&quot;cmd&quot;&gt;cmake&lt;/span&gt; \
    &lt;span class=&quot;copt&quot;&gt;-H&lt;/span&gt;~/local/Source/apple/standalone/swift-cmark \
    &lt;span class=&quot;copt&quot;&gt;-B&lt;/span&gt;~/local/Source/apple/standalone/swift-cmark-build \
    &lt;span class=&quot;copt&quot;&gt;-G&lt;/span&gt; Ninja

&lt;span class=&quot;c&quot;&gt;# Then build.&lt;/span&gt;
&lt;span class=&quot;cmd&quot;&gt;cmake&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;--build&lt;/span&gt; \
    ~/local/Source/apple/standalone/swift-cmark-build
&lt;/pre&gt;

&lt;p&gt;Next up is &lt;a href=&quot;https://github.com/apple/swift-llvm&quot;&gt;apple/swift-llvm&lt;/a&gt; and &lt;a href=&quot;https://github.com/apple/swift-clang&quot;&gt;apple/swift-clang&lt;/a&gt;. LLVM&quot;s CMake defines &lt;a href=&quot;https://cmake.org/cmake/help/latest/command/set.html#set-cache-entry&quot;&gt;cache entry settings&lt;/a&gt; that allow users to build both LLVM and Clang at once. As an example of a cache entry setting, consider the following, defined in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift-llvm/CMakeLists.txt&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/llvm-mirror/llvm/blob/95ed232373a9d7b86f7f42171c57209ec2f83579/CMakeLists.txt#L124-L125&quot;&gt;swift-llvm/CMakeLists.txt&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;124  &lt;/span&gt;&lt;span class=&quot;fs&quot;&gt;set&lt;/span&gt;(&lt;span class=&quot;vg&quot;&gt;LLVM_ENABLE_PROJECTS&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt; &lt;span class=&quot;cma&quot;&gt;CACHE&lt;/span&gt; &lt;span class=&quot;cma&quot;&gt;STRING&lt;/span&gt;
&lt;span class=&quot;ln&quot;&gt;125  &lt;/span&gt;        &lt;span class=&quot;s&quot;&gt;&quot;Semicolon-separated list of projects to build (${LLVM_ALL_PROJECTS}), or \&quot;all\&quot;.&quot;&lt;/span&gt;)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Users are able to set this value by invoking &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake -DLLVM_ENABLE_PROJECTS=&quot;foo&quot;&lt;/code&gt; when configuring &lt;a href=&quot;https://github.com/apple/swift-llvm&quot;&gt;apple/swift-llvm&lt;/a&gt;. The empty string &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;&quot;&lt;/code&gt; is the default value used when the user does not specify &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-DLLVM_ENABLE_PROJECTS=&lt;/code&gt; on the command line.&lt;/p&gt;

&lt;p&gt;A full explanation of LLVM and Clang's CMake build system is outside of the scope of this article – perhaps I'll write about it more next year – but the following invocations configure and build &lt;a href=&quot;https://github.com/apple/swift-llvm&quot;&gt;apple/swift-llvm&lt;/a&gt; and &lt;a href=&quot;https://github.com/apple/swift-clang&quot;&gt;apple/swift-clang&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;c&quot;&gt;# First configure.&lt;/span&gt;
&lt;span class=&quot;cmd&quot;&gt;cmake&lt;/span&gt; \
  &lt;span class=&quot;copt&quot;&gt;-H&lt;/span&gt;~/local/Source/apple/standalone/swift-llvm \
  &lt;span class=&quot;copt&quot;&gt;-B&lt;/span&gt;~/local/Source/apple/standalone/swift-llvm-build \
  &lt;span class=&quot;copt&quot;&gt;-G&lt;/span&gt; Ninja \
  &lt;span class=&quot;copt&quot;&gt;-DLLVM_ENABLE_PROJECTS=&lt;/span&gt;clang

&lt;span class=&quot;c&quot;&gt;# Then build.&lt;/span&gt;
&lt;span class=&quot;cmd&quot;&gt;cmake&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;--build&lt;/span&gt; \
    ~/local/Source/apple/standalone/swift-llvm-build

&lt;span class=&quot;c&quot;&gt;# Finally, create a symlink from the build&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# directory to the C++ headers included with Xcode.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# If you're following along, make sure the&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# path to your Xcode beta is the same as below.&lt;/span&gt;
&lt;span class=&quot;cmd&quot;&gt;ln&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-s&lt;/span&gt; \
    /Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++ \
    ~/local/Source/apple/standalone/swift-llvm-build/include
&lt;/pre&gt;

&lt;p&gt;Now, I can finally configure and build &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; itself. Like LLVM, &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; CMake defines many settings; for example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CMAKE_BUILD_TYPE&lt;/code&gt; is used to determine whether the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; executable is built with debugging symbols or not. I'll go into more of these options below, but for now the following invocations configure and build apple/swift:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;c&quot;&gt;# First configure.&lt;/span&gt;
&lt;span class=&quot;cmd&quot;&gt;cmake&lt;/span&gt; \
  &lt;span class=&quot;copt&quot;&gt;-H&lt;/span&gt;~/local/Source/apple/standalone/swift \
  &lt;span class=&quot;copt&quot;&gt;-B&lt;/span&gt;~/local/Source/apple/standalone/swift-build \
  &lt;span class=&quot;copt&quot;&gt;-G&lt;/span&gt; Ninja \
  &lt;span class=&quot;copt&quot;&gt;-DCMAKE_BUILD_TYPE=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Debug&quot;&lt;/span&gt; \
  &lt;span class=&quot;copt&quot;&gt;-DSWIFT_PATH_TO_CMARK_SOURCE=&lt;/span&gt;&lt;span class=&quot;cvar&quot;&gt;$HOME&lt;/span&gt;/local/Source/apple/standalone/swift-cmark \
  &lt;span class=&quot;copt&quot;&gt;-DSWIFT_PATH_TO_CMARK_BUILD=&lt;/span&gt;&lt;span class=&quot;cvar&quot;&gt;$HOME&lt;/span&gt;/local/Source/apple/standalone/swift-cmark-build \
  &lt;span class=&quot;copt&quot;&gt;-DSWIFT_PATH_TO_LLVM_SOURCE=&lt;/span&gt;&lt;span class=&quot;cvar&quot;&gt;$HOME&lt;/span&gt;/local/Source/apple/standalone/swift-llvm \
  &lt;span class=&quot;copt&quot;&gt;-DSWIFT_PATH_TO_LLVM_BUILD=&lt;/span&gt;&lt;span class=&quot;cvar&quot;&gt;$HOME&lt;/span&gt;/local/Source/apple/standalone/swift-llvm-build \
  &lt;span class=&quot;copt&quot;&gt;-DSWIFT_PATH_TO_CLANG_SOURCE=&lt;/span&gt;&lt;span class=&quot;cvar&quot;&gt;$HOME&lt;/span&gt;/local/Source/apple/standalone/clang \
  &lt;span class=&quot;copt&quot;&gt;-DSWIFT_PATH_TO_CLANG_BUILD=&lt;/span&gt;&lt;span class=&quot;cvar&quot;&gt;$HOME&lt;/span&gt;/local/Source/apple/standalone/swift-llvm-build

&lt;span class=&quot;c&quot;&gt;# Then build.&lt;/span&gt;
&lt;span class=&quot;cmd&quot;&gt;cmake&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;--build&lt;/span&gt; \
    ~/local/Source/apple/standalone/swift-build
&lt;/pre&gt;

&lt;p&gt;Once the build finishes, the built &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift&lt;/code&gt; compiler executable is located at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/local/Source/apple/standalone/swift-build/bin/swift&lt;/code&gt;. It works exactly as well as the executable I built using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script&lt;/code&gt; in my &lt;a href=&quot;http://modocache.io/getting-started-with-swift-development&quot;&gt;last post&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;what-do-swiftutilsbuild-script-and-swiftutilsbuild-script-impl-do&quot;&gt;What do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script-impl&lt;/code&gt; do?&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;utils/build-script&lt;/code&gt; is a Python script that performs the exact same actions I did above:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Use CMake to configure and build &lt;a href=&quot;https://github.com/apple/swift-cmark&quot;&gt;apple/swift-cmark&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Use CMake to configure and build &lt;a href=&quot;https://github.com/apple/swift-llvm&quot;&gt;apple/swift-llvm&lt;/a&gt; and &lt;a href=&quot;https://github.com/apple/swift-clang&quot;&gt;apple/swift-clang&lt;/a&gt;, as well as perform post-build configuration like symlinking C++ headers.&lt;/li&gt;
  &lt;li&gt;Use CMake to configure and build &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script&lt;/code&gt; accepts command-line arguments to specify how the project is built. The logic in the Python script translates these arguments into arguments to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script-impl&lt;/code&gt;, a shellscript that in turn invokes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake&lt;/code&gt;. For example, when a user invokes:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;cexec&quot;&gt;~/local/Source/apple/swift/utils/build-script&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;--release&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;This in turn calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script-impl&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;cexec&quot;&gt;~/local/Source/apple/swift/utils/build-script-impl&lt;/span&gt; \
    &lt;span class=&quot;copt&quot;&gt;--cmark-build-type=&lt;/span&gt;Release \
    &lt;span class=&quot;copt&quot;&gt;--llvm-build-type=&lt;/span&gt;Release \
    &lt;span class=&quot;copt&quot;&gt;--swift-build-type=&lt;/span&gt;Release
&lt;/pre&gt;

&lt;p&gt;When invoked with these arguments, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script-impl&lt;/code&gt; invokes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake -DCMAKE_BUILD_TYPE=Release&lt;/code&gt; to configure and build &lt;a href=&quot;https://github.com/apple/swift-cmark&quot;&gt;apple/swift-cmark&lt;/a&gt;, &lt;a href=&quot;https://github.com/apple/swift-llvm&quot;&gt;apple/swift-llvm&lt;/a&gt; (and thus simultaneously &lt;a href=&quot;https://github.com/apple/swift-clang&quot;&gt;apple/swift-clang&lt;/a&gt;), and &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The shellscript &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script-impl&lt;/code&gt; is an unnecessary complication. Ideally, the Python script &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script&lt;/code&gt; would invoke &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake&lt;/code&gt; directly. &lt;a href=&quot;https://bugs.swift.org/browse/SR-237&quot;&gt;A &lt;/a&gt;&lt;a href=&quot;https://bugs.swift.org/browse/SR-237&quot;&gt;Swift bug report&lt;/a&gt; exists to get rid of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script-impl&lt;/code&gt;, but that's easier said than done: the script contains over 3,000 lines of code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script&lt;/code&gt; places the build products for each project in a separate directory. The full path of the directory is based upon the options used; for the invocation &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script --release --debug-swift&lt;/code&gt;, the products are placed at:&lt;/p&gt;

&lt;pre&gt;
~/local/Source/apple/build/Ninja-ReleaseAssert+swift-DebugAssert/
    cmark-macosx-x86_64/ &lt;span class=&quot;c&quot;&gt;# swift-cmark build products.&lt;/span&gt;
    llvm-macosx-x86_64/  &lt;span class=&quot;c&quot;&gt;# swift-llvm and swift-clang build products.&lt;/span&gt;
    swift-macosx-x86_64/ &lt;span class=&quot;c&quot;&gt;# swift build products.&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;It's clear that, compared to invoking &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake&lt;/code&gt; multiple times to configure and build three separate projects, one invocation of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script&lt;/code&gt; is much simpler for new apple/swift contributors:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Users don't need to know how to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake&lt;/code&gt; on the command line.&lt;/li&gt;
  &lt;li&gt;Users don't need to know the particular CMake settings for each project.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition, some projects related to &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt;, such as &lt;a href=&quot;https://github.com/apple/swift-corelibs-foundation&quot;&gt;apple/swift-corelibs-foundation&lt;/a&gt;, do not include CMake files that describe how to build the project. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script-impl&lt;/code&gt; take care of building these as well.&lt;/p&gt;

&lt;p&gt;However, the simplicity comes at a cost:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;In order to add a new build setting, contributors to &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; need to add the setting to three places: the CMake, the shellscript &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script-impl&lt;/code&gt;, and the Python script &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script&lt;/code&gt;. Even if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script-impl&lt;/code&gt; were finally deleted one day, contributors would still need to modify both CMake and Python in order to add a new setting.&lt;/li&gt;
  &lt;li&gt;In cases where the documentation from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script --help&lt;/code&gt; is not completely clear, users need to trace how an option is translated between Python, shellscript, and CMake. In addition, some options are only accessible via CMake; for example, an option to build static libraries for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sourcekitd&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SOURCEKITD_BUILD_STATIC_INPROC&lt;/code&gt;, is only available in CMake.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script&lt;/code&gt; performs three configure and build actions each time it is invoked, regardless of whether the user has modified any files in &lt;a href=&quot;https://github.com/apple/swift-cmark&quot;&gt;apple/swift-cmark&lt;/a&gt;, &lt;a href=&quot;https://github.com/apple/swift-llvm&quot;&gt;apple/swift-llvm&lt;/a&gt;, or &lt;a href=&quot;https://github.com/apple/swift-clang&quot;&gt;apple/swift-clang&lt;/a&gt;. Although most generators are smart enough to do nothing if no files have changed, the extra configuration steps makes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script&lt;/code&gt; slower than invoking &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake --build&lt;/code&gt; directly.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;This is a frequent stumbling block for new contributors to &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt;.&lt;/p&gt;

  &lt;p&gt;Many experienced contributors recommend newcomers invoke &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ninja -C ~/local/Source/apple/build/swift-macosx-x86_64&lt;/code&gt; directly in order to perform faster incremental builds of &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt;. But a new contributor who doesn't know what &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script&lt;/code&gt; does will have a lot of questions:&lt;/p&gt;

  &lt;ul&gt;
    &lt;li&gt;&quot;What is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ninja&lt;/code&gt;?&quot;&lt;/li&gt;
    &lt;li&gt;&quot;What is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift-macosx-x86_64&lt;/code&gt; directory?&quot;&lt;/li&gt;
    &lt;li&gt;&quot;I used &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script --xcode&lt;/code&gt; in order to generate an Xcode project; attempting to invoke &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ninja&lt;/code&gt; results in an error. Why?&quot;&lt;/li&gt;
  &lt;/ul&gt;

  &lt;p&gt;Contributors familiar with the interaction between &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script&lt;/code&gt; and CMake know that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script --xcode&lt;/code&gt; eventually calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake -G Xcode&lt;/code&gt; when configuring the &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; project, and so it stands to reason that invoking &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ninja&lt;/code&gt; on the configured project would not work. A slight improvement would be to recommend newcomers use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake --build&lt;/code&gt; instead.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;one-last-trick-in-tree-builds-of-appleswift&quot;&gt;One last trick: &quot;In-tree&quot; builds of apple/swift&lt;/h2&gt;

&lt;p&gt;Configuring and building &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; using direct invocations of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake&lt;/code&gt; gave me a new appreciation of the work done by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script-impl&lt;/code&gt;. But it also made me notice that configuring and building Clang did not require a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake&lt;/code&gt; invocation of its own.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://clang.llvm.org/get_started.html&quot;&gt;The recommended way to build the Clang project&lt;/a&gt; is slightly different than the way I built &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; with CMake. Whereas building &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; required me to build LLVM first, Clang is built as part of the LLVM project. LLVM's CMake automatically detects when Clang is present at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;llvm/tools/clang&lt;/code&gt;. If it is, then LLVM's CMake includes Clang in the build.&lt;/p&gt;

&lt;p&gt;It turns out that apple/swift can be built in this way as well:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;c&quot;&gt;# Clone apple/swift-llvm.&lt;/span&gt;
&lt;span class=&quot;cmd&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;clone&lt;/span&gt; &lt;span class=&quot;u&quot;&gt;https://github.com/apple/swift-llvm.git&lt;/span&gt; \
    ~/local/Source/apple/intree/swift-llvm

&lt;span class=&quot;c&quot;&gt;# Clone cmark, clang, and swift&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# into swift-llvm/tools.&lt;/span&gt;
&lt;span class=&quot;cmd&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;clone&lt;/span&gt; &lt;span class=&quot;u&quot;&gt;https://github.com/apple/swift-cmark.git&lt;/span&gt; \
    ~/local/Source/apple/intree/swift-llvm/tools/cmark
&lt;span class=&quot;cmd&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;clone&lt;/span&gt; &lt;span class=&quot;u&quot;&gt;https://github.com/apple/swift-clang.git&lt;/span&gt; \
    ~/local/Source/apple/intree/swift-llvm/tools/clang
&lt;span class=&quot;cmd&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;clone&lt;/span&gt; &lt;span class=&quot;u&quot;&gt;https://github.com/apple/swift.git&lt;/span&gt; \
    ~/local/Source/apple/intree/swift-llvm/tools/swift
&lt;/pre&gt;

&lt;p&gt;Configuring and building &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; &quot;in-tree&quot; requires fewer options to be specified on the command-line, because the paths to the &lt;a href=&quot;https://github.com/apple/swift-llvm&quot;&gt;apple/swift-llvm&lt;/a&gt;, &lt;a href=&quot;https://github.com/apple/swift-cmark&quot;&gt;apple/swift-cmark&lt;/a&gt;, and &lt;a href=&quot;https://github.com/apple/swift-clang&quot;&gt;apple/swift-clang&lt;/a&gt; source and build directories are inferred by Swift's CMake code:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;c&quot;&gt;# First configure.&lt;/span&gt;
&lt;span class=&quot;cmd&quot;&gt;cmake&lt;/span&gt; \
    &lt;span class=&quot;copt&quot;&gt;-H&lt;/span&gt;~/local/Source/apple/intree/swift-llvm \
    &lt;span class=&quot;copt&quot;&gt;-B&lt;/span&gt;~/local/Source/apple/intree/build \
    &lt;span class=&quot;copt&quot;&gt;-G&lt;/span&gt; Ninja

&lt;span class=&quot;c&quot;&gt;# Then build: first Clang, and then Swift.&lt;/span&gt;
&lt;span class=&quot;cmd&quot;&gt;cmake&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;--build&lt;/span&gt; \
    ~/local/Source/apple/intree/build \
    &lt;span class=&quot;copt&quot;&gt;--&lt;/span&gt; clang swift
&lt;/pre&gt;

&lt;p&gt;Compared to the &quot;standalone&quot; build I first tried, in-tree builds of &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt; don't require me to remember to recompile &lt;a href=&quot;https://github.com/apple/swift-llvm&quot;&gt;apple/swift-llvm&lt;/a&gt;. If I make any changes to the &lt;a href=&quot;https://github.com/apple/swift-llvm&quot;&gt;apple/swift-llvm&lt;/a&gt; source code, they will be recompiled the next time I invoke &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake --build&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;However, in-tree builds are not the official documented way to build &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt;; if I encounter an error related to the build system, it's on me to file a bug and maybe even fix it myself.&lt;/p&gt;

&lt;p&gt;For newcomers to apple/swift, I would recommend either using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script&lt;/code&gt;, or the standalone setup.&lt;/p&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt;'s build system has three main components: the CMake that describes how the project is built, and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build-script&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build-script-impl&lt;/code&gt; that are responsible for invoking &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmake&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Because CMake generates build files, but does not build the project itself, it's possible to build with your tool of choice: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ninja&lt;/code&gt;, Xcode, or something else.&lt;/li&gt;
  &lt;li&gt;The LLVM family of projects frequently references two kinds of builds: &quot;in-tree&quot; builds, in which projects reside within the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;llvm/tools&lt;/code&gt; directory, and &quot;standalone&quot; builds, which have the projects reside elsewhere. &quot;In-tree&quot; builds of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;llvm/tools/swift&lt;/code&gt; are more uncommon; the recommended way to build is &quot;standalone&quot;. Builds that use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/utils/build-script&lt;/code&gt; are standalone.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next Sunday morning, I'll post a &quot;deep dive&quot; into &lt;a href=&quot;https://github.com/apple/swift&quot;&gt;apple/swift&lt;/a&gt;'s CMake code: how it uses a &quot;recursive make&quot; pattern, examples of how I read the code to see what it does, and some summaries of how things like the compiler itself, the standard library, and the test suite are built.&lt;/p&gt;</content><author><name></name></author><category term="swiftc" /><summary type="html">My last post explained that invoking swift/utils/build-script compiles the C++ source code in the apple/swift project and produces a swift compiler executable.</summary></entry><entry><title type="html">Getting Started with Swift Compiler Development</title><link href="https://modocache.io/getting-started-with-swift-development" rel="alternate" type="text/html" title="Getting Started with Swift Compiler Development" /><published>2017-08-23T17:00:00+00:00</published><updated>2017-08-23T17:00:00+00:00</updated><id>https://modocache.io/getting-started-with-swift-development</id><content type="html" xml:base="https://modocache.io/getting-started-with-swift-development">&lt;p&gt;Over the next few months, I'll be writing a guide to each section of the Swift compiler source code: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/lib/Driver&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/lib/Frontend&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/lib/Parse&lt;/code&gt;, and so on. First, here's how I set up a workspace for building and making patches to the Swift compiler.&lt;/p&gt;

&lt;p&gt;Being able to modify, experiment with, and attach a debugger to my own copy of the Swift compiler has been crucial to my learning process. If you want to get started contributing, try following along with the setup below.&lt;/p&gt;

&lt;h2 id=&quot;step-0-minimum-disk-space-and-hardware&quot;&gt;Step 0: Minimum disk space and hardware&lt;/h2&gt;

&lt;p&gt;The &lt;a href=&quot;https://github.com/apple/swift/blob/master/README.md&quot;&gt;apple/swift README&lt;/a&gt; recommends at least 20GB of free disk space for build products. In addition, &lt;a href=&quot;http://modocache.io/compiling-swift-what-hardware-is-best&quot;&gt;a powerful CPU will reduce the amount of time it takes to build&lt;/a&gt; the &lt;a href=&quot;https://github.com/apple/swift/blob/master/README.md&quot;&gt;apple/swift&lt;/a&gt; project. I use a MacBook Pro.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;No matter the CPU, I always spend the majority of my time reading the code. Chances are your machine at home is perfectly capable of building &lt;a href=&quot;https://github.com/apple/swift/blob/master/README.md&quot;&gt;apple/swift&lt;/a&gt;. If not, use a &lt;a href=&quot;https://www.digitalocean.com/pricing/&quot;&gt;$20/month Digital Ocean &quot;droplet&quot;&lt;/a&gt; running Ubuntu 16.04. It can compile &lt;a href=&quot;https://github.com/apple/swift/blob/master/README.md&quot;&gt;apple/swift&lt;/a&gt; in a few hours.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;step-1-clone-appleswift&quot;&gt;Step 1: Clone apple/swift&lt;/h2&gt;

&lt;p&gt;The instructions in the &lt;a href=&quot;https://github.com/apple/swift/blob/master/README.md&quot;&gt;apple/swift README&lt;/a&gt; have everything anyone would ever want to know. Based on that, I went on the command line and entered the following three commands:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;c&quot;&gt;# 1. Create the directory where apple/swift&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#    and its accompanying repositories will&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#    live.&lt;/span&gt;
&lt;span class=&quot;cmd&quot;&gt;mkdir&lt;/span&gt; ~/local/Source/apple

&lt;span class=&quot;c&quot;&gt;# 2. Clone apple/swift within the directory&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#    created in step (1).&lt;/span&gt;
&lt;span class=&quot;cmd&quot;&gt;git clone&lt;/span&gt; \
    &lt;span class=&quot;u&quot;&gt;https://github.com/apple/swift.git&lt;/span&gt; \
    ~/local/Source/apple/swift

&lt;span class=&quot;c&quot;&gt;# 3. Run a script inside the apple/swift&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#    repository that automatically downloads&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#    the other repositories you'll need.&lt;/span&gt;
&lt;span class=&quot;cexec&quot;&gt;~/local/Source/apple/swift/utils/update-checkout&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;--clone&lt;/span&gt;
&lt;/pre&gt;

&lt;h2 id=&quot;step-2-build-and-invoke-my-own-copy-of-the-swift-compiler&quot;&gt;Step 2: Build and invoke my own copy of the Swift compiler&lt;/h2&gt;

&lt;p&gt;In order to build a copy of the Swift compiler that I can attach a debugger to, I run the following command:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;cexec&quot;&gt;~/local/Source/apple/swift/utils/build-script&lt;/span&gt; \
    &lt;span class=&quot;copt&quot;&gt;--release&lt;/span&gt; \
    &lt;span class=&quot;copt&quot;&gt;--debug-swift&lt;/span&gt;
&lt;/pre&gt;

&lt;blockquote&gt;
  &lt;p&gt;If the command fails, I double- and triple-check that I have all the prerequisites listed in the &lt;a href=&quot;https://github.com/apple/swift/blob/master/README.md&quot;&gt;apple/swift README&lt;/a&gt; installed. The most common cause of failure for me, on macOS, is because I don't have the latest beta version of Xcode installed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;utils/build-script&lt;/code&gt; executable builds the libraries and executables in the &lt;a href=&quot;https://github.com/apple/swift/blob/master/README.md&quot;&gt;apple/swift&lt;/a&gt; project. Passing it the combination of the  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--release&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--debug-swift&lt;/code&gt; options makes it build the Swift compiler with debugging symbols. Debugging symbols take up a &lt;em&gt;lot&lt;/em&gt; of extra hard drive space, and the build takes a &lt;em&gt;lot&lt;/em&gt; longer with them included, but having them allows me to attach the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lldb&lt;/code&gt; debugger to the Swift compiler to learn what it's doing. That's invaluable to me.&lt;/p&gt;

&lt;p&gt;The build script will produce a ton of build products, including a Swift compiler executable, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftc&lt;/code&gt;. The location of this executable depends on the options passed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;utils/build-script&lt;/code&gt;. Having used the options above, I can invoke my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftc&lt;/code&gt; executable at the following path:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;cexec&quot;&gt;~/local/Source/apple/build/Ninja-ReleaseAssert+swift-DebugAssert/swift-macosx-x86_64/bin/swiftc&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;--version&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;The command above should output version information such as the following:&lt;/p&gt;

&lt;pre&gt;
Swift version 4.1-dev (LLVM 260a9efcdb, Clang 6af0830132, Swift 539894568f)
Target: x86_64-apple-darwin16.7.0
&lt;/pre&gt;

&lt;p&gt;And of course, I can use my built &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftc&lt;/code&gt; to compile and run Swift source code. For example, I created a new file named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.swift&lt;/code&gt; and typed the following:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;hello.swift&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; greeting: &lt;span class=&quot;cls&quot;&gt;String&lt;/span&gt;? = &lt;span class=&quot;s&quot;&gt;&quot;Hello, Swift!&quot;&lt;/span&gt;
&lt;span class=&quot;fs&quot;&gt;print&lt;/span&gt;(greeting)
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;I can compile and run this file using my compiler, like so:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;c&quot;&gt;# 1. Compiles the Swift source code to produce an&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#    executable named 'hello'.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#    (This also outputs some warnings -- more on&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#    these in the next section.)&lt;/span&gt;
&lt;span class=&quot;cexec&quot;&gt;~/local/Source/apple/build/Ninja-ReleaseAssert+swift-DebugAssert/swift-macosx-x86_64/bin/swiftc&lt;/span&gt; \
    hello.swift

&lt;span class=&quot;c&quot;&gt;# 2. Executes the program. This prints&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#    'Optional(&quot;Hello, Swift!&quot;)' to the console.&lt;/span&gt;
&lt;span class=&quot;cexec&quot;&gt;./hello&lt;/span&gt;
&lt;/pre&gt;

&lt;h2 id=&quot;step-3-modify-the-swift-compiler&quot;&gt;Step 3: Modify the Swift compiler&lt;/h2&gt;

&lt;p&gt;Compiling our program with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftc hello.swift&lt;/code&gt; above produced an executable, but the compiler also output some warnings:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;diag&quot;&gt;hello.swift:2:9: &lt;span class=&quot;dw&quot;&gt;warning:&lt;/span&gt; string interpolation produces a debug description for an optional value; did you mean to make this explicit?&lt;/span&gt;
print(&quot;\(greeting)&quot;)
        &lt;span class=&quot;dc&quot;&gt;^~~~~~~~~~&lt;/span&gt;
&lt;span class=&quot;diag&quot;&gt;hello.swift:2:10: &lt;span class=&quot;dn&quot;&gt;note:&lt;/span&gt; use 'String(describing:)' to silence this warning&lt;/span&gt;
print(&quot;\(greeting)&quot;)
        &lt;span class=&quot;dc&quot;&gt;~^~~~~~~~~&lt;/span&gt;
         String(describing:  )
&lt;span class=&quot;diag&quot;&gt;hello.swift:2:10: &lt;span class=&quot;dn&quot;&gt;note:&lt;/span&gt; provide a default value to avoid this warning&lt;/span&gt;
print(&quot;\(greeting)&quot;)
        &lt;span class=&quot;dc&quot;&gt;~^~~~~~~~~&lt;/span&gt;
                  ?? &amp;lt;#default value#&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Just for fun, instead of suggesting the programmer provide a default value with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;?? &amp;lt;#default value#&amp;gt;&lt;/code&gt;, I'll modify the compiler so that it suggests using a force unwrap &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!&lt;/code&gt; instead.&lt;/p&gt;

&lt;p&gt;To do so, I'll open &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/include/swift/AST/DiagnosticsSema.def&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swift/lib/Sema/MiscDiagnostics.cpp&lt;/code&gt; with a text editor and make the following changes:&lt;/p&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/df75e536e699e5dd283b8a0c9a641c6e0cc5cce9/include/swift/AST/DiagnosticsSema.def#L2732-L2735&quot;&gt;~/local/Source/apple/swift/include/swift/AST/DiagnosticsSema.def&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;2732  &lt;/span&gt;&lt;span class=&quot;pp&quot;&gt;NOTE&lt;/span&gt;(default_optional_to_any,none,
&lt;span class=&quot;ln&quot;&gt;2733  &lt;/span&gt;     &lt;span class=&quot;s&quot;&gt;&quot;provide a default value to avoid this warning&quot;&lt;/span&gt;, ())
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt;++++  &lt;/span&gt;&lt;span class=&quot;pp&quot;&gt;NOTE&lt;/span&gt;(force_optional_yolo,none,&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt;++++  &lt;/span&gt;     &lt;span class=&quot;s&quot;&gt;&quot;force unwrap the value, because why not? YOLO!!&quot;&lt;/span&gt;, ())&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt;2734  &lt;/span&gt;&lt;span class=&quot;pp&quot;&gt;NOTE&lt;/span&gt;(force_optional_to_any,none,
&lt;span class=&quot;ln&quot;&gt;2735  &lt;/span&gt;     &lt;span class=&quot;s&quot;&gt;&quot;force-unwrap the value to avoid this warning&quot;&lt;/span&gt;, ())
&lt;/pre&gt;
&lt;/div&gt;

&lt;div class=&quot;source-file&quot;&gt;
&lt;h1&gt;&lt;a href=&quot;https://github.com/apple/swift/blob/df75e536e699e5dd283b8a0c9a641c6e0cc5cce9/lib/Sema/MiscDiagnostics.cpp#L3381-L3384&quot;&gt;~/local/Source/apple/swift/lib/Sema/MiscDiagnostics.cpp&lt;/a&gt;&lt;/h1&gt;
&lt;pre class=&quot;file&quot;&gt;
&lt;span class=&quot;ln&quot;&gt;3381&lt;/span&gt;          &lt;span class=&quot;c&quot;&gt;// Suggest inserting a default value.&lt;/span&gt; 
&lt;div class=&quot;rm&quot;&gt;&lt;span class=&quot;ln&quot;&gt;3382&lt;/span&gt;          TC.&lt;span class=&quot;f&quot;&gt;diagnose&lt;/span&gt;(segment-&amp;gt;&lt;span class=&quot;f&quot;&gt;getLoc&lt;/span&gt;(), &lt;span class=&quot;t&quot;&gt;diag&lt;/span&gt;::&lt;span class=&quot;v&quot;&gt;default_optional_to_any&lt;/span&gt;)&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt;++++&lt;/span&gt;          TC.&lt;span class=&quot;f&quot;&gt;diagnose&lt;/span&gt;(segment-&amp;gt;&lt;span class=&quot;f&quot;&gt;getLoc&lt;/span&gt;(), &lt;span class=&quot;t&quot;&gt;diag&lt;/span&gt;::&lt;span class=&quot;v&quot;&gt;force_optional_yolo&lt;/span&gt;)&lt;/div&gt;
&lt;span class=&quot;ln&quot;&gt;3383&lt;/span&gt;            .&lt;span class=&quot;f&quot;&gt;highlight&lt;/span&gt;(segment-&amp;gt;&lt;span class=&quot;f&quot;&gt;getSourceRange&lt;/span&gt;())
&lt;div class=&quot;rm&quot;&gt;&lt;span class=&quot;ln&quot;&gt;3384&lt;/span&gt;            .&lt;span class=&quot;f&quot;&gt;fixItInsert&lt;/span&gt;(segment-&amp;gt;&lt;span class=&quot;f&quot;&gt;getEndLoc&lt;/span&gt;(), &lt;span class=&quot;s&quot;&gt;&quot; ?? &amp;lt;#default value#&amp;gt;&quot;&lt;/span&gt;);&lt;/div&gt;
&lt;div class=&quot;add&quot;&gt;&lt;span class=&quot;ln&quot;&gt;++++&lt;/span&gt;            .&lt;span class=&quot;f&quot;&gt;fixItInsertAfter&lt;/span&gt;(segment-&amp;gt;&lt;span class=&quot;f&quot;&gt;getEndLoc&lt;/span&gt;(), &lt;span class=&quot;s&quot;&gt;&quot;!&quot;&lt;/span&gt;);&lt;/div&gt;
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Now, if I rebuild &lt;a href=&quot;https://github.com/apple/swift/blob/master/README.md&quot;&gt;apple/swift&lt;/a&gt; and compile the source code again, I'll see the new warnings I added:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;c&quot;&gt;# 1. Rebuild apple/swift, by invoking build-script again.&lt;/span&gt;
&lt;span class=&quot;cexec&quot;&gt;~/local/Source/apple/swift/utils/build-script&lt;/span&gt; \
    &lt;span class=&quot;copt&quot;&gt;--release&lt;/span&gt; \
    &lt;span class=&quot;copt&quot;&gt;--debug-swift&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 2. Use the freshly build 'swiftc' to compile the source code&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#    in hello.swift again.&lt;/span&gt;
&lt;span class=&quot;cexec&quot;&gt;~/local/Source/apple/build/Ninja-ReleaseAssert+swift-DebugAssert/swift-macosx-x86_64/bin/swiftc&lt;/span&gt; \
    hello.swift
&lt;/pre&gt;

&lt;p&gt;This should produce a new set of warnings:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;diag&quot;&gt;hello.swift:2:9: &lt;span class=&quot;dw&quot;&gt;warning:&lt;/span&gt; string interpolation produces a debug description for an optional value; did you mean to make this explicit?&lt;/span&gt;
print(&quot;\(greeting)&quot;)
        &lt;span class=&quot;dc&quot;&gt;^~~~~~~~~~&lt;/span&gt;
&lt;span class=&quot;diag&quot;&gt;hello.swift:2:10: &lt;span class=&quot;dn&quot;&gt;note:&lt;/span&gt; use 'String(describing:)' to silence this warning&lt;/span&gt;
print(&quot;\(greeting)&quot;)
        &lt;span class=&quot;dc&quot;&gt;~^~~~~~~~~&lt;/span&gt;
         String(describing:  )
&lt;span class=&quot;diag&quot;&gt;hello.swift:2:10: &lt;span class=&quot;dn&quot;&gt;note:&lt;/span&gt; force unwrap the value, because why not? YOLO!!&lt;/span&gt;
print(&quot;\(greeting)&quot;)
        &lt;span class=&quot;dc&quot;&gt;~^~~~~~~~~&lt;/span&gt;
                  !
&lt;/pre&gt;

&lt;p&gt;If you've been following along with me, then congratulations! You've just made your first change to the Swift compiler. A change like this one could be sent to &lt;a href=&quot;https://github.com/apple/swift/blob/master/README.md&quot;&gt;apple/swift&lt;/a&gt; as a pull request. If accepted, it would be shipped to each and every Swift user in the next Apple release.&lt;/p&gt;

&lt;p&gt;You could also distribute your modified Swift compiler as an Xcode toolchain. I'll write more about that, and about the &lt;a href=&quot;https://github.com/apple/swift/blob/master/README.md&quot;&gt;apple/swift&lt;/a&gt; build system in general, in my next post.&lt;/p&gt;

&lt;p&gt;If you found this post useful, and stay tuned for my next post, on the &lt;a href=&quot;https://github.com/apple/swift/blob/master/README.md&quot;&gt;apple/swift&lt;/a&gt; build system: a deep dive into its CMake, shellscript, and Python guts.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;bonus-step-4-debug-the-swift-compiler&quot;&gt;Bonus step 4: Debug the Swift compiler&lt;/h2&gt;

&lt;p&gt;I build &lt;a href=&quot;https://github.com/apple/swift/blob/master/README.md&quot;&gt;apple/swift&lt;/a&gt; with debugging symbols so that I can attach the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lldb&lt;/code&gt; debugger to it. As an example, here's how I'd debug the command I executed above: first, I'll use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-###&lt;/code&gt; option in order to have the Swift compiler to print out its &lt;em&gt;sub-commands&lt;/em&gt;:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;cexec&quot;&gt;~/local/Source/apple/build/Ninja-ReleaseAssert+swift-DebugAssert/swift-macosx-x86_64/bin/swiftc&lt;/span&gt; \
    hello.swift \
    &lt;span class=&quot;copt&quot;&gt;-###&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;This prints the following two sub-commands:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;cexec&quot;&gt;/Users/modocache/Source/apple/build/Ninja-ReleaseAssert+swift-DebugAssert/swift-macosx-x86_64/bin/swift&lt;/span&gt; \
    &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt; \
    &lt;span class=&quot;copt&quot;&gt;-c&lt;/span&gt; \
    &lt;span class=&quot;copt&quot;&gt;-primary-file&lt;/span&gt; /Users/modocache/local/Source/tmp/hello.swift \
    &lt;span class=&quot;copt&quot;&gt;-target&lt;/span&gt; &lt;span class=&quot;ctarget&quot;&gt;x86_64-apple-darwin16.7.0&lt;/span&gt; \
    &lt;span class=&quot;copt&quot;&gt;-enable-objc-interop&lt;/span&gt; \
    &lt;span class=&quot;copt&quot;&gt;-color-diagnostics&lt;/span&gt; \
    &lt;span class=&quot;copt&quot;&gt;-module-name&lt;/span&gt; hello \
    &lt;span class=&quot;copt&quot;&gt;-o&lt;/span&gt; /var/folders/ry/2ryfdsb56b30092626qprw6d3rb3ss/T/hello-f994f3.o
&lt;span class=&quot;cexec&quot;&gt;/usr/bin/ld&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;copt&quot;&gt;-o&lt;/span&gt; hello
&lt;/pre&gt;

&lt;ol&gt;
  &lt;li&gt;The first sub-command is an invocation of the Swift compiler with arguments to produce an object file.&lt;/li&gt;
  &lt;li&gt;The second sub-command is an invocation of the system linker. This invocation takes the object file produced by the first sub-command, then generates an executable from that file.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I'm interested in debugging the Swift compiler, so I attach &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lldb&lt;/code&gt; to the first sub-command, by copy-pasting the command from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-###&lt;/code&gt; output above, but prefixing it with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lldb --&lt;/code&gt;, like so:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;cmd&quot;&gt;lldb&lt;/span&gt; -- &lt;span class=&quot;cexec&quot;&gt;/Users/modocache/Source/apple/build/Ninja-ReleaseAssert+swift-DebugAssert/swift-macosx-x86_64/bin/swift&lt;/span&gt; \
    &lt;span class=&quot;copt&quot;&gt;-frontend&lt;/span&gt; \
    &lt;span class=&quot;copt&quot;&gt;-c&lt;/span&gt; \
    &lt;span class=&quot;copt&quot;&gt;-primary-file&lt;/span&gt; /Users/modocache/local/Source/tmp/hello.swift \
    &lt;span class=&quot;copt&quot;&gt;-target&lt;/span&gt; &lt;span class=&quot;ctarget&quot;&gt;x86_64-apple-darwin16.7.0&lt;/span&gt; \
    &lt;span class=&quot;copt&quot;&gt;-enable-objc-interop&lt;/span&gt; \
    &lt;span class=&quot;copt&quot;&gt;-color-diagnostics&lt;/span&gt; \
    &lt;span class=&quot;copt&quot;&gt;-module-name&lt;/span&gt; hello \
    &lt;span class=&quot;copt&quot;&gt;-o&lt;/span&gt; /var/folders/ry/2ryfdsb56b30092626qprw6d3rb3ss/T/hello-f994f3.o
&lt;/pre&gt;

&lt;blockquote&gt;
  &lt;p&gt;On macOS environments with Xcode installed, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lldb&lt;/code&gt; should be available on the command line as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/bin/lldb&lt;/code&gt;. If it's not, double-check that you have the latest version of Xcode installed. If you're using Ubuntu Linux, you should be able to install lldb from &lt;a href=&quot;http://apt.llvm.org/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The above command attaches &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lldb&lt;/code&gt; to the process and displays a prompt where I can enter commands:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;cpr&quot;&gt;(lldb)&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;I commonly want to see how the Swift compiler determines whether to print a warning. For example, here's how I would do that for the string optional warning I modified above: first, I set the breakpoint on that file and line number:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;cpr&quot;&gt;(lldb)&lt;/span&gt; &lt;span class=&quot;cmd&quot;&gt;b&lt;/span&gt; MiscDiagnostics.cpp:3377
&lt;span class=&quot;cout&quot;&gt;Breakpoint 1: where = swift`diagnoseUnintendedOptionalBehavior(swift::TypeChecker&amp;amp;, swift::Expr const*, swift::DeclContext const*)::UnintendedOptionalBehaviorWalker::walkToExprPre(swift::Expr*) + 2931 at MiscDiagnostics.cpp:3378, address = 0x0000000101fce333&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;Then, I run the Swift compiler. It runs until it hits the breakpoint:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;cpr&quot;&gt;(lldb)&lt;/span&gt; &lt;span class=&quot;cmd&quot;&gt;run&lt;/span&gt;
&lt;span class=&quot;cout&quot;&gt;Process 57027 launched: '/Users/bgesiak/Source/apple/build/Ninja-ReleaseAssert+swift-DebugAssert/swift-macosx-x86_64/bin/swift' (x86_64)&lt;/span&gt;
&lt;span class=&quot;diag&quot;&gt;hello.swift:2:9: &lt;span class=&quot;dw&quot;&gt;warning:&lt;/span&gt; string interpolation produces a debug description for an optional value; did you mean to make this explicit?&lt;/span&gt;
print(&quot;\(greeting)&quot;)
        &lt;span class=&quot;dc&quot;&gt;^~~~~~~~~~&lt;/span&gt;
&lt;span class=&quot;diag&quot;&gt;hello.swift:2:10: &lt;span class=&quot;dn&quot;&gt;note:&lt;/span&gt; use 'String(describing:)' to silence this warning&lt;/span&gt;
print(&quot;\(greeting)&quot;)
        &lt;span class=&quot;dc&quot;&gt;~^~~~~~~~~&lt;/span&gt;
         String(describing:  )
&lt;span class=&quot;cout&quot;&gt;Process 57027 stopped&lt;/span&gt;
&lt;span class=&quot;cout&quot;&gt;* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1&lt;/span&gt;
    &lt;span class=&quot;cout&quot;&gt;frame #0: 0x0000000101fce333 swift`diagnoseUnintendedOptionalBehavior(this=0x00007fff5fbf40b0, E=0x00000001178d4a18)::UnintendedOptionalBehaviorWalker::walkToExprPre(swift::Expr*) at MiscDiagnostics.cpp:3378&lt;/span&gt;
   &lt;span class=&quot;dln&quot;&gt;3375&lt;/span&gt;                .&lt;span class=&quot;f&quot;&gt;fixItInsert&lt;/span&gt;(segment-&amp;gt;&lt;span class=&quot;f&quot;&gt;getEndLoc&lt;/span&gt;(), &lt;span class=&quot;s&quot;&gt;&quot;)&quot;&lt;/span&gt;);
   &lt;span class=&quot;dln&quot;&gt;3376&lt;/span&gt;
   &lt;span class=&quot;dln&quot;&gt;3377&lt;/span&gt;              &lt;span class=&quot;c&quot;&gt;// Suggest inserting a default value.&lt;/span&gt;
&lt;span class=&quot;dc&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;dln&quot;&gt;3378&lt;/span&gt;              TC.&lt;span class=&quot;f&quot;&gt;diagnose&lt;/span&gt;(segment-&amp;gt;&lt;span class=&quot;f&quot;&gt;getLoc&lt;/span&gt;(), &lt;span class=&quot;t&quot;&gt;diag&lt;/span&gt;::&lt;span class=&quot;v&quot;&gt;force_optional_yolo&lt;/span&gt;)
   &lt;span class=&quot;dln&quot;&gt;3379&lt;/span&gt;                .&lt;span class=&quot;f&quot;&gt;highlight&lt;/span&gt;(segment-&amp;gt;&lt;span class=&quot;f&quot;&gt;getSourceRange&lt;/span&gt;())
   &lt;span class=&quot;dln&quot;&gt;3380&lt;/span&gt;                .&lt;span class=&quot;f&quot;&gt;fixItInsertAfter&lt;/span&gt;(segment-&amp;gt;&lt;span class=&quot;f&quot;&gt;getEndLoc&lt;/span&gt;(), &lt;span class=&quot;s&quot;&gt;&quot;!&quot;&lt;/span&gt;);
   &lt;span class=&quot;dln&quot;&gt;3381&lt;/span&gt;            }
&lt;span class=&quot;cout&quot;&gt;Target 0: (swift) stopped.&lt;/span&gt;
&lt;span class=&quot;cpr&quot;&gt;(lldb)&lt;/span&gt;
&lt;/pre&gt;

&lt;p&gt;The debugger is now stopped just before the point where the Swift compiler would output the warning I modified. To see how it got here, I can use lldb's &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bt&lt;/code&gt; command, which stands for &quot;backtrace&quot;:&lt;/p&gt;

&lt;pre&gt;
&lt;span class=&quot;gp&quot;&gt;(lldb)&lt;/span&gt; &lt;span class=&quot;cmd&quot;&gt;bt&lt;/span&gt;
 thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
  * frame #0: 0x0000000101fce333 swift`diagnoseUnintendedOptionalBehavior(this=0x00007fff5fbf40b0, E=0x00000001178d4a18)::UnintendedOptionalBehaviorWalker::walkToExprPre(swift::Expr*) at MiscDiagnostics.cpp:3378
    frame #1: 0x00000001027ee90a swift`(anonymous namespace)::Traversal::doIt(this=0x00007fff5fbf4078, E=0x00000001178d4a18) at ASTWalker.cpp:1032
    frame #2: 0x00000001027f3ec0 swift`(anonymous namespace)::Traversal::visitImplicitConversionExpr(this=0x00007fff5fbf4078, E=0x0000000117201890) at ASTWalker.cpp:552
    frame #3: 0x00000001027f17b8 swift`swift::ASTVisitor&amp;lt;(anonymous namespace)::Traversal, swift::Expr*, swift::Stmt*, bool, swift::Pattern*, bool, void&amp;gt;::visitErasureExpr(this=0x00007fff5fbf4078, E=0x0000000117201890) at ExprNodes.def:139
    frame #4: 0x00000001027ef788 swift`swift::ASTVisitor&amp;lt;(anonymous namespace)::Traversal, swift::Expr*, swift::Stmt*, bool, swift::Pattern*, bool, void&amp;gt;::visit(this=0x00007fff5fbf4078, E=0x0000000117201890) at ExprNodes.def:139
    frame #5: 0x00000001027ef036 swift`(anonymous namespace)::Traversal::visit(this=0x00007fff5fbf4078, E=0x0000000117201890) at ASTWalker.cpp:98
    frame #6: 0x00000001027ee940 swift`(anonymous namespace)::Traversal::doIt(this=0x00007fff5fbf4078, E=0x0000000117201890) at ASTWalker.cpp:1037
    frame #7: 0x00000001027f2d00 swift`(anonymous namespace)::Traversal::visitIdentityExpr(this=0x00007fff5fbf4078, E=0x00000001172018c0) at ASTWalker.cpp:461
    frame #8: 0x00000001027f06e8 swift`swift::ASTVisitor&amp;lt;(anonymous namespace)::Traversal, swift::Expr*, swift::Stmt*, bool, swift::Pattern*, bool, void&amp;gt;::visitParenExpr(this=0x00007fff5fbf4078, E=0x00000001172018c0) at ExprNodes.def:90
    frame #9: 0x00000001027ef37c swift`swift::ASTVisitor&amp;lt;(anonymous namespace)::Traversal, swift::Expr*, swift::Stmt*, bool, swift::Pattern*, bool, void&amp;gt;::visit(this=0x00007fff5fbf4078, E=0x00000001172018c0) at ExprNodes.def:90
    frame #10: 0x00000001027ef036 swift`(anonymous namespace)::Traversal::visit(this=0x00007fff5fbf4078, E=0x00000001172018c0) at ASTWalker.cpp:98
    frame #11: 0x00000001027ee940 swift`(anonymous namespace)::Traversal::doIt(this=0x00007fff5fbf4078, E=0x00000001172018c0) at ASTWalker.cpp:1037
    frame #12: 0x00000001027f13fd swift`(anonymous namespace)::Traversal::visitTupleShuffleExpr(this=0x00007fff5fbf4078, E=0x0000000117201908) at ASTWalker.cpp:592
    frame #13: 0x00000001027ef6c4 swift`swift::ASTVisitor&amp;lt;(anonymous namespace)::Traversal, swift::Expr*, swift::Stmt*, bool, swift::Pattern*, bool, void&amp;gt;::visit(this=0x00007fff5fbf4078, E=0x0000000117201908) at ExprNodes.def:132
    frame #14: 0x00000001027ef036 swift`(anonymous namespace)::Traversal::visit(this=0x00007fff5fbf4078, E=0x0000000117201908) at ASTWalker.cpp:98
    frame #15: 0x00000001027ee940 swift`(anonymous namespace)::Traversal::doIt(this=0x00007fff5fbf4078, E=0x0000000117201908) at ASTWalker.cpp:1037
    frame #16: 0x00000001027f3ab1 swift`(anonymous namespace)::Traversal::visitApplyExpr(this=0x00007fff5fbf4078, E=0x00000001178d4aa0) at ASTWalker.cpp:713
    frame #17: 0x00000001027f12a8 swift`swift::ASTVisitor&amp;lt;(anonymous namespace)::Traversal, swift::Expr*, swift::Stmt*, bool, swift::Pattern*, bool, void&amp;gt;::visitCallExpr(this=0x00007fff5fbf4078, E=0x00000001178d4aa0) at ExprNodes.def:121
    frame #18: 0x00000001027ef600 swift`swift::ASTVisitor&amp;lt;(anonymous namespace)::Traversal, swift::Expr*, swift::Stmt*, bool, swift::Pattern*, bool, void&amp;gt;::visit(this=0x00007fff5fbf4078, E=0x00000001178d4aa0) at ExprNodes.def:121
    frame #19: 0x00000001027ef036 swift`(anonymous namespace)::Traversal::visit(this=0x00007fff5fbf4078, E=0x00000001178d4aa0) at ASTWalker.cpp:98
    frame #20: 0x00000001027ee940 swift`(anonymous namespace)::Traversal::doIt(this=0x00007fff5fbf4078, E=0x00000001178d4aa0) at ASTWalker.cpp:1037
    frame #21: 0x00000001027ee8a0 swift`swift::Expr::walk(this=0x00000001178d4aa0, walker=0x00007fff5fbf40b0) at ASTWalker.cpp:1664
    frame #22: 0x0000000101fa8db0 swift`diagnoseUnintendedOptionalBehavior(TC=0x00007fff5fbf6730, E=0x00000001178d4aa0, DC=0x00000001178d48d0) at MiscDiagnostics.cpp:3391
    frame #23: 0x0000000101fa8a3b swift`swift::performSyntacticExprDiagnostics(TC=0x00007fff5fbf6730, E=0x00000001178d4aa0, DC=0x00000001178d48d0, isExprStmt=true) at MiscDiagnostics.cpp:3406
    frame #24: 0x0000000102039c85 swift`swift::TypeChecker::typeCheckExpression(this=0x00007fff5fbf6730, expr=0x00007fff5fbf6320, dc=0x00000001178d48d0, convertType=TypeLoc @ 0x00007fff5fbf4390, convertTypePurpose=CTP_Unused, options=(Storage = 33), listener=0x0000000000000000, baseCS=0x0000000000000000) at TypeCheckConstraints.cpp:1818
    frame #25: 0x00000001021d4855 swift`(anonymous namespace)::StmtChecker::visitBraceStmt(this=0x00007fff5fbf6460, BS=0x00000001178d4ad0) at TypeCheckStmt.cpp:1234
    frame #26: 0x00000001021d438c swift`swift::ASTVisitor&amp;lt;(anonymous namespace)::StmtChecker, void, swift::Stmt*, void, void, void, void&amp;gt;::visit(this=0x00007fff5fbf6460, S=0x00000001178d4ad0) at StmtNodes.def:43
    frame #27: 0x00000001021d250a swift`bool (anonymous namespace)::StmtChecker::typeCheckStmt&amp;lt;swift::BraceStmt&amp;gt;(this=0x00007fff5fbf6460, S=0x00007fff5fbf6448) at TypeCheckStmt.cpp:372
    frame #28: 0x00000001021d2448 swift`swift::TypeChecker::typeCheckTopLevelCodeDecl(this=0x00007fff5fbf6730, TLCD=0x00000001178d48a0) at TypeCheckStmt.cpp:1620
    frame #29: 0x000000010221d299 swift`swift::performTypeChecking(SF=0x0000000117003c00, TLC=0x00007fff5fbf7180, Options=(Storage = 0), StartElem=2, WarnLongFunctionBodies=0, WarnLongExpressionTypeChecking=0, ExpressionTimeoutThreshold=0) at TypeChecker.cpp:720
    frame #30: 0x00000001019329b5 swift`swift::CompilerInstance::performSema(this=0x0000000114818600) at Frontend.cpp:525
    frame #31: 0x00000001000e20de swift`performCompile(Instance=0x0000000114818600, Invocation=0x00007fff5fbfd0a0, Args=ArrayRef&amp;lt;const char *&amp;gt; @ 0x00007fff5fbf9398, ReturnValue=0x00007fff5fbfbec4, observer=0x0000000000000000, Stats=0x0000000000000000) at FrontendTool.cpp:571
    frame #32: 0x00000001000de812 swift`swift::performFrontend(Args=ArrayRef&amp;lt;const char *&amp;gt; @ 0x00007fff5fbfc1d0, Argv0=&amp;quot;/Users/bgesiak/Source/apple/build/Ninja-ReleaseAssert+swift-DebugAssert/swift-macosx-x86_64/bin/swift&amp;quot;, MainAddr=0x000000010000a260, observer=0x0000000000000000) at FrontendTool.cpp:1381
    frame #33: 0x000000010000b573 swift`main(argc_=13, argv_=0x00007fff5fbff870) at driver.cpp:160
    frame #34: 0x00007fffcd3e8235 libdyld.dylib`start + 1
&lt;/pre&gt;

&lt;p&gt;Wow, that's a deep backtrace! Skimming through it from the bottom up, I can see that the Swift compiler starts in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt;, calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;performFrontend&lt;/code&gt;, then &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;performCompile&lt;/code&gt;, and so on, until it begins type checking, and eventually it invokes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;diagnoseUnintendedOptionalBehavior&lt;/code&gt;, which is the function that outputs the warning in question.&lt;/p&gt;

&lt;p&gt;The wall of text from the backtrace is intimidating at first, but no worries: in upcoming posts, I'll explain what each portion of the Swift compiler does. In the end, the Swift compiler is just a command-line program; there's nothing magical or scary about it.&lt;/p&gt;</content><author><name></name></author><category term="swiftc" /><summary type="html">Over the next few months, I'll be writing a guide to each section of the Swift compiler source code: swift/lib/Driver, swift/lib/Frontend, swift/lib/Parse, and so on. First, here's how I set up a workspace for building and making patches to the Swift compiler.</summary></entry></feed>