2016-11-16 10 views
2

私はどのようにrun the gcc preprocessorを知っています。 GCCは明らかにコードの静的解析/最適化を実行します。 2つの定数を追加するか、定数をシフトすると、 "a = constant < <"のままにするか、その操作を手動で実行してコードに "a = shifted_constant"を設定しても、結果のアセンブリコードは同じになります。 SHA256コードからこのスライスを考えるとGCCプリプロセッサPLUS静的解析?

A=0x6a09e667; 
    B=0xbb67ae85; 
    C=0x3c6ef372; 
    D=0xa54ff53a; 
    E=0x510e527f; 
    F=0x9b05688c; 
    G=0x1f83d9ab; 
    H=0x5be0cd19; 

    P(A, B, C, D, E, F, G, H, W[ 0], 0x428a2f98); 

のgcc -Eを実行した後、私はマクロのネストされたマクロであるP-ラインについて

{ tmp = ((((E) >> (6)) | ((E) << (32-(6))))^(((E) >> (11)) 
     | ((E) << (32-(11))))^(((E) >> (25)) | ((E) << (32-(25))))) 
     + (G^(E & (F^G))) + 0x428a2f98 + W[ 0]; D += (tmp + H); 
    H += tmp + ((((A) >> (2)) | ((A) << (32-(2))))^(((A) >> (13)) 
     | ((A) << (32-(13))))^(((A) >> (22)) | ((A) << (32-(22))))) 
     + ((A & B) | (C & (A | B))); }; 

を取得します。だから、

うれしいですが、私は、定数が交換されているより多くの消化の結果を、持っていると思い、一定の算術演算が実行されているなど 私が代わりにこのような上記の何かを得た場合:

{ tmp = hex_constant1 + W[0]; D += (tmp + 0x5be0cd19); H += tmp + hex_constant2; }; 

それは私の好みよりはるかに重要です。表現を手動で計算するのは辛抱強くはありませんでしたが、基本的には2つの16進定数に変換する必要があります。

これを実行するためのツール/コマンドラインオプションはありますか?

+2

プリプロセッサとコンパイラを混在させていませんか?プリプロセッサは、 'defined'(そして' includes'や他のマクロ)を置き換えるだけで、何らかの最適化を実行しません。それがコンパイラの仕事です。 – UnholySheep

答えて

2

ほとんどのコンパイラは、プログラムソースのテキスト文字列を取得するためにプリプロセッサを実行し、それをコンパイラの内部データ構造に解析します。プログラムが解析されると、コンパイラがコードに対して何をするのかを見ることができません(コンパイラに何らかのデバッグダンプがあるかもしれませんが、それを信じることはできません)。

拡張マクロの場所にあるコードのpartial evaluationを実行する必要があります。標準コンパイラはこれを行うのに役立ちません。

program transformation system (PTS)は、ソースコードを解析してコード変換を適用し、変更されたソーステキストを再生成するツールです。良いPTSはあなたが適用されるソース - ソース変換ルールのセットの形で各ルールを記述できるようになる:

rule simplify_times_zero(e: power): product -> product 
     " \e * 0 " -> " \e "; 

when you see *this*, then replace it by *that* if *condition* is true 

簡単な定数の畳み込みを行うには、次のようなルールが必要

特別な(代数)の場合に何らかのゼロを掛ける場合を処理します。 明らかに、以下のルールの束が必要です。

あなたのPTSは、使用しているCまたはC++の特定の方言を読み取ることができ、識別子をその定義に解決できなければなりません(そうでなければ、Eはそれが使用された場所で一定であることを知ることができません)。

私が知っている唯一のPTSはparse many C or C++ dialectsであり、マクロ展開を実行できるのはDMS Software Reengineering Toolkitです。上記の例の構文を使用してルールを受け入れます。 int32_multiplyは数学を行う機能である

rule fold_addition(c1: INT32CONSTANT, c2: INT32CONSTANT): product -> product = 
    " \c1 + \c2 " -> int32_multiply(c1,c2); 

あなたが必要とする追加のルールは、実際に計算を行うルールです。 CおよびC++言語の規則を尊重する各演算子およびオペランドの型ごとにこれらのいずれかが必要です。

はまた、既知の値の代入を行うルールが必要になります。

rule substitute_defined_constant(i: IDENTIFIER): primitive -> primitive 
    " \i " -> macro_definition_value(i) if is_defined_constant(i); 
is_defined_constantを検索し、DMSのフロントマクロ定義の終了、およびチェックによって構築されたシンボルテーブル内の識別子は、私は、フォームのマクロである

iが参照されている点で「define i」を返します。これを条件として記述すると、マクロ定義値が実際に存在しない限り、macro_definition_value関数は呼び出されません。生のシンボルテーブルのサポートは、DMSのCおよびC++フロントエンドによって提供されます。

この一連のルールと、これらのルールをマクロ展開ポイントに適用するルールストラテジを使用すると、DMSは式を表現したフォームに「折りたたむ」ことができます。さて、すべての変換はプログラムのDMSの内部表現で行われますが、DMSは実際にこれを見ることができるように結果をあらかじめ確認することができます。

開発UIの一般的な機能として、これはかなり便利かもしれません。実際にこれをすべて設定して実際に動作させるには、おそらく数日かかります。 DMSは複雑なシステムであり、CとC++は役に立ちません。

これを1回または2回だけ実行するのであれば、弾丸を噛んで手動で行うほうが良いでしょう(または、別の答えが示しているように、デバッガを使ってコンパイラの出力を検査しますでる)。毎日の作業であれば、PTSソリューションはリアルタイム(および精度)の節約になる可能性があります。

2

GCCは前処理されたCコードを最適化しません。前処理の後、このコードは、ほとんどの最適化が適用されている高レベルのIR(GIMPLE)に変換された後、RTLのような低レベルのIRに低下します。

最適化されたGIMPLEダンプは、これらを定数に照らして検索します。あなたは、このように最適化されたツリーのダンプを使用しなければならない。(番号211が異なる場合がありますし、gccのバージョンによって異なります)test.c.211t.optimizedよう

gcc -O2 -fdump-tree-optimized test.c -S 

は、次にファイルを探します。ジングルコードはプリミティブCと非常によく似ているので、定数を読むのに問題はありません。

関連する問題