Skip to content

Blog

LLVM框架(1): 开篇

引言

LLVM(Low Level Virtual machine)项目是由一系列现代编译工具组成的编译器框架,主要子项目包括:

  • LLVM Core: 提供LLVM IR
  • Clang:一个现代C、C++等语言编译器前端
  • LLDB: 调试器
  • libc++:支持C++11、C++14的C++标准库
  • compiler-rt: 运行时库
  • polly: 公共库
  • OpenMP:让Clang支持OpenMP
  • libclc: 实现OpenCL
  • LLD: 链接器
  • ......

按照理解,通过LLVM可以快速建立一个新的编程语言,只要建立了AST后,遍历AST生成LLVM IR形式,这样就可以利用起LLVM自带的大量优化和后端代码生成,从而支持更多的后端硬件平台。

客家人的一种少见“伯-叔”类关系称呼

为什么父亲会管我爷爷叫“叔”,而母亲会管我外婆叫“耶”?

对此,我从小就感到疑惑,但没有得到过满意的解释,大人们都说老一辈就是习惯这样叫的。

最近看南北朝时期的史书,想到南陈后主陈叔宝,还有唐初名将秦叔宝,这里面的“叔宝”的意思就是“爸爸的宝贝”吗?

带着这个关于父母称呼的问题,找到中央民族大学2013年李瑶的一篇硕士论文《汉语“阿”类父母称谓词研究》,算是解惑了。

关于学日语这件事

2010年,那是大三下学期,已经没有太多课了,有时候会跑到教学楼找个安静人少的教室自习。

有一天下午进了一个安静的教室,人不太多,看了一会儿书后突然走进来一位女老师,然后开始用日语上课,原来这是人家的课堂啊!

我震惊了,难道这所理工类学校还有日语专业,我怎么从来没听说过呢?(查资料显示: 日语专业组建于2003年,属于外国语学院)

然后听到老师叫一位男同学到讲台上做学习分享,那个男生在黑板上写了一个大大的“萌”字,然后介绍说最近日本在流行“萌文化”,形成了一种“萌现象”。

使用Dockerfile和CMake编译LLVM程序

引言

Docker是非常方便使用的虚拟容器技术,为自己的项目或程序提供一个Dockerfile文件可以快速的建立对应的开发或部署环境,减少因为环境或工具链缺失而痛苦、漫长的前期准备工作。

LLVM是备受瞩目的编译器项目,提供了一系列工具链,但要将其引入自己的代码中进行编译的过程却也不是那么容易,甚至会导致很多人放弃尝试。

这篇通过Dockerfile建立一个开发环境,然后在这个环境中通过CMake配置以顺利使用LLVM工具链完成项目构建,以后想继续学习或使用LLVM就可以在这个环境中拿这个模板直接操作了。

用readline库改进REPL交互体验

The GNU Readline library provides a set of functions for use by applications that allow users to edit command lines as they are typed in.

引言

GNU readline库是广泛使用的C语言库,在EmacsVi中都有使用到:

这篇将使用此库建立一个简单的REPL,具备一定的交互能力,然后通过默认配置文件以支持中文输入。

Ledge语言:字节码编译文件的存储与加载

Ledge语言: https://ledge-lang.github.io/zh/

引言

虚拟机编译器生成字节码后,如果不是保存在内存中,而是要保存为字节码文件,比如Java保存的.class文件,Python保存的.pyc文件,这些文件里面主要是序列化的常量池和字节码本身。

这里先简单看看.pyc文件里面存了什么,然后为Ledge语言实现初步的字节码文件存储与加载。

C++实现编译器(12): 结语

参照《Writing An Interpreter/Compiler In Go》,改用C++实现。

项目源码: https://github.com/LeslieZhu/monkey-cpp

引言

这两本书是2022年6月出版,8月买到手,11月中旬开始细读,12月中旬完成,历时1个月,记录笔记共10篇。

至此,自制解释器与编译器告一段落,在这过程中获得了一个自顶向下树遍历解释器和一个基于字节码的虚拟机及编译器。

C++实现编译器(11): 闭包

参照《Writing An Interpreter/Compiler In Go》,改用C++实现。

项目源码: https://github.com/LeslieZhu/monkey-cpp

引言

本篇对应的源码位于目录: src/10/

闭包是迄今为止字节码编译器和虚拟机领域中最重要的功能之一。

比如:

let newAdder = fn(a){
    let adder = fn(b) { a + b; }
    return adder;
}

let addTwo = newAdder(2);

addTwo(3); // => 5

newAdder函数返回的adder就是闭包,因为它不仅有自己的参数b,还可以继续访问自己被定义时候的newAdder的参数a。