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