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