LAO Introduction

Quentin Colombet

1. Generalite

Le LAO ext constitue de 4 packages:

Les 3 packages CDT, ECL et PRO sont a la GNU. C'est-a-dire qu'ils utilisent les mecanismes d'automake et configure.

2. Structure d'un package

PACK/
    Makefile ; makefile du package (cf section suivante pour les targets
             ; supportees)
    DOC/
    LIB1/
    LIB2/
        Makefile ; makefile de la lib (cf section suivante pour les targets
                 ; supportees)
        0/ ; Contient les fichiers input des harnais de (self-)tests
           ; (MyModule.0) (e.g. foo.0)
        1/ ; Contient les fichiers d'output attendu des tests (MyModule.1)
           ; (e.g. foo.1)
            MyTarget1/ ; contient les references MyTarget1 specific
            MyTarget2/
        LIB2.xcc ; Interface global de la librairie
                 ; * struct / include
                 ; * harnais de test
                 ; * fonction de tracing
        Module1 ; (Module1.xcc) (e.g. foo.xcc)
        Module2
        MyTarget1/ ; Repertoire utilise pour le targeting des modules pour
                   ; MyTarget1 lorsque necessaire
             MyModule.xcc ; Un fichier par module necessitant un targeting
                          ; (e.g. foo.xcc)
        MyTarget2/
        
Note
Les tests ou self-tests sont ecrit directement dans le .xcc d'un module. Ils sont ensuite extrait par l'outil xccgen (cf XCC) qui va en generer un fichier. Ce fichier est ensuite compile normalement par un compilateur host (e.g. gcc) pour generer un executable. Cet executable est ensuite appele avec les parametres d'input (repertoire 0) et la sortie est comparee avec la sortie attendue (repertoire 1). A ce point, si difference il y a alors le self tests est considere comme echoue. Pour resumer:
xccgen MyModule.xcc # extrait un fichier de test: MyModule_.c
gcc MyModule.c -o MyModule.tst # genere le test executable (commande
                               # simplifiee)
MyModule.tst < 0/MyModule.0 > MyModule.1
(diff MyModule.1 1/MyModule.1 && echo PASS) || echo FAIL

3. Makefile

3.1. Package

Les targets supportees par le Makefile d'un package:

Semantique conforme a GNU.

3.2. LIB

Les targets supportees par le Makefile d'une LIB:

3.3. LAO

Targets

Les targets supportees par le Makefile du package LAO:

Note
Actuellement LAO build dans les sources -> A modifier ?
Note
Pour faire un compilateur a bencher: make speed (voir speed.def)
Note
Pour faire un compilateur de developpement: make debug (voir debug.def)
Installation (make install)

Lors d'une installation, les repertoires suivants sont crees sous le repertoire

LAO:
export/
    lib/ ; Pour Open64
        lao.so
    include/ ; Pour Open64
        MyTarget1/
            lao_....h ; Ne doivent pas faire un diff avec les fichiers en
                      ; configuration (sous svn) de Open64
        MyTarget2/
            lao_....h
include/ ; include a mettre lors de l'utilisation de LAO
bin/
lib/
share/
    doc/

4. Self-Test

Les self-tests servent a verifier qu'un update de LAO ne casse pas son integration dans Open64

4.1. Structure

Working Copy/ LAO/ CDT/ ; Cree par le make extract ECL/ ; Idem PRO/ ; Idem Makefile LAO_INPUT/ ; En configuration, contient les sources des self-tests LAO_TRACE/ ; A creer a la main. Ce repertoire va contenir l'ensemble des ; traces de sortie des self tests. Il peut aussi contenir des ; informations sur les optimisations LAO (cf plus loin)

4.2. Makefile pour les self-tests Open64 (seulement sous PRO)

