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