xref: /freebsd/contrib/llvm-project/clang/lib/CIR/CodeGen/CIRGenModule.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1*700637cbSDimitry Andric //===- CIRGenModule.cpp - Per-Module state for CIR generation -------------===//
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 is the internal per-translation-unit state used for CIR translation.
10*700637cbSDimitry Andric //
11*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
12*700637cbSDimitry Andric 
13*700637cbSDimitry Andric #include "CIRGenModule.h"
14*700637cbSDimitry Andric #include "CIRGenCXXABI.h"
15*700637cbSDimitry Andric #include "CIRGenConstantEmitter.h"
16*700637cbSDimitry Andric #include "CIRGenFunction.h"
17*700637cbSDimitry Andric 
18*700637cbSDimitry Andric #include "clang/AST/ASTContext.h"
19*700637cbSDimitry Andric #include "clang/AST/DeclBase.h"
20*700637cbSDimitry Andric #include "clang/AST/DeclOpenACC.h"
21*700637cbSDimitry Andric #include "clang/AST/GlobalDecl.h"
22*700637cbSDimitry Andric #include "clang/AST/RecordLayout.h"
23*700637cbSDimitry Andric #include "clang/Basic/SourceManager.h"
24*700637cbSDimitry Andric #include "clang/CIR/Dialect/IR/CIRDialect.h"
25*700637cbSDimitry Andric #include "clang/CIR/Interfaces/CIROpInterfaces.h"
26*700637cbSDimitry Andric #include "clang/CIR/MissingFeatures.h"
27*700637cbSDimitry Andric 
28*700637cbSDimitry Andric #include "CIRGenFunctionInfo.h"
29*700637cbSDimitry Andric #include "mlir/IR/BuiltinOps.h"
30*700637cbSDimitry Andric #include "mlir/IR/Location.h"
31*700637cbSDimitry Andric #include "mlir/IR/MLIRContext.h"
32*700637cbSDimitry Andric #include "mlir/IR/Verifier.h"
33*700637cbSDimitry Andric 
34*700637cbSDimitry Andric using namespace clang;
35*700637cbSDimitry Andric using namespace clang::CIRGen;
36*700637cbSDimitry Andric 
createCXXABI(CIRGenModule & cgm)37*700637cbSDimitry Andric static CIRGenCXXABI *createCXXABI(CIRGenModule &cgm) {
38*700637cbSDimitry Andric   switch (cgm.getASTContext().getCXXABIKind()) {
39*700637cbSDimitry Andric   case TargetCXXABI::GenericItanium:
40*700637cbSDimitry Andric   case TargetCXXABI::GenericAArch64:
41*700637cbSDimitry Andric   case TargetCXXABI::AppleARM64:
42*700637cbSDimitry Andric     return CreateCIRGenItaniumCXXABI(cgm);
43*700637cbSDimitry Andric 
44*700637cbSDimitry Andric   case TargetCXXABI::Fuchsia:
45*700637cbSDimitry Andric   case TargetCXXABI::GenericARM:
46*700637cbSDimitry Andric   case TargetCXXABI::iOS:
47*700637cbSDimitry Andric   case TargetCXXABI::WatchOS:
48*700637cbSDimitry Andric   case TargetCXXABI::GenericMIPS:
49*700637cbSDimitry Andric   case TargetCXXABI::WebAssembly:
50*700637cbSDimitry Andric   case TargetCXXABI::XL:
51*700637cbSDimitry Andric   case TargetCXXABI::Microsoft:
52*700637cbSDimitry Andric     cgm.errorNYI("C++ ABI kind not yet implemented");
53*700637cbSDimitry Andric     return nullptr;
54*700637cbSDimitry Andric   }
55*700637cbSDimitry Andric 
56*700637cbSDimitry Andric   llvm_unreachable("invalid C++ ABI kind");
57*700637cbSDimitry Andric }
58*700637cbSDimitry Andric 
CIRGenModule(mlir::MLIRContext & mlirContext,clang::ASTContext & astContext,const clang::CodeGenOptions & cgo,DiagnosticsEngine & diags)59*700637cbSDimitry Andric CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,
60*700637cbSDimitry Andric                            clang::ASTContext &astContext,
61*700637cbSDimitry Andric                            const clang::CodeGenOptions &cgo,
62*700637cbSDimitry Andric                            DiagnosticsEngine &diags)
63*700637cbSDimitry Andric     : builder(mlirContext, *this), astContext(astContext),
64*700637cbSDimitry Andric       langOpts(astContext.getLangOpts()), codeGenOpts(cgo),
65*700637cbSDimitry Andric       theModule{mlir::ModuleOp::create(mlir::UnknownLoc::get(&mlirContext))},
66*700637cbSDimitry Andric       diags(diags), target(astContext.getTargetInfo()),
67*700637cbSDimitry Andric       abi(createCXXABI(*this)), genTypes(*this) {
68*700637cbSDimitry Andric 
69*700637cbSDimitry Andric   // Initialize cached types
70*700637cbSDimitry Andric   VoidTy = cir::VoidType::get(&getMLIRContext());
71*700637cbSDimitry Andric   VoidPtrTy = cir::PointerType::get(VoidTy);
72*700637cbSDimitry Andric   SInt8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/true);
73*700637cbSDimitry Andric   SInt16Ty = cir::IntType::get(&getMLIRContext(), 16, /*isSigned=*/true);
74*700637cbSDimitry Andric   SInt32Ty = cir::IntType::get(&getMLIRContext(), 32, /*isSigned=*/true);
75*700637cbSDimitry Andric   SInt64Ty = cir::IntType::get(&getMLIRContext(), 64, /*isSigned=*/true);
76*700637cbSDimitry Andric   SInt128Ty = cir::IntType::get(&getMLIRContext(), 128, /*isSigned=*/true);
77*700637cbSDimitry Andric   UInt8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/false);
78*700637cbSDimitry Andric   UInt16Ty = cir::IntType::get(&getMLIRContext(), 16, /*isSigned=*/false);
79*700637cbSDimitry Andric   UInt32Ty = cir::IntType::get(&getMLIRContext(), 32, /*isSigned=*/false);
80*700637cbSDimitry Andric   UInt64Ty = cir::IntType::get(&getMLIRContext(), 64, /*isSigned=*/false);
81*700637cbSDimitry Andric   UInt128Ty = cir::IntType::get(&getMLIRContext(), 128, /*isSigned=*/false);
82*700637cbSDimitry Andric   FP16Ty = cir::FP16Type::get(&getMLIRContext());
83*700637cbSDimitry Andric   BFloat16Ty = cir::BF16Type::get(&getMLIRContext());
84*700637cbSDimitry Andric   FloatTy = cir::SingleType::get(&getMLIRContext());
85*700637cbSDimitry Andric   DoubleTy = cir::DoubleType::get(&getMLIRContext());
86*700637cbSDimitry Andric   FP80Ty = cir::FP80Type::get(&getMLIRContext());
87*700637cbSDimitry Andric   FP128Ty = cir::FP128Type::get(&getMLIRContext());
88*700637cbSDimitry Andric 
89*700637cbSDimitry Andric   PointerAlignInBytes =
90*700637cbSDimitry Andric       astContext
91*700637cbSDimitry Andric           .toCharUnitsFromBits(
92*700637cbSDimitry Andric               astContext.getTargetInfo().getPointerAlign(LangAS::Default))
93*700637cbSDimitry Andric           .getQuantity();
94*700637cbSDimitry Andric 
95*700637cbSDimitry Andric   // TODO(CIR): Should be updated once TypeSizeInfoAttr is upstreamed
96*700637cbSDimitry Andric   const unsigned sizeTypeSize =
97*700637cbSDimitry Andric       astContext.getTypeSize(astContext.getSignedSizeType());
98*700637cbSDimitry Andric   SizeAlignInBytes = astContext.toCharUnitsFromBits(sizeTypeSize).getQuantity();
99*700637cbSDimitry Andric   // In CIRGenTypeCache, UIntPtrTy and SizeType are fields of the same union
100*700637cbSDimitry Andric   UIntPtrTy =
101*700637cbSDimitry Andric       cir::IntType::get(&getMLIRContext(), sizeTypeSize, /*isSigned=*/false);
102*700637cbSDimitry Andric   PtrDiffTy =
103*700637cbSDimitry Andric       cir::IntType::get(&getMLIRContext(), sizeTypeSize, /*isSigned=*/true);
104*700637cbSDimitry Andric 
105*700637cbSDimitry Andric   theModule->setAttr(cir::CIRDialect::getTripleAttrName(),
106*700637cbSDimitry Andric                      builder.getStringAttr(getTriple().str()));
107*700637cbSDimitry Andric 
108*700637cbSDimitry Andric   if (cgo.OptimizationLevel > 0 || cgo.OptimizeSize > 0)
109*700637cbSDimitry Andric     theModule->setAttr(cir::CIRDialect::getOptInfoAttrName(),
110*700637cbSDimitry Andric                        cir::OptInfoAttr::get(&mlirContext,
111*700637cbSDimitry Andric                                              cgo.OptimizationLevel,
112*700637cbSDimitry Andric                                              cgo.OptimizeSize));
113*700637cbSDimitry Andric }
114*700637cbSDimitry Andric 
115*700637cbSDimitry Andric CIRGenModule::~CIRGenModule() = default;
116*700637cbSDimitry Andric 
117*700637cbSDimitry Andric /// FIXME: this could likely be a common helper and not necessarily related
118*700637cbSDimitry Andric /// with codegen.
119*700637cbSDimitry Andric /// Return the best known alignment for an unknown pointer to a
120*700637cbSDimitry Andric /// particular class.
getClassPointerAlignment(const CXXRecordDecl * rd)121*700637cbSDimitry Andric CharUnits CIRGenModule::getClassPointerAlignment(const CXXRecordDecl *rd) {
122*700637cbSDimitry Andric   if (!rd->hasDefinition())
123*700637cbSDimitry Andric     return CharUnits::One(); // Hopefully won't be used anywhere.
124*700637cbSDimitry Andric 
125*700637cbSDimitry Andric   auto &layout = astContext.getASTRecordLayout(rd);
126*700637cbSDimitry Andric 
127*700637cbSDimitry Andric   // If the class is final, then we know that the pointer points to an
128*700637cbSDimitry Andric   // object of that type and can use the full alignment.
129*700637cbSDimitry Andric   if (rd->isEffectivelyFinal())
130*700637cbSDimitry Andric     return layout.getAlignment();
131*700637cbSDimitry Andric 
132*700637cbSDimitry Andric   // Otherwise, we have to assume it could be a subclass.
133*700637cbSDimitry Andric   return layout.getNonVirtualAlignment();
134*700637cbSDimitry Andric }
135*700637cbSDimitry Andric 
getNaturalTypeAlignment(QualType t,LValueBaseInfo * baseInfo)136*700637cbSDimitry Andric CharUnits CIRGenModule::getNaturalTypeAlignment(QualType t,
137*700637cbSDimitry Andric                                                 LValueBaseInfo *baseInfo) {
138*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opTBAA());
139*700637cbSDimitry Andric 
140*700637cbSDimitry Andric   // FIXME: This duplicates logic in ASTContext::getTypeAlignIfKnown, but
141*700637cbSDimitry Andric   // that doesn't return the information we need to compute baseInfo.
142*700637cbSDimitry Andric 
143*700637cbSDimitry Andric   // Honor alignment typedef attributes even on incomplete types.
144*700637cbSDimitry Andric   // We also honor them straight for C++ class types, even as pointees;
145*700637cbSDimitry Andric   // there's an expressivity gap here.
146*700637cbSDimitry Andric   if (const auto *tt = t->getAs<TypedefType>()) {
147*700637cbSDimitry Andric     if (unsigned align = tt->getDecl()->getMaxAlignment()) {
148*700637cbSDimitry Andric       if (baseInfo)
149*700637cbSDimitry Andric         *baseInfo = LValueBaseInfo(AlignmentSource::AttributedType);
150*700637cbSDimitry Andric       return astContext.toCharUnitsFromBits(align);
151*700637cbSDimitry Andric     }
152*700637cbSDimitry Andric   }
153*700637cbSDimitry Andric 
154*700637cbSDimitry Andric   // Analyze the base element type, so we don't get confused by incomplete
155*700637cbSDimitry Andric   // array types.
156*700637cbSDimitry Andric   t = astContext.getBaseElementType(t);
157*700637cbSDimitry Andric 
158*700637cbSDimitry Andric   if (t->isIncompleteType()) {
159*700637cbSDimitry Andric     // We could try to replicate the logic from
160*700637cbSDimitry Andric     // ASTContext::getTypeAlignIfKnown, but nothing uses the alignment if the
161*700637cbSDimitry Andric     // type is incomplete, so it's impossible to test. We could try to reuse
162*700637cbSDimitry Andric     // getTypeAlignIfKnown, but that doesn't return the information we need
163*700637cbSDimitry Andric     // to set baseInfo.  So just ignore the possibility that the alignment is
164*700637cbSDimitry Andric     // greater than one.
165*700637cbSDimitry Andric     if (baseInfo)
166*700637cbSDimitry Andric       *baseInfo = LValueBaseInfo(AlignmentSource::Type);
167*700637cbSDimitry Andric     return CharUnits::One();
168*700637cbSDimitry Andric   }
169*700637cbSDimitry Andric 
170*700637cbSDimitry Andric   if (baseInfo)
171*700637cbSDimitry Andric     *baseInfo = LValueBaseInfo(AlignmentSource::Type);
172*700637cbSDimitry Andric 
173*700637cbSDimitry Andric   CharUnits alignment;
174*700637cbSDimitry Andric   if (t.getQualifiers().hasUnaligned()) {
175*700637cbSDimitry Andric     alignment = CharUnits::One();
176*700637cbSDimitry Andric   } else {
177*700637cbSDimitry Andric     assert(!cir::MissingFeatures::alignCXXRecordDecl());
178*700637cbSDimitry Andric     alignment = astContext.getTypeAlignInChars(t);
179*700637cbSDimitry Andric   }
180*700637cbSDimitry Andric 
181*700637cbSDimitry Andric   // Cap to the global maximum type alignment unless the alignment
182*700637cbSDimitry Andric   // was somehow explicit on the type.
183*700637cbSDimitry Andric   if (unsigned maxAlign = astContext.getLangOpts().MaxTypeAlign) {
184*700637cbSDimitry Andric     if (alignment.getQuantity() > maxAlign &&
185*700637cbSDimitry Andric         !astContext.isAlignmentRequired(t))
186*700637cbSDimitry Andric       alignment = CharUnits::fromQuantity(maxAlign);
187*700637cbSDimitry Andric   }
188*700637cbSDimitry Andric   return alignment;
189*700637cbSDimitry Andric }
190*700637cbSDimitry Andric 
getTargetCIRGenInfo()191*700637cbSDimitry Andric const TargetCIRGenInfo &CIRGenModule::getTargetCIRGenInfo() {
192*700637cbSDimitry Andric   if (theTargetCIRGenInfo)
193*700637cbSDimitry Andric     return *theTargetCIRGenInfo;
194*700637cbSDimitry Andric 
195*700637cbSDimitry Andric   const llvm::Triple &triple = getTarget().getTriple();
196*700637cbSDimitry Andric   switch (triple.getArch()) {
197*700637cbSDimitry Andric   default:
198*700637cbSDimitry Andric     assert(!cir::MissingFeatures::targetCIRGenInfoArch());
199*700637cbSDimitry Andric 
200*700637cbSDimitry Andric     // Currently we just fall through to x86_64.
201*700637cbSDimitry Andric     [[fallthrough]];
202*700637cbSDimitry Andric 
203*700637cbSDimitry Andric   case llvm::Triple::x86_64: {
204*700637cbSDimitry Andric     switch (triple.getOS()) {
205*700637cbSDimitry Andric     default:
206*700637cbSDimitry Andric       assert(!cir::MissingFeatures::targetCIRGenInfoOS());
207*700637cbSDimitry Andric 
208*700637cbSDimitry Andric       // Currently we just fall through to x86_64.
209*700637cbSDimitry Andric       [[fallthrough]];
210*700637cbSDimitry Andric 
211*700637cbSDimitry Andric     case llvm::Triple::Linux:
212*700637cbSDimitry Andric       theTargetCIRGenInfo = createX8664TargetCIRGenInfo(genTypes);
213*700637cbSDimitry Andric       return *theTargetCIRGenInfo;
214*700637cbSDimitry Andric     }
215*700637cbSDimitry Andric   }
216*700637cbSDimitry Andric   }
217*700637cbSDimitry Andric }
218*700637cbSDimitry Andric 
getLoc(SourceLocation cLoc)219*700637cbSDimitry Andric mlir::Location CIRGenModule::getLoc(SourceLocation cLoc) {
220*700637cbSDimitry Andric   assert(cLoc.isValid() && "expected valid source location");
221*700637cbSDimitry Andric   const SourceManager &sm = astContext.getSourceManager();
222*700637cbSDimitry Andric   PresumedLoc pLoc = sm.getPresumedLoc(cLoc);
223*700637cbSDimitry Andric   StringRef filename = pLoc.getFilename();
224*700637cbSDimitry Andric   return mlir::FileLineColLoc::get(builder.getStringAttr(filename),
225*700637cbSDimitry Andric                                    pLoc.getLine(), pLoc.getColumn());
226*700637cbSDimitry Andric }
227*700637cbSDimitry Andric 
getLoc(SourceRange cRange)228*700637cbSDimitry Andric mlir::Location CIRGenModule::getLoc(SourceRange cRange) {
229*700637cbSDimitry Andric   assert(cRange.isValid() && "expected a valid source range");
230*700637cbSDimitry Andric   mlir::Location begin = getLoc(cRange.getBegin());
231*700637cbSDimitry Andric   mlir::Location end = getLoc(cRange.getEnd());
232*700637cbSDimitry Andric   mlir::Attribute metadata;
233*700637cbSDimitry Andric   return mlir::FusedLoc::get({begin, end}, metadata, builder.getContext());
234*700637cbSDimitry Andric }
235*700637cbSDimitry Andric 
236*700637cbSDimitry Andric mlir::Operation *
getAddrOfGlobal(GlobalDecl gd,ForDefinition_t isForDefinition)237*700637cbSDimitry Andric CIRGenModule::getAddrOfGlobal(GlobalDecl gd, ForDefinition_t isForDefinition) {
238*700637cbSDimitry Andric   const Decl *d = gd.getDecl();
239*700637cbSDimitry Andric 
240*700637cbSDimitry Andric   if (isa<CXXConstructorDecl>(d) || isa<CXXDestructorDecl>(d))
241*700637cbSDimitry Andric     return getAddrOfCXXStructor(gd, /*FnInfo=*/nullptr, /*FnType=*/nullptr,
242*700637cbSDimitry Andric                                 /*DontDefer=*/false, isForDefinition);
243*700637cbSDimitry Andric 
244*700637cbSDimitry Andric   if (isa<CXXMethodDecl>(d)) {
245*700637cbSDimitry Andric     const CIRGenFunctionInfo &fi =
246*700637cbSDimitry Andric         getTypes().arrangeCXXMethodDeclaration(cast<CXXMethodDecl>(d));
247*700637cbSDimitry Andric     cir::FuncType ty = getTypes().getFunctionType(fi);
248*700637cbSDimitry Andric     return getAddrOfFunction(gd, ty, /*ForVTable=*/false, /*DontDefer=*/false,
249*700637cbSDimitry Andric                              isForDefinition);
250*700637cbSDimitry Andric   }
251*700637cbSDimitry Andric 
252*700637cbSDimitry Andric   if (isa<FunctionDecl>(d)) {
253*700637cbSDimitry Andric     const CIRGenFunctionInfo &fi = getTypes().arrangeGlobalDeclaration(gd);
254*700637cbSDimitry Andric     cir::FuncType ty = getTypes().getFunctionType(fi);
255*700637cbSDimitry Andric     return getAddrOfFunction(gd, ty, /*ForVTable=*/false, /*DontDefer=*/false,
256*700637cbSDimitry Andric                              isForDefinition);
257*700637cbSDimitry Andric   }
258*700637cbSDimitry Andric 
259*700637cbSDimitry Andric   return getAddrOfGlobalVar(cast<VarDecl>(d), /*ty=*/nullptr, isForDefinition)
260*700637cbSDimitry Andric       .getDefiningOp();
261*700637cbSDimitry Andric }
262*700637cbSDimitry Andric 
emitGlobalDecl(const clang::GlobalDecl & d)263*700637cbSDimitry Andric void CIRGenModule::emitGlobalDecl(const clang::GlobalDecl &d) {
264*700637cbSDimitry Andric   // We call getAddrOfGlobal with isForDefinition set to ForDefinition in
265*700637cbSDimitry Andric   // order to get a Value with exactly the type we need, not something that
266*700637cbSDimitry Andric   // might have been created for another decl with the same mangled name but
267*700637cbSDimitry Andric   // different type.
268*700637cbSDimitry Andric   mlir::Operation *op = getAddrOfGlobal(d, ForDefinition);
269*700637cbSDimitry Andric 
270*700637cbSDimitry Andric   // In case of different address spaces, we may still get a cast, even with
271*700637cbSDimitry Andric   // IsForDefinition equal to ForDefinition. Query mangled names table to get
272*700637cbSDimitry Andric   // GlobalValue.
273*700637cbSDimitry Andric   if (!op)
274*700637cbSDimitry Andric     op = getGlobalValue(getMangledName(d));
275*700637cbSDimitry Andric 
276*700637cbSDimitry Andric   assert(op && "expected a valid global op");
277*700637cbSDimitry Andric 
278*700637cbSDimitry Andric   // Check to see if we've already emitted this. This is necessary for a
279*700637cbSDimitry Andric   // couple of reasons: first, decls can end up in deferred-decls queue
280*700637cbSDimitry Andric   // multiple times, and second, decls can end up with definitions in unusual
281*700637cbSDimitry Andric   // ways (e.g. by an extern inline function acquiring a strong function
282*700637cbSDimitry Andric   // redefinition). Just ignore those cases.
283*700637cbSDimitry Andric   // TODO: Not sure what to map this to for MLIR
284*700637cbSDimitry Andric   mlir::Operation *globalValueOp = op;
285*700637cbSDimitry Andric   if (auto gv = dyn_cast<cir::GetGlobalOp>(op))
286*700637cbSDimitry Andric     globalValueOp =
287*700637cbSDimitry Andric         mlir::SymbolTable::lookupSymbolIn(getModule(), gv.getNameAttr());
288*700637cbSDimitry Andric 
289*700637cbSDimitry Andric   if (auto cirGlobalValue =
290*700637cbSDimitry Andric           dyn_cast<cir::CIRGlobalValueInterface>(globalValueOp))
291*700637cbSDimitry Andric     if (!cirGlobalValue.isDeclaration())
292*700637cbSDimitry Andric       return;
293*700637cbSDimitry Andric 
294*700637cbSDimitry Andric   // If this is OpenMP, check if it is legal to emit this global normally.
295*700637cbSDimitry Andric   assert(!cir::MissingFeatures::openMP());
296*700637cbSDimitry Andric 
297*700637cbSDimitry Andric   // Otherwise, emit the definition and move on to the next one.
298*700637cbSDimitry Andric   emitGlobalDefinition(d, op);
299*700637cbSDimitry Andric }
300*700637cbSDimitry Andric 
emitDeferred()301*700637cbSDimitry Andric void CIRGenModule::emitDeferred() {
302*700637cbSDimitry Andric   // Emit code for any potentially referenced deferred decls. Since a previously
303*700637cbSDimitry Andric   // unused static decl may become used during the generation of code for a
304*700637cbSDimitry Andric   // static function, iterate until no changes are made.
305*700637cbSDimitry Andric 
306*700637cbSDimitry Andric   assert(!cir::MissingFeatures::openMP());
307*700637cbSDimitry Andric   assert(!cir::MissingFeatures::deferredVtables());
308*700637cbSDimitry Andric   assert(!cir::MissingFeatures::cudaSupport());
309*700637cbSDimitry Andric 
310*700637cbSDimitry Andric   // Stop if we're out of both deferred vtables and deferred declarations.
311*700637cbSDimitry Andric   if (deferredDeclsToEmit.empty())
312*700637cbSDimitry Andric     return;
313*700637cbSDimitry Andric 
314*700637cbSDimitry Andric   // Grab the list of decls to emit. If emitGlobalDefinition schedules more
315*700637cbSDimitry Andric   // work, it will not interfere with this.
316*700637cbSDimitry Andric   std::vector<GlobalDecl> curDeclsToEmit;
317*700637cbSDimitry Andric   curDeclsToEmit.swap(deferredDeclsToEmit);
318*700637cbSDimitry Andric 
319*700637cbSDimitry Andric   for (const GlobalDecl &d : curDeclsToEmit) {
320*700637cbSDimitry Andric     emitGlobalDecl(d);
321*700637cbSDimitry Andric 
322*700637cbSDimitry Andric     // If we found out that we need to emit more decls, do that recursively.
323*700637cbSDimitry Andric     // This has the advantage that the decls are emitted in a DFS and related
324*700637cbSDimitry Andric     // ones are close together, which is convenient for testing.
325*700637cbSDimitry Andric     if (!deferredDeclsToEmit.empty()) {
326*700637cbSDimitry Andric       emitDeferred();
327*700637cbSDimitry Andric       assert(deferredDeclsToEmit.empty());
328*700637cbSDimitry Andric     }
329*700637cbSDimitry Andric   }
330*700637cbSDimitry Andric }
331*700637cbSDimitry Andric 
emitGlobal(clang::GlobalDecl gd)332*700637cbSDimitry Andric void CIRGenModule::emitGlobal(clang::GlobalDecl gd) {
333*700637cbSDimitry Andric   if (const auto *cd = dyn_cast<clang::OpenACCConstructDecl>(gd.getDecl())) {
334*700637cbSDimitry Andric     emitGlobalOpenACCDecl(cd);
335*700637cbSDimitry Andric     return;
336*700637cbSDimitry Andric   }
337*700637cbSDimitry Andric 
338*700637cbSDimitry Andric   const auto *global = cast<ValueDecl>(gd.getDecl());
339*700637cbSDimitry Andric 
340*700637cbSDimitry Andric   if (const auto *fd = dyn_cast<FunctionDecl>(global)) {
341*700637cbSDimitry Andric     // Update deferred annotations with the latest declaration if the function
342*700637cbSDimitry Andric     // was already used or defined.
343*700637cbSDimitry Andric     if (fd->hasAttr<AnnotateAttr>())
344*700637cbSDimitry Andric       errorNYI(fd->getSourceRange(), "deferredAnnotations");
345*700637cbSDimitry Andric     if (!fd->doesThisDeclarationHaveABody()) {
346*700637cbSDimitry Andric       if (!fd->doesDeclarationForceExternallyVisibleDefinition())
347*700637cbSDimitry Andric         return;
348*700637cbSDimitry Andric 
349*700637cbSDimitry Andric       errorNYI(fd->getSourceRange(),
350*700637cbSDimitry Andric                "function declaration that forces code gen");
351*700637cbSDimitry Andric       return;
352*700637cbSDimitry Andric     }
353*700637cbSDimitry Andric   } else {
354*700637cbSDimitry Andric     const auto *vd = cast<VarDecl>(global);
355*700637cbSDimitry Andric     assert(vd->isFileVarDecl() && "Cannot emit local var decl as global.");
356*700637cbSDimitry Andric     if (vd->isThisDeclarationADefinition() != VarDecl::Definition &&
357*700637cbSDimitry Andric         !astContext.isMSStaticDataMemberInlineDefinition(vd)) {
358*700637cbSDimitry Andric       assert(!cir::MissingFeatures::openMP());
359*700637cbSDimitry Andric       // If this declaration may have caused an inline variable definition to
360*700637cbSDimitry Andric       // change linkage, make sure that it's emitted.
361*700637cbSDimitry Andric       if (astContext.getInlineVariableDefinitionKind(vd) ==
362*700637cbSDimitry Andric           ASTContext::InlineVariableDefinitionKind::Strong)
363*700637cbSDimitry Andric         getAddrOfGlobalVar(vd);
364*700637cbSDimitry Andric       // Otherwise, we can ignore this declaration. The variable will be emitted
365*700637cbSDimitry Andric       // on its first use.
366*700637cbSDimitry Andric       return;
367*700637cbSDimitry Andric     }
368*700637cbSDimitry Andric   }
369*700637cbSDimitry Andric 
370*700637cbSDimitry Andric   // Defer code generation to first use when possible, e.g. if this is an inline
371*700637cbSDimitry Andric   // function. If the global must always be emitted, do it eagerly if possible
372*700637cbSDimitry Andric   // to benefit from cache locality. Deferring code generation is necessary to
373*700637cbSDimitry Andric   // avoid adding initializers to external declarations.
374*700637cbSDimitry Andric   if (mustBeEmitted(global) && mayBeEmittedEagerly(global)) {
375*700637cbSDimitry Andric     // Emit the definition if it can't be deferred.
376*700637cbSDimitry Andric     emitGlobalDefinition(gd);
377*700637cbSDimitry Andric     return;
378*700637cbSDimitry Andric   }
379*700637cbSDimitry Andric 
380*700637cbSDimitry Andric   // If we're deferring emission of a C++ variable with an initializer, remember
381*700637cbSDimitry Andric   // the order in which it appeared on the file.
382*700637cbSDimitry Andric   assert(!cir::MissingFeatures::deferredCXXGlobalInit());
383*700637cbSDimitry Andric 
384*700637cbSDimitry Andric   llvm::StringRef mangledName = getMangledName(gd);
385*700637cbSDimitry Andric   if (getGlobalValue(mangledName) != nullptr) {
386*700637cbSDimitry Andric     // The value has already been used and should therefore be emitted.
387*700637cbSDimitry Andric     addDeferredDeclToEmit(gd);
388*700637cbSDimitry Andric   } else if (mustBeEmitted(global)) {
389*700637cbSDimitry Andric     // The value must be emitted, but cannot be emitted eagerly.
390*700637cbSDimitry Andric     assert(!mayBeEmittedEagerly(global));
391*700637cbSDimitry Andric     addDeferredDeclToEmit(gd);
392*700637cbSDimitry Andric   } else {
393*700637cbSDimitry Andric     // Otherwise, remember that we saw a deferred decl with this name. The first
394*700637cbSDimitry Andric     // use of the mangled name will cause it to move into deferredDeclsToEmit.
395*700637cbSDimitry Andric     deferredDecls[mangledName] = gd;
396*700637cbSDimitry Andric   }
397*700637cbSDimitry Andric }
398*700637cbSDimitry Andric 
emitGlobalFunctionDefinition(clang::GlobalDecl gd,mlir::Operation * op)399*700637cbSDimitry Andric void CIRGenModule::emitGlobalFunctionDefinition(clang::GlobalDecl gd,
400*700637cbSDimitry Andric                                                 mlir::Operation *op) {
401*700637cbSDimitry Andric   auto const *funcDecl = cast<FunctionDecl>(gd.getDecl());
402*700637cbSDimitry Andric   const CIRGenFunctionInfo &fi = getTypes().arrangeGlobalDeclaration(gd);
403*700637cbSDimitry Andric   cir::FuncType funcType = getTypes().getFunctionType(fi);
404*700637cbSDimitry Andric   cir::FuncOp funcOp = dyn_cast_if_present<cir::FuncOp>(op);
405*700637cbSDimitry Andric   if (!funcOp || funcOp.getFunctionType() != funcType) {
406*700637cbSDimitry Andric     funcOp = getAddrOfFunction(gd, funcType, /*ForVTable=*/false,
407*700637cbSDimitry Andric                                /*DontDefer=*/true, ForDefinition);
408*700637cbSDimitry Andric   }
409*700637cbSDimitry Andric 
410*700637cbSDimitry Andric   // Already emitted.
411*700637cbSDimitry Andric   if (!funcOp.isDeclaration())
412*700637cbSDimitry Andric     return;
413*700637cbSDimitry Andric 
414*700637cbSDimitry Andric   setFunctionLinkage(gd, funcOp);
415*700637cbSDimitry Andric   setGVProperties(funcOp, funcDecl);
416*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opFuncMaybeHandleStaticInExternC());
417*700637cbSDimitry Andric   maybeSetTrivialComdat(*funcDecl, funcOp);
418*700637cbSDimitry Andric   assert(!cir::MissingFeatures::setLLVMFunctionFEnvAttributes());
419*700637cbSDimitry Andric 
420*700637cbSDimitry Andric   CIRGenFunction cgf(*this, builder);
421*700637cbSDimitry Andric   curCGF = &cgf;
422*700637cbSDimitry Andric   {
423*700637cbSDimitry Andric     mlir::OpBuilder::InsertionGuard guard(builder);
424*700637cbSDimitry Andric     cgf.generateCode(gd, funcOp, funcType);
425*700637cbSDimitry Andric   }
426*700637cbSDimitry Andric   curCGF = nullptr;
427*700637cbSDimitry Andric 
428*700637cbSDimitry Andric   setNonAliasAttributes(gd, funcOp);
429*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opFuncAttributesForDefinition());
430*700637cbSDimitry Andric 
431*700637cbSDimitry Andric   if (funcDecl->getAttr<ConstructorAttr>())
432*700637cbSDimitry Andric     errorNYI(funcDecl->getSourceRange(), "constructor attribute");
433*700637cbSDimitry Andric   if (funcDecl->getAttr<DestructorAttr>())
434*700637cbSDimitry Andric     errorNYI(funcDecl->getSourceRange(), "destructor attribute");
435*700637cbSDimitry Andric 
436*700637cbSDimitry Andric   if (funcDecl->getAttr<AnnotateAttr>())
437*700637cbSDimitry Andric     errorNYI(funcDecl->getSourceRange(), "deferredAnnotations");
438*700637cbSDimitry Andric }
439*700637cbSDimitry Andric 
getGlobalValue(StringRef name)440*700637cbSDimitry Andric mlir::Operation *CIRGenModule::getGlobalValue(StringRef name) {
441*700637cbSDimitry Andric   return mlir::SymbolTable::lookupSymbolIn(theModule, name);
442*700637cbSDimitry Andric }
443*700637cbSDimitry Andric 
createGlobalOp(CIRGenModule & cgm,mlir::Location loc,StringRef name,mlir::Type t,mlir::Operation * insertPoint)444*700637cbSDimitry Andric cir::GlobalOp CIRGenModule::createGlobalOp(CIRGenModule &cgm,
445*700637cbSDimitry Andric                                            mlir::Location loc, StringRef name,
446*700637cbSDimitry Andric                                            mlir::Type t,
447*700637cbSDimitry Andric                                            mlir::Operation *insertPoint) {
448*700637cbSDimitry Andric   cir::GlobalOp g;
449*700637cbSDimitry Andric   CIRGenBuilderTy &builder = cgm.getBuilder();
450*700637cbSDimitry Andric 
451*700637cbSDimitry Andric   {
452*700637cbSDimitry Andric     mlir::OpBuilder::InsertionGuard guard(builder);
453*700637cbSDimitry Andric 
454*700637cbSDimitry Andric     // If an insertion point is provided, we're replacing an existing global,
455*700637cbSDimitry Andric     // otherwise, create the new global immediately after the last gloabl we
456*700637cbSDimitry Andric     // emitted.
457*700637cbSDimitry Andric     if (insertPoint) {
458*700637cbSDimitry Andric       builder.setInsertionPoint(insertPoint);
459*700637cbSDimitry Andric     } else {
460*700637cbSDimitry Andric       // Group global operations together at the top of the module.
461*700637cbSDimitry Andric       if (cgm.lastGlobalOp)
462*700637cbSDimitry Andric         builder.setInsertionPointAfter(cgm.lastGlobalOp);
463*700637cbSDimitry Andric       else
464*700637cbSDimitry Andric         builder.setInsertionPointToStart(cgm.getModule().getBody());
465*700637cbSDimitry Andric     }
466*700637cbSDimitry Andric 
467*700637cbSDimitry Andric     g = builder.create<cir::GlobalOp>(loc, name, t);
468*700637cbSDimitry Andric     if (!insertPoint)
469*700637cbSDimitry Andric       cgm.lastGlobalOp = g;
470*700637cbSDimitry Andric 
471*700637cbSDimitry Andric     // Default to private until we can judge based on the initializer,
472*700637cbSDimitry Andric     // since MLIR doesn't allow public declarations.
473*700637cbSDimitry Andric     mlir::SymbolTable::setSymbolVisibility(
474*700637cbSDimitry Andric         g, mlir::SymbolTable::Visibility::Private);
475*700637cbSDimitry Andric   }
476*700637cbSDimitry Andric   return g;
477*700637cbSDimitry Andric }
478*700637cbSDimitry Andric 
setCommonAttributes(GlobalDecl gd,mlir::Operation * gv)479*700637cbSDimitry Andric void CIRGenModule::setCommonAttributes(GlobalDecl gd, mlir::Operation *gv) {
480*700637cbSDimitry Andric   const Decl *d = gd.getDecl();
481*700637cbSDimitry Andric   if (isa_and_nonnull<NamedDecl>(d))
482*700637cbSDimitry Andric     setGVProperties(gv, dyn_cast<NamedDecl>(d));
483*700637cbSDimitry Andric   assert(!cir::MissingFeatures::defaultVisibility());
484*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opGlobalUsedOrCompilerUsed());
485*700637cbSDimitry Andric }
486*700637cbSDimitry Andric 
setNonAliasAttributes(GlobalDecl gd,mlir::Operation * op)487*700637cbSDimitry Andric void CIRGenModule::setNonAliasAttributes(GlobalDecl gd, mlir::Operation *op) {
488*700637cbSDimitry Andric   setCommonAttributes(gd, op);
489*700637cbSDimitry Andric 
490*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opGlobalUsedOrCompilerUsed());
491*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opGlobalSection());
492*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opFuncCPUAndFeaturesAttributes());
493*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opFuncSection());
494*700637cbSDimitry Andric 
495*700637cbSDimitry Andric   assert(!cir::MissingFeatures::setTargetAttributes());
496*700637cbSDimitry Andric }
497*700637cbSDimitry Andric 
setLinkageForGV(cir::GlobalOp & gv,const NamedDecl * nd)498*700637cbSDimitry Andric static void setLinkageForGV(cir::GlobalOp &gv, const NamedDecl *nd) {
499*700637cbSDimitry Andric   // Set linkage and visibility in case we never see a definition.
500*700637cbSDimitry Andric   LinkageInfo lv = nd->getLinkageAndVisibility();
501*700637cbSDimitry Andric   // Don't set internal linkage on declarations.
502*700637cbSDimitry Andric   // "extern_weak" is overloaded in LLVM; we probably should have
503*700637cbSDimitry Andric   // separate linkage types for this.
504*700637cbSDimitry Andric   if (isExternallyVisible(lv.getLinkage()) &&
505*700637cbSDimitry Andric       (nd->hasAttr<WeakAttr>() || nd->isWeakImported()))
506*700637cbSDimitry Andric     gv.setLinkage(cir::GlobalLinkageKind::ExternalWeakLinkage);
507*700637cbSDimitry Andric }
508*700637cbSDimitry Andric 
509*700637cbSDimitry Andric /// If the specified mangled name is not in the module,
510*700637cbSDimitry Andric /// create and return an mlir GlobalOp with the specified type (TODO(cir):
511*700637cbSDimitry Andric /// address space).
512*700637cbSDimitry Andric ///
513*700637cbSDimitry Andric /// TODO(cir):
514*700637cbSDimitry Andric /// 1. If there is something in the module with the specified name, return
515*700637cbSDimitry Andric /// it potentially bitcasted to the right type.
516*700637cbSDimitry Andric ///
517*700637cbSDimitry Andric /// 2. If \p d is non-null, it specifies a decl that correspond to this.  This
518*700637cbSDimitry Andric /// is used to set the attributes on the global when it is first created.
519*700637cbSDimitry Andric ///
520*700637cbSDimitry Andric /// 3. If \p isForDefinition is true, it is guaranteed that an actual global
521*700637cbSDimitry Andric /// with type \p ty will be returned, not conversion of a variable with the same
522*700637cbSDimitry Andric /// mangled name but some other type.
523*700637cbSDimitry Andric cir::GlobalOp
getOrCreateCIRGlobal(StringRef mangledName,mlir::Type ty,LangAS langAS,const VarDecl * d,ForDefinition_t isForDefinition)524*700637cbSDimitry Andric CIRGenModule::getOrCreateCIRGlobal(StringRef mangledName, mlir::Type ty,
525*700637cbSDimitry Andric                                    LangAS langAS, const VarDecl *d,
526*700637cbSDimitry Andric                                    ForDefinition_t isForDefinition) {
527*700637cbSDimitry Andric   // Lookup the entry, lazily creating it if necessary.
528*700637cbSDimitry Andric   cir::GlobalOp entry;
529*700637cbSDimitry Andric   if (mlir::Operation *v = getGlobalValue(mangledName)) {
530*700637cbSDimitry Andric     if (!isa<cir::GlobalOp>(v))
531*700637cbSDimitry Andric       errorNYI(d->getSourceRange(), "global with non-GlobalOp type");
532*700637cbSDimitry Andric     entry = cast<cir::GlobalOp>(v);
533*700637cbSDimitry Andric   }
534*700637cbSDimitry Andric 
535*700637cbSDimitry Andric   if (entry) {
536*700637cbSDimitry Andric     assert(!cir::MissingFeatures::addressSpace());
537*700637cbSDimitry Andric     assert(!cir::MissingFeatures::opGlobalWeakRef());
538*700637cbSDimitry Andric 
539*700637cbSDimitry Andric     assert(!cir::MissingFeatures::setDLLStorageClass());
540*700637cbSDimitry Andric     assert(!cir::MissingFeatures::openMP());
541*700637cbSDimitry Andric 
542*700637cbSDimitry Andric     if (entry.getSymType() == ty)
543*700637cbSDimitry Andric       return entry;
544*700637cbSDimitry Andric 
545*700637cbSDimitry Andric     // If there are two attempts to define the same mangled name, issue an
546*700637cbSDimitry Andric     // error.
547*700637cbSDimitry Andric     //
548*700637cbSDimitry Andric     // TODO(cir): look at mlir::GlobalValue::isDeclaration for all aspects of
549*700637cbSDimitry Andric     // recognizing the global as a declaration, for now only check if
550*700637cbSDimitry Andric     // initializer is present.
551*700637cbSDimitry Andric     if (isForDefinition && !entry.isDeclaration()) {
552*700637cbSDimitry Andric       errorNYI(d->getSourceRange(), "global with conflicting type");
553*700637cbSDimitry Andric     }
554*700637cbSDimitry Andric 
555*700637cbSDimitry Andric     // Address space check removed because it is unnecessary because CIR records
556*700637cbSDimitry Andric     // address space info in types.
557*700637cbSDimitry Andric 
558*700637cbSDimitry Andric     // (If global is requested for a definition, we always need to create a new
559*700637cbSDimitry Andric     // global, not just return a bitcast.)
560*700637cbSDimitry Andric     if (!isForDefinition)
561*700637cbSDimitry Andric       return entry;
562*700637cbSDimitry Andric   }
563*700637cbSDimitry Andric 
564*700637cbSDimitry Andric   mlir::Location loc = getLoc(d->getSourceRange());
565*700637cbSDimitry Andric 
566*700637cbSDimitry Andric   // mlir::SymbolTable::Visibility::Public is the default, no need to explicitly
567*700637cbSDimitry Andric   // mark it as such.
568*700637cbSDimitry Andric   cir::GlobalOp gv =
569*700637cbSDimitry Andric       CIRGenModule::createGlobalOp(*this, loc, mangledName, ty,
570*700637cbSDimitry Andric                                    /*insertPoint=*/entry.getOperation());
571*700637cbSDimitry Andric 
572*700637cbSDimitry Andric   // This is the first use or definition of a mangled name.  If there is a
573*700637cbSDimitry Andric   // deferred decl with this name, remember that we need to emit it at the end
574*700637cbSDimitry Andric   // of the file.
575*700637cbSDimitry Andric   auto ddi = deferredDecls.find(mangledName);
576*700637cbSDimitry Andric   if (ddi != deferredDecls.end()) {
577*700637cbSDimitry Andric     // Move the potentially referenced deferred decl to the DeferredDeclsToEmit
578*700637cbSDimitry Andric     // list, and remove it from DeferredDecls (since we don't need it anymore).
579*700637cbSDimitry Andric     addDeferredDeclToEmit(ddi->second);
580*700637cbSDimitry Andric     deferredDecls.erase(ddi);
581*700637cbSDimitry Andric   }
582*700637cbSDimitry Andric 
583*700637cbSDimitry Andric   // Handle things which are present even on external declarations.
584*700637cbSDimitry Andric   if (d) {
585*700637cbSDimitry Andric     if (langOpts.OpenMP && !langOpts.OpenMPSimd)
586*700637cbSDimitry Andric       errorNYI(d->getSourceRange(), "OpenMP target global variable");
587*700637cbSDimitry Andric 
588*700637cbSDimitry Andric     gv.setAlignmentAttr(getSize(astContext.getDeclAlign(d)));
589*700637cbSDimitry Andric     assert(!cir::MissingFeatures::opGlobalConstant());
590*700637cbSDimitry Andric 
591*700637cbSDimitry Andric     setLinkageForGV(gv, d);
592*700637cbSDimitry Andric 
593*700637cbSDimitry Andric     if (d->getTLSKind())
594*700637cbSDimitry Andric       errorNYI(d->getSourceRange(), "thread local global variable");
595*700637cbSDimitry Andric 
596*700637cbSDimitry Andric     setGVProperties(gv, d);
597*700637cbSDimitry Andric 
598*700637cbSDimitry Andric     // If required by the ABI, treat declarations of static data members with
599*700637cbSDimitry Andric     // inline initializers as definitions.
600*700637cbSDimitry Andric     if (astContext.isMSStaticDataMemberInlineDefinition(d))
601*700637cbSDimitry Andric       errorNYI(d->getSourceRange(), "MS static data member inline definition");
602*700637cbSDimitry Andric 
603*700637cbSDimitry Andric     assert(!cir::MissingFeatures::opGlobalSection());
604*700637cbSDimitry Andric     gv.setGlobalVisibilityAttr(getGlobalVisibilityAttrFromDecl(d));
605*700637cbSDimitry Andric 
606*700637cbSDimitry Andric     // Handle XCore specific ABI requirements.
607*700637cbSDimitry Andric     if (getTriple().getArch() == llvm::Triple::xcore)
608*700637cbSDimitry Andric       errorNYI(d->getSourceRange(), "XCore specific ABI requirements");
609*700637cbSDimitry Andric 
610*700637cbSDimitry Andric     // Check if we a have a const declaration with an initializer, we may be
611*700637cbSDimitry Andric     // able to emit it as available_externally to expose it's value to the
612*700637cbSDimitry Andric     // optimizer.
613*700637cbSDimitry Andric     if (getLangOpts().CPlusPlus && gv.isPublic() &&
614*700637cbSDimitry Andric         d->getType().isConstQualified() && gv.isDeclaration() &&
615*700637cbSDimitry Andric         !d->hasDefinition() && d->hasInit() && !d->hasAttr<DLLImportAttr>())
616*700637cbSDimitry Andric       errorNYI(d->getSourceRange(),
617*700637cbSDimitry Andric                "external const declaration with initializer");
618*700637cbSDimitry Andric   }
619*700637cbSDimitry Andric 
620*700637cbSDimitry Andric   return gv;
621*700637cbSDimitry Andric }
622*700637cbSDimitry Andric 
623*700637cbSDimitry Andric cir::GlobalOp
getOrCreateCIRGlobal(const VarDecl * d,mlir::Type ty,ForDefinition_t isForDefinition)624*700637cbSDimitry Andric CIRGenModule::getOrCreateCIRGlobal(const VarDecl *d, mlir::Type ty,
625*700637cbSDimitry Andric                                    ForDefinition_t isForDefinition) {
626*700637cbSDimitry Andric   assert(d->hasGlobalStorage() && "Not a global variable");
627*700637cbSDimitry Andric   QualType astTy = d->getType();
628*700637cbSDimitry Andric   if (!ty)
629*700637cbSDimitry Andric     ty = getTypes().convertTypeForMem(astTy);
630*700637cbSDimitry Andric 
631*700637cbSDimitry Andric   StringRef mangledName = getMangledName(d);
632*700637cbSDimitry Andric   return getOrCreateCIRGlobal(mangledName, ty, astTy.getAddressSpace(), d,
633*700637cbSDimitry Andric                               isForDefinition);
634*700637cbSDimitry Andric }
635*700637cbSDimitry Andric 
636*700637cbSDimitry Andric /// Return the mlir::Value for the address of the given global variable. If
637*700637cbSDimitry Andric /// \p ty is non-null and if the global doesn't exist, then it will be created
638*700637cbSDimitry Andric /// with the specified type instead of whatever the normal requested type would
639*700637cbSDimitry Andric /// be. If \p isForDefinition is true, it is guaranteed that an actual global
640*700637cbSDimitry Andric /// with type \p ty will be returned, not conversion of a variable with the same
641*700637cbSDimitry Andric /// mangled name but some other type.
getAddrOfGlobalVar(const VarDecl * d,mlir::Type ty,ForDefinition_t isForDefinition)642*700637cbSDimitry Andric mlir::Value CIRGenModule::getAddrOfGlobalVar(const VarDecl *d, mlir::Type ty,
643*700637cbSDimitry Andric                                              ForDefinition_t isForDefinition) {
644*700637cbSDimitry Andric   assert(d->hasGlobalStorage() && "Not a global variable");
645*700637cbSDimitry Andric   QualType astTy = d->getType();
646*700637cbSDimitry Andric   if (!ty)
647*700637cbSDimitry Andric     ty = getTypes().convertTypeForMem(astTy);
648*700637cbSDimitry Andric 
649*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opGlobalThreadLocal());
650*700637cbSDimitry Andric 
651*700637cbSDimitry Andric   cir::GlobalOp g = getOrCreateCIRGlobal(d, ty, isForDefinition);
652*700637cbSDimitry Andric   mlir::Type ptrTy = builder.getPointerTo(g.getSymType());
653*700637cbSDimitry Andric   return builder.create<cir::GetGlobalOp>(getLoc(d->getSourceRange()), ptrTy,
654*700637cbSDimitry Andric                                           g.getSymName());
655*700637cbSDimitry Andric }
656*700637cbSDimitry Andric 
emitGlobalVarDefinition(const clang::VarDecl * vd,bool isTentative)657*700637cbSDimitry Andric void CIRGenModule::emitGlobalVarDefinition(const clang::VarDecl *vd,
658*700637cbSDimitry Andric                                            bool isTentative) {
659*700637cbSDimitry Andric   const QualType astTy = vd->getType();
660*700637cbSDimitry Andric 
661*700637cbSDimitry Andric   if (getLangOpts().OpenCL || getLangOpts().OpenMPIsTargetDevice) {
662*700637cbSDimitry Andric     errorNYI(vd->getSourceRange(), "emit OpenCL/OpenMP global variable");
663*700637cbSDimitry Andric     return;
664*700637cbSDimitry Andric   }
665*700637cbSDimitry Andric 
666*700637cbSDimitry Andric   // Whether the definition of the variable is available externally.
667*700637cbSDimitry Andric   // If yes, we shouldn't emit the GloablCtor and GlobalDtor for the variable
668*700637cbSDimitry Andric   // since this is the job for its original source.
669*700637cbSDimitry Andric   bool isDefinitionAvailableExternally =
670*700637cbSDimitry Andric       astContext.GetGVALinkageForVariable(vd) == GVA_AvailableExternally;
671*700637cbSDimitry Andric   assert(!cir::MissingFeatures::needsGlobalCtorDtor());
672*700637cbSDimitry Andric 
673*700637cbSDimitry Andric   // It is useless to emit the definition for an available_externally variable
674*700637cbSDimitry Andric   // which can't be marked as const.
675*700637cbSDimitry Andric   if (isDefinitionAvailableExternally &&
676*700637cbSDimitry Andric       (!vd->hasConstantInitialization() ||
677*700637cbSDimitry Andric        // TODO: Update this when we have interface to check constexpr
678*700637cbSDimitry Andric        // destructor.
679*700637cbSDimitry Andric        vd->needsDestruction(astContext) ||
680*700637cbSDimitry Andric        !vd->getType().isConstantStorage(astContext, true, true)))
681*700637cbSDimitry Andric     return;
682*700637cbSDimitry Andric 
683*700637cbSDimitry Andric   mlir::Attribute init;
684*700637cbSDimitry Andric   const VarDecl *initDecl;
685*700637cbSDimitry Andric   const Expr *initExpr = vd->getAnyInitializer(initDecl);
686*700637cbSDimitry Andric 
687*700637cbSDimitry Andric   std::optional<ConstantEmitter> emitter;
688*700637cbSDimitry Andric 
689*700637cbSDimitry Andric   assert(!cir::MissingFeatures::cudaSupport());
690*700637cbSDimitry Andric 
691*700637cbSDimitry Andric   if (vd->hasAttr<LoaderUninitializedAttr>()) {
692*700637cbSDimitry Andric     errorNYI(vd->getSourceRange(), "loader uninitialized attribute");
693*700637cbSDimitry Andric     return;
694*700637cbSDimitry Andric   } else if (!initExpr) {
695*700637cbSDimitry Andric     // This is a tentative definition; tentative definitions are
696*700637cbSDimitry Andric     // implicitly initialized with { 0 }.
697*700637cbSDimitry Andric     //
698*700637cbSDimitry Andric     // Note that tentative definitions are only emitted at the end of
699*700637cbSDimitry Andric     // a translation unit, so they should never have incomplete
700*700637cbSDimitry Andric     // type. In addition, EmitTentativeDefinition makes sure that we
701*700637cbSDimitry Andric     // never attempt to emit a tentative definition if a real one
702*700637cbSDimitry Andric     // exists. A use may still exists, however, so we still may need
703*700637cbSDimitry Andric     // to do a RAUW.
704*700637cbSDimitry Andric     assert(!astTy->isIncompleteType() && "Unexpected incomplete type");
705*700637cbSDimitry Andric     init = builder.getZeroInitAttr(convertType(vd->getType()));
706*700637cbSDimitry Andric   } else {
707*700637cbSDimitry Andric     emitter.emplace(*this);
708*700637cbSDimitry Andric     mlir::Attribute initializer = emitter->tryEmitForInitializer(*initDecl);
709*700637cbSDimitry Andric     if (!initializer) {
710*700637cbSDimitry Andric       QualType qt = initExpr->getType();
711*700637cbSDimitry Andric       if (vd->getType()->isReferenceType())
712*700637cbSDimitry Andric         qt = vd->getType();
713*700637cbSDimitry Andric 
714*700637cbSDimitry Andric       if (getLangOpts().CPlusPlus) {
715*700637cbSDimitry Andric         if (initDecl->hasFlexibleArrayInit(astContext))
716*700637cbSDimitry Andric           errorNYI(vd->getSourceRange(), "flexible array initializer");
717*700637cbSDimitry Andric         init = builder.getZeroInitAttr(convertType(qt));
718*700637cbSDimitry Andric         if (astContext.GetGVALinkageForVariable(vd) != GVA_AvailableExternally)
719*700637cbSDimitry Andric           errorNYI(vd->getSourceRange(), "global constructor");
720*700637cbSDimitry Andric       } else {
721*700637cbSDimitry Andric         errorNYI(vd->getSourceRange(), "static initializer");
722*700637cbSDimitry Andric       }
723*700637cbSDimitry Andric     } else {
724*700637cbSDimitry Andric       init = initializer;
725*700637cbSDimitry Andric       // We don't need an initializer, so remove the entry for the delayed
726*700637cbSDimitry Andric       // initializer position (just in case this entry was delayed) if we
727*700637cbSDimitry Andric       // also don't need to register a destructor.
728*700637cbSDimitry Andric       if (vd->needsDestruction(astContext) == QualType::DK_cxx_destructor)
729*700637cbSDimitry Andric         errorNYI(vd->getSourceRange(), "delayed destructor");
730*700637cbSDimitry Andric     }
731*700637cbSDimitry Andric   }
732*700637cbSDimitry Andric 
733*700637cbSDimitry Andric   mlir::Type initType;
734*700637cbSDimitry Andric   if (mlir::isa<mlir::SymbolRefAttr>(init)) {
735*700637cbSDimitry Andric     errorNYI(vd->getSourceRange(), "global initializer is a symbol reference");
736*700637cbSDimitry Andric     return;
737*700637cbSDimitry Andric   } else {
738*700637cbSDimitry Andric     assert(mlir::isa<mlir::TypedAttr>(init) && "This should have a type");
739*700637cbSDimitry Andric     auto typedInitAttr = mlir::cast<mlir::TypedAttr>(init);
740*700637cbSDimitry Andric     initType = typedInitAttr.getType();
741*700637cbSDimitry Andric   }
742*700637cbSDimitry Andric   assert(!mlir::isa<mlir::NoneType>(initType) && "Should have a type by now");
743*700637cbSDimitry Andric 
744*700637cbSDimitry Andric   cir::GlobalOp gv =
745*700637cbSDimitry Andric       getOrCreateCIRGlobal(vd, initType, ForDefinition_t(!isTentative));
746*700637cbSDimitry Andric   // TODO(cir): Strip off pointer casts from Entry if we get them?
747*700637cbSDimitry Andric 
748*700637cbSDimitry Andric   if (!gv || gv.getSymType() != initType) {
749*700637cbSDimitry Andric     errorNYI(vd->getSourceRange(), "global initializer with type mismatch");
750*700637cbSDimitry Andric     return;
751*700637cbSDimitry Andric   }
752*700637cbSDimitry Andric 
753*700637cbSDimitry Andric   assert(!cir::MissingFeatures::maybeHandleStaticInExternC());
754*700637cbSDimitry Andric 
755*700637cbSDimitry Andric   if (vd->hasAttr<AnnotateAttr>()) {
756*700637cbSDimitry Andric     errorNYI(vd->getSourceRange(), "annotate global variable");
757*700637cbSDimitry Andric   }
758*700637cbSDimitry Andric 
759*700637cbSDimitry Andric   if (langOpts.CUDA) {
760*700637cbSDimitry Andric     errorNYI(vd->getSourceRange(), "CUDA global variable");
761*700637cbSDimitry Andric   }
762*700637cbSDimitry Andric 
763*700637cbSDimitry Andric   // Set initializer and finalize emission
764*700637cbSDimitry Andric   CIRGenModule::setInitializer(gv, init);
765*700637cbSDimitry Andric   if (emitter)
766*700637cbSDimitry Andric     emitter->finalize(gv);
767*700637cbSDimitry Andric 
768*700637cbSDimitry Andric   // Set CIR's linkage type as appropriate.
769*700637cbSDimitry Andric   cir::GlobalLinkageKind linkage =
770*700637cbSDimitry Andric       getCIRLinkageVarDefinition(vd, /*IsConstant=*/false);
771*700637cbSDimitry Andric 
772*700637cbSDimitry Andric   // Set CIR linkage and DLL storage class.
773*700637cbSDimitry Andric   gv.setLinkage(linkage);
774*700637cbSDimitry Andric   // FIXME(cir): setLinkage should likely set MLIR's visibility automatically.
775*700637cbSDimitry Andric   gv.setVisibility(getMLIRVisibilityFromCIRLinkage(linkage));
776*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opGlobalDLLImportExport());
777*700637cbSDimitry Andric   if (linkage == cir::GlobalLinkageKind::CommonLinkage)
778*700637cbSDimitry Andric     errorNYI(initExpr->getSourceRange(), "common linkage");
779*700637cbSDimitry Andric 
780*700637cbSDimitry Andric   setNonAliasAttributes(vd, gv);
781*700637cbSDimitry Andric 
782*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opGlobalThreadLocal());
783*700637cbSDimitry Andric 
784*700637cbSDimitry Andric   maybeSetTrivialComdat(*vd, gv);
785*700637cbSDimitry Andric }
786*700637cbSDimitry Andric 
emitGlobalDefinition(clang::GlobalDecl gd,mlir::Operation * op)787*700637cbSDimitry Andric void CIRGenModule::emitGlobalDefinition(clang::GlobalDecl gd,
788*700637cbSDimitry Andric                                         mlir::Operation *op) {
789*700637cbSDimitry Andric   const auto *decl = cast<ValueDecl>(gd.getDecl());
790*700637cbSDimitry Andric   if (const auto *fd = dyn_cast<FunctionDecl>(decl)) {
791*700637cbSDimitry Andric     // TODO(CIR): Skip generation of CIR for functions with available_externally
792*700637cbSDimitry Andric     // linkage at -O0.
793*700637cbSDimitry Andric 
794*700637cbSDimitry Andric     if (const auto *method = dyn_cast<CXXMethodDecl>(decl)) {
795*700637cbSDimitry Andric       // Make sure to emit the definition(s) before we emit the thunks. This is
796*700637cbSDimitry Andric       // necessary for the generation of certain thunks.
797*700637cbSDimitry Andric       if (isa<CXXConstructorDecl>(method) || isa<CXXDestructorDecl>(method))
798*700637cbSDimitry Andric         abi->emitCXXStructor(gd);
799*700637cbSDimitry Andric       else if (fd->isMultiVersion())
800*700637cbSDimitry Andric         errorNYI(method->getSourceRange(), "multiversion functions");
801*700637cbSDimitry Andric       else
802*700637cbSDimitry Andric         emitGlobalFunctionDefinition(gd, op);
803*700637cbSDimitry Andric 
804*700637cbSDimitry Andric       if (method->isVirtual())
805*700637cbSDimitry Andric         errorNYI(method->getSourceRange(), "virtual member function");
806*700637cbSDimitry Andric 
807*700637cbSDimitry Andric       return;
808*700637cbSDimitry Andric     }
809*700637cbSDimitry Andric 
810*700637cbSDimitry Andric     if (fd->isMultiVersion())
811*700637cbSDimitry Andric       errorNYI(fd->getSourceRange(), "multiversion functions");
812*700637cbSDimitry Andric     emitGlobalFunctionDefinition(gd, op);
813*700637cbSDimitry Andric     return;
814*700637cbSDimitry Andric   }
815*700637cbSDimitry Andric 
816*700637cbSDimitry Andric   if (const auto *vd = dyn_cast<VarDecl>(decl))
817*700637cbSDimitry Andric     return emitGlobalVarDefinition(vd, !vd->hasDefinition());
818*700637cbSDimitry Andric 
819*700637cbSDimitry Andric   llvm_unreachable("Invalid argument to CIRGenModule::emitGlobalDefinition");
820*700637cbSDimitry Andric }
821*700637cbSDimitry Andric 
822*700637cbSDimitry Andric mlir::Attribute
getConstantArrayFromStringLiteral(const StringLiteral * e)823*700637cbSDimitry Andric CIRGenModule::getConstantArrayFromStringLiteral(const StringLiteral *e) {
824*700637cbSDimitry Andric   assert(!e->getType()->isPointerType() && "Strings are always arrays");
825*700637cbSDimitry Andric 
826*700637cbSDimitry Andric   // Don't emit it as the address of the string, emit the string data itself
827*700637cbSDimitry Andric   // as an inline array.
828*700637cbSDimitry Andric   if (e->getCharByteWidth() == 1) {
829*700637cbSDimitry Andric     SmallString<64> str(e->getString());
830*700637cbSDimitry Andric 
831*700637cbSDimitry Andric     // Resize the string to the right size, which is indicated by its type.
832*700637cbSDimitry Andric     const ConstantArrayType *cat =
833*700637cbSDimitry Andric         astContext.getAsConstantArrayType(e->getType());
834*700637cbSDimitry Andric     uint64_t finalSize = cat->getZExtSize();
835*700637cbSDimitry Andric     str.resize(finalSize);
836*700637cbSDimitry Andric 
837*700637cbSDimitry Andric     mlir::Type eltTy = convertType(cat->getElementType());
838*700637cbSDimitry Andric     return builder.getString(str, eltTy, finalSize);
839*700637cbSDimitry Andric   }
840*700637cbSDimitry Andric 
841*700637cbSDimitry Andric   errorNYI(e->getSourceRange(),
842*700637cbSDimitry Andric            "getConstantArrayFromStringLiteral: wide characters");
843*700637cbSDimitry Andric   return mlir::Attribute();
844*700637cbSDimitry Andric }
845*700637cbSDimitry Andric 
supportsCOMDAT() const846*700637cbSDimitry Andric bool CIRGenModule::supportsCOMDAT() const {
847*700637cbSDimitry Andric   return getTriple().supportsCOMDAT();
848*700637cbSDimitry Andric }
849*700637cbSDimitry Andric 
shouldBeInCOMDAT(CIRGenModule & cgm,const Decl & d)850*700637cbSDimitry Andric static bool shouldBeInCOMDAT(CIRGenModule &cgm, const Decl &d) {
851*700637cbSDimitry Andric   if (!cgm.supportsCOMDAT())
852*700637cbSDimitry Andric     return false;
853*700637cbSDimitry Andric 
854*700637cbSDimitry Andric   if (d.hasAttr<SelectAnyAttr>())
855*700637cbSDimitry Andric     return true;
856*700637cbSDimitry Andric 
857*700637cbSDimitry Andric   GVALinkage linkage;
858*700637cbSDimitry Andric   if (auto *vd = dyn_cast<VarDecl>(&d))
859*700637cbSDimitry Andric     linkage = cgm.getASTContext().GetGVALinkageForVariable(vd);
860*700637cbSDimitry Andric   else
861*700637cbSDimitry Andric     linkage =
862*700637cbSDimitry Andric         cgm.getASTContext().GetGVALinkageForFunction(cast<FunctionDecl>(&d));
863*700637cbSDimitry Andric 
864*700637cbSDimitry Andric   switch (linkage) {
865*700637cbSDimitry Andric   case clang::GVA_Internal:
866*700637cbSDimitry Andric   case clang::GVA_AvailableExternally:
867*700637cbSDimitry Andric   case clang::GVA_StrongExternal:
868*700637cbSDimitry Andric     return false;
869*700637cbSDimitry Andric   case clang::GVA_DiscardableODR:
870*700637cbSDimitry Andric   case clang::GVA_StrongODR:
871*700637cbSDimitry Andric     return true;
872*700637cbSDimitry Andric   }
873*700637cbSDimitry Andric   llvm_unreachable("No such linkage");
874*700637cbSDimitry Andric }
875*700637cbSDimitry Andric 
maybeSetTrivialComdat(const Decl & d,mlir::Operation * op)876*700637cbSDimitry Andric void CIRGenModule::maybeSetTrivialComdat(const Decl &d, mlir::Operation *op) {
877*700637cbSDimitry Andric   if (!shouldBeInCOMDAT(*this, d))
878*700637cbSDimitry Andric     return;
879*700637cbSDimitry Andric   if (auto globalOp = dyn_cast_or_null<cir::GlobalOp>(op)) {
880*700637cbSDimitry Andric     globalOp.setComdat(true);
881*700637cbSDimitry Andric   } else {
882*700637cbSDimitry Andric     auto funcOp = cast<cir::FuncOp>(op);
883*700637cbSDimitry Andric     funcOp.setComdat(true);
884*700637cbSDimitry Andric   }
885*700637cbSDimitry Andric }
886*700637cbSDimitry Andric 
updateCompletedType(const TagDecl * td)887*700637cbSDimitry Andric void CIRGenModule::updateCompletedType(const TagDecl *td) {
888*700637cbSDimitry Andric   // Make sure that this type is translated.
889*700637cbSDimitry Andric   genTypes.updateCompletedType(td);
890*700637cbSDimitry Andric }
891*700637cbSDimitry Andric 
addReplacement(StringRef name,mlir::Operation * op)892*700637cbSDimitry Andric void CIRGenModule::addReplacement(StringRef name, mlir::Operation *op) {
893*700637cbSDimitry Andric   replacements[name] = op;
894*700637cbSDimitry Andric }
895*700637cbSDimitry Andric 
replacePointerTypeArgs(cir::FuncOp oldF,cir::FuncOp newF)896*700637cbSDimitry Andric void CIRGenModule::replacePointerTypeArgs(cir::FuncOp oldF, cir::FuncOp newF) {
897*700637cbSDimitry Andric   std::optional<mlir::SymbolTable::UseRange> optionalUseRange =
898*700637cbSDimitry Andric       oldF.getSymbolUses(theModule);
899*700637cbSDimitry Andric   if (!optionalUseRange)
900*700637cbSDimitry Andric     return;
901*700637cbSDimitry Andric 
902*700637cbSDimitry Andric   for (const mlir::SymbolTable::SymbolUse &u : *optionalUseRange) {
903*700637cbSDimitry Andric     // CallTryOp only shows up after FlattenCFG.
904*700637cbSDimitry Andric     auto call = mlir::dyn_cast<cir::CallOp>(u.getUser());
905*700637cbSDimitry Andric     if (!call)
906*700637cbSDimitry Andric       continue;
907*700637cbSDimitry Andric 
908*700637cbSDimitry Andric     for (const auto [argOp, fnArgType] :
909*700637cbSDimitry Andric          llvm::zip(call.getArgs(), newF.getFunctionType().getInputs())) {
910*700637cbSDimitry Andric       if (argOp.getType() == fnArgType)
911*700637cbSDimitry Andric         continue;
912*700637cbSDimitry Andric 
913*700637cbSDimitry Andric       // The purpose of this entire function is to insert bitcasts in the case
914*700637cbSDimitry Andric       // where these types don't match, but I haven't seen a case where that
915*700637cbSDimitry Andric       // happens.
916*700637cbSDimitry Andric       errorNYI(call.getLoc(), "replace call with mismatched types");
917*700637cbSDimitry Andric     }
918*700637cbSDimitry Andric   }
919*700637cbSDimitry Andric }
920*700637cbSDimitry Andric 
applyReplacements()921*700637cbSDimitry Andric void CIRGenModule::applyReplacements() {
922*700637cbSDimitry Andric   for (auto &i : replacements) {
923*700637cbSDimitry Andric     StringRef mangledName = i.first();
924*700637cbSDimitry Andric     mlir::Operation *replacement = i.second;
925*700637cbSDimitry Andric     mlir::Operation *entry = getGlobalValue(mangledName);
926*700637cbSDimitry Andric     if (!entry)
927*700637cbSDimitry Andric       continue;
928*700637cbSDimitry Andric     assert(isa<cir::FuncOp>(entry) && "expected function");
929*700637cbSDimitry Andric     auto oldF = cast<cir::FuncOp>(entry);
930*700637cbSDimitry Andric     auto newF = dyn_cast<cir::FuncOp>(replacement);
931*700637cbSDimitry Andric     if (!newF) {
932*700637cbSDimitry Andric       // In classic codegen, this can be a global alias, a bitcast, or a GEP.
933*700637cbSDimitry Andric       errorNYI(replacement->getLoc(), "replacement is not a function");
934*700637cbSDimitry Andric       continue;
935*700637cbSDimitry Andric     }
936*700637cbSDimitry Andric 
937*700637cbSDimitry Andric     // LLVM has opaque pointer but CIR not. So we may have to handle these
938*700637cbSDimitry Andric     // different pointer types when performing replacement.
939*700637cbSDimitry Andric     replacePointerTypeArgs(oldF, newF);
940*700637cbSDimitry Andric 
941*700637cbSDimitry Andric     // Replace old with new, but keep the old order.
942*700637cbSDimitry Andric     if (oldF.replaceAllSymbolUses(newF.getSymNameAttr(), theModule).failed())
943*700637cbSDimitry Andric       llvm_unreachable("internal error, cannot RAUW symbol");
944*700637cbSDimitry Andric     if (newF) {
945*700637cbSDimitry Andric       newF->moveBefore(oldF);
946*700637cbSDimitry Andric       oldF->erase();
947*700637cbSDimitry Andric     }
948*700637cbSDimitry Andric   }
949*700637cbSDimitry Andric }
950*700637cbSDimitry Andric 
951*700637cbSDimitry Andric // TODO(CIR): this could be a common method between LLVM codegen.
isVarDeclStrongDefinition(const ASTContext & astContext,CIRGenModule & cgm,const VarDecl * vd,bool noCommon)952*700637cbSDimitry Andric static bool isVarDeclStrongDefinition(const ASTContext &astContext,
953*700637cbSDimitry Andric                                       CIRGenModule &cgm, const VarDecl *vd,
954*700637cbSDimitry Andric                                       bool noCommon) {
955*700637cbSDimitry Andric   // Don't give variables common linkage if -fno-common was specified unless it
956*700637cbSDimitry Andric   // was overridden by a NoCommon attribute.
957*700637cbSDimitry Andric   if ((noCommon || vd->hasAttr<NoCommonAttr>()) && !vd->hasAttr<CommonAttr>())
958*700637cbSDimitry Andric     return true;
959*700637cbSDimitry Andric 
960*700637cbSDimitry Andric   // C11 6.9.2/2:
961*700637cbSDimitry Andric   //   A declaration of an identifier for an object that has file scope without
962*700637cbSDimitry Andric   //   an initializer, and without a storage-class specifier or with the
963*700637cbSDimitry Andric   //   storage-class specifier static, constitutes a tentative definition.
964*700637cbSDimitry Andric   if (vd->getInit() || vd->hasExternalStorage())
965*700637cbSDimitry Andric     return true;
966*700637cbSDimitry Andric 
967*700637cbSDimitry Andric   // A variable cannot be both common and exist in a section.
968*700637cbSDimitry Andric   if (vd->hasAttr<SectionAttr>())
969*700637cbSDimitry Andric     return true;
970*700637cbSDimitry Andric 
971*700637cbSDimitry Andric   // A variable cannot be both common and exist in a section.
972*700637cbSDimitry Andric   // We don't try to determine which is the right section in the front-end.
973*700637cbSDimitry Andric   // If no specialized section name is applicable, it will resort to default.
974*700637cbSDimitry Andric   if (vd->hasAttr<PragmaClangBSSSectionAttr>() ||
975*700637cbSDimitry Andric       vd->hasAttr<PragmaClangDataSectionAttr>() ||
976*700637cbSDimitry Andric       vd->hasAttr<PragmaClangRelroSectionAttr>() ||
977*700637cbSDimitry Andric       vd->hasAttr<PragmaClangRodataSectionAttr>())
978*700637cbSDimitry Andric     return true;
979*700637cbSDimitry Andric 
980*700637cbSDimitry Andric   // Thread local vars aren't considered common linkage.
981*700637cbSDimitry Andric   if (vd->getTLSKind())
982*700637cbSDimitry Andric     return true;
983*700637cbSDimitry Andric 
984*700637cbSDimitry Andric   // Tentative definitions marked with WeakImportAttr are true definitions.
985*700637cbSDimitry Andric   if (vd->hasAttr<WeakImportAttr>())
986*700637cbSDimitry Andric     return true;
987*700637cbSDimitry Andric 
988*700637cbSDimitry Andric   // A variable cannot be both common and exist in a comdat.
989*700637cbSDimitry Andric   if (shouldBeInCOMDAT(cgm, *vd))
990*700637cbSDimitry Andric     return true;
991*700637cbSDimitry Andric 
992*700637cbSDimitry Andric   // Declarations with a required alignment do not have common linkage in MSVC
993*700637cbSDimitry Andric   // mode.
994*700637cbSDimitry Andric   if (astContext.getTargetInfo().getCXXABI().isMicrosoft()) {
995*700637cbSDimitry Andric     if (vd->hasAttr<AlignedAttr>())
996*700637cbSDimitry Andric       return true;
997*700637cbSDimitry Andric     QualType varType = vd->getType();
998*700637cbSDimitry Andric     if (astContext.isAlignmentRequired(varType))
999*700637cbSDimitry Andric       return true;
1000*700637cbSDimitry Andric 
1001*700637cbSDimitry Andric     if (const auto *rt = varType->getAs<RecordType>()) {
1002*700637cbSDimitry Andric       const RecordDecl *rd = rt->getDecl();
1003*700637cbSDimitry Andric       for (const FieldDecl *fd : rd->fields()) {
1004*700637cbSDimitry Andric         if (fd->isBitField())
1005*700637cbSDimitry Andric           continue;
1006*700637cbSDimitry Andric         if (fd->hasAttr<AlignedAttr>())
1007*700637cbSDimitry Andric           return true;
1008*700637cbSDimitry Andric         if (astContext.isAlignmentRequired(fd->getType()))
1009*700637cbSDimitry Andric           return true;
1010*700637cbSDimitry Andric       }
1011*700637cbSDimitry Andric     }
1012*700637cbSDimitry Andric   }
1013*700637cbSDimitry Andric 
1014*700637cbSDimitry Andric   // Microsoft's link.exe doesn't support alignments greater than 32 bytes for
1015*700637cbSDimitry Andric   // common symbols, so symbols with greater alignment requirements cannot be
1016*700637cbSDimitry Andric   // common.
1017*700637cbSDimitry Andric   // Other COFF linkers (ld.bfd and LLD) support arbitrary power-of-two
1018*700637cbSDimitry Andric   // alignments for common symbols via the aligncomm directive, so this
1019*700637cbSDimitry Andric   // restriction only applies to MSVC environments.
1020*700637cbSDimitry Andric   if (astContext.getTargetInfo().getTriple().isKnownWindowsMSVCEnvironment() &&
1021*700637cbSDimitry Andric       astContext.getTypeAlignIfKnown(vd->getType()) >
1022*700637cbSDimitry Andric           astContext.toBits(CharUnits::fromQuantity(32)))
1023*700637cbSDimitry Andric     return true;
1024*700637cbSDimitry Andric 
1025*700637cbSDimitry Andric   return false;
1026*700637cbSDimitry Andric }
1027*700637cbSDimitry Andric 
getCIRLinkageForDeclarator(const DeclaratorDecl * dd,GVALinkage linkage,bool isConstantVariable)1028*700637cbSDimitry Andric cir::GlobalLinkageKind CIRGenModule::getCIRLinkageForDeclarator(
1029*700637cbSDimitry Andric     const DeclaratorDecl *dd, GVALinkage linkage, bool isConstantVariable) {
1030*700637cbSDimitry Andric   if (linkage == GVA_Internal)
1031*700637cbSDimitry Andric     return cir::GlobalLinkageKind::InternalLinkage;
1032*700637cbSDimitry Andric 
1033*700637cbSDimitry Andric   if (dd->hasAttr<WeakAttr>()) {
1034*700637cbSDimitry Andric     if (isConstantVariable)
1035*700637cbSDimitry Andric       return cir::GlobalLinkageKind::WeakODRLinkage;
1036*700637cbSDimitry Andric     return cir::GlobalLinkageKind::WeakAnyLinkage;
1037*700637cbSDimitry Andric   }
1038*700637cbSDimitry Andric 
1039*700637cbSDimitry Andric   if (const auto *fd = dd->getAsFunction())
1040*700637cbSDimitry Andric     if (fd->isMultiVersion() && linkage == GVA_AvailableExternally)
1041*700637cbSDimitry Andric       return cir::GlobalLinkageKind::LinkOnceAnyLinkage;
1042*700637cbSDimitry Andric 
1043*700637cbSDimitry Andric   // We are guaranteed to have a strong definition somewhere else,
1044*700637cbSDimitry Andric   // so we can use available_externally linkage.
1045*700637cbSDimitry Andric   if (linkage == GVA_AvailableExternally)
1046*700637cbSDimitry Andric     return cir::GlobalLinkageKind::AvailableExternallyLinkage;
1047*700637cbSDimitry Andric 
1048*700637cbSDimitry Andric   // Note that Apple's kernel linker doesn't support symbol
1049*700637cbSDimitry Andric   // coalescing, so we need to avoid linkonce and weak linkages there.
1050*700637cbSDimitry Andric   // Normally, this means we just map to internal, but for explicit
1051*700637cbSDimitry Andric   // instantiations we'll map to external.
1052*700637cbSDimitry Andric 
1053*700637cbSDimitry Andric   // In C++, the compiler has to emit a definition in every translation unit
1054*700637cbSDimitry Andric   // that references the function.  We should use linkonce_odr because
1055*700637cbSDimitry Andric   // a) if all references in this translation unit are optimized away, we
1056*700637cbSDimitry Andric   // don't need to codegen it.  b) if the function persists, it needs to be
1057*700637cbSDimitry Andric   // merged with other definitions. c) C++ has the ODR, so we know the
1058*700637cbSDimitry Andric   // definition is dependable.
1059*700637cbSDimitry Andric   if (linkage == GVA_DiscardableODR)
1060*700637cbSDimitry Andric     return !astContext.getLangOpts().AppleKext
1061*700637cbSDimitry Andric                ? cir::GlobalLinkageKind::LinkOnceODRLinkage
1062*700637cbSDimitry Andric                : cir::GlobalLinkageKind::InternalLinkage;
1063*700637cbSDimitry Andric 
1064*700637cbSDimitry Andric   // An explicit instantiation of a template has weak linkage, since
1065*700637cbSDimitry Andric   // explicit instantiations can occur in multiple translation units
1066*700637cbSDimitry Andric   // and must all be equivalent. However, we are not allowed to
1067*700637cbSDimitry Andric   // throw away these explicit instantiations.
1068*700637cbSDimitry Andric   //
1069*700637cbSDimitry Andric   // CUDA/HIP: For -fno-gpu-rdc case, device code is limited to one TU,
1070*700637cbSDimitry Andric   // so say that CUDA templates are either external (for kernels) or internal.
1071*700637cbSDimitry Andric   // This lets llvm perform aggressive inter-procedural optimizations. For
1072*700637cbSDimitry Andric   // -fgpu-rdc case, device function calls across multiple TU's are allowed,
1073*700637cbSDimitry Andric   // therefore we need to follow the normal linkage paradigm.
1074*700637cbSDimitry Andric   if (linkage == GVA_StrongODR) {
1075*700637cbSDimitry Andric     if (getLangOpts().AppleKext)
1076*700637cbSDimitry Andric       return cir::GlobalLinkageKind::ExternalLinkage;
1077*700637cbSDimitry Andric     if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice &&
1078*700637cbSDimitry Andric         !getLangOpts().GPURelocatableDeviceCode)
1079*700637cbSDimitry Andric       return dd->hasAttr<CUDAGlobalAttr>()
1080*700637cbSDimitry Andric                  ? cir::GlobalLinkageKind::ExternalLinkage
1081*700637cbSDimitry Andric                  : cir::GlobalLinkageKind::InternalLinkage;
1082*700637cbSDimitry Andric     return cir::GlobalLinkageKind::WeakODRLinkage;
1083*700637cbSDimitry Andric   }
1084*700637cbSDimitry Andric 
1085*700637cbSDimitry Andric   // C++ doesn't have tentative definitions and thus cannot have common
1086*700637cbSDimitry Andric   // linkage.
1087*700637cbSDimitry Andric   if (!getLangOpts().CPlusPlus && isa<VarDecl>(dd) &&
1088*700637cbSDimitry Andric       !isVarDeclStrongDefinition(astContext, *this, cast<VarDecl>(dd),
1089*700637cbSDimitry Andric                                  getCodeGenOpts().NoCommon)) {
1090*700637cbSDimitry Andric     errorNYI(dd->getBeginLoc(), "common linkage", dd->getDeclKindName());
1091*700637cbSDimitry Andric     return cir::GlobalLinkageKind::CommonLinkage;
1092*700637cbSDimitry Andric   }
1093*700637cbSDimitry Andric 
1094*700637cbSDimitry Andric   // selectany symbols are externally visible, so use weak instead of
1095*700637cbSDimitry Andric   // linkonce.  MSVC optimizes away references to const selectany globals, so
1096*700637cbSDimitry Andric   // all definitions should be the same and ODR linkage should be used.
1097*700637cbSDimitry Andric   // http://msdn.microsoft.com/en-us/library/5tkz6s71.aspx
1098*700637cbSDimitry Andric   if (dd->hasAttr<SelectAnyAttr>())
1099*700637cbSDimitry Andric     return cir::GlobalLinkageKind::WeakODRLinkage;
1100*700637cbSDimitry Andric 
1101*700637cbSDimitry Andric   // Otherwise, we have strong external linkage.
1102*700637cbSDimitry Andric   assert(linkage == GVA_StrongExternal);
1103*700637cbSDimitry Andric   return cir::GlobalLinkageKind::ExternalLinkage;
1104*700637cbSDimitry Andric }
1105*700637cbSDimitry Andric 
1106*700637cbSDimitry Andric cir::GlobalLinkageKind
getCIRLinkageVarDefinition(const VarDecl * vd,bool isConstant)1107*700637cbSDimitry Andric CIRGenModule::getCIRLinkageVarDefinition(const VarDecl *vd, bool isConstant) {
1108*700637cbSDimitry Andric   assert(!isConstant && "constant variables NYI");
1109*700637cbSDimitry Andric   GVALinkage linkage = astContext.GetGVALinkageForVariable(vd);
1110*700637cbSDimitry Andric   return getCIRLinkageForDeclarator(vd, linkage, isConstant);
1111*700637cbSDimitry Andric }
1112*700637cbSDimitry Andric 
getFunctionLinkage(GlobalDecl gd)1113*700637cbSDimitry Andric cir::GlobalLinkageKind CIRGenModule::getFunctionLinkage(GlobalDecl gd) {
1114*700637cbSDimitry Andric   const auto *d = cast<FunctionDecl>(gd.getDecl());
1115*700637cbSDimitry Andric 
1116*700637cbSDimitry Andric   GVALinkage linkage = astContext.GetGVALinkageForFunction(d);
1117*700637cbSDimitry Andric 
1118*700637cbSDimitry Andric   if (const auto *dtor = dyn_cast<CXXDestructorDecl>(d))
1119*700637cbSDimitry Andric     return getCXXABI().getCXXDestructorLinkage(linkage, dtor, gd.getDtorType());
1120*700637cbSDimitry Andric 
1121*700637cbSDimitry Andric   return getCIRLinkageForDeclarator(d, linkage, /*isConstantVariable=*/false);
1122*700637cbSDimitry Andric }
1123*700637cbSDimitry Andric 
1124*700637cbSDimitry Andric static cir::GlobalOp
generateStringLiteral(mlir::Location loc,mlir::TypedAttr c,cir::GlobalLinkageKind lt,CIRGenModule & cgm,StringRef globalName,CharUnits alignment)1125*700637cbSDimitry Andric generateStringLiteral(mlir::Location loc, mlir::TypedAttr c,
1126*700637cbSDimitry Andric                       cir::GlobalLinkageKind lt, CIRGenModule &cgm,
1127*700637cbSDimitry Andric                       StringRef globalName, CharUnits alignment) {
1128*700637cbSDimitry Andric   assert(!cir::MissingFeatures::addressSpace());
1129*700637cbSDimitry Andric 
1130*700637cbSDimitry Andric   // Create a global variable for this string
1131*700637cbSDimitry Andric   // FIXME(cir): check for insertion point in module level.
1132*700637cbSDimitry Andric   cir::GlobalOp gv =
1133*700637cbSDimitry Andric       CIRGenModule::createGlobalOp(cgm, loc, globalName, c.getType());
1134*700637cbSDimitry Andric 
1135*700637cbSDimitry Andric   // Set up extra information and add to the module
1136*700637cbSDimitry Andric   gv.setAlignmentAttr(cgm.getSize(alignment));
1137*700637cbSDimitry Andric   gv.setLinkageAttr(
1138*700637cbSDimitry Andric       cir::GlobalLinkageKindAttr::get(cgm.getBuilder().getContext(), lt));
1139*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opGlobalThreadLocal());
1140*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opGlobalUnnamedAddr());
1141*700637cbSDimitry Andric   CIRGenModule::setInitializer(gv, c);
1142*700637cbSDimitry Andric   if (gv.isWeakForLinker()) {
1143*700637cbSDimitry Andric     assert(cgm.supportsCOMDAT() && "Only COFF uses weak string literals");
1144*700637cbSDimitry Andric     gv.setComdat(true);
1145*700637cbSDimitry Andric   }
1146*700637cbSDimitry Andric   cgm.setDSOLocal(static_cast<mlir::Operation *>(gv));
1147*700637cbSDimitry Andric   return gv;
1148*700637cbSDimitry Andric }
1149*700637cbSDimitry Andric 
1150*700637cbSDimitry Andric // LLVM IR automatically uniques names when new llvm::GlobalVariables are
1151*700637cbSDimitry Andric // created. This is handy, for example, when creating globals for string
1152*700637cbSDimitry Andric // literals. Since we don't do that when creating cir::GlobalOp's, we need
1153*700637cbSDimitry Andric // a mechanism to generate a unique name in advance.
1154*700637cbSDimitry Andric //
1155*700637cbSDimitry Andric // For now, this mechanism is only used in cases where we know that the
1156*700637cbSDimitry Andric // name is compiler-generated, so we don't use the MLIR symbol table for
1157*700637cbSDimitry Andric // the lookup.
getUniqueGlobalName(const std::string & baseName)1158*700637cbSDimitry Andric std::string CIRGenModule::getUniqueGlobalName(const std::string &baseName) {
1159*700637cbSDimitry Andric   // If this is the first time we've generated a name for this basename, use
1160*700637cbSDimitry Andric   // it as is and start a counter for this base name.
1161*700637cbSDimitry Andric   auto it = cgGlobalNames.find(baseName);
1162*700637cbSDimitry Andric   if (it == cgGlobalNames.end()) {
1163*700637cbSDimitry Andric     cgGlobalNames[baseName] = 1;
1164*700637cbSDimitry Andric     return baseName;
1165*700637cbSDimitry Andric   }
1166*700637cbSDimitry Andric 
1167*700637cbSDimitry Andric   std::string result =
1168*700637cbSDimitry Andric       baseName + "." + std::to_string(cgGlobalNames[baseName]++);
1169*700637cbSDimitry Andric   // There should not be any symbol with this name in the module.
1170*700637cbSDimitry Andric   assert(!mlir::SymbolTable::lookupSymbolIn(theModule, result));
1171*700637cbSDimitry Andric   return result;
1172*700637cbSDimitry Andric }
1173*700637cbSDimitry Andric 
1174*700637cbSDimitry Andric /// Return a pointer to a constant array for the given string literal.
getGlobalForStringLiteral(const StringLiteral * s,StringRef name)1175*700637cbSDimitry Andric cir::GlobalOp CIRGenModule::getGlobalForStringLiteral(const StringLiteral *s,
1176*700637cbSDimitry Andric                                                       StringRef name) {
1177*700637cbSDimitry Andric   CharUnits alignment =
1178*700637cbSDimitry Andric       astContext.getAlignOfGlobalVarInChars(s->getType(), /*VD=*/nullptr);
1179*700637cbSDimitry Andric 
1180*700637cbSDimitry Andric   mlir::Attribute c = getConstantArrayFromStringLiteral(s);
1181*700637cbSDimitry Andric 
1182*700637cbSDimitry Andric   if (getLangOpts().WritableStrings) {
1183*700637cbSDimitry Andric     errorNYI(s->getSourceRange(),
1184*700637cbSDimitry Andric              "getGlobalForStringLiteral: Writable strings");
1185*700637cbSDimitry Andric   }
1186*700637cbSDimitry Andric 
1187*700637cbSDimitry Andric   // Mangle the string literal if that's how the ABI merges duplicate strings.
1188*700637cbSDimitry Andric   // Don't do it if they are writable, since we don't want writes in one TU to
1189*700637cbSDimitry Andric   // affect strings in another.
1190*700637cbSDimitry Andric   if (getCXXABI().getMangleContext().shouldMangleStringLiteral(s) &&
1191*700637cbSDimitry Andric       !getLangOpts().WritableStrings) {
1192*700637cbSDimitry Andric     errorNYI(s->getSourceRange(),
1193*700637cbSDimitry Andric              "getGlobalForStringLiteral: mangle string literals");
1194*700637cbSDimitry Andric   }
1195*700637cbSDimitry Andric 
1196*700637cbSDimitry Andric   // Unlike LLVM IR, CIR doesn't automatically unique names for globals, so
1197*700637cbSDimitry Andric   // we need to do that explicitly.
1198*700637cbSDimitry Andric   std::string uniqueName = getUniqueGlobalName(name.str());
1199*700637cbSDimitry Andric   mlir::Location loc = getLoc(s->getSourceRange());
1200*700637cbSDimitry Andric   auto typedC = llvm::cast<mlir::TypedAttr>(c);
1201*700637cbSDimitry Andric   cir::GlobalOp gv =
1202*700637cbSDimitry Andric       generateStringLiteral(loc, typedC, cir::GlobalLinkageKind::PrivateLinkage,
1203*700637cbSDimitry Andric                             *this, uniqueName, alignment);
1204*700637cbSDimitry Andric   setDSOLocal(static_cast<mlir::Operation *>(gv));
1205*700637cbSDimitry Andric 
1206*700637cbSDimitry Andric   assert(!cir::MissingFeatures::sanitizers());
1207*700637cbSDimitry Andric 
1208*700637cbSDimitry Andric   return gv;
1209*700637cbSDimitry Andric }
1210*700637cbSDimitry Andric 
emitDeclContext(const DeclContext * dc)1211*700637cbSDimitry Andric void CIRGenModule::emitDeclContext(const DeclContext *dc) {
1212*700637cbSDimitry Andric   for (Decl *decl : dc->decls()) {
1213*700637cbSDimitry Andric     // Unlike other DeclContexts, the contents of an ObjCImplDecl at TU scope
1214*700637cbSDimitry Andric     // are themselves considered "top-level", so EmitTopLevelDecl on an
1215*700637cbSDimitry Andric     // ObjCImplDecl does not recursively visit them. We need to do that in
1216*700637cbSDimitry Andric     // case they're nested inside another construct (LinkageSpecDecl /
1217*700637cbSDimitry Andric     // ExportDecl) that does stop them from being considered "top-level".
1218*700637cbSDimitry Andric     if (auto *oid = dyn_cast<ObjCImplDecl>(decl))
1219*700637cbSDimitry Andric       errorNYI(oid->getSourceRange(), "emitDeclConext: ObjCImplDecl");
1220*700637cbSDimitry Andric 
1221*700637cbSDimitry Andric     emitTopLevelDecl(decl);
1222*700637cbSDimitry Andric   }
1223*700637cbSDimitry Andric }
1224*700637cbSDimitry Andric 
1225*700637cbSDimitry Andric // Emit code for a single top level declaration.
emitTopLevelDecl(Decl * decl)1226*700637cbSDimitry Andric void CIRGenModule::emitTopLevelDecl(Decl *decl) {
1227*700637cbSDimitry Andric 
1228*700637cbSDimitry Andric   // Ignore dependent declarations.
1229*700637cbSDimitry Andric   if (decl->isTemplated())
1230*700637cbSDimitry Andric     return;
1231*700637cbSDimitry Andric 
1232*700637cbSDimitry Andric   switch (decl->getKind()) {
1233*700637cbSDimitry Andric   default:
1234*700637cbSDimitry Andric     errorNYI(decl->getBeginLoc(), "declaration of kind",
1235*700637cbSDimitry Andric              decl->getDeclKindName());
1236*700637cbSDimitry Andric     break;
1237*700637cbSDimitry Andric 
1238*700637cbSDimitry Andric   case Decl::CXXMethod:
1239*700637cbSDimitry Andric   case Decl::Function: {
1240*700637cbSDimitry Andric     auto *fd = cast<FunctionDecl>(decl);
1241*700637cbSDimitry Andric     // Consteval functions shouldn't be emitted.
1242*700637cbSDimitry Andric     if (!fd->isConsteval())
1243*700637cbSDimitry Andric       emitGlobal(fd);
1244*700637cbSDimitry Andric     break;
1245*700637cbSDimitry Andric   }
1246*700637cbSDimitry Andric 
1247*700637cbSDimitry Andric   case Decl::Var: {
1248*700637cbSDimitry Andric     auto *vd = cast<VarDecl>(decl);
1249*700637cbSDimitry Andric     emitGlobal(vd);
1250*700637cbSDimitry Andric     break;
1251*700637cbSDimitry Andric   }
1252*700637cbSDimitry Andric   case Decl::OpenACCRoutine:
1253*700637cbSDimitry Andric     emitGlobalOpenACCDecl(cast<OpenACCRoutineDecl>(decl));
1254*700637cbSDimitry Andric     break;
1255*700637cbSDimitry Andric   case Decl::OpenACCDeclare:
1256*700637cbSDimitry Andric     emitGlobalOpenACCDecl(cast<OpenACCDeclareDecl>(decl));
1257*700637cbSDimitry Andric     break;
1258*700637cbSDimitry Andric   case Decl::Enum:
1259*700637cbSDimitry Andric   case Decl::Using:          // using X; [C++]
1260*700637cbSDimitry Andric   case Decl::UsingDirective: // using namespace X; [C++]
1261*700637cbSDimitry Andric   case Decl::UsingEnum:      // using enum X; [C++]
1262*700637cbSDimitry Andric   case Decl::NamespaceAlias:
1263*700637cbSDimitry Andric   case Decl::Typedef:
1264*700637cbSDimitry Andric   case Decl::TypeAlias: // using foo = bar; [C++11]
1265*700637cbSDimitry Andric   case Decl::Record:
1266*700637cbSDimitry Andric     assert(!cir::MissingFeatures::generateDebugInfo());
1267*700637cbSDimitry Andric     break;
1268*700637cbSDimitry Andric 
1269*700637cbSDimitry Andric   // No code generation needed.
1270*700637cbSDimitry Andric   case Decl::UsingShadow:
1271*700637cbSDimitry Andric   case Decl::Empty:
1272*700637cbSDimitry Andric     break;
1273*700637cbSDimitry Andric 
1274*700637cbSDimitry Andric   case Decl::CXXConstructor:
1275*700637cbSDimitry Andric     getCXXABI().emitCXXConstructors(cast<CXXConstructorDecl>(decl));
1276*700637cbSDimitry Andric     break;
1277*700637cbSDimitry Andric   case Decl::CXXDestructor:
1278*700637cbSDimitry Andric     getCXXABI().emitCXXDestructors(cast<CXXDestructorDecl>(decl));
1279*700637cbSDimitry Andric     break;
1280*700637cbSDimitry Andric 
1281*700637cbSDimitry Andric   // C++ Decls
1282*700637cbSDimitry Andric   case Decl::LinkageSpec:
1283*700637cbSDimitry Andric   case Decl::Namespace:
1284*700637cbSDimitry Andric     emitDeclContext(Decl::castToDeclContext(decl));
1285*700637cbSDimitry Andric     break;
1286*700637cbSDimitry Andric 
1287*700637cbSDimitry Andric   case Decl::ClassTemplateSpecialization:
1288*700637cbSDimitry Andric   case Decl::CXXRecord:
1289*700637cbSDimitry Andric     assert(!cir::MissingFeatures::generateDebugInfo());
1290*700637cbSDimitry Andric     assert(!cir::MissingFeatures::cxxRecordStaticMembers());
1291*700637cbSDimitry Andric     break;
1292*700637cbSDimitry Andric   }
1293*700637cbSDimitry Andric }
1294*700637cbSDimitry Andric 
setInitializer(cir::GlobalOp & op,mlir::Attribute value)1295*700637cbSDimitry Andric void CIRGenModule::setInitializer(cir::GlobalOp &op, mlir::Attribute value) {
1296*700637cbSDimitry Andric   // Recompute visibility when updating initializer.
1297*700637cbSDimitry Andric   op.setInitialValueAttr(value);
1298*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opGlobalVisibility());
1299*700637cbSDimitry Andric }
1300*700637cbSDimitry Andric 
getAddrAndTypeOfCXXStructor(GlobalDecl gd,const CIRGenFunctionInfo * fnInfo,cir::FuncType fnType,bool dontDefer,ForDefinition_t isForDefinition)1301*700637cbSDimitry Andric std::pair<cir::FuncType, cir::FuncOp> CIRGenModule::getAddrAndTypeOfCXXStructor(
1302*700637cbSDimitry Andric     GlobalDecl gd, const CIRGenFunctionInfo *fnInfo, cir::FuncType fnType,
1303*700637cbSDimitry Andric     bool dontDefer, ForDefinition_t isForDefinition) {
1304*700637cbSDimitry Andric   auto *md = cast<CXXMethodDecl>(gd.getDecl());
1305*700637cbSDimitry Andric 
1306*700637cbSDimitry Andric   if (isa<CXXDestructorDecl>(md)) {
1307*700637cbSDimitry Andric     // Always alias equivalent complete destructors to base destructors in the
1308*700637cbSDimitry Andric     // MS ABI.
1309*700637cbSDimitry Andric     if (getTarget().getCXXABI().isMicrosoft() &&
1310*700637cbSDimitry Andric         gd.getDtorType() == Dtor_Complete &&
1311*700637cbSDimitry Andric         md->getParent()->getNumVBases() == 0)
1312*700637cbSDimitry Andric       errorNYI(md->getSourceRange(),
1313*700637cbSDimitry Andric                "getAddrAndTypeOfCXXStructor: MS ABI complete destructor");
1314*700637cbSDimitry Andric   }
1315*700637cbSDimitry Andric 
1316*700637cbSDimitry Andric   if (!fnType) {
1317*700637cbSDimitry Andric     if (!fnInfo)
1318*700637cbSDimitry Andric       fnInfo = &getTypes().arrangeCXXStructorDeclaration(gd);
1319*700637cbSDimitry Andric     fnType = getTypes().getFunctionType(*fnInfo);
1320*700637cbSDimitry Andric   }
1321*700637cbSDimitry Andric 
1322*700637cbSDimitry Andric   auto fn = getOrCreateCIRFunction(getMangledName(gd), fnType, gd,
1323*700637cbSDimitry Andric                                    /*ForVtable=*/false, dontDefer,
1324*700637cbSDimitry Andric                                    /*IsThunk=*/false, isForDefinition);
1325*700637cbSDimitry Andric 
1326*700637cbSDimitry Andric   return {fnType, fn};
1327*700637cbSDimitry Andric }
1328*700637cbSDimitry Andric 
getAddrOfFunction(clang::GlobalDecl gd,mlir::Type funcType,bool forVTable,bool dontDefer,ForDefinition_t isForDefinition)1329*700637cbSDimitry Andric cir::FuncOp CIRGenModule::getAddrOfFunction(clang::GlobalDecl gd,
1330*700637cbSDimitry Andric                                             mlir::Type funcType, bool forVTable,
1331*700637cbSDimitry Andric                                             bool dontDefer,
1332*700637cbSDimitry Andric                                             ForDefinition_t isForDefinition) {
1333*700637cbSDimitry Andric   assert(!cast<FunctionDecl>(gd.getDecl())->isConsteval() &&
1334*700637cbSDimitry Andric          "consteval function should never be emitted");
1335*700637cbSDimitry Andric 
1336*700637cbSDimitry Andric   if (!funcType) {
1337*700637cbSDimitry Andric     const auto *fd = cast<FunctionDecl>(gd.getDecl());
1338*700637cbSDimitry Andric     funcType = convertType(fd->getType());
1339*700637cbSDimitry Andric   }
1340*700637cbSDimitry Andric 
1341*700637cbSDimitry Andric   // Devirtualized destructor calls may come through here instead of via
1342*700637cbSDimitry Andric   // getAddrOfCXXStructor. Make sure we use the MS ABI base destructor instead
1343*700637cbSDimitry Andric   // of the complete destructor when necessary.
1344*700637cbSDimitry Andric   if (const auto *dd = dyn_cast<CXXDestructorDecl>(gd.getDecl())) {
1345*700637cbSDimitry Andric     if (getTarget().getCXXABI().isMicrosoft() &&
1346*700637cbSDimitry Andric         gd.getDtorType() == Dtor_Complete &&
1347*700637cbSDimitry Andric         dd->getParent()->getNumVBases() == 0)
1348*700637cbSDimitry Andric       errorNYI(dd->getSourceRange(),
1349*700637cbSDimitry Andric                "getAddrOfFunction: MS ABI complete destructor");
1350*700637cbSDimitry Andric   }
1351*700637cbSDimitry Andric 
1352*700637cbSDimitry Andric   StringRef mangledName = getMangledName(gd);
1353*700637cbSDimitry Andric   cir::FuncOp func =
1354*700637cbSDimitry Andric       getOrCreateCIRFunction(mangledName, funcType, gd, forVTable, dontDefer,
1355*700637cbSDimitry Andric                              /*isThunk=*/false, isForDefinition);
1356*700637cbSDimitry Andric   return func;
1357*700637cbSDimitry Andric }
1358*700637cbSDimitry Andric 
getMangledNameImpl(CIRGenModule & cgm,GlobalDecl gd,const NamedDecl * nd)1359*700637cbSDimitry Andric static std::string getMangledNameImpl(CIRGenModule &cgm, GlobalDecl gd,
1360*700637cbSDimitry Andric                                       const NamedDecl *nd) {
1361*700637cbSDimitry Andric   SmallString<256> buffer;
1362*700637cbSDimitry Andric 
1363*700637cbSDimitry Andric   llvm::raw_svector_ostream out(buffer);
1364*700637cbSDimitry Andric   MangleContext &mc = cgm.getCXXABI().getMangleContext();
1365*700637cbSDimitry Andric 
1366*700637cbSDimitry Andric   assert(!cir::MissingFeatures::moduleNameHash());
1367*700637cbSDimitry Andric 
1368*700637cbSDimitry Andric   if (mc.shouldMangleDeclName(nd)) {
1369*700637cbSDimitry Andric     mc.mangleName(gd.getWithDecl(nd), out);
1370*700637cbSDimitry Andric   } else {
1371*700637cbSDimitry Andric     IdentifierInfo *ii = nd->getIdentifier();
1372*700637cbSDimitry Andric     assert(ii && "Attempt to mangle unnamed decl.");
1373*700637cbSDimitry Andric 
1374*700637cbSDimitry Andric     const auto *fd = dyn_cast<FunctionDecl>(nd);
1375*700637cbSDimitry Andric     if (fd &&
1376*700637cbSDimitry Andric         fd->getType()->castAs<FunctionType>()->getCallConv() == CC_X86RegCall) {
1377*700637cbSDimitry Andric       cgm.errorNYI(nd->getSourceRange(), "getMangledName: X86RegCall");
1378*700637cbSDimitry Andric     } else if (fd && fd->hasAttr<CUDAGlobalAttr>() &&
1379*700637cbSDimitry Andric                gd.getKernelReferenceKind() == KernelReferenceKind::Stub) {
1380*700637cbSDimitry Andric       cgm.errorNYI(nd->getSourceRange(), "getMangledName: CUDA device stub");
1381*700637cbSDimitry Andric     }
1382*700637cbSDimitry Andric     out << ii->getName();
1383*700637cbSDimitry Andric   }
1384*700637cbSDimitry Andric 
1385*700637cbSDimitry Andric   // Check if the module name hash should be appended for internal linkage
1386*700637cbSDimitry Andric   // symbols. This should come before multi-version target suffixes are
1387*700637cbSDimitry Andric   // appendded. This is to keep the name and module hash suffix of the internal
1388*700637cbSDimitry Andric   // linkage function together. The unique suffix should only be added when name
1389*700637cbSDimitry Andric   // mangling is done to make sure that the final name can be properly
1390*700637cbSDimitry Andric   // demangled. For example, for C functions without prototypes, name mangling
1391*700637cbSDimitry Andric   // is not done and the unique suffix should not be appended then.
1392*700637cbSDimitry Andric   assert(!cir::MissingFeatures::moduleNameHash());
1393*700637cbSDimitry Andric 
1394*700637cbSDimitry Andric   if (const auto *fd = dyn_cast<FunctionDecl>(nd)) {
1395*700637cbSDimitry Andric     if (fd->isMultiVersion()) {
1396*700637cbSDimitry Andric       cgm.errorNYI(nd->getSourceRange(),
1397*700637cbSDimitry Andric                    "getMangledName: multi-version functions");
1398*700637cbSDimitry Andric     }
1399*700637cbSDimitry Andric   }
1400*700637cbSDimitry Andric   if (cgm.getLangOpts().GPURelocatableDeviceCode) {
1401*700637cbSDimitry Andric     cgm.errorNYI(nd->getSourceRange(),
1402*700637cbSDimitry Andric                  "getMangledName: GPU relocatable device code");
1403*700637cbSDimitry Andric   }
1404*700637cbSDimitry Andric 
1405*700637cbSDimitry Andric   return std::string(out.str());
1406*700637cbSDimitry Andric }
1407*700637cbSDimitry Andric 
getMangledName(GlobalDecl gd)1408*700637cbSDimitry Andric StringRef CIRGenModule::getMangledName(GlobalDecl gd) {
1409*700637cbSDimitry Andric   GlobalDecl canonicalGd = gd.getCanonicalDecl();
1410*700637cbSDimitry Andric 
1411*700637cbSDimitry Andric   // Some ABIs don't have constructor variants. Make sure that base and complete
1412*700637cbSDimitry Andric   // constructors get mangled the same.
1413*700637cbSDimitry Andric   if (const auto *cd = dyn_cast<CXXConstructorDecl>(canonicalGd.getDecl())) {
1414*700637cbSDimitry Andric     if (!getTarget().getCXXABI().hasConstructorVariants()) {
1415*700637cbSDimitry Andric       errorNYI(cd->getSourceRange(),
1416*700637cbSDimitry Andric                "getMangledName: C++ constructor without variants");
1417*700637cbSDimitry Andric       return cast<NamedDecl>(gd.getDecl())->getIdentifier()->getName();
1418*700637cbSDimitry Andric     }
1419*700637cbSDimitry Andric   }
1420*700637cbSDimitry Andric 
1421*700637cbSDimitry Andric   // Keep the first result in the case of a mangling collision.
1422*700637cbSDimitry Andric   const auto *nd = cast<NamedDecl>(gd.getDecl());
1423*700637cbSDimitry Andric   std::string mangledName = getMangledNameImpl(*this, gd, nd);
1424*700637cbSDimitry Andric 
1425*700637cbSDimitry Andric   auto result = manglings.insert(std::make_pair(mangledName, gd));
1426*700637cbSDimitry Andric   return mangledDeclNames[canonicalGd] = result.first->first();
1427*700637cbSDimitry Andric }
1428*700637cbSDimitry Andric 
emitTentativeDefinition(const VarDecl * d)1429*700637cbSDimitry Andric void CIRGenModule::emitTentativeDefinition(const VarDecl *d) {
1430*700637cbSDimitry Andric   assert(!d->getInit() && "Cannot emit definite definitions here!");
1431*700637cbSDimitry Andric 
1432*700637cbSDimitry Andric   StringRef mangledName = getMangledName(d);
1433*700637cbSDimitry Andric   mlir::Operation *gv = getGlobalValue(mangledName);
1434*700637cbSDimitry Andric 
1435*700637cbSDimitry Andric   // If we already have a definition, not declaration, with the same mangled
1436*700637cbSDimitry Andric   // name, emitting of declaration is not required (and would actually overwrite
1437*700637cbSDimitry Andric   // the emitted definition).
1438*700637cbSDimitry Andric   if (gv && !mlir::cast<cir::GlobalOp>(gv).isDeclaration())
1439*700637cbSDimitry Andric     return;
1440*700637cbSDimitry Andric 
1441*700637cbSDimitry Andric   // If we have not seen a reference to this variable yet, place it into the
1442*700637cbSDimitry Andric   // deferred declarations table to be emitted if needed later.
1443*700637cbSDimitry Andric   if (!mustBeEmitted(d) && !gv) {
1444*700637cbSDimitry Andric     deferredDecls[mangledName] = d;
1445*700637cbSDimitry Andric     return;
1446*700637cbSDimitry Andric   }
1447*700637cbSDimitry Andric 
1448*700637cbSDimitry Andric   // The tentative definition is the only definition.
1449*700637cbSDimitry Andric   emitGlobalVarDefinition(d);
1450*700637cbSDimitry Andric }
1451*700637cbSDimitry Andric 
mustBeEmitted(const ValueDecl * global)1452*700637cbSDimitry Andric bool CIRGenModule::mustBeEmitted(const ValueDecl *global) {
1453*700637cbSDimitry Andric   // Never defer when EmitAllDecls is specified.
1454*700637cbSDimitry Andric   if (langOpts.EmitAllDecls)
1455*700637cbSDimitry Andric     return true;
1456*700637cbSDimitry Andric 
1457*700637cbSDimitry Andric   const auto *vd = dyn_cast<VarDecl>(global);
1458*700637cbSDimitry Andric   if (vd &&
1459*700637cbSDimitry Andric       ((codeGenOpts.KeepPersistentStorageVariables &&
1460*700637cbSDimitry Andric         (vd->getStorageDuration() == SD_Static ||
1461*700637cbSDimitry Andric          vd->getStorageDuration() == SD_Thread)) ||
1462*700637cbSDimitry Andric        (codeGenOpts.KeepStaticConsts && vd->getStorageDuration() == SD_Static &&
1463*700637cbSDimitry Andric         vd->getType().isConstQualified())))
1464*700637cbSDimitry Andric     return true;
1465*700637cbSDimitry Andric 
1466*700637cbSDimitry Andric   return getASTContext().DeclMustBeEmitted(global);
1467*700637cbSDimitry Andric }
1468*700637cbSDimitry Andric 
mayBeEmittedEagerly(const ValueDecl * global)1469*700637cbSDimitry Andric bool CIRGenModule::mayBeEmittedEagerly(const ValueDecl *global) {
1470*700637cbSDimitry Andric   // In OpenMP 5.0 variables and function may be marked as
1471*700637cbSDimitry Andric   // device_type(host/nohost) and we should not emit them eagerly unless we sure
1472*700637cbSDimitry Andric   // that they must be emitted on the host/device. To be sure we need to have
1473*700637cbSDimitry Andric   // seen a declare target with an explicit mentioning of the function, we know
1474*700637cbSDimitry Andric   // we have if the level of the declare target attribute is -1. Note that we
1475*700637cbSDimitry Andric   // check somewhere else if we should emit this at all.
1476*700637cbSDimitry Andric   if (langOpts.OpenMP >= 50 && !langOpts.OpenMPSimd) {
1477*700637cbSDimitry Andric     std::optional<OMPDeclareTargetDeclAttr *> activeAttr =
1478*700637cbSDimitry Andric         OMPDeclareTargetDeclAttr::getActiveAttr(global);
1479*700637cbSDimitry Andric     if (!activeAttr || (*activeAttr)->getLevel() != (unsigned)-1)
1480*700637cbSDimitry Andric       return false;
1481*700637cbSDimitry Andric   }
1482*700637cbSDimitry Andric 
1483*700637cbSDimitry Andric   const auto *fd = dyn_cast<FunctionDecl>(global);
1484*700637cbSDimitry Andric   if (fd) {
1485*700637cbSDimitry Andric     // Implicit template instantiations may change linkage if they are later
1486*700637cbSDimitry Andric     // explicitly instantiated, so they should not be emitted eagerly.
1487*700637cbSDimitry Andric     if (fd->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
1488*700637cbSDimitry Andric       return false;
1489*700637cbSDimitry Andric     // Defer until all versions have been semantically checked.
1490*700637cbSDimitry Andric     if (fd->hasAttr<TargetVersionAttr>() && !fd->isMultiVersion())
1491*700637cbSDimitry Andric       return false;
1492*700637cbSDimitry Andric     if (langOpts.SYCLIsDevice) {
1493*700637cbSDimitry Andric       errorNYI(fd->getSourceRange(), "mayBeEmittedEagerly: SYCL");
1494*700637cbSDimitry Andric       return false;
1495*700637cbSDimitry Andric     }
1496*700637cbSDimitry Andric   }
1497*700637cbSDimitry Andric   const auto *vd = dyn_cast<VarDecl>(global);
1498*700637cbSDimitry Andric   if (vd)
1499*700637cbSDimitry Andric     if (astContext.getInlineVariableDefinitionKind(vd) ==
1500*700637cbSDimitry Andric         ASTContext::InlineVariableDefinitionKind::WeakUnknown)
1501*700637cbSDimitry Andric       // A definition of an inline constexpr static data member may change
1502*700637cbSDimitry Andric       // linkage later if it's redeclared outside the class.
1503*700637cbSDimitry Andric       return false;
1504*700637cbSDimitry Andric 
1505*700637cbSDimitry Andric   // If OpenMP is enabled and threadprivates must be generated like TLS, delay
1506*700637cbSDimitry Andric   // codegen for global variables, because they may be marked as threadprivate.
1507*700637cbSDimitry Andric   if (langOpts.OpenMP && langOpts.OpenMPUseTLS &&
1508*700637cbSDimitry Andric       astContext.getTargetInfo().isTLSSupported() && isa<VarDecl>(global) &&
1509*700637cbSDimitry Andric       !global->getType().isConstantStorage(astContext, false, false) &&
1510*700637cbSDimitry Andric       !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(global))
1511*700637cbSDimitry Andric     return false;
1512*700637cbSDimitry Andric 
1513*700637cbSDimitry Andric   assert((fd || vd) &&
1514*700637cbSDimitry Andric          "Only FunctionDecl and VarDecl should hit this path so far.");
1515*700637cbSDimitry Andric   return true;
1516*700637cbSDimitry Andric }
1517*700637cbSDimitry Andric 
shouldAssumeDSOLocal(const CIRGenModule & cgm,cir::CIRGlobalValueInterface gv)1518*700637cbSDimitry Andric static bool shouldAssumeDSOLocal(const CIRGenModule &cgm,
1519*700637cbSDimitry Andric                                  cir::CIRGlobalValueInterface gv) {
1520*700637cbSDimitry Andric   if (gv.hasLocalLinkage())
1521*700637cbSDimitry Andric     return true;
1522*700637cbSDimitry Andric 
1523*700637cbSDimitry Andric   if (!gv.hasDefaultVisibility() && !gv.hasExternalWeakLinkage())
1524*700637cbSDimitry Andric     return true;
1525*700637cbSDimitry Andric 
1526*700637cbSDimitry Andric   // DLLImport explicitly marks the GV as external.
1527*700637cbSDimitry Andric   // so it shouldn't be dso_local
1528*700637cbSDimitry Andric   // But we don't have the info set now
1529*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opGlobalDLLImportExport());
1530*700637cbSDimitry Andric 
1531*700637cbSDimitry Andric   const llvm::Triple &tt = cgm.getTriple();
1532*700637cbSDimitry Andric   const CodeGenOptions &cgOpts = cgm.getCodeGenOpts();
1533*700637cbSDimitry Andric   if (tt.isWindowsGNUEnvironment()) {
1534*700637cbSDimitry Andric     // In MinGW, variables without DLLImport can still be automatically
1535*700637cbSDimitry Andric     // imported from a DLL by the linker; don't mark variables that
1536*700637cbSDimitry Andric     // potentially could come from another DLL as DSO local.
1537*700637cbSDimitry Andric 
1538*700637cbSDimitry Andric     // With EmulatedTLS, TLS variables can be autoimported from other DLLs
1539*700637cbSDimitry Andric     // (and this actually happens in the public interface of libstdc++), so
1540*700637cbSDimitry Andric     // such variables can't be marked as DSO local. (Native TLS variables
1541*700637cbSDimitry Andric     // can't be dllimported at all, though.)
1542*700637cbSDimitry Andric     cgm.errorNYI("shouldAssumeDSOLocal: MinGW");
1543*700637cbSDimitry Andric   }
1544*700637cbSDimitry Andric 
1545*700637cbSDimitry Andric   // On COFF, don't mark 'extern_weak' symbols as DSO local. If these symbols
1546*700637cbSDimitry Andric   // remain unresolved in the link, they can be resolved to zero, which is
1547*700637cbSDimitry Andric   // outside the current DSO.
1548*700637cbSDimitry Andric   if (tt.isOSBinFormatCOFF() && gv.hasExternalWeakLinkage())
1549*700637cbSDimitry Andric     return false;
1550*700637cbSDimitry Andric 
1551*700637cbSDimitry Andric   // Every other GV is local on COFF.
1552*700637cbSDimitry Andric   // Make an exception for windows OS in the triple: Some firmware builds use
1553*700637cbSDimitry Andric   // *-win32-macho triples. This (accidentally?) produced windows relocations
1554*700637cbSDimitry Andric   // without GOT tables in older clang versions; Keep this behaviour.
1555*700637cbSDimitry Andric   // FIXME: even thread local variables?
1556*700637cbSDimitry Andric   if (tt.isOSBinFormatCOFF() || (tt.isOSWindows() && tt.isOSBinFormatMachO()))
1557*700637cbSDimitry Andric     return true;
1558*700637cbSDimitry Andric 
1559*700637cbSDimitry Andric   // Only handle COFF and ELF for now.
1560*700637cbSDimitry Andric   if (!tt.isOSBinFormatELF())
1561*700637cbSDimitry Andric     return false;
1562*700637cbSDimitry Andric 
1563*700637cbSDimitry Andric   llvm::Reloc::Model rm = cgOpts.RelocationModel;
1564*700637cbSDimitry Andric   const LangOptions &lOpts = cgm.getLangOpts();
1565*700637cbSDimitry Andric   if (rm != llvm::Reloc::Static && !lOpts.PIE) {
1566*700637cbSDimitry Andric     // On ELF, if -fno-semantic-interposition is specified and the target
1567*700637cbSDimitry Andric     // supports local aliases, there will be neither CC1
1568*700637cbSDimitry Andric     // -fsemantic-interposition nor -fhalf-no-semantic-interposition. Set
1569*700637cbSDimitry Andric     // dso_local on the function if using a local alias is preferable (can avoid
1570*700637cbSDimitry Andric     // PLT indirection).
1571*700637cbSDimitry Andric     if (!(isa<cir::FuncOp>(gv) && gv.canBenefitFromLocalAlias()))
1572*700637cbSDimitry Andric       return false;
1573*700637cbSDimitry Andric     return !(lOpts.SemanticInterposition || lOpts.HalfNoSemanticInterposition);
1574*700637cbSDimitry Andric   }
1575*700637cbSDimitry Andric 
1576*700637cbSDimitry Andric   // A definition cannot be preempted from an executable.
1577*700637cbSDimitry Andric   if (!gv.isDeclarationForLinker())
1578*700637cbSDimitry Andric     return true;
1579*700637cbSDimitry Andric 
1580*700637cbSDimitry Andric   // Most PIC code sequences that assume that a symbol is local cannot produce a
1581*700637cbSDimitry Andric   // 0 if it turns out the symbol is undefined. While this is ABI and relocation
1582*700637cbSDimitry Andric   // depended, it seems worth it to handle it here.
1583*700637cbSDimitry Andric   if (rm == llvm::Reloc::PIC_ && gv.hasExternalWeakLinkage())
1584*700637cbSDimitry Andric     return false;
1585*700637cbSDimitry Andric 
1586*700637cbSDimitry Andric   // PowerPC64 prefers TOC indirection to avoid copy relocations.
1587*700637cbSDimitry Andric   if (tt.isPPC64())
1588*700637cbSDimitry Andric     return false;
1589*700637cbSDimitry Andric 
1590*700637cbSDimitry Andric   if (cgOpts.DirectAccessExternalData) {
1591*700637cbSDimitry Andric     // If -fdirect-access-external-data (default for -fno-pic), set dso_local
1592*700637cbSDimitry Andric     // for non-thread-local variables. If the symbol is not defined in the
1593*700637cbSDimitry Andric     // executable, a copy relocation will be needed at link time. dso_local is
1594*700637cbSDimitry Andric     // excluded for thread-local variables because they generally don't support
1595*700637cbSDimitry Andric     // copy relocations.
1596*700637cbSDimitry Andric     if (auto globalOp = dyn_cast<cir::GlobalOp>(gv.getOperation())) {
1597*700637cbSDimitry Andric       // Assume variables are not thread-local until that support is added.
1598*700637cbSDimitry Andric       assert(!cir::MissingFeatures::opGlobalThreadLocal());
1599*700637cbSDimitry Andric       return true;
1600*700637cbSDimitry Andric     }
1601*700637cbSDimitry Andric 
1602*700637cbSDimitry Andric     // -fno-pic sets dso_local on a function declaration to allow direct
1603*700637cbSDimitry Andric     // accesses when taking its address (similar to a data symbol). If the
1604*700637cbSDimitry Andric     // function is not defined in the executable, a canonical PLT entry will be
1605*700637cbSDimitry Andric     // needed at link time. -fno-direct-access-external-data can avoid the
1606*700637cbSDimitry Andric     // canonical PLT entry. We don't generalize this condition to -fpie/-fpic as
1607*700637cbSDimitry Andric     // it could just cause trouble without providing perceptible benefits.
1608*700637cbSDimitry Andric     if (isa<cir::FuncOp>(gv) && !cgOpts.NoPLT && rm == llvm::Reloc::Static)
1609*700637cbSDimitry Andric       return true;
1610*700637cbSDimitry Andric   }
1611*700637cbSDimitry Andric 
1612*700637cbSDimitry Andric   // If we can use copy relocations we can assume it is local.
1613*700637cbSDimitry Andric 
1614*700637cbSDimitry Andric   // Otherwise don't assume it is local.
1615*700637cbSDimitry Andric 
1616*700637cbSDimitry Andric   return false;
1617*700637cbSDimitry Andric }
1618*700637cbSDimitry Andric 
setGlobalVisibility(mlir::Operation * gv,const NamedDecl * d) const1619*700637cbSDimitry Andric void CIRGenModule::setGlobalVisibility(mlir::Operation *gv,
1620*700637cbSDimitry Andric                                        const NamedDecl *d) const {
1621*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opGlobalVisibility());
1622*700637cbSDimitry Andric }
1623*700637cbSDimitry Andric 
setDSOLocal(cir::CIRGlobalValueInterface gv) const1624*700637cbSDimitry Andric void CIRGenModule::setDSOLocal(cir::CIRGlobalValueInterface gv) const {
1625*700637cbSDimitry Andric   gv.setDSOLocal(shouldAssumeDSOLocal(*this, gv));
1626*700637cbSDimitry Andric }
1627*700637cbSDimitry Andric 
setDSOLocal(mlir::Operation * op) const1628*700637cbSDimitry Andric void CIRGenModule::setDSOLocal(mlir::Operation *op) const {
1629*700637cbSDimitry Andric   if (auto globalValue = dyn_cast<cir::CIRGlobalValueInterface>(op))
1630*700637cbSDimitry Andric     setDSOLocal(globalValue);
1631*700637cbSDimitry Andric }
1632*700637cbSDimitry Andric 
setGVProperties(mlir::Operation * op,const NamedDecl * d) const1633*700637cbSDimitry Andric void CIRGenModule::setGVProperties(mlir::Operation *op,
1634*700637cbSDimitry Andric                                    const NamedDecl *d) const {
1635*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opGlobalDLLImportExport());
1636*700637cbSDimitry Andric   setGVPropertiesAux(op, d);
1637*700637cbSDimitry Andric }
1638*700637cbSDimitry Andric 
setGVPropertiesAux(mlir::Operation * op,const NamedDecl * d) const1639*700637cbSDimitry Andric void CIRGenModule::setGVPropertiesAux(mlir::Operation *op,
1640*700637cbSDimitry Andric                                       const NamedDecl *d) const {
1641*700637cbSDimitry Andric   setGlobalVisibility(op, d);
1642*700637cbSDimitry Andric   setDSOLocal(op);
1643*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opGlobalPartition());
1644*700637cbSDimitry Andric }
1645*700637cbSDimitry Andric 
setFunctionAttributes(GlobalDecl globalDecl,cir::FuncOp func,bool isIncompleteFunction,bool isThunk)1646*700637cbSDimitry Andric void CIRGenModule::setFunctionAttributes(GlobalDecl globalDecl,
1647*700637cbSDimitry Andric                                          cir::FuncOp func,
1648*700637cbSDimitry Andric                                          bool isIncompleteFunction,
1649*700637cbSDimitry Andric                                          bool isThunk) {
1650*700637cbSDimitry Andric   // NOTE(cir): Original CodeGen checks if this is an intrinsic. In CIR we
1651*700637cbSDimitry Andric   // represent them in dedicated ops. The correct attributes are ensured during
1652*700637cbSDimitry Andric   // translation to LLVM. Thus, we don't need to check for them here.
1653*700637cbSDimitry Andric 
1654*700637cbSDimitry Andric   assert(!cir::MissingFeatures::setFunctionAttributes());
1655*700637cbSDimitry Andric   assert(!cir::MissingFeatures::setTargetAttributes());
1656*700637cbSDimitry Andric 
1657*700637cbSDimitry Andric   // TODO(cir): This needs a lot of work to better match CodeGen. That
1658*700637cbSDimitry Andric   // ultimately ends up in setGlobalVisibility, which already has the linkage of
1659*700637cbSDimitry Andric   // the LLVM GV (corresponding to our FuncOp) computed, so it doesn't have to
1660*700637cbSDimitry Andric   // recompute it here. This is a minimal fix for now.
1661*700637cbSDimitry Andric   if (!isLocalLinkage(getFunctionLinkage(globalDecl))) {
1662*700637cbSDimitry Andric     const Decl *decl = globalDecl.getDecl();
1663*700637cbSDimitry Andric     func.setGlobalVisibilityAttr(getGlobalVisibilityAttrFromDecl(decl));
1664*700637cbSDimitry Andric   }
1665*700637cbSDimitry Andric }
1666*700637cbSDimitry Andric 
getOrCreateCIRFunction(StringRef mangledName,mlir::Type funcType,GlobalDecl gd,bool forVTable,bool dontDefer,bool isThunk,ForDefinition_t isForDefinition,mlir::ArrayAttr extraAttrs)1667*700637cbSDimitry Andric cir::FuncOp CIRGenModule::getOrCreateCIRFunction(
1668*700637cbSDimitry Andric     StringRef mangledName, mlir::Type funcType, GlobalDecl gd, bool forVTable,
1669*700637cbSDimitry Andric     bool dontDefer, bool isThunk, ForDefinition_t isForDefinition,
1670*700637cbSDimitry Andric     mlir::ArrayAttr extraAttrs) {
1671*700637cbSDimitry Andric   const Decl *d = gd.getDecl();
1672*700637cbSDimitry Andric 
1673*700637cbSDimitry Andric   if (isThunk)
1674*700637cbSDimitry Andric     errorNYI(d->getSourceRange(), "getOrCreateCIRFunction: thunk");
1675*700637cbSDimitry Andric 
1676*700637cbSDimitry Andric   // In what follows, we continue past 'errorNYI' as if nothing happened because
1677*700637cbSDimitry Andric   // the rest of the implementation is better than doing nothing.
1678*700637cbSDimitry Andric 
1679*700637cbSDimitry Andric   if (const auto *fd = cast_or_null<FunctionDecl>(d)) {
1680*700637cbSDimitry Andric     // For the device mark the function as one that should be emitted.
1681*700637cbSDimitry Andric     if (getLangOpts().OpenMPIsTargetDevice && fd->isDefined() && !dontDefer &&
1682*700637cbSDimitry Andric         !isForDefinition)
1683*700637cbSDimitry Andric       errorNYI(fd->getSourceRange(),
1684*700637cbSDimitry Andric                "getOrCreateCIRFunction: OpenMP target function");
1685*700637cbSDimitry Andric 
1686*700637cbSDimitry Andric     // Any attempts to use a MultiVersion function should result in retrieving
1687*700637cbSDimitry Andric     // the iFunc instead. Name mangling will handle the rest of the changes.
1688*700637cbSDimitry Andric     if (fd->isMultiVersion())
1689*700637cbSDimitry Andric       errorNYI(fd->getSourceRange(), "getOrCreateCIRFunction: multi-version");
1690*700637cbSDimitry Andric   }
1691*700637cbSDimitry Andric 
1692*700637cbSDimitry Andric   // Lookup the entry, lazily creating it if necessary.
1693*700637cbSDimitry Andric   mlir::Operation *entry = getGlobalValue(mangledName);
1694*700637cbSDimitry Andric   if (entry) {
1695*700637cbSDimitry Andric     if (!isa<cir::FuncOp>(entry))
1696*700637cbSDimitry Andric       errorNYI(d->getSourceRange(), "getOrCreateCIRFunction: non-FuncOp");
1697*700637cbSDimitry Andric 
1698*700637cbSDimitry Andric     assert(!cir::MissingFeatures::weakRefReference());
1699*700637cbSDimitry Andric 
1700*700637cbSDimitry Andric     // Handle dropped DLL attributes.
1701*700637cbSDimitry Andric     if (d && !d->hasAttr<DLLImportAttr>() && !d->hasAttr<DLLExportAttr>()) {
1702*700637cbSDimitry Andric       assert(!cir::MissingFeatures::setDLLStorageClass());
1703*700637cbSDimitry Andric       setDSOLocal(entry);
1704*700637cbSDimitry Andric     }
1705*700637cbSDimitry Andric 
1706*700637cbSDimitry Andric     // If there are two attempts to define the same mangled name, issue an
1707*700637cbSDimitry Andric     // error.
1708*700637cbSDimitry Andric     auto fn = cast<cir::FuncOp>(entry);
1709*700637cbSDimitry Andric     if (isForDefinition && fn && !fn.isDeclaration()) {
1710*700637cbSDimitry Andric       errorNYI(d->getSourceRange(), "Duplicate function definition");
1711*700637cbSDimitry Andric     }
1712*700637cbSDimitry Andric     if (fn && fn.getFunctionType() == funcType) {
1713*700637cbSDimitry Andric       return fn;
1714*700637cbSDimitry Andric     }
1715*700637cbSDimitry Andric 
1716*700637cbSDimitry Andric     if (!isForDefinition) {
1717*700637cbSDimitry Andric       return fn;
1718*700637cbSDimitry Andric     }
1719*700637cbSDimitry Andric 
1720*700637cbSDimitry Andric     // TODO(cir): classic codegen checks here if this is a llvm::GlobalAlias.
1721*700637cbSDimitry Andric     // How will we support this?
1722*700637cbSDimitry Andric   }
1723*700637cbSDimitry Andric 
1724*700637cbSDimitry Andric   auto *funcDecl = llvm::cast_or_null<FunctionDecl>(gd.getDecl());
1725*700637cbSDimitry Andric   bool invalidLoc = !funcDecl ||
1726*700637cbSDimitry Andric                     funcDecl->getSourceRange().getBegin().isInvalid() ||
1727*700637cbSDimitry Andric                     funcDecl->getSourceRange().getEnd().isInvalid();
1728*700637cbSDimitry Andric   cir::FuncOp funcOp = createCIRFunction(
1729*700637cbSDimitry Andric       invalidLoc ? theModule->getLoc() : getLoc(funcDecl->getSourceRange()),
1730*700637cbSDimitry Andric       mangledName, mlir::cast<cir::FuncType>(funcType), funcDecl);
1731*700637cbSDimitry Andric 
1732*700637cbSDimitry Andric   if (d)
1733*700637cbSDimitry Andric     setFunctionAttributes(gd, funcOp, /*isIncompleteFunction=*/false, isThunk);
1734*700637cbSDimitry Andric 
1735*700637cbSDimitry Andric   // 'dontDefer' actually means don't move this to the deferredDeclsToEmit list.
1736*700637cbSDimitry Andric   if (dontDefer) {
1737*700637cbSDimitry Andric     // TODO(cir): This assertion will need an additional condition when we
1738*700637cbSDimitry Andric     // support incomplete functions.
1739*700637cbSDimitry Andric     assert(funcOp.getFunctionType() == funcType);
1740*700637cbSDimitry Andric     return funcOp;
1741*700637cbSDimitry Andric   }
1742*700637cbSDimitry Andric 
1743*700637cbSDimitry Andric   // All MSVC dtors other than the base dtor are linkonce_odr and delegate to
1744*700637cbSDimitry Andric   // each other bottoming out wiht the base dtor. Therefore we emit non-base
1745*700637cbSDimitry Andric   // dtors on usage, even if there is no dtor definition in the TU.
1746*700637cbSDimitry Andric   if (isa_and_nonnull<CXXDestructorDecl>(d) &&
1747*700637cbSDimitry Andric       getCXXABI().useThunkForDtorVariant(cast<CXXDestructorDecl>(d),
1748*700637cbSDimitry Andric                                          gd.getDtorType()))
1749*700637cbSDimitry Andric     errorNYI(d->getSourceRange(), "getOrCreateCIRFunction: dtor");
1750*700637cbSDimitry Andric 
1751*700637cbSDimitry Andric   // This is the first use or definition of a mangled name. If there is a
1752*700637cbSDimitry Andric   // deferred decl with this name, remember that we need to emit it at the end
1753*700637cbSDimitry Andric   // of the file.
1754*700637cbSDimitry Andric   auto ddi = deferredDecls.find(mangledName);
1755*700637cbSDimitry Andric   if (ddi != deferredDecls.end()) {
1756*700637cbSDimitry Andric     // Move the potentially referenced deferred decl to the
1757*700637cbSDimitry Andric     // DeferredDeclsToEmit list, and remove it from DeferredDecls (since we
1758*700637cbSDimitry Andric     // don't need it anymore).
1759*700637cbSDimitry Andric     addDeferredDeclToEmit(ddi->second);
1760*700637cbSDimitry Andric     deferredDecls.erase(ddi);
1761*700637cbSDimitry Andric 
1762*700637cbSDimitry Andric     // Otherwise, there are cases we have to worry about where we're using a
1763*700637cbSDimitry Andric     // declaration for which we must emit a definition but where we might not
1764*700637cbSDimitry Andric     // find a top-level definition.
1765*700637cbSDimitry Andric     //   - member functions defined inline in their classes
1766*700637cbSDimitry Andric     //   - friend functions defined inline in some class
1767*700637cbSDimitry Andric     //   - special member functions with implicit definitions
1768*700637cbSDimitry Andric     // If we ever change our AST traversal to walk into class methods, this
1769*700637cbSDimitry Andric     // will be unnecessary.
1770*700637cbSDimitry Andric     //
1771*700637cbSDimitry Andric     // We also don't emit a definition for a function if it's going to be an
1772*700637cbSDimitry Andric     // entry in a vtable, unless it's already marked as used.
1773*700637cbSDimitry Andric   } else if (getLangOpts().CPlusPlus && d) {
1774*700637cbSDimitry Andric     // Look for a declaration that's lexically in a record.
1775*700637cbSDimitry Andric     for (const auto *fd = cast<FunctionDecl>(d)->getMostRecentDecl(); fd;
1776*700637cbSDimitry Andric          fd = fd->getPreviousDecl()) {
1777*700637cbSDimitry Andric       if (isa<CXXRecordDecl>(fd->getLexicalDeclContext())) {
1778*700637cbSDimitry Andric         if (fd->doesThisDeclarationHaveABody()) {
1779*700637cbSDimitry Andric           addDeferredDeclToEmit(gd.getWithDecl(fd));
1780*700637cbSDimitry Andric           break;
1781*700637cbSDimitry Andric         }
1782*700637cbSDimitry Andric       }
1783*700637cbSDimitry Andric     }
1784*700637cbSDimitry Andric   }
1785*700637cbSDimitry Andric 
1786*700637cbSDimitry Andric   return funcOp;
1787*700637cbSDimitry Andric }
1788*700637cbSDimitry Andric 
1789*700637cbSDimitry Andric cir::FuncOp
createCIRFunction(mlir::Location loc,StringRef name,cir::FuncType funcType,const clang::FunctionDecl * funcDecl)1790*700637cbSDimitry Andric CIRGenModule::createCIRFunction(mlir::Location loc, StringRef name,
1791*700637cbSDimitry Andric                                 cir::FuncType funcType,
1792*700637cbSDimitry Andric                                 const clang::FunctionDecl *funcDecl) {
1793*700637cbSDimitry Andric   cir::FuncOp func;
1794*700637cbSDimitry Andric   {
1795*700637cbSDimitry Andric     mlir::OpBuilder::InsertionGuard guard(builder);
1796*700637cbSDimitry Andric 
1797*700637cbSDimitry Andric     // Some global emissions are triggered while emitting a function, e.g.
1798*700637cbSDimitry Andric     // void s() { x.method() }
1799*700637cbSDimitry Andric     //
1800*700637cbSDimitry Andric     // Be sure to insert a new function before a current one.
1801*700637cbSDimitry Andric     CIRGenFunction *cgf = this->curCGF;
1802*700637cbSDimitry Andric     if (cgf)
1803*700637cbSDimitry Andric       builder.setInsertionPoint(cgf->curFn);
1804*700637cbSDimitry Andric 
1805*700637cbSDimitry Andric     func = builder.create<cir::FuncOp>(loc, name, funcType);
1806*700637cbSDimitry Andric 
1807*700637cbSDimitry Andric     assert(!cir::MissingFeatures::opFuncAstDeclAttr());
1808*700637cbSDimitry Andric     assert(!cir::MissingFeatures::opFuncNoProto());
1809*700637cbSDimitry Andric 
1810*700637cbSDimitry Andric     assert(func.isDeclaration() && "expected empty body");
1811*700637cbSDimitry Andric 
1812*700637cbSDimitry Andric     // A declaration gets private visibility by default, but external linkage
1813*700637cbSDimitry Andric     // as the default linkage.
1814*700637cbSDimitry Andric     func.setLinkageAttr(cir::GlobalLinkageKindAttr::get(
1815*700637cbSDimitry Andric         &getMLIRContext(), cir::GlobalLinkageKind::ExternalLinkage));
1816*700637cbSDimitry Andric     mlir::SymbolTable::setSymbolVisibility(
1817*700637cbSDimitry Andric         func, mlir::SymbolTable::Visibility::Private);
1818*700637cbSDimitry Andric 
1819*700637cbSDimitry Andric     assert(!cir::MissingFeatures::opFuncExtraAttrs());
1820*700637cbSDimitry Andric 
1821*700637cbSDimitry Andric     if (!cgf)
1822*700637cbSDimitry Andric       theModule.push_back(func);
1823*700637cbSDimitry Andric   }
1824*700637cbSDimitry Andric   return func;
1825*700637cbSDimitry Andric }
1826*700637cbSDimitry Andric 
1827*700637cbSDimitry Andric mlir::SymbolTable::Visibility
getMLIRVisibilityFromCIRLinkage(cir::GlobalLinkageKind glk)1828*700637cbSDimitry Andric CIRGenModule::getMLIRVisibilityFromCIRLinkage(cir::GlobalLinkageKind glk) {
1829*700637cbSDimitry Andric   switch (glk) {
1830*700637cbSDimitry Andric   case cir::GlobalLinkageKind::InternalLinkage:
1831*700637cbSDimitry Andric   case cir::GlobalLinkageKind::PrivateLinkage:
1832*700637cbSDimitry Andric     return mlir::SymbolTable::Visibility::Private;
1833*700637cbSDimitry Andric   case cir::GlobalLinkageKind::ExternalLinkage:
1834*700637cbSDimitry Andric   case cir::GlobalLinkageKind::ExternalWeakLinkage:
1835*700637cbSDimitry Andric   case cir::GlobalLinkageKind::LinkOnceODRLinkage:
1836*700637cbSDimitry Andric   case cir::GlobalLinkageKind::AvailableExternallyLinkage:
1837*700637cbSDimitry Andric   case cir::GlobalLinkageKind::CommonLinkage:
1838*700637cbSDimitry Andric   case cir::GlobalLinkageKind::WeakAnyLinkage:
1839*700637cbSDimitry Andric   case cir::GlobalLinkageKind::WeakODRLinkage:
1840*700637cbSDimitry Andric     return mlir::SymbolTable::Visibility::Public;
1841*700637cbSDimitry Andric   default: {
1842*700637cbSDimitry Andric     llvm::errs() << "visibility not implemented for '"
1843*700637cbSDimitry Andric                  << stringifyGlobalLinkageKind(glk) << "'\n";
1844*700637cbSDimitry Andric     assert(0 && "not implemented");
1845*700637cbSDimitry Andric   }
1846*700637cbSDimitry Andric   }
1847*700637cbSDimitry Andric   llvm_unreachable("linkage should be handled above!");
1848*700637cbSDimitry Andric }
1849*700637cbSDimitry Andric 
getGlobalVisibilityKindFromClangVisibility(clang::VisibilityAttr::VisibilityType visibility)1850*700637cbSDimitry Andric cir::VisibilityKind CIRGenModule::getGlobalVisibilityKindFromClangVisibility(
1851*700637cbSDimitry Andric     clang::VisibilityAttr::VisibilityType visibility) {
1852*700637cbSDimitry Andric   switch (visibility) {
1853*700637cbSDimitry Andric   case clang::VisibilityAttr::VisibilityType::Default:
1854*700637cbSDimitry Andric     return cir::VisibilityKind::Default;
1855*700637cbSDimitry Andric   case clang::VisibilityAttr::VisibilityType::Hidden:
1856*700637cbSDimitry Andric     return cir::VisibilityKind::Hidden;
1857*700637cbSDimitry Andric   case clang::VisibilityAttr::VisibilityType::Protected:
1858*700637cbSDimitry Andric     return cir::VisibilityKind::Protected;
1859*700637cbSDimitry Andric   }
1860*700637cbSDimitry Andric   llvm_unreachable("unexpected visibility value");
1861*700637cbSDimitry Andric }
1862*700637cbSDimitry Andric 
1863*700637cbSDimitry Andric cir::VisibilityAttr
getGlobalVisibilityAttrFromDecl(const Decl * decl)1864*700637cbSDimitry Andric CIRGenModule::getGlobalVisibilityAttrFromDecl(const Decl *decl) {
1865*700637cbSDimitry Andric   const clang::VisibilityAttr *va = decl->getAttr<clang::VisibilityAttr>();
1866*700637cbSDimitry Andric   cir::VisibilityAttr cirVisibility =
1867*700637cbSDimitry Andric       cir::VisibilityAttr::get(&getMLIRContext());
1868*700637cbSDimitry Andric   if (va) {
1869*700637cbSDimitry Andric     cirVisibility = cir::VisibilityAttr::get(
1870*700637cbSDimitry Andric         &getMLIRContext(),
1871*700637cbSDimitry Andric         getGlobalVisibilityKindFromClangVisibility(va->getVisibility()));
1872*700637cbSDimitry Andric   }
1873*700637cbSDimitry Andric   return cirVisibility;
1874*700637cbSDimitry Andric }
1875*700637cbSDimitry Andric 
release()1876*700637cbSDimitry Andric void CIRGenModule::release() {
1877*700637cbSDimitry Andric   emitDeferred();
1878*700637cbSDimitry Andric   applyReplacements();
1879*700637cbSDimitry Andric 
1880*700637cbSDimitry Andric   // There's a lot of code that is not implemented yet.
1881*700637cbSDimitry Andric   assert(!cir::MissingFeatures::cgmRelease());
1882*700637cbSDimitry Andric }
1883*700637cbSDimitry Andric 
emitAliasForGlobal(StringRef mangledName,mlir::Operation * op,GlobalDecl aliasGD,cir::FuncOp aliasee,cir::GlobalLinkageKind linkage)1884*700637cbSDimitry Andric void CIRGenModule::emitAliasForGlobal(StringRef mangledName,
1885*700637cbSDimitry Andric                                       mlir::Operation *op, GlobalDecl aliasGD,
1886*700637cbSDimitry Andric                                       cir::FuncOp aliasee,
1887*700637cbSDimitry Andric                                       cir::GlobalLinkageKind linkage) {
1888*700637cbSDimitry Andric 
1889*700637cbSDimitry Andric   auto *aliasFD = dyn_cast<FunctionDecl>(aliasGD.getDecl());
1890*700637cbSDimitry Andric   assert(aliasFD && "expected FunctionDecl");
1891*700637cbSDimitry Andric 
1892*700637cbSDimitry Andric   // The aliasee function type is different from the alias one, this difference
1893*700637cbSDimitry Andric   // is specific to CIR because in LLVM the ptr types are already erased at this
1894*700637cbSDimitry Andric   // point.
1895*700637cbSDimitry Andric   const CIRGenFunctionInfo &fnInfo =
1896*700637cbSDimitry Andric       getTypes().arrangeCXXStructorDeclaration(aliasGD);
1897*700637cbSDimitry Andric   cir::FuncType fnType = getTypes().getFunctionType(fnInfo);
1898*700637cbSDimitry Andric 
1899*700637cbSDimitry Andric   cir::FuncOp alias =
1900*700637cbSDimitry Andric       createCIRFunction(getLoc(aliasGD.getDecl()->getSourceRange()),
1901*700637cbSDimitry Andric                         mangledName, fnType, aliasFD);
1902*700637cbSDimitry Andric   alias.setAliasee(aliasee.getName());
1903*700637cbSDimitry Andric   alias.setLinkage(linkage);
1904*700637cbSDimitry Andric   // Declarations cannot have public MLIR visibility, just mark them private
1905*700637cbSDimitry Andric   // but this really should have no meaning since CIR should not be using
1906*700637cbSDimitry Andric   // this information to derive linkage information.
1907*700637cbSDimitry Andric   mlir::SymbolTable::setSymbolVisibility(
1908*700637cbSDimitry Andric       alias, mlir::SymbolTable::Visibility::Private);
1909*700637cbSDimitry Andric 
1910*700637cbSDimitry Andric   // Alias constructors and destructors are always unnamed_addr.
1911*700637cbSDimitry Andric   assert(!cir::MissingFeatures::opGlobalUnnamedAddr());
1912*700637cbSDimitry Andric 
1913*700637cbSDimitry Andric   // Switch any previous uses to the alias.
1914*700637cbSDimitry Andric   if (op) {
1915*700637cbSDimitry Andric     errorNYI(aliasFD->getSourceRange(), "emitAliasForGlobal: previous uses");
1916*700637cbSDimitry Andric   } else {
1917*700637cbSDimitry Andric     // Name already set by createCIRFunction
1918*700637cbSDimitry Andric   }
1919*700637cbSDimitry Andric 
1920*700637cbSDimitry Andric   // Finally, set up the alias with its proper name and attributes.
1921*700637cbSDimitry Andric   setCommonAttributes(aliasGD, alias);
1922*700637cbSDimitry Andric }
1923*700637cbSDimitry Andric 
convertType(QualType type)1924*700637cbSDimitry Andric mlir::Type CIRGenModule::convertType(QualType type) {
1925*700637cbSDimitry Andric   return genTypes.convertType(type);
1926*700637cbSDimitry Andric }
1927*700637cbSDimitry Andric 
verifyModule() const1928*700637cbSDimitry Andric bool CIRGenModule::verifyModule() const {
1929*700637cbSDimitry Andric   // Verify the module after we have finished constructing it, this will
1930*700637cbSDimitry Andric   // check the structural properties of the IR and invoke any specific
1931*700637cbSDimitry Andric   // verifiers we have on the CIR operations.
1932*700637cbSDimitry Andric   return mlir::verify(theModule).succeeded();
1933*700637cbSDimitry Andric }
1934*700637cbSDimitry Andric 
1935*700637cbSDimitry Andric // TODO(cir): this can be shared with LLVM codegen.
computeNonVirtualBaseClassOffset(const CXXRecordDecl * derivedClass,llvm::iterator_range<CastExpr::path_const_iterator> path)1936*700637cbSDimitry Andric CharUnits CIRGenModule::computeNonVirtualBaseClassOffset(
1937*700637cbSDimitry Andric     const CXXRecordDecl *derivedClass,
1938*700637cbSDimitry Andric     llvm::iterator_range<CastExpr::path_const_iterator> path) {
1939*700637cbSDimitry Andric   CharUnits offset = CharUnits::Zero();
1940*700637cbSDimitry Andric 
1941*700637cbSDimitry Andric   const ASTContext &astContext = getASTContext();
1942*700637cbSDimitry Andric   const CXXRecordDecl *rd = derivedClass;
1943*700637cbSDimitry Andric 
1944*700637cbSDimitry Andric   for (const CXXBaseSpecifier *base : path) {
1945*700637cbSDimitry Andric     assert(!base->isVirtual() && "Should not see virtual bases here!");
1946*700637cbSDimitry Andric 
1947*700637cbSDimitry Andric     // Get the layout.
1948*700637cbSDimitry Andric     const ASTRecordLayout &layout = astContext.getASTRecordLayout(rd);
1949*700637cbSDimitry Andric 
1950*700637cbSDimitry Andric     const auto *baseDecl = cast<CXXRecordDecl>(
1951*700637cbSDimitry Andric         base->getType()->castAs<clang::RecordType>()->getDecl());
1952*700637cbSDimitry Andric 
1953*700637cbSDimitry Andric     // Add the offset.
1954*700637cbSDimitry Andric     offset += layout.getBaseClassOffset(baseDecl);
1955*700637cbSDimitry Andric 
1956*700637cbSDimitry Andric     rd = baseDecl;
1957*700637cbSDimitry Andric   }
1958*700637cbSDimitry Andric 
1959*700637cbSDimitry Andric   return offset;
1960*700637cbSDimitry Andric }
1961*700637cbSDimitry Andric 
errorNYI(SourceLocation loc,llvm::StringRef feature)1962*700637cbSDimitry Andric DiagnosticBuilder CIRGenModule::errorNYI(SourceLocation loc,
1963*700637cbSDimitry Andric                                          llvm::StringRef feature) {
1964*700637cbSDimitry Andric   unsigned diagID = diags.getCustomDiagID(
1965*700637cbSDimitry Andric       DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0");
1966*700637cbSDimitry Andric   return diags.Report(loc, diagID) << feature;
1967*700637cbSDimitry Andric }
1968*700637cbSDimitry Andric 
errorNYI(SourceRange loc,llvm::StringRef feature)1969*700637cbSDimitry Andric DiagnosticBuilder CIRGenModule::errorNYI(SourceRange loc,
1970*700637cbSDimitry Andric                                          llvm::StringRef feature) {
1971*700637cbSDimitry Andric   return errorNYI(loc.getBegin(), feature) << loc;
1972*700637cbSDimitry Andric }
1973