Sto scrivendo un compilatore per un semplice linguaggio di tipo C per un corso che sto seguendo. Questo bit di codice:Cosa c'è di sbagliato con questo numero di registro LLVM?
int main() {
printInt(not(0));
return 0;
}
int not(int n) {
if (n == 0) {
return 1;
} else {
int result = 0;
return result;
}
}
..Io ingenuamente compilare a questo codice binario che:
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
}
Tuttavia, opt non accetta quel codice.
opt: core023.ll:25:5: error: instruction expected to be numbered '%2'
%1 = load i32* %result_0
Ora, da quanto ho capito di registri temporanei senza nome che si suppone di essere numerati in sequenza a partire da 0. che è il caso qui. Ma a quanto pare la riga "% 1 = sub .." avrebbe dovuto essere numerata% 2. Perché? Qualcuna delle istruzioni tra% 0 e% 1 aumenta il numero di sequenza? O forse è solo un difetto successivo di qualcos'altro?
Un altro modo di interpretare la causa del problema è che è necessario evitare la ramificazione immediatamente dopo una dichiarazione di ritorno. Se la tua lingua ha il codice per garantire che tutti i percorsi di controllo ritornino, allora dovrebbe essere banale verificare se il tuo precedente ramo è stato restituito o meno. Nel caso in cui sia ritornato, non è necessario inserire l'istruzione branch (br). C'è una certa quantità di contabilità statale che dovrai fare per rendere LLVM felice con i tuoi blocchi di base. –