从GCC源码分析C语言编译原理——获取gcc源码

目录

一、GCC编译过程

二、GCC内部工作机制

三、GCC优化技术示例

四、源码获取


        之前一直想自己发明一个新语言并配套搞个编译器来着,想了很久发现不太可行,付出与回报不成正比,也没法推广,现在没有一个新的语言的生存环境。所以就通过gcc的原理去对编译原理做加深性的学习吧。GCC(GNU Compiler Collection)是一个广泛使用的编译器集合,支持多种编程语言,如C、C++、Fortran等。

一、GCC编译过程

GCC的编译过程通常分为以下几个主要阶段:

  1. 预处理(Preprocessing)

    • 输入:源代码文件(如.c文件)。
    • 输出:预处理后的代码文件(通常通过gcc -E命令查看,文件后缀通常为.i)。
    • 任务:处理宏定义、文件包含(#include)、条件编译指令(#ifdef等)等。
    • 工具:cpp(C PreProcessor)。
  2. 编译(Compiling)

    • 输入:预处理后的代码文件。
    • 输出:汇编代码文件(通常为.s文件,通过gcc -S命令查看)。
    • 任务:将预处理后的代码翻译成目标架构的汇编代码。
    • 工具:前端编译器(如cc1,针对C语言)。
  3. 汇编(Assembling)

    • 输入:汇编代码文件。
    • 输出:目标文件(通常为.o文件,通过gcc -c命令生成)。
    • 任务:将汇编代码翻译成机器代码,生成目标文件。
    • 工具:as(GNU Assembler)。
  4. 链接(Linking)

    • 输入:一个或多个目标文件。
    • 输出:可执行文件。
    • 任务:将多个目标文件和库文件链接在一起,生成最终的可执行文件。
    • 工具:ld(GNU Linker)。

二、GCC内部工作机制

GCC的内部工作机制复杂而精妙,主要由以下几个部分组成:

  1. 前端(Frontend)

    • 负责处理特定编程语言的语法和语义分析。
    • 生成中间表示(IR,Intermediate Representation)。GCC支持多种前端,每种前端负责不同的编程语言。
  2. 中间表示(IR)

    • GCC使用一种称为GIMPLE的中间表示形式。GIMPLE是一种三地址码,便于进行各种优化和转换。
    • 通过将代码转换为统一的中间表示,GCC可以对不同语言使用相同的优化和后端处理。
  3. 优化器(Optimizer)

    • GCC进行多种优化,包括局部优化、全局优化、循环优化、指令级并行优化等。
    • 优化可以在不同的阶段进行,如GIMPLE层优化、RTL(Register Transfer Level)层优化等。
    • 常见的优化技术包括常量折叠、循环展开、死代码消除等。
  4. 后端(Backend)

    • 负责将中间表示转换为目标机器的汇编代码。
    • 包含特定架构的代码生成器和指令选择器。
    • 处理目标架构的寄存器分配、指令调度等。

三、GCC优化技术示例

  1. 常量传播

    • 原始代码:int square(int x) { int result = x * x; return result; }
    • 优化后代码:int square(int x) { return x * x; }
    • 常量传播和折叠将中间变量result去掉,直接返回计算结果。
  2. 死代码消除

    • 原始代码:int foo(int x) { int y = x * 2; if (x > 10) { y = 0; } return y; }
    • 优化后代码:int foo(int x) { if (x > 10) { return 0; } return x * 2; }
    • 死代码消除移除了不必要的变量和赋值操作。
  3. 循环展开

    • 原始代码:void loop_example(int *arr, int n) { for (int i = 0; i < n; i++) { arr[i] = i * 2; } }
    • 优化后代码:void loop_example(int *arr, int n) { int i; for (i = 0; i <= n - 4; i += 4) { arr[i] = i * 2; arr[i + 1] = (i + 1) * 2; arr[i + 2] = (i + 2) * 2; arr[i + 3] = (i + 3) * 2; } for (; i < n; i++) { arr[i] = i * 2; } }
    • 循环展开减少了循环控制的开销,提高了执行效率。

四、源码获取

        其实有个很有意思的现象,高级语言的编译器源码都是高级语言。gcc的源码是c语言,大家可能会想到先有鸡还是先有蛋的悖论。其实最初C语言的编译器是B语言实现的,再往前推很多的语言的编译是汇编做的,而最开始的汇编器是打孔打出来的。为了方便大家使用,编译器都会根据人的使用习惯去升级。所以可能会出现左脚踩右脚的神奇现象。但时至今日其实编译原理这门科学已经有很久都没有进步过了。越往底层就越趋近于数学。由于研究起来没有收益,全世界对这里的投入近些年来可能近乎于0.

        有点偏离主题了。gcc源码可以通过ftp获取也可以去官网或者github获取。但是我更推荐ftp因为快。其它途径受某些限制的影响很慢。

ftp://gcc.gnu.org/pub/gcc/infrastructure

进来之后有这些东西,release是发布的版本,下载下来可以直接使用

infrastructure目录扮演着至关重要的角色。这个目录主要包含了GCC编译过程中所需的一些基础设施和依赖库。具体来说,这些依赖库是GCC正确编译和运行的基石,它们提供了必要的数学运算和算法支持。

通常,在infrastructure目录下,你会找到诸如GMP(GNU Multiple Precision Arithmetic Library,GNU多精度算术库)、MPFR(Multiple Precision Floating-Point Reliably,多精度浮点可靠库)、MPC(Multiple Precision Complex,多精度复数库)等关键依赖库的源代码。这些库分别用于支持高精度整数运算、高精度浮点运算以及高精度复数运算,是GCC在编译和优化过程中不可或缺的组件。

例如,当你尝试手动下载并安装GCC时,你可能需要先从infrastructure目录下载这些依赖库的源代码,然后在编译GCC之前将它们解压并放置在合适的目录中。这样,GCC在编译过程中就能够正确地找到并使用这些依赖库,从而确保编译出的GCC版本具备完整的功能和性能。

        libstdc++是GCC项目中的一个重要部分,它实现了C++标准库。这个库为C++程序提供了基本的运行时支持,包括内存管理、输入输出、字符串处理等功能。在使用GCC编译C++程序时,libstdc++通常是必需的。

        在软件开发和版本控制领域,“snapshots”通常指的是软件在某一特定时刻的状态记录,也就是快照。这种快照版本通常代表软件的不稳定、尚处于开发中的状态。对于GCC和libstdc++来说,快照版本可能包含了最新的功能或修复,但也可能存在一些未知的问题或错误。因此,使用快照版本需要谨慎,并进行充分的测试。

也可以从gnu官网获取

Software- GNU Project - Free Software Foundation

现在gnu有中文的网页了,十分人性

 我原来在imax6ull上适配的linux是基于7.5的,在exynos4412上适配的是基于4.6.4的,imax6ull已经捐给学校了,因为做我的毕设了。所以现在就拿exynos4412展示吧

gcc的代码都用sha512做的加密,防止下载过程中被黑客注入木马什么的。

Index of /gnu/gcc/gcc-4.6.4

防止有的兄弟找不到可以直接在这个目录下载

        篇幅问题下期在讲gcc源码的目录层次。最近工作特别忙,也就抽出来这点时间搞点自己的事情,顺便和大家分享一下。后面我会调整一下个人时间分配,多花些时间提升自己。希望各位爱好技术的兄弟们我们可以顶峰相见。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式攻城狮-宇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值