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