clang 编译器前端负责从源码生成中间码,它通常由 clang 模块驱动,并通常包含以下几个步骤:

image
本文会先对 clang 编译器前端的流程进行简单的介绍,并会在后面的系列文章依次分享下面的几个库:
clang 模块只包含 5 个可编译文件,大部分的功能都是依赖其它模块提供
clang库 的driver.cpp是整个程序的入口。

image
clang 模块主要负责以下任务:
main 函数检测输入的参数是否包含以 -cc1 开头的参数

image
ExecuteCC1Tool 函数分发不同的 cc1类型。
clang 目前支持 3 种类型

image
-cc1 : LLVM 'Clang' Compiler-cc1as : Clang Integrated Assembler-cc1gen-reproducer: Generate Libclang invocation reproducerscc1_main 函数负责初始化 CompilerInstance、DiagnosticIDs,并调用 CreateFromArgs 函数构建 CompilerInvocation

image
CreateFromArgs 函数内部会非常多的函数对参数进行解析

image
-emit-obj 参数传入时,ParseFrontendArgs 函数会将 frontend::EmitObj赋值给 ProgramAction
后面的 CreateFrontendBaseAction 函数会依赖依赖 ProgramAction

image对 -emit-objc 不熟悉的朋友,可以看看 clang driver 系列文章
clangFrontendTool 模块的 ExecuteCompilerInvocation 函数执行编译任务

image
clangFrontendTool 非常简单,目前只包含一个可编译文件 ExecuteCompilerInvocation.cpp

image
ExecuteCompilerInvocation 会判断先是否存在 -h -v 等参数,如果存在,会执行对应的任务
值得注意的是,这里会尝试加载 plugin

image
CreateFrontendAction 创建需要执行的编译器前端任务

image
CreateFrontendAction 会先调用 CreateFrontendBaseAction 创建 FrontendAction 的子类

image
CreateFrontendBaseAction 函数会因为前文提到的 EmitObj 参数创建 EmitObjAction 的实例

image
ExecuteAction 函数执行编译任务

image
clangFrontend 模块包含了很多重要的功能。
cc1_main 函数创建的 CompilerInstance 就是来自 clangFrontend

CompilerInstance 是 clangFrontend 中非常重要的一个类。它持有了诸如 preprocessor、Target、AST 等属性

image
CompilerInstance::ExecuteAction 会通过 Inputs 获取输入文件,并依次调用以下方法:
Act.BeginSourceFile()Act.Execute()Act.EndSourceFile()
image
Ac就是之前提到的FrontendAction的子类EmitObjAction
Act.BeginSourceFile() 函数会通过懒加载方式创建 FileManager 和 SourceManager

imageFileManager 负责和文件系统交互,文件缓存、目录查找等任务

imageSourceManager 负责查找并将文件缓存到内存

image
createPreprocessor 函数创建预处理器

image预处理器 初始化时,会构建一个包含各个语言的关键字列表IdentifierTable Identifiers;,方便后续词法分析使用

image
createASTContext 创建 ASTContext

image

image
FrontendAction::CreateWrappedASTConsumer 创建 ASTConsumer
image
Act.Execute() 实际上是执行 EmitObjAction 继承自 FrontendAction 的 Execute 函数
FrontendAction:Execute 随后会调用 CodeGenAction::ExecuteAction 函数

image
CodeGenAction::ExecuteAction 函数会调用ASTFrontendAction::ExecuteAction

image
ASTFrontendAction::ExecuteAction 会调用 CompilerInstance的 createSema 函数创建 Sema

image
Sema后续会用于语义分析

image
各项准备工作结束后,就会调用 clangParse 模块的 clang::ParseAST 构建 abstract syntax tree

image
本文对 clang 编译器前端入门知识进行了简单介绍。
下一篇文章,我们会开始分享 ParseAST 的第一个主要流程:词法分析 和 预处理指令