转载

如何在Swift中使用LLVM API?

本文主要内容是演示如何在Swift中使用LLVM,其包含了如下四个要点:

  • 获取最新版本的LLVM
  • 使用CMake和llvm-config编译程序
  • 编写简单的Swift程序,编译并与LLVM进行连接
  • 在内存中编写简单的sum函数并使用LLVM编译器来执行

LLVM的准备

要获取最新版本的LLVM,可以通过中央的SVN repository或官方git镜像进行获取。我建议使用后者,因为速度更快。

对于本文的实例,我会把所有相关文件存放在主目录下的一个目录中:

如何在Swift中使用LLVM API?

LLVM使用CMake来生成程序。编译程序前我们在LLVM目录的同个级别下创建一个独立的目录,并生成编译规定:

如何在Swift中使用LLVM API?

CMake可以生成不同的输出:makefiles, Xcode羡慕, VisualStudio方案等等。如果没有指定别的生成系统,CMake将使用默认的GNU/Make生成系统。

模块化是LLVM的重要优点之一,它里面含有很多“小型”库,部分库会用在本文的示例程序中。如果你是一个LLVM新手,我建议可以借助llm-config工具来进行学习。

可用如下方式来运行llvm-config:

如何在Swift中使用LLVM API?

注意:-j4表示开启多核环境,同时运行4个作业 llvm-config的可用选项还包括了,库路径定位,头文件路径定位,连接标记匹配等等。

也不妨直接使用无选项llvm-config来看看它的运行结果如何。

编译器也是很重要的,我们来看看如何运行它:

如何在Swift中使用LLVM API?

Hello LLVM

上述的准备工作做好后,便可以进行程序编写了。

如何在Swift中使用LLVM API?

如果要检查整个编译环境,可以尝试创建一个空模块然后释放它:

如何在Swift中使用LLVM API?

此外,编译该示例程序还需要向编译器传入标识符,以便指定具体的SDK,指定连接标识,设置头部文件搜索路径等。

如何在Swift中使用LLVM API?

事实上,指定正确的连接标识和库路径是很简单的,这得益于llvm-config:

如何在Swift中使用LLVM API?

至于头部文件和额外参数的实现则更有技巧。正常情况下,在clang中,我们会使用llvm-config - -cflags,注意这方式是不能用在swift编译器中的。让我们检视下- -clfags:

如何在Swift中使用LLVM API?

其输出包含了几个参数,我们可以忽略全部的参数除了头部文件搜索路径(-I …)以及宏定义(-D_...)。问题是swift 编译器不能像clang那样处理宏定义,尽管我们可以使用-Xcc选项来绕过它以clang驱动方式进行:

如何在Swift中使用LLVM API?

如果直接运行它,我们将会看到错误警示:连接器会反馈说不能从ncurses和STD C++库里找到符号。不用担心,正确的写法应该是:

如何在Swift中使用LLVM API?

现在我们执行程序了:

如何在Swift中使用LLVM API?

这看起来未免有点枯燥,但我们有了新的发现:我们可以从Swift里调用LLVM C API!

接下来尝试创建简单的sum加法函数,它对两个输入参数进行现加并返回结果。以下是等价的C程序:

如何在Swift中使用LLVM API?

要创建一个函数,我们需要指定所有用到的类型:返回值类型和参数类型。

多个参数的类型必须以数组方式传递。C API在这方面是强项:

如何在Swift中使用LLVM API?

生成它:

如何在Swift中使用LLVM API?

执行:

如何在Swift中使用LLVM API?

原型就绪后,接着就是函数主体的编写。

代码原子是基本区块。函数和循环体,条件分支(if/else,switch/case等)这些都是基本的区块。我们的函数里也有类似的区块:

如何在Swift中使用LLVM API?

该区块可以使用builder来完成。第一步是获得对函数参数的访问;第二步是使用temp变量来存储结果。最后一步是return语句。

如何在Swift中使用LLVM API?

把该代码放置在sumFunction声明的后面,但是要在LLVMDumpModule之前。完整的示例代码请在文章末端进行查阅。

编译并运行,你将看到如下的函数体:

如何在Swift中使用LLVM API?

最后也是最有趣的环节来了—如何运行这些代码?

LLVM C API 提供了一些执行引擎:如MCJIT以及Interpreter,我们使用的是后者。

下面让我们创建一个执行引擎:

如何在Swift中使用LLVM API?

最后,让我们执行整个加法运算。这里我们使用与函数类型类似的技巧—使用UnsafeMutablePointer来进行API指向。请记得在最后进行相关的内存销毁。

如何在Swift中使用LLVM API?

运算结果应该是:

如何在Swift中使用LLVM API?

完整的代码示例:

如何在Swift中使用LLVM API?

如何在Swift中使用LLVM API?

小结

从Swift中使用LLVM是件很美妙的事情。它给了我们一个非常好的机会—在Swift中借助LLVM来编写语言。C API虽然有一定限制,但是以这为起点也绰绰有余了。

英文出自: lowlevelbits 

正文到此结束
Loading...