Skip to content

Commit fd38921

Browse files
committed
[CIR] Call code gen; create empty cir.func op
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.)
1 parent f1be516 commit fd38921

File tree

12 files changed

+424
-7
lines changed

12 files changed

+424
-7
lines changed

clang/include/clang/CIR/CIRGenerator.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class CIRGenerator : public clang::ASTConsumer {
5353
~CIRGenerator() override;
5454
void Initialize(clang::ASTContext &astCtx) override;
5555
bool HandleTopLevelDecl(clang::DeclGroupRef group) override;
56+
mlir::ModuleOp getModule();
5657
};
5758

5859
} // namespace cir

clang/include/clang/CIR/Dialect/IR/CIRDialect.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,22 @@
1313
#ifndef LLVM_CLANG_CIR_DIALECT_IR_CIRDIALECT_H
1414
#define LLVM_CLANG_CIR_DIALECT_IR_CIRDIALECT_H
1515

16+
#include "mlir/IR/Builders.h"
17+
#include "mlir/IR/BuiltinOps.h"
18+
#include "mlir/IR/BuiltinTypes.h"
19+
#include "mlir/IR/Dialect.h"
20+
#include "mlir/IR/OpDefinition.h"
21+
#include "mlir/Interfaces/CallInterfaces.h"
22+
#include "mlir/Interfaces/ControlFlowInterfaces.h"
23+
#include "mlir/Interfaces/FunctionInterfaces.h"
24+
#include "mlir/Interfaces/InferTypeOpInterface.h"
25+
#include "mlir/Interfaces/LoopLikeInterface.h"
26+
#include "mlir/Interfaces/MemorySlotInterfaces.h"
27+
#include "mlir/Interfaces/SideEffectInterfaces.h"
28+
29+
#include "clang/CIR/Dialect/IR/CIROpsDialect.h.inc"
30+
31+
#define GET_OP_CLASSES
32+
#include "clang/CIR/Dialect/IR/CIROps.h.inc"
33+
1634
#endif // LLVM_CLANG_CIR_DIALECT_IR_CIRDIALECT_H

clang/include/clang/CIR/Dialect/IR/CIROps.td

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,50 @@
1616

1717
include "clang/CIR/Dialect/IR/CIRDialect.td"
1818

19+
include "mlir/Interfaces/ControlFlowInterfaces.td"
20+
include "mlir/Interfaces/FunctionInterfaces.td"
21+
include "mlir/Interfaces/InferTypeOpInterface.td"
22+
include "mlir/Interfaces/LoopLikeInterface.td"
23+
include "mlir/Interfaces/MemorySlotInterfaces.td"
24+
include "mlir/Interfaces/SideEffectInterfaces.td"
25+
26+
include "mlir/IR/BuiltinAttributeInterfaces.td"
27+
include "mlir/IR/EnumAttr.td"
28+
include "mlir/IR/SymbolInterfaces.td"
29+
include "mlir/IR/CommonAttrConstraints.td"
30+
31+
//===----------------------------------------------------------------------===//
32+
// CIR Ops
33+
//===----------------------------------------------------------------------===//
34+
35+
class LLVMLoweringInfo {
36+
string llvmOp = "";
37+
}
38+
39+
class CIR_Op<string mnemonic, list<Trait> traits = []> :
40+
Op<CIR_Dialect, mnemonic, traits>, LLVMLoweringInfo;
41+
42+
//===----------------------------------------------------------------------===//
43+
// FuncOp
44+
//===----------------------------------------------------------------------===//
45+
46+
// For starters, cir.func has only name, nothing else. The other properties
47+
// of a function will be added over time as more of ClangIR is upstreamed.
48+
49+
def FuncOp : CIR_Op<"func"> {
50+
let summary = "Declare or define a function";
51+
let description = [{
52+
... lots of text to be added later ...
53+
}];
54+
55+
let arguments = (ins SymbolNameAttr:$sym_name);
56+
57+
let skipDefaultBuilders = 1;
58+
59+
let builders = [OpBuilder<(ins "StringRef":$name)>];
60+
61+
let hasCustomAssemblyFormat = 1;
62+
let hasVerifier = 1;
63+
}
64+
1965
#endif // LLVM_CLANG_CIR_DIALECT_IR_CIROPS

