本文主要是介绍深入研究Clang(十九) Clang的RISCV支持2,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
前文Clang的RISCV支持1介绍了Clang中有关RISCV的代码主要集中在三个地方:Driver部分、Basic部分和CodeGen部分,并且对Basic部分和CodeGen部分的内容和关系进行了介绍,只有Driver部分因为涉及到了ToolChain、Tool和Command(job)等概念体系而未进行深入介绍。
在介绍完ToolChain、Tool和Command(job)等概念和调用关系之后,我们在本文再对Clang的RISCV支持的Driver部分进行深入分析。
一、Driver部分涉及到RISCV是从ToolChain相关操作开始的,这里最早的介入点位于clang/lib/Driver/Driver.cpp中的Compilation *Driver::BuildCompilation(ArrayRef<constchar *> ArgList) 函数,它首先调用了getToolChain函数。位于同个文件下的getToolChain函数之中,逐步拆解了目标的操作系统、环境和目标平台,具体代码如下:
const ToolChain &Driver::getToolChain(const ArgList &Args,const llvm::Triple &Target) const {auto &TC = ToolChains[Target.str()];if (!TC) {switch (Target.getOS()) {case llvm::Triple::AIX:TC = std::make_unique<toolchains::AIX>(*this, Target, Args);break;...case llvm::Triple::Win32:switch (Target.getEnvironment()) {default:if (Target.isOSBinFormatELF())TC = std::make_unique<toolchains::Generic_ELF>(*this, Target, Args);else if (Target.isOSBinFormatMachO())TC = std::make_unique<toolchains::MachO>(*this, Target, Args);elseTC = std::make_unique<toolchains::Generic_GCC>(*this, Target, Args);break;case llvm::Triple::GNU:TC = std::make_unique<toolchains::MinGW>(*this, Target, Args);break;...}break;...default:// Of these targets, Hexagon is the only one that might have// an OS of Linux, in which case it got handled above already.switch (Target.getArch()) {case llvm::Triple::tce:TC = std::make_unique<toolchains::TCEToolChain>(*this, Target, Args);break;...case llvm::Triple::riscv32:case llvm::Triple::riscv64:TC = std::make_unique<toolchains::RISCVToolChain>(*this, Target, Args);break;default:...}}}// Intentionally omitted from the switch above: llvm::Triple::CUDA. CUDA// compiles always need two toolchains, the CUDA toolchain and the host// toolchain. So the only valid way to create a CUDA toolchain is via// CreateOffloadingDeviceToolChains.return *TC;
}
这里最早出现了有关RISCV的内容,构建所需要的ToolChain:
case llvm::Triple::riscv32:case llvm::Triple::riscv64:TC = std::make_unique<toolchains::RISCVToolChain>(*this, Target, Args);break;
二、上文RISCVToolChain的定义和实现,以及为其所用的RISCV相关的Tool,均位于下列两个文件里:
clang/lib/Driver/ToolChains/RISCVToolchain.h
clang/lib/Driver/ToolChains/RISCVToolchain.cpp
下面进行分类讨论:
1、ToolChain方面:定义了RISCVToolChain,它继承于Generic_ELF,Generic_ELF继承于Generic_GCC,Generic_GCC继承于ToolChain。在源码上的体现:
clang/lib/Driver/ToolChains/RISCVToolchain.h
class LLVM_LIBRARY_VISIBILITY RISCVToolChain : public Generic_ELF {
clang/lib/Driver/ToolChains/Gnu.h
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 {
2、Tool方面:定义了RISCV::Linker,它继承于GnuTool ,GnuTool 继承于Tool。源码上的体现:
clang/lib/Driver/ToolChains/RISCVToolchain.h
namespace tools {
namespace RISCV {
class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool {
clang/lib/Driver/ToolChains/Gnu.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 {
三、Driver部分,还有两个相关文件RISCV.h和RISCV.cpp,他们的完整路径为:
clang/lib/Driver/ToolChains/Arch/RISCV.h
clang/lib/Driver/ToolChains/Arch/RISCV.cpp
这两个文件主要提供了获取ABI、Arch和RISCV目标特征的接口,具体代码表示如下:
clang/lib/Driver/ToolChains/Arch/RISCV.h
namespace clang {
namespace driver {
namespace tools {
namespace riscv {
void getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,const llvm::opt::ArgList &Args,std::vector<llvm::StringRef> &Features);
StringRef getRISCVABI(const llvm::opt::ArgList &Args,const llvm::Triple &Triple);
StringRef getRISCVArch(const llvm::opt::ArgList &Args,const llvm::Triple &Triple);
} // end namespace riscv
} // namespace tools
} // end namespace driver
} // end namespace clang
其中,在实现层面,getRISCVTargetFeatures还会调用getRISCVArch,并且调用getArchFeatures获取Arch特征。getArchFeatures则通过getExtensionVersion获取扩展版本号,然后通过getExtensionFeatures获取扩展特征。所以,具体的扩展版本号、以及扩展特征要进行改动的话,都是在clang/lib/Driver/ToolChains/Arch/RISCV.cpp这个文件里更新。
这里的信息与Basic部分信息不同,Basic部分主要是生成代码所需要的基本信息,而这里则是详细的扩展版本、扩展特征检查和校验。后续会对这里getRISCVABI、getRISCVArch和getRISCVTargetFeatures的被调用关系进行分析。
1、上面所提到的getRISCVABI函数,被调用的地方主要有:
1)Clang、ClangAs这两个Tool子类的AddRISCVTargetArgs函数;(clang/lib/Driver/ToolChains/Clang.h、clang/lib/Driver/ToolChains/Clang.cpp)
2)Assembler这个tool的tools::gnutools::Assembler::ConstructJob函数;
(clang/lib/Driver/ToolChains/Gnu.h、clang/lib/Driver/ToolChains/Gnu.cpp)
3)Generic_GCC::GCCInstallationDetector::ScanGCCForMultilibs函数所调用的findRISCVMultilibs函数之中,以及findRISCVMultilibs函数所调用的findRISCVBareMetalMultilibs函数之中;
(clang/lib/Driver/ToolChains/Gnu.h、clang/lib/Driver/ToolChains/Gnu.cpp)
4)Linux这个toolchain的构造函数,以及它的std::string Linux::getDynamicLinker函数之中。
(clang/lib/Driver/ToolChains/Linux.h、clang/lib/Driver/ToolChains/Linux.cpp)
2、上面所提到的getRISCVArch,被调用的地方在:
1) Assembler这个tool的tools::gnutools::Assembler::ConstructJob函数;
(clang/lib/Driver/ToolChains/Gnu.h、clang/lib/Driver/ToolChains/Gnu.cpp)
2)Generic_GCC::GCCInstallationDetector::ScanGCCForMultilibs函数所调用的findRISCVMultilibs函数所调用的findRISCVBareMetalMultilibs函数之中;
(clang/lib/Driver/ToolChains/Gnu.h、clang/lib/Driver/ToolChains/Gnu.cpp)
3、上面所提到的getRISCVTargetFeatures,被调用的地方在getTargetFeatures函数之中,这个函数主要被Clang这个tool的Clang::RenderTargetOptions函数和Clang::ConstructJob函数、ClangAs这个tool的ClangAs::ConstructJob函数所调用。(clang/lib/Driver/ToolChains/Clang.cpp)
可以看到,这三个函数主要的应用场景还是给Tool的一些子类进行调用。
这篇关于深入研究Clang(十九) Clang的RISCV支持2的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!