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