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
1427// TODO(cir): this could be a common AST helper for both CIR and LLVM codegen.
1429 if (getLangOpts().OpenCL)
1431
1432 // For temporaries inside functions, CUDA treats them as normal variables.
1433 // LangAS::cuda_device, on the other hand, is reserved for those variables
1434 // explicitly marked with __device__.
1435 if (getLangOpts().CUDAIsDevice)
1436 return LangAS::Default;
1437
1438 if (getLangOpts().SYCLIsDevice ||
1439 (getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice))
1440 errorNYI("SYCL or OpenMP temp address space");
1441 return LangAS::Default;
1442}
1443
1445 CIRGenFunction *cgf) {
1446 if (cgf && e->getType()->isVariablyModifiedType())
1448
1450 "emitExplicitCastExprType");
1451}
1452
1454 for (Decl *decl : dc->decls()) {
1455 // Unlike other DeclContexts, the contents of an ObjCImplDecl at TU scope
1456 // are themselves considered "top-level", so EmitTopLevelDecl on an
1457 // ObjCImplDecl does not recursively visit them. We need to do that in
1458 // case they're nested inside another construct (LinkageSpecDecl /
1459 // ExportDecl) that does stop them from being considered "top-level".
1460 if (auto *oid = dyn_cast<ObjCImplDecl>(decl))
1461 errorNYI(oid->getSourceRange(), "emitDeclConext: ObjCImplDecl");
1462
1464 }
1465}
1466
1467// Emit code for a single top level declaration.
1469
1470 // Ignore dependent declarations.
1471 if (decl->isTemplated())
1472 return;
1473
1474 switch (decl->getKind()) {
1475 default:
1476 errorNYI(decl->getBeginLoc(), "declaration of kind",
1477 decl->getDeclKindName());
1478 break;
1479
1480 case Decl::CXXConversion:
1481 case Decl::CXXMethod:
1482 case Decl::Function: {
1483 auto *fd = cast<FunctionDecl>(decl);
1484 // Consteval functions shouldn't be emitted.
1485 if (!fd->isConsteval())
1486 emitGlobal(fd);
1487 break;
1488 }
1489
1490 case Decl::Var:
1491 case Decl::Decomposition:
1492 case Decl::VarTemplateSpecialization: {
1493 auto *vd = cast<VarDecl>(decl);
1495 errorNYI(decl->getSourceRange(), "global variable decompositions");
1496 break;
1497 }
1498 emitGlobal(vd);
1499 break;
1500 }
1501 case Decl::OpenACCRoutine:
1503 break;
1504 case Decl::OpenACCDeclare:
1506 break;
1507 case Decl::Enum:
1508 case Decl::Using: // using X; [C++]
1509 case Decl::UsingDirective: // using namespace X; [C++]
1510 case Decl::UsingEnum: // using enum X; [C++]
1511 case Decl::NamespaceAlias:
1512 case Decl::Typedef:
1513 case Decl::TypeAlias: // using foo = bar; [C++11]
1514 case Decl::Record:
1516 break;
1517
1518 // No code generation needed.
1519 case Decl::ClassTemplate:
1520 case Decl::Concept:
1521 case Decl::CXXDeductionGuide:
1522 case Decl::Empty:
1523 case Decl::FunctionTemplate:
1524 case Decl::StaticAssert:
1525 case Decl::TypeAliasTemplate:
1526 case Decl::UsingShadow:
1527 case Decl::VarTemplate:
1528 case Decl::VarTemplatePartialSpecialization:
1529 break;
1530
1531 case Decl::CXXConstructor:
1533 break;
1534 case Decl::CXXDestructor:
1536 break;
1537
1538 // C++ Decls
1539 case Decl::LinkageSpec:
1540 case Decl::Namespace:
1542 break;
1543
1544 case Decl::ClassTemplateSpecialization:
1545 case Decl::CXXRecord:
1548 break;
1549
1550 case Decl::FileScopeAsm:
1551 // File-scope asm is ignored during device-side CUDA compilation.
1552 if (langOpts.CUDA && langOpts.CUDAIsDevice)
1553 break;
1554 // File-scope asm is ignored during device-side OpenMP compilation.
1555 if (langOpts.OpenMPIsTargetDevice)
1556 break;
1557 // File-scope asm is ignored during device-side SYCL compilation.
1558 if (langOpts.SYCLIsDevice)
1559 break;
1560 auto *file_asm = cast<FileScopeAsmDecl>(decl);
1561 std::string line = file_asm->getAsmString();
1562 globalScopeAsm.push_back(builder.getStringAttr(line));
1563 break;
1564 }
1565}
1566
1567void CIRGenModule::setInitializer(cir::GlobalOp &op, mlir::Attribute value) {
1568 // Recompute visibility when updating initializer.
1569 op.setInitialValueAttr(value);
1571}
1572
1573std::pair<cir::FuncType, cir::FuncOp> CIRGenModule::getAddrAndTypeOfCXXStructor(
1574 GlobalDecl gd, const CIRGenFunctionInfo *fnInfo, cir::FuncType fnType,
1575 bool dontDefer, ForDefinition_t isForDefinition) {
1576 auto *md = cast<CXXMethodDecl>(gd.getDecl());
1577
1578 if (isa<CXXDestructorDecl>(md)) {
1579 // Always alias equivalent complete destructors to base destructors in the
1580 // MS ABI.
1581 if (getTarget().getCXXABI().isMicrosoft() &&
1582 gd.getDtorType() == Dtor_Complete &&
1583 md->getParent()->getNumVBases() == 0)
1584 errorNYI(md->getSourceRange(),
1585 "getAddrAndTypeOfCXXStructor: MS ABI complete destructor");
1586 }
1587
1588 if (!fnType) {
1589 if (!fnInfo)
1591 fnType = getTypes().getFunctionType(*fnInfo);
1592 }
1593
1594 auto fn = getOrCreateCIRFunction(getMangledName(gd), fnType, gd,
1595 /*ForVtable=*/false, dontDefer,
1596 /*IsThunk=*/false, isForDefinition);
1597
1598 return {fnType, fn};
1599}
1600
1602 mlir::Type funcType, bool forVTable,
1603 bool dontDefer,
1604 ForDefinition_t isForDefinition) {
1605 assert(!cast<FunctionDecl>(gd.getDecl())->isConsteval() &&
1606 "consteval function should never be emitted");
1607
1608 if (!funcType) {
1609 const auto *fd = cast<FunctionDecl>(gd.getDecl());
1610 funcType = convertType(fd->getType());
1611 }
1612
1613 // Devirtualized destructor calls may come through here instead of via
1614 // getAddrOfCXXStructor. Make sure we use the MS ABI base destructor instead
1615 // of the complete destructor when necessary.
1616 if (const auto *dd = dyn_cast<CXXDestructorDecl>(gd.getDecl())) {
1617 if (getTarget().getCXXABI().isMicrosoft() &&
1618 gd.getDtorType() == Dtor_Complete &&
1619 dd->getParent()->getNumVBases() == 0)
1620 errorNYI(dd->getSourceRange(),
1621 "getAddrOfFunction: MS ABI complete destructor");
1622 }
1623
1624 StringRef mangledName = getMangledName(gd);
1625 cir::FuncOp func =
1626 getOrCreateCIRFunction(mangledName, funcType, gd, forVTable, dontDefer,
1627 /*isThunk=*/false, isForDefinition);
1628 return func;
1629}
1630
1631static std::string getMangledNameImpl(CIRGenModule &cgm, GlobalDecl gd,
1632 const NamedDecl *nd) {
1633 SmallString<256> buffer;
1634
1635 llvm::raw_svector_ostream out(buffer);
1637
1639
1640 if (mc.shouldMangleDeclName(nd)) {
1641 mc.mangleName(gd.getWithDecl(nd), out);
1642 } else {
1643 IdentifierInfo *ii = nd->getIdentifier();
1644 assert(ii && "Attempt to mangle unnamed decl.");
1645
1646 const auto *fd = dyn_cast<FunctionDecl>(nd);
1647 if (fd &&
1648 fd->getType()->castAs<FunctionType>()->getCallConv() == CC_X86RegCall) {
1649 cgm.errorNYI(nd->getSourceRange(), "getMangledName: X86RegCall");
1650 } else if (fd && fd->hasAttr<CUDAGlobalAttr>() &&
1652 cgm.errorNYI(nd->getSourceRange(), "getMangledName: CUDA device stub");
1653 }
1654 out << ii->getName();
1655 }
1656
1657 // Check if the module name hash should be appended for internal linkage
1658 // symbols. This should come before multi-version target suffixes are
1659 // appendded. This is to keep the name and module hash suffix of the internal
1660 // linkage function together. The unique suffix should only be added when name
1661 // mangling is done to make sure that the final name can be properly
1662 // demangled. For example, for C functions without prototypes, name mangling
1663 // is not done and the unique suffix should not be appended then.
1665
1666 if (const auto *fd = dyn_cast<FunctionDecl>(nd)) {
1667 if (fd->isMultiVersion()) {
1668 cgm.errorNYI(nd->getSourceRange(),
1669 "getMangledName: multi-version functions");
1670 }
1671 }
1672 if (cgm.getLangOpts().GPURelocatableDeviceCode) {
1673 cgm.errorNYI(nd->getSourceRange(),
1674 "getMangledName: GPU relocatable device code");
1675 }
1676
1677 return std::string(out.str());
1678}
1679
1681 GlobalDecl canonicalGd = gd.getCanonicalDecl();
1682
1683 // Some ABIs don't have constructor variants. Make sure that base and complete
1684 // constructors get mangled the same.
1685 if (const auto *cd = dyn_cast<CXXConstructorDecl>(canonicalGd.getDecl())) {
1686 if (!getTarget().getCXXABI().hasConstructorVariants()) {
1687 errorNYI(cd->getSourceRange(),
1688 "getMangledName: C++ constructor without variants");
1689 return cast<NamedDecl>(gd.getDecl())->getIdentifier()->getName();
1690 }
1691 }
1692
1693 // Keep the first result in the case of a mangling collision.
1694 const auto *nd = cast<NamedDecl>(gd.getDecl());
1695 std::string mangledName = getMangledNameImpl(*this, gd, nd);
1696
1697 auto result = manglings.insert(std::make_pair(mangledName, gd));
1698 return mangledDeclNames[canonicalGd] = result.first->first();
1699}
1700
1702 assert(!d->getInit() && "Cannot emit definite definitions here!");
1703
1704 StringRef mangledName = getMangledName(d);
1705 mlir::Operation *gv = getGlobalValue(mangledName);
1706
1707 // If we already have a definition, not declaration, with the same mangled
1708 // name, emitting of declaration is not required (and would actually overwrite
1709 // the emitted definition).
1710 if (gv && !mlir::cast<cir::GlobalOp>(gv).isDeclaration())
1711 return;
1712
1713 // If we have not seen a reference to this variable yet, place it into the
1714 // deferred declarations table to be emitted if needed later.
1715 if (!mustBeEmitted(d) && !gv) {
1716 deferredDecls[mangledName] = d;
1717 return;
1718 }
1719
1720 // The tentative definition is the only definition.
1722}
1723
1725 // Never defer when EmitAllDecls is specified.
1726 if (langOpts.EmitAllDecls)
1727 return true;
1728
1729 const auto *vd = dyn_cast<VarDecl>(global);
1730 if (vd &&
1731 ((codeGenOpts.KeepPersistentStorageVariables &&
1732 (vd->getStorageDuration() == SD_Static ||
1733 vd->getStorageDuration() == SD_Thread)) ||
1734 (codeGenOpts.KeepStaticConsts && vd->getStorageDuration() == SD_Static &&
1735 vd->getType().isConstQualified())))
1736 return true;
1737
1738 return getASTContext().DeclMustBeEmitted(global);
1739}
1740
1742 // In OpenMP 5.0 variables and function may be marked as
1743 // device_type(host/nohost) and we should not emit them eagerly unless we sure
1744 // that they must be emitted on the host/device. To be sure we need to have
1745 // seen a declare target with an explicit mentioning of the function, we know
1746 // we have if the level of the declare target attribute is -1. Note that we
1747 // check somewhere else if we should emit this at all.
1748 if (langOpts.OpenMP >= 50 && !langOpts.OpenMPSimd) {
1749 std::optional<OMPDeclareTargetDeclAttr *> activeAttr =
1750 OMPDeclareTargetDeclAttr::getActiveAttr(global);
1751 if (!activeAttr || (*activeAttr)->getLevel() != (unsigned)-1)
1752 return false;
1753 }
1754
1755 const auto *fd = dyn_cast<FunctionDecl>(global);
1756 if (fd) {
1757 // Implicit template instantiations may change linkage if they are later
1758 // explicitly instantiated, so they should not be emitted eagerly.
1759 if (fd->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
1760 return false;
1761 // Defer until all versions have been semantically checked.
1762 if (fd->hasAttr<TargetVersionAttr>() && !fd->isMultiVersion())
1763 return false;
1764 if (langOpts.SYCLIsDevice) {
1765 errorNYI(fd->getSourceRange(), "mayBeEmittedEagerly: SYCL");
1766 return false;
1767 }
1768 }
1769 const auto *vd = dyn_cast<VarDecl>(global);
1770 if (vd)
1771 if (astContext.getInlineVariableDefinitionKind(vd) ==
1773 // A definition of an inline constexpr static data member may change
1774 // linkage later if it's redeclared outside the class.
1775 return false;
1776
1777 // If OpenMP is enabled and threadprivates must be generated like TLS, delay
1778 // codegen for global variables, because they may be marked as threadprivate.
1779 if (langOpts.OpenMP && langOpts.OpenMPUseTLS &&
1780 astContext.getTargetInfo().isTLSSupported() && isa<VarDecl>(global) &&
1781 !global->getType().isConstantStorage(astContext, false, false) &&
1782 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(global))
1783 return false;
1784
1785 assert((fd || vd) &&
1786 "Only FunctionDecl and VarDecl should hit this path so far.");
1787 return true;
1788}
1789
1790static bool shouldAssumeDSOLocal(const CIRGenModule &cgm,
1791 cir::CIRGlobalValueInterface gv) {
1792 if (gv.hasLocalLinkage())
1793 return true;
1794
1795 if (!gv.hasDefaultVisibility() && !gv.hasExternalWeakLinkage())
1796 return true;
1797
1798 // DLLImport explicitly marks the GV as external.
1799 // so it shouldn't be dso_local
1800 // But we don't have the info set now
1802
1803 const llvm::Triple &tt = cgm.getTriple();
1804 const CodeGenOptions &cgOpts = cgm.getCodeGenOpts();
1805 if (tt.isOSCygMing()) {
1806 // In MinGW and Cygwin, variables without DLLImport can still be
1807 // automatically imported from a DLL by the linker; don't mark variables
1808 // that potentially could come from another DLL as DSO local.
1809
1810 // With EmulatedTLS, TLS variables can be autoimported from other DLLs
1811 // (and this actually happens in the public interface of libstdc++), so
1812 // such variables can't be marked as DSO local. (Native TLS variables
1813 // can't be dllimported at all, though.)
1814 cgm.errorNYI("shouldAssumeDSOLocal: MinGW");
1815 }
1816
1817 // On COFF, don't mark 'extern_weak' symbols as DSO local. If these symbols
1818 // remain unresolved in the link, they can be resolved to zero, which is
1819 // outside the current DSO.
1820 if (tt.isOSBinFormatCOFF() && gv.hasExternalWeakLinkage())
1821 return false;
1822
1823 // Every other GV is local on COFF.
1824 // Make an exception for windows OS in the triple: Some firmware builds use
1825 // *-win32-macho triples. This (accidentally?) produced windows relocations
1826 // without GOT tables in older clang versions; Keep this behaviour.
1827 // FIXME: even thread local variables?
1828 if (tt.isOSBinFormatCOFF() || (tt.isOSWindows() && tt.isOSBinFormatMachO()))
1829 return true;
1830
1831 // Only handle COFF and ELF for now.
1832 if (!tt.isOSBinFormatELF())
1833 return false;
1834
1835 llvm::Reloc::Model rm = cgOpts.RelocationModel;
1836 const LangOptions &lOpts = cgm.getLangOpts();
1837 if (rm != llvm::Reloc::Static && !lOpts.PIE) {
1838 // On ELF, if -fno-semantic-interposition is specified and the target
1839 // supports local aliases, there will be neither CC1
1840 // -fsemantic-interposition nor -fhalf-no-semantic-interposition. Set
1841 // dso_local on the function if using a local alias is preferable (can avoid
1842 // PLT indirection).
1843 if (!(isa<cir::FuncOp>(gv) && gv.canBenefitFromLocalAlias()))
1844 return false;
1845 return !(lOpts.SemanticInterposition || lOpts.HalfNoSemanticInterposition);
1846 }
1847
1848 // A definition cannot be preempted from an executable.
1849 if (!gv.isDeclarationForLinker())
1850 return true;
1851
1852 // Most PIC code sequences that assume that a symbol is local cannot produce a
1853 // 0 if it turns out the symbol is undefined. While this is ABI and relocation
1854 // depended, it seems worth it to handle it here.
1855 if (rm == llvm::Reloc::PIC_ && gv.hasExternalWeakLinkage())
1856 return false;
1857
1858 // PowerPC64 prefers TOC indirection to avoid copy relocations.
1859 if (tt.isPPC64())
1860 return false;
1861
1862 if (cgOpts.DirectAccessExternalData) {
1863 // If -fdirect-access-external-data (default for -fno-pic), set dso_local
1864 // for non-thread-local variables. If the symbol is not defined in the
1865 // executable, a copy relocation will be needed at link time. dso_local is
1866 // excluded for thread-local variables because they generally don't support
1867 // copy relocations.
1868 if (auto globalOp = dyn_cast<cir::GlobalOp>(gv.getOperation())) {
1869 // Assume variables are not thread-local until that support is added.
1871 return true;
1872 }
1873
1874 // -fno-pic sets dso_local on a function declaration to allow direct
1875 // accesses when taking its address (similar to a data symbol). If the
1876 // function is not defined in the executable, a canonical PLT entry will be
1877 // needed at link time. -fno-direct-access-external-data can avoid the
1878 // canonical PLT entry. We don't generalize this condition to -fpie/-fpic as
1879 // it could just cause trouble without providing perceptible benefits.
1880 if (isa<cir::FuncOp>(gv) && !cgOpts.NoPLT && rm == llvm::Reloc::Static)
1881 return true;
1882 }
1883
1884 // If we can use copy relocations we can assume it is local.
1885
1886 // Otherwise don't assume it is local.
1887
1888 return false;
1889}
1890
1891void CIRGenModule::setGlobalVisibility(mlir::Operation *gv,
1892 const NamedDecl *d) const {
1894}
1895
1896void CIRGenModule::setDSOLocal(cir::CIRGlobalValueInterface gv) const {
1897 gv.setDSOLocal(shouldAssumeDSOLocal(*this, gv));
1898}
1899
1900void CIRGenModule::setDSOLocal(mlir::Operation *op) const {
1901 if (auto globalValue = dyn_cast<cir::CIRGlobalValueInterface>(op))
1902 setDSOLocal(globalValue);
1903}
1904
1905void CIRGenModule::setGVProperties(mlir::Operation *op,
1906 const NamedDecl *d) const {
1908 setGVPropertiesAux(op, d);
1909}
1910
1911void CIRGenModule::setGVPropertiesAux(mlir::Operation *op,
1912 const NamedDecl *d) const {
1913 setGlobalVisibility(op, d);
1914 setDSOLocal(op);
1916}
1917
1919 cir::FuncOp func,
1920 bool isIncompleteFunction,
1921 bool isThunk) {
1922 // NOTE(cir): Original CodeGen checks if this is an intrinsic. In CIR we
1923 // represent them in dedicated ops. The correct attributes are ensured during
1924 // translation to LLVM. Thus, we don't need to check for them here.
1925
1928
1929 // TODO(cir): This needs a lot of work to better match CodeGen. That
1930 // ultimately ends up in setGlobalVisibility, which already has the linkage of
1931 // the LLVM GV (corresponding to our FuncOp) computed, so it doesn't have to
1932 // recompute it here. This is a minimal fix for now.
1933 if (!isLocalLinkage(getFunctionLinkage(globalDecl))) {
1934 const Decl *decl = globalDecl.getDecl();
1935 func.setGlobalVisibilityAttr(getGlobalVisibilityAttrFromDecl(decl));
1936 }
1937
1938 // If we plan on emitting this inline builtin, we can't treat it as a builtin.
1939 const auto *fd = cast<FunctionDecl>(globalDecl.getDecl());
1940 if (fd->isInlineBuiltinDeclaration()) {
1941 const FunctionDecl *fdBody;
1942 bool hasBody = fd->hasBody(fdBody);
1943 (void)hasBody;
1944 assert(hasBody && "Inline builtin declarations should always have an "
1945 "available body!");
1947 }
1948}
1949
1951 const clang::FunctionDecl *decl, cir::FuncOp f) {
1954
1955 std::optional<cir::InlineKind> existingInlineKind = f.getInlineKind();
1956 bool isNoInline =
1957 existingInlineKind && *existingInlineKind == cir::InlineKind::NoInline;
1958 bool isAlwaysInline = existingInlineKind &&
1959 *existingInlineKind == cir::InlineKind::AlwaysInline;
1960
1961 if (!decl) {
1962 assert(!cir::MissingFeatures::hlsl());
1963
1964 if (!isAlwaysInline &&
1965 codeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) {
1966 // If inlining is disabled and we don't have a declaration to control
1967 // inlining, mark the function as 'noinline' unless it is explicitly
1968 // marked as 'alwaysinline'.
1969 f.setInlineKindAttr(
1970 cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline));
1971 }
1972
1973 return;
1974 }
1975
1982 assert(!cir::MissingFeatures::hlsl());
1983
1984 // Handle inline attributes
1985 if (decl->hasAttr<NoInlineAttr>() && !isAlwaysInline) {
1986 // Add noinline if the function isn't always_inline.
1987 f.setInlineKindAttr(
1988 cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline));
1989 } else if (decl->hasAttr<AlwaysInlineAttr>() && !isNoInline) {
1990 // Don't override AlwaysInline with NoInline, or vice versa, since we can't
1991 // specify both in IR.
1992 f.setInlineKindAttr(
1993 cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::AlwaysInline));
1994 } else if (codeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) {
1995 // If inlining is disabled, force everything that isn't always_inline
1996 // to carry an explicit noinline attribute.
1997 if (!isAlwaysInline) {
1998 f.setInlineKindAttr(
1999 cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline));
2000 }
2001 } else {
2002 // Otherwise, propagate the inline hint attribute and potentially use its
2003 // absence to mark things as noinline.
2004 // Search function and template pattern redeclarations for inline.
2005 if (auto *fd = dyn_cast<FunctionDecl>(decl)) {
2006 // TODO: Share this checkForInline implementation with classic codegen.
2007 // This logic is likely to change over time, so sharing would help ensure
2008 // consistency.
2009 auto checkForInline = [](const FunctionDecl *decl) {
2010 auto checkRedeclForInline = [](const FunctionDecl *redecl) {
2011 return redecl->isInlineSpecified();
2012 };
2013 if (any_of(decl->redecls(), checkRedeclForInline))
2014 return true;
2015 const FunctionDecl *pattern = decl->getTemplateInstantiationPattern();
2016 if (!pattern)
2017 return false;
2018 return any_of(pattern->redecls(), checkRedeclForInline);
2019 };
2020 if (checkForInline(fd)) {
2021 f.setInlineKindAttr(cir::InlineAttr::get(&getMLIRContext(),
2022 cir::InlineKind::InlineHint));
2023 } else if (codeGenOpts.getInlining() ==
2025 !fd->isInlined() && !isAlwaysInline) {
2026 f.setInlineKindAttr(
2027 cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline));
2028 }
2029 }
2030 }
2031
2033}
2034
2036 StringRef mangledName, mlir::Type funcType, GlobalDecl gd, bool forVTable,
2037 bool dontDefer, bool isThunk, ForDefinition_t isForDefinition,
2038 mlir::ArrayAttr extraAttrs) {
2039 const Decl *d = gd.getDecl();
2040
2041 if (isThunk)
2042 errorNYI(d->getSourceRange(), "getOrCreateCIRFunction: thunk");
2043
2044 // In what follows, we continue past 'errorNYI' as if nothing happened because
2045 // the rest of the implementation is better than doing nothing.
2046
2047 if (const auto *fd = cast_or_null<FunctionDecl>(d)) {
2048 // For the device mark the function as one that should be emitted.
2049 if (getLangOpts().OpenMPIsTargetDevice && fd->isDefined() && !dontDefer &&
2050 !isForDefinition)
2051 errorNYI(fd->getSourceRange(),
2052 "getOrCreateCIRFunction: OpenMP target function");
2053
2054 // Any attempts to use a MultiVersion function should result in retrieving
2055 // the iFunc instead. Name mangling will handle the rest of the changes.
2056 if (fd->isMultiVersion())
2057 errorNYI(fd->getSourceRange(), "getOrCreateCIRFunction: multi-version");
2058 }
2059
2060 // Lookup the entry, lazily creating it if necessary.
2061 mlir::Operation *entry = getGlobalValue(mangledName);
2062 if (entry) {
2063 assert(mlir::isa<cir::FuncOp>(entry));
2064
2066
2067 // Handle dropped DLL attributes.
2068 if (d && !d->hasAttr<DLLImportAttr>() && !d->hasAttr<DLLExportAttr>()) {
2070 setDSOLocal(entry);
2071 }
2072
2073 // If there are two attempts to define the same mangled name, issue an
2074 // error.
2075 auto fn = cast<cir::FuncOp>(entry);
2076 if (isForDefinition && fn && !fn.isDeclaration()) {
2077 errorNYI(d->getSourceRange(), "Duplicate function definition");
2078 }
2079 if (fn && fn.getFunctionType() == funcType) {
2080 return fn;
2081 }
2082
2083 if (!isForDefinition) {
2084 return fn;
2085 }
2086
2087 // TODO(cir): classic codegen checks here if this is a llvm::GlobalAlias.
2088 // How will we support this?
2089 }
2090
2091 auto *funcDecl = llvm::cast_or_null<FunctionDecl>(gd.getDecl());
2092 bool invalidLoc = !funcDecl ||
2093 funcDecl->getSourceRange().getBegin().isInvalid() ||
2094 funcDecl->getSourceRange().getEnd().isInvalid();
2095 cir::FuncOp funcOp = createCIRFunction(
2096 invalidLoc ? theModule->getLoc() : getLoc(funcDecl->getSourceRange()),
2097 mangledName, mlir::cast<cir::FuncType>(funcType), funcDecl);
2098
2099 // If we already created a function with the same mangled name (but different
2100 // type) before, take its name and add it to the list of functions to be
2101 // replaced with F at the end of CodeGen.
2102 //
2103 // This happens if there is a prototype for a function (e.g. "int f()") and
2104 // then a definition of a different type (e.g. "int f(int x)").
2105 if (entry) {
2106
2107 // Fetch a generic symbol-defining operation and its uses.
2108 auto symbolOp = mlir::cast<mlir::SymbolOpInterface>(entry);
2109
2110 // This might be an implementation of a function without a prototype, in
2111 // which case, try to do special replacement of calls which match the new
2112 // prototype. The really key thing here is that we also potentially drop
2113 // arguments from the call site so as to make a direct call, which makes the
2114 // inliner happier and suppresses a number of optimizer warnings (!) about
2115 // dropping arguments.
2116 if (symbolOp.getSymbolUses(symbolOp->getParentOp()))
2118
2119 // Obliterate no-proto declaration.
2120 entry->erase();
2121 }
2122
2123 if (d)
2124 setFunctionAttributes(gd, funcOp, /*isIncompleteFunction=*/false, isThunk);
2125
2126 // 'dontDefer' actually means don't move this to the deferredDeclsToEmit list.
2127 if (dontDefer) {
2128 // TODO(cir): This assertion will need an additional condition when we
2129 // support incomplete functions.
2130 assert(funcOp.getFunctionType() == funcType);
2131 return funcOp;
2132 }
2133
2134 // All MSVC dtors other than the base dtor are linkonce_odr and delegate to
2135 // each other bottoming out wiht the base dtor. Therefore we emit non-base
2136 // dtors on usage, even if there is no dtor definition in the TU.
2137 if (isa_and_nonnull<CXXDestructorDecl>(d) &&
2138 getCXXABI().useThunkForDtorVariant(cast<CXXDestructorDecl>(d),
2139 gd.getDtorType()))
2140 errorNYI(d->getSourceRange(), "getOrCreateCIRFunction: dtor");
2141
2142 // This is the first use or definition of a mangled name. If there is a
2143 // deferred decl with this name, remember that we need to emit it at the end
2144 // of the file.
2145 auto ddi = deferredDecls.find(mangledName);
2146 if (ddi != deferredDecls.end()) {
2147 // Move the potentially referenced deferred decl to the
2148 // DeferredDeclsToEmit list, and remove it from DeferredDecls (since we
2149 // don't need it anymore).
2150 addDeferredDeclToEmit(ddi->second);
2151 deferredDecls.erase(ddi);
2152
2153 // Otherwise, there are cases we have to worry about where we're using a
2154 // declaration for which we must emit a definition but where we might not
2155 // find a top-level definition.
2156 // - member functions defined inline in their classes
2157 // - friend functions defined inline in some class
2158 // - special member functions with implicit definitions
2159 // If we ever change our AST traversal to walk into class methods, this
2160 // will be unnecessary.
2161 //
2162 // We also don't emit a definition for a function if it's going to be an
2163 // entry in a vtable, unless it's already marked as used.
2164 } else if (getLangOpts().CPlusPlus && d) {
2165 // Look for a declaration that's lexically in a record.
2166 for (const auto *fd = cast<FunctionDecl>(d)->getMostRecentDecl(); fd;
2167 fd = fd->getPreviousDecl()) {
2168 if (isa<CXXRecordDecl>(fd->getLexicalDeclContext())) {
2169 if (fd->doesThisDeclarationHaveABody()) {
2171 break;
2172 }
2173 }
2174 }
2175 }
2176
2177 return funcOp;
2178}
2179
2180cir::FuncOp
2181CIRGenModule::createCIRFunction(mlir::Location loc, StringRef name,
2182 cir::FuncType funcType,
2183 const clang::FunctionDecl *funcDecl) {
2184 cir::FuncOp func;
2185 {
2186 mlir::OpBuilder::InsertionGuard guard(builder);
2187
2188 // Some global emissions are triggered while emitting a function, e.g.
2189 // void s() { x.method() }
2190 //
2191 // Be sure to insert a new function before a current one.
2192 CIRGenFunction *cgf = this->curCGF;
2193 if (cgf)
2194 builder.setInsertionPoint(cgf->curFn);
2195
2196 func = cir::FuncOp::create(builder, loc, name, funcType);
2197
2199
2200 if (funcDecl && !funcDecl->hasPrototype())
2201 func.setNoProto(true);
2202
2203 assert(func.isDeclaration() && "expected empty body");
2204
2205 // A declaration gets private visibility by default, but external linkage
2206 // as the default linkage.
2207 func.setLinkageAttr(cir::GlobalLinkageKindAttr::get(
2208 &getMLIRContext(), cir::GlobalLinkageKind::ExternalLinkage));
2209 mlir::SymbolTable::setSymbolVisibility(
2210 func, mlir::SymbolTable::Visibility::Private);
2211
2213
2214 if (!cgf)
2215 theModule.push_back(func);
2216 }
2217 return func;
2218}
2219
2220cir::FuncOp
2221CIRGenModule::createCIRBuiltinFunction(mlir::Location loc, StringRef name,
2222 cir::FuncType ty,
2223 const clang::FunctionDecl *fd) {
2224 cir::FuncOp fnOp = createCIRFunction(loc, name, ty, fd);
2225 fnOp.setBuiltin(true);
2226 return fnOp;
2227}
2228
2229cir::FuncOp CIRGenModule::createRuntimeFunction(cir::FuncType ty,
2230 StringRef name, mlir::ArrayAttr,
2231 [[maybe_unused]] bool isLocal,
2232 bool assumeConvergent) {
2233 if (assumeConvergent)
2234 errorNYI("createRuntimeFunction: assumeConvergent");
2235 if (isLocal)
2236 errorNYI("createRuntimeFunction: local");
2237
2238 cir::FuncOp entry = getOrCreateCIRFunction(name, ty, GlobalDecl(),
2239 /*forVtable=*/false);
2240
2241 if (entry) {
2242 // TODO(cir): set the attributes of the function.
2246 entry.setDSOLocal(true);
2247 }
2248
2249 return entry;
2250}
2251
2252mlir::SymbolTable::Visibility
2254 // MLIR doesn't accept public symbols declarations (only
2255 // definitions).
2256 if (op.isDeclaration())
2257 return mlir::SymbolTable::Visibility::Private;
2258 return getMLIRVisibilityFromCIRLinkage(op.getLinkage());
2259}
2260
2261mlir::SymbolTable::Visibility
2263 switch (glk) {
2264 case cir::GlobalLinkageKind::InternalLinkage:
2265 case cir::GlobalLinkageKind::PrivateLinkage:
2266 return mlir::SymbolTable::Visibility::Private;
2267 case cir::GlobalLinkageKind::ExternalLinkage:
2268 case cir::GlobalLinkageKind::ExternalWeakLinkage:
2269 case cir::GlobalLinkageKind::LinkOnceODRLinkage:
2270 case cir::GlobalLinkageKind::AvailableExternallyLinkage:
2271 case cir::GlobalLinkageKind::CommonLinkage:
2272 case cir::GlobalLinkageKind::WeakAnyLinkage:
2273 case cir::GlobalLinkageKind::WeakODRLinkage:
2274 return mlir::SymbolTable::Visibility::Public;
2275 default: {
2276 llvm::errs() << "visibility not implemented for '"
2277 << stringifyGlobalLinkageKind(glk) << "'\n";
2278 assert(0 && "not implemented");
2279 }
2280 }
2281 llvm_unreachable("linkage should be handled above!");
2282}
2283
2285 clang::VisibilityAttr::VisibilityType visibility) {
2286 switch (visibility) {
2287 case clang::VisibilityAttr::VisibilityType::Default:
2288 return cir::VisibilityKind::Default;
2289 case clang::VisibilityAttr::VisibilityType::Hidden:
2290 return cir::VisibilityKind::Hidden;
2291 case clang::VisibilityAttr::VisibilityType::Protected:
2292 return cir::VisibilityKind::Protected;
2293 }
2294 llvm_unreachable("unexpected visibility value");
2295}
2296
2297cir::VisibilityAttr
2299 const clang::VisibilityAttr *va = decl->getAttr<clang::VisibilityAttr>();
2300 cir::VisibilityAttr cirVisibility =
2301 cir::VisibilityAttr::get(&getMLIRContext());
2302 if (va) {
2303 cirVisibility = cir::VisibilityAttr::get(
2304 &getMLIRContext(),
2305 getGlobalVisibilityKindFromClangVisibility(va->getVisibility()));
2306 }
2307 return cirVisibility;
2308}
2309
2311 emitDeferred();
2312 applyReplacements();
2313
2314 theModule->setAttr(cir::CIRDialect::getModuleLevelAsmAttrName(),
2315 builder.getArrayAttr(globalScopeAsm));
2316
2317 // There's a lot of code that is not implemented yet.
2319}
2320
2321void CIRGenModule::emitAliasForGlobal(StringRef mangledName,
2322 mlir::Operation *op, GlobalDecl aliasGD,
2323 cir::FuncOp aliasee,
2324 cir::GlobalLinkageKind linkage) {
2325
2326 auto *aliasFD = dyn_cast<FunctionDecl>(aliasGD.getDecl());
2327 assert(aliasFD && "expected FunctionDecl");
2328
2329 // The aliasee function type is different from the alias one, this difference
2330 // is specific to CIR because in LLVM the ptr types are already erased at this
2331 // point.
2332 const CIRGenFunctionInfo &fnInfo =
2334 cir::FuncType fnType = getTypes().getFunctionType(fnInfo);
2335
2336 cir::FuncOp alias =
2338 mangledName, fnType, aliasFD);
2339 alias.setAliasee(aliasee.getName());
2340 alias.setLinkage(linkage);
2341 // Declarations cannot have public MLIR visibility, just mark them private
2342 // but this really should have no meaning since CIR should not be using
2343 // this information to derive linkage information.
2344 mlir::SymbolTable::setSymbolVisibility(
2345 alias, mlir::SymbolTable::Visibility::Private);
2346
2347 // Alias constructors and destructors are always unnamed_addr.
2349
2350 // Switch any previous uses to the alias.
2351 if (op) {
2352 errorNYI(aliasFD->getSourceRange(), "emitAliasForGlobal: previous uses");
2353 } else {
2354 // Name already set by createCIRFunction
2355 }
2356
2357 // Finally, set up the alias with its proper name and attributes.
2358 setCommonAttributes(aliasGD, alias);
2359}
2360
2362 return genTypes.convertType(type);
2363}
2364
2366 // Verify the module after we have finished constructing it, this will
2367 // check the structural properties of the IR and invoke any specific
2368 // verifiers we have on the CIR operations.
2369 return mlir::verify(theModule).succeeded();
2370}
2371
2372mlir::Attribute CIRGenModule::getAddrOfRTTIDescriptor(mlir::Location loc,
2373 QualType ty, bool forEh) {
2374 // Return a bogus pointer if RTTI is disabled, unless it's for EH.
2375 // FIXME: should we even be calling this method if RTTI is disabled
2376 // and it's not for EH?
2377 if (!shouldEmitRTTI(forEh))
2378 return builder.getConstNullPtrAttr(builder.getUInt8PtrTy());
2379
2380 if (forEh && ty->isObjCObjectPointerType() &&
2381 langOpts.ObjCRuntime.isGNUFamily()) {
2382 errorNYI(loc, "getAddrOfRTTIDescriptor: Objc PtrType & Objc RT GUN");
2383 return {};
2384 }
2385
2386 return getCXXABI().getAddrOfRTTIDescriptor(loc, ty);
2387}
2388
2389// TODO(cir): this can be shared with LLVM codegen.
2391 const CXXRecordDecl *derivedClass,
2392 llvm::iterator_range<CastExpr::path_const_iterator> path) {
2393 CharUnits offset = CharUnits::Zero();
2394
2395 const ASTContext &astContext = getASTContext();
2396 const CXXRecordDecl *rd = derivedClass;
2397
2398 for (const CXXBaseSpecifier *base : path) {
2399 assert(!base->isVirtual() && "Should not see virtual bases here!");
2400
2401 // Get the layout.
2402 const ASTRecordLayout &layout = astContext.getASTRecordLayout(rd);
2403
2404 const auto *baseDecl = base->getType()->castAsCXXRecordDecl();
2405
2406 // Add the offset.
2407 offset += layout.getBaseClassOffset(baseDecl);
2408
2409 rd = baseDecl;
2410 }
2411
2412 return offset;
2413}
2414
2416 llvm::StringRef feature) {
2417 unsigned diagID = diags.getCustomDiagID(
2418 DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0");
2419 return diags.Report(loc, diagID) << feature;
2420}
2421
2423 llvm::StringRef feature) {
2424 return errorNYI(loc.getBegin(), feature) << loc;
2425}
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:903
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
LangAS getLangTempAllocaAddressSpace() const
Returns the address space for temporary allocations in the language.
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:51
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::TargetAddressSpaceAttr cirAllocaAddressSpace
mlir::Type uCharTy
ClangIR char.
cir::PointerType allocaInt8PtrTy
void* in alloca address space
cir::PointerType voidPtrTy
void* in address space 0
LangStandard - Information about the properties of a particular language standard.