clang 24.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
19#include "mlir/Dialect/OpenMP/Utils/Utils.h"
20#include "mlir/IR/SymbolTable.h"
22#include "clang/AST/ASTLambda.h"
23#include "clang/AST/Attrs.inc"
24#include "clang/AST/DeclBase.h"
37#include "llvm/ADT/STLExtras.h"
38#include "llvm/ADT/StringExtras.h"
39#include "llvm/ADT/StringRef.h"
40#include "llvm/ADT/StringSwitch.h"
41#include "llvm/Support/raw_ostream.h"
42
43#include "CIRGenFunctionInfo.h"
44#include "TargetInfo.h"
45#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
46#include "mlir/IR/Attributes.h"
47#include "mlir/IR/BuiltinOps.h"
48#include "mlir/IR/Location.h"
49#include "mlir/IR/MLIRContext.h"
50#include "mlir/IR/Operation.h"
51#include "mlir/IR/Verifier.h"
52
53#include <algorithm>
54
55using namespace clang;
56using namespace clang::CIRGen;
57
59 switch (cgm.getASTContext().getCXXABIKind()) {
60 case TargetCXXABI::GenericItanium:
61 case TargetCXXABI::GenericAArch64:
62 case TargetCXXABI::AppleARM64:
63 case TargetCXXABI::GenericARM:
64 return CreateCIRGenItaniumCXXABI(cgm);
65
66 case TargetCXXABI::Fuchsia:
67 case TargetCXXABI::iOS:
68 case TargetCXXABI::WatchOS:
69 case TargetCXXABI::GenericMIPS:
70 case TargetCXXABI::WebAssembly:
71 case TargetCXXABI::XL:
72 case TargetCXXABI::Microsoft:
73 cgm.errorNYI("createCXXABI: C++ ABI kind");
74 return nullptr;
75 }
76
77 llvm_unreachable("invalid C++ ABI kind");
78}
79
80CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,
81 clang::ASTContext &astContext,
82 const clang::CodeGenOptions &cgo,
83 DiagnosticsEngine &diags)
84 : builder(mlirContext, *this), astContext(astContext),
85 langOpts(astContext.getLangOpts()), codeGenOpts(cgo),
86 theModule{mlir::ModuleOp::create(mlir::UnknownLoc::get(&mlirContext))},
87 diags(diags), target(astContext.getTargetInfo()),
88 abi(createCXXABI(*this)), genTypes(*this), vtables(*this) {
89
90 // Initialize cached types
91 voidTy = cir::VoidType::get(&getMLIRContext());
92 voidPtrTy = cir::PointerType::get(voidTy);
93 sInt8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/true);
94 sInt16Ty = cir::IntType::get(&getMLIRContext(), 16, /*isSigned=*/true);
95 sInt32Ty = cir::IntType::get(&getMLIRContext(), 32, /*isSigned=*/true);
96 sInt64Ty = cir::IntType::get(&getMLIRContext(), 64, /*isSigned=*/true);
97 sInt128Ty = cir::IntType::get(&getMLIRContext(), 128, /*isSigned=*/true);
98 uInt8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/false);
99 uInt8PtrTy = cir::PointerType::get(uInt8Ty);
101 uInt16Ty = cir::IntType::get(&getMLIRContext(), 16, /*isSigned=*/false);
102 uInt32Ty = cir::IntType::get(&getMLIRContext(), 32, /*isSigned=*/false);
103 uInt64Ty = cir::IntType::get(&getMLIRContext(), 64, /*isSigned=*/false);
104 uInt128Ty = cir::IntType::get(&getMLIRContext(), 128, /*isSigned=*/false);
105 fP16Ty = cir::FP16Type::get(&getMLIRContext());
106 bFloat16Ty = cir::BF16Type::get(&getMLIRContext());
107 floatTy = cir::SingleType::get(&getMLIRContext());
108 doubleTy = cir::DoubleType::get(&getMLIRContext());
109 fP80Ty = cir::FP80Type::get(&getMLIRContext());
110 fP128Ty = cir::FP128Type::get(&getMLIRContext());
111
112 allocaInt8PtrTy = cir::PointerType::get(uInt8Ty, cirAllocaAddressSpace);
113
115 astContext
116 .toCharUnitsFromBits(
117 astContext.getTargetInfo().getPointerAlign(LangAS::Default))
118 .getQuantity();
119
120 const unsigned charSize = astContext.getTargetInfo().getCharWidth();
121 uCharTy = cir::IntType::get(&getMLIRContext(), charSize, /*isSigned=*/false);
122
123 // TODO(CIR): Should be updated once TypeSizeInfoAttr is upstreamed
124 const unsigned sizeTypeSize =
125 astContext.getTypeSize(astContext.getSignedSizeType());
126 SizeSizeInBytes = astContext.toCharUnitsFromBits(sizeTypeSize).getQuantity();
127 // In CIRGenTypeCache, UIntPtrTy and SizeType are fields of the same union
128 uIntPtrTy =
129 cir::IntType::get(&getMLIRContext(), sizeTypeSize, /*isSigned=*/false);
130 ptrDiffTy =
131 cir::IntType::get(&getMLIRContext(), sizeTypeSize, /*isSigned=*/true);
132
133 std::optional<cir::SourceLanguage> sourceLanguage = getCIRSourceLanguage();
134 if (sourceLanguage)
135 theModule->setAttr(
136 cir::CIRDialect::getSourceLanguageAttrName(),
137 cir::SourceLanguageAttr::get(&mlirContext, *sourceLanguage));
138 theModule->setAttr(cir::CIRDialect::getTripleAttrName(),
139 builder.getStringAttr(getTriple().str()));
140
141 if (cgo.OptimizationLevel > 0 || cgo.OptimizeSize > 0)
142 theModule->setAttr(cir::CIRDialect::getOptInfoAttrName(),
143 cir::OptInfoAttr::get(&mlirContext,
144 cgo.OptimizationLevel,
145 cgo.OptimizeSize));
146
147 theModule->setAttr(
148 cir::CIRDialect::getDefaultTlsModelAttrName(),
149 cir::TLSModelAttr::get(&mlirContext, getDefaultCIRTLSModel()));
150
151 if (langOpts.OpenMP) {
152 mlir::omp::OffloadModuleOpts ompOpts(
153 langOpts.OpenMPTargetDebug, langOpts.OpenMPTeamSubscription,
154 langOpts.OpenMPThreadSubscription, langOpts.OpenMPNoThreadState,
155 langOpts.OpenMPNoNestedParallelism, langOpts.OpenMPIsTargetDevice,
156 getTriple().isGPU(), langOpts.OpenMPForceUSM, langOpts.OpenMP,
157 langOpts.OMPHostIRFile, langOpts.OMPTargetTriples, langOpts.NoGPULib);
158 mlir::omp::setOffloadModuleInterfaceAttributes(theModule, ompOpts);
159 mlir::omp::setOpenMPVersionAttribute(theModule, langOpts.OpenMP);
160 }
161
162 if (langOpts.CUDA)
163 createCUDARuntime();
164 if (langOpts.OpenMP)
165 createOpenMPRuntime();
166
167 // Set the module name to be the name of the main file. TranslationUnitDecl
168 // often contains invalid source locations and isn't a reliable source for the
169 // module location.
170 FileID mainFileId = astContext.getSourceManager().getMainFileID();
171 const FileEntry &mainFile =
172 *astContext.getSourceManager().getFileEntryForID(mainFileId);
173 StringRef path = mainFile.tryGetRealPathName();
174 if (!path.empty()) {
175 theModule.setSymName(path);
176 theModule->setLoc(mlir::FileLineColLoc::get(&mlirContext, path,
177 /*line=*/0,
178 /*column=*/0));
179 }
180
181 // Set CUDA GPU binary handle.
182 if (langOpts.CUDA) {
183 llvm::StringRef cudaBinaryName = codeGenOpts.OffloadBinaryToEmbedFile;
184 if (!cudaBinaryName.empty()) {
185 theModule->setAttr(cir::CIRDialect::getCUDABinaryHandleAttrName(),
186 cir::CUDABinaryHandleAttr::get(
187 &mlirContext, mlir::StringAttr::get(
188 &mlirContext, cudaBinaryName)));
189 }
190 }
191}
192
194
195void CIRGenModule::createCUDARuntime() {
196 cudaRuntime.reset(createNVCUDARuntime(*this));
197}
198
199void CIRGenModule::createOpenMPRuntime() {
200 openMPRuntime = std::make_unique<CIRGenOpenMPRuntime>(*this);
201}
202
203/// FIXME: this could likely be a common helper and not necessarily related
204/// with codegen.
205/// Return the best known alignment for an unknown pointer to a
206/// particular class.
208 if (!rd->hasDefinition())
209 return CharUnits::One(); // Hopefully won't be used anywhere.
210
211 auto &layout = astContext.getASTRecordLayout(rd);
212
213 // If the class is final, then we know that the pointer points to an
214 // object of that type and can use the full alignment.
215 if (rd->isEffectivelyFinal())
216 return layout.getAlignment();
217
218 // Otherwise, we have to assume it could be a subclass.
219 return layout.getNonVirtualAlignment();
220}
221
223 LValueBaseInfo *baseInfo,
224 bool forPointeeType) {
226
227 // FIXME: This duplicates logic in ASTContext::getTypeAlignIfKnown, but
228 // that doesn't return the information we need to compute baseInfo.
229
230 // Honor alignment typedef attributes even on incomplete types.
231 // We also honor them straight for C++ class types, even as pointees;
232 // there's an expressivity gap here.
233 if (const auto *tt = t->getAs<TypedefType>()) {
234 if (unsigned align = tt->getDecl()->getMaxAlignment()) {
235 if (baseInfo)
237 return astContext.toCharUnitsFromBits(align);
238 }
239 }
240
241 bool alignForArray = t->isArrayType();
242
243 // Analyze the base element type, so we don't get confused by incomplete
244 // array types.
245 t = astContext.getBaseElementType(t);
246
247 if (t->isIncompleteType()) {
248 // We could try to replicate the logic from
249 // ASTContext::getTypeAlignIfKnown, but nothing uses the alignment if the
250 // type is incomplete, so it's impossible to test. We could try to reuse
251 // getTypeAlignIfKnown, but that doesn't return the information we need
252 // to set baseInfo. So just ignore the possibility that the alignment is
253 // greater than one.
254 if (baseInfo)
256 return CharUnits::One();
257 }
258
259 if (baseInfo)
261
262 CharUnits alignment;
263 const CXXRecordDecl *rd = nullptr;
264 if (t.getQualifiers().hasUnaligned()) {
265 alignment = CharUnits::One();
266 } else if (forPointeeType && !alignForArray &&
267 (rd = t->getAsCXXRecordDecl())) {
268 alignment = getClassPointerAlignment(rd);
269 } else {
270 alignment = astContext.getTypeAlignInChars(t);
271 }
272
273 // Cap to the global maximum type alignment unless the alignment
274 // was somehow explicit on the type.
275 if (unsigned maxAlign = astContext.getLangOpts().MaxTypeAlign) {
276 if (alignment.getQuantity() > maxAlign &&
277 !astContext.isAlignmentRequired(t))
278 alignment = CharUnits::fromQuantity(maxAlign);
279 }
280 return alignment;
281}
282
285 LValueBaseInfo *baseInfo) {
286 return getNaturalTypeAlignment(t->getPointeeType(), baseInfo,
287 /*forPointeeType=*/true);
288}
289
291 if (theTargetCIRGenInfo)
292 return *theTargetCIRGenInfo;
293
294 const llvm::Triple &triple = getTarget().getTriple();
295 switch (triple.getArch()) {
296 default:
298
299 // Currently we just fall through to x86_64.
300 [[fallthrough]];
301
302 case llvm::Triple::x86_64: {
303 switch (triple.getOS()) {
304 default:
306
307 // Currently we just fall through to x86_64.
308 [[fallthrough]];
309
310 case llvm::Triple::Linux:
311 theTargetCIRGenInfo = createX8664TargetCIRGenInfo(genTypes);
312 return *theTargetCIRGenInfo;
313 }
314 }
315 case llvm::Triple::aarch64:
316 case llvm::Triple::aarch64_32:
317 case llvm::Triple::aarch64_be: {
318 theTargetCIRGenInfo = createAArch64TargetCIRGenInfo(genTypes);
319 return *theTargetCIRGenInfo;
320 }
321 case llvm::Triple::nvptx:
322 case llvm::Triple::nvptx64:
323 theTargetCIRGenInfo = createNVPTXTargetCIRGenInfo(genTypes);
324 return *theTargetCIRGenInfo;
325 case llvm::Triple::amdgpu: {
326 theTargetCIRGenInfo = createAMDGPUTargetCIRGenInfo(genTypes);
327 return *theTargetCIRGenInfo;
328 }
329 case llvm::Triple::spirv:
330 case llvm::Triple::spirv32:
331 case llvm::Triple::spirv64:
332 theTargetCIRGenInfo = createSPIRVTargetCIRGenInfo(genTypes);
333 return *theTargetCIRGenInfo;
334 }
335}
336
338 assert(cLoc.isValid() && "expected valid source location");
339 const SourceManager &sm = astContext.getSourceManager();
340 PresumedLoc pLoc = sm.getPresumedLoc(cLoc);
341 StringRef filename = pLoc.getFilename();
342 return mlir::FileLineColLoc::get(builder.getStringAttr(filename),
343 pLoc.getLine(), pLoc.getColumn());
344}
345
346mlir::Location CIRGenModule::getLoc(SourceRange cRange) {
347 assert(cRange.isValid() && "expected a valid source range");
348 mlir::Location begin = getLoc(cRange.getBegin());
349 mlir::Location end = getLoc(cRange.getEnd());
350 mlir::Attribute metadata;
351 return mlir::FusedLoc::get({begin, end}, metadata, builder.getContext());
352}
353
354mlir::Operation *
356 const Decl *d = gd.getDecl();
357
359 return getAddrOfCXXStructor(gd, /*FnInfo=*/nullptr, /*FnType=*/nullptr,
360 /*DontDefer=*/false, isForDefinition);
361
362 if (isa<CXXMethodDecl>(d)) {
363 const CIRGenFunctionInfo &fi =
365 cir::FuncType ty = getTypes().getFunctionType(fi);
366 return getAddrOfFunction(gd, ty, /*ForVTable=*/false, /*DontDefer=*/false,
367 isForDefinition);
368 }
369
370 if (isa<FunctionDecl>(d)) {
372 cir::FuncType ty = getTypes().getFunctionType(fi);
373 return getAddrOfFunction(gd, ty, /*ForVTable=*/false, /*DontDefer=*/false,
374 isForDefinition);
375 }
376
377 return getAddrOfGlobalVar(cast<VarDecl>(d), /*ty=*/nullptr, isForDefinition)
378 .getDefiningOp();
379}
380
382 // We call getAddrOfGlobal with isForDefinition set to ForDefinition in
383 // order to get a Value with exactly the type we need, not something that
384 // might have been created for another decl with the same mangled name but
385 // different type.
386 mlir::Operation *op = getAddrOfGlobal(d, ForDefinition);
387
388 // In case of different address spaces, we may still get a cast, even with
389 // IsForDefinition equal to ForDefinition. Query mangled names table to get
390 // GlobalValue.
391 if (!op)
393
394 assert(op && "expected a valid global op");
395
396 // Check to see if we've already emitted this. This is necessary for a
397 // couple of reasons: first, decls can end up in deferred-decls queue
398 // multiple times, and second, decls can end up with definitions in unusual
399 // ways (e.g. by an extern inline function acquiring a strong function
400 // redefinition). Just ignore those cases.
401 // TODO: Not sure what to map this to for MLIR
402 mlir::Operation *globalValueOp = op;
403 if (auto gv = dyn_cast<cir::GetGlobalOp>(op)) {
404 globalValueOp = getGlobalValue(gv.getName());
405 assert(globalValueOp && "expected a valid global op");
406 }
407
408 if (auto cirGlobalValue =
409 dyn_cast<cir::CIRGlobalValueInterface>(globalValueOp))
410 if (!cirGlobalValue.isDeclaration())
411 return;
412
413 // If this is OpenMP, check if it is legal to emit this global normally.
415
416 // Otherwise, emit the definition and move on to the next one.
418}
419
421 // Emit code for any potentially referenced deferred decls. Since a previously
422 // unused static decl may become used during the generation of code for a
423 // static function, iterate until no changes are made.
424
426
428 // Emitting a vtable doesn't directly cause more vtables to
429 // become deferred, although it can cause functions to be
430 // emitted that then need those vtables.
431 assert(deferredVTables.empty());
432
434
435 // Stop if we're out of both deferred vtables and deferred declarations.
436 if (deferredDeclsToEmit.empty())
437 return;
438
439 // Grab the list of decls to emit. If emitGlobalDefinition schedules more
440 // work, it will not interfere with this.
441 std::vector<GlobalDecl> curDeclsToEmit;
442 curDeclsToEmit.swap(deferredDeclsToEmit);
443
444 for (const GlobalDecl &d : curDeclsToEmit) {
445 // Functions declared with the sycl_kernel_entry_point attribute are
446 // emitted normally during host compilation. During device compilation, a
447 // SYCL kernel caller offload entry point function is generated and emitted
448 // in place of each of these functions.
449 if (const auto *fd = d.getDecl()->getAsFunction()) {
450 if (langOpts.SYCLIsDevice && fd->hasAttr<SYCLKernelEntryPointAttr>() &&
451 fd->isDefined()) {
452 // Functions with an invalid sycl_kernel_entry_point attribute are
453 // ignored during device compilation.
454 if (!fd->getAttr<SYCLKernelEntryPointAttr>()->isInvalidAttr()) {
455 // Generate and emit the SYCL kernel caller function.
457 // Recurse to emit any symbols directly or indirectly referenced
458 // by the SYCL kernel caller function.
459 emitDeferred();
460 }
461 // Do not emit the sycl_kernel_entry_point attributed function.
462 continue;
463 }
464 }
465
467
468 // If we found out that we need to emit more decls, do that recursively.
469 // This has the advantage that the decls are emitted in a DFS and related
470 // ones are close together, which is convenient for testing.
471 if (!deferredVTables.empty() || !deferredDeclsToEmit.empty()) {
472 emitDeferred();
473 assert(deferredVTables.empty() && deferredDeclsToEmit.empty());
474 }
475 }
476}
477
478template <typename AttrT> static bool hasImplicitAttr(const ValueDecl *decl) {
479 if (!decl)
480 return false;
481 if (auto *attr = decl->getAttr<AttrT>())
482 return attr->isImplicit();
483 return decl->isImplicit();
484}
485
486// TODO(cir): This should be shared with OG Codegen.
488 assert(langOpts.CUDA && "Should not be called by non-CUDA languages");
489 // We need to emit host-side 'shadows' for all global
490 // device-side variables because the CUDA runtime needs their
491 // size and host-side address in order to provide access to
492 // their device-side incarnations.
493 return !langOpts.CUDAIsDevice || global->hasAttr<CUDADeviceAttr>() ||
494 global->hasAttr<CUDAConstantAttr>() ||
495 global->hasAttr<CUDASharedAttr>() ||
498}
499
501 const Decl *d) {
502 // ptxas does not allow '.' in symbol names. On the other hand, HIP prefers
503 // postfix beginning with '.' since the symbol name can be demangled.
504 if (langOpts.HIP)
505 os << (isa<VarDecl>(d) ? ".static." : ".intern.");
506 else
507 os << (isa<VarDecl>(d) ? "__static__" : "__intern__");
508
509 // If the CUID is not specified we try to generate a unique postfix.
510 if (getLangOpts().CUID.empty()) {
511 // TODO: Once we add 'PreprocessorOpts' into CIRGenModule this part can be
512 // brought in from OG.
514 "printPostfixForExternalizedDecl: CUID is not specified");
515 } else {
516 os << getASTContext().getCUIDHash();
517 }
518}
519
521 if (const auto *cd = dyn_cast<clang::OpenACCConstructDecl>(gd.getDecl())) {
523 return;
524 }
525
526 const auto *global = cast<ValueDecl>(gd.getDecl());
527
528 // Weak references don't produce any output by themselves.
529 if (global->hasAttr<WeakRefAttr>())
530 return;
531
532 // If this is an alias definition (which otherwise looks like a declaration)
533 // emit it now.
534 if (global->hasAttr<AliasAttr>()) {
535 // Classic codegen calls shouldSkipAliasEmission here to skip alias
536 // emission for OpenMP target device and CUDA configurations.
539 return;
540 }
541
542 // If this is CUDA, be selective about which declarations we emit.
543 // Non-constexpr non-lambda implicit host device functions are not emitted
544 // unless they are used on device side.
545 if (langOpts.CUDA) {
546 assert((isa<FunctionDecl>(global) || isa<VarDecl>(global)) &&
547 "Expected Variable or Function");
548 if (const auto *varDecl = dyn_cast<VarDecl>(global)) {
550 return;
551 // TODO(cir): This should be shared with OG Codegen.
552 } else if (langOpts.CUDAIsDevice) {
553 const auto *functionDecl = dyn_cast<FunctionDecl>(global);
554 if ((!global->hasAttr<CUDADeviceAttr>() ||
555 (langOpts.OffloadImplicitHostDeviceTemplates &&
558 !functionDecl->isConstexpr() &&
560 !getASTContext().CUDAImplicitHostDeviceFunUsedByDevice.count(
561 functionDecl))) &&
562 !global->hasAttr<CUDAGlobalAttr>() &&
563 !(langOpts.HIPStdPar && isa<FunctionDecl>(global) &&
564 !global->hasAttr<CUDAHostAttr>()))
565 return;
566 // Device-only functions are the only things we skip.
567 } else if (!global->hasAttr<CUDAHostAttr>() &&
568 global->hasAttr<CUDADeviceAttr>())
569 return;
570 }
571
572 if (langOpts.OpenMP) {
573 // If this is OpenMP, check if it is legal to emit this global normally.
574 if (openMPRuntime && openMPRuntime->emitTargetGlobal(gd))
575 return;
576 if (auto *drd = dyn_cast<OMPDeclareReductionDecl>(global)) {
577 if (mustBeEmitted(global))
579 return;
580 }
581 if (auto *dmd = dyn_cast<OMPDeclareMapperDecl>(global)) {
582 if (mustBeEmitted(global))
584 return;
585 }
586 }
587
588 if (const auto *fd = dyn_cast<FunctionDecl>(global)) {
589 // Update deferred annotations with the latest declaration if the function
590 // was already used or defined.
591 if (fd->hasAttr<AnnotateAttr>()) {
592 StringRef mangledName = getMangledName(gd);
593 if (getGlobalValue(mangledName))
594 deferredAnnotations[mangledName] = fd;
595 }
596 if (!fd->doesThisDeclarationHaveABody()) {
597 if (!fd->doesDeclarationForceExternallyVisibleDefinition() &&
598 (!fd->isMultiVersion() || !getTarget().getTriple().isAArch64()))
599 return;
600
602 cir::FuncType ty = getTypes().getFunctionType(fi);
603 getAddrOfFunction(gd, ty, /*ForVTable=*/false, /*DontDefer=*/false);
604 return;
605 }
606 } else {
607 const auto *vd = cast<VarDecl>(global);
608 assert(vd->isFileVarDecl() && "Cannot emit local var decl as global.");
609 if (vd->isThisDeclarationADefinition() != VarDecl::Definition &&
610 !astContext.isMSStaticDataMemberInlineDefinition(vd)) {
612 // If this declaration may have caused an inline variable definition to
613 // change linkage, make sure that it's emitted.
614 if (astContext.getInlineVariableDefinitionKind(vd) ==
617 // Otherwise, we can ignore this declaration. The variable will be emitted
618 // on its first use.
619 return;
620 }
621 }
622
623 // Defer code generation to first use when possible, e.g. if this is an inline
624 // function. If the global must always be emitted, do it eagerly if possible
625 // to benefit from cache locality. Deferring code generation is necessary to
626 // avoid adding initializers to external declarations.
627 if (mustBeEmitted(global) && mayBeEmittedEagerly(global)) {
628 // Emit the definition if it can't be deferred.
630 return;
631 }
632
633 // If we're deferring emission of a C++ variable with an initializer, remember
634 // the order in which it appeared on the file.
636
637 llvm::StringRef mangledName = getMangledName(gd);
638 if (getGlobalValue(mangledName) != nullptr) {
639 // The value has already been used and should therefore be emitted.
641 } else if (mustBeEmitted(global)) {
642 // The value must be emitted, but cannot be emitted eagerly.
643 assert(!mayBeEmittedEagerly(global));
645 } else {
646 // Otherwise, remember that we saw a deferred decl with this name. The first
647 // use of the mangled name will cause it to move into deferredDeclsToEmit.
648 deferredDecls[mangledName] = gd;
649 }
650}
651
653 mlir::Operation *op) {
654 auto const *funcDecl = cast<FunctionDecl>(gd.getDecl());
656 cir::FuncType funcType = getTypes().getFunctionType(fi);
657 cir::FuncOp funcOp = dyn_cast_if_present<cir::FuncOp>(op);
658 if (!funcOp || funcOp.getFunctionType() != funcType) {
659 funcOp = getAddrOfFunction(gd, funcType, /*ForVTable=*/false,
660 /*DontDefer=*/true, ForDefinition);
661 }
662
663 // Already emitted.
664 if (!funcOp.isDeclaration())
665 return;
666
667 setFunctionLinkage(gd, funcOp);
668 setGVProperties(funcOp, funcDecl);
670 maybeSetTrivialComdat(*funcDecl, funcOp);
672
673 CIRGenFunction cgf(*this, builder);
674 curCGF = &cgf;
675 {
676 mlir::OpBuilder::InsertionGuard guard(builder);
677 cgf.generateCode(gd, funcOp, funcType);
678 }
679 curCGF = nullptr;
680
681 setNonAliasAttributes(gd, funcOp);
683
684 auto getPriority = [this](const auto *attr) -> int {
685 Expr *e = attr->getPriority();
686 if (e)
687 return e->EvaluateKnownConstInt(this->getASTContext()).getExtValue();
688 return attr->DefaultPriority;
689 };
690
691 if (const ConstructorAttr *ca = funcDecl->getAttr<ConstructorAttr>())
692 addGlobalCtor(funcOp, getPriority(ca));
693 if (const DestructorAttr *da = funcDecl->getAttr<DestructorAttr>())
694 addGlobalDtor(funcOp, getPriority(da));
695
696 if (funcDecl->getAttr<AnnotateAttr>())
697 deferredAnnotations[getMangledName(gd)] = funcDecl;
698
699 if (getLangOpts().OpenMP && funcDecl->hasAttr<OMPDeclareTargetDeclAttr>())
701}
702
703/// Track functions to be called before main() runs.
704void CIRGenModule::addGlobalCtor(cir::FuncOp ctor,
705 std::optional<int> priority) {
708
709 // Traditional LLVM codegen directly adds the function to the list of global
710 // ctors. In CIR we just add a global_ctor attribute to the function. The
711 // global list is created in LoweringPrepare.
712 //
713 // FIXME(from traditional LLVM): Type coercion of void()* types.
714 ctor.setGlobalCtorPriority(priority);
715}
716
717/// Add a function to the list that will be called when the module is unloaded.
718void CIRGenModule::addGlobalDtor(cir::FuncOp dtor,
719 std::optional<int> priority) {
720 if (codeGenOpts.RegisterGlobalDtorsWithAtExit &&
721 (!getASTContext().getTargetInfo().getTriple().isOSAIX()))
722 errorNYI(dtor.getLoc(), "registerGlobalDtorsWithAtExit");
723
724 // FIXME(from traditional LLVM): Type coercion of void()* types.
725 dtor.setGlobalDtorPriority(priority);
726}
727
730 if (dk == VarDecl::Definition && vd->hasAttr<DLLImportAttr>())
731 return;
732
734 // If we have a definition, this might be a deferred decl. If the
735 // instantiation is explicit, make sure we emit it at the end.
738
740}
741
742mlir::Operation *CIRGenModule::getGlobalValue(StringRef name) {
743 auto it = symbolLookupCache.find(name);
744 return it != symbolLookupCache.end() ? it->second : nullptr;
745}
746
747cir::GlobalOp
748CIRGenModule::createGlobalOp(mlir::Location loc, StringRef name, mlir::Type t,
749 bool isConstant,
750 mlir::ptr::MemorySpaceAttrInterface addrSpace,
751 mlir::Operation *insertPoint) {
752 cir::GlobalOp g;
753 CIRGenBuilderTy &builder = getBuilder();
754
755 {
756 mlir::OpBuilder::InsertionGuard guard(builder);
757
758 // If an insertion point is provided, we're replacing an existing global,
759 // otherwise, create the new global immediately after the last gloabl we
760 // emitted.
761 if (insertPoint) {
762 builder.setInsertionPoint(insertPoint);
763 } else {
764 // Group global operations together at the top of the module.
765 if (lastGlobalOp)
766 builder.setInsertionPointAfter(lastGlobalOp);
767 else
768 builder.setInsertionPointToStart(getModule().getBody());
769 }
770
771 g = cir::GlobalOp::create(builder, loc, name, t, isConstant, addrSpace);
772 if (!insertPoint)
773 lastGlobalOp = g;
774
775 // Default to private until we can judge based on the initializer,
776 // since MLIR doesn't allow public declarations.
777 mlir::SymbolTable::setSymbolVisibility(
778 g, mlir::SymbolTable::Visibility::Private);
779 }
780 symbolLookupCache[g.getSymNameAttr()] = g;
781 return g;
782}
783
784void CIRGenModule::setCommonAttributes(GlobalDecl gd, mlir::Operation *gv) {
785 const Decl *d = gd.getDecl();
786 if (isa_and_nonnull<NamedDecl>(d))
787 setGVProperties(gv, dyn_cast<NamedDecl>(d));
789
790 if (auto gvi = mlir::dyn_cast<cir::CIRGlobalValueInterface>(gv)) {
791 if (d && d->hasAttr<UsedAttr>())
793
794 if (const auto *vd = dyn_cast_if_present<VarDecl>(d);
795 vd && ((codeGenOpts.KeepPersistentStorageVariables &&
796 (vd->getStorageDuration() == SD_Static ||
797 vd->getStorageDuration() == SD_Thread)) ||
798 (codeGenOpts.KeepStaticConsts &&
799 vd->getStorageDuration() == SD_Static &&
800 vd->getType().isConstQualified())))
802 }
803}
804
805/// Get the feature delta from the default feature map for the given target CPU.
806static std::vector<std::string>
807getFeatureDeltaFromDefault(const CIRGenModule &cgm, llvm::StringRef targetCPU,
808 llvm::StringMap<bool> &featureMap) {
809 llvm::StringMap<bool> defaultFeatureMap;
811 defaultFeatureMap, cgm.getASTContext().getDiagnostics(), targetCPU, {});
812
813 std::vector<std::string> delta;
814 for (const auto &[k, v] : featureMap) {
815 auto defaultIt = defaultFeatureMap.find(k);
816 if (defaultIt == defaultFeatureMap.end() || defaultIt->getValue() != v)
817 delta.push_back((v ? "+" : "-") + k.str());
818 }
819
820 return delta;
821}
822
823bool CIRGenModule::getCPUAndFeaturesAttributes(
824 GlobalDecl gd, llvm::StringMap<std::string> &attrs,
825 bool setTargetFeatures) {
826 // Add target-cpu and target-features attributes to functions. If
827 // we have a decl for the function and it has a target attribute then
828 // parse that and add it to the feature set.
829 llvm::StringRef targetCPU = getTarget().getTargetOpts().CPU;
830 llvm::StringRef tuneCPU = getTarget().getTargetOpts().TuneCPU;
831 std::vector<std::string> features;
832 // `fd` may be null when emitting attributes for globals that don't have a
833 // FunctionDecl. The AMDGPU branch below handles
834 // the null case via initFeatureMap.
835 const auto *fd = dyn_cast_or_null<FunctionDecl>(gd.getDecl());
836 fd = fd ? fd->getMostRecentDecl() : fd;
837 const auto *td = fd ? fd->getAttr<TargetAttr>() : nullptr;
838 const auto *tv = fd ? fd->getAttr<TargetVersionAttr>() : nullptr;
839 assert((!td || !tv) && "both target_version and target specified");
840 const auto *sd = fd ? fd->getAttr<CPUSpecificAttr>() : nullptr;
841 const auto *tc = fd ? fd->getAttr<TargetClonesAttr>() : nullptr;
842 bool addedAttr = false;
843 if (td || tv || sd || tc) {
844 llvm::StringMap<bool> featureMap;
845 astContext.getFunctionFeatureMap(featureMap, gd);
846
847 // Now add the target-cpu and target-features to the function.
848 // While we populated the feature map above, we still need to
849 // get and parse the target/target_clones attribute so we can
850 // get the cpu for the function.
851 llvm::StringRef featureStr = td ? td->getFeaturesStr() : llvm::StringRef();
852 if (tc && (getTriple().isOSAIX() || getTriple().isX86()))
853 featureStr = tc->getFeatureStr(gd.getMultiVersionIndex());
854 if (!featureStr.empty()) {
855 clang::ParsedTargetAttr parsedAttr =
856 getTarget().parseTargetAttr(featureStr);
857 if (!parsedAttr.CPU.empty() &&
858 getTarget().isValidCPUName(parsedAttr.CPU)) {
859 targetCPU = parsedAttr.CPU;
860 tuneCPU = ""; // Clear the tune CPU.
861 }
862 if (!parsedAttr.Tune.empty() &&
863 getTarget().isValidCPUName(parsedAttr.Tune))
864 tuneCPU = parsedAttr.Tune;
865 }
866
867 if (sd) {
868 // Apply the given CPU name as the 'tune-cpu' so that the optimizer can
869 // favor this processor.
870 tuneCPU = sd->getCPUName(gd.getMultiVersionIndex())->getName();
871 }
872
873 // For AMDGPU, only emit delta features (features that differ from the
874 // target CPU's defaults). Other targets might want to follow a similar
875 // pattern.
876 if (getTarget().getTriple().isAMDGPU()) {
877 features = getFeatureDeltaFromDefault(*this, targetCPU, featureMap);
878 } else {
879 // Produce the canonical string for this set of features.
880 features.reserve(features.size() + featureMap.size());
881 for (const auto &entry : featureMap)
882 features.push_back((entry.getValue() ? "+" : "-") +
883 entry.getKey().str());
884 }
885 } else {
886 // Just add the existing target cpu and target features to the function.
887 if (setTargetFeatures && getTarget().getTriple().isAMDGPU()) {
888 llvm::StringMap<bool> featureMap;
889 if (fd)
890 astContext.getFunctionFeatureMap(featureMap, gd);
891 else
892 getTarget().initFeatureMap(featureMap, astContext.getDiagnostics(),
893 targetCPU,
894 getTarget().getTargetOpts().Features);
895 features = getFeatureDeltaFromDefault(*this, targetCPU, featureMap);
896 } else {
897 features = getTarget().getTargetOpts().Features;
898 }
899 }
900
901 if (!targetCPU.empty()) {
902 attrs[cir::CIRDialect::getTargetCPUAttrName()] = targetCPU.str();
903 addedAttr = true;
904 }
905 if (!tuneCPU.empty()) {
906 attrs[cir::CIRDialect::getTuneCPUAttrName()] = tuneCPU.str();
907 addedAttr = true;
908 }
909 if (!features.empty() && setTargetFeatures) {
910 llvm::erase_if(features, [&](const std::string &f) {
911 assert(!f.empty() && (f[0] == '+' || f[0] == '-') &&
912 "feature string must start with '+' or '-'");
913 return getTarget().isReadOnlyFeature(f.substr(1));
914 });
915 llvm::sort(features);
916 attrs[cir::CIRDialect::getTargetFeaturesAttrName()] =
917 llvm::join(features, ",");
918 addedAttr = true;
919 }
920 // TODO(cir): add metadata for AArch64 Function Multi Versioning.
922 return addedAttr;
923}
924
925void CIRGenModule::setNonAliasAttributes(GlobalDecl gd, mlir::Operation *op) {
926 setCommonAttributes(gd, op);
927
928 const Decl *d = gd.getDecl();
929 if (d) {
930 if (auto gvi = mlir::dyn_cast<cir::CIRGlobalValueInterface>(op)) {
931 if (const auto *sa = d->getAttr<SectionAttr>())
932 gvi.setSection(builder.getStringAttr(sa->getName()));
933 if (d->hasAttr<RetainAttr>())
934 addUsedGlobal(gvi);
935
936 if (auto func = dyn_cast<cir::FuncOp>(op)) {
937 llvm::StringMap<std::string> attrs;
938 if (getCPUAndFeaturesAttributes(gd, attrs)) {
939 // TODO(cir): Classic codegen also removes fmv-features here, which
940 // CIR does not emit yet.
941 //
942 // getCPUAndFeaturesAttributes reads the most recent declaration, so
943 // its result supersedes anything an earlier one wrote. Clear first:
944 // setAttr alone would leave a name this call no longer produces.
945 for (llvm::StringRef name :
946 {cir::CIRDialect::getTargetCPUAttrName(),
947 cir::CIRDialect::getTuneCPUAttrName(),
948 cir::CIRDialect::getTargetFeaturesAttrName()})
949 func->removeAttr(name);
950 for (const auto &[key, val] : attrs)
951 func->setAttr(key, builder.getStringAttr(val));
952 }
953 }
954 }
955 }
956
959}
960
961std::optional<cir::SourceLanguage> CIRGenModule::getCIRSourceLanguage() const {
962 using ClangStd = clang::LangStandard;
963 using CIRLang = cir::SourceLanguage;
964 auto opts = getLangOpts();
965
966 if (opts.CPlusPlus)
967 return CIRLang::CXX;
968 if (opts.C99 || opts.C11 || opts.C17 || opts.C23 || opts.C2y ||
969 opts.LangStd == ClangStd::lang_c89 ||
970 opts.LangStd == ClangStd::lang_gnu89)
971 return CIRLang::C;
972
973 // TODO(cir): support remaining source languages.
975 errorNYI("CIR does not yet support the given source language");
976 return std::nullopt;
977}
978
979LangAS CIRGenModule::getGlobalVarAddressSpace(const VarDecl *d) {
980 if (langOpts.OpenCL) {
985 return as;
986 }
987
988 if (langOpts.SYCLIsDevice &&
989 (!d || d->getType().getAddressSpace() == LangAS::Default))
990 errorNYI("SYCL global address space");
991
992 if (langOpts.CUDA && langOpts.CUDAIsDevice) {
993 if (d) {
994 if (d->hasAttr<CUDAConstantAttr>())
996 if (d->hasAttr<CUDASharedAttr>())
997 return LangAS::cuda_shared;
998 if (d->hasAttr<CUDADeviceAttr>())
999 return LangAS::cuda_device;
1000 if (d->getType().isConstQualified())
1001 return LangAS::cuda_constant;
1002 }
1003 return LangAS::cuda_device;
1004 }
1005
1006 if (langOpts.OpenMP)
1007 errorNYI("OpenMP global address space");
1008
1010}
1011
1012static void setLinkageForGV(cir::GlobalOp &gv, const NamedDecl *nd) {
1013 // Set linkage and visibility in case we never see a definition.
1015 // Don't set internal linkage on declarations.
1016 // "extern_weak" is overloaded in LLVM; we probably should have
1017 // separate linkage types for this.
1018 if (isExternallyVisible(lv.getLinkage()) &&
1019 (nd->hasAttr<WeakAttr>() || nd->isWeakImported()))
1020 gv.setLinkage(cir::GlobalLinkageKind::ExternalWeakLinkage);
1021}
1022
1023static void setLinkageForFunction(CIRGenModule &cgm, cir::FuncOp &func,
1024 const NamedDecl *nd) {
1025 // Mirrors CodeGenModule::setLinkageForGV for function declarations.
1027 if (isExternallyVisible(lv.getLinkage()) &&
1028 (nd->hasAttr<WeakAttr>() || nd->isWeakImported())) {
1029 auto linkage = cir::GlobalLinkageKind::ExternalWeakLinkage;
1030 func.setLinkage(linkage);
1031 func.setLinkageAttr(
1032 cir::GlobalLinkageKindAttr::get(&cgm.getMLIRContext(), linkage));
1033 // Declarations must keep 'private' MLIR visibility; only update for defs.
1034 if (!func.isDeclaration())
1035 mlir::SymbolTable::setSymbolVisibility(
1036 func, cgm.getMLIRVisibilityFromCIRLinkage(linkage));
1037 }
1038}
1039
1040static llvm::SmallVector<int64_t> indexesOfArrayAttr(mlir::ArrayAttr indexes) {
1042 for (mlir::Attribute i : indexes) {
1043 auto ind = mlir::cast<mlir::IntegerAttr>(i);
1044 inds.push_back(ind.getValue().getSExtValue());
1045 }
1046 return inds;
1047}
1048
1049static bool isViewOnGlobal(cir::GlobalOp glob, cir::GlobalViewAttr view) {
1050 return view.getSymbol().getValue() == glob.getSymName();
1051}
1052
1053static cir::GlobalViewAttr createNewGlobalView(CIRGenModule &cgm,
1054 cir::GlobalOp newGlob,
1055 cir::GlobalViewAttr attr,
1056 mlir::Type oldTy) {
1057 // If the attribute does not require indexes or it is not a global view on
1058 // the global we're replacing, keep the original attribute.
1059 if (!attr.getIndices() || !isViewOnGlobal(newGlob, attr))
1060 return attr;
1061
1062 llvm::SmallVector<int64_t> oldInds = indexesOfArrayAttr(attr.getIndices());
1064 CIRGenBuilderTy &bld = cgm.getBuilder();
1065 const cir::CIRDataLayout &layout = cgm.getDataLayout();
1066 mlir::Type newTy = newGlob.getSymType();
1067
1068 uint64_t offset =
1069 bld.computeOffsetFromGlobalViewIndices(layout, oldTy, oldInds);
1070 bld.computeGlobalViewIndicesFromFlatOffset(offset, newTy, layout, newInds);
1071 cir::PointerType newPtrTy;
1072
1073 if (isa<cir::RecordType>(oldTy))
1074 newPtrTy = cir::PointerType::get(newTy);
1075 else if (isa<cir::ArrayType>(oldTy))
1076 newPtrTy = cast<cir::PointerType>(attr.getType());
1077
1078 if (newPtrTy)
1079 return bld.getGlobalViewAttr(newPtrTy, newGlob, newInds);
1080
1081 // This may be unreachable in practice, but keep it as errorNYI while CIR
1082 // is still under development.
1083 cgm.errorNYI("Unhandled type in createNewGlobalView");
1084 return {};
1085}
1086
1087static mlir::Attribute getNewInitValue(CIRGenModule &cgm, cir::GlobalOp newGlob,
1088 mlir::Type oldTy,
1089 mlir::Attribute oldInit) {
1090 if (auto oldView = mlir::dyn_cast<cir::GlobalViewAttr>(oldInit))
1091 return createNewGlobalView(cgm, newGlob, oldView, oldTy);
1092
1093 auto getNewInitElements =
1094 [&](mlir::ArrayAttr oldElements) -> mlir::ArrayAttr {
1096 for (mlir::Attribute elt : oldElements) {
1097 if (auto view = mlir::dyn_cast<cir::GlobalViewAttr>(elt))
1098 newElements.push_back(createNewGlobalView(cgm, newGlob, view, oldTy));
1099 else if (mlir::isa<cir::ConstArrayAttr, cir::ConstRecordAttr>(elt))
1100 newElements.push_back(getNewInitValue(cgm, newGlob, oldTy, elt));
1101 else
1102 newElements.push_back(elt);
1103 }
1104 return mlir::ArrayAttr::get(cgm.getBuilder().getContext(), newElements);
1105 };
1106
1107 if (auto oldArray = mlir::dyn_cast<cir::ConstArrayAttr>(oldInit)) {
1108 // ConstArrayAttr::verify guarantees the elements are either an ArrayAttr or
1109 // a StringAttr. A StringAttr is a string-literal initializer: raw 8-bit
1110 // character bytes with no nested global references, so there is nothing to
1111 // rewrite and it is returned unchanged. The ArrayAttr case recurses to
1112 // rewrite any nested global views.
1113 mlir::Attribute oldElts = oldArray.getElts();
1114 if (mlir::isa<mlir::StringAttr>(oldElts))
1115 return oldInit;
1116 mlir::Attribute newElements =
1117 getNewInitElements(mlir::cast<mlir::ArrayAttr>(oldElts));
1118 return cgm.getBuilder().getConstArray(
1119 newElements, mlir::cast<cir::ArrayType>(oldArray.getType()));
1120 }
1121 if (auto oldRecord = mlir::dyn_cast<cir::ConstRecordAttr>(oldInit)) {
1122 mlir::ArrayAttr newMembers = getNewInitElements(oldRecord.getMembers());
1123 auto recordTy = mlir::cast<cir::RecordType>(oldRecord.getType());
1124 return cgm.getBuilder().getConstRecordOrZeroAttr(newMembers, recordTy);
1125 }
1126
1127 // This may be unreachable in practice, but keep it as errorNYI while CIR
1128 // is still under development.
1129 cgm.errorNYI("Unhandled type in getNewInitValue");
1130 return {};
1131}
1132
1133// We want to replace a global value, but because of CIR's typed pointers,
1134// we need to update the existing uses to reflect the new type, not just replace
1135// them directly.
1136void CIRGenModule::replaceGlobal(cir::GlobalOp oldGV, cir::GlobalOp newGV) {
1137 assert(oldGV.getSymName() == newGV.getSymName() && "symbol names must match");
1138
1139 mlir::Type oldTy = oldGV.getSymType();
1140 mlir::Type newTy = newGV.getSymType();
1141
1143
1144 // If the type didn't change, why are we here?
1145 assert(oldTy != newTy && "expected type change in replaceGlobal");
1146
1147 // Visit all uses and add handling to fix up the types.
1148 std::optional<mlir::SymbolTable::UseRange> oldSymUses =
1149 oldGV.getSymbolUses(theModule);
1150 for (mlir::SymbolTable::SymbolUse use : *oldSymUses) {
1151 mlir::Operation *userOp = use.getUser();
1152 assert(
1153 (mlir::isa<cir::GetGlobalOp, cir::GlobalOp, cir::ConstantOp>(userOp)) &&
1154 "Unexpected user for global op");
1155
1156 if (auto getGlobalOp = dyn_cast<cir::GetGlobalOp>(use.getUser())) {
1157 mlir::Value useOpResultValue = getGlobalOp.getAddr();
1158 useOpResultValue.setType(cir::PointerType::get(newTy));
1159
1160 mlir::OpBuilder::InsertionGuard guard(builder);
1161 builder.setInsertionPointAfter(getGlobalOp);
1162 mlir::Type ptrTy = builder.getPointerTo(oldTy);
1163 mlir::Value cast =
1164 builder.createBitcast(getGlobalOp->getLoc(), useOpResultValue, ptrTy);
1165 useOpResultValue.replaceAllUsesExcept(cast, cast.getDefiningOp());
1166 } else if (auto glob = dyn_cast<cir::GlobalOp>(userOp)) {
1167 if (auto init = glob.getInitialValue()) {
1168 mlir::Attribute nw = getNewInitValue(*this, newGV, oldTy, init.value());
1169 glob.setInitialValueAttr(nw);
1170 }
1171 } else if (auto c = dyn_cast<cir::ConstantOp>(userOp)) {
1172 mlir::Attribute init = getNewInitValue(*this, newGV, oldTy, c.getValue());
1173 auto typedAttr = mlir::cast<mlir::TypedAttr>(init);
1174 mlir::OpBuilder::InsertionGuard guard(builder);
1175 builder.setInsertionPointAfter(c);
1176 auto newUser = cir::ConstantOp::create(builder, c.getLoc(), typedAttr);
1177 c.replaceAllUsesWith(newUser.getOperation());
1178 c.erase();
1179 }
1180 }
1181
1182 // If the old global is being tracked as the most-recently-created global,
1183 // update it so that subsequent globals are not inserted after a (now
1184 // erased) operation, which would leave them detached from the module.
1185 if (lastGlobalOp == oldGV)
1186 lastGlobalOp = newGV;
1187 if (getLangOpts().CUDA)
1188 getCUDARuntime().handleGlobalReplace(oldGV, newGV);
1189 eraseGlobalSymbol(oldGV);
1190 oldGV.erase();
1191}
1192
1193/// If the specified mangled name is not in the module,
1194/// create and return an mlir GlobalOp with the specified type (TODO(cir):
1195/// address space).
1196///
1197/// TODO(cir):
1198/// 1. If there is something in the module with the specified name, return
1199/// it potentially bitcasted to the right type.
1200///
1201/// 2. If \p d is non-null, it specifies a decl that correspond to this. This
1202/// is used to set the attributes on the global when it is first created.
1203///
1204/// 3. If \p isForDefinition is true, it is guaranteed that an actual global
1205/// with type \p ty will be returned, not conversion of a variable with the same
1206/// mangled name but some other type.
1207cir::GlobalOp
1208CIRGenModule::getOrCreateCIRGlobal(StringRef mangledName, mlir::Type ty,
1209 LangAS langAS, const VarDecl *d,
1210 ForDefinition_t isForDefinition) {
1211
1212 // Lookup the entry, lazily creating it if necessary.
1213 cir::GlobalOp entry;
1214 if (mlir::Operation *v = getGlobalValue(mangledName)) {
1215 if (!isa<cir::GlobalOp>(v))
1217 "getOrCreateCIRGlobal: global with non-GlobalOp type");
1218 entry = cast<cir::GlobalOp>(v);
1219 }
1220
1221 if (entry) {
1222 mlir::ptr::MemorySpaceAttrInterface entryCIRAS = entry.getAddrSpaceAttr();
1224
1227
1228 if (entry.getSymType() == ty &&
1229 cir::isMatchingAddressSpace(entryCIRAS, langAS))
1230 return entry;
1231
1232 // If there are two attempts to define the same mangled name, issue an
1233 // error.
1234 //
1235 // TODO(cir): look at mlir::GlobalValue::isDeclaration for all aspects of
1236 // recognizing the global as a declaration, for now only check if
1237 // initializer is present.
1238 if (isForDefinition && !entry.isDeclaration()) {
1240 "getOrCreateCIRGlobal: global with conflicting type");
1241 }
1242
1243 // Address space check removed because it is unnecessary because CIR records
1244 // address space info in types.
1245
1246 // (If global is requested for a definition, we always need to create a new
1247 // global, not just return a bitcast.)
1248 if (!isForDefinition)
1249 return entry;
1250 }
1251
1252 mlir::Location loc = getLoc(d->getSourceRange());
1253
1254 // Calculate constant storage flag before creating the global. This was moved
1255 // from after the global creation to ensure the constant flag is set correctly
1256 // at creation time, matching the logic used in emitCXXGlobalVarDeclInit.
1257 bool isConstant = false;
1258 if (d) {
1259 bool needsDtor =
1261 isConstant = d->getType().isConstantStorage(
1262 astContext, /*ExcludeCtor=*/true, /*ExcludeDtor=*/!needsDtor);
1263 }
1264
1265 mlir::ptr::MemorySpaceAttrInterface declCIRAS =
1266 cir::toCIRAddressSpaceAttr(getMLIRContext(), getGlobalVarAddressSpace(d));
1267
1268 // mlir::SymbolTable::Visibility::Public is the default, no need to explicitly
1269 // mark it as such.
1270 cir::GlobalOp gv = createGlobalOp(loc, mangledName, ty, isConstant, declCIRAS,
1271 /*insertPoint=*/entry.getOperation());
1272
1273 // If we already created a global with the same mangled name (but different
1274 // type) before, remove it from its parent.
1275 if (entry)
1276 replaceGlobal(entry, gv);
1277
1278 // This is the first use or definition of a mangled name. If there is a
1279 // deferred decl with this name, remember that we need to emit it at the end
1280 // of the file.
1281 auto ddi = deferredDecls.find(mangledName);
1282 if (ddi != deferredDecls.end()) {
1283 // Move the potentially referenced deferred decl to the DeferredDeclsToEmit
1284 // list, and remove it from DeferredDecls (since we don't need it anymore).
1285 addDeferredDeclToEmit(ddi->second);
1286 deferredDecls.erase(ddi);
1287 }
1288
1289 // Handle things which are present even on external declarations.
1290 if (d) {
1291 if (langOpts.OpenMP && !langOpts.OpenMPSimd)
1293 "getOrCreateCIRGlobal: OpenMP target global variable");
1294
1295 gv.setAlignmentAttr(getSize(astContext.getDeclAlign(d)));
1296
1297 setLinkageForGV(gv, d);
1298
1299 if (d->getTLSKind())
1300 setTLSMode(gv, *d);
1301
1302 setGVProperties(gv, d);
1303
1304 // If required by the ABI, treat declarations of static data members with
1305 // inline initializers as definitions.
1306 if (astContext.isMSStaticDataMemberInlineDefinition(d))
1308 "getOrCreateCIRGlobal: MS static data member inline definition");
1309
1310 // Emit section information for extern variables.
1311 if (d->hasExternalStorage()) {
1312 if (const SectionAttr *sa = d->getAttr<SectionAttr>())
1313 gv.setSectionAttr(builder.getStringAttr(sa->getName()));
1314 }
1315
1316 // Handle XCore specific ABI requirements.
1317 if (getTriple().getArch() == llvm::Triple::xcore)
1319 "getOrCreateCIRGlobal: XCore specific ABI requirements");
1320
1321 // Check if we a have a const declaration with an initializer, we may be
1322 // able to emit it as available_externally to expose it's value to the
1323 // optimizer.
1324 if (getLangOpts().CPlusPlus && gv.isPublic() &&
1325 d->getType().isConstQualified() && gv.isDeclaration() &&
1326 !d->hasDefinition() && d->hasInit() && !d->hasAttr<DLLImportAttr>())
1327 errorNYI(
1328 d->getSourceRange(),
1329 "getOrCreateCIRGlobal: external const declaration with initializer");
1330 }
1331
1332 if (d &&
1335 // TODO(cir): set target attributes
1336 // External HIP managed variables needed to be recorded for transformation
1337 // in both device and host compilations.
1338 if (getLangOpts().CUDA && d && d->hasAttr<HIPManagedAttr>() &&
1339 d->hasExternalStorage())
1341 "getOrCreateCIRGlobal: HIP managed attribute");
1342 }
1343
1345 return gv;
1346}
1347
1348cir::GlobalOp
1350 ForDefinition_t isForDefinition) {
1351 assert(d->hasGlobalStorage() && "Not a global variable");
1352 QualType astTy = d->getType();
1353 if (!ty)
1354 ty = getTypes().convertTypeForMem(astTy);
1355
1356 StringRef mangledName = getMangledName(d);
1357 return getOrCreateCIRGlobal(mangledName, ty, getGlobalVarAddressSpace(d), d,
1358 isForDefinition);
1359}
1360
1361/// Return the mlir::Value for the address of the given global variable. If
1362/// \p ty is non-null and if the global doesn't exist, then it will be created
1363/// with the specified type instead of whatever the normal requested type would
1364/// be. If \p isForDefinition is true, it is guaranteed that an actual global
1365/// with type \p ty will be returned, not conversion of a variable with the same
1366/// mangled name but some other type.
1367mlir::Value CIRGenModule::getAddrOfGlobalVar(const VarDecl *d, mlir::Type ty,
1368 ForDefinition_t isForDefinition) {
1369 assert(d->hasGlobalStorage() && "Not a global variable");
1370 QualType astTy = d->getType();
1371 if (!ty)
1372 ty = getTypes().convertTypeForMem(astTy);
1373
1374 bool tlsAccess = d->getTLSKind() != VarDecl::TLS_None;
1375 cir::GlobalOp g = getOrCreateCIRGlobal(d, ty, isForDefinition);
1376 mlir::Type ptrTy = builder.getPointerTo(g.getSymType(), g.getAddrSpaceAttr());
1377 return cir::GetGlobalOp::create(
1378 builder, getLoc(d->getSourceRange()), ptrTy, g.getSymNameAttr(),
1379 tlsAccess,
1380 /*static_local=*/g.getStaticLocalGuard().has_value());
1381}
1382
1383cir::GlobalViewAttr CIRGenModule::getAddrOfGlobalVarAttr(const VarDecl *d) {
1384 assert(d->hasGlobalStorage() && "Not a global variable");
1385 mlir::Type ty = getTypes().convertTypeForMem(d->getType());
1386
1387 cir::GlobalOp globalOp = getOrCreateCIRGlobal(d, ty, NotForDefinition);
1388 cir::PointerType ptrTy =
1389 builder.getPointerTo(globalOp.getSymType(), globalOp.getAddrSpaceAttr());
1390 return builder.getGlobalViewAttr(ptrTy, globalOp);
1391}
1392
1393void CIRGenModule::addUsedGlobal(cir::CIRGlobalValueInterface gv) {
1394 assert((mlir::isa<cir::FuncOp>(gv.getOperation()) ||
1395 !gv.isDeclarationForLinker()) &&
1396 "Only globals with definition can force usage.");
1397 llvmUsed.emplace_back(gv);
1398}
1399
1400void CIRGenModule::addCompilerUsedGlobal(cir::CIRGlobalValueInterface gv) {
1401 assert(!gv.isDeclarationForLinker() &&
1402 "Only globals with definition can force usage.");
1403 llvmCompilerUsed.emplace_back(gv);
1404}
1405
1407 cir::CIRGlobalValueInterface gv) {
1408 assert((mlir::isa<cir::FuncOp>(gv.getOperation()) ||
1409 !gv.isDeclarationForLinker()) &&
1410 "Only globals with definition can force usage.");
1411 if (getTriple().isOSBinFormatELF())
1412 llvmCompilerUsed.emplace_back(gv);
1413 else
1414 llvmUsed.emplace_back(gv);
1415}
1416
1417static void emitUsed(CIRGenModule &cgm, StringRef name,
1418 std::vector<cir::CIRGlobalValueInterface> &list) {
1419 if (list.empty())
1420 return;
1421
1422 CIRGenBuilderTy &builder = cgm.getBuilder();
1423 mlir::Location loc = builder.getUnknownLoc();
1425 usedArray.resize(list.size());
1426 for (auto [i, op] : llvm::enumerate(list)) {
1427 usedArray[i] = cir::GlobalViewAttr::get(
1428 cgm.voidPtrTy, mlir::FlatSymbolRefAttr::get(op.getNameAttr()));
1429 }
1430
1431 cir::ArrayType arrayTy = cir::ArrayType::get(cgm.voidPtrTy, usedArray.size());
1432
1433 cir::ConstArrayAttr initAttr = cir::ConstArrayAttr::get(
1434 arrayTy, mlir::ArrayAttr::get(&cgm.getMLIRContext(), usedArray));
1435
1436 cir::GlobalOp gv = cgm.createGlobalOp(loc, name, arrayTy,
1437 /*isConstant=*/false);
1438 gv.setLinkage(cir::GlobalLinkageKind::AppendingLinkage);
1439 gv.setInitialValueAttr(initAttr);
1440 gv.setSectionAttr(builder.getStringAttr("llvm.metadata"));
1441}
1442
1444 emitUsed(*this, "llvm.used", llvmUsed);
1445 emitUsed(*this, "llvm.compiler.used", llvmCompilerUsed);
1446}
1447
1449 bool isTentative) {
1450 if (getLangOpts().OpenCL || getLangOpts().OpenMPIsTargetDevice) {
1452 "emitGlobalVarDefinition: emit OpenCL/OpenMP global variable");
1453 return;
1454 }
1455
1456 // Whether the definition of the variable is available externally.
1457 // If yes, we shouldn't emit the GloablCtor and GlobalDtor for the variable
1458 // since this is the job for its original source.
1459 bool isDefinitionAvailableExternally =
1460 astContext.GetGVALinkageForVariable(vd) == GVA_AvailableExternally;
1461
1462 // It is useless to emit the definition for an available_externally variable
1463 // which can't be marked as const.
1464 if (isDefinitionAvailableExternally &&
1465 (!vd->hasConstantInitialization() ||
1466 // TODO: Update this when we have interface to check constexpr
1467 // destructor.
1468 vd->needsDestruction(astContext) ||
1469 !vd->getType().isConstantStorage(astContext, true, true)))
1470 return;
1471
1472 mlir::Attribute init;
1473 bool needsGlobalCtor = false;
1474 bool needsGlobalDtor =
1475 !isDefinitionAvailableExternally &&
1477 const VarDecl *initDecl;
1478 const Expr *initExpr = vd->getAnyInitializer(initDecl);
1479
1480 std::optional<ConstantEmitter> emitter;
1481
1482 // CUDA E.2.4.1 "__shared__ variables cannot have an initialization
1483 // as part of their declaration." Sema has already checked for
1484 // error cases, so we just need to set Init to PoisonValue.
1485 bool isCUDASharedVar =
1486 getLangOpts().CUDAIsDevice && vd->hasAttr<CUDASharedAttr>();
1487 // Shadows of initialized device-side global variables are also left
1488 // undefined.
1489 // Managed Variables should be initialized on both host side and device side.
1490 bool isCUDAShadowVar =
1491 !getLangOpts().CUDAIsDevice && !vd->hasAttr<HIPManagedAttr>() &&
1492 (vd->hasAttr<CUDAConstantAttr>() || vd->hasAttr<CUDADeviceAttr>() ||
1493 vd->hasAttr<CUDASharedAttr>());
1494 bool isCUDADeviceShadowVar =
1495 getLangOpts().CUDAIsDevice && !vd->hasAttr<HIPManagedAttr>() &&
1498
1499 if (getLangOpts().CUDA &&
1500 (isCUDASharedVar || isCUDAShadowVar || isCUDADeviceShadowVar)) {
1501 init = cir::UndefAttr::get(convertType(vd->getType()));
1502 } else if (vd->hasAttr<LoaderUninitializedAttr>()) {
1504 "emitGlobalVarDefinition: loader uninitialized attribute");
1505 } else if (!initExpr) {
1506 // This is a tentative definition; tentative definitions are
1507 // implicitly initialized with { 0 }.
1508 //
1509 // Note that tentative definitions are only emitted at the end of
1510 // a translation unit, so they should never have incomplete
1511 // type. In addition, EmitTentativeDefinition makes sure that we
1512 // never attempt to emit a tentative definition if a real one
1513 // exists. A use may still exists, however, so we still may need
1514 // to do a RAUW.
1515 assert(!vd->getType()->isIncompleteType() && "Unexpected incomplete type");
1516 init = builder.getZeroInitAttr(convertType(vd->getType()));
1517 } else {
1518 emitter.emplace(*this);
1519 mlir::Attribute initializer = emitter->tryEmitForInitializer(*initDecl);
1520 if (!initializer) {
1521 QualType qt = initExpr->getType();
1522 if (vd->getType()->isReferenceType())
1523 qt = vd->getType();
1524
1525 if (getLangOpts().CPlusPlus) {
1526 if (initDecl->hasFlexibleArrayInit(astContext))
1528 "emitGlobalVarDefinition: flexible array initializer");
1529 init = builder.getZeroInitAttr(convertType(qt));
1530 if (!isDefinitionAvailableExternally)
1531 needsGlobalCtor = true;
1532 } else {
1534 "emitGlobalVarDefinition: static initializer");
1535 }
1536 } else {
1537 init = initializer;
1538 // We don't need an initializer, so remove the entry for the delayed
1539 // initializer position (just in case this entry was delayed) if we
1540 // also don't need to register a destructor.
1542 }
1543 }
1544
1545 mlir::Type initType;
1546 if (mlir::isa<mlir::SymbolRefAttr>(init)) {
1547 errorNYI(
1548 vd->getSourceRange(),
1549 "emitGlobalVarDefinition: global initializer is a symbol reference");
1550 return;
1551 } else {
1552 assert(mlir::isa<mlir::TypedAttr>(init) && "This should have a type");
1553 auto typedInitAttr = mlir::cast<mlir::TypedAttr>(init);
1554 initType = typedInitAttr.getType();
1555 }
1556 assert(!mlir::isa<mlir::NoneType>(initType) && "Should have a type by now");
1557
1558 cir::GlobalOp gv =
1559 getOrCreateCIRGlobal(vd, initType, ForDefinition_t(!isTentative));
1560 // TODO(cir): Strip off pointer casts from Entry if we get them?
1561
1562 if (!gv || gv.getSymType() != initType) {
1564 "emitGlobalVarDefinition: global initializer with type mismatch");
1565 return;
1566 }
1567
1569
1570 if (vd->hasAttr<AnnotateAttr>())
1571 addGlobalAnnotations(vd, gv);
1572
1573 // Set CIR's linkage type as appropriate.
1574 cir::GlobalLinkageKind linkage = getCIRLinkageVarDefinition(vd);
1575
1576 // CUDA B.2.1 "The __device__ qualifier declares a variable that resides on
1577 // the device. [...]"
1578 // CUDA B.2.2 "The __constant__ qualifier, optionally used together with
1579 // __device__, declares a variable that: [...]
1580 // Is accessible from all the threads within the grid and from the host
1581 // through the runtime library (cudaGetSymbolAddress() / cudaGetSymbolSize()
1582 // / cudaMemcpyToSymbol() / cudaMemcpyFromSymbol())."
1583 if (langOpts.CUDA) {
1584 if (langOpts.CUDAIsDevice) {
1585 // __shared__ variables is not marked as externally initialized,
1586 // because they must not be initialized.
1587 if (linkage != cir::GlobalLinkageKind::InternalLinkage &&
1588 !vd->isConstexpr() && !vd->getType().isConstQualified() &&
1589 (vd->hasAttr<CUDADeviceAttr>() || vd->hasAttr<CUDAConstantAttr>() ||
1592 gv->setAttr(cir::CUDAExternallyInitializedAttr::getMnemonic(),
1593 cir::CUDAExternallyInitializedAttr::get(&getMLIRContext()));
1594 }
1595 } else {
1596 // Adjust linkage of shadow variables in host compilation
1598 }
1600 }
1601
1602 // Set initializer and finalize emission
1604 if (emitter)
1605 emitter->finalize(gv);
1606
1607 // If it is safe to mark the global 'constant', do so now.
1608 // Use the same logic as classic codegen EmitGlobalVarDefinition.
1609 gv.setConstant((vd->hasAttr<CUDAConstantAttr>() && langOpts.CUDAIsDevice) ||
1610 (!needsGlobalCtor && !needsGlobalDtor &&
1611 vd->getType().isConstantStorage(astContext,
1612 /*ExcludeCtor=*/true,
1613 /*ExcludeDtor=*/true)));
1614 // If it is in a read-only section, mark it 'constant'.
1615 if (const SectionAttr *sa = vd->getAttr<SectionAttr>()) {
1616 const ASTContext::SectionInfo &si = astContext.SectionInfos[sa->getName()];
1617 if ((si.SectionFlags & ASTContext::PSF_Write) == 0)
1618 gv.setConstant(true);
1619 }
1620
1621 // Set CIR linkage and DLL storage class.
1622 gv.setLinkage(linkage);
1623 // FIXME(cir): setLinkage should likely set MLIR's visibility automatically.
1624 gv.setVisibility(getMLIRVisibilityFromCIRLinkage(linkage));
1626 if (linkage == cir::GlobalLinkageKind::CommonLinkage) {
1627 // common vars aren't constant even if declared const.
1628 gv.setConstant(false);
1629 // Tentative definition of global variables may be initialized with
1630 // non-zero null pointers. In this case they should have weak linkage
1631 // since common linkage must have zero initializer and must not have
1632 // explicit section therefore cannot have non-zero initial value.
1633 std::optional<mlir::Attribute> initializer = gv.getInitialValue();
1634 if (initializer && !getBuilder().isNullValue(*initializer))
1635 gv.setLinkage(cir::GlobalLinkageKind::WeakAnyLinkage);
1636 }
1637
1638 setNonAliasAttributes(vd, gv);
1639
1640 if (vd->getTLSKind() && !vd->isStaticLocal())
1641 setTLSMode(gv, *vd);
1642
1643 maybeSetTrivialComdat(*vd, gv);
1644
1645 // Emit the initializer function if necessary.
1646 if (needsGlobalCtor || needsGlobalDtor)
1647 emitCXXGlobalVarDeclInitFunc(vd, gv, needsGlobalCtor);
1648}
1649
1651 if (getFunctionLinkage(gd) !=
1652 cir::GlobalLinkageKind::AvailableExternallyLinkage)
1653 return true;
1654
1655 const auto *fd = cast<FunctionDecl>(gd.getDecl());
1656 // Inline builtins must be emitted; the body is redirected to a `.inline`
1657 // symbol in CIRGenFunction::generateCode.
1658 if (fd->isInlineBuiltinDeclaration())
1659 return true;
1660
1661 // PR9614 / glibc btowc workaround: an available_externally function whose
1662 // body just calls itself (via asm label or __builtin_* lowering on the
1663 // same name) is not a valid stand-in for the real implementation. Drop
1664 // it from the IR so the optimizer doesn't reason about its body.
1666}
1667
1669 mlir::Operation *op) {
1670 const auto *decl = cast<ValueDecl>(gd.getDecl());
1671 if (const auto *fd = dyn_cast<FunctionDecl>(decl)) {
1672 if (!shouldEmitFunction(gd))
1673 return;
1674
1675 if (const auto *method = dyn_cast<CXXMethodDecl>(decl)) {
1676 // Make sure to emit the definition(s) before we emit the thunks. This is
1677 // necessary for the generation of certain thunks.
1678 if (isa<CXXConstructorDecl>(method) || isa<CXXDestructorDecl>(method))
1679 abi->emitCXXStructor(gd);
1680 else if (fd->isMultiVersion())
1681 errorNYI(method->getSourceRange(), "multiversion functions");
1682 else
1684
1685 if (method->isVirtual())
1686 getVTables().emitThunks(gd);
1687
1688 return;
1689 }
1690
1691 if (fd->isMultiVersion())
1692 errorNYI(fd->getSourceRange(), "multiversion functions");
1694 return;
1695 }
1696
1697 if (const auto *vd = dyn_cast<VarDecl>(decl))
1698 return emitGlobalVarDefinition(vd, !vd->hasDefinition());
1699
1700 llvm_unreachable("Invalid argument to CIRGenModule::emitGlobalDefinition");
1701}
1702
1703mlir::Attribute
1705 assert(!e->getType()->isPointerType() && "Strings are always arrays");
1706
1707 // Don't emit it as the address of the string, emit the string data itself
1708 // as an inline array.
1709 if (e->getCharByteWidth() == 1) {
1710 SmallString<64> str(e->getString());
1711
1712 // Resize the string to the right size, which is indicated by its type.
1713 const ConstantArrayType *cat =
1714 astContext.getAsConstantArrayType(e->getType());
1715 uint64_t finalSize = cat->getZExtSize();
1716 str.resize(finalSize);
1717
1718 mlir::Type eltTy = convertType(cat->getElementType());
1719 return builder.getString(str, eltTy, finalSize, /*ensureNullTerm=*/false);
1720 }
1721
1722 auto arrayTy = mlir::cast<cir::ArrayType>(convertType(e->getType()));
1723
1724 auto arrayEltTy = mlir::cast<cir::IntType>(arrayTy.getElementType());
1725
1726 uint64_t arraySize = arrayTy.getSize();
1727 unsigned literalSize = e->getLength();
1728 assert(arraySize > literalSize &&
1729 "wide string literal array size must have room for null terminator?");
1730
1731 // Check if the string is all null bytes before building the vector.
1732 // In most non-zero cases, this will break out on the first element.
1733 bool isAllZero = true;
1734 for (unsigned i = 0; i < literalSize; ++i) {
1735 if (e->getCodeUnit(i) != 0) {
1736 isAllZero = false;
1737 break;
1738 }
1739 }
1740
1741 if (isAllZero)
1742 return cir::ZeroAttr::get(arrayTy);
1743
1744 // Otherwise emit a constant array holding the characters.
1746 elements.reserve(arraySize);
1747 for (unsigned i = 0; i < literalSize; ++i)
1748 elements.push_back(cir::IntAttr::get(arrayEltTy, e->getCodeUnit(i)));
1749
1750 auto elementsAttr = mlir::ArrayAttr::get(&getMLIRContext(), elements);
1751 return builder.getConstArray(elementsAttr, arrayTy);
1752}
1753
1755 return getTriple().supportsCOMDAT();
1756}
1757
1758static bool shouldBeInCOMDAT(CIRGenModule &cgm, const Decl &d) {
1759 if (!cgm.supportsCOMDAT())
1760 return false;
1761
1762 if (d.hasAttr<SelectAnyAttr>())
1763 return true;
1764
1765 GVALinkage linkage;
1766 if (auto *vd = dyn_cast<VarDecl>(&d))
1767 linkage = cgm.getASTContext().GetGVALinkageForVariable(vd);
1768 else
1769 linkage =
1771
1772 switch (linkage) {
1776 return false;
1779 return true;
1780 }
1781 llvm_unreachable("No such linkage");
1782}
1783
1784void CIRGenModule::maybeSetTrivialComdat(const Decl &d, mlir::Operation *op) {
1785 if (!shouldBeInCOMDAT(*this, d))
1786 return;
1787 if (auto globalOp = dyn_cast_or_null<cir::GlobalOp>(op)) {
1788 globalOp.setComdat(true);
1789 } else {
1790 auto funcOp = cast<cir::FuncOp>(op);
1791 funcOp.setComdat(true);
1792 }
1793}
1794
1796 // Make sure that this type is translated.
1797 genTypes.updateCompletedType(td);
1798}
1799
1800void CIRGenModule::addReplacement(StringRef name, mlir::Operation *op) {
1801 replacements[name] = op;
1802}
1803
1804#ifndef NDEBUG
1805static bool verifyPointerTypeArgs(cir::FuncOp oldF, cir::FuncOp newF,
1806 mlir::SymbolUserMap &userMap) {
1807 for (mlir::Operation *user : userMap.getUsers(oldF)) {
1808 auto call = mlir::dyn_cast<cir::CallOp>(user);
1809 if (!call)
1810 continue;
1811
1812 for (auto [argOp, fnArgType] :
1813 llvm::zip(call.getArgs(), newF.getFunctionType().getInputs())) {
1814 if (argOp.getType() != fnArgType)
1815 return false;
1816 }
1817 }
1818
1819 return true;
1820}
1821#endif // NDEBUG
1822
1823void CIRGenModule::applyReplacements() {
1824 if (replacements.empty())
1825 return;
1826
1827 // Build a symbol user map once — this walks the module O(M) one time.
1828 // Previously, each replaceAllSymbolUses call walked the entire module,
1829 // giving O(R × M) quadratic behavior for R replacements.
1830 mlir::SymbolTableCollection symbolTableCollection;
1831 mlir::SymbolUserMap userMap(symbolTableCollection, theModule);
1832
1833 for (auto &i : replacements) {
1834 StringRef mangledName = i.first;
1835 mlir::Operation *replacement = i.second;
1836 mlir::Operation *entry = getGlobalValue(mangledName);
1837 if (!entry)
1838 continue;
1839 assert(isa<cir::FuncOp>(entry) && "expected function");
1840 auto oldF = cast<cir::FuncOp>(entry);
1841 auto newF = dyn_cast<cir::FuncOp>(replacement);
1842 if (!newF) {
1843 // In classic codegen, this can be a global alias, a bitcast, or a GEP.
1844 errorNYI(replacement->getLoc(), "replacement is not a function");
1845 continue;
1846 }
1847
1848 assert(verifyPointerTypeArgs(oldF, newF, userMap) &&
1849 "call argument types do not match replacement function");
1850
1851 // Replace old with new, but keep the old order. Uses
1852 // SymbolUserMap to touch only actual users, not the whole module.
1853 userMap.replaceAllUsesWith(oldF, newF.getSymNameAttr());
1854 newF->moveBefore(oldF);
1855 eraseGlobalSymbol(oldF);
1856 oldF->erase();
1857 }
1858}
1859
1861 mlir::Location loc, StringRef name, mlir::Type ty,
1862 cir::GlobalLinkageKind linkage, clang::CharUnits alignment) {
1863 auto gv = mlir::dyn_cast_or_null<cir::GlobalOp>(getGlobalValue(name));
1864
1865 if (gv) {
1866 // Check if the variable has the right type.
1867 if (gv.getSymType() == ty)
1868 return gv;
1869
1870 // Because of C++ name mangling, the only way we can end up with an already
1871 // existing global with the same name is if it has been declared extern
1872 // "C".
1873 assert(gv.isDeclaration() && "Declaration has wrong type!");
1874
1875 errorNYI(loc, "createOrReplaceCXXRuntimeVariable: declaration exists with "
1876 "wrong type");
1877 return gv;
1878 }
1879
1880 // Create a new variable.
1881 gv = createGlobalOp(loc, name, ty, /*isConstant=*/true);
1882
1883 // Set up extra information and add to the module
1884 gv.setLinkageAttr(
1885 cir::GlobalLinkageKindAttr::get(&getMLIRContext(), linkage));
1886 mlir::SymbolTable::setSymbolVisibility(gv,
1888
1889 if (supportsCOMDAT() && cir::isWeakForLinker(linkage) &&
1890 !gv.hasAvailableExternallyLinkage()) {
1891 gv.setComdat(true);
1892 }
1893
1894 gv.setAlignmentAttr(getSize(alignment));
1895 setDSOLocal(static_cast<mlir::Operation *>(gv));
1896 return gv;
1897}
1898
1899// TODO(CIR): this could be a common method between LLVM codegen.
1900static bool isVarDeclStrongDefinition(const ASTContext &astContext,
1901 CIRGenModule &cgm, const VarDecl *vd,
1902 bool noCommon) {
1903 // Don't give variables common linkage if -fno-common was specified unless it
1904 // was overridden by a NoCommon attribute.
1905 if ((noCommon || vd->hasAttr<NoCommonAttr>()) && !vd->hasAttr<CommonAttr>())
1906 return true;
1907
1908 // C11 6.9.2/2:
1909 // A declaration of an identifier for an object that has file scope without
1910 // an initializer, and without a storage-class specifier or with the
1911 // storage-class specifier static, constitutes a tentative definition.
1912 if (vd->getInit() || vd->hasExternalStorage())
1913 return true;
1914
1915 // A variable cannot be both common and exist in a section.
1916 if (vd->hasAttr<SectionAttr>())
1917 return true;
1918
1919 // A variable cannot be both common and exist in a section.
1920 // We don't try to determine which is the right section in the front-end.
1921 // If no specialized section name is applicable, it will resort to default.
1922 if (vd->hasAttr<PragmaClangBSSSectionAttr>() ||
1923 vd->hasAttr<PragmaClangDataSectionAttr>() ||
1924 vd->hasAttr<PragmaClangRelroSectionAttr>() ||
1925 vd->hasAttr<PragmaClangRodataSectionAttr>())
1926 return true;
1927
1928 // Thread local vars aren't considered common linkage.
1929 if (vd->getTLSKind())
1930 return true;
1931
1932 // Tentative definitions marked with WeakImportAttr are true definitions.
1933 if (vd->hasAttr<WeakImportAttr>())
1934 return true;
1935
1936 // A variable cannot be both common and exist in a comdat.
1937 if (shouldBeInCOMDAT(cgm, *vd))
1938 return true;
1939
1940 // Declarations with a required alignment do not have common linkage in MSVC
1941 // mode.
1942 if (astContext.getTargetInfo().getCXXABI().isMicrosoft()) {
1943 if (vd->hasAttr<AlignedAttr>())
1944 return true;
1945 QualType varType = vd->getType();
1946 if (astContext.isAlignmentRequired(varType))
1947 return true;
1948
1949 if (const auto *rd = varType->getAsRecordDecl()) {
1950 for (const FieldDecl *fd : rd->fields()) {
1951 if (fd->isBitField())
1952 continue;
1953 if (fd->hasAttr<AlignedAttr>())
1954 return true;
1955 if (astContext.isAlignmentRequired(fd->getType()))
1956 return true;
1957 }
1958 }
1959 }
1960
1961 // Microsoft's link.exe doesn't support alignments greater than 32 bytes for
1962 // common symbols, so symbols with greater alignment requirements cannot be
1963 // common.
1964 // Other COFF linkers (ld.bfd and LLD) support arbitrary power-of-two
1965 // alignments for common symbols via the aligncomm directive, so this
1966 // restriction only applies to MSVC environments.
1967 if (astContext.getTargetInfo().getTriple().isKnownWindowsMSVCEnvironment() &&
1968 astContext.getTypeAlignIfKnown(vd->getType()) >
1969 astContext.toBits(CharUnits::fromQuantity(32)))
1970 return true;
1971
1972 return false;
1973}
1974
1975cir::GlobalLinkageKind
1977 GVALinkage linkage) {
1978 if (linkage == GVA_Internal)
1979 return cir::GlobalLinkageKind::InternalLinkage;
1980
1981 if (dd->hasAttr<WeakAttr>())
1982 return cir::GlobalLinkageKind::WeakAnyLinkage;
1983
1984 if (const auto *fd = dd->getAsFunction())
1985 if (fd->isMultiVersion() && linkage == GVA_AvailableExternally)
1986 return cir::GlobalLinkageKind::LinkOnceAnyLinkage;
1987
1988 // We are guaranteed to have a strong definition somewhere else,
1989 // so we can use available_externally linkage.
1990 if (linkage == GVA_AvailableExternally)
1991 return cir::GlobalLinkageKind::AvailableExternallyLinkage;
1992
1993 // Note that Apple's kernel linker doesn't support symbol
1994 // coalescing, so we need to avoid linkonce and weak linkages there.
1995 // Normally, this means we just map to internal, but for explicit
1996 // instantiations we'll map to external.
1997
1998 // In C++, the compiler has to emit a definition in every translation unit
1999 // that references the function. We should use linkonce_odr because
2000 // a) if all references in this translation unit are optimized away, we
2001 // don't need to codegen it. b) if the function persists, it needs to be
2002 // merged with other definitions. c) C++ has the ODR, so we know the
2003 // definition is dependable.
2004 if (linkage == GVA_DiscardableODR)
2005 return !astContext.getLangOpts().AppleKext
2006 ? cir::GlobalLinkageKind::LinkOnceODRLinkage
2007 : cir::GlobalLinkageKind::InternalLinkage;
2008
2009 // An explicit instantiation of a template has weak linkage, since
2010 // explicit instantiations can occur in multiple translation units
2011 // and must all be equivalent. However, we are not allowed to
2012 // throw away these explicit instantiations.
2013 //
2014 // CUDA/HIP: For -fno-gpu-rdc case, device code is limited to one TU,
2015 // so say that CUDA templates are either external (for kernels) or internal.
2016 // This lets llvm perform aggressive inter-procedural optimizations. For
2017 // -fgpu-rdc case, device function calls across multiple TU's are allowed,
2018 // therefore we need to follow the normal linkage paradigm.
2019 if (linkage == GVA_StrongODR) {
2020 if (getLangOpts().AppleKext)
2021 return cir::GlobalLinkageKind::ExternalLinkage;
2022 if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice &&
2023 !getLangOpts().GPURelocatableDeviceCode)
2024 return dd->hasAttr<CUDAGlobalAttr>()
2025 ? cir::GlobalLinkageKind::ExternalLinkage
2026 : cir::GlobalLinkageKind::InternalLinkage;
2027 return cir::GlobalLinkageKind::WeakODRLinkage;
2028 }
2029
2030 // C++ doesn't have tentative definitions and thus cannot have common
2031 // linkage.
2032 if (!getLangOpts().CPlusPlus && isa<VarDecl>(dd) &&
2033 !isVarDeclStrongDefinition(astContext, *this, cast<VarDecl>(dd),
2034 getCodeGenOpts().NoCommon))
2035 return cir::GlobalLinkageKind::CommonLinkage;
2036
2037 // selectany symbols are externally visible, so use weak instead of
2038 // linkonce. MSVC optimizes away references to const selectany globals, so
2039 // all definitions should be the same and ODR linkage should be used.
2040 // http://msdn.microsoft.com/en-us/library/5tkz6s71.aspx
2041 if (dd->hasAttr<SelectAnyAttr>())
2042 return cir::GlobalLinkageKind::WeakODRLinkage;
2043
2044 // Otherwise, we have strong external linkage.
2045 assert(linkage == GVA_StrongExternal);
2046 return cir::GlobalLinkageKind::ExternalLinkage;
2047}
2048
2049/// This function is called when we implement a function with no prototype, e.g.
2050/// "int foo() {}". If there are existing call uses of the old function in the
2051/// module, this adjusts them to call the new function directly.
2052///
2053/// This is not just a cleanup: the always_inline pass requires direct calls to
2054/// functions to be able to inline them. If there is a bitcast in the way, it
2055/// won't inline them. Instcombine normally deletes these calls, but it isn't
2056/// run at -O0.
2058 mlir::Operation *old, cir::FuncOp newFn) {
2059 // If we're redefining a global as a function, don't transform it.
2060 auto oldFn = mlir::dyn_cast<cir::FuncOp>(old);
2061 if (!oldFn)
2062 return;
2063
2064 // TODO(cir): this RAUW ignores the features below.
2068 if (oldFn->getAttrs().size() <= 1)
2069 errorNYI(old->getLoc(),
2070 "replaceUsesOfNonProtoTypeWithRealFunction: Attribute forwarding");
2071
2072 // Mark new function as originated from a no-proto declaration.
2073 newFn.setNoProto(oldFn.getNoProto());
2074
2075 // Iterate through all calls of the no-proto function.
2076 std::optional<mlir::SymbolTable::UseRange> symUses =
2077 oldFn.getSymbolUses(oldFn->getParentOp());
2078
2079 if (!symUses)
2080 return;
2081
2082 for (const mlir::SymbolTable::SymbolUse &use : symUses.value()) {
2083 mlir::OpBuilder::InsertionGuard guard(builder);
2084
2085 if (auto noProtoCallOp = mlir::dyn_cast<cir::CallOp>(use.getUser())) {
2086 builder.setInsertionPoint(noProtoCallOp);
2087
2088 // Patch call type with the real function type.
2089 cir::FuncType newFnType = newFn.getFunctionType();
2090 mlir::OperandRange callOperands = noProtoCallOp.getOperands();
2091 bool returnTypeMatches =
2092 newFnType.hasVoidReturn()
2093 ? noProtoCallOp.getNumResults() == 0
2094 : noProtoCallOp.getNumResults() == 1 &&
2095 noProtoCallOp.getResultTypes().front() ==
2096 newFnType.getReturnType();
2097 bool typesMatch = !newFn.getNoProto() && returnTypeMatches &&
2098 callOperands.size() == newFnType.getNumInputs();
2099 for (unsigned i = 0, e = newFnType.getNumInputs(); typesMatch && i != e;
2100 ++i) {
2101 if (callOperands[i].getType() != newFnType.getInput(i))
2102 typesMatch = false;
2103 }
2104
2105 cir::CallOp realCallOp;
2106 if (typesMatch) {
2107 // Patch call type with the real function type.
2108 realCallOp =
2109 builder.createCallOp(noProtoCallOp.getLoc(), newFn, callOperands);
2110 } else {
2111 // Build an indirect call whose function-pointer signature matches
2112 // the existing call site.
2113 cir::FuncType origFnType = oldFn.getFunctionType();
2114 cir::FuncType callFnType =
2115 origFnType.isVarArg()
2116 ? cir::FuncType::get(origFnType.getInputs(),
2117 origFnType.getReturnType(),
2118 /*isVarArg=*/false)
2119 : origFnType;
2120 mlir::Value addr = cir::GetGlobalOp::create(
2121 builder, noProtoCallOp.getLoc(), cir::PointerType::get(newFnType),
2122 newFn.getSymName());
2123 mlir::Value casted =
2124 builder.createBitcast(addr, cir::PointerType::get(callFnType));
2125 realCallOp = builder.createIndirectCallOp(
2126 noProtoCallOp.getLoc(), casted, callFnType, callOperands);
2127 }
2128
2129 // Replace old no proto call with fixed call.
2130 noProtoCallOp.replaceAllUsesWith(realCallOp);
2131 noProtoCallOp.erase();
2132 } else if (auto getGlobalOp =
2133 mlir::dyn_cast<cir::GetGlobalOp>(use.getUser())) {
2134 // The GetGlobal was emitted with the no-proto FuncType. Uses of this
2135 // operation (cir.store, cir.cast) were built for that pointer type. When
2136 // we re-type the result to the real FuncType, we need to add a bit the
2137 // old pointer type so those uses are still valid. This can lead to
2138 // some redundant bitcast chains, but those will be cleaned up by the
2139 // canonicalizer.
2140 mlir::Value res = getGlobalOp.getAddr();
2141 const mlir::Type oldResTy = res.getType();
2142 const auto newPtrTy = cir::PointerType::get(newFn.getFunctionType());
2143 if (oldResTy != newPtrTy) {
2144 res.setType(newPtrTy);
2145 builder.setInsertionPointAfter(getGlobalOp.getOperation());
2146 mlir::Value castRes =
2147 cir::CastOp::create(builder, getGlobalOp.getLoc(), oldResTy,
2148 cir::CastKind::bitcast, res);
2149 res.replaceAllUsesExcept(castRes, castRes.getDefiningOp());
2150 }
2151 } else if (mlir::isa<cir::GlobalOp>(use.getUser())) {
2152 // Function addresses in global initializers use GlobalViewAttrs typed to
2153 // the initializer context (e.g. struct field type), not the FuncOp type,
2154 // so no update is required when the no-proto FuncOp is replaced.
2155 } else {
2156 llvm_unreachable(
2157 "replaceUsesOfNonProtoTypeWithRealFunction: unexpected use type");
2158 }
2159 }
2160}
2161
2162cir::GlobalLinkageKind
2164 GVALinkage linkage = astContext.GetGVALinkageForVariable(vd);
2165 return getCIRLinkageForDeclarator(vd, linkage);
2166}
2167
2169 const auto *d = cast<FunctionDecl>(gd.getDecl());
2170
2171 GVALinkage linkage = astContext.GetGVALinkageForFunction(d);
2172
2173 if (const auto *dtor = dyn_cast<CXXDestructorDecl>(d))
2174 return getCXXABI().getCXXDestructorLinkage(linkage, dtor, gd.getDtorType());
2175
2176 return getCIRLinkageForDeclarator(d, linkage);
2177}
2178
2179static cir::GlobalOp
2180generateStringLiteral(mlir::Location loc, mlir::TypedAttr c,
2181 cir::GlobalLinkageKind lt, CIRGenModule &cgm,
2182 StringRef globalName, CharUnits alignment) {
2184
2185 // Create a global variable for this string
2186 // FIXME(cir): check for insertion point in module level.
2187 cir::GlobalOp gv = cgm.createGlobalOp(loc, globalName, c.getType(),
2188 !cgm.getLangOpts().WritableStrings);
2189
2190 // Set up extra information and add to the module
2191 gv.setAlignmentAttr(cgm.getSize(alignment));
2192 gv.setLinkageAttr(
2193 cir::GlobalLinkageKindAttr::get(cgm.getBuilder().getContext(), lt));
2197 if (gv.isWeakForLinker()) {
2198 assert(cgm.supportsCOMDAT() && "Only COFF uses weak string literals");
2199 gv.setComdat(true);
2200 }
2201 cgm.setDSOLocal(static_cast<mlir::Operation *>(gv));
2202 return gv;
2203}
2204
2205// LLVM IR automatically uniques names when new llvm::GlobalVariables are
2206// created. This is handy, for example, when creating globals for string
2207// literals. Since we don't do that when creating cir::GlobalOp's, we need
2208// a mechanism to generate a unique name in advance.
2209//
2210// For now, this mechanism is only used in cases where we know that the
2211// name is compiler-generated, so we don't use the MLIR symbol table for
2212// the lookup.
2213std::string CIRGenModule::getUniqueGlobalName(const std::string &baseName) {
2214 // If this is the first time we've generated a name for this basename, use
2215 // it as is and start a counter for this base name.
2216 auto it = cgGlobalNames.find(baseName);
2217 if (it == cgGlobalNames.end()) {
2218 cgGlobalNames[baseName] = 1;
2219 return baseName;
2220 }
2221
2222 std::string result =
2223 baseName + "." + std::to_string(cgGlobalNames[baseName]++);
2224 // There should not be any symbol with this name in the module.
2225 assert(!getGlobalValue(result));
2226 return result;
2227}
2228
2229/// Return a pointer to a constant array for the given string literal.
2231 StringRef name) {
2232 CharUnits alignment =
2233 astContext.getAlignOfGlobalVarInChars(s->getType(), /*VD=*/nullptr);
2234
2235 mlir::Attribute c = getConstantArrayFromStringLiteral(s);
2236
2237 cir::GlobalOp gv;
2238 if (!getLangOpts().WritableStrings && constantStringMap.count(c)) {
2239 gv = constantStringMap[c];
2240 // The bigger alignment always wins.
2241 if (!gv.getAlignment() ||
2242 uint64_t(alignment.getQuantity()) > *gv.getAlignment())
2243 gv.setAlignmentAttr(getSize(alignment));
2244 } else {
2245 // Mangle the string literal if that's how the ABI merges duplicate strings.
2246 // Don't do it if they are writable, since we don't want writes in one TU to
2247 // affect strings in another.
2248 if (getCXXABI().getMangleContext().shouldMangleStringLiteral(s) &&
2249 !getLangOpts().WritableStrings) {
2251 "getGlobalForStringLiteral: mangle string literals");
2252 }
2253
2254 // Unlike LLVM IR, CIR doesn't automatically unique names for globals, so
2255 // we need to do that explicitly.
2256 std::string uniqueName = getUniqueGlobalName(name.str());
2257 // Synthetic string literals (e.g., from SourceLocExpr) may not have valid
2258 // source locations. Use unknown location in those cases.
2259 mlir::Location loc = s->getBeginLoc().isValid()
2260 ? getLoc(s->getSourceRange())
2261 : builder.getUnknownLoc();
2262 auto typedC = llvm::cast<mlir::TypedAttr>(c);
2263 gv = generateStringLiteral(loc, typedC,
2264 cir::GlobalLinkageKind::PrivateLinkage, *this,
2265 uniqueName, alignment);
2266 setDSOLocal(static_cast<mlir::Operation *>(gv));
2267 constantStringMap[c] = gv;
2268
2270 }
2271 return gv;
2272}
2273
2274/// Return a pointer to a constant array for the given string literal.
2275cir::GlobalViewAttr
2277 StringRef name) {
2278 cir::GlobalOp gv = getGlobalForStringLiteral(s, name);
2279 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(gv.getSymType());
2280 assert(arrayTy && "String literal must be array");
2282 cir::PointerType ptrTy = getBuilder().getPointerTo(arrayTy.getElementType());
2283
2284 return builder.getGlobalViewAttr(ptrTy, gv);
2285}
2286
2287// TODO(cir): this could be a common AST helper for both CIR and LLVM codegen.
2289 if (getLangOpts().OpenCL)
2291
2292 // For temporaries inside functions, CUDA treats them as normal variables.
2293 // LangAS::cuda_device, on the other hand, is reserved for those variables
2294 // explicitly marked with __device__.
2295 if (getLangOpts().CUDAIsDevice)
2296 return LangAS::Default;
2297
2298 if (getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice)
2300 if (getLangOpts().SYCLIsDevice)
2301 errorNYI("SYCL temp address space");
2302
2303 return LangAS::Default;
2304}
2305
2307 CIRGenFunction *cgf) {
2308 if (cgf && e->getType()->isVariablyModifiedType())
2310
2312 "emitExplicitCastExprType");
2313}
2314
2316 const MemberPointerType *mpt) {
2317 if (mpt->isMemberFunctionPointerType()) {
2318 auto ty = mlir::cast<cir::MethodType>(convertType(destTy));
2319 return builder.getNullMethodAttr(ty);
2320 }
2321
2322 auto ty = mlir::cast<cir::DataMemberType>(convertType(destTy));
2323 return builder.getNullDataMemberAttr(ty);
2324}
2325
2328
2329 mlir::Location loc = getLoc(e->getSourceRange());
2330
2331 const auto *decl = cast<DeclRefExpr>(e->getSubExpr())->getDecl();
2332
2333 // A member function pointer.
2334 if (const auto *methodDecl = dyn_cast<CXXMethodDecl>(decl)) {
2335 auto ty = mlir::cast<cir::MethodType>(convertType(e->getType()));
2336 if (methodDecl->isVirtual())
2337 return cir::ConstantOp::create(
2338 builder, loc, getCXXABI().buildVirtualMethodAttr(ty, methodDecl));
2339
2340 const CIRGenFunctionInfo &fi =
2342 cir::FuncType funcTy = getTypes().getFunctionType(fi);
2343 cir::FuncOp methodFuncOp = getAddrOfFunction(methodDecl, funcTy);
2344 return cir::ConstantOp::create(builder, loc,
2345 builder.getMethodAttr(ty, methodFuncOp));
2346 }
2347
2348 // Otherwise, a member data pointer.
2349 auto ty = mlir::cast<cir::DataMemberType>(convertType(e->getType()));
2350 const auto *fieldDecl = cast<FieldDecl>(decl);
2351 const auto *mpt = e->getType()->castAs<MemberPointerType>();
2352 const auto *destClass = mpt->getMostRecentCXXRecordDecl();
2353
2354 // Empty [[no_unique_address]] fields have no CIR field index; represent the
2355 // pointer-to-data-member by its concrete byte offset within the class.
2357 // This function should ONLY be accessed in reference to itself, I don't see
2358 // any cases/couldn't find any cases where anything else could get here, and
2359 // classic-codegen does the same.
2360 assert(fieldDecl->getParent() == destClass &&
2361 "scalar member pointer should be relative to the declaring class");
2362 uint64_t offset =
2363 astContext.toCharUnitsFromBits(astContext.getFieldOffset(fieldDecl))
2364 .getQuantity();
2365 return cir::ConstantOp::create(builder, loc,
2366 cir::DataMemberOffsetAttr::get(ty, offset));
2367 }
2368
2369 std::optional<llvm::SmallVector<int32_t>> path =
2370 buildMemberPath(destClass, fieldDecl);
2371 if (!path)
2372 return {};
2373 return cir::ConstantOp::create(builder, loc,
2374 builder.getDataMemberAttr(ty, *path));
2375}
2376
2377std::optional<llvm::SmallVector<int32_t>>
2379 const FieldDecl *field) {
2381 if (!findFieldMemberPath(destClass, field, path))
2382 return std::nullopt;
2383 return path;
2384}
2385
2386bool CIRGenModule::findFieldMemberPath(const CXXRecordDecl *currentClass,
2387 const FieldDecl *field,
2389 const CIRGenRecordLayout &layout =
2390 getTypes().getCIRGenRecordLayout(currentClass);
2391
2392 // The field is declared directly in this class.
2393 if (astContext.isSameEntity(field->getParent(), currentClass)) {
2394 int32_t fieldIdx;
2395 if (currentClass->isUnion()) {
2396 // For unions, getCIRFieldNo always returns 0 for every union member (all
2397 // members share offset 0 in the CIR record). Use the declaration-order
2398 // index to distinguish members with the same type at the same offset.
2399 if (!layout.isZeroInitializable()) {
2400 errorNYI(field->getLocation(),
2401 "data member pointer for non-zero-initializable union");
2402 return false;
2403 }
2404 fieldIdx = static_cast<int32_t>(field->getFieldIndex());
2405 } else {
2406 fieldIdx = static_cast<int32_t>(layout.getCIRFieldNo(field));
2407 }
2408 path.push_back(fieldIdx);
2409 return true;
2410 }
2411
2412 // Otherwise search the base subobjects. A virtual base only blocks lowering
2413 // when the field actually lives within it; a virtual base elsewhere in the
2414 // hierarchy must not stop us from reaching a member through a non-virtual
2415 // path.
2416 for (const CXXBaseSpecifier &base : currentClass->bases()) {
2417 const auto *baseDecl =
2418 cast<CXXRecordDecl>(base.getType()->getAsRecordDecl());
2419
2420 if (base.isVirtual()) {
2421 // A pointer to a data member that traverses a virtual base is ill-formed,
2422 // so this guard only fires defensively if the member is reached through
2423 // the virtual base. An unrelated virtual base is skipped so it does not
2424 // block members reached through a non-virtual path.
2425 llvm::SmallVector<int32_t> discardedPath;
2426 if (findFieldMemberPath(baseDecl, field, discardedPath)) {
2427 errorNYI(field->getLocation(),
2428 "data member pointer through virtual base");
2429 return false;
2430 }
2431 continue;
2432 }
2433
2434 // If a base class doesn't participate in layout, the field cannot be in it,
2435 // skip it.
2436 if (!layout.hasNonVirtualBaseCIRField(baseDecl))
2437 continue;
2438
2439 auto baseFieldIdx =
2440 static_cast<int32_t>(layout.getNonVirtualBaseCIRFieldNo(baseDecl));
2441 path.push_back(baseFieldIdx);
2442 if (findFieldMemberPath(baseDecl, field, path))
2443 return true;
2444 path.pop_back();
2445 }
2446 return false;
2447}
2448
2450 return isEmptyFieldForLayout(astContext, field) &&
2451 field->isPotentiallyOverlapping();
2452}
2453
2455 for (Decl *decl : dc->decls()) {
2456 // Unlike other DeclContexts, the contents of an ObjCImplDecl at TU scope
2457 // are themselves considered "top-level", so EmitTopLevelDecl on an
2458 // ObjCImplDecl does not recursively visit them. We need to do that in
2459 // case they're nested inside another construct (LinkageSpecDecl /
2460 // ExportDecl) that does stop them from being considered "top-level".
2461 if (auto *oid = dyn_cast<ObjCImplDecl>(decl))
2462 errorNYI(oid->getSourceRange(), "emitDeclConext: ObjCImplDecl");
2463
2465 }
2466}
2467
2468// Emit code for a single top level declaration.
2470
2471 // Ignore dependent declarations.
2472 if (decl->isTemplated())
2473 return;
2474
2475 switch (decl->getKind()) {
2476 default:
2477 errorNYI(decl->getBeginLoc(), "declaration of kind",
2478 decl->getDeclKindName());
2479 break;
2480
2481 case Decl::CXXConversion:
2482 case Decl::CXXMethod:
2483 case Decl::Function: {
2484 auto *fd = cast<FunctionDecl>(decl);
2485 // Consteval functions shouldn't be emitted.
2486 if (!fd->isConsteval())
2487 emitGlobal(fd);
2488 break;
2489 }
2490 case Decl::Export:
2492 break;
2493
2494 case Decl::Var:
2495 case Decl::Decomposition:
2496 case Decl::VarTemplateSpecialization: {
2498 if (auto *decomp = dyn_cast<DecompositionDecl>(decl))
2499 for (auto *binding : decomp->flat_bindings())
2500 if (auto *holdingVar = binding->getHoldingVar())
2501 emitGlobal(holdingVar);
2502 break;
2503 }
2504 case Decl::OpenACCRoutine:
2506 break;
2507 case Decl::OpenACCDeclare:
2509 break;
2510 case Decl::OMPThreadPrivate:
2512 break;
2513 case Decl::OMPGroupPrivate:
2515 break;
2516 case Decl::OMPAllocate:
2518 break;
2519 case Decl::OMPCapturedExpr:
2521 break;
2522 case Decl::OMPDeclareReduction:
2524 break;
2525 case Decl::OMPDeclareMapper:
2527 break;
2528 case Decl::OMPRequires:
2530 break;
2531 case Decl::Enum:
2532 case Decl::Using: // using X; [C++]
2533 case Decl::UsingDirective: // using namespace X; [C++]
2534 case Decl::UsingEnum: // using enum X; [C++]
2535 case Decl::NamespaceAlias:
2536 case Decl::Typedef:
2537 case Decl::TypeAlias: // using foo = bar; [C++11]
2538 case Decl::Record:
2540 break;
2541
2542 // No code generation needed.
2543 case Decl::ClassTemplate:
2544 case Decl::Concept:
2545 case Decl::CXXDeductionGuide:
2546 case Decl::Empty:
2547 case Decl::ExplicitInstantiation:
2548 case Decl::FunctionTemplate:
2549 case Decl::StaticAssert:
2550 case Decl::TypeAliasTemplate:
2551 case Decl::UsingShadow:
2552 case Decl::VarTemplate:
2553 case Decl::VarTemplatePartialSpecialization:
2554 break;
2555
2556 case Decl::CXXConstructor:
2558 break;
2559 case Decl::CXXDestructor:
2561 break;
2562
2563 // C++ Decls
2564 case Decl::LinkageSpec:
2565 case Decl::Namespace:
2567 break;
2568
2569 case Decl::ClassTemplateSpecialization:
2570 case Decl::CXXRecord: {
2573 for (auto *childDecl : crd->decls())
2575 emitTopLevelDecl(childDecl);
2576 break;
2577 }
2578
2579 case Decl::FileScopeAsm:
2580 // File-scope asm is ignored during device-side CUDA compilation.
2581 if (langOpts.CUDA && langOpts.CUDAIsDevice)
2582 break;
2583 // File-scope asm is ignored during device-side OpenMP compilation.
2584 if (langOpts.OpenMPIsTargetDevice)
2585 break;
2586 // File-scope asm is ignored during device-side SYCL compilation.
2587 if (langOpts.SYCLIsDevice)
2588 break;
2589 auto *file_asm = cast<FileScopeAsmDecl>(decl);
2590 std::string line = file_asm->getAsmString();
2591 globalScopeAsm.push_back(builder.getStringAttr(line));
2592 break;
2593 }
2594}
2595
2596void CIRGenModule::setInitializer(cir::GlobalOp &op, mlir::Attribute value) {
2597 // Recompute visibility when updating initializer.
2598 op.setInitialValueAttr(value);
2600}
2601
2602std::pair<cir::FuncType, cir::FuncOp> CIRGenModule::getAddrAndTypeOfCXXStructor(
2603 GlobalDecl gd, const CIRGenFunctionInfo *fnInfo, cir::FuncType fnType,
2604 bool dontDefer, ForDefinition_t isForDefinition) {
2605 auto *md = cast<CXXMethodDecl>(gd.getDecl());
2606
2607 if (isa<CXXDestructorDecl>(md)) {
2608 // Always alias equivalent complete destructors to base destructors in the
2609 // MS ABI.
2610 if (getTarget().getCXXABI().isMicrosoft() &&
2611 gd.getDtorType() == Dtor_Complete &&
2612 md->getParent()->getNumVBases() == 0)
2613 errorNYI(md->getSourceRange(),
2614 "getAddrAndTypeOfCXXStructor: MS ABI complete destructor");
2615 }
2616
2617 if (!fnType) {
2618 if (!fnInfo)
2620 fnType = getTypes().getFunctionType(*fnInfo);
2621 }
2622
2623 auto fn = getOrCreateCIRFunction(getMangledName(gd), fnType, gd,
2624 /*ForVtable=*/false, dontDefer,
2625 /*IsThunk=*/false, isForDefinition);
2626
2627 return {fnType, fn};
2628}
2629
2631 mlir::Type funcType, bool forVTable,
2632 bool dontDefer,
2633 ForDefinition_t isForDefinition) {
2634 assert(!cast<FunctionDecl>(gd.getDecl())->isConsteval() &&
2635 "consteval function should never be emitted");
2636
2637 if (!funcType) {
2638 const auto *fd = cast<FunctionDecl>(gd.getDecl());
2639 funcType = convertType(fd->getType());
2640 }
2641
2642 // Devirtualized destructor calls may come through here instead of via
2643 // getAddrOfCXXStructor. Make sure we use the MS ABI base destructor instead
2644 // of the complete destructor when necessary.
2645 if (const auto *dd = dyn_cast<CXXDestructorDecl>(gd.getDecl())) {
2646 if (getTarget().getCXXABI().isMicrosoft() &&
2647 gd.getDtorType() == Dtor_Complete &&
2648 dd->getParent()->getNumVBases() == 0)
2649 errorNYI(dd->getSourceRange(),
2650 "getAddrOfFunction: MS ABI complete destructor");
2651 }
2652
2653 StringRef mangledName = getMangledName(gd);
2654 cir::FuncOp func =
2655 getOrCreateCIRFunction(mangledName, funcType, gd, forVTable, dontDefer,
2656 /*isThunk=*/false, isForDefinition);
2657 // Returns kernel handle for HIP kernel stub function.
2658 if (langOpts.CUDA && !langOpts.CUDAIsDevice &&
2659 cast<FunctionDecl>(gd.getDecl())->hasAttr<CUDAGlobalAttr>()) {
2660 mlir::Operation *handle = getCUDARuntime().getKernelHandle(func, gd);
2661
2662 // For HIP the kernel handle is a GlobalOp, which cannot be cast to
2663 // FuncOp. Return the stub directly in that case.
2664 bool isHIPHandle = mlir::isa<cir::GlobalOp>(*handle);
2665 if (isForDefinition || isHIPHandle)
2666 return func;
2667 return mlir::dyn_cast<cir::FuncOp>(*handle);
2668 }
2669 return func;
2670}
2671
2672static std::string getMangledNameImpl(CIRGenModule &cgm, GlobalDecl gd,
2673 const NamedDecl *nd) {
2674 SmallString<256> buffer;
2675
2676 llvm::raw_svector_ostream out(buffer);
2678
2680
2681 if (mc.shouldMangleDeclName(nd)) {
2682 mc.mangleName(gd.getWithDecl(nd), out);
2683 } else {
2684 IdentifierInfo *ii = nd->getIdentifier();
2685 assert(ii && "Attempt to mangle unnamed decl.");
2686
2687 const auto *fd = dyn_cast<FunctionDecl>(nd);
2688 if (fd &&
2689 fd->getType()->castAs<FunctionType>()->getCallConv() == CC_X86RegCall) {
2690 cgm.errorNYI(nd->getSourceRange(), "getMangledName: X86RegCall");
2691 } else if (fd && fd->hasAttr<CUDAGlobalAttr>() &&
2693 out << "__device_stub__" << ii->getName();
2694 } else if (fd &&
2695 DeviceKernelAttr::isOpenCLSpelling(
2696 fd->getAttr<DeviceKernelAttr>()) &&
2698 cgm.errorNYI(nd->getSourceRange(), "getMangledName: OpenCL Stub");
2699 } else {
2700 out << ii->getName();
2701 }
2702 }
2703
2704 // Check if the module name hash should be appended for internal linkage
2705 // symbols. This should come before multi-version target suffixes are
2706 // appendded. This is to keep the name and module hash suffix of the internal
2707 // linkage function together. The unique suffix should only be added when name
2708 // mangling is done to make sure that the final name can be properly
2709 // demangled. For example, for C functions without prototypes, name mangling
2710 // is not done and the unique suffix should not be appended then.
2712
2713 if (const auto *fd = dyn_cast<FunctionDecl>(nd)) {
2714 if (fd->isMultiVersion()) {
2715 cgm.errorNYI(nd->getSourceRange(),
2716 "getMangledName: multi-version functions");
2717 }
2718 }
2719 if (cgm.getLangOpts().GPURelocatableDeviceCode) {
2720 cgm.errorNYI(nd->getSourceRange(),
2721 "getMangledName: GPU relocatable device code");
2722 }
2723
2724 return std::string(out.str());
2725}
2726
2727static FunctionDecl *
2729 const FunctionDecl *protoFunc) {
2730 // If this is a C no-prototype function, we can take the 'easy' way out and
2731 // just create a function with no arguments/functions, etc.
2732 if (!protoFunc->hasPrototype())
2733 return FunctionDecl::Create(
2734 ctx, /*DC=*/ctx.getTranslationUnitDecl(),
2735 /*StartLoc=*/SourceLocation{}, /*NLoc=*/SourceLocation{}, bindName,
2736 protoFunc->getType(), /*TInfo=*/nullptr, StorageClass::SC_None);
2737
2738 QualType funcTy = protoFunc->getType();
2739 auto *fpt = cast<FunctionProtoType>(protoFunc->getType());
2740
2741 // If this is a member function, add an explicit 'this' to the function type.
2742 if (auto *methodDecl = dyn_cast<CXXMethodDecl>(protoFunc);
2743 methodDecl && methodDecl->isImplicitObjectMemberFunction()) {
2744 llvm::SmallVector<QualType> paramTypes{fpt->getParamTypes()};
2745 paramTypes.insert(paramTypes.begin(), methodDecl->getThisType());
2746
2747 funcTy = ctx.getFunctionType(fpt->getReturnType(), paramTypes,
2748 fpt->getExtProtoInfo());
2749 fpt = cast<FunctionProtoType>(funcTy);
2750 }
2751
2752 auto *tempFunc =
2754 /*StartLoc=*/SourceLocation{},
2755 /*NLoc=*/SourceLocation{}, bindName, funcTy,
2756 /*TInfo=*/nullptr, StorageClass::SC_None);
2757
2759 params.reserve(fpt->getNumParams());
2760
2761 // Add all of the parameters.
2762 for (unsigned i = 0, e = fpt->getNumParams(); i != e; ++i) {
2764 ctx, tempFunc, /*StartLoc=*/SourceLocation{},
2765 /*IdLoc=*/SourceLocation{},
2766 /*Id=*/nullptr, fpt->getParamType(i), /*TInfo=*/nullptr,
2767 StorageClass::SC_None, /*DefArg=*/nullptr);
2768 parm->setScopeInfo(0, i);
2769 params.push_back(parm);
2770 }
2771
2772 tempFunc->setParams(params);
2773
2774 return tempFunc;
2775}
2776
2777std::string
2779 const FunctionDecl *attachedFunction) {
2781 getASTContext(), bindName, attachedFunction);
2782
2783 std::string ret = getMangledNameImpl(*this, GlobalDecl(tempFunc), tempFunc);
2784
2785 // This does nothing (it is a do-nothing function), since this is a
2786 // slab-allocator, but leave a call in to immediately destroy this in case we
2787 // ever come up with a way of getting allocations back.
2788 getASTContext().Deallocate(tempFunc);
2789 return ret;
2790}
2791
2793 GlobalDecl canonicalGd = gd.getCanonicalDecl();
2794
2795 // Some ABIs don't have constructor variants. Make sure that base and complete
2796 // constructors get mangled the same.
2797 if (const auto *cd = dyn_cast<CXXConstructorDecl>(canonicalGd.getDecl())) {
2798 if (!getTarget().getCXXABI().hasConstructorVariants()) {
2799 errorNYI(cd->getSourceRange(),
2800 "getMangledName: C++ constructor without variants");
2801 return cast<NamedDecl>(gd.getDecl())->getIdentifier()->getName();
2802 }
2803 }
2804
2805 // In CUDA/HIP device compilation with -fgpu-rdc, the mangled name of a
2806 // static device variable depends on whether the variable is referenced by
2807 // a host or device host function. Therefore the mangled name cannot be
2808 // cached.
2809 if (!langOpts.CUDAIsDevice || !astContext.mayExternalize(gd.getDecl())) {
2810 auto foundName = mangledDeclNames.find(canonicalGd);
2811 if (foundName != mangledDeclNames.end())
2812 return foundName->second;
2813 }
2814
2815 // Keep the first result in the case of a mangling collision.
2816 const auto *nd = cast<NamedDecl>(gd.getDecl());
2817 std::string mangledName = getMangledNameImpl(*this, gd, nd);
2818
2819 auto result = manglings.insert(std::make_pair(mangledName, gd));
2820 return mangledDeclNames[canonicalGd] = result.first->first();
2821}
2822
2824 assert(!d->getInit() && "Cannot emit definite definitions here!");
2825
2826 StringRef mangledName = getMangledName(d);
2827 mlir::Operation *gv = getGlobalValue(mangledName);
2828
2829 // If we already have a definition, not declaration, with the same mangled
2830 // name, emitting of declaration is not required (and would actually overwrite
2831 // the emitted definition).
2832 if (gv && !mlir::cast<cir::GlobalOp>(gv).isDeclaration())
2833 return;
2834
2835 // If we have not seen a reference to this variable yet, place it into the
2836 // deferred declarations table to be emitted if needed later.
2837 if (!mustBeEmitted(d) && !gv) {
2838 deferredDecls[mangledName] = d;
2839 return;
2840 }
2841
2842 // The tentative definition is the only definition.
2844}
2845
2847 // Never defer when EmitAllDecls is specified.
2848 if (langOpts.EmitAllDecls)
2849 return true;
2850
2851 const auto *vd = dyn_cast<VarDecl>(global);
2852 if (vd &&
2853 ((codeGenOpts.KeepPersistentStorageVariables &&
2854 (vd->getStorageDuration() == SD_Static ||
2855 vd->getStorageDuration() == SD_Thread)) ||
2856 (codeGenOpts.KeepStaticConsts && vd->getStorageDuration() == SD_Static &&
2857 vd->getType().isConstQualified())))
2858 return true;
2859
2860 return getASTContext().DeclMustBeEmitted(global);
2861}
2862
2864 // In OpenMP 5.0 variables and function may be marked as
2865 // device_type(host/nohost) and we should not emit them eagerly unless we sure
2866 // that they must be emitted on the host/device. To be sure we need to have
2867 // seen a declare target with an explicit mentioning of the function, we know
2868 // we have if the level of the declare target attribute is -1. Note that we
2869 // check somewhere else if we should emit this at all.
2870 if (langOpts.OpenMP >= 50 && !langOpts.OpenMPSimd) {
2871 std::optional<OMPDeclareTargetDeclAttr *> activeAttr =
2872 OMPDeclareTargetDeclAttr::getActiveAttr(global);
2873 if (!activeAttr || (*activeAttr)->getLevel() != (unsigned)-1)
2874 return false;
2875 }
2876
2877 const auto *fd = dyn_cast<FunctionDecl>(global);
2878 if (fd) {
2879 // Implicit template instantiations may change linkage if they are later
2880 // explicitly instantiated, so they should not be emitted eagerly.
2881 if (fd->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
2882 return false;
2883 // Defer until all versions have been semantically checked.
2884 if (fd->hasAttr<TargetVersionAttr>() && !fd->isMultiVersion())
2885 return false;
2886 if (langOpts.SYCLIsDevice) {
2887 errorNYI(fd->getSourceRange(), "mayBeEmittedEagerly: SYCL");
2888 return false;
2889 }
2890 }
2891 const auto *vd = dyn_cast<VarDecl>(global);
2892 if (vd)
2893 if (astContext.getInlineVariableDefinitionKind(vd) ==
2895 // A definition of an inline constexpr static data member may change
2896 // linkage later if it's redeclared outside the class.
2897 return false;
2898
2899 // If OpenMP is enabled and threadprivates must be generated like TLS, delay
2900 // codegen for global variables, because they may be marked as threadprivate.
2901 if (langOpts.OpenMP && langOpts.OpenMPUseTLS &&
2902 astContext.getTargetInfo().isTLSSupported() && isa<VarDecl>(global) &&
2903 !global->getType().isConstantStorage(astContext, false, false) &&
2904 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(global))
2905 return false;
2906
2907 assert((fd || vd) &&
2908 "Only FunctionDecl and VarDecl should hit this path so far.");
2909 return true;
2910}
2911
2912static bool shouldAssumeDSOLocal(const CIRGenModule &cgm,
2913 cir::CIRGlobalValueInterface gv) {
2914 if (gv.hasLocalLinkage())
2915 return true;
2916
2917 if (!gv.hasDefaultVisibility() && !gv.hasExternalWeakLinkage())
2918 return true;
2919
2920 // DLLImport explicitly marks the GV as external.
2921 // so it shouldn't be dso_local
2922 // But we don't have the info set now
2924
2925 const llvm::Triple &tt = cgm.getTriple();
2926 const CodeGenOptions &cgOpts = cgm.getCodeGenOpts();
2927 if (tt.isOSCygMing()) {
2928 // In MinGW and Cygwin, variables without DLLImport can still be
2929 // automatically imported from a DLL by the linker; don't mark variables
2930 // that potentially could come from another DLL as DSO local.
2931
2932 // With EmulatedTLS, TLS variables can be autoimported from other DLLs
2933 // (and this actually happens in the public interface of libstdc++), so
2934 // such variables can't be marked as DSO local. (Native TLS variables
2935 // can't be dllimported at all, though.)
2936 cgm.errorNYI("shouldAssumeDSOLocal: MinGW");
2937 }
2938
2939 // On COFF, don't mark 'extern_weak' symbols as DSO local. If these symbols
2940 // remain unresolved in the link, they can be resolved to zero, which is
2941 // outside the current DSO.
2942 if (tt.isOSBinFormatCOFF() && gv.hasExternalWeakLinkage())
2943 return false;
2944
2945 // Every other GV is local on COFF.
2946 // Make an exception for windows OS in the triple: Some firmware builds use
2947 // *-win32-macho triples. This (accidentally?) produced windows relocations
2948 // without GOT tables in older clang versions; Keep this behaviour.
2949 // FIXME: even thread local variables?
2950 if (tt.isOSBinFormatCOFF() || (tt.isOSWindows() && tt.isOSBinFormatMachO()))
2951 return true;
2952
2953 // Only handle COFF and ELF for now.
2954 if (!tt.isOSBinFormatELF())
2955 return false;
2956
2957 llvm::Reloc::Model rm = cgOpts.RelocationModel;
2958 const LangOptions &lOpts = cgm.getLangOpts();
2959 if (rm != llvm::Reloc::Static && !lOpts.PIE) {
2960 // On ELF, if -fno-semantic-interposition is specified and the target
2961 // supports local aliases, there will be neither CC1
2962 // -fsemantic-interposition nor -fhalf-no-semantic-interposition. Set
2963 // dso_local on the function if using a local alias is preferable (can avoid
2964 // PLT indirection).
2965 if (!(isa<cir::FuncOp>(gv) && gv.canBenefitFromLocalAlias()))
2966 return false;
2967 return !(lOpts.SemanticInterposition || lOpts.HalfNoSemanticInterposition);
2968 }
2969
2970 // A definition cannot be preempted from an executable.
2971 if (!gv.isDeclarationForLinker())
2972 return true;
2973
2974 // Most PIC code sequences that assume that a symbol is local cannot produce a
2975 // 0 if it turns out the symbol is undefined. While this is ABI and relocation
2976 // depended, it seems worth it to handle it here.
2977 if (rm == llvm::Reloc::PIC_ && gv.hasExternalWeakLinkage())
2978 return false;
2979
2980 // PowerPC64 prefers TOC indirection to avoid copy relocations.
2981 if (tt.isPPC64())
2982 return false;
2983
2984 if (cgOpts.DirectAccessExternalData) {
2985 // If -fdirect-access-external-data (default for -fno-pic), set dso_local
2986 // for non-thread-local variables. If the symbol is not defined in the
2987 // executable, a copy relocation will be needed at link time. dso_local is
2988 // excluded for thread-local variables because they generally don't support
2989 // copy relocations.
2990 if (auto globalOp = dyn_cast<cir::GlobalOp>(gv.getOperation())) {
2991 // Assume variables are not thread-local until that support is added.
2993 return true;
2994 }
2995
2996 // -fno-pic sets dso_local on a function declaration to allow direct
2997 // accesses when taking its address (similar to a data symbol). If the
2998 // function is not defined in the executable, a canonical PLT entry will be
2999 // needed at link time. -fno-direct-access-external-data can avoid the
3000 // canonical PLT entry. We don't generalize this condition to -fpie/-fpic as
3001 // it could just cause trouble without providing perceptible benefits.
3002 if (isa<cir::FuncOp>(gv) && !cgOpts.NoPLT && rm == llvm::Reloc::Static)
3003 return true;
3004 }
3005
3006 // If we can use copy relocations we can assume it is local.
3007
3008 // Otherwise don't assume it is local.
3009
3010 return false;
3011}
3012
3013void CIRGenModule::setGlobalVisibility(cir::CIRGlobalValueInterface gv,
3014 const NamedDecl *d) const {
3015 // Internal definitions always have default visibility.
3016 if (gv.hasLocalLinkage()) {
3017 gv.setGlobalVisibility(cir::VisibilityKind::Default);
3018 return;
3019 }
3020 if (!d)
3021 return;
3022
3023 // Set visibility for definitions, and for declarations if requested globally
3024 // or set explicitly.
3026
3027 // OpenMP declare target variables must be visible to the host so they can
3028 // be registered. We require protected visibility unless the variable has
3029 // the DT_nohost modifier and does not need to be registered.
3030 if (getASTContext().getLangOpts().OpenMP &&
3031 getASTContext().getLangOpts().OpenMPIsTargetDevice && isa<VarDecl>(d) &&
3032 d->hasAttr<OMPDeclareTargetDeclAttr>() &&
3033 d->getAttr<OMPDeclareTargetDeclAttr>()->getDevType() !=
3034 OMPDeclareTargetDeclAttr::DT_NoHost &&
3036 llvm_unreachable("setGlobalVisibility: OpenMP is NYI");
3037 return;
3038 }
3039
3040 // CUDA/HIP device kernels and global variables must be visible to the host
3041 // so they can be registered / initialized. We require protected visibility
3042 // unless the user explicitly requested hidden via an attribute.
3043 if (getASTContext().getLangOpts().CUDAIsDevice &&
3045 !d->hasAttr<OMPDeclareTargetDeclAttr>()) {
3046 bool needsProtected = false;
3047 if (isa<FunctionDecl>(d)) {
3048 needsProtected =
3049 d->hasAttr<CUDAGlobalAttr>() || d->hasAttr<DeviceKernelAttr>();
3050 } else if (const auto *vd = dyn_cast<VarDecl>(d)) {
3051 needsProtected = vd->hasAttr<CUDADeviceAttr>() ||
3052 vd->hasAttr<CUDAConstantAttr>() ||
3053 vd->getType()->isCUDADeviceBuiltinSurfaceType() ||
3054 vd->getType()->isCUDADeviceBuiltinTextureType();
3055 }
3056 if (needsProtected) {
3057 gv.setGlobalVisibility(cir::VisibilityKind::Protected);
3058 return;
3059 }
3060 }
3061
3063 gv.setGlobalVisibility(cir::VisibilityKind::Hidden);
3064 return;
3065 }
3066
3068
3069 if (lv.isVisibilityExplicit() || getLangOpts().SetVisibilityForExternDecls ||
3070 !gv.isDeclarationForLinker())
3071 gv.setGlobalVisibility(getCIRVisibilityKind(lv.getVisibility()));
3072}
3073
3074void CIRGenModule::setDSOLocal(cir::CIRGlobalValueInterface gv) const {
3075 gv.setDSOLocal(shouldAssumeDSOLocal(*this, gv));
3076}
3077
3078void CIRGenModule::setDSOLocal(mlir::Operation *op) const {
3079 if (auto globalValue = dyn_cast<cir::CIRGlobalValueInterface>(op))
3080 setDSOLocal(globalValue);
3081}
3082
3083void CIRGenModule::setGVProperties(mlir::Operation *op,
3084 const NamedDecl *d) const {
3086 setGVPropertiesAux(op, d);
3087}
3088
3089void CIRGenModule::setGVPropertiesAux(mlir::Operation *op,
3090 const NamedDecl *d) const {
3092 setDSOLocal(op);
3094}
3095
3097 GlobalDecl &result) const {
3098 auto res = manglings.find(mangledName);
3099 if (res == manglings.end())
3100 return false;
3101 result = res->getValue();
3102 return true;
3103}
3104
3105static cir::TLSModel getCIRTLSModel(StringRef S) {
3106 return llvm::StringSwitch<cir::TLSModel>(S)
3107 .Case("global-dynamic", cir::TLSModel::GeneralDynamic)
3108 .Case("local-dynamic", cir::TLSModel::LocalDynamic)
3109 .Case("initial-exec", cir::TLSModel::InitialExec)
3110 .Case("local-exec", cir::TLSModel::LocalExec);
3111}
3112
3114 switch (getCodeGenOpts().getDefaultTLSModel()) {
3116 return cir::TLSModel::GeneralDynamic;
3118 return cir::TLSModel::LocalDynamic;
3120 return cir::TLSModel::InitialExec;
3122 return cir::TLSModel::LocalExec;
3123 }
3124 llvm_unreachable("Invalid TLS model!");
3125}
3126
3127void CIRGenModule::setTLSMode(mlir::Operation *op, const VarDecl &d,
3128 bool isExtendingDecl) {
3129 assert(d.getTLSKind() && "setting TLS mode on non-TLS var!");
3130
3131 cir::TLSModel tlm = getDefaultCIRTLSModel();
3132
3133 // Override the TLS model if it is explicitly specified.
3134 if (const auto *attr = d.getAttr<TLSModelAttr>())
3135 tlm = getCIRTLSModel(attr->getModel());
3136
3137 auto global = cast<cir::GlobalOp>(op);
3138 global.setTlsModel(tlm);
3139
3140 // For namespace-scope dyanmic TLS we need to set the wrapper, int, or guard
3141 // info.
3142 if (d.isStaticLocal())
3143 return;
3144
3145 // If this function was called to set the TLS mode for a temporary whose
3146 // lifetime is extended by the variable declared by `d`, don't emit the
3147 // wrapper, init, and guard info.
3148 if (isExtendingDecl)
3149 return;
3150
3151 setGlobalTlsReferences(d, global);
3152}
3153
3155 const CIRGenFunctionInfo &info,
3156 cir::FuncOp func, bool isThunk) {
3157 // TODO(cir): More logic of constructAttributeList is needed.
3158 cir::CallingConv callingConv;
3159 cir::SideEffect sideEffect;
3160
3161 // TODO(cir): The current list should be initialized with the extra function
3162 // attributes, but we don't have those yet. For now, the PAL is initialized
3163 // with nothing.
3165 // Initialize PAL with existing attributes to merge attributes.
3166 mlir::NamedAttrList pal{};
3167 std::vector<mlir::NamedAttrList> argAttrs(info.arguments().size());
3168 mlir::NamedAttrList retAttrs{};
3169 constructAttributeList(func.getName(), info, globalDecl, pal, argAttrs,
3170 retAttrs, callingConv, sideEffect,
3171 /*attrOnCallSite=*/false, isThunk);
3172
3173 for (mlir::NamedAttribute attr : pal)
3174 func->setAttr(attr.getName(), attr.getValue());
3175
3176 llvm::for_each(llvm::enumerate(argAttrs), [func](auto idx_arg_pair) {
3177 mlir::function_interface_impl::setArgAttrs(func, idx_arg_pair.index(),
3178 idx_arg_pair.value());
3179 });
3180 if (!retAttrs.empty())
3181 mlir::function_interface_impl::setResultAttrs(func, 0, retAttrs);
3182
3183 // TODO(cir): Check X86_VectorCall incompatibility wiht WinARM64EC
3184
3185 // TODO(cir): Set the calling convention computed by constructAttributeList
3186 // on the function. FuncOp supports calling_conv, but target-specific
3187 // CodeGen is needed to set it correctly (e.g., AMDGPU kernel functions
3188 // should be marked with AMDGPUKernel).
3190}
3191
3193 cir::FuncOp func,
3194 bool isIncompleteFunction,
3195 bool isThunk) {
3196 // NOTE(cir): Original CodeGen checks if this is an intrinsic. In CIR we
3197 // represent them in dedicated ops. The correct attributes are ensured during
3198 // translation to LLVM. Thus, we don't need to check for them here.
3199
3200 const auto *funcDecl = cast<FunctionDecl>(globalDecl.getDecl());
3201
3202 if (!isIncompleteFunction)
3203 setCIRFunctionAttributes(globalDecl,
3204 getTypes().arrangeGlobalDeclaration(globalDecl),
3205 func, isThunk);
3206
3207 if (!isIncompleteFunction && func.isDeclaration())
3208 getTargetCIRGenInfo().setTargetAttributes(funcDecl, func, *this);
3209
3210 // Mirrors setLinkageForGV in CodeGenModule::SetFunctionAttributes.
3211 setLinkageForFunction(*this, func, funcDecl);
3212
3213 // If we plan on emitting this inline builtin, we can't treat it as a builtin.
3214 if (funcDecl->isInlineBuiltinDeclaration()) {
3215 const FunctionDecl *fdBody;
3216 bool hasBody = funcDecl->hasBody(fdBody);
3217 (void)hasBody;
3218 assert(hasBody && "Inline builtin declarations should always have an "
3219 "available body!");
3221 }
3222
3223 if (funcDecl->isReplaceableGlobalAllocationFunction()) {
3224 // A replaceable global allocation function does not act like a builtin by
3225 // default, only if it is invoked by a new-expression or delete-expression.
3226 func->setAttr(cir::CIRDialect::getNoBuiltinAttrName(),
3227 mlir::UnitAttr::get(&getMLIRContext()));
3228 }
3229}
3230
3231/// Determines whether the language options require us to model
3232/// unwind exceptions. We treat -fexceptions as mandating this
3233/// except under the fragile ObjC ABI with only ObjC exceptions
3234/// enabled. This means, for example, that C with -fexceptions
3235/// enables this.
3236static bool hasUnwindExceptions(const LangOptions &langOpts) {
3237 // If exceptions are completely disabled, obviously this is false.
3238 if (!langOpts.Exceptions)
3239 return false;
3240 // If C++ exceptions are enabled, this is true.
3241 if (langOpts.CXXExceptions)
3242 return true;
3243 // If ObjC exceptions are enabled, this depends on the ABI.
3244 if (langOpts.ObjCExceptions)
3245 return langOpts.ObjCRuntime.hasUnwindExceptions();
3246 return true;
3247}
3248
3250 const clang::FunctionDecl *decl, cir::FuncOp f) {
3253
3254 if (!hasUnwindExceptions(langOpts))
3255 f->setAttr(cir::CIRDialect::getNoThrowAttrName(),
3256 mlir::UnitAttr::get(&getMLIRContext()));
3257
3258 std::optional<cir::InlineKind> existingInlineKind = f.getInlineKind();
3259 bool isNoInline =
3260 existingInlineKind && *existingInlineKind == cir::InlineKind::NoInline;
3261 bool isAlwaysInline = existingInlineKind &&
3262 *existingInlineKind == cir::InlineKind::AlwaysInline;
3263 if (!decl) {
3264 assert(!cir::MissingFeatures::hlsl());
3265
3266 if (!isAlwaysInline &&
3267 codeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) {
3268 // If inlining is disabled and we don't have a declaration to control
3269 // inlining, mark the function as 'noinline' unless it is explicitly
3270 // marked as 'alwaysinline'.
3271 f.setInlineKind(cir::InlineKind::NoInline);
3272 }
3273
3274 return;
3275 }
3276
3283 assert(!cir::MissingFeatures::hlsl());
3284
3285 // Handle inline attributes
3286 if (decl->hasAttr<NoInlineAttr>() && !isAlwaysInline) {
3287 // Add noinline if the function isn't always_inline.
3288 f.setInlineKind(cir::InlineKind::NoInline);
3289 } else if (decl->hasAttr<AlwaysInlineAttr>() && !isNoInline) {
3290 // Don't override AlwaysInline with NoInline, or vice versa, since we can't
3291 // specify both in IR.
3292 f.setInlineKind(cir::InlineKind::AlwaysInline);
3293 } else if (codeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) {
3294 // If inlining is disabled, force everything that isn't always_inline
3295 // to carry an explicit noinline attribute.
3296 if (!isAlwaysInline)
3297 f.setInlineKind(cir::InlineKind::NoInline);
3298 } else {
3299 // Otherwise, propagate the inline hint attribute and potentially use its
3300 // absence to mark things as noinline.
3301 // Search function and template pattern redeclarations for inline.
3302 if (auto *fd = dyn_cast<FunctionDecl>(decl)) {
3303 // TODO: Share this checkForInline implementation with classic codegen.
3304 // This logic is likely to change over time, so sharing would help ensure
3305 // consistency.
3306 auto checkForInline = [](const FunctionDecl *decl) {
3307 auto checkRedeclForInline = [](const FunctionDecl *redecl) {
3308 return redecl->isInlineSpecified();
3309 };
3310 if (any_of(decl->redecls(), checkRedeclForInline))
3311 return true;
3312 const FunctionDecl *pattern = decl->getTemplateInstantiationPattern();
3313 if (!pattern)
3314 return false;
3315 return any_of(pattern->redecls(), checkRedeclForInline);
3316 };
3317 if (checkForInline(fd)) {
3318 f.setInlineKind(cir::InlineKind::InlineHint);
3319 } else if (codeGenOpts.getInlining() ==
3321 !fd->isInlined() && !isAlwaysInline) {
3322 f.setInlineKind(cir::InlineKind::NoInline);
3323 }
3324 }
3325 }
3326
3328}
3329
3330// Maps an AST address space to the OpenCL logical address space kind recorded
3331// in kernel argument metadata. This mapping is independent of the target
3332// address space map, allowing consumers to distinguish OpenCL logical address
3333// spaces even when the target maps them to the same address space.
3334static cir::LangAddressSpace
3336 switch (addressSpace) {
3338 return cir::LangAddressSpace::OffloadGlobal;
3340 return cir::LangAddressSpace::OffloadConstant;
3342 return cir::LangAddressSpace::OffloadLocal;
3344 return cir::LangAddressSpace::OffloadGeneric;
3346 return cir::LangAddressSpace::OffloadGlobalDevice;
3348 return cir::LangAddressSpace::OffloadGlobalHost;
3349 default:
3350 // All other AST address spaces, including target-specific ones, use the
3351 // OpenCL metadata default, which lowers to SPIR address space ID 0.
3352 return cir::LangAddressSpace::Default;
3353 }
3354}
3355
3357 const clang::FunctionDecl *fd) {
3358 assert(fd && "expected a kernel function declaration");
3360
3361 // Create arrays that represent the kernel argument metadata. Each array has
3362 // one value per kernel argument, in source order.
3363 SmallVector<mlir::Attribute> addressQuals;
3364 SmallVector<mlir::Attribute> accessQuals;
3365 SmallVector<mlir::Attribute> argTypeNames;
3366 SmallVector<mlir::Attribute> argBaseTypeNames;
3367 SmallVector<mlir::Attribute> argTypeQuals;
3369
3370 for (const ParmVarDecl *param : fd->parameters()) {
3371 argNames.push_back(builder.getStringAttr(param->getName()));
3372
3373 QualType type = param->getType();
3374 std::string typeQuals;
3375
3376 if (type->isImageType() || type->isPipeType()) {
3377 errorNYI(param->getSourceRange(),
3378 "OpenCL kernel argument metadata for image and pipe types");
3379 return;
3380 }
3381
3382 accessQuals.push_back(builder.getStringAttr("none"));
3383
3384 auto getTypeSpelling = [&](QualType paramType) {
3385 std::string typeName = paramType.getUnqualifiedType().getAsString(policy);
3386
3387 if (paramType.isCanonical()) {
3388 StringRef typeNameRef = typeName;
3389 if (typeNameRef.consume_front("unsigned "))
3390 return std::string("u") + typeNameRef.str();
3391 if (typeNameRef.consume_front("signed "))
3392 return typeNameRef.str();
3393 }
3394
3395 return typeName;
3396 };
3397
3398 // Type metadata preserves source spelling, while base type metadata uses
3399 // canonical spelling without typedefs.
3400 if (type->isPointerType()) {
3401 QualType pointeeType = type->getPointeeType();
3402 addressQuals.push_back(cir::LangAddressSpaceAttr::get(
3403 &getMLIRContext(),
3405
3406 argTypeNames.push_back(
3407 builder.getStringAttr(getTypeSpelling(pointeeType) + "*"));
3408 argBaseTypeNames.push_back(builder.getStringAttr(
3409 getTypeSpelling(pointeeType.getCanonicalType()) + "*"));
3410
3411 if (type.isRestrictQualified())
3412 typeQuals = "restrict";
3413 if (pointeeType.isConstQualified() ||
3415 typeQuals += typeQuals.empty() ? "const" : " const";
3416 if (pointeeType.isVolatileQualified())
3417 typeQuals += typeQuals.empty() ? "volatile" : " volatile";
3418 } else {
3419 addressQuals.push_back(cir::LangAddressSpaceAttr::get(
3420 &getMLIRContext(), cir::LangAddressSpace::Default));
3421
3422 argTypeNames.push_back(builder.getStringAttr(getTypeSpelling(type)));
3423 argBaseTypeNames.push_back(
3424 builder.getStringAttr(getTypeSpelling(type.getCanonicalType())));
3425 }
3426
3427 argTypeQuals.push_back(builder.getStringAttr(typeQuals));
3428 }
3429
3430 mlir::ArrayAttr names;
3431 if (getCodeGenOpts().EmitOpenCLArgMetadata)
3432 names = builder.getArrayAttr(argNames);
3433
3434 mlir::Attribute metadata = cir::OpenCLKernelArgMetadataAttr::get(
3435 func.getContext(), builder.getArrayAttr(addressQuals),
3436 builder.getArrayAttr(accessQuals), builder.getArrayAttr(argTypeNames),
3437 builder.getArrayAttr(argBaseTypeNames),
3438 builder.getArrayAttr(argTypeQuals), names);
3439 func->setAttr(cir::CIRDialect::getOpenCLKernelArgMetadataAttrName(),
3440 metadata);
3441}
3442
3444 StringRef mangledName, mlir::Type funcType, GlobalDecl gd, bool forVTable,
3445 bool dontDefer, bool isThunk, ForDefinition_t isForDefinition,
3446 mlir::NamedAttrList extraAttrs) {
3447 const Decl *d = gd.getDecl();
3448
3449 if (const auto *fd = cast_or_null<FunctionDecl>(d)) {
3450 // For the device, mark the function as one that should be emitted.
3451 if (getLangOpts().OpenMPIsTargetDevice && openMPRuntime &&
3452 !getOpenMPRuntime().markAsGlobalTarget(gd) && fd->isDefined() &&
3453 !dontDefer && !isForDefinition) {
3454 if (const FunctionDecl *fdDef = fd->getDefinition()) {
3455 GlobalDecl gdDef;
3456 if (const auto *cd = dyn_cast<CXXConstructorDecl>(fdDef))
3457 gdDef = GlobalDecl(cd, gd.getCtorType());
3458 else if (const auto *dd = dyn_cast<CXXDestructorDecl>(fdDef))
3459 gdDef = GlobalDecl(dd, gd.getDtorType());
3460 else
3461 gdDef = GlobalDecl(fdDef);
3462 emitGlobal(gdDef);
3463 }
3464 }
3465
3466 // Any attempts to use a MultiVersion function should result in retrieving
3467 // the iFunc instead. Name mangling will handle the rest of the changes.
3468 if (fd->isMultiVersion())
3469 errorNYI(fd->getSourceRange(), "getOrCreateCIRFunction: multi-version");
3470 }
3471
3472 // Lookup the entry, lazily creating it if necessary.
3473 mlir::Operation *entry = getGlobalValue(mangledName);
3474 if (entry) {
3475 assert(mlir::isa<cir::FuncOp>(entry));
3476
3478
3479 // Handle dropped DLL attributes.
3480 if (d && !d->hasAttr<DLLImportAttr>() && !d->hasAttr<DLLExportAttr>()) {
3482 setDSOLocal(entry);
3483 }
3484
3485 // If there are two attempts to define the same mangled name, issue an
3486 // error.
3487 auto fn = cast<cir::FuncOp>(entry);
3488 if (isForDefinition && fn && !fn.isDeclaration()) {
3489 GlobalDecl otherGd;
3490 // Check that GD is not yet in DiagnosedConflictingDefinitions is required
3491 // to make sure that we issue an error only once.
3492 if (lookupRepresentativeDecl(mangledName, otherGd) &&
3493 (gd.getCanonicalDecl().getDecl() !=
3494 otherGd.getCanonicalDecl().getDecl()) &&
3495 diagnosedConflictingDefinitions.insert(gd).second) {
3496 getDiags().Report(d->getLocation(), diag::err_duplicate_mangled_name)
3497 << mangledName;
3498 getDiags().Report(otherGd.getDecl()->getLocation(),
3499 diag::note_previous_definition);
3500 }
3501 }
3502
3503 if (fn && fn.getFunctionType() == funcType) {
3504 return fn;
3505 }
3506
3507 if (!isForDefinition) {
3508 return fn;
3509 }
3510
3511 // TODO(cir): classic codegen checks here if this is a llvm::GlobalAlias.
3512 // How will we support this?
3513 }
3514
3515 auto *funcDecl = llvm::cast_or_null<FunctionDecl>(gd.getDecl());
3516 bool invalidLoc = !funcDecl ||
3517 funcDecl->getSourceRange().getBegin().isInvalid() ||
3518 funcDecl->getSourceRange().getEnd().isInvalid();
3519 cir::FuncOp funcOp = createCIRFunction(
3520 invalidLoc ? theModule->getLoc() : getLoc(funcDecl->getSourceRange()),
3521 mangledName, mlir::cast<cir::FuncType>(funcType), funcDecl);
3522
3523 if (funcDecl && funcDecl->hasAttr<AnnotateAttr>())
3524 deferredAnnotations[mangledName] = funcDecl;
3525
3526 // If we already created a function with the same mangled name (but different
3527 // type) before, take its name and add it to the list of functions to be
3528 // replaced with F at the end of CodeGen.
3529 //
3530 // This happens if there is a prototype for a function (e.g. "int f()") and
3531 // then a definition of a different type (e.g. "int f(int x)").
3532 if (entry) {
3533
3534 // Fetch a generic symbol-defining operation and its uses.
3535 auto symbolOp = mlir::cast<mlir::SymbolOpInterface>(entry);
3536
3537 // This might be an implementation of a function without a prototype, in
3538 // which case, try to do special replacement of calls which match the new
3539 // prototype. The really key thing here is that we also potentially drop
3540 // arguments from the call site so as to make a direct call, which makes the
3541 // inliner happier and suppresses a number of optimizer warnings (!) about
3542 // dropping arguments.
3543 if (symbolOp.getSymbolUses(symbolOp->getParentOp()))
3545
3546 // Obliterate no-proto declaration.
3547 eraseGlobalSymbol(entry);
3548 entry->erase();
3549 }
3550
3551 if (d)
3552 setFunctionAttributes(gd, funcOp, /*isIncompleteFunction=*/false, isThunk);
3553 if (!extraAttrs.empty()) {
3554 extraAttrs.append(funcOp->getAttrs());
3555 funcOp->setAttrs(extraAttrs);
3556 }
3557
3558 // 'dontDefer' actually means don't move this to the deferredDeclsToEmit list.
3559 if (dontDefer) {
3560 // TODO(cir): This assertion will need an additional condition when we
3561 // support incomplete functions.
3562 assert(funcOp.getFunctionType() == funcType);
3563 return funcOp;
3564 }
3565
3566 // All MSVC dtors other than the base dtor are linkonce_odr and delegate to
3567 // each other bottoming out wiht the base dtor. Therefore we emit non-base
3568 // dtors on usage, even if there is no dtor definition in the TU.
3569 if (isa_and_nonnull<CXXDestructorDecl>(d) &&
3570 getCXXABI().useThunkForDtorVariant(cast<CXXDestructorDecl>(d),
3571 gd.getDtorType()))
3572 errorNYI(d->getSourceRange(), "getOrCreateCIRFunction: dtor");
3573
3574 // This is the first use or definition of a mangled name. If there is a
3575 // deferred decl with this name, remember that we need to emit it at the end
3576 // of the file.
3577 auto ddi = deferredDecls.find(mangledName);
3578 if (ddi != deferredDecls.end()) {
3579 // Move the potentially referenced deferred decl to the
3580 // DeferredDeclsToEmit list, and remove it from DeferredDecls (since we
3581 // don't need it anymore).
3582 addDeferredDeclToEmit(ddi->second);
3583 deferredDecls.erase(ddi);
3584
3585 // Otherwise, there are cases we have to worry about where we're using a
3586 // declaration for which we must emit a definition but where we might not
3587 // find a top-level definition.
3588 // - member functions defined inline in their classes
3589 // - friend functions defined inline in some class
3590 // - special member functions with implicit definitions
3591 // If we ever change our AST traversal to walk into class methods, this
3592 // will be unnecessary.
3593 //
3594 // We also don't emit a definition for a function if it's going to be an
3595 // entry in a vtable, unless it's already marked as used.
3596 } else if (getLangOpts().CPlusPlus && d) {
3597 // Look for a declaration that's lexically in a record.
3598 for (const auto *fd = cast<FunctionDecl>(d)->getMostRecentDecl(); fd;
3599 fd = fd->getPreviousDecl()) {
3600 if (isa<CXXRecordDecl>(fd->getLexicalDeclContext())) {
3601 if (fd->doesThisDeclarationHaveABody()) {
3603 break;
3604 }
3605 }
3606 }
3607 }
3608
3609 return funcOp;
3610}
3611
3612cir::FuncOp
3613CIRGenModule::createCIRFunction(mlir::Location loc, StringRef name,
3614 cir::FuncType funcType,
3615 const clang::FunctionDecl *funcDecl) {
3616 cir::FuncOp func;
3617 {
3618 mlir::OpBuilder::InsertionGuard guard(builder);
3619
3620 // Functions always belong at module scope, but the ambient insertion
3621 // point may be inside another op's region, e.g. a thunk body or a
3622 // global's ctor region, so it cannot be used here.
3623 builder.setInsertionPointToEnd(theModule.getBody());
3624
3625 func = cir::FuncOp::create(builder, loc, name, funcType);
3626
3627 symbolLookupCache[func.getSymNameAttr()] = func;
3628
3630
3631 if (funcDecl && !funcDecl->hasPrototype())
3632 func.setNoProto(true);
3633
3634 assert(func.isDeclaration() && "expected empty body");
3635
3636 // A declaration gets private visibility by default, but external linkage
3637 // as the default linkage.
3638 func.setLinkageAttr(cir::GlobalLinkageKindAttr::get(
3639 &getMLIRContext(), cir::GlobalLinkageKind::ExternalLinkage));
3640 mlir::SymbolTable::setSymbolVisibility(
3641 func, mlir::SymbolTable::Visibility::Private);
3642
3644
3645 // Record the func_info tag, a C++ special member form or a known standard
3646 // library entity.
3647 setFuncInfoAttr(func, funcDecl);
3648
3649 if (this->getLangOpts().OpenACC) {
3650 // We only have to handle this attribute, since OpenACCAnnotAttrs are
3651 // handled via the end-of-TU work.
3652 for (const auto *attr :
3653 funcDecl->specific_attrs<OpenACCRoutineDeclAttr>())
3654 emitOpenACCRoutineDecl(funcDecl, func, attr->getLocation(),
3655 attr->Clauses);
3656 }
3657 }
3658 return func;
3659}
3660
3661cir::FuncOp
3662CIRGenModule::createCIRBuiltinFunction(mlir::Location loc, StringRef name,
3663 cir::FuncType ty,
3664 const clang::FunctionDecl *fd) {
3665 cir::FuncOp fnOp = createCIRFunction(loc, name, ty, fd);
3666 fnOp.setBuiltin(true);
3667 return fnOp;
3668}
3669
3670static cir::CtorKind getCtorKindFromDecl(const CXXConstructorDecl *ctor) {
3671 if (ctor->isDefaultConstructor())
3672 return cir::CtorKind::Default;
3673 if (ctor->isCopyConstructor())
3674 return cir::CtorKind::Copy;
3675 if (ctor->isMoveConstructor())
3676 return cir::CtorKind::Move;
3677 return cir::CtorKind::Custom;
3678}
3679
3680static cir::AssignKind getAssignKindFromDecl(const CXXMethodDecl *method) {
3681 if (method->isCopyAssignmentOperator())
3682 return cir::AssignKind::Copy;
3683 if (method->isMoveAssignmentOperator())
3684 return cir::AssignKind::Move;
3685 llvm_unreachable("not a copy or move assignment operator");
3686}
3687
3688void CIRGenModule::setFuncInfoAttr(cir::FuncOp funcOp,
3689 const clang::FunctionDecl *funcDecl) {
3690 if (!funcDecl)
3691 return;
3692
3693 if (const auto *dtor = dyn_cast<CXXDestructorDecl>(funcDecl)) {
3694 auto cxxDtor = cir::CXXDtorAttr::get(
3695 convertType(getASTContext().getCanonicalTagType(dtor->getParent())),
3696 dtor->isTrivial());
3697 funcOp.setFuncInfoAttr(cxxDtor);
3698 return;
3699 }
3700
3701 if (const auto *ctor = dyn_cast<CXXConstructorDecl>(funcDecl)) {
3702 cir::CtorKind kind = getCtorKindFromDecl(ctor);
3703 auto cxxCtor = cir::CXXCtorAttr::get(
3704 convertType(getASTContext().getCanonicalTagType(ctor->getParent())),
3705 kind, ctor->isTrivial());
3706 funcOp.setFuncInfoAttr(cxxCtor);
3707 return;
3708 }
3709
3710 const auto *method = dyn_cast<CXXMethodDecl>(funcDecl);
3711 if (method && (method->isCopyAssignmentOperator() ||
3712 method->isMoveAssignmentOperator())) {
3713 cir::AssignKind assignKind = getAssignKindFromDecl(method);
3714 auto cxxAssign = cir::CXXAssignAttr::get(
3715 convertType(getASTContext().getCanonicalTagType(method->getParent())),
3716 assignKind, method->isTrivial());
3717 funcOp.setFuncInfoAttr(cxxAssign);
3718 return;
3719 }
3720
3721 // Otherwise tag a function that matches a known standard library entity. A
3722 // known entity is named by a plain identifier in std. For a member the
3723 // record decides std membership. Inline namespaces, like the versioning
3724 // namespace of libc++, count as part of std.
3725 if (!funcDecl->getIdentifier())
3726 return;
3727 bool inStdNamespace = method ? method->getParent()->isInStdNamespace()
3728 : funcDecl->isInStdNamespace();
3729 if (!inStdNamespace)
3730 return;
3731
3732 // The names and the tags come from CIRStdOps.td, and the recognizer checks
3733 // the shape of each call. Only free functions name a known entity today, so
3734 // a member like char_traits::find never shares the tag of the free std::find.
3735 std::optional<cir::KnownFuncKind> kind;
3736 if (!method) {
3737 kind = llvm::StringSwitch<std::optional<cir::KnownFuncKind>>(
3738 funcDecl->getName())
3739 .Case(cir::StdFindOp::getFunctionName(),
3740 cir::StdFindOp::getFuncKind())
3741 .Default(std::nullopt);
3742 }
3743 if (!kind)
3744 return;
3745
3746 funcOp.setFuncInfoAttr(cir::FuncIdentityAttr::get(&getMLIRContext(), *kind));
3747}
3748
3749static void setWindowsItaniumDLLImport(CIRGenModule &cgm, bool isLocal,
3750 cir::FuncOp funcOp, StringRef name) {
3751 // In Windows Itanium environments, try to mark runtime functions
3752 // dllimport. For Mingw and MSVC, don't. We don't really know if the user
3753 // will link their standard library statically or dynamically. Marking
3754 // functions imported when they are not imported can cause linker errors
3755 // and warnings.
3756 if (!isLocal && cgm.getTarget().getTriple().isWindowsItaniumEnvironment() &&
3757 !cgm.getCodeGenOpts().LTOVisibilityPublicStd) {
3761 }
3762}
3763
3764cir::FuncOp CIRGenModule::createRuntimeFunction(cir::FuncType ty,
3765 StringRef name,
3766 mlir::NamedAttrList extraAttrs,
3767 bool isLocal,
3768 bool assumeConvergent) {
3769 if (assumeConvergent)
3770 errorNYI("createRuntimeFunction: assumeConvergent");
3771
3772 cir::FuncOp entry = getOrCreateCIRFunction(name, ty, GlobalDecl(),
3773 /*forVtable=*/false, extraAttrs);
3774
3775 if (entry) {
3776 // TODO(cir): set the attributes of the function.
3779 setWindowsItaniumDLLImport(*this, isLocal, entry, name);
3780 entry.setDSOLocal(true);
3781 }
3782
3783 return entry;
3784}
3785
3786mlir::SymbolTable::Visibility
3788 // MLIR doesn't accept public symbols declarations (only
3789 // definitions).
3790 if (op.isDeclaration())
3791 return mlir::SymbolTable::Visibility::Private;
3792 return getMLIRVisibilityFromCIRLinkage(op.getLinkage());
3793}
3794
3795mlir::SymbolTable::Visibility
3797 switch (glk) {
3798 case cir::GlobalLinkageKind::InternalLinkage:
3799 case cir::GlobalLinkageKind::PrivateLinkage:
3800 return mlir::SymbolTable::Visibility::Private;
3801 case cir::GlobalLinkageKind::ExternalLinkage:
3802 case cir::GlobalLinkageKind::ExternalWeakLinkage:
3803 case cir::GlobalLinkageKind::LinkOnceODRLinkage:
3804 case cir::GlobalLinkageKind::AvailableExternallyLinkage:
3805 case cir::GlobalLinkageKind::CommonLinkage:
3806 case cir::GlobalLinkageKind::WeakAnyLinkage:
3807 case cir::GlobalLinkageKind::WeakODRLinkage:
3808 return mlir::SymbolTable::Visibility::Public;
3809 default: {
3810 llvm::errs() << "visibility not implemented for '"
3811 << stringifyGlobalLinkageKind(glk) << "'\n";
3812 assert(0 && "not implemented");
3813 }
3814 }
3815 llvm_unreachable("linkage should be handled above!");
3816}
3817
3819 clang::VisibilityAttr::VisibilityType visibility) {
3820 switch (visibility) {
3821 case clang::VisibilityAttr::VisibilityType::Default:
3822 return cir::VisibilityKind::Default;
3823 case clang::VisibilityAttr::VisibilityType::Hidden:
3824 return cir::VisibilityKind::Hidden;
3825 case clang::VisibilityAttr::VisibilityType::Protected:
3826 return cir::VisibilityKind::Protected;
3827 }
3828 llvm_unreachable("unexpected visibility value");
3829}
3830
3831cir::VisibilityAttr
3833 const clang::VisibilityAttr *va = decl->getAttr<clang::VisibilityAttr>();
3834 cir::VisibilityAttr cirVisibility =
3835 cir::VisibilityAttr::get(&getMLIRContext());
3836 if (va) {
3837 cirVisibility = cir::VisibilityAttr::get(
3838 &getMLIRContext(),
3839 getGlobalVisibilityKindFromClangVisibility(va->getVisibility()));
3840 }
3841 return cirVisibility;
3842}
3843
3845 emitDeferred();
3847 applyReplacements();
3848
3849 theModule->setAttr(cir::CIRDialect::getModuleLevelAsmAttrName(),
3850 builder.getArrayAttr(globalScopeAsm));
3851
3852 emitGlobalAnnotations();
3853
3854 if (!recordLayoutEntries.empty())
3855 theModule->setAttr(
3856 cir::CIRDialect::getRecordLayoutsAttrName(),
3857 mlir::DictionaryAttr::get(&getMLIRContext(), recordLayoutEntries));
3858
3859 if (getTriple().isAMDGPU() ||
3860 (getTriple().isSPIRV() && getTriple().getVendor() == llvm::Triple::AMD))
3862
3863 if (getLangOpts().HIP) {
3864 // Emit a unique ID so that host and device binaries from the same
3865 // compilation unit can be associated.
3866 std::string cuidName =
3867 ("__hip_cuid_" + getASTContext().getCUIDHash()).str();
3868 auto int8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/false);
3869 auto loc = builder.getUnknownLoc();
3870 mlir::ptr::MemorySpaceAttrInterface addrSpace =
3871 cir::LangAddressSpaceAttr::get(&getMLIRContext(),
3872 getGlobalVarAddressSpace(nullptr));
3873
3874 auto gv = createGlobalOp(loc, cuidName, int8Ty,
3875 /*isConstant=*/false, addrSpace);
3876 gv.setLinkage(cir::GlobalLinkageKind::ExternalLinkage);
3877 // Initialize with zero
3878 auto zeroAttr = cir::IntAttr::get(int8Ty, 0);
3879 gv.setInitialValueAttr(zeroAttr);
3880 // External linkage requires public visibility
3881 mlir::SymbolTable::setSymbolVisibility(
3882 gv, mlir::SymbolTable::Visibility::Public);
3883
3885 }
3886
3887 if (astContext.getLangOpts().CUDA && cudaRuntime)
3889
3890 emitLLVMUsed();
3891
3892 // Classic codegen calls `checkAliases` here to validate any alias
3893 // definitions emitted during codegen.
3895
3896 // There's a lot of code that is not implemented yet.
3898}
3899
3901 const auto *d = cast<ValueDecl>(gd.getDecl());
3902 const AliasAttr *aa = d->getAttr<AliasAttr>();
3903 assert(aa && "Not an alias?");
3904
3905 StringRef mangledName = getMangledName(gd);
3906
3907 if (aa->getAliasee() == mangledName) {
3908 diags.Report(aa->getLocation(), diag::err_cyclic_alias) << 0;
3909 return;
3910 }
3911
3912 // If there is a definition in the module, then it wins over the alias.
3913 // This is dubious, but allow it to be safe. Just ignore the alias.
3914 mlir::Operation *entry = getGlobalValue(mangledName);
3915 if (entry) {
3916 auto entryGV = mlir::dyn_cast<cir::CIRGlobalValueInterface>(entry);
3917 if (entryGV && entryGV.isDefinition())
3918 return;
3919 }
3920
3921 // Classic codegen pushes the alias onto an `Aliases` list at this point so
3922 // that `checkAliases` can later validate the alias and recover on error.
3924
3925 mlir::Location loc = getLoc(d->getSourceRange());
3926 bool isFunction = isa<FunctionDecl>(d);
3927
3928 // Get the linkage and the type of the alias.
3929 mlir::Type declTy;
3930 cir::GlobalLinkageKind linkage;
3931 if (isFunction) {
3932 declTy = getTypes().getFunctionType(gd);
3933 linkage = getFunctionLinkage(gd);
3934 } else {
3935 declTy = getTypes().convertTypeForMem(d->getType());
3936 const auto *vd = cast<VarDecl>(d);
3937 linkage = getCIRLinkageVarDefinition(vd);
3938 }
3939 //
3940 // Create the alias op.
3941 // TODO(cir): Make GlobalAlias a separate op.
3942 cir::CIRGlobalValueInterface alias =
3943 isFunction ? mlir::cast<cir::CIRGlobalValueInterface>(
3944 createCIRFunction(loc, mangledName,
3945 mlir::cast<cir::FuncType>(declTy),
3947 .getOperation())
3948 : mlir::cast<cir::CIRGlobalValueInterface>(
3949 createGlobalOp(loc, mangledName, declTy).getOperation());
3950
3951 // Create the alias op. If there is an existing declaration with the same
3952 // name, erase it: any references to it via flat symbol reference will
3953 // automatically resolve to the new alias.
3954 // However, function aliases actually change its type, so we have to replace
3955 // uses of it.
3956 if (entry) {
3957 if (isFunction)
3959 entry, mlir::cast<cir::FuncOp>(alias.getOperation()));
3960 eraseGlobalSymbol(entry);
3961 entry->erase();
3962 }
3963
3964 // Aliases that target weak symbols must themselves be marked weak.
3965 if (d->hasAttr<WeakAttr>() || d->hasAttr<WeakRefAttr>() ||
3966 d->isWeakImported())
3967 linkage = cir::GlobalLinkageKind::WeakAnyLinkage;
3968
3969 // Aliases are always definitions, so the MLIR visibility should match the
3970 // linkage rather than defaulting to private.
3971 mlir::SymbolTable::Visibility visibility =
3973
3974 alias.setAliasee(aa->getAliasee());
3975 alias.setLinkage(linkage);
3976 mlir::SymbolTable::setSymbolVisibility(alias, visibility);
3978 setCommonAttributes(gd, alias);
3980}
3981
3982void CIRGenModule::emitAliasForGlobal(StringRef mangledName,
3983 mlir::Operation *op, GlobalDecl aliasGD,
3984 cir::FuncOp aliasee,
3985 cir::GlobalLinkageKind linkage) {
3986
3987 auto *aliasFD = dyn_cast<FunctionDecl>(aliasGD.getDecl());
3988 assert(aliasFD && "expected FunctionDecl");
3989
3990 // The aliasee function type is different from the alias one, this difference
3991 // is specific to CIR because in LLVM the ptr types are already erased at this
3992 // point.
3993 const CIRGenFunctionInfo &fnInfo =
3995 cir::FuncType fnType = getTypes().getFunctionType(fnInfo);
3996
3997 cir::FuncOp alias =
3999 mangledName, fnType, aliasFD);
4000 alias.setAliasee(aliasee.getName());
4001 alias.setLinkage(linkage);
4002 // Declarations cannot have public MLIR visibility, just mark them private
4003 // but this really should have no meaning since CIR should not be using
4004 // this information to derive linkage information.
4005 mlir::SymbolTable::setSymbolVisibility(
4006 alias, mlir::SymbolTable::Visibility::Private);
4007
4008 // Alias constructors and destructors are always unnamed_addr.
4010
4011 if (op) {
4012 // Any existing users of the existing function declaration will be
4013 // referencing the function by flat symbol reference (i.e. the name), so
4014 // those uses will automatically resolve to the alias now that we've
4015 // replaced the function declaration. We can safely erase the existing
4016 // function declaration.
4017 assert(cast<cir::FuncOp>(op).getFunctionType() == alias.getFunctionType() &&
4018 "declaration exists with different type");
4020 op->erase();
4021 } else {
4022 // Name already set by createCIRFunction
4023 }
4024
4025 // Finally, set up the alias with its proper name and attributes.
4026 setCommonAttributes(aliasGD, alias);
4027}
4028
4030 return genTypes.convertType(type);
4031}
4032
4034 // Verify the module after we have finished constructing it, this will
4035 // check the structural properties of the IR and invoke any specific
4036 // verifiers we have on the CIR operations.
4037 return mlir::verify(theModule).succeeded();
4038}
4039
4040mlir::Attribute CIRGenModule::getAddrOfRTTIDescriptor(mlir::Location loc,
4041 QualType ty, bool forEh) {
4042 // Return a bogus pointer if RTTI is disabled, unless it's for EH.
4043 // FIXME: should we even be calling this method if RTTI is disabled
4044 // and it's not for EH?
4045 if (!shouldEmitRTTI(forEh))
4046 return builder.getConstNullPtrAttr(builder.getUInt8PtrTy());
4047
4048 if (forEh && ty->isObjCObjectPointerType() &&
4049 langOpts.ObjCRuntime.isGNUFamily()) {
4050 errorNYI(loc, "getAddrOfRTTIDescriptor: Objc PtrType & Objc RT GUN");
4051 return {};
4052 }
4053
4054 return getCXXABI().getAddrOfRTTIDescriptor(loc, ty);
4055}
4056
4057// TODO(cir): this can be shared with LLVM codegen.
4059 const CXXRecordDecl *derivedClass,
4060 llvm::iterator_range<CastExpr::path_const_iterator> path) {
4061 CharUnits offset = CharUnits::Zero();
4062
4063 const ASTContext &astContext = getASTContext();
4064 const CXXRecordDecl *rd = derivedClass;
4065
4066 for (const CXXBaseSpecifier *base : path) {
4067 assert(!base->isVirtual() && "Should not see virtual bases here!");
4068
4069 // Get the layout.
4070 const ASTRecordLayout &layout = astContext.getASTRecordLayout(rd);
4071
4072 const auto *baseDecl = base->getType()->castAsCXXRecordDecl();
4073
4074 // Add the offset.
4075 offset += layout.getBaseClassOffset(baseDecl);
4076
4077 rd = baseDecl;
4078 }
4079
4080 return offset;
4081}
4082
4084 llvm::StringRef feature) {
4085 unsigned diagID = diags.getCustomDiagID(
4086 DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0");
4087 return diags.Report(loc, diagID) << feature;
4088}
4089
4091 llvm::StringRef feature) {
4092 return errorNYI(loc.getBegin(), feature) << loc;
4093}
4094
4096 unsigned diagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error, "%0");
4097 getDiags().Report(astContext.getFullLoc(loc), diagID) << error;
4098}
4099
4100/// Print out an error that codegen doesn't support the specified stmt yet.
4101void CIRGenModule::errorUnsupported(const Stmt *s, llvm::StringRef type) {
4102 unsigned diagId = diags.getCustomDiagID(DiagnosticsEngine::Error,
4103 "cannot compile this %0 yet");
4104 diags.Report(astContext.getFullLoc(s->getBeginLoc()), diagId)
4105 << type << s->getSourceRange();
4106}
4107
4108/// Print out an error that codegen doesn't support the specified decl yet.
4109void CIRGenModule::errorUnsupported(const Decl *d, llvm::StringRef type) {
4110 unsigned diagId = diags.getCustomDiagID(DiagnosticsEngine::Error,
4111 "cannot compile this %0 yet");
4112 diags.Report(astContext.getFullLoc(d->getLocation()), diagId) << type;
4113}
4114
4115mlir::Operation *
4117 const Expr *init) {
4118 assert((mte->getStorageDuration() == SD_Static ||
4119 mte->getStorageDuration() == SD_Thread) &&
4120 "not a global temporary");
4121 const auto *varDecl = cast<VarDecl>(mte->getExtendingDecl());
4122
4123 // Use the MaterializeTemporaryExpr's type if it has the same unqualified
4124 // base type as Init. This preserves cv-qualifiers (e.g. const from a
4125 // constexpr or const-ref binding) that skipRValueSubobjectAdjustments may
4126 // have dropped via NoOp casts, while correctly falling back to Init's type
4127 // when a real subobject adjustment changed the type (e.g. member access or
4128 // base-class cast in C++98), where E->getType() reflects the reference type,
4129 // not the actual storage type.
4130 QualType materializedType = init->getType();
4131 if (getASTContext().hasSameUnqualifiedType(mte->getType(), materializedType))
4132 materializedType = mte->getType();
4133
4134 CharUnits align = getASTContext().getTypeAlignInChars(materializedType);
4135 mlir::Location loc = getLoc(mte->getSourceRange());
4136
4137 // FIXME: If an externally-visible declaration extends multiple temporaries,
4138 // we need to give each temporary the same name in every translation unit (and
4139 // we also need to make the temporaries externally-visible).
4141 llvm::raw_svector_ostream out(name);
4143 varDecl, mte->getManglingNumber(), out);
4144
4145 auto insertResult = materializedGlobalTemporaryMap.insert({mte, nullptr});
4146 if (!insertResult.second) {
4147 mlir::Type type = getTypes().convertTypeForMem(materializedType);
4148 // We've seen this before: either we already created it or we're in the
4149 // process of doing so.
4150 if (!insertResult.first->second) {
4151 // We recursively re-entered this function, probably during emission of
4152 // the initializer. Create a placeholder.
4153 insertResult.first->second =
4154 createGlobalOp(loc, name, type, /*isConstant=*/false);
4155 }
4156 return insertResult.first->second;
4157 }
4158
4159 APValue *value = nullptr;
4160 if (mte->getStorageDuration() == SD_Static && varDecl->evaluateValue()) {
4161 // If the initializer of the extending declaration is a constant
4162 // initializer, we should have a cached constant initializer for this
4163 // temporay. Note taht this m ight have a different value from the value
4164 // computed by evaluating the initializer if the surrounding constant
4165 // expression modifies the temporary.
4166 value = mte->getOrCreateValue(/*MayCreate=*/false);
4167 }
4168
4169 // Try evaluating it now, it might have a constant initializer
4170 Expr::EvalResult evalResult;
4171 if (!value && init->EvaluateAsRValue(evalResult, getASTContext()) &&
4172 !evalResult.hasSideEffects())
4173 value = &evalResult.Val;
4174
4176
4177 std::optional<ConstantEmitter> emitter;
4178 mlir::Attribute initialValue = nullptr;
4179 bool isConstant = false;
4180 mlir::Type type;
4181
4182 if (value) {
4183 emitter.emplace(*this);
4184 initialValue = emitter->emitForInitializer(*value, materializedType);
4185
4186 isConstant = materializedType.isConstantStorage(
4187 getASTContext(), /*ExcludeCtor=*/value, /*ExcludeDtor=*/false);
4188
4189 type = mlir::cast<mlir::TypedAttr>(initialValue).getType();
4190 } else {
4191 // No initializer, the initialization will be provided when we initialize
4192 // the declaration which performed lifetime extension.
4193 type = getTypes().convertTypeForMem(materializedType);
4194 }
4195
4196 // Create a global variable for this lifetime-extended temporary.
4197 cir::GlobalLinkageKind linkage = getCIRLinkageVarDefinition(varDecl);
4198 if (linkage == cir::GlobalLinkageKind::ExternalLinkage) {
4199 const VarDecl *initVD;
4200 if (varDecl->isStaticDataMember() && varDecl->getAnyInitializer(initVD) &&
4202 // Temporaries defined inside a class get linkonce_odr linkage because the
4203 // calss can be defined in multiple translation units.
4204 errorNYI(mte->getSourceRange(), "static data member initialization");
4205 } else {
4206 // There is no need for this temporary to have external linkage if the
4207 // VarDecl has external linkage.
4208 linkage = cir::GlobalLinkageKind::InternalLinkage;
4209 }
4210 }
4211 cir::GlobalOp gv = createGlobalOp(loc, name, type, isConstant);
4212 gv.setInitialValueAttr(initialValue);
4213 gv.setLinkage(linkage);
4214 gv.setVisibility(getMLIRVisibilityFromCIRLinkage(linkage));
4215
4216 if (emitter)
4217 emitter->finalize(gv);
4218 // Don't assign dllimport or dllexport to local linkage globals
4219 if (!gv.hasLocalLinkage()) {
4222 }
4223
4224 gv.setAlignment(align.getAsAlign().value());
4225 if (supportsCOMDAT() && gv.isWeakForLinker())
4226 gv.setComdat(true);
4227 if (varDecl->getTLSKind())
4228 setTLSMode(gv, *varDecl, /*isExtendingDecl=*/true);
4229 mlir::Operation *cv = gv;
4230
4232
4233 // Update the map with the new temporary. If we created a placeholder above,
4234 // erase it as well, the name will have been the same, so our symbol
4235 // references would have been correct. We still do a 'replaceAllUsesWith' in
4236 // case some sort of expression formed a reference to the placeholder
4237 // temporary.
4238 mlir::Operation *&entry = materializedGlobalTemporaryMap[mte];
4239 if (entry) {
4240 entry->replaceAllUsesWith(cv);
4241 eraseGlobalSymbol(entry);
4242 entry->erase();
4243 }
4244 entry = cv;
4245
4246 return cv;
4247}
4248
4250 const UnnamedGlobalConstantDecl *gcd) {
4251 unsigned numEntries = unnamedGlobalConstantDeclMap.size();
4252 cir::GlobalOp *globalOpEntry = &unnamedGlobalConstantDeclMap[gcd];
4253
4254 if (*globalOpEntry)
4255 return *globalOpEntry;
4256
4257 ConstantEmitter emitter(*this);
4258
4259 const APValue &value = gcd->getValue();
4260 assert(!value.isAbsent());
4262 "emitForInitializer should take gcd->getType().getAddressSpace()");
4263 mlir::Attribute init = emitter.emitForInitializer(value, gcd->getType());
4264 auto typedInit = dyn_cast<mlir::TypedAttr>(init);
4265
4266 if (!typedInit)
4267 errorNYI(gcd->getSourceRange(),
4268 "getAddrOfUnnamedGlobalConstantDecl: non-typed initializer");
4269
4271
4272 // Classic codegen always creates these with .constant, then counts on the
4273 // auto-addition of '.#'. CIR global doesn't have this, so we'll just auto-add
4274 // one if this isn't the first. We could probably choose a better name than
4275 // .constant to be unique for this type of decl, but this is consistent with
4276 // classic codegen.
4277 std::string name = numEntries == 0
4278 ? ".constant"
4279 : (Twine(".constant.") + Twine(numEntries)).str();
4280 auto globalOp = createGlobalOp(builder.getUnknownLoc(), name,
4281 typedInit.getType(), /*is_constant=*/true);
4282 globalOp.setLinkage(cir::GlobalLinkageKind::PrivateLinkage);
4283
4284 CharUnits alignment = getASTContext().getTypeAlignInChars(gcd->getType());
4285 globalOp.setAlignment(alignment.getAsAlign().value());
4286 CIRGenModule::setInitializer(globalOp, init);
4287
4288 emitter.finalize(globalOp);
4289 *globalOpEntry = globalOp;
4290 return globalOp;
4291}
4292
4293cir::GlobalOp
4295 StringRef name = getMangledName(tpo);
4296 CharUnits alignment = getNaturalTypeAlignment(tpo->getType());
4297
4298 if (auto globalOp =
4299 mlir::dyn_cast_or_null<cir::GlobalOp>(getGlobalValue(name)))
4300 return globalOp;
4301
4302 ConstantEmitter emitter(*this);
4304 "emitForInitializer should take tpo->getType().getAddressSpace()");
4305 mlir::Attribute init =
4306 emitter.emitForInitializer(tpo->getValue(), tpo->getType());
4307
4308 if (!init) {
4309 errorUnsupported(tpo, "template parameter object");
4310 return {};
4311 }
4312
4313 mlir::TypedAttr typedInit = cast<mlir::TypedAttr>(init);
4314
4315 cir::GlobalLinkageKind linkage =
4317 ? cir::GlobalLinkageKind::LinkOnceODRLinkage
4318 : cir::GlobalLinkageKind::InternalLinkage;
4319
4321 auto globalOp = createGlobalOp(builder.getUnknownLoc(), name,
4322 typedInit.getType(), /*is_constant=*/true);
4323 globalOp.setLinkage(linkage);
4324 globalOp.setAlignment(alignment.getAsAlign().value());
4325 globalOp.setComdat(supportsCOMDAT() &&
4326 linkage == cir::GlobalLinkageKind::LinkOnceODRLinkage);
4327
4328 CIRGenModule::setInitializer(globalOp, init);
4329 emitter.finalize(globalOp);
4330
4331 insertGlobalSymbol(globalOp);
4332
4333 return globalOp;
4334}
4335
4336//===----------------------------------------------------------------------===//
4337// Annotations
4338//===----------------------------------------------------------------------===//
4339
4340mlir::ArrayAttr
4341CIRGenModule::getOrCreateAnnotationArgs(const AnnotateAttr *attr) {
4342 ArrayRef<Expr *> exprs = {attr->args_begin(), attr->args_size()};
4343 // Return a null attr for no-args annotations so OptionalParameter omits
4344 // the args portion entirely from the printed IR.
4345 if (exprs.empty())
4346 return {};
4347
4348 llvm::FoldingSetNodeID id;
4349 for (Expr *e : exprs)
4350 id.Add(cast<clang::ConstantExpr>(e)->getAPValueResult());
4351
4352 mlir::ArrayAttr &lookup = annotationArgs[id.ComputeHash()];
4353 if (lookup)
4354 return lookup;
4355
4357 args.reserve(exprs.size());
4358 for (Expr *e : exprs) {
4359 if (auto *strE = dyn_cast<clang::StringLiteral>(e->IgnoreParenCasts())) {
4360 args.push_back(builder.getStringAttr(strE->getString()));
4361 } else if (auto *intE =
4362 dyn_cast<clang::IntegerLiteral>(e->IgnoreParenCasts())) {
4363 auto intTy = builder.getIntegerType(intE->getValue().getBitWidth());
4364 args.push_back(builder.getIntegerAttr(intTy, intE->getValue()));
4365 } else {
4366 errorNYI(e->getExprLoc(), "annotation argument expression");
4367 }
4368 }
4369
4370 return lookup = builder.getArrayAttr(args);
4371}
4372
4373cir::AnnotationAttr CIRGenModule::emitAnnotateAttr(const AnnotateAttr *aa) {
4374 mlir::StringAttr annoGV = builder.getStringAttr(aa->getAnnotation());
4375 mlir::ArrayAttr args = getOrCreateAnnotationArgs(aa);
4376 return cir::AnnotationAttr::get(&getMLIRContext(), annoGV, args);
4377}
4378
4380 mlir::Operation *gv) {
4381 assert(d->hasAttr<AnnotateAttr>() && "no annotate attribute");
4382 assert((isa<cir::GlobalOp>(gv) || isa<cir::FuncOp>(gv)) &&
4383 "annotation only on globals");
4385 for (const auto *i : d->specific_attrs<AnnotateAttr>())
4386 annotations.push_back(emitAnnotateAttr(i));
4387 if (auto global = dyn_cast<cir::GlobalOp>(gv))
4388 global.setAnnotationsAttr(builder.getArrayAttr(annotations));
4389 else if (auto func = dyn_cast<cir::FuncOp>(gv))
4390 func.setAnnotationsAttr(builder.getArrayAttr(annotations));
4391}
4392
4393void CIRGenModule::emitGlobalAnnotations() {
4394 for (const auto &[mangledName, vd] : deferredAnnotations) {
4395 mlir::Operation *gv = getGlobalValue(mangledName);
4396 if (gv)
4397 addGlobalAnnotations(vd, gv);
4398 }
4399 deferredAnnotations.clear();
4400}
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 cir::LangAddressSpace getOpenCLKernelArgAddressSpace(LangAS addressSpace)
static bool shouldBeInCOMDAT(CIRGenModule &cgm, const Decl &d)
static mlir::Attribute getNewInitValue(CIRGenModule &cgm, cir::GlobalOp newGlob, mlir::Type oldTy, mlir::Attribute oldInit)
static bool hasUnwindExceptions(const LangOptions &langOpts)
Determines whether the language options require us to model unwind exceptions.
static void setWindowsItaniumDLLImport(CIRGenModule &cgm, bool isLocal, cir::FuncOp funcOp, StringRef name)
static std::string getMangledNameImpl(CIRGenModule &cgm, GlobalDecl gd, const NamedDecl *nd)
static llvm::SmallVector< int64_t > indexesOfArrayAttr(mlir::ArrayAttr indexes)
static bool isViewOnGlobal(cir::GlobalOp glob, cir::GlobalViewAttr view)
static void setLinkageForFunction(CIRGenModule &cgm, cir::FuncOp &func, 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 std::vector< std::string > getFeatureDeltaFromDefault(const CIRGenModule &cgm, llvm::StringRef targetCPU, llvm::StringMap< bool > &featureMap)
Get the feature delta from the default feature map for the given target CPU.
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 bool verifyPointerTypeArgs(cir::FuncOp oldF, cir::FuncOp newF, mlir::SymbolUserMap &userMap)
static cir::CtorKind getCtorKindFromDecl(const CXXConstructorDecl *ctor)
static void emitUsed(CIRGenModule &cgm, StringRef name, std::vector< cir::CIRGlobalValueInterface > &list)
static cir::TLSModel getCIRTLSModel(StringRef S)
static cir::GlobalViewAttr createNewGlobalView(CIRGenModule &cgm, cir::GlobalOp newGlob, cir::GlobalViewAttr attr, mlir::Type oldTy)
This file defines OpenACC nodes for declarative directives.
static constexpr bool needsDtor()
TokenType getType() const
Returns the token's type, e.g.
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
Defines the SourceManager interface.
This file defines OpenMP AST classes for executable directives and clauses.
cir::GlobalViewAttr getGlobalViewAttr(cir::GlobalOp globalOp, mlir::ArrayAttr indices={})
Get constant address of a global variable as an MLIR attribute.
cir::PointerType getPointerTo(mlir::Type ty)
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Definition APValue.h:122
bool isAbsent() const
Definition APValue.h:484
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:223
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...
StringRef getCUIDHash() const
void Deallocate(void *Ptr) const
Definition ASTContext.h:904
GVALinkage GetGVALinkageForFunction(const FunctionDecl *FD) const
bool isSameEntity(const NamedDecl *X, const NamedDecl *Y) const
Determine whether the two declarations refer to the same entity.
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.
const clang::PrintingPolicy & getPrintingPolicy() const
Definition ASTContext.h:877
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.
DiagnosticsEngine & getDiagnostics() const
const TargetInfo & getTargetInfo() const
Definition ASTContext.h:943
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.
mlir::Attribute getConstRecordOrZeroAttr(mlir::ArrayAttr arrayAttr, cir::RecordType recordTy)
uint64_t computeOffsetFromGlobalViewIndices(const cir::CIRDataLayout &layout, mlir::Type ty, llvm::ArrayRef< int64_t > indices)
void computeGlobalViewIndicesFromFlatOffset(int64_t offset, mlir::Type ty, cir::CIRDataLayout layout, llvm::SmallVectorImpl< int64_t > &indices)
cir::ConstArrayAttr getConstArray(mlir::Attribute attrs, cir::ArrayType arrayTy) const
virtual void handleGlobalReplace(cir::GlobalOp oldGV, cir::GlobalOp newGV)
virtual mlir::Operation * getKernelHandle(cir::FuncOp fn, GlobalDecl gd)=0
virtual void finalizeModule()
Perform module finalization: on device side, mark ODR-used device variables as compiler-used.
virtual void internalizeDeviceSideVar(const VarDecl *d, cir::GlobalLinkageKind &linkage)=0
Adjust linkage of shadow variables in host compilation.
virtual void handleVarRegistration(const VarDecl *vd, cir::GlobalOp var)=0
Check whether a variable is a device variable and register it if true.
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
cir::FuncOp generateCode(clang::GlobalDecl gd, cir::FuncOp fn, cir::FuncType funcType)
void emitVariablyModifiedType(QualType ty)
This class organizes the cross-function state that is used while generating CIR code.
cir::GlobalOp getAddrOfUnnamedGlobalConstantDecl(const UnnamedGlobalConstantDecl *gcd)
void setGlobalVisibility(cir::CIRGlobalValueInterface gv, const NamedDecl *d) const
Set the visibility for the given global.
void addUsedOrCompilerUsedGlobal(cir::CIRGlobalValueInterface gv)
Add a global to a list to be added to the llvm.compiler.used metadata.
void setFuncInfoAttr(cir::FuncOp funcOp, const clang::FunctionDecl *funcDecl)
Record the func_info tag for a function, either a C++ special member form (constructor,...
void replaceUsesOfNonProtoTypeWithRealFunction(mlir::Operation *old, cir::FuncOp newFn)
This function is called when we implement a function with no prototype, e.g.
bool shouldEmitFunction(clang::GlobalDecl gd)
Check if fd ends up calling itself directly through asm label or builtin-pointer-to-self trickery (e....
llvm::StringRef getMangledName(clang::GlobalDecl gd)
CharUnits computeNonVirtualBaseClassOffset(const CXXRecordDecl *derivedClass, llvm::iterator_range< CastExpr::path_const_iterator > path)
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.
cir::GlobalLinkageKind getCIRLinkageVarDefinition(const VarDecl *vd)
clang::ASTContext & getASTContext() const
void insertGlobalSymbol(mlir::Operation *op)
cir::FuncOp getAddrOfCXXStructor(clang::GlobalDecl gd, const CIRGenFunctionInfo *fnInfo=nullptr, cir::FuncType fnType=nullptr, bool dontDefer=false, ForDefinition_t isForDefinition=NotForDefinition)
CIRGenCUDARuntime & getCUDARuntime()
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.
std::vector< cir::CIRGlobalValueInterface > llvmUsed
List of global values which are required to be present in the object file; This is used for forcing v...
void emitOMPCapturedExpr(const OMPCapturedExprDecl *d)
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)
cir::TLSModel getDefaultCIRTLSModel() const
Get TLS mode from CodeGenOptions.
void setGlobalTlsReferences(const VarDecl &vd, cir::GlobalOp globalOp)
void emitOpenCLKernelArgMetadata(cir::FuncOp func, const clang::FunctionDecl *fd)
Generate OpenCL kernel argument metadata for a kernel function.
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.
cir::GlobalOp getAddrOfTemplateParamObject(const TemplateParamObjectDecl *tpo)
Get the GlobalOp of a template parameter object.
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.
llvm::DenseMap< const UnnamedGlobalConstantDecl *, cir::GlobalOp > unnamedGlobalConstantDeclMap
std::vector< cir::CIRGlobalValueInterface > llvmCompilerUsed
void emitOMPRequiresDecl(const OMPRequiresDecl *d)
void emitGlobalDefinition(clang::GlobalDecl gd, mlir::Operation *op=nullptr)
clang::DiagnosticsEngine & getDiags() const
cir::GlobalLinkageKind getCIRLinkageForDeclarator(const DeclaratorDecl *dd, GVALinkage linkage)
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)
void emitAliasDefinition(GlobalDecl gd)
Emit a definition for an __attribute__((alias)) declaration.
void addUsedGlobal(cir::CIRGlobalValueInterface gv)
Add a global value to the llvmUsed list.
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)
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)
std::optional< llvm::SmallVector< int32_t > > buildMemberPath(const CXXRecordDecl *destClass, const FieldDecl *field)
Build a GEP-style field-index path from destClass to field.
void emitLLVMUsed()
Emit llvm.used and llvm.compiler.used globals.
mlir::Value emitMemberPointerConstant(const UnaryOperator *e)
void emitGlobalOpenACCDecl(const clang::OpenACCConstructDecl *cd)
void setTLSMode(mlir::Operation *op, const VarDecl &d, bool isExtendingDecl=false)
Set TLS mode for the given operation based on the given variable declaration.
void emitExplicitCastExprType(const ExplicitCastExpr *e, CIRGenFunction *cgf=nullptr)
Emit type info if type of an expression is a variably modified type.
const cir::CIRDataLayout getDataLayout() const
void eraseGlobalSymbol(mlir::Operation *op)
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.
llvm::StringMap< mlir::Operation * > symbolLookupCache
Cache for O(1) symbol lookups by name, replacing the O(N) linear scan in SymbolTable::lookupSymbolIn ...
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 printPostfixForExternalizedDecl(llvm::raw_ostream &os, const Decl *d)
Print the postfix for externalized static variable or kernels for single source offloading languages ...
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::GlobalOp createGlobalOp(mlir::Location loc, llvm::StringRef name, mlir::Type t, bool isConstant=false, mlir::ptr::MemorySpaceAttrInterface addrSpace={}, mlir::Operation *insertPoint=nullptr)
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)
static cir::VisibilityKind getCIRVisibilityKind(Visibility v)
void setGVPropertiesAux(mlir::Operation *op, const NamedDecl *d) const
LangAS getLangTempAllocaAddressSpace() const
Returns the address space for temporary allocations in the language.
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
mlir::TypedAttr emitNullMemberAttr(QualType t, const MemberPointerType *mpt)
Returns a null attribute to represent either a null method or null data member, depending on the type...
mlir::Operation * getGlobalValue(llvm::StringRef ref)
void emitOMPDeclareReduction(const OMPDeclareReductionDecl *d)
mlir::ModuleOp getModule() const
void addCompilerUsedGlobal(cir::CIRGlobalValueInterface gv)
Add a global value to the llvmCompilerUsed list.
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.
mlir::MLIRContext & getMLIRContext()
void emitSYCLKernelCaller(const clang::FunctionDecl *kernelEntryPointFn, clang::ASTContext &ctx)
Emit the SYCL kernel caller offload entry point function generated for a function declared with the s...
mlir::Operation * getAddrOfGlobal(clang::GlobalDecl gd, ForDefinition_t isForDefinition=NotForDefinition)
void maybeSetTrivialComdat(const clang::Decl &d, mlir::Operation *op)
bool isEmptyFieldForMemberPointer(const FieldDecl *field)
Returns true if field is an empty field that isn't laid out in the CIR record (e.g.
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.
bool lookupRepresentativeDecl(llvm::StringRef mangledName, clang::GlobalDecl &gd) const
void emitDeclContext(const DeclContext *dc)
clang::CharUnits getNaturalPointeeTypeAlignment(clang::QualType t, LValueBaseInfo *baseInfo=nullptr)
void emitGlobal(clang::GlobalDecl gd)
Emit code for a single global function or variable declaration.
bool mayBeEmittedEagerly(const clang::ValueDecl *d)
Determine whether the definition can be emitted eagerly, or should be delayed until the end of the tr...
void addGlobalAnnotations(const clang::ValueDecl *d, mlir::Operation *gv)
Add global annotations for a global value (GlobalOp or FuncOp).
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)
CIRGenOpenMPRuntime & getOpenMPRuntime()
void emitAMDGPUMetadata()
Emits AMDGPU specific Metadata.
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,...
void emitDeclareTargetFunction(const FunctionDecl *fd, cir::FuncOp funcOp)
If the function has an OMPDeclareTargetDeclAttr, set the corresponding omp.declare_target attribute o...
This class handles record and union layout info while lowering AST types to CIR types.
bool hasNonVirtualBaseCIRField(const CXXRecordDecl *rd) const
unsigned getCIRFieldNo(const clang::FieldDecl *fd) const
Return cir::RecordType element number that corresponds to the field FD.
bool isZeroInitializable() const
Check whether this struct can be C++ zero-initialized with a zeroinitializer.
unsigned getNonVirtualBaseCIRFieldNo(const CXXRecordDecl *rd) const
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.
const CIRGenRecordLayout & getCIRGenRecordLayout(const clang::RecordDecl *rd)
Return record layout info for the given record decl.
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.
mlir::Attribute emitForInitializer(const APValue &value, QualType destType)
virtual clang::LangAS getGlobalVarAddressSpace(CIRGenModule &cgm, const clang::VarDecl *d) const
Get target favored AST address space of a global variable for languages other than OpenCL and CUDA.
virtual mlir::ptr::MemorySpaceAttrInterface getCIRAllocaAddressSpace() const
Get the address space for alloca.
Definition TargetInfo.h:76
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:152
Represents a base class of a C++ class.
Definition DeclCXX.h:146
Represents a C++ constructor within a class.
Definition DeclCXX.h:2637
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:3063
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:3058
bool isDefaultConstructor() const
Whether this constructor is a default constructor (C++ [class.ctor]p5), which can be used to default-...
Definition DeclCXX.cpp:3049
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2145
bool isMoveAssignmentOperator() const
Determine whether this is a move assignment operator.
Definition DeclCXX.cpp:2751
bool isCopyAssignmentOperator() const
Determine whether this is a copy-assignment operator, regardless of whether it was declared implicitl...
Definition DeclCXX.cpp:2730
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:2341
base_class_range bases()
Definition DeclCXX.h:608
bool hasDefinition() const
Definition DeclCXX.h:561
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
Definition CharUnits.h:189
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:3874
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1466
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Definition DeclBase.h:2403
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
bool isInStdNamespace() const
Definition DeclBase.cpp:453
T * getAttr() const
Definition DeclBase.h:581
bool isWeakImported() const
Determine whether this is a weak-imported symbol.
Definition DeclBase.cpp:876
bool isInExportDeclContext() const
Whether this declaration was exported in a lexical context.
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:567
SourceLocation getLocation() const
Definition DeclBase.h:447
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
Definition DeclBase.h:935
bool hasAttr() const
Definition DeclBase.h:585
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition DeclBase.h:435
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:234
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:926
ExplicitCastExpr - An explicit cast written in the source code.
Definition Expr.h:3948
This represents one expression.
Definition Expr.h:113
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:145
Represents a member of a struct/union/class.
Definition Decl.h:3294
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
Definition Decl.h:3379
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Definition Decl.h:3530
bool isPotentiallyOverlapping() const
Determine if this field is of potentially-overlapping class type, that is, subobject with the [[no_un...
Definition Decl.cpp:4868
Cached information about one file (either on disk or in the virtual file system).
Definition FileEntry.h:273
StringRef tryGetRealPathName() const
Definition FileEntry.h:298
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:2058
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:2302
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2904
bool hasPrototype() const
Whether this function has a prototype, either because one was explicitly written or because it was "i...
Definition Decl.h:2569
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
FunctionDecl * getDefinition()
Get the definition for this declaration.
Definition Decl.h:2395
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
Definition Decl.cpp:3188
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4617
CallingConv getCallConv() const
Definition TypeBase.h:4972
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:60
CXXCtorType getCtorType() const
Definition GlobalDecl.h:117
GlobalDecl getCanonicalDecl() const
Definition GlobalDecl.h:106
KernelReferenceKind getKernelReferenceKind() const
Definition GlobalDecl.h:142
GlobalDecl getWithDecl(const Decl *D)
Definition GlobalDecl.h:170
unsigned getMultiVersionIndex() const
Definition GlobalDecl.h:134
CXXDtorType getDtorType() const
Definition GlobalDecl.h:122
const Decl * getDecl() const
Definition GlobalDecl.h:115
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...
clang::ObjCRuntime ObjCRuntime
std::string CUID
The user provided compilation unit ID, if non-empty.
Visibility getVisibility() const
Definition Visibility.h:89
void setLinkage(Linkage L)
Definition Visibility.h:92
Linkage getLinkage() const
Definition Visibility.h:88
bool isVisibilityExplicit() const
Definition Visibility.h:90
MangleContext - Context for tracking state which persists across multiple calls to the C++ name mangl...
Definition Mangle.h:56
bool isTriviallyRecursive(const FunctionDecl *FD)
Return true if FD's body contains a direct call back to the symbol it links as, through an asm label ...
Definition Mangle.cpp:198
bool shouldMangleDeclName(const NamedDecl *D)
Definition Mangle.cpp:129
void mangleName(GlobalDecl GD, raw_ostream &)
Definition Mangle.cpp:245
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:4971
StorageDuration getStorageDuration() const
Retrieve the storage duration for the materialized temporary.
Definition ExprCXX.h:4996
APValue * getOrCreateValue(bool MayCreate) const
Get the storage for the constant value of a materialized temporary of static storage duration.
Definition ExprCXX.h:5004
ValueDecl * getExtendingDecl()
Get the declaration which triggered the lifetime-extension of this temporary, if any.
Definition ExprCXX.h:5021
unsigned getManglingNumber() const
Definition ExprCXX.h:5032
A pointer to member type per C++ 8.3.3 - Pointers to members.
Definition TypeBase.h:3767
CXXRecordDecl * getMostRecentCXXRecordDecl() const
Note: this can trigger extra deserialization when external AST sources are used.
Definition Type.cpp:5703
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:1228
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:301
bool hasUnwindExceptions() const
Does this runtime use zero-cost exceptions?
Represents a parameter to a function.
Definition Decl.h:1819
void setScopeInfo(unsigned scopeDepth, unsigned parameterIndex)
Definition Decl.h:1852
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:2945
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:938
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
Definition TypeBase.h:8586
LangAS getAddressSpace() const
Return the address space of this type.
Definition TypeBase.h:8628
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8542
QualType getCanonicalType() const
Definition TypeBase.h:8554
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition TypeBase.h:8575
bool isConstantStorage(const ASTContext &Ctx, bool ExcludeCtor, bool ExcludeDtor)
Definition TypeBase.h:1037
bool hasUnaligned() const
Definition TypeBase.h:512
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:85
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:355
StringLiteral - This represents a string literal expression, e.g.
Definition Expr.h:1819
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Expr.h:1993
unsigned getLength() const
Definition Expr.h:1929
uint32_t getCodeUnit(size_t i) const
Definition Expr.h:1902
StringRef getString() const
Definition Expr.h:1887
unsigned getCharByteWidth() const
Definition Expr.h:1930
Represents the declaration of a struct/union/class/enum.
Definition Decl.h:3851
bool isUnion() const
Definition Decl.h:4062
bool isMicrosoft() const
Is this ABI an MSVC-compatible ABI?
TargetOptions & getTargetOpts() const
Retrieve the target options.
Definition TargetInfo.h:332
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
bool isReadOnlyFeature(StringRef Feature) const
Determine whether the given target feature is read only.
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
virtual ParsedTargetAttr parseTargetAttr(StringRef Str) const
virtual bool initFeatureMap(llvm::StringMap< bool > &Features, DiagnosticsEngine &Diags, StringRef CPU, const std::vector< std::string > &FeatureVec) const
Initialize the map with the default set of target features for the CPU this should include all legal ...
std::vector< std::string > Features
The list of target specific features to enable or disable – this should be a list of strings starting...
std::string TuneCPU
If given, the name of the target CPU to tune code for.
std::string CPU
If given, the name of the target CPU to generate code for.
A template parameter object.
const APValue & getValue() const
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:8838
bool isPointerType() const
Definition TypeBase.h:8739
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9405
bool isReferenceType() const
Definition TypeBase.h:8763
bool isCUDADeviceBuiltinSurfaceType() const
Check if the type is the CUDA device builtin surface type.
Definition Type.cpp:5510
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:789
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition TypeBase.h:2877
bool isCUDADeviceBuiltinTextureType() const
Check if the type is the CUDA device builtin texture type.
Definition Type.cpp:5519
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
Definition Type.cpp:2559
bool isObjCObjectPointerType() const
Definition TypeBase.h:8918
bool isMemberFunctionPointerType() const
Definition TypeBase.h:8824
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9338
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition Expr.h:2264
Expr * getSubExpr() const
Definition Expr.h:2305
An artificial decl, representing a global anonymous constant value which is uniquified by value withi...
Definition DeclCXX.h:4485
const APValue & getValue() const
Definition DeclCXX.h:4511
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:932
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
Definition Decl.h:1593
TLSKind getTLSKind() const
Definition Decl.cpp:2150
bool hasInit() const
Definition Decl.cpp:2380
DefinitionKind isThisDeclarationADefinition(ASTContext &) const
Check whether this declaration is a definition.
Definition Decl.cpp:2242
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:2172
bool hasFlexibleArrayInit(const ASTContext &Ctx) const
Whether this variable has a flexible array member initialized with one or more elements.
Definition Decl.cpp:2834
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition Decl.h:1247
bool hasConstantInitialization() const
Determine whether this variable has constant initialization.
Definition Decl.cpp:2641
VarDecl * getDefinition(ASTContext &)
Get the real (not just tentative) definition for this declaration.
Definition Decl.cpp:2348
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
Definition Decl.h:1214
QualType::DestructionKind needsDestruction(const ASTContext &Ctx) const
Would the destruction of this variable have any effect, and if so, what kind?
Definition Decl.cpp:2823
const Expr * getInit() const
Definition Decl.h:1391
bool hasExternalStorage() const
Returns true if a variable has extern or private_extern storage.
Definition Decl.h:1238
@ TLS_None
Not a TLS variable.
Definition Decl.h:952
@ DeclarationOnly
This declaration is only a declaration.
Definition Decl.h:1318
@ Definition
This declaration is definitely a definition.
Definition Decl.h:1324
DefinitionKind hasDefinition(ASTContext &) const
Check whether this variable is defined in this translation unit.
Definition Decl.cpp:2357
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:2751
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Definition Decl.h:1381
bool isMatchingAddressSpace(mlir::ptr::MemorySpaceAttrInterface cirAS, clang::LangAS as)
mlir::ptr::MemorySpaceAttrInterface toCIRAddressSpaceAttr(mlir::MLIRContext &ctx, clang::LangAS langAS)
Convert an AST LangAS to the appropriate CIR address space attribute interface.
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)
Definition NVPTX.cpp:123
CIRGenCXXABI * CreateCIRGenItaniumCXXABI(CIRGenModule &cgm)
Creates and Itanium-family ABI.
std::unique_ptr< TargetCIRGenInfo > createX8664TargetCIRGenInfo(CIRGenTypes &cgt)
std::unique_ptr< TargetCIRGenInfo > createSPIRVTargetCIRGenInfo(CIRGenTypes &cgt)
Definition SPIRV.cpp:60
bool isEmptyFieldForLayout(const ASTContext &context, const FieldDecl *fd)
isEmptyFieldForLayout - Return true if the field is "empty", that is, either a zero-width bit-field o...
std::unique_ptr< TargetCIRGenInfo > createAArch64TargetCIRGenInfo(CIRGenTypes &cgt)
Definition AArch64.cpp:117
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.
Top level wrappers for InstallAPI frontend operations.
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
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ SC_None
Definition Specifiers.h:251
@ SD_Thread
Thread storage duration.
Definition Specifiers.h:341
@ SD_Static
Static storage duration.
Definition Specifiers.h:342
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:189
@ TSK_ExplicitInstantiationDefinition
This template specialization was instantiated from a template due to an explicit instantiation defini...
Definition Specifiers.h:207
@ TSK_ImplicitInstantiation
This template specialization was implicitly instantiated from a template.
Definition Specifiers.h:195
@ CC_X86RegCall
Definition Specifiers.h:288
U cast(CodeGen::Address addr)
Definition Address.h:327
bool isExternallyVisible(Linkage L)
Definition Linkage.h:90
@ HiddenVisibility
Objects with "hidden" visibility are not seen by the dynamic linker.
Definition Visibility.h:37
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 int32_t
static bool globalCtorLexOrder()
static bool opFuncArmNewAttr()
static bool getRuntimeFunctionDecl()
static bool weakRefReference()
static bool opFuncOptNoneAttr()
static bool addressSpace()
static bool opFuncMinSizeAttr()
static bool opGlobalUnnamedAddr()
static bool opGlobalThreadLocal()
static bool opFuncMultiVersioning()
static bool sourceLanguageCases()
static bool shouldSkipAliasEmission()
static bool opFuncAstDeclAttr()
static bool opFuncNoDuplicateAttr()
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 attributeNoBuiltin()
static bool opGlobalDLLImportExport()
static bool opGlobalPartition()
static bool opGlobalPragmaClangSection()
static bool opGlobalWeakRef()
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 checkAliases()
static bool generateDebugInfo()
static bool targetCIRGenInfoOS()
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:666
APValue Val
Val - This is the value the expression can be folded to.
Definition Expr.h:668
bool hasSideEffects() const
Return true if the evaluated expression has side effects.
Definition Expr.h:660
Describes how types, statements, expressions, and declarations should be printed.