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