clang/lib/CIR/CodeGen/CIRGenModule.cpp

Lines changed: 147 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414

1515
#include "clang/AST/ASTContext.h"
1616
#include "clang/AST/DeclBase.h"
17+
#include "clang/AST/GlobalDecl.h"
18+
#include "clang/Basic/SourceManager.h"
19+
#include "clang/CIR/Dialect/IR/CIRDialect.h"
1720

1821
#include "mlir/IR/BuiltinOps.h"
1922
#include "mlir/IR/Location.h"
@@ -24,9 +27,149 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &context,
2427
clang::ASTContext &astctx,
2528
const clang::CodeGenOptions &cgo,
2629
DiagnosticsEngine &diags)
27-
: astCtx(astctx), langOpts(astctx.getLangOpts()),
28-
theModule{mlir::ModuleOp::create(mlir::UnknownLoc())},
29-
target(astCtx.getTargetInfo()) {}
30+
: builder(&context), astCtx(astctx), langOpts(astctx.getLangOpts()),
31+
theModule{mlir::ModuleOp::create(mlir::UnknownLoc::get(&context))},
32+
diags(diags), target(astCtx.getTargetInfo()) {}
33+
34+
mlir::Location CIRGenModule::getLoc(SourceLocation cLoc) {
35+
assert(cLoc.isValid() && "expected valid source location");
36+
const SourceManager &sm = astCtx.getSourceManager();
37+
PresumedLoc pLoc = sm.getPresumedLoc(cLoc);
38+
StringRef filename = pLoc.getFilename();
39+
return mlir::FileLineColLoc::get(builder.getStringAttr(filename),
40+
pLoc.getLine(), pLoc.getColumn());
41+
}
42+
43+
mlir::Location CIRGenModule::getLoc(SourceRange cRange) {
44+
assert(cRange.isValid() && "expected a valid source range");
45+
mlir::Location begin = getLoc(cRange.getBegin());
46+
mlir::Location end = getLoc(cRange.getEnd());
47+
SmallVector<mlir::Location, 2> locs = {begin, end};
48+
mlir::Attribute metadata;
49+
return mlir::FusedLoc::get(locs, metadata, builder.getContext());
50+
}
51+
52+
void CIRGenModule::buildGlobal(clang::GlobalDecl gd) {
53+
54+
const auto *global = cast<ValueDecl>(gd.getDecl());
55+
56+
if (const auto *fd = dyn_cast<FunctionDecl>(global)) {
57+
// Update deferred annotations with the latest declaration if the function
58+
// was already used or defined.
59+
if (fd->hasAttr<AnnotateAttr>()) {
60+
errorNYI(fd->getSourceRange(), "defferedAnnotations");
61+
}
62+
if (!fd->doesThisDeclarationHaveABody()) {
63+
if (!fd->doesDeclarationForceExternallyVisibleDefinition())
64+
return;
65+
66+
errorNYI(fd->getSourceRange(),
67+
"function declaration that forces code gen");
68+
return;
69+
}
70+
} else {
71+
const auto *vd = cast<VarDecl>(global);
72+
assert(vd->isFileVarDecl() && "Cannot emit local var decl as global.");
73+
errorNYI(vd->getSourceRange(), "global variable declaration");
74+
}
75+
76+
// NYI: Defer emitting some global definitions until later
77+
buildGlobalDefinition(gd);
78+
}
79+
80+
void CIRGenModule::buildGlobalFunctionDefinition(clang::GlobalDecl gd,
81+
mlir::Operation *op) {
82+
auto const *d = cast<FunctionDecl>(gd.getDecl());
83+
84+
builder.create<mlir::cir::FuncOp>(getLoc(d->getSourceRange()),
85+
d->getIdentifier()->getName());
86+
}
87+
88+
void CIRGenModule::buildGlobalDefinition(clang::GlobalDecl gd,
89+
mlir::Operation *op) {
90+
const auto *d = cast<ValueDecl>(gd.getDecl());
91+
if (const auto *fd = dyn_cast<FunctionDecl>(d)) {
92+
// NYI: Skip generation of CIR for functions with available_externally
93+
// linkage at -O0.
94+
95+
if (const auto *method = dyn_cast<CXXMethodDecl>(d)) {
96+
// Make sure to emit the definition(s) before we emit the thunks. This is
97+
// necessary for the generation of certain thunks.
98+
(void)method;
99+
errorNYI(method->getSourceRange(), "member function");
100+
return;
101+
}
102+
103+
if (fd->isMultiVersion())
104+
errorNYI(fd->getSourceRange(), "multiversion functions");
105+
buildGlobalFunctionDefinition(gd, op);
106+
return;
107+
}
108+
109+
if (const auto *vd = dyn_cast<VarDecl>(d)) {
110+
(void)vd;
111+
errorNYI(vd->getSourceRange(), "global variable definition");
112+
return;
113+
}
114+
115+
llvm_unreachable("Invalid argument to CIRGenModule::buildGlobalDefinition");
116+
}
30117