Target: * refs * tests: * Utilise des variables de makefile (Variables surchargeable par l'environnement ou sur la ligne de commande) pour specifier: * Le repertoire d'input: LAO_INPUT (par defaut ../../LAO_INPUT) * Le repertoire de sortie des traces: LAO_TRACE (par defaut ../../LAO_TRACE). * Utilise des options passees a LAO que l'on peut surcharger soit: * En les positionnant dans l'environnement * En creant des fichiers se nommant: MyOption=MyValue dans le repertoire specifie par la variable LAO_TRACE * inputs * traces

Note: La liste des options que l'on peut surcharger pour les optimisations de LAO se retrouve dans les fichiers ECL/LIR/configure.xcc, ECL/LIR/optimize.xcc, ... E.g. FORCE_SCHEDULINGMyMask, LIR_TRACEMyFileDescriptor, ...

Note: Tout les tests en input n'ont pas forcement les appels aux trois phases d'optimisations possible de LAO. Typiquement la phase d'allocation peut ne pas etre presente. Bon a savoir lorsque l'on fait des tests sur l'allocation.

Note: On peut directement faire un 'make foo.trace', il faut seulement qu'un fichier foo.input.c existe (utile pour faire des tests avec LAO_INPUT par ex)

5. Documentation

La documenation est directement extraite des commentaires des sources. Le formalisme utilise est passe de Doxygen a asciidoc pour etre maintenant en WLM via xccgen.

5.1. Extraction

L'extraction de la documentation se fait avec la commande suivante: xccgen foo.xcc -k wlm Ici, wlm specifie le format du fichier de sortie (son extension).

L'extraction sort un fichier ascii avec le corps des commentaires marquee "extractible". Pour faire ce marquage, le commentaire doit commencer par /*@XCC. Exemple:

/*@XCC.h
 * MyComment
 * ...
 */

Ce commentaire va produire le texte suivant dans le fichier de documentation:

MyComment
...

Ces commentaires peuvent etre de n'importe quel forme, mais pour etre automatiquement pris en charge par la construction de la documentation (make wlmdoc), ils doivent utiliser le formalisme wlm.

5.2. WLM

Wlm correspond a un wiki language markup. Ces fichiers ascii sont directement lisible mais peuvent aussi etre traduit en html via l'outil wlm2html.pl (situe dans CDT/BIN).

Des exemples de code wlm sont lisible dans sample.wlm (aussi sous CDT/BIN) ou dans n'importe quel source (e.g. LIR.xcc).

Dans ce formalisme, le choix a ete fait de rendre explicite la creation de certaines balises. Concretement cela veut dire que les sequences de caracteres speciales dans certains langages de wiki sont ici normales. Elles n'ont donc pas besoin d'etre echappees pour generer la sequence effectivement ecrite. Exemple:

* foo // pas une liste
*<TAB>foo // une liste lorsque l'on met une vrai tabulation.

5.3. Cas particuliers

L'ensemble des fichiers wlm extrait des commentaires sont pris en charge automatiquement par le processus de construction de la documentation. Cependant, il se peut que vous ayez a documenter des choses ne se trouvant pas dans des sources (e.g. ECL/DOC/index.wlm offre des liens sur la documentation de l'ensemble des modules de la LIB).

Dans ce cas, vous allez creer votre propre fichier wlm que vous allez mettre en configuration. Une fois ce fichier creer, il faut l'ajouter a la liste des documents gerer "a la main" pour la generation du html. Pour cela, il faut l'ajouter dans le fichier makefile.am pour qu'il soit pris en charge par la generation de la documentation.

Attention: Lorsque l'on touche a makefile.am ou configure.ac il faut faire un make -f Maintainer.

6. XCC

6.1. Principe

eXtra C Comments. Extension des commentaires C, ce langage sert, en combinaison avec xccgen, a disptacher et generer automatiquement des portions de codes, ainsi qu'a extraire la documentation (cf Documentation).

De maniere generale, les fichiers utilisant le langage XCC peuvent dans le meme fichier le declarer le prototype et l'implementation associee. Le code sera ensuite dispatcher dans les .h et .c correspondant. Cela permet d'avoir toute l'information centralise pour le developpeur qui met a jour simultanement la documentation, les interfaces et l'implementation.

