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未发布的问题,因为我们仍处于相同的功能中.
'函数返回时,alloca'd内存自动释放.
我们应该如何编译while循环?
我们可以避免这个问题吗?
你生成错误的IR:具体来说,alloca在循环中是一个坏主意,并且确实可能导致堆栈溢出.
我希望看到的是alloca外循环,然后load,add和store序列内循环.以后你可以运行mem2reg通,这将摆脱的allocaS和转换load以及store更高效的phi.
alloca对于while条件,同样的事情:你需要做同样的事情,提前准备内存,只在循环内部准备内存store.