clang 22.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 "CIRGenCXXABI.h"
16#include "CIRGenFunction.h"
17
19#include "clang/AST/DeclBase.h"
27
28#include "CIRGenFunctionInfo.h"
29#include "mlir/IR/BuiltinOps.h"
30#include "mlir/IR/Location.h"
31#include "mlir/IR/MLIRContext.h"
32#include "mlir/IR/Verifier.h"
33
34using namespace clang;
35using namespace clang::CIRGen;
36
38 switch (cgm.getASTContext().getCXXABIKind()) {
39 case TargetCXXABI::GenericItanium:
40 case TargetCXXABI::GenericAArch64:
41 case TargetCXXABI::AppleARM64:
42 return CreateCIRGenItaniumCXXABI(cgm);
43
44 case TargetCXXABI::Fuchsia:
45 case TargetCXXABI::GenericARM:
46 case TargetCXXABI::iOS:
47 case TargetCXXABI::WatchOS:
48 case TargetCXXABI::GenericMIPS:
49 case TargetCXXABI::WebAssembly:
50 case TargetCXXABI::XL:
51 case TargetCXXABI::Microsoft:
52 cgm.errorNYI("C++ ABI kind not yet implemented");
53 return nullptr;
54 }
55
56 llvm_unreachable("invalid C++ ABI kind");
57}
58
59CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,
60 clang::ASTContext &astContext,
61 const clang::CodeGenOptions &cgo,
62 DiagnosticsEngine &diags)
63 : builder(mlirContext, *this), astContext(astContext),
64 langOpts(astContext.getLangOpts()), codeGenOpts(cgo),
65 theModule{mlir::ModuleOp::create(mlir::UnknownLoc::get(&mlirContext))},
66 diags(diags), target(astContext.getTargetInfo()),
67 abi(createCXXABI(*this)), genTypes(*this), vtables(*this) {
68
69 // Initialize cached types
70 voidTy = cir::VoidType::get(&getMLIRContext());
71 voidPtrTy = cir::PointerType::get(voidTy);
72 sInt8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/true);
73 sInt16Ty = cir::IntType::get(&getMLIRContext(), 16, /*isSigned=*/true);
74 sInt32Ty = cir::IntType::get(&getMLIRContext(), 32, /*isSigned=*/true);
75 sInt64Ty = cir::IntType::get(&getMLIRContext(), 64, /*isSigned=*/true);
76 sInt128Ty = cir::IntType::get(&getMLIRContext(), 128, /*isSigned=*/true);
77 uInt8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/false);
78 uInt8PtrTy = cir::PointerType::get(uInt8Ty);
80 uInt16Ty = cir::IntType::get(&getMLIRContext(), 16, /*isSigned=*/false);
81 uInt32Ty = cir::IntType::get(&getMLIRContext(), 32, /*isSigned=*/false);
82 uInt64Ty = cir::IntType::get(&getMLIRContext(), 64, /*isSigned=*/false);
83 uInt128Ty = cir::IntType::get(&getMLIRContext(), 128, /*isSigned=*/false);
84 fP16Ty = cir::FP16Type::get(&getMLIRContext());
85 bFloat16Ty = cir::BF16Type::get(&getMLIRContext());
86 floatTy = cir::SingleType::get(&getMLIRContext());
87 doubleTy = cir::DoubleType::get(&getMLIRContext());
88 fP80Ty = cir::FP80Type::get(&getMLIRContext());
89 fP128Ty = cir::FP128Type::get(&getMLIRContext());
90
91 allocaInt8PtrTy = cir::PointerType::get(uInt8Ty, cirAllocaAddressSpace);
92
94 astContext
95 .toCharUnitsFromBits(
96 astContext.getTargetInfo().getPointerAlign(LangAS::Default))
97 .getQuantity();
98
99 const unsigned charSize = astContext.getTargetInfo().getCharWidth();
100 uCharTy = cir::IntType::get(&getMLIRContext(), charSize, /*isSigned=*/false);
101
102 // TODO(CIR): Should be updated once TypeSizeInfoAttr is upstreamed
103 const unsigned sizeTypeSize =
104 astContext.getTypeSize(astContext.getSignedSizeType());
105 SizeSizeInBytes = astContext.toCharUnitsFromBits(sizeTypeSize).getQuantity();
106 // In CIRGenTypeCache, UIntPtrTy and SizeType are fields of the same union
107 uIntPtrTy =
108 cir::IntType::get(&getMLIRContext(), sizeTypeSize, /*isSigned=*/false);
109 ptrDiffTy =
110 cir::IntType::get(&getMLIRContext(), sizeTypeSize, /*isSigned=*/true);
111
112 std::optional<cir::SourceLanguage> sourceLanguage = getCIRSourceLanguage();
113 if (sourceLanguage)
114 theModule->setAttr(
115 cir::CIRDialect::getSourceLanguageAttrName(),
116 cir::SourceLanguageAttr::get(&mlirContext, *sourceLanguage));
117 theModule->setAttr(cir::CIRDialect::getTripleAttrName(),
118 builder.getStringAttr(getTriple().str()));
119
120 if (cgo.OptimizationLevel > 0 || cgo.OptimizeSize > 0)
121 theModule->setAttr(cir::CIRDialect::getOptInfoAttrName(),
122 cir::OptInfoAttr::get(&mlirContext,
123 cgo.OptimizationLevel,
124 cgo.OptimizeSize));
125 // Set the module name to be the name of the main file. TranslationUnitDecl
126 // often contains invalid source locations and isn't a reliable source for the
127 // module location.
128 FileID mainFileId = astContext.getSourceManager().getMainFileID();
129 const FileEntry &mainFile =
130 *astContext.getSourceManager().getFileEntryForID(mainFileId);
131 StringRef path = mainFile.tryGetRealPathName();
132 if (!path.empty()) {
133 theModule.setSymName(path);
134 theModule->setLoc(mlir::FileLineColLoc::get(&mlirContext, path,
135 /*line=*/0,
136 /*column=*/0));
137 }
138}
139
141
142/// FIXME: this could likely be a common helper and not necessarily related
143/// with codegen.
144/// Return the best known alignment for an unknown pointer to a
145/// particular class.
147 if (!rd->hasDefinition())
148 return CharUnits::One(); // Hopefully won't be used anywhere.
149
150 auto &layout = astContext.getASTRecordLayout(rd);
151
152 // If the class is final, then we know that the pointer points to an
153 // object of that type and can use the full alignment.
154 if (rd->isEffectivelyFinal())
155 return layout.getAlignment();
156
157 // Otherwise, we have to assume it could be a subclass.
158 return layout.getNonVirtualAlignment();
159}
160
162 LValueBaseInfo *baseInfo) {
164
165 // FIXME: This duplicates logic in ASTContext::getTypeAlignIfKnown, but
166 // that doesn't return the information we need to compute baseInfo.
167
168 // Honor alignment typedef attributes even on incomplete types.
169 // We also honor them straight for C++ class types, even as pointees;
170 // there's an expressivity gap here.
171 if (const auto *tt = t->getAs<TypedefType>()) {
172 if (unsigned align = tt->getDecl()->getMaxAlignment()) {
173 if (baseInfo)
175 return astContext.toCharUnitsFromBits(align);
176 }
177 }
178
179 // Analyze the base element type, so we don't get confused by incomplete
180 // array types.
181 t = astContext.getBaseElementType(t);
182
183 if (t->isIncompleteType()) {
184 // We could try to replicate the logic from
185 // ASTContext::getTypeAlignIfKnown, but nothing uses the alignment if the
186 // type is incomplete, so it's impossible to test. We could try to reuse
187 // getTypeAlignIfKnown, but that doesn't return the information we need
188 // to set baseInfo. So just ignore the possibility that the alignment is
189 // greater than one.
190 if (baseInfo)
192 return CharUnits::One();
193 }
194
195 if (baseInfo)
197
198 CharUnits alignment;
199 if (t.getQualifiers().hasUnaligned()) {
200 alignment = CharUnits::One();
201 } else {
203 alignment = astContext.getTypeAlignInChars(t);
204 }
205
206 // Cap to the global maximum type alignment unless the alignment
207 // was somehow explicit on the type.
208 if (unsigned maxAlign = astContext.getLangOpts().MaxTypeAlign) {
209 if (alignment.getQuantity() > maxAlign &&
210 !astContext.isAlignmentRequired(t))
211 alignment = CharUnits::fromQuantity(maxAlign);
212 }
213 return alignment;
214}
215
217 if (theTargetCIRGenInfo)
218 return *theTargetCIRGenInfo;
219
220 const llvm::Triple &triple = getTarget().getTriple();
221 switch (triple.getArch()) {
222 default:
224
225 // Currently we just fall through to x86_64.
226 [[fallthrough]];
227
228 case llvm::Triple::x86_64: {
229 switch (triple.getOS()) {
230 default:
232
233 // Currently we just fall through to x86_64.
234 [[fallthrough]];
235
236 case llvm::Triple::Linux:
237 theTargetCIRGenInfo = createX8664TargetCIRGenInfo(genTypes);
238 return *theTargetCIRGenInfo;
239 }
240 }
241 }
242}
243
245 assert(cLoc.isValid() && "expected valid source location");
246 const SourceManager &sm = astContext.getSourceManager();
247 PresumedLoc pLoc = sm.getPresumedLoc(cLoc);
248 StringRef filename = pLoc.getFilename();
249 return mlir::FileLineColLoc::get(builder.getStringAttr(filename),
250 pLoc.getLine(), pLoc.getColumn());
251}
252
253mlir::Location CIRGenModule::getLoc(SourceRange cRange) {
254 assert(cRange.isValid() && "expected a valid source range");
255 mlir::Location begin = getLoc(cRange.getBegin());
256 mlir::Location end = getLoc(cRange.getEnd());
257 mlir::Attribute metadata;
258 return mlir::FusedLoc::get({begin, end}, metadata, builder.getContext());
259}
260
261mlir::Operation *
263 const Decl *d = gd.getDecl();
264
266 return getAddrOfCXXStructor(gd, /*FnInfo=*/nullptr, /*FnType=*/nullptr,
267 /*DontDefer=*/false, isForDefinition);
268
269 if (isa<CXXMethodDecl>(d)) {
270 const CIRGenFunctionInfo &fi =
272 cir::FuncType ty = getTypes().getFunctionType(fi);
273 return getAddrOfFunction(gd, ty, /*ForVTable=*/false, /*DontDefer=*/false,
274 isForDefinition);
275 }
276
277 if (isa<FunctionDecl>(d)) {
279 cir::FuncType ty = getTypes().getFunctionType(fi);
280 return getAddrOfFunction(gd, ty, /*ForVTable=*/false, /*DontDefer=*/false,
281 isForDefinition);
282 }
283
284 return getAddrOfGlobalVar(cast<VarDecl>(d), /*ty=*/nullptr, isForDefinition)
285 .getDefiningOp();
286}
287
289 // We call getAddrOfGlobal with isForDefinition set to ForDefinition in
290 // order to get a Value with exactly the type we need, not something that
291 // might have been created for another decl with the same mangled name but
292 // different type.
293 mlir::Operation *op = getAddrOfGlobal(d, ForDefinition);
294
295 // In case of different address spaces, we may still get a cast, even with
296 // IsForDefinition equal to ForDefinition. Query mangled names table to get
297 // GlobalValue.
298 if (!op)
300
301 assert(op && "expected a valid global op");
302
303 // Check to see if we've already emitted this. This is necessary for a
304 // couple of reasons: first, decls can end up in deferred-decls queue
305 // multiple times, and second, decls can end up with definitions in unusual
306 // ways (e.g. by an extern inline function acquiring a strong function
307 // redefinition). Just ignore those cases.
308 // TODO: Not sure what to map this to for MLIR
309 mlir::Operation *globalValueOp = op;
310 if (auto gv = dyn_cast<cir::GetGlobalOp>(op))
311 globalValueOp =
312 mlir::SymbolTable::lookupSymbolIn(getModule(), gv.getNameAttr());
313
314 if (auto cirGlobalValue =
315 dyn_cast<cir::CIRGlobalValueInterface>(globalValueOp))
316 if (!cirGlobalValue.isDeclaration())
317 return;
318
319 // If this is OpenMP, check if it is legal to emit this global normally.
321
322 // Otherwise, emit the definition and move on to the next one.
324}
325
327 // Emit code for any potentially referenced deferred decls. Since a previously
328 // unused static decl may become used during the generation of code for a
329 // static function, iterate until no changes are made.
330
334
335 // Stop if we're out of both deferred vtables and deferred declarations.
336 if (deferredDeclsToEmit.empty())
337 return;
338
339 // Grab the list of decls to emit. If emitGlobalDefinition schedules more
340 // work, it will not interfere with this.
341 std::vector<GlobalDecl> curDeclsToEmit;
342 curDeclsToEmit.swap(deferredDeclsToEmit);
343
344 for (const GlobalDecl &d : curDeclsToEmit) {
346
347 // If we found out that we need to emit more decls, do that recursively.
348 // This has the advantage that the decls are emitted in a DFS and related
349 // ones are close together, which is convenient for testing.
350 if (!deferredDeclsToEmit.empty()) {
351 emitDeferred();
352 assert(deferredDeclsToEmit.empty());
353 }
354 }
355}
356
358 if (const auto *cd = dyn_cast<clang::OpenACCConstructDecl>(gd.getDecl())) {
360 return;
361 }
362
363 const auto *global = cast<ValueDecl>(gd.getDecl());
364
365 if (const auto *fd = dyn_cast<FunctionDecl>(global)) {
366 // Update deferred annotations with the latest declaration if the function
367 // was already used or defined.
368 if (fd->hasAttr<AnnotateAttr>())
369 errorNYI(fd->getSourceRange(), "deferredAnnotations");
370 if (!fd->doesThisDeclarationHaveABody()) {
371 if (!fd->doesDeclarationForceExternallyVisibleDefinition())
372 return;
373
374 errorNYI(fd->getSourceRange(),
375 "function declaration that forces code gen");
376 return;
377 }
378 } else {
379 const auto *vd = cast<VarDecl>(global);
380 assert(vd->isFileVarDecl() && "Cannot emit local var decl as global.");
381 if (vd->isThisDeclarationADefinition() != VarDecl::Definition &&
382 !astContext.isMSStaticDataMemberInlineDefinition(vd)) {
384 // If this declaration may have caused an inline variable definition to
385 // change linkage, make sure that it's emitted.
386 if (astContext.getInlineVariableDefinitionKind(vd) ==
389 // Otherwise, we can ignore this declaration. The variable will be emitted
390 // on its first use.
391 return;
392 }
393 }
394
395 // Defer code generation to first use when possible, e.g. if this is an inline
396 // function. If the global must always be emitted, do it eagerly if possible
397 // to benefit from cache locality. Deferring code generation is necessary to
398 // avoid adding initializers to external declarations.
399 if (mustBeEmitted(global) && mayBeEmittedEagerly(global)) {
400 // Emit the definition if it can't be deferred.
402 return;
403 }
404
405 // If we're deferring emission of a C++ variable with an initializer, remember
406 // the order in which it appeared on the file.
408
409 llvm::StringRef mangledName = getMangledName(gd);
410 if (getGlobalValue(mangledName) != nullptr) {
411 // The value has already been used and should therefore be emitted.
413 } else if (mustBeEmitted(global)) {
414 // The value must be emitted, but cannot be emitted eagerly.
415 assert(!mayBeEmittedEagerly(global));
417 } else {
418 // Otherwise, remember that we saw a deferred decl with this name. The first
419 // use of the mangled name will cause it to move into deferredDeclsToEmit.
420 deferredDecls[mangledName] = gd;
421 }
422}
423
425 mlir::Operation *op) {
426 auto const *funcDecl = cast<FunctionDecl>(gd.getDecl());
428 cir::FuncType funcType = getTypes().getFunctionType(fi);
429 cir::FuncOp funcOp = dyn_cast_if_present<cir::FuncOp>(op);
430 if (!funcOp || funcOp.getFunctionType() != funcType) {
431 funcOp = getAddrOfFunction(gd, funcType, /*ForVTable=*/false,
432 /*DontDefer=*/true, ForDefinition);
433 }
434
435 // Already emitted.
436 if (!funcOp.isDeclaration())
437 return;
438
439 setFunctionLinkage(gd, funcOp);
440 setGVProperties(funcOp, funcDecl);
442 maybeSetTrivialComdat(*funcDecl, funcOp);
444
445 CIRGenFunction cgf(*this, builder);
446 curCGF = &cgf;
447 {
448 mlir::OpBuilder::InsertionGuard guard(builder);
449 cgf.generateCode(gd, funcOp, funcType);
450 }
451 curCGF = nullptr;
452
453 setNonAliasAttributes(gd, funcOp);
455
456 auto getPriority = [this](const auto *attr) -> int {
457 Expr *e = attr->getPriority();
458 if (e)
459 return e->EvaluateKnownConstInt(this->getASTContext()).getExtValue();
460 return attr->DefaultPriority;
461 };
462
463 if (const ConstructorAttr *ca = funcDecl->getAttr<ConstructorAttr>())
464 addGlobalCtor(funcOp, getPriority(ca));
465 if (const DestructorAttr *da = funcDecl->getAttr<DestructorAttr>())
466 addGlobalDtor(funcOp, getPriority(da));
467
468 if (funcDecl->getAttr<AnnotateAttr>())
469 errorNYI(funcDecl->getSourceRange(), "deferredAnnotations");
470}
471
472/// Track functions to be called before main() runs.
473void CIRGenModule::addGlobalCtor(cir::FuncOp ctor,
474 std::optional<int> priority) {
477
478 // Traditional LLVM codegen directly adds the function to the list of global
479 // ctors. In CIR we just add a global_ctor attribute to the function. The
480 // global list is created in LoweringPrepare.
481 //
482 // FIXME(from traditional LLVM): Type coercion of void()* types.
483 ctor.setGlobalCtorPriority(priority);
484}
485
486/// Add a function to the list that will be called when the module is unloaded.
487void CIRGenModule::addGlobalDtor(cir::FuncOp dtor,
488 std::optional<int> priority) {
489 if (codeGenOpts.RegisterGlobalDtorsWithAtExit &&
490 (!getASTContext().getTargetInfo().getTriple().isOSAIX()))
491 errorNYI(dtor.getLoc(), "registerGlobalDtorsWithAtExit");
492
493 // FIXME(from traditional LLVM): Type coercion of void()* types.
494 dtor.setGlobalDtorPriority(priority);
495}
496
499 if (dk == VarDecl::Definition && vd->hasAttr<DLLImportAttr>())
500 return;
501
503 // If we have a definition, this might be a deferred decl. If the
504 // instantiation is explicit, make sure we emit it at the end.
507
509}
510
511mlir::Operation *CIRGenModule::getGlobalValue(StringRef name) {
512 return mlir::SymbolTable::lookupSymbolIn(theModule, name);
513}
514
515cir::GlobalOp CIRGenModule::createGlobalOp(CIRGenModule &cgm,
516 mlir::Location loc, StringRef name,
517 mlir::Type t, bool isConstant,
518 mlir::Operation *insertPoint) {
519 cir::GlobalOp g;
520 CIRGenBuilderTy &builder = cgm.getBuilder();
521
522 {
523 mlir::OpBuilder::InsertionGuard guard(builder);
524
525 // If an insertion point is provided, we're replacing an existing global,
526 // otherwise, create the new global immediately after the last gloabl we
527 // emitted.
528 if (insertPoint) {
529 builder.setInsertionPoint(insertPoint);
530 } else {
531 // Group global operations together at the top of the module.
532 if (cgm.lastGlobalOp)
533 builder.setInsertionPointAfter(cgm.lastGlobalOp);
534 else
535 builder.setInsertionPointToStart(cgm.getModule().getBody());
536 }
537
538 g = cir::GlobalOp::create(builder, loc, name, t, isConstant);
539 if (!insertPoint)
540 cgm.lastGlobalOp = g;
541
542 // Default to private until we can judge based on the initializer,
543 // since MLIR doesn't allow public declarations.
544 mlir::SymbolTable::setSymbolVisibility(
545 g, mlir::SymbolTable::Visibility::Private);
546 }
547 return g;
548}
549
550void CIRGenModule::setCommonAttributes(GlobalDecl gd, mlir::Operation *gv) {
551 const Decl *d = gd.getDecl();
552 if (isa_and_nonnull<NamedDecl>(d))
553 setGVProperties(gv, dyn_cast<NamedDecl>(d));
556}
557
558void CIRGenModule::setNonAliasAttributes(GlobalDecl gd, mlir::Operation *op) {
559 setCommonAttributes(gd, op);
560
565
567}
568
569std::optional<cir::SourceLanguage> CIRGenModule::getCIRSourceLanguage() const {
570 using ClangStd = clang::LangStandard;
571 using CIRLang = cir::SourceLanguage;
572 auto opts = getLangOpts();
573
574 if (opts.CPlusPlus)
575 return CIRLang::CXX;
576 if (opts.C99 || opts.C11 || opts.C17 || opts.C23 || opts.C2y ||
577 opts.LangStd == ClangStd::lang_c89 ||
578 opts.LangStd == ClangStd::lang_gnu89)
579 return CIRLang::C;
580
581 // TODO(cir): support remaining source languages.
583 errorNYI("CIR does not yet support the given source language");
584 return std::nullopt;
585}
586
587static void setLinkageForGV(cir::GlobalOp &gv, const NamedDecl *nd) {
588 // Set linkage and visibility in case we never see a definition.
590 // Don't set internal linkage on declarations.
591 // "extern_weak" is overloaded in LLVM; we probably should have
592 // separate linkage types for this.
594 (nd->hasAttr<WeakAttr>() || nd->isWeakImported()))
595 gv.setLinkage(cir::GlobalLinkageKind::ExternalWeakLinkage);
596}
597
598/// If the specified mangled name is not in the module,
599/// create and return an mlir GlobalOp with the specified type (TODO(cir):
600/// address space).
601///
602/// TODO(cir):
603/// 1. If there is something in the module with the specified name, return
604/// it potentially bitcasted to the right type.
605///
606/// 2. If \p d is non-null, it specifies a decl that correspond to this. This
607/// is used to set the attributes on the global when it is first created.
608///
609/// 3. If \p isForDefinition is true, it is guaranteed that an actual global
610/// with type \p ty will be returned, not conversion of a variable with the same
611/// mangled name but some other type.
612cir::GlobalOp
613CIRGenModule::getOrCreateCIRGlobal(StringRef mangledName, mlir::Type ty,
614 LangAS langAS, const VarDecl *d,
615 ForDefinition_t isForDefinition) {
616 // Lookup the entry, lazily creating it if necessary.
617 cir::GlobalOp entry;
618 if (mlir::Operation *v = getGlobalValue(mangledName)) {
619 if (!isa<cir::GlobalOp>(v))
620 errorNYI(d->getSourceRange(), "global with non-GlobalOp type");
621 entry = cast<cir::GlobalOp>(v);
622 }
623
624 if (entry) {
627
630
631 if (entry.getSymType() == ty)
632 return entry;
633
634 // If there are two attempts to define the same mangled name, issue an
635 // error.
636 //
637 // TODO(cir): look at mlir::GlobalValue::isDeclaration for all aspects of
638 // recognizing the global as a declaration, for now only check if
639 // initializer is present.
640 if (isForDefinition && !entry.isDeclaration()) {
641 errorNYI(d->getSourceRange(), "global with conflicting type");
642 }
643
644 // Address space check removed because it is unnecessary because CIR records
645 // address space info in types.
646
647 // (If global is requested for a definition, we always need to create a new
648 // global, not just return a bitcast.)
649 if (!isForDefinition)
650 return entry;
651 }
652
653 mlir::Location loc = getLoc(d->getSourceRange());
654
655 // mlir::SymbolTable::Visibility::Public is the default, no need to explicitly
656 // mark it as such.
657 cir::GlobalOp gv =
658 CIRGenModule::createGlobalOp(*this, loc, mangledName, ty, false,
659 /*insertPoint=*/entry.getOperation());
660
661 // This is the first use or definition of a mangled name. If there is a
662 // deferred decl with this name, remember that we need to emit it at the end
663 // of the file.
664 auto ddi = deferredDecls.find(mangledName);
665 if (ddi != deferredDecls.end()) {
666 // Move the potentially referenced deferred decl to the DeferredDeclsToEmit
667 // list, and remove it from DeferredDecls (since we don't need it anymore).
668 addDeferredDeclToEmit(ddi->second);
669 deferredDecls.erase(ddi);
670 }
671
672 // Handle things which are present even on external declarations.
673 if (d) {
674 if (langOpts.OpenMP && !langOpts.OpenMPSimd)
675 errorNYI(d->getSourceRange(), "OpenMP target global variable");
676
677 gv.setAlignmentAttr(getSize(astContext.getDeclAlign(d)));
678 // FIXME: This code is overly simple and should be merged with other global
679 // handling.
680 gv.setConstant(d->getType().isConstantStorage(
681 astContext, /*ExcludeCtor=*/false, /*ExcludeDtor=*/false));
682
683 setLinkageForGV(gv, d);
684
685 if (d->getTLSKind()) {
687 errorNYI(d->getSourceRange(), "TLS dynamic");
688 setTLSMode(gv, *d);
689 }
690
691 setGVProperties(gv, d);
692
693 // If required by the ABI, treat declarations of static data members with
694 // inline initializers as definitions.
695 if (astContext.isMSStaticDataMemberInlineDefinition(d))
696 errorNYI(d->getSourceRange(), "MS static data member inline definition");
697
699 gv.setGlobalVisibilityAttr(getGlobalVisibilityAttrFromDecl(d));
700
701 // Handle XCore specific ABI requirements.
702 if (getTriple().getArch() == llvm::Triple::xcore)
703 errorNYI(d->getSourceRange(), "XCore specific ABI requirements");
704
705 // Check if we a have a const declaration with an initializer, we may be
706 // able to emit it as available_externally to expose it's value to the
707 // optimizer.
708 if (getLangOpts().CPlusPlus && gv.isPublic() &&
709 d->getType().isConstQualified() && gv.isDeclaration() &&
710 !d->hasDefinition() && d->hasInit() && !d->hasAttr<DLLImportAttr>())
712 "external const declaration with initializer");
713 }
714
715 return gv;
716}
717
718cir::GlobalOp
720 ForDefinition_t isForDefinition) {
721 assert(d->hasGlobalStorage() && "Not a global variable");
722 QualType astTy = d->getType();
723 if (!ty)
724 ty = getTypes().convertTypeForMem(astTy);
725
726 StringRef mangledName = getMangledName(d);
727 return getOrCreateCIRGlobal(mangledName, ty, astTy.getAddressSpace(), d,
728 isForDefinition);
729}
730
731/// Return the mlir::Value for the address of the given global variable. If
732/// \p ty is non-null and if the global doesn't exist, then it will be created
733/// with the specified type instead of whatever the normal requested type would
734/// be. If \p isForDefinition is true, it is guaranteed that an actual global
735/// with type \p ty will be returned, not conversion of a variable with the same
736/// mangled name but some other type.
737mlir::Value CIRGenModule::getAddrOfGlobalVar(const VarDecl *d, mlir::Type ty,
738 ForDefinition_t isForDefinition) {
739 assert(d->hasGlobalStorage() && "Not a global variable");
740 QualType astTy = d->getType();
741 if (!ty)
742 ty = getTypes().convertTypeForMem(astTy);
743
744 bool tlsAccess = d->getTLSKind() != VarDecl::TLS_None;
745 cir::GlobalOp g = getOrCreateCIRGlobal(d, ty, isForDefinition);
746 mlir::Type ptrTy = builder.getPointerTo(g.getSymType());
747 return cir::GetGlobalOp::create(builder, getLoc(d->getSourceRange()), ptrTy,
748 g.getSymNameAttr(), tlsAccess);
749}
750
751cir::GlobalViewAttr CIRGenModule::getAddrOfGlobalVarAttr(const VarDecl *d) {
752 assert(d->hasGlobalStorage() && "Not a global variable");
753 mlir::Type ty = getTypes().convertTypeForMem(d->getType());
754
755 cir::GlobalOp globalOp = getOrCreateCIRGlobal(d, ty, NotForDefinition);
757 cir::PointerType ptrTy = builder.getPointerTo(globalOp.getSymType());
758 return builder.getGlobalViewAttr(ptrTy, globalOp);
759}
760
762 bool isTentative) {
763 if (getLangOpts().OpenCL || getLangOpts().OpenMPIsTargetDevice) {
764 errorNYI(vd->getSourceRange(), "emit OpenCL/OpenMP global variable");
765 return;
766 }
767
768 // Whether the definition of the variable is available externally.
769 // If yes, we shouldn't emit the GloablCtor and GlobalDtor for the variable
770 // since this is the job for its original source.
771 bool isDefinitionAvailableExternally =
772 astContext.GetGVALinkageForVariable(vd) == GVA_AvailableExternally;
773
774 // It is useless to emit the definition for an available_externally variable
775 // which can't be marked as const.
776 if (isDefinitionAvailableExternally &&
778 // TODO: Update this when we have interface to check constexpr
779 // destructor.
780 vd->needsDestruction(astContext) ||
781 !vd->getType().isConstantStorage(astContext, true, true)))
782 return;
783
784 mlir::Attribute init;
785 bool needsGlobalCtor = false;
786 bool needsGlobalDtor =
787 !isDefinitionAvailableExternally &&
789 const VarDecl *initDecl;
790 const Expr *initExpr = vd->getAnyInitializer(initDecl);
791
792 std::optional<ConstantEmitter> emitter;
793
795
796 if (vd->hasAttr<LoaderUninitializedAttr>()) {
797 errorNYI(vd->getSourceRange(), "loader uninitialized attribute");
798 return;
799 } else if (!initExpr) {
800 // This is a tentative definition; tentative definitions are
801 // implicitly initialized with { 0 }.
802 //
803 // Note that tentative definitions are only emitted at the end of
804 // a translation unit, so they should never have incomplete
805 // type. In addition, EmitTentativeDefinition makes sure that we
806 // never attempt to emit a tentative definition if a real one
807 // exists. A use may still exists, however, so we still may need
808 // to do a RAUW.
809 assert(!vd->getType()->isIncompleteType() && "Unexpected incomplete type");
810 init = builder.getZeroInitAttr(convertType(vd->getType()));
811 } else {
812 emitter.emplace(*this);
813 mlir::Attribute initializer = emitter->tryEmitForInitializer(*initDecl);
814 if (!initializer) {
815 QualType qt = initExpr->getType();
816 if (vd->getType()->isReferenceType())
817 qt = vd->getType();
818
819 if (getLangOpts().CPlusPlus) {
820 if (initDecl->hasFlexibleArrayInit(astContext))
821 errorNYI(vd->getSourceRange(), "flexible array initializer");
822 init = builder.getZeroInitAttr(convertType(qt));
823 if (!isDefinitionAvailableExternally)
824 needsGlobalCtor = true;
825 } else {
826 errorNYI(vd->getSourceRange(), "static initializer");
827 }
828 } else {
829 init = initializer;
830 // We don't need an initializer, so remove the entry for the delayed
831 // initializer position (just in case this entry was delayed) if we
832 // also don't need to register a destructor.
834 }
835 }
836
837 mlir::Type initType;
838 if (mlir::isa<mlir::SymbolRefAttr>(init)) {
839 errorNYI(vd->getSourceRange(), "global initializer is a symbol reference");
840 return;
841 } else {
842 assert(mlir::isa<mlir::TypedAttr>(init) && "This should have a type");
843 auto typedInitAttr = mlir::cast<mlir::TypedAttr>(init);
844 initType = typedInitAttr.getType();
845 }
846 assert(!mlir::isa<mlir::NoneType>(initType) && "Should have a type by now");
847
848 cir::GlobalOp gv =
849 getOrCreateCIRGlobal(vd, initType, ForDefinition_t(!isTentative));
850 // TODO(cir): Strip off pointer casts from Entry if we get them?
851
852 if (!gv || gv.getSymType() != initType) {
853 errorNYI(vd->getSourceRange(), "global initializer with type mismatch");
854 return;
855 }
856
858
859 if (vd->hasAttr<AnnotateAttr>()) {
860 errorNYI(vd->getSourceRange(), "annotate global variable");
861 }
862
863 if (langOpts.CUDA) {
864 errorNYI(vd->getSourceRange(), "CUDA global variable");
865 }
866
867 // Set initializer and finalize emission
869 if (emitter)
870 emitter->finalize(gv);
871
872 // If it is safe to mark the global 'constant', do so now.
873 gv.setConstant((vd->hasAttr<CUDAConstantAttr>() && langOpts.CUDAIsDevice) ||
874 (!needsGlobalCtor && !needsGlobalDtor &&
876 astContext, /*ExcludeCtor=*/true, /*ExcludeDtor=*/true)));
878
879 // Set CIR's linkage type as appropriate.
880 cir::GlobalLinkageKind linkage =
881 getCIRLinkageVarDefinition(vd, /*IsConstant=*/false);
882
883 // Set CIR linkage and DLL storage class.
884 gv.setLinkage(linkage);
885 // FIXME(cir): setLinkage should likely set MLIR's visibility automatically.
886 gv.setVisibility(getMLIRVisibilityFromCIRLinkage(linkage));
888 if (linkage == cir::GlobalLinkageKind::CommonLinkage) {
889 // common vars aren't constant even if declared const.
890 gv.setConstant(false);
891 // Tentative definition of global variables may be initialized with
892 // non-zero null pointers. In this case they should have weak linkage
893 // since common linkage must have zero initializer and must not have
894 // explicit section therefore cannot have non-zero initial value.
895 std::optional<mlir::Attribute> initializer = gv.getInitialValue();
896 if (initializer && !getBuilder().isNullValue(*initializer))
897 gv.setLinkage(cir::GlobalLinkageKind::WeakAnyLinkage);
898 }
899
900 setNonAliasAttributes(vd, gv);
901
903
904 maybeSetTrivialComdat(*vd, gv);
905
906 // Emit the initializer function if necessary.
907 if (needsGlobalCtor || needsGlobalDtor)
908 emitCXXGlobalVarDeclInitFunc(vd, gv, needsGlobalCtor);
909}
910
912 mlir::Operation *op) {
913 const auto *decl = cast<ValueDecl>(gd.getDecl());
914 if (const auto *fd = dyn_cast<FunctionDecl>(decl)) {
915 // TODO(CIR): Skip generation of CIR for functions with available_externally
916 // linkage at -O0.
917
918 if (const auto *method = dyn_cast<CXXMethodDecl>(decl)) {
919 // Make sure to emit the definition(s) before we emit the thunks. This is
920 // necessary for the generation of certain thunks.
921 if (isa<CXXConstructorDecl>(method) || isa<CXXDestructorDecl>(method))
922 abi->emitCXXStructor(gd);
923 else if (fd->isMultiVersion())
924 errorNYI(method->getSourceRange(), "multiversion functions");
925 else
927
928 if (method->isVirtual())
930
931 return;
932 }
933
934 if (fd->isMultiVersion())
935 errorNYI(fd->getSourceRange(), "multiversion functions");
937 return;
938 }
939
940 if (const auto *vd = dyn_cast<VarDecl>(decl))
941 return emitGlobalVarDefinition(vd, !vd->hasDefinition());
942
943 llvm_unreachable("Invalid argument to CIRGenModule::emitGlobalDefinition");
944}
945
946mlir::Attribute
948 assert(!e->getType()->isPointerType() && "Strings are always arrays");
949
950 // Don't emit it as the address of the string, emit the string data itself
951 // as an inline array.
952 if (e->getCharByteWidth() == 1) {
953 SmallString<64> str(e->getString());
954
955 // Resize the string to the right size, which is indicated by its type.
956 const ConstantArrayType *cat =
957 astContext.getAsConstantArrayType(e->getType());
958 uint64_t finalSize = cat->getZExtSize();
959 str.resize(finalSize);
960
961 mlir::Type eltTy = convertType(cat->getElementType());
962 return builder.getString(str, eltTy, finalSize);
963 }
964
966 "getConstantArrayFromStringLiteral: wide characters");
967 return mlir::Attribute();
968}
969
971 return getTriple().supportsCOMDAT();
972}
973
974static bool shouldBeInCOMDAT(CIRGenModule &cgm, const Decl &d) {
975 if (!cgm.supportsCOMDAT())
976 return false;
977
978 if (d.hasAttr<SelectAnyAttr>())
979 return true;
980
981 GVALinkage linkage;
982 if (auto *vd = dyn_cast<VarDecl>(&d))
983 linkage = cgm.getASTContext().GetGVALinkageForVariable(vd);
984 else
985 linkage =
987
988 switch (linkage) {
992 return false;
995 return true;
996 }
997 llvm_unreachable("No such linkage");
998}
999
1000void CIRGenModule::maybeSetTrivialComdat(const Decl &d, mlir::Operation *op) {
1001 if (!shouldBeInCOMDAT(*this, d))
1002 return;
1003 if (auto globalOp = dyn_cast_or_null<cir::GlobalOp>(op)) {
1004 globalOp.setComdat(true);
1005 } else {
1006 auto funcOp = cast<cir::FuncOp>(op);
1007 funcOp.setComdat(true);
1008 }
1009}
1010
1012 // Make sure that this type is translated.
1013 genTypes.updateCompletedType(td);
1014}
1015
1016void CIRGenModule::addReplacement(StringRef name, mlir::Operation *op) {
1017 replacements[name] = op;
1018}
1019
1020void CIRGenModule::replacePointerTypeArgs(cir::FuncOp oldF, cir::FuncOp newF) {
1021 std::optional<mlir::SymbolTable::UseRange> optionalUseRange =
1022 oldF.getSymbolUses(theModule);
1023 if (!optionalUseRange)
1024 return;
1025
1026 for (const mlir::SymbolTable::SymbolUse &u : *optionalUseRange) {
1027 // CallTryOp only shows up after FlattenCFG.
1028 auto call = mlir::dyn_cast<cir::CallOp>(u.getUser());
1029 if (!call)
1030 continue;
1031
1032 for (const auto [argOp, fnArgType] :
1033 llvm::zip(call.getArgs(), newF.getFunctionType().getInputs())) {
1034 if (argOp.getType() == fnArgType)
1035 continue;
1036
1037 // The purpose of this entire function is to insert bitcasts in the case
1038 // where these types don't match, but I haven't seen a case where that
1039 // happens.
1040 errorNYI(call.getLoc(), "replace call with mismatched types");
1041 }
1042 }
1043}
1044
1045void CIRGenModule::applyReplacements() {
1046 for (auto &i : replacements) {
1047 StringRef mangledName = i.first();
1048 mlir::Operation *replacement = i.second;
1049 mlir::Operation *entry = getGlobalValue(mangledName);
1050 if (!entry)
1051 continue;
1052 assert(isa<cir::FuncOp>(entry) && "expected function");
1053 auto oldF = cast<cir::FuncOp>(entry);
1054 auto newF = dyn_cast<cir::FuncOp>(replacement);
1055 if (!newF) {
1056 // In classic codegen, this can be a global alias, a bitcast, or a GEP.
1057 errorNYI(replacement->getLoc(), "replacement is not a function");
1058 continue;
1059 }
1060
1061 // LLVM has opaque pointer but CIR not. So we may have to handle these
1062 // different pointer types when performing replacement.
1063 replacePointerTypeArgs(oldF, newF);
1064
1065 // Replace old with new, but keep the old order.
1066 if (oldF.replaceAllSymbolUses(newF.getSymNameAttr(), theModule).failed())
1067 llvm_unreachable("internal error, cannot RAUW symbol");
1068 if (newF) {
1069 newF->moveBefore(oldF);
1070 oldF->erase();
1071 }
1072 }
1073}
1074
1076 mlir::Location loc, StringRef name, mlir::Type ty,
1077 cir::GlobalLinkageKind linkage, clang::CharUnits alignment) {
1078 auto gv = mlir::dyn_cast_or_null<cir::GlobalOp>(
1079 mlir::SymbolTable::lookupSymbolIn(theModule, name));
1080
1081 if (gv) {
1082 // Check if the variable has the right type.
1083 if (gv.getSymType() == ty)
1084 return gv;
1085
1086 // Because of C++ name mangling, the only way we can end up with an already
1087 // existing global with the same name is if it has been declared extern
1088 // "C".
1089 assert(gv.isDeclaration() && "Declaration has wrong type!");
1090
1091 errorNYI(loc, "createOrReplaceCXXRuntimeVariable: declaration exists with "
1092 "wrong type");
1093 return gv;
1094 }
1095
1096 // Create a new variable.
1097 gv = createGlobalOp(*this, loc, name, ty);
1098
1099 // Set up extra information and add to the module
1100 gv.setLinkageAttr(
1101 cir::GlobalLinkageKindAttr::get(&getMLIRContext(), linkage));
1102 mlir::SymbolTable::setSymbolVisibility(gv,
1104
1105 if (supportsCOMDAT() && cir::isWeakForLinker(linkage) &&
1106 !gv.hasAvailableExternallyLinkage()) {
1107 gv.setComdat(true);
1108 }
1109
1110 gv.setAlignmentAttr(getSize(alignment));
1111 setDSOLocal(static_cast<mlir::Operation *>(gv));
1112 return gv;
1113}
1114
1115// TODO(CIR): this could be a common method between LLVM codegen.
1116static bool isVarDeclStrongDefinition(const ASTContext &astContext,
1117 CIRGenModule &cgm, const VarDecl *vd,
1118 bool noCommon) {
1119 // Don't give variables common linkage if -fno-common was specified unless it
1120 // was overridden by a NoCommon attribute.
1121 if ((noCommon || vd->hasAttr<NoCommonAttr>()) && !vd->hasAttr<CommonAttr>())
1122 return true;
1123
1124 // C11 6.9.2/2:
1125 // A declaration of an identifier for an object that has file scope without
1126 // an initializer, and without a storage-class specifier or with the
1127 // storage-class specifier static, constitutes a tentative definition.
1128 if (vd->getInit() || vd->hasExternalStorage())
1129 return true;
1130
1131 // A variable cannot be both common and exist in a section.
1132 if (vd->hasAttr<SectionAttr>())
1133 return true;
1134
1135 // A variable cannot be both common and exist in a section.
1136 // We don't try to determine which is the right section in the front-end.
1137 // If no specialized section name is applicable, it will resort to default.
1138 if (vd->hasAttr<PragmaClangBSSSectionAttr>() ||
1139 vd->hasAttr<PragmaClangDataSectionAttr>() ||
1140 vd->hasAttr<PragmaClangRelroSectionAttr>() ||
1141 vd->hasAttr<PragmaClangRodataSectionAttr>())
1142 return true;
1143
1144 // Thread local vars aren't considered common linkage.
1145 if (vd->getTLSKind())
1146 return true;
1147
1148 // Tentative definitions marked with WeakImportAttr are true definitions.
1149 if (vd->hasAttr<WeakImportAttr>())
1150 return true;
1151
1152 // A variable cannot be both common and exist in a comdat.
1153 if (shouldBeInCOMDAT(cgm, *vd))
1154 return true;
1155
1156 // Declarations with a required alignment do not have common linkage in MSVC
1157 // mode.
1158 if (astContext.getTargetInfo().getCXXABI().isMicrosoft()) {
1159 if (vd->hasAttr<AlignedAttr>())
1160 return true;
1161 QualType varType = vd->getType();
1162 if (astContext.isAlignmentRequired(varType))
1163 return true;
1164
1165 if (const auto *rd = varType->getAsRecordDecl()) {
1166 for (const FieldDecl *fd : rd->fields()) {
1167 if (fd->isBitField())
1168 continue;
1169 if (fd->hasAttr<AlignedAttr>())
1170 return true;
1171 if (astContext.isAlignmentRequired(fd->getType()))
1172 return true;
1173 }
1174 }
1175 }
1176
1177 // Microsoft's link.exe doesn't support alignments greater than 32 bytes for
1178 // common symbols, so symbols with greater alignment requirements cannot be
1179 // common.
1180 // Other COFF linkers (ld.bfd and LLD) support arbitrary power-of-two
1181 // alignments for common symbols via the aligncomm directive, so this
1182 // restriction only applies to MSVC environments.
1183 if (astContext.getTargetInfo().getTriple().isKnownWindowsMSVCEnvironment() &&
1184 astContext.getTypeAlignIfKnown(vd->getType()) >
1185 astContext.toBits(CharUnits::fromQuantity(32)))
1186 return true;
1187
1188 return false;
1189}
1190
1192 const DeclaratorDecl *dd, GVALinkage linkage, bool isConstantVariable) {
1193 if (linkage == GVA_Internal)
1194 return cir::GlobalLinkageKind::InternalLinkage;
1195
1196 if (dd->hasAttr<WeakAttr>()) {
1197 if (isConstantVariable)
1198 return cir::GlobalLinkageKind::WeakODRLinkage;
1199 return cir::GlobalLinkageKind::WeakAnyLinkage;
1200 }
1201
1202 if (const auto *fd = dd->getAsFunction())
1203 if (fd->isMultiVersion() && linkage == GVA_AvailableExternally)
1204 return cir::GlobalLinkageKind::LinkOnceAnyLinkage;
1205
1206 // We are guaranteed to have a strong definition somewhere else,
1207 // so we can use available_externally linkage.
1208 if (linkage == GVA_AvailableExternally)
1209 return cir::GlobalLinkageKind::AvailableExternallyLinkage;
1210
1211 // Note that Apple's kernel linker doesn't support symbol
1212 // coalescing, so we need to avoid linkonce and weak linkages there.
1213 // Normally, this means we just map to internal, but for explicit
1214 // instantiations we'll map to external.
1215
1216 // In C++, the compiler has to emit a definition in every translation unit
1217 // that references the function. We should use linkonce_odr because
1218 // a) if all references in this translation unit are optimized away, we
1219 // don't need to codegen it. b) if the function persists, it needs to be
1220 // merged with other definitions. c) C++ has the ODR, so we know the
1221 // definition is dependable.
1222 if (linkage == GVA_DiscardableODR)
1223 return !astContext.getLangOpts().AppleKext
1224 ? cir::GlobalLinkageKind::LinkOnceODRLinkage
1225 : cir::GlobalLinkageKind::InternalLinkage;
1226
1227 // An explicit instantiation of a template has weak linkage, since
1228 // explicit instantiations can occur in multiple translation units
1229 // and must all be equivalent. However, we are not allowed to
1230 // throw away these explicit instantiations.
1231 //
1232 // CUDA/HIP: For -fno-gpu-rdc case, device code is limited to one TU,
1233 // so say that CUDA templates are either external (for kernels) or internal.
1234 // This lets llvm perform aggressive inter-procedural optimizations. For
1235 // -fgpu-rdc case, device function calls across multiple TU's are allowed,
1236 // therefore we need to follow the normal linkage paradigm.
1237 if (linkage == GVA_StrongODR) {
1238 if (getLangOpts().AppleKext)
1239 return cir::GlobalLinkageKind::ExternalLinkage;
1240 if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice &&
1241 !getLangOpts().GPURelocatableDeviceCode)
1242 return dd->hasAttr<CUDAGlobalAttr>()
1243 ? cir::GlobalLinkageKind::ExternalLinkage
1244 : cir::GlobalLinkageKind::InternalLinkage;
1245 return cir::GlobalLinkageKind::WeakODRLinkage;
1246 }
1247
1248 // C++ doesn't have tentative definitions and thus cannot have common
1249 // linkage.
1250 if (!getLangOpts().CPlusPlus && isa<VarDecl>(dd) &&
1251 !isVarDeclStrongDefinition(astContext, *this, cast<VarDecl>(dd),
1252 getCodeGenOpts().NoCommon))
1253 return cir::GlobalLinkageKind::CommonLinkage;
1254
1255 // selectany symbols are externally visible, so use weak instead of
1256 // linkonce. MSVC optimizes away references to const selectany globals, so
1257 // all definitions should be the same and ODR linkage should be used.
1258 // http://msdn.microsoft.com/en-us/library/5tkz6s71.aspx
1259 if (dd->hasAttr<SelectAnyAttr>())
1260 return cir::GlobalLinkageKind::WeakODRLinkage;
1261
1262 // Otherwise, we have strong external linkage.
1263 assert(linkage == GVA_StrongExternal);
1264 return cir::GlobalLinkageKind::ExternalLinkage;
1265}
1266
1267/// This function is called when we implement a function with no prototype, e.g.
1268/// "int foo() {}". If there are existing call uses of the old function in the
1269/// module, this adjusts them to call the new function directly.
1270///
1271/// This is not just a cleanup: the always_inline pass requires direct calls to
1272/// functions to be able to inline them. If there is a bitcast in the way, it
1273/// won't inline them. Instcombine normally deletes these calls, but it isn't
1274/// run at -O0.
1276 mlir::Operation *old, cir::FuncOp newFn) {
1277 // If we're redefining a global as a function, don't transform it.
1278 auto oldFn = mlir::dyn_cast<cir::FuncOp>(old);
1279 if (!oldFn)
1280 return;
1281
1282 // TODO(cir): this RAUW ignores the features below.
1286 if (oldFn->getAttrs().size() <= 1)
1287 errorNYI(old->getLoc(),
1288 "replaceUsesOfNonProtoTypeWithRealFunction: Attribute forwarding");
1289
1290 // Mark new function as originated from a no-proto declaration.
1291 newFn.setNoProto(oldFn.getNoProto());
1292
1293 // Iterate through all calls of the no-proto function.
1294 std::optional<mlir::SymbolTable::UseRange> symUses =
1295 oldFn.getSymbolUses(oldFn->getParentOp());
1296 for (const mlir::SymbolTable::SymbolUse &use : symUses.value()) {
1297 mlir::OpBuilder::InsertionGuard guard(builder);
1298
1299 if (auto noProtoCallOp = mlir::dyn_cast<cir::CallOp>(use.getUser())) {
1300 builder.setInsertionPoint(noProtoCallOp);
1301
1302 // Patch call type with the real function type.
1303 cir::CallOp realCallOp = builder.createCallOp(
1304 noProtoCallOp.getLoc(), newFn, noProtoCallOp.getOperands());
1305
1306 // Replace old no proto call with fixed call.
1307 noProtoCallOp.replaceAllUsesWith(realCallOp);
1308 noProtoCallOp.erase();
1309 } else if (auto getGlobalOp =
1310 mlir::dyn_cast<cir::GetGlobalOp>(use.getUser())) {
1311 // Replace type
1312 getGlobalOp.getAddr().setType(
1313 cir::PointerType::get(newFn.getFunctionType()));
1314 } else {
1315 errorNYI(use.getUser()->getLoc(),
1316 "replaceUsesOfNonProtoTypeWithRealFunction: unexpected use");
1317 }
1318 }
1319}
1320
1321cir::GlobalLinkageKind
1323 assert(!isConstant && "constant variables NYI");
1324 GVALinkage linkage = astContext.GetGVALinkageForVariable(vd);
1325 return getCIRLinkageForDeclarator(vd, linkage, isConstant);
1326}
1327
1329 const auto *d = cast<FunctionDecl>(gd.getDecl());
1330
1331 GVALinkage linkage = astContext.GetGVALinkageForFunction(d);
1332
1333 if (const auto *dtor = dyn_cast<CXXDestructorDecl>(d))
1334 return getCXXABI().getCXXDestructorLinkage(linkage, dtor, gd.getDtorType());
1335
1336 return getCIRLinkageForDeclarator(d, linkage, /*isConstantVariable=*/false);
1337}
1338
1339static cir::GlobalOp
1340generateStringLiteral(mlir::Location loc, mlir::TypedAttr c,
1341 cir::GlobalLinkageKind lt, CIRGenModule &cgm,
1342 StringRef globalName, CharUnits alignment) {
1344
1345 // Create a global variable for this string
1346 // FIXME(cir): check for insertion point in module level.
1347 cir::GlobalOp gv = CIRGenModule::createGlobalOp(
1348 cgm, loc, globalName, c.getType(), !cgm.getLangOpts().WritableStrings);
1349
1350 // Set up extra information and add to the module
1351 gv.setAlignmentAttr(cgm.getSize(alignment));
1352 gv.setLinkageAttr(
1353 cir::GlobalLinkageKindAttr::get(cgm.getBuilder().getContext(), lt));
1357 if (gv.isWeakForLinker()) {
1358 assert(cgm.supportsCOMDAT() && "Only COFF uses weak string literals");
1359 gv.setComdat(true);
1360 }
1361 cgm.setDSOLocal(static_cast<mlir::Operation *>(gv));
1362 return gv;
1363}
1364
1365// LLVM IR automatically uniques names when new llvm::GlobalVariables are
1366// created. This is handy, for example, when creating globals for string
1367// literals. Since we don't do that when creating cir::GlobalOp's, we need
1368// a mechanism to generate a unique name in advance.
1369//
1370// For now, this mechanism is only used in cases where we know that the
1371// name is compiler-generated, so we don't use the MLIR symbol table for
1372// the lookup.
1373std::string CIRGenModule::getUniqueGlobalName(const std::string &baseName) {
1374 // If this is the first time we've generated a name for this basename, use
1375 // it as is and start a counter for this base name.
1376 auto it = cgGlobalNames.find(baseName);
1377 if (it == cgGlobalNames.end()) {
1378 cgGlobalNames[baseName] = 1;
1379 return baseName;
1380 }
1381
1382 std::string result =
1383 baseName + "." + std::to_string(cgGlobalNames[baseName]++);
1384 // There should not be any symbol with this name in the module.
1385 assert(!mlir::SymbolTable::lookupSymbolIn(theModule, result));
1386 return result;
1387}
1388
1389/// Return a pointer to a constant array for the given string literal.
1391 StringRef name) {
1392 CharUnits alignment =
1393 astContext.getAlignOfGlobalVarInChars(s->getType(), /*VD=*/nullptr);
1394
1395 mlir::Attribute c = getConstantArrayFromStringLiteral(s);
1396
1397 cir::GlobalOp gv;
1398 if (!getLangOpts().WritableStrings && constantStringMap.count(c)) {
1399 gv = constantStringMap[c];
1400 // The bigger alignment always wins.
1401 if (!gv.getAlignment() ||
1402 uint64_t(alignment.getQuantity()) > *gv.getAlignment())
1403 gv.setAlignmentAttr(getSize(alignment));
1404 } else {
1405 // Mangle the string literal if that's how the ABI merges duplicate strings.
1406 // Don't do it if they are writable, since we don't want writes in one TU to
1407 // affect strings in another.
1408 if (getCXXABI().getMangleContext().shouldMangleStringLiteral(s) &&
1409 !getLangOpts().WritableStrings) {
1410 errorNYI(s->getSourceRange(),
1411 "getGlobalForStringLiteral: mangle string literals");
1412 }
1413
1414 // Unlike LLVM IR, CIR doesn't automatically unique names for globals, so
1415 // we need to do that explicitly.
1416 std::string uniqueName = getUniqueGlobalName(name.str());
1417 mlir::Location loc = getLoc(s->getSourceRange());
1418 auto typedC = llvm::cast<mlir::TypedAttr>(c);
1419 gv = generateStringLiteral(loc, typedC,
1420 cir::GlobalLinkageKind::PrivateLinkage, *this,
1421 uniqueName, alignment);
1422 setDSOLocal(static_cast<mlir::Operation *>(gv));
1423 constantStringMap[c] = gv;
1424
1426 }
1427 return gv;
1428}
1429
1430/// Return a pointer to a constant array for the given string literal.
1431cir::GlobalViewAttr
1433 StringRef name) {
1434 cir::GlobalOp gv = getGlobalForStringLiteral(s, name);
1435 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(gv.getSymType());
1436 assert(arrayTy && "String literal must be array");
1438 cir::PointerType ptrTy = getBuilder().getPointerTo(arrayTy.getElementType());
1439
1440 return builder.getGlobalViewAttr(ptrTy, gv);
1441}
1442
1443// TODO(cir): this could be a common AST helper for both CIR and LLVM codegen.
1445 if (getLangOpts().OpenCL)
1447
1448 // For temporaries inside functions, CUDA treats them as normal variables.
1449 // LangAS::cuda_device, on the other hand, is reserved for those variables
1450 // explicitly marked with __device__.
1451 if (getLangOpts().CUDAIsDevice)
1452 return LangAS::Default;
1453
1454 if (getLangOpts().SYCLIsDevice ||
1455 (getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice))
1456 errorNYI("SYCL or OpenMP temp address space");
1457 return LangAS::Default;
1458}
1459
1461 CIRGenFunction *cgf) {
1462 if (cgf && e->getType()->isVariablyModifiedType())
1464
1466 "emitExplicitCastExprType");
1467}
1468
1471
1472 mlir::Location loc = getLoc(e->getSourceRange());
1473
1474 const auto *decl = cast<DeclRefExpr>(e->getSubExpr())->getDecl();
1475
1476 // A member function pointer.
1477 if (isa<CXXMethodDecl>(decl)) {
1478 errorNYI(e->getSourceRange(), "emitMemberPointerConstant: method pointer");
1479 return {};
1480 }
1481
1482 // Otherwise, a member data pointer.
1483 auto ty = mlir::cast<cir::DataMemberType>(convertType(e->getType()));
1484 const auto *fieldDecl = cast<FieldDecl>(decl);
1485 return cir::ConstantOp::create(
1486 builder, loc, builder.getDataMemberAttr(ty, fieldDecl->getFieldIndex()));
1487}
1488
1490 for (Decl *decl : dc->decls()) {
1491 // Unlike other DeclContexts, the contents of an ObjCImplDecl at TU scope
1492 // are themselves considered "top-level", so EmitTopLevelDecl on an
1493 // ObjCImplDecl does not recursively visit them. We need to do that in
1494 // case they're nested inside another construct (LinkageSpecDecl /
1495 // ExportDecl) that does stop them from being considered "top-level".
1496 if (auto *oid = dyn_cast<ObjCImplDecl>(decl))
1497 errorNYI(oid->getSourceRange(), "emitDeclConext: ObjCImplDecl");
1498
1500 }
1501}
1502
1503// Emit code for a single top level declaration.
1505
1506 // Ignore dependent declarations.
1507 if (decl->isTemplated())
1508 return;
1509
1510 switch (decl->getKind()) {
1511 default:
1512 errorNYI(decl->getBeginLoc(), "declaration of kind",
1513 decl->getDeclKindName());
1514 break;
1515
1516 case Decl::CXXConversion:
1517 case Decl::CXXMethod:
1518 case Decl::Function: {
1519 auto *fd = cast<FunctionDecl>(decl);
1520 // Consteval functions shouldn't be emitted.
1521 if (!fd->isConsteval())
1522 emitGlobal(fd);
1523 break;
1524 }
1525
1526 case Decl::Var:
1527 case Decl::Decomposition:
1528 case Decl::VarTemplateSpecialization: {
1529 auto *vd = cast<VarDecl>(decl);
1531 errorNYI(decl->getSourceRange(), "global variable decompositions");
1532 break;
1533 }
1534 emitGlobal(vd);
1535 break;
1536 }
1537 case Decl::OpenACCRoutine:
1539 break;
1540 case Decl::OpenACCDeclare:
1542 break;
1543 case Decl::Enum:
1544 case Decl::Using: // using X; [C++]
1545 case Decl::UsingDirective: // using namespace X; [C++]
1546 case Decl::UsingEnum: // using enum X; [C++]
1547 case Decl::NamespaceAlias:
1548 case Decl::Typedef:
1549 case Decl::TypeAlias: // using foo = bar; [C++11]
1550 case Decl::Record:
1552 break;
1553
1554 // No code generation needed.
1555 case Decl::ClassTemplate:
1556 case Decl::Concept:
1557 case Decl::CXXDeductionGuide:
1558 case Decl::Empty:
1559 case Decl::FunctionTemplate:
1560 case Decl::StaticAssert:
1561 case Decl::TypeAliasTemplate:
1562 case Decl::UsingShadow:
1563 case Decl::VarTemplate:
1564 case Decl::VarTemplatePartialSpecialization:
1565 break;
1566
1567 case Decl::CXXConstructor:
1569 break;
1570 case Decl::CXXDestructor:
1572 break;
1573
1574 // C++ Decls
1575 case Decl::LinkageSpec:
1576 case Decl::Namespace:
1578 break;
1579
1580 case Decl::ClassTemplateSpecialization:
1581 case Decl::CXXRecord: {
1584 for (auto *childDecl : crd->decls())
1586 emitTopLevelDecl(childDecl);
1587 break;
1588 }
1589
1590 case Decl::FileScopeAsm:
1591 // File-scope asm is ignored during device-side CUDA compilation.
1592 if (langOpts.CUDA && langOpts.CUDAIsDevice)
1593 break;
1594 // File-scope asm is ignored during device-side OpenMP compilation.
1595 if (langOpts.OpenMPIsTargetDevice)
1596 break;
1597 // File-scope asm is ignored during device-side SYCL compilation.
1598 if (langOpts.SYCLIsDevice)
1599 break;
1600 auto *file_asm = cast<FileScopeAsmDecl>(decl);
1601 std::string line = file_asm->getAsmString();
1602 globalScopeAsm.push_back(builder.getStringAttr(line));
1603 break;
1604 }
1605}
1606
1607void CIRGenModule::setInitializer(cir::GlobalOp &op, mlir::Attribute value) {
1608 // Recompute visibility when updating initializer.
1609 op.setInitialValueAttr(value);
1611}
1612
1613std::pair<cir::FuncType, cir::FuncOp> CIRGenModule::getAddrAndTypeOfCXXStructor(
1614 GlobalDecl gd, const CIRGenFunctionInfo *fnInfo, cir::FuncType fnType,
1615 bool dontDefer, ForDefinition_t isForDefinition) {
1616 auto *md = cast<CXXMethodDecl>(gd.getDecl());
1617
1618 if (isa<CXXDestructorDecl>(md)) {
1619 // Always alias equivalent complete destructors to base destructors in the
1620 // MS ABI.
1621 if (getTarget().getCXXABI().isMicrosoft() &&
1622 gd.getDtorType() == Dtor_Complete &&
1623 md->getParent()->getNumVBases() == 0)
1624 errorNYI(md->getSourceRange(),
1625 "getAddrAndTypeOfCXXStructor: MS ABI complete destructor");
1626 }
1627
1628 if (!fnType) {
1629 if (!fnInfo)
1631 fnType = getTypes().getFunctionType(*fnInfo);
1632 }
1633
1634 auto fn = getOrCreateCIRFunction(getMangledName(gd), fnType, gd,
1635 /*ForVtable=*/false, dontDefer,
1636 /*IsThunk=*/false, isForDefinition);
1637
1638 return {fnType, fn};
1639}
1640
1642 mlir::Type funcType, bool forVTable,
1643 bool dontDefer,
1644 ForDefinition_t isForDefinition) {
1645 assert(!cast<FunctionDecl>(gd.getDecl())->isConsteval() &&
1646 "consteval function should never be emitted");
1647
1648 if (!funcType) {
1649 const auto *fd = cast<FunctionDecl>(gd.getDecl());
1650 funcType = convertType(fd->getType());
1651 }
1652
1653 // Devirtualized destructor calls may come through here instead of via
1654 // getAddrOfCXXStructor. Make sure we use the MS ABI base destructor instead
1655 // of the complete destructor when necessary.
1656 if (const auto *dd = dyn_cast<CXXDestructorDecl>(gd.getDecl())) {
1657 if (getTarget().getCXXABI().isMicrosoft() &&
1658 gd.getDtorType() == Dtor_Complete &&
1659 dd->getParent()->getNumVBases() == 0)
1660 errorNYI(dd->getSourceRange(),
1661 "getAddrOfFunction: MS ABI complete destructor");
1662 }
1663
1664 StringRef mangledName = getMangledName(gd);
1665 cir::FuncOp func =
1666 getOrCreateCIRFunction(mangledName, funcType, gd, forVTable, dontDefer,
1667 /*isThunk=*/false, isForDefinition);
1668 return func;
1669}
1670
1671static std::string getMangledNameImpl(CIRGenModule &cgm, GlobalDecl gd,
1672 const NamedDecl *nd) {
1673 SmallString<256> buffer;
1674
1675 llvm::raw_svector_ostream out(buffer);
1677
1679
1680 if (mc.shouldMangleDeclName(nd)) {
1681 mc.mangleName(gd.getWithDecl(nd), out);
1682 } else {
1683 IdentifierInfo *ii = nd->getIdentifier();
1684 assert(ii && "Attempt to mangle unnamed decl.");
1685
1686 const auto *fd = dyn_cast<FunctionDecl>(nd);
1687 if (fd &&
1688 fd->getType()->castAs<FunctionType>()->getCallConv() == CC_X86RegCall) {
1689 cgm.errorNYI(nd->getSourceRange(), "getMangledName: X86RegCall");
1690 } else if (fd && fd->hasAttr<CUDAGlobalAttr>() &&
1692 cgm.errorNYI(nd->getSourceRange(), "getMangledName: CUDA device stub");
1693 }
1694 out << ii->getName();
1695 }
1696
1697 // Check if the module name hash should be appended for internal linkage
1698 // symbols. This should come before multi-version target suffixes are
1699 // appendded. This is to keep the name and module hash suffix of the internal
1700 // linkage function together. The unique suffix should only be added when name
1701 // mangling is done to make sure that the final name can be properly
1702 // demangled. For example, for C functions without prototypes, name mangling
1703 // is not done and the unique suffix should not be appended then.
1705
1706 if (const auto *fd = dyn_cast<FunctionDecl>(nd)) {
1707 if (fd->isMultiVersion()) {
1708 cgm.errorNYI(nd->getSourceRange(),
1709 "getMangledName: multi-version functions");
1710 }
1711 }
1712 if (cgm.getLangOpts().GPURelocatableDeviceCode) {
1713 cgm.errorNYI(nd->getSourceRange(),
1714 "getMangledName: GPU relocatable device code");
1715 }
1716
1717 return std::string(out.str());
1718}
1719
1721 GlobalDecl canonicalGd = gd.getCanonicalDecl();
1722
1723 // Some ABIs don't have constructor variants. Make sure that base and complete
1724 // constructors get mangled the same.
1725 if (const auto *cd = dyn_cast<CXXConstructorDecl>(canonicalGd.getDecl())) {
1726 if (!getTarget().getCXXABI().hasConstructorVariants()) {
1727 errorNYI(cd->getSourceRange(),
1728 "getMangledName: C++ constructor without variants");
1729 return cast<NamedDecl>(gd.getDecl())->getIdentifier()->getName();
1730 }
1731 }
1732
1733 // Keep the first result in the case of a mangling collision.
1734 const auto *nd = cast<NamedDecl>(gd.getDecl());
1735 std::string mangledName = getMangledNameImpl(*this, gd, nd);
1736
1737 auto result = manglings.insert(std::make_pair(mangledName, gd));
1738 return mangledDeclNames[canonicalGd] = result.first->first();
1739}
1740
1742 assert(!d->getInit() && "Cannot emit definite definitions here!");
1743
1744 StringRef mangledName = getMangledName(d);
1745 mlir::Operation *gv = getGlobalValue(mangledName);
1746
1747 // If we already have a definition, not declaration, with the same mangled
1748 // name, emitting of declaration is not required (and would actually overwrite
1749 // the emitted definition).
1750 if (gv && !mlir::cast<cir::GlobalOp>(gv).isDeclaration())
1751 return;
1752
1753 // If we have not seen a reference to this variable yet, place it into the
1754 // deferred declarations table to be emitted if needed later.
1755 if (!mustBeEmitted(d) && !gv) {
1756 deferredDecls[mangledName] = d;
1757 return;
1758 }
1759
1760 // The tentative definition is the only definition.
1762}
1763
1765 // Never defer when EmitAllDecls is specified.
1766 if (langOpts.EmitAllDecls)
1767 return true;
1768
1769 const auto *vd = dyn_cast<VarDecl>(global);
1770 if (vd &&
1771 ((codeGenOpts.KeepPersistentStorageVariables &&
1772 (vd->getStorageDuration() == SD_Static ||
1773 vd->getStorageDuration() == SD_Thread)) ||
1774 (codeGenOpts.KeepStaticConsts && vd->getStorageDuration() == SD_Static &&
1775 vd->getType().isConstQualified())))
1776 return true;
1777
1778 return getASTContext().DeclMustBeEmitted(global);
1779}
1780
1782 // In OpenMP 5.0 variables and function may be marked as
1783 // device_type(host/nohost) and we should not emit them eagerly unless we sure
1784 // that they must be emitted on the host/device. To be sure we need to have
1785 // seen a declare target with an explicit mentioning of the function, we know
1786 // we have if the level of the declare target attribute is -1. Note that we
1787 // check somewhere else if we should emit this at all.
1788 if (langOpts.OpenMP >= 50 && !langOpts.OpenMPSimd) {
1789 std::optional<OMPDeclareTargetDeclAttr *> activeAttr =
1790 OMPDeclareTargetDeclAttr::getActiveAttr(global);
1791 if (!activeAttr || (*activeAttr)->getLevel() != (unsigned)-1)
1792 return false;
1793 }
1794
1795 const auto *fd = dyn_cast<FunctionDecl>(global);
1796 if (fd) {
1797 // Implicit template instantiations may change linkage if they are later
1798 // explicitly instantiated, so they should not be emitted eagerly.
1799 if (fd->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
1800 return false;
1801 // Defer until all versions have been semantically checked.
1802 if (fd->hasAttr<TargetVersionAttr>() && !fd->isMultiVersion())
1803 return false;
1804 if (langOpts.SYCLIsDevice) {
1805 errorNYI(fd->getSourceRange(), "mayBeEmittedEagerly: SYCL");
1806 return false;
1807 }
1808 }
1809 const auto *vd = dyn_cast<VarDecl>(global);
1810 if (vd)
1811 if (astContext.getInlineVariableDefinitionKind(vd) ==
1813 // A definition of an inline constexpr static data member may change
1814 // linkage later if it's redeclared outside the class.
1815 return false;
1816
1817 // If OpenMP is enabled and threadprivates must be generated like TLS, delay
1818 // codegen for global variables, because they may be marked as threadprivate.
1819 if (langOpts.OpenMP && langOpts.OpenMPUseTLS &&
1820 astContext.getTargetInfo().isTLSSupported() && isa<VarDecl>(global) &&
1821 !global->getType().isConstantStorage(astContext, false, false) &&
1822 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(global))
1823 return false;
1824
1825 assert((fd || vd) &&
1826 "Only FunctionDecl and VarDecl should hit this path so far.");
1827 return true;
1828}
1829
1830static bool shouldAssumeDSOLocal(const CIRGenModule &cgm,
1831 cir::CIRGlobalValueInterface gv) {
1832 if (gv.hasLocalLinkage())
1833 return true;
1834
1835 if (!gv.hasDefaultVisibility() && !gv.hasExternalWeakLinkage())
1836 return true;
1837
1838 // DLLImport explicitly marks the GV as external.
1839 // so it shouldn't be dso_local
1840 // But we don't have the info set now
1842
1843 const llvm::Triple &tt = cgm.getTriple();
1844 const CodeGenOptions &cgOpts = cgm.getCodeGenOpts();
1845 if (tt.isOSCygMing()) {
1846 // In MinGW and Cygwin, variables without DLLImport can still be
1847 // automatically imported from a DLL by the linker; don't mark variables
1848 // that potentially could come from another DLL as DSO local.
1849
1850 // With EmulatedTLS, TLS variables can be autoimported from other DLLs
1851 // (and this actually happens in the public interface of libstdc++), so
1852 // such variables can't be marked as DSO local. (Native TLS variables
1853 // can't be dllimported at all, though.)
1854 cgm.errorNYI("shouldAssumeDSOLocal: MinGW");
1855 }
1856
1857 // On COFF, don't mark 'extern_weak' symbols as DSO local. If these symbols
1858 // remain unresolved in the link, they can be resolved to zero, which is
1859 // outside the current DSO.
1860 if (tt.isOSBinFormatCOFF() && gv.hasExternalWeakLinkage())
1861 return false;
1862
1863 // Every other GV is local on COFF.
1864 // Make an exception for windows OS in the triple: Some firmware builds use
1865 // *-win32-macho triples. This (accidentally?) produced windows relocations
1866 // without GOT tables in older clang versions; Keep this behaviour.
1867 // FIXME: even thread local variables?
1868 if (tt.isOSBinFormatCOFF() || (tt.isOSWindows() && tt.isOSBinFormatMachO()))
1869 return true;
1870
1871 // Only handle COFF and ELF for now.
1872 if (!tt.isOSBinFormatELF())
1873 return false;
1874
1875 llvm::Reloc::Model rm = cgOpts.RelocationModel;
1876 const LangOptions &lOpts = cgm.getLangOpts();
1877 if (rm != llvm::Reloc::Static && !lOpts.PIE) {
1878 // On ELF, if -fno-semantic-interposition is specified and the target
1879 // supports local aliases, there will be neither CC1
1880 // -fsemantic-interposition nor -fhalf-no-semantic-interposition. Set
1881 // dso_local on the function if using a local alias is preferable (can avoid
1882 // PLT indirection).
1883 if (!(isa<cir::FuncOp>(gv) && gv.canBenefitFromLocalAlias()))
1884 return false;
1885 return !(lOpts.SemanticInterposition || lOpts.HalfNoSemanticInterposition);
1886 }
1887
1888 // A definition cannot be preempted from an executable.
1889 if (!gv.isDeclarationForLinker())
1890 return true;
1891
1892 // Most PIC code sequences that assume that a symbol is local cannot produce a
1893 // 0 if it turns out the symbol is undefined. While this is ABI and relocation
1894 // depended, it seems worth it to handle it here.
1895 if (rm == llvm::Reloc::PIC_ && gv.hasExternalWeakLinkage())
1896 return false;
1897
1898 // PowerPC64 prefers TOC indirection to avoid copy relocations.
1899 if (tt.isPPC64())
1900 return false;
1901
1902 if (cgOpts.DirectAccessExternalData) {
1903 // If -fdirect-access-external-data (default for -fno-pic), set dso_local
1904 // for non-thread-local variables. If the symbol is not defined in the
1905 // executable, a copy relocation will be needed at link time. dso_local is
1906 // excluded for thread-local variables because they generally don't support
1907 // copy relocations.
1908 if (auto globalOp = dyn_cast<cir::GlobalOp>(gv.getOperation())) {
1909 // Assume variables are not thread-local until that support is added.
1911 return true;
1912 }
1913
1914 // -fno-pic sets dso_local on a function declaration to allow direct
1915 // accesses when taking its address (similar to a data symbol). If the
1916 // function is not defined in the executable, a canonical PLT entry will be
1917 // needed at link time. -fno-direct-access-external-data can avoid the
1918 // canonical PLT entry. We don't generalize this condition to -fpie/-fpic as
1919 // it could just cause trouble without providing perceptible benefits.
1920 if (isa<cir::FuncOp>(gv) && !cgOpts.NoPLT && rm == llvm::Reloc::Static)
1921 return true;
1922 }
1923
1924 // If we can use copy relocations we can assume it is local.
1925
1926 // Otherwise don't assume it is local.
1927
1928 return false;
1929}
1930
1931void CIRGenModule::setGlobalVisibility(mlir::Operation *gv,
1932 const NamedDecl *d) const {
1934}
1935
1936void CIRGenModule::setDSOLocal(cir::CIRGlobalValueInterface gv) const {
1937 gv.setDSOLocal(shouldAssumeDSOLocal(*this, gv));
1938}
1939
1940void CIRGenModule::setDSOLocal(mlir::Operation *op) const {
1941 if (auto globalValue = dyn_cast<cir::CIRGlobalValueInterface>(op))
1942 setDSOLocal(globalValue);
1943}
1944
1945void CIRGenModule::setGVProperties(mlir::Operation *op,
1946 const NamedDecl *d) const {
1948 setGVPropertiesAux(op, d);
1949}
1950
1951void CIRGenModule::setGVPropertiesAux(mlir::Operation *op,
1952 const NamedDecl *d) const {
1953 setGlobalVisibility(op, d);
1954 setDSOLocal(op);
1956}
1957
1959 switch (getCodeGenOpts().getDefaultTLSModel()) {
1961 return cir::TLS_Model::GeneralDynamic;
1963 return cir::TLS_Model::LocalDynamic;
1965 return cir::TLS_Model::InitialExec;
1967 return cir::TLS_Model::LocalExec;
1968 }
1969 llvm_unreachable("Invalid TLS model!");
1970}
1971
1972void CIRGenModule::setTLSMode(mlir::Operation *op, const VarDecl &d) {
1973 assert(d.getTLSKind() && "setting TLS mode on non-TLS var!");
1974
1975 cir::TLS_Model tlm = getDefaultCIRTLSModel();
1976
1977 // Override the TLS model if it is explicitly specified.
1978 if (d.getAttr<TLSModelAttr>())
1979 errorNYI(d.getSourceRange(), "TLS model attribute");
1980
1981 auto global = cast<cir::GlobalOp>(op);
1982 global.setTlsModel(tlm);
1983}
1984
1986 cir::FuncOp func,
1987 bool isIncompleteFunction,
1988 bool isThunk) {
1989 // NOTE(cir): Original CodeGen checks if this is an intrinsic. In CIR we
1990 // represent them in dedicated ops. The correct attributes are ensured during
1991 // translation to LLVM. Thus, we don't need to check for them here.
1992
1995
1996 // TODO(cir): This needs a lot of work to better match CodeGen. That
1997 // ultimately ends up in setGlobalVisibility, which already has the linkage of
1998 // the LLVM GV (corresponding to our FuncOp) computed, so it doesn't have to
1999 // recompute it here. This is a minimal fix for now.
2000 if (!isLocalLinkage(getFunctionLinkage(globalDecl))) {
2001 const Decl *decl = globalDecl.getDecl();
2002 func.setGlobalVisibilityAttr(getGlobalVisibilityAttrFromDecl(decl));
2003 }
2004
2005 // If we plan on emitting this inline builtin, we can't treat it as a builtin.
2006 const auto *fd = cast<FunctionDecl>(globalDecl.getDecl());
2007 if (fd->isInlineBuiltinDeclaration()) {
2008 const FunctionDecl *fdBody;
2009 bool hasBody = fd->hasBody(fdBody);
2010 (void)hasBody;
2011 assert(hasBody && "Inline builtin declarations should always have an "
2012 "available body!");
2014 }
2015}
2016
2018 const clang::FunctionDecl *decl, cir::FuncOp f) {
2021
2022 std::optional<cir::InlineKind> existingInlineKind = f.getInlineKind();
2023 bool isNoInline =
2024 existingInlineKind && *existingInlineKind == cir::InlineKind::NoInline;
2025 bool isAlwaysInline = existingInlineKind &&
2026 *existingInlineKind == cir::InlineKind::AlwaysInline;
2027 if (!decl) {
2028 assert(!cir::MissingFeatures::hlsl());
2029
2030 if (!isAlwaysInline &&
2031 codeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) {
2032 // If inlining is disabled and we don't have a declaration to control
2033 // inlining, mark the function as 'noinline' unless it is explicitly
2034 // marked as 'alwaysinline'.
2035 f.setInlineKind(cir::InlineKind::NoInline);
2036 }
2037
2038 return;
2039 }
2040
2047 assert(!cir::MissingFeatures::hlsl());
2048
2049 // Handle inline attributes
2050 if (decl->hasAttr<NoInlineAttr>() && !isAlwaysInline) {
2051 // Add noinline if the function isn't always_inline.
2052 f.setInlineKind(cir::InlineKind::NoInline);
2053 } else if (decl->hasAttr<AlwaysInlineAttr>() && !isNoInline) {
2054 // Don't override AlwaysInline with NoInline, or vice versa, since we can't
2055 // specify both in IR.
2056 f.setInlineKind(cir::InlineKind::AlwaysInline);
2057 } else if (codeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) {
2058 // If inlining is disabled, force everything that isn't always_inline
2059 // to carry an explicit noinline attribute.
2060 if (!isAlwaysInline) {
2061 f.setInlineKind(cir::InlineKind::NoInline);
2062 }
2063 } else {
2064 // Otherwise, propagate the inline hint attribute and potentially use its
2065 // absence to mark things as noinline.
2066 // Search function and template pattern redeclarations for inline.
2067 if (auto *fd = dyn_cast<FunctionDecl>(decl)) {
2068 // TODO: Share this checkForInline implementation with classic codegen.
2069 // This logic is likely to change over time, so sharing would help ensure
2070 // consistency.
2071 auto checkForInline = [](const FunctionDecl *decl) {
2072 auto checkRedeclForInline = [](const FunctionDecl *redecl) {
2073 return redecl->isInlineSpecified();
2074 };
2075 if (any_of(decl->redecls(), checkRedeclForInline))
2076 return true;
2077 const FunctionDecl *pattern = decl->getTemplateInstantiationPattern();
2078 if (!pattern)
2079 return false;
2080 return any_of(pattern->redecls(), checkRedeclForInline);
2081 };
2082 if (checkForInline(fd)) {
2083 f.setInlineKind(cir::InlineKind::InlineHint);
2084 } else if (codeGenOpts.getInlining() ==
2086 !fd->isInlined() && !isAlwaysInline) {
2087 f.setInlineKind(cir::InlineKind::NoInline);
2088 }
2089 }
2090 }
2091
2093}
2094
2096 StringRef mangledName, mlir::Type funcType, GlobalDecl gd, bool forVTable,
2097 bool dontDefer, bool isThunk, ForDefinition_t isForDefinition,
2098 mlir::ArrayAttr extraAttrs) {
2099 const Decl *d = gd.getDecl();
2100
2101 if (isThunk)
2102 errorNYI(d->getSourceRange(), "getOrCreateCIRFunction: thunk");
2103
2104 // In what follows, we continue past 'errorNYI' as if nothing happened because
2105 // the rest of the implementation is better than doing nothing.
2106
2107 if (const auto *fd = cast_or_null<FunctionDecl>(d)) {
2108 // For the device mark the function as one that should be emitted.
2109 if (getLangOpts().OpenMPIsTargetDevice && fd->isDefined() && !dontDefer &&
2110 !isForDefinition)
2111 errorNYI(fd->getSourceRange(),
2112 "getOrCreateCIRFunction: OpenMP target function");
2113
2114 // Any attempts to use a MultiVersion function should result in retrieving
2115 // the iFunc instead. Name mangling will handle the rest of the changes.
2116 if (fd->isMultiVersion())
2117 errorNYI(fd->getSourceRange(), "getOrCreateCIRFunction: multi-version");
2118 }
2119
2120 // Lookup the entry, lazily creating it if necessary.
2121 mlir::Operation *entry = getGlobalValue(mangledName);
2122 if (entry) {
2123 assert(mlir::isa<cir::FuncOp>(entry));
2124
2126
2127 // Handle dropped DLL attributes.
2128 if (d && !d->hasAttr<DLLImportAttr>() && !d->hasAttr<DLLExportAttr>()) {
2130 setDSOLocal(entry);
2131 }
2132
2133 // If there are two attempts to define the same mangled name, issue an
2134 // error.
2135 auto fn = cast<cir::FuncOp>(entry);
2136 if (isForDefinition && fn && !fn.isDeclaration()) {
2137 errorNYI(d->getSourceRange(), "Duplicate function definition");
2138 }
2139 if (fn && fn.getFunctionType() == funcType) {
2140 return fn;
2141 }
2142
2143 if (!isForDefinition) {
2144 return fn;
2145 }
2146
2147 // TODO(cir): classic codegen checks here if this is a llvm::GlobalAlias.
2148 // How will we support this?
2149 }
2150
2151 auto *funcDecl = llvm::cast_or_null<FunctionDecl>(gd.getDecl());
2152 bool invalidLoc = !funcDecl ||
2153 funcDecl->getSourceRange().getBegin().isInvalid() ||
2154 funcDecl->getSourceRange().getEnd().isInvalid();
2155 cir::FuncOp funcOp = createCIRFunction(
2156 invalidLoc ? theModule->getLoc() : getLoc(funcDecl->getSourceRange()),
2157 mangledName, mlir::cast<cir::FuncType>(funcType), funcDecl);
2158
2159 // If we already created a function with the same mangled name (but different
2160 // type) before, take its name and add it to the list of functions to be
2161 // replaced with F at the end of CodeGen.
2162 //
2163 // This happens if there is a prototype for a function (e.g. "int f()") and
2164 // then a definition of a different type (e.g. "int f(int x)").
2165 if (entry) {
2166
2167 // Fetch a generic symbol-defining operation and its uses.
2168 auto symbolOp = mlir::cast<mlir::SymbolOpInterface>(entry);
2169
2170 // This might be an implementation of a function without a prototype, in
2171 // which case, try to do special replacement of calls which match the new
2172 // prototype. The really key thing here is that we also potentially drop
2173 // arguments from the call site so as to make a direct call, which makes the
2174 // inliner happier and suppresses a number of optimizer warnings (!) about
2175 // dropping arguments.
2176 if (symbolOp.getSymbolUses(symbolOp->getParentOp()))
2178
2179 // Obliterate no-proto declaration.
2180 entry->erase();
2181 }
2182
2183 if (d)
2184 setFunctionAttributes(gd, funcOp, /*isIncompleteFunction=*/false, isThunk);
2185
2186 // 'dontDefer' actually means don't move this to the deferredDeclsToEmit list.
2187 if (dontDefer) {
2188 // TODO(cir): This assertion will need an additional condition when we
2189 // support incomplete functions.
2190 assert(funcOp.getFunctionType() == funcType);
2191 return funcOp;
2192 }
2193
2194 // All MSVC dtors other than the base dtor are linkonce_odr and delegate to
2195 // each other bottoming out wiht the base dtor. Therefore we emit non-base
2196 // dtors on usage, even if there is no dtor definition in the TU.
2197 if (isa_and_nonnull<CXXDestructorDecl>(d) &&
2198 getCXXABI().useThunkForDtorVariant(cast<CXXDestructorDecl>(d),
2199 gd.getDtorType()))
2200 errorNYI(d->getSourceRange(), "getOrCreateCIRFunction: dtor");
2201
2202 // This is the first use or definition of a mangled name. If there is a
2203 // deferred decl with this name, remember that we need to emit it at the end
2204 // of the file.
2205 auto ddi = deferredDecls.find(mangledName);
2206 if (ddi != deferredDecls.end()) {
2207 // Move the potentially referenced deferred decl to the
2208 // DeferredDeclsToEmit list, and remove it from DeferredDecls (since we
2209 // don't need it anymore).
2210 addDeferredDeclToEmit(ddi->second);
2211 deferredDecls.erase(ddi);
2212
2213 // Otherwise, there are cases we have to worry about where we're using a
2214 // declaration for which we must emit a definition but where we might not
2215 // find a top-level definition.
2216 // - member functions defined inline in their classes
2217 // - friend functions defined inline in some class
2218 // - special member functions with implicit definitions
2219 // If we ever change our AST traversal to walk into class methods, this
2220 // will be unnecessary.
2221 //
2222 // We also don't emit a definition for a function if it's going to be an
2223 // entry in a vtable, unless it's already marked as used.
2224 } else if (getLangOpts().CPlusPlus && d) {
2225 // Look for a declaration that's lexically in a record.
2226 for (const auto *fd = cast<FunctionDecl>(d)->getMostRecentDecl(); fd;
2227 fd = fd->getPreviousDecl()) {
2228 if (isa<CXXRecordDecl>(fd->getLexicalDeclContext())) {
2229 if (fd->doesThisDeclarationHaveABody()) {
2231 break;
2232 }
2233 }
2234 }
2235 }
2236
2237 return funcOp;
2238}
2239
2240cir::FuncOp
2241CIRGenModule::createCIRFunction(mlir::Location loc, StringRef name,
2242 cir::FuncType funcType,
2243 const clang::FunctionDecl *funcDecl) {
2244 cir::FuncOp func;
2245 {
2246 mlir::OpBuilder::InsertionGuard guard(builder);
2247
2248 // Some global emissions are triggered while emitting a function, e.g.
2249 // void s() { x.method() }
2250 //
2251 // Be sure to insert a new function before a current one.
2252 CIRGenFunction *cgf = this->curCGF;
2253 if (cgf)
2254 builder.setInsertionPoint(cgf->curFn);
2255
2256 func = cir::FuncOp::create(builder, loc, name, funcType);
2257
2259
2260 if (funcDecl && !funcDecl->hasPrototype())
2261 func.setNoProto(true);
2262
2263 assert(func.isDeclaration() && "expected empty body");
2264
2265 // A declaration gets private visibility by default, but external linkage
2266 // as the default linkage.
2267 func.setLinkageAttr(cir::GlobalLinkageKindAttr::get(
2268 &getMLIRContext(), cir::GlobalLinkageKind::ExternalLinkage));
2269 mlir::SymbolTable::setSymbolVisibility(
2270 func, mlir::SymbolTable::Visibility::Private);
2271
2273
2274 // Mark C++ special member functions (Constructor, Destructor etc.)
2275 setCXXSpecialMemberAttr(func, funcDecl);
2276
2277 if (!cgf)
2278 theModule.push_back(func);
2279
2280 if (this->getLangOpts().OpenACC) {
2281 // We only have to handle this attribute, since OpenACCAnnotAttrs are
2282 // handled via the end-of-TU work.
2283 for (const auto *attr :
2284 funcDecl->specific_attrs<OpenACCRoutineDeclAttr>())
2285 emitOpenACCRoutineDecl(funcDecl, func, attr->getLocation(),
2286 attr->Clauses);
2287 }
2288 }
2289 return func;
2290}
2291
2292cir::FuncOp
2293CIRGenModule::createCIRBuiltinFunction(mlir::Location loc, StringRef name,
2294 cir::FuncType ty,
2295 const clang::FunctionDecl *fd) {
2296 cir::FuncOp fnOp = createCIRFunction(loc, name, ty, fd);
2297 fnOp.setBuiltin(true);
2298 return fnOp;
2299}
2300
2301static cir::CtorKind getCtorKindFromDecl(const CXXConstructorDecl *ctor) {
2302 if (ctor->isDefaultConstructor())
2303 return cir::CtorKind::Default;
2304 if (ctor->isCopyConstructor())
2305 return cir::CtorKind::Copy;
2306 if (ctor->isMoveConstructor())
2307 return cir::CtorKind::Move;
2308 return cir::CtorKind::Custom;
2309}
2310
2311static cir::AssignKind getAssignKindFromDecl(const CXXMethodDecl *method) {
2312 if (method->isCopyAssignmentOperator())
2313 return cir::AssignKind::Copy;
2314 if (method->isMoveAssignmentOperator())
2315 return cir::AssignKind::Move;
2316 llvm_unreachable("not a copy or move assignment operator");
2317}
2318
2320 cir::FuncOp funcOp, const clang::FunctionDecl *funcDecl) {
2321 if (!funcDecl)
2322 return;
2323
2324 if (const auto *dtor = dyn_cast<CXXDestructorDecl>(funcDecl)) {
2325 auto cxxDtor = cir::CXXDtorAttr::get(
2326 convertType(getASTContext().getCanonicalTagType(dtor->getParent())),
2327 dtor->isTrivial());
2328 funcOp.setCxxSpecialMemberAttr(cxxDtor);
2329 return;
2330 }
2331
2332 if (const auto *ctor = dyn_cast<CXXConstructorDecl>(funcDecl)) {
2333 cir::CtorKind kind = getCtorKindFromDecl(ctor);
2334 auto cxxCtor = cir::CXXCtorAttr::get(
2335 convertType(getASTContext().getCanonicalTagType(ctor->getParent())),
2336 kind, ctor->isTrivial());
2337 funcOp.setCxxSpecialMemberAttr(cxxCtor);
2338 return;
2339 }
2340
2341 const auto *method = dyn_cast<CXXMethodDecl>(funcDecl);
2342 if (method && (method->isCopyAssignmentOperator() ||
2343 method->isMoveAssignmentOperator())) {
2344 cir::AssignKind assignKind = getAssignKindFromDecl(method);
2345 auto cxxAssign = cir::CXXAssignAttr::get(
2346 convertType(getASTContext().getCanonicalTagType(method->getParent())),
2347 assignKind, method->isTrivial());
2348 funcOp.setCxxSpecialMemberAttr(cxxAssign);
2349 return;
2350 }
2351}
2352
2353cir::FuncOp CIRGenModule::createRuntimeFunction(cir::FuncType ty,
2354 StringRef name, mlir::ArrayAttr,
2355 [[maybe_unused]] bool isLocal,
2356 bool assumeConvergent) {
2357 if (assumeConvergent)
2358 errorNYI("createRuntimeFunction: assumeConvergent");
2359 if (isLocal)
2360 errorNYI("createRuntimeFunction: local");
2361
2362 cir::FuncOp entry = getOrCreateCIRFunction(name, ty, GlobalDecl(),
2363 /*forVtable=*/false);
2364
2365 if (entry) {
2366 // TODO(cir): set the attributes of the function.
2370 entry.setDSOLocal(true);
2371 }
2372
2373 return entry;
2374}
2375
2376mlir::SymbolTable::Visibility
2378 // MLIR doesn't accept public symbols declarations (only
2379 // definitions).
2380 if (op.isDeclaration())
2381 return mlir::SymbolTable::Visibility::Private;
2382 return getMLIRVisibilityFromCIRLinkage(op.getLinkage());
2383}
2384
2385mlir::SymbolTable::Visibility
2387 switch (glk) {
2388 case cir::GlobalLinkageKind::InternalLinkage:
2389 case cir::GlobalLinkageKind::PrivateLinkage:
2390 return mlir::SymbolTable::Visibility::Private;
2391 case cir::GlobalLinkageKind::ExternalLinkage:
2392 case cir::GlobalLinkageKind::ExternalWeakLinkage:
2393 case cir::GlobalLinkageKind::LinkOnceODRLinkage:
2394 case cir::GlobalLinkageKind::AvailableExternallyLinkage:
2395 case cir::GlobalLinkageKind::CommonLinkage:
2396 case cir::GlobalLinkageKind::WeakAnyLinkage:
2397 case cir::GlobalLinkageKind::WeakODRLinkage:
2398 return mlir::SymbolTable::Visibility::Public;
2399 default: {
2400 llvm::errs() << "visibility not implemented for '"
2401 << stringifyGlobalLinkageKind(glk) << "'\n";
2402 assert(0 && "not implemented");
2403 }
2404 }
2405 llvm_unreachable("linkage should be handled above!");
2406}
2407
2409 clang::VisibilityAttr::VisibilityType visibility) {
2410 switch (visibility) {
2411 case clang::VisibilityAttr::VisibilityType::Default:
2412 return cir::VisibilityKind::Default;
2413 case clang::VisibilityAttr::VisibilityType::Hidden:
2414 return cir::VisibilityKind::Hidden;
2415 case clang::VisibilityAttr::VisibilityType::Protected:
2416 return cir::VisibilityKind::Protected;
2417 }
2418 llvm_unreachable("unexpected visibility value");
2419}
2420
2421cir::VisibilityAttr
2423 const clang::VisibilityAttr *va = decl->getAttr<clang::VisibilityAttr>();
2424 cir::VisibilityAttr cirVisibility =
2425 cir::VisibilityAttr::get(&getMLIRContext());
2426 if (va) {
2427 cirVisibility = cir::VisibilityAttr::get(
2428 &getMLIRContext(),
2429 getGlobalVisibilityKindFromClangVisibility(va->getVisibility()));
2430 }
2431 return cirVisibility;
2432}
2433
2435 emitDeferred();
2436 applyReplacements();
2437
2438 theModule->setAttr(cir::CIRDialect::getModuleLevelAsmAttrName(),
2439 builder.getArrayAttr(globalScopeAsm));
2440
2441 // There's a lot of code that is not implemented yet.
2443}
2444
2445void CIRGenModule::emitAliasForGlobal(StringRef mangledName,
2446 mlir::Operation *op, GlobalDecl aliasGD,
2447 cir::FuncOp aliasee,
2448 cir::GlobalLinkageKind linkage) {
2449
2450 auto *aliasFD = dyn_cast<FunctionDecl>(aliasGD.getDecl());
2451 assert(aliasFD && "expected FunctionDecl");
2452
2453 // The aliasee function type is different from the alias one, this difference
2454 // is specific to CIR because in LLVM the ptr types are already erased at this
2455 // point.
2456 const CIRGenFunctionInfo &fnInfo =
2458 cir::FuncType fnType = getTypes().getFunctionType(fnInfo);
2459
2460 cir::FuncOp alias =
2462 mangledName, fnType, aliasFD);
2463 alias.setAliasee(aliasee.getName());
2464 alias.setLinkage(linkage);
2465 // Declarations cannot have public MLIR visibility, just mark them private
2466 // but this really should have no meaning since CIR should not be using
2467 // this information to derive linkage information.
2468 mlir::SymbolTable::setSymbolVisibility(
2469 alias, mlir::SymbolTable::Visibility::Private);
2470
2471 // Alias constructors and destructors are always unnamed_addr.
2473
2474 // Switch any previous uses to the alias.
2475 if (op) {
2476 errorNYI(aliasFD->getSourceRange(), "emitAliasForGlobal: previous uses");
2477 } else {
2478 // Name already set by createCIRFunction
2479 }
2480
2481 // Finally, set up the alias with its proper name and attributes.
2482 setCommonAttributes(aliasGD, alias);
2483}
2484
2486 return genTypes.convertType(type);
2487}
2488
2490 // Verify the module after we have finished constructing it, this will
2491 // check the structural properties of the IR and invoke any specific
2492 // verifiers we have on the CIR operations.
2493 return mlir::verify(theModule).succeeded();
2494}
2495
2496mlir::Attribute CIRGenModule::getAddrOfRTTIDescriptor(mlir::Location loc,
2497 QualType ty, bool forEh) {
2498 // Return a bogus pointer if RTTI is disabled, unless it's for EH.
2499 // FIXME: should we even be calling this method if RTTI is disabled
2500 // and it's not for EH?
2501 if (!shouldEmitRTTI(forEh))
2502 return builder.getConstNullPtrAttr(builder.getUInt8PtrTy());
2503
2504 if (forEh && ty->isObjCObjectPointerType() &&
2505 langOpts.ObjCRuntime.isGNUFamily()) {
2506 errorNYI(loc, "getAddrOfRTTIDescriptor: Objc PtrType & Objc RT GUN");
2507 return {};
2508 }
2509
2510 return getCXXABI().getAddrOfRTTIDescriptor(loc, ty);
2511}
2512
2513// TODO(cir): this can be shared with LLVM codegen.
2515 const CXXRecordDecl *derivedClass,
2516 llvm::iterator_range<CastExpr::path_const_iterator> path) {
2517 CharUnits offset = CharUnits::Zero();
2518
2519 const ASTContext &astContext = getASTContext();
2520 const CXXRecordDecl *rd = derivedClass;
2521
2522 for (const CXXBaseSpecifier *base : path) {
2523 assert(!base->isVirtual() && "Should not see virtual bases here!");
2524
2525 // Get the layout.
2526 const ASTRecordLayout &layout = astContext.getASTRecordLayout(rd);
2527
2528 const auto *baseDecl = base->getType()->castAsCXXRecordDecl();
2529
2530 // Add the offset.
2531 offset += layout.getBaseClassOffset(baseDecl);
2532
2533 rd = baseDecl;
2534 }
2535
2536 return offset;
2537}
2538
2540 llvm::StringRef feature) {
2541 unsigned diagID = diags.getCustomDiagID(
2542 DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0");
2543 return diags.Report(loc, diagID) << feature;
2544}
2545
2547 llvm::StringRef feature) {
2548 return errorNYI(loc.getBegin(), feature) << loc;
2549}
2550
2551void CIRGenModule::mapBlockAddress(cir::BlockAddrInfoAttr blockInfo,
2552 cir::LabelOp label) {
2553 [[maybe_unused]] auto result =
2554 blockAddressInfoToLabel.try_emplace(blockInfo, label);
2555 assert(result.second &&
2556 "attempting to map a blockaddress info that is already mapped");
2557}
2558
2559void CIRGenModule::mapUnresolvedBlockAddress(cir::BlockAddressOp op) {
2560 [[maybe_unused]] auto result = unresolvedBlockAddressToLabel.insert(op);
2561 assert(result.second &&
2562 "attempting to map a blockaddress operation that is already mapped");
2563}
2564
2565void CIRGenModule::mapResolvedBlockAddress(cir::BlockAddressOp op,
2566 cir::LabelOp label) {
2567 [[maybe_unused]] auto result = blockAddressToLabel.try_emplace(op, label);
2568 assert(result.second &&
2569 "attempting to map a blockaddress operation that is already mapped");
2570}
2571
2573 cir::LabelOp newLabel) {
2574 auto *it = blockAddressToLabel.find(op);
2575 assert(it != blockAddressToLabel.end() &&
2576 "trying to update a blockaddress not previously mapped");
2577 assert(!it->second && "blockaddress already has a resolved label");
2578
2579 it->second = newLabel;
2580}
2581
2582cir::LabelOp
2583CIRGenModule::lookupBlockAddressInfo(cir::BlockAddrInfoAttr blockInfo) {
2584 return blockAddressInfoToLabel.lookup(blockInfo);
2585}
Defines the clang::ASTContext interface.
static bool shouldAssumeDSOLocal(const CIRGenModule &cgm, cir::CIRGlobalValueInterface gv)
static cir::AssignKind getAssignKindFromDecl(const CXXMethodDecl *method)
static bool shouldBeInCOMDAT(CIRGenModule &cgm, const Decl &d)
static std::string getMangledNameImpl(CIRGenModule &cgm, GlobalDecl gd, const NamedDecl *nd)
static cir::GlobalOp generateStringLiteral(mlir::Location loc, mlir::TypedAttr c, cir::GlobalLinkageKind lt, CIRGenModule &cgm, StringRef globalName, CharUnits alignment)
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)
This file defines OpenACC nodes for declarative directives.
Defines the SourceManager interface.
__device__ __2f16 float __ockl_bool s
__device__ __2f16 float c
cir::PointerType getPointerTo(mlir::Type ty)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:220
@ 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...
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...
const TargetInfo & getTargetInfo() const
Definition ASTContext.h:895
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.
Implements C++ ABI-specific code generation functions.
virtual mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc, QualType ty)=0
virtual void emitCXXConstructors(const clang::CXXConstructorDecl *d)=0
Emit constructor variants required by this ABI.
virtual void emitCXXDestructors(const clang::CXXDestructorDecl *d)=0
Emit dtor variants required by this ABI.
clang::MangleContext & getMangleContext()
Gets the mangle context.
virtual cir::GlobalLinkageKind getCXXDestructorLinkage(GVALinkage linkage, const CXXDestructorDecl *dtor, CXXDtorType dt) const
cir::FuncOp generateCode(clang::GlobalDecl gd, cir::FuncOp fn, cir::FuncType funcType)
void emitVariablyModifiedType(QualType ty)
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.
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)
cir::FuncOp createRuntimeFunction(cir::FuncType ty, llvm::StringRef name, mlir::ArrayAttr={}, bool isLocal=false, bool assumeConvergent=false)
llvm::DenseMap< cir::BlockAddrInfoAttr, cir::LabelOp > blockAddressInfoToLabel
Map BlockAddrInfoAttr (function name, label name) to the corresponding CIR LabelOp.
void emitTopLevelDecl(clang::Decl *decl)
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 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 emitGlobalDefinition(clang::GlobalDecl gd, mlir::Operation *op=nullptr)
void mapResolvedBlockAddress(cir::BlockAddressOp op, cir::LabelOp)
mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc, QualType ty, bool forEH=false)
Get the address of the RTTI descriptor for the given type.
clang::CharUnits getNaturalTypeAlignment(clang::QualType t, LValueBaseInfo *baseInfo)
FIXME: this could likely be a common helper and not necessarily related with codegen.
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
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 emitGlobalDecl(const clang::GlobalDecl &d)
Helper for emitDeferred to apply actual codegen.
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::ArrayAttr extraAttrs={})
void emitGlobalVarDefinition(const clang::VarDecl *vd, bool isTentative=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.
std::map< llvm::StringRef, clang::GlobalDecl > deferredDecls
This contains all the decls which have definitions but which are deferred for emission and therefore ...
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
const clang::LangOptions & getLangOpts() const
void emitOpenACCRoutineDecl(const clang::FunctionDecl *funcDecl, cir::FuncOp func, SourceLocation pragmaLoc, ArrayRef< const OpenACCClause * > clauses)
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)
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
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::Operation * getGlobalValue(llvm::StringRef ref)
mlir::ModuleOp getModule() const
cir::GlobalLinkageKind getCIRLinkageForDeclarator(const DeclaratorDecl *dd, GVALinkage linkage, bool isConstantVariable)
mlir::MLIRContext & getMLIRContext()
mlir::Operation * getAddrOfGlobal(clang::GlobalDecl gd, ForDefinition_t isForDefinition=NotForDefinition)
static cir::GlobalOp createGlobalOp(CIRGenModule &cgm, mlir::Location loc, llvm::StringRef name, mlir::Type t, bool isConstant=false, mlir::Operation *insertPoint=nullptr)
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.
void emitDeclContext(const DeclContext *dc)
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.
void emitGlobalFunctionDefinition(clang::GlobalDecl gd, mlir::Operation *op)
CIRGenVTables & getVTables()
void setFunctionLinkage(GlobalDecl gd, cir::FuncOp f)
std::vector< clang::GlobalDecl > deferredDeclsToEmit
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 cir::TargetAddressSpaceAttr getCIRAllocaAddressSpace() const
Get the address space for alloca.
Definition TargetInfo.h:51
Represents a base class of a C++ class.
Definition DeclCXX.h:146
Represents a C++ constructor within a class.
Definition DeclCXX.h:2604
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:3013
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:3008
bool isDefaultConstructor() const
Whether this constructor is a default constructor (C++ [class.ctor]p5), which can be used to default-...
Definition DeclCXX.cpp:2999
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2129
bool isMoveAssignmentOperator() const
Determine whether this is a move assignment operator.
Definition DeclCXX.cpp:2735
bool isCopyAssignmentOperator() const
Determine whether this is a copy-assignment operator, regardless of whether it was declared implicitl...
Definition DeclCXX.cpp:2714
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:2325
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:3760
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
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
ExplicitCastExpr - An explicit cast written in the source code.
Definition Expr.h:3862
This represents one expression.
Definition Expr.h:112
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
QualType getType() const
Definition Expr.h:144
Represents a member of a struct/union/class.
Definition Decl.h:3160
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:2000
bool hasPrototype() const
Whether this function has a prototype, either because one was explicitly written or because it was "i...
Definition Decl.h:2443
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:3195
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4450
CallingConv getCallConv() const
Definition TypeBase.h:4805
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...
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:186
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
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:8404
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8318
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition TypeBase.h:8351
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
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:338
StringLiteral - This represents a string literal expression, e.g.
Definition Expr.h:1799
StringRef getString() const
Definition Expr.h:1867
unsigned getCharByteWidth() const
Definition Expr.h:1910
Represents the declaration of a struct/union/class/enum.
Definition Decl.h:3717
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.
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition Type.h:41
bool isPointerType() const
Definition TypeBase.h:8515
bool isReferenceType() const
Definition TypeBase.h:8539
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition TypeBase.h:2800
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
Definition Type.cpp:2435
bool isObjCObjectPointerType() const
Definition TypeBase.h:8684
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9091
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition Expr.h:2244
Expr * getSubExpr() const
Definition Expr.h:2285
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
TLSKind getTLSKind() const
Definition Decl.cpp:2175
bool hasInit() const
Definition Decl.cpp:2405
DefinitionKind isThisDeclarationADefinition(ASTContext &) const
Check whether this declaration is a definition.
Definition Decl.cpp:2267
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:2197
bool hasFlexibleArrayInit(const ASTContext &Ctx) const
Whether this variable has a flexible array member initialized with one or more elements.
Definition Decl.cpp:2869
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition Decl.h:1226
bool hasConstantInitialization() const
Determine whether this variable has constant initialization.
Definition Decl.cpp:2655
VarDecl * getDefinition(ASTContext &)
Get the real (not just tentative) definition for this declaration.
Definition Decl.cpp:2373
QualType::DestructionKind needsDestruction(const ASTContext &Ctx) const
Would the destruction of this variable have any effect, and if so, what kind?
Definition Decl.cpp:2858
const Expr * getInit() const
Definition Decl.h:1368
bool hasExternalStorage() const
Returns true if a variable has extern or private_extern storage.
Definition Decl.h:1217
@ TLS_Dynamic
TLS with a dynamic initializer.
Definition Decl.h:952
@ TLS_None
Not a TLS variable.
Definition Decl.h:946
@ Definition
This declaration is definitely a definition.
Definition Decl.h:1301
DefinitionKind hasDefinition(ASTContext &) const
Check whether this variable is defined in this translation unit.
Definition Decl.cpp:2382
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:2786
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Definition Decl.h:1358
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 ...
CIRGenCXXABI * CreateCIRGenItaniumCXXABI(CIRGenModule &cgm)
Creates and Itanium-family ABI.
std::unique_ptr< TargetCIRGenInfo > createX8664TargetCIRGenInfo(CIRGenTypes &cgt)
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const internal::VariadicDynCastAllOfMatcher< Decl, FieldDecl > fieldDecl
Matches field declarations.
const internal::VariadicAllOfMatcher< Decl > decl
Matches declarations.
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
@ SD_Thread
Thread storage duration.
Definition Specifiers.h:342
@ SD_Static
Static storage duration.
Definition Specifiers.h:343
@ 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 alignCXXRecordDecl()
static bool opFuncArmNewAttr()
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 setFunctionAttributes()
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 setTargetAttributes()
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 deferredVtables()
static bool cudaSupport()
static bool opFuncMaybeHandleStaticInExternC()
static bool generateDebugInfo()
static bool targetCIRGenInfoOS()
static bool opFuncCPUAndFeaturesAttributes()
static bool maybeHandleStaticInExternC()
static bool setLLVMFunctionFEnvAttributes()
cir::TargetAddressSpaceAttr cirAllocaAddressSpace
mlir::Type uCharTy
ClangIR char.
cir::PointerType allocaInt8PtrTy
void* in alloca address space
cir::PointerType voidPtrTy
void* in address space 0
LangStandard - Information about the properties of a particular language standard.