Notes de la séance 7 de TransProg M2
====================================

Traduction de Kontix en Javix

Dans les grandes lignes, cela va beaucoup ressembler à Fopix2javix

Principales différences :

Compilation du If

On parle ici d’un If de TailExpr, le BIf se compilera lui comme
auparavant (cf Fopix2Javix). Dans le cas de TailExpr, comme le
bloc “then” finira déjà par un saut, on n’a pas besoin de mettre le
goto label_end_XY en fin de bloc “then” (et donc pas de label
label_end_XY en fin de bloc “else”. Bref, pour If((cmp_op,be1,be2),te1,te2) :

Compil(be1)
Compil(be2)
ificmp_INVOP label_else_YZ   ;; avec INVOP l'inverse de cmp_op
Compil(te1)
label_else_YZ:
Compil(te2)

Let / BLet

R.A.S., on met le résultat du calcul du BasicExpr be1 dans une variable Javix
vX avant de continuer, cf Fopix2Javix

Call

On s’occupe ici de Call(be,[a0,...an]).

Plus de sauvegarde de variable (et encore moins de restauration).
Plus d’adresse de retour !
Attention : v0 et v1 réservés pour K et E. Donc a0 ira en v2.

calcul de l'argument 0
calcul de l'argument 1
...
calcul de l'argument n
AStore (n+2)
...
AStore 2
Goto label_f
;zone qui n'est plus atteinte

2eme cas : appel indirect, i.e. be n’est pas un Fun :

calcul de be
calcul de l'argument 0
calcul de l'argument 1
...
calcul de l'argument n
AStore (n+2)
...
AStore 2
Goto dispatch ;; avec le resultat du calcul de be sur la pile
;zone qui n'est plus atteinte

Ret

Un Ret(be), c’est une sorte de Call(K,[be]) :

; Pour récuperer le code de label de K:
ALoad(0)
Unbox
Puis calcul de be
AStore(2) ; resultat de be
Goto dispatch

Remarque: comme v0 contiendra toujours un entier (le code du label de la
continuation actuelle), on peut faire une entorse au principe mettant
uniquement des pointeurs ou des entiers boxés dans les variables JVM.
Optimisation possible : décider de toujours mettre dans v0 un entier non boxé.
Dans ce cas, le code précédent devient:

ILoad(0)
Calcul de be
AStore(2)
Goto dispatch

PushCont

Rappel, en pseudo-code un PushCont(cont,saves,expr) correspond à :

let E = [K,E,...saves...] in
let K = cont in
expr

On va donc implémenter ce pseudo-code en Javix:

Push la bonne taille de ce nouvel env
Anewarray
Store dans un temporaire (ou des Dup dans la pile pour garder l'adresse de ce nouveau tableau)
remplir ce tableau:
 - v0 en 1ere case,
 - v1 en deuxième (attention à ne pas avoir déjà écrabouillé v1)
 - et les autres variables dans saves ensuite
Enfin, avec l'adresse du tableau sur la pile,
AStore(1)
Push XYZ
IStore(0) ;; sinon sans l'optimisation cela sera Box puis AStore(0)

DefCont

Autant DefFun n’a rien de spécial, on y met juste la compilation de
son corps (un TailExpr), autant pour un DefCont, il y a un travail
initial, “ouvrir” l’environnement reçu. C’est le travail contraire
d’un PushCont. En pseudo-code:

Defcont(kont,[x,y,z],r,expr)
 ==
 def kont(e,r) =
     let [K,E,x,y,z] = e in
     expr

en pseudo-Javix:

label_kont:
 ; extraire l'environnement e
 v0 <- v1[0] ; changement de K
 v3 <- v1[2] ; mise de x en v3
 v4 <- v1[3] ; mise de y en v4
 v5 <- v1[4] ; mise de z en v5
 ...
 v1 <- v1[1] ; changement de E ;; à bien faire en dernier sinon v1 perdu
 ; v2 contient l'argument r (résultat donné à cette continuation)
 Compil(expr) ; avec la bonne table disant r en v2, x en v3, y en v4 ...

Mise en place initiale de la continuation et de l’env

Mettre quelque part une fonction _ret stoppant juste l’exécution et
rendant la main à la JVM:

_ret:
return

Les toutes premières instructions de notre code seront donc:

Push NNN ; si NNN est le code du label _ret
IStore(0) ; première mise en place de K (si on optimise v0 sans Box)
Push 0
Anewarray
AStore(1) ; première mise en place de E (tableau vide)
Compil(main de kontix)

Calcul de hauteur de pile

A voir la prochaine fois.