プログラムを実行せずにconstexprを取得する

Dec 04 2020

私はライブラリ(ソースとコンパイルの両方)を持っており、ライブラリ内のあるタイプが簡単にコピー可能かどうかを知る必要があるプログラム(このライブラリにリンクされていない)を書いています。

プログラムに次のようにfile.cppに書き込むことができます。

#include "mylibrary.hpp"
int main()
{
    std::cout << std::is_trivially_copyable<A>::value << '\n';
    std::cout << std::is_trivially_copyable<B>::value << '\n';
    std::cout << std::is_trivially_copyable<C>::value << '\n';
    std::cout << std::is_trivially_copyable<D>::value << '\n';
}

次に、このコードをコンパイルして実行し、出力を解析します。この情報を取得するためのより良い方法はありますか?(パフォーマンスは重要です)。libclangはそれを行うことができますか?

コメントのために更新:

XY問題について:私がやろうとしているのは、C ++ヘッダーファイルのパスを引数として取得し、そのヘッダーファイルのrust-c ++バインディングを生成するプログラム(rust-bindgenと呼ばれる)をrustで作成することです。タイプが簡単にコピー可能/再配置可能かどうかに応じて、バインディングを異なる方法で生成する必要があります。

したがって、C ++ヘッダーファイルへのパスがあり、そのヘッダーファイルで定義されている特定のタイプが簡単にコピーできるかどうかを知る必要があります。上記のアプローチは機能しますが、file.cppのコンパイルが含まれるため、時間がかかります。

TLDR:2つの文字列を引数として受け取り、ブール値を返す高速rust関数を作成するにはどうすればよいですか。最初の文字列はC ++ヘッダーファイルへのパスで、2番目の文字列はそのヘッダーファイルで定義されている型の名前です。タイプが簡単にコピー可能かどうかを示すブール値を返す必要があります。

回答

2 ecatmur Dec 04 2020 at 04:56

少なくともIRに対しては、コードをコンパイルする必要があります。これは、C ++クラスの些細なことは、入力にプラットフォーム属性、使用可能なヘッダー、プリプロセッサ定義、コンパイラオプションなどが含まれる可能性がある任意の複雑な計算に依存する可能性があるためです。これらはC ++コンパイラでのみ実行できます。

clangをバイナリとして呼び出す場合、IRを発行するオプションはclang -S -emit-llvmあり、LLVMIR出力を解析する必要があります。たとえば

#include <type_traits>
struct A {};
struct B { B(B const&); };
struct C { ~C(); };
struct D { D(D const&) = default; };
int a = std::is_trivially_copyable<A>::value;
int b = std::is_trivially_copyable<B>::value;
int c = std::is_trivially_copyable<C>::value;
int d = std::is_trivially_copyable<D>::value;

IRは次のとおりです。

@a = dso_local local_unnamed_addr global i32 1, align 4, !dbg !0
@b = dso_local local_unnamed_addr global i32 0, align 4, !dbg !6
@c = dso_local local_unnamed_addr global i32 0, align 4, !dbg !10
@d = dso_local local_unnamed_addr global i32 1, align 4, !dbg !12
 ^ variable name                             ^ initializer

libclangを使用する場合は、EmitLLVMOnlyActionを呼び出して、GlobalVariable定義を抽出できるモジュールを提供する必要があります。参照:LLVMIRを作成する方法