为什么LLVM抛出不兼容类型的"参数"创建数组时出错?

时间:2013-09-10 05:02:39

标签: python compiler-construction llvm llvm-py

我正在使用LLVM和llvmpy库。

我的目标是创建类似于以下C代码的东西:

int a[] = {1, 2};
int b[] = {1, 2, 3};
int c[] = {1};
int* ptrs[] = {a, b, c};

以下是上述摘录的输出IR:

%1 = alloca i32, align 4
%a = alloca [2 x i32], align 4
%b = alloca [3 x i32], align 4
%c = alloca [1 x i32], align 4
%ptrs = alloca [3 x i32*], align 16
store i32 0, i32* %1
%2 = bitcast [2 x i32]* %a to i8*
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %2, i8* bitcast ([2 x i32]* @main.a to i8*), i64 8, i32 4, i1 false)
%3 = bitcast [3 x i32]* %b to i8*
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %3, i8* bitcast ([3 x i32]* @main.b to i8*), i64 12, i32 4, i1 false)
%4 = bitcast [1 x i32]* %c to i8*
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %4, i8* bitcast ([1 x i32]* @main.c to i8*), i64 4, i32 4, i1 false)
%5 = getelementptr inbounds [3 x i32*]* %ptrs, i64 0, i64 0
%6 = getelementptr inbounds [2 x i32]* %a, i32 0, i32 0
store i32* %6, i32** %5
%7 = getelementptr inbounds i32** %5, i64 1
%8 = getelementptr inbounds [3 x i32]* %b, i32 0, i32 0
store i32* %8, i32** %7
%9 = getelementptr inbounds i32** %7, i64 1
%10 = getelementptr inbounds [1 x i32]* %c, i32 0, i32 0
store i32* %10, i32** %9
%11 = load i32* %1
ret i32 %11

我相信我已经足够了解它 - 它只是抓住指向每个单独数组头部的指针,然后使用getelementptr沿着存储数组走动并插入每个指针。

以下是我在llvmpy中提出的内容:

pointers = []
for array in arrays:
    # Store each of the { 1, ... } arrays in memory.
    type = Type.array(Type.int(), len(arrays))
    ptr = builder.alloca_array(type, Constant.int(Type.int(), len(arrays)))
    builder.store(array, ptr)
    # And keep track of their pointers.
    indices = [ Constant.int(Type.int(), 0), Constant.int(Type.int(), 0) ]
    head = builder.gep(ptr, indices)
    pointers.append(head)
# Finally, construct the array to hold the pointers.
type = Type.pointer(Type.int())
array = Constant.array(type, pointers)
return array

但我收到错误:

  

include / llvm / Support / Casting.h:219:typename cast_retty :: ret_type llvm :: cast_or_null(llvm :: Value *):断言   `isa(Val)&& “不兼容类型的cast_or_null()参数!”'   失败。

在包含代码的行上:

array = Constant.array(type, pointers)

当我检查指针的类型和数组的类型时,它们似乎都是int32*。我究竟做错了什么?并且Value是一个需要投射的通用占位符吗?

1 个答案:

答案 0 :(得分:1)

你在做什么相当于写下以下内容,非法,IR:

%x = getelementptr ...
%y = getelementptr ...
%z = getelementptr ...
%array = [ i32* %x, i32* %y, i32* %z ]

为什么违法?因为您正在尝试创建常量数组(您使用的是Constant类 - 所以Constant.array相当于使用上面的[]数组文字语法包含非常量值(%x%y%z)。如果要将这些指针存储在数组中,则必须首先alloca数组,然后依次将store每个指针放在其中。