FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

MLIRについての勉強 (チュートリアルをベースとした自作言語作成)

MLIRはMulti Level Intermediate Representationの略で、LLVM IRよりも更にメタ化したような中間言語だ。LLVM IRでは吸収しきれないような各言語で定義される中間表現を、許容するために開発された。

これを使ってみたいので、まずはToyに似たような言語を使って自分でMLIRを生成できるようになりたい。いくつか試行をしている。

MYSVというVerilogに等価な言語を作って、まずはそれをParseしてDumpできるようにする。これまMLIRを生成する前段階だ。

 assign A = 0;
 assign Hoge = 2;

前回まででとりあえず簡単なVerilogをParseできるようになったので、今度はこれをMLIRにビルドしていく、というわけだ。

まずはMLIRを出力できるモードを作る。

  switch (emitAction) {
  case Action::DumpAST:
    dumpAST();
    return 0;
  case Action::DumpMLIR:
    dumpMLIR(*moduleAST);
    return 0;
  default:
    llvm::errs() << "No action specified (parsing only?), use -emit=<action>\n";
  }

基本的な考え方としては、前回作った自作のASTツリーをMLIRにコンバートしていく。MLIRGen.cppを実装していく。

moduleASTの中に入っているAssignExprASTに分解していく。mlirGen(AssignExprAST)に分解していく。

   /// Public API: convert the AST for a Mysv module (source file) to an MLIR                                                                                                                                                        
   /// Module operation.                                                                                                                                                                                                             
   mlir::ModuleOp mlirGen(ModuleAST &moduleAST) {
     // We create an empty MLIR module and codegen functions one at a time and                                                                                                                                                       
     // add them to the module.                                                                                                                                                                                                      
     theModule = mlir::ModuleOp::create(builder.getUnknownLoc());

     for (AssignExprAST &a : moduleAST)
       mlirGen(a);
     // ...
     return theModule;
   }

AssignExprASTに対するMLIRの構築がこのようになる。引き続きMLIRブロックを作っていく。

   /// Emit a new function and add it to the MLIR module.                                                                                                                                                                            
   mlir::Value mlirGen(AssignExprAST &assignAST) {
     auto *init = vardecl.getInitVal();
     if (!init) {
       emitError(loc(vardecl.loc()),
                 "missing initializer in variable declaration");
       return nullptr;
     }

     mlir::Value value = mlirGen(*init);
     if (!value)
       return nullptr;

     // Register the value in the symbol table.                                                                                                                                                                                      
     if (failed(declare(vardecl.getName(), value)))
       return nullptr;

     return value;
   }