Je suis en train d'écrire un compilateur pour un simple langage C-like pour un cours que je prends. Ce bit de code:Quel est le problème avec ce numéro de registre LLVM?
int main() {
printInt(not(0));
return 0;
}
int not(int n) {
if (n == 0) {
return 1;
} else {
int result = 0;
return result;
}
}
..Je à cette compilation naïvement code binaire:
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
}
Cependant, opt n'accepte pas ce code.
opt: core023.ll:25:5: error: instruction expected to be numbered '%2'
%1 = load i32* %result_0
Maintenant, ce que je comprends des registres temporaires anonymes, ils sont censés être numérotés de manière séquentielle à partir de 0. Ce qui est le cas ici. Mais apparemment la ligne "% 1 = sub .." aurait dû être numérotée% 2. Pourquoi donc? Est-ce que l'une des instructions entre% 0 et% 1 augmente le numéro de séquence? Ou peut-être que c'est juste une faute de suivi de quelque chose d'autre?
Une autre façon d'interpréter la cause du problème est que vous devez éviter de vous ramifier immédiatement après une instruction return. Si votre langage a du code pour garantir le retour de tous les chemins de contrôle, il devrait être trivial de vérifier si votre branche précédente est déjà retournée ou non. Dans le cas où il est retourné, il n'est pas nécessaire d'insérer l'instruction branch (br). Vous aurez besoin d'une certaine quantité de comptabilité d'état pour rendre LLVM heureux avec vos blocs de base. –