c编译器学习01:tcc、chibicc简介

出发点

最近在调研大量c代码,人工效率比较低,感觉能用c编译器,实现自动生成代码、自动检查代码…都需要一个基础:c编译器。

tcc

https://bellard.org/tcc/
这个是我目前准备使用的编译器,因为"With libtcc, you can use TCC as a backend for dynamic code generation."
查阅tcc相关资料时,把我引到了8cc(9cc chibicc)等工程,凭感觉,可以从更简单的chibicc入手。

chibicc

https://github.com/rui314/chibicc
文档:https://www.sigbus.info/compilerbook#
作者说他的代码是配合书写的,代码提交历史记录就是逐步的开发过程(功能逐步增加),作者建议按照commit记录来学习。
计划先翻译文档,然后根据代码记录逐步描述chibicc的开发过程。
第一条commit记录:https://github.com/rui314/chibicc/commits/main/?after=90d1f7f199cc55b13c7fdb5839d1409806633fdb+314

C编译器开发的相关链接

https://github.com/rui314/8cc
除了流行的编译器书籍,如《龙书》之外,我发现以下书籍/文档对于开发C编译器非常有用。请注意,标准草案版本与正式版本非常接近。您实际上可以将它们用作标准文档。

LCC: 一个可重定位的C编译器:设计与实现 http://www.amazon.com/dp/0805316701,https://github.com/drh/lcc

TCC:Tiny C Compiler http://bellard.org/tcc/,http://repo.or.cz/w/tinycc.git/tree

C99标准最终草案 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf

C11标准最终草案 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf

Dave Prosser的C预处理算法 http://www.spinellis.gr/blog/20060626/

x86-64 ABI http://www.x86-64.org/documentation/abi.pdf

chibicc README.md 翻译

https://github.com/rui314/chibicc/blob/main/README.md

chibicc:一个小型C编译器

(旧版已移至 historical/old 分支。这是 2020 年 9 月上传的新版本。)

chibicc 是又一个实现了大多数 C11 特性的小型 C 编译器。尽管它可能仍然属于“玩具编译器”类别,就像其他小型编译器一样,但 chibicc 可以编译几个真实世界的程序,包括 Git、SQLite、libpng 和 chibicc 本身,而无需对这些程序进行修改。生成的这些程序的可执行文件通过了各自的测试套件。因此,chibicc 实际上支持广泛的 C11 特性,并且能够正确编译数十万行真实世界的 C 代码。

chibicc 被开发为我目前正在撰写的一本关于 C 编译器和低级编程的参考实现。这本书采用了渐进式的方法来涵盖广泛的主题;在第一章中,读者将实现一个只接受一个数字作为“语言”的“编译器”,然后在书的每个部分中逐步添加功能,直到编译器接受的语言与 C11 规范指定的语言相匹配。我从 Abdulaziz Ghuloum 的论文中采用了这种渐进式方法。

该项目的每个提交都对应于书中的一个章节。出于这个目的,不仅项目的最终状态,而且每个提交都经过了精心编写,考虑到了可读性。读者应该能够通过阅读本项目的一个或几个提交来了解如何实现 C 语言特性。例如,这是 while、[]、?: 和线程局部变量是如何实现的。如果你有充足的空闲时间,从第一个提交开始阅读可能会很有趣。

如果你喜欢这个项目,请考虑在书籍发布时购买一本!😀我在这里发布源代码是为了让人们提前获得它,因为我计划在发布书籍后以一种开放且自由的许可证进行发布。如果我不收费提供源代码,对我来说将其保持私有并没有太多意义。我希望在 2021 年出版这本书。你可以在这里注册,以便在网上免费提供一章内容或书籍发布时收到通知。

我把 chibicc 的发音读作 chee bee cee cee。“chibi”在日语中意为“迷你”或“小”。“cc”代表 C 编译器。

状态

chibicc 几乎支持 C11 的所有强制性特性以及大多数可选特性,还支持一些 GCC 语言扩展。

在小型编译器中经常缺少但被 chibicc 支持的特性包括(但不限于):

预处理器
float、double 和 long double(x87 80 位浮点数)
位域
alloca()
可变长度数组
复合字面量
线程局部变量
原子变量
共享符号
指定初始化项
L、u、U 和 u8 字符串字面量
根据 x86-64 SystemV ABI 指定的以结构体作为值传递或返回的函数
chibicc 不支持复数、K&R 风格的函数原型和 GCC 风格的内联汇编。故意不包含双字符和三字符。