31118
// Emit code for a single top level declaration.
32-
void CIRGenModule::buildTopLevelDecl(Decl *decl) {}
119+
void CIRGenModule::buildTopLevelDecl(Decl *decl) {
120+
121+
// Ignore dependent declarations.
122+
if (decl->isTemplated())
123+
return;
124+
125+
switch (decl->getKind()) {
126+
default:
127+
errorNYI(decl->getBeginLoc(), "declaration of kind",
128+
decl->getDeclKindName());
129+
break;
130+
131+
case Decl::Function: {
132+
auto *fd = cast<FunctionDecl>(decl);
133+
// Consteval functions shouldn't be emitted.
134+
if (!fd->isConsteval())
135+
buildGlobal(fd);
136+
break;
137+
}
138+
}
139+
}
140+
141+
DiagnosticBuilder CIRGenModule::errorNYI(llvm::StringRef feature) {
142+
unsigned diagID = diags.getCustomDiagID(DiagnosticsEngine::Error,
143+
"ClangIR code gen NYI: %0");
144+
return diags.Report(diagID) << feature;
145+
}
146+
147+
DiagnosticBuilder CIRGenModule::errorNYI(SourceLocation loc,
148+
llvm::StringRef feature) {
149+
unsigned diagID = diags.getCustomDiagID(DiagnosticsEngine::Error,
150+
"ClangIR code gen NYI: %0");
151+
return diags.Report(loc, diagID) << feature;
152+
}
153+
154+
DiagnosticBuilder CIRGenModule::errorNYI(SourceLocation loc,
155+
llvm::StringRef feature,
156+
llvm::StringRef name) {
157+
unsigned diagID = diags.getCustomDiagID(DiagnosticsEngine::Error,
158+
"ClangIR code gen NYI: %0: %1");
159+
return diags.Report(loc, diagID) << feature << name;
160+
}
161+
162+
DiagnosticBuilder CIRGenModule::errorNYI(SourceRange loc,
163+
llvm::StringRef feature) {
164+
unsigned diagID = diags.getCustomDiagID(DiagnosticsEngine::Error,
165+
"ClangIR code gen NYI: %0");
166+
return diags.Report(loc.getBegin(), diagID) << feature << loc;
167+
}
168+
169+
DiagnosticBuilder CIRGenModule::errorNYI(SourceRange loc,
170+
llvm::StringRef feature,
171+
llvm::StringRef name) {
172+
unsigned diagID = diags.getCustomDiagID(DiagnosticsEngine::Error,
173+
"ClangIR code gen NYI: %0: %1");
174+
return diags.Report(loc.getBegin(), diagID) << feature << name << loc;
175+
}

clang/lib/CIR/CodeGen/CIRGenModule.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,21 @@
1515

1616
#include "CIRGenTypeCache.h"
1717

18+
#include "mlir/IR/Builders.h"
1819
#include "mlir/IR/BuiltinOps.h"
1920
#include "mlir/IR/MLIRContext.h"
21+
#include "llvm/ADT/StringRef.h"
2022

2123
namespace clang {
2224
class ASTContext;
2325
class CodeGenOptions;
2426
class Decl;
27+
class DiagnosticBuilder;
2528
class DiagnosticsEngine;
29+
class GlobalDecl;
2630
class LangOptions;
31+
class SourceLocation;
32+
class SourceRange;
2733
class TargetInfo;
2834
} // namespace clang
2935

