深入研究Clang(十七) Clang Driver库的Tool
Posted snsn1984
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入研究Clang(十七) Clang Driver库的Tool相关的知识,希望对你有一定的参考价值。
Tool也是Clang的Driver库里的一个类,它是具体编译工具的信息,代码注释中的原文是:Tool - Information on a specific compilation tool.(clang/include/clang/Driver/Tool.h)本文将对Tool的实现以及其相关调用关系做一个简单的分析。
一、Tool的实现和继承关系
1、Tool的定义和实现都位于clang/include/clang/Driver/Tool.h和clang/lib/Driver/Tool.cpp之中。
2、Tool的成员变量(Tool.h中)很能说明Tool的相关信息:
/// The tool name (for debugging).
const char *Name;
/// The human readable name for the tool, for use in diagnostics.
const char *ShortName;
/// The tool chain this tool is a part of.
const ToolChain &TheToolChain;
这里可以看到每个tool都有一个名字,还有一个短名字,同时还是构成一个tool chain的一部分。这里也能看到,Tool和ToolChain是双向关联的,Tool中通过TheToolChain关联到它所在的ToolChain,ToolChain通过如下列表和Tool关联:
mutable std::unique_ptr<Tool> Clang;
mutable std::unique_ptr<Tool> Flang;
mutable std::unique_ptr<Tool> Assemble;
mutable std::unique_ptr<Tool> Link;
mutable std::unique_ptr<Tool> IfsMerge;
mutable std::unique_ptr<Tool> OffloadBundler;
mutable std::unique_ptr<Tool> OffloadWrapper;
3、Tool在clang/lib/Driver/ToolChains目录之下具有一系列的子类,以Clang.h为例。Clang.h 之中定义了:
namespace clang
class ObjCRuntime;
namespace driver
namespace tools
/// Clang compiler tool.
class LLVM_LIBRARY_VISIBILITY Clang : public Tool
/// Clang integrated assembler tool.
class LLVM_LIBRARY_VISIBILITY ClangAs : public Tool
/// Offload bundler tool.
class LLVM_LIBRARY_VISIBILITY OffloadBundler final : public Tool
/// Offload wrapper tool.
class LLVM_LIBRARY_VISIBILITY OffloadWrapper final : public Tool
这里面的Clang和ClangAs有AddRISCVTargetArgs 这样的成员函数,为Clang或者是ClangAs添加RISCV这样的目标参数:
void Clang::AddRISCVTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const
const llvm::Triple &Triple = getToolChain().getTriple();
StringRef ABIName = riscv::getRISCVABI(Args, Triple);
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(ABIName.data());
SetRISCVSmallDataLimit(getToolChain(), Args, CmdArgs);
void ClangAs::AddRISCVTargetArgs(const ArgList &Args,
ArgStringList &CmdArgs) const
const llvm::Triple &Triple = getToolChain().getTriple();
StringRef ABIName = riscv::getRISCVABI(Args, Triple);
CmdArgs.push_back("-target-abi");
CmdArgs.push_back(ABIName.data());
其中的riscv::getRISCVABI这个函数,就是在clang/lib/Driver/ToolChains/Arch/RISCV.h中声明,在clang/lib/Driver/ToolChains/Arch/RISCV.cpp实现的。
4、clang/lib/Driver/ToolChains/Gun.h之中也定义了一系列的子类:
namespace tools
/// Base class for all GNU tools that provide the same behavior when
/// it comes to response files support
class LLVM_LIBRARY_VISIBILITY GnuTool : public Tool
/// Directly call GNU Binutils' assembler and linker.
namespace gnutools
class LLVM_LIBRARY_VISIBILITY Assembler : public GnuTool
class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool
/// gcc - Generic GCC tool implementations.
namespace gcc
class LLVM_LIBRARY_VISIBILITY Common : public GnuTool
class LLVM_LIBRARY_VISIBILITY Preprocessor : public Common
class LLVM_LIBRARY_VISIBILITY Compiler : public Common
class LLVM_LIBRARY_VISIBILITY Linker : public Common
这里基于Tool,定义了子类GunTool,并且为GunTool定义了子类Assembler 、Linker 和Common,又基于gcc::Common定义了Preprocessor和gcc::Preprocessor、gcc::Compiler 和gcc::Linker。
同时,本文件中还定义了toolchains的子类:
namespace toolchains
/// Generic_GCC - A tool chain using the 'gcc' command to perform
/// all subcommands; this relies on gcc translating the majority of
/// command line options.
class LLVM_LIBRARY_VISIBILITY Generic_GCC : public ToolChain
class LLVM_LIBRARY_VISIBILITY Generic_ELF : public Generic_GCC
Generic_ELF 是Generic_GCC 的子类,Generic_GCC 又是ToolChain 的子类。
二、Tool的调用关系
1、上一部分内容在介绍Tool的子类的同时,在Gun.h顺便介绍了Generic_ELF类,它其实还是一部分类的父类。clang/lib/Driver/ToolChains/Linux.h中的Linux类,是操作系统相关类的典型,它继承于Generic_ELF:
class LLVM_LIBRARY_VISIBILITY Linux : public Generic_ELF
clang/lib/Driver/ToolChains/RISCVToolchain.h中的RISCVToolchain累,是硬件平台相关类的典型,它也继承于Generic_ELF:
classLLVM_LIBRARY_VISIBILITY RISCVToolChain : public Generic_ELF
2、ToolChain对Tool的调用关系,比较显然易见的是通过getXXX系列函数,对成员函数做操作的。其中还包含了buildAssembler和buildLinker。(clang/lib/Driver/ToolChain.cpp)
Tool *ToolChain::getClang() const
if (!Clang)
Clang.reset(new tools::Clang(*this));
return Clang.get();
Tool *ToolChain::getFlang() const
if (!Flang)
Flang.reset(new tools::Flang(*this));
return Flang.get();
Tool *ToolChain::buildAssembler() const
return new tools::ClangAs(*this);
Tool *ToolChain::buildLinker() const
llvm_unreachable("Linking is not supported by this toolchain");
Tool *ToolChain::getAssemble() const
if (!Assemble)
Assemble.reset(buildAssembler());
return Assemble.get();
Tool *ToolChain::getClangAs() const
if (!Assemble)
Assemble.reset(new tools::ClangAs(*this));
return Assemble.get();
Tool *ToolChain::getLink() const
if (!Link)
Link.reset(buildLinker());
return Link.get();
Tool *ToolChain::getIfsMerge() const
if (!IfsMerge)
IfsMerge.reset(new tools::ifstool::Merger(*this));
return IfsMerge.get();
Tool *ToolChain::getOffloadBundler() const
if (!OffloadBundler)
OffloadBundler.reset(new tools::OffloadBundler(*this));
return OffloadBundler.get();
Tool *ToolChain::getOffloadWrapper() const
if (!OffloadWrapper)
OffloadWrapper.reset(new tools::OffloadWrapper(*this));
return OffloadWrapper.get();
这些成员函数会在其子类中根据需要去进行重载。以RISCV相关的RISCVToolchain为例(clang/lib/Driver/ToolChains/RISCVToolchain.cpp):
Tool *RISCVToolChain::buildLinker() const
return new tools::RISCV::Linker(*this);
其重载了buildLinker。
3、Tool对job的调用关系,主要体现在通过ConstructJob (clang/include/clang/Driver/Tool.h):
/// ConstructJob - Construct jobs to perform the action \\p JA,
/// writing to \\p Output and with \\p Inputs, and add the jobs to
/// \\p C.
///
/// \\param TCArgs - The argument list for this toolchain, with any
/// tool chain specific translations applied.
/// \\param LinkingOutput - If this output will eventually feed the
/// linker, then this is the final output name of the linked image.
virtual void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const = 0;
这个成员函数,也在其子类之中进行重载。以RISCV相关的RISCV::Linker 为例(clang/lib/Driver/ToolChains/RISCVToolchain.h):
namespace RISCV
class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool
public:
Linker(const ToolChain &TC) : GnuTool("RISCV::Linker", "ld", TC)
bool hasIntegratedCPP() const override return false;
bool isLinkJob() const override return true;
void ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output, const InputInfoList &Inputs,
const llvm::opt::ArgList &TCArgs,
const char *LinkingOutput) const override;
;
三、总结
1、Tool作为一个概念,其上接ToolChain,下接job。
2、Tool作为一个具体的类,其具有庞大的子类群体,这些子类群体包含了软件因素相关的子类和硬件因素相关的子类。
3、Tool和ToolChain这两个类本身都是独立文件保存的,但是Tool的子类群体和ToolChain的子类群体,在很多情况下共存在头文件和CPP文件之中的。
编辑于 2020-05-14
以上是关于深入研究Clang(十七) Clang Driver库的Tool的主要内容,如果未能解决你的问题,请参考以下文章
深入研究Clang(十六) Clang Driver库的ToolChain
深入研究Clang(十六) Clang Driver库的ToolChain
深入研究Clang(十八) Clang Driver库的job