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