编译原理语法分析器_WebAssembly到底处于编译阶段的哪个环节?

463d7cc4a5b2f8bf604e7d1a991806ba.png

作者 | Paul 编辑 | Yonie相信不少人听说过 WebAssembly,它是由 Google、Microsoft、Mozilla、Apple 等几家大公司合作发起的一个关于面向 Web 的通用二进制和文本格式的项目。现在就让我们一步步揭开 WebAssembly 的神秘面纱,并亲自动手将 WebAssembly 应用在实际业务中。   引言  

众所周知,无论是 Chrome、Firefox、Safari、Edge 还是其他浏览器,能够运行的语言就是 Javascript。为了能够让其他语言的代码在浏览器中运行,WebAssembly 才被创造出来。我们并不需要亲自编写 WebAssembly 的代码,唯一要做的就是把其他高级语言编译成 WebAssembly 即可,这样便能复用大量其他语言现有的代码。而且 WebAssembly 还拥有比 JavaScript 更好的性能,能够更快的加载和执行。

e04e4fae8bf14787f21ac57a675e6b09.png

那为啥 WebAssembly 的性能就一定会比 JavaScript 好很多呢?具体原因还得看下它们到底是处于编译阶段哪个环节了。

编译步骤

作为程序员的我们,每天都在用各种高级语言写源代码。但要让机器能读懂这些字符串代码,就得靠编译系统一步步把它们编译成目标代码。

1571c2462e843f788c298ba763666bec.png

预编译

预编译首先会处理源代码中那些以 # 开头(如 #include、#define 等)的预编译指令,在编译开始前就先对原始的代码文件进行调整。经过了预编译之后,你写的代码其实已经有了很大的变化。

词法分析

词法分析是计算机科学中将字符序列转换为单词(Token)序列的过程。进行词法分析的程序或者函数叫作词法分析器(lexical analyzer,简称 lexer),也叫扫描器(Scanner),供语法分析器调用。

词法分析阶段是编译过程的第一个阶段,任务是从左到右以字符流的方式逐行扫描源代码,然后根据构词规则一一识别关键词、标志符、字面量、运算符等,并分割成一个个按顺序排列的标记 Token。

语法分析

语法分析是根据某种给定的形式文法对由单词序列(如英语单词序列)构成的输入文本进行分析并确定其语法结构的一种过程。进行语法分析的程序或者函数叫作语法分析器(parser),供语义分析调用。

语法分析阶段是编译过程的一个逻辑阶段,任务是在词法分析分割出来的标记 Token 的基础上,将 Token 序列组合成各类语法短语如“程序”、“语句”、“表达式”等。

语义分析

语义分析是编译过程的一个最实质性的阶段,任务是对结构上正确的源代码进行上下文有关性质的审查,进行类型审查。

其实经过语法分析之后就能初步得到了抽象语法树,树上的每个节点都是一个表达式,但此时还不确定是否有意义。于是需要通过语义分析,遍历整个抽象语法树,把每个节点的表达式都标识类型,并且验证是否合法。

抽象语法树

抽象语法树(Abstract Syntax Tree,AST),是源代码语法结构的一种抽象表示。它以树状的形式表现编程语言的语法结构,树上的每个节点都表示源代码中的一种结构,如下图所示:

6d1dd6a270271622837c8703df71396c.png

从语法分析开始,就已经生成了初步的抽象语法树。经过了语义分析之后,抽象语法树又变得更加完善,自此最终版的抽象语法树 AST 已经建立完成。

中间码

经过前面几个阶段之后,我们已经有了最终版的 AST。但是该 AST 并不能完美运行在各个硬件平台上,因为不同平台的汇编处理都是不一样的。

于是便在 AST 和多个平台的汇编代码中间,抽象出了一个中间码(Intermediate Representation),在中间码的设计里抹平了硬件平台造成的差异。中间码的强大之处在于跨平台,与语言无关。

目标代码

计算机是通过汇编指令来执行操作的,如移动到内存某个地址、位移多少个字节等。因此需要通过目标平台的汇编器,由 AST 转成的中间码生成目标平台的汇编代码,这些才是机器能读懂的目标代码。

