了解 LLVM IR,从手写开始

一、总览 如果你想要了解 LLVM,那么有几种可能呢?你或许是想要创造一门新的编程语言的技术爱好者;或是陷入编译课的泥沼不能自拔的大学生,但不管怎么样,你都只希望使用 LLVM 做一件事:生成目标代码。 但是这一过程并不容易。你大概率经过了编译前端的艰辛历程,但是现在在你面前的是另一座大山,LLVM IR。在最开始就看到什么基本块、虚拟寄存器、phi 节点之类的概念使你心烦意乱;各种各样的代码示例中充满了和重点并不相关的细节。这些都使你无从下手…… 或许一个更好的学习方式是将 LLVM IR 视为一种特殊的编程语言,而非编译器的 “中间表示”。这种语言站在了高级与低级语言之间,既具备了一定的抽象能力,又反映了底层汇编的工作原理。 本篇文章,就将以编程语言的视角粗略介绍 LLVM IR。通过直接手写 LLVM IR,逐步分析其特点和原理。希望能够有所帮助。 (1)准备工作 LLVM IR 虽然是中间代码,但是 LLVM 也提供了 lli 工具用于解释/即时编译执行 LLVM IR 文件。这样 LLVM IR 又与 Java 字节码有了一些相似之处。使用 lli 可以直接运行我们手写的中间代码,很是方便。使用 lli 这需要安装 LLVM。 sudo apt-get install llvm 另外,LLVM 中是没有内建输入输出的,因为 LLVM 的工作在操作系统之下。这就导致了一个问题,我们不能得知程序的执行结果。一种方法是可以用函数的返回值来输出,但是这样输出只能是单个数值。为了方便起见,可以先用 c 语言编写一个输出库。并使用 clang 将其编译成 LLVM IR。为此需要安装 clang sudo apt-get install clang 对于输出库,这里只简单定义 putint 函数。 // lib.c #include <stdio.h> void putint(int i) { printf("%d\n", i); } 使用 clang 将其翻译成中间代码。不要担心,我们并不需要关心生成的 lib....

十一月 3, 2023 · 17 分钟 · 3612 字 · Wokron

基本正则表达式总结

简介 正则表达式是用于描述字符串匹配模式的表达式。利用正则表达式进行匹配,可以实现检查字符串是否符合某种规则、字符串是否含有某种子串;替换匹配的子串或者从某个串中取出符合某个条件的子串。 正则表达式的引擎是一种自动机,在根据规则完成自动机的构建后,对任意字符串的匹配都将花费 O(n) 的时间复杂度。有关正则表达式的理论及实现本文并不继续深入。 基本语法 这里将介绍正则表达式的基本语法。另外这里推荐网站 regex101,可以用于验证正则表达式。 字符与字符集 正则表达式中一般的字符用于匹配字符串中对应的相同字符。例如正则表达式 “a” 可以匹配字符串中的字符 ‘a’ 。 “abc” 可以匹配字符串中的子串 “abc” 。 对于在正则表达式中具有特殊含义的字符,需要进行转义,在原字符前加上反斜杠 “\” 用方括号将一个或多个字符括起来表示一个字符集,一个字符集匹配在该字符集中出现的字符。例如 [abc],可以匹配 ‘a’ ‘b’ 或 ‘c’。 还可以在字符集中指定要匹配的字符的范围,例如 [a-z],用来匹配所有的小写英文字母。在同一字符集内可以有多个范围,例如 [a-zA-Z0-9]。 在字符集括号内的所有字符之前添加 “^” 表示对该字符集取反,即匹配所有不在字符集内的元素。例如 [^a-b] 匹配所有不是小写英文字母的元素。 字符 “.” 可用于匹配换行符为所有字符。 限定符 限定符用来指定其前面的部分将要匹配几次。例如a{2,5}匹配2到5个a,即"aa"、“aaa”、“aaaa"和"aaaaa”。具体的限定符含义如下表所示: 限定符 解释 {n} 匹配内容n次 {n,} 匹配内容次数大于等于n次 {n,m} 匹配内容次数为n到m次 * 匹配零次或多次,同{0,} + 匹配一次或多次,同{1,} ? 匹配零次或一次,同{0,1} 注意,限定符匹配默认遵循贪婪原则,即在同样能够完成匹配的情况下,会匹配尽可能多的字符。例如要匹配<html><dir>hello,world</dir></html>中的标签,若使用正则表达式 “<.+>",则只会匹配整个字符串。 解决方法是在限定符后加上一个问号 “?” 。这样限定符的匹配模式便会切换为懒惰匹配,即在同样能够完成匹配的情况下,会匹配尽可能少的字符。 组 用括号将一部分表达式括起,可以将这部分表达式作为一个整体。 比如说,需要匹配 “aacacaaac”,可以归纳出字符串中重复的部分 “a+c”,将该部分作为一个整体,则该部分重复了三次。最终得到可以匹配该字符串的正则表达式为 “(a+c){3}"。 另外,组分为捕获组与非捕获组,捕获组即单纯的括号,非捕获组包括 “(?:exp)” “(?=exp)” “(?!exp)” “(?<=exp)” “(?<!exp)"。这里先说明 “(exp)” 和 “(?...

九月 21, 2022 · 2 分钟 · 241 字 · Wokron