1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
|
//===--- 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 "mlir/Dialect/OpenACC/OpenACC.h"
#include "mlir/IR/MLIRContext.h"
#include "mlir/Target/LLVMIR/Import.h"
#include "clang/AST/DeclGroup.h"
#include "clang/CIR/CIRGenerator.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "clang/CIR/Dialect/OpenACC/RegisterOpenACCExtensions.h"
#include "llvm/IR/DataLayout.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() {
// There should normally not be any leftover inline method definitions.
assert(deferredInlineMemberFuncDefs.empty() || diags.hasErrorOccurred());
}
static void setMLIRDataLayout(mlir::ModuleOp &mod, const llvm::DataLayout &dl) {
mlir::MLIRContext *mlirContext = mod.getContext();
mlir::DataLayoutSpecInterface dlSpec =
mlir::translateDataLayout(dl, mlirContext);
mod->setAttr(mlir::DLTIDialect::kDataLayoutAttrName, dlSpec);
}
void CIRGenerator::Initialize(ASTContext &astContext) {
using namespace llvm;
this->astContext = &astContext;
mlirContext = std::make_unique<mlir::MLIRContext>();
mlirContext->loadDialect<mlir::DLTIDialect>();
mlirContext->loadDialect<cir::CIRDialect>();
mlirContext->getOrLoadDialect<mlir::acc::OpenACCDialect>();
// Register extensions to integrate CIR types with OpenACC.
mlir::DialectRegistry registry;
cir::acc::registerOpenACCExtensions(registry);
mlirContext->appendDialectRegistry(registry);
cgm = std::make_unique<clang::CIRGen::CIRGenModule>(
*mlirContext.get(), astContext, codeGenOpts, diags);
mlir::ModuleOp mod = cgm->getModule();
llvm::DataLayout layout =
llvm::DataLayout(astContext.getTargetInfo().getDataLayoutString());
setMLIRDataLayout(mod, layout);
}
bool CIRGenerator::verifyModule() const { return cgm->verifyModule(); }
mlir::ModuleOp CIRGenerator::getModule() const { return cgm->getModule(); }
bool CIRGenerator::HandleTopLevelDecl(DeclGroupRef group) {
if (diags.hasUnrecoverableErrorOccurred())
return true;
HandlingTopLevelDeclRAII handlingDecl(*this);
for (Decl *decl : group)
cgm->emitTopLevelDecl(decl);
return true;
}
void CIRGenerator::HandleTranslationUnit(ASTContext &astContext) {
// Release the Builder when there is no error.
if (!diags.hasErrorOccurred() && cgm)
cgm->release();
// If there are errors before or when releasing the cgm, reset the module to
// stop here before invoking the backend.
assert(!cir::MissingFeatures::cleanupAfterErrorDiags());
}
void CIRGenerator::HandleInlineFunctionDefinition(FunctionDecl *d) {
if (diags.hasErrorOccurred())
return;
assert(d->doesThisDeclarationHaveABody());
// We may want to emit this definition. However, that decision might be
// based on computing the linkage, and we have to defer that in case we are
// inside of something that will chagne the method's final linkage, e.g.
// typedef struct {
// void bar();
// void foo() { bar(); }
// } A;
deferredInlineMemberFuncDefs.push_back(d);
// Provide some coverage mapping even for methods that aren't emitted.
// Don't do this for templated classes though, as they may not be
// instantiable.
assert(!cir::MissingFeatures::coverageMapping());
}
void CIRGenerator::emitDeferredDecls() {
if (deferredInlineMemberFuncDefs.empty())
return;
// Emit any deferred inline method definitions. Note that more deferred
// methods may be added during this loop, since ASTConsumer callbacks can be
// invoked if AST inspection results in declarations being added. Therefore,
// we use an index to loop over the deferredInlineMemberFuncDefs rather than
// a range.
HandlingTopLevelDeclRAII handlingDecls(*this);
for (unsigned i = 0; i != deferredInlineMemberFuncDefs.size(); ++i)
cgm->emitTopLevelDecl(deferredInlineMemberFuncDefs[i]);
deferredInlineMemberFuncDefs.clear();
}
/// HandleTagDeclDefinition - This callback is invoked each time a TagDecl to
/// (e.g. struct, union, enum, class) is completed. This allows the client to
/// hack on the type, which can occur at any point in the file (because these
/// can be defined in declspecs).
void CIRGenerator::HandleTagDeclDefinition(TagDecl *d) {
if (diags.hasErrorOccurred())
return;
// Don't allow re-entrant calls to CIRGen triggered by PCH deserialization to
// emit deferred decls.
HandlingTopLevelDeclRAII handlingDecl(*this, /*EmitDeferred=*/false);
cgm->updateCompletedType(d);
// For MSVC compatibility, treat declarations of static data members with
// inline initializers as definitions.
if (astContext->getTargetInfo().getCXXABI().isMicrosoft())
cgm->errorNYI(d->getSourceRange(), "HandleTagDeclDefinition: MSABI");
// For OpenMP emit declare reduction functions, if required.
if (astContext->getLangOpts().OpenMP)
cgm->errorNYI(d->getSourceRange(), "HandleTagDeclDefinition: OpenMP");
}
void CIRGenerator::CompleteTentativeDefinition(VarDecl *d) {
if (diags.hasErrorOccurred())
return;
cgm->emitTentativeDefinition(d);
}
|