首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >LLVM的llc生成不正确的代码

LLVM的llc生成不正确的代码
EN

Stack Overflow用户
提问于 2017-12-21 14:57:14
回答 1查看 87关注 0票数 3

我正在LLVM中编写一个函数pass,它生成IR文件。问题是,组装的代码似乎不像我所期望的那样运行。由于我对LLVM非常陌生,我想知道我是否误解了LLVM的IR语义,或者这是llc的错误行为。

LLVM IR是:

代码语言:javascript
复制
define void @fff(i32*) #0 {
  %2 = alloca i32*, align 8
  %3 = alloca i32, align 4
  %4 = load i8*, i8** @dirty
  br label %5

; <label>:5:                                      ; preds = %1
  store i32* %0, i32** %2, align 8
  %6 = load i32*, i32** %2, align 8
  %7 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.4, i32 0, i32 0), i32* %6)
  %8 = load i32*, i32** %2, align 8
  %9 = load i32, i32* %8, align 4
  %readDirty = load atomic i8, i8* %4 acquire, align 8
  %10 = icmp eq i8 %readDirty, 1
  br i1 %10, label %Restart, label %11, !prof !3

; <label>:11:                                     ; preds = %5
  store i32 %9, i32* %3, align 4
  ret void

Restart:                                          ; preds = %5
  ;EDIT: bug was here. Must include label %5 as a possible destination block
  indirectbr i8* blockaddress(@fff, %5), []
}

这与以下C代码(大致)相对应:

代码语言:javascript
复制
char *dirty=1; 
void fff(int *head) ATTR{
restart:
    printf("head = %p\n", head);
    int r = *head;
    if(*dirty)
        goto restart; //But using indirect branch
}

接下来,我使用以下方法组装、链接和运行:

代码语言:javascript
复制
llc -filetype=obj simpleOut.ll -o out.o
gcc -o exe out.o
./exe

如果我用address 0x7ffeea51d7a8调用函数,它会打印:

代码语言:javascript
复制
head = 0x7ffeea51d7a8
head = 0x2e889e825bf4005c
Segmentation fault: 11

x86_64程序集代码是:

代码语言:javascript
复制
;head reside in rcx
100000d60:  55  pushq   %rbp
100000d61:  48 89 e5    movq    %rsp, %rbp
100000d64:  53  pushq   %rbx
100000d65:  48 83 ec 18     subq    $24, %rsp
100000d69:  48 89 f9    movq    %rdi, %rcx
100000d6c:  48 8d 3d dd 02 00 00    leaq    733(%rip), %rdi
100000d73:  ff 17   callq   *(%rdi)
100000d75:  48 8b 18    movq    (%rax), %rbx
100000d78:  48 8d 3d c0 01 00 00    leaq    448(%rip), %rdi
100000d7f:  48 89 4d f0     movq    %rcx, -16(%rbp)
100000d83:  48 8b 75 f0     movq    -16(%rbp), %rsi
100000d87:  b0 00   movb    $0, %al
100000d89:  e8 62 01 00 00  callq   354 ;call to printf, corrupt rcx
100000d8e:  48 8b 45 f0     movq    -16(%rbp), %rax
100000d92:  8b 00   movl    (%rax), %eax
100000d94:  80 3b 01    cmpb    $1, (%rbx)
100000d97:  74 0a   je  10 <_fff+0x43>
100000d99:  89 45 ec    movl    %eax, -20(%rbp)
100000d9c:  48 83 c4 18     addq    $24, %rsp
100000da0:  5b  popq    %rbx
100000da1:  5d  popq    %rbp
100000da2:  c3  retq
100000da3:  48 8d 05 ce ff ff ff    leaq    -50(%rip), %rax
100000daa:  ff e0   jmpq    *%rax ;jumps to 100000d78
100000dac:  0f 1f 40 00     nopl    (%rax)

问题似乎是,LLVM语句store i32* %0, i32** %2, align 8即使在重新启动之后也会转换为movq %rcx, -16(%rbp),其中寄存器rcx已经被printf函数破坏了。

如果这似乎是一个bug,我将向LLVM提交一个bug报告。只是想确认一下我没有误解LLVM的IR。

llc版本为5.0.0,通过自制安装。gcc (用于链接)为clang-900.0.39.2。

谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-12-21 21:16:37

根据文档,应该向indirectbr指令提供所有可能的目标块的列表。省略被跳到的BB会产生未定义的行为。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47927558

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档