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