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?
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. –