xref: /freebsd/contrib/llvm-project/clang/lib/CIR/CodeGen/CIRGenerator.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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