为什么LLVM具有类似程序集的IR,而不是类似树的IR?或者:为什么项目针对LLVM IR而不是clang的AST?


14

为什么LLVM的中间表示(LLVM IR)类似于树而不是像树?

或者,为什么语言实现针对LLVM IR而不是clang的AST?

我不是想立刻问两个不同的问题。在我看来,似乎客户和库程序员都已达成共识,LLVM的API(仅此而已)显然是好的软件设计,我的问题是“为什么?”。

我问的原因是,如果IR类似于AST,LLVM似乎可以为前端提供更多功能,因为那时clang基于AST的工具可以用于任何前端。另外,如果针对LLVM IR的语言针对clang的AST,则可以获得更多功能。

Clang具有用于创建和使用AST的类和函数,并且它是唯一与LLVM项目紧密相关的前端项目,那么为什么clang的AST功能在LLVM外部?

在我的头顶上,我知道Rust(rustc),D(ldc)和Haskell(GHC)都可以使用LLVM作为后端,但是它们不使用Clang AST(据我所知,我可以是错的)。我不知道这些编译器的所有内部细节,但是至少Rust和D当然看起来可以将它们编译为clang的AST。也许Haskell也可以,但是我对此不太确定。

这是因为历史原因(LLVM最初是“低级虚拟机”,后来出现了clang)吗?这是因为其他前端希望对提供给LLVM的内容进行尽可能多的控制吗?clang的AST不适合“非C类”语言是否有根本原因?

我不希望这个问题成为阅读中的练习。我只是希望它对那些对编译器设计感到好奇但还不太熟练的人有所帮助。由于LLVM和clang项目是公开开发的,所以我希望熟悉这些项目开发的人员可以回答,或者希望答案对于某些自己有足够信心回答的书呆子很明显。


抢占一些显而易见但不令人满意的答案:

是的,拥有类似程序集的IR可以使制作IR的人获得更多控制权(也许X lang比clang更好的代码库和AST格式),但是如果这是唯一的答案,那么问题就变成了“为什么LLVM 具有程序集-例如IR,而不是高级树状IR和底层程序集IR?”。

是的,将编程语言解析为AST并不难(至少与其他编译步骤相比)。即使这样,为什么还要使用单独的AST?如果没有其他问题,则使用相同的AST可以使您使用在AST上运行的工具(即使只是简单的东西,例如AST打印机)。

是的,我强烈同意,更加模块化是一件好事,但如果这是唯一的原因,那么为什么其他语言的实现往往针对LLVM IR代替铛的AST?

这些先发制人可能是错误的或忽略了细节,因此,如果您有更多细节或我的假设有误,请随时提供这些答案。


对于任何想回答一个更为明确的问题的人:类组装IR与树形IR的优缺点是什么?


1
我不是LLVM专家,但我认为您方面有些误解。LLVM没有类似于IR的组件。实际上,其IR更像是图形而不是树。我以“类似asm”的方式假设您是指人类可读的IR(*。ll文件),如果是这样,那么这样做只是为了方便。但是,让我们等待一个能给出更全面答案的真正专家:)
AlexDenisov

1
历史可能是一个重要方面:LLVM最初旨在将编译器后端与编译器前端分离。想法是,编译器供应商将在语言优化上竞争,而CPU供应商将在低级优化上竞争。例如,微软和苹果将彼此竞争,后者的C编译器将产生来自C的“最佳”位代码,而英特尔和AMD将彼此竞争,其LLVM后端将从位代码产生“最佳”的机器代码。应用程序供应商将他们的船在应用位码,最后汇编将用户的做...
约尔格W¯¯米塔格

1
……机器。LLVM一次启动,当时还不清楚每个人都在使用Intel。苹果仍在使用PowerPC,英特尔仍在推动Itanium,依此类推。在AFAIK中,Apple在其某些3D框架中仍以这种方式使用LLVM,其中代码以位代码的形式提供,然后根据所安装的卡类型针对nVidia或ATI进行编译。
约尔格W¯¯米塔格

1
原谅我,但是IR是什么?
亚当·科普利

1
@AdamCopley 中间代表
Praxeolitic

Answers:


13

这里有很多相互关联的问题,我会尽力将它们分开。

为什么其他语言基于LLVM IR而不是AST?

这仅仅是因为clang是C / C ++前端,它产生的AST与C / C ++紧密耦合。另一种语言可以使用它,但是它需要与C / C ++的某些子集几乎相同的语义,这是非常有限的。正如您所指出的,对AST的解析非常简单,因此限制您的语义选择不太值得花一点钱。

但是,如果您要为C / C ++编写工具(例如静态分析器),则重新使用AST非常有意义,因为使用AST比使用C / C ++处理原始文本要容易得多。

LLVM IR为什么是它的形式?

选择LLVM IR作为编写编译器优化的合适形式。因此,它的主要功能是SSA形式。它的IR级别很低,因此适用于多种语言,例如,它不键入内存,因为这在不同语言之间差异很大。

现在,碰巧情况是编写编译器优化是一项非常专业的任务,并且通常与语言功能设计正交。但是,使编译语言快速运行是相当普遍的要求。而且,从LLVM IR到ASM的转换是相当机械的,对于语言设计人员来说通常也不是那么有趣。

因此,将语言简化为LLVM IR可以为语言设计人员提供许多“免费的东西”,这在实践中非常有用,使他们可以专注于语言本身。

使用其他IR是否有用(好,不问,而是某种暗示)?

绝对!AST对于程序结构的某些转换非常有用,但如果要转换程序流,则很难使用。SSA表单通常更好。但是,LLVM IR的级别很低,因此丢失了很多高级结构(故意这样做,因此更通用)。在AST与低电平IR之间具有IR可能是有益的。Rust和Swift都采用这种方法,并且两者之间的IR很高。


Haskell在进入LLVM之前也有许多IR。
DylanSp '17

1
@ DylanSp的确如此。对于复杂的语言,它实际上已成为最佳实践。例如,Rust最初并没有这样做,而是重构为包括高级别的IR。我也相信有一些关于为c做此事的讨论,但我不确定这样做的去向。
亚历克斯(Alex)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.