clang 23.0.0git
CIRGenModule.cpp
Go to the documentation of this file.
1//===- CIRGenModule.cpp - Per-Module state for CIR generation -------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This is the internal per-translation-unit state used for CIR translation.
10//
11//===----------------------------------------------------------------------===//
12
13#include "CIRGenModule.h"
14#include "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 // Calculate constant storage flag before creating the global. This was moved
666 // from after the global creation to ensure the constant flag is set correctly
667 // at creation time, matching the logic used in emitCXXGlobalVarDeclInit.
668 bool isConstant = false;
669 if (d) {
670 bool needsDtor =
672 isConstant = d->getType().isConstantStorage(
673 astContext, /*ExcludeCtor=*/true, /*ExcludeDtor=*/!needsDtor);
674 }
675
676 // mlir::SymbolTable::Visibility::Public is the default, no need to explicitly
677 // mark it as such.
678 cir::GlobalOp gv =
679 CIRGenModule::createGlobalOp(*this, loc, mangledName, ty, isConstant,
680 /*insertPoint=*/entry.getOperation());
681
682 // This is the first use or definition of a mangled name. If there is a
683 // deferred decl with this name, remember that we need to emit it at the end
684 // of the file.
685 auto ddi = deferredDecls.find(mangledName);
686 if (ddi != deferredDecls.end()) {
687 // Move the potentially referenced deferred decl to the DeferredDeclsToEmit
688 // list, and remove it from DeferredDecls (since we don't need it anymore).
689 addDeferredDeclToEmit(ddi->second);
690 deferredDecls.erase(ddi);
691 }
692
693 // Handle things which are present even on external declarations.
694 if (d) {
695 if (langOpts.OpenMP && !langOpts.OpenMPSimd)
696 errorNYI(d->getSourceRange(), "OpenMP target global variable");
697
698 gv.setAlignmentAttr(getSize(astContext.getDeclAlign(d)));
699
700 setLinkageForGV(gv, d);
701
702 if (d->getTLSKind()) {
704 errorNYI(d->getSourceRange(), "TLS dynamic");
705 setTLSMode(gv, *d);
706 }
707
708 setGVProperties(gv, d);
709
710 // If required by the ABI, treat declarations of static data members with
711 // inline initializers as definitions.
712 if (astContext.isMSStaticDataMemberInlineDefinition(d))
713 errorNYI(d->getSourceRange(), "MS static data member inline definition");
714
716 gv.setGlobalVisibilityAttr(getGlobalVisibilityAttrFromDecl(d));
717
718 // Handle XCore specific ABI requirements.
719 if (getTriple().getArch() == llvm::Triple::xcore)
720 errorNYI(d->getSourceRange(), "XCore specific ABI requirements");
721
722 // Check if we a have a const declaration with an initializer, we may be
723 // able to emit it as available_externally to expose it's value to the
724 // optimizer.
725 if (getLangOpts().CPlusPlus && gv.isPublic() &&
726 d->getType().isConstQualified() && gv.isDeclaration() &&
727 !d->hasDefinition() && d->hasInit() && !d->hasAttr<DLLImportAttr>())
729 "external const declaration with initializer");
730 }
731
732 return gv;
733}
734
735cir::GlobalOp
737 ForDefinition_t isForDefinition) {
738 assert(d->hasGlobalStorage() && "Not a global variable");
739 QualType astTy = d->getType();
740 if (!ty)
741 ty = getTypes().convertTypeForMem(astTy);
742
743 StringRef mangledName = getMangledName(d);
744 return getOrCreateCIRGlobal(mangledName, ty, astTy.getAddressSpace(), d,
745 isForDefinition);
746}
747
748/// Return the mlir::Value for the address of the given global variable. If
749/// \p ty is non-null and if the global doesn't exist, then it will be created
750/// with the specified type instead of whatever the normal requested type would
751/// be. If \p isForDefinition is true, it is guaranteed that an actual global
752/// with type \p ty will be returned, not conversion of a variable with the same
753/// mangled name but some other type.
754mlir::Value CIRGenModule::getAddrOfGlobalVar(const VarDecl *d, mlir::Type ty,
755 ForDefinition_t isForDefinition) {
756 assert(d->hasGlobalStorage() && "Not a global variable");
757 QualType astTy = d->getType();
758 if (!ty)
759 ty = getTypes().convertTypeForMem(astTy);
760
761 bool tlsAccess = d->getTLSKind() != VarDecl::TLS_None;
762 cir::GlobalOp g = getOrCreateCIRGlobal(d, ty, isForDefinition);
763 mlir::Type ptrTy = builder.getPointerTo(g.getSymType());
764 return cir::GetGlobalOp::create(builder, getLoc(d->getSourceRange()), ptrTy,
765 g.getSymNameAttr(), tlsAccess);
766}
767
768cir::GlobalViewAttr CIRGenModule::getAddrOfGlobalVarAttr(const VarDecl *d) {
769 assert(d->hasGlobalStorage() && "Not a global variable");
770 mlir::Type ty = getTypes().convertTypeForMem(d->getType());
771
772 cir::GlobalOp globalOp = getOrCreateCIRGlobal(d, ty, NotForDefinition);
774 cir::PointerType ptrTy = builder.getPointerTo(globalOp.getSymType());
775 return builder.getGlobalViewAttr(ptrTy, globalOp);
776}
777
779 bool isTentative) {
780 if (getLangOpts().OpenCL || getLangOpts().OpenMPIsTargetDevice) {
781 errorNYI(vd->getSourceRange(), "emit OpenCL/OpenMP global variable");
782 return;
783 }
784
785 // Whether the definition of the variable is available externally.
786 // If yes, we shouldn't emit the GloablCtor and GlobalDtor for the variable
787 // since this is the job for its original source.
788 bool isDefinitionAvailableExternally =
789 astContext.GetGVALinkageForVariable(vd) == GVA_AvailableExternally;
790
791 // It is useless to emit the definition for an available_externally variable
792 // which can't be marked as const.
793 if (isDefinitionAvailableExternally &&
795 // TODO: Update this when we have interface to check constexpr
796 // destructor.
797 vd->needsDestruction(astContext) ||
798 !vd->getType().isConstantStorage(astContext, true, true)))
799 return;
800
801 mlir::Attribute init;
802 bool needsGlobalCtor = false;
803 bool needsGlobalDtor =
804 !isDefinitionAvailableExternally &&
806 const VarDecl *initDecl;
807 const Expr *initExpr = vd->getAnyInitializer(initDecl);
808
809 std::optional<ConstantEmitter> emitter;
810
812
813 if (vd->hasAttr<LoaderUninitializedAttr>()) {
814 errorNYI(vd->getSourceRange(), "loader uninitialized attribute");
815 return;
816 } else if (!initExpr) {
817 // This is a tentative definition; tentative definitions are
818 // implicitly initialized with { 0 }.
819 //
820 // Note that tentative definitions are only emitted at the end of
821 // a translation unit, so they should never have incomplete
822 // type. In addition, EmitTentativeDefinition makes sure that we
823 // never attempt to emit a tentative definition if a real one
824 // exists. A use may still exists, however, so we still may need
825 // to do a RAUW.
826 assert(!vd->getType()->isIncompleteType() && "Unexpected incomplete type");
827 init = builder.getZeroInitAttr(convertType(vd->getType()));
828 } else {
829 emitter.emplace(*this);
830 mlir::Attribute initializer = emitter->tryEmitForInitializer(*initDecl);
831 if (!initializer) {
832 QualType qt = initExpr->getType();
833 if (vd->getType()->isReferenceType())
834 qt = vd->getType();
835
836 if (getLangOpts().CPlusPlus) {
837 if (initDecl->hasFlexibleArrayInit(astContext))
838 errorNYI(vd->getSourceRange(), "flexible array initializer");
839 init = builder.getZeroInitAttr(convertType(qt));
840 if (!isDefinitionAvailableExternally)
841 needsGlobalCtor = true;
842 } else {
843 errorNYI(vd->getSourceRange(), "static initializer");
844 }
845 } else {
846 init = initializer;
847 // We don't need an initializer, so remove the entry for the delayed
848 // initializer position (just in case this entry was delayed) if we
849 // also don't need to register a destructor.
851 }
852 }
853
854 mlir::Type initType;
855 if (mlir::isa<mlir::SymbolRefAttr>(init)) {
856 errorNYI(vd->getSourceRange(), "global initializer is a symbol reference");
857 return;
858 } else {
859 assert(mlir::isa<mlir::TypedAttr>(init) && "This should have a type");
860 auto typedInitAttr = mlir::cast<mlir::TypedAttr>(init);
861 initType = typedInitAttr.getType();
862 }
863 assert(!mlir::isa<mlir::NoneType>(initType) && "Should have a type by now");
864
865 cir::GlobalOp gv =
866 getOrCreateCIRGlobal(vd, initType, ForDefinition_t(!isTentative));
867 // TODO(cir): Strip off pointer casts from Entry if we get them?
868
869 if (!gv || gv.getSymType() != initType) {
870 errorNYI(vd->getSourceRange(), "global initializer with type mismatch");
871 return;
872 }
873
875
876 if (vd->hasAttr<AnnotateAttr>()) {
877 errorNYI(vd->getSourceRange(), "annotate global variable");
878 }
879
880 if (langOpts.CUDA) {
881 errorNYI(vd->getSourceRange(), "CUDA global variable");
882 }
883
884 // Set initializer and finalize emission
886 if (emitter)
887 emitter->finalize(gv);
888
889 // If it is safe to mark the global 'constant', do so now.
890 // Use the same logic as classic codegen EmitGlobalVarDefinition.
891 gv.setConstant((vd->hasAttr<CUDAConstantAttr>() && langOpts.CUDAIsDevice) ||
892 (!needsGlobalCtor && !needsGlobalDtor &&
893 vd->getType().isConstantStorage(astContext,
894 /*ExcludeCtor=*/true,
895 /*ExcludeDtor=*/true)));
897
898 // Set CIR's linkage type as appropriate.
899 cir::GlobalLinkageKind linkage =
900 getCIRLinkageVarDefinition(vd, /*IsConstant=*/false);
901
902 // Set CIR linkage and DLL storage class.
903 gv.setLinkage(linkage);
904 // FIXME(cir): setLinkage should likely set MLIR's visibility automatically.
905 gv.setVisibility(getMLIRVisibilityFromCIRLinkage(linkage));
907 if (linkage == cir::GlobalLinkageKind::CommonLinkage) {
908 // common vars aren't constant even if declared const.
909 gv.setConstant(false);
910 // Tentative definition of global variables may be initialized with
911 // non-zero null pointers. In this case they should have weak linkage
912 // since common linkage must have zero initializer and must not have
913 // explicit section therefore cannot have non-zero initial value.
914 std::optional<mlir::Attribute> initializer = gv.getInitialValue();
915 if (initializer && !getBuilder().isNullValue(*initializer))
916 gv.setLinkage(cir::GlobalLinkageKind::WeakAnyLinkage);
917 }
918
919 setNonAliasAttributes(vd, gv);
920
922
923 maybeSetTrivialComdat(*vd, gv);
924
925 // Emit the initializer function if necessary.
926 if (needsGlobalCtor || needsGlobalDtor)
927 emitCXXGlobalVarDeclInitFunc(vd, gv, needsGlobalCtor);
928}
929
931 mlir::Operation *op) {
932 const auto *decl = cast<ValueDecl>(gd.getDecl());
933 if (const auto *fd = dyn_cast<FunctionDecl>(decl)) {
934 // TODO(CIR): Skip generation of CIR for functions with available_externally
935 // linkage at -O0.
936
937 if (const auto *method = dyn_cast<CXXMethodDecl>(decl)) {
938 // Make sure to emit the definition(s) before we emit the thunks. This is
939 // necessary for the generation of certain thunks.
940 if (isa<CXXConstructorDecl>(method) || isa<CXXDestructorDecl>(method))
941 abi->emitCXXStructor(gd);
942 else if (fd->isMultiVersion())
943 errorNYI(method->getSourceRange(), "multiversion functions");
944 else
946
947 if (method->isVirtual())
949
950 return;
951 }
952
953 if (fd->isMultiVersion())
954 errorNYI(fd->getSourceRange(), "multiversion functions");
956 return;
957 }
958
959 if (const auto *vd = dyn_cast<VarDecl>(decl))
960 return emitGlobalVarDefinition(vd, !vd->hasDefinition());
961
962 llvm_unreachable("Invalid argument to CIRGenModule::emitGlobalDefinition");
963}
964
965mlir::Attribute
967 assert(!e->getType()->isPointerType() && "Strings are always arrays");
968
969 // Don't emit it as the address of the string, emit the string data itself
970 // as an inline array.
971 if (e->getCharByteWidth() == 1) {
972 SmallString<64> str(e->getString());
973
974 // Resize the string to the right size, which is indicated by its type.
975 const ConstantArrayType *cat =
976 astContext.getAsConstantArrayType(e->getType());
977 uint64_t finalSize = cat->getZExtSize();
978 str.resize(finalSize);
979
980 mlir::Type eltTy = convertType(cat->getElementType());
981 return builder.getString(str, eltTy, finalSize);
982 }
983
984 auto arrayTy = mlir::cast<cir::ArrayType>(convertType(e->getType()));
985
986 auto arrayEltTy = mlir::cast<cir::IntType>(arrayTy.getElementType());
987
988 uint64_t arraySize = arrayTy.getSize();
989 unsigned literalSize = e->getLength();
990 assert(arraySize == literalSize + 1 &&
991 "wide string literal array size must be literal length plus null "
992 "terminator");
993
994 // Check if the string is all null bytes before building the vector.
995 // In most non-zero cases, this will break out on the first element.
996 bool isAllZero = true;
997 for (unsigned i = 0; i < literalSize; ++i) {
998 if (e->getCodeUnit(i) != 0) {
999 isAllZero = false;
1000 break;
1001 }
1002 }
1003
1004 if (isAllZero)
1005 return cir::ZeroAttr::get(arrayTy);
1006
1007 // Otherwise emit a constant array holding the characters.
1009 elements.reserve(arraySize);
1010 for (unsigned i = 0; i < literalSize; ++i)
1011 elements.push_back(cir::IntAttr::get(arrayEltTy, e->getCodeUnit(i)));
1012 // Add null terminator
1013 elements.push_back(cir::IntAttr::get(arrayEltTy, 0));
1014
1015 auto elementsAttr = mlir::ArrayAttr::get(&getMLIRContext(), elements);
1016 return builder.getConstArray(elementsAttr, arrayTy);
1017}
1018
1020 return getTriple().supportsCOMDAT();
1021}
1022
1023static bool shouldBeInCOMDAT(CIRGenModule &cgm, const Decl &d) {
1024 if (!cgm.supportsCOMDAT())
1025 return false;
1026
1027 if (d.hasAttr<SelectAnyAttr>())
1028 return true;
1029
1030 GVALinkage linkage;
1031 if (auto *vd = dyn_cast<VarDecl>(&d))
1032 linkage = cgm.getASTContext().GetGVALinkageForVariable(vd);
1033 else
1034 linkage =
1036
1037 switch (linkage) {
1041 return false;
1044 return true;
1045 }
1046 llvm_unreachable("No such linkage");
1047}
1048
1049void CIRGenModule::maybeSetTrivialComdat(const Decl &d, mlir::Operation *op) {
1050 if (!shouldBeInCOMDAT(*this, d))
1051 return;
1052 if (auto globalOp = dyn_cast_or_null<cir::GlobalOp>(op)) {
1053 globalOp.setComdat(true);
1054 } else {
1055 auto funcOp = cast<cir::FuncOp>(op);
1056 funcOp.setComdat(true);
1057 }
1058}
1059
1061 // Make sure that this type is translated.
1062 genTypes.updateCompletedType(td);
1063}
1064
1065void CIRGenModule::addReplacement(StringRef name, mlir::Operation *op) {
1066 replacements[name] = op;
1067}
1068
1069void CIRGenModule::replacePointerTypeArgs(cir::FuncOp oldF, cir::FuncOp newF) {
1070 std::optional<mlir::SymbolTable::UseRange> optionalUseRange =
1071 oldF.getSymbolUses(theModule);
1072 if (!optionalUseRange)
1073 return;
1074
1075 for (const mlir::SymbolTable::SymbolUse &u : *optionalUseRange) {
1076 // CallTryOp only shows up after FlattenCFG.
1077 auto call = mlir::dyn_cast<cir::CallOp>(u.getUser());
1078 if (!call)
1079 continue;
1080
1081 for (const auto [argOp, fnArgType] :
1082 llvm::zip(call.getArgs(), newF.getFunctionType().getInputs())) {
1083 if (argOp.getType() == fnArgType)
1084 continue;
1085
1086 // The purpose of this entire function is to insert bitcasts in the case
1087 // where these types don't match, but I haven't seen a case where that
1088 // happens.
1089 errorNYI(call.getLoc(), "replace call with mismatched types");
1090 }
1091 }
1092}
1093
1094void CIRGenModule::applyReplacements() {
1095 for (auto &i : replacements) {
1096 StringRef mangledName = i.first();
1097 mlir::Operation *replacement = i.second;
1098 mlir::Operation *entry = getGlobalValue(mangledName);
1099 if (!entry)
1100 continue;
1101 assert(isa<cir::FuncOp>(entry) && "expected function");
1102 auto oldF = cast<cir::FuncOp>(entry);
1103 auto newF = dyn_cast<cir::FuncOp>(replacement);
1104 if (!newF) {
1105 // In classic codegen, this can be a global alias, a bitcast, or a GEP.
1106 errorNYI(replacement->getLoc(), "replacement is not a function");
1107 continue;
1108 }
1109
1110 // LLVM has opaque pointer but CIR not. So we may have to handle these
1111 // different pointer types when performing replacement.
1112 replacePointerTypeArgs(oldF, newF);
1113
1114 // Replace old with new, but keep the old order.
1115 if (oldF.replaceAllSymbolUses(newF.getSymNameAttr(), theModule).failed())
1116 llvm_unreachable("internal error, cannot RAUW symbol");
1117 if (newF) {
1118 newF->moveBefore(oldF);
1119 oldF->erase();
1120 }
1121 }
1122}
1123
1125 mlir::Location loc, StringRef name, mlir::Type ty,
1126 cir::GlobalLinkageKind linkage, clang::CharUnits alignment) {
1127 auto gv = mlir::dyn_cast_or_null<cir::GlobalOp>(
1128 mlir::SymbolTable::lookupSymbolIn(theModule, name));
1129
1130 if (gv) {
1131 // Check if the variable has the right type.
1132 if (gv.getSymType() == ty)
1133 return gv;
1134
1135 // Because of C++ name mangling, the only way we can end up with an already
1136 // existing global with the same name is if it has been declared extern
1137 // "C".
1138 assert(gv.isDeclaration() && "Declaration has wrong type!");
1139
1140 errorNYI(loc, "createOrReplaceCXXRuntimeVariable: declaration exists with "
1141 "wrong type");
1142 return gv;
1143 }
1144
1145 // Create a new variable.
1146 gv = createGlobalOp(*this, loc, name, ty);
1147
1148 // Set up extra information and add to the module
1149 gv.setLinkageAttr(
1150 cir::GlobalLinkageKindAttr::get(&getMLIRContext(), linkage));
1151 mlir::SymbolTable::setSymbolVisibility(gv,
1153
1154 if (supportsCOMDAT() && cir::isWeakForLinker(linkage) &&
1155 !gv.hasAvailableExternallyLinkage()) {
1156 gv.setComdat(true);
1157 }
1158
1159 gv.setAlignmentAttr(getSize(alignment));
1160 setDSOLocal(static_cast<mlir::Operation *>(gv));
1161 return gv;
1162}
1163
1164// TODO(CIR): this could be a common method between LLVM codegen.
1165static bool isVarDeclStrongDefinition(const ASTContext &astContext,
1166 CIRGenModule &cgm, const VarDecl *vd,
1167 bool noCommon) {
1168 // Don't give variables common linkage if -fno-common was specified unless it
1169 // was overridden by a NoCommon attribute.
1170 if ((noCommon || vd->hasAttr<NoCommonAttr>()) && !vd->hasAttr<CommonAttr>())
1171 return true;
1172
1173 // C11 6.9.2/2:
1174 // A declaration of an identifier for an object that has file scope without
1175 // an initializer, and without a storage-class specifier or with the
1176 // storage-class specifier static, constitutes a tentative definition.
1177 if (vd->getInit() || vd->hasExternalStorage())
1178 return true;
1179
1180 // A variable cannot be both common and exist in a section.
1181 if (vd->hasAttr<SectionAttr>())
1182 return true;
1183
1184 // A variable cannot be both common and exist in a section.
1185 // We don't try to determine which is the right section in the front-end.
1186 // If no specialized section name is applicable, it will resort to default.
1187 if (vd->hasAttr<PragmaClangBSSSectionAttr>() ||
1188 vd->hasAttr<PragmaClangDataSectionAttr>() ||
1189 vd->hasAttr<PragmaClangRelroSectionAttr>() ||
1190 vd->hasAttr<PragmaClangRodataSectionAttr>())
1191 return true;
1192
1193 // Thread local vars aren't considered common linkage.
1194 if (vd->getTLSKind())
1195 return true;
1196
1197 // Tentative definitions marked with WeakImportAttr are true definitions.
1198 if (vd->hasAttr<WeakImportAttr>())
1199 return true;
1200
1201 // A variable cannot be both common and exist in a comdat.
1202 if (shouldBeInCOMDAT(cgm, *vd))
1203 return true;
1204
1205 // Declarations with a required alignment do not have common linkage in MSVC
1206 // mode.
1207 if (astContext.getTargetInfo().getCXXABI().isMicrosoft()) {
1208 if (vd->hasAttr<AlignedAttr>())
1209 return true;
1210 QualType varType = vd->getType();
1211 if (astContext.isAlignmentRequired(varType))
1212 return true;
1213
1214 if (const auto *rd = varType->getAsRecordDecl()) {
1215 for (const FieldDecl *fd : rd->fields()) {
1216 if (fd->isBitField())
1217 continue;
1218 if (fd->hasAttr<AlignedAttr>())
1219 return true;
1220 if (astContext.isAlignmentRequired(fd->getType()))
1221 return true;
1222 }
1223 }
1224 }
1225
1226 // Microsoft's link.exe doesn't support alignments greater than 32 bytes for
1227 // common symbols, so symbols with greater alignment requirements cannot be
1228 // common.
1229 // Other COFF linkers (ld.bfd and LLD) support arbitrary power-of-two
1230 // alignments for common symbols via the aligncomm directive, so this
1231 // restriction only applies to MSVC environments.
1232 if (astContext.getTargetInfo().getTriple().isKnownWindowsMSVCEnvironment() &&
1233 astContext.getTypeAlignIfKnown(vd->getType()) >
1234 astContext.toBits(CharUnits::fromQuantity(32)))
1235 return true;
1236
1237 return false;
1238}
1239
1241 const DeclaratorDecl *dd, GVALinkage linkage, bool isConstantVariable) {
1242 if (linkage == GVA_Internal)
1243 return cir::GlobalLinkageKind::InternalLinkage;
1244
1245 if (dd->hasAttr<WeakAttr>()) {
1246 if (isConstantVariable)
1247 return cir::GlobalLinkageKind::WeakODRLinkage;
1248 return cir::GlobalLinkageKind::WeakAnyLinkage;
1249 }
1250
1251 if (const auto *fd = dd->getAsFunction())
1252 if (fd->isMultiVersion() && linkage == GVA_AvailableExternally)
1253 return cir::GlobalLinkageKind::LinkOnceAnyLinkage;
1254
1255 // We are guaranteed to have a strong definition somewhere else,
1256 // so we can use available_externally linkage.
1257 if (linkage == GVA_AvailableExternally)
1258 return cir::GlobalLinkageKind::AvailableExternallyLinkage;
1259
1260 // Note that Apple's kernel linker doesn't support symbol
1261 // coalescing, so we need to avoid linkonce and weak linkages there.
1262 // Normally, this means we just map to internal, but for explicit
1263 // instantiations we'll map to external.
1264
1265 // In C++, the compiler has to emit a definition in every translation unit
1266 // that references the function. We should use linkonce_odr because
1267 // a) if all references in this translation unit are optimized away, we
1268 // don't need to codegen it. b) if the function persists, it needs to be
1269 // merged with other definitions. c) C++ has the ODR, so we know the
1270 // definition is dependable.
1271 if (linkage == GVA_DiscardableODR)
1272 return !astContext.getLangOpts().AppleKext
1273 ? cir::GlobalLinkageKind::LinkOnceODRLinkage
1274 : cir::GlobalLinkageKind::InternalLinkage;
1275
1276 // An explicit instantiation of a template has weak linkage, since
1277 // explicit instantiations can occur in multiple translation units
1278 // and must all be equivalent. However, we are not allowed to
1279 // throw away these explicit instantiations.
1280 //
1281 // CUDA/HIP: For -fno-gpu-rdc case, device code is limited to one TU,
1282 // so say that CUDA templates are either external (for kernels) or internal.
1283 // This lets llvm perform aggressive inter-procedural optimizations. For
1284 // -fgpu-rdc case, device function calls across multiple TU's are allowed,
1285 // therefore we need to follow the normal linkage paradigm.
1286 if (linkage == GVA_StrongODR) {
1287 if (getLangOpts().AppleKext)
1288 return cir::GlobalLinkageKind::ExternalLinkage;
1289 if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice &&
1290 !getLangOpts().GPURelocatableDeviceCode)
1291 return dd->hasAttr<CUDAGlobalAttr>()
1292 ? cir::GlobalLinkageKind::ExternalLinkage
1293 : cir::GlobalLinkageKind::InternalLinkage;
1294 return cir::GlobalLinkageKind::WeakODRLinkage;
1295 }
1296
1297 // C++ doesn't have tentative definitions and thus cannot have common
1298 // linkage.
1299 if (!getLangOpts().CPlusPlus && isa<VarDecl>(dd) &&
1300 !isVarDeclStrongDefinition(astContext, *this, cast<VarDecl>(dd),
1301 getCodeGenOpts().NoCommon))
1302 return cir::GlobalLinkageKind::CommonLinkage;
1303
1304 // selectany symbols are externally visible, so use weak instead of
1305 // linkonce. MSVC optimizes away references to const selectany globals, so
1306 // all definitions should be the same and ODR linkage should be used.
1307 // http://msdn.microsoft.com/en-us/library/5tkz6s71.aspx
1308 if (dd->hasAttr<SelectAnyAttr>())
1309 return cir::GlobalLinkageKind::WeakODRLinkage;
1310
1311 // Otherwise, we have strong external linkage.
1312 assert(linkage == GVA_StrongExternal);
1313 return cir::GlobalLinkageKind::ExternalLinkage;
1314}
1315
1316/// This function is called when we implement a function with no prototype, e.g.
1317/// "int foo() {}". If there are existing call uses of the old function in the
1318/// module, this adjusts them to call the new function directly.
1319///
1320/// This is not just a cleanup: the always_inline pass requires direct calls to
1321/// functions to be able to inline them. If there is a bitcast in the way, it
1322/// won't inline them. Instcombine normally deletes these calls, but it isn't
1323/// run at -O0.
1325 mlir::Operation *old, cir::FuncOp newFn) {
1326 // If we're redefining a global as a function, don't transform it.
1327 auto oldFn = mlir::dyn_cast<cir::FuncOp>(old);
1328 if (!oldFn)
1329 return;
1330
1331 // TODO(cir): this RAUW ignores the features below.
1335 if (oldFn->getAttrs().size() <= 1)
1336 errorNYI(old->getLoc(),
1337 "replaceUsesOfNonProtoTypeWithRealFunction: Attribute forwarding");
1338
1339 // Mark new function as originated from a no-proto declaration.
1340 newFn.setNoProto(oldFn.getNoProto());
1341
1342 // Iterate through all calls of the no-proto function.
1343 std::optional<mlir::SymbolTable::UseRange> symUses =
1344 oldFn.getSymbolUses(oldFn->getParentOp());
1345 for (const mlir::SymbolTable::SymbolUse &use : symUses.value()) {
1346 mlir::OpBuilder::InsertionGuard guard(builder);
1347
1348 if (auto noProtoCallOp = mlir::dyn_cast<cir::CallOp>(use.getUser())) {
1349 builder.setInsertionPoint(noProtoCallOp);
1350
1351 // Patch call type with the real function type.
1352 cir::CallOp realCallOp = builder.createCallOp(
1353 noProtoCallOp.getLoc(), newFn, noProtoCallOp.getOperands());
1354
1355 // Replace old no proto call with fixed call.
1356 noProtoCallOp.replaceAllUsesWith(realCallOp);
1357 noProtoCallOp.erase();
1358 } else if (auto getGlobalOp =
1359 mlir::dyn_cast<cir::GetGlobalOp>(use.getUser())) {
1360 // Replace type
1361 getGlobalOp.getAddr().setType(
1362 cir::PointerType::get(newFn.getFunctionType()));
1363 } else {
1364 errorNYI(use.getUser()->getLoc(),
1365 "replaceUsesOfNonProtoTypeWithRealFunction: unexpected use");
1366 }
1367 }
1368}
1369
1370cir::GlobalLinkageKind
1372 assert(!isConstant && "constant variables NYI");
1373 GVALinkage linkage = astContext.GetGVALinkageForVariable(vd);
1374 return getCIRLinkageForDeclarator(vd, linkage, isConstant);
1375}
1376
1378 const auto *d = cast<FunctionDecl>(gd.getDecl());
1379
1380 GVALinkage linkage = astContext.GetGVALinkageForFunction(d);
1381
1382 if (const auto *dtor = dyn_cast<CXXDestructorDecl>(d))
1383 return getCXXABI().getCXXDestructorLinkage(linkage, dtor, gd.getDtorType());
1384
1385 return getCIRLinkageForDeclarator(d, linkage, /*isConstantVariable=*/false);
1386}
1387
1388static cir::GlobalOp
1389generateStringLiteral(mlir::Location loc, mlir::TypedAttr c,
1390 cir::GlobalLinkageKind lt, CIRGenModule &cgm,
1391 StringRef globalName, CharUnits alignment) {
1393
1394 // Create a global variable for this string
1395 // FIXME(cir): check for insertion point in module level.
1396 cir::GlobalOp gv = CIRGenModule::createGlobalOp(
1397 cgm, loc, globalName, c.getType(), !cgm.getLangOpts().WritableStrings);
1398
1399 // Set up extra information and add to the module
1400 gv.setAlignmentAttr(cgm.getSize(alignment));
1401 gv.setLinkageAttr(
1402 cir::GlobalLinkageKindAttr::get(cgm.getBuilder().getContext(), lt));
1406 if (gv.isWeakForLinker()) {
1407 assert(cgm.supportsCOMDAT() && "Only COFF uses weak string literals");
1408 gv.setComdat(true);
1409 }
1410 cgm.setDSOLocal(static_cast<mlir::Operation *>(gv));
1411 return gv;
1412}
1413
1414// LLVM IR automatically uniques names when new llvm::GlobalVariables are
1415// created. This is handy, for example, when creating globals for string
1416// literals. Since we don't do that when creating cir::GlobalOp's, we need
1417// a mechanism to generate a unique name in advance.
1418//
1419// For now, this mechanism is only used in cases where we know that the
1420// name is compiler-generated, so we don't use the MLIR symbol table for
1421// the lookup.
1422std::string CIRGenModule::getUniqueGlobalName(const std::string &baseName) {
1423 // If this is the first time we've generated a name for this basename, use
1424 // it as is and start a counter for this base name.
1425 auto it = cgGlobalNames.find(baseName);
1426 if (it == cgGlobalNames.end()) {
1427 cgGlobalNames[baseName] = 1;
1428 return baseName;
1429 }
1430
1431 std::string result =
1432 baseName + "." + std::to_string(cgGlobalNames[baseName]++);
1433 // There should not be any symbol with this name in the module.
1434 assert(!mlir::SymbolTable::lookupSymbolIn(theModule, result));
1435 return result;
1436}
1437
1438/// Return a pointer to a constant array for the given string literal.
1440 StringRef name) {
1441 CharUnits alignment =
1442 astContext.getAlignOfGlobalVarInChars(s->getType(), /*VD=*/nullptr);
1443
1444 mlir::Attribute c = getConstantArrayFromStringLiteral(s);
1445
1446 cir::GlobalOp gv;
1447 if (!getLangOpts().WritableStrings && constantStringMap.count(c)) {
1448 gv = constantStringMap[c];
1449 // The bigger alignment always wins.
1450 if (!gv.getAlignment() ||
1451 uint64_t(alignment.getQuantity()) > *gv.getAlignment())
1452 gv.setAlignmentAttr(getSize(alignment));
1453 } else {
1454 // Mangle the string literal if that's how the ABI merges duplicate strings.
1455 // Don't do it if they are writable, since we don't want writes in one TU to
1456 // affect strings in another.
1457 if (getCXXABI().getMangleContext().shouldMangleStringLiteral(s) &&
1458 !getLangOpts().WritableStrings) {
1459 errorNYI(s->getSourceRange(),
1460 "getGlobalForStringLiteral: mangle string literals");
1461 }
1462
1463 // Unlike LLVM IR, CIR doesn't automatically unique names for globals, so
1464 // we need to do that explicitly.
1465 std::string uniqueName = getUniqueGlobalName(name.str());
1466 // Synthetic string literals (e.g., from SourceLocExpr) may not have valid
1467 // source locations. Use unknown location in those cases.
1468 mlir::Location loc = s->getBeginLoc().isValid()
1469 ? getLoc(s->getSourceRange())
1470 : builder.getUnknownLoc();
1471 auto typedC = llvm::cast<mlir::TypedAttr>(c);
1472 gv = generateStringLiteral(loc, typedC,
1473 cir::GlobalLinkageKind::PrivateLinkage, *this,
1474 uniqueName, alignment);
1475 setDSOLocal(static_cast<mlir::Operation *>(gv));
1476 constantStringMap[c] = gv;
1477
1479 }
1480 return gv;
1481}
1482
1483/// Return a pointer to a constant array for the given string literal.
1484cir::GlobalViewAttr
1486 StringRef name) {
1487 cir::GlobalOp gv = getGlobalForStringLiteral(s, name);
1488 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(gv.getSymType());
1489 assert(arrayTy && "String literal must be array");
1491 cir::PointerType ptrTy = getBuilder().getPointerTo(arrayTy.getElementType());
1492
1493 return builder.getGlobalViewAttr(ptrTy, gv);
1494}
1495
1496// TODO(cir): this could be a common AST helper for both CIR and LLVM codegen.
1498 if (getLangOpts().OpenCL)
1500
1501 // For temporaries inside functions, CUDA treats them as normal variables.
1502 // LangAS::cuda_device, on the other hand, is reserved for those variables
1503 // explicitly marked with __device__.
1504 if (getLangOpts().CUDAIsDevice)
1505 return LangAS::Default;
1506
1507 if (getLangOpts().SYCLIsDevice ||
1508 (getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice))
1509 errorNYI("SYCL or OpenMP temp address space");
1510 return LangAS::Default;
1511}
1512
1514 CIRGenFunction *cgf) {
1515 if (cgf && e->getType()->isVariablyModifiedType())
1517
1519 "emitExplicitCastExprType");
1520}
1521
1524
1525 mlir::Location loc = getLoc(e->getSourceRange());
1526
1527 const auto *decl = cast<DeclRefExpr>(e->getSubExpr())->getDecl();
1528
1529 // A member function pointer.
1530 if (const auto *methodDecl = dyn_cast<CXXMethodDecl>(decl)) {
1531 auto ty = mlir::cast<cir::MethodType>(convertType(e->getType()));
1532 if (methodDecl->isVirtual())
1533 return cir::ConstantOp::create(
1534 builder, loc, getCXXABI().buildVirtualMethodAttr(ty, methodDecl));
1535
1536 cir::FuncOp methodFuncOp = getAddrOfFunction(methodDecl);
1537 return cir::ConstantOp::create(builder, loc,
1538 builder.getMethodAttr(ty, methodFuncOp));
1539 }
1540
1541 // Otherwise, a member data pointer.
1542 auto ty = mlir::cast<cir::DataMemberType>(convertType(e->getType()));
1543 const auto *fieldDecl = cast<FieldDecl>(decl);
1544 return cir::ConstantOp::create(
1545 builder, loc, builder.getDataMemberAttr(ty, fieldDecl->getFieldIndex()));
1546}
1547
1549 for (Decl *decl : dc->decls()) {
1550 // Unlike other DeclContexts, the contents of an ObjCImplDecl at TU scope
1551 // are themselves considered "top-level", so EmitTopLevelDecl on an
1552 // ObjCImplDecl does not recursively visit them. We need to do that in
1553 // case they're nested inside another construct (LinkageSpecDecl /
1554 // ExportDecl) that does stop them from being considered "top-level".
1555 if (auto *oid = dyn_cast<ObjCImplDecl>(decl))
1556 errorNYI(oid->getSourceRange(), "emitDeclConext: ObjCImplDecl");
1557
1559 }
1560}
1561
1562// Emit code for a single top level declaration.
1564
1565 // Ignore dependent declarations.
1566 if (decl->isTemplated())
1567 return;
1568
1569 switch (decl->getKind()) {
1570 default:
1571 errorNYI(decl->getBeginLoc(), "declaration of kind",
1572 decl->getDeclKindName());
1573 break;
1574
1575 case Decl::CXXConversion:
1576 case Decl::CXXMethod:
1577 case Decl::Function: {
1578 auto *fd = cast<FunctionDecl>(decl);
1579 // Consteval functions shouldn't be emitted.
1580 if (!fd->isConsteval())
1581 emitGlobal(fd);
1582 break;
1583 }
1584
1585 case Decl::Var:
1586 case Decl::Decomposition:
1587 case Decl::VarTemplateSpecialization: {
1588 auto *vd = cast<VarDecl>(decl);
1590 errorNYI(decl->getSourceRange(), "global variable decompositions");
1591 break;
1592 }
1593 emitGlobal(vd);
1594 break;
1595 }
1596 case Decl::OpenACCRoutine:
1598 break;
1599 case Decl::OpenACCDeclare:
1601 break;
1602 case Decl::OMPThreadPrivate:
1604 break;
1605 case Decl::OMPGroupPrivate:
1607 break;
1608 case Decl::OMPAllocate:
1610 break;
1611 case Decl::OMPCapturedExpr:
1613 break;
1614 case Decl::OMPDeclareReduction:
1616 break;
1617 case Decl::OMPDeclareMapper:
1619 break;
1620 case Decl::OMPRequires:
1622 break;
1623 case Decl::Enum:
1624 case Decl::Using: // using X; [C++]
1625 case Decl::UsingDirective: // using namespace X; [C++]
1626 case Decl::UsingEnum: // using enum X; [C++]
1627 case Decl::NamespaceAlias:
1628 case Decl::Typedef:
1629 case Decl::TypeAlias: // using foo = bar; [C++11]
1630 case Decl::Record:
1632 break;
1633
1634 // No code generation needed.
1635 case Decl::ClassTemplate:
1636 case Decl::Concept:
1637 case Decl::CXXDeductionGuide:
1638 case Decl::Empty:
1639 case Decl::FunctionTemplate:
1640 case Decl::StaticAssert:
1641 case Decl::TypeAliasTemplate:
1642 case Decl::UsingShadow:
1643 case Decl::VarTemplate:
1644 case Decl::VarTemplatePartialSpecialization:
1645 break;
1646
1647 case Decl::CXXConstructor:
1649 break;
1650 case Decl::CXXDestructor:
1652 break;
1653
1654 // C++ Decls
1655 case Decl::LinkageSpec:
1656 case Decl::Namespace:
1658 break;
1659
1660 case Decl::ClassTemplateSpecialization:
1661 case Decl::CXXRecord: {
1664 for (auto *childDecl : crd->decls())
1666 emitTopLevelDecl(childDecl);
1667 break;
1668 }
1669
1670 case Decl::FileScopeAsm:
1671 // File-scope asm is ignored during device-side CUDA compilation.
1672 if (langOpts.CUDA && langOpts.CUDAIsDevice)
1673 break;
1674 // File-scope asm is ignored during device-side OpenMP compilation.
1675 if (langOpts.OpenMPIsTargetDevice)
1676 break;
1677 // File-scope asm is ignored during device-side SYCL compilation.
1678 if (langOpts.SYCLIsDevice)
1679 break;
1680 auto *file_asm = cast<FileScopeAsmDecl>(decl);
1681 std::string line = file_asm->getAsmString();
1682 globalScopeAsm.push_back(builder.getStringAttr(line));
1683 break;
1684 }
1685}
1686
1687void CIRGenModule::setInitializer(cir::GlobalOp &op, mlir::Attribute value) {
1688 // Recompute visibility when updating initializer.
1689 op.setInitialValueAttr(value);
1691}
1692
1693std::pair<cir::FuncType, cir::FuncOp> CIRGenModule::getAddrAndTypeOfCXXStructor(
1694 GlobalDecl gd, const CIRGenFunctionInfo *fnInfo, cir::FuncType fnType,
1695 bool dontDefer, ForDefinition_t isForDefinition) {
1696 auto *md = cast<CXXMethodDecl>(gd.getDecl());
1697
1698 if (isa<CXXDestructorDecl>(md)) {
1699 // Always alias equivalent complete destructors to base destructors in the
1700 // MS ABI.
1701 if (getTarget().getCXXABI().isMicrosoft() &&
1702 gd.getDtorType() == Dtor_Complete &&
1703 md->getParent()->getNumVBases() == 0)
1704 errorNYI(md->getSourceRange(),
1705 "getAddrAndTypeOfCXXStructor: MS ABI complete destructor");
1706 }
1707
1708 if (!fnType) {
1709 if (!fnInfo)
1711 fnType = getTypes().getFunctionType(*fnInfo);
1712 }
1713
1714 auto fn = getOrCreateCIRFunction(getMangledName(gd), fnType, gd,
1715 /*ForVtable=*/false, dontDefer,
1716 /*IsThunk=*/false, isForDefinition);
1717
1718 return {fnType, fn};
1719}
1720
1722 mlir::Type funcType, bool forVTable,
1723 bool dontDefer,
1724 ForDefinition_t isForDefinition) {
1725 assert(!cast<FunctionDecl>(gd.getDecl())->isConsteval() &&
1726 "consteval function should never be emitted");
1727
1728 if (!funcType) {
1729 const auto *fd = cast<FunctionDecl>(gd.getDecl());
1730 funcType = convertType(fd->getType());
1731 }
1732
1733 // Devirtualized destructor calls may come through here instead of via
1734 // getAddrOfCXXStructor. Make sure we use the MS ABI base destructor instead
1735 // of the complete destructor when necessary.
1736 if (const auto *dd = dyn_cast<CXXDestructorDecl>(gd.getDecl())) {
1737 if (getTarget().getCXXABI().isMicrosoft() &&
1738 gd.getDtorType() == Dtor_Complete &&
1739 dd->getParent()->getNumVBases() == 0)
1740 errorNYI(dd->getSourceRange(),
1741 "getAddrOfFunction: MS ABI complete destructor");
1742 }
1743
1744 StringRef mangledName = getMangledName(gd);
1745 cir::FuncOp func =
1746 getOrCreateCIRFunction(mangledName, funcType, gd, forVTable, dontDefer,
1747 /*isThunk=*/false, isForDefinition);
1748 return func;
1749}
1750
1751static std::string getMangledNameImpl(CIRGenModule &cgm, GlobalDecl gd,
1752 const NamedDecl *nd) {
1753 SmallString<256> buffer;
1754
1755 llvm::raw_svector_ostream out(buffer);
1757
1759
1760 if (mc.shouldMangleDeclName(nd)) {
1761 mc.mangleName(gd.getWithDecl(nd), out);
1762 } else {
1763 IdentifierInfo *ii = nd->getIdentifier();
1764 assert(ii && "Attempt to mangle unnamed decl.");
1765
1766 const auto *fd = dyn_cast<FunctionDecl>(nd);
1767 if (fd &&
1768 fd->getType()->castAs<FunctionType>()->getCallConv() == CC_X86RegCall) {
1769 cgm.errorNYI(nd->getSourceRange(), "getMangledName: X86RegCall");
1770 } else if (fd && fd->hasAttr<CUDAGlobalAttr>() &&
1772 cgm.errorNYI(nd->getSourceRange(), "getMangledName: CUDA device stub");
1773 }
1774 out << ii->getName();
1775 }
1776
1777 // Check if the module name hash should be appended for internal linkage
1778 // symbols. This should come before multi-version target suffixes are
1779 // appendded. This is to keep the name and module hash suffix of the internal
1780 // linkage function together. The unique suffix should only be added when name
1781 // mangling is done to make sure that the final name can be properly
1782 // demangled. For example, for C functions without prototypes, name mangling
1783 // is not done and the unique suffix should not be appended then.
1785
1786 if (const auto *fd = dyn_cast<FunctionDecl>(nd)) {
1787 if (fd->isMultiVersion()) {
1788 cgm.errorNYI(nd->getSourceRange(),
1789 "getMangledName: multi-version functions");
1790 }
1791 }
1792 if (cgm.getLangOpts().GPURelocatableDeviceCode) {
1793 cgm.errorNYI(nd->getSourceRange(),
1794 "getMangledName: GPU relocatable device code");
1795 }
1796
1797 return std::string(out.str());
1798}
1799
1800static FunctionDecl *
1802 const FunctionDecl *protoFunc) {
1803 // If this is a C no-prototype function, we can take the 'easy' way out and
1804 // just create a function with no arguments/functions, etc.
1805 if (!protoFunc->hasPrototype())
1806 return FunctionDecl::Create(
1807 ctx, /*DC=*/ctx.getTranslationUnitDecl(),
1808 /*StartLoc=*/SourceLocation{}, /*NLoc=*/SourceLocation{}, bindName,
1809 protoFunc->getType(), /*TInfo=*/nullptr, StorageClass::SC_None);
1810
1811 QualType funcTy = protoFunc->getType();
1812 auto *fpt = cast<FunctionProtoType>(protoFunc->getType());
1813
1814 // If this is a member function, add an explicit 'this' to the function type.
1815 if (auto *methodDecl = dyn_cast<CXXMethodDecl>(protoFunc);
1816 methodDecl && methodDecl->isImplicitObjectMemberFunction()) {
1817 llvm::SmallVector<QualType> paramTypes{fpt->getParamTypes()};
1818 paramTypes.insert(paramTypes.begin(), methodDecl->getThisType());
1819
1820 funcTy = ctx.getFunctionType(fpt->getReturnType(), paramTypes,
1821 fpt->getExtProtoInfo());
1822 fpt = cast<FunctionProtoType>(funcTy);
1823 }
1824
1825 auto *tempFunc =
1827 /*StartLoc=*/SourceLocation{},
1828 /*NLoc=*/SourceLocation{}, bindName, funcTy,
1829 /*TInfo=*/nullptr, StorageClass::SC_None);
1830
1832 params.reserve(fpt->getNumParams());
1833
1834 // Add all of the parameters.
1835 for (unsigned i = 0, e = fpt->getNumParams(); i != e; ++i) {
1837 ctx, tempFunc, /*StartLoc=*/SourceLocation{},
1838 /*IdLoc=*/SourceLocation{},
1839 /*Id=*/nullptr, fpt->getParamType(i), /*TInfo=*/nullptr,
1840 StorageClass::SC_None, /*DefArg=*/nullptr);
1841 parm->setScopeInfo(0, i);
1842 params.push_back(parm);
1843 }
1844
1845 tempFunc->setParams(params);
1846
1847 return tempFunc;
1848}
1849
1850std::string
1852 const FunctionDecl *attachedFunction) {
1854 getASTContext(), bindName, attachedFunction);
1855
1856 std::string ret = getMangledNameImpl(*this, GlobalDecl(tempFunc), tempFunc);
1857
1858 // This does nothing (it is a do-nothing function), since this is a
1859 // slab-allocator, but leave a call in to immediately destroy this in case we
1860 // ever come up with a way of getting allocations back.
1861 getASTContext().Deallocate(tempFunc);
1862 return ret;
1863}
1864
1866 GlobalDecl canonicalGd = gd.getCanonicalDecl();
1867
1868 // Some ABIs don't have constructor variants. Make sure that base and complete
1869 // constructors get mangled the same.
1870 if (const auto *cd = dyn_cast<CXXConstructorDecl>(canonicalGd.getDecl())) {
1871 if (!getTarget().getCXXABI().hasConstructorVariants()) {
1872 errorNYI(cd->getSourceRange(),
1873 "getMangledName: C++ constructor without variants");
1874 return cast<NamedDecl>(gd.getDecl())->getIdentifier()->getName();
1875 }
1876 }
1877
1878 // Keep the first result in the case of a mangling collision.
1879 const auto *nd = cast<NamedDecl>(gd.getDecl());
1880 std::string mangledName = getMangledNameImpl(*this, gd, nd);
1881
1882 auto result = manglings.insert(std::make_pair(mangledName, gd));
1883 return mangledDeclNames[canonicalGd] = result.first->first();
1884}
1885
1887 assert(!d->getInit() && "Cannot emit definite definitions here!");
1888
1889 StringRef mangledName = getMangledName(d);
1890 mlir::Operation *gv = getGlobalValue(mangledName);
1891
1892 // If we already have a definition, not declaration, with the same mangled
1893 // name, emitting of declaration is not required (and would actually overwrite
1894 // the emitted definition).
1895 if (gv && !mlir::cast<cir::GlobalOp>(gv).isDeclaration())
1896 return;
1897
1898 // If we have not seen a reference to this variable yet, place it into the
1899 // deferred declarations table to be emitted if needed later.
1900 if (!mustBeEmitted(d) && !gv) {
1901 deferredDecls[mangledName] = d;
1902 return;
1903 }
1904
1905 // The tentative definition is the only definition.
1907}
1908
1910 // Never defer when EmitAllDecls is specified.
1911 if (langOpts.EmitAllDecls)
1912 return true;
1913
1914 const auto *vd = dyn_cast<VarDecl>(global);
1915 if (vd &&
1916 ((codeGenOpts.KeepPersistentStorageVariables &&
1917 (vd->getStorageDuration() == SD_Static ||
1918 vd->getStorageDuration() == SD_Thread)) ||
1919 (codeGenOpts.KeepStaticConsts && vd->getStorageDuration() == SD_Static &&
1920 vd->getType().isConstQualified())))
1921 return true;
1922
1923 return getASTContext().DeclMustBeEmitted(global);
1924}
1925
1927 // In OpenMP 5.0 variables and function may be marked as
1928 // device_type(host/nohost) and we should not emit them eagerly unless we sure
1929 // that they must be emitted on the host/device. To be sure we need to have
1930 // seen a declare target with an explicit mentioning of the function, we know
1931 // we have if the level of the declare target attribute is -1. Note that we
1932 // check somewhere else if we should emit this at all.
1933 if (langOpts.OpenMP >= 50 && !langOpts.OpenMPSimd) {
1934 std::optional<OMPDeclareTargetDeclAttr *> activeAttr =
1935 OMPDeclareTargetDeclAttr::getActiveAttr(global);
1936 if (!activeAttr || (*activeAttr)->getLevel() != (unsigned)-1)
1937 return false;
1938 }
1939
1940 const auto *fd = dyn_cast<FunctionDecl>(global);
1941 if (fd) {
1942 // Implicit template instantiations may change linkage if they are later
1943 // explicitly instantiated, so they should not be emitted eagerly.
1944 if (fd->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
1945 return false;
1946 // Defer until all versions have been semantically checked.
1947 if (fd->hasAttr<TargetVersionAttr>() && !fd->isMultiVersion())
1948 return false;
1949 if (langOpts.SYCLIsDevice) {
1950 errorNYI(fd->getSourceRange(), "mayBeEmittedEagerly: SYCL");
1951 return false;
1952 }
1953 }
1954 const auto *vd = dyn_cast<VarDecl>(global);
1955 if (vd)
1956 if (astContext.getInlineVariableDefinitionKind(vd) ==
1958 // A definition of an inline constexpr static data member may change
1959 // linkage later if it's redeclared outside the class.
1960 return false;
1961
1962 // If OpenMP is enabled and threadprivates must be generated like TLS, delay
1963 // codegen for global variables, because they may be marked as threadprivate.
1964 if (langOpts.OpenMP && langOpts.OpenMPUseTLS &&
1965 astContext.getTargetInfo().isTLSSupported() && isa<VarDecl>(global) &&
1966 !global->getType().isConstantStorage(astContext, false, false) &&
1967 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(global))
1968 return false;
1969
1970 assert((fd || vd) &&
1971 "Only FunctionDecl and VarDecl should hit this path so far.");
1972 return true;
1973}
1974
1975static bool shouldAssumeDSOLocal(const CIRGenModule &cgm,
1976 cir::CIRGlobalValueInterface gv) {
1977 if (gv.hasLocalLinkage())
1978 return true;
1979
1980 if (!gv.hasDefaultVisibility() && !gv.hasExternalWeakLinkage())
1981 return true;
1982
1983 // DLLImport explicitly marks the GV as external.
1984 // so it shouldn't be dso_local
1985 // But we don't have the info set now
1987
1988 const llvm::Triple &tt = cgm.getTriple();
1989 const CodeGenOptions &cgOpts = cgm.getCodeGenOpts();
1990 if (tt.isOSCygMing()) {
1991 // In MinGW and Cygwin, variables without DLLImport can still be
1992 // automatically imported from a DLL by the linker; don't mark variables
1993 // that potentially could come from another DLL as DSO local.
1994
1995 // With EmulatedTLS, TLS variables can be autoimported from other DLLs
1996 // (and this actually happens in the public interface of libstdc++), so
1997 // such variables can't be marked as DSO local. (Native TLS variables
1998 // can't be dllimported at all, though.)
1999 cgm.errorNYI("shouldAssumeDSOLocal: MinGW");
2000 }
2001
2002 // On COFF, don't mark 'extern_weak' symbols as DSO local. If these symbols
2003 // remain unresolved in the link, they can be resolved to zero, which is
2004 // outside the current DSO.
2005 if (tt.isOSBinFormatCOFF() && gv.hasExternalWeakLinkage())
2006 return false;
2007
2008 // Every other GV is local on COFF.
2009 // Make an exception for windows OS in the triple: Some firmware builds use
2010 // *-win32-macho triples. This (accidentally?) produced windows relocations
2011 // without GOT tables in older clang versions; Keep this behaviour.
2012 // FIXME: even thread local variables?
2013 if (tt.isOSBinFormatCOFF() || (tt.isOSWindows() && tt.isOSBinFormatMachO()))
2014 return true;
2015
2016 // Only handle COFF and ELF for now.
2017 if (!tt.isOSBinFormatELF())
2018 return false;
2019
2020 llvm::Reloc::Model rm = cgOpts.RelocationModel;
2021 const LangOptions &lOpts = cgm.getLangOpts();
2022 if (rm != llvm::Reloc::Static && !lOpts.PIE) {
2023 // On ELF, if -fno-semantic-interposition is specified and the target
2024 // supports local aliases, there will be neither CC1
2025 // -fsemantic-interposition nor -fhalf-no-semantic-interposition. Set
2026 // dso_local on the function if using a local alias is preferable (can avoid
2027 // PLT indirection).
2028 if (!(isa<cir::FuncOp>(gv) && gv.canBenefitFromLocalAlias()))
2029 return false;
2030 return !(lOpts.SemanticInterposition || lOpts.HalfNoSemanticInterposition);
2031 }
2032
2033 // A definition cannot be preempted from an executable.
2034 if (!gv.isDeclarationForLinker())
2035 return true;
2036
2037 // Most PIC code sequences that assume that a symbol is local cannot produce a
2038 // 0 if it turns out the symbol is undefined. While this is ABI and relocation
2039 // depended, it seems worth it to handle it here.
2040 if (rm == llvm::Reloc::PIC_ && gv.hasExternalWeakLinkage())
2041 return false;
2042
2043 // PowerPC64 prefers TOC indirection to avoid copy relocations.
2044 if (tt.isPPC64())
2045 return false;
2046
2047 if (cgOpts.DirectAccessExternalData) {
2048 // If -fdirect-access-external-data (default for -fno-pic), set dso_local
2049 // for non-thread-local variables. If the symbol is not defined in the
2050 // executable, a copy relocation will be needed at link time. dso_local is
2051 // excluded for thread-local variables because they generally don't support
2052 // copy relocations.
2053 if (auto globalOp = dyn_cast<cir::GlobalOp>(gv.getOperation())) {
2054 // Assume variables are not thread-local until that support is added.
2056 return true;
2057 }
2058
2059 // -fno-pic sets dso_local on a function declaration to allow direct
2060 // accesses when taking its address (similar to a data symbol). If the
2061 // function is not defined in the executable, a canonical PLT entry will be
2062 // needed at link time. -fno-direct-access-external-data can avoid the
2063 // canonical PLT entry. We don't generalize this condition to -fpie/-fpic as
2064 // it could just cause trouble without providing perceptible benefits.
2065 if (isa<cir::FuncOp>(gv) && !cgOpts.NoPLT && rm == llvm::Reloc::Static)
2066 return true;
2067 }
2068
2069 // If we can use copy relocations we can assume it is local.
2070
2071 // Otherwise don't assume it is local.
2072
2073 return false;
2074}
2075
2076void CIRGenModule::setGlobalVisibility(mlir::Operation *gv,
2077 const NamedDecl *d) const {
2079}
2080
2081void CIRGenModule::setDSOLocal(cir::CIRGlobalValueInterface gv) const {
2082 gv.setDSOLocal(shouldAssumeDSOLocal(*this, gv));
2083}
2084
2085void CIRGenModule::setDSOLocal(mlir::Operation *op) const {
2086 if (auto globalValue = dyn_cast<cir::CIRGlobalValueInterface>(op))
2087 setDSOLocal(globalValue);
2088}
2089
2090void CIRGenModule::setGVProperties(mlir::Operation *op,
2091 const NamedDecl *d) const {
2093 setGVPropertiesAux(op, d);
2094}
2095
2096void CIRGenModule::setGVPropertiesAux(mlir::Operation *op,
2097 const NamedDecl *d) const {
2098 setGlobalVisibility(op, d);
2099 setDSOLocal(op);
2101}
2102
2104 switch (getCodeGenOpts().getDefaultTLSModel()) {
2106 return cir::TLS_Model::GeneralDynamic;
2108 return cir::TLS_Model::LocalDynamic;
2110 return cir::TLS_Model::InitialExec;
2112 return cir::TLS_Model::LocalExec;
2113 }
2114 llvm_unreachable("Invalid TLS model!");
2115}
2116
2117void CIRGenModule::setTLSMode(mlir::Operation *op, const VarDecl &d) {
2118 assert(d.getTLSKind() && "setting TLS mode on non-TLS var!");
2119
2120 cir::TLS_Model tlm = getDefaultCIRTLSModel();
2121
2122 // Override the TLS model if it is explicitly specified.
2123 if (d.getAttr<TLSModelAttr>())
2124 errorNYI(d.getSourceRange(), "TLS model attribute");
2125
2126 auto global = cast<cir::GlobalOp>(op);
2127 global.setTlsModel(tlm);
2128}
2129
2131 const CIRGenFunctionInfo &info,
2132 cir::FuncOp func, bool isThunk) {
2133 // TODO(cir): More logic of constructAttributeList is needed.
2134 cir::CallingConv callingConv;
2135 cir::SideEffect sideEffect;
2136
2137 // TODO(cir): The current list should be initialized with the extra function
2138 // attributes, but we don't have those yet. For now, the PAL is initialized
2139 // with nothing.
2141 // Initialize PAL with existing attributes to merge attributes.
2142 mlir::NamedAttrList pal{};
2143 constructAttributeList(func.getName(), info, globalDecl, pal, callingConv,
2144 sideEffect,
2145 /*attrOnCallSite=*/false, isThunk);
2146
2147 for (mlir::NamedAttribute attr : pal)
2148 func->setAttr(attr.getName(), attr.getValue());
2149
2150 // TODO(cir): Check X86_VectorCall incompatibility wiht WinARM64EC
2151
2152 // TODO(cir): typically the calling conv is set right here, but since
2153 // cir::CallingConv is empty and we've not yet added calling-conv to FuncOop,
2154 // this isn't really useful here. This should call func.setCallingConv/etc
2155 // later.
2157}
2158
2160 cir::FuncOp func,
2161 bool isIncompleteFunction,
2162 bool isThunk) {
2163 // NOTE(cir): Original CodeGen checks if this is an intrinsic. In CIR we
2164 // represent them in dedicated ops. The correct attributes are ensured during
2165 // translation to LLVM. Thus, we don't need to check for them here.
2166
2167 if (!isIncompleteFunction)
2168 setCIRFunctionAttributes(globalDecl,
2169 getTypes().arrangeGlobalDeclaration(globalDecl),
2170 func, isThunk);
2171
2173
2174 // TODO(cir): This needs a lot of work to better match CodeGen. That
2175 // ultimately ends up in setGlobalVisibility, which already has the linkage of
2176 // the LLVM GV (corresponding to our FuncOp) computed, so it doesn't have to
2177 // recompute it here. This is a minimal fix for now.
2178 if (!isLocalLinkage(getFunctionLinkage(globalDecl))) {
2179 const Decl *decl = globalDecl.getDecl();
2180 func.setGlobalVisibilityAttr(getGlobalVisibilityAttrFromDecl(decl));
2181 }
2182
2183 // If we plan on emitting this inline builtin, we can't treat it as a builtin.
2184 const auto *fd = cast<FunctionDecl>(globalDecl.getDecl());
2185 if (fd->isInlineBuiltinDeclaration()) {
2186 const FunctionDecl *fdBody;
2187 bool hasBody = fd->hasBody(fdBody);
2188 (void)hasBody;
2189 assert(hasBody && "Inline builtin declarations should always have an "
2190 "available body!");
2192 }
2193}
2194
2196 const clang::FunctionDecl *decl, cir::FuncOp f) {
2199
2200 std::optional<cir::InlineKind> existingInlineKind = f.getInlineKind();
2201 bool isNoInline =
2202 existingInlineKind && *existingInlineKind == cir::InlineKind::NoInline;
2203 bool isAlwaysInline = existingInlineKind &&
2204 *existingInlineKind == cir::InlineKind::AlwaysInline;
2205 if (!decl) {
2206 assert(!cir::MissingFeatures::hlsl());
2207
2208 if (!isAlwaysInline &&
2209 codeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) {
2210 // If inlining is disabled and we don't have a declaration to control
2211 // inlining, mark the function as 'noinline' unless it is explicitly
2212 // marked as 'alwaysinline'.
2213 f.setInlineKind(cir::InlineKind::NoInline);
2214 }
2215
2216 return;
2217 }
2218
2225 assert(!cir::MissingFeatures::hlsl());
2226
2227 // Handle inline attributes
2228 if (decl->hasAttr<NoInlineAttr>() && !isAlwaysInline) {
2229 // Add noinline if the function isn't always_inline.
2230 f.setInlineKind(cir::InlineKind::NoInline);
2231 } else if (decl->hasAttr<AlwaysInlineAttr>() && !isNoInline) {
2232 // Don't override AlwaysInline with NoInline, or vice versa, since we can't
2233 // specify both in IR.
2234 f.setInlineKind(cir::InlineKind::AlwaysInline);
2235 } else if (codeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) {
2236 // If inlining is disabled, force everything that isn't always_inline
2237 // to carry an explicit noinline attribute.
2238 if (!isAlwaysInline) {
2239 f.setInlineKind(cir::InlineKind::NoInline);
2240 }
2241 } else {
2242 // Otherwise, propagate the inline hint attribute and potentially use its
2243 // absence to mark things as noinline.
2244 // Search function and template pattern redeclarations for inline.
2245 if (auto *fd = dyn_cast<FunctionDecl>(decl)) {
2246 // TODO: Share this checkForInline implementation with classic codegen.
2247 // This logic is likely to change over time, so sharing would help ensure
2248 // consistency.
2249 auto checkForInline = [](const FunctionDecl *decl) {
2250 auto checkRedeclForInline = [](const FunctionDecl *redecl) {
2251 return redecl->isInlineSpecified();
2252 };
2253 if (any_of(decl->redecls(), checkRedeclForInline))
2254 return true;
2255 const FunctionDecl *pattern = decl->getTemplateInstantiationPattern();
2256 if (!pattern)
2257 return false;
2258 return any_of(pattern->redecls(), checkRedeclForInline);
2259 };
2260 if (checkForInline(fd)) {
2261 f.setInlineKind(cir::InlineKind::InlineHint);
2262 } else if (codeGenOpts.getInlining() ==
2264 !fd->isInlined() && !isAlwaysInline) {
2265 f.setInlineKind(cir::InlineKind::NoInline);
2266 }
2267 }
2268 }
2269
2271}
2272
2274 StringRef mangledName, mlir::Type funcType, GlobalDecl gd, bool forVTable,
2275 bool dontDefer, bool isThunk, ForDefinition_t isForDefinition,
2276 mlir::ArrayAttr extraAttrs) {
2277 const Decl *d = gd.getDecl();
2278
2279 if (isThunk)
2280 errorNYI(d->getSourceRange(), "getOrCreateCIRFunction: thunk");
2281
2282 // In what follows, we continue past 'errorNYI' as if nothing happened because
2283 // the rest of the implementation is better than doing nothing.
2284
2285 if (const auto *fd = cast_or_null<FunctionDecl>(d)) {
2286 // For the device mark the function as one that should be emitted.
2287 if (getLangOpts().OpenMPIsTargetDevice && fd->isDefined() && !dontDefer &&
2288 !isForDefinition)
2289 errorNYI(fd->getSourceRange(),
2290 "getOrCreateCIRFunction: OpenMP target function");
2291
2292 // Any attempts to use a MultiVersion function should result in retrieving
2293 // the iFunc instead. Name mangling will handle the rest of the changes.
2294 if (fd->isMultiVersion())
2295 errorNYI(fd->getSourceRange(), "getOrCreateCIRFunction: multi-version");
2296 }
2297
2298 // Lookup the entry, lazily creating it if necessary.
2299 mlir::Operation *entry = getGlobalValue(mangledName);
2300 if (entry) {
2301 assert(mlir::isa<cir::FuncOp>(entry));
2302
2304
2305 // Handle dropped DLL attributes.
2306 if (d && !d->hasAttr<DLLImportAttr>() && !d->hasAttr<DLLExportAttr>()) {
2308 setDSOLocal(entry);
2309 }
2310
2311 // If there are two attempts to define the same mangled name, issue an
2312 // error.
2313 auto fn = cast<cir::FuncOp>(entry);
2314 if (isForDefinition && fn && !fn.isDeclaration()) {
2315 errorNYI(d->getSourceRange(), "Duplicate function definition");
2316 }
2317 if (fn && fn.getFunctionType() == funcType) {
2318 return fn;
2319 }
2320
2321 if (!isForDefinition) {
2322 return fn;
2323 }
2324
2325 // TODO(cir): classic codegen checks here if this is a llvm::GlobalAlias.
2326 // How will we support this?
2327 }
2328
2329 auto *funcDecl = llvm::cast_or_null<FunctionDecl>(gd.getDecl());
2330 bool invalidLoc = !funcDecl ||
2331 funcDecl->getSourceRange().getBegin().isInvalid() ||
2332 funcDecl->getSourceRange().getEnd().isInvalid();
2333 cir::FuncOp funcOp = createCIRFunction(
2334 invalidLoc ? theModule->getLoc() : getLoc(funcDecl->getSourceRange()),
2335 mangledName, mlir::cast<cir::FuncType>(funcType), funcDecl);
2336
2337 // If we already created a function with the same mangled name (but different
2338 // type) before, take its name and add it to the list of functions to be
2339 // replaced with F at the end of CodeGen.
2340 //
2341 // This happens if there is a prototype for a function (e.g. "int f()") and
2342 // then a definition of a different type (e.g. "int f(int x)").
2343 if (entry) {
2344
2345 // Fetch a generic symbol-defining operation and its uses.
2346 auto symbolOp = mlir::cast<mlir::SymbolOpInterface>(entry);
2347
2348 // This might be an implementation of a function without a prototype, in
2349 // which case, try to do special replacement of calls which match the new
2350 // prototype. The really key thing here is that we also potentially drop
2351 // arguments from the call site so as to make a direct call, which makes the
2352 // inliner happier and suppresses a number of optimizer warnings (!) about
2353 // dropping arguments.
2354 if (symbolOp.getSymbolUses(symbolOp->getParentOp()))
2356
2357 // Obliterate no-proto declaration.
2358 entry->erase();
2359 }
2360
2361 if (d)
2362 setFunctionAttributes(gd, funcOp, /*isIncompleteFunction=*/false, isThunk);
2363
2364 // 'dontDefer' actually means don't move this to the deferredDeclsToEmit list.
2365 if (dontDefer) {
2366 // TODO(cir): This assertion will need an additional condition when we
2367 // support incomplete functions.
2368 assert(funcOp.getFunctionType() == funcType);
2369 return funcOp;
2370 }
2371
2372 // All MSVC dtors other than the base dtor are linkonce_odr and delegate to
2373 // each other bottoming out wiht the base dtor. Therefore we emit non-base
2374 // dtors on usage, even if there is no dtor definition in the TU.
2375 if (isa_and_nonnull<CXXDestructorDecl>(d) &&
2376 getCXXABI().useThunkForDtorVariant(cast<CXXDestructorDecl>(d),
2377 gd.getDtorType()))
2378 errorNYI(d->getSourceRange(), "getOrCreateCIRFunction: dtor");
2379
2380 // This is the first use or definition of a mangled name. If there is a
2381 // deferred decl with this name, remember that we need to emit it at the end
2382 // of the file.
2383 auto ddi = deferredDecls.find(mangledName);
2384 if (ddi != deferredDecls.end()) {
2385 // Move the potentially referenced deferred decl to the
2386 // DeferredDeclsToEmit list, and remove it from DeferredDecls (since we
2387 // don't need it anymore).
2388 addDeferredDeclToEmit(ddi->second);
2389 deferredDecls.erase(ddi);
2390
2391 // Otherwise, there are cases we have to worry about where we're using a
2392 // declaration for which we must emit a definition but where we might not
2393 // find a top-level definition.
2394 // - member functions defined inline in their classes
2395 // - friend functions defined inline in some class
2396 // - special member functions with implicit definitions
2397 // If we ever change our AST traversal to walk into class methods, this
2398 // will be unnecessary.
2399 //
2400 // We also don't emit a definition for a function if it's going to be an
2401 // entry in a vtable, unless it's already marked as used.
2402 } else if (getLangOpts().CPlusPlus && d) {
2403 // Look for a declaration that's lexically in a record.
2404 for (const auto *fd = cast<FunctionDecl>(d)->getMostRecentDecl(); fd;
2405 fd = fd->getPreviousDecl()) {
2406 if (isa<CXXRecordDecl>(fd->getLexicalDeclContext())) {
2407 if (fd->doesThisDeclarationHaveABody()) {
2409 break;
2410 }
2411 }
2412 }
2413 }
2414
2415 return funcOp;
2416}
2417
2418cir::FuncOp
2419CIRGenModule::createCIRFunction(mlir::Location loc, StringRef name,
2420 cir::FuncType funcType,
2421 const clang::FunctionDecl *funcDecl) {
2422 cir::FuncOp func;
2423 {
2424 mlir::OpBuilder::InsertionGuard guard(builder);
2425
2426 // Some global emissions are triggered while emitting a function, e.g.
2427 // void s() { x.method() }
2428 //
2429 // Be sure to insert a new function before a current one.
2430 CIRGenFunction *cgf = this->curCGF;
2431 if (cgf)
2432 builder.setInsertionPoint(cgf->curFn);
2433
2434 func = cir::FuncOp::create(builder, loc, name, funcType);
2435
2437
2438 if (funcDecl && !funcDecl->hasPrototype())
2439 func.setNoProto(true);
2440
2441 assert(func.isDeclaration() && "expected empty body");
2442
2443 // A declaration gets private visibility by default, but external linkage
2444 // as the default linkage.
2445 func.setLinkageAttr(cir::GlobalLinkageKindAttr::get(
2446 &getMLIRContext(), cir::GlobalLinkageKind::ExternalLinkage));
2447 mlir::SymbolTable::setSymbolVisibility(
2448 func, mlir::SymbolTable::Visibility::Private);
2449
2451
2452 // Mark C++ special member functions (Constructor, Destructor etc.)
2453 setCXXSpecialMemberAttr(func, funcDecl);
2454
2455 if (!cgf)
2456 theModule.push_back(func);
2457
2458 if (this->getLangOpts().OpenACC) {
2459 // We only have to handle this attribute, since OpenACCAnnotAttrs are
2460 // handled via the end-of-TU work.
2461 for (const auto *attr :
2462 funcDecl->specific_attrs<OpenACCRoutineDeclAttr>())
2463 emitOpenACCRoutineDecl(funcDecl, func, attr->getLocation(),
2464 attr->Clauses);
2465 }
2466 }
2467 return func;
2468}
2469
2470cir::FuncOp
2471CIRGenModule::createCIRBuiltinFunction(mlir::Location loc, StringRef name,
2472 cir::FuncType ty,
2473 const clang::FunctionDecl *fd) {
2474 cir::FuncOp fnOp = createCIRFunction(loc, name, ty, fd);
2475 fnOp.setBuiltin(true);
2476 return fnOp;
2477}
2478
2479static cir::CtorKind getCtorKindFromDecl(const CXXConstructorDecl *ctor) {
2480 if (ctor->isDefaultConstructor())
2481 return cir::CtorKind::Default;
2482 if (ctor->isCopyConstructor())
2483 return cir::CtorKind::Copy;
2484 if (ctor->isMoveConstructor())
2485 return cir::CtorKind::Move;
2486 return cir::CtorKind::Custom;
2487}
2488
2489static cir::AssignKind getAssignKindFromDecl(const CXXMethodDecl *method) {
2490 if (method->isCopyAssignmentOperator())
2491 return cir::AssignKind::Copy;
2492 if (method->isMoveAssignmentOperator())
2493 return cir::AssignKind::Move;
2494 llvm_unreachable("not a copy or move assignment operator");
2495}
2496
2498 cir::FuncOp funcOp, const clang::FunctionDecl *funcDecl) {
2499 if (!funcDecl)
2500 return;
2501
2502 if (const auto *dtor = dyn_cast<CXXDestructorDecl>(funcDecl)) {
2503 auto cxxDtor = cir::CXXDtorAttr::get(
2504 convertType(getASTContext().getCanonicalTagType(dtor->getParent())),
2505 dtor->isTrivial());
2506 funcOp.setCxxSpecialMemberAttr(cxxDtor);
2507 return;
2508 }
2509
2510 if (const auto *ctor = dyn_cast<CXXConstructorDecl>(funcDecl)) {
2511 cir::CtorKind kind = getCtorKindFromDecl(ctor);
2512 auto cxxCtor = cir::CXXCtorAttr::get(
2513 convertType(getASTContext().getCanonicalTagType(ctor->getParent())),
2514 kind, ctor->isTrivial());
2515 funcOp.setCxxSpecialMemberAttr(cxxCtor);
2516 return;
2517 }
2518
2519 const auto *method = dyn_cast<CXXMethodDecl>(funcDecl);
2520 if (method && (method->isCopyAssignmentOperator() ||
2521 method->isMoveAssignmentOperator())) {
2522 cir::AssignKind assignKind = getAssignKindFromDecl(method);
2523 auto cxxAssign = cir::CXXAssignAttr::get(
2524 convertType(getASTContext().getCanonicalTagType(method->getParent())),
2525 assignKind, method->isTrivial());
2526 funcOp.setCxxSpecialMemberAttr(cxxAssign);
2527 return;
2528 }
2529}
2530
2531static void setWindowsItaniumDLLImport(CIRGenModule &cgm, bool isLocal,
2532 cir::FuncOp funcOp, StringRef name) {
2533 // In Windows Itanium environments, try to mark runtime functions
2534 // dllimport. For Mingw and MSVC, don't. We don't really know if the user
2535 // will link their standard library statically or dynamically. Marking
2536 // functions imported when they are not imported can cause linker errors
2537 // and warnings.
2538 if (!isLocal && cgm.getTarget().getTriple().isWindowsItaniumEnvironment() &&
2539 !cgm.getCodeGenOpts().LTOVisibilityPublicStd) {
2543 }
2544}
2545
2546cir::FuncOp CIRGenModule::createRuntimeFunction(cir::FuncType ty,
2547 StringRef name, mlir::ArrayAttr,
2548 bool isLocal,
2549 bool assumeConvergent) {
2550 if (assumeConvergent)
2551 errorNYI("createRuntimeFunction: assumeConvergent");
2552
2553 cir::FuncOp entry = getOrCreateCIRFunction(name, ty, GlobalDecl(),
2554 /*forVtable=*/false);
2555
2556 if (entry) {
2557 // TODO(cir): set the attributes of the function.
2560 setWindowsItaniumDLLImport(*this, isLocal, entry, name);
2561 entry.setDSOLocal(true);
2562 }
2563
2564 return entry;
2565}
2566
2567mlir::SymbolTable::Visibility
2569 // MLIR doesn't accept public symbols declarations (only
2570 // definitions).
2571 if (op.isDeclaration())
2572 return mlir::SymbolTable::Visibility::Private;
2573 return getMLIRVisibilityFromCIRLinkage(op.getLinkage());
2574}
2575
2576mlir::SymbolTable::Visibility
2578 switch (glk) {
2579 case cir::GlobalLinkageKind::InternalLinkage:
2580 case cir::GlobalLinkageKind::PrivateLinkage:
2581 return mlir::SymbolTable::Visibility::Private;
2582 case cir::GlobalLinkageKind::ExternalLinkage:
2583 case cir::GlobalLinkageKind::ExternalWeakLinkage:
2584 case cir::GlobalLinkageKind::LinkOnceODRLinkage:
2585 case cir::GlobalLinkageKind::AvailableExternallyLinkage:
2586 case cir::GlobalLinkageKind::CommonLinkage:
2587 case cir::GlobalLinkageKind::WeakAnyLinkage:
2588 case cir::GlobalLinkageKind::WeakODRLinkage:
2589 return mlir::SymbolTable::Visibility::Public;
2590 default: {
2591 llvm::errs() << "visibility not implemented for '"
2592 << stringifyGlobalLinkageKind(glk) << "'\n";
2593 assert(0 && "not implemented");
2594 }
2595 }
2596 llvm_unreachable("linkage should be handled above!");
2597}
2598
2600 clang::VisibilityAttr::VisibilityType visibility) {
2601 switch (visibility) {
2602 case clang::VisibilityAttr::VisibilityType::Default:
2603 return cir::VisibilityKind::Default;
2604 case clang::VisibilityAttr::VisibilityType::Hidden:
2605 return cir::VisibilityKind::Hidden;
2606 case clang::VisibilityAttr::VisibilityType::Protected:
2607 return cir::VisibilityKind::Protected;
2608 }
2609 llvm_unreachable("unexpected visibility value");
2610}
2611
2612cir::VisibilityAttr
2614 const clang::VisibilityAttr *va = decl->getAttr<clang::VisibilityAttr>();
2615 cir::VisibilityAttr cirVisibility =
2616 cir::VisibilityAttr::get(&getMLIRContext());
2617 if (va) {
2618 cirVisibility = cir::VisibilityAttr::get(
2619 &getMLIRContext(),
2620 getGlobalVisibilityKindFromClangVisibility(va->getVisibility()));
2621 }
2622 return cirVisibility;
2623}
2624
2626 emitDeferred();
2627 applyReplacements();
2628
2629 theModule->setAttr(cir::CIRDialect::getModuleLevelAsmAttrName(),
2630 builder.getArrayAttr(globalScopeAsm));
2631
2632 // There's a lot of code that is not implemented yet.
2634}
2635
2636void CIRGenModule::emitAliasForGlobal(StringRef mangledName,
2637 mlir::Operation *op, GlobalDecl aliasGD,
2638 cir::FuncOp aliasee,
2639 cir::GlobalLinkageKind linkage) {
2640
2641 auto *aliasFD = dyn_cast<FunctionDecl>(aliasGD.getDecl());
2642 assert(aliasFD && "expected FunctionDecl");
2643
2644 // The aliasee function type is different from the alias one, this difference
2645 // is specific to CIR because in LLVM the ptr types are already erased at this
2646 // point.
2647 const CIRGenFunctionInfo &fnInfo =
2649 cir::FuncType fnType = getTypes().getFunctionType(fnInfo);
2650
2651 cir::FuncOp alias =
2653 mangledName, fnType, aliasFD);
2654 alias.setAliasee(aliasee.getName());
2655 alias.setLinkage(linkage);
2656 // Declarations cannot have public MLIR visibility, just mark them private
2657 // but this really should have no meaning since CIR should not be using
2658 // this information to derive linkage information.
2659 mlir::SymbolTable::setSymbolVisibility(
2660 alias, mlir::SymbolTable::Visibility::Private);
2661
2662 // Alias constructors and destructors are always unnamed_addr.
2664
2665 // Switch any previous uses to the alias.
2666 if (op) {
2667 errorNYI(aliasFD->getSourceRange(), "emitAliasForGlobal: previous uses");
2668 } else {
2669 // Name already set by createCIRFunction
2670 }
2671
2672 // Finally, set up the alias with its proper name and attributes.
2673 setCommonAttributes(aliasGD, alias);
2674}
2675
2677 return genTypes.convertType(type);
2678}
2679
2681 // Verify the module after we have finished constructing it, this will
2682 // check the structural properties of the IR and invoke any specific
2683 // verifiers we have on the CIR operations.
2684 return mlir::verify(theModule).succeeded();
2685}
2686
2687mlir::Attribute CIRGenModule::getAddrOfRTTIDescriptor(mlir::Location loc,
2688 QualType ty, bool forEh) {
2689 // Return a bogus pointer if RTTI is disabled, unless it's for EH.
2690 // FIXME: should we even be calling this method if RTTI is disabled
2691 // and it's not for EH?
2692 if (!shouldEmitRTTI(forEh))
2693 return builder.getConstNullPtrAttr(builder.getUInt8PtrTy());
2694
2695 if (forEh && ty->isObjCObjectPointerType() &&
2696 langOpts.ObjCRuntime.isGNUFamily()) {
2697 errorNYI(loc, "getAddrOfRTTIDescriptor: Objc PtrType & Objc RT GUN");
2698 return {};
2699 }
2700
2701 return getCXXABI().getAddrOfRTTIDescriptor(loc, ty);
2702}
2703
2704// TODO(cir): this can be shared with LLVM codegen.
2706 const CXXRecordDecl *derivedClass,
2707 llvm::iterator_range<CastExpr::path_const_iterator> path) {
2708 CharUnits offset = CharUnits::Zero();
2709
2710 const ASTContext &astContext = getASTContext();
2711 const CXXRecordDecl *rd = derivedClass;
2712
2713 for (const CXXBaseSpecifier *base : path) {
2714 assert(!base->isVirtual() && "Should not see virtual bases here!");
2715
2716 // Get the layout.
2717 const ASTRecordLayout &layout = astContext.getASTRecordLayout(rd);
2718
2719 const auto *baseDecl = base->getType()->castAsCXXRecordDecl();
2720
2721 // Add the offset.
2722 offset += layout.getBaseClassOffset(baseDecl);
2723
2724 rd = baseDecl;
2725 }
2726
2727 return offset;
2728}
2729
2731 llvm::StringRef feature) {
2732 unsigned diagID = diags.getCustomDiagID(
2733 DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0");
2734 return diags.Report(loc, diagID) << feature;
2735}
2736
2738 llvm::StringRef feature) {
2739 return errorNYI(loc.getBegin(), feature) << loc;
2740}
2741
2743 unsigned diagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error, "%0");
2744 getDiags().Report(astContext.getFullLoc(loc), diagID) << error;
2745}
2746
2747/// Print out an error that codegen doesn't support the specified stmt yet.
2748void CIRGenModule::errorUnsupported(const Stmt *s, llvm::StringRef type) {
2749 unsigned diagId = diags.getCustomDiagID(DiagnosticsEngine::Error,
2750 "cannot compile this %0 yet");
2751 diags.Report(astContext.getFullLoc(s->getBeginLoc()), diagId)
2752 << type << s->getSourceRange();
2753}
2754
2755/// Print out an error that codegen doesn't support the specified decl yet.
2756void CIRGenModule::errorUnsupported(const Decl *d, llvm::StringRef type) {
2757 unsigned diagId = diags.getCustomDiagID(DiagnosticsEngine::Error,
2758 "cannot compile this %0 yet");
2759 diags.Report(astContext.getFullLoc(d->getLocation()), diagId) << type;
2760}
2761
2762void CIRGenModule::mapBlockAddress(cir::BlockAddrInfoAttr blockInfo,
2763 cir::LabelOp label) {
2764 [[maybe_unused]] auto result =
2765 blockAddressInfoToLabel.try_emplace(blockInfo, label);
2766 assert(result.second &&
2767 "attempting to map a blockaddress info that is already mapped");
2768}
2769
2770void CIRGenModule::mapUnresolvedBlockAddress(cir::BlockAddressOp op) {
2771 [[maybe_unused]] auto result = unresolvedBlockAddressToLabel.insert(op);
2772 assert(result.second &&
2773 "attempting to map a blockaddress operation that is already mapped");
2774}
2775
2776void CIRGenModule::mapResolvedBlockAddress(cir::BlockAddressOp op,
2777 cir::LabelOp label) {
2778 [[maybe_unused]] auto result = blockAddressToLabel.try_emplace(op, label);
2779 assert(result.second &&
2780 "attempting to map a blockaddress operation that is already mapped");
2781}
2782
2784 cir::LabelOp newLabel) {
2785 auto *it = blockAddressToLabel.find(op);
2786 assert(it != blockAddressToLabel.end() &&
2787 "trying to update a blockaddress not previously mapped");
2788 assert(!it->second && "blockaddress already has a resolved label");
2789
2790 it->second = newLabel;
2791}
2792
2793cir::LabelOp
2794CIRGenModule::lookupBlockAddressInfo(cir::BlockAddrInfoAttr blockInfo) {
2795 return blockAddressInfoToLabel.lookup(blockInfo);
2796}
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.
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
Defines the SourceManager interface.
__device__ __2f16 float __ockl_bool s
__device__ __2f16 float c
cir::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:870
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:909
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)
clang::DiagnosticsEngine & getDiags() const
mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc, QualType ty, bool forEH=false)
Get the address of the RTTI descriptor for the given type.
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
void setCIRFunctionAttributes(GlobalDecl gd, const CIRGenFunctionInfo &info, cir::FuncOp func, bool isThunk)
Set the CIR function attributes (Sext, zext, etc).
const llvm::Triple & getTriple() const
static mlir::SymbolTable::Visibility getMLIRVisibility(Visibility v)
void emitTentativeDefinition(const VarDecl *d)
cir::GlobalOp createOrReplaceCXXRuntimeVariable(mlir::Location loc, llvm::StringRef name, mlir::Type ty, cir::GlobalLinkageKind linkage, clang::CharUnits alignment)
Will return a global variable of the given type.
void emitOMPAllocateDecl(const OMPAllocateDecl *d)
void error(SourceLocation loc, llvm::StringRef error)
Emit a general error that something can't be done.
void emitGlobalDecl(const clang::GlobalDecl &d)
Helper for emitDeferred to apply actual codegen.
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 ...
void errorUnsupported(const Stmt *s, llvm::StringRef type)
Print out an error that codegen doesn't support the specified stmt yet.
mlir::Value getAddrOfGlobalVar(const VarDecl *d, mlir::Type ty={}, ForDefinition_t isForDefinition=NotForDefinition)
Return the mlir::Value for the address of the given global variable.
static void setInitializer(cir::GlobalOp &op, mlir::Attribute value)
cir::GlobalViewAttr getAddrOfGlobalVarAttr(const VarDecl *d)
Return the mlir::GlobalViewAttr for the address of the given global.
void addGlobalCtor(cir::FuncOp ctor, std::optional< int > priority=std::nullopt)
Add a global constructor or destructor to the module.
cir::GlobalLinkageKind getFunctionLinkage(GlobalDecl gd)
void updateCompletedType(const clang::TagDecl *td)
const clang::CodeGenOptions & getCodeGenOpts() const
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)
void constructAttributeList(llvm::StringRef name, const CIRGenFunctionInfo &info, CIRGenCalleeInfo calleeInfo, mlir::NamedAttrList &attrs, cir::CallingConv &callingConv, cir::SideEffect &sideEffect, bool attrOnCallSite, bool isThunk)
Get the CIR attributes and calling convention to use for a particular function type.
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
SourceLocation getLocation() const
Definition DeclBase.h:439
bool hasAttr() const
Definition DeclBase.h:577
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition DeclBase.h:427
Represents a ValueDecl that came out of a declarator.
Definition Decl.h:780
A little helper class used to produce diagnostics.
Concrete class used by the front-end to report problems and issues.
Definition Diagnostic.h:232
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
Definition Diagnostic.h:905
ExplicitCastExpr - An explicit cast written in the source code.
Definition Expr.h:3928
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:3199
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:2957
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:8428
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8342
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition TypeBase.h:8375
bool isConstantStorage(const ASTContext &Ctx, bool ExcludeCtor, bool ExcludeDtor)
Definition TypeBase.h:1036
bool hasUnaligned() const
Definition TypeBase.h:511
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
This class handles loading and caching of source files into memory.
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
Stmt - This represents one statement.
Definition Stmt.h:86
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp: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:8539
bool isReferenceType() const
Definition TypeBase.h:8563
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:2436
bool isObjCObjectPointerType() const
Definition TypeBase.h:8714
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9121
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:2179
bool hasInit() const
Definition Decl.cpp:2409
DefinitionKind isThisDeclarationADefinition(ASTContext &) const
Check whether this declaration is a definition.
Definition Decl.cpp:2271
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:2201
bool hasFlexibleArrayInit(const ASTContext &Ctx) const
Whether this variable has a flexible array member initialized with one or more elements.
Definition Decl.cpp:2873
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:2659
VarDecl * getDefinition(ASTContext &)
Get the real (not just tentative) definition for this declaration.
Definition Decl.cpp:2377
QualType::DestructionKind needsDestruction(const ASTContext &Ctx) const
Would the destruction of this variable have any effect, and if so, what kind?
Definition Decl.cpp:2862
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:2386
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:2790
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 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.