published on in 编译

JIT・Lightning 示例「incr」

在上一篇文章中我们简单地介绍了一下GNU/Lightning,现在我们来讲解上一篇文章中测试用的示例。

#include <stdio.h>
#include <lightning.h>

static jit_state_t *_jit;

typedef int (*pifi)(int);    /* Pointer to Int Function of Int */

int main(int argc, char *argv[])
{
  jit_node_t  *in;
  pifi         incr;

  init_jit(argv[0]);
  _jit = jit_new_state();

  jit_prolog();                    /*      prolog              */
  in = jit_arg();                  /*      in = arg            */
  jit_getarg(JIT_R0, in);          /*      getarg R0           */
  jit_addi(JIT_R0, JIT_R0, 1);     /*      addi   R0, R0, 1    */
  jit_retr(JIT_R0);                /*      retr   R0           */

  incr = jit_emit();
  jit_clear_state();

  /* call the generated code, passing 5 as an argument */
  printf("%d + 1 = %d\n", 5, incr(5));

  jit_destroy_state();
  finish_jit();
  return 0;
}

引入头文件

#include <lightning.h>

想要成功使用lightning中的一系列函数与变量,我们需要引入头文件lightning.h

声明jit_state_t结构指针

static jit_state_t *_jit;

jit_state_t结构用于存储jit代码声明信息,_jit这个变量名在lightning中有特殊意义,所以通常情况下我们应该直接使用_jit,或者用#define _jit <其它名称>来定义。

定义一个函数类型

typedef int (*pifi)(int);

为了方便我们后续使用jit生成的函数,我们定义一个函数类型与之对应。该类型的函数接收一个int整型返回一个int整型。

声明一个变量用来获取函数参数

jit_node_t  *in;

使用jit_node_t声明的指针in可以用于在jit代码中获取函数的变量。

声明函数指针变量

pifi         incr;

全局初始化jit

init_jit(argv[0]);

必须在创建jit_state_t对象之前调用此函数。该函数会进行全局状态初始化,可能需要检测CPU或操作系统特性。如果在配置时启用了反汇编,它会接收一个字符串参数,该参数稍后用于使用GNU binutils从共享对象中读取符号。如果不执行反汇编,则可以使用NULL指针作为参数。

创建state

_jit = jit_new_state();

准备书写jit代码

jit_prolog();

在此函数调用后我们就可以开始书写jit代码了。

获取函数输入

in = jit_arg();
jit_getarg(JIT_R0, in);

使用in = jit_arg()从函数中获取参数「这里说的函数当前还没有实现,等到相关的代码书写完后会将这个函数赋值给incr」;调用jit_getarg函数将得到的参数in的值传递给寄存器JIT_R0

实现加一操作

jit_addi(JIT_R0, JIT_R0, 1);

jit_addi可实现寄存器整数相加赋值的操作,将第2、3个参数的寄存器值或数值相加并赋值给第1个参数的寄存器。

返回寄存器的值

jit_retr(JIT_R0);

类似C程序中函数的返回语句return,此处使用jit_retr返回了寄存器JIT_R0的值。

生成机器码

incr = jit_emit();

该函数会将之前书写的jit代码转换为机器码,然后封装成一个函数指针,我们使用incr接收它。

清除state

jit_clear_state();

得到incr函数后我们清理掉state中的一些不必要的内容。

调用并观察incr

printf("%d + 1 = %d\n", 5, incr(5));

释放内存中的state信息

jit_destroy_state();

确定不会再使用jit生成的函数后,我们可以释放并销毁内存中的state信息。

结束jit

finish_jit();

最后我们再清除全局的jit state信息。