编译的那些事儿

283 阅读3分钟

概念

编译 就是把高级语言逻辑 转换为 低级语言指令

那么问题来了:低级语言和高级语言是啥?

低级语言:是涉及到寄存器,cpu指令等,与机器有关,描述在机器上具体执行过程的语言。

计算机硬件只能识别“断开”(0)和“闭合”(1)两种物理状态,低级语言符合机器的思考方式。
如字节码、机器语言、汇编语言

高级语言:是用来表达逻辑,提供各种逻辑组织方式(if else等)的语言。

高级语符合人的思考方式,编写和阅读都相对容易。
如Javascript、C、C++、Java、Python

低级语言执行效率高,高级语言开发效率高

解析(parser)

词法解析:按照状态机进行分词,把字符串拆分到最小颗粒的单词;

语法解析:单词之间的组合方式

LL 解析和 LR 解析

LL parsing:从左到右,尝试构建最左边的推导

LR parsing:从左到右,尝试构建最右边的推导

AST处理

AST:Abtract Syntaxt Tree 抽象语法树

编译器(Compiler)处理

按照语法结构递归AST 进行每个节点的翻译,用线性IR的指令来翻译AST节点的属性

语义分析:检查语义错误,主要有 作用域分析 引用消解 类型推倒和检查 正确性检查

程序分析(静态分析):线性IR的分析,建立控制流(if /while /函数调用)图,可以用于编译优化

优化后的线性IR可以生成汇编代码,通过汇编器转成机器码

转译器(Transpiler)处理

转译器的目标代码也是嵌套结构的高级语言,所以转译是从树形结构到树形结构,不需要翻译成线性IR

babel tyoescript eslint postcss prettier 等都是转译器,

babel是把高版本es代码转成低版本 ,并注入polyfill。

Taro也是基于babel封装的小程序转译器

解释器(Interpreter)处理

解释器/直译器:用一门高级语言来解释另一门高级语言(一般都用c++写)

像v8、spidermonkey等都是用c++来写的js解释器。

tree walker解释器:直接解释执行ast

虚拟机:解释线性代码的,比如汇编代码,字节码等这种的程序,因为机器代码就是线性的

Ignation解释器:把解析出的 AST 转成字节码,然后解释执行字节码,热度到达阈值之后会交给 turbofan 编译为汇编代码之后生成机器代码,来加速。gc 是独立的做内存管理的

前端编译相关

工程化相关的转译器: babel、typescript、eslint、terser、prettier、postcss、posthtml、taro、vue template compiler等

js引擎: v8、javascriptcore、quickjs等

wasm(WebAssembly): LLVM(编译框架) 可以生成wasm字节码,所以c++、rust等可以转为LLVM IR(Intermediate Representation,中间表示) 的语言都可以做 wasm 开发

注:通常情况下,一门编程语言只需要完成能够生成LLVM IR的编译器前端即可,然后就可以轻松使用LLVM的各种编译优化、JIT支持、目标代码生成等功能