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