19#include "mlir/Dialect/OpenMP/OpenMPOffloadUtils.h"
22#include "clang/AST/Attrs.inc"
35#include "llvm/ADT/StringRef.h"
39#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
40#include "mlir/IR/Attributes.h"
41#include "mlir/IR/BuiltinOps.h"
42#include "mlir/IR/Location.h"
43#include "mlir/IR/MLIRContext.h"
44#include "mlir/IR/Operation.h"
45#include "mlir/IR/Verifier.h"
54 case TargetCXXABI::GenericItanium:
55 case TargetCXXABI::GenericAArch64:
56 case TargetCXXABI::AppleARM64:
59 case TargetCXXABI::Fuchsia:
60 case TargetCXXABI::GenericARM:
61 case TargetCXXABI::iOS:
62 case TargetCXXABI::WatchOS:
63 case TargetCXXABI::GenericMIPS:
64 case TargetCXXABI::WebAssembly:
65 case TargetCXXABI::XL:
66 case TargetCXXABI::Microsoft:
67 cgm.
errorNYI(
"createCXXABI: C++ ABI kind");
71 llvm_unreachable(
"invalid C++ ABI kind");
74CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,
78 : builder(mlirContext, *this), astContext(astContext),
79 langOpts(astContext.
getLangOpts()), codeGenOpts(cgo),
80 theModule{
mlir::ModuleOp::create(
mlir::UnknownLoc::get(&mlirContext))},
81 diags(diags), target(astContext.getTargetInfo()),
82 abi(
createCXXABI(*this)), genTypes(*this), vtables(*this) {
110 .toCharUnitsFromBits(
114 const unsigned charSize = astContext.getTargetInfo().getCharWidth();
118 const unsigned sizeTypeSize =
119 astContext.getTypeSize(astContext.getSignedSizeType());
120 SizeSizeInBytes = astContext.toCharUnitsFromBits(sizeTypeSize).getQuantity();
127 std::optional<cir::SourceLanguage> sourceLanguage = getCIRSourceLanguage();
130 cir::CIRDialect::getSourceLanguageAttrName(),
131 cir::SourceLanguageAttr::get(&mlirContext, *sourceLanguage));
132 theModule->setAttr(cir::CIRDialect::getTripleAttrName(),
133 builder.getStringAttr(
getTriple().str()));
135 if (cgo.OptimizationLevel > 0 || cgo.OptimizeSize > 0)
136 theModule->setAttr(cir::CIRDialect::getOptInfoAttrName(),
137 cir::OptInfoAttr::get(&mlirContext,
138 cgo.OptimizationLevel,
141 if (langOpts.OpenMP) {
142 mlir::omp::OffloadModuleOpts ompOpts(
143 langOpts.OpenMPTargetDebug, langOpts.OpenMPTeamSubscription,
144 langOpts.OpenMPThreadSubscription, langOpts.OpenMPNoThreadState,
145 langOpts.OpenMPNoNestedParallelism, langOpts.OpenMPIsTargetDevice,
146 getTriple().isGPU(), langOpts.OpenMPForceUSM, langOpts.OpenMP,
147 langOpts.OMPHostIRFile, langOpts.OMPTargetTriples, langOpts.NoGPULib);
148 mlir::omp::setOffloadModuleInterfaceAttributes(theModule, ompOpts);
157 FileID mainFileId = astContext.getSourceManager().getMainFileID();
159 *astContext.getSourceManager().getFileEntryForID(mainFileId);
162 theModule.setSymName(path);
163 theModule->setLoc(mlir::FileLineColLoc::get(&mlirContext, path,
170 llvm::StringRef cudaBinaryName = codeGenOpts.CudaGpuBinaryFileName;
171 if (!cudaBinaryName.empty()) {
172 theModule->setAttr(cir::CIRDialect::getCUDABinaryHandleAttrName(),
173 cir::CUDABinaryHandleAttr::get(
174 &mlirContext, mlir::StringAttr::get(
175 &mlirContext, cudaBinaryName)));
182void CIRGenModule::createCUDARuntime() {
194 auto &layout = astContext.getASTRecordLayout(rd);
199 return layout.getAlignment();
202 return layout.getNonVirtualAlignment();
207 bool forPointeeType) {
217 if (
unsigned align = tt->getDecl()->getMaxAlignment()) {
220 return astContext.toCharUnitsFromBits(align);
228 t = astContext.getBaseElementType(t);
249 }
else if (forPointeeType && !alignForArray &&
253 alignment = astContext.getTypeAlignInChars(t);
258 if (
unsigned maxAlign = astContext.getLangOpts().MaxTypeAlign) {
260 !astContext.isAlignmentRequired(t))
274 if (theTargetCIRGenInfo)
275 return *theTargetCIRGenInfo;
278 switch (triple.getArch()) {
285 case llvm::Triple::x86_64: {
286 switch (triple.getOS()) {
293 case llvm::Triple::Linux:
295 return *theTargetCIRGenInfo;
298 case llvm::Triple::nvptx:
299 case llvm::Triple::nvptx64:
301 return *theTargetCIRGenInfo;
302 case llvm::Triple::amdgcn: {
304 return *theTargetCIRGenInfo;
310 assert(cLoc.
isValid() &&
"expected valid source location");
314 return mlir::FileLineColLoc::get(builder.getStringAttr(filename),
319 assert(cRange.
isValid() &&
"expected a valid source range");
322 mlir::Attribute metadata;
323 return mlir::FusedLoc::get({begin, end}, metadata, builder.getContext());
332 false, isForDefinition);
366 assert(op &&
"expected a valid global op");
374 mlir::Operation *globalValueOp = op;
375 if (
auto gv = dyn_cast<cir::GetGlobalOp>(op)) {
377 mlir::SymbolTable::lookupSymbolIn(
getModule(), gv.getNameAttr());
378 assert(globalValueOp &&
"expected a valid global op");
381 if (
auto cirGlobalValue =
382 dyn_cast<cir::CIRGlobalValueInterface>(globalValueOp))
383 if (!cirGlobalValue.isDeclaration())
404 assert(deferredVTables.empty());
414 std::vector<GlobalDecl> curDeclsToEmit;
433 if (
auto *
attr =
decl->getAttr<AttrT>())
434 return attr->isImplicit();
435 return decl->isImplicit();
440 assert(langOpts.CUDA &&
"Should not be called by non-CUDA languages");
445 return !langOpts.CUDAIsDevice || global->
hasAttr<CUDADeviceAttr>() ||
446 global->
hasAttr<CUDAConstantAttr>() ||
447 global->
hasAttr<CUDASharedAttr>() ||
453 if (
const auto *cd = dyn_cast<clang::OpenACCConstructDecl>(gd.
getDecl())) {
471 "Expected Variable or Function");
472 if (
const auto *
varDecl = dyn_cast<VarDecl>(global)) {
476 }
else if (langOpts.CUDAIsDevice) {
477 const auto *
functionDecl = dyn_cast<FunctionDecl>(global);
478 if ((!global->hasAttr<CUDADeviceAttr>() ||
479 (langOpts.OffloadImplicitHostDeviceTemplates &&
484 !
getASTContext().CUDAImplicitHostDeviceFunUsedByDevice.count(
486 !global->hasAttr<CUDAGlobalAttr>() &&
488 !global->hasAttr<CUDAHostAttr>()))
491 }
else if (!global->hasAttr<CUDAHostAttr>() &&
492 global->hasAttr<CUDADeviceAttr>())
496 if (
const auto *fd = dyn_cast<FunctionDecl>(global)) {
499 if (fd->hasAttr<AnnotateAttr>()) {
502 deferredAnnotations[mangledName] = fd;
504 if (!fd->doesThisDeclarationHaveABody()) {
505 if (!fd->doesDeclarationForceExternallyVisibleDefinition())
509 "function declaration that forces code gen");
514 assert(vd->isFileVarDecl() &&
"Cannot emit local var decl as global.");
516 !astContext.isMSStaticDataMemberInlineDefinition(vd)) {
520 if (astContext.getInlineVariableDefinitionKind(vd) ==
559 mlir::Operation *op) {
563 cir::FuncOp funcOp = dyn_cast_if_present<cir::FuncOp>(op);
564 if (!funcOp || funcOp.getFunctionType() != funcType) {
570 if (!funcOp.isDeclaration())
582 mlir::OpBuilder::InsertionGuard guard(builder);
587 setNonAliasAttributes(gd, funcOp);
590 auto getPriority = [
this](
const auto *
attr) ->
int {
594 return attr->DefaultPriority;
597 if (
const ConstructorAttr *ca = funcDecl->getAttr<ConstructorAttr>())
599 if (
const DestructorAttr *da = funcDecl->getAttr<DestructorAttr>())
602 if (funcDecl->getAttr<AnnotateAttr>())
608 std::optional<int> priority) {
617 ctor.setGlobalCtorPriority(priority);
622 std::optional<int> priority) {
623 if (codeGenOpts.RegisterGlobalDtorsWithAtExit &&
625 errorNYI(dtor.getLoc(),
"registerGlobalDtorsWithAtExit");
628 dtor.setGlobalDtorPriority(priority);
646 return mlir::SymbolTable::lookupSymbolIn(theModule, name);
651 StringRef name, mlir::Type t,
bool isConstant,
652 mlir::ptr::MemorySpaceAttrInterface addrSpace,
653 mlir::Operation *insertPoint) {
658 mlir::OpBuilder::InsertionGuard guard(builder);
664 builder.setInsertionPoint(insertPoint);
670 builder.setInsertionPointToStart(cgm.
getModule().getBody());
673 g = cir::GlobalOp::create(builder, loc, name, t, isConstant, addrSpace);
679 mlir::SymbolTable::setSymbolVisibility(
680 g, mlir::SymbolTable::Visibility::Private);
687 if (isa_and_nonnull<NamedDecl>(d))
691 if (
auto gvi = mlir::dyn_cast<cir::CIRGlobalValueInterface>(gv)) {
692 if (d && d->
hasAttr<UsedAttr>())
695 if (
const auto *vd = dyn_cast_if_present<VarDecl>(d);
696 vd && ((codeGenOpts.KeepPersistentStorageVariables &&
697 (vd->getStorageDuration() ==
SD_Static ||
698 vd->getStorageDuration() ==
SD_Thread)) ||
699 (codeGenOpts.KeepStaticConsts &&
701 vd->getType().isConstQualified())))
706void CIRGenModule::setNonAliasAttributes(
GlobalDecl gd, mlir::Operation *op) {
711 if (
auto gvi = mlir::dyn_cast<cir::CIRGlobalValueInterface>(op)) {
712 if (
const auto *sa = d->
getAttr<SectionAttr>())
713 gvi.setSection(builder.getStringAttr(sa->getName()));
725std::optional<cir::SourceLanguage> CIRGenModule::getCIRSourceLanguage()
const {
726 using ClangStd = clang::LangStandard;
727 using CIRLang = cir::SourceLanguage;
732 if (opts.C99 || opts.C11 || opts.C17 || opts.C23 || opts.C2y ||
733 opts.LangStd == ClangStd::lang_c89 ||
734 opts.LangStd == ClangStd::lang_gnu89)
739 errorNYI(
"CIR does not yet support the given source language");
743LangAS CIRGenModule::getGlobalVarAddressSpace(
const VarDecl *d) {
744 if (langOpts.OpenCL) {
752 if (langOpts.SYCLIsDevice &&
754 errorNYI(
"SYCL global address space");
756 if (langOpts.CUDA && langOpts.CUDAIsDevice) {
758 if (d->
hasAttr<CUDAConstantAttr>())
760 if (d->
hasAttr<CUDASharedAttr>())
762 if (d->
hasAttr<CUDADeviceAttr>())
771 errorNYI(
"OpenMP global address space");
784 gv.
setLinkage(cir::GlobalLinkageKind::ExternalWeakLinkage);
789 for (mlir::Attribute i : indexes) {
790 auto ind = mlir::cast<mlir::IntegerAttr>(i);
791 inds.push_back(ind.getValue().getSExtValue());
797 return view.getSymbol().getValue() == glob.getSymName();
801 cir::GlobalOp newGlob,
802 cir::GlobalViewAttr
attr,
813 mlir::Type newTy = newGlob.getSymType();
818 cir::PointerType newPtrTy;
821 newPtrTy = cir::PointerType::get(newTy);
830 cgm.
errorNYI(
"Unhandled type in createNewGlobalView");
836 mlir::Attribute oldInit) {
837 if (
auto oldView = mlir::dyn_cast<cir::GlobalViewAttr>(oldInit))
840 auto getNewInitElements =
841 [&](mlir::ArrayAttr oldElements) -> mlir::ArrayAttr {
843 for (mlir::Attribute elt : oldElements) {
844 if (
auto view = mlir::dyn_cast<cir::GlobalViewAttr>(elt))
846 else if (mlir::isa<cir::ConstArrayAttr, cir::ConstRecordAttr>(elt))
849 newElements.push_back(elt);
851 return mlir::ArrayAttr::get(cgm.
getBuilder().getContext(), newElements);
854 if (
auto oldArray = mlir::dyn_cast<cir::ConstArrayAttr>(oldInit)) {
855 mlir::Attribute newElements =
856 getNewInitElements(mlir::cast<mlir::ArrayAttr>(oldArray.getElts()));
858 newElements, mlir::cast<cir::ArrayType>(oldArray.getType()));
860 if (
auto oldRecord = mlir::dyn_cast<cir::ConstRecordAttr>(oldInit)) {
861 mlir::ArrayAttr newMembers = getNewInitElements(oldRecord.getMembers());
862 auto recordTy = mlir::cast<cir::RecordType>(oldRecord.getType());
864 newMembers, recordTy.getPacked(), recordTy.getPadded(), recordTy);
869 cgm.
errorNYI(
"Unhandled type in getNewInitValue");
877 assert(oldGV.getSymName() == newGV.getSymName() &&
"symbol names must match");
879 mlir::Type oldTy = oldGV.getSymType();
880 mlir::Type newTy = newGV.getSymType();
885 assert(oldTy != newTy &&
"expected type change in replaceGlobal");
888 std::optional<mlir::SymbolTable::UseRange> oldSymUses =
889 oldGV.getSymbolUses(theModule);
890 for (mlir::SymbolTable::SymbolUse use : *oldSymUses) {
891 mlir::Operation *userOp = use.getUser();
893 (mlir::isa<cir::GetGlobalOp, cir::GlobalOp, cir::ConstantOp>(userOp)) &&
894 "Unexpected user for global op");
896 if (
auto getGlobalOp = dyn_cast<cir::GetGlobalOp>(use.getUser())) {
897 mlir::Value useOpResultValue = getGlobalOp.getAddr();
898 useOpResultValue.setType(cir::PointerType::get(newTy));
900 mlir::OpBuilder::InsertionGuard guard(builder);
901 builder.setInsertionPointAfter(getGlobalOp);
902 mlir::Type ptrTy = builder.getPointerTo(oldTy);
904 builder.createBitcast(getGlobalOp->getLoc(), useOpResultValue, ptrTy);
905 useOpResultValue.replaceAllUsesExcept(
cast,
cast.getDefiningOp());
906 }
else if (
auto glob = dyn_cast<cir::GlobalOp>(userOp)) {
907 if (
auto init = glob.getInitialValue()) {
908 mlir::Attribute nw =
getNewInitValue(*
this, newGV, oldTy, init.value());
909 glob.setInitialValueAttr(nw);
911 }
else if (
auto c = dyn_cast<cir::ConstantOp>(userOp)) {
913 auto typedAttr = mlir::cast<mlir::TypedAttr>(init);
914 mlir::OpBuilder::InsertionGuard guard(builder);
915 builder.setInsertionPointAfter(
c);
916 auto newUser = cir::ConstantOp::create(builder,
c.getLoc(), typedAttr);
917 c.replaceAllUsesWith(newUser.getOperation());
954 "getOrCreateCIRGlobal: global with non-GlobalOp type");
959 mlir::ptr::MemorySpaceAttrInterface entryCIRAS = entry.getAddrSpaceAttr();
965 if (entry.getSymType() == ty &&
975 if (isForDefinition && !entry.isDeclaration()) {
977 "getOrCreateCIRGlobal: global with conflicting type");
985 if (!isForDefinition)
994 bool isConstant =
false;
999 astContext,
true, !needsDtor);
1002 mlir::ptr::MemorySpaceAttrInterface declCIRAS =
1008 *
this, loc, mangledName, ty, isConstant, declCIRAS,
1009 entry.getOperation());
1029 if (langOpts.OpenMP && !langOpts.OpenMPSimd)
1031 "getOrCreateCIRGlobal: OpenMP target global variable");
1033 gv.setAlignmentAttr(
getSize(astContext.getDeclAlign(d)));
1047 if (astContext.isMSStaticDataMemberInlineDefinition(d))
1049 "getOrCreateCIRGlobal: MS static data member inline definition");
1053 if (
const SectionAttr *sa = d->
getAttr<SectionAttr>())
1054 gv.setSectionAttr(builder.getStringAttr(sa->getName()));
1059 if (
getTriple().getArch() == llvm::Triple::xcore)
1061 "getOrCreateCIRGlobal: XCore specific ABI requirements");
1071 "getOrCreateCIRGlobal: external const declaration with initializer");
1083 "getOrCreateCIRGlobal: HIP managed attribute");
1118 mlir::Type ptrTy = builder.getPointerTo(g.getSymType(), g.getAddrSpaceAttr());
1119 return cir::GetGlobalOp::create(
1122 g.getStaticLocalGuard().has_value());
1130 cir::PointerType ptrTy =
1131 builder.getPointerTo(globalOp.getSymType(), globalOp.getAddrSpaceAttr());
1132 return builder.getGlobalViewAttr(ptrTy, globalOp);
1136 assert((mlir::isa<cir::FuncOp>(gv.getOperation()) ||
1137 !gv.isDeclarationForLinker()) &&
1138 "Only globals with definition can force usage.");
1143 assert(!gv.isDeclarationForLinker() &&
1144 "Only globals with definition can force usage.");
1149 cir::CIRGlobalValueInterface gv) {
1150 assert((mlir::isa<cir::FuncOp>(gv.getOperation()) ||
1151 !gv.isDeclarationForLinker()) &&
1152 "Only globals with definition can force usage.");
1160 std::vector<cir::CIRGlobalValueInterface> &list) {
1165 mlir::Location loc = builder.getUnknownLoc();
1167 usedArray.resize(list.size());
1168 for (
auto [i, op] : llvm::enumerate(list)) {
1169 usedArray[i] = cir::GlobalViewAttr::get(
1170 cgm.
voidPtrTy, mlir::FlatSymbolRefAttr::get(op.getNameAttr()));
1173 cir::ArrayType arrayTy = cir::ArrayType::get(cgm.
voidPtrTy, usedArray.size());
1175 cir::ConstArrayAttr initAttr = cir::ConstArrayAttr::get(
1176 arrayTy, mlir::ArrayAttr::get(&cgm.
getMLIRContext(), usedArray));
1180 gv.setLinkage(cir::GlobalLinkageKind::AppendingLinkage);
1181 gv.setInitialValueAttr(initAttr);
1182 gv.setSectionAttr(builder.getStringAttr(
"llvm.metadata"));
1194 "emitGlobalVarDefinition: emit OpenCL/OpenMP global variable");
1201 bool isDefinitionAvailableExternally =
1206 if (isDefinitionAvailableExternally &&
1214 mlir::Attribute init;
1215 bool needsGlobalCtor =
false;
1216 bool needsGlobalDtor =
1217 !isDefinitionAvailableExternally &&
1222 std::optional<ConstantEmitter> emitter;
1227 bool isCUDASharedVar =
1232 bool isCUDAShadowVar =
1234 (vd->
hasAttr<CUDAConstantAttr>() || vd->
hasAttr<CUDADeviceAttr>() ||
1235 vd->
hasAttr<CUDASharedAttr>());
1236 bool isCUDADeviceShadowVar =
1242 (isCUDASharedVar || isCUDAShadowVar || isCUDADeviceShadowVar)) {
1244 }
else if (vd->
hasAttr<LoaderUninitializedAttr>()) {
1246 "emitGlobalVarDefinition: loader uninitialized attribute");
1247 }
else if (!initExpr) {
1260 emitter.emplace(*
this);
1261 mlir::Attribute initializer = emitter->tryEmitForInitializer(*initDecl);
1270 "emitGlobalVarDefinition: flexible array initializer");
1272 if (!isDefinitionAvailableExternally)
1273 needsGlobalCtor =
true;
1276 "emitGlobalVarDefinition: static initializer");
1287 mlir::Type initType;
1288 if (mlir::isa<mlir::SymbolRefAttr>(init)) {
1291 "emitGlobalVarDefinition: global initializer is a symbol reference");
1294 assert(mlir::isa<mlir::TypedAttr>(init) &&
"This should have a type");
1295 auto typedInitAttr = mlir::cast<mlir::TypedAttr>(init);
1296 initType = typedInitAttr.getType();
1298 assert(!mlir::isa<mlir::NoneType>(initType) &&
"Should have a type by now");
1304 if (!gv || gv.getSymType() != initType) {
1306 "emitGlobalVarDefinition: global initializer with type mismatch");
1312 if (vd->
hasAttr<AnnotateAttr>())
1325 if (langOpts.CUDA) {
1326 if (langOpts.CUDAIsDevice) {
1329 if (linkage != cir::GlobalLinkageKind::InternalLinkage &&
1331 (vd->
hasAttr<CUDADeviceAttr>() || vd->
hasAttr<CUDAConstantAttr>() ||
1334 gv->setAttr(cir::CUDAExternallyInitializedAttr::getMnemonic(),
1350 emitter->finalize(gv);
1354 gv.setConstant((vd->
hasAttr<CUDAConstantAttr>() && langOpts.CUDAIsDevice) ||
1355 (!needsGlobalCtor && !needsGlobalDtor &&
1360 if (
const SectionAttr *sa = vd->
getAttr<SectionAttr>()) {
1363 gv.setConstant(
true);
1367 gv.setLinkage(linkage);
1371 if (linkage == cir::GlobalLinkageKind::CommonLinkage) {
1373 gv.setConstant(
false);
1378 std::optional<mlir::Attribute> initializer = gv.getInitialValue();
1379 if (initializer && !
getBuilder().isNullValue(*initializer))
1380 gv.setLinkage(cir::GlobalLinkageKind::WeakAnyLinkage);
1383 setNonAliasAttributes(vd, gv);
1390 if (needsGlobalCtor || needsGlobalDtor)
1395 mlir::Operation *op) {
1397 if (
const auto *fd = dyn_cast<FunctionDecl>(
decl)) {
1401 if (
const auto *method = dyn_cast<CXXMethodDecl>(
decl)) {
1405 abi->emitCXXStructor(gd);
1406 else if (fd->isMultiVersion())
1407 errorNYI(method->getSourceRange(),
"multiversion functions");
1411 if (method->isVirtual())
1417 if (fd->isMultiVersion())
1418 errorNYI(fd->getSourceRange(),
"multiversion functions");
1423 if (
const auto *vd = dyn_cast<VarDecl>(
decl))
1426 llvm_unreachable(
"Invalid argument to CIRGenModule::emitGlobalDefinition");
1440 astContext.getAsConstantArrayType(e->
getType());
1441 uint64_t finalSize = cat->getZExtSize();
1442 str.resize(finalSize);
1444 mlir::Type eltTy =
convertType(cat->getElementType());
1445 return builder.getString(str, eltTy, finalSize,
false);
1450 auto arrayEltTy = mlir::cast<cir::IntType>(arrayTy.getElementType());
1452 uint64_t arraySize = arrayTy.getSize();
1454 assert(arraySize == literalSize + 1 &&
1455 "wide string literal array size must be literal length plus null "
1460 bool isAllZero =
true;
1461 for (
unsigned i = 0; i < literalSize; ++i) {
1469 return cir::ZeroAttr::get(arrayTy);
1473 elements.reserve(arraySize);
1474 for (
unsigned i = 0; i < literalSize; ++i)
1475 elements.push_back(cir::IntAttr::get(arrayEltTy, e->
getCodeUnit(i)));
1477 elements.push_back(cir::IntAttr::get(arrayEltTy, 0));
1479 auto elementsAttr = mlir::ArrayAttr::get(&
getMLIRContext(), elements);
1480 return builder.getConstArray(elementsAttr, arrayTy);
1491 if (d.
hasAttr<SelectAnyAttr>())
1495 if (
auto *vd = dyn_cast<VarDecl>(&d))
1510 llvm_unreachable(
"No such linkage");
1516 if (
auto globalOp = dyn_cast_or_null<cir::GlobalOp>(op)) {
1517 globalOp.setComdat(
true);
1520 funcOp.setComdat(
true);
1526 genTypes.updateCompletedType(td);
1530 replacements[name] = op;
1536 std::optional<mlir::SymbolTable::UseRange> optionalUseRange =
1537 oldF.getSymbolUses(modOp);
1538 if (!optionalUseRange)
1541 for (
const mlir::SymbolTable::SymbolUse &u : *optionalUseRange) {
1542 auto call = mlir::dyn_cast<cir::CallOp>(u.getUser());
1546 for (
auto [argOp, fnArgType] :
1547 llvm::zip(call.getArgs(), newF.getFunctionType().getInputs())) {
1548 if (argOp.getType() != fnArgType)
1557void CIRGenModule::applyReplacements() {
1558 for (
auto &i : replacements) {
1559 StringRef mangledName = i.first;
1560 mlir::Operation *replacement = i.second;
1566 auto newF = dyn_cast<cir::FuncOp>(replacement);
1569 errorNYI(replacement->getLoc(),
"replacement is not a function");
1574 "call argument types do not match replacement function");
1577 if (oldF.replaceAllSymbolUses(newF.getSymNameAttr(), theModule).failed())
1578 llvm_unreachable(
"internal error, cannot RAUW symbol");
1580 newF->moveBefore(oldF);
1587 mlir::Location loc, StringRef name, mlir::Type ty,
1589 auto gv = mlir::dyn_cast_or_null<cir::GlobalOp>(
1590 mlir::SymbolTable::lookupSymbolIn(theModule, name));
1594 if (gv.getSymType() == ty)
1600 assert(gv.isDeclaration() &&
"Declaration has wrong type!");
1602 errorNYI(loc,
"createOrReplaceCXXRuntimeVariable: declaration exists with "
1613 mlir::SymbolTable::setSymbolVisibility(gv,
1617 !gv.hasAvailableExternallyLinkage()) {
1621 gv.setAlignmentAttr(
getSize(alignment));
1632 if ((noCommon || vd->
hasAttr<NoCommonAttr>()) && !vd->
hasAttr<CommonAttr>())
1643 if (vd->
hasAttr<SectionAttr>())
1649 if (vd->
hasAttr<PragmaClangBSSSectionAttr>() ||
1650 vd->
hasAttr<PragmaClangDataSectionAttr>() ||
1651 vd->
hasAttr<PragmaClangRelroSectionAttr>() ||
1652 vd->
hasAttr<PragmaClangRodataSectionAttr>())
1660 if (vd->
hasAttr<WeakImportAttr>())
1670 if (vd->
hasAttr<AlignedAttr>())
1677 for (
const FieldDecl *fd : rd->fields()) {
1678 if (fd->isBitField())
1680 if (fd->hasAttr<AlignedAttr>())
1702cir::GlobalLinkageKind
1706 return cir::GlobalLinkageKind::InternalLinkage;
1709 return cir::GlobalLinkageKind::WeakAnyLinkage;
1713 return cir::GlobalLinkageKind::LinkOnceAnyLinkage;
1718 return cir::GlobalLinkageKind::AvailableExternallyLinkage;
1732 return !astContext.getLangOpts().AppleKext
1733 ? cir::GlobalLinkageKind::LinkOnceODRLinkage
1734 : cir::GlobalLinkageKind::InternalLinkage;
1748 return cir::GlobalLinkageKind::ExternalLinkage;
1751 return dd->
hasAttr<CUDAGlobalAttr>()
1752 ? cir::GlobalLinkageKind::ExternalLinkage
1753 : cir::GlobalLinkageKind::InternalLinkage;
1754 return cir::GlobalLinkageKind::WeakODRLinkage;
1762 return cir::GlobalLinkageKind::CommonLinkage;
1768 if (dd->
hasAttr<SelectAnyAttr>())
1769 return cir::GlobalLinkageKind::WeakODRLinkage;
1773 return cir::GlobalLinkageKind::ExternalLinkage;
1785 mlir::Operation *old, cir::FuncOp newFn) {
1787 auto oldFn = mlir::dyn_cast<cir::FuncOp>(old);
1795 if (oldFn->getAttrs().size() <= 1)
1797 "replaceUsesOfNonProtoTypeWithRealFunction: Attribute forwarding");
1800 newFn.setNoProto(oldFn.getNoProto());
1803 std::optional<mlir::SymbolTable::UseRange> symUses =
1804 oldFn.getSymbolUses(oldFn->getParentOp());
1805 for (
const mlir::SymbolTable::SymbolUse &use : symUses.value()) {
1806 mlir::OpBuilder::InsertionGuard guard(builder);
1808 if (
auto noProtoCallOp = mlir::dyn_cast<cir::CallOp>(use.getUser())) {
1809 builder.setInsertionPoint(noProtoCallOp);
1812 cir::CallOp realCallOp = builder.createCallOp(
1813 noProtoCallOp.getLoc(), newFn, noProtoCallOp.getOperands());
1816 noProtoCallOp.replaceAllUsesWith(realCallOp);
1817 noProtoCallOp.erase();
1818 }
else if (
auto getGlobalOp =
1819 mlir::dyn_cast<cir::GetGlobalOp>(use.getUser())) {
1826 mlir::Value res = getGlobalOp.getAddr();
1827 const mlir::Type oldResTy = res.getType();
1828 const auto newPtrTy = cir::PointerType::get(newFn.getFunctionType());
1829 if (oldResTy != newPtrTy) {
1830 res.setType(newPtrTy);
1831 builder.setInsertionPointAfter(getGlobalOp.getOperation());
1832 mlir::Value castRes =
1833 cir::CastOp::create(builder, getGlobalOp.getLoc(), oldResTy,
1834 cir::CastKind::bitcast, res);
1835 res.replaceAllUsesExcept(castRes, castRes.getDefiningOp());
1837 }
else if (mlir::isa<cir::GlobalOp>(use.getUser())) {
1843 "replaceUsesOfNonProtoTypeWithRealFunction: unexpected use type");
1848cir::GlobalLinkageKind
1850 GVALinkage linkage = astContext.GetGVALinkageForVariable(vd);
1857 GVALinkage linkage = astContext.GetGVALinkageForFunction(d);
1859 if (
const auto *dtor = dyn_cast<CXXDestructorDecl>(d))
1868 StringRef globalName,
CharUnits alignment) {
1874 cgm, loc, globalName,
c.getType(), !cgm.
getLangOpts().WritableStrings);
1877 gv.setAlignmentAttr(cgm.
getSize(alignment));
1879 cir::GlobalLinkageKindAttr::get(cgm.
getBuilder().getContext(), lt));
1883 if (gv.isWeakForLinker()) {
1884 assert(cgm.
supportsCOMDAT() &&
"Only COFF uses weak string literals");
1887 cgm.
setDSOLocal(
static_cast<mlir::Operation *
>(gv));
1908 std::string result =
1911 assert(!mlir::SymbolTable::lookupSymbolIn(theModule, result));
1919 astContext.getAlignOfGlobalVarInChars(
s->getType(),
nullptr);
1927 if (!gv.getAlignment() ||
1928 uint64_t(alignment.
getQuantity()) > *gv.getAlignment())
1929 gv.setAlignmentAttr(
getSize(alignment));
1934 if (
getCXXABI().getMangleContext().shouldMangleStringLiteral(
s) &&
1937 "getGlobalForStringLiteral: mangle string literals");
1945 mlir::Location loc =
s->getBeginLoc().isValid()
1947 : builder.getUnknownLoc();
1948 auto typedC = llvm::cast<mlir::TypedAttr>(
c);
1950 cir::GlobalLinkageKind::PrivateLinkage, *
this,
1951 uniqueName, alignment);
1965 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(gv.getSymType());
1966 assert(arrayTy &&
"String literal must be array");
1970 return builder.getGlobalViewAttr(ptrTy, gv);
1986 errorNYI(
"SYCL or OpenMP temp address space");
1996 "emitExplicitCastExprType");
2002 auto ty = mlir::cast<cir::MethodType>(
convertType(destTy));
2003 return builder.getNullMethodAttr(ty);
2006 auto ty = mlir::cast<cir::DataMemberType>(
convertType(destTy));
2007 return builder.getNullDataMemberAttr(ty);
2018 if (
const auto *methodDecl = dyn_cast<CXXMethodDecl>(
decl)) {
2020 if (methodDecl->isVirtual())
2021 return cir::ConstantOp::create(
2022 builder, loc,
getCXXABI().buildVirtualMethodAttr(ty, methodDecl));
2028 return cir::ConstantOp::create(builder, loc,
2029 builder.getMethodAttr(ty, methodFuncOp));
2035 return cir::ConstantOp::create(
2036 builder, loc, builder.getDataMemberAttr(ty,
fieldDecl->getFieldIndex()));
2046 if (
auto *oid = dyn_cast<ObjCImplDecl>(
decl))
2047 errorNYI(oid->getSourceRange(),
"emitDeclConext: ObjCImplDecl");
2057 if (
decl->isTemplated())
2060 switch (
decl->getKind()) {
2063 decl->getDeclKindName());
2066 case Decl::CXXConversion:
2067 case Decl::CXXMethod:
2068 case Decl::Function: {
2071 if (!fd->isConsteval())
2080 case Decl::Decomposition:
2081 case Decl::VarTemplateSpecialization: {
2083 if (
auto *decomp = dyn_cast<DecompositionDecl>(
decl))
2084 for (
auto *binding : decomp->flat_bindings())
2085 if (
auto *holdingVar = binding->getHoldingVar())
2089 case Decl::OpenACCRoutine:
2092 case Decl::OpenACCDeclare:
2095 case Decl::OMPThreadPrivate:
2098 case Decl::OMPGroupPrivate:
2101 case Decl::OMPAllocate:
2104 case Decl::OMPCapturedExpr:
2107 case Decl::OMPDeclareReduction:
2110 case Decl::OMPDeclareMapper:
2113 case Decl::OMPRequires:
2118 case Decl::UsingDirective:
2119 case Decl::UsingEnum:
2120 case Decl::NamespaceAlias:
2122 case Decl::TypeAlias:
2128 case Decl::ClassTemplate:
2130 case Decl::CXXDeductionGuide:
2132 case Decl::ExplicitInstantiation:
2133 case Decl::FunctionTemplate:
2134 case Decl::StaticAssert:
2135 case Decl::TypeAliasTemplate:
2136 case Decl::UsingShadow:
2137 case Decl::VarTemplate:
2138 case Decl::VarTemplatePartialSpecialization:
2141 case Decl::CXXConstructor:
2144 case Decl::CXXDestructor:
2149 case Decl::LinkageSpec:
2150 case Decl::Namespace:
2154 case Decl::ClassTemplateSpecialization:
2155 case Decl::CXXRecord: {
2158 for (
auto *childDecl : crd->
decls())
2164 case Decl::FileScopeAsm:
2166 if (langOpts.CUDA && langOpts.CUDAIsDevice)
2169 if (langOpts.OpenMPIsTargetDevice)
2172 if (langOpts.SYCLIsDevice)
2175 std::string line = file_asm->getAsmString();
2176 globalScopeAsm.push_back(builder.getStringAttr(line));
2183 op.setInitialValueAttr(value);
2197 md->getParent()->getNumVBases() == 0)
2199 "getAddrAndTypeOfCXXStructor: MS ABI complete destructor");
2210 false, isForDefinition);
2212 return {fnType, fn};
2216 mlir::Type funcType,
bool forVTable,
2220 "consteval function should never be emitted");
2230 if (
const auto *dd = dyn_cast<CXXDestructorDecl>(gd.
getDecl())) {
2233 dd->getParent()->getNumVBases() == 0)
2235 "getAddrOfFunction: MS ABI complete destructor");
2241 false, isForDefinition);
2243 if (langOpts.CUDA && !langOpts.CUDAIsDevice &&
2249 bool isHIPHandle = mlir::isa<cir::GlobalOp>(*handle);
2250 if (isForDefinition || isHIPHandle)
2252 return mlir::dyn_cast<cir::FuncOp>(*handle);
2261 llvm::raw_svector_ostream
out(buffer);
2270 assert(ii &&
"Attempt to mangle unnamed decl.");
2272 const auto *fd = dyn_cast<FunctionDecl>(nd);
2276 }
else if (fd && fd->hasAttr<CUDAGlobalAttr>() &&
2280 DeviceKernelAttr::isOpenCLSpelling(
2281 fd->getAttr<DeviceKernelAttr>()) &&
2298 if (
const auto *fd = dyn_cast<FunctionDecl>(nd)) {
2299 if (fd->isMultiVersion()) {
2301 "getMangledName: multi-version functions");
2306 "getMangledName: GPU relocatable device code");
2309 return std::string(
out.str());
2312static FunctionDecl *
2327 if (
auto *methodDecl = dyn_cast<CXXMethodDecl>(protoFunc);
2328 methodDecl && methodDecl->isImplicitObjectMemberFunction()) {
2330 paramTypes.insert(paramTypes.begin(), methodDecl->getThisType());
2333 fpt->getExtProtoInfo());
2344 params.reserve(fpt->getNumParams());
2347 for (
unsigned i = 0, e = fpt->getNumParams(); i != e; ++i) {
2351 nullptr, fpt->getParamType(i),
nullptr,
2354 params.push_back(parm);
2357 tempFunc->setParams(params);
2382 if (
const auto *cd = dyn_cast<CXXConstructorDecl>(canonicalGd.
getDecl())) {
2385 "getMangledName: C++ constructor without variants");
2394 auto result = manglings.insert(std::make_pair(mangledName, gd));
2395 return mangledDeclNames[canonicalGd] = result.first->first();
2399 assert(!d->
getInit() &&
"Cannot emit definite definitions here!");
2407 if (gv && !mlir::cast<cir::GlobalOp>(gv).isDeclaration())
2423 if (langOpts.EmitAllDecls)
2426 const auto *vd = dyn_cast<VarDecl>(global);
2428 ((codeGenOpts.KeepPersistentStorageVariables &&
2429 (vd->getStorageDuration() ==
SD_Static ||
2430 vd->getStorageDuration() ==
SD_Thread)) ||
2431 (codeGenOpts.KeepStaticConsts && vd->getStorageDuration() ==
SD_Static &&
2432 vd->getType().isConstQualified())))
2445 if (langOpts.OpenMP >= 50 && !langOpts.OpenMPSimd) {
2446 std::optional<OMPDeclareTargetDeclAttr *> activeAttr =
2447 OMPDeclareTargetDeclAttr::getActiveAttr(global);
2448 if (!activeAttr || (*activeAttr)->getLevel() != (
unsigned)-1)
2452 const auto *fd = dyn_cast<FunctionDecl>(global);
2459 if (fd->hasAttr<TargetVersionAttr>() && !fd->isMultiVersion())
2461 if (langOpts.SYCLIsDevice) {
2462 errorNYI(fd->getSourceRange(),
"mayBeEmittedEagerly: SYCL");
2466 const auto *vd = dyn_cast<VarDecl>(global);
2468 if (astContext.getInlineVariableDefinitionKind(vd) ==
2476 if (langOpts.OpenMP && langOpts.OpenMPUseTLS &&
2477 astContext.getTargetInfo().isTLSSupported() &&
isa<VarDecl>(global) &&
2479 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(global))
2482 assert((fd || vd) &&
2483 "Only FunctionDecl and VarDecl should hit this path so far.");
2488 cir::CIRGlobalValueInterface gv) {
2489 if (gv.hasLocalLinkage())
2492 if (!gv.hasDefaultVisibility() && !gv.hasExternalWeakLinkage())
2500 const llvm::Triple &tt = cgm.
getTriple();
2502 if (tt.isOSCygMing()) {
2511 cgm.
errorNYI(
"shouldAssumeDSOLocal: MinGW");
2517 if (tt.isOSBinFormatCOFF() && gv.hasExternalWeakLinkage())
2525 if (tt.isOSBinFormatCOFF() || (tt.isOSWindows() && tt.isOSBinFormatMachO()))
2529 if (!tt.isOSBinFormatELF())
2534 if (rm != llvm::Reloc::Static && !lOpts.PIE) {
2542 return !(lOpts.SemanticInterposition || lOpts.HalfNoSemanticInterposition);
2546 if (!gv.isDeclarationForLinker())
2552 if (rm == llvm::Reloc::PIC_ && gv.hasExternalWeakLinkage())
2559 if (cgOpts.DirectAccessExternalData) {
2565 if (
auto globalOp = dyn_cast<cir::GlobalOp>(gv.getOperation())) {
2598 if (
auto globalValue = dyn_cast<cir::CIRGlobalValueInterface>(op))
2617 auto res = manglings.find(mangledName);
2618 if (res == manglings.end())
2620 result = res->getValue();
2627 return cir::TLS_Model::GeneralDynamic;
2629 return cir::TLS_Model::LocalDynamic;
2631 return cir::TLS_Model::InitialExec;
2633 return cir::TLS_Model::LocalExec;
2635 llvm_unreachable(
"Invalid TLS model!");
2639 assert(d.
getTLSKind() &&
"setting TLS mode on non-TLS var!");
2644 if (d.
getAttr<TLSModelAttr>())
2648 global.setTlsModel(tlm);
2653 cir::FuncOp func,
bool isThunk) {
2655 cir::CallingConv callingConv;
2656 cir::SideEffect sideEffect;
2663 mlir::NamedAttrList pal{};
2664 std::vector<mlir::NamedAttrList> argAttrs(info.
arguments().size());
2665 mlir::NamedAttrList retAttrs{};
2667 retAttrs, callingConv, sideEffect,
2670 for (mlir::NamedAttribute
attr : pal)
2671 func->setAttr(
attr.getName(),
attr.getValue());
2673 llvm::for_each(llvm::enumerate(argAttrs), [func](
auto idx_arg_pair) {
2674 mlir::function_interface_impl::setArgAttrs(func, idx_arg_pair.index(),
2675 idx_arg_pair.value());
2677 if (!retAttrs.empty())
2678 mlir::function_interface_impl::setResultAttrs(func, 0, retAttrs);
2691 bool isIncompleteFunction,
2699 if (!isIncompleteFunction)
2701 getTypes().arrangeGlobalDeclaration(globalDecl),
2704 if (!isIncompleteFunction && func.isDeclaration())
2717 if (funcDecl->isInlineBuiltinDeclaration()) {
2719 bool hasBody = funcDecl->
hasBody(fdBody);
2721 assert(hasBody &&
"Inline builtin declarations should always have an "
2726 if (funcDecl->isReplaceableGlobalAllocationFunction()) {
2729 func->setAttr(cir::CIRDialect::getNoBuiltinAttrName(),
2741 if (!langOpts.Exceptions)
2744 if (langOpts.CXXExceptions)
2747 if (langOpts.ObjCExceptions)
2758 f->setAttr(cir::CIRDialect::getNoThrowAttrName(),
2761 std::optional<cir::InlineKind> existingInlineKind = f.getInlineKind();
2763 existingInlineKind && *existingInlineKind == cir::InlineKind::NoInline;
2764 bool isAlwaysInline = existingInlineKind &&
2765 *existingInlineKind == cir::InlineKind::AlwaysInline;
2769 if (!isAlwaysInline &&
2774 f.setInlineKind(cir::InlineKind::NoInline);
2789 if (
decl->hasAttr<NoInlineAttr>() && !isAlwaysInline) {
2791 f.setInlineKind(cir::InlineKind::NoInline);
2792 }
else if (
decl->hasAttr<AlwaysInlineAttr>() && !isNoInline) {
2795 f.setInlineKind(cir::InlineKind::AlwaysInline);
2799 if (!isAlwaysInline)
2800 f.setInlineKind(cir::InlineKind::NoInline);
2805 if (
auto *fd = dyn_cast<FunctionDecl>(
decl)) {
2810 auto checkRedeclForInline = [](
const FunctionDecl *redecl) {
2811 return redecl->isInlineSpecified();
2813 if (any_of(
decl->redecls(), checkRedeclForInline))
2818 return any_of(pattern->
redecls(), checkRedeclForInline);
2820 if (checkForInline(fd)) {
2821 f.setInlineKind(cir::InlineKind::InlineHint);
2822 }
else if (codeGenOpts.getInlining() ==
2824 !fd->isInlined() && !isAlwaysInline) {
2825 f.setInlineKind(cir::InlineKind::NoInline);
2834 StringRef mangledName, mlir::Type funcType,
GlobalDecl gd,
bool forVTable,
2836 mlir::NamedAttrList extraAttrs) {
2839 if (
const auto *fd = cast_or_null<FunctionDecl>(d)) {
2841 if (
getLangOpts().OpenMPIsTargetDevice && fd->isDefined() && !dontDefer &&
2844 "getOrCreateCIRFunction: OpenMP target function");
2848 if (fd->isMultiVersion())
2849 errorNYI(fd->getSourceRange(),
"getOrCreateCIRFunction: multi-version");
2855 assert(mlir::isa<cir::FuncOp>(entry));
2860 if (d && !d->
hasAttr<DLLImportAttr>() && !d->
hasAttr<DLLExportAttr>()) {
2868 if (isForDefinition && fn && !fn.isDeclaration()) {
2875 diagnosedConflictingDefinitions.insert(gd).second) {
2879 diag::note_previous_definition);
2883 if (fn && fn.getFunctionType() == funcType) {
2887 if (!isForDefinition) {
2895 auto *funcDecl = llvm::cast_or_null<FunctionDecl>(gd.
getDecl());
2896 bool invalidLoc = !funcDecl ||
2897 funcDecl->getSourceRange().getBegin().isInvalid() ||
2898 funcDecl->getSourceRange().getEnd().isInvalid();
2900 invalidLoc ? theModule->getLoc() :
getLoc(funcDecl->getSourceRange()),
2901 mangledName, mlir::cast<cir::FuncType>(funcType), funcDecl);
2903 if (funcDecl && funcDecl->hasAttr<AnnotateAttr>())
2904 deferredAnnotations[mangledName] = funcDecl;
2915 auto symbolOp = mlir::cast<mlir::SymbolOpInterface>(entry);
2923 if (symbolOp.getSymbolUses(symbolOp->getParentOp()))
2932 if (!extraAttrs.empty()) {
2933 extraAttrs.append(funcOp->getAttrs());
2934 funcOp->setAttrs(extraAttrs);
2941 assert(funcOp.getFunctionType() == funcType);
2948 if (isa_and_nonnull<CXXDestructorDecl>(d) &&
2978 fd = fd->getPreviousDecl()) {
2980 if (fd->doesThisDeclarationHaveABody()) {
2993 cir::FuncType funcType,
2997 mlir::OpBuilder::InsertionGuard guard(builder);
3005 builder.setInsertionPoint(cgf->
curFn);
3007 func = cir::FuncOp::create(builder, loc, name, funcType);
3012 func.setNoProto(
true);
3014 assert(func.isDeclaration() &&
"expected empty body");
3018 func.setLinkageAttr(cir::GlobalLinkageKindAttr::get(
3020 mlir::SymbolTable::setSymbolVisibility(
3021 func, mlir::SymbolTable::Visibility::Private);
3029 theModule.push_back(func);
3034 for (
const auto *
attr :
3048 fnOp.setBuiltin(
true);
3054 return cir::CtorKind::Default;
3056 return cir::CtorKind::Copy;
3058 return cir::CtorKind::Move;
3059 return cir::CtorKind::Custom;
3064 return cir::AssignKind::Copy;
3066 return cir::AssignKind::Move;
3067 llvm_unreachable(
"not a copy or move assignment operator");
3075 if (
const auto *dtor = dyn_cast<CXXDestructorDecl>(funcDecl)) {
3076 auto cxxDtor = cir::CXXDtorAttr::get(
3079 funcOp.setCxxSpecialMemberAttr(cxxDtor);
3083 if (
const auto *ctor = dyn_cast<CXXConstructorDecl>(funcDecl)) {
3085 auto cxxCtor = cir::CXXCtorAttr::get(
3087 kind, ctor->isTrivial());
3088 funcOp.setCxxSpecialMemberAttr(cxxCtor);
3092 const auto *method = dyn_cast<CXXMethodDecl>(funcDecl);
3093 if (method && (method->isCopyAssignmentOperator() ||
3094 method->isMoveAssignmentOperator())) {
3096 auto cxxAssign = cir::CXXAssignAttr::get(
3098 assignKind, method->isTrivial());
3099 funcOp.setCxxSpecialMemberAttr(cxxAssign);
3105 cir::FuncOp funcOp, StringRef name) {
3121 mlir::NamedAttrList extraAttrs,
3123 bool assumeConvergent) {
3124 if (assumeConvergent)
3125 errorNYI(
"createRuntimeFunction: assumeConvergent");
3135 entry.setDSOLocal(
true);
3141mlir::SymbolTable::Visibility
3145 if (op.isDeclaration())
3146 return mlir::SymbolTable::Visibility::Private;
3150mlir::SymbolTable::Visibility
3153 case cir::GlobalLinkageKind::InternalLinkage:
3154 case cir::GlobalLinkageKind::PrivateLinkage:
3155 return mlir::SymbolTable::Visibility::Private;
3156 case cir::GlobalLinkageKind::ExternalLinkage:
3157 case cir::GlobalLinkageKind::ExternalWeakLinkage:
3158 case cir::GlobalLinkageKind::LinkOnceODRLinkage:
3159 case cir::GlobalLinkageKind::AvailableExternallyLinkage:
3160 case cir::GlobalLinkageKind::CommonLinkage:
3161 case cir::GlobalLinkageKind::WeakAnyLinkage:
3162 case cir::GlobalLinkageKind::WeakODRLinkage:
3163 return mlir::SymbolTable::Visibility::Public;
3165 llvm::errs() <<
"visibility not implemented for '"
3166 << stringifyGlobalLinkageKind(glk) <<
"'\n";
3167 assert(0 &&
"not implemented");
3170 llvm_unreachable(
"linkage should be handled above!");
3174 clang::VisibilityAttr::VisibilityType visibility) {
3175 switch (visibility) {
3176 case clang::VisibilityAttr::VisibilityType::Default:
3177 return cir::VisibilityKind::Default;
3178 case clang::VisibilityAttr::VisibilityType::Hidden:
3179 return cir::VisibilityKind::Hidden;
3180 case clang::VisibilityAttr::VisibilityType::Protected:
3181 return cir::VisibilityKind::Protected;
3183 llvm_unreachable(
"unexpected visibility value");
3188 const clang::VisibilityAttr *va =
decl->getAttr<clang::VisibilityAttr>();
3189 cir::VisibilityAttr cirVisibility =
3192 cirVisibility = cir::VisibilityAttr::get(
3196 return cirVisibility;
3202 applyReplacements();
3204 theModule->setAttr(cir::CIRDialect::getModuleLevelAsmAttrName(),
3205 builder.getArrayAttr(globalScopeAsm));
3207 emitGlobalAnnotations();
3209 if (!recordLayoutEntries.empty())
3211 cir::CIRDialect::getRecordLayoutsAttrName(),
3212 mlir::DictionaryAttr::get(&
getMLIRContext(), recordLayoutEntries));
3221 std::string cuidName =
3224 auto loc = builder.getUnknownLoc();
3225 mlir::ptr::MemorySpaceAttrInterface addrSpace =
3227 getGlobalVarAddressSpace(
nullptr));
3231 gv.setLinkage(cir::GlobalLinkageKind::ExternalLinkage);
3233 auto zeroAttr = cir::IntAttr::get(int8Ty, 0);
3234 gv.setInitialValueAttr(zeroAttr);
3236 mlir::SymbolTable::setSymbolVisibility(
3237 gv, mlir::SymbolTable::Visibility::Public);
3250 cir::FuncOp aliasee,
3251 cir::GlobalLinkageKind linkage) {
3253 auto *aliasFD = dyn_cast<FunctionDecl>(aliasGD.
getDecl());
3254 assert(aliasFD &&
"expected FunctionDecl");
3265 mangledName, fnType, aliasFD);
3266 alias.setAliasee(aliasee.getName());
3267 alias.setLinkage(linkage);
3271 mlir::SymbolTable::setSymbolVisibility(
3272 alias, mlir::SymbolTable::Visibility::Private);
3284 "declaration exists with different type");
3295 return genTypes.convertType(
type);
3302 return mlir::verify(theModule).succeeded();
3311 return builder.getConstNullPtrAttr(builder.getUInt8PtrTy());
3314 langOpts.ObjCRuntime.isGNUFamily()) {
3315 errorNYI(loc,
"getAddrOfRTTIDescriptor: Objc PtrType & Objc RT GUN");
3325 llvm::iterator_range<CastExpr::path_const_iterator> path) {
3332 assert(!base->isVirtual() &&
"Should not see virtual bases here!");
3337 const auto *baseDecl = base->getType()->castAsCXXRecordDecl();
3349 llvm::StringRef feature) {
3350 unsigned diagID = diags.getCustomDiagID(
3352 return diags.Report(loc, diagID) << feature;
3356 llvm::StringRef feature) {
3368 "cannot compile this %0 yet");
3369 diags.Report(astContext.getFullLoc(
s->getBeginLoc()), diagId)
3370 <<
type <<
s->getSourceRange();
3376 "cannot compile this %0 yet");
3377 diags.Report(astContext.getFullLoc(d->
getLocation()), diagId) <<
type;
3381 cir::LabelOp label) {
3382 [[maybe_unused]]
auto result =
3384 assert(result.second &&
3385 "attempting to map a blockaddress info that is already mapped");
3390 assert(result.second &&
3391 "attempting to map a blockaddress operation that is already mapped");
3395 cir::LabelOp label) {
3397 assert(result.second &&
3398 "attempting to map a blockaddress operation that is already mapped");
3402 cir::LabelOp newLabel) {
3405 "trying to update a blockaddress not previously mapped");
3406 assert(!it->second &&
"blockaddress already has a resolved label");
3408 it->second = newLabel;
3421 "not a global temporary");
3433 materializedType = mte->
getType();
3437 auto insertResult = materializedGlobalTemporaryMap.insert({mte,
nullptr});
3438 if (!insertResult.second)
3445 llvm::raw_svector_ostream
out(name);
3463 value = &evalResult.
Val;
3467 std::optional<ConstantEmitter> emitter;
3468 mlir::Attribute initialValue =
nullptr;
3469 bool isConstant =
false;
3473 emitter.emplace(*
this);
3474 initialValue = emitter->emitForInitializer(*value, materializedType);
3479 type = mlir::cast<mlir::TypedAttr>(initialValue).getType();
3488 if (linkage == cir::GlobalLinkageKind::ExternalLinkage) {
3490 if (
varDecl->isStaticDataMember() &&
varDecl->getAnyInitializer(initVD) &&
3498 linkage = cir::GlobalLinkageKind::InternalLinkage;
3503 gv.setInitialValueAttr(initialValue);
3506 emitter->finalize(gv);
3508 if (!gv.hasLocalLinkage()) {
3513 gv.setAlignment(align.getAsAlign().value());
3516 "Global temporary with comdat/weak linkage");
3519 "Global temporary with thread local storage");
3520 mlir::Operation *cv = gv;
3526 mlir::Operation *&entry = materializedGlobalTemporaryMap[mte];
3528 entry->replaceAllUsesWith(cv);
3541CIRGenModule::getOrCreateAnnotationArgs(
const AnnotateAttr *
attr) {
3548 llvm::FoldingSetNodeID id;
3549 for (
Expr *e : exprs)
3552 mlir::ArrayAttr &lookup = annotationArgs[
id.ComputeHash()];
3557 args.reserve(exprs.size());
3558 for (
Expr *e : exprs) {
3559 if (
auto *strE = dyn_cast<clang::StringLiteral>(e->IgnoreParenCasts())) {
3560 args.push_back(builder.getStringAttr(strE->getString()));
3561 }
else if (
auto *intE =
3562 dyn_cast<clang::IntegerLiteral>(e->IgnoreParenCasts())) {
3563 auto intTy = builder.getIntegerType(intE->getValue().getBitWidth());
3564 args.push_back(builder.getIntegerAttr(intTy, intE->getValue()));
3566 errorNYI(e->getExprLoc(),
"annotation argument expression");
3570 return lookup = builder.getArrayAttr(args);
3573cir::AnnotationAttr CIRGenModule::emitAnnotateAttr(
const AnnotateAttr *aa) {
3574 mlir::StringAttr annoGV = builder.getStringAttr(aa->getAnnotation());
3575 mlir::ArrayAttr args = getOrCreateAnnotationArgs(aa);
3576 return cir::AnnotationAttr::get(&
getMLIRContext(), annoGV, args);
3580 mlir::Operation *gv) {
3581 assert(d->
hasAttr<AnnotateAttr>() &&
"no annotate attribute");
3583 "annotation only on globals");
3586 annotations.push_back(emitAnnotateAttr(i));
3587 if (
auto global = dyn_cast<cir::GlobalOp>(gv))
3588 global.setAnnotationsAttr(builder.getArrayAttr(annotations));
3589 else if (
auto func = dyn_cast<cir::FuncOp>(gv))
3590 func.setAnnotationsAttr(builder.getArrayAttr(annotations));
3593void CIRGenModule::emitGlobalAnnotations() {
3594 for (
const auto &[mangledName, vd] : deferredAnnotations) {
3599 deferredAnnotations.clear();
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 void emitUsed(CIRGenModule &cgm, StringRef name, std::vector< cir::CIRGlobalValueInterface > &list)
static bool verifyPointerTypeArgs(mlir::ModuleOp modOp, cir::FuncOp oldF, cir::FuncOp newF)
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],...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
TranslationUnitDecl * getTranslationUnitDecl() const
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
@ Strong
Strong definition.
@ 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...
StringRef getCUIDHash() const
void Deallocate(void *Ptr) const
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
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 addUsedOrCompilerUsedGlobal(cir::CIRGlobalValueInterface gv)
Add a global to a list to be added to the llvm.compiler.used metadata.
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.
cir::GlobalLinkageKind getCIRLinkageVarDefinition(const VarDecl *vd)
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.
std::vector< cir::CIRGlobalValueInterface > llvmUsed
List of global values which are required to be present in the object file; This is used for forcing v...
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.
std::vector< cir::CIRGlobalValueInterface > llvmCompilerUsed
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
cir::GlobalLinkageKind getCIRLinkageForDeclarator(const DeclaratorDecl *dd, GVALinkage linkage)
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)
void addUsedGlobal(cir::CIRGlobalValueInterface gv)
Add a global value to the llvmUsed list.
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)
void emitLLVMUsed()
Emit llvm.used and llvm.compiler.used globals.
mlir::Value emitMemberPointerConstant(const UnaryOperator *e)
void emitGlobalOpenACCDecl(const clang::OpenACCConstructDecl *cd)
bool verifyModule() const
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
bool supportsCOMDAT() const
void addCompilerUsedGlobal(cir::CIRGlobalValueInterface gv)
Add a global value to the llvmCompilerUsed list.
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.
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)
clang::CharUnits getNaturalPointeeTypeAlignment(clang::QualType t, LValueBaseInfo *baseInfo=nullptr)
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...
void mapBlockAddress(cir::BlockAddrInfoAttr blockInfo, cir::LabelOp label)
void addGlobalAnnotations(const clang::ValueDecl *d, mlir::Operation *gv)
Add global annotations for a global value (GlobalOp or FuncOp).
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.
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.
Represents a base class of a C++ class.
Represents a C++ constructor within a class.
bool isMoveConstructor(unsigned &TypeQuals) const
Determine whether this constructor is a move constructor (C++11 [class.copy]p3), which can be used to...
bool isCopyConstructor(unsigned &TypeQuals) const
Whether this constructor is a copy constructor (C++ [class.copy]p2, which can be used to copy the cla...
bool isDefaultConstructor() const
Whether this constructor is a default constructor (C++ [class.ctor]p5), which can be used to default-...
Represents a static or instance method of a struct/union/class.
bool isMoveAssignmentOperator() const
Determine whether this is a move assignment operator.
bool isCopyAssignmentOperator() const
Determine whether this is a copy-assignment operator, regardless of whether it was declared implicitl...
Represents a C++ struct/union/class.
bool isEffectivelyFinal() const
Determine whether it's impossible for a class to be derived from this class.
bool hasDefinition() const
CharUnits - This is an opaque type for sizes expressed in character units.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static CharUnits One()
One - Construct a CharUnits quantity of one.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
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.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Decl - This represents one declaration (or definition), e.g.
bool isWeakImported() const
Determine whether this is a weak-imported symbol.
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
static DeclContext * castToDeclContext(const Decl *)
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
SourceLocation getLocation() const
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Represents a ValueDecl that came out of a declarator.
A little helper class used to produce diagnostics.
Concrete class used by the front-end to report problems and issues.
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.
ExplicitCastExpr - An explicit cast written in the source code.
This represents one expression.
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...
Represents a member of a struct/union/class.
Cached information about one file (either on disk or in the virtual file system).
StringRef tryGetRealPathName() const
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Represents a function declaration or definition.
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={})
bool hasPrototype() const
Whether this function has a prototype, either because one was explicitly written or because it was "i...
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.
FunctionType - C99 6.7.5.3 - Function Declarators.
CallingConv getCallConv() const
GlobalDecl - represents a global declaration.
GlobalDecl getCanonicalDecl() const
KernelReferenceKind getKernelReferenceKind() const
GlobalDecl getWithDecl(const Decl *D)
CXXDtorType getDtorType() const
const Decl * getDecl() const
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)
Linkage getLinkage() const
MangleContext - Context for tracking state which persists across multiple calls to the C++ name mangl...
bool shouldMangleDeclName(const NamedDecl *D)
void mangleName(GlobalDecl GD, raw_ostream &)
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.
StorageDuration getStorageDuration() const
Retrieve the storage duration for the materialized temporary.
APValue * getOrCreateValue(bool MayCreate) const
Get the storage for the constant value of a materialized temporary of static storage duration.
ValueDecl * getExtendingDecl()
Get the declaration which triggered the lifetime-extension of this temporary, if any.
unsigned getManglingNumber() const
A pointer to member type per C++ 8.3.3 - Pointers to members.
This represents a decl that may have a name.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
LinkageInfo getLinkageAndVisibility() const
Determines the linkage and visibility of this entity.
bool hasUnwindExceptions() const
Does this runtime use zero-cost exceptions?
Represents a parameter to a function.
void setScopeInfo(unsigned scopeDepth, unsigned parameterIndex)
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
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.
LangAS getAddressSpace() const
Return the address space of this type.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
bool isConstQualified() const
Determine whether this type is const-qualified.
bool isConstantStorage(const ASTContext &Ctx, bool ExcludeCtor, bool ExcludeDtor)
bool hasUnaligned() const
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.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
StringLiteral - This represents a string literal expression, e.g.
unsigned getLength() const
uint32_t getCodeUnit(size_t i) const
StringRef getString() const
unsigned getCharByteWidth() const
Represents the declaration of a struct/union/class/enum.
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...
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool isPointerType() const
bool isReferenceType() const
bool isCUDADeviceBuiltinSurfaceType() const
Check if the type is the CUDA device builtin surface type.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
bool isCUDADeviceBuiltinTextureType() const
Check if the type is the CUDA device builtin texture type.
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
bool isObjCObjectPointerType() const
bool isMemberFunctionPointerType() const
const T * getAs() const
Member-template getAs<specific type>'.
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Expr * getSubExpr() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
TLSKind getTLSKind() const
DefinitionKind isThisDeclarationADefinition(ASTContext &) const
Check whether this declaration is a definition.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
bool hasFlexibleArrayInit(const ASTContext &Ctx) const
Whether this variable has a flexible array member initialized with one or more elements.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
bool hasConstantInitialization() const
Determine whether this variable has constant initialization.
VarDecl * getDefinition(ASTContext &)
Get the real (not just tentative) definition for this declaration.
QualType::DestructionKind needsDestruction(const ASTContext &Ctx) const
Would the destruction of this variable have any effect, and if so, what kind?
const Expr * getInit() const
bool hasExternalStorage() const
Returns true if a variable has extern or private_extern storage.
@ TLS_Dynamic
TLS with a dynamic initializer.
@ TLS_None
Not a TLS variable.
@ DeclarationOnly
This declaration is only a declaration.
@ Definition
This declaration is definitely a definition.
DefinitionKind hasDefinition(ASTContext &) const
Check whether this variable is defined in this translation unit.
TemplateSpecializationKind getTemplateSpecializationKind() const
If this variable is an instantiation of a variable template or a static data member of a class templa...
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
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)
GVALinkage
A more specific kind of linkage than enum Linkage.
@ GVA_AvailableExternally
@ SD_Thread
Thread storage duration.
@ SD_Static
Static storage duration.
bool isLambdaCallOperator(const CXXMethodDecl *MD)
@ Dtor_Complete
Complete object dtor.
LangAS
Defines the address space values used by the address space qualifier of QualType.
@ FirstTargetAddressSpace
TemplateSpecializationKind
Describes the kind of template specialization that a particular template specialization declaration r...
@ TSK_ExplicitInstantiationDefinition
This template specialization was instantiated from a template due to an explicit instantiation defini...
@ TSK_ImplicitInstantiation
This template specialization was implicitly instantiated from a template.
U cast(CodeGen::Address addr)
bool isExternallyVisible(Linkage L)
static bool globalCtorLexOrder()
static bool opFuncArmNewAttr()
static bool getRuntimeFunctionDecl()
static bool weakRefReference()
static bool opFuncOptNoneAttr()
static bool addressSpace()
static bool opFuncMinSizeAttr()
static bool opGlobalUnnamedAddr()
static bool opGlobalThreadLocal()
static bool sourceLanguageCases()
static bool opFuncAstDeclAttr()
static bool opFuncNoDuplicateAttr()
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 attributeNoBuiltin()
static bool opGlobalDLLImportExport()
static bool opGlobalPartition()
static bool opGlobalPragmaClangSection()
static bool opGlobalWeakRef()
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.
unsigned char SizeSizeInBytes
unsigned char PointerAlignInBytes
cir::PointerType allocaInt8PtrTy
void* in alloca address space
cir::PointerType uInt8PtrTy
mlir::ptr::MemorySpaceAttrInterface cirAllocaAddressSpace
cir::PointerType voidPtrTy
void* in address space 0
EvalResult is a struct with detailed info about an evaluated expression.
APValue Val
Val - This is the value the expression can be folded to.
bool hasSideEffects() const
Return true if the evaluated expression has side effects.