2009-06-09 6 views
0

Je suis curieuse de savoir comment implémenter inline expansion. J'écris mon propre compilateur juste pour le plaisir et l'éducation. J'apprends beaucoup par l'exemple, donc si quelqu'un peut me fournir un algorithme qui ne m'introduit pas, cela m'aiderait beaucoup.Implémentation de l'extension inline

Je préfère en C++ mais le langage n'a pas d'importance.

La langue cible pour laquelle j'essaie d'écrire est JavaScript. Pour clarifier, je cherche des façons d'améliorer ShrinkSafe. GWT intègre les fonctions javascript, ce qui est possible. GWT effectue une initialisation avant l'exécution du code.

Répondre

1

Une implémentation courante consiste à le faire dans la phase d'optimisation, en tant que règle de réécriture. Vous remplacez l'instruction d'appel de fonction réelle par les instructions appelées (moins l'instruction return, naturellement).

Ensuite, vous vous assurez que l'optimiseur de judas peut éliminer la configuration de pile qui a précédé l'instruction d'appel et le prologue de l'appelé qui est maintenant en ligne. De même, vous devez vous assurer que l'optimiseur de judas peut optimiser l'épilogue des calles et le traitement de la valeur de retour par les appelants. Le plus grand avantage de ceci est qu'il rend la séquence d'instructions contiguës en mémoire et que l'optimiseur de judas vous épargne généralement un tas de push/pop stack.

+0

Quelles heuristiques dois-je utiliser? A quoi ressemblerait le code? Comment vérifier si l'expression est une expression à heure constante? –

+0

Vous recherchez essentiellement des modèles courants tels que "PUSH Reg1; PUSH Reg2; POP Reg3; POP Reg1;" - les instructions PUSH sont ce qui reste de la configuration de l'argument appelant; les POP proviennent du prologue en ligne. Ces 4 ins peuvent être réécrits comme "MOV Reg2 -> REG3", un seul ins. Le type exact de motifs que vous trouverez dans l'optimiseur est bien sûr déterminé par le flux d'instructions émis par * votre * compilateur, donc vous êtes l'expert en la matière. – MSalters

1

La doublure est effectuée après que le code a été analysé dans un arbre.

for(int loop=1;loop <= 10;++loop) 
{ 
    f(loop); 
} 

for-| 
    --- (Init Code)---Assign--| 
    |       --- loop 
    |       | 
    |       --- 1 
    --- (Condition)--- <= | 
    |      --- loop 
    |      | 
    |      --- 10 
    --- (Post) --- ++ | 
    |     --- loop 
    | 
    --- (Body) Call | 
        --- (Function Name) f 
        | 
        --- (Parameter List)---Node1 -- loop 
              | 
              NULL 

Vous aurez également un arbre d'analyse syntaxique pour la fonction f.
Pour intégrer la fonction, vous devez créer une copie de l'arborescence pour la fonction f. Ensuite, parser l'arbre a remplacer toutes les références au paramètre utilisé dans l'appel de fonction avec la variable (boucle dans ce cas). Une fois cela fait. remplacez le nœud 'Call' dans l'arbre ci-dessus par le nouvel arbre que vous venez de créer.