19#include "mlir/Dialect/OpenMP/Utils/Utils.h"
20#include "mlir/IR/SymbolTable.h"
23#include "clang/AST/Attrs.inc"
41#include "llvm/ADT/STLExtras.h"
42#include "llvm/ADT/StringExtras.h"
43#include "llvm/ADT/StringRef.h"
44#include "llvm/ADT/StringSwitch.h"
45#include "llvm/Support/raw_ostream.h"
49#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
50#include "mlir/IR/Attributes.h"
51#include "mlir/IR/BuiltinOps.h"
52#include "mlir/IR/Location.h"
53#include "mlir/IR/MLIRContext.h"
54#include "mlir/IR/Operation.h"
55#include "mlir/IR/Verifier.h"
64 case TargetCXXABI::GenericItanium:
65 case TargetCXXABI::GenericAArch64:
66 case TargetCXXABI::AppleARM64:
67 case TargetCXXABI::GenericARM:
69 case TargetCXXABI::Microsoft:
72 case TargetCXXABI::Fuchsia:
73 case TargetCXXABI::iOS:
74 case TargetCXXABI::WatchOS:
75 case TargetCXXABI::GenericMIPS:
76 case TargetCXXABI::WebAssembly:
77 case TargetCXXABI::XL:
78 cgm.
errorNYI(
"createCXXABI: C++ ABI kind");
82 llvm_unreachable(
"invalid C++ ABI kind");
85CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,
89 : builder(mlirContext, *this), astContext(astContext),
92 theModule{
mlir::ModuleOp::create(
mlir::UnknownLoc::get(&mlirContext))},
93 diags(diags), target(astContext.getTargetInfo()),
94 abi(
createCXXABI(*this)), genTypes(*this), vtables(*this) {
101 langOpts.CPlusPlusModules &&
130 .toCharUnitsFromBits(
134 const unsigned charSize = target.getCharWidth();
137 const unsigned sizeTypeSize = target.getTypeWidth(target.getSizeType());
145 std::optional<cir::SourceLanguage> sourceLanguage = getCIRSourceLanguage();
148 cir::CIRDialect::getSourceLanguageAttrName(),
149 cir::SourceLanguageAttr::get(&mlirContext, *sourceLanguage));
150 if (langOpts.OpenCL || (langOpts.CUDAIsDevice &&
getTriple().isSPIRV())) {
153 langOpts.OpenCL ? langOpts.getOpenCLCompatibleVersion() : 200;
154 setOpenCLVersionAttr(cir::CIRDialect::getOpenCLVersionAttrName(), version);
155 if (langOpts.OpenCLCPlusPlus)
156 setOpenCLVersionAttr(cir::CIRDialect::getOpenCLCXXVersionAttrName(),
157 langOpts.OpenCLCPlusPlusVersion);
160 unsigned spirMajor = version / 100;
161 theModule->setAttr(cir::CIRDialect::getOpenCLSPIRVersionAttrName(),
164 spirMajor > 1 ? 0 : 2));
167 theModule->setAttr(cir::CIRDialect::getTripleAttrName(),
168 builder.getStringAttr(
getTriple().str()));
169 theModule->setAttr(cir::CIRDialect::getTargetABIAttrName(),
170 builder.getStringAttr(
getTarget().getABI()));
175 cir::CIRDialect::getCXXABIAttrName(),
178 if (llvm::VersionTuple sdkVersion =
getTarget().getSDKVersion();
180 theModule->setAttr(cir::CIRDialect::getSDKVersionAttrName(),
181 builder.getStringAttr(sdkVersion.getAsString()));
184 theModule->setAttr(cir::CIRDialect::getSizeTypeWidthAttrName(),
185 builder.getI32IntegerAttr(sizeTypeSize));
186 theModule->setAttr(cir::CIRDialect::getIntTypeWidthAttrName(),
187 builder.getI32IntegerAttr(target.getIntWidth()));
193 cir::CIRDialect::getLoweringLangOptionsAttrName(),
194 cir::LoweringLangOptionsAttr::get(
197 langOpts.ThreadsafeStatics,
199 langOpts.CUDAIsDevice,
202 langOpts.GPURelocatableDeviceCode,
203 langOpts.OpenMP != 0,
204 langOpts.OpenMPIsTargetDevice,
206 static_cast<int32_t
>(langOpts.getClangABICompat())));
208 if (cgo.OptimizationLevel > 0 || cgo.OptimizeSize > 0)
209 theModule->setAttr(cir::CIRDialect::getOptInfoAttrName(),
210 cir::OptInfoAttr::get(&mlirContext,
211 cgo.OptimizationLevel,
215 cir::CIRDialect::getDefaultTlsModelAttrName(),
218 if (langOpts.OpenMP) {
219 mlir::omp::OffloadModuleOpts ompOpts(
220 langOpts.OpenMPTargetDebug, langOpts.OpenMPTeamSubscription,
221 langOpts.OpenMPThreadSubscription, langOpts.OpenMPNoThreadState,
222 langOpts.OpenMPNoNestedParallelism, langOpts.OpenMPIsTargetDevice,
223 getTriple().isGPU(), langOpts.OpenMPForceUSM, langOpts.OpenMP,
224 langOpts.OMPHostIRFile, langOpts.OMPTargetTriples, langOpts.NoGPULib);
225 mlir::omp::setOffloadModuleInterfaceAttributes(theModule, ompOpts);
226 mlir::omp::setOpenMPVersionAttribute(theModule, langOpts.OpenMP);
232 createOpenMPRuntime();
237 FileID mainFileId = astContext.getSourceManager().getMainFileID();
239 *astContext.getSourceManager().getFileEntryForID(mainFileId);
242 theModule.setSymName(path);
243 theModule->setLoc(mlir::FileLineColLoc::get(&mlirContext, path,
251void CIRGenModule::setOpenCLVersionAttr(StringRef attrName,
unsigned version) {
253 attrName, cir::OpenCLVersionAttr::get(&
getMLIRContext(), version / 100,
254 (version % 100) / 10));
257void CIRGenModule::createCUDARuntime() {
261void CIRGenModule::createOpenMPRuntime() {
262 openMPRuntime = std::make_unique<CIRGenOpenMPRuntime>(*
this);
273 auto &layout = astContext.getASTRecordLayout(rd);
278 return layout.getAlignment();
281 return layout.getNonVirtualAlignment();
286 bool forPointeeType) {
296 if (
unsigned align = tt->getDecl()->getMaxAlignment()) {
299 return astContext.toCharUnitsFromBits(align);
307 t = astContext.getBaseElementType(t);
328 }
else if (forPointeeType && !alignForArray &&
332 alignment = astContext.getTypeAlignInChars(t);
337 if (
unsigned maxAlign = astContext.getLangOpts().MaxTypeAlign) {
339 !astContext.isAlignmentRequired(t))
353 if (theTargetCIRGenInfo)
354 return *theTargetCIRGenInfo;
357 switch (triple.getArch()) {
364 case llvm::Triple::x86_64: {
365 switch (triple.getOS()) {
372 case llvm::Triple::Linux:
374 return *theTargetCIRGenInfo;
377 case llvm::Triple::aarch64:
378 case llvm::Triple::aarch64_32:
379 case llvm::Triple::aarch64_be: {
381 return *theTargetCIRGenInfo;
383 case llvm::Triple::nvptx:
384 case llvm::Triple::nvptx64:
386 return *theTargetCIRGenInfo;
387 case llvm::Triple::amdgpu: {
389 return *theTargetCIRGenInfo;
391 case llvm::Triple::spir:
392 case llvm::Triple::spir64:
393 case llvm::Triple::spirv:
394 case llvm::Triple::spirv32:
395 case llvm::Triple::spirv64:
397 return *theTargetCIRGenInfo;
402 assert(cLoc.
isValid() &&
"expected valid source location");
406 return mlir::FileLineColLoc::get(builder.getStringAttr(filename),
411 assert(cRange.
isValid() &&
"expected a valid source range");
414 mlir::Attribute metadata;
415 return mlir::FusedLoc::get({begin, end}, metadata, builder.getContext());
424 false, isForDefinition);
458 assert(op &&
"expected a valid global op");
466 mlir::Operation *globalValueOp = op;
467 if (
auto gv = dyn_cast<cir::GetGlobalOp>(op)) {
469 assert(globalValueOp &&
"expected a valid global op");
472 if (
auto cirGlobalValue =
473 dyn_cast<cir::CIRGlobalValueInterface>(globalValueOp))
474 if (!cirGlobalValue.isDeclaration())
495 assert(deferredVTables.empty());
505 std::vector<GlobalDecl> curDeclsToEmit;
513 if (
const auto *fd = d.getDecl()->getAsFunction()) {
514 if (langOpts.SYCLIsDevice && fd->hasAttr<SYCLKernelEntryPointAttr>() &&
518 if (!fd->getAttr<SYCLKernelEntryPointAttr>()->isInvalidAttr()) {
547 os << (isa<VarDecl>(d) ?
".static." :
".intern.");
549 os << (isa<VarDecl>(d) ?
"__static__" :
"__intern__");
556 "printPostfixForExternalizedDecl: CUID is not specified");
563 if (
const auto *cd = dyn_cast<clang::OpenACCConstructDecl>(gd.
getDecl())) {
571 if (global->hasAttr<WeakRefAttr>())
576 if (global->hasAttr<AliasAttr>()) {
585 if (langOpts.CUDA && !
getASTContext().shouldEmitCUDADecl(global))
588 if (langOpts.OpenMP) {
590 if (openMPRuntime && openMPRuntime->emitTargetGlobal(gd))
592 if (
auto *drd = dyn_cast<OMPDeclareReductionDecl>(global)) {
597 if (
auto *dmd = dyn_cast<OMPDeclareMapperDecl>(global)) {
604 if (
const auto *fd = dyn_cast<FunctionDecl>(global)) {
607 if (fd->hasAttr<AnnotateAttr>()) {
610 deferredAnnotations[mangledName] = fd;
612 if (!fd->doesThisDeclarationHaveABody()) {
613 if (!fd->doesDeclarationForceExternallyVisibleDefinition() &&
624 assert(vd->isFileVarDecl() &&
"Cannot emit local var decl as global.");
626 !astContext.isMSStaticDataMemberInlineDefinition(vd)) {
630 if (astContext.getInlineVariableDefinitionKind(vd) ==
645 if (
auto existing = dyn_cast_if_present<cir::CIRGlobalValueInterface>(
647 existing && !existing.isDeclaration())
675 mlir::Operation *op) {
679 cir::FuncOp funcOp = dyn_cast_if_present<cir::FuncOp>(op);
680 if (!funcOp || funcOp.getFunctionType() != funcType) {
686 if (!funcOp.isDeclaration())
698 mlir::OpBuilder::InsertionGuard guard(builder);
703 setNonAliasAttributes(gd, funcOp);
706 auto getPriority = [
this](
const auto *
attr) ->
int {
710 return attr->DefaultPriority;
713 if (
const ConstructorAttr *ca = funcDecl->getAttr<ConstructorAttr>())
715 if (
const DestructorAttr *da = funcDecl->getAttr<DestructorAttr>())
718 if (funcDecl->getAttr<AnnotateAttr>())
721 if (
getLangOpts().OpenMP && funcDecl->hasAttr<OMPDeclareTargetDeclAttr>())
727 std::optional<int> priority) {
736 ctor.setGlobalCtorPriority(priority);
741 std::optional<int> priority) {
742 if (codeGenOpts.RegisterGlobalDtorsWithAtExit &&
744 errorNYI(dtor.getLoc(),
"registerGlobalDtorsWithAtExit");
747 dtor.setGlobalDtorPriority(priority);
773 mlir::ptr::MemorySpaceAttrInterface addrSpace,
774 mlir::Operation *insertPoint) {
779 mlir::OpBuilder::InsertionGuard guard(builder);
785 builder.setInsertionPoint(insertPoint);
791 builder.setInsertionPointToStart(
getModule().getBody());
794 g = cir::GlobalOp::create(builder, loc, name, t, isConstant, addrSpace);
800 mlir::SymbolTable::setSymbolVisibility(
801 g, mlir::SymbolTable::Visibility::Private);
809 if (isa_and_nonnull<NamedDecl>(d))
813 if (
auto gvi = mlir::dyn_cast<cir::CIRGlobalValueInterface>(gv)) {
814 if (d && d->
hasAttr<UsedAttr>())
817 if (
const auto *vd = dyn_cast_if_present<VarDecl>(d);
818 vd && ((codeGenOpts.KeepPersistentStorageVariables &&
819 (vd->getStorageDuration() ==
SD_Static ||
820 vd->getStorageDuration() ==
SD_Thread)) ||
821 (codeGenOpts.KeepStaticConsts &&
823 vd->getType().isConstQualified())))
829static std::vector<std::string>
831 llvm::StringMap<bool> &featureMap) {
832 llvm::StringMap<bool> defaultFeatureMap;
836 std::vector<std::string> delta;
837 for (
const auto &[k, v] : featureMap) {
838 auto defaultIt = defaultFeatureMap.find(k);
839 if (defaultIt == defaultFeatureMap.end() || defaultIt->getValue() != v)
840 delta.push_back((v ?
"+" :
"-") + k.str());
846bool CIRGenModule::getCPUAndFeaturesAttributes(
847 GlobalDecl gd, llvm::StringMap<std::string> &attrs,
848 bool setTargetFeatures) {
854 std::vector<std::string> features;
858 const auto *fd = dyn_cast_or_null<FunctionDecl>(gd.
getDecl());
859 fd = fd ? fd->getMostRecentDecl() : fd;
860 const auto *td = fd ? fd->getAttr<TargetAttr>() :
nullptr;
861 const auto *tv = fd ? fd->getAttr<TargetVersionAttr>() :
nullptr;
862 assert((!td || !tv) &&
"both target_version and target specified");
863 const auto *sd = fd ? fd->getAttr<CPUSpecificAttr>() :
nullptr;
864 const auto *tc = fd ? fd->getAttr<TargetClonesAttr>() :
nullptr;
865 bool addedAttr =
false;
866 if (td || tv || sd || tc) {
867 llvm::StringMap<bool> featureMap;
868 astContext.getFunctionFeatureMap(featureMap, gd);
874 llvm::StringRef featureStr = td ? td->getFeaturesStr() : llvm::StringRef();
877 if (!featureStr.empty()) {
878 clang::ParsedTargetAttr parsedAttr =
880 if (!parsedAttr.
CPU.empty() &&
882 targetCPU = parsedAttr.
CPU;
885 if (!parsedAttr.
Tune.empty() &&
887 tuneCPU = parsedAttr.
Tune;
903 features.reserve(features.size() + featureMap.size());
904 for (
const auto &entry : featureMap)
905 features.push_back((entry.getValue() ?
"+" :
"-") +
906 entry.getKey().str());
911 llvm::StringMap<bool> featureMap;
913 astContext.getFunctionFeatureMap(featureMap, gd);
924 if (!targetCPU.empty()) {
925 attrs[cir::CIRDialect::getTargetCPUAttrName()] = targetCPU.str();
928 if (!tuneCPU.empty()) {
929 attrs[cir::CIRDialect::getTuneCPUAttrName()] = tuneCPU.str();
932 if (!features.empty() && setTargetFeatures) {
933 llvm::erase_if(features, [&](
const std::string &f) {
934 assert(!f.empty() && (f[0] ==
'+' || f[0] ==
'-') &&
935 "feature string must start with '+' or '-'");
938 llvm::sort(features);
939 attrs[cir::CIRDialect::getTargetFeaturesAttrName()] =
940 llvm::join(features,
",");
948void CIRGenModule::setNonAliasAttributes(GlobalDecl gd, mlir::Operation *op) {
953 if (
auto gvi = mlir::dyn_cast<cir::CIRGlobalValueInterface>(op)) {
954 if (
const auto *sa = d->
getAttr<SectionAttr>())
955 gvi.setSection(builder.getStringAttr(sa->getName()));
959 if (
auto func = dyn_cast<cir::FuncOp>(op)) {
960 llvm::StringMap<std::string> attrs;
961 if (getCPUAndFeaturesAttributes(gd, attrs)) {
968 for (llvm::StringRef name :
969 {cir::CIRDialect::getTargetCPUAttrName(),
970 cir::CIRDialect::getTuneCPUAttrName(),
971 cir::CIRDialect::getTargetFeaturesAttrName()})
972 func->removeAttr(name);
973 for (
const auto &[key, val] : attrs)
974 func->setAttr(key, builder.getStringAttr(val));
984std::optional<cir::SourceLanguage> CIRGenModule::getCIRSourceLanguage()
const {
985 using ClangStd = clang::LangStandard;
986 using CIRLang = cir::SourceLanguage;
989 if (opts.OpenCLCPlusPlus)
990 return CIRLang::OpenCLCXX;
992 return CIRLang::OpenCLC;
995 if (opts.C99 || opts.C11 || opts.C17 || opts.C23 || opts.C2y ||
996 opts.LangStd == ClangStd::lang_c89 ||
997 opts.LangStd == ClangStd::lang_gnu89)
1002 errorNYI(
"CIR does not yet support the given source language");
1003 return std::nullopt;
1006LangAS CIRGenModule::getGlobalVarAddressSpace(
const VarDecl *d) {
1007 if (langOpts.OpenCL) {
1015 if (langOpts.SYCLIsDevice &&
1019 if (langOpts.CUDA && langOpts.CUDAIsDevice) {
1021 if (d->
hasAttr<CUDAConstantAttr>())
1023 if (d->
hasAttr<CUDASharedAttr>())
1025 if (d->
hasAttr<CUDADeviceAttr>())
1033 if (langOpts.OpenMP)
1034 errorNYI(
"OpenMP global address space");
1047 gv.
setLinkage(cir::GlobalLinkageKind::ExternalWeakLinkage);
1056 auto linkage = cir::GlobalLinkageKind::ExternalWeakLinkage;
1057 func.setLinkage(linkage);
1058 func.setLinkageAttr(
1059 cir::GlobalLinkageKindAttr::get(&cgm.
getMLIRContext(), linkage));
1061 if (!func.isDeclaration())
1062 mlir::SymbolTable::setSymbolVisibility(
1069 for (mlir::Attribute i : indexes) {
1070 auto ind = mlir::cast<mlir::IntegerAttr>(i);
1071 inds.push_back(ind.getValue().getSExtValue());
1077 return view.getSymbol().getValue() == glob.getSymName();
1081 cir::GlobalOp newGlob,
1082 cir::GlobalViewAttr
attr,
1093 mlir::Type newTy = newGlob.getSymType();
1099 return cir::GlobalOffsetAttr::get(
attr.getType(),
attr.getSymbol(),
1100 static_cast<int64_t
>(offset));
1102 cir::PointerType newPtrTy;
1105 newPtrTy = cir::PointerType::get(newTy);
1111 attr.getAddressPoint());
1115 cgm.
errorNYI(
"Unhandled type in createNewGlobalView");
1121 mlir::Attribute oldInit) {
1122 if (
auto oldView = mlir::dyn_cast<cir::GlobalViewAttr>(oldInit))
1127 if (mlir::isa<cir::GlobalOffsetAttr>(oldInit))
1130 auto getNewInitElements =
1131 [&](mlir::ArrayAttr oldElements) -> mlir::ArrayAttr {
1133 for (mlir::Attribute elt : oldElements) {
1134 if (
auto view = mlir::dyn_cast<cir::GlobalViewAttr>(elt))
1136 else if (mlir::isa<cir::ConstArrayAttr, cir::ConstRecordAttr>(elt))
1139 newElements.push_back(elt);
1141 return mlir::ArrayAttr::get(cgm.
getBuilder().getContext(), newElements);
1144 if (
auto oldArray = mlir::dyn_cast<cir::ConstArrayAttr>(oldInit)) {
1150 mlir::Attribute oldElts = oldArray.getElts();
1151 if (mlir::isa<mlir::StringAttr>(oldElts))
1153 mlir::Attribute newElements =
1154 getNewInitElements(mlir::cast<mlir::ArrayAttr>(oldElts));
1156 newElements, mlir::cast<cir::ArrayType>(oldArray.getType()));
1158 if (
auto oldRecord = mlir::dyn_cast<cir::ConstRecordAttr>(oldInit)) {
1159 mlir::ArrayAttr newMembers = getNewInitElements(oldRecord.getMembers());
1160 auto recordTy = mlir::cast<cir::RecordType>(oldRecord.getType());
1166 cgm.
errorNYI(
"Unhandled type in getNewInitValue");
1174 assert(oldGV.getSymName() == newGV.getSymName() &&
"symbol names must match");
1176 mlir::Type oldTy = oldGV.getSymType();
1177 mlir::Type newTy = newGV.getSymType();
1182 assert(oldTy != newTy &&
"expected type change in replaceGlobal");
1185 std::optional<mlir::SymbolTable::UseRange> oldSymUses =
1186 oldGV.getSymbolUses(theModule);
1187 for (mlir::SymbolTable::SymbolUse use : *oldSymUses) {
1188 mlir::Operation *userOp = use.getUser();
1190 (mlir::isa<cir::GetGlobalOp, cir::GlobalOp, cir::ConstantOp>(userOp)) &&
1191 "Unexpected user for global op");
1193 if (
auto getGlobalOp = dyn_cast<cir::GetGlobalOp>(use.getUser())) {
1194 mlir::Value useOpResultValue = getGlobalOp.getAddr();
1195 useOpResultValue.setType(cir::PointerType::get(newTy));
1197 mlir::OpBuilder::InsertionGuard guard(builder);
1198 builder.setInsertionPointAfter(getGlobalOp);
1199 mlir::Type ptrTy = builder.getPointerTo(oldTy);
1201 builder.createBitcast(getGlobalOp->getLoc(), useOpResultValue, ptrTy);
1202 useOpResultValue.replaceAllUsesExcept(
cast,
cast.getDefiningOp());
1203 }
else if (
auto glob = dyn_cast<cir::GlobalOp>(userOp)) {
1204 if (
auto init = glob.getInitialValue()) {
1205 mlir::Attribute nw =
getNewInitValue(*
this, newGV, oldTy, init.value());
1206 glob.setInitialValueAttr(nw);
1208 }
else if (
auto c = dyn_cast<cir::ConstantOp>(userOp)) {
1209 mlir::Attribute init =
getNewInitValue(*
this, newGV, oldTy, c.getValue());
1210 auto typedAttr = mlir::cast<mlir::TypedAttr>(init);
1211 mlir::OpBuilder::InsertionGuard guard(builder);
1212 builder.setInsertionPointAfter(c);
1213 auto newUser = cir::ConstantOp::create(builder, c.getLoc(), typedAttr);
1214 c.replaceAllUsesWith(newUser.getOperation());
1250 cir::GlobalOp entry;
1254 "getOrCreateCIRGlobal: global with non-GlobalOp type");
1259 mlir::ptr::MemorySpaceAttrInterface entryCIRAS = entry.getAddrSpaceAttr();
1265 if (entry.getSymType() == ty &&
1276 if (isForDefinition && !entry.isDeclaration()) {
1278 "getOrCreateCIRGlobal: global with conflicting type");
1286 if (!isForDefinition)
1295 bool isConstant =
false;
1297 QualType declType = d->
getType();
1312 mlir::ptr::MemorySpaceAttrInterface declCIRAS =
1317 cir::GlobalOp gv =
createGlobalOp(loc, mangledName, ty, isConstant, declCIRAS,
1318 entry.getOperation());
1338 if (langOpts.OpenMP && !langOpts.OpenMPSimd)
1340 "getOrCreateCIRGlobal: OpenMP target global variable");
1342 gv.setAlignmentAttr(
getSize(astContext.getDeclAlign(d)));
1353 if (astContext.isMSStaticDataMemberInlineDefinition(d))
1355 "getOrCreateCIRGlobal: MS static data member inline definition");
1359 if (
const SectionAttr *sa = d->
getAttr<SectionAttr>())
1360 gv.setSectionAttr(builder.getStringAttr(sa->getName()));
1364 if (
getTriple().getArch() == llvm::Triple::xcore)
1366 "getOrCreateCIRGlobal: XCore specific ABI requirements");
1376 "getOrCreateCIRGlobal: external const declaration with initializer");
1422 mlir::Type ptrTy = builder.getPointerTo(g.getSymType(), g.getAddrSpaceAttr());
1423 mlir::Value addr = cir::GetGlobalOp::create(
1426 g.getDynamicInitGuard().has_value() &&
1436 auto ptrTy = mlir::cast<cir::PointerType>(addr.getType());
1437 mlir::ptr::MemorySpaceAttrInterface declAS =
1439 if (ptrTy.getAddrSpace() == declAS)
1441 return builder.createAddrSpaceCast(
1442 addr, builder.getPointerTo(ptrTy.getPointee(), declAS));
1450 cir::PointerType ptrTy =
1451 builder.getPointerTo(globalOp.getSymType(), globalOp.getAddrSpaceAttr());
1452 return builder.getGlobalViewAttr(ptrTy, globalOp);
1456 assert((mlir::isa<cir::FuncOp>(gv.getOperation()) ||
1457 !gv.isDeclarationForLinker()) &&
1458 "Only globals with definition can force usage.");
1463 assert(!gv.isDeclarationForLinker() &&
1464 "Only globals with definition can force usage.");
1469 cir::CIRGlobalValueInterface gv) {
1470 assert((mlir::isa<cir::FuncOp>(gv.getOperation()) ||
1471 !gv.isDeclarationForLinker()) &&
1472 "Only globals with definition can force usage.");
1480 std::vector<cir::CIRGlobalValueInterface> &list) {
1485 mlir::Location loc = builder.getUnknownLoc();
1487 usedArray.resize(list.size());
1488 for (
auto [i, op] : llvm::enumerate(list)) {
1489 usedArray[i] = cir::GlobalViewAttr::get(
1490 cgm.
voidPtrTy, mlir::FlatSymbolRefAttr::get(op.getNameAttr()));
1493 cir::ArrayType arrayTy = cir::ArrayType::get(cgm.
voidPtrTy, usedArray.size());
1495 cir::ConstArrayAttr initAttr = cir::ConstArrayAttr::get(
1496 arrayTy, mlir::ArrayAttr::get(&cgm.
getMLIRContext(), usedArray));
1500 gv.setLinkage(cir::GlobalLinkageKind::AppendingLinkage);
1501 gv.setInitialValueAttr(initAttr);
1502 gv.setSectionAttr(builder.getStringAttr(
"llvm.metadata"));
1519 "emitGlobalVarDefinition: emit OpenMP global variable");
1526 bool isDefinitionAvailableExternally =
1531 if (isDefinitionAvailableExternally &&
1539 mlir::Attribute init;
1540 bool needsGlobalCtor =
false;
1541 bool needsGlobalDtor =
1542 !isDefinitionAvailableExternally &&
1547 std::optional<ConstantEmitter> emitter;
1552 bool isCUDASharedVar =
1557 bool isCUDAShadowVar =
1559 (vd->
hasAttr<CUDAConstantAttr>() || vd->
hasAttr<CUDADeviceAttr>() ||
1560 vd->
hasAttr<CUDASharedAttr>());
1561 bool isCUDADeviceShadowVar =
1567 (isCUDASharedVar || isCUDAShadowVar || isCUDADeviceShadowVar)) {
1569 }
else if (vd->
hasAttr<LoaderUninitializedAttr>()) {
1571 "emitGlobalVarDefinition: loader uninitialized attribute");
1572 }
else if (!initExpr) {
1585 emitter.emplace(*
this);
1586 mlir::Attribute initializer = emitter->tryEmitForInitializer(*initDecl);
1595 "emitGlobalVarDefinition: flexible array initializer");
1597 if (!isDefinitionAvailableExternally)
1598 needsGlobalCtor =
true;
1601 "emitGlobalVarDefinition: static initializer");
1612 mlir::Type initType;
1613 if (mlir::isa<mlir::SymbolRefAttr>(init)) {
1616 "emitGlobalVarDefinition: global initializer is a symbol reference");
1619 assert(mlir::isa<mlir::TypedAttr>(init) &&
"This should have a type");
1620 auto typedInitAttr = mlir::cast<mlir::TypedAttr>(init);
1621 initType = typedInitAttr.getType();
1623 assert(!mlir::isa<mlir::NoneType>(initType) &&
"Should have a type by now");
1629 if (!gv || gv.getSymType() != initType) {
1631 "emitGlobalVarDefinition: global initializer with type mismatch");
1637 if (vd->
hasAttr<AnnotateAttr>())
1650 if (langOpts.CUDA) {
1651 if (langOpts.CUDAIsDevice) {
1654 if (linkage != cir::GlobalLinkageKind::InternalLinkage &&
1656 (vd->
hasAttr<CUDADeviceAttr>() || vd->
hasAttr<CUDAConstantAttr>() ||
1659 gv->setAttr(cir::CUDAExternallyInitializedAttr::getMnemonic(),
1672 emitter->finalize(gv);
1676 gv.setConstant((vd->
hasAttr<CUDAConstantAttr>() && langOpts.CUDAIsDevice) ||
1677 (!needsGlobalCtor && !needsGlobalDtor &&
1682 if (
const SectionAttr *sa = vd->
getAttr<SectionAttr>()) {
1685 gv.setConstant(
true);
1689 gv.setLinkage(linkage);
1693 if (linkage == cir::GlobalLinkageKind::CommonLinkage) {
1695 gv.setConstant(
false);
1700 std::optional<mlir::Attribute> initializer = gv.getInitialValue();
1701 if (initializer && !
getBuilder().isNullValue(*initializer))
1702 gv.setLinkage(cir::GlobalLinkageKind::WeakAnyLinkage);
1705 setNonAliasAttributes(vd, gv);
1713 if (needsGlobalCtor || needsGlobalDtor) {
1736 cir::GlobalLinkageKind::AvailableExternallyLinkage)
1742 if (fd->isInlineBuiltinDeclaration())
1745 if (codeGenOpts.OptimizationLevel == 0 && !fd->hasAttr<AlwaysInlineAttr>())
1750 if (
const Module *m = fd->getOwningModule();
1752 getASTContext().getCurrentNamedModule() != m->getTopLevelModule()) {
1753 errorNYI(fd->getSourceRange(),
"should emit function in a named module");
1756 if (fd->hasAttr<NoInlineAttr>())
1767 mlir::Operation *op) {
1769 if (
const auto *fd = dyn_cast<FunctionDecl>(
decl)) {
1773 if (
const auto *method = dyn_cast<CXXMethodDecl>(
decl)) {
1777 abi->emitCXXStructor(gd);
1778 else if (fd->isMultiVersion())
1779 errorNYI(method->getSourceRange(),
"multiversion functions");
1783 if (method->isVirtual())
1789 if (fd->isMultiVersion())
1790 errorNYI(fd->getSourceRange(),
"multiversion functions");
1795 if (
const auto *vd = dyn_cast<VarDecl>(
decl))
1798 llvm_unreachable(
"Invalid argument to CIRGenModule::emitGlobalDefinition");
1812 astContext.getAsConstantArrayType(e->
getType());
1813 uint64_t finalSize = cat->getZExtSize();
1814 str.resize(finalSize);
1816 mlir::Type eltTy =
convertType(cat->getElementType());
1817 return builder.getString(str, eltTy, finalSize,
false);
1822 auto arrayEltTy = mlir::cast<cir::IntType>(arrayTy.getElementType());
1824 uint64_t arraySize = arrayTy.getSize();
1826 assert(arraySize > literalSize &&
1827 "wide string literal array size must have room for null terminator?");
1831 bool isAllZero =
true;
1832 for (
unsigned i = 0; i < literalSize; ++i) {
1840 return cir::ZeroAttr::get(arrayTy);
1844 elements.reserve(arraySize);
1845 for (
unsigned i = 0; i < literalSize; ++i)
1846 elements.push_back(cir::IntAttr::get(
1847 arrayEltTy, llvm::APInt(arrayEltTy.getWidth(), e->
getCodeUnit(i))));
1849 auto elementsAttr = mlir::ArrayAttr::get(&
getMLIRContext(), elements);
1850 return builder.getConstArray(elementsAttr, arrayTy);
1860 if (
auto globalOp = dyn_cast_or_null<cir::GlobalOp>(op)) {
1861 globalOp.setSelfComdat();
1864 funcOp.setSelfComdat();
1870 genTypes.updateCompletedType(td);
1874 replacements[name] = op;
1879 mlir::SymbolUserMap &userMap) {
1880 for (mlir::Operation *user : userMap.getUsers(oldF)) {
1881 auto call = mlir::dyn_cast<cir::CallOp>(user);
1885 for (
auto [argOp, fnArgType] :
1886 llvm::zip(call.getArgs(), newF.getFunctionType().getInputs())) {
1887 if (argOp.getType() != fnArgType)
1896void CIRGenModule::applyReplacements() {
1897 if (replacements.empty())
1903 mlir::SymbolTableCollection symbolTableCollection;
1904 mlir::SymbolUserMap userMap(symbolTableCollection, theModule);
1906 for (
auto &i : replacements) {
1907 StringRef mangledName = i.first;
1908 mlir::Operation *replacement = i.second;
1914 auto newF = dyn_cast<cir::FuncOp>(replacement);
1917 errorNYI(replacement->getLoc(),
"replacement is not a function");
1922 "call argument types do not match replacement function");
1926 userMap.replaceAllUsesWith(oldF, newF.getSymNameAttr());
1927 newF->moveBefore(oldF);
1934 mlir::Location loc, StringRef name, mlir::Type ty,
1936 auto gv = mlir::dyn_cast_or_null<cir::GlobalOp>(
getGlobalValue(name));
1940 if (gv.getSymType() == ty)
1946 assert(gv.isDeclaration() &&
"Declaration has wrong type!");
1948 errorNYI(loc,
"createOrReplaceCXXRuntimeVariable: declaration exists with "
1959 mlir::SymbolTable::setSymbolVisibility(gv,
1963 !gv.hasAvailableExternallyLinkage()) {
1967 gv.setAlignmentAttr(
getSize(alignment));
1972cir::GlobalLinkageKind
1976 return cir::GlobalLinkageKind::InternalLinkage;
1979 return cir::GlobalLinkageKind::WeakAnyLinkage;
1983 return cir::GlobalLinkageKind::LinkOnceAnyLinkage;
1988 return cir::GlobalLinkageKind::AvailableExternallyLinkage;
2002 return !astContext.getLangOpts().AppleKext
2003 ? cir::GlobalLinkageKind::LinkOnceODRLinkage
2004 : cir::GlobalLinkageKind::InternalLinkage;
2018 return cir::GlobalLinkageKind::ExternalLinkage;
2021 return dd->
hasAttr<CUDAGlobalAttr>()
2022 ? cir::GlobalLinkageKind::ExternalLinkage
2023 : cir::GlobalLinkageKind::InternalLinkage;
2024 return cir::GlobalLinkageKind::WeakODRLinkage;
2032 return cir::GlobalLinkageKind::CommonLinkage;
2038 if (dd->
hasAttr<SelectAnyAttr>())
2039 return cir::GlobalLinkageKind::WeakODRLinkage;
2043 return cir::GlobalLinkageKind::ExternalLinkage;
2055 mlir::Operation *old, cir::FuncOp newFn) {
2057 auto oldFn = mlir::dyn_cast<cir::FuncOp>(old);
2065 unsigned numInherentAttrs = 0;
2066 oldFn->getName().walkInherentAttrs(
2067 oldFn, [&](llvm::StringRef, mlir::Attribute &
attr) {
2070 if (numInherentAttrs <= 1)
2072 "replaceUsesOfNonProtoTypeWithRealFunction: Attribute forwarding");
2075 newFn.setNoProto(oldFn.getNoProto());
2078 std::optional<mlir::SymbolTable::UseRange> symUses =
2079 oldFn.getSymbolUses(oldFn->getParentOp());
2084 for (
const mlir::SymbolTable::SymbolUse &use : symUses.value()) {
2085 mlir::OpBuilder::InsertionGuard guard(builder);
2087 if (
auto noProtoCallOp = mlir::dyn_cast<cir::CallOp>(use.getUser())) {
2088 builder.setInsertionPoint(noProtoCallOp);
2091 cir::FuncType newFnType = newFn.getFunctionType();
2092 mlir::OperandRange callOperands = noProtoCallOp.getOperands();
2093 bool returnTypeMatches =
2094 newFnType.hasVoidReturn()
2095 ? noProtoCallOp.getNumResults() == 0
2096 : noProtoCallOp.getNumResults() == 1 &&
2097 noProtoCallOp.getResultTypes().front() ==
2098 newFnType.getReturnType();
2099 bool typesMatch = !newFn.getNoProto() && returnTypeMatches &&
2100 callOperands.size() == newFnType.getNumInputs();
2101 for (
unsigned i = 0, e = newFnType.getNumInputs(); typesMatch && i != e;
2103 if (callOperands[i].
getType() != newFnType.getInput(i))
2107 cir::CallOp realCallOp;
2111 builder.createCallOp(noProtoCallOp.getLoc(), newFn, callOperands);
2119 cir::FuncType origFnType = oldFn.getFunctionType();
2120 cir::FuncType callFnType =
2122 ? cir::FuncType::get(llvm::to_vector(callOperands.getTypes()),
2123 origFnType.getReturnType(),
2126 mlir::Value addr = cir::GetGlobalOp::create(
2127 builder, noProtoCallOp.getLoc(), cir::PointerType::get(newFnType),
2128 newFn.getSymName());
2129 mlir::Value casted =
2130 builder.createBitcast(addr, cir::PointerType::get(callFnType));
2131 realCallOp = builder.createIndirectCallOp(
2132 noProtoCallOp.getLoc(), casted, callFnType, callOperands);
2134 realCallOp.setCallingConv(noProtoCallOp.getCallingConv());
2137 noProtoCallOp.replaceAllUsesWith(realCallOp);
2138 noProtoCallOp.erase();
2139 }
else if (
auto getGlobalOp =
2140 mlir::dyn_cast<cir::GetGlobalOp>(use.getUser())) {
2147 mlir::Value res = getGlobalOp.getAddr();
2148 const mlir::Type oldResTy = res.getType();
2149 const auto newPtrTy = cir::PointerType::get(newFn.getFunctionType());
2150 if (oldResTy != newPtrTy) {
2151 res.setType(newPtrTy);
2152 builder.setInsertionPointAfter(getGlobalOp.getOperation());
2153 mlir::Value castRes =
2154 cir::CastOp::create(builder, getGlobalOp.getLoc(), oldResTy,
2155 cir::CastKind::bitcast, res);
2156 res.replaceAllUsesExcept(castRes, castRes.getDefiningOp());
2158 }
else if (mlir::isa<cir::GlobalOp>(use.getUser())) {
2164 "replaceUsesOfNonProtoTypeWithRealFunction: unexpected use type");
2169cir::GlobalLinkageKind
2171 GVALinkage linkage = astContext.GetGVALinkageForVariable(vd);
2178 GVALinkage linkage = astContext.GetGVALinkageForFunction(d);
2180 if (
const auto *dtor = dyn_cast<CXXDestructorDecl>(d))
2189 StringRef globalName,
CharUnits alignment) {
2192 mlir::ptr::MemorySpaceAttrInterface addrSpace =
2202 gv.setAlignmentAttr(cgm.
getSize(alignment));
2204 cir::GlobalLinkageKindAttr::get(cgm.
getBuilder().getContext(), lt));
2208 if (gv.isWeakForLinker()) {
2209 assert(cgm.
supportsCOMDAT() &&
"Only COFF uses weak string literals");
2212 cgm.
setDSOLocal(
static_cast<mlir::Operation *
>(gv));
2233 std::string result =
2244 astContext.getAlignOfGlobalVarInChars(s->
getType(),
nullptr);
2252 if (!gv.getAlignment() ||
2253 uint64_t(alignment.
getQuantity()) > *gv.getAlignment())
2254 gv.setAlignmentAttr(
getSize(alignment));
2259 if (
getCXXABI().getMangleContext().shouldMangleStringLiteral(s) &&
2262 "getGlobalForStringLiteral: mangle string literals");
2272 : builder.getUnknownLoc();
2273 auto typedC = llvm::cast<mlir::TypedAttr>(c);
2275 cir::GlobalLinkageKind::PrivateLinkage, *
this,
2276 uniqueName, alignment);
2290 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(gv.getSymType());
2291 assert(arrayTy &&
"String literal must be array");
2293 arrayTy.getElementType(),
2296 return builder.getGlobalViewAttr(ptrTy, gv);
2300 StringRef str, StringRef name) {
2301 mlir::Attribute init = builder.getString(str,
convertType(astContext.CharTy),
2307 cir::GlobalLinkageKind::PrivateLinkage, *
this,
2312mlir::ptr::MemorySpaceAttrInterface
2343 "emitExplicitCastExprType");
2349 auto ty = mlir::cast<cir::MethodType>(
convertType(destTy));
2350 return builder.getNullMethodAttr(ty);
2353 auto ty = mlir::cast<cir::DataMemberType>(
convertType(destTy));
2354 return builder.getNullDataMemberAttr(ty);
2365 if (
const auto *methodDecl = dyn_cast<CXXMethodDecl>(
decl)) {
2367 if (methodDecl->isVirtual())
2368 return cir::ConstantOp::create(
2369 builder, loc,
getCXXABI().buildVirtualMethodAttr(ty, methodDecl));
2375 return cir::ConstantOp::create(builder, loc,
2376 builder.getMethodAttr(ty, methodFuncOp));
2391 assert(
fieldDecl->getParent() == destClass &&
2392 "scalar member pointer should be relative to the declaring class");
2394 astContext.toCharUnitsFromBits(astContext.getFieldOffset(
fieldDecl))
2396 return cir::ConstantOp::create(builder, loc,
2397 cir::DataMemberOffsetAttr::get(ty, offset));
2400 std::optional<llvm::SmallVector<int32_t>> path =
2404 return cir::ConstantOp::create(builder, loc,
2405 builder.getDataMemberAttr(ty, *path));
2408std::optional<llvm::SmallVector<int32_t>>
2416 if (
const auto *indirectField = dyn_cast<IndirectFieldDecl>(
decl)) {
2418 for (
const NamedDecl *nd : indirectField->chain()) {
2420 if (!findFieldMemberPath(currentClass, field, path))
2421 return std::nullopt;
2422 currentClass = field->getType()->getAsCXXRecordDecl();
2428 return std::nullopt;
2432bool CIRGenModule::findFieldMemberPath(
const CXXRecordDecl *currentClass,
2442 if (currentClass->
isUnion()) {
2448 "data member pointer for non-zero-initializable union");
2455 path.push_back(fieldIdx);
2463 for (
const CXXBaseSpecifier &base : currentClass->
bases()) {
2464 const auto *baseDecl =
2467 if (base.isVirtual()) {
2472 llvm::SmallVector<int32_t> discardedPath;
2473 if (findFieldMemberPath(baseDecl, field, discardedPath)) {
2475 "data member pointer through virtual base");
2488 path.push_back(baseFieldIdx);
2489 if (findFieldMemberPath(baseDecl, field, path))
2517 if (
auto *oid = dyn_cast<ObjCImplDecl>(
decl))
2518 errorNYI(oid->getSourceRange(),
"emitDeclConext: ObjCImplDecl");
2528 if (
decl->isTemplated())
2531 switch (
decl->getKind()) {
2534 decl->getDeclKindName());
2537 case Decl::CXXConversion:
2538 case Decl::CXXMethod:
2539 case Decl::Function: {
2542 if (!fd->isConsteval())
2547 case Decl::Import: {
2556 if (!importedModules.insert(mod))
2558 moduleImportLocs[mod] = importDecl->getLocation();
2575 visited.insert(mod);
2576 stack.push_back(mod);
2578 while (!stack.empty()) {
2580 if (!emittedModuleInitializers.insert(cur).second)
2583 for (
Decl *initializer : astContext.getModuleInitializers(cur))
2590 if (submodule->IsExplicit)
2593 if (visited.insert(submodule).second)
2594 stack.push_back(submodule);
2605 case Decl::Decomposition:
2606 case Decl::VarTemplateSpecialization: {
2608 if (
auto *decomp = dyn_cast<DecompositionDecl>(
decl))
2609 for (
auto *binding : decomp->flat_bindings())
2610 if (
auto *holdingVar = binding->getHoldingVar())
2614 case Decl::OpenACCRoutine:
2617 case Decl::OpenACCDeclare:
2620 case Decl::OMPThreadPrivate:
2623 case Decl::OMPGroupPrivate:
2626 case Decl::OMPAllocate:
2629 case Decl::OMPCapturedExpr:
2632 case Decl::OMPDeclareReduction:
2635 case Decl::OMPDeclareMapper:
2638 case Decl::OMPRequires:
2643 case Decl::UsingDirective:
2644 case Decl::UsingEnum:
2645 case Decl::NamespaceAlias:
2647 case Decl::TypeAlias:
2654 case Decl::IndirectField:
2658 case Decl::ClassTemplate:
2660 case Decl::CXXDeductionGuide:
2662 case Decl::ExplicitInstantiation:
2663 case Decl::FunctionTemplate:
2664 case Decl::StaticAssert:
2665 case Decl::TypeAliasTemplate:
2666 case Decl::UsingShadow:
2667 case Decl::VarTemplate:
2668 case Decl::VarTemplatePartialSpecialization:
2671 case Decl::CXXConstructor:
2674 case Decl::CXXDestructor:
2679 case Decl::LinkageSpec:
2680 case Decl::Namespace:
2684 case Decl::ClassTemplateSpecialization:
2685 case Decl::CXXRecord: {
2688 for (
auto *childDecl : crd->
decls())
2694 case Decl::FileScopeAsm:
2696 if (langOpts.CUDA && langOpts.CUDAIsDevice)
2699 if (langOpts.OpenMPIsTargetDevice)
2702 if (langOpts.SYCLIsDevice)
2705 std::string line = file_asm->getAsmString();
2706 globalScopeAsm.push_back(builder.getStringAttr(line));
2713 op.setInitialValueAttr(value);
2727 md->getParent()->getNumVBases() == 0)
2729 "getAddrAndTypeOfCXXStructor: MS ABI complete destructor");
2740 false, isForDefinition);
2742 return {fnType, fn};
2746 mlir::Type funcType,
bool forVTable,
2750 "consteval function should never be emitted");
2760 if (
const auto *dd = dyn_cast<CXXDestructorDecl>(gd.
getDecl())) {
2763 dd->getParent()->getNumVBases() == 0)
2765 "getAddrOfFunction: MS ABI complete destructor");
2771 false, isForDefinition);
2773 if (langOpts.CUDA && !langOpts.CUDAIsDevice &&
2779 bool isHIPHandle = mlir::isa<cir::GlobalOp>(*handle);
2780 if (isForDefinition || isHIPHandle)
2782 return mlir::dyn_cast<cir::FuncOp>(*handle);
2791 llvm::raw_svector_ostream
out(buffer);
2800 assert(ii &&
"Attempt to mangle unnamed decl.");
2802 const auto *fd = dyn_cast<FunctionDecl>(nd);
2806 }
else if (fd && fd->hasAttr<CUDAGlobalAttr>() &&
2810 DeviceKernelAttr::isOpenCLSpelling(
2811 fd->getAttr<DeviceKernelAttr>()) &&
2828 if (
const auto *fd = dyn_cast<FunctionDecl>(nd)) {
2829 if (fd->isMultiVersion()) {
2831 "getMangledName: multi-version functions");
2839 "getMangledName: GPU relocatable device code");
2842 return std::string(
out.str());
2845static FunctionDecl *
2860 if (
auto *methodDecl = dyn_cast<CXXMethodDecl>(protoFunc);
2861 methodDecl && methodDecl->isImplicitObjectMemberFunction()) {
2863 paramTypes.insert(paramTypes.begin(), methodDecl->getThisType());
2866 fpt->getExtProtoInfo());
2877 params.reserve(fpt->getNumParams());
2880 for (
unsigned i = 0, e = fpt->getNumParams(); i != e; ++i) {
2884 nullptr, fpt->getParamType(i),
nullptr,
2887 params.push_back(parm);
2890 tempFunc->setParams(params);
2915 if (
const auto *cd = dyn_cast<CXXConstructorDecl>(canonicalGd.
getDecl())) {
2918 "getMangledName: C++ constructor without variants");
2927 if (!langOpts.CUDAIsDevice || !astContext.mayExternalize(gd.
getDecl())) {
2928 auto foundName = mangledDeclNames.find(canonicalGd);
2929 if (foundName != mangledDeclNames.end())
2930 return foundName->second;
2937 auto result = manglings.insert(std::make_pair(mangledName, gd));
2938 return mangledDeclNames[canonicalGd] = result.first->first();
2942 assert(!d->
getInit() &&
"Cannot emit definite definitions here!");
2950 if (gv && !mlir::cast<cir::GlobalOp>(gv).isDeclaration())
2966 if (langOpts.EmitAllDecls)
2969 const auto *vd = dyn_cast<VarDecl>(global);
2971 ((codeGenOpts.KeepPersistentStorageVariables &&
2972 (vd->getStorageDuration() ==
SD_Static ||
2973 vd->getStorageDuration() ==
SD_Thread)) ||
2974 (codeGenOpts.KeepStaticConsts && vd->getStorageDuration() ==
SD_Static &&
2975 vd->getType().isConstQualified())))
2988 if (langOpts.OpenMP >= 50 && !langOpts.OpenMPSimd) {
2989 std::optional<OMPDeclareTargetDeclAttr *> activeAttr =
2990 OMPDeclareTargetDeclAttr::getActiveAttr(global);
2991 if (!activeAttr || (*activeAttr)->getLevel() != (
unsigned)-1)
2995 const auto *fd = dyn_cast<FunctionDecl>(global);
3002 if (fd->hasAttr<TargetVersionAttr>() && !fd->isMultiVersion())
3006 if (langOpts.SYCLIsDevice && fd->hasAttr<SYCLKernelEntryPointAttr>())
3009 const auto *vd = dyn_cast<VarDecl>(global);
3011 if (astContext.getInlineVariableDefinitionKind(vd) ==
3019 if (langOpts.OpenMP && langOpts.OpenMPUseTLS &&
3020 astContext.getTargetInfo().isTLSSupported() &&
isa<VarDecl>(global) &&
3022 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(global))
3025 assert((fd || vd) &&
3026 "Only FunctionDecl and VarDecl should hit this path so far.");
3031 cir::CIRGlobalValueInterface gv) {
3032 if (gv.hasLocalLinkage())
3035 if (!gv.hasDefaultVisibility() && !gv.hasExternalWeakLinkage())
3043 const llvm::Triple &tt = cgm.
getTriple();
3045 if (tt.isOSCygMing()) {
3054 cgm.
errorNYI(
"shouldAssumeDSOLocal: MinGW");
3060 if (tt.isOSBinFormatCOFF() && gv.hasExternalWeakLinkage())
3068 if (tt.isOSBinFormatCOFF() || (tt.isOSWindows() && tt.isOSBinFormatMachO()))
3072 if (!tt.isOSBinFormatELF())
3077 if (rm != llvm::Reloc::Static && !lOpts.PIE) {
3085 return !(lOpts.SemanticInterposition || lOpts.HalfNoSemanticInterposition);
3089 if (!gv.isDeclarationForLinker())
3095 if (rm == llvm::Reloc::PIC_ && gv.hasExternalWeakLinkage())
3102 if (cgOpts.DirectAccessExternalData) {
3108 if (
auto globalOp = dyn_cast<cir::GlobalOp>(gv.getOperation())) {
3134 if (gv.hasLocalLinkage()) {
3135 gv.setGlobalVisibility(cir::VisibilityKind::Default);
3150 d->
hasAttr<OMPDeclareTargetDeclAttr>() &&
3151 d->
getAttr<OMPDeclareTargetDeclAttr>()->getDevType() !=
3152 OMPDeclareTargetDeclAttr::DT_NoHost &&
3154 llvm_unreachable(
"setGlobalVisibility: OpenMP is NYI");
3163 !d->
hasAttr<OMPDeclareTargetDeclAttr>()) {
3164 bool needsProtected =
false;
3168 }
else if (
const auto *vd = dyn_cast<VarDecl>(d)) {
3169 needsProtected = vd->hasAttr<CUDADeviceAttr>() ||
3170 vd->hasAttr<CUDAConstantAttr>() ||
3171 vd->getType()->isCUDADeviceBuiltinSurfaceType() ||
3172 vd->getType()->isCUDADeviceBuiltinTextureType();
3174 if (needsProtected) {
3175 gv.setGlobalVisibility(cir::VisibilityKind::Protected);
3181 gv.setGlobalVisibility(cir::VisibilityKind::Hidden);
3188 !gv.isDeclarationForLinker())
3197 if (
auto globalValue = dyn_cast<cir::CIRGlobalValueInterface>(op))
3216 auto res = manglings.find(mangledName);
3217 if (res == manglings.end())
3219 result = res->getValue();
3224 return llvm::StringSwitch<cir::TLSModel>(S)
3225 .Case(
"global-dynamic", cir::TLSModel::GeneralDynamic)
3226 .Case(
"local-dynamic", cir::TLSModel::LocalDynamic)
3227 .Case(
"initial-exec", cir::TLSModel::InitialExec)
3228 .Case(
"local-exec", cir::TLSModel::LocalExec);
3234 return cir::TLSModel::GeneralDynamic;
3236 return cir::TLSModel::LocalDynamic;
3238 return cir::TLSModel::InitialExec;
3240 return cir::TLSModel::LocalExec;
3242 llvm_unreachable(
"Invalid TLS model!");
3246 bool isExtendingDecl) {
3247 assert(d.
getTLSKind() &&
"setting TLS mode on non-TLS var!");
3256 global.setTlsModel(tlm);
3266 if (isExtendingDecl)
3274 cir::FuncOp func,
bool isThunk) {
3276 cir::CallingConv callingConv;
3283 mlir::NamedAttrList pal{};
3284 std::vector<mlir::NamedAttrList> argAttrs(info.arguments().size());
3285 mlir::NamedAttrList retAttrs{};
3287 retAttrs, callingConv,
3290 for (mlir::NamedAttribute
attr : pal)
3291 func->setAttr(
attr.getName(),
attr.getValue());
3293 llvm::for_each(llvm::enumerate(argAttrs), [func](
auto idx_arg_pair) {
3294 mlir::function_interface_impl::setArgAttrs(func, idx_arg_pair.index(),
3295 idx_arg_pair.value());
3297 if (!retAttrs.empty())
3298 mlir::function_interface_impl::setResultAttrs(func, 0, retAttrs);
3302 func.setCallingConv(callingConv);
3307 bool isIncompleteFunction,
3315 if (!isIncompleteFunction)
3317 getTypes().arrangeGlobalDeclaration(globalDecl),
3320 if (!isIncompleteFunction && func.isDeclaration())
3325 if (
const auto *errorAttr = funcDecl->getAttr<ErrorAttr>()) {
3326 if (errorAttr->isError())
3327 func->setAttr(cir::CIRDialect::getDontCallErrorAttrName(),
3329 errorAttr->getUserDiagnostic()));
3330 else if (errorAttr->isWarning())
3331 func->setAttr(cir::CIRDialect::getDontCallWarnAttrName(),
3333 errorAttr->getUserDiagnostic()));
3340 if (funcDecl->isInlineBuiltinDeclaration()) {
3342 bool hasBody = funcDecl->
hasBody(fdBody);
3344 assert(hasBody &&
"Inline builtin declarations should always have an "
3349 if (funcDecl->isReplaceableGlobalAllocationFunction()) {
3352 func->setAttr(cir::CIRDialect::getNoBuiltinAttrName(),
3360 if ((!
decl || !
decl->hasAttr<NoUwtableAttr>()) && codeGenOpts.UnwindTables)
3361 f.setUwtable(
static_cast<cir::UnwindTableKind
>(codeGenOpts.UnwindTables));
3366 f->setAttr(cir::CIRDialect::getNoThrowAttrName(),
3369 std::optional<cir::InlineKind> existingInlineKind = f.getInlineKind();
3371 existingInlineKind && *existingInlineKind == cir::InlineKind::NoInline;
3372 bool isAlwaysInline = existingInlineKind &&
3373 *existingInlineKind == cir::InlineKind::AlwaysInline;
3377 if (!isAlwaysInline &&
3382 f.setInlineKind(cir::InlineKind::NoInline);
3394 bool shouldAddOptNone =
3395 !codeGenOpts.DisableO0ImplyOptNone && codeGenOpts.OptimizationLevel == 0;
3397 shouldAddOptNone &= !
decl->hasAttr<MinSizeAttr>();
3398 shouldAddOptNone &= !
decl->hasAttr<AlwaysInlineAttr>();
3401 if ((shouldAddOptNone ||
decl->hasAttr<OptimizeNoneAttr>()) &&
3404 f->setAttr(cir::CIRDialect::getOptNoneAttrName(),
3408 f.setInlineKind(cir::InlineKind::NoInline);
3412 if (
decl->hasAttr<NakedAttr>())
3413 f->setAttr(cir::CIRDialect::getNakedAttrName(),
3417 f->removeAttr(cir::CIRDialect::getOptimizeForSizeAttrName());
3418 f->removeAttr(cir::CIRDialect::getMinSizeAttrName());
3419 }
else if (
decl->hasAttr<NakedAttr>()) {
3421 f->setAttr(cir::CIRDialect::getNakedAttrName(),
3423 f.setInlineKind(cir::InlineKind::NoInline);
3424 }
else if (
decl->hasAttr<NoDuplicateAttr>()) {
3425 f->setAttr(cir::CIRDialect::getNoDuplicatesAttrName(),
3427 }
else if (
decl->hasAttr<NoInlineAttr>() && !isAlwaysInline) {
3429 f.setInlineKind(cir::InlineKind::NoInline);
3430 }
else if (
decl->hasAttr<AlwaysInlineAttr>() && !isNoInline) {
3433 f.setInlineKind(cir::InlineKind::AlwaysInline);
3437 if (!isAlwaysInline)
3438 f.setInlineKind(cir::InlineKind::NoInline);
3443 if (
auto *fd = dyn_cast<FunctionDecl>(
decl)) {
3448 auto checkRedeclForInline = [](
const FunctionDecl *redecl) {
3449 return redecl->isInlineSpecified();
3451 if (any_of(
decl->redecls(), checkRedeclForInline))
3456 return any_of(pattern->
redecls(), checkRedeclForInline);
3458 if (checkForInline(fd)) {
3459 f.setInlineKind(cir::InlineKind::InlineHint);
3460 }
else if (codeGenOpts.getInlining() ==
3462 !fd->isInlined() && !isAlwaysInline) {
3463 f.setInlineKind(cir::InlineKind::NoInline);
3470 if (!
decl->hasAttr<OptimizeNoneAttr>()) {
3471 if (
decl->hasAttr<ColdAttr>()) {
3472 if (!shouldAddOptNone)
3473 f->setAttr(cir::CIRDialect::getOptimizeForSizeAttrName(),
3476 f->setAttr(cir::CIRDialect::getColdAttrName(),
3480 if (
decl->hasAttr<HotAttr>())
3481 f->setAttr(cir::CIRDialect::getHotAttrName(),
3484 if (
decl->hasAttr<MinSizeAttr>())
3485 f->setAttr(cir::CIRDialect::getMinSizeAttrName(),
3489 std::optional<uint64_t> explicitAlignment;
3490 if (
unsigned alignment =
3492 explicitAlignment = alignment;
3493 else if (langOpts.FunctionAlignment)
3494 explicitAlignment = 1ull << langOpts.FunctionAlignment;
3496 if (explicitAlignment) {
3497 f.setAlignment(*explicitAlignment);
3498 f.setPreferredAlignment(*explicitAlignment);
3499 }
else if (langOpts.PreferredFunctionAlignment) {
3500 f.setPreferredAlignment(langOpts.PreferredFunctionAlignment);
3522static cir::LangAddressSpace
3524 switch (addressSpace) {
3526 return cir::LangAddressSpace::OffloadGlobal;
3528 return cir::LangAddressSpace::OffloadConstant;
3530 return cir::LangAddressSpace::OffloadLocal;
3532 return cir::LangAddressSpace::OffloadGeneric;
3534 return cir::LangAddressSpace::OffloadGlobalDevice;
3536 return cir::LangAddressSpace::OffloadGlobalHost;
3540 return cir::LangAddressSpace::Default;
3546 assert(fd &&
"expected a kernel function declaration");
3559 argNames.push_back(builder.getStringAttr(param->getName()));
3562 std::string typeQuals;
3564 if (
type->isImageType() ||
type->isPipeType()) {
3566 "OpenCL kernel argument metadata for image and pipe types");
3570 accessQuals.push_back(builder.getStringAttr(
"none"));
3572 auto getTypeSpelling = [&](
QualType paramType) {
3573 std::string typeName = paramType.getUnqualifiedType().getAsString(policy);
3575 if (paramType.isCanonical()) {
3576 StringRef typeNameRef = typeName;
3577 if (typeNameRef.consume_front(
"unsigned "))
3578 return std::string(
"u") + typeNameRef.str();
3579 if (typeNameRef.consume_front(
"signed "))
3580 return typeNameRef.str();
3588 if (
type->isPointerType()) {
3590 addressQuals.push_back(cir::LangAddressSpaceAttr::get(
3594 argTypeNames.push_back(
3595 builder.getStringAttr(getTypeSpelling(
pointeeType) +
"*"));
3596 argBaseTypeNames.push_back(builder.getStringAttr(
3597 getTypeSpelling(
pointeeType.getCanonicalType()) +
"*"));
3599 if (
type.isRestrictQualified())
3600 typeQuals =
"restrict";
3603 typeQuals += typeQuals.empty() ?
"const" :
" const";
3605 typeQuals += typeQuals.empty() ?
"volatile" :
" volatile";
3607 addressQuals.push_back(cir::LangAddressSpaceAttr::get(
3610 argTypeNames.push_back(builder.getStringAttr(getTypeSpelling(
type)));
3611 argBaseTypeNames.push_back(
3612 builder.getStringAttr(getTypeSpelling(
type.getCanonicalType())));
3615 argTypeQuals.push_back(builder.getStringAttr(typeQuals));
3618 mlir::ArrayAttr names;
3620 names = builder.getArrayAttr(argNames);
3622 mlir::Attribute metadata = cir::OpenCLKernelArgMetadataAttr::get(
3623 func.getContext(), builder.getArrayAttr(addressQuals),
3624 builder.getArrayAttr(accessQuals), builder.getArrayAttr(argTypeNames),
3625 builder.getArrayAttr(argBaseTypeNames),
3626 builder.getArrayAttr(argTypeQuals), names);
3627 func->setAttr(cir::CIRDialect::getOpenCLKernelArgMetadataAttrName(),
3632 StringRef mangledName, mlir::Type funcType,
GlobalDecl gd,
bool forVTable,
3634 mlir::NamedAttrList extraAttrs) {
3637 if (
const auto *fd = cast_or_null<FunctionDecl>(d)) {
3639 if (
getLangOpts().OpenMPIsTargetDevice && openMPRuntime &&
3641 !dontDefer && !isForDefinition) {
3644 if (
const auto *cd = dyn_cast<CXXConstructorDecl>(fdDef))
3646 else if (
const auto *dd = dyn_cast<CXXDestructorDecl>(fdDef))
3656 if (fd->isMultiVersion())
3657 errorNYI(fd->getSourceRange(),
"getOrCreateCIRFunction: multi-version");
3663 assert(mlir::isa<cir::FuncOp>(entry));
3668 if (d && !d->
hasAttr<DLLImportAttr>() && !d->
hasAttr<DLLExportAttr>()) {
3676 if (isForDefinition && fn && !fn.isDeclaration()) {
3683 diagnosedConflictingDefinitions.insert(gd).second) {
3687 diag::note_previous_definition);
3691 if (fn && fn.getFunctionType() == funcType) {
3695 if (!isForDefinition) {
3703 auto *funcDecl = llvm::cast_or_null<FunctionDecl>(gd.
getDecl());
3704 bool invalidLoc = !funcDecl ||
3705 funcDecl->getSourceRange().getBegin().isInvalid() ||
3706 funcDecl->getSourceRange().getEnd().isInvalid();
3708 invalidLoc ? theModule->getLoc() :
getLoc(funcDecl->getSourceRange()),
3709 mangledName, mlir::cast<cir::FuncType>(funcType), funcDecl);
3711 if (funcDecl && funcDecl->hasAttr<AnnotateAttr>())
3712 deferredAnnotations[mangledName] = funcDecl;
3723 auto symbolOp = mlir::cast<mlir::SymbolOpInterface>(entry);
3731 if (symbolOp.getSymbolUses(symbolOp->getParentOp()))
3741 if (!extraAttrs.empty())
3742 for (mlir::NamedAttribute attr : extraAttrs)
3743 if (!funcOp->hasDiscardableAttr(
attr.getName()))
3744 funcOp->setDiscardableAttr(
attr.getName(),
attr.getValue());
3750 assert(funcOp.getFunctionType() == funcType);
3757 if (isa_and_nonnull<CXXDestructorDecl>(d) &&
3787 fd = fd->getPreviousDecl()) {
3789 if (fd->doesThisDeclarationHaveABody()) {
3802 cir::FuncType funcType,
3806 mlir::OpBuilder::InsertionGuard guard(builder);
3811 builder.setInsertionPointToEnd(theModule.getBody());
3813 func = cir::FuncOp::create(builder, loc, name, funcType);
3820 func.setNoProto(
true);
3822 assert(func.isDeclaration() &&
"expected empty body");
3826 func.setLinkageAttr(cir::GlobalLinkageKindAttr::get(
3828 mlir::SymbolTable::setSymbolVisibility(
3829 func, mlir::SymbolTable::Visibility::Private);
3840 for (
const auto *
attr :
3854 fnOp.setBuiltin(
true);
3860 return cir::CtorKind::Default;
3862 return cir::CtorKind::Copy;
3864 return cir::CtorKind::Move;
3865 return cir::CtorKind::Custom;
3870 return cir::AssignKind::Copy;
3872 return cir::AssignKind::Move;
3873 llvm_unreachable(
"not a copy or move assignment operator");
3881 if (
const auto *dtor = dyn_cast<CXXDestructorDecl>(funcDecl)) {
3882 auto cxxDtor = cir::CXXDtorAttr::get(
3885 funcOp.setFuncInfoAttr(cxxDtor);
3889 if (
const auto *ctor = dyn_cast<CXXConstructorDecl>(funcDecl)) {
3891 auto cxxCtor = cir::CXXCtorAttr::get(
3893 kind, ctor->isTrivial());
3894 funcOp.setFuncInfoAttr(cxxCtor);
3898 const auto *method = dyn_cast<CXXMethodDecl>(funcDecl);
3899 if (method && (method->isCopyAssignmentOperator() ||
3900 method->isMoveAssignmentOperator())) {
3902 auto cxxAssign = cir::CXXAssignAttr::get(
3904 assignKind, method->isTrivial());
3905 funcOp.setFuncInfoAttr(cxxAssign);
3915 bool inStdNamespace = method ? method->getParent()->isInStdNamespace()
3917 if (!inStdNamespace)
3923 std::optional<cir::KnownFuncKind>
kind;
3925 kind = llvm::StringSwitch<std::optional<cir::KnownFuncKind>>(
3927 .Case(cir::StdFindOp::getFunctionName(),
3928 cir::StdFindOp::getFuncKind())
3929 .Default(std::nullopt);
3938 cir::FuncOp funcOp, StringRef name) {
3954 mlir::NamedAttrList extraAttrs,
3956 bool assumeConvergent) {
3957 if (assumeConvergent)
3958 errorNYI(
"createRuntimeFunction: assumeConvergent");
3968 entry.setDSOLocal(
true);
3974mlir::SymbolTable::Visibility
3978 if (op.isDeclaration())
3979 return mlir::SymbolTable::Visibility::Private;
3983mlir::SymbolTable::Visibility
3986 case cir::GlobalLinkageKind::InternalLinkage:
3987 case cir::GlobalLinkageKind::PrivateLinkage:
3988 return mlir::SymbolTable::Visibility::Private;
3989 case cir::GlobalLinkageKind::ExternalLinkage:
3990 case cir::GlobalLinkageKind::ExternalWeakLinkage:
3991 case cir::GlobalLinkageKind::LinkOnceODRLinkage:
3992 case cir::GlobalLinkageKind::AvailableExternallyLinkage:
3993 case cir::GlobalLinkageKind::CommonLinkage:
3994 case cir::GlobalLinkageKind::WeakAnyLinkage:
3995 case cir::GlobalLinkageKind::WeakODRLinkage:
3996 return mlir::SymbolTable::Visibility::Public;
3998 llvm::errs() <<
"visibility not implemented for '"
3999 << stringifyGlobalLinkageKind(glk) <<
"'\n";
4000 assert(0 &&
"not implemented");
4003 llvm_unreachable(
"linkage should be handled above!");
4006std::string CIRGenModule::getModuleInitializerName(
clang::Module *mod) {
4008 llvm::raw_string_ostream
out(name);
4010 .mangleModuleInitializer(mod,
out);
4017 applyReplacements();
4019 theModule->setAttr(cir::CIRDialect::getModuleLevelAsmAttrName(),
4020 builder.getArrayAttr(globalScopeAsm));
4022 emitGlobalAnnotations();
4024 if (std::optional<cir::FramePointerKind>
kind =
4027 cir::CIRDialect::getModuleFramePointerAttrName(),
4030 if (!recordLayoutEntries.empty())
4032 cir::CIRDialect::getRecordLayoutsAttrName(),
4033 mlir::DictionaryAttr::get(&
getMLIRContext(), recordLayoutEntries));
4042 std::string cuidName =
4045 auto loc = builder.getUnknownLoc();
4046 mlir::ptr::MemorySpaceAttrInterface addrSpace =
4051 gv.setLinkage(cir::GlobalLinkageKind::ExternalLinkage);
4053 auto zeroAttr = cir::IntAttr::get(int8Ty, 0);
4054 gv.setInitialValueAttr(zeroAttr);
4056 mlir::SymbolTable::setSymbolVisibility(
4057 gv, mlir::SymbolTable::Visibility::Public);
4062 if (astContext.getLangOpts().CUDA && cudaRuntime)
4075 if (cxx20ModuleInits) {
4076 clang::Module *primary = astContext.getCurrentNamedModule();
4078 if (isInterfaceUnit)
4080 cir::CIRDialect::getCXXModuleInitFnNameAttrName(),
4081 builder.getStringAttr(getModuleInitializerName(primary)));
4087 primary, importedModules.getArrayRef())) {
4090 auto importLoc = moduleImportLocs.find(mod);
4091 mlir::Location loc =
4092 getLoc(importLoc != moduleImportLocs.end() ? importLoc->second
4094 importedInits.push_back(cir::CXXModuleInitAttr::get(
4096 builder.getStringAttr(getModuleInitializerName(mod)), loc));
4098 if (!importedInits.empty())
4099 theModule->setAttr(cir::CIRDialect::getCXXModuleImportedInitsAttrName(),
4100 builder.getArrayAttr(importedInits));
4116 const AliasAttr *aa = d->
getAttr<AliasAttr>();
4117 assert(aa &&
"Not an alias?");
4121 if (aa->getAliasee() == mangledName) {
4122 diags.Report(aa->getLocation(), diag::err_cyclic_alias) << 0;
4130 auto entryGV = mlir::dyn_cast<cir::CIRGlobalValueInterface>(entry);
4131 if (entryGV && entryGV.isDefinition())
4144 cir::GlobalLinkageKind linkage;
4156 cir::CIRGlobalValueInterface alias =
4157 isFunction ? mlir::cast<cir::CIRGlobalValueInterface>(
4159 mlir::cast<cir::FuncType>(declTy),
4162 : mlir::cast<cir::CIRGlobalValueInterface>(
4173 entry, mlir::cast<cir::FuncOp>(alias.getOperation()));
4181 linkage = cir::GlobalLinkageKind::WeakAnyLinkage;
4185 mlir::SymbolTable::Visibility visibility =
4188 alias.setAliasee(aa->getAliasee());
4189 alias.setLinkage(linkage);
4190 mlir::SymbolTable::setSymbolVisibility(alias, visibility);
4198 cir::FuncOp aliasee,
4199 cir::GlobalLinkageKind linkage) {
4201 auto *aliasFD = dyn_cast<FunctionDecl>(aliasGD.
getDecl());
4202 assert(aliasFD &&
"expected FunctionDecl");
4213 mangledName, fnType, aliasFD);
4214 alias.setAliasee(aliasee.getName());
4215 alias.setLinkage(linkage);
4219 mlir::SymbolTable::setSymbolVisibility(
4220 alias, mlir::SymbolTable::Visibility::Private);
4232 "declaration exists with different type");
4244 return genTypes.convertType(
type);
4251 return mlir::verify(theModule).succeeded();
4260 return builder.getConstNullPtrAttr(builder.getUInt8PtrTy());
4263 langOpts.ObjCRuntime.isGNUFamily()) {
4264 errorNYI(loc,
"getAddrOfRTTIDescriptor: Objc PtrType & Objc RT GUN");
4274 llvm::iterator_range<CastExpr::path_const_iterator> path) {
4281 assert(!base->isVirtual() &&
"Should not see virtual bases here!");
4286 const auto *baseDecl = base->getType()->castAsCXXRecordDecl();
4298 llvm::StringRef feature) {
4299 unsigned diagID = diags.getCustomDiagID(
4301 return diags.Report(loc, diagID) << feature;
4305 llvm::StringRef feature) {
4317 "cannot compile this %0 yet");
4318 diags.Report(astContext.getFullLoc(s->
getBeginLoc()), diagId)
4325 "cannot compile this %0 yet");
4326 diags.Report(astContext.getFullLoc(d->
getLocation()), diagId) <<
type;
4334 "not a global temporary");
4346 materializedType = mte->
getType();
4355 llvm::raw_svector_ostream
out(name);
4359 auto insertResult = materializedGlobalTemporaryMap.insert({mte,
nullptr});
4360 if (!insertResult.second) {
4364 if (!insertResult.first->second) {
4367 insertResult.first->second =
4370 return insertResult.first->second;
4387 value = &evalResult.
Val;
4391 std::optional<ConstantEmitter> emitter;
4392 mlir::Attribute initialValue =
nullptr;
4393 bool isConstant =
false;
4397 emitter.emplace(*
this);
4398 initialValue = emitter->emitForInitializer(*value, materializedType);
4403 type = mlir::cast<mlir::TypedAttr>(initialValue).getType();
4412 if (linkage == cir::GlobalLinkageKind::ExternalLinkage) {
4414 if (
varDecl->isStaticDataMember() &&
varDecl->getAnyInitializer(initVD) &&
4422 linkage = cir::GlobalLinkageKind::InternalLinkage;
4426 gv.setInitialValueAttr(initialValue);
4427 gv.setLinkage(linkage);
4431 emitter->finalize(gv);
4433 if (!gv.hasLocalLinkage()) {
4438 gv.setAlignment(align.getAsAlign().value());
4443 mlir::Operation *cv = gv;
4452 mlir::Operation *&entry = materializedGlobalTemporaryMap[mte];
4454 entry->replaceAllUsesWith(cv);
4469 return *globalOpEntry;
4476 "emitForInitializer should take gcd->getType().getAddressSpace()");
4478 auto typedInit = dyn_cast<mlir::TypedAttr>(init);
4482 "getAddrOfUnnamedGlobalConstantDecl: non-typed initializer");
4491 std::string name = numEntries == 0
4493 : (Twine(
".constant.") + Twine(numEntries)).str();
4495 typedInit.getType(),
true);
4496 globalOp.setLinkage(cir::GlobalLinkageKind::PrivateLinkage);
4499 globalOp.setAlignment(alignment.
getAsAlign().value());
4503 *globalOpEntry = globalOp;
4518 "emitForInitializer should take tpo->getType().getAddressSpace()");
4519 mlir::Attribute init =
4529 cir::GlobalLinkageKind linkage =
4531 ? cir::GlobalLinkageKind::LinkOnceODRLinkage
4532 : cir::GlobalLinkageKind::InternalLinkage;
4536 typedInit.getType(),
true);
4537 globalOp.setLinkage(linkage);
4538 globalOp.setAlignment(alignment.
getAsAlign().value());
4539 if (
supportsCOMDAT() && linkage == cir::GlobalLinkageKind::LinkOnceODRLinkage)
4540 globalOp.setSelfComdat();
4555CIRGenModule::getOrCreateAnnotationArgs(
const AnnotateAttr *
attr) {
4562 llvm::FoldingSetNodeID id;
4563 for (
Expr *e : exprs)
4566 mlir::ArrayAttr &lookup = annotationArgs[
id.computeHash()];
4571 args.reserve(exprs.size());
4572 for (
Expr *e : exprs) {
4573 if (
auto *strE = dyn_cast<clang::StringLiteral>(e->IgnoreParenCasts())) {
4574 args.push_back(builder.getStringAttr(strE->getString()));
4575 }
else if (
auto *intE =
4576 dyn_cast<clang::IntegerLiteral>(e->IgnoreParenCasts())) {
4577 auto intTy = builder.getIntegerType(intE->getValue().getBitWidth());
4578 args.push_back(builder.getIntegerAttr(intTy, intE->getValue()));
4580 errorNYI(e->getExprLoc(),
"annotation argument expression");
4584 return lookup = builder.getArrayAttr(args);
4587cir::AnnotationAttr CIRGenModule::emitAnnotateAttr(
const AnnotateAttr *aa) {
4588 mlir::StringAttr annoGV = builder.getStringAttr(aa->getAnnotation());
4589 mlir::ArrayAttr args = getOrCreateAnnotationArgs(aa);
4590 return cir::AnnotationAttr::get(&
getMLIRContext(), annoGV, args);
4594 mlir::Operation *gv) {
4595 assert(d->
hasAttr<AnnotateAttr>() &&
"no annotate attribute");
4597 "annotation only on globals");
4600 annotations.push_back(emitAnnotateAttr(i));
4601 if (
auto global = dyn_cast<cir::GlobalOp>(gv))
4602 global.setAnnotationsAttr(builder.getArrayAttr(annotations));
4603 else if (
auto func = dyn_cast<cir::FuncOp>(gv))
4604 func.setAnnotationsAttr(builder.getArrayAttr(annotations));
4607void CIRGenModule::emitGlobalAnnotations() {
4608 for (
const auto &[mangledName, vd] : deferredAnnotations) {
4613 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 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)
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.
bool computeGlobalViewIndicesFromFlatOffset(int64_t offset, mlir::Type ty, const cir::CIRDataLayout &layout, llvm::SmallVectorImpl< int64_t > &indices)
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
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.
cir::GlobalOp createGlobalString(mlir::Location loc, llvm::StringRef str, llvm::StringRef name)
Create a private constant global holding the null-terminated string str, mirroring llvm::IRBuilder::C...
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)
const cir::CIRDataLayout & getDataLayout() const
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)
static std::optional< cir::FramePointerKind > getFramePointerKind(CodeGenOptions::FramePointerKind kind)
Returns the frame pointer kind to record on functions and on the module, or std::nullopt when kind is...
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.
mlir::TypedAttr emitNullConstantAttr(QualType t)
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.
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)
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 setCIRFunctionAttributesForDefinition(const clang::Decl *decl, cir::FuncOp f)
Set extra attributes (inline, etc.) for a function.
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)
mlir::ptr::MemorySpaceAttrInterface getGlobalCIRAddressSpace(LangAS as)
Return the CIR address space attribute for a global in as, honoring the target address space map wher...
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).
std::string getOpenACCBindMangledName(const IdentifierInfo *bindName, const FunctionDecl *attachedFunction)
void emitGlobalFunctionDefinition(clang::GlobalDecl gd, mlir::Operation *op)
CIRGenVTables & getVTables()
void setFunctionLinkage(GlobalDecl gd, cir::FuncOp f)
std::vector< clang::GlobalDecl > deferredDeclsToEmit
void emitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *d)
CIRGenOpenMPRuntime & getOpenMPRuntime()
void emitAMDGPUMetadata()
Emits AMDGPU specific Metadata.
void emitOMPGroupPrivateDecl(const OMPGroupPrivateDecl *d)
mlir::Attribute getConstantArrayFromStringLiteral(const StringLiteral *e)
Return a constant array for the given string.
void setCommonAttributes(GlobalDecl gd, mlir::Operation *op)
Set attributes which are common to any form of a global definition (alias, Objective-C method,...
void emitDeclareTargetFunction(const FunctionDecl *fd, cir::FuncOp funcOp)
If the function has an OMPDeclareTargetDeclAttr, set the corresponding omp.declare_target attribute o...
This class handles record and union layout info while lowering AST types to CIR types.
bool hasNonVirtualBaseCIRField(const CXXRecordDecl *rd) const
unsigned getCIRFieldNo(const clang::FieldDecl *fd) const
Return cir::RecordType element number that corresponds to the field FD.
bool hasCIRField(const clang::FieldDecl *fd) const
bool isZeroInitializable() const
Check whether this struct can be C++ zero-initialized with a zeroinitializer.
unsigned getNonVirtualBaseCIRFieldNo(const CXXRecordDecl *rd) const
const CIRGenFunctionInfo & arrangeGlobalDeclaration(GlobalDecl gd)
const CIRGenFunctionInfo & arrangeCXXMethodDeclaration(const clang::CXXMethodDecl *md)
C++ methods have some special rules and also have implicit parameters.
const CIRGenFunctionInfo & arrangeCXXStructorDeclaration(clang::GlobalDecl gd)
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 getGlobalCIRAddressSpace(clang::LangAS as) const
Get the CIR address space attribute for a global in AST address space as.
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.
Decl - This represents one declaration (or definition), e.g.
bool isInStdNamespace() const
bool isWeakImported() const
Determine whether this is a weak-imported symbol.
bool isInExportDeclContext() const
Whether this declaration was exported in a lexical context.
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
static DeclContext * castToDeclContext(const Decl *)
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
SourceLocation getLocation() const
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Represents a ValueDecl that came out of a declarator.
A little helper class used to produce diagnostics.
Concrete class used by the front-end to report problems and issues.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
ExplicitCastExpr - An explicit cast written in the source code.
This represents one expression.
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
Represents a member of a struct/union/class.
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
bool isPotentiallyOverlapping() const
Determine if this field is of potentially-overlapping class type, that is, subobject with the [[no_un...
Cached information about one file (either on disk or in the virtual file system).
StringRef tryGetRealPathName() const
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Represents a function declaration or definition.
static FunctionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin=false, bool isInlineSpecified=false, bool hasWrittenPrototype=true, ConstexprSpecKind ConstexprKind=ConstexprSpecKind::Unspecified, const AssociatedConstraint &TrailingRequiresClause={})
ArrayRef< ParmVarDecl * > parameters() const
bool hasPrototype() const
Whether this function has a prototype, either because one was explicitly written or because it was "i...
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
FunctionDecl * getDefinition()
Get the definition for this declaration.
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
FunctionType - C99 6.7.5.3 - Function Declarators.
CallingConv getCallConv() const
GlobalDecl - represents a global declaration.
CXXCtorType getCtorType() const
GlobalDecl getCanonicalDecl() const
KernelReferenceKind getKernelReferenceKind() const
GlobalDecl getWithDecl(const Decl *D)
unsigned getMultiVersionIndex() const
CXXDtorType getDtorType() const
const Decl * getDecl() const
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
std::string CUID
The user provided compilation unit ID, if non-empty.
Visibility getVisibility() const
void setLinkage(Linkage L)
Linkage getLinkage() const
bool isVisibilityExplicit() const
MangleContext - Context for tracking state which persists across multiple calls to the C++ name mangl...
bool isTriviallyRecursive(const FunctionDecl *FD)
Return true if FD's body contains a direct call back to the symbol it links as, through an asm label ...
bool shouldMangleDeclName(const NamedDecl *D)
void mangleName(GlobalDecl GD, raw_ostream &)
ManglerKind getKind() const
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.
SourceLocation DefinitionLoc
The location of the module definition.
llvm::iterator_range< submodule_iterator > submodules()
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.
static const auto & getSpelling(Kind ABIKind)
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.
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
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.
mlir::ptr::MemorySpaceAttrInterface normalizeDefaultAddressSpace(mlir::ptr::MemorySpaceAttrInterface addrSpace)
Normalize LangAddressSpace::Default to null (empty attribute).
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)
Determines whether the language options require us to model unwind exceptions.
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...
llvm::SmallVector< Module *, 8 > importedModulesToInitialize(Module *Primary, llvm::ArrayRef< Module * > Imported)
The C++20 named modules whose Itanium initializer function the global init function of a translation ...
bool hasUnwindExceptions(const LangOptions &LangOpts)
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::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.
@ 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.
__builtin_bitreverse32 uint32_t __builtin_riscv_aaddu_u32 __builtin_riscv_asubu_u32 __builtin_elementwise_add_sat __builtin_elementwise_sub_sat int32_t
static bool globalCtorLexOrder()
static bool opFuncArmNewAttr()
static bool getRuntimeFunctionDecl()
static bool weakRefReference()
static bool addressSpace()
static bool opGlobalUnnamedAddr()
static bool opGlobalThreadLocal()
static bool opFuncMultiVersioning()
static bool sourceLanguageCases()
static bool shouldSkipAliasEmission()
static bool opFuncAstDeclAttr()
static bool stackProtector()
static bool moduleNameHash()
static bool opGlobalVisibility()
static bool setDLLStorageClass()
static bool opFuncParameterAttributes()
static bool targetCIRGenInfoArch()
static bool opFuncExtraAttrs()
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 opFuncExceptions()
static bool opFuncArmStreamingAttr()
static bool cudaSupport()
static bool opFuncMaybeHandleStaticInExternC()
static bool checkAliases()
static bool generateDebugInfo()
static bool emitModuleLinkOptions()
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.