当在源代码中发现错误时,chibicc 会输出简单但友好的错误消息。

没有优化步骤。chibicc 生成的代码非常糟糕,可能比 GCC 的输出慢两倍或更多。一旦前端完成,我计划添加一个优化步骤。

我正在使用 Ubuntu 20.04 的 x86-64 作为开发平台。我做了一些小的更改,使 chibicc 在 Ubuntu 18.04、Fedora 32 和 Gentoo 2.6 上工作,但目前可移植性不是我的目标。除了 Ubuntu 20.04,它可能在其他系统上工作,也可能不工作。

内部结构

chibicc 包含以下几个阶段:

  • 词法分析:词法分析器接受一个字符串作为输入,将其分解为一个标记列表并返回。

  • 预处理:预处理器接受一个标记列表作为输入,并输出一个新的宏扩展标记列表。它在展开宏的同时解释预处理指令。

  • 解析:递归下降解析器从预处理器的输出中构建抽象语法树。它还为每个 AST 节点添加了类型。

  • 代码生成:代码生成器为给定的 AST 节点生成汇编文本。

贡献

当我发现这个编译器中的一个 bug 时,我会回到引入 bug 的原始提交,并重新编写提交历史,仿佛从一开始就没有这样的 bug。这是修复 bug 的一种不寻常的方式,但作为一本书的一部分,保持每个提交都没有 bug 是很重要的。

因此,我不接受此存储库中的拉取请求。如果您发现了一个 bug,您可以向我发送一个拉取请求,但我很可能会阅读您的补丁,然后将其应用到我之前的提交中,通过重写历史。我会在某个地方致谢您的名字,但您的更改将由我在提交到此存储库之前进行重写。

另外,请假设我会偶尔将我的本地仓库强制推送到这个公共仓库以重写历史。如果您克隆了这个项目并在其上进行了本地提交,那么当我强制推送新的提交时,您的更改将不得不手动进行重新基础操作。

设计原则

chibicc 的核心价值在于其简洁性和源代码的可读性。为了实现这个目标,在编写代码时,我小心翼翼地避免过于巧妙。让我解释一下这是什么意思。

通常,当你习惯了代码库时,你会受到诱惑,想要使用更多的抽象和聪明的技巧来改进代码。但这种改进并不总是提高第一次读者的可读性,实际上有时会降低可读性。我尽量避免这种陷阱。我写这段代码不是为了自己,而是为了第一次读者。

如果你看一下源代码,你会发现一些看起来很蠢的代码片段。这些是有意这样写的(但在某些地方我可能确实遗漏了一些东西)。以下是一些显著的例子:

  • 递归下降解析器包含许多看起来相似的函数,用于处理看起来相似的生成式语法规则。你可能会被诱惑去通过使用高阶函数或宏来减少重复,但我认为那太复杂了。最好是允许一些小的重复。

  • chibicc 不会过于努力节省内存。例如,在分词器开始工作之前,整个输入源文件会首先被读入内存。

  • 如果我们知道 n 不会太大,那么慢速算法是可以接受的。例如,在预处理器中,我们使用链表作为集合,因此成员检查的时间复杂度是 O(n),其中 n 是集合的大小。但这没关系,因为我们知道 n 通常是非常小的。即使 n 可能很大,我仍然坚持使用简单的慢速算法,直到通过基准测试证明它是瓶颈为止。

  • 每种 AST 节点类型只使用 Node 结构的几个成员。其他未使用的 Node 成员在运行时只是内存的浪费。我们可以使用联合来节省内存,但我决定简单地将所有内容放在同一个结构中。我相信这种效率损失是可以忽略不计的。即使这很重要,我们随时都可以更改代码以使用联合。我想避免过早优化。

  • chibicc 总是使用 calloc 分配堆内存,它是 malloc 的一种变体,用零清除内存。calloc 稍微慢一些,但应该是可以忽略的。

  • 最后但并非最不重要的是,chibicc 使用 calloc 分配内存,但从不调用 free。分配的堆内存在进程退出之前不会被释放。我确信这种内存管理策略(或者说缺乏策略)看起来非常奇怪,但对于像编译器这样的短暂程序是有道理的。例如,D 编程语言的编译器 DMD 也出于同样的原因使用相同的内存管理方案 [1]。

关于作者

