[clang] c695a32 - [CIR] Call code gen; create empty cir.func op (#113483)

via cfe-commits cfe-commits at lists.llvm.org
Tue Nov 5 11:16:34 PST 2024


Author: David Olsen
Date: 2024-11-05T11:16:30-08:00
New Revision: c695a32576525b047f92b90de71eb707c152e29c

URL: https://github.com/llvm/llvm-project/commit/c695a32576525b047f92b90de71eb707c152e29c
DIFF: https://github.com/llvm/llvm-project/commit/c695a32576525b047f92b90de71eb707c152e29c.diff

LOG: [CIR] Call code gen; create empty cir.func op (#113483)

Finish hooking up ClangIR code gen into the Clang control flow,
initializing enough that basic code gen is possible.

Add an almost empty `cir.func` op to the ClangIR dialect. Currently the
only property of the function is its name. Add the code necessary to
code gen a cir.func op.

Create essentially empty files
clang/lib/CIR/Dialect/IR/{CIRAttrs.cpp,CIRTypes.cpp}. These will be
filled in later as attributes and types are defined in the ClangIR
dialect.

(Part of upstreaming the ClangIR incubator project into LLVM.)

Added: 
    clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
    clang/lib/CIR/Dialect/IR/CIRTypes.cpp

Modified: 
    clang/include/clang/CIR/CIRGenerator.h
    clang/include/clang/CIR/Dialect/IR/CIRDialect.h
    clang/include/clang/CIR/Dialect/IR/CIROps.td
    clang/lib/CIR/CodeGen/CIRGenModule.cpp
    clang/lib/CIR/CodeGen/CIRGenModule.h
    clang/lib/CIR/CodeGen/CIRGenerator.cpp
    clang/lib/CIR/Dialect/IR/CIRDialect.cpp
    clang/lib/CIR/Dialect/IR/CMakeLists.txt
    clang/lib/CIR/FrontendAction/CIRGenAction.cpp
    clang/lib/Driver/ToolChains/Clang.cpp
    clang/test/CIR/hello.c

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/CIR/CIRGenerator.h b/clang/include/clang/CIR/CIRGenerator.h
index 9a8930ac46ea9c..aa1a7e64459b35 100644
--- a/clang/include/clang/CIR/CIRGenerator.h
+++ b/clang/include/clang/CIR/CIRGenerator.h
@@ -53,6 +53,7 @@ class CIRGenerator : public clang::ASTConsumer {
   ~CIRGenerator() override;
   void Initialize(clang::ASTContext &astCtx) override;
   bool HandleTopLevelDecl(clang::DeclGroupRef group) override;
+  mlir::ModuleOp getModule() const;
 };
 
 } // namespace cir

diff  --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
index d53e5d1663d62a..0b71bdad29a3af 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
@@ -13,4 +13,25 @@
 #ifndef LLVM_CLANG_CIR_DIALECT_IR_CIRDIALECT_H
 #define LLVM_CLANG_CIR_DIALECT_IR_CIRDIALECT_H
 
+#include "mlir/IR/Builders.h"
+#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/BuiltinTypes.h"
+#include "mlir/IR/Dialect.h"
+#include "mlir/IR/OpDefinition.h"
+#include "mlir/Interfaces/CallInterfaces.h"
+#include "mlir/Interfaces/ControlFlowInterfaces.h"
+#include "mlir/Interfaces/FunctionInterfaces.h"
+#include "mlir/Interfaces/InferTypeOpInterface.h"
+#include "mlir/Interfaces/LoopLikeInterface.h"
+#include "mlir/Interfaces/MemorySlotInterfaces.h"
+#include "mlir/Interfaces/SideEffectInterfaces.h"
+
+#include "clang/CIR/Dialect/IR/CIROpsDialect.h.inc"
+
+// TableGen'erated files for MLIR dialects require that a macro be defined when
+// they are included.  GET_OP_CLASSES tells the file to define the classes for
+// the operations of that dialect.
+#define GET_OP_CLASSES
+#include "clang/CIR/Dialect/IR/CIROps.h.inc"
+
 #endif // LLVM_CLANG_CIR_DIALECT_IR_CIRDIALECT_H

diff  --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 7311c8db783e06..c0440faa3c7b17 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -16,4 +16,86 @@
 
 include "clang/CIR/Dialect/IR/CIRDialect.td"
 
+include "mlir/IR/BuiltinAttributeInterfaces.td"
+include "mlir/IR/EnumAttr.td"
+include "mlir/IR/SymbolInterfaces.td"
+include "mlir/IR/CommonAttrConstraints.td"
+include "mlir/Interfaces/ControlFlowInterfaces.td"
+include "mlir/Interfaces/FunctionInterfaces.td"
+include "mlir/Interfaces/InferTypeOpInterface.td"
+include "mlir/Interfaces/LoopLikeInterface.td"
+include "mlir/Interfaces/MemorySlotInterfaces.td"
+include "mlir/Interfaces/SideEffectInterfaces.td"
+
+//===----------------------------------------------------------------------===//
+// CIR Ops
+//===----------------------------------------------------------------------===//
+
+// LLVMLoweringInfo is used by cir-tablegen to generate LLVM lowering logic
+// automatically for CIR operations. The `llvmOp` field gives the name of the
+// LLVM IR dialect operation that the CIR operation will be lowered to. The
+// input arguments of the CIR operation will be passed in the same order to the
+// lowered LLVM IR operation.
+//
+// Example:
+//
+// For the following CIR operation definition:
+//
+//   def FooOp : CIR_Op<"foo"> {
+//     // ...
+//     let arguments = (ins CIR_AnyType:$arg1, CIR_AnyType:$arg2);
+//     let llvmOp = "BarOp";
+//   }
+//
+// cir-tablegen will generate LLVM lowering code for the FooOp similar to the
+// following:
+//
+//   class CIRFooOpLowering
+//       : public mlir::OpConversionPattern<mlir::cir::FooOp> {
+//   public:
+//     using OpConversionPattern<mlir::cir::FooOp>::OpConversionPattern;
+//
+//     mlir::LogicalResult matchAndRewrite(
+//         mlir::cir::FooOp op,
+//         OpAdaptor adaptor,
+//         mlir::ConversionPatternRewriter &rewriter) const override {
+//       rewriter.replaceOpWithNewOp<mlir::LLVM::BarOp>(
+//         op, adaptor.getOperands()[0], adaptor.getOperands()[1]);
+//       return mlir::success();
+//     }
+//   }
+//
+// If you want fully customized LLVM IR lowering logic, simply exclude the
+// `llvmOp` field from your CIR operation definition.
+class LLVMLoweringInfo {
+  string llvmOp = "";
+}
+
+class CIR_Op<string mnemonic, list<Trait> traits = []> :
+    Op<CIR_Dialect, mnemonic, traits>, LLVMLoweringInfo;
+
+//===----------------------------------------------------------------------===//
+// FuncOp
+//===----------------------------------------------------------------------===//
+
+// TODO(CIR): For starters, cir.func has only name, nothing else.  The other
+// properties of a function will be added over time as more of ClangIR is
+// upstreamed.
+
+def FuncOp : CIR_Op<"func"> {
+  let summary = "Declare or define a function";
+  let description = [{
+    ... lots of text to be added later ...
+  }];
+
+  let arguments = (ins SymbolNameAttr:$sym_name);
+
+  let skipDefaultBuilders = 1;
+
+  let builders = [OpBuilder<(ins "StringRef":$name)>];
+
+  let hasCustomAssemblyFormat = 1;
+  let hasVerifier = 1;
+}
+
 #endif // LLVM_CLANG_CIR_DIALECT_IR_CIROPS

diff  --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 95e62326939fc2..c1adc7ecbf74dd 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -14,6 +14,9 @@
 
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclBase.h"
+#include "clang/AST/GlobalDecl.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/CIR/Dialect/IR/CIRDialect.h"
 
 #include "mlir/IR/BuiltinOps.h"
 #include "mlir/IR/Location.h"
@@ -24,9 +27,134 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &context,
                            clang::ASTContext &astctx,
                            const clang::CodeGenOptions &cgo,
                            DiagnosticsEngine &diags)
