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