我是植山瑠偉。我是 8cc 的创作者,这是一个业余爱好的 C 编译器,也是 LLVM lld 链接器当前版本的原始创作者,它是各种操作系统和大型构建系统使用的生产级链接器。

参考文献

tcc:由法布里斯·贝拉尔德编写的一个小型 C 编译器。我从这个编译器中学到了很多,但是 tcc 和 chibicc 的设计是不同的。特别是,tcc 是一种单通道编译器,而 chibicc 是一种多通道编译器。
https://bellard.org/tcc/

lcc:另一个小型 C 编译器。创作者写了一本关于 lcc 内部的书,我发现这是一个很好的资源,可以了解编译器是如何实现的。
https://github.com/drh/lcc
https://sites.google.com/site/lccretargetablecompiler/

《逐步构建编译器的方法》
https://blog.csdn.net/weixin_43172531/article/details/136125185

罗布·派克的编程五定律
https://blog.csdn.net/weixin_43172531/article/details/136125027

[1] https://www.drdobbs.com/cpp/increasing-compiler-speed-by-over-75/240158941
DMD 对内存分配的方式有点隐秘。由于编译器是短暂的程序,速度至关重要,因此 DMD 只是不停地分配内存,从不释放。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/691564.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

rocketMQ-Dashboard安装与部署

1、下载最新版本rocketMQ-Dashboard 下载地址:https://github.com/apache/rocketmq-dashboard 2、下载后解压,并用idea打开 3、修改配置 ①、修改端口及rocketmq服务的ip:port ②、修改访问账号、密码 3、然后启动访问: 4、mav…

代码随想录算法训练营第二十三天|669. 修剪二叉搜索树、108.将有序数组转换为二叉搜索树、538.把二叉搜索树转换为累加树

669. 修剪二叉搜索树 刷题https://leetcode.cn/problems/trim-a-binary-search-tree/description/文章讲解https://programmercarl.com/0669.%E4%BF%AE%E5%89%AA%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91.html视频讲解https://www.bilibili.com/video/BV17P41177ud/?sh…

[M二叉树] lc105. 从前序与中序遍历序列构造二叉树(递归建树+迭代建树+经典问题)

文章目录 1. 题目来源2. 题目解析 1. 题目来源 链接:105. 从前序与中序遍历序列构造二叉树 力扣题解:官方题解:从前序与中序遍历序列构造二叉树 之前的博文: 剑指 offer 的博文,有图例,代码也十分清楚&a…

8.2 新特性 - 透明的读写分离

文章目录 前言1. 安装部署1.1 下载安装包1.2 MySQL Shell1.3 配置 MySQL 实例1.4 启动 ReplicaSet1.5 启动 8.2 Router 2. 测试路由总结 前言 MySQL 8.0 官方推出过一个高可用方案 ReplicaSet 主要由 Router、MySQL Shell、MySQL Server 三个组件组成。 MySQL Shell 负责管理…

【.NET Core】C#编程规范

【.NET Core】C#编程规范 文章目录 【.NET Core】C#编程规范一、概述1.1 结构清晰第一1.2 简洁之风1.3 代码风格保持一致性 二、命名约定三、类型参数命名指南3.1 请使用描述性名称命名泛型类型参数,除非单个字面名称完全具有自我说明性且描述性名称不会增加任何作用…

C++寒假打卡2.19

题目列表 #字母转换 难度系数 ⭐ (送分) #数位求和 难度系数 ⭐⭐ (几乎也是送分) #分糖果 难度系数 ⭐⭐⭐ #猴子摘桃 难度系数 ⭐⭐⭐ (板字题) #最大值 难度系数 ⭐⭐⭐⭐…

设计模式三:工厂模式

工厂模式包括简单工厂模式、工厂方法模式和抽象工厂模式,其中后两者属于23中设计模式 各种模式中共同用到的实体对象类: //汽车类:宝马X3/X5/X7;发动机类:B48TU、B48//宝马汽车接口 public interface BMWCar {void s…

Bert基础(一)--transformer概览

1、简介 当下最先进的深度学习架构之一,Transformer被广泛应用于自然语言处理领域。它不单替代了以前流行的循环神经网络(recurrent neural network, RNN)和长短期记忆(long short-term memory, LSTM)网络,并且以它为基础衍生出了诸如BERT、GPT-3、T5等…

2024全年放假日历表及调休安排 用手机便签设置放假倒计时

