19#include "mlir/Dialect/OpenMP/Utils/Utils.h"
20#include "mlir/IR/SymbolTable.h"
23#include "clang/AST/Attrs.inc"
42#include "llvm/ADT/STLExtras.h"
43#include "llvm/ADT/StringExtras.h"
44#include "llvm/ADT/StringRef.h"
45#include "llvm/ADT/StringSwitch.h"
46#include "llvm/Support/raw_ostream.h"
50#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
51#include "mlir/IR/Attributes.h"
52#include "mlir/IR/BuiltinOps.h"
53#include "mlir/IR/Location.h"
54#include "mlir/IR/MLIRContext.h"
55#include "mlir/IR/Operation.h"
56#include "mlir/IR/Verifier.h"
65 case TargetCXXABI::GenericItanium:
66 case TargetCXXABI::GenericAArch64:
67 case TargetCXXABI::AppleARM64:
68 case TargetCXXABI::GenericARM:
70 case TargetCXXABI::Microsoft:
73 case TargetCXXABI::Fuchsia:
74 case TargetCXXABI::iOS:
75 case TargetCXXABI::WatchOS:
76 case TargetCXXABI::GenericMIPS:
77 case TargetCXXABI::WebAssembly:
78 case TargetCXXABI::XL:
79 cgm.
errorNYI(
"createCXXABI: C++ ABI kind");
83 llvm_unreachable(
"invalid C++ ABI kind");
86CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,
90 : builder(mlirContext, *this), astContext(astContext),
91 langOpts(astContext.
getLangOpts()), codeGenOpts(cgo),
92 theModule{
mlir::ModuleOp::create(
mlir::UnknownLoc::get(&mlirContext))},
93 diags(diags), target(astContext.getTargetInfo()),
94 abi(
createCXXABI(*this)), genTypes(*this), vtables(*this) {
122 .toCharUnitsFromBits(
126 const unsigned charSize = target.getCharWidth();
129 const unsigned sizeTypeSize = target.getTypeWidth(target.getSizeType());
137 std::optional<cir::SourceLanguage> sourceLanguage = getCIRSourceLanguage();
140 cir::CIRDialect::getSourceLanguageAttrName(),
141 cir::SourceLanguageAttr::get(&mlirContext, *sourceLanguage));
142 if (langOpts.OpenCL || (langOpts.CUDAIsDevice &&
getTriple().isSPIRV())) {
145 langOpts.OpenCL ? langOpts.getOpenCLCompatibleVersion() : 200;
146 setOpenCLVersionAttr(cir::CIRDialect::getOpenCLVersionAttrName(), version);
147 if (langOpts.OpenCLCPlusPlus)
148 setOpenCLVersionAttr(cir::CIRDialect::getOpenCLCXXVersionAttrName(),
149 langOpts.OpenCLCPlusPlusVersion);
152 unsigned spirMajor = version / 100;
153 theModule->setAttr(cir::CIRDialect::getOpenCLSPIRVersionAttrName(),
156 spirMajor > 1 ? 0 : 2));
159 theModule->setAttr(cir::CIRDialect::getTripleAttrName(),
160 builder.getStringAttr(
getTriple().str()));
161 theModule->setAttr(cir::CIRDialect::getTargetABIAttrName(),
162 builder.getStringAttr(
getTarget().getABI()));
163 if (llvm::VersionTuple sdkVersion =
getTarget().getSDKVersion();
165 theModule->setAttr(cir::CIRDialect::getSDKVersionAttrName(),
166 builder.getStringAttr(sdkVersion.getAsString()));
169 theModule->setAttr(cir::CIRDialect::getSizeTypeWidthAttrName(),
170 builder.getI32IntegerAttr(sizeTypeSize));
171 theModule->setAttr(cir::CIRDialect::getIntTypeWidthAttrName(),
172 builder.getI32IntegerAttr(target.getIntWidth()));
178 cir::CIRDialect::getLoweringLangOptionsAttrName(),
179 cir::LoweringLangOptionsAttr::get(
182 langOpts.ThreadsafeStatics,
184 langOpts.CUDAIsDevice,
186 langOpts.GPURelocatableDeviceCode,
187 langOpts.OpenMP != 0,
188 langOpts.OpenMPIsTargetDevice,
190 static_cast<int32_t
>(langOpts.getClangABICompat())));
192 if (cgo.OptimizationLevel > 0 || cgo.OptimizeSize > 0)
193 theModule->setAttr(cir::CIRDialect::getOptInfoAttrName(),
194 cir::OptInfoAttr::get(&mlirContext,
195 cgo.OptimizationLevel,
199 cir::CIRDialect::getDefaultTlsModelAttrName(),
202 if (langOpts.OpenMP) {
203 mlir::omp::OffloadModuleOpts ompOpts(
204 langOpts.OpenMPTargetDebug, langOpts.OpenMPTeamSubscription,
205 langOpts.OpenMPThreadSubscription, langOpts.OpenMPNoThreadState,
206 langOpts.OpenMPNoNestedParallelism, langOpts.OpenMPIsTargetDevice,
207 getTriple().isGPU(), langOpts.OpenMPForceUSM, langOpts.OpenMP,
208 langOpts.OMPHostIRFile, langOpts.OMPTargetTriples, langOpts.NoGPULib);
209 mlir::omp::setOffloadModuleInterfaceAttributes(theModule, ompOpts);
210 mlir::omp::setOpenMPVersionAttribute(theModule, langOpts.OpenMP);
216 createOpenMPRuntime();
221 FileID mainFileId = astContext.getSourceManager().getMainFileID();
223 *astContext.getSourceManager().getFileEntryForID(mainFileId);
226 theModule.setSymName(path);
227 theModule->setLoc(mlir::FileLineColLoc::get(&mlirContext, path,
235void CIRGenModule::setOpenCLVersionAttr(StringRef attrName,
unsigned version) {
237 attrName, cir::OpenCLVersionAttr::get(&
getMLIRContext(), version / 100,
238 (version % 100) / 10));
241void CIRGenModule::createCUDARuntime() {
245void CIRGenModule::createOpenMPRuntime() {
246 openMPRuntime = std::make_unique<CIRGenOpenMPRuntime>(*
this);
257 auto &layout = astContext.getASTRecordLayout(rd);
262 return layout.getAlignment();
265 return layout.getNonVirtualAlignment();
270 bool forPointeeType) {
280 if (
unsigned align = tt->getDecl()->getMaxAlignment()) {
283 return astContext.toCharUnitsFromBits(align);
291 t = astContext.getBaseElementType(t);
312 }
else if (forPointeeType && !alignForArray &&
316 alignment = astContext.getTypeAlignInChars(t);
321 if (
unsigned maxAlign = astContext.getLangOpts().MaxTypeAlign) {
323 !astContext.isAlignmentRequired(t))
337 if (theTargetCIRGenInfo)
338 return *theTargetCIRGenInfo;
341 switch (triple.getArch()) {
348 case llvm::Triple::x86_64: {
349 switch (triple.getOS()) {
356 case llvm::Triple::Linux:
358 return *theTargetCIRGenInfo;
361 case llvm::Triple::aarch64:
362 case llvm::Triple::aarch64_32:
363 case llvm::Triple::aarch64_be: {
365 return *theTargetCIRGenInfo;
367 case llvm::Triple::nvptx:
368 case llvm::Triple::nvptx64:
370 return *theTargetCIRGenInfo;
371 case llvm::Triple::amdgpu: {
373 return *theTargetCIRGenInfo;
375 case llvm::Triple::spir:
376 case llvm::Triple::spir64:
377 case llvm::Triple::spirv:
378 case llvm::Triple::spirv32:
379 case llvm::Triple::spirv64:
381 return *theTargetCIRGenInfo;
386 assert(cLoc.
isValid() &&
"expected valid source location");
390 return mlir::FileLineColLoc::get(builder.getStringAttr(filename),
395 assert(cRange.
isValid() &&
"expected a valid source range");
398 mlir::Attribute metadata;
399 return mlir::FusedLoc::get({begin, end}, metadata, builder.getContext());
408 false, isForDefinition);
442 assert(op &&
"expected a valid global op");
450 mlir::Operation *globalValueOp = op;
451 if (
auto gv = dyn_cast<cir::GetGlobalOp>(op)) {
453 assert(globalValueOp &&
"expected a valid global op");
456 if (
auto cirGlobalValue =
457 dyn_cast<cir::CIRGlobalValueInterface>(globalValueOp))
458 if (!cirGlobalValue.isDeclaration())
479 assert(deferredVTables.empty());
489 std::vector<GlobalDecl> curDeclsToEmit;
497 if (
const auto *fd = d.getDecl()->getAsFunction()) {
498 if (langOpts.SYCLIsDevice && fd->hasAttr<SYCLKernelEntryPointAttr>() &&
502 if (!fd->getAttr<SYCLKernelEntryPointAttr>()->isInvalidAttr()) {
529 if (
auto *
attr =
decl->getAttr<AttrT>())
530 return attr->isImplicit();
531 return decl->isImplicit();
536 assert(langOpts.CUDA &&
"Should not be called by non-CUDA languages");
541 return !langOpts.CUDAIsDevice || global->
hasAttr<CUDADeviceAttr>() ||
542 global->
hasAttr<CUDAConstantAttr>() ||
543 global->
hasAttr<CUDASharedAttr>() ||
553 os << (isa<VarDecl>(d) ?
".static." :
".intern.");
555 os << (isa<VarDecl>(d) ?
"__static__" :
"__intern__");
562 "printPostfixForExternalizedDecl: CUID is not specified");
569 if (
const auto *cd = dyn_cast<clang::OpenACCConstructDecl>(gd.
getDecl())) {
577 if (global->hasAttr<WeakRefAttr>())
582 if (global->hasAttr<AliasAttr>()) {
595 "Expected Variable or Function");
596 if (
const auto *
varDecl = dyn_cast<VarDecl>(global)) {
600 }
else if (langOpts.CUDAIsDevice) {
601 const auto *
functionDecl = dyn_cast<FunctionDecl>(global);
602 if ((!global->hasAttr<CUDADeviceAttr>() ||
603 (langOpts.OffloadImplicitHostDeviceTemplates &&
608 !
getASTContext().CUDAImplicitHostDeviceFunUsedByDevice.count(
610 !global->hasAttr<CUDAGlobalAttr>() &&
612 !global->hasAttr<CUDAHostAttr>()))
615 }
else if (!global->hasAttr<CUDAHostAttr>() &&
616 global->hasAttr<CUDADeviceAttr>())
620 if (langOpts.OpenMP) {
622 if (openMPRuntime && openMPRuntime->emitTargetGlobal(gd))
624 if (
auto *drd = dyn_cast<OMPDeclareReductionDecl>(global)) {
629 if (
auto *dmd = dyn_cast<OMPDeclareMapperDecl>(global)) {
636 if (
const auto *fd = dyn_cast<FunctionDecl>(global)) {
639 if (fd->hasAttr<AnnotateAttr>()) {
642 deferredAnnotations[mangledName] = fd;
644 if (!fd->doesThisDeclarationHaveABody()) {
645 if (!fd->doesDeclarationForceExternallyVisibleDefinition() &&
656 assert(vd->isFileVarDecl() &&
"Cannot emit local var decl as global.");
658 !astContext.isMSStaticDataMemberInlineDefinition(vd)) {
662 if (astContext.getInlineVariableDefinitionKind(vd) ==
701 mlir::Operation *op) {
705 cir::FuncOp funcOp = dyn_cast_if_present<cir::FuncOp>(op);
706 if (!funcOp || funcOp.getFunctionType() != funcType) {
712 if (!funcOp.isDeclaration())
724 mlir::OpBuilder::InsertionGuard guard(builder);
729 setNonAliasAttributes(gd, funcOp);
732 auto getPriority = [
this](
const auto *
attr) ->
int {
736 return attr->DefaultPriority;
739 if (
const ConstructorAttr *ca = funcDecl->getAttr<ConstructorAttr>())
741 if (
const DestructorAttr *da = funcDecl->getAttr<DestructorAttr>())
744 if (funcDecl->getAttr<AnnotateAttr>())
747 if (
getLangOpts().OpenMP && funcDecl->hasAttr<OMPDeclareTargetDeclAttr>())
753 std::optional<int> priority) {
762 ctor.setGlobalCtorPriority(priority);
767 std::optional<int> priority) {
768 if (codeGenOpts.RegisterGlobalDtorsWithAtExit &&
770 errorNYI(dtor.getLoc(),
"registerGlobalDtorsWithAtExit");
773 dtor.setGlobalDtorPriority(priority);
799 mlir::ptr::MemorySpaceAttrInterface addrSpace,
800 mlir::Operation *insertPoint) {
805 mlir::OpBuilder::InsertionGuard guard(builder);
811 builder.setInsertionPoint(insertPoint);
817 builder.setInsertionPointToStart(
getModule().getBody());
820 g = cir::GlobalOp::create(builder, loc, name, t, isConstant, addrSpace);
826 mlir::SymbolTable::setSymbolVisibility(
827 g, mlir::SymbolTable::Visibility::Private);
835 if (isa_and_nonnull<NamedDecl>(d))
839 if (
auto gvi = mlir::dyn_cast<cir::CIRGlobalValueInterface>(gv)) {
840 if (d && d->
hasAttr<UsedAttr>())
843 if (
const auto *vd = dyn_cast_if_present<VarDecl>(d);
844 vd && ((codeGenOpts.KeepPersistentStorageVariables &&
845 (vd->getStorageDuration() ==
SD_Static ||
846 vd->getStorageDuration() ==
SD_Thread)) ||
847 (codeGenOpts.KeepStaticConsts &&
849 vd->getType().isConstQualified())))
855static std::vector<std::string>
857 llvm::StringMap<bool> &featureMap) {
858 llvm::StringMap<bool> defaultFeatureMap;
862 std::vector<std::string> delta;
863 for (
const auto &[k, v] : featureMap) {
864 auto defaultIt = defaultFeatureMap.find(k);
865 if (defaultIt == defaultFeatureMap.end() || defaultIt->getValue() != v)
866 delta.push_back((v ?
"+" :
"-") + k.str());
872bool CIRGenModule::getCPUAndFeaturesAttributes(
873 GlobalDecl gd, llvm::StringMap<std::string> &attrs,
874 bool setTargetFeatures) {
880 std::vector<std::string> features;
884 const auto *fd = dyn_cast_or_null<FunctionDecl>(gd.
getDecl());
885 fd = fd ? fd->getMostRecentDecl() : fd;
886 const auto *td = fd ? fd->getAttr<TargetAttr>() :
nullptr;
887 const auto *tv = fd ? fd->getAttr<TargetVersionAttr>() :
nullptr;
888 assert((!td || !tv) &&
"both target_version and target specified");
889 const auto *sd = fd ? fd->getAttr<CPUSpecificAttr>() :
nullptr;
890 const auto *tc = fd ? fd->getAttr<TargetClonesAttr>() :
nullptr;
891 bool addedAttr =
false;
892 if (td || tv || sd || tc) {
893 llvm::StringMap<bool> featureMap;
894 astContext.getFunctionFeatureMap(featureMap, gd);
900 llvm::StringRef featureStr = td ? td->getFeaturesStr() : llvm::StringRef();
903 if (!featureStr.empty()) {
904 clang::ParsedTargetAttr parsedAttr =
906 if (!parsedAttr.
CPU.empty() &&
908 targetCPU = parsedAttr.
CPU;
911 if (!parsedAttr.
Tune.empty() &&
913 tuneCPU = parsedAttr.
Tune;
929 features.reserve(features.size() + featureMap.size());
930 for (
const auto &entry : featureMap)
931 features.push_back((entry.getValue() ?
"+" :
"-") +
932 entry.getKey().str());
937 llvm::StringMap<bool> featureMap;
939 astContext.getFunctionFeatureMap(featureMap, gd);
950 if (!targetCPU.empty()) {
951 attrs[cir::CIRDialect::getTargetCPUAttrName()] = targetCPU.str();
954 if (!tuneCPU.empty()) {
955 attrs[cir::CIRDialect::getTuneCPUAttrName()] = tuneCPU.str();
958 if (!features.empty() && setTargetFeatures) {
959 llvm::erase_if(features, [&](
const std::string &f) {
960 assert(!f.empty() && (f[0] ==
'+' || f[0] ==
'-') &&
961 "feature string must start with '+' or '-'");
964 llvm::sort(features);
965 attrs[cir::CIRDialect::getTargetFeaturesAttrName()] =
966 llvm::join(features,
",");
974void CIRGenModule::setNonAliasAttributes(GlobalDecl gd, mlir::Operation *op) {
979 if (
auto gvi = mlir::dyn_cast<cir::CIRGlobalValueInterface>(op)) {
980 if (
const auto *sa = d->
getAttr<SectionAttr>())
981 gvi.setSection(builder.getStringAttr(sa->getName()));
985 if (
auto func = dyn_cast<cir::FuncOp>(op)) {
986 llvm::StringMap<std::string> attrs;
987 if (getCPUAndFeaturesAttributes(gd, attrs)) {
994 for (llvm::StringRef name :
995 {cir::CIRDialect::getTargetCPUAttrName(),
996 cir::CIRDialect::getTuneCPUAttrName(),
997 cir::CIRDialect::getTargetFeaturesAttrName()})
998 func->removeAttr(name);
999 for (
const auto &[key, val] : attrs)
1000 func->setAttr(key, builder.getStringAttr(val));
1010std::optional<cir::SourceLanguage> CIRGenModule::getCIRSourceLanguage()
const {
1011 using ClangStd = clang::LangStandard;
1012 using CIRLang = cir::SourceLanguage;
1015 if (opts.OpenCLCPlusPlus)
1016 return CIRLang::OpenCLCXX;
1018 return CIRLang::OpenCLC;
1020 return CIRLang::CXX;
1021 if (opts.C99 || opts.C11 || opts.C17 || opts.C23 || opts.C2y ||
1022 opts.LangStd == ClangStd::lang_c89 ||
1023 opts.LangStd == ClangStd::lang_gnu89)
1028 errorNYI(
"CIR does not yet support the given source language");
1029 return std::nullopt;
1032LangAS CIRGenModule::getGlobalVarAddressSpace(
const VarDecl *d) {
1033 if (langOpts.OpenCL) {
1041 if (langOpts.SYCLIsDevice &&
1043 errorNYI(
"SYCL global address space");
1045 if (langOpts.CUDA && langOpts.CUDAIsDevice) {
1047 if (d->
hasAttr<CUDAConstantAttr>())
1049 if (d->
hasAttr<CUDASharedAttr>())
1051 if (d->
hasAttr<CUDADeviceAttr>())
1059 if (langOpts.OpenMP)
1060 errorNYI(
"OpenMP global address space");
1073 gv.
setLinkage(cir::GlobalLinkageKind::ExternalWeakLinkage);
1082 auto linkage = cir::GlobalLinkageKind::ExternalWeakLinkage;
1083 func.setLinkage(linkage);
1084 func.setLinkageAttr(
1085 cir::GlobalLinkageKindAttr::get(&cgm.
getMLIRContext(), linkage));
1087 if (!func.isDeclaration())
1088 mlir::SymbolTable::setSymbolVisibility(
1095 for (mlir::Attribute i : indexes) {
1096 auto ind = mlir::cast<mlir::IntegerAttr>(i);
1097 inds.push_back(ind.getValue().getSExtValue());
1103 return view.getSymbol().getValue() == glob.getSymName();
1107 cir::GlobalOp newGlob,
1108 cir::GlobalViewAttr
attr,
1119 mlir::Type newTy = newGlob.getSymType();
1125 return cir::GlobalOffsetAttr::get(
attr.getType(),
attr.getSymbol(),
1126 static_cast<int64_t
>(offset));
1128 cir::PointerType newPtrTy;
1131 newPtrTy = cir::PointerType::get(newTy);
1140 cgm.
errorNYI(
"Unhandled type in createNewGlobalView");
1146 mlir::Attribute oldInit) {
1147 if (
auto oldView = mlir::dyn_cast<cir::GlobalViewAttr>(oldInit))
1152 if (mlir::isa<cir::GlobalOffsetAttr>(oldInit))
1155 auto getNewInitElements =
1156 [&](mlir::ArrayAttr oldElements) -> mlir::ArrayAttr {
1158 for (mlir::Attribute elt : oldElements) {
1159 if (
auto view = mlir::dyn_cast<cir::GlobalViewAttr>(elt))
1161 else if (mlir::isa<cir::ConstArrayAttr, cir::ConstRecordAttr>(elt))
1164 newElements.push_back(elt);
1166 return mlir::ArrayAttr::get(cgm.
getBuilder().getContext(), newElements);
1169 if (
auto oldArray = mlir::dyn_cast<cir::ConstArrayAttr>(oldInit)) {
1175 mlir::Attribute oldElts = oldArray.getElts();
1176 if (mlir::isa<mlir::StringAttr>(oldElts))
1178 mlir::Attribute newElements =
1179 getNewInitElements(mlir::cast<mlir::ArrayAttr>(oldElts));
1181 newElements, mlir::cast<cir::ArrayType>(oldArray.getType()));
1183 if (
auto oldRecord = mlir::dyn_cast<cir::ConstRecordAttr>(oldInit)) {
1184 mlir::ArrayAttr newMembers = getNewInitElements(oldRecord.getMembers());
1185 auto recordTy = mlir::cast<cir::RecordType>(oldRecord.getType());
1191 cgm.
errorNYI(
"Unhandled type in getNewInitValue");
1199 assert(oldGV.getSymName() == newGV.getSymName() &&
"symbol names must match");
1201 mlir::Type oldTy = oldGV.getSymType();
1202 mlir::Type newTy = newGV.getSymType();
1207 assert(oldTy != newTy &&
"expected type change in replaceGlobal");
1210 std::optional<mlir::SymbolTable::UseRange> oldSymUses =
1211 oldGV.getSymbolUses(theModule);
1212 for (mlir::SymbolTable::SymbolUse use : *oldSymUses) {
1213 mlir::Operation *userOp = use.getUser();
1215 (mlir::isa<cir::GetGlobalOp, cir::GlobalOp, cir::ConstantOp>(userOp)) &&
1216 "Unexpected user for global op");
1218 if (
auto getGlobalOp = dyn_cast<cir::GetGlobalOp>(use.getUser())) {
1219 mlir::Value useOpResultValue = getGlobalOp.getAddr();
1220 useOpResultValue.setType(cir::PointerType::get(newTy));
1222 mlir::OpBuilder::InsertionGuard guard(builder);
1223 builder.setInsertionPointAfter(getGlobalOp);
1224 mlir::Type ptrTy = builder.getPointerTo(oldTy);
1226 builder.createBitcast(getGlobalOp->getLoc(), useOpResultValue, ptrTy);
1227 useOpResultValue.replaceAllUsesExcept(
cast,
cast.getDefiningOp());
1228 }
else if (
auto glob = dyn_cast<cir::GlobalOp>(userOp)) {
1229 if (
auto init = glob.getInitialValue()) {
1230 mlir::Attribute nw =
getNewInitValue(*
this, newGV, oldTy, init.value());
1231 glob.setInitialValueAttr(nw);
1233 }
else if (
auto c = dyn_cast<cir::ConstantOp>(userOp)) {
1234 mlir::Attribute init =
getNewInitValue(*
this, newGV, oldTy, c.getValue());
1235 auto typedAttr = mlir::cast<mlir::TypedAttr>(init);
1236 mlir::OpBuilder::InsertionGuard guard(builder);
1237 builder.setInsertionPointAfter(c);
1238 auto newUser = cir::ConstantOp::create(builder, c.getLoc(), typedAttr);
1239 c.replaceAllUsesWith(newUser.getOperation());
1275 cir::GlobalOp entry;
1279 "getOrCreateCIRGlobal: global with non-GlobalOp type");
1284 mlir::ptr::MemorySpaceAttrInterface entryCIRAS = entry.getAddrSpaceAttr();
1290 if (entry.getSymType() == ty &&
1300 if (isForDefinition && !entry.isDeclaration()) {
1302 "getOrCreateCIRGlobal: global with conflicting type");
1310 if (!isForDefinition)
1319 bool isConstant =
false;
1321 QualType declType = d->
getType();
1336 mlir::ptr::MemorySpaceAttrInterface declCIRAS =
1341 cir::GlobalOp gv =
createGlobalOp(loc, mangledName, ty, isConstant, declCIRAS,
1342 entry.getOperation());
1362 if (langOpts.OpenMP && !langOpts.OpenMPSimd)
1364 "getOrCreateCIRGlobal: OpenMP target global variable");
1366 gv.setAlignmentAttr(
getSize(astContext.getDeclAlign(d)));
1377 if (astContext.isMSStaticDataMemberInlineDefinition(d))
1379 "getOrCreateCIRGlobal: MS static data member inline definition");
1383 if (
const SectionAttr *sa = d->
getAttr<SectionAttr>())
1384 gv.setSectionAttr(builder.getStringAttr(sa->getName()));
1388 if (
getTriple().getArch() == llvm::Triple::xcore)
1390 "getOrCreateCIRGlobal: XCore specific ABI requirements");
1400 "getOrCreateCIRGlobal: external const declaration with initializer");
1412 "getOrCreateCIRGlobal: HIP managed attribute");
1447 mlir::Type ptrTy = builder.getPointerTo(g.getSymType(), g.getAddrSpaceAttr());
1448 mlir::Value addr = cir::GetGlobalOp::create(
1451 g.getStaticLocalGuard().has_value());
1460 auto ptrTy = mlir::cast<cir::PointerType>(addr.getType());
1461 mlir::ptr::MemorySpaceAttrInterface declAS =
1463 if (ptrTy.getAddrSpace() == declAS)
1465 return builder.createAddrSpaceCast(
1466 addr, builder.getPointerTo(ptrTy.getPointee(), declAS));
1474 cir::PointerType ptrTy =
1475 builder.getPointerTo(globalOp.getSymType(), globalOp.getAddrSpaceAttr());
1476 return builder.getGlobalViewAttr(ptrTy, globalOp);
1480 assert((mlir::isa<cir::FuncOp>(gv.getOperation()) ||
1481 !gv.isDeclarationForLinker()) &&
1482 "Only globals with definition can force usage.");
1487 assert(!gv.isDeclarationForLinker() &&
1488 "Only globals with definition can force usage.");
1493 cir::CIRGlobalValueInterface gv) {
1494 assert((mlir::isa<cir::FuncOp>(gv.getOperation()) ||
1495 !gv.isDeclarationForLinker()) &&
1496 "Only globals with definition can force usage.");
1504 std::vector<cir::CIRGlobalValueInterface> &list) {
1509 mlir::Location loc = builder.getUnknownLoc();
1511 usedArray.resize(list.size());
1512 for (
auto [i, op] : llvm::enumerate(list)) {
1513 usedArray[i] = cir::GlobalViewAttr::get(
1514 cgm.
voidPtrTy, mlir::FlatSymbolRefAttr::get(op.getNameAttr()));
1517 cir::ArrayType arrayTy = cir::ArrayType::get(cgm.
voidPtrTy, usedArray.size());
1519 cir::ConstArrayAttr initAttr = cir::ConstArrayAttr::get(
1520 arrayTy, mlir::ArrayAttr::get(&cgm.
getMLIRContext(), usedArray));
1524 gv.setLinkage(cir::GlobalLinkageKind::AppendingLinkage);
1525 gv.setInitialValueAttr(initAttr);
1526 gv.setSectionAttr(builder.getStringAttr(
"llvm.metadata"));
1543 "emitGlobalVarDefinition: emit OpenMP global variable");
1550 bool isDefinitionAvailableExternally =
1555 if (isDefinitionAvailableExternally &&
1563 mlir::Attribute init;
1564 bool needsGlobalCtor =
false;
1565 bool needsGlobalDtor =
1566 !isDefinitionAvailableExternally &&
1571 std::optional<ConstantEmitter> emitter;
1576 bool isCUDASharedVar =
1581 bool isCUDAShadowVar =
1583 (vd->
hasAttr<CUDAConstantAttr>() || vd->
hasAttr<CUDADeviceAttr>() ||
1584 vd->
hasAttr<CUDASharedAttr>());
1585 bool isCUDADeviceShadowVar =
1591 (isCUDASharedVar || isCUDAShadowVar || isCUDADeviceShadowVar)) {
1593 }
else if (vd->
hasAttr<LoaderUninitializedAttr>()) {
1595 "emitGlobalVarDefinition: loader uninitialized attribute");
1596 }
else if (!initExpr) {
1609 emitter.emplace(*
this);
1610 mlir::Attribute initializer = emitter->tryEmitForInitializer(*initDecl);
1619 "emitGlobalVarDefinition: flexible array initializer");
1621 if (!isDefinitionAvailableExternally)
1622 needsGlobalCtor =
true;
1625 "emitGlobalVarDefinition: static initializer");
1636 mlir::Type initType;
1637 if (mlir::isa<mlir::SymbolRefAttr>(init)) {
1640 "emitGlobalVarDefinition: global initializer is a symbol reference");
1643 assert(mlir::isa<mlir::TypedAttr>(init) &&
"This should have a type");
1644 auto typedInitAttr = mlir::cast<mlir::TypedAttr>(init);
1645 initType = typedInitAttr.getType();
1647 assert(!mlir::isa<mlir::NoneType>(initType) &&
"Should have a type by now");
1653 if (!gv || gv.getSymType() != initType) {
1655 "emitGlobalVarDefinition: global initializer with type mismatch");
1661 if (vd->
hasAttr<AnnotateAttr>())
1674 if (langOpts.CUDA) {
1675 if (langOpts.CUDAIsDevice) {
1678 if (linkage != cir::GlobalLinkageKind::InternalLinkage &&
1680 (vd->
hasAttr<CUDADeviceAttr>() || vd->
hasAttr<CUDAConstantAttr>() ||
1683 gv->setAttr(cir::CUDAExternallyInitializedAttr::getMnemonic(),
1696 emitter->finalize(gv);
1700 gv.setConstant((vd->
hasAttr<CUDAConstantAttr>() && langOpts.CUDAIsDevice) ||
1701 (!needsGlobalCtor && !needsGlobalDtor &&
1706 if (
const SectionAttr *sa = vd->
getAttr<SectionAttr>()) {
1709 gv.setConstant(
true);
1713 gv.setLinkage(linkage);
1717 if (linkage == cir::GlobalLinkageKind::CommonLinkage) {
1719 gv.setConstant(
false);
1724 std::optional<mlir::Attribute> initializer = gv.getInitialValue();
1725 if (initializer && !
getBuilder().isNullValue(*initializer))
1726 gv.setLinkage(cir::GlobalLinkageKind::WeakAnyLinkage);
1729 setNonAliasAttributes(vd, gv);
1737 if (needsGlobalCtor || needsGlobalDtor)
1743 cir::GlobalLinkageKind::AvailableExternallyLinkage)
1749 if (fd->isInlineBuiltinDeclaration())
1752 if (codeGenOpts.OptimizationLevel == 0 && !fd->hasAttr<AlwaysInlineAttr>())
1757 if (
const Module *m = fd->getOwningModule();
1759 getASTContext().getCurrentNamedModule() != m->getTopLevelModule()) {
1760 errorNYI(fd->getSourceRange(),
"should emit function in a named module");
1763 if (fd->hasAttr<NoInlineAttr>())
1774 mlir::Operation *op) {
1776 if (
const auto *fd = dyn_cast<FunctionDecl>(
decl)) {
1780 if (
const auto *method = dyn_cast<CXXMethodDecl>(
decl)) {
1784 abi->emitCXXStructor(gd);
1785 else if (fd->isMultiVersion())
1786 errorNYI(method->getSourceRange(),
"multiversion functions");
1790 if (method->isVirtual())
1796 if (fd->isMultiVersion())
1797 errorNYI(fd->getSourceRange(),
"multiversion functions");
1802 if (
const auto *vd = dyn_cast<VarDecl>(
decl))
1805 llvm_unreachable(
"Invalid argument to CIRGenModule::emitGlobalDefinition");
1819 astContext.getAsConstantArrayType(e->
getType());
1820 uint64_t finalSize = cat->getZExtSize();
1821 str.resize(finalSize);
1823 mlir::Type eltTy =
convertType(cat->getElementType());
1824 return builder.getString(str, eltTy, finalSize,
false);
1829 auto arrayEltTy = mlir::cast<cir::IntType>(arrayTy.getElementType());
1831 uint64_t arraySize = arrayTy.getSize();
1833 assert(arraySize > literalSize &&
1834 "wide string literal array size must have room for null terminator?");
1838 bool isAllZero =
true;
1839 for (
unsigned i = 0; i < literalSize; ++i) {
1847 return cir::ZeroAttr::get(arrayTy);
1851 elements.reserve(arraySize);
1852 for (
unsigned i = 0; i < literalSize; ++i)
1853 elements.push_back(cir::IntAttr::get(
1854 arrayEltTy, llvm::APInt(arrayEltTy.getWidth(), e->
getCodeUnit(i))));
1856 auto elementsAttr = mlir::ArrayAttr::get(&
getMLIRContext(), elements);
1857 return builder.getConstArray(elementsAttr, arrayTy);
1867 if (
auto globalOp = dyn_cast_or_null<cir::GlobalOp>(op)) {
1868 globalOp.setSelfComdat();
1871 funcOp.setSelfComdat();
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));
1979cir::GlobalLinkageKind
1983 return cir::GlobalLinkageKind::InternalLinkage;
1986 return cir::GlobalLinkageKind::WeakAnyLinkage;
1990 return cir::GlobalLinkageKind::LinkOnceAnyLinkage;
1995 return cir::GlobalLinkageKind::AvailableExternallyLinkage;
2009 return !astContext.getLangOpts().AppleKext
2010 ? cir::GlobalLinkageKind::LinkOnceODRLinkage
2011 : cir::GlobalLinkageKind::InternalLinkage;
2025 return cir::GlobalLinkageKind::ExternalLinkage;
2028 return dd->
hasAttr<CUDAGlobalAttr>()
2029 ? cir::GlobalLinkageKind::ExternalLinkage
2030 : cir::GlobalLinkageKind::InternalLinkage;
2031 return cir::GlobalLinkageKind::WeakODRLinkage;
2039 return cir::GlobalLinkageKind::CommonLinkage;
2045 if (dd->
hasAttr<SelectAnyAttr>())
2046 return cir::GlobalLinkageKind::WeakODRLinkage;
2050 return cir::GlobalLinkageKind::ExternalLinkage;
2062 mlir::Operation *old, cir::FuncOp newFn) {
2064 auto oldFn = mlir::dyn_cast<cir::FuncOp>(old);
2072 unsigned numInherentAttrs = 0;
2073 oldFn->getName().walkInherentAttrs(
2074 oldFn, [&](llvm::StringRef, mlir::Attribute &
attr) {
2077 if (numInherentAttrs <= 1)
2079 "replaceUsesOfNonProtoTypeWithRealFunction: Attribute forwarding");
2082 newFn.setNoProto(oldFn.getNoProto());
2085 std::optional<mlir::SymbolTable::UseRange> symUses =
2086 oldFn.getSymbolUses(oldFn->getParentOp());
2091 for (
const mlir::SymbolTable::SymbolUse &use : symUses.value()) {
2092 mlir::OpBuilder::InsertionGuard guard(builder);
2094 if (
auto noProtoCallOp = mlir::dyn_cast<cir::CallOp>(use.getUser())) {
2095 builder.setInsertionPoint(noProtoCallOp);
2098 cir::FuncType newFnType = newFn.getFunctionType();
2099 mlir::OperandRange callOperands = noProtoCallOp.getOperands();
2100 bool returnTypeMatches =
2101 newFnType.hasVoidReturn()
2102 ? noProtoCallOp.getNumResults() == 0
2103 : noProtoCallOp.getNumResults() == 1 &&
2104 noProtoCallOp.getResultTypes().front() ==
2105 newFnType.getReturnType();
2106 bool typesMatch = !newFn.getNoProto() && returnTypeMatches &&
2107 callOperands.size() == newFnType.getNumInputs();
2108 for (
unsigned i = 0, e = newFnType.getNumInputs(); typesMatch && i != e;
2110 if (callOperands[i].
getType() != newFnType.getInput(i))
2114 cir::CallOp realCallOp;
2118 builder.createCallOp(noProtoCallOp.getLoc(), newFn, callOperands);
2126 cir::FuncType origFnType = oldFn.getFunctionType();
2127 cir::FuncType callFnType =
2129 ? cir::FuncType::get(llvm::to_vector(callOperands.getTypes()),
2130 origFnType.getReturnType(),
2133 mlir::Value addr = cir::GetGlobalOp::create(
2134 builder, noProtoCallOp.getLoc(), cir::PointerType::get(newFnType),
2135 newFn.getSymName());
2136 mlir::Value casted =
2137 builder.createBitcast(addr, cir::PointerType::get(callFnType));
2138 realCallOp = builder.createIndirectCallOp(
2139 noProtoCallOp.getLoc(), casted, callFnType, callOperands);
2143 noProtoCallOp.replaceAllUsesWith(realCallOp);
2144 noProtoCallOp.erase();
2145 }
else if (
auto getGlobalOp =
2146 mlir::dyn_cast<cir::GetGlobalOp>(use.getUser())) {
2153 mlir::Value res = getGlobalOp.getAddr();
2154 const mlir::Type oldResTy = res.getType();
2155 const auto newPtrTy = cir::PointerType::get(newFn.getFunctionType());
2156 if (oldResTy != newPtrTy) {
2157 res.setType(newPtrTy);
2158 builder.setInsertionPointAfter(getGlobalOp.getOperation());
2159 mlir::Value castRes =
2160 cir::CastOp::create(builder, getGlobalOp.getLoc(), oldResTy,
2161 cir::CastKind::bitcast, res);
2162 res.replaceAllUsesExcept(castRes, castRes.getDefiningOp());
2164 }
else if (mlir::isa<cir::GlobalOp>(use.getUser())) {
2170 "replaceUsesOfNonProtoTypeWithRealFunction: unexpected use type");
2175cir::GlobalLinkageKind
2177 GVALinkage linkage = astContext.GetGVALinkageForVariable(vd);
2184 GVALinkage linkage = astContext.GetGVALinkageForFunction(d);
2186 if (
const auto *dtor = dyn_cast<CXXDestructorDecl>(d))
2195 StringRef globalName,
CharUnits alignment) {
2206 gv.setAlignmentAttr(cgm.
getSize(alignment));
2208 cir::GlobalLinkageKindAttr::get(cgm.
getBuilder().getContext(), lt));
2212 if (gv.isWeakForLinker()) {
2213 assert(cgm.
supportsCOMDAT() &&
"Only COFF uses weak string literals");
2216 cgm.
setDSOLocal(
static_cast<mlir::Operation *
>(gv));
2237 std::string result =
2248 astContext.getAlignOfGlobalVarInChars(s->
getType(),
nullptr);
2256 if (!gv.getAlignment() ||
2257 uint64_t(alignment.
getQuantity()) > *gv.getAlignment())
2258 gv.setAlignmentAttr(
getSize(alignment));
2263 if (
getCXXABI().getMangleContext().shouldMangleStringLiteral(s) &&
2266 "getGlobalForStringLiteral: mangle string literals");
2276 : builder.getUnknownLoc();
2277 auto typedC = llvm::cast<mlir::TypedAttr>(c);
2279 cir::GlobalLinkageKind::PrivateLinkage, *
this,
2280 uniqueName, alignment);
2294 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(gv.getSymType());
2295 assert(arrayTy &&
"String literal must be array");
2297 arrayTy.getElementType(),
2300 return builder.getGlobalViewAttr(ptrTy, gv);
2310 errorNYI(
"SYCL global constant address space");
2342 "emitExplicitCastExprType");
2348 auto ty = mlir::cast<cir::MethodType>(
convertType(destTy));
2349 return builder.getNullMethodAttr(ty);
2352 auto ty = mlir::cast<cir::DataMemberType>(
convertType(destTy));
2353 return builder.getNullDataMemberAttr(ty);
2364 if (
const auto *methodDecl = dyn_cast<CXXMethodDecl>(
decl)) {
2366 if (methodDecl->isVirtual())
2367 return cir::ConstantOp::create(
2368 builder, loc,
getCXXABI().buildVirtualMethodAttr(ty, methodDecl));
2374 return cir::ConstantOp::create(builder, loc,
2375 builder.getMethodAttr(ty, methodFuncOp));
2390 assert(
fieldDecl->getParent() == destClass &&
2391 "scalar member pointer should be relative to the declaring class");
2393 astContext.toCharUnitsFromBits(astContext.getFieldOffset(
fieldDecl))
2395 return cir::ConstantOp::create(builder, loc,
2396 cir::DataMemberOffsetAttr::get(ty, offset));
2399 std::optional<llvm::SmallVector<int32_t>> path =
2403 return cir::ConstantOp::create(builder, loc,
2404 builder.getDataMemberAttr(ty, *path));
2407std::optional<llvm::SmallVector<int32_t>>
2415 if (
const auto *indirectField = dyn_cast<IndirectFieldDecl>(
decl)) {
2417 for (
const NamedDecl *nd : indirectField->chain()) {
2419 if (!findFieldMemberPath(currentClass, field, path))
2420 return std::nullopt;
2421 currentClass = field->getType()->getAsCXXRecordDecl();
2427 return std::nullopt;
2431bool CIRGenModule::findFieldMemberPath(
const CXXRecordDecl *currentClass,
2441 if (currentClass->
isUnion()) {
2447 "data member pointer for non-zero-initializable union");
2454 path.push_back(fieldIdx);
2462 for (
const CXXBaseSpecifier &base : currentClass->
bases()) {
2463 const auto *baseDecl =
2466 if (base.isVirtual()) {
2471 llvm::SmallVector<int32_t> discardedPath;
2472 if (findFieldMemberPath(baseDecl, field, discardedPath)) {
2474 "data member pointer through virtual base");
2487 path.push_back(baseFieldIdx);
2488 if (findFieldMemberPath(baseDecl, field, path))
2516 if (
auto *oid = dyn_cast<ObjCImplDecl>(
decl))
2517 errorNYI(oid->getSourceRange(),
"emitDeclConext: ObjCImplDecl");
2527 if (
decl->isTemplated())
2530 switch (
decl->getKind()) {
2533 decl->getDeclKindName());
2536 case Decl::CXXConversion:
2537 case Decl::CXXMethod:
2538 case Decl::Function: {
2541 if (!fd->isConsteval())
2550 case Decl::Decomposition:
2551 case Decl::VarTemplateSpecialization: {
2553 if (
auto *decomp = dyn_cast<DecompositionDecl>(
decl))
2554 for (
auto *binding : decomp->flat_bindings())
2555 if (
auto *holdingVar = binding->getHoldingVar())
2559 case Decl::OpenACCRoutine:
2562 case Decl::OpenACCDeclare:
2565 case Decl::OMPThreadPrivate:
2568 case Decl::OMPGroupPrivate:
2571 case Decl::OMPAllocate:
2574 case Decl::OMPCapturedExpr:
2577 case Decl::OMPDeclareReduction:
2580 case Decl::OMPDeclareMapper:
2583 case Decl::OMPRequires:
2588 case Decl::UsingDirective:
2589 case Decl::UsingEnum:
2590 case Decl::NamespaceAlias:
2592 case Decl::TypeAlias:
2599 case Decl::IndirectField:
2603 case Decl::ClassTemplate:
2605 case Decl::CXXDeductionGuide:
2607 case Decl::ExplicitInstantiation:
2608 case Decl::FunctionTemplate:
2609 case Decl::StaticAssert:
2610 case Decl::TypeAliasTemplate:
2611 case Decl::UsingShadow:
2612 case Decl::VarTemplate:
2613 case Decl::VarTemplatePartialSpecialization:
2616 case Decl::CXXConstructor:
2619 case Decl::CXXDestructor:
2624 case Decl::LinkageSpec:
2625 case Decl::Namespace:
2629 case Decl::ClassTemplateSpecialization:
2630 case Decl::CXXRecord: {
2633 for (
auto *childDecl : crd->
decls())
2639 case Decl::FileScopeAsm:
2641 if (langOpts.CUDA && langOpts.CUDAIsDevice)
2644 if (langOpts.OpenMPIsTargetDevice)
2647 if (langOpts.SYCLIsDevice)
2650 std::string line = file_asm->getAsmString();
2651 globalScopeAsm.push_back(builder.getStringAttr(line));
2658 op.setInitialValueAttr(value);
2672 md->getParent()->getNumVBases() == 0)
2674 "getAddrAndTypeOfCXXStructor: MS ABI complete destructor");
2685 false, isForDefinition);
2687 return {fnType, fn};
2691 mlir::Type funcType,
bool forVTable,
2695 "consteval function should never be emitted");
2705 if (
const auto *dd = dyn_cast<CXXDestructorDecl>(gd.
getDecl())) {
2708 dd->getParent()->getNumVBases() == 0)
2710 "getAddrOfFunction: MS ABI complete destructor");
2716 false, isForDefinition);
2718 if (langOpts.CUDA && !langOpts.CUDAIsDevice &&
2724 bool isHIPHandle = mlir::isa<cir::GlobalOp>(*handle);
2725 if (isForDefinition || isHIPHandle)
2727 return mlir::dyn_cast<cir::FuncOp>(*handle);
2736 llvm::raw_svector_ostream
out(buffer);
2745 assert(ii &&
"Attempt to mangle unnamed decl.");
2747 const auto *fd = dyn_cast<FunctionDecl>(nd);
2751 }
else if (fd && fd->hasAttr<CUDAGlobalAttr>() &&
2755 DeviceKernelAttr::isOpenCLSpelling(
2756 fd->getAttr<DeviceKernelAttr>()) &&
2773 if (
const auto *fd = dyn_cast<FunctionDecl>(nd)) {
2774 if (fd->isMultiVersion()) {
2776 "getMangledName: multi-version functions");
2784 "getMangledName: GPU relocatable device code");
2787 return std::string(
out.str());
2790static FunctionDecl *
2805 if (
auto *methodDecl = dyn_cast<CXXMethodDecl>(protoFunc);
2806 methodDecl && methodDecl->isImplicitObjectMemberFunction()) {
2808 paramTypes.insert(paramTypes.begin(), methodDecl->getThisType());
2811 fpt->getExtProtoInfo());
2822 params.reserve(fpt->getNumParams());
2825 for (
unsigned i = 0, e = fpt->getNumParams(); i != e; ++i) {
2829 nullptr, fpt->getParamType(i),
nullptr,
2832 params.push_back(parm);
2835 tempFunc->setParams(params);
2860 if (
const auto *cd = dyn_cast<CXXConstructorDecl>(canonicalGd.
getDecl())) {
2863 "getMangledName: C++ constructor without variants");
2872 if (!langOpts.CUDAIsDevice || !astContext.mayExternalize(gd.
getDecl())) {
2873 auto foundName = mangledDeclNames.find(canonicalGd);
2874 if (foundName != mangledDeclNames.end())
2875 return foundName->second;
2882 auto result = manglings.insert(std::make_pair(mangledName, gd));
2883 return mangledDeclNames[canonicalGd] = result.first->first();
2887 assert(!d->
getInit() &&
"Cannot emit definite definitions here!");
2895 if (gv && !mlir::cast<cir::GlobalOp>(gv).isDeclaration())
2911 if (langOpts.EmitAllDecls)
2914 const auto *vd = dyn_cast<VarDecl>(global);
2916 ((codeGenOpts.KeepPersistentStorageVariables &&
2917 (vd->getStorageDuration() ==
SD_Static ||
2918 vd->getStorageDuration() ==
SD_Thread)) ||
2919 (codeGenOpts.KeepStaticConsts && vd->getStorageDuration() ==
SD_Static &&
2920 vd->getType().isConstQualified())))
2933 if (langOpts.OpenMP >= 50 && !langOpts.OpenMPSimd) {
2934 std::optional<OMPDeclareTargetDeclAttr *> activeAttr =
2935 OMPDeclareTargetDeclAttr::getActiveAttr(global);
2936 if (!activeAttr || (*activeAttr)->getLevel() != (
unsigned)-1)
2940 const auto *fd = dyn_cast<FunctionDecl>(global);
2947 if (fd->hasAttr<TargetVersionAttr>() && !fd->isMultiVersion())
2951 if (langOpts.SYCLIsDevice && fd->hasAttr<SYCLKernelEntryPointAttr>())
2954 const auto *vd = dyn_cast<VarDecl>(global);
2956 if (astContext.getInlineVariableDefinitionKind(vd) ==
2964 if (langOpts.OpenMP && langOpts.OpenMPUseTLS &&
2965 astContext.getTargetInfo().isTLSSupported() &&
isa<VarDecl>(global) &&
2967 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(global))
2970 assert((fd || vd) &&
2971 "Only FunctionDecl and VarDecl should hit this path so far.");
2976 cir::CIRGlobalValueInterface gv) {
2977 if (gv.hasLocalLinkage())
2980 if (!gv.hasDefaultVisibility() && !gv.hasExternalWeakLinkage())
2988 const llvm::Triple &tt = cgm.
getTriple();
2990 if (tt.isOSCygMing()) {
2999 cgm.
errorNYI(
"shouldAssumeDSOLocal: MinGW");
3005 if (tt.isOSBinFormatCOFF() && gv.hasExternalWeakLinkage())
3013 if (tt.isOSBinFormatCOFF() || (tt.isOSWindows() && tt.isOSBinFormatMachO()))
3017 if (!tt.isOSBinFormatELF())
3022 if (rm != llvm::Reloc::Static && !lOpts.PIE) {
3030 return !(lOpts.SemanticInterposition || lOpts.HalfNoSemanticInterposition);
3034 if (!gv.isDeclarationForLinker())
3040 if (rm == llvm::Reloc::PIC_ && gv.hasExternalWeakLinkage())
3047 if (cgOpts.DirectAccessExternalData) {
3053 if (
auto globalOp = dyn_cast<cir::GlobalOp>(gv.getOperation())) {
3079 if (gv.hasLocalLinkage()) {
3080 gv.setGlobalVisibility(cir::VisibilityKind::Default);
3095 d->
hasAttr<OMPDeclareTargetDeclAttr>() &&
3096 d->
getAttr<OMPDeclareTargetDeclAttr>()->getDevType() !=
3097 OMPDeclareTargetDeclAttr::DT_NoHost &&
3099 llvm_unreachable(
"setGlobalVisibility: OpenMP is NYI");
3108 !d->
hasAttr<OMPDeclareTargetDeclAttr>()) {
3109 bool needsProtected =
false;
3113 }
else if (
const auto *vd = dyn_cast<VarDecl>(d)) {
3114 needsProtected = vd->hasAttr<CUDADeviceAttr>() ||
3115 vd->hasAttr<CUDAConstantAttr>() ||
3116 vd->getType()->isCUDADeviceBuiltinSurfaceType() ||
3117 vd->getType()->isCUDADeviceBuiltinTextureType();
3119 if (needsProtected) {
3120 gv.setGlobalVisibility(cir::VisibilityKind::Protected);
3126 gv.setGlobalVisibility(cir::VisibilityKind::Hidden);
3133 !gv.isDeclarationForLinker())
3142 if (
auto globalValue = dyn_cast<cir::CIRGlobalValueInterface>(op))
3161 auto res = manglings.find(mangledName);
3162 if (res == manglings.end())
3164 result = res->getValue();
3169 return llvm::StringSwitch<cir::TLSModel>(S)
3170 .Case(
"global-dynamic", cir::TLSModel::GeneralDynamic)
3171 .Case(
"local-dynamic", cir::TLSModel::LocalDynamic)
3172 .Case(
"initial-exec", cir::TLSModel::InitialExec)
3173 .Case(
"local-exec", cir::TLSModel::LocalExec);
3179 return cir::TLSModel::GeneralDynamic;
3181 return cir::TLSModel::LocalDynamic;
3183 return cir::TLSModel::InitialExec;
3185 return cir::TLSModel::LocalExec;
3187 llvm_unreachable(
"Invalid TLS model!");
3191 bool isExtendingDecl) {
3192 assert(d.
getTLSKind() &&
"setting TLS mode on non-TLS var!");
3201 global.setTlsModel(tlm);
3211 if (isExtendingDecl)
3219 cir::FuncOp func,
bool isThunk) {
3221 cir::CallingConv callingConv;
3228 mlir::NamedAttrList pal{};
3229 std::vector<mlir::NamedAttrList> argAttrs(info.arguments().size());
3230 mlir::NamedAttrList retAttrs{};
3232 retAttrs, callingConv,
3235 for (mlir::NamedAttribute
attr : pal)
3236 func->setAttr(
attr.getName(),
attr.getValue());
3238 llvm::for_each(llvm::enumerate(argAttrs), [func](
auto idx_arg_pair) {
3239 mlir::function_interface_impl::setArgAttrs(func, idx_arg_pair.index(),
3240 idx_arg_pair.value());
3242 if (!retAttrs.empty())
3243 mlir::function_interface_impl::setResultAttrs(func, 0, retAttrs);
3247 func.setCallingConv(callingConv);
3252 bool isIncompleteFunction,
3260 if (!isIncompleteFunction)
3262 getTypes().arrangeGlobalDeclaration(globalDecl),
3265 if (!isIncompleteFunction && func.isDeclaration())
3270 if (
const auto *errorAttr = funcDecl->getAttr<ErrorAttr>()) {
3271 if (errorAttr->isError())
3272 func->setAttr(cir::CIRDialect::getDontCallErrorAttrName(),
3274 errorAttr->getUserDiagnostic()));
3275 else if (errorAttr->isWarning())
3276 func->setAttr(cir::CIRDialect::getDontCallWarnAttrName(),
3278 errorAttr->getUserDiagnostic()));
3285 if (funcDecl->isInlineBuiltinDeclaration()) {
3287 bool hasBody = funcDecl->
hasBody(fdBody);
3289 assert(hasBody &&
"Inline builtin declarations should always have an "
3294 if (funcDecl->isReplaceableGlobalAllocationFunction()) {
3297 func->setAttr(cir::CIRDialect::getNoBuiltinAttrName(),
3305 if ((!
decl || !
decl->hasAttr<NoUwtableAttr>()) && codeGenOpts.UnwindTables)
3306 f.setUwtable(
static_cast<cir::UnwindTableKind
>(codeGenOpts.UnwindTables));
3311 f->setAttr(cir::CIRDialect::getNoThrowAttrName(),
3314 std::optional<cir::InlineKind> existingInlineKind = f.getInlineKind();
3316 existingInlineKind && *existingInlineKind == cir::InlineKind::NoInline;
3317 bool isAlwaysInline = existingInlineKind &&
3318 *existingInlineKind == cir::InlineKind::AlwaysInline;
3322 if (!isAlwaysInline &&
3327 f.setInlineKind(cir::InlineKind::NoInline);
3342 if (
decl->hasAttr<NoInlineAttr>() && !isAlwaysInline) {
3344 f.setInlineKind(cir::InlineKind::NoInline);
3345 }
else if (
decl->hasAttr<AlwaysInlineAttr>() && !isNoInline) {
3348 f.setInlineKind(cir::InlineKind::AlwaysInline);
3352 if (!isAlwaysInline)
3353 f.setInlineKind(cir::InlineKind::NoInline);
3358 if (
auto *fd = dyn_cast<FunctionDecl>(
decl)) {
3363 auto checkRedeclForInline = [](
const FunctionDecl *redecl) {
3364 return redecl->isInlineSpecified();
3366 if (any_of(
decl->redecls(), checkRedeclForInline))
3371 return any_of(pattern->
redecls(), checkRedeclForInline);
3373 if (checkForInline(fd)) {
3374 f.setInlineKind(cir::InlineKind::InlineHint);
3375 }
else if (codeGenOpts.getInlining() ==
3377 !fd->isInlined() && !isAlwaysInline) {
3378 f.setInlineKind(cir::InlineKind::NoInline);
3385 std::optional<uint64_t> explicitAlignment;
3386 if (
unsigned alignment =
3388 explicitAlignment = alignment;
3389 else if (langOpts.FunctionAlignment)
3390 explicitAlignment = 1ull << langOpts.FunctionAlignment;
3392 if (explicitAlignment) {
3393 f.setAlignment(*explicitAlignment);
3394 f.setPreferredAlignment(*explicitAlignment);
3395 }
else if (langOpts.PreferredFunctionAlignment) {
3396 f.setPreferredAlignment(langOpts.PreferredFunctionAlignment);
3418static cir::LangAddressSpace
3420 switch (addressSpace) {
3422 return cir::LangAddressSpace::OffloadGlobal;
3424 return cir::LangAddressSpace::OffloadConstant;
3426 return cir::LangAddressSpace::OffloadLocal;
3428 return cir::LangAddressSpace::OffloadGeneric;
3430 return cir::LangAddressSpace::OffloadGlobalDevice;
3432 return cir::LangAddressSpace::OffloadGlobalHost;
3436 return cir::LangAddressSpace::Default;
3442 assert(fd &&
"expected a kernel function declaration");
3455 argNames.push_back(builder.getStringAttr(param->getName()));
3458 std::string typeQuals;
3460 if (
type->isImageType() ||
type->isPipeType()) {
3462 "OpenCL kernel argument metadata for image and pipe types");
3466 accessQuals.push_back(builder.getStringAttr(
"none"));
3468 auto getTypeSpelling = [&](
QualType paramType) {
3469 std::string typeName = paramType.getUnqualifiedType().getAsString(policy);
3471 if (paramType.isCanonical()) {
3472 StringRef typeNameRef = typeName;
3473 if (typeNameRef.consume_front(
"unsigned "))
3474 return std::string(
"u") + typeNameRef.str();
3475 if (typeNameRef.consume_front(
"signed "))
3476 return typeNameRef.str();
3484 if (
type->isPointerType()) {
3486 addressQuals.push_back(cir::LangAddressSpaceAttr::get(
3490 argTypeNames.push_back(
3491 builder.getStringAttr(getTypeSpelling(
pointeeType) +
"*"));
3492 argBaseTypeNames.push_back(builder.getStringAttr(
3493 getTypeSpelling(
pointeeType.getCanonicalType()) +
"*"));
3495 if (
type.isRestrictQualified())
3496 typeQuals =
"restrict";
3499 typeQuals += typeQuals.empty() ?
"const" :
" const";
3501 typeQuals += typeQuals.empty() ?
"volatile" :
" volatile";
3503 addressQuals.push_back(cir::LangAddressSpaceAttr::get(
3506 argTypeNames.push_back(builder.getStringAttr(getTypeSpelling(
type)));
3507 argBaseTypeNames.push_back(
3508 builder.getStringAttr(getTypeSpelling(
type.getCanonicalType())));
3511 argTypeQuals.push_back(builder.getStringAttr(typeQuals));
3514 mlir::ArrayAttr names;
3516 names = builder.getArrayAttr(argNames);
3518 mlir::Attribute metadata = cir::OpenCLKernelArgMetadataAttr::get(
3519 func.getContext(), builder.getArrayAttr(addressQuals),
3520 builder.getArrayAttr(accessQuals), builder.getArrayAttr(argTypeNames),
3521 builder.getArrayAttr(argBaseTypeNames),
3522 builder.getArrayAttr(argTypeQuals), names);
3523 func->setAttr(cir::CIRDialect::getOpenCLKernelArgMetadataAttrName(),
3528 StringRef mangledName, mlir::Type funcType,
GlobalDecl gd,
bool forVTable,
3530 mlir::NamedAttrList extraAttrs) {
3533 if (
const auto *fd = cast_or_null<FunctionDecl>(d)) {
3535 if (
getLangOpts().OpenMPIsTargetDevice && openMPRuntime &&
3537 !dontDefer && !isForDefinition) {
3540 if (
const auto *cd = dyn_cast<CXXConstructorDecl>(fdDef))
3542 else if (
const auto *dd = dyn_cast<CXXDestructorDecl>(fdDef))
3552 if (fd->isMultiVersion())
3553 errorNYI(fd->getSourceRange(),
"getOrCreateCIRFunction: multi-version");
3559 assert(mlir::isa<cir::FuncOp>(entry));
3564 if (d && !d->
hasAttr<DLLImportAttr>() && !d->
hasAttr<DLLExportAttr>()) {
3572 if (isForDefinition && fn && !fn.isDeclaration()) {
3579 diagnosedConflictingDefinitions.insert(gd).second) {
3583 diag::note_previous_definition);
3587 if (fn && fn.getFunctionType() == funcType) {
3591 if (!isForDefinition) {
3599 auto *funcDecl = llvm::cast_or_null<FunctionDecl>(gd.
getDecl());
3600 bool invalidLoc = !funcDecl ||
3601 funcDecl->getSourceRange().getBegin().isInvalid() ||
3602 funcDecl->getSourceRange().getEnd().isInvalid();
3604 invalidLoc ? theModule->getLoc() :
getLoc(funcDecl->getSourceRange()),
3605 mangledName, mlir::cast<cir::FuncType>(funcType), funcDecl);
3607 if (funcDecl && funcDecl->hasAttr<AnnotateAttr>())
3608 deferredAnnotations[mangledName] = funcDecl;
3619 auto symbolOp = mlir::cast<mlir::SymbolOpInterface>(entry);
3627 if (symbolOp.getSymbolUses(symbolOp->getParentOp()))
3637 if (!extraAttrs.empty())
3638 for (mlir::NamedAttribute attr : extraAttrs)
3639 if (!funcOp->hasDiscardableAttr(
attr.getName()))
3640 funcOp->setDiscardableAttr(
attr.getName(),
attr.getValue());
3646 assert(funcOp.getFunctionType() == funcType);
3653 if (isa_and_nonnull<CXXDestructorDecl>(d) &&
3683 fd = fd->getPreviousDecl()) {
3685 if (fd->doesThisDeclarationHaveABody()) {
3698 cir::FuncType funcType,
3702 mlir::OpBuilder::InsertionGuard guard(builder);
3707 builder.setInsertionPointToEnd(theModule.getBody());
3709 func = cir::FuncOp::create(builder, loc, name, funcType);
3716 func.setNoProto(
true);
3718 assert(func.isDeclaration() &&
"expected empty body");
3722 func.setLinkageAttr(cir::GlobalLinkageKindAttr::get(
3724 mlir::SymbolTable::setSymbolVisibility(
3725 func, mlir::SymbolTable::Visibility::Private);
3736 for (
const auto *
attr :
3750 fnOp.setBuiltin(
true);
3756 return cir::CtorKind::Default;
3758 return cir::CtorKind::Copy;
3760 return cir::CtorKind::Move;
3761 return cir::CtorKind::Custom;
3766 return cir::AssignKind::Copy;
3768 return cir::AssignKind::Move;
3769 llvm_unreachable(
"not a copy or move assignment operator");
3777 if (
const auto *dtor = dyn_cast<CXXDestructorDecl>(funcDecl)) {
3778 auto cxxDtor = cir::CXXDtorAttr::get(
3781 funcOp.setFuncInfoAttr(cxxDtor);
3785 if (
const auto *ctor = dyn_cast<CXXConstructorDecl>(funcDecl)) {
3787 auto cxxCtor = cir::CXXCtorAttr::get(
3789 kind, ctor->isTrivial());
3790 funcOp.setFuncInfoAttr(cxxCtor);
3794 const auto *method = dyn_cast<CXXMethodDecl>(funcDecl);
3795 if (method && (method->isCopyAssignmentOperator() ||
3796 method->isMoveAssignmentOperator())) {
3798 auto cxxAssign = cir::CXXAssignAttr::get(
3800 assignKind, method->isTrivial());
3801 funcOp.setFuncInfoAttr(cxxAssign);
3811 bool inStdNamespace = method ? method->getParent()->isInStdNamespace()
3813 if (!inStdNamespace)
3819 std::optional<cir::KnownFuncKind>
kind;
3821 kind = llvm::StringSwitch<std::optional<cir::KnownFuncKind>>(
3823 .Case(cir::StdFindOp::getFunctionName(),
3824 cir::StdFindOp::getFuncKind())
3825 .Default(std::nullopt);
3834 cir::FuncOp funcOp, StringRef name) {
3850 mlir::NamedAttrList extraAttrs,
3852 bool assumeConvergent) {
3853 if (assumeConvergent)
3854 errorNYI(
"createRuntimeFunction: assumeConvergent");
3864 entry.setDSOLocal(
true);
3870mlir::SymbolTable::Visibility
3874 if (op.isDeclaration())
3875 return mlir::SymbolTable::Visibility::Private;
3879mlir::SymbolTable::Visibility
3882 case cir::GlobalLinkageKind::InternalLinkage:
3883 case cir::GlobalLinkageKind::PrivateLinkage:
3884 return mlir::SymbolTable::Visibility::Private;
3885 case cir::GlobalLinkageKind::ExternalLinkage:
3886 case cir::GlobalLinkageKind::ExternalWeakLinkage:
3887 case cir::GlobalLinkageKind::LinkOnceODRLinkage:
3888 case cir::GlobalLinkageKind::AvailableExternallyLinkage:
3889 case cir::GlobalLinkageKind::CommonLinkage:
3890 case cir::GlobalLinkageKind::WeakAnyLinkage:
3891 case cir::GlobalLinkageKind::WeakODRLinkage:
3892 return mlir::SymbolTable::Visibility::Public;
3894 llvm::errs() <<
"visibility not implemented for '"
3895 << stringifyGlobalLinkageKind(glk) <<
"'\n";
3896 assert(0 &&
"not implemented");
3899 llvm_unreachable(
"linkage should be handled above!");
3905 applyReplacements();
3907 theModule->setAttr(cir::CIRDialect::getModuleLevelAsmAttrName(),
3908 builder.getArrayAttr(globalScopeAsm));
3910 emitGlobalAnnotations();
3912 if (!recordLayoutEntries.empty())
3914 cir::CIRDialect::getRecordLayoutsAttrName(),
3915 mlir::DictionaryAttr::get(&
getMLIRContext(), recordLayoutEntries));
3924 std::string cuidName =
3927 auto loc = builder.getUnknownLoc();
3928 mlir::ptr::MemorySpaceAttrInterface addrSpace =
3930 getGlobalVarAddressSpace(
nullptr));
3934 gv.setLinkage(cir::GlobalLinkageKind::ExternalLinkage);
3936 auto zeroAttr = cir::IntAttr::get(int8Ty, 0);
3937 gv.setInitialValueAttr(zeroAttr);
3939 mlir::SymbolTable::setSymbolVisibility(
3940 gv, mlir::SymbolTable::Visibility::Public);
3945 if (astContext.getLangOpts().CUDA && cudaRuntime)
3964 if (langOpts.CPlusPlusModules &&
3967 if (
clang::Module *primary = astContext.getCurrentNamedModule();
3970 llvm::raw_svector_ostream
out(fnName);
3972 .mangleModuleInitializer(primary,
out);
3973 theModule->setAttr(cir::CIRDialect::getCXXModuleInitFnNameAttrName(),
3974 builder.getStringAttr(fnName));
3988 const AliasAttr *aa = d->
getAttr<AliasAttr>();
3989 assert(aa &&
"Not an alias?");
3993 if (aa->getAliasee() == mangledName) {
3994 diags.Report(aa->getLocation(), diag::err_cyclic_alias) << 0;
4002 auto entryGV = mlir::dyn_cast<cir::CIRGlobalValueInterface>(entry);
4003 if (entryGV && entryGV.isDefinition())
4016 cir::GlobalLinkageKind linkage;
4028 cir::CIRGlobalValueInterface alias =
4029 isFunction ? mlir::cast<cir::CIRGlobalValueInterface>(
4031 mlir::cast<cir::FuncType>(declTy),
4034 : mlir::cast<cir::CIRGlobalValueInterface>(
4045 entry, mlir::cast<cir::FuncOp>(alias.getOperation()));
4053 linkage = cir::GlobalLinkageKind::WeakAnyLinkage;
4057 mlir::SymbolTable::Visibility visibility =
4060 alias.setAliasee(aa->getAliasee());
4061 alias.setLinkage(linkage);
4062 mlir::SymbolTable::setSymbolVisibility(alias, visibility);
4070 cir::FuncOp aliasee,
4071 cir::GlobalLinkageKind linkage) {
4073 auto *aliasFD = dyn_cast<FunctionDecl>(aliasGD.
getDecl());
4074 assert(aliasFD &&
"expected FunctionDecl");
4085 mangledName, fnType, aliasFD);
4086 alias.setAliasee(aliasee.getName());
4087 alias.setLinkage(linkage);
4091 mlir::SymbolTable::setSymbolVisibility(
4092 alias, mlir::SymbolTable::Visibility::Private);
4104 "declaration exists with different type");
4116 return genTypes.convertType(
type);
4123 return mlir::verify(theModule).succeeded();
4132 return builder.getConstNullPtrAttr(builder.getUInt8PtrTy());
4135 langOpts.ObjCRuntime.isGNUFamily()) {
4136 errorNYI(loc,
"getAddrOfRTTIDescriptor: Objc PtrType & Objc RT GUN");
4146 llvm::iterator_range<CastExpr::path_const_iterator> path) {
4153 assert(!base->isVirtual() &&
"Should not see virtual bases here!");
4158 const auto *baseDecl = base->getType()->castAsCXXRecordDecl();
4170 llvm::StringRef feature) {
4171 unsigned diagID = diags.getCustomDiagID(
4173 return diags.Report(loc, diagID) << feature;
4177 llvm::StringRef feature) {
4189 "cannot compile this %0 yet");
4190 diags.Report(astContext.getFullLoc(s->
getBeginLoc()), diagId)
4197 "cannot compile this %0 yet");
4198 diags.Report(astContext.getFullLoc(d->
getLocation()), diagId) <<
type;
4206 "not a global temporary");
4218 materializedType = mte->
getType();
4227 llvm::raw_svector_ostream
out(name);
4231 auto insertResult = materializedGlobalTemporaryMap.insert({mte,
nullptr});
4232 if (!insertResult.second) {
4236 if (!insertResult.first->second) {
4239 insertResult.first->second =
4242 return insertResult.first->second;
4259 value = &evalResult.
Val;
4263 std::optional<ConstantEmitter> emitter;
4264 mlir::Attribute initialValue =
nullptr;
4265 bool isConstant =
false;
4269 emitter.emplace(*
this);
4270 initialValue = emitter->emitForInitializer(*value, materializedType);
4275 type = mlir::cast<mlir::TypedAttr>(initialValue).getType();
4284 if (linkage == cir::GlobalLinkageKind::ExternalLinkage) {
4286 if (
varDecl->isStaticDataMember() &&
varDecl->getAnyInitializer(initVD) &&
4294 linkage = cir::GlobalLinkageKind::InternalLinkage;
4298 gv.setInitialValueAttr(initialValue);
4299 gv.setLinkage(linkage);
4303 emitter->finalize(gv);
4305 if (!gv.hasLocalLinkage()) {
4310 gv.setAlignment(align.getAsAlign().value());
4315 mlir::Operation *cv = gv;
4324 mlir::Operation *&entry = materializedGlobalTemporaryMap[mte];
4326 entry->replaceAllUsesWith(cv);
4341 return *globalOpEntry;
4348 "emitForInitializer should take gcd->getType().getAddressSpace()");
4350 auto typedInit = dyn_cast<mlir::TypedAttr>(init);
4354 "getAddrOfUnnamedGlobalConstantDecl: non-typed initializer");
4363 std::string name = numEntries == 0
4365 : (Twine(
".constant.") + Twine(numEntries)).str();
4367 typedInit.getType(),
true);
4368 globalOp.setLinkage(cir::GlobalLinkageKind::PrivateLinkage);
4371 globalOp.setAlignment(alignment.
getAsAlign().value());
4375 *globalOpEntry = globalOp;
4390 "emitForInitializer should take tpo->getType().getAddressSpace()");
4391 mlir::Attribute init =
4401 cir::GlobalLinkageKind linkage =
4403 ? cir::GlobalLinkageKind::LinkOnceODRLinkage
4404 : cir::GlobalLinkageKind::InternalLinkage;
4408 typedInit.getType(),
true);
4409 globalOp.setLinkage(linkage);
4410 globalOp.setAlignment(alignment.
getAsAlign().value());
4411 if (
supportsCOMDAT() && linkage == cir::GlobalLinkageKind::LinkOnceODRLinkage)
4412 globalOp.setSelfComdat();
4427CIRGenModule::getOrCreateAnnotationArgs(
const AnnotateAttr *
attr) {
4434 llvm::FoldingSetNodeID id;
4435 for (
Expr *e : exprs)
4438 mlir::ArrayAttr &lookup = annotationArgs[
id.computeHash()];
4443 args.reserve(exprs.size());
4444 for (
Expr *e : exprs) {
4445 if (
auto *strE = dyn_cast<clang::StringLiteral>(e->IgnoreParenCasts())) {
4446 args.push_back(builder.getStringAttr(strE->getString()));
4447 }
else if (
auto *intE =
4448 dyn_cast<clang::IntegerLiteral>(e->IgnoreParenCasts())) {
4449 auto intTy = builder.getIntegerType(intE->getValue().getBitWidth());
4450 args.push_back(builder.getIntegerAttr(intTy, intE->getValue()));
4452 errorNYI(e->getExprLoc(),
"annotation argument expression");
4456 return lookup = builder.getArrayAttr(args);
4459cir::AnnotationAttr CIRGenModule::emitAnnotateAttr(
const AnnotateAttr *aa) {
4460 mlir::StringAttr annoGV = builder.getStringAttr(aa->getAnnotation());
4461 mlir::ArrayAttr args = getOrCreateAnnotationArgs(aa);
4462 return cir::AnnotationAttr::get(&
getMLIRContext(), annoGV, args);
4466 mlir::Operation *gv) {
4467 assert(d->
hasAttr<AnnotateAttr>() &&
"no annotate attribute");
4469 "annotation only on globals");
4472 annotations.push_back(emitAnnotateAttr(i));
4473 if (
auto global = dyn_cast<cir::GlobalOp>(gv))
4474 global.setAnnotationsAttr(builder.getArrayAttr(annotations));
4475 else if (
auto func = dyn_cast<cir::FuncOp>(gv))
4476 func.setAnnotationsAttr(builder.getArrayAttr(annotations));
4479void CIRGenModule::emitGlobalAnnotations() {
4480 for (
const auto &[mangledName, vd] : deferredAnnotations) {
4485 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 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 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
bool isSameEntity(const NamedDecl *X, const NamedDecl *Y) const
Determine whether the two declarations refer to the same entity.
const clang::PrintingPolicy & getPrintingPolicy() const
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
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.
void addSYCLModuleIdAttr(cir::FuncOp fn)
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.
mlir::Value castGlobalToDeclAddrSpace(mlir::Value addr, const VarDecl &vd)
Cast addr, the address of the global vd, to the address space of the declared type of vd if they diff...
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)
LangAS getGlobalConstantAddressSpace() const
Wrapper around CodeGenUtils::getGlobalConstantAddressSpace, currently needed to enforce failure on SY...
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)
mlir::ptr::MemorySpaceAttrInterface getPointerAddressSpace(clang::QualType pointeeTy) const
Returns the CIR address space for a pointer/reference to pointeeTy, or a null attribute for the defau...
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
This is an opaque type for sizes expressed in character units.
llvm::Align getAsAlign() const
Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit bytes.
QuantityType getQuantity() const
Get the raw integer representation of this quantity.
static CharUnits One()
Construct a CharUnits quantity of one.
static CharUnits fromQuantity(QuantityType Quantity)
Construct a CharUnits quantity from a raw integer type.
static CharUnits 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.
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.
LangAS getAddressSpace() const
Return the address space of this type.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
bool isConstQualified() const
Determine whether this type is const-qualified.
bool isConstantStorage(const ASTContext &Ctx, bool ExcludeCtor, bool ExcludeDtor)
bool hasUnaligned() const
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.
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.
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...
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)
std::unique_ptr< TargetCIRGenInfo > createAArch64TargetCIRGenInfo(CIRGenTypes &cgt)
CIRGenCXXABI * CreateCIRGenMicrosoftCXXABI(CIRGenModule &cgm)
Creates Microsoft ABI.
CIRGenCUDARuntime * createNVCUDARuntime(CIRGenModule &cgm)
LangAS getGlobalConstantAddressSpace(const LangOptions &LangOpts, const TargetInfo &Target)
Return the AST address space of constant literal, which is used to emit the constant literal as globa...
bool isVarDeclStrongDefinition(const ASTContext &Ctx, const VarDecl *D, bool NoCommon)
Check whether D is a strong definition, and thus must not be given common linkage.
bool isEmptyFieldForLayout(const ASTContext &Ctx, const FieldDecl *FD)
Return true iff the field is "empty", that is, either a zero-width bit-field or an isEmptyRecordForLa...
bool hasUnwindExceptions(const LangOptions &LangOpts)
Determines whether the language options require us to model unwind exceptions.
bool shouldBeInCOMDAT(const ASTContext &Ctx, const Decl &D)
Check whether D should be emitted into a COMDAT group.
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
QualType pointeeType(QualType T)
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 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.