2017-02-27 3 views
1

J'ai un module D qui, je l'espère, contient des parties publiques et privées. J'ai essayé d'utiliser les mots-clés privé et statique avant les définitions de fonction. J'ai une fonction que je souhaite rendre externe - appelable/publique et idéalement je voudrais qu'elle soit intégrée au site d'appel. Cette fonction appelle d'autres fonctions internes au module qui sont destinées à être privées, c'est-à-dire qui ne peuvent pas être appelées de l'extérieur. Les appels vers ceux-ci sont insérés avec succès dans le module et une grande partie de la graisse est éliminée par CTFE plus propagation à constante connue. Cependant, le compilateur GDC génère également des copies de ces routines internes, même si elles ont été intégrées au besoin et qu'elles ne sont pas supposées être appelables de l'extérieur. Je compile avec -O3 -frelease. Que devrais-je faire - devrais-je m'attendre à cela même si j'utilise de l'électricité statique et/ou privée?D/DLang: Inhibition de la génération de code des fonctions inline privées du module

J'ai également jeté un bref coup d'oeil à ce thread concerning GCC en espérant un aperçu.

Comme je l'ai mentionné plus tôt, j'ai essayé à la fois en utilisant privé et statique sur ces fonctions internes, mais je ne peux pas sembler supprimer la génération de code. Je pourrais comprendre cela si un débogueur avait besoin de copies de ces routines pour définir des points d'arrêt. Je dois souligner que cela pourrait peut-être être réglé d'une manière ou d'une autre au moment de la liaison, pour autant que je sache. Je n'ai pas essayé de lier le programme, je regarde juste le code généré dans le Matt Godbolt D Compiler Explorer en utilisant GDC. Tout peut être transformé en modèles avec une liste de paramètres de modèle de longueur nulle (par exemple, auto my_fn() (dans arg_t x)), essayé, cela ne sert à rien mais ne nuit pas.

Un couple d'autres choses à essayer: Je pourrais essayer de faire une classe statique avec des parties intimes, comme un moyen de mettre en œuvre un paquet, style Ada. (Doit être strictement instance unique.) Je n'ai jamais fait de C++, seulement des quantités massives d'ASM et C professionnellement. Donc, ce serait une courbe d'apprentissage. La seule autre chose que je peux penser est d'utiliser des définitions de fonctions imbriquées, Pascal/Ada-style, déplacer les routines internes à l'intérieur du corps de leurs appelants. Mais cela a beaucoup d'inconvénients.

exemple rugueux

module junk; 

auto my_public_fn() { return my_private_fn(); } 

private 
static // 'static' and/or 'private', tried both 
auto my_private_fn() { xxx ; return whatever; } 
+0

Je n'ai pas pu comparer LDC avec GDC car actuellement les routines contiennent un code asm étendu spécifique à GCC. J'ai remarqué que les corps de fonctions indésirables ne sont pas seulement ceux qui contiennent asm btw. –

+1

vous n'avez certainement pas besoin de 'static'. cela n'a aucun sens pour les déclarations de haut niveau. – Cauterite

+1

"Je n'ai pas essayé de lier le programme" - alors que je ne connais pas grand-chose à GDC, il est possible que l'élimination de code mort/repliement COMDAT se produise au moment de la liaison pour faire disparaître ces fonctions. Peut-être que GDC ne prend pas la peine d'essayer DCE à ce niveau parce que l'éditeur de liens est censé en prendre soin de toute façon. Je suis juste en train de spéculer ... – Cauterite

Répondre

2

Je viens d'avoir une brève discussion avec Iain à ce sujet et la mise en œuvre ne soit pas aussi simple qu'il n'y paraît.

d'abord static a beaucoup de significations dans D, mais le sens C de unité de traduction fonction locale n'est pas un d'entre eux ;-)

marquage Ainsi, ces fonctions private semble intuitive. Après tout, si vous ne pouvez pas accéder à une fonction depuis l'extérieur de l'unité de traduction et que vous ne laissez jamais une adresse à la fonction, pourquoi ne pas la supprimer? Il pourrait être complètement inutilisé ou inline dans tous les appelants dans ce cas.

Maintenant, voici le hic: Nous ne pouvons pas savoir avec certitude si une fonction est utilisé:

private void fooPrivate() {} 

/*template*/ void fooPublic()() 
{ 
    fooPrivate(); 
} 

Lors de la compilation du fichier GDC ne sait rien sur le modèle fooPublic (en tant que modèles ne peuvent être entièrement analysés lorsque instancié), donc fooPrivate semble être inutilisé. Lorsque plus tard, en utilisant fooPublic dans un fichier différent, GDC comptera sur fooPrivate étant déjà émis dans la source d'origine - après tout ce n'est pas un modèle donc il n'est pas émis dans le nouveau module.

Il existe peut-être des solutions de contournement mais tout ce problème semble non trivial.Nous pourrions également introduire un attribut personnalisé gcc.attribute pour cela. Cela causerait les mêmes problèmes avec les templates, mais comme il s'agit d'une annotation spécifique pour un usecase (contrairement à private) nous pourrions compter sur l'utilisateur pour faire la bonne chose.

+0

Serait-il possible pour un éditeur de liens de faire le tri, comme implémenter des modules obj comme une bibliothèque contenant des pièces séparées? (A dû faire quelque chose comme ceci à la main une fois sur un projet énorme il y a des décennies.) Assez facile pour dire que je ne suis pas celui qui fait le travail. Pourrait être un cauchemar. Je n'ai aucune idée de ce que GCC C/C++ fait. –

+0

Je ne sais pas combien cela en vaudrait la peine. Je bêlais parce que j'écrivais des fonctions qui étaient uniquement utilisées par CTFE, ou toujours en ligne, mais le corps généré n'était tout simplement jamais utilisé, laissé assis là. –

+0

Si vous pouviez contrôler facilement le positionnement du corps de la fonction, hotness vs coldness (GCC a ceci?), L'utilisateur place tous les corps de fonctions inutilisés ensemble à l'extrémité "froide" de l'obj, ou mieux toutes ces sous-sections dans leur propre section externe à concaténer ensemble. –