对于绝大多数的上班族来说,春节长假已经结束,现在要回归到正常的工作和生活中。为了给生活增加一些“盼头”,很多小伙伴不约而同打开手机日历,查看下个法定节假日是什么时候。下面给大家具体讲一下2024全年放假日历表及调休安排&a…

UE5 C++ 创建可缩放的相机

一.要将相机设置在Pawn类里 1.在MyPawn头文件里,加上摇臂和相机组件 #include "GameFramework/SpringArmComponent.h" #include "Camera/CameraComponent.h" 2.在Pawm里声明SceneComponet,SpringArmComponent,CameraComponent组件…

CES 的Agent插件状态显示“故障”该如何处理?

Agent插件状态显示“故障”该如何处理? 操作系统监控插件每1分钟发送1次心跳;当服务端3分钟收不到插件心跳时,“插件状态”显示为“故障”。 “故障”原因可能为: Agent域名无法解析,请先确认修改DNS与添加安全组中D…

Excel生成不重复的UUID

第一步:在单元格中使用函数 第二步:下拉批量生成 生成函数如下: CONCATENATE(DEC2HEX(RANDBETWEEN(0,4294967295),8),DEC2HEX(RANDBETWEEN(0,42949),4),,DEC2HEX(RANDBETWEEN(0,42949),4),DEC2HEX(RANDBETWEEN(0,42949),4),DEC2HEX(RANDBETW…

Unity MVC开发模式与开发流程详解

在Unity游戏开发中,采用MVC(Model-View-Controller)模式是一种非常常见的设计模式。MVC模式将应用程序分为三个部分:模型(Model)、视图(View)和控制器(Controller&#x…

分页工具类

介绍 方法 convertToIPage 用于将一个 List 转换为 IPage&#xff0c;并在方法内部计算总数和总页数。该方法利用了 MyBatis-Plus 框架提供的 IPage 接口&#xff0c;并采用泛型 <T>&#xff0c;使其能够兼容任意类型的数据。 package com.util;import com.baomidou.my…

vue3+element Plus+ts 自定义主题色,以及生成主题色各种透明度

目录 思路 安装css-color-function【接收一个颜色值&#xff0c;生成不同的透明度】 获取后台配置的主题色或者使用ColorPicker修改主题色 最终结果如下 思路 本篇文章的主体思路是从element Plus官网引申而来。结合了我以前用vue2element-ui配置主题色生成透明度&#x…

谈谈:你在工作中用到的设计模式!

谈谈:你在工作中用到的设计模式! Hello大家龙年好! 春节的假期转眼间过去,我们也要回归往日的节奏 因为最近和小伙伴们聊天发现,我们普遍在面试中,对被问起设计模式在工作中的应用,既有点熟悉,又有点陌生, 在网上看吧,又感觉鸡肋(为啥?不能解燃煤之急啊!哈哈),所以,为了打破这…

【大厂AI课学习笔记】【2.2机器学习开发任务实例】(5)数据理解

数据理解&#xff0c;就是理解数据。 理解数据&#xff0c;就是观察数据&#xff0c;获得更多数据的特点。 这里要对数据进行一些处理。 查看样本数据的均值、最大值、最小值、数量、标准差等&#xff1b; 查看更详细的数据分位数信息。 通过观察加深数据理解&#xff0c;…

体验即王道:提升B端管理系统用户体验的10大法则

大家好&#xff0c;我是贝格前端工场&#xff0c;专注于前端开发和UI设计&#xff0c;有需求可以私信。本篇从用户体验角度来分析管理系统如何设计和开发。 一、用户体验的重要性 B端管理系统的用户体验对于企业的成功至关重要。 提高工作效率&#xff1a;一个好的用户体验可…

什么是网络安全?一文了解网络安全究竟有多重要!

随着互联网的普及和数字化进程的加速&#xff0c;网络安全已经成为我们生活中不可或缺的一部分。然而&#xff0c;很多人对于网络安全的概念仍然模糊不清。 那么&#xff0c;什么是网络安全&#xff1f;它究竟有多重要呢&#xff1f; 一、网络安全的定义 网络安全是指保护网络…

python + requests + pytest 接口自动化测试

测试框架目录 目录名称目录内容common1.读取测试用例的方法 2.连接数据库的方法(pymysql) 3.封装自己的请求 4.封装输出日志文件 5.读取保存的数据文件 封装一些公共方法api存储测试接口case封装测试用例data存放测试数据data.xlsx 接口需要用到的字段写进Excel logs存放日志文…