【问题标题】:How is clang able to steer C/C++ code optimization?clang 如何引导 C/C++ 代码优化?
【发布时间】:2014-12-30 04:12:03
【问题描述】:

有人告诉我,clang 是一个像 gcc 一样工作的驱动程序,可以进行预处理、编译和链接工作。在编译和链接过程中,据我所知,实际上是 llvm 进行了优化("-O1", "-O2", "-O3", "-Os", "-flto")。

但我就是无法理解llvm 是如何参与的

似乎编译源代码甚至不需要libLLVMCore.a之类的静态库,而是debian clang包依赖于另一个名为libllvm-3.4的包(clang版本为3.4),其中包含libLLVM-3.4.so(.1),确实clang 使用这个共享库进行优化?

查了一下clang源码,发现include/clang/Driver/Options.td包含了相关选项,可惜没找到include那个文件的源文件,所以还是不了解机制。

希望有人能给我一些提示。

【问题讨论】:

  • 这可能是另一个 XY 问题。如果你得到这个问题的答案,你打算解决什么问题?
  • @MSalters 我只是想知道 clang 如何驱动 llvm 进行优化工作。我正在从事一个似乎需要 clang sanitizer 和 llvm IR pass 分析的项目,所以我想知道有关 clang 工作原理的详细信息。基本上,我们希望实现一个(非常轻量级的)驱动程序,其工作方式类似于 clang,但针对端到端代码漏洞检查。
  • 好吧,我已经觉得某处确实存在问题。为 LLVM 编写目标语言描述并对其进行编译不是更好吗? LLVM 编译器不限于针对 x86 或 ARM,它是可扩展的。定义合适的目标语言后,您的漏洞将在最终输出中脱颖而出。
  • @MSalters 我认为为目标语言编写前端对我来说仍然很困难,我们目前只对 x86(32/64) 作为架构的 c/c++ 代码感兴趣。所以希望有关于llvm转换和分析pass的驱动接口的详细解答。

标签: c++ gcc compilation clang llvm


【解决方案1】:

(TL;DontWannaRead - 跳到这个答案的结尾)

要正确回答您的问题,您首先需要了解编译器的front-endback-end(尤其是第一个)之间的区别。

Clang 是 C、C++、Objective C 和 Objective C++ 语言的编译器前端 (http://en.wikipedia.org/wiki/Clang)。

Clang 的职责如下:

即从 C++ 源代码(或 C 或 Objective C 等)转换为 LLVM IR,这是该代码应该做什么的文本低级表示。为了做到这一点,Clang 使用了许多子模块,您可以在任何体面的编译器构造书籍中找到它们的描述:词法分析器、解析器 + 语义分析器 (Sema) 等。

LLVM 是一组库,其主要任务如下:假设我们有以下 C++ 函数的 LLVM IR 表示

int double_this_number(int num) {
    int result = 0;
    result = num;
    result = result * 2;
    return result;
}

LLVM 通道的核心应该优化 LLVM IR 代码:

如何处理优化的 LLVM IR 代码完全取决于您:您可以将其转换为 x86_64 可执行代码或对其进行修改,然后将其作为 ARM 可执行代码或 GPU 可执行代码输出。这取决于您的项目目标。

“后端”一词经常令人困惑,因为有许多论文将 LLVM 库定义为编译器链中的“中间端”,并将“后端”定义为执行代码生成的最终模块( LLVM IR 到可执行代码或其他不再需要编译器处理的东西)。其他来源将 LLVM 称为 Clang 的后端。无论哪种方式,它们的角色都很明确,并且它们提供了一个强大的机制:无论您的目标是什么语言(C++、C、Objective C、Python 等),如果您有一个将其转换为 LLVM IR 的前端,您可以使用同一组 LLVM 库对其进行优化,并且只要您有目标架构的后端,就可以生成优化的可执行代码。

回顾 LLVM 是一组库(不仅仅是优化通道,还有 data structures、实用程序模块、诊断模块等),Clang 在其期间还利用了许多 LLVM 库>前端进程。您不能真正将 每个 LLVM 模块从 Clang 中分离出来,因为后者是建立在前一组之上的。

至于 Clang 被称为“编译驱动程序”的原因:Clang 管理解释命令行参数(描述和许多声明是TableGen'd,它们可能需要的不仅仅是一个简单的 grep 才能游泳通过源),决定要执行哪些Jobs 和阶段,根据所需/可能的优化和转换级别设置CodeGenOptions 并调用适当的模块(BackendUtil.cpp 中的clangCodeGen 是使用要应用的优化填充模块传递管理器)和工具(例如 Windows ld 链接器)。它从头到尾引导编译过程。

最后,我建议阅读 Clang 和 LLVM 文档,它们非常详尽,您的大部分问题都应该首先在那里寻找答案。

【讨论】:

  • 我想我的问题有点模棱两可,但是你给出了这样一个很好的答案来告诉我如何深入到IR一代,尤其是最后三段;非常感谢!
  • btw,你能告诉我生成图片的工具是什么吗?
  • @HongxuChen 我用的是Publisher
【解决方案2】:

它并不完全像 GCC,所以不要花太多时间试图精确匹配两者。

LLVM 编译器是针对一种特定语言 LLVM 的编译器。 Clang 所做的是将 C++ 代码编译为 LLVM,而不进行优化。然后,Clang 可以调用 LLVM 编译器将该 LLVM 代码编译为优化的程序集。

【讨论】:

  • 我知道它们并不完全相同,但我希望获得更多详细信息关于如何 clang 调用llvm 编译器来完成优化工作。
猜你喜欢
  • 1970-01-01
  • 2012-11-13
  • 1970-01-01
  • 2013-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-02
  • 1970-01-01
相关资源
最近更新 更多