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