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