19#include "mlir/Dialect/OpenMP/Utils/Utils.h"
20#include "mlir/IR/SymbolTable.h"
23#include "clang/AST/Attrs.inc"
40#include "llvm/ADT/STLExtras.h"
41#include "llvm/ADT/StringExtras.h"
42#include "llvm/ADT/StringRef.h"
43#include "llvm/ADT/StringSwitch.h"
44#include "llvm/Support/raw_ostream.h"
48#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
49#include "mlir/IR/Attributes.h"
50#include "mlir/IR/BuiltinOps.h"
51#include "mlir/IR/Location.h"
52#include "mlir/IR/MLIRContext.h"
53#include "mlir/IR/Operation.h"
54#include "mlir/IR/Verifier.h"
63 case TargetCXXABI::GenericItanium:
64 case TargetCXXABI::GenericAArch64:
65 case TargetCXXABI::AppleARM64:
66 case TargetCXXABI::GenericARM:
68 case TargetCXXABI::Microsoft:
71 case TargetCXXABI::Fuchsia:
72 case TargetCXXABI::iOS:
73 case TargetCXXABI::WatchOS:
74 case TargetCXXABI::GenericMIPS:
75 case TargetCXXABI::WebAssembly:
76 case TargetCXXABI::XL:
77 cgm.
errorNYI(
"createCXXABI: C++ ABI kind");
81 llvm_unreachable(
"invalid C++ ABI kind");
84CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,
88 : builder(mlirContext, *this), astContext(astContext),
89 langOpts(astContext.
getLangOpts()), codeGenOpts(cgo),
90 theModule{
mlir::ModuleOp::create(
mlir::UnknownLoc::get(&mlirContext))},
91 diags(diags), target(astContext.getTargetInfo()),
92 abi(
createCXXABI(*this)), genTypes(*this), vtables(*this) {
120 .toCharUnitsFromBits(
124 const unsigned charSize = target.getCharWidth();
127 const unsigned sizeTypeSize = target.getTypeWidth(target.getSizeType());
135 std::optional<cir::SourceLanguage> sourceLanguage = getCIRSourceLanguage();
138 cir::CIRDialect::getSourceLanguageAttrName(),
139 cir::SourceLanguageAttr::get(&mlirContext, *sourceLanguage));
140 if (langOpts.OpenCL || (langOpts.CUDAIsDevice &&
getTriple().isSPIRV())) {
143 langOpts.OpenCL ? langOpts.getOpenCLCompatibleVersion() : 200;
144 setOpenCLVersionAttr(cir::CIRDialect::getOpenCLVersionAttrName(), version);
145 if (langOpts.OpenCLCPlusPlus)
146 setOpenCLVersionAttr(cir::CIRDialect::getOpenCLCXXVersionAttrName(),
147 langOpts.OpenCLCPlusPlusVersion);
149 theModule->setAttr(cir::CIRDialect::getTripleAttrName(),
150 builder.getStringAttr(
getTriple().str()));
153 theModule->setAttr(cir::CIRDialect::getSizeTypeWidthAttrName(),
154 builder.getI32IntegerAttr(sizeTypeSize));
155 theModule->setAttr(cir::CIRDialect::getIntTypeWidthAttrName(),
156 builder.getI32IntegerAttr(target.getIntWidth()));
162 cir::CIRDialect::getLoweringLangOptionsAttrName(),
163 cir::LoweringLangOptionsAttr::get(
166 langOpts.ThreadsafeStatics,
168 langOpts.CUDAIsDevice,
170 langOpts.GPURelocatableDeviceCode,
171 langOpts.OpenMP != 0,
172 langOpts.OpenMPIsTargetDevice,
174 static_cast<int32_t
>(langOpts.getClangABICompat())));
176 if (cgo.OptimizationLevel > 0 || cgo.OptimizeSize > 0)
177 theModule->setAttr(cir::CIRDialect::getOptInfoAttrName(),
178 cir::OptInfoAttr::get(&mlirContext,
179 cgo.OptimizationLevel,
183 cir::CIRDialect::getDefaultTlsModelAttrName(),
186 if (langOpts.OpenMP) {
187 mlir::omp::OffloadModuleOpts ompOpts(
188 langOpts.OpenMPTargetDebug, langOpts.OpenMPTeamSubscription,
189 langOpts.OpenMPThreadSubscription, langOpts.OpenMPNoThreadState,
190 langOpts.OpenMPNoNestedParallelism, langOpts.OpenMPIsTargetDevice,
191 getTriple().isGPU(), langOpts.OpenMPForceUSM, langOpts.OpenMP,
192 langOpts.OMPHostIRFile, langOpts.OMPTargetTriples, langOpts.NoGPULib);
193 mlir::omp::setOffloadModuleInterfaceAttributes(theModule, ompOpts);
194 mlir::omp::setOpenMPVersionAttribute(theModule, langOpts.OpenMP);
200 createOpenMPRuntime();
205 FileID mainFileId = astContext.getSourceManager().getMainFileID();
207 *astContext.getSourceManager().getFileEntryForID(mainFileId);
210 theModule.setSymName(path);
211 theModule->setLoc(mlir::FileLineColLoc::get(&mlirContext, path,
218 llvm::StringRef cudaBinaryName = codeGenOpts.OffloadBinaryToEmbedFile;
219 if (!cudaBinaryName.empty()) {
220 theModule->setAttr(cir::CIRDialect::getCUDABinaryHandleAttrName(),
221 cir::CUDABinaryHandleAttr::get(
222 &mlirContext, mlir::StringAttr::get(
223 &mlirContext, cudaBinaryName)));
230void CIRGenModule::setOpenCLVersionAttr(StringRef attrName,
unsigned version) {
232 attrName, cir::OpenCLVersionAttr::get(&
getMLIRContext(), version / 100,
233 (version % 100) / 10));
236void CIRGenModule::createCUDARuntime() {
240void CIRGenModule::createOpenMPRuntime() {
241 openMPRuntime = std::make_unique<CIRGenOpenMPRuntime>(*
this);
252 auto &layout = astContext.getASTRecordLayout(rd);
257 return layout.getAlignment();
260 return layout.getNonVirtualAlignment();
265 bool forPointeeType) {
275 if (
unsigned align = tt->getDecl()->getMaxAlignment()) {
278 return astContext.toCharUnitsFromBits(align);
286 t = astContext.getBaseElementType(t);
307 }
else if (forPointeeType && !alignForArray &&
311 alignment = astContext.getTypeAlignInChars(t);
316 if (
unsigned maxAlign = astContext.getLangOpts().MaxTypeAlign) {
318 !astContext.isAlignmentRequired(t))
332 if (theTargetCIRGenInfo)
333 return *theTargetCIRGenInfo;
336 switch (triple.getArch()) {
343 case llvm::Triple::x86_64: {
344 switch (triple.getOS()) {
351 case llvm::Triple::Linux:
353 return *theTargetCIRGenInfo;
356 case llvm::Triple::aarch64:
357 case llvm::Triple::aarch64_32:
358 case llvm::Triple::aarch64_be: {
360 return *theTargetCIRGenInfo;
362 case llvm::Triple::nvptx:
363 case llvm::Triple::nvptx64:
365 return *theTargetCIRGenInfo;
366 case llvm::Triple::amdgpu: {
368 return *theTargetCIRGenInfo;
370 case llvm::Triple::spir:
371 case llvm::Triple::spir64:
372 case llvm::Triple::spirv:
373 case llvm::Triple::spirv32:
374 case llvm::Triple::spirv64:
376 return *theTargetCIRGenInfo;
381 assert(cLoc.
isValid() &&
"expected valid source location");
385 return mlir::FileLineColLoc::get(builder.getStringAttr(filename),
390 assert(cRange.
isValid() &&
"expected a valid source range");
393 mlir::Attribute metadata;
394 return mlir::FusedLoc::get({begin, end}, metadata, builder.getContext());
403 false, isForDefinition);
437 assert(op &&
"expected a valid global op");
445 mlir::Operation *globalValueOp = op;
446 if (
auto gv = dyn_cast<cir::GetGlobalOp>(op)) {
448 assert(globalValueOp &&
"expected a valid global op");
451 if (
auto cirGlobalValue =
452 dyn_cast<cir::CIRGlobalValueInterface>(globalValueOp))
453 if (!cirGlobalValue.isDeclaration())
474 assert(deferredVTables.empty());
484 std::vector<GlobalDecl> curDeclsToEmit;
492 if (
const auto *fd = d.getDecl()->getAsFunction()) {
493 if (langOpts.SYCLIsDevice && fd->hasAttr<SYCLKernelEntryPointAttr>() &&
497 if (!fd->getAttr<SYCLKernelEntryPointAttr>()->isInvalidAttr()) {
524 if (
auto *
attr =
decl->getAttr<AttrT>())
525 return attr->isImplicit();
526 return decl->isImplicit();
531 assert(langOpts.CUDA &&
"Should not be called by non-CUDA languages");
536 return !langOpts.CUDAIsDevice || global->
hasAttr<CUDADeviceAttr>() ||
537 global->
hasAttr<CUDAConstantAttr>() ||
538 global->
hasAttr<CUDASharedAttr>() ||
548 os << (isa<VarDecl>(d) ?
".static." :
".intern.");
550 os << (isa<VarDecl>(d) ?
"__static__" :
"__intern__");
557 "printPostfixForExternalizedDecl: CUID is not specified");
564 if (
const auto *cd = dyn_cast<clang::OpenACCConstructDecl>(gd.
getDecl())) {
572 if (global->hasAttr<WeakRefAttr>())
577 if (global->hasAttr<AliasAttr>()) {
590 "Expected Variable or Function");
591 if (
const auto *
varDecl = dyn_cast<VarDecl>(global)) {
595 }
else if (langOpts.CUDAIsDevice) {
596 const auto *
functionDecl = dyn_cast<FunctionDecl>(global);
597 if ((!global->hasAttr<CUDADeviceAttr>() ||
598 (langOpts.OffloadImplicitHostDeviceTemplates &&
603 !
getASTContext().CUDAImplicitHostDeviceFunUsedByDevice.count(
605 !global->hasAttr<CUDAGlobalAttr>() &&
607 !global->hasAttr<CUDAHostAttr>()))
610 }
else if (!global->hasAttr<CUDAHostAttr>() &&
611 global->hasAttr<CUDADeviceAttr>())
615 if (langOpts.OpenMP) {
617 if (openMPRuntime && openMPRuntime->emitTargetGlobal(gd))
619 if (
auto *drd = dyn_cast<OMPDeclareReductionDecl>(global)) {
624 if (
auto *dmd = dyn_cast<OMPDeclareMapperDecl>(global)) {
631 if (
const auto *fd = dyn_cast<FunctionDecl>(global)) {
634 if (fd->hasAttr<AnnotateAttr>()) {
637 deferredAnnotations[mangledName] = fd;
639 if (!fd->doesThisDeclarationHaveABody()) {
640 if (!fd->doesDeclarationForceExternallyVisibleDefinition() &&
651 assert(vd->isFileVarDecl() &&
"Cannot emit local var decl as global.");
653 !astContext.isMSStaticDataMemberInlineDefinition(vd)) {
657 if (astContext.getInlineVariableDefinitionKind(vd) ==
696 mlir::Operation *op) {
700 cir::FuncOp funcOp = dyn_cast_if_present<cir::FuncOp>(op);
701 if (!funcOp || funcOp.getFunctionType() != funcType) {
707 if (!funcOp.isDeclaration())
719 mlir::OpBuilder::InsertionGuard guard(builder);
724 setNonAliasAttributes(gd, funcOp);
727 auto getPriority = [
this](
const auto *
attr) ->
int {
731 return attr->DefaultPriority;
734 if (
const ConstructorAttr *ca = funcDecl->getAttr<ConstructorAttr>())
736 if (
const DestructorAttr *da = funcDecl->getAttr<DestructorAttr>())
739 if (funcDecl->getAttr<AnnotateAttr>())
742 if (
getLangOpts().OpenMP && funcDecl->hasAttr<OMPDeclareTargetDeclAttr>())
748 std::optional<int> priority) {
757 ctor.setGlobalCtorPriority(priority);
762 std::optional<int> priority) {
763 if (codeGenOpts.RegisterGlobalDtorsWithAtExit &&
765 errorNYI(dtor.getLoc(),
"registerGlobalDtorsWithAtExit");
768 dtor.setGlobalDtorPriority(priority);
794 mlir::ptr::MemorySpaceAttrInterface addrSpace,
795 mlir::Operation *insertPoint) {
800 mlir::OpBuilder::InsertionGuard guard(builder);
806 builder.setInsertionPoint(insertPoint);
812 builder.setInsertionPointToStart(
getModule().getBody());
815 g = cir::GlobalOp::create(builder, loc, name, t, isConstant, addrSpace);
821 mlir::SymbolTable::setSymbolVisibility(
822 g, mlir::SymbolTable::Visibility::Private);
830 if (isa_and_nonnull<NamedDecl>(d))
834 if (
auto gvi = mlir::dyn_cast<cir::CIRGlobalValueInterface>(gv)) {
835 if (d && d->
hasAttr<UsedAttr>())
838 if (
const auto *vd = dyn_cast_if_present<VarDecl>(d);
839 vd && ((codeGenOpts.KeepPersistentStorageVariables &&
840 (vd->getStorageDuration() ==
SD_Static ||
841 vd->getStorageDuration() ==
SD_Thread)) ||
842 (codeGenOpts.KeepStaticConsts &&
844 vd->getType().isConstQualified())))
850static std::vector<std::string>
852 llvm::StringMap<bool> &featureMap) {
853 llvm::StringMap<bool> defaultFeatureMap;
857 std::vector<std::string> delta;
858 for (
const auto &[k, v] : featureMap) {
859 auto defaultIt = defaultFeatureMap.find(k);
860 if (defaultIt == defaultFeatureMap.end() || defaultIt->getValue() != v)
861 delta.push_back((v ?
"+" :
"-") + k.str());
867bool CIRGenModule::getCPUAndFeaturesAttributes(
868 GlobalDecl gd, llvm::StringMap<std::string> &attrs,
869 bool setTargetFeatures) {
875 std::vector<std::string> features;
879 const auto *fd = dyn_cast_or_null<FunctionDecl>(gd.
getDecl());
880 fd = fd ? fd->getMostRecentDecl() : fd;
881 const auto *td = fd ? fd->getAttr<TargetAttr>() :
nullptr;
882 const auto *tv = fd ? fd->getAttr<TargetVersionAttr>() :
nullptr;
883 assert((!td || !tv) &&
"both target_version and target specified");
884 const auto *sd = fd ? fd->getAttr<CPUSpecificAttr>() :
nullptr;
885 const auto *tc = fd ? fd->getAttr<TargetClonesAttr>() :
nullptr;
886 bool addedAttr =
false;
887 if (td || tv || sd || tc) {
888 llvm::StringMap<bool> featureMap;
889 astContext.getFunctionFeatureMap(featureMap, gd);
895 llvm::StringRef featureStr = td ? td->getFeaturesStr() : llvm::StringRef();
898 if (!featureStr.empty()) {
899 clang::ParsedTargetAttr parsedAttr =
901 if (!parsedAttr.
CPU.empty() &&
903 targetCPU = parsedAttr.
CPU;
906 if (!parsedAttr.
Tune.empty() &&
908 tuneCPU = parsedAttr.
Tune;
924 features.reserve(features.size() + featureMap.size());
925 for (
const auto &entry : featureMap)
926 features.push_back((entry.getValue() ?
"+" :
"-") +
927 entry.getKey().str());
932 llvm::StringMap<bool> featureMap;
934 astContext.getFunctionFeatureMap(featureMap, gd);
945 if (!targetCPU.empty()) {
946 attrs[cir::CIRDialect::getTargetCPUAttrName()] = targetCPU.str();
949 if (!tuneCPU.empty()) {
950 attrs[cir::CIRDialect::getTuneCPUAttrName()] = tuneCPU.str();
953 if (!features.empty() && setTargetFeatures) {
954 llvm::erase_if(features, [&](
const std::string &f) {
955 assert(!f.empty() && (f[0] ==
'+' || f[0] ==
'-') &&
956 "feature string must start with '+' or '-'");
959 llvm::sort(features);
960 attrs[cir::CIRDialect::getTargetFeaturesAttrName()] =
961 llvm::join(features,
",");
969void CIRGenModule::setNonAliasAttributes(GlobalDecl gd, mlir::Operation *op) {
974 if (
auto gvi = mlir::dyn_cast<cir::CIRGlobalValueInterface>(op)) {
975 if (
const auto *sa = d->
getAttr<SectionAttr>())
976 gvi.setSection(builder.getStringAttr(sa->getName()));
980 if (
auto func = dyn_cast<cir::FuncOp>(op)) {
981 llvm::StringMap<std::string> attrs;
982 if (getCPUAndFeaturesAttributes(gd, attrs)) {
989 for (llvm::StringRef name :
990 {cir::CIRDialect::getTargetCPUAttrName(),
991 cir::CIRDialect::getTuneCPUAttrName(),
992 cir::CIRDialect::getTargetFeaturesAttrName()})
993 func->removeAttr(name);
994 for (
const auto &[key, val] : attrs)
995 func->setAttr(key, builder.getStringAttr(val));
1005std::optional<cir::SourceLanguage> CIRGenModule::getCIRSourceLanguage()
const {
1006 using ClangStd = clang::LangStandard;
1007 using CIRLang = cir::SourceLanguage;
1010 if (opts.OpenCLCPlusPlus)
1011 return CIRLang::OpenCLCXX;
1013 return CIRLang::OpenCLC;
1015 return CIRLang::CXX;
1016 if (opts.C99 || opts.C11 || opts.C17 || opts.C23 || opts.C2y ||
1017 opts.LangStd == ClangStd::lang_c89 ||
1018 opts.LangStd == ClangStd::lang_gnu89)
1023 errorNYI(
"CIR does not yet support the given source language");
1024 return std::nullopt;
1027LangAS CIRGenModule::getGlobalVarAddressSpace(
const VarDecl *d) {
1028 if (langOpts.OpenCL) {
1036 if (langOpts.SYCLIsDevice &&
1038 errorNYI(
"SYCL global address space");
1040 if (langOpts.CUDA && langOpts.CUDAIsDevice) {
1042 if (d->
hasAttr<CUDAConstantAttr>())
1044 if (d->
hasAttr<CUDASharedAttr>())
1046 if (d->
hasAttr<CUDADeviceAttr>())
1054 if (langOpts.OpenMP)
1055 errorNYI(
"OpenMP global address space");
1068 gv.
setLinkage(cir::GlobalLinkageKind::ExternalWeakLinkage);
1077 auto linkage = cir::GlobalLinkageKind::ExternalWeakLinkage;
1078 func.setLinkage(linkage);
1079 func.setLinkageAttr(
1080 cir::GlobalLinkageKindAttr::get(&cgm.
getMLIRContext(), linkage));
1082 if (!func.isDeclaration())
1083 mlir::SymbolTable::setSymbolVisibility(
1090 for (mlir::Attribute i : indexes) {
1091 auto ind = mlir::cast<mlir::IntegerAttr>(i);
1092 inds.push_back(ind.getValue().getSExtValue());
1098 return view.getSymbol().getValue() == glob.getSymName();
1102 cir::GlobalOp newGlob,
1103 cir::GlobalViewAttr
attr,
1114 mlir::Type newTy = newGlob.getSymType();
1120 return cir::GlobalOffsetAttr::get(
attr.getType(),
attr.getSymbol(),
1121 static_cast<int64_t
>(offset));
1123 cir::PointerType newPtrTy;
1126 newPtrTy = cir::PointerType::get(newTy);
1135 cgm.
errorNYI(
"Unhandled type in createNewGlobalView");
1141 mlir::Attribute oldInit) {
1142 if (
auto oldView = mlir::dyn_cast<cir::GlobalViewAttr>(oldInit))
1147 if (mlir::isa<cir::GlobalOffsetAttr>(oldInit))
1150 auto getNewInitElements =
1151 [&](mlir::ArrayAttr oldElements) -> mlir::ArrayAttr {
1153 for (mlir::Attribute elt : oldElements) {
1154 if (
auto view = mlir::dyn_cast<cir::GlobalViewAttr>(elt))
1156 else if (mlir::isa<cir::ConstArrayAttr, cir::ConstRecordAttr>(elt))
1159 newElements.push_back(elt);
1161 return mlir::ArrayAttr::get(cgm.
getBuilder().getContext(), newElements);
1164 if (
auto oldArray = mlir::dyn_cast<cir::ConstArrayAttr>(oldInit)) {
1170 mlir::Attribute oldElts = oldArray.getElts();
1171 if (mlir::isa<mlir::StringAttr>(oldElts))
1173 mlir::Attribute newElements =
1174 getNewInitElements(mlir::cast<mlir::ArrayAttr>(oldElts));
1176 newElements, mlir::cast<cir::ArrayType>(oldArray.getType()));
1178 if (
auto oldRecord = mlir::dyn_cast<cir::ConstRecordAttr>(oldInit)) {
1179 mlir::ArrayAttr newMembers = getNewInitElements(oldRecord.getMembers());
1180 auto recordTy = mlir::cast<cir::RecordType>(oldRecord.getType());
1186 cgm.
errorNYI(
"Unhandled type in getNewInitValue");
1194 assert(oldGV.getSymName() == newGV.getSymName() &&
"symbol names must match");
1196 mlir::Type oldTy = oldGV.getSymType();
1197 mlir::Type newTy = newGV.getSymType();
1202 assert(oldTy != newTy &&
"expected type change in replaceGlobal");
1205 std::optional<mlir::SymbolTable::UseRange> oldSymUses =
1206 oldGV.getSymbolUses(theModule);
1207 for (mlir::SymbolTable::SymbolUse use : *oldSymUses) {
1208 mlir::Operation *userOp = use.getUser();
1210 (mlir::isa<cir::GetGlobalOp, cir::GlobalOp, cir::ConstantOp>(userOp)) &&
1211 "Unexpected user for global op");
1213 if (
auto getGlobalOp = dyn_cast<cir::GetGlobalOp>(use.getUser())) {
1214 mlir::Value useOpResultValue = getGlobalOp.getAddr();
1215 useOpResultValue.setType(cir::PointerType::get(newTy));
1217 mlir::OpBuilder::InsertionGuard guard(builder);
1218 builder.setInsertionPointAfter(getGlobalOp);
1219 mlir::Type ptrTy = builder.getPointerTo(oldTy);
1221 builder.createBitcast(getGlobalOp->getLoc(), useOpResultValue, ptrTy);
1222 useOpResultValue.replaceAllUsesExcept(
cast,
cast.getDefiningOp());
1223 }
else if (
auto glob = dyn_cast<cir::GlobalOp>(userOp)) {
1224 if (
auto init = glob.getInitialValue()) {
1225 mlir::Attribute nw =
getNewInitValue(*
this, newGV, oldTy, init.value());
1226 glob.setInitialValueAttr(nw);
1228 }
else if (
auto c = dyn_cast<cir::ConstantOp>(userOp)) {
1229 mlir::Attribute init =
getNewInitValue(*
this, newGV, oldTy, c.getValue());
1230 auto typedAttr = mlir::cast<mlir::TypedAttr>(init);
1231 mlir::OpBuilder::InsertionGuard guard(builder);
1232 builder.setInsertionPointAfter(c);
1233 auto newUser = cir::ConstantOp::create(builder, c.getLoc(), typedAttr);
1234 c.replaceAllUsesWith(newUser.getOperation());
1270 cir::GlobalOp entry;
1274 "getOrCreateCIRGlobal: global with non-GlobalOp type");
1279 mlir::ptr::MemorySpaceAttrInterface entryCIRAS = entry.getAddrSpaceAttr();
1285 if (entry.getSymType() == ty &&
1295 if (isForDefinition && !entry.isDeclaration()) {
1297 "getOrCreateCIRGlobal: global with conflicting type");
1305 if (!isForDefinition)
1314 bool isConstant =
false;
1316 QualType declType = d->
getType();
1331 mlir::ptr::MemorySpaceAttrInterface declCIRAS =
1336 cir::GlobalOp gv =
createGlobalOp(loc, mangledName, ty, isConstant, declCIRAS,
1337 entry.getOperation());
1357 if (langOpts.OpenMP && !langOpts.OpenMPSimd)
1359 "getOrCreateCIRGlobal: OpenMP target global variable");
1361 gv.setAlignmentAttr(
getSize(astContext.getDeclAlign(d)));
1372 if (astContext.isMSStaticDataMemberInlineDefinition(d))
1374 "getOrCreateCIRGlobal: MS static data member inline definition");
1378 if (
const SectionAttr *sa = d->
getAttr<SectionAttr>())
1379 gv.setSectionAttr(builder.getStringAttr(sa->getName()));
1383 if (
getTriple().getArch() == llvm::Triple::xcore)
1385 "getOrCreateCIRGlobal: XCore specific ABI requirements");
1395 "getOrCreateCIRGlobal: external const declaration with initializer");
1407 "getOrCreateCIRGlobal: HIP managed attribute");
1442 mlir::Type ptrTy = builder.getPointerTo(g.getSymType(), g.getAddrSpaceAttr());
1443 return cir::GetGlobalOp::create(
1446 g.getStaticLocalGuard().has_value());
1454 cir::PointerType ptrTy =
1455 builder.getPointerTo(globalOp.getSymType(), globalOp.getAddrSpaceAttr());
1456 return builder.getGlobalViewAttr(ptrTy, globalOp);
1460 assert((mlir::isa<cir::FuncOp>(gv.getOperation()) ||
1461 !gv.isDeclarationForLinker()) &&
1462 "Only globals with definition can force usage.");
1467 assert(!gv.isDeclarationForLinker() &&
1468 "Only globals with definition can force usage.");
1473 cir::CIRGlobalValueInterface gv) {
1474 assert((mlir::isa<cir::FuncOp>(gv.getOperation()) ||
1475 !gv.isDeclarationForLinker()) &&
1476 "Only globals with definition can force usage.");
1484 std::vector<cir::CIRGlobalValueInterface> &list) {
1489 mlir::Location loc = builder.getUnknownLoc();
1491 usedArray.resize(list.size());
1492 for (
auto [i, op] : llvm::enumerate(list)) {
1493 usedArray[i] = cir::GlobalViewAttr::get(
1494 cgm.
voidPtrTy, mlir::FlatSymbolRefAttr::get(op.getNameAttr()));
1497 cir::ArrayType arrayTy = cir::ArrayType::get(cgm.
voidPtrTy, usedArray.size());
1499 cir::ConstArrayAttr initAttr = cir::ConstArrayAttr::get(
1500 arrayTy, mlir::ArrayAttr::get(&cgm.
getMLIRContext(), usedArray));
1504 gv.setLinkage(cir::GlobalLinkageKind::AppendingLinkage);
1505 gv.setInitialValueAttr(initAttr);
1506 gv.setSectionAttr(builder.getStringAttr(
"llvm.metadata"));
1518 "emitGlobalVarDefinition: emit OpenCL/OpenMP global variable");
1525 bool isDefinitionAvailableExternally =
1530 if (isDefinitionAvailableExternally &&
1538 mlir::Attribute init;
1539 bool needsGlobalCtor =
false;
1540 bool needsGlobalDtor =
1541 !isDefinitionAvailableExternally &&
1546 std::optional<ConstantEmitter> emitter;
1551 bool isCUDASharedVar =
1556 bool isCUDAShadowVar =
1558 (vd->
hasAttr<CUDAConstantAttr>() || vd->
hasAttr<CUDADeviceAttr>() ||
1559 vd->
hasAttr<CUDASharedAttr>());
1560 bool isCUDADeviceShadowVar =
1566 (isCUDASharedVar || isCUDAShadowVar || isCUDADeviceShadowVar)) {
1568 }
else if (vd->
hasAttr<LoaderUninitializedAttr>()) {
1570 "emitGlobalVarDefinition: loader uninitialized attribute");
1571 }
else if (!initExpr) {
1584 emitter.emplace(*
this);
1585 mlir::Attribute initializer = emitter->tryEmitForInitializer(*initDecl);
1594 "emitGlobalVarDefinition: flexible array initializer");
1596 if (!isDefinitionAvailableExternally)
1597 needsGlobalCtor =
true;
1600 "emitGlobalVarDefinition: static initializer");
1611 mlir::Type initType;
1612 if (mlir::isa<mlir::SymbolRefAttr>(init)) {
1615 "emitGlobalVarDefinition: global initializer is a symbol reference");
1618 assert(mlir::isa<mlir::TypedAttr>(init) &&
"This should have a type");
1619 auto typedInitAttr = mlir::cast<mlir::TypedAttr>(init);
1620 initType = typedInitAttr.getType();
1622 assert(!mlir::isa<mlir::NoneType>(initType) &&
"Should have a type by now");
1628 if (!gv || gv.getSymType() != initType) {
1630 "emitGlobalVarDefinition: global initializer with type mismatch");
1636 if (vd->
hasAttr<AnnotateAttr>())
1649 if (langOpts.CUDA) {
1650 if (langOpts.CUDAIsDevice) {
1653 if (linkage != cir::GlobalLinkageKind::InternalLinkage &&
1655 (vd->
hasAttr<CUDADeviceAttr>() || vd->
hasAttr<CUDAConstantAttr>() ||
1658 gv->setAttr(cir::CUDAExternallyInitializedAttr::getMnemonic(),
1671 emitter->finalize(gv);
1675 gv.setConstant((vd->
hasAttr<CUDAConstantAttr>() && langOpts.CUDAIsDevice) ||
1676 (!needsGlobalCtor && !needsGlobalDtor &&
1681 if (
const SectionAttr *sa = vd->
getAttr<SectionAttr>()) {
1684 gv.setConstant(
true);
1688 gv.setLinkage(linkage);
1692 if (linkage == cir::GlobalLinkageKind::CommonLinkage) {
1694 gv.setConstant(
false);
1699 std::optional<mlir::Attribute> initializer = gv.getInitialValue();
1700 if (initializer && !
getBuilder().isNullValue(*initializer))
1701 gv.setLinkage(cir::GlobalLinkageKind::WeakAnyLinkage);
1704 setNonAliasAttributes(vd, gv);
1712 if (needsGlobalCtor || needsGlobalDtor)
1718 cir::GlobalLinkageKind::AvailableExternallyLinkage)
1724 if (fd->isInlineBuiltinDeclaration())
1727 if (codeGenOpts.OptimizationLevel == 0 && !fd->hasAttr<AlwaysInlineAttr>())
1732 if (
const Module *m = fd->getOwningModule();
1734 getASTContext().getCurrentNamedModule() != m->getTopLevelModule()) {
1735 errorNYI(fd->getSourceRange(),
"should emit function in a named module");
1738 if (fd->hasAttr<NoInlineAttr>())
1749 mlir::Operation *op) {
1751 if (
const auto *fd = dyn_cast<FunctionDecl>(
decl)) {
1755 if (
const auto *method = dyn_cast<CXXMethodDecl>(
decl)) {
1759 abi->emitCXXStructor(gd);
1760 else if (fd->isMultiVersion())
1761 errorNYI(method->getSourceRange(),
"multiversion functions");
1765 if (method->isVirtual())
1771 if (fd->isMultiVersion())
1772 errorNYI(fd->getSourceRange(),
"multiversion functions");
1777 if (
const auto *vd = dyn_cast<VarDecl>(
decl))
1780 llvm_unreachable(
"Invalid argument to CIRGenModule::emitGlobalDefinition");
1794 astContext.getAsConstantArrayType(e->
getType());
1795 uint64_t finalSize = cat->getZExtSize();
1796 str.resize(finalSize);
1798 mlir::Type eltTy =
convertType(cat->getElementType());
1799 return builder.getString(str, eltTy, finalSize,
false);
1804 auto arrayEltTy = mlir::cast<cir::IntType>(arrayTy.getElementType());
1806 uint64_t arraySize = arrayTy.getSize();
1808 assert(arraySize > literalSize &&
1809 "wide string literal array size must have room for null terminator?");
1813 bool isAllZero =
true;
1814 for (
unsigned i = 0; i < literalSize; ++i) {
1822 return cir::ZeroAttr::get(arrayTy);
1826 elements.reserve(arraySize);
1827 for (
unsigned i = 0; i < literalSize; ++i)
1828 elements.push_back(cir::IntAttr::get(arrayEltTy, e->
getCodeUnit(i)));
1830 auto elementsAttr = mlir::ArrayAttr::get(&
getMLIRContext(), elements);
1831 return builder.getConstArray(elementsAttr, arrayTy);
1842 if (d.
hasAttr<SelectAnyAttr>())
1846 if (
auto *vd = dyn_cast<VarDecl>(&d))
1861 llvm_unreachable(
"No such linkage");
1867 if (
auto globalOp = dyn_cast_or_null<cir::GlobalOp>(op)) {
1868 globalOp.setComdat(
true);
1871 funcOp.setComdat(
true);
1877 genTypes.updateCompletedType(td);
1881 replacements[name] = op;
1886 mlir::SymbolUserMap &userMap) {
1887 for (mlir::Operation *user : userMap.getUsers(oldF)) {
1888 auto call = mlir::dyn_cast<cir::CallOp>(user);
1892 for (
auto [argOp, fnArgType] :
1893 llvm::zip(call.getArgs(), newF.getFunctionType().getInputs())) {
1894 if (argOp.getType() != fnArgType)
1903void CIRGenModule::applyReplacements() {
1904 if (replacements.empty())
1910 mlir::SymbolTableCollection symbolTableCollection;
1911 mlir::SymbolUserMap userMap(symbolTableCollection, theModule);
1913 for (
auto &i : replacements) {
1914 StringRef mangledName = i.first;
1915 mlir::Operation *replacement = i.second;
1921 auto newF = dyn_cast<cir::FuncOp>(replacement);
1924 errorNYI(replacement->getLoc(),
"replacement is not a function");
1929 "call argument types do not match replacement function");
1933 userMap.replaceAllUsesWith(oldF, newF.getSymNameAttr());
1934 newF->moveBefore(oldF);
1941 mlir::Location loc, StringRef name, mlir::Type ty,
1943 auto gv = mlir::dyn_cast_or_null<cir::GlobalOp>(
getGlobalValue(name));
1947 if (gv.getSymType() == ty)
1953 assert(gv.isDeclaration() &&
"Declaration has wrong type!");
1955 errorNYI(loc,
"createOrReplaceCXXRuntimeVariable: declaration exists with "
1966 mlir::SymbolTable::setSymbolVisibility(gv,
1970 !gv.hasAvailableExternallyLinkage()) {
1974 gv.setAlignmentAttr(
getSize(alignment));
1985 if ((noCommon || vd->
hasAttr<NoCommonAttr>()) && !vd->
hasAttr<CommonAttr>())
1996 if (vd->
hasAttr<SectionAttr>())
2002 if (vd->
hasAttr<PragmaClangBSSSectionAttr>() ||
2003 vd->
hasAttr<PragmaClangDataSectionAttr>() ||
2004 vd->
hasAttr<PragmaClangRelroSectionAttr>() ||
2005 vd->
hasAttr<PragmaClangRodataSectionAttr>())
2013 if (vd->
hasAttr<WeakImportAttr>())
2023 if (vd->
hasAttr<AlignedAttr>())
2030 for (
const FieldDecl *fd : rd->fields()) {
2031 if (fd->isBitField())
2033 if (fd->hasAttr<AlignedAttr>())
2055cir::GlobalLinkageKind
2059 return cir::GlobalLinkageKind::InternalLinkage;
2062 return cir::GlobalLinkageKind::WeakAnyLinkage;
2066 return cir::GlobalLinkageKind::LinkOnceAnyLinkage;
2071 return cir::GlobalLinkageKind::AvailableExternallyLinkage;
2085 return !astContext.getLangOpts().AppleKext
2086 ? cir::GlobalLinkageKind::LinkOnceODRLinkage
2087 : cir::GlobalLinkageKind::InternalLinkage;
2101 return cir::GlobalLinkageKind::ExternalLinkage;
2104 return dd->
hasAttr<CUDAGlobalAttr>()
2105 ? cir::GlobalLinkageKind::ExternalLinkage
2106 : cir::GlobalLinkageKind::InternalLinkage;
2107 return cir::GlobalLinkageKind::WeakODRLinkage;
2115 return cir::GlobalLinkageKind::CommonLinkage;
2121 if (dd->
hasAttr<SelectAnyAttr>())
2122 return cir::GlobalLinkageKind::WeakODRLinkage;
2126 return cir::GlobalLinkageKind::ExternalLinkage;
2138 mlir::Operation *old, cir::FuncOp newFn) {
2140 auto oldFn = mlir::dyn_cast<cir::FuncOp>(old);
2148 unsigned numInherentAttrs = 0;
2149 oldFn->getName().walkInherentAttrs(
2150 oldFn, [&](llvm::StringRef, mlir::Attribute &
attr) {
2153 if (numInherentAttrs <= 1)
2155 "replaceUsesOfNonProtoTypeWithRealFunction: Attribute forwarding");
2158 newFn.setNoProto(oldFn.getNoProto());
2161 std::optional<mlir::SymbolTable::UseRange> symUses =
2162 oldFn.getSymbolUses(oldFn->getParentOp());
2167 for (
const mlir::SymbolTable::SymbolUse &use : symUses.value()) {
2168 mlir::OpBuilder::InsertionGuard guard(builder);
2170 if (
auto noProtoCallOp = mlir::dyn_cast<cir::CallOp>(use.getUser())) {
2171 builder.setInsertionPoint(noProtoCallOp);
2174 cir::FuncType newFnType = newFn.getFunctionType();
2175 mlir::OperandRange callOperands = noProtoCallOp.getOperands();
2176 bool returnTypeMatches =
2177 newFnType.hasVoidReturn()
2178 ? noProtoCallOp.getNumResults() == 0
2179 : noProtoCallOp.getNumResults() == 1 &&
2180 noProtoCallOp.getResultTypes().front() ==
2181 newFnType.getReturnType();
2182 bool typesMatch = !newFn.getNoProto() && returnTypeMatches &&
2183 callOperands.size() == newFnType.getNumInputs();
2184 for (
unsigned i = 0, e = newFnType.getNumInputs(); typesMatch && i != e;
2186 if (callOperands[i].
getType() != newFnType.getInput(i))
2190 cir::CallOp realCallOp;
2194 builder.createCallOp(noProtoCallOp.getLoc(), newFn, callOperands);
2198 cir::FuncType origFnType = oldFn.getFunctionType();
2199 cir::FuncType callFnType =
2200 origFnType.isVarArg()
2201 ? cir::FuncType::get(origFnType.getInputs(),
2202 origFnType.getReturnType(),
2205 mlir::Value addr = cir::GetGlobalOp::create(
2206 builder, noProtoCallOp.getLoc(), cir::PointerType::get(newFnType),
2207 newFn.getSymName());
2208 mlir::Value casted =
2209 builder.createBitcast(addr, cir::PointerType::get(callFnType));
2210 realCallOp = builder.createIndirectCallOp(
2211 noProtoCallOp.getLoc(), casted, callFnType, callOperands);
2215 noProtoCallOp.replaceAllUsesWith(realCallOp);
2216 noProtoCallOp.erase();
2217 }
else if (
auto getGlobalOp =
2218 mlir::dyn_cast<cir::GetGlobalOp>(use.getUser())) {
2225 mlir::Value res = getGlobalOp.getAddr();
2226 const mlir::Type oldResTy = res.getType();
2227 const auto newPtrTy = cir::PointerType::get(newFn.getFunctionType());
2228 if (oldResTy != newPtrTy) {
2229 res.setType(newPtrTy);
2230 builder.setInsertionPointAfter(getGlobalOp.getOperation());
2231 mlir::Value castRes =
2232 cir::CastOp::create(builder, getGlobalOp.getLoc(), oldResTy,
2233 cir::CastKind::bitcast, res);
2234 res.replaceAllUsesExcept(castRes, castRes.getDefiningOp());
2236 }
else if (mlir::isa<cir::GlobalOp>(use.getUser())) {
2242 "replaceUsesOfNonProtoTypeWithRealFunction: unexpected use type");
2247cir::GlobalLinkageKind
2249 GVALinkage linkage = astContext.GetGVALinkageForVariable(vd);
2256 GVALinkage linkage = astContext.GetGVALinkageForFunction(d);
2258 if (
const auto *dtor = dyn_cast<CXXDestructorDecl>(d))
2267 StringRef globalName,
CharUnits alignment) {
2272 cir::GlobalOp gv = cgm.
createGlobalOp(loc, globalName, c.getType(),
2276 gv.setAlignmentAttr(cgm.
getSize(alignment));
2278 cir::GlobalLinkageKindAttr::get(cgm.
getBuilder().getContext(), lt));
2282 if (gv.isWeakForLinker()) {
2283 assert(cgm.
supportsCOMDAT() &&
"Only COFF uses weak string literals");
2286 cgm.
setDSOLocal(
static_cast<mlir::Operation *
>(gv));
2307 std::string result =
2318 astContext.getAlignOfGlobalVarInChars(s->
getType(),
nullptr);
2326 if (!gv.getAlignment() ||
2327 uint64_t(alignment.
getQuantity()) > *gv.getAlignment())
2328 gv.setAlignmentAttr(
getSize(alignment));
2333 if (
getCXXABI().getMangleContext().shouldMangleStringLiteral(s) &&
2336 "getGlobalForStringLiteral: mangle string literals");
2346 : builder.getUnknownLoc();
2347 auto typedC = llvm::cast<mlir::TypedAttr>(c);
2349 cir::GlobalLinkageKind::PrivateLinkage, *
this,
2350 uniqueName, alignment);
2364 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(gv.getSymType());
2365 assert(arrayTy &&
"String literal must be array");
2369 return builder.getGlobalViewAttr(ptrTy, gv);
2398 "emitExplicitCastExprType");
2404 auto ty = mlir::cast<cir::MethodType>(
convertType(destTy));
2405 return builder.getNullMethodAttr(ty);
2408 auto ty = mlir::cast<cir::DataMemberType>(
convertType(destTy));
2409 return builder.getNullDataMemberAttr(ty);
2420 if (
const auto *methodDecl = dyn_cast<CXXMethodDecl>(
decl)) {
2422 if (methodDecl->isVirtual())
2423 return cir::ConstantOp::create(
2424 builder, loc,
getCXXABI().buildVirtualMethodAttr(ty, methodDecl));
2430 return cir::ConstantOp::create(builder, loc,
2431 builder.getMethodAttr(ty, methodFuncOp));
2446 assert(
fieldDecl->getParent() == destClass &&
2447 "scalar member pointer should be relative to the declaring class");
2449 astContext.toCharUnitsFromBits(astContext.getFieldOffset(
fieldDecl))
2451 return cir::ConstantOp::create(builder, loc,
2452 cir::DataMemberOffsetAttr::get(ty, offset));
2455 std::optional<llvm::SmallVector<int32_t>> path =
2459 return cir::ConstantOp::create(builder, loc,
2460 builder.getDataMemberAttr(ty, *path));
2463std::optional<llvm::SmallVector<int32_t>>
2471 if (
const auto *indirectField = dyn_cast<IndirectFieldDecl>(
decl)) {
2473 for (
const NamedDecl *nd : indirectField->chain()) {
2475 if (!findFieldMemberPath(currentClass, field, path))
2476 return std::nullopt;
2477 currentClass = field->getType()->getAsCXXRecordDecl();
2483 return std::nullopt;
2487bool CIRGenModule::findFieldMemberPath(
const CXXRecordDecl *currentClass,
2497 if (currentClass->
isUnion()) {
2503 "data member pointer for non-zero-initializable union");
2510 path.push_back(fieldIdx);
2518 for (
const CXXBaseSpecifier &base : currentClass->
bases()) {
2519 const auto *baseDecl =
2522 if (base.isVirtual()) {
2527 llvm::SmallVector<int32_t> discardedPath;
2528 if (findFieldMemberPath(baseDecl, field, discardedPath)) {
2530 "data member pointer through virtual base");
2543 path.push_back(baseFieldIdx);
2544 if (findFieldMemberPath(baseDecl, field, path))
2572 if (
auto *oid = dyn_cast<ObjCImplDecl>(
decl))
2573 errorNYI(oid->getSourceRange(),
"emitDeclConext: ObjCImplDecl");
2583 if (
decl->isTemplated())
2586 switch (
decl->getKind()) {
2589 decl->getDeclKindName());
2592 case Decl::CXXConversion:
2593 case Decl::CXXMethod:
2594 case Decl::Function: {
2597 if (!fd->isConsteval())
2606 case Decl::Decomposition:
2607 case Decl::VarTemplateSpecialization: {
2609 if (
auto *decomp = dyn_cast<DecompositionDecl>(
decl))
2610 for (
auto *binding : decomp->flat_bindings())
2611 if (
auto *holdingVar = binding->getHoldingVar())
2615 case Decl::OpenACCRoutine:
2618 case Decl::OpenACCDeclare:
2621 case Decl::OMPThreadPrivate:
2624 case Decl::OMPGroupPrivate:
2627 case Decl::OMPAllocate:
2630 case Decl::OMPCapturedExpr:
2633 case Decl::OMPDeclareReduction:
2636 case Decl::OMPDeclareMapper:
2639 case Decl::OMPRequires:
2644 case Decl::UsingDirective:
2645 case Decl::UsingEnum:
2646 case Decl::NamespaceAlias:
2648 case Decl::TypeAlias:
2655 case Decl::IndirectField:
2659 case Decl::ClassTemplate:
2661 case Decl::CXXDeductionGuide:
2663 case Decl::ExplicitInstantiation:
2664 case Decl::FunctionTemplate:
2665 case Decl::StaticAssert:
2666 case Decl::TypeAliasTemplate:
2667 case Decl::UsingShadow:
2668 case Decl::VarTemplate:
2669 case Decl::VarTemplatePartialSpecialization:
2672 case Decl::CXXConstructor:
2675 case Decl::CXXDestructor:
2680 case Decl::LinkageSpec:
2681 case Decl::Namespace:
2685 case Decl::ClassTemplateSpecialization:
2686 case Decl::CXXRecord: {
2689 for (
auto *childDecl : crd->
decls())
2695 case Decl::FileScopeAsm:
2697 if (langOpts.CUDA && langOpts.CUDAIsDevice)
2700 if (langOpts.OpenMPIsTargetDevice)
2703 if (langOpts.SYCLIsDevice)
2706 std::string line = file_asm->getAsmString();
2707 globalScopeAsm.push_back(builder.getStringAttr(line));
2714 op.setInitialValueAttr(value);
2728 md->getParent()->getNumVBases() == 0)
2730 "getAddrAndTypeOfCXXStructor: MS ABI complete destructor");
2741 false, isForDefinition);
2743 return {fnType, fn};
2747 mlir::Type funcType,
bool forVTable,
2751 "consteval function should never be emitted");
2761 if (
const auto *dd = dyn_cast<CXXDestructorDecl>(gd.
getDecl())) {
2764 dd->getParent()->getNumVBases() == 0)
2766 "getAddrOfFunction: MS ABI complete destructor");
2772 false, isForDefinition);
2774 if (langOpts.CUDA && !langOpts.CUDAIsDevice &&
2780 bool isHIPHandle = mlir::isa<cir::GlobalOp>(*handle);
2781 if (isForDefinition || isHIPHandle)
2783 return mlir::dyn_cast<cir::FuncOp>(*handle);
2792 llvm::raw_svector_ostream
out(buffer);
2801 assert(ii &&
"Attempt to mangle unnamed decl.");
2803 const auto *fd = dyn_cast<FunctionDecl>(nd);
2807 }
else if (fd && fd->hasAttr<CUDAGlobalAttr>() &&
2811 DeviceKernelAttr::isOpenCLSpelling(
2812 fd->getAttr<DeviceKernelAttr>()) &&
2829 if (
const auto *fd = dyn_cast<FunctionDecl>(nd)) {
2830 if (fd->isMultiVersion()) {
2832 "getMangledName: multi-version functions");
2837 "getMangledName: GPU relocatable device code");
2840 return std::string(
out.str());
2843static FunctionDecl *
2858 if (
auto *methodDecl = dyn_cast<CXXMethodDecl>(protoFunc);
2859 methodDecl && methodDecl->isImplicitObjectMemberFunction()) {
2861 paramTypes.insert(paramTypes.begin(), methodDecl->getThisType());
2864 fpt->getExtProtoInfo());
2875 params.reserve(fpt->getNumParams());
2878 for (
unsigned i = 0, e = fpt->getNumParams(); i != e; ++i) {
2882 nullptr, fpt->getParamType(i),
nullptr,
2885 params.push_back(parm);
2888 tempFunc->setParams(params);
2913 if (
const auto *cd = dyn_cast<CXXConstructorDecl>(canonicalGd.
getDecl())) {
2916 "getMangledName: C++ constructor without variants");
2925 if (!langOpts.CUDAIsDevice || !astContext.mayExternalize(gd.
getDecl())) {
2926 auto foundName = mangledDeclNames.find(canonicalGd);
2927 if (foundName != mangledDeclNames.end())
2928 return foundName->second;
2935 auto result = manglings.insert(std::make_pair(mangledName, gd));
2936 return mangledDeclNames[canonicalGd] = result.first->first();
2940 assert(!d->
getInit() &&
"Cannot emit definite definitions here!");
2948 if (gv && !mlir::cast<cir::GlobalOp>(gv).isDeclaration())
2964 if (langOpts.EmitAllDecls)
2967 const auto *vd = dyn_cast<VarDecl>(global);
2969 ((codeGenOpts.KeepPersistentStorageVariables &&
2970 (vd->getStorageDuration() ==
SD_Static ||
2971 vd->getStorageDuration() ==
SD_Thread)) ||
2972 (codeGenOpts.KeepStaticConsts && vd->getStorageDuration() ==
SD_Static &&
2973 vd->getType().isConstQualified())))
2986 if (langOpts.OpenMP >= 50 && !langOpts.OpenMPSimd) {
2987 std::optional<OMPDeclareTargetDeclAttr *> activeAttr =
2988 OMPDeclareTargetDeclAttr::getActiveAttr(global);
2989 if (!activeAttr || (*activeAttr)->getLevel() != (
unsigned)-1)
2993 const auto *fd = dyn_cast<FunctionDecl>(global);
3000 if (fd->hasAttr<TargetVersionAttr>() && !fd->isMultiVersion())
3002 if (langOpts.SYCLIsDevice) {
3003 errorNYI(fd->getSourceRange(),
"mayBeEmittedEagerly: SYCL");
3007 const auto *vd = dyn_cast<VarDecl>(global);
3009 if (astContext.getInlineVariableDefinitionKind(vd) ==
3017 if (langOpts.OpenMP && langOpts.OpenMPUseTLS &&
3018 astContext.getTargetInfo().isTLSSupported() &&
isa<VarDecl>(global) &&
3020 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(global))
3023 assert((fd || vd) &&
3024 "Only FunctionDecl and VarDecl should hit this path so far.");
3029 cir::CIRGlobalValueInterface gv) {
3030 if (gv.hasLocalLinkage())
3033 if (!gv.hasDefaultVisibility() && !gv.hasExternalWeakLinkage())
3041 const llvm::Triple &tt = cgm.
getTriple();
3043 if (tt.isOSCygMing()) {
3052 cgm.
errorNYI(
"shouldAssumeDSOLocal: MinGW");
3058 if (tt.isOSBinFormatCOFF() && gv.hasExternalWeakLinkage())
3066 if (tt.isOSBinFormatCOFF() || (tt.isOSWindows() && tt.isOSBinFormatMachO()))
3070 if (!tt.isOSBinFormatELF())
3075 if (rm != llvm::Reloc::Static && !lOpts.PIE) {
3083 return !(lOpts.SemanticInterposition || lOpts.HalfNoSemanticInterposition);
3087 if (!gv.isDeclarationForLinker())
3093 if (rm == llvm::Reloc::PIC_ && gv.hasExternalWeakLinkage())
3100 if (cgOpts.DirectAccessExternalData) {
3106 if (
auto globalOp = dyn_cast<cir::GlobalOp>(gv.getOperation())) {
3132 if (gv.hasLocalLinkage()) {
3133 gv.setGlobalVisibility(cir::VisibilityKind::Default);
3148 d->
hasAttr<OMPDeclareTargetDeclAttr>() &&
3149 d->
getAttr<OMPDeclareTargetDeclAttr>()->getDevType() !=
3150 OMPDeclareTargetDeclAttr::DT_NoHost &&
3152 llvm_unreachable(
"setGlobalVisibility: OpenMP is NYI");
3161 !d->
hasAttr<OMPDeclareTargetDeclAttr>()) {
3162 bool needsProtected =
false;
3166 }
else if (
const auto *vd = dyn_cast<VarDecl>(d)) {
3167 needsProtected = vd->hasAttr<CUDADeviceAttr>() ||
3168 vd->hasAttr<CUDAConstantAttr>() ||
3169 vd->getType()->isCUDADeviceBuiltinSurfaceType() ||
3170 vd->getType()->isCUDADeviceBuiltinTextureType();
3172 if (needsProtected) {
3173 gv.setGlobalVisibility(cir::VisibilityKind::Protected);
3179 gv.setGlobalVisibility(cir::VisibilityKind::Hidden);
3186 !gv.isDeclarationForLinker())
3195 if (
auto globalValue = dyn_cast<cir::CIRGlobalValueInterface>(op))
3214 auto res = manglings.find(mangledName);
3215 if (res == manglings.end())
3217 result = res->getValue();
3222 return llvm::StringSwitch<cir::TLSModel>(S)
3223 .Case(
"global-dynamic", cir::TLSModel::GeneralDynamic)
3224 .Case(
"local-dynamic", cir::TLSModel::LocalDynamic)
3225 .Case(
"initial-exec", cir::TLSModel::InitialExec)
3226 .Case(
"local-exec", cir::TLSModel::LocalExec);
3232 return cir::TLSModel::GeneralDynamic;
3234 return cir::TLSModel::LocalDynamic;
3236 return cir::TLSModel::InitialExec;
3238 return cir::TLSModel::LocalExec;
3240 llvm_unreachable(
"Invalid TLS model!");
3244 bool isExtendingDecl) {
3245 assert(d.
getTLSKind() &&
"setting TLS mode on non-TLS var!");
3254 global.setTlsModel(tlm);
3264 if (isExtendingDecl)
3272 cir::FuncOp func,
bool isThunk) {
3274 cir::CallingConv callingConv;
3281 mlir::NamedAttrList pal{};
3282 std::vector<mlir::NamedAttrList> argAttrs(info.arguments().size());
3283 mlir::NamedAttrList retAttrs{};
3285 retAttrs, callingConv,
3288 for (mlir::NamedAttribute
attr : pal)
3289 func->setAttr(
attr.getName(),
attr.getValue());
3291 llvm::for_each(llvm::enumerate(argAttrs), [func](
auto idx_arg_pair) {
3292 mlir::function_interface_impl::setArgAttrs(func, idx_arg_pair.index(),
3293 idx_arg_pair.value());
3295 if (!retAttrs.empty())
3296 mlir::function_interface_impl::setResultAttrs(func, 0, retAttrs);
3300 func.setCallingConv(callingConv);
3305 bool isIncompleteFunction,
3313 if (!isIncompleteFunction)
3315 getTypes().arrangeGlobalDeclaration(globalDecl),
3318 if (!isIncompleteFunction && func.isDeclaration())
3325 if (funcDecl->isInlineBuiltinDeclaration()) {
3327 bool hasBody = funcDecl->
hasBody(fdBody);
3329 assert(hasBody &&
"Inline builtin declarations should always have an "
3334 if (funcDecl->isReplaceableGlobalAllocationFunction()) {
3337 func->setAttr(cir::CIRDialect::getNoBuiltinAttrName(),
3348 f->setAttr(cir::CIRDialect::getNoThrowAttrName(),
3351 std::optional<cir::InlineKind> existingInlineKind = f.getInlineKind();
3353 existingInlineKind && *existingInlineKind == cir::InlineKind::NoInline;
3354 bool isAlwaysInline = existingInlineKind &&
3355 *existingInlineKind == cir::InlineKind::AlwaysInline;
3359 if (!isAlwaysInline &&
3364 f.setInlineKind(cir::InlineKind::NoInline);
3379 if (
decl->hasAttr<NoInlineAttr>() && !isAlwaysInline) {
3381 f.setInlineKind(cir::InlineKind::NoInline);
3382 }
else if (
decl->hasAttr<AlwaysInlineAttr>() && !isNoInline) {
3385 f.setInlineKind(cir::InlineKind::AlwaysInline);
3389 if (!isAlwaysInline)
3390 f.setInlineKind(cir::InlineKind::NoInline);
3395 if (
auto *fd = dyn_cast<FunctionDecl>(
decl)) {
3400 auto checkRedeclForInline = [](
const FunctionDecl *redecl) {
3401 return redecl->isInlineSpecified();
3403 if (any_of(
decl->redecls(), checkRedeclForInline))
3408 return any_of(pattern->
redecls(), checkRedeclForInline);
3410 if (checkForInline(fd)) {
3411 f.setInlineKind(cir::InlineKind::InlineHint);
3412 }
else if (codeGenOpts.getInlining() ==
3414 !fd->isInlined() && !isAlwaysInline) {
3415 f.setInlineKind(cir::InlineKind::NoInline);
3422 std::optional<uint64_t> explicitAlignment;
3423 if (
unsigned alignment =
3425 explicitAlignment = alignment;
3426 else if (langOpts.FunctionAlignment)
3427 explicitAlignment = 1ull << langOpts.FunctionAlignment;
3429 if (explicitAlignment) {
3430 f.setAlignment(*explicitAlignment);
3431 f.setPreferredAlignment(*explicitAlignment);
3432 }
else if (langOpts.PreferredFunctionAlignment) {
3433 f.setPreferredAlignment(langOpts.PreferredFunctionAlignment);
3450static cir::LangAddressSpace
3452 switch (addressSpace) {
3454 return cir::LangAddressSpace::OffloadGlobal;
3456 return cir::LangAddressSpace::OffloadConstant;
3458 return cir::LangAddressSpace::OffloadLocal;
3460 return cir::LangAddressSpace::OffloadGeneric;
3462 return cir::LangAddressSpace::OffloadGlobalDevice;
3464 return cir::LangAddressSpace::OffloadGlobalHost;
3468 return cir::LangAddressSpace::Default;
3474 assert(fd &&
"expected a kernel function declaration");
3487 argNames.push_back(builder.getStringAttr(param->getName()));
3490 std::string typeQuals;
3492 if (
type->isImageType() ||
type->isPipeType()) {
3494 "OpenCL kernel argument metadata for image and pipe types");
3498 accessQuals.push_back(builder.getStringAttr(
"none"));
3500 auto getTypeSpelling = [&](
QualType paramType) {
3501 std::string typeName = paramType.getUnqualifiedType().getAsString(policy);
3503 if (paramType.isCanonical()) {
3504 StringRef typeNameRef = typeName;
3505 if (typeNameRef.consume_front(
"unsigned "))
3506 return std::string(
"u") + typeNameRef.str();
3507 if (typeNameRef.consume_front(
"signed "))
3508 return typeNameRef.str();
3516 if (
type->isPointerType()) {
3518 addressQuals.push_back(cir::LangAddressSpaceAttr::get(
3522 argTypeNames.push_back(
3523 builder.getStringAttr(getTypeSpelling(pointeeType) +
"*"));
3524 argBaseTypeNames.push_back(builder.getStringAttr(
3527 if (
type.isRestrictQualified())
3528 typeQuals =
"restrict";
3531 typeQuals += typeQuals.empty() ?
"const" :
" const";
3533 typeQuals += typeQuals.empty() ?
"volatile" :
" volatile";
3535 addressQuals.push_back(cir::LangAddressSpaceAttr::get(
3538 argTypeNames.push_back(builder.getStringAttr(getTypeSpelling(
type)));
3539 argBaseTypeNames.push_back(
3540 builder.getStringAttr(getTypeSpelling(
type.getCanonicalType())));
3543 argTypeQuals.push_back(builder.getStringAttr(typeQuals));
3546 mlir::ArrayAttr names;
3548 names = builder.getArrayAttr(argNames);
3550 mlir::Attribute metadata = cir::OpenCLKernelArgMetadataAttr::get(
3551 func.getContext(), builder.getArrayAttr(addressQuals),
3552 builder.getArrayAttr(accessQuals), builder.getArrayAttr(argTypeNames),
3553 builder.getArrayAttr(argBaseTypeNames),
3554 builder.getArrayAttr(argTypeQuals), names);
3555 func->setAttr(cir::CIRDialect::getOpenCLKernelArgMetadataAttrName(),
3560 StringRef mangledName, mlir::Type funcType,
GlobalDecl gd,
bool forVTable,
3562 mlir::NamedAttrList extraAttrs) {
3565 if (
const auto *fd = cast_or_null<FunctionDecl>(d)) {
3567 if (
getLangOpts().OpenMPIsTargetDevice && openMPRuntime &&
3569 !dontDefer && !isForDefinition) {
3572 if (
const auto *cd = dyn_cast<CXXConstructorDecl>(fdDef))
3574 else if (
const auto *dd = dyn_cast<CXXDestructorDecl>(fdDef))
3584 if (fd->isMultiVersion())
3585 errorNYI(fd->getSourceRange(),
"getOrCreateCIRFunction: multi-version");
3591 assert(mlir::isa<cir::FuncOp>(entry));
3596 if (d && !d->
hasAttr<DLLImportAttr>() && !d->
hasAttr<DLLExportAttr>()) {
3604 if (isForDefinition && fn && !fn.isDeclaration()) {
3611 diagnosedConflictingDefinitions.insert(gd).second) {
3615 diag::note_previous_definition);
3619 if (fn && fn.getFunctionType() == funcType) {
3623 if (!isForDefinition) {
3631 auto *funcDecl = llvm::cast_or_null<FunctionDecl>(gd.
getDecl());
3632 bool invalidLoc = !funcDecl ||
3633 funcDecl->getSourceRange().getBegin().isInvalid() ||
3634 funcDecl->getSourceRange().getEnd().isInvalid();
3636 invalidLoc ? theModule->getLoc() :
getLoc(funcDecl->getSourceRange()),
3637 mangledName, mlir::cast<cir::FuncType>(funcType), funcDecl);
3639 if (funcDecl && funcDecl->hasAttr<AnnotateAttr>())
3640 deferredAnnotations[mangledName] = funcDecl;
3651 auto symbolOp = mlir::cast<mlir::SymbolOpInterface>(entry);
3659 if (symbolOp.getSymbolUses(symbolOp->getParentOp()))
3669 if (!extraAttrs.empty())
3670 for (mlir::NamedAttribute attr : extraAttrs)
3671 if (!funcOp->hasDiscardableAttr(
attr.getName()))
3672 funcOp->setDiscardableAttr(
attr.getName(),
attr.getValue());
3678 assert(funcOp.getFunctionType() == funcType);
3685 if (isa_and_nonnull<CXXDestructorDecl>(d) &&
3715 fd = fd->getPreviousDecl()) {
3717 if (fd->doesThisDeclarationHaveABody()) {
3730 cir::FuncType funcType,
3734 mlir::OpBuilder::InsertionGuard guard(builder);
3739 builder.setInsertionPointToEnd(theModule.getBody());
3741 func = cir::FuncOp::create(builder, loc, name, funcType);
3748 func.setNoProto(
true);
3750 assert(func.isDeclaration() &&
"expected empty body");
3754 func.setLinkageAttr(cir::GlobalLinkageKindAttr::get(
3756 mlir::SymbolTable::setSymbolVisibility(
3757 func, mlir::SymbolTable::Visibility::Private);
3768 for (
const auto *
attr :
3782 fnOp.setBuiltin(
true);
3788 return cir::CtorKind::Default;
3790 return cir::CtorKind::Copy;
3792 return cir::CtorKind::Move;
3793 return cir::CtorKind::Custom;
3798 return cir::AssignKind::Copy;
3800 return cir::AssignKind::Move;
3801 llvm_unreachable(
"not a copy or move assignment operator");
3809 if (
const auto *dtor = dyn_cast<CXXDestructorDecl>(funcDecl)) {
3810 auto cxxDtor = cir::CXXDtorAttr::get(
3813 funcOp.setFuncInfoAttr(cxxDtor);
3817 if (
const auto *ctor = dyn_cast<CXXConstructorDecl>(funcDecl)) {
3819 auto cxxCtor = cir::CXXCtorAttr::get(
3821 kind, ctor->isTrivial());
3822 funcOp.setFuncInfoAttr(cxxCtor);
3826 const auto *method = dyn_cast<CXXMethodDecl>(funcDecl);
3827 if (method && (method->isCopyAssignmentOperator() ||
3828 method->isMoveAssignmentOperator())) {
3830 auto cxxAssign = cir::CXXAssignAttr::get(
3832 assignKind, method->isTrivial());
3833 funcOp.setFuncInfoAttr(cxxAssign);
3843 bool inStdNamespace = method ? method->getParent()->isInStdNamespace()
3845 if (!inStdNamespace)
3851 std::optional<cir::KnownFuncKind>
kind;
3853 kind = llvm::StringSwitch<std::optional<cir::KnownFuncKind>>(
3855 .Case(cir::StdFindOp::getFunctionName(),
3856 cir::StdFindOp::getFuncKind())
3857 .Default(std::nullopt);
3866 cir::FuncOp funcOp, StringRef name) {
3882 mlir::NamedAttrList extraAttrs,
3884 bool assumeConvergent) {
3885 if (assumeConvergent)
3886 errorNYI(
"createRuntimeFunction: assumeConvergent");
3896 entry.setDSOLocal(
true);
3902mlir::SymbolTable::Visibility
3906 if (op.isDeclaration())
3907 return mlir::SymbolTable::Visibility::Private;
3911mlir::SymbolTable::Visibility
3914 case cir::GlobalLinkageKind::InternalLinkage:
3915 case cir::GlobalLinkageKind::PrivateLinkage:
3916 return mlir::SymbolTable::Visibility::Private;
3917 case cir::GlobalLinkageKind::ExternalLinkage:
3918 case cir::GlobalLinkageKind::ExternalWeakLinkage:
3919 case cir::GlobalLinkageKind::LinkOnceODRLinkage:
3920 case cir::GlobalLinkageKind::AvailableExternallyLinkage:
3921 case cir::GlobalLinkageKind::CommonLinkage:
3922 case cir::GlobalLinkageKind::WeakAnyLinkage:
3923 case cir::GlobalLinkageKind::WeakODRLinkage:
3924 return mlir::SymbolTable::Visibility::Public;
3926 llvm::errs() <<
"visibility not implemented for '"
3927 << stringifyGlobalLinkageKind(glk) <<
"'\n";
3928 assert(0 &&
"not implemented");
3931 llvm_unreachable(
"linkage should be handled above!");
3937 applyReplacements();
3939 theModule->setAttr(cir::CIRDialect::getModuleLevelAsmAttrName(),
3940 builder.getArrayAttr(globalScopeAsm));
3942 emitGlobalAnnotations();
3944 if (!recordLayoutEntries.empty())
3946 cir::CIRDialect::getRecordLayoutsAttrName(),
3947 mlir::DictionaryAttr::get(&
getMLIRContext(), recordLayoutEntries));
3956 std::string cuidName =
3959 auto loc = builder.getUnknownLoc();
3960 mlir::ptr::MemorySpaceAttrInterface addrSpace =
3962 getGlobalVarAddressSpace(
nullptr));
3966 gv.setLinkage(cir::GlobalLinkageKind::ExternalLinkage);
3968 auto zeroAttr = cir::IntAttr::get(int8Ty, 0);
3969 gv.setInitialValueAttr(zeroAttr);
3971 mlir::SymbolTable::setSymbolVisibility(
3972 gv, mlir::SymbolTable::Visibility::Public);
3977 if (astContext.getLangOpts().CUDA && cudaRuntime)
3985 if (langOpts.CPlusPlusModules &&
3988 if (
clang::Module *primary = astContext.getCurrentNamedModule();
3991 llvm::raw_svector_ostream
out(fnName);
3993 .mangleModuleInitializer(primary,
out);
3994 theModule->setAttr(cir::CIRDialect::getCXXModuleInitFnNameAttrName(),
3995 builder.getStringAttr(fnName));
4009 const AliasAttr *aa = d->
getAttr<AliasAttr>();
4010 assert(aa &&
"Not an alias?");
4014 if (aa->getAliasee() == mangledName) {
4015 diags.Report(aa->getLocation(), diag::err_cyclic_alias) << 0;
4023 auto entryGV = mlir::dyn_cast<cir::CIRGlobalValueInterface>(entry);
4024 if (entryGV && entryGV.isDefinition())
4037 cir::GlobalLinkageKind linkage;
4049 cir::CIRGlobalValueInterface alias =
4050 isFunction ? mlir::cast<cir::CIRGlobalValueInterface>(
4052 mlir::cast<cir::FuncType>(declTy),
4055 : mlir::cast<cir::CIRGlobalValueInterface>(
4066 entry, mlir::cast<cir::FuncOp>(alias.getOperation()));
4074 linkage = cir::GlobalLinkageKind::WeakAnyLinkage;
4078 mlir::SymbolTable::Visibility visibility =
4081 alias.setAliasee(aa->getAliasee());
4082 alias.setLinkage(linkage);
4083 mlir::SymbolTable::setSymbolVisibility(alias, visibility);
4091 cir::FuncOp aliasee,
4092 cir::GlobalLinkageKind linkage) {
4094 auto *aliasFD = dyn_cast<FunctionDecl>(aliasGD.
getDecl());
4095 assert(aliasFD &&
"expected FunctionDecl");
4106 mangledName, fnType, aliasFD);
4107 alias.setAliasee(aliasee.getName());
4108 alias.setLinkage(linkage);
4112 mlir::SymbolTable::setSymbolVisibility(
4113 alias, mlir::SymbolTable::Visibility::Private);
4125 "declaration exists with different type");
4137 return genTypes.convertType(
type);
4144 return mlir::verify(theModule).succeeded();
4153 return builder.getConstNullPtrAttr(builder.getUInt8PtrTy());
4156 langOpts.ObjCRuntime.isGNUFamily()) {
4157 errorNYI(loc,
"getAddrOfRTTIDescriptor: Objc PtrType & Objc RT GUN");
4167 llvm::iterator_range<CastExpr::path_const_iterator> path) {
4174 assert(!base->isVirtual() &&
"Should not see virtual bases here!");
4179 const auto *baseDecl = base->getType()->castAsCXXRecordDecl();
4191 llvm::StringRef feature) {
4192 unsigned diagID = diags.getCustomDiagID(
4194 return diags.Report(loc, diagID) << feature;
4198 llvm::StringRef feature) {
4210 "cannot compile this %0 yet");
4211 diags.Report(astContext.getFullLoc(s->
getBeginLoc()), diagId)
4218 "cannot compile this %0 yet");
4219 diags.Report(astContext.getFullLoc(d->
getLocation()), diagId) <<
type;
4227 "not a global temporary");
4239 materializedType = mte->
getType();
4248 llvm::raw_svector_ostream
out(name);
4252 auto insertResult = materializedGlobalTemporaryMap.insert({mte,
nullptr});
4253 if (!insertResult.second) {
4257 if (!insertResult.first->second) {
4260 insertResult.first->second =
4263 return insertResult.first->second;
4280 value = &evalResult.
Val;
4284 std::optional<ConstantEmitter> emitter;
4285 mlir::Attribute initialValue =
nullptr;
4286 bool isConstant =
false;
4290 emitter.emplace(*
this);
4291 initialValue = emitter->emitForInitializer(*value, materializedType);
4296 type = mlir::cast<mlir::TypedAttr>(initialValue).getType();
4305 if (linkage == cir::GlobalLinkageKind::ExternalLinkage) {
4307 if (
varDecl->isStaticDataMember() &&
varDecl->getAnyInitializer(initVD) &&
4315 linkage = cir::GlobalLinkageKind::InternalLinkage;
4319 gv.setInitialValueAttr(initialValue);
4320 gv.setLinkage(linkage);
4324 emitter->finalize(gv);
4326 if (!gv.hasLocalLinkage()) {
4331 gv.setAlignment(align.getAsAlign().value());
4336 mlir::Operation *cv = gv;
4345 mlir::Operation *&entry = materializedGlobalTemporaryMap[mte];
4347 entry->replaceAllUsesWith(cv);
4362 return *globalOpEntry;
4369 "emitForInitializer should take gcd->getType().getAddressSpace()");
4371 auto typedInit = dyn_cast<mlir::TypedAttr>(init);
4375 "getAddrOfUnnamedGlobalConstantDecl: non-typed initializer");
4384 std::string name = numEntries == 0
4386 : (Twine(
".constant.") + Twine(numEntries)).str();
4388 typedInit.getType(),
true);
4389 globalOp.setLinkage(cir::GlobalLinkageKind::PrivateLinkage);
4392 globalOp.setAlignment(alignment.
getAsAlign().value());
4396 *globalOpEntry = globalOp;
4411 "emitForInitializer should take tpo->getType().getAddressSpace()");
4412 mlir::Attribute init =
4422 cir::GlobalLinkageKind linkage =
4424 ? cir::GlobalLinkageKind::LinkOnceODRLinkage
4425 : cir::GlobalLinkageKind::InternalLinkage;
4429 typedInit.getType(),
true);
4430 globalOp.setLinkage(linkage);
4431 globalOp.setAlignment(alignment.
getAsAlign().value());
4433 linkage == cir::GlobalLinkageKind::LinkOnceODRLinkage);
4448CIRGenModule::getOrCreateAnnotationArgs(
const AnnotateAttr *
attr) {
4455 llvm::FoldingSetNodeID id;
4456 for (
Expr *e : exprs)
4459 mlir::ArrayAttr &lookup = annotationArgs[
id.computeHash()];
4464 args.reserve(exprs.size());
4465 for (
Expr *e : exprs) {
4466 if (
auto *strE = dyn_cast<clang::StringLiteral>(e->IgnoreParenCasts())) {
4467 args.push_back(builder.getStringAttr(strE->getString()));
4468 }
else if (
auto *intE =
4469 dyn_cast<clang::IntegerLiteral>(e->IgnoreParenCasts())) {
4470 auto intTy = builder.getIntegerType(intE->getValue().getBitWidth());
4471 args.push_back(builder.getIntegerAttr(intTy, intE->getValue()));
4473 errorNYI(e->getExprLoc(),
"annotation argument expression");
4477 return lookup = builder.getArrayAttr(args);
4480cir::AnnotationAttr CIRGenModule::emitAnnotateAttr(
const AnnotateAttr *aa) {
4481 mlir::StringAttr annoGV = builder.getStringAttr(aa->getAnnotation());
4482 mlir::ArrayAttr args = getOrCreateAnnotationArgs(aa);
4483 return cir::AnnotationAttr::get(&
getMLIRContext(), annoGV, args);
4487 mlir::Operation *gv) {
4488 assert(d->
hasAttr<AnnotateAttr>() &&
"no annotate attribute");
4490 "annotation only on globals");
4493 annotations.push_back(emitAnnotateAttr(i));
4494 if (
auto global = dyn_cast<cir::GlobalOp>(gv))
4495 global.setAnnotationsAttr(builder.getArrayAttr(annotations));
4496 else if (
auto func = dyn_cast<cir::FuncOp>(gv))
4497 func.setAnnotationsAttr(builder.getArrayAttr(annotations));
4500void CIRGenModule::emitGlobalAnnotations() {
4501 for (
const auto &[mangledName, vd] : deferredAnnotations) {
4506 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 cir::LangAddressSpace getOpenCLKernelArgAddressSpace(LangAS addressSpace)
static bool shouldBeInCOMDAT(CIRGenModule &cgm, const Decl &d)
static mlir::Attribute getNewInitValue(CIRGenModule &cgm, cir::GlobalOp newGlob, mlir::Type oldTy, mlir::Attribute oldInit)
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 void setLinkageForFunction(CIRGenModule &cgm, cir::FuncOp &func, const NamedDecl *nd)
static cir::GlobalOp generateStringLiteral(mlir::Location loc, mlir::TypedAttr c, cir::GlobalLinkageKind lt, CIRGenModule &cgm, StringRef globalName, CharUnits alignment)
static bool hasImplicitAttr(const ValueDecl *decl)
static std::vector< std::string > getFeatureDeltaFromDefault(const CIRGenModule &cgm, llvm::StringRef targetCPU, llvm::StringMap< bool > &featureMap)
Get the feature delta from the default feature map for the given target CPU.
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 bool verifyPointerTypeArgs(cir::FuncOp oldF, cir::FuncOp newF, mlir::SymbolUserMap &userMap)
static mlir::Attribute createNewGlobalView(CIRGenModule &cgm, cir::GlobalOp newGlob, cir::GlobalViewAttr attr, mlir::Type oldTy)
static cir::CtorKind getCtorKindFromDecl(const CXXConstructorDecl *ctor)
static void emitUsed(CIRGenModule &cgm, StringRef name, std::vector< cir::CIRGlobalValueInterface > &list)
static cir::TLSModel getCIRTLSModel(StringRef S)
static Decl::Kind getKind(const Decl *D)
This file defines OpenACC nodes for declarative directives.
static constexpr bool needsDtor()
static unsigned getCharWidth(tok::TokenKind kind, const TargetInfo &Target)
Defines the clang::Module class, which describes a module in the source code.
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
Defines the SourceManager interface.
This file defines OpenMP AST classes for executable directives and clauses.
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 isSameEntity(const NamedDecl *X, const NamedDecl *Y) const
Determine whether the two declarations refer to the same entity.
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.
const clang::PrintingPolicy & getPrintingPolicy() const
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.
DiagnosticsEngine & getDiagnostics() const
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, cir::RecordType recordTy)
uint64_t computeOffsetFromGlobalViewIndices(const cir::CIRDataLayout &layout, mlir::Type ty, llvm::ArrayRef< int64_t > indices)
cir::ConstArrayAttr getConstArray(mlir::Attribute attrs, cir::ArrayType arrayTy) const
bool computeGlobalViewIndicesFromFlatOffset(int64_t offset, mlir::Type ty, cir::CIRDataLayout layout, llvm::SmallVectorImpl< int64_t > &indices)
virtual void handleGlobalReplace(cir::GlobalOp oldGV, cir::GlobalOp newGV)
virtual mlir::Operation * getKernelHandle(cir::FuncOp fn, GlobalDecl gd)=0
virtual void finalizeModule()
Perform module finalization: on device side, mark ODR-used device variables as compiler-used.
virtual void internalizeDeviceSideVar(const VarDecl *d, cir::GlobalLinkageKind &linkage)=0
Adjust linkage of shadow variables in host compilation.
virtual void handleVarRegistration(const VarDecl *vd, cir::GlobalOp var)=0
Check whether a variable is a device variable and register it if true.
Implements C++ ABI-specific code generation functions.
virtual mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc, QualType ty)=0
virtual void emitCXXConstructors(const clang::CXXConstructorDecl *d)=0
Emit constructor variants required by this ABI.
virtual void emitCXXDestructors(const clang::CXXDestructorDecl *d)=0
Emit dtor variants required by this ABI.
clang::MangleContext & getMangleContext()
Gets the mangle context.
virtual cir::GlobalLinkageKind getCXXDestructorLinkage(GVALinkage linkage, const CXXDestructorDecl *dtor, CXXDtorType dt) const
cir::FuncOp generateCode(clang::GlobalDecl gd, cir::FuncOp fn, cir::FuncType funcType)
void emitVariablyModifiedType(QualType ty)
This class organizes the cross-function state that is used while generating CIR code.
cir::GlobalOp getAddrOfUnnamedGlobalConstantDecl(const UnnamedGlobalConstantDecl *gcd)
void setGlobalVisibility(cir::CIRGlobalValueInterface gv, const NamedDecl *d) const
Set the visibility for the given global.
void addUsedOrCompilerUsedGlobal(cir::CIRGlobalValueInterface gv)
Add a global to a list to be added to the llvm.compiler.used metadata.
void setFuncInfoAttr(cir::FuncOp funcOp, const clang::FunctionDecl *funcDecl)
Record the func_info tag for a function, either a C++ special member form (constructor,...
void replaceUsesOfNonProtoTypeWithRealFunction(mlir::Operation *old, cir::FuncOp newFn)
This function is called when we implement a function with no prototype, e.g.
bool shouldEmitFunction(clang::GlobalDecl gd)
Check if fd ends up calling itself directly through asm label or builtin-pointer-to-self trickery (e....
llvm::StringRef getMangledName(clang::GlobalDecl gd)
CharUnits computeNonVirtualBaseClassOffset(const CXXRecordDecl *derivedClass, llvm::iterator_range< CastExpr::path_const_iterator > path)
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
void insertGlobalSymbol(mlir::Operation *op)
cir::FuncOp getAddrOfCXXStructor(clang::GlobalDecl gd, const CIRGenFunctionInfo *fnInfo=nullptr, cir::FuncType fnType=nullptr, bool dontDefer=false, ForDefinition_t isForDefinition=NotForDefinition)
CIRGenCUDARuntime & getCUDARuntime()
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)
std::optional< llvm::SmallVector< int32_t > > buildMemberPath(const CXXRecordDecl *destClass, const ValueDecl *decl)
Build a GEP-style field-index path from destClass to decl.
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)
cir::TLSModel getDefaultCIRTLSModel() const
Get TLS mode from CodeGenOptions.
void setGlobalTlsReferences(const VarDecl &vd, cir::GlobalOp globalOp)
void emitOpenCLKernelArgMetadata(cir::FuncOp func, const clang::FunctionDecl *fd)
Generate OpenCL kernel argument metadata for a kernel function.
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.
cir::GlobalOp getAddrOfTemplateParamObject(const TemplateParamObjectDecl *tpo)
Get the GlobalOp of a template parameter object.
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.
llvm::DenseMap< const UnnamedGlobalConstantDecl *, cir::GlobalOp > unnamedGlobalConstantDeclMap
std::vector< cir::CIRGlobalValueInterface > llvmCompilerUsed
void emitOMPRequiresDecl(const OMPRequiresDecl *d)
void emitGlobalDefinition(clang::GlobalDecl gd, mlir::Operation *op=nullptr)
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 emitAliasDefinition(GlobalDecl gd)
Emit a definition for an __attribute__((alias)) declaration.
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)
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 setTLSMode(mlir::Operation *op, const VarDecl &d, bool isExtendingDecl=false)
Set TLS mode for the given operation based on the given variable declaration.
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
void eraseGlobalSymbol(mlir::Operation *op)
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.
llvm::StringMap< mlir::Operation * > symbolLookupCache
Cache for O(1) symbol lookups by name, replacing the O(N) linear scan in SymbolTable::lookupSymbolIn ...
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 printPostfixForExternalizedDecl(llvm::raw_ostream &os, const Decl *d)
Print the postfix for externalized static variable or kernels for single source offloading languages ...
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::GlobalOp createGlobalOp(mlir::Location loc, llvm::StringRef name, mlir::Type t, bool isConstant=false, mlir::ptr::MemorySpaceAttrInterface addrSpace={}, mlir::Operation *insertPoint=nullptr)
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)
static cir::VisibilityKind getCIRVisibilityKind(Visibility v)
void setGVPropertiesAux(mlir::Operation *op, const NamedDecl *d) const
LangAS getLangTempAllocaAddressSpace() const
Returns the address space for temporary allocations in the language.
mlir::Location getLoc(clang::SourceLocation cLoc)
Helpers to convert the presumed location of Clang's SourceLocation to an MLIR Location.
llvm::DenseMap< mlir::Attribute, cir::GlobalOp > constantStringMap
mlir::Operation * lastGlobalOp
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.
llvm::StringMap< unsigned > cgGlobalNames
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()
void emitSYCLKernelCaller(const clang::FunctionDecl *kernelEntryPointFn, clang::ASTContext &ctx)
Emit the SYCL kernel caller offload entry point function generated for a function declared with the s...
mlir::Operation * getAddrOfGlobal(clang::GlobalDecl gd, ForDefinition_t isForDefinition=NotForDefinition)
void maybeSetTrivialComdat(const clang::Decl &d, mlir::Operation *op)
bool isEmptyFieldForMemberPointer(const FieldDecl *field)
Returns true if field is a potentially-overlapping field with no CIR field index (e....
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.
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.
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 constructAttributeList(llvm::StringRef name, const CIRGenFunctionInfo &info, CIRGenCalleeInfo calleeInfo, mlir::NamedAttrList &attrs, llvm::MutableArrayRef< mlir::NamedAttrList > argAttrs, mlir::NamedAttrList &retAttrs, cir::CallingConv &callingConv, bool attrOnCallSite, bool isThunk)
Get the CIR attributes and calling convention to use for a particular function type.
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)
CIRGenOpenMPRuntime & getOpenMPRuntime()
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.
void setCommonAttributes(GlobalDecl gd, mlir::Operation *op)
Set attributes which are common to any form of a global definition (alias, Objective-C method,...
void emitDeclareTargetFunction(const FunctionDecl *fd, cir::FuncOp funcOp)
If the function has an OMPDeclareTargetDeclAttr, set the corresponding omp.declare_target attribute o...
This class handles record and union layout info while lowering AST types to CIR types.
bool hasNonVirtualBaseCIRField(const CXXRecordDecl *rd) const
unsigned getCIRFieldNo(const clang::FieldDecl *fd) const
Return cir::RecordType element number that corresponds to the field FD.
bool hasCIRField(const clang::FieldDecl *fd) const
bool isZeroInitializable() const
Check whether this struct can be C++ zero-initialized with a zeroinitializer.
unsigned getNonVirtualBaseCIRFieldNo(const CXXRecordDecl *rd) const
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.
const CIRGenRecordLayout & getCIRGenRecordLayout(const clang::RecordDecl *rd)
Return record layout info for the given record decl.
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.
void finalize(cir::GlobalOp gv)
mlir::Attribute emitForInitializer(const APValue &value, QualType destType)
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.
CXXRecordDecl * getMostRecentDecl()
bool hasDefinition() const
CharUnits - This is an opaque type for sizes expressed in character units.
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
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 isInStdNamespace() const
bool isWeakImported() const
Determine whether this is a weak-imported symbol.
bool isInExportDeclContext() const
Whether this declaration was exported in a lexical context.
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.
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
bool isPotentiallyOverlapping() const
Determine if this field is of potentially-overlapping class type, that is, subobject with the [[no_un...
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={})
ArrayRef< ParmVarDecl * > parameters() const
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.
FunctionDecl * getDefinition()
Get the definition for this declaration.
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.
CXXCtorType getCtorType() const
GlobalDecl getCanonicalDecl() const
KernelReferenceKind getKernelReferenceKind() const
GlobalDecl getWithDecl(const Decl *D)
unsigned getMultiVersionIndex() const
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...
std::string CUID
The user provided compilation unit ID, if non-empty.
Visibility getVisibility() const
void setLinkage(Linkage L)
Linkage getLinkage() const
bool isVisibilityExplicit() const
MangleContext - Context for tracking state which persists across multiple calls to the C++ name mangl...
bool isTriviallyRecursive(const FunctionDecl *FD)
Return true if FD's body contains a direct call back to the symbol it links as, through an asm label ...
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.
CXXRecordDecl * getMostRecentCXXRecordDecl() const
Note: this can trigger extra deserialization when external AST sources are used.
Describes a module or submodule.
bool isModuleImplementation() const
Is this a module implementation.
bool isNamedModule() const
Does this Module is a named module of a standard named module?
Module * getTopLevelModule()
Retrieve the top-level module for this (sub)module, which may be this module.
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.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
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.
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
LangAS getAddressSpace() const
Return the address space of this type.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
QualType getCanonicalType() const
bool isConstQualified() const
Determine whether this type is const-qualified.
bool isConstantStorage(const ASTContext &Ctx, bool ExcludeCtor, bool ExcludeDtor)
bool hasUnaligned() const
Represents a struct/union/class.
RecordDecl * getMostRecentDecl()
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...
SourceLocation getBeginLoc() const LLVM_READONLY
StringLiteral - This represents a string literal expression, e.g.
SourceLocation getBeginLoc() const LLVM_READONLY
unsigned getLength() const
uint32_t getCodeUnit(size_t I) const
Return the code unit at the given position.
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?
TargetOptions & getTargetOpts() const
Retrieve the target options.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
bool isReadOnlyFeature(StringRef Feature) const
Determine whether the given target feature is read only.
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
virtual ParsedTargetAttr parseTargetAttr(StringRef Str) const
virtual bool initFeatureMap(llvm::StringMap< bool > &Features, DiagnosticsEngine &Diags, StringRef CPU, const std::vector< std::string > &FeatureVec) const
Initialize the map with the default set of target features for the CPU this should include all legal ...
std::vector< std::string > Features
The list of target specific features to enable or disable – this should be a list of strings starting...
std::string TuneCPU
If given, the name of the target CPU to tune code for.
std::string CPU
If given, the name of the target CPU to generate code for.
A template parameter object.
const APValue & getValue() const
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
const T * castAs() const
Member-template castAs<specific type>.
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
An artificial decl, representing a global anonymous constant value which is uniquified by value withi...
const APValue & getValue() 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.
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
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_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)
std::unique_ptr< TargetCIRGenInfo > createCommonSPIRTargetCIRGenInfo(CIRGenTypes &cgt)
bool isEmptyFieldForLayout(const ASTContext &context, const FieldDecl *fd)
isEmptyFieldForLayout - Return true if the field is "empty", that is, either a zero-width bit-field o...
std::unique_ptr< TargetCIRGenInfo > createAArch64TargetCIRGenInfo(CIRGenTypes &cgt)
CIRGenCXXABI * CreateCIRGenMicrosoftCXXABI(CIRGenModule &cgm)
Creates Microsoft ABI.
CIRGenCUDARuntime * createNVCUDARuntime(CIRGenModule &cgm)
bool hasUnwindExceptions(const LangOptions &LangOpts)
Determines whether the language options require us to model unwind exceptions.
const internal::VariadicDynCastAllOfMatcher< Decl, VarDecl > varDecl
Matches variable declarations.
const internal::VariadicAllOfMatcher< Attr > attr
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.
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
GVALinkage
A more specific kind of linkage than enum Linkage.
@ GVA_AvailableExternally
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ 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)
@ HiddenVisibility
Objects with "hidden" visibility are not seen by the dynamic linker.
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 opFuncMultiVersioning()
static bool sourceLanguageCases()
static bool shouldSkipAliasEmission()
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 checkAliases()
static bool generateDebugInfo()
static bool targetCIRGenInfoOS()
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.
Describes how types, statements, expressions, and declarations should be printed.