19#include "mlir/Dialect/OpenMP/OpenMPOffloadUtils.h"
22#include "clang/AST/Attrs.inc"
36#include "llvm/ADT/StringRef.h"
40#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
41#include "mlir/IR/Attributes.h"
42#include "mlir/IR/BuiltinOps.h"
43#include "mlir/IR/Location.h"
44#include "mlir/IR/MLIRContext.h"
45#include "mlir/IR/Operation.h"
46#include "mlir/IR/Verifier.h"
55 case TargetCXXABI::GenericItanium:
56 case TargetCXXABI::GenericAArch64:
57 case TargetCXXABI::AppleARM64:
60 case TargetCXXABI::Fuchsia:
61 case TargetCXXABI::GenericARM:
62 case TargetCXXABI::iOS:
63 case TargetCXXABI::WatchOS:
64 case TargetCXXABI::GenericMIPS:
65 case TargetCXXABI::WebAssembly:
66 case TargetCXXABI::XL:
67 case TargetCXXABI::Microsoft:
68 cgm.
errorNYI(
"createCXXABI: C++ ABI kind");
72 llvm_unreachable(
"invalid C++ ABI kind");
75CIRGenModule::CIRGenModule(mlir::MLIRContext &mlirContext,
79 : builder(mlirContext, *this), astContext(astContext),
80 langOpts(astContext.
getLangOpts()), codeGenOpts(cgo),
81 theModule{
mlir::ModuleOp::create(
mlir::UnknownLoc::get(&mlirContext))},
82 diags(diags), target(astContext.getTargetInfo()),
83 abi(
createCXXABI(*this)), genTypes(*this), vtables(*this) {
111 .toCharUnitsFromBits(
115 const unsigned charSize = astContext.getTargetInfo().getCharWidth();
119 const unsigned sizeTypeSize =
120 astContext.getTypeSize(astContext.getSignedSizeType());
121 SizeSizeInBytes = astContext.toCharUnitsFromBits(sizeTypeSize).getQuantity();
128 std::optional<cir::SourceLanguage> sourceLanguage = getCIRSourceLanguage();
131 cir::CIRDialect::getSourceLanguageAttrName(),
132 cir::SourceLanguageAttr::get(&mlirContext, *sourceLanguage));
133 theModule->setAttr(cir::CIRDialect::getTripleAttrName(),
134 builder.getStringAttr(
getTriple().str()));
136 if (cgo.OptimizationLevel > 0 || cgo.OptimizeSize > 0)
137 theModule->setAttr(cir::CIRDialect::getOptInfoAttrName(),
138 cir::OptInfoAttr::get(&mlirContext,
139 cgo.OptimizationLevel,
142 if (langOpts.OpenMP) {
143 mlir::omp::OffloadModuleOpts ompOpts(
144 langOpts.OpenMPTargetDebug, langOpts.OpenMPTeamSubscription,
145 langOpts.OpenMPThreadSubscription, langOpts.OpenMPNoThreadState,
146 langOpts.OpenMPNoNestedParallelism, langOpts.OpenMPIsTargetDevice,
147 getTriple().isGPU(), langOpts.OpenMPForceUSM, langOpts.OpenMP,
148 langOpts.OMPHostIRFile, langOpts.OMPTargetTriples, langOpts.NoGPULib);
149 mlir::omp::setOffloadModuleInterfaceAttributes(theModule, ompOpts);
155 createOpenMPRuntime();
160 FileID mainFileId = astContext.getSourceManager().getMainFileID();
162 *astContext.getSourceManager().getFileEntryForID(mainFileId);
165 theModule.setSymName(path);
166 theModule->setLoc(mlir::FileLineColLoc::get(&mlirContext, path,
173 llvm::StringRef cudaBinaryName = codeGenOpts.CudaGpuBinaryFileName;
174 if (!cudaBinaryName.empty()) {
175 theModule->setAttr(cir::CIRDialect::getCUDABinaryHandleAttrName(),
176 cir::CUDABinaryHandleAttr::get(
177 &mlirContext, mlir::StringAttr::get(
178 &mlirContext, cudaBinaryName)));
185void CIRGenModule::createCUDARuntime() {
189void CIRGenModule::createOpenMPRuntime() {
190 openMPRuntime = std::make_unique<CIRGenOpenMPRuntime>(*
this);
201 auto &layout = astContext.getASTRecordLayout(rd);
206 return layout.getAlignment();
209 return layout.getNonVirtualAlignment();
214 bool forPointeeType) {
224 if (
unsigned align = tt->getDecl()->getMaxAlignment()) {
227 return astContext.toCharUnitsFromBits(align);
235 t = astContext.getBaseElementType(t);
256 }
else if (forPointeeType && !alignForArray &&
260 alignment = astContext.getTypeAlignInChars(t);
265 if (
unsigned maxAlign = astContext.getLangOpts().MaxTypeAlign) {
267 !astContext.isAlignmentRequired(t))
281 if (theTargetCIRGenInfo)
282 return *theTargetCIRGenInfo;
285 switch (triple.getArch()) {
292 case llvm::Triple::x86_64: {
293 switch (triple.getOS()) {
300 case llvm::Triple::Linux:
302 return *theTargetCIRGenInfo;
305 case llvm::Triple::nvptx:
306 case llvm::Triple::nvptx64:
308 return *theTargetCIRGenInfo;
309 case llvm::Triple::amdgcn: {
311 return *theTargetCIRGenInfo;
317 assert(cLoc.
isValid() &&
"expected valid source location");
321 return mlir::FileLineColLoc::get(builder.getStringAttr(filename),
326 assert(cRange.
isValid() &&
"expected a valid source range");
329 mlir::Attribute metadata;
330 return mlir::FusedLoc::get({begin, end}, metadata, builder.getContext());
339 false, isForDefinition);
373 assert(op &&
"expected a valid global op");
381 mlir::Operation *globalValueOp = op;
382 if (
auto gv = dyn_cast<cir::GetGlobalOp>(op)) {
384 assert(globalValueOp &&
"expected a valid global op");
387 if (
auto cirGlobalValue =
388 dyn_cast<cir::CIRGlobalValueInterface>(globalValueOp))
389 if (!cirGlobalValue.isDeclaration())
410 assert(deferredVTables.empty());
420 std::vector<GlobalDecl> curDeclsToEmit;
439 if (
auto *
attr =
decl->getAttr<AttrT>())
440 return attr->isImplicit();
441 return decl->isImplicit();
446 assert(langOpts.CUDA &&
"Should not be called by non-CUDA languages");
451 return !langOpts.CUDAIsDevice || global->
hasAttr<CUDADeviceAttr>() ||
452 global->
hasAttr<CUDAConstantAttr>() ||
453 global->
hasAttr<CUDASharedAttr>() ||
459 if (
const auto *cd = dyn_cast<clang::OpenACCConstructDecl>(gd.
getDecl())) {
471 "Expected Variable or Function");
472 if (
const auto *
varDecl = dyn_cast<VarDecl>(global)) {
476 }
else if (langOpts.CUDAIsDevice) {
477 const auto *
functionDecl = dyn_cast<FunctionDecl>(global);
478 if ((!global->hasAttr<CUDADeviceAttr>() ||
479 (langOpts.OffloadImplicitHostDeviceTemplates &&
484 !
getASTContext().CUDAImplicitHostDeviceFunUsedByDevice.count(
486 !global->hasAttr<CUDAGlobalAttr>() &&
488 !global->hasAttr<CUDAHostAttr>()))
491 }
else if (!global->hasAttr<CUDAHostAttr>() &&
492 global->hasAttr<CUDADeviceAttr>())
496 if (langOpts.OpenMP) {
498 if (openMPRuntime && openMPRuntime->emitTargetGlobal(gd))
500 if (
auto *drd = dyn_cast<OMPDeclareReductionDecl>(global)) {
505 if (
auto *dmd = dyn_cast<OMPDeclareMapperDecl>(global)) {
512 if (
const auto *fd = dyn_cast<FunctionDecl>(global)) {
515 if (fd->hasAttr<AnnotateAttr>()) {
518 deferredAnnotations[mangledName] = fd;
520 if (!fd->doesThisDeclarationHaveABody()) {
521 if (!fd->doesDeclarationForceExternallyVisibleDefinition())
525 "function declaration that forces code gen");
530 assert(vd->isFileVarDecl() &&
"Cannot emit local var decl as global.");
532 !astContext.isMSStaticDataMemberInlineDefinition(vd)) {
536 if (astContext.getInlineVariableDefinitionKind(vd) ==
575 mlir::Operation *op) {
579 cir::FuncOp funcOp = dyn_cast_if_present<cir::FuncOp>(op);
580 if (!funcOp || funcOp.getFunctionType() != funcType) {
586 if (!funcOp.isDeclaration())
598 mlir::OpBuilder::InsertionGuard guard(builder);
603 setNonAliasAttributes(gd, funcOp);
606 auto getPriority = [
this](
const auto *
attr) ->
int {
610 return attr->DefaultPriority;
613 if (
const ConstructorAttr *ca = funcDecl->getAttr<ConstructorAttr>())
615 if (
const DestructorAttr *da = funcDecl->getAttr<DestructorAttr>())
618 if (funcDecl->getAttr<AnnotateAttr>())
621 if (
getLangOpts().OpenMP && funcDecl->hasAttr<OMPDeclareTargetDeclAttr>())
627 std::optional<int> priority) {
636 ctor.setGlobalCtorPriority(priority);
641 std::optional<int> priority) {
642 if (codeGenOpts.RegisterGlobalDtorsWithAtExit &&
644 errorNYI(dtor.getLoc(),
"registerGlobalDtorsWithAtExit");
647 dtor.setGlobalDtorPriority(priority);
671 StringRef name, mlir::Type t,
bool isConstant,
672 mlir::ptr::MemorySpaceAttrInterface addrSpace,
673 mlir::Operation *insertPoint) {
678 mlir::OpBuilder::InsertionGuard guard(builder);
684 builder.setInsertionPoint(insertPoint);
690 builder.setInsertionPointToStart(cgm.
getModule().getBody());
693 g = cir::GlobalOp::create(builder, loc, name, t, isConstant, addrSpace);
699 mlir::SymbolTable::setSymbolVisibility(
700 g, mlir::SymbolTable::Visibility::Private);
708 if (isa_and_nonnull<NamedDecl>(d))
712 if (
auto gvi = mlir::dyn_cast<cir::CIRGlobalValueInterface>(gv)) {
713 if (d && d->
hasAttr<UsedAttr>())
716 if (
const auto *vd = dyn_cast_if_present<VarDecl>(d);
717 vd && ((codeGenOpts.KeepPersistentStorageVariables &&
718 (vd->getStorageDuration() ==
SD_Static ||
719 vd->getStorageDuration() ==
SD_Thread)) ||
720 (codeGenOpts.KeepStaticConsts &&
722 vd->getType().isConstQualified())))
727void CIRGenModule::setNonAliasAttributes(
GlobalDecl gd, mlir::Operation *op) {
732 if (
auto gvi = mlir::dyn_cast<cir::CIRGlobalValueInterface>(op)) {
733 if (
const auto *sa = d->
getAttr<SectionAttr>())
734 gvi.setSection(builder.getStringAttr(sa->getName()));
746std::optional<cir::SourceLanguage> CIRGenModule::getCIRSourceLanguage()
const {
747 using ClangStd = clang::LangStandard;
748 using CIRLang = cir::SourceLanguage;
753 if (opts.C99 || opts.C11 || opts.C17 || opts.C23 || opts.C2y ||
754 opts.LangStd == ClangStd::lang_c89 ||
755 opts.LangStd == ClangStd::lang_gnu89)
760 errorNYI(
"CIR does not yet support the given source language");
764LangAS CIRGenModule::getGlobalVarAddressSpace(
const VarDecl *d) {
765 if (langOpts.OpenCL) {
773 if (langOpts.SYCLIsDevice &&
775 errorNYI(
"SYCL global address space");
777 if (langOpts.CUDA && langOpts.CUDAIsDevice) {
779 if (d->
hasAttr<CUDAConstantAttr>())
781 if (d->
hasAttr<CUDASharedAttr>())
783 if (d->
hasAttr<CUDADeviceAttr>())
792 errorNYI(
"OpenMP global address space");
805 gv.
setLinkage(cir::GlobalLinkageKind::ExternalWeakLinkage);
810 for (mlir::Attribute i : indexes) {
811 auto ind = mlir::cast<mlir::IntegerAttr>(i);
812 inds.push_back(ind.getValue().getSExtValue());
818 return view.getSymbol().getValue() == glob.getSymName();
822 cir::GlobalOp newGlob,
823 cir::GlobalViewAttr
attr,
834 mlir::Type newTy = newGlob.getSymType();
839 cir::PointerType newPtrTy;
842 newPtrTy = cir::PointerType::get(newTy);
851 cgm.
errorNYI(
"Unhandled type in createNewGlobalView");
857 mlir::Attribute oldInit) {
858 if (
auto oldView = mlir::dyn_cast<cir::GlobalViewAttr>(oldInit))
861 auto getNewInitElements =
862 [&](mlir::ArrayAttr oldElements) -> mlir::ArrayAttr {
864 for (mlir::Attribute elt : oldElements) {
865 if (
auto view = mlir::dyn_cast<cir::GlobalViewAttr>(elt))
867 else if (mlir::isa<cir::ConstArrayAttr, cir::ConstRecordAttr>(elt))
870 newElements.push_back(elt);
872 return mlir::ArrayAttr::get(cgm.
getBuilder().getContext(), newElements);
875 if (
auto oldArray = mlir::dyn_cast<cir::ConstArrayAttr>(oldInit)) {
876 mlir::Attribute newElements =
877 getNewInitElements(mlir::cast<mlir::ArrayAttr>(oldArray.getElts()));
879 newElements, mlir::cast<cir::ArrayType>(oldArray.getType()));
881 if (
auto oldRecord = mlir::dyn_cast<cir::ConstRecordAttr>(oldInit)) {
882 mlir::ArrayAttr newMembers = getNewInitElements(oldRecord.getMembers());
883 auto recordTy = mlir::cast<cir::RecordType>(oldRecord.getType());
885 newMembers, recordTy.getPacked(), recordTy.getPadded(), recordTy);
890 cgm.
errorNYI(
"Unhandled type in getNewInitValue");
898 assert(oldGV.getSymName() == newGV.getSymName() &&
"symbol names must match");
900 mlir::Type oldTy = oldGV.getSymType();
901 mlir::Type newTy = newGV.getSymType();
906 assert(oldTy != newTy &&
"expected type change in replaceGlobal");
909 std::optional<mlir::SymbolTable::UseRange> oldSymUses =
910 oldGV.getSymbolUses(theModule);
911 for (mlir::SymbolTable::SymbolUse use : *oldSymUses) {
912 mlir::Operation *userOp = use.getUser();
914 (mlir::isa<cir::GetGlobalOp, cir::GlobalOp, cir::ConstantOp>(userOp)) &&
915 "Unexpected user for global op");
917 if (
auto getGlobalOp = dyn_cast<cir::GetGlobalOp>(use.getUser())) {
918 mlir::Value useOpResultValue = getGlobalOp.getAddr();
919 useOpResultValue.setType(cir::PointerType::get(newTy));
921 mlir::OpBuilder::InsertionGuard guard(builder);
922 builder.setInsertionPointAfter(getGlobalOp);
923 mlir::Type ptrTy = builder.getPointerTo(oldTy);
925 builder.createBitcast(getGlobalOp->getLoc(), useOpResultValue, ptrTy);
926 useOpResultValue.replaceAllUsesExcept(
cast,
cast.getDefiningOp());
927 }
else if (
auto glob = dyn_cast<cir::GlobalOp>(userOp)) {
928 if (
auto init = glob.getInitialValue()) {
929 mlir::Attribute nw =
getNewInitValue(*
this, newGV, oldTy, init.value());
930 glob.setInitialValueAttr(nw);
932 }
else if (
auto c = dyn_cast<cir::ConstantOp>(userOp)) {
934 auto typedAttr = mlir::cast<mlir::TypedAttr>(init);
935 mlir::OpBuilder::InsertionGuard guard(builder);
936 builder.setInsertionPointAfter(
c);
937 auto newUser = cir::ConstantOp::create(builder,
c.getLoc(), typedAttr);
938 c.replaceAllUsesWith(newUser.getOperation());
976 "getOrCreateCIRGlobal: global with non-GlobalOp type");
981 mlir::ptr::MemorySpaceAttrInterface entryCIRAS = entry.getAddrSpaceAttr();
987 if (entry.getSymType() == ty &&
997 if (isForDefinition && !entry.isDeclaration()) {
999 "getOrCreateCIRGlobal: global with conflicting type");
1007 if (!isForDefinition)
1016 bool isConstant =
false;
1021 astContext,
true, !needsDtor);
1024 mlir::ptr::MemorySpaceAttrInterface declCIRAS =
1030 *
this, loc, mangledName, ty, isConstant, declCIRAS,
1031 entry.getOperation());
1051 if (langOpts.OpenMP && !langOpts.OpenMPSimd)
1053 "getOrCreateCIRGlobal: OpenMP target global variable");
1055 gv.setAlignmentAttr(
getSize(astContext.getDeclAlign(d)));
1069 if (astContext.isMSStaticDataMemberInlineDefinition(d))
1071 "getOrCreateCIRGlobal: MS static data member inline definition");
1075 if (
const SectionAttr *sa = d->
getAttr<SectionAttr>())
1076 gv.setSectionAttr(builder.getStringAttr(sa->getName()));
1081 if (
getTriple().getArch() == llvm::Triple::xcore)
1083 "getOrCreateCIRGlobal: XCore specific ABI requirements");
1093 "getOrCreateCIRGlobal: external const declaration with initializer");
1105 "getOrCreateCIRGlobal: HIP managed attribute");
1140 mlir::Type ptrTy = builder.getPointerTo(g.getSymType(), g.getAddrSpaceAttr());
1141 return cir::GetGlobalOp::create(
1144 g.getStaticLocalGuard().has_value());
1152 cir::PointerType ptrTy =
1153 builder.getPointerTo(globalOp.getSymType(), globalOp.getAddrSpaceAttr());
1154 return builder.getGlobalViewAttr(ptrTy, globalOp);
1158 assert((mlir::isa<cir::FuncOp>(gv.getOperation()) ||
1159 !gv.isDeclarationForLinker()) &&
1160 "Only globals with definition can force usage.");
1165 assert(!gv.isDeclarationForLinker() &&
1166 "Only globals with definition can force usage.");
1171 cir::CIRGlobalValueInterface gv) {
1172 assert((mlir::isa<cir::FuncOp>(gv.getOperation()) ||
1173 !gv.isDeclarationForLinker()) &&
1174 "Only globals with definition can force usage.");
1182 std::vector<cir::CIRGlobalValueInterface> &list) {
1187 mlir::Location loc = builder.getUnknownLoc();
1189 usedArray.resize(list.size());
1190 for (
auto [i, op] : llvm::enumerate(list)) {
1191 usedArray[i] = cir::GlobalViewAttr::get(
1192 cgm.
voidPtrTy, mlir::FlatSymbolRefAttr::get(op.getNameAttr()));
1195 cir::ArrayType arrayTy = cir::ArrayType::get(cgm.
voidPtrTy, usedArray.size());
1197 cir::ConstArrayAttr initAttr = cir::ConstArrayAttr::get(
1198 arrayTy, mlir::ArrayAttr::get(&cgm.
getMLIRContext(), usedArray));
1202 gv.setLinkage(cir::GlobalLinkageKind::AppendingLinkage);
1203 gv.setInitialValueAttr(initAttr);
1204 gv.setSectionAttr(builder.getStringAttr(
"llvm.metadata"));
1216 "emitGlobalVarDefinition: emit OpenCL/OpenMP global variable");
1223 bool isDefinitionAvailableExternally =
1228 if (isDefinitionAvailableExternally &&
1236 mlir::Attribute init;
1237 bool needsGlobalCtor =
false;
1238 bool needsGlobalDtor =
1239 !isDefinitionAvailableExternally &&
1244 std::optional<ConstantEmitter> emitter;
1249 bool isCUDASharedVar =
1254 bool isCUDAShadowVar =
1256 (vd->
hasAttr<CUDAConstantAttr>() || vd->
hasAttr<CUDADeviceAttr>() ||
1257 vd->
hasAttr<CUDASharedAttr>());
1258 bool isCUDADeviceShadowVar =
1264 (isCUDASharedVar || isCUDAShadowVar || isCUDADeviceShadowVar)) {
1266 }
else if (vd->
hasAttr<LoaderUninitializedAttr>()) {
1268 "emitGlobalVarDefinition: loader uninitialized attribute");
1269 }
else if (!initExpr) {
1282 emitter.emplace(*
this);
1283 mlir::Attribute initializer = emitter->tryEmitForInitializer(*initDecl);
1292 "emitGlobalVarDefinition: flexible array initializer");
1294 if (!isDefinitionAvailableExternally)
1295 needsGlobalCtor =
true;
1298 "emitGlobalVarDefinition: static initializer");
1309 mlir::Type initType;
1310 if (mlir::isa<mlir::SymbolRefAttr>(init)) {
1313 "emitGlobalVarDefinition: global initializer is a symbol reference");
1316 assert(mlir::isa<mlir::TypedAttr>(init) &&
"This should have a type");
1317 auto typedInitAttr = mlir::cast<mlir::TypedAttr>(init);
1318 initType = typedInitAttr.getType();
1320 assert(!mlir::isa<mlir::NoneType>(initType) &&
"Should have a type by now");
1326 if (!gv || gv.getSymType() != initType) {
1328 "emitGlobalVarDefinition: global initializer with type mismatch");
1334 if (vd->
hasAttr<AnnotateAttr>())
1347 if (langOpts.CUDA) {
1348 if (langOpts.CUDAIsDevice) {
1351 if (linkage != cir::GlobalLinkageKind::InternalLinkage &&
1353 (vd->
hasAttr<CUDADeviceAttr>() || vd->
hasAttr<CUDAConstantAttr>() ||
1356 gv->setAttr(cir::CUDAExternallyInitializedAttr::getMnemonic(),
1372 emitter->finalize(gv);
1376 gv.setConstant((vd->
hasAttr<CUDAConstantAttr>() && langOpts.CUDAIsDevice) ||
1377 (!needsGlobalCtor && !needsGlobalDtor &&
1382 if (
const SectionAttr *sa = vd->
getAttr<SectionAttr>()) {
1385 gv.setConstant(
true);
1389 gv.setLinkage(linkage);
1393 if (linkage == cir::GlobalLinkageKind::CommonLinkage) {
1395 gv.setConstant(
false);
1400 std::optional<mlir::Attribute> initializer = gv.getInitialValue();
1401 if (initializer && !
getBuilder().isNullValue(*initializer))
1402 gv.setLinkage(cir::GlobalLinkageKind::WeakAnyLinkage);
1405 setNonAliasAttributes(vd, gv);
1412 if (needsGlobalCtor || needsGlobalDtor)
1417 mlir::Operation *op) {
1419 if (
const auto *fd = dyn_cast<FunctionDecl>(
decl)) {
1423 if (
const auto *method = dyn_cast<CXXMethodDecl>(
decl)) {
1427 abi->emitCXXStructor(gd);
1428 else if (fd->isMultiVersion())
1429 errorNYI(method->getSourceRange(),
"multiversion functions");
1433 if (method->isVirtual())
1439 if (fd->isMultiVersion())
1440 errorNYI(fd->getSourceRange(),
"multiversion functions");
1445 if (
const auto *vd = dyn_cast<VarDecl>(
decl))
1448 llvm_unreachable(
"Invalid argument to CIRGenModule::emitGlobalDefinition");
1462 astContext.getAsConstantArrayType(e->
getType());
1463 uint64_t finalSize = cat->getZExtSize();
1464 str.resize(finalSize);
1466 mlir::Type eltTy =
convertType(cat->getElementType());
1467 return builder.getString(str, eltTy, finalSize,
false);
1472 auto arrayEltTy = mlir::cast<cir::IntType>(arrayTy.getElementType());
1474 uint64_t arraySize = arrayTy.getSize();
1476 assert(arraySize == literalSize + 1 &&
1477 "wide string literal array size must be literal length plus null "
1482 bool isAllZero =
true;
1483 for (
unsigned i = 0; i < literalSize; ++i) {
1491 return cir::ZeroAttr::get(arrayTy);
1495 elements.reserve(arraySize);
1496 for (
unsigned i = 0; i < literalSize; ++i)
1497 elements.push_back(cir::IntAttr::get(arrayEltTy, e->
getCodeUnit(i)));
1499 elements.push_back(cir::IntAttr::get(arrayEltTy, 0));
1501 auto elementsAttr = mlir::ArrayAttr::get(&
getMLIRContext(), elements);
1502 return builder.getConstArray(elementsAttr, arrayTy);
1513 if (d.
hasAttr<SelectAnyAttr>())
1517 if (
auto *vd = dyn_cast<VarDecl>(&d))
1532 llvm_unreachable(
"No such linkage");
1538 if (
auto globalOp = dyn_cast_or_null<cir::GlobalOp>(op)) {
1539 globalOp.setComdat(
true);
1542 funcOp.setComdat(
true);
1548 genTypes.updateCompletedType(td);
1552 replacements[name] = op;
1558 std::optional<mlir::SymbolTable::UseRange> optionalUseRange =
1559 oldF.getSymbolUses(modOp);
1560 if (!optionalUseRange)
1563 for (
const mlir::SymbolTable::SymbolUse &u : *optionalUseRange) {
1564 auto call = mlir::dyn_cast<cir::CallOp>(u.getUser());
1568 for (
auto [argOp, fnArgType] :
1569 llvm::zip(call.getArgs(), newF.getFunctionType().getInputs())) {
1570 if (argOp.getType() != fnArgType)
1579void CIRGenModule::applyReplacements() {
1580 for (
auto &i : replacements) {
1581 StringRef mangledName = i.first;
1582 mlir::Operation *replacement = i.second;
1588 auto newF = dyn_cast<cir::FuncOp>(replacement);
1591 errorNYI(replacement->getLoc(),
"replacement is not a function");
1596 "call argument types do not match replacement function");
1599 if (oldF.replaceAllSymbolUses(newF.getSymNameAttr(), theModule).failed())
1600 llvm_unreachable(
"internal error, cannot RAUW symbol");
1602 newF->moveBefore(oldF);
1610 mlir::Location loc, StringRef name, mlir::Type ty,
1612 auto gv = mlir::dyn_cast_or_null<cir::GlobalOp>(
getGlobalValue(name));
1616 if (gv.getSymType() == ty)
1622 assert(gv.isDeclaration() &&
"Declaration has wrong type!");
1624 errorNYI(loc,
"createOrReplaceCXXRuntimeVariable: declaration exists with "
1635 mlir::SymbolTable::setSymbolVisibility(gv,
1639 !gv.hasAvailableExternallyLinkage()) {
1643 gv.setAlignmentAttr(
getSize(alignment));
1654 if ((noCommon || vd->
hasAttr<NoCommonAttr>()) && !vd->
hasAttr<CommonAttr>())
1665 if (vd->
hasAttr<SectionAttr>())
1671 if (vd->
hasAttr<PragmaClangBSSSectionAttr>() ||
1672 vd->
hasAttr<PragmaClangDataSectionAttr>() ||
1673 vd->
hasAttr<PragmaClangRelroSectionAttr>() ||
1674 vd->
hasAttr<PragmaClangRodataSectionAttr>())
1682 if (vd->
hasAttr<WeakImportAttr>())
1692 if (vd->
hasAttr<AlignedAttr>())
1699 for (
const FieldDecl *fd : rd->fields()) {
1700 if (fd->isBitField())
1702 if (fd->hasAttr<AlignedAttr>())
1724cir::GlobalLinkageKind
1728 return cir::GlobalLinkageKind::InternalLinkage;
1731 return cir::GlobalLinkageKind::WeakAnyLinkage;
1735 return cir::GlobalLinkageKind::LinkOnceAnyLinkage;
1740 return cir::GlobalLinkageKind::AvailableExternallyLinkage;
1754 return !astContext.getLangOpts().AppleKext
1755 ? cir::GlobalLinkageKind::LinkOnceODRLinkage
1756 : cir::GlobalLinkageKind::InternalLinkage;
1770 return cir::GlobalLinkageKind::ExternalLinkage;
1773 return dd->
hasAttr<CUDAGlobalAttr>()
1774 ? cir::GlobalLinkageKind::ExternalLinkage
1775 : cir::GlobalLinkageKind::InternalLinkage;
1776 return cir::GlobalLinkageKind::WeakODRLinkage;
1784 return cir::GlobalLinkageKind::CommonLinkage;
1790 if (dd->
hasAttr<SelectAnyAttr>())
1791 return cir::GlobalLinkageKind::WeakODRLinkage;
1795 return cir::GlobalLinkageKind::ExternalLinkage;
1807 mlir::Operation *old, cir::FuncOp newFn) {
1809 auto oldFn = mlir::dyn_cast<cir::FuncOp>(old);
1817 if (oldFn->getAttrs().size() <= 1)
1819 "replaceUsesOfNonProtoTypeWithRealFunction: Attribute forwarding");
1822 newFn.setNoProto(oldFn.getNoProto());
1825 std::optional<mlir::SymbolTable::UseRange> symUses =
1826 oldFn.getSymbolUses(oldFn->getParentOp());
1827 for (
const mlir::SymbolTable::SymbolUse &use : symUses.value()) {
1828 mlir::OpBuilder::InsertionGuard guard(builder);
1830 if (
auto noProtoCallOp = mlir::dyn_cast<cir::CallOp>(use.getUser())) {
1831 builder.setInsertionPoint(noProtoCallOp);
1834 cir::CallOp realCallOp = builder.createCallOp(
1835 noProtoCallOp.getLoc(), newFn, noProtoCallOp.getOperands());
1838 noProtoCallOp.replaceAllUsesWith(realCallOp);
1839 noProtoCallOp.erase();
1840 }
else if (
auto getGlobalOp =
1841 mlir::dyn_cast<cir::GetGlobalOp>(use.getUser())) {
1848 mlir::Value res = getGlobalOp.getAddr();
1849 const mlir::Type oldResTy = res.getType();
1850 const auto newPtrTy = cir::PointerType::get(newFn.getFunctionType());
1851 if (oldResTy != newPtrTy) {
1852 res.setType(newPtrTy);
1853 builder.setInsertionPointAfter(getGlobalOp.getOperation());
1854 mlir::Value castRes =
1855 cir::CastOp::create(builder, getGlobalOp.getLoc(), oldResTy,
1856 cir::CastKind::bitcast, res);
1857 res.replaceAllUsesExcept(castRes, castRes.getDefiningOp());
1859 }
else if (mlir::isa<cir::GlobalOp>(use.getUser())) {
1865 "replaceUsesOfNonProtoTypeWithRealFunction: unexpected use type");
1870cir::GlobalLinkageKind
1872 GVALinkage linkage = astContext.GetGVALinkageForVariable(vd);
1879 GVALinkage linkage = astContext.GetGVALinkageForFunction(d);
1881 if (
const auto *dtor = dyn_cast<CXXDestructorDecl>(d))
1890 StringRef globalName,
CharUnits alignment) {
1896 cgm, loc, globalName,
c.getType(), !cgm.
getLangOpts().WritableStrings);
1899 gv.setAlignmentAttr(cgm.
getSize(alignment));
1901 cir::GlobalLinkageKindAttr::get(cgm.
getBuilder().getContext(), lt));
1905 if (gv.isWeakForLinker()) {
1906 assert(cgm.
supportsCOMDAT() &&
"Only COFF uses weak string literals");
1909 cgm.
setDSOLocal(
static_cast<mlir::Operation *
>(gv));
1930 std::string result =
1941 astContext.getAlignOfGlobalVarInChars(
s->getType(),
nullptr);
1949 if (!gv.getAlignment() ||
1950 uint64_t(alignment.
getQuantity()) > *gv.getAlignment())
1951 gv.setAlignmentAttr(
getSize(alignment));
1956 if (
getCXXABI().getMangleContext().shouldMangleStringLiteral(
s) &&
1959 "getGlobalForStringLiteral: mangle string literals");
1967 mlir::Location loc =
s->getBeginLoc().isValid()
1969 : builder.getUnknownLoc();
1970 auto typedC = llvm::cast<mlir::TypedAttr>(
c);
1972 cir::GlobalLinkageKind::PrivateLinkage, *
this,
1973 uniqueName, alignment);
1987 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(gv.getSymType());
1988 assert(arrayTy &&
"String literal must be array");
1992 return builder.getGlobalViewAttr(ptrTy, gv);
2008 errorNYI(
"SYCL or OpenMP temp address space");
2018 "emitExplicitCastExprType");
2024 auto ty = mlir::cast<cir::MethodType>(
convertType(destTy));
2025 return builder.getNullMethodAttr(ty);
2028 auto ty = mlir::cast<cir::DataMemberType>(
convertType(destTy));
2029 return builder.getNullDataMemberAttr(ty);
2040 if (
const auto *methodDecl = dyn_cast<CXXMethodDecl>(
decl)) {
2042 if (methodDecl->isVirtual())
2043 return cir::ConstantOp::create(
2044 builder, loc,
getCXXABI().buildVirtualMethodAttr(ty, methodDecl));
2050 return cir::ConstantOp::create(builder, loc,
2051 builder.getMethodAttr(ty, methodFuncOp));
2057 return cir::ConstantOp::create(
2058 builder, loc, builder.getDataMemberAttr(ty,
fieldDecl->getFieldIndex()));
2068 if (
auto *oid = dyn_cast<ObjCImplDecl>(
decl))
2069 errorNYI(oid->getSourceRange(),
"emitDeclConext: ObjCImplDecl");
2079 if (
decl->isTemplated())
2082 switch (
decl->getKind()) {
2085 decl->getDeclKindName());
2088 case Decl::CXXConversion:
2089 case Decl::CXXMethod:
2090 case Decl::Function: {
2093 if (!fd->isConsteval())
2102 case Decl::Decomposition:
2103 case Decl::VarTemplateSpecialization: {
2105 if (
auto *decomp = dyn_cast<DecompositionDecl>(
decl))
2106 for (
auto *binding : decomp->flat_bindings())
2107 if (
auto *holdingVar = binding->getHoldingVar())
2111 case Decl::OpenACCRoutine:
2114 case Decl::OpenACCDeclare:
2117 case Decl::OMPThreadPrivate:
2120 case Decl::OMPGroupPrivate:
2123 case Decl::OMPAllocate:
2126 case Decl::OMPCapturedExpr:
2129 case Decl::OMPDeclareReduction:
2132 case Decl::OMPDeclareMapper:
2135 case Decl::OMPRequires:
2140 case Decl::UsingDirective:
2141 case Decl::UsingEnum:
2142 case Decl::NamespaceAlias:
2144 case Decl::TypeAlias:
2150 case Decl::ClassTemplate:
2152 case Decl::CXXDeductionGuide:
2154 case Decl::ExplicitInstantiation:
2155 case Decl::FunctionTemplate:
2156 case Decl::StaticAssert:
2157 case Decl::TypeAliasTemplate:
2158 case Decl::UsingShadow:
2159 case Decl::VarTemplate:
2160 case Decl::VarTemplatePartialSpecialization:
2163 case Decl::CXXConstructor:
2166 case Decl::CXXDestructor:
2171 case Decl::LinkageSpec:
2172 case Decl::Namespace:
2176 case Decl::ClassTemplateSpecialization:
2177 case Decl::CXXRecord: {
2180 for (
auto *childDecl : crd->
decls())
2186 case Decl::FileScopeAsm:
2188 if (langOpts.CUDA && langOpts.CUDAIsDevice)
2191 if (langOpts.OpenMPIsTargetDevice)
2194 if (langOpts.SYCLIsDevice)
2197 std::string line = file_asm->getAsmString();
2198 globalScopeAsm.push_back(builder.getStringAttr(line));
2205 op.setInitialValueAttr(value);
2219 md->getParent()->getNumVBases() == 0)
2221 "getAddrAndTypeOfCXXStructor: MS ABI complete destructor");
2232 false, isForDefinition);
2234 return {fnType, fn};
2238 mlir::Type funcType,
bool forVTable,
2242 "consteval function should never be emitted");
2252 if (
const auto *dd = dyn_cast<CXXDestructorDecl>(gd.
getDecl())) {
2255 dd->getParent()->getNumVBases() == 0)
2257 "getAddrOfFunction: MS ABI complete destructor");
2263 false, isForDefinition);
2265 if (langOpts.CUDA && !langOpts.CUDAIsDevice &&
2271 bool isHIPHandle = mlir::isa<cir::GlobalOp>(*handle);
2272 if (isForDefinition || isHIPHandle)
2274 return mlir::dyn_cast<cir::FuncOp>(*handle);
2283 llvm::raw_svector_ostream
out(buffer);
2292 assert(ii &&
"Attempt to mangle unnamed decl.");
2294 const auto *fd = dyn_cast<FunctionDecl>(nd);
2298 }
else if (fd && fd->hasAttr<CUDAGlobalAttr>() &&
2302 DeviceKernelAttr::isOpenCLSpelling(
2303 fd->getAttr<DeviceKernelAttr>()) &&
2320 if (
const auto *fd = dyn_cast<FunctionDecl>(nd)) {
2321 if (fd->isMultiVersion()) {
2323 "getMangledName: multi-version functions");
2328 "getMangledName: GPU relocatable device code");
2331 return std::string(
out.str());
2334static FunctionDecl *
2349 if (
auto *methodDecl = dyn_cast<CXXMethodDecl>(protoFunc);
2350 methodDecl && methodDecl->isImplicitObjectMemberFunction()) {
2352 paramTypes.insert(paramTypes.begin(), methodDecl->getThisType());
2355 fpt->getExtProtoInfo());
2366 params.reserve(fpt->getNumParams());
2369 for (
unsigned i = 0, e = fpt->getNumParams(); i != e; ++i) {
2373 nullptr, fpt->getParamType(i),
nullptr,
2376 params.push_back(parm);
2379 tempFunc->setParams(params);
2404 if (
const auto *cd = dyn_cast<CXXConstructorDecl>(canonicalGd.
getDecl())) {
2407 "getMangledName: C++ constructor without variants");
2416 auto result = manglings.insert(std::make_pair(mangledName, gd));
2417 return mangledDeclNames[canonicalGd] = result.first->first();
2421 assert(!d->
getInit() &&
"Cannot emit definite definitions here!");
2429 if (gv && !mlir::cast<cir::GlobalOp>(gv).isDeclaration())
2445 if (langOpts.EmitAllDecls)
2448 const auto *vd = dyn_cast<VarDecl>(global);
2450 ((codeGenOpts.KeepPersistentStorageVariables &&
2451 (vd->getStorageDuration() ==
SD_Static ||
2452 vd->getStorageDuration() ==
SD_Thread)) ||
2453 (codeGenOpts.KeepStaticConsts && vd->getStorageDuration() ==
SD_Static &&
2454 vd->getType().isConstQualified())))
2467 if (langOpts.OpenMP >= 50 && !langOpts.OpenMPSimd) {
2468 std::optional<OMPDeclareTargetDeclAttr *> activeAttr =
2469 OMPDeclareTargetDeclAttr::getActiveAttr(global);
2470 if (!activeAttr || (*activeAttr)->getLevel() != (
unsigned)-1)
2474 const auto *fd = dyn_cast<FunctionDecl>(global);
2481 if (fd->hasAttr<TargetVersionAttr>() && !fd->isMultiVersion())
2483 if (langOpts.SYCLIsDevice) {
2484 errorNYI(fd->getSourceRange(),
"mayBeEmittedEagerly: SYCL");
2488 const auto *vd = dyn_cast<VarDecl>(global);
2490 if (astContext.getInlineVariableDefinitionKind(vd) ==
2498 if (langOpts.OpenMP && langOpts.OpenMPUseTLS &&
2499 astContext.getTargetInfo().isTLSSupported() &&
isa<VarDecl>(global) &&
2501 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(global))
2504 assert((fd || vd) &&
2505 "Only FunctionDecl and VarDecl should hit this path so far.");
2510 cir::CIRGlobalValueInterface gv) {
2511 if (gv.hasLocalLinkage())
2514 if (!gv.hasDefaultVisibility() && !gv.hasExternalWeakLinkage())
2522 const llvm::Triple &tt = cgm.
getTriple();
2524 if (tt.isOSCygMing()) {
2533 cgm.
errorNYI(
"shouldAssumeDSOLocal: MinGW");
2539 if (tt.isOSBinFormatCOFF() && gv.hasExternalWeakLinkage())
2547 if (tt.isOSBinFormatCOFF() || (tt.isOSWindows() && tt.isOSBinFormatMachO()))
2551 if (!tt.isOSBinFormatELF())
2556 if (rm != llvm::Reloc::Static && !lOpts.PIE) {
2564 return !(lOpts.SemanticInterposition || lOpts.HalfNoSemanticInterposition);
2568 if (!gv.isDeclarationForLinker())
2574 if (rm == llvm::Reloc::PIC_ && gv.hasExternalWeakLinkage())
2581 if (cgOpts.DirectAccessExternalData) {
2587 if (
auto globalOp = dyn_cast<cir::GlobalOp>(gv.getOperation())) {
2620 if (
auto globalValue = dyn_cast<cir::CIRGlobalValueInterface>(op))
2639 auto res = manglings.find(mangledName);
2640 if (res == manglings.end())
2642 result = res->getValue();
2649 return cir::TLS_Model::GeneralDynamic;
2651 return cir::TLS_Model::LocalDynamic;
2653 return cir::TLS_Model::InitialExec;
2655 return cir::TLS_Model::LocalExec;
2657 llvm_unreachable(
"Invalid TLS model!");
2661 assert(d.
getTLSKind() &&
"setting TLS mode on non-TLS var!");
2666 if (d.
getAttr<TLSModelAttr>())
2670 global.setTlsModel(tlm);
2675 cir::FuncOp func,
bool isThunk) {
2677 cir::CallingConv callingConv;
2678 cir::SideEffect sideEffect;
2685 mlir::NamedAttrList pal{};
2686 std::vector<mlir::NamedAttrList> argAttrs(info.
arguments().size());
2687 mlir::NamedAttrList retAttrs{};
2689 retAttrs, callingConv, sideEffect,
2692 for (mlir::NamedAttribute
attr : pal)
2693 func->setAttr(
attr.getName(),
attr.getValue());
2695 llvm::for_each(llvm::enumerate(argAttrs), [func](
auto idx_arg_pair) {
2696 mlir::function_interface_impl::setArgAttrs(func, idx_arg_pair.index(),
2697 idx_arg_pair.value());
2699 if (!retAttrs.empty())
2700 mlir::function_interface_impl::setResultAttrs(func, 0, retAttrs);
2713 bool isIncompleteFunction,
2721 if (!isIncompleteFunction)
2723 getTypes().arrangeGlobalDeclaration(globalDecl),
2726 if (!isIncompleteFunction && func.isDeclaration())
2739 if (funcDecl->isInlineBuiltinDeclaration()) {
2741 bool hasBody = funcDecl->
hasBody(fdBody);
2743 assert(hasBody &&
"Inline builtin declarations should always have an "
2748 if (funcDecl->isReplaceableGlobalAllocationFunction()) {
2751 func->setAttr(cir::CIRDialect::getNoBuiltinAttrName(),
2763 if (!langOpts.Exceptions)
2766 if (langOpts.CXXExceptions)
2769 if (langOpts.ObjCExceptions)
2780 f->setAttr(cir::CIRDialect::getNoThrowAttrName(),
2783 std::optional<cir::InlineKind> existingInlineKind = f.getInlineKind();
2785 existingInlineKind && *existingInlineKind == cir::InlineKind::NoInline;
2786 bool isAlwaysInline = existingInlineKind &&
2787 *existingInlineKind == cir::InlineKind::AlwaysInline;
2791 if (!isAlwaysInline &&
2796 f.setInlineKind(cir::InlineKind::NoInline);
2811 if (
decl->hasAttr<NoInlineAttr>() && !isAlwaysInline) {
2813 f.setInlineKind(cir::InlineKind::NoInline);
2814 }
else if (
decl->hasAttr<AlwaysInlineAttr>() && !isNoInline) {
2817 f.setInlineKind(cir::InlineKind::AlwaysInline);
2821 if (!isAlwaysInline)
2822 f.setInlineKind(cir::InlineKind::NoInline);
2827 if (
auto *fd = dyn_cast<FunctionDecl>(
decl)) {
2832 auto checkRedeclForInline = [](
const FunctionDecl *redecl) {
2833 return redecl->isInlineSpecified();
2835 if (any_of(
decl->redecls(), checkRedeclForInline))
2840 return any_of(pattern->
redecls(), checkRedeclForInline);
2842 if (checkForInline(fd)) {
2843 f.setInlineKind(cir::InlineKind::InlineHint);
2844 }
else if (codeGenOpts.getInlining() ==
2846 !fd->isInlined() && !isAlwaysInline) {
2847 f.setInlineKind(cir::InlineKind::NoInline);
2856 StringRef mangledName, mlir::Type funcType,
GlobalDecl gd,
bool forVTable,
2858 mlir::NamedAttrList extraAttrs) {
2861 if (
const auto *fd = cast_or_null<FunctionDecl>(d)) {
2863 if (
getLangOpts().OpenMPIsTargetDevice && openMPRuntime &&
2865 !dontDefer && !isForDefinition) {
2868 if (
const auto *cd = dyn_cast<CXXConstructorDecl>(fdDef))
2870 else if (
const auto *dd = dyn_cast<CXXDestructorDecl>(fdDef))
2880 if (fd->isMultiVersion())
2881 errorNYI(fd->getSourceRange(),
"getOrCreateCIRFunction: multi-version");
2887 assert(mlir::isa<cir::FuncOp>(entry));
2892 if (d && !d->
hasAttr<DLLImportAttr>() && !d->
hasAttr<DLLExportAttr>()) {
2900 if (isForDefinition && fn && !fn.isDeclaration()) {
2907 diagnosedConflictingDefinitions.insert(gd).second) {
2911 diag::note_previous_definition);
2915 if (fn && fn.getFunctionType() == funcType) {
2919 if (!isForDefinition) {
2927 auto *funcDecl = llvm::cast_or_null<FunctionDecl>(gd.
getDecl());
2928 bool invalidLoc = !funcDecl ||
2929 funcDecl->getSourceRange().getBegin().isInvalid() ||
2930 funcDecl->getSourceRange().getEnd().isInvalid();
2932 invalidLoc ? theModule->getLoc() :
getLoc(funcDecl->getSourceRange()),
2933 mangledName, mlir::cast<cir::FuncType>(funcType), funcDecl);
2935 if (funcDecl && funcDecl->hasAttr<AnnotateAttr>())
2936 deferredAnnotations[mangledName] = funcDecl;
2947 auto symbolOp = mlir::cast<mlir::SymbolOpInterface>(entry);
2955 if (symbolOp.getSymbolUses(symbolOp->getParentOp()))
2965 if (!extraAttrs.empty()) {
2966 extraAttrs.append(funcOp->getAttrs());
2967 funcOp->setAttrs(extraAttrs);
2974 assert(funcOp.getFunctionType() == funcType);
2981 if (isa_and_nonnull<CXXDestructorDecl>(d) &&
3011 fd = fd->getPreviousDecl()) {
3013 if (fd->doesThisDeclarationHaveABody()) {
3026 cir::FuncType funcType,
3030 mlir::OpBuilder::InsertionGuard guard(builder);
3038 builder.setInsertionPoint(cgf->
curFn);
3040 func = cir::FuncOp::create(builder, loc, name, funcType);
3047 func.setNoProto(
true);
3049 assert(func.isDeclaration() &&
"expected empty body");
3053 func.setLinkageAttr(cir::GlobalLinkageKindAttr::get(
3055 mlir::SymbolTable::setSymbolVisibility(
3056 func, mlir::SymbolTable::Visibility::Private);
3064 theModule.push_back(func);
3069 for (
const auto *
attr :
3083 fnOp.setBuiltin(
true);
3089 return cir::CtorKind::Default;
3091 return cir::CtorKind::Copy;
3093 return cir::CtorKind::Move;
3094 return cir::CtorKind::Custom;
3099 return cir::AssignKind::Copy;
3101 return cir::AssignKind::Move;
3102 llvm_unreachable(
"not a copy or move assignment operator");
3110 if (
const auto *dtor = dyn_cast<CXXDestructorDecl>(funcDecl)) {
3111 auto cxxDtor = cir::CXXDtorAttr::get(
3114 funcOp.setCxxSpecialMemberAttr(cxxDtor);
3118 if (
const auto *ctor = dyn_cast<CXXConstructorDecl>(funcDecl)) {
3120 auto cxxCtor = cir::CXXCtorAttr::get(
3122 kind, ctor->isTrivial());
3123 funcOp.setCxxSpecialMemberAttr(cxxCtor);
3127 const auto *method = dyn_cast<CXXMethodDecl>(funcDecl);
3128 if (method && (method->isCopyAssignmentOperator() ||
3129 method->isMoveAssignmentOperator())) {
3131 auto cxxAssign = cir::CXXAssignAttr::get(
3133 assignKind, method->isTrivial());
3134 funcOp.setCxxSpecialMemberAttr(cxxAssign);
3140 cir::FuncOp funcOp, StringRef name) {
3156 mlir::NamedAttrList extraAttrs,
3158 bool assumeConvergent) {
3159 if (assumeConvergent)
3160 errorNYI(
"createRuntimeFunction: assumeConvergent");
3170 entry.setDSOLocal(
true);
3176mlir::SymbolTable::Visibility
3180 if (op.isDeclaration())
3181 return mlir::SymbolTable::Visibility::Private;
3185mlir::SymbolTable::Visibility
3188 case cir::GlobalLinkageKind::InternalLinkage:
3189 case cir::GlobalLinkageKind::PrivateLinkage:
3190 return mlir::SymbolTable::Visibility::Private;
3191 case cir::GlobalLinkageKind::ExternalLinkage:
3192 case cir::GlobalLinkageKind::ExternalWeakLinkage:
3193 case cir::GlobalLinkageKind::LinkOnceODRLinkage:
3194 case cir::GlobalLinkageKind::AvailableExternallyLinkage:
3195 case cir::GlobalLinkageKind::CommonLinkage:
3196 case cir::GlobalLinkageKind::WeakAnyLinkage:
3197 case cir::GlobalLinkageKind::WeakODRLinkage:
3198 return mlir::SymbolTable::Visibility::Public;
3200 llvm::errs() <<
"visibility not implemented for '"
3201 << stringifyGlobalLinkageKind(glk) <<
"'\n";
3202 assert(0 &&
"not implemented");
3205 llvm_unreachable(
"linkage should be handled above!");
3209 clang::VisibilityAttr::VisibilityType visibility) {
3210 switch (visibility) {
3211 case clang::VisibilityAttr::VisibilityType::Default:
3212 return cir::VisibilityKind::Default;
3213 case clang::VisibilityAttr::VisibilityType::Hidden:
3214 return cir::VisibilityKind::Hidden;
3215 case clang::VisibilityAttr::VisibilityType::Protected:
3216 return cir::VisibilityKind::Protected;
3218 llvm_unreachable(
"unexpected visibility value");
3223 const clang::VisibilityAttr *va =
decl->getAttr<clang::VisibilityAttr>();
3224 cir::VisibilityAttr cirVisibility =
3227 cirVisibility = cir::VisibilityAttr::get(
3231 return cirVisibility;
3237 applyReplacements();
3239 theModule->setAttr(cir::CIRDialect::getModuleLevelAsmAttrName(),
3240 builder.getArrayAttr(globalScopeAsm));
3242 emitGlobalAnnotations();
3244 if (!recordLayoutEntries.empty())
3246 cir::CIRDialect::getRecordLayoutsAttrName(),
3247 mlir::DictionaryAttr::get(&
getMLIRContext(), recordLayoutEntries));
3256 std::string cuidName =
3259 auto loc = builder.getUnknownLoc();
3260 mlir::ptr::MemorySpaceAttrInterface addrSpace =
3262 getGlobalVarAddressSpace(
nullptr));
3266 gv.setLinkage(cir::GlobalLinkageKind::ExternalLinkage);
3268 auto zeroAttr = cir::IntAttr::get(int8Ty, 0);
3269 gv.setInitialValueAttr(zeroAttr);
3271 mlir::SymbolTable::setSymbolVisibility(
3272 gv, mlir::SymbolTable::Visibility::Public);
3285 cir::FuncOp aliasee,
3286 cir::GlobalLinkageKind linkage) {
3288 auto *aliasFD = dyn_cast<FunctionDecl>(aliasGD.
getDecl());
3289 assert(aliasFD &&
"expected FunctionDecl");
3300 mangledName, fnType, aliasFD);
3301 alias.setAliasee(aliasee.getName());
3302 alias.setLinkage(linkage);
3306 mlir::SymbolTable::setSymbolVisibility(
3307 alias, mlir::SymbolTable::Visibility::Private);
3319 "declaration exists with different type");
3331 return genTypes.convertType(
type);
3338 return mlir::verify(theModule).succeeded();
3347 return builder.getConstNullPtrAttr(builder.getUInt8PtrTy());
3350 langOpts.ObjCRuntime.isGNUFamily()) {
3351 errorNYI(loc,
"getAddrOfRTTIDescriptor: Objc PtrType & Objc RT GUN");
3361 llvm::iterator_range<CastExpr::path_const_iterator> path) {
3368 assert(!base->isVirtual() &&
"Should not see virtual bases here!");
3373 const auto *baseDecl = base->getType()->castAsCXXRecordDecl();
3385 llvm::StringRef feature) {
3386 unsigned diagID = diags.getCustomDiagID(
3388 return diags.Report(loc, diagID) << feature;
3392 llvm::StringRef feature) {
3404 "cannot compile this %0 yet");
3405 diags.Report(astContext.getFullLoc(
s->getBeginLoc()), diagId)
3406 <<
type <<
s->getSourceRange();
3412 "cannot compile this %0 yet");
3413 diags.Report(astContext.getFullLoc(d->
getLocation()), diagId) <<
type;
3417 cir::LabelOp label) {
3418 [[maybe_unused]]
auto result =
3420 assert(result.second &&
3421 "attempting to map a blockaddress info that is already mapped");
3426 assert(result.second &&
3427 "attempting to map a blockaddress operation that is already mapped");
3431 cir::LabelOp label) {
3433 assert(result.second &&
3434 "attempting to map a blockaddress operation that is already mapped");
3438 cir::LabelOp newLabel) {
3441 "trying to update a blockaddress not previously mapped");
3442 assert(!it->second &&
"blockaddress already has a resolved label");
3444 it->second = newLabel;
3457 "not a global temporary");
3469 materializedType = mte->
getType();
3473 auto insertResult = materializedGlobalTemporaryMap.insert({mte,
nullptr});
3474 if (!insertResult.second)
3481 llvm::raw_svector_ostream
out(name);
3499 value = &evalResult.
Val;
3503 std::optional<ConstantEmitter> emitter;
3504 mlir::Attribute initialValue =
nullptr;
3505 bool isConstant =
false;
3509 emitter.emplace(*
this);
3510 initialValue = emitter->emitForInitializer(*value, materializedType);
3515 type = mlir::cast<mlir::TypedAttr>(initialValue).getType();
3524 if (linkage == cir::GlobalLinkageKind::ExternalLinkage) {
3526 if (
varDecl->isStaticDataMember() &&
varDecl->getAnyInitializer(initVD) &&
3534 linkage = cir::GlobalLinkageKind::InternalLinkage;
3539 gv.setInitialValueAttr(initialValue);
3542 emitter->finalize(gv);
3544 if (!gv.hasLocalLinkage()) {
3549 gv.setAlignment(align.getAsAlign().value());
3552 "Global temporary with comdat/weak linkage");
3555 "Global temporary with thread local storage");
3556 mlir::Operation *cv = gv;
3562 mlir::Operation *&entry = materializedGlobalTemporaryMap[mte];
3564 entry->replaceAllUsesWith(cv);
3584 "emitForInitializer should take tpo->getType().getAddressSpace()");
3585 mlir::Attribute init =
3595 cir::GlobalLinkageKind linkage =
3597 ? cir::GlobalLinkageKind::LinkOnceODRLinkage
3598 : cir::GlobalLinkageKind::InternalLinkage;
3601 auto globalOp =
createGlobalOp(*
this, builder.getUnknownLoc(), name,
3602 typedInit.getType(),
true);
3603 globalOp.setLinkage(linkage);
3604 globalOp.setAlignment(alignment.
getAsAlign().value());
3606 linkage == cir::GlobalLinkageKind::LinkOnceODRLinkage);
3621CIRGenModule::getOrCreateAnnotationArgs(
const AnnotateAttr *
attr) {
3628 llvm::FoldingSetNodeID id;
3629 for (
Expr *e : exprs)
3632 mlir::ArrayAttr &lookup = annotationArgs[
id.ComputeHash()];
3637 args.reserve(exprs.size());
3638 for (
Expr *e : exprs) {
3639 if (
auto *strE = dyn_cast<clang::StringLiteral>(e->IgnoreParenCasts())) {
3640 args.push_back(builder.getStringAttr(strE->getString()));
3641 }
else if (
auto *intE =
3642 dyn_cast<clang::IntegerLiteral>(e->IgnoreParenCasts())) {
3643 auto intTy = builder.getIntegerType(intE->getValue().getBitWidth());
3644 args.push_back(builder.getIntegerAttr(intTy, intE->getValue()));
3646 errorNYI(e->getExprLoc(),
"annotation argument expression");
3650 return lookup = builder.getArrayAttr(args);
3653cir::AnnotationAttr CIRGenModule::emitAnnotateAttr(
const AnnotateAttr *aa) {
3654 mlir::StringAttr annoGV = builder.getStringAttr(aa->getAnnotation());
3655 mlir::ArrayAttr args = getOrCreateAnnotationArgs(aa);
3656 return cir::AnnotationAttr::get(&
getMLIRContext(), annoGV, args);
3660 mlir::Operation *gv) {
3661 assert(d->
hasAttr<AnnotateAttr>() &&
"no annotate attribute");
3663 "annotation only on globals");
3666 annotations.push_back(emitAnnotateAttr(i));
3667 if (
auto global = dyn_cast<cir::GlobalOp>(gv))
3668 global.setAnnotationsAttr(builder.getArrayAttr(annotations));
3669 else if (
auto func = dyn_cast<cir::FuncOp>(gv))
3670 func.setAnnotationsAttr(builder.getArrayAttr(annotations));
3673void CIRGenModule::emitGlobalAnnotations() {
3674 for (
const auto &[mangledName, vd] : deferredAnnotations) {
3679 deferredAnnotations.clear();
Defines the clang::ASTContext interface.
This file provides some common utility functions for processing Lambda related AST Constructs.
static bool shouldAssumeDSOLocal(const CIRGenModule &cgm, cir::CIRGlobalValueInterface gv)
static cir::AssignKind getAssignKindFromDecl(const CXXMethodDecl *method)
static FunctionDecl * createOpenACCBindTempFunction(ASTContext &ctx, const IdentifierInfo *bindName, const FunctionDecl *protoFunc)
static bool shouldBeInCOMDAT(CIRGenModule &cgm, const Decl &d)
static mlir::Attribute getNewInitValue(CIRGenModule &cgm, cir::GlobalOp newGlob, mlir::Type oldTy, mlir::Attribute oldInit)
static bool hasUnwindExceptions(const LangOptions &langOpts)
Determines whether the language options require us to model unwind exceptions.
static void setWindowsItaniumDLLImport(CIRGenModule &cgm, bool isLocal, cir::FuncOp funcOp, StringRef name)
static std::string getMangledNameImpl(CIRGenModule &cgm, GlobalDecl gd, const NamedDecl *nd)
static llvm::SmallVector< int64_t > indexesOfArrayAttr(mlir::ArrayAttr indexes)
static bool isViewOnGlobal(cir::GlobalOp glob, cir::GlobalViewAttr view)
static cir::GlobalOp generateStringLiteral(mlir::Location loc, mlir::TypedAttr c, cir::GlobalLinkageKind lt, CIRGenModule &cgm, StringRef globalName, CharUnits alignment)
static bool hasImplicitAttr(const ValueDecl *decl)
static CIRGenCXXABI * createCXXABI(CIRGenModule &cgm)
static bool isVarDeclStrongDefinition(const ASTContext &astContext, CIRGenModule &cgm, const VarDecl *vd, bool noCommon)
static void setLinkageForGV(cir::GlobalOp &gv, const NamedDecl *nd)
static cir::CtorKind getCtorKindFromDecl(const CXXConstructorDecl *ctor)
static void emitUsed(CIRGenModule &cgm, StringRef name, std::vector< cir::CIRGlobalValueInterface > &list)
static bool verifyPointerTypeArgs(mlir::ModuleOp modOp, cir::FuncOp oldF, cir::FuncOp newF)
static cir::GlobalViewAttr createNewGlobalView(CIRGenModule &cgm, cir::GlobalOp newGlob, cir::GlobalViewAttr attr, mlir::Type oldTy)
This file defines OpenACC nodes for declarative directives.
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
Defines the SourceManager interface.
This file defines OpenMP AST classes for executable directives and clauses.
__device__ __2f16 float __ockl_bool s
__device__ __2f16 float c
cir::GlobalViewAttr getGlobalViewAttr(cir::GlobalOp globalOp, mlir::ArrayAttr indices={})
Get constant address of a global variable as an MLIR attribute.
cir::PointerType getPointerTo(mlir::Type ty)
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
TranslationUnitDecl * getTranslationUnitDecl() const
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
@ Strong
Strong definition.
@ WeakUnknown
Weak for now, might become strong later in this TU.
bool DeclMustBeEmitted(const Decl *D)
Determines if the decl can be CodeGen'ed or deserialized from PCH lazily, only when used; this is onl...
StringRef getCUIDHash() const
void Deallocate(void *Ptr) const
GVALinkage GetGVALinkageForFunction(const FunctionDecl *FD) const
bool isAlignmentRequired(const Type *T) const
Determine if the alignment the type has was required using an alignment attribute.
int64_t toBits(CharUnits CharSize) const
Convert a size in characters to a size in bits.
GVALinkage GetGVALinkageForVariable(const VarDecl *VD) const
unsigned getTypeAlignIfKnown(QualType T, bool NeedsPreferredAlignment=false) const
Return the alignment of a type, in bits, or 0 if the type is incomplete and we cannot determine the a...
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
const TargetInfo & getTargetInfo() const
TargetCXXABI::Kind getCXXABIKind() const
Return the C++ ABI kind that should be used.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
mlir::Attribute getConstRecordOrZeroAttr(mlir::ArrayAttr arrayAttr, bool packed=false, bool padded=false, mlir::Type type={})
uint64_t computeOffsetFromGlobalViewIndices(const cir::CIRDataLayout &layout, mlir::Type ty, llvm::ArrayRef< int64_t > indices)
void computeGlobalViewIndicesFromFlatOffset(int64_t offset, mlir::Type ty, cir::CIRDataLayout layout, llvm::SmallVectorImpl< int64_t > &indices)
cir::ConstArrayAttr getConstArray(mlir::Attribute attrs, cir::ArrayType arrayTy) const
virtual mlir::Operation * getKernelHandle(cir::FuncOp fn, GlobalDecl gd)=0
Implements C++ ABI-specific code generation functions.
virtual mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc, QualType ty)=0
virtual void emitCXXConstructors(const clang::CXXConstructorDecl *d)=0
Emit constructor variants required by this ABI.
virtual void emitCXXDestructors(const clang::CXXDestructorDecl *d)=0
Emit dtor variants required by this ABI.
clang::MangleContext & getMangleContext()
Gets the mangle context.
virtual cir::GlobalLinkageKind getCXXDestructorLinkage(GVALinkage linkage, const CXXDestructorDecl *dtor, CXXDtorType dt) const
llvm::ArrayRef< CanQualType > arguments() const
cir::FuncOp generateCode(clang::GlobalDecl gd, cir::FuncOp fn, cir::FuncType funcType)
void emitVariablyModifiedType(QualType ty)
mlir::Operation * curFn
The current function or global initializer that is generated code for.
This class organizes the cross-function state that is used while generating CIR code.
void updateResolvedBlockAddress(cir::BlockAddressOp op, cir::LabelOp newLabel)
void addUsedOrCompilerUsedGlobal(cir::CIRGlobalValueInterface gv)
Add a global to a list to be added to the llvm.compiler.used metadata.
void replaceUsesOfNonProtoTypeWithRealFunction(mlir::Operation *old, cir::FuncOp newFn)
This function is called when we implement a function with no prototype, e.g.
static cir::GlobalOp createGlobalOp(CIRGenModule &cgm, mlir::Location loc, llvm::StringRef name, mlir::Type t, bool isConstant=false, mlir::ptr::MemorySpaceAttrInterface addrSpace={}, mlir::Operation *insertPoint=nullptr)
llvm::StringRef getMangledName(clang::GlobalDecl gd)
CharUnits computeNonVirtualBaseClassOffset(const CXXRecordDecl *derivedClass, llvm::iterator_range< CastExpr::path_const_iterator > path)
void setGlobalVisibility(mlir::Operation *op, const NamedDecl *d) const
Set the visibility for the given global.
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
void emitDeferred()
Emit any needed decls for which code generation was deferred.
cir::GlobalLinkageKind getCIRLinkageVarDefinition(const VarDecl *vd)
clang::ASTContext & getASTContext() const
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()
llvm::DenseMap< cir::BlockAddrInfoAttr, cir::LabelOp > blockAddressInfoToLabel
Map BlockAddrInfoAttr (function name, label name) to the corresponding CIR LabelOp.
void emitTopLevelDecl(clang::Decl *decl)
void emitOMPDeclareMapper(const OMPDeclareMapperDecl *d)
void addReplacement(llvm::StringRef name, mlir::Operation *op)
mlir::Type convertType(clang::QualType type)
bool shouldEmitRTTI(bool forEH=false)
cir::GlobalOp getGlobalForStringLiteral(const StringLiteral *s, llvm::StringRef name=".str")
Return a global symbol reference to a constant array for the given string literal.
std::vector< cir::CIRGlobalValueInterface > llvmUsed
List of global values which are required to be present in the object file; This is used for forcing v...
void emitOMPCapturedExpr(const OMPCapturedExprDecl *d)
void mapUnresolvedBlockAddress(cir::BlockAddressOp op)
bool mustBeEmitted(const clang::ValueDecl *d)
Determine whether the definition must be emitted; if this returns false, the definition can be emitte...
void emitGlobalOpenACCDeclareDecl(const clang::OpenACCDeclareDecl *cd)
mlir::IntegerAttr getSize(CharUnits size)
CIRGenBuilderTy & getBuilder()
void setDSOLocal(mlir::Operation *op) const
std::string getUniqueGlobalName(const std::string &baseName)
std::pair< cir::FuncType, cir::FuncOp > getAddrAndTypeOfCXXStructor(clang::GlobalDecl gd, const CIRGenFunctionInfo *fnInfo=nullptr, cir::FuncType fnType=nullptr, bool dontDefer=false, ForDefinition_t isForDefinition=NotForDefinition)
void setGVProperties(mlir::Operation *op, const NamedDecl *d) const
Set visibility, dllimport/dllexport and dso_local.
cir::GlobalOp getOrCreateCIRGlobal(llvm::StringRef mangledName, mlir::Type ty, LangAS langAS, const VarDecl *d, ForDefinition_t isForDefinition)
If the specified mangled name is not in the module, create and return an mlir::GlobalOp value.
cir::FuncOp createCIRBuiltinFunction(mlir::Location loc, llvm::StringRef name, cir::FuncType ty, const clang::FunctionDecl *fd)
Create a CIR function with builtin attribute set.
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.
std::vector< cir::CIRGlobalValueInterface > llvmCompilerUsed
void emitOMPRequiresDecl(const OMPRequiresDecl *d)
void emitGlobalDefinition(clang::GlobalDecl gd, mlir::Operation *op=nullptr)
void mapResolvedBlockAddress(cir::BlockAddressOp op, cir::LabelOp)
clang::DiagnosticsEngine & getDiags() const
cir::GlobalLinkageKind getCIRLinkageForDeclarator(const DeclaratorDecl *dd, GVALinkage linkage)
mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc, QualType ty, bool forEH=false)
Get the address of the RTTI descriptor for the given type.
void setFunctionAttributes(GlobalDecl gd, cir::FuncOp f, bool isIncompleteFunction, bool isThunk)
Set function attributes for a function declaration.
static mlir::SymbolTable::Visibility getMLIRVisibilityFromCIRLinkage(cir::GlobalLinkageKind GLK)
const clang::TargetInfo & getTarget() const
void setCIRFunctionAttributes(GlobalDecl gd, const CIRGenFunctionInfo &info, cir::FuncOp func, bool isThunk)
Set the CIR function attributes (Sext, zext, etc).
const llvm::Triple & getTriple() const
static mlir::SymbolTable::Visibility getMLIRVisibility(Visibility v)
void emitTentativeDefinition(const VarDecl *d)
void addUsedGlobal(cir::CIRGlobalValueInterface gv)
Add a global value to the llvmUsed list.
cir::GlobalOp createOrReplaceCXXRuntimeVariable(mlir::Location loc, llvm::StringRef name, mlir::Type ty, cir::GlobalLinkageKind linkage, clang::CharUnits alignment)
Will return a global variable of the given type.
void emitOMPAllocateDecl(const OMPAllocateDecl *d)
void error(SourceLocation loc, llvm::StringRef error)
Emit a general error that something can't be done.
void emitGlobalDecl(const clang::GlobalDecl &d)
Helper for emitDeferred to apply actual codegen.
void emitGlobalVarDefinition(const clang::VarDecl *vd, bool isTentative=false)
cir::FuncOp createRuntimeFunction(cir::FuncType ty, llvm::StringRef name, mlir::NamedAttrList extraAttrs={}, bool isLocal=false, bool assumeConvergent=false)
void setTLSMode(mlir::Operation *op, const VarDecl &d)
Set TLS mode for the given operation based on the given variable declaration.
cir::FuncOp getAddrOfFunction(clang::GlobalDecl gd, mlir::Type funcType=nullptr, bool forVTable=false, bool dontDefer=false, ForDefinition_t isForDefinition=NotForDefinition)
Return the address of the given function.
void emitAliasForGlobal(llvm::StringRef mangledName, mlir::Operation *op, GlobalDecl aliasGD, cir::FuncOp aliasee, cir::GlobalLinkageKind linkage)
void emitLLVMUsed()
Emit llvm.used and llvm.compiler.used globals.
mlir::Value emitMemberPointerConstant(const UnaryOperator *e)
void emitGlobalOpenACCDecl(const clang::OpenACCConstructDecl *cd)
bool verifyModule() const
void emitExplicitCastExprType(const ExplicitCastExpr *e, CIRGenFunction *cgf=nullptr)
Emit type info if type of an expression is a variably modified type.
const cir::CIRDataLayout getDataLayout() const
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 constructAttributeList(llvm::StringRef name, const CIRGenFunctionInfo &info, CIRGenCalleeInfo calleeInfo, mlir::NamedAttrList &attrs, llvm::MutableArrayRef< mlir::NamedAttrList > argAttrs, mlir::NamedAttrList &retAttrs, cir::CallingConv &callingConv, cir::SideEffect &sideEffect, bool attrOnCallSite, bool isThunk)
Get the CIR attributes and calling convention to use for a particular function type.
cir::FuncOp getOrCreateCIRFunction(llvm::StringRef mangledName, mlir::Type funcType, clang::GlobalDecl gd, bool forVTable, bool dontDefer=false, bool isThunk=false, ForDefinition_t isForDefinition=NotForDefinition, mlir::NamedAttrList extraAttrs={})
void emitOpenACCRoutineDecl(const clang::FunctionDecl *funcDecl, cir::FuncOp func, SourceLocation pragmaLoc, ArrayRef< const OpenACCClause * > clauses)
void emitVTablesOpportunistically()
Try to emit external vtables as available_externally if they have emitted all inlined virtual functio...
cir::TLS_Model getDefaultCIRTLSModel() const
Get TLS mode from CodeGenOptions.
void addGlobalDtor(cir::FuncOp dtor, std::optional< int > priority=std::nullopt)
Add a function to the list that will be called when the module is unloaded.
void addDeferredDeclToEmit(clang::GlobalDecl GD)
bool shouldEmitCUDAGlobalVar(const VarDecl *global) const
cir::FuncOp createCIRFunction(mlir::Location loc, llvm::StringRef name, cir::FuncType funcType, const clang::FunctionDecl *funcDecl)
const TargetCIRGenInfo & getTargetCIRGenInfo()
void emitCXXGlobalVarDeclInitFunc(const VarDecl *vd, cir::GlobalOp addr, bool performInit)
void setGVPropertiesAux(mlir::Operation *op, const NamedDecl *d) const
LangAS getLangTempAllocaAddressSpace() const
Returns the address space for temporary allocations in the language.
llvm::DenseSet< cir::BlockAddressOp > unresolvedBlockAddressToLabel
Track CIR BlockAddressOps that cannot be resolved immediately because their LabelOp has not yet been ...
mlir::Location getLoc(clang::SourceLocation cLoc)
Helpers to convert the presumed location of Clang's SourceLocation to an MLIR Location.
llvm::DenseMap< mlir::Attribute, cir::GlobalOp > constantStringMap
mlir::Operation * lastGlobalOp
void replaceGlobal(cir::GlobalOp oldGV, cir::GlobalOp newGV)
Replace all uses of the old global with the new global, updating types and references as needed.
static cir::VisibilityKind getGlobalVisibilityKindFromClangVisibility(clang::VisibilityAttr::VisibilityType visibility)
llvm::StringMap< unsigned > cgGlobalNames
void setCXXSpecialMemberAttr(cir::FuncOp funcOp, const clang::FunctionDecl *funcDecl)
Mark the function as a special member (e.g. constructor, destructor)
mlir::TypedAttr emitNullMemberAttr(QualType t, const MemberPointerType *mpt)
Returns a null attribute to represent either a null method or null data member, depending on the type...
mlir::Operation * getGlobalValue(llvm::StringRef ref)
void emitOMPDeclareReduction(const OMPDeclareReductionDecl *d)
mlir::ModuleOp getModule() const
bool supportsCOMDAT() const
void addCompilerUsedGlobal(cir::CIRGlobalValueInterface gv)
Add a global value to the llvmCompilerUsed list.
clang::CharUnits getNaturalTypeAlignment(clang::QualType t, LValueBaseInfo *baseInfo=nullptr, bool forPointeeType=false)
FIXME: this could likely be a common helper and not necessarily related with codegen.
mlir::MLIRContext & getMLIRContext()
mlir::Operation * getAddrOfGlobal(clang::GlobalDecl gd, ForDefinition_t isForDefinition=NotForDefinition)
void maybeSetTrivialComdat(const clang::Decl &d, mlir::Operation *op)
CIRGenCXXABI & getCXXABI() const
cir::GlobalViewAttr getAddrOfConstantStringFromLiteral(const StringLiteral *s, llvm::StringRef name=".str")
Return a global symbol reference to a constant array for the given string literal.
llvm::MapVector< cir::BlockAddressOp, cir::LabelOp > blockAddressToLabel
Map CIR BlockAddressOps directly to their resolved LabelOps.
bool lookupRepresentativeDecl(llvm::StringRef mangledName, clang::GlobalDecl &gd) const
void emitDeclContext(const DeclContext *dc)
clang::CharUnits getNaturalPointeeTypeAlignment(clang::QualType t, LValueBaseInfo *baseInfo=nullptr)
void emitGlobal(clang::GlobalDecl gd)
Emit code for a single global function or variable declaration.
cir::LabelOp lookupBlockAddressInfo(cir::BlockAddrInfoAttr blockInfo)
bool mayBeEmittedEagerly(const clang::ValueDecl *d)
Determine whether the definition can be emitted eagerly, or should be delayed until the end of the tr...
void mapBlockAddress(cir::BlockAddrInfoAttr blockInfo, cir::LabelOp label)
void addGlobalAnnotations(const clang::ValueDecl *d, mlir::Operation *gv)
Add global annotations for a global value (GlobalOp or FuncOp).
void setCIRFunctionAttributesForDefinition(const clang::FunctionDecl *fd, cir::FuncOp f)
Set extra attributes (inline, etc.) for a function.
std::string getOpenACCBindMangledName(const IdentifierInfo *bindName, const FunctionDecl *attachedFunction)
void emitGlobalFunctionDefinition(clang::GlobalDecl gd, mlir::Operation *op)
CIRGenVTables & getVTables()
void setFunctionLinkage(GlobalDecl gd, cir::FuncOp f)
std::vector< clang::GlobalDecl > deferredDeclsToEmit
void emitOMPThreadPrivateDecl(const OMPThreadPrivateDecl *d)
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.
cir::VisibilityAttr getGlobalVisibilityAttrFromDecl(const Decl *decl)
void setCommonAttributes(GlobalDecl gd, mlir::Operation *op)
Set attributes which are common to any form of a global definition (alias, Objective-C method,...
void emitDeclareTargetFunction(const FunctionDecl *fd, cir::FuncOp funcOp)
If the function has an OMPDeclareTargetDeclAttr, set the corresponding omp.declare_target attribute o...
const CIRGenFunctionInfo & arrangeGlobalDeclaration(GlobalDecl gd)
const CIRGenFunctionInfo & arrangeCXXMethodDeclaration(const clang::CXXMethodDecl *md)
C++ methods have some special rules and also have implicit parameters.
const CIRGenFunctionInfo & arrangeCXXStructorDeclaration(clang::GlobalDecl gd)
cir::FuncType getFunctionType(const CIRGenFunctionInfo &info)
Get the CIR function type for.
mlir::Type convertTypeForMem(clang::QualType, bool forBitField=false)
Convert type T into an mlir::Type.
void emitThunks(GlobalDecl gd)
Emit the associated thunks for the given global decl.
void finalize(cir::GlobalOp gv)
mlir::Attribute emitForInitializer(const APValue &value, QualType destType)
virtual clang::LangAS getGlobalVarAddressSpace(CIRGenModule &cgm, const clang::VarDecl *d) const
Get target favored AST address space of a global variable for languages other than OpenCL and CUDA.
virtual mlir::ptr::MemorySpaceAttrInterface getCIRAllocaAddressSpace() const
Get the address space for alloca.
virtual void setTargetAttributes(const clang::Decl *decl, mlir::Operation *global, CIRGenModule &module) const
Provides a convenient hook to handle extra target-specific attributes for the given global.
Represents a base class of a C++ class.
Represents a C++ constructor within a class.
bool isMoveConstructor(unsigned &TypeQuals) const
Determine whether this constructor is a move constructor (C++11 [class.copy]p3), which can be used to...
bool isCopyConstructor(unsigned &TypeQuals) const
Whether this constructor is a copy constructor (C++ [class.copy]p2, which can be used to copy the cla...
bool isDefaultConstructor() const
Whether this constructor is a default constructor (C++ [class.ctor]p5), which can be used to default-...
Represents a static or instance method of a struct/union/class.
bool isMoveAssignmentOperator() const
Determine whether this is a move assignment operator.
bool isCopyAssignmentOperator() const
Determine whether this is a copy-assignment operator, regardless of whether it was declared implicitl...
Represents a C++ struct/union/class.
bool isEffectivelyFinal() const
Determine whether it's impossible for a class to be derived from this class.
bool hasDefinition() const
CharUnits - This is an opaque type for sizes expressed in character units.
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static CharUnits One()
One - Construct a CharUnits quantity of one.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
CodeGenOptions - Track various options which control how the code is optimized and passed to the back...
llvm::Reloc::Model RelocationModel
The name of the relocation model to use.
Represents the canonical version of C arrays with a specified constant size.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Decl - This represents one declaration (or definition), e.g.
bool isWeakImported() const
Determine whether this is a weak-imported symbol.
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
static DeclContext * castToDeclContext(const Decl *)
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
SourceLocation getLocation() const
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Represents a ValueDecl that came out of a declarator.
A little helper class used to produce diagnostics.
Concrete class used by the front-end to report problems and issues.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
ExplicitCastExpr - An explicit cast written in the source code.
This represents one expression.
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
Represents a member of a struct/union/class.
Cached information about one file (either on disk or in the virtual file system).
StringRef tryGetRealPathName() const
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Represents a function declaration or definition.
static FunctionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin=false, bool isInlineSpecified=false, bool hasWrittenPrototype=true, ConstexprSpecKind ConstexprKind=ConstexprSpecKind::Unspecified, const AssociatedConstraint &TrailingRequiresClause={})
bool hasPrototype() const
Whether this function has a prototype, either because one was explicitly written or because it was "i...
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
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)
CXXDtorType getDtorType() const
const Decl * getDecl() const
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
clang::ObjCRuntime ObjCRuntime
void setLinkage(Linkage L)
Linkage getLinkage() const
MangleContext - Context for tracking state which persists across multiple calls to the C++ name mangl...
bool shouldMangleDeclName(const NamedDecl *D)
void mangleName(GlobalDecl GD, raw_ostream &)
virtual void mangleReferenceTemporary(const VarDecl *D, unsigned ManglingNumber, raw_ostream &)=0
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
StorageDuration getStorageDuration() const
Retrieve the storage duration for the materialized temporary.
APValue * getOrCreateValue(bool MayCreate) const
Get the storage for the constant value of a materialized temporary of static storage duration.
ValueDecl * getExtendingDecl()
Get the declaration which triggered the lifetime-extension of this temporary, if any.
unsigned getManglingNumber() const
A pointer to member type per C++ 8.3.3 - Pointers to members.
This represents a decl that may have a name.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
LinkageInfo getLinkageAndVisibility() const
Determines the linkage and visibility of this entity.
bool hasUnwindExceptions() const
Does this runtime use zero-cost exceptions?
Represents a parameter to a function.
void setScopeInfo(unsigned scopeDepth, unsigned parameterIndex)
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
Represents an unpacked "presumed" location which can be presented to the user.
unsigned getColumn() const
Return the presumed column number of this location.
const char * getFilename() const
Return the presumed filename of this location.
unsigned getLine() const
Return the presumed line number of this location.
A (possibly-)qualified type.
LangAS getAddressSpace() const
Return the address space of this type.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
bool isConstQualified() const
Determine whether this type is const-qualified.
bool isConstantStorage(const ASTContext &Ctx, bool ExcludeCtor, bool ExcludeDtor)
bool hasUnaligned() const
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
This class handles loading and caching of source files into memory.
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
Stmt - This represents one statement.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
StringLiteral - This represents a string literal expression, e.g.
unsigned getLength() const
uint32_t getCodeUnit(size_t i) const
StringRef getString() const
unsigned getCharByteWidth() const
Represents the declaration of a struct/union/class/enum.
bool isMicrosoft() const
Is this ABI an MSVC-compatible ABI?
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
A template parameter object.
const APValue & getValue() const
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool isPointerType() const
bool isReferenceType() const
bool isCUDADeviceBuiltinSurfaceType() const
Check if the type is the CUDA device builtin surface type.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
bool isCUDADeviceBuiltinTextureType() const
Check if the type is the CUDA device builtin texture type.
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
bool isObjCObjectPointerType() const
bool isMemberFunctionPointerType() const
const T * getAs() const
Member-template getAs<specific type>'.
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Expr * getSubExpr() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
TLSKind getTLSKind() const
DefinitionKind isThisDeclarationADefinition(ASTContext &) const
Check whether this declaration is a definition.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
bool hasFlexibleArrayInit(const ASTContext &Ctx) const
Whether this variable has a flexible array member initialized with one or more elements.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
bool hasConstantInitialization() const
Determine whether this variable has constant initialization.
VarDecl * getDefinition(ASTContext &)
Get the real (not just tentative) definition for this declaration.
QualType::DestructionKind needsDestruction(const ASTContext &Ctx) const
Would the destruction of this variable have any effect, and if so, what kind?
const Expr * getInit() const
bool hasExternalStorage() const
Returns true if a variable has extern or private_extern storage.
@ TLS_Dynamic
TLS with a dynamic initializer.
@ TLS_None
Not a TLS variable.
@ DeclarationOnly
This declaration is only a declaration.
@ Definition
This declaration is definitely a definition.
DefinitionKind hasDefinition(ASTContext &) const
Check whether this variable is defined in this translation unit.
TemplateSpecializationKind getTemplateSpecializationKind() const
If this variable is an instantiation of a variable template or a static data member of a class templa...
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
bool isMatchingAddressSpace(mlir::ptr::MemorySpaceAttrInterface cirAS, clang::LangAS as)
mlir::ptr::MemorySpaceAttrInterface toCIRAddressSpaceAttr(mlir::MLIRContext &ctx, clang::LangAS langAS)
Convert an AST LangAS to the appropriate CIR address space attribute interface.
static bool isWeakForLinker(GlobalLinkageKind linkage)
Whether the definition of this global may be replaced at link time.
@ AttributedType
The l-value was considered opaque, so the alignment was determined from a type, but that type was an ...
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
std::unique_ptr< TargetCIRGenInfo > createAMDGPUTargetCIRGenInfo(CIRGenTypes &cgt)
std::unique_ptr< TargetCIRGenInfo > createNVPTXTargetCIRGenInfo(CIRGenTypes &cgt)
CIRGenCXXABI * CreateCIRGenItaniumCXXABI(CIRGenModule &cgm)
Creates and Itanium-family ABI.
std::unique_ptr< TargetCIRGenInfo > createX8664TargetCIRGenInfo(CIRGenTypes &cgt)
CIRGenCUDARuntime * createNVCUDARuntime(CIRGenModule &cgm)
const internal::VariadicDynCastAllOfMatcher< Decl, VarDecl > varDecl
Matches variable declarations.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const internal::VariadicDynCastAllOfMatcher< Decl, FieldDecl > fieldDecl
Matches field declarations.
const internal::VariadicDynCastAllOfMatcher< Decl, FunctionDecl > functionDecl
Matches function declarations.
const internal::VariadicAllOfMatcher< Decl > decl
Matches declarations.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
GVALinkage
A more specific kind of linkage than enum Linkage.
@ GVA_AvailableExternally
@ SD_Thread
Thread storage duration.
@ SD_Static
Static storage duration.
bool isLambdaCallOperator(const CXXMethodDecl *MD)
@ Dtor_Complete
Complete object dtor.
LangAS
Defines the address space values used by the address space qualifier of QualType.
@ FirstTargetAddressSpace
TemplateSpecializationKind
Describes the kind of template specialization that a particular template specialization declaration r...
@ TSK_ExplicitInstantiationDefinition
This template specialization was instantiated from a template due to an explicit instantiation defini...
@ TSK_ImplicitInstantiation
This template specialization was implicitly instantiated from a template.
U cast(CodeGen::Address addr)
bool isExternallyVisible(Linkage L)
static bool globalCtorLexOrder()
static bool opFuncArmNewAttr()
static bool getRuntimeFunctionDecl()
static bool weakRefReference()
static bool opFuncOptNoneAttr()
static bool addressSpace()
static bool opFuncMinSizeAttr()
static bool opGlobalUnnamedAddr()
static bool opGlobalThreadLocal()
static bool sourceLanguageCases()
static bool opFuncAstDeclAttr()
static bool opFuncNoDuplicateAttr()
static bool stackProtector()
static bool moduleNameHash()
static bool opGlobalVisibility()
static bool setDLLStorageClass()
static bool opFuncUnwindTablesAttr()
static bool opFuncParameterAttributes()
static bool targetCIRGenInfoArch()
static bool opFuncExtraAttrs()
static bool opFuncNakedAttr()
static bool attributeNoBuiltin()
static bool opGlobalDLLImportExport()
static bool opGlobalPartition()
static bool opGlobalPragmaClangSection()
static bool opGlobalWeakRef()
static bool deferredCXXGlobalInit()
static bool opFuncOperandBundles()
static bool opFuncCallingConv()
static bool globalCtorAssociatedData()
static bool defaultVisibility()
static bool opFuncColdHotAttr()
static bool opFuncExceptions()
static bool opFuncArmStreamingAttr()
static bool cudaSupport()
static bool opFuncMaybeHandleStaticInExternC()
static bool generateDebugInfo()
static bool targetCIRGenInfoOS()
static bool opFuncCPUAndFeaturesAttributes()
static bool maybeHandleStaticInExternC()
static bool setLLVMFunctionFEnvAttributes()
mlir::Type uCharTy
ClangIR char.
unsigned char SizeSizeInBytes
unsigned char PointerAlignInBytes
cir::PointerType allocaInt8PtrTy
void* in alloca address space
cir::PointerType uInt8PtrTy
mlir::ptr::MemorySpaceAttrInterface cirAllocaAddressSpace
cir::PointerType voidPtrTy
void* in address space 0
EvalResult is a struct with detailed info about an evaluated expression.
APValue Val
Val - This is the value the expression can be folded to.
bool hasSideEffects() const
Return true if the evaluated expression has side effects.