clang 24.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/OpenMPUtils.h"
20#include "mlir/IR/SymbolTable.h"
22#include "clang/AST/ASTLambda.h"
23#include "clang/AST/Attrs.inc"
24#include "clang/AST/DeclBase.h"
37#include "llvm/ADT/STLExtras.h"
38#include "llvm/ADT/StringExtras.h"
39#include "llvm/ADT/StringRef.h"
40#include "llvm/ADT/StringSwitch.h"
41#include "llvm/Support/raw_ostream.h"
42
43#include "CIRGenFunctionInfo.h"
44#include "TargetInfo.h"
45#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
46#include "mlir/IR/Attributes.h"
47#include "mlir/IR/BuiltinOps.h"
48#include "mlir/IR/Location.h"
49#include "mlir/IR/MLIRContext.h"
50#include "mlir/IR/Operation.h"
51#include "mlir/IR/Verifier.h"
52
53#include <algorithm>
54
55using namespace clang;
56using namespace clang::CIRGen;
57
59 switch (cgm.getASTContext().getCXXABIKind()) {
60 case TargetCXXABI::GenericItanium:
61 case TargetCXXABI::GenericAArch64:
62 case TargetCXXABI::AppleARM64:
63 case TargetCXXABI::GenericARM:
64 return CreateCIRGenItaniumCXXABI(cgm);
65
66 case TargetCXXABI::Fuchsia:
67 case TargetCXXABI::iOS:
68 case TargetCXXABI::WatchOS:
69 case TargetCXXABI::GenericMIPS:
70 case TargetCXXABI::WebAssembly:
71 case TargetCXXABI::XL:
72 case TargetCXXABI::Microsoft:
73 cgm.errorNYI("createCXXABI: C++ ABI kind");
74 return nullptr;
75 }
76
77 llvm_unreachable("invalid C++ ABI kind");
78}
79
80CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,
81 clang::ASTContext &astContext,
82 const clang::CodeGenOptions &cgo,
83 DiagnosticsEngine &diags)
84 : builder(mlirContext, *this), astContext(astContext),
85 langOpts(astContext.getLangOpts()), codeGenOpts(cgo),
86 theModule{mlir::ModuleOp::create(mlir::UnknownLoc::get(&mlirContext))},
87 diags(diags), target(astContext.getTargetInfo()),
88 abi(createCXXABI(*this)), genTypes(*this), vtables(*this) {
89
90 // Initialize cached types
91 voidTy = cir::VoidType::get(&getMLIRContext());
92 voidPtrTy = cir::PointerType::get(voidTy);
93 sInt8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/true);
94 sInt16Ty = cir::IntType::get(&getMLIRContext(), 16, /*isSigned=*/true);
95 sInt32Ty = cir::IntType::get(&getMLIRContext(), 32, /*isSigned=*/true);
96 sInt64Ty = cir::IntType::get(&getMLIRContext(), 64, /*isSigned=*/true);
97 sInt128Ty = cir::IntType::get(&getMLIRContext(), 128, /*isSigned=*/true);
98 uInt8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/false);
99 uInt8PtrTy = cir::PointerType::get(uInt8Ty);
101 uInt16Ty = cir::IntType::get(&getMLIRContext(), 16, /*isSigned=*/false);
102 uInt32Ty = cir::IntType::get(&getMLIRContext(), 32, /*isSigned=*/false);
103 uInt64Ty = cir::IntType::get(&getMLIRContext(), 64, /*isSigned=*/false);
104 uInt128Ty = cir::IntType::get(&getMLIRContext(), 128, /*isSigned=*/false);
105 fP16Ty = cir::FP16Type::get(&getMLIRContext());
106 bFloat16Ty = cir::BF16Type::get(&getMLIRContext());
107 floatTy = cir::SingleType::get(&getMLIRContext());
108 doubleTy = cir::DoubleType::get(&getMLIRContext());
109 fP80Ty = cir::FP80Type::get(&getMLIRContext());
110 fP128Ty = cir::FP128Type::get(&getMLIRContext());
111
112 allocaInt8PtrTy = cir::PointerType::get(uInt8Ty, cirAllocaAddressSpace);
113
115 astContext
116 .toCharUnitsFromBits(
117 astContext.getTargetInfo().getPointerAlign(LangAS::Default))
118 .getQuantity();
119
120 const unsigned charSize = astContext.getTargetInfo().getCharWidth();
121 uCharTy = cir::IntType::get(&getMLIRContext(), charSize, /*isSigned=*/false);
122
123 // TODO(CIR): Should be updated once TypeSizeInfoAttr is upstreamed
124 const unsigned sizeTypeSize =
125 astContext.getTypeSize(astContext.getSignedSizeType());
126 SizeSizeInBytes = astContext.toCharUnitsFromBits(sizeTypeSize).getQuantity();
127 // In CIRGenTypeCache, UIntPtrTy and SizeType are fields of the same union
128 uIntPtrTy =
129 cir::IntType::get(&getMLIRContext(), sizeTypeSize, /*isSigned=*/false);
130 ptrDiffTy =
131 cir::IntType::get(&getMLIRContext(), sizeTypeSize, /*isSigned=*/true);
132
133 std::optional<cir::SourceLanguage> sourceLanguage = getCIRSourceLanguage();
134 if (sourceLanguage)
135 theModule->setAttr(
136 cir::CIRDialect::getSourceLanguageAttrName(),
137 cir::SourceLanguageAttr::get(&mlirContext, *sourceLanguage));
138 theModule->setAttr(cir::CIRDialect::getTripleAttrName(),
139 builder.getStringAttr(getTriple().str()));
140
141 if (cgo.OptimizationLevel > 0 || cgo.OptimizeSize > 0)
142 theModule->setAttr(cir::CIRDialect::getOptInfoAttrName(),
143 cir::OptInfoAttr::get(&mlirContext,
144 cgo.OptimizationLevel,
145 cgo.OptimizeSize));
146
147 if (langOpts.OpenMP) {
148 mlir::omp::OffloadModuleOpts ompOpts(
149 langOpts.OpenMPTargetDebug, langOpts.OpenMPTeamSubscription,
150 langOpts.OpenMPThreadSubscription, langOpts.OpenMPNoThreadState,
151 langOpts.OpenMPNoNestedParallelism, langOpts.OpenMPIsTargetDevice,
152 getTriple().isGPU(), langOpts.OpenMPForceUSM, langOpts.OpenMP,
153 langOpts.OMPHostIRFile, langOpts.OMPTargetTriples, langOpts.NoGPULib);
154 mlir::omp::setOffloadModuleInterfaceAttributes(theModule, ompOpts);
155 mlir::omp::setOpenMPVersionAttribute(theModule, langOpts.OpenMP);
156 }
157
158 if (langOpts.CUDA)
159 createCUDARuntime();
160 if (langOpts.OpenMP)
161 createOpenMPRuntime();
162
163 // Set the module name to be the name of the main file. TranslationUnitDecl
164 // often contains invalid source locations and isn't a reliable source for the
165 // module location.
166 FileID mainFileId = astContext.getSourceManager().getMainFileID();
167 const FileEntry &mainFile =
168 *astContext.getSourceManager().getFileEntryForID(mainFileId);
169 StringRef path = mainFile.tryGetRealPathName();
170 if (!path.empty()) {
171 theModule.setSymName(path);
172 theModule->setLoc(mlir::FileLineColLoc::get(&mlirContext, path,
173 /*line=*/0,
174 /*column=*/0));
175 }
176
177 // Set CUDA GPU binary handle.
178 if (langOpts.CUDA) {
179 llvm::StringRef cudaBinaryName = codeGenOpts.CudaGpuBinaryFileName;
180 if (!cudaBinaryName.empty()) {
181 theModule->setAttr(cir::CIRDialect::getCUDABinaryHandleAttrName(),
182 cir::CUDABinaryHandleAttr::get(
183 &mlirContext, mlir::StringAttr::get(
184 &mlirContext, cudaBinaryName)));
185 }
186 }
187}
188
190
191void CIRGenModule::createCUDARuntime() {
192 cudaRuntime.reset(createNVCUDARuntime(*this));
193}
194
195void CIRGenModule::createOpenMPRuntime() {
196 openMPRuntime = std::make_unique<CIRGenOpenMPRuntime>(*this);
197}
198
199/// FIXME: this could likely be a common helper and not necessarily related
200/// with codegen.
201/// Return the best known alignment for an unknown pointer to a
202/// particular class.
204 if (!rd->hasDefinition())
205 return CharUnits::One(); // Hopefully won't be used anywhere.
206
207 auto &layout = astContext.getASTRecordLayout(rd);
208
209 // If the class is final, then we know that the pointer points to an
210 // object of that type and can use the full alignment.
211 if (rd->isEffectivelyFinal())
212 return layout.getAlignment();
213
214 // Otherwise, we have to assume it could be a subclass.
215 return layout.getNonVirtualAlignment();
216}
217
219 LValueBaseInfo *baseInfo,
220 bool forPointeeType) {
222
223 // FIXME: This duplicates logic in ASTContext::getTypeAlignIfKnown, but
224 // that doesn't return the information we need to compute baseInfo.
225
226 // Honor alignment typedef attributes even on incomplete types.
227 // We also honor them straight for C++ class types, even as pointees;
228 // there's an expressivity gap here.
229 if (const auto *tt = t->getAs<TypedefType>()) {
230 if (unsigned align = tt->getDecl()->getMaxAlignment()) {
231 if (baseInfo)
233 return astContext.toCharUnitsFromBits(align);
234 }
235 }
236
237 bool alignForArray = t->isArrayType();
238
239 // Analyze the base element type, so we don't get confused by incomplete
240 // array types.
241 t = astContext.getBaseElementType(t);
242
243 if (t->isIncompleteType()) {
244 // We could try to replicate the logic from
245 // ASTContext::getTypeAlignIfKnown, but nothing uses the alignment if the
246 // type is incomplete, so it's impossible to test. We could try to reuse
247 // getTypeAlignIfKnown, but that doesn't return the information we need
248 // to set baseInfo. So just ignore the possibility that the alignment is
249 // greater than one.
250 if (baseInfo)
252 return CharUnits::One();
253 }
254
255 if (baseInfo)
257
258 CharUnits alignment;
259 const CXXRecordDecl *rd = nullptr;
260 if (t.getQualifiers().hasUnaligned()) {
261 alignment = CharUnits::One();
262 } else if (forPointeeType && !alignForArray &&
263 (rd = t->getAsCXXRecordDecl())) {
264 alignment = getClassPointerAlignment(rd);
265 } else {
266 alignment = astContext.getTypeAlignInChars(t);
267 }
268
269 // Cap to the global maximum type alignment unless the alignment
270 // was somehow explicit on the type.
271 if (unsigned maxAlign = astContext.getLangOpts().MaxTypeAlign) {
272 if (alignment.getQuantity() > maxAlign &&
273 !astContext.isAlignmentRequired(t))
274 alignment = CharUnits::fromQuantity(maxAlign);
275 }
276 return alignment;
277}
278
281 LValueBaseInfo *baseInfo) {
282 return getNaturalTypeAlignment(t->getPointeeType(), baseInfo,
283 /*forPointeeType=*/true);
284}
285
287 if (theTargetCIRGenInfo)
288 return *theTargetCIRGenInfo;
289
290 const llvm::Triple &triple = getTarget().getTriple();
291 switch (triple.getArch()) {
292 default:
294
295 // Currently we just fall through to x86_64.
296 [[fallthrough]];
297
298 case llvm::Triple::x86_64: {
299 switch (triple.getOS()) {
300 default:
302
303 // Currently we just fall through to x86_64.
304 [[fallthrough]];
305
306 case llvm::Triple::Linux:
307 theTargetCIRGenInfo = createX8664TargetCIRGenInfo(genTypes);
308 return *theTargetCIRGenInfo;
309 }
310 }
311 case llvm::Triple::nvptx:
312 case llvm::Triple::nvptx64:
313 theTargetCIRGenInfo = createNVPTXTargetCIRGenInfo(genTypes);
314 return *theTargetCIRGenInfo;
315 case llvm::Triple::amdgpu: {
316 theTargetCIRGenInfo = createAMDGPUTargetCIRGenInfo(genTypes);
317 return *theTargetCIRGenInfo;
318 }
319 case llvm::Triple::spirv:
320 case llvm::Triple::spirv32:
321 case llvm::Triple::spirv64:
322 theTargetCIRGenInfo = createSPIRVTargetCIRGenInfo(genTypes);
323 return *theTargetCIRGenInfo;
324 }
325}
326
328 assert(cLoc.isValid() && "expected valid source location");
329 const SourceManager &sm = astContext.getSourceManager();
330 PresumedLoc pLoc = sm.getPresumedLoc(cLoc);
331 StringRef filename = pLoc.getFilename();
332 return mlir::FileLineColLoc::get(builder.getStringAttr(filename),
333 pLoc.getLine(), pLoc.getColumn());
334}
335
336mlir::Location CIRGenModule::getLoc(SourceRange cRange) {
337 assert(cRange.isValid() && "expected a valid source range");
338 mlir::Location begin = getLoc(cRange.getBegin());
339 mlir::Location end = getLoc(cRange.getEnd());
340 mlir::Attribute metadata;
341 return mlir::FusedLoc::get({begin, end}, metadata, builder.getContext());
342}
343
344mlir::Operation *
346 const Decl *d = gd.getDecl();
347
349 return getAddrOfCXXStructor(gd, /*FnInfo=*/nullptr, /*FnType=*/nullptr,
350 /*DontDefer=*/false, isForDefinition);
351
352 if (isa<CXXMethodDecl>(d)) {
353 const CIRGenFunctionInfo &fi =
355 cir::FuncType ty = getTypes().getFunctionType(fi);
356 return getAddrOfFunction(gd, ty, /*ForVTable=*/false, /*DontDefer=*/false,
357 isForDefinition);
358 }
359
360 if (isa<FunctionDecl>(d)) {
362 cir::FuncType ty = getTypes().getFunctionType(fi);
363 return getAddrOfFunction(gd, ty, /*ForVTable=*/false, /*DontDefer=*/false,
364 isForDefinition);
365 }
366
367 return getAddrOfGlobalVar(cast<VarDecl>(d), /*ty=*/nullptr, isForDefinition)
368 .getDefiningOp();
369}
370
372 // We call getAddrOfGlobal with isForDefinition set to ForDefinition in
373 // order to get a Value with exactly the type we need, not something that
374 // might have been created for another decl with the same mangled name but
375 // different type.
376 mlir::Operation *op = getAddrOfGlobal(d, ForDefinition);
377
378 // In case of different address spaces, we may still get a cast, even with
379 // IsForDefinition equal to ForDefinition. Query mangled names table to get
380 // GlobalValue.
381 if (!op)
383
384 assert(op && "expected a valid global op");
385
386 // Check to see if we've already emitted this. This is necessary for a
387 // couple of reasons: first, decls can end up in deferred-decls queue
388 // multiple times, and second, decls can end up with definitions in unusual
389 // ways (e.g. by an extern inline function acquiring a strong function
390 // redefinition). Just ignore those cases.
391 // TODO: Not sure what to map this to for MLIR
392 mlir::Operation *globalValueOp = op;
393 if (auto gv = dyn_cast<cir::GetGlobalOp>(op)) {
394 globalValueOp = getGlobalValue(gv.getName());
395 assert(globalValueOp && "expected a valid global op");
396 }
397
398 if (auto cirGlobalValue =
399 dyn_cast<cir::CIRGlobalValueInterface>(globalValueOp))
400 if (!cirGlobalValue.isDeclaration())
401 return;
402
403 // If this is OpenMP, check if it is legal to emit this global normally.
405
406 // Otherwise, emit the definition and move on to the next one.
408}
409
411 // Emit code for any potentially referenced deferred decls. Since a previously
412 // unused static decl may become used during the generation of code for a
413 // static function, iterate until no changes are made.
414
416
418 // Emitting a vtable doesn't directly cause more vtables to
419 // become deferred, although it can cause functions to be
420 // emitted that then need those vtables.
421 assert(deferredVTables.empty());
422
424
425 // Stop if we're out of both deferred vtables and deferred declarations.
426 if (deferredDeclsToEmit.empty())
427 return;
428
429 // Grab the list of decls to emit. If emitGlobalDefinition schedules more
430 // work, it will not interfere with this.
431 std::vector<GlobalDecl> curDeclsToEmit;
432 curDeclsToEmit.swap(deferredDeclsToEmit);
433
434 for (const GlobalDecl &d : curDeclsToEmit) {
436
437 // If we found out that we need to emit more decls, do that recursively.
438 // This has the advantage that the decls are emitted in a DFS and related
439 // ones are close together, which is convenient for testing.
440 if (!deferredVTables.empty() || !deferredDeclsToEmit.empty()) {
441 emitDeferred();
442 assert(deferredVTables.empty() && deferredDeclsToEmit.empty());
443 }
444 }
445}
446
447template <typename AttrT> static bool hasImplicitAttr(const ValueDecl *decl) {
448 if (!decl)
449 return false;
450 if (auto *attr = decl->getAttr<AttrT>())
451 return attr->isImplicit();
452 return decl->isImplicit();
453}
454
455// TODO(cir): This should be shared with OG Codegen.
457 assert(langOpts.CUDA && "Should not be called by non-CUDA languages");
458 // We need to emit host-side 'shadows' for all global
459 // device-side variables because the CUDA runtime needs their
460 // size and host-side address in order to provide access to
461 // their device-side incarnations.
462 return !langOpts.CUDAIsDevice || global->hasAttr<CUDADeviceAttr>() ||
463 global->hasAttr<CUDAConstantAttr>() ||
464 global->hasAttr<CUDASharedAttr>() ||
467}
468
470 const Decl *d) {
471 // ptxas does not allow '.' in symbol names. On the other hand, HIP prefers
472 // postfix beginning with '.' since the symbol name can be demangled.
473 if (langOpts.HIP)
474 os << (isa<VarDecl>(d) ? ".static." : ".intern.");
475 else
476 os << (isa<VarDecl>(d) ? "__static__" : "__intern__");
477
478 // If the CUID is not specified we try to generate a unique postfix.
479 if (getLangOpts().CUID.empty()) {
480 // TODO: Once we add 'PreprocessorOpts' into CIRGenModule this part can be
481 // brought in from OG.
483 "printPostfixForExternalizedDecl: CUID is not specified");
484 } else {
485 os << getASTContext().getCUIDHash();
486 }
487}
488
490 if (const auto *cd = dyn_cast<clang::OpenACCConstructDecl>(gd.getDecl())) {
492 return;
493 }
494
495 const auto *global = cast<ValueDecl>(gd.getDecl());
496
497 // Weak references don't produce any output by themselves.
498 if (global->hasAttr<WeakRefAttr>())
499 return;
500
501 // If this is an alias definition (which otherwise looks like a declaration)
502 // emit it now.
503 if (global->hasAttr<AliasAttr>()) {
504 // Classic codegen calls shouldSkipAliasEmission here to skip alias
505 // emission for OpenMP target device and CUDA configurations.
508 return;
509 }
510
511 // If this is CUDA, be selective about which declarations we emit.
512 // Non-constexpr non-lambda implicit host device functions are not emitted
513 // unless they are used on device side.
514 if (langOpts.CUDA) {
515 assert((isa<FunctionDecl>(global) || isa<VarDecl>(global)) &&
516 "Expected Variable or Function");
517 if (const auto *varDecl = dyn_cast<VarDecl>(global)) {
519 return;
520 // TODO(cir): This should be shared with OG Codegen.
521 } else if (langOpts.CUDAIsDevice) {
522 const auto *functionDecl = dyn_cast<FunctionDecl>(global);
523 if ((!global->hasAttr<CUDADeviceAttr>() ||
524 (langOpts.OffloadImplicitHostDeviceTemplates &&
527 !functionDecl->isConstexpr() &&
529 !getASTContext().CUDAImplicitHostDeviceFunUsedByDevice.count(
530 functionDecl))) &&
531 !global->hasAttr<CUDAGlobalAttr>() &&
532 !(langOpts.HIPStdPar && isa<FunctionDecl>(global) &&
533 !global->hasAttr<CUDAHostAttr>()))
534 return;
535 // Device-only functions are the only things we skip.
536 } else if (!global->hasAttr<CUDAHostAttr>() &&
537 global->hasAttr<CUDADeviceAttr>())
538 return;
539 }
540
541 if (langOpts.OpenMP) {
542 // If this is OpenMP, check if it is legal to emit this global normally.
543 if (openMPRuntime && openMPRuntime->emitTargetGlobal(gd))
544 return;
545 if (auto *drd = dyn_cast<OMPDeclareReductionDecl>(global)) {
546 if (mustBeEmitted(global))
548 return;
549 }
550 if (auto *dmd = dyn_cast<OMPDeclareMapperDecl>(global)) {
551 if (mustBeEmitted(global))
553 return;
554 }
555 }
556
557 if (const auto *fd = dyn_cast<FunctionDecl>(global)) {
558 // Update deferred annotations with the latest declaration if the function
559 // was already used or defined.
560 if (fd->hasAttr<AnnotateAttr>()) {
561 StringRef mangledName = getMangledName(gd);
562 if (getGlobalValue(mangledName))
563 deferredAnnotations[mangledName] = fd;
564 }
565 if (!fd->doesThisDeclarationHaveABody()) {
566 if (!fd->doesDeclarationForceExternallyVisibleDefinition() &&
567 (!fd->isMultiVersion() || !getTarget().getTriple().isAArch64()))
568 return;
569
571 cir::FuncType ty = getTypes().getFunctionType(fi);
572 getAddrOfFunction(gd, ty, /*ForVTable=*/false, /*DontDefer=*/false);
573 return;
574 }
575 } else {
576 const auto *vd = cast<VarDecl>(global);
577 assert(vd->isFileVarDecl() && "Cannot emit local var decl as global.");
578 if (vd->isThisDeclarationADefinition() != VarDecl::Definition &&
579 !astContext.isMSStaticDataMemberInlineDefinition(vd)) {
581 // If this declaration may have caused an inline variable definition to
582 // change linkage, make sure that it's emitted.
583 if (astContext.getInlineVariableDefinitionKind(vd) ==
586 // Otherwise, we can ignore this declaration. The variable will be emitted
587 // on its first use.
588 return;
589 }
590 }
591
592 // Defer code generation to first use when possible, e.g. if this is an inline
593 // function. If the global must always be emitted, do it eagerly if possible
594 // to benefit from cache locality. Deferring code generation is necessary to
595 // avoid adding initializers to external declarations.
596 if (mustBeEmitted(global) && mayBeEmittedEagerly(global)) {
597 // Emit the definition if it can't be deferred.
599 return;
600 }
601
602 // If we're deferring emission of a C++ variable with an initializer, remember
603 // the order in which it appeared on the file.
605
606 llvm::StringRef mangledName = getMangledName(gd);
607 if (getGlobalValue(mangledName) != nullptr) {
608 // The value has already been used and should therefore be emitted.
610 } else if (mustBeEmitted(global)) {
611 // The value must be emitted, but cannot be emitted eagerly.
612 assert(!mayBeEmittedEagerly(global));
614 } else {
615 // Otherwise, remember that we saw a deferred decl with this name. The first
616 // use of the mangled name will cause it to move into deferredDeclsToEmit.
617 deferredDecls[mangledName] = gd;
618 }
619}
620
622 mlir::Operation *op) {
623 auto const *funcDecl = cast<FunctionDecl>(gd.getDecl());
625 cir::FuncType funcType = getTypes().getFunctionType(fi);
626 cir::FuncOp funcOp = dyn_cast_if_present<cir::FuncOp>(op);
627 if (!funcOp || funcOp.getFunctionType() != funcType) {
628 funcOp = getAddrOfFunction(gd, funcType, /*ForVTable=*/false,
629 /*DontDefer=*/true, ForDefinition);
630 }
631
632 // Already emitted.
633 if (!funcOp.isDeclaration())
634 return;
635
636 setFunctionLinkage(gd, funcOp);
637 setGVProperties(funcOp, funcDecl);
639 maybeSetTrivialComdat(*funcDecl, funcOp);
641
642 CIRGenFunction cgf(*this, builder);
643 curCGF = &cgf;
644 {
645 mlir::OpBuilder::InsertionGuard guard(builder);
646 cgf.generateCode(gd, funcOp, funcType);
647 }
648 curCGF = nullptr;
649
650 setNonAliasAttributes(gd, funcOp);
652
653 auto getPriority = [this](const auto *attr) -> int {
654 Expr *e = attr->getPriority();
655 if (e)
656 return e->EvaluateKnownConstInt(this->getASTContext()).getExtValue();
657 return attr->DefaultPriority;
658 };
659
660 if (const ConstructorAttr *ca = funcDecl->getAttr<ConstructorAttr>())
661 addGlobalCtor(funcOp, getPriority(ca));
662 if (const DestructorAttr *da = funcDecl->getAttr<DestructorAttr>())
663 addGlobalDtor(funcOp, getPriority(da));
664
665 if (funcDecl->getAttr<AnnotateAttr>())
666 deferredAnnotations[getMangledName(gd)] = funcDecl;
667
668 if (getLangOpts().OpenMP && funcDecl->hasAttr<OMPDeclareTargetDeclAttr>())
670}
671
672/// Track functions to be called before main() runs.
673void CIRGenModule::addGlobalCtor(cir::FuncOp ctor,
674 std::optional<int> priority) {
677
678 // Traditional LLVM codegen directly adds the function to the list of global
679 // ctors. In CIR we just add a global_ctor attribute to the function. The
680 // global list is created in LoweringPrepare.
681 //
682 // FIXME(from traditional LLVM): Type coercion of void()* types.
683 ctor.setGlobalCtorPriority(priority);
684}
685
686/// Add a function to the list that will be called when the module is unloaded.
687void CIRGenModule::addGlobalDtor(cir::FuncOp dtor,
688 std::optional<int> priority) {
689 if (codeGenOpts.RegisterGlobalDtorsWithAtExit &&
690 (!getASTContext().getTargetInfo().getTriple().isOSAIX()))
691 errorNYI(dtor.getLoc(), "registerGlobalDtorsWithAtExit");
692
693 // FIXME(from traditional LLVM): Type coercion of void()* types.
694 dtor.setGlobalDtorPriority(priority);
695}
696
699 if (dk == VarDecl::Definition && vd->hasAttr<DLLImportAttr>())
700 return;
701
703 // If we have a definition, this might be a deferred decl. If the
704 // instantiation is explicit, make sure we emit it at the end.
707
709}
710
711mlir::Operation *CIRGenModule::getGlobalValue(StringRef name) {
712 auto it = symbolLookupCache.find(name);
713 return it != symbolLookupCache.end() ? it->second : nullptr;
714}
715
716cir::GlobalOp
717CIRGenModule::createGlobalOp(mlir::Location loc, StringRef name, mlir::Type t,
718 bool isConstant,
719 mlir::ptr::MemorySpaceAttrInterface addrSpace,
720 mlir::Operation *insertPoint) {
721 cir::GlobalOp g;
722 CIRGenBuilderTy &builder = getBuilder();
723
724 {
725 mlir::OpBuilder::InsertionGuard guard(builder);
726
727 // If an insertion point is provided, we're replacing an existing global,
728 // otherwise, create the new global immediately after the last gloabl we
729 // emitted.
730 if (insertPoint) {
731 builder.setInsertionPoint(insertPoint);
732 } else {
733 // Group global operations together at the top of the module.
734 if (lastGlobalOp)
735 builder.setInsertionPointAfter(lastGlobalOp);
736 else
737 builder.setInsertionPointToStart(getModule().getBody());
738 }
739
740 g = cir::GlobalOp::create(builder, loc, name, t, isConstant, addrSpace);
741 if (!insertPoint)
742 lastGlobalOp = g;
743
744 // Default to private until we can judge based on the initializer,
745 // since MLIR doesn't allow public declarations.
746 mlir::SymbolTable::setSymbolVisibility(
747 g, mlir::SymbolTable::Visibility::Private);
748 }
749 symbolLookupCache[g.getSymNameAttr()] = g;
750 return g;
751}
752
753void CIRGenModule::setCommonAttributes(GlobalDecl gd, mlir::Operation *gv) {
754 const Decl *d = gd.getDecl();
755 if (isa_and_nonnull<NamedDecl>(d))
756 setGVProperties(gv, dyn_cast<NamedDecl>(d));
758
759 if (auto gvi = mlir::dyn_cast<cir::CIRGlobalValueInterface>(gv)) {
760 if (d && d->hasAttr<UsedAttr>())
762
763 if (const auto *vd = dyn_cast_if_present<VarDecl>(d);
764 vd && ((codeGenOpts.KeepPersistentStorageVariables &&
765 (vd->getStorageDuration() == SD_Static ||
766 vd->getStorageDuration() == SD_Thread)) ||
767 (codeGenOpts.KeepStaticConsts &&
768 vd->getStorageDuration() == SD_Static &&
769 vd->getType().isConstQualified())))
771 }
772}
773
774/// Get the feature delta from the default feature map for the given target CPU.
775static std::vector<std::string>
776getFeatureDeltaFromDefault(const CIRGenModule &cgm, llvm::StringRef targetCPU,
777 llvm::StringMap<bool> &featureMap) {
778 llvm::StringMap<bool> defaultFeatureMap;
780 defaultFeatureMap, cgm.getASTContext().getDiagnostics(), targetCPU, {});
781
782 std::vector<std::string> delta;
783 for (const auto &[k, v] : featureMap) {
784 auto defaultIt = defaultFeatureMap.find(k);
785 if (defaultIt == defaultFeatureMap.end() || defaultIt->getValue() != v)
786 delta.push_back((v ? "+" : "-") + k.str());
787 }
788
789 return delta;
790}
791
792bool CIRGenModule::getCPUAndFeaturesAttributes(
793 GlobalDecl gd, llvm::StringMap<std::string> &attrs,
794 bool setTargetFeatures) {
795 // Add target-cpu and target-features attributes to functions. If
796 // we have a decl for the function and it has a target attribute then
797 // parse that and add it to the feature set.
798 llvm::StringRef targetCPU = getTarget().getTargetOpts().CPU;
799 llvm::StringRef tuneCPU = getTarget().getTargetOpts().TuneCPU;
800 std::vector<std::string> features;
801 // `fd` may be null when emitting attributes for globals that don't have a
802 // FunctionDecl. The AMDGPU branch below handles
803 // the null case via initFeatureMap.
804 const auto *fd = dyn_cast_or_null<FunctionDecl>(gd.getDecl());
805 fd = fd ? fd->getMostRecentDecl() : fd;
806 const auto *td = fd ? fd->getAttr<TargetAttr>() : nullptr;
807 const auto *tv = fd ? fd->getAttr<TargetVersionAttr>() : nullptr;
808 assert((!td || !tv) && "both target_version and target specified");
809 const auto *sd = fd ? fd->getAttr<CPUSpecificAttr>() : nullptr;
810 const auto *tc = fd ? fd->getAttr<TargetClonesAttr>() : nullptr;
811 bool addedAttr = false;
812 if (td || tv || sd || tc) {
813 llvm::StringMap<bool> featureMap;
814 astContext.getFunctionFeatureMap(featureMap, gd);
815
816 // Now add the target-cpu and target-features to the function.
817 // While we populated the feature map above, we still need to
818 // get and parse the target/target_clones attribute so we can
819 // get the cpu for the function.
820 llvm::StringRef featureStr = td ? td->getFeaturesStr() : llvm::StringRef();
821 if (tc && (getTriple().isOSAIX() || getTriple().isX86()))
822 featureStr = tc->getFeatureStr(gd.getMultiVersionIndex());
823 if (!featureStr.empty()) {
824 clang::ParsedTargetAttr parsedAttr =
825 getTarget().parseTargetAttr(featureStr);
826 if (!parsedAttr.CPU.empty() &&
827 getTarget().isValidCPUName(parsedAttr.CPU)) {
828 targetCPU = parsedAttr.CPU;
829 tuneCPU = ""; // Clear the tune CPU.
830 }
831 if (!parsedAttr.Tune.empty() &&
832 getTarget().isValidCPUName(parsedAttr.Tune))
833 tuneCPU = parsedAttr.Tune;
834 }
835
836 if (sd) {
837 // Apply the given CPU name as the 'tune-cpu' so that the optimizer can
838 // favor this processor.
839 tuneCPU = sd->getCPUName(gd.getMultiVersionIndex())->getName();
840 }
841
842 // For AMDGPU, only emit delta features (features that differ from the
843 // target CPU's defaults). Other targets might want to follow a similar
844 // pattern.
845 if (getTarget().getTriple().isAMDGPU()) {
846 features = getFeatureDeltaFromDefault(*this, targetCPU, featureMap);
847 } else {
848 // Produce the canonical string for this set of features.
849 features.reserve(features.size() + featureMap.size());
850 for (const auto &entry : featureMap)
851 features.push_back((entry.getValue() ? "+" : "-") +
852 entry.getKey().str());
853 }
854 } else {
855 // Just add the existing target cpu and target features to the function.
856 if (setTargetFeatures && getTarget().getTriple().isAMDGPU()) {
857 llvm::StringMap<bool> featureMap;
858 if (fd)
859 astContext.getFunctionFeatureMap(featureMap, gd);
860 else
861 getTarget().initFeatureMap(featureMap, astContext.getDiagnostics(),
862 targetCPU,
863 getTarget().getTargetOpts().Features);
864 features = getFeatureDeltaFromDefault(*this, targetCPU, featureMap);
865 } else {
866 features = getTarget().getTargetOpts().Features;
867 }
868 }
869
870 if (!targetCPU.empty()) {
871 attrs["cir.target-cpu"] = targetCPU.str();
872 addedAttr = true;
873 }
874 if (!tuneCPU.empty()) {
875 attrs["cir.tune-cpu"] = tuneCPU.str();
876 addedAttr = true;
877 }
878 if (!features.empty() && setTargetFeatures) {
879 llvm::erase_if(features, [&](const std::string &f) {
880 assert(!f.empty() && (f[0] == '+' || f[0] == '-') &&
881 "feature string must start with '+' or '-'");
882 return getTarget().isReadOnlyFeature(f.substr(1));
883 });
884 llvm::sort(features);
885 attrs["cir.target-features"] = llvm::join(features, ",");
886 addedAttr = true;
887 }
888 // TODO(cir): add metadata for AArch64 Function Multi Versioning.
890 return addedAttr;
891}
892
893void CIRGenModule::setNonAliasAttributes(GlobalDecl gd, mlir::Operation *op) {
894 setCommonAttributes(gd, op);
895
896 const Decl *d = gd.getDecl();
897 if (d) {
898 if (auto gvi = mlir::dyn_cast<cir::CIRGlobalValueInterface>(op)) {
899 if (const auto *sa = d->getAttr<SectionAttr>())
900 gvi.setSection(builder.getStringAttr(sa->getName()));
901 if (d->hasAttr<RetainAttr>())
902 addUsedGlobal(gvi);
903
904 if (auto func = dyn_cast<cir::FuncOp>(op)) {
905 llvm::StringMap<std::string> attrs;
906 if (getCPUAndFeaturesAttributes(gd, attrs)) {
907 // TODO(cir): Classic codegen removes the existing target-cpu,
908 // target-features, tune-cpu and fmv-features attributes here
909 // before adding the new ones.
910 for (const auto &[key, val] : attrs)
911 func->setAttr(key, builder.getStringAttr(val));
912 }
913 }
914 }
915 }
916
919}
920
921std::optional<cir::SourceLanguage> CIRGenModule::getCIRSourceLanguage() const {
922 using ClangStd = clang::LangStandard;
923 using CIRLang = cir::SourceLanguage;
924 auto opts = getLangOpts();
925
926 if (opts.CPlusPlus)
927 return CIRLang::CXX;
928 if (opts.C99 || opts.C11 || opts.C17 || opts.C23 || opts.C2y ||
929 opts.LangStd == ClangStd::lang_c89 ||
930 opts.LangStd == ClangStd::lang_gnu89)
931 return CIRLang::C;
932
933 // TODO(cir): support remaining source languages.
935 errorNYI("CIR does not yet support the given source language");
936 return std::nullopt;
937}
938
939LangAS CIRGenModule::getGlobalVarAddressSpace(const VarDecl *d) {
940 if (langOpts.OpenCL) {
945 return as;
946 }
947
948 if (langOpts.SYCLIsDevice &&
949 (!d || d->getType().getAddressSpace() == LangAS::Default))
950 errorNYI("SYCL global address space");
951
952 if (langOpts.CUDA && langOpts.CUDAIsDevice) {
953 if (d) {
954 if (d->hasAttr<CUDAConstantAttr>())
956 if (d->hasAttr<CUDASharedAttr>())
957 return LangAS::cuda_shared;
958 if (d->hasAttr<CUDADeviceAttr>())
959 return LangAS::cuda_device;
960 if (d->getType().isConstQualified())
962 }
963 return LangAS::cuda_device;
964 }
965
966 if (langOpts.OpenMP)
967 errorNYI("OpenMP global address space");
968
970}
971
972static void setLinkageForGV(cir::GlobalOp &gv, const NamedDecl *nd) {
973 // Set linkage and visibility in case we never see a definition.
975 // Don't set internal linkage on declarations.
976 // "extern_weak" is overloaded in LLVM; we probably should have
977 // separate linkage types for this.
979 (nd->hasAttr<WeakAttr>() || nd->isWeakImported()))
980 gv.setLinkage(cir::GlobalLinkageKind::ExternalWeakLinkage);
981}
982
983static void setLinkageForFunction(CIRGenModule &cgm, cir::FuncOp &func,
984 const NamedDecl *nd) {
985 // Mirrors CodeGenModule::setLinkageForGV for function declarations.
988 (nd->hasAttr<WeakAttr>() || nd->isWeakImported())) {
989 auto linkage = cir::GlobalLinkageKind::ExternalWeakLinkage;
990 func.setLinkage(linkage);
991 func.setLinkageAttr(
992 cir::GlobalLinkageKindAttr::get(&cgm.getMLIRContext(), linkage));
993 // Declarations must keep 'private' MLIR visibility; only update for defs.
994 if (!func.isDeclaration())
995 mlir::SymbolTable::setSymbolVisibility(
996 func, cgm.getMLIRVisibilityFromCIRLinkage(linkage));
997 }
998}
999
1000static llvm::SmallVector<int64_t> indexesOfArrayAttr(mlir::ArrayAttr indexes) {
1002 for (mlir::Attribute i : indexes) {
1003 auto ind = mlir::cast<mlir::IntegerAttr>(i);
1004 inds.push_back(ind.getValue().getSExtValue());
1005 }
1006 return inds;
1007}
1008
1009static bool isViewOnGlobal(cir::GlobalOp glob, cir::GlobalViewAttr view) {
1010 return view.getSymbol().getValue() == glob.getSymName();
1011}
1012
1013static cir::GlobalViewAttr createNewGlobalView(CIRGenModule &cgm,
1014 cir::GlobalOp newGlob,
1015 cir::GlobalViewAttr attr,
1016 mlir::Type oldTy) {
1017 // If the attribute does not require indexes or it is not a global view on
1018 // the global we're replacing, keep the original attribute.
1019 if (!attr.getIndices() || !isViewOnGlobal(newGlob, attr))
1020 return attr;
1021
1022 llvm::SmallVector<int64_t> oldInds = indexesOfArrayAttr(attr.getIndices());
1024 CIRGenBuilderTy &bld = cgm.getBuilder();
1025 const cir::CIRDataLayout &layout = cgm.getDataLayout();
1026 mlir::Type newTy = newGlob.getSymType();
1027
1028 uint64_t offset =
1029 bld.computeOffsetFromGlobalViewIndices(layout, oldTy, oldInds);
1030 bld.computeGlobalViewIndicesFromFlatOffset(offset, newTy, layout, newInds);
1031 cir::PointerType newPtrTy;
1032
1033 if (isa<cir::RecordType>(oldTy))
1034 newPtrTy = cir::PointerType::get(newTy);
1035 else if (isa<cir::ArrayType>(oldTy))
1036 newPtrTy = cast<cir::PointerType>(attr.getType());
1037
1038 if (newPtrTy)
1039 return bld.getGlobalViewAttr(newPtrTy, newGlob, newInds);
1040
1041 // This may be unreachable in practice, but keep it as errorNYI while CIR
1042 // is still under development.
1043 cgm.errorNYI("Unhandled type in createNewGlobalView");
1044 return {};
1045}
1046
1047static mlir::Attribute getNewInitValue(CIRGenModule &cgm, cir::GlobalOp newGlob,
1048 mlir::Type oldTy,
1049 mlir::Attribute oldInit) {
1050 if (auto oldView = mlir::dyn_cast<cir::GlobalViewAttr>(oldInit))
1051 return createNewGlobalView(cgm, newGlob, oldView, oldTy);
1052
1053 auto getNewInitElements =
1054 [&](mlir::ArrayAttr oldElements) -> mlir::ArrayAttr {
1056 for (mlir::Attribute elt : oldElements) {
1057 if (auto view = mlir::dyn_cast<cir::GlobalViewAttr>(elt))
1058 newElements.push_back(createNewGlobalView(cgm, newGlob, view, oldTy));
1059 else if (mlir::isa<cir::ConstArrayAttr, cir::ConstRecordAttr>(elt))
1060 newElements.push_back(getNewInitValue(cgm, newGlob, oldTy, elt));
1061 else
1062 newElements.push_back(elt);
1063 }
1064 return mlir::ArrayAttr::get(cgm.getBuilder().getContext(), newElements);
1065 };
1066
1067 if (auto oldArray = mlir::dyn_cast<cir::ConstArrayAttr>(oldInit)) {
1068 // ConstArrayAttr::verify guarantees the elements are either an ArrayAttr or
1069 // a StringAttr. A StringAttr is a string-literal initializer: raw 8-bit
1070 // character bytes with no nested global references, so there is nothing to
1071 // rewrite and it is returned unchanged. The ArrayAttr case recurses to
1072 // rewrite any nested global views.
1073 mlir::Attribute oldElts = oldArray.getElts();
1074 if (mlir::isa<mlir::StringAttr>(oldElts))
1075 return oldInit;
1076 mlir::Attribute newElements =
1077 getNewInitElements(mlir::cast<mlir::ArrayAttr>(oldElts));
1078 return cgm.getBuilder().getConstArray(
1079 newElements, mlir::cast<cir::ArrayType>(oldArray.getType()));
1080 }
1081 if (auto oldRecord = mlir::dyn_cast<cir::ConstRecordAttr>(oldInit)) {
1082 mlir::ArrayAttr newMembers = getNewInitElements(oldRecord.getMembers());
1083 auto recordTy = mlir::cast<cir::RecordType>(oldRecord.getType());
1085 newMembers, recordTy.getPacked(), recordTy.getPadded(), recordTy);
1086 }
1087
1088 // This may be unreachable in practice, but keep it as errorNYI while CIR
1089 // is still under development.
1090 cgm.errorNYI("Unhandled type in getNewInitValue");
1091 return {};
1092}
1093
1094// We want to replace a global value, but because of CIR's typed pointers,
1095// we need to update the existing uses to reflect the new type, not just replace
1096// them directly.
1097void CIRGenModule::replaceGlobal(cir::GlobalOp oldGV, cir::GlobalOp newGV) {
1098 assert(oldGV.getSymName() == newGV.getSymName() && "symbol names must match");
1099
1100 mlir::Type oldTy = oldGV.getSymType();
1101 mlir::Type newTy = newGV.getSymType();
1102
1104
1105 // If the type didn't change, why are we here?
1106 assert(oldTy != newTy && "expected type change in replaceGlobal");
1107
1108 // Visit all uses and add handling to fix up the types.
1109 std::optional<mlir::SymbolTable::UseRange> oldSymUses =
1110 oldGV.getSymbolUses(theModule);
1111 for (mlir::SymbolTable::SymbolUse use : *oldSymUses) {
1112 mlir::Operation *userOp = use.getUser();
1113 assert(
1114 (mlir::isa<cir::GetGlobalOp, cir::GlobalOp, cir::ConstantOp>(userOp)) &&
1115 "Unexpected user for global op");
1116
1117 if (auto getGlobalOp = dyn_cast<cir::GetGlobalOp>(use.getUser())) {
1118 mlir::Value useOpResultValue = getGlobalOp.getAddr();
1119 useOpResultValue.setType(cir::PointerType::get(newTy));
1120
1121 mlir::OpBuilder::InsertionGuard guard(builder);
1122 builder.setInsertionPointAfter(getGlobalOp);
1123 mlir::Type ptrTy = builder.getPointerTo(oldTy);
1124 mlir::Value cast =
1125 builder.createBitcast(getGlobalOp->getLoc(), useOpResultValue, ptrTy);
1126 useOpResultValue.replaceAllUsesExcept(cast, cast.getDefiningOp());
1127 } else if (auto glob = dyn_cast<cir::GlobalOp>(userOp)) {
1128 if (auto init = glob.getInitialValue()) {
1129 mlir::Attribute nw = getNewInitValue(*this, newGV, oldTy, init.value());
1130 glob.setInitialValueAttr(nw);
1131 }
1132 } else if (auto c = dyn_cast<cir::ConstantOp>(userOp)) {
1133 mlir::Attribute init = getNewInitValue(*this, newGV, oldTy, c.getValue());
1134 auto typedAttr = mlir::cast<mlir::TypedAttr>(init);
1135 mlir::OpBuilder::InsertionGuard guard(builder);
1136 builder.setInsertionPointAfter(c);
1137 auto newUser = cir::ConstantOp::create(builder, c.getLoc(), typedAttr);
1138 c.replaceAllUsesWith(newUser.getOperation());
1139 c.erase();
1140 }
1141 }
1142
1143 // If the old global is being tracked as the most-recently-created global,
1144 // update it so that subsequent globals are not inserted after a (now
1145 // erased) operation, which would leave them detached from the module.
1146 if (lastGlobalOp == oldGV)
1147 lastGlobalOp = newGV;
1148 if (getLangOpts().CUDA)
1149 getCUDARuntime().handleGlobalReplace(oldGV, newGV);
1150 eraseGlobalSymbol(oldGV);
1151 oldGV.erase();
1152}
1153
1154/// If the specified mangled name is not in the module,
1155/// create and return an mlir GlobalOp with the specified type (TODO(cir):
1156/// address space).
1157///
1158/// TODO(cir):
1159/// 1. If there is something in the module with the specified name, return
1160/// it potentially bitcasted to the right type.
1161///
1162/// 2. If \p d is non-null, it specifies a decl that correspond to this. This
1163/// is used to set the attributes on the global when it is first created.
1164///
1165/// 3. If \p isForDefinition is true, it is guaranteed that an actual global
1166/// with type \p ty will be returned, not conversion of a variable with the same
1167/// mangled name but some other type.
1168cir::GlobalOp
1169CIRGenModule::getOrCreateCIRGlobal(StringRef mangledName, mlir::Type ty,
1170 LangAS langAS, const VarDecl *d,
1171 ForDefinition_t isForDefinition) {
1172
1173 // Lookup the entry, lazily creating it if necessary.
1174 cir::GlobalOp entry;
1175 if (mlir::Operation *v = getGlobalValue(mangledName)) {
1176 if (!isa<cir::GlobalOp>(v))
1178 "getOrCreateCIRGlobal: global with non-GlobalOp type");
1179 entry = cast<cir::GlobalOp>(v);
1180 }
1181
1182 if (entry) {
1183 mlir::ptr::MemorySpaceAttrInterface entryCIRAS = entry.getAddrSpaceAttr();
1185
1188
1189 if (entry.getSymType() == ty &&
1190 cir::isMatchingAddressSpace(entryCIRAS, langAS))
1191 return entry;
1192
1193 // If there are two attempts to define the same mangled name, issue an
1194 // error.
1195 //
1196 // TODO(cir): look at mlir::GlobalValue::isDeclaration for all aspects of
1197 // recognizing the global as a declaration, for now only check if
1198 // initializer is present.
1199 if (isForDefinition && !entry.isDeclaration()) {
1201 "getOrCreateCIRGlobal: global with conflicting type");
1202 }
1203
1204 // Address space check removed because it is unnecessary because CIR records
1205 // address space info in types.
1206
1207 // (If global is requested for a definition, we always need to create a new
1208 // global, not just return a bitcast.)
1209 if (!isForDefinition)
1210 return entry;
1211 }
1212
1213 mlir::Location loc = getLoc(d->getSourceRange());
1214
1215 // Calculate constant storage flag before creating the global. This was moved
1216 // from after the global creation to ensure the constant flag is set correctly
1217 // at creation time, matching the logic used in emitCXXGlobalVarDeclInit.
1218 bool isConstant = false;
1219 if (d) {
1220 bool needsDtor =
1222 isConstant = d->getType().isConstantStorage(
1223 astContext, /*ExcludeCtor=*/true, /*ExcludeDtor=*/!needsDtor);
1224 }
1225
1226 mlir::ptr::MemorySpaceAttrInterface declCIRAS =
1227 cir::toCIRAddressSpaceAttr(getMLIRContext(), getGlobalVarAddressSpace(d));
1228
1229 // mlir::SymbolTable::Visibility::Public is the default, no need to explicitly
1230 // mark it as such.
1231 cir::GlobalOp gv = createGlobalOp(loc, mangledName, ty, isConstant, declCIRAS,
1232 /*insertPoint=*/entry.getOperation());
1233
1234 // If we already created a global with the same mangled name (but different
1235 // type) before, remove it from its parent.
1236 if (entry)
1237 replaceGlobal(entry, gv);
1238
1239 // This is the first use or definition of a mangled name. If there is a
1240 // deferred decl with this name, remember that we need to emit it at the end
1241 // of the file.
1242 auto ddi = deferredDecls.find(mangledName);
1243 if (ddi != deferredDecls.end()) {
1244 // Move the potentially referenced deferred decl to the DeferredDeclsToEmit
1245 // list, and remove it from DeferredDecls (since we don't need it anymore).
1246 addDeferredDeclToEmit(ddi->second);
1247 deferredDecls.erase(ddi);
1248 }
1249
1250 // Handle things which are present even on external declarations.
1251 if (d) {
1252 if (langOpts.OpenMP && !langOpts.OpenMPSimd)
1254 "getOrCreateCIRGlobal: OpenMP target global variable");
1255
1256 gv.setAlignmentAttr(getSize(astContext.getDeclAlign(d)));
1257
1258 setLinkageForGV(gv, d);
1259
1260 if (d->getTLSKind())
1261 setTLSMode(gv, *d);
1262
1263 setGVProperties(gv, d);
1264
1265 // If required by the ABI, treat declarations of static data members with
1266 // inline initializers as definitions.
1267 if (astContext.isMSStaticDataMemberInlineDefinition(d))
1269 "getOrCreateCIRGlobal: MS static data member inline definition");
1270
1271 // Emit section information for extern variables.
1272 if (d->hasExternalStorage()) {
1273 if (const SectionAttr *sa = d->getAttr<SectionAttr>())
1274 gv.setSectionAttr(builder.getStringAttr(sa->getName()));
1275 }
1276
1277 // Handle XCore specific ABI requirements.
1278 if (getTriple().getArch() == llvm::Triple::xcore)
1280 "getOrCreateCIRGlobal: XCore specific ABI requirements");
1281
1282 // Check if we a have a const declaration with an initializer, we may be
1283 // able to emit it as available_externally to expose it's value to the
1284 // optimizer.
1285 if (getLangOpts().CPlusPlus && gv.isPublic() &&
1286 d->getType().isConstQualified() && gv.isDeclaration() &&
1287 !d->hasDefinition() && d->hasInit() && !d->hasAttr<DLLImportAttr>())
1288 errorNYI(
1289 d->getSourceRange(),
1290 "getOrCreateCIRGlobal: external const declaration with initializer");
1291 }
1292
1293 if (d &&
1296 // TODO(cir): set target attributes
1297 // External HIP managed variables needed to be recorded for transformation
1298 // in both device and host compilations.
1299 if (getLangOpts().CUDA && d && d->hasAttr<HIPManagedAttr>() &&
1300 d->hasExternalStorage())
1302 "getOrCreateCIRGlobal: HIP managed attribute");
1303 }
1304
1306 return gv;
1307}
1308
1309cir::GlobalOp
1311 ForDefinition_t isForDefinition) {
1312 assert(d->hasGlobalStorage() && "Not a global variable");
1313 QualType astTy = d->getType();
1314 if (!ty)
1315 ty = getTypes().convertTypeForMem(astTy);
1316
1317 StringRef mangledName = getMangledName(d);
1318 return getOrCreateCIRGlobal(mangledName, ty, getGlobalVarAddressSpace(d), d,
1319 isForDefinition);
1320}
1321
1322/// Return the mlir::Value for the address of the given global variable. If
1323/// \p ty is non-null and if the global doesn't exist, then it will be created
1324/// with the specified type instead of whatever the normal requested type would
1325/// be. If \p isForDefinition is true, it is guaranteed that an actual global
1326/// with type \p ty will be returned, not conversion of a variable with the same
1327/// mangled name but some other type.
1328mlir::Value CIRGenModule::getAddrOfGlobalVar(const VarDecl *d, mlir::Type ty,
1329 ForDefinition_t isForDefinition) {
1330 assert(d->hasGlobalStorage() && "Not a global variable");
1331 QualType astTy = d->getType();
1332 if (!ty)
1333 ty = getTypes().convertTypeForMem(astTy);
1334
1335 bool tlsAccess = d->getTLSKind() != VarDecl::TLS_None;
1336 cir::GlobalOp g = getOrCreateCIRGlobal(d, ty, isForDefinition);
1337 mlir::Type ptrTy = builder.getPointerTo(g.getSymType(), g.getAddrSpaceAttr());
1338 return cir::GetGlobalOp::create(
1339 builder, getLoc(d->getSourceRange()), ptrTy, g.getSymNameAttr(),
1340 tlsAccess,
1341 /*static_local=*/g.getStaticLocalGuard().has_value());
1342}
1343
1344cir::GlobalViewAttr CIRGenModule::getAddrOfGlobalVarAttr(const VarDecl *d) {
1345 assert(d->hasGlobalStorage() && "Not a global variable");
1346 mlir::Type ty = getTypes().convertTypeForMem(d->getType());
1347
1348 cir::GlobalOp globalOp = getOrCreateCIRGlobal(d, ty, NotForDefinition);
1349 cir::PointerType ptrTy =
1350 builder.getPointerTo(globalOp.getSymType(), globalOp.getAddrSpaceAttr());
1351 return builder.getGlobalViewAttr(ptrTy, globalOp);
1352}
1353
1354void CIRGenModule::addUsedGlobal(cir::CIRGlobalValueInterface gv) {
1355 assert((mlir::isa<cir::FuncOp>(gv.getOperation()) ||
1356 !gv.isDeclarationForLinker()) &&
1357 "Only globals with definition can force usage.");
1358 llvmUsed.emplace_back(gv);
1359}
1360
1361void CIRGenModule::addCompilerUsedGlobal(cir::CIRGlobalValueInterface gv) {
1362 assert(!gv.isDeclarationForLinker() &&
1363 "Only globals with definition can force usage.");
1364 llvmCompilerUsed.emplace_back(gv);
1365}
1366
1368 cir::CIRGlobalValueInterface gv) {
1369 assert((mlir::isa<cir::FuncOp>(gv.getOperation()) ||
1370 !gv.isDeclarationForLinker()) &&
1371 "Only globals with definition can force usage.");
1372 if (getTriple().isOSBinFormatELF())
1373 llvmCompilerUsed.emplace_back(gv);
1374 else
1375 llvmUsed.emplace_back(gv);
1376}
1377
1378static void emitUsed(CIRGenModule &cgm, StringRef name,
1379 std::vector<cir::CIRGlobalValueInterface> &list) {
1380 if (list.empty())
1381 return;
1382
1383 CIRGenBuilderTy &builder = cgm.getBuilder();
1384 mlir::Location loc = builder.getUnknownLoc();
1386 usedArray.resize(list.size());
1387 for (auto [i, op] : llvm::enumerate(list)) {
1388 usedArray[i] = cir::GlobalViewAttr::get(
1389 cgm.voidPtrTy, mlir::FlatSymbolRefAttr::get(op.getNameAttr()));
1390 }
1391
1392 cir::ArrayType arrayTy = cir::ArrayType::get(cgm.voidPtrTy, usedArray.size());
1393
1394 cir::ConstArrayAttr initAttr = cir::ConstArrayAttr::get(
1395 arrayTy, mlir::ArrayAttr::get(&cgm.getMLIRContext(), usedArray));
1396
1397 cir::GlobalOp gv = cgm.createGlobalOp(loc, name, arrayTy,
1398 /*isConstant=*/false);
1399 gv.setLinkage(cir::GlobalLinkageKind::AppendingLinkage);
1400 gv.setInitialValueAttr(initAttr);
1401 gv.setSectionAttr(builder.getStringAttr("llvm.metadata"));
1402}
1403
1405 emitUsed(*this, "llvm.used", llvmUsed);
1406 emitUsed(*this, "llvm.compiler.used", llvmCompilerUsed);
1407}
1408
1410 bool isTentative) {
1411 if (getLangOpts().OpenCL || getLangOpts().OpenMPIsTargetDevice) {
1413 "emitGlobalVarDefinition: emit OpenCL/OpenMP global variable");
1414 return;
1415 }
1416
1417 // Whether the definition of the variable is available externally.
1418 // If yes, we shouldn't emit the GloablCtor and GlobalDtor for the variable
1419 // since this is the job for its original source.
1420 bool isDefinitionAvailableExternally =
1421 astContext.GetGVALinkageForVariable(vd) == GVA_AvailableExternally;
1422
1423 // It is useless to emit the definition for an available_externally variable
1424 // which can't be marked as const.
1425 if (isDefinitionAvailableExternally &&
1426 (!vd->hasConstantInitialization() ||
1427 // TODO: Update this when we have interface to check constexpr
1428 // destructor.
1429 vd->needsDestruction(astContext) ||
1430 !vd->getType().isConstantStorage(astContext, true, true)))
1431 return;
1432
1433 mlir::Attribute init;
1434 bool needsGlobalCtor = false;
1435 bool needsGlobalDtor =
1436 !isDefinitionAvailableExternally &&
1438 const VarDecl *initDecl;
1439 const Expr *initExpr = vd->getAnyInitializer(initDecl);
1440
1441 std::optional<ConstantEmitter> emitter;
1442
1443 // CUDA E.2.4.1 "__shared__ variables cannot have an initialization
1444 // as part of their declaration." Sema has already checked for
1445 // error cases, so we just need to set Init to PoisonValue.
1446 bool isCUDASharedVar =
1447 getLangOpts().CUDAIsDevice && vd->hasAttr<CUDASharedAttr>();
1448 // Shadows of initialized device-side global variables are also left
1449 // undefined.
1450 // Managed Variables should be initialized on both host side and device side.
1451 bool isCUDAShadowVar =
1452 !getLangOpts().CUDAIsDevice && !vd->hasAttr<HIPManagedAttr>() &&
1453 (vd->hasAttr<CUDAConstantAttr>() || vd->hasAttr<CUDADeviceAttr>() ||
1454 vd->hasAttr<CUDASharedAttr>());
1455 bool isCUDADeviceShadowVar =
1456 getLangOpts().CUDAIsDevice && !vd->hasAttr<HIPManagedAttr>() &&
1459
1460 if (getLangOpts().CUDA &&
1461 (isCUDASharedVar || isCUDAShadowVar || isCUDADeviceShadowVar)) {
1462 init = cir::UndefAttr::get(convertType(vd->getType()));
1463 } else if (vd->hasAttr<LoaderUninitializedAttr>()) {
1465 "emitGlobalVarDefinition: loader uninitialized attribute");
1466 } else if (!initExpr) {
1467 // This is a tentative definition; tentative definitions are
1468 // implicitly initialized with { 0 }.
1469 //
1470 // Note that tentative definitions are only emitted at the end of
1471 // a translation unit, so they should never have incomplete
1472 // type. In addition, EmitTentativeDefinition makes sure that we
1473 // never attempt to emit a tentative definition if a real one
1474 // exists. A use may still exists, however, so we still may need
1475 // to do a RAUW.
1476 assert(!vd->getType()->isIncompleteType() && "Unexpected incomplete type");
1477 init = builder.getZeroInitAttr(convertType(vd->getType()));
1478 } else {
1479 emitter.emplace(*this);
1480 mlir::Attribute initializer = emitter->tryEmitForInitializer(*initDecl);
1481 if (!initializer) {
1482 QualType qt = initExpr->getType();
1483 if (vd->getType()->isReferenceType())
1484 qt = vd->getType();
1485
1486 if (getLangOpts().CPlusPlus) {
1487 if (initDecl->hasFlexibleArrayInit(astContext))
1489 "emitGlobalVarDefinition: flexible array initializer");
1490 init = builder.getZeroInitAttr(convertType(qt));
1491 if (!isDefinitionAvailableExternally)
1492 needsGlobalCtor = true;
1493 } else {
1495 "emitGlobalVarDefinition: static initializer");
1496 }
1497 } else {
1498 init = initializer;
1499 // We don't need an initializer, so remove the entry for the delayed
1500 // initializer position (just in case this entry was delayed) if we
1501 // also don't need to register a destructor.
1503 }
1504 }
1505
1506 mlir::Type initType;
1507 if (mlir::isa<mlir::SymbolRefAttr>(init)) {
1508 errorNYI(
1509 vd->getSourceRange(),
1510 "emitGlobalVarDefinition: global initializer is a symbol reference");
1511 return;
1512 } else {
1513 assert(mlir::isa<mlir::TypedAttr>(init) && "This should have a type");
1514 auto typedInitAttr = mlir::cast<mlir::TypedAttr>(init);
1515 initType = typedInitAttr.getType();
1516 }
1517 assert(!mlir::isa<mlir::NoneType>(initType) && "Should have a type by now");
1518
1519 cir::GlobalOp gv =
1520 getOrCreateCIRGlobal(vd, initType, ForDefinition_t(!isTentative));
1521 // TODO(cir): Strip off pointer casts from Entry if we get them?
1522
1523 if (!gv || gv.getSymType() != initType) {
1525 "emitGlobalVarDefinition: global initializer with type mismatch");
1526 return;
1527 }
1528
1530
1531 if (vd->hasAttr<AnnotateAttr>())
1532 addGlobalAnnotations(vd, gv);
1533
1534 // Set CIR's linkage type as appropriate.
1535 cir::GlobalLinkageKind linkage = getCIRLinkageVarDefinition(vd);
1536
1537 // CUDA B.2.1 "The __device__ qualifier declares a variable that resides on
1538 // the device. [...]"
1539 // CUDA B.2.2 "The __constant__ qualifier, optionally used together with
1540 // __device__, declares a variable that: [...]
1541 // Is accessible from all the threads within the grid and from the host
1542 // through the runtime library (cudaGetSymbolAddress() / cudaGetSymbolSize()
1543 // / cudaMemcpyToSymbol() / cudaMemcpyFromSymbol())."
1544 if (langOpts.CUDA) {
1545 if (langOpts.CUDAIsDevice) {
1546 // __shared__ variables is not marked as externally initialized,
1547 // because they must not be initialized.
1548 if (linkage != cir::GlobalLinkageKind::InternalLinkage &&
1549 !vd->isConstexpr() && !vd->getType().isConstQualified() &&
1550 (vd->hasAttr<CUDADeviceAttr>() || vd->hasAttr<CUDAConstantAttr>() ||
1553 gv->setAttr(cir::CUDAExternallyInitializedAttr::getMnemonic(),
1554 cir::CUDAExternallyInitializedAttr::get(&getMLIRContext()));
1555 }
1556 } else {
1557 // Adjust linkage of shadow variables in host compilation
1559 }
1561 }
1562
1563 // Set initializer and finalize emission
1565 if (emitter)
1566 emitter->finalize(gv);
1567
1568 // If it is safe to mark the global 'constant', do so now.
1569 // Use the same logic as classic codegen EmitGlobalVarDefinition.
1570 gv.setConstant((vd->hasAttr<CUDAConstantAttr>() && langOpts.CUDAIsDevice) ||
1571 (!needsGlobalCtor && !needsGlobalDtor &&
1572 vd->getType().isConstantStorage(astContext,
1573 /*ExcludeCtor=*/true,
1574 /*ExcludeDtor=*/true)));
1575 // If it is in a read-only section, mark it 'constant'.
1576 if (const SectionAttr *sa = vd->getAttr<SectionAttr>()) {
1577 const ASTContext::SectionInfo &si = astContext.SectionInfos[sa->getName()];
1578 if ((si.SectionFlags & ASTContext::PSF_Write) == 0)
1579 gv.setConstant(true);
1580 }
1581
1582 // Set CIR linkage and DLL storage class.
1583 gv.setLinkage(linkage);
1584 // FIXME(cir): setLinkage should likely set MLIR's visibility automatically.
1585 gv.setVisibility(getMLIRVisibilityFromCIRLinkage(linkage));
1587 if (linkage == cir::GlobalLinkageKind::CommonLinkage) {
1588 // common vars aren't constant even if declared const.
1589 gv.setConstant(false);
1590 // Tentative definition of global variables may be initialized with
1591 // non-zero null pointers. In this case they should have weak linkage
1592 // since common linkage must have zero initializer and must not have
1593 // explicit section therefore cannot have non-zero initial value.
1594 std::optional<mlir::Attribute> initializer = gv.getInitialValue();
1595 if (initializer && !getBuilder().isNullValue(*initializer))
1596 gv.setLinkage(cir::GlobalLinkageKind::WeakAnyLinkage);
1597 }
1598
1599 setNonAliasAttributes(vd, gv);
1600
1601 if (vd->getTLSKind() && !vd->isStaticLocal())
1602 setTLSMode(gv, *vd);
1603
1604 maybeSetTrivialComdat(*vd, gv);
1605
1606 // Emit the initializer function if necessary.
1607 if (needsGlobalCtor || needsGlobalDtor)
1608 emitCXXGlobalVarDeclInitFunc(vd, gv, needsGlobalCtor);
1609}
1610
1612 if (getFunctionLinkage(gd) !=
1613 cir::GlobalLinkageKind::AvailableExternallyLinkage)
1614 return true;
1615
1616 const auto *fd = cast<FunctionDecl>(gd.getDecl());
1617 // Inline builtins must be emitted; the body is redirected to a `.inline`
1618 // symbol in CIRGenFunction::generateCode.
1619 if (fd->isInlineBuiltinDeclaration())
1620 return true;
1621
1622 // PR9614 / glibc btowc workaround: an available_externally function whose
1623 // body just calls itself (via asm label or __builtin_* lowering on the
1624 // same name) is not a valid stand-in for the real implementation. Drop
1625 // it from the IR so the optimizer doesn't reason about its body.
1627}
1628
1630 mlir::Operation *op) {
1631 const auto *decl = cast<ValueDecl>(gd.getDecl());
1632 if (const auto *fd = dyn_cast<FunctionDecl>(decl)) {
1633 if (!shouldEmitFunction(gd))
1634 return;
1635
1636 if (const auto *method = dyn_cast<CXXMethodDecl>(decl)) {
1637 // Make sure to emit the definition(s) before we emit the thunks. This is
1638 // necessary for the generation of certain thunks.
1639 if (isa<CXXConstructorDecl>(method) || isa<CXXDestructorDecl>(method))
1640 abi->emitCXXStructor(gd);
1641 else if (fd->isMultiVersion())
1642 errorNYI(method->getSourceRange(), "multiversion functions");
1643 else
1645
1646 if (method->isVirtual())
1647 getVTables().emitThunks(gd);
1648
1649 return;
1650 }
1651
1652 if (fd->isMultiVersion())
1653 errorNYI(fd->getSourceRange(), "multiversion functions");
1655 return;
1656 }
1657
1658 if (const auto *vd = dyn_cast<VarDecl>(decl))
1659 return emitGlobalVarDefinition(vd, !vd->hasDefinition());
1660
1661 llvm_unreachable("Invalid argument to CIRGenModule::emitGlobalDefinition");
1662}
1663
1664mlir::Attribute
1666 assert(!e->getType()->isPointerType() && "Strings are always arrays");
1667
1668 // Don't emit it as the address of the string, emit the string data itself
1669 // as an inline array.
1670 if (e->getCharByteWidth() == 1) {
1671 SmallString<64> str(e->getString());
1672
1673 // Resize the string to the right size, which is indicated by its type.
1674 const ConstantArrayType *cat =
1675 astContext.getAsConstantArrayType(e->getType());
1676 uint64_t finalSize = cat->getZExtSize();
1677 str.resize(finalSize);
1678
1679 mlir::Type eltTy = convertType(cat->getElementType());
1680 return builder.getString(str, eltTy, finalSize, /*ensureNullTerm=*/false);
1681 }
1682
1683 auto arrayTy = mlir::cast<cir::ArrayType>(convertType(e->getType()));
1684
1685 auto arrayEltTy = mlir::cast<cir::IntType>(arrayTy.getElementType());
1686
1687 uint64_t arraySize = arrayTy.getSize();
1688 unsigned literalSize = e->getLength();
1689 assert(arraySize > literalSize &&
1690 "wide string literal array size must have room for null terminator?");
1691
1692 // Check if the string is all null bytes before building the vector.
1693 // In most non-zero cases, this will break out on the first element.
1694 bool isAllZero = true;
1695 for (unsigned i = 0; i < literalSize; ++i) {
1696 if (e->getCodeUnit(i) != 0) {
1697 isAllZero = false;
1698 break;
1699 }
1700 }
1701
1702 if (isAllZero)
1703 return cir::ZeroAttr::get(arrayTy);
1704
1705 // Otherwise emit a constant array holding the characters.
1707 elements.reserve(arraySize);
1708 for (unsigned i = 0; i < literalSize; ++i)
1709 elements.push_back(cir::IntAttr::get(arrayEltTy, e->getCodeUnit(i)));
1710
1711 auto elementsAttr = mlir::ArrayAttr::get(&getMLIRContext(), elements);
1712 return builder.getConstArray(elementsAttr, arrayTy);
1713}
1714
1716 return getTriple().supportsCOMDAT();
1717}
1718
1719static bool shouldBeInCOMDAT(CIRGenModule &cgm, const Decl &d) {
1720 if (!cgm.supportsCOMDAT())
1721 return false;
1722
1723 if (d.hasAttr<SelectAnyAttr>())
1724 return true;
1725
1726 GVALinkage linkage;
1727 if (auto *vd = dyn_cast<VarDecl>(&d))
1728 linkage = cgm.getASTContext().GetGVALinkageForVariable(vd);
1729 else
1730 linkage =
1732
1733 switch (linkage) {
1737 return false;
1740 return true;
1741 }
1742 llvm_unreachable("No such linkage");
1743}
1744
1745void CIRGenModule::maybeSetTrivialComdat(const Decl &d, mlir::Operation *op) {
1746 if (!shouldBeInCOMDAT(*this, d))
1747 return;
1748 if (auto globalOp = dyn_cast_or_null<cir::GlobalOp>(op)) {
1749 globalOp.setComdat(true);
1750 } else {
1751 auto funcOp = cast<cir::FuncOp>(op);
1752 funcOp.setComdat(true);
1753 }
1754}
1755
1757 // Make sure that this type is translated.
1758 genTypes.updateCompletedType(td);
1759}
1760
1761void CIRGenModule::addReplacement(StringRef name, mlir::Operation *op) {
1762 replacements[name] = op;
1763}
1764
1765#ifndef NDEBUG
1766static bool verifyPointerTypeArgs(cir::FuncOp oldF, cir::FuncOp newF,
1767 mlir::SymbolUserMap &userMap) {
1768 for (mlir::Operation *user : userMap.getUsers(oldF)) {
1769 auto call = mlir::dyn_cast<cir::CallOp>(user);
1770 if (!call)
1771 continue;
1772
1773 for (auto [argOp, fnArgType] :
1774 llvm::zip(call.getArgs(), newF.getFunctionType().getInputs())) {
1775 if (argOp.getType() != fnArgType)
1776 return false;
1777 }
1778 }
1779
1780 return true;
1781}
1782#endif // NDEBUG
1783
1784void CIRGenModule::applyReplacements() {
1785 if (replacements.empty())
1786 return;
1787
1788 // Build a symbol user map once — this walks the module O(M) one time.
1789 // Previously, each replaceAllSymbolUses call walked the entire module,
1790 // giving O(R × M) quadratic behavior for R replacements.
1791 mlir::SymbolTableCollection symbolTableCollection;
1792 mlir::SymbolUserMap userMap(symbolTableCollection, theModule);
1793
1794 for (auto &i : replacements) {
1795 StringRef mangledName = i.first;
1796 mlir::Operation *replacement = i.second;
1797 mlir::Operation *entry = getGlobalValue(mangledName);
1798 if (!entry)
1799 continue;
1800 assert(isa<cir::FuncOp>(entry) && "expected function");
1801 auto oldF = cast<cir::FuncOp>(entry);
1802 auto newF = dyn_cast<cir::FuncOp>(replacement);
1803 if (!newF) {
1804 // In classic codegen, this can be a global alias, a bitcast, or a GEP.
1805 errorNYI(replacement->getLoc(), "replacement is not a function");
1806 continue;
1807 }
1808
1809 assert(verifyPointerTypeArgs(oldF, newF, userMap) &&
1810 "call argument types do not match replacement function");
1811
1812 // Replace old with new, but keep the old order. Uses
1813 // SymbolUserMap to touch only actual users, not the whole module.
1814 userMap.replaceAllUsesWith(oldF, newF.getSymNameAttr());
1815 newF->moveBefore(oldF);
1816 eraseGlobalSymbol(oldF);
1817 oldF->erase();
1818 }
1819}
1820
1822 mlir::Location loc, StringRef name, mlir::Type ty,
1823 cir::GlobalLinkageKind linkage, clang::CharUnits alignment) {
1824 auto gv = mlir::dyn_cast_or_null<cir::GlobalOp>(getGlobalValue(name));
1825
1826 if (gv) {
1827 // Check if the variable has the right type.
1828 if (gv.getSymType() == ty)
1829 return gv;
1830
1831 // Because of C++ name mangling, the only way we can end up with an already
1832 // existing global with the same name is if it has been declared extern
1833 // "C".
1834 assert(gv.isDeclaration() && "Declaration has wrong type!");
1835
1836 errorNYI(loc, "createOrReplaceCXXRuntimeVariable: declaration exists with "
1837 "wrong type");
1838 return gv;
1839 }
1840
1841 // Create a new variable.
1842 gv = createGlobalOp(loc, name, ty);
1843
1844 // Set up extra information and add to the module
1845 gv.setLinkageAttr(
1846 cir::GlobalLinkageKindAttr::get(&getMLIRContext(), linkage));
1847 mlir::SymbolTable::setSymbolVisibility(gv,
1849
1850 if (supportsCOMDAT() && cir::isWeakForLinker(linkage) &&
1851 !gv.hasAvailableExternallyLinkage()) {
1852 gv.setComdat(true);
1853 }
1854
1855 gv.setAlignmentAttr(getSize(alignment));
1856 setDSOLocal(static_cast<mlir::Operation *>(gv));
1857 return gv;
1858}
1859
1860// TODO(CIR): this could be a common method between LLVM codegen.
1861static bool isVarDeclStrongDefinition(const ASTContext &astContext,
1862 CIRGenModule &cgm, const VarDecl *vd,
1863 bool noCommon) {
1864 // Don't give variables common linkage if -fno-common was specified unless it
1865 // was overridden by a NoCommon attribute.
1866 if ((noCommon || vd->hasAttr<NoCommonAttr>()) && !vd->hasAttr<CommonAttr>())
1867 return true;
1868
1869 // C11 6.9.2/2:
1870 // A declaration of an identifier for an object that has file scope without
1871 // an initializer, and without a storage-class specifier or with the
1872 // storage-class specifier static, constitutes a tentative definition.
1873 if (vd->getInit() || vd->hasExternalStorage())
1874 return true;
1875
1876 // A variable cannot be both common and exist in a section.
1877 if (vd->hasAttr<SectionAttr>())
1878 return true;
1879
1880 // A variable cannot be both common and exist in a section.
1881 // We don't try to determine which is the right section in the front-end.
1882 // If no specialized section name is applicable, it will resort to default.
1883 if (vd->hasAttr<PragmaClangBSSSectionAttr>() ||
1884 vd->hasAttr<PragmaClangDataSectionAttr>() ||
1885 vd->hasAttr<PragmaClangRelroSectionAttr>() ||
1886 vd->hasAttr<PragmaClangRodataSectionAttr>())
1887 return true;
1888
1889 // Thread local vars aren't considered common linkage.
1890 if (vd->getTLSKind())
1891 return true;
1892
1893 // Tentative definitions marked with WeakImportAttr are true definitions.
1894 if (vd->hasAttr<WeakImportAttr>())
1895 return true;
1896
1897 // A variable cannot be both common and exist in a comdat.
1898 if (shouldBeInCOMDAT(cgm, *vd))
1899 return true;
1900
1901 // Declarations with a required alignment do not have common linkage in MSVC
1902 // mode.
1903 if (astContext.getTargetInfo().getCXXABI().isMicrosoft()) {
1904 if (vd->hasAttr<AlignedAttr>())
1905 return true;
1906 QualType varType = vd->getType();
1907 if (astContext.isAlignmentRequired(varType))
1908 return true;
1909
1910 if (const auto *rd = varType->getAsRecordDecl()) {
1911 for (const FieldDecl *fd : rd->fields()) {
1912 if (fd->isBitField())
1913 continue;
1914 if (fd->hasAttr<AlignedAttr>())
1915 return true;
1916 if (astContext.isAlignmentRequired(fd->getType()))
1917 return true;
1918 }
1919 }
1920 }
1921
1922 // Microsoft's link.exe doesn't support alignments greater than 32 bytes for
1923 // common symbols, so symbols with greater alignment requirements cannot be
1924 // common.
1925 // Other COFF linkers (ld.bfd and LLD) support arbitrary power-of-two
1926 // alignments for common symbols via the aligncomm directive, so this
1927 // restriction only applies to MSVC environments.
1928 if (astContext.getTargetInfo().getTriple().isKnownWindowsMSVCEnvironment() &&
1929 astContext.getTypeAlignIfKnown(vd->getType()) >
1930 astContext.toBits(CharUnits::fromQuantity(32)))
1931 return true;
1932
1933 return false;
1934}
1935
1936cir::GlobalLinkageKind
1938 GVALinkage linkage) {
1939 if (linkage == GVA_Internal)
1940 return cir::GlobalLinkageKind::InternalLinkage;
1941
1942 if (dd->hasAttr<WeakAttr>())
1943 return cir::GlobalLinkageKind::WeakAnyLinkage;
1944
1945 if (const auto *fd = dd->getAsFunction())
1946 if (fd->isMultiVersion() && linkage == GVA_AvailableExternally)
1947 return cir::GlobalLinkageKind::LinkOnceAnyLinkage;
1948
1949 // We are guaranteed to have a strong definition somewhere else,
1950 // so we can use available_externally linkage.
1951 if (linkage == GVA_AvailableExternally)
1952 return cir::GlobalLinkageKind::AvailableExternallyLinkage;
1953
1954 // Note that Apple's kernel linker doesn't support symbol
1955 // coalescing, so we need to avoid linkonce and weak linkages there.
1956 // Normally, this means we just map to internal, but for explicit
1957 // instantiations we'll map to external.
1958
1959 // In C++, the compiler has to emit a definition in every translation unit
1960 // that references the function. We should use linkonce_odr because
1961 // a) if all references in this translation unit are optimized away, we
1962 // don't need to codegen it. b) if the function persists, it needs to be
1963 // merged with other definitions. c) C++ has the ODR, so we know the
1964 // definition is dependable.
1965 if (linkage == GVA_DiscardableODR)
1966 return !astContext.getLangOpts().AppleKext
1967 ? cir::GlobalLinkageKind::LinkOnceODRLinkage
1968 : cir::GlobalLinkageKind::InternalLinkage;
1969
1970 // An explicit instantiation of a template has weak linkage, since
1971 // explicit instantiations can occur in multiple translation units
1972 // and must all be equivalent. However, we are not allowed to
1973 // throw away these explicit instantiations.
1974 //
1975 // CUDA/HIP: For -fno-gpu-rdc case, device code is limited to one TU,
1976 // so say that CUDA templates are either external (for kernels) or internal.
1977 // This lets llvm perform aggressive inter-procedural optimizations. For
1978 // -fgpu-rdc case, device function calls across multiple TU's are allowed,
1979 // therefore we need to follow the normal linkage paradigm.
1980 if (linkage == GVA_StrongODR) {
1981 if (getLangOpts().AppleKext)
1982 return cir::GlobalLinkageKind::ExternalLinkage;
1983 if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice &&
1984 !getLangOpts().GPURelocatableDeviceCode)
1985 return dd->hasAttr<CUDAGlobalAttr>()
1986 ? cir::GlobalLinkageKind::ExternalLinkage
1987 : cir::GlobalLinkageKind::InternalLinkage;
1988 return cir::GlobalLinkageKind::WeakODRLinkage;
1989 }
1990
1991 // C++ doesn't have tentative definitions and thus cannot have common
1992 // linkage.
1993 if (!getLangOpts().CPlusPlus && isa<VarDecl>(dd) &&
1994 !isVarDeclStrongDefinition(astContext, *this, cast<VarDecl>(dd),
1995 getCodeGenOpts().NoCommon))
1996 return cir::GlobalLinkageKind::CommonLinkage;
1997
1998 // selectany symbols are externally visible, so use weak instead of
1999 // linkonce. MSVC optimizes away references to const selectany globals, so
2000 // all definitions should be the same and ODR linkage should be used.
2001 // http://msdn.microsoft.com/en-us/library/5tkz6s71.aspx
2002 if (dd->hasAttr<SelectAnyAttr>())
2003 return cir::GlobalLinkageKind::WeakODRLinkage;
2004
2005 // Otherwise, we have strong external linkage.
2006 assert(linkage == GVA_StrongExternal);
2007 return cir::GlobalLinkageKind::ExternalLinkage;
2008}
2009
2010/// This function is called when we implement a function with no prototype, e.g.
2011/// "int foo() {}". If there are existing call uses of the old function in the
2012/// module, this adjusts them to call the new function directly.
2013///
2014/// This is not just a cleanup: the always_inline pass requires direct calls to
2015/// functions to be able to inline them. If there is a bitcast in the way, it
2016/// won't inline them. Instcombine normally deletes these calls, but it isn't
2017/// run at -O0.
2019 mlir::Operation *old, cir::FuncOp newFn) {
2020 // If we're redefining a global as a function, don't transform it.
2021 auto oldFn = mlir::dyn_cast<cir::FuncOp>(old);
2022 if (!oldFn)
2023 return;
2024
2025 // TODO(cir): this RAUW ignores the features below.
2029 if (oldFn->getAttrs().size() <= 1)
2030 errorNYI(old->getLoc(),
2031 "replaceUsesOfNonProtoTypeWithRealFunction: Attribute forwarding");
2032
2033 // Mark new function as originated from a no-proto declaration.
2034 newFn.setNoProto(oldFn.getNoProto());
2035
2036 // Iterate through all calls of the no-proto function.
2037 std::optional<mlir::SymbolTable::UseRange> symUses =
2038 oldFn.getSymbolUses(oldFn->getParentOp());
2039 for (const mlir::SymbolTable::SymbolUse &use : symUses.value()) {
2040 mlir::OpBuilder::InsertionGuard guard(builder);
2041
2042 if (auto noProtoCallOp = mlir::dyn_cast<cir::CallOp>(use.getUser())) {
2043 builder.setInsertionPoint(noProtoCallOp);
2044
2045 // Patch call type with the real function type.
2046 cir::FuncType newFnType = newFn.getFunctionType();
2047 mlir::OperandRange callOperands = noProtoCallOp.getOperands();
2048 bool returnTypeMatches =
2049 newFnType.hasVoidReturn()
2050 ? noProtoCallOp.getNumResults() == 0
2051 : noProtoCallOp.getNumResults() == 1 &&
2052 noProtoCallOp.getResultTypes().front() ==
2053 newFnType.getReturnType();
2054 bool typesMatch = !newFn.getNoProto() && returnTypeMatches &&
2055 callOperands.size() == newFnType.getNumInputs();
2056 for (unsigned i = 0, e = newFnType.getNumInputs(); typesMatch && i != e;
2057 ++i) {
2058 if (callOperands[i].getType() != newFnType.getInput(i))
2059 typesMatch = false;
2060 }
2061
2062 cir::CallOp realCallOp;
2063 if (typesMatch) {
2064 // Patch call type with the real function type.
2065 realCallOp =
2066 builder.createCallOp(noProtoCallOp.getLoc(), newFn, callOperands);
2067 } else {
2068 // Build an indirect call whose function-pointer signature matches
2069 // the existing call site.
2070 cir::FuncType origFnType = oldFn.getFunctionType();
2071 cir::FuncType callFnType =
2072 origFnType.isVarArg()
2073 ? cir::FuncType::get(origFnType.getInputs(),
2074 origFnType.getReturnType(),
2075 /*isVarArg=*/false)
2076 : origFnType;
2077 mlir::Value addr = cir::GetGlobalOp::create(
2078 builder, noProtoCallOp.getLoc(), cir::PointerType::get(newFnType),
2079 newFn.getSymName());
2080 mlir::Value casted =
2081 builder.createBitcast(addr, cir::PointerType::get(callFnType));
2082 realCallOp = builder.createIndirectCallOp(
2083 noProtoCallOp.getLoc(), casted, callFnType, callOperands);
2084 }
2085
2086 // Replace old no proto call with fixed call.
2087 noProtoCallOp.replaceAllUsesWith(realCallOp);
2088 noProtoCallOp.erase();
2089 } else if (auto getGlobalOp =
2090 mlir::dyn_cast<cir::GetGlobalOp>(use.getUser())) {
2091 // The GetGlobal was emitted with the no-proto FuncType. Uses of this
2092 // operation (cir.store, cir.cast) were built for that pointer type. When
2093 // we re-type the result to the real FuncType, we need to add a bit the
2094 // old pointer type so those uses are still valid. This can lead to
2095 // some redundant bitcast chains, but those will be cleaned up by the
2096 // canonicalizer.
2097 mlir::Value res = getGlobalOp.getAddr();
2098 const mlir::Type oldResTy = res.getType();
2099 const auto newPtrTy = cir::PointerType::get(newFn.getFunctionType());
2100 if (oldResTy != newPtrTy) {
2101 res.setType(newPtrTy);
2102 builder.setInsertionPointAfter(getGlobalOp.getOperation());
2103 mlir::Value castRes =
2104 cir::CastOp::create(builder, getGlobalOp.getLoc(), oldResTy,
2105 cir::CastKind::bitcast, res);
2106 res.replaceAllUsesExcept(castRes, castRes.getDefiningOp());
2107 }
2108 } else if (mlir::isa<cir::GlobalOp>(use.getUser())) {
2109 // Function addresses in global initializers use GlobalViewAttrs typed to
2110 // the initializer context (e.g. struct field type), not the FuncOp type,
2111 // so no update is required when the no-proto FuncOp is replaced.
2112 } else {
2113 llvm_unreachable(
2114 "replaceUsesOfNonProtoTypeWithRealFunction: unexpected use type");
2115 }
2116 }
2117}
2118
2119cir::GlobalLinkageKind
2121 GVALinkage linkage = astContext.GetGVALinkageForVariable(vd);
2122 return getCIRLinkageForDeclarator(vd, linkage);
2123}
2124
2126 const auto *d = cast<FunctionDecl>(gd.getDecl());
2127
2128 GVALinkage linkage = astContext.GetGVALinkageForFunction(d);
2129
2130 if (const auto *dtor = dyn_cast<CXXDestructorDecl>(d))
2131 return getCXXABI().getCXXDestructorLinkage(linkage, dtor, gd.getDtorType());
2132
2133 return getCIRLinkageForDeclarator(d, linkage);
2134}
2135
2136static cir::GlobalOp
2137generateStringLiteral(mlir::Location loc, mlir::TypedAttr c,
2138 cir::GlobalLinkageKind lt, CIRGenModule &cgm,
2139 StringRef globalName, CharUnits alignment) {
2141
2142 // Create a global variable for this string
2143 // FIXME(cir): check for insertion point in module level.
2144 cir::GlobalOp gv = cgm.createGlobalOp(loc, globalName, c.getType(),
2145 !cgm.getLangOpts().WritableStrings);
2146
2147 // Set up extra information and add to the module
2148 gv.setAlignmentAttr(cgm.getSize(alignment));
2149 gv.setLinkageAttr(
2150 cir::GlobalLinkageKindAttr::get(cgm.getBuilder().getContext(), lt));
2154 if (gv.isWeakForLinker()) {
2155 assert(cgm.supportsCOMDAT() && "Only COFF uses weak string literals");
2156 gv.setComdat(true);
2157 }
2158 cgm.setDSOLocal(static_cast<mlir::Operation *>(gv));
2159 return gv;
2160}
2161
2162// LLVM IR automatically uniques names when new llvm::GlobalVariables are
2163// created. This is handy, for example, when creating globals for string
2164// literals. Since we don't do that when creating cir::GlobalOp's, we need
2165// a mechanism to generate a unique name in advance.
2166//
2167// For now, this mechanism is only used in cases where we know that the
2168// name is compiler-generated, so we don't use the MLIR symbol table for
2169// the lookup.
2170std::string CIRGenModule::getUniqueGlobalName(const std::string &baseName) {
2171 // If this is the first time we've generated a name for this basename, use
2172 // it as is and start a counter for this base name.
2173 auto it = cgGlobalNames.find(baseName);
2174 if (it == cgGlobalNames.end()) {
2175 cgGlobalNames[baseName] = 1;
2176 return baseName;
2177 }
2178
2179 std::string result =
2180 baseName + "." + std::to_string(cgGlobalNames[baseName]++);
2181 // There should not be any symbol with this name in the module.
2182 assert(!getGlobalValue(result));
2183 return result;
2184}
2185
2186/// Return a pointer to a constant array for the given string literal.
2188 StringRef name) {
2189 CharUnits alignment =
2190 astContext.getAlignOfGlobalVarInChars(s->getType(), /*VD=*/nullptr);
2191
2192 mlir::Attribute c = getConstantArrayFromStringLiteral(s);
2193
2194 cir::GlobalOp gv;
2195 if (!getLangOpts().WritableStrings && constantStringMap.count(c)) {
2196 gv = constantStringMap[c];
2197 // The bigger alignment always wins.
2198 if (!gv.getAlignment() ||
2199 uint64_t(alignment.getQuantity()) > *gv.getAlignment())
2200 gv.setAlignmentAttr(getSize(alignment));
2201 } else {
2202 // Mangle the string literal if that's how the ABI merges duplicate strings.
2203 // Don't do it if they are writable, since we don't want writes in one TU to
2204 // affect strings in another.
2205 if (getCXXABI().getMangleContext().shouldMangleStringLiteral(s) &&
2206 !getLangOpts().WritableStrings) {
2208 "getGlobalForStringLiteral: mangle string literals");
2209 }
2210
2211 // Unlike LLVM IR, CIR doesn't automatically unique names for globals, so
2212 // we need to do that explicitly.
2213 std::string uniqueName = getUniqueGlobalName(name.str());
2214 // Synthetic string literals (e.g., from SourceLocExpr) may not have valid
2215 // source locations. Use unknown location in those cases.
2216 mlir::Location loc = s->getBeginLoc().isValid()
2217 ? getLoc(s->getSourceRange())
2218 : builder.getUnknownLoc();
2219 auto typedC = llvm::cast<mlir::TypedAttr>(c);
2220 gv = generateStringLiteral(loc, typedC,
2221 cir::GlobalLinkageKind::PrivateLinkage, *this,
2222 uniqueName, alignment);
2223 setDSOLocal(static_cast<mlir::Operation *>(gv));
2224 constantStringMap[c] = gv;
2225
2227 }
2228 return gv;
2229}
2230
2231/// Return a pointer to a constant array for the given string literal.
2232cir::GlobalViewAttr
2234 StringRef name) {
2235 cir::GlobalOp gv = getGlobalForStringLiteral(s, name);
2236 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(gv.getSymType());
2237 assert(arrayTy && "String literal must be array");
2239 cir::PointerType ptrTy = getBuilder().getPointerTo(arrayTy.getElementType());
2240
2241 return builder.getGlobalViewAttr(ptrTy, gv);
2242}
2243
2244// TODO(cir): this could be a common AST helper for both CIR and LLVM codegen.
2246 if (getLangOpts().OpenCL)
2248
2249 // For temporaries inside functions, CUDA treats them as normal variables.
2250 // LangAS::cuda_device, on the other hand, is reserved for those variables
2251 // explicitly marked with __device__.
2252 if (getLangOpts().CUDAIsDevice)
2253 return LangAS::Default;
2254
2255 if (getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice)
2257 if (getLangOpts().SYCLIsDevice)
2258 errorNYI("SYCL temp address space");
2259
2260 return LangAS::Default;
2261}
2262
2264 CIRGenFunction *cgf) {
2265 if (cgf && e->getType()->isVariablyModifiedType())
2267
2269 "emitExplicitCastExprType");
2270}
2271
2273 const MemberPointerType *mpt) {
2274 if (mpt->isMemberFunctionPointerType()) {
2275 auto ty = mlir::cast<cir::MethodType>(convertType(destTy));
2276 return builder.getNullMethodAttr(ty);
2277 }
2278
2279 auto ty = mlir::cast<cir::DataMemberType>(convertType(destTy));
2280 return builder.getNullDataMemberAttr(ty);
2281}
2282
2285
2286 mlir::Location loc = getLoc(e->getSourceRange());
2287
2288 const auto *decl = cast<DeclRefExpr>(e->getSubExpr())->getDecl();
2289
2290 // A member function pointer.
2291 if (const auto *methodDecl = dyn_cast<CXXMethodDecl>(decl)) {
2292 auto ty = mlir::cast<cir::MethodType>(convertType(e->getType()));
2293 if (methodDecl->isVirtual())
2294 return cir::ConstantOp::create(
2295 builder, loc, getCXXABI().buildVirtualMethodAttr(ty, methodDecl));
2296
2297 const CIRGenFunctionInfo &fi =
2299 cir::FuncType funcTy = getTypes().getFunctionType(fi);
2300 cir::FuncOp methodFuncOp = getAddrOfFunction(methodDecl, funcTy);
2301 return cir::ConstantOp::create(builder, loc,
2302 builder.getMethodAttr(ty, methodFuncOp));
2303 }
2304
2305 // Otherwise, a member data pointer.
2306 auto ty = mlir::cast<cir::DataMemberType>(convertType(e->getType()));
2307 const auto *fieldDecl = cast<FieldDecl>(decl);
2308 const auto *mpt = e->getType()->castAs<MemberPointerType>();
2309 const auto *destClass = mpt->getMostRecentCXXRecordDecl();
2310
2311 // Empty [[no_unique_address]] fields have no CIR field index; represent the
2312 // pointer-to-data-member by its concrete byte offset within the class.
2314 // This function should ONLY be accessed in reference to itself, I don't see
2315 // any cases/couldn't find any cases where anything else could get here, and
2316 // classic-codegen does the same.
2317 assert(fieldDecl->getParent() == destClass &&
2318 "scalar member pointer should be relative to the declaring class");
2319 uint64_t offset =
2320 astContext.toCharUnitsFromBits(astContext.getFieldOffset(fieldDecl))
2321 .getQuantity();
2322 return cir::ConstantOp::create(builder, loc,
2323 cir::DataMemberOffsetAttr::get(ty, offset));
2324 }
2325
2326 std::optional<llvm::SmallVector<int32_t>> path =
2327 buildMemberPath(destClass, fieldDecl);
2328 if (!path)
2329 return {};
2330 return cir::ConstantOp::create(builder, loc,
2331 builder.getDataMemberAttr(ty, *path));
2332}
2333
2334std::optional<llvm::SmallVector<int32_t>>
2336 const FieldDecl *field) {
2338 if (!findFieldMemberPath(destClass, field, path))
2339 return std::nullopt;
2340 return path;
2341}
2342
2343bool CIRGenModule::findFieldMemberPath(const CXXRecordDecl *currentClass,
2344 const FieldDecl *field,
2346 const CIRGenRecordLayout &layout =
2347 getTypes().getCIRGenRecordLayout(currentClass);
2348
2349 // The field is declared directly in this class.
2350 if (field->getParent() == currentClass) {
2351 int32_t fieldIdx;
2352 if (currentClass->isUnion()) {
2353 // For unions, getCIRFieldNo always returns 0 for every union member (all
2354 // members share offset 0 in the CIR record). Use the declaration-order
2355 // index to distinguish members with the same type at the same offset.
2356 if (!layout.isZeroInitializable()) {
2357 errorNYI(field->getLocation(),
2358 "data member pointer for non-zero-initializable union");
2359 return false;
2360 }
2361 fieldIdx = static_cast<int32_t>(field->getFieldIndex());
2362 } else {
2363 fieldIdx = static_cast<int32_t>(layout.getCIRFieldNo(field));
2364 }
2365 path.push_back(fieldIdx);
2366 return true;
2367 }
2368
2369 // Otherwise search the base subobjects. A virtual base only blocks lowering
2370 // when the field actually lives within it; a virtual base elsewhere in the
2371 // hierarchy must not stop us from reaching a member through a non-virtual
2372 // path.
2373 for (const CXXBaseSpecifier &base : currentClass->bases()) {
2374 const auto *baseDecl =
2375 cast<CXXRecordDecl>(base.getType()->getAsRecordDecl());
2376
2377 if (base.isVirtual()) {
2378 // A pointer to a data member that traverses a virtual base is ill-formed,
2379 // so this guard only fires defensively if the member is reached through
2380 // the virtual base. An unrelated virtual base is skipped so it does not
2381 // block members reached through a non-virtual path.
2382 llvm::SmallVector<int32_t> discardedPath;
2383 if (findFieldMemberPath(baseDecl, field, discardedPath)) {
2384 errorNYI(field->getLocation(),
2385 "data member pointer through virtual base");
2386 return false;
2387 }
2388 continue;
2389 }
2390
2391 // If a base class doesn't participate in layout, the field cannot be in it,
2392 // skip it.
2393 if (!layout.hasNonVirtualBaseCIRField(baseDecl))
2394 continue;
2395
2396 auto baseFieldIdx =
2397 static_cast<int32_t>(layout.getNonVirtualBaseCIRFieldNo(baseDecl));
2398 path.push_back(baseFieldIdx);
2399 if (findFieldMemberPath(baseDecl, field, path))
2400 return true;
2401 path.pop_back();
2402 }
2403 return false;
2404}
2405
2407 return isEmptyFieldForLayout(astContext, field) &&
2408 field->isPotentiallyOverlapping();
2409}
2410
2412 for (Decl *decl : dc->decls()) {
2413 // Unlike other DeclContexts, the contents of an ObjCImplDecl at TU scope
2414 // are themselves considered "top-level", so EmitTopLevelDecl on an
2415 // ObjCImplDecl does not recursively visit them. We need to do that in
2416 // case they're nested inside another construct (LinkageSpecDecl /
2417 // ExportDecl) that does stop them from being considered "top-level".
2418 if (auto *oid = dyn_cast<ObjCImplDecl>(decl))
2419 errorNYI(oid->getSourceRange(), "emitDeclConext: ObjCImplDecl");
2420
2422 }
2423}
2424
2425// Emit code for a single top level declaration.
2427
2428 // Ignore dependent declarations.
2429 if (decl->isTemplated())
2430 return;
2431
2432 switch (decl->getKind()) {
2433 default:
2434 errorNYI(decl->getBeginLoc(), "declaration of kind",
2435 decl->getDeclKindName());
2436 break;
2437
2438 case Decl::CXXConversion:
2439 case Decl::CXXMethod:
2440 case Decl::Function: {
2441 auto *fd = cast<FunctionDecl>(decl);
2442 // Consteval functions shouldn't be emitted.
2443 if (!fd->isConsteval())
2444 emitGlobal(fd);
2445 break;
2446 }
2447 case Decl::Export:
2449 break;
2450
2451 case Decl::Var:
2452 case Decl::Decomposition:
2453 case Decl::VarTemplateSpecialization: {
2455 if (auto *decomp = dyn_cast<DecompositionDecl>(decl))
2456 for (auto *binding : decomp->flat_bindings())
2457 if (auto *holdingVar = binding->getHoldingVar())
2458 emitGlobal(holdingVar);
2459 break;
2460 }
2461 case Decl::OpenACCRoutine:
2463 break;
2464 case Decl::OpenACCDeclare:
2466 break;
2467 case Decl::OMPThreadPrivate:
2469 break;
2470 case Decl::OMPGroupPrivate:
2472 break;
2473 case Decl::OMPAllocate:
2475 break;
2476 case Decl::OMPCapturedExpr:
2478 break;
2479 case Decl::OMPDeclareReduction:
2481 break;
2482 case Decl::OMPDeclareMapper:
2484 break;
2485 case Decl::OMPRequires:
2487 break;
2488 case Decl::Enum:
2489 case Decl::Using: // using X; [C++]
2490 case Decl::UsingDirective: // using namespace X; [C++]
2491 case Decl::UsingEnum: // using enum X; [C++]
2492 case Decl::NamespaceAlias:
2493 case Decl::Typedef:
2494 case Decl::TypeAlias: // using foo = bar; [C++11]
2495 case Decl::Record:
2497 break;
2498
2499 // No code generation needed.
2500 case Decl::ClassTemplate:
2501 case Decl::Concept:
2502 case Decl::CXXDeductionGuide:
2503 case Decl::Empty:
2504 case Decl::ExplicitInstantiation:
2505 case Decl::FunctionTemplate:
2506 case Decl::StaticAssert:
2507 case Decl::TypeAliasTemplate:
2508 case Decl::UsingShadow:
2509 case Decl::VarTemplate:
2510 case Decl::VarTemplatePartialSpecialization:
2511 break;
2512
2513 case Decl::CXXConstructor:
2515 break;
2516 case Decl::CXXDestructor:
2518 break;
2519
2520 // C++ Decls
2521 case Decl::LinkageSpec:
2522 case Decl::Namespace:
2524 break;
2525
2526 case Decl::ClassTemplateSpecialization:
2527 case Decl::CXXRecord: {
2530 for (auto *childDecl : crd->decls())
2532 emitTopLevelDecl(childDecl);
2533 break;
2534 }
2535
2536 case Decl::FileScopeAsm:
2537 // File-scope asm is ignored during device-side CUDA compilation.
2538 if (langOpts.CUDA && langOpts.CUDAIsDevice)
2539 break;
2540 // File-scope asm is ignored during device-side OpenMP compilation.
2541 if (langOpts.OpenMPIsTargetDevice)
2542 break;
2543 // File-scope asm is ignored during device-side SYCL compilation.
2544 if (langOpts.SYCLIsDevice)
2545 break;
2546 auto *file_asm = cast<FileScopeAsmDecl>(decl);
2547 std::string line = file_asm->getAsmString();
2548 globalScopeAsm.push_back(builder.getStringAttr(line));
2549 break;
2550 }
2551}
2552
2553void CIRGenModule::setInitializer(cir::GlobalOp &op, mlir::Attribute value) {
2554 // Recompute visibility when updating initializer.
2555 op.setInitialValueAttr(value);
2557}
2558
2559std::pair<cir::FuncType, cir::FuncOp> CIRGenModule::getAddrAndTypeOfCXXStructor(
2560 GlobalDecl gd, const CIRGenFunctionInfo *fnInfo, cir::FuncType fnType,
2561 bool dontDefer, ForDefinition_t isForDefinition) {
2562 auto *md = cast<CXXMethodDecl>(gd.getDecl());
2563
2564 if (isa<CXXDestructorDecl>(md)) {
2565 // Always alias equivalent complete destructors to base destructors in the
2566 // MS ABI.
2567 if (getTarget().getCXXABI().isMicrosoft() &&
2568 gd.getDtorType() == Dtor_Complete &&
2569 md->getParent()->getNumVBases() == 0)
2570 errorNYI(md->getSourceRange(),
2571 "getAddrAndTypeOfCXXStructor: MS ABI complete destructor");
2572 }
2573
2574 if (!fnType) {
2575 if (!fnInfo)
2577 fnType = getTypes().getFunctionType(*fnInfo);
2578 }
2579
2580 auto fn = getOrCreateCIRFunction(getMangledName(gd), fnType, gd,
2581 /*ForVtable=*/false, dontDefer,
2582 /*IsThunk=*/false, isForDefinition);
2583
2584 return {fnType, fn};
2585}
2586
2588 mlir::Type funcType, bool forVTable,
2589 bool dontDefer,
2590 ForDefinition_t isForDefinition) {
2591 assert(!cast<FunctionDecl>(gd.getDecl())->isConsteval() &&
2592 "consteval function should never be emitted");
2593
2594 if (!funcType) {
2595 const auto *fd = cast<FunctionDecl>(gd.getDecl());
2596 funcType = convertType(fd->getType());
2597 }
2598
2599 // Devirtualized destructor calls may come through here instead of via
2600 // getAddrOfCXXStructor. Make sure we use the MS ABI base destructor instead
2601 // of the complete destructor when necessary.
2602 if (const auto *dd = dyn_cast<CXXDestructorDecl>(gd.getDecl())) {
2603 if (getTarget().getCXXABI().isMicrosoft() &&
2604 gd.getDtorType() == Dtor_Complete &&
2605 dd->getParent()->getNumVBases() == 0)
2606 errorNYI(dd->getSourceRange(),
2607 "getAddrOfFunction: MS ABI complete destructor");
2608 }
2609
2610 StringRef mangledName = getMangledName(gd);
2611 cir::FuncOp func =
2612 getOrCreateCIRFunction(mangledName, funcType, gd, forVTable, dontDefer,
2613 /*isThunk=*/false, isForDefinition);
2614 // Returns kernel handle for HIP kernel stub function.
2615 if (langOpts.CUDA && !langOpts.CUDAIsDevice &&
2616 cast<FunctionDecl>(gd.getDecl())->hasAttr<CUDAGlobalAttr>()) {
2617 mlir::Operation *handle = getCUDARuntime().getKernelHandle(func, gd);
2618
2619 // For HIP the kernel handle is a GlobalOp, which cannot be cast to
2620 // FuncOp. Return the stub directly in that case.
2621 bool isHIPHandle = mlir::isa<cir::GlobalOp>(*handle);
2622 if (isForDefinition || isHIPHandle)
2623 return func;
2624 return mlir::dyn_cast<cir::FuncOp>(*handle);
2625 }
2626 return func;
2627}
2628
2629static std::string getMangledNameImpl(CIRGenModule &cgm, GlobalDecl gd,
2630 const NamedDecl *nd) {
2631 SmallString<256> buffer;
2632
2633 llvm::raw_svector_ostream out(buffer);
2635
2637
2638 if (mc.shouldMangleDeclName(nd)) {
2639 mc.mangleName(gd.getWithDecl(nd), out);
2640 } else {
2641 IdentifierInfo *ii = nd->getIdentifier();
2642 assert(ii && "Attempt to mangle unnamed decl.");
2643
2644 const auto *fd = dyn_cast<FunctionDecl>(nd);
2645 if (fd &&
2646 fd->getType()->castAs<FunctionType>()->getCallConv() == CC_X86RegCall) {
2647 cgm.errorNYI(nd->getSourceRange(), "getMangledName: X86RegCall");
2648 } else if (fd && fd->hasAttr<CUDAGlobalAttr>() &&
2650 out << "__device_stub__" << ii->getName();
2651 } else if (fd &&
2652 DeviceKernelAttr::isOpenCLSpelling(
2653 fd->getAttr<DeviceKernelAttr>()) &&
2655 cgm.errorNYI(nd->getSourceRange(), "getMangledName: OpenCL Stub");
2656 } else {
2657 out << ii->getName();
2658 }
2659 }
2660
2661 // Check if the module name hash should be appended for internal linkage
2662 // symbols. This should come before multi-version target suffixes are
2663 // appendded. This is to keep the name and module hash suffix of the internal
2664 // linkage function together. The unique suffix should only be added when name
2665 // mangling is done to make sure that the final name can be properly
2666 // demangled. For example, for C functions without prototypes, name mangling
2667 // is not done and the unique suffix should not be appended then.
2669
2670 if (const auto *fd = dyn_cast<FunctionDecl>(nd)) {
2671 if (fd->isMultiVersion()) {
2672 cgm.errorNYI(nd->getSourceRange(),
2673 "getMangledName: multi-version functions");
2674 }
2675 }
2676 if (cgm.getLangOpts().GPURelocatableDeviceCode) {
2677 cgm.errorNYI(nd->getSourceRange(),
2678 "getMangledName: GPU relocatable device code");
2679 }
2680
2681 return std::string(out.str());
2682}
2683
2684static FunctionDecl *
2686 const FunctionDecl *protoFunc) {
2687 // If this is a C no-prototype function, we can take the 'easy' way out and
2688 // just create a function with no arguments/functions, etc.
2689 if (!protoFunc->hasPrototype())
2690 return FunctionDecl::Create(
2691 ctx, /*DC=*/ctx.getTranslationUnitDecl(),
2692 /*StartLoc=*/SourceLocation{}, /*NLoc=*/SourceLocation{}, bindName,
2693 protoFunc->getType(), /*TInfo=*/nullptr, StorageClass::SC_None);
2694
2695 QualType funcTy = protoFunc->getType();
2696 auto *fpt = cast<FunctionProtoType>(protoFunc->getType());
2697
2698 // If this is a member function, add an explicit 'this' to the function type.
2699 if (auto *methodDecl = dyn_cast<CXXMethodDecl>(protoFunc);
2700 methodDecl && methodDecl->isImplicitObjectMemberFunction()) {
2701 llvm::SmallVector<QualType> paramTypes{fpt->getParamTypes()};
2702 paramTypes.insert(paramTypes.begin(), methodDecl->getThisType());
2703
2704 funcTy = ctx.getFunctionType(fpt->getReturnType(), paramTypes,
2705 fpt->getExtProtoInfo());
2706 fpt = cast<FunctionProtoType>(funcTy);
2707 }
2708
2709 auto *tempFunc =
2711 /*StartLoc=*/SourceLocation{},
2712 /*NLoc=*/SourceLocation{}, bindName, funcTy,
2713 /*TInfo=*/nullptr, StorageClass::SC_None);
2714
2716 params.reserve(fpt->getNumParams());
2717
2718 // Add all of the parameters.
2719 for (unsigned i = 0, e = fpt->getNumParams(); i != e; ++i) {
2721 ctx, tempFunc, /*StartLoc=*/SourceLocation{},
2722 /*IdLoc=*/SourceLocation{},
2723 /*Id=*/nullptr, fpt->getParamType(i), /*TInfo=*/nullptr,
2724 StorageClass::SC_None, /*DefArg=*/nullptr);
2725 parm->setScopeInfo(0, i);
2726 params.push_back(parm);
2727 }
2728
2729 tempFunc->setParams(params);
2730
2731 return tempFunc;
2732}
2733
2734std::string
2736 const FunctionDecl *attachedFunction) {
2738 getASTContext(), bindName, attachedFunction);
2739
2740 std::string ret = getMangledNameImpl(*this, GlobalDecl(tempFunc), tempFunc);
2741
2742 // This does nothing (it is a do-nothing function), since this is a
2743 // slab-allocator, but leave a call in to immediately destroy this in case we
2744 // ever come up with a way of getting allocations back.
2745 getASTContext().Deallocate(tempFunc);
2746 return ret;
2747}
2748
2750 GlobalDecl canonicalGd = gd.getCanonicalDecl();
2751
2752 // Some ABIs don't have constructor variants. Make sure that base and complete
2753 // constructors get mangled the same.
2754 if (const auto *cd = dyn_cast<CXXConstructorDecl>(canonicalGd.getDecl())) {
2755 if (!getTarget().getCXXABI().hasConstructorVariants()) {
2756 errorNYI(cd->getSourceRange(),
2757 "getMangledName: C++ constructor without variants");
2758 return cast<NamedDecl>(gd.getDecl())->getIdentifier()->getName();
2759 }
2760 }
2761
2762 // Keep the first result in the case of a mangling collision.
2763 const auto *nd = cast<NamedDecl>(gd.getDecl());
2764 std::string mangledName = getMangledNameImpl(*this, gd, nd);
2765
2766 auto result = manglings.insert(std::make_pair(mangledName, gd));
2767 return mangledDeclNames[canonicalGd] = result.first->first();
2768}
2769
2771 assert(!d->getInit() && "Cannot emit definite definitions here!");
2772
2773 StringRef mangledName = getMangledName(d);
2774 mlir::Operation *gv = getGlobalValue(mangledName);
2775
2776 // If we already have a definition, not declaration, with the same mangled
2777 // name, emitting of declaration is not required (and would actually overwrite
2778 // the emitted definition).
2779 if (gv && !mlir::cast<cir::GlobalOp>(gv).isDeclaration())
2780 return;
2781
2782 // If we have not seen a reference to this variable yet, place it into the
2783 // deferred declarations table to be emitted if needed later.
2784 if (!mustBeEmitted(d) && !gv) {
2785 deferredDecls[mangledName] = d;
2786 return;
2787 }
2788
2789 // The tentative definition is the only definition.
2791}
2792
2794 // Never defer when EmitAllDecls is specified.
2795 if (langOpts.EmitAllDecls)
2796 return true;
2797
2798 const auto *vd = dyn_cast<VarDecl>(global);
2799 if (vd &&
2800 ((codeGenOpts.KeepPersistentStorageVariables &&
2801 (vd->getStorageDuration() == SD_Static ||
2802 vd->getStorageDuration() == SD_Thread)) ||
2803 (codeGenOpts.KeepStaticConsts && vd->getStorageDuration() == SD_Static &&
2804 vd->getType().isConstQualified())))
2805 return true;
2806
2807 return getASTContext().DeclMustBeEmitted(global);
2808}
2809
2811 // In OpenMP 5.0 variables and function may be marked as
2812 // device_type(host/nohost) and we should not emit them eagerly unless we sure
2813 // that they must be emitted on the host/device. To be sure we need to have
2814 // seen a declare target with an explicit mentioning of the function, we know
2815 // we have if the level of the declare target attribute is -1. Note that we
2816 // check somewhere else if we should emit this at all.
2817 if (langOpts.OpenMP >= 50 && !langOpts.OpenMPSimd) {
2818 std::optional<OMPDeclareTargetDeclAttr *> activeAttr =
2819 OMPDeclareTargetDeclAttr::getActiveAttr(global);
2820 if (!activeAttr || (*activeAttr)->getLevel() != (unsigned)-1)
2821 return false;
2822 }
2823
2824 const auto *fd = dyn_cast<FunctionDecl>(global);
2825 if (fd) {
2826 // Implicit template instantiations may change linkage if they are later
2827 // explicitly instantiated, so they should not be emitted eagerly.
2828 if (fd->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
2829 return false;
2830 // Defer until all versions have been semantically checked.
2831 if (fd->hasAttr<TargetVersionAttr>() && !fd->isMultiVersion())
2832 return false;
2833 if (langOpts.SYCLIsDevice) {
2834 errorNYI(fd->getSourceRange(), "mayBeEmittedEagerly: SYCL");
2835 return false;
2836 }
2837 }
2838 const auto *vd = dyn_cast<VarDecl>(global);
2839 if (vd)
2840 if (astContext.getInlineVariableDefinitionKind(vd) ==
2842 // A definition of an inline constexpr static data member may change
2843 // linkage later if it's redeclared outside the class.
2844 return false;
2845
2846 // If OpenMP is enabled and threadprivates must be generated like TLS, delay
2847 // codegen for global variables, because they may be marked as threadprivate.
2848 if (langOpts.OpenMP && langOpts.OpenMPUseTLS &&
2849 astContext.getTargetInfo().isTLSSupported() && isa<VarDecl>(global) &&
2850 !global->getType().isConstantStorage(astContext, false, false) &&
2851 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(global))
2852 return false;
2853
2854 assert((fd || vd) &&
2855 "Only FunctionDecl and VarDecl should hit this path so far.");
2856 return true;
2857}
2858
2859static bool shouldAssumeDSOLocal(const CIRGenModule &cgm,
2860 cir::CIRGlobalValueInterface gv) {
2861 if (gv.hasLocalLinkage())
2862 return true;
2863
2864 if (!gv.hasDefaultVisibility() && !gv.hasExternalWeakLinkage())
2865 return true;
2866
2867 // DLLImport explicitly marks the GV as external.
2868 // so it shouldn't be dso_local
2869 // But we don't have the info set now
2871
2872 const llvm::Triple &tt = cgm.getTriple();
2873 const CodeGenOptions &cgOpts = cgm.getCodeGenOpts();
2874 if (tt.isOSCygMing()) {
2875 // In MinGW and Cygwin, variables without DLLImport can still be
2876 // automatically imported from a DLL by the linker; don't mark variables
2877 // that potentially could come from another DLL as DSO local.
2878
2879 // With EmulatedTLS, TLS variables can be autoimported from other DLLs
2880 // (and this actually happens in the public interface of libstdc++), so
2881 // such variables can't be marked as DSO local. (Native TLS variables
2882 // can't be dllimported at all, though.)
2883 cgm.errorNYI("shouldAssumeDSOLocal: MinGW");
2884 }
2885
2886 // On COFF, don't mark 'extern_weak' symbols as DSO local. If these symbols
2887 // remain unresolved in the link, they can be resolved to zero, which is
2888 // outside the current DSO.
2889 if (tt.isOSBinFormatCOFF() && gv.hasExternalWeakLinkage())
2890 return false;
2891
2892 // Every other GV is local on COFF.
2893 // Make an exception for windows OS in the triple: Some firmware builds use
2894 // *-win32-macho triples. This (accidentally?) produced windows relocations
2895 // without GOT tables in older clang versions; Keep this behaviour.
2896 // FIXME: even thread local variables?
2897 if (tt.isOSBinFormatCOFF() || (tt.isOSWindows() && tt.isOSBinFormatMachO()))
2898 return true;
2899
2900 // Only handle COFF and ELF for now.
2901 if (!tt.isOSBinFormatELF())
2902 return false;
2903
2904 llvm::Reloc::Model rm = cgOpts.RelocationModel;
2905 const LangOptions &lOpts = cgm.getLangOpts();
2906 if (rm != llvm::Reloc::Static && !lOpts.PIE) {
2907 // On ELF, if -fno-semantic-interposition is specified and the target
2908 // supports local aliases, there will be neither CC1
2909 // -fsemantic-interposition nor -fhalf-no-semantic-interposition. Set
2910 // dso_local on the function if using a local alias is preferable (can avoid
2911 // PLT indirection).
2912 if (!(isa<cir::FuncOp>(gv) && gv.canBenefitFromLocalAlias()))
2913 return false;
2914 return !(lOpts.SemanticInterposition || lOpts.HalfNoSemanticInterposition);
2915 }
2916
2917 // A definition cannot be preempted from an executable.
2918 if (!gv.isDeclarationForLinker())
2919 return true;
2920
2921 // Most PIC code sequences that assume that a symbol is local cannot produce a
2922 // 0 if it turns out the symbol is undefined. While this is ABI and relocation
2923 // depended, it seems worth it to handle it here.
2924 if (rm == llvm::Reloc::PIC_ && gv.hasExternalWeakLinkage())
2925 return false;
2926
2927 // PowerPC64 prefers TOC indirection to avoid copy relocations.
2928 if (tt.isPPC64())
2929 return false;
2930
2931 if (cgOpts.DirectAccessExternalData) {
2932 // If -fdirect-access-external-data (default for -fno-pic), set dso_local
2933 // for non-thread-local variables. If the symbol is not defined in the
2934 // executable, a copy relocation will be needed at link time. dso_local is
2935 // excluded for thread-local variables because they generally don't support
2936 // copy relocations.
2937 if (auto globalOp = dyn_cast<cir::GlobalOp>(gv.getOperation())) {
2938 // Assume variables are not thread-local until that support is added.
2940 return true;
2941 }
2942
2943 // -fno-pic sets dso_local on a function declaration to allow direct
2944 // accesses when taking its address (similar to a data symbol). If the
2945 // function is not defined in the executable, a canonical PLT entry will be
2946 // needed at link time. -fno-direct-access-external-data can avoid the
2947 // canonical PLT entry. We don't generalize this condition to -fpie/-fpic as
2948 // it could just cause trouble without providing perceptible benefits.
2949 if (isa<cir::FuncOp>(gv) && !cgOpts.NoPLT && rm == llvm::Reloc::Static)
2950 return true;
2951 }
2952
2953 // If we can use copy relocations we can assume it is local.
2954
2955 // Otherwise don't assume it is local.
2956
2957 return false;
2958}
2959
2960void CIRGenModule::setGlobalVisibility(cir::CIRGlobalValueInterface gv,
2961 const NamedDecl *d) const {
2962 // Internal definitions always have default visibility.
2963 if (gv.hasLocalLinkage()) {
2964 gv.setGlobalVisibility(cir::VisibilityKind::Default);
2965 return;
2966 }
2967 if (!d)
2968 return;
2969
2970 // Set visibility for definitions, and for declarations if requested globally
2971 // or set explicitly.
2973
2974 // OpenMP declare target variables must be visible to the host so they can
2975 // be registered. We require protected visibility unless the variable has
2976 // the DT_nohost modifier and does not need to be registered.
2977 if (getASTContext().getLangOpts().OpenMP &&
2978 getASTContext().getLangOpts().OpenMPIsTargetDevice && isa<VarDecl>(d) &&
2979 d->hasAttr<OMPDeclareTargetDeclAttr>() &&
2980 d->getAttr<OMPDeclareTargetDeclAttr>()->getDevType() !=
2981 OMPDeclareTargetDeclAttr::DT_NoHost &&
2983 llvm_unreachable("setGlobalVisibility: OpenMP is NYI");
2984 return;
2985 }
2986
2987 // CUDA/HIP device kernels and global variables must be visible to the host
2988 // so they can be registered / initialized. We require protected visibility
2989 // unless the user explicitly requested hidden via an attribute.
2990 if (getASTContext().getLangOpts().CUDAIsDevice &&
2992 !d->hasAttr<OMPDeclareTargetDeclAttr>()) {
2993 bool needsProtected = false;
2994 if (isa<FunctionDecl>(d)) {
2995 needsProtected =
2996 d->hasAttr<CUDAGlobalAttr>() || d->hasAttr<DeviceKernelAttr>();
2997 } else if (const auto *vd = dyn_cast<VarDecl>(d)) {
2998 needsProtected = vd->hasAttr<CUDADeviceAttr>() ||
2999 vd->hasAttr<CUDAConstantAttr>() ||
3000 vd->getType()->isCUDADeviceBuiltinSurfaceType() ||
3001 vd->getType()->isCUDADeviceBuiltinTextureType();
3002 }
3003 if (needsProtected) {
3004 gv.setGlobalVisibility(cir::VisibilityKind::Protected);
3005 return;
3006 }
3007 }
3008
3010 gv.setGlobalVisibility(cir::VisibilityKind::Hidden);
3011 return;
3012 }
3013
3015
3016 if (lv.isVisibilityExplicit() || getLangOpts().SetVisibilityForExternDecls ||
3017 !gv.isDeclarationForLinker())
3018 gv.setGlobalVisibility(getCIRVisibilityKind(lv.getVisibility()));
3019}
3020
3021void CIRGenModule::setDSOLocal(cir::CIRGlobalValueInterface gv) const {
3022 gv.setDSOLocal(shouldAssumeDSOLocal(*this, gv));
3023}
3024
3025void CIRGenModule::setDSOLocal(mlir::Operation *op) const {
3026 if (auto globalValue = dyn_cast<cir::CIRGlobalValueInterface>(op))
3027 setDSOLocal(globalValue);
3028}
3029
3030void CIRGenModule::setGVProperties(mlir::Operation *op,
3031 const NamedDecl *d) const {
3033 setGVPropertiesAux(op, d);
3034}
3035
3036void CIRGenModule::setGVPropertiesAux(mlir::Operation *op,
3037 const NamedDecl *d) const {
3039 setDSOLocal(op);
3041}
3042
3044 GlobalDecl &result) const {
3045 auto res = manglings.find(mangledName);
3046 if (res == manglings.end())
3047 return false;
3048 result = res->getValue();
3049 return true;
3050}
3051
3053 switch (getCodeGenOpts().getDefaultTLSModel()) {
3055 return cir::TLS_Model::GeneralDynamic;
3057 return cir::TLS_Model::LocalDynamic;
3059 return cir::TLS_Model::InitialExec;
3061 return cir::TLS_Model::LocalExec;
3062 }
3063 llvm_unreachable("Invalid TLS model!");
3064}
3065
3066void CIRGenModule::setTLSMode(mlir::Operation *op, const VarDecl &d,
3067 bool isExtendingDecl) {
3068 assert(d.getTLSKind() && "setting TLS mode on non-TLS var!");
3069
3070 cir::TLS_Model tlm = getDefaultCIRTLSModel();
3071
3072 // Override the TLS model if it is explicitly specified.
3073 if (d.getAttr<TLSModelAttr>())
3074 errorNYI(d.getSourceRange(), "TLS model attribute");
3075
3076 auto global = cast<cir::GlobalOp>(op);
3077 global.setTlsModel(tlm);
3078
3079 // For namespace-scope dyanmic TLS we need to set the wrapper, int, or guard
3080 // info.
3081 if (d.isStaticLocal() || tlm != cir::TLS_Model::GeneralDynamic)
3082 return;
3083
3084 // If this function was called to set the TLS mode for a temporary whose
3085 // lifetime is extended by the variable declared by `d`, don't emit the
3086 // wrapper, init, and guard info.
3087 if (isExtendingDecl)
3088 return;
3089
3090 setGlobalTlsReferences(d, global);
3091}
3092
3094 const CIRGenFunctionInfo &info,
3095 cir::FuncOp func, bool isThunk) {
3096 // TODO(cir): More logic of constructAttributeList is needed.
3097 cir::CallingConv callingConv;
3098 cir::SideEffect sideEffect;
3099
3100 // TODO(cir): The current list should be initialized with the extra function
3101 // attributes, but we don't have those yet. For now, the PAL is initialized
3102 // with nothing.
3104 // Initialize PAL with existing attributes to merge attributes.
3105 mlir::NamedAttrList pal{};
3106 std::vector<mlir::NamedAttrList> argAttrs(info.arguments().size());
3107 mlir::NamedAttrList retAttrs{};
3108 constructAttributeList(func.getName(), info, globalDecl, pal, argAttrs,
3109 retAttrs, callingConv, sideEffect,
3110 /*attrOnCallSite=*/false, isThunk);
3111
3112 for (mlir::NamedAttribute attr : pal)
3113 func->setAttr(attr.getName(), attr.getValue());
3114
3115 llvm::for_each(llvm::enumerate(argAttrs), [func](auto idx_arg_pair) {
3116 mlir::function_interface_impl::setArgAttrs(func, idx_arg_pair.index(),
3117 idx_arg_pair.value());
3118 });
3119 if (!retAttrs.empty())
3120 mlir::function_interface_impl::setResultAttrs(func, 0, retAttrs);
3121
3122 // TODO(cir): Check X86_VectorCall incompatibility wiht WinARM64EC
3123
3124 // TODO(cir): Set the calling convention computed by constructAttributeList
3125 // on the function. FuncOp supports calling_conv, but target-specific
3126 // CodeGen is needed to set it correctly (e.g., AMDGPU kernel functions
3127 // should be marked with AMDGPUKernel).
3129}
3130
3132 cir::FuncOp func,
3133 bool isIncompleteFunction,
3134 bool isThunk) {
3135 // NOTE(cir): Original CodeGen checks if this is an intrinsic. In CIR we
3136 // represent them in dedicated ops. The correct attributes are ensured during
3137 // translation to LLVM. Thus, we don't need to check for them here.
3138
3139 const auto *funcDecl = cast<FunctionDecl>(globalDecl.getDecl());
3140
3141 if (!isIncompleteFunction)
3142 setCIRFunctionAttributes(globalDecl,
3143 getTypes().arrangeGlobalDeclaration(globalDecl),
3144 func, isThunk);
3145
3146 if (!isIncompleteFunction && func.isDeclaration())
3147 getTargetCIRGenInfo().setTargetAttributes(funcDecl, func, *this);
3148
3149 // Mirrors setLinkageForGV in CodeGenModule::SetFunctionAttributes.
3150 setLinkageForFunction(*this, func, funcDecl);
3151
3152 // If we plan on emitting this inline builtin, we can't treat it as a builtin.
3153 if (funcDecl->isInlineBuiltinDeclaration()) {
3154 const FunctionDecl *fdBody;
3155 bool hasBody = funcDecl->hasBody(fdBody);
3156 (void)hasBody;
3157 assert(hasBody && "Inline builtin declarations should always have an "
3158 "available body!");
3160 }
3161
3162 if (funcDecl->isReplaceableGlobalAllocationFunction()) {
3163 // A replaceable global allocation function does not act like a builtin by
3164 // default, only if it is invoked by a new-expression or delete-expression.
3165 func->setAttr(cir::CIRDialect::getNoBuiltinAttrName(),
3166 mlir::UnitAttr::get(&getMLIRContext()));
3167 }
3168}
3169
3170/// Determines whether the language options require us to model
3171/// unwind exceptions. We treat -fexceptions as mandating this
3172/// except under the fragile ObjC ABI with only ObjC exceptions
3173/// enabled. This means, for example, that C with -fexceptions
3174/// enables this.
3175static bool hasUnwindExceptions(const LangOptions &langOpts) {
3176 // If exceptions are completely disabled, obviously this is false.
3177 if (!langOpts.Exceptions)
3178 return false;
3179 // If C++ exceptions are enabled, this is true.
3180 if (langOpts.CXXExceptions)
3181 return true;
3182 // If ObjC exceptions are enabled, this depends on the ABI.
3183 if (langOpts.ObjCExceptions)
3184 return langOpts.ObjCRuntime.hasUnwindExceptions();
3185 return true;
3186}
3187
3189 const clang::FunctionDecl *decl, cir::FuncOp f) {
3192
3193 if (!hasUnwindExceptions(langOpts))
3194 f->setAttr(cir::CIRDialect::getNoThrowAttrName(),
3195 mlir::UnitAttr::get(&getMLIRContext()));
3196
3197 std::optional<cir::InlineKind> existingInlineKind = f.getInlineKind();
3198 bool isNoInline =
3199 existingInlineKind && *existingInlineKind == cir::InlineKind::NoInline;
3200 bool isAlwaysInline = existingInlineKind &&
3201 *existingInlineKind == cir::InlineKind::AlwaysInline;
3202 if (!decl) {
3203 assert(!cir::MissingFeatures::hlsl());
3204
3205 if (!isAlwaysInline &&
3206 codeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) {
3207 // If inlining is disabled and we don't have a declaration to control
3208 // inlining, mark the function as 'noinline' unless it is explicitly
3209 // marked as 'alwaysinline'.
3210 f.setInlineKind(cir::InlineKind::NoInline);
3211 }
3212
3213 return;
3214 }
3215
3222 assert(!cir::MissingFeatures::hlsl());
3223
3224 // Handle inline attributes
3225 if (decl->hasAttr<NoInlineAttr>() && !isAlwaysInline) {
3226 // Add noinline if the function isn't always_inline.
3227 f.setInlineKind(cir::InlineKind::NoInline);
3228 } else if (decl->hasAttr<AlwaysInlineAttr>() && !isNoInline) {
3229 // Don't override AlwaysInline with NoInline, or vice versa, since we can't
3230 // specify both in IR.
3231 f.setInlineKind(cir::InlineKind::AlwaysInline);
3232 } else if (codeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) {
3233 // If inlining is disabled, force everything that isn't always_inline
3234 // to carry an explicit noinline attribute.
3235 if (!isAlwaysInline)
3236 f.setInlineKind(cir::InlineKind::NoInline);
3237 } else {
3238 // Otherwise, propagate the inline hint attribute and potentially use its
3239 // absence to mark things as noinline.
3240 // Search function and template pattern redeclarations for inline.
3241 if (auto *fd = dyn_cast<FunctionDecl>(decl)) {
3242 // TODO: Share this checkForInline implementation with classic codegen.
3243 // This logic is likely to change over time, so sharing would help ensure
3244 // consistency.
3245 auto checkForInline = [](const FunctionDecl *decl) {
3246 auto checkRedeclForInline = [](const FunctionDecl *redecl) {
3247 return redecl->isInlineSpecified();
3248 };
3249 if (any_of(decl->redecls(), checkRedeclForInline))
3250 return true;
3251 const FunctionDecl *pattern = decl->getTemplateInstantiationPattern();
3252 if (!pattern)
3253 return false;
3254 return any_of(pattern->redecls(), checkRedeclForInline);
3255 };
3256 if (checkForInline(fd)) {
3257 f.setInlineKind(cir::InlineKind::InlineHint);
3258 } else if (codeGenOpts.getInlining() ==
3260 !fd->isInlined() && !isAlwaysInline) {
3261 f.setInlineKind(cir::InlineKind::NoInline);
3262 }
3263 }
3264 }
3265
3267}
3268
3270 StringRef mangledName, mlir::Type funcType, GlobalDecl gd, bool forVTable,
3271 bool dontDefer, bool isThunk, ForDefinition_t isForDefinition,
3272 mlir::NamedAttrList extraAttrs) {
3273 const Decl *d = gd.getDecl();
3274
3275 if (const auto *fd = cast_or_null<FunctionDecl>(d)) {
3276 // For the device, mark the function as one that should be emitted.
3277 if (getLangOpts().OpenMPIsTargetDevice && openMPRuntime &&
3278 !getOpenMPRuntime().markAsGlobalTarget(gd) && fd->isDefined() &&
3279 !dontDefer && !isForDefinition) {
3280 if (const FunctionDecl *fdDef = fd->getDefinition()) {
3281 GlobalDecl gdDef;
3282 if (const auto *cd = dyn_cast<CXXConstructorDecl>(fdDef))
3283 gdDef = GlobalDecl(cd, gd.getCtorType());
3284 else if (const auto *dd = dyn_cast<CXXDestructorDecl>(fdDef))
3285 gdDef = GlobalDecl(dd, gd.getDtorType());
3286 else
3287 gdDef = GlobalDecl(fdDef);
3288 emitGlobal(gdDef);
3289 }
3290 }
3291
3292 // Any attempts to use a MultiVersion function should result in retrieving
3293 // the iFunc instead. Name mangling will handle the rest of the changes.
3294 if (fd->isMultiVersion())
3295 errorNYI(fd->getSourceRange(), "getOrCreateCIRFunction: multi-version");
3296 }
3297
3298 // Lookup the entry, lazily creating it if necessary.
3299 mlir::Operation *entry = getGlobalValue(mangledName);
3300 if (entry) {
3301 assert(mlir::isa<cir::FuncOp>(entry));
3302
3304
3305 // Handle dropped DLL attributes.
3306 if (d && !d->hasAttr<DLLImportAttr>() && !d->hasAttr<DLLExportAttr>()) {
3308 setDSOLocal(entry);
3309 }
3310
3311 // If there are two attempts to define the same mangled name, issue an
3312 // error.
3313 auto fn = cast<cir::FuncOp>(entry);
3314 if (isForDefinition && fn && !fn.isDeclaration()) {
3315 GlobalDecl otherGd;
3316 // Check that GD is not yet in DiagnosedConflictingDefinitions is required
3317 // to make sure that we issue an error only once.
3318 if (lookupRepresentativeDecl(mangledName, otherGd) &&
3319 (gd.getCanonicalDecl().getDecl() !=
3320 otherGd.getCanonicalDecl().getDecl()) &&
3321 diagnosedConflictingDefinitions.insert(gd).second) {
3322 getDiags().Report(d->getLocation(), diag::err_duplicate_mangled_name)
3323 << mangledName;
3324 getDiags().Report(otherGd.getDecl()->getLocation(),
3325 diag::note_previous_definition);
3326 }
3327 }
3328
3329 if (fn && fn.getFunctionType() == funcType) {
3330 return fn;
3331 }
3332
3333 if (!isForDefinition) {
3334 return fn;
3335 }
3336
3337 // TODO(cir): classic codegen checks here if this is a llvm::GlobalAlias.
3338 // How will we support this?
3339 }
3340
3341 auto *funcDecl = llvm::cast_or_null<FunctionDecl>(gd.getDecl());
3342 bool invalidLoc = !funcDecl ||
3343 funcDecl->getSourceRange().getBegin().isInvalid() ||
3344 funcDecl->getSourceRange().getEnd().isInvalid();
3345 cir::FuncOp funcOp = createCIRFunction(
3346 invalidLoc ? theModule->getLoc() : getLoc(funcDecl->getSourceRange()),
3347 mangledName, mlir::cast<cir::FuncType>(funcType), funcDecl);
3348
3349 if (funcDecl && funcDecl->hasAttr<AnnotateAttr>())
3350 deferredAnnotations[mangledName] = funcDecl;
3351
3352 // If we already created a function with the same mangled name (but different
3353 // type) before, take its name and add it to the list of functions to be
3354 // replaced with F at the end of CodeGen.
3355 //
3356 // This happens if there is a prototype for a function (e.g. "int f()") and
3357 // then a definition of a different type (e.g. "int f(int x)").
3358 if (entry) {
3359
3360 // Fetch a generic symbol-defining operation and its uses.
3361 auto symbolOp = mlir::cast<mlir::SymbolOpInterface>(entry);
3362
3363 // This might be an implementation of a function without a prototype, in
3364 // which case, try to do special replacement of calls which match the new
3365 // prototype. The really key thing here is that we also potentially drop
3366 // arguments from the call site so as to make a direct call, which makes the
3367 // inliner happier and suppresses a number of optimizer warnings (!) about
3368 // dropping arguments.
3369 if (symbolOp.getSymbolUses(symbolOp->getParentOp()))
3371
3372 // Obliterate no-proto declaration.
3373 eraseGlobalSymbol(entry);
3374 entry->erase();
3375 }
3376
3377 if (d)
3378 setFunctionAttributes(gd, funcOp, /*isIncompleteFunction=*/false, isThunk);
3379 if (!extraAttrs.empty()) {
3380 extraAttrs.append(funcOp->getAttrs());
3381 funcOp->setAttrs(extraAttrs);
3382 }
3383
3384 // 'dontDefer' actually means don't move this to the deferredDeclsToEmit list.
3385 if (dontDefer) {
3386 // TODO(cir): This assertion will need an additional condition when we
3387 // support incomplete functions.
3388 assert(funcOp.getFunctionType() == funcType);
3389 return funcOp;
3390 }
3391
3392 // All MSVC dtors other than the base dtor are linkonce_odr and delegate to
3393 // each other bottoming out wiht the base dtor. Therefore we emit non-base
3394 // dtors on usage, even if there is no dtor definition in the TU.
3395 if (isa_and_nonnull<CXXDestructorDecl>(d) &&
3396 getCXXABI().useThunkForDtorVariant(cast<CXXDestructorDecl>(d),
3397 gd.getDtorType()))
3398 errorNYI(d->getSourceRange(), "getOrCreateCIRFunction: dtor");
3399
3400 // This is the first use or definition of a mangled name. If there is a
3401 // deferred decl with this name, remember that we need to emit it at the end
3402 // of the file.
3403 auto ddi = deferredDecls.find(mangledName);
3404 if (ddi != deferredDecls.end()) {
3405 // Move the potentially referenced deferred decl to the
3406 // DeferredDeclsToEmit list, and remove it from DeferredDecls (since we
3407 // don't need it anymore).
3408 addDeferredDeclToEmit(ddi->second);
3409 deferredDecls.erase(ddi);
3410
3411 // Otherwise, there are cases we have to worry about where we're using a
3412 // declaration for which we must emit a definition but where we might not
3413 // find a top-level definition.
3414 // - member functions defined inline in their classes
3415 // - friend functions defined inline in some class
3416 // - special member functions with implicit definitions
3417 // If we ever change our AST traversal to walk into class methods, this
3418 // will be unnecessary.
3419 //
3420 // We also don't emit a definition for a function if it's going to be an
3421 // entry in a vtable, unless it's already marked as used.
3422 } else if (getLangOpts().CPlusPlus && d) {
3423 // Look for a declaration that's lexically in a record.
3424 for (const auto *fd = cast<FunctionDecl>(d)->getMostRecentDecl(); fd;
3425 fd = fd->getPreviousDecl()) {
3426 if (isa<CXXRecordDecl>(fd->getLexicalDeclContext())) {
3427 if (fd->doesThisDeclarationHaveABody()) {
3429 break;
3430 }
3431 }
3432 }
3433 }
3434
3435 return funcOp;
3436}
3437
3438cir::FuncOp
3439CIRGenModule::createCIRFunction(mlir::Location loc, StringRef name,
3440 cir::FuncType funcType,
3441 const clang::FunctionDecl *funcDecl) {
3442 cir::FuncOp func;
3443 {
3444 mlir::OpBuilder::InsertionGuard guard(builder);
3445
3446 // Some global emissions are triggered while emitting a function, e.g.
3447 // void s() { x.method() }
3448 //
3449 // Be sure to insert a new function before a current one.
3450 CIRGenFunction *cgf = this->curCGF;
3451 if (cgf)
3452 builder.setInsertionPoint(cgf->curFn);
3453
3454 func = cir::FuncOp::create(builder, loc, name, funcType);
3455
3456 symbolLookupCache[func.getSymNameAttr()] = func;
3457
3459
3460 if (funcDecl && !funcDecl->hasPrototype())
3461 func.setNoProto(true);
3462
3463 assert(func.isDeclaration() && "expected empty body");
3464
3465 // A declaration gets private visibility by default, but external linkage
3466 // as the default linkage.
3467 func.setLinkageAttr(cir::GlobalLinkageKindAttr::get(
3468 &getMLIRContext(), cir::GlobalLinkageKind::ExternalLinkage));
3469 mlir::SymbolTable::setSymbolVisibility(
3470 func, mlir::SymbolTable::Visibility::Private);
3471
3473
3474 // Record the func_info tag, a C++ special member form or a known standard
3475 // library entity.
3476 setFuncInfoAttr(func, funcDecl);
3477
3478 if (!cgf)
3479 theModule.push_back(func);
3480
3481 if (this->getLangOpts().OpenACC) {
3482 // We only have to handle this attribute, since OpenACCAnnotAttrs are
3483 // handled via the end-of-TU work.
3484 for (const auto *attr :
3485 funcDecl->specific_attrs<OpenACCRoutineDeclAttr>())
3486 emitOpenACCRoutineDecl(funcDecl, func, attr->getLocation(),
3487 attr->Clauses);
3488 }
3489 }
3490 return func;
3491}
3492
3493cir::FuncOp
3494CIRGenModule::createCIRBuiltinFunction(mlir::Location loc, StringRef name,
3495 cir::FuncType ty,
3496 const clang::FunctionDecl *fd) {
3497 cir::FuncOp fnOp = createCIRFunction(loc, name, ty, fd);
3498 fnOp.setBuiltin(true);
3499 return fnOp;
3500}
3501
3502static cir::CtorKind getCtorKindFromDecl(const CXXConstructorDecl *ctor) {
3503 if (ctor->isDefaultConstructor())
3504 return cir::CtorKind::Default;
3505 if (ctor->isCopyConstructor())
3506 return cir::CtorKind::Copy;
3507 if (ctor->isMoveConstructor())
3508 return cir::CtorKind::Move;
3509 return cir::CtorKind::Custom;
3510}
3511
3512static cir::AssignKind getAssignKindFromDecl(const CXXMethodDecl *method) {
3513 if (method->isCopyAssignmentOperator())
3514 return cir::AssignKind::Copy;
3515 if (method->isMoveAssignmentOperator())
3516 return cir::AssignKind::Move;
3517 llvm_unreachable("not a copy or move assignment operator");
3518}
3519
3520void CIRGenModule::setFuncInfoAttr(cir::FuncOp funcOp,
3521 const clang::FunctionDecl *funcDecl) {
3522 if (!funcDecl)
3523 return;
3524
3525 if (const auto *dtor = dyn_cast<CXXDestructorDecl>(funcDecl)) {
3526 auto cxxDtor = cir::CXXDtorAttr::get(
3527 convertType(getASTContext().getCanonicalTagType(dtor->getParent())),
3528 dtor->isTrivial());
3529 funcOp.setFuncInfoAttr(cxxDtor);
3530 return;
3531 }
3532
3533 if (const auto *ctor = dyn_cast<CXXConstructorDecl>(funcDecl)) {
3534 cir::CtorKind kind = getCtorKindFromDecl(ctor);
3535 auto cxxCtor = cir::CXXCtorAttr::get(
3536 convertType(getASTContext().getCanonicalTagType(ctor->getParent())),
3537 kind, ctor->isTrivial());
3538 funcOp.setFuncInfoAttr(cxxCtor);
3539 return;
3540 }
3541
3542 const auto *method = dyn_cast<CXXMethodDecl>(funcDecl);
3543 if (method && (method->isCopyAssignmentOperator() ||
3544 method->isMoveAssignmentOperator())) {
3545 cir::AssignKind assignKind = getAssignKindFromDecl(method);
3546 auto cxxAssign = cir::CXXAssignAttr::get(
3547 convertType(getASTContext().getCanonicalTagType(method->getParent())),
3548 assignKind, method->isTrivial());
3549 funcOp.setFuncInfoAttr(cxxAssign);
3550 return;
3551 }
3552
3553 // Otherwise tag a function that matches a known standard library entity. A
3554 // known entity is named by a plain identifier in std. For a member the
3555 // record decides std membership. Inline namespaces, like the versioning
3556 // namespace of libc++, count as part of std.
3557 if (!funcDecl->getIdentifier())
3558 return;
3559 bool inStdNamespace = method ? method->getParent()->isInStdNamespace()
3560 : funcDecl->isInStdNamespace();
3561 if (!inStdNamespace)
3562 return;
3563
3564 // The names and the tags come from CIRStdOps.td, and the recognizer checks
3565 // the shape of each call. Only free functions name a known entity today, so
3566 // a member like char_traits::find never shares the tag of the free std::find.
3567 std::optional<cir::KnownFuncKind> kind;
3568 if (!method) {
3569 kind = llvm::StringSwitch<std::optional<cir::KnownFuncKind>>(
3570 funcDecl->getName())
3571 .Case(cir::StdFindOp::getFunctionName(),
3572 cir::StdFindOp::getFuncKind())
3573 .Default(std::nullopt);
3574 }
3575 if (!kind)
3576 return;
3577
3578 funcOp.setFuncInfoAttr(cir::FuncIdentityAttr::get(&getMLIRContext(), *kind));
3579}
3580
3581static void setWindowsItaniumDLLImport(CIRGenModule &cgm, bool isLocal,
3582 cir::FuncOp funcOp, StringRef name) {
3583 // In Windows Itanium environments, try to mark runtime functions
3584 // dllimport. For Mingw and MSVC, don't. We don't really know if the user
3585 // will link their standard library statically or dynamically. Marking
3586 // functions imported when they are not imported can cause linker errors
3587 // and warnings.
3588 if (!isLocal && cgm.getTarget().getTriple().isWindowsItaniumEnvironment() &&
3589 !cgm.getCodeGenOpts().LTOVisibilityPublicStd) {
3593 }
3594}
3595
3596cir::FuncOp CIRGenModule::createRuntimeFunction(cir::FuncType ty,
3597 StringRef name,
3598 mlir::NamedAttrList extraAttrs,
3599 bool isLocal,
3600 bool assumeConvergent) {
3601 if (assumeConvergent)
3602 errorNYI("createRuntimeFunction: assumeConvergent");
3603
3604 cir::FuncOp entry = getOrCreateCIRFunction(name, ty, GlobalDecl(),
3605 /*forVtable=*/false, extraAttrs);
3606
3607 if (entry) {
3608 // TODO(cir): set the attributes of the function.
3611 setWindowsItaniumDLLImport(*this, isLocal, entry, name);
3612 entry.setDSOLocal(true);
3613 }
3614
3615 return entry;
3616}
3617
3618mlir::SymbolTable::Visibility
3620 // MLIR doesn't accept public symbols declarations (only
3621 // definitions).
3622 if (op.isDeclaration())
3623 return mlir::SymbolTable::Visibility::Private;
3624 return getMLIRVisibilityFromCIRLinkage(op.getLinkage());
3625}
3626
3627mlir::SymbolTable::Visibility
3629 switch (glk) {
3630 case cir::GlobalLinkageKind::InternalLinkage:
3631 case cir::GlobalLinkageKind::PrivateLinkage:
3632 return mlir::SymbolTable::Visibility::Private;
3633 case cir::GlobalLinkageKind::ExternalLinkage:
3634 case cir::GlobalLinkageKind::ExternalWeakLinkage:
3635 case cir::GlobalLinkageKind::LinkOnceODRLinkage:
3636 case cir::GlobalLinkageKind::AvailableExternallyLinkage:
3637 case cir::GlobalLinkageKind::CommonLinkage:
3638 case cir::GlobalLinkageKind::WeakAnyLinkage:
3639 case cir::GlobalLinkageKind::WeakODRLinkage:
3640 return mlir::SymbolTable::Visibility::Public;
3641 default: {
3642 llvm::errs() << "visibility not implemented for '"
3643 << stringifyGlobalLinkageKind(glk) << "'\n";
3644 assert(0 && "not implemented");
3645 }
3646 }
3647 llvm_unreachable("linkage should be handled above!");
3648}
3649
3651 clang::VisibilityAttr::VisibilityType visibility) {
3652 switch (visibility) {
3653 case clang::VisibilityAttr::VisibilityType::Default:
3654 return cir::VisibilityKind::Default;
3655 case clang::VisibilityAttr::VisibilityType::Hidden:
3656 return cir::VisibilityKind::Hidden;
3657 case clang::VisibilityAttr::VisibilityType::Protected:
3658 return cir::VisibilityKind::Protected;
3659 }
3660 llvm_unreachable("unexpected visibility value");
3661}
3662
3663cir::VisibilityAttr
3665 const clang::VisibilityAttr *va = decl->getAttr<clang::VisibilityAttr>();
3666 cir::VisibilityAttr cirVisibility =
3667 cir::VisibilityAttr::get(&getMLIRContext());
3668 if (va) {
3669 cirVisibility = cir::VisibilityAttr::get(
3670 &getMLIRContext(),
3671 getGlobalVisibilityKindFromClangVisibility(va->getVisibility()));
3672 }
3673 return cirVisibility;
3674}
3675
3677 emitDeferred();
3679 applyReplacements();
3680
3681 theModule->setAttr(cir::CIRDialect::getModuleLevelAsmAttrName(),
3682 builder.getArrayAttr(globalScopeAsm));
3683
3684 emitGlobalAnnotations();
3685
3686 if (!recordLayoutEntries.empty())
3687 theModule->setAttr(
3688 cir::CIRDialect::getRecordLayoutsAttrName(),
3689 mlir::DictionaryAttr::get(&getMLIRContext(), recordLayoutEntries));
3690
3691 if (getTriple().isAMDGPU() ||
3692 (getTriple().isSPIRV() && getTriple().getVendor() == llvm::Triple::AMD))
3694
3695 if (getLangOpts().HIP) {
3696 // Emit a unique ID so that host and device binaries from the same
3697 // compilation unit can be associated.
3698 std::string cuidName =
3699 ("__hip_cuid_" + getASTContext().getCUIDHash()).str();
3700 auto int8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/false);
3701 auto loc = builder.getUnknownLoc();
3702 mlir::ptr::MemorySpaceAttrInterface addrSpace =
3703 cir::LangAddressSpaceAttr::get(&getMLIRContext(),
3704 getGlobalVarAddressSpace(nullptr));
3705
3706 auto gv = createGlobalOp(loc, cuidName, int8Ty,
3707 /*isConstant=*/false, addrSpace);
3708 gv.setLinkage(cir::GlobalLinkageKind::ExternalLinkage);
3709 // Initialize with zero
3710 auto zeroAttr = cir::IntAttr::get(int8Ty, 0);
3711 gv.setInitialValueAttr(zeroAttr);
3712 // External linkage requires public visibility
3713 mlir::SymbolTable::setSymbolVisibility(
3714 gv, mlir::SymbolTable::Visibility::Public);
3715
3717 }
3718
3719 if (astContext.getLangOpts().CUDA && cudaRuntime)
3721
3722 emitLLVMUsed();
3723
3724 // Classic codegen calls `checkAliases` here to validate any alias
3725 // definitions emitted during codegen.
3727
3728 // There's a lot of code that is not implemented yet.
3730}
3731
3733 const auto *d = cast<ValueDecl>(gd.getDecl());
3734 const AliasAttr *aa = d->getAttr<AliasAttr>();
3735 assert(aa && "Not an alias?");
3736
3737 StringRef mangledName = getMangledName(gd);
3738
3739 if (aa->getAliasee() == mangledName) {
3740 diags.Report(aa->getLocation(), diag::err_cyclic_alias) << 0;
3741 return;
3742 }
3743
3744 // If there is a definition in the module, then it wins over the alias.
3745 // This is dubious, but allow it to be safe. Just ignore the alias.
3746 mlir::Operation *entry = getGlobalValue(mangledName);
3747 if (entry) {
3748 auto entryGV = mlir::dyn_cast<cir::CIRGlobalValueInterface>(entry);
3749 if (entryGV && entryGV.isDefinition())
3750 return;
3751 }
3752
3753 // Classic codegen pushes the alias onto an `Aliases` list at this point so
3754 // that `checkAliases` can later validate the alias and recover on error.
3756
3757 mlir::Location loc = getLoc(d->getSourceRange());
3758 bool isFunction = isa<FunctionDecl>(d);
3759
3760 // Get the linkage and the type of the alias.
3761 mlir::Type declTy;
3762 cir::GlobalLinkageKind linkage;
3763 if (isFunction) {
3764 declTy = getTypes().getFunctionType(gd);
3765 linkage = getFunctionLinkage(gd);
3766 } else {
3767 declTy = getTypes().convertTypeForMem(d->getType());
3768 const auto *vd = cast<VarDecl>(d);
3769 linkage = getCIRLinkageVarDefinition(vd);
3770 }
3771
3772 // Aliases that target weak symbols must themselves be marked weak.
3773 if (d->hasAttr<WeakAttr>() || d->hasAttr<WeakRefAttr>() ||
3774 d->isWeakImported())
3775 linkage = cir::GlobalLinkageKind::WeakAnyLinkage;
3776
3777 // Create the alias op. If there is an existing declaration with the same
3778 // name, erase it: any references to it via flat symbol reference will
3779 // automatically resolve to the new alias.
3780 if (entry) {
3781 eraseGlobalSymbol(entry);
3782 entry->erase();
3783 }
3784
3785 // Aliases are always definitions, so the MLIR visibility should match the
3786 // linkage rather than defaulting to private.
3787 mlir::SymbolTable::Visibility visibility =
3789
3790 // TODO(cir): Make GlobalAlias a separate op.
3791 cir::CIRGlobalValueInterface alias =
3792 isFunction ? mlir::cast<cir::CIRGlobalValueInterface>(
3793 createCIRFunction(loc, mangledName,
3794 mlir::cast<cir::FuncType>(declTy),
3796 .getOperation())
3797 : mlir::cast<cir::CIRGlobalValueInterface>(
3798 createGlobalOp(loc, mangledName, declTy).getOperation());
3799 alias.setAliasee(aa->getAliasee());
3800 alias.setLinkage(linkage);
3801 mlir::SymbolTable::setSymbolVisibility(alias, visibility);
3803 setCommonAttributes(gd, alias);
3805}
3806
3807void CIRGenModule::emitAliasForGlobal(StringRef mangledName,
3808 mlir::Operation *op, GlobalDecl aliasGD,
3809 cir::FuncOp aliasee,
3810 cir::GlobalLinkageKind linkage) {
3811
3812 auto *aliasFD = dyn_cast<FunctionDecl>(aliasGD.getDecl());
3813 assert(aliasFD && "expected FunctionDecl");
3814
3815 // The aliasee function type is different from the alias one, this difference
3816 // is specific to CIR because in LLVM the ptr types are already erased at this
3817 // point.
3818 const CIRGenFunctionInfo &fnInfo =
3820 cir::FuncType fnType = getTypes().getFunctionType(fnInfo);
3821
3822 cir::FuncOp alias =
3824 mangledName, fnType, aliasFD);
3825 alias.setAliasee(aliasee.getName());
3826 alias.setLinkage(linkage);
3827 // Declarations cannot have public MLIR visibility, just mark them private
3828 // but this really should have no meaning since CIR should not be using
3829 // this information to derive linkage information.
3830 mlir::SymbolTable::setSymbolVisibility(
3831 alias, mlir::SymbolTable::Visibility::Private);
3832
3833 // Alias constructors and destructors are always unnamed_addr.
3835
3836 if (op) {
3837 // Any existing users of the existing function declaration will be
3838 // referencing the function by flat symbol reference (i.e. the name), so
3839 // those uses will automatically resolve to the alias now that we've
3840 // replaced the function declaration. We can safely erase the existing
3841 // function declaration.
3842 assert(cast<cir::FuncOp>(op).getFunctionType() == alias.getFunctionType() &&
3843 "declaration exists with different type");
3845 op->erase();
3846 } else {
3847 // Name already set by createCIRFunction
3848 }
3849
3850 // Finally, set up the alias with its proper name and attributes.
3851 setCommonAttributes(aliasGD, alias);
3852}
3853
3855 return genTypes.convertType(type);
3856}
3857
3859 // Verify the module after we have finished constructing it, this will
3860 // check the structural properties of the IR and invoke any specific
3861 // verifiers we have on the CIR operations.
3862 return mlir::verify(theModule).succeeded();
3863}
3864
3865mlir::Attribute CIRGenModule::getAddrOfRTTIDescriptor(mlir::Location loc,
3866 QualType ty, bool forEh) {
3867 // Return a bogus pointer if RTTI is disabled, unless it's for EH.
3868 // FIXME: should we even be calling this method if RTTI is disabled
3869 // and it's not for EH?
3870 if (!shouldEmitRTTI(forEh))
3871 return builder.getConstNullPtrAttr(builder.getUInt8PtrTy());
3872
3873 if (forEh && ty->isObjCObjectPointerType() &&
3874 langOpts.ObjCRuntime.isGNUFamily()) {
3875 errorNYI(loc, "getAddrOfRTTIDescriptor: Objc PtrType & Objc RT GUN");
3876 return {};
3877 }
3878
3879 return getCXXABI().getAddrOfRTTIDescriptor(loc, ty);
3880}
3881
3882// TODO(cir): this can be shared with LLVM codegen.
3884 const CXXRecordDecl *derivedClass,
3885 llvm::iterator_range<CastExpr::path_const_iterator> path) {
3886 CharUnits offset = CharUnits::Zero();
3887
3888 const ASTContext &astContext = getASTContext();
3889 const CXXRecordDecl *rd = derivedClass;
3890
3891 for (const CXXBaseSpecifier *base : path) {
3892 assert(!base->isVirtual() && "Should not see virtual bases here!");
3893
3894 // Get the layout.
3895 const ASTRecordLayout &layout = astContext.getASTRecordLayout(rd);
3896
3897 const auto *baseDecl = base->getType()->castAsCXXRecordDecl();
3898
3899 // Add the offset.
3900 offset += layout.getBaseClassOffset(baseDecl);
3901
3902 rd = baseDecl;
3903 }
3904
3905 return offset;
3906}
3907
3909 llvm::StringRef feature) {
3910 unsigned diagID = diags.getCustomDiagID(
3911 DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0");
3912 return diags.Report(loc, diagID) << feature;
3913}
3914
3916 llvm::StringRef feature) {
3917 return errorNYI(loc.getBegin(), feature) << loc;
3918}
3919
3921 unsigned diagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error, "%0");
3922 getDiags().Report(astContext.getFullLoc(loc), diagID) << error;
3923}
3924
3925/// Print out an error that codegen doesn't support the specified stmt yet.
3926void CIRGenModule::errorUnsupported(const Stmt *s, llvm::StringRef type) {
3927 unsigned diagId = diags.getCustomDiagID(DiagnosticsEngine::Error,
3928 "cannot compile this %0 yet");
3929 diags.Report(astContext.getFullLoc(s->getBeginLoc()), diagId)
3930 << type << s->getSourceRange();
3931}
3932
3933/// Print out an error that codegen doesn't support the specified decl yet.
3934void CIRGenModule::errorUnsupported(const Decl *d, llvm::StringRef type) {
3935 unsigned diagId = diags.getCustomDiagID(DiagnosticsEngine::Error,
3936 "cannot compile this %0 yet");
3937 diags.Report(astContext.getFullLoc(d->getLocation()), diagId) << type;
3938}
3939
3940void CIRGenModule::mapBlockAddress(cir::BlockAddrInfoAttr blockInfo,
3941 cir::LabelOp label) {
3942 [[maybe_unused]] auto result =
3943 blockAddressInfoToLabel.try_emplace(blockInfo, label);
3944 assert(result.second &&
3945 "attempting to map a blockaddress info that is already mapped");
3946}
3947
3948cir::LabelOp
3949CIRGenModule::lookupBlockAddressInfo(cir::BlockAddrInfoAttr blockInfo) {
3950 return blockAddressInfoToLabel.lookup(blockInfo);
3951}
3952
3953mlir::Operation *
3955 const Expr *init) {
3956 assert((mte->getStorageDuration() == SD_Static ||
3957 mte->getStorageDuration() == SD_Thread) &&
3958 "not a global temporary");
3959 const auto *varDecl = cast<VarDecl>(mte->getExtendingDecl());
3960
3961 // Use the MaterializeTemporaryExpr's type if it has the same unqualified
3962 // base type as Init. This preserves cv-qualifiers (e.g. const from a
3963 // constexpr or const-ref binding) that skipRValueSubobjectAdjustments may
3964 // have dropped via NoOp casts, while correctly falling back to Init's type
3965 // when a real subobject adjustment changed the type (e.g. member access or
3966 // base-class cast in C++98), where E->getType() reflects the reference type,
3967 // not the actual storage type.
3968 QualType materializedType = init->getType();
3969 if (getASTContext().hasSameUnqualifiedType(mte->getType(), materializedType))
3970 materializedType = mte->getType();
3971
3972 CharUnits align = getASTContext().getTypeAlignInChars(materializedType);
3973 mlir::Location loc = getLoc(mte->getSourceRange());
3974
3975 // FIXME: If an externally-visible declaration extends multiple temporaries,
3976 // we need to give each temporary the same name in every translation unit (and
3977 // we also need to make the temporaries externally-visible).
3979 llvm::raw_svector_ostream out(name);
3981 varDecl, mte->getManglingNumber(), out);
3982
3983 auto insertResult = materializedGlobalTemporaryMap.insert({mte, nullptr});
3984 if (!insertResult.second) {
3985 mlir::Type type = getTypes().convertTypeForMem(materializedType);
3986 // We've seen this before: either we already created it or we're in the
3987 // process of doing so.
3988 if (!insertResult.first->second) {
3989 // We recursively re-entered this function, probably during emission of
3990 // the initializer. Create a placeholder.
3991 insertResult.first->second =
3992 createGlobalOp(loc, name, type, /*isConstant=*/false);
3993 }
3994 return insertResult.first->second;
3995 }
3996
3997 APValue *value = nullptr;
3998 if (mte->getStorageDuration() == SD_Static && varDecl->evaluateValue()) {
3999 // If the initializer of the extending declaration is a constant
4000 // initializer, we should have a cached constant initializer for this
4001 // temporay. Note taht this m ight have a different value from the value
4002 // computed by evaluating the initializer if the surrounding constant
4003 // expression modifies the temporary.
4004 value = mte->getOrCreateValue(/*MayCreate=*/false);
4005 }
4006
4007 // Try evaluating it now, it might have a constant initializer
4008 Expr::EvalResult evalResult;
4009 if (!value && init->EvaluateAsRValue(evalResult, getASTContext()) &&
4010 !evalResult.hasSideEffects())
4011 value = &evalResult.Val;
4012
4014
4015 std::optional<ConstantEmitter> emitter;
4016 mlir::Attribute initialValue = nullptr;
4017 bool isConstant = false;
4018 mlir::Type type;
4019
4020 if (value) {
4021 emitter.emplace(*this);
4022 initialValue = emitter->emitForInitializer(*value, materializedType);
4023
4024 isConstant = materializedType.isConstantStorage(
4025 getASTContext(), /*ExcludeCtor=*/value, /*ExcludeDtor=*/false);
4026
4027 type = mlir::cast<mlir::TypedAttr>(initialValue).getType();
4028 } else {
4029 // No initializer, the initialization will be provided when we initialize
4030 // the declaration which performed lifetime extension.
4031 type = getTypes().convertTypeForMem(materializedType);
4032 }
4033
4034 // Create a global variable for this lifetime-extended temporary.
4035 cir::GlobalLinkageKind linkage = getCIRLinkageVarDefinition(varDecl);
4036 if (linkage == cir::GlobalLinkageKind::ExternalLinkage) {
4037 const VarDecl *initVD;
4038 if (varDecl->isStaticDataMember() && varDecl->getAnyInitializer(initVD) &&
4040 // Temporaries defined inside a class get linkonce_odr linkage because the
4041 // calss can be defined in multiple translation units.
4042 errorNYI(mte->getSourceRange(), "static data member initialization");
4043 } else {
4044 // There is no need for this temporary to have external linkage if the
4045 // VarDecl has external linkage.
4046 linkage = cir::GlobalLinkageKind::InternalLinkage;
4047 }
4048 }
4049 cir::GlobalOp gv = createGlobalOp(loc, name, type, isConstant);
4050 gv.setInitialValueAttr(initialValue);
4051 gv.setLinkage(linkage);
4052 gv.setVisibility(getMLIRVisibilityFromCIRLinkage(linkage));
4053
4054 if (emitter)
4055 emitter->finalize(gv);
4056 // Don't assign dllimport or dllexport to local linkage globals
4057 if (!gv.hasLocalLinkage()) {
4060 }
4061
4062 gv.setAlignment(align.getAsAlign().value());
4063 if (supportsCOMDAT() && gv.isWeakForLinker())
4064 gv.setComdat(true);
4065 if (varDecl->getTLSKind())
4066 setTLSMode(gv, *varDecl, /*isExtendingDecl=*/true);
4067 mlir::Operation *cv = gv;
4068
4070
4071 // Update the map with the new temporary. If we created a placeholder above,
4072 // erase it as well, the name will have been the same, so our symbol
4073 // references would have been correct. We still do a 'replaceAllUsesWith' in
4074 // case some sort of expression formed a reference to the placeholder
4075 // temporary.
4076 mlir::Operation *&entry = materializedGlobalTemporaryMap[mte];
4077 if (entry) {
4078 entry->replaceAllUsesWith(cv);
4079 eraseGlobalSymbol(entry);
4080 entry->erase();
4081 }
4082 entry = cv;
4083
4084 return cv;
4085}
4086
4088 const UnnamedGlobalConstantDecl *gcd) {
4089 unsigned numEntries = unnamedGlobalConstantDeclMap.size();
4090 cir::GlobalOp *globalOpEntry = &unnamedGlobalConstantDeclMap[gcd];
4091
4092 if (*globalOpEntry)
4093 return *globalOpEntry;
4094
4095 ConstantEmitter emitter(*this);
4096
4097 const APValue &value = gcd->getValue();
4098 assert(!value.isAbsent());
4100 "emitForInitializer should take gcd->getType().getAddressSpace()");
4101 mlir::Attribute init = emitter.emitForInitializer(value, gcd->getType());
4102 auto typedInit = dyn_cast<mlir::TypedAttr>(init);
4103
4104 if (!typedInit)
4105 errorNYI(gcd->getSourceRange(),
4106 "getAddrOfUnnamedGlobalConstantDecl: non-typed initializer");
4107
4109
4110 // Classic codegen always creates these with .constant, then counts on the
4111 // auto-addition of '.#'. CIR global doesn't have this, so we'll just auto-add
4112 // one if this isn't the first. We could probably choose a better name than
4113 // .constant to be unique for this type of decl, but this is consistent with
4114 // classic codegen.
4115 std::string name = numEntries == 0
4116 ? ".constant"
4117 : (Twine(".constant.") + Twine(numEntries)).str();
4118 auto globalOp = createGlobalOp(builder.getUnknownLoc(), name,
4119 typedInit.getType(), /*is_constant=*/true);
4120 globalOp.setLinkage(cir::GlobalLinkageKind::PrivateLinkage);
4121
4122 CharUnits alignment = getASTContext().getTypeAlignInChars(gcd->getType());
4123 globalOp.setAlignment(alignment.getAsAlign().value());
4124 CIRGenModule::setInitializer(globalOp, init);
4125
4126 emitter.finalize(globalOp);
4127 *globalOpEntry = globalOp;
4128 return globalOp;
4129}
4130
4131cir::GlobalOp
4133 StringRef name = getMangledName(tpo);
4134 CharUnits alignment = getNaturalTypeAlignment(tpo->getType());
4135
4136 if (auto globalOp =
4137 mlir::dyn_cast_or_null<cir::GlobalOp>(getGlobalValue(name)))
4138 return globalOp;
4139
4140 ConstantEmitter emitter(*this);
4142 "emitForInitializer should take tpo->getType().getAddressSpace()");
4143 mlir::Attribute init =
4144 emitter.emitForInitializer(tpo->getValue(), tpo->getType());
4145
4146 if (!init) {
4147 errorUnsupported(tpo, "template parameter object");
4148 return {};
4149 }
4150
4151 mlir::TypedAttr typedInit = cast<mlir::TypedAttr>(init);
4152
4153 cir::GlobalLinkageKind linkage =
4155 ? cir::GlobalLinkageKind::LinkOnceODRLinkage
4156 : cir::GlobalLinkageKind::InternalLinkage;
4157
4159 auto globalOp = createGlobalOp(builder.getUnknownLoc(), name,
4160 typedInit.getType(), /*is_constant=*/true);
4161 globalOp.setLinkage(linkage);
4162 globalOp.setAlignment(alignment.getAsAlign().value());
4163 globalOp.setComdat(supportsCOMDAT() &&
4164 linkage == cir::GlobalLinkageKind::LinkOnceODRLinkage);
4165
4166 CIRGenModule::setInitializer(globalOp, init);
4167 emitter.finalize(globalOp);
4168
4169 insertGlobalSymbol(globalOp);
4170
4171 return globalOp;
4172}
4173
4174//===----------------------------------------------------------------------===//
4175// Annotations
4176//===----------------------------------------------------------------------===//
4177
4178mlir::ArrayAttr
4179CIRGenModule::getOrCreateAnnotationArgs(const AnnotateAttr *attr) {
4180 ArrayRef<Expr *> exprs = {attr->args_begin(), attr->args_size()};
4181 // Return a null attr for no-args annotations so OptionalParameter omits
4182 // the args portion entirely from the printed IR.
4183 if (exprs.empty())
4184 return {};
4185
4186 llvm::FoldingSetNodeID id;
4187 for (Expr *e : exprs)
4188 id.Add(cast<clang::ConstantExpr>(e)->getAPValueResult());
4189
4190 mlir::ArrayAttr &lookup = annotationArgs[id.ComputeHash()];
4191 if (lookup)
4192 return lookup;
4193
4195 args.reserve(exprs.size());
4196 for (Expr *e : exprs) {
4197 if (auto *strE = dyn_cast<clang::StringLiteral>(e->IgnoreParenCasts())) {
4198 args.push_back(builder.getStringAttr(strE->getString()));
4199 } else if (auto *intE =
4200 dyn_cast<clang::IntegerLiteral>(e->IgnoreParenCasts())) {
4201 auto intTy = builder.getIntegerType(intE->getValue().getBitWidth());
4202 args.push_back(builder.getIntegerAttr(intTy, intE->getValue()));
4203 } else {
4204 errorNYI(e->getExprLoc(), "annotation argument expression");
4205 }
4206 }
4207
4208 return lookup = builder.getArrayAttr(args);
4209}
4210
4211cir::AnnotationAttr CIRGenModule::emitAnnotateAttr(const AnnotateAttr *aa) {
4212 mlir::StringAttr annoGV = builder.getStringAttr(aa->getAnnotation());
4213 mlir::ArrayAttr args = getOrCreateAnnotationArgs(aa);
4214 return cir::AnnotationAttr::get(&getMLIRContext(), annoGV, args);
4215}
4216
4218 mlir::Operation *gv) {
4219 assert(d->hasAttr<AnnotateAttr>() && "no annotate attribute");
4220 assert((isa<cir::GlobalOp>(gv) || isa<cir::FuncOp>(gv)) &&
4221 "annotation only on globals");
4223 for (const auto *i : d->specific_attrs<AnnotateAttr>())
4224 annotations.push_back(emitAnnotateAttr(i));
4225 if (auto global = dyn_cast<cir::GlobalOp>(gv))
4226 global.setAnnotationsAttr(builder.getArrayAttr(annotations));
4227 else if (auto func = dyn_cast<cir::FuncOp>(gv))
4228 func.setAnnotationsAttr(builder.getArrayAttr(annotations));
4229}
4230
4231void CIRGenModule::emitGlobalAnnotations() {
4232 for (const auto &[mangledName, vd] : deferredAnnotations) {
4233 mlir::Operation *gv = getGlobalValue(mangledName);
4234 if (gv)
4235 addGlobalAnnotations(vd, gv);
4236 }
4237 deferredAnnotations.clear();
4238}
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 void setLinkageForFunction(CIRGenModule &cgm, cir::FuncOp &func, const NamedDecl *nd)
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 bool verifyPointerTypeArgs(cir::FuncOp oldF, cir::FuncOp newF, mlir::SymbolUserMap &userMap)
static cir::CtorKind getCtorKindFromDecl(const CXXConstructorDecl *ctor)
static void emitUsed(CIRGenModule &cgm, StringRef name, std::vector< cir::CIRGlobalValueInterface > &list)
static cir::GlobalViewAttr createNewGlobalView(CIRGenModule &cgm, cir::GlobalOp newGlob, cir::GlobalViewAttr attr, mlir::Type oldTy)
This file defines OpenACC nodes for declarative directives.
TokenType getType() const
Returns the token's type, e.g.
*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.
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:484
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:223
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:888
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:927
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 void handleGlobalReplace(cir::GlobalOp oldGV, cir::GlobalOp newGV)
virtual mlir::Operation * getKernelHandle(cir::FuncOp fn, GlobalDecl gd)=0
virtual void finalizeModule()
Perform module finalization: on device side, mark ODR-used device variables as compiler-used.
virtual void internalizeDeviceSideVar(const VarDecl *d, cir::GlobalLinkageKind &linkage)=0
Adjust linkage of shadow variables in host compilation.
virtual void handleVarRegistration(const VarDecl *vd, cir::GlobalOp var)=0
Check whether a variable is a device variable and register it if true.
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 setGlobalVisibility(cir::CIRGlobalValueInterface gv, const NamedDecl *d) const
Set the visibility for the given global.
void addUsedOrCompilerUsedGlobal(cir::CIRGlobalValueInterface gv)
Add a global to a list to be added to the llvm.compiler.used metadata.
void setFuncInfoAttr(cir::FuncOp funcOp, const clang::FunctionDecl *funcDecl)
Record the func_info tag for a function, either a C++ special member form (constructor,...
void replaceUsesOfNonProtoTypeWithRealFunction(mlir::Operation *old, cir::FuncOp newFn)
This function is called when we implement a function with no prototype, e.g.
bool shouldEmitFunction(clang::GlobalDecl gd)
Check if fd ends up calling itself directly through asm label or builtin-pointer-to-self trickery (e....
llvm::StringRef getMangledName(clang::GlobalDecl gd)
CharUnits computeNonVirtualBaseClassOffset(const CXXRecordDecl *derivedClass, llvm::iterator_range< CastExpr::path_const_iterator > path)
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)
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)
void setGlobalTlsReferences(const VarDecl &vd, cir::GlobalOp globalOp)
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)
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 emitAliasDefinition(GlobalDecl gd)
Emit a definition for an __attribute__((alias)) declaration.
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)
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)
std::optional< llvm::SmallVector< int32_t > > buildMemberPath(const CXXRecordDecl *destClass, const FieldDecl *field)
Build a GEP-style field-index path from destClass to field.
void emitLLVMUsed()
Emit llvm.used and llvm.compiler.used globals.
mlir::Value emitMemberPointerConstant(const UnaryOperator *e)
void emitGlobalOpenACCDecl(const clang::OpenACCConstructDecl *cd)
void setTLSMode(mlir::Operation *op, const VarDecl &d, bool isExtendingDecl=false)
Set TLS mode for the given operation based on the given variable declaration.
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 printPostfixForExternalizedDecl(llvm::raw_ostream &os, const Decl *d)
Print the postfix for externalized static variable or kernels for single source offloading languages ...
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::GlobalOp createGlobalOp(mlir::Location loc, llvm::StringRef name, mlir::Type t, bool isConstant=false, mlir::ptr::MemorySpaceAttrInterface addrSpace={}, mlir::Operation *insertPoint=nullptr)
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)
static cir::VisibilityKind getCIRVisibilityKind(Visibility v)
void setGVPropertiesAux(mlir::Operation *op, const NamedDecl *d) const
LangAS getLangTempAllocaAddressSpace() const
Returns the address space for temporary allocations in the language.
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
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)
bool isEmptyFieldForMemberPointer(const FieldDecl *field)
Returns true if field is an empty field that isn't laid out in the CIR record (e.g.
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.
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...
This class handles record and union layout info while lowering AST types to CIR types.
bool hasNonVirtualBaseCIRField(const CXXRecordDecl *rd) const
unsigned getCIRFieldNo(const clang::FieldDecl *fd) const
Return cir::RecordType element number that corresponds to the field FD.
bool isZeroInitializable() const
Check whether this struct can be C++ zero-initialized with a zeroinitializer.
unsigned getNonVirtualBaseCIRFieldNo(const CXXRecordDecl *rd) const
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.
const CIRGenRecordLayout & getCIRGenRecordLayout(const clang::RecordDecl *rd)
Return record layout info for the given record decl.
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:122
Represents a base class of a C++ class.
Definition DeclCXX.h:146
Represents a C++ constructor within a class.
Definition DeclCXX.h:2633
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:3063
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:3058
bool isDefaultConstructor() const
Whether this constructor is a default constructor (C++ [class.ctor]p5), which can be used to default-...
Definition DeclCXX.cpp:3049
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2145
bool isMoveAssignmentOperator() const
Determine whether this is a move assignment operator.
Definition DeclCXX.cpp:2751
bool isCopyAssignmentOperator() const
Determine whether this is a copy-assignment operator, regardless of whether it was declared implicitl...
Definition DeclCXX.cpp:2730
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:2341
base_class_range bases()
Definition DeclCXX.h:608
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:3859
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1466
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Definition DeclBase.h:2403
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
bool isInStdNamespace() const
Definition DeclBase.cpp:453
T * getAttr() const
Definition DeclBase.h:581
bool isWeakImported() const
Determine whether this is a weak-imported symbol.
Definition DeclBase.cpp:876
bool isInExportDeclContext() const
Whether this declaration was exported in a lexical context.
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:935
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:234
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:915
ExplicitCastExpr - An explicit cast written in the source code.
Definition Expr.h:3934
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:3204
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
Definition Decl.h:3289
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Definition Decl.h:3440
bool isPotentiallyOverlapping() const
Determine if this field is of potentially-overlapping class type, that is, subobject with the [[no_un...
Definition Decl.cpp:4804
Cached information about one file (either on disk or in the virtual file system).
Definition FileEntry.h:273
StringRef tryGetRealPathName() const
Definition FileEntry.h:298
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:2029
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:2225
bool hasPrototype() const
Whether this function has a prototype, either because one was explicitly written or because it was "i...
Definition Decl.h:2479
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:2318
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
Definition Decl.cpp:3179
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4602
CallingConv getCallConv() const
Definition TypeBase.h:4957
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
unsigned getMultiVersionIndex() const
Definition GlobalDecl.h:125
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
std::string CUID
The user provided compilation unit ID, if non-empty.
Visibility getVisibility() const
Definition Visibility.h:89
void setLinkage(Linkage L)
Definition Visibility.h:92
Linkage getLinkage() const
Definition Visibility.h:88
bool isVisibilityExplicit() const
Definition Visibility.h:90
MangleContext - Context for tracking state which persists across multiple calls to the C++ name mangl...
Definition Mangle.h:56
bool isTriviallyRecursive(const FunctionDecl *FD)
Return true if FD's body contains a direct call back to the symbol it links as, through an asm label ...
Definition Mangle.cpp:198
bool shouldMangleDeclName(const NamedDecl *D)
Definition Mangle.cpp:129
void mangleName(GlobalDecl GD, raw_ostream &)
Definition Mangle.cpp:245
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:4919
StorageDuration getStorageDuration() const
Retrieve the storage duration for the materialized temporary.
Definition ExprCXX.h:4944
APValue * getOrCreateValue(bool MayCreate) const
Get the storage for the constant value of a materialized temporary of static storage duration.
Definition ExprCXX.h:4952
ValueDecl * getExtendingDecl()
Get the declaration which triggered the lifetime-extension of this temporary, if any.
Definition ExprCXX.h:4969
unsigned getManglingNumber() const
Definition ExprCXX.h:4980
A pointer to member type per C++ 8.3.3 - Pointers to members.
Definition TypeBase.h:3752
CXXRecordDecl * getMostRecentCXXRecordDecl() const
Note: this can trigger extra deserialization when external AST sources are used.
Definition Type.cpp:5646
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
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:301
bool hasUnwindExceptions() const
Does this runtime use zero-cost exceptions?
Represents a parameter to a function.
Definition Decl.h:1819
void setScopeInfo(unsigned scopeDepth, unsigned parameterIndex)
Definition Decl.h:1852
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:2936
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:938
LangAS getAddressSpace() const
Return the address space of this type.
Definition TypeBase.h:8615
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8529
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition TypeBase.h:8562
bool isConstantStorage(const ASTContext &Ctx, bool ExcludeCtor, bool ExcludeDtor)
Definition TypeBase.h:1037
bool hasUnaligned() const
Definition TypeBase.h:512
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:85
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:355
StringLiteral - This represents a string literal expression, e.g.
Definition Expr.h:1805
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Expr.h:1979
unsigned getLength() const
Definition Expr.h:1915
uint32_t getCodeUnit(size_t i) const
Definition Expr.h:1888
StringRef getString() const
Definition Expr.h:1873
unsigned getCharByteWidth() const
Definition Expr.h:1916
Represents the declaration of a struct/union/class/enum.
Definition Decl.h:3761
bool isUnion() const
Definition Decl.h:3972
bool isMicrosoft() const
Is this ABI an MSVC-compatible ABI?
TargetOptions & getTargetOpts() const
Retrieve the target options.
Definition TargetInfo.h:330
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 ParsedTargetAttr parseTargetAttr(StringRef Str) const
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:8825
bool isPointerType() const
Definition TypeBase.h:8726
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9386
bool isReferenceType() const
Definition TypeBase.h:8750
bool isCUDADeviceBuiltinSurfaceType() const
Check if the type is the CUDA device builtin surface type.
Definition Type.cpp:5478
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:2865
bool isCUDADeviceBuiltinTextureType() const
Check if the type is the CUDA device builtin texture type.
Definition Type.cpp:5487
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
Definition Type.cpp:2531
bool isObjCObjectPointerType() const
Definition TypeBase.h:8905
bool isMemberFunctionPointerType() const
Definition TypeBase.h:8811
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9319
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition Expr.h:2250
Expr * getSubExpr() const
Definition Expr.h:2291
An artificial decl, representing a global anonymous constant value which is uniquified by value withi...
Definition DeclCXX.h:4481
const APValue & getValue() const
Definition DeclCXX.h:4507
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:932
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
Definition Decl.h:1593
TLSKind getTLSKind() const
Definition Decl.cpp:2149
bool hasInit() const
Definition Decl.cpp:2379
DefinitionKind isThisDeclarationADefinition(ASTContext &) const
Check whether this declaration is a definition.
Definition Decl.cpp:2241
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:2171
bool hasFlexibleArrayInit(const ASTContext &Ctx) const
Whether this variable has a flexible array member initialized with one or more elements.
Definition Decl.cpp:2825
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition Decl.h:1247
bool hasConstantInitialization() const
Determine whether this variable has constant initialization.
Definition Decl.cpp:2632
VarDecl * getDefinition(ASTContext &)
Get the real (not just tentative) definition for this declaration.
Definition Decl.cpp:2347
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
Definition Decl.h:1214
QualType::DestructionKind needsDestruction(const ASTContext &Ctx) const
Would the destruction of this variable have any effect, and if so, what kind?
Definition Decl.cpp:2814
const Expr * getInit() const
Definition Decl.h:1391
bool hasExternalStorage() const
Returns true if a variable has extern or private_extern storage.
Definition Decl.h:1238
@ TLS_None
Not a TLS variable.
Definition Decl.h:952
@ DeclarationOnly
This declaration is only a declaration.
Definition Decl.h:1318
@ Definition
This declaration is definitely a definition.
Definition Decl.h:1324
DefinitionKind hasDefinition(ASTContext &) const
Check whether this variable is defined in this translation unit.
Definition Decl.cpp:2356
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:2742
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Definition Decl.h:1381
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)
Definition NVPTX.cpp:85
CIRGenCXXABI * CreateCIRGenItaniumCXXABI(CIRGenModule &cgm)
Creates and Itanium-family ABI.
std::unique_ptr< TargetCIRGenInfo > createX8664TargetCIRGenInfo(CIRGenTypes &cgt)
std::unique_ptr< TargetCIRGenInfo > createSPIRVTargetCIRGenInfo(CIRGenTypes &cgt)
Definition SPIRV.cpp:56
bool isEmptyFieldForLayout(const ASTContext &context, const FieldDecl *fd)
isEmptyFieldForLayout - Return true if the field is "empty", that is, either a zero-width bit-field o...
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
@ HiddenVisibility
Objects with "hidden" visibility are not seen by the dynamic linker.
Definition Visibility.h:37
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 int32_t
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 shouldSkipAliasEmission()
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 checkAliases()
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:652
APValue Val
Val - This is the value the expression can be folded to.
Definition Expr.h:654
bool hasSideEffects() const
Return true if the evaluated expression has side effects.
Definition Expr.h:646