2014-07-08 56 views
-1

当我通过LLVM文件去,LLVM - 代码生成流

有一些用语,但我不完全理解的含义。

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

  1. [前端]源代码 - > Tokeniser(令牌流) - >分析器(分析器操作)

    有人能解释什么Tokeniser究竟怎么办? Parser也做了什么?可能提供一个可以使这个更清晰的例子。

  2. [后端] IR - >优化器(IR) - >代码生成

    我不明白在这一步,应该做哪些优化。

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

感谢您的任何反馈。

回答

3

所有这些都是标准的编译器术语(参见Aho,Lam,Sethi,Ullmann:Compilers)。

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

IN:

int main(int argc, char* argv[]) 
{ 

    printf("blimey\n"); 
    // this is a comment 
    return 0; 
} 

标记生成器的输出是令牌的序列,其中一个标记被定义为不包含空白字符的字符串(也可以设计出更好的令牌类型,其将保持跟踪,如果数字看起来像实数或整数,字符序列是保留字或不是......)。有时,语言的保留字是由一个唯一的标识符(通常是一个整数)所取代,这表示数字字符序列转换为实际的数字,所以你可能会得到:

OUT:

"int" "main" "(" "int" "argc" "," "char", "*", "argv" "[" "]" "{" 
"printf" "(" "blimey\n" ")" ";" "return" "0" ";" "}" 

注意“{”后面的空行不见了,所以是注释。您不需要评论来构建分析树。我也欺骗了字符串“blimey \ n”,它需要注释为一个常量(带引号)的字符串。那是分词器。分离标记化/解析的要点是标记化可以用比解析器更快的有限状态自动机完成。

解析器从上面的序列中构建一棵树。显示解析器的输出在这里很困难,因为我们没有解析语言的语法。所以,我采取一个更简单的语言:

标记生成器输出为“富+ 3 *酒吧”:

"foo" "+" "3" "*" "bar" 

有算术表达式中大部分的解析器将建立该语言的一些语法树:

 + 
    / \ 
"foo" * 
     /\ 
     3 "bar" 

AST: “抽象语法树不同......从解析树,因为形式的肤浅的区别,不重要的翻译,不会出现在语法树”(编译四段2.5)

假设你写了“foo +(3 * bar)”表达式。解析器仍然会构建上面的树,因为括号不是必需的。但是,如果你写了 “(富+ 3)*吧”,你会得到一个不同的树:

 * 
    /\ 
    + "bar" 
/\ 
"foo" 3 

没有括号!抽象的树结构编码一切。实施方式:如果您正在使用现代面向对象语言编写编译器,则抽象语法树将由类层次结构表示。在C中,每个标记的节点类型都有一个“结构”(带有整数)。

可以从树中生成可执行代码(或任何您需要的代码),但它很乏味。所以在许多情况下(P代码为Pascal,其他三个地址代码中间表示为C ...),树被变换(展平)为中间表示(IR)。目的是在设计良好的IR上进行优化更容易。有数以百万计的优化你可能想要做的:

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

优化器大部分时间保持了IR ...即是一个功能红外 - >红外,但有几个聪明的优化器,其翻译IR1 - > IR2(改变表示),使某些属性显式化(用'benton''moggi''monad'进行搜索将使你开始)。

+1

这是一个很好的答案,我相信这可以帮助人们了解更多。请允许我有一段时间来通过这个。非常感谢你。 – Sam

+0

在前端和后端之间有一件事我没有在我的问题中指出。 AST,你会介意在这个故事中解释AST的规则吗?谢谢。 – Sam

+1

这个答案很好,但也请参阅:http://www.aosabook.org/en/llvm.html –