编译器的一个趋势是使用类型化中间语言。Haskell的ghc
使用其core
中间语言(System F-omega的变体)作为该架构的实例[1]。另一个例子是LLVM,其核心是一种类型化的中间语言[2]。采用这种方法的好处在于可以早期检测代码生成器中组成部分的转换中的错误。此外,在优化和代码生成过程中还可以使用类型信息。
为了提高效率,类型化IR需要进行类型检查,而不是通过推断来确定其类型。为了使类型检查快速进行,每个变量和每个绑定器都携带着类型以便进行轻松的类型检查。
然而,编译器流水线中的许多转换可能会引入新的变量。例如,规范化转换K(.)
可能会转换应用程序。
M(N)
转换为类似的表达式
let x = K(M) in
let y = K(N) in x(y)
问题. 我想知道编译器如何处理给新引入的变量赋类型的问题。它们是否重新进行类型检查,在上面的示例中 K(M)
和 K(N)
?这不是很耗时吗?它是否需要传递环境?它们是否使用从AST节点到类型信息的映射来避免重新运行类型检查?
S. Marlow, S. Peyton Jones,《Glasgow Haskell Compiler》。
alloca
节点、函数参数和全局变量声明一起保存。其余部分始终可以重建。为了方便,在转换之间,我还将类型附加到GEP节点上,但是如果存在可以引入新GEP的转换,则会重新运行类型传播。 - SK-logic