-    : astCtx(astctx), langOpts(astctx.getLangOpts()),
-      theModule{mlir::ModuleOp::create(mlir::UnknownLoc())},
-      target(astCtx.getTargetInfo()) {}
+    : builder(&context), astCtx(astctx), langOpts(astctx.getLangOpts()),
+      theModule{mlir::ModuleOp::create(mlir::UnknownLoc::get(&context))},
+      diags(diags), target(astCtx.getTargetInfo()) {}
+
+mlir::Location CIRGenModule::getLoc(SourceLocation cLoc) {
+  assert(cLoc.isValid() && "expected valid source location");
+  const SourceManager &sm = astCtx.getSourceManager();
+  PresumedLoc pLoc = sm.getPresumedLoc(cLoc);
+  StringRef filename = pLoc.getFilename();
+  return mlir::FileLineColLoc::get(builder.getStringAttr(filename),
+                                   pLoc.getLine(), pLoc.getColumn());
+}
+
+mlir::Location CIRGenModule::getLoc(SourceRange cRange) {
+  assert(cRange.isValid() && "expected a valid source range");
+  mlir::Location begin = getLoc(cRange.getBegin());
+  mlir::Location end = getLoc(cRange.getEnd());
+  mlir::Attribute metadata;
+  return mlir::FusedLoc::get({begin, end}, metadata, builder.getContext());
+}
+
+void CIRGenModule::buildGlobal(clang::GlobalDecl gd) {
+  const auto *global = cast<ValueDecl>(gd.getDecl());
+
+  if (const auto *fd = dyn_cast<FunctionDecl>(global)) {
+    // Update deferred annotations with the latest declaration if the function
+    // was already used or defined.
+    if (fd->hasAttr<AnnotateAttr>())
+      errorNYI(fd->getSourceRange(), "deferredAnnotations");
+    if (!fd->doesThisDeclarationHaveABody()) {
+      if (!fd->doesDeclarationForceExternallyVisibleDefinition())
+        return;
+
+      errorNYI(fd->getSourceRange(),
+               "function declaration that forces code gen");
+      return;
+    }
+  } else {
+    errorNYI(global->getSourceRange(), "global variable declaration");
+  }
+
+  // TODO(CIR): Defer emitting some global definitions until later
+  buildGlobalDefinition(gd);
+}
+
+void CIRGenModule::buildGlobalFunctionDefinition(clang::GlobalDecl gd,
+                                                 mlir::Operation *op) {
+  auto const *funcDecl = cast<FunctionDecl>(gd.getDecl());
+  auto funcOp = builder.create<mlir::cir::FuncOp>(
+      getLoc(funcDecl->getSourceRange()), funcDecl->getIdentifier()->getName());
+  theModule.push_back(funcOp);
+}
+
+void CIRGenModule::buildGlobalDefinition(clang::GlobalDecl gd,
+                                         mlir::Operation *op) {
+  const auto *decl = cast<ValueDecl>(gd.getDecl());
+  if (const auto *fd = dyn_cast<FunctionDecl>(decl)) {
+    // TODO(CIR): Skip generation of CIR for functions with available_externally
+    // linkage at -O0.
+
+    if (const auto *method = dyn_cast<CXXMethodDecl>(decl)) {
+      // Make sure to emit the definition(s) before we emit the thunks. This is
+      // necessary for the generation of certain thunks.
+      (void)method;
+      errorNYI(method->getSourceRange(), "member function");
+      return;
+    }
+
+    if (fd->isMultiVersion())
+      errorNYI(fd->getSourceRange(), "multiversion functions");
+    buildGlobalFunctionDefinition(gd, op);
+    return;
+  }
+
+  llvm_unreachable("Invalid argument to CIRGenModule::buildGlobalDefinition");
+}
 
 // Emit code for a single top level declaration.
