将LLVM代码与C代码集成的正确方法是什么?

时间:2016-03-17 19:43:40

标签: c llvm jit

所以,我有一些生成LLVM IR的代码。在仔细阅读了本手册后,我设法编写了一个编写如下代码的函数:

define [1 x i32] @topLevel([3 x i32] %inputArray, 
    [1 x i32] %returnArray) {
bb0:         
  %node_1 = extractvalue [3 x i32] %inputArray, 0
  %node_2 = extractvalue [3 x i32] %inputArray, 1
  %node_3 = extractvalue [3 x i32] %inputArray, 2
  %node_8 = and i32 %node_1, %node_2
  %0 = xor i32 %node_8, 1
  %node_7 = and i32 %node_3, %0
  %1 = xor i32 %node_3, 1
  %node_6 = and i32 %1, %node_8
  %2 = xor i32 %node_6, 1
  %3 = xor i32 %node_7, 1
  %node_5 = and i32 %2, %3
  %node_4 = xor i32 %node_5, 1
  %4 = insertvalue [1 x i32] %returnArray, i32 %node_4, 0
  ret [1 x i32] %4
}        

然而,我得到一些非常随机的输出,我无法弄清楚为什么。

所以我在C中编写了一些测试代码,并尝试使用clang将其与前一个函数一起编译。

#include <stdio.h>

int * topLevel(int*, int*);

int main() {
  int i[3] = {0, 0, 0};
  int o[1] = {0};
  int *r;

  printf("sizeof(int) = %lu\n", sizeof(int));

  int a =0, b = 0,c=0;
  for (a=0; a < 2; ++a) {
    for(b=0; b < 2; ++b) {
      for(c=0; c < 2; ++c) {
        i[0] = a;
        i[1] = b;
        i[2] = c;
        r = topLevel(i, o);
        printf("i={%d, %d, %d} o={%d}\n", i[0], i[1], i[2], o[0]);
      }
    }
  }
}

我非常乐观,我会得到正确的输出。男孩,我错了。

我期望输出的是:

 sizeof(int) = 4
 i={0, 0, 0} o={0}
 i={0, 0, 1} o={1}
 i={0, 1, 0} o={0}
 i={0, 1, 1} o={1}
 i={1, 0, 0} o={0}
 i={1, 0, 1} o={1}
 i={1, 1, 0} o={1}
 i={1, 1, 1} o={0}

然而,输出是这个,这是假的:

 sizeof(int) = 4
 i={0, 0, 0} o={0}
 i={0, 0, 1} o={0}
 i={0, 1, 0} o={0}
 i={0, 1, 1} o={0}
 i={1, 0, 0} o={0}
 i={1, 0, 1} o={0}
 i={1, 1, 0} o={0}
 i={1, 1, 1} o={0}

我做错了什么?对不起。我想问一个更具体的问题,但我迷路了。我不知道从哪里开始寻找错误。

1 个答案:

答案 0 :(得分:1)

事实证明问题并未将我的代码与LLVM IR代码链接起来。

答案更简单:提取值和插入值说明无意用于处理内存中的数组。它们用于在寄存器中使用数组。

为了说明(并测试)我遇到的问题,我写了两个更简单的代码。

第一个用于处理寄存器中的数组,不适用于C数组。当它由C代码调用时,它将产生垃圾:

define [1 x i32] @workWithRegisterArrays([1 x i32] %inputArray, 
                                         [1 x i32] %returnArray) {
bb0:         
  %0 = extractvalue [1 x i32] %inputArray, 0
  %1 = insertvalue [1 x i32] %returnArray, i32 %0, 0
  ret [1 x i32] %1
}        

第二个代码,将第一个参数的数组的第一个元素从第二个参数复制到数组的第一个元素。 要在C中使用数组,您需要使用getelementptr来查找索引,以及实际执行内存访问的加载和存储操作。

define void @workWithMemoryArrays(i32* %inputArray, 
                                  i32* %returnArray) {
bb0:         

  %elem_in  = getelementptr inbounds i32, i32* %inputArray, i32 0
  %elem_ret = getelementptr inbounds i32, i32* %returnArray, i32 0
  %val      = load i32, i32* %elem_in
  store i32 %val, i32* %elem_ret
  ret void
}        
相关问题