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