使用LLVM IR中的小字符串初始化大型i8阵列

时间:2015-11-17 03:36:52

标签: llvm llvm-ir

我想用一个小字符串在LLVM IR中初始化一大块i8。我想做这样的事情:

@str = [1024 x i8] c"Hello World!\0A\00"

请注意,字符串长度仅为14(如果您不计算空字节,则为13)。我现在不关心其他字节的内容。由于初始化程序数组大小与目标数组大小不匹配,上述代码因constant expression type mismatch而无效。一种解决方案是在字符串后发出正确数量的\00 s,但我不想这样做,因为它会导致大量无用的垃圾。有没有我可以采取的快捷方式,还是我必须执行两步为字符串分配空间然后将字符串常量复制到它?如果我确实需要执行这样的副本,我应该使用什么?

1 个答案:

答案 0 :(得分:0)

在LLVM IR中,全局变量定义has to be initialized。对于数组初始化,array constant必须匹配数组的大小。因此,我没有办法在没有尾随零的情况下一步初始化数组。

但是,您可以使用zeroinitializer初始化带有零的I8数组,然后使用strncpymemcpy将小字符串复制到其中。您可以在C中编写这样的片段,看看clang如何编译它:

#include <string.h>

extern char str[1024] = "";

int main() {
    char* hello = "Hello World!";
    strncpy(str, hello, sizeof(str));
    return 0;
}

使用clang -O3 -S -emit-llvm test2.c -o test.ll时,bitcode文件应类似于以下内容:

@str = global [1024 x i8] zeroinitializer, align 16
@.str = private unnamed_addr constant [13 x i8] c"Hello World!\00", align 1

define i32 @main() nounwind uwtable {
  %1 = tail call i8* @strncpy(i8* getelementptr inbounds ([1024 x i8]* @str, i64 0, i64 0), i8* getelementptr inbounds ([13 x i8]* @.str, i64 0, i64 0), i64 1024) nounwind
  ret i32 0
}

declare i8* @strncpy(i8*, i8* nocapture, i64) nounwind