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/Arith/IR/Arith.h"
16#include "mlir/Dialect/DLTI/DLTI.h"
17#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
18#include "mlir/Dialect/OpenACC/OpenACC.h"
19#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
20#include "mlir/IR/MLIRContext.h"
21
22#include "clang/AST/DeclGroup.h"
29#include "llvm/IR/DataLayout.h"
30
31using namespace cir;
32using namespace clang;
33
34void CIRGenerator::anchor() {}
35
38 const CodeGenOptions &cgo)
39 : diags(diags), fs(std::move(vfs)), codeGenOpts{cgo},
40 handlingTopLevelDecls{0} {}
42 // There should normally not be any leftover inline method definitions.
43 assert(deferredInlineMemberFuncDefs.empty() || diags.hasErrorOccurred());
44}
45
47 using namespace llvm;
48
49 this->astContext = &astContext;
50
51 mlirContext = std::make_unique<mlir::MLIRContext>();
52 // MLIR multithreading stays enabled; the CIRDiagnosticHandler is only ever
53 // invoked from a single thread.
55 mlirContext->loadDialect<mlir::DLTIDialect, mlir::LLVM::LLVMDialect,
56 cir::CIRDialect>();
57 const LangOptions &langOpts = astContext.getLangOpts();
58 // OpenACC lowering emits Arith constants for bounds and clause operands.
59 if (langOpts.OpenACC)
61 ->loadDialect<mlir::acc::OpenACCDialect, mlir::arith::ArithDialect>();
62 if (langOpts.OpenMP)
63 mlirContext->getOrLoadDialect<mlir::omp::OpenMPDialect>();
64
65 cgm = std::make_unique<clang::CIRGen::CIRGenModule>(
66 *mlirContext.get(), astContext, codeGenOpts, diags);
67 mlir::ModuleOp mod = cgm->getModule();
68 llvm::DataLayout layout =
69 llvm::DataLayout(astContext.getTargetInfo().getDataLayoutString());
70 cir::setMLIRDataLayout(mod, layout);
71}
72
73bool CIRGenerator::verifyModule() const { return cgm->verifyModule(); }
74
75mlir::ModuleOp CIRGenerator::getModule() const { return cgm->getModule(); }
76
77const Decl *CIRGenerator::getDeclForMangledName(llvm::StringRef mangledName) {
78 GlobalDecl result;
79 if (!cgm->lookupRepresentativeDecl(mangledName, result))
80 return nullptr;
81 const Decl *decl = result.getCanonicalDecl().getDecl();
82 if (auto *fd = dyn_cast<FunctionDecl>(decl)) {
83 if (fd->hasBody(fd))
84 return fd;
85 } else if (auto *td = dyn_cast<TagDecl>(decl)) {
86 if (auto *def = td->getDefinition())
87 return def;
88 }
89 return decl;
90}
91
93 if (diags.hasUnrecoverableErrorOccurred())
94 return true;
95
96 HandlingTopLevelDeclRAII handlingDecl(*this);
97
98 for (Decl *decl : group)
99 cgm->emitTopLevelDecl(decl);
100
101 return true;
102}
103
105 // Release the Builder when there is no error.
106 if (!diags.hasErrorOccurred() && cgm)
107 cgm->release();
108
109 // If there are errors before or when releasing the cgm, reset the module to
110 // stop here before invoking the backend.
112}
113
115 if (diags.hasErrorOccurred())
116 return;
117
118 assert(d->doesThisDeclarationHaveABody());
119
120 // We may want to emit this definition. However, that decision might be
121 // based on computing the linkage, and we have to defer that in case we are
122 // inside of something that will chagne the method's final linkage, e.g.
123 // typedef struct {
124 // void bar();
125 // void foo() { bar(); }
126 // } A;
127 deferredInlineMemberFuncDefs.push_back(d);
128
129 // Provide some coverage mapping even for methods that aren't emitted.
130 // Don't do this for templated classes though, as they may not be
131 // instantiable.
133}
134
136 if (deferredInlineMemberFuncDefs.empty())
137 return;
138
139 // Emit any deferred inline method definitions. Note that more deferred
140 // methods may be added during this loop, since ASTConsumer callbacks can be
141 // invoked if AST inspection results in declarations being added. Therefore,
142 // we use an index to loop over the deferredInlineMemberFuncDefs rather than
143 // a range.
144 HandlingTopLevelDeclRAII handlingDecls(*this);
145 for (unsigned i = 0; i != deferredInlineMemberFuncDefs.size(); ++i)
146 cgm->emitTopLevelDecl(deferredInlineMemberFuncDefs[i]);
147 deferredInlineMemberFuncDefs.clear();
148}
149
150/// HandleTagDeclDefinition - This callback is invoked each time a TagDecl to
151/// (e.g. struct, union, enum, class) is completed. This allows the client to
152/// hack on the type, which can occur at any point in the file (because these
153/// can be defined in declspecs).
155 if (diags.hasErrorOccurred())
156 return;
157
158 // Don't allow re-entrant calls to CIRGen triggered by PCH deserialization to
159 // emit deferred decls.
160 HandlingTopLevelDeclRAII handlingDecl(*this, /*EmitDeferred=*/false);
161
162 cgm->updateCompletedType(d);
163
164 // For MSVC compatibility, treat declarations of static data members with
165 // inline initializers as definitions.
166 if (astContext->getTargetInfo().getCXXABI().isMicrosoft())
167 cgm->errorNYI(d->getSourceRange(), "HandleTagDeclDefinition: MSABI");
168
169 // For OpenMP emit declare reduction functions or declare mapper, if
170 // required.
171 if (astContext->getLangOpts().OpenMP) {
172 for (Decl *member : d->decls()) {
173 if (auto *drd = dyn_cast<OMPDeclareReductionDecl>(member)) {
174 if (astContext->DeclMustBeEmitted(drd))
175 cgm->errorNYI(d->getSourceRange(),
176 "HandleTagDeclDefinition: OMPDeclareReductionDecl");
177 } else if (auto *dmd = dyn_cast<OMPDeclareMapperDecl>(member)) {
178 if (astContext->DeclMustBeEmitted(dmd))
179 cgm->errorNYI(d->getSourceRange(),
180 "HandleTagDeclDefinition: OMPDeclareMapperDecl");
181 }
182 }
183 }
184}
185
187 if (diags.hasErrorOccurred())
188 return;
189
191}
192
194 if (diags.hasErrorOccurred())
195 return;
196
197 cgm->handleCXXStaticMemberVarInstantiation(D);
198}
199
201 const OpenACCRoutineDecl *RD) {
202 llvm::StringRef mangledName = cgm->getMangledName(FD);
203 cir::FuncOp entry =
204 mlir::dyn_cast_if_present<cir::FuncOp>(cgm->getGlobalValue(mangledName));
205
206 // if this wasn't generated, don't force it to be.
207 if (!entry)
208 return;
209 cgm->emitOpenACCRoutineDecl(FD, entry, RD->getBeginLoc(), RD->clauses());
210}
211
213 if (diags.hasErrorOccurred())
214 return;
215
216 cgm->emitTentativeDefinition(d);
217}
218
220 if (diags.hasErrorOccurred())
221 return;
222
223 cgm->emitVTable(rd);
224}
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:2405
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
SourceLocation getBeginLoc() const LLVM_READONLY
Definition DeclBase.h:440
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:2082
bool doesThisDeclarationHaveABody() const
Returns whether this specific declaration of the function has a body.
Definition Decl.h:2482
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:3898
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:5001
Represents a variable declaration or definition.
Definition Decl.h:934
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()