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