参考:
Create a working compiler with the LLVM framework, Part 2
How to parse C programs with Clang: A tutorial
一、Preprocessor
前端由许多部分组成,其中第一部分通常是一个 lexer,clang 中 Preprocessor 类是 lexer 的 main interface。处于性能考虑,clang 没有独立的预处理器程序,而是在 lexing 的过程中进行预处理。
Preprocessor 的构造函数如下所示:
Preprocessor::Preprocessor( std::shared_ptr<PreprocessorOptions> PPOpts, // constructor: PreprocessorOptions() DiagnosticsEngine& diags, LangOptions& opts, // constructor: LangOptions() // Keep track of the various options that can be enabled, // which controls the dialect of C or C++ that is accepted SourceManager& SM, HeaderSearch& Headers, ModuleLoader& TheModuleLoader, IdentifierInfoLookup* IILookup = nullptr, bool OwnsHeaderSearch = false, TranslationUnitKind TUKind = TU_Complete )
DiagnosticsEngine : 用来给用户报告错误和警告信息。构造函数如下:
DiagnosticsEngine::DiagnosticsEngine( IntrusiveRefCntPtr<DiagnosticIDs> Diags, // constructor: DiagnosticIDs() // used for handling and querying diagnostic IDs DiagnosticOptions* DiagOpts, // constructor: DiagnosticOptions() // Options for controlling the compiler diagnostics engine DiagnosticConsumer* client = nullptr, bool ShouldOwnClient = true )
其中 DiagnosticConsumer 是一个抽象接口,由前端的 clients 实现,用来 formats and prints fully processed diagnostics。clang 内置一个 TextDiagnosticsConsumer 类,将错误和警告信息写到 console 上,clang binary 用的 DiagnosticConsumer 也是这个类。TextDiagnosticsConsumer 的构造函数如下:
TextDiagnosticPrinter::TextDiagnosticPrinter( raw_ostream& os, // llvm::outs() returns a reference to a raw_ostream for standard output DiagnosticOptions* diags, bool OwnsOutputStream = false // within destructor:(OS is the member, initialized with os) // if (OwnsOutputStream) delete &OS )
SourceManager :handles loading and caching of source files into memory。构造函数如下:
SourceManager::SourceManager( DiagnosticsEngine& Diag, FileManager& FileMgr, bool UserFilesAreVolatile = false )
FileManager :implements support for file system lookup, file system caching, and directory search management。构造函数如下:
FileManager::FileManager( const FileSystemOptions& FileSystemOpts, // use default constructor IntrusiveRefCntPtr<vfs::FileSystem> FS = nullptr )
HeaderSearch :Encapsulates the information needed to find the file referenced by a #include or #include_next, (sub-)framework lookup, etc。构造函数如下:
HeaderSearch::HeaderSearch( std::shared_ptr<HeaderSearchOptions> HSOpts, // constructor: HeaderSearchOptions::HeaderSearchOptions(StringRef _Sysroot = "/") SourceManager& SourceMgr, DiagnosticsEngine& Diags, const LangOptions& LangOpts, const TargetInfo* Target )
TargetInfo :Exposes information about the current target。 其构造函数为 protected,因此需要调用工厂函数 static TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags, const std::shared_ptr<TargetOptions>& Opts) ,其中 TargetOptions 类包含 target 的相关信息,如 CPU、ABI 等。类中有一个属性 Triple 用以定义 target 的架构。Triple 是一个 string,形如 i386-apple-darwin,通过 llvm::sys::getDefaultTargetTriple() 可以获得编译 llvm 的机器的 host triple。
ModuleLoader:描述了 module loader 的抽象接口。Module loader 负责解析一个 module name(如“std”),将其与实际的 module file 联系起来,并加载该 module。CompilerInstance 便是一个实现了该接口的 module loader
p,li { white-space: pre-wrap }