Skip to content

Commit

Permalink
[CIR] Build out AST consumer patterns to reach the entry point into C…
Browse files Browse the repository at this point in the history
…IRGen

Build out the necessary infrastructure for the main entry point into
ClangIR generation -- CIRGenModule. A set of boilerplate classes exist
to facilitate this -- CIRGenerator, CIRGenAction, EmitCIRAction and
CIRGenConsumer. These all mirror the corresponding types from LLVM
generation by Clang's CodeGen.

The main entry point to CIR generation is
`CIRGenModule::buildTopLevelDecl`. It is currently just an empty
function. We've added a test to ensure that the pipeline reaches this
point and doesn't fail, but does nothing else. This will be removed in
one of the subsequent patches that'll add basic `cir.func` emission.

This patch also re-adds `-emit-cir` to the driver. lib/Driver/Driver.cpp
requires that a driver flag exists to facilirate the selection of the
right actions for the driver to create. Without a driver flag you get
the standard behaviors of `-S`, `-c`, etc. If we want to emit CIR IR
and, eventually, bytecode we'll need a driver flag to force this. This
is why `-emit-llvm` is a driver flag. Notably, `-emit-llvm-bc` as a cc1
flag doesn't ever do the right thing. Without a driver flag it is
incorrectly ignored and an executable is emitted. With `-S` a file named
`something.s` is emitted which actually contains bitcode.

Reviewers: AaronBallman, MaskRay, bcardosolopes

Reviewed By: bcardosolopes, AaronBallman

Pull Request: #91007
  • Loading branch information
lanza authored Oct 9, 2024
1 parent 208584d commit 1bb52e9
Show file tree
Hide file tree
Showing 16 changed files with 440 additions and 1 deletion.
60 changes: 60 additions & 0 deletions clang/include/clang/CIR/CIRGenerator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
//===- 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 LLVM_CLANG_CIR_CIRGENERATOR_H
#define LLVM_CLANG_CIR_CIRGENERATOR_H

#include "clang/AST/ASTConsumer.h"
#include "clang/Basic/CodeGenOptions.h"

#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/Support/VirtualFileSystem.h"

#include <memory>

namespace clang {
class DeclGroupRef;
class DiagnosticsEngine;
} // namespace clang

namespace mlir {
class MLIRContext;
} // namespace mlir
namespace cir {
class CIRGenModule;

class CIRGenerator : public clang::ASTConsumer {
virtual void anchor();
clang::DiagnosticsEngine &diags;
clang::ASTContext *astCtx;
// Only used for debug info.
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs;

const clang::CodeGenOptions &codeGenOpts;

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() override;
void Initialize(clang::ASTContext &astCtx) override;
bool HandleTopLevelDecl(clang::DeclGroupRef group) override;
};

} // namespace cir

#endif // LLVM_CLANG_CIR_CIRGENERATOR_H
60 changes: 60 additions & 0 deletions clang/include/clang/CIR/FrontendAction/CIRGenAction.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
//===---- 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"

#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/OwningOpRef.h"

namespace mlir {
class MLIRContext;
class ModuleOp;
} // namespace mlir

namespace cir {
class CIRGenConsumer;

class CIRGenAction : public clang::ASTFrontendAction {
public:
enum class OutputType {
EmitCIR,
};

private:
friend class CIRGenConsumer;

mlir::OwningOpRef<mlir::ModuleOp> MLIRMod;

mlir::MLIRContext *MLIRCtx;

protected:
CIRGenAction(OutputType Action, mlir::MLIRContext *MLIRCtx = nullptr);

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
2 changes: 1 addition & 1 deletion clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -2996,7 +2996,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

Expand Down
2 changes: 2 additions & 0 deletions clang/lib/CIR/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
32 changes: 32 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenModule.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//===- 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/ASTContext.h"
#include "clang/AST/DeclBase.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()),
theModule{mlir::ModuleOp::create(mlir::UnknownLoc())},
target(astCtx.getTargetInfo()) {}

// Emit code for a single top level declaration.
void CIRGenModule::buildTopLevelDecl(Decl *decl) {}
62 changes: 62 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenModule.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//===--- 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_CIR_CODEGEN_CIRGENMODULE_H
#define LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENMODULE_H

#include "CIRGenTypeCache.h"

#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/MLIRContext.h"

namespace clang {
class ASTContext;
class CodeGenOptions;
class Decl;
class DiagnosticsEngine;
class LangOptions;
class TargetInfo;
} // namespace clang

using namespace clang;
namespace cir {

/// 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;

public:
CIRGenModule(mlir::MLIRContext &context, clang::ASTContext &astctx,
const clang::CodeGenOptions &cgo,
clang::DiagnosticsEngine &diags);

~CIRGenModule() = default;

private:
/// Hold Clang AST information.
clang::ASTContext &astCtx;

const clang::LangOptions &langOpts;

/// A "module" matches a c/cpp source file: containing a list of functions.
mlir::ModuleOp theModule;

const clang::TargetInfo &target;

public:
void buildTopLevelDecl(clang::Decl *decl);
};
} // namespace cir

#endif // LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENMODULE_H
27 changes: 27 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenTypeCache.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//===--- 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_CIRGENTYPECACHE_H
#define LLVM_CLANG_LIB_CIR_CIRGENTYPECACHE_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() = default;
};

} // namespace cir

#endif // LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENTYPECACHE_H
43 changes: 43 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenerator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//===--- 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/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} {}
CIRGenerator::~CIRGenerator() = default;

void CIRGenerator::Initialize(ASTContext &astCtx) {
using namespace llvm;

this->astCtx = &astCtx;

cgm = std::make_unique<CIRGenModule>(*mlirCtx, astCtx, codeGenOpts, diags);
}

bool CIRGenerator::HandleTopLevelDecl(DeclGroupRef group) {

for (Decl *decl : group)
cgm->buildTopLevelDecl(decl);

return true;
}
23 changes: 23 additions & 0 deletions clang/lib/CIR/CodeGen/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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
)
Loading

0 comments on commit 1bb52e9

Please sign in to comment.