LLVM-代码生成流

LLVM-代码生成流,llvm,llvm-clang,llvm-ir,Llvm,Llvm Clang,Llvm Ir,当我浏览LLVM文档时 有些术语的含义我并不完全理解 请提供反馈,如果你知道任何 [前端]源代码->令牌服务器令牌流->解析器操作 有人能解释一下Tokeniser到底做什么吗?解析器也做什么? 可能会提供一个例子,使这一点更加清楚 [后端]红外->优化程序红外->代码生成 我不明白在这一步,什么优化应该做 我知道不同的前端和后端之间有一些区别。 但我要求的是一般情况 感谢您的反馈。所有这些都是标准的编译器术语请参见Aho、Lam、Sethi、Ullmann:编译器 编译器的输入是一个包含字符串

当我浏览LLVM文档时

有些术语的含义我并不完全理解

请提供反馈,如果你知道任何

[前端]源代码->令牌服务器令牌流->解析器操作

有人能解释一下Tokeniser到底做什么吗?解析器也做什么? 可能会提供一个例子,使这一点更加清楚

[后端]红外->优化程序红外->代码生成

我不明白在这一步,什么优化应该做

我知道不同的前端和后端之间有一些区别。 但我要求的是一般情况


感谢您的反馈。

所有这些都是标准的编译器术语请参见Aho、Lam、Sethi、Ullmann:编译器

编译器的输入是一个包含字符串的文件

在:

标记器的输出是一个标记序列,其中标记被定义为不包含空格的字符串。您还可以设计一种更好的标记类型,它可以跟踪数字是否为实数或整数,字符序列是否为保留字。。。。有时,该语言的保留字会被唯一标识符(通常为整数)替换,表示数字的字符序列会转换为实际数字,因此您可能会得到:

输出:

请注意,后面的空行{注释也消失了。构建解析树不需要注释。我还欺骗了字符串blimey\n,它需要被注释为一个带常量引号的字符串。这就是标记器。分离标记化/解析的要点是,标记化可以使用比解析器更快的有限状态自动机来完成

解析器根据上面的序列构建一个树。在这里显示解析器的输出很困难,因为我们没有被解析语言的语法。因此我选择一种更简单的语言:

“foo+3*bar”的标记器输出:

"foo" "+" "3" "*" "bar"
算术表达式语言有许多语法,其中大多数语法分析器将构建此树:

      +
    /   \
"foo"    *
        / \
       3  "bar"
AST: 抽象语法树不同于解析树,因为语法树编译器第2.5节没有出现形式上的表面区别,这对翻译不重要

假设您编写了表达式foo+3*bar。解析器仍然会构建上面的树,因为不需要括号。但是如果您编写了foo+3*bar,您将得到一个不同的树:

        *
      /  \
     +   "bar"
   /  \
"foo"  3
没有括号!抽象树结构对所有内容进行编码。实现方面:如果您使用现代面向对象语言编写编译器,抽象语法树将由类层次结构表示。在C中,每个节点类型都有一个“struct”,并用整数标记

可以从树中生成可执行代码或任何您需要的代码,但这很繁琐。因此,在许多情况下,Pascal的p代码,C的其他三种地址代码中间表示形式……树被展平转换为中间表示形式IR。其目的是更容易在精心设计的IR.您可能需要进行数百万次优化:

use algebraic identities x+0 => x, x*1 => x etc
drop unused variables
simplify control flow
reorder assignments
...

大多数情况下,优化程序都会保留IR…即函数IR->IR,但有两个聪明的优化程序会转换IR1->IR2更改表示,以明确某些属性使用“benton”“moggi”“monad”搜索将让您开始。

这是一个很好的答案,我相信这有助于人们理解mo请允许我在这段时间内完成这件事。非常感谢。在我的问题中我没有指出前端和后端中间的一件事。AST,你介意帮助解释这个故事中AST的规则吗?谢谢。
        *
      /  \
     +   "bar"
   /  \
"foo"  3
use algebraic identities x+0 => x, x*1 => x etc
drop unused variables
simplify control flow
reorder assignments
...