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