Le langage RTL de GCC
Portage de GCC pour Simple CPU

Par Wilfrid et Michel

Du RTL àl'assembleur

Les fichiers de descriptions permettent d'interfacer le back-end (le portage sur une cible particulière) avec l'architecture interne de GCC. En interne GCC utilise un méta-language nommé RTL. Il est généré après l'optimisation de l'arbre généré après l'étape de front-end (parsing). Pour appréhender les subtilités de ce langage il est utile de se plonger dans la documentation interne de GCC (GCC internals).

Les fichiers de description contiennent non pas des codes RTL mais la correspondance de patterns RTL avec la sortie assembleur qui va etre généré.

RTL est issu de la représentation d'arbre de syntaxe abstraite, modifié par divers passages dans le 'middle-end' de GCC. Puis Il est converti en langage assembleur pour la cible préalablement choisie.  GCC emploie actuellement la forme RTL pour effectuer une partie de son travail d'optimisation.  RTL est habituellement écrit sous une forme qui ressemble à une expression de LISP.
Une liste RTL est composée de 5 types d’objets :

Langage RTL, les expressions

Les expressions sont classées par leurs codes (notés RTX pour "RTL eXpression"). Les codes que l'on a à disposition sont énumérés dans le fichier rtl.def. Ils sont équivalents à des énumérations du C. De plus, les codes sont indépendants de la cible. Des macros de manipulation de codes sont disponibles :

GET_CODE (x) pour l'extraction.

PUT_Code (x, newcode) pour l'insertion de nouveau code.

Le code RTX détermine le nombre et le type des opérandes qui sont rattachés à l'expression. Un de ces inconvénients est que, contrairement au Lisp, nous ne pouvons pas déterminer la nature des opérandes d'un simple coup d'oeil. Il faut d'abord déterminer le code RTX, puis en déduire leur nature.

Voici un exemple d'un code RTX :

(set:SI (reg:SI 0) (plus:SI (reg:SI 1) (reg:SI 2)))

Cette expression représente l'addition du registre 1 au registre 2, et le stockage du résultat dans le registre 0.

(define_insn "addsi_regs"
  [(set (match_operand:SI 0 "register_operand"  "=r")
    (plus:SI (match_operand:SI 1 "register_operand"  "%0")
         (match_operand:SI 2 "register_operand"  "r")))]
  ""
  "addn    %2, %0"
)

Voici le pattern correspondant à l'instruction décrite précédemment. On trouve en fin d'expression le code assembleur qui sera généré. Dans le cas de l'exemple présent:

addn r1, r2

Les patterns et le code assembleur à générer sont disponibles dans les fichiers ".md"

Le RTL produit par GCC est unique pour chaque processeur cible, car faisant intervenir des optimisations propres à chaque architecture. Cependant, la signification du RTL est plus ou moins indépendante de la cible : il serait habituellement possible de lire et comprendre un morceau de RTL sans savoir pour quel processeur il a été produit.  De même, la signification du RTL ne dépend pas habituellement du langage de haut niveau original du programme.

Lors de la compilation de GCC pour une cible particulière celui-ci requiere qu'un autre ensemble de composants soit présents et prets pour la cile, les binutils.

Présentation des Binutils
Simple-Cpu The Simple CPU project The Simple CPU project
Un projet de disk91
Small CPU project