clang 23.0.0git
CIRGenModule.cpp
Go to the documentation of this file.
1//===- CIRGenModule.cpp - Per-Module state for CIR generation -------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This is the internal per-translation-unit state used for CIR translation.
10//
11//===----------------------------------------------------------------------===//
12
13#include "CIRGenModule.h"
14#include "CIRGenCUDARuntime.h"
15#include "CIRGenCXXABI.h"
17#include "CIRGenFunction.h"
18
20#include "clang/AST/ASTLambda.h"
21#include "clang/AST/Attrs.inc"
22#include "clang/AST/DeclBase.h"
33
34#include "CIRGenFunctionInfo.h"
35#include "TargetInfo.h"
36#include "mlir/IR/BuiltinOps.h"
37#include "mlir/IR/Location.h"
38#include "mlir/IR/MLIRContext.h"
39#include "mlir/IR/Operation.h"
40#include "mlir/IR/Verifier.h"
41
42#include <algorithm>
43
44using namespace clang;
45using namespace clang::CIRGen;
46
48 switch (cgm.getASTContext().getCXXABIKind()) {
49 case TargetCXXABI::GenericItanium:
50 case TargetCXXABI::GenericAArch64:
51 case TargetCXXABI::AppleARM64:
52 return CreateCIRGenItaniumCXXABI(cgm);
53
54 case TargetCXXABI::Fuchsia:
55 case TargetCXXABI::GenericARM:
56 case TargetCXXABI::iOS:
57 case TargetCXXABI::WatchOS:
58 case TargetCXXABI::GenericMIPS:
59 case TargetCXXABI::WebAssembly:
60 case TargetCXXABI::XL:
61 case TargetCXXABI::Microsoft:
62 cgm.errorNYI("createCXXABI: C++ ABI kind");
63 return nullptr;
64 }
65
66 llvm_unreachable("invalid C++ ABI kind");
67}
68
69CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,
70 clang::ASTContext &astContext,
71 const clang::CodeGenOptions &cgo,
72 DiagnosticsEngine &diags)
73 : builder(mlirContext, *this), astContext(astContext),
74 langOpts(astContext.getLangOpts()), codeGenOpts(cgo),
75 theModule{mlir::ModuleOp::create(mlir::UnknownLoc::get(&mlirContext))},
76 diags(diags), target(astContext.getTargetInfo()),
77 abi(createCXXABI(*this)), genTypes(*this), vtables(*this) {
78
79 // Initialize cached types
80 voidTy = cir::VoidType::get(&getMLIRContext());
81 voidPtrTy = cir::PointerType::get(voidTy);
82 sInt8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/true);
83 sInt16Ty = cir::IntType::get(&getMLIRContext(), 16, /*isSigned=*/true);
84 sInt32Ty = cir::IntType::get(&getMLIRContext(), 32, /*isSigned=*/true);
85 sInt64Ty = cir::IntType::get(&getMLIRContext(), 64, /*isSigned=*/true);
86 sInt128Ty = cir::IntType::get(&getMLIRContext(), 128, /*isSigned=*/true);
87 uInt8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/false);
88 uInt8PtrTy = cir::PointerType::get(uInt8Ty);
90 uInt16Ty = cir::IntType::get(&getMLIRContext(), 16, /*isSigned=*/false);
91 uInt32Ty = cir::IntType::get(&getMLIRContext(), 32, /*isSigned=*/false);
92 uInt64Ty = cir::IntType::get(&getMLIRContext(), 64, /*isSigned=*/false);
93 uInt128Ty = cir::IntType::get(&getMLIRContext(), 128, /*isSigned=*/false);
94 fP16Ty = cir::FP16Type::get(&getMLIRContext());
95 bFloat16Ty = cir::BF16Type::get(&getMLIRContext());
96 floatTy = cir::SingleType::get(&getMLIRContext());
97 doubleTy = cir::DoubleType::get(&getMLIRContext());
98 fP80Ty = cir::FP80Type::get(&getMLIRContext());
99 fP128Ty = cir::FP128Type::get(&getMLIRContext());
100
101 allocaInt8PtrTy = cir::PointerType::get(uInt8Ty, cirAllocaAddressSpace);
102
104 astContext
105 .toCharUnitsFromBits(
106 astContext.getTargetInfo().getPointerAlign(LangAS::Default))
107 .getQuantity();
108
109 const unsigned charSize = astContext.getTargetInfo().getCharWidth();
110 uCharTy = cir::IntType::get(&getMLIRContext(), charSize, /*isSigned=*/false);
111
112 // TODO(CIR): Should be updated once TypeSizeInfoAttr is upstreamed
113 const unsigned sizeTypeSize =
114 astContext.getTypeSize(astContext.getSignedSizeType());
115 SizeSizeInBytes = astContext.toCharUnitsFromBits(sizeTypeSize).getQuantity();
116 // In CIRGenTypeCache, UIntPtrTy and SizeType are fields of the same union
117 uIntPtrTy =
118 cir::IntType::get(&getMLIRContext(), sizeTypeSize, /*isSigned=*/false);
119 ptrDiffTy =
120 cir::IntType::get(&getMLIRContext(), sizeTypeSize, /*isSigned=*/true);
121
122 std::optional<cir::SourceLanguage> sourceLanguage = getCIRSourceLanguage();
123 if (sourceLanguage)
124 theModule->setAttr(
125 cir::CIRDialect::getSourceLanguageAttrName(),
126 cir::SourceLanguageAttr::get(&mlirContext, *sourceLanguage));
127 theModule->setAttr(cir::CIRDialect::getTripleAttrName(),
128 builder.getStringAttr(getTriple().str()));
129
130 if (cgo.OptimizationLevel > 0 || cgo.OptimizeSize > 0)
131 theModule->setAttr(cir::CIRDialect::getOptInfoAttrName(),
132 cir::OptInfoAttr::get(&mlirContext,
133 cgo.OptimizationLevel,
134 cgo.OptimizeSize));
135
136 if (langOpts.CUDA)
137 createCUDARuntime();
138
139 // Set the module name to be the name of the main file. TranslationUnitDecl
140 // often contains invalid source locations and isn't a reliable source for the
141 // module location.
142 FileID mainFileId = astContext.getSourceManager().getMainFileID();
143 const FileEntry &mainFile =
144 *astContext.getSourceManager().getFileEntryForID(mainFileId);
145 StringRef path = mainFile.tryGetRealPathName();
146 if (!path.empty()) {
147 theModule.setSymName(path);
148 theModule->setLoc(mlir::FileLineColLoc::get(&mlirContext, path,
149 /*line=*/0,
150 /*column=*/0));
151 }
152}
153
155
156void CIRGenModule::createCUDARuntime() {
157 cudaRuntime.reset(createNVCUDARuntime(*this));
158}
159
160/// FIXME: this could likely be a common helper and not necessarily related
161/// with codegen.
162/// Return the best known alignment for an unknown pointer to a
163/// particular class.
165 if (!rd->hasDefinition())
166 return CharUnits::One(); // Hopefully won't be used anywhere.
167
168 auto &layout = astContext.getASTRecordLayout(rd);
169
170 // If the class is final, then we know that the pointer points to an
171 // object of that type and can use the full alignment.
172 if (rd->isEffectivelyFinal())
173 return layout.getAlignment();
174
175 // Otherwise, we have to assume it could be a subclass.
176 return layout.getNonVirtualAlignment();
177}
178
180 LValueBaseInfo *baseInfo,
181 bool forPointeeType) {
183
184 // FIXME: This duplicates logic in ASTContext::getTypeAlignIfKnown, but
185 // that doesn't return the information we need to compute baseInfo.
186
187 // Honor alignment typedef attributes even on incomplete types.
188 // We also honor them straight for C++ class types, even as pointees;
189 // there's an expressivity gap here.
190 if (const auto *tt = t->getAs<TypedefType>()) {
191 if (unsigned align = tt->getDecl()->getMaxAlignment()) {
192 if (baseInfo)
194 return astContext.toCharUnitsFromBits(align);
195 }
196 }
197
198 bool alignForArray = t->isArrayType();
199
200 // Analyze the base element type, so we don't get confused by incomplete
201 // array types.
202 t = astContext.getBaseElementType(t);
203
204 if (t->isIncompleteType()) {
205 // We could try to replicate the logic from
206 // ASTContext::getTypeAlignIfKnown, but nothing uses the alignment if the
207 // type is incomplete, so it's impossible to test. We could try to reuse
208 // getTypeAlignIfKnown, but that doesn't return the information we need
209 // to set baseInfo. So just ignore the possibility that the alignment is
210 // greater than one.
211 if (baseInfo)
213 return CharUnits::One();
214 }
215
216 if (baseInfo)
218
219 CharUnits alignment;
220 const CXXRecordDecl *rd = nullptr;
221 if (t.getQualifiers().hasUnaligned()) {
222 alignment = CharUnits::One();
223 } else if (forPointeeType && !alignForArray &&
224 (rd = t->getAsCXXRecordDecl())) {
225 alignment = getClassPointerAlignment(rd);
226 } else {
227 alignment = astContext.getTypeAlignInChars(t);
228 }
229
230 // Cap to the global maximum type alignment unless the alignment
231 // was somehow explicit on the type.
232 if (unsigned maxAlign = astContext.getLangOpts().MaxTypeAlign) {
233 if (alignment.getQuantity() > maxAlign &&
234 !astContext.isAlignmentRequired(t))
235 alignment = CharUnits::fromQuantity(maxAlign);
236 }
237 return alignment;
238}
239
241 if (theTargetCIRGenInfo)
242 return *theTargetCIRGenInfo;
243
244 const llvm::Triple &triple = getTarget().getTriple();
245 switch (triple.getArch()) {
246 default:
248
249 // Currently we just fall through to x86_64.
250 [[fallthrough]];
251
252 case llvm::Triple::x86_64: {
253 switch (triple.getOS()) {
254 default:
256
257 // Currently we just fall through to x86_64.
258 [[fallthrough]];
259
260 case llvm::Triple::Linux:
261 theTargetCIRGenInfo = createX8664TargetCIRGenInfo(genTypes);
262 return *theTargetCIRGenInfo;
263 }
264 }
265 case llvm::Triple::nvptx:
266 case llvm::Triple::nvptx64:
267 theTargetCIRGenInfo = createNVPTXTargetCIRGenInfo(genTypes);
268 return *theTargetCIRGenInfo;
269 case llvm::Triple::amdgcn: {
270 theTargetCIRGenInfo = createAMDGPUTargetCIRGenInfo(genTypes);
271 return *theTargetCIRGenInfo;
272 }
273 }
274}
275
277 assert(cLoc.isValid() && "expected valid source location");
278 const SourceManager &sm = astContext.getSourceManager();
279 PresumedLoc pLoc = sm.getPresumedLoc(cLoc);
280 StringRef filename = pLoc.getFilename();
281 return mlir::FileLineColLoc::get(builder.getStringAttr(filename),
282 pLoc.getLine(), pLoc.getColumn());
283}
284
285mlir::Location CIRGenModule::getLoc(SourceRange cRange) {
286 assert(cRange.isValid() && "expected a valid source range");
287 mlir::Location begin = getLoc(cRange.getBegin());
288 mlir::Location end = getLoc(cRange.getEnd());
289 mlir::Attribute metadata;
290 return mlir::FusedLoc::get({begin, end}, metadata, builder.getContext());
291}
292
293mlir::Operation *
295 const Decl *d = gd.getDecl();
296
298 return getAddrOfCXXStructor(gd, /*FnInfo=*/nullptr, /*FnType=*/nullptr,
299 /*DontDefer=*/false, isForDefinition);
300
301 if (isa<CXXMethodDecl>(d)) {
302 const CIRGenFunctionInfo &fi =
304 cir::FuncType ty = getTypes().getFunctionType(fi);
305 return getAddrOfFunction(gd, ty, /*ForVTable=*/false, /*DontDefer=*/false,
306 isForDefinition);
307 }
308
309 if (isa<FunctionDecl>(d)) {
311 cir::FuncType ty = getTypes().getFunctionType(fi);
312 return getAddrOfFunction(gd, ty, /*ForVTable=*/false, /*DontDefer=*/false,
313 isForDefinition);
314 }
315
316 return getAddrOfGlobalVar(cast<VarDecl>(d), /*ty=*/nullptr, isForDefinition)
317 .getDefiningOp();
318}
319
321 // We call getAddrOfGlobal with isForDefinition set to ForDefinition in
322 // order to get a Value with exactly the type we need, not something that
323 // might have been created for another decl with the same mangled name but
324 // different type.
325 mlir::Operation *op = getAddrOfGlobal(d, ForDefinition);
326
327 // In case of different address spaces, we may still get a cast, even with
328 // IsForDefinition equal to ForDefinition. Query mangled names table to get
329 // GlobalValue.
330 if (!op)
332
333 assert(op && "expected a valid global op");
334
335 // Check to see if we've already emitted this. This is necessary for a
336 // couple of reasons: first, decls can end up in deferred-decls queue
337 // multiple times, and second, decls can end up with definitions in unusual
338 // ways (e.g. by an extern inline function acquiring a strong function
339 // redefinition). Just ignore those cases.
340 // TODO: Not sure what to map this to for MLIR
341 mlir::Operation *globalValueOp = op;
342 if (auto gv = dyn_cast<cir::GetGlobalOp>(op))
343 globalValueOp =
344 mlir::SymbolTable::lookupSymbolIn(getModule(), gv.getNameAttr());
345
346 if (auto cirGlobalValue =
347 dyn_cast<cir::CIRGlobalValueInterface>(globalValueOp))
348 if (!cirGlobalValue.isDeclaration())
349 return;
350
351 // If this is OpenMP, check if it is legal to emit this global normally.
353
354 // Otherwise, emit the definition and move on to the next one.
356}
357
359 // Emit code for any potentially referenced deferred decls. Since a previously
360 // unused static decl may become used during the generation of code for a
361 // static function, iterate until no changes are made.
362
364
366 // Emitting a vtable doesn't directly cause more vtables to
367 // become deferred, although it can cause functions to be
368 // emitted that then need those vtables.
369 assert(deferredVTables.empty());
370
372
373 // Stop if we're out of both deferred vtables and deferred declarations.
374 if (deferredDeclsToEmit.empty())
375 return;
376
377 // Grab the list of decls to emit. If emitGlobalDefinition schedules more
378 // work, it will not interfere with this.
379 std::vector<GlobalDecl> curDeclsToEmit;
380 curDeclsToEmit.swap(deferredDeclsToEmit);
381
382 for (const GlobalDecl &d : curDeclsToEmit) {
384
385 // If we found out that we need to emit more decls, do that recursively.
386 // This has the advantage that the decls are emitted in a DFS and related
387 // ones are close together, which is convenient for testing.
388 if (!deferredVTables.empty() || !deferredDeclsToEmit.empty()) {
389 emitDeferred();
390 assert(deferredVTables.empty() && deferredDeclsToEmit.empty());
391 }
392 }
393}
394
395template <typename AttrT> static bool hasImplicitAttr(const ValueDecl *decl) {
396 if (!decl)
397 return false;
398 if (auto *attr = decl->getAttr<AttrT>())
399 return attr->isImplicit();
400 return decl->isImplicit();
401}
402
403// TODO(cir): This should be shared with OG Codegen.
405 assert(langOpts.CUDA && "Should not be called by non-CUDA languages");
406 // We need to emit host-side 'shadows' for all global
407 // device-side variables because the CUDA runtime needs their
408 // size and host-side address in order to provide access to
409 // their device-side incarnations.
410 return !langOpts.CUDAIsDevice || global->hasAttr<CUDADeviceAttr>() ||
411 global->hasAttr<CUDAConstantAttr>() ||
412 global->hasAttr<CUDASharedAttr>() ||
415}
416
418 if (const auto *cd = dyn_cast<clang::OpenACCConstructDecl>(gd.getDecl())) {
420 return;
421 }
422
423 // TODO(OMP): The logic in this function for the 'rest' of the OpenMP
424 // declarative declarations is complicated and needs to be done on a per-kind
425 // basis, so all of that needs to be added when we implement the individual
426 // global-allowed declarations. See uses of `cir::MissingFeatures::openMP
427 // throughout this function.
428
429 const auto *global = cast<ValueDecl>(gd.getDecl());
430
431 // If this is CUDA, be selective about which declarations we emit.
432 // Non-constexpr non-lambda implicit host device functions are not emitted
433 // unless they are used on device side.
434 if (langOpts.CUDA) {
435 assert((isa<FunctionDecl>(global) || isa<VarDecl>(global)) &&
436 "Expected Variable or Function");
437 if (const auto *varDecl = dyn_cast<VarDecl>(global)) {
439 return;
440 // TODO(cir): This should be shared with OG Codegen.
441 } else if (langOpts.CUDAIsDevice) {
442 const auto *functionDecl = dyn_cast<FunctionDecl>(global);
443 if ((!global->hasAttr<CUDADeviceAttr>() ||
444 (langOpts.OffloadImplicitHostDeviceTemplates &&
447 !functionDecl->isConstexpr() &&
449 !getASTContext().CUDAImplicitHostDeviceFunUsedByDevice.count(
450 functionDecl))) &&
451 !global->hasAttr<CUDAGlobalAttr>() &&
452 !(langOpts.HIPStdPar && isa<FunctionDecl>(global) &&
453 !global->hasAttr<CUDAHostAttr>()))
454 return;
455 // Device-only functions are the only things we skip.
456 } else if (!global->hasAttr<CUDAHostAttr>() &&
457 global->hasAttr<CUDADeviceAttr>())
458 return;
459 }
460
461 if (const auto *fd = dyn_cast<FunctionDecl>(global)) {
462 // Update deferred annotations with the latest declaration if the function
463 // was already used or defined.
464 if (fd->hasAttr<AnnotateAttr>())
465 errorNYI(fd->getSourceRange(), "deferredAnnotations");
466 if (!fd->doesThisDeclarationHaveABody()) {
467 if (!fd->doesDeclarationForceExternallyVisibleDefinition())
468 return;
469
470 errorNYI(fd->getSourceRange(),
471 "function declaration that forces code gen");
472 return;
473 }
474 } else {
475 const auto *vd = cast<VarDecl>(global);
476 assert(vd->isFileVarDecl() && "Cannot emit local var decl as global.");
477 if (vd->isThisDeclarationADefinition() != VarDecl::Definition &&
478 !astContext.isMSStaticDataMemberInlineDefinition(vd)) {
480 // If this declaration may have caused an inline variable definition to
481 // change linkage, make sure that it's emitted.
482 if (astContext.getInlineVariableDefinitionKind(vd) ==
485 // Otherwise, we can ignore this declaration. The variable will be emitted
486 // on its first use.
487 return;
488 }
489 }
490
491 // Defer code generation to first use when possible, e.g. if this is an inline
492 // function. If the global must always be emitted, do it eagerly if possible
493 // to benefit from cache locality. Deferring code generation is necessary to
494 // avoid adding initializers to external declarations.
495 if (mustBeEmitted(global) && mayBeEmittedEagerly(global)) {
496 // Emit the definition if it can't be deferred.
498 return;
499 }
500
501 // If we're deferring emission of a C++ variable with an initializer, remember
502 // the order in which it appeared on the file.
504
505 llvm::StringRef mangledName = getMangledName(gd);
506 if (getGlobalValue(mangledName) != nullptr) {
507 // The value has already been used and should therefore be emitted.
509 } else if (mustBeEmitted(global)) {
510 // The value must be emitted, but cannot be emitted eagerly.
511 assert(!mayBeEmittedEagerly(global));
513 } else {
514 // Otherwise, remember that we saw a deferred decl with this name. The first
515 // use of the mangled name will cause it to move into deferredDeclsToEmit.
516 deferredDecls[mangledName] = gd;
517 }
518}
519
521 mlir::Operation *op) {
522 auto const *funcDecl = cast<FunctionDecl>(gd.getDecl());
524 cir::FuncType funcType = getTypes().getFunctionType(fi);
525 cir::FuncOp funcOp = dyn_cast_if_present<cir::FuncOp>(op);
526 if (!funcOp || funcOp.getFunctionType() != funcType) {
527 funcOp = getAddrOfFunction(gd, funcType, /*ForVTable=*/false,
528 /*DontDefer=*/true, ForDefinition);
529 }
530
531 // Already emitted.
532 if (!funcOp.isDeclaration())
533 return;
534
535 setFunctionLinkage(gd, funcOp);
536 setGVProperties(funcOp, funcDecl);
538 maybeSetTrivialComdat(*funcDecl, funcOp);
540
541 CIRGenFunction cgf(*this, builder);
542 curCGF = &cgf;
543 {
544 mlir::OpBuilder::InsertionGuard guard(builder);
545 cgf.generateCode(gd, funcOp, funcType);
546 }
547 curCGF = nullptr;
548
549 setNonAliasAttributes(gd, funcOp);
551
552 auto getPriority = [this](const auto *attr) -> int {
553 Expr *e = attr->getPriority();
554 if (e)
555 return e->EvaluateKnownConstInt(this->getASTContext()).getExtValue();
556 return attr->DefaultPriority;
557 };
558
559 if (const ConstructorAttr *ca = funcDecl->getAttr<ConstructorAttr>())
560 addGlobalCtor(funcOp, getPriority(ca));
561 if (const DestructorAttr *da = funcDecl->getAttr<DestructorAttr>())
562 addGlobalDtor(funcOp, getPriority(da));
563
564 if (funcDecl->getAttr<AnnotateAttr>())
565 errorNYI(funcDecl->getSourceRange(), "deferredAnnotations");
566}
567
568/// Track functions to be called before main() runs.
569void CIRGenModule::addGlobalCtor(cir::FuncOp ctor,
570 std::optional<int> priority) {
573
574 // Traditional LLVM codegen directly adds the function to the list of global
575 // ctors. In CIR we just add a global_ctor attribute to the function. The
576 // global list is created in LoweringPrepare.
577 //
578 // FIXME(from traditional LLVM): Type coercion of void()* types.
579 ctor.setGlobalCtorPriority(priority);
580}
581
582/// Add a function to the list that will be called when the module is unloaded.
583void CIRGenModule::addGlobalDtor(cir::FuncOp dtor,
584 std::optional<int> priority) {
585 if (codeGenOpts.RegisterGlobalDtorsWithAtExit &&
586 (!getASTContext().getTargetInfo().getTriple().isOSAIX()))
587 errorNYI(dtor.getLoc(), "registerGlobalDtorsWithAtExit");
588
589 // FIXME(from traditional LLVM): Type coercion of void()* types.
590 dtor.setGlobalDtorPriority(priority);
591}
592
595 if (dk == VarDecl::Definition && vd->hasAttr<DLLImportAttr>())
596 return;
597
599 // If we have a definition, this might be a deferred decl. If the
600 // instantiation is explicit, make sure we emit it at the end.
603
605}
606
607mlir::Operation *CIRGenModule::getGlobalValue(StringRef name) {
608 return mlir::SymbolTable::lookupSymbolIn(theModule, name);
609}
610
611cir::GlobalOp CIRGenModule::createGlobalOp(CIRGenModule &cgm,
612 mlir::Location loc, StringRef name,
613 mlir::Type t, bool isConstant,
614 mlir::Operation *insertPoint) {
615 cir::GlobalOp g;
616 CIRGenBuilderTy &builder = cgm.getBuilder();
617
618 {
619 mlir::OpBuilder::InsertionGuard guard(builder);
620
621 // If an insertion point is provided, we're replacing an existing global,
622 // otherwise, create the new global immediately after the last gloabl we
623 // emitted.
624 if (insertPoint) {
625 builder.setInsertionPoint(insertPoint);
626 } else {
627 // Group global operations together at the top of the module.
628 if (cgm.lastGlobalOp)
629 builder.setInsertionPointAfter(cgm.lastGlobalOp);
630 else
631 builder.setInsertionPointToStart(cgm.getModule().getBody());
632 }
633
634 g = cir::GlobalOp::create(builder, loc, name, t, isConstant);
635 if (!insertPoint)
636 cgm.lastGlobalOp = g;
637
638 // Default to private until we can judge based on the initializer,
639 // since MLIR doesn't allow public declarations.
640 mlir::SymbolTable::setSymbolVisibility(
641 g, mlir::SymbolTable::Visibility::Private);
642 }
643 return g;
644}
645
646void CIRGenModule::setCommonAttributes(GlobalDecl gd, mlir::Operation *gv) {
647 const Decl *d = gd.getDecl();
648 if (isa_and_nonnull<NamedDecl>(d))
649 setGVProperties(gv, dyn_cast<NamedDecl>(d));
652}
653
654void CIRGenModule::setNonAliasAttributes(GlobalDecl gd, mlir::Operation *op) {
655 setCommonAttributes(gd, op);
656
661
663}
664
665std::optional<cir::SourceLanguage> CIRGenModule::getCIRSourceLanguage() const {
666 using ClangStd = clang::LangStandard;
667 using CIRLang = cir::SourceLanguage;
668 auto opts = getLangOpts();
669
670 if (opts.CPlusPlus)
671 return CIRLang::CXX;
672 if (opts.C99 || opts.C11 || opts.C17 || opts.C23 || opts.C2y ||
673 opts.LangStd == ClangStd::lang_c89 ||
674 opts.LangStd == ClangStd::lang_gnu89)
675 return CIRLang::C;
676
677 // TODO(cir): support remaining source languages.
679 errorNYI("CIR does not yet support the given source language");
680 return std::nullopt;
681}
682
683static void setLinkageForGV(cir::GlobalOp &gv, const NamedDecl *nd) {
684 // Set linkage and visibility in case we never see a definition.
686 // Don't set internal linkage on declarations.
687 // "extern_weak" is overloaded in LLVM; we probably should have
688 // separate linkage types for this.
690 (nd->hasAttr<WeakAttr>() || nd->isWeakImported()))
691 gv.setLinkage(cir::GlobalLinkageKind::ExternalWeakLinkage);
692}
693
694// We want to replace a global value, but because of CIR's typed pointers,
695// we need to update the existing uses to reflect the new type, not just replace
696// them directly.
697void CIRGenModule::replaceGlobal(cir::GlobalOp oldGV, cir::GlobalOp newGV) {
698 assert(oldGV.getSymName() == newGV.getSymName() && "symbol names must match");
699
700 mlir::Type oldTy = oldGV.getSymType();
701 mlir::Type newTy = newGV.getSymType();
702
704
705 // If the type didn't change, why are we here?
706 assert(oldTy != newTy && "expected type change in replaceGlobal");
707
708 // Visit all uses and add handling to fix up the types.
709 std::optional<mlir::SymbolTable::UseRange> oldSymUses =
710 oldGV.getSymbolUses(theModule);
711 for (mlir::SymbolTable::SymbolUse use : *oldSymUses) {
712 mlir::Operation *userOp = use.getUser();
713 assert(
714 (mlir::isa<cir::GetGlobalOp, cir::GlobalOp, cir::ConstantOp>(userOp)) &&
715 "Unexpected user for global op");
716
717 if (auto getGlobalOp = dyn_cast<cir::GetGlobalOp>(use.getUser())) {
718 mlir::Value useOpResultValue = getGlobalOp.getAddr();
719 useOpResultValue.setType(cir::PointerType::get(newTy));
720
721 mlir::OpBuilder::InsertionGuard guard(builder);
722 builder.setInsertionPointAfter(getGlobalOp);
723 mlir::Type ptrTy = builder.getPointerTo(oldTy);
724 mlir::Value cast =
725 builder.createBitcast(getGlobalOp->getLoc(), useOpResultValue, ptrTy);
726 useOpResultValue.replaceAllUsesExcept(cast, cast.getDefiningOp());
727 } else {
728 errorNYI(userOp->getLoc(), "Replace global op use in global view attr");
729 }
730 }
731
732 oldGV.erase();
733}
734
735/// If the specified mangled name is not in the module,
736/// create and return an mlir GlobalOp with the specified type (TODO(cir):
737/// address space).
738///
739/// TODO(cir):
740/// 1. If there is something in the module with the specified name, return
741/// it potentially bitcasted to the right type.
742///
743/// 2. If \p d is non-null, it specifies a decl that correspond to this. This
744/// is used to set the attributes on the global when it is first created.
745///
746/// 3. If \p isForDefinition is true, it is guaranteed that an actual global
747/// with type \p ty will be returned, not conversion of a variable with the same
748/// mangled name but some other type.
749cir::GlobalOp
750CIRGenModule::getOrCreateCIRGlobal(StringRef mangledName, mlir::Type ty,
751 LangAS langAS, const VarDecl *d,
752 ForDefinition_t isForDefinition) {
753 // Lookup the entry, lazily creating it if necessary.
754 cir::GlobalOp entry;
755 if (mlir::Operation *v = getGlobalValue(mangledName)) {
756 if (!isa<cir::GlobalOp>(v))
758 "getOrCreateCIRGlobal: global with non-GlobalOp type");
759 entry = cast<cir::GlobalOp>(v);
760 }
761
762 if (entry) {
765
768
769 if (entry.getSymType() == ty)
770 return entry;
771
772 // If there are two attempts to define the same mangled name, issue an
773 // error.
774 //
775 // TODO(cir): look at mlir::GlobalValue::isDeclaration for all aspects of
776 // recognizing the global as a declaration, for now only check if
777 // initializer is present.
778 if (isForDefinition && !entry.isDeclaration()) {
780 "getOrCreateCIRGlobal: global with conflicting type");
781 }
782
783 // Address space check removed because it is unnecessary because CIR records
784 // address space info in types.
785
786 // (If global is requested for a definition, we always need to create a new
787 // global, not just return a bitcast.)
788 if (!isForDefinition)
789 return entry;
790 }
791
792 mlir::Location loc = getLoc(d->getSourceRange());
793
794 // Calculate constant storage flag before creating the global. This was moved
795 // from after the global creation to ensure the constant flag is set correctly
796 // at creation time, matching the logic used in emitCXXGlobalVarDeclInit.
797 bool isConstant = false;
798 if (d) {
799 bool needsDtor =
801 isConstant = d->getType().isConstantStorage(
802 astContext, /*ExcludeCtor=*/true, /*ExcludeDtor=*/!needsDtor);
803 }
804
805 // mlir::SymbolTable::Visibility::Public is the default, no need to explicitly
806 // mark it as such.
807 cir::GlobalOp gv =
808 CIRGenModule::createGlobalOp(*this, loc, mangledName, ty, isConstant,
809 /*insertPoint=*/entry.getOperation());
810
811 // If we already created a global with the same mangled name (but different
812 // type) before, remove it from its parent.
813 if (entry)
814 replaceGlobal(entry, gv);
815
816 // This is the first use or definition of a mangled name. If there is a
817 // deferred decl with this name, remember that we need to emit it at the end
818 // of the file.
819 auto ddi = deferredDecls.find(mangledName);
820 if (ddi != deferredDecls.end()) {
821 // Move the potentially referenced deferred decl to the DeferredDeclsToEmit
822 // list, and remove it from DeferredDecls (since we don't need it anymore).
823 addDeferredDeclToEmit(ddi->second);
824 deferredDecls.erase(ddi);
825 }
826
827 // Handle things which are present even on external declarations.
828 if (d) {
829 if (langOpts.OpenMP && !langOpts.OpenMPSimd)
831 "getOrCreateCIRGlobal: OpenMP target global variable");
832
833 gv.setAlignmentAttr(getSize(astContext.getDeclAlign(d)));
834
835 setLinkageForGV(gv, d);
836
837 if (d->getTLSKind()) {
839 errorNYI(d->getSourceRange(), "getOrCreateCIRGlobal: TLS dynamic");
840 setTLSMode(gv, *d);
841 }
842
843 setGVProperties(gv, d);
844
845 // If required by the ABI, treat declarations of static data members with
846 // inline initializers as definitions.
847 if (astContext.isMSStaticDataMemberInlineDefinition(d))
849 "getOrCreateCIRGlobal: MS static data member inline definition");
850
852 gv.setGlobalVisibilityAttr(getGlobalVisibilityAttrFromDecl(d));
853
854 // Handle XCore specific ABI requirements.
855 if (getTriple().getArch() == llvm::Triple::xcore)
857 "getOrCreateCIRGlobal: XCore specific ABI requirements");
858
859 // Check if we a have a const declaration with an initializer, we may be
860 // able to emit it as available_externally to expose it's value to the
861 // optimizer.
862 if (getLangOpts().CPlusPlus && gv.isPublic() &&
863 d->getType().isConstQualified() && gv.isDeclaration() &&
864 !d->hasDefinition() && d->hasInit() && !d->hasAttr<DLLImportAttr>())
865 errorNYI(
866 d->getSourceRange(),
867 "getOrCreateCIRGlobal: external const declaration with initializer");
868 }
869
870 if (d &&
873 // TODO(cir): set target attributes
874 // External HIP managed variables needed to be recorded for transformation
875 // in both device and host compilations.
876 if (getLangOpts().CUDA && d && d->hasAttr<HIPManagedAttr>() &&
879 "getOrCreateCIRGlobal: HIP managed attribute");
880 }
881
883 return gv;
884}
885
886cir::GlobalOp
888 ForDefinition_t isForDefinition) {
889 assert(d->hasGlobalStorage() && "Not a global variable");
890 QualType astTy = d->getType();
891 if (!ty)
892 ty = getTypes().convertTypeForMem(astTy);
893
894 StringRef mangledName = getMangledName(d);
895 return getOrCreateCIRGlobal(mangledName, ty, astTy.getAddressSpace(), d,
896 isForDefinition);
897}
898
899/// Return the mlir::Value for the address of the given global variable. If
900/// \p ty is non-null and if the global doesn't exist, then it will be created
901/// with the specified type instead of whatever the normal requested type would
902/// be. If \p isForDefinition is true, it is guaranteed that an actual global
903/// with type \p ty will be returned, not conversion of a variable with the same
904/// mangled name but some other type.
905mlir::Value CIRGenModule::getAddrOfGlobalVar(const VarDecl *d, mlir::Type ty,
906 ForDefinition_t isForDefinition) {
907 assert(d->hasGlobalStorage() && "Not a global variable");
908 QualType astTy = d->getType();
909 if (!ty)
910 ty = getTypes().convertTypeForMem(astTy);
911
912 bool tlsAccess = d->getTLSKind() != VarDecl::TLS_None;
913 cir::GlobalOp g = getOrCreateCIRGlobal(d, ty, isForDefinition);
914 mlir::Type ptrTy = builder.getPointerTo(g.getSymType());
915 return cir::GetGlobalOp::create(
916 builder, getLoc(d->getSourceRange()), ptrTy, g.getSymNameAttr(),
917 tlsAccess,
918 /*static_local=*/g.getStaticLocalGuard().has_value());
919}
920
921cir::GlobalViewAttr CIRGenModule::getAddrOfGlobalVarAttr(const VarDecl *d) {
922 assert(d->hasGlobalStorage() && "Not a global variable");
923 mlir::Type ty = getTypes().convertTypeForMem(d->getType());
924
925 cir::GlobalOp globalOp = getOrCreateCIRGlobal(d, ty, NotForDefinition);
927 cir::PointerType ptrTy = builder.getPointerTo(globalOp.getSymType());
928 return builder.getGlobalViewAttr(ptrTy, globalOp);
929}
930
932 bool isTentative) {
933 if (getLangOpts().OpenCL || getLangOpts().OpenMPIsTargetDevice) {
935 "emitGlobalVarDefinition: emit OpenCL/OpenMP global variable");
936 return;
937 }
938
939 // Whether the definition of the variable is available externally.
940 // If yes, we shouldn't emit the GloablCtor and GlobalDtor for the variable
941 // since this is the job for its original source.
942 bool isDefinitionAvailableExternally =
943 astContext.GetGVALinkageForVariable(vd) == GVA_AvailableExternally;
944
945 // It is useless to emit the definition for an available_externally variable
946 // which can't be marked as const.
947 if (isDefinitionAvailableExternally &&
949 // TODO: Update this when we have interface to check constexpr
950 // destructor.
951 vd->needsDestruction(astContext) ||
952 !vd->getType().isConstantStorage(astContext, true, true)))
953 return;
954
955 mlir::Attribute init;
956 bool needsGlobalCtor = false;
957 bool needsGlobalDtor =
958 !isDefinitionAvailableExternally &&
960 const VarDecl *initDecl;
961 const Expr *initExpr = vd->getAnyInitializer(initDecl);
962
963 std::optional<ConstantEmitter> emitter;
964
966
967 // CUDA E.2.4.1 "__shared__ variables cannot have an initialization
968 // as part of their declaration." Sema has already checked for
969 // error cases, so we just need to set Init to UndefValue.
970 bool isCUDASharedVar =
971 getLangOpts().CUDAIsDevice && vd->hasAttr<CUDASharedAttr>();
972 // TODO(cir): implement isCUDAShadowVar and isCUDADeviceShadowVar, reference:
973 // OGCG
974
975 if (getLangOpts().CUDA && isCUDASharedVar) {
976 init = cir::UndefAttr::get(&getMLIRContext(), convertType(vd->getType()));
977 } else if (vd->hasAttr<LoaderUninitializedAttr>()) {
979 "emitGlobalVarDefinition: loader uninitialized attribute");
980 } else if (!initExpr) {
981 // This is a tentative definition; tentative definitions are
982 // implicitly initialized with { 0 }.
983 //
984 // Note that tentative definitions are only emitted at the end of
985 // a translation unit, so they should never have incomplete
986 // type. In addition, EmitTentativeDefinition makes sure that we
987 // never attempt to emit a tentative definition if a real one
988 // exists. A use may still exists, however, so we still may need
989 // to do a RAUW.
990 assert(!vd->getType()->isIncompleteType() && "Unexpected incomplete type");
991 init = builder.getZeroInitAttr(convertType(vd->getType()));
992 } else {
993 emitter.emplace(*this);
994 mlir::Attribute initializer = emitter->tryEmitForInitializer(*initDecl);
995 if (!initializer) {
996 QualType qt = initExpr->getType();
997 if (vd->getType()->isReferenceType())
998 qt = vd->getType();
999
1000 if (getLangOpts().CPlusPlus) {
1001 if (initDecl->hasFlexibleArrayInit(astContext))
1003 "emitGlobalVarDefinition: flexible array initializer");
1004 init = builder.getZeroInitAttr(convertType(qt));
1005 if (!isDefinitionAvailableExternally)
1006 needsGlobalCtor = true;
1007 } else {
1009 "emitGlobalVarDefinition: static initializer");
1010 }
1011 } else {
1012 init = initializer;
1013 // We don't need an initializer, so remove the entry for the delayed
1014 // initializer position (just in case this entry was delayed) if we
1015 // also don't need to register a destructor.
1017 }
1018 }
1019
1020 mlir::Type initType;
1021 if (mlir::isa<mlir::SymbolRefAttr>(init)) {
1022 errorNYI(
1023 vd->getSourceRange(),
1024 "emitGlobalVarDefinition: global initializer is a symbol reference");
1025 return;
1026 } else {
1027 assert(mlir::isa<mlir::TypedAttr>(init) && "This should have a type");
1028 auto typedInitAttr = mlir::cast<mlir::TypedAttr>(init);
1029 initType = typedInitAttr.getType();
1030 }
1031 assert(!mlir::isa<mlir::NoneType>(initType) && "Should have a type by now");
1032
1033 cir::GlobalOp gv =
1034 getOrCreateCIRGlobal(vd, initType, ForDefinition_t(!isTentative));
1035 // TODO(cir): Strip off pointer casts from Entry if we get them?
1036
1037 if (!gv || gv.getSymType() != initType) {
1039 "emitGlobalVarDefinition: global initializer with type mismatch");
1040 return;
1041 }
1042
1044
1045 if (vd->hasAttr<AnnotateAttr>()) {
1047 "emitGlobalVarDefinition: annotate global variable");
1048 }
1049
1050 // Set CIR's linkage type as appropriate.
1051 cir::GlobalLinkageKind linkage =
1052 getCIRLinkageVarDefinition(vd, /*IsConstant=*/false);
1053
1054 // CUDA B.2.1 "The __device__ qualifier declares a variable that resides on
1055 // the device. [...]"
1056 // CUDA B.2.2 "The __constant__ qualifier, optionally used together with
1057 // __device__, declares a variable that: [...]
1058 // Is accessible from all the threads within the grid and from the host
1059 // through the runtime library (cudaGetSymbolAddress() / cudaGetSymbolSize()
1060 // / cudaMemcpyToSymbol() / cudaMemcpyFromSymbol())."
1061 if (langOpts.CUDA) {
1062 if (langOpts.CUDAIsDevice) {
1063 // __shared__ variables is not marked as externally initialized,
1064 // because they must not be initialized.
1065 if (linkage != cir::GlobalLinkageKind::InternalLinkage &&
1066 !vd->isConstexpr() && !vd->getType().isConstQualified() &&
1067 (vd->hasAttr<CUDADeviceAttr>() || vd->hasAttr<CUDAConstantAttr>() ||
1070 gv->setAttr(cir::CUDAExternallyInitializedAttr::getMnemonic(),
1071 cir::CUDAExternallyInitializedAttr::get(&getMLIRContext()));
1072 }
1073 } else {
1074 // TODO(cir):
1075 // Adjust linkage of shadow variables in host compilation
1076 // getCUDARuntime().internalizeDeviceSideVar(vd, linkage);
1077 }
1078 // TODO(cir):
1079 // Handle variable registration
1080 // getCUDARuntime().handleVarRegistration(vd, gv);
1081 }
1082
1083 // Set initializer and finalize emission
1085 if (emitter)
1086 emitter->finalize(gv);
1087
1088 // If it is safe to mark the global 'constant', do so now.
1089 // Use the same logic as classic codegen EmitGlobalVarDefinition.
1090 gv.setConstant((vd->hasAttr<CUDAConstantAttr>() && langOpts.CUDAIsDevice) ||
1091 (!needsGlobalCtor && !needsGlobalDtor &&
1092 vd->getType().isConstantStorage(astContext,
1093 /*ExcludeCtor=*/true,
1094 /*ExcludeDtor=*/true)));
1096
1097 // Set CIR linkage and DLL storage class.
1098 gv.setLinkage(linkage);
1099 // FIXME(cir): setLinkage should likely set MLIR's visibility automatically.
1100 gv.setVisibility(getMLIRVisibilityFromCIRLinkage(linkage));
1102 if (linkage == cir::GlobalLinkageKind::CommonLinkage) {
1103 // common vars aren't constant even if declared const.
1104 gv.setConstant(false);
1105 // Tentative definition of global variables may be initialized with
1106 // non-zero null pointers. In this case they should have weak linkage
1107 // since common linkage must have zero initializer and must not have
1108 // explicit section therefore cannot have non-zero initial value.
1109 std::optional<mlir::Attribute> initializer = gv.getInitialValue();
1110 if (initializer && !getBuilder().isNullValue(*initializer))
1111 gv.setLinkage(cir::GlobalLinkageKind::WeakAnyLinkage);
1112 }
1113
1114 setNonAliasAttributes(vd, gv);
1115
1117
1118 maybeSetTrivialComdat(*vd, gv);
1119
1120 // Emit the initializer function if necessary.
1121 if (needsGlobalCtor || needsGlobalDtor)
1122 emitCXXGlobalVarDeclInitFunc(vd, gv, needsGlobalCtor);
1123}
1124
1126 mlir::Operation *op) {
1127 const auto *decl = cast<ValueDecl>(gd.getDecl());
1128 if (const auto *fd = dyn_cast<FunctionDecl>(decl)) {
1129 // TODO(CIR): Skip generation of CIR for functions with available_externally
1130 // linkage at -O0.
1131
1132 if (const auto *method = dyn_cast<CXXMethodDecl>(decl)) {
1133 // Make sure to emit the definition(s) before we emit the thunks. This is
1134 // necessary for the generation of certain thunks.
1135 if (isa<CXXConstructorDecl>(method) || isa<CXXDestructorDecl>(method))
1136 abi->emitCXXStructor(gd);
1137 else if (fd->isMultiVersion())
1138 errorNYI(method->getSourceRange(), "multiversion functions");
1139 else
1141
1142 if (method->isVirtual())
1143 getVTables().emitThunks(gd);
1144
1145 return;
1146 }
1147
1148 if (fd->isMultiVersion())
1149 errorNYI(fd->getSourceRange(), "multiversion functions");
1151 return;
1152 }
1153
1154 if (const auto *vd = dyn_cast<VarDecl>(decl))
1155 return emitGlobalVarDefinition(vd, !vd->hasDefinition());
1156
1157 llvm_unreachable("Invalid argument to CIRGenModule::emitGlobalDefinition");
1158}
1159
1160mlir::Attribute
1162 assert(!e->getType()->isPointerType() && "Strings are always arrays");
1163
1164 // Don't emit it as the address of the string, emit the string data itself
1165 // as an inline array.
1166 if (e->getCharByteWidth() == 1) {
1167 SmallString<64> str(e->getString());
1168
1169 // Resize the string to the right size, which is indicated by its type.
1170 const ConstantArrayType *cat =
1171 astContext.getAsConstantArrayType(e->getType());
1172 uint64_t finalSize = cat->getZExtSize();
1173 str.resize(finalSize);
1174
1175 mlir::Type eltTy = convertType(cat->getElementType());
1176 return builder.getString(str, eltTy, finalSize, /*ensureNullTerm=*/false);
1177 }
1178
1179 auto arrayTy = mlir::cast<cir::ArrayType>(convertType(e->getType()));
1180
1181 auto arrayEltTy = mlir::cast<cir::IntType>(arrayTy.getElementType());
1182
1183 uint64_t arraySize = arrayTy.getSize();
1184 unsigned literalSize = e->getLength();
1185 assert(arraySize == literalSize + 1 &&
1186 "wide string literal array size must be literal length plus null "
1187 "terminator");
1188
1189 // Check if the string is all null bytes before building the vector.
1190 // In most non-zero cases, this will break out on the first element.
1191 bool isAllZero = true;
1192 for (unsigned i = 0; i < literalSize; ++i) {
1193 if (e->getCodeUnit(i) != 0) {
1194 isAllZero = false;
1195 break;
1196 }
1197 }
1198
1199 if (isAllZero)
1200 return cir::ZeroAttr::get(arrayTy);
1201
1202 // Otherwise emit a constant array holding the characters.
1204 elements.reserve(arraySize);
1205 for (unsigned i = 0; i < literalSize; ++i)
1206 elements.push_back(cir::IntAttr::get(arrayEltTy, e->getCodeUnit(i)));
1207 // Add null terminator
1208 elements.push_back(cir::IntAttr::get(arrayEltTy, 0));
1209
1210 auto elementsAttr = mlir::ArrayAttr::get(&getMLIRContext(), elements);
1211 return builder.getConstArray(elementsAttr, arrayTy);
1212}
1213
1215 return getTriple().supportsCOMDAT();
1216}
1217
1218static bool shouldBeInCOMDAT(CIRGenModule &cgm, const Decl &d) {
1219 if (!cgm.supportsCOMDAT())
1220 return false;
1221
1222 if (d.hasAttr<SelectAnyAttr>())
1223 return true;
1224
1225 GVALinkage linkage;
1226 if (auto *vd = dyn_cast<VarDecl>(&d))
1227 linkage = cgm.getASTContext().GetGVALinkageForVariable(vd);
1228 else
1229 linkage =
1231
1232 switch (linkage) {
1236 return false;
1239 return true;
1240 }
1241 llvm_unreachable("No such linkage");
1242}
1243
1244void CIRGenModule::maybeSetTrivialComdat(const Decl &d, mlir::Operation *op) {
1245 if (!shouldBeInCOMDAT(*this, d))
1246 return;
1247 if (auto globalOp = dyn_cast_or_null<cir::GlobalOp>(op)) {
1248 globalOp.setComdat(true);
1249 } else {
1250 auto funcOp = cast<cir::FuncOp>(op);
1251 funcOp.setComdat(true);
1252 }
1253}
1254
1256 // Make sure that this type is translated.
1257 genTypes.updateCompletedType(td);
1258}
1259
1260void CIRGenModule::addReplacement(StringRef name, mlir::Operation *op) {
1261 replacements[name] = op;
1262}
1263
1264void CIRGenModule::replacePointerTypeArgs(cir::FuncOp oldF, cir::FuncOp newF) {
1265 std::optional<mlir::SymbolTable::UseRange> optionalUseRange =
1266 oldF.getSymbolUses(theModule);
1267 if (!optionalUseRange)
1268 return;
1269
1270 for (const mlir::SymbolTable::SymbolUse &u : *optionalUseRange) {
1271 // CallTryOp only shows up after FlattenCFG.
1272 auto call = mlir::dyn_cast<cir::CallOp>(u.getUser());
1273 if (!call)
1274 continue;
1275
1276 for (const auto [argOp, fnArgType] :
1277 llvm::zip(call.getArgs(), newF.getFunctionType().getInputs())) {
1278 if (argOp.getType() == fnArgType)
1279 continue;
1280
1281 // The purpose of this entire function is to insert bitcasts in the case
1282 // where these types don't match, but I haven't seen a case where that
1283 // happens.
1284 errorNYI(call.getLoc(), "replace call with mismatched types");
1285 }
1286 }
1287}
1288
1289void CIRGenModule::applyReplacements() {
1290 for (auto &i : replacements) {
1291 StringRef mangledName = i.first;
1292 mlir::Operation *replacement = i.second;
1293 mlir::Operation *entry = getGlobalValue(mangledName);
1294 if (!entry)
1295 continue;
1296 assert(isa<cir::FuncOp>(entry) && "expected function");
1297 auto oldF = cast<cir::FuncOp>(entry);
1298 auto newF = dyn_cast<cir::FuncOp>(replacement);
1299 if (!newF) {
1300 // In classic codegen, this can be a global alias, a bitcast, or a GEP.
1301 errorNYI(replacement->getLoc(), "replacement is not a function");
1302 continue;
1303 }
1304
1305 // LLVM has opaque pointer but CIR not. So we may have to handle these
1306 // different pointer types when performing replacement.
1307 replacePointerTypeArgs(oldF, newF);
1308
1309 // Replace old with new, but keep the old order.
1310 if (oldF.replaceAllSymbolUses(newF.getSymNameAttr(), theModule).failed())
1311 llvm_unreachable("internal error, cannot RAUW symbol");
1312 if (newF) {
1313 newF->moveBefore(oldF);
1314 oldF->erase();
1315 }
1316 }
1317}
1318
1320 mlir::Location loc, StringRef name, mlir::Type ty,
1321 cir::GlobalLinkageKind linkage, clang::CharUnits alignment) {
1322 auto gv = mlir::dyn_cast_or_null<cir::GlobalOp>(
1323 mlir::SymbolTable::lookupSymbolIn(theModule, name));
1324
1325 if (gv) {
1326 // Check if the variable has the right type.
1327 if (gv.getSymType() == ty)
1328 return gv;
1329
1330 // Because of C++ name mangling, the only way we can end up with an already
1331 // existing global with the same name is if it has been declared extern
1332 // "C".
1333 assert(gv.isDeclaration() && "Declaration has wrong type!");
1334
1335 errorNYI(loc, "createOrReplaceCXXRuntimeVariable: declaration exists with "
1336 "wrong type");
1337 return gv;
1338 }
1339
1340 // Create a new variable.
1341 gv = createGlobalOp(*this, loc, name, ty);
1342
1343 // Set up extra information and add to the module
1344 gv.setLinkageAttr(
1345 cir::GlobalLinkageKindAttr::get(&getMLIRContext(), linkage));
1346 mlir::SymbolTable::setSymbolVisibility(gv,
1348
1349 if (supportsCOMDAT() && cir::isWeakForLinker(linkage) &&
1350 !gv.hasAvailableExternallyLinkage()) {
1351 gv.setComdat(true);
1352 }
1353
1354 gv.setAlignmentAttr(getSize(alignment));
1355 setDSOLocal(static_cast<mlir::Operation *>(gv));
1356 return gv;
1357}
1358
1359// TODO(CIR): this could be a common method between LLVM codegen.
1360static bool isVarDeclStrongDefinition(const ASTContext &astContext,
1361 CIRGenModule &cgm, const VarDecl *vd,
1362 bool noCommon) {
1363 // Don't give variables common linkage if -fno-common was specified unless it
1364 // was overridden by a NoCommon attribute.
1365 if ((noCommon || vd->hasAttr<NoCommonAttr>()) && !vd->hasAttr<CommonAttr>())
1366 return true;
1367
1368 // C11 6.9.2/2:
1369 // A declaration of an identifier for an object that has file scope without
1370 // an initializer, and without a storage-class specifier or with the
1371 // storage-class specifier static, constitutes a tentative definition.
1372 if (vd->getInit() || vd->hasExternalStorage())
1373 return true;
1374
1375 // A variable cannot be both common and exist in a section.
1376 if (vd->hasAttr<SectionAttr>())
1377 return true;
1378
1379 // A variable cannot be both common and exist in a section.
1380 // We don't try to determine which is the right section in the front-end.
1381 // If no specialized section name is applicable, it will resort to default.
1382 if (vd->hasAttr<PragmaClangBSSSectionAttr>() ||
1383 vd->hasAttr<PragmaClangDataSectionAttr>() ||
1384 vd->hasAttr<PragmaClangRelroSectionAttr>() ||
1385 vd->hasAttr<PragmaClangRodataSectionAttr>())
1386 return true;
1387
1388 // Thread local vars aren't considered common linkage.
1389 if (vd->getTLSKind())
1390 return true;
1391
1392 // Tentative definitions marked with WeakImportAttr are true definitions.
1393 if (vd->hasAttr<WeakImportAttr>())
1394 return true;
1395
1396 // A variable cannot be both common and exist in a comdat.
1397 if (shouldBeInCOMDAT(cgm, *vd))
1398 return true;
1399
1400 // Declarations with a required alignment do not have common linkage in MSVC
1401 // mode.
1402 if (astContext.getTargetInfo().getCXXABI().isMicrosoft()) {
1403 if (vd->hasAttr<AlignedAttr>())
1404 return true;
1405 QualType varType = vd->getType();
1406 if (astContext.isAlignmentRequired(varType))
1407 return true;
1408
1409 if (const auto *rd = varType->getAsRecordDecl()) {
1410 for (const FieldDecl *fd : rd->fields()) {
1411 if (fd->isBitField())
1412 continue;
1413 if (fd->hasAttr<AlignedAttr>())
1414 return true;
1415 if (astContext.isAlignmentRequired(fd->getType()))
1416 return true;
1417 }
1418 }
1419 }
1420
1421 // Microsoft's link.exe doesn't support alignments greater than 32 bytes for
1422 // common symbols, so symbols with greater alignment requirements cannot be
1423 // common.
1424 // Other COFF linkers (ld.bfd and LLD) support arbitrary power-of-two
1425 // alignments for common symbols via the aligncomm directive, so this
1426 // restriction only applies to MSVC environments.
1427 if (astContext.getTargetInfo().getTriple().isKnownWindowsMSVCEnvironment() &&
1428 astContext.getTypeAlignIfKnown(vd->getType()) >
1429 astContext.toBits(CharUnits::fromQuantity(32)))
1430 return true;
1431
1432 return false;
1433}
1434
1436 const DeclaratorDecl *dd, GVALinkage linkage, bool isConstantVariable) {
1437 if (linkage == GVA_Internal)
1438 return cir::GlobalLinkageKind::InternalLinkage;
1439
1440 if (dd->hasAttr<WeakAttr>()) {
1441 if (isConstantVariable)
1442 return cir::GlobalLinkageKind::WeakODRLinkage;
1443 return cir::GlobalLinkageKind::WeakAnyLinkage;
1444 }
1445
1446 if (const auto *fd = dd->getAsFunction())
1447 if (fd->isMultiVersion() && linkage == GVA_AvailableExternally)
1448 return cir::GlobalLinkageKind::LinkOnceAnyLinkage;
1449
1450 // We are guaranteed to have a strong definition somewhere else,
1451 // so we can use available_externally linkage.
1452 if (linkage == GVA_AvailableExternally)
1453 return cir::GlobalLinkageKind::AvailableExternallyLinkage;
1454
1455 // Note that Apple's kernel linker doesn't support symbol
1456 // coalescing, so we need to avoid linkonce and weak linkages there.
1457 // Normally, this means we just map to internal, but for explicit
1458 // instantiations we'll map to external.
1459
1460 // In C++, the compiler has to emit a definition in every translation unit
1461 // that references the function. We should use linkonce_odr because
1462 // a) if all references in this translation unit are optimized away, we
1463 // don't need to codegen it. b) if the function persists, it needs to be
1464 // merged with other definitions. c) C++ has the ODR, so we know the
1465 // definition is dependable.
1466 if (linkage == GVA_DiscardableODR)
1467 return !astContext.getLangOpts().AppleKext
1468 ? cir::GlobalLinkageKind::LinkOnceODRLinkage
1469 : cir::GlobalLinkageKind::InternalLinkage;
1470
1471 // An explicit instantiation of a template has weak linkage, since
1472 // explicit instantiations can occur in multiple translation units
1473 // and must all be equivalent. However, we are not allowed to
1474 // throw away these explicit instantiations.
1475 //
1476 // CUDA/HIP: For -fno-gpu-rdc case, device code is limited to one TU,
1477 // so say that CUDA templates are either external (for kernels) or internal.
1478 // This lets llvm perform aggressive inter-procedural optimizations. For
1479 // -fgpu-rdc case, device function calls across multiple TU's are allowed,
1480 // therefore we need to follow the normal linkage paradigm.
1481 if (linkage == GVA_StrongODR) {
1482 if (getLangOpts().AppleKext)
1483 return cir::GlobalLinkageKind::ExternalLinkage;
1484 if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice &&
1485 !getLangOpts().GPURelocatableDeviceCode)
1486 return dd->hasAttr<CUDAGlobalAttr>()
1487 ? cir::GlobalLinkageKind::ExternalLinkage
1488 : cir::GlobalLinkageKind::InternalLinkage;
1489 return cir::GlobalLinkageKind::WeakODRLinkage;
1490 }
1491
1492 // C++ doesn't have tentative definitions and thus cannot have common
1493 // linkage.
1494 if (!getLangOpts().CPlusPlus && isa<VarDecl>(dd) &&
1495 !isVarDeclStrongDefinition(astContext, *this, cast<VarDecl>(dd),
1496 getCodeGenOpts().NoCommon))
1497 return cir::GlobalLinkageKind::CommonLinkage;
1498
1499 // selectany symbols are externally visible, so use weak instead of
1500 // linkonce. MSVC optimizes away references to const selectany globals, so
1501 // all definitions should be the same and ODR linkage should be used.
1502 // http://msdn.microsoft.com/en-us/library/5tkz6s71.aspx
1503 if (dd->hasAttr<SelectAnyAttr>())
1504 return cir::GlobalLinkageKind::WeakODRLinkage;
1505
1506 // Otherwise, we have strong external linkage.
1507 assert(linkage == GVA_StrongExternal);
1508 return cir::GlobalLinkageKind::ExternalLinkage;
1509}
1510
1511/// This function is called when we implement a function with no prototype, e.g.
1512/// "int foo() {}". If there are existing call uses of the old function in the
1513/// module, this adjusts them to call the new function directly.
1514///
1515/// This is not just a cleanup: the always_inline pass requires direct calls to
1516/// functions to be able to inline them. If there is a bitcast in the way, it
1517/// won't inline them. Instcombine normally deletes these calls, but it isn't
1518/// run at -O0.
1520 mlir::Operation *old, cir::FuncOp newFn) {
1521 // If we're redefining a global as a function, don't transform it.
1522 auto oldFn = mlir::dyn_cast<cir::FuncOp>(old);
1523 if (!oldFn)
1524 return;
1525
1526 // TODO(cir): this RAUW ignores the features below.
1530 if (oldFn->getAttrs().size() <= 1)
1531 errorNYI(old->getLoc(),
1532 "replaceUsesOfNonProtoTypeWithRealFunction: Attribute forwarding");
1533
1534 // Mark new function as originated from a no-proto declaration.
1535 newFn.setNoProto(oldFn.getNoProto());
1536
1537 // Iterate through all calls of the no-proto function.
1538 std::optional<mlir::SymbolTable::UseRange> symUses =
1539 oldFn.getSymbolUses(oldFn->getParentOp());
1540 for (const mlir::SymbolTable::SymbolUse &use : symUses.value()) {
1541 mlir::OpBuilder::InsertionGuard guard(builder);
1542
1543 if (auto noProtoCallOp = mlir::dyn_cast<cir::CallOp>(use.getUser())) {
1544 builder.setInsertionPoint(noProtoCallOp);
1545
1546 // Patch call type with the real function type.
1547 cir::CallOp realCallOp = builder.createCallOp(
1548 noProtoCallOp.getLoc(), newFn, noProtoCallOp.getOperands());
1549
1550 // Replace old no proto call with fixed call.
1551 noProtoCallOp.replaceAllUsesWith(realCallOp);
1552 noProtoCallOp.erase();
1553 } else if (auto getGlobalOp =
1554 mlir::dyn_cast<cir::GetGlobalOp>(use.getUser())) {
1555 // Replace type
1556 getGlobalOp.getAddr().setType(
1557 cir::PointerType::get(newFn.getFunctionType()));
1558 } else {
1559 errorNYI(use.getUser()->getLoc(),
1560 "replaceUsesOfNonProtoTypeWithRealFunction: unexpected use");
1561 }
1562 }
1563}
1564
1565cir::GlobalLinkageKind
1567 assert(!isConstant && "constant variables NYI");
1568 GVALinkage linkage = astContext.GetGVALinkageForVariable(vd);
1569 return getCIRLinkageForDeclarator(vd, linkage, isConstant);
1570}
1571
1573 const auto *d = cast<FunctionDecl>(gd.getDecl());
1574
1575 GVALinkage linkage = astContext.GetGVALinkageForFunction(d);
1576
1577 if (const auto *dtor = dyn_cast<CXXDestructorDecl>(d))
1578 return getCXXABI().getCXXDestructorLinkage(linkage, dtor, gd.getDtorType());
1579
1580 return getCIRLinkageForDeclarator(d, linkage, /*isConstantVariable=*/false);
1581}
1582
1583static cir::GlobalOp
1584generateStringLiteral(mlir::Location loc, mlir::TypedAttr c,
1585 cir::GlobalLinkageKind lt, CIRGenModule &cgm,
1586 StringRef globalName, CharUnits alignment) {
1588
1589 // Create a global variable for this string
1590 // FIXME(cir): check for insertion point in module level.
1591 cir::GlobalOp gv = CIRGenModule::createGlobalOp(
1592 cgm, loc, globalName, c.getType(), !cgm.getLangOpts().WritableStrings);
1593
1594 // Set up extra information and add to the module
1595 gv.setAlignmentAttr(cgm.getSize(alignment));
1596 gv.setLinkageAttr(
1597 cir::GlobalLinkageKindAttr::get(cgm.getBuilder().getContext(), lt));
1601 if (gv.isWeakForLinker()) {
1602 assert(cgm.supportsCOMDAT() && "Only COFF uses weak string literals");
1603 gv.setComdat(true);
1604 }
1605 cgm.setDSOLocal(static_cast<mlir::Operation *>(gv));
1606 return gv;
1607}
1608
1609// LLVM IR automatically uniques names when new llvm::GlobalVariables are
1610// created. This is handy, for example, when creating globals for string
1611// literals. Since we don't do that when creating cir::GlobalOp's, we need
1612// a mechanism to generate a unique name in advance.
1613//
1614// For now, this mechanism is only used in cases where we know that the
1615// name is compiler-generated, so we don't use the MLIR symbol table for
1616// the lookup.
1617std::string CIRGenModule::getUniqueGlobalName(const std::string &baseName) {
1618 // If this is the first time we've generated a name for this basename, use
1619 // it as is and start a counter for this base name.
1620 auto it = cgGlobalNames.find(baseName);
1621 if (it == cgGlobalNames.end()) {
1622 cgGlobalNames[baseName] = 1;
1623 return baseName;
1624 }
1625
1626 std::string result =
1627 baseName + "." + std::to_string(cgGlobalNames[baseName]++);
1628 // There should not be any symbol with this name in the module.
1629 assert(!mlir::SymbolTable::lookupSymbolIn(theModule, result));
1630 return result;
1631}
1632
1633/// Return a pointer to a constant array for the given string literal.
1635 StringRef name) {
1636 CharUnits alignment =
1637 astContext.getAlignOfGlobalVarInChars(s->getType(), /*VD=*/nullptr);
1638
1639 mlir::Attribute c = getConstantArrayFromStringLiteral(s);
1640
1641 cir::GlobalOp gv;
1642 if (!getLangOpts().WritableStrings && constantStringMap.count(c)) {
1643 gv = constantStringMap[c];
1644 // The bigger alignment always wins.
1645 if (!gv.getAlignment() ||
1646 uint64_t(alignment.getQuantity()) > *gv.getAlignment())
1647 gv.setAlignmentAttr(getSize(alignment));
1648 } else {
1649 // Mangle the string literal if that's how the ABI merges duplicate strings.
1650 // Don't do it if they are writable, since we don't want writes in one TU to
1651 // affect strings in another.
1652 if (getCXXABI().getMangleContext().shouldMangleStringLiteral(s) &&
1653 !getLangOpts().WritableStrings) {
1654 errorNYI(s->getSourceRange(),
1655 "getGlobalForStringLiteral: mangle string literals");
1656 }
1657
1658 // Unlike LLVM IR, CIR doesn't automatically unique names for globals, so
1659 // we need to do that explicitly.
1660 std::string uniqueName = getUniqueGlobalName(name.str());
1661 // Synthetic string literals (e.g., from SourceLocExpr) may not have valid
1662 // source locations. Use unknown location in those cases.
1663 mlir::Location loc = s->getBeginLoc().isValid()
1664 ? getLoc(s->getSourceRange())
1665 : builder.getUnknownLoc();
1666 auto typedC = llvm::cast<mlir::TypedAttr>(c);
1667 gv = generateStringLiteral(loc, typedC,
1668 cir::GlobalLinkageKind::PrivateLinkage, *this,
1669 uniqueName, alignment);
1670 setDSOLocal(static_cast<mlir::Operation *>(gv));
1671 constantStringMap[c] = gv;
1672
1674 }
1675 return gv;
1676}
1677
1678/// Return a pointer to a constant array for the given string literal.
1679cir::GlobalViewAttr
1681 StringRef name) {
1682 cir::GlobalOp gv = getGlobalForStringLiteral(s, name);
1683 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(gv.getSymType());
1684 assert(arrayTy && "String literal must be array");
1686 cir::PointerType ptrTy = getBuilder().getPointerTo(arrayTy.getElementType());
1687
1688 return builder.getGlobalViewAttr(ptrTy, gv);
1689}
1690
1691// TODO(cir): this could be a common AST helper for both CIR and LLVM codegen.
1693 if (getLangOpts().OpenCL)
1695
1696 // For temporaries inside functions, CUDA treats them as normal variables.
1697 // LangAS::cuda_device, on the other hand, is reserved for those variables
1698 // explicitly marked with __device__.
1699 if (getLangOpts().CUDAIsDevice)
1700 return LangAS::Default;
1701
1702 if (getLangOpts().SYCLIsDevice ||
1703 (getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice))
1704 errorNYI("SYCL or OpenMP temp address space");
1705 return LangAS::Default;
1706}
1707
1709 CIRGenFunction *cgf) {
1710 if (cgf && e->getType()->isVariablyModifiedType())
1712
1714 "emitExplicitCastExprType");
1715}
1716
1719
1720 mlir::Location loc = getLoc(e->getSourceRange());
1721
1722 const auto *decl = cast<DeclRefExpr>(e->getSubExpr())->getDecl();
1723
1724 // A member function pointer.
1725 if (const auto *methodDecl = dyn_cast<CXXMethodDecl>(decl)) {
1726 auto ty = mlir::cast<cir::MethodType>(convertType(e->getType()));
1727 if (methodDecl->isVirtual())
1728 return cir::ConstantOp::create(
1729 builder, loc, getCXXABI().buildVirtualMethodAttr(ty, methodDecl));
1730
1731 cir::FuncOp methodFuncOp = getAddrOfFunction(methodDecl);
1732 return cir::ConstantOp::create(builder, loc,
1733 builder.getMethodAttr(ty, methodFuncOp));
1734 }
1735
1736 // Otherwise, a member data pointer.
1737 auto ty = mlir::cast<cir::DataMemberType>(convertType(e->getType()));
1738 const auto *fieldDecl = cast<FieldDecl>(decl);
1739 return cir::ConstantOp::create(
1740 builder, loc, builder.getDataMemberAttr(ty, fieldDecl->getFieldIndex()));
1741}
1742
1744 for (Decl *decl : dc->decls()) {
1745 // Unlike other DeclContexts, the contents of an ObjCImplDecl at TU scope
1746 // are themselves considered "top-level", so EmitTopLevelDecl on an
1747 // ObjCImplDecl does not recursively visit them. We need to do that in
1748 // case they're nested inside another construct (LinkageSpecDecl /
1749 // ExportDecl) that does stop them from being considered "top-level".
1750 if (auto *oid = dyn_cast<ObjCImplDecl>(decl))
1751 errorNYI(oid->getSourceRange(), "emitDeclConext: ObjCImplDecl");
1752
1754 }
1755}
1756
1757// Emit code for a single top level declaration.
1759
1760 // Ignore dependent declarations.
1761 if (decl->isTemplated())
1762 return;
1763
1764 switch (decl->getKind()) {
1765 default:
1766 errorNYI(decl->getBeginLoc(), "declaration of kind",
1767 decl->getDeclKindName());
1768 break;
1769
1770 case Decl::CXXConversion:
1771 case Decl::CXXMethod:
1772 case Decl::Function: {
1773 auto *fd = cast<FunctionDecl>(decl);
1774 // Consteval functions shouldn't be emitted.
1775 if (!fd->isConsteval())
1776 emitGlobal(fd);
1777 break;
1778 }
1779
1780 case Decl::Var:
1781 case Decl::Decomposition:
1782 case Decl::VarTemplateSpecialization: {
1783 auto *vd = cast<VarDecl>(decl);
1785 errorNYI(decl->getSourceRange(), "global variable decompositions");
1786 break;
1787 }
1788 emitGlobal(vd);
1789 break;
1790 }
1791 case Decl::OpenACCRoutine:
1793 break;
1794 case Decl::OpenACCDeclare:
1796 break;
1797 case Decl::OMPThreadPrivate:
1799 break;
1800 case Decl::OMPGroupPrivate:
1802 break;
1803 case Decl::OMPAllocate:
1805 break;
1806 case Decl::OMPCapturedExpr:
1808 break;
1809 case Decl::OMPDeclareReduction:
1811 break;
1812 case Decl::OMPDeclareMapper:
1814 break;
1815 case Decl::OMPRequires:
1817 break;
1818 case Decl::Enum:
1819 case Decl::Using: // using X; [C++]
1820 case Decl::UsingDirective: // using namespace X; [C++]
1821 case Decl::UsingEnum: // using enum X; [C++]
1822 case Decl::NamespaceAlias:
1823 case Decl::Typedef:
1824 case Decl::TypeAlias: // using foo = bar; [C++11]
1825 case Decl::Record:
1827 break;
1828
1829 // No code generation needed.
1830 case Decl::ClassTemplate:
1831 case Decl::Concept:
1832 case Decl::CXXDeductionGuide:
1833 case Decl::Empty:
1834 case Decl::FunctionTemplate:
1835 case Decl::StaticAssert:
1836 case Decl::TypeAliasTemplate:
1837 case Decl::UsingShadow:
1838 case Decl::VarTemplate:
1839 case Decl::VarTemplatePartialSpecialization:
1840 break;
1841
1842 case Decl::CXXConstructor:
1844 break;
1845 case Decl::CXXDestructor:
1847 break;
1848
1849 // C++ Decls
1850 case Decl::LinkageSpec:
1851 case Decl::Namespace:
1853 break;
1854
1855 case Decl::ClassTemplateSpecialization:
1856 case Decl::CXXRecord: {
1859 for (auto *childDecl : crd->decls())
1861 emitTopLevelDecl(childDecl);
1862 break;
1863 }
1864
1865 case Decl::FileScopeAsm:
1866 // File-scope asm is ignored during device-side CUDA compilation.
1867 if (langOpts.CUDA && langOpts.CUDAIsDevice)
1868 break;
1869 // File-scope asm is ignored during device-side OpenMP compilation.
1870 if (langOpts.OpenMPIsTargetDevice)
1871 break;
1872 // File-scope asm is ignored during device-side SYCL compilation.
1873 if (langOpts.SYCLIsDevice)
1874 break;
1875 auto *file_asm = cast<FileScopeAsmDecl>(decl);
1876 std::string line = file_asm->getAsmString();
1877 globalScopeAsm.push_back(builder.getStringAttr(line));
1878 break;
1879 }
1880}
1881
1882void CIRGenModule::setInitializer(cir::GlobalOp &op, mlir::Attribute value) {
1883 // Recompute visibility when updating initializer.
1884 op.setInitialValueAttr(value);
1886}
1887
1888std::pair<cir::FuncType, cir::FuncOp> CIRGenModule::getAddrAndTypeOfCXXStructor(
1889 GlobalDecl gd, const CIRGenFunctionInfo *fnInfo, cir::FuncType fnType,
1890 bool dontDefer, ForDefinition_t isForDefinition) {
1891 auto *md = cast<CXXMethodDecl>(gd.getDecl());
1892
1893 if (isa<CXXDestructorDecl>(md)) {
1894 // Always alias equivalent complete destructors to base destructors in the
1895 // MS ABI.
1896 if (getTarget().getCXXABI().isMicrosoft() &&
1897 gd.getDtorType() == Dtor_Complete &&
1898 md->getParent()->getNumVBases() == 0)
1899 errorNYI(md->getSourceRange(),
1900 "getAddrAndTypeOfCXXStructor: MS ABI complete destructor");
1901 }
1902
1903 if (!fnType) {
1904 if (!fnInfo)
1906 fnType = getTypes().getFunctionType(*fnInfo);
1907 }
1908
1909 auto fn = getOrCreateCIRFunction(getMangledName(gd), fnType, gd,
1910 /*ForVtable=*/false, dontDefer,
1911 /*IsThunk=*/false, isForDefinition);
1912
1913 return {fnType, fn};
1914}
1915
1917 mlir::Type funcType, bool forVTable,
1918 bool dontDefer,
1919 ForDefinition_t isForDefinition) {
1920 assert(!cast<FunctionDecl>(gd.getDecl())->isConsteval() &&
1921 "consteval function should never be emitted");
1922
1923 if (!funcType) {
1924 const auto *fd = cast<FunctionDecl>(gd.getDecl());
1925 funcType = convertType(fd->getType());
1926 }
1927
1928 // Devirtualized destructor calls may come through here instead of via
1929 // getAddrOfCXXStructor. Make sure we use the MS ABI base destructor instead
1930 // of the complete destructor when necessary.
1931 if (const auto *dd = dyn_cast<CXXDestructorDecl>(gd.getDecl())) {
1932 if (getTarget().getCXXABI().isMicrosoft() &&
1933 gd.getDtorType() == Dtor_Complete &&
1934 dd->getParent()->getNumVBases() == 0)
1935 errorNYI(dd->getSourceRange(),
1936 "getAddrOfFunction: MS ABI complete destructor");
1937 }
1938
1939 StringRef mangledName = getMangledName(gd);
1940 cir::FuncOp func =
1941 getOrCreateCIRFunction(mangledName, funcType, gd, forVTable, dontDefer,
1942 /*isThunk=*/false, isForDefinition);
1943 // Returns kernel handle for HIP kernel stub function.
1944 if (langOpts.CUDA && !langOpts.CUDAIsDevice &&
1945 cast<FunctionDecl>(gd.getDecl())->hasAttr<CUDAGlobalAttr>()) {
1946 mlir::Operation *handle = getCUDARuntime().getKernelHandle(func, gd);
1947
1948 // For HIP the kernel handle is a GlobalOp, which cannot be cast to
1949 // FuncOp. Return the stub directly in that case.
1950 bool isHIPHandle = mlir::isa<cir::GlobalOp>(*handle);
1951 if (isForDefinition || isHIPHandle)
1952 return func;
1953 return mlir::dyn_cast<cir::FuncOp>(*handle);
1954 }
1955 return func;
1956}
1957
1958static std::string getMangledNameImpl(CIRGenModule &cgm, GlobalDecl gd,
1959 const NamedDecl *nd) {
1960 SmallString<256> buffer;
1961
1962 llvm::raw_svector_ostream out(buffer);
1964
1966
1967 if (mc.shouldMangleDeclName(nd)) {
1968 mc.mangleName(gd.getWithDecl(nd), out);
1969 } else {
1970 IdentifierInfo *ii = nd->getIdentifier();
1971 assert(ii && "Attempt to mangle unnamed decl.");
1972
1973 const auto *fd = dyn_cast<FunctionDecl>(nd);
1974 if (fd &&
1975 fd->getType()->castAs<FunctionType>()->getCallConv() == CC_X86RegCall) {
1976 cgm.errorNYI(nd->getSourceRange(), "getMangledName: X86RegCall");
1977 } else if (fd && fd->hasAttr<CUDAGlobalAttr>() &&
1979 out << "__device_stub__" << ii->getName();
1980 } else if (fd &&
1981 DeviceKernelAttr::isOpenCLSpelling(
1982 fd->getAttr<DeviceKernelAttr>()) &&
1984 cgm.errorNYI(nd->getSourceRange(), "getMangledName: OpenCL Stub");
1985 } else {
1986 out << ii->getName();
1987 }
1988 }
1989
1990 // Check if the module name hash should be appended for internal linkage
1991 // symbols. This should come before multi-version target suffixes are
1992 // appendded. This is to keep the name and module hash suffix of the internal
1993 // linkage function together. The unique suffix should only be added when name
1994 // mangling is done to make sure that the final name can be properly
1995 // demangled. For example, for C functions without prototypes, name mangling
1996 // is not done and the unique suffix should not be appended then.
1998
1999 if (const auto *fd = dyn_cast<FunctionDecl>(nd)) {
2000 if (fd->isMultiVersion()) {
2001 cgm.errorNYI(nd->getSourceRange(),
2002 "getMangledName: multi-version functions");
2003 }
2004 }
2005 if (cgm.getLangOpts().GPURelocatableDeviceCode) {
2006 cgm.errorNYI(nd->getSourceRange(),
2007 "getMangledName: GPU relocatable device code");
2008 }
2009
2010 return std::string(out.str());
2011}
2012
2013static FunctionDecl *
2015 const FunctionDecl *protoFunc) {
2016 // If this is a C no-prototype function, we can take the 'easy' way out and
2017 // just create a function with no arguments/functions, etc.
2018 if (!protoFunc->hasPrototype())
2019 return FunctionDecl::Create(
2020 ctx, /*DC=*/ctx.getTranslationUnitDecl(),
2021 /*StartLoc=*/SourceLocation{}, /*NLoc=*/SourceLocation{}, bindName,
2022 protoFunc->getType(), /*TInfo=*/nullptr, StorageClass::SC_None);
2023
2024 QualType funcTy = protoFunc->getType();
2025 auto *fpt = cast<FunctionProtoType>(protoFunc->getType());
2026
2027 // If this is a member function, add an explicit 'this' to the function type.
2028 if (auto *methodDecl = dyn_cast<CXXMethodDecl>(protoFunc);
2029 methodDecl && methodDecl->isImplicitObjectMemberFunction()) {
2030 llvm::SmallVector<QualType> paramTypes{fpt->getParamTypes()};
2031 paramTypes.insert(paramTypes.begin(), methodDecl->getThisType());
2032
2033 funcTy = ctx.getFunctionType(fpt->getReturnType(), paramTypes,
2034 fpt->getExtProtoInfo());
2035 fpt = cast<FunctionProtoType>(funcTy);
2036 }
2037
2038 auto *tempFunc =
2040 /*StartLoc=*/SourceLocation{},
2041 /*NLoc=*/SourceLocation{}, bindName, funcTy,
2042 /*TInfo=*/nullptr, StorageClass::SC_None);
2043
2045 params.reserve(fpt->getNumParams());
2046
2047 // Add all of the parameters.
2048 for (unsigned i = 0, e = fpt->getNumParams(); i != e; ++i) {
2050 ctx, tempFunc, /*StartLoc=*/SourceLocation{},
2051 /*IdLoc=*/SourceLocation{},
2052 /*Id=*/nullptr, fpt->getParamType(i), /*TInfo=*/nullptr,
2053 StorageClass::SC_None, /*DefArg=*/nullptr);
2054 parm->setScopeInfo(0, i);
2055 params.push_back(parm);
2056 }
2057
2058 tempFunc->setParams(params);
2059
2060 return tempFunc;
2061}
2062
2063std::string
2065 const FunctionDecl *attachedFunction) {
2067 getASTContext(), bindName, attachedFunction);
2068
2069 std::string ret = getMangledNameImpl(*this, GlobalDecl(tempFunc), tempFunc);
2070
2071 // This does nothing (it is a do-nothing function), since this is a
2072 // slab-allocator, but leave a call in to immediately destroy this in case we
2073 // ever come up with a way of getting allocations back.
2074 getASTContext().Deallocate(tempFunc);
2075 return ret;
2076}
2077
2079 GlobalDecl canonicalGd = gd.getCanonicalDecl();
2080
2081 // Some ABIs don't have constructor variants. Make sure that base and complete
2082 // constructors get mangled the same.
2083 if (const auto *cd = dyn_cast<CXXConstructorDecl>(canonicalGd.getDecl())) {
2084 if (!getTarget().getCXXABI().hasConstructorVariants()) {
2085 errorNYI(cd->getSourceRange(),
2086 "getMangledName: C++ constructor without variants");
2087 return cast<NamedDecl>(gd.getDecl())->getIdentifier()->getName();
2088 }
2089 }
2090
2091 // Keep the first result in the case of a mangling collision.
2092 const auto *nd = cast<NamedDecl>(gd.getDecl());
2093 std::string mangledName = getMangledNameImpl(*this, gd, nd);
2094
2095 auto result = manglings.insert(std::make_pair(mangledName, gd));
2096 return mangledDeclNames[canonicalGd] = result.first->first();
2097}
2098
2100 assert(!d->getInit() && "Cannot emit definite definitions here!");
2101
2102 StringRef mangledName = getMangledName(d);
2103 mlir::Operation *gv = getGlobalValue(mangledName);
2104
2105 // If we already have a definition, not declaration, with the same mangled
2106 // name, emitting of declaration is not required (and would actually overwrite
2107 // the emitted definition).
2108 if (gv && !mlir::cast<cir::GlobalOp>(gv).isDeclaration())
2109 return;
2110
2111 // If we have not seen a reference to this variable yet, place it into the
2112 // deferred declarations table to be emitted if needed later.
2113 if (!mustBeEmitted(d) && !gv) {
2114 deferredDecls[mangledName] = d;
2115 return;
2116 }
2117
2118 // The tentative definition is the only definition.
2120}
2121
2123 // Never defer when EmitAllDecls is specified.
2124 if (langOpts.EmitAllDecls)
2125 return true;
2126
2127 const auto *vd = dyn_cast<VarDecl>(global);
2128 if (vd &&
2129 ((codeGenOpts.KeepPersistentStorageVariables &&
2130 (vd->getStorageDuration() == SD_Static ||
2131 vd->getStorageDuration() == SD_Thread)) ||
2132 (codeGenOpts.KeepStaticConsts && vd->getStorageDuration() == SD_Static &&
2133 vd->getType().isConstQualified())))
2134 return true;
2135
2136 return getASTContext().DeclMustBeEmitted(global);
2137}
2138
2140 // In OpenMP 5.0 variables and function may be marked as
2141 // device_type(host/nohost) and we should not emit them eagerly unless we sure
2142 // that they must be emitted on the host/device. To be sure we need to have
2143 // seen a declare target with an explicit mentioning of the function, we know
2144 // we have if the level of the declare target attribute is -1. Note that we
2145 // check somewhere else if we should emit this at all.
2146 if (langOpts.OpenMP >= 50 && !langOpts.OpenMPSimd) {
2147 std::optional<OMPDeclareTargetDeclAttr *> activeAttr =
2148 OMPDeclareTargetDeclAttr::getActiveAttr(global);
2149 if (!activeAttr || (*activeAttr)->getLevel() != (unsigned)-1)
2150 return false;
2151 }
2152
2153 const auto *fd = dyn_cast<FunctionDecl>(global);
2154 if (fd) {
2155 // Implicit template instantiations may change linkage if they are later
2156 // explicitly instantiated, so they should not be emitted eagerly.
2157 if (fd->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
2158 return false;
2159 // Defer until all versions have been semantically checked.
2160 if (fd->hasAttr<TargetVersionAttr>() && !fd->isMultiVersion())
2161 return false;
2162 if (langOpts.SYCLIsDevice) {
2163 errorNYI(fd->getSourceRange(), "mayBeEmittedEagerly: SYCL");
2164 return false;
2165 }
2166 }
2167 const auto *vd = dyn_cast<VarDecl>(global);
2168 if (vd)
2169 if (astContext.getInlineVariableDefinitionKind(vd) ==
2171 // A definition of an inline constexpr static data member may change
2172 // linkage later if it's redeclared outside the class.
2173 return false;
2174
2175 // If OpenMP is enabled and threadprivates must be generated like TLS, delay
2176 // codegen for global variables, because they may be marked as threadprivate.
2177 if (langOpts.OpenMP && langOpts.OpenMPUseTLS &&
2178 astContext.getTargetInfo().isTLSSupported() && isa<VarDecl>(global) &&
2179 !global->getType().isConstantStorage(astContext, false, false) &&
2180 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(global))
2181 return false;
2182
2183 assert((fd || vd) &&
2184 "Only FunctionDecl and VarDecl should hit this path so far.");
2185 return true;
2186}
2187
2188static bool shouldAssumeDSOLocal(const CIRGenModule &cgm,
2189 cir::CIRGlobalValueInterface gv) {
2190 if (gv.hasLocalLinkage())
2191 return true;
2192
2193 if (!gv.hasDefaultVisibility() && !gv.hasExternalWeakLinkage())
2194 return true;
2195
2196 // DLLImport explicitly marks the GV as external.
2197 // so it shouldn't be dso_local
2198 // But we don't have the info set now
2200
2201 const llvm::Triple &tt = cgm.getTriple();
2202 const CodeGenOptions &cgOpts = cgm.getCodeGenOpts();
2203 if (tt.isOSCygMing()) {
2204 // In MinGW and Cygwin, variables without DLLImport can still be
2205 // automatically imported from a DLL by the linker; don't mark variables
2206 // that potentially could come from another DLL as DSO local.
2207
2208 // With EmulatedTLS, TLS variables can be autoimported from other DLLs
2209 // (and this actually happens in the public interface of libstdc++), so
2210 // such variables can't be marked as DSO local. (Native TLS variables
2211 // can't be dllimported at all, though.)
2212 cgm.errorNYI("shouldAssumeDSOLocal: MinGW");
2213 }
2214
2215 // On COFF, don't mark 'extern_weak' symbols as DSO local. If these symbols
2216 // remain unresolved in the link, they can be resolved to zero, which is
2217 // outside the current DSO.
2218 if (tt.isOSBinFormatCOFF() && gv.hasExternalWeakLinkage())
2219 return false;
2220
2221 // Every other GV is local on COFF.
2222 // Make an exception for windows OS in the triple: Some firmware builds use
2223 // *-win32-macho triples. This (accidentally?) produced windows relocations
2224 // without GOT tables in older clang versions; Keep this behaviour.
2225 // FIXME: even thread local variables?
2226 if (tt.isOSBinFormatCOFF() || (tt.isOSWindows() && tt.isOSBinFormatMachO()))
2227 return true;
2228
2229 // Only handle COFF and ELF for now.
2230 if (!tt.isOSBinFormatELF())
2231 return false;
2232
2233 llvm::Reloc::Model rm = cgOpts.RelocationModel;
2234 const LangOptions &lOpts = cgm.getLangOpts();
2235 if (rm != llvm::Reloc::Static && !lOpts.PIE) {
2236 // On ELF, if -fno-semantic-interposition is specified and the target
2237 // supports local aliases, there will be neither CC1
2238 // -fsemantic-interposition nor -fhalf-no-semantic-interposition. Set
2239 // dso_local on the function if using a local alias is preferable (can avoid
2240 // PLT indirection).
2241 if (!(isa<cir::FuncOp>(gv) && gv.canBenefitFromLocalAlias()))
2242 return false;
2243 return !(lOpts.SemanticInterposition || lOpts.HalfNoSemanticInterposition);
2244 }
2245
2246 // A definition cannot be preempted from an executable.
2247 if (!gv.isDeclarationForLinker())
2248 return true;
2249
2250 // Most PIC code sequences that assume that a symbol is local cannot produce a
2251 // 0 if it turns out the symbol is undefined. While this is ABI and relocation
2252 // depended, it seems worth it to handle it here.
2253 if (rm == llvm::Reloc::PIC_ && gv.hasExternalWeakLinkage())
2254 return false;
2255
2256 // PowerPC64 prefers TOC indirection to avoid copy relocations.
2257 if (tt.isPPC64())
2258 return false;
2259
2260 if (cgOpts.DirectAccessExternalData) {
2261 // If -fdirect-access-external-data (default for -fno-pic), set dso_local
2262 // for non-thread-local variables. If the symbol is not defined in the
2263 // executable, a copy relocation will be needed at link time. dso_local is
2264 // excluded for thread-local variables because they generally don't support
2265 // copy relocations.
2266 if (auto globalOp = dyn_cast<cir::GlobalOp>(gv.getOperation())) {
2267 // Assume variables are not thread-local until that support is added.
2269 return true;
2270 }
2271
2272 // -fno-pic sets dso_local on a function declaration to allow direct
2273 // accesses when taking its address (similar to a data symbol). If the
2274 // function is not defined in the executable, a canonical PLT entry will be
2275 // needed at link time. -fno-direct-access-external-data can avoid the
2276 // canonical PLT entry. We don't generalize this condition to -fpie/-fpic as
2277 // it could just cause trouble without providing perceptible benefits.
2278 if (isa<cir::FuncOp>(gv) && !cgOpts.NoPLT && rm == llvm::Reloc::Static)
2279 return true;
2280 }
2281
2282 // If we can use copy relocations we can assume it is local.
2283
2284 // Otherwise don't assume it is local.
2285
2286 return false;
2287}
2288
2289void CIRGenModule::setGlobalVisibility(mlir::Operation *gv,
2290 const NamedDecl *d) const {
2292}
2293
2294void CIRGenModule::setDSOLocal(cir::CIRGlobalValueInterface gv) const {
2295 gv.setDSOLocal(shouldAssumeDSOLocal(*this, gv));
2296}
2297
2298void CIRGenModule::setDSOLocal(mlir::Operation *op) const {
2299 if (auto globalValue = dyn_cast<cir::CIRGlobalValueInterface>(op))
2300 setDSOLocal(globalValue);
2301}
2302
2303void CIRGenModule::setGVProperties(mlir::Operation *op,
2304 const NamedDecl *d) const {
2306 setGVPropertiesAux(op, d);
2307}
2308
2309void CIRGenModule::setGVPropertiesAux(mlir::Operation *op,
2310 const NamedDecl *d) const {
2311 setGlobalVisibility(op, d);
2312 setDSOLocal(op);
2314}
2315
2317 GlobalDecl &result) const {
2318 auto res = manglings.find(mangledName);
2319 if (res == manglings.end())
2320 return false;
2321 result = res->getValue();
2322 return true;
2323}
2324
2326 switch (getCodeGenOpts().getDefaultTLSModel()) {
2328 return cir::TLS_Model::GeneralDynamic;
2330 return cir::TLS_Model::LocalDynamic;
2332 return cir::TLS_Model::InitialExec;
2334 return cir::TLS_Model::LocalExec;
2335 }
2336 llvm_unreachable("Invalid TLS model!");
2337}
2338
2339void CIRGenModule::setTLSMode(mlir::Operation *op, const VarDecl &d) {
2340 assert(d.getTLSKind() && "setting TLS mode on non-TLS var!");
2341
2342 cir::TLS_Model tlm = getDefaultCIRTLSModel();
2343
2344 // Override the TLS model if it is explicitly specified.
2345 if (d.getAttr<TLSModelAttr>())
2346 errorNYI(d.getSourceRange(), "TLS model attribute");
2347
2348 auto global = cast<cir::GlobalOp>(op);
2349 global.setTlsModel(tlm);
2350}
2351
2353 const CIRGenFunctionInfo &info,
2354 cir::FuncOp func, bool isThunk) {
2355 // TODO(cir): More logic of constructAttributeList is needed.
2356 cir::CallingConv callingConv;
2357 cir::SideEffect sideEffect;
2358
2359 // TODO(cir): The current list should be initialized with the extra function
2360 // attributes, but we don't have those yet. For now, the PAL is initialized
2361 // with nothing.
2363 // Initialize PAL with existing attributes to merge attributes.
2364 mlir::NamedAttrList pal{};
2365 std::vector<mlir::NamedAttrList> argAttrs(info.arguments().size());
2366 mlir::NamedAttrList retAttrs{};
2367 constructAttributeList(func.getName(), info, globalDecl, pal, argAttrs,
2368 retAttrs, callingConv, sideEffect,
2369 /*attrOnCallSite=*/false, isThunk);
2370
2371 for (mlir::NamedAttribute attr : pal)
2372 func->setAttr(attr.getName(), attr.getValue());
2373
2374 llvm::for_each(llvm::enumerate(argAttrs), [func](auto idx_arg_pair) {
2375 mlir::function_interface_impl::setArgAttrs(func, idx_arg_pair.index(),
2376 idx_arg_pair.value());
2377 });
2378 if (!retAttrs.empty())
2379 mlir::function_interface_impl::setResultAttrs(func, 0, retAttrs);
2380
2381 // TODO(cir): Check X86_VectorCall incompatibility wiht WinARM64EC
2382
2383 // TODO(cir): typically the calling conv is set right here, but since
2384 // cir::CallingConv is empty and we've not yet added calling-conv to FuncOop,
2385 // this isn't really useful here. This should call func.setCallingConv/etc
2386 // later.
2388}
2389
2391 cir::FuncOp func,
2392 bool isIncompleteFunction,
2393 bool isThunk) {
2394 // NOTE(cir): Original CodeGen checks if this is an intrinsic. In CIR we
2395 // represent them in dedicated ops. The correct attributes are ensured during
2396 // translation to LLVM. Thus, we don't need to check for them here.
2397
2398 if (!isIncompleteFunction)
2399 setCIRFunctionAttributes(globalDecl,
2400 getTypes().arrangeGlobalDeclaration(globalDecl),
2401 func, isThunk);
2402
2404
2405 // TODO(cir): This needs a lot of work to better match CodeGen. That
2406 // ultimately ends up in setGlobalVisibility, which already has the linkage of
2407 // the LLVM GV (corresponding to our FuncOp) computed, so it doesn't have to
2408 // recompute it here. This is a minimal fix for now.
2409 if (!isLocalLinkage(getFunctionLinkage(globalDecl))) {
2410 const Decl *decl = globalDecl.getDecl();
2411 func.setGlobalVisibilityAttr(getGlobalVisibilityAttrFromDecl(decl));
2412 }
2413
2414 // If we plan on emitting this inline builtin, we can't treat it as a builtin.
2415 const auto *fd = cast<FunctionDecl>(globalDecl.getDecl());
2416 if (fd->isInlineBuiltinDeclaration()) {
2417 const FunctionDecl *fdBody;
2418 bool hasBody = fd->hasBody(fdBody);
2419 (void)hasBody;
2420 assert(hasBody && "Inline builtin declarations should always have an "
2421 "available body!");
2423 }
2424
2425 if (fd->isReplaceableGlobalAllocationFunction()) {
2426 // A replaceable global allocation function does not act like a builtin by
2427 // default, only if it is invoked by a new-expression or delete-expression.
2428 func->setAttr(cir::CIRDialect::getNoBuiltinAttrName(),
2429 mlir::UnitAttr::get(&getMLIRContext()));
2430 }
2431}
2432
2434 const clang::FunctionDecl *decl, cir::FuncOp f) {
2437
2438 std::optional<cir::InlineKind> existingInlineKind = f.getInlineKind();
2439 bool isNoInline =
2440 existingInlineKind && *existingInlineKind == cir::InlineKind::NoInline;
2441 bool isAlwaysInline = existingInlineKind &&
2442 *existingInlineKind == cir::InlineKind::AlwaysInline;
2443 if (!decl) {
2444 assert(!cir::MissingFeatures::hlsl());
2445
2446 if (!isAlwaysInline &&
2447 codeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) {
2448 // If inlining is disabled and we don't have a declaration to control
2449 // inlining, mark the function as 'noinline' unless it is explicitly
2450 // marked as 'alwaysinline'.
2451 f.setInlineKind(cir::InlineKind::NoInline);
2452 }
2453
2454 return;
2455 }
2456
2463 assert(!cir::MissingFeatures::hlsl());
2464
2465 // Handle inline attributes
2466 if (decl->hasAttr<NoInlineAttr>() && !isAlwaysInline) {
2467 // Add noinline if the function isn't always_inline.
2468 f.setInlineKind(cir::InlineKind::NoInline);
2469 } else if (decl->hasAttr<AlwaysInlineAttr>() && !isNoInline) {
2470 // Don't override AlwaysInline with NoInline, or vice versa, since we can't
2471 // specify both in IR.
2472 f.setInlineKind(cir::InlineKind::AlwaysInline);
2473 } else if (codeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) {
2474 // If inlining is disabled, force everything that isn't always_inline
2475 // to carry an explicit noinline attribute.
2476 if (!isAlwaysInline)
2477 f.setInlineKind(cir::InlineKind::NoInline);
2478 } else {
2479 // Otherwise, propagate the inline hint attribute and potentially use its
2480 // absence to mark things as noinline.
2481 // Search function and template pattern redeclarations for inline.
2482 if (auto *fd = dyn_cast<FunctionDecl>(decl)) {
2483 // TODO: Share this checkForInline implementation with classic codegen.
2484 // This logic is likely to change over time, so sharing would help ensure
2485 // consistency.
2486 auto checkForInline = [](const FunctionDecl *decl) {
2487 auto checkRedeclForInline = [](const FunctionDecl *redecl) {
2488 return redecl->isInlineSpecified();
2489 };
2490 if (any_of(decl->redecls(), checkRedeclForInline))
2491 return true;
2492 const FunctionDecl *pattern = decl->getTemplateInstantiationPattern();
2493 if (!pattern)
2494 return false;
2495 return any_of(pattern->redecls(), checkRedeclForInline);
2496 };
2497 if (checkForInline(fd)) {
2498 f.setInlineKind(cir::InlineKind::InlineHint);
2499 } else if (codeGenOpts.getInlining() ==
2501 !fd->isInlined() && !isAlwaysInline) {
2502 f.setInlineKind(cir::InlineKind::NoInline);
2503 }
2504 }
2505 }
2506
2508}
2509
2511 StringRef mangledName, mlir::Type funcType, GlobalDecl gd, bool forVTable,
2512 bool dontDefer, bool isThunk, ForDefinition_t isForDefinition,
2513 mlir::NamedAttrList extraAttrs) {
2514 const Decl *d = gd.getDecl();
2515
2516 if (const auto *fd = cast_or_null<FunctionDecl>(d)) {
2517 // For the device mark the function as one that should be emitted.
2518 if (getLangOpts().OpenMPIsTargetDevice && fd->isDefined() && !dontDefer &&
2519 !isForDefinition)
2520 errorNYI(fd->getSourceRange(),
2521 "getOrCreateCIRFunction: OpenMP target function");
2522
2523 // Any attempts to use a MultiVersion function should result in retrieving
2524 // the iFunc instead. Name mangling will handle the rest of the changes.
2525 if (fd->isMultiVersion())
2526 errorNYI(fd->getSourceRange(), "getOrCreateCIRFunction: multi-version");
2527 }
2528
2529 // Lookup the entry, lazily creating it if necessary.
2530 mlir::Operation *entry = getGlobalValue(mangledName);
2531 if (entry) {
2532 assert(mlir::isa<cir::FuncOp>(entry));
2533
2535
2536 // Handle dropped DLL attributes.
2537 if (d && !d->hasAttr<DLLImportAttr>() && !d->hasAttr<DLLExportAttr>()) {
2539 setDSOLocal(entry);
2540 }
2541
2542 // If there are two attempts to define the same mangled name, issue an
2543 // error.
2544 auto fn = cast<cir::FuncOp>(entry);
2545 if (isForDefinition && fn && !fn.isDeclaration()) {
2546 GlobalDecl otherGd;
2547 // Check that GD is not yet in DiagnosedConflictingDefinitions is required
2548 // to make sure that we issue an error only once.
2549 if (lookupRepresentativeDecl(mangledName, otherGd) &&
2550 (gd.getCanonicalDecl().getDecl() !=
2551 otherGd.getCanonicalDecl().getDecl()) &&
2552 diagnosedConflictingDefinitions.insert(gd).second) {
2553 getDiags().Report(d->getLocation(), diag::err_duplicate_mangled_name)
2554 << mangledName;
2555 getDiags().Report(otherGd.getDecl()->getLocation(),
2556 diag::note_previous_definition);
2557 }
2558 }
2559
2560 if (fn && fn.getFunctionType() == funcType) {
2561 return fn;
2562 }
2563
2564 if (!isForDefinition) {
2565 return fn;
2566 }
2567
2568 // TODO(cir): classic codegen checks here if this is a llvm::GlobalAlias.
2569 // How will we support this?
2570 }
2571
2572 auto *funcDecl = llvm::cast_or_null<FunctionDecl>(gd.getDecl());
2573 bool invalidLoc = !funcDecl ||
2574 funcDecl->getSourceRange().getBegin().isInvalid() ||
2575 funcDecl->getSourceRange().getEnd().isInvalid();
2576 cir::FuncOp funcOp = createCIRFunction(
2577 invalidLoc ? theModule->getLoc() : getLoc(funcDecl->getSourceRange()),
2578 mangledName, mlir::cast<cir::FuncType>(funcType), funcDecl);
2579
2580 // If we already created a function with the same mangled name (but different
2581 // type) before, take its name and add it to the list of functions to be
2582 // replaced with F at the end of CodeGen.
2583 //
2584 // This happens if there is a prototype for a function (e.g. "int f()") and
2585 // then a definition of a different type (e.g. "int f(int x)").
2586 if (entry) {
2587
2588 // Fetch a generic symbol-defining operation and its uses.
2589 auto symbolOp = mlir::cast<mlir::SymbolOpInterface>(entry);
2590
2591 // This might be an implementation of a function without a prototype, in
2592 // which case, try to do special replacement of calls which match the new
2593 // prototype. The really key thing here is that we also potentially drop
2594 // arguments from the call site so as to make a direct call, which makes the
2595 // inliner happier and suppresses a number of optimizer warnings (!) about
2596 // dropping arguments.
2597 if (symbolOp.getSymbolUses(symbolOp->getParentOp()))
2599
2600 // Obliterate no-proto declaration.
2601 entry->erase();
2602 }
2603
2604 if (d)
2605 setFunctionAttributes(gd, funcOp, /*isIncompleteFunction=*/false, isThunk);
2606 if (!extraAttrs.empty()) {
2607 extraAttrs.append(funcOp->getAttrs());
2608 funcOp->setAttrs(extraAttrs);
2609 }
2610
2611 // 'dontDefer' actually means don't move this to the deferredDeclsToEmit list.
2612 if (dontDefer) {
2613 // TODO(cir): This assertion will need an additional condition when we
2614 // support incomplete functions.
2615 assert(funcOp.getFunctionType() == funcType);
2616 return funcOp;
2617 }
2618
2619 // All MSVC dtors other than the base dtor are linkonce_odr and delegate to
2620 // each other bottoming out wiht the base dtor. Therefore we emit non-base
2621 // dtors on usage, even if there is no dtor definition in the TU.
2622 if (isa_and_nonnull<CXXDestructorDecl>(d) &&
2623 getCXXABI().useThunkForDtorVariant(cast<CXXDestructorDecl>(d),
2624 gd.getDtorType()))
2625 errorNYI(d->getSourceRange(), "getOrCreateCIRFunction: dtor");
2626
2627 // This is the first use or definition of a mangled name. If there is a
2628 // deferred decl with this name, remember that we need to emit it at the end
2629 // of the file.
2630 auto ddi = deferredDecls.find(mangledName);
2631 if (ddi != deferredDecls.end()) {
2632 // Move the potentially referenced deferred decl to the
2633 // DeferredDeclsToEmit list, and remove it from DeferredDecls (since we
2634 // don't need it anymore).
2635 addDeferredDeclToEmit(ddi->second);
2636 deferredDecls.erase(ddi);
2637
2638 // Otherwise, there are cases we have to worry about where we're using a
2639 // declaration for which we must emit a definition but where we might not
2640 // find a top-level definition.
2641 // - member functions defined inline in their classes
2642 // - friend functions defined inline in some class
2643 // - special member functions with implicit definitions
2644 // If we ever change our AST traversal to walk into class methods, this
2645 // will be unnecessary.
2646 //
2647 // We also don't emit a definition for a function if it's going to be an
2648 // entry in a vtable, unless it's already marked as used.
2649 } else if (getLangOpts().CPlusPlus && d) {
2650 // Look for a declaration that's lexically in a record.
2651 for (const auto *fd = cast<FunctionDecl>(d)->getMostRecentDecl(); fd;
2652 fd = fd->getPreviousDecl()) {
2653 if (isa<CXXRecordDecl>(fd->getLexicalDeclContext())) {
2654 if (fd->doesThisDeclarationHaveABody()) {
2656 break;
2657 }
2658 }
2659 }
2660 }
2661
2662 return funcOp;
2663}
2664
2665cir::FuncOp
2666CIRGenModule::createCIRFunction(mlir::Location loc, StringRef name,
2667 cir::FuncType funcType,
2668 const clang::FunctionDecl *funcDecl) {
2669 cir::FuncOp func;
2670 {
2671 mlir::OpBuilder::InsertionGuard guard(builder);
2672
2673 // Some global emissions are triggered while emitting a function, e.g.
2674 // void s() { x.method() }
2675 //
2676 // Be sure to insert a new function before a current one.
2677 CIRGenFunction *cgf = this->curCGF;
2678 if (cgf)
2679 builder.setInsertionPoint(cgf->curFn);
2680
2681 func = cir::FuncOp::create(builder, loc, name, funcType);
2682
2684
2685 if (funcDecl && !funcDecl->hasPrototype())
2686 func.setNoProto(true);
2687
2688 assert(func.isDeclaration() && "expected empty body");
2689
2690 // A declaration gets private visibility by default, but external linkage
2691 // as the default linkage.
2692 func.setLinkageAttr(cir::GlobalLinkageKindAttr::get(
2693 &getMLIRContext(), cir::GlobalLinkageKind::ExternalLinkage));
2694 mlir::SymbolTable::setSymbolVisibility(
2695 func, mlir::SymbolTable::Visibility::Private);
2696
2698
2699 // Mark C++ special member functions (Constructor, Destructor etc.)
2700 setCXXSpecialMemberAttr(func, funcDecl);
2701
2702 if (!cgf)
2703 theModule.push_back(func);
2704
2705 if (this->getLangOpts().OpenACC) {
2706 // We only have to handle this attribute, since OpenACCAnnotAttrs are
2707 // handled via the end-of-TU work.
2708 for (const auto *attr :
2709 funcDecl->specific_attrs<OpenACCRoutineDeclAttr>())
2710 emitOpenACCRoutineDecl(funcDecl, func, attr->getLocation(),
2711 attr->Clauses);
2712 }
2713 }
2714 return func;
2715}
2716
2717cir::FuncOp
2718CIRGenModule::createCIRBuiltinFunction(mlir::Location loc, StringRef name,
2719 cir::FuncType ty,
2720 const clang::FunctionDecl *fd) {
2721 cir::FuncOp fnOp = createCIRFunction(loc, name, ty, fd);
2722 fnOp.setBuiltin(true);
2723 return fnOp;
2724}
2725
2726static cir::CtorKind getCtorKindFromDecl(const CXXConstructorDecl *ctor) {
2727 if (ctor->isDefaultConstructor())
2728 return cir::CtorKind::Default;
2729 if (ctor->isCopyConstructor())
2730 return cir::CtorKind::Copy;
2731 if (ctor->isMoveConstructor())
2732 return cir::CtorKind::Move;
2733 return cir::CtorKind::Custom;
2734}
2735
2736static cir::AssignKind getAssignKindFromDecl(const CXXMethodDecl *method) {
2737 if (method->isCopyAssignmentOperator())
2738 return cir::AssignKind::Copy;
2739 if (method->isMoveAssignmentOperator())
2740 return cir::AssignKind::Move;
2741 llvm_unreachable("not a copy or move assignment operator");
2742}
2743
2745 cir::FuncOp funcOp, const clang::FunctionDecl *funcDecl) {
2746 if (!funcDecl)
2747 return;
2748
2749 if (const auto *dtor = dyn_cast<CXXDestructorDecl>(funcDecl)) {
2750 auto cxxDtor = cir::CXXDtorAttr::get(
2751 convertType(getASTContext().getCanonicalTagType(dtor->getParent())),
2752 dtor->isTrivial());
2753 funcOp.setCxxSpecialMemberAttr(cxxDtor);
2754 return;
2755 }
2756
2757 if (const auto *ctor = dyn_cast<CXXConstructorDecl>(funcDecl)) {
2758 cir::CtorKind kind = getCtorKindFromDecl(ctor);
2759 auto cxxCtor = cir::CXXCtorAttr::get(
2760 convertType(getASTContext().getCanonicalTagType(ctor->getParent())),
2761 kind, ctor->isTrivial());
2762 funcOp.setCxxSpecialMemberAttr(cxxCtor);
2763 return;
2764 }
2765
2766 const auto *method = dyn_cast<CXXMethodDecl>(funcDecl);
2767 if (method && (method->isCopyAssignmentOperator() ||
2768 method->isMoveAssignmentOperator())) {
2769 cir::AssignKind assignKind = getAssignKindFromDecl(method);
2770 auto cxxAssign = cir::CXXAssignAttr::get(
2771 convertType(getASTContext().getCanonicalTagType(method->getParent())),
2772 assignKind, method->isTrivial());
2773 funcOp.setCxxSpecialMemberAttr(cxxAssign);
2774 return;
2775 }
2776}
2777
2778static void setWindowsItaniumDLLImport(CIRGenModule &cgm, bool isLocal,
2779 cir::FuncOp funcOp, StringRef name) {
2780 // In Windows Itanium environments, try to mark runtime functions
2781 // dllimport. For Mingw and MSVC, don't. We don't really know if the user
2782 // will link their standard library statically or dynamically. Marking
2783 // functions imported when they are not imported can cause linker errors
2784 // and warnings.
2785 if (!isLocal && cgm.getTarget().getTriple().isWindowsItaniumEnvironment() &&
2786 !cgm.getCodeGenOpts().LTOVisibilityPublicStd) {
2790 }
2791}
2792
2793cir::FuncOp CIRGenModule::createRuntimeFunction(cir::FuncType ty,
2794 StringRef name,
2795 mlir::NamedAttrList extraAttrs,
2796 bool isLocal,
2797 bool assumeConvergent) {
2798 if (assumeConvergent)
2799 errorNYI("createRuntimeFunction: assumeConvergent");
2800
2801 cir::FuncOp entry = getOrCreateCIRFunction(name, ty, GlobalDecl(),
2802 /*forVtable=*/false, extraAttrs);
2803
2804 if (entry) {
2805 // TODO(cir): set the attributes of the function.
2808 setWindowsItaniumDLLImport(*this, isLocal, entry, name);
2809 entry.setDSOLocal(true);
2810 }
2811
2812 return entry;
2813}
2814
2815mlir::SymbolTable::Visibility
2817 // MLIR doesn't accept public symbols declarations (only
2818 // definitions).
2819 if (op.isDeclaration())
2820 return mlir::SymbolTable::Visibility::Private;
2821 return getMLIRVisibilityFromCIRLinkage(op.getLinkage());
2822}
2823
2824mlir::SymbolTable::Visibility
2826 switch (glk) {
2827 case cir::GlobalLinkageKind::InternalLinkage:
2828 case cir::GlobalLinkageKind::PrivateLinkage:
2829 return mlir::SymbolTable::Visibility::Private;
2830 case cir::GlobalLinkageKind::ExternalLinkage:
2831 case cir::GlobalLinkageKind::ExternalWeakLinkage:
2832 case cir::GlobalLinkageKind::LinkOnceODRLinkage:
2833 case cir::GlobalLinkageKind::AvailableExternallyLinkage:
2834 case cir::GlobalLinkageKind::CommonLinkage:
2835 case cir::GlobalLinkageKind::WeakAnyLinkage:
2836 case cir::GlobalLinkageKind::WeakODRLinkage:
2837 return mlir::SymbolTable::Visibility::Public;
2838 default: {
2839 llvm::errs() << "visibility not implemented for '"
2840 << stringifyGlobalLinkageKind(glk) << "'\n";
2841 assert(0 && "not implemented");
2842 }
2843 }
2844 llvm_unreachable("linkage should be handled above!");
2845}
2846
2848 clang::VisibilityAttr::VisibilityType visibility) {
2849 switch (visibility) {
2850 case clang::VisibilityAttr::VisibilityType::Default:
2851 return cir::VisibilityKind::Default;
2852 case clang::VisibilityAttr::VisibilityType::Hidden:
2853 return cir::VisibilityKind::Hidden;
2854 case clang::VisibilityAttr::VisibilityType::Protected:
2855 return cir::VisibilityKind::Protected;
2856 }
2857 llvm_unreachable("unexpected visibility value");
2858}
2859
2860cir::VisibilityAttr
2862 const clang::VisibilityAttr *va = decl->getAttr<clang::VisibilityAttr>();
2863 cir::VisibilityAttr cirVisibility =
2864 cir::VisibilityAttr::get(&getMLIRContext());
2865 if (va) {
2866 cirVisibility = cir::VisibilityAttr::get(
2867 &getMLIRContext(),
2868 getGlobalVisibilityKindFromClangVisibility(va->getVisibility()));
2869 }
2870 return cirVisibility;
2871}
2872
2874 emitDeferred();
2876 applyReplacements();
2877
2878 theModule->setAttr(cir::CIRDialect::getModuleLevelAsmAttrName(),
2879 builder.getArrayAttr(globalScopeAsm));
2880
2881 // There's a lot of code that is not implemented yet.
2883}
2884
2885void CIRGenModule::emitAliasForGlobal(StringRef mangledName,
2886 mlir::Operation *op, GlobalDecl aliasGD,
2887 cir::FuncOp aliasee,
2888 cir::GlobalLinkageKind linkage) {
2889
2890 auto *aliasFD = dyn_cast<FunctionDecl>(aliasGD.getDecl());
2891 assert(aliasFD && "expected FunctionDecl");
2892
2893 // The aliasee function type is different from the alias one, this difference
2894 // is specific to CIR because in LLVM the ptr types are already erased at this
2895 // point.
2896 const CIRGenFunctionInfo &fnInfo =
2898 cir::FuncType fnType = getTypes().getFunctionType(fnInfo);
2899
2900 cir::FuncOp alias =
2902 mangledName, fnType, aliasFD);
2903 alias.setAliasee(aliasee.getName());
2904 alias.setLinkage(linkage);
2905 // Declarations cannot have public MLIR visibility, just mark them private
2906 // but this really should have no meaning since CIR should not be using
2907 // this information to derive linkage information.
2908 mlir::SymbolTable::setSymbolVisibility(
2909 alias, mlir::SymbolTable::Visibility::Private);
2910
2911 // Alias constructors and destructors are always unnamed_addr.
2913
2914 // Switch any previous uses to the alias.
2915 if (op) {
2916 errorNYI(aliasFD->getSourceRange(), "emitAliasForGlobal: previous uses");
2917 } else {
2918 // Name already set by createCIRFunction
2919 }
2920
2921 // Finally, set up the alias with its proper name and attributes.
2922 setCommonAttributes(aliasGD, alias);
2923}
2924
2926 return genTypes.convertType(type);
2927}
2928
2930 // Verify the module after we have finished constructing it, this will
2931 // check the structural properties of the IR and invoke any specific
2932 // verifiers we have on the CIR operations.
2933 return mlir::verify(theModule).succeeded();
2934}
2935
2936mlir::Attribute CIRGenModule::getAddrOfRTTIDescriptor(mlir::Location loc,
2937 QualType ty, bool forEh) {
2938 // Return a bogus pointer if RTTI is disabled, unless it's for EH.
2939 // FIXME: should we even be calling this method if RTTI is disabled
2940 // and it's not for EH?
2941 if (!shouldEmitRTTI(forEh))
2942 return builder.getConstNullPtrAttr(builder.getUInt8PtrTy());
2943
2944 if (forEh && ty->isObjCObjectPointerType() &&
2945 langOpts.ObjCRuntime.isGNUFamily()) {
2946 errorNYI(loc, "getAddrOfRTTIDescriptor: Objc PtrType & Objc RT GUN");
2947 return {};
2948 }
2949
2950 return getCXXABI().getAddrOfRTTIDescriptor(loc, ty);
2951}
2952
2953// TODO(cir): this can be shared with LLVM codegen.
2955 const CXXRecordDecl *derivedClass,
2956 llvm::iterator_range<CastExpr::path_const_iterator> path) {
2957 CharUnits offset = CharUnits::Zero();
2958
2959 const ASTContext &astContext = getASTContext();
2960 const CXXRecordDecl *rd = derivedClass;
2961
2962 for (const CXXBaseSpecifier *base : path) {
2963 assert(!base->isVirtual() && "Should not see virtual bases here!");
2964
2965 // Get the layout.
2966 const ASTRecordLayout &layout = astContext.getASTRecordLayout(rd);
2967
2968 const auto *baseDecl = base->getType()->castAsCXXRecordDecl();
2969
2970 // Add the offset.
2971 offset += layout.getBaseClassOffset(baseDecl);
2972
2973 rd = baseDecl;
2974 }
2975
2976 return offset;
2977}
2978
2980 llvm::StringRef feature) {
2981 unsigned diagID = diags.getCustomDiagID(
2982 DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0");
2983 return diags.Report(loc, diagID) << feature;
2984}
2985
2987 llvm::StringRef feature) {
2988 return errorNYI(loc.getBegin(), feature) << loc;
2989}
2990
2992 unsigned diagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error, "%0");
2993 getDiags().Report(astContext.getFullLoc(loc), diagID) << error;
2994}
2995
2996/// Print out an error that codegen doesn't support the specified stmt yet.
2997void CIRGenModule::errorUnsupported(const Stmt *s, llvm::StringRef type) {
2998 unsigned diagId = diags.getCustomDiagID(DiagnosticsEngine::Error,
2999 "cannot compile this %0 yet");
3000 diags.Report(astContext.getFullLoc(s->getBeginLoc()), diagId)
3001 << type << s->getSourceRange();
3002}
3003
3004/// Print out an error that codegen doesn't support the specified decl yet.
3005void CIRGenModule::errorUnsupported(const Decl *d, llvm::StringRef type) {
3006 unsigned diagId = diags.getCustomDiagID(DiagnosticsEngine::Error,
3007 "cannot compile this %0 yet");
3008 diags.Report(astContext.getFullLoc(d->getLocation()), diagId) << type;
3009}
3010
3011void CIRGenModule::mapBlockAddress(cir::BlockAddrInfoAttr blockInfo,
3012 cir::LabelOp label) {
3013 [[maybe_unused]] auto result =
3014 blockAddressInfoToLabel.try_emplace(blockInfo, label);
3015 assert(result.second &&
3016 "attempting to map a blockaddress info that is already mapped");
3017}
3018
3019void CIRGenModule::mapUnresolvedBlockAddress(cir::BlockAddressOp op) {
3020 [[maybe_unused]] auto result = unresolvedBlockAddressToLabel.insert(op);
3021 assert(result.second &&
3022 "attempting to map a blockaddress operation that is already mapped");
3023}
3024
3025void CIRGenModule::mapResolvedBlockAddress(cir::BlockAddressOp op,
3026 cir::LabelOp label) {
3027 [[maybe_unused]] auto result = blockAddressToLabel.try_emplace(op, label);
3028 assert(result.second &&
3029 "attempting to map a blockaddress operation that is already mapped");
3030}
3031
3033 cir::LabelOp newLabel) {
3034 auto *it = blockAddressToLabel.find(op);
3035 assert(it != blockAddressToLabel.end() &&
3036 "trying to update a blockaddress not previously mapped");
3037 assert(!it->second && "blockaddress already has a resolved label");
3038
3039 it->second = newLabel;
3040}
3041
3042cir::LabelOp
3043CIRGenModule::lookupBlockAddressInfo(cir::BlockAddrInfoAttr blockInfo) {
3044 return blockAddressInfoToLabel.lookup(blockInfo);
3045}
3046
3047mlir::Operation *
3049 const Expr *init) {
3050 assert((mte->getStorageDuration() == SD_Static ||
3051 mte->getStorageDuration() == SD_Thread) &&
3052 "not a global temporary");
3053 const auto *varDecl = cast<VarDecl>(mte->getExtendingDecl());
3054
3055 // If we're not materializing a subobject of the temporary, keep the
3056 // cv-qualifiers from the type of the MaterializeTemporaryExpr.
3057 QualType materializedType = init->getType();
3058 if (init == mte->getSubExpr())
3059 materializedType = mte->getType();
3060
3061 CharUnits align = getASTContext().getTypeAlignInChars(materializedType);
3062
3063 auto insertResult = materializedGlobalTemporaryMap.insert({mte, nullptr});
3064 if (!insertResult.second)
3065 errorNYI(mte->getSourceRange(), "duplicate materialized temporaries");
3066
3067 // FIXME: If an externally-visible declaration extends multiple temporaries,
3068 // we need to give each temporary the same name in every translation unit (and
3069 // we also need to make the temporaries externally-visible).
3071 llvm::raw_svector_ostream out(name);
3073 varDecl, mte->getManglingNumber(), out);
3074
3075 APValue *value = nullptr;
3076 if (mte->getStorageDuration() == SD_Static && varDecl->evaluateValue()) {
3077 // If the initializer of the extending declaration is a constant
3078 // initializer, we should have a cached constant initializer for this
3079 // temporay. Note taht this m ight have a different value from the value
3080 // computed by evaluating the initializer if the surrounding constant
3081 // expression modifies the temporary.
3082 value = mte->getOrCreateValue(/*MayCreate=*/false);
3083 }
3084
3085 // Try evaluating it now, it might have a constant initializer
3086 Expr::EvalResult evalResult;
3087 if (!value && init->EvaluateAsRValue(evalResult, getASTContext()) &&
3088 !evalResult.hasSideEffects())
3089 value = &evalResult.Val;
3090
3092
3093 std::optional<ConstantEmitter> emitter;
3094 mlir::Attribute initialValue = nullptr;
3095 bool isConstant = false;
3096 mlir::Type type;
3097
3098 if (value) {
3099 emitter.emplace(*this);
3100 initialValue = emitter->emitForInitializer(*value, materializedType);
3101
3102 isConstant = materializedType.isConstantStorage(
3103 getASTContext(), /*ExcludeCtor=*/value, /*ExcludeDtor=*/false);
3104
3105 type = mlir::cast<mlir::TypedAttr>(initialValue).getType();
3106 } else {
3107 // No initializer, the initialization will be provided when we initialize
3108 // the declaration which performed lifetime extension.
3109 type = getTypes().convertTypeForMem(materializedType);
3110 }
3111
3112 // Create a global variable for this lifetime-extended temporary.
3113 cir::GlobalLinkageKind linkage =
3114 getCIRLinkageVarDefinition(varDecl, /*isConstant=*/false);
3115 if (linkage == cir::GlobalLinkageKind::ExternalLinkage) {
3116 const VarDecl *initVD;
3117 if (varDecl->isStaticDataMember() && varDecl->getAnyInitializer(initVD) &&
3119 // Temporaries defined inside a class get linkonce_odr linkage because the
3120 // calss can be defined in multiple translation units.
3121 errorNYI(mte->getSourceRange(), "static data member initialization");
3122 } else {
3123 // There is no need for this temporary to have external linkage if the
3124 // VarDecl has external linkage.
3125 linkage = cir::GlobalLinkageKind::InternalLinkage;
3126 }
3127 }
3128 mlir::Location loc = getLoc(mte->getSourceRange());
3129 cir::GlobalOp gv = createGlobalOp(*this, loc, name, type, isConstant);
3130 gv.setInitialValueAttr(initialValue);
3131
3132 if (emitter)
3133 emitter->finalize(gv);
3134 // Don't assign dllimport or dllexport to local linkage globals
3135 if (!gv.hasLocalLinkage()) {
3138 }
3139
3140 gv.setAlignment(align.getAsAlign().value());
3141 if (supportsCOMDAT() && gv.isWeakForLinker())
3142 errorNYI(mte->getSourceRange(),
3143 "Global temporary with comdat/weak linkage");
3144 if (varDecl->getTLSKind())
3145 errorNYI(mte->getSourceRange(),
3146 "Global temporary with thread local storage");
3147 mlir::Operation *cv = gv;
3148
3150
3151 // Update the map with the new temporary. If we created a placeholder above,
3152 // replace it with the new global now.
3153 mlir::Operation *&entry = materializedGlobalTemporaryMap[mte];
3154 if (entry) {
3155 entry->replaceAllUsesWith(cv);
3156 entry->erase();
3157 }
3158 entry = cv;
3159
3160 return cv;
3161}
Defines the clang::ASTContext interface.
This file provides some common utility functions for processing Lambda related AST Constructs.
static bool shouldAssumeDSOLocal(const CIRGenModule &cgm, cir::CIRGlobalValueInterface gv)
static cir::AssignKind getAssignKindFromDecl(const CXXMethodDecl *method)
static FunctionDecl * createOpenACCBindTempFunction(ASTContext &ctx, const IdentifierInfo *bindName, const FunctionDecl *protoFunc)
static bool shouldBeInCOMDAT(CIRGenModule &cgm, const Decl &d)
static void setWindowsItaniumDLLImport(CIRGenModule &cgm, bool isLocal, cir::FuncOp funcOp, StringRef name)
static std::string getMangledNameImpl(CIRGenModule &cgm, GlobalDecl gd, const NamedDecl *nd)
static cir::GlobalOp generateStringLiteral(mlir::Location loc, mlir::TypedAttr c, cir::GlobalLinkageKind lt, CIRGenModule &cgm, StringRef globalName, CharUnits alignment)
static bool hasImplicitAttr(const ValueDecl *decl)
static CIRGenCXXABI * createCXXABI(CIRGenModule &cgm)
static bool isVarDeclStrongDefinition(const ASTContext &astContext, CIRGenModule &cgm, const VarDecl *vd, bool noCommon)
static void setLinkageForGV(cir::GlobalOp &gv, const NamedDecl *nd)
static cir::CtorKind getCtorKindFromDecl(const CXXConstructorDecl *ctor)
This file defines OpenACC nodes for declarative directives.
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
Defines the SourceManager interface.
__device__ __2f16 float __ockl_bool s
__device__ __2f16 float c
cir::PointerType getPointerTo(mlir::Type ty)
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Definition APValue.h:122
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:226
TranslationUnitDecl * getTranslationUnitDecl() const
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
@ WeakUnknown
Weak for now, might become strong later in this TU.
bool DeclMustBeEmitted(const Decl *D)
Determines if the decl can be CodeGen'ed or deserialized from PCH lazily, only when used; this is onl...
void Deallocate(void *Ptr) const
Definition ASTContext.h:877
GVALinkage GetGVALinkageForFunction(const FunctionDecl *FD) const
bool isAlignmentRequired(const Type *T) const
Determine if the alignment the type has was required using an alignment attribute.
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
GVALinkage GetGVALinkageForVariable(const VarDecl *VD) const
unsigned getTypeAlignIfKnown(QualType T, bool NeedsPreferredAlignment=false) const
Return the alignment of a type, in bits, or 0 if the type is incomplete and we cannot determine the a...
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
const TargetInfo & getTargetInfo() const
Definition ASTContext.h:916
TargetCXXABI::Kind getCXXABIKind() const
Return the C++ ABI kind that should be used.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
virtual mlir::Operation * getKernelHandle(cir::FuncOp fn, GlobalDecl gd)=0
Implements C++ ABI-specific code generation functions.
virtual mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc, QualType ty)=0
virtual void emitCXXConstructors(const clang::CXXConstructorDecl *d)=0
Emit constructor variants required by this ABI.
virtual void emitCXXDestructors(const clang::CXXDestructorDecl *d)=0
Emit dtor variants required by this ABI.
clang::MangleContext & getMangleContext()
Gets the mangle context.
virtual cir::GlobalLinkageKind getCXXDestructorLinkage(GVALinkage linkage, const CXXDestructorDecl *dtor, CXXDtorType dt) const
llvm::ArrayRef< CanQualType > arguments() const
cir::FuncOp generateCode(clang::GlobalDecl gd, cir::FuncOp fn, cir::FuncType funcType)
void emitVariablyModifiedType(QualType ty)
mlir::Operation * curFn
The current function or global initializer that is generated code for.
This class organizes the cross-function state that is used while generating CIR code.
void updateResolvedBlockAddress(cir::BlockAddressOp op, cir::LabelOp newLabel)
void replaceUsesOfNonProtoTypeWithRealFunction(mlir::Operation *old, cir::FuncOp newFn)
This function is called when we implement a function with no prototype, e.g.
llvm::StringRef getMangledName(clang::GlobalDecl gd)
CharUnits computeNonVirtualBaseClassOffset(const CXXRecordDecl *derivedClass, llvm::iterator_range< CastExpr::path_const_iterator > path)
void setGlobalVisibility(mlir::Operation *op, const NamedDecl *d) const
Set the visibility for the given global.
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
void emitDeferred()
Emit any needed decls for which code generation was deferred.
clang::ASTContext & getASTContext() const
cir::FuncOp getAddrOfCXXStructor(clang::GlobalDecl gd, const CIRGenFunctionInfo *fnInfo=nullptr, cir::FuncType fnType=nullptr, bool dontDefer=false, ForDefinition_t isForDefinition=NotForDefinition)
CIRGenCUDARuntime & getCUDARuntime()
llvm::DenseMap< cir::BlockAddrInfoAttr, cir::LabelOp > blockAddressInfoToLabel
Map BlockAddrInfoAttr (function name, label name) to the corresponding CIR LabelOp.
void emitTopLevelDecl(clang::Decl *decl)
void emitOMPDeclareMapper(const OMPDeclareMapperDecl *d)
void addReplacement(llvm::StringRef name, mlir::Operation *op)
mlir::Type convertType(clang::QualType type)
bool shouldEmitRTTI(bool forEH=false)
cir::GlobalOp getGlobalForStringLiteral(const StringLiteral *s, llvm::StringRef name=".str")
Return a global symbol reference to a constant array for the given string literal.
void emitOMPCapturedExpr(const OMPCapturedExprDecl *d)
void mapUnresolvedBlockAddress(cir::BlockAddressOp op)
bool mustBeEmitted(const clang::ValueDecl *d)
Determine whether the definition must be emitted; if this returns false, the definition can be emitte...
void emitGlobalOpenACCDeclareDecl(const clang::OpenACCDeclareDecl *cd)
mlir::IntegerAttr getSize(CharUnits size)
CIRGenBuilderTy & getBuilder()
void setDSOLocal(mlir::Operation *op) const
std::string getUniqueGlobalName(const std::string &baseName)
std::pair< cir::FuncType, cir::FuncOp > getAddrAndTypeOfCXXStructor(clang::GlobalDecl gd, const CIRGenFunctionInfo *fnInfo=nullptr, cir::FuncType fnType=nullptr, bool dontDefer=false, ForDefinition_t isForDefinition=NotForDefinition)
void setGVProperties(mlir::Operation *op, const NamedDecl *d) const
Set visibility, dllimport/dllexport and dso_local.
cir::GlobalOp getOrCreateCIRGlobal(llvm::StringRef mangledName, mlir::Type ty, LangAS langAS, const VarDecl *d, ForDefinition_t isForDefinition)
If the specified mangled name is not in the module, create and return an mlir::GlobalOp value.
cir::FuncOp createCIRBuiltinFunction(mlir::Location loc, llvm::StringRef name, cir::FuncType ty, const clang::FunctionDecl *fd)
Create a CIR function with builtin attribute set.
void emitGlobalOpenACCRoutineDecl(const clang::OpenACCRoutineDecl *cd)
clang::CharUnits getClassPointerAlignment(const clang::CXXRecordDecl *rd)
Return the best known alignment for an unknown pointer to a particular class.
void handleCXXStaticMemberVarInstantiation(VarDecl *vd)
Tell the consumer that this variable has been instantiated.
void emitOMPRequiresDecl(const OMPRequiresDecl *d)
void emitGlobalDefinition(clang::GlobalDecl gd, mlir::Operation *op=nullptr)
void mapResolvedBlockAddress(cir::BlockAddressOp op, cir::LabelOp)
clang::DiagnosticsEngine & getDiags() const
mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc, QualType ty, bool forEH=false)
Get the address of the RTTI descriptor for the given type.
void setFunctionAttributes(GlobalDecl gd, cir::FuncOp f, bool isIncompleteFunction, bool isThunk)
Set function attributes for a function declaration.
static mlir::SymbolTable::Visibility getMLIRVisibilityFromCIRLinkage(cir::GlobalLinkageKind GLK)
const clang::TargetInfo & getTarget() const
void setCIRFunctionAttributes(GlobalDecl gd, const CIRGenFunctionInfo &info, cir::FuncOp func, bool isThunk)
Set the CIR function attributes (Sext, zext, etc).
const llvm::Triple & getTriple() const
static mlir::SymbolTable::Visibility getMLIRVisibility(Visibility v)
void emitTentativeDefinition(const VarDecl *d)
cir::GlobalOp createOrReplaceCXXRuntimeVariable(mlir::Location loc, llvm::StringRef name, mlir::Type ty, cir::GlobalLinkageKind linkage, clang::CharUnits alignment)
Will return a global variable of the given type.
void emitOMPAllocateDecl(const OMPAllocateDecl *d)
void error(SourceLocation loc, llvm::StringRef error)
Emit a general error that something can't be done.
void emitGlobalDecl(const clang::GlobalDecl &d)
Helper for emitDeferred to apply actual codegen.
void emitGlobalVarDefinition(const clang::VarDecl *vd, bool isTentative=false)
cir::FuncOp createRuntimeFunction(cir::FuncType ty, llvm::StringRef name, mlir::NamedAttrList extraAttrs={}, bool isLocal=false, bool assumeConvergent=false)
void setTLSMode(mlir::Operation *op, const VarDecl &d)
Set TLS mode for the given operation based on the given variable declaration.
cir::FuncOp getAddrOfFunction(clang::GlobalDecl gd, mlir::Type funcType=nullptr, bool forVTable=false, bool dontDefer=false, ForDefinition_t isForDefinition=NotForDefinition)
Return the address of the given function.
void emitAliasForGlobal(llvm::StringRef mangledName, mlir::Operation *op, GlobalDecl aliasGD, cir::FuncOp aliasee, cir::GlobalLinkageKind linkage)
mlir::Value emitMemberPointerConstant(const UnaryOperator *e)
void emitGlobalOpenACCDecl(const clang::OpenACCConstructDecl *cd)
void emitExplicitCastExprType(const ExplicitCastExpr *e, CIRGenFunction *cgf=nullptr)
Emit type info if type of an expression is a variably modified type.
mlir::Operation * getAddrOfGlobalTemporary(const MaterializeTemporaryExpr *mte, const Expr *init)
Returns a pointer to a global variable representing a temporary with static or thread storage duratio...
std::map< llvm::StringRef, clang::GlobalDecl > deferredDecls
This contains all the decls which have definitions but which are deferred for emission and therefore ...
void errorUnsupported(const Stmt *s, llvm::StringRef type)
Print out an error that codegen doesn't support the specified stmt yet.
mlir::Value getAddrOfGlobalVar(const VarDecl *d, mlir::Type ty={}, ForDefinition_t isForDefinition=NotForDefinition)
Return the mlir::Value for the address of the given global variable.
static void setInitializer(cir::GlobalOp &op, mlir::Attribute value)
cir::GlobalViewAttr getAddrOfGlobalVarAttr(const VarDecl *d)
Return the mlir::GlobalViewAttr for the address of the given global.
void addGlobalCtor(cir::FuncOp ctor, std::optional< int > priority=std::nullopt)
Add a global constructor or destructor to the module.
cir::GlobalLinkageKind getFunctionLinkage(GlobalDecl gd)
void updateCompletedType(const clang::TagDecl *td)
const clang::CodeGenOptions & getCodeGenOpts() const
void emitDeferredVTables()
Emit any vtables which we deferred and still have a use for.
const clang::LangOptions & getLangOpts() const
void constructAttributeList(llvm::StringRef name, const CIRGenFunctionInfo &info, CIRGenCalleeInfo calleeInfo, mlir::NamedAttrList &attrs, llvm::MutableArrayRef< mlir::NamedAttrList > argAttrs, mlir::NamedAttrList &retAttrs, cir::CallingConv &callingConv, cir::SideEffect &sideEffect, bool attrOnCallSite, bool isThunk)
Get the CIR attributes and calling convention to use for a particular function type.
cir::FuncOp getOrCreateCIRFunction(llvm::StringRef mangledName, mlir::Type funcType, clang::GlobalDecl gd, bool forVTable, bool dontDefer=false, bool isThunk=false, ForDefinition_t isForDefinition=NotForDefinition, mlir::NamedAttrList extraAttrs={})
void emitOpenACCRoutineDecl(const clang::FunctionDecl *funcDecl, cir::FuncOp func, SourceLocation pragmaLoc, ArrayRef< const OpenACCClause * > clauses)
void emitVTablesOpportunistically()
Try to emit external vtables as available_externally if they have emitted all inlined virtual functio...
cir::TLS_Model getDefaultCIRTLSModel() const
Get TLS mode from CodeGenOptions.
void addGlobalDtor(cir::FuncOp dtor, std::optional< int > priority=std::nullopt)
Add a function to the list that will be called when the module is unloaded.
void addDeferredDeclToEmit(clang::GlobalDecl GD)
bool shouldEmitCUDAGlobalVar(const VarDecl *global) const
cir::FuncOp createCIRFunction(mlir::Location loc, llvm::StringRef name, cir::FuncType funcType, const clang::FunctionDecl *funcDecl)
const TargetCIRGenInfo & getTargetCIRGenInfo()
void emitCXXGlobalVarDeclInitFunc(const VarDecl *vd, cir::GlobalOp addr, bool performInit)
void setGVPropertiesAux(mlir::Operation *op, const NamedDecl *d) const
LangAS getLangTempAllocaAddressSpace() const
Returns the address space for temporary allocations in the language.
llvm::DenseSet< cir::BlockAddressOp > unresolvedBlockAddressToLabel
Track CIR BlockAddressOps that cannot be resolved immediately because their LabelOp has not yet been ...
mlir::Location getLoc(clang::SourceLocation cLoc)
Helpers to convert the presumed location of Clang's SourceLocation to an MLIR Location.
llvm::DenseMap< mlir::Attribute, cir::GlobalOp > constantStringMap
mlir::Operation * lastGlobalOp
void replaceGlobal(cir::GlobalOp oldGV, cir::GlobalOp newGV)
Replace all uses of the old global with the new global, updating types and references as needed.
static cir::VisibilityKind getGlobalVisibilityKindFromClangVisibility(clang::VisibilityAttr::VisibilityType visibility)
llvm::StringMap< unsigned > cgGlobalNames
void setCXXSpecialMemberAttr(cir::FuncOp funcOp, const clang::FunctionDecl *funcDecl)
Mark the function as a special member (e.g. constructor, destructor)
mlir::Operation * getGlobalValue(llvm::StringRef ref)
void emitOMPDeclareReduction(const OMPDeclareReductionDecl *d)
mlir::ModuleOp getModule() const
clang::CharUnits getNaturalTypeAlignment(clang::QualType t, LValueBaseInfo *baseInfo=nullptr, bool forPointeeType=false)
FIXME: this could likely be a common helper and not necessarily related with codegen.
cir::GlobalLinkageKind getCIRLinkageForDeclarator(const DeclaratorDecl *dd, GVALinkage linkage, bool isConstantVariable)
mlir::MLIRContext & getMLIRContext()
mlir::Operation * getAddrOfGlobal(clang::GlobalDecl gd, ForDefinition_t isForDefinition=NotForDefinition)
static cir::GlobalOp createGlobalOp(CIRGenModule &cgm, mlir::Location loc, llvm::StringRef name, mlir::Type t, bool isConstant=false, mlir::Operation *insertPoint=nullptr)
void maybeSetTrivialComdat(const clang::Decl &d, mlir::Operation *op)
CIRGenCXXABI & getCXXABI() const
cir::GlobalViewAttr getAddrOfConstantStringFromLiteral(const StringLiteral *s, llvm::StringRef name=".str")
Return a global symbol reference to a constant array for the given string literal.
llvm::MapVector< cir::BlockAddressOp, cir::LabelOp > blockAddressToLabel
Map CIR BlockAddressOps directly to their resolved LabelOps.
bool lookupRepresentativeDecl(llvm::StringRef mangledName, clang::GlobalDecl &gd) const
void emitDeclContext(const DeclContext *dc)
void emitGlobal(clang::GlobalDecl gd)
Emit code for a single global function or variable declaration.
cir::LabelOp lookupBlockAddressInfo(cir::BlockAddrInfoAttr blockInfo)
bool mayBeEmittedEagerly(const clang::ValueDecl *d)
Determine whether the definition can be emitted eagerly, or should be delayed until the end of the tr...
cir::GlobalLinkageKind getCIRLinkageVarDefinition(const VarDecl *vd, bool isConstant)
void mapBlockAddress(cir::BlockAddrInfoAttr blockInfo, cir::LabelOp label)
void setCIRFunctionAttributesForDefinition(const clang::FunctionDecl *fd, cir::FuncOp f)
Set extra attributes (inline, etc.) for a function.
std::string getOpenACCBindMangledName(const IdentifierInfo *bindName, const FunctionDecl *attachedFunction)
void emitGlobalFunctionDefinition(clang::GlobalDecl gd, mlir::Operation *op)
CIRGenVTables & getVTables()
void setFunctionLinkage(GlobalDecl gd, cir::FuncOp f)
std::vector< clang::GlobalDecl > deferredDeclsToEmit
void emitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *d)
void emitOMPGroupPrivateDecl(const OMPGroupPrivateDecl *d)
mlir::Attribute getConstantArrayFromStringLiteral(const StringLiteral *e)
Return a constant array for the given string.
cir::VisibilityAttr getGlobalVisibilityAttrFromDecl(const Decl *decl)
void setCommonAttributes(GlobalDecl gd, mlir::Operation *op)
Set attributes which are common to any form of a global definition (alias, Objective-C method,...
const CIRGenFunctionInfo & arrangeGlobalDeclaration(GlobalDecl gd)
const CIRGenFunctionInfo & arrangeCXXMethodDeclaration(const clang::CXXMethodDecl *md)
C++ methods have some special rules and also have implicit parameters.
const CIRGenFunctionInfo & arrangeCXXStructorDeclaration(clang::GlobalDecl gd)
cir::FuncType getFunctionType(const CIRGenFunctionInfo &info)
Get the CIR function type for.
mlir::Type convertTypeForMem(clang::QualType, bool forBitField=false)
Convert type T into an mlir::Type.
void emitThunks(GlobalDecl gd)
Emit the associated thunks for the given global decl.
virtual mlir::ptr::MemorySpaceAttrInterface getCIRAllocaAddressSpace() const
Get the address space for alloca.
Definition TargetInfo.h:60
virtual void setTargetAttributes(const clang::Decl *decl, mlir::Operation *global, CIRGenModule &module) const
Provides a convenient hook to handle extra target-specific attributes for the given global.
Definition TargetInfo.h:114
Represents a base class of a C++ class.
Definition DeclCXX.h:146
Represents a C++ constructor within a class.
Definition DeclCXX.h:2611
bool isMoveConstructor(unsigned &TypeQuals) const
Determine whether this constructor is a move constructor (C++11 [class.copy]p3), which can be used to...
Definition DeclCXX.cpp:3031
bool isCopyConstructor(unsigned &TypeQuals) const
Whether this constructor is a copy constructor (C++ [class.copy]p2, which can be used to copy the cla...
Definition DeclCXX.cpp:3026
bool isDefaultConstructor() const
Whether this constructor is a default constructor (C++ [class.ctor]p5), which can be used to default-...
Definition DeclCXX.cpp:3017
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2136
bool isMoveAssignmentOperator() const
Determine whether this is a move assignment operator.
Definition DeclCXX.cpp:2753
bool isCopyAssignmentOperator() const
Determine whether this is a copy-assignment operator, regardless of whether it was declared implicitl...
Definition DeclCXX.cpp:2732
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
bool isEffectivelyFinal() const
Determine whether it's impossible for a class to be derived from this class.
Definition DeclCXX.cpp:2343
bool hasDefinition() const
Definition DeclCXX.h:561
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition CharUnits.h:185
static CharUnits One()
One - Construct a CharUnits quantity of one.
Definition CharUnits.h:58
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition CharUnits.h:63
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
Definition CharUnits.h:53
CodeGenOptions - Track various options which control how the code is optimized and passed to the back...
llvm::Reloc::Model RelocationModel
The name of the relocation model to use.
Represents the canonical version of C arrays with a specified constant size.
Definition TypeBase.h:3768
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1449
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Definition DeclBase.h:2373
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
T * getAttr() const
Definition DeclBase.h:573
bool isWeakImported() const
Determine whether this is a weak-imported symbol.
Definition DeclBase.cpp:870
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
Definition DeclBase.cpp:273
static DeclContext * castToDeclContext(const Decl *)
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
Definition DeclBase.h:559
SourceLocation getLocation() const
Definition DeclBase.h:439
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
Definition DeclBase.h:918
bool hasAttr() const
Definition DeclBase.h:577
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition DeclBase.h:427
Represents a ValueDecl that came out of a declarator.
Definition Decl.h:780
A little helper class used to produce diagnostics.
Concrete class used by the front-end to report problems and issues.
Definition Diagnostic.h:232
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
Definition Diagnostic.h:913
ExplicitCastExpr - An explicit cast written in the source code.
Definition Expr.h:3931
This represents one expression.
Definition Expr.h:112
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
QualType getType() const
Definition Expr.h:144
Represents a member of a struct/union/class.
Definition Decl.h:3160
Cached information about one file (either on disk or in the virtual file system).
Definition FileEntry.h:302
StringRef tryGetRealPathName() const
Definition FileEntry.h:327
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Represents a function declaration or definition.
Definition Decl.h:2000
static FunctionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin=false, bool isInlineSpecified=false, bool hasWrittenPrototype=true, ConstexprSpecKind ConstexprKind=ConstexprSpecKind::Unspecified, const AssociatedConstraint &TrailingRequiresClause={})
Definition Decl.h:2189
bool hasPrototype() const
Whether this function has a prototype, either because one was explicitly written or because it was "i...
Definition Decl.h:2443
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
Definition Decl.cpp:3200
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4511
CallingConv getCallConv() const
Definition TypeBase.h:4866
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:57
GlobalDecl getCanonicalDecl() const
Definition GlobalDecl.h:97
KernelReferenceKind getKernelReferenceKind() const
Definition GlobalDecl.h:135
GlobalDecl getWithDecl(const Decl *D)
Definition GlobalDecl.h:172
CXXDtorType getDtorType() const
Definition GlobalDecl.h:113
const Decl * getDecl() const
Definition GlobalDecl.h:106
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
void setLinkage(Linkage L)
Definition Visibility.h:92
Linkage getLinkage() const
Definition Visibility.h:88
MangleContext - Context for tracking state which persists across multiple calls to the C++ name mangl...
Definition Mangle.h:52
bool shouldMangleDeclName(const NamedDecl *D)
Definition Mangle.cpp:121
void mangleName(GlobalDecl GD, raw_ostream &)
Definition Mangle.cpp:186
virtual void mangleReferenceTemporary(const VarDecl *D, unsigned ManglingNumber, raw_ostream &)=0
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
Definition ExprCXX.h:4921
StorageDuration getStorageDuration() const
Retrieve the storage duration for the materialized temporary.
Definition ExprCXX.h:4946
Expr * getSubExpr() const
Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.
Definition ExprCXX.h:4938
APValue * getOrCreateValue(bool MayCreate) const
Get the storage for the constant value of a materialized temporary of static storage duration.
Definition ExprCXX.h:4954
ValueDecl * getExtendingDecl()
Get the declaration which triggered the lifetime-extension of this temporary, if any.
Definition ExprCXX.h:4971
unsigned getManglingNumber() const
Definition ExprCXX.h:4982
This represents a decl that may have a name.
Definition Decl.h:274
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition Decl.h:295
LinkageInfo getLinkageAndVisibility() const
Determines the linkage and visibility of this entity.
Definition Decl.cpp:1226
Represents a parameter to a function.
Definition Decl.h:1790
void setScopeInfo(unsigned scopeDepth, unsigned parameterIndex)
Definition Decl.h:1823
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
Definition Decl.cpp:2958
Represents an unpacked "presumed" location which can be presented to the user.
unsigned getColumn() const
Return the presumed column number of this location.
const char * getFilename() const
Return the presumed filename of this location.
unsigned getLine() const
Return the presumed line number of this location.
A (possibly-)qualified type.
Definition TypeBase.h:937
LangAS getAddressSpace() const
Return the address space of this type.
Definition TypeBase.h:8514
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8428
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition TypeBase.h:8461
bool isConstantStorage(const ASTContext &Ctx, bool ExcludeCtor, bool ExcludeDtor)
Definition TypeBase.h:1036
bool hasUnaligned() const
Definition TypeBase.h:511
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
This class handles loading and caching of source files into memory.
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
Stmt - This represents one statement.
Definition Stmt.h:86
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
StringLiteral - This represents a string literal expression, e.g.
Definition Expr.h:1802
unsigned getLength() const
Definition Expr.h:1912
uint32_t getCodeUnit(size_t i) const
Definition Expr.h:1885
StringRef getString() const
Definition Expr.h:1870
unsigned getCharByteWidth() const
Definition Expr.h:1913
Represents the declaration of a struct/union/class/enum.
Definition Decl.h:3717
bool isMicrosoft() const
Is this ABI an MSVC-compatible ABI?
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition Type.h:41
bool isArrayType() const
Definition TypeBase.h:8724
bool isPointerType() const
Definition TypeBase.h:8625
bool isReferenceType() const
Definition TypeBase.h:8649
bool isCUDADeviceBuiltinSurfaceType() const
Check if the type is the CUDA device builtin surface type.
Definition Type.cpp:5410
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition TypeBase.h:2808
bool isCUDADeviceBuiltinTextureType() const
Check if the type is the CUDA device builtin texture type.
Definition Type.cpp:5419
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
Definition Type.cpp:2479
bool isObjCObjectPointerType() const
Definition TypeBase.h:8804
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9218
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition Expr.h:2247
Expr * getSubExpr() const
Definition Expr.h:2288
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:712
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:926
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
Definition Decl.h:1569
TLSKind getTLSKind() const
Definition Decl.cpp:2180
bool hasInit() const
Definition Decl.cpp:2410
DefinitionKind isThisDeclarationADefinition(ASTContext &) const
Check whether this declaration is a definition.
Definition Decl.cpp:2272
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:2202
bool hasFlexibleArrayInit(const ASTContext &Ctx) const
Whether this variable has a flexible array member initialized with one or more elements.
Definition Decl.cpp:2874
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition Decl.h:1226
bool hasConstantInitialization() const
Determine whether this variable has constant initialization.
Definition Decl.cpp:2660
VarDecl * getDefinition(ASTContext &)
Get the real (not just tentative) definition for this declaration.
Definition Decl.cpp:2378
QualType::DestructionKind needsDestruction(const ASTContext &Ctx) const
Would the destruction of this variable have any effect, and if so, what kind?
Definition Decl.cpp:2863
const Expr * getInit() const
Definition Decl.h:1368
bool hasExternalStorage() const
Returns true if a variable has extern or private_extern storage.
Definition Decl.h:1217
@ TLS_Dynamic
TLS with a dynamic initializer.
Definition Decl.h:952
@ TLS_None
Not a TLS variable.
Definition Decl.h:946
@ DeclarationOnly
This declaration is only a declaration.
Definition Decl.h:1295
@ Definition
This declaration is definitely a definition.
Definition Decl.h:1301
DefinitionKind hasDefinition(ASTContext &) const
Check whether this variable is defined in this translation unit.
Definition Decl.cpp:2387
TemplateSpecializationKind getTemplateSpecializationKind() const
If this variable is an instantiation of a variable template or a static data member of a class templa...
Definition Decl.cpp:2791
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Definition Decl.h:1358
static bool isWeakForLinker(GlobalLinkageKind linkage)
Whether the definition of this global may be replaced at link time.
@ AttributedType
The l-value was considered opaque, so the alignment was determined from a type, but that type was an ...
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
std::unique_ptr< TargetCIRGenInfo > createAMDGPUTargetCIRGenInfo(CIRGenTypes &cgt)
std::unique_ptr< TargetCIRGenInfo > createNVPTXTargetCIRGenInfo(CIRGenTypes &cgt)
CIRGenCXXABI * CreateCIRGenItaniumCXXABI(CIRGenModule &cgm)
Creates and Itanium-family ABI.
std::unique_ptr< TargetCIRGenInfo > createX8664TargetCIRGenInfo(CIRGenTypes &cgt)
CIRGenCUDARuntime * createNVCUDARuntime(CIRGenModule &cgm)
const internal::VariadicDynCastAllOfMatcher< Decl, VarDecl > varDecl
Matches variable declarations.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const internal::VariadicDynCastAllOfMatcher< Decl, FieldDecl > fieldDecl
Matches field declarations.
const internal::VariadicDynCastAllOfMatcher< Decl, FunctionDecl > functionDecl
Matches function declarations.
const internal::VariadicAllOfMatcher< Decl > decl
Matches declarations.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
@ CPlusPlus
GVALinkage
A more specific kind of linkage than enum Linkage.
Definition Linkage.h:72
@ GVA_StrongODR
Definition Linkage.h:77
@ GVA_StrongExternal
Definition Linkage.h:76
@ GVA_AvailableExternally
Definition Linkage.h:74
@ GVA_DiscardableODR
Definition Linkage.h:75
@ GVA_Internal
Definition Linkage.h:73
@ SC_None
Definition Specifiers.h:250
@ SD_Thread
Thread storage duration.
Definition Specifiers.h:342
@ SD_Static
Static storage duration.
Definition Specifiers.h:343
bool isLambdaCallOperator(const CXXMethodDecl *MD)
Definition ASTLambda.h:28
@ Dtor_Complete
Complete object dtor.
Definition ABI.h:36
LangAS
Defines the address space values used by the address space qualifier of QualType.
TemplateSpecializationKind
Describes the kind of template specialization that a particular template specialization declaration r...
Definition Specifiers.h:188
@ TSK_ExplicitInstantiationDefinition
This template specialization was instantiated from a template due to an explicit instantiation defini...
Definition Specifiers.h:206
@ TSK_ImplicitInstantiation
This template specialization was implicitly instantiated from a template.
Definition Specifiers.h:194
@ CC_X86RegCall
Definition Specifiers.h:287
U cast(CodeGen::Address addr)
Definition Address.h:327
bool isExternallyVisible(Linkage L)
Definition Linkage.h:90
static bool globalCtorLexOrder()
static bool opFuncArmNewAttr()
static bool getRuntimeFunctionDecl()
static bool weakRefReference()
static bool opFuncOptNoneAttr()
static bool opGlobalSection()
static bool addressSpace()
static bool opFuncMinSizeAttr()
static bool opGlobalUnnamedAddr()
static bool opGlobalThreadLocal()
static bool sourceLanguageCases()
static bool opFuncAstDeclAttr()
static bool opFuncNoDuplicateAttr()
static bool opGlobalUsedOrCompilerUsed()
static bool stackProtector()
static bool moduleNameHash()
static bool opGlobalVisibility()
static bool setDLLStorageClass()
static bool opFuncUnwindTablesAttr()
static bool opFuncParameterAttributes()
static bool targetCIRGenInfoArch()
static bool opFuncExtraAttrs()
static bool opFuncNakedAttr()
static bool opFuncSection()
static bool attributeNoBuiltin()
static bool opGlobalDLLImportExport()
static bool opGlobalPartition()
static bool opGlobalWeakRef()
static bool setTargetAttributes()
static bool deferredCXXGlobalInit()
static bool opFuncOperandBundles()
static bool opFuncCallingConv()
static bool globalCtorAssociatedData()
static bool defaultVisibility()
static bool opFuncColdHotAttr()
static bool opFuncExceptions()
static bool opFuncArmStreamingAttr()
static bool cudaSupport()
static bool opFuncMaybeHandleStaticInExternC()
static bool generateDebugInfo()
static bool targetCIRGenInfoOS()
static bool opFuncCPUAndFeaturesAttributes()
static bool maybeHandleStaticInExternC()
static bool setLLVMFunctionFEnvAttributes()
mlir::Type uCharTy
ClangIR char.
cir::PointerType allocaInt8PtrTy
void* in alloca address space
mlir::ptr::MemorySpaceAttrInterface cirAllocaAddressSpace
cir::PointerType voidPtrTy
void* in address space 0
EvalResult is a struct with detailed info about an evaluated expression.
Definition Expr.h:648
APValue Val
Val - This is the value the expression can be folded to.
Definition Expr.h:650
bool hasSideEffects() const
Return true if the evaluated expression has side effects.
Definition Expr.h:642
LangStandard - Information about the properties of a particular language standard.