Driver-Level Setup
clang_main
├─> parse driver arguments & initialize Driver
├─> if -cc1 execute the compiler
├─> BuildCompilation
│ ├─> TranslateInputArgs (raw args → TranslatedArgs)
│ ├─> Configure ToolChains (host & offload)
│ ├─> Validate flags & compute TargetTriple
│ ├─> Determine driver-mode (gcc/g++/cpp/clang-cl)
│ ├─> Plan phases (preprocess → compile → assemble → link)
│ ├─> create Action DAG (nodes for each compilation step)
│ └─> BuildJobs
│ └─> create Job list (Command objects)
└─> ExecuteCompilation
├─> fork & exec each Job in DAG order (parallel where possible)
└─> collect exit codes & handle failures
clang_main
- set clang_main has the bottom of the stack
- Setup bug report message
- On Windows, reopen any missing
stdin/stdout/stderrhandles toNUL - Initialize all architecture targets (x86, ARM, AArch64, etc.)
- Create a
BumpPtrAllocatorandStringSaverto own strings from@fileresponse files - Get the program name (e.g.
bin/clang) - Determine if arguments are MSVC-style (
clang-clmode) expandResponseFiles: splice tokens from any@fileentries into the argument list- If this is a
-cc1invocation (seen later viaExecuteCC1Tool) - Parse early settings like
-canonical-prefixes/-no-canonical-prefixes - Handle CL-mode environment variables (
CL,_CL_) for MSVC overrides - Apply
CCC_OVERRIDE_OPTIONSoverrides (e.g.CCC_OVERRIDE_OPTIONS="# O0 +-g")#silences the “### Removing …” / “### Adding …” messages- Replaces any
-O*flags with-O0 - Appends
-gto the flag list
- GetExecutablePath: compute the absolute or raw driver path
- Parse
-fintegrated-cc1/-fno-integrated-cc1to choose in-process vs. external cc1 - Setup the diagnostic engine
- Parse DiagOpts (
-Werror,-pedantic, etc.) - Instantiate
TextDiagnosticPrinterandDiagnosticsEngine
- Parse DiagOpts (
- Initialize the filesystem VFS and process warning options
- Initialize
TheDriver(GCC-like driver main body) - Configure extra arguments (target, mode, prefix)
- Assign
TheDriver.CC1Main = ExecuteCC1WithContextif using in-process cc1 - Build the
CompilationviaBuildCompilation(preprocess, compile, assemble, link) - Handle errors/crashes during
Compilationcreation (Windows specifics, reproducers) - Execute compilation jobs:
TheDriver.ExecuteCompilation(*C, FailingCommands) - Handle compilation errors/crashes and emit diagnostics
BuildCompilation
-
Get driver mode (
--driver-mode=g++)Default mapping:
clang foo.c # DriverMode == "gcc" clang++ foo.cpp # DriverMode == "g++" clang -E foo.c # DriverMode == "cpp" clang-cl foo.c # DriverMode == "cl" -
Parse command-line arguments into
CLOptions -
Load config file (
~/.config/clang/config) vialoadConfigFilesOrder of override:
- Head defaults (
CfgOptionsHead) - User arguments (
CLOptions) - Tail overrides (
CfgOptionsTail)
- Head defaults (
-
Fuse head + user + tail into a single argument set
-
Translate input args via
TranslateInputArgs(*UArgs)→TranslatedArgs -
Claim flags to suppress unused warnings:
-canonical-prefixes/-no-canonical-prefixes-fintegrated-cc1/-fno-integrated-cc1
-
Handle hidden debug flags (
-ccc-print-phases,-ccc-print-bindings) -
Setup MSVC or DXC/HLSL→Vulkan/SPIR-V modes
-
Configure target and install directories (
COMPILER_PATH, etc.) -
Compute
TargetTriplefrom--target,-m*, driver-mode -
Select toolchain via
getToolChain -
Validate/warn on triple vs. object-format mismatches
-
Append multilib macros from
TC.getMultilibMacroDefinesStr -
Invoke phases: preprocess → compile → assemble → link
-
Apply architecture-specific settings (~50 lines)
-
Initialize the
Compilationclass -
Call
BuildJobs(*C)to schedule compile processes
Compilation class
Compilation::Compilation(const Driver &D,
const ToolChain &_DefaultToolchain,
InputArgList *_Args,
DerivedArgList *_TranslatedArgs,
bool ContainsError)
: TheDriver(D),
DefaultToolchain(_DefaultToolchain),
Args(_Args),
TranslatedArgs(_TranslatedArgs),
ContainsError(ContainsError) {
// The offloading host toolchain is the default toolchain.
OrderedOffloadingToolchains.insert(
std::make_pair(Action::OFK_Host, &DefaultToolchain));
}- TheDriver: Reference to the
Drivercontrolling this compilation. - DefaultToolchain: Host
ToolChainfor codegen. - Args / TranslatedArgs: Raw and translated argument lists.
- ContainsError: Error flag from initial parsing.
- OrderedOffloadingToolchains: Inserts
Action::OFK_Host→ host toolchain.
BuildJobs
Action:
An abstract compilation step (a node in the DAG (Directed Acyclic Graph)). you can see them with -ccc-print-phases
Example:
➜ clang -ccc-print-phases foo.c bar.c
+- 0: input, "foo.c", c
+- 1: preprocessor, {0}, cpp-output
+- 2: compiler, {1}, ir
+- 3: backend, {2}, assembler
+- 4: assembler, {3}, object
| +- 5: input, "bar.c", c
| +- 6: preprocessor, {5}, cpp-output
| +- 7: compiler, {6}, ir
| +- 8: backend, {7}, assembler
|- 9: assembler, {8}, object
10: linker, {4, 9}, imageJob
A Job is the concrete command-line execution that performs an Action defined in Clang’s compilation DAG. you can see them with the -ccc-print-bindings or in detail with -###
➜ clang -ccc-print-bindings foo.c bar.c
# "x86_64-unknown-linux-gnu" - "clang", inputs: ["foo.c"], output: "/tmp/foo-4040da.o"
# "x86_64-unknown-linux-gnu" - "clang", inputs: ["bar.c"], output: "/tmp/bar-15d3e6.o"
# "x86_64-unknown-linux-gnu" - "GNU::Linker", inputs: ["/tmp/foo-4040da.o", "/tmp/bar-15d3e6.o"], output: "a.out"Driver::BuildJobs steps:
- Count outputs (including
.ifs/.ifsoexceptions for-o) - Handle Mach-O multi-arch (
-arch) specifics - Collect the list of architectures
- For each Action:
- Determine
LinkingOutputforLipoJobAction - Call
BuildJobsForActionto create Jobs
- Determine
- Disable integrated-cc1 if
C.getJobs().size() > 1 - Print stats if
CCPrintProcessStatsis enabled - looking for an
assemblerjob to set aHasAssembleJobbool - Return based on errors or
-Qunused-arguments - Suppress warnings for flags like
-fdriver-only,-###, etc. - Warn on any remaining unclaimed or unsupported arguments
ExecuteCompilation
this is call in clang_main
- LogOnly mode: if
-fdriver-only, print jobs (-v) then execute in log-only mode. - Dry run: if
-###, print jobs and exit based on diagnostic errors. - Error check: abort early if any diagnostic errors before execution.
- Response files: set up response files for each job when needed.
- Execute jobs: run
C.ExecuteJobs, collecting failures inFailingCommands. - Fast exit: return
0when there are no failures. - Cleanup: on failure and when not saving temps, remove produced result files; for crashes (
<0), also clean failure files. - Signal handling: ignore
EX_IOERR(SIGPIPE) without printing diagnostics. - Detailed diagnostics: if a failing tool lacks good diagnostics or exit code ≠1, emit
err_drv_command_failedorerr_drv_command_signalled. - Return code: propagate the first non-zero or special exit code in
Res.
ExecuteJobs
In Unix, all jobs are executed regardless of whether an error occurs
In MSVC’s CLMode, jobs stop when an error occurs
on all the jobs :
- call the function ExecuteCommand
- if fail store in the failing command vector
- if CLMode return
ExecuteCommand
- print if
CC_PRINT_OPTIONS - Execute
C.Execute - manage error
Execute
- Print file names for logging and diagnostics.
- Construct
Argv:- If no response file: push
Executable, optionalPrependArg, thenArguments, terminate withnullptr. - If a response file is needed:
- Serialize arguments into
RespContentsviawriteResponseFile. - Build
Argvfor the response file (@filesyntax). - Write the response file with proper encoding; on error, set
ErrMsg/ExecutionFailedand return-1.
- Serialize arguments into
- If no response file: push
- Prepare environment (
Env) if any variables are set. - Convert
Argvarray toStringRefarray (Args). - Handle redirects:
- If
RedirectFilesare present, convert tostd::optional<StringRef>list and callExecuteAndWaitwith those. - Otherwise, call
ExecuteAndWaitwith the providedRedirects.
- If
- Execute and wait:
llvm::sys::ExecuteAndWaitforks, execsExecutablewithArgsandEnv, applies redirects, collects exit code inErrMsg/ExecutionFailed, and recordsProcStat.
- Return the child process exit code (or
-1on exec failure).