clang 24.0.0git
CIRGenModule.cpp
Go to the documentation of this file.
1//===- CIRGenModule.cpp - Per-Module state for CIR generation -------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This is the internal per-translation-unit state used for CIR translation.
10//
11//===----------------------------------------------------------------------===//
12
13#include "CIRGenModule.h"
14#include "CIRGenCUDARuntime.h"
15#include "CIRGenCXXABI.h"
17#include "CIRGenFunction.h"
18
19#include "mlir/Dialect/OpenMP/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::amdgpu: {
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 // ConstArrayAttr::verify guarantees the elements are either an ArrayAttr or
1067 // a StringAttr. A StringAttr is a string-literal initializer: raw 8-bit
1068 // character bytes with no nested global references, so there is nothing to
1069 // rewrite and it is returned unchanged. The ArrayAttr case recurses to
1070 // rewrite any nested global views.
1071 mlir::Attribute oldElts = oldArray.getElts();
1072 if (mlir::isa<mlir::StringAttr>(oldElts))
1073 return oldInit;
1074 mlir::Attribute newElements =
1075 getNewInitElements(mlir::cast<mlir::ArrayAttr>(oldElts));
1076 return cgm.getBuilder().getConstArray(
1077 newElements, mlir::cast<cir::ArrayType>(oldArray.getType()));
1078 }
1079 if (auto oldRecord = mlir::dyn_cast<cir::ConstRecordAttr>(oldInit)) {
1080 mlir::ArrayAttr newMembers = getNewInitElements(oldRecord.getMembers());
1081 auto recordTy = mlir::cast<cir::RecordType>(oldRecord.getType());
1083 newMembers, recordTy.getPacked(), recordTy.getPadded(), recordTy);
1084 }
1085
1086 // This may be unreachable in practice, but keep it as errorNYI while CIR
1087 // is still under development.
1088 cgm.errorNYI("Unhandled type in getNewInitValue");
1089 return {};
1090}
1091
1092// We want to replace a global value, but because of CIR's typed pointers,
1093// we need to update the existing uses to reflect the new type, not just replace
1094// them directly.
1095void CIRGenModule::replaceGlobal(cir::GlobalOp oldGV, cir::GlobalOp newGV) {
1096 assert(oldGV.getSymName() == newGV.getSymName() && "symbol names must match");
1097
1098 mlir::Type oldTy = oldGV.getSymType();
1099 mlir::Type newTy = newGV.getSymType();
1100
1102
1103 // If the type didn't change, why are we here?
1104 assert(oldTy != newTy && "expected type change in replaceGlobal");
1105
1106 // Visit all uses and add handling to fix up the types.
1107 std::optional<mlir::SymbolTable::UseRange> oldSymUses =
1108 oldGV.getSymbolUses(theModule);
1109 for (mlir::SymbolTable::SymbolUse use : *oldSymUses) {
1110 mlir::Operation *userOp = use.getUser();
1111 assert(
1112 (mlir::isa<cir::GetGlobalOp, cir::GlobalOp, cir::ConstantOp>(userOp)) &&
1113 "Unexpected user for global op");
1114
1115 if (auto getGlobalOp = dyn_cast<cir::GetGlobalOp>(use.getUser())) {
1116 mlir::Value useOpResultValue = getGlobalOp.getAddr();
1117 useOpResultValue.setType(cir::PointerType::get(newTy));
1118
1119 mlir::OpBuilder::InsertionGuard guard(builder);
1120 builder.setInsertionPointAfter(getGlobalOp);
1121 mlir::Type ptrTy = builder.getPointerTo(oldTy);
1122 mlir::Value cast =
1123 builder.createBitcast(getGlobalOp->getLoc(), useOpResultValue, ptrTy);
1124 useOpResultValue.replaceAllUsesExcept(cast, cast.getDefiningOp());
1125 } else if (auto glob = dyn_cast<cir::GlobalOp>(userOp)) {
1126 if (auto init = glob.getInitialValue()) {
1127 mlir::Attribute nw = getNewInitValue(*this, newGV, oldTy, init.value());
1128 glob.setInitialValueAttr(nw);
1129 }
1130 } else if (auto c = dyn_cast<cir::ConstantOp>(userOp)) {
1131 mlir::Attribute init = getNewInitValue(*this, newGV, oldTy, c.getValue());
1132 auto typedAttr = mlir::cast<mlir::TypedAttr>(init);
1133 mlir::OpBuilder::InsertionGuard guard(builder);
1134 builder.setInsertionPointAfter(c);
1135 auto newUser = cir::ConstantOp::create(builder, c.getLoc(), typedAttr);
1136 c.replaceAllUsesWith(newUser.getOperation());
1137 c.erase();
1138 }
1139 }
1140
1141 // If the old global is being tracked as the most-recently-created global,
1142 // update it so that subsequent globals are not inserted after a (now
1143 // erased) operation, which would leave them detached from the module.
1144 if (lastGlobalOp == oldGV)
1145 lastGlobalOp = newGV;
1146 if (getLangOpts().CUDA)
1147 getCUDARuntime().handleGlobalReplace(oldGV, newGV);
1148 eraseGlobalSymbol(oldGV);
1149 oldGV.erase();
1150}
1151
1152/// If the specified mangled name is not in the module,
1153/// create and return an mlir GlobalOp with the specified type (TODO(cir):
1154/// address space).
1155///
1156/// TODO(cir):
1157/// 1. If there is something in the module with the specified name, return
1158/// it potentially bitcasted to the right type.
1159///
1160/// 2. If \p d is non-null, it specifies a decl that correspond to this. This
1161/// is used to set the attributes on the global when it is first created.
1162///
1163/// 3. If \p isForDefinition is true, it is guaranteed that an actual global
1164/// with type \p ty will be returned, not conversion of a variable with the same
1165/// mangled name but some other type.
1166cir::GlobalOp
1167CIRGenModule::getOrCreateCIRGlobal(StringRef mangledName, mlir::Type ty,
1168 LangAS langAS, const VarDecl *d,
1169 ForDefinition_t isForDefinition) {
1170
1171 // Lookup the entry, lazily creating it if necessary.
1172 cir::GlobalOp entry;
1173 if (mlir::Operation *v = getGlobalValue(mangledName)) {
1174 if (!isa<cir::GlobalOp>(v))
1176 "getOrCreateCIRGlobal: global with non-GlobalOp type");
1177 entry = cast<cir::GlobalOp>(v);
1178 }
1179
1180 if (entry) {
1181 mlir::ptr::MemorySpaceAttrInterface entryCIRAS = entry.getAddrSpaceAttr();
1183
1186
1187 if (entry.getSymType() == ty &&
1188 cir::isMatchingAddressSpace(entryCIRAS, langAS))
1189 return entry;
1190
1191 // If there are two attempts to define the same mangled name, issue an
1192 // error.
1193 //
1194 // TODO(cir): look at mlir::GlobalValue::isDeclaration for all aspects of
1195 // recognizing the global as a declaration, for now only check if
1196 // initializer is present.
1197 if (isForDefinition && !entry.isDeclaration()) {
1199 "getOrCreateCIRGlobal: global with conflicting type");
1200 }
1201
1202 // Address space check removed because it is unnecessary because CIR records
1203 // address space info in types.
1204
1205 // (If global is requested for a definition, we always need to create a new
1206 // global, not just return a bitcast.)
1207 if (!isForDefinition)
1208 return entry;
1209 }
1210
1211 mlir::Location loc = getLoc(d->getSourceRange());
1212
1213 // Calculate constant storage flag before creating the global. This was moved
1214 // from after the global creation to ensure the constant flag is set correctly
1215 // at creation time, matching the logic used in emitCXXGlobalVarDeclInit.
1216 bool isConstant = false;
1217 if (d) {
1218 bool needsDtor =
1220 isConstant = d->getType().isConstantStorage(
1221 astContext, /*ExcludeCtor=*/true, /*ExcludeDtor=*/!needsDtor);
1222 }
1223
1224 mlir::ptr::MemorySpaceAttrInterface declCIRAS =
1225 cir::toCIRAddressSpaceAttr(getMLIRContext(), getGlobalVarAddressSpace(d));
1226
1227 // mlir::SymbolTable::Visibility::Public is the default, no need to explicitly
1228 // mark it as such.
1229 cir::GlobalOp gv = createGlobalOp(loc, mangledName, ty, isConstant, declCIRAS,
1230 /*insertPoint=*/entry.getOperation());
1231
1232 // If we already created a global with the same mangled name (but different
1233 // type) before, remove it from its parent.
1234 if (entry)
1235 replaceGlobal(entry, gv);
1236
1237 // This is the first use or definition of a mangled name. If there is a
1238 // deferred decl with this name, remember that we need to emit it at the end
1239 // of the file.
1240 auto ddi = deferredDecls.find(mangledName);
1241 if (ddi != deferredDecls.end()) {
1242 // Move the potentially referenced deferred decl to the DeferredDeclsToEmit
1243 // list, and remove it from DeferredDecls (since we don't need it anymore).
1244 addDeferredDeclToEmit(ddi->second);
1245 deferredDecls.erase(ddi);
1246 }
1247
1248 // Handle things which are present even on external declarations.
1249 if (d) {
1250 if (langOpts.OpenMP && !langOpts.OpenMPSimd)
1252 "getOrCreateCIRGlobal: OpenMP target global variable");
1253
1254 gv.setAlignmentAttr(getSize(astContext.getDeclAlign(d)));
1255
1256 setLinkageForGV(gv, d);
1257
1258 if (d->getTLSKind())
1259 setTLSMode(gv, *d);
1260
1261 setGVProperties(gv, d);
1262
1263 // If required by the ABI, treat declarations of static data members with
1264 // inline initializers as definitions.
1265 if (astContext.isMSStaticDataMemberInlineDefinition(d))
1267 "getOrCreateCIRGlobal: MS static data member inline definition");
1268
1269 // Emit section information for extern variables.
1270 if (d->hasExternalStorage()) {
1271 if (const SectionAttr *sa = d->getAttr<SectionAttr>())
1272 gv.setSectionAttr(builder.getStringAttr(sa->getName()));
1273 }
1274
1275 // Handle XCore specific ABI requirements.
1276 if (getTriple().getArch() == llvm::Triple::xcore)
1278 "getOrCreateCIRGlobal: XCore specific ABI requirements");
1279
1280 // Check if we a have a const declaration with an initializer, we may be
1281 // able to emit it as available_externally to expose it's value to the
1282 // optimizer.
1283 if (getLangOpts().CPlusPlus && gv.isPublic() &&
1284 d->getType().isConstQualified() && gv.isDeclaration() &&
1285 !d->hasDefinition() && d->hasInit() && !d->hasAttr<DLLImportAttr>())
1286 errorNYI(
1287 d->getSourceRange(),
1288 "getOrCreateCIRGlobal: external const declaration with initializer");
1289 }
1290
1291 if (d &&
1294 // TODO(cir): set target attributes
1295 // External HIP managed variables needed to be recorded for transformation
1296 // in both device and host compilations.
1297 if (getLangOpts().CUDA && d && d->hasAttr<HIPManagedAttr>() &&
1298 d->hasExternalStorage())
1300 "getOrCreateCIRGlobal: HIP managed attribute");
1301 }
1302
1304 return gv;
1305}
1306
1307cir::GlobalOp
1309 ForDefinition_t isForDefinition) {
1310 assert(d->hasGlobalStorage() && "Not a global variable");
1311 QualType astTy = d->getType();
1312 if (!ty)
1313 ty = getTypes().convertTypeForMem(astTy);
1314
1315 StringRef mangledName = getMangledName(d);
1316 return getOrCreateCIRGlobal(mangledName, ty, getGlobalVarAddressSpace(d), d,
1317 isForDefinition);
1318}
1319
1320/// Return the mlir::Value for the address of the given global variable. If
1321/// \p ty is non-null and if the global doesn't exist, then it will be created
1322/// with the specified type instead of whatever the normal requested type would
1323/// be. If \p isForDefinition is true, it is guaranteed that an actual global
1324/// with type \p ty will be returned, not conversion of a variable with the same
1325/// mangled name but some other type.
1326mlir::Value CIRGenModule::getAddrOfGlobalVar(const VarDecl *d, mlir::Type ty,
1327 ForDefinition_t isForDefinition) {
1328 assert(d->hasGlobalStorage() && "Not a global variable");
1329 QualType astTy = d->getType();
1330 if (!ty)
1331 ty = getTypes().convertTypeForMem(astTy);
1332
1333 bool tlsAccess = d->getTLSKind() != VarDecl::TLS_None;
1334 cir::GlobalOp g = getOrCreateCIRGlobal(d, ty, isForDefinition);
1335 mlir::Type ptrTy = builder.getPointerTo(g.getSymType(), g.getAddrSpaceAttr());
1336 return cir::GetGlobalOp::create(
1337 builder, getLoc(d->getSourceRange()), ptrTy, g.getSymNameAttr(),
1338 tlsAccess,
1339 /*static_local=*/g.getStaticLocalGuard().has_value());
1340}
1341
1342cir::GlobalViewAttr CIRGenModule::getAddrOfGlobalVarAttr(const VarDecl *d) {
1343 assert(d->hasGlobalStorage() && "Not a global variable");
1344 mlir::Type ty = getTypes().convertTypeForMem(d->getType());
1345
1346 cir::GlobalOp globalOp = getOrCreateCIRGlobal(d, ty, NotForDefinition);
1347 cir::PointerType ptrTy =
1348 builder.getPointerTo(globalOp.getSymType(), globalOp.getAddrSpaceAttr());
1349 return builder.getGlobalViewAttr(ptrTy, globalOp);
1350}
1351
1352void CIRGenModule::addUsedGlobal(cir::CIRGlobalValueInterface gv) {
1353 assert((mlir::isa<cir::FuncOp>(gv.getOperation()) ||
1354 !gv.isDeclarationForLinker()) &&
1355 "Only globals with definition can force usage.");
1356 llvmUsed.emplace_back(gv);
1357}
1358
1359void CIRGenModule::addCompilerUsedGlobal(cir::CIRGlobalValueInterface gv) {
1360 assert(!gv.isDeclarationForLinker() &&
1361 "Only globals with definition can force usage.");
1362 llvmCompilerUsed.emplace_back(gv);
1363}
1364
1366 cir::CIRGlobalValueInterface gv) {
1367 assert((mlir::isa<cir::FuncOp>(gv.getOperation()) ||
1368 !gv.isDeclarationForLinker()) &&
1369 "Only globals with definition can force usage.");
1370 if (getTriple().isOSBinFormatELF())
1371 llvmCompilerUsed.emplace_back(gv);
1372 else
1373 llvmUsed.emplace_back(gv);
1374}
1375
1376static void emitUsed(CIRGenModule &cgm, StringRef name,
1377 std::vector<cir::CIRGlobalValueInterface> &list) {
1378 if (list.empty())
1379 return;
1380
1381 CIRGenBuilderTy &builder = cgm.getBuilder();
1382 mlir::Location loc = builder.getUnknownLoc();
1384 usedArray.resize(list.size());
1385 for (auto [i, op] : llvm::enumerate(list)) {
1386 usedArray[i] = cir::GlobalViewAttr::get(
1387 cgm.voidPtrTy, mlir::FlatSymbolRefAttr::get(op.getNameAttr()));
1388 }
1389
1390 cir::ArrayType arrayTy = cir::ArrayType::get(cgm.voidPtrTy, usedArray.size());
1391
1392 cir::ConstArrayAttr initAttr = cir::ConstArrayAttr::get(
1393 arrayTy, mlir::ArrayAttr::get(&cgm.getMLIRContext(), usedArray));
1394
1395 cir::GlobalOp gv = cgm.createGlobalOp(loc, name, arrayTy,
1396 /*isConstant=*/false);
1397 gv.setLinkage(cir::GlobalLinkageKind::AppendingLinkage);
1398 gv.setInitialValueAttr(initAttr);
1399 gv.setSectionAttr(builder.getStringAttr("llvm.metadata"));
1400}
1401
1403 emitUsed(*this, "llvm.used", llvmUsed);
1404 emitUsed(*this, "llvm.compiler.used", llvmCompilerUsed);
1405}
1406
1408 bool isTentative) {
1409 if (getLangOpts().OpenCL || getLangOpts().OpenMPIsTargetDevice) {
1411 "emitGlobalVarDefinition: emit OpenCL/OpenMP global variable");
1412 return;
1413 }
1414
1415 // Whether the definition of the variable is available externally.
1416 // If yes, we shouldn't emit the GloablCtor and GlobalDtor for the variable
1417 // since this is the job for its original source.
1418 bool isDefinitionAvailableExternally =
1419 astContext.GetGVALinkageForVariable(vd) == GVA_AvailableExternally;
1420
1421 // It is useless to emit the definition for an available_externally variable
1422 // which can't be marked as const.
1423 if (isDefinitionAvailableExternally &&
1424 (!vd->hasConstantInitialization() ||
1425 // TODO: Update this when we have interface to check constexpr
1426 // destructor.
1427 vd->needsDestruction(astContext) ||
1428 !vd->getType().isConstantStorage(astContext, true, true)))
1429 return;
1430
1431 mlir::Attribute init;
1432 bool needsGlobalCtor = false;
1433 bool needsGlobalDtor =
1434 !isDefinitionAvailableExternally &&
1436 const VarDecl *initDecl;
1437 const Expr *initExpr = vd->getAnyInitializer(initDecl);
1438
1439 std::optional<ConstantEmitter> emitter;
1440
1441 // CUDA E.2.4.1 "__shared__ variables cannot have an initialization
1442 // as part of their declaration." Sema has already checked for
1443 // error cases, so we just need to set Init to PoisonValue.
1444 bool isCUDASharedVar =
1445 getLangOpts().CUDAIsDevice && vd->hasAttr<CUDASharedAttr>();
1446 // Shadows of initialized device-side global variables are also left
1447 // undefined.
1448 // Managed Variables should be initialized on both host side and device side.
1449 bool isCUDAShadowVar =
1450 !getLangOpts().CUDAIsDevice && !vd->hasAttr<HIPManagedAttr>() &&
1451 (vd->hasAttr<CUDAConstantAttr>() || vd->hasAttr<CUDADeviceAttr>() ||
1452 vd->hasAttr<CUDASharedAttr>());
1453 bool isCUDADeviceShadowVar =
1454 getLangOpts().CUDAIsDevice && !vd->hasAttr<HIPManagedAttr>() &&
1457
1458 if (getLangOpts().CUDA &&
1459 (isCUDASharedVar || isCUDAShadowVar || isCUDADeviceShadowVar)) {
1460 init = cir::UndefAttr::get(convertType(vd->getType()));
1461 } else if (vd->hasAttr<LoaderUninitializedAttr>()) {
1463 "emitGlobalVarDefinition: loader uninitialized attribute");
1464 } else if (!initExpr) {
1465 // This is a tentative definition; tentative definitions are
1466 // implicitly initialized with { 0 }.
1467 //
1468 // Note that tentative definitions are only emitted at the end of
1469 // a translation unit, so they should never have incomplete
1470 // type. In addition, EmitTentativeDefinition makes sure that we
1471 // never attempt to emit a tentative definition if a real one
1472 // exists. A use may still exists, however, so we still may need
1473 // to do a RAUW.
1474 assert(!vd->getType()->isIncompleteType() && "Unexpected incomplete type");
1475 init = builder.getZeroInitAttr(convertType(vd->getType()));
1476 } else {
1477 emitter.emplace(*this);
1478 mlir::Attribute initializer = emitter->tryEmitForInitializer(*initDecl);
1479 if (!initializer) {
1480 QualType qt = initExpr->getType();
1481 if (vd->getType()->isReferenceType())
1482 qt = vd->getType();
1483
1484 if (getLangOpts().CPlusPlus) {
1485 if (initDecl->hasFlexibleArrayInit(astContext))
1487 "emitGlobalVarDefinition: flexible array initializer");
1488 init = builder.getZeroInitAttr(convertType(qt));
1489 if (!isDefinitionAvailableExternally)
1490 needsGlobalCtor = true;
1491 } else {
1493 "emitGlobalVarDefinition: static initializer");
1494 }
1495 } else {
1496 init = initializer;
1497 // We don't need an initializer, so remove the entry for the delayed
1498 // initializer position (just in case this entry was delayed) if we
1499 // also don't need to register a destructor.
1501 }
1502 }
1503
1504 mlir::Type initType;
1505 if (mlir::isa<mlir::SymbolRefAttr>(init)) {
1506 errorNYI(
1507 vd->getSourceRange(),
1508 "emitGlobalVarDefinition: global initializer is a symbol reference");
1509 return;
1510 } else {
1511 assert(mlir::isa<mlir::TypedAttr>(init) && "This should have a type");
1512 auto typedInitAttr = mlir::cast<mlir::TypedAttr>(init);
1513 initType = typedInitAttr.getType();
1514 }
1515 assert(!mlir::isa<mlir::NoneType>(initType) && "Should have a type by now");
1516
1517 cir::GlobalOp gv =
1518 getOrCreateCIRGlobal(vd, initType, ForDefinition_t(!isTentative));
1519 // TODO(cir): Strip off pointer casts from Entry if we get them?
1520
1521 if (!gv || gv.getSymType() != initType) {
1523 "emitGlobalVarDefinition: global initializer with type mismatch");
1524 return;
1525 }
1526
1528
1529 if (vd->hasAttr<AnnotateAttr>())
1530 addGlobalAnnotations(vd, gv);
1531
1532 // Set CIR's linkage type as appropriate.
1533 cir::GlobalLinkageKind linkage = getCIRLinkageVarDefinition(vd);
1534
1535 // CUDA B.2.1 "The __device__ qualifier declares a variable that resides on
1536 // the device. [...]"
1537 // CUDA B.2.2 "The __constant__ qualifier, optionally used together with
1538 // __device__, declares a variable that: [...]
1539 // Is accessible from all the threads within the grid and from the host
1540 // through the runtime library (cudaGetSymbolAddress() / cudaGetSymbolSize()
1541 // / cudaMemcpyToSymbol() / cudaMemcpyFromSymbol())."
1542 if (langOpts.CUDA) {
1543 if (langOpts.CUDAIsDevice) {
1544 // __shared__ variables is not marked as externally initialized,
1545 // because they must not be initialized.
1546 if (linkage != cir::GlobalLinkageKind::InternalLinkage &&
1547 !vd->isConstexpr() && !vd->getType().isConstQualified() &&
1548 (vd->hasAttr<CUDADeviceAttr>() || vd->hasAttr<CUDAConstantAttr>() ||
1551 gv->setAttr(cir::CUDAExternallyInitializedAttr::getMnemonic(),
1552 cir::CUDAExternallyInitializedAttr::get(&getMLIRContext()));
1553 }
1554 } else {
1555 // Adjust linkage of shadow variables in host compilation
1557 }
1559 }
1560
1561 // Set initializer and finalize emission
1563 if (emitter)
1564 emitter->finalize(gv);
1565
1566 // If it is safe to mark the global 'constant', do so now.
1567 // Use the same logic as classic codegen EmitGlobalVarDefinition.
1568 gv.setConstant((vd->hasAttr<CUDAConstantAttr>() && langOpts.CUDAIsDevice) ||
1569 (!needsGlobalCtor && !needsGlobalDtor &&
1570 vd->getType().isConstantStorage(astContext,
1571 /*ExcludeCtor=*/true,
1572 /*ExcludeDtor=*/true)));
1573 // If it is in a read-only section, mark it 'constant'.
1574 if (const SectionAttr *sa = vd->getAttr<SectionAttr>()) {
1575 const ASTContext::SectionInfo &si = astContext.SectionInfos[sa->getName()];
1576 if ((si.SectionFlags & ASTContext::PSF_Write) == 0)
1577 gv.setConstant(true);
1578 }
1579
1580 // Set CIR linkage and DLL storage class.
1581 gv.setLinkage(linkage);
1582 // FIXME(cir): setLinkage should likely set MLIR's visibility automatically.
1583 gv.setVisibility(getMLIRVisibilityFromCIRLinkage(linkage));
1585 if (linkage == cir::GlobalLinkageKind::CommonLinkage) {
1586 // common vars aren't constant even if declared const.
1587 gv.setConstant(false);
1588 // Tentative definition of global variables may be initialized with
1589 // non-zero null pointers. In this case they should have weak linkage
1590 // since common linkage must have zero initializer and must not have
1591 // explicit section therefore cannot have non-zero initial value.
1592 std::optional<mlir::Attribute> initializer = gv.getInitialValue();
1593 if (initializer && !getBuilder().isNullValue(*initializer))
1594 gv.setLinkage(cir::GlobalLinkageKind::WeakAnyLinkage);
1595 }
1596
1597 setNonAliasAttributes(vd, gv);
1598
1599 if (vd->getTLSKind() && !vd->isStaticLocal())
1600 setTLSMode(gv, *vd);
1601
1602 maybeSetTrivialComdat(*vd, gv);
1603
1604 // Emit the initializer function if necessary.
1605 if (needsGlobalCtor || needsGlobalDtor)
1606 emitCXXGlobalVarDeclInitFunc(vd, gv, needsGlobalCtor);
1607}
1608
1610 if (getFunctionLinkage(gd) !=
1611 cir::GlobalLinkageKind::AvailableExternallyLinkage)
1612 return true;
1613
1614 const auto *fd = cast<FunctionDecl>(gd.getDecl());
1615 // Inline builtins must be emitted; the body is redirected to a `.inline`
1616 // symbol in CIRGenFunction::generateCode.
1617 if (fd->isInlineBuiltinDeclaration())
1618 return true;
1619
1620 // PR9614 / glibc btowc workaround: an available_externally function whose
1621 // body just calls itself (via asm label or __builtin_* lowering on the
1622 // same name) is not a valid stand-in for the real implementation. Drop
1623 // it from the IR so the optimizer doesn't reason about its body.
1625}
1626
1628 mlir::Operation *op) {
1629 const auto *decl = cast<ValueDecl>(gd.getDecl());
1630 if (const auto *fd = dyn_cast<FunctionDecl>(decl)) {
1631 if (!shouldEmitFunction(gd))
1632 return;
1633
1634 if (const auto *method = dyn_cast<CXXMethodDecl>(decl)) {
1635 // Make sure to emit the definition(s) before we emit the thunks. This is
1636 // necessary for the generation of certain thunks.
1637 if (isa<CXXConstructorDecl>(method) || isa<CXXDestructorDecl>(method))
1638 abi->emitCXXStructor(gd);
1639 else if (fd->isMultiVersion())
1640 errorNYI(method->getSourceRange(), "multiversion functions");
1641 else
1643
1644 if (method->isVirtual())
1645 getVTables().emitThunks(gd);
1646
1647 return;
1648 }
1649
1650 if (fd->isMultiVersion())
1651 errorNYI(fd->getSourceRange(), "multiversion functions");
1653 return;
1654 }
1655
1656 if (const auto *vd = dyn_cast<VarDecl>(decl))
1657 return emitGlobalVarDefinition(vd, !vd->hasDefinition());
1658
1659 llvm_unreachable("Invalid argument to CIRGenModule::emitGlobalDefinition");
1660}
1661
1662mlir::Attribute
1664 assert(!e->getType()->isPointerType() && "Strings are always arrays");
1665
1666 // Don't emit it as the address of the string, emit the string data itself
1667 // as an inline array.
1668 if (e->getCharByteWidth() == 1) {
1669 SmallString<64> str(e->getString());
1670
1671 // Resize the string to the right size, which is indicated by its type.
1672 const ConstantArrayType *cat =
1673 astContext.getAsConstantArrayType(e->getType());
1674 uint64_t finalSize = cat->getZExtSize();
1675 str.resize(finalSize);
1676
1677 mlir::Type eltTy = convertType(cat->getElementType());
1678 return builder.getString(str, eltTy, finalSize, /*ensureNullTerm=*/false);
1679 }
1680
1681 auto arrayTy = mlir::cast<cir::ArrayType>(convertType(e->getType()));
1682
1683 auto arrayEltTy = mlir::cast<cir::IntType>(arrayTy.getElementType());
1684
1685 uint64_t arraySize = arrayTy.getSize();
1686 unsigned literalSize = e->getLength();
1687 assert(arraySize > literalSize &&
1688 "wide string literal array size must have room for null terminator?");
1689
1690 // Check if the string is all null bytes before building the vector.
1691 // In most non-zero cases, this will break out on the first element.
1692 bool isAllZero = true;
1693 for (unsigned i = 0; i < literalSize; ++i) {
1694 if (e->getCodeUnit(i) != 0) {
1695 isAllZero = false;
1696 break;
1697 }
1698 }
1699
1700 if (isAllZero)
1701 return cir::ZeroAttr::get(arrayTy);
1702
1703 // Otherwise emit a constant array holding the characters.
1705 elements.reserve(arraySize);
1706 for (unsigned i = 0; i < literalSize; ++i)
1707 elements.push_back(cir::IntAttr::get(arrayEltTy, e->getCodeUnit(i)));
1708
1709 auto elementsAttr = mlir::ArrayAttr::get(&getMLIRContext(), elements);
1710 return builder.getConstArray(elementsAttr, arrayTy);
1711}
1712
1714 return getTriple().supportsCOMDAT();
1715}
1716
1717static bool shouldBeInCOMDAT(CIRGenModule &cgm, const Decl &d) {
1718 if (!cgm.supportsCOMDAT())
1719 return false;
1720
1721 if (d.hasAttr<SelectAnyAttr>())
1722 return true;
1723
1724 GVALinkage linkage;
1725 if (auto *vd = dyn_cast<VarDecl>(&d))
1726 linkage = cgm.getASTContext().GetGVALinkageForVariable(vd);
1727 else
1728 linkage =
1730
1731 switch (linkage) {
1735 return false;
1738 return true;
1739 }
1740 llvm_unreachable("No such linkage");
1741}
1742
1743void CIRGenModule::maybeSetTrivialComdat(const Decl &d, mlir::Operation *op) {
1744 if (!shouldBeInCOMDAT(*this, d))
1745 return;
1746 if (auto globalOp = dyn_cast_or_null<cir::GlobalOp>(op)) {
1747 globalOp.setComdat(true);
1748 } else {
1749 auto funcOp = cast<cir::FuncOp>(op);
1750 funcOp.setComdat(true);
1751 }
1752}
1753
1755 // Make sure that this type is translated.
1756 genTypes.updateCompletedType(td);
1757}
1758
1759void CIRGenModule::addReplacement(StringRef name, mlir::Operation *op) {
1760 replacements[name] = op;
1761}
1762
1763#ifndef NDEBUG
1764static bool verifyPointerTypeArgs(cir::FuncOp oldF, cir::FuncOp newF,
1765 mlir::SymbolUserMap &userMap) {
1766 for (mlir::Operation *user : userMap.getUsers(oldF)) {
1767 auto call = mlir::dyn_cast<cir::CallOp>(user);
1768 if (!call)
1769 continue;
1770
1771 for (auto [argOp, fnArgType] :
1772 llvm::zip(call.getArgs(), newF.getFunctionType().getInputs())) {
1773 if (argOp.getType() != fnArgType)
1774 return false;
1775 }
1776 }
1777
1778 return true;
1779}
1780#endif // NDEBUG
1781
1782void CIRGenModule::applyReplacements() {
1783 if (replacements.empty())
1784 return;
1785
1786 // Build a symbol user map once — this walks the module O(M) one time.
1787 // Previously, each replaceAllSymbolUses call walked the entire module,
1788 // giving O(R × M) quadratic behavior for R replacements.
1789 mlir::SymbolTableCollection symbolTableCollection;
1790 mlir::SymbolUserMap userMap(symbolTableCollection, theModule);
1791
1792 for (auto &i : replacements) {
1793 StringRef mangledName = i.first;
1794 mlir::Operation *replacement = i.second;
1795 mlir::Operation *entry = getGlobalValue(mangledName);
1796 if (!entry)
1797 continue;
1798 assert(isa<cir::FuncOp>(entry) && "expected function");
1799 auto oldF = cast<cir::FuncOp>(entry);
1800 auto newF = dyn_cast<cir::FuncOp>(replacement);
1801 if (!newF) {
1802 // In classic codegen, this can be a global alias, a bitcast, or a GEP.
1803 errorNYI(replacement->getLoc(), "replacement is not a function");
1804 continue;
1805 }
1806
1807 assert(verifyPointerTypeArgs(oldF, newF, userMap) &&
1808 "call argument types do not match replacement function");
1809
1810 // Replace old with new, but keep the old order. Uses
1811 // SymbolUserMap to touch only actual users, not the whole module.
1812 userMap.replaceAllUsesWith(oldF, newF.getSymNameAttr());
1813 newF->moveBefore(oldF);
1814 eraseGlobalSymbol(oldF);
1815 oldF->erase();
1816 }
1817}
1818
1820 mlir::Location loc, StringRef name, mlir::Type ty,
1821 cir::GlobalLinkageKind linkage, clang::CharUnits alignment) {
1822 auto gv = mlir::dyn_cast_or_null<cir::GlobalOp>(getGlobalValue(name));
1823
1824 if (gv) {
1825 // Check if the variable has the right type.
1826 if (gv.getSymType() == ty)
1827 return gv;
1828
1829 // Because of C++ name mangling, the only way we can end up with an already
1830 // existing global with the same name is if it has been declared extern
1831 // "C".
1832 assert(gv.isDeclaration() && "Declaration has wrong type!");
1833
1834 errorNYI(loc, "createOrReplaceCXXRuntimeVariable: declaration exists with "
1835 "wrong type");
1836 return gv;
1837 }
1838
1839 // Create a new variable.
1840 gv = createGlobalOp(loc, name, ty);
1841
1842 // Set up extra information and add to the module
1843 gv.setLinkageAttr(
1844 cir::GlobalLinkageKindAttr::get(&getMLIRContext(), linkage));
1845 mlir::SymbolTable::setSymbolVisibility(gv,
1847
1848 if (supportsCOMDAT() && cir::isWeakForLinker(linkage) &&
1849 !gv.hasAvailableExternallyLinkage()) {
1850 gv.setComdat(true);
1851 }
1852
1853 gv.setAlignmentAttr(getSize(alignment));
1854 setDSOLocal(static_cast<mlir::Operation *>(gv));
1855 return gv;
1856}
1857
1858// TODO(CIR): this could be a common method between LLVM codegen.
1859static bool isVarDeclStrongDefinition(const ASTContext &astContext,
1860 CIRGenModule &cgm, const VarDecl *vd,
1861 bool noCommon) {
1862 // Don't give variables common linkage if -fno-common was specified unless it
1863 // was overridden by a NoCommon attribute.
1864 if ((noCommon || vd->hasAttr<NoCommonAttr>()) && !vd->hasAttr<CommonAttr>())
1865 return true;
1866
1867 // C11 6.9.2/2:
1868 // A declaration of an identifier for an object that has file scope without
1869 // an initializer, and without a storage-class specifier or with the
1870 // storage-class specifier static, constitutes a tentative definition.
1871 if (vd->getInit() || vd->hasExternalStorage())
1872 return true;
1873
1874 // A variable cannot be both common and exist in a section.
1875 if (vd->hasAttr<SectionAttr>())
1876 return true;
1877
1878 // A variable cannot be both common and exist in a section.
1879 // We don't try to determine which is the right section in the front-end.
1880 // If no specialized section name is applicable, it will resort to default.
1881 if (vd->hasAttr<PragmaClangBSSSectionAttr>() ||
1882 vd->hasAttr<PragmaClangDataSectionAttr>() ||
1883 vd->hasAttr<PragmaClangRelroSectionAttr>() ||
1884 vd->hasAttr<PragmaClangRodataSectionAttr>())
1885 return true;
1886
1887 // Thread local vars aren't considered common linkage.
1888 if (vd->getTLSKind())
1889 return true;
1890
1891 // Tentative definitions marked with WeakImportAttr are true definitions.
1892 if (vd->hasAttr<WeakImportAttr>())
1893 return true;
1894
1895 // A variable cannot be both common and exist in a comdat.
1896 if (shouldBeInCOMDAT(cgm, *vd))
1897 return true;
1898
1899 // Declarations with a required alignment do not have common linkage in MSVC
1900 // mode.
1901 if (astContext.getTargetInfo().getCXXABI().isMicrosoft()) {
1902 if (vd->hasAttr<AlignedAttr>())
1903 return true;
1904 QualType varType = vd->getType();
1905 if (astContext.isAlignmentRequired(varType))
1906 return true;
1907
1908 if (const auto *rd = varType->getAsRecordDecl()) {
1909 for (const FieldDecl *fd : rd->fields()) {
1910 if (fd->isBitField())
1911 continue;
1912 if (fd->hasAttr<AlignedAttr>())
1913 return true;
1914 if (astContext.isAlignmentRequired(fd->getType()))
1915 return true;
1916 }
1917 }
1918 }
1919
1920 // Microsoft's link.exe doesn't support alignments greater than 32 bytes for
1921 // common symbols, so symbols with greater alignment requirements cannot be
1922 // common.
1923 // Other COFF linkers (ld.bfd and LLD) support arbitrary power-of-two
1924 // alignments for common symbols via the aligncomm directive, so this
1925 // restriction only applies to MSVC environments.
1926 if (astContext.getTargetInfo().getTriple().isKnownWindowsMSVCEnvironment() &&
1927 astContext.getTypeAlignIfKnown(vd->getType()) >
1928 astContext.toBits(CharUnits::fromQuantity(32)))
1929 return true;
1930
1931 return false;
1932}
1933
1934cir::GlobalLinkageKind
1936 GVALinkage linkage) {
1937 if (linkage == GVA_Internal)
1938 return cir::GlobalLinkageKind::InternalLinkage;
1939
1940 if (dd->hasAttr<WeakAttr>())
1941 return cir::GlobalLinkageKind::WeakAnyLinkage;
1942
1943 if (const auto *fd = dd->getAsFunction())
1944 if (fd->isMultiVersion() && linkage == GVA_AvailableExternally)
1945 return cir::GlobalLinkageKind::LinkOnceAnyLinkage;
1946
1947 // We are guaranteed to have a strong definition somewhere else,
1948 // so we can use available_externally linkage.
1949 if (linkage == GVA_AvailableExternally)
1950 return cir::GlobalLinkageKind::AvailableExternallyLinkage;
1951
1952 // Note that Apple's kernel linker doesn't support symbol
1953 // coalescing, so we need to avoid linkonce and weak linkages there.
1954 // Normally, this means we just map to internal, but for explicit
1955 // instantiations we'll map to external.
1956
1957 // In C++, the compiler has to emit a definition in every translation unit
1958 // that references the function. We should use linkonce_odr because
1959 // a) if all references in this translation unit are optimized away, we
1960 // don't need to codegen it. b) if the function persists, it needs to be
1961 // merged with other definitions. c) C++ has the ODR, so we know the
1962 // definition is dependable.
1963 if (linkage == GVA_DiscardableODR)
1964 return !astContext.getLangOpts().AppleKext
1965 ? cir::GlobalLinkageKind::LinkOnceODRLinkage
1966 : cir::GlobalLinkageKind::InternalLinkage;
1967
1968 // An explicit instantiation of a template has weak linkage, since
1969 // explicit instantiations can occur in multiple translation units
1970 // and must all be equivalent. However, we are not allowed to
1971 // throw away these explicit instantiations.
1972 //
1973 // CUDA/HIP: For -fno-gpu-rdc case, device code is limited to one TU,
1974 // so say that CUDA templates are either external (for kernels) or internal.
1975 // This lets llvm perform aggressive inter-procedural optimizations. For
1976 // -fgpu-rdc case, device function calls across multiple TU's are allowed,
1977 // therefore we need to follow the normal linkage paradigm.
1978 if (linkage == GVA_StrongODR) {
1979 if (getLangOpts().AppleKext)
1980 return cir::GlobalLinkageKind::ExternalLinkage;
1981 if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice &&
1982 !getLangOpts().GPURelocatableDeviceCode)
1983 return dd->hasAttr<CUDAGlobalAttr>()
1984 ? cir::GlobalLinkageKind::ExternalLinkage
1985 : cir::GlobalLinkageKind::InternalLinkage;
1986 return cir::GlobalLinkageKind::WeakODRLinkage;
1987 }
1988
1989 // C++ doesn't have tentative definitions and thus cannot have common
1990 // linkage.
1991 if (!getLangOpts().CPlusPlus && isa<VarDecl>(dd) &&
1992 !isVarDeclStrongDefinition(astContext, *this, cast<VarDecl>(dd),
1993 getCodeGenOpts().NoCommon))
1994 return cir::GlobalLinkageKind::CommonLinkage;
1995
1996 // selectany symbols are externally visible, so use weak instead of
1997 // linkonce. MSVC optimizes away references to const selectany globals, so
1998 // all definitions should be the same and ODR linkage should be used.
1999 // http://msdn.microsoft.com/en-us/library/5tkz6s71.aspx
2000 if (dd->hasAttr<SelectAnyAttr>())
2001 return cir::GlobalLinkageKind::WeakODRLinkage;
2002
2003 // Otherwise, we have strong external linkage.
2004 assert(linkage == GVA_StrongExternal);
2005 return cir::GlobalLinkageKind::ExternalLinkage;
2006}
2007
2008/// This function is called when we implement a function with no prototype, e.g.
2009/// "int foo() {}". If there are existing call uses of the old function in the
2010/// module, this adjusts them to call the new function directly.
2011///
2012/// This is not just a cleanup: the always_inline pass requires direct calls to
2013/// functions to be able to inline them. If there is a bitcast in the way, it
2014/// won't inline them. Instcombine normally deletes these calls, but it isn't
2015/// run at -O0.
2017 mlir::Operation *old, cir::FuncOp newFn) {
2018 // If we're redefining a global as a function, don't transform it.
2019 auto oldFn = mlir::dyn_cast<cir::FuncOp>(old);
2020 if (!oldFn)
2021 return;
2022
2023 // TODO(cir): this RAUW ignores the features below.
2027 if (oldFn->getAttrs().size() <= 1)
2028 errorNYI(old->getLoc(),
2029 "replaceUsesOfNonProtoTypeWithRealFunction: Attribute forwarding");
2030
2031 // Mark new function as originated from a no-proto declaration.
2032 newFn.setNoProto(oldFn.getNoProto());
2033
2034 // Iterate through all calls of the no-proto function.
2035 std::optional<mlir::SymbolTable::UseRange> symUses =
2036 oldFn.getSymbolUses(oldFn->getParentOp());
2037 for (const mlir::SymbolTable::SymbolUse &use : symUses.value()) {
2038 mlir::OpBuilder::InsertionGuard guard(builder);
2039
2040 if (auto noProtoCallOp = mlir::dyn_cast<cir::CallOp>(use.getUser())) {
2041 builder.setInsertionPoint(noProtoCallOp);
2042
2043 // Patch call type with the real function type.
2044 cir::FuncType newFnType = newFn.getFunctionType();
2045 mlir::OperandRange callOperands = noProtoCallOp.getOperands();
2046 bool returnTypeMatches =
2047 newFnType.hasVoidReturn()
2048 ? noProtoCallOp.getNumResults() == 0
2049 : noProtoCallOp.getNumResults() == 1 &&
2050 noProtoCallOp.getResultTypes().front() ==
2051 newFnType.getReturnType();
2052 bool typesMatch = !newFn.getNoProto() && returnTypeMatches &&
2053 callOperands.size() == newFnType.getNumInputs();
2054 for (unsigned i = 0, e = newFnType.getNumInputs(); typesMatch && i != e;
2055 ++i) {
2056 if (callOperands[i].getType() != newFnType.getInput(i))
2057 typesMatch = false;
2058 }
2059
2060 cir::CallOp realCallOp;
2061 if (typesMatch) {
2062 // Patch call type with the real function type.
2063 realCallOp =
2064 builder.createCallOp(noProtoCallOp.getLoc(), newFn, callOperands);
2065 } else {
2066 // Build an indirect call whose function-pointer signature matches
2067 // the existing call site.
2068 cir::FuncType origFnType = oldFn.getFunctionType();
2069 cir::FuncType callFnType =
2070 origFnType.isVarArg()
2071 ? cir::FuncType::get(origFnType.getInputs(),
2072 origFnType.getReturnType(),
2073 /*isVarArg=*/false)
2074 : origFnType;
2075 mlir::Value addr = cir::GetGlobalOp::create(
2076 builder, noProtoCallOp.getLoc(), cir::PointerType::get(newFnType),
2077 newFn.getSymName());
2078 mlir::Value casted =
2079 builder.createBitcast(addr, cir::PointerType::get(callFnType));
2080 realCallOp = builder.createIndirectCallOp(
2081 noProtoCallOp.getLoc(), casted, callFnType, callOperands);
2082 }
2083
2084 // Replace old no proto call with fixed call.
2085 noProtoCallOp.replaceAllUsesWith(realCallOp);
2086 noProtoCallOp.erase();
2087 } else if (auto getGlobalOp =
2088 mlir::dyn_cast<cir::GetGlobalOp>(use.getUser())) {
2089 // The GetGlobal was emitted with the no-proto FuncType. Uses of this
2090 // operation (cir.store, cir.cast) were built for that pointer type. When
2091 // we re-type the result to the real FuncType, we need to add a bit the
2092 // old pointer type so those uses are still valid. This can lead to
2093 // some redundant bitcast chains, but those will be cleaned up by the
2094 // canonicalizer.
2095 mlir::Value res = getGlobalOp.getAddr();
2096 const mlir::Type oldResTy = res.getType();
2097 const auto newPtrTy = cir::PointerType::get(newFn.getFunctionType());
2098 if (oldResTy != newPtrTy) {
2099 res.setType(newPtrTy);
2100 builder.setInsertionPointAfter(getGlobalOp.getOperation());
2101 mlir::Value castRes =
2102 cir::CastOp::create(builder, getGlobalOp.getLoc(), oldResTy,
2103 cir::CastKind::bitcast, res);
2104 res.replaceAllUsesExcept(castRes, castRes.getDefiningOp());
2105 }
2106 } else if (mlir::isa<cir::GlobalOp>(use.getUser())) {
2107 // Function addresses in global initializers use GlobalViewAttrs typed to
2108 // the initializer context (e.g. struct field type), not the FuncOp type,
2109 // so no update is required when the no-proto FuncOp is replaced.
2110 } else {
2111 llvm_unreachable(
2112 "replaceUsesOfNonProtoTypeWithRealFunction: unexpected use type");
2113 }
2114 }
2115}
2116
2117cir::GlobalLinkageKind
2119 GVALinkage linkage = astContext.GetGVALinkageForVariable(vd);
2120 return getCIRLinkageForDeclarator(vd, linkage);
2121}
2122
2124 const auto *d = cast<FunctionDecl>(gd.getDecl());
2125
2126 GVALinkage linkage = astContext.GetGVALinkageForFunction(d);
2127
2128 if (const auto *dtor = dyn_cast<CXXDestructorDecl>(d))
2129 return getCXXABI().getCXXDestructorLinkage(linkage, dtor, gd.getDtorType());
2130
2131 return getCIRLinkageForDeclarator(d, linkage);
2132}
2133
2134static cir::GlobalOp
2135generateStringLiteral(mlir::Location loc, mlir::TypedAttr c,
2136 cir::GlobalLinkageKind lt, CIRGenModule &cgm,
2137 StringRef globalName, CharUnits alignment) {
2139
2140 // Create a global variable for this string
2141 // FIXME(cir): check for insertion point in module level.
2142 cir::GlobalOp gv = cgm.createGlobalOp(loc, globalName, c.getType(),
2143 !cgm.getLangOpts().WritableStrings);
2144
2145 // Set up extra information and add to the module
2146 gv.setAlignmentAttr(cgm.getSize(alignment));
2147 gv.setLinkageAttr(
2148 cir::GlobalLinkageKindAttr::get(cgm.getBuilder().getContext(), lt));
2152 if (gv.isWeakForLinker()) {
2153 assert(cgm.supportsCOMDAT() && "Only COFF uses weak string literals");
2154 gv.setComdat(true);
2155 }
2156 cgm.setDSOLocal(static_cast<mlir::Operation *>(gv));
2157 return gv;
2158}
2159
2160// LLVM IR automatically uniques names when new llvm::GlobalVariables are
2161// created. This is handy, for example, when creating globals for string
2162// literals. Since we don't do that when creating cir::GlobalOp's, we need
2163// a mechanism to generate a unique name in advance.
2164//
2165// For now, this mechanism is only used in cases where we know that the
2166// name is compiler-generated, so we don't use the MLIR symbol table for
2167// the lookup.
2168std::string CIRGenModule::getUniqueGlobalName(const std::string &baseName) {
2169 // If this is the first time we've generated a name for this basename, use
2170 // it as is and start a counter for this base name.
2171 auto it = cgGlobalNames.find(baseName);
2172 if (it == cgGlobalNames.end()) {
2173 cgGlobalNames[baseName] = 1;
2174 return baseName;
2175 }
2176
2177 std::string result =
2178 baseName + "." + std::to_string(cgGlobalNames[baseName]++);
2179 // There should not be any symbol with this name in the module.
2180 assert(!getGlobalValue(result));
2181 return result;
2182}
2183
2184/// Return a pointer to a constant array for the given string literal.
2186 StringRef name) {
2187 CharUnits alignment =
2188 astContext.getAlignOfGlobalVarInChars(s->getType(), /*VD=*/nullptr);
2189
2190 mlir::Attribute c = getConstantArrayFromStringLiteral(s);
2191
2192 cir::GlobalOp gv;
2193 if (!getLangOpts().WritableStrings && constantStringMap.count(c)) {
2194 gv = constantStringMap[c];
2195 // The bigger alignment always wins.
2196 if (!gv.getAlignment() ||
2197 uint64_t(alignment.getQuantity()) > *gv.getAlignment())
2198 gv.setAlignmentAttr(getSize(alignment));
2199 } else {
2200 // Mangle the string literal if that's how the ABI merges duplicate strings.
2201 // Don't do it if they are writable, since we don't want writes in one TU to
2202 // affect strings in another.
2203 if (getCXXABI().getMangleContext().shouldMangleStringLiteral(s) &&
2204 !getLangOpts().WritableStrings) {
2206 "getGlobalForStringLiteral: mangle string literals");
2207 }
2208
2209 // Unlike LLVM IR, CIR doesn't automatically unique names for globals, so
2210 // we need to do that explicitly.
2211 std::string uniqueName = getUniqueGlobalName(name.str());
2212 // Synthetic string literals (e.g., from SourceLocExpr) may not have valid
2213 // source locations. Use unknown location in those cases.
2214 mlir::Location loc = s->getBeginLoc().isValid()
2215 ? getLoc(s->getSourceRange())
2216 : builder.getUnknownLoc();
2217 auto typedC = llvm::cast<mlir::TypedAttr>(c);
2218 gv = generateStringLiteral(loc, typedC,
2219 cir::GlobalLinkageKind::PrivateLinkage, *this,
2220 uniqueName, alignment);
2221 setDSOLocal(static_cast<mlir::Operation *>(gv));
2222 constantStringMap[c] = gv;
2223
2225 }
2226 return gv;
2227}
2228
2229/// Return a pointer to a constant array for the given string literal.
2230cir::GlobalViewAttr
2232 StringRef name) {
2233 cir::GlobalOp gv = getGlobalForStringLiteral(s, name);
2234 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(gv.getSymType());
2235 assert(arrayTy && "String literal must be array");
2237 cir::PointerType ptrTy = getBuilder().getPointerTo(arrayTy.getElementType());
2238
2239 return builder.getGlobalViewAttr(ptrTy, gv);
2240}
2241
2242// TODO(cir): this could be a common AST helper for both CIR and LLVM codegen.
2244 if (getLangOpts().OpenCL)
2246
2247 // For temporaries inside functions, CUDA treats them as normal variables.
2248 // LangAS::cuda_device, on the other hand, is reserved for those variables
2249 // explicitly marked with __device__.
2250 if (getLangOpts().CUDAIsDevice)
2251 return LangAS::Default;
2252
2253 if (getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice)
2255 if (getLangOpts().SYCLIsDevice)
2256 errorNYI("SYCL temp address space");
2257
2258 return LangAS::Default;
2259}
2260
2262 CIRGenFunction *cgf) {
2263 if (cgf && e->getType()->isVariablyModifiedType())
2265
2267 "emitExplicitCastExprType");
2268}
2269
2271 const MemberPointerType *mpt) {
2272 if (mpt->isMemberFunctionPointerType()) {
2273 auto ty = mlir::cast<cir::MethodType>(convertType(destTy));
2274 return builder.getNullMethodAttr(ty);
2275 }
2276
2277 auto ty = mlir::cast<cir::DataMemberType>(convertType(destTy));
2278 return builder.getNullDataMemberAttr(ty);
2279}
2280
2283
2284 mlir::Location loc = getLoc(e->getSourceRange());
2285
2286 const auto *decl = cast<DeclRefExpr>(e->getSubExpr())->getDecl();
2287
2288 // A member function pointer.
2289 if (const auto *methodDecl = dyn_cast<CXXMethodDecl>(decl)) {
2290 auto ty = mlir::cast<cir::MethodType>(convertType(e->getType()));
2291 if (methodDecl->isVirtual())
2292 return cir::ConstantOp::create(
2293 builder, loc, getCXXABI().buildVirtualMethodAttr(ty, methodDecl));
2294
2295 const CIRGenFunctionInfo &fi =
2297 cir::FuncType funcTy = getTypes().getFunctionType(fi);
2298 cir::FuncOp methodFuncOp = getAddrOfFunction(methodDecl, funcTy);
2299 return cir::ConstantOp::create(builder, loc,
2300 builder.getMethodAttr(ty, methodFuncOp));
2301 }
2302
2303 // Otherwise, a member data pointer.
2304 auto ty = mlir::cast<cir::DataMemberType>(convertType(e->getType()));
2305 const auto *fieldDecl = cast<FieldDecl>(decl);
2306 const auto *mpt = e->getType()->castAs<MemberPointerType>();
2307 const auto *destClass = mpt->getMostRecentCXXRecordDecl();
2308
2309 if (fieldDecl->hasAttr<NoUniqueAddressAttr>()) {
2311 errorNYI(e->getExprLoc(),
2312 "emitMemberPointerConstant: no_unique_address field");
2313 return {};
2314 }
2315
2316 std::optional<llvm::SmallVector<int32_t>> path =
2317 buildMemberPath(destClass, fieldDecl);
2318 if (!path)
2319 return {};
2320 return cir::ConstantOp::create(builder, loc,
2321 builder.getDataMemberAttr(ty, *path));
2322}
2323
2324std::optional<llvm::SmallVector<int32_t>>
2326 const FieldDecl *field) {
2327 assert(!field->hasAttr<NoUniqueAddressAttr>());
2328
2330 if (!findFieldMemberPath(destClass, field, path))
2331 return std::nullopt;
2332 return path;
2333}
2334
2335bool CIRGenModule::findFieldMemberPath(const CXXRecordDecl *currentClass,
2336 const FieldDecl *field,
2338 const CIRGenRecordLayout &layout =
2339 getTypes().getCIRGenRecordLayout(currentClass);
2340
2341 // The field is declared directly in this class.
2342 if (field->getParent() == currentClass) {
2343 int32_t fieldIdx;
2344 if (currentClass->isUnion()) {
2345 // For unions, getCIRFieldNo always returns 0 for every union member (all
2346 // members share offset 0 in the CIR record). Use the declaration-order
2347 // index to distinguish members with the same type at the same offset.
2348 if (!layout.isZeroInitializable()) {
2349 errorNYI(field->getLocation(),
2350 "data member pointer for non-zero-initializable union");
2351 return false;
2352 }
2353 fieldIdx = static_cast<int32_t>(field->getFieldIndex());
2354 } else {
2355 fieldIdx = static_cast<int32_t>(layout.getCIRFieldNo(field));
2356 }
2357 path.push_back(fieldIdx);
2358 return true;
2359 }
2360
2361 // Otherwise search the base subobjects. A virtual base only blocks lowering
2362 // when the field actually lives within it; a virtual base elsewhere in the
2363 // hierarchy must not stop us from reaching a member through a non-virtual
2364 // path.
2365 for (const CXXBaseSpecifier &base : currentClass->bases()) {
2366 const auto *baseDecl =
2367 cast<CXXRecordDecl>(base.getType()->getAsRecordDecl());
2368
2369 if (base.isVirtual()) {
2370 // A pointer to a data member that traverses a virtual base is ill-formed,
2371 // so this guard only fires defensively if the member is reached through
2372 // the virtual base. An unrelated virtual base is skipped so it does not
2373 // block members reached through a non-virtual path.
2374 llvm::SmallVector<int32_t> discardedPath;
2375 if (findFieldMemberPath(baseDecl, field, discardedPath)) {
2376 errorNYI(field->getLocation(),
2377 "data member pointer through virtual base");
2378 return false;
2379 }
2380 continue;
2381 }
2382
2383 // If a base class doesn't participate in layout, the field cannot be in it,
2384 // skip it.
2385 if (!layout.hasNonVirtualBaseCIRField(baseDecl))
2386 continue;
2387
2388 auto baseFieldIdx =
2389 static_cast<int32_t>(layout.getNonVirtualBaseCIRFieldNo(baseDecl));
2390 path.push_back(baseFieldIdx);
2391 if (findFieldMemberPath(baseDecl, field, path))
2392 return true;
2393 path.pop_back();
2394 }
2395 return false;
2396}
2397
2399 for (Decl *decl : dc->decls()) {
2400 // Unlike other DeclContexts, the contents of an ObjCImplDecl at TU scope
2401 // are themselves considered "top-level", so EmitTopLevelDecl on an
2402 // ObjCImplDecl does not recursively visit them. We need to do that in
2403 // case they're nested inside another construct (LinkageSpecDecl /
2404 // ExportDecl) that does stop them from being considered "top-level".
2405 if (auto *oid = dyn_cast<ObjCImplDecl>(decl))
2406 errorNYI(oid->getSourceRange(), "emitDeclConext: ObjCImplDecl");
2407
2409 }
2410}
2411
2412// Emit code for a single top level declaration.
2414
2415 // Ignore dependent declarations.
2416 if (decl->isTemplated())
2417 return;
2418
2419 switch (decl->getKind()) {
2420 default:
2421 errorNYI(decl->getBeginLoc(), "declaration of kind",
2422 decl->getDeclKindName());
2423 break;
2424
2425 case Decl::CXXConversion:
2426 case Decl::CXXMethod:
2427 case Decl::Function: {
2428 auto *fd = cast<FunctionDecl>(decl);
2429 // Consteval functions shouldn't be emitted.
2430 if (!fd->isConsteval())
2431 emitGlobal(fd);
2432 break;
2433 }
2434 case Decl::Export:
2436 break;
2437
2438 case Decl::Var:
2439 case Decl::Decomposition:
2440 case Decl::VarTemplateSpecialization: {
2442 if (auto *decomp = dyn_cast<DecompositionDecl>(decl))
2443 for (auto *binding : decomp->flat_bindings())
2444 if (auto *holdingVar = binding->getHoldingVar())
2445 emitGlobal(holdingVar);
2446 break;
2447 }
2448 case Decl::OpenACCRoutine:
2450 break;
2451 case Decl::OpenACCDeclare:
2453 break;
2454 case Decl::OMPThreadPrivate:
2456 break;
2457 case Decl::OMPGroupPrivate:
2459 break;
2460 case Decl::OMPAllocate:
2462 break;
2463 case Decl::OMPCapturedExpr:
2465 break;
2466 case Decl::OMPDeclareReduction:
2468 break;
2469 case Decl::OMPDeclareMapper:
2471 break;
2472 case Decl::OMPRequires:
2474 break;
2475 case Decl::Enum:
2476 case Decl::Using: // using X; [C++]
2477 case Decl::UsingDirective: // using namespace X; [C++]
2478 case Decl::UsingEnum: // using enum X; [C++]
2479 case Decl::NamespaceAlias:
2480 case Decl::Typedef:
2481 case Decl::TypeAlias: // using foo = bar; [C++11]
2482 case Decl::Record:
2484 break;
2485
2486 // No code generation needed.
2487 case Decl::ClassTemplate:
2488 case Decl::Concept:
2489 case Decl::CXXDeductionGuide:
2490 case Decl::Empty:
2491 case Decl::ExplicitInstantiation:
2492 case Decl::FunctionTemplate:
2493 case Decl::StaticAssert:
2494 case Decl::TypeAliasTemplate:
2495 case Decl::UsingShadow:
2496 case Decl::VarTemplate:
2497 case Decl::VarTemplatePartialSpecialization:
2498 break;
2499
2500 case Decl::CXXConstructor:
2502 break;
2503 case Decl::CXXDestructor:
2505 break;
2506
2507 // C++ Decls
2508 case Decl::LinkageSpec:
2509 case Decl::Namespace:
2511 break;
2512
2513 case Decl::ClassTemplateSpecialization:
2514 case Decl::CXXRecord: {
2517 for (auto *childDecl : crd->decls())
2519 emitTopLevelDecl(childDecl);
2520 break;
2521 }
2522
2523 case Decl::FileScopeAsm:
2524 // File-scope asm is ignored during device-side CUDA compilation.
2525 if (langOpts.CUDA && langOpts.CUDAIsDevice)
2526 break;
2527 // File-scope asm is ignored during device-side OpenMP compilation.
2528 if (langOpts.OpenMPIsTargetDevice)
2529 break;
2530 // File-scope asm is ignored during device-side SYCL compilation.
2531 if (langOpts.SYCLIsDevice)
2532 break;
2533 auto *file_asm = cast<FileScopeAsmDecl>(decl);
2534 std::string line = file_asm->getAsmString();
2535 globalScopeAsm.push_back(builder.getStringAttr(line));
2536 break;
2537 }
2538}
2539
2540void CIRGenModule::setInitializer(cir::GlobalOp &op, mlir::Attribute value) {
2541 // Recompute visibility when updating initializer.
2542 op.setInitialValueAttr(value);
2544}
2545
2546std::pair<cir::FuncType, cir::FuncOp> CIRGenModule::getAddrAndTypeOfCXXStructor(
2547 GlobalDecl gd, const CIRGenFunctionInfo *fnInfo, cir::FuncType fnType,
2548 bool dontDefer, ForDefinition_t isForDefinition) {
2549 auto *md = cast<CXXMethodDecl>(gd.getDecl());
2550
2551 if (isa<CXXDestructorDecl>(md)) {
2552 // Always alias equivalent complete destructors to base destructors in the
2553 // MS ABI.
2554 if (getTarget().getCXXABI().isMicrosoft() &&
2555 gd.getDtorType() == Dtor_Complete &&
2556 md->getParent()->getNumVBases() == 0)
2557 errorNYI(md->getSourceRange(),
2558 "getAddrAndTypeOfCXXStructor: MS ABI complete destructor");
2559 }
2560
2561 if (!fnType) {
2562 if (!fnInfo)
2564 fnType = getTypes().getFunctionType(*fnInfo);
2565 }
2566
2567 auto fn = getOrCreateCIRFunction(getMangledName(gd), fnType, gd,
2568 /*ForVtable=*/false, dontDefer,
2569 /*IsThunk=*/false, isForDefinition);
2570
2571 return {fnType, fn};
2572}
2573
2575 mlir::Type funcType, bool forVTable,
2576 bool dontDefer,
2577 ForDefinition_t isForDefinition) {
2578 assert(!cast<FunctionDecl>(gd.getDecl())->isConsteval() &&
2579 "consteval function should never be emitted");
2580
2581 if (!funcType) {
2582 const auto *fd = cast<FunctionDecl>(gd.getDecl());
2583 funcType = convertType(fd->getType());
2584 }
2585
2586 // Devirtualized destructor calls may come through here instead of via
2587 // getAddrOfCXXStructor. Make sure we use the MS ABI base destructor instead
2588 // of the complete destructor when necessary.
2589 if (const auto *dd = dyn_cast<CXXDestructorDecl>(gd.getDecl())) {
2590 if (getTarget().getCXXABI().isMicrosoft() &&
2591 gd.getDtorType() == Dtor_Complete &&
2592 dd->getParent()->getNumVBases() == 0)
2593 errorNYI(dd->getSourceRange(),
2594 "getAddrOfFunction: MS ABI complete destructor");
2595 }
2596
2597 StringRef mangledName = getMangledName(gd);
2598 cir::FuncOp func =
2599 getOrCreateCIRFunction(mangledName, funcType, gd, forVTable, dontDefer,
2600 /*isThunk=*/false, isForDefinition);
2601 // Returns kernel handle for HIP kernel stub function.
2602 if (langOpts.CUDA && !langOpts.CUDAIsDevice &&
2603 cast<FunctionDecl>(gd.getDecl())->hasAttr<CUDAGlobalAttr>()) {
2604 mlir::Operation *handle = getCUDARuntime().getKernelHandle(func, gd);
2605
2606 // For HIP the kernel handle is a GlobalOp, which cannot be cast to
2607 // FuncOp. Return the stub directly in that case.
2608 bool isHIPHandle = mlir::isa<cir::GlobalOp>(*handle);
2609 if (isForDefinition || isHIPHandle)
2610 return func;
2611 return mlir::dyn_cast<cir::FuncOp>(*handle);
2612 }
2613 return func;
2614}
2615
2616static std::string getMangledNameImpl(CIRGenModule &cgm, GlobalDecl gd,
2617 const NamedDecl *nd) {
2618 SmallString<256> buffer;
2619
2620 llvm::raw_svector_ostream out(buffer);
2622
2624
2625 if (mc.shouldMangleDeclName(nd)) {
2626 mc.mangleName(gd.getWithDecl(nd), out);
2627 } else {
2628 IdentifierInfo *ii = nd->getIdentifier();
2629 assert(ii && "Attempt to mangle unnamed decl.");
2630
2631 const auto *fd = dyn_cast<FunctionDecl>(nd);
2632 if (fd &&
2633 fd->getType()->castAs<FunctionType>()->getCallConv() == CC_X86RegCall) {
2634 cgm.errorNYI(nd->getSourceRange(), "getMangledName: X86RegCall");
2635 } else if (fd && fd->hasAttr<CUDAGlobalAttr>() &&
2637 out << "__device_stub__" << ii->getName();
2638 } else if (fd &&
2639 DeviceKernelAttr::isOpenCLSpelling(
2640 fd->getAttr<DeviceKernelAttr>()) &&
2642 cgm.errorNYI(nd->getSourceRange(), "getMangledName: OpenCL Stub");
2643 } else {
2644 out << ii->getName();
2645 }
2646 }
2647
2648 // Check if the module name hash should be appended for internal linkage
2649 // symbols. This should come before multi-version target suffixes are
2650 // appendded. This is to keep the name and module hash suffix of the internal
2651 // linkage function together. The unique suffix should only be added when name
2652 // mangling is done to make sure that the final name can be properly
2653 // demangled. For example, for C functions without prototypes, name mangling
2654 // is not done and the unique suffix should not be appended then.
2656
2657 if (const auto *fd = dyn_cast<FunctionDecl>(nd)) {
2658 if (fd->isMultiVersion()) {
2659 cgm.errorNYI(nd->getSourceRange(),
2660 "getMangledName: multi-version functions");
2661 }
2662 }
2663 if (cgm.getLangOpts().GPURelocatableDeviceCode) {
2664 cgm.errorNYI(nd->getSourceRange(),
2665 "getMangledName: GPU relocatable device code");
2666 }
2667
2668 return std::string(out.str());
2669}
2670
2671static FunctionDecl *
2673 const FunctionDecl *protoFunc) {
2674 // If this is a C no-prototype function, we can take the 'easy' way out and
2675 // just create a function with no arguments/functions, etc.
2676 if (!protoFunc->hasPrototype())
2677 return FunctionDecl::Create(
2678 ctx, /*DC=*/ctx.getTranslationUnitDecl(),
2679 /*StartLoc=*/SourceLocation{}, /*NLoc=*/SourceLocation{}, bindName,
2680 protoFunc->getType(), /*TInfo=*/nullptr, StorageClass::SC_None);
2681
2682 QualType funcTy = protoFunc->getType();
2683 auto *fpt = cast<FunctionProtoType>(protoFunc->getType());
2684
2685 // If this is a member function, add an explicit 'this' to the function type.
2686 if (auto *methodDecl = dyn_cast<CXXMethodDecl>(protoFunc);
2687 methodDecl && methodDecl->isImplicitObjectMemberFunction()) {
2688 llvm::SmallVector<QualType> paramTypes{fpt->getParamTypes()};
2689 paramTypes.insert(paramTypes.begin(), methodDecl->getThisType());
2690
2691 funcTy = ctx.getFunctionType(fpt->getReturnType(), paramTypes,
2692 fpt->getExtProtoInfo());
2693 fpt = cast<FunctionProtoType>(funcTy);
2694 }
2695
2696 auto *tempFunc =
2698 /*StartLoc=*/SourceLocation{},
2699 /*NLoc=*/SourceLocation{}, bindName, funcTy,
2700 /*TInfo=*/nullptr, StorageClass::SC_None);
2701
2703 params.reserve(fpt->getNumParams());
2704
2705 // Add all of the parameters.
2706 for (unsigned i = 0, e = fpt->getNumParams(); i != e; ++i) {
2708 ctx, tempFunc, /*StartLoc=*/SourceLocation{},
2709 /*IdLoc=*/SourceLocation{},
2710 /*Id=*/nullptr, fpt->getParamType(i), /*TInfo=*/nullptr,
2711 StorageClass::SC_None, /*DefArg=*/nullptr);
2712 parm->setScopeInfo(0, i);
2713 params.push_back(parm);
2714 }
2715
2716 tempFunc->setParams(params);
2717
2718 return tempFunc;
2719}
2720
2721std::string
2723 const FunctionDecl *attachedFunction) {
2725 getASTContext(), bindName, attachedFunction);
2726
2727 std::string ret = getMangledNameImpl(*this, GlobalDecl(tempFunc), tempFunc);
2728
2729 // This does nothing (it is a do-nothing function), since this is a
2730 // slab-allocator, but leave a call in to immediately destroy this in case we
2731 // ever come up with a way of getting allocations back.
2732 getASTContext().Deallocate(tempFunc);
2733 return ret;
2734}
2735
2737 GlobalDecl canonicalGd = gd.getCanonicalDecl();
2738
2739 // Some ABIs don't have constructor variants. Make sure that base and complete
2740 // constructors get mangled the same.
2741 if (const auto *cd = dyn_cast<CXXConstructorDecl>(canonicalGd.getDecl())) {
2742 if (!getTarget().getCXXABI().hasConstructorVariants()) {
2743 errorNYI(cd->getSourceRange(),
2744 "getMangledName: C++ constructor without variants");
2745 return cast<NamedDecl>(gd.getDecl())->getIdentifier()->getName();
2746 }
2747 }
2748
2749 // Keep the first result in the case of a mangling collision.
2750 const auto *nd = cast<NamedDecl>(gd.getDecl());
2751 std::string mangledName = getMangledNameImpl(*this, gd, nd);
2752
2753 auto result = manglings.insert(std::make_pair(mangledName, gd));
2754 return mangledDeclNames[canonicalGd] = result.first->first();
2755}
2756
2758 assert(!d->getInit() && "Cannot emit definite definitions here!");
2759
2760 StringRef mangledName = getMangledName(d);
2761 mlir::Operation *gv = getGlobalValue(mangledName);
2762
2763 // If we already have a definition, not declaration, with the same mangled
2764 // name, emitting of declaration is not required (and would actually overwrite
2765 // the emitted definition).
2766 if (gv && !mlir::cast<cir::GlobalOp>(gv).isDeclaration())
2767 return;
2768
2769 // If we have not seen a reference to this variable yet, place it into the
2770 // deferred declarations table to be emitted if needed later.
2771 if (!mustBeEmitted(d) && !gv) {
2772 deferredDecls[mangledName] = d;
2773 return;
2774 }
2775
2776 // The tentative definition is the only definition.
2778}
2779
2781 // Never defer when EmitAllDecls is specified.
2782 if (langOpts.EmitAllDecls)
2783 return true;
2784
2785 const auto *vd = dyn_cast<VarDecl>(global);
2786 if (vd &&
2787 ((codeGenOpts.KeepPersistentStorageVariables &&
2788 (vd->getStorageDuration() == SD_Static ||
2789 vd->getStorageDuration() == SD_Thread)) ||
2790 (codeGenOpts.KeepStaticConsts && vd->getStorageDuration() == SD_Static &&
2791 vd->getType().isConstQualified())))
2792 return true;
2793
2794 return getASTContext().DeclMustBeEmitted(global);
2795}
2796
2798 // In OpenMP 5.0 variables and function may be marked as
2799 // device_type(host/nohost) and we should not emit them eagerly unless we sure
2800 // that they must be emitted on the host/device. To be sure we need to have
2801 // seen a declare target with an explicit mentioning of the function, we know
2802 // we have if the level of the declare target attribute is -1. Note that we
2803 // check somewhere else if we should emit this at all.
2804 if (langOpts.OpenMP >= 50 && !langOpts.OpenMPSimd) {
2805 std::optional<OMPDeclareTargetDeclAttr *> activeAttr =
2806 OMPDeclareTargetDeclAttr::getActiveAttr(global);
2807 if (!activeAttr || (*activeAttr)->getLevel() != (unsigned)-1)
2808 return false;
2809 }
2810
2811 const auto *fd = dyn_cast<FunctionDecl>(global);
2812 if (fd) {
2813 // Implicit template instantiations may change linkage if they are later
2814 // explicitly instantiated, so they should not be emitted eagerly.
2815 if (fd->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
2816 return false;
2817 // Defer until all versions have been semantically checked.
2818 if (fd->hasAttr<TargetVersionAttr>() && !fd->isMultiVersion())
2819 return false;
2820 if (langOpts.SYCLIsDevice) {
2821 errorNYI(fd->getSourceRange(), "mayBeEmittedEagerly: SYCL");
2822 return false;
2823 }
2824 }
2825 const auto *vd = dyn_cast<VarDecl>(global);
2826 if (vd)
2827 if (astContext.getInlineVariableDefinitionKind(vd) ==
2829 // A definition of an inline constexpr static data member may change
2830 // linkage later if it's redeclared outside the class.
2831 return false;
2832
2833 // If OpenMP is enabled and threadprivates must be generated like TLS, delay
2834 // codegen for global variables, because they may be marked as threadprivate.
2835 if (langOpts.OpenMP && langOpts.OpenMPUseTLS &&
2836 astContext.getTargetInfo().isTLSSupported() && isa<VarDecl>(global) &&
2837 !global->getType().isConstantStorage(astContext, false, false) &&
2838 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(global))
2839 return false;
2840
2841 assert((fd || vd) &&
2842 "Only FunctionDecl and VarDecl should hit this path so far.");
2843 return true;
2844}
2845
2846static bool shouldAssumeDSOLocal(const CIRGenModule &cgm,
2847 cir::CIRGlobalValueInterface gv) {
2848 if (gv.hasLocalLinkage())
2849 return true;
2850
2851 if (!gv.hasDefaultVisibility() && !gv.hasExternalWeakLinkage())
2852 return true;
2853
2854 // DLLImport explicitly marks the GV as external.
2855 // so it shouldn't be dso_local
2856 // But we don't have the info set now
2858
2859 const llvm::Triple &tt = cgm.getTriple();
2860 const CodeGenOptions &cgOpts = cgm.getCodeGenOpts();
2861 if (tt.isOSCygMing()) {
2862 // In MinGW and Cygwin, variables without DLLImport can still be
2863 // automatically imported from a DLL by the linker; don't mark variables
2864 // that potentially could come from another DLL as DSO local.
2865
2866 // With EmulatedTLS, TLS variables can be autoimported from other DLLs
2867 // (and this actually happens in the public interface of libstdc++), so
2868 // such variables can't be marked as DSO local. (Native TLS variables
2869 // can't be dllimported at all, though.)
2870 cgm.errorNYI("shouldAssumeDSOLocal: MinGW");
2871 }
2872
2873 // On COFF, don't mark 'extern_weak' symbols as DSO local. If these symbols
2874 // remain unresolved in the link, they can be resolved to zero, which is
2875 // outside the current DSO.
2876 if (tt.isOSBinFormatCOFF() && gv.hasExternalWeakLinkage())
2877 return false;
2878
2879 // Every other GV is local on COFF.
2880 // Make an exception for windows OS in the triple: Some firmware builds use
2881 // *-win32-macho triples. This (accidentally?) produced windows relocations
2882 // without GOT tables in older clang versions; Keep this behaviour.
2883 // FIXME: even thread local variables?
2884 if (tt.isOSBinFormatCOFF() || (tt.isOSWindows() && tt.isOSBinFormatMachO()))
2885 return true;
2886
2887 // Only handle COFF and ELF for now.
2888 if (!tt.isOSBinFormatELF())
2889 return false;
2890
2891 llvm::Reloc::Model rm = cgOpts.RelocationModel;
2892 const LangOptions &lOpts = cgm.getLangOpts();
2893 if (rm != llvm::Reloc::Static && !lOpts.PIE) {
2894 // On ELF, if -fno-semantic-interposition is specified and the target
2895 // supports local aliases, there will be neither CC1
2896 // -fsemantic-interposition nor -fhalf-no-semantic-interposition. Set
2897 // dso_local on the function if using a local alias is preferable (can avoid
2898 // PLT indirection).
2899 if (!(isa<cir::FuncOp>(gv) && gv.canBenefitFromLocalAlias()))
2900 return false;
2901 return !(lOpts.SemanticInterposition || lOpts.HalfNoSemanticInterposition);
2902 }
2903
2904 // A definition cannot be preempted from an executable.
2905 if (!gv.isDeclarationForLinker())
2906 return true;
2907
2908 // Most PIC code sequences that assume that a symbol is local cannot produce a
2909 // 0 if it turns out the symbol is undefined. While this is ABI and relocation
2910 // depended, it seems worth it to handle it here.
2911 if (rm == llvm::Reloc::PIC_ && gv.hasExternalWeakLinkage())
2912 return false;
2913
2914 // PowerPC64 prefers TOC indirection to avoid copy relocations.
2915 if (tt.isPPC64())
2916 return false;
2917
2918 if (cgOpts.DirectAccessExternalData) {
2919 // If -fdirect-access-external-data (default for -fno-pic), set dso_local
2920 // for non-thread-local variables. If the symbol is not defined in the
2921 // executable, a copy relocation will be needed at link time. dso_local is
2922 // excluded for thread-local variables because they generally don't support
2923 // copy relocations.
2924 if (auto globalOp = dyn_cast<cir::GlobalOp>(gv.getOperation())) {
2925 // Assume variables are not thread-local until that support is added.
2927 return true;
2928 }
2929
2930 // -fno-pic sets dso_local on a function declaration to allow direct
2931 // accesses when taking its address (similar to a data symbol). If the
2932 // function is not defined in the executable, a canonical PLT entry will be
2933 // needed at link time. -fno-direct-access-external-data can avoid the
2934 // canonical PLT entry. We don't generalize this condition to -fpie/-fpic as
2935 // it could just cause trouble without providing perceptible benefits.
2936 if (isa<cir::FuncOp>(gv) && !cgOpts.NoPLT && rm == llvm::Reloc::Static)
2937 return true;
2938 }
2939
2940 // If we can use copy relocations we can assume it is local.
2941
2942 // Otherwise don't assume it is local.
2943
2944 return false;
2945}
2946
2947void CIRGenModule::setGlobalVisibility(cir::CIRGlobalValueInterface gv,
2948 const NamedDecl *d) const {
2949 // Internal definitions always have default visibility.
2950 if (gv.hasLocalLinkage()) {
2951 gv.setGlobalVisibility(cir::VisibilityKind::Default);
2952 return;
2953 }
2954 if (!d)
2955 return;
2956
2957 // Set visibility for definitions, and for declarations if requested globally
2958 // or set explicitly.
2960
2961 // OpenMP declare target variables must be visible to the host so they can
2962 // be registered. We require protected visibility unless the variable has
2963 // the DT_nohost modifier and does not need to be registered.
2964 if (getASTContext().getLangOpts().OpenMP &&
2965 getASTContext().getLangOpts().OpenMPIsTargetDevice && isa<VarDecl>(d) &&
2966 d->hasAttr<OMPDeclareTargetDeclAttr>() &&
2967 d->getAttr<OMPDeclareTargetDeclAttr>()->getDevType() !=
2968 OMPDeclareTargetDeclAttr::DT_NoHost &&
2970 llvm_unreachable("setGlobalVisibility: OpenMP is NYI");
2971 return;
2972 }
2973
2974 // CUDA/HIP device kernels and global variables must be visible to the host
2975 // so they can be registered / initialized. We require protected visibility
2976 // unless the user explicitly requested hidden via an attribute.
2977 if (getASTContext().getLangOpts().CUDAIsDevice &&
2979 !d->hasAttr<OMPDeclareTargetDeclAttr>()) {
2980 bool needsProtected = false;
2981 if (isa<FunctionDecl>(d)) {
2982 needsProtected =
2983 d->hasAttr<CUDAGlobalAttr>() || d->hasAttr<DeviceKernelAttr>();
2984 } else if (const auto *vd = dyn_cast<VarDecl>(d)) {
2985 needsProtected = vd->hasAttr<CUDADeviceAttr>() ||
2986 vd->hasAttr<CUDAConstantAttr>() ||
2987 vd->getType()->isCUDADeviceBuiltinSurfaceType() ||
2988 vd->getType()->isCUDADeviceBuiltinTextureType();
2989 }
2990 if (needsProtected) {
2991 gv.setGlobalVisibility(cir::VisibilityKind::Protected);
2992 return;
2993 }
2994 }
2995
2997 gv.setGlobalVisibility(cir::VisibilityKind::Hidden);
2998 return;
2999 }
3000
3002
3003 if (lv.isVisibilityExplicit() || getLangOpts().SetVisibilityForExternDecls ||
3004 !gv.isDeclarationForLinker())
3005 gv.setGlobalVisibility(getCIRVisibilityKind(lv.getVisibility()));
3006}
3007
3008void CIRGenModule::setDSOLocal(cir::CIRGlobalValueInterface gv) const {
3009 gv.setDSOLocal(shouldAssumeDSOLocal(*this, gv));
3010}
3011
3012void CIRGenModule::setDSOLocal(mlir::Operation *op) const {
3013 if (auto globalValue = dyn_cast<cir::CIRGlobalValueInterface>(op))
3014 setDSOLocal(globalValue);
3015}
3016
3017void CIRGenModule::setGVProperties(mlir::Operation *op,
3018 const NamedDecl *d) const {
3020 setGVPropertiesAux(op, d);
3021}
3022
3023void CIRGenModule::setGVPropertiesAux(mlir::Operation *op,
3024 const NamedDecl *d) const {
3026 setDSOLocal(op);
3028}
3029
3031 GlobalDecl &result) const {
3032 auto res = manglings.find(mangledName);
3033 if (res == manglings.end())
3034 return false;
3035 result = res->getValue();
3036 return true;
3037}
3038
3040 switch (getCodeGenOpts().getDefaultTLSModel()) {
3042 return cir::TLS_Model::GeneralDynamic;
3044 return cir::TLS_Model::LocalDynamic;
3046 return cir::TLS_Model::InitialExec;
3048 return cir::TLS_Model::LocalExec;
3049 }
3050 llvm_unreachable("Invalid TLS model!");
3051}
3052
3053void CIRGenModule::setTLSMode(mlir::Operation *op, const VarDecl &d,
3054 bool isExtendingDecl) {
3055 assert(d.getTLSKind() && "setting TLS mode on non-TLS var!");
3056
3057 cir::TLS_Model tlm = getDefaultCIRTLSModel();
3058
3059 // Override the TLS model if it is explicitly specified.
3060 if (d.getAttr<TLSModelAttr>())
3061 errorNYI(d.getSourceRange(), "TLS model attribute");
3062
3063 auto global = cast<cir::GlobalOp>(op);
3064 global.setTlsModel(tlm);
3065
3066 // For namespace-scope dyanmic TLS we need to set the wrapper, int, or guard
3067 // info.
3068 if (d.isStaticLocal() || tlm != cir::TLS_Model::GeneralDynamic)
3069 return;
3070
3071 // If this function was called to set the TLS mode for a temporary whose
3072 // lifetime is extended by the variable declared by `d`, don't emit the
3073 // wrapper, init, and guard info.
3074 if (isExtendingDecl)
3075 return;
3076
3077 setGlobalTlsReferences(d, global);
3078}
3079
3081 const CIRGenFunctionInfo &info,
3082 cir::FuncOp func, bool isThunk) {
3083 // TODO(cir): More logic of constructAttributeList is needed.
3084 cir::CallingConv callingConv;
3085 cir::SideEffect sideEffect;
3086
3087 // TODO(cir): The current list should be initialized with the extra function
3088 // attributes, but we don't have those yet. For now, the PAL is initialized
3089 // with nothing.
3091 // Initialize PAL with existing attributes to merge attributes.
3092 mlir::NamedAttrList pal{};
3093 std::vector<mlir::NamedAttrList> argAttrs(info.arguments().size());
3094 mlir::NamedAttrList retAttrs{};
3095 constructAttributeList(func.getName(), info, globalDecl, pal, argAttrs,
3096 retAttrs, callingConv, sideEffect,
3097 /*attrOnCallSite=*/false, isThunk);
3098
3099 for (mlir::NamedAttribute attr : pal)
3100 func->setAttr(attr.getName(), attr.getValue());
3101
3102 llvm::for_each(llvm::enumerate(argAttrs), [func](auto idx_arg_pair) {
3103 mlir::function_interface_impl::setArgAttrs(func, idx_arg_pair.index(),
3104 idx_arg_pair.value());
3105 });
3106 if (!retAttrs.empty())
3107 mlir::function_interface_impl::setResultAttrs(func, 0, retAttrs);
3108
3109 // TODO(cir): Check X86_VectorCall incompatibility wiht WinARM64EC
3110
3111 // TODO(cir): Set the calling convention computed by constructAttributeList
3112 // on the function. FuncOp supports calling_conv, but target-specific
3113 // CodeGen is needed to set it correctly (e.g., AMDGPU kernel functions
3114 // should be marked with AMDGPUKernel).
3116}
3117
3119 cir::FuncOp func,
3120 bool isIncompleteFunction,
3121 bool isThunk) {
3122 // NOTE(cir): Original CodeGen checks if this is an intrinsic. In CIR we
3123 // represent them in dedicated ops. The correct attributes are ensured during
3124 // translation to LLVM. Thus, we don't need to check for them here.
3125
3126 const auto *funcDecl = cast<FunctionDecl>(globalDecl.getDecl());
3127
3128 if (!isIncompleteFunction)
3129 setCIRFunctionAttributes(globalDecl,
3130 getTypes().arrangeGlobalDeclaration(globalDecl),
3131 func, isThunk);
3132
3133 if (!isIncompleteFunction && func.isDeclaration())
3134 getTargetCIRGenInfo().setTargetAttributes(funcDecl, func, *this);
3135
3136 // Mirrors setLinkageForGV in CodeGenModule::SetFunctionAttributes.
3137 setLinkageForFunction(*this, func, funcDecl);
3138
3139 // If we plan on emitting this inline builtin, we can't treat it as a builtin.
3140 if (funcDecl->isInlineBuiltinDeclaration()) {
3141 const FunctionDecl *fdBody;
3142 bool hasBody = funcDecl->hasBody(fdBody);
3143 (void)hasBody;
3144 assert(hasBody && "Inline builtin declarations should always have an "
3145 "available body!");
3147 }
3148
3149 if (funcDecl->isReplaceableGlobalAllocationFunction()) {
3150 // A replaceable global allocation function does not act like a builtin by
3151 // default, only if it is invoked by a new-expression or delete-expression.
3152 func->setAttr(cir::CIRDialect::getNoBuiltinAttrName(),
3153 mlir::UnitAttr::get(&getMLIRContext()));
3154 }
3155}
3156
3157/// Determines whether the language options require us to model
3158/// unwind exceptions. We treat -fexceptions as mandating this
3159/// except under the fragile ObjC ABI with only ObjC exceptions
3160/// enabled. This means, for example, that C with -fexceptions
3161/// enables this.
3162static bool hasUnwindExceptions(const LangOptions &langOpts) {
3163 // If exceptions are completely disabled, obviously this is false.
3164 if (!langOpts.Exceptions)
3165 return false;
3166 // If C++ exceptions are enabled, this is true.
3167 if (langOpts.CXXExceptions)
3168 return true;
3169 // If ObjC exceptions are enabled, this depends on the ABI.
3170 if (langOpts.ObjCExceptions)
3171 return langOpts.ObjCRuntime.hasUnwindExceptions();
3172 return true;
3173}
3174
3176 const clang::FunctionDecl *decl, cir::FuncOp f) {
3179
3180 if (!hasUnwindExceptions(langOpts))
3181 f->setAttr(cir::CIRDialect::getNoThrowAttrName(),
3182 mlir::UnitAttr::get(&getMLIRContext()));
3183
3184 std::optional<cir::InlineKind> existingInlineKind = f.getInlineKind();
3185 bool isNoInline =
3186 existingInlineKind && *existingInlineKind == cir::InlineKind::NoInline;
3187 bool isAlwaysInline = existingInlineKind &&
3188 *existingInlineKind == cir::InlineKind::AlwaysInline;
3189 if (!decl) {
3190 assert(!cir::MissingFeatures::hlsl());
3191
3192 if (!isAlwaysInline &&
3193 codeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) {
3194 // If inlining is disabled and we don't have a declaration to control
3195 // inlining, mark the function as 'noinline' unless it is explicitly
3196 // marked as 'alwaysinline'.
3197 f.setInlineKind(cir::InlineKind::NoInline);
3198 }
3199
3200 return;
3201 }
3202
3209 assert(!cir::MissingFeatures::hlsl());
3210
3211 // Handle inline attributes
3212 if (decl->hasAttr<NoInlineAttr>() && !isAlwaysInline) {
3213 // Add noinline if the function isn't always_inline.
3214 f.setInlineKind(cir::InlineKind::NoInline);
3215 } else if (decl->hasAttr<AlwaysInlineAttr>() && !isNoInline) {
3216 // Don't override AlwaysInline with NoInline, or vice versa, since we can't
3217 // specify both in IR.
3218 f.setInlineKind(cir::InlineKind::AlwaysInline);
3219 } else if (codeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) {
3220 // If inlining is disabled, force everything that isn't always_inline
3221 // to carry an explicit noinline attribute.
3222 if (!isAlwaysInline)
3223 f.setInlineKind(cir::InlineKind::NoInline);
3224 } else {
3225 // Otherwise, propagate the inline hint attribute and potentially use its
3226 // absence to mark things as noinline.
3227 // Search function and template pattern redeclarations for inline.
3228 if (auto *fd = dyn_cast<FunctionDecl>(decl)) {
3229 // TODO: Share this checkForInline implementation with classic codegen.
3230 // This logic is likely to change over time, so sharing would help ensure
3231 // consistency.
3232 auto checkForInline = [](const FunctionDecl *decl) {
3233 auto checkRedeclForInline = [](const FunctionDecl *redecl) {
3234 return redecl->isInlineSpecified();
3235 };
3236 if (any_of(decl->redecls(), checkRedeclForInline))
3237 return true;
3238 const FunctionDecl *pattern = decl->getTemplateInstantiationPattern();
3239 if (!pattern)
3240 return false;
3241 return any_of(pattern->redecls(), checkRedeclForInline);
3242 };
3243 if (checkForInline(fd)) {
3244 f.setInlineKind(cir::InlineKind::InlineHint);
3245 } else if (codeGenOpts.getInlining() ==
3247 !fd->isInlined() && !isAlwaysInline) {
3248 f.setInlineKind(cir::InlineKind::NoInline);
3249 }
3250 }
3251 }
3252
3254}
3255
3257 StringRef mangledName, mlir::Type funcType, GlobalDecl gd, bool forVTable,
3258 bool dontDefer, bool isThunk, ForDefinition_t isForDefinition,
3259 mlir::NamedAttrList extraAttrs) {
3260 const Decl *d = gd.getDecl();
3261
3262 if (const auto *fd = cast_or_null<FunctionDecl>(d)) {
3263 // For the device, mark the function as one that should be emitted.
3264 if (getLangOpts().OpenMPIsTargetDevice && openMPRuntime &&
3265 !getOpenMPRuntime().markAsGlobalTarget(gd) && fd->isDefined() &&
3266 !dontDefer && !isForDefinition) {
3267 if (const FunctionDecl *fdDef = fd->getDefinition()) {
3268 GlobalDecl gdDef;
3269 if (const auto *cd = dyn_cast<CXXConstructorDecl>(fdDef))
3270 gdDef = GlobalDecl(cd, gd.getCtorType());
3271 else if (const auto *dd = dyn_cast<CXXDestructorDecl>(fdDef))
3272 gdDef = GlobalDecl(dd, gd.getDtorType());
3273 else
3274 gdDef = GlobalDecl(fdDef);
3275 emitGlobal(gdDef);
3276 }
3277 }
3278
3279 // Any attempts to use a MultiVersion function should result in retrieving
3280 // the iFunc instead. Name mangling will handle the rest of the changes.
3281 if (fd->isMultiVersion())
3282 errorNYI(fd->getSourceRange(), "getOrCreateCIRFunction: multi-version");
3283 }
3284
3285 // Lookup the entry, lazily creating it if necessary.
3286 mlir::Operation *entry = getGlobalValue(mangledName);
3287 if (entry) {
3288 assert(mlir::isa<cir::FuncOp>(entry));
3289
3291
3292 // Handle dropped DLL attributes.
3293 if (d && !d->hasAttr<DLLImportAttr>() && !d->hasAttr<DLLExportAttr>()) {
3295 setDSOLocal(entry);
3296 }
3297
3298 // If there are two attempts to define the same mangled name, issue an
3299 // error.
3300 auto fn = cast<cir::FuncOp>(entry);
3301 if (isForDefinition && fn && !fn.isDeclaration()) {
3302 GlobalDecl otherGd;
3303 // Check that GD is not yet in DiagnosedConflictingDefinitions is required
3304 // to make sure that we issue an error only once.
3305 if (lookupRepresentativeDecl(mangledName, otherGd) &&
3306 (gd.getCanonicalDecl().getDecl() !=
3307 otherGd.getCanonicalDecl().getDecl()) &&
3308 diagnosedConflictingDefinitions.insert(gd).second) {
3309 getDiags().Report(d->getLocation(), diag::err_duplicate_mangled_name)
3310 << mangledName;
3311 getDiags().Report(otherGd.getDecl()->getLocation(),
3312 diag::note_previous_definition);
3313 }
3314 }
3315
3316 if (fn && fn.getFunctionType() == funcType) {
3317 return fn;
3318 }
3319
3320 if (!isForDefinition) {
3321 return fn;
3322 }
3323
3324 // TODO(cir): classic codegen checks here if this is a llvm::GlobalAlias.
3325 // How will we support this?
3326 }
3327
3328 auto *funcDecl = llvm::cast_or_null<FunctionDecl>(gd.getDecl());
3329 bool invalidLoc = !funcDecl ||
3330 funcDecl->getSourceRange().getBegin().isInvalid() ||
3331 funcDecl->getSourceRange().getEnd().isInvalid();
3332 cir::FuncOp funcOp = createCIRFunction(
3333 invalidLoc ? theModule->getLoc() : getLoc(funcDecl->getSourceRange()),
3334 mangledName, mlir::cast<cir::FuncType>(funcType), funcDecl);
3335
3336 if (funcDecl && funcDecl->hasAttr<AnnotateAttr>())
3337 deferredAnnotations[mangledName] = funcDecl;
3338
3339 // If we already created a function with the same mangled name (but different
3340 // type) before, take its name and add it to the list of functions to be
3341 // replaced with F at the end of CodeGen.
3342 //
3343 // This happens if there is a prototype for a function (e.g. "int f()") and
3344 // then a definition of a different type (e.g. "int f(int x)").
3345 if (entry) {
3346
3347 // Fetch a generic symbol-defining operation and its uses.
3348 auto symbolOp = mlir::cast<mlir::SymbolOpInterface>(entry);
3349
3350 // This might be an implementation of a function without a prototype, in
3351 // which case, try to do special replacement of calls which match the new
3352 // prototype. The really key thing here is that we also potentially drop
3353 // arguments from the call site so as to make a direct call, which makes the
3354 // inliner happier and suppresses a number of optimizer warnings (!) about
3355 // dropping arguments.
3356 if (symbolOp.getSymbolUses(symbolOp->getParentOp()))
3358
3359 // Obliterate no-proto declaration.
3360 eraseGlobalSymbol(entry);
3361 entry->erase();
3362 }
3363
3364 if (d)
3365 setFunctionAttributes(gd, funcOp, /*isIncompleteFunction=*/false, isThunk);
3366 if (!extraAttrs.empty()) {
3367 extraAttrs.append(funcOp->getAttrs());
3368 funcOp->setAttrs(extraAttrs);
3369 }
3370
3371 // 'dontDefer' actually means don't move this to the deferredDeclsToEmit list.
3372 if (dontDefer) {
3373 // TODO(cir): This assertion will need an additional condition when we
3374 // support incomplete functions.
3375 assert(funcOp.getFunctionType() == funcType);
3376 return funcOp;
3377 }
3378
3379 // All MSVC dtors other than the base dtor are linkonce_odr and delegate to
3380 // each other bottoming out wiht the base dtor. Therefore we emit non-base
3381 // dtors on usage, even if there is no dtor definition in the TU.
3382 if (isa_and_nonnull<CXXDestructorDecl>(d) &&
3383 getCXXABI().useThunkForDtorVariant(cast<CXXDestructorDecl>(d),
3384 gd.getDtorType()))
3385 errorNYI(d->getSourceRange(), "getOrCreateCIRFunction: dtor");
3386
3387 // This is the first use or definition of a mangled name. If there is a
3388 // deferred decl with this name, remember that we need to emit it at the end
3389 // of the file.
3390 auto ddi = deferredDecls.find(mangledName);
3391 if (ddi != deferredDecls.end()) {
3392 // Move the potentially referenced deferred decl to the
3393 // DeferredDeclsToEmit list, and remove it from DeferredDecls (since we
3394 // don't need it anymore).
3395 addDeferredDeclToEmit(ddi->second);
3396 deferredDecls.erase(ddi);
3397
3398 // Otherwise, there are cases we have to worry about where we're using a
3399 // declaration for which we must emit a definition but where we might not
3400 // find a top-level definition.
3401 // - member functions defined inline in their classes
3402 // - friend functions defined inline in some class
3403 // - special member functions with implicit definitions
3404 // If we ever change our AST traversal to walk into class methods, this
3405 // will be unnecessary.
3406 //
3407 // We also don't emit a definition for a function if it's going to be an
3408 // entry in a vtable, unless it's already marked as used.
3409 } else if (getLangOpts().CPlusPlus && d) {
3410 // Look for a declaration that's lexically in a record.
3411 for (const auto *fd = cast<FunctionDecl>(d)->getMostRecentDecl(); fd;
3412 fd = fd->getPreviousDecl()) {
3413 if (isa<CXXRecordDecl>(fd->getLexicalDeclContext())) {
3414 if (fd->doesThisDeclarationHaveABody()) {
3416 break;
3417 }
3418 }
3419 }
3420 }
3421
3422 return funcOp;
3423}
3424
3425cir::FuncOp
3426CIRGenModule::createCIRFunction(mlir::Location loc, StringRef name,
3427 cir::FuncType funcType,
3428 const clang::FunctionDecl *funcDecl) {
3429 cir::FuncOp func;
3430 {
3431 mlir::OpBuilder::InsertionGuard guard(builder);
3432
3433 // Some global emissions are triggered while emitting a function, e.g.
3434 // void s() { x.method() }
3435 //
3436 // Be sure to insert a new function before a current one.
3437 CIRGenFunction *cgf = this->curCGF;
3438 if (cgf)
3439 builder.setInsertionPoint(cgf->curFn);
3440
3441 func = cir::FuncOp::create(builder, loc, name, funcType);
3442
3443 symbolLookupCache[func.getSymNameAttr()] = func;
3444
3446
3447 if (funcDecl && !funcDecl->hasPrototype())
3448 func.setNoProto(true);
3449
3450 assert(func.isDeclaration() && "expected empty body");
3451
3452 // A declaration gets private visibility by default, but external linkage
3453 // as the default linkage.
3454 func.setLinkageAttr(cir::GlobalLinkageKindAttr::get(
3455 &getMLIRContext(), cir::GlobalLinkageKind::ExternalLinkage));
3456 mlir::SymbolTable::setSymbolVisibility(
3457 func, mlir::SymbolTable::Visibility::Private);
3458
3460
3461 // Mark C++ special member functions (Constructor, Destructor etc.)
3462 setCXXSpecialMemberAttr(func, funcDecl);
3463
3464 if (!cgf)
3465 theModule.push_back(func);
3466
3467 if (this->getLangOpts().OpenACC) {
3468 // We only have to handle this attribute, since OpenACCAnnotAttrs are
3469 // handled via the end-of-TU work.
3470 for (const auto *attr :
3471 funcDecl->specific_attrs<OpenACCRoutineDeclAttr>())
3472 emitOpenACCRoutineDecl(funcDecl, func, attr->getLocation(),
3473 attr->Clauses);
3474 }
3475 }
3476 return func;
3477}
3478
3479cir::FuncOp
3480CIRGenModule::createCIRBuiltinFunction(mlir::Location loc, StringRef name,
3481 cir::FuncType ty,
3482 const clang::FunctionDecl *fd) {
3483 cir::FuncOp fnOp = createCIRFunction(loc, name, ty, fd);
3484 fnOp.setBuiltin(true);
3485 return fnOp;
3486}
3487
3488static cir::CtorKind getCtorKindFromDecl(const CXXConstructorDecl *ctor) {
3489 if (ctor->isDefaultConstructor())
3490 return cir::CtorKind::Default;
3491 if (ctor->isCopyConstructor())
3492 return cir::CtorKind::Copy;
3493 if (ctor->isMoveConstructor())
3494 return cir::CtorKind::Move;
3495 return cir::CtorKind::Custom;
3496}
3497
3498static cir::AssignKind getAssignKindFromDecl(const CXXMethodDecl *method) {
3499 if (method->isCopyAssignmentOperator())
3500 return cir::AssignKind::Copy;
3501 if (method->isMoveAssignmentOperator())
3502 return cir::AssignKind::Move;
3503 llvm_unreachable("not a copy or move assignment operator");
3504}
3505
3507 cir::FuncOp funcOp, const clang::FunctionDecl *funcDecl) {
3508 if (!funcDecl)
3509 return;
3510
3511 if (const auto *dtor = dyn_cast<CXXDestructorDecl>(funcDecl)) {
3512 auto cxxDtor = cir::CXXDtorAttr::get(
3513 convertType(getASTContext().getCanonicalTagType(dtor->getParent())),
3514 dtor->isTrivial());
3515 funcOp.setFuncInfoAttr(cxxDtor);
3516 return;
3517 }
3518
3519 if (const auto *ctor = dyn_cast<CXXConstructorDecl>(funcDecl)) {
3520 cir::CtorKind kind = getCtorKindFromDecl(ctor);
3521 auto cxxCtor = cir::CXXCtorAttr::get(
3522 convertType(getASTContext().getCanonicalTagType(ctor->getParent())),
3523 kind, ctor->isTrivial());
3524 funcOp.setFuncInfoAttr(cxxCtor);
3525 return;
3526 }
3527
3528 const auto *method = dyn_cast<CXXMethodDecl>(funcDecl);
3529 if (method && (method->isCopyAssignmentOperator() ||
3530 method->isMoveAssignmentOperator())) {
3531 cir::AssignKind assignKind = getAssignKindFromDecl(method);
3532 auto cxxAssign = cir::CXXAssignAttr::get(
3533 convertType(getASTContext().getCanonicalTagType(method->getParent())),
3534 assignKind, method->isTrivial());
3535 funcOp.setFuncInfoAttr(cxxAssign);
3536 return;
3537 }
3538}
3539
3540static void setWindowsItaniumDLLImport(CIRGenModule &cgm, bool isLocal,
3541 cir::FuncOp funcOp, StringRef name) {
3542 // In Windows Itanium environments, try to mark runtime functions
3543 // dllimport. For Mingw and MSVC, don't. We don't really know if the user
3544 // will link their standard library statically or dynamically. Marking
3545 // functions imported when they are not imported can cause linker errors
3546 // and warnings.
3547 if (!isLocal && cgm.getTarget().getTriple().isWindowsItaniumEnvironment() &&
3548 !cgm.getCodeGenOpts().LTOVisibilityPublicStd) {
3552 }
3553}
3554
3555cir::FuncOp CIRGenModule::createRuntimeFunction(cir::FuncType ty,
3556 StringRef name,
3557 mlir::NamedAttrList extraAttrs,
3558 bool isLocal,
3559 bool assumeConvergent) {
3560 if (assumeConvergent)
3561 errorNYI("createRuntimeFunction: assumeConvergent");
3562
3563 cir::FuncOp entry = getOrCreateCIRFunction(name, ty, GlobalDecl(),
3564 /*forVtable=*/false, extraAttrs);
3565
3566 if (entry) {
3567 // TODO(cir): set the attributes of the function.
3570 setWindowsItaniumDLLImport(*this, isLocal, entry, name);
3571 entry.setDSOLocal(true);
3572 }
3573
3574 return entry;
3575}
3576
3577mlir::SymbolTable::Visibility
3579 // MLIR doesn't accept public symbols declarations (only
3580 // definitions).
3581 if (op.isDeclaration())
3582 return mlir::SymbolTable::Visibility::Private;
3583 return getMLIRVisibilityFromCIRLinkage(op.getLinkage());
3584}
3585
3586mlir::SymbolTable::Visibility
3588 switch (glk) {
3589 case cir::GlobalLinkageKind::InternalLinkage:
3590 case cir::GlobalLinkageKind::PrivateLinkage:
3591 return mlir::SymbolTable::Visibility::Private;
3592 case cir::GlobalLinkageKind::ExternalLinkage:
3593 case cir::GlobalLinkageKind::ExternalWeakLinkage:
3594 case cir::GlobalLinkageKind::LinkOnceODRLinkage:
3595 case cir::GlobalLinkageKind::AvailableExternallyLinkage:
3596 case cir::GlobalLinkageKind::CommonLinkage:
3597 case cir::GlobalLinkageKind::WeakAnyLinkage:
3598 case cir::GlobalLinkageKind::WeakODRLinkage:
3599 return mlir::SymbolTable::Visibility::Public;
3600 default: {
3601 llvm::errs() << "visibility not implemented for '"
3602 << stringifyGlobalLinkageKind(glk) << "'\n";
3603 assert(0 && "not implemented");
3604 }
3605 }
3606 llvm_unreachable("linkage should be handled above!");
3607}
3608
3610 clang::VisibilityAttr::VisibilityType visibility) {
3611 switch (visibility) {
3612 case clang::VisibilityAttr::VisibilityType::Default:
3613 return cir::VisibilityKind::Default;
3614 case clang::VisibilityAttr::VisibilityType::Hidden:
3615 return cir::VisibilityKind::Hidden;
3616 case clang::VisibilityAttr::VisibilityType::Protected:
3617 return cir::VisibilityKind::Protected;
3618 }
3619 llvm_unreachable("unexpected visibility value");
3620}
3621
3622cir::VisibilityAttr
3624 const clang::VisibilityAttr *va = decl->getAttr<clang::VisibilityAttr>();
3625 cir::VisibilityAttr cirVisibility =
3626 cir::VisibilityAttr::get(&getMLIRContext());
3627 if (va) {
3628 cirVisibility = cir::VisibilityAttr::get(
3629 &getMLIRContext(),
3630 getGlobalVisibilityKindFromClangVisibility(va->getVisibility()));
3631 }
3632 return cirVisibility;
3633}
3634
3636 emitDeferred();
3638 applyReplacements();
3639
3640 theModule->setAttr(cir::CIRDialect::getModuleLevelAsmAttrName(),
3641 builder.getArrayAttr(globalScopeAsm));
3642
3643 emitGlobalAnnotations();
3644
3645 if (!recordLayoutEntries.empty())
3646 theModule->setAttr(
3647 cir::CIRDialect::getRecordLayoutsAttrName(),
3648 mlir::DictionaryAttr::get(&getMLIRContext(), recordLayoutEntries));
3649
3650 if (getTriple().isAMDGPU() ||
3651 (getTriple().isSPIRV() && getTriple().getVendor() == llvm::Triple::AMD))
3653
3654 if (getLangOpts().HIP) {
3655 // Emit a unique ID so that host and device binaries from the same
3656 // compilation unit can be associated.
3657 std::string cuidName =
3658 ("__hip_cuid_" + getASTContext().getCUIDHash()).str();
3659 auto int8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/false);
3660 auto loc = builder.getUnknownLoc();
3661 mlir::ptr::MemorySpaceAttrInterface addrSpace =
3662 cir::LangAddressSpaceAttr::get(&getMLIRContext(),
3663 getGlobalVarAddressSpace(nullptr));
3664
3665 auto gv = createGlobalOp(loc, cuidName, int8Ty,
3666 /*isConstant=*/false, addrSpace);
3667 gv.setLinkage(cir::GlobalLinkageKind::ExternalLinkage);
3668 // Initialize with zero
3669 auto zeroAttr = cir::IntAttr::get(int8Ty, 0);
3670 gv.setInitialValueAttr(zeroAttr);
3671 // External linkage requires public visibility
3672 mlir::SymbolTable::setSymbolVisibility(
3673 gv, mlir::SymbolTable::Visibility::Public);
3674
3676 }
3677
3678 if (astContext.getLangOpts().CUDA && cudaRuntime)
3680
3681 emitLLVMUsed();
3682
3683 // Classic codegen calls `checkAliases` here to validate any alias
3684 // definitions emitted during codegen.
3686
3687 // There's a lot of code that is not implemented yet.
3689}
3690
3692 const auto *d = cast<ValueDecl>(gd.getDecl());
3693 const AliasAttr *aa = d->getAttr<AliasAttr>();
3694 assert(aa && "Not an alias?");
3695
3696 StringRef mangledName = getMangledName(gd);
3697
3698 if (aa->getAliasee() == mangledName) {
3699 diags.Report(aa->getLocation(), diag::err_cyclic_alias) << 0;
3700 return;
3701 }
3702
3703 // If there is a definition in the module, then it wins over the alias.
3704 // This is dubious, but allow it to be safe. Just ignore the alias.
3705 mlir::Operation *entry = getGlobalValue(mangledName);
3706 if (entry) {
3707 auto entryGV = mlir::dyn_cast<cir::CIRGlobalValueInterface>(entry);
3708 if (entryGV && entryGV.isDefinition())
3709 return;
3710 }
3711
3712 // Classic codegen pushes the alias onto an `Aliases` list at this point so
3713 // that `checkAliases` can later validate the alias and recover on error.
3715
3716 mlir::Location loc = getLoc(d->getSourceRange());
3717 bool isFunction = isa<FunctionDecl>(d);
3718
3719 // Get the linkage and the type of the alias.
3720 mlir::Type declTy;
3721 cir::GlobalLinkageKind linkage;
3722 if (isFunction) {
3723 declTy = getTypes().getFunctionType(gd);
3724 linkage = getFunctionLinkage(gd);
3725 } else {
3726 declTy = getTypes().convertTypeForMem(d->getType());
3727 const auto *vd = cast<VarDecl>(d);
3728 linkage = getCIRLinkageVarDefinition(vd);
3729 }
3730
3731 // Aliases that target weak symbols must themselves be marked weak.
3732 if (d->hasAttr<WeakAttr>() || d->hasAttr<WeakRefAttr>() ||
3733 d->isWeakImported())
3734 linkage = cir::GlobalLinkageKind::WeakAnyLinkage;
3735
3736 // Create the alias op. If there is an existing declaration with the same
3737 // name, erase it: any references to it via flat symbol reference will
3738 // automatically resolve to the new alias.
3739 if (entry) {
3740 eraseGlobalSymbol(entry);
3741 entry->erase();
3742 }
3743
3744 // Aliases are always definitions, so the MLIR visibility should match the
3745 // linkage rather than defaulting to private.
3746 mlir::SymbolTable::Visibility visibility =
3748
3749 // TODO(cir): Make GlobalAlias a separate op.
3750 cir::CIRGlobalValueInterface alias =
3751 isFunction ? mlir::cast<cir::CIRGlobalValueInterface>(
3752 createCIRFunction(loc, mangledName,
3753 mlir::cast<cir::FuncType>(declTy),
3755 .getOperation())
3756 : mlir::cast<cir::CIRGlobalValueInterface>(
3757 createGlobalOp(loc, mangledName, declTy).getOperation());
3758 alias.setAliasee(aa->getAliasee());
3759 alias.setLinkage(linkage);
3760 mlir::SymbolTable::setSymbolVisibility(alias, visibility);
3762 setCommonAttributes(gd, alias);
3764}
3765
3766void CIRGenModule::emitAliasForGlobal(StringRef mangledName,
3767 mlir::Operation *op, GlobalDecl aliasGD,
3768 cir::FuncOp aliasee,
3769 cir::GlobalLinkageKind linkage) {
3770
3771 auto *aliasFD = dyn_cast<FunctionDecl>(aliasGD.getDecl());
3772 assert(aliasFD && "expected FunctionDecl");
3773
3774 // The aliasee function type is different from the alias one, this difference
3775 // is specific to CIR because in LLVM the ptr types are already erased at this
3776 // point.
3777 const CIRGenFunctionInfo &fnInfo =
3779 cir::FuncType fnType = getTypes().getFunctionType(fnInfo);
3780
3781 cir::FuncOp alias =
3783 mangledName, fnType, aliasFD);
3784 alias.setAliasee(aliasee.getName());
3785 alias.setLinkage(linkage);
3786 // Declarations cannot have public MLIR visibility, just mark them private
3787 // but this really should have no meaning since CIR should not be using
3788 // this information to derive linkage information.
3789 mlir::SymbolTable::setSymbolVisibility(
3790 alias, mlir::SymbolTable::Visibility::Private);
3791
3792 // Alias constructors and destructors are always unnamed_addr.
3794
3795 if (op) {
3796 // Any existing users of the existing function declaration will be
3797 // referencing the function by flat symbol reference (i.e. the name), so
3798 // those uses will automatically resolve to the alias now that we've
3799 // replaced the function declaration. We can safely erase the existing
3800 // function declaration.
3801 assert(cast<cir::FuncOp>(op).getFunctionType() == alias.getFunctionType() &&
3802 "declaration exists with different type");
3804 op->erase();
3805 } else {
3806 // Name already set by createCIRFunction
3807 }
3808
3809 // Finally, set up the alias with its proper name and attributes.
3810 setCommonAttributes(aliasGD, alias);
3811}
3812
3814 return genTypes.convertType(type);
3815}
3816
3818 // Verify the module after we have finished constructing it, this will
3819 // check the structural properties of the IR and invoke any specific
3820 // verifiers we have on the CIR operations.
3821 return mlir::verify(theModule).succeeded();
3822}
3823
3824mlir::Attribute CIRGenModule::getAddrOfRTTIDescriptor(mlir::Location loc,
3825 QualType ty, bool forEh) {
3826 // Return a bogus pointer if RTTI is disabled, unless it's for EH.
3827 // FIXME: should we even be calling this method if RTTI is disabled
3828 // and it's not for EH?
3829 if (!shouldEmitRTTI(forEh))
3830 return builder.getConstNullPtrAttr(builder.getUInt8PtrTy());
3831
3832 if (forEh && ty->isObjCObjectPointerType() &&
3833 langOpts.ObjCRuntime.isGNUFamily()) {
3834 errorNYI(loc, "getAddrOfRTTIDescriptor: Objc PtrType & Objc RT GUN");
3835 return {};
3836 }
3837
3838 return getCXXABI().getAddrOfRTTIDescriptor(loc, ty);
3839}
3840
3841// TODO(cir): this can be shared with LLVM codegen.
3843 const CXXRecordDecl *derivedClass,
3844 llvm::iterator_range<CastExpr::path_const_iterator> path) {
3845 CharUnits offset = CharUnits::Zero();
3846
3847 const ASTContext &astContext = getASTContext();
3848 const CXXRecordDecl *rd = derivedClass;
3849
3850 for (const CXXBaseSpecifier *base : path) {
3851 assert(!base->isVirtual() && "Should not see virtual bases here!");
3852
3853 // Get the layout.
3854 const ASTRecordLayout &layout = astContext.getASTRecordLayout(rd);
3855
3856 const auto *baseDecl = base->getType()->castAsCXXRecordDecl();
3857
3858 // Add the offset.
3859 offset += layout.getBaseClassOffset(baseDecl);
3860
3861 rd = baseDecl;
3862 }
3863
3864 return offset;
3865}
3866
3868 llvm::StringRef feature) {
3869 unsigned diagID = diags.getCustomDiagID(
3870 DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0");
3871 return diags.Report(loc, diagID) << feature;
3872}
3873
3875 llvm::StringRef feature) {
3876 return errorNYI(loc.getBegin(), feature) << loc;
3877}
3878
3880 unsigned diagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error, "%0");
3881 getDiags().Report(astContext.getFullLoc(loc), diagID) << error;
3882}
3883
3884/// Print out an error that codegen doesn't support the specified stmt yet.
3885void CIRGenModule::errorUnsupported(const Stmt *s, llvm::StringRef type) {
3886 unsigned diagId = diags.getCustomDiagID(DiagnosticsEngine::Error,
3887 "cannot compile this %0 yet");
3888 diags.Report(astContext.getFullLoc(s->getBeginLoc()), diagId)
3889 << type << s->getSourceRange();
3890}
3891
3892/// Print out an error that codegen doesn't support the specified decl yet.
3893void CIRGenModule::errorUnsupported(const Decl *d, llvm::StringRef type) {
3894 unsigned diagId = diags.getCustomDiagID(DiagnosticsEngine::Error,
3895 "cannot compile this %0 yet");
3896 diags.Report(astContext.getFullLoc(d->getLocation()), diagId) << type;
3897}
3898
3899void CIRGenModule::mapBlockAddress(cir::BlockAddrInfoAttr blockInfo,
3900 cir::LabelOp label) {
3901 [[maybe_unused]] auto result =
3902 blockAddressInfoToLabel.try_emplace(blockInfo, label);
3903 assert(result.second &&
3904 "attempting to map a blockaddress info that is already mapped");
3905}
3906
3907cir::LabelOp
3908CIRGenModule::lookupBlockAddressInfo(cir::BlockAddrInfoAttr blockInfo) {
3909 return blockAddressInfoToLabel.lookup(blockInfo);
3910}
3911
3912mlir::Operation *
3914 const Expr *init) {
3915 assert((mte->getStorageDuration() == SD_Static ||
3916 mte->getStorageDuration() == SD_Thread) &&
3917 "not a global temporary");
3918 const auto *varDecl = cast<VarDecl>(mte->getExtendingDecl());
3919
3920 // Use the MaterializeTemporaryExpr's type if it has the same unqualified
3921 // base type as Init. This preserves cv-qualifiers (e.g. const from a
3922 // constexpr or const-ref binding) that skipRValueSubobjectAdjustments may
3923 // have dropped via NoOp casts, while correctly falling back to Init's type
3924 // when a real subobject adjustment changed the type (e.g. member access or
3925 // base-class cast in C++98), where E->getType() reflects the reference type,
3926 // not the actual storage type.
3927 QualType materializedType = init->getType();
3928 if (getASTContext().hasSameUnqualifiedType(mte->getType(), materializedType))
3929 materializedType = mte->getType();
3930
3931 CharUnits align = getASTContext().getTypeAlignInChars(materializedType);
3932 mlir::Location loc = getLoc(mte->getSourceRange());
3933
3934 // FIXME: If an externally-visible declaration extends multiple temporaries,
3935 // we need to give each temporary the same name in every translation unit (and
3936 // we also need to make the temporaries externally-visible).
3938 llvm::raw_svector_ostream out(name);
3940 varDecl, mte->getManglingNumber(), out);
3941
3942 auto insertResult = materializedGlobalTemporaryMap.insert({mte, nullptr});
3943 if (!insertResult.second) {
3944 mlir::Type type = getTypes().convertTypeForMem(materializedType);
3945 // We've seen this before: either we already created it or we're in the
3946 // process of doing so.
3947 if (!insertResult.first->second) {
3948 // We recursively re-entered this function, probably during emission of
3949 // the initializer. Create a placeholder.
3950 insertResult.first->second =
3951 createGlobalOp(loc, name, type, /*isConstant=*/false);
3952 }
3953 return insertResult.first->second;
3954 }
3955
3956 APValue *value = nullptr;
3957 if (mte->getStorageDuration() == SD_Static && varDecl->evaluateValue()) {
3958 // If the initializer of the extending declaration is a constant
3959 // initializer, we should have a cached constant initializer for this
3960 // temporay. Note taht this m ight have a different value from the value
3961 // computed by evaluating the initializer if the surrounding constant
3962 // expression modifies the temporary.
3963 value = mte->getOrCreateValue(/*MayCreate=*/false);
3964 }
3965
3966 // Try evaluating it now, it might have a constant initializer
3967 Expr::EvalResult evalResult;
3968 if (!value && init->EvaluateAsRValue(evalResult, getASTContext()) &&
3969 !evalResult.hasSideEffects())
3970 value = &evalResult.Val;
3971
3973
3974 std::optional<ConstantEmitter> emitter;
3975 mlir::Attribute initialValue = nullptr;
3976 bool isConstant = false;
3977 mlir::Type type;
3978
3979 if (value) {
3980 emitter.emplace(*this);
3981 initialValue = emitter->emitForInitializer(*value, materializedType);
3982
3983 isConstant = materializedType.isConstantStorage(
3984 getASTContext(), /*ExcludeCtor=*/value, /*ExcludeDtor=*/false);
3985
3986 type = mlir::cast<mlir::TypedAttr>(initialValue).getType();
3987 } else {
3988 // No initializer, the initialization will be provided when we initialize
3989 // the declaration which performed lifetime extension.
3990 type = getTypes().convertTypeForMem(materializedType);
3991 }
3992
3993 // Create a global variable for this lifetime-extended temporary.
3994 cir::GlobalLinkageKind linkage = getCIRLinkageVarDefinition(varDecl);
3995 if (linkage == cir::GlobalLinkageKind::ExternalLinkage) {
3996 const VarDecl *initVD;
3997 if (varDecl->isStaticDataMember() && varDecl->getAnyInitializer(initVD) &&
3999 // Temporaries defined inside a class get linkonce_odr linkage because the
4000 // calss can be defined in multiple translation units.
4001 errorNYI(mte->getSourceRange(), "static data member initialization");
4002 } else {
4003 // There is no need for this temporary to have external linkage if the
4004 // VarDecl has external linkage.
4005 linkage = cir::GlobalLinkageKind::InternalLinkage;
4006 }
4007 }
4008 cir::GlobalOp gv = createGlobalOp(loc, name, type, isConstant);
4009 gv.setInitialValueAttr(initialValue);
4010 gv.setLinkage(linkage);
4011 gv.setVisibility(getMLIRVisibilityFromCIRLinkage(linkage));
4012
4013 if (emitter)
4014 emitter->finalize(gv);
4015 // Don't assign dllimport or dllexport to local linkage globals
4016 if (!gv.hasLocalLinkage()) {
4019 }
4020
4021 gv.setAlignment(align.getAsAlign().value());
4022 if (supportsCOMDAT() && gv.isWeakForLinker())
4023 gv.setComdat(true);
4024 if (varDecl->getTLSKind())
4025 setTLSMode(gv, *varDecl, /*isExtendingDecl=*/true);
4026 mlir::Operation *cv = gv;
4027
4029
4030 // Update the map with the new temporary. If we created a placeholder above,
4031 // erase it as well, the name will have been the same, so our symbol
4032 // references would have been correct. We still do a 'replaceAllUsesWith' in
4033 // case some sort of expression formed a reference to the placeholder
4034 // temporary.
4035 mlir::Operation *&entry = materializedGlobalTemporaryMap[mte];
4036 if (entry) {
4037 entry->replaceAllUsesWith(cv);
4038 eraseGlobalSymbol(entry);
4039 entry->erase();
4040 }
4041 entry = cv;
4042
4043 return cv;
4044}
4045
4047 const UnnamedGlobalConstantDecl *gcd) {
4048 unsigned numEntries = unnamedGlobalConstantDeclMap.size();
4049 cir::GlobalOp *globalOpEntry = &unnamedGlobalConstantDeclMap[gcd];
4050
4051 if (*globalOpEntry)
4052 return *globalOpEntry;
4053
4054 ConstantEmitter emitter(*this);
4055
4056 const APValue &value = gcd->getValue();
4057 assert(!value.isAbsent());
4059 "emitForInitializer should take gcd->getType().getAddressSpace()");
4060 mlir::Attribute init = emitter.emitForInitializer(value, gcd->getType());
4061 auto typedInit = dyn_cast<mlir::TypedAttr>(init);
4062
4063 if (!typedInit)
4064 errorNYI(gcd->getSourceRange(),
4065 "getAddrOfUnnamedGlobalConstantDecl: non-typed initializer");
4066
4068
4069 // Classic codegen always creates these with .constant, then counts on the
4070 // auto-addition of '.#'. CIR global doesn't have this, so we'll just auto-add
4071 // one if this isn't the first. We could probably choose a better name than
4072 // .constant to be unique for this type of decl, but this is consistent with
4073 // classic codegen.
4074 std::string name = numEntries == 0
4075 ? ".constant"
4076 : (Twine(".constant.") + Twine(numEntries)).str();
4077 auto globalOp = createGlobalOp(builder.getUnknownLoc(), name,
4078 typedInit.getType(), /*is_constant=*/true);
4079 globalOp.setLinkage(cir::GlobalLinkageKind::PrivateLinkage);
4080
4081 CharUnits alignment = getASTContext().getTypeAlignInChars(gcd->getType());
4082 globalOp.setAlignment(alignment.getAsAlign().value());
4083 CIRGenModule::setInitializer(globalOp, init);
4084
4085 emitter.finalize(globalOp);
4086 *globalOpEntry = globalOp;
4087 return globalOp;
4088}
4089
4090cir::GlobalOp
4092 StringRef name = getMangledName(tpo);
4093 CharUnits alignment = getNaturalTypeAlignment(tpo->getType());
4094
4095 if (auto globalOp =
4096 mlir::dyn_cast_or_null<cir::GlobalOp>(getGlobalValue(name)))
4097 return globalOp;
4098
4099 ConstantEmitter emitter(*this);
4101 "emitForInitializer should take tpo->getType().getAddressSpace()");
4102 mlir::Attribute init =
4103 emitter.emitForInitializer(tpo->getValue(), tpo->getType());
4104
4105 if (!init) {
4106 errorUnsupported(tpo, "template parameter object");
4107 return {};
4108 }
4109
4110 mlir::TypedAttr typedInit = cast<mlir::TypedAttr>(init);
4111
4112 cir::GlobalLinkageKind linkage =
4114 ? cir::GlobalLinkageKind::LinkOnceODRLinkage
4115 : cir::GlobalLinkageKind::InternalLinkage;
4116
4118 auto globalOp = createGlobalOp(builder.getUnknownLoc(), name,
4119 typedInit.getType(), /*is_constant=*/true);
4120 globalOp.setLinkage(linkage);
4121 globalOp.setAlignment(alignment.getAsAlign().value());
4122 globalOp.setComdat(supportsCOMDAT() &&
4123 linkage == cir::GlobalLinkageKind::LinkOnceODRLinkage);
4124
4125 CIRGenModule::setInitializer(globalOp, init);
4126 emitter.finalize(globalOp);
4127
4128 insertGlobalSymbol(globalOp);
4129
4130 return globalOp;
4131}
4132
4133//===----------------------------------------------------------------------===//
4134// Annotations
4135//===----------------------------------------------------------------------===//
4136
4137mlir::ArrayAttr
4138CIRGenModule::getOrCreateAnnotationArgs(const AnnotateAttr *attr) {
4139 ArrayRef<Expr *> exprs = {attr->args_begin(), attr->args_size()};
4140 // Return a null attr for no-args annotations so OptionalParameter omits
4141 // the args portion entirely from the printed IR.
4142 if (exprs.empty())
4143 return {};
4144
4145 llvm::FoldingSetNodeID id;
4146 for (Expr *e : exprs)
4147 id.Add(cast<clang::ConstantExpr>(e)->getAPValueResult());
4148
4149 mlir::ArrayAttr &lookup = annotationArgs[id.ComputeHash()];
4150 if (lookup)
4151 return lookup;
4152
4154 args.reserve(exprs.size());
4155 for (Expr *e : exprs) {
4156 if (auto *strE = dyn_cast<clang::StringLiteral>(e->IgnoreParenCasts())) {
4157 args.push_back(builder.getStringAttr(strE->getString()));
4158 } else if (auto *intE =
4159 dyn_cast<clang::IntegerLiteral>(e->IgnoreParenCasts())) {
4160 auto intTy = builder.getIntegerType(intE->getValue().getBitWidth());
4161 args.push_back(builder.getIntegerAttr(intTy, intE->getValue()));
4162 } else {
4163 errorNYI(e->getExprLoc(), "annotation argument expression");
4164 }
4165 }
4166
4167 return lookup = builder.getArrayAttr(args);
4168}
4169
4170cir::AnnotationAttr CIRGenModule::emitAnnotateAttr(const AnnotateAttr *aa) {
4171 mlir::StringAttr annoGV = builder.getStringAttr(aa->getAnnotation());
4172 mlir::ArrayAttr args = getOrCreateAnnotationArgs(aa);
4173 return cir::AnnotationAttr::get(&getMLIRContext(), annoGV, args);
4174}
4175
4177 mlir::Operation *gv) {
4178 assert(d->hasAttr<AnnotateAttr>() && "no annotate attribute");
4179 assert((isa<cir::GlobalOp>(gv) || isa<cir::FuncOp>(gv)) &&
4180 "annotation only on globals");
4182 for (const auto *i : d->specific_attrs<AnnotateAttr>())
4183 annotations.push_back(emitAnnotateAttr(i));
4184 if (auto global = dyn_cast<cir::GlobalOp>(gv))
4185 global.setAnnotationsAttr(builder.getArrayAttr(annotations));
4186 else if (auto func = dyn_cast<cir::FuncOp>(gv))
4187 func.setAnnotationsAttr(builder.getArrayAttr(annotations));
4188}
4189
4190void CIRGenModule::emitGlobalAnnotations() {
4191 for (const auto &[mangledName, vd] : deferredAnnotations) {
4192 mlir::Operation *gv = getGlobalValue(mangledName);
4193 if (gv)
4194 addGlobalAnnotations(vd, gv);
4195 }
4196 deferredAnnotations.clear();
4197}
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:888
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:927
TargetCXXABI::Kind getCXXABIKind() const
Return the C++ ABI kind that should be used.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
mlir::Attribute getConstRecordOrZeroAttr(mlir::ArrayAttr arrayAttr, bool packed=false, bool padded=false, mlir::Type type={})
uint64_t computeOffsetFromGlobalViewIndices(const cir::CIRDataLayout &layout, mlir::Type ty, llvm::ArrayRef< int64_t > indices)
void computeGlobalViewIndicesFromFlatOffset(int64_t offset, mlir::Type ty, cir::CIRDataLayout layout, llvm::SmallVectorImpl< int64_t > &indices)
cir::ConstArrayAttr getConstArray(mlir::Attribute attrs, cir::ArrayType arrayTy) const
virtual void handleGlobalReplace(cir::GlobalOp oldGV, cir::GlobalOp newGV)
virtual mlir::Operation * getKernelHandle(cir::FuncOp fn, GlobalDecl gd)=0
virtual void finalizeModule()
Perform module finalization: on device side, mark ODR-used device variables as compiler-used.
virtual void internalizeDeviceSideVar(const VarDecl *d, cir::GlobalLinkageKind &linkage)=0
Adjust linkage of shadow variables in host compilation.
virtual void handleVarRegistration(const VarDecl *vd, cir::GlobalOp var)=0
Check whether a variable is a device variable and register it if true.
Implements C++ ABI-specific code generation functions.
virtual mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc, QualType ty)=0
virtual void emitCXXConstructors(const clang::CXXConstructorDecl *d)=0
Emit constructor variants required by this ABI.
virtual void emitCXXDestructors(const clang::CXXDestructorDecl *d)=0
Emit dtor variants required by this ABI.
clang::MangleContext & getMangleContext()
Gets the mangle context.
virtual cir::GlobalLinkageKind getCXXDestructorLinkage(GVALinkage linkage, const CXXDestructorDecl *dtor, CXXDtorType dt) const
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.
bool hasNonVirtualBaseCIRField(const CXXRecordDecl *rd) const
unsigned getCIRFieldNo(const clang::FieldDecl *fd) const
Return cir::RecordType element number that corresponds to the field FD.
bool isZeroInitializable() const
Check whether this struct can be C++ zero-initialized with a zeroinitializer.
unsigned getNonVirtualBaseCIRFieldNo(const CXXRecordDecl *rd) const
const CIRGenFunctionInfo & arrangeGlobalDeclaration(GlobalDecl gd)
const CIRGenFunctionInfo & arrangeCXXMethodDeclaration(const clang::CXXMethodDecl *md)
C++ methods have some special rules and also have implicit parameters.
const CIRGenFunctionInfo & arrangeCXXStructorDeclaration(clang::GlobalDecl gd)
cir::FuncType getFunctionType(const CIRGenFunctionInfo &info)
Get the CIR function type for.
const CIRGenRecordLayout & getCIRGenRecordLayout(const clang::RecordDecl *rd)
Return record layout info for the given record decl.
mlir::Type convertTypeForMem(clang::QualType, bool forBitField=false)
Convert type T into an mlir::Type.
void emitThunks(GlobalDecl gd)
Emit the associated thunks for the given global decl.
mlir::Attribute emitForInitializer(const APValue &value, QualType destType)
virtual clang::LangAS getGlobalVarAddressSpace(CIRGenModule &cgm, const clang::VarDecl *d) const
Get target favored AST address space of a global variable for languages other than OpenCL and CUDA.
virtual mlir::ptr::MemorySpaceAttrInterface getCIRAllocaAddressSpace() const
Get the address space for alloca.
Definition TargetInfo.h:64
virtual void setTargetAttributes(const clang::Decl *decl, mlir::Operation *global, CIRGenModule &module) const
Provides a convenient hook to handle extra target-specific attributes for the given global.
Definition TargetInfo.h:122
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:3096
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:3091
bool isDefaultConstructor() const
Whether this constructor is a default constructor (C++ [class.ctor]p5), which can be used to default-...
Definition DeclCXX.cpp:3082
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:2784
bool isCopyAssignmentOperator() const
Determine whether this is a copy-assignment operator, regardless of whether it was declared implicitl...
Definition DeclCXX.cpp:2763
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:2403
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:876
bool isInExportDeclContext() const
Whether this declaration was exported in a lexical context.
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
Definition DeclBase.cpp:273
static DeclContext * castToDeclContext(const Decl *)
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
Definition DeclBase.h:567
SourceLocation getLocation() const
Definition DeclBase.h:447
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
Definition DeclBase.h:935
bool hasAttr() const
Definition DeclBase.h:585
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition DeclBase.h:435
Represents a ValueDecl that came out of a declarator.
Definition Decl.h:780
A little helper class used to produce diagnostics.
Concrete class used by the front-end to report problems and issues.
Definition Diagnostic.h:234
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
Definition Diagnostic.h:915
ExplicitCastExpr - An explicit cast written in the source code.
Definition Expr.h:3934
This represents one expression.
Definition Expr.h:112
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
QualType getType() const
Definition Expr.h:144
Represents a member of a struct/union/class.
Definition Decl.h:3204
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
Definition Decl.h:3289
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Definition Decl.h:3440
Cached information about one file (either on disk or in the virtual file system).
Definition FileEntry.h:273
StringRef tryGetRealPathName() const
Definition FileEntry.h:298
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Represents a function declaration or definition.
Definition Decl.h:2029
static FunctionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin=false, bool isInlineSpecified=false, bool hasWrittenPrototype=true, ConstexprSpecKind ConstexprKind=ConstexprSpecKind::Unspecified, const AssociatedConstraint &TrailingRequiresClause={})
Definition Decl.h:2225
bool hasPrototype() const
Whether this function has a prototype, either because one was explicitly written or because it was "i...
Definition Decl.h:2479
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
FunctionDecl * getDefinition()
Get the definition for this declaration.
Definition Decl.h:2318
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
Definition Decl.cpp:3177
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:1819
void setScopeInfo(unsigned scopeDepth, unsigned parameterIndex)
Definition Decl.h:1852
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
Definition Decl.cpp: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:3761
bool isUnion() const
Definition Decl.h:3972
bool isMicrosoft() const
Is this ABI an MSVC-compatible ABI?
TargetOptions & getTargetOpts() const
Retrieve the target options.
Definition TargetInfo.h:330
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
SourceLocation getExprLoc() const
Definition Expr.h:2374
Expr * getSubExpr() const
Definition Expr.h:2291
An artificial decl, representing a global anonymous constant value which is uniquified by value withi...
Definition DeclCXX.h:4481
const APValue & getValue() const
Definition DeclCXX.h:4507
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:712
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:932
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
Definition Decl.h:1593
TLSKind getTLSKind() const
Definition Decl.cpp: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:1391
bool hasExternalStorage() const
Returns true if a variable has extern or private_extern storage.
Definition Decl.h:1238
@ TLS_None
Not a TLS variable.
Definition Decl.h:952
@ DeclarationOnly
This declaration is only a declaration.
Definition Decl.h:1318
@ Definition
This declaration is definitely a definition.
Definition Decl.h:1324
DefinitionKind hasDefinition(ASTContext &) const
Check whether this variable is defined in this translation unit.
Definition Decl.cpp: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:1381
bool isMatchingAddressSpace(mlir::ptr::MemorySpaceAttrInterface cirAS, clang::LangAS as)
mlir::ptr::MemorySpaceAttrInterface toCIRAddressSpaceAttr(mlir::MLIRContext &ctx, clang::LangAS langAS)
Convert an AST LangAS to the appropriate CIR address space attribute interface.
static bool isWeakForLinker(GlobalLinkageKind linkage)
Whether the definition of this global may be replaced at link time.
@ AttributedType
The l-value was considered opaque, so the alignment was determined from a type, but that type was an ...
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
std::unique_ptr< TargetCIRGenInfo > createAMDGPUTargetCIRGenInfo(CIRGenTypes &cgt)
std::unique_ptr< TargetCIRGenInfo > createNVPTXTargetCIRGenInfo(CIRGenTypes &cgt)
Definition NVPTX.cpp:85
CIRGenCXXABI * CreateCIRGenItaniumCXXABI(CIRGenModule &cgm)
Creates and Itanium-family ABI.
std::unique_ptr< TargetCIRGenInfo > createX8664TargetCIRGenInfo(CIRGenTypes &cgt)
std::unique_ptr< TargetCIRGenInfo > createSPIRVTargetCIRGenInfo(CIRGenTypes &cgt)
Definition SPIRV.cpp:56
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 noUniqueAddressLayout()
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