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