107#include <type_traits>
112#define DEPOTNAME "__local_depot"
146 unsigned numSymbols()
const {
return Symbols.size(); }
148 bool allSymbolsAligned(
unsigned ptrSize)
const {
150 [=](
unsigned pos) {
return pos % ptrSize == 0; });
155 std::vector<unsigned char> buffer;
167 const NVPTXAsmPrinter &AP;
168 const bool EmitGeneric;
171 AggBuffer(
unsigned Size,
const NVPTXAsmPrinter &AP)
173 EmitGeneric(AP.EmitGeneric) {}
175 unsigned getBufferSize()
const {
return Size; }
178 unsigned getCurpos()
const {
return curpos; }
182 void addBytes(
const unsigned char *Ptr,
unsigned Num,
unsigned Bytes) {
186 addZeros(Bytes - Num);
191 buffer[curpos] = Byte;
195 void addZeros(
unsigned Num) {
196 for ([[maybe_unused]]
unsigned _ :
llvm::seq(Num)) {
203 Symbols.push_back(GVar);
204 SymbolsBeforeStripping.
push_back(GVarBeforeStripping);
214 friend class AggBuffer;
219 StringRef getPassName()
const override {
return "NVPTX Assembly Printer"; }
226 void emitStartOfAsmFile(
Module &M)
override;
228 void emitFunctionEntryLabel()
override;
229 void emitFunctionBodyStart()
override;
230 void emitFunctionBodyEnd()
override;
241 unsigned getVirtualRegisterNumber(
Register Reg)
const;
244 const char *Modifier =
nullptr);
249 template <
typename T>
250 void printFunctionDirectives(
const T &V,
raw_ostream &O)
const;
252 void emitGlobals(
const Module &M);
259 void emitCallPrototype(
const CallBase &CB,
MCSymbol *PrototypeSymbol)
const;
269 bool ProcessingGeneric)
const;
278 bool doInitialization(
Module &M)
override;
279 bool doFinalization(
Module &M)
override;
294 VRegRCMap VRegMapping;
297 std::map<const Function *, std::vector<const GlobalVariable *>> localDecls;
306 bool EmitInitializer);
308 std::string getPTXFundamentalTypeStr(
Type *Ty)
const;
311 void bufferLEByte(
const Constant *CPV,
int Bytes, AggBuffer *aggBuffer);
312 void bufferAggregateConstant(
const Constant *CV, AggBuffer *aggBuffer);
313 void bufferAggregateConstVec(
const ConstantVector *CV, AggBuffer *aggBuffer);
335 const bool EmitGeneric;
350 std::string getVirtualRegisterName(
Register Reg)
const;
352 const MCSymbol *getFunctionFrameSymbol()
const override;
380 if (SP->getUnit()->isDebugDirectivesOnly() || SP->getUnit()->isNoDebug())
390discoverDependentGlobals(
const Value *V,
391 SmallVectorImpl<const GlobalVariable *> &Globals,
392 SmallPtrSetImpl<const GlobalVariable *> &Seen) {
394 if (Seen.
insert(GV).second)
407 discoverDependentGlobals(
GEP->getPointerOperand(), Globals, Seen);
412 for (
const auto &O :
U->operands())
413 discoverDependentGlobals(O, Globals, Seen);
416struct GlobalVariableDependencyNode {
417 const GlobalVariable *GV =
nullptr;
418 unsigned ModuleOrder = 0;
422class GlobalVariableDependencyGraph {
425 GlobalVariableDependencyNode SyntheticRoot;
428 std::map<const GlobalVariable *, GlobalVariableDependencyNode> Nodes;
431 explicit GlobalVariableDependencyGraph(
const Module &M) {
432 unsigned ModuleOrder = 0;
433 for (
const GlobalVariable &GV :
M.globals()) {
434 GlobalVariableDependencyNode &
Node = Nodes.try_emplace(&GV).first->second;
436 Node.ModuleOrder = ModuleOrder++;
437 SyntheticRoot.Dependencies.push_back(&Node);
440 for (
auto &[GV, Node] : Nodes) {
442 SmallPtrSet<const GlobalVariable *, 4> Seen;
443 for (
const Use &Operand : GV->operands())
444 discoverDependentGlobals(Operand, Dependencies, Seen);
446 for (
const GlobalVariable *Dependency : Dependencies) {
447 auto It = Nodes.find(Dependency);
448 if (It != Nodes.end())
449 Node.Dependencies.push_back(&It->second);
454 const GlobalVariableDependencyNode *getEntryNode()
const {
455 return &SyntheticRoot;
459struct GlobalVariableDependencyGraphTraits {
460 using NodeRef =
const GlobalVariableDependencyNode *;
461 using ChildIteratorType =
464 static NodeRef getEntryNode(NodeRef Node) {
return Node; }
465 static ChildIteratorType child_begin(NodeRef Node) {
466 return Node->Dependencies.begin();
468 static ChildIteratorType child_end(NodeRef Node) {
469 return Node->Dependencies.end();
473using GlobalVariableSCCIterator =
474 scc_iterator<
const GlobalVariableDependencyNode *,
475 GlobalVariableDependencyGraphTraits>;
477static bool shouldSkipModuleLevelGlobal(
const GlobalVariable &GV) {
483static bool isForwardDeclarableGlobal(
const GlobalVariable *GVar) {
484 if (shouldSkipModuleLevelGlobal(*GVar) || GVar->
isDeclaration() ||
505 const DenseSet<const GlobalVariableDependencyNode *> &ForwardDeclared) {
506 using Node = GlobalVariableDependencyNode;
508 DenseSet<const Node *> SCCSet;
511 DenseMap<const Node *, unsigned> DependencyCount;
512 DenseMap<const Node *, SmallVector<const Node *, 4>> Dependents;
513 std::set<std::pair<unsigned, const Node *>>
Ready;
517 for (
const Node *
N : SCC) {
518 unsigned &
Count = DependencyCount[
N];
519 for (
const Node *Dependency :
N->Dependencies) {
520 if (!SCCSet.
count(Dependency) || ForwardDeclared.
count(Dependency))
523 Dependents[Dependency].push_back(
N);
526 Ready.emplace(
N->ModuleOrder,
N);
530 while (!
Ready.empty()) {
535 auto It = Dependents.
find(
N);
536 if (It == Dependents.
end())
538 for (
const Node *Dependent : It->second) {
539 assert(DependencyCount[Dependent] &&
"Dependency already satisfied");
540 if (--DependencyCount[Dependent] == 0)
541 Ready.emplace(Dependent->ModuleOrder, Dependent);
545 if (Order.
size() !=
SCC.size())
553 NVPTX_MC::verifyInstructionPredicates(
MI->getOpcode(),
554 getSubtargetInfo().getFeatureBits());
557 lowerToMCInst(
MI, Inst);
558 EmitToStreamer(*OutStreamer, Inst);
561void NVPTXAsmPrinter::lowerToMCInst(
const MachineInstr *
MI, MCInst &OutMI) {
563 for (
const auto MO :
MI->operands())
567MCOperand NVPTXAsmPrinter::lowerOperand(
const MachineOperand &MO) {
599 case Type::BFloatTyID:
602 case Type::FloatTyID:
605 case Type::DoubleTyID:
614static NVPTX::VirtualRegisterKind
616 if (RC == &NVPTX::B1RegClass)
618 if (RC == &NVPTX::B16RegClass)
620 if (RC == &NVPTX::B32RegClass)
622 if (RC == &NVPTX::B64RegClass)
624 if (RC == &NVPTX::B128RegClass)
629unsigned NVPTXAsmPrinter::getVirtualRegisterNumber(
Register Reg)
const {
631 assert(It != VRegMapping.
end() &&
"Bad register class");
633 const unsigned Num = It->second.lookup(
Reg);
634 assert(Num &&
"Bad virtual register");
638MCRegister NVPTXAsmPrinter::encodeVirtualRegister(
Register Reg) {
643 const unsigned Num = getVirtualRegisterNumber(
Reg);
644 assert(Num <= NVPTX::VirtualRegisterNumMask &&
645 "Too many virtual registers");
646 return (
static_cast<unsigned>(Kind) << NVPTX::VirtualRegisterKindShift) |
652 assert(
Reg.
id() <= NVPTX::VirtualRegisterNumMask &&
653 "Physical register would decode as a virtual register");
657MCOperand NVPTXAsmPrinter::GetSymbolRef(
const MCSymbol *Symbol) {
663template <
typename OwnerT>
665 bool IsByVal,
bool IsKernel,
StringRef Name,
670 const Align ParamAlign =
673 O <<
".align " << ParamAlign.
value() <<
" .b8 " << Name <<
"["
674 <<
DL.getTypeAllocSize(Ty) <<
"]";
678 assert((Ty->isFloatingPointTy() || Ty->isIntOrPtrTy()) &&
679 "Unknown parameter type");
680 const unsigned Size =
DL.getTypeSizeInBits(Ty).getFixedValue();
687template <
typename OwnerT>
690 Type *RetTy =
Owner->getFunctionType()->getReturnType();
704void NVPTXAsmPrinter::emitCallPrototype(
const CallBase &CB,
705 MCSymbol *PrototypeSymbol)
const {
706 const DataLayout &
DL = getDataLayout();
707 const NVPTXSubtarget &STI = MF->getSubtarget<NVPTXSubtarget>();
709 OutStreamer->emitLabel(PrototypeSymbol);
711 SmallString<128> Str;
712 raw_svector_ostream
O(Str);
714 O <<
".callprototype ";
718 auto MakeArg = [&](
const unsigned I) {
723 printParam(&CB, Ty,
I + AttributeList::FirstArgIndex, IsByVal,
728 const unsigned NumArgs = FTy->getNumParams();
738 if (FTy->isVarArg() && CB.
arg_size() > NumArgs)
739 O << (NonEmptyArgs.empty() ?
"" :
",") <<
" .param .align "
743 printFunctionDirectives(CB, O);
746 OutStreamer->emitRawText(
O.str());
749void NVPTXAsmPrinter::emitJumpTable(
const MachineJumpTableEntry &MJT,
750 unsigned MJTI)
const {
751 OutStreamer->emitLabel(GetJTISymbol(MJTI));
753 if (MJT.
MBBs.empty())
758 return MBB->getSymbol();
760 getTargetStreamer()->emitBranchTargetsDirective(Targets);
765bool NVPTXAsmPrinter::isLoopHeaderOfNoUnroll(
766 const MachineBasicBlock &
MBB)
const {
767 const MachineLoopInfo *LI = GetMLI(*MF);
768 assert(LI &&
"NVPTXAsmPrinter requires MachineLoopInfo");
781 if (
const BasicBlock *PBB = PMBB->getBasicBlock()) {
783 PBB->getTerminator()->getMetadata(LLVMContext::MD_loop)) {
786 if (MDNode *UnrollCountMD =
798void NVPTXAsmPrinter::emitBasicBlockStart(
const MachineBasicBlock &
MBB) {
800 if (isLoopHeaderOfNoUnroll(
MBB))
801 getTargetStreamer()->emitPragmaDirective(
"nounroll");
804void NVPTXAsmPrinter::emitFunctionEntryLabel() {
805 SmallString<128> Str;
806 raw_svector_ostream
O(Str);
808 if (!GlobalsEmitted) {
809 emitGlobals(*MF->getFunction().getParent());
810 GlobalsEmitted =
true;
814 MRI = &MF->getRegInfo();
815 F = &MF->getFunction();
816 emitLinkageDirective(
F, O);
824 CurrentFnSym->print(O, MAI);
826 emitFunctionParamList(
F, O);
830 emitKernelFunctionDirectives(*
F, O);
832 printFunctionDirectives(*
F, O);
834 OutStreamer->emitRawText(
O.str());
838 OutStreamer->emitRawText(StringRef(
"{\n"));
839 setAndEmitFunctionVirtualRegisters(*MF);
840 encodeDebugInfoRegisterNumbers(*MF);
852 OutStreamer->emitRawText(StringRef(
"}\n"));
856void NVPTXAsmPrinter::emitFunctionBodyStart() {
857 SmallString<128> Str;
858 raw_svector_ostream
O(Str);
859 emitDemotedVars(&MF->getFunction(), O);
860 OutStreamer->emitRawText(
O.str());
862 const auto *MFI = MF->getInfo<NVPTXMachineFunctionInfo>();
863 for (
const auto &[CB, Symbol] : MFI->getCallPrototypes())
864 emitCallPrototype(*CB, Symbol);
866 if (
const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo())
867 for (
const auto &[Idx, JT] :
enumerate(MJTI->getJumpTables()))
868 emitJumpTable(JT, Idx);
871void NVPTXAsmPrinter::emitFunctionBodyEnd() {
875const MCSymbol *NVPTXAsmPrinter::getFunctionFrameSymbol()
const {
876 return OutContext.getOrCreateSymbol(
DEPOTNAME + Twine(getFunctionNumber()));
879void NVPTXAsmPrinter::emitImplicitDef(
const MachineInstr *
MI)
const {
882 OutStreamer->AddComment(Twine(
"implicit-def: ") +
883 getVirtualRegisterName(RegNo));
885 OutStreamer->AddComment(Twine(
"implicit-def: ") +
887 OutStreamer->addBlankLine();
890void NVPTXAsmPrinter::emitKernelFunctionDirectives(
const Function &
F,
891 raw_ostream &O)
const {
897 O <<
formatv(
".reqntid {0:$[, ]}\n",
902 O <<
formatv(
".maxntid {0:$[, ]}\n",
906 O <<
".minnctapersm " << *Mincta <<
"\n";
909 O <<
".maxnreg " << *Maxnreg <<
"\n";
913 const NVPTXTargetMachine &NTM =
static_cast<const NVPTXTargetMachine &
>(TM);
914 const NVPTXSubtarget *STI = &NTM.
getSubtarget<NVPTXSubtarget>(
F);
916 if (STI->hasFeature(NVPTX::SM90)) {
922 if (!BlocksAreClusters)
923 O <<
".explicitcluster\n";
925 if (ClusterDim[0] != 0) {
927 "cluster_dim_x != 0 implies cluster_dim_y and cluster_dim_z "
928 "should be non-zero as well");
930 O <<
formatv(
".reqnctapercluster {0:$[, ]}\n",
934 "cluster_dim_x == 0 implies cluster_dim_y and cluster_dim_z "
935 "should be 0 as well");
939 if (BlocksAreClusters) {
940 LLVMContext &Ctx =
F.getContext();
942 Ctx.
diagnose(DiagnosticInfoUnsupported(
943 F,
"blocksareclusters requires reqntid and cluster_dim attributes",
945 else if (!STI->hasFeature(NVPTX::PTX90))
946 Ctx.
diagnose(DiagnosticInfoUnsupported(
947 F,
"blocksareclusters requires PTX version >= 9.0",
950 O <<
".blocksareclusters\n";
954 O <<
".maxclusterrank " << *Maxclusterrank <<
"\n";
958std::string NVPTXAsmPrinter::getVirtualRegisterName(
Register Reg)
const {
962 raw_string_ostream(Name) << NVPTX::getVirtualRegisterPrefix(Kind)
963 << getVirtualRegisterNumber(
Reg);
967void NVPTXAsmPrinter::emitAliasDeclaration(
const GlobalAlias *GA,
972 "NVPTX aliasee must be a non-kernel function definition");
978 emitDeclarationWithName(
F, getSymbol(GA), O);
981void NVPTXAsmPrinter::emitDeclaration(
const Function *
F, raw_ostream &O) {
982 emitDeclarationWithName(
F, getSymbol(
F), O);
985void NVPTXAsmPrinter::emitDeclarationWithName(
const Function *
F, MCSymbol *S,
987 emitLinkageDirective(
F, O);
996 emitFunctionParamList(
F, O);
999 printFunctionDirectives(*
F, O);
1008 return GV->
getName() !=
"llvm.used";
1010 for (
const User *U :
C->users())
1020 if (OtherGV->getName() ==
"llvm.used")
1024 if (
const Function *CurFunc =
I->getFunction()) {
1025 if (OneFunc && (CurFunc != OneFunc))
1066 for (
const User *U :
C->users()) {
1071 if (
const Function *Caller =
I->getFunction())
1079void NVPTXAsmPrinter::emitDeclarations(
const Module &M, raw_ostream &O) {
1080 SmallPtrSet<const Function *, 32> SeenSet;
1082 if (
F.getAttributes().hasFnAttr(
"nvptx-libcall-callee")) {
1083 emitDeclaration(&
F, O);
1087 if (
F.isDeclaration()) {
1090 if (
F.getIntrinsicID())
1094 if (
F.isIntrinsic()) {
1095 LLVMContext &Ctx =
F.getContext();
1096 Ctx.
diagnose(DiagnosticInfoUnsupported(
1097 F,
"unknown intrinsic '" +
F.getName() +
1098 "' cannot be lowered by the NVPTX backend"));
1101 emitDeclaration(&
F, O);
1104 for (
const User *U :
F.users()) {
1110 emitDeclaration(&
F, O);
1116 emitDeclaration(&
F, O);
1131 emitDeclaration(&
F, O);
1137 for (
const GlobalAlias &GA :
M.aliases())
1138 emitAliasDeclaration(&GA, O);
1141void NVPTXAsmPrinter::emitStartOfAsmFile(
Module &M) {
1145 const NVPTXTargetMachine &NTM =
static_cast<const NVPTXTargetMachine &
>(TM);
1149 emitHeader(M, *STI);
1153DwarfDebug *NVPTXAsmPrinter::createDwarfDebug() {
1154 return new NVPTXDwarfDebug(
this);
1157bool NVPTXAsmPrinter::doInitialization(
Module &M) {
1158 const NVPTXTargetMachine &NTM =
static_cast<const NVPTXTargetMachine &
>(TM);
1160 if (
M.alias_size() &&
1161 (!STI.hasFeature(NVPTX::PTX63) || !STI.hasFeature(NVPTX::SM30)))
1167 GlobalsEmitted =
false;
1171 for (
const GlobalValue &GV :
M.global_values())
1177void NVPTXAsmPrinter::emitGlobals(
const Module &M) {
1178 SmallString<128> Str2;
1179 raw_svector_ostream OS2(Str2);
1181 emitDeclarations(M, OS2);
1183 const NVPTXTargetMachine &NTM =
static_cast<const NVPTXTargetMachine &
>(TM);
1191 GlobalVariableDependencyGraph DependencyGraph(M);
1192 for (GlobalVariableSCCIterator
I =
1193 GlobalVariableSCCIterator::begin(DependencyGraph.getEntryNode());
1194 !
I.isAtEnd(); ++
I) {
1199 if (!
SCC.front()->GV) {
1200 assert(
SCC.size() == 1 &&
"Synthetic root must be in its own SCC");
1205 return LHS->ModuleOrder <
RHS->ModuleOrder;
1208 const bool IsCyclic =
I.hasCycle();
1209 DenseSet<const GlobalVariableDependencyNode *> ForwardDeclared;
1211 for (
const auto *Node : SCC)
1212 if (isForwardDeclarableGlobal(
Node->GV))
1213 ForwardDeclared.
insert(Node);
1217 IsCyclic ? orderDefinitionsInSCC(SCC, ForwardDeclared)
1220 for (
const auto *Node : SCC) {
1221 if (!ForwardDeclared.
count(Node))
1224 emitPTXGlobalVariableDefinition(
Node->GV, OS2, STI,
1229 for (
const GlobalVariable *GV : OrderedGlobals)
1230 printModuleLevelGV(GV, OS2,
false, STI);
1235 OutStreamer->emitRawText(OS2.str());
1238void NVPTXAsmPrinter::emitGlobalAlias(
const Module &M,
const GlobalAlias &GA) {
1239 getTargetStreamer()->emitAliasDirective(getSymbol(&GA),
1243NVPTXTargetStreamer *NVPTXAsmPrinter::getTargetStreamer()
const {
1244 return static_cast<NVPTXTargetStreamer *
>(OutStreamer->getTargetStreamer());
1249 switch(
CU->getEmissionKind()) {
1262void NVPTXAsmPrinter::emitHeader(
Module &M,
const NVPTXSubtarget &STI) {
1263 auto *TS = getTargetStreamer();
1268 TS->emitVersionDirective(PTXVersion);
1270 const NVPTXTargetMachine &NTM =
static_cast<const NVPTXTargetMachine &
>(TM);
1273 TS->emitTargetDirective(STI.
getTargetName(), TexModeIndependent,
1275 TS->emitAddressSizeDirective(
M.getDataLayout().getPointerSizeInBits());
1278bool NVPTXAsmPrinter::doFinalization(
Module &M) {
1281 if (!GlobalsEmitted) {
1283 GlobalsEmitted =
true;
1292 static_cast<NVPTXTargetStreamer *
>(OutStreamer->getTargetStreamer());
1295 TS->closeLastSection();
1297 TS->emitEmptySectionDirective(
".debug_macinfo");
1301 TS->outputDwarfFileDirectives();
1319void NVPTXAsmPrinter::emitLinkageDirective(
const GlobalValue *V,
1321 if (
static_cast<NVPTXTargetMachine &
>(TM).getDrvInterface() == NVPTX::CUDA) {
1322 if (
V->hasExternalLinkage()) {
1325 else if (
V->isDeclaration())
1329 }
else if (
V->hasAppendingLinkage()) {
1331 "' has unsupported appending linkage type");
1332 }
else if (!
V->hasInternalLinkage() && !
V->hasPrivateLinkage()) {
1338void NVPTXAsmPrinter::printModuleLevelGV(
const GlobalVariable *GVar,
1339 raw_ostream &O,
bool ProcessDemoted,
1340 const NVPTXSubtarget &STI) {
1342 if (shouldSkipModuleLevelGlobal(*GVar))
1361 if (OpaqueType == PTXOpaqueType::Texture) {
1362 O <<
".global .texref ";
1363 getSymbol(GVar)->print(O, MAI);
1368 if (OpaqueType == PTXOpaqueType::Surface) {
1369 O <<
".global .surfref ";
1370 getSymbol(GVar)->print(O, MAI);
1379 emitPTXGlobalVariableDefinition(GVar, O, STI,
false);
1384 if (OpaqueType == PTXOpaqueType::Sampler) {
1385 O <<
".global .samplerref ";
1386 getSymbol(GVar)->print(O, MAI);
1388 const Constant *Initializer =
nullptr;
1391 const ConstantInt *CI =
nullptr;
1402 O <<
"addr_mode_" << i <<
" = ";
1408 O <<
"clamp_to_border";
1411 O <<
"clamp_to_edge";
1422 O <<
"filter_mode = ";
1437 O <<
", force_unnormalized_coords = 1";
1457 const Function *DemotedFunc =
nullptr;
1459 O <<
"// " << GVar->
getName() <<
" has been demoted\n";
1460 localDecls[DemotedFunc].push_back(GVar);
1464 emitPTXGlobalVariableDefinition(GVar, O, STI,
true);
1468template <
typename T>
1469void NVPTXAsmPrinter::printFunctionDirectives(
const T &V,
1470 raw_ostream &O)
const {
1471 const NVPTXSubtarget &STI =
1472 *
static_cast<const NVPTXTargetMachine &
>(TM).getSubtargetImpl();
1475 V.getFunctionType()->getReturnType()->isVoidTy())
1485 O <<
".abi_preserve " << *
ABI.Preserve <<
"\n";
1486 if (
ABI.PreserveControl)
1487 O <<
".abi_preserve_control " << *
ABI.PreserveControl <<
"\n";
1490void NVPTXAsmPrinter::emitPTXGlobalVariableDefinition(
1491 const GlobalVariable *GVar, raw_ostream &O,
const NVPTXSubtarget &STI,
1492 bool EmitInitializer) {
1493 const DataLayout &
DL = getDataLayout();
1500 if (!STI.hasFeature(NVPTX::PTX40) || !STI.hasFeature(NVPTX::SM30))
1502 ".attribute(.managed) requires PTX version >= 4.0 and sm_30");
1503 O <<
" .attribute(.managed)";
1507 << GVar->
getAlign().value_or(
DL.getPrefTypeAlign(ETy)).value();
1509 const Constant *Initializer =
nullptr;
1516 "' is not allowed in addrspace(" +
1524 O <<
" ." << getPTXFundamentalTypeStr(ETy) <<
" ";
1525 getSymbol(GVar)->print(O, MAI);
1527 if (EmitInitializer && Initializer) {
1529 printScalarConstant(Initializer, O);
1540 "type not supported yet");
1542 const uint64_t ElementSize =
DL.getTypeStoreSize(ETy);
1546 getSymbol(GVar)->print(O, MAI);
1548 O <<
"[" << ElementSize <<
"]";
1549 else if (!EmitInitializer)
1554 AggBuffer aggBuffer(ElementSize, *
this);
1555 bufferAggregateConstant(Initializer, &aggBuffer);
1556 if (aggBuffer.numSymbols()) {
1557 const unsigned int ptrSize = MAI.getCodePointerSize();
1558 if (ElementSize % ptrSize || !aggBuffer.allSymbolsAligned(ptrSize)) {
1563 "' requires at least PTX ISA version 7.1");
1565 getSymbol(GVar)->print(O, MAI);
1566 O <<
"[" << ElementSize <<
"]";
1567 if (EmitInitializer) {
1569 aggBuffer.printBytes(O);
1573 O <<
" .u" << ptrSize * 8 <<
" ";
1574 getSymbol(GVar)->print(O, MAI);
1575 O <<
"[" << ElementSize / ptrSize <<
"]";
1576 if (EmitInitializer) {
1578 aggBuffer.printWords(O);
1584 getSymbol(GVar)->print(O, MAI);
1585 O <<
"[" << ElementSize <<
"]";
1586 if (EmitInitializer) {
1588 aggBuffer.printBytes(O);
1594void NVPTXAsmPrinter::AggBuffer::printSymbol(
unsigned nSym, raw_ostream &os) {
1595 const Value *
v = Symbols[nSym];
1596 const Value *v0 = SymbolsBeforeStripping[nSym];
1601 bool isGenericPointer = PTy && PTy->getAddressSpace() == 0;
1604 Name->print(os, AP.MAI);
1607 Name->print(os, AP.MAI);
1610 const MCExpr *Expr = AP.lowerConstantForGV(CExpr,
false);
1611 AP.printMCExpr(*Expr, os);
1616void NVPTXAsmPrinter::AggBuffer::printBytes(raw_ostream &os) {
1617 unsigned int ptrSize = AP.MAI.getCodePointerSize();
1622 unsigned int InitializerCount =
Size;
1625 if (numSymbols() == 0)
1626 while (InitializerCount >= 1 && !buffer[InitializerCount - 1])
1629 symbolPosInBuffer.push_back(InitializerCount);
1630 unsigned int nSym = 0;
1631 unsigned int nextSymbolPos = symbolPosInBuffer[nSym];
1632 for (
unsigned int pos = 0; pos < InitializerCount;) {
1635 if (pos != nextSymbolPos) {
1636 os << (
unsigned int)buffer[pos];
1643 std::string symText;
1644 llvm::raw_string_ostream oss(symText);
1645 printSymbol(nSym, oss);
1646 for (
unsigned i = 0; i < ptrSize; ++i) {
1650 os <<
"(" << symText <<
")";
1653 nextSymbolPos = symbolPosInBuffer[++nSym];
1654 assert(nextSymbolPos >= pos);
1658void NVPTXAsmPrinter::AggBuffer::printWords(raw_ostream &os) {
1659 unsigned int ptrSize = AP.MAI.getCodePointerSize();
1660 symbolPosInBuffer.push_back(
Size);
1661 unsigned int nSym = 0;
1662 unsigned int nextSymbolPos = symbolPosInBuffer[nSym];
1663 assert(nextSymbolPos % ptrSize == 0);
1664 for (
unsigned int pos = 0; pos <
Size; pos += ptrSize) {
1667 if (pos == nextSymbolPos) {
1668 printSymbol(nSym, os);
1669 nextSymbolPos = symbolPosInBuffer[++nSym];
1670 assert(nextSymbolPos % ptrSize == 0);
1671 assert(nextSymbolPos >= pos + ptrSize);
1672 }
else if (ptrSize == 4)
1679void NVPTXAsmPrinter::emitDemotedVars(
const Function *
F, raw_ostream &O) {
1680 auto It = localDecls.find(
F);
1681 if (It == localDecls.end())
1686 const NVPTXTargetMachine &NTM =
static_cast<const NVPTXTargetMachine &
>(TM);
1689 for (
const GlobalVariable *GV : GVars) {
1690 O <<
"\t// demoted variable\n\t";
1691 printModuleLevelGV(GV, O,
true, STI);
1715 switch (OpaqueType) {
1717 return ".samplerref";
1728void NVPTXAsmPrinter::emitPTXAddressSpace(
unsigned int AddressSpace,
1729 raw_ostream &O)
const {
1737std::string NVPTXAsmPrinter::getPTXFundamentalTypeStr(
Type *Ty)
const {
1739 case Type::IntegerTyID:
1740 case Type::PointerTyID: {
1741 const uint64_t NumBits = getDataLayout().getTypeStoreSizeInBits(Ty);
1742 assert(NumBits <= 64 &&
"type too large");
1745 case Type::BFloatTyID:
1746 case Type::HalfTyID:
1747 case Type::FloatTyID:
1748 case Type::DoubleTyID:
1756void NVPTXAsmPrinter::emitFunctionParamList(
const Function *
F, raw_ostream &O) {
1757 const DataLayout &
DL = getDataLayout();
1758 const NVPTXSubtarget &STI = TM.getSubtarget<NVPTXSubtarget>(*F);
1760 const NVPTXMachineFunctionInfo *MFI =
1761 MF ? MF->getInfo<NVPTXMachineFunctionInfo>() : nullptr;
1769 const auto NonEmptyArgs =
1771 return !Arg.getType()->isEmptyTy();
1774 if (NonEmptyArgs.empty() && !
F->isVarArg()) {
1781 auto MakeParam = [&](
const auto &IndexedArg) {
1782 const auto &[ParamIndex, Arg] = IndexedArg;
1783 Type *Ty = Arg.getType();
1784 MCSymbol *
const ParamSym = TLI->getParamSymbol(OutContext,
F, ParamIndex);
1790 const bool IsByVal = Arg.hasByValAttr();
1796 if (IsKernelFunc && !AsArray) {
1798 if (!OpaqueType.
empty()) {
1803 O << OpaqueType <<
" " << *ParamSym;
1808 const unsigned AS = PTy->getAddressSpace();
1809 O <<
".param .u" <<
DL.getPointerSizeInBits(AS) <<
" .ptr";
1815 O <<
" .align " << Arg.getParamAlign().valueOrOne().value() <<
" "
1821 printParam(
F, IsByVal ? Arg.getParamByValType() : Ty,
1822 Arg.getArgNo() + AttributeList::FirstArgIndex, IsByVal,
1823 IsKernelFunc, ParamSym->
getName(),
DL, O);
1829 O << (NonEmptyArgs.empty() ?
"" :
",\n") <<
"\t.param .align "
1831 << *TLI->getParamSymbol(OutContext,
F, -1) <<
"[]";
1836void NVPTXAsmPrinter::setAndEmitFunctionVirtualRegisters(
1838 auto *TS = getTargetStreamer();
1843 TS->emitLocalDirective(MFI.
getMaxAlign(), getFunctionFrameSymbol(),
1847 const NVPTXRegisterInfo *NRI =
1851 TS->emitRegDirective(
1852 NRI->getRegSizeInBits(FrameReg, *MRI).getFixedValue(),
1861 Register VR = Register::index2VirtReg(
I);
1864 auto &RCRegMap = VRegMapping[MRI->
getRegClass(VR)];
1865 RCRegMap[VR] = RCRegMap.
size() + 1;
1873 const auto It = VRegMapping.
find(&RC);
1874 if (It == VRegMapping.
end() || It->second.empty())
1877 TS->emitRegDirective(
1878 TRI->getRegSizeInBits(RC).getFixedValue(),
1880 It->second.size() + 1);
1886void NVPTXAsmPrinter::encodeDebugInfoRegisterNumbers(
1888 const NVPTXSubtarget &STI = MF.
getSubtarget<NVPTXSubtarget>();
1898 NRI->addToDebugRegisterMap(
Reg, getVirtualRegisterName(
Reg));
1901void NVPTXAsmPrinter::printFPConstant(
const ConstantFP *Fp,
1902 raw_ostream &O)
const {
1915void NVPTXAsmPrinter::printScalarConstant(
const Constant *CPV, raw_ostream &O) {
1921 const APInt API = CFP->getValueAPF().bitcastToAPInt();
1933 if (EmitGeneric && !
isa<Function>(CPV) && !IsNonGenericPointer) {
1935 getSymbol(GVar)->print(O, MAI);
1938 getSymbol(GVar)->print(O, MAI);
1950void NVPTXAsmPrinter::bufferLEByte(
const Constant *CPV,
int Bytes,
1951 AggBuffer *AggBuffer) {
1952 const DataLayout &
DL = getDataLayout();
1953 int AllocSize =
DL.getTypeAllocSize(CPV->
getType());
1957 AggBuffer->addZeros(Bytes ? Bytes : AllocSize);
1962 auto AddIntToBuffer = [AggBuffer, Bytes](
const APInt &Val) {
1963 size_t NumBytes = (Val.getBitWidth() + 7) / 8;
1969 for (
unsigned I = 0;
I < NumBytes - 1; ++
I) {
1970 Buf[
I] = Val.extractBitsAsZExtValue(8,
I * 8);
1972 size_t LastBytePosition = (NumBytes - 1) * 8;
1973 size_t LastByteBits = Val.getBitWidth() - LastBytePosition;
1975 Val.extractBitsAsZExtValue(LastByteBits, LastBytePosition);
1976 AggBuffer->addBytes(Buf.data(), NumBytes, Bytes);
1980 case Type::IntegerTyID:
1986 if (
const auto *CI =
1991 if (Cexpr->getOpcode() == Instruction::PtrToInt) {
1992 Value *
V = Cexpr->getOperand(0)->stripPointerCasts();
1993 AggBuffer->addSymbol(V, Cexpr->getOperand(0));
1994 AggBuffer->addZeros(AllocSize);
2001 AggBuffer->addSymbol(Cexpr, Cexpr);
2002 AggBuffer->addZeros(AllocSize);
2008 case Type::HalfTyID:
2009 case Type::BFloatTyID:
2010 case Type::FloatTyID:
2011 case Type::DoubleTyID:
2012 case Type::FP128TyID:
2016 case Type::PointerTyID: {
2018 AggBuffer->addSymbol(GVar, GVar);
2020 const Value *
v = Cexpr->stripPointerCasts();
2021 AggBuffer->addSymbol(v, Cexpr);
2023 AggBuffer->addZeros(AllocSize);
2027 case Type::ArrayTyID:
2028 case Type::FixedVectorTyID:
2029 case Type::StructTyID: {
2033 unsigned StartPos = AggBuffer->getCurpos();
2034 bufferAggregateConstant(CPV, AggBuffer);
2035 unsigned Written = AggBuffer->getCurpos() - StartPos;
2036 unsigned SlotSize = std::max<int>(Bytes, AllocSize);
2037 if (SlotSize > Written)
2038 AggBuffer->addZeros(SlotSize - Written);
2040 AggBuffer->addZeros(Bytes);
2051void NVPTXAsmPrinter::bufferAggregateConstant(
const Constant *CPV,
2052 AggBuffer *aggBuffer) {
2053 const DataLayout &
DL = getDataLayout();
2055 auto ExtendBuffer = [](APInt Val, AggBuffer *Buffer) {
2058 unsigned NumBits = std::min(8u, Val.
getBitWidth() -
I * 8);
2066 for (
unsigned I :
llvm::seq(VTy->getNumElements()))
2075 ExtendBuffer(CI->
getValue(), aggBuffer);
2081 assert(CFP->getType()->isFloatingPointTy() &&
"Expected fp constant!");
2082 if (CFP->getType()->isFP128Ty()) {
2083 ExtendBuffer(CFP->getValueAPF().bitcastToAPInt(), aggBuffer);
2097 bufferAggregateConstVec(CVec, aggBuffer);
2102 for (
unsigned I :
llvm::seq(CDS->getNumElements()))
2103 bufferLEByte(
cast<Constant>(CDS->getElementAsConstant(
I)), 0, aggBuffer);
2112 ?
DL.getStructLayout(ST)->getElementOffset(0) +
2113 DL.getTypeAllocSize(ST)
2114 :
DL.getStructLayout(ST)->getElementOffset(
I + 1);
2115 int Bytes = EndOffset -
DL.getStructLayout(ST)->getElementOffset(
I);
2124void NVPTXAsmPrinter::bufferAggregateConstVec(
const ConstantVector *CV,
2125 AggBuffer *aggBuffer) {
2127 const unsigned BuffSize = aggBuffer->getBufferSize();
2130 if (BuffSize >= NumElems) {
2143 assert(ElemTySize < 8 &&
"Expected sub-byte data type.");
2144 assert(8 % ElemTySize == 0 &&
"Element type size must evenly divide a byte.");
2146 unsigned NumElemsPerByte = 8 / ElemTySize;
2147 unsigned NumCompleteBytes = NumElems / NumElemsPerByte;
2148 unsigned NumTailElems = NumElems % NumElemsPerByte;
2153 auto ConvertSubCVtoInt8 = [
this, &ElemTy](
const ConstantVector *CV,
2155 unsigned NumPaddingZeros = 0) {
2162 if (NumPaddingZeros)
2163 SubCVElems.
append(NumPaddingZeros, ConstantInt::getNullValue(ElemTy));
2169 ConstantInt *MergedElem =
2176 "Cannot lower vector global with unusual element type");
2183 for (
unsigned ByteIdx :
llvm::seq(NumCompleteBytes))
2184 bufferLEByte(ConvertSubCVtoInt8(CV, ByteIdx * NumElemsPerByte,
2185 (ByteIdx + 1) * NumElemsPerByte),
2189 if (NumTailElems > 0)
2190 bufferLEByte(ConvertSubCVtoInt8(CV, NumElems - NumTailElems, NumElems,
2191 NumElemsPerByte - NumTailElems),
2200NVPTXAsmPrinter::lowerConstantForGV(
const Constant *CV,
2201 bool ProcessingGeneric)
const {
2202 MCContext &Ctx = OutContext;
2212 if (ProcessingGeneric)
2222 switch (
CE->getOpcode()) {
2226 case Instruction::AddrSpaceCast: {
2229 if (DstTy->getAddressSpace() == 0)
2235 case Instruction::GetElementPtr: {
2236 const DataLayout &
DL = getDataLayout();
2239 APInt OffsetAI(
DL.getPointerTypeSizeInBits(
CE->getType()), 0);
2242 const MCExpr *
Base = lowerConstantForGV(
CE->getOperand(0),
2247 int64_t
Offset = OffsetAI.getSExtValue();
2252 case Instruction::Trunc:
2258 case Instruction::BitCast:
2259 return lowerConstantForGV(
CE->getOperand(0), ProcessingGeneric);
2261 case Instruction::IntToPtr: {
2262 const DataLayout &
DL = getDataLayout();
2270 return lowerConstantForGV(
Op, ProcessingGeneric);
2275 case Instruction::PtrToInt: {
2276 const DataLayout &
DL = getDataLayout();
2281 Type *Ty =
CE->getType();
2283 const MCExpr *OpExpr = lowerConstantForGV(
Op, ProcessingGeneric);
2287 if (
DL.getTypeAllocSize(Ty) ==
DL.getTypeAllocSize(
Op->getType()))
2293 unsigned InBits =
DL.getTypeAllocSizeInBits(
Op->getType());
2300 case Instruction::Add: {
2301 const MCExpr *
LHS = lowerConstantForGV(
CE->getOperand(0), ProcessingGeneric);
2302 const MCExpr *
RHS = lowerConstantForGV(
CE->getOperand(1), ProcessingGeneric);
2303 switch (
CE->getOpcode()) {
2315 return lowerConstantForGV(
C, ProcessingGeneric);
2319 raw_string_ostream OS(S);
2320 OS <<
"Unsupported expression in static initializer: ";
2321 CE->printAsOperand(OS,
false,
2326void NVPTXAsmPrinter::printMCExpr(
const MCExpr &Expr, raw_ostream &OS)
const {
2327 OutContext.getAsmInfo().printExpr(OS, Expr);
2332bool NVPTXAsmPrinter::PrintAsmOperand(
const MachineInstr *
MI,
unsigned OpNo,
2333 const char *ExtraCode, raw_ostream &O) {
2334 if (ExtraCode && ExtraCode[0]) {
2335 if (ExtraCode[1] != 0)
2338 switch (ExtraCode[0]) {
2352bool NVPTXAsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
2354 const char *ExtraCode,
2356 if (ExtraCode && ExtraCode[0])
2366void NVPTXAsmPrinter::printOperand(
const MachineInstr *
MI,
unsigned OpNum,
2368 const MachineOperand &MO =
MI->getOperand(OpNum);
2372 if (MO.
getReg() == NVPTX::VRDepot)
2373 getFunctionFrameSymbol()->print(O, MAI);
2377 O << getVirtualRegisterName(MO.
getReg());
2390 PrintSymbolOperand(MO, O);
2406void NVPTXAsmPrinter::printMemOperand(
const MachineInstr *
MI,
unsigned OpNum,
2407 raw_ostream &O,
const char *Modifier) {
2410 if (Modifier && strcmp(Modifier,
"add") == 0) {
2414 if (
MI->getOperand(OpNum + 1).isImm() &&
2415 MI->getOperand(OpNum + 1).getImm() == 0)
2426 return !Trimmed.
empty() &&
2427 (std::isalpha(
static_cast<unsigned char>(Trimmed[0])) ||
2434 if (!
MI || !
MI->getDebugLoc())
2436 const DISubprogram *SP =
MI->getMF()->getFunction().getSubprogram();
2440 if (!
DL->getFile() || !
DL->getLine() ||
DL->isImplicitCode())
2446struct InlineAsmInliningContext {
2448 unsigned FileIA = 0;
2449 unsigned LineIA = 0;
2452 bool hasInlinedAt()
const {
return FuncNameSym !=
nullptr; }
2458static InlineAsmInliningContext
2462 InlineAsmInliningContext Ctx;
2464 if (!InlinedAt || !InlinedAt->getFile() || !NVDD ||
2471 Ctx.FileIA =
Streamer.emitDwarfFileDirective(
2472 0, InlinedAt->getFile()->getDirectory(),
2473 InlinedAt->getFile()->getFilename(), std::nullopt, std::nullopt, CUID);
2474 Ctx.LineIA = InlinedAt->getLine();
2475 Ctx.ColIA = InlinedAt->getColumn();
2479void NVPTXAsmPrinter::emitInlineAsm(StringRef Str,
const MCSubtargetInfo &STI,
2480 const MCTargetOptions &MCOptions,
2481 const MDNode *LocMDNode,
2483 const MachineInstr *
MI) {
2484 assert(!Str.empty() &&
"Can't emit empty inline asm block");
2485 if (Str.back() == 0)
2486 Str = Str.substr(0, Str.size() - 1);
2488 auto emitAsmStr = [&](StringRef AsmStr) {
2489 emitInlineAsmStart();
2490 OutStreamer->emitRawText(AsmStr);
2491 emitInlineAsmEnd(STI,
nullptr,
MI);
2500 const DIFile *
File =
DL->getFile();
2501 unsigned Line =
DL->getLine();
2502 const unsigned Column =
DL->getColumn();
2503 const unsigned CUID = OutStreamer->getContext().getDwarfCompileUnitID();
2504 const unsigned FileNumber = OutStreamer->emitDwarfFileDirective(
2505 0,
File->getDirectory(),
File->getFilename(), std::nullopt, std::nullopt,
2508 auto *NVDD =
static_cast<NVPTXDwarfDebug *
>(getDwarfDebug());
2509 InlineAsmInliningContext InlineCtx =
2512 SmallVector<StringRef, 16>
Lines;
2513 Str.split(Lines,
'\n');
2514 emitInlineAsmStart();
2515 for (
const StringRef &L : Lines) {
2516 StringRef RTrimmed =
L.rtrim(
'\r');
2518 if (InlineCtx.hasInlinedAt()) {
2519 OutStreamer->emitDwarfLocDirectiveWithInlinedAt(
2520 FileNumber, Line, Column, InlineCtx.FileIA, InlineCtx.LineIA,
2522 File->getFilename());
2524 OutStreamer->emitDwarfLocDirective(FileNumber, Line, Column,
2526 File->getFilename());
2529 OutStreamer->emitRawText(RTrimmed);
2532 emitInlineAsmEnd(STI,
nullptr,
MI);
2535char NVPTXAsmPrinter::ID = 0;
2542LLVMInitializeNVPTXAsmPrinter() {
2563 Printer.runOnMachineFunction(MF);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
amdgpu next use AMDGPU Next Use Analysis Printer
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 ManagedStatic< DebugCounterOwner > Owner
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 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 bool canDemoteGlobalVar(const GlobalVariable *GV, Function const *&f)
static void printReturnValClause(const OwnerT *Owner, StringRef Name, const DataLayout &DL, raw_ostream &O)
static StringRef getPTXAddressSpaceName(unsigned AddressSpace)
The PTX state space directive for AddressSpace, or an empty string if it does not name one,...
static StringRef getPTXOpaqueTypeName(PTXOpaqueType OpaqueType)
The PTX opaque type directive for an image or sampler handle, or an empty string for PTXOpaqueType::N...
static bool useFuncSeen(const Constant *C, const SmallPtrSetImpl< const Function * > &SeenSet)
static NVPTX::VirtualRegisterKind getVirtualRegisterKind(const TargetRegisterClass *RC)
static void printParam(const OwnerT *Owner, Type *Ty, unsigned AttrIdx, bool IsByVal, bool IsKernel, StringRef Name, const DataLayout &DL, raw_ostream &O)
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.
ModuleAnalysisManager MAM
#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.
std::unique_ptr< MCStreamer > && Streamer
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
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.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
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...
bool isByValArgument(unsigned ArgNo) const
Determine whether this argument is passed by value.
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.
A parsed version of the target data layout string in and methods for querying it.
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
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...
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.
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.
StringRef getName() const
getName - Get the symbol name.
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 alignment of this function's frame.
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.
Function & getFunction()
Return the LLVM function that this machine code represents.
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
MCSymbol * getMCSymbol() const
@ MO_Immediate
Immediate operand.
@ MO_MCSymbol
MCSymbol reference (for debug/eh info)
@ 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.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
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(const MCSymbol *Symbol) const
Check whether Symbol's handle was replaced with an image reference.
void clearDebugRegisterMap() const
Register getFrameLocalRegister(const MachineFunction &MF) const
Register getFrameRegister(const MachineFunction &MF) const override
unsigned getMaxRequiredAlignment() const
StringRef getTargetName() const
bool hasMaskOperator() const
const NVPTXTargetLowering * getTargetLowering() const override
unsigned getPTXVersion() const
bool hasABIPreserve() const
const NVPTXRegisterInfo * getRegisterInfo() const override
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.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
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.
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
bool isFP128Ty() const
Return true if this is 'fp128'.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isAggregateType() const
Return true if the type is an aggregate type.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
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 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.
OuterAnalysisManagerProxy< ModuleAnalysisManager, MachineFunction > ModuleAnalysisManagerMachineFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
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 &)
unsigned promoteScalarKernelArgumentSize(unsigned Size)
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)
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
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)
SmallVector< unsigned, 3 > getMaxNTID(const Function &)
LLVM_ABI void setupModuleAsmPrinter(Module &M, ModuleAnalysisManager &MAM, AsmPrinter &AsmPrinter)
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...
unsigned promoteScalarArgumentSize(unsigned Size)
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.
LLVM_ABI void setupMachineFunctionAsmPrinter(MachineFunctionAnalysisManager &MFAM, MachineFunction &MF, AsmPrinter &AsmPrinter)
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 *)
@ End
Run the machine verifier once, at the end of the pipeline.
ABIPreserveInfo getABIPreserve(AttributeList Attrs)
On a function, the attributes are looked up on the function definition or declaration.
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.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Target & getTheNVPTXTarget32()
MCRegisterClass TargetRegisterClass
This struct is a compact representation of a valid (non-zero power of two) alignment.
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,...