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