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