2017-02-27 2 views
1

私は公的および私的な部分が含まれることを望むDモジュールを持っています。私は関数定義の前にキーワードprivateとstaticを使ってみました。私は外部呼び出し可能/公表を望む機能を持っており、理想的にはコールサイトでインライン展開したいと思っています。この関数は、プライベートであることを意図した、すなわち外部呼び出し可能でない他のモジュール内部関数を呼び出します。これらの呼び出しはモジュール内で成功裏にインライン化され、CTFEと既知の定数の伝播によって多くのクレートが処分されます。しかし、GDCコンパイラは、必要に応じてインライン展開され、外部呼び出し可能ではないと想定されていても、これらの内部ルーチンのコピーを生成します。私は-O3-freleaseでコンパイルしています。私は何をしなければなりません - 私が静的および/または私的なものを使用してもこれを期待していますか?D/DLang:モジュールプライベートのインライン関数のコード生成を禁止する

私はまた、この洞察を願ってこのthread concerning GCCを簡単に見ました。

前述のとおり、これらの内部関数でプライベートとスタティックの両方を使用しようとしましたが、コード生成を抑制できないようです。デバッガがブレークポイントを設定するためにこれらのルーチンのコピーを持つ必要があるならば、私はこれを理解することができました。私はこれがリンク時に何らかの形でソートされる可能性があることを強調する必要があります。私はプログラムをリンクしようとしませんでしたが、GDCを使ってMatt Godbolt Dコンパイラエクスプローラで生成されたコードを調べています。テンプレートパラメータの長さがゼロのリスト(例えば、my_fn()(arg_t x))のすべてをテンプレートにすることができ、それを試してみましたが、役に立たないけど害はありません。

他にもいくつか試してみましょう:アダプティブスタイルのパッケージを実装する方法として、私はプライベートパーツで静的クラスを作成してみることができます。 (厳密には単一インスタンスにする必要がある)私はC++を一度もやっていない。大量のasmとCだけを専門に扱っている。それは学習曲線になるでしょう。

私が考えることができる唯一の他のものは、ネストされた関数定義、Pascal/Ada-styleを使用して、内部ルーチンを呼び出し元の本体の内部に移動することです。しかし、これには多くの欠点があります。

ラフの例では、

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

現在、GCC固有の拡張asmコードがルーチンに含まれているため、LDCとGDCを比較できませんでした。私は、望ましくない機能体がasm btwを含むものだけではないことに気づいた。 –

+1

あなたは間違いなく '静的'を必要としません。トップレベルの宣言には意味がありません。 – Cauterite

+1

"私はプログラムをリンクしようとしませんでした" - 私はGDCについてあまり知らないうちに、リンク時にデッドコード除去/ COMDATフォールディングが発生してこれらの関数が消滅する可能性があります。おそらく、GDCはこのレベルでDCEを試しても構いません。なぜなら、リンカーはとにかくそれを世話することが期待されるからです。私はちょうどしかし推測している... – Cauterite

答えて

2

私はこのことについてイアンとの短い議論を持っていたし、これを実装することは、思ったほど簡単ではありません。

すべてstaticの第一は、Dには多くの意味を持っていますが、翻訳単位のローカル機能のCの意味はprivateが直感的に思えるように、これらの機能をマーキング;-)

そのうちの一つではありません。結局のところ、変換ユニットの外部から関数にアクセスできず、関数にアドレスを漏らしていない場合、それを削除しないのはなぜですか?このケースでは、完全に使用されていないか、すべての呼び出し元にインライン化されている可能性があります。

は今ここにキャッチです:関数が未使用であれば我々は確実に知ることはできません。

private void fooPrivate() {} 

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

ファイルをコンパイルするときにインスタンス化するときのテンプレートは唯一の完全に解析することができるようGDCはfooPublicテンプレート(について何も知りません)ので、fooPrivateは使用されていないようです。後でfooPublicを別のファイルに使用すると、GDCはfooPrivateが元のソースに既に送信されていることに依存します。すべてがテンプレートではないため、新しいモジュールに送信されません。

回避方法がありますが、この全体的な問題は軽微ではないようです。これに対してカスタムgcc.attribute属性を導入することもできます。それはテンプレートでも同じ問題を引き起こしますが、1つのユースケースの特定のアノテーション(privateとは違って)では、正しいことをするためにユーザーに頼ることができます。

+0

別の部分を含むライブラリとしてobjモジュールを実装するように、リンカがこれを整理することは可能でしょうか? (何十年も前の巨大なプロジェクトでこのようなことを一度手作業でやったことがありました)。私は仕事をしている人ではありません。悪夢になるかもしれない。私はGCC C/C++が何をしているのか分かりません。 –

+0

私は努力の価値がどれくらいあるのか分かりません。私はCTFEが単独で雇用していた機能を書いていたため、あるいは常にインライン化されているにも関わらず、生成された体は一度も使用されずにそこに座っていたからです。 –

+0

関数本体の配置、暑さと寒さ(GCCにはこれがありますか?)を簡単に制御できれば、ユーザーは使用していない関数本体をすべてobjの 'cold'の端に配置するか、一緒に連結されるように、それぞれの外部セクションに分割します。 –

関連する問題