Code Ă trois adresses
En informatique, le code à trois adresses[1] (TAC ou 3AC) est un type de langage intermédiaire utilisé par les compilateurs comme Clang/LLVM.
Chaque instruction TAC a au plus trois opérandes et est généralement une combinaison d'affectation et d'un opérateur binaire. Par exemple : t1 := t2 + t3
. Le nom dĂ©rive de l'utilisation de trois opĂ©randes dans ces instructions mĂȘme si des instructions avec moins d'opĂ©randes peuvent se produire.
Ătant donnĂ© que le code Ă trois adresses est utilisĂ© comme langage intermĂ©diaire dans les compilateurs, les opĂ©randes ne seront probablement pas des adresses mĂ©moire concrĂštes ou des registres de processeur, mais plutĂŽt des adresses symboliques qui seront traduites en adresses rĂ©elles lors de l'allocation des registres. Il n'est pas rare non plus que les noms d'opĂ©randes soient numĂ©rotĂ©s sĂ©quentiellement, car le code Ă trois adresses est gĂ©nĂ©ralement gĂ©nĂ©rĂ© par le compilateur.
Exemples
Calcul d'une solution d'une équation du second degré
En code à trois adresses, cela se décompose en plusieurs instructions distinctes, plus faciles à traduire en langage d'assemblage. Il est également plus facile de détecter des sous-expressions qui se répÚtent, pour raccourcir le code.
Instruction Ă convertir : Ăcriture dans un langage de programmation classique : x = (-b + sqrt(b^2 - 4*a*c)) / (2*a)
|
Code Ă trois adresses : t1 := b * b
t2 := 4 * a
t3 := t2 * c
t4 := t1 - t3
t5 := sqrt(t4)
t6 := 0 - b
t7 := t5 + t6
t8 := 2 * a
t9 := t7 / t8
x := t9
|
Boucle
Le code Ă trois adresses peut avoir des sauts conditionnels et inconditionnels et des mĂ©thodes d'accĂšs Ă la mĂ©moire. Il peut Ă©galement avoir des mĂ©thodes d'appel de fonctions. De cette façon, le code Ă trois adresses peut ĂȘtre utile dans l'analyse de flux de contrĂŽle. Dans l'exemple de type C ci-aprĂšs, une boucle stocke les carrĂ©s des nombres entre 0 et 9 :
int b[10];
for (int i = 0; i < 10; ++i) {
b[i] = i * i;
}
|
t1 := 0 ; Initialisation de i
t2 := b ; Initialisation d'un pointeur sur b[i]
L1: if t1 >= 10 goto L2 ; Saut conditionnel
t3 := t1 * t1 ; Calcul du carré de i
*t2 := t3 ; Déréférencement, affectation dans b[i]
t1 := t1 + 1 ; Incrémentation de i
t2 := t2 + 4 ; Passage Ă la case b[i] suivante
goto L1 ; Répétition de la boucle
L2:
|
Le code Ă trois adresses sur la droite contient une optimisation : le pointeur t2
, qui parcourt les cases du tableau b
, est incrémenté en synchronisation avec i
. Le chiffre 4 correspond au nombre d'octets utilisé par chaque case de b
(en C, une variable de type int
occupe gĂ©nĂ©ralement 4 octets). Sans cette optimisation, il aurait Ă©tĂ© nĂ©cessaire dâutiliser deux adresses (appelĂ©es t4
et t5
ci-dessous) Ă la place de la simple adresse t2
:
t4 := i * 4
t5 := b + t4
*t5 := t3
Notes et références
- Aho, Alfred V. (Sethi, Ravi., Ullman, Jeffrey D., 1942-), Compilers, principles, techniques, and tools, Reading, Mass., Addison-Wesley Pub. Co, , 466 (ISBN 0201100886, OCLC 12285707, lire en ligne )