Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ClangにReflection提案っぽいものを実装してみた話

Koudai Iwahori
April 17, 2019
750

 ClangにReflection提案っぽいものを実装してみた話

Koudai Iwahori

April 17, 2019
Tweet

Transcript

  1. 何したの? • C++コンパイラのお勉強がてらReflection提案(P1240)とMetaclass提案 (P0707) を雑にClangに実装してみた ◦ https://github.com/ho-ri1991/clang-reflection-metaclass • コンパイラ初心者なのでガチプロの方はマサカリをご準備ください ※真面目にメンテが必要なプロジェクトの場合は

    Clang Toolingなどで頑張る方が良いと思います c.f. CppCon 2018 “Building a C++ Reflection System in One Weekend Using Clang and LLVM” ※提案者(Andrew Sutton)の実装はこれ https://github.com/asutton/clang (読んでいないが、間違いなくこっちのほうが良い実装になっていると思います)
  2. Clang Parser Lexer AST CodeGen Sema main.cpp “int” “main” (“

    ...... LLVM IR https://github.com/llvm-mirror/clang/tree/master/include/clang
  3. Clang Parser Lexer AST CodeGen Sema main.cpp “int” “main” “(“

    “)” LLVM IR clang -Xclang -dump-tokens -fsyntax-only main.cpp
  4. Clang clang main.cpp -Xclang -ast-dump -fsyntax-only Parser Lexer AST CodeGen

    Sema main.cpp “int” “main” “(“ “)” LLVM IR
  5. Clang clang main.cpp -S -emit-llvm -o - Parser Lexer AST

    CodeGen Sema main.cpp “int” “main” “(“ “)” LLVM IR
  6. Reflection in C++ • ご存知のようにコンパイル時計算の需要がある ◦ Type traitsとかでいろいろ情報がとれるし 頑張ればいろいろ情報がとれる ◦

    Conceptも入る • ただ、取れないものも多い ◦ クラス名 ◦ メンバ変数・関数、enumフィールドのリスト ◦ 足りないものが多い
  7. Reflection TS (N4766, P0385) isocpp.org/std/status Approved for publication @ Kona

    meeting https://isocpp.org/files/img/wg21-timeline-2019-04.png
  8. Reflection TS (N4766, P0385) • Reflection TSではStatic Reflectionを入れようとしている ◦ より包括的なリフレクションのサポート

    • コンパイル時にクラス・名前空間などのメタ情報を取れるようになる ◦ クラス名、Enumerator名、名前空間名 ◦ メンバ変数/関数のリスト (名前と型)、public/private、ポインタなど ◦ 基本は名前がついているものから取れる • 式の構文木は取れない • TMPをベースとした設計 • 今回は省略
  9. Value Based Reflectionの構文 • reflexpr ( operand ) という構文 ◦

    メタ情報が入った実装依存の値が返ってくる
  10. Enum to String (Value Based Reflection) Expansion Statement (P1306) (コンパイル時vectorやtupleのloop

    expansion) Enumメンバの情報が入った constexprな vector(P0784)が返ってくる Enumのメタ情報を保持した値
  11. 構文を追加する Parser Lexer AST CodeGen Sema main.cpp “int” “main” “{“

    ...... LLVM IR このあたりを拡張する Parser, Semaは省略 ※予約後にする場合はLexerも必要 ※Reflectionはコンパイル時計算なので  コード生成は触らなくてもできる ※実際どうやるのが正攻法かはわからない
  12. Enum to String in Value Base Reflection Expansion Statement (P1306)

    (コンパイル時vectorやtupleのloop expansion)
  13. 偽Expansion Statementを実装する • constexpr vectorを作るのはちょっと大変 • やりたいことはメタ情報のリストを返すリフレクションのloop expansionなのでそれ だけ対応する •

    やることは単純 ◦ forのbodyをパースしてbodyのASTを作る ◦ リストサイズの分だけその bodyをコピーする ◦ ループ変数の初期値をそれぞれ書き換える ▪ 実際には細かいところで結構ハマった
  14. Reflection TSを越えて • identifierを生成して変数・関数宣言 ◦ 今はプリプロセッサマクロでしかできない ◦ Type/Value Based Reflection

    (P0385/P1240)提案に含まれている • より簡単なCode Injectionの機構 (P0712, p0633) • Metaclass ◦ constexpr関数でクラスの生成規則を作る
  15. References • clang ◦ https://clang.llvm.org/doxygen/index.html ◦ https://clang.llvm.org/docs/InternalsManual.html ◦ https://llvm.org/devmtg/2016-09/slides/Rink-SyntaxMacros.pdf ◦

    https://www.youtube.com/watch?v=DUiUBt-fqEY • Reflection ◦ Reflection TS : n4750 ◦ Type Based Reflection : p0385 ◦ Value Based Reflection : p1240 ◦ Expansion Statements : p1306 ◦ p0712 ◦ p0993 ◦ https://github.com/asutton/clang