[clang] [CIR] Add CIRGenerator and plug it via CIRGenAction (PR #90831)

Nathan Lanza via cfe-commits cfe-commits at lists.llvm.org
Fri May 3 12:17:51 PDT 2024


https://github.com/lanza updated https://github.com/llvm/llvm-project/pull/90831

>From e57548737a72c5308e23fb442774b9bd9eca0bfa Mon Sep 17 00:00:00 2001
From: Nathan Lanza <nathanlanza at gmail.com>
Date: Thu, 2 May 2024 07:55:36 +0000
Subject: [PATCH 1/3] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20in?=
 =?UTF-8?q?itial=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.5
---
 clang/include/clang/CIR/CIRGenerator.h        | 28 +++++++++
 .../clang/CIRFrontendAction/CIRGenAction.h    | 62 +++++++++++++++++++
 clang/lib/CIR/CMakeLists.txt                  |  2 +
 clang/lib/CIR/CodeGen/CIRGenModule.cpp        | 21 +++++++
 clang/lib/CIR/CodeGen/CIRGenModule.h          | 42 +++++++++++++
 clang/lib/CIR/CodeGen/CIRGenTypeCache.h       | 28 +++++++++
 clang/lib/CIR/CodeGen/CIRGenerator.cpp        | 26 ++++++++
 clang/lib/CIR/CodeGen/CMakeLists.txt          | 23 +++++++
 clang/lib/CIR/FrontendAction/CIRGenAction.cpp | 46 ++++++++++++++
 clang/lib/CIR/FrontendAction/CMakeLists.txt   | 12 ++++
 clang/lib/FrontendTool/CMakeLists.txt         |  9 +++
 .../ExecuteCompilerInvocation.cpp             | 17 +++++
 12 files changed, 316 insertions(+)
 create mode 100644 clang/include/clang/CIR/CIRGenerator.h
 create mode 100644 clang/include/clang/CIRFrontendAction/CIRGenAction.h
 create mode 100644 clang/lib/CIR/CodeGen/CIRGenModule.cpp
 create mode 100644 clang/lib/CIR/CodeGen/CIRGenModule.h
 create mode 100644 clang/lib/CIR/CodeGen/CIRGenTypeCache.h
 create mode 100644 clang/lib/CIR/CodeGen/CIRGenerator.cpp
 create mode 100644 clang/lib/CIR/CodeGen/CMakeLists.txt
 create mode 100644 clang/lib/CIR/FrontendAction/CIRGenAction.cpp
 create mode 100644 clang/lib/CIR/FrontendAction/CMakeLists.txt

diff --git a/clang/include/clang/CIR/CIRGenerator.h b/clang/include/clang/CIR/CIRGenerator.h
new file mode 100644
index 00000000000000..c910f02698f41f
--- /dev/null
+++ b/clang/include/clang/CIR/CIRGenerator.h
@@ -0,0 +1,28 @@
+//===- CIRGenerator.h - CIR Generation from Clang AST ---------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares a simple interface to perform CIR generation from Clang
+// AST
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CIRGENERATOR_H_
+#define CLANG_CIRGENERATOR_H_
+
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/DeclGroup.h"
+
+namespace cir {
+class CIRGenerator : public clang::ASTConsumer {
+public:
+  bool HandleTopLevelDecl(clang::DeclGroupRef D) override;
+};
+
+} // namespace cir
+
+#endif // CLANG_CIRGENERATOR_H_
diff --git a/clang/include/clang/CIRFrontendAction/CIRGenAction.h b/clang/include/clang/CIRFrontendAction/CIRGenAction.h
new file mode 100644
index 00000000000000..02c906b173f52b
--- /dev/null
+++ b/clang/include/clang/CIRFrontendAction/CIRGenAction.h
@@ -0,0 +1,62 @@
+//===---- CIRGenAction.h - CIR Code Generation Frontend Action -*- C++ -*--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CIR_CIRGENACTION_H
+#define LLVM_CLANG_CIR_CIRGENACTION_H
+
+#include "clang/Frontend/FrontendAction.h"
+
+namespace mlir {
+class MLIRContext;
+class ModuleOp;
+template <typename T> class OwningOpRef;
+} // namespace mlir
+
+namespace cir {
+
+class CIRGenAction : public clang::ASTFrontendAction {
+public:
+  enum class OutputType {
+    EmitCIR,
+  };
+
+private:
+  friend class CIRGenConsumer;
+
+  // TODO: this is redundant but just using the OwningModuleRef requires more of
+  // clang against MLIR. Hide this somewhere else.
+  std::unique_ptr<mlir::OwningOpRef<mlir::ModuleOp>> mlirModule;
+
+  mlir::MLIRContext *mlirContext;
+
+protected:
+  CIRGenAction(OutputType action, mlir::MLIRContext *mlirContext = nullptr);
+
+  void foo() {
+
+  }
+
+  std::unique_ptr<clang::ASTConsumer>
+  CreateASTConsumer(clang::CompilerInstance &CI,
+                    llvm::StringRef InFile) override;
+
+public:
+  ~CIRGenAction() override;
+  OutputType action;
+};
+
+class EmitCIRAction : public CIRGenAction {
+  virtual void anchor();
+
+public:
+  EmitCIRAction(mlir::MLIRContext *mlirCtx = nullptr);
+};
+
+} // namespace cir
+
+#endif
diff --git a/clang/lib/CIR/CMakeLists.txt b/clang/lib/CIR/CMakeLists.txt
index d2ff200e0da5f5..11cca734808dfa 100644
--- a/clang/lib/CIR/CMakeLists.txt
+++ b/clang/lib/CIR/CMakeLists.txt
@@ -2,3 +2,5 @@ include_directories(${LLVM_MAIN_SRC_DIR}/../mlir/include)
 include_directories(${CMAKE_BINARY_DIR}/tools/mlir/include)
 
 add_subdirectory(Dialect)
+add_subdirectory(CodeGen)
+add_subdirectory(FrontendAction)
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
new file mode 100644
index 00000000000000..c9ed81a749cd2b
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -0,0 +1,21 @@
+//===- CIRGenModule.cpp - Per-Module state for CIR generation -------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the internal per-translation-unit state used for CIR translation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIRGenModule.h"
+
+#include "clang/AST/DeclBase.h"
+
+using namespace cir;
+
+// Emit code for a single top level declaration.
+void CIRGenModule::buildTopLevelDecl(Decl *decl) {
+}
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h
new file mode 100644
index 00000000000000..4fbd441b7a6196
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.h
@@ -0,0 +1,42 @@
+//===--- CIRGenModule.h - Per-Module state for CIR gen ----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the internal per-translation-unit state used for CIR translation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_CODEGEN_CIRGENMODULE_H
+#define LLVM_CLANG_LIB_CODEGEN_CIRGENMODULE_H
+
+#include "CIRGenTypeCache.h"
+
+#include "clang/AST/ASTContext.h"
+#include "clang/Basic/CodeGenOptions.h"
+#include "clang/Basic/Diagnostic.h"
+#include "mlir/IR/MLIRContext.h"
+
+using namespace clang;
+namespace cir {
+/// Implementation of a CIR/MLIR emission from Clang AST.
+///
+/// This will emit operations that are specific to C(++)/ObjC(++) language,
+/// preserving the semantics of the language and (hopefully) allow to perform
+/// accurate analysis and transformation based on these high level semantics.
+class CIRGenModule : public CIRGenTypeCache {
+  CIRGenModule(CIRGenModule &) = delete;
+  CIRGenModule &operator=(CIRGenModule &) = delete;
+
+public:
+  CIRGenModule(mlir::MLIRContext &context, clang::ASTContext &astctx,
+               const clang::CodeGenOptions &CGO,
+               clang::DiagnosticsEngine &Diags);
+
+  ~CIRGenModule();
+  void buildTopLevelDecl(clang::Decl *decl);
+};
+#endif // LLVM_CLANG_LIB_CODEGEN_CIRGENMODULE_H
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypeCache.h b/clang/lib/CIR/CodeGen/CIRGenTypeCache.h
new file mode 100644
index 00000000000000..e23c6b0531e3c7
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenTypeCache.h
@@ -0,0 +1,28 @@
+//===--- CIRGenTypeCache.h - Commonly used LLVM types and info -*- C++ --*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This structure provides a set of common types useful during CIR emission.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_CIR_CODEGENTYPECACHE_H
+#define LLVM_CLANG_LIB_CIR_CODEGENTYPECACHE_H
+
+namespace cir {
+
+/// This structure provides a set of types that are commonly used
+/// during IR emission. It's initialized once in CodeGenModule's
+/// constructor and then copied around into new CIRGenFunction's.
+struct CIRGenTypeCache {
+  CIRGenTypeCache() {}
+
+};
+
+} // namespace cir
+
+#endif
diff --git a/clang/lib/CIR/CodeGen/CIRGenerator.cpp b/clang/lib/CIR/CodeGen/CIRGenerator.cpp
new file mode 100644
index 00000000000000..a35a5c1372eedd
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenerator.cpp
@@ -0,0 +1,26 @@
+//===--- CIRGenerator.cpp - Emit CIR from ASTs ----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This builds an AST and converts it to CIR.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIRGenModule.h"
+
+#include "clang/CIR/CIRGenerator.h"
+
+using namespace cir;
+using namespace clang;
+
+bool CIRGenerator::HandleTopLevelDecl(DeclGroupRef D) {
+  for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {
+    CGM->buildTopLevelDecl(*I);
+  }
+
+  return true;
+}
diff --git a/clang/lib/CIR/CodeGen/CMakeLists.txt b/clang/lib/CIR/CodeGen/CMakeLists.txt
new file mode 100644
index 00000000000000..17a3aabfbd7f0e
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CMakeLists.txt
@@ -0,0 +1,23 @@
+set(
+  LLVM_LINK_COMPONENTS
+  Core
+  Support
+)
+
+get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
+
+add_clang_library(clangCIR
+  CIRGenerator.cpp
+  CIRGenModule.cpp
+
+  DEPENDS
+  MLIRCIR
+  ${dialect_libs}
+
+  LINK_LIBS
+  clangAST
+  clangBasic
+  clangLex
+  ${dialect_libs}
+  MLIRCIR
+)
diff --git a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
new file mode 100644
index 00000000000000..5d75ad1c15a66f
--- /dev/null
+++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
@@ -0,0 +1,46 @@
+//===--- CIRGenAction.cpp - LLVM Code generation Frontend Action ---------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/CIR/CIRGenerator.h"
+#include "clang/CIRFrontendAction/CIRGenAction.h"
+
+#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/MLIRContext.h"
+#include "mlir/IR/OwningOpRef.h"
+
+using namespace cir;
+using namespace clang;
+
+namespace cir {
+
+class CIRGenConsumer : public clang::ASTConsumer {
+
+  virtual void anchor();
+
+  std::unique_ptr<CIRGenerator> gen;
+  bool HandleTopLevelDecl(DeclGroupRef D) override {
+    gen->HandleTopLevelDecl(D);
+    return true;
+  }
+};
+} // namespace cir
+
+void CIRGenConsumer::anchor() {}
+
+CIRGenAction::CIRGenAction(OutputType act, mlir::MLIRContext *mlirContext)
+    : mlirContext(mlirContext ? mlirContext : new mlir::MLIRContext),
+      action(act) {}
+
+CIRGenAction::~CIRGenAction() { mlirModule.reset(); }
+
+std::unique_ptr<ASTConsumer>
+CIRGenAction::CreateASTConsumer(CompilerInstance &ci, StringRef inputFile) {}
+
+void EmitCIRAction::anchor() {}
+EmitCIRAction::EmitCIRAction(mlir::MLIRContext *_MLIRContext)
+    : CIRGenAction(OutputType::EmitCIR, _MLIRContext) {}
diff --git a/clang/lib/CIR/FrontendAction/CMakeLists.txt b/clang/lib/CIR/FrontendAction/CMakeLists.txt
new file mode 100644
index 00000000000000..164d9e259fb09c
--- /dev/null
+++ b/clang/lib/CIR/FrontendAction/CMakeLists.txt
@@ -0,0 +1,12 @@
+set(LLVM_LINK_COMPONENTS
+  )
+
+get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
+
+add_clang_library(clangCIRFrontendAction
+  CIRGenAction.cpp
+
+  LINK_LIBS
+  MLIRCIR
+  MLIRIR
+  )
diff --git a/clang/lib/FrontendTool/CMakeLists.txt b/clang/lib/FrontendTool/CMakeLists.txt
index 51c379ade2704c..6c6e6fd61e643a 100644
--- a/clang/lib/FrontendTool/CMakeLists.txt
+++ b/clang/lib/FrontendTool/CMakeLists.txt
@@ -12,6 +12,14 @@ set(link_libs
   clangRewriteFrontend
   )
 
+set(deps)
+
+if(CLANG_ENABLE_CIR)
+  list(APPEND link_libs
+    clangCIRFrontendAction
+    )
+endif()
+
 if(CLANG_ENABLE_ARCMT)
   list(APPEND link_libs
     clangARCMigrate
@@ -29,6 +37,7 @@ add_clang_library(clangFrontendTool
 
   DEPENDS
   ClangDriverOptions
+  ${deps}
 
   LINK_LIBS
   ${link_libs}
diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index 7476b1076d1038..ff1216992cded5 100644
--- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -31,6 +31,11 @@
 #include "llvm/Support/BuryPointer.h"
 #include "llvm/Support/DynamicLibrary.h"
 #include "llvm/Support/ErrorHandling.h"
+
+#if CLANG_ENABLE_CIR
+#include "clang/CIRFrontendAction/CIRGenAction.h"
+#endif
+
 using namespace clang;
 using namespace llvm::opt;
 
@@ -42,6 +47,14 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
   StringRef Action("unknown");
   (void)Action;
 
+  auto UseCIR = CI.getFrontendOpts().UseClangIRPipeline;
+  auto Act = CI.getFrontendOpts().ProgramAction;
+  auto EmitsCIR = Act == EmitCIR;
+
+  if (!UseCIR && EmitsCIR)
+    llvm::report_fatal_error(
+        "-emit-cir and -emit-cir-only only valid when using -fclangir");
+
   switch (CI.getFrontendOpts().ProgramAction) {
   case ASTDeclList:            return std::make_unique<ASTDeclListAction>();
   case ASTDump:                return std::make_unique<ASTDumpAction>();
@@ -53,8 +66,12 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
   case DumpTokens:             return std::make_unique<DumpTokensAction>();
   case EmitAssembly:           return std::make_unique<EmitAssemblyAction>();
   case EmitBC:                 return std::make_unique<EmitBCAction>();
+#if CLANG_ENABLE_CIR
+  case EmitCIR:                return std::make_unique<::cir::EmitCIRAction>();
+#else
   case EmitCIR:
     llvm_unreachable("CIR suppport not built into clang");
+#endif
   case EmitHTML:               return std::make_unique<HTMLPrintAction>();
   case EmitLLVM:               return std::make_unique<EmitLLVMAction>();
   case EmitLLVMOnly:           return std::make_unique<EmitLLVMOnlyAction>();

>From 4300feb4223b8ad7321884e360719355685e6646 Mon Sep 17 00:00:00 2001
From: Nathan Lanza <nathanlanza at gmail.com>
Date: Fri, 3 May 2024 07:10:47 +0000
Subject: [PATCH 2/3] get buildTopLevelDecl to run

Created using spr 1.3.5
---
 clang/include/clang/CIR/CIRGenerator.h        | 31 ++++++++++++
 .../clang/CIRFrontendAction/CIRGenAction.h    |  7 ++-
 clang/include/clang/Driver/Options.td         |  2 +-
 clang/lib/CIR/CodeGen/CIRGenModule.cpp        | 16 +++++++
 clang/lib/CIR/CodeGen/CIRGenModule.h          | 27 +++++++++--
 clang/lib/CIR/CodeGen/CIRGenTypeCache.h       |  7 ++-
 clang/lib/CIR/CodeGen/CIRGenerator.cpp        | 20 ++++++++
 clang/lib/CIR/FrontendAction/CIRGenAction.cpp | 47 ++++++++++++++++++-
 clang/lib/CIR/FrontendAction/CMakeLists.txt   |  3 ++
 clang/lib/Driver/ToolChains/Clang.cpp         |  3 ++
 .../ExecuteCompilerInvocation.cpp             |  3 +-
 clang/test/CIR/hello.c                        |  5 ++
 clang/test/CIR/lit.local.cfg                  |  2 +
 13 files changed, 158 insertions(+), 15 deletions(-)
 create mode 100644 clang/test/CIR/hello.c
 create mode 100644 clang/test/CIR/lit.local.cfg

diff --git a/clang/include/clang/CIR/CIRGenerator.h b/clang/include/clang/CIR/CIRGenerator.h
index c910f02698f41f..824038a9900132 100644
--- a/clang/include/clang/CIR/CIRGenerator.h
+++ b/clang/include/clang/CIR/CIRGenerator.h
@@ -16,10 +16,41 @@
 
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/DeclGroup.h"
+#include "clang/Basic/CodeGenOptions.h"
+#include "clang/Basic/Diagnostic.h"
 
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/Support/VirtualFileSystem.h"
+
+#include <memory>
+
+namespace mlir {
+class MLIRContext;
+} // namespace mlir
 namespace cir {
+class CIRGenModule;
+
 class CIRGenerator : public clang::ASTConsumer {
+  virtual void anchor();
+  clang::DiagnosticsEngine &Diags;
+  clang::ASTContext *astCtx;
+  llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
+      fs; // Only used for debug info.
+
+  const clang::CodeGenOptions codeGenOpts; // Intentionally copied in.
+
+  unsigned HandlingTopLevelDecls;
+
+protected:
+  std::unique_ptr<mlir::MLIRContext> mlirCtx;
+  std::unique_ptr<CIRGenModule> CGM;
+
 public:
+  CIRGenerator(clang::DiagnosticsEngine &diags,
+               llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
+               const clang::CodeGenOptions &CGO);
+  ~CIRGenerator();
+  void Initialize(clang::ASTContext &Context) override;
   bool HandleTopLevelDecl(clang::DeclGroupRef D) override;
 };
 
diff --git a/clang/include/clang/CIRFrontendAction/CIRGenAction.h b/clang/include/clang/CIRFrontendAction/CIRGenAction.h
index 02c906b173f52b..f522b818cbb725 100644
--- a/clang/include/clang/CIRFrontendAction/CIRGenAction.h
+++ b/clang/include/clang/CIRFrontendAction/CIRGenAction.h
@@ -18,6 +18,7 @@ template <typename T> class OwningOpRef;
 } // namespace mlir
 
 namespace cir {
+class CIRGenConsumer;
 
 class CIRGenAction : public clang::ASTFrontendAction {
 public:
@@ -37,16 +38,14 @@ class CIRGenAction : public clang::ASTFrontendAction {
 protected:
   CIRGenAction(OutputType action, mlir::MLIRContext *mlirContext = nullptr);
 
-  void foo() {
-
-  }
-
   std::unique_ptr<clang::ASTConsumer>
   CreateASTConsumer(clang::CompilerInstance &CI,
                     llvm::StringRef InFile) override;
 
 public:
   ~CIRGenAction() override;
+
+  CIRGenConsumer *cgConsumer;
   OutputType action;
 };
 
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 953f6fc649e621..d679c9c51c53e2 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -2900,7 +2900,7 @@ defm clangir : BoolFOption<"clangir",
   PosFlag<SetTrue, [], [ClangOption, CC1Option], "Use the ClangIR pipeline to compile">,
   NegFlag<SetFalse, [], [ClangOption, CC1Option], "Use the AST -> LLVM pipeline to compile">,
   BothFlags<[], [ClangOption, CC1Option], "">>;
-def emit_cir : Flag<["-"], "emit-cir">, Visibility<[CC1Option]>,
+def emit_cir : Flag<["-"], "emit-cir">, Visibility<[ClangOption, CC1Option]>,
   Group<Action_Group>, HelpText<"Build ASTs and then lower to ClangIR">;
 /// ClangIR-specific options - END
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index c9ed81a749cd2b..b87d467f8510b2 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -14,8 +14,24 @@
 
 #include "clang/AST/DeclBase.h"
 
+#include "llvm/Support/Debug.h"
+
+#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/Location.h"
+#include "mlir/IR/MLIRContext.h"
+
 using namespace cir;
+CIRGenModule::CIRGenModule(mlir::MLIRContext &context,
+                           clang::ASTContext &astctx,
+                           const clang::CodeGenOptions &CGO,
+                           DiagnosticsEngine &Diags)
+    : astCtx(astctx), langOpts(astctx.getLangOpts()), codeGenOpts(CGO),
+      theModule{mlir::ModuleOp::create(mlir::UnknownLoc())}, Diags(Diags),
+      target(astCtx.getTargetInfo()) {}
+
+CIRGenModule::~CIRGenModule() {}
 
 // Emit code for a single top level declaration.
 void CIRGenModule::buildTopLevelDecl(Decl *decl) {
+  llvm::outs() << "CIRGenModule::buildTopLevelDecl\n";
 }
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h
index 4fbd441b7a6196..02d57e2fc65ff1 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.h
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.h
@@ -10,14 +10,16 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_LIB_CODEGEN_CIRGENMODULE_H
-#define LLVM_CLANG_LIB_CODEGEN_CIRGENMODULE_H
+#ifndef LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENMODULE_H
+#define LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENMODULE_H
 
 #include "CIRGenTypeCache.h"
 
 #include "clang/AST/ASTContext.h"
 #include "clang/Basic/CodeGenOptions.h"
 #include "clang/Basic/Diagnostic.h"
+
+#include "mlir/IR/BuiltinOps.h"
 #include "mlir/IR/MLIRContext.h"
 
 using namespace clang;
@@ -37,6 +39,25 @@ class CIRGenModule : public CIRGenTypeCache {
                clang::DiagnosticsEngine &Diags);
 
   ~CIRGenModule();
+
+private:
+  /// Hold Clang AST information.
+  clang::ASTContext &astCtx;
+
+  const clang::LangOptions &langOpts;
+
+  const clang::CodeGenOptions &codeGenOpts;
+
+  /// A "module" matches a c/cpp source file: containing a list of functions.
+  mlir::ModuleOp theModule;
+
+  clang::DiagnosticsEngine &Diags;
+
+  const clang::TargetInfo ⌖
+
+public:
   void buildTopLevelDecl(clang::Decl *decl);
 };
-#endif // LLVM_CLANG_LIB_CODEGEN_CIRGENMODULE_H
+} // namespace cir
+
+#endif // LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENMODULE_H
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypeCache.h b/clang/lib/CIR/CodeGen/CIRGenTypeCache.h
index e23c6b0531e3c7..9b865aa20b4fde 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypeCache.h
+++ b/clang/lib/CIR/CodeGen/CIRGenTypeCache.h
@@ -10,8 +10,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_LIB_CIR_CODEGENTYPECACHE_H
-#define LLVM_CLANG_LIB_CIR_CODEGENTYPECACHE_H
+#ifndef LLVM_CLANG_LIB_CIR_CIRGENTYPECACHE_H
+#define LLVM_CLANG_LIB_CIR_CIRGENTYPECACHE_H
 
 namespace cir {
 
@@ -20,9 +20,8 @@ namespace cir {
 /// constructor and then copied around into new CIRGenFunction's.
 struct CIRGenTypeCache {
   CIRGenTypeCache() {}
-
 };
 
 } // namespace cir
 
-#endif
+#endif // LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENTYPECACHE_H
diff --git a/clang/lib/CIR/CodeGen/CIRGenerator.cpp b/clang/lib/CIR/CodeGen/CIRGenerator.cpp
index a35a5c1372eedd..00f9e97ee13273 100644
--- a/clang/lib/CIR/CodeGen/CIRGenerator.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenerator.cpp
@@ -12,12 +12,32 @@
 
 #include "CIRGenModule.h"
 
+#include "clang/AST/DeclGroup.h"
 #include "clang/CIR/CIRGenerator.h"
 
 using namespace cir;
 using namespace clang;
 
+void CIRGenerator::anchor() {}
+
+CIRGenerator::CIRGenerator(clang::DiagnosticsEngine &diags,
+                           llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs,
+                           const CodeGenOptions &CGO)
+    : Diags(diags), fs(std::move(vfs)), codeGenOpts{CGO},
+      HandlingTopLevelDecls(0) {}
+CIRGenerator::~CIRGenerator() {}
+
+void CIRGenerator::Initialize(ASTContext &astCtx) {
+  using namespace llvm;
+
+  this->astCtx = &astCtx;
+
+  CGM = std::make_unique<CIRGenModule>(*mlirCtx.get(), astCtx, codeGenOpts,
+                                       Diags);
+}
+
 bool CIRGenerator::HandleTopLevelDecl(DeclGroupRef D) {
+
   for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {
     CGM->buildTopLevelDecl(*I);
   }
diff --git a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
index 5d75ad1c15a66f..ac43a91f93487d 100644
--- a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
+++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
@@ -6,8 +6,9 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "clang/CIR/CIRGenerator.h"
 #include "clang/CIRFrontendAction/CIRGenAction.h"
+#include "clang/CIR/CIRGenerator.h"
+#include "clang/Frontend/CompilerInstance.h"
 
 #include "mlir/IR/BuiltinOps.h"
 #include "mlir/IR/MLIRContext.h"
@@ -22,7 +23,39 @@ class CIRGenConsumer : public clang::ASTConsumer {
 
   virtual void anchor();
 
+  CIRGenAction::OutputType action;
+
+  DiagnosticsEngine &diagnosticsEngine;
+  const HeaderSearchOptions &headerSearchOptions;
+  const CodeGenOptions &codeGenOptions;
+  const TargetOptions &targetOptions;
+  const LangOptions &langOptions;
+  const FrontendOptions &feOptions;
+
+  std::unique_ptr<raw_pwrite_stream> outputStream;
+
+  ASTContext *astContext{nullptr};
+  IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
   std::unique_ptr<CIRGenerator> gen;
+
+public:
+  CIRGenConsumer(CIRGenAction::OutputType action,
+                 DiagnosticsEngine &diagnosticsEngine,
+                 IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
+                 const HeaderSearchOptions &headerSearchOptions,
+                 const CodeGenOptions &codeGenOptions,
+                 const TargetOptions &targetOptions,
+                 const LangOptions &langOptions,
+                 const FrontendOptions &feOptions,
+                 std::unique_ptr<raw_pwrite_stream> os)
+      : action(action), diagnosticsEngine(diagnosticsEngine),
+        headerSearchOptions(headerSearchOptions),
+        codeGenOptions(codeGenOptions), targetOptions(targetOptions),
+        langOptions(langOptions), feOptions(feOptions),
+        outputStream(std::move(os)), FS(VFS),
+        gen(std::make_unique<CIRGenerator>(diagnosticsEngine, std::move(VFS),
+                                           codeGenOptions)) {}
+
   bool HandleTopLevelDecl(DeclGroupRef D) override {
     gen->HandleTopLevelDecl(D);
     return true;
@@ -39,7 +72,17 @@ CIRGenAction::CIRGenAction(OutputType act, mlir::MLIRContext *mlirContext)
 CIRGenAction::~CIRGenAction() { mlirModule.reset(); }
 
 std::unique_ptr<ASTConsumer>
-CIRGenAction::CreateASTConsumer(CompilerInstance &ci, StringRef inputFile) {}
+CIRGenAction::CreateASTConsumer(CompilerInstance &ci, StringRef inputFile) {
+  auto out = ci.takeOutputStream();
+
+  auto Result = std::make_unique<cir::CIRGenConsumer>(
+      action, ci.getDiagnostics(), &ci.getVirtualFileSystem(),
+      ci.getHeaderSearchOpts(), ci.getCodeGenOpts(), ci.getTargetOpts(),
+      ci.getLangOpts(), ci.getFrontendOpts(), std::move(out));
+  cgConsumer = Result.get();
+
+  return std::move(Result);
+}
 
 void EmitCIRAction::anchor() {}
 EmitCIRAction::EmitCIRAction(mlir::MLIRContext *_MLIRContext)
diff --git a/clang/lib/CIR/FrontendAction/CMakeLists.txt b/clang/lib/CIR/FrontendAction/CMakeLists.txt
index 164d9e259fb09c..a39138ca6190c2 100644
--- a/clang/lib/CIR/FrontendAction/CMakeLists.txt
+++ b/clang/lib/CIR/FrontendAction/CMakeLists.txt
@@ -7,6 +7,9 @@ add_clang_library(clangCIRFrontendAction
   CIRGenAction.cpp
 
   LINK_LIBS
+  clangAST
+  clangFrontend
+  clangCIR
   MLIRCIR
   MLIRIR
   )
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 2cb0c721354499..f3dddebd1b6cea 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -4944,6 +4944,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
     }
   }
 
+  if (Args.hasArg(options::OPT_fclangir))
+    CmdArgs.push_back("-fclangir");
+
   if (IsOpenMPDevice) {
     // We have to pass the triple of the host if compiling for an OpenMP device.
     std::string NormalizedTriple =
diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index ff1216992cded5..563e8473f4fce6 100644
--- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -67,7 +67,8 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
   case EmitAssembly:           return std::make_unique<EmitAssemblyAction>();
   case EmitBC:                 return std::make_unique<EmitBCAction>();
 #if CLANG_ENABLE_CIR
-  case EmitCIR:                return std::make_unique<::cir::EmitCIRAction>();
+  case EmitCIR:
+    return std::make_unique<::cir::EmitCIRAction>();
 #else
   case EmitCIR:
     llvm_unreachable("CIR suppport not built into clang");
diff --git a/clang/test/CIR/hello.c b/clang/test/CIR/hello.c
new file mode 100644
index 00000000000000..d8ea5aba02493c
--- /dev/null
+++ b/clang/test/CIR/hello.c
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s | FileCheck %s
+
+// CHECK: CIRGenModule::buildTopLevelDecl
+
+void foo() {}
diff --git a/clang/test/CIR/lit.local.cfg b/clang/test/CIR/lit.local.cfg
new file mode 100644
index 00000000000000..6e9e8b42c00885
--- /dev/null
+++ b/clang/test/CIR/lit.local.cfg
@@ -0,0 +1,2 @@
+if not config.root.clang_enable_cir:
+    clang.unsupported = True

>From 13a6fe87db2cb8750090596925742e2c6f746af2 Mon Sep 17 00:00:00 2001
From: Nathan Lanza <nathanlanza at gmail.com>
Date: Fri, 3 May 2024 07:22:53 +0000
Subject: [PATCH 3/3] fix comments

Created using spr 1.3.5
---
 clang/include/clang/CIRFrontendAction/CIRGenAction.h | 8 ++++----
 clang/lib/CIR/CodeGen/CIRGenModule.h                 | 8 +++-----
 clang/lib/CIR/FrontendAction/CIRGenAction.cpp        | 2 +-
 clang/lib/CIR/FrontendAction/CMakeLists.txt          | 2 ++
 clang/lib/FrontendTool/CMakeLists.txt                | 6 ++++++
 5 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/clang/include/clang/CIRFrontendAction/CIRGenAction.h b/clang/include/clang/CIRFrontendAction/CIRGenAction.h
index f522b818cbb725..aaf73ec2bffc47 100644
--- a/clang/include/clang/CIRFrontendAction/CIRGenAction.h
+++ b/clang/include/clang/CIRFrontendAction/CIRGenAction.h
@@ -11,10 +11,12 @@
 
 #include "clang/Frontend/FrontendAction.h"
 
+#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/OwningOpRef.h"
+
 namespace mlir {
 class MLIRContext;
 class ModuleOp;
-template <typename T> class OwningOpRef;
 } // namespace mlir
 
 namespace cir {
@@ -29,9 +31,7 @@ class CIRGenAction : public clang::ASTFrontendAction {
 private:
   friend class CIRGenConsumer;
 
-  // TODO: this is redundant but just using the OwningModuleRef requires more of
-  // clang against MLIR. Hide this somewhere else.
-  std::unique_ptr<mlir::OwningOpRef<mlir::ModuleOp>> mlirModule;
+  mlir::OwningOpRef<mlir::ModuleOp> mlirModule;
 
   mlir::MLIRContext *mlirContext;
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h
index 02d57e2fc65ff1..e629edcb91614d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.h
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.h
@@ -24,11 +24,9 @@
 
 using namespace clang;
 namespace cir {
-/// Implementation of a CIR/MLIR emission from Clang AST.
-///
-/// This will emit operations that are specific to C(++)/ObjC(++) language,
-/// preserving the semantics of the language and (hopefully) allow to perform
-/// accurate analysis and transformation based on these high level semantics.
+
+/// This class organizes the cross-function state that is used while generating
+/// CIR code.
 class CIRGenModule : public CIRGenTypeCache {
   CIRGenModule(CIRGenModule &) = delete;
   CIRGenModule &operator=(CIRGenModule &) = delete;
diff --git a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
index ac43a91f93487d..afbf0f119d6f4e 100644
--- a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
+++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
@@ -69,7 +69,7 @@ CIRGenAction::CIRGenAction(OutputType act, mlir::MLIRContext *mlirContext)
     : mlirContext(mlirContext ? mlirContext : new mlir::MLIRContext),
       action(act) {}
 
-CIRGenAction::~CIRGenAction() { mlirModule.reset(); }
+CIRGenAction::~CIRGenAction() { mlirModule.release(); }
 
 std::unique_ptr<ASTConsumer>
 CIRGenAction::CreateASTConsumer(CompilerInstance &ci, StringRef inputFile) {
diff --git a/clang/lib/CIR/FrontendAction/CMakeLists.txt b/clang/lib/CIR/FrontendAction/CMakeLists.txt
index a39138ca6190c2..b0616ab5d64b09 100644
--- a/clang/lib/CIR/FrontendAction/CMakeLists.txt
+++ b/clang/lib/CIR/FrontendAction/CMakeLists.txt
@@ -1,4 +1,6 @@
 set(LLVM_LINK_COMPONENTS
+  Core
+  Support
   )
 
 get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
diff --git a/clang/lib/FrontendTool/CMakeLists.txt b/clang/lib/FrontendTool/CMakeLists.txt
index 6c6e6fd61e643a..bfc7652b4c118f 100644
--- a/clang/lib/FrontendTool/CMakeLists.txt
+++ b/clang/lib/FrontendTool/CMakeLists.txt
@@ -17,6 +17,7 @@ set(deps)
 if(CLANG_ENABLE_CIR)
   list(APPEND link_libs
     clangCIRFrontendAction
+    MLIRIR
     )
 endif()
 
@@ -42,3 +43,8 @@ add_clang_library(clangFrontendTool
   LINK_LIBS
   ${link_libs}
   )
+
+if(CLANG_ENABLE_CIR)
+  target_include_directories(clangFrontendTool PRIVATE ${LLVM_MAIN_SRC_DIR}/../mlir/include)
+  target_include_directories(clangFrontendTool PRIVATE ${CMAKE_BINARY_DIR}/tools/mlir/include)
+endif()



More information about the cfe-commits mailing list