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