C语言 如何在LLVM IR中将`[8 x i1]`转换为`i8`

niknxzdl  于 2023-08-03  发布在  其他
关注(0)|答案(1)|浏览(103)

我正在编写一个编译器,生成LLVM IR。但是我使用的helper库(ollvm)只支持三种整数类型:i1i32i64。但是,我需要字符和字符串的byte(i8)值。
目前,我正在尝试通过将[8 x i1]转换为i8,从8个i1构造i8值。下面的代码编译了,但没有打印出我所期望的结果。

define i32 @main() #0 {
  %arr = alloca [8 x i1], align 1
  store [8 x i1] [ i1 1, i1 0, i1 0, i1 0, i1 1, i1 0, i1 0, i1 0 ], [8 x i1]* %arr
  %ptr = getelementptr inbounds [8 x i1], [8 x i1]* %arr, i64 0, i64 0
  %ptr2 = bitcast i1* %ptr to i8*
  %result = load i8, i8* %ptr2, align 1
  call void @printByte(i8 noundef %result)
  ret i32 0
}

字符串
printByte函数在C中定义如下。

void printByte(char x) {
    printf("%x", x);
}


这段代码打印1,但我希望它打印1100010001的十六进制值)。
此外,除了第一个值之外,所有数组值都将被忽略。例如,它在给定[0, 1, 0, 1, 1, 1, 1, 1]的情况下打印0,在给定[1, 1, 0, 1, 1, 1, 1, 1]的情况下打印1(只有第一个值重要)。
你能解释一下为什么这段代码是这样工作的吗?我该如何修复它?

9jyewag0

9jyewag01#

数组类型[8 x i1]在LLVM中的大小为8。所以这条线

store [8 x i1] [ i1 1, i1 0, i1 0, i1 0, i1 1, i1 0, i1 0, i1 0 ], [8 x i1]* %arr

字符串
将8 bytes 设置为1,0,0,0,1,0,0,0,而不是8 bits
试试看

%arr = alloca [8 x i8]
store [8 x i8] [i8 1, i8 0, i8 0, i8 0, i8 1, i8 0, i8 0, i8 0], ptr %arr
%result = load i64, ptr %arr
ret i64 %result


返回0x100000001
注意,你应该使用不透明的ptr类型,而不是类型化的指针,一般来说,你不需要在指针类型之间使用bitcast

相关问题