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