clang 23.0.0git
CIRGenModule.cpp
Go to the documentation of this file.
1//===- CIRGenModule.cpp - Per-Module state for CIR generation -------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This is the internal per-translation-unit state used for CIR translation.
10//
11//===----------------------------------------------------------------------===//
12
13#include "CIRGenModule.h"
14#include "CIRGenCUDARuntime.h"
15#include "CIRGenCXXABI.h"
17#include "CIRGenFunction.h"
18
20#include "clang/AST/ASTLambda.h"
21#include "clang/AST/DeclBase.h"
32
33#include "CIRGenFunctionInfo.h"
34#include "TargetInfo.h"
35#include "mlir/IR/BuiltinOps.h"
36#include "mlir/IR/Location.h"
37#include "mlir/IR/MLIRContext.h"
38#include "mlir/IR/Operation.h"
39#include "mlir/IR/Verifier.h"
40
41#include <algorithm>
42
43using namespace clang;
44using namespace clang::CIRGen;
45
47 switch (cgm.getASTContext().getCXXABIKind()) {
48 case TargetCXXABI::GenericItanium:
49 case TargetCXXABI::GenericAArch64:
50 case TargetCXXABI::AppleARM64:
51 return CreateCIRGenItaniumCXXABI(cgm);
52
53 case TargetCXXABI::Fuchsia:
54 case TargetCXXABI::GenericARM:
55 case TargetCXXABI::iOS:
56 case TargetCXXABI::WatchOS:
57 case TargetCXXABI::GenericMIPS:
58 case TargetCXXABI::WebAssembly:
59 case TargetCXXABI::XL:
60 case TargetCXXABI::Microsoft:
61 cgm.errorNYI("C++ ABI kind not yet implemented");
62 return nullptr;
63 }
64
65 llvm_unreachable("invalid C++ ABI kind");
66}
67
68CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,
69 clang::ASTContext &astContext,
70 const clang::CodeGenOptions &cgo,
71 DiagnosticsEngine &diags)
72 : builder(mlirContext, *this), astContext(astContext),
73 langOpts(astContext.getLangOpts()), codeGenOpts(cgo),
74 theModule{mlir::ModuleOp::create(mlir::UnknownLoc::get(&mlirContext))},
75 diags(diags), target(astContext.getTargetInfo()),
76 abi(createCXXABI(*this)), genTypes(*this), vtables(*this) {
77
78 // Initialize cached types
79 voidTy = cir::VoidType::get(&getMLIRContext());
80 voidPtrTy = cir::PointerType::get(voidTy);
81 sInt8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/true);
82 sInt16Ty = cir::IntType::get(&getMLIRContext(), 16, /*isSigned=*/true);
83 sInt32Ty = cir::IntType::get(&getMLIRContext(), 32, /*isSigned=*/true);
84 sInt64Ty = cir::IntType::get(&getMLIRContext(), 64, /*isSigned=*/true);
85 sInt128Ty = cir::IntType::get(&getMLIRContext(), 128, /*isSigned=*/true);
86 uInt8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/false);
87 uInt8PtrTy = cir::PointerType::get(uInt8Ty);
89 uInt16Ty = cir::IntType::get(&getMLIRContext(), 16, /*isSigned=*/false);
90 uInt32Ty = cir::IntType::get(&getMLIRContext(), 32, /*isSigned=*/false);
91 uInt64Ty = cir::IntType::get(&getMLIRContext(), 64, /*isSigned=*/false);
92 uInt128Ty = cir::IntType::get(&getMLIRContext(), 128, /*isSigned=*/false);
93 fP16Ty = cir::FP16Type::get(&getMLIRContext());
94 bFloat16Ty = cir::BF16Type::get(&getMLIRContext());
95 floatTy = cir::SingleType::get(&getMLIRContext());
96 doubleTy = cir::DoubleType::get(&getMLIRContext());
97 fP80Ty = cir::FP80Type::get(&getMLIRContext());
98 fP128Ty = cir::FP128Type::get(&getMLIRContext());
99
100 allocaInt8PtrTy = cir::PointerType::get(uInt8Ty, cirAllocaAddressSpace);
101
103 astContext
104 .toCharUnitsFromBits(
105 astContext.getTargetInfo().getPointerAlign(LangAS::Default))
106 .getQuantity();
107
108 const unsigned charSize = astContext.getTargetInfo().getCharWidth();
109 uCharTy = cir::IntType::get(&getMLIRContext(), charSize, /*isSigned=*/false);
110
111 // TODO(CIR): Should be updated once TypeSizeInfoAttr is upstreamed
112 const unsigned sizeTypeSize =
113 astContext.getTypeSize(astContext.getSignedSizeType());
114 SizeSizeInBytes = astContext.toCharUnitsFromBits(sizeTypeSize).getQuantity();
115 // In CIRGenTypeCache, UIntPtrTy and SizeType are fields of the same union
116 uIntPtrTy =
117 cir::IntType::get(&getMLIRContext(), sizeTypeSize, /*isSigned=*/false);
118 ptrDiffTy =
119 cir::IntType::get(&getMLIRContext(), sizeTypeSize, /*isSigned=*/true);
120
121 std::optional<cir::SourceLanguage> sourceLanguage = getCIRSourceLanguage();
122 if (sourceLanguage)
123 theModule->setAttr(
124 cir::CIRDialect::getSourceLanguageAttrName(),
125 cir::SourceLanguageAttr::get(&mlirContext, *sourceLanguage));
126 theModule->setAttr(cir::CIRDialect::getTripleAttrName(),
127 builder.getStringAttr(getTriple().str()));
128
129 if (cgo.OptimizationLevel > 0 || cgo.OptimizeSize > 0)
130 theModule->setAttr(cir::CIRDialect::getOptInfoAttrName(),
131 cir::OptInfoAttr::get(&mlirContext,
132 cgo.OptimizationLevel,
133 cgo.OptimizeSize));
134
135 if (langOpts.CUDA)
136 createCUDARuntime();
137
138 // Set the module name to be the name of the main file. TranslationUnitDecl
139 // often contains invalid source locations and isn't a reliable source for the
140 // module location.
141 FileID mainFileId = astContext.getSourceManager().getMainFileID();
142 const FileEntry &mainFile =
143 *astContext.getSourceManager().getFileEntryForID(mainFileId);
144 StringRef path = mainFile.tryGetRealPathName();
145 if (!path.empty()) {
146 theModule.setSymName(path);
147 theModule->setLoc(mlir::FileLineColLoc::get(&mlirContext, path,
148 /*line=*/0,
149 /*column=*/0));
150 }
151}
152
154
155void CIRGenModule::createCUDARuntime() {
156 cudaRuntime.reset(createNVCUDARuntime(*this));
157}
158
159/// FIXME: this could likely be a common helper and not necessarily related
160/// with codegen.
161/// Return the best known alignment for an unknown pointer to a
162/// particular class.
164 if (!rd->hasDefinition())
165 return CharUnits::One(); // Hopefully won't be used anywhere.
166
167 auto &layout = astContext.getASTRecordLayout(rd);
168
169 // If the class is final, then we know that the pointer points to an
170 // object of that type and can use the full alignment.
171 if (rd->isEffectivelyFinal())
172 return layout.getAlignment();
173
174 // Otherwise, we have to assume it could be a subclass.
175 return layout.getNonVirtualAlignment();
176}
177
179 LValueBaseInfo *baseInfo) {
181
182 // FIXME: This duplicates logic in ASTContext::getTypeAlignIfKnown, but
183 // that doesn't return the information we need to compute baseInfo.
184
185 // Honor alignment typedef attributes even on incomplete types.
186 // We also honor them straight for C++ class types, even as pointees;
187 // there's an expressivity gap here.
188 if (const auto *tt = t->getAs<TypedefType>()) {
189 if (unsigned align = tt->getDecl()->getMaxAlignment()) {
190 if (baseInfo)
192 return astContext.toCharUnitsFromBits(align);
193 }
194 }
195
196 // Analyze the base element type, so we don't get confused by incomplete
197 // array types.
198 t = astContext.getBaseElementType(t);
199
200 if (t->isIncompleteType()) {
201 // We could try to replicate the logic from
202 // ASTContext::getTypeAlignIfKnown, but nothing uses the alignment if the
203 // type is incomplete, so it's impossible to test. We could try to reuse
204 // getTypeAlignIfKnown, but that doesn't return the information we need
205 // to set baseInfo. So just ignore the possibility that the alignment is
206 // greater than one.
207 if (baseInfo)
209 return CharUnits::One();
210 }
211
212 if (baseInfo)
214
215 CharUnits alignment;
216 if (t.getQualifiers().hasUnaligned()) {
217 alignment = CharUnits::One();
218 } else {
220 alignment = astContext.getTypeAlignInChars(t);
221 }
222
223 // Cap to the global maximum type alignment unless the alignment
224 // was somehow explicit on the type.
225 if (unsigned maxAlign = astContext.getLangOpts().MaxTypeAlign) {
226 if (alignment.getQuantity() > maxAlign &&
227 !astContext.isAlignmentRequired(t))
228 alignment = CharUnits::fromQuantity(maxAlign);
229 }
230 return alignment;
231}
232
234 if (theTargetCIRGenInfo)
235 return *theTargetCIRGenInfo;
236
237 const llvm::Triple &triple = getTarget().getTriple();
238 switch (triple.getArch()) {
239 default:
241
242 // Currently we just fall through to x86_64.
243 [[fallthrough]];
244
245 case llvm::Triple::x86_64: {
246 switch (triple.getOS()) {
247 default:
249
250 // Currently we just fall through to x86_64.
251 [[fallthrough]];
252
253 case llvm::Triple::Linux:
254 theTargetCIRGenInfo = createX8664TargetCIRGenInfo(genTypes);
255 return *theTargetCIRGenInfo;
256 }
257 }
258 case llvm::Triple::nvptx:
259 case llvm::Triple::nvptx64:
260 theTargetCIRGenInfo = createNVPTXTargetCIRGenInfo(genTypes);
261 return *theTargetCIRGenInfo;
262 }
263}
264
266 assert(cLoc.isValid() && "expected valid source location");
267 const SourceManager &sm = astContext.getSourceManager();
268 PresumedLoc pLoc = sm.getPresumedLoc(cLoc);
269 StringRef filename = pLoc.getFilename();
270 return mlir::FileLineColLoc::get(builder.getStringAttr(filename),
271 pLoc.getLine(), pLoc.getColumn());
272}
273
274mlir::Location CIRGenModule::getLoc(SourceRange cRange) {
275 assert(cRange.isValid() && "expected a valid source range");
276 mlir::Location begin = getLoc(cRange.getBegin());
277 mlir::Location end = getLoc(cRange.getEnd());
278 mlir::Attribute metadata;
279 return mlir::FusedLoc::get({begin, end}, metadata, builder.getContext());
280}
281
282mlir::Operation *
284 const Decl *d = gd.getDecl();
285
287 return getAddrOfCXXStructor(gd, /*FnInfo=*/nullptr, /*FnType=*/nullptr,
288 /*DontDefer=*/false, isForDefinition);
289
290 if (isa<CXXMethodDecl>(d)) {
291 const CIRGenFunctionInfo &fi =
293 cir::FuncType ty = getTypes().getFunctionType(fi);
294 return getAddrOfFunction(gd, ty, /*ForVTable=*/false, /*DontDefer=*/false,
295 isForDefinition);
296 }
297
298 if (isa<FunctionDecl>(d)) {
300 cir::FuncType ty = getTypes().getFunctionType(fi);
301 return getAddrOfFunction(gd, ty, /*ForVTable=*/false, /*DontDefer=*/false,
302 isForDefinition);
303 }
304
305 return getAddrOfGlobalVar(cast<VarDecl>(d), /*ty=*/nullptr, isForDefinition)
306 .getDefiningOp();
307}
308
310 // We call getAddrOfGlobal with isForDefinition set to ForDefinition in
311 // order to get a Value with exactly the type we need, not something that
312 // might have been created for another decl with the same mangled name but
313 // different type.
314 mlir::Operation *op = getAddrOfGlobal(d, ForDefinition);
315
316 // In case of different address spaces, we may still get a cast, even with
317 // IsForDefinition equal to ForDefinition. Query mangled names table to get
318 // GlobalValue.
319 if (!op)
321
322 assert(op && "expected a valid global op");
323
324 // Check to see if we've already emitted this. This is necessary for a
325 // couple of reasons: first, decls can end up in deferred-decls queue
326 // multiple times, and second, decls can end up with definitions in unusual
327 // ways (e.g. by an extern inline function acquiring a strong function
328 // redefinition). Just ignore those cases.
329 // TODO: Not sure what to map this to for MLIR
330 mlir::Operation *globalValueOp = op;
331 if (auto gv = dyn_cast<cir::GetGlobalOp>(op))
332 globalValueOp =
333 mlir::SymbolTable::lookupSymbolIn(getModule(), gv.getNameAttr());
334
335 if (auto cirGlobalValue =
336 dyn_cast<cir::CIRGlobalValueInterface>(globalValueOp))
337 if (!cirGlobalValue.isDeclaration())
338 return;
339
340 // If this is OpenMP, check if it is legal to emit this global normally.
342
343 // Otherwise, emit the definition and move on to the next one.
345}
346
348 // Emit code for any potentially referenced deferred decls. Since a previously
349 // unused static decl may become used during the generation of code for a
350 // static function, iterate until no changes are made.
351
355
356 // Stop if we're out of both deferred vtables and deferred declarations.
357 if (deferredDeclsToEmit.empty())
358 return;
359
360 // Grab the list of decls to emit. If emitGlobalDefinition schedules more
361 // work, it will not interfere with this.
362 std::vector<GlobalDecl> curDeclsToEmit;
363 curDeclsToEmit.swap(deferredDeclsToEmit);
364
365 for (const GlobalDecl &d : curDeclsToEmit) {
367
368 // If we found out that we need to emit more decls, do that recursively.
369 // This has the advantage that the decls are emitted in a DFS and related
370 // ones are close together, which is convenient for testing.
371 if (!deferredDeclsToEmit.empty()) {
372 emitDeferred();
373 assert(deferredDeclsToEmit.empty());
374 }
375 }
376}
377
378template <typename AttrT> static bool hasImplicitAttr(const ValueDecl *decl) {
379 if (!decl)
380 return false;
381 if (auto *attr = decl->getAttr<AttrT>())
382 return attr->isImplicit();
383 return decl->isImplicit();
384}
385
386// TODO(cir): This should be shared with OG Codegen.
388 assert(langOpts.CUDA && "Should not be called by non-CUDA languages");
389 // We need to emit host-side 'shadows' for all global
390 // device-side variables because the CUDA runtime needs their
391 // size and host-side address in order to provide access to
392 // their device-side incarnations.
393 return !langOpts.CUDAIsDevice || global->hasAttr<CUDADeviceAttr>() ||
394 global->hasAttr<CUDAConstantAttr>() ||
395 global->hasAttr<CUDASharedAttr>() ||
398}
399
401 if (const auto *cd = dyn_cast<clang::OpenACCConstructDecl>(gd.getDecl())) {
403 return;
404 }
405
406 // TODO(OMP): The logic in this function for the 'rest' of the OpenMP
407 // declarative declarations is complicated and needs to be done on a per-kind
408 // basis, so all of that needs to be added when we implement the individual
409 // global-allowed declarations. See uses of `cir::MissingFeatures::openMP
410 // throughout this function.
411
412 const auto *global = cast<ValueDecl>(gd.getDecl());
413
414 // If this is CUDA, be selective about which declarations we emit.
415 // Non-constexpr non-lambda implicit host device functions are not emitted
416 // unless they are used on device side.
417 if (langOpts.CUDA) {
418 assert((isa<FunctionDecl>(global) || isa<VarDecl>(global)) &&
419 "Expected Variable or Function");
420 if (const auto *varDecl = dyn_cast<VarDecl>(global)) {
422 return;
423 // TODO(cir): This should be shared with OG Codegen.
424 } else if (langOpts.CUDAIsDevice) {
425 const auto *functionDecl = dyn_cast<FunctionDecl>(global);
426 if ((!global->hasAttr<CUDADeviceAttr>() ||
427 (langOpts.OffloadImplicitHostDeviceTemplates &&
430 !functionDecl->isConstexpr() &&
432 !getASTContext().CUDAImplicitHostDeviceFunUsedByDevice.count(
433 functionDecl))) &&
434 !global->hasAttr<CUDAGlobalAttr>() &&
435 !(langOpts.HIPStdPar && isa<FunctionDecl>(global) &&
436 !global->hasAttr<CUDAHostAttr>()))
437 return;
438 // Device-only functions are the only things we skip.
439 } else if (!global->hasAttr<CUDAHostAttr>() &&
440 global->hasAttr<CUDADeviceAttr>())
441 return;
442 }
443
444 if (const auto *fd = dyn_cast<FunctionDecl>(global)) {
445 // Update deferred annotations with the latest declaration if the function
446 // was already used or defined.
447 if (fd->hasAttr<AnnotateAttr>())
448 errorNYI(fd->getSourceRange(), "deferredAnnotations");
449 if (!fd->doesThisDeclarationHaveABody()) {
450 if (!fd->doesDeclarationForceExternallyVisibleDefinition())
451 return;
452
453 errorNYI(fd->getSourceRange(),
454 "function declaration that forces code gen");
455 return;
456 }
457 } else {
458 const auto *vd = cast<VarDecl>(global);
459 assert(vd->isFileVarDecl() && "Cannot emit local var decl as global.");
460 if (vd->isThisDeclarationADefinition() != VarDecl::Definition &&
461 !astContext.isMSStaticDataMemberInlineDefinition(vd)) {
463 // If this declaration may have caused an inline variable definition to
464 // change linkage, make sure that it's emitted.
465 if (astContext.getInlineVariableDefinitionKind(vd) ==
468 // Otherwise, we can ignore this declaration. The variable will be emitted
469 // on its first use.
470 return;
471 }
472 }
473
474 // Defer code generation to first use when possible, e.g. if this is an inline
475 // function. If the global must always be emitted, do it eagerly if possible
476 // to benefit from cache locality. Deferring code generation is necessary to
477 // avoid adding initializers to external declarations.
478 if (mustBeEmitted(global) && mayBeEmittedEagerly(global)) {
479 // Emit the definition if it can't be deferred.
481 return;
482 }
483
484 // If we're deferring emission of a C++ variable with an initializer, remember
485 // the order in which it appeared on the file.
487
488 llvm::StringRef mangledName = getMangledName(gd);
489 if (getGlobalValue(mangledName) != nullptr) {
490 // The value has already been used and should therefore be emitted.
492 } else if (mustBeEmitted(global)) {
493 // The value must be emitted, but cannot be emitted eagerly.
494 assert(!mayBeEmittedEagerly(global));
496 } else {
497 // Otherwise, remember that we saw a deferred decl with this name. The first
498 // use of the mangled name will cause it to move into deferredDeclsToEmit.
499 deferredDecls[mangledName] = gd;
500 }
501}
502
504 mlir::Operation *op) {
505 auto const *funcDecl = cast<FunctionDecl>(gd.getDecl());
507 cir::FuncType funcType = getTypes().getFunctionType(fi);
508 cir::FuncOp funcOp = dyn_cast_if_present<cir::FuncOp>(op);
509 if (!funcOp || funcOp.getFunctionType() != funcType) {
510 funcOp = getAddrOfFunction(gd, funcType, /*ForVTable=*/false,
511 /*DontDefer=*/true, ForDefinition);
512 }
513
514 // Already emitted.
515 if (!funcOp.isDeclaration())
516 return;
517
518 setFunctionLinkage(gd, funcOp);
519 setGVProperties(funcOp, funcDecl);
521 maybeSetTrivialComdat(*funcDecl, funcOp);
523
524 CIRGenFunction cgf(*this, builder);
525 curCGF = &cgf;
526 {
527 mlir::OpBuilder::InsertionGuard guard(builder);
528 cgf.generateCode(gd, funcOp, funcType);
529 }
530 curCGF = nullptr;
531
532 setNonAliasAttributes(gd, funcOp);
534
535 auto getPriority = [this](const auto *attr) -> int {
536 Expr *e = attr->getPriority();
537 if (e)
538 return e->EvaluateKnownConstInt(this->getASTContext()).getExtValue();
539 return attr->DefaultPriority;
540 };
541
542 if (const ConstructorAttr *ca = funcDecl->getAttr<ConstructorAttr>())
543 addGlobalCtor(funcOp, getPriority(ca));
544 if (const DestructorAttr *da = funcDecl->getAttr<DestructorAttr>())
545 addGlobalDtor(funcOp, getPriority(da));
546
547 if (funcDecl->getAttr<AnnotateAttr>())
548 errorNYI(funcDecl->getSourceRange(), "deferredAnnotations");
549}
550
551/// Track functions to be called before main() runs.
552void CIRGenModule::addGlobalCtor(cir::FuncOp ctor,
553 std::optional<int> priority) {
556
557 // Traditional LLVM codegen directly adds the function to the list of global
558 // ctors. In CIR we just add a global_ctor attribute to the function. The
559 // global list is created in LoweringPrepare.
560 //
561 // FIXME(from traditional LLVM): Type coercion of void()* types.
562 ctor.setGlobalCtorPriority(priority);
563}
564
565/// Add a function to the list that will be called when the module is unloaded.
566void CIRGenModule::addGlobalDtor(cir::FuncOp dtor,
567 std::optional<int> priority) {
568 if (codeGenOpts.RegisterGlobalDtorsWithAtExit &&
569 (!getASTContext().getTargetInfo().getTriple().isOSAIX()))
570 errorNYI(dtor.getLoc(), "registerGlobalDtorsWithAtExit");
571
572 // FIXME(from traditional LLVM): Type coercion of void()* types.
573 dtor.setGlobalDtorPriority(priority);
574}
575
578 if (dk == VarDecl::Definition && vd->hasAttr<DLLImportAttr>())
579 return;
580
582 // If we have a definition, this might be a deferred decl. If the
583 // instantiation is explicit, make sure we emit it at the end.
586
588}
589
590mlir::Operation *CIRGenModule::getGlobalValue(StringRef name) {
591 return mlir::SymbolTable::lookupSymbolIn(theModule, name);
592}
593
594cir::GlobalOp CIRGenModule::createGlobalOp(CIRGenModule &cgm,
595 mlir::Location loc, StringRef name,
596 mlir::Type t, bool isConstant,
597 mlir::Operation *insertPoint) {
598 cir::GlobalOp g;
599 CIRGenBuilderTy &builder = cgm.getBuilder();
600
601 {
602 mlir::OpBuilder::InsertionGuard guard(builder);
603
604 // If an insertion point is provided, we're replacing an existing global,
605 // otherwise, create the new global immediately after the last gloabl we
606 // emitted.
607 if (insertPoint) {
608 builder.setInsertionPoint(insertPoint);
609 } else {
610 // Group global operations together at the top of the module.
611 if (cgm.lastGlobalOp)
612 builder.setInsertionPointAfter(cgm.lastGlobalOp);
613 else
614 builder.setInsertionPointToStart(cgm.getModule().getBody());
615 }
616
617 g = cir::GlobalOp::create(builder, loc, name, t, isConstant);
618 if (!insertPoint)
619 cgm.lastGlobalOp = g;
620
621 // Default to private until we can judge based on the initializer,
622 // since MLIR doesn't allow public declarations.
623 mlir::SymbolTable::setSymbolVisibility(
624 g, mlir::SymbolTable::Visibility::Private);
625 }
626 return g;
627}
628
629void CIRGenModule::setCommonAttributes(GlobalDecl gd, mlir::Operation *gv) {
630 const Decl *d = gd.getDecl();
631 if (isa_and_nonnull<NamedDecl>(d))
632 setGVProperties(gv, dyn_cast<NamedDecl>(d));
635}
636
637void CIRGenModule::setNonAliasAttributes(GlobalDecl gd, mlir::Operation *op) {
638 setCommonAttributes(gd, op);
639
644
646}
647
648std::optional<cir::SourceLanguage> CIRGenModule::getCIRSourceLanguage() const {
649 using ClangStd = clang::LangStandard;
650 using CIRLang = cir::SourceLanguage;
651 auto opts = getLangOpts();
652
653 if (opts.CPlusPlus)
654 return CIRLang::CXX;
655 if (opts.C99 || opts.C11 || opts.C17 || opts.C23 || opts.C2y ||
656 opts.LangStd == ClangStd::lang_c89 ||
657 opts.LangStd == ClangStd::lang_gnu89)
658 return CIRLang::C;
659
660 // TODO(cir): support remaining source languages.
662 errorNYI("CIR does not yet support the given source language");
663 return std::nullopt;
664}
665
666static void setLinkageForGV(cir::GlobalOp &gv, const NamedDecl *nd) {
667 // Set linkage and visibility in case we never see a definition.
669 // Don't set internal linkage on declarations.
670 // "extern_weak" is overloaded in LLVM; we probably should have
671 // separate linkage types for this.
673 (nd->hasAttr<WeakAttr>() || nd->isWeakImported()))
674 gv.setLinkage(cir::GlobalLinkageKind::ExternalWeakLinkage);
675}
676
677// We want to replace a global value, but because of CIR's typed pointers,
678// we need to update the existing uses to reflect the new type, not just replace
679// them directly.
680void CIRGenModule::replaceGlobal(cir::GlobalOp oldGV, cir::GlobalOp newGV) {
681 assert(oldGV.getSymName() == newGV.getSymName() && "symbol names must match");
682
683 mlir::Type oldTy = oldGV.getSymType();
684 mlir::Type newTy = newGV.getSymType();
685
687
688 // If the type didn't change, why are we here?
689 assert(oldTy != newTy && "expected type change in replaceGlobal");
690
691 // Visit all uses and add handling to fix up the types.
692 std::optional<mlir::SymbolTable::UseRange> oldSymUses =
693 oldGV.getSymbolUses(theModule);
694 for (mlir::SymbolTable::SymbolUse use : *oldSymUses) {
695 mlir::Operation *userOp = use.getUser();
696 assert(
697 (mlir::isa<cir::GetGlobalOp, cir::GlobalOp, cir::ConstantOp>(userOp)) &&
698 "Unexpected user for global op");
699
700 if (auto getGlobalOp = dyn_cast<cir::GetGlobalOp>(use.getUser())) {
701 mlir::Value useOpResultValue = getGlobalOp.getAddr();
702 useOpResultValue.setType(cir::PointerType::get(newTy));
703
704 mlir::OpBuilder::InsertionGuard guard(builder);
705 builder.setInsertionPointAfter(getGlobalOp);
706 mlir::Type ptrTy = builder.getPointerTo(oldTy);
707 mlir::Value cast =
708 builder.createBitcast(getGlobalOp->getLoc(), useOpResultValue, ptrTy);
709 useOpResultValue.replaceAllUsesExcept(cast, cast.getDefiningOp());
710 } else {
711 errorNYI(userOp->getLoc(), "Replace global op use in global view attr");
712 }
713 }
714
715 oldGV.erase();
716}
717
718/// If the specified mangled name is not in the module,
719/// create and return an mlir GlobalOp with the specified type (TODO(cir):
720/// address space).
721///
722/// TODO(cir):
723/// 1. If there is something in the module with the specified name, return
724/// it potentially bitcasted to the right type.
725///
726/// 2. If \p d is non-null, it specifies a decl that correspond to this. This
727/// is used to set the attributes on the global when it is first created.
728///
729/// 3. If \p isForDefinition is true, it is guaranteed that an actual global
730/// with type \p ty will be returned, not conversion of a variable with the same
731/// mangled name but some other type.
732cir::GlobalOp
733CIRGenModule::getOrCreateCIRGlobal(StringRef mangledName, mlir::Type ty,
734 LangAS langAS, const VarDecl *d,
735 ForDefinition_t isForDefinition) {
736 // Lookup the entry, lazily creating it if necessary.
737 cir::GlobalOp entry;
738 if (mlir::Operation *v = getGlobalValue(mangledName)) {
739 if (!isa<cir::GlobalOp>(v))
740 errorNYI(d->getSourceRange(), "global with non-GlobalOp type");
741 entry = cast<cir::GlobalOp>(v);
742 }
743
744 if (entry) {
747
750
751 if (entry.getSymType() == ty)
752 return entry;
753
754 // If there are two attempts to define the same mangled name, issue an
755 // error.
756 //
757 // TODO(cir): look at mlir::GlobalValue::isDeclaration for all aspects of
758 // recognizing the global as a declaration, for now only check if
759 // initializer is present.
760 if (isForDefinition && !entry.isDeclaration()) {
761 errorNYI(d->getSourceRange(), "global with conflicting type");
762 }
763
764 // Address space check removed because it is unnecessary because CIR records
765 // address space info in types.
766
767 // (If global is requested for a definition, we always need to create a new
768 // global, not just return a bitcast.)
769 if (!isForDefinition)
770 return entry;
771 }
772
773 mlir::Location loc = getLoc(d->getSourceRange());
774
775 // Calculate constant storage flag before creating the global. This was moved
776 // from after the global creation to ensure the constant flag is set correctly
777 // at creation time, matching the logic used in emitCXXGlobalVarDeclInit.
778 bool isConstant = false;
779 if (d) {
780 bool needsDtor =
782 isConstant = d->getType().isConstantStorage(
783 astContext, /*ExcludeCtor=*/true, /*ExcludeDtor=*/!needsDtor);
784 }
785
786 // mlir::SymbolTable::Visibility::Public is the default, no need to explicitly
787 // mark it as such.
788 cir::GlobalOp gv =
789 CIRGenModule::createGlobalOp(*this, loc, mangledName, ty, isConstant,
790 /*insertPoint=*/entry.getOperation());
791
792 // If we already created a global with the same mangled name (but different
793 // type) before, remove it from its parent.
794 if (entry)
795 replaceGlobal(entry, gv);
796
797 // This is the first use or definition of a mangled name. If there is a
798 // deferred decl with this name, remember that we need to emit it at the end
799 // of the file.
800 auto ddi = deferredDecls.find(mangledName);
801 if (ddi != deferredDecls.end()) {
802 // Move the potentially referenced deferred decl to the DeferredDeclsToEmit
803 // list, and remove it from DeferredDecls (since we don't need it anymore).
804 addDeferredDeclToEmit(ddi->second);
805 deferredDecls.erase(ddi);
806 }
807
808 // Handle things which are present even on external declarations.
809 if (d) {
810 if (langOpts.OpenMP && !langOpts.OpenMPSimd)
811 errorNYI(d->getSourceRange(), "OpenMP target global variable");
812
813 gv.setAlignmentAttr(getSize(astContext.getDeclAlign(d)));
814
815 setLinkageForGV(gv, d);
816
817 if (d->getTLSKind()) {
819 errorNYI(d->getSourceRange(), "TLS dynamic");
820 setTLSMode(gv, *d);
821 }
822
823 setGVProperties(gv, d);
824
825 // If required by the ABI, treat declarations of static data members with
826 // inline initializers as definitions.
827 if (astContext.isMSStaticDataMemberInlineDefinition(d))
828 errorNYI(d->getSourceRange(), "MS static data member inline definition");
829
831 gv.setGlobalVisibilityAttr(getGlobalVisibilityAttrFromDecl(d));
832
833 // Handle XCore specific ABI requirements.
834 if (getTriple().getArch() == llvm::Triple::xcore)
835 errorNYI(d->getSourceRange(), "XCore specific ABI requirements");
836
837 // Check if we a have a const declaration with an initializer, we may be
838 // able to emit it as available_externally to expose it's value to the
839 // optimizer.
840 if (getLangOpts().CPlusPlus && gv.isPublic() &&
841 d->getType().isConstQualified() && gv.isDeclaration() &&
842 !d->hasDefinition() && d->hasInit() && !d->hasAttr<DLLImportAttr>())
844 "external const declaration with initializer");
845 }
846
847 return gv;
848}
849
850cir::GlobalOp
852 ForDefinition_t isForDefinition) {
853 assert(d->hasGlobalStorage() && "Not a global variable");
854 QualType astTy = d->getType();
855 if (!ty)
856 ty = getTypes().convertTypeForMem(astTy);
857
858 StringRef mangledName = getMangledName(d);
859 return getOrCreateCIRGlobal(mangledName, ty, astTy.getAddressSpace(), d,
860 isForDefinition);
861}
862
863/// Return the mlir::Value for the address of the given global variable. If
864/// \p ty is non-null and if the global doesn't exist, then it will be created
865/// with the specified type instead of whatever the normal requested type would
866/// be. If \p isForDefinition is true, it is guaranteed that an actual global
867/// with type \p ty will be returned, not conversion of a variable with the same
868/// mangled name but some other type.
869mlir::Value CIRGenModule::getAddrOfGlobalVar(const VarDecl *d, mlir::Type ty,
870 ForDefinition_t isForDefinition) {
871 assert(d->hasGlobalStorage() && "Not a global variable");
872 QualType astTy = d->getType();
873 if (!ty)
874 ty = getTypes().convertTypeForMem(astTy);
875
876 bool tlsAccess = d->getTLSKind() != VarDecl::TLS_None;
877 cir::GlobalOp g = getOrCreateCIRGlobal(d, ty, isForDefinition);
878 mlir::Type ptrTy = builder.getPointerTo(g.getSymType());
879 return cir::GetGlobalOp::create(
880 builder, getLoc(d->getSourceRange()), ptrTy, g.getSymNameAttr(),
881 tlsAccess,
882 /*static_local=*/g.getStaticLocalGuard().has_value());
883}
884
885cir::GlobalViewAttr CIRGenModule::getAddrOfGlobalVarAttr(const VarDecl *d) {
886 assert(d->hasGlobalStorage() && "Not a global variable");
887 mlir::Type ty = getTypes().convertTypeForMem(d->getType());
888
889 cir::GlobalOp globalOp = getOrCreateCIRGlobal(d, ty, NotForDefinition);
891 cir::PointerType ptrTy = builder.getPointerTo(globalOp.getSymType());
892 return builder.getGlobalViewAttr(ptrTy, globalOp);
893}
894
896 bool isTentative) {
897 if (getLangOpts().OpenCL || getLangOpts().OpenMPIsTargetDevice) {
898 errorNYI(vd->getSourceRange(), "emit OpenCL/OpenMP global variable");
899 return;
900 }
901
902 // Whether the definition of the variable is available externally.
903 // If yes, we shouldn't emit the GloablCtor and GlobalDtor for the variable
904 // since this is the job for its original source.
905 bool isDefinitionAvailableExternally =
906 astContext.GetGVALinkageForVariable(vd) == GVA_AvailableExternally;
907
908 // It is useless to emit the definition for an available_externally variable
909 // which can't be marked as const.
910 if (isDefinitionAvailableExternally &&
912 // TODO: Update this when we have interface to check constexpr
913 // destructor.
914 vd->needsDestruction(astContext) ||
915 !vd->getType().isConstantStorage(astContext, true, true)))
916 return;
917
918 mlir::Attribute init;
919 bool needsGlobalCtor = false;
920 bool needsGlobalDtor =
921 !isDefinitionAvailableExternally &&
923 const VarDecl *initDecl;
924 const Expr *initExpr = vd->getAnyInitializer(initDecl);
925
926 std::optional<ConstantEmitter> emitter;
927
929
930 if (vd->hasAttr<LoaderUninitializedAttr>()) {
931 errorNYI(vd->getSourceRange(), "loader uninitialized attribute");
932 return;
933 } else if (!initExpr) {
934 // This is a tentative definition; tentative definitions are
935 // implicitly initialized with { 0 }.
936 //
937 // Note that tentative definitions are only emitted at the end of
938 // a translation unit, so they should never have incomplete
939 // type. In addition, EmitTentativeDefinition makes sure that we
940 // never attempt to emit a tentative definition if a real one
941 // exists. A use may still exists, however, so we still may need
942 // to do a RAUW.
943 assert(!vd->getType()->isIncompleteType() && "Unexpected incomplete type");
944 init = builder.getZeroInitAttr(convertType(vd->getType()));
945 } else {
946 emitter.emplace(*this);
947 mlir::Attribute initializer = emitter->tryEmitForInitializer(*initDecl);
948 if (!initializer) {
949 QualType qt = initExpr->getType();
950 if (vd->getType()->isReferenceType())
951 qt = vd->getType();
952
953 if (getLangOpts().CPlusPlus) {
954 if (initDecl->hasFlexibleArrayInit(astContext))
955 errorNYI(vd->getSourceRange(), "flexible array initializer");
956 init = builder.getZeroInitAttr(convertType(qt));
957 if (!isDefinitionAvailableExternally)
958 needsGlobalCtor = true;
959 } else {
960 errorNYI(vd->getSourceRange(), "static initializer");
961 }
962 } else {
963 init = initializer;
964 // We don't need an initializer, so remove the entry for the delayed
965 // initializer position (just in case this entry was delayed) if we
966 // also don't need to register a destructor.
968 }
969 }
970
971 mlir::Type initType;
972 if (mlir::isa<mlir::SymbolRefAttr>(init)) {
973 errorNYI(vd->getSourceRange(), "global initializer is a symbol reference");
974 return;
975 } else {
976 assert(mlir::isa<mlir::TypedAttr>(init) && "This should have a type");
977 auto typedInitAttr = mlir::cast<mlir::TypedAttr>(init);
978 initType = typedInitAttr.getType();
979 }
980 assert(!mlir::isa<mlir::NoneType>(initType) && "Should have a type by now");
981
982 cir::GlobalOp gv =
983 getOrCreateCIRGlobal(vd, initType, ForDefinition_t(!isTentative));
984 // TODO(cir): Strip off pointer casts from Entry if we get them?
985
986 if (!gv || gv.getSymType() != initType) {
987 errorNYI(vd->getSourceRange(), "global initializer with type mismatch");
988 return;
989 }
990
992
993 if (vd->hasAttr<AnnotateAttr>()) {
994 errorNYI(vd->getSourceRange(), "annotate global variable");
995 }
996
997 if (langOpts.CUDA) {
998 errorNYI(vd->getSourceRange(), "CUDA global variable");
999 }
1000
1001 // Set initializer and finalize emission
1003 if (emitter)
1004 emitter->finalize(gv);
1005
1006 // If it is safe to mark the global 'constant', do so now.
1007 // Use the same logic as classic codegen EmitGlobalVarDefinition.
1008 gv.setConstant((vd->hasAttr<CUDAConstantAttr>() && langOpts.CUDAIsDevice) ||
1009 (!needsGlobalCtor && !needsGlobalDtor &&
1010 vd->getType().isConstantStorage(astContext,
1011 /*ExcludeCtor=*/true,
1012 /*ExcludeDtor=*/true)));
1014
1015 // Set CIR's linkage type as appropriate.
1016 cir::GlobalLinkageKind linkage =
1017 getCIRLinkageVarDefinition(vd, /*IsConstant=*/false);
1018
1019 // Set CIR linkage and DLL storage class.
1020 gv.setLinkage(linkage);
1021 // FIXME(cir): setLinkage should likely set MLIR's visibility automatically.
1022 gv.setVisibility(getMLIRVisibilityFromCIRLinkage(linkage));
1024 if (linkage == cir::GlobalLinkageKind::CommonLinkage) {
1025 // common vars aren't constant even if declared const.
1026 gv.setConstant(false);
1027 // Tentative definition of global variables may be initialized with
1028 // non-zero null pointers. In this case they should have weak linkage
1029 // since common linkage must have zero initializer and must not have
1030 // explicit section therefore cannot have non-zero initial value.
1031 std::optional<mlir::Attribute> initializer = gv.getInitialValue();
1032 if (initializer && !getBuilder().isNullValue(*initializer))
1033 gv.setLinkage(cir::GlobalLinkageKind::WeakAnyLinkage);
1034 }
1035
1036 setNonAliasAttributes(vd, gv);
1037
1039
1040 maybeSetTrivialComdat(*vd, gv);
1041
1042 // Emit the initializer function if necessary.
1043 if (needsGlobalCtor || needsGlobalDtor)
1044 emitCXXGlobalVarDeclInitFunc(vd, gv, needsGlobalCtor);
1045}
1046
1048 mlir::Operation *op) {
1049 const auto *decl = cast<ValueDecl>(gd.getDecl());
1050 if (const auto *fd = dyn_cast<FunctionDecl>(decl)) {
1051 // TODO(CIR): Skip generation of CIR for functions with available_externally
1052 // linkage at -O0.
1053
1054 if (const auto *method = dyn_cast<CXXMethodDecl>(decl)) {
1055 // Make sure to emit the definition(s) before we emit the thunks. This is
1056 // necessary for the generation of certain thunks.
1057 if (isa<CXXConstructorDecl>(method) || isa<CXXDestructorDecl>(method))
1058 abi->emitCXXStructor(gd);
1059 else if (fd->isMultiVersion())
1060 errorNYI(method->getSourceRange(), "multiversion functions");
1061 else
1063
1064 if (method->isVirtual())
1065 getVTables().emitThunks(gd);
1066
1067 return;
1068 }
1069
1070 if (fd->isMultiVersion())
1071 errorNYI(fd->getSourceRange(), "multiversion functions");
1073 return;
1074 }
1075
1076 if (const auto *vd = dyn_cast<VarDecl>(decl))
1077 return emitGlobalVarDefinition(vd, !vd->hasDefinition());
1078
1079 llvm_unreachable("Invalid argument to CIRGenModule::emitGlobalDefinition");
1080}
1081
1082mlir::Attribute
1084 assert(!e->getType()->isPointerType() && "Strings are always arrays");
1085
1086 // Don't emit it as the address of the string, emit the string data itself
1087 // as an inline array.
1088 if (e->getCharByteWidth() == 1) {
1089 SmallString<64> str(e->getString());
1090
1091 // Resize the string to the right size, which is indicated by its type.
1092 const ConstantArrayType *cat =
1093 astContext.getAsConstantArrayType(e->getType());
1094 uint64_t finalSize = cat->getZExtSize();
1095 str.resize(finalSize);
1096
1097 mlir::Type eltTy = convertType(cat->getElementType());
1098 return builder.getString(str, eltTy, finalSize);
1099 }
1100
1101 auto arrayTy = mlir::cast<cir::ArrayType>(convertType(e->getType()));
1102
1103 auto arrayEltTy = mlir::cast<cir::IntType>(arrayTy.getElementType());
1104
1105 uint64_t arraySize = arrayTy.getSize();
1106 unsigned literalSize = e->getLength();
1107 assert(arraySize == literalSize + 1 &&
1108 "wide string literal array size must be literal length plus null "
1109 "terminator");
1110
1111 // Check if the string is all null bytes before building the vector.
1112 // In most non-zero cases, this will break out on the first element.
1113 bool isAllZero = true;
1114 for (unsigned i = 0; i < literalSize; ++i) {
1115 if (e->getCodeUnit(i) != 0) {
1116 isAllZero = false;
1117 break;
1118 }
1119 }
1120
1121 if (isAllZero)
1122 return cir::ZeroAttr::get(arrayTy);
1123
1124 // Otherwise emit a constant array holding the characters.
1126 elements.reserve(arraySize);
1127 for (unsigned i = 0; i < literalSize; ++i)
1128 elements.push_back(cir::IntAttr::get(arrayEltTy, e->getCodeUnit(i)));
1129 // Add null terminator
1130 elements.push_back(cir::IntAttr::get(arrayEltTy, 0));
1131
1132 auto elementsAttr = mlir::ArrayAttr::get(&getMLIRContext(), elements);
1133 return builder.getConstArray(elementsAttr, arrayTy);
1134}
1135
1137 return getTriple().supportsCOMDAT();
1138}
1139
1140static bool shouldBeInCOMDAT(CIRGenModule &cgm, const Decl &d) {
1141 if (!cgm.supportsCOMDAT())
1142 return false;
1143
1144 if (d.hasAttr<SelectAnyAttr>())
1145 return true;
1146
1147 GVALinkage linkage;
1148 if (auto *vd = dyn_cast<VarDecl>(&d))
1149 linkage = cgm.getASTContext().GetGVALinkageForVariable(vd);
1150 else
1151 linkage =
1153
1154 switch (linkage) {
1158 return false;
1161 return true;
1162 }
1163 llvm_unreachable("No such linkage");
1164}
1165
1166void CIRGenModule::maybeSetTrivialComdat(const Decl &d, mlir::Operation *op) {
1167 if (!shouldBeInCOMDAT(*this, d))
1168 return;
1169 if (auto globalOp = dyn_cast_or_null<cir::GlobalOp>(op)) {
1170 globalOp.setComdat(true);
1171 } else {
1172 auto funcOp = cast<cir::FuncOp>(op);
1173 funcOp.setComdat(true);
1174 }
1175}
1176
1178 // Make sure that this type is translated.
1179 genTypes.updateCompletedType(td);
1180}
1181
1182void CIRGenModule::addReplacement(StringRef name, mlir::Operation *op) {
1183 replacements[name] = op;
1184}
1185
1186void CIRGenModule::replacePointerTypeArgs(cir::FuncOp oldF, cir::FuncOp newF) {
1187 std::optional<mlir::SymbolTable::UseRange> optionalUseRange =
1188 oldF.getSymbolUses(theModule);
1189 if (!optionalUseRange)
1190 return;
1191
1192 for (const mlir::SymbolTable::SymbolUse &u : *optionalUseRange) {
1193 // CallTryOp only shows up after FlattenCFG.
1194 auto call = mlir::dyn_cast<cir::CallOp>(u.getUser());
1195 if (!call)
1196 continue;
1197
1198 for (const auto [argOp, fnArgType] :
1199 llvm::zip(call.getArgs(), newF.getFunctionType().getInputs())) {
1200 if (argOp.getType() == fnArgType)
1201 continue;
1202
1203 // The purpose of this entire function is to insert bitcasts in the case
1204 // where these types don't match, but I haven't seen a case where that
1205 // happens.
1206 errorNYI(call.getLoc(), "replace call with mismatched types");
1207 }
1208 }
1209}
1210
1211void CIRGenModule::applyReplacements() {
1212 for (auto &i : replacements) {
1213 StringRef mangledName = i.first;
1214 mlir::Operation *replacement = i.second;
1215 mlir::Operation *entry = getGlobalValue(mangledName);
1216 if (!entry)
1217 continue;
1218 assert(isa<cir::FuncOp>(entry) && "expected function");
1219 auto oldF = cast<cir::FuncOp>(entry);
1220 auto newF = dyn_cast<cir::FuncOp>(replacement);
1221 if (!newF) {
1222 // In classic codegen, this can be a global alias, a bitcast, or a GEP.
1223 errorNYI(replacement->getLoc(), "replacement is not a function");
1224 continue;
1225 }
1226
1227 // LLVM has opaque pointer but CIR not. So we may have to handle these
1228 // different pointer types when performing replacement.
1229 replacePointerTypeArgs(oldF, newF);
1230
1231 // Replace old with new, but keep the old order.
1232 if (oldF.replaceAllSymbolUses(newF.getSymNameAttr(), theModule).failed())
1233 llvm_unreachable("internal error, cannot RAUW symbol");
1234 if (newF) {
1235 newF->moveBefore(oldF);
1236 oldF->erase();
1237 }
1238 }
1239}
1240
1242 mlir::Location loc, StringRef name, mlir::Type ty,
1243 cir::GlobalLinkageKind linkage, clang::CharUnits alignment) {
1244 auto gv = mlir::dyn_cast_or_null<cir::GlobalOp>(
1245 mlir::SymbolTable::lookupSymbolIn(theModule, name));
1246
1247 if (gv) {
1248 // Check if the variable has the right type.
1249 if (gv.getSymType() == ty)
1250 return gv;
1251
1252 // Because of C++ name mangling, the only way we can end up with an already
1253 // existing global with the same name is if it has been declared extern
1254 // "C".
1255 assert(gv.isDeclaration() && "Declaration has wrong type!");
1256
1257 errorNYI(loc, "createOrReplaceCXXRuntimeVariable: declaration exists with "
1258 "wrong type");
1259 return gv;
1260 }
1261
1262 // Create a new variable.
1263 gv = createGlobalOp(*this, loc, name, ty);
1264
1265 // Set up extra information and add to the module
1266 gv.setLinkageAttr(
1267 cir::GlobalLinkageKindAttr::get(&getMLIRContext(), linkage));
1268 mlir::SymbolTable::setSymbolVisibility(gv,
1270
1271 if (supportsCOMDAT() && cir::isWeakForLinker(linkage) &&
1272 !gv.hasAvailableExternallyLinkage()) {
1273 gv.setComdat(true);
1274 }
1275
1276 gv.setAlignmentAttr(getSize(alignment));
1277 setDSOLocal(static_cast<mlir::Operation *>(gv));
1278 return gv;
1279}
1280
1281// TODO(CIR): this could be a common method between LLVM codegen.
1282static bool isVarDeclStrongDefinition(const ASTContext &astContext,
1283 CIRGenModule &cgm, const VarDecl *vd,
1284 bool noCommon) {
1285 // Don't give variables common linkage if -fno-common was specified unless it
1286 // was overridden by a NoCommon attribute.
1287 if ((noCommon || vd->hasAttr<NoCommonAttr>()) && !vd->hasAttr<CommonAttr>())
1288 return true;
1289
1290 // C11 6.9.2/2:
1291 // A declaration of an identifier for an object that has file scope without
1292 // an initializer, and without a storage-class specifier or with the
1293 // storage-class specifier static, constitutes a tentative definition.
1294 if (vd->getInit() || vd->hasExternalStorage())
1295 return true;
1296
1297 // A variable cannot be both common and exist in a section.
1298 if (vd->hasAttr<SectionAttr>())
1299 return true;
1300
1301 // A variable cannot be both common and exist in a section.
1302 // We don't try to determine which is the right section in the front-end.
1303 // If no specialized section name is applicable, it will resort to default.
1304 if (vd->hasAttr<PragmaClangBSSSectionAttr>() ||
1305 vd->hasAttr<PragmaClangDataSectionAttr>() ||
1306 vd->hasAttr<PragmaClangRelroSectionAttr>() ||
1307 vd->hasAttr<PragmaClangRodataSectionAttr>())
1308 return true;
1309
1310 // Thread local vars aren't considered common linkage.
1311 if (vd->getTLSKind())
1312 return true;
1313
1314 // Tentative definitions marked with WeakImportAttr are true definitions.
1315 if (vd->hasAttr<WeakImportAttr>())
1316 return true;
1317
1318 // A variable cannot be both common and exist in a comdat.
1319 if (shouldBeInCOMDAT(cgm, *vd))
1320 return true;
1321
1322 // Declarations with a required alignment do not have common linkage in MSVC
1323 // mode.
1324 if (astContext.getTargetInfo().getCXXABI().isMicrosoft()) {
1325 if (vd->hasAttr<AlignedAttr>())
1326 return true;
1327 QualType varType = vd->getType();
1328 if (astContext.isAlignmentRequired(varType))
1329 return true;
1330
1331 if (const auto *rd = varType->getAsRecordDecl()) {
1332 for (const FieldDecl *fd : rd->fields()) {
1333 if (fd->isBitField())
1334 continue;
1335 if (fd->hasAttr<AlignedAttr>())
1336 return true;
1337 if (astContext.isAlignmentRequired(fd->getType()))
1338 return true;
1339 }
1340 }
1341 }
1342
1343 // Microsoft's link.exe doesn't support alignments greater than 32 bytes for
1344 // common symbols, so symbols with greater alignment requirements cannot be
1345 // common.
1346 // Other COFF linkers (ld.bfd and LLD) support arbitrary power-of-two
1347 // alignments for common symbols via the aligncomm directive, so this
1348 // restriction only applies to MSVC environments.
1349 if (astContext.getTargetInfo().getTriple().isKnownWindowsMSVCEnvironment() &&
1350 astContext.getTypeAlignIfKnown(vd->getType()) >
1351 astContext.toBits(CharUnits::fromQuantity(32)))
1352 return true;
1353
1354 return false;
1355}
1356
1358 const DeclaratorDecl *dd, GVALinkage linkage, bool isConstantVariable) {
1359 if (linkage == GVA_Internal)
1360 return cir::GlobalLinkageKind::InternalLinkage;
1361
1362 if (dd->hasAttr<WeakAttr>()) {
1363 if (isConstantVariable)
1364 return cir::GlobalLinkageKind::WeakODRLinkage;
1365 return cir::GlobalLinkageKind::WeakAnyLinkage;
1366 }
1367
1368 if (const auto *fd = dd->getAsFunction())
1369 if (fd->isMultiVersion() && linkage == GVA_AvailableExternally)
1370 return cir::GlobalLinkageKind::LinkOnceAnyLinkage;
1371
1372 // We are guaranteed to have a strong definition somewhere else,
1373 // so we can use available_externally linkage.
1374 if (linkage == GVA_AvailableExternally)
1375 return cir::GlobalLinkageKind::AvailableExternallyLinkage;
1376
1377 // Note that Apple's kernel linker doesn't support symbol
1378 // coalescing, so we need to avoid linkonce and weak linkages there.
1379 // Normally, this means we just map to internal, but for explicit
1380 // instantiations we'll map to external.
1381
1382 // In C++, the compiler has to emit a definition in every translation unit
1383 // that references the function. We should use linkonce_odr because
1384 // a) if all references in this translation unit are optimized away, we
1385 // don't need to codegen it. b) if the function persists, it needs to be
1386 // merged with other definitions. c) C++ has the ODR, so we know the
1387 // definition is dependable.
1388 if (linkage == GVA_DiscardableODR)
1389 return !astContext.getLangOpts().AppleKext
1390 ? cir::GlobalLinkageKind::LinkOnceODRLinkage
1391 : cir::GlobalLinkageKind::InternalLinkage;
1392
1393 // An explicit instantiation of a template has weak linkage, since
1394 // explicit instantiations can occur in multiple translation units
1395 // and must all be equivalent. However, we are not allowed to
1396 // throw away these explicit instantiations.
1397 //
1398 // CUDA/HIP: For -fno-gpu-rdc case, device code is limited to one TU,
1399 // so say that CUDA templates are either external (for kernels) or internal.
1400 // This lets llvm perform aggressive inter-procedural optimizations. For
1401 // -fgpu-rdc case, device function calls across multiple TU's are allowed,
1402 // therefore we need to follow the normal linkage paradigm.
1403 if (linkage == GVA_StrongODR) {
1404 if (getLangOpts().AppleKext)
1405 return cir::GlobalLinkageKind::ExternalLinkage;
1406 if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice &&
1407 !getLangOpts().GPURelocatableDeviceCode)
1408 return dd->hasAttr<CUDAGlobalAttr>()
1409 ? cir::GlobalLinkageKind::ExternalLinkage
1410 : cir::GlobalLinkageKind::InternalLinkage;
1411 return cir::GlobalLinkageKind::WeakODRLinkage;
1412 }
1413
1414 // C++ doesn't have tentative definitions and thus cannot have common
1415 // linkage.
1416 if (!getLangOpts().CPlusPlus && isa<VarDecl>(dd) &&
1417 !isVarDeclStrongDefinition(astContext, *this, cast<VarDecl>(dd),
1418 getCodeGenOpts().NoCommon))
1419 return cir::GlobalLinkageKind::CommonLinkage;
1420
1421 // selectany symbols are externally visible, so use weak instead of
1422 // linkonce. MSVC optimizes away references to const selectany globals, so
1423 // all definitions should be the same and ODR linkage should be used.
1424 // http://msdn.microsoft.com/en-us/library/5tkz6s71.aspx
1425 if (dd->hasAttr<SelectAnyAttr>())
1426 return cir::GlobalLinkageKind::WeakODRLinkage;
1427
1428 // Otherwise, we have strong external linkage.
1429 assert(linkage == GVA_StrongExternal);
1430 return cir::GlobalLinkageKind::ExternalLinkage;
1431}
1432
1433/// This function is called when we implement a function with no prototype, e.g.
1434/// "int foo() {}". If there are existing call uses of the old function in the
1435/// module, this adjusts them to call the new function directly.
1436///
1437/// This is not just a cleanup: the always_inline pass requires direct calls to
1438/// functions to be able to inline them. If there is a bitcast in the way, it
1439/// won't inline them. Instcombine normally deletes these calls, but it isn't
1440/// run at -O0.
1442 mlir::Operation *old, cir::FuncOp newFn) {
1443 // If we're redefining a global as a function, don't transform it.
1444 auto oldFn = mlir::dyn_cast<cir::FuncOp>(old);
1445 if (!oldFn)
1446 return;
1447
1448 // TODO(cir): this RAUW ignores the features below.
1452 if (oldFn->getAttrs().size() <= 1)
1453 errorNYI(old->getLoc(),
1454 "replaceUsesOfNonProtoTypeWithRealFunction: Attribute forwarding");
1455
1456 // Mark new function as originated from a no-proto declaration.
1457 newFn.setNoProto(oldFn.getNoProto());
1458
1459 // Iterate through all calls of the no-proto function.
1460 std::optional<mlir::SymbolTable::UseRange> symUses =
1461 oldFn.getSymbolUses(oldFn->getParentOp());
1462 for (const mlir::SymbolTable::SymbolUse &use : symUses.value()) {
1463 mlir::OpBuilder::InsertionGuard guard(builder);
1464
1465 if (auto noProtoCallOp = mlir::dyn_cast<cir::CallOp>(use.getUser())) {
1466 builder.setInsertionPoint(noProtoCallOp);
1467
1468 // Patch call type with the real function type.
1469 cir::CallOp realCallOp = builder.createCallOp(
1470 noProtoCallOp.getLoc(), newFn, noProtoCallOp.getOperands());
1471
1472 // Replace old no proto call with fixed call.
1473 noProtoCallOp.replaceAllUsesWith(realCallOp);
1474 noProtoCallOp.erase();
1475 } else if (auto getGlobalOp =
1476 mlir::dyn_cast<cir::GetGlobalOp>(use.getUser())) {
1477 // Replace type
1478 getGlobalOp.getAddr().setType(
1479 cir::PointerType::get(newFn.getFunctionType()));
1480 } else {
1481 errorNYI(use.getUser()->getLoc(),
1482 "replaceUsesOfNonProtoTypeWithRealFunction: unexpected use");
1483 }
1484 }
1485}
1486
1487cir::GlobalLinkageKind
1489 assert(!isConstant && "constant variables NYI");
1490 GVALinkage linkage = astContext.GetGVALinkageForVariable(vd);
1491 return getCIRLinkageForDeclarator(vd, linkage, isConstant);
1492}
1493
1495 const auto *d = cast<FunctionDecl>(gd.getDecl());
1496
1497 GVALinkage linkage = astContext.GetGVALinkageForFunction(d);
1498
1499 if (const auto *dtor = dyn_cast<CXXDestructorDecl>(d))
1500 return getCXXABI().getCXXDestructorLinkage(linkage, dtor, gd.getDtorType());
1501
1502 return getCIRLinkageForDeclarator(d, linkage, /*isConstantVariable=*/false);
1503}
1504
1505static cir::GlobalOp
1506generateStringLiteral(mlir::Location loc, mlir::TypedAttr c,
1507 cir::GlobalLinkageKind lt, CIRGenModule &cgm,
1508 StringRef globalName, CharUnits alignment) {
1510
1511 // Create a global variable for this string
1512 // FIXME(cir): check for insertion point in module level.
1513 cir::GlobalOp gv = CIRGenModule::createGlobalOp(
1514 cgm, loc, globalName, c.getType(), !cgm.getLangOpts().WritableStrings);
1515
1516 // Set up extra information and add to the module
1517 gv.setAlignmentAttr(cgm.getSize(alignment));
1518 gv.setLinkageAttr(
1519 cir::GlobalLinkageKindAttr::get(cgm.getBuilder().getContext(), lt));
1523 if (gv.isWeakForLinker()) {
1524 assert(cgm.supportsCOMDAT() && "Only COFF uses weak string literals");
1525 gv.setComdat(true);
1526 }
1527 cgm.setDSOLocal(static_cast<mlir::Operation *>(gv));
1528 return gv;
1529}
1530
1531// LLVM IR automatically uniques names when new llvm::GlobalVariables are
1532// created. This is handy, for example, when creating globals for string
1533// literals. Since we don't do that when creating cir::GlobalOp's, we need
1534// a mechanism to generate a unique name in advance.
1535//
1536// For now, this mechanism is only used in cases where we know that the
1537// name is compiler-generated, so we don't use the MLIR symbol table for
1538// the lookup.
1539std::string CIRGenModule::getUniqueGlobalName(const std::string &baseName) {
1540 // If this is the first time we've generated a name for this basename, use
1541 // it as is and start a counter for this base name.
1542 auto it = cgGlobalNames.find(baseName);
1543 if (it == cgGlobalNames.end()) {
1544 cgGlobalNames[baseName] = 1;
1545 return baseName;
1546 }
1547
1548 std::string result =
1549 baseName + "." + std::to_string(cgGlobalNames[baseName]++);
1550 // There should not be any symbol with this name in the module.
1551 assert(!mlir::SymbolTable::lookupSymbolIn(theModule, result));
1552 return result;
1553}
1554
1555/// Return a pointer to a constant array for the given string literal.
1557 StringRef name) {
1558 CharUnits alignment =
1559 astContext.getAlignOfGlobalVarInChars(s->getType(), /*VD=*/nullptr);
1560
1561 mlir::Attribute c = getConstantArrayFromStringLiteral(s);
1562
1563 cir::GlobalOp gv;
1564 if (!getLangOpts().WritableStrings && constantStringMap.count(c)) {
1565 gv = constantStringMap[c];
1566 // The bigger alignment always wins.
1567 if (!gv.getAlignment() ||
1568 uint64_t(alignment.getQuantity()) > *gv.getAlignment())
1569 gv.setAlignmentAttr(getSize(alignment));
1570 } else {
1571 // Mangle the string literal if that's how the ABI merges duplicate strings.
1572 // Don't do it if they are writable, since we don't want writes in one TU to
1573 // affect strings in another.
1574 if (getCXXABI().getMangleContext().shouldMangleStringLiteral(s) &&
1575 !getLangOpts().WritableStrings) {
1576 errorNYI(s->getSourceRange(),
1577 "getGlobalForStringLiteral: mangle string literals");
1578 }
1579
1580 // Unlike LLVM IR, CIR doesn't automatically unique names for globals, so
1581 // we need to do that explicitly.
1582 std::string uniqueName = getUniqueGlobalName(name.str());
1583 // Synthetic string literals (e.g., from SourceLocExpr) may not have valid
1584 // source locations. Use unknown location in those cases.
1585 mlir::Location loc = s->getBeginLoc().isValid()
1586 ? getLoc(s->getSourceRange())
1587 : builder.getUnknownLoc();
1588 auto typedC = llvm::cast<mlir::TypedAttr>(c);
1589 gv = generateStringLiteral(loc, typedC,
1590 cir::GlobalLinkageKind::PrivateLinkage, *this,
1591 uniqueName, alignment);
1592 setDSOLocal(static_cast<mlir::Operation *>(gv));
1593 constantStringMap[c] = gv;
1594
1596 }
1597 return gv;
1598}
1599
1600/// Return a pointer to a constant array for the given string literal.
1601cir::GlobalViewAttr
1603 StringRef name) {
1604 cir::GlobalOp gv = getGlobalForStringLiteral(s, name);
1605 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(gv.getSymType());
1606 assert(arrayTy && "String literal must be array");
1608 cir::PointerType ptrTy = getBuilder().getPointerTo(arrayTy.getElementType());
1609
1610 return builder.getGlobalViewAttr(ptrTy, gv);
1611}
1612
1613// TODO(cir): this could be a common AST helper for both CIR and LLVM codegen.
1615 if (getLangOpts().OpenCL)
1617
1618 // For temporaries inside functions, CUDA treats them as normal variables.
1619 // LangAS::cuda_device, on the other hand, is reserved for those variables
1620 // explicitly marked with __device__.
1621 if (getLangOpts().CUDAIsDevice)
1622 return LangAS::Default;
1623
1624 if (getLangOpts().SYCLIsDevice ||
1625 (getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice))
1626 errorNYI("SYCL or OpenMP temp address space");
1627 return LangAS::Default;
1628}
1629
1631 CIRGenFunction *cgf) {
1632 if (cgf && e->getType()->isVariablyModifiedType())
1634
1636 "emitExplicitCastExprType");
1637}
1638
1641
1642 mlir::Location loc = getLoc(e->getSourceRange());
1643
1644 const auto *decl = cast<DeclRefExpr>(e->getSubExpr())->getDecl();
1645
1646 // A member function pointer.
1647 if (const auto *methodDecl = dyn_cast<CXXMethodDecl>(decl)) {
1648 auto ty = mlir::cast<cir::MethodType>(convertType(e->getType()));
1649 if (methodDecl->isVirtual())
1650 return cir::ConstantOp::create(
1651 builder, loc, getCXXABI().buildVirtualMethodAttr(ty, methodDecl));
1652
1653 cir::FuncOp methodFuncOp = getAddrOfFunction(methodDecl);
1654 return cir::ConstantOp::create(builder, loc,
1655 builder.getMethodAttr(ty, methodFuncOp));
1656 }
1657
1658 // Otherwise, a member data pointer.
1659 auto ty = mlir::cast<cir::DataMemberType>(convertType(e->getType()));
1660 const auto *fieldDecl = cast<FieldDecl>(decl);
1661 return cir::ConstantOp::create(
1662 builder, loc, builder.getDataMemberAttr(ty, fieldDecl->getFieldIndex()));
1663}
1664
1666 for (Decl *decl : dc->decls()) {
1667 // Unlike other DeclContexts, the contents of an ObjCImplDecl at TU scope
1668 // are themselves considered "top-level", so EmitTopLevelDecl on an
1669 // ObjCImplDecl does not recursively visit them. We need to do that in
1670 // case they're nested inside another construct (LinkageSpecDecl /
1671 // ExportDecl) that does stop them from being considered "top-level".
1672 if (auto *oid = dyn_cast<ObjCImplDecl>(decl))
1673 errorNYI(oid->getSourceRange(), "emitDeclConext: ObjCImplDecl");
1674
1676 }
1677}
1678
1679// Emit code for a single top level declaration.
1681
1682 // Ignore dependent declarations.
1683 if (decl->isTemplated())
1684 return;
1685
1686 switch (decl->getKind()) {
1687 default:
1688 errorNYI(decl->getBeginLoc(), "declaration of kind",
1689 decl->getDeclKindName());
1690 break;
1691
1692 case Decl::CXXConversion:
1693 case Decl::CXXMethod:
1694 case Decl::Function: {
1695 auto *fd = cast<FunctionDecl>(decl);
1696 // Consteval functions shouldn't be emitted.
1697 if (!fd->isConsteval())
1698 emitGlobal(fd);
1699 break;
1700 }
1701
1702 case Decl::Var:
1703 case Decl::Decomposition:
1704 case Decl::VarTemplateSpecialization: {
1705 auto *vd = cast<VarDecl>(decl);
1707 errorNYI(decl->getSourceRange(), "global variable decompositions");
1708 break;
1709 }
1710 emitGlobal(vd);
1711 break;
1712 }
1713 case Decl::OpenACCRoutine:
1715 break;
1716 case Decl::OpenACCDeclare:
1718 break;
1719 case Decl::OMPThreadPrivate:
1721 break;
1722 case Decl::OMPGroupPrivate:
1724 break;
1725 case Decl::OMPAllocate:
1727 break;
1728 case Decl::OMPCapturedExpr:
1730 break;
1731 case Decl::OMPDeclareReduction:
1733 break;
1734 case Decl::OMPDeclareMapper:
1736 break;
1737 case Decl::OMPRequires:
1739 break;
1740 case Decl::Enum:
1741 case Decl::Using: // using X; [C++]
1742 case Decl::UsingDirective: // using namespace X; [C++]
1743 case Decl::UsingEnum: // using enum X; [C++]
1744 case Decl::NamespaceAlias:
1745 case Decl::Typedef:
1746 case Decl::TypeAlias: // using foo = bar; [C++11]
1747 case Decl::Record:
1749 break;
1750
1751 // No code generation needed.
1752 case Decl::ClassTemplate:
1753 case Decl::Concept:
1754 case Decl::CXXDeductionGuide:
1755 case Decl::Empty:
1756 case Decl::FunctionTemplate:
1757 case Decl::StaticAssert:
1758 case Decl::TypeAliasTemplate:
1759 case Decl::UsingShadow:
1760 case Decl::VarTemplate:
1761 case Decl::VarTemplatePartialSpecialization:
1762 break;
1763
1764 case Decl::CXXConstructor:
1766 break;
1767 case Decl::CXXDestructor:
1769 break;
1770
1771 // C++ Decls
1772 case Decl::LinkageSpec:
1773 case Decl::Namespace:
1775 break;
1776
1777 case Decl::ClassTemplateSpecialization:
1778 case Decl::CXXRecord: {
1781 for (auto *childDecl : crd->decls())
1783 emitTopLevelDecl(childDecl);
1784 break;
1785 }
1786
1787 case Decl::FileScopeAsm:
1788 // File-scope asm is ignored during device-side CUDA compilation.
1789 if (langOpts.CUDA && langOpts.CUDAIsDevice)
1790 break;
1791 // File-scope asm is ignored during device-side OpenMP compilation.
1792 if (langOpts.OpenMPIsTargetDevice)
1793 break;
1794 // File-scope asm is ignored during device-side SYCL compilation.
1795 if (langOpts.SYCLIsDevice)
1796 break;
1797 auto *file_asm = cast<FileScopeAsmDecl>(decl);
1798 std::string line = file_asm->getAsmString();
1799 globalScopeAsm.push_back(builder.getStringAttr(line));
1800 break;
1801 }
1802}
1803
1804void CIRGenModule::setInitializer(cir::GlobalOp &op, mlir::Attribute value) {
1805 // Recompute visibility when updating initializer.
1806 op.setInitialValueAttr(value);
1808}
1809
1810std::pair<cir::FuncType, cir::FuncOp> CIRGenModule::getAddrAndTypeOfCXXStructor(
1811 GlobalDecl gd, const CIRGenFunctionInfo *fnInfo, cir::FuncType fnType,
1812 bool dontDefer, ForDefinition_t isForDefinition) {
1813 auto *md = cast<CXXMethodDecl>(gd.getDecl());
1814
1815 if (isa<CXXDestructorDecl>(md)) {
1816 // Always alias equivalent complete destructors to base destructors in the
1817 // MS ABI.
1818 if (getTarget().getCXXABI().isMicrosoft() &&
1819 gd.getDtorType() == Dtor_Complete &&
1820 md->getParent()->getNumVBases() == 0)
1821 errorNYI(md->getSourceRange(),
1822 "getAddrAndTypeOfCXXStructor: MS ABI complete destructor");
1823 }
1824
1825 if (!fnType) {
1826 if (!fnInfo)
1828 fnType = getTypes().getFunctionType(*fnInfo);
1829 }
1830
1831 auto fn = getOrCreateCIRFunction(getMangledName(gd), fnType, gd,
1832 /*ForVtable=*/false, dontDefer,
1833 /*IsThunk=*/false, isForDefinition);
1834
1835 return {fnType, fn};
1836}
1837
1839 mlir::Type funcType, bool forVTable,
1840 bool dontDefer,
1841 ForDefinition_t isForDefinition) {
1842 assert(!cast<FunctionDecl>(gd.getDecl())->isConsteval() &&
1843 "consteval function should never be emitted");
1844
1845 if (!funcType) {
1846 const auto *fd = cast<FunctionDecl>(gd.getDecl());
1847 funcType = convertType(fd->getType());
1848 }
1849
1850 // Devirtualized destructor calls may come through here instead of via
1851 // getAddrOfCXXStructor. Make sure we use the MS ABI base destructor instead
1852 // of the complete destructor when necessary.
1853 if (const auto *dd = dyn_cast<CXXDestructorDecl>(gd.getDecl())) {
1854 if (getTarget().getCXXABI().isMicrosoft() &&
1855 gd.getDtorType() == Dtor_Complete &&
1856 dd->getParent()->getNumVBases() == 0)
1857 errorNYI(dd->getSourceRange(),
1858 "getAddrOfFunction: MS ABI complete destructor");
1859 }
1860
1861 StringRef mangledName = getMangledName(gd);
1862 cir::FuncOp func =
1863 getOrCreateCIRFunction(mangledName, funcType, gd, forVTable, dontDefer,
1864 /*isThunk=*/false, isForDefinition);
1865 // Returns kernel handle for HIP kernel stub function.
1866 if (langOpts.CUDA && !langOpts.CUDAIsDevice &&
1867 cast<FunctionDecl>(gd.getDecl())->hasAttr<CUDAGlobalAttr>()) {
1868 mlir::Operation *handle = getCUDARuntime().getKernelHandle(func, gd);
1869
1870 // For HIP the kernel handle is a GlobalOp, which cannot be cast to
1871 // FuncOp. Return the stub directly in that case.
1872 bool isHIPHandle = mlir::isa<cir::GlobalOp>(*handle);
1873 if (isForDefinition || isHIPHandle)
1874 return func;
1875 return mlir::dyn_cast<cir::FuncOp>(*handle);
1876 }
1877 return func;
1878}
1879
1880static std::string getMangledNameImpl(CIRGenModule &cgm, GlobalDecl gd,
1881 const NamedDecl *nd) {
1882 SmallString<256> buffer;
1883
1884 llvm::raw_svector_ostream out(buffer);
1886
1888
1889 if (mc.shouldMangleDeclName(nd)) {
1890 mc.mangleName(gd.getWithDecl(nd), out);
1891 } else {
1892 IdentifierInfo *ii = nd->getIdentifier();
1893 assert(ii && "Attempt to mangle unnamed decl.");
1894
1895 const auto *fd = dyn_cast<FunctionDecl>(nd);
1896 if (fd &&
1897 fd->getType()->castAs<FunctionType>()->getCallConv() == CC_X86RegCall) {
1898 cgm.errorNYI(nd->getSourceRange(), "getMangledName: X86RegCall");
1899 } else if (fd && fd->hasAttr<CUDAGlobalAttr>() &&
1901 out << "__device_stub__" << ii->getName();
1902 } else if (fd &&
1903 DeviceKernelAttr::isOpenCLSpelling(
1904 fd->getAttr<DeviceKernelAttr>()) &&
1906 cgm.errorNYI(nd->getSourceRange(), "getMangledName: OpenCL Stub");
1907 } else {
1908 out << ii->getName();
1909 }
1910 }
1911
1912 // Check if the module name hash should be appended for internal linkage
1913 // symbols. This should come before multi-version target suffixes are
1914 // appendded. This is to keep the name and module hash suffix of the internal
1915 // linkage function together. The unique suffix should only be added when name
1916 // mangling is done to make sure that the final name can be properly
1917 // demangled. For example, for C functions without prototypes, name mangling
1918 // is not done and the unique suffix should not be appended then.
1920
1921 if (const auto *fd = dyn_cast<FunctionDecl>(nd)) {
1922 if (fd->isMultiVersion()) {
1923 cgm.errorNYI(nd->getSourceRange(),
1924 "getMangledName: multi-version functions");
1925 }
1926 }
1927 if (cgm.getLangOpts().GPURelocatableDeviceCode) {
1928 cgm.errorNYI(nd->getSourceRange(),
1929 "getMangledName: GPU relocatable device code");
1930 }
1931
1932 return std::string(out.str());
1933}
1934
1935static FunctionDecl *
1937 const FunctionDecl *protoFunc) {
1938 // If this is a C no-prototype function, we can take the 'easy' way out and
1939 // just create a function with no arguments/functions, etc.
1940 if (!protoFunc->hasPrototype())
1941 return FunctionDecl::Create(
1942 ctx, /*DC=*/ctx.getTranslationUnitDecl(),
1943 /*StartLoc=*/SourceLocation{}, /*NLoc=*/SourceLocation{}, bindName,
1944 protoFunc->getType(), /*TInfo=*/nullptr, StorageClass::SC_None);
1945
1946 QualType funcTy = protoFunc->getType();
1947 auto *fpt = cast<FunctionProtoType>(protoFunc->getType());
1948
1949 // If this is a member function, add an explicit 'this' to the function type.
1950 if (auto *methodDecl = dyn_cast<CXXMethodDecl>(protoFunc);
1951 methodDecl && methodDecl->isImplicitObjectMemberFunction()) {
1952 llvm::SmallVector<QualType> paramTypes{fpt->getParamTypes()};
1953 paramTypes.insert(paramTypes.begin(), methodDecl->getThisType());
1954
1955 funcTy = ctx.getFunctionType(fpt->getReturnType(), paramTypes,
1956 fpt->getExtProtoInfo());
1957 fpt = cast<FunctionProtoType>(funcTy);
1958 }
1959
1960 auto *tempFunc =
1962 /*StartLoc=*/SourceLocation{},
1963 /*NLoc=*/SourceLocation{}, bindName, funcTy,
1964 /*TInfo=*/nullptr, StorageClass::SC_None);
1965
1967 params.reserve(fpt->getNumParams());
1968
1969 // Add all of the parameters.
1970 for (unsigned i = 0, e = fpt->getNumParams(); i != e; ++i) {
1972 ctx, tempFunc, /*StartLoc=*/SourceLocation{},
1973 /*IdLoc=*/SourceLocation{},
1974 /*Id=*/nullptr, fpt->getParamType(i), /*TInfo=*/nullptr,
1975 StorageClass::SC_None, /*DefArg=*/nullptr);
1976 parm->setScopeInfo(0, i);
1977 params.push_back(parm);
1978 }
1979
1980 tempFunc->setParams(params);
1981
1982 return tempFunc;
1983}
1984
1985std::string
1987 const FunctionDecl *attachedFunction) {
1989 getASTContext(), bindName, attachedFunction);
1990
1991 std::string ret = getMangledNameImpl(*this, GlobalDecl(tempFunc), tempFunc);
1992
1993 // This does nothing (it is a do-nothing function), since this is a
1994 // slab-allocator, but leave a call in to immediately destroy this in case we
1995 // ever come up with a way of getting allocations back.
1996 getASTContext().Deallocate(tempFunc);
1997 return ret;
1998}
1999
2001 GlobalDecl canonicalGd = gd.getCanonicalDecl();
2002
2003 // Some ABIs don't have constructor variants. Make sure that base and complete
2004 // constructors get mangled the same.
2005 if (const auto *cd = dyn_cast<CXXConstructorDecl>(canonicalGd.getDecl())) {
2006 if (!getTarget().getCXXABI().hasConstructorVariants()) {
2007 errorNYI(cd->getSourceRange(),
2008 "getMangledName: C++ constructor without variants");
2009 return cast<NamedDecl>(gd.getDecl())->getIdentifier()->getName();
2010 }
2011 }
2012
2013 // Keep the first result in the case of a mangling collision.
2014 const auto *nd = cast<NamedDecl>(gd.getDecl());
2015 std::string mangledName = getMangledNameImpl(*this, gd, nd);
2016
2017 auto result = manglings.insert(std::make_pair(mangledName, gd));
2018 return mangledDeclNames[canonicalGd] = result.first->first();
2019}
2020
2022 assert(!d->getInit() && "Cannot emit definite definitions here!");
2023
2024 StringRef mangledName = getMangledName(d);
2025 mlir::Operation *gv = getGlobalValue(mangledName);
2026
2027 // If we already have a definition, not declaration, with the same mangled
2028 // name, emitting of declaration is not required (and would actually overwrite
2029 // the emitted definition).
2030 if (gv && !mlir::cast<cir::GlobalOp>(gv).isDeclaration())
2031 return;
2032
2033 // If we have not seen a reference to this variable yet, place it into the
2034 // deferred declarations table to be emitted if needed later.
2035 if (!mustBeEmitted(d) && !gv) {
2036 deferredDecls[mangledName] = d;
2037 return;
2038 }
2039
2040 // The tentative definition is the only definition.
2042}
2043
2045 // Never defer when EmitAllDecls is specified.
2046 if (langOpts.EmitAllDecls)
2047 return true;
2048
2049 const auto *vd = dyn_cast<VarDecl>(global);
2050 if (vd &&
2051 ((codeGenOpts.KeepPersistentStorageVariables &&
2052 (vd->getStorageDuration() == SD_Static ||
2053 vd->getStorageDuration() == SD_Thread)) ||
2054 (codeGenOpts.KeepStaticConsts && vd->getStorageDuration() == SD_Static &&
2055 vd->getType().isConstQualified())))
2056 return true;
2057
2058 return getASTContext().DeclMustBeEmitted(global);
2059}
2060
2062 // In OpenMP 5.0 variables and function may be marked as
2063 // device_type(host/nohost) and we should not emit them eagerly unless we sure
2064 // that they must be emitted on the host/device. To be sure we need to have
2065 // seen a declare target with an explicit mentioning of the function, we know
2066 // we have if the level of the declare target attribute is -1. Note that we
2067 // check somewhere else if we should emit this at all.
2068 if (langOpts.OpenMP >= 50 && !langOpts.OpenMPSimd) {
2069 std::optional<OMPDeclareTargetDeclAttr *> activeAttr =
2070 OMPDeclareTargetDeclAttr::getActiveAttr(global);
2071 if (!activeAttr || (*activeAttr)->getLevel() != (unsigned)-1)
2072 return false;
2073 }
2074
2075 const auto *fd = dyn_cast<FunctionDecl>(global);
2076 if (fd) {
2077 // Implicit template instantiations may change linkage if they are later
2078 // explicitly instantiated, so they should not be emitted eagerly.
2079 if (fd->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
2080 return false;
2081 // Defer until all versions have been semantically checked.
2082 if (fd->hasAttr<TargetVersionAttr>() && !fd->isMultiVersion())
2083 return false;
2084 if (langOpts.SYCLIsDevice) {
2085 errorNYI(fd->getSourceRange(), "mayBeEmittedEagerly: SYCL");
2086 return false;
2087 }
2088 }
2089 const auto *vd = dyn_cast<VarDecl>(global);
2090 if (vd)
2091 if (astContext.getInlineVariableDefinitionKind(vd) ==
2093 // A definition of an inline constexpr static data member may change
2094 // linkage later if it's redeclared outside the class.
2095 return false;
2096
2097 // If OpenMP is enabled and threadprivates must be generated like TLS, delay
2098 // codegen for global variables, because they may be marked as threadprivate.
2099 if (langOpts.OpenMP && langOpts.OpenMPUseTLS &&
2100 astContext.getTargetInfo().isTLSSupported() && isa<VarDecl>(global) &&
2101 !global->getType().isConstantStorage(astContext, false, false) &&
2102 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(global))
2103 return false;
2104
2105 assert((fd || vd) &&
2106 "Only FunctionDecl and VarDecl should hit this path so far.");
2107 return true;
2108}
2109
2110static bool shouldAssumeDSOLocal(const CIRGenModule &cgm,
2111 cir::CIRGlobalValueInterface gv) {
2112 if (gv.hasLocalLinkage())
2113 return true;
2114
2115 if (!gv.hasDefaultVisibility() && !gv.hasExternalWeakLinkage())
2116 return true;
2117
2118 // DLLImport explicitly marks the GV as external.
2119 // so it shouldn't be dso_local
2120 // But we don't have the info set now
2122
2123 const llvm::Triple &tt = cgm.getTriple();
2124 const CodeGenOptions &cgOpts = cgm.getCodeGenOpts();
2125 if (tt.isOSCygMing()) {
2126 // In MinGW and Cygwin, variables without DLLImport can still be
2127 // automatically imported from a DLL by the linker; don't mark variables
2128 // that potentially could come from another DLL as DSO local.
2129
2130 // With EmulatedTLS, TLS variables can be autoimported from other DLLs
2131 // (and this actually happens in the public interface of libstdc++), so
2132 // such variables can't be marked as DSO local. (Native TLS variables
2133 // can't be dllimported at all, though.)
2134 cgm.errorNYI("shouldAssumeDSOLocal: MinGW");
2135 }
2136
2137 // On COFF, don't mark 'extern_weak' symbols as DSO local. If these symbols
2138 // remain unresolved in the link, they can be resolved to zero, which is
2139 // outside the current DSO.
2140 if (tt.isOSBinFormatCOFF() && gv.hasExternalWeakLinkage())
2141 return false;
2142
2143 // Every other GV is local on COFF.
2144 // Make an exception for windows OS in the triple: Some firmware builds use
2145 // *-win32-macho triples. This (accidentally?) produced windows relocations
2146 // without GOT tables in older clang versions; Keep this behaviour.
2147 // FIXME: even thread local variables?
2148 if (tt.isOSBinFormatCOFF() || (tt.isOSWindows() && tt.isOSBinFormatMachO()))
2149 return true;
2150
2151 // Only handle COFF and ELF for now.
2152 if (!tt.isOSBinFormatELF())
2153 return false;
2154
2155 llvm::Reloc::Model rm = cgOpts.RelocationModel;
2156 const LangOptions &lOpts = cgm.getLangOpts();
2157 if (rm != llvm::Reloc::Static && !lOpts.PIE) {
2158 // On ELF, if -fno-semantic-interposition is specified and the target
2159 // supports local aliases, there will be neither CC1
2160 // -fsemantic-interposition nor -fhalf-no-semantic-interposition. Set
2161 // dso_local on the function if using a local alias is preferable (can avoid
2162 // PLT indirection).
2163 if (!(isa<cir::FuncOp>(gv) && gv.canBenefitFromLocalAlias()))
2164 return false;
2165 return !(lOpts.SemanticInterposition || lOpts.HalfNoSemanticInterposition);
2166 }
2167
2168 // A definition cannot be preempted from an executable.
2169 if (!gv.isDeclarationForLinker())
2170 return true;
2171
2172 // Most PIC code sequences that assume that a symbol is local cannot produce a
2173 // 0 if it turns out the symbol is undefined. While this is ABI and relocation
2174 // depended, it seems worth it to handle it here.
2175 if (rm == llvm::Reloc::PIC_ && gv.hasExternalWeakLinkage())
2176 return false;
2177
2178 // PowerPC64 prefers TOC indirection to avoid copy relocations.
2179 if (tt.isPPC64())
2180 return false;
2181
2182 if (cgOpts.DirectAccessExternalData) {
2183 // If -fdirect-access-external-data (default for -fno-pic), set dso_local
2184 // for non-thread-local variables. If the symbol is not defined in the
2185 // executable, a copy relocation will be needed at link time. dso_local is
2186 // excluded for thread-local variables because they generally don't support
2187 // copy relocations.
2188 if (auto globalOp = dyn_cast<cir::GlobalOp>(gv.getOperation())) {
2189 // Assume variables are not thread-local until that support is added.
2191 return true;
2192 }
2193
2194 // -fno-pic sets dso_local on a function declaration to allow direct
2195 // accesses when taking its address (similar to a data symbol). If the
2196 // function is not defined in the executable, a canonical PLT entry will be
2197 // needed at link time. -fno-direct-access-external-data can avoid the
2198 // canonical PLT entry. We don't generalize this condition to -fpie/-fpic as
2199 // it could just cause trouble without providing perceptible benefits.
2200 if (isa<cir::FuncOp>(gv) && !cgOpts.NoPLT && rm == llvm::Reloc::Static)
2201 return true;
2202 }
2203
2204 // If we can use copy relocations we can assume it is local.
2205
2206 // Otherwise don't assume it is local.
2207
2208 return false;
2209}
2210
2211void CIRGenModule::setGlobalVisibility(mlir::Operation *gv,
2212 const NamedDecl *d) const {
2214}
2215
2216void CIRGenModule::setDSOLocal(cir::CIRGlobalValueInterface gv) const {
2217 gv.setDSOLocal(shouldAssumeDSOLocal(*this, gv));
2218}
2219
2220void CIRGenModule::setDSOLocal(mlir::Operation *op) const {
2221 if (auto globalValue = dyn_cast<cir::CIRGlobalValueInterface>(op))
2222 setDSOLocal(globalValue);
2223}
2224
2225void CIRGenModule::setGVProperties(mlir::Operation *op,
2226 const NamedDecl *d) const {
2228 setGVPropertiesAux(op, d);
2229}
2230
2231void CIRGenModule::setGVPropertiesAux(mlir::Operation *op,
2232 const NamedDecl *d) const {
2233 setGlobalVisibility(op, d);
2234 setDSOLocal(op);
2236}
2237
2239 GlobalDecl &result) const {
2240 auto res = manglings.find(mangledName);
2241 if (res == manglings.end())
2242 return false;
2243 result = res->getValue();
2244 return true;
2245}
2246
2248 switch (getCodeGenOpts().getDefaultTLSModel()) {
2250 return cir::TLS_Model::GeneralDynamic;
2252 return cir::TLS_Model::LocalDynamic;
2254 return cir::TLS_Model::InitialExec;
2256 return cir::TLS_Model::LocalExec;
2257 }
2258 llvm_unreachable("Invalid TLS model!");
2259}
2260
2261void CIRGenModule::setTLSMode(mlir::Operation *op, const VarDecl &d) {
2262 assert(d.getTLSKind() && "setting TLS mode on non-TLS var!");
2263
2264 cir::TLS_Model tlm = getDefaultCIRTLSModel();
2265
2266 // Override the TLS model if it is explicitly specified.
2267 if (d.getAttr<TLSModelAttr>())
2268 errorNYI(d.getSourceRange(), "TLS model attribute");
2269
2270 auto global = cast<cir::GlobalOp>(op);
2271 global.setTlsModel(tlm);
2272}
2273
2275 const CIRGenFunctionInfo &info,
2276 cir::FuncOp func, bool isThunk) {
2277 // TODO(cir): More logic of constructAttributeList is needed.
2278 cir::CallingConv callingConv;
2279 cir::SideEffect sideEffect;
2280
2281 // TODO(cir): The current list should be initialized with the extra function
2282 // attributes, but we don't have those yet. For now, the PAL is initialized
2283 // with nothing.
2285 // Initialize PAL with existing attributes to merge attributes.
2286 mlir::NamedAttrList pal{};
2287 std::vector<mlir::NamedAttrList> argAttrs(info.arguments().size());
2288 mlir::NamedAttrList retAttrs{};
2289 constructAttributeList(func.getName(), info, globalDecl, pal, argAttrs,
2290 retAttrs, callingConv, sideEffect,
2291 /*attrOnCallSite=*/false, isThunk);
2292
2293 for (mlir::NamedAttribute attr : pal)
2294 func->setAttr(attr.getName(), attr.getValue());
2295
2296 llvm::for_each(llvm::enumerate(argAttrs), [func](auto idx_arg_pair) {
2297 mlir::function_interface_impl::setArgAttrs(func, idx_arg_pair.index(),
2298 idx_arg_pair.value());
2299 });
2300 if (!retAttrs.empty())
2301 mlir::function_interface_impl::setResultAttrs(func, 0, retAttrs);
2302
2303 // TODO(cir): Check X86_VectorCall incompatibility wiht WinARM64EC
2304
2305 // TODO(cir): typically the calling conv is set right here, but since
2306 // cir::CallingConv is empty and we've not yet added calling-conv to FuncOop,
2307 // this isn't really useful here. This should call func.setCallingConv/etc
2308 // later.
2310}
2311
2313 cir::FuncOp func,
2314 bool isIncompleteFunction,
2315 bool isThunk) {
2316 // NOTE(cir): Original CodeGen checks if this is an intrinsic. In CIR we
2317 // represent them in dedicated ops. The correct attributes are ensured during
2318 // translation to LLVM. Thus, we don't need to check for them here.
2319
2320 if (!isIncompleteFunction)
2321 setCIRFunctionAttributes(globalDecl,
2322 getTypes().arrangeGlobalDeclaration(globalDecl),
2323 func, isThunk);
2324
2326
2327 // TODO(cir): This needs a lot of work to better match CodeGen. That
2328 // ultimately ends up in setGlobalVisibility, which already has the linkage of
2329 // the LLVM GV (corresponding to our FuncOp) computed, so it doesn't have to
2330 // recompute it here. This is a minimal fix for now.
2331 if (!isLocalLinkage(getFunctionLinkage(globalDecl))) {
2332 const Decl *decl = globalDecl.getDecl();
2333 func.setGlobalVisibilityAttr(getGlobalVisibilityAttrFromDecl(decl));
2334 }
2335
2336 // If we plan on emitting this inline builtin, we can't treat it as a builtin.
2337 const auto *fd = cast<FunctionDecl>(globalDecl.getDecl());
2338 if (fd->isInlineBuiltinDeclaration()) {
2339 const FunctionDecl *fdBody;
2340 bool hasBody = fd->hasBody(fdBody);
2341 (void)hasBody;
2342 assert(hasBody && "Inline builtin declarations should always have an "
2343 "available body!");
2345 }
2346}
2347
2349 const clang::FunctionDecl *decl, cir::FuncOp f) {
2352
2353 std::optional<cir::InlineKind> existingInlineKind = f.getInlineKind();
2354 bool isNoInline =
2355 existingInlineKind && *existingInlineKind == cir::InlineKind::NoInline;
2356 bool isAlwaysInline = existingInlineKind &&
2357 *existingInlineKind == cir::InlineKind::AlwaysInline;
2358 if (!decl) {
2359 assert(!cir::MissingFeatures::hlsl());
2360
2361 if (!isAlwaysInline &&
2362 codeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) {
2363 // If inlining is disabled and we don't have a declaration to control
2364 // inlining, mark the function as 'noinline' unless it is explicitly
2365 // marked as 'alwaysinline'.
2366 f.setInlineKind(cir::InlineKind::NoInline);
2367 }
2368
2369 return;
2370 }
2371
2378 assert(!cir::MissingFeatures::hlsl());
2379
2380 // Handle inline attributes
2381 if (decl->hasAttr<NoInlineAttr>() && !isAlwaysInline) {
2382 // Add noinline if the function isn't always_inline.
2383 f.setInlineKind(cir::InlineKind::NoInline);
2384 } else if (decl->hasAttr<AlwaysInlineAttr>() && !isNoInline) {
2385 // Don't override AlwaysInline with NoInline, or vice versa, since we can't
2386 // specify both in IR.
2387 f.setInlineKind(cir::InlineKind::AlwaysInline);
2388 } else if (codeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) {
2389 // If inlining is disabled, force everything that isn't always_inline
2390 // to carry an explicit noinline attribute.
2391 if (!isAlwaysInline)
2392 f.setInlineKind(cir::InlineKind::NoInline);
2393 } else {
2394 // Otherwise, propagate the inline hint attribute and potentially use its
2395 // absence to mark things as noinline.
2396 // Search function and template pattern redeclarations for inline.
2397 if (auto *fd = dyn_cast<FunctionDecl>(decl)) {
2398 // TODO: Share this checkForInline implementation with classic codegen.
2399 // This logic is likely to change over time, so sharing would help ensure
2400 // consistency.
2401 auto checkForInline = [](const FunctionDecl *decl) {
2402 auto checkRedeclForInline = [](const FunctionDecl *redecl) {
2403 return redecl->isInlineSpecified();
2404 };
2405 if (any_of(decl->redecls(), checkRedeclForInline))
2406 return true;
2407 const FunctionDecl *pattern = decl->getTemplateInstantiationPattern();
2408 if (!pattern)
2409 return false;
2410 return any_of(pattern->redecls(), checkRedeclForInline);
2411 };
2412 if (checkForInline(fd)) {
2413 f.setInlineKind(cir::InlineKind::InlineHint);
2414 } else if (codeGenOpts.getInlining() ==
2416 !fd->isInlined() && !isAlwaysInline) {
2417 f.setInlineKind(cir::InlineKind::NoInline);
2418 }
2419 }
2420 }
2421
2423}
2424
2426 StringRef mangledName, mlir::Type funcType, GlobalDecl gd, bool forVTable,
2427 bool dontDefer, bool isThunk, ForDefinition_t isForDefinition,
2428 mlir::NamedAttrList extraAttrs) {
2429 const Decl *d = gd.getDecl();
2430
2431 if (const auto *fd = cast_or_null<FunctionDecl>(d)) {
2432 // For the device mark the function as one that should be emitted.
2433 if (getLangOpts().OpenMPIsTargetDevice && fd->isDefined() && !dontDefer &&
2434 !isForDefinition)
2435 errorNYI(fd->getSourceRange(),
2436 "getOrCreateCIRFunction: OpenMP target function");
2437
2438 // Any attempts to use a MultiVersion function should result in retrieving
2439 // the iFunc instead. Name mangling will handle the rest of the changes.
2440 if (fd->isMultiVersion())
2441 errorNYI(fd->getSourceRange(), "getOrCreateCIRFunction: multi-version");
2442 }
2443
2444 // Lookup the entry, lazily creating it if necessary.
2445 mlir::Operation *entry = getGlobalValue(mangledName);
2446 if (entry) {
2447 assert(mlir::isa<cir::FuncOp>(entry));
2448
2450
2451 // Handle dropped DLL attributes.
2452 if (d && !d->hasAttr<DLLImportAttr>() && !d->hasAttr<DLLExportAttr>()) {
2454 setDSOLocal(entry);
2455 }
2456
2457 // If there are two attempts to define the same mangled name, issue an
2458 // error.
2459 auto fn = cast<cir::FuncOp>(entry);
2460 if (isForDefinition && fn && !fn.isDeclaration()) {
2461 GlobalDecl otherGd;
2462 // Check that GD is not yet in DiagnosedConflictingDefinitions is required
2463 // to make sure that we issue an error only once.
2464 if (lookupRepresentativeDecl(mangledName, otherGd) &&
2465 (gd.getCanonicalDecl().getDecl() !=
2466 otherGd.getCanonicalDecl().getDecl()) &&
2467 diagnosedConflictingDefinitions.insert(gd).second) {
2468 getDiags().Report(d->getLocation(), diag::err_duplicate_mangled_name)
2469 << mangledName;
2470 getDiags().Report(otherGd.getDecl()->getLocation(),
2471 diag::note_previous_definition);
2472 }
2473 }
2474
2475 if (fn && fn.getFunctionType() == funcType) {
2476 return fn;
2477 }
2478
2479 if (!isForDefinition) {
2480 return fn;
2481 }
2482
2483 // TODO(cir): classic codegen checks here if this is a llvm::GlobalAlias.
2484 // How will we support this?
2485 }
2486
2487 auto *funcDecl = llvm::cast_or_null<FunctionDecl>(gd.getDecl());
2488 bool invalidLoc = !funcDecl ||
2489 funcDecl->getSourceRange().getBegin().isInvalid() ||
2490 funcDecl->getSourceRange().getEnd().isInvalid();
2491 cir::FuncOp funcOp = createCIRFunction(
2492 invalidLoc ? theModule->getLoc() : getLoc(funcDecl->getSourceRange()),
2493 mangledName, mlir::cast<cir::FuncType>(funcType), funcDecl);
2494
2495 // If we already created a function with the same mangled name (but different
2496 // type) before, take its name and add it to the list of functions to be
2497 // replaced with F at the end of CodeGen.
2498 //
2499 // This happens if there is a prototype for a function (e.g. "int f()") and
2500 // then a definition of a different type (e.g. "int f(int x)").
2501 if (entry) {
2502
2503 // Fetch a generic symbol-defining operation and its uses.
2504 auto symbolOp = mlir::cast<mlir::SymbolOpInterface>(entry);
2505
2506 // This might be an implementation of a function without a prototype, in
2507 // which case, try to do special replacement of calls which match the new
2508 // prototype. The really key thing here is that we also potentially drop
2509 // arguments from the call site so as to make a direct call, which makes the
2510 // inliner happier and suppresses a number of optimizer warnings (!) about
2511 // dropping arguments.
2512 if (symbolOp.getSymbolUses(symbolOp->getParentOp()))
2514
2515 // Obliterate no-proto declaration.
2516 entry->erase();
2517 }
2518
2519 if (d)
2520 setFunctionAttributes(gd, funcOp, /*isIncompleteFunction=*/false, isThunk);
2521 if (!extraAttrs.empty()) {
2522 extraAttrs.append(funcOp->getAttrs());
2523 funcOp->setAttrs(extraAttrs);
2524 }
2525
2526 // 'dontDefer' actually means don't move this to the deferredDeclsToEmit list.
2527 if (dontDefer) {
2528 // TODO(cir): This assertion will need an additional condition when we
2529 // support incomplete functions.
2530 assert(funcOp.getFunctionType() == funcType);
2531 return funcOp;
2532 }
2533
2534 // All MSVC dtors other than the base dtor are linkonce_odr and delegate to
2535 // each other bottoming out wiht the base dtor. Therefore we emit non-base
2536 // dtors on usage, even if there is no dtor definition in the TU.
2537 if (isa_and_nonnull<CXXDestructorDecl>(d) &&
2538 getCXXABI().useThunkForDtorVariant(cast<CXXDestructorDecl>(d),
2539 gd.getDtorType()))
2540 errorNYI(d->getSourceRange(), "getOrCreateCIRFunction: dtor");
2541
2542 // This is the first use or definition of a mangled name. If there is a
2543 // deferred decl with this name, remember that we need to emit it at the end
2544 // of the file.
2545 auto ddi = deferredDecls.find(mangledName);
2546 if (ddi != deferredDecls.end()) {
2547 // Move the potentially referenced deferred decl to the
2548 // DeferredDeclsToEmit list, and remove it from DeferredDecls (since we
2549 // don't need it anymore).
2550 addDeferredDeclToEmit(ddi->second);
2551 deferredDecls.erase(ddi);
2552
2553 // Otherwise, there are cases we have to worry about where we're using a
2554 // declaration for which we must emit a definition but where we might not
2555 // find a top-level definition.
2556 // - member functions defined inline in their classes
2557 // - friend functions defined inline in some class
2558 // - special member functions with implicit definitions
2559 // If we ever change our AST traversal to walk into class methods, this
2560 // will be unnecessary.
2561 //
2562 // We also don't emit a definition for a function if it's going to be an
2563 // entry in a vtable, unless it's already marked as used.
2564 } else if (getLangOpts().CPlusPlus && d) {
2565 // Look for a declaration that's lexically in a record.
2566 for (const auto *fd = cast<FunctionDecl>(d)->getMostRecentDecl(); fd;
2567 fd = fd->getPreviousDecl()) {
2568 if (isa<CXXRecordDecl>(fd->getLexicalDeclContext())) {
2569 if (fd->doesThisDeclarationHaveABody()) {
2571 break;
2572 }
2573 }
2574 }
2575 }
2576
2577 return funcOp;
2578}
2579
2580cir::FuncOp
2581CIRGenModule::createCIRFunction(mlir::Location loc, StringRef name,
2582 cir::FuncType funcType,
2583 const clang::FunctionDecl *funcDecl) {
2584 cir::FuncOp func;
2585 {
2586 mlir::OpBuilder::InsertionGuard guard(builder);
2587
2588 // Some global emissions are triggered while emitting a function, e.g.
2589 // void s() { x.method() }
2590 //
2591 // Be sure to insert a new function before a current one.
2592 CIRGenFunction *cgf = this->curCGF;
2593 if (cgf)
2594 builder.setInsertionPoint(cgf->curFn);
2595
2596 func = cir::FuncOp::create(builder, loc, name, funcType);
2597
2599
2600 if (funcDecl && !funcDecl->hasPrototype())
2601 func.setNoProto(true);
2602
2603 assert(func.isDeclaration() && "expected empty body");
2604
2605 // A declaration gets private visibility by default, but external linkage
2606 // as the default linkage.
2607 func.setLinkageAttr(cir::GlobalLinkageKindAttr::get(
2608 &getMLIRContext(), cir::GlobalLinkageKind::ExternalLinkage));
2609 mlir::SymbolTable::setSymbolVisibility(
2610 func, mlir::SymbolTable::Visibility::Private);
2611
2613
2614 // Mark C++ special member functions (Constructor, Destructor etc.)
2615 setCXXSpecialMemberAttr(func, funcDecl);
2616
2617 if (!cgf)
2618 theModule.push_back(func);
2619
2620 if (this->getLangOpts().OpenACC) {
2621 // We only have to handle this attribute, since OpenACCAnnotAttrs are
2622 // handled via the end-of-TU work.
2623 for (const auto *attr :
2624 funcDecl->specific_attrs<OpenACCRoutineDeclAttr>())
2625 emitOpenACCRoutineDecl(funcDecl, func, attr->getLocation(),
2626 attr->Clauses);
2627 }
2628 }
2629 return func;
2630}
2631
2632cir::FuncOp
2633CIRGenModule::createCIRBuiltinFunction(mlir::Location loc, StringRef name,
2634 cir::FuncType ty,
2635 const clang::FunctionDecl *fd) {
2636 cir::FuncOp fnOp = createCIRFunction(loc, name, ty, fd);
2637 fnOp.setBuiltin(true);
2638 return fnOp;
2639}
2640
2641static cir::CtorKind getCtorKindFromDecl(const CXXConstructorDecl *ctor) {
2642 if (ctor->isDefaultConstructor())
2643 return cir::CtorKind::Default;
2644 if (ctor->isCopyConstructor())
2645 return cir::CtorKind::Copy;
2646 if (ctor->isMoveConstructor())
2647 return cir::CtorKind::Move;
2648 return cir::CtorKind::Custom;
2649}
2650
2651static cir::AssignKind getAssignKindFromDecl(const CXXMethodDecl *method) {
2652 if (method->isCopyAssignmentOperator())
2653 return cir::AssignKind::Copy;
2654 if (method->isMoveAssignmentOperator())
2655 return cir::AssignKind::Move;
2656 llvm_unreachable("not a copy or move assignment operator");
2657}
2658
2660 cir::FuncOp funcOp, const clang::FunctionDecl *funcDecl) {
2661 if (!funcDecl)
2662 return;
2663
2664 if (const auto *dtor = dyn_cast<CXXDestructorDecl>(funcDecl)) {
2665 auto cxxDtor = cir::CXXDtorAttr::get(
2666 convertType(getASTContext().getCanonicalTagType(dtor->getParent())),
2667 dtor->isTrivial());
2668 funcOp.setCxxSpecialMemberAttr(cxxDtor);
2669 return;
2670 }
2671
2672 if (const auto *ctor = dyn_cast<CXXConstructorDecl>(funcDecl)) {
2673 cir::CtorKind kind = getCtorKindFromDecl(ctor);
2674 auto cxxCtor = cir::CXXCtorAttr::get(
2675 convertType(getASTContext().getCanonicalTagType(ctor->getParent())),
2676 kind, ctor->isTrivial());
2677 funcOp.setCxxSpecialMemberAttr(cxxCtor);
2678 return;
2679 }
2680
2681 const auto *method = dyn_cast<CXXMethodDecl>(funcDecl);
2682 if (method && (method->isCopyAssignmentOperator() ||
2683 method->isMoveAssignmentOperator())) {
2684 cir::AssignKind assignKind = getAssignKindFromDecl(method);
2685 auto cxxAssign = cir::CXXAssignAttr::get(
2686 convertType(getASTContext().getCanonicalTagType(method->getParent())),
2687 assignKind, method->isTrivial());
2688 funcOp.setCxxSpecialMemberAttr(cxxAssign);
2689 return;
2690 }
2691}
2692
2693static void setWindowsItaniumDLLImport(CIRGenModule &cgm, bool isLocal,
2694 cir::FuncOp funcOp, StringRef name) {
2695 // In Windows Itanium environments, try to mark runtime functions
2696 // dllimport. For Mingw and MSVC, don't. We don't really know if the user
2697 // will link their standard library statically or dynamically. Marking
2698 // functions imported when they are not imported can cause linker errors
2699 // and warnings.
2700 if (!isLocal && cgm.getTarget().getTriple().isWindowsItaniumEnvironment() &&
2701 !cgm.getCodeGenOpts().LTOVisibilityPublicStd) {
2705 }
2706}
2707
2708cir::FuncOp CIRGenModule::createRuntimeFunction(cir::FuncType ty,
2709 StringRef name,
2710 mlir::NamedAttrList extraAttrs,
2711 bool isLocal,
2712 bool assumeConvergent) {
2713 if (assumeConvergent)
2714 errorNYI("createRuntimeFunction: assumeConvergent");
2715
2716 cir::FuncOp entry = getOrCreateCIRFunction(name, ty, GlobalDecl(),
2717 /*forVtable=*/false, extraAttrs);
2718
2719 if (entry) {
2720 // TODO(cir): set the attributes of the function.
2723 setWindowsItaniumDLLImport(*this, isLocal, entry, name);
2724 entry.setDSOLocal(true);
2725 }
2726
2727 return entry;
2728}
2729
2730mlir::SymbolTable::Visibility
2732 // MLIR doesn't accept public symbols declarations (only
2733 // definitions).
2734 if (op.isDeclaration())
2735 return mlir::SymbolTable::Visibility::Private;
2736 return getMLIRVisibilityFromCIRLinkage(op.getLinkage());
2737}
2738
2739mlir::SymbolTable::Visibility
2741 switch (glk) {
2742 case cir::GlobalLinkageKind::InternalLinkage:
2743 case cir::GlobalLinkageKind::PrivateLinkage:
2744 return mlir::SymbolTable::Visibility::Private;
2745 case cir::GlobalLinkageKind::ExternalLinkage:
2746 case cir::GlobalLinkageKind::ExternalWeakLinkage:
2747 case cir::GlobalLinkageKind::LinkOnceODRLinkage:
2748 case cir::GlobalLinkageKind::AvailableExternallyLinkage:
2749 case cir::GlobalLinkageKind::CommonLinkage:
2750 case cir::GlobalLinkageKind::WeakAnyLinkage:
2751 case cir::GlobalLinkageKind::WeakODRLinkage:
2752 return mlir::SymbolTable::Visibility::Public;
2753 default: {
2754 llvm::errs() << "visibility not implemented for '"
2755 << stringifyGlobalLinkageKind(glk) << "'\n";
2756 assert(0 && "not implemented");
2757 }
2758 }
2759 llvm_unreachable("linkage should be handled above!");
2760}
2761
2763 clang::VisibilityAttr::VisibilityType visibility) {
2764 switch (visibility) {
2765 case clang::VisibilityAttr::VisibilityType::Default:
2766 return cir::VisibilityKind::Default;
2767 case clang::VisibilityAttr::VisibilityType::Hidden:
2768 return cir::VisibilityKind::Hidden;
2769 case clang::VisibilityAttr::VisibilityType::Protected:
2770 return cir::VisibilityKind::Protected;
2771 }
2772 llvm_unreachable("unexpected visibility value");
2773}
2774
2775cir::VisibilityAttr
2777 const clang::VisibilityAttr *va = decl->getAttr<clang::VisibilityAttr>();
2778 cir::VisibilityAttr cirVisibility =
2779 cir::VisibilityAttr::get(&getMLIRContext());
2780 if (va) {
2781 cirVisibility = cir::VisibilityAttr::get(
2782 &getMLIRContext(),
2783 getGlobalVisibilityKindFromClangVisibility(va->getVisibility()));
2784 }
2785 return cirVisibility;
2786}
2787
2789 emitDeferred();
2790 applyReplacements();
2791
2792 theModule->setAttr(cir::CIRDialect::getModuleLevelAsmAttrName(),
2793 builder.getArrayAttr(globalScopeAsm));
2794
2795 // There's a lot of code that is not implemented yet.
2797}
2798
2799void CIRGenModule::emitAliasForGlobal(StringRef mangledName,
2800 mlir::Operation *op, GlobalDecl aliasGD,
2801 cir::FuncOp aliasee,
2802 cir::GlobalLinkageKind linkage) {
2803
2804 auto *aliasFD = dyn_cast<FunctionDecl>(aliasGD.getDecl());
2805 assert(aliasFD && "expected FunctionDecl");
2806
2807 // The aliasee function type is different from the alias one, this difference
2808 // is specific to CIR because in LLVM the ptr types are already erased at this
2809 // point.
2810 const CIRGenFunctionInfo &fnInfo =
2812 cir::FuncType fnType = getTypes().getFunctionType(fnInfo);
2813
2814 cir::FuncOp alias =
2816 mangledName, fnType, aliasFD);
2817 alias.setAliasee(aliasee.getName());
2818 alias.setLinkage(linkage);
2819 // Declarations cannot have public MLIR visibility, just mark them private
2820 // but this really should have no meaning since CIR should not be using
2821 // this information to derive linkage information.
2822 mlir::SymbolTable::setSymbolVisibility(
2823 alias, mlir::SymbolTable::Visibility::Private);
2824
2825 // Alias constructors and destructors are always unnamed_addr.
2827
2828 // Switch any previous uses to the alias.
2829 if (op) {
2830 errorNYI(aliasFD->getSourceRange(), "emitAliasForGlobal: previous uses");
2831 } else {
2832 // Name already set by createCIRFunction
2833 }
2834
2835 // Finally, set up the alias with its proper name and attributes.
2836 setCommonAttributes(aliasGD, alias);
2837}
2838
2840 return genTypes.convertType(type);
2841}
2842
2844 // Verify the module after we have finished constructing it, this will
2845 // check the structural properties of the IR and invoke any specific
2846 // verifiers we have on the CIR operations.
2847 return mlir::verify(theModule).succeeded();
2848}
2849
2850mlir::Attribute CIRGenModule::getAddrOfRTTIDescriptor(mlir::Location loc,
2851 QualType ty, bool forEh) {
2852 // Return a bogus pointer if RTTI is disabled, unless it's for EH.
2853 // FIXME: should we even be calling this method if RTTI is disabled
2854 // and it's not for EH?
2855 if (!shouldEmitRTTI(forEh))
2856 return builder.getConstNullPtrAttr(builder.getUInt8PtrTy());
2857
2858 if (forEh && ty->isObjCObjectPointerType() &&
2859 langOpts.ObjCRuntime.isGNUFamily()) {
2860 errorNYI(loc, "getAddrOfRTTIDescriptor: Objc PtrType & Objc RT GUN");
2861 return {};
2862 }
2863
2864 return getCXXABI().getAddrOfRTTIDescriptor(loc, ty);
2865}
2866
2867// TODO(cir): this can be shared with LLVM codegen.
2869 const CXXRecordDecl *derivedClass,
2870 llvm::iterator_range<CastExpr::path_const_iterator> path) {
2871 CharUnits offset = CharUnits::Zero();
2872
2873 const ASTContext &astContext = getASTContext();
2874 const CXXRecordDecl *rd = derivedClass;
2875
2876 for (const CXXBaseSpecifier *base : path) {
2877 assert(!base->isVirtual() && "Should not see virtual bases here!");
2878
2879 // Get the layout.
2880 const ASTRecordLayout &layout = astContext.getASTRecordLayout(rd);
2881
2882 const auto *baseDecl = base->getType()->castAsCXXRecordDecl();
2883
2884 // Add the offset.
2885 offset += layout.getBaseClassOffset(baseDecl);
2886
2887 rd = baseDecl;
2888 }
2889
2890 return offset;
2891}
2892
2894 llvm::StringRef feature) {
2895 unsigned diagID = diags.getCustomDiagID(
2896 DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0");
2897 return diags.Report(loc, diagID) << feature;
2898}
2899
2901 llvm::StringRef feature) {
2902 return errorNYI(loc.getBegin(), feature) << loc;
2903}
2904
2906 unsigned diagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error, "%0");
2907 getDiags().Report(astContext.getFullLoc(loc), diagID) << error;
2908}
2909
2910/// Print out an error that codegen doesn't support the specified stmt yet.
2911void CIRGenModule::errorUnsupported(const Stmt *s, llvm::StringRef type) {
2912 unsigned diagId = diags.getCustomDiagID(DiagnosticsEngine::Error,
2913 "cannot compile this %0 yet");
2914 diags.Report(astContext.getFullLoc(s->getBeginLoc()), diagId)
2915 << type << s->getSourceRange();
2916}
2917
2918/// Print out an error that codegen doesn't support the specified decl yet.
2919void CIRGenModule::errorUnsupported(const Decl *d, llvm::StringRef type) {
2920 unsigned diagId = diags.getCustomDiagID(DiagnosticsEngine::Error,
2921 "cannot compile this %0 yet");
2922 diags.Report(astContext.getFullLoc(d->getLocation()), diagId) << type;
2923}
2924
2925void CIRGenModule::mapBlockAddress(cir::BlockAddrInfoAttr blockInfo,
2926 cir::LabelOp label) {
2927 [[maybe_unused]] auto result =
2928 blockAddressInfoToLabel.try_emplace(blockInfo, label);
2929 assert(result.second &&
2930 "attempting to map a blockaddress info that is already mapped");
2931}
2932
2933void CIRGenModule::mapUnresolvedBlockAddress(cir::BlockAddressOp op) {
2934 [[maybe_unused]] auto result = unresolvedBlockAddressToLabel.insert(op);
2935 assert(result.second &&
2936 "attempting to map a blockaddress operation that is already mapped");
2937}
2938
2939void CIRGenModule::mapResolvedBlockAddress(cir::BlockAddressOp op,
2940 cir::LabelOp label) {
2941 [[maybe_unused]] auto result = blockAddressToLabel.try_emplace(op, label);
2942 assert(result.second &&
2943 "attempting to map a blockaddress operation that is already mapped");
2944}
2945
2947 cir::LabelOp newLabel) {
2948 auto *it = blockAddressToLabel.find(op);
2949 assert(it != blockAddressToLabel.end() &&
2950 "trying to update a blockaddress not previously mapped");
2951 assert(!it->second && "blockaddress already has a resolved label");
2952
2953 it->second = newLabel;
2954}
2955
2956cir::LabelOp
2957CIRGenModule::lookupBlockAddressInfo(cir::BlockAddrInfoAttr blockInfo) {
2958 return blockAddressInfoToLabel.lookup(blockInfo);
2959}
2960
2961mlir::Operation *
2963 const Expr *init) {
2964 assert((mte->getStorageDuration() == SD_Static ||
2965 mte->getStorageDuration() == SD_Thread) &&
2966 "not a global temporary");
2967 const auto *varDecl = cast<VarDecl>(mte->getExtendingDecl());
2968
2969 // If we're not materializing a subobject of the temporary, keep the
2970 // cv-qualifiers from the type of the MaterializeTemporaryExpr.
2971 QualType materializedType = init->getType();
2972 if (init == mte->getSubExpr())
2973 materializedType = mte->getType();
2974
2975 CharUnits align = getASTContext().getTypeAlignInChars(materializedType);
2976
2977 auto insertResult = materializedGlobalTemporaryMap.insert({mte, nullptr});
2978 if (!insertResult.second)
2979 errorNYI(mte->getSourceRange(), "duplicate materialized temporaries");
2980
2981 // FIXME: If an externally-visible declaration extends multiple temporaries,
2982 // we need to give each temporary the same name in every translation unit (and
2983 // we also need to make the temporaries externally-visible).
2985 llvm::raw_svector_ostream out(name);
2987 varDecl, mte->getManglingNumber(), out);
2988
2989 APValue *value = nullptr;
2990 if (mte->getStorageDuration() == SD_Static && varDecl->evaluateValue()) {
2991 // If the initializer of the extending declaration is a constant
2992 // initializer, we should have a cached constant initializer for this
2993 // temporay. Note taht this m ight have a different value from the value
2994 // computed by evaluating the initializer if the surrounding constant
2995 // expression modifies the temporary.
2996 value = mte->getOrCreateValue(/*MayCreate=*/false);
2997 }
2998
2999 // Try evaluating it now, it might have a constant initializer
3000 Expr::EvalResult evalResult;
3001 if (!value && init->EvaluateAsRValue(evalResult, getASTContext()) &&
3002 !evalResult.hasSideEffects())
3003 value = &evalResult.Val;
3004
3006
3007 std::optional<ConstantEmitter> emitter;
3008 mlir::Attribute initialValue = nullptr;
3009 bool isConstant = false;
3010 mlir::Type type;
3011
3012 if (value) {
3013 emitter.emplace(*this);
3014 initialValue = emitter->emitForInitializer(*value, materializedType);
3015
3016 isConstant = materializedType.isConstantStorage(
3017 getASTContext(), /*ExcludeCtor=*/value, /*ExcludeDtor=*/false);
3018
3019 type = mlir::cast<mlir::TypedAttr>(initialValue).getType();
3020 } else {
3021 // No initializer, the initialization will be provided when we initialize
3022 // the declaration which performed lifetime extension.
3023 type = getTypes().convertTypeForMem(materializedType);
3024 }
3025
3026 // Create a global variable for this lifetime-extended temporary.
3027 cir::GlobalLinkageKind linkage =
3028 getCIRLinkageVarDefinition(varDecl, /*isConstant=*/false);
3029 if (linkage == cir::GlobalLinkageKind::ExternalLinkage) {
3030 const VarDecl *initVD;
3031 if (varDecl->isStaticDataMember() && varDecl->getAnyInitializer(initVD) &&
3033 // Temporaries defined inside a class get linkonce_odr linkage because the
3034 // calss can be defined in multiple translation units.
3035 errorNYI(mte->getSourceRange(), "static data member initialization");
3036 } else {
3037 // There is no need for this temporary to have external linkage if the
3038 // VarDecl has external linkage.
3039 linkage = cir::GlobalLinkageKind::InternalLinkage;
3040 }
3041 }
3042 mlir::Location loc = getLoc(mte->getSourceRange());
3043 cir::GlobalOp gv = createGlobalOp(*this, loc, name, type, isConstant);
3044 gv.setInitialValueAttr(initialValue);
3045
3046 if (emitter)
3047 emitter->finalize(gv);
3048 // Don't assign dllimport or dllexport to local linkage globals
3049 if (!gv.hasLocalLinkage()) {
3052 }
3053
3054 gv.setAlignment(align.getAsAlign().value());
3055 if (supportsCOMDAT() && gv.isWeakForLinker())
3056 errorNYI(mte->getSourceRange(),
3057 "Global temporary with comdat/weak linkage");
3058 if (varDecl->getTLSKind())
3059 errorNYI(mte->getSourceRange(),
3060 "Global temporary with thread local storage");
3061 mlir::Operation *cv = gv;
3062
3064
3065 // Update the map with the new temporary. If we created a placeholder above,
3066 // replace it with the new global now.
3067 mlir::Operation *&entry = materializedGlobalTemporaryMap[mte];
3068 if (entry) {
3069 entry->replaceAllUsesWith(cv);
3070 entry->erase();
3071 }
3072 entry = cv;
3073
3074 return cv;
3075}
Defines the clang::ASTContext interface.
This file provides some common utility functions for processing Lambda related AST Constructs.
static bool shouldAssumeDSOLocal(const CIRGenModule &cgm, cir::CIRGlobalValueInterface gv)
static cir::AssignKind getAssignKindFromDecl(const CXXMethodDecl *method)
static FunctionDecl * createOpenACCBindTempFunction(ASTContext &ctx, const IdentifierInfo *bindName, const FunctionDecl *protoFunc)
static bool shouldBeInCOMDAT(CIRGenModule &cgm, const Decl &d)
static void setWindowsItaniumDLLImport(CIRGenModule &cgm, bool isLocal, cir::FuncOp funcOp, StringRef name)
static std::string getMangledNameImpl(CIRGenModule &cgm, GlobalDecl gd, const NamedDecl *nd)
static cir::GlobalOp generateStringLiteral(mlir::Location loc, mlir::TypedAttr c, cir::GlobalLinkageKind lt, CIRGenModule &cgm, StringRef globalName, CharUnits alignment)
static bool hasImplicitAttr(const ValueDecl *decl)
static CIRGenCXXABI * createCXXABI(CIRGenModule &cgm)
static bool isVarDeclStrongDefinition(const ASTContext &astContext, CIRGenModule &cgm, const VarDecl *vd, bool noCommon)
static void setLinkageForGV(cir::GlobalOp &gv, const NamedDecl *nd)
static cir::CtorKind getCtorKindFromDecl(const CXXConstructorDecl *ctor)
This file defines OpenACC nodes for declarative directives.
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
Defines the SourceManager interface.
__device__ __2f16 float __ockl_bool s
__device__ __2f16 float c
cir::PointerType getPointerTo(mlir::Type ty)
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Definition APValue.h:122
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:226
TranslationUnitDecl * getTranslationUnitDecl() const
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
@ WeakUnknown
Weak for now, might become strong later in this TU.
bool DeclMustBeEmitted(const Decl *D)
Determines if the decl can be CodeGen'ed or deserialized from PCH lazily, only when used; this is onl...
void Deallocate(void *Ptr) const
Definition ASTContext.h:877
GVALinkage GetGVALinkageForFunction(const FunctionDecl *FD) const
bool isAlignmentRequired(const Type *T) const
Determine if the alignment the type has was required using an alignment attribute.
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
GVALinkage GetGVALinkageForVariable(const VarDecl *VD) const
unsigned getTypeAlignIfKnown(QualType T, bool NeedsPreferredAlignment=false) const
Return the alignment of a type, in bits, or 0 if the type is incomplete and we cannot determine the a...
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
const TargetInfo & getTargetInfo() const
Definition ASTContext.h:916
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.
virtual mlir::Operation * getKernelHandle(cir::FuncOp fn, GlobalDecl gd)=0
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
llvm::ArrayRef< CanQualType > arguments() const
cir::FuncOp generateCode(clang::GlobalDecl gd, cir::FuncOp fn, cir::FuncType funcType)
void emitVariablyModifiedType(QualType ty)
mlir::Operation * curFn
The current function or global initializer that is generated code for.
This class organizes the cross-function state that is used while generating CIR code.
void updateResolvedBlockAddress(cir::BlockAddressOp op, cir::LabelOp newLabel)
void replaceUsesOfNonProtoTypeWithRealFunction(mlir::Operation *old, cir::FuncOp newFn)
This function is called when we implement a function with no prototype, e.g.
llvm::StringRef getMangledName(clang::GlobalDecl gd)
CharUnits computeNonVirtualBaseClassOffset(const CXXRecordDecl *derivedClass, llvm::iterator_range< CastExpr::path_const_iterator > path)
void setGlobalVisibility(mlir::Operation *op, const NamedDecl *d) const
Set the visibility for the given global.
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
void emitDeferred()
Emit any needed decls for which code generation was deferred.
clang::ASTContext & getASTContext() const
cir::FuncOp getAddrOfCXXStructor(clang::GlobalDecl gd, const CIRGenFunctionInfo *fnInfo=nullptr, cir::FuncType fnType=nullptr, bool dontDefer=false, ForDefinition_t isForDefinition=NotForDefinition)
CIRGenCUDARuntime & getCUDARuntime()
llvm::DenseMap< cir::BlockAddrInfoAttr, cir::LabelOp > blockAddressInfoToLabel
Map BlockAddrInfoAttr (function name, label name) to the corresponding CIR LabelOp.
void emitTopLevelDecl(clang::Decl *decl)
void emitOMPDeclareMapper(const OMPDeclareMapperDecl *d)
void addReplacement(llvm::StringRef name, mlir::Operation *op)
mlir::Type convertType(clang::QualType type)
bool shouldEmitRTTI(bool forEH=false)
cir::GlobalOp getGlobalForStringLiteral(const StringLiteral *s, llvm::StringRef name=".str")
Return a global symbol reference to a constant array for the given string literal.
void emitOMPCapturedExpr(const OMPCapturedExprDecl *d)
void mapUnresolvedBlockAddress(cir::BlockAddressOp op)
bool mustBeEmitted(const clang::ValueDecl *d)
Determine whether the definition must be emitted; if this returns false, the definition can be emitte...
void emitGlobalOpenACCDeclareDecl(const clang::OpenACCDeclareDecl *cd)
mlir::IntegerAttr getSize(CharUnits size)
CIRGenBuilderTy & getBuilder()
void setDSOLocal(mlir::Operation *op) const
std::string getUniqueGlobalName(const std::string &baseName)
std::pair< cir::FuncType, cir::FuncOp > getAddrAndTypeOfCXXStructor(clang::GlobalDecl gd, const CIRGenFunctionInfo *fnInfo=nullptr, cir::FuncType fnType=nullptr, bool dontDefer=false, ForDefinition_t isForDefinition=NotForDefinition)
void setGVProperties(mlir::Operation *op, const NamedDecl *d) const
Set visibility, dllimport/dllexport and dso_local.
cir::GlobalOp getOrCreateCIRGlobal(llvm::StringRef mangledName, mlir::Type ty, LangAS langAS, const VarDecl *d, ForDefinition_t isForDefinition)
If the specified mangled name is not in the module, create and return an mlir::GlobalOp value.
cir::FuncOp createCIRBuiltinFunction(mlir::Location loc, llvm::StringRef name, cir::FuncType ty, const clang::FunctionDecl *fd)
Create a CIR function with builtin attribute set.
void emitGlobalOpenACCRoutineDecl(const clang::OpenACCRoutineDecl *cd)
clang::CharUnits getClassPointerAlignment(const clang::CXXRecordDecl *rd)
Return the best known alignment for an unknown pointer to a particular class.
void handleCXXStaticMemberVarInstantiation(VarDecl *vd)
Tell the consumer that this variable has been instantiated.
void emitOMPRequiresDecl(const OMPRequiresDecl *d)
void emitGlobalDefinition(clang::GlobalDecl gd, mlir::Operation *op=nullptr)
void mapResolvedBlockAddress(cir::BlockAddressOp op, cir::LabelOp)
clang::DiagnosticsEngine & getDiags() const
mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc, QualType ty, bool forEH=false)
Get the address of the RTTI descriptor for the given type.
void setFunctionAttributes(GlobalDecl gd, cir::FuncOp f, bool isIncompleteFunction, bool isThunk)
Set function attributes for a function declaration.
static mlir::SymbolTable::Visibility getMLIRVisibilityFromCIRLinkage(cir::GlobalLinkageKind GLK)
const clang::TargetInfo & getTarget() const
void setCIRFunctionAttributes(GlobalDecl gd, const CIRGenFunctionInfo &info, cir::FuncOp func, bool isThunk)
Set the CIR function attributes (Sext, zext, etc).
const llvm::Triple & getTriple() const
static mlir::SymbolTable::Visibility getMLIRVisibility(Visibility v)
void emitTentativeDefinition(const VarDecl *d)
cir::GlobalOp createOrReplaceCXXRuntimeVariable(mlir::Location loc, llvm::StringRef name, mlir::Type ty, cir::GlobalLinkageKind linkage, clang::CharUnits alignment)
Will return a global variable of the given type.
void emitOMPAllocateDecl(const OMPAllocateDecl *d)
void error(SourceLocation loc, llvm::StringRef error)
Emit a general error that something can't be done.
void emitGlobalDecl(const clang::GlobalDecl &d)
Helper for emitDeferred to apply actual codegen.
void emitGlobalVarDefinition(const clang::VarDecl *vd, bool isTentative=false)
cir::FuncOp createRuntimeFunction(cir::FuncType ty, llvm::StringRef name, mlir::NamedAttrList extraAttrs={}, bool isLocal=false, bool assumeConvergent=false)
void setTLSMode(mlir::Operation *op, const VarDecl &d)
Set TLS mode for the given operation based on the given variable declaration.
cir::FuncOp getAddrOfFunction(clang::GlobalDecl gd, mlir::Type funcType=nullptr, bool forVTable=false, bool dontDefer=false, ForDefinition_t isForDefinition=NotForDefinition)
Return the address of the given function.
void emitAliasForGlobal(llvm::StringRef mangledName, mlir::Operation *op, GlobalDecl aliasGD, cir::FuncOp aliasee, cir::GlobalLinkageKind linkage)
mlir::Value emitMemberPointerConstant(const UnaryOperator *e)
void emitGlobalOpenACCDecl(const clang::OpenACCConstructDecl *cd)
void emitExplicitCastExprType(const ExplicitCastExpr *e, CIRGenFunction *cgf=nullptr)
Emit type info if type of an expression is a variably modified type.
mlir::Operation * getAddrOfGlobalTemporary(const MaterializeTemporaryExpr *mte, const Expr *init)
Returns a pointer to a global variable representing a temporary with static or thread storage duratio...
std::map< llvm::StringRef, clang::GlobalDecl > deferredDecls
This contains all the decls which have definitions but which are deferred for emission and therefore ...
void errorUnsupported(const Stmt *s, llvm::StringRef type)
Print out an error that codegen doesn't support the specified stmt yet.
mlir::Value getAddrOfGlobalVar(const VarDecl *d, mlir::Type ty={}, ForDefinition_t isForDefinition=NotForDefinition)
Return the mlir::Value for the address of the given global variable.
static void setInitializer(cir::GlobalOp &op, mlir::Attribute value)
cir::GlobalViewAttr getAddrOfGlobalVarAttr(const VarDecl *d)
Return the mlir::GlobalViewAttr for the address of the given global.
void addGlobalCtor(cir::FuncOp ctor, std::optional< int > priority=std::nullopt)
Add a global constructor or destructor to the module.
cir::GlobalLinkageKind getFunctionLinkage(GlobalDecl gd)
void updateCompletedType(const clang::TagDecl *td)
const clang::CodeGenOptions & getCodeGenOpts() const
const clang::LangOptions & getLangOpts() const
void constructAttributeList(llvm::StringRef name, const CIRGenFunctionInfo &info, CIRGenCalleeInfo calleeInfo, mlir::NamedAttrList &attrs, llvm::MutableArrayRef< mlir::NamedAttrList > argAttrs, mlir::NamedAttrList &retAttrs, cir::CallingConv &callingConv, cir::SideEffect &sideEffect, bool attrOnCallSite, bool isThunk)
Get the CIR attributes and calling convention to use for a particular function type.
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::NamedAttrList extraAttrs={})
void emitOpenACCRoutineDecl(const clang::FunctionDecl *funcDecl, cir::FuncOp func, SourceLocation pragmaLoc, ArrayRef< const OpenACCClause * > clauses)
cir::TLS_Model getDefaultCIRTLSModel() const
Get TLS mode from CodeGenOptions.
void addGlobalDtor(cir::FuncOp dtor, std::optional< int > priority=std::nullopt)
Add a function to the list that will be called when the module is unloaded.
void addDeferredDeclToEmit(clang::GlobalDecl GD)
bool shouldEmitCUDAGlobalVar(const VarDecl *global) const
cir::FuncOp createCIRFunction(mlir::Location loc, llvm::StringRef name, cir::FuncType funcType, const clang::FunctionDecl *funcDecl)
const TargetCIRGenInfo & getTargetCIRGenInfo()
void emitCXXGlobalVarDeclInitFunc(const VarDecl *vd, cir::GlobalOp addr, bool performInit)
void setGVPropertiesAux(mlir::Operation *op, const NamedDecl *d) const
LangAS getLangTempAllocaAddressSpace() const
Returns the address space for temporary allocations in the language.
llvm::DenseSet< cir::BlockAddressOp > unresolvedBlockAddressToLabel
Track CIR BlockAddressOps that cannot be resolved immediately because their LabelOp has not yet been ...
mlir::Location getLoc(clang::SourceLocation cLoc)
Helpers to convert the presumed location of Clang's SourceLocation to an MLIR Location.
llvm::DenseMap< mlir::Attribute, cir::GlobalOp > constantStringMap
mlir::Operation * lastGlobalOp
void replaceGlobal(cir::GlobalOp oldGV, cir::GlobalOp newGV)
Replace all uses of the old global with the new global, updating types and references as needed.
static cir::VisibilityKind getGlobalVisibilityKindFromClangVisibility(clang::VisibilityAttr::VisibilityType visibility)
llvm::StringMap< unsigned > cgGlobalNames
void setCXXSpecialMemberAttr(cir::FuncOp funcOp, const clang::FunctionDecl *funcDecl)
Mark the function as a special member (e.g. constructor, destructor)
mlir::Operation * getGlobalValue(llvm::StringRef ref)
void emitOMPDeclareReduction(const OMPDeclareReductionDecl *d)
mlir::ModuleOp getModule() const
cir::GlobalLinkageKind getCIRLinkageForDeclarator(const DeclaratorDecl *dd, GVALinkage linkage, bool isConstantVariable)
mlir::MLIRContext & getMLIRContext()
mlir::Operation * getAddrOfGlobal(clang::GlobalDecl gd, ForDefinition_t isForDefinition=NotForDefinition)
static cir::GlobalOp createGlobalOp(CIRGenModule &cgm, mlir::Location loc, llvm::StringRef name, mlir::Type t, bool isConstant=false, mlir::Operation *insertPoint=nullptr)
void maybeSetTrivialComdat(const clang::Decl &d, mlir::Operation *op)
CIRGenCXXABI & getCXXABI() const
cir::GlobalViewAttr getAddrOfConstantStringFromLiteral(const StringLiteral *s, llvm::StringRef name=".str")
Return a global symbol reference to a constant array for the given string literal.
llvm::MapVector< cir::BlockAddressOp, cir::LabelOp > blockAddressToLabel
Map CIR BlockAddressOps directly to their resolved LabelOps.
bool lookupRepresentativeDecl(llvm::StringRef mangledName, clang::GlobalDecl &gd) const
void emitDeclContext(const DeclContext *dc)
void emitGlobal(clang::GlobalDecl gd)
Emit code for a single global function or variable declaration.
cir::LabelOp lookupBlockAddressInfo(cir::BlockAddrInfoAttr blockInfo)
bool mayBeEmittedEagerly(const clang::ValueDecl *d)
Determine whether the definition can be emitted eagerly, or should be delayed until the end of the tr...
cir::GlobalLinkageKind getCIRLinkageVarDefinition(const VarDecl *vd, bool isConstant)
void mapBlockAddress(cir::BlockAddrInfoAttr blockInfo, cir::LabelOp label)
void setCIRFunctionAttributesForDefinition(const clang::FunctionDecl *fd, cir::FuncOp f)
Set extra attributes (inline, etc.) for a function.
std::string getOpenACCBindMangledName(const IdentifierInfo *bindName, const FunctionDecl *attachedFunction)
void emitGlobalFunctionDefinition(clang::GlobalDecl gd, mlir::Operation *op)
CIRGenVTables & getVTables()
void setFunctionLinkage(GlobalDecl gd, cir::FuncOp f)
std::vector< clang::GlobalDecl > deferredDeclsToEmit
void emitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *d)
void emitOMPGroupPrivateDecl(const OMPGroupPrivateDecl *d)
mlir::Attribute getConstantArrayFromStringLiteral(const StringLiteral *e)
Return a constant array for the given string.
cir::VisibilityAttr getGlobalVisibilityAttrFromDecl(const Decl *decl)
void setCommonAttributes(GlobalDecl gd, mlir::Operation *op)
Set attributes which are common to any form of a global definition (alias, Objective-C method,...
clang::CharUnits getNaturalTypeAlignment(clang::QualType t, LValueBaseInfo *baseInfo=nullptr)
FIXME: this could likely be a common helper and not necessarily related with codegen.
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 mlir::ptr::MemorySpaceAttrInterface getCIRAllocaAddressSpace() const
Get the address space for alloca.
Definition TargetInfo.h:53
Represents a base class of a C++ class.
Definition DeclCXX.h:146
Represents a C++ constructor within a class.
Definition DeclCXX.h:2611
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:3031
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:3026
bool isDefaultConstructor() const
Whether this constructor is a default constructor (C++ [class.ctor]p5), which can be used to default-...
Definition DeclCXX.cpp:3017
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2136
bool isMoveAssignmentOperator() const
Determine whether this is a move assignment operator.
Definition DeclCXX.cpp:2753
bool isCopyAssignmentOperator() const
Determine whether this is a copy-assignment operator, regardless of whether it was declared implicitl...
Definition DeclCXX.cpp:2732
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:2343
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:3768
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1449
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Definition DeclBase.h:2373
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
T * getAttr() const
Definition DeclBase.h:573
bool isWeakImported() const
Determine whether this is a weak-imported symbol.
Definition DeclBase.cpp:870
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
Definition DeclBase.cpp:273
static DeclContext * castToDeclContext(const Decl *)
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
Definition DeclBase.h:559
SourceLocation getLocation() const
Definition DeclBase.h:439
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
Definition DeclBase.h:918
bool hasAttr() const
Definition DeclBase.h:577
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition DeclBase.h:427
Represents a ValueDecl that came out of a declarator.
Definition Decl.h:780
A little helper class used to produce diagnostics.
Concrete class used by the front-end to report problems and issues.
Definition Diagnostic.h:232
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
Definition Diagnostic.h:913
ExplicitCastExpr - An explicit cast written in the source code.
Definition Expr.h:3931
This represents one expression.
Definition Expr.h:112
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
QualType getType() const
Definition Expr.h:144
Represents a member of a struct/union/class.
Definition Decl.h:3160
Cached information about one file (either on disk or in the virtual file system).
Definition FileEntry.h:302
StringRef tryGetRealPathName() const
Definition FileEntry.h:327
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Represents a function declaration or definition.
Definition Decl.h:2000
static FunctionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin=false, bool isInlineSpecified=false, bool hasWrittenPrototype=true, ConstexprSpecKind ConstexprKind=ConstexprSpecKind::Unspecified, const AssociatedConstraint &TrailingRequiresClause={})
Definition Decl.h:2189
bool hasPrototype() const
Whether this function has a prototype, either because one was explicitly written or because it was "i...
Definition Decl.h:2443
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
Definition Decl.cpp:3200
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4511
CallingConv getCallConv() const
Definition TypeBase.h:4866
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
virtual void mangleReferenceTemporary(const VarDecl *D, unsigned ManglingNumber, raw_ostream &)=0
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
Definition ExprCXX.h:4921
StorageDuration getStorageDuration() const
Retrieve the storage duration for the materialized temporary.
Definition ExprCXX.h:4946
Expr * getSubExpr() const
Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.
Definition ExprCXX.h:4938
APValue * getOrCreateValue(bool MayCreate) const
Get the storage for the constant value of a materialized temporary of static storage duration.
Definition ExprCXX.h:4954
ValueDecl * getExtendingDecl()
Get the declaration which triggered the lifetime-extension of this temporary, if any.
Definition ExprCXX.h:4971
unsigned getManglingNumber() const
Definition ExprCXX.h:4982
This represents a decl that may have a name.
Definition Decl.h:274
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition Decl.h:295
LinkageInfo getLinkageAndVisibility() const
Determines the linkage and visibility of this entity.
Definition Decl.cpp:1226
Represents a parameter to a function.
Definition Decl.h:1790
void setScopeInfo(unsigned scopeDepth, unsigned parameterIndex)
Definition Decl.h:1823
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
Definition Decl.cpp:2958
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:8514
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8428
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition TypeBase.h:8461
bool isConstantStorage(const ASTContext &Ctx, bool ExcludeCtor, bool ExcludeDtor)
Definition TypeBase.h:1036
bool hasUnaligned() const
Definition TypeBase.h:511
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
This class handles loading and caching of source files into memory.
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
Stmt - This represents one statement.
Definition Stmt.h:86
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
StringLiteral - This represents a string literal expression, e.g.
Definition Expr.h:1802
unsigned getLength() const
Definition Expr.h:1912
uint32_t getCodeUnit(size_t i) const
Definition Expr.h:1885
StringRef getString() const
Definition Expr.h:1870
unsigned getCharByteWidth() const
Definition Expr.h:1913
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:8625
bool isReferenceType() const
Definition TypeBase.h:8649
bool isCUDADeviceBuiltinSurfaceType() const
Check if the type is the CUDA device builtin surface type.
Definition Type.cpp:5407
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition TypeBase.h:2808
bool isCUDADeviceBuiltinTextureType() const
Check if the type is the CUDA device builtin texture type.
Definition Type.cpp:5416
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
Definition Type.cpp:2479
bool isObjCObjectPointerType() const
Definition TypeBase.h:8804
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9218
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition Expr.h:2247
Expr * getSubExpr() const
Definition Expr.h:2288
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:2180
bool hasInit() const
Definition Decl.cpp:2410
DefinitionKind isThisDeclarationADefinition(ASTContext &) const
Check whether this declaration is a definition.
Definition Decl.cpp:2272
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:2202
bool hasFlexibleArrayInit(const ASTContext &Ctx) const
Whether this variable has a flexible array member initialized with one or more elements.
Definition Decl.cpp:2874
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:2660
VarDecl * getDefinition(ASTContext &)
Get the real (not just tentative) definition for this declaration.
Definition Decl.cpp:2378
QualType::DestructionKind needsDestruction(const ASTContext &Ctx) const
Would the destruction of this variable have any effect, and if so, what kind?
Definition Decl.cpp:2863
const Expr * getInit() const
Definition Decl.h:1368
bool hasExternalStorage() const
Returns true if a variable has extern or private_extern storage.
Definition Decl.h:1217
@ TLS_Dynamic
TLS with a dynamic initializer.
Definition Decl.h:952
@ TLS_None
Not a TLS variable.
Definition Decl.h:946
@ Definition
This declaration is definitely a definition.
Definition Decl.h:1301
DefinitionKind hasDefinition(ASTContext &) const
Check whether this variable is defined in this translation unit.
Definition Decl.cpp:2387
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:2791
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 ...
std::unique_ptr< TargetCIRGenInfo > createNVPTXTargetCIRGenInfo(CIRGenTypes &cgt)
CIRGenCXXABI * CreateCIRGenItaniumCXXABI(CIRGenModule &cgm)
Creates and Itanium-family ABI.
std::unique_ptr< TargetCIRGenInfo > createX8664TargetCIRGenInfo(CIRGenTypes &cgt)
CIRGenCUDARuntime * createNVCUDARuntime(CIRGenModule &cgm)
const internal::VariadicDynCastAllOfMatcher< Decl, VarDecl > varDecl
Matches variable declarations.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const internal::VariadicDynCastAllOfMatcher< Decl, FieldDecl > fieldDecl
Matches field declarations.
const internal::VariadicDynCastAllOfMatcher< Decl, FunctionDecl > functionDecl
Matches function declarations.
const internal::VariadicAllOfMatcher< Decl > decl
Matches declarations.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
@ CPlusPlus
GVALinkage
A more specific kind of linkage than enum Linkage.
Definition Linkage.h:72
@ GVA_StrongODR
Definition Linkage.h:77
@ GVA_StrongExternal
Definition Linkage.h:76
@ GVA_AvailableExternally
Definition Linkage.h:74
@ GVA_DiscardableODR
Definition Linkage.h:75
@ GVA_Internal
Definition Linkage.h:73
@ SC_None
Definition Specifiers.h:250
@ SD_Thread
Thread storage duration.
Definition Specifiers.h:342
@ SD_Static
Static storage duration.
Definition Specifiers.h:343
bool isLambdaCallOperator(const CXXMethodDecl *MD)
Definition ASTLambda.h:28
@ Dtor_Complete
Complete object dtor.
Definition ABI.h:36
LangAS
Defines the address space values used by the address space qualifier of QualType.
TemplateSpecializationKind
Describes the kind of template specialization that a particular template specialization declaration r...
Definition Specifiers.h:188
@ TSK_ExplicitInstantiationDefinition
This template specialization was instantiated from a template due to an explicit instantiation defini...
Definition Specifiers.h:206
@ TSK_ImplicitInstantiation
This template specialization was implicitly instantiated from a template.
Definition Specifiers.h:194
@ CC_X86RegCall
Definition Specifiers.h:287
U cast(CodeGen::Address addr)
Definition Address.h:327
bool isExternallyVisible(Linkage L)
Definition Linkage.h:90
static bool globalCtorLexOrder()
static bool alignCXXRecordDecl()
static bool opFuncArmNewAttr()
static bool getRuntimeFunctionDecl()
static bool weakRefReference()
static bool opFuncOptNoneAttr()
static bool opGlobalSection()
static bool addressSpace()
static bool opFuncMinSizeAttr()
static bool opGlobalUnnamedAddr()
static bool opGlobalThreadLocal()
static bool sourceLanguageCases()
static bool opFuncAstDeclAttr()
static bool opFuncNoDuplicateAttr()
static bool opGlobalUsedOrCompilerUsed()
static bool stackProtector()
static bool moduleNameHash()
static bool opGlobalVisibility()
static bool setDLLStorageClass()
static bool opFuncUnwindTablesAttr()
static bool opFuncParameterAttributes()
static bool targetCIRGenInfoArch()
static bool opFuncExtraAttrs()
static bool opFuncNakedAttr()
static bool opFuncSection()
static bool attributeNoBuiltin()
static bool opGlobalDLLImportExport()
static bool opGlobalPartition()
static bool opGlobalWeakRef()
static bool setTargetAttributes()
static bool deferredCXXGlobalInit()
static bool opFuncOperandBundles()
static bool opFuncCallingConv()
static bool globalCtorAssociatedData()
static bool defaultVisibility()
static bool opFuncColdHotAttr()
static bool opFuncExceptions()
static bool opFuncArmStreamingAttr()
static bool deferredVtables()
static bool cudaSupport()
static bool opFuncMaybeHandleStaticInExternC()
static bool generateDebugInfo()
static bool targetCIRGenInfoOS()
static bool opFuncCPUAndFeaturesAttributes()
static bool maybeHandleStaticInExternC()
static bool setLLVMFunctionFEnvAttributes()
mlir::Type uCharTy
ClangIR char.
cir::PointerType allocaInt8PtrTy
void* in alloca address space
mlir::ptr::MemorySpaceAttrInterface cirAllocaAddressSpace
cir::PointerType voidPtrTy
void* in address space 0
EvalResult is a struct with detailed info about an evaluated expression.
Definition Expr.h:648
APValue Val
Val - This is the value the expression can be folded to.
Definition Expr.h:650
bool hasSideEffects() const
Return true if the evaluated expression has side effects.
Definition Expr.h:642
LangStandard - Information about the properties of a particular language standard.