Paramètres d’exécution dans gcc (inverse va_args / varargs)

J’essaie d’apporter quelques améliorations à un interpréteur de microcontrôleurs sur lequel je travaille. Pour exécuter les fonctions intégrées, j’ai actuellement quelque chose comme ceci (bien qu’un peu plus rapide):

function executeBuiltin(functionName, functionArgs) { if (functionName=="foo") foo(getIntFromArg(functionArgs[0])); if (functionName=="bar") bar(getIntFromArg(functionArgs[0]),getBoolFromArg(functionArgs[1]),getFloatFromArg(functionArgs[2])); if (functionName=="baz") baz(); ... } 

Mais il s’agit d’un dispositif embarqué (ARM) avec des ressources très limitées, et j’ai besoin de réduire considérablement la taille du code. Ce que j’aimerais faire, c’est avoir une fonction polyvalente pour appeler d’autres fonctions avec des arguments différents – quelque chose comme ceci:

 function executeBuiltin(functionName, functionArgs) { functionData = fast_lookup(functionName); call_with_args(functionData.functionPointer, functionData.functionArgumentTypes, functionArgs); } 

Je veux donc pouvoir appeler une fonction C standard et lui transmettre tous les arguments nécessaires (qui peuvent tous être de types différents). Pour cela, j’ai besoin d’une fonction call_with_args .

Je veux éviter de réécrire chaque fonction pour prendre argc + argv. Idéalement, chaque fonction appelée serait une fonction C entièrement standard.

Il y a une discussion à ce sujet ici – mais est-ce que quelque chose a changé depuis 1993, quand cet article a été écrit? Surtout que je suis sous ARM où les arguments sont dans les registres plutôt que sur la stack. Même si ce n’est pas dans la norme C, y a-t-il quelque chose de spécifique à GCC qui peut être fait?


UPDATE: Malgré le comportement indéfini selon la spécification, il semble qu’en raison de la façon dont les appels C fonctionnent, il est possible de transmettre plus d’arguments à une fonction que prévu et tout ira bien, ainsi vous pourrez tout décompresser les arguments dans un tableau de uint32s et peut ensuite simplement transmettre chaque uint32 à la fonction.

Cela facilite beaucoup l’écriture de code «agréable» pour les appels, et cela semble plutôt bien fonctionner (sur les plates-formes 32 bits). Le seul problème semble être le passage de nombres 64 bits et la compilation pour 64 bits x86 car cela semble faire quelque chose de particulièrement étrange dans ce cas.

    Serait-il possible de le faire lors de la compilation avec des macros? Quelque chose du genre: https://www.redhat.com/archives/libvir-list/2014-March/msg00730.html

    Si l’exécution était requirejse, __buildin_apply_args () pourrait peut-être être utilisé.

    de ce document , section 5.5, Passage de parameters , il semble que les parameters soient passés à la fois dans les registres et dans la stack, comme avec la plupart des plates-formes actuelles.

    Avec “C non standard”, je pense emballer les parameters et appeler la fonction en suivant la documentation avec un peu d’ asm() . Cependant, vous avez quand même besoin d’une information minimale sur la signature de la fonction appelée (combien de bits pour chaque argument à passer).

    De ce sharepoint vue, je préférerais préparer un tableau de noms de fonctions, un tableau de pointeurs de fonctions et un tableau de signatures de fonctions énumérées (dans le nombre de bits de chaque argument … vous n’avez pas besoin de différencier void * de char * par exemple) et un commutateur / cas sur les signatures, et un commutateur / cas sur le dernier. J’ai donc rapporté deux réponses ici.

    Vous pouvez effectuer une sérialisation très simple pour transmettre des arguments arbitraires. Créez un tableau et des octets memcpy sizeof (arg) pour chaque argument passé.

    Ou vous pouvez créer des structures pour les arguments de fonction.

    Chaque fonction prend un caractère * ou un vide *. Ensuite, vous transmettez un pointeur à une structure avec les parameters de fonction ou définissez un ensemble de macros ou de fonctions permettant de coder et de décoder les données arbitraires d’un tableau, puis de passer le pointeur à ce tableau.