xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/AMDGPU/AMDGPUHSAMetadataStreamer.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===--- AMDGPUHSAMetadataStreamer.cpp --------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// AMDGPU HSA Metadata Streamer.
110b57cec5SDimitry Andric ///
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "AMDGPUHSAMetadataStreamer.h"
160b57cec5SDimitry Andric #include "AMDGPU.h"
17e8d8bef9SDimitry Andric #include "GCNSubtarget.h"
180b57cec5SDimitry Andric #include "MCTargetDesc/AMDGPUTargetStreamer.h"
190b57cec5SDimitry Andric #include "SIMachineFunctionInfo.h"
200b57cec5SDimitry Andric #include "SIProgramInfo.h"
210b57cec5SDimitry Andric #include "llvm/IR/Module.h"
22*0fca6ea1SDimitry Andric #include "llvm/MC/MCContext.h"
23*0fca6ea1SDimitry Andric #include "llvm/MC/MCExpr.h"
24e8d8bef9SDimitry Andric using namespace llvm;
25e8d8bef9SDimitry Andric 
26e8d8bef9SDimitry Andric static std::pair<Type *, Align> getArgumentTypeAlign(const Argument &Arg,
27e8d8bef9SDimitry Andric                                                      const DataLayout &DL) {
28e8d8bef9SDimitry Andric   Type *Ty = Arg.getType();
29e8d8bef9SDimitry Andric   MaybeAlign ArgAlign;
30e8d8bef9SDimitry Andric   if (Arg.hasByRefAttr()) {
31e8d8bef9SDimitry Andric     Ty = Arg.getParamByRefType();
32e8d8bef9SDimitry Andric     ArgAlign = Arg.getParamAlign();
33e8d8bef9SDimitry Andric   }
34e8d8bef9SDimitry Andric 
35e8d8bef9SDimitry Andric   if (!ArgAlign)
36e8d8bef9SDimitry Andric     ArgAlign = DL.getABITypeAlign(Ty);
37e8d8bef9SDimitry Andric 
38bdd1243dSDimitry Andric   return std::pair(Ty, *ArgAlign);
39e8d8bef9SDimitry Andric }
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric namespace llvm {
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric static cl::opt<bool> DumpHSAMetadata(
440b57cec5SDimitry Andric     "amdgpu-dump-hsa-metadata",
450b57cec5SDimitry Andric     cl::desc("Dump AMDGPU HSA Metadata"));
460b57cec5SDimitry Andric static cl::opt<bool> VerifyHSAMetadata(
470b57cec5SDimitry Andric     "amdgpu-verify-hsa-metadata",
480b57cec5SDimitry Andric     cl::desc("Verify AMDGPU HSA Metadata"));
490b57cec5SDimitry Andric 
50*0fca6ea1SDimitry Andric namespace AMDGPU::HSAMD {
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
535f757f3fSDimitry Andric // HSAMetadataStreamerV4
540b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
555f757f3fSDimitry Andric 
565f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::dump(StringRef HSAMetadataString) const {
570b57cec5SDimitry Andric   errs() << "AMDGPU HSA Metadata:\n" << HSAMetadataString << '\n';
580b57cec5SDimitry Andric }
590b57cec5SDimitry Andric 
605f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::verify(StringRef HSAMetadataString) const {
610b57cec5SDimitry Andric   errs() << "AMDGPU HSA Metadata Parser Test: ";
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric   msgpack::Document FromHSAMetadataString;
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric   if (!FromHSAMetadataString.fromYAML(HSAMetadataString)) {
660b57cec5SDimitry Andric     errs() << "FAIL\n";
670b57cec5SDimitry Andric     return;
680b57cec5SDimitry Andric   }
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric   std::string ToHSAMetadataString;
710b57cec5SDimitry Andric   raw_string_ostream StrOS(ToHSAMetadataString);
720b57cec5SDimitry Andric   FromHSAMetadataString.toYAML(StrOS);
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric   errs() << (HSAMetadataString == StrOS.str() ? "PASS" : "FAIL") << '\n';
750b57cec5SDimitry Andric   if (HSAMetadataString != ToHSAMetadataString) {
760b57cec5SDimitry Andric     errs() << "Original input: " << HSAMetadataString << '\n'
770b57cec5SDimitry Andric            << "Produced output: " << StrOS.str() << '\n';
780b57cec5SDimitry Andric   }
790b57cec5SDimitry Andric }
800b57cec5SDimitry Andric 
81bdd1243dSDimitry Andric std::optional<StringRef>
825f757f3fSDimitry Andric MetadataStreamerMsgPackV4::getAccessQualifier(StringRef AccQual) const {
83bdd1243dSDimitry Andric   return StringSwitch<std::optional<StringRef>>(AccQual)
840b57cec5SDimitry Andric       .Case("read_only", StringRef("read_only"))
850b57cec5SDimitry Andric       .Case("write_only", StringRef("write_only"))
860b57cec5SDimitry Andric       .Case("read_write", StringRef("read_write"))
87bdd1243dSDimitry Andric       .Default(std::nullopt);
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric 
905f757f3fSDimitry Andric std::optional<StringRef> MetadataStreamerMsgPackV4::getAddressSpaceQualifier(
91bdd1243dSDimitry Andric     unsigned AddressSpace) const {
920b57cec5SDimitry Andric   switch (AddressSpace) {
930b57cec5SDimitry Andric   case AMDGPUAS::PRIVATE_ADDRESS:
940b57cec5SDimitry Andric     return StringRef("private");
950b57cec5SDimitry Andric   case AMDGPUAS::GLOBAL_ADDRESS:
960b57cec5SDimitry Andric     return StringRef("global");
970b57cec5SDimitry Andric   case AMDGPUAS::CONSTANT_ADDRESS:
980b57cec5SDimitry Andric     return StringRef("constant");
990b57cec5SDimitry Andric   case AMDGPUAS::LOCAL_ADDRESS:
1000b57cec5SDimitry Andric     return StringRef("local");
1010b57cec5SDimitry Andric   case AMDGPUAS::FLAT_ADDRESS:
1020b57cec5SDimitry Andric     return StringRef("generic");
1030b57cec5SDimitry Andric   case AMDGPUAS::REGION_ADDRESS:
1040b57cec5SDimitry Andric     return StringRef("region");
1050b57cec5SDimitry Andric   default:
106bdd1243dSDimitry Andric     return std::nullopt;
1070b57cec5SDimitry Andric   }
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric 
110bdd1243dSDimitry Andric StringRef
1115f757f3fSDimitry Andric MetadataStreamerMsgPackV4::getValueKind(Type *Ty, StringRef TypeQual,
1120b57cec5SDimitry Andric                                         StringRef BaseTypeName) const {
113349cc55cSDimitry Andric   if (TypeQual.contains("pipe"))
1140b57cec5SDimitry Andric     return "pipe";
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric   return StringSwitch<StringRef>(BaseTypeName)
1170b57cec5SDimitry Andric       .Case("image1d_t", "image")
1180b57cec5SDimitry Andric       .Case("image1d_array_t", "image")
1190b57cec5SDimitry Andric       .Case("image1d_buffer_t", "image")
1200b57cec5SDimitry Andric       .Case("image2d_t", "image")
1210b57cec5SDimitry Andric       .Case("image2d_array_t", "image")
1220b57cec5SDimitry Andric       .Case("image2d_array_depth_t", "image")
1230b57cec5SDimitry Andric       .Case("image2d_array_msaa_t", "image")
1240b57cec5SDimitry Andric       .Case("image2d_array_msaa_depth_t", "image")
1250b57cec5SDimitry Andric       .Case("image2d_depth_t", "image")
1260b57cec5SDimitry Andric       .Case("image2d_msaa_t", "image")
1270b57cec5SDimitry Andric       .Case("image2d_msaa_depth_t", "image")
1280b57cec5SDimitry Andric       .Case("image3d_t", "image")
1290b57cec5SDimitry Andric       .Case("sampler_t", "sampler")
1300b57cec5SDimitry Andric       .Case("queue_t", "queue")
1310b57cec5SDimitry Andric       .Default(isa<PointerType>(Ty)
1320b57cec5SDimitry Andric                    ? (Ty->getPointerAddressSpace() == AMDGPUAS::LOCAL_ADDRESS
1330b57cec5SDimitry Andric                           ? "dynamic_shared_pointer"
1340b57cec5SDimitry Andric                           : "global_buffer")
1350b57cec5SDimitry Andric                    : "by_value");
1360b57cec5SDimitry Andric }
1370b57cec5SDimitry Andric 
1385f757f3fSDimitry Andric std::string MetadataStreamerMsgPackV4::getTypeName(Type *Ty,
139bdd1243dSDimitry Andric                                                    bool Signed) const {
1400b57cec5SDimitry Andric   switch (Ty->getTypeID()) {
1410b57cec5SDimitry Andric   case Type::IntegerTyID: {
1420b57cec5SDimitry Andric     if (!Signed)
1430b57cec5SDimitry Andric       return (Twine('u') + getTypeName(Ty, true)).str();
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric     auto BitWidth = Ty->getIntegerBitWidth();
1460b57cec5SDimitry Andric     switch (BitWidth) {
1470b57cec5SDimitry Andric     case 8:
1480b57cec5SDimitry Andric       return "char";
1490b57cec5SDimitry Andric     case 16:
1500b57cec5SDimitry Andric       return "short";
1510b57cec5SDimitry Andric     case 32:
1520b57cec5SDimitry Andric       return "int";
1530b57cec5SDimitry Andric     case 64:
1540b57cec5SDimitry Andric       return "long";
1550b57cec5SDimitry Andric     default:
1560b57cec5SDimitry Andric       return (Twine('i') + Twine(BitWidth)).str();
1570b57cec5SDimitry Andric     }
1580b57cec5SDimitry Andric   }
1590b57cec5SDimitry Andric   case Type::HalfTyID:
1600b57cec5SDimitry Andric     return "half";
1610b57cec5SDimitry Andric   case Type::FloatTyID:
1620b57cec5SDimitry Andric     return "float";
1630b57cec5SDimitry Andric   case Type::DoubleTyID:
1640b57cec5SDimitry Andric     return "double";
1655ffd83dbSDimitry Andric   case Type::FixedVectorTyID: {
1665ffd83dbSDimitry Andric     auto VecTy = cast<FixedVectorType>(Ty);
1670b57cec5SDimitry Andric     auto ElTy = VecTy->getElementType();
1685ffd83dbSDimitry Andric     auto NumElements = VecTy->getNumElements();
1690b57cec5SDimitry Andric     return (Twine(getTypeName(ElTy, Signed)) + Twine(NumElements)).str();
1700b57cec5SDimitry Andric   }
1710b57cec5SDimitry Andric   default:
1720b57cec5SDimitry Andric     return "unknown";
1730b57cec5SDimitry Andric   }
1740b57cec5SDimitry Andric }
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric msgpack::ArrayDocNode
1775f757f3fSDimitry Andric MetadataStreamerMsgPackV4::getWorkGroupDimensions(MDNode *Node) const {
1780b57cec5SDimitry Andric   auto Dims = HSAMetadataDoc->getArrayNode();
1790b57cec5SDimitry Andric   if (Node->getNumOperands() != 3)
1800b57cec5SDimitry Andric     return Dims;
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric   for (auto &Op : Node->operands())
1830b57cec5SDimitry Andric     Dims.push_back(Dims.getDocument()->getNode(
1840b57cec5SDimitry Andric         uint64_t(mdconst::extract<ConstantInt>(Op)->getZExtValue())));
1850b57cec5SDimitry Andric   return Dims;
1860b57cec5SDimitry Andric }
1870b57cec5SDimitry Andric 
1885f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitVersion() {
1890b57cec5SDimitry Andric   auto Version = HSAMetadataDoc->getArrayNode();
1905f757f3fSDimitry Andric   Version.push_back(Version.getDocument()->getNode(VersionMajorV4));
1915f757f3fSDimitry Andric   Version.push_back(Version.getDocument()->getNode(VersionMinorV4));
1920b57cec5SDimitry Andric   getRootMetadata("amdhsa.version") = Version;
1930b57cec5SDimitry Andric }
1940b57cec5SDimitry Andric 
1955f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitTargetID(
1965f757f3fSDimitry Andric     const IsaInfo::AMDGPUTargetID &TargetID) {
1975f757f3fSDimitry Andric   getRootMetadata("amdhsa.target") =
1985f757f3fSDimitry Andric       HSAMetadataDoc->getNode(TargetID.toString(), /*Copy=*/true);
1995f757f3fSDimitry Andric }
2005f757f3fSDimitry Andric 
2015f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitPrintf(const Module &Mod) {
2020b57cec5SDimitry Andric   auto Node = Mod.getNamedMetadata("llvm.printf.fmts");
2030b57cec5SDimitry Andric   if (!Node)
2040b57cec5SDimitry Andric     return;
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric   auto Printf = HSAMetadataDoc->getArrayNode();
207bdd1243dSDimitry Andric   for (auto *Op : Node->operands())
2080b57cec5SDimitry Andric     if (Op->getNumOperands())
2090b57cec5SDimitry Andric       Printf.push_back(Printf.getDocument()->getNode(
2100b57cec5SDimitry Andric           cast<MDString>(Op->getOperand(0))->getString(), /*Copy=*/true));
2110b57cec5SDimitry Andric   getRootMetadata("amdhsa.printf") = Printf;
2120b57cec5SDimitry Andric }
2130b57cec5SDimitry Andric 
2145f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitKernelLanguage(const Function &Func,
2150b57cec5SDimitry Andric                                                    msgpack::MapDocNode Kern) {
2160b57cec5SDimitry Andric   // TODO: What about other languages?
2170b57cec5SDimitry Andric   auto Node = Func.getParent()->getNamedMetadata("opencl.ocl.version");
2180b57cec5SDimitry Andric   if (!Node || !Node->getNumOperands())
2190b57cec5SDimitry Andric     return;
2200b57cec5SDimitry Andric   auto Op0 = Node->getOperand(0);
2210b57cec5SDimitry Andric   if (Op0->getNumOperands() <= 1)
2220b57cec5SDimitry Andric     return;
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric   Kern[".language"] = Kern.getDocument()->getNode("OpenCL C");
2250b57cec5SDimitry Andric   auto LanguageVersion = Kern.getDocument()->getArrayNode();
2260b57cec5SDimitry Andric   LanguageVersion.push_back(Kern.getDocument()->getNode(
2270b57cec5SDimitry Andric       mdconst::extract<ConstantInt>(Op0->getOperand(0))->getZExtValue()));
2280b57cec5SDimitry Andric   LanguageVersion.push_back(Kern.getDocument()->getNode(
2290b57cec5SDimitry Andric       mdconst::extract<ConstantInt>(Op0->getOperand(1))->getZExtValue()));
2300b57cec5SDimitry Andric   Kern[".language_version"] = LanguageVersion;
2310b57cec5SDimitry Andric }
2320b57cec5SDimitry Andric 
2335f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitKernelAttrs(const Function &Func,
2340b57cec5SDimitry Andric                                                 msgpack::MapDocNode Kern) {
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric   if (auto Node = Func.getMetadata("reqd_work_group_size"))
2370b57cec5SDimitry Andric     Kern[".reqd_workgroup_size"] = getWorkGroupDimensions(Node);
2380b57cec5SDimitry Andric   if (auto Node = Func.getMetadata("work_group_size_hint"))
2390b57cec5SDimitry Andric     Kern[".workgroup_size_hint"] = getWorkGroupDimensions(Node);
2400b57cec5SDimitry Andric   if (auto Node = Func.getMetadata("vec_type_hint")) {
2410b57cec5SDimitry Andric     Kern[".vec_type_hint"] = Kern.getDocument()->getNode(
2420b57cec5SDimitry Andric         getTypeName(
2430b57cec5SDimitry Andric             cast<ValueAsMetadata>(Node->getOperand(0))->getType(),
2440b57cec5SDimitry Andric             mdconst::extract<ConstantInt>(Node->getOperand(1))->getZExtValue()),
2450b57cec5SDimitry Andric         /*Copy=*/true);
2460b57cec5SDimitry Andric   }
2470b57cec5SDimitry Andric   if (Func.hasFnAttribute("runtime-handle")) {
2480b57cec5SDimitry Andric     Kern[".device_enqueue_symbol"] = Kern.getDocument()->getNode(
2490b57cec5SDimitry Andric         Func.getFnAttribute("runtime-handle").getValueAsString().str(),
2500b57cec5SDimitry Andric         /*Copy=*/true);
2510b57cec5SDimitry Andric   }
252349cc55cSDimitry Andric   if (Func.hasFnAttribute("device-init"))
253349cc55cSDimitry Andric     Kern[".kind"] = Kern.getDocument()->getNode("init");
254349cc55cSDimitry Andric   else if (Func.hasFnAttribute("device-fini"))
255349cc55cSDimitry Andric     Kern[".kind"] = Kern.getDocument()->getNode("fini");
2560b57cec5SDimitry Andric }
2570b57cec5SDimitry Andric 
2585f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitKernelArgs(const MachineFunction &MF,
2590b57cec5SDimitry Andric                                                msgpack::MapDocNode Kern) {
2601fd87a68SDimitry Andric   auto &Func = MF.getFunction();
2610b57cec5SDimitry Andric   unsigned Offset = 0;
2620b57cec5SDimitry Andric   auto Args = HSAMetadataDoc->getArrayNode();
2630b57cec5SDimitry Andric   for (auto &Arg : Func.args())
2640b57cec5SDimitry Andric     emitKernelArg(Arg, Offset, Args);
2650b57cec5SDimitry Andric 
2661fd87a68SDimitry Andric   emitHiddenKernelArgs(MF, Offset, Args);
2670b57cec5SDimitry Andric 
2680b57cec5SDimitry Andric   Kern[".args"] = Args;
2690b57cec5SDimitry Andric }
2700b57cec5SDimitry Andric 
2715f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitKernelArg(const Argument &Arg,
272bdd1243dSDimitry Andric                                               unsigned &Offset,
2730b57cec5SDimitry Andric                                               msgpack::ArrayDocNode Args) {
2740b57cec5SDimitry Andric   auto Func = Arg.getParent();
2750b57cec5SDimitry Andric   auto ArgNo = Arg.getArgNo();
2760b57cec5SDimitry Andric   const MDNode *Node;
2770b57cec5SDimitry Andric 
2780b57cec5SDimitry Andric   StringRef Name;
2790b57cec5SDimitry Andric   Node = Func->getMetadata("kernel_arg_name");
2800b57cec5SDimitry Andric   if (Node && ArgNo < Node->getNumOperands())
2810b57cec5SDimitry Andric     Name = cast<MDString>(Node->getOperand(ArgNo))->getString();
2820b57cec5SDimitry Andric   else if (Arg.hasName())
2830b57cec5SDimitry Andric     Name = Arg.getName();
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric   StringRef TypeName;
2860b57cec5SDimitry Andric   Node = Func->getMetadata("kernel_arg_type");
2870b57cec5SDimitry Andric   if (Node && ArgNo < Node->getNumOperands())
2880b57cec5SDimitry Andric     TypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
2890b57cec5SDimitry Andric 
2900b57cec5SDimitry Andric   StringRef BaseTypeName;
2910b57cec5SDimitry Andric   Node = Func->getMetadata("kernel_arg_base_type");
2920b57cec5SDimitry Andric   if (Node && ArgNo < Node->getNumOperands())
2930b57cec5SDimitry Andric     BaseTypeName = cast<MDString>(Node->getOperand(ArgNo))->getString();
2940b57cec5SDimitry Andric 
2955f757f3fSDimitry Andric   StringRef ActAccQual;
2965f757f3fSDimitry Andric   // Do we really need NoAlias check here?
2975f757f3fSDimitry Andric   if (Arg.getType()->isPointerTy() && Arg.hasNoAliasAttr()) {
2985f757f3fSDimitry Andric     if (Arg.onlyReadsMemory())
2995f757f3fSDimitry Andric       ActAccQual = "read_only";
3005f757f3fSDimitry Andric     else if (Arg.hasAttribute(Attribute::WriteOnly))
3015f757f3fSDimitry Andric       ActAccQual = "write_only";
3025f757f3fSDimitry Andric   }
3035f757f3fSDimitry Andric 
3040b57cec5SDimitry Andric   StringRef AccQual;
3050b57cec5SDimitry Andric   Node = Func->getMetadata("kernel_arg_access_qual");
3060b57cec5SDimitry Andric   if (Node && ArgNo < Node->getNumOperands())
3070b57cec5SDimitry Andric     AccQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric   StringRef TypeQual;
3100b57cec5SDimitry Andric   Node = Func->getMetadata("kernel_arg_type_qual");
3110b57cec5SDimitry Andric   if (Node && ArgNo < Node->getNumOperands())
3120b57cec5SDimitry Andric     TypeQual = cast<MDString>(Node->getOperand(ArgNo))->getString();
3130b57cec5SDimitry Andric 
314*0fca6ea1SDimitry Andric   const DataLayout &DL = Func->getDataLayout();
3150b57cec5SDimitry Andric 
3165ffd83dbSDimitry Andric   MaybeAlign PointeeAlign;
317e8d8bef9SDimitry Andric   Type *Ty = Arg.hasByRefAttr() ? Arg.getParamByRefType() : Arg.getType();
318e8d8bef9SDimitry Andric 
319e8d8bef9SDimitry Andric   // FIXME: Need to distinguish in memory alignment from pointer alignment.
3200b57cec5SDimitry Andric   if (auto PtrTy = dyn_cast<PointerType>(Ty)) {
32104eeddc0SDimitry Andric     if (PtrTy->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS)
32204eeddc0SDimitry Andric       PointeeAlign = Arg.getParamAlign().valueOrOne();
3230b57cec5SDimitry Andric   }
3240b57cec5SDimitry Andric 
325e8d8bef9SDimitry Andric   // There's no distinction between byval aggregates and raw aggregates.
326e8d8bef9SDimitry Andric   Type *ArgTy;
327e8d8bef9SDimitry Andric   Align ArgAlign;
328e8d8bef9SDimitry Andric   std::tie(ArgTy, ArgAlign) = getArgumentTypeAlign(Arg, DL);
329e8d8bef9SDimitry Andric 
330e8d8bef9SDimitry Andric   emitKernelArg(DL, ArgTy, ArgAlign,
331e8d8bef9SDimitry Andric                 getValueKind(ArgTy, TypeQual, BaseTypeName), Offset, Args,
3325f757f3fSDimitry Andric                 PointeeAlign, Name, TypeName, BaseTypeName, ActAccQual,
3335f757f3fSDimitry Andric                 AccQual, TypeQual);
3340b57cec5SDimitry Andric }
3350b57cec5SDimitry Andric 
3365f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitKernelArg(
337e8d8bef9SDimitry Andric     const DataLayout &DL, Type *Ty, Align Alignment, StringRef ValueKind,
338e8d8bef9SDimitry Andric     unsigned &Offset, msgpack::ArrayDocNode Args, MaybeAlign PointeeAlign,
339e8d8bef9SDimitry Andric     StringRef Name, StringRef TypeName, StringRef BaseTypeName,
3405f757f3fSDimitry Andric     StringRef ActAccQual, StringRef AccQual, StringRef TypeQual) {
3410b57cec5SDimitry Andric   auto Arg = Args.getDocument()->getMapNode();
3420b57cec5SDimitry Andric 
3430b57cec5SDimitry Andric   if (!Name.empty())
3440b57cec5SDimitry Andric     Arg[".name"] = Arg.getDocument()->getNode(Name, /*Copy=*/true);
3450b57cec5SDimitry Andric   if (!TypeName.empty())
3460b57cec5SDimitry Andric     Arg[".type_name"] = Arg.getDocument()->getNode(TypeName, /*Copy=*/true);
3470b57cec5SDimitry Andric   auto Size = DL.getTypeAllocSize(Ty);
3480b57cec5SDimitry Andric   Arg[".size"] = Arg.getDocument()->getNode(Size);
3495ffd83dbSDimitry Andric   Offset = alignTo(Offset, Alignment);
3500b57cec5SDimitry Andric   Arg[".offset"] = Arg.getDocument()->getNode(Offset);
3510b57cec5SDimitry Andric   Offset += Size;
3520b57cec5SDimitry Andric   Arg[".value_kind"] = Arg.getDocument()->getNode(ValueKind, /*Copy=*/true);
3530b57cec5SDimitry Andric   if (PointeeAlign)
3545ffd83dbSDimitry Andric     Arg[".pointee_align"] = Arg.getDocument()->getNode(PointeeAlign->value());
3550b57cec5SDimitry Andric 
3560b57cec5SDimitry Andric   if (auto PtrTy = dyn_cast<PointerType>(Ty))
3570b57cec5SDimitry Andric     if (auto Qualifier = getAddressSpaceQualifier(PtrTy->getAddressSpace()))
358bdd1243dSDimitry Andric       // Limiting address space to emit only for a certain ValueKind.
359bdd1243dSDimitry Andric       if (ValueKind == "global_buffer" || ValueKind == "dynamic_shared_pointer")
360bdd1243dSDimitry Andric         Arg[".address_space"] = Arg.getDocument()->getNode(*Qualifier,
361bdd1243dSDimitry Andric                                                            /*Copy=*/true);
3620b57cec5SDimitry Andric 
3630b57cec5SDimitry Andric   if (auto AQ = getAccessQualifier(AccQual))
3640b57cec5SDimitry Andric     Arg[".access"] = Arg.getDocument()->getNode(*AQ, /*Copy=*/true);
3650b57cec5SDimitry Andric 
3665f757f3fSDimitry Andric   if (auto AAQ = getAccessQualifier(ActAccQual))
3675f757f3fSDimitry Andric     Arg[".actual_access"] = Arg.getDocument()->getNode(*AAQ, /*Copy=*/true);
3680b57cec5SDimitry Andric 
3690b57cec5SDimitry Andric   SmallVector<StringRef, 1> SplitTypeQuals;
3700b57cec5SDimitry Andric   TypeQual.split(SplitTypeQuals, " ", -1, false);
3710b57cec5SDimitry Andric   for (StringRef Key : SplitTypeQuals) {
3720b57cec5SDimitry Andric     if (Key == "const")
3730b57cec5SDimitry Andric       Arg[".is_const"] = Arg.getDocument()->getNode(true);
3740b57cec5SDimitry Andric     else if (Key == "restrict")
3750b57cec5SDimitry Andric       Arg[".is_restrict"] = Arg.getDocument()->getNode(true);
3760b57cec5SDimitry Andric     else if (Key == "volatile")
3770b57cec5SDimitry Andric       Arg[".is_volatile"] = Arg.getDocument()->getNode(true);
3780b57cec5SDimitry Andric     else if (Key == "pipe")
3790b57cec5SDimitry Andric       Arg[".is_pipe"] = Arg.getDocument()->getNode(true);
3800b57cec5SDimitry Andric   }
3810b57cec5SDimitry Andric 
3820b57cec5SDimitry Andric   Args.push_back(Arg);
3830b57cec5SDimitry Andric }
3840b57cec5SDimitry Andric 
3855f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitHiddenKernelArgs(
386bdd1243dSDimitry Andric     const MachineFunction &MF, unsigned &Offset, msgpack::ArrayDocNode Args) {
3871fd87a68SDimitry Andric   auto &Func = MF.getFunction();
3881fd87a68SDimitry Andric   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
3891fd87a68SDimitry Andric 
3900eae32dcSDimitry Andric   unsigned HiddenArgNumBytes = ST.getImplicitArgNumBytes(Func);
3910b57cec5SDimitry Andric   if (!HiddenArgNumBytes)
3920b57cec5SDimitry Andric     return;
3930b57cec5SDimitry Andric 
394349cc55cSDimitry Andric   const Module *M = Func.getParent();
395349cc55cSDimitry Andric   auto &DL = M->getDataLayout();
3960b57cec5SDimitry Andric   auto Int64Ty = Type::getInt64Ty(Func.getContext());
3970b57cec5SDimitry Andric 
39881ad6265SDimitry Andric   Offset = alignTo(Offset, ST.getAlignmentForImplicitArgPtr());
39981ad6265SDimitry Andric 
4000b57cec5SDimitry Andric   if (HiddenArgNumBytes >= 8)
401e8d8bef9SDimitry Andric     emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_x", Offset,
402e8d8bef9SDimitry Andric                   Args);
4030b57cec5SDimitry Andric   if (HiddenArgNumBytes >= 16)
404e8d8bef9SDimitry Andric     emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_y", Offset,
405e8d8bef9SDimitry Andric                   Args);
4060b57cec5SDimitry Andric   if (HiddenArgNumBytes >= 24)
407e8d8bef9SDimitry Andric     emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_z", Offset,
408e8d8bef9SDimitry Andric                   Args);
4090b57cec5SDimitry Andric 
4100b57cec5SDimitry Andric   auto Int8PtrTy =
4115f757f3fSDimitry Andric       PointerType::get(Func.getContext(), AMDGPUAS::GLOBAL_ADDRESS);
4120b57cec5SDimitry Andric 
4130b57cec5SDimitry Andric   if (HiddenArgNumBytes >= 32) {
41481ad6265SDimitry Andric     // We forbid the use of features requiring hostcall when compiling OpenCL
41581ad6265SDimitry Andric     // before code object V5, which makes the mutual exclusion between the
41681ad6265SDimitry Andric     // "printf buffer" and "hostcall buffer" here sound.
417349cc55cSDimitry Andric     if (M->getNamedMetadata("llvm.printf.fmts"))
418e8d8bef9SDimitry Andric       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_printf_buffer", Offset,
419e8d8bef9SDimitry Andric                     Args);
42081ad6265SDimitry Andric     else if (!Func.hasFnAttribute("amdgpu-no-hostcall-ptr"))
421e8d8bef9SDimitry Andric       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_hostcall_buffer", Offset,
422e8d8bef9SDimitry Andric                     Args);
42381ad6265SDimitry Andric     else
424e8d8bef9SDimitry Andric       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_none", Offset, Args);
4250b57cec5SDimitry Andric   }
4260b57cec5SDimitry Andric 
4270b57cec5SDimitry Andric   // Emit "default queue" and "completion action" arguments if enqueue kernel is
4280b57cec5SDimitry Andric   // used, otherwise emit dummy "none" arguments.
429bdd1243dSDimitry Andric   if (HiddenArgNumBytes >= 40) {
430bdd1243dSDimitry Andric     if (!Func.hasFnAttribute("amdgpu-no-default-queue")) {
431e8d8bef9SDimitry Andric       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_default_queue", Offset,
432e8d8bef9SDimitry Andric                     Args);
4330b57cec5SDimitry Andric     } else {
434e8d8bef9SDimitry Andric       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_none", Offset, Args);
435bdd1243dSDimitry Andric     }
436bdd1243dSDimitry Andric   }
437bdd1243dSDimitry Andric 
438bdd1243dSDimitry Andric   if (HiddenArgNumBytes >= 48) {
43906c3fb27SDimitry Andric     if (!Func.hasFnAttribute("amdgpu-no-completion-action")) {
440bdd1243dSDimitry Andric       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_completion_action", Offset,
441bdd1243dSDimitry Andric                     Args);
442bdd1243dSDimitry Andric     } else {
443e8d8bef9SDimitry Andric       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_none", Offset, Args);
4440b57cec5SDimitry Andric     }
4450b57cec5SDimitry Andric   }
4460b57cec5SDimitry Andric 
4470b57cec5SDimitry Andric   // Emit the pointer argument for multi-grid object.
44881ad6265SDimitry Andric   if (HiddenArgNumBytes >= 56) {
44981ad6265SDimitry Andric     if (!Func.hasFnAttribute("amdgpu-no-multigrid-sync-arg")) {
450e8d8bef9SDimitry Andric       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_multigrid_sync_arg", Offset,
451e8d8bef9SDimitry Andric                     Args);
45281ad6265SDimitry Andric     } else {
45381ad6265SDimitry Andric       emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_none", Offset, Args);
45481ad6265SDimitry Andric     }
45581ad6265SDimitry Andric   }
4560b57cec5SDimitry Andric }
4570b57cec5SDimitry Andric 
4585f757f3fSDimitry Andric msgpack::MapDocNode
4595f757f3fSDimitry Andric MetadataStreamerMsgPackV4::getHSAKernelProps(const MachineFunction &MF,
4605f757f3fSDimitry Andric                                              const SIProgramInfo &ProgramInfo,
46106c3fb27SDimitry Andric                                              unsigned CodeObjectVersion) const {
4620b57cec5SDimitry Andric   const GCNSubtarget &STM = MF.getSubtarget<GCNSubtarget>();
4630b57cec5SDimitry Andric   const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>();
4640b57cec5SDimitry Andric   const Function &F = MF.getFunction();
4650b57cec5SDimitry Andric 
4660b57cec5SDimitry Andric   auto Kern = HSAMetadataDoc->getMapNode();
4670b57cec5SDimitry Andric 
4688bcb0991SDimitry Andric   Align MaxKernArgAlign;
4690b57cec5SDimitry Andric   Kern[".kernarg_segment_size"] = Kern.getDocument()->getNode(
4700b57cec5SDimitry Andric       STM.getKernArgSegmentSize(F, MaxKernArgAlign));
4710b57cec5SDimitry Andric   Kern[".group_segment_fixed_size"] =
4720b57cec5SDimitry Andric       Kern.getDocument()->getNode(ProgramInfo.LDSSize);
473*0fca6ea1SDimitry Andric   DelayedExprs->assignDocNode(Kern[".private_segment_fixed_size"],
474*0fca6ea1SDimitry Andric                               msgpack::Type::UInt, ProgramInfo.ScratchSize);
475*0fca6ea1SDimitry Andric   if (CodeObjectVersion >= AMDGPU::AMDHSA_COV5) {
476*0fca6ea1SDimitry Andric     DelayedExprs->assignDocNode(Kern[".uses_dynamic_stack"],
477*0fca6ea1SDimitry Andric                                 msgpack::Type::Boolean,
478*0fca6ea1SDimitry Andric                                 ProgramInfo.DynamicCallStack);
479*0fca6ea1SDimitry Andric   }
48006c3fb27SDimitry Andric 
48106c3fb27SDimitry Andric   if (CodeObjectVersion >= AMDGPU::AMDHSA_COV5 && STM.supportsWGP())
482bdd1243dSDimitry Andric     Kern[".workgroup_processor_mode"] =
483bdd1243dSDimitry Andric         Kern.getDocument()->getNode(ProgramInfo.WgpMode);
484349cc55cSDimitry Andric 
485349cc55cSDimitry Andric   // FIXME: The metadata treats the minimum as 16?
4860b57cec5SDimitry Andric   Kern[".kernarg_segment_align"] =
4878bcb0991SDimitry Andric       Kern.getDocument()->getNode(std::max(Align(4), MaxKernArgAlign).value());
4880b57cec5SDimitry Andric   Kern[".wavefront_size"] =
4890b57cec5SDimitry Andric       Kern.getDocument()->getNode(STM.getWavefrontSize());
490*0fca6ea1SDimitry Andric   DelayedExprs->assignDocNode(Kern[".sgpr_count"], msgpack::Type::UInt,
491*0fca6ea1SDimitry Andric                               ProgramInfo.NumSGPR);
492*0fca6ea1SDimitry Andric   DelayedExprs->assignDocNode(Kern[".vgpr_count"], msgpack::Type::UInt,
493*0fca6ea1SDimitry Andric                               ProgramInfo.NumVGPR);
49481ad6265SDimitry Andric 
49581ad6265SDimitry Andric   // Only add AGPR count to metadata for supported devices
49681ad6265SDimitry Andric   if (STM.hasMAIInsts()) {
497*0fca6ea1SDimitry Andric     DelayedExprs->assignDocNode(Kern[".agpr_count"], msgpack::Type::UInt,
498*0fca6ea1SDimitry Andric                                 ProgramInfo.NumAccVGPR);
49981ad6265SDimitry Andric   }
50081ad6265SDimitry Andric 
5010b57cec5SDimitry Andric   Kern[".max_flat_workgroup_size"] =
5020b57cec5SDimitry Andric       Kern.getDocument()->getNode(MFI.getMaxFlatWorkGroupSize());
503*0fca6ea1SDimitry Andric   unsigned NumWGX = MFI.getMaxNumWorkGroupsX();
504*0fca6ea1SDimitry Andric   unsigned NumWGY = MFI.getMaxNumWorkGroupsY();
505*0fca6ea1SDimitry Andric   unsigned NumWGZ = MFI.getMaxNumWorkGroupsZ();
506*0fca6ea1SDimitry Andric   if (NumWGX != 0 && NumWGY != 0 && NumWGZ != 0) {
507*0fca6ea1SDimitry Andric     Kern[".max_num_workgroups_x"] = Kern.getDocument()->getNode(NumWGX);
508*0fca6ea1SDimitry Andric     Kern[".max_num_workgroups_y"] = Kern.getDocument()->getNode(NumWGY);
509*0fca6ea1SDimitry Andric     Kern[".max_num_workgroups_z"] = Kern.getDocument()->getNode(NumWGZ);
510*0fca6ea1SDimitry Andric   }
5110b57cec5SDimitry Andric   Kern[".sgpr_spill_count"] =
5120b57cec5SDimitry Andric       Kern.getDocument()->getNode(MFI.getNumSpilledSGPRs());
5130b57cec5SDimitry Andric   Kern[".vgpr_spill_count"] =
5140b57cec5SDimitry Andric       Kern.getDocument()->getNode(MFI.getNumSpilledVGPRs());
5150b57cec5SDimitry Andric 
5160b57cec5SDimitry Andric   return Kern;
5170b57cec5SDimitry Andric }
5180b57cec5SDimitry Andric 
5195f757f3fSDimitry Andric bool MetadataStreamerMsgPackV4::emitTo(AMDGPUTargetStreamer &TargetStreamer) {
520*0fca6ea1SDimitry Andric   DelayedExprs->resolveDelayedExpressions();
5210b57cec5SDimitry Andric   return TargetStreamer.EmitHSAMetadata(*HSAMetadataDoc, true);
5220b57cec5SDimitry Andric }
5230b57cec5SDimitry Andric 
5245f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::begin(const Module &Mod,
525fe6060f1SDimitry Andric                                       const IsaInfo::AMDGPUTargetID &TargetID) {
5260b57cec5SDimitry Andric   emitVersion();
5275f757f3fSDimitry Andric   emitTargetID(TargetID);
5280b57cec5SDimitry Andric   emitPrintf(Mod);
5290b57cec5SDimitry Andric   getRootMetadata("amdhsa.kernels") = HSAMetadataDoc->getArrayNode();
530*0fca6ea1SDimitry Andric   DelayedExprs->clear();
5310b57cec5SDimitry Andric }
5320b57cec5SDimitry Andric 
5335f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::end() {
534*0fca6ea1SDimitry Andric   DelayedExprs->resolveDelayedExpressions();
5350b57cec5SDimitry Andric   std::string HSAMetadataString;
5360b57cec5SDimitry Andric   raw_string_ostream StrOS(HSAMetadataString);
5370b57cec5SDimitry Andric   HSAMetadataDoc->toYAML(StrOS);
5380b57cec5SDimitry Andric 
5390b57cec5SDimitry Andric   if (DumpHSAMetadata)
5400b57cec5SDimitry Andric     dump(StrOS.str());
5410b57cec5SDimitry Andric   if (VerifyHSAMetadata)
5420b57cec5SDimitry Andric     verify(StrOS.str());
5430b57cec5SDimitry Andric }
5440b57cec5SDimitry Andric 
5455f757f3fSDimitry Andric void MetadataStreamerMsgPackV4::emitKernel(const MachineFunction &MF,
5460b57cec5SDimitry Andric                                            const SIProgramInfo &ProgramInfo) {
5470b57cec5SDimitry Andric   auto &Func = MF.getFunction();
54806c3fb27SDimitry Andric   if (Func.getCallingConv() != CallingConv::AMDGPU_KERNEL &&
54906c3fb27SDimitry Andric       Func.getCallingConv() != CallingConv::SPIR_KERNEL)
55006c3fb27SDimitry Andric     return;
5510b57cec5SDimitry Andric 
5527a6dacacSDimitry Andric   auto CodeObjectVersion =
5537a6dacacSDimitry Andric       AMDGPU::getAMDHSACodeObjectVersion(*Func.getParent());
55406c3fb27SDimitry Andric   auto Kern = getHSAKernelProps(MF, ProgramInfo, CodeObjectVersion);
5550b57cec5SDimitry Andric 
5560b57cec5SDimitry Andric   auto Kernels =
5570b57cec5SDimitry Andric       getRootMetadata("amdhsa.kernels").getArray(/*Convert=*/true);
5580b57cec5SDimitry Andric 
5590b57cec5SDimitry Andric   {
5600b57cec5SDimitry Andric     Kern[".name"] = Kern.getDocument()->getNode(Func.getName());
5610b57cec5SDimitry Andric     Kern[".symbol"] = Kern.getDocument()->getNode(
5620b57cec5SDimitry Andric         (Twine(Func.getName()) + Twine(".kd")).str(), /*Copy=*/true);
5630b57cec5SDimitry Andric     emitKernelLanguage(Func, Kern);
5640b57cec5SDimitry Andric     emitKernelAttrs(Func, Kern);
5651fd87a68SDimitry Andric     emitKernelArgs(MF, Kern);
5660b57cec5SDimitry Andric   }
5670b57cec5SDimitry Andric 
5680b57cec5SDimitry Andric   Kernels.push_back(Kern);
5690b57cec5SDimitry Andric }
5700b57cec5SDimitry Andric 
571fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
5721fd87a68SDimitry Andric // HSAMetadataStreamerV5
5731fd87a68SDimitry Andric //===----------------------------------------------------------------------===//
5741fd87a68SDimitry Andric 
575bdd1243dSDimitry Andric void MetadataStreamerMsgPackV5::emitVersion() {
5761fd87a68SDimitry Andric   auto Version = HSAMetadataDoc->getArrayNode();
5771fd87a68SDimitry Andric   Version.push_back(Version.getDocument()->getNode(VersionMajorV5));
5781fd87a68SDimitry Andric   Version.push_back(Version.getDocument()->getNode(VersionMinorV5));
5791fd87a68SDimitry Andric   getRootMetadata("amdhsa.version") = Version;
5801fd87a68SDimitry Andric }
5811fd87a68SDimitry Andric 
582bdd1243dSDimitry Andric void MetadataStreamerMsgPackV5::emitHiddenKernelArgs(
583bdd1243dSDimitry Andric     const MachineFunction &MF, unsigned &Offset, msgpack::ArrayDocNode Args) {
5841fd87a68SDimitry Andric   auto &Func = MF.getFunction();
5851fd87a68SDimitry Andric   const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
58681ad6265SDimitry Andric 
58781ad6265SDimitry Andric   // No implicit kernel argument is used.
58881ad6265SDimitry Andric   if (ST.getImplicitArgNumBytes(Func) == 0)
58981ad6265SDimitry Andric     return;
59081ad6265SDimitry Andric 
5911fd87a68SDimitry Andric   const Module *M = Func.getParent();
5921fd87a68SDimitry Andric   auto &DL = M->getDataLayout();
59381ad6265SDimitry Andric   const SIMachineFunctionInfo &MFI = *MF.getInfo<SIMachineFunctionInfo>();
5941fd87a68SDimitry Andric 
5951fd87a68SDimitry Andric   auto Int64Ty = Type::getInt64Ty(Func.getContext());
5961fd87a68SDimitry Andric   auto Int32Ty = Type::getInt32Ty(Func.getContext());
5971fd87a68SDimitry Andric   auto Int16Ty = Type::getInt16Ty(Func.getContext());
5981fd87a68SDimitry Andric 
59981ad6265SDimitry Andric   Offset = alignTo(Offset, ST.getAlignmentForImplicitArgPtr());
6001fd87a68SDimitry Andric   emitKernelArg(DL, Int32Ty, Align(4), "hidden_block_count_x", Offset, Args);
6011fd87a68SDimitry Andric   emitKernelArg(DL, Int32Ty, Align(4), "hidden_block_count_y", Offset, Args);
6021fd87a68SDimitry Andric   emitKernelArg(DL, Int32Ty, Align(4), "hidden_block_count_z", Offset, Args);
6031fd87a68SDimitry Andric 
6041fd87a68SDimitry Andric   emitKernelArg(DL, Int16Ty, Align(2), "hidden_group_size_x", Offset, Args);
6051fd87a68SDimitry Andric   emitKernelArg(DL, Int16Ty, Align(2), "hidden_group_size_y", Offset, Args);
6061fd87a68SDimitry Andric   emitKernelArg(DL, Int16Ty, Align(2), "hidden_group_size_z", Offset, Args);
6071fd87a68SDimitry Andric 
6081fd87a68SDimitry Andric   emitKernelArg(DL, Int16Ty, Align(2), "hidden_remainder_x", Offset, Args);
6091fd87a68SDimitry Andric   emitKernelArg(DL, Int16Ty, Align(2), "hidden_remainder_y", Offset, Args);
6101fd87a68SDimitry Andric   emitKernelArg(DL, Int16Ty, Align(2), "hidden_remainder_z", Offset, Args);
6111fd87a68SDimitry Andric 
6121fd87a68SDimitry Andric   // Reserved for hidden_tool_correlation_id.
6131fd87a68SDimitry Andric   Offset += 8;
6141fd87a68SDimitry Andric 
6151fd87a68SDimitry Andric   Offset += 8; // Reserved.
6161fd87a68SDimitry Andric 
6171fd87a68SDimitry Andric   emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_x", Offset, Args);
6181fd87a68SDimitry Andric   emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_y", Offset, Args);
6191fd87a68SDimitry Andric   emitKernelArg(DL, Int64Ty, Align(8), "hidden_global_offset_z", Offset, Args);
6201fd87a68SDimitry Andric 
6211fd87a68SDimitry Andric   emitKernelArg(DL, Int16Ty, Align(2), "hidden_grid_dims", Offset, Args);
6221fd87a68SDimitry Andric 
6231fd87a68SDimitry Andric   Offset += 6; // Reserved.
6241fd87a68SDimitry Andric   auto Int8PtrTy =
6255f757f3fSDimitry Andric       PointerType::get(Func.getContext(), AMDGPUAS::GLOBAL_ADDRESS);
6261fd87a68SDimitry Andric 
6271fd87a68SDimitry Andric   if (M->getNamedMetadata("llvm.printf.fmts")) {
6281fd87a68SDimitry Andric     emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_printf_buffer", Offset,
6291fd87a68SDimitry Andric                   Args);
63081ad6265SDimitry Andric   } else {
6311fd87a68SDimitry Andric     Offset += 8; // Skipped.
63281ad6265SDimitry Andric   }
6331fd87a68SDimitry Andric 
63481ad6265SDimitry Andric   if (!Func.hasFnAttribute("amdgpu-no-hostcall-ptr")) {
6351fd87a68SDimitry Andric     emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_hostcall_buffer", Offset,
6361fd87a68SDimitry Andric                   Args);
63781ad6265SDimitry Andric   } else {
6381fd87a68SDimitry Andric     Offset += 8; // Skipped.
63981ad6265SDimitry Andric   }
6401fd87a68SDimitry Andric 
64181ad6265SDimitry Andric   if (!Func.hasFnAttribute("amdgpu-no-multigrid-sync-arg")) {
6421fd87a68SDimitry Andric     emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_multigrid_sync_arg", Offset,
6431fd87a68SDimitry Andric                 Args);
64481ad6265SDimitry Andric   } else {
64581ad6265SDimitry Andric     Offset += 8; // Skipped.
64681ad6265SDimitry Andric   }
6471fd87a68SDimitry Andric 
64881ad6265SDimitry Andric   if (!Func.hasFnAttribute("amdgpu-no-heap-ptr"))
64981ad6265SDimitry Andric     emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_heap_v1", Offset, Args);
65081ad6265SDimitry Andric   else
65181ad6265SDimitry Andric     Offset += 8; // Skipped.
6521fd87a68SDimitry Andric 
653bdd1243dSDimitry Andric   if (!Func.hasFnAttribute("amdgpu-no-default-queue")) {
6541fd87a68SDimitry Andric     emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_default_queue", Offset,
6551fd87a68SDimitry Andric                   Args);
656bdd1243dSDimitry Andric   } else {
657bdd1243dSDimitry Andric     Offset += 8; // Skipped.
658bdd1243dSDimitry Andric   }
659bdd1243dSDimitry Andric 
66006c3fb27SDimitry Andric   if (!Func.hasFnAttribute("amdgpu-no-completion-action")) {
6611fd87a68SDimitry Andric     emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_completion_action", Offset,
6621fd87a68SDimitry Andric                   Args);
66381ad6265SDimitry Andric   } else {
664bdd1243dSDimitry Andric     Offset += 8; // Skipped.
66581ad6265SDimitry Andric   }
6661fd87a68SDimitry Andric 
6671db9f3b2SDimitry Andric   // Emit argument for hidden dynamic lds size
6681db9f3b2SDimitry Andric   if (MFI.isDynamicLDSUsed()) {
6691db9f3b2SDimitry Andric     emitKernelArg(DL, Int32Ty, Align(4), "hidden_dynamic_lds_size", Offset,
6701db9f3b2SDimitry Andric                   Args);
6711db9f3b2SDimitry Andric   } else {
6721db9f3b2SDimitry Andric     Offset += 4; // skipped
6731db9f3b2SDimitry Andric   }
6741db9f3b2SDimitry Andric 
6751db9f3b2SDimitry Andric   Offset += 68; // Reserved.
6761fd87a68SDimitry Andric 
67781ad6265SDimitry Andric   // hidden_private_base and hidden_shared_base are only when the subtarget has
67881ad6265SDimitry Andric   // ApertureRegs.
67981ad6265SDimitry Andric   if (!ST.hasApertureRegs()) {
6801fd87a68SDimitry Andric     emitKernelArg(DL, Int32Ty, Align(4), "hidden_private_base", Offset, Args);
6811fd87a68SDimitry Andric     emitKernelArg(DL, Int32Ty, Align(4), "hidden_shared_base", Offset, Args);
68281ad6265SDimitry Andric   } else {
6831fd87a68SDimitry Andric     Offset += 8; // Skipped.
68481ad6265SDimitry Andric   }
6851fd87a68SDimitry Andric 
6865f757f3fSDimitry Andric   if (MFI.getUserSGPRInfo().hasQueuePtr())
6871fd87a68SDimitry Andric     emitKernelArg(DL, Int8PtrTy, Align(8), "hidden_queue_ptr", Offset, Args);
6881fd87a68SDimitry Andric }
6891fd87a68SDimitry Andric 
690bdd1243dSDimitry Andric void MetadataStreamerMsgPackV5::emitKernelAttrs(const Function &Func,
691bdd1243dSDimitry Andric                                                 msgpack::MapDocNode Kern) {
6925f757f3fSDimitry Andric   MetadataStreamerMsgPackV4::emitKernelAttrs(Func, Kern);
693bdd1243dSDimitry Andric 
694bdd1243dSDimitry Andric   if (Func.getFnAttribute("uniform-work-group-size").getValueAsBool())
695bdd1243dSDimitry Andric     Kern[".uniform_work_group_size"] = Kern.getDocument()->getNode(1);
696bdd1243dSDimitry Andric }
697bdd1243dSDimitry Andric 
698*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
699*0fca6ea1SDimitry Andric // HSAMetadataStreamerV6
700*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
701bdd1243dSDimitry Andric 
702*0fca6ea1SDimitry Andric void MetadataStreamerMsgPackV6::emitVersion() {
703*0fca6ea1SDimitry Andric   auto Version = HSAMetadataDoc->getArrayNode();
704*0fca6ea1SDimitry Andric   Version.push_back(Version.getDocument()->getNode(VersionMajorV6));
705*0fca6ea1SDimitry Andric   Version.push_back(Version.getDocument()->getNode(VersionMinorV6));
706*0fca6ea1SDimitry Andric   getRootMetadata("amdhsa.version") = Version;
707*0fca6ea1SDimitry Andric }
708*0fca6ea1SDimitry Andric 
709*0fca6ea1SDimitry Andric } // end namespace AMDGPU::HSAMD
7100b57cec5SDimitry Andric } // end namespace llvm
711