2014-01-09 4 views
4

내가 LLVM-IR을 대상으로 장난감 언어에 대한 프론트 엔드 컴파일러를 구현하고 반면에 스택 오버 플로우가 발생하고 while 문 컴파일 실행 때 내가 스택 오버 플로우가 발생 : 예를 들어LLVM의 alloca를 문

을,이 코드는 영원히 실행해야하지만, 컴파일 된 버전 스택 오버플로가 발생합니다.

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 
} 

우리는 우리의 문제는 우리가 같은 기능을 여전히 때문에 해제되지 않은 모든 alloca에서 오는 생각 : 여기

def run(): Void = { 
    i = 0; 
    while(true) { 
     i = i + 1; 
    } 
} 

그리고

는 comipled LLVM-IR이다.

LLVM Documentation

:

'alloca'd 메모리가 자동으로 할 때 함수가 반환을 발표한다.

while 루프를 어떻게 컴파일해야합니까?
이 문제를 방지 할 수 있습니까?

답변

6

나쁜 IR을 생성합니다. 즉, 루프 내에서 alloca은 좋지 않은 생각이며 실제로 스택 오버플로가 발생할 수 있습니다. 내가 볼 기대 무엇

는 루프 외부의 alloca, 루프 내부 load, addstore 순서입니다. 나중에 alloca을 없애고 loadstore을보다 효율적인 phi으로 변환하는 mem2reg 패스를 실행할 수 있습니다.

while 조건과 동일한 내용 : 동일한 작업을 수행하고 사전에 메모리를 준비하고 루프 내부에만 store 만 넣어야합니다. 하도록 선택할 -mem2reg 결과 후

0

mem2reg 패스를 사용하여 할당 값을 레지스터 값으로 변환하십시오. 레지스터 값은 마지막 사용에 도달하면 해제됩니다.

+0

윌 문이 더 큰 상태/신체 표현이있을 때 동안이 작품? – anotherCode245

+0

예, ir 수준에서 작동하므로 더 많은 지침이 길어질뿐입니다. – user1937198

+0

우리는'opt -S -mem2reg test.ll -o test.ll'을 시도했습니다. 우리는 여전히 몸에'alloca'를 가지고 있기 때문에 여전히 스택 오버플로가 있습니다. –

0
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 
    %3 = alloca i1, align 4 
    store i1 true, i1* %3, align 4 
    %4 = alloca i32, align 4 
    br label %whilecond 

whilecond: 
    ; while(true) 
    ; Generated by compileExpression(condition) 
    %5 = load i1* %3, align 4 
    br i1 %5, label %whilebody, label %whileexit 

whilebody: 
    ; i = i + 1 
    ; Generated by compileExpression(body) 
    %6 = load i32* %i, align 4 
    store i32 1, i32* %4, align 4 
    %7 = load i32* %4, align 4 
    %8 = add nsw i32 %6, %7 
    store i32 %8, i32* %i, align 4 
    br label %whilecond 

whileexit: 
    %9 = load i32* %i, align 4 
    ret i32 %9 
} 

:

define i32 @run() #0 { 
     br label %whilecond 

whilecond:          ; preds = %whilebody, %0 
     %i.0 = phi i32 [ 0, %0 ], [ %1, %whilebody ] 
     br i1 true, label %whilebody, label %whileexit 

whilebody:          ; preds = %whilecond 
     %1 = add nsw i32 %i.0, 1 
     br label %whilecond 

whileexit:          ; preds = %whilecond 
     ret i32 %i.0 
}