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