xccgen est l'outil interpretant les fichiers xcc (sorte de preprocesseur) et generant les .h .c necessaires. Ces fichiers sont ensuite compilable via un compilateur C99.

Ex: foo.xcc -> foo.c foo.h foo_.h foo_.c -> foo.o foo_.o -> .... (xccgen) (gcc)

Concretement, les commandes XCC sont specifiees dans les commentaires des fichiers xcc (fichier C avec commentaire XCC) qui commence avec la directive @XCC.

Cette directive est suivie par l'extension du fichier qui va recevoir le paragraphe suivant. Sachant que le nom de base du fichier et le meme que le fichier xcc.

Exemple avec un fichier foo.xcc:

//@XCC.c  <-- Specifie que le paragraphe suivant doit etre emis dans foo.c

Types de commentaire supportes:

//@XCC MyExtension
MyParagraphe
/*@XCC MyExtension
 * Comment
 * ...
 */
MyParagraphe

La terminaison d'un paragraphe est definit par la sequence de caractere \n\n.

Attention
Le decoupage en paragraphe n'est pas conscient d'un eventuel scoping de fonction/structure.

L'on peut voir xccgen comme un dispatcher de code. Il prend le fichier xcc et en fonction des commentaires qu'il rencontre et ajoute les contributions de chacun des paragraphes dans le fichier specifie. Les paragraphes qui ne sont pas explicitement dispatcher dans un fichier, c'est-a-dire qui ne sont pas precede par un commentaire de la forme "//XCC MyExtension" ou "/*XCC MyExtension", sont emit dans le fichier .c correspondant.

6.2. Conventions

Par convention, le dispatching des sources doit etre repartie dans quatre fichiers en fonction de leur porter:

6.3. Interpretation

Principe

Lorsque le paragraphe est une fonction ou un prototype, il est directement emis dans le fichier specifie par le commentaire xcc ou a defaut le .c. Toutefois, lorsque le paragraphe est une structure sont contenu est interprete.

Supposons que la structure ce nomme MaStruct_. Cette interpretation donne lieu:

Les directives de commandes XCC possitionnable dans une structure sont:

Exemple
Fichier XCC

Considerons le code xcc suivant dans le fichier foo.xcc:

//@XCC_.h
struct MaStruct_ {
    //@args Memory memory, CodeRegion codeRegion
    //@ctor     TemporaryTable globalTable = CodeRegion_globalTable(codeRegion);
    //@ctor     Procedure procedure = CodeRegion_procedure(codeRegion);
    //@ctor     Temporary_ *dedicated = Procedure_dedicated(procedure);
     Memory MEMORY;
    //@ctor     *MaStruct__MEMORY(this) = memory;
    CodeRegion CODEREGION;
    //@ctor     *MaStruct__CODEREGION(this) = codeRegion;
    //@access VIRTUALFIELD MaStruct_MEMORY(this)+12
    //@decl     void MaStruct_ctor_(MaStruct this, Temporary_ *dedicated
    //@decl                     bool doIt);
    //@ctor     MaStruct_ctor_(this, dedicated, true);
    //@size     sizeof(MaStruct_)
};
Interpretation et generation

Voyons pas a pas l'interpretation et la generation:

//@XCC_.h
struct MaStruct_ {

Specifie que la definition de la structure ainsi que toutes ces contributions vont etre placees dans foo_.h.

Rencontre de la definition d'une structure, emettra les types suivants apres sa definition:

typedef struct MaStruct_ MaStruct_, *MaStruct;
typedef const struct MaStruct_ *const_MaStruct;
  //@args Memory memory, CodeRegion codeRegion

Specifie les arguments supplementatire pour le constructeur et la fonction size

