105#include <type_traits>
110#define DEPOTNAME "__local_depot"
144 unsigned numSymbols()
const {
return Symbols.size(); }
146 bool allSymbolsAligned(
unsigned ptrSize)
const {
148 [=](
unsigned pos) {
return pos % ptrSize == 0; });
153 std::vector<unsigned char> buffer;
165 const NVPTXAsmPrinter &AP;
166 const bool EmitGeneric;
169 AggBuffer(
unsigned Size,
const NVPTXAsmPrinter &AP)
171 EmitGeneric(AP.EmitGeneric) {}
173 unsigned getBufferSize()
const {
return Size; }
176 unsigned getCurpos()
const {
return curpos; }
180 void addBytes(
const unsigned char *Ptr,
unsigned Num,
unsigned Bytes) {
184 addZeros(Bytes - Num);
189 buffer[curpos] = Byte;
193 void addZeros(
unsigned Num) {
194 for ([[maybe_unused]]
unsigned _ :
llvm::seq(Num)) {
201 Symbols.push_back(GVar);
202 SymbolsBeforeStripping.
push_back(GVarBeforeStripping);
212 friend class AggBuffer;
217 StringRef getPassName()
const override {
return "NVPTX Assembly Printer"; }
224 void emitStartOfAsmFile(
Module &M)
override;
226 void emitFunctionEntryLabel()
override;
227 void emitFunctionBodyStart()
override;
228 void emitFunctionBodyEnd()
override;
239 unsigned getVirtualRegisterNumber(
Register Reg)
const;
242 const char *Modifier =
nullptr);
245 void emitGlobals(
const Module &M);
254 void emitCallPrototype(
const CallBase &CB,
unsigned UniqueCallSite,
260 template <
typename T>
bool shouldEmitPTXNoReturn(
const T &V)
const {
261 static_assert(std::is_same_v<Function, T> || std::is_base_of_v<CallBase, T>,
262 "expected a function or a call site");
265 if (!NTM.getSubtargetImpl()->hasNoReturn())
268 if (!V.doesNotReturn() || !V.getFunctionType()->getReturnType()->isVoidTy())
271 if constexpr (std::is_same_v<Function, T>)
284 bool ProcessingGeneric)
const;
293 bool doInitialization(
Module &M)
override;
294 bool doFinalization(
Module &M)
override;
309 VRegRCMap VRegMapping;
312 std::map<const Function *, std::vector<const GlobalVariable *>> localDecls;
319 bool EmitInitializer);
321 std::string getPTXFundamentalTypeStr(
Type *Ty,
bool =
true)
const;
324 void bufferLEByte(
const Constant *CPV,
int Bytes, AggBuffer *aggBuffer);
325 void bufferAggregateConstant(
const Constant *CV, AggBuffer *aggBuffer);
326 void bufferAggregateConstVec(
const ConstantVector *CV, AggBuffer *aggBuffer);
348 const bool EmitGeneric;
351 NVPTXAsmPrinter(
TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
363 std::string getVirtualRegisterName(
Register Reg)
const;
365 const MCSymbol *getFunctionFrameSymbol()
const override;
376 assert(V.hasName() &&
"Found texture variable with no name");
381 assert(V.hasName() &&
"Found surface variable with no name");
386 assert(V.hasName() &&
"Found sampler variable with no name");
408 if (SP->getUnit()->isDebugDirectivesOnly() || SP->getUnit()->isNoDebug())
418discoverDependentGlobals(
const Value *V,
419 SmallVectorImpl<const GlobalVariable *> &Globals,
420 SmallPtrSetImpl<const GlobalVariable *> &Seen) {
422 if (Seen.
insert(GV).second)
435 discoverDependentGlobals(
GEP->getPointerOperand(), Globals, Seen);
440 for (
const auto &O :
U->operands())
441 discoverDependentGlobals(O, Globals, Seen);
444struct GlobalVariableDependencyNode {
445 const GlobalVariable *GV =
nullptr;
446 unsigned ModuleOrder = 0;
450class GlobalVariableDependencyGraph {
453 GlobalVariableDependencyNode SyntheticRoot;
456 std::map<const GlobalVariable *, GlobalVariableDependencyNode> Nodes;
459 explicit GlobalVariableDependencyGraph(
const Module &M) {
460 unsigned ModuleOrder = 0;
461 for (
const GlobalVariable &GV :
M.globals()) {
462 GlobalVariableDependencyNode &
Node = Nodes.try_emplace(&GV).first->second;
464 Node.ModuleOrder = ModuleOrder++;
465 SyntheticRoot.Dependencies.push_back(&Node);
468 for (
auto &[GV, Node] : Nodes) {
470 SmallPtrSet<const GlobalVariable *, 4> Seen;
471 for (
const Use &Operand : GV->operands())
472 discoverDependentGlobals(Operand, Dependencies, Seen);
474 for (
const GlobalVariable *Dependency : Dependencies) {
475 auto It = Nodes.find(Dependency);
476 if (It != Nodes.end())
477 Node.Dependencies.push_back(&It->second);
482 const GlobalVariableDependencyNode *getEntryNode()
const {
483 return &SyntheticRoot;
487struct GlobalVariableDependencyGraphTraits {
488 using NodeRef =
const GlobalVariableDependencyNode *;
489 using ChildIteratorType =
492 static NodeRef getEntryNode(NodeRef Node) {
return Node; }
493 static ChildIteratorType child_begin(NodeRef Node) {
494 return Node->Dependencies.begin();
496 static ChildIteratorType child_end(NodeRef Node) {
497 return Node->Dependencies.end();
501using GlobalVariableSCCIterator =
502 scc_iterator<
const GlobalVariableDependencyNode *,
503 GlobalVariableDependencyGraphTraits>;
505static bool shouldSkipModuleLevelGlobal(
const GlobalVariable &GV) {
511static bool isForwardDeclarableGlobal(
const GlobalVariable *GVar) {
512 if (shouldSkipModuleLevelGlobal(*GVar) || GVar->
isDeclaration() ||
533 const DenseSet<const GlobalVariableDependencyNode *> &ForwardDeclared) {
534 using Node = GlobalVariableDependencyNode;
536 DenseSet<const Node *> SCCSet;
539 DenseMap<const Node *, unsigned> DependencyCount;
540 DenseMap<const Node *, SmallVector<const Node *, 4>> Dependents;
541 std::set<std::pair<unsigned, const Node *>>
Ready;
545 for (
const Node *
N : SCC) {
546 unsigned &
Count = DependencyCount[
N];
547 for (
const Node *Dependency :
N->Dependencies) {
548 if (!SCCSet.
count(Dependency) || ForwardDeclared.
count(Dependency))
551 Dependents[Dependency].push_back(
N);
554 Ready.emplace(
N->ModuleOrder,
N);
558 while (!
Ready.empty()) {
563 auto It = Dependents.
find(
N);
564 if (It == Dependents.
end())
566 for (
const Node *Dependent : It->second) {
567 assert(DependencyCount[Dependent] &&
"Dependency already satisfied");
568 if (--DependencyCount[Dependent] == 0)
569 Ready.emplace(Dependent->ModuleOrder, Dependent);
573 if (Order.
size() !=
SCC.size())
581 NVPTX_MC::verifyInstructionPredicates(
MI->getOpcode(),
582 getSubtargetInfo().getFeatureBits());
585 lowerToMCInst(
MI, Inst);
586 EmitToStreamer(*OutStreamer, Inst);
589void NVPTXAsmPrinter::lowerToMCInst(
const MachineInstr *
MI, MCInst &OutMI) {
591 for (
const auto MO :
MI->operands())
595MCOperand NVPTXAsmPrinter::lowerOperand(
const MachineOperand &MO) {
625 case Type::BFloatTyID:
628 case Type::FloatTyID:
631 case Type::DoubleTyID:
640static NVPTX::VirtualRegisterKind
642 if (RC == &NVPTX::B1RegClass)
644 if (RC == &NVPTX::B16RegClass)
646 if (RC == &NVPTX::B32RegClass)
648 if (RC == &NVPTX::B64RegClass)
650 if (RC == &NVPTX::B128RegClass)
655unsigned NVPTXAsmPrinter::getVirtualRegisterNumber(
Register Reg)
const {
657 assert(It != VRegMapping.
end() &&
"Bad register class");
659 const unsigned Num = It->second.lookup(
Reg);
660 assert(Num &&
"Bad virtual register");
664MCRegister NVPTXAsmPrinter::encodeVirtualRegister(
Register Reg) {
669 const unsigned Num = getVirtualRegisterNumber(
Reg);
670 assert(Num <= NVPTX::VirtualRegisterNumMask &&
671 "Too many virtual registers");
672 return (
static_cast<unsigned>(Kind) << NVPTX::VirtualRegisterKindShift) |
678 assert(
Reg.
id() <= NVPTX::VirtualRegisterNumMask &&
679 "Physical register would decode as a virtual register");
683MCOperand NVPTXAsmPrinter::GetSymbolRef(
const MCSymbol *Symbol) {
689void NVPTXAsmPrinter::printReturnValStr(
const Function *
F, raw_ostream &O) {
690 const DataLayout &
DL = getDataLayout();
691 const NVPTXSubtarget &STI = TM.getSubtarget<NVPTXSubtarget>(*F);
694 Type *Ty =
F->getReturnType();
701 auto PrintScalarRetVal = [&](
unsigned Size) {
705 const unsigned TotalSize =
DL.getTypeAllocSize(Ty);
706 const Align RetAlignment =
708 O <<
".param .align " << RetAlignment.
value() <<
" .b8 func_retval0["
713 PrintScalarRetVal(ITy->getBitWidth());
715 PrintScalarRetVal(TLI->getPointerTy(
DL).getSizeInBits());
721void NVPTXAsmPrinter::printReturnValStr(
const MachineFunction &MF,
724 printReturnValStr(&
F, O);
727void NVPTXAsmPrinter::emitCallPrototype(
const CallBase &CB,
728 unsigned UniqueCallSite,
729 raw_ostream &O)
const {
730 const DataLayout &
DL = getDataLayout();
731 const NVPTXSubtarget &STI = MF->
getSubtarget<NVPTXSubtarget>();
733 const auto PtrVT = TLI->getPointerTy(
DL);
736 O <<
"prototype_" << UniqueCallSite <<
" : .callprototype ";
743 const Align RetAlign =
745 O <<
".param .align " << RetAlign.
value() <<
" .b8 _["
746 <<
DL.getTypeAllocSize(RetTy) <<
"]";
750 size = ITy->getBitWidth();
753 "Floating point type expected here");
761 O <<
".param .b" <<
size <<
" _";
763 O <<
".param .b" << PtrVT.getSizeInBits() <<
" _";
771 auto MakeArg = [&](
const unsigned I) {
777 &CB, ETy,
I + AttributeList::FirstArgIndex,
DL);
779 O <<
".param .align " << ParamByValAlign.
value() <<
" .b8 _["
780 <<
DL.getTypeAllocSize(ETy) <<
"]";
787 O <<
".param .align " << ParamAlign.
value() <<
" .b8 _["
788 <<
DL.getTypeAllocSize(Ty) <<
"]";
796 sz = PtrVT.getSizeInBits();
800 O <<
".param .b" << sz <<
" _";
804 const unsigned NumArgs = FTy->getNumParams();
814 if (FTy->isVarArg() && CB.
arg_size() > NumArgs)
815 O << (NonEmptyArgs.empty() ?
"" :
",") <<
" .param .align "
819 if (shouldEmitPTXNoReturn(CB))
824void NVPTXAsmPrinter::emitJumpTable(
const MachineJumpTableEntry &MJT,
825 unsigned MJTI)
const {
826 OutStreamer->emitLabel(GetJTISymbol(MJTI));
828 if (MJT.
MBBs.empty())
833 return MBB->getSymbol();
835 getTargetStreamer()->emitBranchTargetsDirective(Targets);
840bool NVPTXAsmPrinter::isLoopHeaderOfNoUnroll(
841 const MachineBasicBlock &
MBB)
const {
842 MachineLoopInfo &LI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
855 if (
const BasicBlock *PBB = PMBB->getBasicBlock()) {
857 PBB->getTerminator()->getMetadata(LLVMContext::MD_loop)) {
860 if (MDNode *UnrollCountMD =
872void NVPTXAsmPrinter::emitBasicBlockStart(
const MachineBasicBlock &
MBB) {
874 if (isLoopHeaderOfNoUnroll(
MBB))
875 getTargetStreamer()->emitPragmaDirective(
"nounroll");
878void NVPTXAsmPrinter::emitFunctionEntryLabel() {
879 SmallString<128> Str;
880 raw_svector_ostream
O(Str);
882 if (!GlobalsEmitted) {
884 GlobalsEmitted =
true;
890 emitLinkageDirective(
F, O);
895 printReturnValStr(*MF, O);
898 CurrentFnSym->print(O, MAI);
900 emitFunctionParamList(
F, O);
904 emitKernelFunctionDirectives(*
F, O);
906 if (shouldEmitPTXNoReturn(*
F))
909 OutStreamer->emitRawText(
O.str());
913 OutStreamer->emitRawText(StringRef(
"{\n"));
914 setAndEmitFunctionVirtualRegisters(*MF);
915 encodeDebugInfoRegisterNumbers(*MF);
920bool NVPTXAsmPrinter::runOnMachineFunction(MachineFunction &
F) {
927 OutStreamer->emitRawText(StringRef(
"}\n"));
931void NVPTXAsmPrinter::emitFunctionBodyStart() {
932 SmallString<128> Str;
933 raw_svector_ostream
O(Str);
936 const auto *MFI = MF->
getInfo<NVPTXMachineFunctionInfo>();
937 for (
const auto &[Id, CB] : MFI->getCallPrototypes())
938 emitCallPrototype(*CB, Id, O);
940 OutStreamer->emitRawText(
O.str());
943 for (
const auto &[Idx, JT] :
enumerate(MJTI->getJumpTables()))
944 emitJumpTable(JT, Idx);
947void NVPTXAsmPrinter::emitFunctionBodyEnd() {
951const MCSymbol *NVPTXAsmPrinter::getFunctionFrameSymbol()
const {
952 return OutContext.getOrCreateSymbol(
DEPOTNAME + Twine(getFunctionNumber()));
955void NVPTXAsmPrinter::emitImplicitDef(
const MachineInstr *
MI)
const {
958 OutStreamer->AddComment(Twine(
"implicit-def: ") +
959 getVirtualRegisterName(RegNo));
961 OutStreamer->AddComment(Twine(
"implicit-def: ") +
963 OutStreamer->addBlankLine();
966void NVPTXAsmPrinter::emitKernelFunctionDirectives(
const Function &
F,
967 raw_ostream &O)
const {
973 O <<
formatv(
".reqntid {0:$[, ]}\n",
978 O <<
formatv(
".maxntid {0:$[, ]}\n",
982 O <<
".minnctapersm " << *Mincta <<
"\n";
985 O <<
".maxnreg " << *Maxnreg <<
"\n";
989 const NVPTXTargetMachine &NTM =
static_cast<const NVPTXTargetMachine &
>(TM);
990 const NVPTXSubtarget *STI = &NTM.
getSubtarget<NVPTXSubtarget>(
F);
998 if (!BlocksAreClusters)
999 O <<
".explicitcluster\n";
1001 if (ClusterDim[0] != 0) {
1003 "cluster_dim_x != 0 implies cluster_dim_y and cluster_dim_z "
1004 "should be non-zero as well");
1006 O <<
formatv(
".reqnctapercluster {0:$[, ]}\n",
1010 "cluster_dim_x == 0 implies cluster_dim_y and cluster_dim_z "
1011 "should be 0 as well");
1015 if (BlocksAreClusters) {
1016 LLVMContext &Ctx =
F.getContext();
1018 Ctx.
diagnose(DiagnosticInfoUnsupported(
1019 F,
"blocksareclusters requires reqntid and cluster_dim attributes",
1020 F.getSubprogram()));
1022 Ctx.
diagnose(DiagnosticInfoUnsupported(
1023 F,
"blocksareclusters requires PTX version >= 9.0",
1024 F.getSubprogram()));
1026 O <<
".blocksareclusters\n";
1030 O <<
".maxclusterrank " << *Maxclusterrank <<
"\n";
1034std::string NVPTXAsmPrinter::getVirtualRegisterName(
Register Reg)
const {
1038 raw_string_ostream(Name) << NVPTX::getVirtualRegisterPrefix(Kind)
1039 << getVirtualRegisterNumber(
Reg);
1043void NVPTXAsmPrinter::emitAliasDeclaration(
const GlobalAlias *GA,
1048 "NVPTX aliasee must be a non-kernel function definition");
1054 emitDeclarationWithName(
F, getSymbol(GA), O);
1057void NVPTXAsmPrinter::emitDeclaration(
const Function *
F, raw_ostream &O) {
1058 emitDeclarationWithName(
F, getSymbol(
F), O);
1061void NVPTXAsmPrinter::emitDeclarationWithName(
const Function *
F, MCSymbol *S,
1063 emitLinkageDirective(
F, O);
1068 printReturnValStr(
F, O);
1071 emitFunctionParamList(
F, O);
1073 if (shouldEmitPTXNoReturn(*
F))
1083 return GV->
getName() !=
"llvm.used";
1085 for (
const User *U :
C->users())
1095 if (OtherGV->getName() ==
"llvm.used")
1099 if (
const Function *CurFunc =
I->getFunction()) {
1100 if (OneFunc && (CurFunc != OneFunc))
1141 for (
const User *U :
C->users()) {
1146 if (
const Function *Caller =
I->getFunction())
1154void NVPTXAsmPrinter::emitDeclarations(
const Module &M, raw_ostream &O) {
1155 SmallPtrSet<const Function *, 32> SeenSet;
1156 for (
const Function &
F : M) {
1157 if (
F.getAttributes().hasFnAttr(
"nvptx-libcall-callee")) {
1158 emitDeclaration(&
F, O);
1162 if (
F.isDeclaration()) {
1165 if (
F.getIntrinsicID())
1169 if (
F.isIntrinsic()) {
1170 LLVMContext &Ctx =
F.getContext();
1171 Ctx.
diagnose(DiagnosticInfoUnsupported(
1172 F,
"unknown intrinsic '" +
F.getName() +
1173 "' cannot be lowered by the NVPTX backend"));
1176 emitDeclaration(&
F, O);
1179 for (
const User *U :
F.users()) {
1185 emitDeclaration(&
F, O);
1191 emitDeclaration(&
F, O);
1206 emitDeclaration(&
F, O);
1212 for (
const GlobalAlias &GA :
M.aliases())
1213 emitAliasDeclaration(&GA, O);
1216void NVPTXAsmPrinter::emitStartOfAsmFile(
Module &M) {
1220 const NVPTXTargetMachine &NTM =
static_cast<const NVPTXTargetMachine &
>(TM);
1224 emitHeader(M, *STI);
1228DwarfDebug *NVPTXAsmPrinter::createDwarfDebug() {
1229 return new NVPTXDwarfDebug(
this);
1232bool NVPTXAsmPrinter::doInitialization(
Module &M) {
1233 const NVPTXTargetMachine &NTM =
static_cast<const NVPTXTargetMachine &
>(TM);
1241 GlobalsEmitted =
false;
1246void NVPTXAsmPrinter::emitGlobals(
const Module &M) {
1247 SmallString<128> Str2;
1248 raw_svector_ostream OS2(Str2);
1250 emitDeclarations(M, OS2);
1252 const NVPTXTargetMachine &NTM =
static_cast<const NVPTXTargetMachine &
>(TM);
1260 GlobalVariableDependencyGraph DependencyGraph(M);
1261 for (GlobalVariableSCCIterator
I =
1262 GlobalVariableSCCIterator::begin(DependencyGraph.getEntryNode());
1263 !
I.isAtEnd(); ++
I) {
1268 if (!
SCC.front()->GV) {
1269 assert(
SCC.size() == 1 &&
"Synthetic root must be in its own SCC");
1274 return LHS->ModuleOrder <
RHS->ModuleOrder;
1277 const bool IsCyclic =
I.hasCycle();
1278 DenseSet<const GlobalVariableDependencyNode *> ForwardDeclared;
1280 for (
const auto *Node : SCC)
1281 if (isForwardDeclarableGlobal(
Node->GV))
1282 ForwardDeclared.
insert(Node);
1286 IsCyclic ? orderDefinitionsInSCC(SCC, ForwardDeclared)
1289 for (
const auto *Node : SCC) {
1290 if (!ForwardDeclared.
count(Node))
1293 emitPTXGlobalVariableDefinition(
Node->GV, OS2, STI,
1298 for (
const GlobalVariable *GV : OrderedGlobals)
1299 printModuleLevelGV(GV, OS2,
false, STI);
1304 OutStreamer->emitRawText(OS2.str());
1307void NVPTXAsmPrinter::emitGlobalAlias(
const Module &M,
const GlobalAlias &GA) {
1308 getTargetStreamer()->emitAliasDirective(getSymbol(&GA),
1312NVPTXTargetStreamer *NVPTXAsmPrinter::getTargetStreamer()
const {
1313 return static_cast<NVPTXTargetStreamer *
>(OutStreamer->getTargetStreamer());
1318 switch(
CU->getEmissionKind()) {
1331void NVPTXAsmPrinter::emitHeader(
Module &M,
const NVPTXSubtarget &STI) {
1332 auto *TS = getTargetStreamer();
1337 TS->emitVersionDirective(PTXVersion);
1339 const NVPTXTargetMachine &NTM =
static_cast<const NVPTXTargetMachine &
>(TM);
1342 TS->emitTargetDirective(STI.
getTargetName(), TexModeIndependent,
1344 TS->emitAddressSizeDirective(
M.getDataLayout().getPointerSizeInBits());
1347bool NVPTXAsmPrinter::doFinalization(
Module &M) {
1350 if (!GlobalsEmitted) {
1352 GlobalsEmitted =
true;
1361 static_cast<NVPTXTargetStreamer *
>(OutStreamer->getTargetStreamer());
1364 TS->closeLastSection();
1366 TS->emitEmptySectionDirective(
".debug_macinfo");
1370 TS->outputDwarfFileDirectives();
1388void NVPTXAsmPrinter::emitLinkageDirective(
const GlobalValue *V,
1390 if (
static_cast<NVPTXTargetMachine &
>(TM).getDrvInterface() == NVPTX::CUDA) {
1391 if (
V->hasExternalLinkage()) {
1394 else if (
V->isDeclaration())
1398 }
else if (
V->hasAppendingLinkage()) {
1400 "' has unsupported appending linkage type");
1401 }
else if (!
V->hasInternalLinkage() && !
V->hasPrivateLinkage()) {
1407void NVPTXAsmPrinter::printModuleLevelGV(
const GlobalVariable *GVar,
1408 raw_ostream &O,
bool ProcessDemoted,
1409 const NVPTXSubtarget &STI) {
1411 if (shouldSkipModuleLevelGlobal(*GVar))
1430 if (OpaqueType == PTXOpaqueType::Texture) {
1435 if (OpaqueType == PTXOpaqueType::Surface) {
1444 emitPTXGlobalVariable(GVar, O, STI);
1449 if (OpaqueType == PTXOpaqueType::Sampler) {
1452 const Constant *Initializer =
nullptr;
1455 const ConstantInt *CI =
nullptr;
1466 O <<
"addr_mode_" << i <<
" = ";
1472 O <<
"clamp_to_border";
1475 O <<
"clamp_to_edge";
1486 O <<
"filter_mode = ";
1501 O <<
", force_unnormalized_coords = 1";
1521 const Function *DemotedFunc =
nullptr;
1523 O <<
"// " << GVar->
getName() <<
" has been demoted\n";
1524 localDecls[DemotedFunc].push_back(GVar);
1528 emitPTXGlobalVariableDefinition(GVar, O, STI,
true);
1532void NVPTXAsmPrinter::emitPTXGlobalVariableDefinition(
1533 const GlobalVariable *GVar, raw_ostream &O,
const NVPTXSubtarget &STI,
1534 bool EmitInitializer) {
1535 const DataLayout &
DL = getDataLayout();
1545 ".attribute(.managed) requires PTX version >= 4.0 and sm_30");
1546 O <<
" .attribute(.managed)";
1550 << GVar->
getAlign().value_or(
DL.getPrefTypeAlign(ETy)).value();
1559 O << getPTXFundamentalTypeStr(ETy,
false);
1561 getSymbol(GVar)->print(O, MAI);
1572 printScalarConstant(Initializer, O);
1581 "' is not allowed in addrspace(" +
1592 case Type::IntegerTyID:
1593 case Type::FP128TyID:
1594 case Type::StructTyID:
1595 case Type::ArrayTyID:
1596 case Type::FixedVectorTyID: {
1597 const uint64_t ElementSize =
DL.getTypeStoreSize(ETy);
1605 AggBuffer aggBuffer(ElementSize, *
this);
1606 bufferAggregateConstant(Initializer, &aggBuffer);
1607 if (aggBuffer.numSymbols()) {
1608 const unsigned int ptrSize = MAI.getCodePointerSize();
1609 if (ElementSize % ptrSize ||
1610 !aggBuffer.allSymbolsAligned(ptrSize)) {
1614 "initialized packed aggregate with pointers '" +
1616 "' requires at least PTX ISA version 7.1");
1618 getSymbol(GVar)->print(O, MAI);
1619 O <<
"[" << ElementSize <<
"]";
1620 if (EmitInitializer) {
1622 aggBuffer.printBytes(O);
1626 O <<
" .u" << ptrSize * 8 <<
" ";
1627 getSymbol(GVar)->print(O, MAI);
1628 O <<
"[" << ElementSize / ptrSize <<
"]";
1629 if (EmitInitializer) {
1631 aggBuffer.printWords(O);
1637 getSymbol(GVar)->print(O, MAI);
1638 O <<
"[" << ElementSize <<
"]";
1639 if (EmitInitializer) {
1641 aggBuffer.printBytes(O);
1647 getSymbol(GVar)->print(O, MAI);
1649 O <<
"[" << ElementSize <<
"]";
1653 getSymbol(GVar)->print(O, MAI);
1655 O <<
"[" << ElementSize <<
"]";
1665void NVPTXAsmPrinter::AggBuffer::printSymbol(
unsigned nSym, raw_ostream &os) {
1666 const Value *
v = Symbols[nSym];
1667 const Value *v0 = SymbolsBeforeStripping[nSym];
1672 bool isGenericPointer = PTy && PTy->getAddressSpace() == 0;
1675 Name->print(os, AP.MAI);
1678 Name->print(os, AP.MAI);
1681 const MCExpr *Expr = AP.lowerConstantForGV(CExpr,
false);
1682 AP.printMCExpr(*Expr, os);
1687void NVPTXAsmPrinter::AggBuffer::printBytes(raw_ostream &os) {
1688 unsigned int ptrSize = AP.MAI.getCodePointerSize();
1693 unsigned int InitializerCount =
Size;
1696 if (numSymbols() == 0)
1697 while (InitializerCount >= 1 && !buffer[InitializerCount - 1])
1700 symbolPosInBuffer.push_back(InitializerCount);
1701 unsigned int nSym = 0;
1702 unsigned int nextSymbolPos = symbolPosInBuffer[nSym];
1703 for (
unsigned int pos = 0; pos < InitializerCount;) {
1706 if (pos != nextSymbolPos) {
1707 os << (
unsigned int)buffer[pos];
1714 std::string symText;
1715 llvm::raw_string_ostream oss(symText);
1716 printSymbol(nSym, oss);
1717 for (
unsigned i = 0; i < ptrSize; ++i) {
1721 os <<
"(" << symText <<
")";
1724 nextSymbolPos = symbolPosInBuffer[++nSym];
1725 assert(nextSymbolPos >= pos);
1729void NVPTXAsmPrinter::AggBuffer::printWords(raw_ostream &os) {
1730 unsigned int ptrSize = AP.MAI.getCodePointerSize();
1731 symbolPosInBuffer.push_back(
Size);
1732 unsigned int nSym = 0;
1733 unsigned int nextSymbolPos = symbolPosInBuffer[nSym];
1734 assert(nextSymbolPos % ptrSize == 0);
1735 for (
unsigned int pos = 0; pos <
Size; pos += ptrSize) {
1738 if (pos == nextSymbolPos) {
1739 printSymbol(nSym, os);
1740 nextSymbolPos = symbolPosInBuffer[++nSym];
1741 assert(nextSymbolPos % ptrSize == 0);
1742 assert(nextSymbolPos >= pos + ptrSize);
1743 }
else if (ptrSize == 4)
1750void NVPTXAsmPrinter::emitDemotedVars(
const Function *
F, raw_ostream &O) {
1751 auto It = localDecls.find(
F);
1752 if (It == localDecls.end())
1757 const NVPTXTargetMachine &NTM =
static_cast<const NVPTXTargetMachine &
>(TM);
1760 for (
const GlobalVariable *GV : GVars) {
1761 O <<
"\t// demoted variable\n\t";
1762 printModuleLevelGV(GV, O,
true, STI);
1766void NVPTXAsmPrinter::emitPTXAddressSpace(
unsigned int AddressSpace,
1767 raw_ostream &O)
const {
1789NVPTXAsmPrinter::getPTXFundamentalTypeStr(
Type *Ty,
bool useB4PTR)
const {
1791 case Type::IntegerTyID: {
1795 if (NumBits <= 64) {
1796 std::string
name =
"u";
1802 case Type::BFloatTyID:
1803 case Type::HalfTyID:
1807 case Type::FloatTyID:
1809 case Type::DoubleTyID:
1811 case Type::PointerTyID: {
1813 assert((PtrSize == 64 || PtrSize == 32) &&
"Unexpected pointer size");
1831void NVPTXAsmPrinter::emitPTXGlobalVariable(
const GlobalVariable *GVar,
1833 const NVPTXSubtarget &STI) {
1834 const DataLayout &
DL = getDataLayout();
1844 ".attribute(.managed) requires PTX version >= 4.0 and sm_30");
1846 O <<
" .attribute(.managed)";
1849 << GVar->
getAlign().value_or(
DL.getPrefTypeAlign(ETy)).value();
1854 getSymbol(GVar)->print(O, MAI);
1860 O <<
" ." << getPTXFundamentalTypeStr(ETy) <<
" ";
1861 getSymbol(GVar)->print(O, MAI);
1865 int64_t ElementSize = 0;
1872 case Type::StructTyID:
1873 case Type::ArrayTyID:
1874 case Type::FixedVectorTyID:
1875 ElementSize =
DL.getTypeStoreSize(ETy);
1877 getSymbol(GVar)->print(O, MAI);
1889void NVPTXAsmPrinter::emitFunctionParamList(
const Function *
F, raw_ostream &O) {
1890 const DataLayout &
DL = getDataLayout();
1891 const NVPTXSubtarget &STI = TM.getSubtarget<NVPTXSubtarget>(*F);
1893 const NVPTXMachineFunctionInfo *MFI =
1894 MF ? MF->
getInfo<NVPTXMachineFunctionInfo>() : nullptr;
1896 bool IsFirst =
true;
1903 const auto NonEmptyArgs =
1905 return !Arg.getType()->isEmptyTy();
1908 if (NonEmptyArgs.empty() && !
F->isVarArg()) {
1915 for (
const auto &[ParamIndex, Arg] :
enumerate(NonEmptyArgs)) {
1916 Type *Ty = Arg.getType();
1917 const std::string ParamSym = TLI->getParamName(
F, ParamIndex);
1927 if (ArgOpaqueType != PTXOpaqueType::None) {
1933 switch (ArgOpaqueType) {
1934 case PTXOpaqueType::Sampler:
1935 O <<
".samplerref ";
1937 case PTXOpaqueType::Texture:
1940 case PTXOpaqueType::Surface:
1943 case PTXOpaqueType::None:
1951 if (Arg.hasByValAttr()) {
1953 Type *ETy = Arg.getParamByValType();
1954 assert(ETy &&
"Param should have byval type");
1960 const unsigned ParamIdx = Arg.getArgNo() + AttributeList::FirstArgIndex;
1961 const Align OptimalAlign =
1965 O <<
"\t.param .align " << OptimalAlign.
value() <<
" .b8 " << ParamSym
1966 <<
"[" <<
DL.getTypeAllocSize(ETy) <<
"]";
1976 F, Ty, Arg.getArgNo() + AttributeList::FirstArgIndex,
DL);
1978 O <<
"\t.param .align " << OptimalAlign.
value() <<
" .b8 " << ParamSym
1979 <<
"[" <<
DL.getTypeAllocSize(Ty) <<
"]";
1985 unsigned PTySizeInBits = 0;
1988 TLI->getPointerTy(
DL, PTy->getAddressSpace()).getSizeInBits();
1989 assert(PTySizeInBits &&
"Invalid pointer size");
1994 O <<
"\t.param .u" << PTySizeInBits <<
" .ptr";
1996 switch (PTy->getAddressSpace()) {
2013 O <<
" .align " << Arg.getParamAlign().valueOrOne().value() <<
" "
2024 O << getPTXFundamentalTypeStr(Ty);
2025 O <<
" " << ParamSym;
2034 assert(PTySizeInBits &&
"Invalid pointer size");
2035 Size = PTySizeInBits;
2038 O <<
"\t.param .b" <<
Size <<
" " << ParamSym;
2041 if (
F->isVarArg()) {
2045 << TLI->getParamName(
F, -1) <<
"[]";
2051void NVPTXAsmPrinter::setAndEmitFunctionVirtualRegisters(
2052 const MachineFunction &MF) {
2053 auto *TS = getTargetStreamer();
2058 TS->emitLocalDirective(MFI.
getMaxAlign(), getFunctionFrameSymbol(),
2062 const NVPTXRegisterInfo *NRI =
2066 TS->emitRegDirective(
2067 NRI->getRegSizeInBits(FrameReg, *MRI).getFixedValue(),
2076 Register VR = Register::index2VirtReg(
I);
2079 auto &RCRegMap = VRegMapping[MRI->
getRegClass(VR)];
2080 RCRegMap[VR] = RCRegMap.
size() + 1;
2088 const auto It = VRegMapping.
find(&RC);
2089 if (It == VRegMapping.
end() || It->second.empty())
2092 TS->emitRegDirective(
2093 TRI->getRegSizeInBits(RC).getFixedValue(),
2095 It->second.size() + 1);
2101void NVPTXAsmPrinter::encodeDebugInfoRegisterNumbers(
2102 const MachineFunction &MF) {
2103 const NVPTXSubtarget &STI = MF.
getSubtarget<NVPTXSubtarget>();
2113 NRI->addToDebugRegisterMap(
Reg, getVirtualRegisterName(
Reg));
2116void NVPTXAsmPrinter::printFPConstant(
const ConstantFP *Fp,
2117 raw_ostream &O)
const {
2120 unsigned int numHex;
2126 APF.
convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven, &ignored);
2130 APF.
convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven, &ignored);
2138void NVPTXAsmPrinter::printScalarConstant(
const Constant *CPV, raw_ostream &O) {
2144 printFPConstant(CFP, O);
2153 if (EmitGeneric && !
isa<Function>(CPV) && !IsNonGenericPointer) {
2155 getSymbol(GVar)->print(O, MAI);
2158 getSymbol(GVar)->print(O, MAI);
2170void NVPTXAsmPrinter::bufferLEByte(
const Constant *CPV,
int Bytes,
2171 AggBuffer *AggBuffer) {
2172 const DataLayout &
DL = getDataLayout();
2173 int AllocSize =
DL.getTypeAllocSize(CPV->
getType());
2177 AggBuffer->addZeros(Bytes ? Bytes : AllocSize);
2182 auto AddIntToBuffer = [AggBuffer, Bytes](
const APInt &Val) {
2183 size_t NumBytes = (Val.getBitWidth() + 7) / 8;
2189 for (
unsigned I = 0;
I < NumBytes - 1; ++
I) {
2190 Buf[
I] = Val.extractBitsAsZExtValue(8,
I * 8);
2192 size_t LastBytePosition = (NumBytes - 1) * 8;
2193 size_t LastByteBits = Val.getBitWidth() - LastBytePosition;
2195 Val.extractBitsAsZExtValue(LastByteBits, LastBytePosition);
2196 AggBuffer->addBytes(Buf.data(), NumBytes, Bytes);
2200 case Type::IntegerTyID:
2206 if (
const auto *CI =
2211 if (Cexpr->getOpcode() == Instruction::PtrToInt) {
2212 Value *
V = Cexpr->getOperand(0)->stripPointerCasts();
2213 AggBuffer->addSymbol(V, Cexpr->getOperand(0));
2214 AggBuffer->addZeros(AllocSize);
2221 AggBuffer->addSymbol(Cexpr, Cexpr);
2222 AggBuffer->addZeros(AllocSize);
2228 case Type::HalfTyID:
2229 case Type::BFloatTyID:
2230 case Type::FloatTyID:
2231 case Type::DoubleTyID:
2235 case Type::PointerTyID: {
2237 AggBuffer->addSymbol(GVar, GVar);
2239 const Value *
v = Cexpr->stripPointerCasts();
2240 AggBuffer->addSymbol(v, Cexpr);
2242 AggBuffer->addZeros(AllocSize);
2246 case Type::ArrayTyID:
2247 case Type::FixedVectorTyID:
2248 case Type::StructTyID: {
2252 unsigned StartPos = AggBuffer->getCurpos();
2253 bufferAggregateConstant(CPV, AggBuffer);
2254 unsigned Written = AggBuffer->getCurpos() - StartPos;
2255 unsigned SlotSize = std::max<int>(Bytes, AllocSize);
2256 if (SlotSize > Written)
2257 AggBuffer->addZeros(SlotSize - Written);
2259 AggBuffer->addZeros(Bytes);
2270void NVPTXAsmPrinter::bufferAggregateConstant(
const Constant *CPV,
2271 AggBuffer *aggBuffer) {
2272 const DataLayout &
DL = getDataLayout();
2274 auto ExtendBuffer = [](APInt Val, AggBuffer *Buffer) {
2277 unsigned NumBits = std::min(8u, Val.
getBitWidth() -
I * 8);
2285 for (
unsigned I :
llvm::seq(VTy->getNumElements()))
2294 ExtendBuffer(CI->
getValue(), aggBuffer);
2300 assert(CFP->getType()->isFloatingPointTy() &&
"Expected fp constant!");
2301 if (CFP->getType()->isFP128Ty()) {
2302 ExtendBuffer(CFP->getValueAPF().bitcastToAPInt(), aggBuffer);
2316 bufferAggregateConstVec(CVec, aggBuffer);
2321 for (
unsigned I :
llvm::seq(CDS->getNumElements()))
2322 bufferLEByte(
cast<Constant>(CDS->getElementAsConstant(
I)), 0, aggBuffer);
2331 ?
DL.getStructLayout(ST)->getElementOffset(0) +
2332 DL.getTypeAllocSize(ST)
2333 :
DL.getStructLayout(ST)->getElementOffset(
I + 1);
2334 int Bytes = EndOffset -
DL.getStructLayout(ST)->getElementOffset(
I);
2343void NVPTXAsmPrinter::bufferAggregateConstVec(
const ConstantVector *CV,
2344 AggBuffer *aggBuffer) {
2346 const unsigned BuffSize = aggBuffer->getBufferSize();
2349 if (BuffSize >= NumElems) {
2362 assert(ElemTySize < 8 &&
"Expected sub-byte data type.");
2363 assert(8 % ElemTySize == 0 &&
"Element type size must evenly divide a byte.");
2365 unsigned NumElemsPerByte = 8 / ElemTySize;
2366 unsigned NumCompleteBytes = NumElems / NumElemsPerByte;
2367 unsigned NumTailElems = NumElems % NumElemsPerByte;
2372 auto ConvertSubCVtoInt8 = [
this, &ElemTy](
const ConstantVector *CV,
2373 unsigned Start,
unsigned End,
2374 unsigned NumPaddingZeros = 0) {
2381 if (NumPaddingZeros)
2382 SubCVElems.
append(NumPaddingZeros, ConstantInt::getNullValue(ElemTy));
2388 ConstantInt *MergedElem =
2395 "Cannot lower vector global with unusual element type");
2402 for (
unsigned ByteIdx :
llvm::seq(NumCompleteBytes))
2403 bufferLEByte(ConvertSubCVtoInt8(CV, ByteIdx * NumElemsPerByte,
2404 (ByteIdx + 1) * NumElemsPerByte),
2408 if (NumTailElems > 0)
2409 bufferLEByte(ConvertSubCVtoInt8(CV, NumElems - NumTailElems, NumElems,
2410 NumElemsPerByte - NumTailElems),
2419NVPTXAsmPrinter::lowerConstantForGV(
const Constant *CV,
2420 bool ProcessingGeneric)
const {
2421 MCContext &Ctx = OutContext;
2431 if (ProcessingGeneric)
2441 switch (
CE->getOpcode()) {
2445 case Instruction::AddrSpaceCast: {
2448 if (DstTy->getAddressSpace() == 0)
2454 case Instruction::GetElementPtr: {
2455 const DataLayout &
DL = getDataLayout();
2458 APInt OffsetAI(
DL.getPointerTypeSizeInBits(
CE->getType()), 0);
2461 const MCExpr *
Base = lowerConstantForGV(
CE->getOperand(0),
2466 int64_t
Offset = OffsetAI.getSExtValue();
2471 case Instruction::Trunc:
2477 case Instruction::BitCast:
2478 return lowerConstantForGV(
CE->getOperand(0), ProcessingGeneric);
2480 case Instruction::IntToPtr: {
2481 const DataLayout &
DL = getDataLayout();
2489 return lowerConstantForGV(
Op, ProcessingGeneric);
2494 case Instruction::PtrToInt: {
2495 const DataLayout &
DL = getDataLayout();
2500 Type *Ty =
CE->getType();
2502 const MCExpr *OpExpr = lowerConstantForGV(
Op, ProcessingGeneric);
2506 if (
DL.getTypeAllocSize(Ty) ==
DL.getTypeAllocSize(
Op->getType()))
2512 unsigned InBits =
DL.getTypeAllocSizeInBits(
Op->getType());
2519 case Instruction::Add: {
2520 const MCExpr *
LHS = lowerConstantForGV(
CE->getOperand(0), ProcessingGeneric);
2521 const MCExpr *
RHS = lowerConstantForGV(
CE->getOperand(1), ProcessingGeneric);
2522 switch (
CE->getOpcode()) {
2534 return lowerConstantForGV(
C, ProcessingGeneric);
2538 raw_string_ostream OS(S);
2539 OS <<
"Unsupported expression in static initializer: ";
2540 CE->printAsOperand(OS,
false,
2545void NVPTXAsmPrinter::printMCExpr(
const MCExpr &Expr, raw_ostream &OS)
const {
2546 OutContext.getAsmInfo().printExpr(OS, Expr);
2551bool NVPTXAsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNo,
2552 const char *ExtraCode, raw_ostream &O) {
2553 if (ExtraCode && ExtraCode[0]) {
2554 if (ExtraCode[1] != 0)
2557 switch (ExtraCode[0]) {
2571bool NVPTXAsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
2573 const char *ExtraCode,
2575 if (ExtraCode && ExtraCode[0])
2585void NVPTXAsmPrinter::printOperand(
const MachineInstr *
MI,
unsigned OpNum,
2587 const MachineOperand &MO =
MI->getOperand(OpNum);
2591 if (MO.
getReg() == NVPTX::VRDepot)
2592 getFunctionFrameSymbol()->print(O, MAI);
2596 O << getVirtualRegisterName(MO.
getReg());
2609 PrintSymbolOperand(MO, O);
2621void NVPTXAsmPrinter::printMemOperand(
const MachineInstr *
MI,
unsigned OpNum,
2622 raw_ostream &O,
const char *Modifier) {
2625 if (Modifier && strcmp(Modifier,
"add") == 0) {
2629 if (
MI->getOperand(OpNum + 1).isImm() &&
2630 MI->getOperand(OpNum + 1).getImm() == 0)
2641 return !Trimmed.
empty() &&
2642 (std::isalpha(
static_cast<unsigned char>(Trimmed[0])) ||
2649 if (!
MI || !
MI->getDebugLoc())
2651 const DISubprogram *SP =
MI->getMF()->getFunction().getSubprogram();
2655 if (!
DL->getFile() || !
DL->getLine())
2661struct InlineAsmInliningContext {
2663 unsigned FileIA = 0;
2664 unsigned LineIA = 0;
2667 bool hasInlinedAt()
const {
return FuncNameSym !=
nullptr; }
2673static InlineAsmInliningContext
2677 InlineAsmInliningContext Ctx;
2679 if (!InlinedAt || !InlinedAt->getFile() || !NVDD ||
2687 0, InlinedAt->getFile()->getDirectory(),
2688 InlinedAt->getFile()->getFilename(), std::nullopt, std::nullopt, CUID);
2689 Ctx.LineIA = InlinedAt->getLine();
2690 Ctx.ColIA = InlinedAt->getColumn();
2694void NVPTXAsmPrinter::emitInlineAsm(StringRef Str,
const MCSubtargetInfo &STI,
2695 const MCTargetOptions &MCOptions,
2696 const MDNode *LocMDNode,
2698 const MachineInstr *
MI) {
2699 assert(!Str.empty() &&
"Can't emit empty inline asm block");
2700 if (Str.back() == 0)
2701 Str = Str.substr(0, Str.size() - 1);
2703 auto emitAsmStr = [&](StringRef AsmStr) {
2704 emitInlineAsmStart();
2705 OutStreamer->emitRawText(AsmStr);
2706 emitInlineAsmEnd(STI,
nullptr,
MI);
2715 const DIFile *
File =
DL->getFile();
2716 unsigned Line =
DL->getLine();
2717 const unsigned Column =
DL->getColumn();
2718 const unsigned CUID = OutStreamer->getContext().getDwarfCompileUnitID();
2719 const unsigned FileNumber = OutStreamer->emitDwarfFileDirective(
2720 0,
File->getDirectory(),
File->getFilename(), std::nullopt, std::nullopt,
2723 auto *NVDD =
static_cast<NVPTXDwarfDebug *
>(getDwarfDebug());
2724 InlineAsmInliningContext InlineCtx =
2727 SmallVector<StringRef, 16>
Lines;
2728 Str.split(Lines,
'\n');
2729 emitInlineAsmStart();
2730 for (
const StringRef &L : Lines) {
2731 StringRef RTrimmed =
L.rtrim(
'\r');
2733 if (InlineCtx.hasInlinedAt()) {
2734 OutStreamer->emitDwarfLocDirectiveWithInlinedAt(
2735 FileNumber, Line, Column, InlineCtx.FileIA, InlineCtx.LineIA,
2737 File->getFilename());
2739 OutStreamer->emitDwarfLocDirective(FileNumber, Line, Column,
2741 File->getFilename());
2744 OutStreamer->emitRawText(RTrimmed);
2747 emitInlineAsmEnd(STI,
nullptr,
MI);
2750char NVPTXAsmPrinter::ID = 0;
2757LLVMInitializeNVPTXAsmPrinter() {
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_EXTERNAL_VISIBILITY
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static bool hasDebugInfo(const MachineFunction *MF)
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
static void addSymbol(Object &Obj, const NewSymbolInfo &SymInfo, uint8_t DefaultVisibility)
static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, HexagonAsmPrinter &Printer, bool MustExtend)
Module.h This file contains the declarations for the Module class.
#define DWARF2_FLAG_IS_STMT
Machine Check Debug Module
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static void emitInlineAsm(LLVMContext &C, BasicBlock *BB, StringRef AsmText)
static StringRef getTextureName(const Value &V)
static const DILocation * getInlineAsmDebugLoc(const MachineInstr *MI)
Returns the DILocation for an inline asm MachineInstr if debug line info should be emitted,...
static bool hasFullDebugInfo(Module &M)
static StringRef getSurfaceName(const Value &V)
static bool canDemoteGlobalVar(const GlobalVariable *GV, Function const *&f)
static StringRef getSamplerName(const Value &V)
static bool useFuncSeen(const Constant *C, const SmallPtrSetImpl< const Function * > &SeenSet)
static NVPTX::VirtualRegisterKind getVirtualRegisterKind(const TargetRegisterClass *RC)
static bool usedInGlobalVarDef(const Constant *C)
static InlineAsmInliningContext getInlineAsmInliningContext(const DILocation *DL, const MachineFunction &MF, NVPTXDwarfDebug *NVDD, MCStreamer &Streamer, unsigned CUID)
Resolves the enhanced-lineinfo inlining context for an inline asm debug location.
static bool isPTXInstruction(StringRef Line)
Returns true if Line begins with an alphabetic character or underscore, indicating it is a PTX instru...
static bool usedInOneFunc(const User *U, Function const *&OneFunc)
static void emitInitialRawDwarfLocDirective(const MachineFunction &MF, DwarfDebug *DD, MCStreamer &OutStreamer)
Emits initial debug location directive.
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected components (SCCs) of a ...
static bool printOperand(raw_ostream &OS, const SelectionDAG *G, const SDValue Value)
static void printMemOperand(raw_ostream &OS, const MachineMemOperand &MMO, const MachineFunction *MF, const Module *M, const MachineFrameInfo *MFI, const TargetInstrInfo *TII, LLVMContext &Ctx)
Provides some synthesis utilities to produce sequences of values.
This file defines the SmallPtrSet class.
This file defines the SmallString class.
This file defines the SmallVector class.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
APInt bitcastToAPInt() const
uint64_t getZExtValue() const
Get zero extended value.
LLVM_ABI uint64_t extractBitsAsZExtValue(unsigned numBits, unsigned bitPosition) const
unsigned getBitWidth() const
Return the number of bits in the APInt.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
This class is intended to be used as a driving class for all asm writers.
bool doInitialization(Module &M) override
Set up the AsmPrinter when we are working on a new module.
void getAnalysisUsage(AnalysisUsage &AU) const override
Record analysis usage.
bool doFinalization(Module &M) override
Shut down the asmprinter.
virtual void emitBasicBlockStart(const MachineBasicBlock &MBB)
Targets can override this to emit stuff at the start of a basic block.
bool runOnMachineFunction(MachineFunction &MF) override
Emit the specified function out to the OutStreamer.
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
LLVM_ABI bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const
Determine whether the argument or parameter has the given attribute.
Type * getParamByValType(unsigned ArgNo) const
Extract the byval type for a call or parameter.
Value * getArgOperand(unsigned i) const
FunctionType * getFunctionType() const
unsigned arg_size() const
static LLVM_ABI Constant * getBitCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
ConstantFP - Floating Point Values [float, double].
const APFloat & getValueAPF() const
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
const APInt & getValue() const
Return the constant as an APInt value reference.
Constant Vector Declarations.
FixedVectorType * getType() const
Specialize the getType() method to always return a FixedVectorType, which reduces the amount of casti...
static LLVM_ABI Constant * get(ArrayRef< Constant * > V)
This is an important base class in LLVM.
bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
LLVM_ABI Constant * getAggregateElement(unsigned Elt) const
For aggregates (struct/array/vector) return the constant that corresponds to the specified element if...
Subprogram description. Uses SubclassData1.
iterator find(const_arg_type_t< KeyT > Val)
Collects and handles dwarf debug information.
const MachineInstr * emitInitialLocDirective(const MachineFunction &MF, unsigned CUID)
Emits inital debug location directive.
unsigned getNumElements() const
Type * getReturnType() const
DISubprogram * getSubprogram() const
Get the attached subprogram.
LLVM_ABI const GlobalObject * getAliaseeObject() const
StringRef getSection() const
Get the custom section of this global if it has one.
bool hasSection() const
Check if this global has a custom object file section.
bool hasLinkOnceLinkage() const
bool hasExternalLinkage() const
LLVM_ABI bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
bool hasLocalLinkage() const
bool hasPrivateLinkage() const
unsigned getAddressSpace() const
Module * getParent()
Get the module that this global value is contained inside of...
PointerType * getType() const
Global values are always pointers.
bool hasWeakLinkage() const
bool hasCommonLinkage() const
bool hasAvailableExternallyLinkage() const
Type * getValueType() const
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
bool hasInitializer() const
Definitions have initializers, declarations don't.
MaybeAlign getAlign() const
Returns the alignment of the given variable.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
bool isLoopHeader(const BlockT *BB) const
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
static const MCBinaryExpr * createAnd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Base class for the full range of assembler expressions which are needed for parsing.
Instances of this class represent a single low-level machine instruction.
void addOperand(const MCOperand Op)
void setOpcode(unsigned Op)
Instances of this class represent operands of the MCInst class.
static MCOperand createExpr(const MCExpr *Val)
static MCOperand createReg(MCRegister Reg)
static MCOperand createImm(int64_t Val)
Wrapper class representing physical registers. Should be passed by value.
Streaming machine code generation interface.
virtual bool hasRawTextSupport() const
Return true if this asm streamer supports emitting unformatted text to the .s file with EmitRawText.
unsigned emitDwarfFileDirective(unsigned FileNo, StringRef Directory, StringRef Filename, std::optional< MD5::MD5Result > Checksum=std::nullopt, std::optional< StringRef > Source=std::nullopt, unsigned CUID=0)
Associate a filename with a specified logical file number.
Generic base class for all target subtargets.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
iterator_range< pred_iterator > predecessors()
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
Align getMaxAlign() const
Return the alignment in bytes that this function must be aligned to, which is greater than the defaul...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
MachineBasicBlock * getMBB() const
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
const char * getSymbolName() const
Register getReg() const
getReg - Returns the register number.
const ConstantFP * getFPImm() const
@ MO_Immediate
Immediate operand.
@ MO_GlobalAddress
Address of a global value.
@ MO_MachineBasicBlock
MachineBasicBlock reference.
@ MO_Register
Register operand.
@ MO_ExternalSymbol
Name of external global symbol.
@ MO_JumpTableIndex
Address of indexed Jump Table for switch.
@ MO_FPImmediate
Floating-point immediate operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
bool def_empty(Register RegNo) const
def_empty - Return true if there are no instructions defining the specified register (it may be live-...
unsigned getNumVirtRegs() const
getNumVirtRegs - Return the number of virtual registers created.
bool use_empty(Register RegNo) const
use_empty - Return true if there are no instructions using the specified register.
A Module instance is used to store all the information related to an LLVM module.
NVPTX-specific DwarfDebug implementation.
bool isEnhancedLineinfo(const MachineFunction &MF) const
Returns true if the enhanced lineinfo mode (with inlined_at) is active for the given MachineFunction.
MCSymbol * getOrCreateFuncNameSymbol(StringRef LinkageName)
Get or create an MCSymbol in .debug_str for a function's linkage name.
static const NVPTXFloatMCExpr * createConstantBFPHalf(const APFloat &Flt, MCContext &Ctx)
static const NVPTXFloatMCExpr * createConstantFPHalf(const APFloat &Flt, MCContext &Ctx)
static const NVPTXFloatMCExpr * createConstantFPSingle(const APFloat &Flt, MCContext &Ctx)
static const NVPTXFloatMCExpr * createConstantFPDouble(const APFloat &Flt, MCContext &Ctx)
static const NVPTXGenericMCSymbolRefExpr * create(const MCSymbolRefExpr *SymExpr, MCContext &Ctx)
static const char * getRegisterName(MCRegister Reg)
bool checkImageHandleSymbol(StringRef Symbol) const
Check if the symbol has a mapping.
void clearDebugRegisterMap() const
Register getFrameLocalRegister(const MachineFunction &MF) const
Register getFrameRegister(const MachineFunction &MF) const override
StringRef getTargetName() const
unsigned getMaxRequiredAlignment() const
bool hasMaskOperator() const
const NVPTXTargetLowering * getTargetLowering() const override
unsigned getPTXVersion() const
const NVPTXRegisterInfo * getRegisterInfo() const override
unsigned getSmVersion() const
NVPTX::DrvInterface getDrvInterface() const
const NVPTXSubtarget * getSubtargetImpl(const Function &) const override
Virtual method implemented by subclasses that returns a reference to that target's TargetSubtargetInf...
Implments NVPTX-specific streamer.
unsigned getAddressSpace() const
Return the address space of the Pointer type.
Wrapper class representing virtual and physical registers.
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
constexpr unsigned id() const
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
typename SuperClass::const_iterator const_iterator
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
Check if the string is empty.
StringRef ltrim(char Char) const
Return string with consecutive Char characters starting from the the left removed.
Primary interface to the complete machine description for the target machine.
const STC & getSubtarget(const Function &F) const
This method returns a pointer to the specified type of TargetSubtargetInfo.
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI bool isEmptyTy() const
Return true if this type is empty, that is, it has no elements or all of its elements are empty.
bool isPointerTy() const
True if this is an instance of PointerType.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isIntOrPtrTy() const
Return true if this is an integer type or a pointer type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
TypeID getTypeID() const
Return the type id for the type.
bool isVoidTy() const
Return true if this is 'void'.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
iterator_range< user_iterator > users()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Type * getElementType() const
std::pair< iterator, bool > insert(const ValueT &V)
void insert_range(Range &&R)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
This class implements an extremely fast bulk output stream that can only output to a stream.
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr StringLiteral MaxNTID("nvvm.maxntid")
constexpr StringLiteral ReqNTID("nvvm.reqntid")
constexpr StringLiteral ClusterDim("nvvm.cluster_dim")
constexpr StringLiteral BlocksAreClusters("nvvm.blocksareclusters")
@ CE
Windows NT (Windows on ARM)
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
@ Ready
Emitted to memory, but waiting on transitive dependencies.
std::pair< NodeId, LaneBitmask > NodeRef
NodeAddr< NodeBase * > Node
uint64_t read64le(const void *P)
uint32_t read32le(const void *P)
This is an optimization pass for GlobalISel generic memory operations.
bool isManaged(const Value &)
SmallVector< unsigned, 3 > getReqNTID(const Function &)
constexpr auto not_equal_to(T &&Arg)
Functor variant of std::not_equal_to that can be used as a UnaryPredicate in functional algorithms li...
Align getDeviceByValParamAlign(const Function *F, Type *ArgTy, unsigned AttrIdx, const DataLayout &DL)
The .param-space alignment for a byval parameter or call argument: the (possibly promoted) parameter ...
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
bool hasBlocksAreClusters(const Function &)
SmallVector< unsigned, 3 > getClusterDim(const Function &)
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
void interleave(ForwardIterator begin, ForwardIterator end, UnaryFunctor each_fn, NullaryFunctor between_fn)
An STL-style algorithm similar to std::for_each that applies a second functor between every pair of e...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
std::optional< unsigned > getMaxNReg(const Function &)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
PTXOpaqueType getPTXOpaqueType(const GlobalVariable &)
std::string utostr(uint64_t X, bool isNeg=false)
constexpr auto equal_to(T &&Arg)
Functor variant of std::equal_to that can be used as a UnaryPredicate in functional algorithms like a...
auto map_range(ContainerTy &&C, FuncTy F)
Return a range that applies F to the elements of C.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
std::optional< unsigned > getMinCTASm(const Function &)
LLVM_ABI Constant * ConstantFoldConstant(const Constant *C, const DataLayout &DL, const TargetLibraryInfo *TLI=nullptr)
ConstantFoldConstant - Fold the constant using the specified DataLayout.
auto dyn_cast_or_null(const Y &Val)
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
void sort(IteratorTy Start, IteratorTy End)
unsigned promoteScalarArgumentSize(unsigned size)
SmallVector< unsigned, 3 > getMaxNTID(const Function &)
auto make_first_range(ContainerTy &&c)
Given a container of pairs, return a range over the first elements.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
bool shouldPassAsArray(Type *Ty)
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
iterator_range< filter_iterator< detail::IterOfRange< RangeT >, PredicateT > > make_filter_range(RangeT &&Range, PredicateT Pred)
Convenience function that takes a range of elements and a predicate, and return a new filter_iterator...
std::optional< unsigned > getMaxClusterRank(const Function &)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
FormattedNumber format_hex_no_prefix(uint64_t N, unsigned Width, bool Upper=false)
format_hex_no_prefix - Output N as a fixed width hexadecimal.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
LLVM_ABI void write_hex(raw_ostream &S, uint64_t N, HexPrintStyle Style, std::optional< size_t > Width=std::nullopt)
DWARFExpression::Operation Op
Align getPTXParamAlign(const Function *F, Type *Ty, unsigned AttrIdx, const DataLayout &DL)
Alignment for a function parameter or return value at AttributeList index AttrIdx (FirstArgIndex + ar...
ArrayRef(const T &OneElt) -> ArrayRef< T >
Target & getTheNVPTXTarget64()
auto make_second_range(ContainerTy &&c)
Given a container of pairs, return a range over the second elements.
bool isKernelFunction(const Function &F)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
constexpr auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
void clearAnnotationCache(const Module *)
LLVM_ABI Constant * ConstantFoldIntegerCast(Constant *C, Type *DestTy, bool IsSigned, const DataLayout &DL)
Constant fold a zext, sext or trunc, depending on IsSigned and whether the DestTy is wider or narrowe...
LLVM_ABI MDNode * GetUnrollMetadata(MDNode *LoopID, StringRef Name)
Given an llvm.loop loop id metadata node, returns the loop hint metadata node with the given name (fo...
LLVM_ABI DISubprogram * getDISubprogram(const MDNode *Scope)
Find subprogram that is enclosing this scope.
Target & getTheNVPTXTarget32()
MCRegisterClass TargetRegisterClass
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
MachineJumpTableEntry - One jump table in the jump table info.
std::vector< MachineBasicBlock * > MBBs
MBBs - The vector of basic blocks from which to create the jump table.
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...