b774c806d9b6fced7af4d19dde644b4e.png

编译前端与后端

前面介绍了这么多编译步骤,其实我们可以把中间码当成一个分界线,中间码以前的环节叫做编译前端,中间码以后的环节叫做编译后端。

编译前端

编译前端包括预编译、词法分析、语法分析、语义分析、抽象语法树等,专门用来处理语言专属特性。虽然不同语言的词法关键字、语法规则、语义分析的函数类型校验可能都不一样,甚至某些语言都没有预编译这个环节,但每个语言都可以开发一套编译前端,按照标准生成的统一中间码就可以无缝对接给任意编译后端,这就是语言无关。

编译后端

编译后端这里只包含了目标代码生成部分,其实还应该包括将目标代码链接成为可执行文件的环节。编译后端专门负责处理各个平台的差异,根据不同语言生成的标准中间码,生成对应的目标代码,这就是平台无关。

530ec6846c082e642a622e2e0ca931bd.png

编译工具 GCC

GCC(GNU Compiler Collection,GNU 编译器套装),包含了编译前端与编译后端所有模块。其中,编译前端部分支持 C、C++、Fortran、Pascal、Objective-C、Java 等语言,编译后端支持 x86、mips、Alpha、ARM、AVR、IA-64、SPARC、PowerPC 等 30 多种平台。

GCC 虽然被广泛的使用,但目前也面临了危机。后起之秀的 Clang / LLVM,大有全面赶超 GCC 的势头。

Clang / LLVM

Clang 是一个 C++ 编写、基于 LLVM、发布于 LLVM BSD 许可证下的 C / C++ / Objective-C / Objective-C++ 的编译器。那为啥已经有了 GCC 后还要开发 Clang 呢?Clang 相比于 GCC 有什么优势呢?因为 Clang 是一个高度模块化开发的轻量级编译器,它的编译速度快、占用内存小、非常方便进行二次开发。

而有了 Clang 这个编译器前端还不够,于是就跟 LLVM 这个编译器后端组合成一个完整的编译器套件,如下图所示:

3bc13c39afe63a0aeeb81268ad99068b.png

WebAssembly在编译环节的位置

前面说了这么多,但还是不知道 WebAssembly 处于编译阶段哪个环节啊?心急吃不了热豆腐,凡事都要对基础知识有一定了解之后,才能茅塞顿开。

通过下图你便可以一目了然 WebAssembly 所处的位置,它能做到像 Java 字节码一样,一次编译到处运行,具有跨平台特性。以此同时,作为中间码的 WebAssembly 直接省略编译前端的步骤,而 JavaScript 需要实时编译,相比之下性能优势显著。

05b715967573a556c30bea370b76c22d.png

参考资料

  • WebAssely:解决 JavaScript 痼疾的银弹?: https://www.infoq.cn/article/2017/07/WebAssembly-solve-JavaScript

  • WebAssembly 的过去、现在和未来: http://www.fly63.com/article/detial/1596

  • 扯淡:大白话聊聊编译那点事儿: https://awhisper.github.io/2017/02/26/%E6%89%AF%E6%B7%A1%EF%BC%9A%E5%A4%A7%E7%99%BD%E8%AF%9D%E8%81%8A%E8%81%8A%E7%BC%96%E8%AF%91%E9%82%A3%E7%82%B9%E4%BA%8B%E5%84%BF/

  • LLVM 相比于 JVM,有哪些技术优势?: https://www.zhihu.com/question/47819047

  • WebAssembly 系列(三)编译器如何生成汇编: https://zhuanlan.zhihu.com/p/25718411

  • WebAssembly 入门:将字节码带入 Web 世界: https://www.anquanke.com/post/id/85934

  • JavaScript 是如何工作的:与 WebAssembly 比较及其使用场景: https://blog.fundebug.com/2018/12/24/how-does-webassembly-works/

  • LLVM 编译原理和使用: https://blog.csdn.net/yayaayaya123/article/details/83993041  

48434a2fdbdd67209b392d19058b96cc.gif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值