clang 24.0.0git
CIRGenerator.cpp
Go to the documentation of this file.
1//===--- CIRGenerator.cpp - Emit CIR from ASTs ----------------------------===//
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 builds an AST and converts it to CIR.
10//
11//===----------------------------------------------------------------------===//
12
13#include "CIRGenModule.h"
14
15#include "mlir/Dialect/DLTI/DLTI.h"
16#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
17#include "mlir/Dialect/OpenACC/OpenACC.h"
18#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
19#include "mlir/IR/MLIRContext.h"
20
21#include "clang/AST/DeclGroup.h"
28#include "llvm/IR/DataLayout.h"
29
30using namespace cir;
31using namespace clang;
32
33void CIRGenerator::anchor() {}
34
37 const CodeGenOptions &cgo)
38 : diags(diags), fs(std::move(vfs)), codeGenOpts{cgo},
39 handlingTopLevelDecls{0} {}
41 // There should normally not be any leftover inline method definitions.
42 assert(deferredInlineMemberFuncDefs.empty() || diags.hasErrorOccurred());
43}
44
46 using namespace llvm;
47
48 this->astContext = &astContext;
49
50 mlirContext = std::make_unique<mlir::MLIRContext>();
51 // MLIR multithreading stays enabled; the CIRDiagnosticHandler is only ever
52 // invoked from a single thread.
54 mlirContext->loadDialect<mlir::DLTIDialect, mlir::LLVM::LLVMDialect,
55 cir::CIRDialect>();
56 const LangOptions &langOpts = astContext.getLangOpts();
57 if (langOpts.OpenACC)
58 mlirContext->getOrLoadDialect<mlir::acc::OpenACCDialect>();
59 if (langOpts.OpenMP)
60 mlirContext->getOrLoadDialect<mlir::omp::OpenMPDialect>();
61
62 cgm = std::make_unique<clang::CIRGen::CIRGenModule>(
63 *mlirContext.get(), astContext, codeGenOpts, diags);
64 mlir::ModuleOp mod = cgm->getModule();
65 llvm::DataLayout layout =
66 llvm::DataLayout(astContext.getTargetInfo().getDataLayoutString());
67 cir::setMLIRDataLayout(mod, layout);
68}
69
70bool CIRGenerator::verifyModule() const { return cgm->verifyModule(); }
71
72mlir::ModuleOp CIRGenerator::getModule() const { return cgm->getModule(); }
73
74const Decl *CIRGenerator::getDeclForMangledName(llvm::StringRef mangledName) {
75 GlobalDecl result;
76 if (!cgm->lookupRepresentativeDecl(mangledName, result))
77 return nullptr;
78 const Decl *decl = result.getCanonicalDecl().getDecl();
79 if (auto *fd = dyn_cast<FunctionDecl>(decl)) {
80 if (fd->hasBody(fd))
81 return fd;
82 } else if (auto *td = dyn_cast<TagDecl>(decl)) {
83 if (auto *def = td->getDefinition())
84 return def;
85 }
86 return decl;
87}
88
90 if (diags.hasUnrecoverableErrorOccurred())
91 return true;
92
93 HandlingTopLevelDeclRAII handlingDecl(*this);
94
95 for (Decl *decl : group)
96 cgm->emitTopLevelDecl(decl);
97
98 return true;
99}
100
102 // Release the Builder when there is no error.
103 if (!diags.hasErrorOccurred() && cgm)
104 cgm->release();
105
106 // If there are errors before or when releasing the cgm, reset the module to
107 // stop here before invoking the backend.
109}
110
112 if (diags.hasErrorOccurred())
113 return;
114
115 assert(d->doesThisDeclarationHaveABody());
116
117 // We may want to emit this definition. However, that decision might be
118 // based on computing the linkage, and we have to defer that in case we are
119 // inside of something that will chagne the method's final linkage, e.g.
120 // typedef struct {
121 // void bar();
122 // void foo() { bar(); }
123 // } A;
124 deferredInlineMemberFuncDefs.push_back(d);
125
126 // Provide some coverage mapping even for methods that aren't emitted.
127 // Don't do this for templated classes though, as they may not be
128 // instantiable.
130}
131
133 if (deferredInlineMemberFuncDefs.empty())
134 return;
135
136 // Emit any deferred inline method definitions. Note that more deferred
137 // methods may be added during this loop, since ASTConsumer callbacks can be
138 // invoked if AST inspection results in declarations being added. Therefore,
139 // we use an index to loop over the deferredInlineMemberFuncDefs rather than
140 // a range.
141 HandlingTopLevelDeclRAII handlingDecls(*this);
142 for (unsigned i = 0; i != deferredInlineMemberFuncDefs.size(); ++i)
143 cgm->emitTopLevelDecl(deferredInlineMemberFuncDefs[i]);
144 deferredInlineMemberFuncDefs.clear();
145}
146
147/// HandleTagDeclDefinition - This callback is invoked each time a TagDecl to
148/// (e.g. struct, union, enum, class) is completed. This allows the client to
149/// hack on the type, which can occur at any point in the file (because these
150/// can be defined in declspecs).
152 if (diags.hasErrorOccurred())
153 return;
154
155 // Don't allow re-entrant calls to CIRGen triggered by PCH deserialization to
156 // emit deferred decls.
157 HandlingTopLevelDeclRAII handlingDecl(*this, /*EmitDeferred=*/false);
158
159 cgm->updateCompletedType(d);
160
161 // For MSVC compatibility, treat declarations of static data members with
162 // inline initializers as definitions.
163 if (astContext->getTargetInfo().getCXXABI().isMicrosoft())
164 cgm->errorNYI(d->getSourceRange(), "HandleTagDeclDefinition: MSABI");
165
166 // For OpenMP emit declare reduction functions or declare mapper, if
167 // required.
168 if (astContext->getLangOpts().OpenMP) {
169 for (Decl *member : d->decls()) {
170 if (auto *drd = dyn_cast<OMPDeclareReductionDecl>(member)) {
171 if (astContext->DeclMustBeEmitted(drd))
172 cgm->errorNYI(d->getSourceRange(),
173 "HandleTagDeclDefinition: OMPDeclareReductionDecl");
174 } else if (auto *dmd = dyn_cast<OMPDeclareMapperDecl>(member)) {
175 if (astContext->DeclMustBeEmitted(dmd))
176 cgm->errorNYI(d->getSourceRange(),
177 "HandleTagDeclDefinition: OMPDeclareMapperDecl");
178 }
179 }
180 }
181}
182
184 if (diags.hasErrorOccurred())
185 return;
186
188}
189
191 if (diags.hasErrorOccurred())
192 return;
193
194 cgm->handleCXXStaticMemberVarInstantiation(D);
195}
196
198 const OpenACCRoutineDecl *RD) {
199 llvm::StringRef mangledName = cgm->getMangledName(FD);
200 cir::FuncOp entry =
201 mlir::dyn_cast_if_present<cir::FuncOp>(cgm->getGlobalValue(mangledName));
202
203 // if this wasn't generated, don't force it to be.
204 if (!entry)
205 return;
206 cgm->emitOpenACCRoutineDecl(FD, entry, RD->getBeginLoc(), RD->clauses());
207}
208
210 if (diags.hasErrorOccurred())
211 return;
212
213 cgm->emitTentativeDefinition(d);
214}
215
217 if (diags.hasErrorOccurred())
218 return;
219
220 cgm->emitVTable(rd);
221}
This file defines OpenACC nodes for declarative directives.
void HandleTagDeclDefinition(clang::TagDecl *d) override
HandleTagDeclDefinition - This callback is invoked each time a TagDecl to (e.g.
CIRGenerator(clang::DiagnosticsEngine &diags, llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > fs, const clang::CodeGenOptions &cgo)
mlir::ModuleOp getModule() const
std::unique_ptr< clang::CIRGen::CIRGenModule > cgm
void HandleTranslationUnit(clang::ASTContext &astContext) override
HandleTranslationUnit - This method is called when the ASTs for entire translation unit have been par...
bool verifyModule() const
void HandleVTable(clang::CXXRecordDecl *rd) override
Callback involved at the end of a translation unit to notify the consumer that a vtable for the given...
~CIRGenerator() override
bool HandleTopLevelDecl(clang::DeclGroupRef group) override
HandleTopLevelDecl - Handle the specified top-level declaration.
void CompleteTentativeDefinition(clang::VarDecl *d) override
CompleteTentativeDefinition - Callback invoked at the end of a translation unit to notify the consume...
void HandleTagDeclRequiredDefinition(const clang::TagDecl *D) override
This callback is invoked the first time each TagDecl is required to be complete.
void HandleOpenACCRoutineReference(const clang::FunctionDecl *FD, const clang::OpenACCRoutineDecl *RD) override
Callback to handle the end-of-translation unit attachment of OpenACC routine declaration information.
const clang::Decl * getDeclForMangledName(llvm::StringRef mangledName)
Return the Decl that generated the given mangled name, if known.
void HandleInlineFunctionDefinition(clang::FunctionDecl *d) override
This callback is invoked each time an inline (method or friend) function definition in a class is com...
void HandleCXXStaticMemberVarInstantiation(clang::VarDecl *D) override
HandleCXXStaticMemberVarInstantiation - Tell the consumer that this.
std::unique_ptr< mlir::MLIRContext > mlirContext
void Initialize(clang::ASTContext &astContext) override
Initialize - This is called to initialize the consumer, providing the ASTContext.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:245
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
CodeGenOptions - Track various options which control how the code is optimized and passed to the back...
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Definition DeclBase.h:2417
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
SourceLocation getBeginLoc() const LLVM_READONLY
Definition DeclBase.h:439
Concrete class used by the front-end to report problems and issues.
Definition Diagnostic.h:241
Represents a function declaration or definition.
Definition Decl.h:2059
bool doesThisDeclarationHaveABody() const
Returns whether this specific declaration of the function has a body.
Definition Decl.h:2440
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:60
GlobalDecl getCanonicalDecl() const
Definition GlobalDecl.h:106
const Decl * getDecl() const
Definition GlobalDecl.h:115
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
ArrayRef< const OpenACCClause * > clauses() const
Definition DeclOpenACC.h:62
Represents the declaration of a struct/union/class/enum.
Definition Decl.h:3856
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4972
Represents a variable declaration or definition.
Definition Decl.h:933
void registerAllDialects(mlir::DialectRegistry &registry)
void setMLIRDataLayout(mlir::ModuleOp mod, const llvm::DataLayout &dl)
Translate dl into a DLTI data-layout spec and attach it to mod.
const internal::VariadicAllOfMatcher< Decl > decl
Matches declarations.
Top level wrappers for InstallAPI frontend operations.
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30
static bool coverageMapping()
static bool cleanupAfterErrorDiags()
static bool generateDebugInfo()