-void CIRGenModule::buildTopLevelDecl(Decl *decl) {}
+void CIRGenModule::buildTopLevelDecl(Decl *decl) {
+
+  // Ignore dependent declarations.
+  if (decl->isTemplated())
+    return;
+
+  switch (decl->getKind()) {
+  default:
+    errorNYI(decl->getBeginLoc(), "declaration of kind",
+             decl->getDeclKindName());
+    break;
+
+  case Decl::Function: {
+    auto *fd = cast<FunctionDecl>(decl);
+    // Consteval functions shouldn't be emitted.
+    if (!fd->isConsteval())
+      buildGlobal(fd);
+    break;
+  }
+  }
+}
+
+DiagnosticBuilder CIRGenModule::errorNYI(llvm::StringRef feature) {
+  unsigned diagID = diags.getCustomDiagID(
+      DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0");
+  return diags.Report(diagID) << feature;
+}
+
+DiagnosticBuilder CIRGenModule::errorNYI(SourceLocation loc,
+                                         llvm::StringRef feature) {
+  unsigned diagID = diags.getCustomDiagID(
+      DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0");
+  return diags.Report(loc, diagID) << feature;
+}
+
+DiagnosticBuilder CIRGenModule::errorNYI(SourceLocation loc,
+                                         llvm::StringRef feature,
+                                         llvm::StringRef name) {
+  unsigned diagID = diags.getCustomDiagID(
+      DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0: %1");
+  return diags.Report(loc, diagID) << feature << name;
+}
+
+DiagnosticBuilder CIRGenModule::errorNYI(SourceRange loc,
+                                         llvm::StringRef feature) {
+  return errorNYI(loc.getBegin(), feature) << loc;
+}
+
+DiagnosticBuilder CIRGenModule::errorNYI(SourceRange loc,
+                                         llvm::StringRef feature,
+                                         llvm::StringRef name) {
+  return errorNYI(loc.getBegin(), feature, name) << loc;
+}

diff  --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h
index ab2a1d8864659a..2bf6a5d9c8f597 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.h
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.h
@@ -15,15 +15,21 @@
 
 #include "CIRGenTypeCache.h"
 
+#include "mlir/IR/Builders.h"
 #include "mlir/IR/BuiltinOps.h"
 #include "mlir/IR/MLIRContext.h"
+#include "llvm/ADT/StringRef.h"
 
 namespace clang {
 class ASTContext;
 class CodeGenOptions;
 class Decl;
+class DiagnosticBuilder;
 class DiagnosticsEngine;
+class GlobalDecl;
 class LangOptions;
+class SourceLocation;
+class SourceRange;
 class TargetInfo;
 } // namespace clang
 
@@ -44,6 +50,10 @@ class CIRGenModule : public CIRGenTypeCache {
   ~CIRGenModule() = default;
 
 private:
+  // TODO(CIR) 'builder' will change to CIRGenBuilderTy once that type is
+  // defined
+  mlir::OpBuilder builder;
+
   /// Hold Clang AST information.
   clang::ASTContext &astCtx;
 
@@ -52,10 +62,34 @@ class CIRGenModule : public CIRGenTypeCache {
   /// A "module" matches a c/cpp source file: containing a list of functions.
   mlir::ModuleOp theModule;
 
+  clang::DiagnosticsEngine &diags;
+
   const clang::TargetInfo ⌖
 
 public:
+  mlir::ModuleOp getModule() const { return theModule; }
+
+  /// Helpers to convert the presumed location of Clang's SourceLocation to an
+  /// MLIR Location.
+  mlir::Location getLoc(clang::SourceLocation cLoc);
+  mlir::Location getLoc(clang::SourceRange cRange);
+
   void buildTopLevelDecl(clang::Decl *decl);
+
+  /// Emit code for a single global function or variable declaration. Forward
+  /// declarations are emitted lazily.
+  void buildGlobal(clang::GlobalDecl gd);
+
+  void buildGlobalDefinition(clang::GlobalDecl gd,
+                             mlir::Operation *op = nullptr);
+  void buildGlobalFunctionDefinition(clang::GlobalDecl gd, mlir::Operation *op);
+
+  /// Helpers to emit "not yet implemented" error diagnostics
+  DiagnosticBuilder errorNYI(llvm::StringRef);
+  DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef);
+  DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef, llvm::StringRef);
+  DiagnosticBuilder errorNYI(SourceRange, llvm::StringRef);
+  DiagnosticBuilder errorNYI(SourceRange, llvm::StringRef, llvm::StringRef);
 };
 } // namespace cir
 

diff  --git a/clang/lib/CIR/CodeGen/CIRGenerator.cpp b/clang/lib/CIR/CodeGen/CIRGenerator.cpp
index 159355a99ece80..152124a00b2bbd 100644
--- a/clang/lib/CIR/CodeGen/CIRGenerator.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenerator.cpp
@@ -12,8 +12,11 @@
 
 #include "CIRGenModule.h"
 
+#include "mlir/IR/MLIRContext.h"
+
 #include "clang/AST/DeclGroup.h"
 #include "clang/CIR/CIRGenerator.h"
+#include "clang/CIR/Dialect/IR/CIRDialect.h"
 
 using namespace cir;
 using namespace clang;
@@ -31,9 +34,14 @@ void CIRGenerator::Initialize(ASTContext &astCtx) {
 
   this->astCtx = &astCtx;
 
-  cgm = std::make_unique<CIRGenModule>(*mlirCtx, astCtx, codeGenOpts, diags);
+  mlirCtx = std::make_unique<mlir::MLIRContext>();
+  mlirCtx->loadDialect<mlir::cir::CIRDialect>();
+  cgm = std::make_unique<CIRGenModule>(*mlirCtx.get(), astCtx, codeGenOpts,
+                                       diags);
 }
 
+mlir::ModuleOp CIRGenerator::getModule() const { return cgm->getModule(); }
+
 bool CIRGenerator::HandleTopLevelDecl(DeclGroupRef group) {
 
   for (Decl *decl : group)

diff  --git a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
new file mode 100644
index 00000000000000..6d74d72b77dca7
--- /dev/null
+++ b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
@@ -0,0 +1,38 @@
+//===- CIRAttrs.cpp - MLIR CIR Attributes ---------------------------------===//
+//
+// 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 defines the attributes in the CIR dialect.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/CIR/Dialect/IR/CIRDialect.h"
+
+using namespace mlir;
+using namespace mlir::cir;
+
+//===----------------------------------------------------------------------===//
+// General CIR parsing / printing
+//===----------------------------------------------------------------------===//
+
+Attribute CIRDialect::parseAttribute(DialectAsmParser &parser,
+                                     Type type) const {
+  // No attributes yet to parse
+  return Attribute{};
+}
+
+void CIRDialect::printAttribute(Attribute attr, DialectAsmPrinter &os) const {
+  // No attributes yet to print
+}
+
+//===----------------------------------------------------------------------===//
+// CIR Dialect
+//===----------------------------------------------------------------------===//
+
+void CIRDialect::registerAttributes() {
+  // No attributes yet to register
+}

diff  --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index c2829c3ff2af8c..e0b38a2902bdbb 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -10,4 +10,57 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include <clang/CIR/Dialect/IR/CIRDialect.h>
+#include "clang/CIR/Dialect/IR/CIRDialect.h"
+
+#include "mlir/Support/LogicalResult.h"
+
+#include "clang/CIR/Dialect/IR/CIROpsDialect.cpp.inc"
+
+using namespace mlir;
+using namespace mlir::cir;
+
+//===----------------------------------------------------------------------===//
+// CIR Dialect
+//===----------------------------------------------------------------------===//
+
+void mlir::cir::CIRDialect::initialize() {
+  registerTypes();
+  registerAttributes();
+  addOperations<
+#define GET_OP_LIST
+#include "clang/CIR/Dialect/IR/CIROps.cpp.inc"
+      >();
+}
+
+//===----------------------------------------------------------------------===//
+// FuncOp
+//===----------------------------------------------------------------------===//
+
+void mlir::cir::FuncOp::build(OpBuilder &builder, OperationState &result,
+                              StringRef name) {
+  result.addAttribute(SymbolTable::getSymbolAttrName(),
+                      builder.getStringAttr(name));
+}
+
+ParseResult cir::FuncOp::parse(OpAsmParser &parser, OperationState &state) {
+  StringAttr nameAttr;
+  if (parser.parseSymbolName(nameAttr, SymbolTable::getSymbolAttrName(),
+                             state.attributes))
+    return failure();
+  return success();
+}
+
+void cir::FuncOp::print(OpAsmPrinter &p) {
+  p << ' ';
+  // For now the only property a function has is its name
+  p.printSymbolName(getSymName());
+}
+
+mlir::LogicalResult mlir::cir::FuncOp::verify() { return success(); }
+
+//===----------------------------------------------------------------------===//
+// TableGen'd op method definitions
+//===----------------------------------------------------------------------===//
+
+#define GET_OP_CLASSES
+#include "clang/CIR/Dialect/IR/CIROps.cpp.inc"

diff  --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
new file mode 100644
index 00000000000000..167c237ae5515c
--- /dev/null
+++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
@@ -0,0 +1,37 @@
+//===- CIRTypes.cpp - MLIR CIR Types --------------------------------------===//
+//
+// 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 defines the types in the CIR dialect.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/CIR/Dialect/IR/CIRDialect.h"
+
+using namespace mlir;
+using namespace mlir::cir;
+
+//===----------------------------------------------------------------------===//
+// General CIR parsing / printing
+//===----------------------------------------------------------------------===//
+
+Type CIRDialect::parseType(DialectAsmParser &parser) const {
+  // No types yet to parse
+  return Type{};
+}
+
+void CIRDialect::printType(Type type, DialectAsmPrinter &os) const {
+  // No types yet to print
+}
+
+//===----------------------------------------------------------------------===//
+// CIR Dialect
+//===----------------------------------------------------------------------===//
+
+void CIRDialect::registerTypes() {
+  // No types yet to register
+}

diff  --git a/clang/lib/CIR/Dialect/IR/CMakeLists.txt b/clang/lib/CIR/Dialect/IR/CMakeLists.txt
index 0d7476b555705d..1518e8c760609c 100644
--- a/clang/lib/CIR/Dialect/IR/CMakeLists.txt
+++ b/clang/lib/CIR/Dialect/IR/CMakeLists.txt
@@ -1,3 +1,8 @@
 add_clang_library(MLIRCIR
+  CIRAttrs.cpp
   CIRDialect.cpp
+  CIRTypes.cpp
+
+  LINK_LIBS PUBLIC
+  MLIRIR
   )

diff  --git a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
index 72b9fa0c13c595..5a31e207081936 100644
--- a/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
+++ b/clang/lib/CIR/FrontendAction/CIRGenAction.cpp
@@ -22,8 +22,11 @@ class CIRGenConsumer : public clang::ASTConsumer {
 
   virtual void anchor();
 
+  CIRGenAction::OutputType Action;
+
   std::unique_ptr<raw_pwrite_stream> OutputStream;
 
+  ASTContext *Context{nullptr};
   IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
   std::unique_ptr<CIRGenerator> Gen;
 
@@ -37,14 +40,37 @@ class CIRGenConsumer : public clang::ASTConsumer {
                  const LangOptions &LangOptions,
                  const FrontendOptions &FEOptions,
                  std::unique_ptr<raw_pwrite_stream> OS)
-      : OutputStream(std::move(OS)), FS(VFS),
+      : Action(Action), OutputStream(std::move(OS)), FS(VFS),
         Gen(std::make_unique<CIRGenerator>(DiagnosticsEngine, std::move(VFS),
                                            CodeGenOptions)) {}
 
+  void Initialize(ASTContext &Ctx) override {
+    assert(!Context && "initialized multiple times");
+    Context = &Ctx;
+    Gen->Initialize(Ctx);
+  }
+
   bool HandleTopLevelDecl(DeclGroupRef D) override {
     Gen->HandleTopLevelDecl(D);
     return true;
   }
+
+  void HandleTranslationUnit(ASTContext &C) override {
+    Gen->HandleTranslationUnit(C);
+    mlir::ModuleOp MlirModule = Gen->getModule();
+    switch (Action) {
+    case CIRGenAction::OutputType::EmitCIR:
+      if (OutputStream && MlirModule) {
+        mlir::OpPrintingFlags Flags;
+        Flags.enableDebugInfo(/*enable=*/true, /*prettyForm=*/false);
+        MlirModule->print(*OutputStream, Flags);
+      }
+      break;
+    default:
+      llvm_unreachable("NYI: CIRGenAction other than EmitCIR");
+      break;
+    }
+  }
 };
 } // namespace cir
 
@@ -55,10 +81,23 @@ CIRGenAction::CIRGenAction(OutputType Act, mlir::MLIRContext *MLIRCtx)
 
 CIRGenAction::~CIRGenAction() { MLIRMod.release(); }
 
+static std::unique_ptr<raw_pwrite_stream>
+getOutputStream(CompilerInstance &CI, StringRef InFile,
+                CIRGenAction::OutputType Action) {
+  switch (Action) {
+  case CIRGenAction::OutputType::EmitCIR:
+    return CI.createDefaultOutputFile(false, InFile, "cir");
+  }
+  llvm_unreachable("Invalid CIRGenAction::OutputType");
+}
+
 std::unique_ptr<ASTConsumer>
 CIRGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
   std::unique_ptr<llvm::raw_pwrite_stream> Out = CI.takeOutputStream();
 
+  if (!Out)
+    Out = getOutputStream(CI, InFile, Action);
+
   auto Result = std::make_unique<cir::CIRGenConsumer>(
       Action, CI.getDiagnostics(), &CI.getVirtualFileSystem(),
       CI.getHeaderSearchOpts(), CI.getCodeGenOpts(), CI.getTargetOpts(),

diff  --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index dca8d3fd7b3eaf..0952262c360185 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -5358,6 +5358,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
     } else if (JA.getType() == types::TY_RewrittenLegacyObjC) {
       CmdArgs.push_back("-rewrite-objc");
       rewriteKind = RK_Fragile;
+    } else if (JA.getType() == types::TY_CIR) {
+      CmdArgs.push_back("-emit-cir");
     } else {
       assert(JA.getType() == types::TY_PP_Asm && "Unexpected output type!");
     }

diff  --git a/clang/test/CIR/hello.c b/clang/test/CIR/hello.c
index 61f38d0a5bd01a..4b07c04994aa8f 100644
--- a/clang/test/CIR/hello.c
+++ b/clang/test/CIR/hello.c
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s | FileCheck --allow-empty %s
+// Smoke test for ClangIR code generation
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o -  | FileCheck %s
 
-// just confirm that we don't crash
-// CHECK-NOT: *
 void foo() {}
+// CHECK: cir.func @foo


        


More information about the cfe-commits mailing list