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