失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 【实验】编译原理——编译器认知实验

【实验】编译原理——编译器认知实验

时间:2022-03-22 03:40:41

相关推荐

【实验】编译原理——编译器认知实验

系列文章目录

学习笔记

【学习笔记】编译原理——第一章 编译引论

【学习笔记】编译原理——第二章 词法分析

实验

【实验】编译原理——编译器认知实验


文章目录

系列文章目录学习笔记实验一、实验目的二、实验内容三、实验步骤实验结果4.1 G++4.2 LLVM4.3 G++编译器优化4.4 LLVM编译器优化4.5 G++和LLVM优化对比五、实验心得

一、实验目的

本实验的目的是了解工业界常用的编译器 GCC 和 LLVM,熟悉编译器的安装 和使用过程,观察编译器工作过程中生成的中间文件的格式和内容,了解编译器 的优化效果,为编译器的学习和构造奠定基础。

二、实验内容

本实验主要的内容为在 Linux 平台上安装和运行工业界常用的编译器 GCC 和 LLVM,如果系统中没有安装,则需要首先安装编译器,安装完成后编写简单的测 试程序,使用编译器编译,并观察中间输出结果。

对于 GCC 编译器,完成编译器安装和测试程序编写后,按如下步骤完成:

查看编译器的版本

使用编译器编译单个文件

使用编译器编译链接多个文件

查看预处理结果:g++ -E hello.c -o hello.i

查看语法分析树:g+±fdump-tree-all hello.c

查看中间代码生成结果:Code generation result: g+±fdump-rtl-all hello.c

查看生成的目标代码(汇编代码):g++–S hello.c –o hello.s

对于 LLVM 编译器,完成编译器安装和测试程序编写后,按如下步骤完成:

查看编译器的版本

使用编译器编译单个文件

使用编译器编译链接多个文件

查看编译流程和阶段:clang -ccc-print-phases test.c -c

查看词法分析结果:clang test.c -Xclang -dump-tokens

查看词法分析结果 2:clang test.c -Xclang -dump-raw-tokens

查看语义分析结果:clang test.c -Xclang -ast-dump

查看语义分析结果 2:clang test.c -Xclang -ast-view

查看编译优化的结果:clang test.c -S -mllvm -print-after-all

查看生成的目标代码结果: clang test.c –S

三、实验步骤

编译器安装

在Linux系统下安装GCC、Clang、LLVM。

sudo apt-get install Clangsudo apt-get install LLVM

编写测试程序

需要注意的是,不但要求对单个 C 文件进行编译,还要求对多个 C 文件一起编译和链接。运行编译器进行观测

分别运行 GCC 和 LLVM 编译器,首先要学习编译器的基本使用方法,其次要通过编译选项查看分析编译器的中间结果,及其与输入源码之间的对应关系,最后使用-O0、-O1、-O2 和-O3 分别使用两个编译器对输入程序进行优化编译,并对比 GCC 和 LLVM 优化后程序的运行效率。编写实验报告

根据观测结果编写实验报告。

实验结果

4.1 G++

①查看编译器版本

在Visual Studio Code中查看G++编译器版本

②编译单个文件

③编译链接多个文件

④查看预处理结果:g++ -E hello.cpp -o hello.i

⑤查看语法分析树:g+±fdump-tree-all hello.cpp

在hello.cpp.001t.tu中生成相关语法树,部分文件内容

⑥查看中间代码生成结果: g++ -fdump-rtl-all hello.cpp

编译生成如下文件:

在hello.cpp.192r.expand文件中可以看到如下代码,目的是使得内存边界对齐。

⑦查看生成的目标代码(汇编代码):g++ -S hello.cpp -o hello.s

运行命令生成hello.s文件,虽然目前还未学过汇编代码,但是能够看到我们在源码中定义的变量name和number均以.string的形式在汇编代码中出现。

4.2 LLVM

①查看编译器的版本

运行clang –version 和clang++ --version都能查看到编译器的版本。

②使用编译器编译单个文件

③使用编译器编译链接多个文件

④查看编译流程和阶段:clang++ -ccc-print-phases hello.cpp -c

⑤查看词法分析结果:clang++ -c hello.cpp -Xclang -dump-tokens

Loc=XXXX 表示该字符或字符串所对应的行数及位置

Int ‘int’ , 表⽰ int 代表整型

Identifier ‘main’, 表⽰ main 是⼀个标识符

numeric_constant ‘XXXXXX’,表⽰数值常量

l_paren ‘(‘ , 表示左括号

⑥查看词法分析结果 2:clang test.c -Xclang -dump-raw-tokens

可以看到词法分析2比词法分析1更加详细,比如对空格‘ ’也同样进行了分析。

⑦查看语义分析结果:clang test.c -Xclang -ast-dump

语义分析部分终端显示较多,以下截取部分进行展示:

可以看到,从命名空间开始分析

UsingDirectiveDecl 0x35e7158 <hello.cpp:4:1, col:17> col:17 Namespace 0x2fa7ab8 ‘std’

再到分析函数,FunctionDecl 0x35e71c8 <line:6:1, col:16> col:5 BubbleSort ‘int (void)’

层层分析,最后到定义的字符串

StringLiteral 0x35e73a8 col:19 ‘const char [12]’ lvalue “XXXXXX”

⑧查看编译优化的结果:

部分代码如图所示:

⑨查看生成的目标代码结果: clang++ hello.cpp –S

查看生成的汇编代码:

4.3 G++编译器优化

⽤编写的100*100矩阵相乘的C++代码,使用G++编译器并⽤不同编译优化选项,如分别运行以下命令:

g++ matrix.cpp -O0 -o matrix0g++ matrix.cpp -O1 -o matrix1g++ matrix.cpp -O2 -o matrix2g++ matrix.cpp -O3 -o matrix3

运行结果如图所示:

时间对比如下:

可以看出 O1,O2,O3 三种优化选择能够明显提升矩阵乘法运算的效率。

4.4 LLVM编译器优化

⽤编写的100*100矩阵相乘的C++代码,使用LLVM编译器并⽤不同编译优化选项,如分别运行以下命令:

clang++ matrix.cpp -o clang_matrixclang++ matrix.cpp -O0 -o clang_matrix0clang++ matrix.cpp -O1 -o clang_matrix1clang++ matrix.cpp -O2 -o clang_matrix2clang++ matrix.cpp -O3 -o clang_matrix3

运行结果如下图所示:

时间对比如下:

可以看出 O1,O2,O3 三种优化选择能够明显提升矩阵乘法运算的效率。

4.5 G++和LLVM优化对比

由上述柱状图可以看出,在矩阵乘法这个程序上,在相同规模的情况下,在⽆优化,和 -O0 优化的编译情况下,G++编译器的运行时间小于LLVM编译器。在 O2,O3 优化的编译情况下,两者的效率不分上下。但是在O1优化情况下G++效率比LLVM大得多,程序运行时间更短。

五、实验心得

①通过本实验,我了解了编译过程中的每个过程⽣成的⽂件,

②了解了编译器的常⽤选项,包括⼀些优化参数

③通过使用不同的编译器,调用不同的优化参数,体会到这些参数对程序运行带来的不同影响

如果觉得《【实验】编译原理——编译器认知实验》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。