diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2018-04-02 11:58:42 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2018-04-02 12:39:30 (GMT) |
commit | 1db4ef323b7a76093356ae76268132f3760e1631 (patch) | |
tree | fec36ee0ec1b6b2010b62ca4177edca0e31e2114 /tools/d2c/conv | |
parent | 1bc80837dde03a32b5ab185067f7bd4c499a9850 (diff) |
Rewritten the whole instruction definition format.
Diffstat (limited to 'tools/d2c/conv')
-rw-r--r-- | tools/d2c/conv/Makefile.am | 3 | ||||
-rw-r--r-- | tools/d2c/conv/manager.c | 420 | ||||
-rw-r--r-- | tools/d2c/conv/manager.h | 19 | ||||
-rw-r--r-- | tools/d2c/conv/tokens.l | 7 |
4 files changed, 231 insertions, 218 deletions
diff --git a/tools/d2c/conv/Makefile.am b/tools/d2c/conv/Makefile.am index d2d495b..a22d5f7 100644 --- a/tools/d2c/conv/Makefile.am +++ b/tools/d2c/conv/Makefile.am @@ -26,6 +26,9 @@ libd2cconv_la_SOURCES = \ tokens.l \ grammar.y +# _GNU_SOURCE : asprintf +libd2cconv_la_CFLAGS = -D_GNU_SOURCE + # Automake fait les choses à moitié CLEANFILES = grammar.h grammar.c grammar.output tokens.c tokens.h diff --git a/tools/d2c/conv/manager.c b/tools/d2c/conv/manager.c index 555ea38..33518db 100644 --- a/tools/d2c/conv/manager.c +++ b/tools/d2c/conv/manager.c @@ -29,6 +29,7 @@ #include <malloc.h> #include <stdbool.h> #include <string.h> +#include <unistd.h> #include "../helpers.h" @@ -42,11 +43,6 @@ /* Fonction de conversion */ struct _conv_func { - bool used; /* Conversion utilisée ? */ - bool intermediate; /* Variable intermédiaire ? */ - bool declared; /* Expression déjà déclarée ? */ - bool defined; /* Expression déjà définie ? */ - char *dest; /* Variable de destination */ bool is_expr; /* Choix du contenu réel */ @@ -64,9 +60,18 @@ struct _conv_func }; + bool used_as_inter; /* Variable intermédiaire ? */ + bool used_as_op; /* Opérande finale d'instruct° */ + bool declared; /* Expression déjà déclarée ? */ + bool defined; /* Expression déjà définie ? */ + }; +/* Indique si l'utilisation en intermédiaire est brute ou non. */ +static bool is_conv_func_raw_as_inter(const conv_func *); + + /* ---------------------------- ENSEMBLES DE CONVERSIONS ---------------------------- */ @@ -196,25 +201,6 @@ const char *get_conv_dest_name(const conv_func *func) /****************************************************************************** * * * Paramètres : func = fonction de conversion à consulter. * -* * -* Description : Indique la nature d'une conversion : fonction ou expression ?* -* * -* Retour : Indication sur la constitution interne de la conversion. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool is_conv_func_expression(const conv_func *func) -{ - return func->is_expr; - -} - - -/****************************************************************************** -* * -* Paramètres : func = fonction de conversion à consulter. * * bits = gestionnaire des bits d'encodage. * * list = liste de l'ensemble des fonctions de conversion. * * size = taille déterminée avec précision. [OUT] * @@ -260,8 +246,13 @@ bool mark_conv_func(conv_func *func, bool inter, const coding_bits *bits, const { bool result; /* Bilan à remonter */ - func->used = true; - func->intermediate |= inter; + if (inter) + func->used_as_inter = true; + else + { + assert(!func->is_expr); + func->used_as_op = true; + } if (func->is_expr) result = ensure_arg_expr_content_fully_marked(func->expr, bits, list); @@ -275,69 +266,160 @@ bool mark_conv_func(conv_func *func, bool inter, const coding_bits *bits, const /****************************************************************************** * * -* Paramètres : func = fonction de conversion à manipuler. * -* fd = descripteur d'un flux ouvert en écriture. * -* bits = gestionnaire des bits d'encodage. * -* list = liste de l'ensemble des fonctions de conversion. * -* pp = pré-processeur pour les échanges de chaînes. * -* wide = taille des mots décodés. * +* Paramètres : func = fonction de conversion à consulter. * * * -* Description : Déclare les variables associées à une fonction de conversion.* +* Description : Indique si l'utilisation en intermédiaire est brute ou non. * * * -* Retour : Bilan de l'opération. * +* Retour : true si une variable brute est à manipuler, false sinon. * * * * Remarques : - * * * ******************************************************************************/ -bool declare_conv_func(conv_func *func, int fd, const coding_bits *bits, const conv_list *list, const pre_processor *pp, unsigned int wide) +static bool is_conv_func_raw_as_inter(const conv_func *func) { - bool result; /* Bilan à remonter */ + bool result; /* Résultat à faire remonter */ - printf(" -> declaration for '%s': declared ? %d - expr ? %d\n", - func->dest, func->declared, func->is_expr); + if (func->is_expr) + result = true; + else + result = (strcmp(func->name, "UInt") == 0); - assert(func->used); + return result; - /* Si la fonction a déjà été définie lors d'un précédent besoin... */ - if (func->declared) return true; +} - if (func->is_expr) - result = ensure_arg_expr_content_fully_declared(func->expr, fd, bits, list, pp, wide); - else - result = ensure_arg_list_content_fully_declared(func->args, fd, bits, list, pp, wide); - if (result && func->intermediate) - { - if (!func->is_expr && is_operand_producer(pp, func->name)) - dprintf(fd, "\t\tGArchOperand *val_%s;\n", func->dest); - else - dprintf(fd, "\t\tuint%u_t val_%s;\n", wide, func->dest); - } - func->declared = result; +/****************************************************************************** +* * +* Paramètres : func = fonction de conversion à manipuler. * +* fd = descripteur d'un flux ouvert en écriture. * +* inter = note un résultat de conversion comme intermédiaire. * +* * +* Description : Imprime la désignation de la destination d'une conversion. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ - return result; +void write_conv_func(conv_func *func, int fd, bool inter) +{ + bool as_raw; /* Choix logique du format */ + + if (inter) + as_raw = is_conv_func_raw_as_inter(func); + else + as_raw = false; + + if (as_raw) + dprintf(fd, "val_%s", func->dest); + else + dprintf(fd, "op_%s", func->dest); } /****************************************************************************** * * -* Paramètres : func = fonction de conversion à consulter. * +* Paramètres : func = fonction de conversion à manipuler. * +* fd = descripteur d'un flux ouvert en écriture. * +* bits = gestionnaire des bits d'encodage. * +* list = liste de l'ensemble des fonctions de conversion. * +* tab = décalage éventuel selon l'inclusion. * * * -* Description : Indique si une conversion a déjà été définie. * +* Description : Déclare les variables associées à une fonction de conversion.* * * -* Retour : Etat de la définition. * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -bool is_conv_func_already_defined(const conv_func *func) +bool declare_conv_func(conv_func *func, int fd, const coding_bits *bits, const conv_list *list, const char *tab) { - return func->defined; + bool result; /* Bilan à remonter */ + bool as_raw; /* Choix logique du format */ + unsigned int wide; /* Taille des mots */ + off_t start; /* Point de départ dans le code*/ + off_t end; /* Point d'arrivée dans le code*/ + + assert(func->used_as_inter || func->used_as_op); + + /** + * Si la fonction a déjà été définie lors d'un précédent besoin... + */ + if (func->declared) return true; + + if (func->is_expr) + result = ensure_arg_expr_content_fully_declared(func->expr, fd, bits, list, tab); + + else + result = ensure_arg_list_content_fully_declared(func->args, fd, bits, list, tab); + + if (result) + { + if (func->used_as_inter) + { + as_raw = is_conv_func_raw_as_inter(func); + + /** + * Si la variable intermédiaire n'est pas brute, deux cas de figure + * sont possibles : + * + * - la variable est un objet purement intermédiaire. + * - la variable est un object qui sera également utilisé en opérande. + * + * Dans les deux cas, on laisse la déclaration en tant qu'opérande + * rédiger la déclaration car il s'agit de déclarations identiques. + */ + + if (as_raw) + { + wide = count_coded_bits(bits); + + start = lseek(fd, 0, SEEK_CUR); + + dprintf(fd, "\t%suint%u_t ", tab, wide); + + write_conv_func(func, fd, true); + + dprintf(fd, ";"); + + end = lseek(fd, 0, SEEK_CUR); + + dprintf(fd, "%*s", (tab[0] == '\0' ? 42 : 39) - (int)(end - start), "/"); + dprintf(fd, "* Champ brut à décoder */\n"); + + } + + } + + if (func->used_as_op || (func->used_as_inter && !as_raw)) + { + start = lseek(fd, 0, SEEK_CUR); + + dprintf(fd, "\t%sGArchOperand *", tab); + + write_conv_func(func, fd, false); + + dprintf(fd, ";"); + + end = lseek(fd, 0, SEEK_CUR); + + dprintf(fd, "%*s", (tab[0] == '\0' ? 42 : 39) - (int)(end - start), "/"); + dprintf(fd, "* Opérande à intégrer */\n"); + + } + + } + + func->declared = result; + + return result; } @@ -345,13 +427,11 @@ bool is_conv_func_already_defined(const conv_func *func) /****************************************************************************** * * * Paramètres : func = fonction de conversion à manipuler. * -* last = précise si la conversion est la dernière. * -* internal = indique le type de manipulation finale. * * fd = descripteur d'un flux ouvert en écriture. * -* arch = architecture visée par l'opération globale. * * bits = gestionnaire des bits d'encodage. * * list = liste de l'ensemble des fonctions de conversion. * -* pp = pré-processeur pour les échanges de chaînes. * +* tab = décalage éventuel selon l'inclusion. * +* optional = indique si l'opérande finale est optionnelle. * * exit = exprime le besoin d'une voie de sortie. [OUT] * * * * Description : Définit les variables associées à une fonction de conversion.* @@ -362,89 +442,109 @@ bool is_conv_func_already_defined(const conv_func *func) * * ******************************************************************************/ -bool define_conv_func(conv_func *func, bool last, bool internal, int fd, const char *arch, const coding_bits *bits, const conv_list *list, const pre_processor *pp, bool *exit) +bool define_conv_func(conv_func *func, int fd, const coding_bits *bits, const conv_list *list, const char *tab, bool optional, bool *exit) { bool result; /* Bilan à remonter */ - const char *callable; /* Fonction à appeler */ + bool as_raw; /* Choix logique du format */ - /* Si la fonction a déjà été définie lors d'un précédent besoin... */ - if (func->defined) return true; + /** + * Si la fonction a déjà été définie lors d'un précédent besoin... + */ + if (func->defined) + { + // TODO : faire un object_ref() si c'est un objet + //assert(0); + + return true; + + } if (func->is_expr) - result = ensure_arg_expr_content_fully_defined(func->expr, fd, arch, bits, list, pp, exit); + result = ensure_arg_expr_content_fully_defined(func->expr, fd, bits, list, tab, exit); else - result = ensure_arg_list_content_fully_defined(func->args, fd, arch, bits, list, pp, exit); - - /* Nom de la fonction effectivement appelée */ + result = ensure_arg_list_content_fully_defined(func->args, fd, bits, list, tab, exit); - if (!func->is_expr) + if (result) { - callable = find_macro(pp, func->name); + if (func->used_as_inter) + { + as_raw = is_conv_func_raw_as_inter(func); - if (callable == NULL) - callable = func->name; + /** + * Se référer au besoin aux commentaires de declare_conv_func(). + */ - } - else callable = NULL; + if (as_raw) + { + dprintf(fd, "\t%s", tab); - if (last && callable == NULL) - { - fprintf(stderr, "Error: expected function to store '%s'.\n", func->dest); - return false; - } + write_conv_func(func, fd, true); - /* Dernier niveau : la variable de destination est imposée ! */ - if (last) - { - /* Si l'on doit manipuler une propriété d'instructon... */ - if (internal) - result = checked_call_instr_func(false, callable, func->args, fd, bits, list, pp); + dprintf(fd, " = "); - /* Si on doit constituer un opérande à ajouter... */ - else - { - if (strchr(callable, '(') == NULL) - dprintf(fd, "\t\top = %s(", callable); - else - dprintf(fd, "\t\top = %s", callable); + if (func->is_expr) + result = define_arg_expr(func->expr, fd, bits, list); - result &= define_arg_list(func->args, fd, bits, list); + else + { + assert(strcmp(func->name, "UInt") == 0); + assert(get_arg_list_size(func->args) == 1); - dprintf(fd, ");\n"); + result = define_arg_list(func->args, fd, bits, list); - } + } - } + dprintf(fd, ";\n"); + dprintf(fd, "\n"); - /* On constitue une variable intermédiaire, dont on peut conserver le nom ! */ - else - { - dprintf(fd, "\t\tval_%s = ", func->dest); + } - if (func->is_expr) - result &= define_arg_expr(func->expr, fd, bits, list); + } - else + if (func->used_as_op || (func->used_as_inter && !as_raw)) { - dprintf(fd, "%s(", callable); + dprintf(fd, "\t%s", tab); + + write_conv_func(func, fd, false); + + dprintf(fd, " = %s(", func->name); result = define_arg_list(func->args, fd, bits, list); - dprintf(fd, ")"); + dprintf(fd, ");\n"); - } + if (optional) + { + if (as_raw) + { + fprintf(stderr, "%s can not be optional and used as intermediate value as the same time!\n", + func->dest); - dprintf(fd, ";\n"); + result = false; + + } + + } + + else + { + dprintf(fd, "\t%sif (", tab); + + write_conv_func(func, fd, false); + + dprintf(fd, " == NULL) goto bad_exit;\n"); + + *exit = true; + + } + + dprintf(fd, "\n"); - if (!func->is_expr && is_operand_producer(pp, func->name)) - { - dprintf(fd, "\t\tif (val_%s == NULL) goto bad_exit;\n", func->dest); - *exit = true; } - } + func->defined = result; - func->defined = result; + } return result; @@ -562,91 +662,3 @@ conv_func *find_named_conv_in_list(const conv_list *list, const char *name) return result; } - - -/****************************************************************************** -* * -* Paramètres : list = liste de fonctions de conversion à consulter. * -* fd = descripteur d'un flux ouvert en écriture. * -* bits = gestionnaire des bits d'encodage. * -* pp = pré-processeur pour les échanges de chaînes. * -* wide = taille des mots décodés. * -* * -* Description : Déclare l'ensemble des variables intermédiaires. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool declare_used_intermediate_conversions(const conv_list *list, int fd, const coding_bits *bits, const pre_processor *pp, unsigned int wide) -{ - bool result; /* Bilan à remonter */ - size_t i; /* Boucle de parcours */ - conv_func *func; /* Conversion à traiter */ - - result = true; - - for (i = 0; i < list->func_count && result; i++) - { - func = list->functions[i]; - - if (func->used && func->intermediate) - result = declare_conv_func(func, fd, bits, list, pp, wide); - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : list = liste de fonctions de conversion à consulter. * -* fd = descripteur d'un flux ouvert en écriture. * -* arch = architecture visée par l'opération globale. * -* bits = gestionnaire des bits d'encodage. * -* pp = pré-processeur pour les échanges de chaînes. * -* exit = exprime le besoin d'une voie de sortie. [OUT] * -* * -* Description : Définit l'ensemble des variables intermédiaires. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool define_used_intermediate_conversions(const conv_list *list, int fd, const char *arch, const coding_bits *bits, const pre_processor *pp, bool *exit) -{ - bool result; /* Bilan à remonter */ - bool got_one; /* Suit le nombre d'impressions*/ - size_t i; /* Boucle de parcours */ - conv_func *func; /* Conversion à traiter */ - - result = true; - - got_one = false; - - for (i = 0; i < list->func_count && result; i++) - { - func = list->functions[i]; - - if (func->used && func->intermediate) - { - result = define_conv_func(func, false, false, fd, arch, bits, list, pp, exit); - - got_one = true; - - } - - } - - if (got_one) - dprintf(fd, "\n"); - - return result; - -} diff --git a/tools/d2c/conv/manager.h b/tools/d2c/conv/manager.h index db6e325..035635c 100644 --- a/tools/d2c/conv/manager.h +++ b/tools/d2c/conv/manager.h @@ -53,23 +53,20 @@ void delete_conv_func(conv_func *); /* Indique la variable de destination d'une conversion. */ const char *get_conv_dest_name(const conv_func *); -/* Indique la nature d'une conversion : fonction ou expression ? */ -bool is_conv_func_expression(const conv_func *); - /* Détermine la taille en bits du résultat d'une fonction. */ bool compute_conv_func_size(const conv_func *, const coding_bits *, const conv_list *, unsigned int *); /* Marque les champs utilisés par une fonction de conversion. */ bool mark_conv_func(conv_func *, bool, const coding_bits *, const conv_list *); -/* Déclare les variables associées à une fonction de conversion. */ -bool declare_conv_func(conv_func *, int, const coding_bits *, const conv_list *, const pre_processor *, unsigned int); +/* Imprime la désignation de la destination d'une conversion. */ +void write_conv_func(conv_func *, int, bool); -/* Indique si une conversion a déjà été définie. */ -bool is_conv_func_already_defined(const conv_func *); +/* Déclare les variables associées à une fonction de conversion. */ +bool declare_conv_func(conv_func *, int, const coding_bits *, const conv_list *, const char *); /* Définit les variables associées à une fonction de conversion. */ -bool define_conv_func(conv_func *, bool, bool, int, const char *, const coding_bits *, const conv_list *, const pre_processor *, bool *); +bool define_conv_func(conv_func *, int, const coding_bits *, const conv_list *, const char *, bool, bool *); @@ -92,12 +89,6 @@ void register_conversion(conv_list *, conv_func *); /* Recherche un résultat précis dans une liste de fonctions. */ conv_func *find_named_conv_in_list(const conv_list *, const char *); -/* Déclare l'ensemble des variables intermédiaires. */ -bool declare_used_intermediate_conversions(const conv_list *, int, const coding_bits *, const pre_processor *, unsigned int); - -/* Définit l'ensemble des variables intermédiaires. */ -bool define_used_intermediate_conversions(const conv_list *, int, const char *, const coding_bits *, const pre_processor *, bool *); - #endif /* _TOOLS_D2C_CONV_MANAGER_H */ diff --git a/tools/d2c/conv/tokens.l b/tools/d2c/conv/tokens.l index ef6b958..f1d196d 100644 --- a/tools/d2c/conv/tokens.l +++ b/tools/d2c/conv/tokens.l @@ -28,5 +28,12 @@ <raw_line>[^\n]+ { yylvalp->cstring = yytext; return RAW_LINE; } <raw_line>"\n" { yy_pop_state(); } +. { + char *msg; + asprintf(&msg, "Unhandled token in d2c conv block: '%s'", yytext); + YY_FATAL_ERROR(msg); + free(msg); + } + %% |