2012-05-06 17 views
6

Estoy escribiendo un compilador para un lenguaje simple tipo C para un curso que estoy tomando. Este trozo de código:¿Qué pasa con este número de registro LLVM?

int main() { 
    printInt(not(0)); 
    return 0; 
} 

int not(int n) { 
    if (n == 0) { 
     return 1; 
    } else { 
     int result = 0; 
     return result; 
    } 
} 

..I ingenuamente compilar este código binario:

declare void @printInt(i32) 
declare void @printDouble(double) 
declare void @printString(i8*) 
declare i32 @readInt() 
declare double @readDouble() 

define i32 @main() { 
entry: 
    %0 = call i32 @not(i32 0) 
    call void @printInt(i32 %0) 
    ret i32 0 
    unreachable 
} 

define i32 @not(i32 %n_0) { 
entry: 
    %0 = icmp eq i32 %n_0, 0 
    br i1 %0, label %lab0, label %lab1 
lab0: 
    ret i32 1 
    br label %lab2 
lab1: 
    %result_0 = alloca i32 
    store i32 0, i32* %result_0 
    %1 = load i32* %result_0 
    ret i32 %1 
    br label %lab2 
lab2: 
    unreachable 
} 

Sin embargo, opt no acepta ese código.

opt: core023.ll:25:5: error: instruction expected to be numbered '%2' 
%1 = load i32* %result_0 

Ahora, por lo que entiendo de registros temporales sin nombre se supone que deben ser numeradas secuencialmente empezando por 0. ¿Cuál es el caso aquí. Pero aparentemente la línea "% 1 = sub .." debería haber sido numerada% 2. ¿Porqué es eso? ¿Alguna de las instrucciones entre% 0 y% 1 aumenta el número de secuencia? ¿O tal vez es solo una falla de seguimiento de otra cosa?

Respuesta

9

En LLVM, todo lo que puede tienen un nombre pero no lo hace se le asigna un número. Esto también incluye bloques básicos. En su caso

lab0: 
    ret i32 1 
    br label %lab2 

define dos bloques básicos porque cada terminator instruction termina un bloque básico. Esto significa que, conceptualmente, el código se analiza como

lab0: 
    ret i32 1 
1: 
    br label %lab2 

y el siguiente número libre después de eso es 2.

para evitar un comportamiento extraño como esto, yo siempre recomiendo nombrar explícitamente los bloques básicos.

+0

Otra forma de interpretar la causa del problema es que debe evitar la bifurcación inmediatamente después de una declaración de devolución. Si su idioma tiene un código que garantiza que todas las rutas de control regresen, entonces debería ser trivial verificar si su rama anterior ha regresado o no. En el caso de que haya regresado, no hay necesidad de insertar la instrucción de bifurcación (br). Hay una cantidad de contabilidad estatal que deberá hacer para que LLVM esté contento con sus bloques básicos. –