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/Attrs.inc"
22#include "clang/AST/DeclBase.h"
34
35#include "CIRGenFunctionInfo.h"
36#include "TargetInfo.h"
37#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
38#include "mlir/IR/BuiltinOps.h"
39#include "mlir/IR/Location.h"
40#include "mlir/IR/MLIRContext.h"
41#include "mlir/IR/Operation.h"
42#include "mlir/IR/Verifier.h"
43
44#include <algorithm>
45
46using namespace clang;
47using namespace clang::CIRGen;
48
50 switch (cgm.getASTContext().getCXXABIKind()) {
51 case TargetCXXABI::GenericItanium:
52 case TargetCXXABI::GenericAArch64:
53 case TargetCXXABI::AppleARM64:
54 return CreateCIRGenItaniumCXXABI(cgm);
55
56 case TargetCXXABI::Fuchsia:
57 case TargetCXXABI::GenericARM:
58 case TargetCXXABI::iOS:
59 case TargetCXXABI::WatchOS:
60 case TargetCXXABI::GenericMIPS:
61 case TargetCXXABI::WebAssembly:
62 case TargetCXXABI::XL:
63 case TargetCXXABI::Microsoft:
64 cgm.errorNYI("createCXXABI: C++ ABI kind");
65 return nullptr;
66 }
67
68 llvm_unreachable("invalid C++ ABI kind");
69}
70
71CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,
72 clang::ASTContext &astContext,
73 const clang::CodeGenOptions &cgo,
74 DiagnosticsEngine &diags)
75 : builder(mlirContext, *this), astContext(astContext),
76 langOpts(astContext.getLangOpts()), codeGenOpts(cgo),
77 theModule{mlir::ModuleOp::create(mlir::UnknownLoc::get(&mlirContext))},
78 diags(diags), target(astContext.getTargetInfo()),
79 abi(createCXXABI(*this)), genTypes(*this), vtables(*this) {
80
81 // Initialize cached types
82 voidTy = cir::VoidType::get(&getMLIRContext());
83 voidPtrTy = cir::PointerType::get(voidTy);
84 sInt8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/true);
85 sInt16Ty = cir::IntType::get(&getMLIRContext(), 16, /*isSigned=*/true);
86 sInt32Ty = cir::IntType::get(&getMLIRContext(), 32, /*isSigned=*/true);
87 sInt64Ty = cir::IntType::get(&getMLIRContext(), 64, /*isSigned=*/true);
88 sInt128Ty = cir::IntType::get(&getMLIRContext(), 128, /*isSigned=*/true);
89 uInt8Ty = cir::IntType::get(&getMLIRContext(), 8, /*isSigned=*/false);
90 uInt8PtrTy = cir::PointerType::get(uInt8Ty);
92 uInt16Ty = cir::IntType::get(&getMLIRContext(), 16, /*isSigned=*/false);
93 uInt32Ty = cir::IntType::get(&getMLIRContext(), 32, /*isSigned=*/false);
94 uInt64Ty = cir::IntType::get(&getMLIRContext(), 64, /*isSigned=*/false);
95 uInt128Ty = cir::IntType::get(&getMLIRContext(), 128, /*isSigned=*/false);
96 fP16Ty = cir::FP16Type::get(&getMLIRContext());
97 bFloat16Ty = cir::BF16Type::get(&getMLIRContext());
98 floatTy = cir::SingleType::get(&getMLIRContext());
99 doubleTy = cir::DoubleType::get(&getMLIRContext());
100 fP80Ty = cir::FP80Type::get(&getMLIRContext());
101 fP128Ty = cir::FP128Type::get(&getMLIRContext());
102
103 allocaInt8PtrTy = cir::PointerType::get(uInt8Ty, cirAllocaAddressSpace);
104
106 astContext
107 .toCharUnitsFromBits(
108 astContext.getTargetInfo().getPointerAlign(LangAS::Default))
109 .getQuantity();
110
111 const unsigned charSize = astContext.getTargetInfo().getCharWidth();
112 uCharTy = cir::IntType::get(&getMLIRContext(), charSize, /*isSigned=*/false);
113
114 // TODO(CIR): Should be updated once TypeSizeInfoAttr is upstreamed
115 const unsigned sizeTypeSize =
116 astContext.getTypeSize(astContext.getSignedSizeType());
117 SizeSizeInBytes = astContext.toCharUnitsFromBits(sizeTypeSize).getQuantity();
118 // In CIRGenTypeCache, UIntPtrTy and SizeType are fields of the same union
119 uIntPtrTy =
120 cir::IntType::get(&getMLIRContext(), sizeTypeSize, /*isSigned=*/false);
121 ptrDiffTy =
122 cir::IntType::get(&getMLIRContext(), sizeTypeSize, /*isSigned=*/true);
123
124 std::optional<cir::SourceLanguage> sourceLanguage = getCIRSourceLanguage();
125 if (sourceLanguage)
126 theModule->setAttr(
127 cir::CIRDialect::getSourceLanguageAttrName(),
128 cir::SourceLanguageAttr::get(&mlirContext, *sourceLanguage));
129 theModule->setAttr(cir::CIRDialect::getTripleAttrName(),
130 builder.getStringAttr(getTriple().str()));
131
132 if (cgo.OptimizationLevel > 0 || cgo.OptimizeSize > 0)
133 theModule->setAttr(cir::CIRDialect::getOptInfoAttrName(),
134 cir::OptInfoAttr::get(&mlirContext,
135 cgo.OptimizationLevel,
136 cgo.OptimizeSize));
137
138 if (langOpts.CUDA)
139 createCUDARuntime();
140
141 // Set the module name to be the name of the main file. TranslationUnitDecl
142 // often contains invalid source locations and isn't a reliable source for the
143 // module location.
144 FileID mainFileId = astContext.getSourceManager().getMainFileID();
145 const FileEntry &mainFile =
146 *astContext.getSourceManager().getFileEntryForID(mainFileId);
147 StringRef path = mainFile.tryGetRealPathName();
148 if (!path.empty()) {
149 theModule.setSymName(path);
150 theModule->setLoc(mlir::FileLineColLoc::get(&mlirContext, path,
151 /*line=*/0,
152 /*column=*/0));
153 }
154}
155
157
158void CIRGenModule::createCUDARuntime() {
159 cudaRuntime.reset(createNVCUDARuntime(*this));
160}
161
162/// FIXME: this could likely be a common helper and not necessarily related
163/// with codegen.
164/// Return the best known alignment for an unknown pointer to a
165/// particular class.
167 if (!rd->hasDefinition())
168 return CharUnits::One(); // Hopefully won't be used anywhere.
169
170 auto &layout = astContext.getASTRecordLayout(rd);
171
172 // If the class is final, then we know that the pointer points to an
173 // object of that type and can use the full alignment.
174 if (rd->isEffectivelyFinal())
175 return layout.getAlignment();
176
177 // Otherwise, we have to assume it could be a subclass.
178 return layout.getNonVirtualAlignment();
179}
180
182 LValueBaseInfo *baseInfo,
183 bool forPointeeType) {
185
186 // FIXME: This duplicates logic in ASTContext::getTypeAlignIfKnown, but
187 // that doesn't return the information we need to compute baseInfo.
188
189 // Honor alignment typedef attributes even on incomplete types.
190 // We also honor them straight for C++ class types, even as pointees;
191 // there's an expressivity gap here.
192 if (const auto *tt = t->getAs<TypedefType>()) {
193 if (unsigned align = tt->getDecl()->getMaxAlignment()) {
194 if (baseInfo)
196 return astContext.toCharUnitsFromBits(align);
197 }
198 }
199
200 bool alignForArray = t->isArrayType();
201
202 // Analyze the base element type, so we don't get confused by incomplete
203 // array types.
204 t = astContext.getBaseElementType(t);
205
206 if (t->isIncompleteType()) {
207 // We could try to replicate the logic from
208 // ASTContext::getTypeAlignIfKnown, but nothing uses the alignment if the
209 // type is incomplete, so it's impossible to test. We could try to reuse
210 // getTypeAlignIfKnown, but that doesn't return the information we need
211 // to set baseInfo. So just ignore the possibility that the alignment is
212 // greater than one.
213 if (baseInfo)
215 return CharUnits::One();
216 }
217
218 if (baseInfo)
220
221 CharUnits alignment;
222 const CXXRecordDecl *rd = nullptr;
223 if (t.getQualifiers().hasUnaligned()) {
224 alignment = CharUnits::One();
225 } else if (forPointeeType && !alignForArray &&
226 (rd = t->getAsCXXRecordDecl())) {
227 alignment = getClassPointerAlignment(rd);
228 } else {
229 alignment = astContext.getTypeAlignInChars(t);
230 }
231
232 // Cap to the global maximum type alignment unless the alignment
233 // was somehow explicit on the type.
234 if (unsigned maxAlign = astContext.getLangOpts().MaxTypeAlign) {
235 if (alignment.getQuantity() > maxAlign &&
236 !astContext.isAlignmentRequired(t))
237 alignment = CharUnits::fromQuantity(maxAlign);
238 }
239 return alignment;
240}
241
243 if (theTargetCIRGenInfo)
244 return *theTargetCIRGenInfo;
245
246 const llvm::Triple &triple = getTarget().getTriple();
247 switch (triple.getArch()) {
248 default:
250
251 // Currently we just fall through to x86_64.
252 [[fallthrough]];
253
254 case llvm::Triple::x86_64: {
255 switch (triple.getOS()) {
256 default:
258
259 // Currently we just fall through to x86_64.
260 [[fallthrough]];
261
262 case llvm::Triple::Linux:
263 theTargetCIRGenInfo = createX8664TargetCIRGenInfo(genTypes);
264 return *theTargetCIRGenInfo;
265 }
266 }
267 case llvm::Triple::nvptx:
268 case llvm::Triple::nvptx64:
269 theTargetCIRGenInfo = createNVPTXTargetCIRGenInfo(genTypes);
270 return *theTargetCIRGenInfo;
271 case llvm::Triple::amdgcn: {
272 theTargetCIRGenInfo = createAMDGPUTargetCIRGenInfo(genTypes);
273 return *theTargetCIRGenInfo;
274 }
275 }
276}
277
279 assert(cLoc.isValid() && "expected valid source location");
280 const SourceManager &sm = astContext.getSourceManager();
281 PresumedLoc pLoc = sm.getPresumedLoc(cLoc);
282 StringRef filename = pLoc.getFilename();
283 return mlir::FileLineColLoc::get(builder.getStringAttr(filename),
284 pLoc.getLine(), pLoc.getColumn());
285}
286
287mlir::Location CIRGenModule::getLoc(SourceRange cRange) {
288 assert(cRange.isValid() && "expected a valid source range");
289 mlir::Location begin = getLoc(cRange.getBegin());
290 mlir::Location end = getLoc(cRange.getEnd());
291 mlir::Attribute metadata;
292 return mlir::FusedLoc::get({begin, end}, metadata, builder.getContext());
293}
294
295mlir::Operation *
297 const Decl *d = gd.getDecl();
298
300 return getAddrOfCXXStructor(gd, /*FnInfo=*/nullptr, /*FnType=*/nullptr,
301 /*DontDefer=*/false, isForDefinition);
302
303 if (isa<CXXMethodDecl>(d)) {
304 const CIRGenFunctionInfo &fi =
306 cir::FuncType ty = getTypes().getFunctionType(fi);
307 return getAddrOfFunction(gd, ty, /*ForVTable=*/false, /*DontDefer=*/false,
308 isForDefinition);
309 }
310
311 if (isa<FunctionDecl>(d)) {
313 cir::FuncType ty = getTypes().getFunctionType(fi);
314 return getAddrOfFunction(gd, ty, /*ForVTable=*/false, /*DontDefer=*/false,
315 isForDefinition);
316 }
317
318 return getAddrOfGlobalVar(cast<VarDecl>(d), /*ty=*/nullptr, isForDefinition)
319 .getDefiningOp();
320}
321
323 // We call getAddrOfGlobal with isForDefinition set to ForDefinition in
324 // order to get a Value with exactly the type we need, not something that
325 // might have been created for another decl with the same mangled name but
326 // different type.
327 mlir::Operation *op = getAddrOfGlobal(d, ForDefinition);
328
329 // In case of different address spaces, we may still get a cast, even with
330 // IsForDefinition equal to ForDefinition. Query mangled names table to get
331 // GlobalValue.
332 if (!op)
334
335 assert(op && "expected a valid global op");
336
337 // Check to see if we've already emitted this. This is necessary for a
338 // couple of reasons: first, decls can end up in deferred-decls queue
339 // multiple times, and second, decls can end up with definitions in unusual
340 // ways (e.g. by an extern inline function acquiring a strong function
341 // redefinition). Just ignore those cases.
342 // TODO: Not sure what to map this to for MLIR
343 mlir::Operation *globalValueOp = op;
344 if (auto gv = dyn_cast<cir::GetGlobalOp>(op))
345 globalValueOp =
346 mlir::SymbolTable::lookupSymbolIn(getModule(), gv.getNameAttr());
347
348 if (auto cirGlobalValue =
349 dyn_cast<cir::CIRGlobalValueInterface>(globalValueOp))
350 if (!cirGlobalValue.isDeclaration())
351 return;
352
353 // If this is OpenMP, check if it is legal to emit this global normally.
355
356 // Otherwise, emit the definition and move on to the next one.
358}
359
361 // Emit code for any potentially referenced deferred decls. Since a previously
362 // unused static decl may become used during the generation of code for a
363 // static function, iterate until no changes are made.
364
366
368 // Emitting a vtable doesn't directly cause more vtables to
369 // become deferred, although it can cause functions to be
370 // emitted that then need those vtables.
371 assert(deferredVTables.empty());
372
374
375 // Stop if we're out of both deferred vtables and deferred declarations.
376 if (deferredDeclsToEmit.empty())
377 return;
378
379 // Grab the list of decls to emit. If emitGlobalDefinition schedules more
380 // work, it will not interfere with this.
381 std::vector<GlobalDecl> curDeclsToEmit;
382 curDeclsToEmit.swap(deferredDeclsToEmit);
383
384 for (const GlobalDecl &d : curDeclsToEmit) {
386
387 // If we found out that we need to emit more decls, do that recursively.
388 // This has the advantage that the decls are emitted in a DFS and related
389 // ones are close together, which is convenient for testing.
390 if (!deferredVTables.empty() || !deferredDeclsToEmit.empty()) {
391 emitDeferred();
392 assert(deferredVTables.empty() && deferredDeclsToEmit.empty());
393 }
394 }
395}
396
397template <typename AttrT> static bool hasImplicitAttr(const ValueDecl *decl) {
398 if (!decl)
399 return false;
400 if (auto *attr = decl->getAttr<AttrT>())
401 return attr->isImplicit();
402 return decl->isImplicit();
403}
404
405// TODO(cir): This should be shared with OG Codegen.
407 assert(langOpts.CUDA && "Should not be called by non-CUDA languages");
408 // We need to emit host-side 'shadows' for all global
409 // device-side variables because the CUDA runtime needs their
410 // size and host-side address in order to provide access to
411 // their device-side incarnations.
412 return !langOpts.CUDAIsDevice || global->hasAttr<CUDADeviceAttr>() ||
413 global->hasAttr<CUDAConstantAttr>() ||
414 global->hasAttr<CUDASharedAttr>() ||
417}
418
420 if (const auto *cd = dyn_cast<clang::OpenACCConstructDecl>(gd.getDecl())) {
422 return;
423 }
424
425 // TODO(OMP): The logic in this function for the 'rest' of the OpenMP
426 // declarative declarations is complicated and needs to be done on a per-kind
427 // basis, so all of that needs to be added when we implement the individual
428 // global-allowed declarations. See uses of `cir::MissingFeatures::openMP
429 // throughout this function.
430
431 const auto *global = cast<ValueDecl>(gd.getDecl());
432
433 // If this is CUDA, be selective about which declarations we emit.
434 // Non-constexpr non-lambda implicit host device functions are not emitted
435 // unless they are used on device side.
436 if (langOpts.CUDA) {
437 assert((isa<FunctionDecl>(global) || isa<VarDecl>(global)) &&
438 "Expected Variable or Function");
439 if (const auto *varDecl = dyn_cast<VarDecl>(global)) {
441 return;
442 // TODO(cir): This should be shared with OG Codegen.
443 } else if (langOpts.CUDAIsDevice) {
444 const auto *functionDecl = dyn_cast<FunctionDecl>(global);
445 if ((!global->hasAttr<CUDADeviceAttr>() ||
446 (langOpts.OffloadImplicitHostDeviceTemplates &&
449 !functionDecl->isConstexpr() &&
451 !getASTContext().CUDAImplicitHostDeviceFunUsedByDevice.count(
452 functionDecl))) &&
453 !global->hasAttr<CUDAGlobalAttr>() &&
454 !(langOpts.HIPStdPar && isa<FunctionDecl>(global) &&
455 !global->hasAttr<CUDAHostAttr>()))
456 return;
457 // Device-only functions are the only things we skip.
458 } else if (!global->hasAttr<CUDAHostAttr>() &&
459 global->hasAttr<CUDADeviceAttr>())
460 return;
461 }
462
463 if (const auto *fd = dyn_cast<FunctionDecl>(global)) {
464 // Update deferred annotations with the latest declaration if the function
465 // was already used or defined.
466 if (fd->hasAttr<AnnotateAttr>())
467 errorNYI(fd->getSourceRange(), "deferredAnnotations");
468 if (!fd->doesThisDeclarationHaveABody()) {
469 if (!fd->doesDeclarationForceExternallyVisibleDefinition())
470 return;
471
472 errorNYI(fd->getSourceRange(),
473 "function declaration that forces code gen");
474 return;
475 }
476 } else {
477 const auto *vd = cast<VarDecl>(global);
478 assert(vd->isFileVarDecl() && "Cannot emit local var decl as global.");
479 if (vd->isThisDeclarationADefinition() != VarDecl::Definition &&
480 !astContext.isMSStaticDataMemberInlineDefinition(vd)) {
482 // If this declaration may have caused an inline variable definition to
483 // change linkage, make sure that it's emitted.
484 if (astContext.getInlineVariableDefinitionKind(vd) ==
487 // Otherwise, we can ignore this declaration. The variable will be emitted
488 // on its first use.
489 return;
490 }
491 }
492
493 // Defer code generation to first use when possible, e.g. if this is an inline
494 // function. If the global must always be emitted, do it eagerly if possible
495 // to benefit from cache locality. Deferring code generation is necessary to
496 // avoid adding initializers to external declarations.
497 if (mustBeEmitted(global) && mayBeEmittedEagerly(global)) {
498 // Emit the definition if it can't be deferred.
500 return;
501 }
502
503 // If we're deferring emission of a C++ variable with an initializer, remember
504 // the order in which it appeared on the file.
506
507 llvm::StringRef mangledName = getMangledName(gd);
508 if (getGlobalValue(mangledName) != nullptr) {
509 // The value has already been used and should therefore be emitted.
511 } else if (mustBeEmitted(global)) {
512 // The value must be emitted, but cannot be emitted eagerly.
513 assert(!mayBeEmittedEagerly(global));
515 } else {
516 // Otherwise, remember that we saw a deferred decl with this name. The first
517 // use of the mangled name will cause it to move into deferredDeclsToEmit.
518 deferredDecls[mangledName] = gd;
519 }
520}
521
523 mlir::Operation *op) {
524 auto const *funcDecl = cast<FunctionDecl>(gd.getDecl());
526 cir::FuncType funcType = getTypes().getFunctionType(fi);
527 cir::FuncOp funcOp = dyn_cast_if_present<cir::FuncOp>(op);
528 if (!funcOp || funcOp.getFunctionType() != funcType) {
529 funcOp = getAddrOfFunction(gd, funcType, /*ForVTable=*/false,
530 /*DontDefer=*/true, ForDefinition);
531 }
532
533 // Already emitted.
534 if (!funcOp.isDeclaration())
535 return;
536
537 setFunctionLinkage(gd, funcOp);
538 setGVProperties(funcOp, funcDecl);
540 maybeSetTrivialComdat(*funcDecl, funcOp);
542
543 CIRGenFunction cgf(*this, builder);
544 curCGF = &cgf;
545 {
546 mlir::OpBuilder::InsertionGuard guard(builder);
547 cgf.generateCode(gd, funcOp, funcType);
548 }
549 curCGF = nullptr;
550
551 setNonAliasAttributes(gd, funcOp);
553
554 auto getPriority = [this](const auto *attr) -> int {
555 Expr *e = attr->getPriority();
556 if (e)
557 return e->EvaluateKnownConstInt(this->getASTContext()).getExtValue();
558 return attr->DefaultPriority;
559 };
560
561 if (const ConstructorAttr *ca = funcDecl->getAttr<ConstructorAttr>())
562 addGlobalCtor(funcOp, getPriority(ca));
563 if (const DestructorAttr *da = funcDecl->getAttr<DestructorAttr>())
564 addGlobalDtor(funcOp, getPriority(da));
565
566 if (funcDecl->getAttr<AnnotateAttr>())
567 errorNYI(funcDecl->getSourceRange(), "deferredAnnotations");
568}
569
570/// Track functions to be called before main() runs.
571void CIRGenModule::addGlobalCtor(cir::FuncOp ctor,
572 std::optional<int> priority) {
575
576 // Traditional LLVM codegen directly adds the function to the list of global
577 // ctors. In CIR we just add a global_ctor attribute to the function. The
578 // global list is created in LoweringPrepare.
579 //
580 // FIXME(from traditional LLVM): Type coercion of void()* types.
581 ctor.setGlobalCtorPriority(priority);
582}
583
584/// Add a function to the list that will be called when the module is unloaded.
585void CIRGenModule::addGlobalDtor(cir::FuncOp dtor,
586 std::optional<int> priority) {
587 if (codeGenOpts.RegisterGlobalDtorsWithAtExit &&
588 (!getASTContext().getTargetInfo().getTriple().isOSAIX()))
589 errorNYI(dtor.getLoc(), "registerGlobalDtorsWithAtExit");
590
591 // FIXME(from traditional LLVM): Type coercion of void()* types.
592 dtor.setGlobalDtorPriority(priority);
593}
594
597 if (dk == VarDecl::Definition && vd->hasAttr<DLLImportAttr>())
598 return;
599
601 // If we have a definition, this might be a deferred decl. If the
602 // instantiation is explicit, make sure we emit it at the end.
605
607}
608
609mlir::Operation *CIRGenModule::getGlobalValue(StringRef name) {
610 return mlir::SymbolTable::lookupSymbolIn(theModule, name);
611}
612
613cir::GlobalOp
614CIRGenModule::createGlobalOp(CIRGenModule &cgm, mlir::Location loc,
615 StringRef name, mlir::Type t, bool isConstant,
616 mlir::ptr::MemorySpaceAttrInterface addrSpace,
617 mlir::Operation *insertPoint) {
618 cir::GlobalOp g;
619 CIRGenBuilderTy &builder = cgm.getBuilder();
620
621 {
622 mlir::OpBuilder::InsertionGuard guard(builder);
623
624 // If an insertion point is provided, we're replacing an existing global,
625 // otherwise, create the new global immediately after the last gloabl we
626 // emitted.
627 if (insertPoint) {
628 builder.setInsertionPoint(insertPoint);
629 } else {
630 // Group global operations together at the top of the module.
631 if (cgm.lastGlobalOp)
632 builder.setInsertionPointAfter(cgm.lastGlobalOp);
633 else
634 builder.setInsertionPointToStart(cgm.getModule().getBody());
635 }
636
637 g = cir::GlobalOp::create(builder, loc, name, t, isConstant, addrSpace);
638 if (!insertPoint)
639 cgm.lastGlobalOp = g;
640
641 // Default to private until we can judge based on the initializer,
642 // since MLIR doesn't allow public declarations.
643 mlir::SymbolTable::setSymbolVisibility(
644 g, mlir::SymbolTable::Visibility::Private);
645 }
646 return g;
647}
648
649void CIRGenModule::setCommonAttributes(GlobalDecl gd, mlir::Operation *gv) {
650 const Decl *d = gd.getDecl();
651 if (isa_and_nonnull<NamedDecl>(d))
652 setGVProperties(gv, dyn_cast<NamedDecl>(d));
655}
656
657void CIRGenModule::setNonAliasAttributes(GlobalDecl gd, mlir::Operation *op) {
658 setCommonAttributes(gd, op);
659
664
666}
667
668std::optional<cir::SourceLanguage> CIRGenModule::getCIRSourceLanguage() const {
669 using ClangStd = clang::LangStandard;
670 using CIRLang = cir::SourceLanguage;
671 auto opts = getLangOpts();
672
673 if (opts.CPlusPlus)
674 return CIRLang::CXX;
675 if (opts.C99 || opts.C11 || opts.C17 || opts.C23 || opts.C2y ||
676 opts.LangStd == ClangStd::lang_c89 ||
677 opts.LangStd == ClangStd::lang_gnu89)
678 return CIRLang::C;
679
680 // TODO(cir): support remaining source languages.
682 errorNYI("CIR does not yet support the given source language");
683 return std::nullopt;
684}
685
686LangAS CIRGenModule::getGlobalVarAddressSpace(const VarDecl *d) {
687 if (langOpts.OpenCL) {
692 return as;
693 }
694
695 if (langOpts.SYCLIsDevice &&
696 (!d || d->getType().getAddressSpace() == LangAS::Default))
697 errorNYI("SYCL global address space");
698
699 if (langOpts.CUDA && langOpts.CUDAIsDevice) {
700 if (d) {
701 if (d->hasAttr<CUDAConstantAttr>())
703 if (d->hasAttr<CUDASharedAttr>())
704 return LangAS::cuda_shared;
705 if (d->hasAttr<CUDADeviceAttr>())
706 return LangAS::cuda_device;
707 if (d->getType().isConstQualified())
709 }
710 return LangAS::cuda_device;
711 }
712
713 if (langOpts.OpenMP)
714 errorNYI("OpenMP global address space");
715
717}
718
719static void setLinkageForGV(cir::GlobalOp &gv, const NamedDecl *nd) {
720 // Set linkage and visibility in case we never see a definition.
722 // Don't set internal linkage on declarations.
723 // "extern_weak" is overloaded in LLVM; we probably should have
724 // separate linkage types for this.
726 (nd->hasAttr<WeakAttr>() || nd->isWeakImported()))
727 gv.setLinkage(cir::GlobalLinkageKind::ExternalWeakLinkage);
728}
729
730static llvm::SmallVector<int64_t> indexesOfArrayAttr(mlir::ArrayAttr indexes) {
732 for (mlir::Attribute i : indexes) {
733 auto ind = mlir::cast<mlir::IntegerAttr>(i);
734 inds.push_back(ind.getValue().getSExtValue());
735 }
736 return inds;
737}
738
739static bool isViewOnGlobal(cir::GlobalOp glob, cir::GlobalViewAttr view) {
740 return view.getSymbol().getValue() == glob.getSymName();
741}
742
743static cir::GlobalViewAttr createNewGlobalView(CIRGenModule &cgm,
744 cir::GlobalOp newGlob,
745 cir::GlobalViewAttr attr,
746 mlir::Type oldTy) {
747 // If the attribute does not require indexes or it is not a global view on
748 // the global we're replacing, keep the original attribute.
749 if (!attr.getIndices() || !isViewOnGlobal(newGlob, attr))
750 return attr;
751
752 llvm::SmallVector<int64_t> oldInds = indexesOfArrayAttr(attr.getIndices());
754 CIRGenBuilderTy &bld = cgm.getBuilder();
755 const cir::CIRDataLayout &layout = cgm.getDataLayout();
756 mlir::Type newTy = newGlob.getSymType();
757
758 uint64_t offset =
759 bld.computeOffsetFromGlobalViewIndices(layout, oldTy, oldInds);
760 bld.computeGlobalViewIndicesFromFlatOffset(offset, newTy, layout, newInds);
761 cir::PointerType newPtrTy;
762
763 if (isa<cir::RecordType>(oldTy))
764 newPtrTy = cir::PointerType::get(newTy);
765 else if (isa<cir::ArrayType>(oldTy))
766 newPtrTy = cast<cir::PointerType>(attr.getType());
767
768 if (newPtrTy)
769 return bld.getGlobalViewAttr(newPtrTy, newGlob, newInds);
770
771 // This may be unreachable in practice, but keep it as errorNYI while CIR
772 // is still under development.
773 cgm.errorNYI("Unhandled type in createNewGlobalView");
774 return {};
775}
776
777static mlir::Attribute getNewInitValue(CIRGenModule &cgm, cir::GlobalOp newGlob,
778 mlir::Type oldTy,
779 mlir::Attribute oldInit) {
780 if (auto oldView = mlir::dyn_cast<cir::GlobalViewAttr>(oldInit))
781 return createNewGlobalView(cgm, newGlob, oldView, oldTy);
782
783 auto getNewInitElements =
784 [&](mlir::ArrayAttr oldElements) -> mlir::ArrayAttr {
786 for (mlir::Attribute elt : oldElements) {
787 if (auto view = mlir::dyn_cast<cir::GlobalViewAttr>(elt))
788 newElements.push_back(createNewGlobalView(cgm, newGlob, view, oldTy));
789 else if (mlir::isa<cir::ConstArrayAttr, cir::ConstRecordAttr>(elt))
790 newElements.push_back(getNewInitValue(cgm, newGlob, oldTy, elt));
791 else
792 newElements.push_back(elt);
793 }
794 return mlir::ArrayAttr::get(cgm.getBuilder().getContext(), newElements);
795 };
796
797 if (auto oldArray = mlir::dyn_cast<cir::ConstArrayAttr>(oldInit)) {
798 mlir::Attribute newElements =
799 getNewInitElements(mlir::cast<mlir::ArrayAttr>(oldArray.getElts()));
800 return cgm.getBuilder().getConstArray(
801 newElements, mlir::cast<cir::ArrayType>(oldArray.getType()));
802 }
803 if (auto oldRecord = mlir::dyn_cast<cir::ConstRecordAttr>(oldInit)) {
804 mlir::ArrayAttr newMembers = getNewInitElements(oldRecord.getMembers());
805 auto recordTy = mlir::cast<cir::RecordType>(oldRecord.getType());
807 newMembers, recordTy.getPacked(), recordTy.getPadded(), recordTy);
808 }
809
810 // This may be unreachable in practice, but keep it as errorNYI while CIR
811 // is still under development.
812 cgm.errorNYI("Unhandled type in getNewInitValue");
813 return {};
814}
815
816// We want to replace a global value, but because of CIR's typed pointers,
817// we need to update the existing uses to reflect the new type, not just replace
818// them directly.
819void CIRGenModule::replaceGlobal(cir::GlobalOp oldGV, cir::GlobalOp newGV) {
820 assert(oldGV.getSymName() == newGV.getSymName() && "symbol names must match");
821
822 mlir::Type oldTy = oldGV.getSymType();
823 mlir::Type newTy = newGV.getSymType();
824
826
827 // If the type didn't change, why are we here?
828 assert(oldTy != newTy && "expected type change in replaceGlobal");
829
830 // Visit all uses and add handling to fix up the types.
831 std::optional<mlir::SymbolTable::UseRange> oldSymUses =
832 oldGV.getSymbolUses(theModule);
833 for (mlir::SymbolTable::SymbolUse use : *oldSymUses) {
834 mlir::Operation *userOp = use.getUser();
835 assert(
836 (mlir::isa<cir::GetGlobalOp, cir::GlobalOp, cir::ConstantOp>(userOp)) &&
837 "Unexpected user for global op");
838
839 if (auto getGlobalOp = dyn_cast<cir::GetGlobalOp>(use.getUser())) {
840 mlir::Value useOpResultValue = getGlobalOp.getAddr();
841 useOpResultValue.setType(cir::PointerType::get(newTy));
842
843 mlir::OpBuilder::InsertionGuard guard(builder);
844 builder.setInsertionPointAfter(getGlobalOp);
845 mlir::Type ptrTy = builder.getPointerTo(oldTy);
846 mlir::Value cast =
847 builder.createBitcast(getGlobalOp->getLoc(), useOpResultValue, ptrTy);
848 useOpResultValue.replaceAllUsesExcept(cast, cast.getDefiningOp());
849 } else if (auto glob = dyn_cast<cir::GlobalOp>(userOp)) {
850 if (auto init = glob.getInitialValue()) {
851 mlir::Attribute nw = getNewInitValue(*this, newGV, oldTy, init.value());
852 glob.setInitialValueAttr(nw);
853 }
854 } else if (auto c = dyn_cast<cir::ConstantOp>(userOp)) {
855 mlir::Attribute init = getNewInitValue(*this, newGV, oldTy, c.getValue());
856 auto typedAttr = mlir::cast<mlir::TypedAttr>(init);
857 mlir::OpBuilder::InsertionGuard guard(builder);
858 builder.setInsertionPointAfter(c);
859 auto newUser = cir::ConstantOp::create(builder, c.getLoc(), typedAttr);
860 c.replaceAllUsesWith(newUser.getOperation());
861 c.erase();
862 }
863 }
864
865 oldGV.erase();
866}
867
868/// If the specified mangled name is not in the module,
869/// create and return an mlir GlobalOp with the specified type (TODO(cir):
870/// address space).
871///
872/// TODO(cir):
873/// 1. If there is something in the module with the specified name, return
874/// it potentially bitcasted to the right type.
875///
876/// 2. If \p d is non-null, it specifies a decl that correspond to this. This
877/// is used to set the attributes on the global when it is first created.
878///
879/// 3. If \p isForDefinition is true, it is guaranteed that an actual global
880/// with type \p ty will be returned, not conversion of a variable with the same
881/// mangled name but some other type.
882cir::GlobalOp
883CIRGenModule::getOrCreateCIRGlobal(StringRef mangledName, mlir::Type ty,
884 LangAS langAS, const VarDecl *d,
885 ForDefinition_t isForDefinition) {
886 // Lookup the entry, lazily creating it if necessary.
887 cir::GlobalOp entry;
888 if (mlir::Operation *v = getGlobalValue(mangledName)) {
889 if (!isa<cir::GlobalOp>(v))
891 "getOrCreateCIRGlobal: global with non-GlobalOp type");
892 entry = cast<cir::GlobalOp>(v);
893 }
894
895 if (entry) {
897
900
901 if (entry.getSymType() == ty &&
902 (cir::isMatchingAddressSpace(entry.getAddrSpaceAttr(), langAS)))
903 return entry;
904
905 // If there are two attempts to define the same mangled name, issue an
906 // error.
907 //
908 // TODO(cir): look at mlir::GlobalValue::isDeclaration for all aspects of
909 // recognizing the global as a declaration, for now only check if
910 // initializer is present.
911 if (isForDefinition && !entry.isDeclaration()) {
913 "getOrCreateCIRGlobal: global with conflicting type");
914 }
915
916 // Address space check removed because it is unnecessary because CIR records
917 // address space info in types.
918
919 // (If global is requested for a definition, we always need to create a new
920 // global, not just return a bitcast.)
921 if (!isForDefinition)
922 return entry;
923 }
924
925 mlir::Location loc = getLoc(d->getSourceRange());
926
927 // Calculate constant storage flag before creating the global. This was moved
928 // from after the global creation to ensure the constant flag is set correctly
929 // at creation time, matching the logic used in emitCXXGlobalVarDeclInit.
930 bool isConstant = false;
931 if (d) {
932 bool needsDtor =
934 isConstant = d->getType().isConstantStorage(
935 astContext, /*ExcludeCtor=*/true, /*ExcludeDtor=*/!needsDtor);
936 }
937
938 mlir::ptr::MemorySpaceAttrInterface declCIRAS =
939 cir::toCIRAddressSpaceAttr(getMLIRContext(), getGlobalVarAddressSpace(d));
940
941 // mlir::SymbolTable::Visibility::Public is the default, no need to explicitly
942 // mark it as such.
943 cir::GlobalOp gv = CIRGenModule::createGlobalOp(
944 *this, loc, mangledName, ty, isConstant, declCIRAS,
945 /*insertPoint=*/entry.getOperation());
946
947 // If we already created a global with the same mangled name (but different
948 // type) before, remove it from its parent.
949 if (entry)
950 replaceGlobal(entry, gv);
951
952 // This is the first use or definition of a mangled name. If there is a
953 // deferred decl with this name, remember that we need to emit it at the end
954 // of the file.
955 auto ddi = deferredDecls.find(mangledName);
956 if (ddi != deferredDecls.end()) {
957 // Move the potentially referenced deferred decl to the DeferredDeclsToEmit
958 // list, and remove it from DeferredDecls (since we don't need it anymore).
959 addDeferredDeclToEmit(ddi->second);
960 deferredDecls.erase(ddi);
961 }
962
963 // Handle things which are present even on external declarations.
964 if (d) {
965 if (langOpts.OpenMP && !langOpts.OpenMPSimd)
967 "getOrCreateCIRGlobal: OpenMP target global variable");
968
969 gv.setAlignmentAttr(getSize(astContext.getDeclAlign(d)));
970
971 setLinkageForGV(gv, d);
972
973 if (d->getTLSKind()) {
975 errorNYI(d->getSourceRange(), "getOrCreateCIRGlobal: TLS dynamic");
976 setTLSMode(gv, *d);
977 }
978
979 setGVProperties(gv, d);
980
981 // If required by the ABI, treat declarations of static data members with
982 // inline initializers as definitions.
983 if (astContext.isMSStaticDataMemberInlineDefinition(d))
985 "getOrCreateCIRGlobal: MS static data member inline definition");
986
988 gv.setGlobalVisibilityAttr(getGlobalVisibilityAttrFromDecl(d));
989
990 // Handle XCore specific ABI requirements.
991 if (getTriple().getArch() == llvm::Triple::xcore)
993 "getOrCreateCIRGlobal: XCore specific ABI requirements");
994
995 // Check if we a have a const declaration with an initializer, we may be
996 // able to emit it as available_externally to expose it's value to the
997 // optimizer.
998 if (getLangOpts().CPlusPlus && gv.isPublic() &&
999 d->getType().isConstQualified() && gv.isDeclaration() &&
1000 !d->hasDefinition() && d->hasInit() && !d->hasAttr<DLLImportAttr>())
1001 errorNYI(
1002 d->getSourceRange(),
1003 "getOrCreateCIRGlobal: external const declaration with initializer");
1004 }
1005
1006 if (d &&
1009 // TODO(cir): set target attributes
1010 // External HIP managed variables needed to be recorded for transformation
1011 // in both device and host compilations.
1012 if (getLangOpts().CUDA && d && d->hasAttr<HIPManagedAttr>() &&
1013 d->hasExternalStorage())
1015 "getOrCreateCIRGlobal: HIP managed attribute");
1016 }
1017
1019 return gv;
1020}
1021
1022cir::GlobalOp
1024 ForDefinition_t isForDefinition) {
1025 assert(d->hasGlobalStorage() && "Not a global variable");
1026 QualType astTy = d->getType();
1027 if (!ty)
1028 ty = getTypes().convertTypeForMem(astTy);
1029
1030 StringRef mangledName = getMangledName(d);
1031 return getOrCreateCIRGlobal(mangledName, ty, getGlobalVarAddressSpace(d), d,
1032 isForDefinition);
1033}
1034
1035/// Return the mlir::Value for the address of the given global variable. If
1036/// \p ty is non-null and if the global doesn't exist, then it will be created
1037/// with the specified type instead of whatever the normal requested type would
1038/// be. If \p isForDefinition is true, it is guaranteed that an actual global
1039/// with type \p ty will be returned, not conversion of a variable with the same
1040/// mangled name but some other type.
1041mlir::Value CIRGenModule::getAddrOfGlobalVar(const VarDecl *d, mlir::Type ty,
1042 ForDefinition_t isForDefinition) {
1043 assert(d->hasGlobalStorage() && "Not a global variable");
1044 QualType astTy = d->getType();
1045 if (!ty)
1046 ty = getTypes().convertTypeForMem(astTy);
1047
1048 bool tlsAccess = d->getTLSKind() != VarDecl::TLS_None;
1049 cir::GlobalOp g = getOrCreateCIRGlobal(d, ty, isForDefinition);
1050 mlir::Type ptrTy = builder.getPointerTo(g.getSymType(), g.getAddrSpaceAttr());
1051 return cir::GetGlobalOp::create(
1052 builder, getLoc(d->getSourceRange()), ptrTy, g.getSymNameAttr(),
1053 tlsAccess,
1054 /*static_local=*/g.getStaticLocalGuard().has_value());
1055}
1056
1057cir::GlobalViewAttr CIRGenModule::getAddrOfGlobalVarAttr(const VarDecl *d) {
1058 assert(d->hasGlobalStorage() && "Not a global variable");
1059 mlir::Type ty = getTypes().convertTypeForMem(d->getType());
1060
1061 cir::GlobalOp globalOp = getOrCreateCIRGlobal(d, ty, NotForDefinition);
1062 cir::PointerType ptrTy =
1063 builder.getPointerTo(globalOp.getSymType(), globalOp.getAddrSpaceAttr());
1064 return builder.getGlobalViewAttr(ptrTy, globalOp);
1065}
1066
1068 bool isTentative) {
1069 if (getLangOpts().OpenCL || getLangOpts().OpenMPIsTargetDevice) {
1071 "emitGlobalVarDefinition: emit OpenCL/OpenMP global variable");
1072 return;
1073 }
1074
1075 // Whether the definition of the variable is available externally.
1076 // If yes, we shouldn't emit the GloablCtor and GlobalDtor for the variable
1077 // since this is the job for its original source.
1078 bool isDefinitionAvailableExternally =
1079 astContext.GetGVALinkageForVariable(vd) == GVA_AvailableExternally;
1080
1081 // It is useless to emit the definition for an available_externally variable
1082 // which can't be marked as const.
1083 if (isDefinitionAvailableExternally &&
1084 (!vd->hasConstantInitialization() ||
1085 // TODO: Update this when we have interface to check constexpr
1086 // destructor.
1087 vd->needsDestruction(astContext) ||
1088 !vd->getType().isConstantStorage(astContext, true, true)))
1089 return;
1090
1091 mlir::Attribute init;
1092 bool needsGlobalCtor = false;
1093 bool needsGlobalDtor =
1094 !isDefinitionAvailableExternally &&
1096 const VarDecl *initDecl;
1097 const Expr *initExpr = vd->getAnyInitializer(initDecl);
1098
1099 std::optional<ConstantEmitter> emitter;
1100
1101 // CUDA E.2.4.1 "__shared__ variables cannot have an initialization
1102 // as part of their declaration." Sema has already checked for
1103 // error cases, so we just need to set Init to PoisonValue.
1104 bool isCUDASharedVar =
1105 getLangOpts().CUDAIsDevice && vd->hasAttr<CUDASharedAttr>();
1106 // Shadows of initialized device-side global variables are also left
1107 // undefined.
1108 // Managed Variables should be initialized on both host side and device side.
1109 bool isCUDAShadowVar =
1110 !getLangOpts().CUDAIsDevice && !vd->hasAttr<HIPManagedAttr>() &&
1111 (vd->hasAttr<CUDAConstantAttr>() || vd->hasAttr<CUDADeviceAttr>() ||
1112 vd->hasAttr<CUDASharedAttr>());
1113 bool isCUDADeviceShadowVar =
1114 getLangOpts().CUDAIsDevice && !vd->hasAttr<HIPManagedAttr>() &&
1117
1118 if (getLangOpts().CUDA &&
1119 (isCUDASharedVar || isCUDAShadowVar || isCUDADeviceShadowVar)) {
1120 init = cir::PoisonAttr::get(convertType(vd->getType()));
1121 } else if (vd->hasAttr<LoaderUninitializedAttr>()) {
1123 "emitGlobalVarDefinition: loader uninitialized attribute");
1124 } else if (!initExpr) {
1125 // This is a tentative definition; tentative definitions are
1126 // implicitly initialized with { 0 }.
1127 //
1128 // Note that tentative definitions are only emitted at the end of
1129 // a translation unit, so they should never have incomplete
1130 // type. In addition, EmitTentativeDefinition makes sure that we
1131 // never attempt to emit a tentative definition if a real one
1132 // exists. A use may still exists, however, so we still may need
1133 // to do a RAUW.
1134 assert(!vd->getType()->isIncompleteType() && "Unexpected incomplete type");
1135 init = builder.getZeroInitAttr(convertType(vd->getType()));
1136 } else {
1137 emitter.emplace(*this);
1138 mlir::Attribute initializer = emitter->tryEmitForInitializer(*initDecl);
1139 if (!initializer) {
1140 QualType qt = initExpr->getType();
1141 if (vd->getType()->isReferenceType())
1142 qt = vd->getType();
1143
1144 if (getLangOpts().CPlusPlus) {
1145 if (initDecl->hasFlexibleArrayInit(astContext))
1147 "emitGlobalVarDefinition: flexible array initializer");
1148 init = builder.getZeroInitAttr(convertType(qt));
1149 if (!isDefinitionAvailableExternally)
1150 needsGlobalCtor = true;
1151 } else {
1153 "emitGlobalVarDefinition: static initializer");
1154 }
1155 } else {
1156 init = initializer;
1157 // We don't need an initializer, so remove the entry for the delayed
1158 // initializer position (just in case this entry was delayed) if we
1159 // also don't need to register a destructor.
1161 }
1162 }
1163
1164 mlir::Type initType;
1165 if (mlir::isa<mlir::SymbolRefAttr>(init)) {
1166 errorNYI(
1167 vd->getSourceRange(),
1168 "emitGlobalVarDefinition: global initializer is a symbol reference");
1169 return;
1170 } else {
1171 assert(mlir::isa<mlir::TypedAttr>(init) && "This should have a type");
1172 auto typedInitAttr = mlir::cast<mlir::TypedAttr>(init);
1173 initType = typedInitAttr.getType();
1174 }
1175 assert(!mlir::isa<mlir::NoneType>(initType) && "Should have a type by now");
1176
1177 cir::GlobalOp gv =
1178 getOrCreateCIRGlobal(vd, initType, ForDefinition_t(!isTentative));
1179 // TODO(cir): Strip off pointer casts from Entry if we get them?
1180
1181 if (!gv || gv.getSymType() != initType) {
1183 "emitGlobalVarDefinition: global initializer with type mismatch");
1184 return;
1185 }
1186
1188
1189 if (vd->hasAttr<AnnotateAttr>()) {
1191 "emitGlobalVarDefinition: annotate global variable");
1192 }
1193
1194 // Set CIR's linkage type as appropriate.
1195 cir::GlobalLinkageKind linkage =
1196 getCIRLinkageVarDefinition(vd, /*IsConstant=*/false);
1197
1198 // CUDA B.2.1 "The __device__ qualifier declares a variable that resides on
1199 // the device. [...]"
1200 // CUDA B.2.2 "The __constant__ qualifier, optionally used together with
1201 // __device__, declares a variable that: [...]
1202 // Is accessible from all the threads within the grid and from the host
1203 // through the runtime library (cudaGetSymbolAddress() / cudaGetSymbolSize()
1204 // / cudaMemcpyToSymbol() / cudaMemcpyFromSymbol())."
1205 if (langOpts.CUDA) {
1206 if (langOpts.CUDAIsDevice) {
1207 // __shared__ variables is not marked as externally initialized,
1208 // because they must not be initialized.
1209 if (linkage != cir::GlobalLinkageKind::InternalLinkage &&
1210 !vd->isConstexpr() && !vd->getType().isConstQualified() &&
1211 (vd->hasAttr<CUDADeviceAttr>() || vd->hasAttr<CUDAConstantAttr>() ||
1214 gv->setAttr(cir::CUDAExternallyInitializedAttr::getMnemonic(),
1215 cir::CUDAExternallyInitializedAttr::get(&getMLIRContext()));
1216 }
1217 } else {
1218 // TODO(cir):
1219 // Adjust linkage of shadow variables in host compilation
1220 // getCUDARuntime().internalizeDeviceSideVar(vd, linkage);
1221 }
1222 // TODO(cir):
1223 // Handle variable registration
1224 // getCUDARuntime().handleVarRegistration(vd, gv);
1225 }
1226
1227 // Set initializer and finalize emission
1229 if (emitter)
1230 emitter->finalize(gv);
1231
1232 // If it is safe to mark the global 'constant', do so now.
1233 // Use the same logic as classic codegen EmitGlobalVarDefinition.
1234 gv.setConstant((vd->hasAttr<CUDAConstantAttr>() && langOpts.CUDAIsDevice) ||
1235 (!needsGlobalCtor && !needsGlobalDtor &&
1236 vd->getType().isConstantStorage(astContext,
1237 /*ExcludeCtor=*/true,
1238 /*ExcludeDtor=*/true)));
1240
1241 // Set CIR linkage and DLL storage class.
1242 gv.setLinkage(linkage);
1243 // FIXME(cir): setLinkage should likely set MLIR's visibility automatically.
1244 gv.setVisibility(getMLIRVisibilityFromCIRLinkage(linkage));
1246 if (linkage == cir::GlobalLinkageKind::CommonLinkage) {
1247 // common vars aren't constant even if declared const.
1248 gv.setConstant(false);
1249 // Tentative definition of global variables may be initialized with
1250 // non-zero null pointers. In this case they should have weak linkage
1251 // since common linkage must have zero initializer and must not have
1252 // explicit section therefore cannot have non-zero initial value.
1253 std::optional<mlir::Attribute> initializer = gv.getInitialValue();
1254 if (initializer && !getBuilder().isNullValue(*initializer))
1255 gv.setLinkage(cir::GlobalLinkageKind::WeakAnyLinkage);
1256 }
1257
1258 setNonAliasAttributes(vd, gv);
1259
1261
1262 maybeSetTrivialComdat(*vd, gv);
1263
1264 // Emit the initializer function if necessary.
1265 if (needsGlobalCtor || needsGlobalDtor)
1266 emitCXXGlobalVarDeclInitFunc(vd, gv, needsGlobalCtor);
1267}
1268
1270 mlir::Operation *op) {
1271 const auto *decl = cast<ValueDecl>(gd.getDecl());
1272 if (const auto *fd = dyn_cast<FunctionDecl>(decl)) {
1273 // TODO(CIR): Skip generation of CIR for functions with available_externally
1274 // linkage at -O0.
1275
1276 if (const auto *method = dyn_cast<CXXMethodDecl>(decl)) {
1277 // Make sure to emit the definition(s) before we emit the thunks. This is
1278 // necessary for the generation of certain thunks.
1279 if (isa<CXXConstructorDecl>(method) || isa<CXXDestructorDecl>(method))
1280 abi->emitCXXStructor(gd);
1281 else if (fd->isMultiVersion())
1282 errorNYI(method->getSourceRange(), "multiversion functions");
1283 else
1285
1286 if (method->isVirtual())
1287 getVTables().emitThunks(gd);
1288
1289 return;
1290 }
1291
1292 if (fd->isMultiVersion())
1293 errorNYI(fd->getSourceRange(), "multiversion functions");
1295 return;
1296 }
1297
1298 if (const auto *vd = dyn_cast<VarDecl>(decl))
1299 return emitGlobalVarDefinition(vd, !vd->hasDefinition());
1300
1301 llvm_unreachable("Invalid argument to CIRGenModule::emitGlobalDefinition");
1302}
1303
1304mlir::Attribute
1306 assert(!e->getType()->isPointerType() && "Strings are always arrays");
1307
1308 // Don't emit it as the address of the string, emit the string data itself
1309 // as an inline array.
1310 if (e->getCharByteWidth() == 1) {
1311 SmallString<64> str(e->getString());
1312
1313 // Resize the string to the right size, which is indicated by its type.
1314 const ConstantArrayType *cat =
1315 astContext.getAsConstantArrayType(e->getType());
1316 uint64_t finalSize = cat->getZExtSize();
1317 str.resize(finalSize);
1318
1319 mlir::Type eltTy = convertType(cat->getElementType());
1320 return builder.getString(str, eltTy, finalSize, /*ensureNullTerm=*/false);
1321 }
1322
1323 auto arrayTy = mlir::cast<cir::ArrayType>(convertType(e->getType()));
1324
1325 auto arrayEltTy = mlir::cast<cir::IntType>(arrayTy.getElementType());
1326
1327 uint64_t arraySize = arrayTy.getSize();
1328 unsigned literalSize = e->getLength();
1329 assert(arraySize == literalSize + 1 &&
1330 "wide string literal array size must be literal length plus null "
1331 "terminator");
1332
1333 // Check if the string is all null bytes before building the vector.
1334 // In most non-zero cases, this will break out on the first element.
1335 bool isAllZero = true;
1336 for (unsigned i = 0; i < literalSize; ++i) {
1337 if (e->getCodeUnit(i) != 0) {
1338 isAllZero = false;
1339 break;
1340 }
1341 }
1342
1343 if (isAllZero)
1344 return cir::ZeroAttr::get(arrayTy);
1345
1346 // Otherwise emit a constant array holding the characters.
1348 elements.reserve(arraySize);
1349 for (unsigned i = 0; i < literalSize; ++i)
1350 elements.push_back(cir::IntAttr::get(arrayEltTy, e->getCodeUnit(i)));
1351 // Add null terminator
1352 elements.push_back(cir::IntAttr::get(arrayEltTy, 0));
1353
1354 auto elementsAttr = mlir::ArrayAttr::get(&getMLIRContext(), elements);
1355 return builder.getConstArray(elementsAttr, arrayTy);
1356}
1357
1359 return getTriple().supportsCOMDAT();
1360}
1361
1362static bool shouldBeInCOMDAT(CIRGenModule &cgm, const Decl &d) {
1363 if (!cgm.supportsCOMDAT())
1364 return false;
1365
1366 if (d.hasAttr<SelectAnyAttr>())
1367 return true;
1368
1369 GVALinkage linkage;
1370 if (auto *vd = dyn_cast<VarDecl>(&d))
1371 linkage = cgm.getASTContext().GetGVALinkageForVariable(vd);
1372 else
1373 linkage =
1375
1376 switch (linkage) {
1380 return false;
1383 return true;
1384 }
1385 llvm_unreachable("No such linkage");
1386}
1387
1388void CIRGenModule::maybeSetTrivialComdat(const Decl &d, mlir::Operation *op) {
1389 if (!shouldBeInCOMDAT(*this, d))
1390 return;
1391 if (auto globalOp = dyn_cast_or_null<cir::GlobalOp>(op)) {
1392 globalOp.setComdat(true);
1393 } else {
1394 auto funcOp = cast<cir::FuncOp>(op);
1395 funcOp.setComdat(true);
1396 }
1397}
1398
1400 // Make sure that this type is translated.
1401 genTypes.updateCompletedType(td);
1402}
1403
1404void CIRGenModule::addReplacement(StringRef name, mlir::Operation *op) {
1405 replacements[name] = op;
1406}
1407
1408void CIRGenModule::replacePointerTypeArgs(cir::FuncOp oldF, cir::FuncOp newF) {
1409 std::optional<mlir::SymbolTable::UseRange> optionalUseRange =
1410 oldF.getSymbolUses(theModule);
1411 if (!optionalUseRange)
1412 return;
1413
1414 for (const mlir::SymbolTable::SymbolUse &u : *optionalUseRange) {
1415 // CallTryOp only shows up after FlattenCFG.
1416 auto call = mlir::dyn_cast<cir::CallOp>(u.getUser());
1417 if (!call)
1418 continue;
1419
1420 for (const auto [argOp, fnArgType] :
1421 llvm::zip(call.getArgs(), newF.getFunctionType().getInputs())) {
1422 if (argOp.getType() == fnArgType)
1423 continue;
1424
1425 // The purpose of this entire function is to insert bitcasts in the case
1426 // where these types don't match, but I haven't seen a case where that
1427 // happens.
1428 errorNYI(call.getLoc(), "replace call with mismatched types");
1429 }
1430 }
1431}
1432
1433void CIRGenModule::applyReplacements() {
1434 for (auto &i : replacements) {
1435 StringRef mangledName = i.first;
1436 mlir::Operation *replacement = i.second;
1437 mlir::Operation *entry = getGlobalValue(mangledName);
1438 if (!entry)
1439 continue;
1440 assert(isa<cir::FuncOp>(entry) && "expected function");
1441 auto oldF = cast<cir::FuncOp>(entry);
1442 auto newF = dyn_cast<cir::FuncOp>(replacement);
1443 if (!newF) {
1444 // In classic codegen, this can be a global alias, a bitcast, or a GEP.
1445 errorNYI(replacement->getLoc(), "replacement is not a function");
1446 continue;
1447 }
1448
1449 // LLVM has opaque pointer but CIR not. So we may have to handle these
1450 // different pointer types when performing replacement.
1451 replacePointerTypeArgs(oldF, newF);
1452
1453 // Replace old with new, but keep the old order.
1454 if (oldF.replaceAllSymbolUses(newF.getSymNameAttr(), theModule).failed())
1455 llvm_unreachable("internal error, cannot RAUW symbol");
1456 if (newF) {
1457 newF->moveBefore(oldF);
1458 oldF->erase();
1459 }
1460 }
1461}
1462
1464 mlir::Location loc, StringRef name, mlir::Type ty,
1465 cir::GlobalLinkageKind linkage, clang::CharUnits alignment) {
1466 auto gv = mlir::dyn_cast_or_null<cir::GlobalOp>(
1467 mlir::SymbolTable::lookupSymbolIn(theModule, name));
1468
1469 if (gv) {
1470 // Check if the variable has the right type.
1471 if (gv.getSymType() == ty)
1472 return gv;
1473
1474 // Because of C++ name mangling, the only way we can end up with an already
1475 // existing global with the same name is if it has been declared extern
1476 // "C".
1477 assert(gv.isDeclaration() && "Declaration has wrong type!");
1478
1479 errorNYI(loc, "createOrReplaceCXXRuntimeVariable: declaration exists with "
1480 "wrong type");
1481 return gv;
1482 }
1483
1484 // Create a new variable.
1485 gv = createGlobalOp(*this, loc, name, ty);
1486
1487 // Set up extra information and add to the module
1488 gv.setLinkageAttr(
1489 cir::GlobalLinkageKindAttr::get(&getMLIRContext(), linkage));
1490 mlir::SymbolTable::setSymbolVisibility(gv,
1492
1493 if (supportsCOMDAT() && cir::isWeakForLinker(linkage) &&
1494 !gv.hasAvailableExternallyLinkage()) {
1495 gv.setComdat(true);
1496 }
1497
1498 gv.setAlignmentAttr(getSize(alignment));
1499 setDSOLocal(static_cast<mlir::Operation *>(gv));
1500 return gv;
1501}
1502
1503// TODO(CIR): this could be a common method between LLVM codegen.
1504static bool isVarDeclStrongDefinition(const ASTContext &astContext,
1505 CIRGenModule &cgm, const VarDecl *vd,
1506 bool noCommon) {
1507 // Don't give variables common linkage if -fno-common was specified unless it
1508 // was overridden by a NoCommon attribute.
1509 if ((noCommon || vd->hasAttr<NoCommonAttr>()) && !vd->hasAttr<CommonAttr>())
1510 return true;
1511
1512 // C11 6.9.2/2:
1513 // A declaration of an identifier for an object that has file scope without
1514 // an initializer, and without a storage-class specifier or with the
1515 // storage-class specifier static, constitutes a tentative definition.
1516 if (vd->getInit() || vd->hasExternalStorage())
1517 return true;
1518
1519 // A variable cannot be both common and exist in a section.
1520 if (vd->hasAttr<SectionAttr>())
1521 return true;
1522
1523 // A variable cannot be both common and exist in a section.
1524 // We don't try to determine which is the right section in the front-end.
1525 // If no specialized section name is applicable, it will resort to default.
1526 if (vd->hasAttr<PragmaClangBSSSectionAttr>() ||
1527 vd->hasAttr<PragmaClangDataSectionAttr>() ||
1528 vd->hasAttr<PragmaClangRelroSectionAttr>() ||
1529 vd->hasAttr<PragmaClangRodataSectionAttr>())
1530 return true;
1531
1532 // Thread local vars aren't considered common linkage.
1533 if (vd->getTLSKind())
1534 return true;
1535
1536 // Tentative definitions marked with WeakImportAttr are true definitions.
1537 if (vd->hasAttr<WeakImportAttr>())
1538 return true;
1539
1540 // A variable cannot be both common and exist in a comdat.
1541 if (shouldBeInCOMDAT(cgm, *vd))
1542 return true;
1543
1544 // Declarations with a required alignment do not have common linkage in MSVC
1545 // mode.
1546 if (astContext.getTargetInfo().getCXXABI().isMicrosoft()) {
1547 if (vd->hasAttr<AlignedAttr>())
1548 return true;
1549 QualType varType = vd->getType();
1550 if (astContext.isAlignmentRequired(varType))
1551 return true;
1552
1553 if (const auto *rd = varType->getAsRecordDecl()) {
1554 for (const FieldDecl *fd : rd->fields()) {
1555 if (fd->isBitField())
1556 continue;
1557 if (fd->hasAttr<AlignedAttr>())
1558 return true;
1559 if (astContext.isAlignmentRequired(fd->getType()))
1560 return true;
1561 }
1562 }
1563 }
1564
1565 // Microsoft's link.exe doesn't support alignments greater than 32 bytes for
1566 // common symbols, so symbols with greater alignment requirements cannot be
1567 // common.
1568 // Other COFF linkers (ld.bfd and LLD) support arbitrary power-of-two
1569 // alignments for common symbols via the aligncomm directive, so this
1570 // restriction only applies to MSVC environments.
1571 if (astContext.getTargetInfo().getTriple().isKnownWindowsMSVCEnvironment() &&
1572 astContext.getTypeAlignIfKnown(vd->getType()) >
1573 astContext.toBits(CharUnits::fromQuantity(32)))
1574 return true;
1575
1576 return false;
1577}
1578
1580 const DeclaratorDecl *dd, GVALinkage linkage, bool isConstantVariable) {
1581 if (linkage == GVA_Internal)
1582 return cir::GlobalLinkageKind::InternalLinkage;
1583
1584 if (dd->hasAttr<WeakAttr>()) {
1585 if (isConstantVariable)
1586 return cir::GlobalLinkageKind::WeakODRLinkage;
1587 return cir::GlobalLinkageKind::WeakAnyLinkage;
1588 }
1589
1590 if (const auto *fd = dd->getAsFunction())
1591 if (fd->isMultiVersion() && linkage == GVA_AvailableExternally)
1592 return cir::GlobalLinkageKind::LinkOnceAnyLinkage;
1593
1594 // We are guaranteed to have a strong definition somewhere else,
1595 // so we can use available_externally linkage.
1596 if (linkage == GVA_AvailableExternally)
1597 return cir::GlobalLinkageKind::AvailableExternallyLinkage;
1598
1599 // Note that Apple's kernel linker doesn't support symbol
1600 // coalescing, so we need to avoid linkonce and weak linkages there.
1601 // Normally, this means we just map to internal, but for explicit
1602 // instantiations we'll map to external.
1603
1604 // In C++, the compiler has to emit a definition in every translation unit
1605 // that references the function. We should use linkonce_odr because
1606 // a) if all references in this translation unit are optimized away, we
1607 // don't need to codegen it. b) if the function persists, it needs to be
1608 // merged with other definitions. c) C++ has the ODR, so we know the
1609 // definition is dependable.
1610 if (linkage == GVA_DiscardableODR)
1611 return !astContext.getLangOpts().AppleKext
1612 ? cir::GlobalLinkageKind::LinkOnceODRLinkage
1613 : cir::GlobalLinkageKind::InternalLinkage;
1614
1615 // An explicit instantiation of a template has weak linkage, since
1616 // explicit instantiations can occur in multiple translation units
1617 // and must all be equivalent. However, we are not allowed to
1618 // throw away these explicit instantiations.
1619 //
1620 // CUDA/HIP: For -fno-gpu-rdc case, device code is limited to one TU,
1621 // so say that CUDA templates are either external (for kernels) or internal.
1622 // This lets llvm perform aggressive inter-procedural optimizations. For
1623 // -fgpu-rdc case, device function calls across multiple TU's are allowed,
1624 // therefore we need to follow the normal linkage paradigm.
1625 if (linkage == GVA_StrongODR) {
1626 if (getLangOpts().AppleKext)
1627 return cir::GlobalLinkageKind::ExternalLinkage;
1628 if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice &&
1629 !getLangOpts().GPURelocatableDeviceCode)
1630 return dd->hasAttr<CUDAGlobalAttr>()
1631 ? cir::GlobalLinkageKind::ExternalLinkage
1632 : cir::GlobalLinkageKind::InternalLinkage;
1633 return cir::GlobalLinkageKind::WeakODRLinkage;
1634 }
1635
1636 // C++ doesn't have tentative definitions and thus cannot have common
1637 // linkage.
1638 if (!getLangOpts().CPlusPlus && isa<VarDecl>(dd) &&
1639 !isVarDeclStrongDefinition(astContext, *this, cast<VarDecl>(dd),
1640 getCodeGenOpts().NoCommon))
1641 return cir::GlobalLinkageKind::CommonLinkage;
1642
1643 // selectany symbols are externally visible, so use weak instead of
1644 // linkonce. MSVC optimizes away references to const selectany globals, so
1645 // all definitions should be the same and ODR linkage should be used.
1646 // http://msdn.microsoft.com/en-us/library/5tkz6s71.aspx
1647 if (dd->hasAttr<SelectAnyAttr>())
1648 return cir::GlobalLinkageKind::WeakODRLinkage;
1649
1650 // Otherwise, we have strong external linkage.
1651 assert(linkage == GVA_StrongExternal);
1652 return cir::GlobalLinkageKind::ExternalLinkage;
1653}
1654
1655/// This function is called when we implement a function with no prototype, e.g.
1656/// "int foo() {}". If there are existing call uses of the old function in the
1657/// module, this adjusts them to call the new function directly.
1658///
1659/// This is not just a cleanup: the always_inline pass requires direct calls to
1660/// functions to be able to inline them. If there is a bitcast in the way, it
1661/// won't inline them. Instcombine normally deletes these calls, but it isn't
1662/// run at -O0.
1664 mlir::Operation *old, cir::FuncOp newFn) {
1665 // If we're redefining a global as a function, don't transform it.
1666 auto oldFn = mlir::dyn_cast<cir::FuncOp>(old);
1667 if (!oldFn)
1668 return;
1669
1670 // TODO(cir): this RAUW ignores the features below.
1674 if (oldFn->getAttrs().size() <= 1)
1675 errorNYI(old->getLoc(),
1676 "replaceUsesOfNonProtoTypeWithRealFunction: Attribute forwarding");
1677
1678 // Mark new function as originated from a no-proto declaration.
1679 newFn.setNoProto(oldFn.getNoProto());
1680
1681 // Iterate through all calls of the no-proto function.
1682 std::optional<mlir::SymbolTable::UseRange> symUses =
1683 oldFn.getSymbolUses(oldFn->getParentOp());
1684 for (const mlir::SymbolTable::SymbolUse &use : symUses.value()) {
1685 mlir::OpBuilder::InsertionGuard guard(builder);
1686
1687 if (auto noProtoCallOp = mlir::dyn_cast<cir::CallOp>(use.getUser())) {
1688 builder.setInsertionPoint(noProtoCallOp);
1689
1690 // Patch call type with the real function type.
1691 cir::CallOp realCallOp = builder.createCallOp(
1692 noProtoCallOp.getLoc(), newFn, noProtoCallOp.getOperands());
1693
1694 // Replace old no proto call with fixed call.
1695 noProtoCallOp.replaceAllUsesWith(realCallOp);
1696 noProtoCallOp.erase();
1697 } else if (auto getGlobalOp =
1698 mlir::dyn_cast<cir::GetGlobalOp>(use.getUser())) {
1699 // Replace type
1700 getGlobalOp.getAddr().setType(
1701 cir::PointerType::get(newFn.getFunctionType()));
1702 } else {
1703 errorNYI(use.getUser()->getLoc(),
1704 "replaceUsesOfNonProtoTypeWithRealFunction: unexpected use");
1705 }
1706 }
1707}
1708
1709cir::GlobalLinkageKind
1711 assert(!isConstant && "constant variables NYI");
1712 GVALinkage linkage = astContext.GetGVALinkageForVariable(vd);
1713 return getCIRLinkageForDeclarator(vd, linkage, isConstant);
1714}
1715
1717 const auto *d = cast<FunctionDecl>(gd.getDecl());
1718
1719 GVALinkage linkage = astContext.GetGVALinkageForFunction(d);
1720
1721 if (const auto *dtor = dyn_cast<CXXDestructorDecl>(d))
1722 return getCXXABI().getCXXDestructorLinkage(linkage, dtor, gd.getDtorType());
1723
1724 return getCIRLinkageForDeclarator(d, linkage, /*isConstantVariable=*/false);
1725}
1726
1727static cir::GlobalOp
1728generateStringLiteral(mlir::Location loc, mlir::TypedAttr c,
1729 cir::GlobalLinkageKind lt, CIRGenModule &cgm,
1730 StringRef globalName, CharUnits alignment) {
1732
1733 // Create a global variable for this string
1734 // FIXME(cir): check for insertion point in module level.
1735 cir::GlobalOp gv = CIRGenModule::createGlobalOp(
1736 cgm, loc, globalName, c.getType(), !cgm.getLangOpts().WritableStrings);
1737
1738 // Set up extra information and add to the module
1739 gv.setAlignmentAttr(cgm.getSize(alignment));
1740 gv.setLinkageAttr(
1741 cir::GlobalLinkageKindAttr::get(cgm.getBuilder().getContext(), lt));
1745 if (gv.isWeakForLinker()) {
1746 assert(cgm.supportsCOMDAT() && "Only COFF uses weak string literals");
1747 gv.setComdat(true);
1748 }
1749 cgm.setDSOLocal(static_cast<mlir::Operation *>(gv));
1750 return gv;
1751}
1752
1753// LLVM IR automatically uniques names when new llvm::GlobalVariables are
1754// created. This is handy, for example, when creating globals for string
1755// literals. Since we don't do that when creating cir::GlobalOp's, we need
1756// a mechanism to generate a unique name in advance.
1757//
1758// For now, this mechanism is only used in cases where we know that the
1759// name is compiler-generated, so we don't use the MLIR symbol table for
1760// the lookup.
1761std::string CIRGenModule::getUniqueGlobalName(const std::string &baseName) {
1762 // If this is the first time we've generated a name for this basename, use
1763 // it as is and start a counter for this base name.
1764 auto it = cgGlobalNames.find(baseName);
1765 if (it == cgGlobalNames.end()) {
1766 cgGlobalNames[baseName] = 1;
1767 return baseName;
1768 }
1769
1770 std::string result =
1771 baseName + "." + std::to_string(cgGlobalNames[baseName]++);
1772 // There should not be any symbol with this name in the module.
1773 assert(!mlir::SymbolTable::lookupSymbolIn(theModule, result));
1774 return result;
1775}
1776
1777/// Return a pointer to a constant array for the given string literal.
1779 StringRef name) {
1780 CharUnits alignment =
1781 astContext.getAlignOfGlobalVarInChars(s->getType(), /*VD=*/nullptr);
1782
1783 mlir::Attribute c = getConstantArrayFromStringLiteral(s);
1784
1785 cir::GlobalOp gv;
1786 if (!getLangOpts().WritableStrings && constantStringMap.count(c)) {
1787 gv = constantStringMap[c];
1788 // The bigger alignment always wins.
1789 if (!gv.getAlignment() ||
1790 uint64_t(alignment.getQuantity()) > *gv.getAlignment())
1791 gv.setAlignmentAttr(getSize(alignment));
1792 } else {
1793 // Mangle the string literal if that's how the ABI merges duplicate strings.
1794 // Don't do it if they are writable, since we don't want writes in one TU to
1795 // affect strings in another.
1796 if (getCXXABI().getMangleContext().shouldMangleStringLiteral(s) &&
1797 !getLangOpts().WritableStrings) {
1798 errorNYI(s->getSourceRange(),
1799 "getGlobalForStringLiteral: mangle string literals");
1800 }
1801
1802 // Unlike LLVM IR, CIR doesn't automatically unique names for globals, so
1803 // we need to do that explicitly.
1804 std::string uniqueName = getUniqueGlobalName(name.str());
1805 // Synthetic string literals (e.g., from SourceLocExpr) may not have valid
1806 // source locations. Use unknown location in those cases.
1807 mlir::Location loc = s->getBeginLoc().isValid()
1808 ? getLoc(s->getSourceRange())
1809 : builder.getUnknownLoc();
1810 auto typedC = llvm::cast<mlir::TypedAttr>(c);
1811 gv = generateStringLiteral(loc, typedC,
1812 cir::GlobalLinkageKind::PrivateLinkage, *this,
1813 uniqueName, alignment);
1814 setDSOLocal(static_cast<mlir::Operation *>(gv));
1815 constantStringMap[c] = gv;
1816
1818 }
1819 return gv;
1820}
1821
1822/// Return a pointer to a constant array for the given string literal.
1823cir::GlobalViewAttr
1825 StringRef name) {
1826 cir::GlobalOp gv = getGlobalForStringLiteral(s, name);
1827 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(gv.getSymType());
1828 assert(arrayTy && "String literal must be array");
1830 cir::PointerType ptrTy = getBuilder().getPointerTo(arrayTy.getElementType());
1831
1832 return builder.getGlobalViewAttr(ptrTy, gv);
1833}
1834
1835// TODO(cir): this could be a common AST helper for both CIR and LLVM codegen.
1837 if (getLangOpts().OpenCL)
1839
1840 // For temporaries inside functions, CUDA treats them as normal variables.
1841 // LangAS::cuda_device, on the other hand, is reserved for those variables
1842 // explicitly marked with __device__.
1843 if (getLangOpts().CUDAIsDevice)
1844 return LangAS::Default;
1845
1846 if (getLangOpts().SYCLIsDevice ||
1847 (getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice))
1848 errorNYI("SYCL or OpenMP temp address space");
1849 return LangAS::Default;
1850}
1851
1853 CIRGenFunction *cgf) {
1854 if (cgf && e->getType()->isVariablyModifiedType())
1856
1858 "emitExplicitCastExprType");
1859}
1860
1862 const MemberPointerType *mpt) {
1863 if (mpt->isMemberFunctionPointerType()) {
1864 auto ty = mlir::cast<cir::MethodType>(convertType(destTy));
1865 return builder.getNullMethodAttr(ty);
1866 }
1867
1868 auto ty = mlir::cast<cir::DataMemberType>(convertType(destTy));
1869 return builder.getNullDataMemberAttr(ty);
1870}
1871
1874
1875 mlir::Location loc = getLoc(e->getSourceRange());
1876
1877 const auto *decl = cast<DeclRefExpr>(e->getSubExpr())->getDecl();
1878
1879 // A member function pointer.
1880 if (const auto *methodDecl = dyn_cast<CXXMethodDecl>(decl)) {
1881 auto ty = mlir::cast<cir::MethodType>(convertType(e->getType()));
1882 if (methodDecl->isVirtual())
1883 return cir::ConstantOp::create(
1884 builder, loc, getCXXABI().buildVirtualMethodAttr(ty, methodDecl));
1885
1886 cir::FuncOp methodFuncOp = getAddrOfFunction(methodDecl);
1887 return cir::ConstantOp::create(builder, loc,
1888 builder.getMethodAttr(ty, methodFuncOp));
1889 }
1890
1891 // Otherwise, a member data pointer.
1892 auto ty = mlir::cast<cir::DataMemberType>(convertType(e->getType()));
1893 const auto *fieldDecl = cast<FieldDecl>(decl);
1894 return cir::ConstantOp::create(
1895 builder, loc, builder.getDataMemberAttr(ty, fieldDecl->getFieldIndex()));
1896}
1897
1899 for (Decl *decl : dc->decls()) {
1900 // Unlike other DeclContexts, the contents of an ObjCImplDecl at TU scope
1901 // are themselves considered "top-level", so EmitTopLevelDecl on an
1902 // ObjCImplDecl does not recursively visit them. We need to do that in
1903 // case they're nested inside another construct (LinkageSpecDecl /
1904 // ExportDecl) that does stop them from being considered "top-level".
1905 if (auto *oid = dyn_cast<ObjCImplDecl>(decl))
1906 errorNYI(oid->getSourceRange(), "emitDeclConext: ObjCImplDecl");
1907
1909 }
1910}
1911
1912// Emit code for a single top level declaration.
1914
1915 // Ignore dependent declarations.
1916 if (decl->isTemplated())
1917 return;
1918
1919 switch (decl->getKind()) {
1920 default:
1921 errorNYI(decl->getBeginLoc(), "declaration of kind",
1922 decl->getDeclKindName());
1923 break;
1924
1925 case Decl::CXXConversion:
1926 case Decl::CXXMethod:
1927 case Decl::Function: {
1928 auto *fd = cast<FunctionDecl>(decl);
1929 // Consteval functions shouldn't be emitted.
1930 if (!fd->isConsteval())
1931 emitGlobal(fd);
1932 break;
1933 }
1934
1935 case Decl::Var:
1936 case Decl::Decomposition:
1937 case Decl::VarTemplateSpecialization: {
1938 auto *vd = cast<VarDecl>(decl);
1940 errorNYI(decl->getSourceRange(), "global variable decompositions");
1941 break;
1942 }
1943 emitGlobal(vd);
1944 break;
1945 }
1946 case Decl::OpenACCRoutine:
1948 break;
1949 case Decl::OpenACCDeclare:
1951 break;
1952 case Decl::OMPThreadPrivate:
1954 break;
1955 case Decl::OMPGroupPrivate:
1957 break;
1958 case Decl::OMPAllocate:
1960 break;
1961 case Decl::OMPCapturedExpr:
1963 break;
1964 case Decl::OMPDeclareReduction:
1966 break;
1967 case Decl::OMPDeclareMapper:
1969 break;
1970 case Decl::OMPRequires:
1972 break;
1973 case Decl::Enum:
1974 case Decl::Using: // using X; [C++]
1975 case Decl::UsingDirective: // using namespace X; [C++]
1976 case Decl::UsingEnum: // using enum X; [C++]
1977 case Decl::NamespaceAlias:
1978 case Decl::Typedef:
1979 case Decl::TypeAlias: // using foo = bar; [C++11]
1980 case Decl::Record:
1982 break;
1983
1984 // No code generation needed.
1985 case Decl::ClassTemplate:
1986 case Decl::Concept:
1987 case Decl::CXXDeductionGuide:
1988 case Decl::Empty:
1989 case Decl::FunctionTemplate:
1990 case Decl::StaticAssert:
1991 case Decl::TypeAliasTemplate:
1992 case Decl::UsingShadow:
1993 case Decl::VarTemplate:
1994 case Decl::VarTemplatePartialSpecialization:
1995 break;
1996
1997 case Decl::CXXConstructor:
1999 break;
2000 case Decl::CXXDestructor:
2002 break;
2003
2004 // C++ Decls
2005 case Decl::LinkageSpec:
2006 case Decl::Namespace:
2008 break;
2009
2010 case Decl::ClassTemplateSpecialization:
2011 case Decl::CXXRecord: {
2014 for (auto *childDecl : crd->decls())
2016 emitTopLevelDecl(childDecl);
2017 break;
2018 }
2019
2020 case Decl::FileScopeAsm:
2021 // File-scope asm is ignored during device-side CUDA compilation.
2022 if (langOpts.CUDA && langOpts.CUDAIsDevice)
2023 break;
2024 // File-scope asm is ignored during device-side OpenMP compilation.
2025 if (langOpts.OpenMPIsTargetDevice)
2026 break;
2027 // File-scope asm is ignored during device-side SYCL compilation.
2028 if (langOpts.SYCLIsDevice)
2029 break;
2030 auto *file_asm = cast<FileScopeAsmDecl>(decl);
2031 std::string line = file_asm->getAsmString();
2032 globalScopeAsm.push_back(builder.getStringAttr(line));
2033 break;
2034 }
2035}
2036
2037void CIRGenModule::setInitializer(cir::GlobalOp &op, mlir::Attribute value) {
2038 // Recompute visibility when updating initializer.
2039 op.setInitialValueAttr(value);
2041}
2042
2043std::pair<cir::FuncType, cir::FuncOp> CIRGenModule::getAddrAndTypeOfCXXStructor(
2044 GlobalDecl gd, const CIRGenFunctionInfo *fnInfo, cir::FuncType fnType,
2045 bool dontDefer, ForDefinition_t isForDefinition) {
2046 auto *md = cast<CXXMethodDecl>(gd.getDecl());
2047
2048 if (isa<CXXDestructorDecl>(md)) {
2049 // Always alias equivalent complete destructors to base destructors in the
2050 // MS ABI.
2051 if (getTarget().getCXXABI().isMicrosoft() &&
2052 gd.getDtorType() == Dtor_Complete &&
2053 md->getParent()->getNumVBases() == 0)
2054 errorNYI(md->getSourceRange(),
2055 "getAddrAndTypeOfCXXStructor: MS ABI complete destructor");
2056 }
2057
2058 if (!fnType) {
2059 if (!fnInfo)
2061 fnType = getTypes().getFunctionType(*fnInfo);
2062 }
2063
2064 auto fn = getOrCreateCIRFunction(getMangledName(gd), fnType, gd,
2065 /*ForVtable=*/false, dontDefer,
2066 /*IsThunk=*/false, isForDefinition);
2067
2068 return {fnType, fn};
2069}
2070
2072 mlir::Type funcType, bool forVTable,
2073 bool dontDefer,
2074 ForDefinition_t isForDefinition) {
2075 assert(!cast<FunctionDecl>(gd.getDecl())->isConsteval() &&
2076 "consteval function should never be emitted");
2077
2078 if (!funcType) {
2079 const auto *fd = cast<FunctionDecl>(gd.getDecl());
2080 funcType = convertType(fd->getType());
2081 }
2082
2083 // Devirtualized destructor calls may come through here instead of via
2084 // getAddrOfCXXStructor. Make sure we use the MS ABI base destructor instead
2085 // of the complete destructor when necessary.
2086 if (const auto *dd = dyn_cast<CXXDestructorDecl>(gd.getDecl())) {
2087 if (getTarget().getCXXABI().isMicrosoft() &&
2088 gd.getDtorType() == Dtor_Complete &&
2089 dd->getParent()->getNumVBases() == 0)
2090 errorNYI(dd->getSourceRange(),
2091 "getAddrOfFunction: MS ABI complete destructor");
2092 }
2093
2094 StringRef mangledName = getMangledName(gd);
2095 cir::FuncOp func =
2096 getOrCreateCIRFunction(mangledName, funcType, gd, forVTable, dontDefer,
2097 /*isThunk=*/false, isForDefinition);
2098 // Returns kernel handle for HIP kernel stub function.
2099 if (langOpts.CUDA && !langOpts.CUDAIsDevice &&
2100 cast<FunctionDecl>(gd.getDecl())->hasAttr<CUDAGlobalAttr>()) {
2101 mlir::Operation *handle = getCUDARuntime().getKernelHandle(func, gd);
2102
2103 // For HIP the kernel handle is a GlobalOp, which cannot be cast to
2104 // FuncOp. Return the stub directly in that case.
2105 bool isHIPHandle = mlir::isa<cir::GlobalOp>(*handle);
2106 if (isForDefinition || isHIPHandle)
2107 return func;
2108 return mlir::dyn_cast<cir::FuncOp>(*handle);
2109 }
2110 return func;
2111}
2112
2113static std::string getMangledNameImpl(CIRGenModule &cgm, GlobalDecl gd,
2114 const NamedDecl *nd) {
2115 SmallString<256> buffer;
2116
2117 llvm::raw_svector_ostream out(buffer);
2119
2121
2122 if (mc.shouldMangleDeclName(nd)) {
2123 mc.mangleName(gd.getWithDecl(nd), out);
2124 } else {
2125 IdentifierInfo *ii = nd->getIdentifier();
2126 assert(ii && "Attempt to mangle unnamed decl.");
2127
2128 const auto *fd = dyn_cast<FunctionDecl>(nd);
2129 if (fd &&
2130 fd->getType()->castAs<FunctionType>()->getCallConv() == CC_X86RegCall) {
2131 cgm.errorNYI(nd->getSourceRange(), "getMangledName: X86RegCall");
2132 } else if (fd && fd->hasAttr<CUDAGlobalAttr>() &&
2134 out << "__device_stub__" << ii->getName();
2135 } else if (fd &&
2136 DeviceKernelAttr::isOpenCLSpelling(
2137 fd->getAttr<DeviceKernelAttr>()) &&
2139 cgm.errorNYI(nd->getSourceRange(), "getMangledName: OpenCL Stub");
2140 } else {
2141 out << ii->getName();
2142 }
2143 }
2144
2145 // Check if the module name hash should be appended for internal linkage
2146 // symbols. This should come before multi-version target suffixes are
2147 // appendded. This is to keep the name and module hash suffix of the internal
2148 // linkage function together. The unique suffix should only be added when name
2149 // mangling is done to make sure that the final name can be properly
2150 // demangled. For example, for C functions without prototypes, name mangling
2151 // is not done and the unique suffix should not be appended then.
2153
2154 if (const auto *fd = dyn_cast<FunctionDecl>(nd)) {
2155 if (fd->isMultiVersion()) {
2156 cgm.errorNYI(nd->getSourceRange(),
2157 "getMangledName: multi-version functions");
2158 }
2159 }
2160 if (cgm.getLangOpts().GPURelocatableDeviceCode) {
2161 cgm.errorNYI(nd->getSourceRange(),
2162 "getMangledName: GPU relocatable device code");
2163 }
2164
2165 return std::string(out.str());
2166}
2167
2168static FunctionDecl *
2170 const FunctionDecl *protoFunc) {
2171 // If this is a C no-prototype function, we can take the 'easy' way out and
2172 // just create a function with no arguments/functions, etc.
2173 if (!protoFunc->hasPrototype())
2174 return FunctionDecl::Create(
2175 ctx, /*DC=*/ctx.getTranslationUnitDecl(),
2176 /*StartLoc=*/SourceLocation{}, /*NLoc=*/SourceLocation{}, bindName,
2177 protoFunc->getType(), /*TInfo=*/nullptr, StorageClass::SC_None);
2178
2179 QualType funcTy = protoFunc->getType();
2180 auto *fpt = cast<FunctionProtoType>(protoFunc->getType());
2181
2182 // If this is a member function, add an explicit 'this' to the function type.
2183 if (auto *methodDecl = dyn_cast<CXXMethodDecl>(protoFunc);
2184 methodDecl && methodDecl->isImplicitObjectMemberFunction()) {
2185 llvm::SmallVector<QualType> paramTypes{fpt->getParamTypes()};
2186 paramTypes.insert(paramTypes.begin(), methodDecl->getThisType());
2187
2188 funcTy = ctx.getFunctionType(fpt->getReturnType(), paramTypes,
2189 fpt->getExtProtoInfo());
2190 fpt = cast<FunctionProtoType>(funcTy);
2191 }
2192
2193 auto *tempFunc =
2195 /*StartLoc=*/SourceLocation{},
2196 /*NLoc=*/SourceLocation{}, bindName, funcTy,
2197 /*TInfo=*/nullptr, StorageClass::SC_None);
2198
2200 params.reserve(fpt->getNumParams());
2201
2202 // Add all of the parameters.
2203 for (unsigned i = 0, e = fpt->getNumParams(); i != e; ++i) {
2205 ctx, tempFunc, /*StartLoc=*/SourceLocation{},
2206 /*IdLoc=*/SourceLocation{},
2207 /*Id=*/nullptr, fpt->getParamType(i), /*TInfo=*/nullptr,
2208 StorageClass::SC_None, /*DefArg=*/nullptr);
2209 parm->setScopeInfo(0, i);
2210 params.push_back(parm);
2211 }
2212
2213 tempFunc->setParams(params);
2214
2215 return tempFunc;
2216}
2217
2218std::string
2220 const FunctionDecl *attachedFunction) {
2222 getASTContext(), bindName, attachedFunction);
2223
2224 std::string ret = getMangledNameImpl(*this, GlobalDecl(tempFunc), tempFunc);
2225
2226 // This does nothing (it is a do-nothing function), since this is a
2227 // slab-allocator, but leave a call in to immediately destroy this in case we
2228 // ever come up with a way of getting allocations back.
2229 getASTContext().Deallocate(tempFunc);
2230 return ret;
2231}
2232
2234 GlobalDecl canonicalGd = gd.getCanonicalDecl();
2235
2236 // Some ABIs don't have constructor variants. Make sure that base and complete
2237 // constructors get mangled the same.
2238 if (const auto *cd = dyn_cast<CXXConstructorDecl>(canonicalGd.getDecl())) {
2239 if (!getTarget().getCXXABI().hasConstructorVariants()) {
2240 errorNYI(cd->getSourceRange(),
2241 "getMangledName: C++ constructor without variants");
2242 return cast<NamedDecl>(gd.getDecl())->getIdentifier()->getName();
2243 }
2244 }
2245
2246 // Keep the first result in the case of a mangling collision.
2247 const auto *nd = cast<NamedDecl>(gd.getDecl());
2248 std::string mangledName = getMangledNameImpl(*this, gd, nd);
2249
2250 auto result = manglings.insert(std::make_pair(mangledName, gd));
2251 return mangledDeclNames[canonicalGd] = result.first->first();
2252}
2253
2255 assert(!d->getInit() && "Cannot emit definite definitions here!");
2256
2257 StringRef mangledName = getMangledName(d);
2258 mlir::Operation *gv = getGlobalValue(mangledName);
2259
2260 // If we already have a definition, not declaration, with the same mangled
2261 // name, emitting of declaration is not required (and would actually overwrite
2262 // the emitted definition).
2263 if (gv && !mlir::cast<cir::GlobalOp>(gv).isDeclaration())
2264 return;
2265
2266 // If we have not seen a reference to this variable yet, place it into the
2267 // deferred declarations table to be emitted if needed later.
2268 if (!mustBeEmitted(d) && !gv) {
2269 deferredDecls[mangledName] = d;
2270 return;
2271 }
2272
2273 // The tentative definition is the only definition.
2275}
2276
2278 // Never defer when EmitAllDecls is specified.
2279 if (langOpts.EmitAllDecls)
2280 return true;
2281
2282 const auto *vd = dyn_cast<VarDecl>(global);
2283 if (vd &&
2284 ((codeGenOpts.KeepPersistentStorageVariables &&
2285 (vd->getStorageDuration() == SD_Static ||
2286 vd->getStorageDuration() == SD_Thread)) ||
2287 (codeGenOpts.KeepStaticConsts && vd->getStorageDuration() == SD_Static &&
2288 vd->getType().isConstQualified())))
2289 return true;
2290
2291 return getASTContext().DeclMustBeEmitted(global);
2292}
2293
2295 // In OpenMP 5.0 variables and function may be marked as
2296 // device_type(host/nohost) and we should not emit them eagerly unless we sure
2297 // that they must be emitted on the host/device. To be sure we need to have
2298 // seen a declare target with an explicit mentioning of the function, we know
2299 // we have if the level of the declare target attribute is -1. Note that we
2300 // check somewhere else if we should emit this at all.
2301 if (langOpts.OpenMP >= 50 && !langOpts.OpenMPSimd) {
2302 std::optional<OMPDeclareTargetDeclAttr *> activeAttr =
2303 OMPDeclareTargetDeclAttr::getActiveAttr(global);
2304 if (!activeAttr || (*activeAttr)->getLevel() != (unsigned)-1)
2305 return false;
2306 }
2307
2308 const auto *fd = dyn_cast<FunctionDecl>(global);
2309 if (fd) {
2310 // Implicit template instantiations may change linkage if they are later
2311 // explicitly instantiated, so they should not be emitted eagerly.
2312 if (fd->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
2313 return false;
2314 // Defer until all versions have been semantically checked.
2315 if (fd->hasAttr<TargetVersionAttr>() && !fd->isMultiVersion())
2316 return false;
2317 if (langOpts.SYCLIsDevice) {
2318 errorNYI(fd->getSourceRange(), "mayBeEmittedEagerly: SYCL");
2319 return false;
2320 }
2321 }
2322 const auto *vd = dyn_cast<VarDecl>(global);
2323 if (vd)
2324 if (astContext.getInlineVariableDefinitionKind(vd) ==
2326 // A definition of an inline constexpr static data member may change
2327 // linkage later if it's redeclared outside the class.
2328 return false;
2329
2330 // If OpenMP is enabled and threadprivates must be generated like TLS, delay
2331 // codegen for global variables, because they may be marked as threadprivate.
2332 if (langOpts.OpenMP && langOpts.OpenMPUseTLS &&
2333 astContext.getTargetInfo().isTLSSupported() && isa<VarDecl>(global) &&
2334 !global->getType().isConstantStorage(astContext, false, false) &&
2335 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(global))
2336 return false;
2337
2338 assert((fd || vd) &&
2339 "Only FunctionDecl and VarDecl should hit this path so far.");
2340 return true;
2341}
2342
2343static bool shouldAssumeDSOLocal(const CIRGenModule &cgm,
2344 cir::CIRGlobalValueInterface gv) {
2345 if (gv.hasLocalLinkage())
2346 return true;
2347
2348 if (!gv.hasDefaultVisibility() && !gv.hasExternalWeakLinkage())
2349 return true;
2350
2351 // DLLImport explicitly marks the GV as external.
2352 // so it shouldn't be dso_local
2353 // But we don't have the info set now
2355
2356 const llvm::Triple &tt = cgm.getTriple();
2357 const CodeGenOptions &cgOpts = cgm.getCodeGenOpts();
2358 if (tt.isOSCygMing()) {
2359 // In MinGW and Cygwin, variables without DLLImport can still be
2360 // automatically imported from a DLL by the linker; don't mark variables
2361 // that potentially could come from another DLL as DSO local.
2362
2363 // With EmulatedTLS, TLS variables can be autoimported from other DLLs
2364 // (and this actually happens in the public interface of libstdc++), so
2365 // such variables can't be marked as DSO local. (Native TLS variables
2366 // can't be dllimported at all, though.)
2367 cgm.errorNYI("shouldAssumeDSOLocal: MinGW");
2368 }
2369
2370 // On COFF, don't mark 'extern_weak' symbols as DSO local. If these symbols
2371 // remain unresolved in the link, they can be resolved to zero, which is
2372 // outside the current DSO.
2373 if (tt.isOSBinFormatCOFF() && gv.hasExternalWeakLinkage())
2374 return false;
2375
2376 // Every other GV is local on COFF.
2377 // Make an exception for windows OS in the triple: Some firmware builds use
2378 // *-win32-macho triples. This (accidentally?) produced windows relocations
2379 // without GOT tables in older clang versions; Keep this behaviour.
2380 // FIXME: even thread local variables?
2381 if (tt.isOSBinFormatCOFF() || (tt.isOSWindows() && tt.isOSBinFormatMachO()))
2382 return true;
2383
2384 // Only handle COFF and ELF for now.
2385 if (!tt.isOSBinFormatELF())
2386 return false;
2387
2388 llvm::Reloc::Model rm = cgOpts.RelocationModel;
2389 const LangOptions &lOpts = cgm.getLangOpts();
2390 if (rm != llvm::Reloc::Static && !lOpts.PIE) {
2391 // On ELF, if -fno-semantic-interposition is specified and the target
2392 // supports local aliases, there will be neither CC1
2393 // -fsemantic-interposition nor -fhalf-no-semantic-interposition. Set
2394 // dso_local on the function if using a local alias is preferable (can avoid
2395 // PLT indirection).
2396 if (!(isa<cir::FuncOp>(gv) && gv.canBenefitFromLocalAlias()))
2397 return false;
2398 return !(lOpts.SemanticInterposition || lOpts.HalfNoSemanticInterposition);
2399 }
2400
2401 // A definition cannot be preempted from an executable.
2402 if (!gv.isDeclarationForLinker())
2403 return true;
2404
2405 // Most PIC code sequences that assume that a symbol is local cannot produce a
2406 // 0 if it turns out the symbol is undefined. While this is ABI and relocation
2407 // depended, it seems worth it to handle it here.
2408 if (rm == llvm::Reloc::PIC_ && gv.hasExternalWeakLinkage())
2409 return false;
2410
2411 // PowerPC64 prefers TOC indirection to avoid copy relocations.
2412 if (tt.isPPC64())
2413 return false;
2414
2415 if (cgOpts.DirectAccessExternalData) {
2416 // If -fdirect-access-external-data (default for -fno-pic), set dso_local
2417 // for non-thread-local variables. If the symbol is not defined in the
2418 // executable, a copy relocation will be needed at link time. dso_local is
2419 // excluded for thread-local variables because they generally don't support
2420 // copy relocations.
2421 if (auto globalOp = dyn_cast<cir::GlobalOp>(gv.getOperation())) {
2422 // Assume variables are not thread-local until that support is added.
2424 return true;
2425 }
2426
2427 // -fno-pic sets dso_local on a function declaration to allow direct
2428 // accesses when taking its address (similar to a data symbol). If the
2429 // function is not defined in the executable, a canonical PLT entry will be
2430 // needed at link time. -fno-direct-access-external-data can avoid the
2431 // canonical PLT entry. We don't generalize this condition to -fpie/-fpic as
2432 // it could just cause trouble without providing perceptible benefits.
2433 if (isa<cir::FuncOp>(gv) && !cgOpts.NoPLT && rm == llvm::Reloc::Static)
2434 return true;
2435 }
2436
2437 // If we can use copy relocations we can assume it is local.
2438
2439 // Otherwise don't assume it is local.
2440
2441 return false;
2442}
2443
2444void CIRGenModule::setGlobalVisibility(mlir::Operation *gv,
2445 const NamedDecl *d) const {
2447}
2448
2449void CIRGenModule::setDSOLocal(cir::CIRGlobalValueInterface gv) const {
2450 gv.setDSOLocal(shouldAssumeDSOLocal(*this, gv));
2451}
2452
2453void CIRGenModule::setDSOLocal(mlir::Operation *op) const {
2454 if (auto globalValue = dyn_cast<cir::CIRGlobalValueInterface>(op))
2455 setDSOLocal(globalValue);
2456}
2457
2458void CIRGenModule::setGVProperties(mlir::Operation *op,
2459 const NamedDecl *d) const {
2461 setGVPropertiesAux(op, d);
2462}
2463
2464void CIRGenModule::setGVPropertiesAux(mlir::Operation *op,
2465 const NamedDecl *d) const {
2466 setGlobalVisibility(op, d);
2467 setDSOLocal(op);
2469}
2470
2472 GlobalDecl &result) const {
2473 auto res = manglings.find(mangledName);
2474 if (res == manglings.end())
2475 return false;
2476 result = res->getValue();
2477 return true;
2478}
2479
2481 switch (getCodeGenOpts().getDefaultTLSModel()) {
2483 return cir::TLS_Model::GeneralDynamic;
2485 return cir::TLS_Model::LocalDynamic;
2487 return cir::TLS_Model::InitialExec;
2489 return cir::TLS_Model::LocalExec;
2490 }
2491 llvm_unreachable("Invalid TLS model!");
2492}
2493
2494void CIRGenModule::setTLSMode(mlir::Operation *op, const VarDecl &d) {
2495 assert(d.getTLSKind() && "setting TLS mode on non-TLS var!");
2496
2497 cir::TLS_Model tlm = getDefaultCIRTLSModel();
2498
2499 // Override the TLS model if it is explicitly specified.
2500 if (d.getAttr<TLSModelAttr>())
2501 errorNYI(d.getSourceRange(), "TLS model attribute");
2502
2503 auto global = cast<cir::GlobalOp>(op);
2504 global.setTlsModel(tlm);
2505}
2506
2508 const CIRGenFunctionInfo &info,
2509 cir::FuncOp func, bool isThunk) {
2510 // TODO(cir): More logic of constructAttributeList is needed.
2511 cir::CallingConv callingConv;
2512 cir::SideEffect sideEffect;
2513
2514 // TODO(cir): The current list should be initialized with the extra function
2515 // attributes, but we don't have those yet. For now, the PAL is initialized
2516 // with nothing.
2518 // Initialize PAL with existing attributes to merge attributes.
2519 mlir::NamedAttrList pal{};
2520 std::vector<mlir::NamedAttrList> argAttrs(info.arguments().size());
2521 mlir::NamedAttrList retAttrs{};
2522 constructAttributeList(func.getName(), info, globalDecl, pal, argAttrs,
2523 retAttrs, callingConv, sideEffect,
2524 /*attrOnCallSite=*/false, isThunk);
2525
2526 for (mlir::NamedAttribute attr : pal)
2527 func->setAttr(attr.getName(), attr.getValue());
2528
2529 llvm::for_each(llvm::enumerate(argAttrs), [func](auto idx_arg_pair) {
2530 mlir::function_interface_impl::setArgAttrs(func, idx_arg_pair.index(),
2531 idx_arg_pair.value());
2532 });
2533 if (!retAttrs.empty())
2534 mlir::function_interface_impl::setResultAttrs(func, 0, retAttrs);
2535
2536 // TODO(cir): Check X86_VectorCall incompatibility wiht WinARM64EC
2537
2538 // TODO(cir): typically the calling conv is set right here, but since
2539 // cir::CallingConv is empty and we've not yet added calling-conv to FuncOop,
2540 // this isn't really useful here. This should call func.setCallingConv/etc
2541 // later.
2543}
2544
2546 cir::FuncOp func,
2547 bool isIncompleteFunction,
2548 bool isThunk) {
2549 // NOTE(cir): Original CodeGen checks if this is an intrinsic. In CIR we
2550 // represent them in dedicated ops. The correct attributes are ensured during
2551 // translation to LLVM. Thus, we don't need to check for them here.
2552
2553 if (!isIncompleteFunction)
2554 setCIRFunctionAttributes(globalDecl,
2555 getTypes().arrangeGlobalDeclaration(globalDecl),
2556 func, isThunk);
2557
2559
2560 // TODO(cir): This needs a lot of work to better match CodeGen. That
2561 // ultimately ends up in setGlobalVisibility, which already has the linkage of
2562 // the LLVM GV (corresponding to our FuncOp) computed, so it doesn't have to
2563 // recompute it here. This is a minimal fix for now.
2564 if (!isLocalLinkage(getFunctionLinkage(globalDecl))) {
2565 const Decl *decl = globalDecl.getDecl();
2566 func.setGlobalVisibilityAttr(getGlobalVisibilityAttrFromDecl(decl));
2567 }
2568
2569 // If we plan on emitting this inline builtin, we can't treat it as a builtin.
2570 const auto *fd = cast<FunctionDecl>(globalDecl.getDecl());
2571 if (fd->isInlineBuiltinDeclaration()) {
2572 const FunctionDecl *fdBody;
2573 bool hasBody = fd->hasBody(fdBody);
2574 (void)hasBody;
2575 assert(hasBody && "Inline builtin declarations should always have an "
2576 "available body!");
2578 }
2579
2580 if (fd->isReplaceableGlobalAllocationFunction()) {
2581 // A replaceable global allocation function does not act like a builtin by
2582 // default, only if it is invoked by a new-expression or delete-expression.
2583 func->setAttr(cir::CIRDialect::getNoBuiltinAttrName(),
2584 mlir::UnitAttr::get(&getMLIRContext()));
2585 }
2586}
2587
2588/// Determines whether the language options require us to model
2589/// unwind exceptions. We treat -fexceptions as mandating this
2590/// except under the fragile ObjC ABI with only ObjC exceptions
2591/// enabled. This means, for example, that C with -fexceptions
2592/// enables this.
2593static bool hasUnwindExceptions(const LangOptions &langOpts) {
2594 // If exceptions are completely disabled, obviously this is false.
2595 if (!langOpts.Exceptions)
2596 return false;
2597 // If C++ exceptions are enabled, this is true.
2598 if (langOpts.CXXExceptions)
2599 return true;
2600 // If ObjC exceptions are enabled, this depends on the ABI.
2601 if (langOpts.ObjCExceptions)
2602 return langOpts.ObjCRuntime.hasUnwindExceptions();
2603 return true;
2604}
2605
2607 const clang::FunctionDecl *decl, cir::FuncOp f) {
2610
2611 if (!hasUnwindExceptions(langOpts))
2612 f->setAttr(cir::CIRDialect::getNoThrowAttrName(),
2613 mlir::UnitAttr::get(&getMLIRContext()));
2614
2615 std::optional<cir::InlineKind> existingInlineKind = f.getInlineKind();
2616 bool isNoInline =
2617 existingInlineKind && *existingInlineKind == cir::InlineKind::NoInline;
2618 bool isAlwaysInline = existingInlineKind &&
2619 *existingInlineKind == cir::InlineKind::AlwaysInline;
2620 if (!decl) {
2621 assert(!cir::MissingFeatures::hlsl());
2622
2623 if (!isAlwaysInline &&
2624 codeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) {
2625 // If inlining is disabled and we don't have a declaration to control
2626 // inlining, mark the function as 'noinline' unless it is explicitly
2627 // marked as 'alwaysinline'.
2628 f.setInlineKind(cir::InlineKind::NoInline);
2629 }
2630
2631 return;
2632 }
2633
2640 assert(!cir::MissingFeatures::hlsl());
2641
2642 // Handle inline attributes
2643 if (decl->hasAttr<NoInlineAttr>() && !isAlwaysInline) {
2644 // Add noinline if the function isn't always_inline.
2645 f.setInlineKind(cir::InlineKind::NoInline);
2646 } else if (decl->hasAttr<AlwaysInlineAttr>() && !isNoInline) {
2647 // Don't override AlwaysInline with NoInline, or vice versa, since we can't
2648 // specify both in IR.
2649 f.setInlineKind(cir::InlineKind::AlwaysInline);
2650 } else if (codeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) {
2651 // If inlining is disabled, force everything that isn't always_inline
2652 // to carry an explicit noinline attribute.
2653 if (!isAlwaysInline)
2654 f.setInlineKind(cir::InlineKind::NoInline);
2655 } else {
2656 // Otherwise, propagate the inline hint attribute and potentially use its
2657 // absence to mark things as noinline.
2658 // Search function and template pattern redeclarations for inline.
2659 if (auto *fd = dyn_cast<FunctionDecl>(decl)) {
2660 // TODO: Share this checkForInline implementation with classic codegen.
2661 // This logic is likely to change over time, so sharing would help ensure
2662 // consistency.
2663 auto checkForInline = [](const FunctionDecl *decl) {
2664 auto checkRedeclForInline = [](const FunctionDecl *redecl) {
2665 return redecl->isInlineSpecified();
2666 };
2667 if (any_of(decl->redecls(), checkRedeclForInline))
2668 return true;
2669 const FunctionDecl *pattern = decl->getTemplateInstantiationPattern();
2670 if (!pattern)
2671 return false;
2672 return any_of(pattern->redecls(), checkRedeclForInline);
2673 };
2674 if (checkForInline(fd)) {
2675 f.setInlineKind(cir::InlineKind::InlineHint);
2676 } else if (codeGenOpts.getInlining() ==
2678 !fd->isInlined() && !isAlwaysInline) {
2679 f.setInlineKind(cir::InlineKind::NoInline);
2680 }
2681 }
2682 }
2683
2685}
2686
2688 StringRef mangledName, mlir::Type funcType, GlobalDecl gd, bool forVTable,
2689 bool dontDefer, bool isThunk, ForDefinition_t isForDefinition,
2690 mlir::NamedAttrList extraAttrs) {
2691 const Decl *d = gd.getDecl();
2692
2693 if (const auto *fd = cast_or_null<FunctionDecl>(d)) {
2694 // For the device mark the function as one that should be emitted.
2695 if (getLangOpts().OpenMPIsTargetDevice && fd->isDefined() && !dontDefer &&
2696 !isForDefinition)
2697 errorNYI(fd->getSourceRange(),
2698 "getOrCreateCIRFunction: OpenMP target function");
2699
2700 // Any attempts to use a MultiVersion function should result in retrieving
2701 // the iFunc instead. Name mangling will handle the rest of the changes.
2702 if (fd->isMultiVersion())
2703 errorNYI(fd->getSourceRange(), "getOrCreateCIRFunction: multi-version");
2704 }
2705
2706 // Lookup the entry, lazily creating it if necessary.
2707 mlir::Operation *entry = getGlobalValue(mangledName);
2708 if (entry) {
2709 assert(mlir::isa<cir::FuncOp>(entry));
2710
2712
2713 // Handle dropped DLL attributes.
2714 if (d && !d->hasAttr<DLLImportAttr>() && !d->hasAttr<DLLExportAttr>()) {
2716 setDSOLocal(entry);
2717 }
2718
2719 // If there are two attempts to define the same mangled name, issue an
2720 // error.
2721 auto fn = cast<cir::FuncOp>(entry);
2722 if (isForDefinition && fn && !fn.isDeclaration()) {
2723 GlobalDecl otherGd;
2724 // Check that GD is not yet in DiagnosedConflictingDefinitions is required
2725 // to make sure that we issue an error only once.
2726 if (lookupRepresentativeDecl(mangledName, otherGd) &&
2727 (gd.getCanonicalDecl().getDecl() !=
2728 otherGd.getCanonicalDecl().getDecl()) &&
2729 diagnosedConflictingDefinitions.insert(gd).second) {
2730 getDiags().Report(d->getLocation(), diag::err_duplicate_mangled_name)
2731 << mangledName;
2732 getDiags().Report(otherGd.getDecl()->getLocation(),
2733 diag::note_previous_definition);
2734 }
2735 }
2736
2737 if (fn && fn.getFunctionType() == funcType) {
2738 return fn;
2739 }
2740
2741 if (!isForDefinition) {
2742 return fn;
2743 }
2744
2745 // TODO(cir): classic codegen checks here if this is a llvm::GlobalAlias.
2746 // How will we support this?
2747 }
2748
2749 auto *funcDecl = llvm::cast_or_null<FunctionDecl>(gd.getDecl());
2750 bool invalidLoc = !funcDecl ||
2751 funcDecl->getSourceRange().getBegin().isInvalid() ||
2752 funcDecl->getSourceRange().getEnd().isInvalid();
2753 cir::FuncOp funcOp = createCIRFunction(
2754 invalidLoc ? theModule->getLoc() : getLoc(funcDecl->getSourceRange()),
2755 mangledName, mlir::cast<cir::FuncType>(funcType), funcDecl);
2756
2757 // If we already created a function with the same mangled name (but different
2758 // type) before, take its name and add it to the list of functions to be
2759 // replaced with F at the end of CodeGen.
2760 //
2761 // This happens if there is a prototype for a function (e.g. "int f()") and
2762 // then a definition of a different type (e.g. "int f(int x)").
2763 if (entry) {
2764
2765 // Fetch a generic symbol-defining operation and its uses.
2766 auto symbolOp = mlir::cast<mlir::SymbolOpInterface>(entry);
2767
2768 // This might be an implementation of a function without a prototype, in
2769 // which case, try to do special replacement of calls which match the new
2770 // prototype. The really key thing here is that we also potentially drop
2771 // arguments from the call site so as to make a direct call, which makes the
2772 // inliner happier and suppresses a number of optimizer warnings (!) about
2773 // dropping arguments.
2774 if (symbolOp.getSymbolUses(symbolOp->getParentOp()))
2776
2777 // Obliterate no-proto declaration.
2778 entry->erase();
2779 }
2780
2781 if (d)
2782 setFunctionAttributes(gd, funcOp, /*isIncompleteFunction=*/false, isThunk);
2783 if (!extraAttrs.empty()) {
2784 extraAttrs.append(funcOp->getAttrs());
2785 funcOp->setAttrs(extraAttrs);
2786 }
2787
2788 // 'dontDefer' actually means don't move this to the deferredDeclsToEmit list.
2789 if (dontDefer) {
2790 // TODO(cir): This assertion will need an additional condition when we
2791 // support incomplete functions.
2792 assert(funcOp.getFunctionType() == funcType);
2793 return funcOp;
2794 }
2795
2796 // All MSVC dtors other than the base dtor are linkonce_odr and delegate to
2797 // each other bottoming out wiht the base dtor. Therefore we emit non-base
2798 // dtors on usage, even if there is no dtor definition in the TU.
2799 if (isa_and_nonnull<CXXDestructorDecl>(d) &&
2800 getCXXABI().useThunkForDtorVariant(cast<CXXDestructorDecl>(d),
2801 gd.getDtorType()))
2802 errorNYI(d->getSourceRange(), "getOrCreateCIRFunction: dtor");
2803
2804 // This is the first use or definition of a mangled name. If there is a
2805 // deferred decl with this name, remember that we need to emit it at the end
2806 // of the file.
2807 auto ddi = deferredDecls.find(mangledName);
2808 if (ddi != deferredDecls.end()) {
2809 // Move the potentially referenced deferred decl to the
2810 // DeferredDeclsToEmit list, and remove it from DeferredDecls (since we
2811 // don't need it anymore).
2812 addDeferredDeclToEmit(ddi->second);
2813 deferredDecls.erase(ddi);
2814
2815 // Otherwise, there are cases we have to worry about where we're using a
2816 // declaration for which we must emit a definition but where we might not
2817 // find a top-level definition.
2818 // - member functions defined inline in their classes
2819 // - friend functions defined inline in some class
2820 // - special member functions with implicit definitions
2821 // If we ever change our AST traversal to walk into class methods, this
2822 // will be unnecessary.
2823 //
2824 // We also don't emit a definition for a function if it's going to be an
2825 // entry in a vtable, unless it's already marked as used.
2826 } else if (getLangOpts().CPlusPlus && d) {
2827 // Look for a declaration that's lexically in a record.
2828 for (const auto *fd = cast<FunctionDecl>(d)->getMostRecentDecl(); fd;
2829 fd = fd->getPreviousDecl()) {
2830 if (isa<CXXRecordDecl>(fd->getLexicalDeclContext())) {
2831 if (fd->doesThisDeclarationHaveABody()) {
2833 break;
2834 }
2835 }
2836 }
2837 }
2838
2839 return funcOp;
2840}
2841
2842cir::FuncOp
2843CIRGenModule::createCIRFunction(mlir::Location loc, StringRef name,
2844 cir::FuncType funcType,
2845 const clang::FunctionDecl *funcDecl) {
2846 cir::FuncOp func;
2847 {
2848 mlir::OpBuilder::InsertionGuard guard(builder);
2849
2850 // Some global emissions are triggered while emitting a function, e.g.
2851 // void s() { x.method() }
2852 //
2853 // Be sure to insert a new function before a current one.
2854 CIRGenFunction *cgf = this->curCGF;
2855 if (cgf)
2856 builder.setInsertionPoint(cgf->curFn);
2857
2858 func = cir::FuncOp::create(builder, loc, name, funcType);
2859
2861
2862 if (funcDecl && !funcDecl->hasPrototype())
2863 func.setNoProto(true);
2864
2865 assert(func.isDeclaration() && "expected empty body");
2866
2867 // A declaration gets private visibility by default, but external linkage
2868 // as the default linkage.
2869 func.setLinkageAttr(cir::GlobalLinkageKindAttr::get(
2870 &getMLIRContext(), cir::GlobalLinkageKind::ExternalLinkage));
2871 mlir::SymbolTable::setSymbolVisibility(
2872 func, mlir::SymbolTable::Visibility::Private);
2873
2875
2876 // Mark C++ special member functions (Constructor, Destructor etc.)
2877 setCXXSpecialMemberAttr(func, funcDecl);
2878
2879 if (!cgf)
2880 theModule.push_back(func);
2881
2882 if (this->getLangOpts().OpenACC) {
2883 // We only have to handle this attribute, since OpenACCAnnotAttrs are
2884 // handled via the end-of-TU work.
2885 for (const auto *attr :
2886 funcDecl->specific_attrs<OpenACCRoutineDeclAttr>())
2887 emitOpenACCRoutineDecl(funcDecl, func, attr->getLocation(),
2888 attr->Clauses);
2889 }
2890 }
2891 return func;
2892}
2893
2894cir::FuncOp
2895CIRGenModule::createCIRBuiltinFunction(mlir::Location loc, StringRef name,
2896 cir::FuncType ty,
2897 const clang::FunctionDecl *fd) {
2898 cir::FuncOp fnOp = createCIRFunction(loc, name, ty, fd);
2899 fnOp.setBuiltin(true);
2900 return fnOp;
2901}
2902
2903static cir::CtorKind getCtorKindFromDecl(const CXXConstructorDecl *ctor) {
2904 if (ctor->isDefaultConstructor())
2905 return cir::CtorKind::Default;
2906 if (ctor->isCopyConstructor())
2907 return cir::CtorKind::Copy;
2908 if (ctor->isMoveConstructor())
2909 return cir::CtorKind::Move;
2910 return cir::CtorKind::Custom;
2911}
2912
2913static cir::AssignKind getAssignKindFromDecl(const CXXMethodDecl *method) {
2914 if (method->isCopyAssignmentOperator())
2915 return cir::AssignKind::Copy;
2916 if (method->isMoveAssignmentOperator())
2917 return cir::AssignKind::Move;
2918 llvm_unreachable("not a copy or move assignment operator");
2919}
2920
2922 cir::FuncOp funcOp, const clang::FunctionDecl *funcDecl) {
2923 if (!funcDecl)
2924 return;
2925
2926 if (const auto *dtor = dyn_cast<CXXDestructorDecl>(funcDecl)) {
2927 auto cxxDtor = cir::CXXDtorAttr::get(
2928 convertType(getASTContext().getCanonicalTagType(dtor->getParent())),
2929 dtor->isTrivial());
2930 funcOp.setCxxSpecialMemberAttr(cxxDtor);
2931 return;
2932 }
2933
2934 if (const auto *ctor = dyn_cast<CXXConstructorDecl>(funcDecl)) {
2935 cir::CtorKind kind = getCtorKindFromDecl(ctor);
2936 auto cxxCtor = cir::CXXCtorAttr::get(
2937 convertType(getASTContext().getCanonicalTagType(ctor->getParent())),
2938 kind, ctor->isTrivial());
2939 funcOp.setCxxSpecialMemberAttr(cxxCtor);
2940 return;
2941 }
2942
2943 const auto *method = dyn_cast<CXXMethodDecl>(funcDecl);
2944 if (method && (method->isCopyAssignmentOperator() ||
2945 method->isMoveAssignmentOperator())) {
2946 cir::AssignKind assignKind = getAssignKindFromDecl(method);
2947 auto cxxAssign = cir::CXXAssignAttr::get(
2948 convertType(getASTContext().getCanonicalTagType(method->getParent())),
2949 assignKind, method->isTrivial());
2950 funcOp.setCxxSpecialMemberAttr(cxxAssign);
2951 return;
2952 }
2953}
2954
2955static void setWindowsItaniumDLLImport(CIRGenModule &cgm, bool isLocal,
2956 cir::FuncOp funcOp, StringRef name) {
2957 // In Windows Itanium environments, try to mark runtime functions
2958 // dllimport. For Mingw and MSVC, don't. We don't really know if the user
2959 // will link their standard library statically or dynamically. Marking
2960 // functions imported when they are not imported can cause linker errors
2961 // and warnings.
2962 if (!isLocal && cgm.getTarget().getTriple().isWindowsItaniumEnvironment() &&
2963 !cgm.getCodeGenOpts().LTOVisibilityPublicStd) {
2967 }
2968}
2969
2970cir::FuncOp CIRGenModule::createRuntimeFunction(cir::FuncType ty,
2971 StringRef name,
2972 mlir::NamedAttrList extraAttrs,
2973 bool isLocal,
2974 bool assumeConvergent) {
2975 if (assumeConvergent)
2976 errorNYI("createRuntimeFunction: assumeConvergent");
2977
2978 cir::FuncOp entry = getOrCreateCIRFunction(name, ty, GlobalDecl(),
2979 /*forVtable=*/false, extraAttrs);
2980
2981 if (entry) {
2982 // TODO(cir): set the attributes of the function.
2985 setWindowsItaniumDLLImport(*this, isLocal, entry, name);
2986 entry.setDSOLocal(true);
2987 }
2988
2989 return entry;
2990}
2991
2992mlir::SymbolTable::Visibility
2994 // MLIR doesn't accept public symbols declarations (only
2995 // definitions).
2996 if (op.isDeclaration())
2997 return mlir::SymbolTable::Visibility::Private;
2998 return getMLIRVisibilityFromCIRLinkage(op.getLinkage());
2999}
3000
3001mlir::SymbolTable::Visibility
3003 switch (glk) {
3004 case cir::GlobalLinkageKind::InternalLinkage:
3005 case cir::GlobalLinkageKind::PrivateLinkage:
3006 return mlir::SymbolTable::Visibility::Private;
3007 case cir::GlobalLinkageKind::ExternalLinkage:
3008 case cir::GlobalLinkageKind::ExternalWeakLinkage:
3009 case cir::GlobalLinkageKind::LinkOnceODRLinkage:
3010 case cir::GlobalLinkageKind::AvailableExternallyLinkage:
3011 case cir::GlobalLinkageKind::CommonLinkage:
3012 case cir::GlobalLinkageKind::WeakAnyLinkage:
3013 case cir::GlobalLinkageKind::WeakODRLinkage:
3014 return mlir::SymbolTable::Visibility::Public;
3015 default: {
3016 llvm::errs() << "visibility not implemented for '"
3017 << stringifyGlobalLinkageKind(glk) << "'\n";
3018 assert(0 && "not implemented");
3019 }
3020 }
3021 llvm_unreachable("linkage should be handled above!");
3022}
3023
3025 clang::VisibilityAttr::VisibilityType visibility) {
3026 switch (visibility) {
3027 case clang::VisibilityAttr::VisibilityType::Default:
3028 return cir::VisibilityKind::Default;
3029 case clang::VisibilityAttr::VisibilityType::Hidden:
3030 return cir::VisibilityKind::Hidden;
3031 case clang::VisibilityAttr::VisibilityType::Protected:
3032 return cir::VisibilityKind::Protected;
3033 }
3034 llvm_unreachable("unexpected visibility value");
3035}
3036
3037cir::VisibilityAttr
3039 const clang::VisibilityAttr *va = decl->getAttr<clang::VisibilityAttr>();
3040 cir::VisibilityAttr cirVisibility =
3041 cir::VisibilityAttr::get(&getMLIRContext());
3042 if (va) {
3043 cirVisibility = cir::VisibilityAttr::get(
3044 &getMLIRContext(),
3045 getGlobalVisibilityKindFromClangVisibility(va->getVisibility()));
3046 }
3047 return cirVisibility;
3048}
3049
3051 emitDeferred();
3053 applyReplacements();
3054
3055 theModule->setAttr(cir::CIRDialect::getModuleLevelAsmAttrName(),
3056 builder.getArrayAttr(globalScopeAsm));
3057
3058 if (getTriple().isAMDGPU() ||
3059 (getTriple().isSPIRV() && getTriple().getVendor() == llvm::Triple::AMD))
3061
3062 // There's a lot of code that is not implemented yet.
3064}
3065
3066void CIRGenModule::emitAliasForGlobal(StringRef mangledName,
3067 mlir::Operation *op, GlobalDecl aliasGD,
3068 cir::FuncOp aliasee,
3069 cir::GlobalLinkageKind linkage) {
3070
3071 auto *aliasFD = dyn_cast<FunctionDecl>(aliasGD.getDecl());
3072 assert(aliasFD && "expected FunctionDecl");
3073
3074 // The aliasee function type is different from the alias one, this difference
3075 // is specific to CIR because in LLVM the ptr types are already erased at this
3076 // point.
3077 const CIRGenFunctionInfo &fnInfo =
3079 cir::FuncType fnType = getTypes().getFunctionType(fnInfo);
3080
3081 cir::FuncOp alias =
3083 mangledName, fnType, aliasFD);
3084 alias.setAliasee(aliasee.getName());
3085 alias.setLinkage(linkage);
3086 // Declarations cannot have public MLIR visibility, just mark them private
3087 // but this really should have no meaning since CIR should not be using
3088 // this information to derive linkage information.
3089 mlir::SymbolTable::setSymbolVisibility(
3090 alias, mlir::SymbolTable::Visibility::Private);
3091
3092 // Alias constructors and destructors are always unnamed_addr.
3094
3095 // Switch any previous uses to the alias.
3096 if (op) {
3097 errorNYI(aliasFD->getSourceRange(), "emitAliasForGlobal: previous uses");
3098 } else {
3099 // Name already set by createCIRFunction
3100 }
3101
3102 // Finally, set up the alias with its proper name and attributes.
3103 setCommonAttributes(aliasGD, alias);
3104}
3105
3107 return genTypes.convertType(type);
3108}
3109
3111 // Verify the module after we have finished constructing it, this will
3112 // check the structural properties of the IR and invoke any specific
3113 // verifiers we have on the CIR operations.
3114 return mlir::verify(theModule).succeeded();
3115}
3116
3117mlir::Attribute CIRGenModule::getAddrOfRTTIDescriptor(mlir::Location loc,
3118 QualType ty, bool forEh) {
3119 // Return a bogus pointer if RTTI is disabled, unless it's for EH.
3120 // FIXME: should we even be calling this method if RTTI is disabled
3121 // and it's not for EH?
3122 if (!shouldEmitRTTI(forEh))
3123 return builder.getConstNullPtrAttr(builder.getUInt8PtrTy());
3124
3125 if (forEh && ty->isObjCObjectPointerType() &&
3126 langOpts.ObjCRuntime.isGNUFamily()) {
3127 errorNYI(loc, "getAddrOfRTTIDescriptor: Objc PtrType & Objc RT GUN");
3128 return {};
3129 }
3130
3131 return getCXXABI().getAddrOfRTTIDescriptor(loc, ty);
3132}
3133
3134// TODO(cir): this can be shared with LLVM codegen.
3136 const CXXRecordDecl *derivedClass,
3137 llvm::iterator_range<CastExpr::path_const_iterator> path) {
3138 CharUnits offset = CharUnits::Zero();
3139
3140 const ASTContext &astContext = getASTContext();
3141 const CXXRecordDecl *rd = derivedClass;
3142
3143 for (const CXXBaseSpecifier *base : path) {
3144 assert(!base->isVirtual() && "Should not see virtual bases here!");
3145
3146 // Get the layout.
3147 const ASTRecordLayout &layout = astContext.getASTRecordLayout(rd);
3148
3149 const auto *baseDecl = base->getType()->castAsCXXRecordDecl();
3150
3151 // Add the offset.
3152 offset += layout.getBaseClassOffset(baseDecl);
3153
3154 rd = baseDecl;
3155 }
3156
3157 return offset;
3158}
3159
3161 llvm::StringRef feature) {
3162 unsigned diagID = diags.getCustomDiagID(
3163 DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0");
3164 return diags.Report(loc, diagID) << feature;
3165}
3166
3168 llvm::StringRef feature) {
3169 return errorNYI(loc.getBegin(), feature) << loc;
3170}
3171
3173 unsigned diagID = getDiags().getCustomDiagID(DiagnosticsEngine::Error, "%0");
3174 getDiags().Report(astContext.getFullLoc(loc), diagID) << error;
3175}
3176
3177/// Print out an error that codegen doesn't support the specified stmt yet.
3178void CIRGenModule::errorUnsupported(const Stmt *s, llvm::StringRef type) {
3179 unsigned diagId = diags.getCustomDiagID(DiagnosticsEngine::Error,
3180 "cannot compile this %0 yet");
3181 diags.Report(astContext.getFullLoc(s->getBeginLoc()), diagId)
3182 << type << s->getSourceRange();
3183}
3184
3185/// Print out an error that codegen doesn't support the specified decl yet.
3186void CIRGenModule::errorUnsupported(const Decl *d, llvm::StringRef type) {
3187 unsigned diagId = diags.getCustomDiagID(DiagnosticsEngine::Error,
3188 "cannot compile this %0 yet");
3189 diags.Report(astContext.getFullLoc(d->getLocation()), diagId) << type;
3190}
3191
3192void CIRGenModule::mapBlockAddress(cir::BlockAddrInfoAttr blockInfo,
3193 cir::LabelOp label) {
3194 [[maybe_unused]] auto result =
3195 blockAddressInfoToLabel.try_emplace(blockInfo, label);
3196 assert(result.second &&
3197 "attempting to map a blockaddress info that is already mapped");
3198}
3199
3200void CIRGenModule::mapUnresolvedBlockAddress(cir::BlockAddressOp op) {
3201 [[maybe_unused]] auto result = unresolvedBlockAddressToLabel.insert(op);
3202 assert(result.second &&
3203 "attempting to map a blockaddress operation that is already mapped");
3204}
3205
3206void CIRGenModule::mapResolvedBlockAddress(cir::BlockAddressOp op,
3207 cir::LabelOp label) {
3208 [[maybe_unused]] auto result = blockAddressToLabel.try_emplace(op, label);
3209 assert(result.second &&
3210 "attempting to map a blockaddress operation that is already mapped");
3211}
3212
3214 cir::LabelOp newLabel) {
3215 auto *it = blockAddressToLabel.find(op);
3216 assert(it != blockAddressToLabel.end() &&
3217 "trying to update a blockaddress not previously mapped");
3218 assert(!it->second && "blockaddress already has a resolved label");
3219
3220 it->second = newLabel;
3221}
3222
3223cir::LabelOp
3224CIRGenModule::lookupBlockAddressInfo(cir::BlockAddrInfoAttr blockInfo) {
3225 return blockAddressInfoToLabel.lookup(blockInfo);
3226}
3227
3228mlir::Operation *
3230 const Expr *init) {
3231 assert((mte->getStorageDuration() == SD_Static ||
3232 mte->getStorageDuration() == SD_Thread) &&
3233 "not a global temporary");
3234 const auto *varDecl = cast<VarDecl>(mte->getExtendingDecl());
3235
3236 // If we're not materializing a subobject of the temporary, keep the
3237 // cv-qualifiers from the type of the MaterializeTemporaryExpr.
3238 QualType materializedType = init->getType();
3239 if (init == mte->getSubExpr())
3240 materializedType = mte->getType();
3241
3242 CharUnits align = getASTContext().getTypeAlignInChars(materializedType);
3243
3244 auto insertResult = materializedGlobalTemporaryMap.insert({mte, nullptr});
3245 if (!insertResult.second)
3246 errorNYI(mte->getSourceRange(), "duplicate materialized temporaries");
3247
3248 // FIXME: If an externally-visible declaration extends multiple temporaries,
3249 // we need to give each temporary the same name in every translation unit (and
3250 // we also need to make the temporaries externally-visible).
3252 llvm::raw_svector_ostream out(name);
3254 varDecl, mte->getManglingNumber(), out);
3255
3256 APValue *value = nullptr;
3257 if (mte->getStorageDuration() == SD_Static && varDecl->evaluateValue()) {
3258 // If the initializer of the extending declaration is a constant
3259 // initializer, we should have a cached constant initializer for this
3260 // temporay. Note taht this m ight have a different value from the value
3261 // computed by evaluating the initializer if the surrounding constant
3262 // expression modifies the temporary.
3263 value = mte->getOrCreateValue(/*MayCreate=*/false);
3264 }
3265
3266 // Try evaluating it now, it might have a constant initializer
3267 Expr::EvalResult evalResult;
3268 if (!value && init->EvaluateAsRValue(evalResult, getASTContext()) &&
3269 !evalResult.hasSideEffects())
3270 value = &evalResult.Val;
3271
3273
3274 std::optional<ConstantEmitter> emitter;
3275 mlir::Attribute initialValue = nullptr;
3276 bool isConstant = false;
3277 mlir::Type type;
3278
3279 if (value) {
3280 emitter.emplace(*this);
3281 initialValue = emitter->emitForInitializer(*value, materializedType);
3282
3283 isConstant = materializedType.isConstantStorage(
3284 getASTContext(), /*ExcludeCtor=*/value, /*ExcludeDtor=*/false);
3285
3286 type = mlir::cast<mlir::TypedAttr>(initialValue).getType();
3287 } else {
3288 // No initializer, the initialization will be provided when we initialize
3289 // the declaration which performed lifetime extension.
3290 type = getTypes().convertTypeForMem(materializedType);
3291 }
3292
3293 // Create a global variable for this lifetime-extended temporary.
3294 cir::GlobalLinkageKind linkage =
3295 getCIRLinkageVarDefinition(varDecl, /*isConstant=*/false);
3296 if (linkage == cir::GlobalLinkageKind::ExternalLinkage) {
3297 const VarDecl *initVD;
3298 if (varDecl->isStaticDataMember() && varDecl->getAnyInitializer(initVD) &&
3300 // Temporaries defined inside a class get linkonce_odr linkage because the
3301 // calss can be defined in multiple translation units.
3302 errorNYI(mte->getSourceRange(), "static data member initialization");
3303 } else {
3304 // There is no need for this temporary to have external linkage if the
3305 // VarDecl has external linkage.
3306 linkage = cir::GlobalLinkageKind::InternalLinkage;
3307 }
3308 }
3309 mlir::Location loc = getLoc(mte->getSourceRange());
3310 cir::GlobalOp gv = createGlobalOp(*this, loc, name, type, isConstant);
3311 gv.setInitialValueAttr(initialValue);
3312
3313 if (emitter)
3314 emitter->finalize(gv);
3315 // Don't assign dllimport or dllexport to local linkage globals
3316 if (!gv.hasLocalLinkage()) {
3319 }
3320
3321 gv.setAlignment(align.getAsAlign().value());
3322 if (supportsCOMDAT() && gv.isWeakForLinker())
3323 errorNYI(mte->getSourceRange(),
3324 "Global temporary with comdat/weak linkage");
3325 if (varDecl->getTLSKind())
3326 errorNYI(mte->getSourceRange(),
3327 "Global temporary with thread local storage");
3328 mlir::Operation *cv = gv;
3329
3331
3332 // Update the map with the new temporary. If we created a placeholder above,
3333 // replace it with the new global now.
3334 mlir::Operation *&entry = materializedGlobalTemporaryMap[mte];
3335 if (entry) {
3336 entry->replaceAllUsesWith(cv);
3337 entry->erase();
3338 }
3339 entry = cv;
3340
3341 return cv;
3342}
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 mlir::Attribute getNewInitValue(CIRGenModule &cgm, cir::GlobalOp newGlob, mlir::Type oldTy, mlir::Attribute oldInit)
static bool hasUnwindExceptions(const LangOptions &langOpts)
Determines whether the language options require us to model unwind exceptions.
static void setWindowsItaniumDLLImport(CIRGenModule &cgm, bool isLocal, cir::FuncOp funcOp, StringRef name)
static std::string getMangledNameImpl(CIRGenModule &cgm, GlobalDecl gd, const NamedDecl *nd)
static llvm::SmallVector< int64_t > indexesOfArrayAttr(mlir::ArrayAttr indexes)
static bool isViewOnGlobal(cir::GlobalOp glob, cir::GlobalViewAttr view)
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)
static cir::GlobalViewAttr createNewGlobalView(CIRGenModule &cgm, cir::GlobalOp newGlob, cir::GlobalViewAttr attr, mlir::Type oldTy)
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::GlobalViewAttr getGlobalViewAttr(cir::GlobalOp globalOp, mlir::ArrayAttr indices={})
Get constant address of a global variable as an MLIR attribute.
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:878
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:917
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.
mlir::Attribute getConstRecordOrZeroAttr(mlir::ArrayAttr arrayAttr, bool packed=false, bool padded=false, mlir::Type type={})
uint64_t computeOffsetFromGlobalViewIndices(const cir::CIRDataLayout &layout, mlir::Type ty, llvm::ArrayRef< int64_t > indices)
void computeGlobalViewIndicesFromFlatOffset(int64_t offset, mlir::Type ty, cir::CIRDataLayout layout, llvm::SmallVectorImpl< int64_t > &indices)
cir::ConstArrayAttr getConstArray(mlir::Attribute attrs, cir::ArrayType arrayTy) const
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.
static cir::GlobalOp createGlobalOp(CIRGenModule &cgm, mlir::Location loc, llvm::StringRef name, mlir::Type t, bool isConstant=false, mlir::ptr::MemorySpaceAttrInterface addrSpace={}, mlir::Operation *insertPoint=nullptr)
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.
const cir::CIRDataLayout getDataLayout() const
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
void emitDeferredVTables()
Emit any vtables which we deferred and still have a use for.
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)
void emitVTablesOpportunistically()
Try to emit external vtables as available_externally if they have emitted all inlined virtual functio...
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::TypedAttr emitNullMemberAttr(QualType t, const MemberPointerType *mpt)
Returns a null attribute to represent either a null method or null data member, depending on the type...
mlir::Operation * getGlobalValue(llvm::StringRef ref)
void emitOMPDeclareReduction(const OMPDeclareReductionDecl *d)
mlir::ModuleOp getModule() const
clang::CharUnits getNaturalTypeAlignment(clang::QualType t, LValueBaseInfo *baseInfo=nullptr, bool forPointeeType=false)
FIXME: this could likely be a common helper and not necessarily related with codegen.
cir::GlobalLinkageKind getCIRLinkageForDeclarator(const DeclaratorDecl *dd, GVALinkage linkage, bool isConstantVariable)
mlir::MLIRContext & getMLIRContext()
mlir::Operation * getAddrOfGlobal(clang::GlobalDecl gd, ForDefinition_t isForDefinition=NotForDefinition)
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 emitAMDGPUMetadata()
Emits AMDGPU specific Metadata.
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,...
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 clang::LangAS getGlobalVarAddressSpace(CIRGenModule &cgm, const clang::VarDecl *d) const
Get target favored AST address space of a global variable for languages other than OpenCL and CUDA.
virtual mlir::ptr::MemorySpaceAttrInterface getCIRAllocaAddressSpace() const
Get the address space for alloca.
Definition TargetInfo.h:60
virtual void setTargetAttributes(const clang::Decl *decl, mlir::Operation *global, CIRGenModule &module) const
Provides a convenient hook to handle extra target-specific attributes for the given global.
Definition TargetInfo.h:114
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:3810
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:4553
CallingConv getCallConv() const
Definition TypeBase.h:4908
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...
clang::ObjCRuntime ObjCRuntime
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
A pointer to member type per C++ 8.3.3 - Pointers to members.
Definition TypeBase.h:3703
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
bool hasUnwindExceptions() const
Does this runtime use zero-cost exceptions?
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:8557
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8471
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition TypeBase.h:8504
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.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition Type.h:41
bool isArrayType() const
Definition TypeBase.h:8767
bool isPointerType() const
Definition TypeBase.h:8668
bool isReferenceType() const
Definition TypeBase.h:8692
bool isCUDADeviceBuiltinSurfaceType() const
Check if the type is the CUDA device builtin surface type.
Definition Type.cpp:5410
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition TypeBase.h:2850
bool isCUDADeviceBuiltinTextureType() const
Check if the type is the CUDA device builtin texture type.
Definition Type.cpp:5419
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:8847
bool isMemberFunctionPointerType() const
Definition TypeBase.h:8753
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9261
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
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
Definition Decl.h:1569
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
@ DeclarationOnly
This declaration is only a declaration.
Definition Decl.h:1295
@ 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
bool isMatchingAddressSpace(mlir::ptr::MemorySpaceAttrInterface cirAS, clang::LangAS as)
mlir::ptr::MemorySpaceAttrInterface toCIRAddressSpaceAttr(mlir::MLIRContext &ctx, clang::LangAS langAS)
Convert an AST LangAS to the appropriate CIR address space attribute interface.
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 > createAMDGPUTargetCIRGenInfo(CIRGenTypes &cgt)
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 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 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.