@@ -44,6 +50,9 @@ class CIRGenModule : public CIRGenTypeCache {
4450
~CIRGenModule() = default;
4551

4652
private:
53+
// TODO 'builder' will change to CIRGenBuilderTy once that type is defined
54+
mlir::OpBuilder builder;
55+
4756
/// Hold Clang AST information.
4857
clang::ASTContext &astCtx;
4958

@@ -52,10 +61,32 @@ class CIRGenModule : public CIRGenTypeCache {
5261
/// A "module" matches a c/cpp source file: containing a list of functions.
5362
mlir::ModuleOp theModule;
5463

64+
clang::DiagnosticsEngine &diags;
65+
5566
const clang::TargetInfo &target;
5667

5768
public:
69+
mlir::ModuleOp getModule() const { return theModule; }
70+
71+
/// Helpers to convert Clang's SourceLocation to an MLIR Location.
72+
mlir::Location getLoc(clang::SourceLocation cLoc);
73+
mlir::Location getLoc(clang::SourceRange cRange);
74+
5875
void buildTopLevelDecl(clang::Decl *decl);
76+
77+
/// Emit code for a single global function or variable declaration. Forward
78+
/// declarations are emitted lazily.
79+
void buildGlobal(clang::GlobalDecl gd);
80+
81+
void buildGlobalDefinition(clang::GlobalDecl gd,
82+
mlir::Operation *op = nullptr);
83+
void buildGlobalFunctionDefinition(clang::GlobalDecl gd, mlir::Operation *op);
84+
85+
DiagnosticBuilder errorNYI(llvm::StringRef);
86+
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef);
87+
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef, llvm::StringRef);
88+
DiagnosticBuilder errorNYI(SourceRange, llvm::StringRef);
89+
DiagnosticBuilder errorNYI(SourceRange, llvm::StringRef, llvm::StringRef);
5990
};
6091
} // namespace cir
6192

clang/lib/CIR/CodeGen/CIRGenerator.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,11 @@
1212

1313
#include "CIRGenModule.h"
1414

15+
#include "mlir/IR/MLIRContext.h"
16+
1517
#include "clang/AST/DeclGroup.h"
1618
#include "clang/CIR/CIRGenerator.h"
19+
#include "clang/CIR/Dialect/IR/CIRDialect.h"
1720

1821
using namespace cir;
1922
using namespace clang;
@@ -31,9 +34,14 @@ void CIRGenerator::Initialize(ASTContext &astCtx) {
3134

3235
this->astCtx = &astCtx;
3336

34-
cgm = std::make_unique<CIRGenModule>(*mlirCtx, astCtx, codeGenOpts, diags);
37+
mlirCtx = std::make_unique<mlir::MLIRContext>();
38+
mlirCtx->getOrLoadDialect<mlir::cir::CIRDialect>();
39+
cgm = std::make_unique<CIRGenModule>(*mlirCtx.get(), astCtx, codeGenOpts,
40+
diags);
3541
}
3642

43+
mlir::ModuleOp CIRGenerator::getModule() { return cgm->getModule(); }
44+
3745
bool CIRGenerator::HandleTopLevelDecl(DeclGroupRef group) {
3846

3947
for (Decl *decl : group)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//===- CIRAttrs.cpp - MLIR CIR Attributes ---------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file defines the attributes in the CIR dialect.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "clang/CIR/Dialect/IR/CIRDialect.h"
14+
15+
using namespace mlir;
16+
using namespace mlir::cir;
17+
18+
//===----------------------------------------------------------------------===//
19+
// General CIR parsing / printing
20+
//===----------------------------------------------------------------------===//
21+
22+
Attribute CIRDialect::parseAttribute(DialectAsmParser &parser,
23+
Type type) const {
24+
// No attributes yet to parse
25+
return Attribute{};
26+
}
27+
28+
void CIRDialect::printAttribute(Attribute attr, DialectAsmPrinter &os) const {
29+
// No attributes yet to print
30+
}
31+
32+
//===----------------------------------------------------------------------===//
33+
// CIR Dialect
34+
//===----------------------------------------------------------------------===//
35+
36+
void CIRDialect::registerAttributes() {
37+
// No attributes yet to register
38+
}

0 commit comments

Comments
 (0)