    //@ctor     TemporaryTable globalTable = CodeRegion_globalTable(codeRegion);

Premier contribution au constructeur. Generation du prototype avec les arguments specifies par @args:

MaStruct
MaStruct_Ctor(MaStruct this, Memory memory, CodeRegion codeRegion) {
    // Ajout de la contribution
    TemporaryTable globalTable = CodeRegion_globalTable(codeRegion);

---------

    //@ctor     Procedure procedure = CodeRegion_procedure(codeRegion);
    //@ctor     Temporary_ *dedicated = Procedure_dedicated(procedure);

Nouvelles contributions au contructeur

    Procedure procedure = CodeRegion_procedure(codeRegion);
    Temporary_ *dedicated = Procedure_dedicated(procedure);

---------

    Memory MEMORY;

Rencontre d'un champ:

Emission du champ dans la structure emettra les macros suivantes apres la definition de la structure

#define MaStruct_MEMORY(this) ((this)->MEMORY)
#define MaStruct__MEMORY(this) (&(this)->MEMORY)

---------

    //@ctor     *MaStruct__MEMORY(this) = memory;

Nouvelle contribution au constructeur:

    *MaStruct__MEMORY(this) = memory;

---------

    CodeRegion CODEREGION;

Rencontre d'un champ:

#define MaStruct_CODEREGION(this) ((this)->CODEREGION)
#define MaStruct__CODEREGION(this) (&(this)->CODEREGION)

---------

    //@ctor     *MaStruct__CODEREGION(this) = codeRegion;

Nouvelle contribution au constructeur:

    *MaStruct__CODEREGION(this) = codeRegion;

---------

    //@access VIRTUALFIELD MaStruct_MEMORY(this)+12

Definition d'un accesseur sur un champ virtuel VIRTUALFIELD:

#define MaStruct_VIRTUALFIELD(this) MaStruct_MEMORY(this)+12

---------

    //@decl     void MaStruct_ctor_(MaStruct this, Temporary_ *dedicated
    //@decl                     bool doIt);

Contribution aux declarations. Le debut d'une forward declaration d'une fonction. La contribution sera emis avant les fonctions constructeur, destructeur, copy, etc.

void MaStruct_ctor_(MaStruct this, Temporary_ *dedicated
                    bool doIt);

---------

    //@ctor     MaStruct_ctor_(this, dedicated, true);

Nouvelle contribution au constructeur:

MaStruct_ctor_(this, dedicated, true);

---------

    //@size     sizeof(MaStruct_)

Contribution pour la fonction se calcul de taille de la structure. Generation du prototype avec les arguments specifies par @args:

size_t
MaStruct_Size(Memory memory, CodeRegion codeRegion) {
    return
    // Ajout de la contribution
    sizeof(MaStruct_)
   ;

---------

};

Fin de la structure.

Emission de la definition, suivi des macros, suivi des declarations, suivi des fonctions generees (constructeur, destructeur, ...).

---------

7. Resultat final

Voici le resultat final dans le foo_.h, commentaire mis a part.

struct MaStruct_ {
    Memory MEMORY;
    CodeRegion CODEREGION;
};
typedef struct MaStruct_ MaStruct_, *MaStruct;
typedef const struct MaStruct_ *const_MaStruct;
#define MaStruct_MEMORY(this) ((this)->MEMORY)
#define MaStruct__MEMORY(this) (&(this)->MEMORY)
#define MaStruct_CODEREGION(this) ((this)->CODEREGION)
#define MaStruct__CODEREGION(this) (&(this)->CODEREGION)
#define MaStruct_VIRTUALFIELD(this) MaStruct_MEMORY(this)+12
void MaStruct_ctor_(MaStruct this, Temporary_ *dedicated
                    bool doIt);
MaStruct
MaStruct_Ctor(MaStruct this, Memory memory, CodeRegion codeRegion) {
    TemporaryTable globalTable = CodeRegion_globalTable(codeRegion);
    Procedure procedure = CodeRegion_procedure(codeRegion);
    Temporary_ *dedicated = Procedure_dedicated(procedure);
    *MaStruct__MEMORY(this) = memory;
    *MaStruct__CODEREGION(this) = codeRegion;
    MaStruct_ctor_(this, dedicated, true);
    return this;
}
size_t
MaStruct_Size(Memory memory, CodeRegion codeRegion) {
    return
    sizeof(MaStruct_)
   ;
}