㈠ 写编译器必须要会汇编语言吗
这种事情从理论层面来说:不一定要与汇编语言有什么瓜葛。你完全可以让你的编译器直接编译成机器码。大部分C/C++编译器(不是所有的)之所以先编译成汇编语言,是为了解构。从C到汇编的“翻译”相对容易(都算是抽象语言,有语义的),同时汇编语言的编译器效率很高,可以生成质量非常高的机器码。所以两者结合,可以突出各自的优势,减少复杂度。
但是如果有必要,当然也可以直接编写产生机器码的编译器,实际上Java/C#这样的半编译语言和Js这样的脚本语言,都没有先转换成汇编的这一步。前者是因为强大的虚拟机技术,直接把字节码转换成机器码执行了,后者是灵活的解释器,实时把代码转换成机器码执行,而完全没有“编译”这一步(当然如果深究的话,出于性能考虑,很多高性能的解释器也会提前“预编译”一部分代码,但这是具体实现,不是宏观概念)。
㈡ 利用LLVM实现JS的编译器,创造属于自己的语言
本文聚焦于使用LLVM构建JavaScript编译器,旨在探索自定义语言的开发过程。参考官方教程Kaleidoscope实现,本文仅构建JavaScript编译器的演示版本。对于深入学习,如JIT实现与代码优化,可访问github.com/zy445566/llvm-guide-zh,获取官方教程与代码集。
LLVM,作为编译器基础设施,为语言实现提供了强大支持。最初设计用于替代gcc,它超越了简单编译的功能,成为构建新语言的完整工具。本文编译器流程包括:编写AST解析语言结构、将分析结果绑定生成IR(中间语言)、生成二进制或汇编代码。LLVM亦适用于实现JIT,或结合编译器与虚拟机。
首先,定义token类型识别词法结构,并实现解析方法,可同时用于字符跳跃。定义语法结构,自定义解析逻辑。循环获取token并调用对应解析方法,解析JS方法,尤其复杂的是ParseExpression,涉及递归解析表达式。
生成IR相对直觉,需先定义AST结构,然后编写代码将解析结果绑定至IR。IR作为中间语言,简化了语言转换过程。实现编译器,通过编译器生成JSVM文件,使用自编译器编译JS文件,输出结果进行验证。最后,通过C引用JS文件,编译成二进制文件,实现最终功能。
初次接触编译器开发可能感到挑战与混乱,但本文示例展示了如何利用LLVM构建JavaScript编译器,为学习者提供了宝贵经验。期待LLVM未来能更深入地支持JavaScript,例如Facebook的prepack项目尝试使用LLVM将JS编译为二进制,无需运行时。通过本文分享的示例,JS自举的实现之路正逐渐清晰。