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