LLVM alloca导致while语句上的堆栈溢出

Bin*_*ain 4 compiler-construction llvm llvm-ir

我正在为针对LLVM-IR的玩具语言实现前端编译器,并且在运行编译while语句时遇到堆栈溢出:

例如,此代码应该永远运行,但我们的编译版本堆栈在一段时间后溢出.

def run(): Void = {
    i = 0;
    while(true) {
        i = i + 1;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是编译的LLVM-IR:

define i32 @run() nounwind ssp {
    ; i = 0
    %i = alloca i32, align 4
    %1 = alloca i32, align 4
    store i32 0, i32* %1, align 4
    %2 = load i32* %1, align 4
    store i32 %2, i32* %i, align 4
    br label %3

; <label>: %3
    ; while(true)
    ; Generated by compileExpression(condition)
    %4 = alloca i1, align 4
    store i1 true, i1* %4, align 4
    %5 = load i1* %4, align 4
    br i1 %5, label %6, label %11

; <label>: %6
    ; i = i + 1
    ; Generated by compileExpression(body)
    %7 = load i32* %i, align 4
    %8 = alloca i32, align 4
    store i32 1, i32* %8, align 4
    %9 = load i32* %8, align 4
    %10 = add nsw i32 %7, %9
    store i32 %10, i32* %i, align 4
    br label %3

; <label>: %11
    %12 = load i32* %i, align 4
    ret i32 %12
}
Run Code Online (Sandbox Code Playgroud)

我们认为我们的问题来自于所有alloca未发布的问题,因为我们仍处于相同的功能中.

LLVM文档:

'函数返回时,alloca'd内存自动释放.

我们应该如何编译while循环?
我们可以避免这个问题吗?

Oak*_*Oak 7

你生成错误的IR:具体来说,alloca在循环中是一个坏主意,并且确实可能​​导致堆栈溢出.

我希望看到的是alloca外循环,然后load,addstore序列内循环.以后你可以运行mem2reg通,这将摆脱的allocaS和转换load以及store更高效的phi.

alloca对于while条件,同样的事情:你需要做同样的事情,提前准备内存,只在循环内部准备内存store.